diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..ca9f3a2 Binary files /dev/null and b/.DS_Store differ diff --git a/PediatricPancreas/.DS_Store b/PediatricPancreas/.DS_Store index 3e79a77..5cbbadf 100644 Binary files a/PediatricPancreas/.DS_Store and b/PediatricPancreas/.DS_Store differ diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.pbxproj b/PediatricPancreas/PediatricPancreas.xcodeproj/project.pbxproj index 49d91c0..d6cdaa7 100644 --- a/PediatricPancreas/PediatricPancreas.xcodeproj/project.pbxproj +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/project.pbxproj @@ -3,14 +3,18 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ + 0C42BA55AA9C30B4EBAF4D10 /* Pods_PediatricPancreas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9EC5829C1A7FDF4B6B4BCCDA /* Pods_PediatricPancreas.framework */; }; + 5DDB49170E9C584BBB8ADDDC /* Pods_PediatricPancreas_PediatricPancreasUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 627838B2FEF3755DEC94D46E /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */; }; + 641CFA7B835315AE0F95162D /* Pods_PediatricPancreasTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1A354E72CFCC8271F32B8A6 /* Pods_PediatricPancreasTests.framework */; }; 758D7F5223F4CDD7006B6A9C /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 758D7F4F23F4CDB1006B6A9C /* ResearchKit.framework */; }; 758D7F5323F4CDD7006B6A9C /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 758D7F4F23F4CDB1006B6A9C /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 758D7F6B23F4CECE006B6A9C /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 758D7F6823F4CEC5006B6A9C /* CareKit.framework */; }; 758D7F6C23F4CECE006B6A9C /* CareKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 758D7F6823F4CEC5006B6A9C /* CareKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7B4CD9C123FAC3E00053736E /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B4CD9BB23FAC3E00053736E /* GoogleService-Info.plist */; }; AB9EF51D23F4C26700BC0139 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB9EF51C23F4C26700BC0139 /* AppDelegate.swift */; }; AB9EF51F23F4C26700BC0139 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB9EF51E23F4C26700BC0139 /* SceneDelegate.swift */; }; AB9EF52123F4C26700BC0139 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB9EF52023F4C26700BC0139 /* ContentView.swift */; }; @@ -82,9 +86,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0AB61D4F269E2A6399C88007 /* Pods-PediatricPancreas.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas.release.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.release.xcconfig"; sourceTree = ""; }; + 19685DC0E64DA8567F238DFB /* Pods-PediatricPancreasTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreasTests.release.xcconfig"; path = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.release.xcconfig"; sourceTree = ""; }; + 627838B2FEF3755DEC94D46E /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PediatricPancreas_PediatricPancreasUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 758D7F4823F4CDB1006B6A9C /* ResearchKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ResearchKit.xcodeproj; path = "ResearchKit-master/ResearchKit.xcodeproj"; sourceTree = ""; }; 758D7F6023F4CEC5006B6A9C /* CareKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CareKit.xcodeproj; path = "CareKit-master/CareKit/CareKit.xcodeproj"; sourceTree = ""; }; 758D7F6D23F4CFC9006B6A9C /* PediatricPancreas.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PediatricPancreas.entitlements; sourceTree = ""; }; + 75E45119AEB839753A050A94 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig"; sourceTree = ""; }; + 78E4CD127DB76208AD274D1E /* Pods-PediatricPancreas.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas.debug.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.debug.xcconfig"; sourceTree = ""; }; + 7B4CD9BB23FAC3E00053736E /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 805C3B4517638F7F05D1F6F5 /* Pods-PediatricPancreasTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreasTests.debug.xcconfig"; path = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.debug.xcconfig"; sourceTree = ""; }; + 9EC5829C1A7FDF4B6B4BCCDA /* Pods_PediatricPancreas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PediatricPancreas.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AB38888A23F4C6C400AB9EE4 /* CareKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; AB9EF51923F4C26700BC0139 /* PediatricPancreas.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PediatricPancreas.app; sourceTree = BUILT_PRODUCTS_DIR; }; AB9EF51C23F4C26700BC0139 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -100,6 +112,8 @@ AB9EF53A23F4C26E00BC0139 /* PediatricPancreasUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PediatricPancreasUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; AB9EF53E23F4C26E00BC0139 /* PediatricPancreasUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PediatricPancreasUITests.swift; sourceTree = ""; }; AB9EF54023F4C26E00BC0139 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E1A354E72CFCC8271F32B8A6 /* Pods_PediatricPancreasTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PediatricPancreasTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + EC5C95A95239257E7BC6DECC /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -109,6 +123,7 @@ files = ( 758D7F6B23F4CECE006B6A9C /* CareKit.framework in Frameworks */, 758D7F5223F4CDD7006B6A9C /* ResearchKit.framework in Frameworks */, + 0C42BA55AA9C30B4EBAF4D10 /* Pods_PediatricPancreas.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -116,6 +131,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 641CFA7B835315AE0F95162D /* Pods_PediatricPancreasTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -123,6 +139,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5DDB49170E9C584BBB8ADDDC /* Pods_PediatricPancreas_PediatricPancreasUITests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -151,6 +168,9 @@ isa = PBXGroup; children = ( AB38888A23F4C6C400AB9EE4 /* CareKitUI.framework */, + 9EC5829C1A7FDF4B6B4BCCDA /* Pods_PediatricPancreas.framework */, + 627838B2FEF3755DEC94D46E /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */, + E1A354E72CFCC8271F32B8A6 /* Pods_PediatricPancreasTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -165,6 +185,7 @@ AB9EF53D23F4C26E00BC0139 /* PediatricPancreasUITests */, AB9EF51A23F4C26700BC0139 /* Products */, AB38887023F4C49000AB9EE4 /* Frameworks */, + F19EF0294D25002281777085 /* Pods */, ); sourceTree = ""; }; @@ -187,6 +208,7 @@ AB9EF52023F4C26700BC0139 /* ContentView.swift */, AB9EF52223F4C26E00BC0139 /* Assets.xcassets */, AB9EF52723F4C26E00BC0139 /* LaunchScreen.storyboard */, + 7B4CD9BB23FAC3E00053736E /* GoogleService-Info.plist */, AB9EF52A23F4C26E00BC0139 /* Info.plist */, AB9EF52423F4C26E00BC0139 /* Preview Content */, ); @@ -219,6 +241,19 @@ path = PediatricPancreasUITests; sourceTree = ""; }; + F19EF0294D25002281777085 /* Pods */ = { + isa = PBXGroup; + children = ( + 78E4CD127DB76208AD274D1E /* Pods-PediatricPancreas.debug.xcconfig */, + 0AB61D4F269E2A6399C88007 /* Pods-PediatricPancreas.release.xcconfig */, + EC5C95A95239257E7BC6DECC /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */, + 75E45119AEB839753A050A94 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */, + 805C3B4517638F7F05D1F6F5 /* Pods-PediatricPancreasTests.debug.xcconfig */, + 19685DC0E64DA8567F238DFB /* Pods-PediatricPancreasTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -226,10 +261,12 @@ isa = PBXNativeTarget; buildConfigurationList = AB9EF54323F4C26E00BC0139 /* Build configuration list for PBXNativeTarget "PediatricPancreas" */; buildPhases = ( + CCED2A12F92AF276D70D7CBC /* [CP] Check Pods Manifest.lock */, AB9EF51523F4C26700BC0139 /* Sources */, AB9EF51623F4C26700BC0139 /* Frameworks */, AB9EF51723F4C26700BC0139 /* Resources */, 758D7F5423F4CDD7006B6A9C /* Embed Frameworks */, + C694CA1150C8F4D1C097DE0B /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -244,6 +281,7 @@ isa = PBXNativeTarget; buildConfigurationList = AB9EF54623F4C26E00BC0139 /* Build configuration list for PBXNativeTarget "PediatricPancreasTests" */; buildPhases = ( + 2B2201B2662031AB5C98A5CA /* [CP] Check Pods Manifest.lock */, AB9EF52B23F4C26E00BC0139 /* Sources */, AB9EF52C23F4C26E00BC0139 /* Frameworks */, AB9EF52D23F4C26E00BC0139 /* Resources */, @@ -262,9 +300,11 @@ isa = PBXNativeTarget; buildConfigurationList = AB9EF54923F4C26E00BC0139 /* Build configuration list for PBXNativeTarget "PediatricPancreasUITests" */; buildPhases = ( + A28244F246DDBC82DFC948CB /* [CP] Check Pods Manifest.lock */, AB9EF53623F4C26E00BC0139 /* Sources */, AB9EF53723F4C26E00BC0139 /* Frameworks */, AB9EF53823F4C26E00BC0139 /* Resources */, + C60A7D783E29F9CC8446050E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -366,6 +406,7 @@ buildActionMask = 2147483647; files = ( AB9EF52923F4C26E00BC0139 /* LaunchScreen.storyboard in Resources */, + 7B4CD9C123FAC3E00053736E /* GoogleService-Info.plist in Resources */, AB9EF52623F4C26E00BC0139 /* Preview Assets.xcassets in Resources */, AB9EF52323F4C26E00BC0139 /* Assets.xcassets in Resources */, ); @@ -387,6 +428,109 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 2B2201B2662031AB5C98A5CA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PediatricPancreasTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + A28244F246DDBC82DFC948CB /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PediatricPancreas-PediatricPancreasUITests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + C60A7D783E29F9CC8446050E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C694CA1150C8F4D1C097DE0B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + CCED2A12F92AF276D70D7CBC /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PediatricPancreas-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ AB9EF51523F4C26700BC0139 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -557,6 +701,7 @@ }; AB9EF54423F4C26E00BC0139 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 78E4CD127DB76208AD274D1E /* Pods-PediatricPancreas.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = PediatricPancreas/PediatricPancreas.entitlements; @@ -578,6 +723,7 @@ }; AB9EF54523F4C26E00BC0139 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0AB61D4F269E2A6399C88007 /* Pods-PediatricPancreas.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = PediatricPancreas/PediatricPancreas.entitlements; @@ -599,6 +745,7 @@ }; AB9EF54723F4C26E00BC0139 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 805C3B4517638F7F05D1F6F5 /* Pods-PediatricPancreasTests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -621,6 +768,7 @@ }; AB9EF54823F4C26E00BC0139 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 19685DC0E64DA8567F238DFB /* Pods-PediatricPancreasTests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -643,6 +791,7 @@ }; AB9EF54A23F4C26E00BC0139 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = EC5C95A95239257E7BC6DECC /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; @@ -663,6 +812,7 @@ }; AB9EF54B23F4C26E00BC0139 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 75E45119AEB839753A050A94 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..acad545 Binary files /dev/null and b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate index 13e22f3..8da084f 100644 Binary files a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate and b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/WorkspaceSettings.xcsettings b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..dd7403b --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,16 @@ + + + + + BuildLocationStyle + UseAppPreferences + CustomBuildLocationType + RelativeToDerivedData + DerivedDataLocationStyle + Default + IssueFilterStyle + ShowActiveSchemeOnly + LiveSourceIssuesEnabled + + + diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate index 3fe8f16..d244bd1 100644 Binary files a/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate and b/PediatricPancreas/PediatricPancreas.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..19effd5 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas.xcscheme_^#shared#^_ + + orderHint + 8 + + + + diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist index 19effd5..b4b9750 100644 --- a/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ PediatricPancreas.xcscheme_^#shared#^_ orderHint - 8 + 27 diff --git a/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..19effd5 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas.xcscheme_^#shared#^_ + + orderHint + 8 + + + + diff --git a/PediatricPancreas/PediatricPancreas.xcworkspace/contents.xcworkspacedata b/PediatricPancreas/PediatricPancreas.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..7d86955 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/PediatricPancreas/PediatricPancreas.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas/PediatricPancreas.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..29de728 Binary files /dev/null and b/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..82a8906 Binary files /dev/null and b/PediatricPancreas/PediatricPancreas.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas/PediatricPancreas/AppDelegate.swift b/PediatricPancreas/PediatricPancreas/AppDelegate.swift index 49abf95..e84e7c7 100644 --- a/PediatricPancreas/PediatricPancreas/AppDelegate.swift +++ b/PediatricPancreas/PediatricPancreas/AppDelegate.swift @@ -11,7 +11,7 @@ import ResearchKit import CareKitUI import CareKitStore import CareKit - +import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -20,6 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + FirebaseApp.configure() return true } diff --git a/PediatricPancreas/PediatricPancreas/GoogleService-Info.plist b/PediatricPancreas/PediatricPancreas/GoogleService-Info.plist new file mode 100644 index 0000000..1057921 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 158315296857-lanl3u0vm7vk5p1ljl3iijl485eg9k9n.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.158315296857-lanl3u0vm7vk5p1ljl3iijl485eg9k9n + API_KEY + AIzaSyCOuyD66ZZFJa3SMGCKJNzF1v5g-5t0Q4E + GCM_SENDER_ID + 158315296857 + PLIST_VERSION + 1 + BUNDLE_ID + iHackHealth.PediatricPancreas + PROJECT_ID + pediatric-pancreatitis + STORAGE_BUCKET + pediatric-pancreatitis.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:158315296857:ios:d1ced85fab3a995eb5d948 + DATABASE_URL + https://pediatric-pancreatitis.firebaseio.com + + \ No newline at end of file diff --git a/PediatricPancreas/PediatricPancreas/Resource.swift b/PediatricPancreas/PediatricPancreas/Resource.swift new file mode 100644 index 0000000..62b1030 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas/Resource.swift @@ -0,0 +1,20 @@ +// +// Resource.swift +// resources +// +// Created by Taewon Kim on 2/23/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import Foundation + +class Resource { + + var labelName: String +// var pointsTo: Resource + + init(labelName: String) { + self.labelName = labelName +// self.pointsTo = pointsTo + } +} diff --git a/PediatricPancreas/PediatricPancreas/ResourceCell.swift b/PediatricPancreas/PediatricPancreas/ResourceCell.swift new file mode 100644 index 0000000..8dbc78c --- /dev/null +++ b/PediatricPancreas/PediatricPancreas/ResourceCell.swift @@ -0,0 +1,19 @@ +// +// ResourceCell.swift +// resources +// +// Created by Taewon Kim on 2/23/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import UIKit + +class ResourceCell: UITableViewCell { + + @IBOutlet weak var resourceName: UILabel! + + func setResource(resource: Resource) { + resourceName.text = resource.labelName + } + +} diff --git a/PediatricPancreas/PediatricPancreas/ResourceListScreen.swift b/PediatricPancreas/PediatricPancreas/ResourceListScreen.swift new file mode 100644 index 0000000..713c915 --- /dev/null +++ b/PediatricPancreas/PediatricPancreas/ResourceListScreen.swift @@ -0,0 +1,51 @@ +// +// ResourceListScreen.swift +// resources +// +// Created by Taewon Kim on 2/23/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import UIKit + +class ResourceListScreen: UIViewController { + + + @IBOutlet weak var tableView: UITableView! + + var resources: [Resource] = [] + + override func viewDidLoad() { + super.viewDidLoad() + resources = createArray() + + } + + func createArray() -> [Resource] { + + var tempResources: [Resource] = [] + + let resource1 = Resource(labelName: "Acute Pancreatitis") + let resource2 = Resource(labelName: "Chronic Pancreatitis") + + tempResources.append(resource1) + tempResources.append(resource2) + + return tempResources + } +} + +extension ResourceListScreen: UITableViewDataSource, UITableViewDelegate { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return resources.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let resource = resources[indexPath.row] + let cell = tableView.dequeueReusableCell(withIdentifier: "ResourceCell") as! ResourceCell + + cell.setResource(resource: resource) + + return cell + } +} diff --git a/PediatricPancreas/Podfile b/PediatricPancreas/Podfile new file mode 100644 index 0000000..8812b78 --- /dev/null +++ b/PediatricPancreas/Podfile @@ -0,0 +1,24 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'PediatricPancreas' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for PediatricPancreas + + pod 'Firebase/Core' + pod 'Firebase/Database' + + target 'PediatricPancreasTests' do + inherit! :search_paths + # Pods for testing + end + + target 'PediatricPancreasUITests' do + # Pods for testing + + + end + +end diff --git a/PediatricPancreas/Podfile.lock b/PediatricPancreas/Podfile.lock new file mode 100644 index 0000000..6858f88 --- /dev/null +++ b/PediatricPancreas/Podfile.lock @@ -0,0 +1,124 @@ +PODS: + - Firebase/Core (6.17.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.2.2) + - Firebase/CoreOnly (6.17.0): + - FirebaseCore (= 6.6.2) + - Firebase/Database (6.17.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.1.4) + - FirebaseAnalytics (6.2.2): + - FirebaseCore (~> 6.6) + - FirebaseInstanceID (~> 4.3) + - GoogleAppMeasurement (= 6.2.2) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAuthInterop (1.0.0) + - FirebaseCore (6.6.2): + - FirebaseCoreDiagnostics (~> 1.2) + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.2.0): + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleDataTransportCCTSupport (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.2.0) + - FirebaseDatabase (6.1.4): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.1.0): + - FirebaseCore (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.5) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.3.1): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - GoogleAppMeasurement (6.2.2): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (4.0.0) + - GoogleDataTransportCCTSupport (1.4.0): + - GoogleDataTransport (~> 4.0) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.5.1) + - GoogleUtilities/Logger (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.5.1): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.5.1)" + - GoogleUtilities/Reachability (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.5.1): + - GoogleUtilities/Logger + - leveldb-library (1.22) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - PromisesObjC (1.2.8) + +DEPENDENCIES: + - Firebase/Core + - Firebase/Database + +SPEC REPOS: + trunk: + - Firebase + - FirebaseAnalytics + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop + - FirebaseDatabase + - FirebaseInstallations + - FirebaseInstanceID + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + Firebase: 2672e5636b42f977177716317e68346ae5e9de25 + FirebaseAnalytics: cf95d3aab897612783020fbd98401d5366f135ee + FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc + FirebaseCore: a1dd9dd6355a8356dd30a8f076839e242285a81c + FirebaseCoreDiagnostics: 5e78803ab276bc5b50340e3c539c06c3de35c649 + FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 + FirebaseDatabase: 0144e0706a4761f1b0e8679572eba8095ddb59be + FirebaseInstallations: 575cd32f2aec0feeb0e44f5d0110a09e5e60b47b + FirebaseInstanceID: 031d7d0c8e7b5c030bbeb4d2a690550375e83fec + GoogleAppMeasurement: d0560d915abf15e692e8538ba1d58442217b6aff + GoogleDataTransport: 47fe3b8e1673e5187dfd615656a3c5034f150d69 + GoogleDataTransportCCTSupport: 36f69887fd212db6d7ef4dd45ba44523717a434e + GoogleUtilities: 06eb53bb579efe7099152735900dd04bf09e7275 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 + +PODFILE CHECKSUM: c4ea62e4deb9d9bae7aab1df7399af99eb57d649 + +COCOAPODS: 1.9.0 diff --git a/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/Firebase.h b/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/Firebase.h new file mode 100755 index 0000000..e5049ca --- /dev/null +++ b/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/Firebase.h @@ -0,0 +1,172 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#if !defined(__has_include) + #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \ + import the headers individually." +#else + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Dynamic Links works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase In App Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif +#endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Performance works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Remote Config works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + +#endif // defined(__has_include) diff --git a/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/module.modulemap b/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/module.modulemap new file mode 100755 index 0000000..3685b54 --- /dev/null +++ b/PediatricPancreas/Pods/Firebase/CoreOnly/Sources/module.modulemap @@ -0,0 +1,4 @@ +module Firebase { + export * + header "Firebase.h" +} \ No newline at end of file diff --git a/PediatricPancreas/Pods/Firebase/LICENSE b/PediatricPancreas/Pods/Firebase/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/Firebase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/Firebase/README.md b/PediatricPancreas/Pods/Firebase/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas/Pods/Firebase/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector new file mode 100755 index 0000000..1a7eaec Binary files /dev/null and b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap new file mode 100755 index 0000000..99a4b1d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module FIRAnalyticsConnector { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics new file mode 100755 index 0000000..fa7ceb9 Binary files /dev/null and b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h new file mode 100755 index 0000000..d499af6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h @@ -0,0 +1,62 @@ +#import + +#import "FIRAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides App Delegate handlers to be used in your App Delegate. + * + * To save time integrating Firebase Analytics in an application, Firebase Analytics does not + * require delegation implementation from the AppDelegate. Instead this is automatically done by + * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App + * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting + * it to NO, and adding the methods in this category to corresponding delegation handlers. + * + * To handle Universal Links, you must return YES in + * [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. + */ +@interface FIRAnalytics (AppDelegate) + +/** + * Handles events related to a URL session that are waiting to be processed. + * + * For optimal use of Firebase Analytics, call this method from the + * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler] + * method of the app delegate in your app. + * + * @param identifier The identifier of the URL session requiring attention. + * @param completionHandler The completion handler to call when you finish processing the events. + * Calling this completion handler lets the system know that your app's user interface is + * updated and a new snapshot can be taken. + */ ++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(nullable void (^)(void))completionHandler; + +/** + * Handles the event when the app is launched by a URL. + * + * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and + * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on + * iOS 8.x and below) in your app. + * + * @param url The URL resource to open. This resource can be a network resource or a file. + */ ++ (void)handleOpenURL:(NSURL *)url; + +/** + * Handles the event when the app receives data associated with user activity that includes a + * Universal Link (on iOS 9.0 and above). + * + * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app + * delegate (on iOS 9.0 and above). + * + * @param userActivity The activity object containing the data associated with the task the user + * was performing. + */ ++ (void)handleUserActivity:(id)userActivity; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h new file mode 100755 index 0000000..be0b1fa --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -0,0 +1,136 @@ +#import + +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" + +NS_ASSUME_NONNULL_BEGIN + +/// The top level Firebase Analytics singleton that provides methods for logging events and setting +/// user properties. See the developer guides for general +/// information on using Firebase Analytics in your apps. +/// +/// @note The Analytics SDK uses SQLite to persist events and other app-specific data. Calling +/// certain thread-unsafe global SQLite methods like `sqlite3_shutdown()` can result in +/// unexpected crashes at runtime. +NS_SWIFT_NAME(Analytics) +@interface FIRAnalytics : NSObject + +/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have +/// the same parameters. Up to 500 event names are supported. Using predefined events and/or +/// parameters is recommended for optimal reporting. +/// +/// The following event names are reserved and cannot be used: +///
    +///
  • ad_activeview
  • +///
  • ad_click
  • +///
  • ad_exposure
  • +///
  • ad_impression
  • +///
  • ad_query
  • +///
  • adunit_exposure
  • +///
  • app_clear_data
  • +///
  • app_remove
  • +///
  • app_update
  • +///
  • error
  • +///
  • first_open
  • +///
  • in_app_purchase
  • +///
  • notification_dismiss
  • +///
  • notification_foreground
  • +///
  • notification_open
  • +///
  • notification_receive
  • +///
  • os_update
  • +///
  • screen_view
  • +///
  • session_start
  • +///
  • user_engagement
  • +///
+/// +/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or +/// underscores. The name must start with an alphabetic character. Some event names are +/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are +/// case-sensitive and that logging two events whose names differ only in case will result in +/// two distinct events. +/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has +/// no parameters. Parameter names can be up to 40 characters long and must start with an +/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString +/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are +/// supported. NSString parameter values can be up to 100 characters long. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names. ++ (void)logEventWithName:(NSString *)name + parameters:(nullable NSDictionary *)parameters + NS_SWIFT_NAME(logEvent(_:parameters:)); + +/// Sets a user property to a given value. Up to 25 user property names are supported. Once set, +/// user property values persist throughout the app lifecycle and across sessions. +/// +/// The following user property names are reserved and cannot be used: +///
    +///
  • first_open_time
  • +///
  • last_deep_link_referrer
  • +///
  • user_id
  • +///
+/// +/// @param value The value of the user property. Values can be up to 36 characters long. Setting the +/// value to nil removes the user property. +/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters +/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and +/// "ga_" prefixes are reserved and should not be used for user property names. ++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name + NS_SWIFT_NAME(setUserProperty(_:forName:)); + +/// Sets the user ID property. This feature must be used in accordance with +/// Google's Privacy Policy +/// +/// @param userID The user ID to ascribe to the user of this app on this device, which must be +/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID. ++ (void)setUserID:(nullable NSString *)userID; + +/// Sets the current screen name, which specifies the current visual context in your app. This helps +/// identify the areas in your app where users spend their time and how they interact with your app. +/// Must be called on the main thread. +/// +/// Note that screen reporting is enabled automatically and records the class name of the current +/// UIViewController for you without requiring you to call this method. If you implement +/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class +/// will not be automatically tracked. The class name can optionally be overridden by calling this +/// method in the viewDidAppear callback of your UIViewController and specifying the +/// screenClassOverride parameter. setScreenName:screenClass: must be called after +/// [super viewDidAppear:]. +/// +/// If your app does not use a distinct UIViewController for each screen, you should call this +/// method and specify a distinct screenName each time a new screen is presented to the user. +/// +/// The screen name and screen class remain in effect until the current UIViewController changes or +/// a new call to setScreenName:screenClass: is made. +/// +/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil +/// to clear the current screen name. +/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By +/// default this is the class name of the current UIViewController. Set to nil to revert to the +/// default class name. ++ (void)setScreenName:(nullable NSString *)screenName + screenClass:(nullable NSString *)screenClassOverride; + +/// Sets whether analytics collection is enabled for this app on this device. This setting is +/// persisted across app sessions. By default it is enabled. +/// +/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection. ++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets the interval of inactivity in seconds that terminates the current session. The default +/// value is 1800 seconds (30 minutes). +/// +/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current +/// session terminates. ++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval; + +/// The unique ID for this instance of the application. ++ (NSString *)appInstanceID; + +/// Clears all analytics data for this instance from the device and resets the app instance ID. +/// FIRAnalyticsConfiguration values will be reset to the default values. ++ (void)resetAnalyticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h new file mode 100755 index 0000000..c70c53e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -0,0 +1,407 @@ +/// @file FIREventNames.h +/// +/// Predefined event names. +/// +/// An Event is an important occurrence in your app that you want to measure. You can report up to +/// 500 different types of Events per app and you can associate up to 25 unique parameters with each +/// Event type. Some common events are suggested below, but you may also choose to specify custom +/// Event types that are associated with your specific app. Each event type is identified by a +/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. + +#import + +/// Add Payment Info event. This event signifies that a user has submitted their payment information +/// to your app. +static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) = + @"add_payment_info"; + +/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for +/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness +/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart"; + +/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. +/// Use this event to identify popular gift items in your app. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) = + @"add_to_wishlist"; + +/// App Open event. By logging this event when an App becomes active, developers can understand how +/// often users leave and return during the course of a Session. Although Sessions are automatically +/// reported, this event can provide further clarification around the continuous engagement of +/// app-users. +static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open"; + +/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of +/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the +/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue +/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue +/// metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) = + @"begin_checkout"; + +/// Campaign Detail event. Log this event to supply the referral details of a re-engagement +/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource, +/// kFIRParameterMedium or kFIRParameterCampaign. Params: +/// +///
    +///
  • @c kFIRParameterSource (NSString)
  • +///
  • @c kFIRParameterMedium (NSString)
  • +///
  • @c kFIRParameterCampaign (NSString)
  • +///
  • @c kFIRParameterTerm (NSString) (optional)
  • +///
  • @c kFIRParameterContent (NSString) (optional)
  • +///
  • @c kFIRParameterAdNetworkClickID (NSString) (optional)
  • +///
  • @c kFIRParameterCP1 (NSString) (optional)
  • +///
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) = + @"campaign_details"; + +/// Checkout progress. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString) (optional)
  • +///
+static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) = + @"checkout_progress"; + +/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log +/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy. +/// Params: +/// +///
    +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventEarnVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency"; + +/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterLocation (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) = + @"ecommerce_purchase"; + +/// Generate Lead event. Log this event when a lead has been generated in the app to understand the +/// efficacy of your install and re-engagement campaigns. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) = + @"generate_lead"; + +/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use +/// this event to analyze how popular certain groups or social features are in your app. Params: +/// +///
    +///
  • @c kFIRParameterGroupID (NSString)
  • +///
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group"; + +/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can +/// help you gauge the level distribution of your userbase and help you identify certain levels that +/// are difficult to pass. Params: +/// +///
    +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up"; + +/// Login event. Apps with a login feature can report this event to signify that a user has logged +/// in. +static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login"; + +/// Post Score event. Log this event when the user posts a score in your gaming app. This event can +/// help you understand how users are actually performing in your game and it can help you correlate +/// high scores with certain audiences or behaviors. Params: +/// +///
    +///
  • @c kFIRParameterScore (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score"; + +/// Present Offer event. This event signifies that the app has presented a purchase offer to a user. +/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge +/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) = + @"present_offer"; + +/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
+static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) = + @"purchase_refund"; + +/// Remove from cart event. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) = + @"remove_from_cart"; + +/// Search event. Apps that support search features can use this event to contextualize search +/// operations by supplying the appropriate, corresponding parameters. This event can help you +/// identify the most popular content in your app. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search"; + +/// Select Content event. This general purpose event signifies that a user has selected some content +/// of a certain type in an app. The content can be any object in your app. This event can help you +/// identify popular content and categories of content in your app. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) = + @"select_content"; + +/// Set checkout option. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString)
  • +///
+static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) = + @"set_checkout_option"; + +/// Share event. Apps with social features can log the Share event to identify the most viral +/// content. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share"; + +/// Sign Up event. This event indicates that a user has signed up for an account in your app. The +/// parameter signifies the method by which the user signed up. Use this event to understand the +/// different behaviors between logged in and logged out users. Params: +/// +///
    +///
  • @c kFIRParameterSignUpMethod (NSString)
  • +///
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up"; + +/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can +/// help you identify which virtual goods are the most popular objects of purchase. Params: +/// +///
    +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventSpendVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency"; + +/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use +/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this +/// process and move on to the full app experience. +static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) = + @"tutorial_begin"; + +/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding +/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your +/// on-boarding process. +static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) = + @"tutorial_complete"; + +/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your +/// game. Since achievements generally represent the breadth of a gaming experience, this event can +/// help you understand how many users are experiencing all that your game has to offer. Params: +/// +///
    +///
  • @c kFIRParameterAchievementID (NSString)
  • +///
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) = + @"unlock_achievement"; + +/// View Item event. This event signifies that some content was shown to the user. This content may +/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to +/// contextualize the event. Use this event to discover the most popular items viewed in your app. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterFlightNumber (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterSearchTerm (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item"; + +/// View Item List event. Log this event when the user has been presented with a list of items of a +/// certain category. Params: +/// +///
    +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) = + @"view_item_list"; + +/// View Search Results event. Log this event when the user has been presented with the results of a +/// search. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = + @"view_search_results"; + +/// Level Start event. Log this event when the user starts a new level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = + @"level_start"; + +/// Level End event. Log this event when the user finishes a level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
  • @c kFIRParameterSuccess (NSString)
  • +///
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end"; diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h new file mode 100755 index 0000000..ad9fff7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h @@ -0,0 +1,532 @@ +/// @file FIRParameterNames.h +/// +/// Predefined event parameter names. +/// +/// Params supply information that contextualize Events. You can associate up to 25 unique Params +/// with each Event type. Some Params are suggested below for certain common Events, but you are +/// not limited to these. You may supply extra Params for suggested Events or custom Params for +/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. Param values can +/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and +/// should not be used. + +#import + +/// Game achievement ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) = + @"achievement_id"; + +/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format. +///
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAdNetworkClickID + NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid"; + +/// The store or affiliation from which this transaction occurred (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) = + @"affiliation"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Character used in game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) = + @"character"; + +/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) = + @"checkout_step"; + +/// Some option on a step in an ecommerce flow (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutOption + NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option"; + +/// Campaign content (NSString). +static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content"; + +/// Type of content selected (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) = + @"content_type"; + +/// Coupon code for a purchasable item (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"zz123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon"; + +/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign. +/// Use varies by network. +///
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1"; + +/// The name of a creative used in a promotional spot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) = + @"creative_name"; + +/// The name of a creative slot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) = + @"creative_slot"; + +/// Purchase currency in 3-letter +/// ISO_4217 format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) = + @"currency"; + +/// Flight or Travel destination (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) = + @"destination"; + +/// The arrival date, check-out date or rental end date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date"; + +/// Flight number for travel events (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) = + @"flight_number"; + +/// Group/clan/guild ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id"; + +/// Index of an item in a list (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index"; + +/// Item brand (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) = + @"item_brand"; + +/// Item category (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"t-shirts",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) = + @"item_category"; + +/// Item ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"p7654",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id"; + +/// The Google Place ID (NSString) that +/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemLocationID + NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id"; + +/// Item name (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"abc",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) = + @"item_name"; + +/// The list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) = + @"item_list"; + +/// Item variant (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Red",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) = + @"item_variant"; + +/// Level in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level"; + +/// Location (NSString). The Google Place ID +/// that corresponds to the associated event. Alternatively, you can supply your own custom +/// Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) = + @"location"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// Number of nights staying at hotel (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfNights + NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights"; + +/// Number of passengers traveling (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfPassengers + NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers"; + +/// Number of rooms for travel events (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) = + @"number_of_rooms"; + +/// Flight or Travel origin (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin"; + +/// Purchase price (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price"; + +/// Purchase quantity (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) = + @"quantity"; + +/// Score in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score"; + +/// The search string/keywords used (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) = + @"search_term"; + +/// Shipping cost (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(9.50),
+///       kFIRParameterCurrency : @"USD",  // e.g. $9.50 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) = + @"shipping"; + +/// Sign up method (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// 
+/// +/// This constant has been deprecated. Use Method constant instead. +static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) = + @"sign_up_method"; + +/// A particular approach used in an operation; for example, "facebook" or "email" in the context +/// of a sign_up or login event. (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method"; + +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The departure date, check-in date or rental start date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) = + @"start_date"; + +/// Tax amount (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax"; + +/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term"; + +/// A single ID for a ecommerce group transaction (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"ab7236dd9823",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) = + @"transaction_id"; + +/// Travel class (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) = + @"travel_class"; + +/// A context-specific numeric value which is accumulated automatically for each event type. This is +/// a general purpose parameter that is useful for accumulating a key metric that pertains to an +/// event. Examples include revenue, distance, time and points. Value should be specified as signed +/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events +/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be +/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is +/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the +/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid +/// currency code for conversion events will cause that +/// conversion to be omitted from reporting. +///
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value"; + +/// Name of virtual currency type (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterVirtualCurrencyName + NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name"; + +/// The name of a level in a game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) = + @"level_name"; + +/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned +/// integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success"; + +/// Indicates that the associated event should either extend the current session +/// or start a new session if no session was active when the event was logged. +/// Specify YES to extend the current session or to start a new session; any +/// other value will not extend or start a session. +///
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) = + @"extend_session"; diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h new file mode 100755 index 0000000..132aef7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h @@ -0,0 +1,29 @@ +/// @file FIRUserPropertyNames.h +/// +/// Predefined user property names. +/// +/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can +/// later analyze different behaviors of various segments of your userbase. You may supply up to 25 +/// unique UserProperties per app, and you can use the name and value of your choosing for each one. +/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and +/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to +/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not +/// be used. + +#import + +/// The method used to sign in. For example, "google", "facebook" or "twitter". +static NSString *const kFIRUserPropertySignUpMethod + NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method"; + +/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user. +/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the +/// documentation for +/// more details and information about related settings. +/// +///
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// 
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals + NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads"; diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h new file mode 100755 index 0000000..ed7588a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h @@ -0,0 +1,5 @@ +#import "FIRAnalytics+AppDelegate.h" +#import "FIRAnalytics.h" +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" diff --git a/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap new file mode 100755 index 0000000..d7c5905 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module FirebaseAnalytics { + umbrella header "FirebaseAnalytics.h" + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h b/PediatricPancreas/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h new file mode 100644 index 0000000..5c365a3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h @@ -0,0 +1,42 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRAuthInterop_h +#define FIRAuthInterop_h + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRTokenCallback + @brief The type of block which gets called when a token is ready. + */ +typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(TokenCallback); + +/// Common methods for Auth interoperability. +NS_SWIFT_NAME(AuthInterop) +@protocol FIRAuthInterop + +/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired. +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback; + +/// Get the current Auth user's UID. Returns nil if there is no user signed in. +- (nullable NSString *)getUserID; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRAuthInterop_h */ diff --git a/PediatricPancreas/Pods/FirebaseAuthInterop/LICENSE b/PediatricPancreas/Pods/FirebaseAuthInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAuthInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseAuthInterop/README.md b/PediatricPancreas/Pods/FirebaseAuthInterop/README.md new file mode 100644 index 0000000..4414b3e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseAuthInterop/README.md @@ -0,0 +1,179 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +An experimental Carthage distribution is now available. See +[Carthage](Carthage.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[AuthSamples/README.md](AuthSamples/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +FirebaseAuth, FirebaseCore, FirebaseDatabase and FirebaseStorage now compile, run unit tests, and +work on macOS and tvOS, thanks to contributions from the community. There are a few tweaks needed, +like ensuring iOS-only, macOS-only, or tvOS-only code is correctly guarded with checks for +`TARGET_OS_IOS`, `TARGET_OS_OSX` and `TARGET_OS_TV`. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +For installation instructions, see [above](README.md#accessing-firebase-source-snapshots). + +Note that the Firebase pod is not available for macOS and tvOS. Install a selection of the +`FirebaseAuth`, `FirebaseCore`, `FirebaseDatabase` and `FirebaseStorage` CocoaPods. + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m new file mode 100644 index 0000000..3a7d6de --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m @@ -0,0 +1,62 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +@implementation FIRAnalyticsConfiguration +#pragma clang diagnostic pop + ++ (FIRAnalyticsConfiguration *)sharedInstance { + static FIRAnalyticsConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRAnalyticsConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (void)postNotificationName:(NSString *)name value:(id)value { + if (!name.length || !value) { + return; + } + [[NSNotificationCenter defaultCenter] postNotificationName:name + object:self + userInfo:@{name : value}]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled { + [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist { + // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO. + FIRAnalyticsEnabledState analyticsEnabledState = + analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo; + if (shouldPersist) { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:@(analyticsEnabledState) + forKey:kFIRAPersistedConfigMeasurementEnabledStateKey]; + [userDefaults synchronize]; + } + + [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification + value:@(analyticsCollectionEnabled)]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m new file mode 100644 index 0000000..02f3ac3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m @@ -0,0 +1,912 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#if __has_include() +#import +#endif + +#if __has_include() +#import +#endif + +#import + +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" +#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +#import + +#import + +// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics +// pod to a Core dependency. These symbols are not used and should be deleted after the transition. +NSString *const kFIRServiceAdMob; +NSString *const kFIRServiceAuth; +NSString *const kFIRServiceAuthUI; +NSString *const kFIRServiceCrash; +NSString *const kFIRServiceDatabase; +NSString *const kFIRServiceDynamicLinks; +NSString *const kFIRServiceFirestore; +NSString *const kFIRServiceFunctions; +NSString *const kFIRServiceInstanceID; +NSString *const kFIRServiceInvites; +NSString *const kFIRServiceMessaging; +NSString *const kFIRServiceMeasurement; +NSString *const kFIRServicePerformance; +NSString *const kFIRServiceRemoteConfig; +NSString *const kFIRServiceStorage; +NSString *const kGGLServiceAnalytics; +NSString *const kGGLServiceSignIn; + +NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT"; +NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification"; +NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification"; +NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; +NSString *const kFIRAppNameKey = @"FIRAppNameKey"; +NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; + +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseDataCollectionDefaultEnabled"; + +NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; + +NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; +NSString *const kFIRAppDiagnosticsErrorKey = @"Error"; +NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; +NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; +NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; + +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey = + @"FIRAuthStateDidChangeInternalNotificationUIDKey"; + +/** + * The URL to download plist files. + */ +static NSString *const kPlistURL = @"https://console.firebase.google.com/"; + +/** + * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle + * events from Core. + */ +static NSMutableArray> *sRegisteredAsConfigurable; + +@interface FIRApp () + +#ifdef DEBUG +@property(nonatomic) BOOL alreadyOutputDataCollectionFlag; +#endif // DEBUG + +@end + +@implementation FIRApp + +// This is necessary since our custom getter prevents `_options` from being created. +@synthesize options = _options; + +static NSMutableDictionary *sAllApps; +static FIRApp *sDefaultApp; +static NSMutableDictionary *sLibraryVersions; +static dispatch_once_t sFirebaseUserAgentOnceToken; + ++ (void)configure { + FIROptions *options = [FIROptions defaultOptions]; + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find " + @"a valid GoogleService-Info.plist in your project. Please download one " + @"from %@.", + kPlistURL]; + } + [FIRApp configureWithOptions:options]; +#if TARGET_OS_OSX || TARGET_OS_TV + FIRLogNotice(kFIRLoggerCore, @"I-COR000028", + @"tvOS and macOS SDK support is not part of the official Firebase product. " + @"Instead they are community supported. Details at " + @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md."); +#endif +} + ++ (void)configureWithOptions:(FIROptions *)options { + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Options is nil. Please pass a valid options."]; + } + [FIRApp configureWithName:kFIRDefaultAppName options:options]; +} + ++ (NSCharacterSet *)applicationNameAllowedCharacters { + static NSCharacterSet *applicationNameAllowedCharacters; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableCharacterSet *allowedNameCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedNameCharacters addCharactersInString:@"-_"]; + applicationNameAllowedCharacters = [allowedNameCharacters copy]; + }); + return applicationNameAllowedCharacters; +} + ++ (void)configureWithName:(NSString *)name options:(FIROptions *)options { + if (!name || !options) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."]; + } + if (name.length == 0) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."]; + } + + if ([name isEqualToString:kFIRDefaultAppName]) { + if (sDefaultApp) { + // The default app already exixts. Handle duplicate `configure` calls and return. + [self appWasConfiguredTwice:sDefaultApp usingOptions:options]; + return; + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app."); + } else { + // Validate the app name and ensure it hasn't been configured already. + NSCharacterSet *nameCharacters = [NSCharacterSet characterSetWithCharactersInString:name]; + + if (![[self applicationNameAllowedCharacters] isSupersetOfSet:nameCharacters]) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App name can only contain alphanumeric, " + @"hyphen (-), and underscore (_) characters"]; + } + + @synchronized(self) { + if (sAllApps && sAllApps[name]) { + // The app already exists. Handle a duplicate `configure` call and return. + [self appWasConfiguredTwice:sAllApps[name] usingOptions:options]; + return; + } + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name); + } + + @synchronized(self) { + FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options]; + if (app.isDefaultApp) { + sDefaultApp = app; + } + + [FIRApp addAppToAppDictionary:app]; + + // The FIRApp instance is ready to go, `sDefaultApp` is assigned, other SDKs are now ready to be + // instantiated. + [app.container instantiateEagerComponents]; + [FIRApp sendNotificationsToSDKs:app]; + } +} + +/// Called when `configure` has been called multiple times for the same app. This can either throw +/// an exception (most cases) or ignore the duplicate configuration in situations where it's allowed +/// like an extension. ++ (void)appWasConfiguredTwice:(FIRApp *)app usingOptions:(FIROptions *)options { + // Only extensions should potentially be able to call `configure` more than once. + if (![GULAppEnvironmentUtil isAppExtension]) { + // Throw an exception since this is now an invalid state. + if (app.isDefaultApp) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Default app has already been configured."]; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } + } + + // In an extension, the entry point could be called multiple times. As long as the options are + // identical we should allow multiple `configure` calls. + if ([options isEqual:app.options]) { + // Everything is identical but the extension's lifecycle triggered `configure` twice. + // Ignore duplicate calls and return since everything should still be in a valid state. + FIRLogDebug(kFIRLoggerCore, @"I-COR000035", + @"Ignoring second `configure` call in an extension."); + return; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } +} + ++ (FIRApp *)defaultApp { + if (sDefaultApp) { + return sDefaultApp; + } + FIRLogError(kFIRLoggerCore, @"I-COR000003", + @"The default Firebase app has not yet been " + @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your " + @"application initialization. Read more: https://goo.gl/ctyzm8."); + return nil; +} + ++ (FIRApp *)appNamed:(NSString *)name { + @synchronized(self) { + if (sAllApps) { + FIRApp *app = sAllApps[name]; + if (app) { + return app; + } + } + FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name); + return nil; + } +} + ++ (NSDictionary *)allApps { + @synchronized(self) { + if (!sAllApps) { + FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet."); + } + return [sAllApps copy]; + } +} + +// Public only for tests ++ (void)resetApps { + @synchronized(self) { + sDefaultApp = nil; + [sAllApps removeAllObjects]; + sAllApps = nil; + [sLibraryVersions removeAllObjects]; + sLibraryVersions = nil; + sFirebaseUserAgentOnceToken = 0; + } +} + +- (void)deleteApp:(FIRAppVoidBoolCallback)completion { + @synchronized([self class]) { + if (sAllApps && sAllApps[self.name]) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); + + // Remove all cached instances from the container before deleting the app. + [self.container removeAllCachedInstances]; + + [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; + if ([self.name isEqualToString:kFIRDefaultAppName]) { + sDefaultApp = nil; + } + NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name}; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification + object:[self class] + userInfo:appInfoDict]; + completion(YES); + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist."); + completion(NO); + } + } +} + ++ (void)addAppToAppDictionary:(FIRApp *)app { + if (!sAllApps) { + sAllApps = [NSMutableDictionary dictionary]; + } + if ([app configureCore]) { + sAllApps[app.name] = app; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in " + @"GoogleService-Info.plist or set in the customized options."]; + } +} + +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options { + self = [super init]; + if (self) { + _name = [name copy]; + _options = [options copy]; + _options.editingLocked = YES; + _isDefaultApp = [name isEqualToString:kFIRDefaultAppName]; + _container = [[FIRComponentContainer alloc] initWithApp:self]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)configureCore { + [self checkExpectedBundleID]; + if (![self isAppIDValid]) { + return NO; + } + + [self logCoreTelemetryIfEnabled]; + +#if TARGET_OS_IOS + // Initialize the Analytics once there is a valid options under default app. Analytics should + // always initialize first by itself before the other SDKs. + if ([self.name isEqualToString:kFIRDefaultAppName]) { + Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics"); + if (firAnalyticsClass) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:); +#pragma clang diagnostic pop + if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [firAnalyticsClass performSelector:startWithConfigurationSelector + withObject:[FIRConfiguration sharedInstance].analyticsConfiguration + withObject:_options]; +#pragma clang diagnostic pop + } + } + } +#endif + + [self subscribeForAppDidBecomeActiveNotifications]; + + return YES; +} + +- (FIROptions *)options { + return [_options copy]; +} + +- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled { +#ifdef DEBUG + FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.", + dataCollectionDefaultEnabled ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; +#endif // DEBUG + + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key]; + + // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set + // within FIROptions and change the Analytics value if necessary. Analytics only works with the + // default app, so return if this isn't the default app. + if (!self.isDefaultApp) { + return; + } + + // Check if the Analytics flag is explicitly set. If so, no further actions are necessary. + if ([self.options isAnalyticsCollectionExplicitlySet]) { + return; + } + + // The Analytics flag has not been explicitly set, so update with the value being set. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[FIRAnalyticsConfiguration sharedInstance] + setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled + persistSetting:NO]; +#pragma clang diagnostic pop +} + +- (BOOL)isDataCollectionDefaultEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.", + [defaultsObject boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.", + [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [collectionEnabledPlistValue boolValue]; + } + +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set."); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return YES; +} + +#pragma mark - private + ++ (void)sendNotificationsToSDKs:(FIRApp *)app { + // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`. + NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp]; + NSDictionary *appInfoDict = @{ + kFIRAppNameKey : app.name, + kFIRAppIsDefaultAppKey : isDefaultApp, + kFIRGoogleAppIDKey : app.options.googleAppID + }; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification + object:self + userInfo:appInfoDict]; + + // This is the new way of sending information to SDKs. + // TODO: Do we want this on a background thread, maybe? + @synchronized(self) { + for (Class library in sRegisteredAsConfigurable) { + [library configureWithApp:app]; + } + } +} + ++ (NSError *)errorForMissingOptions { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : + @"Unable to parse GoogleService-Info.plist in order to configure services.", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidPlistFile + userInfo:errorDict]; +} + ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", service]; + NSDictionary *errorDict = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + return [NSError errorWithDomain:domain code:code userInfo:errorDict]; +} + ++ (NSError *)errorForInvalidAppID { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : @"Unable to validate Google App ID", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the " + @"customized options." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidAppID + userInfo:errorDict]; +} + ++ (BOOL)isDefaultAppConfigured { + return (sDefaultApp != nil); +} + ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version { + // Create the set of characters which aren't allowed, only if this feature is used. + NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedSet addCharactersInString:@"-_."]; + NSCharacterSet *disallowedSet = [allowedSet invertedSet]; + // Make sure the library name and version strings do not contain unexpected characters, and + // add the name/version pair to the dictionary. + if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound && + [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) { + @synchronized(self) { + if (!sLibraryVersions) { + sLibraryVersions = [[NSMutableDictionary alloc] init]; + } + sLibraryVersions[name] = version; + } + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000027", + @"The library name (%@) or version number (%@) contain invalid characters. " + @"Only alphanumeric, dash, underscore and period characters are allowed.", + name, version); + } +} + ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version { + // This is called at +load time, keep the work to a minimum. + + // Ensure the class given conforms to the proper protocol. + if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] || + ![(Class)library respondsToSelector:@selector(componentsToRegister)]) { + [NSException raise:NSInvalidArgumentException + format:@"Class %@ attempted to register components, but it does not conform to " + @"`FIRLibrary or provide a `componentsToRegister:` method.", + library]; + } + + [FIRComponentContainer registerAsComponentRegistrant:library]; + if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRegisteredAsConfigurable = [[NSMutableArray alloc] init]; + }); + @synchronized(self) { + [sRegisteredAsConfigurable addObject:library]; + } + } + [self registerLibrary:name withVersion:version]; +} + ++ (NSString *)firebaseUserAgent { + @synchronized(self) { + dispatch_once(&sFirebaseUserAgentOnceToken, ^{ + // Report FirebaseCore version for useragent string + [FIRApp registerLibrary:@"fire-ios" + withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]]; + + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *xcodeVersion = info[@"DTXcodeBuild"]; + NSString *sdkVersion = info[@"DTSDKBuild"]; + if (xcodeVersion) { + [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion]; + } + if (sdkVersion) { + [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion]; + } + + NSString *swiftFlagValue = [self hasSwiftRuntime] ? @"true" : @"false"; + [FIRApp registerLibrary:@"swift" withVersion:swiftFlagValue]; + }); + + NSMutableArray *libraries = + [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count]; + for (NSString *libraryName in sLibraryVersions) { + [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName, + sLibraryVersions[libraryName]]]; + } + [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + return [libraries componentsJoinedByString:@" "]; + } +} + ++ (BOOL)hasSwiftRuntime { + // The class + // [Swift._SwiftObject](https://github.com/apple/swift/blob/5eac3e2818eb340b11232aff83edfbd1c307fa03/stdlib/public/runtime/SwiftObject.h#L35) + // is a part of Swift runtime, so it should be present if Swift runtime is available. + + BOOL hasSwiftRuntime = + objc_lookUpClass("Swift._SwiftObject") != nil || + // Swift object class name before + // https://github.com/apple/swift/commit/9637b4a6e11ddca72f5f6dbe528efc7c92f14d01 + objc_getClass("_TtCs12_SwiftObject") != nil; + + return hasSwiftRuntime; +} + +- (void)checkExpectedBundleID { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *expectedBundleID = [self expectedBundleID]; + // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for + // backward compatibility. + if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID + inBundles:bundles]) { + FIRLogError(kFIRLoggerCore, @"I-COR000008", + @"The project's Bundle ID is inconsistent with " + @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are " + @"using a customized options. To ensure that everything can be configured " + @"correctly, you may need to make the Bundle IDs consistent. To continue with this " + @"plist file, you may change your app's bundle identifier to '%@'. Or you can " + @"download a new configuration file that matches your bundle identifier from %@ " + @"and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + } +} + +#pragma mark - private - App ID Validation + +/** + * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. + * This is the main method for validating app ID. + * + * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + */ +- (BOOL)isAppIDValid { + NSString *appID = _options.googleAppID; + BOOL isValid = [FIRApp validateAppID:appID]; + if (!isValid) { + NSString *expectedBundleID = [self expectedBundleID]; + FIRLogError(kFIRLoggerCore, @"I-COR000009", + @"The GOOGLE_APP_ID either in the plist file " + @"'%@.%@' or the one set in the customized options is invalid. If you are using " + @"the plist file, use the iOS version of bundle identifier to download the file, " + @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle " + @"identifier to '%@'. Or you can download a new configuration file that matches " + @"your bundle identifier from %@ and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + }; + return isValid; +} + ++ (BOOL)validateAppID:(NSString *)appID { + // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not + // have a valid fingerprint, otherwise we just warn about the potential issue. + if (!appID.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + NSString *appIDVersion; + if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] + intoString:&appIDVersion]) { + return NO; + } + + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + NSArray *knownVersions = @[ @"1" ]; + if (![knownVersions containsObject:appIDVersion]) { + // Permit unknown yet properly formatted app ID versions. + FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion); + return YES; + } + + if (![self validateAppIDFormat:appID withVersion:appIDVersion]) { + return NO; + } + + if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + return NO; + } + + return YES; +} + ++ (NSString *)actualBundleID { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +/** + * Validates that the format of the app ID string is what is expected based on the supplied version. + * The version must end in ":". + * + * For v1 app ids the format is expected to be + * '::ios:'. + * + * This method does not verify that the contents of the app id are correct, just that they fulfill + * the expected format. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected format, NO otherwise. + */ ++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { + if (!appID.length || !version.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + // Skip version part + // '**::ios:' + if (![stringScanner scanString:version intoString:NULL]) { + // The version part is missing or mismatched + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '*:*:ios:' + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':**:ios:'. + NSInteger projectNumber = NSNotFound; + if (![stringScanner scanInteger:&projectNumber]) { + // NO project number found. + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':*:*ios:'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The project number must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::*ios*:'. + NSString *platform; + if (![stringScanner scanUpToString:@":" intoString:&platform]) { + return NO; + } + + if (![platform isEqualToString:@"ios"]) { + // The platform must be @"ios" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios*:*'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The platform must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios:**'. + unsigned long long fingerprint = NSNotFound; + if (![stringScanner scanHexLongLong:&fingerprint]) { + // Fingerprint part is missing + return NO; + } + + if (!stringScanner.isAtEnd) { + // There are not allowed characters in the fingerprint part + return NO; + } + + return YES; +} + +/** + * Validates that the fingerprint of the app ID string is what is expected based on the supplied + * version. + * + * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * otherwise. + */ ++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { + // Extract the supplied fingerprint from the supplied app ID. + // This assumes the app ID format is the same for all known versions below. If the app ID format + // changes in future versions, the tokenizing of the app ID format will need to take into account + // the version of the app ID. + NSArray *components = [appID componentsSeparatedByString:@":"]; + if (components.count != 4) { + return NO; + } + + NSString *suppliedFingerprintString = components[3]; + if (!suppliedFingerprintString.length) { + return NO; + } + + uint64_t suppliedFingerprint; + NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; + if (![scanner scanHexLongLong:&suppliedFingerprint]) { + return NO; + } + + if ([version isEqual:@"1"]) { + // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated. + return YES; + } + + // Unknown version. + return NO; +} + +- (NSString *)expectedBundleID { + return _options.bundleID; +} + +// end App ID validation + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error { + // Do nothing. Please remove calls to this method. +} +#pragma clang diagnostic pop + +#pragma mark - App Life Cycle + +- (void)subscribeForAppDidBecomeActiveNotifications { +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification; +#elif TARGET_OS_OSX + NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification; +#endif + +#if !TARGET_OS_WATCH + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidBecomeActive:) + name:notificationName + object:nil]; +#endif +} + +- (void)appDidBecomeActive:(NSNotification *)notification { + [self logCoreTelemetryIfEnabled]; +} + +- (void)logCoreTelemetryIfEnabled { + if ([self isDataCollectionDefaultEnabled]) { + [FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m new file mode 100644 index 0000000..e4125cd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m @@ -0,0 +1,47 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h" + +#import + +@implementation FIRAppAssociationRegistration + ++ (nullable id)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(id _Nullable (^)(void))creationBlock { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey); + if (!objectsByKey) { + objectsByKey = [[NSMutableDictionary alloc] init]; + objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + id obj = objectsByKey[key]; + NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey]; + if (obj) { + if ([creationBlockBeingCalled isEqual:obj]) { + [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed" + format:@"host: %@ key: %@", host, key]; + } + return obj; + } + objectsByKey[key] = creationBlockBeingCalled; + obj = creationBlock(); + objectsByKey[key] = obj; + return obj; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h new file mode 100644 index 0000000..d9475dd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * This class provides utilities for accessing resources in bundles. + */ +@interface FIRBundleUtil : NSObject + +/** + * Finds all relevant bundles, starting with [NSBundle mainBundle]. + */ ++ (NSArray *)relevantBundles; + +/** + * Reads the options dictionary from one of the provided bundles. + * + * @param resourceName The resource name, e.g. @"GoogleService-Info". + * @param fileType The file type (extension), e.g. @"plist". + * @param bundles The bundles to expect, in priority order. See also + * +[FIRBundleUtil relevantBundles]. + */ ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles; + +/** + * Finds URL schemes defined in all relevant bundles, starting with those from + * [NSBundle mainBundle]. + */ ++ (NSArray *)relevantURLSchemes; + +/** + * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension + * suffixes). + */ ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles; + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m new file mode 100644 index 0000000..b858f14 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m @@ -0,0 +1,75 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" + +#import + +@implementation FIRBundleUtil + ++ (NSArray *)relevantBundles { + return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ]; +} + ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles { + // Loop through all bundles to find the config dict. + for (NSBundle *bundle in bundles) { + NSString *path = [bundle pathForResource:resourceName ofType:fileType]; + // Use the first one we find. + if (path) { + return path; + } + } + return nil; +} + ++ (NSArray *)relevantURLSchemes { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (NSBundle *bundle in [[self class] relevantBundles]) { + NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]]; + } + } + return result; +} + ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { + for (NSBundle *bundle in bundles) { + // This allows app extensions that have the app's bundle as their prefix to pass this test. + NSString *applicationBundleIdentifier = + [GULAppEnvironmentUtil isAppExtension] + ? [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier] + : bundle.bundleIdentifier; + + if ([applicationBundleIdentifier isEqualToString:bundleIdentifier]) { + return YES; + } + } + return NO; +} + ++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m new file mode 100644 index 0000000..9c1fbed --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponent.h" + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRComponent () + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock; + +@end + +@implementation FIRComponent + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; +} + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:instantiationTiming + dependencies:dependencies + creationBlock:creationBlock]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + self = [super init]; + if (self) { + _protocol = protocol; + _instantiationTiming = instantiationTiming; + _dependencies = [dependencies copy]; + _creationBlock = creationBlock; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m new file mode 100644 index 0000000..9f91786 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m @@ -0,0 +1,208 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer () + +/// The dictionary of components that are registered for a particular app. The key is an `NSString` +/// of the protocol. +@property(nonatomic, strong) NSMutableDictionary *components; + +/// Cached instances of components that requested to be cached. +@property(nonatomic, strong) NSMutableDictionary *cachedInstances; + +/// Protocols of components that have requested to be eagerly instantiated. +@property(nonatomic, strong, nullable) NSMutableArray *eagerProtocolsToInstantiate; + +@end + +@implementation FIRComponentContainer + +// Collection of all classes that register to provide components. +static NSMutableSet *sFIRComponentRegistrants; + +#pragma mark - Public Registration + ++ (void)registerAsComponentRegistrant:(Class)klass { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sFIRComponentRegistrants = [[NSMutableSet alloc] init]; + }); + + [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants]; +} + ++ (void)registerAsComponentRegistrant:(Class)klass + inSet:(NSMutableSet *)allRegistrants { + [allRegistrants addObject:klass]; +} + +#pragma mark - Internal Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWithApp:app registrants:sFIRComponentRegistrants]; +} + +- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants { + self = [super init]; + if (self) { + _app = app; + _cachedInstances = [NSMutableDictionary dictionary]; + _components = [NSMutableDictionary dictionary]; + + [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app]; + } + return self; +} + +- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app { + // Keep track of any components that need to eagerly instantiate after all components are added. + self.eagerProtocolsToInstantiate = [[NSMutableArray alloc] init]; + + // Loop through the verified component registrants and populate the components array. + for (Class klass in classes) { + // Loop through all the components being registered and store them as appropriate. + // Classes which do not provide functionality should use a dummy FIRComponentRegistrant + // protocol. + for (FIRComponent *component in [klass componentsToRegister]) { + // Check if the component has been registered before, and error out if so. + NSString *protocolName = NSStringFromProtocol(component.protocol); + if (self.components[protocolName]) { + FIRLogError(kFIRLoggerCore, @"I-COR000029", + @"Attempted to register protocol %@, but it already has an implementation.", + protocolName); + continue; + } + + // Store the creation block for later usage. + self.components[protocolName] = component.creationBlock; + + // Queue any protocols that should be eagerly instantiated. Don't instantiate them yet + // because they could depend on other components that haven't been added to the components + // array yet. + BOOL shouldInstantiateEager = + (component.instantiationTiming == FIRInstantiationTimingAlwaysEager); + BOOL shouldInstantiateDefaultEager = + (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp && + [app isDefaultApp]); + if (shouldInstantiateEager || shouldInstantiateDefaultEager) { + [self.eagerProtocolsToInstantiate addObject:component.protocol]; + } + } + } +} + +#pragma mark - Instance Creation + +- (void)instantiateEagerComponents { + // After all components are registered, instantiate the ones that are requesting eager + // instantiation. + @synchronized(self) { + for (Protocol *protocol in self.eagerProtocolsToInstantiate) { + // Get an instance for the protocol, which will instantiate it since it couldn't have been + // cached yet. Ignore the instance coming back since we don't need it. + __unused id unusedInstance = [self instanceForProtocol:protocol]; + } + + // All eager instantiation is complete, clear the stored property now. + self.eagerProtocolsToInstantiate = nil; + } +} + +/// Instantiate an instance of a class that conforms to the specified protocol. +/// This will: +/// - Call the block to create an instance if possible, +/// - Validate that the instance returned conforms to the protocol it claims to, +/// - Cache the instance if the block requests it +/// +/// Note that this method assumes the caller already has @sychronized on self. +- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol + withBlock:(FIRComponentCreationBlock)creationBlock { + if (!creationBlock) { + return nil; + } + + // Create an instance using the creation block. + BOOL shouldCache = NO; + id instance = creationBlock(self, &shouldCache); + if (!instance) { + return nil; + } + + // An instance was created, validate that it conforms to the protocol it claims to. + NSString *protocolName = NSStringFromProtocol(protocol); + if (![instance conformsToProtocol:protocol]) { + FIRLogError(kFIRLoggerCore, @"I-COR000030", + @"An instance conforming to %@ was requested, but the instance provided does not " + @"conform to the protocol", + protocolName); + } + + // The instance is ready to be returned, but check if it should be cached first before returning. + if (shouldCache) { + self.cachedInstances[protocolName] = instance; + } + + return instance; +} + +#pragma mark - Internal Retrieval + +- (nullable id)instanceForProtocol:(Protocol *)protocol { + // Check if there is a cached instance, and return it if so. + NSString *protocolName = NSStringFromProtocol(protocol); + + id cachedInstance; + @synchronized(self) { + cachedInstance = self.cachedInstances[protocolName]; + if (!cachedInstance) { + // Use the creation block to instantiate an instance and return it. + FIRComponentCreationBlock creationBlock = self.components[protocolName]; + cachedInstance = [self instantiateInstanceForProtocol:protocol withBlock:creationBlock]; + } + } + return cachedInstance; +} + +#pragma mark - Lifecycle + +- (void)removeAllCachedInstances { + @synchronized(self) { + // Loop through the cache and notify each instance that is a maintainer to clean up after + // itself. + for (id instance in self.cachedInstances.allValues) { + if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] && + [instance respondsToSelector:@selector(appWillBeDeleted:)]) { + [instance appWillBeDeleted:self.app]; + } + } + + // Empty the cache. + [self.cachedInstances removeAllObjects]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m new file mode 100644 index 0000000..6410f2e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentType.h" + +#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" + +@implementation FIRComponentType + ++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container { + // Forward the call to the container. + return [container instanceForProtocol:protocol]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m new file mode 100644 index 0000000..a1c9f4a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m @@ -0,0 +1,46 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" + +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" + +extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +@implementation FIRConfiguration + ++ (instancetype)sharedInstance { + static FIRConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance]; + } + return self; +} + +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel { + NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin, + @"Invalid logger level, %ld", (long)loggerLevel); + FIRSetLoggerLevel(loggerLevel); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m new file mode 100644 index 0000000..4981ca1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" + +#import + +#import + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop. +Class FIRCoreDiagnosticsImplementation; + +@implementation FIRCoreDiagnosticsConnector + ++ (void)initialize { + if (!FIRCoreDiagnosticsImplementation) { + FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics"); + if (FIRCoreDiagnosticsImplementation) { + NSAssert([FIRCoreDiagnosticsImplementation + conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)], + @"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol."); + NSAssert( + [FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)], + @"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData."); + } + } +} + ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options { + if (FIRCoreDiagnosticsImplementation) { + FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init]; + [diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey]; + [diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey]; + [diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey]; + [diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey]; + [diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey]; + [diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist) + forKey:kFIRCDUsingOptionsFromDefaultPlistKey]; + [diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey]; + [FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m new file mode 100644 index 0000000..e1e2578 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRDependency () + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +@end + +@implementation FIRDependency + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol { + return [[self alloc] initWithProtocol:protocol isRequired:YES]; +} + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + return [[self alloc] initWithProtocol:protocol isRequired:required]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + self = [super init]; + if (self) { + _protocol = protocol; + _isRequired = required; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m new file mode 100644 index 0000000..bbe0561 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" + +#import + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +@implementation FIRDiagnosticsData { + /** Backing ivar for the diagnosticObjects property. */ + NSMutableDictionary *_diagnosticObjects; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _diagnosticObjects = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)insertValue:(nullable id)value forKey:(NSString *)key { + if (key) { + _diagnosticObjects[key] = value; + } +} + +#pragma mark - FIRCoreDiagnosticsData + +- (NSDictionary *)diagnosticObjects { + if (!_diagnosticObjects[kFIRCDllAppsCountKey]) { + _diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count); + } + if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) { + _diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] = + @([[FIRApp defaultApp] isDataCollectionDefaultEnabled]); + } + if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) { + _diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent]; + } + return _diagnosticObjects; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)setDiagnosticObjects:(NSDictionary *)diagnosticObjects { + NSAssert(NO, @"Please use -insertValue:forKey:"); +} +#pragma clang diagnostic pop + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m new file mode 100644 index 0000000..104eeb8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m @@ -0,0 +1,21 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRErrors.h" + +NSString *const kFirebaseErrorDomain = @"com.firebase"; +NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config"; +NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core"; +NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf"; +NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage"; diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m new file mode 100644 index 0000000..277b0f7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import +#import + +const static long secondsInDay = 86400; +@implementation FIRHeartbeatInfo : NSObject + +/** Updates the storage with the heartbeat information corresponding to this tag. + * @param heartbeatTag Tag which could either be sdk specific tag or the global tag. + * @return Boolean representing whether the heartbeat needs to be sent for this tag or not. + */ ++ (BOOL)updateIfNeededHeartbeatDateForTag:(NSString *)heartbeatTag { + @synchronized(self) { + NSString *const kHeartbeatStorageFile = @"HEARTBEAT_INFO_STORAGE"; + GULHeartbeatDateStorage *dataStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kHeartbeatStorageFile]; + NSDate *heartbeatTime = [dataStorage heartbeatDateForTag:heartbeatTag]; + NSDate *currentDate = [NSDate date]; + if (heartbeatTime != nil) { + NSTimeInterval secondsBetween = [currentDate timeIntervalSinceDate:heartbeatTime]; + if (secondsBetween < secondsInDay) { + return false; + } + } + return [dataStorage setHearbeatDate:currentDate forTag:heartbeatTag]; + } +} + ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag { + NSString *globalTag = @"GLOBAL"; + BOOL isSdkHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:heartbeatTag]; + BOOL isGlobalHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:globalTag]; + if (!isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Both sdk and global heartbeat not needed. + return FIRHeartbeatInfoCodeNone; + } else if (isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Only SDK heartbeat needed. + return FIRHeartbeatInfoCodeSDK; + } else if (!isSdkHeartbeatNeeded && isGlobalHeartbeatNeeded) { + // Only global heartbeat needed. + return FIRHeartbeatInfoCodeGlobal; + } else { + // Both sdk and global heartbeat are needed. + return FIRHeartbeatInfoCodeCombined; + } +} +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m new file mode 100644 index 0000000..ba2ee1f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m @@ -0,0 +1,179 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +#import +#import +#import + +#import "FirebaseCore/Sources/FIRVersion.h" + +FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]"; + +// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones! +FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]"; +FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]"; +FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]"; +FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]"; +FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]"; +FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]"; +FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]"; +FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]"; + +/// Arguments passed on launch. +NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled"; +NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled"; +NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR"; + +/// Key for the debug mode bit in NSUserDefaults. +NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode"; + +/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults` +/// will be used. +static NSUserDefaults *sFIRLoggerUserDefaults; + +static dispatch_once_t sFIRLoggerOnceToken; + +// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled +// flags used by Analytics. Users who use those flags expect Analytics to log verbosely, +// while the rest of Firebase logs at the default level. This flag is introduced to support +// that behavior. +static BOOL sFIRAnalyticsDebugMode; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void FIRLoggerInitializeASL() { + dispatch_once(&sFIRLoggerOnceToken, ^{ + // Register Firebase Version with GULLogger. + GULLoggerRegisterVersion(FIRVersionString); + + // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. + NSArray *arguments = [NSProcessInfo processInfo].arguments; + BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument]; + + // Use the standard NSUserDefaults if it hasn't been explicitly set. + if (sFIRLoggerUserDefaults == nil) { + sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults]; + } + + BOOL forceDebugMode = NO; + BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey]; + if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] || + debugMode) { // Debug mode + [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey]; + forceDebugMode = YES; + } + GULLoggerInitializeASL(); + if (overrideSTDERR) { + GULLoggerEnableSTDERR(); + } + if (forceDebugMode) { + GULLoggerForceDebug(); + } + }); +} + +__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) { + sFIRAnalyticsDebugMode = analyticsDebugMode; +} + +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) { + FIRLoggerInitializeASL(); + GULSetLoggerLevel((GULLoggerLevel)loggerLevel); +} + +#ifdef DEBUG +void FIRResetLogger() { + extern void GULResetLogger(void); + sFIRLoggerOnceToken = 0; + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + sFIRLoggerUserDefaults = nil; + GULResetLogger(); +} + +void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) { + sFIRLoggerUserDefaults = defaults; +} +#endif + +/** + * Check if the level is high enough to be loggable. + * + * Analytics can override the log level with an intentional race condition. + * Add the attribute to get a clean thread sanitizer run. + */ +__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, + BOOL analyticsComponent) { + FIRLoggerInitializeASL(); + if (sFIRAnalyticsDebugMode && analyticsComponent) { + return YES; + } + return GULIsLoggableLevel((GULLoggerLevel)loggerLevel); +} + +void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + FIRLoggerInitializeASL(); + GULLogBasic((GULLoggerLevel)level, service, + sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode, + message, args_ptr); +} + +/** + * Generates the logging functions using macros. + * + * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed. + * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed. + */ +#define FIR_LOGGING_FUNCTION(level) \ + void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +FIR_LOGGING_FUNCTION(Error) +FIR_LOGGING_FUNCTION(Warning) +FIR_LOGGING_FUNCTION(Notice) +FIR_LOGGING_FUNCTION(Info) +FIR_LOGGING_FUNCTION(Debug) + +#undef FIR_MAKE_LOGGER + +#pragma mark - FIRLoggerWrapper + +@implementation FIRLoggerWrapper + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + FIRLogBasic(level, service, messageCode, message, args); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m new file mode 100644 index 0000000..d185330 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m @@ -0,0 +1,490 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Keys for the strings in the plist file. +NSString *const kFIRAPIKey = @"API_KEY"; +NSString *const kFIRTrackingID = @"TRACKING_ID"; +NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID"; +NSString *const kFIRClientID = @"CLIENT_ID"; +NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID"; +NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID"; +NSString *const kFIRDatabaseURL = @"DATABASE_URL"; +NSString *const kFIRStorageBucket = @"STORAGE_BUCKET"; +// The key to locate the expected bundle identifier in the plist file. +NSString *const kFIRBundleID = @"BUNDLE_ID"; +// The key to locate the project identifier in the plist file. +NSString *const kFIRProjectID = @"PROJECT_ID"; + +NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED"; + +NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED"; +NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED"; + +// Library version ID formatted like: +// @"5" // Major version (one or more digits) +// @"04" // Minor version (exactly 2 digits) +// @"01" // Build number (exactly 2 digits) +// @"000"; // Fixed "000" +NSString *kFIRLibraryVersionID; + +// Plist file name. +NSString *const kServiceInfoFileName = @"GoogleService-Info"; +// Plist file type. +NSString *const kServiceInfoFileType = @"plist"; + +// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp. +NSString *const kFIRExceptionBadModification = + @"Attempted to modify options after it's set on FIRApp. Please modify all properties before " + @"initializing FIRApp."; + +@interface FIROptions () + +/** + * This property maintains the actual configuration key-value pairs. + */ +@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary; + +/** + * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary. + * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the main plist override values from the GoogleService-Info.plist. + */ +@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary; + +/** + * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the infoDictionary override values from the GoogleService-Info.plist. + */ +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary; + +/** + * Throw exception if editing is locked when attempting to modify an option. + */ +- (void)checkEditingLocked; + +@end + +@implementation FIROptions { + /// Backing variable for self.analyticsOptionsDictionary. + NSDictionary *_analyticsOptionsDictionary; +} + +static FIROptions *sDefaultOptions = nil; +static NSDictionary *sDefaultOptionsDictionary = nil; + +#pragma mark - Public only for internal class methods + ++ (FIROptions *)defaultOptions { + if (sDefaultOptions != nil) { + return sDefaultOptions; + } + + NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary]; + if (defaultOptionsDictionary == nil) { + return nil; + } + + sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary]; + return sDefaultOptions; +} + +#pragma mark - Private class methods + ++ (NSDictionary *)defaultOptionsDictionary { + if (sDefaultOptionsDictionary != nil) { + return sDefaultOptionsDictionary; + } + NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName]; + if (plistFilePath == nil) { + return nil; + } + sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath]; + if (sDefaultOptionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000011", + @"The configuration file is not a dictionary: " + @"'%@.%@'.", + kServiceInfoFileName, kServiceInfoFileType); + } + return sDefaultOptionsDictionary; +} + +// Returns the path of the plist file with a given file name. ++ (NSString *)plistFilePathWithName:(NSString *)fileName { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *plistFilePath = + [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName + andFileType:kServiceInfoFileType + inBundles:bundles]; + if (plistFilePath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.", + fileName, kServiceInfoFileType); + } + return plistFilePath; +} + ++ (void)resetDefaultOptions { + sDefaultOptions = nil; + sDefaultOptionsDictionary = nil; +} + +#pragma mark - Private instance methods + +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary { + self = [super init]; + if (self) { + _optionsDictionary = [optionsDictionary mutableCopy]; + _usingOptionsFromDefaultPlist = YES; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + FIROptions *newOptions = [[[self class] allocWithZone:zone] init]; + if (newOptions) { + newOptions.optionsDictionary = self.optionsDictionary; + newOptions.deepLinkURLScheme = self.deepLinkURLScheme; + newOptions.appGroupID = self.appGroupID; + newOptions.editingLocked = self.isEditingLocked; + newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist; + } + return newOptions; +} + +#pragma mark - Public instance methods + +- (instancetype)initWithContentsOfFile:(NSString *)plistPath { + self = [super init]; + if (self) { + if (plistPath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil."); + return nil; + } + _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy]; + if (_optionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000014", + @"The configuration file at %@ does not exist or " + @"is not a well-formed plist file.", + plistPath); + return nil; + } + // TODO: Do we want to validate the dictionary here? It says we do that already in + // the public header. + } + return self; +} + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary]; + [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID]; + [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID]; + [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID]; + self.optionsDictionary = mutableOptionsDict; + } + return self; +} + +- (NSString *)APIKey { + return self.optionsDictionary[kFIRAPIKey]; +} + +- (void)checkEditingLocked { + if (self.isEditingLocked) { + [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification]; + } +} + +- (void)setAPIKey:(NSString *)APIKey { + [self checkEditingLocked]; + _optionsDictionary[kFIRAPIKey] = [APIKey copy]; +} + +- (NSString *)clientID { + return self.optionsDictionary[kFIRClientID]; +} + +- (void)setClientID:(NSString *)clientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRClientID] = [clientID copy]; +} + +- (NSString *)trackingID { + return self.optionsDictionary[kFIRTrackingID]; +} + +- (void)setTrackingID:(NSString *)trackingID { + [self checkEditingLocked]; + _optionsDictionary[kFIRTrackingID] = [trackingID copy]; +} + +- (NSString *)GCMSenderID { + return self.optionsDictionary[kFIRGCMSenderID]; +} + +- (void)setGCMSenderID:(NSString *)GCMSenderID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy]; +} + +- (NSString *)projectID { + return self.optionsDictionary[kFIRProjectID]; +} + +- (void)setProjectID:(NSString *)projectID { + [self checkEditingLocked]; + _optionsDictionary[kFIRProjectID] = [projectID copy]; +} + +- (NSString *)androidClientID { + return self.optionsDictionary[kFIRAndroidClientID]; +} + +- (void)setAndroidClientID:(NSString *)androidClientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy]; +} + +- (NSString *)googleAppID { + return self.optionsDictionary[kFIRGoogleAppID]; +} + +- (void)setGoogleAppID:(NSString *)googleAppID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy]; +} + +- (NSString *)libraryVersionID { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The unit tests are set up to catch anything that does not properly convert. + NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString]; + NSArray *components = [version componentsSeparatedByString:@"."]; + NSString *major = [components objectAtIndex:0]; + NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]]; + NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]]; + kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch]; + }); + return kFIRLibraryVersionID; +} + +- (void)setLibraryVersionID:(NSString *)libraryVersionID { + _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy]; +} + +- (NSString *)databaseURL { + return self.optionsDictionary[kFIRDatabaseURL]; +} + +- (void)setDatabaseURL:(NSString *)databaseURL { + [self checkEditingLocked]; + + _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy]; +} + +- (NSString *)storageBucket { + return self.optionsDictionary[kFIRStorageBucket]; +} + +- (void)setStorageBucket:(NSString *)storageBucket { + [self checkEditingLocked]; + _optionsDictionary[kFIRStorageBucket] = [storageBucket copy]; +} + +- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme { + [self checkEditingLocked]; + _deepLinkURLScheme = [deepLinkURLScheme copy]; +} + +- (NSString *)bundleID { + return self.optionsDictionary[kFIRBundleID]; +} + +- (void)setBundleID:(NSString *)bundleID { + [self checkEditingLocked]; + _optionsDictionary[kFIRBundleID] = [bundleID copy]; +} + +- (void)setAppGroupID:(NSString *)appGroupID { + [self checkEditingLocked]; + _appGroupID = [appGroupID copy]; +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + if (!object || ![object isKindOfClass:[FIROptions class]]) { + return NO; + } + + return [self isEqualToOptions:(FIROptions *)object]; +} + +- (BOOL)isEqualToOptions:(FIROptions *)options { + // Skip any non-FIROptions classes. + if (![options isKindOfClass:[FIROptions class]]) { + return NO; + } + + // Check the internal dictionary and custom properties for differences. + if (![options.optionsDictionary isEqualToDictionary:self.optionsDictionary]) { + return NO; + } + + // Validate extra properties not contained in the dictionary. Only validate it if one of the + // objects has the property set. + if ((options.deepLinkURLScheme != nil || self.deepLinkURLScheme != nil) && + ![options.deepLinkURLScheme isEqualToString:self.deepLinkURLScheme]) { + return NO; + } + + if ((options.appGroupID != nil || self.appGroupID != nil) && + ![options.appGroupID isEqualToString:self.appGroupID]) { + return NO; + } + + // Validate the Analytics options haven't changed with the Info.plist. + if (![options.analyticsOptionsDictionary isEqualToDictionary:self.analyticsOptionsDictionary]) { + return NO; + } + + // We don't care about the `editingLocked` or `usingOptionsFromDefaultPlist` properties since + // those relate to lifecycle and construction, we only care if the contents of the options + // themselves are equal. + return YES; +} + +- (NSUInteger)hash { + // This is strongly recommended for any object that implements a custom `isEqual:` method to + // ensure that dictionary and set behavior matches other `isEqual:` checks. + // Note: `self.analyticsOptionsDictionary` was left out here since it solely relies on the + // contents of the main bundle's `Info.plist`. We should avoid reading that file and the contents + // should be identical. + return self.optionsDictionary.hash ^ self.deepLinkURLScheme.hash ^ self.appGroupID.hash; +} + +#pragma mark - Internal instance methods + +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary { + if (_analyticsOptionsDictionary == nil) { + NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init]; + NSArray *measurementKeys = @[ + kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled, + kFIRIsAnalyticsCollectionDeactivated + ]; + for (NSString *key in measurementKeys) { + id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil; + if (!value) { + continue; + } + tempAnalyticsOptions[key] = value; + } + _analyticsOptionsDictionary = tempAnalyticsOptions; + } + return _analyticsOptionsDictionary; +} + +- (NSDictionary *)analyticsOptionsDictionary { + return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary]; +} + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still + * be supported. + */ +- (BOOL)isMeasurementEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (value == nil) { + // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have + // to check if it's the default app. The FIROptions instance can't be modified after + // `+configure` is called, so it's not a good place to copy it either in case the flag is + // changed at runtime. + + // If no values are set for Analytics, fall back to the global collection switch in FIRApp. + // Analytics only supports the default FIRApp, so check that first. + if (![FIRApp isDefaultAppConfigured]) { + return NO; + } + + // Fall back to the default app's collection switch when the key is not in the dictionary. + return [FIRApp defaultApp].isDataCollectionDefaultEnabled; + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionExplicitlySet { + // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication + // that the developer wants FirebaseAnalytics enabled so continue checking. + if (self.isAnalyticsCollectionDeactivated) { + return YES; + } + + // Check if the current Analytics flag is set. + id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // Check if the old measurement flag is set. + id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // No flags are set to explicitly enable or disable FirebaseAnalytics. + return NO; +} + +- (BOOL)isAnalyticsCollectionEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (value == nil) { + return self.isMeasurementEnabled; // Fall back to older plist flag. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionDeactivated { + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated]; + if (value == nil) { + return NO; // Analytics Collection is not deactivated when the key is not in the dictionary. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsEnabled { + return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue]; +} + +- (BOOL)isSignInEnabled { + return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h new file mode 100644 index 0000000..226efb1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The version of the Firebase SDK. */ +FOUNDATION_EXPORT const char *const FIRVersionString; + +/** The version of the FirebaseCore Component. */ +FOUNDATION_EXPORT const char *const FIRCoreVersionString; diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m new file mode 100644 index 0000000..ec0f6ba --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_VERSION +#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation" +#endif + +#ifndef FIRCore_VERSION +#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation" +#endif + +// The following two macros supply the incantation so that the C +// preprocessor does not try to parse the version as a floating +// point number. See +// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/ +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION); +const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION); diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h new file mode 100644 index 0000000..6429ac7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// Values stored in analyticsEnabledState. Never alter these constants since they must match with +/// values persisted to disk. +typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) { + // 0 is the default value for keys not found stored in persisted config, so it cannot represent + // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet. + kFIRAnalyticsEnabledStateNotSet = 0, + kFIRAnalyticsEnabledStateSetYes = 1, + kFIRAnalyticsEnabledStateSetNo = 2, +}; + +/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads +/// measurementEnabledState using this same key. +static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey = + @"/google/measurement/measurement_enabled_state"; + +static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification = + @"FIRAnalyticsConfigurationSetEnabledNotification"; +static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification = + @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification"; +static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification = + @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification"; + +@interface FIRAnalyticsConfiguration : NSObject + +/// Returns the shared instance of FIRAnalyticsConfiguration. ++ (FIRAnalyticsConfiguration *)sharedInstance; + +// Sets whether analytics collection is enabled for this app on this device. This setting is +// persisted across app sessions. By default it is enabled. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist +/// the value or not. The setting should not be persisted if being set by the global data collection +/// flag. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist; + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h new file mode 100644 index 0000000..3fc69c6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// TODO: Remove this once Auth moves over to Core's instance registration system. +/** @class FIRAppAssociationRegistration + @brief Manages object associations as a singleton-dependent: At most one object is + registered for any given host/key pair, and the object shall be created on-the-fly when + asked for. + */ +@interface FIRAppAssociationRegistration : NSObject + +/** @fn registeredObjectWithHost:key:creationBlock: + @brief Retrieves the registered object with a particular host and key. + @param host The host object. + @param key The key to specify the registered object on the host. + @param creationBlock The block to return the object to be registered if not already. + The block is executed immediately before this method returns if it is executed at all. + It can also be executed multiple times across different method invocations if previous + execution of the block returns @c nil. + @return The registered object for the host/key pair, or @c nil if no object is registered + and @c creationBlock returns @c nil. + @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this + method again within the @c creationBlock with the same host/key pair raises an exception. + The registered object is retained by the host. + */ ++ (nullable ObjectType)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(ObjectType _Nullable (^)(void))creationBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 0000000..ad1a186 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,162 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 0000000..cb51ee7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 0000000..8dfab9c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h new file mode 100644 index 0000000..2b77981 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer (Private) + +/// Initializes a container for a given app. This should only be called by the app itself. +- (instancetype)initWithApp:(FIRApp *)app; + +/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the +/// protocol wasn't registered, or if the instance couldn't be instantiated for the provided app. +- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:)); + +/// Instantiates all the components that have registered as "eager" after initialization. +- (void)instantiateEagerComponents; + +/// Remove all of the cached instances stored and allow them to clean up after themselves. +- (void)removeAllCachedInstances; + +/// Register a class to provide components for the interoperability system. The class should conform +/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects. ++ (void)registerAsComponentRegistrant:(Class)klass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 0000000..6f2aca7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h new file mode 100644 index 0000000..0d1a36f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 0000000..76c0c05 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 0000000..46e9b7e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h new file mode 100644 index 0000000..ac5ef2c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */ +@interface FIRDiagnosticsData : NSObject + +/** Inserts values into the diagnosticObjects dictionary if the value isn't nil. + * + * @param value The value to insert if it's not nil. + * @param key The key to associate it with. + */ +- (void)insertValue:(nullable id)value forKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 0000000..f77b3d0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 0000000..19e4732 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 0000000..bfff73e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 0000000..af9d968 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 0000000..548e389 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 0000000..0660a3c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,114 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h new file mode 100644 index 0000000..e0dd6d6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h @@ -0,0 +1,127 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** A block that takes a BOOL and has no return value. */ +typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback); + +/** + * The entry point of Firebase SDKs. + * + * Initialize and configure FIRApp using +[FIRApp configure] + * or other customized ways as shown below. + * + * The logging system has two modes: default mode and debug mode. In default mode, only logs with + * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent + * to device. The log levels that Firebase uses are consistent with the ASL log levels. + * + * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this + * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled, + * further executions of the application will also be in debug mode. In order to return to default + * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled. + * + * It is also possible to change the default logging level in code by calling setLoggerLevel: on + * the FIRConfiguration interface. + */ +NS_SWIFT_NAME(FirebaseApp) +@interface FIRApp : NSObject + +/** + * Configures a default Firebase app. Raises an exception if any configuration step fails. The + * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched + * and before using Firebase services. This method is thread safe and contains synchronous file I/O + * (reading GoogleService-Info.plist from disk). + */ ++ (void)configure; + +/** + * Configures the default Firebase app with the provided options. The default app is named + * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread + * safe. + * + * @param options The Firebase application options used to configure the service. + */ ++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:)); + +/** + * Configures a Firebase app with the given name and options. Raises an exception if any + * configuration step fails. This method is thread safe. + * + * @param name The application's name given by the developer. The name should should only contain + Letters, Numbers and Underscore. + * @param options The Firebase application options used to configure the services. + */ +// clang-format off ++ (void)configureWithName:(NSString *)name + options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:)); +// clang-format on + +/** + * Returns the default app, or nil if the default app does not exist. + */ ++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app()); + +/** + * Returns a previously created FIRApp instance with the given name, or nil if no such app exists. + * This method is thread safe. + */ ++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:)); + +/** + * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This + * method is thread safe. + */ +@property(class, readonly, nullable) NSDictionary *allApps; + +/** + * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for + * future use. This method is thread safe. + */ +- (void)deleteApp:(FIRAppVoidBoolCallback)completion; + +/** + * FIRApp instances should not be initialized directly. Call +[FIRApp configure], + * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Gets the name of this app. + */ +@property(nonatomic, copy, readonly) NSString *name; + +/** + * Gets a copy of the options for this app. These are non-modifiable. + */ +@property(nonatomic, copy, readonly) FIROptions *options; + +/** + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value + * is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled) + BOOL dataCollectionDefaultEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h new file mode 100644 index 0000000..8de3b07 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This interface provides global level properties that the developer can tweak. + */ +NS_SWIFT_NAME(FirebaseConfiguration) +@interface FIRConfiguration : NSObject + +/** Returns the shared configuration object. */ +@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared); + +/** + * Sets the logging level for internal Firebase logging. Firebase will only log messages + * that are logged at or below loggerLevel. The messages are logged both to the Xcode + * console and to the device's log. Note that if an app is running from AppStore, it will + * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose) + * setting. + * + * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice. + */ +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h new file mode 100644 index 0000000..dca3aa0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note that importing GULLoggerLevel.h will lead to a non-modular header +// import error. + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, FIRLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + FIRLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + FIRLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + FIRLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + FIRLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + FIRLoggerLevelDebug = 7, + /** Minimum log level. */ + FIRLoggerLevelMin = FIRLoggerLevelError, + /** Maximum log level. */ + FIRLoggerLevelMax = FIRLoggerLevelDebug +} NS_SWIFT_NAME(FirebaseLoggerLevel); diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h new file mode 100644 index 0000000..67fbe5b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class provides constant fields of Google APIs. + */ +NS_SWIFT_NAME(FirebaseOptions) +@interface FIROptions : NSObject + +/** + * Returns the default options. The first time this is called it synchronously reads + * GoogleService-Info.plist from disk. + */ ++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions()); + +/** + * An iOS API key used for authenticating requests from your app, e.g. + * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers. + */ +@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey); + +/** + * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set + * manually or in a plist. + */ +@property(nonatomic, copy) NSString *bundleID; + +/** + * The OAuth2 client ID for iOS application used to authenticate Google users, for example + * @"12345.apps.googleusercontent.com", used for signing in with Google. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** + * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics. + */ +@property(nonatomic, copy, nullable) NSString *trackingID; + +/** + * The Project Number from the Google Developer's console, for example @"012345678901", used to + * configure Google Cloud Messaging. + */ +@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID); + +/** + * The Project ID from the Firebase console, for example @"abc-xyz-123". + */ +@property(nonatomic, copy, nullable) NSString *projectID; + +/** + * The Android client ID used in Google AppInvite when an iOS app has its Android version, for + * example @"12345.apps.googleusercontent.com". + */ +@property(nonatomic, copy, nullable) NSString *androidClientID; + +/** + * The Google App ID that is used to uniquely identify an instance of an app. + */ +@property(nonatomic, copy) NSString *googleAppID; + +/** + * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com". + */ +@property(nonatomic, copy, nullable) NSString *databaseURL; + +/** + * The URL scheme used to set up Durable Deep Link service. + */ +@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme; + +/** + * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com". + */ +@property(nonatomic, copy, nullable) NSString *storageBucket; + +/** + * The App Group identifier to share data between the application and the application extensions. + * The App Group must be configured in the application and on the Apple Developer Portal. Default + * value `nil`. + */ +@property(nonatomic, copy, nullable) NSString *appGroupID; + +/** + * Initializes a customized instance of FIROptions from the file at the given plist file path. This + * will read the file synchronously from disk. + * For example, + * NSString *filePath = + * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + * Returns nil if the plist file does not exist or is invalid. + */ +- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath; + +/** + * Initializes a customized instance of FIROptions with required fields. Use the mutable properties + * to modify fields for configuring specific services. + */ +// clang-format off +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + GCMSenderID:(NSString *)GCMSenderID + NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)); +// clang-format on + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h new file mode 100644 index 0000000..95119ae --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" diff --git a/PediatricPancreas/Pods/FirebaseCore/LICENSE b/PediatricPancreas/Pods/FirebaseCore/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseCore/README.md b/PediatricPancreas/Pods/FirebaseCore/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCore/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m new file mode 100644 index 0000000..bb0326b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m @@ -0,0 +1,641 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#include + +#import +#import +#import +#import + +#import +#import +#import + +#import +#import + +#import +#import +#import + +#import "FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h" + +/** The logger service string to use when printing to the console. */ +static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]"; + +#ifdef FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = YES; +#else // FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = NO; +#endif // FIREBASE_BUILD_ZIP_FILE + +#ifdef FIREBASE_BUILD_CARTHAGE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE +#elif FIREBASE_BUILD_ZIP_FILE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE +#else +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS +#endif + +static NSString *const kFIRServiceMLVisionOnDeviceAutoML = @"MLVisionOnDeviceAutoML"; +static NSString *const kFIRServiceMLVisionOnDeviceFace = @"MLVisionOnDeviceFace"; +static NSString *const kFIRServiceMLVisionOnDeviceBarcode = @"MLVisionOnDeviceBarcode"; +static NSString *const kFIRServiceMLVisionOnDeviceText = @"MLVisionOnDeviceText"; +static NSString *const kFIRServiceMLVisionOnDeviceLabel = @"MLVisionOnDeviceLabel"; +static NSString *const kFIRServiceMLVisionOnDeviceObjectDetection = + @"MLVisionOnDeviceObjectDetection"; +static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter"; + +static NSString *const kFIRServiceAdMob = @"AdMob"; +static NSString *const kFIRServiceAuth = @"Auth"; +static NSString *const kFIRServiceAuthUI = @"AuthUI"; +static NSString *const kFIRServiceCrash = @"Crash"; +static NSString *const kFIRServiceDatabase = @"Database"; +static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks"; +static NSString *const kFIRServiceFirestore = @"Firestore"; +static NSString *const kFIRServiceFunctions = @"Functions"; +static NSString *const kFIRServiceIAM = @"InAppMessaging"; +static NSString *const kFIRServiceInstanceID = @"InstanceID"; +static NSString *const kFIRServiceInvites = @"Invites"; +static NSString *const kFIRServiceMessaging = @"Messaging"; +static NSString *const kFIRServiceMeasurement = @"Measurement"; +static NSString *const kFIRServicePerformance = @"Performance"; +static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig"; +static NSString *const kFIRServiceStorage = @"Storage"; +static NSString *const kGGLServiceAnalytics = @"Analytics"; +static NSString *const kGGLServiceSignIn = @"SignIn"; +static NSString *const kFIRAppDiagnosticsConfigurationTypeKey = + @"FIRAppDiagnosticsConfigurationTypeKey"; +static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey"; +static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey"; +static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey"; +static NSString *const kFIRCoreDiagnosticsHeartbeatTag = @"FIRCoreDiagnostics"; + +/** + * The file name to the recent heartbeat date. + */ +NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE"; + +/** + * @note This should implement the GDTCOREventDataObject protocol, but can't because of + * weak-linking. + */ +@interface FIRCoreDiagnosticsLog : NSObject + +/** The config that will be converted to proto bytes. */ +@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config; + +@end + +@implementation FIRCoreDiagnosticsLog + +- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config { + self = [super init]; + if (self) { + _config = config; + } + return self; +} + +// Provided and required by the GDTCOREventDataObject protocol. +- (NSData *)transportBytes { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + CFDataSetLength(dataRef, ostream.bytes_written); + + return CFBridgingRelease(dataRef); +} + +- (void)dealloc { + pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config); +} + +@end + +NS_ASSUME_NONNULL_BEGIN + +/** This class produces a protobuf containing diagnostics and usage data to be logged. */ +@interface FIRCoreDiagnostics : NSObject + +/** The queue on which all diagnostics collection will occur. */ +@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue; + +/** The transport object used to send data. */ +@property(nonatomic, readonly) GDTCORTransport *transport; + +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) GULHeartbeatDateStorage *heartbeatDateStorage; + +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRCoreDiagnostics + ++ (instancetype)sharedInstance { + static FIRCoreDiagnostics *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRCoreDiagnostics alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"137" + transformers:nil + target:kGDTCORTargetFLL]; + + GULHeartbeatDateStorage *dateStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kFIRCoreDiagnosticsHeartbeatDateFileName]; + + return [self initWithTransport:transport heartbeatDateStorage:dateStorage]; +} + +/** Initializer for unit tests. + * + * @param transport A `GDTCORTransport` instance which that be used to send event. + * @param heartbeatDateStorage An instanse of date storage to track heartbeat sending. + * @return Returns the initialized `FIRCoreDiagnostics` instance. + */ +- (instancetype)initWithTransport:(GDTCORTransport *)transport + heartbeatDateStorage:(GULHeartbeatDateStorage *)heartbeatDateStorage { + self = [super init]; + if (self) { + _diagnosticsQueue = + dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL); + _transport = transport; + _heartbeatDateStorage = heartbeatDateStorage; + } + return self; +} + +#pragma mark - Metadata helpers + +/** Returns the model of iOS device. Sample platform strings are @"iPhone7,1" for iPhone 6 Plus, + * @"iPhone7,2" for iPhone 6, etc. Refer to the Hardware strings at + * https://en.wikipedia.org/wiki/List_of_iOS_devices + * + * @return The device model as an NSString. + */ ++ (NSString *)deviceModel { + static NSString *deviceModel = nil; + if (deviceModel == nil) { + struct utsname systemInfo; + uname(&systemInfo); + deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + } + return deviceModel; +} + +#pragma mark - nanopb helper functions + +/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param string The string to encode as pb_bytes. + */ +pb_bytes_array_t *FIREncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return FIREncodeData(stringBytes); +} + +/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param data The data to copy into the new bytes array. + */ +pb_bytes_array_t *FIREncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +/** Maps a service string to the representative nanopb enum. + * + * @param serviceString The SDK service string to convert. + * @return The representative nanopb enum. + */ +logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum( + NSString *serviceString) { + static NSDictionary *serviceStringToTypeEnum; + if (serviceStringToTypeEnum == nil) { + serviceStringToTypeEnum = @{ + kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB), + kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING), + kFIRServiceMeasurement : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT), + kFIRServiceRemoteConfig : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG), + kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE), + kFIRServiceDynamicLinks : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS), + kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH), + kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI), + kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE), + kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS), + kFIRServicePerformance : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE), + kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE), + kFIRServiceMLVisionOnDeviceAutoML : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML), + kFIRServiceMLVisionOnDeviceFace : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE), + kFIRServiceMLVisionOnDeviceBarcode : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE), + kFIRServiceMLVisionOnDeviceText : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT), + kFIRServiceMLVisionOnDeviceLabel : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL), + kFIRServiceMLVisionOnDeviceObjectDetection : @( + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION), + kFIRServiceMLModelInterpreter : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER), + kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS), + kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN), + kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING), + }; + } + if (serviceStringToTypeEnum[serviceString] != nil) { + return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue; + } + return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE; +} + +#pragma mark - Proto population functions + +/** Populates the given proto with data related to an SDK logDiagnostics call from the + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey]; + if (configurationType != nil) { + switch (configurationType.integerValue) { + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE; + config->has_configuration_type = 1; + break; + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK; + config->has_configuration_type = 1; + break; + default: + break; + } + } + + NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey]; + if (sdkName) { + config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName); + config->has_sdk_name = 1; + } + + NSString *version = diagnosticObjects[kFIRCDSdkVersionKey]; + if (version) { + config->sdk_version = FIREncodeString(version); + } +} + +/** Populates the given proto with data from the calling FIRApp using the given + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE; + config->has_pod_name = 1; + + if (!diagnosticObjects[kFIRCDllAppsCountKey]) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"App count is a required value in the data dict."); + } + config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue]; + config->has_app_count = 1; + + NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey]; + if (googleAppID.length) { + config->app_id = FIREncodeString(googleAppID); + } + + NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey]; + if (bundleID.length) { + config->bundle_id = FIREncodeString(bundleID); + } + + NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey]; + if (firebaseUserAgent.length) { + config->platform_info = FIREncodeString(firebaseUserAgent); + } + + NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey]; + if (usingOptionsFromDefaultPlist != nil) { + config->use_default_app = [usingOptionsFromDefaultPlist boolValue]; + config->has_use_default_app = 1; + } + + NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey]; + if (libraryVersionID) { + config->icore_version = FIREncodeString(libraryVersionID); + } + + NSString *deviceModel = [FIRCoreDiagnostics deviceModel]; + if (deviceModel.length) { + config->device_model = FIREncodeString(deviceModel); + } + + NSString *osVersion = [GULAppEnvironmentUtil systemVersion]; + if (osVersion.length) { + config->os_version = FIREncodeString(osVersion); + } + + config->using_zip_file = kUsingZipFile; + config->has_using_zip_file = 1; + config->deployment_type = kDeploymentType; + config->has_deployment_type = 1; + config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore]; + config->has_deployed_in_app_store = 1; +} + +/** Populates the given proto with installed services data. + * + * @param config The proto to populate + */ +void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSMutableArray *sdkServiceInstalledArray = [NSMutableArray array]; + + // AdMob + if (NSClassFromString(@"GADBannerView") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))]; + } + // CloudMessaging + if (NSClassFromString(@"FIRMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))]; + } + // RemoteConfig + if (NSClassFromString(@"FIRRemoteConfig") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))]; + } + // Measurement/Analtyics + if (NSClassFromString(@"FIRAnalytics") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))]; + } + // ML Vision On Device AutoML. + if (NSClassFromString(@"FIRVisionOnDeviceAutoMLImageLabelerOptions") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceAutoML))]; + } + // ML Vision On Device Face. + if (NSClassFromString(@"FIRVisionFaceDetector") != nil && + NSClassFromString(@"GMVFaceDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceFace))]; + } + // ML Vision On Device Barcode. + if (NSClassFromString(@"FIRVisionBarcodeDetector") != nil && + NSClassFromString(@"GMVBarcodeDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceBarcode))]; + } + // ML Vision On Device Text. + if (NSClassFromString(@"FIRVisionTextDetector") != nil && + NSClassFromString(@"GMVTextDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceText))]; + } + // ML Vision On Device Image Label. + if (NSClassFromString(@"FIRVisionLabelDetector") != nil && + NSClassFromString(@"GMVLabelDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceLabel))]; + } + // ML Vision On Device Object. + if (NSClassFromString(@"FIRVisionObjectDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceObjectDetection))]; + } + // ML Model Interpreter + if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))]; + } + // Database + if (NSClassFromString(@"FIRDatabase") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))]; + } + // DynamicDeepLink + if (NSClassFromString(@"FIRDynamicLinks") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))]; + } + // Auth + if (NSClassFromString(@"FIRAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))]; + } + // AuthUI + if (NSClassFromString(@"FUIAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))]; + } + // Firestore + if (NSClassFromString(@"FIRFirestore") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))]; + } + // Functions + if (NSClassFromString(@"FIRFunctions") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))]; + } + // Performance + if (NSClassFromString(@"FIRPerformance") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))]; + } + // Storage + if (NSClassFromString(@"FIRStorage") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))]; + } + // SignIn via Google pod + if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))]; + } + // Analytics via Google pod + if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))]; + } + + // In-App Messaging + if (NSClassFromString(@"FIRInAppMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))]; + } + + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled = + malloc(sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType) * + sdkServiceInstalledArray.count); + for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) { + NSNumber *typeEnum = sdkServiceInstalledArray[i]; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType = + (int32_t)typeEnum.integerValue; + servicesInstalled[i] = serviceType; + } + + config->sdk_service_installed = servicesInstalled; + config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count; +} + +/** Populates the proto with the number of linked frameworks. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithNumberOfLinkedFrameworks( + logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + int numFrameworks = -1; // Subtract the app binary itself. + unsigned int numImages; + const char **imageNames = objc_copyImageNames(&numImages); + for (unsigned int i = 0; i < numImages; i++) { + NSString *imageName = [NSString stringWithUTF8String:imageNames[i]]; + if ([imageName rangeOfString:@"System/Library"].length != 0 // Apple .frameworks + || [imageName rangeOfString:@"Developer/Library"].length != 0 // Xcode debug .frameworks + || [imageName rangeOfString:@"usr/lib"].length != 0) { // Public .dylibs + continue; + } + numFrameworks++; + } + free(imageNames); + config->dynamic_framework_count = numFrameworks; + config->has_dynamic_framework_count = 1; +} + +/** Populates the proto with Info.plist values. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + + NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @""; + NSString *sdkVersion = info[@"DTSDKBuild"] ?: @""; + NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion]; + config->apple_framework_version = FIREncodeString(combinedVersions); + + NSString *minVersion = info[@"MinimumOSVersion"]; + if (minVersion) { + config->min_supported_ios_version = FIREncodeString(minVersion); + } + + // Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and + // report it. It's enabled by default. + NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"]; + BOOL appDelegateSwizzled = YES; + if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) { + appDelegateSwizzled = [appDelegateSwizzledNum boolValue]; + } + config->swizzling_enabled = appDelegateSwizzled; + config->has_swizzling_enabled = 1; +} + +#pragma mark - FIRCoreDiagnosticsInterop + ++ (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance]; + [diagnostics sendDiagnosticsData:diagnosticsData]; +} + +- (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + dispatch_async(self.diagnosticsQueue, ^{ + NSDictionary *diagnosticObjects = diagnosticsData.diagnosticObjects; + NSNumber *isDataCollectionDefaultEnabled = + diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]; + if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) { + return; + } + + // Create the proto. + logs_proto_mobilesdk_ios_ICoreConfiguration icore_config = + logs_proto_mobilesdk_ios_ICoreConfiguration_init_default; + + icore_config.using_gdt = 1; + icore_config.has_using_gdt = 1; + + // Populate the proto with information. + FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects); + FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects); + FIRPopulateProtoWithInstalledServices(&icore_config); + FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config); + FIRPopulateProtoWithInfoPlistValues(&icore_config); + [self setHeartbeatFlagIfNeededToConfig:&icore_config]; + + // This log object is capable of converting the proto to bytes. + FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config]; + + // Send the log as a telemetry event. + GDTCOREvent *event = [self.transport eventForTransport]; + event.dataObject = (id)log; + [self.transport sendTelemetryEvent:event]; + }); +} + +#pragma mark - Heartbeat + +- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config { + // Check if need to send a heartbeat. + NSDate *currentDate = [NSDate date]; + NSDate *lastCheckin = + [self.heartbeatDateStorage heartbeatDateForTag:kFIRCoreDiagnosticsHeartbeatTag]; + if (lastCheckin) { + // Ensure the previous checkin was on a different date in the past. + if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) { + return; + } + } + + // Update heartbeat sent date. + [self.heartbeatDateStorage setHearbeatDate:currentDate forTag:kFIRCoreDiagnosticsHeartbeatTag]; + // Set the flag. + config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE; + config->has_sdk_name = 1; +} + +- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 { + return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] || + [date1 compare:date2] == NSOrderedAscending; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c new file mode 100644 index 0000000..4b2ac2f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 */ + +#include "firebasecore.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0), + PB_FIELD( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, configuration_type, 0), + PB_FIELD( 9, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0), + PB_FIELD( 10, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0), + PB_FIELD( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, app_id, 0), + PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, bundle_id, 0), + PB_FIELD( 18, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0), + PB_FIELD( 19, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0), + PB_FIELD( 20, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0), + PB_FIELD( 21, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0), + PB_FIELD( 22, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0), + PB_FIELD( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, os_version, 0), + PB_FIELD( 25, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0), + PB_FIELD( 26, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0), + PB_FIELD( 27, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0), + PB_FIELD( 28, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0), + PB_FIELD( 29, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0), + PB_FIELD( 30, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0), + PB_FIELD( 31, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0), + PB_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, platform_info, 0), + PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, swizzling_enabled, 0), + PB_LAST_FIELD +}; + + + + + + + +/* @@protoc_insertion_point(eof) */ diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h new file mode 100644 index 0000000..3e4c195 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h @@ -0,0 +1,193 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 */ + +#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType { + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3 +} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName { + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType { + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4 +} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1)) + +/* Struct definitions */ +typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration { + bool has_configuration_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type; + pb_size_t sdk_service_installed_count; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed; + pb_bytes_array_t *device_model; + pb_bytes_array_t *app_id; + pb_bytes_array_t *bundle_id; + bool has_pod_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name; + pb_bytes_array_t *icore_version; + pb_bytes_array_t *sdk_version; + bool has_sdk_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name; + bool has_app_count; + int32_t app_count; + pb_bytes_array_t *os_version; + pb_bytes_array_t *min_supported_ios_version; + bool has_use_default_app; + bool use_default_app; + bool has_deployed_in_app_store; + bool deployed_in_app_store; + bool has_dynamic_framework_count; + int32_t dynamic_framework_count; + pb_bytes_array_t *apple_framework_version; + bool has_using_zip_file; + bool using_zip_file; + bool has_deployment_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type; + pb_bytes_array_t *platform_info; + bool has_swizzling_enabled; + bool swizzling_enabled; + bool has_using_gdt; + bool using_gdt; +/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */ +} logs_proto_mobilesdk_ios_ICoreConfiguration; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22]; + +/* Maximum encoded size of messages (where known) */ +/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define FIREBASECORE_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnostics/LICENSE b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnostics/README.md b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnostics/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h new file mode 100644 index 0000000..69c4072 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkNameKey @"FIRCDSdkNameKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey" + +/** If present, is an NSString. */ +#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey" + +/** If present, is an NSString. */ +#define kFIRCDBundleIDKey @"FIRCDBundleID" + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey" + +/** If present, is an NSString. */ +#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey" + +/** If present, is an NSString. */ +#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey" + +/** Defines the interface of a data object needed to log diagnostics data. */ +@protocol FIRCoreDiagnosticsData + +@required + +/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */ +@property(nonatomic) NSDictionary *diagnosticObjects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 0000000..2b0eb71 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/LICENSE b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/README.md b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseCoreDiagnosticsInterop/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m new file mode 100644 index 0000000..c1d48ec --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m @@ -0,0 +1,105 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FChildrenNode.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseReference.h" +#import "FTransformedEnumerator.h" +#import "FValidation.h" + +@interface FIRDataSnapshot () +@property(nonatomic, strong) FIRDatabaseReference *ref; +@end + +@implementation FIRDataSnapshot + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node { + self = [super init]; + if (self != nil) { + self->_ref = ref; + self->_node = node; + } + return self; +} + +- (id)value { + return [self.node.node val]; +} + +- (id)valueInExportFormat { + return [self.node.node valForExport:YES]; +} + +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString { + [FValidation validateFrom:@"child:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + FIRDatabaseReference *childRef = [self.ref child:childPathString]; + + id childNode = [self.node.node getChild:childPath]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:childNode]]; +} + +- (BOOL)hasChild:(NSString *)childPathString { + [FValidation validateFrom:@"hasChild:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + return ![[self.node.node getChild:childPath] isEmpty]; +} + +- (id)priority { + id priority = [self.node.node getPriority]; + return priority.val; +} + +- (BOOL)hasChildren { + if ([self.node.node isLeafNode]) { + return false; + } else { + return ![self.node.node isEmpty]; + } +} + +- (BOOL)exists { + return ![self.node.node isEmpty]; +} + +- (NSString *)key { + return [self.ref key]; +} + +- (NSUInteger)childrenCount { + return [self.node.node numChildren]; +} + +- (NSEnumerator *)children { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.node.childEnumerator + andTransform:^id(FNamedNode *node) { + FIRDatabaseReference *childRef = [self.ref child:node.name]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:node.node]]; + }]; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"Snap (%@) %@", self.key, self.node.node]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m new file mode 100644 index 0000000..8957336 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m @@ -0,0 +1,234 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import +#import +#import +#import + +#import "FIRDatabase.h" +#import "FIRDatabaseComponent.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoInfo.h" +#import "FValidation.h" + +@implementation FIRDatabase + +// The STR and STR_EXPAND macro allow a numeric version passed to he compiler +// driver with a -D to be treated as a string instead of an invalid floating +// point value. +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); + ++ (FIRDatabase *)database { + if (![FIRApp isDefaultAppConfigured]) { + [NSException raise:@"FIRAppNotConfigured" + format:@"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp " + @"configure]` (`FirebaseApp.configure()` in Swift) " + @"before using " + @"Firebase Database."]; + } + return [FIRDatabase databaseForApp:[FIRApp defaultApp]]; +} + ++ (FIRDatabase *)databaseWithURL:(NSString *)url { + FIRApp *app = [FIRApp defaultApp]; + if (app == nil) { + [NSException + raise:@"FIRAppNotConfigured" + format: + @"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp configure]` (`FirebaseApp.configure()` in " + @"Swift) before using Firebase Database."]; + } + return [FIRDatabase databaseForApp:app URL:url]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + return [FIRDatabase databaseForApp:app URL:app.options.databaseURL]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + @"Specify DatabaseURL within FIRApp or from your " + @"databaseForApp:URL: call."]; + } + id provider = + FIR_COMPONENT(FIRDatabaseProvider, app.container); + return [provider databaseForApp:app URL:url]; +} + ++ (NSString *)buildVersion { + // TODO: Restore git hash when build moves back to git + return [NSString stringWithFormat:@"%s_%s", FIREBASE_SEMVER, __DATE__]; +} + ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config { + FIRDatabase *db = [[FIRDatabase alloc] initWithApp:nil + repoInfo:repoInfo + config:config]; + [db ensureRepo]; + return db; +} + ++ (NSString *)sdkVersion { + return [NSString stringWithUTF8String:FIREBASE_SEMVER]; +} + ++ (void)setLoggingEnabled:(BOOL)enabled { + [FUtilities setLoggingEnabled:enabled]; + FFLog(@"I-RDB024001", @"BUILD Version: %@", [FIRDatabase buildVersion]); +} + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self != nil) { + self->_repoInfo = info; + self->_config = config; + self->_app = app; + } + return self; +} + +- (FIRDatabaseReference *)reference { + [self ensureRepo]; + + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:[FPath empty]]; +} + +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path { + [self ensureRepo]; + + [FValidation validateFrom:@"referenceWithPath" validRootPathString:path]; + FPath *childPath = [[FPath alloc] initWith:path]; + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:childPath]; +} + +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl { + [self ensureRepo]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"Invalid nil url passed to referenceFromURL:"]; + } + FParsedUrl *parsedUrl = [FUtilities parseUrl:databaseUrl]; + [FValidation validateFrom:@"referenceFromURL:" validURL:parsedUrl]; + if (![parsedUrl.repoInfo.host isEqualToString:_repoInfo.host]) { + [NSException + raise:@"InvalidDatabaseURL" + format: + @"Invalid URL (%@) passed to getReference(). URL was expected " + "to match configured Database URL: %@", + databaseUrl, [self reference].URL]; + } + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parsedUrl.path]; +} + +- (void)purgeOutstandingWrites { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo purgeOutstandingWrites]; + }); +} + +- (void)goOnline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo resume]; + }); +} + +- (void)goOffline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo interrupt]; + }); +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen:@"setPersistenceEnabled"]; + self->_config.persistenceEnabled = persistenceEnabled; +} + +- (BOOL)persistenceEnabled { + return self->_config.persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen:@"setPersistenceCacheSizeBytes"]; + self->_config.persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (NSUInteger)persistenceCacheSizeBytes { + return self->_config.persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen:@"setCallbackQueue"]; + self->_config.callbackQueue = callbackQueue; +} + +- (dispatch_queue_t)callbackQueue { + return self->_config.callbackQueue; +} + +- (void)assertUnfrozen:(NSString *)methodName { + if (self.repo != nil) { + [NSException + raise:@"FIRDatabaseAlreadyInUse" + format:@"Calls to %@ must be made before any other usage of " + "FIRDatabase instance.", + methodName]; + } +} + +- (void)ensureRepo { + if (self.repo == nil) { + self.repo = [FRepoManager createRepo:self.repoInfo + config:self.config + database:self]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h new file mode 100644 index 0000000..9d8bdb2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRDatabase; + +NS_ASSUME_NONNULL_BEGIN + +/// This protocol is used in the interop registration process to register an +/// instance provider for individual FIRApps. +@protocol FIRDatabaseProvider + +/// Gets a FirebaseDatabase instance for the specified URL, using the specified +/// FirebaseApp. +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url; + +@end + +/// A concrete implementation for FIRDatabaseProvider to create Database +/// instances. +@interface FIRDatabaseComponent : NSObject + +/// The FIRApp that instances will be set up with. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable, use `databaseForApp:URL:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m new file mode 100644 index 0000000..8e44778 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m @@ -0,0 +1,173 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseComponent.h" + +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoManager.h" + +#import +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A NSMutableDictionary of FirebaseApp name and FRepoInfo to FirebaseDatabase + * instance. */ +typedef NSMutableDictionary FIRDatabaseDictionary; + +@interface FIRDatabaseComponent () +@property(nonatomic) FIRDatabaseDictionary *instances; +/// Internal intializer. +- (instancetype)initWithApp:(FIRApp *)app; +@end + +@implementation FIRDatabaseComponent + +#pragma mark - Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + self = [super init]; + if (self) { + _app = app; + _instances = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Lifecycle + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-db" + withVersion:[FIRDatabase sdkVersion]]; +} + +#pragma mark - FIRComponentRegistrant + ++ (NSArray *)componentsToRegister { + FIRDependency *authDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop) + isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + return [[FIRDatabaseComponent alloc] initWithApp:container.app]; + }; + FIRComponent *databaseProvider = + [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ authDep ] + creationBlock:creationBlock]; + return @[ databaseProvider ]; +} + +#pragma mark - Instance management. + +- (void)appWillBeDeleted:(FIRApp *)app { + NSString *appName = app.name; + if (appName == nil) { + return; + } + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + // Clean up the deleted instance in an effort to remove any resources + // still in use. Note: Any leftover instances of this exact database + // will be invalid. + for (FIRDatabase *database in [instances allValues]) { + [FRepoManager disposeRepos:database.config]; + } + [instances removeAllObjects]; + } +} + +#pragma mark - FIRDatabaseProvider Conformance + +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + "Specify DatabaseURL within FIRApp or from your " + "databaseForApp:URL: call."]; + } + + NSURL *databaseUrl = [NSURL URLWithString:url]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"The Database URL '%@' cannot be parsed. " + "Specify a valid DatabaseURL within FIRApp or from " + "your databaseForApp:URL: call.", + databaseUrl]; + } else if (![databaseUrl.path isEqualToString:@""] && + ![databaseUrl.path isEqualToString:@"/"]) { + [NSException + raise:@"InvalidDatabaseURL" + format:@"Configured Database URL '%@' is invalid. It should point " + "to the root of a Firebase Database but it includes a " + "path: %@", + databaseUrl, databaseUrl.path]; + } + + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:databaseUrl.absoluteString]; + NSString *urlIndex = + [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host, + [parsedUrl.path toString]]; + FIRDatabase *database = instances[urlIndex]; + if (!database) { + id authTokenProvider = [FAuthTokenProvider + authTokenProviderWithAuth:FIR_COMPONENT(FIRAuthInterop, + app.container)]; + + // If this is the default app, don't set the session persistence key + // so that we use our default ("default") instead of the FIRApp + // default ("[DEFAULT]") so that we preserve the default location + // used by the legacy Firebase SDK. + NSString *sessionIdentifier = @"default"; + if (![FIRApp isDefaultAppConfigured] || + app != [FIRApp defaultApp]) { + sessionIdentifier = app.name; + } + + FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc] + initWithSessionIdentifier:sessionIdentifier + authTokenProvider:authTokenProvider]; + database = [[FIRDatabase alloc] initWithApp:app + repoInfo:parsedUrl.repoInfo + config:config]; + instances[urlIndex] = database; + } + + return database; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h new file mode 100644 index 0000000..85399f9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FAuthTokenProvider; + +NS_ASSUME_NONNULL_BEGIN + +/** + * TODO: Merge FIRDatabaseConfig into FIRDatabase. + */ +@interface FIRDatabaseConfig : NSObject + +- (id)initWithSessionIdentifier:(NSString *)identifier + authTokenProvider:(id)authTokenProvider; + +/** + * By default the Firebase Database client will keep data in memory while your + * application is running, but not when it is restarted. By setting this value + * to YES, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first FIRDatabaseReference and only needs to be called once per + * application. + * + * If your app uses Firebase Authentication, the client will automatically + * persist the user's authentication token across restarts, even without + * persistence enabled. But if the auth token expired while offline and you've + * enabled persistence, the client will pause write operations until you + * successfully re-authenticate (or explicitly unauthenticate) to prevent your + * writes from being sent unauthenticated and failing due to security rules. + */ +@property(nonatomic) BOOL persistenceEnabled; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m new file mode 100644 index 0000000..9e9f8b5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m @@ -0,0 +1,92 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRNoopAuthTokenProvider.h" + +@interface FIRDatabaseConfig (Private) + +@property(nonatomic, strong, readwrite) NSString *sessionIdentifier; + +@end + +@implementation FIRDatabaseConfig + +- (id)init { + [NSException raise:NSInvalidArgumentException + format:@"Can't create config objects!"]; + return nil; +} + +- (id)initWithSessionIdentifier:(NSString *)identifier + authTokenProvider:(id)authTokenProvider { + self = [super init]; + if (self != nil) { + self->_sessionIdentifier = identifier; + self->_callbackQueue = dispatch_get_main_queue(); + self->_persistenceCacheSizeBytes = + 10 * 1024 * 1024; // Default cache size is 10MB + self->_authTokenProvider = authTokenProvider; + } + return self; +} + +- (void)assertUnfrozen { + if (self.isFrozen) { + [NSException raise:NSGenericException + format:@"Can't modify config objects after they are in use " + @"for FIRDatabaseReferences."]; + } +} + +- (void)setAuthTokenProvider:(id)authTokenProvider { + [self assertUnfrozen]; + self->_authTokenProvider = authTokenProvider; +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen]; + self->_persistenceEnabled = persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen]; + // Can't be less than 1MB + if (persistenceCacheSizeBytes < 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"The minimum cache size must be at least 1MB"]; + } + if (persistenceCacheSizeBytes > 100 * 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"Firebase Database currently doesn't support a " + @"cache size larger than 100MB"]; + } + self->_persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen]; + self->_callbackQueue = callbackQueue; +} + +- (void)freeze { + self->_isFrozen = YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m new file mode 100644 index 0000000..cd62979 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m @@ -0,0 +1,677 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FChildEventRegistration.h" +#import "FConstants.h" +#import "FIRDatabaseQuery_Private.h" +#import "FKeyIndex.h" +#import "FLeafNode.h" +#import "FPath.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FSnapshotUtilities.h" +#import "FValidation.h" +#import "FValueEventRegistration.h" +#import "FValueIndex.h" + +@implementation FIRDatabaseQuery + +@synthesize repo; +@synthesize path; +@synthesize queryParams; + +#define INVALID_QUERY_PARAM_ERROR @"InvalidQueryParameter" + ++ (dispatch_queue_t)sharedQueue { + // We use this shared queue across all of the FQueries so things happen FIFO + // (as opposed to dispatch_get_global_queue(0, 0) which is concurrent) + static dispatch_once_t pred; + static dispatch_queue_t sharedDispatchQueue; + + dispatch_once(&pred, ^{ + sharedDispatchQueue = dispatch_queue_create("FirebaseWorker", NULL); + }); + + return sharedDispatchQueue; +} + +- (id)initWithRepo:(FRepo *)theRepo path:(FPath *)thePath { + return [self initWithRepo:theRepo + path:thePath + params:nil + orderByCalled:NO + priorityMethodCalled:NO]; +} + +- (id)initWithRepo:(FRepo *)theRepo + path:(FPath *)thePath + params:(FQueryParams *)theParams + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled { + self = [super init]; + if (self) { + self.repo = theRepo; + self.path = thePath; + if (!theParams) { + theParams = [FQueryParams defaultInstance]; + } + if (![theParams isValid]) { + @throw [[NSException alloc] + initWithName:@"InvalidArgumentError" + reason:@"Queries are limited to two constraints" + userInfo:nil]; + } + self.queryParams = theParams; + self.orderByCalled = orderByCalled; + self.priorityMethodCalled = priorityMethodCalled; + } + return self; +} + +- (FQuerySpec *)querySpec { + return [[FQuerySpec alloc] initWithPath:self.path params:self.queryParams]; +} + +- (void)validateQueryEndpointsForParams:(FQueryParams *)params { + if ([params.index isEqual:[FKeyIndex keyIndex]]) { + if ([params hasStart]) { + if (params.indexStartKey != [FUtilities minName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryStartingAtValue:childKey: " + @"or queryEqualTo:andChildKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexStartValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryStartingAtValue: with other types " + @"than string in combination with queryOrderedByKey"]; + } + } + if ([params hasEnd]) { + if (params.indexEndKey != [FUtilities maxName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryEndingAtValue:childKey: or " + @"queryEqualToValue:childKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexEndValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryEndingAtValue: with other types than " + @"string in combination with queryOrderedByKey"]; + } + } + } else if ([params.index isEqual:[FPriorityIndex priorityIndex]]) { + if (([params hasStart] && + ![FValidation validatePriorityValue:params.indexStartValue.val]) || + ([params hasEnd] && + ![FValidation validatePriorityValue:params.indexEndValue.val])) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format:@"When using queryOrderedByPriority, values provided to " + @"queryStartingAtValue:, queryEndingAtValue:, or " + @"queryEqualToValue: must be valid priorities."]; + } + } +} + +- (void)validateEqualToCall { + if ([self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryStartingAtValue:"]; + } + if ([self.queryParams hasEnd]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryEndingAtValue:"]; + } +} + +- (void)validateNoPreviousOrderByCalled { + if (self.orderByCalled) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Cannot use multiple queryOrderedBy calls!"]; + } +} + +- (void)validateIndexValueType:(id)type fromMethod:(NSString *)method { + if (type != nil && ![type isKindOfClass:[NSNumber class]] && + ![type isKindOfClass:[NSString class]] && + ![type isKindOfClass:[NSNull class]]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"You can only pass nil, NSString or NSNumber to %@", + method]; + } +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [self queryStartingAtInternal:startValue + childKey:nil + from:@"queryStartingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryStartingAtValue: instead of " + @"queryStartingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + return [self queryStartingAtInternal:startValue + childKey:childKey + from:@"queryStartingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtInternal:(id)startValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:startValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasStart]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryStartingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id startNode = [FSnapshotUtilities nodeFrom:startValue]; + FQueryParams *params = [self.queryParams startAt:startNode + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [self queryEndingAtInternal:endValue + childKey:nil + from:@"queryEndingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEndingAtValue: instead of " + @"queryEndingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + + return [self queryEndingAtInternal:endValue + childKey:childKey + from:@"queryEndingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtInternal:(id)endValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:endValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryEndingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id endNode = [FSnapshotUtilities nodeFrom:endValue]; + FQueryParams *params = [self.queryParams endAt:endNode childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [self queryEqualToInternal:value + childKey:nil + from:@"queryEqualToValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEqualToValue: instead of " + @"queryEqualTo:childKey: when using queryOrderedByKey:" + userInfo:nil]; + } + return [self queryEqualToInternal:value + childKey:childKey + from:@"queryEqualToValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToInternal:(id)value + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:value fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd] || [self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't call %@ after queryStartingAtValue, queryEndingAtValue " + @"or queryEqualToValue was previously called", + methodName]; + } + id node = [FSnapshotUtilities nodeFrom:value]; + FQueryParams *params = [[self.queryParams startAt:node + childKey:childKey] endAt:node + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (void)validateLimitRange:(NSUInteger)limit { + // No need to check for negative ranges, since limit is unsigned + if (limit == 0) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit can't be zero"]; + } + if (limit >= 1ul << 31) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit must be less than 2,147,483,648"]; + } +} + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToFirst: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToFirst:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToLast: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToLast:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)indexPathString { + if ([indexPathString isEqualToString:@"$key"] || + [indexPathString isEqualToString:@".key"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByKey: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$priority"] || + [indexPathString isEqualToString:@".priority"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByPriority: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$value"] || + [indexPathString isEqualToString:@".value"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByValue: instead.", + indexPathString] + userInfo:nil]; + } + [self validateNoPreviousOrderByCalled]; + + [FValidation validateFrom:@"queryOrderedByChild:" + validPathString:indexPathString]; + FPath *indexPath = [FPath pathWithString:indexPathString]; + if (indexPath.isEmpty) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString + stringWithFormat:@"(queryOrderedByChild:) with an " + @"empty path is invalid. Use " + @"queryOrderedByValue: instead."] + userInfo:nil]; + } + id index = [[FPathIndex alloc] initWithPath:indexPath]; + + FQueryParams *params = [self.queryParams orderBy:index]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FKeyIndex keyIndex]]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByValue { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FValueIndex valueIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = + [self.queryParams orderBy:[FPriorityIndex priorityIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *))block { + [FValidation validateFrom:@"observeEventType:withBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [FValidation + validateFrom:@"observeEventType:andPreviousSiblingKeyWithBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:withBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // Handle FIRDataEventTypeValue specially because they shouldn't have + // prevName callbacks + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + [self observeValueEventWithHandle:handle + withBlock:block + cancelCallback:cancelBlock]; + return handle; + } else { + // Wrap up the userCallback so we can treat everything as a callback + // that has a prevName + fbt_void_datasnapshot userCallback = [block copy]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (userCallback != nil) { + userCallback(snapshot); + } + } + withCancelBlock:cancelBlock]; + } +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:" + @"andPreviousSiblingKeyWithBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // TODO: This gets hit by observeSingleEventOfType. Need to fix. + /* + @throw [[NSException alloc] initWithName:@"InvalidEventTypeForObserver" + reason:@"(observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock:) + Cannot use + observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock: with + FIRDataEventTypeValue. Use observeEventType:withBlock:withCancelBlock: + instead." userInfo:nil]; + */ + } + + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + NSDictionary *callbacks = + @{[NSNumber numberWithInteger:eventType] : [block copy]}; + [self observeChildEventWithHandle:handle + withCallbacks:callbacks + cancelCallback:cancelBlock]; + + return handle; +} + +// If we want to distinguish between value event listeners and child event +// listeners, like in the Java client, we can consider exporting this. If we do, +// add argument validation. Otherwise, arguments are validated in the +// public-facing portions of the API. Also, move the FIRDatabaseHandle logic. +- (void)observeValueEventWithHandle:(FIRDatabaseHandle)handle + withBlock:(fbt_void_datasnapshot)block + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:block + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +// Note: as with the above method, we may wish to expose this at some point. +- (void)observeChildEventWithHandle:(FIRDatabaseHandle)handle + withCallbacks:(NSDictionary *)callbacks + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FChildEventRegistration *registration = + [[FChildEventRegistration alloc] initWithRepo:self.repo + handle:handle + callbacks:callbacks + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + FValueEventRegistration *event = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:nil + cancelCallback:nil]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo removeEventRegistration:event forQuery:self.querySpec]; + }); +} + +- (void)removeAllObservers { + [self removeObserverWithHandle:NSNotFound]; +} + +- (void)keepSynced:(BOOL)keepSynced { + if ([self.path.getFront isEqualToString:kDotInfoPrefix]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't keep query on .info tree synced (this " + @"already is the case)."]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo keepQuery:self.querySpec synced:keepSynced]; + }); +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (block != nil) { + block(snapshot); + } + } + withCancelBlock:cancelBlock]; +} + +/** + * Attaches a listener, waits for the first event, and then removes the listener + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + __block FIRDatabaseHandle handle; + __block BOOL firstCall = YES; + + fbt_void_datasnapshot_nsstring callback = [block copy]; + fbt_void_datasnapshot_nsstring wrappedCallback = + ^(FIRDataSnapshot *snap, NSString *prevName) { + if (firstCall) { + firstCall = NO; + [self removeObserverWithHandle:handle]; + callback(snap, prevName); + } + }; + + fbt_void_nserror cancelCallback = [cancelBlock copy]; + handle = [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:wrappedCallback + withCancelBlock:^(NSError *error) { + [self removeObserverWithHandle:handle]; + + if (cancelCallback) { + cancelCallback(error); + } + }]; +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"(%@ %@)", self.path, self.queryParams.description]; +} + +- (FIRDatabaseReference *)ref { + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:self.path]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m new file mode 100644 index 0000000..5da7fae --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m @@ -0,0 +1,149 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FChildrenNode.h" +#import "FIRMutableData_Private.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FTransformedEnumerator.h" + +@interface FIRMutableData () + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder; + +@property(strong, nonatomic) FSnapshotHolder *data; +@property(strong, nonatomic) FPath *prefixPath; + +@end + +@implementation FIRMutableData + +@synthesize data; +@synthesize prefixPath; + +- (id)initWithNode:(id)node { + FSnapshotHolder *holder = [[FSnapshotHolder alloc] init]; + FPath *path = [FPath empty]; + [holder updateSnapshot:path withNewSnapshot:node]; + return [self initWithPrefixPath:path andSnapshotHolder:holder]; +} + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder { + self = [super init]; + if (self) { + self.prefixPath = path; + self.data = snapshotHolder; + } + return self; +} + +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path { + FPath *wholePath = [self.prefixPath childFromString:path]; + return [[FIRMutableData alloc] initWithPrefixPath:wholePath + andSnapshotHolder:self.data]; +} + +- (FIRMutableData *)parent { + if ([self.prefixPath isEmpty]) { + return nil; + } else { + FPath *path = [self.prefixPath parent]; + return [[FIRMutableData alloc] initWithPrefixPath:path + andSnapshotHolder:self.data]; + } +} + +- (void)setValue:(id)aValue { + id node = [FSnapshotUtilities nodeFrom:aValue + withValidationFrom:@"setValue:"]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (void)setPriority:(id)aPriority { + id node = [self.data getNode:self.prefixPath]; + id pri = [FSnapshotUtilities nodeFrom:aPriority]; + node = [node updatePriority:pri]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (id)value { + return [[self.data getNode:self.prefixPath] val]; +} + +- (id)priority { + return [[[self.data getNode:self.prefixPath] getPriority] val]; +} + +- (BOOL)hasChildren { + id node = [self.data getNode:self.prefixPath]; + return ![node isLeafNode] && ![(FChildrenNode *)node isEmpty]; +} + +- (BOOL)hasChildAtPath:(NSString *)path { + id node = [self.data getNode:self.prefixPath]; + FPath *childPath = [[FPath alloc] initWith:path]; + return ![[node getChild:childPath] isEmpty]; +} + +- (NSUInteger)childrenCount { + return [[self.data getNode:self.prefixPath] numChildren]; +} + +- (NSString *)key { + return [self.prefixPath getBack]; +} + +- (id)nodeValue { + return [self.data getNode:self.prefixPath]; +} + +- (NSEnumerator *)children { + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:self.nodeValue]; + return [[FTransformedEnumerator alloc] + initWithEnumerator:[indexedNode childEnumerator] + andTransform:^id(FNamedNode *node) { + FPath *childPath = [self.prefixPath childFromString:node.name]; + FIRMutableData *childData = + [[FIRMutableData alloc] initWithPrefixPath:childPath + andSnapshotHolder:self.data]; + return childData; + }]; +} + +- (BOOL)isEqualToData:(FIRMutableData *)other { + return self.data == other.data && + [[self.prefixPath description] + isEqualToString:[other.prefixPath description]]; +} + +- (NSString *)description { + if (self.key == nil) { + return [NSString + stringWithFormat:@"FIRMutableData (top-most transaction) %@ %@", + self.key, self.value]; + } else { + return [NSString + stringWithFormat:@"FIRMutableData (%@) %@", self.key, self.value]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m new file mode 100644 index 0000000..e5be5c5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRServerValue.h" +#import "FIRDatabaseReference.h" + +@implementation FIRServerValue + ++ (NSDictionary *)timestamp { + static NSDictionary *timestamp = nil; + if (timestamp == nil) { + timestamp = @{@".sv" : @"timestamp"}; + } + return timestamp; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m new file mode 100644 index 0000000..9fec862 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" + +@implementation FIRTransactionResult + +@synthesize update; +@synthesize isSuccess; + ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = YES; + result.update = value; + return result; +} + ++ (FIRTransactionResult *)abort { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = NO; + result.update = nil; + return result; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h new file mode 100644 index 0000000..ac23045 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIndexedNode.h" +#import "FTypedefs_Private.h" + +@interface FIRDataSnapshot () + +// in _Private for testing purposes +@property(nonatomic, strong) FIndexedNode *node; + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h new file mode 100644 index 0000000..30f19f0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseQuery () + ++ (dispatch_queue_t)sharedQueue; + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; +- (id)initWithRepo:(FRepo *)repo + path:(FPath *)path + params:(FQueryParams *)params + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled; + +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) FQueryParams *queryParams; +@property(nonatomic) BOOL orderByCalled; +@property(nonatomic) BOOL priorityMethodCalled; + +- (FQuerySpec *)querySpec; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h new file mode 100644 index 0000000..1d7e37c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseReference.h" +#import "FRepo.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseReference () + +- (id)initWithConfig:(FIRDatabaseConfig *)config; +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h new file mode 100644 index 0000000..0ff3e70 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabase.h" + +@class FRepo; +@class FRepoInfo; +@class FIRDatabaseConfig; + +@interface FIRDatabase () + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic, strong) FRepo *repo; + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config; + ++ (NSString *)buildVersion; ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h new file mode 100644 index 0000000..fded102 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FNode.h" + +@interface FIRMutableData () + +- (id)initWithNode:(id)node; +- (id)nodeValue; +- (BOOL)isEqualToData:(FIRMutableData *)other; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h new file mode 100644 index 0000000..bdf250a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FIRTransactionResult.h" + +@interface FIRTransactionResult () + +@property(nonatomic) BOOL isSuccess; +@property(nonatomic, strong) FIRMutableData *update; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h new file mode 100644 index 0000000..dac55bc --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FTYPEDEFS_PRIVATE__ +#define __FTYPEDEFS_PRIVATE__ + +#import + +typedef NS_ENUM(NSInteger, FTransactionStatus) { + FTransactionInitializing, // 0 + FTransactionRun, // 1 + FTransactionSent, // 2 + FTransactionCompleted, // 3 + FTransactionSentNeedsAbort, // 4 + FTransactionNeedsAbort // 5 +}; + +@protocol FNode; +@class FPath; +@class FIRTransactionResult; +@class FIRMutableData; +@class FIRDataSnapshot; +@class FCompoundHash; + +typedef void (^fbt_void_nserror_bool_datasnapshot)(NSError *error, + BOOL committed, + FIRDataSnapshot *snapshot); +typedef FIRTransactionResult * (^fbt_transactionresult_mutabledata)( + FIRMutableData *currentData); +typedef void (^fbt_void_path_node)(FPath *, id); +typedef void (^fbt_void_nsstring)(NSString *); +typedef BOOL (^fbt_bool_nsstring_node)(NSString *, id); +typedef void (^fbt_void_path_node_marray)(FPath *, id, NSMutableArray *); +typedef BOOL (^fbt_bool_void)(void); +typedef void (^fbt_void_nsstring_nsstring)(NSString *str1, NSString *str2); +typedef void (^fbt_void_nsstring_nserror)(NSString *str, NSError *error); +typedef BOOL (^fbt_bool_path)(FPath *str); +typedef void (^fbt_void_id)(id data); +typedef NSString * (^fbt_nsstring_void)(void); +typedef FCompoundHash * (^fbt_compoundhash_void)(void); +typedef NSArray * (^fbt_nsarray_nsstring_id)(NSString *status, id Data); +typedef NSArray * (^fbt_nsarray_nsstring)(NSString *status); + +// WWDC 2012 session 712 starting in page 83 for saving blocks in properties +// (use @property (strong) type name). + +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h new file mode 100644 index 0000000..4327a0d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h @@ -0,0 +1,195 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FConstants_h +#define Firebase_FConstants_h + +#import + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestType; +FOUNDATION_EXPORT NSString *const kFWPRequestTypeData; +FOUNDATION_EXPORT NSString *const kFWPRequestDataPayload; +FOUNDATION_EXPORT NSString *const kFWPRequestNumber; +FOUNDATION_EXPORT NSString *const kFWPRequestPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPRequestError; +FOUNDATION_EXPORT NSString *const kFWPRequestAction; +FOUNDATION_EXPORT NSString *const kFWPResponseForRNData; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatus; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusOk; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusDataStale; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionData; +FOUNDATION_EXPORT NSString *const kFWPResponseDataWarnings; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAction; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdate; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAuthRevoked; +FOUNDATION_EXPORT NSString *const kFWPASyncServerListenCancelled; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerSecurityDebug; +FOUNDATION_EXPORT NSString + *const kFWPAsyncServerDataUpdateBodyPath; // {“a”: “d”, “b”: {“p”: “/”, “d”: + // “”}} +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateStartPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateEndPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyTag; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataQueries; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessage; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMessage; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHello; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloTimestamp; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloVersion; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloConnectedHost; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloSession; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageShutdown; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageReset; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestActionPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedListen; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedUnlisten; +FOUNDATION_EXPORT NSString + *const kFWPRequestActionListen; // {"t": "d", "d": {"r": 1, "a": "l", "b": { + // "p": "/" } } } +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnlisten; +FOUNDATION_EXPORT NSString *const kFWPRequestActionStats; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectCancel; +FOUNDATION_EXPORT NSString *const kFWPRequestActionAuth; +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnauth; +FOUNDATION_EXPORT NSString *const kFWPRequestCredential; +FOUNDATION_EXPORT NSString *const kFWPRequestPath; +FOUNDATION_EXPORT NSString *const kFWPRequestCounters; +FOUNDATION_EXPORT NSString *const kFWPRequestQueries; +FOUNDATION_EXPORT NSString *const kFWPRequestTag; +FOUNDATION_EXPORT NSString *const kFWPRequestData; +FOUNDATION_EXPORT NSString *const kFWPRequestHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashPaths; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashHashes; +FOUNDATION_EXPORT NSString *const kFWPRequestStatus; + +#pragma mark - +#pragma mark Websock Transport Constants + +FOUNDATION_EXPORT NSString *const kWireProtocolVersionParam; +FOUNDATION_EXPORT NSString *const kWebsocketProtocolVersion; +FOUNDATION_EXPORT NSString *const kWebsocketServerKillPacket; +FOUNDATION_EXPORT const int kWebsocketMaxFrameSize; +FOUNDATION_EXPORT NSUInteger const kWebsocketKeepaliveInterval; +FOUNDATION_EXPORT NSUInteger const kWebsocketConnectTimeout; + +FOUNDATION_EXPORT float const kPersistentConnReconnectMinDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMaxDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMultiplier; +FOUNDATION_EXPORT float const + kPersistentConnSuccessfulConnectionEstablishedDelay; + +#pragma mark - +#pragma mark Query / QueryParams constants + +FOUNDATION_EXPORT NSString *const kQueryDefault; +FOUNDATION_EXPORT NSString *const kQueryDefaultObject; +FOUNDATION_EXPORT NSString *const kViewManagerDictConstView; +FOUNDATION_EXPORT NSString *const kFQPIndexStartValue; +FOUNDATION_EXPORT NSString *const kFQPIndexStartName; +FOUNDATION_EXPORT NSString *const kFQPIndexEndValue; +FOUNDATION_EXPORT NSString *const kFQPIndexEndName; +FOUNDATION_EXPORT NSString *const kFQPLimit; +FOUNDATION_EXPORT NSString *const kFQPViewFrom; +FOUNDATION_EXPORT NSString *const kFQPViewFromLeft; +FOUNDATION_EXPORT NSString *const kFQPViewFromRight; +FOUNDATION_EXPORT NSString *const kFQPIndex; + +#pragma mark - +#pragma mark Interrupt Reasons + +FOUNDATION_EXPORT NSString *const kFInterruptReasonServerKill; +FOUNDATION_EXPORT NSString *const kFInterruptReasonWaitingForOpen; +FOUNDATION_EXPORT NSString *const kFInterruptReasonRepoInterrupt; +FOUNDATION_EXPORT NSString *const kFInterruptReasonAuthExpired; + +#pragma mark - +#pragma mark Payload constants + +FOUNDATION_EXPORT NSString *const kPayloadPriority; +FOUNDATION_EXPORT NSString *const kPayloadValue; +FOUNDATION_EXPORT NSString *const kPayloadMetadataPrefix; + +#pragma mark - +#pragma mark ServerValue constants + +FOUNDATION_EXPORT NSString *const kServerValueSubKey; +FOUNDATION_EXPORT NSString *const kServerValuePriority; + +#pragma mark - +#pragma mark.info/ constants + +FOUNDATION_EXPORT NSString *const kDotInfoPrefix; +FOUNDATION_EXPORT NSString *const kDotInfoConnected; +FOUNDATION_EXPORT NSString *const kDotInfoServerTimeOffset; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +FOUNDATION_EXPORT NSString *const kJavaScriptObject; +FOUNDATION_EXPORT NSString *const kJavaScriptString; +FOUNDATION_EXPORT NSString *const kJavaScriptBoolean; +FOUNDATION_EXPORT NSString *const kJavaScriptNumber; +FOUNDATION_EXPORT NSString *const kJavaScriptNull; +FOUNDATION_EXPORT NSString *const kJavaScriptTrue; +FOUNDATION_EXPORT NSString *const kJavaScriptFalse; + +#pragma mark - +#pragma mark Error handling constants + +FOUNDATION_EXPORT NSString *const kFErrorDomain; +FOUNDATION_EXPORT NSUInteger const kFAuthError; +FOUNDATION_EXPORT NSString *const kFErrorWriteCanceled; + +#pragma mark - +#pragma mark Validation Constants + +FOUNDATION_EXPORT NSUInteger const kFirebaseMaxObjectDepth; +FOUNDATION_EXPORT const unsigned int kFirebaseMaxLeafSize; + +#pragma mark - +#pragma mark Transaction Constants + +FOUNDATION_EXPORT NSUInteger const kFTransactionMaxRetries; +FOUNDATION_EXPORT NSString *const kFTransactionTooManyRetries; +FOUNDATION_EXPORT NSString *const kFTransactionNoData; +FOUNDATION_EXPORT NSString *const kFTransactionSet; +FOUNDATION_EXPORT NSString *const kFTransactionDisconnect; + +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m new file mode 100644 index 0000000..1cf50ad --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m @@ -0,0 +1,185 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConstants.h" + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +NSString *const kFWPRequestType = @"t"; +NSString *const kFWPRequestTypeData = @"d"; +NSString *const kFWPRequestDataPayload = @"d"; +NSString *const kFWPRequestNumber = @"r"; +NSString *const kFWPRequestPayloadBody = @"b"; +NSString *const kFWPRequestError = @"error"; +NSString *const kFWPRequestAction = @"a"; +NSString *const kFWPResponseForRNData = @"b"; +NSString *const kFWPResponseForActionStatus = @"s"; +NSString *const kFWPResponseForActionStatusOk = @"ok"; +NSString *const kFWPResponseForActionStatusDataStale = @"datastale"; +NSString *const kFWPResponseForActionData = @"d"; +NSString *const kFWPResponseDataWarnings = @"w"; +NSString *const kFWPAsyncServerAction = @"a"; +NSString *const kFWPAsyncServerPayloadBody = @"b"; +NSString *const kFWPAsyncServerDataUpdate = @"d"; +NSString *const kFWPAsyncServerDataMerge = @"m"; +NSString *const kFWPAsyncServerDataRangeMerge = @"rm"; +NSString *const kFWPAsyncServerAuthRevoked = @"ac"; +NSString *const kFWPASyncServerListenCancelled = @"c"; +NSString *const kFWPAsyncServerSecurityDebug = @"sd"; +NSString *const kFWPAsyncServerDataUpdateBodyPath = + @"p"; // {“a”: “d”, “b”: {“p”: “/”, “d”: “”}} +NSString *const kFWPAsyncServerDataUpdateBodyData = @"d"; +NSString *const kFWPAsyncServerDataUpdateStartPath = @"s"; +NSString *const kFWPAsyncServerDataUpdateEndPath = @"e"; +NSString *const kFWPAsyncServerDataUpdateRangeMerge = @"m"; +NSString *const kFWPAsyncServerDataUpdateBodyTag = @"t"; +NSString *const kFWPAsyncServerDataQueries = @"q"; + +NSString *const kFWPAsyncServerEnvelopeType = @"t"; +NSString *const kFWPAsyncServerEnvelopeData = @"d"; +NSString *const kFWPAsyncServerControlMessage = @"c"; +NSString *const kFWPAsyncServerControlMessageType = @"t"; +NSString *const kFWPAsyncServerControlMessageData = @"d"; +NSString *const kFWPAsyncServerDataMessage = @"d"; + +NSString *const kFWPAsyncServerHello = @"h"; +NSString *const kFWPAsyncServerHelloTimestamp = @"ts"; +NSString *const kFWPAsyncServerHelloVersion = @"v"; +NSString *const kFWPAsyncServerHelloConnectedHost = @"h"; +NSString *const kFWPAsyncServerHelloSession = @"s"; + +NSString *const kFWPAsyncServerControlMessageShutdown = @"s"; +NSString *const kFWPAsyncServerControlMessageReset = @"r"; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +NSString *const kFWPRequestActionPut = @"p"; +NSString *const kFWPRequestActionMerge = @"m"; +NSString *const kFWPRequestActionListen = + @"l"; // {"t": "d", "d": {"r": 1, "a": "l", "b": { "p": "/" } } } +NSString *const kFWPRequestActionUnlisten = @"u"; +NSString *const kFWPRequestActionStats = @"s"; +NSString *const kFWPRequestActionTaggedListen = @"q"; +NSString *const kFWPRequestActionTaggedUnlisten = @"n"; +NSString *const kFWPRequestActionDisconnectPut = @"o"; +NSString *const kFWPRequestActionDisconnectMerge = @"om"; +NSString *const kFWPRequestActionDisconnectCancel = @"oc"; +NSString *const kFWPRequestActionAuth = @"auth"; +NSString *const kFWPRequestActionUnauth = @"unauth"; +NSString *const kFWPRequestCredential = @"cred"; +NSString *const kFWPRequestPath = @"p"; +NSString *const kFWPRequestCounters = @"c"; +NSString *const kFWPRequestQueries = @"q"; +NSString *const kFWPRequestTag = @"t"; +NSString *const kFWPRequestData = @"d"; +NSString *const kFWPRequestHash = @"h"; +NSString *const kFWPRequestCompoundHash = @"ch"; +NSString *const kFWPRequestCompoundHashPaths = @"ps"; +NSString *const kFWPRequestCompoundHashHashes = @"hs"; +NSString *const kFWPRequestStatus = @"s"; + +#pragma mark - +#pragma mark Websock Transport Constants + +NSString *const kWireProtocolVersionParam = @"v"; +NSString *const kWebsocketProtocolVersion = @"5"; +NSString *const kWebsocketServerKillPacket = @"kill"; +const int kWebsocketMaxFrameSize = 16384; +NSUInteger const kWebsocketKeepaliveInterval = 45; +NSUInteger const kWebsocketConnectTimeout = 30; + +float const kPersistentConnReconnectMinDelay = 1.0; +float const kPersistentConnReconnectMaxDelay = 30.0; +float const kPersistentConnReconnectMultiplier = 1.3f; +float const kPersistentConnSuccessfulConnectionEstablishedDelay = 30.0; + +#pragma mark - +#pragma mark Query constants + +NSString *const kQueryDefault = @"default"; +NSString *const kQueryDefaultObject = @"{}"; +NSString *const kViewManagerDictConstView = @"view"; +NSString *const kFQPIndexStartValue = @"sp"; +NSString *const kFQPIndexStartName = @"sn"; +NSString *const kFQPIndexEndValue = @"ep"; +NSString *const kFQPIndexEndName = @"en"; +NSString *const kFQPLimit = @"l"; +NSString *const kFQPViewFrom = @"vf"; +NSString *const kFQPViewFromLeft = @"l"; +NSString *const kFQPViewFromRight = @"r"; +NSString *const kFQPIndex = @"i"; + +#pragma mark - +#pragma mark Interrupt Reasons + +NSString *const kFInterruptReasonServerKill = @"server_kill"; +NSString *const kFInterruptReasonWaitingForOpen = @"waiting_for_open"; +NSString *const kFInterruptReasonRepoInterrupt = @"repo_interrupt"; + +#pragma mark - +#pragma mark Payload constants + +NSString *const kPayloadPriority = @".priority"; +NSString *const kPayloadValue = @".value"; +NSString *const kPayloadMetadataPrefix = @"."; + +#pragma mark - +#pragma mark ServerValue constants + +NSString *const kServerValueSubKey = @".sv"; +NSString *const kServerValuePriority = @"timestamp"; + +#pragma mark - +#pragma mark.info/ constants + +NSString *const kDotInfoPrefix = @".info"; +NSString *const kDotInfoConnected = @"connected"; +NSString *const kDotInfoServerTimeOffset = @"serverTimeOffset"; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +NSString *const kJavaScriptObject = @"object"; +NSString *const kJavaScriptString = @"string"; +NSString *const kJavaScriptBoolean = @"boolean"; +NSString *const kJavaScriptNumber = @"number"; +NSString *const kJavaScriptNull = @"null"; +NSString *const kJavaScriptTrue = @"true"; +NSString *const kJavaScriptFalse = @"false"; + +#pragma mark - +#pragma mark Error handling constants + +NSString *const kFErrorDomain = @"com.firebase"; +NSUInteger const kFAuthError = 1; +NSString *const kFErrorWriteCanceled = @"write_canceled"; + +#pragma mark - +#pragma mark Validation Constants + +NSUInteger const kFirebaseMaxObjectDepth = 1000; +const unsigned int kFirebaseMaxLeafSize = 1024 * 1024 * 10; // 10 MB + +#pragma mark - +#pragma mark Transaction Constants + +NSUInteger const kFTransactionMaxRetries = 25; +NSString *const kFTransactionTooManyRetries = @"maxretry"; +NSString *const kFTransactionNoData = @"nodata"; +NSString *const kFTransactionSet = @"set"; +NSString *const kFTransactionDisconnect = @"disconnect"; diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h new file mode 100644 index 0000000..2453a81 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +@interface FCompoundHashBuilder : NSObject + +- (FPath *)currentPath; + +@end + +typedef BOOL (^FCompoundHashSplitStrategy)(FCompoundHashBuilder *builder); + +@interface FCompoundHash : NSObject + +@property(nonatomic, strong, readonly) NSArray *posts; +@property(nonatomic, strong, readonly) NSArray *hashes; + ++ (FCompoundHash *)fromNode:(id)node; ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m new file mode 100644 index 0000000..ced79cd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m @@ -0,0 +1,259 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundHash.h" +#import "FChildrenNode.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" + +@interface FCompoundHashBuilder () + +@property(nonatomic, strong) FCompoundHashSplitStrategy splitStrategy; + +@property(nonatomic, strong) NSMutableArray *currentPaths; +@property(nonatomic, strong) NSMutableArray *currentHashes; + +@end + +@implementation FCompoundHashBuilder { + + // NOTE: We use the existence of this to know if we've started building a + // range (i.e. encountered a leaf node). + NSMutableString *optHashValueBuilder; + + // The current path as a stack. This is used in combination with + // currentPathDepth to simultaneously store the last leaf node path. The + // depth is changed when descending and ascending, at the same time the + // current key is set for the current depth. Because the keys are left + // unchanged for ascending the path will also contain the path of the last + // visited leaf node (using lastLeafDepth elements) + NSMutableArray *currentPath; + NSInteger lastLeafDepth; + NSInteger currentPathDepth; + + BOOL needsComma; +} + +- (instancetype)initWithSplitStrategy:(FCompoundHashSplitStrategy)strategy { + self = [super init]; + if (self != nil) { + self->_splitStrategy = strategy; + self->optHashValueBuilder = nil; + self->currentPath = [NSMutableArray array]; + self->lastLeafDepth = -1; + self->currentPathDepth = 0; + self->needsComma = YES; + self->_currentPaths = [NSMutableArray array]; + self->_currentHashes = [NSMutableArray array]; + } + return self; +} + +- (BOOL)isBuildingRange { + return self->optHashValueBuilder != nil; +} + +- (NSUInteger)currentHashLength { + return self->optHashValueBuilder.length; +} + +- (FPath *)currentPath { + return [self currentPathWithDepth:self->currentPathDepth]; +} + +- (FPath *)currentPathWithDepth:(NSInteger)depth { + NSArray *pieces = + [self->currentPath subarrayWithRange:NSMakeRange(0, depth)]; + return [[FPath alloc] initWithPieces:pieces andPieceNum:0]; +} + +- (void)enumerateCurrentPathToDepth:(NSInteger)depth + withBlock:(void (^)(NSString *key))block { + for (NSInteger i = 0; i < depth; i++) { + block(self->currentPath[i]); + } +} + +- (void)appendKey:(NSString *)key toString:(NSMutableString *)string { + [FSnapshotUtilities appendHashV2RepresentationForString:key + toString:string]; +} + +- (void)ensureRange { + if (![self isBuildingRange]) { + optHashValueBuilder = [NSMutableString string]; + [optHashValueBuilder appendString:@"("]; + [self + enumerateCurrentPathToDepth:self->currentPathDepth + withBlock:^(NSString *key) { + [self appendKey:key + toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + }]; + self->needsComma = NO; + } +} + +- (void)processLeaf:(FLeafNode *)leafNode { + [self ensureRange]; + + self->lastLeafDepth = self->currentPathDepth; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode + toString:self->optHashValueBuilder + hashVersion:FDataHashVersionV2]; + self->needsComma = YES; + if (self.splitStrategy(self)) { + [self endRange]; + } +} + +- (void)startChild:(NSString *)key { + [self ensureRange]; + + if (self->needsComma) { + [self->optHashValueBuilder appendString:@","]; + } + [self appendKey:key toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + if (self->currentPathDepth == currentPath.count) { + [self->currentPath addObject:key]; + } else { + self->currentPath[self->currentPathDepth] = key; + } + self->currentPathDepth++; + self->needsComma = NO; +} + +- (void)endChild { + self->currentPathDepth--; + if ([self isBuildingRange]) { + [self->optHashValueBuilder appendString:@")"]; + } + self->needsComma = YES; +} + +- (void)finishHashing { + NSAssert(self->currentPathDepth == 0, + @"Can't finish hashing in the middle of processing a child"); + if ([self isBuildingRange]) { + [self endRange]; + } + + // Always close with the empty hash for the remaining range to allow simple + // appending + [self.currentHashes addObject:@""]; +} + +- (void)endRange { + NSAssert([self isBuildingRange], + @"Can't end range without starting a range!"); + // Add closing parenthesis for current depth + for (NSUInteger i = 0; i < currentPathDepth; i++) { + [self->optHashValueBuilder appendString:@")"]; + } + [self->optHashValueBuilder appendString:@")"]; + + FPath *lastLeafPath = [self currentPathWithDepth:self->lastLeafDepth]; + NSString *hash = + [FStringUtilities base64EncodedSha1:self->optHashValueBuilder]; + [self.currentHashes addObject:hash]; + [self.currentPaths addObject:lastLeafPath]; + + self->optHashValueBuilder = nil; +} + +@end + +@interface FCompoundHash () + +@property(nonatomic, strong, readwrite) NSArray *posts; +@property(nonatomic, strong, readwrite) NSArray *hashes; + +@end + +@implementation FCompoundHash + +- (id)initWithPosts:(NSArray *)posts hashes:(NSArray *)hashes { + self = [super init]; + if (self != nil) { + if (posts.count != hashes.count - 1) { + [NSException raise:NSInvalidArgumentException + format:@"Number of posts need to be n-1 for n hashes " + @"in FCompoundHash"]; + } + self.posts = posts; + self.hashes = hashes; + } + return self; +} + ++ (FCompoundHashSplitStrategy)simpleSizeSplitStrategyForNode:(id)node { + NSUInteger estimatedSize = + [FSnapshotUtilities estimateSerializedNodeSize:node]; + + // Splits for + // 1k -> 512 (2 parts) + // 5k -> 715 (7 parts) + // 100k -> 3.2k (32 parts) + // 500k -> 7k (71 parts) + // 5M -> 23k (228 parts) + NSUInteger splitThreshold = MAX(512, (NSUInteger)sqrt(estimatedSize * 100)); + + return ^BOOL(FCompoundHashBuilder *builder) { + // Never split on priorities + return [builder currentHashLength] > splitThreshold && + ![[[builder currentPath] getBack] isEqualToString:@".priority"]; + }; +} + ++ (FCompoundHash *)fromNode:(id)node { + return [FCompoundHash + fromNode:node + splitStrategy:[FCompoundHash simpleSizeSplitStrategyForNode:node]]; +} + ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy { + if ([node isEmpty]) { + return [[FCompoundHash alloc] initWithPosts:@[] hashes:@[ @"" ]]; + } else { + FCompoundHashBuilder *builder = + [[FCompoundHashBuilder alloc] initWithSplitStrategy:strategy]; + [FCompoundHash processNode:node builder:builder]; + [builder finishHashing]; + return [[FCompoundHash alloc] initWithPosts:builder.currentPaths + hashes:builder.currentHashes]; + } +} + ++ (void)processNode:(id)node builder:(FCompoundHashBuilder *)builder { + if ([node isLeafNode]) { + [builder processLeaf:node]; + } else { + NSAssert(![node isEmpty], @"Can't calculate hash on empty node!"); + FChildrenNode *childrenNode = (FChildrenNode *)node; + [childrenNode enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [builder startChild:key]; + [self processNode:node builder:builder]; + [builder endChild]; + }]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h new file mode 100644 index 0000000..8efd803 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" + +@class FQuerySpec; +@protocol FSyncTreeHash; + +typedef NSArray * (^fbt_startListeningBlock)(FQuerySpec *query, NSNumber *tagId, + id hash, + fbt_nsarray_nsstring onComplete); +typedef void (^fbt_stopListeningBlock)(FQuerySpec *query, NSNumber *tagId); + +@interface FListenProvider : NSObject + +@property(nonatomic, copy) fbt_startListeningBlock startListening; +@property(nonatomic, copy) fbt_stopListeningBlock stopListening; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m new file mode 100644 index 0000000..27da015 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenProvider.h" +#import "FIRDatabaseQuery.h" + +@implementation FListenProvider + +@synthesize startListening; +@synthesize stopListening; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h new file mode 100644 index 0000000..81836fd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FRepoInfo.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@protocol FPersistentConnectionDelegate; +@protocol FSyncTreeHash; +@class FQuerySpec; +@class FIRDatabaseConfig; + +@interface FPersistentConnection : NSObject + +@property(nonatomic, weak) id delegate; +@property(nonatomic) BOOL pauseWrites; + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)queue + config:(FIRDatabaseConfig *)config; + +- (void)open; + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete; +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete; + +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete; + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId; +- (void)refreshAuthToken:(NSString *)token; +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)ackPuts; +- (void)purgeOutstandingWrites; + +- (void)interruptForReason:(NSString *)reason; +- (void)resumeForReason:(NSString *)reason; +- (BOOL)isInterruptedForReason:(NSString *)reason; + +// FConnection delegate methods +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +// Testing methods +- (NSDictionary *)dumpListens; + +@end + +@protocol FPersistentConnectionDelegate + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)path + tagId:(NSNumber *)tag; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m new file mode 100644 index 0000000..69f52c1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m @@ -0,0 +1,1141 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FAtomicNumber.h" +#import "FAuthTokenProvider.h" +#import "FCompoundHash.h" +#import "FConstants.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseReference.h" +#import "FIRRetryHelper.h" +#import "FIndex.h" +#import "FPersistentConnection.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTupleCallbackStatus.h" +#import "FTupleOnDisconnect.h" +#import "FUtilities.h" +#import +#import +#import +#import + +@interface FOutstandingQuery : NSObject + +@property(nonatomic, strong) FQuerySpec *query; +@property(nonatomic, strong) NSNumber *tagId; +@property(nonatomic, strong) id syncTreeHash; +@property(nonatomic, copy) fbt_void_nsstring onComplete; + +@end + +@implementation FOutstandingQuery + +@end + +@interface FOutstandingPut : NSObject + +@property(nonatomic, strong) NSString *action; +@property(nonatomic, strong) NSDictionary *request; +@property(nonatomic, copy) fbt_void_nsstring_nsstring onCompleteBlock; +@property(nonatomic) BOOL sent; + +@end + +@implementation FOutstandingPut + +@end + +typedef enum { + ConnectionStateDisconnected, + ConnectionStateGettingToken, + ConnectionStateConnecting, + ConnectionStateAuthenticating, + ConnectionStateConnected +} ConnectionState; + +@interface FPersistentConnection () { + ConnectionState connectionState; + BOOL firstConnection; + NSTimeInterval reconnectDelay; + NSTimeInterval lastConnectionAttemptTime; + NSTimeInterval lastConnectionEstablishedTime; + SCNetworkReachabilityRef reachability; +} + +- (int)getNextRequestNumber; +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body; +- (void)handleTimestamp:(NSNumber *)timestamp; +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback; + +@property(nonatomic, strong) FConnection *realtime; +@property(nonatomic, strong) NSMutableDictionary *listens; +@property(nonatomic, strong) NSMutableDictionary *outstandingPuts; +@property(nonatomic, strong) NSMutableArray *onDisconnectQueue; +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FAtomicNumber *putCounter; +@property(nonatomic, strong) FAtomicNumber *requestNumber; +@property(nonatomic, strong) NSMutableDictionary *requestCBHash; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic) NSUInteger unackedListensCount; +@property(nonatomic, strong) NSMutableArray *putsToAck; +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic, strong) NSString *lastSessionID; +@property(nonatomic, strong) NSMutableSet *interruptReasons; +@property(nonatomic, strong) FIRRetryHelper *retryHelper; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) NSString *authToken; +@property(nonatomic) BOOL forceAuthTokenRefresh; +@property(nonatomic) NSUInteger currentFetchTokenAttempt; + +@end + +@implementation FPersistentConnection + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)dispatchQueue + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self) { + self->_config = config; + self->_repoInfo = repoInfo; + self->_dispatchQueue = dispatchQueue; + self->_authTokenProvider = config.authTokenProvider; + NSAssert(self->_authTokenProvider != nil, + @"Expected auth token provider"); + self.interruptReasons = [NSMutableSet set]; + + self.listens = [[NSMutableDictionary alloc] init]; + self.outstandingPuts = [[NSMutableDictionary alloc] init]; + self.onDisconnectQueue = [[NSMutableArray alloc] init]; + self.putCounter = [[FAtomicNumber alloc] init]; + self.requestNumber = [[FAtomicNumber alloc] init]; + self.requestCBHash = [[NSMutableDictionary alloc] init]; + self.unackedListensCount = 0; + self.putsToAck = [NSMutableArray array]; + connectionState = ConnectionStateDisconnected; + firstConnection = YES; + reconnectDelay = kPersistentConnReconnectMinDelay; + + self->_retryHelper = [[FIRRetryHelper alloc] + initWithDispatchQueue:dispatchQueue + minRetryDelayAfterFailure:kPersistentConnReconnectMinDelay + maxRetryDelay:kPersistentConnReconnectMaxDelay + retryExponent:kPersistentConnReconnectMultiplier + jitterFactor:0.7]; + + [self setupNotifications]; + // Make sure we don't actually connect until open is called + [self interruptForReason:kFInterruptReasonWaitingForOpen]; + } + // nb: The reason establishConnection isn't called here like the JS version + // is because callers need to set the delegate first. The ctor can be + // modified to accept the delegate but that deviates from normal ios + // conventions. After the delegate has been set, the caller is responsible + // for calling establishConnection: + return self; +} + +- (void)dealloc { + if (reachability) { + // Unschedule the notifications + SCNetworkReachabilitySetDispatchQueue(reachability, NULL); + CFRelease(reachability); + } +} + +#pragma mark - +#pragma mark Public methods + +- (void)open { + [self resumeForReason:kFInterruptReasonWaitingForOpen]; +} + +/** + * Note that the listens dictionary has a type of Map[String (pathString), + * Map[FQueryParams, FOutstandingQuery]] + * + * This means, for each path we care about, there are sets of queryParams that + * correspond to an FOutstandingQuery object. There can be multiple sets at a + * path since we overlap listens for a short time while adding or removing a + * query from a location in the tree. + */ +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete { + FFLog(@"I-RDB034001", @"Listen called for %@", query); + + NSAssert(self.listens[query] == nil, + @"listen() called twice for the same query"); + NSAssert(query.isDefault || !query.loadsAllData, + @"listen called for non-default but complete query"); + FOutstandingQuery *outstanding = [[FOutstandingQuery alloc] init]; + outstanding.query = query; + outstanding.tagId = tagId; + outstanding.syncTreeHash = hash; + outstanding.onComplete = onComplete; + [self.listens setObject:outstanding forKey:query]; + if ([self connected]) { + [self sendListen:outstanding]; + } +} + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionPut + forPath:pathString + withHash:hash + withCallback:onComplete]; +} + +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionMerge + forPath:pathString + withHash:nil + withCallback:onComplete]; +} + +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectPut + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectPut; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectMerge + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectMerge; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectCancel + forPath:[path description] + withData:[NSNull null] + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectCancel; + tuple.data = [NSNull null]; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId { + FPath *path = query.path; + FFLog(@"I-RDB034002", @"Unlistening for %@", query); + + NSArray *outstanding = [self removeListen:query]; + if (outstanding.count > 0 && [self connected]) { + [self sendUnlisten:path queryParams:query.params tagId:tagId]; + } +} + +- (void)refreshAuthToken:(NSString *)token { + self.authToken = token; + if ([self connected]) { + if (token != nil) { + [self sendAuthAndRestoreStateAfterComplete:NO]; + } else { + [self sendUnauth]; + } + } +} + +#pragma mark - +#pragma mark Connection status + +- (BOOL)connected { + return self->connectionState == ConnectionStateAuthenticating || + self->connectionState == ConnectionStateConnected; +} + +- (BOOL)canSendWrites { + return self->connectionState == ConnectionStateConnected; +} + +#pragma mark - +#pragma mark FConnection delegate methods + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB034003", @"On ready"); + lastConnectionEstablishedTime = [[NSDate date] timeIntervalSince1970]; + [self handleTimestamp:timestamp]; + + if (firstConnection) { + [self sendConnectStats]; + } + + [self restoreAuth]; + firstConnection = NO; + self.lastSessionID = sessionID; + dispatch_async(self.dispatchQueue, ^{ + [self.delegate onConnect:self]; + }); +} + +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message { + if (message[kFWPRequestNumber] != nil) { + // this is a response to a request we sent + NSNumber *rn = [NSNumber + numberWithInt:[[message objectForKey:kFWPRequestNumber] intValue]]; + if ([self.requestCBHash objectForKey:rn]) { + void (^callback)(NSDictionary *) = + [self.requestCBHash objectForKey:rn]; + [self.requestCBHash removeObjectForKey:rn]; + + if (callback) { + // dispatch_async(self.dispatchQueue, ^{ + callback([message objectForKey:kFWPResponseForRNData]); + //}); + } + } + } else if (message[kFWPRequestError] != nil) { + NSString *error = [message objectForKey:kFWPRequestError]; + @throw [[NSException alloc] initWithName:@"FirebaseDatabaseServerError" + reason:error + userInfo:nil]; + } else if (message[kFWPAsyncServerAction] != nil) { + // this is a server push of some sort + NSString *action = [message objectForKey:kFWPAsyncServerAction]; + NSDictionary *body = [message objectForKey:kFWPAsyncServerPayloadBody]; + [self onDataPushWithAction:action andBody:body]; + } +} + +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason { + FFLog(@"I-RDB034004", @"Got on disconnect due to %s", + (reason == DISCONNECT_REASON_SERVER_RESET) ? "server_reset" + : "other"); + connectionState = ConnectionStateDisconnected; + // Drop the realtime connection + self.realtime = nil; + [self cancelSentTransactions]; + [self.requestCBHash removeAllObjects]; + self.unackedListensCount = 0; + if ([self shouldReconnect]) { + NSTimeInterval timeSinceLastConnectSucceeded = + [[NSDate date] timeIntervalSince1970] - + lastConnectionEstablishedTime; + BOOL lastConnectionWasSuccessful; + if (lastConnectionEstablishedTime > 0) { + lastConnectionWasSuccessful = + timeSinceLastConnectSucceeded > + kPersistentConnSuccessfulConnectionEstablishedDelay; + } else { + lastConnectionWasSuccessful = NO; + } + + if (reason == DISCONNECT_REASON_SERVER_RESET || + lastConnectionWasSuccessful) { + [self.retryHelper signalSuccess]; + } + [self tryScheduleReconnect]; + } + lastConnectionEstablishedTime = 0; + [self.delegate onDisconnect:self]; +} + +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason { + FFWarn(@"I-RDB034005", + @"Firebase Database connection was forcefully killed by the server. " + @" Will not attempt reconnect. Reason: %@", + reason); + [self interruptForReason:kFInterruptReasonServerKill]; +} + +#pragma mark - +#pragma mark Connection handling methods + +- (void)interruptForReason:(NSString *)reason { + FFLog(@"I-RDB034006", @"Connection interrupted for: %@", reason); + + [self.interruptReasons addObject:reason]; + if (self.realtime) { + // Will call onDisconnect and set the connection state to Disconnected + [self.realtime close]; + self.realtime = nil; + } else { + [self.retryHelper cancel]; + self->connectionState = ConnectionStateDisconnected; + } + // Reset timeouts + [self.retryHelper signalSuccess]; +} + +- (void)resumeForReason:(NSString *)reason { + FFLog(@"I-RDB034007", @"Connection no longer interrupted for: %@", reason); + [self.interruptReasons removeObject:reason]; + + if ([self shouldReconnect] && + connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } +} + +- (BOOL)shouldReconnect { + return self.interruptReasons.count == 0; +} + +- (BOOL)isInterruptedForReason:(NSString *)reason { + return [self.interruptReasons containsObject:reason]; +} + +#pragma mark - +#pragma mark Private methods + +- (void)tryScheduleReconnect { + if ([self shouldReconnect]) { + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + BOOL forceRefresh = self.forceAuthTokenRefresh; + self.forceAuthTokenRefresh = NO; + FFLog(@"I-RDB034008", @"Scheduling connection attempt"); + [self.retryHelper retry:^{ + FFLog(@"I-RDB034009", @"Trying to fetch auth token"); + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + self->connectionState = ConnectionStateGettingToken; + self.currentFetchTokenAttempt++; + NSUInteger thisFetchTokenAttempt = self.currentFetchTokenAttempt; + [self.authTokenProvider + fetchTokenForcingRefresh:forceRefresh + withCallback:^(NSString *token, NSError *error) { + if (thisFetchTokenAttempt == + self.currentFetchTokenAttempt) { + if (error != nil) { + self->connectionState = + ConnectionStateDisconnected; + FFLog(@"I-RDB034010", + @"Error fetching token: %@", error); + [self tryScheduleReconnect]; + } else { + // Someone could have interrupted us while + // fetching the token, marking the + // connection as Disconnected + if (self->connectionState == + ConnectionStateGettingToken) { + FFLog(@"I-RDB034011", + @"Successfully fetched token, " + @"opening connection"); + [self openNetworkConnectionWithToken: + token]; + } else { + NSAssert( + self->connectionState == + ConnectionStateDisconnected, + @"Expected connection state " + @"disconnected, but got %d", + self->connectionState); + FFLog(@"I-RDB034012", + @"Not opening connection after " + @"token refresh, because " + @"connection was set to " + @"disconnected."); + } + } + } else { + FFLog(@"I-RDB034013", + @"Ignoring fetch token result, because " + @"this was not the latest attempt."); + } + }]; + }]; + } +} + +- (void)openNetworkConnectionWithToken:(NSString *)token { + NSAssert(self->connectionState == ConnectionStateGettingToken, + @"Trying to open network connection while in wrong state: %d", + self->connectionState); + self.authToken = token; + self->connectionState = ConnectionStateConnecting; + self.realtime = [[FConnection alloc] initWith:self.repoInfo + andDispatchQueue:self.dispatchQueue + lastSessionID:self.lastSessionID]; + self.realtime.delegate = self; + [self.realtime open]; +} + +static void reachabilityCallback(SCNetworkReachabilityRef ref, + SCNetworkReachabilityFlags flags, void *info) { + if (flags & kSCNetworkReachabilityFlagsReachable) { + FFLog(@"I-RDB034014", + @"Network became reachable. Trigger a connection attempt"); + FPersistentConnection *self = (__bridge FPersistentConnection *)info; + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + } else { + FFLog(@"I-RDB034015", @"Network is not reachable"); + } +} + +- (void)enteringForeground { + dispatch_async(self.dispatchQueue, ^{ + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + }); +} + +- (void)setupNotifications { + + NSString *const *foregroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationWillEnterForegroundNotification"); + if (foregroundConstant) { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(enteringForeground) + name:*foregroundConstant + object:nil]; + } + // An empty address is interpreted a generic internet access + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + reachability = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + SCNetworkReachabilityContext ctx = {0, (__bridge void *)(self), NULL, NULL, + NULL}; + if (SCNetworkReachabilitySetCallback(reachability, reachabilityCallback, + &ctx)) { + SCNetworkReachabilitySetDispatchQueue(reachability, self.dispatchQueue); + } else { + FFLog(@"I-RDB034016", + @"Failed to set up network reachability monitoring"); + CFRelease(reachability); + reachability = NULL; + } +} + +- (void)sendAuthAndRestoreStateAfterComplete:(BOOL)restoreStateAfterComplete { + NSAssert([self connected], @"Must be connected to send auth"); + NSAssert(self.authToken != nil, + @"Can't send auth if there is no credential"); + + NSDictionary *requestData = @{kFWPRequestCredential : self.authToken}; + [self sendAction:kFWPRequestActionAuth + body:requestData + sensitive:YES + callback:^(NSDictionary *data) { + self->connectionState = ConnectionStateConnected; + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + id responseData = [data objectForKey:kFWPResponseForActionData]; + if (responseData == nil) { + responseData = @"error"; + } + + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (statusOk) { + if (restoreStateAfterComplete) { + [self restoreState]; + } + } else { + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034017", @"Authentication failed: %@ (%@)", + status, responseData); + } else { + FFWarn(@"I-RDB034018", @"Authentication failed: %@ (%@)", + status, responseData); + } + [self.realtime close]; + } + }]; +} + +- (void)sendUnauth { + [self sendAction:kFWPRequestActionUnauth + body:@{} + sensitive:NO + callback:nil]; +} + +- (void)onAuthRevokedWithStatus:(NSString *)status + andReason:(NSString *)reason { + // This might be for an earlier token than we just recently sent. But since + // we need to close the connection anyways, we can set it to null here and + // we will refresh the token later on reconnect + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034019", @"Auth token revoked: %@ (%@)", status, reason); + } else { + FFWarn(@"I-RDB034020", @"Auth token revoked: %@ (%@)", status, reason); + } + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + // Try reconnecting on auth revocation + [self.realtime close]; +} + +- (void)onListenRevoked:(FPath *)path { + NSArray *queries = [self removeAllListensAtPath:path]; + for (FOutstandingQuery *query in queries) { + query.onComplete(@"permission_denied"); + } +} + +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback { + + NSDictionary *request = + @{kFWPRequestPath : pathString, kFWPRequestData : data}; + FFLog(@"I-RDB034021", @"onDisconnect %@: %@", action, request); + + [self sendAction:action + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + callback(status, errorReason); + }]; +} + +- (void)sendPut:(NSNumber *)index { + NSAssert([self canSendWrites], + @"sendPut called when not able to send writes"); + FOutstandingPut *put = self.outstandingPuts[index]; + assert(put != nil); + fbt_void_nsstring_nsstring onComplete = put.onCompleteBlock; + + // Do not async this block; copying the block insinde sendAction: doesn't + // happen in time (or something) so coredumps + put.sent = YES; + [self sendAction:put.action + body:put.request + sensitive:NO + callback:^(NSDictionary *data) { + FOutstandingPut *currentPut = self.outstandingPuts[index]; + if (currentPut == put) { + [self.outstandingPuts removeObjectForKey:index]; + + if (onComplete != nil) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + if (self.unackedListensCount == 0) { + onComplete(status, errorReason); + } else { + FTupleCallbackStatus *putToAck = + [[FTupleCallbackStatus alloc] init]; + putToAck.block = onComplete; + putToAck.status = status; + putToAck.errorReason = errorReason; + [self.putsToAck addObject:putToAck]; + } + } + } else { + FFLog(@"I-RDB034022", + @"Ignoring on complete for put %@ because it was " + @"already removed", + index); + } + }]; +} + +- (void)sendUnlisten:(FPath *)path + queryParams:(FQueryParams *)queryParams + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB034023", @"Unlisten on %@ for %@", path, queryParams); + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:[path toString], kFWPRequestPath, nil]; + if (tagId != nil) { + [request setObject:queryParams.wireProtocolParams + forKey:kFWPRequestQueries]; + [request setObject:tagId forKey:kFWPRequestTag]; + } + + [self sendAction:kFWPRequestActionTaggedUnlisten + body:request + sensitive:NO + callback:nil]; +} + +- (void)putInternal:(id)data + forAction:(NSString *)action + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:pathString, kFWPRequestPath, data, + kFWPRequestData, nil]; + if (hash) { + [request setObject:hash forKey:kFWPRequestHash]; + } + + FOutstandingPut *put = [[FOutstandingPut alloc] init]; + put.action = action; + put.request = request; + put.onCompleteBlock = onComplete; + put.sent = NO; + + NSNumber *index = [self.putCounter getAndIncrement]; + self.outstandingPuts[index] = put; + + if ([self canSendWrites]) { + FFLog(@"I-RDB034024", @"Was connected, and added as index: %@", index); + [self sendPut:index]; + } else { + FFLog(@"I-RDB034025", + @"Wasn't connected or writes paused, so added to outstanding " + @"puts only. Path: %@", + pathString); + } +} + +- (void)sendListen:(FOutstandingQuery *)listenSpec { + FQuerySpec *query = listenSpec.query; + FFLog(@"I-RDB034026", @"Listen for %@", query); + NSMutableDictionary *request = + [NSMutableDictionary dictionaryWithObject:[query.path toString] + forKey:kFWPRequestPath]; + + // Only bother to send query if it's non-default + if (listenSpec.tagId != nil) { + [request setObject:[query.params wireProtocolParams] + forKey:kFWPRequestQueries]; + [request setObject:listenSpec.tagId forKey:kFWPRequestTag]; + } + + [request setObject:[listenSpec.syncTreeHash simpleHash] + forKey:kFWPRequestHash]; + if ([listenSpec.syncTreeHash includeCompoundHash]) { + FCompoundHash *compoundHash = [listenSpec.syncTreeHash compoundHash]; + NSMutableArray *posts = [NSMutableArray array]; + for (FPath *path in compoundHash.posts) { + [posts addObject:path.wireFormat]; + } + request[kFWPRequestCompoundHash] = @{ + kFWPRequestCompoundHashHashes : compoundHash.hashes, + kFWPRequestCompoundHashPaths : posts + }; + } + + fbt_void_nsdictionary onResponse = ^(NSDictionary *response) { + FFLog(@"I-RDB034027", @"Listen response %@", response); + // warn in any case, even if the listener was removed + [self warnOnListenWarningsForQuery:query + payload:response[kFWPResponseForActionData]]; + + FOutstandingQuery *currentListenSpec = self.listens[query]; + + // only trigger actions if the listen hasn't been removed (and maybe + // readded) + if (currentListenSpec == listenSpec) { + NSString *status = [response objectForKey:kFWPRequestStatus]; + if (![status isEqualToString:@"ok"]) { + [self removeListen:query]; + } + + if (listenSpec.onComplete) { + listenSpec.onComplete(status); + } + } + + self.unackedListensCount--; + NSAssert(self.unackedListensCount >= 0, + @"unackedListensCount decremented to be negative."); + if (self.unackedListensCount == 0) { + [self ackPuts]; + } + }; + + [self sendAction:kFWPRequestActionTaggedListen + body:request + sensitive:NO + callback:onResponse]; + + self.unackedListensCount++; +} + +- (void)warnOnListenWarningsForQuery:(FQuerySpec *)query payload:(id)payload { + if (payload != nil && [payload isKindOfClass:[NSDictionary class]]) { + NSDictionary *payloadDict = payload; + id warnings = payloadDict[kFWPResponseDataWarnings]; + if (warnings != nil && [warnings isKindOfClass:[NSArray class]]) { + NSArray *warningsArr = warnings; + if ([warningsArr containsObject:@"no_index"]) { + NSString *indexSpec = [NSString + stringWithFormat:@"\".indexOn\": \"%@\"", + [query.params.index queryDefinition]]; + NSString *indexPath = [query.path description]; + FFWarn(@"I-RDB034028", + @"Using an unspecified index. Your data will be " + @"downloaded and filtered on the client. " + "Consider adding %@ at %@ to your security rules for " + "better performance", + indexSpec, indexPath); + } + } + } +} + +- (int)getNextRequestNumber { + return [[self.requestNumber getAndIncrement] intValue]; +} + +- (void)sendAction:(NSString *)action + body:(NSDictionary *)message + sensitive:(BOOL)sensitive + callback:(void (^)(NSDictionary *data))onMessage { + // Hold onto the onMessage callback for this request before firing it off + NSNumber *rn = [NSNumber numberWithInt:[self getNextRequestNumber]]; + NSDictionary *msg = [NSDictionary + dictionaryWithObjectsAndKeys:rn, kFWPRequestNumber, action, + kFWPRequestAction, message, + kFWPRequestPayloadBody, nil]; + + [self.realtime sendRequest:msg sensitive:sensitive]; + + if (onMessage) { + // Debug message without a callback; bump the rn, but don't hold onto + // the cb + [self.requestCBHash setObject:[onMessage copy] forKey:rn]; + } +} + +- (void)cancelSentTransactions { + NSMutableDictionary + *cancelledOutstandingPuts = [[NSMutableDictionary alloc] init]; + + for (NSNumber *index in self.outstandingPuts) { + FOutstandingPut *put = self.outstandingPuts[index]; + if (put.request[kFWPRequestHash] && put.sent) { + // This is a sent transaction put. + cancelledOutstandingPuts[index] = put; + } + } + + [cancelledOutstandingPuts + enumerateKeysAndObjectsUsingBlock:^( + NSNumber *index, FOutstandingPut *outstandingPut, BOOL *stop) { + // `onCompleteBlock:` may invoke `rerunTransactionsForPath:` and + // enqueue new writes. We defer calling it until we have finished + // enumerating all existing writes. + outstandingPut.onCompleteBlock( + kFTransactionDisconnect, + @"Client was disconnected while running a transaction"); + [self.outstandingPuts removeObjectForKey:index]; + }]; +} + +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body { + FFLog(@"I-RDB034029", @"handleServerMessage: %@, %@", action, body); + id delegate = self.delegate; + if ([action isEqualToString:kFWPAsyncServerDataUpdate] || + [action isEqualToString:kFWPAsyncServerDataMerge]) { + BOOL isMerge = [action isEqualToString:kFWPAsyncServerDataMerge]; + + if ([body objectForKey:kFWPAsyncServerDataUpdateBodyPath] && + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]) { + NSString *path = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + id payloadData = + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]; + if (isMerge && [payloadData isKindOfClass:[NSDictionary class]] && + [payloadData count] == 0) { + // ignore empty merge + } else { + [delegate + onDataUpdate:self + forPath:path + message:payloadData + isMerge:isMerge + tagId:[body objectForKey: + kFWPAsyncServerDataUpdateBodyTag]]; + } + } else { + FFLog( + @"I-RDB034030", + @"Malformed data response from server missing path or data: %@", + body); + } + } else if ([action isEqualToString:kFWPAsyncServerDataRangeMerge]) { + NSString *path = body[kFWPAsyncServerDataUpdateBodyPath]; + NSArray *ranges = body[kFWPAsyncServerDataUpdateBodyData]; + NSNumber *tag = body[kFWPAsyncServerDataUpdateBodyTag]; + NSMutableArray *rangeMerges = [NSMutableArray array]; + for (NSDictionary *range in ranges) { + NSString *startString = range[kFWPAsyncServerDataUpdateStartPath]; + NSString *endString = range[kFWPAsyncServerDataUpdateEndPath]; + id updateData = range[kFWPAsyncServerDataUpdateRangeMerge]; + id updates = [FSnapshotUtilities nodeFrom:updateData]; + FPath *start = (startString != nil) + ? [[FPath alloc] initWith:startString] + : nil; + FPath *end = + (endString != nil) ? [[FPath alloc] initWith:endString] : nil; + FRangeMerge *merge = [[FRangeMerge alloc] initWithStart:start + end:end + updates:updates]; + [rangeMerges addObject:merge]; + } + [delegate onRangeMerge:rangeMerges forPath:path tagId:tag]; + } else if ([action isEqualToString:kFWPAsyncServerAuthRevoked]) { + NSString *status = [body objectForKey:kFWPResponseForActionStatus]; + NSString *reason = [body objectForKey:kFWPResponseForActionData]; + [self onAuthRevokedWithStatus:status andReason:reason]; + } else if ([action isEqualToString:kFWPASyncServerListenCancelled]) { + NSString *pathString = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + [self onListenRevoked:[[FPath alloc] initWith:pathString]]; + } else if ([action isEqualToString:kFWPAsyncServerSecurityDebug]) { + NSString *msg = [body objectForKey:@"msg"]; + if (msg != nil) { + NSArray *msgs = [msg componentsSeparatedByString:@"\n"]; + for (NSString *m in msgs) { + FFWarn(@"I-RDB034031", @"%@", m); + } + } + } else { + // TODO: revoke listens, auth, security debug + FFLog(@"I-RDB034032", @"Unsupported action from server: %@", action); + } +} + +- (void)restoreAuth { + FFLog(@"I-RDB034033", @"Calling restore state"); + + NSAssert(self->connectionState == ConnectionStateConnecting, + @"Wanted to restore auth, but was in wrong state: %d", + self->connectionState); + if (self.authToken == nil) { + FFLog(@"I-RDB034034", @"Not restoring auth because token is nil"); + self->connectionState = ConnectionStateConnected; + [self restoreState]; + } else { + FFLog(@"I-RDB034035", @"Restoring auth"); + self->connectionState = ConnectionStateAuthenticating; + [self sendAuthAndRestoreStateAfterComplete:YES]; + } +} + +- (void)restoreState { + NSAssert(self->connectionState == ConnectionStateConnected, + @"Should be connected if we're restoring state, but we are: %d", + self->connectionState); + + [self.listens enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *query, FOutstandingQuery *outstandingListen, + BOOL *stop) { + FFLog(@"I-RDB034036", @"Restoring listen for %@", query); + [self sendListen:outstandingListen]; + }]; + + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (int i = 0; i < [keys count]; i++) { + if ([self.outstandingPuts objectForKey:[keys objectAtIndex:i]] != nil) { + FFLog(@"I-RDB034037", @"Restoring put: %d", i); + [self sendPut:[keys objectAtIndex:i]]; + } else { + FFLog(@"I-RDB034038", @"Restoring put: skipped nil: %d", i); + } + } + + for (FTupleOnDisconnect *tuple in self.onDisconnectQueue) { + [self sendOnDisconnectAction:tuple.action + forPath:tuple.pathString + withData:tuple.data + andCallback:tuple.onComplete]; + } + [self.onDisconnectQueue removeAllObjects]; +} + +- (NSArray *)removeListen:(FQuerySpec *)query { + NSAssert(query.isDefault || !query.loadsAllData, + @"removeListen called for non-default but complete query"); + + FOutstandingQuery *outstanding = self.listens[query]; + if (!outstanding) { + FFLog(@"I-RDB034039", + @"Trying to remove listener for query %@ but no listener exists", + query); + return @[]; + } else { + [self.listens removeObjectForKey:query]; + return @[ outstanding ]; + } +} + +- (NSArray *)removeAllListensAtPath:(FPath *)path { + FFLog(@"I-RDB034040", @"Removing all listens at path %@", path); + NSMutableArray *removed = [NSMutableArray array]; + NSMutableArray *toRemove = [NSMutableArray array]; + [self.listens + enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *spec, FOutstandingQuery *outstanding, BOOL *stop) { + if ([spec.path isEqual:path]) { + [removed addObject:outstanding]; + [toRemove addObject:spec]; + } + }]; + [self.listens removeObjectsForKeys:toRemove]; + return removed; +} + +- (void)purgeOutstandingWrites { + // We might have unacked puts in our queue that we need to ack now before we + // send out any cancels... + [self ackPuts]; + // Cancel in order + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (NSNumber *key in keys) { + FOutstandingPut *put = self.outstandingPuts[key]; + if (put.onCompleteBlock != nil) { + put.onCompleteBlock(kFErrorWriteCanceled, nil); + } + } + for (FTupleOnDisconnect *onDisconnect in self.onDisconnectQueue) { + if (onDisconnect.onComplete != nil) { + onDisconnect.onComplete(kFErrorWriteCanceled, nil); + } + } + [self.outstandingPuts removeAllObjects]; + [self.onDisconnectQueue removeAllObjects]; +} + +- (void)ackPuts { + for (FTupleCallbackStatus *put in self.putsToAck) { + put.block(put.status, put.errorReason); + } + [self.putsToAck removeAllObjects]; +} + +- (void)handleTimestamp:(NSNumber *)timestamp { + FFLog(@"I-RDB034041", @"Handling timestamp: %@", timestamp); + double timestampDeltaMs = [timestamp doubleValue] - + ([[NSDate date] timeIntervalSince1970] * 1000); + [self.delegate onServerInfoUpdate:self + updates:@{ + kDotInfoServerTimeOffset : [NSNumber + numberWithDouble:timestampDeltaMs] + }]; +} + +- (void)sendStats:(NSDictionary *)stats { + if ([stats count] > 0) { + NSDictionary *request = @{kFWPRequestCounters : stats}; + [self sendAction:kFWPRequestActionStats + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (!statusOk) { + FFLog(@"I-RDB034042", @"Failed to send stats: %@", + errorReason); + } + }]; + } else { + FFLog(@"I-RDB034043", @"Not sending stats because stats are empty"); + } +} + +- (void)sendConnectStats { + NSMutableDictionary *stats = [NSMutableDictionary dictionary]; + +#if TARGET_OS_IOS || TARGET_OS_TV + if (self.config.persistenceEnabled) { + stats[@"persistence.ios.enabled"] = @1; + } +#elif TARGET_OS_OSX + if (self.config.persistenceEnabled) { + stats[@"persistence.osx.enabled"] = @1; + } +#endif + NSString *sdkVersion = + [[FIRDatabase sdkVersion] stringByReplacingOccurrencesOfString:@"." + withString:@"-"]; + NSString *sdkStatName = + [NSString stringWithFormat:@"sdk.objc.%@", sdkVersion]; + stats[sdkStatName] = @1; + FFLog(@"I-RDB034044", @"Sending first connection stats"); + [self sendStats:stats]; +} + +- (NSDictionary *)dumpListens { + return self.listens; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h new file mode 100644 index 0000000..5d957c5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FIndex +, FNodeFilter, FNode; + +@interface FQueryParams : NSObject + +@property(nonatomic, readonly) BOOL limitSet; +@property(nonatomic, readonly) NSInteger limit; + +@property(nonatomic, strong, readonly) NSString *viewFrom; +@property(nonatomic, strong, readonly) id indexStartValue; +@property(nonatomic, strong, readonly) NSString *indexStartKey; +@property(nonatomic, strong, readonly) id indexEndValue; +@property(nonatomic, strong, readonly) NSString *indexEndKey; + +@property(nonatomic, strong, readonly) id index; + +- (BOOL)loadsAllData; +- (BOOL)isDefault; +- (BOOL)isValid; +- (BOOL)hasAnchoredLimit; + +- (FQueryParams *)limitTo:(NSInteger)limit; +- (FQueryParams *)limitToFirst:(NSInteger)newLimit; +- (FQueryParams *)limitToLast:(NSInteger)newLimit; + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)startAt:(id)indexValue; +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)endAt:(id)indexValue; + +- (FQueryParams *)orderBy:(id)index; + ++ (FQueryParams *)defaultInstance; ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict; + +- (BOOL)hasStart; +- (BOOL)hasEnd; + +- (NSDictionary *)wireProtocolParams; +- (BOOL)isViewFromLeft; +- (id)nodeFilter; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m new file mode 100644 index 0000000..c19cfba --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m @@ -0,0 +1,393 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FConstants.h" +#import "FIndex.h" +#import "FIndexedFilter.h" +#import "FLimitedFilter.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FPriorityIndex.h" +#import "FRangedFilter.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" + +@interface FQueryParams () + +@property(nonatomic, readwrite) BOOL limitSet; +@property(nonatomic, readwrite) NSInteger limit; + +@property(nonatomic, strong, readwrite) NSString *viewFrom; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexStartValue; +@property(nonatomic, strong, readwrite) NSString *indexStartKey; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexEndValue; +@property(nonatomic, strong, readwrite) NSString *indexEndKey; + +@property(nonatomic, strong, readwrite) id index; + +@end + +@implementation FQueryParams + ++ (FQueryParams *)defaultInstance { + static FQueryParams *defaultParams = nil; + static dispatch_once_t defaultParamsToken; + dispatch_once(&defaultParamsToken, ^{ + defaultParams = [[FQueryParams alloc] init]; + }); + return defaultParams; +} + +- (id)init { + self = [super init]; + if (self) { + self->_limitSet = NO; + self->_limit = 0; + + self->_viewFrom = nil; + self->_indexStartValue = nil; + self->_indexStartKey = nil; + self->_indexEndValue = nil; + self->_indexEndKey = nil; + + self->_index = [FPriorityIndex priorityIndex]; + } + return self; +} + +/** + * Only valid if hasStart is true + */ +- (id)indexStartValue { + NSAssert([self hasStart], @"Only valid if start has been set"); + return _indexStartValue; +} + +/** + * Only valid if hasStart is true. + * @return The starting key name for the range defined by these query parameters + */ +- (NSString *)indexStartKey { + NSAssert([self hasStart], @"Only valid if start has been set"); + if (_indexStartKey == nil) { + return [FUtilities minName]; + } else { + return _indexStartKey; + } +} + +/** + * Only valid if hasEnd is true. + */ +- (id)indexEndValue { + NSAssert([self hasEnd], @"Only valid if end has been set"); + return _indexEndValue; +} + +/** + * Only valid if hasEnd is true. + * @return The end key name for the range defined by these query parameters + */ +- (NSString *)indexEndKey { + NSAssert([self hasEnd], @"Only valid if end has been set"); + if (_indexEndKey == nil) { + return [FUtilities maxName]; + } else { + return _indexEndKey; + } +} + +/** + * @return true if a limit has been set and has been explicitly anchored + */ +- (BOOL)hasAnchoredLimit { + return self.limitSet && self.viewFrom != nil; +} + +/** + * Only valid to call if limitSet returns true + */ +- (NSInteger)limit { + NSAssert(self.limitSet, @"Only valid if limit has been set"); + return _limit; +} + +- (BOOL)hasStart { + return self->_indexStartValue != nil; +} + +- (BOOL)hasEnd { + return self->_indexEndValue != nil; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)mutableCopy { + FQueryParams *other = [[[self class] alloc] init]; + // Maybe need to do extra copying here + other->_limitSet = _limitSet; + other->_limit = _limit; + other->_indexStartValue = _indexStartValue; + other->_indexStartKey = _indexStartKey; + other->_indexEndValue = _indexEndValue; + other->_indexEndKey = _indexEndKey; + other->_viewFrom = _viewFrom; + other->_index = _index; + return other; +} + +- (FQueryParams *)limitTo:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = nil; + return newParams; +} + +- (FQueryParams *)limitToFirst:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromLeft; + return newParams; +} + +- (FQueryParams *)limitToLast:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromRight; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexStartValue = indexValue; + newParams->_indexStartKey = key; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue { + return [self startAt:indexValue childKey:nil]; +} + +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexEndValue = indexValue; + newParams->_indexEndKey = key; + return newParams; +} + +- (FQueryParams *)endAt:(id)indexValue { + return [self endAt:indexValue childKey:nil]; +} + +- (FQueryParams *)orderBy:(id)newIndex { + FQueryParams *newParams = [self mutableCopy]; + newParams->_index = newIndex; + return newParams; +} + +- (NSDictionary *)wireProtocolParams { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + if ([self hasStart]) { + [dict setObject:[self.indexStartValue valForExport:YES] + forKey:kFQPIndexStartValue]; + + // Don't use property as it will be [MIN-NAME] + if (self->_indexStartKey != nil) { + [dict setObject:self->_indexStartKey forKey:kFQPIndexStartName]; + } + } + + if ([self hasEnd]) { + [dict setObject:[self.indexEndValue valForExport:YES] + forKey:kFQPIndexEndValue]; + + // Don't use property as it will be [MAX-NAME] + if (self->_indexEndKey != nil) { + [dict setObject:self->_indexEndKey forKey:kFQPIndexEndName]; + } + } + + if (self.limitSet) { + [dict setObject:[NSNumber numberWithInteger:self.limit] + forKey:kFQPLimit]; + NSString *vf = self.viewFrom; + if (vf == nil) { + // limit() rather than limitToFirst or limitToLast was called. + // This means that only one of startSet or endSet is true. Use them + // to calculate which side of the view to anchor to. If neither is + // set, Anchor to end + if ([self hasStart]) { + vf = kFQPViewFromLeft; + } else { + vf = kFQPViewFromRight; + } + } + [dict setObject:vf forKey:kFQPViewFrom]; + } + + // For now, priority index is the default, so we only specify if it's some + // other index. + if (![self.index isEqual:[FPriorityIndex priorityIndex]]) { + [dict setObject:[self.index queryDefinition] forKey:kFQPIndex]; + } + + return dict; +} + ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict { + if (dict.count == 0) { + return [FQueryParams defaultInstance]; + } + + FQueryParams *params = [[FQueryParams alloc] init]; + if (dict[kFQPLimit] != nil) { + params->_limitSet = YES; + params->_limit = [dict[kFQPLimit] integerValue]; + } + + if (dict[kFQPIndexStartValue] != nil) { + params->_indexStartValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexStartValue]]; + if (dict[kFQPIndexStartName] != nil) { + params->_indexStartKey = dict[kFQPIndexStartName]; + } + } + + if (dict[kFQPIndexEndValue] != nil) { + params->_indexEndValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexEndValue]]; + if (dict[kFQPIndexEndName] != nil) { + params->_indexEndKey = dict[kFQPIndexEndName]; + } + } + + if (dict[kFQPViewFrom] != nil) { + NSString *viewFrom = dict[kFQPViewFrom]; + if (![viewFrom isEqualToString:kFQPViewFromLeft] && + ![viewFrom isEqualToString:kFQPViewFromRight]) { + [NSException raise:NSInvalidArgumentException + format:@"Unknown view from paramter: %@", viewFrom]; + } + params->_viewFrom = viewFrom; + } + + NSString *index = dict[kFQPIndex]; + if (index != nil) { + params->_index = [FIndex indexFromQueryDefinition:index]; + } + + return params; +} + +- (BOOL)isViewFromLeft { + if (self.viewFrom != nil) { + // Not null, we can just check + return [self.viewFrom isEqualToString:kFQPViewFromLeft]; + } else { + // If start is set, it's view from left. Otherwise not. + return self.hasStart; + } +} + +- (id)nodeFilter { + if (self.loadsAllData) { + return [[FIndexedFilter alloc] initWithIndex:self.index]; + } else if (self.limitSet) { + return [[FLimitedFilter alloc] initWithQueryParams:self]; + } else { + return [[FRangedFilter alloc] initWithQueryParams:self]; + } +} + +- (BOOL)isValid { + return !(self.hasStart && self.hasEnd && self.limitSet && + !self.hasAnchoredLimit); +} + +- (BOOL)loadsAllData { + return !(self.hasStart || self.hasEnd || self.limitSet); +} + +- (BOOL)isDefault { + return [self loadsAllData] && + [self.index isEqual:[FPriorityIndex priorityIndex]]; +} + +- (NSString *)description { + return [[self wireProtocolParams] description]; +} + +- (BOOL)isEqual:(id)obj { + if (self == obj) { + return YES; + } + if (![obj isKindOfClass:[self class]]) { + return NO; + } + FQueryParams *other = (FQueryParams *)obj; + if (self->_limitSet != other->_limitSet) + return NO; + if (self->_limit != other->_limit) + return NO; + if ((self->_index != other->_index) && ! + [self->_index isEqual:other->_index]) + return NO; + if ((self->_indexStartKey != other->_indexStartKey) && + ![self->_indexStartKey isEqualToString:other->_indexStartKey]) + return NO; + if ((self->_indexStartValue != other->_indexStartValue) && + ![self->_indexStartValue isEqual:other->_indexStartValue]) + return NO; + if ((self->_indexEndKey != other->_indexEndKey) && + ![self->_indexEndKey isEqualToString:other->_indexEndKey]) + return NO; + if ((self->_indexEndValue != other->_indexEndValue) && + ![self->_indexEndValue isEqual:other->_indexEndValue]) + return NO; + if ([self isViewFromLeft] != [other isViewFromLeft]) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger result = _limitSet ? _limit : 0; + result = 31 * result + ([self isViewFromLeft] ? 1231 : 1237); + result = 31 * result + [_indexStartKey hash]; + result = 31 * result + [_indexStartValue hash]; + result = 31 * result + [_indexEndKey hash]; + result = 31 * result + [_indexEndValue hash]; + result = 31 * result + [_index hash]; + return result; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h new file mode 100644 index 0000000..2eece87 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FQuerySpec : NSObject + +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FQueryParams *params; + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params; + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path; + +- (id)index; +- (BOOL)isDefault; +- (BOOL)loadsAllData; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m new file mode 100644 index 0000000..c408bf8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQuerySpec.h" + +@interface FQuerySpec () + +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) FQueryParams *params; + +@end + +@implementation FQuerySpec + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params { + self = [super init]; + if (self != nil) { + self->_path = path; + self->_params = params; + } + return self; +} + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path { + return [[FQuerySpec alloc] initWithPath:path + params:[FQueryParams defaultInstance]]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)index { + return self.params.index; +} + +- (BOOL)isDefault { + return self.params.isDefault; +} + +- (BOOL)loadsAllData { + return self.params.loadsAllData; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FQuerySpec class]]) { + return NO; + } + + FQuerySpec *other = (FQuerySpec *)object; + + if (![self.path isEqual:other.path]) { + return NO; + } + + return [self.params isEqual:other.params]; +} + +- (NSUInteger)hash { + return self.path.hash * 31 + self.params.hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FQuerySpec (path: %@, params: %@)", + self.path, self.params]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h new file mode 100644 index 0000000..5f7938a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +/** + * Applies a merge of a snap for a given interval of paths. + * Each leaf in the current node which the relative path lies *after* (the + * optional) start and lies *before or at* (the optional) end will be deleted. + * Each leaf in snap that lies in the interval will be added to the resulting + * node. Nodes outside of the range are ignored. nil for start and end are + * sentinel values that represent -infinity and +infinity respectively (aka + * includes any path). Priorities of children nodes are treated as leaf children + * of that node. + */ +@interface FRangeMerge : NSObject + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates; + +- (id)applyToNode:(id)node; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m new file mode 100644 index 0000000..3dc1576 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m @@ -0,0 +1,134 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangeMerge.h" + +#import "FEmptyNode.h" + +@interface FRangeMerge () + +@property(nonatomic, strong) FPath *optExclusiveStart; +@property(nonatomic, strong) FPath *optInclusiveEnd; +@property(nonatomic, strong) id updates; + +@end + +@implementation FRangeMerge + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates { + self = [super init]; + if (self != nil) { + self->_optExclusiveStart = start; + self->_optInclusiveEnd = end; + self->_updates = updates; + } + return self; +} + +- (id)applyToNode:(id)node { + return [self updateRangeInNode:[FPath empty] + node:node + updates:self.updates]; +} + +- (id)updateRangeInNode:(FPath *)currentPath + node:(id)node + updates:(id)updates { + NSComparisonResult startComparison = + (self.optExclusiveStart == nil) + ? NSOrderedDescending + : [currentPath compare:self.optExclusiveStart]; + NSComparisonResult endComparison = + (self.optInclusiveEnd == nil) + ? NSOrderedAscending + : [currentPath compare:self.optInclusiveEnd]; + BOOL startInNode = self.optExclusiveStart != nil && + [currentPath contains:self.optExclusiveStart]; + BOOL endInNode = self.optInclusiveEnd != nil && + [currentPath contains:self.optInclusiveEnd]; + if (startComparison == NSOrderedDescending && + endComparison == NSOrderedAscending && !endInNode) { + // child is completly contained + return updates; + } else if (startComparison == NSOrderedDescending && endInNode && + [updates isLeafNode]) { + return updates; + } else if (startComparison == NSOrderedDescending && + endComparison == NSOrderedSame) { + NSAssert(endInNode, @"End not in node"); + NSAssert(![updates isLeafNode], @"Found leaf node update, this case " + @"should have been handled above."); + if ([node isLeafNode]) { + // Update node was not a leaf node, so we can delete it + return [FEmptyNode emptyNode]; + } else { + // Unaffected by range, ignore + return node; + } + } else if (startInNode || endInNode) { + // There is a partial update we need to do, so collect all relevant + // children + NSMutableSet *allChildren = [NSMutableSet set]; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + [updates enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + + __block id newNode = node; + void (^action)(id, BOOL *) = ^void(NSString *key, BOOL *stop) { + id currentChild = [node getImmediateChild:key]; + id updatedChild = + [self updateRangeInNode:[currentPath childFromString:key] + node:currentChild + updates:[updates getImmediateChild:key]]; + // Only need to update if the node changed + if (updatedChild != currentChild) { + newNode = [newNode updateImmediateChild:key + withNewChild:updatedChild]; + } + }; + + [allChildren enumerateObjectsUsingBlock:action]; + + // Add priority last, so the node is not empty when applying + if (!updates.getPriority.isEmpty || !node.getPriority.isEmpty) { + BOOL stop = NO; + action(@".priority", &stop); + } + return newNode; + } else { + // Unaffected by this range + NSAssert(endComparison == NSOrderedDescending || + startComparison <= NSOrderedSame, + @"Invalid range for update"); + return node; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"RangeMerge (optExclusiveStart = %@, " + @"optExclusiveEng = %@, updates = %@)", + self.optExclusiveStart, + self.optInclusiveEnd, self.updates]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h new file mode 100644 index 0000000..4e3899a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h @@ -0,0 +1,93 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FPersistentConnection.h" +#import "FRepoInfo.h" +#import "FTupleUserCallback.h" +#import + +@class FQuerySpec; +@class FPersistence; +@class FAuthenticationManager; +@class FIRDatabaseConfig; +@protocol FEventRegistration; +@class FCompoundWrite; +@protocol FClock; +@class FIRDatabase; + +@interface FRepo : NSObject + +@property(nonatomic, strong) FIRDatabaseConfig *config; + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete; +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; +- (void)purgeOutstandingWrites; + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced; + +- (NSString *)name; +- (NSTimeInterval)serverTime; + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; + +// Disconnect methods +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; + +// Connection Management. +- (void)interrupt; +- (void)resume; + +// Transactions +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally; + +// Testing methods +- (NSDictionary *)dumpListens; +- (void)dispose; +- (void)setHijackHash:(BOOL)hijack; + +@property(nonatomic, strong, readonly) FAuthenticationManager *auth; +@property(nonatomic, strong, readonly) FIRDatabase *database; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m new file mode 100644 index 0000000..5d894bf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m @@ -0,0 +1,1450 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FAtomicNumber.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FIRDataSnapshot.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FIRMutableData.h" +#import "FIRMutableData_Private.h" +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" +#import "FLevelDBStorageEngine.h" +#import "FListenProvider.h" +#import "FPersistenceManager.h" +#import "FQuerySpec.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FRepo_Private.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTree.h" +#import "FTupleNodePath.h" +#import "FTupleSetIdPath.h" +#import "FTupleTransaction.h" +#import "FValueEventRegistration.h" +#import "FWriteRecord.h" +#import +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FRepo () + +@property(nonatomic, strong) FOffsetClock *serverClock; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FIRDatabase *database; +@property(nonatomic, strong, readwrite) FAuthenticationManager *auth; +@property(nonatomic, strong) FSyncTree *infoSyncTree; +@property(nonatomic) NSInteger writeIdCounter; +@property(nonatomic) BOOL hijackHash; +@property(nonatomic, strong) FTree *transactionQueueTree; +@property(nonatomic) BOOL loggedTransactionPersistenceWarning; + +/** + * Test only. For load testing the server. + */ +@property(nonatomic, strong) id (^interceptServerDataCallback) + (NSString *pathString, id data); +@end + +@implementation FRepo + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + self = [super init]; + if (self) { + self.repoInfo = info; + self.config = config; + self.database = database; + + // Access can occur outside of shared queue, so the clock needs to be + // initialized here + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] offset:0]; + + self.connection = [[FPersistentConnection alloc] + initWithRepoInfo:self.repoInfo + dispatchQueue:[FIRDatabaseQuery sharedQueue] + config:self.config]; + + // Needs to be called before authentication manager is instantiated + self.eventRaiser = + [[FEventRaiser alloc] initWithQueue:self.config.callbackQueue]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self deferredInit]; + }); + } + return self; +} + +- (void)deferredInit { + // TODO: cleanup on dealloc + __weak FRepo *weakSelf = self; + [self.config.authTokenProvider listenForTokenChanges:^(NSString *token) { + [weakSelf.connection refreshAuthToken:token]; + }]; + + // Open connection now so that by the time we are connected the deferred + // init has run This relies on the fact that all callbacks run on repos + // queue + self.connection.delegate = self; + [self.connection open]; + + self.dataUpdateCount = 0; + self.rangeMergeUpdateCount = 0; + self.interceptServerDataCallback = nil; + + if (self.config.persistenceEnabled) { + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", self.repoInfo.host, + self.repoInfo.namespace]; + NSString *persistencePrefix = + [NSString stringWithFormat:@"%@/%@", self.config.sessionIdentifier, + repoHashString]; + + id cachePolicy = [[FLRUCachePolicy alloc] + initWithMaxSize:self.config.persistenceCacheSizeBytes]; + + id engine; + if (self.config.forceStorageEngine != nil) { + engine = self.config.forceStorageEngine; + } else { + FLevelDBStorageEngine *levelDBEngine = + [[FLevelDBStorageEngine alloc] initWithPath:persistencePrefix]; + // We need the repo info to run the legacy migration. Future + // migrations will be managed by the database itself Remove this + // once we are confident that no-one is using legacy migration + // anymore... + [levelDBEngine runLegacyMigration:self.repoInfo]; + engine = levelDBEngine; + } + + self.persistenceManager = + [[FPersistenceManager alloc] initWithStorageEngine:engine + cachePolicy:cachePolicy]; + } else { + self.persistenceManager = nil; + } + + [self initTransactions]; + + // A list of data pieces and paths to be set when this client disconnects + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + self.infoData = [[FSnapshotHolder alloc] init]; + + FListenProvider *infoListenProvider = [[FListenProvider alloc] init]; + infoListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + NSArray *infoEvents = @[]; + FRepo *strongSelf = weakSelf; + id node = [strongSelf.infoData getNode:query.path]; + // This is possibly a hack, but we have different semantics for .info + // endpoints. We don't raise null events on initial data... + if (![node isEmpty]) { + infoEvents = + [strongSelf.infoSyncTree applyServerOverwriteAtPath:query.path + newData:node]; + [strongSelf.eventRaiser raiseCallback:^{ + onComplete(kFWPResponseForActionStatusOk); + }]; + } + return infoEvents; + }; + infoListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tagId) { + }; + self.infoSyncTree = + [[FSyncTree alloc] initWithListenProvider:infoListenProvider]; + + FListenProvider *serverListenProvider = [[FListenProvider alloc] init]; + serverListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + [weakSelf.connection listen:query + tagId:tagId + hash:hash + onComplete:^(NSString *status) { + NSArray *events = onComplete(status); + [weakSelf.eventRaiser raiseEvents:events]; + }]; + // No synchronous events for network-backed sync trees + return @[]; + }; + serverListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tag) { + [weakSelf.connection unlisten:query tagId:tag]; + }; + self.serverSyncTree = + [[FSyncTree alloc] initWithPersistenceManager:self.persistenceManager + listenProvider:serverListenProvider]; + + [self restoreWrites]; + + [self updateInfo:kDotInfoConnected withValue:@NO]; + + [self setupNotifications]; +} + +- (void)restoreWrites { + NSArray *writes = self.persistenceManager.userWrites; + + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + __block NSInteger lastWriteId = NSIntegerMin; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + NSInteger writeId = write.writeId; + fbt_void_nsstring_nsstring callback = + ^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:write.path + status:status + message:@"Persisted write"]; + [self ackWrite:writeId + rerunTransactionsAtPath:write.path + status:status]; + }; + if (lastWriteId >= writeId) { + [NSException raise:NSInternalInconsistencyException + format:@"Restored writes were not in order!"]; + } + lastWriteId = writeId; + self.writeIdCounter = writeId + 1; + if ([write isOverwrite]) { + FFLog(@"I-RDB038001", @"Restoring overwrite with id %ld", + (long)write.writeId); + [self.connection putData:[write.overwrite valForExport:YES] + forPath:[write.path toString] + withHash:nil + withCallback:callback]; + id resolved = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withServerValues:serverValues]; + [self.serverSyncTree applyUserOverwriteAtPath:write.path + newData:resolved + writeId:writeId + isVisible:YES]; + } else { + FFLog(@"I-RDB038002", @"Restoring merge with id %ld", + (long)write.writeId); + [self.connection mergeData:[write.merge valForExport:YES] + forPath:[write.path toString] + withCallback:callback]; + FCompoundWrite *resolved = + [FServerValues resolveDeferredValueCompoundWrite:write.merge + withServerValues:serverValues]; + [self.serverSyncTree applyUserMergeAtPath:write.path + changedChildren:resolved + writeId:writeId]; + } + }]; +} + +- (NSString *)name { + return self.repoInfo.namespace; +} + +- (NSString *)description { + return [self.repoInfo description]; +} + +- (void)interrupt { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; +} + +- (void)resume { + [self.connection resumeForReason:kFInterruptReasonRepoInterrupt]; +} + +// NOTE: Typically if you're calling this, you should be in an @autoreleasepool +// block to make sure that ARC kicks in and cleans up things no longer +// referenced (i.e. pendingPutsDB). +- (void)dispose { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; + + // We need to nil out any references to LevelDB, to make sure the + // LevelDB exclusive locks are released. + [self.persistenceManager close]; +} + +- (NSInteger)nextWriteId { + return self->_writeIdCounter++; +} + +- (NSTimeInterval)serverTime { + return [self.serverClock currentTime]; +} + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete { + id value = [node valForExport:YES]; + FFLog(@"I-RDB038003", @"Setting: %@ with %@ pri: %@", [path toString], + [value description], [[node getPriority] val]); + + // TODO: Optimize this behavior to either (a) store flag to skip resolving + // where possible and / or (b) store unresolved paths on JSON parse + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id newNode = + [FServerValues resolveDeferredValueSnapshot:node + withServerValues:serverValues]; + + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserOverwrite:node + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserOverwriteAtPath:path + newData:newNode + writeId:writeId + isVisible:YES]; + [self.eventRaiser raiseEvents:events]; + + [self.connection putData:value + forPath:[path toString] + withHash:nil + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"setValue: or removeValue:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:onComplete + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + FPath *affectedPath = [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; +} + +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + NSDictionary *values = [nodes valForExport:YES]; + + FFLog(@"I-RDB038004", @"Updating: %@ with %@", [path toString], + [values description]); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + FCompoundWrite *resolved = + [FServerValues resolveDeferredValueCompoundWrite:nodes + withServerValues:serverValues]; + + if (!resolved.isEmpty) { + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserMerge:nodes + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserMergeAtPath:path + changedChildren:resolved + writeId:writeId]; + [self.eventRaiser raiseEvents:events]; + + [self.connection mergeData:values + forPath:[path description] + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"updateChildValues:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + [nodes enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + FPath *pathFromRoot = [path child:childPath]; + FFLog(@"I-RDB038005", @"Cancelling transactions at path: %@", + pathFromRoot); + FPath *affectedPath = [self abortTransactionsAtPath:pathFromRoot + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + } else { + FFLog(@"I-RDB038006", @"update called with empty data. Doing nothing"); + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectCancelPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect forgetPath:path]; + } else { + FFLog(@"I-RDB038007", + @"cancelDisconnectOperations: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectPutData:[node valForExport:YES] + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect rememberData:node onPath:path]; + } else { + FFWarn(@"I-RDB038008", + @"onDisconnectSetValue: or " + @"onDisconnectRemoveValue: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + if (!nodes.isEmpty) { + NSDictionary *values = [nodes valForExport:YES]; + + [self.connection + onDisconnectMergeData:values + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = [status + isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [nodes enumerateWrites:^(FPath *relativePath, + id nodeUnresolved, + BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self.onDisconnect rememberData:nodeUnresolved + onPath:childPath]; + }]; + } else { + FFWarn(@"I-RDB038009", + @"onDisconnectUpdateChildValues: at %@ " + @"failed %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + } else { + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)purgeOutstandingWrites { + FFLog(@"I-RDB038010", @"Purging outstanding writes"); + NSArray *events = [self.serverSyncTree removeAllWrites]; + [self.eventRaiser raiseEvents:events]; + // Abort any transactions + [self abortTransactionsAtPath:[FPath empty] error:kFErrorWriteCanceled]; + // Remove outstanding writes from connection + [self.connection purgeOutstandingWrites]; +} + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } else { + events = [self.serverSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + // These are guaranteed not to raise events, since we're not passing in a + // cancelError. However we can future-proof a little bit by handling the + // return values anyways. + FFLog(@"I-RDB038011", @"Removing event registration with hande: %lu", + (unsigned long)eventRegistration.handle); + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } else { + events = [self.serverSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced { + NSAssert(![[query.path getFront] isEqualToString:kDotInfoPrefix], + @"Can't keep .info tree synced!"); + [self.serverSyncTree keepQuery:query synced:synced]; +} + +- (void)updateInfo:(NSString *)pathString withValue:(id)value { + // hack to make serverTimeOffset available in a threadsafe way. Property is + // marked as atomic + if ([pathString isEqualToString:kDotInfoServerTimeOffset]) { + NSTimeInterval offset = [(NSNumber *)value doubleValue] / 1000.0; + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] + offset:offset]; + } + + FPath *path = [[FPath alloc] + initWith:[NSString + stringWithFormat:@"%@/%@", kDotInfoPrefix, pathString]]; + id newNode = [FSnapshotUtilities nodeFrom:value]; + [self.infoData updateSnapshot:path withNewSnapshot:newNode]; + NSArray *events = [self.infoSyncTree applyServerOverwriteAtPath:path + newData:newNode]; + [self.eventRaiser raiseEvents:events]; +} + +- (void)callOnComplete:(fbt_void_nserror_ref)onComplete + withStatus:(NSString *)status + errorReason:(NSString *)errorReason + andPath:(FPath *)path { + if (onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + BOOL statusOk = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSError *err = nil; + if (!statusOk) { + err = [FUtilities errorForStatus:status andReason:errorReason]; + } + [self.eventRaiser raiseCallback:^{ + onComplete(err, ref); + }]; + } +} + +- (void)ackWrite:(NSInteger)writeId + rerunTransactionsAtPath:(FPath *)path + status:(NSString *)status { + if ([status isEqualToString:kFErrorWriteCanceled]) { + // This write was already removed, we just need to ignore it... + } else { + BOOL success = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSArray *clearEvents = + [self.serverSyncTree ackUserWriteWithWriteId:writeId + revert:!success + persist:YES + clock:self.serverClock]; + if ([clearEvents count] > 0) { + [self rerunTransactionsForPath:path]; + } + [self.eventRaiser raiseEvents:clearEvents]; + } +} + +- (void)warnIfWriteFailedAtPath:(FPath *)path + status:(NSString *)status + message:(NSString *)message { + if (!([status isEqualToString:kFWPResponseForActionStatusOk] || + [status isEqualToString:kFErrorWriteCanceled])) { + FFWarn(@"I-RDB038012", @"%@ at %@ failed: %@", message, path, status); + } +} + +#pragma mark - +#pragma mark FPersistentConnectionDelegate methods + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)data + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB038013", @"onDataUpdateForPath: %@ withMessage: %@", + pathString, data); + + // For testing. + self.dataUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + data = self.interceptServerDataCallback + ? self.interceptServerDataCallback(pathString, data) + : data; + NSArray *events = nil; + + if (tagId != nil) { + if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *taggedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = + [self.serverSyncTree applyTaggedQueryMergeAtPath:path + changedChildren:taggedChildren + tagId:tagId]; + } else { + id taggedSnap = [FSnapshotUtilities nodeFrom:data]; + events = + [self.serverSyncTree applyTaggedQueryOverwriteAtPath:path + newData:taggedSnap + tagId:tagId]; + } + } else if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *changedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = [self.serverSyncTree applyServerMergeAtPath:path + changedChildren:changedChildren]; + } else { + id snap = [FSnapshotUtilities nodeFrom:data]; + events = [self.serverSyncTree applyServerOverwriteAtPath:path + newData:snap]; + } + + if ([events count] > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)pathString + tagId:(NSNumber *)tag { + FFLog(@"I-RDB038014", @"onRangeMerge: %@ => %@", pathString, ranges); + + // For testing + self.rangeMergeUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + NSArray *events; + if (tag != nil) { + events = [self.serverSyncTree applyTaggedServerRangeMergeAtPath:path + updates:ranges + tagId:tag]; + } else { + events = [self.serverSyncTree applyServerRangeMergeAtPath:path + updates:ranges]; + } + if (events.count > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onConnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@YES]; +} + +- (void)onDisconnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@NO]; + [self runOnDisconnectEvents]; +} + +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates { + for (NSString *key in updates) { + id val = [updates objectForKey:key]; + [self updateInfo:key withValue:val]; + } +} + +- (void)setupNotifications { + NSString *const *backgroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationDidEnterBackgroundNotification"); + if (backgroundConstant) { + FFLog(@"I-RDB038015", @"Registering for background notification."); + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didEnterBackground) + name:*backgroundConstant + object:nil]; + } else { + FFLog(@"I-RDB038016", + @"Skipped registering for background notification."); + } +} + +- (void)didEnterBackground { + if (!self.config.persistenceEnabled) + return; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + // The idea is to wait until any outstanding sets get written to disk. Since + // the sets might still be in our dispatch queue, we wait for the dispatch + // queue to catch up and for persistence to catch up. This may be + // undesirable though. The dispatch queue might just be processing a bunch + // of incoming data or something. We might want to keep track of whether + // there are any unpersisted sets or something. + FFLog(@"I-RDB038017", + @"Entering background. Starting background task to finish work."); + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + assert(uiApplicationClass); // If we are here, we should be on iOS and + // UIApplication should be available. + + UIApplication *application = [uiApplicationClass sharedApplication]; + __block UIBackgroundTaskIdentifier bgTask = + [application beginBackgroundTaskWithExpirationHandler:^{ + [application endBackgroundTask:bgTask]; + }]; + + NSDate *start = [NSDate date]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + NSTimeInterval finishTime = [start timeIntervalSinceNow] * -1; + FFLog(@"I-RDB038018", @"Background task completed. Queue time: %f", + finishTime); + [application endBackgroundTask:bgTask]; + }); +#endif +} + +#pragma mark - +#pragma mark Internal methods + +/** + * Applies all the changes stored up in the onDisconnect tree + */ +- (void)runOnDisconnectEvents { + FFLog(@"I-RDB038019", @"Running onDisconnectEvents"); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + FSparseSnapshotTree *resolvedTree = + [FServerValues resolveDeferredValueTree:self.onDisconnect + withServerValues:serverValues]; + NSMutableArray *events = [[NSMutableArray alloc] init]; + + [resolvedTree + forEachTreeAtPath:[FPath empty] + do:^(FPath *path, id node) { + [events addObjectsFromArray: + [self.serverSyncTree + applyServerOverwriteAtPath:path + newData:node]]; + FPath *affectedPath = + [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + [self.eventRaiser raiseEvents:events]; +} + +- (NSDictionary *)dumpListens { + return [self.connection dumpListens]; +} + +#pragma mark - +#pragma mark Transactions + +/** + * Setup the transaction data structures + */ +- (void)initTransactions { + self.transactionQueueTree = [[FTree alloc] init]; + self.hijackHash = NO; + self.loggedTransactionPersistenceWarning = NO; +} + +/** + * Creates a new transaction, add its to the transactions we're tracking, and + * sends it to the server if possible + */ +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally { + if (self.config.persistenceEnabled && + !self.loggedTransactionPersistenceWarning) { + self.loggedTransactionPersistenceWarning = YES; + FFInfo(@"I-RDB038020", + @"runTransactionBlock: usage detected while persistence is " + @"enabled. Please be aware that transactions " + @"*will not* be persisted across app restarts. " + @"See " + @"https://www.firebase.com/docs/ios/guide/" + @"offline-capabilities.html#section-handling-transactions-" + @"offline for more details."); + } + + FIRDatabaseReference *watchRef = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + // make sure we're listening on this node + // Note: we can't do this asynchronously. To preserve event ordering, it has + // to be done in this block. This is ok, this block is guaranteed to be our + // own event loop + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + fbt_void_datasnapshot cb = ^(FIRDataSnapshot *snapshot) { + }; + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self + handle:handle + callback:cb + cancelCallback:nil]; + [watchRef.repo addEventRegistration:registration + forQuery:watchRef.querySpec]; + fbt_void_void unwatcher = ^{ + [watchRef removeObserverWithHandle:handle]; + }; + + // Save all the data that represents this transaction + FTupleTransaction *transaction = [[FTupleTransaction alloc] init]; + transaction.path = path; + transaction.update = update; + transaction.onComplete = onComplete; + transaction.status = FTransactionInitializing; + transaction.order = [FUtilities LUIDGenerator]; + transaction.applyLocally = applyLocally; + transaction.retryCount = 0; + transaction.unwatcher = unwatcher; + transaction.currentWriteId = nil; + transaction.currentInputSnapshot = nil; + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + + // Run transaction initially + id currentState = [self latestStateAtPath:path excludeWriteIds:nil]; + transaction.currentInputSnapshot = currentState; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentState]; + FIRTransactionResult *result = transaction.update(mutableCurrent); + + if (!result.isSuccess) { + // Abort the transaction + transaction.unwatcher(); + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + if (transaction.onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self + path:transaction.path]; + FIndexedNode *indexedNode = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + [self.eventRaiser raiseCallback:^{ + transaction.onComplete(nil, NO, snap); + }]; + } + } else { + // Note: different from js. We don't need to validate, FIRMutableData + // does validation. We also don't have to worry about priorities. Just + // mark as run and add to queue. + transaction.status = FTransactionRun; + FTree *queueNode = [self.transactionQueueTree subTree:transaction.path]; + NSMutableArray *nodeQueue = [queueNode getValue]; + if (nodeQueue == nil) { + nodeQueue = [[NSMutableArray alloc] init]; + } + [nodeQueue addObject:transaction]; + [queueNode setValue:nodeQueue]; + + // Update visibleData and raise events + // Note: We intentionally raise events after updating all of our + // transaction state, since the user could start new transactions from + // the event callbacks + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id newValUnresolved = [result.update nodeValue]; + id newVal = + [FServerValues resolveDeferredValueSnapshot:newValUnresolved + withServerValues:serverValues]; + transaction.currentOutputSnapshotRaw = newValUnresolved; + transaction.currentOutputSnapshotResolved = newVal; + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + + NSArray *events = [self.serverSyncTree + applyUserOverwriteAtPath:path + newData:newVal + writeId:[transaction.currentWriteId integerValue] + isVisible:transaction.applyLocally]; + [self.eventRaiser raiseEvents:events]; + + [self sendAllReadyTransactions]; + } +} + +/** + * @param writeIdsToExclude A specific set to exclude + */ +- (id)latestStateAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + id latestState = + [self.serverSyncTree calcCompleteEventCacheAtPath:path + excludeWriteIds:writeIdsToExclude]; + return latestState ? latestState : [FEmptyNode emptyNode]; +} + +/** + * Sends any already-run transactions that aren't waiting for outstanding + * transactions to complete. + * + * Externally, call the version with no arguments. + * Internally, calls itself recursively with a particular transactionQueueTree + * node to recurse through the tree + */ +- (void)sendAllReadyTransactions { + FTree *node = self.transactionQueueTree; + + [self pruneCompletedTransactionsBelowNode:node]; + [self sendReadyTransactionsForTree:node]; +} + +- (void)sendReadyTransactionsForTree:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + queue = [self buildTransactionQueueAtNode:node]; + NSAssert([queue count] > 0, @"Sending zero length transaction queue"); + + NSUInteger notRunIndex = [queue + indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { + return ((FTupleTransaction *)obj).status != FTransactionRun; + }]; + + // If they're all run (and not sent), we can send them. Else, we must + // wait. + if (notRunIndex == NSNotFound) { + [self sendTransactionQueue:queue atPath:node.path]; + } + } else if ([node hasChildren]) { + [node forEachChild:^(FTree *child) { + [self sendReadyTransactionsForTree:child]; + }]; + } +} + +/** + * Given a list of run transactions, send them to the server and then handle the + * result (success or failure). + */ +- (void)sendTransactionQueue:(NSMutableArray *)queue atPath:(FPath *)path { + // Mark transactions as sent and bump the retry count + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + id latestState = [self latestStateAtPath:path + excludeWriteIds:writeIdsToExclude]; + id snapToSend = latestState; + NSString *latestHash = [latestState dataHash]; + for (FTupleTransaction *transaction in queue) { + NSAssert( + transaction.status == FTransactionRun, + @"[FRepo sendTransactionQueue:] items in queue should all be run."); + FFLog(@"I-RDB038021", @"Transaction at %@ set to SENT", + transaction.path); + transaction.status = FTransactionSent; + transaction.retryCount++; + FPath *relativePath = [FPath relativePathFrom:path to:transaction.path]; + // If we've gotten to this point, the output snapshot must be defined. + snapToSend = + [snapToSend updateChild:relativePath + withNewChild:transaction.currentOutputSnapshotRaw]; + } + + id dataToSend = [snapToSend valForExport:YES]; + NSString *pathToSend = [path description]; + latestHash = self.hijackHash ? @"badhash" : latestHash; + + // Send the put + [self.connection + putData:dataToSend + forPath:pathToSend + withHash:latestHash + withCallback:^(NSString *status, NSString *errorReason) { + FFLog(@"I-RDB038022", @"Transaction put response: %@ : %@", + pathToSend, status); + + NSMutableArray *events = [[NSMutableArray alloc] init]; + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + // Queue up the callbacks and fire them after cleaning up all of + // our transaction state, since the callback could trigger more + // transactions or sets. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionCompleted; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:NO + persist:NO + clock:self.serverClock]]; + if (transaction.onComplete) { + // We never unset the output snapshot, and given that this + // transaction is complete, it should be set + id node = + transaction.currentOutputSnapshotResolved; + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:node]; + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + fbt_void_void cb = ^{ + transaction.onComplete(nil, YES, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + transaction.unwatcher(); + } + + // Now remove the completed transactions. + [self + pruneCompletedTransactionsBelowNode:[self.transactionQueueTree + subTree:path]]; + // There may be pending transactions that we can now send. + [self sendAllReadyTransactions]; + + // Finally, trigger onComplete callbacks + [self.eventRaiser raiseCallbacks:callbacks]; + } else { + // transactions are no longer sent. Update their status + // appropriately. + if ([status + isEqualToString:kFWPResponseForActionStatusDataStale]) { + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + transaction.status = FTransactionNeedsAbort; + } else { + transaction.status = FTransactionRun; + } + } + } else { + FFWarn(@"I-RDB038023", + @"runTransactionBlock: at %@ failed: %@", path, + status); + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionNeedsAbort; + [transaction setAbortStatus:status reason:errorReason]; + } + } + } + + [self rerunTransactionsForPath:path]; + [self.eventRaiser raiseEvents:events]; + }]; +} + +/** + * Finds all transactions dependent on the data at changed Path and reruns them. + * + * Should be called any time cached data changes. + * + * Return the highest path that was affected by rerunning transactions. This is + * the path at which events need to be raised for. + */ +- (FPath *)rerunTransactionsForPath:(FPath *)changedPath { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return changedPath; + } else { + FTree *rootMostTransactionNode = + [self getAncestorTransactionNodeForPath:changedPath]; + FPath *path = rootMostTransactionNode.path; + + NSArray *queue = + [self buildTransactionQueueAtNode:rootMostTransactionNode]; + [self rerunTransactionQueue:queue atPath:path]; + + return path; + } +} + +/** + * Does all the work of rerunning transactions (as well as cleans up aborted + * transactions and whatnot). + */ +- (void)rerunTransactionQueue:(NSArray *)queue atPath:(FPath *)path { + if (queue.count == 0) { + return; // nothing to do + } + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since the callback could trigger more transactions or + // sets. + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Ignore, by default, all of the sets in this queue, since we're re-running + // all of them. However, we want to include the results of new sets + // triggered as part of this re-run, so we don't want to ignore a range, + // just these specific sets. + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + + for (FTupleTransaction *transaction in queue) { + FPath *relativePath __unused = + [FPath relativePathFrom:path to:transaction.path]; + BOOL abortTransaction = NO; + NSAssert(relativePath != nil, @"[FRepo rerunTransactionsQueue:] " + @"relativePath should not be null."); + + if (transaction.status == FTransactionNeedsAbort) { + abortTransaction = YES; + if (![transaction.abortStatus + isEqualToString:kFErrorWriteCanceled]) { + NSArray *ackEvents = [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]; + [events addObjectsFromArray:ackEvents]; + } + } else if (transaction.status == FTransactionRun) { + if (transaction.retryCount >= kFTransactionMaxRetries) { + abortTransaction = YES; + [transaction setAbortStatus:kFTransactionTooManyRetries + reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // This code reruns a transaction + id currentNode = + [self latestStateAtPath:transaction.path + excludeWriteIds:writeIdsToExclude]; + transaction.currentInputSnapshot = currentNode; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentNode]; + FIRTransactionResult *result = + transaction.update(mutableCurrent); + if (result.isSuccess) { + NSNumber *oldWriteId = transaction.currentWriteId; + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + + id newVal = [result.update nodeValue]; + id newValResolved = [FServerValues + resolveDeferredValueSnapshot:newVal + withServerValues:serverValues]; + + transaction.currentOutputSnapshotRaw = newVal; + transaction.currentOutputSnapshotResolved = newValResolved; + + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + // Mutates writeIdsToExclude in place + [writeIdsToExclude removeObject:oldWriteId]; + [events + addObjectsFromArray: + [self.serverSyncTree + applyUserOverwriteAtPath:transaction.path + newData: + transaction + .currentOutputSnapshotResolved + writeId: + [transaction.currentWriteId + integerValue] + isVisible:transaction + .applyLocally]]; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[oldWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + abortTransaction = YES; + // The user aborted the transaction. JS treats ths as a + // "nodata" abort, but it's not an error, so we don't send + // them an error. + [transaction setAbortStatus:nil reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } + } + } + + [self.eventRaiser raiseEvents:events]; + events = nil; + + if (abortTransaction) { + // Abort + transaction.status = FTransactionCompleted; + transaction.unwatcher(); + if (transaction.onComplete) { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIndexedNode *lastInput = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:lastInput]; + fbt_void_void cb = ^{ + // Unlike JS, no need to check for "nodata" because ObjC has + // abortError = nil + transaction.onComplete(transaction.abortError, NO, snap); + }; + [callbacks addObject:[cb copy]]; + } + } + } + + // Note: unlike current js client, we don't need to preserve priority. Users + // can set priority via FIRMutableData + + // Clean up completed transactions. + [self pruneCompletedTransactionsBelowNode:self.transactionQueueTree]; + + // Now fire callbacks, now that we're in a good, known state. + [self.eventRaiser raiseCallbacks:callbacks]; + + // Try to send the transaction result to the server + [self sendAllReadyTransactions]; +} + +- (FTree *)getAncestorTransactionNodeForPath:(FPath *)path { + FTree *transactionNode = self.transactionQueueTree; + + while (![path isEmpty] && [transactionNode getValue] == nil) { + NSString *front = [path getFront]; + transactionNode = + [transactionNode subTree:[[FPath alloc] initWith:front]]; + path = [path popFront]; + } + + return transactionNode; +} + +- (NSMutableArray *)buildTransactionQueueAtNode:(FTree *)node { + NSMutableArray *queue = [[NSMutableArray alloc] init]; + [self aggregateTransactionQueuesForNode:node andQueue:queue]; + + [queue sortUsingComparator:^NSComparisonResult(FTupleTransaction *obj1, + FTupleTransaction *obj2) { + return [obj1.order compare:obj2.order]; + }]; + + return queue; +} + +- (void)aggregateTransactionQueuesForNode:(FTree *)node + andQueue:(NSMutableArray *)queue { + NSArray *nodeQueue = [node getValue]; + [queue addObjectsFromArray:nodeQueue]; + + [node forEachChild:^(FTree *child) { + [self aggregateTransactionQueuesForNode:child andQueue:queue]; + }]; +} + +/** + * Remove COMPLETED transactions at or below this node in the + * transactionQueueTree + */ +- (void)pruneCompletedTransactionsBelowNode:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + int i = 0; + // remove all of the completed transactions from the queue + while (i < queue.count) { + FTupleTransaction *transaction = [queue objectAtIndex:i]; + if (transaction.status == FTransactionCompleted) { + [queue removeObjectAtIndex:i]; + } else { + i++; + } + } + if (queue.count > 0) { + [node setValue:queue]; + } else { + [node setValue:nil]; + } + } + + [node forEachChildMutationSafe:^(FTree *child) { + [self pruneCompletedTransactionsBelowNode:child]; + }]; +} + +/** + * Aborts all transactions on ancestors or descendants of the specified path. + * Called when doing a setValue: or updateChildValues: since we consider them + * incompatible with transactions + * + * @param path path for which we want to abort related transactions. + */ +- (FPath *)abortTransactionsAtPath:(FPath *)path error:(NSString *)error { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return path; + } else { + FPath *affectedPath = + [self getAncestorTransactionNodeForPath:path].path; + + FTree *transactionNode = [self.transactionQueueTree subTree:path]; + [transactionNode forEachAncestor:^BOOL(FTree *ancestor) { + [self abortTransactionsAtNode:ancestor error:error]; + return NO; + }]; + + [self abortTransactionsAtNode:transactionNode error:error]; + + [transactionNode forEachDescendant:^(FTree *child) { + [self abortTransactionsAtNode:child error:error]; + }]; + + return affectedPath; + } +} + +/** + * Abort transactions stored in this transactions queue node. + * + * @param node Node to abort transactions for. + */ +- (void)abortTransactionsAtNode:(FTree *)node error:(NSString *)error { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since can be immediately aborted and removed. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Go through queue. Any already-sent transactions must be marked for + // abort, while the unsent ones can be immediately aborted and removed + NSMutableArray *events = [[NSMutableArray alloc] init]; + int lastSent = -1; + // Note: all of the sent transactions will be at the front of the queue, + // so safe to increment lastSent + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + // No-op. already marked. + } else if (transaction.status == FTransactionSent) { + // Mark this transaction for abort when it returns + lastSent++; + transaction.status = FTransactionSentNeedsAbort; + [transaction setAbortStatus:error reason:nil]; + } else { + // we can abort this immediately + transaction.unwatcher(); + if ([error isEqualToString:kFTransactionSet]) { + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // If it was cancelled it was already removed from the sync + // tree, no need to ack + NSAssert([error isEqualToString:kFErrorWriteCanceled], nil); + } + + if (transaction.onComplete) { + NSError *abortReason = [FUtilities errorForStatus:error + andReason:nil]; + FIRDataSnapshot *snapshot = nil; + fbt_void_void cb = ^{ + transaction.onComplete(abortReason, NO, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + } + } + if (lastSent == -1) { + // We're not waiting for any sent transactions. We can clear the + // queue. + [node setValue:nil]; + } else { + // Remove the transactions we aborted + NSRange theRange; + theRange.location = lastSent + 1; + theRange.length = queue.count - theRange.location; + [queue removeObjectsInRange:theRange]; + } + + // Now fire the callbacks + [self.eventRaiser raiseEvents:events]; + [self.eventRaiser raiseCallbacks:callbacks]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h new file mode 100644 index 0000000..46e9b8b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FRepoInfo : NSObject + +@property(nonatomic, readonly, strong) NSString *host; +@property(nonatomic, readonly, strong) NSString *namespace; +@property(nonatomic, strong) NSString *internalHost; +@property(nonatomic, readonly) bool secure; + +- (id)initWithHost:(NSString *)host + isSecure:(bool)secure + withNamespace:(NSString *)namespace; + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID; +- (NSString *)connectionURL; +- (void)clearInternalHostCache; +- (BOOL)isDemoHost; +- (BOOL)isCustomHost; + +- (id)copyWithZone:(NSZone *)zone; +- (NSUInteger)hash; +- (BOOL)isEqual:(id)anObject; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m new file mode 100644 index 0000000..b2dd2e2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoInfo.h" +#import "FConstants.h" + +@interface FRepoInfo () + +@property(nonatomic, strong) NSString *domain; + +@end + +@implementation FRepoInfo + +@synthesize namespace; +@synthesize host; +@synthesize internalHost; +@synthesize secure; +@synthesize domain; + +- (id)initWithHost:(NSString *)aHost + isSecure:(bool)isSecure + withNamespace:(NSString *)aNamespace { + self = [super init]; + if (self) { + host = aHost; + domain = + [host containsString:@"."] + ? [host + substringFromIndex:[host rangeOfString:@"."].location + 1] + : host; + secure = isSecure; + namespace = aNamespace; + + // Get cached internal host if it exists + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSString *cachedInternalHost = [[NSUserDefaults standardUserDefaults] + stringForKey:internalHostKey]; + if (cachedInternalHost != nil) { + internalHost = cachedInternalHost; + } else { + internalHost = self.host; + } + } + return self; +} + +- (NSString *)description { + // The namespace is encoded in the hostname, so we can just return this. + return [NSString + stringWithFormat:@"http%@://%@", (self.secure ? @"s" : @""), self.host]; +} + +- (void)setInternalHost:(NSString *)newHost { + if (![internalHost isEqualToString:newHost]) { + internalHost = newHost; + + // Cache the internal host so we don't need to redirect later on + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache setObject:internalHost forKey:internalHostKey]; + [cache synchronize]; + } +} + +- (void)clearInternalHostCache { + internalHost = self.host; + + // Remove the cached entry + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache removeObjectForKey:internalHostKey]; + [cache synchronize]; +} + +- (BOOL)isDemoHost { + return [self.domain isEqualToString:@"firebaseio-demo.com"]; +} + +- (BOOL)isCustomHost { + return ![self.domain isEqualToString:@"firebaseio-demo.com"] && + ![self.domain isEqualToString:@"firebaseio.com"]; +} + +- (NSString *)connectionURL { + return [self connectionURLWithLastSessionID:nil]; +} + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID { + NSString *scheme; + if (self.secure) { + scheme = @"wss"; + } else { + scheme = @"ws"; + } + NSString *url = + [NSString stringWithFormat:@"%@://%@/.ws?%@=%@&ns=%@", scheme, + self.internalHost, kWireProtocolVersionParam, + kWebsocketProtocolVersion, self.namespace]; + + if (lastSessionID != nil) { + url = [NSString stringWithFormat:@"%@&ls=%@", url, lastSessionID]; + } + return url; +} + +- (id)copyWithZone:(NSZone *)zone; +{ + return self; // Immutable +} + +- (NSUInteger)hash { + NSUInteger result = host.hash; + result = 31 * result + (secure ? 1 : 0); + result = 31 * result + namespace.hash; + result = 31 * result + host.hash; + return result; +} + +- (BOOL)isEqual:(id)anObject { + if (![anObject isKindOfClass:[FRepoInfo class]]) + return NO; + FRepoInfo *other = (FRepoInfo *)anObject; + return secure == other.secure && [host isEqualToString:other.host] && + [namespace isEqualToString:other.namespace]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h new file mode 100644 index 0000000..ba8d1fc --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FRepo.h" +#import "FRepoInfo.h" +#import + +@interface FRepoManager : NSObject + ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config; ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; ++ (void)interruptAll; ++ (void)interrupt:(FIRDatabaseConfig *)config; ++ (void)resumeAll; ++ (void)resume:(FIRDatabaseConfig *)config; ++ (void)disposeRepos:(FIRDatabaseConfig *)config; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m new file mode 100644 index 0000000..54ad196 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m @@ -0,0 +1,148 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoManager.h" +#import "FAtomicNumber.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepo.h" +#import + +@implementation FRepoManager + +typedef NSMutableDictionary *> + FRepoDictionary; + ++ (FRepoDictionary *)configs { + static dispatch_once_t pred = 0; + static FRepoDictionary *configs; + dispatch_once(&pred, ^{ + configs = [NSMutableDictionary dictionary]; + }); + return configs; +} + +/** + * Used for legacy unit tests. The public API should go through + * FirebaseDatabase which calls createRepo. + */ ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos || repos[repoInfo] == nil) { + // Calling this should create the repo. + [FIRDatabase createDatabaseForTests:repoInfo config:config]; + } + + return configs[config.sessionIdentifier][repoInfo]; + } +} + ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos) { + repos = [NSMutableDictionary dictionary]; + configs[config.sessionIdentifier] = repos; + } + FRepo *repo = repos[repoInfo]; + if (repo == nil) { + repo = [[FRepo alloc] initWithRepoInfo:repoInfo + config:config + database:database]; + repos[repoInfo] = repo; + return repo; + } else { + [NSException + raise:@"RepoExists" + format:@"createRepo called for Repo that already exists."]; + return nil; + } + } +} + ++ (void)interrupt:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + }); +} + ++ (void)interruptAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + } + }); +} + ++ (void)resume:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + }); +} + ++ (void)resumeAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + } + }); +} + ++ (void)disposeRepos:(FIRDatabaseConfig *)config { + // Do this synchronously to make sure we release our references to LevelDB + // before returning, allowing LevelDB to close and release its exclusive + // locks. + dispatch_sync([FIRDatabaseQuery sharedQueue], ^{ + FFLog(@"I-RDB040001", @"Disposing all repos for Config with name %@", + config.sessionIdentifier); + NSMutableDictionary *configs = [FRepoManager configs]; + for (FRepo *repo in [configs[config.sessionIdentifier] allValues]) { + [repo dispose]; + } + [configs removeObjectForKey:config.sessionIdentifier]; + }); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h new file mode 100644 index 0000000..8dc1350 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepo.h" +#import "FSparseSnapshotTree.h" + +@class FSyncTree; +@class FAtomicNumber; +@class FEventRaiser; +@class FSnapshotHolder; + +@interface FRepo () + +- (void)runOnDisconnectEvents; + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPersistentConnection *connection; +@property(nonatomic, strong) FSnapshotHolder *infoData; +@property(nonatomic, strong) FSparseSnapshotTree *onDisconnect; +@property(nonatomic, strong) FEventRaiser *eventRaiser; +@property(nonatomic, strong) FSyncTree *serverSyncTree; + +// For testing. +@property(nonatomic) long dataUpdateCount; +@property(nonatomic) long rangeMergeUpdateCount; + +- (NSInteger)nextWriteId; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h new file mode 100644 index 0000000..33d1e57 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FSparseSnapshotTree.h" +#import + +@interface FServerValues : NSObject + ++ (NSDictionary *)generateServerValues:(id)clock; ++ (id)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withServerValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueSnapshot:(id)node + withServerValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueTree:(FSparseSnapshotTree *)tree + withServerValues:(NSDictionary *)serverValues; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m new file mode 100644 index 0000000..5519862 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m @@ -0,0 +1,115 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FServerValues.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" + +@implementation FServerValues + ++ (NSDictionary *)generateServerValues:(id)clock { + long long millis = (long long)([clock currentTime] * 1000); + return @{@"timestamp" : [NSNumber numberWithLongLong:millis]}; +} + ++ (id)resolveDeferredValue:(id)val + withServerValues:(NSDictionary *)serverValues { + if ([val isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = val; + if (dict[kServerValueSubKey] != nil) { + NSString *serverValueType = [dict objectForKey:kServerValueSubKey]; + if (serverValues[serverValueType] != nil) { + return [serverValues objectForKey:serverValueType]; + } else { + // TODO: Throw unrecognizedServerValue error here + } + } + } + return val; +} + ++ (FCompoundWrite *)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withServerValues: + (NSDictionary *)serverValues { + __block FCompoundWrite *resolved = write; + [write enumerateWrites:^(FPath *path, id node, BOOL *stop) { + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:node + withServerValues:serverValues]; + // Node actually changed, use pointer inequality here + if (resolvedNode != node) { + resolved = [resolved addWrite:resolvedNode atPath:path]; + } + }]; + return resolved; +} + ++ (id)resolveDeferredValueTree:(FSparseSnapshotTree *)tree + withServerValues:(NSDictionary *)serverValues { + FSparseSnapshotTree *resolvedTree = [[FSparseSnapshotTree alloc] init]; + [tree + forEachTreeAtPath:[FPath empty] + do:^(FPath *path, id node) { + [resolvedTree + rememberData: + [FServerValues + resolveDeferredValueSnapshot:node + withServerValues:serverValues] + onPath:path]; + }]; + return resolvedTree; +} + ++ (id)resolveDeferredValueSnapshot:(id)node + withServerValues:(NSDictionary *)serverValues { + id priorityVal = + [FServerValues resolveDeferredValue:[[node getPriority] val] + withServerValues:serverValues]; + id priority = [FSnapshotUtilities nodeFrom:priorityVal]; + + if ([node isLeafNode]) { + id value = [self resolveDeferredValue:[node val] + withServerValues:serverValues]; + if (![value isEqual:[node val]] || + ![priority isEqual:[node getPriority]]) { + return [[FLeafNode alloc] initWithValue:value + withPriority:priority]; + } else { + return node; + } + } else { + __block FChildrenNode *newNode = node; + if (![priority isEqual:[node getPriority]]) { + newNode = [newNode updatePriority:priority]; + } + + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + id newChildNode = + [FServerValues resolveDeferredValueSnapshot:childNode + withServerValues:serverValues]; + if (![newChildNode isEqual:childNode]) { + newNode = [newNode updateImmediateChild:childKey + withNewChild:newChildNode]; + } + }]; + return newNode; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h new file mode 100644 index 0000000..d682a8e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FSnapshotHolder : NSObject + +- (id)getNode:(FPath *)path; +- (void)updateSnapshot:(FPath *)path withNewSnapshot:(id)newSnapshotNode; + +@property(nonatomic, strong) id rootNode; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m new file mode 100644 index 0000000..59a7b52 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotHolder.h" +#import "FEmptyNode.h" + +@interface FSnapshotHolder () + +@end + +@implementation FSnapshotHolder + +@synthesize rootNode; + +- (id)init { + self = [super init]; + if (self) { + self.rootNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)getNode:(FPath *)path { + return [self.rootNode getChild:path]; +} + +- (void)updateSnapshot:(FPath *)path + withNewSnapshot:(id)newSnapshotNode { + self.rootNode = [self.rootNode updateChild:path + withNewChild:newSnapshotNode]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h new file mode 100644 index 0000000..dab5406 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@class FSparseSnapshotTree; + +typedef void (^fbt_void_nsstring_sstree)(NSString *, FSparseSnapshotTree *); + +@interface FSparseSnapshotTree : NSObject + +- (id)findPath:(FPath *)path; +- (void)rememberData:(id)data onPath:(FPath *)path; +- (BOOL)forgetPath:(FPath *)path; +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func; +- (void)forEachChild:(fbt_void_nsstring_sstree)func; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m new file mode 100644 index 0000000..6219309 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSparseSnapshotTree.h" +#import "FChildrenNode.h" + +@interface FSparseSnapshotTree () { + id value; + NSMutableDictionary *children; +} + +@end + +@implementation FSparseSnapshotTree + +- (id)init { + self = [super init]; + if (self) { + value = nil; + children = nil; + } + return self; +} + +- (id)findPath:(FPath *)path { + if (value != nil) { + return [value getChild:path]; + } else if (![path isEmpty] && children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + FSparseSnapshotTree *childTree = children[childKey]; + if (childTree != nil) { + return [childTree findPath:path]; + } else { + return nil; + } + } else { + return nil; + } +} + +- (void)rememberData:(id)data onPath:(FPath *)path { + if ([path isEmpty]) { + value = data; + children = nil; + } else if (value != nil) { + value = [value updateChild:path withNewChild:data]; + } else { + if (children == nil) { + children = [[NSMutableDictionary alloc] init]; + } + + NSString *childKey = [path getFront]; + if (children[childKey] == nil) { + children[childKey] = [[FSparseSnapshotTree alloc] init]; + } + + FSparseSnapshotTree *child = children[childKey]; + path = [path popFront]; + [child rememberData:data onPath:path]; + } +} + +- (BOOL)forgetPath:(FPath *)path { + if ([path isEmpty]) { + value = nil; + children = nil; + return YES; + } else { + if (value != nil) { + if ([value isLeafNode]) { + // non-empty path at leaf. the path leads to nowhere + return NO; + } else { + id tmp = value; + value = nil; + + [tmp enumerateChildrenUsingBlock:^(NSString *key, + id node, BOOL *stop) { + [self rememberData:node onPath:[[FPath alloc] initWith:key]]; + }]; + + // we've cleared out the value and set children. Call ourself + // again to hit the next case + return [self forgetPath:path]; + } + } else if (children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + + if (children[childKey] != nil) { + FSparseSnapshotTree *child = children[childKey]; + BOOL safeToRemove = [child forgetPath:path]; + if (safeToRemove) { + [children removeObjectForKey:childKey]; + } + } + + if ([children count] == 0) { + children = nil; + return YES; + } else { + return NO; + } + } else { + return YES; + } + } +} + +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func { + if (value != nil) { + func(prefixPath, value); + } else { + [self forEachChild:^(NSString *key, FSparseSnapshotTree *tree) { + FPath *path = [prefixPath childFromString:key]; + [tree forEachTreeAtPath:path do:func]; + }]; + } +} + +- (void)forEachChild:(fbt_void_nsstring_sstree)func { + if (children != nil) { + for (NSString *key in children) { + FSparseSnapshotTree *tree = [children objectForKey:key]; + func(key, tree); + } + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h new file mode 100644 index 0000000..a9bd4d9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FOperation; +@class FWriteTreeRef; +@protocol FNode; +@protocol FEventRegistration; +@class FQuerySpec; +@class FChildrenNode; +@class FTupleRemovedQueriesEvents; +@class FView; +@class FPath; +@class FCacheNode; +@class FPersistenceManager; + +@interface FSyncPoint : NSObject + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence; + +- (BOOL)isEmpty; + +/** + * Returns array of FEvent + */ +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; + +/** + * Returns array of FEvent + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache; + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query; + +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +/** + * Returns array of FViews + */ +- (NSArray *)queryViews; +- (id)completeServerCacheAtPath:(FPath *)path; +- (FView *)viewForQuery:(FQuerySpec *)query; +- (BOOL)viewExistsForQuery:(FQuerySpec *)query; +- (BOOL)hasCompleteView; +- (FView *)completeView; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m new file mode 100644 index 0000000..6496ae8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m @@ -0,0 +1,302 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncPoint.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FDataEvent.h" +#import "FEmptyNode.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FView.h" +#import "FViewCache.h" +#import "FWriteTreeRef.h" + +/** + * SyncPoint represents a single location in a SyncTree with 1 or more event + * registrations, meaning we need to maintain 1 or more Views at this location + * to cache server data and raise appropriate events for server changes and user + * writes (set, transaction, update). + * + * It's responsible for: + * - Maintaining the set of 1 or more views necessary at this location (a + * SyncPoint with 0 views should be removed). + * - Proxying user / server operations to the views as appropriate (i.e. + * applyServerOverwrite, applyUserOverwrite, etc.) + */ +@interface FSyncPoint () +/** + * The Views being tracked at this location in the tree, stored as a map where + * the key is a queryParams and the value is the View for that query. + * + * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more + * is an odd use case). + * + * Maps NSString -> FView + */ +@property(nonatomic, strong) NSMutableDictionary *views; + +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@end + +@implementation FSyncPoint + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence { + self = [super init]; + if (self) { + self.persistenceManager = persistence; + self.views = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (BOOL)isEmpty { + return [self.views count] == 0; +} + +- (NSArray *)applyOperation:(id)operation + toView:(FView *)view + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FViewOperationResult *result = [view applyOperation:operation + writesCache:writesCache + serverCache:optCompleteServerCache]; + if (!view.query.loadsAllData) { + NSMutableSet *removed = [NSMutableSet set]; + NSMutableSet *added = [NSMutableSet set]; + [result.changes enumerateObjectsUsingBlock:^( + FChange *change, NSUInteger idx, BOOL *stop) { + if (change.type == FIRDataEventTypeChildAdded) { + [added addObject:change.childKey]; + } else if (change.type == FIRDataEventTypeChildRemoved) { + [removed addObject:change.childKey]; + } + }]; + if ([removed count] > 0 || [added count] > 0) { + [self.persistenceManager + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQuery:view.query]; + } + } + return result.events; +} + +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FQueryParams *queryParams = operation.source.queryParams; + if (queryParams != nil) { + FView *view = [self.views objectForKey:queryParams]; + NSAssert(view != nil, @"SyncTree gave us an op for an invalid query."); + return [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + } else { + NSMutableArray *events = [[NSMutableArray alloc] init]; + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *key, FView *view, BOOL *stop) { + NSArray *eventsForView = [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + [events addObjectsFromArray:eventsForView]; + }]; + return events; + } +} + +/** + * Add an event callback for the specified query + * Returns Array of FEvent events to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache { + NSAssert(self.views[query.params] == nil, @"Found view for query: %@", + query.params); + // TODO: make writesCache take flag for complete server node + id eventCache = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + serverCache.isFullyInitialized ? serverCache.node : nil]; + BOOL eventCacheComplete; + if (eventCache != nil) { + eventCacheComplete = YES; + } else { + eventCache = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren:serverCache + .node]; + eventCacheComplete = NO; + } + + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:eventCache + index:query.index]; + FCacheNode *eventCacheNode = + [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:eventCacheComplete + isFiltered:NO]; + FViewCache *viewCache = + [[FViewCache alloc] initWithEventCache:eventCacheNode + serverCache:serverCache]; + FView *view = [[FView alloc] initWithQuery:query + initialViewCache:viewCache]; + // If this is a non-default query we need to tell persistence our current + // view of the data + if (!query.loadsAllData) { + NSMutableSet *allKeys = [NSMutableSet set]; + [view.eventCache enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [allKeys addObject:key]; + }]; + [self.persistenceManager setTrackedQueryKeys:allKeys forQuery:query]; + } + self.views[query.params] = view; + return [self addEventRegistration:eventRegistration + forExistingViewForQuery:query]; +} + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query { + FView *view = self.views[query.params]; + NSAssert(view != nil, @"No view for query: %@", query); + [view addEventRegistration:eventRegistration]; + return [view initialEvents:eventRegistration]; +} + +/** + * Remove event callback(s). Return cancelEvents if a cancelError is specified. + * + * If query is the default query, we'll check all views for the specified + * eventRegistration. If eventRegistration is nil, we'll remove all callbacks + * for the specified view(s). + * + * @return FTupleRemovedQueriesEvents removed queries and any cancel events + */ +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + NSMutableArray *removedQueries = [[NSMutableArray alloc] init]; + __block NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + BOOL hadCompleteView = [self hasCompleteView]; + if ([query isDefault]) { + // When you do [ref removeObserverWithHandle:], we search all views for + // the registration to remove. + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *viewQueryParams, FView *view, + BOOL *stop) { + [cancelEvents + addObjectsFromArray:[view + removeEventRegistration:eventRegistration + cancelError:cancelError]]; + if ([view isEmpty]) { + [self.views removeObjectForKey:viewQueryParams]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + }]; + } else { + // remove the callback from the specific view + FView *view = [self.views objectForKey:query.params]; + if (view != nil) { + [cancelEvents addObjectsFromArray: + [view removeEventRegistration:eventRegistration + cancelError:cancelError]]; + + if ([view isEmpty]) { + [self.views removeObjectForKey:query.params]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + } + } + + if (hadCompleteView && ![self hasCompleteView]) { + // We removed our last complete view + [removedQueries addObject:[FQuerySpec defaultQueryAtPath:query.path]]; + } + + return [[FTupleRemovedQueriesEvents alloc] + initWithRemovedQueries:removedQueries + cancelEvents:cancelEvents]; +} + +- (NSArray *)queryViews { + __block NSMutableArray *filteredViews = [[NSMutableArray alloc] init]; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if (![view.query loadsAllData]) { + [filteredViews addObject:view]; + } + }]; + + return filteredViews; +} + +- (id)completeServerCacheAtPath:(FPath *)path { + __block id serverCache = nil; + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + serverCache = [view completeServerCacheFor:path]; + *stop = (serverCache != nil); + }]; + return serverCache; +} + +- (FView *)viewForQuery:(FQuerySpec *)query { + return [self.views objectForKey:query.params]; +} + +- (BOOL)viewExistsForQuery:(FQuerySpec *)query { + return [self viewForQuery:query] != nil; +} + +- (BOOL)hasCompleteView { + return [self completeView] != nil; +} + +- (FView *)completeView { + __block FView *completeView = nil; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if ([view.query loadsAllData]) { + completeView = view; + *stop = YES; + } + }]; + + return completeView; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h new file mode 100644 index 0000000..ef89774 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FListenProvider; +@protocol FNode; +@class FPath; +@protocol FEventRegistration; +@protocol FPersistedServerCache; +@class FQuerySpec; +@class FCompoundWrite; +@class FPersistenceManager; +@class FCompoundHash; +@protocol FClock; + +@protocol FSyncTreeHash + +- (NSString *)simpleHash; +- (FCompoundHash *)compoundHash; +- (BOOL)includeCompoundHash; + +@end + +@interface FSyncTree : NSObject + +- (id)initWithListenProvider:(FListenProvider *)provider; +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider; + +// These methods all return NSArray of FEvent +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock; +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData; +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren; +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges; +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId; +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced; +- (NSArray *)removeAllWrites; + +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m new file mode 100644 index 0000000..e7fa3dc --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m @@ -0,0 +1,1038 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncTree.h" +#import "FAckUserWrite.h" +#import "FAtomicNumber.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundHash.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FImmutableTree.h" +#import "FKeepSyncedEventRegistration.h" +#import "FListenComplete.h" +#import "FListenProvider.h" +#import "FMerge.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncPoint.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FUtilities.h" +#import "FView.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" +#import "FWriteTreeRef.h" +#import + +// Size after which we start including the compound hash +static const NSUInteger kFSizeThresholdForCompoundHash = 1024; + +@interface FListenContainer : NSObject + +@property(nonatomic, strong) FView *view; +@property(nonatomic, copy) fbt_nsarray_nsstring onComplete; + +@end + +@implementation FListenContainer + +- (instancetype)initWithView:(FView *)view + onComplete:(fbt_nsarray_nsstring)onComplete { + self = [super init]; + if (self != nil) { + self->_view = view; + self->_onComplete = onComplete; + } + return self; +} + +- (id)serverCache { + return self.view.serverCache; +} + +- (FCompoundHash *)compoundHash { + return [FCompoundHash fromNode:[self serverCache]]; +} + +- (NSString *)simpleHash { + return [[self serverCache] dataHash]; +} + +- (BOOL)includeCompoundHash { + return [FSnapshotUtilities estimateSerializedNodeSize:[self serverCache]] > + kFSizeThresholdForCompoundHash; +} + +@end + +@interface FSyncTree () + +/** + * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more + * views. + */ +@property(nonatomic, strong) FImmutableTree *syncPointTree; + +/** + * A tree of all pending user writes (user-initiated set, transactions, updates, + * etc) + */ +@property(nonatomic, strong) FWriteTree *pendingWriteTree; + +/** + * Maps tagId -> FTuplePathQueryParams + */ +@property(nonatomic, strong) NSMutableDictionary *tagToQueryMap; +@property(nonatomic, strong) NSMutableDictionary *queryToTagMap; +@property(nonatomic, strong) FListenProvider *listenProvider; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FAtomicNumber *queryTagCounter; +@property(nonatomic, strong) NSMutableSet *keepSyncedQueries; + +@end + +/** + * SyncTree is the central class for managing event callback registration, data + * caching, views (query processing), and event generation. There are typically + * two SyncTree instances for each Repo, one for the normal Firebase data, and + * one for the .info data. + * + * It has a number of responsibilities, including: + * - Tracking all user event callbacks (registered via addEventRegistration: + * and removeEventRegistration:). + * - Applying and caching data changes for user setValue:, + * runTransactionBlock:, and updateChildValues: calls + * (applyUserOverwriteAtPath:, applyUserMergeAtPath:). + * - Applying and caching data changes for server data changes + * (applyServerOverwriteAtPath:, applyServerMergeAtPath:). + * - Generating user-facing events for server and user changes (all of the + * apply* methods return the set of events that need to be raised as a result). + * - Maintaining the appropriate set of server listens to ensure we are always + * subscribed to the correct set of paths and queries to satisfy the current set + * of user event callbacks (listens are started/stopped using the provided + * listenProvider). + * + * NOTE: Although SyncTree tracks event callbacks and calculates events to + * raise, the actual events are returned to the caller rather than raised + * synchronously. + */ +@implementation FSyncTree + +- (id)initWithListenProvider:(FListenProvider *)provider { + return [self initWithPersistenceManager:nil listenProvider:provider]; +} + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider { + self = [super init]; + if (self) { + self.syncPointTree = [FImmutableTree empty]; + self.pendingWriteTree = [[FWriteTree alloc] init]; + self.tagToQueryMap = [[NSMutableDictionary alloc] init]; + self.queryToTagMap = [[NSMutableDictionary alloc] init]; + self.listenProvider = provider; + self.persistenceManager = persistenceManager; + self.queryTagCounter = [[FAtomicNumber alloc] init]; + self.keepSyncedQueries = [NSMutableSet set]; + } + return self; +} + +#pragma mark - +#pragma mark Apply Operations + +/** + * Apply data changes for a user-generated setValue: runTransactionBlock: + * updateChildValues:, etc. + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + // Record pending write + [self.pendingWriteTree addOverwriteAtPath:path + newData:newData + writeId:writeId + isVisible:visible]; + if (!visible) { + return @[]; + } else { + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource userInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply the data from a user-generated updateChildValues: call + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + // Record pending merge + [self.pendingWriteTree addMergeAtPath:path + changedChildren:changedChildren + writeId:writeId]; + + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource userInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Acknowledge a pending user write that was previously registered with + * applyUserOverwriteAtPath: or applyUserMergeAtPath: + * TODO[offline]: Taking a serverClock here is awkward, but server values are + * awkward. :-( + * @return NSArray of FEvent to raise. + */ +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock { + FWriteRecord *write = [self.pendingWriteTree writeForId:writeId]; + BOOL needToReevaluate = [self.pendingWriteTree removeWriteId:writeId]; + if (write.visible) { + if (persist) { + [self.persistenceManager removeUserWrite:writeId]; + } + if (!revert) { + NSDictionary *serverValues = + [FServerValues generateServerValues:clock]; + if ([write isOverwrite]) { + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withServerValues:serverValues]; + [self.persistenceManager applyUserWrite:resolvedNode + toServerCacheAtPath:write.path]; + } else { + FCompoundWrite *resolvedMerge = [FServerValues + resolveDeferredValueCompoundWrite:write.merge + withServerValues:serverValues]; + [self.persistenceManager applyUserMerge:resolvedMerge + toServerCacheAtPath:write.path]; + } + } + } + if (!needToReevaluate) { + return @[]; + } else { + __block FImmutableTree *affectedTree = [FImmutableTree empty]; + if (write.isOverwrite) { + affectedTree = [affectedTree setValue:@YES atPath:[FPath empty]]; + } else { + [write.merge + enumerateWrites:^(FPath *path, id node, BOOL *stop) { + affectedTree = [affectedTree setValue:@YES atPath:path]; + }]; + } + FAckUserWrite *operation = + [[FAckUserWrite alloc] initWithPath:write.path + affectedTree:affectedTree + revert:revert]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply new server data for the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData { + [self.persistenceManager + updateServerCacheWithNode:newData + forQuery:[FQuerySpec defaultQueryAtPath:path]]; + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource serverInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Applied new server data to be merged in at the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren { + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource serverInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + // Removed view, so it's safe to just ignore this update + return @[]; + } else { + // This could be for any "complete" (unfiltered) view, and if there is + // more than one complete view, they should each have the same cache so + // it doesn't matter which one we use. + FView *view = [syncPoint completeView]; + if (view != nil) { + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyServerOverwriteAtPath:path newData:serverNode]; + } else { + // There doesn't exist a view for this update, so it was removed and + // it's safe to just ignore this range merge + return @[]; + } + } +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyListenCompleteAtPath:(FPath *)path { + [self.persistenceManager + setQueryComplete:[FQuerySpec defaultQueryAtPath:path]]; + id operation = [[FListenComplete alloc] + initWithSource:[FOperationSource serverInstance] + path:path]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedListenCompleteAtPath:(FPath *)path + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + [self.persistenceManager setQueryComplete:query]; + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + id op = [[FListenComplete alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath]; + return [self applyTaggedOperation:op atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Internal helper method to apply tagged operation + */ +- (NSArray *)applyTaggedOperation:(id)operation + atPath:(FPath *)path { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + return [syncPoint applyOperation:operation + writesCache:writesCache + serverCache:nil]; +} + +/** + * Apply new server data for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + FQuerySpec *queryToOverwrite = + relativePath.isEmpty ? query : [FQuerySpec defaultQueryAtPath:path]; + [self.persistenceManager updateServerCacheWithNode:newData + forQuery:queryToOverwrite]; + FOverwrite *operation = [[FOverwrite alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + snap:newData]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // Query must have been removed already + return @[]; + } +} + +/** + * Apply server data to be merged in for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = [[FMerge alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + children:changedChildren]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + NSAssert([path isEqual:query.path], + @"Tagged update path and query path must match"); + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FView *view = [syncPoint viewForQuery:query]; + NSAssert(view != nil, + @"Missing view for query tag that we're tracking"); + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyTaggedQueryOverwriteAtPath:path + newData:serverNode + tagId:tagId]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Add an event callback for the specified query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + FPath *path = query.path; + + __block BOOL foundAncestorDefaultView = NO; + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + foundAncestorDefaultView = + foundAncestorDefaultView || [syncPoint hasCompleteView]; + return !foundAncestorDefaultView; + }]; + + [self.persistenceManager setQueryActive:query]; + + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + syncPoint = [[FSyncPoint alloc] + initWithPersistenceManager:self.persistenceManager]; + self.syncPointTree = [self.syncPointTree setValue:syncPoint + atPath:path]; + } + + BOOL viewAlreadyExists = [syncPoint viewExistsForQuery:query]; + NSArray *events; + if (viewAlreadyExists) { + events = [syncPoint addEventRegistration:eventRegistration + forExistingViewForQuery:query]; + } else { + if (![query loadsAllData]) { + // We need to track a tag for this query + NSAssert(self.queryToTagMap[query] == nil, + @"View does not exist, but we have a tag"); + NSNumber *tagId = [self.queryTagCounter getAndIncrement]; + self.queryToTagMap[query] = tagId; + self.tagToQueryMap[tagId] = query; + } + + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + FCacheNode *serverCache = [self serverCacheForQuery:query]; + events = [syncPoint addEventRegistration:eventRegistration + forNonExistingViewForQuery:query + writesCache:writesCache + serverCache:serverCache]; + + // There was no view and no default listen + if (!foundAncestorDefaultView) { + FView *view = [syncPoint viewForQuery:query]; + NSMutableArray *mutableEvents = [events mutableCopy]; + [mutableEvents + addObjectsFromArray:[self setupListenerOnQuery:query + view:view]]; + events = mutableEvents; + } + } + + return events; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + __block id serverCacheNode = nil; + + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathToSyncPoint + to:query.path]; + serverCacheNode = + [syncPoint completeServerCacheAtPath:relativePath]; + return serverCacheNode == nil; + }]; + + FCacheNode *serverCache; + if (serverCacheNode != nil) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + FCacheNode *persistenceServerCache = + [self.persistenceManager serverCacheForQuery:query]; + if (persistenceServerCache.isFullyInitialized) { + serverCache = persistenceServerCache; + } else { + serverCacheNode = [FEmptyNode emptyNode]; + + FImmutableTree *subtree = + [self.syncPointTree subtreeAtPath:query.path]; + [subtree + forEachChild:^(NSString *childKey, FSyncPoint *childSyncPoint) { + id completeCache = + [childSyncPoint completeServerCacheAtPath:[FPath empty]]; + if (completeCache) { + serverCacheNode = + [serverCacheNode updateImmediateChild:childKey + withNewChild:completeCache]; + } + }]; + // Fill the node with any available children we have + [persistenceServerCache.node + enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (![serverCacheNode hasChild:key]) { + serverCacheNode = + [serverCacheNode updateImmediateChild:key + withNewChild:node]; + } + }]; + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:NO + isFiltered:NO]; + } + } + + return serverCache; +} + +/** + * Remove event callback(s). + * + * If query is the default query, we'll check all queries for the specified + * eventRegistration. If eventRegistration is null, we'll remove all callbacks + * for the specified query/queries. + * + * @param eventRegistration if nil, all callbacks are removed + * @param cancelError If provided, appropriate cancel events will be returned + * @return NSArray of FEvent to raise. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + // Find the syncPoint first. Then deal with whether or not it has matching + // listeners + FPath *path = query.path; + FSyncPoint *maybeSyncPoint = [self.syncPointTree valueAtPath:path]; + NSArray *cancelEvents = @[]; + + // A removal on a default query affects all queries at that location. A + // removal on an indexed query, even one without other query constraints, + // does *not* affect all queries at that location. So this check must be for + // 'default', and not loadsAllData: + if (maybeSyncPoint && + ([query isDefault] || [maybeSyncPoint viewExistsForQuery:query])) { + FTupleRemovedQueriesEvents *removedAndEvents = + [maybeSyncPoint removeEventRegistration:eventRegistration + forQuery:query + cancelError:cancelError]; + if ([maybeSyncPoint isEmpty]) { + self.syncPointTree = [self.syncPointTree removeValueAtPath:path]; + } + NSArray *removed = removedAndEvents.removedQueries; + cancelEvents = removedAndEvents.cancelEvents; + + // We may have just removed one of many listeners and can short-circuit + // this whole process We may also not have removed a default listener, + // in which case all of the descendant listeners should already be + // properly set up. + // + // Since indexed queries can shadow if they don't have other query + // constraints, check for loadsAllData: instead of isDefault: + NSUInteger defaultQueryIndex = [removed + indexOfObjectPassingTest:^BOOL(FQuerySpec *q, NSUInteger idx, + BOOL *stop) { + return [q loadsAllData]; + }]; + BOOL removingDefault = defaultQueryIndex != NSNotFound; + [removed enumerateObjectsUsingBlock:^(FQuerySpec *query, NSUInteger idx, + BOOL *stop) { + [self.persistenceManager setQueryInactive:query]; + }]; + NSNumber *covered = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *relativePath, + FSyncPoint *parentSyncPoint) { + return + [NSNumber numberWithBool:[parentSyncPoint hasCompleteView]]; + }]; + + if (removingDefault && ![covered boolValue]) { + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // There are potentially child listeners. Determine what if any + // listens we need to send before executing the removal + if (![subtree isEmpty]) { + // We need to fold over our subtree and collect the listeners to + // send + NSArray *newViews = + [self collectDistinctViewsForSubTree:subtree]; + + // Ok, we've collected all the listens we need. Set them up. + [newViews enumerateObjectsUsingBlock:^( + FView *view, NSUInteger idx, BOOL *stop) { + FQuerySpec *newQuery = view.query; + FListenContainer *listenContainer = + [self createListenerForView:view]; + self.listenProvider.startListening( + [self queryForListening:newQuery], + [self tagForQuery:newQuery], listenContainer, + listenContainer.onComplete); + }]; + } else { + // There's nothing below us, so nothing we need to start + // listening on + } + } + + // If we removed anything and we're not covered by a higher up listen, + // we need to stop listening on this query. The above block has us + // covered in terms of making sure we're set up on listens lower in the + // tree. Also, note that if we have a cancelError, it's already been + // removed at the provider level. + if (![covered boolValue] && [removed count] > 0 && cancelError == nil) { + // If we removed a default, then we weren't listening on any of the + // other queries here. Just cancel the one default. Otherwise, we + // need to iterate through and cancel each individual query + if (removingDefault) { + // We don't tag default listeners + self.listenProvider.stopListening( + [self queryForListening:query], nil); + } else { + [removed + enumerateObjectsUsingBlock:^(FQuerySpec *queryToRemove, + NSUInteger idx, BOOL *stop) { + NSNumber *tagToRemove = + [self.queryToTagMap objectForKey:queryToRemove]; + self.listenProvider.stopListening( + [self queryForListening:queryToRemove], tagToRemove); + }]; + } + } + // Now, clear all the tags we're tracking for the removed listens. + [self removeTags:removed]; + } else { + // No-op, this listener must've been already removed + } + return cancelEvents; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced { + // Only do something if we actually need to add/remove an event registration + if (keepSynced && ![self.keepSyncedQueries containsObject:query]) { + [self addEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query]; + [self.keepSyncedQueries addObject:query]; + } else if (!keepSynced && [self.keepSyncedQueries containsObject:query]) { + [self removeEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query + cancelError:nil]; + [self.keepSyncedQueries removeObject:query]; + } +} + +- (NSArray *)removeAllWrites { + [self.persistenceManager removeAllUserWrites]; + NSArray *removedWrites = [self.pendingWriteTree removeAllWrites]; + if (removedWrites.count > 0) { + FImmutableTree *affectedTree = + [[FImmutableTree empty] setValue:@YES atPath:[FPath empty]]; + return [self applyOperationToSyncPoints:[[FAckUserWrite alloc] + initWithPath:[FPath empty] + affectedTree:affectedTree + revert:YES]]; + } else { + return @[]; + } +} + +/** + * Returns a complete cache, if we have one, of the data at a particular path. + * The location must have a listener above it, but as this is only used by + * transaction code, that should always be the case anyways. + * + * Note: this method will *include* hidden writes from transaction with + * applyLocally set to false. + * @param path The path to the data we want + * @param writeIdsToExclude A specific set to be excluded + */ +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + BOOL includeHiddenSets = YES; + FWriteTree *writeTree = self.pendingWriteTree; + id serverCache = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *pathSoFar, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathSoFar to:path]; + id serverCache = + [syncPoint completeServerCacheAtPath:relativePath]; + if (serverCache) { + return serverCache; + } else { + return nil; + } + }]; + return [writeTree calculateCompleteEventCacheAtPath:path + completeServerCache:serverCache + excludeWriteIds:writeIdsToExclude + includeHiddenWrites:includeHiddenSets]; +} + +#pragma mark - +#pragma mark Private Methods +/** + * This collapses multiple unfiltered views into a single view, since we only + * need a single listener for them. + * @return NSArray of FView + */ +- (NSArray *)collectDistinctViewsForSubTree:(FImmutableTree *)subtree { + return [subtree foldWithBlock:^NSArray *(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (maybeChildSyncPoint && [maybeChildSyncPoint hasCompleteView]) { + FView *completeView = [maybeChildSyncPoint completeView]; + return @[ completeView ]; + } else { + // No complete view here, flatten any deeper listens into an array + NSMutableArray *views = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint) { + views = [[maybeChildSyncPoint queryViews] mutableCopy]; + } + [childMap enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, NSArray *childViews, BOOL *stop) { + [views addObjectsFromArray:childViews]; + }]; + return views; + } + }]; +} + +/** + * @param queries NSArray of FQuerySpec + */ +- (void)removeTags:(NSArray *)queries { + [queries enumerateObjectsUsingBlock:^(FQuerySpec *removedQuery, + NSUInteger idx, BOOL *stop) { + if (![removedQuery loadsAllData]) { + // We should have a tag for this + NSNumber *removedQueryTag = self.queryToTagMap[removedQuery]; + [self.queryToTagMap removeObjectForKey:removedQuery]; + [self.tagToQueryMap removeObjectForKey:removedQueryTag]; + } + }]; +} + +- (FQuerySpec *)queryForListening:(FQuerySpec *)query { + if (query.loadsAllData && !query.isDefault) { + // We treat queries that load all data as default queries + return [FQuerySpec defaultQueryAtPath:query.path]; + } else { + return query; + } +} + +/** + * For a given new listen, manage the de-duplication of outstanding + * subscriptions. + * @return NSArray of FEvent events to support synchronous data sources + */ +- (NSArray *)setupListenerOnQuery:(FQuerySpec *)query view:(FView *)view { + FPath *path = query.path; + NSNumber *tagId = [self tagForQuery:query]; + FListenContainer *listenContainer = [self createListenerForView:view]; + + NSArray *events = self.listenProvider.startListening( + [self queryForListening:query], tagId, listenContainer, + listenContainer.onComplete); + + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // The root of this subtree has our query. We're here because we definitely + // need to send a listen for that, but we may need to shadow other listens + // as well. + if (tagId != nil) { + NSAssert(![subtree.value hasCompleteView], + @"If we're adding a query, it shouldn't be shadowed"); + } else { + // Shadow everything at or below this location, this is a default + // listener. + NSArray *queriesToStop = + [subtree foldWithBlock:^id(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (![relativePath isEmpty] && maybeChildSyncPoint != nil && + [maybeChildSyncPoint hasCompleteView]) { + return @[ [maybeChildSyncPoint completeView].query ]; + } else { + // No default listener here, flatten any deeper queries into + // an array + NSMutableArray *queries = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint != nil) { + for (FView *view in [maybeChildSyncPoint queryViews]) { + [queries addObject:view.query]; + } + } + [childMap + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, NSArray *childQueries, BOOL *stop) { + [queries addObjectsFromArray:childQueries]; + }]; + return queries; + } + }]; + for (FQuerySpec *queryToStop in queriesToStop) { + self.listenProvider.stopListening( + [self queryForListening:queryToStop], + [self tagForQuery:queryToStop]); + } + } + return events; +} + +- (FListenContainer *)createListenerForView:(FView *)view { + FQuerySpec *query = view.query; + NSNumber *tagId = [self tagForQuery:query]; + + FListenContainer *listenContainer = [[FListenContainer alloc] + initWithView:view + onComplete:^(NSString *status) { + if ([status isEqualToString:@"ok"]) { + if (tagId != nil) { + return [self applyTaggedListenCompleteAtPath:query.path + tagId:tagId]; + } else { + return [self applyListenCompleteAtPath:query.path]; + } + } else { + // If a listen failed, kill all of the listeners here, not just + // the one that triggered the error. Note that this may need to + // be scoped to just this listener if we change permissions on + // filtered children + NSError *error = [FUtilities errorForStatus:status + andReason:nil]; + FFWarn(@"I-RDB038012", @"Listener at %@ failed: %@", query.path, + status); + return [self removeEventRegistration:nil + forQuery:query + cancelError:error]; + } + }]; + + return listenContainer; +} + +/** + * @return The query associated with the given tag, if we have one + */ +- (FQuerySpec *)queryForTag:(NSNumber *)tagId { + return self.tagToQueryMap[tagId]; +} + +/** + * @return The tag associated with the given query + */ +- (NSNumber *)tagForQuery:(FQuerySpec *)query { + return self.queryToTagMap[query]; +} + +#pragma mark - +#pragma mark applyOperation Helpers + +/** +* A helper method that visits all descendant and ancestor SyncPoints, applying +the operation. +* +* NOTES: +* - Descendant SyncPoints will be visited first (since we raise events +depth-first). + +* - We call applyOperation: on each SyncPoint passing three things: +* 1. A version of the Operation that has been made relative to the SyncPoint +location. +* 2. A WriteTreeRef of any writes we have cached at the SyncPoint location. +* 3. A snapshot Node with cached server data, if we have it. + +* - We concatenate all of the events returned by each SyncPoint and return the +result. +* +* @return Array of FEvent +*/ +- (NSArray *)applyOperationToSyncPoints:(id)operation { + return [self applyOperationHelper:operation + syncPointTree:self.syncPointTree + serverCache:nil + writesCache:[self.pendingWriteTree + childWritesForPath:[FPath empty]]]; +} + +/** + * Recursive helper for applyOperationToSyncPoints_ + */ +- (NSArray *)applyOperationHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + if ([operation.path isEmpty]) { + return [self applyOperationDescendantsHelper:operation + syncPointTree:syncPointTree + serverCache:serverCache + writesCache:writesCache]; + } else { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + if (serverCache == nil && syncPoint != nil) { + serverCache = [syncPoint completeServerCacheAtPath:[FPath empty]]; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSString *childKey = [operation.path getFront]; + id childOperation = [operation operationForChild:childKey]; + FImmutableTree *childTree = [syncPointTree.children get:childKey]; + if (childTree != nil && childOperation != nil) { + id childServerCache = + serverCache ? [serverCache getImmediateChild:childKey] : nil; + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + [events + addObjectsFromArray:[self + applyOperationHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + + if (syncPoint) { + [events addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:serverCache]]; + } + + return events; + } +} + +/** + * Recursive helper for applyOperationToSyncPoints: + */ +- (NSArray *)applyOperationDescendantsHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + id resolvedServerCache; + if (serverCache == nil & syncPoint != nil) { + resolvedServerCache = + [syncPoint completeServerCacheAtPath:[FPath empty]]; + } else { + resolvedServerCache = serverCache; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + [syncPointTree.children enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, + BOOL *stop) { + id childServerCache = nil; + if (resolvedServerCache != nil) { + childServerCache = [resolvedServerCache getImmediateChild:childKey]; + } + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + id childOperation = [operation operationForChild:childKey]; + if (childOperation != nil) { + [events addObjectsFromArray: + [self applyOperationDescendantsHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + }]; + + if (syncPoint) { + [events + addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:resolvedServerCache]]; + } + + return events; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h new file mode 100644 index 0000000..435fb6a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@class FCompoundWrite; +@protocol FNode; + +@interface FWriteRecord : NSObject + +- initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible; +- initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId; + +@property(nonatomic, readonly) NSInteger writeId; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id overwrite; +/** + * Maps NSString -> id + */ +@property(nonatomic, strong, readonly) FCompoundWrite *merge; +@property(nonatomic, readonly) BOOL visible; + +- (BOOL)isMerge; +- (BOOL)isOverwrite; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m new file mode 100644 index 0000000..be1816e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m @@ -0,0 +1,139 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteRecord.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" + +@interface FWriteRecord () +@property(nonatomic, readwrite) NSInteger writeId; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) id overwrite; +@property(nonatomic, strong, readwrite) FCompoundWrite *merge; +@property(nonatomic, readwrite) BOOL visible; +@end + +@implementation FWriteRecord + +- (id)initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible { + self = [super init]; + if (self) { + self.path = path; + if (overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as overwrite parameter to an " + @"overwrite write record"]; + } + self.overwrite = overwrite; + self.merge = nil; + self.writeId = writeId; + self.visible = isVisible; + } + return self; +} + +- (id)initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId { + self = [super init]; + if (self) { + self.path = path; + if (merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as merge parameter to an merge " + @"write record"]; + } + self.overwrite = nil; + self.merge = merge; + self.writeId = writeId; + self.visible = YES; + } + return self; +} + +- (id)overwrite { + if (self->_overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get overwrite for merge write record!"]; + } + return self->_overwrite; +} + +- (FCompoundWrite *)compoundWrite { + if (self->_merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get merge for overwrite write record!"]; + } + return self->_merge; +} + +- (BOOL)isMerge { + return self->_merge != nil; +} + +- (BOOL)isOverwrite { + return self->_overwrite != nil; +} + +- (NSString *)description { + if (self.isOverwrite) { + return + [NSString stringWithFormat:@"FWriteRecord { writeId = %lu, path = " + @"%@, overwrite = %@, visible = %d }", + (unsigned long)self.writeId, self.path, + self.overwrite, self.visible]; + } else { + return [NSString + stringWithFormat: + @"FWriteRecord { writeId = %lu, path = %@, merge = %@ }", + (unsigned long)self.writeId, self.path, self.merge]; + } +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[self class]]) { + return NO; + } + FWriteRecord *other = (FWriteRecord *)object; + if (self->_writeId != other->_writeId) + return NO; + if (self->_path != other->_path && ![self->_path isEqual:other->_path]) + return NO; + if (self->_overwrite != other->_overwrite && + ![self->_overwrite isEqual:other->_overwrite]) + return NO; + if (self->_merge != other->_merge && ![self->_merge isEqual:other->_merge]) + return NO; + if (self->_visible != other->_visible) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self->_writeId * 17; + hash = hash * 31 + self->_path.hash; + hash = hash * 31 + self->_overwrite.hash; + hash = hash * 31 + self->_merge.hash; + hash = hash * 31 + ((self->_visible) ? 1 : 0); + return hash; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h new file mode 100644 index 0000000..178946b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@protocol FNode; +@class FCompoundWrite; +@class FWriteTreeRef; +@class FChildrenNode; +@class FNamedNode; +@class FWriteRecord; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTree : NSObject + +- (FWriteTreeRef *)childWritesForPath:(FPath *)path; +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (BOOL)removeWriteId:(NSInteger)writeId; +- (NSArray *)removeAllWrites; +- (FWriteRecord *)writeForId:(NSInteger)writeId; + +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites; + +- (id)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap:(id)existingEventSnap + existingServerSnap:(id)existingServerSnap; + +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)path + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m new file mode 100644 index 0000000..d8592c0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m @@ -0,0 +1,577 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTree.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FImmutableTree.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTreeRef.h" + +@interface FWriteTree () +/** + * A tree tracking the results of applying all visible writes. This does not + * include transactions with applyLocally=false or writes that are completely + * shadowed by other writes. Contains id as values. + */ +@property(nonatomic, strong) FCompoundWrite *visibleWrites; +/** + * A list of pending writes, regardless of visibility and shadowed-ness. Used to + * calcuate arbitrary sets of the changed data, such as hidden writes (from + * transactions) or changes with certain writes excluded (also used by + * transactions). Contains FWriteRecords. + */ +@property(nonatomic, strong) NSMutableArray *allWrites; +@property(nonatomic) NSInteger lastWriteId; +@end + +/** + * FWriteTree tracks all pending user-initiated writes and has methods to + * calcuate the result of merging them with underlying server data (to create + * "event cache" data). Pending writes are added with addOverwriteAtPath: and + * addMergeAtPath: and removed with removeWriteId:. + */ +@implementation FWriteTree + +@synthesize allWrites; +@synthesize lastWriteId; + +- (id)init { + self = [super init]; + if (self) { + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [[NSMutableArray alloc] init]; + self.lastWriteId = -1; + } + return self; +} + +/** + * Create a new WriteTreeRef for the given path. For use with a new sync point + * at the given path. + */ +- (FWriteTreeRef *)childWritesForPath:(FPath *)path { + return [[FWriteTreeRef alloc] initWithPath:path writeTree:self]; +} + +/** + * Record a new overwrite from user code. + * @param visible Is set to false by some transactions. It should be excluded + * from event caches. + */ +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older write on top of a newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + overwrite:newData + writeId:writeId + visible:visible]; + [self.allWrites addObject:record]; + + if (visible) { + self.visibleWrites = [self.visibleWrites addWrite:newData atPath:path]; + } + + self.lastWriteId = writeId; +} + +/** + * Record a new merge from user code. + * @param changedChildren maps NSString -> id + */ +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older merge on top of newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + merge:changedChildren + writeId:writeId]; + [self.allWrites addObject:record]; + + self.visibleWrites = [self.visibleWrites addCompoundWrite:changedChildren + atPath:path]; + self.lastWriteId = writeId; +} + +- (FWriteRecord *)writeForId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + return write.writeId == writeId; + }]; + return (index == NSNotFound) ? nil : self.allWrites[index]; +} + +/** + * Remove a write (either an overwrite or merge) that has been successfully + * acknowledged by the server. Recalculates the tree if necessary. We return the + * path of the write and whether it may have been visible, meaning views need to + * reevaluate. + * + * @return YES if the write may have been visible (meaning we'll need to + * reevaluate / raise events as a result). + */ +- (BOOL)removeWriteId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + if (record.writeId == writeId) { + return YES; + } else { + return NO; + } + }]; + NSAssert(index != NSNotFound, + @"[FWriteTree removeWriteId:] called with nonexistent writeId."); + FWriteRecord *writeToRemove = self.allWrites[index]; + [self.allWrites removeObjectAtIndex:index]; + + BOOL removedWriteWasVisible = writeToRemove.visible; + BOOL removedWriteOverlapsWithOtherWrites = NO; + NSInteger i = [self.allWrites count] - 1; + + while (removedWriteWasVisible && i >= 0) { + FWriteRecord *currentWrite = [self.allWrites objectAtIndex:i]; + if (currentWrite.visible) { + if (i >= index && [self record:currentWrite + containsPath:writeToRemove.path]) { + // The removed write was completely shadowed by a subsequent + // write. + removedWriteWasVisible = NO; + } else if ([writeToRemove.path contains:currentWrite.path]) { + // Either we're covering some writes or they're covering part of + // us (depending on which came first). + removedWriteOverlapsWithOtherWrites = YES; + } + } + i--; + } + + if (!removedWriteWasVisible) { + return NO; + } else if (removedWriteOverlapsWithOtherWrites) { + // There's some shadowing going on. Just rebuild the visible writes from + // scratch. + [self resetTree]; + return YES; + } else { + // There's no shadowing. We can safely just remove the write(s) from + // visibleWrites. + if ([writeToRemove isOverwrite]) { + self.visibleWrites = + [self.visibleWrites removeWriteAtPath:writeToRemove.path]; + } else { + FCompoundWrite *merge = writeToRemove.merge; + [merge enumerateWrites:^(FPath *path, id node, BOOL *stop) { + self.visibleWrites = [self.visibleWrites + removeWriteAtPath:[writeToRemove.path child:path]]; + }]; + } + return YES; + } +} + +- (NSArray *)removeAllWrites { + NSArray *writes = self.allWrites; + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [NSMutableArray array]; + return writes; +} + +/** + * @return A complete snapshot for the given path if there's visible write data + * at that path, else nil. No server data is considered. + */ +- (id)completeWriteDataAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * Given optional, underlying server data, and an optional set of constraints + * (exclude some sets, include hidden writes), attempt to calculate a complete + * snapshot for the given path + * @param includeHiddenWrites Defaults to false, whether or not to layer on + * writes with visible set to false + */ +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites { + if (writeIdsToExclude == nil && !includeHiddenWrites) { + id shadowingNode = + [self.visibleWrites completeNodeAtPath:treePath]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + // No cache here. Can't claim complete knowledge. + FCompoundWrite *subMerge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (subMerge.isEmpty) { + return completeServerCache; + } else if (completeServerCache == nil && + ![subMerge hasCompleteWriteAtPath:[FPath empty]]) { + // We wouldn't have a complete snapshot since there's no + // underlying data and no complete shadow + return nil; + } else { + id layeredCache = completeServerCache != nil + ? completeServerCache + : [FEmptyNode emptyNode]; + return [subMerge applyToNode:layeredCache]; + } + } + } else { + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (!includeHiddenWrites && merge.isEmpty) { + return completeServerCache; + } else { + // If the server cache is null and we don't have a complete cache, + // we need to return nil + if (!includeHiddenWrites && completeServerCache == nil && + ![merge hasCompleteWriteAtPath:[FPath empty]]) { + return nil; + } else { + BOOL (^filter)(FWriteRecord *) = ^(FWriteRecord *record) { + return (BOOL)( + (record.visible || includeHiddenWrites) && + (writeIdsToExclude == nil || + ![writeIdsToExclude + containsObject: + [NSNumber numberWithInteger:record.writeId]]) && + ([record.path contains:treePath] || + [treePath contains:record.path])); + }; + FCompoundWrite *mergeAtPath = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:filter + treeRoot:treePath]; + id layeredCache = completeServerCache + ? completeServerCache + : [FEmptyNode emptyNode]; + return [mergeAtPath applyToNode:layeredCache]; + } + } + } +} + +/** + * With optional, underlying server data, attempt to return a children node of + * children that we have complete data for. Used when creating new views, to + * pre-fill their complete event children snapshot. + */ +- (FChildrenNode *)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren { + __block id completeChildren = [FEmptyNode emptyNode]; + id topLevelSet = [self.visibleWrites completeNodeAtPath:treePath]; + if (topLevelSet != nil) { + if (![topLevelSet isLeafNode]) { + // We're shadowing everything. Return the children. + FChildrenNode *topChildrenNode = topLevelSet; + [topChildrenNode enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + completeChildren = [completeChildren updateImmediateChild:key + withNewChild:node]; + }]; + } + return completeChildren; + } else { + // Layer any children we have on top of this + // We know we don't have a top-level set, so just enumerate existing + // children, and apply any updates + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + [completeServerChildren enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FCompoundWrite *childMerge = + [merge childCompoundWriteAtPath:[[FPath alloc] initWith:key]]; + id newChildNode = [childMerge applyToNode:node]; + completeChildren = + [completeChildren updateImmediateChild:key + withNewChild:newChildNode]; + }]; + // Add any complete children we have from the set. + for (FNamedNode *node in merge.completeChildren) { + completeChildren = + [completeChildren updateImmediateChild:node.name + withNewChild:node.node]; + } + return completeChildren; + } +} + +/** + * Given that the underlying server data has updated, determine what, if + * anything, needs to be applied to the event cache. + * + * Possibilities + * + * 1. No write are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some write is completely shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events .. + * + * Either existingEventSnap or existingServerSnap must exist. + */ +- (id)calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + NSAssert(existingEventSnap != nil || existingServerSnap != nil, + @"Either existingEventSnap or existingServerSanp must exist."); + + FPath *path = [treePath child:childPath]; + if ([self.visibleWrites hasCompleteWriteAtPath:path]) { + // At this point we can probably guarantee that we're in case 2, meaning + // no events May need to check visibility while doing the + // findRootMostValueAndPath call + return nil; + } else { + // This could be more efficient if the serverNode + updates doesn't + // change the eventSnap However this is tricky to find out, since user + // updates don't necessary change the server snap, e.g. priority updates + // on empty nodes, or deep deletes. Another special case is if the + // server adds nodes, but doesn't change any existing writes. It is + // therefore not enough to only check if the updates change the + // serverNode. Maybe check if the merge tree contains these special + // cases and only do a full overwrite in that case? + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + if (childMerge.isEmpty) { + // We're not shadowing at all. Case 1 + return [existingServerSnap getChild:childPath]; + } else { + return [childMerge + applyToNode:[existingServerSnap getChild:childPath]]; + } + } +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + FPath *path = [treePath childFromString:childKey]; + id shadowingNode = [self.visibleWrites completeNodeAtPath:path]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + if ([existingServerCache isCompleteForChild:childKey]) { + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + return [childMerge applyToNode:[existingServerCache.node + getImmediateChild:childKey]]; + } else { + return nil; + } + } +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns null if + * there is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that were outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)treePath + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + __block id toIterate; + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + id shadowingNode = [merge completeNodeAtPath:[FPath empty]]; + if (shadowingNode != nil) { + toIterate = shadowingNode; + } else if (completeServerData != nil) { + toIterate = [merge applyToNode:completeServerData]; + } else { + return nil; + } + + __block NSString *currentNextKey = nil; + __block id currentNextNode = nil; + [toIterate enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if ([index compareKey:key + andNode:node + toOtherKey:post.name + andNode:post.node + reverse:reverse] > NSOrderedSame && + (!currentNextKey || [index compareKey:key + andNode:node + toOtherKey:currentNextKey + andNode:currentNextNode + reverse:reverse] < NSOrderedSame)) { + currentNextKey = key; + currentNextNode = node; + } + }]; + + if (currentNextKey != nil) { + return [FNamedNode nodeWithName:currentNextKey node:currentNextNode]; + } else { + return nil; + } +} + +#pragma mark - +#pragma mark Private Methods + +- (BOOL)record:(FWriteRecord *)record containsPath:(FPath *)path { + if ([record isOverwrite]) { + return [record.path contains:path]; + } else { + __block BOOL contains = NO; + [record.merge + enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + contains = [[record.path child:childPath] contains:path]; + *stop = contains; + }]; + return contains; + } +} + +/** + * Re-layer the writes and merges into a tree so we can efficiently calculate + * event snapshots + */ +- (void)resetTree { + self.visibleWrites = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:[FWriteTree defaultFilter] + treeRoot:[FPath empty]]; + if ([self.allWrites count] > 0) { + FWriteRecord *lastRecord = self.allWrites[[self.allWrites count] - 1]; + self.lastWriteId = lastRecord.writeId; + } else { + self.lastWriteId = -1; + } +} + +/** + * The default filter used when constructing the tree. Keep everything that's + * visible. + */ ++ (BOOL (^)(FWriteRecord *record))defaultFilter { + static BOOL (^filter)(FWriteRecord *); + static dispatch_once_t filterToken; + dispatch_once(&filterToken, ^{ + filter = ^(FWriteRecord *record) { + return YES; + }; + }); + return filter; +} + +/** + * Static method. Given an array of WriteRecords, a filter for which ones to + * include, and a path, construct a merge at that path + * @return An FImmutableTree of ids. + */ ++ (FCompoundWrite *)layerTreeFromWrites:(NSArray *)writes + filter:(BOOL (^)(FWriteRecord *record))filter + treeRoot:(FPath *)treeRoot { + __block FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + // Theory, a later set will either: + // a) abort a relevant transaction, so no need to worry about excluding it + // from calculating that transaction b) not be relevant to a transaction + // (separate branch), so again will not affect the data for that + // transaction + if (filter(record)) { + FPath *writePath = record.path; + if ([record isOverwrite]) { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addWrite:record.overwrite + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + id child = [record.overwrite + getChild:[FPath relativePathFrom:writePath to:treeRoot]]; + compoundWrite = [compoundWrite addWrite:child + atPath:[FPath empty]]; + } else { + // There is no overlap between root path and write path, + // ignore write + } + } else { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addCompoundWrite:record.merge + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + FPath *relativePath = [FPath relativePathFrom:writePath + to:treeRoot]; + if (relativePath.isEmpty) { + compoundWrite = + [compoundWrite addCompoundWrite:record.merge + atPath:[FPath empty]]; + } else { + id child = + [record.merge completeNodeAtPath:relativePath]; + if (child != nil) { + // There exists a child in this node that matches the + // root path + id deepNode = + [child getChild:[relativePath popFront]]; + compoundWrite = + [compoundWrite addWrite:deepNode + atPath:[FPath empty]]; + } + } + } else { + // There is no overlap between root path and write path, + // ignore write + } + } + } + }]; + return compoundWrite; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h new file mode 100644 index 0000000..962ad5c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FChildrenNode; +@class FPath; +@class FNamedNode; +@class FWriteRecord; +@class FWriteTree; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTreeRef : NSObject + +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree; + +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache; + +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (FChildrenNode *)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m new file mode 100644 index 0000000..809d1a9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m @@ -0,0 +1,159 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTreeRef.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" + +@interface FWriteTreeRef () +/** + * The path to this particular FWriteTreeRef. Used for calling methods on + * writeTree while exposing a simpler interface to callers. + */ +@property(nonatomic, strong) FPath *path; +/** + * A reference to the actual tree of the write data. All methods are + * pass-through to the tree, but with the appropriate path prefixed. + * + * This lets us make cheap references to points in the tree for sync points + * without having to copy and maintain all of the data. + */ +@property(nonatomic, strong) FWriteTree *writeTree; +@end + +/** + * A FWriteTreeRef wraps a FWriteTree and a FPath, for convenient access to a + * particular subtree. All the methods just proxy to the underlying FWriteTree. + */ +@implementation FWriteTreeRef +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree { + self = [super init]; + if (self) { + self.path = aPath; + self.writeTree = tree; + } + return self; +} + +/** + * @return If possible, returns a complete event cache, using the underlying + * server data if possible. In addition, can be used to get a cache that + * includes hidden writes, and excludes arbitrary writes. Note that customizing + * the returned node can lead to a more expensive calculation. + */ +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache { + return [self.writeTree calculateCompleteEventCacheAtPath:self.path + completeServerCache:completeServerCache + excludeWriteIds:nil + includeHiddenWrites:NO]; +} + +/** + * @return If possible, returns a children node containing all of the complete + * children we have data for. The returned data is a mix of the given server + * data and write data. + */ +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (id)completeServerChildren { + return [self.writeTree + calculateCompleteEventChildrenAtPath:self.path + completeServerChildren:completeServerChildren]; +} + +/** + * Given that either the underlying server data has updated or the outstanding + * writes have been updating, determine what, if anything, needs to be applied + * to the event cache. + * + * Possibilities: + * + * 1. No writes are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some writes are completly shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events should be raised. + * + * Either existingEventSnap or existingServerSnap must exist, this is validated + * via an assert. + */ +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + return [self.writeTree + calculateEventCacheAfterServerOverwriteAtPath:self.path + childPath:childPath + existingEventSnap:existingEventSnap + existingServerSnap:existingServerSnap]; +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns nil if there + * is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.writeTree shadowingWriteAtPath:[self.path child:path]]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that are outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + return [self.writeTree calculateNextNodeAfterPost:post + atPath:self.path + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + return [self.writeTree calculateCompleteChildAtPath:self.path + childKey:childKey + cache:existingServerCache]; +} + +/** + * @return a WriteTreeref for a child. + */ +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey { + return + [[FWriteTreeRef alloc] initWithPath:[self.path childFromString:childKey] + writeTree:self.writeTree]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h new file mode 100644 index 0000000..97a23bf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FPath; +@class FOperationSource; +@class FImmutableTree; + +@interface FAckUserWrite : NSObject + +- initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)affectedTree + revert:(BOOL)shouldRevert; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +// A FImmutableTree, containing @YES for each affected path. Affected paths +// can't overlap. +@property(nonatomic, strong, readonly) FImmutableTree *affectedTree; +@property(nonatomic, readonly) BOOL revert; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m new file mode 100644 index 0000000..2a1f287 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAckUserWrite.h" +#import "FImmutableTree.h" +#import "FOperationSource.h" +#import "FPath.h" + +@implementation FAckUserWrite + +- (id)initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)tree + revert:(BOOL)shouldRevert { + self = [super init]; + if (self) { + self->_source = [FOperationSource userInstance]; + self->_type = FOperationTypeAckUserWrite; + self->_path = operationPath; + self->_affectedTree = tree; + self->_revert = shouldRevert; + } + return self; +} + +- (FAckUserWrite *)operationForChild:(NSString *)childKey { + if (![self.path isEmpty]) { + NSAssert([self.path.getFront isEqualToString:childKey], + @"operationForChild called for unrelated child."); + return [[FAckUserWrite alloc] initWithPath:[self.path popFront] + affectedTree:self.affectedTree + revert:self.revert]; + } else if (self.affectedTree.value != nil) { + NSAssert(self.affectedTree.children.isEmpty, + @"affectedTree should not have overlapping affected paths."); + // All child locations are affected as well; just return same operation. + return self; + } else { + FImmutableTree *childTree = + [self.affectedTree subtreeAtPath:[[FPath alloc] initWith:childKey]]; + return [[FAckUserWrite alloc] initWithPath:[FPath empty] + affectedTree:childTree + revert:self.revert]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat: + @"FAckUserWrite { path=%@, revert=%d, affectedTree=%@ }", + self.path, self.revert, self.affectedTree]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h new file mode 100644 index 0000000..56fbec9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FCompoundWrite; + +@interface FMerge : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)children; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FCompoundWrite *children; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m new file mode 100644 index 0000000..c344755 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m @@ -0,0 +1,85 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMerge.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" + +@interface FMerge () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) FCompoundWrite *children; +@end + +@implementation FMerge + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize children; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)someChildren { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeMerge; + self.path = aPath; + self.children = someChildren; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + FCompoundWrite *childTree = [self.children + childCompoundWriteAtPath:[[FPath alloc] initWith:childKey]]; + if (childTree.isEmpty) { + return nil; + } else if (childTree.rootWrite != nil) { + // We have a snapshot for the child in question. This becomes an + // overwrite of the child. + return [[FOverwrite alloc] initWithSource:self.source + path:[FPath empty] + snap:childTree.rootWrite]; + } else { + // This is a merge at a deeper level + return [[FMerge alloc] initWithSource:self.source + path:[FPath empty] + children:childTree]; + } + } else { + NSAssert( + [self.path.getFront isEqualToString:childKey], + @"Can't get a merge for a child not on the path of the operation"); + return [[FMerge alloc] initWithSource:self.source + path:[self.path popFront] + children:self.children]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"FMerge { path=%@, soruce=%@ children=%@}", + self.path, self.source, self.children]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h new file mode 100644 index 0000000..41f6054 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FOperationSource; +@class FPath; + +typedef NS_ENUM(NSInteger, FOperationType) { + FOperationTypeOverwrite = 0, + FOperationTypeMerge = 1, + FOperationTypeAckUserWrite = 2, + FOperationTypeListenComplete = 3 +}; + +@protocol FOperation +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +- (id)operationForChild:(NSString *)childKey; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h new file mode 100644 index 0000000..747487b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQueryParams; + +@interface FOperationSource : NSObject + +@property(nonatomic, readonly) BOOL fromUser; +@property(nonatomic, readonly) BOOL fromServer; +@property(nonatomic, readonly) BOOL isTagged; +@property(nonatomic, strong, readonly) FQueryParams *queryParams; + +- initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)isTagged; + ++ (FOperationSource *)userInstance; ++ (FOperationSource *)serverInstance; ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m new file mode 100644 index 0000000..92e3db8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FOperationSource () +@property(nonatomic, readwrite) BOOL fromUser; +@property(nonatomic, readwrite) BOOL fromServer; +@property(nonatomic, readwrite) BOOL isTagged; +@property(nonatomic, strong, readwrite) FQueryParams *queryParams; +@end + +@implementation FOperationSource + +@synthesize fromUser; +@synthesize fromServer; +@synthesize queryParams; + +- (id)initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)tagged { + self = [super init]; + if (self) { + self.fromUser = isFromUser; + self.fromServer = isFromServer; + self.queryParams = params; + self.isTagged = tagged; + } + return self; +} + ++ (FOperationSource *)userInstance { + static FOperationSource *user = nil; + static dispatch_once_t userToken; + dispatch_once(&userToken, ^{ + user = [[FOperationSource alloc] initWithFromUser:YES + fromServer:NO + queryParams:nil + tagged:NO]; + }); + return user; +} + ++ (FOperationSource *)serverInstance { + static FOperationSource *server = nil; + static dispatch_once_t serverToken; + dispatch_once(&serverToken, ^{ + server = [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:nil + tagged:NO]; + }); + return server; +} + ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params { + return [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:params + tagged:YES]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FOperationSource { fromUser=%d, " + @"fromServer=%d, queryId=%@, tagged=%d }", + self.fromUser, self.fromServer, + self.queryParams, self.isTagged]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h new file mode 100644 index 0000000..7d738ac --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@protocol FNode; + +@interface FOverwrite : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id snap; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m new file mode 100644 index 0000000..ad4daec --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOverwrite.h" +#import "FNode.h" +#import "FOperationSource.h" + +@interface FOverwrite () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) id snap; +@end + +@implementation FOverwrite + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize snap; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeOverwrite; + self.path = aPath; + self.snap = aSnap; + } + return self; +} + +- (FOverwrite *)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FOverwrite alloc] + initWithSource:self.source + path:[FPath empty] + snap:[self.snap getImmediateChild:childKey]]; + } else { + return [[FOverwrite alloc] initWithSource:self.source + path:[self.path popFront] + snap:self.snap]; + } +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"FOverwrite { path=%@, source=%@, snapshot=%@ }", + self.path, self.source, self.snap]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h new file mode 100644 index 0000000..a63d0d8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRRetryHelper : NSObject + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor; + +- (void)retry:(void (^)(void))block; + +- (void)cancel; + +- (void)signalSuccess; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m new file mode 100644 index 0000000..ef24d12 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRRetryHelper.h" +#import "FUtilities.h" +#import + +@interface FIRRetryHelperTask : NSObject + +@property(nonatomic, strong) void (^block)(void); + +@end + +@implementation FIRRetryHelperTask + +- (instancetype)initWithBlock:(void (^)(void))block { + self = [super init]; + if (self != nil) { + self->_block = [block copy]; + } + return self; +} + +- (BOOL)isCanceled { + return self.block == nil; +} + +- (void)cancel { + self.block = nil; +} + +- (void)execute { + if (self.block) { + self.block(); + } +} + +@end + +@interface FIRRetryHelper () + +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic) NSTimeInterval minRetryDelayAfterFailure; +@property(nonatomic) NSTimeInterval maxRetryDelay; +@property(nonatomic) double retryExponent; +@property(nonatomic) double jitterFactor; + +@property(nonatomic) BOOL lastWasSuccess; +@property(nonatomic) NSTimeInterval currentRetryDelay; + +@property(nonatomic, strong) FIRRetryHelperTask *scheduledRetry; + +@end + +@implementation FIRRetryHelper + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor { + self = [super init]; + if (self != nil) { + self->_dispatchQueue = dispatchQueue; + self->_minRetryDelayAfterFailure = minRetryDelayAfterFailure; + self->_maxRetryDelay = maxRetryDelay; + self->_retryExponent = retryExponent; + self->_jitterFactor = jitterFactor; + self->_lastWasSuccess = YES; + } + return self; +} + +- (void)retry:(void (^)(void))block { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054001", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } + + NSTimeInterval delay; + if (self.lastWasSuccess) { + delay = 0; + } else { + if (self.currentRetryDelay == 0) { + self.currentRetryDelay = self.minRetryDelayAfterFailure; + } else { + NSTimeInterval newDelay = + (self.currentRetryDelay * self.retryExponent); + self.currentRetryDelay = MIN(newDelay, self.maxRetryDelay); + } + + delay = ((1 - self.jitterFactor) * self.currentRetryDelay) + + (self.jitterFactor * self.currentRetryDelay * + [FUtilities randomDouble]); + FFLog(@"I-RDB054002", @"Scheduling retry in %fs", delay); + } + self.lastWasSuccess = NO; + FIRRetryHelperTask *task = [[FIRRetryHelperTask alloc] initWithBlock:block]; + self.scheduledRetry = task; + dispatch_time_t popTime = + dispatch_time(DISPATCH_TIME_NOW, (long long)(delay * NSEC_PER_SEC)); + dispatch_after(popTime, self.dispatchQueue, ^{ + if (![task isCanceled]) { + self.scheduledRetry = nil; + [task execute]; + } + }); +} + +- (void)signalSuccess { + self.lastWasSuccess = YES; + self.currentRetryDelay = 0; +} + +- (void)cancel { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054003", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } else { + FFLog(@"I-RDB054004", @"No existing retry attempt to cancel"); + } + self.currentRetryDelay = 0; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h new file mode 100644 index 0000000..e6d4961 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FTuplePathValue.h" + +@interface FImmutableTree : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap; + ++ (FImmutableTree *)empty; +- (BOOL)isEmpty; + +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id))predicate; +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath; +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath; +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath; +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath; +- (id)valueAtPath:(FPath *)relativePath; +- (id)rootMostValueOnPath:(FPath *)path; +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate; +- (id)leafMostValueOnPath:(FPath *)path; +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate; +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate; +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath; +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block; +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block; +- (FPath *)forEachOnPath:(FPath *)path + whileBlock:(BOOL (^)(FPath *path, id value))block; +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block; +- (void)forEach:(void (^)(FPath *path, id value))block; +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block; + +@property(nonatomic, strong, readonly) id value; +@property(nonatomic, strong, readonly) FImmutableSortedDictionary *children; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m new file mode 100644 index 0000000..34e62ae --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m @@ -0,0 +1,486 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableTree.h" +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FUtilities.h" + +@interface FImmutableTree () +@property(nonatomic, strong, readwrite) id value; +/** + * Maps NSString -> FImmutableTree, where is type of value. + */ +@property(nonatomic, strong, readwrite) FImmutableSortedDictionary *children; +@end + +@implementation FImmutableTree +@synthesize value; +@synthesize children; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.children = [FImmutableTree emptyChildren]; + } + return self; +} + +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap { + self = [super init]; + if (self) { + self.value = aValue; + self.children = childrenMap; + } + return self; +} + ++ (FImmutableSortedDictionary *)emptyChildren { + static dispatch_once_t emptyChildrenToken; + static FImmutableSortedDictionary *emptyChildren; + dispatch_once(&emptyChildrenToken, ^{ + emptyChildren = [FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities stringComparator]]; + }); + return emptyChildren; +} + ++ (FImmutableTree *)empty { + static dispatch_once_t emptyImmutableTreeToken; + static FImmutableTree *emptyTree = nil; + dispatch_once(&emptyImmutableTreeToken, ^{ + emptyTree = [[FImmutableTree alloc] initWithValue:nil]; + }); + return emptyTree; +} + +- (BOOL)isEmpty { + return self.value == nil && [self.children isEmpty]; +} + +/** + * Given a path and a predicate, return the first node and the path to that node + * where the predicate returns true + * // TODO Do a perf test. If we're creating a bunch of FTuplePathValue objects + * on the way back out, it may be better to pass down a pathSoFar FPath + */ +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id value))predicate { + if (self.value != nil && predicate(self.value)) { + return [[FTuplePathValue alloc] initWithPath:[FPath empty] + value:self.value]; + } else { + if ([relativePath isEmpty]) { + return nil; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child != nil) { + FTuplePathValue *childExistingPathAndValue = + [child findRootMostMatchingPath:[relativePath popFront] + predicate:predicate]; + if (childExistingPathAndValue != nil) { + FPath *fullPath = [[[FPath alloc] initWith:front] + child:childExistingPathAndValue.path]; + return [[FTuplePathValue alloc] + initWithPath:fullPath + value:childExistingPathAndValue.value]; + } else { + return nil; + } + } else { + // No child matching path + return nil; + } + } + } +} + +/** + * Find, if it exists, the shortest subpath of the given path that points a + * defined value in the tree + */ +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath { + return [self findRootMostMatchingPath:relativePath + predicate:^BOOL(__unsafe_unretained id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path { + return [self rootMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return self.value; + } else if (path.isEmpty) { + return nil; + } else { + return [[self.children get:path.getFront] + rootMostValueOnPath:[path popFront] + matching:predicate]; + } +} + +- (id)leafMostValueOnPath:(FPath *)path { + return [self leafMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate { + __block id currentValue = self.value; + __block FImmutableTree *currentTree = self; + [relativePath enumerateComponentsUsingBlock:^(NSString *key, BOOL *stop) { + currentTree = [currentTree.children get:key]; + if (currentTree == nil) { + *stop = YES; + } else { + id treeValue = currentTree.value; + if (treeValue != nil && predicate(treeValue)) { + currentValue = treeValue; + } + } + }]; + return currentValue; +} + +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return YES; + } else { + __block BOOL found = NO; + [self.children enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *subtree, BOOL *stop) { + found = [subtree containsValueMatching:predicate]; + if (found) + *stop = YES; + }]; + return found; + } +} + +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *childTree = [self.children get:front]; + if (childTree != nil) { + return [childTree subtreeAtPath:[relativePath popFront]]; + } else { + return [FImmutableTree empty]; + } + } +} + +/** + * Sets a value at the specified path + */ +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return [[FImmutableTree alloc] initWithValue:newValue + children:self.children]; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setValue:newValue + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren = + [self.children insertKey:front withValue:newChild]; + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Remove the value at the specified path + */ +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + if ([self.children isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:nil + children:self.children]; + } + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + FImmutableTree *newChild = + [child removeValueAtPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front + withValue:newChild]; + } + if (self.value == nil && [newChildren isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } + } else { + return self; + } + } +} + +/** + * Gets a value from the tree + */ +- (id)valueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self.value; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + return [child valueAtPath:[relativePath popFront]]; + } else { + return nil; + } + } +} + +/** + * Replaces the subtree at the specified path with the given new tree + */ +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return newTree; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setTree:newTree + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front withValue:newChild]; + } + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Performs a depth first fold on this tree. Transforms a tree into a single + * value, given a function that operates on the path to a node, an optional + * current value, and a map of the child names to folded subtrees + */ +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + return [self foldWithPathSoFar:[FPath empty] withBlock:block]; +} + +/** + * Recursive helper for public facing foldWithBlock: method + */ +- (id)foldWithPathSoFar:(FPath *)pathSoFar + withBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + __block NSMutableDictionary *accum = [[NSMutableDictionary alloc] init]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + accum[childKey] = + [childTree foldWithPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + return block(pathSoFar, self.value, accum); +} + +/** + * Find the first matching value on the given path. Return the result of + * applying block to it. + */ +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block { + return [self findOnPath:path pathSoFar:[FPath empty] andApplyBlock:block]; +} + +- (id)findOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + andApplyBlock:(id (^)(FPath *path, id value))block { + id result = self.value ? block(pathSoFar, self.value) : nil; + if (result != nil) { + return result; + } else { + if ([pathToFollow isEmpty]) { + return nil; + } else { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild != nil) { + return [nextChild findOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + andApplyBlock:block]; + } else { + return nil; + } + } + } +} +/** + * Call the block on each value along the path for as long as that function + * returns true + * @return The path to the deepest location inspected + */ +- (FPath *)forEachOnPath:(FPath *)path whileBlock:(BOOL (^)(FPath *, id))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] whileBlock:block]; +} + +- (FPath *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + whileBlock:(BOOL (^)(FPath *, id))block { + if ([pathToFollow isEmpty]) { + if (self.value) { + block(pathSoFar, self.value); + } + return pathSoFar; + } else { + BOOL shouldContinue = YES; + if (self.value) { + shouldContinue = block(pathSoFar, self.value); + } + if (shouldContinue) { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return + [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + whileBlock:block]; + } else { + return pathSoFar; + } + } else { + return pathSoFar; + } + } +} + +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] performBlock:block]; +} + +- (FImmutableTree *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + performBlock:(void (^)(FPath *path, id value))block { + if ([pathToFollow isEmpty]) { + return self; + } else { + if (self.value) { + block(pathSoFar, self.value); + } + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + performBlock:block]; + } else { + return [FImmutableTree empty]; + } + } +} +/** + * Calls the given block for each node in the tree that has a value. Called in + * depth-first order + */ +- (void)forEach:(void (^)(FPath *path, id value))block { + [self forEachPathSoFar:[FPath empty] withBlock:block]; +} + +- (void)forEachPathSoFar:(FPath *)pathSoFar + withBlock:(void (^)(FPath *path, id value))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [childTree forEachPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + if (self.value) { + block(pathSoFar, self.value); + } +} + +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value) { + block(childKey, childTree.value); + } + }]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableTree class]]) { + return NO; + } + FImmutableTree *other = (FImmutableTree *)object; + return (self.value == other.value || [self.value isEqual:other.value]) && + [self.children isEqual:other.children]; +} + +- (NSUInteger)hash { + return self.children.hash * 31 + [self.value hash]; +} + +- (NSString *)description { + NSMutableString *string = [[NSMutableString alloc] init]; + [string appendString:@"FImmutableTree { value="]; + [string appendString:(self.value ? [self.value description] : @"")]; + [string appendString:@", children={"]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [string appendString:@" "]; + [string appendString:childKey]; + [string appendString:@"="]; + [string appendString:[childTree.value description]]; + }]; + [string appendString:@" } }"]; + return [NSString stringWithString:string]; +} + +- (NSString *)debugDescription { + return [self description]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h new file mode 100644 index 0000000..cfa86aa --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FPath : NSObject + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner; ++ (FPath *)empty; ++ (FPath *)pathWithString:(NSString *)string; + +- (id)initWith:(NSString *)path; +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum; + +- (id)copyWithZone:(NSZone *)zone; + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *key, + BOOL *stop))block; +- (NSString *)getFront; +- (NSUInteger)length; +- (FPath *)popFront; +- (NSString *)getBack; +- (NSString *)toString; +- (NSString *)toStringWithTrailingSlash; +- (NSString *)wireFormat; +- (FPath *)parent; +- (FPath *)child:(FPath *)childPathObj; +- (FPath *)childFromString:(NSString *)childPath; +- (BOOL)isEmpty; +- (BOOL)contains:(FPath *)other; +- (NSComparisonResult)compare:(FPath *)other; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m new file mode 100644 index 0000000..f655240 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" + +#import "FUtilities.h" + +@interface FPath () + +@property(nonatomic, readwrite, assign) NSInteger pieceNum; +@property(nonatomic, strong) NSArray *pieces; + +@end + +@implementation FPath + +#pragma mark - +#pragma mark Initializers + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner { + NSString *outerFront = [outer getFront]; + NSString *innerFront = [inner getFront]; + if (outerFront == nil) { + return inner; + } else if ([outerFront isEqualToString:innerFront]) { + return [self relativePathFrom:[outer popFront] to:[inner popFront]]; + } else { + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:[NSString + stringWithFormat: + @"innerPath (%@) is not within outerPath (%@)", + inner, outer] + userInfo:nil]; + } +} + ++ (FPath *)pathWithString:(NSString *)string { + return [[FPath alloc] initWith:string]; +} + +- (id)initWith:(NSString *)path { + self = [super init]; + if (self) { + NSArray *pathPieces = [path componentsSeparatedByString:@"/"]; + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + self.pieces = newPieces; + self.pieceNum = 0; + } + return self; +} + +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum { + self = [super init]; + if (self) { + self.pieceNum = aPieceNum; + self.pieces = somePieces; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable, so it's safe to return self + return self; +} + +- (NSString *)description { + return [self toString]; +} + +#pragma mark - +#pragma mark Public methods + +- (NSString *)getFront { + if (self.pieceNum >= self.pieces.count) { + return nil; + } + return [self.pieces objectAtIndex:self.pieceNum]; +} + +/** + * @return The number of segments in this path + */ +- (NSUInteger)length { + return self.pieces.count - self.pieceNum; +} + +- (FPath *)popFront { + NSInteger newPieceNum = self.pieceNum; + if (newPieceNum < self.pieces.count) { + newPieceNum++; + } + return [[FPath alloc] initWithPieces:self.pieces andPieceNum:newPieceNum]; +} + +- (NSString *)getBack { + if (self.pieceNum < self.pieces.count) { + return [self.pieces lastObject]; + } else { + return nil; + } +} + +- (NSString *)toString { + return [self toStringWithTrailingSlash:NO]; +} + +- (NSString *)toStringWithTrailingSlash { + return [self toStringWithTrailingSlash:YES]; +} + +- (NSString *)toStringWithTrailingSlash:(BOOL)trailingSlash { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [pathString appendString:@"/"]; + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + if ([pathString length] == 0) { + return @"/"; + } else { + if (trailingSlash) { + [pathString appendString:@"/"]; + } + return pathString; + } +} + +- (NSString *)wireFormat { + if ([self isEmpty]) { + return @"/"; + } else { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + if (i > self.pieceNum) { + [pathString appendString:@"/"]; + } + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + return pathString; + } +} + +- (FPath *)parent { + if (self.pieceNum >= self.pieces.count) { + return nil; + } else { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count - 1; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; + } +} + +- (FPath *)child:(FPath *)childPathObj { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + for (NSInteger i = childPathObj.pieceNum; i < childPathObj.pieces.count; + i++) { + [newPieces addObject:[childPathObj.pieces objectAtIndex:i]]; + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +- (FPath *)childFromString:(NSString *)childPath { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + NSArray *pathPieces = [childPath componentsSeparatedByString:@"/"]; + for (unsigned int i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +/** + * @return True if there are no segments in this path + */ +- (BOOL)isEmpty { + return self.pieceNum >= self.pieces.count; +} + +/** + * @return Singleton to represent an empty path + */ ++ (FPath *)empty { + static dispatch_once_t oneEmptyPath; + static FPath *emptyPath; + dispatch_once(&oneEmptyPath, ^{ + emptyPath = [[FPath alloc] initWith:@""]; + }); + return emptyPath; +} + +- (BOOL)contains:(FPath *)other { + if (self.length > other.length) { + return NO; + } + + NSInteger i = self.pieceNum; + NSInteger j = other.pieceNum; + while (i < self.pieces.count) { + NSString *thisSeg = [self.pieces objectAtIndex:i]; + NSString *otherSeg = [other.pieces objectAtIndex:j]; + if (![thisSeg isEqualToString:otherSeg]) { + return NO; + } + ++i; + ++j; + } + return YES; +} + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *, BOOL *))block { + BOOL stop = NO; + for (NSInteger i = self.pieceNum; !stop && i < self.pieces.count; i++) { + block(self.pieces[i], &stop); + } +} + +- (NSComparisonResult)compare:(FPath *)other { + NSInteger myCount = self.pieces.count; + NSInteger otherCount = other.pieces.count; + for (NSInteger i = self.pieceNum, j = other.pieceNum; + i < myCount && j < otherCount; i++, j++) { + NSComparisonResult comparison = [FUtilities compareKey:self.pieces[i] + toKey:other.pieces[j]]; + if (comparison != NSOrderedSame) { + return comparison; + } + } + if (self.length < other.length) { + return NSOrderedAscending; + } else if (other.length < self.length) { + return NSOrderedDescending; + } else { + NSAssert(self.length == other.length, + @"Paths must be the same lengths"); + return NSOrderedSame; + } +} + +/** + * @return YES if paths are the same + */ +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (!other || ![other isKindOfClass:[self class]]) { + return NO; + } + FPath *otherPath = (FPath *)other; + if (self.length != otherPath.length) { + return NO; + } + for (NSUInteger i = self.pieceNum, j = otherPath.pieceNum; + i < self.pieces.count; i++, j++) { + if (![self.pieces[i] isEqualToString:otherPath.pieces[j]]) { + return NO; + } + } + return YES; +} + +- (NSUInteger)hash { + NSUInteger hashCode = 0; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + hashCode = hashCode * 37 + [self.pieces[i] hash]; + } + return hashCode; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h new file mode 100644 index 0000000..d5c77ab --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTreeNode.h" +#import + +@interface FTree : NSObject + +- (id)init; +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode; + +- (FTree *)subTree:(FPath *)path; +- (id)getValue; +- (void)setValue:(id)value; +- (void)clear; +- (BOOL)hasChildren; +- (BOOL)isEmpty; +- (void)forEachChildMutationSafe:(void (^)(FTree *))action; +- (void)forEachChild:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf; +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action; +- (BOOL)valueExistsAtOrAbove:(FPath *)path; +- (FPath *)path; +- (void)updateParents; +- (void)updateChild:(NSString *)childName withNode:(FTree *)child; + +@property(nonatomic, strong) NSString *name; +@property(nonatomic, strong) FTree *parent; +@property(nonatomic, strong) FTreeNode *node; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m new file mode 100644 index 0000000..209b59f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m @@ -0,0 +1,193 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTree.h" +#import "FPath.h" +#import "FTreeNode.h" +#import "FUtilities.h" + +@implementation FTree + +@synthesize name; +@synthesize parent; +@synthesize node; + +- (id)init { + self = [super init]; + if (self) { + self.name = @""; + self.parent = nil; + self.node = [[FTreeNode alloc] init]; + } + return self; +} + +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode { + self = [super init]; + if (self) { + self.name = aName != nil ? aName : @""; + self.parent = aParent != nil ? aParent : nil; + self.node = aNode != nil ? aNode : [[FTreeNode alloc] init]; + } + return self; +} + +- (FTree *)subTree:(FPath *)path { + FTree *child = self; + NSString *next = [path getFront]; + while (next != nil) { + FTreeNode *childNode = child.node.children[next]; + if (childNode == nil) { + childNode = [[FTreeNode alloc] init]; + } + child = [[FTree alloc] initWithName:next + withParent:child + withNode:childNode]; + path = [path popFront]; + next = [path getFront]; + } + return child; +} + +- (id)getValue { + return self.node.value; +} + +- (void)setValue:(id)value { + self.node.value = value; + [self updateParents]; +} + +- (void)clear { + self.node.value = nil; + [self.node.children removeAllObjects]; + self.node.childCount = 0; + [self updateParents]; +} + +- (BOOL)hasChildren { + return self.node.childCount > 0; +} + +- (BOOL)isEmpty { + return [self getValue] == nil && ![self hasChildren]; +} + +- (void)forEachChild:(void (^)(FTree *))action { + for (NSString *key in self.node.children) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachChildMutationSafe:(void (^)(FTree *))action { + for (NSString *key in [self.node.children copy]) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachDescendant:(void (^)(FTree *))action { + [self forEachDescendant:action includeSelf:NO childrenFirst:NO]; +} + +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst { + if (incSelf && !childFirst) { + action(self); + } + + [self forEachChild:^(FTree *child) { + [child forEachDescendant:action includeSelf:YES childrenFirst:childFirst]; + }]; + + if (incSelf && childFirst) { + action(self); + } +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action { + return [self forEachAncestor:action includeSelf:NO]; +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf { + FTree *aNode = (incSelf) ? self : self.parent; + while (aNode != nil) { + if (action(aNode)) { + return YES; + } + aNode = aNode.parent; + } + return NO; +} + +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action { + [self forEachChild:^(FTree *child) { + if ([child getValue] != nil) { + action(child); + } else { + [child forEachImmediateDescendantWithValue:action]; + } + }]; +} + +- (BOOL)valueExistsAtOrAbove:(FPath *)path { + FTreeNode *aNode = self.node; + while (aNode != nil) { + if (aNode.value != nil) { + return YES; + } + aNode = [aNode.children objectForKey:path.getFront]; + path = [path popFront]; + } + // XXX Check with Michael if this is correct; deviates from JS. + return NO; +} + +- (FPath *)path { + return [[FPath alloc] + initWith:(self.parent == nil) + ? self.name + : [NSString stringWithFormat:@"%@/%@", [self.parent path], + self.name]]; +} + +- (void)updateParents { + [self.parent updateChild:self.name withNode:self]; +} + +- (void)updateChild:(NSString *)childName withNode:(FTree *)child { + BOOL childEmpty = [child isEmpty]; + BOOL childExists = self.node.children[childName] != nil; + if (childEmpty && childExists) { + [self.node.children removeObjectForKey:childName]; + self.node.childCount = self.node.childCount - 1; + [self updateParents]; + } else if (!childEmpty && !childExists) { + [self.node.children setObject:child.node forKey:childName]; + self.node.childCount = self.node.childCount + 1; + [self updateParents]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h new file mode 100644 index 0000000..549f3b1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTreeNode : NSObject + +@property(nonatomic, strong) NSMutableDictionary *children; +@property(nonatomic, readwrite, assign) int childCount; +@property(nonatomic, strong) id value; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m new file mode 100644 index 0000000..bae6c62 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTreeNode.h" + +@implementation FTreeNode + +@synthesize children; +@synthesize childCount; +@synthesize value; + +- (id)init { + self = [super init]; + if (self) { + self.children = [[NSMutableDictionary alloc] init]; + self.childCount = 0; + self.value = nil; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h new file mode 100644 index 0000000..eff0cb0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@class FPath; + +/** + * A cache node only stores complete children. Additionally it holds a flag + * whether the node can be considered fully initialized in the sense that we + * know at one point in time, this represented a valid state of the world, e.g. + * initialized with data from the server, or a complete overwrite by the client. + * It is not necessarily complete because it may have been from a tagged query. + * The filtered flag also tracks whether a node potentially had children removed + * due to a filter. + */ +@interface FCacheNode : NSObject + +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered; + +- (BOOL)isCompleteForPath:(FPath *)path; +- (BOOL)isCompleteForChild:(NSString *)childKey; + +@property(nonatomic, readonly) BOOL isFullyInitialized; +@property(nonatomic, readonly) BOOL isFiltered; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) id node; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m new file mode 100644 index 0000000..a991d52 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FPath.h" + +@interface FCacheNode () +@property(nonatomic, readwrite) BOOL isFullyInitialized; +@property(nonatomic, readwrite) BOOL isFiltered; +@property(nonatomic, strong, readwrite) FIndexedNode *indexedNode; +@end + +@implementation FCacheNode +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered { + self = [super init]; + if (self) { + self.indexedNode = indexedNode; + self.isFullyInitialized = fullyInitialized; + self.isFiltered = filtered; + } + return self; +} + +- (BOOL)isCompleteForPath:(FPath *)path { + if (path.isEmpty) { + return self.isFullyInitialized && !self.isFiltered; + } else { + NSString *childKey = [path getFront]; + return [self isCompleteForChild:childKey]; + } +} + +- (BOOL)isCompleteForChild:(NSString *)childKey { + return (self.isFullyInitialized && !self.isFiltered) || + [self.node hasChild:childKey]; +} + +- (id)node { + return self.indexedNode.node; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h new file mode 100644 index 0000000..dd58642 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import + +@protocol FEventRegistration; + +@interface FCancelEvent : NSObject + +- initWithEventRegistration:(id)eventRegistration + error:(NSError *)error + path:(FPath *)path; + +@property(nonatomic, strong, readonly) NSError *error; +@property(nonatomic, strong, readonly) FPath *path; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m new file mode 100644 index 0000000..b069a71 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCancelEvent.h" +#import "FEventRegistration.h" +#import "FPath.h" + +@interface FCancelEvent () +@property(nonatomic, strong) id eventRegistration; +@property(nonatomic, strong, readwrite) NSError *error; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FCancelEvent + +@synthesize eventRegistration; +@synthesize error; +@synthesize path; + +- (id)initWithEventRegistration:(id)registration + error:(NSError *)anError + path:(FPath *)aPath { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.error = anError; + self.path = aPath; + } + return self; +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return YES; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@: cancel", self.path]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h new file mode 100644 index 0000000..101ec8f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import + +@interface FChange : NSObject + +@property(nonatomic, readonly) FIRDataEventType type; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) NSString *childKey; +@property(nonatomic, strong, readonly) NSString *prevKey; +@property(nonatomic, strong, readonly) FIndexedNode *oldIndexedNode; + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode; + +- (FChange *)changeWithPrevKey:(NSString *)prevKey; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m new file mode 100644 index 0000000..8ad1cfc --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" + +@interface FChange () + +@property(nonatomic, strong, readwrite) NSString *prevKey; + +@end + +@implementation FChange + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode { + return [self initWithType:type + indexedNode:indexedNode + childKey:nil + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey { + return [self initWithType:type + indexedNode:indexedNode + childKey:childKey + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode { + self = [super init]; + if (self != nil) { + self->_type = type; + self->_indexedNode = indexedNode; + self->_childKey = childKey; + self->_oldIndexedNode = oldIndexedNode; + } + return self; +} + +- (FChange *)changeWithPrevKey:(NSString *)prevKey { + FChange *newChange = [[FChange alloc] initWithType:self.type + indexedNode:self.indexedNode + childKey:self.childKey + oldIndexedNode:self.oldIndexedNode]; + newChange.prevKey = prevKey; + return newChange; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event: %d, data: %@", (int)self.type, + [self.indexedNode.node val]]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h new file mode 100644 index 0000000..0b0c633 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FChildEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +/** + * Maps FIRDataEventType (as NSNumber) to fbt_void_datasnapshot_nsstring + */ +@property(nonatomic, copy, readonly) NSDictionary *callbacks; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m new file mode 100644 index 0000000..1b688c1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import + +@interface FChildEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) NSDictionary *callbacks; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FChildEventRegistration + +- (id)initWithRepo:(id)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callbacks = callbackBlocks; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return self.callbacks != nil && + [self.callbacks + objectForKey:[NSNumber numberWithInteger:eventType]] != nil; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[query.path childFromString:change.childKey]]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:change.type + eventRegistration:self + dataSnapshot:snapshot + prevName:change.prevKey]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB061001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callbacks != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB061002", @"Raising event callback (%ld) on %@", + (long)dataEvent.eventType, dataEvent.path); + fbt_void_datasnapshot_nsstring callback = [self.callbacks + objectForKey:[NSNumber numberWithInteger:dataEvent.eventType]]; + + if (callback != nil) { + dispatch_async(queue, ^{ + callback(dataEvent.snapshot, dataEvent.prevName); + }); + } + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h new file mode 100644 index 0000000..a0d28f9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabaseReference.h" +#import "FTupleUserCallback.h" +#import + +@protocol FEventRegistration; +@protocol FIndex; + +@interface FDataEvent : NSObject + +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot; +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)snapshot + prevName:(NSString *)prevName; + +@property(nonatomic, strong, readonly) id eventRegistration; +@property(nonatomic, strong, readonly) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readonly) NSString *prevName; +@property(nonatomic, readonly) FIRDataEventType eventType; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m new file mode 100644 index 0000000..886a21e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FDataEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndex.h" + +@interface FDataEvent () +@property(nonatomic, strong, readwrite) id + eventRegistration; +@property(nonatomic, strong, readwrite) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readwrite) NSString *prevName; +@property(nonatomic, readwrite) FIRDataEventType eventType; +@end + +@implementation FDataEvent + +@synthesize eventRegistration; +@synthesize snapshot; +@synthesize prevName; +@synthesize eventType; + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot { + return [self initWithEventType:type + eventRegistration:registration + dataSnapshot:dataSnapshot + prevName:nil]; +} + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot + prevName:(NSString *)previousName { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.snapshot = dataSnapshot; + self.prevName = previousName; + self.eventType = type; + } + return self; +} + +- (FPath *)path { + // Used for logging, so delay calculation + FIRDatabaseReference *ref = self.snapshot.ref; + if (self.eventType == FIRDataEventTypeValue) { + return ref.path; + } else { + return ref.parent.path; + } +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return NO; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event %d, data: %@", (int)eventType, + [snapshot value]]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h new file mode 100644 index 0000000..cddcf73 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import + +@class FPath; + +@protocol FEvent +- (FPath *)path; +- (void)fireEventOnQueue:(dispatch_queue_t)queue; +- (BOOL)isCancelEvent; +- (NSString *)description; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h new file mode 100644 index 0000000..c46bff5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" + +@class FPath; +@class FRepo; +@class FIRDatabaseConfig; + +/** + * Left as instance methods rather than class methods so that we could + * potentially callback on different queues for different repos. This is + * semi-parallel to JS's FEventQueue + */ +@interface FEventRaiser : NSObject + +- (id)initWithQueue:(dispatch_queue_t)queue; + +- (void)raiseEvents:(NSArray *)eventDataList; +- (void)raiseCallback:(fbt_void_void)callback; +- (void)raiseCallbacks:(NSArray *)callbackList; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m new file mode 100644 index 0000000..d745358 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRaiser.h" +#import "FDataEvent.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTupleUserCallback.h" +#import "FTypedefs.h" +#import "FUtilities.h" + +@interface FEventRaiser () + +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +/** + * This class exists for symmetry with other clients, but since events are + * async, we don't need to do the complicated stuff the JS client does to + * preserve event order. + */ +@implementation FEventRaiser + +- (id)init { + [NSException raise:NSInternalInconsistencyException + format:@"Can't use default constructor"]; + return nil; +} + +- (id)initWithQueue:(dispatch_queue_t)queue { + self = [super init]; + if (self != nil) { + self->_queue = queue; + } + return self; +} + +- (void)raiseEvents:(NSArray *)eventDataList { + for (id event in eventDataList) { + [event fireEventOnQueue:self.queue]; + } +} + +- (void)raiseCallback:(fbt_void_void)callback { + dispatch_async(self.queue, callback); +} + +- (void)raiseCallbacks:(NSArray *)callbackList { + for (fbt_void_void callback in callbackList) { + dispatch_async(self.queue, callback); + } +} + ++ (void)raiseCallbacks:(NSArray *)callbackList queue:(dispatch_queue_t)queue { + for (fbt_void_void callback in callbackList) { + dispatch_async(queue, callback); + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h new file mode 100644 index 0000000..79a2eb0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" +#import "FIRDataEventType.h" +#import + +@protocol FEvent; +@class FDataEvent; +@class FCancelEvent; +@class FQuerySpec; + +@protocol FEventRegistration +- (BOOL)responseTo:(FIRDataEventType)eventType; +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query; +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue; +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path; +/** + * Used to figure out what event registration match the event registration that + * needs to be removed. + */ +- (BOOL)matches:(id)other; +@property(nonatomic, readonly) FIRDatabaseHandle handle; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h new file mode 100644 index 0000000..d4dca60 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FEventRegistration.h" + +/** + * A singleton event registration to mark a query as keep synced + */ +@interface FKeepSyncedEventRegistration : NSObject + ++ (FKeepSyncedEventRegistration *)instance; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m new file mode 100644 index 0000000..1821829 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeepSyncedEventRegistration.h" + +@interface FKeepSyncedEventRegistration () + +@end + +@implementation FKeepSyncedEventRegistration + ++ (FKeepSyncedEventRegistration *)instance { + static dispatch_once_t onceToken; + static FKeepSyncedEventRegistration *keepSynced; + dispatch_once(&onceToken, ^{ + keepSynced = [[FKeepSyncedEventRegistration alloc] init]; + }); + return keepSynced; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return NO; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never create event for FKeepSyncedEventRegistration"]; + return nil; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never raise event for FKeepSyncedEventRegistration"]; +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + // Don't create cancel events.... + return nil; +} + +- (FIRDatabaseHandle)handle { + // TODO[offline]: returning arbitray, can't return NSNotFound since that is + // used to match other event registrations We should really redo this to + // match on different kind of events (single observer, all observers, + // cancelled) rather than on a NSNotFound handle... + return NSNotFound - 1; +} + +- (BOOL)matches:(id)other { + // Only matches singleton instance + return self == other; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h new file mode 100644 index 0000000..819febe --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FValueEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +@property(nonatomic, copy, readonly) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m new file mode 100644 index 0000000..ad9368b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import + +@interface FValueEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FValueEventRegistration + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callback = callbackBlock; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return eventType == FIRDataEventTypeValue; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:query.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:FIRDataEventTypeValue + eventRegistration:self + dataSnapshot:snapshot]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB065001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callback != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB065002", @"Raising value event on %@", + dataEvent.snapshot.key); + dispatch_async(queue, ^{ + self.callback(dataEvent.snapshot); + }); + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h new file mode 100644 index 0000000..0b4b9d8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@protocol FOperation; +@protocol FEventRegistration; +@class FWriteTreeRef; +@class FQuerySpec; +@class FChange; +@class FPath; +@class FViewCache; + +@interface FViewOperationResult : NSObject + +@property(nonatomic, strong, readonly) NSArray *changes; +@property(nonatomic, strong, readonly) NSArray *events; + +@end + +@interface FView : NSObject + +@property(nonatomic, strong, readonly) FQuerySpec *query; + +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache; + +- (id)eventCache; +- (id)serverCache; +- (id)completeServerCacheFor:(FPath *)path; +- (BOOL)isEmpty; + +- (void)addEventRegistration:(id)eventRegistration; +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError; + +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; +- (NSArray *)initialEvents:(id)registration; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m new file mode 100644 index 0000000..a15e13d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FView.h" +#import "FCacheNode.h" +#import "FCancelEvent.h" +#import "FEmptyNode.h" +#import "FEventGenerator.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FViewCache.h" +#import "FViewProcessor.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +@interface FViewOperationResult () + +@property(nonatomic, strong, readwrite) NSArray *changes; +@property(nonatomic, strong, readwrite) NSArray *events; + +@end + +@implementation FViewOperationResult + +- (id)initWithChanges:(NSArray *)changes events:(NSArray *)events { + self = [super init]; + if (self != nil) { + self->_changes = changes; + self->_events = events; + } + return self; +} + +@end + +/** + * A view represents a specific location and query that has 1 or more event + * registrations. + * + * It does several things: + * - Maintains the list of event registration for this location/query. + * - Maintains a cache of the data visible for this location/query. + * - Applies new operations (via applyOperation), updates the cache, and based + * on the event registrations returns the set of events to be raised. + */ +@interface FView () + +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, strong) FViewProcessor *processor; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) NSMutableArray *eventRegistrations; +@property(nonatomic, strong) FEventGenerator *eventGenerator; + +@end + +@implementation FView +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache { + self = [super init]; + if (self) { + self.query = query; + + FIndexedFilter *indexFilter = + [[FIndexedFilter alloc] initWithIndex:query.index]; + id filter = query.params.nodeFilter; + self.processor = [[FViewProcessor alloc] initWithFilter:filter]; + FCacheNode *initialServerCache = initialViewCache.cachedServerSnap; + FCacheNode *initialEventCache = initialViewCache.cachedEventSnap; + + // Don't filter server node with other filter than index, wait for + // tagged listen + FIndexedNode *emptyIndexedNode = + [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:query.index]; + FIndexedNode *serverSnap = + [indexFilter updateFullNode:emptyIndexedNode + withNewNode:initialServerCache.indexedNode + accumulator:nil]; + FIndexedNode *eventSnap = + [filter updateFullNode:emptyIndexedNode + withNewNode:initialEventCache.indexedNode + accumulator:nil]; + FCacheNode *newServerCache = [[FCacheNode alloc] + initWithIndexedNode:serverSnap + isFullyInitialized:initialServerCache.isFullyInitialized + isFiltered:indexFilter.filtersNodes]; + FCacheNode *newEventCache = [[FCacheNode alloc] + initWithIndexedNode:eventSnap + isFullyInitialized:initialEventCache.isFullyInitialized + isFiltered:filter.filtersNodes]; + + self.viewCache = [[FViewCache alloc] initWithEventCache:newEventCache + serverCache:newServerCache]; + + self.eventRegistrations = [[NSMutableArray alloc] init]; + + self.eventGenerator = [[FEventGenerator alloc] initWithQuery:query]; + } + + return self; +} + +- (id)serverCache { + return self.viewCache.cachedServerSnap.node; +} + +- (id)eventCache { + return self.viewCache.cachedEventSnap.node; +} + +- (id)completeServerCacheFor:(FPath *)path { + id cache = self.viewCache.completeServerSnap; + if (cache) { + // If this isn't a "loadsAllData" view, then cache isn't actually a + // complete cache and we need to see if it contains the child we're + // interested in. + if ([self.query loadsAllData] || + (!path.isEmpty && + ![cache getImmediateChild:path.getFront].isEmpty)) { + return [cache getChild:path]; + } + } + return nil; +} + +- (BOOL)isEmpty { + return self.eventRegistrations.count == 0; +} + +- (void)addEventRegistration:(id)eventRegistration { + [self.eventRegistrations addObject:eventRegistration]; +} + +/** + * @param eventRegistration If null, remove all callbacks. + * @param cancelError If a cancelError is provided, appropriate cancel events + * will be returned. + * @return Cancel events, if cancelError was provided. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError { + NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + if (cancelError != nil) { + NSAssert(eventRegistration == nil, + @"A cancel should cancel all event registrations."); + FPath *path = self.query.path; + for (id registration in self.eventRegistrations) { + FCancelEvent *maybeEvent = + [registration createCancelEventFromError:cancelError path:path]; + if (maybeEvent) { + [cancelEvents addObject:maybeEvent]; + } + } + } + + if (eventRegistration) { + NSUInteger i = 0; + while (i < self.eventRegistrations.count) { + id existing = self.eventRegistrations[i]; + if ([existing matches:eventRegistration]) { + [self.eventRegistrations removeObjectAtIndex:i]; + } else { + i++; + } + } + } else { + [self.eventRegistrations removeAllObjects]; + } + return cancelEvents; +} + +/** + * Applies the given Operation, updates our cache, and returns the appropriate + * events and changes + */ +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + if (operation.type == FOperationTypeMerge && + operation.source.queryParams != nil) { + NSAssert(self.viewCache.completeServerSnap != nil, + @"We should always have a full cache before handling merges"); + NSAssert(self.viewCache.completeEventSnap != nil, + @"Missing event cache, even though we have a server cache"); + } + FViewCache *oldViewCache = self.viewCache; + FViewProcessorResult *result = + [self.processor applyOperationOn:oldViewCache + operation:operation + writesCache:writesCache + completeCache:optCompleteServerCache]; + + NSAssert(result.viewCache.cachedServerSnap.isFullyInitialized || + !oldViewCache.cachedServerSnap.isFullyInitialized, + @"Once a server snap is complete, it should never go back."); + + self.viewCache = result.viewCache; + NSArray *events = [self + generateEventsForChanges:result.changes + eventCache:result.viewCache.cachedEventSnap.indexedNode + registration:nil]; + return [[FViewOperationResult alloc] initWithChanges:result.changes + events:events]; +} + +- (NSArray *)initialEvents:(id)registration { + FCacheNode *eventSnap = self.viewCache.cachedEventSnap; + NSMutableArray *initialChanges = [[NSMutableArray alloc] init]; + [eventSnap.indexedNode.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:node]; + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:indexed + childKey:key]; + [initialChanges addObject:change]; + }]; + if (eventSnap.isFullyInitialized) { + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + [initialChanges addObject:change]; + } + return [self generateEventsForChanges:initialChanges + eventCache:eventSnap.indexedNode + registration:registration]; +} + +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + registration:(id)registration { + NSArray *registrations; + if (registration == nil) { + registrations = [[NSArray alloc] initWithArray:self.eventRegistrations]; + } else { + registrations = [[NSArray alloc] initWithObjects:registration, nil]; + } + return [self.eventGenerator generateEventsForChanges:changes + eventCache:eventCache + eventRegistrations:registrations]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FView (%@)", self.query]; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h new file mode 100644 index 0000000..62618d2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h @@ -0,0 +1,40 @@ +#/* +* Copyright 2017 Google +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#import + +@protocol FNode; +@class FCacheNode; +@class FIndexedNode; + +@interface FViewCache : NSObject + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache; + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; + +@property(nonatomic, strong, readonly) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readonly) id completeEventSnap; +@property(nonatomic, strong, readonly) FCacheNode *cachedServerSnap; +@property(nonatomic, strong, readonly) id completeServerSnap; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m new file mode 100644 index 0000000..13e9283 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewCache.h" +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FNode.h" + +@interface FViewCache () +@property(nonatomic, strong, readwrite) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readwrite) FCacheNode *cachedServerSnap; +@end + +@implementation FViewCache + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache { + self = [super init]; + if (self) { + self.cachedEventSnap = eventCache; + self.cachedServerSnap = serverCache; + } + return self; +} + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedEventCache = + [[FCacheNode alloc] initWithIndexedNode:eventSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:updatedEventCache + serverCache:self.cachedServerSnap]; +} + +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedServerCache = + [[FCacheNode alloc] initWithIndexedNode:serverSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:self.cachedEventSnap + serverCache:updatedServerCache]; +} + +- (id)completeEventSnap { + return (self.cachedEventSnap.isFullyInitialized) ? self.cachedEventSnap.node + : nil; +} + +- (id)completeServerSnap { + return (self.cachedServerSnap.isFullyInitialized) + ? self.cachedServerSnap.node + : nil; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h new file mode 100644 index 0000000..bf25163 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FChange; + +@interface FChildChangeAccumulator : NSObject + +- (id)init; +- (void)trackChildChange:(FChange *)change; +- (NSArray *)changes; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m new file mode 100644 index 0000000..e35c2e2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildChangeAccumulator.h" +#import "FChange.h" +#import "FIndex.h" + +@interface FChildChangeAccumulator () +@property(nonatomic, strong) NSMutableDictionary *changeMap; +@end + +@implementation FChildChangeAccumulator + +- (id)init { + self = [super init]; + if (self) { + self.changeMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)trackChildChange:(FChange *)change { + FIRDataEventType type = change.type; + NSString *childKey = change.childKey; + NSAssert(type == FIRDataEventTypeChildAdded || + type == FIRDataEventTypeChildChanged || + type == FIRDataEventTypeChildRemoved, + @"Only child changes supported for tracking."); + NSAssert(![change.childKey isEqualToString:@".priority"], + @"Changes not tracked on priority"); + if (self.changeMap[childKey] != nil) { + FChange *oldChange = [self.changeMap objectForKey:childKey]; + FIRDataEventType oldType = oldChange.type; + if (type == FIRDataEventTypeChildAdded && + oldType == FIRDataEventTypeChildRemoved) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.indexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildAdded) { + [self.changeMap removeObjectForKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildRemoved + indexedNode:oldChange.oldIndexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildAdded) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:change.indexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.oldIndexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else { + NSString *reason = [NSString + stringWithFormat: + @"Illegal combination of changes: %@ occurred after %@", + change, oldChange]; + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:reason + userInfo:nil]; + } + } else { + [self.changeMap setObject:change forKey:childKey]; + } +} + +- (NSArray *)changes { + return [self.changeMap allValues]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h new file mode 100644 index 0000000..0c04bc1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FNamedNode; +@protocol FIndex; + +@protocol FCompleteChildSource + +- (id)completeChild:(NSString *)childKey; +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h new file mode 100644 index 0000000..291e79a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@protocol FIndex; + +@interface FIndexedFilter : NSObject + +- (id)initWithIndex:(id)theIndex; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m new file mode 100644 index 0000000..f49af79 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m @@ -0,0 +1,164 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FIndexedNode.h" +#import "FKeyIndex.h" +#import "FNode.h" + +@interface FIndexedFilter () +@property(nonatomic, strong, readwrite) id index; +@end + +@implementation FIndexedFilter +- (id)initWithIndex:(id)theIndex { + self = [super init]; + if (self) { + self.index = theIndex; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)indexedNode + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert([indexedNode hasIndex:self.index], + @"The index in FIndexedNode must match the index of the filter"); + id node = indexedNode.node; + id oldChildSnap = [node getImmediateChild:childKey]; + + // Check if anything actually changed. + if ([[oldChildSnap getChild:affectedPath] + isEqual:[newChildSnap getChild:affectedPath]]) { + // There's an edge case where a child can enter or leave the view + // because affectedPath was set to null. In this case, affectedPath will + // appear null in both the old and new snapshots. So we need to avoid + // treating these cases as "nothing changed." + if (oldChildSnap.isEmpty == newChildSnap.isEmpty) { +// Nothing changed. +#ifdef DEBUG + NSAssert([oldChildSnap isEqual:newChildSnap], + @"Old and new snapshots should be equal."); +#endif + + return indexedNode; + } + } + if (optChangeAccumulator) { + if (newChildSnap.isEmpty) { + if ([node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + NSAssert(node.isLeafNode, + @"A child remove without an old child only makes " + @"sense on a leaf node."); + } + } else if (oldChildSnap.isEmpty) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } + if (node.isLeafNode && newChildSnap.isEmpty) { + return indexedNode; + } else { + return [indexedNode updateChild:childKey withNewChild:newChildSnap]; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (optChangeAccumulator) { + [oldSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if (![newSnap.node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if ([oldSnap.node hasChild:childKey]) { + id oldChildSnap = + [oldSnap.node getImmediateChild:childKey]; + if (![oldChildSnap isEqual:childNode]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:childNode] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + } + return newSnap; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + if ([oldSnap.node isEmpty]) { + return oldSnap; + } else { + return [oldSnap updatePriority:priority]; + } +} + +- (BOOL)filtersNodes { + return NO; +} + +- (id)indexedFilter { + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h new file mode 100644 index 0000000..0642e72 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; + +@interface FLimitedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m new file mode 100644 index 0000000..fab9aab --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m @@ -0,0 +1,285 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLimitedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FQueryParams.h" +#import "FRangedFilter.h" +#import "FTreeSortedDictionary.h" + +@interface FLimitedFilter () +@property(nonatomic, strong) FRangedFilter *rangedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic) NSInteger limit; +@property(nonatomic) BOOL reverse; + +@end + +@implementation FLimitedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.rangedFilter = [[FRangedFilter alloc] initWithQueryParams:params]; + self.index = params.index; + self.limit = params.limit; + self.reverse = !params.isViewFromLeft; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self.rangedFilter matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + if ([[oldSnap.node getImmediateChild:childKey] isEqual:newChildSnap]) { + // No change + return oldSnap; + } else if (oldSnap.node.numChildren < self.limit) { + return [[self.rangedFilter indexedFilter] + updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; + } else { + return [self fullLimitUpdateNode:oldSnap + forChildKey:childKey + newChild:newChildSnap + fromSource:source + accumulator:optChangeAccumulator]; + } +} + +- (FIndexedNode *)fullLimitUpdateNode:(FIndexedNode *)oldIndexed + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert(oldIndexed.node.numChildren == self.limit, + @"Should have number of children equal to limit."); + + FNamedNode *windowBoundary = + self.reverse ? oldIndexed.firstChild : oldIndexed.lastChild; + + BOOL inRange = [self.rangedFilter matchesKey:childKey andNode:newChildSnap]; + if ([oldIndexed.node hasChild:childKey]) { + // `childKey` was already in `oldSnap`. Figure out if it remains in the + // window or needs to be replaced. + id oldChildSnap = [oldIndexed.node getImmediateChild:childKey]; + + // In case the `newChildSnap` falls outside the window, get the + // `nextChild` that might replace it. + FNamedNode *nextChild = [source childByIndex:self.index + afterChild:windowBoundary + isReverse:(BOOL)self.reverse]; + if (nextChild != nil && ([nextChild.name isEqualToString:childKey] || + [oldIndexed.node hasChild:nextChild.name])) { + // There is a weird edge case where a node is updated as part of a + // merge in the write tree, but hasn't been applied to the limited + // filter yet. Ignore this next child which will be updated later in + // the limited filter... + nextChild = [source childByIndex:self.index + afterChild:nextChild + isReverse:self.reverse]; + } + + // Figure out if `newChildSnap` is in range and ordered before + // `nextChild` + BOOL remainsInWindow = inRange && !newChildSnap.isEmpty; + remainsInWindow = remainsInWindow && + (!nextChild || [self.index compareKey:nextChild.name + andNode:nextChild.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= + NSOrderedSame); + if (remainsInWindow) { + // `newChildSnap` is ordered before `nextChild`, so it's a child + // changed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + return [oldIndexed updateChild:childKey withNewChild:newChildSnap]; + } else { + // `newChildSnap` is ordered after `nextChild`, so it's a child + // removed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + FIndexedNode *newIndexed = + [oldIndexed updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + + // We need to check if the `nextChild` is actually in range before + // adding it + BOOL nextChildInRange = + (nextChild != nil) && + [self.rangedFilter matchesKey:nextChild.name + andNode:nextChild.node]; + if (nextChildInRange) { + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode + indexedNodeWithNode:nextChild.node] + childKey:nextChild.name]; + [optChangeAccumulator trackChildChange:change]; + } + return [newIndexed updateChild:nextChild.name + withNewChild:nextChild.node]; + } else { + return newIndexed; + } + } + } else if (newChildSnap.isEmpty) { + // We're deleting a node, but it was not in the window, so ignore it. + return oldIndexed; + } else if (inRange) { + // `newChildSnap` is in range, but was ordered after `windowBoundary`. + // If this has changed, we bump out the `windowBoundary` and add the + // `newChildSnap` + if ([self.index compareKey:windowBoundary.name + andNode:windowBoundary.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= NSOrderedSame) { + if (optChangeAccumulator != nil) { + FChange *removedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode + indexedNodeWithNode:windowBoundary.node] + childKey:windowBoundary.name]; + FChange *addedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:removedChange]; + [optChangeAccumulator trackChildChange:addedChange]; + } + return [[oldIndexed updateChild:childKey withNewChild:newChildSnap] + updateChild:windowBoundary.name + withNewChild:[FEmptyNode emptyNode]]; + } else { + return oldIndexed; + } + } else { + // `newChildSnap` was not in range and remains not in range, so ignore + // it. + return oldIndexed; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode || newSnap.node.isEmpty) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + filtered = newSnap; + // Don't support priorities on queries. + filtered = [filtered updatePriority:[FEmptyNode emptyNode]]; + FNamedNode *startPost = nil; + FNamedNode *endPost = nil; + if (self.reverse) { + startPost = self.rangedFilter.endPost; + endPost = self.rangedFilter.startPost; + } else { + startPost = self.rangedFilter.startPost; + endPost = self.rangedFilter.endPost; + } + __block BOOL foundStartPost = NO; + __block NSUInteger count = 0; + [newSnap + enumerateChildrenReverse:self.reverse + usingBlock:^(NSString *childKey, id childNode, + BOOL *stop) { + if (!foundStartPost && + [self.index + compareKey:startPost.name + andNode:startPost.node + toOtherKey:childKey + andNode:childNode + reverse:self.reverse] <= NSOrderedSame) { + // Start adding + foundStartPost = YES; + } + BOOL inRange = foundStartPost && count < self.limit; + inRange = inRange && + [self.index compareKey:childKey + andNode:childNode + toOtherKey:endPost.name + andNode:endPost.node + reverse:self.reverse] <= + NSOrderedSame; + if (inRange) { + count++; + } else { + filtered = [filtered + updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries. + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +- (id)indexedFilter { + return self.rangedFilter.indexedFilter; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h new file mode 100644 index 0000000..d19c6fb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@protocol FCompleteChildSource; +@class FChildChangeAccumulator; +@protocol FIndex; +@class FPath; + +/** + * FNodeFilter is used to update nodes and complete children of nodes while + * applying queries on the fly and keeping track of any child changes. This + * class does not track value changes as value changes depend on more than just + * the node itself. Different kind of queries require different kind of + * implementations of this interface. + */ +@protocol FNodeFilter + +/** + * Update a single complete child in the snap. If the child equals the old child + * in the snap, this is a no-op. The method expects an indexed snap. + */ +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator:(FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update a node in full and output any resulting change from this complete + * update. + */ +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update the priority of the root node + */ +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap; + +/** + * Returns true if children might be filtered due to query critiera + */ +- (BOOL)filtersNodes; + +/** + * Returns the index filter that this filter uses to get a NodeFilter that + * doesn't filter any children. + */ +@property(nonatomic, strong, readonly) id indexedFilter; + +/** + * Returns the index that this filter uses + */ +@property(nonatomic, strong, readonly) id index; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.h new file mode 100644 index 0000000..e85cb2a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FClock + +- (NSTimeInterval)currentTime; + +@end + +@interface FSystemClock : NSObject + ++ (FSystemClock *)clock; + +@end + +@interface FOffsetClock : NSObject + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.m new file mode 100644 index 0000000..5d9a9ec --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FClock.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" + +@implementation FSystemClock + +- (NSTimeInterval)currentTime { + return [[NSDate date] timeIntervalSince1970]; +} + ++ (FSystemClock *)clock { + static dispatch_once_t onceToken; + static FSystemClock *clock; + dispatch_once(&onceToken, ^{ + clock = [[FSystemClock alloc] init]; + }); + return clock; +} + +@end + +@interface FOffsetClock () + +@property(nonatomic, strong) id clock; +@property(nonatomic) NSTimeInterval offset; + +@end + +@implementation FOffsetClock + +- (NSTimeInterval)currentTime { + return [self.clock currentTime] + self.offset; +} + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset { + self = [super init]; + if (self != nil) { + self->_clock = clock; + self->_offset = offset; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h new file mode 100644 index 0000000..443664e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; +@class FIndexedNode; +@protocol FNode; + +@interface FEventGenerator : NSObject +- (id)initWithQuery:(FQuerySpec *)query; +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m new file mode 100644 index 0000000..162b0ac --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m @@ -0,0 +1,169 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventGenerator.h" +#import "FChange.h" +#import "FDataEvent.h" +#import "FEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" + +@interface FEventGenerator () +@property(nonatomic, strong) FQuerySpec *query; +@end + +/** + * An EventGenerator is used to convert "raw" changes (fb.core.view.Change) as + * computed by the CacheDiffer into actual events (fb.core.view.Event) that can + * be raised. See generateEventsForChanges() for details. + */ +@implementation FEventGenerator + +- (id)initWithQuery:(FQuerySpec *)query { + self = [super init]; + if (self) { + self.query = query; + } + return self; +} + +/** + * Given a set of raw changes (no moved events, and prevName not specified yet), + * and a set of EventRegistrations that should be notified of these changes, + * generate the actual events to be raised. + * + * Notes: + * - child_moved events will be synthesized at this time for any child_changed + * events that affect our index + * - prevName will be calculated based on the index ordering + * + * @param changes NSArray of FChange, not necessarily in order. + * @param registrations is NSArray of FEventRegistration. + * @return NSArray of FEvent. + */ +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *events = [[NSMutableArray alloc] init]; + + // child_moved is index-specific, so check all our child_changed events to + // see if we need to materialize child_moved events with this view's index + NSMutableArray *moves = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == FIRDataEventTypeChildChanged && + [self.query.index + indexedValueChangedBetween:change.oldIndexedNode.node + and:change.indexedNode.node]) { + FChange *moveChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildMoved + indexedNode:change.indexedNode + childKey:change.childKey + oldIndexedNode:nil]; + [moves addObject:moveChange]; + } + } + + [self generateEvents:events + forType:FIRDataEventTypeChildRemoved + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildAdded + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildMoved + changes:moves + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildChanged + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeValue + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + + return events; +} + +- (void)generateEvents:(NSMutableArray *)events + forType:(FIRDataEventType)eventType + changes:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *filteredChanges = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == eventType) { + [filteredChanges addObject:change]; + } + } + + id index = self.query.index; + + [filteredChanges + sortUsingComparator:^NSComparisonResult(FChange *one, FChange *two) { + if (one.childKey == nil || two.childKey == nil) { + @throw [[NSException alloc] + initWithName:@"InternalInconsistencyError" + reason:@"Should only compare child_ events" + userInfo:nil]; + } + return [index compareKey:one.childKey + andNode:one.indexedNode.node + toOtherKey:two.childKey + andNode:two.indexedNode.node]; + }]; + + for (FChange *change in filteredChanges) { + for (id registration in registrations) { + if ([registration responseTo:eventType]) { + id event = [self generateEventForChange:change + registration:registration + eventCache:eventCache]; + [events addObject:event]; + } + } + } +} + +- (id)generateEventForChange:(FChange *)change + registration:(id)registration + eventCache:(FIndexedNode *)eventCache { + FChange *materializedChange; + if (change.type == FIRDataEventTypeValue || + change.type == FIRDataEventTypeChildRemoved) { + materializedChange = change; + } else { + NSString *prevChildKey = + [eventCache predecessorForChildKey:change.childKey + childNode:change.indexedNode.node + index:self.query.index]; + materializedChange = [change changeWithPrevKey:prevChildKey]; + } + return [registration createEventFrom:materializedChange query:self.query]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h new file mode 100644 index 0000000..ca2f34b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig.h" + +@protocol FStorageEngine; + +@interface FIRDatabaseConfig () + +@property(nonatomic, readonly) BOOL isFrozen; +@property(nonatomic, strong, readonly) NSString *sessionIdentifier; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) id forceStorageEngine; + +- (void)freeze; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m new file mode 100644 index 0000000..b3c0106 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m @@ -0,0 +1,528 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIRDatabase.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FNextPushId.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" +#import +#import + +@implementation FIRDatabaseReference + +#pragma mark - +#pragma mark Constructors + +- (id)initWithConfig:(FIRDatabaseConfig *)config { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:[[FIRApp defaultApp] options].databaseURL]; + [FValidation validateFrom:@"initWithUrl:" validURL:parsedUrl]; + return [self initWithRepo:[FRepoManager getRepo:parsedUrl.repoInfo + config:config] + path:parsedUrl.path]; +} + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path { + return [super initWithRepo:repo + path:path + params:[FQueryParams defaultInstance] + orderByCalled:NO + priorityMethodCalled:NO]; +} + +#pragma mark - +#pragma mark Ancillary methods + +- (nullable NSString *)key { + if ([self.path isEmpty]) { + return nil; + } else { + return [self.path getBack]; + } +} + +- (FIRDatabase *)database { + return self.repo.database; +} + +- (FIRDatabaseReference *)parent { + FPath *parentPath = [self.path parent]; + FIRDatabaseReference *parent = nil; + if (parentPath != nil) { + parent = [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parentPath]; + } + return parent; +} + +- (NSString *)URL { + FIRDatabaseReference *parent = [self parent]; + return parent == nil + ? [self.repo description] + : [NSString + stringWithFormat:@"%@/%@", [parent description], + [FStringUtilities urlEncoded:self.key]]; +} + +- (NSString *)description { + return [self URL]; +} + +- (FIRDatabaseReference *)root { + return [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[[FPath alloc] initWith:@""]]; +} + +#pragma mark - +#pragma mark Child methods + +- (FIRDatabaseReference *)child:(NSString *)pathString { + if ([self.path getFront] == nil) { + // we're at the root + [FValidation validateFrom:@"child:" validRootPathString:pathString]; + } else { + [FValidation validateFrom:@"child:" validPathString:pathString]; + } + FPath *path = [self.path childFromString:pathString]; + FIRDatabaseReference *firebaseRef = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:path]; + return firebaseRef; +} + +- (FIRDatabaseReference *)childByAutoId { + [FValidation validateFrom:@"childByAutoId:" writablePath:self.path]; + + NSString *name = [FNextPushId get:self.repo.serverTime]; + return [self child:name]; +} + +#pragma mark - +#pragma mark Basic write methods + +- (void)setValue:(id)value { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"setValue:"]; +} + +- (void)setValue:(id)value withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"setValue:withCompletionBlock:"]; +} + +- (void)setValue:(id)value andPriority:(id)priority { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"setValue:andPriority:"]; +} + +- (void)setValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"setValue:andPriority:withCompletionBlock:"]; +} + +- (void)setValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + id newNode = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:self.path withNode:newNode withCallback:userCallback]; + }); +} + +- (void)removeValue { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"removeValue:"]; +} + +- (void)removeValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"removeValueWithCompletionBlock:"]; +} + +- (void)setPriority:(id)priority { + [self setPriorityInternal:priority + withCompletionBlock:nil + from:@"setPriority:"]; +} + +- (void)setPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + + [self setPriorityInternal:priority + withCompletionBlock:block + from:@"setPriority:withCompletionBlock:"]; +} + +- (void)setPriorityInternal:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:[self.path childFromString:@".priority"] + withNode:[FSnapshotUtilities nodeFrom:priority] + withCallback:userCallback]; + }); +} + +- (void)updateChildValues:(NSDictionary *)values { + [self updateChildValuesInternal:values + withCompletionBlock:nil + from:@"updateChildValues:"]; +} + +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self updateChildValuesInternal:values + withCompletionBlock:block + from:@"updateChildValues:withCompletionBlock:"]; +} + +- (void)updateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo update:self.path withNodes:merge withCallback:userCallback]; + }); +} + +#pragma mark - +#pragma mark Disconnect Operations + +- (void)onDisconnectSetValue:(id)value { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectSetValue:"]; +} + +- (void)onDisconnectSetValue:(id)value + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectSetValue:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValue:(id)value andPriority:(id)priority { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"onDisconnectSetValue:andPriority:"]; +} + +- (void)onDisconnectSetValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"onDisconnectSetValue:andPriority:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + id newNodeUnresolved = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectSet:self.path + withNode:newNodeUnresolved + withCallback:userCallback]; + }); +} + +- (void)onDisconnectRemoveValue { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectRemoveValue:"]; +} + +- (void)onDisconnectRemoveValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectRemoveValueWithCompletionB" + @"lock:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values { + [self + onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:nil + from: + @"onDisconnectUpdateChildValues:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:block + from:@"onDisconnectUpdateChildValues" + @":withCompletionBlock:"]; +} + +- (void)onDisconnectUpdateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectUpdate:self.path + withNodes:merge + withCallback:userCallback]; + }); +} + +- (void)cancelDisconnectOperations { + [self cancelDisconnectOperationsWithCompletionBlock:nil]; +} + +- (void)cancelDisconnectOperationsWithCompletionBlock: + (fbt_void_nserror_ref)block { + fbt_void_nserror_ref callback = nil; + if (block != nil) { + callback = [block copy]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectCancel:self.path withCallback:callback]; + }); +} + +#pragma mark - +#pragma mark Connection management methods + ++ (void)goOffline { + [FRepoManager interruptAll]; +} + ++ (void)goOnline { + [FRepoManager resumeAll]; +} + +#pragma mark - +#pragma mark Data reading methods deferred to FQuery + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + [super removeObserverWithHandle:handle]; +} + +- (void)removeAllObservers { + [super removeAllObservers]; +} + +- (void)keepSynced:(BOOL)keepSynced { + [super keepSynced:keepSynced]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +#pragma mark - +#pragma mark Query methods +// These methods suppress warnings from having method definitions in +// FIRDatabaseReference.h for docs generation. + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + return [super queryLimitedToFirst:limit]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + return [super queryLimitedToLast:limit]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key { + return [super queryOrderedByChild:key]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + return [super queryOrderedByKey]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + return [super queryOrderedByPriority]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [super queryStartingAtValue:startValue]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + return [super queryStartingAtValue:startValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [super queryEndingAtValue:endValue]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + return [super queryEndingAtValue:endValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [super queryEqualToValue:value]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + return [super queryEqualToValue:value childKey:childKey]; +} + +#pragma mark - +#pragma mark Transaction methods + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block { + [FValidation validateFrom:@"runTransactionBlock:" writablePath:self.path]; + [self runTransactionBlock:block andCompletionBlock:nil withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)update + andCompletionBlock: + (fbt_void_nserror_bool_datasnapshot)completionBlock { + [FValidation validateFrom:@"runTransactionBlock:andCompletionBlock:" + writablePath:self.path]; + [self runTransactionBlock:update + andCompletionBlock:completionBlock + withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block + andCompletionBlock:(fbt_void_nserror_bool_datasnapshot)completionBlock + withLocalEvents:(BOOL)localEvents { + [FValidation + validateFrom:@"runTransactionBlock:andCompletionBlock:withLocalEvents:" + writablePath:self.path]; + fbt_transactionresult_mutabledata updateCopy = [block copy]; + fbt_void_nserror_bool_datasnapshot onCompleteCopy = [completionBlock copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo startTransactionOnPath:self.path + update:updateCopy + onComplete:onCompleteCopy + withLocalEvents:localEvents]; + }); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.h new file mode 100644 index 0000000..89bec76 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableSortedDictionary; +@class FNamedNode; +@protocol FNode; + +@protocol FIndex +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2; + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse; + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2; + +- (BOOL)isDefinedOn:(id)node; +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode; +- (FNamedNode *)minPost; +- (FNamedNode *)maxPost; +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name; +- (NSString *)queryDefinition; + +@end + +@interface FIndex : NSObject + ++ (id)indexFromQueryDefinition:(NSString *)string; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.m new file mode 100644 index 0000000..0366399 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FIndex.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" + +#import "FKeyIndex.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FValueIndex.h" + +@implementation FIndex + ++ (id)indexFromQueryDefinition:(NSString *)string { + if ([string isEqualToString:@".key"]) { + return [FKeyIndex keyIndex]; + } else if ([string isEqualToString:@".value"]) { + return [FValueIndex valueIndex]; + } else if ([string isEqualToString:@".priority"]) { + return [FPriorityIndex priorityIndex]; + } else { + return + [[FPathIndex alloc] initWithPath:[[FPath alloc] initWith:string]]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h new file mode 100644 index 0000000..281a5ac --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FKeyIndex : NSObject ++ (id)keyIndex; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m new file mode 100644 index 0000000..ac10829 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeyIndex.h" +#import "FEmptyNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FKeyIndex () + +@property(nonatomic, strong) FNamedNode *maxPost; + +@end + +@implementation FKeyIndex + +- (id)init { + self = [super init]; + if (self) { + self.maxPost = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FEmptyNode emptyNode]]; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + return [FUtilities compareKey:key1 toKey:key2]; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return NO; // The key for a node never changes. +} + +- (FNamedNode *)minPost { + return [FNamedNode min]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + NSString *key = indexValue.val; + NSAssert([key isKindOfClass:[NSString class]], + @"KeyIndex indexValue must always be a string."); + // We just use empty node, but it'll never be compared, since our comparator + // only looks at name. + return [[FNamedNode alloc] initWithName:key andNode:[FEmptyNode emptyNode]]; +} + +- (NSString *)queryDefinition { + return @".key"; +} + +- (NSString *)description { + return @"FKeyIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".key" hash]; +} + ++ (id)keyIndex { + static id keyIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + keyIndex = [[FKeyIndex alloc] init]; + }); + return keyIndex; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h new file mode 100644 index 0000000..99aabf8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" +#import + +@interface FListenComplete : NSObject + +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, readonly) FOperationType type; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m new file mode 100644 index 0000000..26370c6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenComplete.h" +#import "FOperationSource.h" +#import "FPath.h" + +@interface FListenComplete () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, readwrite) FOperationType type; +@end + +@implementation FListenComplete +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath { + NSAssert(!aSource.fromUser, + @"Can't have a listen complete from a user source"); + self = [super init]; + if (self) { + self.source = aSource; + self.path = aPath; + self.type = FOperationTypeListenComplete; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FListenComplete alloc] initWithSource:self.source + path:[FPath empty]]; + } else { + return [[FListenComplete alloc] initWithSource:self.source + path:[self.path popFront]]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FListenComplete { path=%@, source=%@ }", + self.path, self.source]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h new file mode 100644 index 0000000..c68137e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import + +@interface FMaxNode : FChildrenNode ++ (id)maxNode; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m new file mode 100644 index 0000000..28e7672 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMaxNode.h" +#import "FEmptyNode.h" +#import "FUtilities.h" + +@implementation FMaxNode { +} +- (id)init { + self = [super init]; + if (self) { + } + return self; +} + ++ (id)maxNode { + static FMaxNode *maxNode = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + maxNode = [[FMaxNode alloc] init]; + }); + return maxNode; +} + +- (NSComparisonResult)compare:(id)other { + if (other == self) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + +- (BOOL)isEqual:(id)other { + return other == self; +} + +- (id)getImmediateChild:(NSString *)childName { + return [FEmptyNode emptyNode]; +} + +- (BOOL)isEmpty { + return NO; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h new file mode 100644 index 0000000..4414dfd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FNamedNode : NSObject + +@property(nonatomic, strong, readonly) NSString *name; +@property(nonatomic, strong, readonly) id node; + +- (id)initWithName:(NSString *)name andNode:(id)node; + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node; + ++ (FNamedNode *)min; ++ (FNamedNode *)max; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m new file mode 100644 index 0000000..3b2eaf7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNamedNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FMaxNode.h" +#import "FUtilities.h" + +@interface FNamedNode () +@property(nonatomic, strong, readwrite) NSString *name; +@property(nonatomic, strong, readwrite) id node; +@end + +@implementation FNamedNode + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node { + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (id)initWithName:(NSString *)name andNode:(id)node { + self = [super init]; + if (self) { + self.name = name; + self.node = node; + } + return self; +} + +- (id)copy { + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + ++ (FNamedNode *)min { + static FNamedNode *min = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + min = [[FNamedNode alloc] initWithName:[FUtilities minName] + andNode:[FEmptyNode emptyNode]]; + }); + return min; +} + ++ (FNamedNode *)max { + static FNamedNode *max = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + max = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FMaxNode maxNode]]; + }); + return max; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"NamedNode[%@] %@", self.name, self.node]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (object == nil || ![object isKindOfClass:[FNamedNode class]]) { + return NO; + } + + FNamedNode *namedNode = object; + if (![self.name isEqualToString:namedNode.name]) { + return NO; + } + if (![self.node isEqual:namedNode.node]) { + return NO; + } + + return YES; +} + +- (NSUInteger)hash { + NSUInteger nameHash = [self.name hash]; + NSUInteger nodeHash = [self.node hash]; + NSUInteger result = 31 * nameHash + nodeHash; + return result; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h new file mode 100644 index 0000000..6ab9151 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import "FPath.h" +#import + +@interface FPathIndex : NSObject +- (id)initWithPath:(FPath *)path; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m new file mode 100644 index 0000000..214eab8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m @@ -0,0 +1,135 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPathIndex.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FPathIndex () +@property(nonatomic, strong) FPath *path; +@end + +@implementation FPathIndex + +- (id)initWithPath:(FPath *)path { + self = [super init]; + if (self) { + if (path.isEmpty || [path.getFront isEqualToString:@".priority"]) { + [NSException raise:NSInvalidArgumentException + format:@"Invalid path for PathIndex: %@", path]; + } + _path = path; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getChild:self.path]; + id child2 = [node2 getChild:self.path]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return ![node getChild:self.path].isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getChild:self.path]; + id newValue = [newNode getChild:self.path]; + return [oldValue compare:newValue] != NSOrderedSame; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + id maxNode = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:[FMaxNode maxNode]]; + + return [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:maxNode]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return [self.path wireFormat]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FPathIndex(%@)", self.path]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + if (![other isKindOfClass:[FPathIndex class]]) { + return NO; + } + return ([self.path isEqual:((FPathIndex *)other).path]); +} + +- (NSUInteger)hash { + return [self.path hash]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h new file mode 100644 index 0000000..1b4534e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" + +@interface FPriorityIndex : NSObject ++ (id)priorityIndex; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m new file mode 100644 index 0000000..0b33837 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m @@ -0,0 +1,126 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPriorityIndex.h" + +#import "FEmptyNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FUtilities.h" + +// TODO: Abstract into some common base class? + +@implementation FPriorityIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getPriority]; + id child2 = [node2 getPriority]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return !node.getPriority.isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getPriority]; + id newValue = [newNode getPriority]; + return ![oldValue isEqual:newValue]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return [self makePost:[FMaxNode maxNode] name:[FUtilities maxName]]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FLeafNode alloc] initWithValue:@"[PRIORITY-POST]" + withPriority:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return @".priority"; +} + +- (NSString *)description { + return @"FPriorityIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + return [other isKindOfClass:[FPriorityIndex class]]; +} + +- (NSUInteger)hash { + // chosen by a fair dice roll. Guaranteed to be random + return 3155577; +} + ++ (id)priorityIndex { + static id index; + static dispatch_once_t once; + dispatch_once(&once, ^{ + index = [[FPriorityIndex alloc] init]; + }); + + return index; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h new file mode 100644 index 0000000..3c1aadd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; +@class FNamedNode; + +@interface FRangedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +- (BOOL)matchesKey:(NSString *)key andNode:(id)node; + +@property(nonatomic, strong, readonly) FNamedNode *startPost; +@property(nonatomic, strong, readonly) FNamedNode *endPost; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m new file mode 100644 index 0000000..bd8ef81 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m @@ -0,0 +1,129 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangedFilter.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FQueryParams.h" + +@interface FRangedFilter () +@property(nonatomic, strong, readwrite) id indexedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic, strong, readwrite) FNamedNode *startPost; +@property(nonatomic, strong, readwrite) FNamedNode *endPost; +@end + +@implementation FRangedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.indexedFilter = + [[FIndexedFilter alloc] initWithIndex:params.index]; + self.index = params.index; + self.startPost = [FRangedFilter startPostFromQueryParams:params]; + self.endPost = [FRangedFilter endPostFromQueryParams:params]; + } + return self; +} + ++ (FNamedNode *)startPostFromQueryParams:(FQueryParams *)params { + if ([params hasStart]) { + NSString *startKey = params.indexStartKey; + return [params.index makePost:params.indexStartValue name:startKey]; + } else { + return params.index.minPost; + } +} + ++ (FNamedNode *)endPostFromQueryParams:(FQueryParams *)params { + if ([params hasEnd]) { + NSString *endKey = params.indexEndKey; + return [params.index makePost:params.indexEndValue name:endKey]; + } else { + return params.index.maxPost; + } +} + +- (BOOL)matchesKey:(NSString *)key andNode:(id)node { + return ([self.index compareKey:self.startPost.name + andNode:self.startPost.node + toOtherKey:key + andNode:node] <= NSOrderedSame && + [self.index compareKey:key + andNode:node + toOtherKey:self.endPost.name + andNode:self.endPost.node] <= NSOrderedSame); +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + return [self.indexedFilter updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + // Dont' support priorities on queries + filtered = [newSnap updatePriority:[FEmptyNode emptyNode]]; + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + if (![self matchesKey:key andNode:node]) { + filtered = [filtered updateChild:key + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h new file mode 100644 index 0000000..25a59b4 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTransformedEnumerator : NSEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform; +- (id)nextObject; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m new file mode 100644 index 0000000..567e100 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTransformedEnumerator.h" + +@interface FTransformedEnumerator () +@property(nonatomic, strong) NSEnumerator *enumerator; +@property(nonatomic, copy) id (^transform)(id); +@end + +@implementation FTransformedEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform { + self = [super init]; + if (self) { + self.enumerator = enumerator; + self.transform = transform; + } + return self; +} + +- (id)nextObject { + id next = self.enumerator.nextObject; + if (next != nil) { + return self.transform(next); + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h new file mode 100644 index 0000000..a79f202 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FValueIndex : NSObject ++ (id)valueIndex; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m new file mode 100644 index 0000000..61021c8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueIndex.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@implementation FValueIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + NSComparisonResult indexCmp = [node1 compare:node2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return ![oldNode isEqual:newNode]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return FNamedNode.max; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + return [[FNamedNode alloc] initWithName:name andNode:indexValue]; +} + +- (NSString *)queryDefinition { + return @".value"; +} + +- (NSString *)description { + return @"FValueIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".value" hash]; +} + ++ (id)valueIndex { + static id valueIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueIndex = [[FValueIndex alloc] init]; + }); + return valueIndex; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h new file mode 100644 index 0000000..ea6676e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; +@class FViewProcessorResult; +@class FChildChangeAccumulator; +@protocol FNode; +@class FWriteTreeRef; +@class FPath; +@protocol FOperation; +@protocol FNodeFilter; + +@interface FViewProcessor : NSObject + +- (id)initWithFilter:(id)nodeFilter; + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache; +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m new file mode 100644 index 0000000..5524996 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m @@ -0,0 +1,831 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessor.h" +#import "FAckUserWrite.h" +#import "FCacheNode.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FIRDataEventType.h" +#import "FImmutableTree.h" +#import "FKeyIndex.h" +#import "FMerge.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FViewCache.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +/** + * An implementation of FCompleteChildSource that never returns any additional + * children + */ +@interface FNoCompleteChildSource : NSObject +@end + +@implementation FNoCompleteChildSource ++ (FNoCompleteChildSource *)instance { + static FNoCompleteChildSource *source = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + source = [[FNoCompleteChildSource alloc] init]; + }); + return source; +} + +- (id)completeChild:(NSString *)childKey { + return nil; +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + return nil; +} +@end + +/** + * An implementation of FCompleteChildSource that uses a FWriteTree in addition + * to any other server data or old event caches available to calculate complete + * children. + */ +@interface FWriteTreeCompleteChildSource : NSObject +@property(nonatomic, strong) FWriteTreeRef *writes; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) id optCompleteServerCache; +@end + +@implementation FWriteTreeCompleteChildSource +- (id)initWithWrites:(FWriteTreeRef *)writes + viewCache:(FViewCache *)viewCache + serverCache:(id)optCompleteServerCache { + self = [super init]; + if (self) { + self.writes = writes; + self.viewCache = viewCache; + self.optCompleteServerCache = optCompleteServerCache; + } + return self; +} + +- (id)completeChild:(NSString *)childKey { + FCacheNode *node = self.viewCache.cachedEventSnap; + if ([node isCompleteForChild:childKey]) { + return [node.node getImmediateChild:childKey]; + } else { + FCacheNode *serverNode; + if (self.optCompleteServerCache) { + // Since we're only ever getting child nodes, we can use the key + // index here + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:self.optCompleteServerCache + index:[FKeyIndex keyIndex]]; + serverNode = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + serverNode = self.viewCache.cachedServerSnap; + } + return [self.writes calculateCompleteChild:childKey cache:serverNode]; + } +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + id completeServerData = self.optCompleteServerCache != nil + ? self.optCompleteServerCache + : self.viewCache.completeServerSnap; + return [self.writes calculateNextNodeAfterPost:child + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +@end + +@interface FViewProcessor () +@property(nonatomic, strong) id filter; +@end + +@implementation FViewProcessor + +- (id)initWithFilter:(id)nodeFilter { + self = [super init]; + if (self) { + self.filter = nodeFilter; + } + return self; +} + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache { + FChildChangeAccumulator *accumulator = + [[FChildChangeAccumulator alloc] init]; + FViewCache *newViewCache; + + if (operation.type == FOperationTypeOverwrite) { + FOverwrite *overwrite = (FOverwrite *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserOverwriteTo:oldViewCache + changePath:overwrite.path + changedSnap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, + @"Unknown source for overwrite."); + // We filter the node if it's a tagged update or the node has been + // previously filtered and the update is not at the root in which + // case it is ok (and necessary) to mark the node unfiltered again + BOOL filterServerNode = overwrite.source.isTagged || + (oldViewCache.cachedServerSnap.isFiltered && + !overwrite.path.isEmpty); + newViewCache = [self applyServerOverwriteTo:oldViewCache + changePath:overwrite.path + snap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeMerge) { + FMerge *merge = (FMerge *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, @"Unknown source for merge."); + // We filter the node if it's a tagged update or the node has been + // previously filtered + BOOL filterServerNode = merge.source.isTagged || + oldViewCache.cachedServerSnap.isFiltered; + newViewCache = [self applyServerMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeAckUserWrite) { + FAckUserWrite *ackWrite = (FAckUserWrite *)operation; + if (!ackWrite.revert) { + newViewCache = [self ackUserWriteOn:oldViewCache + ackPath:ackWrite.path + affectedTree:ackWrite.affectedTree + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + newViewCache = [self revertUserWriteOn:oldViewCache + path:ackWrite.path + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeListenComplete) { + newViewCache = [self listenCompleteOldCache:oldViewCache + path:operation.path + writesCache:writesCache + serverCache:optCompleteCache + accumulator:accumulator]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Unknown operation encountered %ld.", (long)operation.type]; + return nil; + } + + NSArray *changes = [self maybeAddValueFromOldViewCache:oldViewCache + newViewCache:newViewCache + changes:accumulator.changes]; + FViewProcessorResult *results = + [[FViewProcessorResult alloc] initWithViewCache:newViewCache + changes:changes]; + return results; +} + +- (NSArray *)maybeAddValueFromOldViewCache:(FViewCache *)oldViewCache + newViewCache:(FViewCache *)newViewCache + changes:(NSArray *)changes { + NSArray *newChanges = changes; + FCacheNode *eventSnap = newViewCache.cachedEventSnap; + if (eventSnap.isFullyInitialized) { + BOOL isLeafOrEmpty = + eventSnap.node.isLeafNode || eventSnap.node.isEmpty; + if ([changes count] > 0 || + !oldViewCache.cachedEventSnap.isFullyInitialized || + (isLeafOrEmpty && + ![eventSnap.node isEqual:oldViewCache.completeEventSnap]) || + ![eventSnap.node.getPriority + isEqual:oldViewCache.completeEventSnap.getPriority]) { + FChange *valueChange = + [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + NSMutableArray *mutableChanges = [changes mutableCopy]; + [mutableChanges addObject:valueChange]; + newChanges = mutableChanges; + } + } + return newChanges; +} + +- (FViewCache *) + generateEventCacheAfterServerEvent:(FViewCache *)viewCache + path:(FPath *)changePath + writesCache:(FWriteTreeRef *)writesCache + source:(id)source + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = viewCache.cachedEventSnap; + if ([writesCache shadowingWriteAtPath:changePath] != nil) { + // we have a shadowing write, ignore changes. + return viewCache; + } else { + FIndexedNode *newEventCache; + if (changePath.isEmpty) { + // TODO: figure out how this plays with "sliding ack windows" + NSAssert( + viewCache.cachedServerSnap.isFullyInitialized, + @"If change path is empty, we must have complete server data"); + id nodeWithLocalWrites; + if (viewCache.cachedServerSnap.isFiltered) { + // We need to special case this, because we need to only apply + // writes to complete children, or we might end up raising + // events for incomplete children. If the server data is + // filtered deep writes cannot be guaranteed to be complete + id serverCache = viewCache.completeServerSnap; + FChildrenNode *completeChildren = + ([serverCache isKindOfClass:[FChildrenNode class]]) + ? serverCache + : [FEmptyNode emptyNode]; + nodeWithLocalWrites = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + completeChildren]; + } else { + nodeWithLocalWrites = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:nodeWithLocalWrites + index:self.filter.index]; + newEventCache = [self.filter + updateFullNode:viewCache.cachedEventSnap.indexedNode + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + NSAssert( + changePath.length == 1, + @"Can't have a priority with additional path components"); + id oldEventNode = oldEventSnap.node; + id serverNode = viewCache.cachedServerSnap.node; + // we might have overwrites for this priority + id updatedPriority = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventNode + existingServerSnap: + serverNode]; + if (updatedPriority != nil) { + newEventCache = + [self.filter updatePriority:updatedPriority + forNode:oldEventSnap.indexedNode]; + } else { + // priority didn't change, keep old node + newEventCache = oldEventSnap.indexedNode; + } + } else { + FPath *childChangePath = [changePath popFront]; + id newEventChild; + if ([oldEventSnap isCompleteForChild:childKey]) { + id serverNode = viewCache.cachedServerSnap.node; + id eventChildUpdate = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventSnap.node + existingServerSnap: + serverNode]; + if (eventChildUpdate != nil) { + newEventChild = + [[oldEventSnap.node getImmediateChild:childKey] + updateChild:childChangePath + withNewChild:eventChildUpdate]; + } else { + // Nothing changed, just keep the old child + newEventChild = + [oldEventSnap.node getImmediateChild:childKey]; + } + } else { + newEventChild = [writesCache + calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + } + if (newEventChild != nil) { + newEventCache = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newEventChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + } else { + // No complete children available or no change + newEventCache = oldEventSnap.indexedNode; + } + } + } + return [viewCache updateEventSnap:newEventCache + isComplete:(oldEventSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)applyServerOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + snap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerSnap = oldViewCache.cachedServerSnap; + FIndexedNode *newServerCache; + id serverFilter = + filterServerNode ? self.filter : self.filter.indexedFilter; + + if (changePath.isEmpty) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:serverFilter.index]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else if (serverFilter.filtersNodes && !oldServerSnap.isFiltered) { + // We want to filter the server node, but we didn't filter the server + // node yet, so simulate a full update + NSAssert(![changePath isEmpty], + @"An empty path should been caught in the other branch"); + NSString *childKey = [changePath getFront]; + FPath *updatePath = [changePath popFront]; + id newChild = [[oldServerSnap.node getImmediateChild:childKey] + updateChild:updatePath + withNewChild:changedSnap]; + FIndexedNode *indexed = + [oldServerSnap.indexedNode updateChild:childKey + withNewChild:newChild]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else { + NSString *childKey = [changePath getFront]; + if (![oldServerSnap isCompleteForPath:changePath] && + changePath.length > 1) { + // We don't update incomplete nodes with updates intended for other + // listeners. + return oldViewCache; + } + FPath *childChangePath = [changePath popFront]; + id childNode = [oldServerSnap.node getImmediateChild:childKey]; + id newChildNode = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + if ([childKey isEqualToString:@".priority"]) { + newServerCache = + [serverFilter updatePriority:newChildNode + forNode:oldServerSnap.indexedNode]; + } else { + newServerCache = + [serverFilter updateChildIn:oldServerSnap.indexedNode + forChildKey:childKey + newChild:newChildNode + affectedPath:childChangePath + fromSource:[FNoCompleteChildSource instance] + accumulator:nil]; + } + } + FViewCache *newViewCache = + [oldViewCache updateServerSnap:newServerCache + isComplete:(oldServerSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:serverFilter.filtersNodes]; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:newViewCache + serverCache:optCompleteCache]; + return [self generateEventCacheAfterServerEvent:newViewCache + path:changePath + writesCache:writesCache + source:source + accumulator:accumulator]; +} + +- (FViewCache *)applyUserOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + changedSnap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = oldViewCache.cachedEventSnap; + FViewCache *newViewCache; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:oldViewCache + serverCache:optCompleteCache]; + if (changePath.isEmpty) { + FIndexedNode *newIndexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:self.filter.index]; + FIndexedNode *newEventCache = + [self.filter updateFullNode:oldEventSnap.indexedNode + withNewNode:newIndexed + accumulator:accumulator]; + newViewCache = [oldViewCache updateEventSnap:newEventCache + isComplete:YES + isFiltered:self.filter.filtersNodes]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + FIndexedNode *newEventCache = [self.filter + updatePriority:changedSnap + forNode:oldViewCache.cachedEventSnap.indexedNode]; + newViewCache = + [oldViewCache updateEventSnap:newEventCache + isComplete:oldEventSnap.isFullyInitialized + isFiltered:oldEventSnap.isFiltered]; + } else { + FPath *childChangePath = [changePath popFront]; + id oldChild = [oldEventSnap.node getImmediateChild:childKey]; + id newChild; + if (childChangePath.isEmpty) { + // Child overwrite, we can replace the child + newChild = changedSnap; + } else { + id childNode = [source completeChild:childKey]; + if (childNode != nil) { + if ([[childChangePath getBack] + isEqualToString:@".priority"] && + [childNode getChild:[childChangePath parent]].isEmpty) { + // This is a priority update on an empty node. If this + // node exists on the server, the server will send down + // the priority in the update, so ignore for now + newChild = childNode; + } else { + newChild = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + } + } else { + newChild = [FEmptyNode emptyNode]; + } + } + if (![oldChild isEqual:newChild]) { + FIndexedNode *newEventSnap = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + newViewCache = [oldViewCache + updateEventSnap:newEventSnap + isComplete:oldEventSnap.isFullyInitialized + isFiltered:self.filter.filtersNodes]; + } else { + newViewCache = oldViewCache; + } + } + } + return newViewCache; +} + ++ (BOOL)cache:(FViewCache *)viewCache hasChild:(NSString *)childKey { + return [viewCache.cachedEventSnap isCompleteForChild:childKey]; +} + +/** + * @param changedChildren NSDictionary of child name (NSString*) to child value + * (id) + */ +- (FViewCache *)applyUserMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + accumulator:(FChildChangeAccumulator *)accumulator { + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if ([FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if (![FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)applyServerMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + // If we don't have a cache yet, this merge was intended for a previously + // listen in the same location. Ignore it and wait for the complete data + // update coming soon. + if (viewCache.cachedServerSnap.node.isEmpty && + !viewCache.cachedServerSnap.isFullyInitialized) { + return viewCache; + } + + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + FCompoundWrite *actualMerge; + if (path.isEmpty) { + actualMerge = changedChildren; + } else { + actualMerge = + [[FCompoundWrite emptyWrite] addCompoundWrite:changedChildren + atPath:path]; + } + id serverNode = viewCache.cachedServerSnap.node; + + NSDictionary *childCompoundWrites = actualMerge.childCompoundWrites; + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + if ([serverNode hasChild:childKey]) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + bool isUnknownDeepMerge = + ![viewCache.cachedServerSnap isCompleteForChild:childKey] && + childMerge.rootWrite == nil; + if (![serverNode hasChild:childKey] && !isUnknownDeepMerge) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)ackUserWriteOn:(FViewCache *)viewCache + ackPath:(FPath *)ackPath + affectedTree:(FImmutableTree *)affectedTree + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + + if ([writesCache shadowingWriteAtPath:ackPath] != nil) { + return viewCache; + } + + // Only filter server node if it is currently filtered + BOOL filterServerNode = viewCache.cachedServerSnap.isFiltered; + + // Essentially we'll just get our existing server cache for the affected + // paths and re-apply it as a server update now that it won't be shadowed. + FCacheNode *serverCache = viewCache.cachedServerSnap; + if (affectedTree.value != nil) { + // This is an overwrite. + if ((ackPath.isEmpty && serverCache.isFullyInitialized) || + [serverCache isCompleteForPath:ackPath]) { + return + [self applyServerOverwriteTo:viewCache + changePath:ackPath + snap:[serverCache.node getChild:ackPath] + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else if (ackPath.isEmpty) { + // This is a goofy edge case where we are acking data at this + // location but don't have full data. We should just re-apply + // whatever we have in our cache as a merge. + FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + for (FNamedNode *child in serverCache.node.childEnumerator) { + changedChildren = [changedChildren addWrite:child.node + atKey:child.name]; + } + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else { + return viewCache; + } + } else { + // This is a merge. + __block FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + [affectedTree forEach:^(FPath *mergePath, id value) { + FPath *serverCachePath = [ackPath child:mergePath]; + if ([serverCache isCompleteForPath:serverCachePath]) { + changedChildren = [changedChildren + addWrite:[serverCache.node getChild:serverCachePath] + atPath:mergePath]; + } + }]; + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } +} + +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + if ([writesCache shadowingWriteAtPath:path] != nil) { + return viewCache; + } else { + id source = [[FWriteTreeCompleteChildSource alloc] + initWithWrites:writesCache + viewCache:viewCache + serverCache:optCompleteCache]; + FIndexedNode *oldEventCache = viewCache.cachedEventSnap.indexedNode; + FIndexedNode *newEventCache; + if (path.isEmpty || [[path getFront] isEqualToString:@".priority"]) { + id newNode; + if (viewCache.cachedServerSnap.isFullyInitialized) { + newNode = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } else { + newNode = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + viewCache.cachedServerSnap.node]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:newNode + index:self.filter.index]; + newEventCache = [self.filter updateFullNode:oldEventCache + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [path getFront]; + id newChild = + [writesCache calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + if (newChild == nil && + [viewCache.cachedServerSnap isCompleteForChild:childKey]) { + newChild = [oldEventCache.node getImmediateChild:childKey]; + } + if (newChild != nil) { + newEventCache = [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:newChild + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else if (newChild == nil && + [viewCache.cachedEventSnap.node hasChild:childKey]) { + // No complete child available, delete the existing one, if any + newEventCache = + [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:[FEmptyNode emptyNode] + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else { + newEventCache = oldEventCache; + } + if (newEventCache.node.isEmpty && + viewCache.cachedServerSnap.isFullyInitialized) { + // We might have reverted all child writes. Maybe the old event + // was a leaf node. + id complete = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + if (complete.isLeafNode) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:complete]; + newEventCache = [self.filter updateFullNode:newEventCache + withNewNode:indexed + accumulator:accumulator]; + } + } + } + BOOL complete = viewCache.cachedServerSnap.isFullyInitialized || + [writesCache shadowingWriteAtPath:[FPath empty]] != nil; + return [viewCache updateEventSnap:newEventCache + isComplete:complete + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)listenCompleteOldCache:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)servercache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerNode = viewCache.cachedServerSnap; + FViewCache *newViewCache = [viewCache + updateServerSnap:oldServerNode.indexedNode + isComplete:(oldServerNode.isFullyInitialized || path.isEmpty) + isFiltered:oldServerNode.isFiltered]; + return [self + generateEventCacheAfterServerEvent:newViewCache + path:path + writesCache:writesCache + source:[FNoCompleteChildSource instance] + accumulator:accumulator]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h new file mode 100644 index 0000000..8d3e2ef --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; + +@interface FViewProcessorResult : NSObject +@property(nonatomic, strong, readonly) FViewCache *viewCache; +/** + * List of FChanges. + */ +@property(nonatomic, strong, readonly) NSArray *changes; + +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m new file mode 100644 index 0000000..0d38947 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessorResult.h" +#import "FViewCache.h" + +@interface FViewProcessorResult () +@property(nonatomic, strong, readwrite) FViewCache *viewCache; +@property(nonatomic, strong, readwrite) NSArray *changes; +@end + +@implementation FViewProcessorResult +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes { + self = [super init]; + if (self) { + self.viewCache = viewCache; + self.changes = changes; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h new file mode 100644 index 0000000..a4f8b15 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FTypedefs.h" +#import "FTypedefs_Private.h" + +@protocol FIRAuthInterop; + +@protocol FAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback; + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener; + +@end + +@interface FAuthTokenProvider : NSObject + ++ (id)authTokenProviderWithAuth:(id)auth; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m new file mode 100644 index 0000000..cd7fbe7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" + +#import +#import +#import +#import + +#import "FIRDatabaseQuery_Private.h" +#import "FIRNoopAuthTokenProvider.h" +#import "FUtilities.h" + +@interface FAuthStateListenerWrapper : NSObject + +@property(nonatomic, copy) fbt_void_nsstring listener; +@property(nonatomic, weak) id auth; + +@end + +@implementation FAuthStateListenerWrapper + +- (instancetype)initWithListener:(fbt_void_nsstring)listener + auth:(id)auth { + self = [super init]; + if (self != nil) { + self->_listener = listener; + self->_auth = auth; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(authStateDidChangeNotification:) + name:FIRAuthStateDidChangeInternalNotification + object:nil]; + } + return self; +} + +- (void)authStateDidChangeNotification:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + if (notification.object == self.auth) { + NSString *token = + userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + self.listener(token); + }); + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + +@interface FIRFirebaseAuthTokenProvider : NSObject + +@property(nonatomic, strong) id auth; +/** Strong references to the auth listeners as they are only weak in + * FIRFirebaseApp */ +@property(nonatomic, strong) NSMutableArray *authListeners; + +- (instancetype)initWithAuth:(id)auth; + +@end + +@implementation FIRFirebaseAuthTokenProvider + +- (instancetype)initWithAuth:(id)auth { + self = [super init]; + if (self != nil) { + self->_auth = auth; + self->_authListeners = [NSMutableArray array]; + } + return self; +} + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + if (self.auth == nil) { + // Signal that Auth is not available by returning nil. + callback(nil, nil); + } else { + [self.auth getTokenForcingRefresh:forceRefresh + withCallback:^(NSString *_Nullable token, + NSError *_Nullable error) { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(token, error); + }); + }]; + } +} + +- (void)listenForTokenChanges:(_Nonnull fbt_void_nsstring)listener { + FAuthStateListenerWrapper *wrapper = + [[FAuthStateListenerWrapper alloc] initWithListener:listener + auth:self.auth]; + [self.authListeners addObject:wrapper]; +} + +@end + +@implementation FAuthTokenProvider + ++ (id)authTokenProviderWithAuth: + (id)authInterop { + return [[FIRFirebaseAuthTokenProvider alloc] initWithAuth:authInterop]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h new file mode 100644 index 0000000..137c0ce --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import + +@interface FIRNoopAuthTokenProvider : NSObject + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m new file mode 100644 index 0000000..c50d308 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRNoopAuthTokenProvider.h" +#import "FAuthTokenProvider.h" +#import "FIRDatabaseQuery_Private.h" + +@implementation FIRNoopAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(nil, nil); + }); +} + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener { + // no-op, because token never changes +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h new file mode 100644 index 0000000..6305d34 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FCachePolicy + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries; +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck; +- (float)percentOfQueriesToPruneAtOnce; +- (NSUInteger)maxNumberOfQueriesToKeep; + +@end + +@interface FLRUCachePolicy : NSObject + +@property(nonatomic, readonly) NSUInteger maxSize; + +- (id)initWithMaxSize:(NSUInteger)maxSize; + +@end + +@interface FNoCachePolicy : NSObject + ++ (FNoCachePolicy *)noCachePolicy; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m new file mode 100644 index 0000000..c1ecd98 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCachePolicy.h" + +@interface FLRUCachePolicy () + +@property(nonatomic, readwrite) NSUInteger maxSize; + +@end + +static const NSUInteger kFServerUpdatesBetweenCacheSizeChecks = 1000; +static const NSUInteger kFMaxNumberOfPrunableQueriesToKeep = 1000; +static const float kFPercentOfQueriesToPruneAtOnce = 0.2f; + +@implementation FLRUCachePolicy + +- (id)initWithMaxSize:(NSUInteger)maxSize { + self = [super init]; + if (self != nil) { + self->_maxSize = maxSize; + } + return self; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return cacheSize > self.maxSize || + numTrackedQueries > kFMaxNumberOfPrunableQueriesToKeep; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return serverUpdatesSinceLastCheck > kFServerUpdatesBetweenCacheSizeChecks; +} + +- (float)percentOfQueriesToPruneAtOnce { + return kFPercentOfQueriesToPruneAtOnce; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return kFMaxNumberOfPrunableQueriesToKeep; +} + +@end + +@implementation FNoCachePolicy + ++ (FNoCachePolicy *)noCachePolicy { + return [[FNoCachePolicy alloc] init]; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return NO; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return NO; +} + +- (float)percentOfQueriesToPruneAtOnce { + return 0; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return NSUIntegerMax; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h new file mode 100644 index 0000000..6d32b98 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" +#import "FQuerySpec.h" +#import "FStorageEngine.h" + +@class FCacheNode; +@class FTrackedQuery; +@class FPruneForest; +@class FRepoInfo; + +@interface FLevelDBStorageEngine : NSObject + ++ (NSString *)firebaseDir; + +- (id)initWithPath:(NSString *)path; + +- (void)runLegacyMigration:(FRepoInfo *)info; +- (void)purgeEverything; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m new file mode 100644 index 0000000..77a8303 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m @@ -0,0 +1,990 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FLevelDBStorageEngine.h" + +#import "APLevelDB.h" +#import "FEmptyNode.h" +#import "FPendingPut.h" // For legacy migration +#import "FPruneForest.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import "FWriteRecord.h" +#import + +@interface FLevelDBStorageEngine () + +@property(nonatomic, strong) NSString *basePath; +@property(nonatomic, strong) APLevelDB *writesDB; +@property(nonatomic, strong) APLevelDB *serverCacheDB; + +@end + +// WARNING: If you change this, you need to write a migration script +static NSString *const kFPersistenceVersion = @"1"; + +static NSString *const kFServerDBPath = @"server_data"; +static NSString *const kFWritesDBPath = @"writes"; + +static NSString *const kFUserWriteId = @"id"; +static NSString *const kFUserWritePath = @"path"; +static NSString *const kFUserWriteOverwrite = @"o"; +static NSString *const kFUserWriteMerge = @"m"; + +static NSString *const kFTrackedQueryId = @"id"; +static NSString *const kFTrackedQueryPath = @"path"; +static NSString *const kFTrackedQueryParams = @"p"; +static NSString *const kFTrackedQueryLastUse = @"lu"; +static NSString *const kFTrackedQueryIsComplete = @"c"; +static NSString *const kFTrackedQueryIsActive = @"a"; + +static NSString *const kFServerCachePrefix = @"/server_cache/"; +// '~' is the last non-control character in the ASCII table until 127 +// We wan't the entire range of thing stored in the DB +static NSString *const kFServerCacheRangeEnd = @"/server_cache~"; +static NSString *const kFTrackedQueriesPrefix = @"/tracked_queries/"; +static NSString *const kFTrackedQueryKeysPrefix = @"/tracked_query_keys/"; + +// Failed to load JSON because a valid JSON turns out to be NaN while +// deserializing +static const NSInteger kFNanFailureCode = 3840; + +static NSString *writeRecordKey(NSUInteger writeId) { + return [NSString stringWithFormat:@"%lu", (unsigned long)(writeId)]; +} + +static NSString *serverCacheKey(FPath *path) { + return [NSString stringWithFormat:@"%@%@", kFServerCachePrefix, + ([path toStringWithTrailingSlash])]; +} + +static NSString *trackedQueryKey(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu", kFTrackedQueriesPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKeyPrefix(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu/", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKey(NSUInteger trackedQueryId, NSString *key) { + return [NSString stringWithFormat:@"%@%lu/%@", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId, key]; +} + +@implementation FLevelDBStorageEngine +#pragma mark - Constructors + +- (id)initWithPath:(NSString *)dbPath { + self = [super init]; + if (self) { + self.basePath = [[FLevelDBStorageEngine firebaseDir] + stringByAppendingPathComponent:dbPath]; + /* For reference: + serverDataDB = [aPersistence createDbByName:@"server_data"]; + FPangolinDB *completenessDb = [aPersistence + createDbByName:@"server_complete"]; + */ + [FLevelDBStorageEngine ensureDir:self.basePath markAsDoNotBackup:YES]; + [self runMigration]; + [self openDatabases]; + } + return self; +} + +- (void)runMigration { + // Currently we're at version 1, so all we need to do is write that to a + // file + NSString *versionFile = + [self.basePath stringByAppendingPathComponent:@"version"]; + NSError *error; + NSString *oldVersion = + [NSString stringWithContentsOfFile:versionFile + encoding:NSUTF8StringEncoding + error:&error]; + if (!oldVersion) { + // This is probably fine, we don't have a version file yet + BOOL success = [kFPersistenceVersion writeToFile:versionFile + atomically:NO + encoding:NSUTF8StringEncoding + error:&error]; + if (!success) { + FFWarn(@"I-RDB076001", @"Failed to write version for database: %@", + error); + } + } else if ([oldVersion isEqualToString:kFPersistenceVersion]) { + // Everythings fine no need for migration + } else { + // If we add more versions in the future, we need to run migration here + [NSException raise:NSInternalInconsistencyException + format:@"Unrecognized database version: %@", oldVersion]; + } +} + +- (void)runLegacyMigration:(FRepoInfo *)info { + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + NSString *firebaseDir = + [documentsDir stringByAppendingPathComponent:@"firebase"]; + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", info.host, info.namespace]; + NSString *legacyBaseDir = + [NSString stringWithFormat:@"%@/1/%@/v1", firebaseDir, repoHashString]; + if ([[NSFileManager defaultManager] fileExistsAtPath:legacyBaseDir]) { + FFWarn(@"I-RDB076002", @"Legacy database found, migrating..."); + // We only need to migrate writes + NSError *error = nil; + APLevelDB *writes = [APLevelDB + levelDBWithPath:[legacyBaseDir stringByAppendingPathComponent: + @"outstanding_puts"] + error:&error]; + if (writes != nil) { + __block NSUInteger numberOfWritesRestored = 0; + // Maybe we could use write batches, but what the heck, I'm sure + // it'll go fine :P + [writes enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + id pendingPut = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + if ([pendingPut isKindOfClass:[FPendingPut class]]) { + FPendingPut *put = pendingPut; + id newNode = + [FSnapshotUtilities nodeFrom:put.data + priority:put.priority]; + [self saveUserOverwrite:newNode + atPath:put.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut + isKindOfClass:[FPendingPutPriority class]]) { + // This is for backwards compatibility. Older clients will + // save FPendingPutPriority. New ones will need to read it and + // translate. + FPendingPutPriority *putPriority = pendingPut; + FPath *priorityPath = + [putPriority.path childFromString:@".priority"]; + id newNode = + [FSnapshotUtilities nodeFrom:putPriority.priority + priority:nil]; + [self saveUserOverwrite:newNode + atPath:priorityPath + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut isKindOfClass:[FPendingUpdate class]]) { + FPendingUpdate *update = pendingPut; + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:update.data]; + [self saveUserMerge:merge + atPath:update.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else { + FFWarn(@"I-RDB076003", + @"Failed to migrate legacy write, meh!"); + } + }]; + FFWarn(@"I-RDB076004", @"Migrated %lu writes", + (unsigned long)numberOfWritesRestored); + [writes close]; + FFWarn(@"I-RDB076005", @"Deleting legacy database..."); + BOOL success = + [[NSFileManager defaultManager] removeItemAtPath:legacyBaseDir + error:&error]; + if (!success) { + FFWarn(@"I-RDB076006", @"Failed to delete legacy database: %@", + error); + } else { + FFWarn(@"I-RDB076007", @"Finished migrating legacy database."); + } + } else { + FFWarn(@"I-RDB076008", @"Failed to migrate old database: %@", + error); + } + } +} + +- (void)openDatabases { + self.serverCacheDB = [self createDB:kFServerDBPath]; + self.writesDB = [self createDB:kFWritesDBPath]; +} + +- (void)purgeDatabase:(NSString *)dbPath { + NSString *path = [self.basePath stringByAppendingPathComponent:dbPath]; + NSError *error; + FFWarn(@"I-RDB076009", @"Deleting database at path %@", path); + BOOL success = [[NSFileManager defaultManager] removeItemAtPath:path + error:&error]; + if (!success) { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to delete database files: %@", error]; + } +} + +- (void)purgeEverything { + [self close]; + [@[ kFServerDBPath, kFWritesDBPath ] + enumerateObjectsUsingBlock:^(NSString *dbPath, NSUInteger idx, + BOOL *stop) { + [self purgeDatabase:dbPath]; + }]; + + [self openDatabases]; +} + +- (void)close { + // autoreleasepool will cause deallocation which will close the DB + @autoreleasepool { + [self.serverCacheDB close]; + self.serverCacheDB = nil; + [self.writesDB close]; + self.writesDB = nil; + } +} + ++ (NSString *)firebaseDir { +#if TARGET_OS_IOS || TARGET_OS_TV + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + return [documentsDir stringByAppendingPathComponent:@"firebase"]; +#elif TARGET_OS_OSX + return [NSHomeDirectory() stringByAppendingPathComponent:@".firebase"]; +#endif +} + +- (APLevelDB *)createDB:(NSString *)dbName { + NSError *err = nil; + NSString *path = [self.basePath stringByAppendingPathComponent:dbName]; + APLevelDB *db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + FFWarn(@"I-RDB076036", + @"Failed to read database persistence file '%@': %@", dbName, + [err localizedDescription]); + err = nil; + + // Delete the database and try again. + [self purgeDatabase:dbName]; + db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + NSString *reason = [NSString + stringWithFormat:@"Error initializing persistence: %@", + [err description]]; + @throw [NSException + exceptionWithName:@"FirebaseDatabasePersistenceFailure" + reason:reason + userInfo:nil]; + } + } + + return db; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteOverwrite : [node valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user overwrite: %@, (Error: %@)", + write, error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteMerge : [merge valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user merge: %@ (Error: %@)", write, + error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.writesDB removeKey:writeRecordKey(writeId)]; +} + +- (void)removeAllUserWrites { + __block NSUInteger count = 0; + NSDate *start = [NSDate date]; + id batch = [self.writesDB beginWriteBatch]; + [self.writesDB enumerateKeys:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + count++; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076010", @"Failed to remove all users writes on disk!"); + } else { + FFDebug(@"I-RDB076011", @"Removed %lu writes in %fms", + (unsigned long)count, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSArray *)userWrites { + NSDate *date = [NSDate date]; + NSMutableArray *writes = [NSMutableArray array]; + [self.writesDB enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + NSError *error = nil; + NSDictionary *writeJSON = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (writeJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076012", + @"Failed to deserialize write (%@), likely because of out " + @"of range doubles (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076013", @"Removing failed write with key %@", key); + [self.writesDB removeKey:key]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialize write: %@", error]; + } + } else { + NSInteger writeId = + ((NSNumber *)writeJSON[kFUserWriteId]).integerValue; + FPath *path = [FPath pathWithString:writeJSON[kFUserWritePath]]; + FWriteRecord *writeRecord; + if (writeJSON[kFUserWriteMerge] != nil) { + // It's a merge + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:writeJSON[kFUserWriteMerge]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + merge:merge + writeId:writeId]; + } else { + // It's an overwrite + NSAssert(writeJSON[kFUserWriteOverwrite] != nil, + @"Persisted write did not contain merge or overwrite!"); + id node = + [FSnapshotUtilities nodeFrom:writeJSON[kFUserWriteOverwrite]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + overwrite:node + writeId:writeId + visible:YES]; + } + [writes addObject:writeRecord]; + } + }]; + // Make sure writes are sorted + [writes sortUsingComparator:^NSComparisonResult(FWriteRecord *one, + FWriteRecord *two) { + if (one.writeId < two.writeId) { + return NSOrderedAscending; + } else if (one.writeId > two.writeId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + FFDebug(@"I-RDB076014", @"Loaded %lu writes in %fms", + (unsigned long)writes.count, [date timeIntervalSinceNow] * -1000); + return writes; +} + +- (id)serverCacheAtPath:(FPath *)path { + NSDate *start = [NSDate date]; + id data = [self internalNestedDataForPath:path]; + id node = [FSnapshotUtilities nodeFrom:data]; + FFDebug(@"I-RDB076015", @"Loaded node with %d children at %@ in %fms", + [node numChildren], path, [start timeIntervalSinceNow] * -1000); + return node; +} + +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block id node = [FEmptyNode emptyNode]; + [keys enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + id data = [self internalNestedDataForPath:[path childFromString:key]]; + node = [node updateImmediateChild:key + withNewChild:[FSnapshotUtilities nodeFrom:data]]; + }]; + FFDebug(@"I-RDB076016", + @"Loaded node with %d children for %lu keys at %@ in %fms", + [node numChildren], (unsigned long)keys.count, path, + [start timeIntervalSinceNow] * -1000); + return node; +} + +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + __block NSUInteger counter = 0; + if (merge) { + // remove any children that exist + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + FPath *childPath = [path childFromString:childKey]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:childNode + atPath:childPath + batch:batch + counter:&counter]; + }]; + } else { + // remove everything + [self removeAllWithPrefix:serverCacheKey(path) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node atPath:path batch:batch counter:&counter]; + } + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076017", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076018", @"Saved %lu leaf nodes for overwrite in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block NSUInteger counter = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node + atPath:childPath + batch:batch + counter:&counter]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076019", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076020", @"Saved %lu leaf nodes for merge in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveNodeInternal:(id)node + atPath:(FPath *)path + batch:(id)batch + counter:(NSUInteger *)counter { + id data = [node valForExport:YES]; + if (data != nil && ![data isKindOfClass:[NSNull class]]) { + [self internalSetNestedData:data + forKey:serverCacheKey(path) + withBatch:batch + counter:counter]; + } +} + +- (NSUInteger)serverCacheEstimatedSizeInBytes { + // Use the exact size, because for pruning the approximate size can lead to + // weird situations where we prune everything because no compaction is ever + // run + return [self.serverCacheDB exactSizeFrom:kFServerCachePrefix + to:kFServerCacheRangeEnd]; +} + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path { + // TODO: be more intelligent, don't scan entire database... + + __block NSUInteger pruned = 0; + __block NSUInteger kept = 0; + NSDate *start = [NSDate date]; + + NSString *prefix = serverCacheKey(path); + id batch = [self.serverCacheDB beginWriteBatch]; + + [self.serverCacheDB + enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *dbKey, BOOL *stop) { + NSString *pathStr = + [dbKey substringFromIndex:prefix.length]; + FPath *relativePath = [[FPath alloc] initWith:pathStr]; + if ([pruneForest shouldPruneUnkeptDescendantsAtPath: + relativePath]) { + pruned++; + [batch removeKey:dbKey]; + } else { + kept++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076021", @"Failed to prune cache on disk!"); + } else { + FFDebug(@"I-RDB076022", @"Pruned %lu paths, kept %lu paths in %fms", + (unsigned long)pruned, (unsigned long)kept, + [start timeIntervalSinceNow] * -1000); + } +} + +#pragma mark - Tracked Queries + +- (NSArray *)loadTrackedQueries { + NSDate *date = [NSDate date]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + [self.serverCacheDB + enumerateKeysWithPrefix:kFTrackedQueriesPrefix + asData:^(NSString *key, NSData *data, BOOL *stop) { + NSError *error = nil; + NSDictionary *queryJSON = + [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (queryJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn( + @"I-RDB076023", + @"Failed to deserialize tracked query " + @"(%@), likely because of out of range " + @"doubles (Error: %@)", + [[NSString alloc] + initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076024", + @"Removing failed tracked query with " + @"key %@", + key); + [self.serverCacheDB removeKey:key]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Failed to deserialize tracked " + @"query: %@", + error]; + } + } else { + NSUInteger queryId = + ((NSNumber *)queryJSON[kFTrackedQueryId]) + .unsignedIntegerValue; + FPath *path = + [FPath pathWithString: + queryJSON[kFTrackedQueryPath]]; + FQueryParams *params = [FQueryParams + fromQueryObject:queryJSON + [kFTrackedQueryParams]]; + FQuerySpec *query = + [[FQuerySpec alloc] initWithPath:path + params:params]; + BOOL isComplete = + [queryJSON[kFTrackedQueryIsComplete] + boolValue]; + BOOL isActive = + [queryJSON[kFTrackedQueryIsActive] + boolValue]; + NSTimeInterval lastUse = + [queryJSON[kFTrackedQueryLastUse] + doubleValue]; + + FTrackedQuery *trackedQuery = + [[FTrackedQuery alloc] + initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:isComplete]; + + [trackedQueries addObject:trackedQuery]; + } + }]; + FFDebug(@"I-RDB076025", @"Loaded %lu tracked queries in %fms", + (unsigned long)trackedQueries.count, + [date timeIntervalSinceNow] * -1000); + return trackedQueries; +} + +- (void)removeTrackedQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [batch removeKey:trackedQueryKey(queryId)]; + __block NSUInteger keyCount = 0; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + keyCount++; + }]; + + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076026", @"Failed to remove tracked query on disk!"); + } else { + FFDebug(@"I-RDB076027", + @"Removed query with id %lu (and removed %lu keys) in %fms", + (unsigned long)queryId, (unsigned long)keyCount, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveTrackedQuery:(FTrackedQuery *)query { + NSDate *start = [NSDate date]; + NSDictionary *trackedQuery = @{ + kFTrackedQueryId : @(query.queryId), + kFTrackedQueryPath : [query.query.path toStringWithTrailingSlash], + kFTrackedQueryParams : [query.query.params wireProtocolParams], + kFTrackedQueryLastUse : @(query.lastUse), + kFTrackedQueryIsComplete : @(query.isComplete), + kFTrackedQueryIsActive : @(query.isActive) + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:trackedQuery + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize tracked query (Error: %@)", error); + [self.serverCacheDB setData:data forKey:trackedQueryKey(query.queryId)]; + FFDebug(@"I-RDB076028", @"Saved tracked query %lu in %fms", + (unsigned long)query.queryId, [start timeIntervalSinceNow] * -1000); +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + __block NSUInteger removed = 0; + __block NSUInteger added = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + NSMutableSet *seenKeys = [NSMutableSet set]; + // First, delete any keys that might be stored and are not part of the + // current keys + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + if ([keys containsObject:actualKey]) { + // Already in DB + [seenKeys addObject:actualKey]; + } else { + // Not part of set, delete key + [batch removeKey:dbKey]; + removed++; + } + }]; + + // Next add any keys that are missing in the database + [keys enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + if (![seenKeys containsObject:childKey]) { + [batch setString:childKey + forKey:trackedQueryKeysKey(queryId, childKey)]; + added++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076029", @"Failed to set tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076030", + @"Set %lu tracked keys (%lu added, %lu removed) for query %lu " + @"in %fms", + (unsigned long)keys.count, (unsigned long)added, + (unsigned long)removed, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [removed enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:trackedQueryKeysKey(queryId, key)]; + }]; + [added enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch setString:key forKey:trackedQueryKeysKey(queryId, key)]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076031", @"Failed to update tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076032", + @"Added %lu tracked keys, removed %lu for query %lu in %fms", + (unsigned long)added.count, (unsigned long)removed.count, + (unsigned long)queryId, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + NSMutableSet *set = [NSMutableSet set]; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + [set addObject:actualKey]; + }]; + FFDebug(@"I-RDB076033", @"Loaded %lu tracked keys for query %lu in %fms", + (unsigned long)set.count, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + return set; +} + +#pragma mark - Internal methods + +- (void)removeAllLeafNodesOnPath:(FPath *)path + batch:(id)batch { + while (!path.isEmpty) { + [batch removeKey:serverCacheKey(path)]; + path = [path parent]; + } + // Make sure to delete any nodes at the root + [batch removeKey:serverCacheKey([FPath empty])]; +} + +- (void)removeAllWithPrefix:(NSString *)prefix + batch:(id)batch + database:(APLevelDB *)database { + assert(prefix != nil); + + [database enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + }]; +} + +#pragma mark - Internal helper methods + +- (void)internalSetNestedData:(id)value + forKey:(NSString *)key + withBatch:(id)batch + counter:(NSUInteger *)counter { + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id childKey, id obj, + BOOL *stop) { + assert(obj != nil); + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", key, childKey]; + [self internalSetNestedData:obj + forKey:childPath + withBatch:batch + counter:counter]; + }]; + } else { + NSData *data = [self serializePrimitive:value]; + [batch setData:data forKey:key]; + (*counter)++; + } +} + +- (id)internalNestedDataForPath:(FPath *)path { + NSAssert(path != nil, @"Path was nil!"); + + NSString *baseKey = serverCacheKey(path); + + // HACK to make sure iter is freed now to avoid race conditions (if self.db + // is deleted before iter, you get an access violation). + @autoreleasepool { + APLevelDBIterator *iter = + [APLevelDBIterator iteratorWithLevelDB:self.serverCacheDB]; + + [iter seekToKey:baseKey]; + if (iter.key == nil || ![iter.key hasPrefix:baseKey]) { + // No data. + return nil; + } else { + return [self internalNestedDataFromIterator:iter + andKeyPrefix:baseKey]; + } + } +} + +- (id)internalNestedDataFromIterator:(APLevelDBIterator *)iterator + andKeyPrefix:(NSString *)prefix { + NSString *key = iterator.key; + + if ([key isEqualToString:prefix]) { + id result = [self deserializePrimitive:iterator.valueAsData]; + [iterator nextKey]; + return result; + } else { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + while (key != nil && [key hasPrefix:prefix]) { + NSString *relativePath = [key substringFromIndex:prefix.length]; + NSArray *pathPieces = + [relativePath componentsSeparatedByString:@"/"]; + assert(pathPieces.count > 0); + NSString *childName = pathPieces[0]; + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", prefix, childName]; + id childValue = [self internalNestedDataFromIterator:iterator + andKeyPrefix:childPath]; + [dict setValue:childValue forKey:childName]; + + key = iterator.key; + } + return dict; + } +} + +- (NSData *)serializePrimitive:(id)value { + // HACK: The built-in serialization only works on dicts and arrays. So we + // create an array and then strip off the leading / trailing byte (the [ and + // ]). + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:@[ value ] + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize primitive: %@", error); + + return [data subdataWithRange:NSMakeRange(1, data.length - 2)]; +} + +- (id)fixDoubleParsing:(id)value + __attribute__((no_sanitize("float-cast-overflow"))) { + if ([value isKindOfClass:[NSDecimalNumber class]]) { + // In case the value is an NSDecimalNumber, we may be dealing with + // precisions that are higher than what can be represented in a double. + // In this case it does not suffice to check for integral numbers by + // casting the [value doubleValue] to an int64_t, because this will + // cause the compared values to be rounded to double precision. + // Coupled with a bug in [NSDecimalNumber longLongValue] that triggers + // when converting values with high precision, this would cause + // values of high precision, but with an integral 'doubleValue' + // representation to be converted to bogus values. + // A radar for the NSDecimalNumber issue can be found here: + // http://www.openradar.me/radar?id=5007005597040640 + // Consider the NSDecimalNumber value: 999.9999999999999487 + // This number has a 'doubleValue' of 1000. Using the previous version + // of this method would cause the value to be interpreted to be integral + // and then the resulting value would be based on the longLongValue + // which due to the NSDecimalNumber issue would turn out as -844. + // By using NSDecimal logic to test for integral values, + // 999.9999999999999487 will not be considered integral, and instead + // of triggering the 'longLongValue' issue, it will be returned as + // the 'doubleValue' representation (1000). + // Please note, that even without the NSDecimalNumber issue, the + // 'correct' longLongValue of 999.9999999999999487 is 999 and not 1000, + // so the previous code would cause issues even without the bug + // referenced in the radar. + NSDecimal original = [(NSDecimalNumber *)value decimalValue]; + NSDecimal rounded; + NSDecimalRound(&rounded, &original, 0, NSRoundPlain); + if (NSDecimalCompare(&original, &rounded) != NSOrderedSame) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } else if ([value isKindOfClass:[NSNumber class]]) { + // The parser for double values in JSONSerialization at the root takes + // some short-cuts and delivers wrong results (wrong rounding) for some + // double values, including 2.47. Because we use the exact bytes for + // hashing on the server this will lead to hash mismatches. The parser + // of NSNumber seems to be more in line with what the server expects, so + // we use that here + CFNumberType type = CFNumberGetType((CFNumberRef)value); + if (type == kCFNumberDoubleType || type == kCFNumberFloatType) { + // The NSJSON parser returns all numbers as double values, even + // those that contain no exponent. To make sure that the String + // conversion below doesn't unexpectedly reduce precision, we make + // sure that our number is indeed not an integer. + if ((double)(int64_t)[value doubleValue] != [value doubleValue]) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } + } + return value; +} + +- (id)deserializePrimitive:(NSData *)data { + NSError *error = nil; + id result = + [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingAllowFragments + error:&error]; + if (result != nil) { + return [self fixDoubleParsing:result]; + } else { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076034", + @"Failed to load primitive %@, likely because doubles where " + @"out of range (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + return [NSNull null]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialiaze primitive: %@", error]; + return nil; + } + } +} + ++ (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup { + NSError *error; + BOOL success = + [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + @throw [NSException + exceptionWithName:@"FailedToCreatePersistenceDir" + reason:@"Failed to create persistence directory." + userInfo:@{@"path" : path}]; + } + + if (markAsDoNotBackup) { + NSURL *firebaseDirURL = [NSURL fileURLWithPath:path]; + success = [firebaseDirURL setResourceValue:@YES + forKey:NSURLIsExcludedFromBackupKey + error:&error]; + if (!success) { + FFWarn( + @"I-RDB076035", + @"Failed to mark firebase database folder as do not backup: %@", + error); + [NSException raise:@"Error marking as do not backup" + format:@"Failed to mark folder %@ as do not backup", + firebaseDirURL]; + } + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h new file mode 100644 index 0000000..602bf8c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +// These are all legacy classes and are used to migrate older persistence data +// base to newer ones These classes should not be used in newer code + +@interface FPendingPut : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id data; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end + +@interface FPendingPutPriority : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; + +@end + +@interface FPendingUpdate : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) NSDictionary *data; + +- (id)initWithPath:(FPath *)aPath andData:(NSDictionary *)aData; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m new file mode 100644 index 0000000..c519599 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPendingPut.h" + +@implementation FPendingPut + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingPutPriority + +@synthesize path; +@synthesize priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingUpdate + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h new file mode 100644 index 0000000..681c56d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCacheNode.h" +#import "FCachePolicy.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FQuerySpec.h" +#import "FRepoInfo.h" +#import "FStorageEngine.h" + +@interface FPersistenceManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy; +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path; +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path; + +- (void)setQueryComplete:(FQuerySpec *)spec; +- (void)setQueryActive:(FQuerySpec *)spec; +- (void)setQueryInactive:(FQuerySpec *)spec; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m new file mode 100644 index 0000000..8924802 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m @@ -0,0 +1,231 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPersistenceManager.h" +#import "FCacheNode.h" +#import "FClock.h" +#import "FIndexedNode.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FTrackedQueryManager.h" +#import "FUtilities.h" +#import + +@interface FPersistenceManager () + +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id cachePolicy; +@property(nonatomic, strong) FTrackedQueryManager *trackedQueryManager; +@property(nonatomic) NSUInteger serverCacheUpdatesSinceLastPruneCheck; + +@end + +@implementation FPersistenceManager + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_cachePolicy = cachePolicy; + self->_trackedQueryManager = [[FTrackedQueryManager alloc] + initWithStorageEngine:self.storageEngine + clock:[FSystemClock clock]]; + } + return self; +} + +- (void)close { + [self.storageEngine close]; + self.storageEngine = nil; + self.trackedQueryManager = nil; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserOverwrite:node atPath:path writeId:writeId]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserMerge:merge atPath:path writeId:writeId]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.storageEngine removeUserWrite:writeId]; +} + +- (void)removeAllUserWrites { + [self.storageEngine removeAllUserWrites]; +} + +- (NSArray *)userWrites { + return [self.storageEngine userWrites]; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + NSSet *trackedKeys; + BOOL complete; + // TODO[offline]: Should we use trackedKeys to find out if this location is + // a child of a complete query? + if ([self.trackedQueryManager isQueryComplete:query]) { + complete = YES; + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + if (!query.loadsAllData && trackedQuery.isComplete) { + trackedKeys = [self.storageEngine + trackedQueryKeysForQuery:trackedQuery.queryId]; + } else { + trackedKeys = nil; + } + } else { + complete = NO; + trackedKeys = + [self.trackedQueryManager knownCompleteChildrenAtPath:query.path]; + } + + id node; + if (trackedKeys != nil) { + node = [self.storageEngine serverCacheForKeys:trackedKeys + atPath:query.path]; + } else { + node = [self.storageEngine serverCacheAtPath:query.path]; + } + + FIndexedNode *indexedNode = [FIndexedNode indexedNodeWithNode:node + index:query.index]; + return [[FCacheNode alloc] initWithIndexedNode:indexedNode + isFullyInitialized:complete + isFiltered:(trackedKeys != nil)]; +} + +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)query { + BOOL merge = !query.loadsAllData; + [self.storageEngine updateServerCache:node atPath:query.path merge:merge]; + [self setQueryComplete:query]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + [self.storageEngine updateServerCacheWithMerge:merge atPath:path]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path { + // TODO[offline]: rework this to be more efficient + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + [self applyUserWrite:node toServerCacheAtPath:[path child:relativePath]]; + }]; +} + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path { + // This is a hack to guess whether we already cached this because we got a + // server data update for this write via an existing active default query. + // If we didn't, then we'll manually cache this and add a tracked query to + // mark it complete and keep it cached. Unfortunately this is just a guess + // and it's possible that we *did* get an update (e.g. via a filtered query) + // and by overwriting the cache here, we'll actually store an incorrect + // value (e.g. in the case that we wrote a ServerValue.TIMESTAMP and the + // server resolved it to a different value). + // TODO[offline]: Consider reworking. + if (![self.trackedQueryManager hasActiveDefaultQueryAtPath:path]) { + [self.storageEngine updateServerCache:write atPath:path merge:NO]; + [self.trackedQueryManager ensureCompleteTrackedQueryAtPath:path]; + } +} + +- (void)setQueryComplete:(FQuerySpec *)query { + if (query.loadsAllData) { + [self.trackedQueryManager setQueriesCompleteAtPath:query.path]; + } else { + [self.trackedQueryManager setQueryComplete:query]; + } +} + +- (void)setQueryActive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryActive:spec]; +} + +- (void)setQueryInactive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryInactive:spec]; +} + +- (void)doPruneCheckAfterServerUpdate { + self.serverCacheUpdatesSinceLastPruneCheck++; + if ([self.cachePolicy + shouldCheckCacheSize:self.serverCacheUpdatesSinceLastPruneCheck]) { + FFDebug(@"I-RDB078001", @"Reached prune check threshold. Checking..."); + NSDate *date = [NSDate date]; + self.serverCacheUpdatesSinceLastPruneCheck = 0; + BOOL canPrune = YES; + NSUInteger cacheSize = + [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078002", @"Server cache size: %lu", + (unsigned long)cacheSize); + while (canPrune && + [self.cachePolicy + shouldPruneCacheWithSize:cacheSize + numberOfTrackedQueries:self.trackedQueryManager + .numberOfPrunableQueries]) { + FPruneForest *pruneForest = + [self.trackedQueryManager pruneOldQueries:self.cachePolicy]; + if (pruneForest.prunesAnything) { + [self.storageEngine pruneCache:pruneForest + atPath:[FPath empty]]; + } else { + canPrune = NO; + } + cacheSize = [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078003", @"Cache size after pruning: %lu", + (unsigned long)cacheSize); + } + FFDebug(@"I-RDB078004", @"Pruning round took %fms", + [date timeIntervalSinceNow] * -1000); + } +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine setTrackedQueryKeys:keys + forQueryId:trackedQuery.queryId]; +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQueryId:trackedQuery.queryId]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h new file mode 100644 index 0000000..9e77217 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FPruneForest : NSObject + ++ (FPruneForest *)empty; + +- (BOOL)prunesAnything; +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path; +- (BOOL)shouldKeepPath:(FPath *)path; +- (BOOL)affectsPath:(FPath *)path; +- (FPruneForest *)child:(NSString *)childKey; +- (FPruneForest *)childAtPath:(FPath *)childKey; +- (FPruneForest *)prunePath:(FPath *)path; +- (FPruneForest *)keepPath:(FPath *)path; +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path; +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path; + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *path))block; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m new file mode 100644 index 0000000..e795c69 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m @@ -0,0 +1,194 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPruneForest.h" + +#import "FImmutableTree.h" + +@interface FPruneForest () + +@property(nonatomic, strong) FImmutableTree *pruneForest; + +@end + +@implementation FPruneForest + +static BOOL (^kFPrunePredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return [pruneValue boolValue]; +}; + +static BOOL (^kFKeepPredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return ![pruneValue boolValue]; +}; + ++ (FImmutableTree *)pruneTree { + static dispatch_once_t onceToken; + static FImmutableTree *pruneTree; + dispatch_once(&onceToken, ^{ + pruneTree = [[FImmutableTree alloc] initWithValue:@YES]; + }); + return pruneTree; +} + ++ (FImmutableTree *)keepTree { + static dispatch_once_t onceToken; + static FImmutableTree *keepTree; + dispatch_once(&onceToken, ^{ + keepTree = [[FImmutableTree alloc] initWithValue:@NO]; + }); + return keepTree; +} + +- (id)initWithForest:(FImmutableTree *)tree { + self = [super init]; + if (self != nil) { + self->_pruneForest = tree; + } + return self; +} + ++ (FPruneForest *)empty { + static dispatch_once_t onceToken; + static FPruneForest *forest; + dispatch_once(&onceToken, ^{ + forest = [[FPruneForest alloc] initWithForest:[FImmutableTree empty]]; + }); + return forest; +} + +- (BOOL)prunesAnything { + return [self.pruneForest containsValueMatching:kFPrunePredicate]; +} + +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && [shouldPrune boolValue]; +} + +- (BOOL)shouldKeepPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && ![shouldPrune boolValue]; +} + +- (BOOL)affectsPath:(FPath *)path { + return [self.pruneForest rootMostValueOnPath:path] != nil || + ![[self.pruneForest subtreeAtPath:path] isEmpty]; +} + +- (FPruneForest *)child:(NSString *)childKey { + FImmutableTree *childPruneForest = [self.pruneForest.children get:childKey]; + if (childPruneForest == nil) { + if (self.pruneForest.value != nil) { + childPruneForest = [self.pruneForest.value boolValue] + ? [FPruneForest pruneTree] + : [FPruneForest keepTree]; + } else { + childPruneForest = [FImmutableTree empty]; + } + } else { + if (childPruneForest.value == nil && self.pruneForest.value != nil) { + childPruneForest = [childPruneForest setValue:self.pruneForest.value + atPath:[FPath empty]]; + } + } + return [[FPruneForest alloc] initWithForest:childPruneForest]; +} + +- (FPruneForest *)childAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + return [[self child:path.getFront] childAtPath:[path popFront]]; + } +} + +- (FPruneForest *)prunePath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest pruneTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest keepTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + return [self setPruneValue:[FPruneForest keepTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + return [self setPruneValue:[FPruneForest pruneTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)setPruneValue:(FImmutableTree *)pruneValue + forAll:(NSSet *)children + atPath:(FPath *)path { + FImmutableTree *subtree = [self.pruneForest subtreeAtPath:path]; + __block FImmutableSortedDictionary *childrenDictionary = subtree.children; + [children enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + childrenDictionary = [childrenDictionary insertKey:childKey + withValue:pruneValue]; + }]; + FImmutableTree *newSubtree = + [[FImmutableTree alloc] initWithValue:subtree.value + children:childrenDictionary]; + return [[FPruneForest alloc] + initWithForest:[self.pruneForest setTree:newSubtree atPath:path]]; +} + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *))block { + [self.pruneForest forEach:^(FPath *path, id value) { + if (value != nil && ![value boolValue]) { + block(path); + } + }]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h new file mode 100644 index 0000000..5f418b8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FPruneForest; +@class FPath; +@class FCompoundWrite; +@class FQuerySpec; +@class FTrackedQuery; + +@protocol FStorageEngine + +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (id)serverCacheAtPath:(FPath *)path; +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path; +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; +- (NSUInteger)serverCacheEstimatedSizeInBytes; + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path; + +- (NSArray *)loadTrackedQueries; +- (void)removeTrackedQuery:(NSUInteger)queryId; +- (void)saveTrackedQuery:(FTrackedQuery *)query; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId; +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h new file mode 100644 index 0000000..7413816 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; + +@interface FTrackedQuery : NSObject + +@property(nonatomic, readonly) NSUInteger queryId; +@property(nonatomic, strong, readonly) FQuerySpec *query; +@property(nonatomic, readonly) NSTimeInterval lastUse; +@property(nonatomic, readonly) BOOL isComplete; +@property(nonatomic, readonly) BOOL isActive; + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive; +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete; + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse; +- (FTrackedQuery *)setComplete; +- (FTrackedQuery *)setActiveState:(BOOL)isActive; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m new file mode 100644 index 0000000..6ca7ec0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQuery.h" + +#import "FQuerySpec.h" + +@interface FTrackedQuery () + +@property(nonatomic, readwrite) NSUInteger queryId; +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, readwrite) NSTimeInterval lastUse; +@property(nonatomic, readwrite) BOOL isComplete; +@property(nonatomic, readwrite) BOOL isActive; + +@end + +@implementation FTrackedQuery + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete { + self = [super init]; + if (self != nil) { + self->_queryId = queryId; + self->_query = query; + self->_lastUse = lastUse; + self->_isComplete = isComplete; + self->_isActive = isActive; + } + return self; +} + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive { + return [self initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:NO]; +} + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:lastUse + isActive:self.isActive + isComplete:self.isComplete]; +} + +- (FTrackedQuery *)setComplete { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:self.isActive + isComplete:YES]; +} + +- (FTrackedQuery *)setActiveState:(BOOL)isActive { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:isActive + isComplete:self.isComplete]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FTrackedQuery class]]) { + return NO; + } + FTrackedQuery *other = (FTrackedQuery *)object; + if (self.queryId != other.queryId) + return NO; + if (self.query != other.query && ![self.query isEqual:other.query]) + return NO; + if (self.lastUse != other.lastUse) + return NO; + if (self.isComplete != other.isComplete) + return NO; + if (self.isActive != other.isActive) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self.queryId; + hash = hash * 31 + self.query.hash; + hash = hash * 31 + (self.isActive ? 1 : 0); + hash = hash * 31 + (NSUInteger)self.lastUse; + hash = hash * 31 + (self.isComplete ? 1 : 0); + hash = hash * 31 + (self.isActive ? 1 : 0); + return hash; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h new file mode 100644 index 0000000..cd7d5a1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FStorageEngine; +@protocol FClock; +@protocol FCachePolicy; +@class FQuerySpec; +@class FPath; +@class FTrackedQuery; +@class FPruneForest; + +@interface FTrackedQueryManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock; + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query; + +- (BOOL)isQueryComplete:(FQuerySpec *)query; + +- (void)removeTrackedQuery:(FQuerySpec *)query; +- (void)setQueryComplete:(FQuerySpec *)query; +- (void)setQueriesCompleteAtPath:(FPath *)path; +- (void)setQueryActive:(FQuerySpec *)query; +- (void)setQueryInactive:(FQuerySpec *)query; + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path; +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path; + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy; +- (NSUInteger)numberOfPrunableQueries; +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path; + +// For testing +- (void)verifyCache; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m new file mode 100644 index 0000000..26accaf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m @@ -0,0 +1,375 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQueryManager.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FImmutableTree.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import + +@interface FTrackedQueryManager () + +@property(nonatomic, strong) FImmutableTree *trackedQueryTree; +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id clock; +@property(nonatomic) NSUInteger currentQueryId; + +@end + +@implementation FTrackedQueryManager + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_clock = clock; + self->_trackedQueryTree = [FImmutableTree empty]; + + NSTimeInterval lastUse = [clock currentTime]; + + NSArray *trackedQueries = [self.storageEngine loadTrackedQueries]; + [trackedQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *trackedQuery, NSUInteger idx, + BOOL *stop) { + self.currentQueryId = + MAX(trackedQuery.queryId + 1, self.currentQueryId); + if (trackedQuery.isActive) { + trackedQuery = + [[trackedQuery setActiveState:NO] updateLastUse:lastUse]; + FFDebug( + @"I-RDB081001", + @"Setting active query %lu from previous app start inactive", + (unsigned long)trackedQuery.queryId); + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + [self cacheTrackedQuery:trackedQuery]; + }]; + } + return self; +} + ++ (void)assertValidTrackedQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData || query.isDefault, + @"Can't have tracked non-default query that loads all data"); +} + ++ (FQuerySpec *)normalizeQuery:(FQuerySpec *)query { + return query.loadsAllData ? [FQuerySpec defaultQueryAtPath:query.path] + : query; +} + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + NSDictionary *set = [self.trackedQueryTree valueAtPath:query.path]; + return set[query.params]; +} + +- (void)removeTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + NSAssert(trackedQuery, @"Tracked query must exist to be removed!"); + + [self.storageEngine removeTrackedQuery:trackedQuery.queryId]; + NSMutableDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + [trackedQueries removeObjectForKey:query.params]; +} + +- (void)setQueryActive:(FQuerySpec *)query { + [self setQueryActive:YES forQuery:query]; +} + +- (void)setQueryInactive:(FQuerySpec *)query { + [self setQueryActive:NO forQuery:query]; +} + +- (void)setQueryActive:(BOOL)isActive forQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + + // Regardless of whether it's now active or no langer active, we update the + // lastUse time + NSTimeInterval lastUse = [self.clock currentTime]; + if (trackedQuery != nil) { + trackedQuery = + [[trackedQuery updateLastUse:lastUse] setActiveState:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } else { + NSAssert(isActive, @"If we're setting the query to inactive, we should " + @"already be tracking it!"); + trackedQuery = [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:lastUse + isActive:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + + [self cacheTrackedQuery:trackedQuery]; +} + +- (void)setQueryComplete:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (!trackedQuery) { + // We might have removed a query and pruned it before we got the + // complete message from the server... + FFWarn(@"I-RDB081002", + @"Trying to set a query complete that is not tracked!"); + } else if (!trackedQuery.isComplete) { + trackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } else { + // Nothing to do, already marked complete + } +} + +- (void)setQueriesCompleteAtPath:(FPath *)path { + [[self.trackedQueryTree subtreeAtPath:path] + forEach:^(FPath *childPath, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *parms, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isComplete) { + FTrackedQuery *newTrackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:newTrackedQuery]; + [self cacheTrackedQuery:newTrackedQuery]; + } + }]; + }]; +} + +- (BOOL)isQueryComplete:(FQuerySpec *)query { + if ([self isIncludedInDefaultCompleteQuery:query]) { + return YES; + } else if (query.loadsAllData) { + // We didn't find a default complete query, so must not be complete. + return NO; + } else { + NSDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + return [trackedQueries[query.params] isComplete]; + } +} + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path { + return [self.trackedQueryTree + rootMostValueOnPath:path + matching:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isActive]; + }] != nil; +} + +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path { + FQuerySpec *query = [FQuerySpec defaultQueryAtPath:path]; + if (![self isIncludedInDefaultCompleteQuery:query]) { + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (trackedQuery == nil) { + trackedQuery = + [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:[self.clock currentTime] + isActive:NO + isComplete:YES]; + } else { + NSAssert(!trackedQuery.isComplete, + @"This should have been handled above!"); + trackedQuery = [trackedQuery setComplete]; + } + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } +} + +- (BOOL)isIncludedInDefaultCompleteQuery:(FQuerySpec *)query { + return + [self.trackedQueryTree + findRootMostMatchingPath:query.path + predicate:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isComplete]; + }] != nil; +} + +- (void)cacheTrackedQuery:(FTrackedQuery *)query { + [FTrackedQueryManager assertValidTrackedQuery:query.query]; + NSMutableDictionary *trackedDict = + [self.trackedQueryTree valueAtPath:query.query.path]; + if (trackedDict == nil) { + trackedDict = [NSMutableDictionary dictionary]; + self.trackedQueryTree = + [self.trackedQueryTree setValue:trackedDict + atPath:query.query.path]; + } + trackedDict[query.query.params] = query; +} + +- (NSUInteger)numberOfQueriesToPrune:(id)cachePolicy + prunableCount:(NSUInteger)numPrunable { + NSUInteger numPercent = (NSUInteger)ceilf( + numPrunable * [cachePolicy percentOfQueriesToPruneAtOnce]); + NSUInteger maxToKeep = [cachePolicy maxNumberOfQueriesToKeep]; + NSUInteger numMax = (numPrunable > maxToKeep) ? numPrunable - maxToKeep : 0; + // Make sure we get below number of max queries to prune + return MAX(numMax, numPercent); +} + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy { + NSMutableArray *pruneableQueries = [NSMutableArray array]; + NSMutableArray *unpruneableQueries = [NSMutableArray array]; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + [pruneableQueries addObject:trackedQuery]; + } else { + [unpruneableQueries addObject:trackedQuery]; + } + }]; + }]; + [pruneableQueries sortUsingComparator:^NSComparisonResult( + FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.lastUse < q2.lastUse) { + return NSOrderedAscending; + } else if (q1.lastUse > q2.lastUse) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + + __block FPruneForest *pruneForest = [FPruneForest empty]; + NSUInteger numToPrune = + [self numberOfQueriesToPrune:cachePolicy + prunableCount:pruneableQueries.count]; + + // TODO: do in transaction + for (NSUInteger i = 0; i < numToPrune; i++) { + FTrackedQuery *toPrune = pruneableQueries[i]; + pruneForest = [pruneForest prunePath:toPrune.query.path]; + [self removeTrackedQuery:toPrune.query]; + } + + // Keep the rest of the prunable queries + for (NSUInteger i = numToPrune; i < pruneableQueries.count; i++) { + FTrackedQuery *toKeep = pruneableQueries[i]; + pruneForest = [pruneForest keepPath:toKeep.query.path]; + } + + // Also keep unprunable queries + [unpruneableQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *toKeep, NSUInteger idx, BOOL *stop) { + pruneForest = [pruneForest keepPath:toKeep.query.path]; + }]; + + return pruneForest; +} + +- (NSUInteger)numberOfPrunableQueries { + __block NSUInteger count = 0; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + count++; + } + }]; + }]; + return count; +} + +- (NSSet *)filteredQueryIdsAtPath:(FPath *)path { + NSDictionary *queries = [self.trackedQueryTree valueAtPath:path]; + if (queries) { + NSMutableSet *ids = [NSMutableSet set]; + [queries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *query, BOOL *stop) { + if (!query.query.loadsAllData) { + [ids addObject:@(query.queryId)]; + } + }]; + return ids; + } else { + return [NSSet set]; + } +} + +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path { + NSAssert(![self isQueryComplete:[FQuerySpec defaultQueryAtPath:path]], + @"Path is fully complete"); + + NSMutableSet *completeChildren = [NSMutableSet set]; + // First, get complete children from any queries at this location. + NSSet *queryIds = [self filteredQueryIdsAtPath:path]; + [queryIds enumerateObjectsUsingBlock:^(NSNumber *queryId, BOOL *stop) { + NSSet *keys = [self.storageEngine + trackedQueryKeysForQuery:[queryId unsignedIntegerValue]]; + [completeChildren unionSet:keys]; + }]; + + // Second, get any complete default queries immediately below us. + [[[self.trackedQueryTree subtreeAtPath:path] children] + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childTree.value[[FQueryParams defaultInstance]] isComplete]) { + [completeChildren addObject:childKey]; + } + }]; + + return completeChildren; +} + +- (void)verifyCache { + NSArray *storedTrackedQueries = [self.storageEngine loadTrackedQueries]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + + [self.trackedQueryTree forEach:^(FPath *path, NSDictionary *queryDict) { + [trackedQueries addObjectsFromArray:queryDict.allValues]; + }]; + NSComparator comparator = + ^NSComparisonResult(FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.queryId < q2.queryId) { + return NSOrderedAscending; + } else if (q1.queryId > q2.queryId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }; + [trackedQueries sortUsingComparator:comparator]; + storedTrackedQueries = + [storedTrackedQueries sortedArrayUsingComparator:comparator]; + + if (![trackedQueries isEqualToArray:storedTrackedQueries]) { + [NSException + raise:NSInternalInconsistencyException + format:@"Tracked queries and queries stored on disk don't match"]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h new file mode 100644 index 0000000..3aecd81 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FIRDataEventType_h +#define Firebase_FIRDataEventType_h + +#import + +/** + * This enum is the set of events that you can observe at a Firebase Database + * location. + */ +typedef NS_ENUM(NSInteger, FIRDataEventType) { + /// A new child node is added to a location. + FIRDataEventTypeChildAdded, + /// A child node is removed from a location. + FIRDataEventTypeChildRemoved, + /// A child node at a location changes. + FIRDataEventTypeChildChanged, + /// A child node moves relative to the other child nodes at a location. + FIRDataEventTypeChildMoved, + /// Any data changes at a location or, recursively, at any child node. + FIRDataEventTypeValue +} NS_SWIFT_NAME(DataEventType); + +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h new file mode 100644 index 0000000..e88febb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h @@ -0,0 +1,142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabaseReference; + +/** + * A FIRDataSnapshot contains data from a Firebase Database location. Any time + * you read Firebase data, you receive the data as a FIRDataSnapshot. + * + * FIRDataSnapshots are passed to the blocks you attach with + * observeEventType:withBlock: or observeSingleEvent:withBlock:. They are + * efficiently-generated immutable copies of the data at a Firebase Database + * location. They can't be modified and will never change. To modify data at a + * location, use a FIRDatabaseReference (e.g. with setValue:). + */ +NS_SWIFT_NAME(DataSnapshot) +@interface FIRDataSnapshot : NSObject + +#pragma mark - Navigating and inspecting a snapshot + +/** + * Gets a FIRDataSnapshot for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') + * or a deeper slash-separated path (e.g. 'fred/name/first'). If the child + * location has no data, an empty FIRDataSnapshot is returned. + * + * @param childPathString A relative path to the location of child data. + * @return The FIRDataSnapshot for the child location. + */ +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString; + +/** + * Return YES if the specified child exists. + * + * @param childPathString A relative path to the location of a potential child. + * @return YES if data exists at the specified childPathString, else NO. + */ +- (BOOL)hasChild:(NSString *)childPathString; + +/** + * Return YES if the DataSnapshot has any children. + * + * @return YES if this snapshot has any children, else NO. + */ +- (BOOL)hasChildren; + +/** + * Return YES if the DataSnapshot contains a non-null value. + * + * @return YES if this snapshot contains a non-null value, else NO. + */ +- (BOOL)exists; + +#pragma mark - Data export + +/** + * Returns the raw value at this location, coupled with any metadata, such as + * priority. + * + * Priorities, where they exist, are accessible under the ".priority" key in + * instances of NSDictionary. For leaf locations with priorities, the value will + * be under the ".value" key. + */ +- (id __nullable)valueInExportFormat; + +#pragma mark - Properties + +/** + * Returns the contents of this data snapshot as native types. + * + * Data types returned: + * + NSDictionary + * + NSArray + * + NSNumber (also includes booleans) + * + NSString + * + * @return The data as a native object. + */ +@property(strong, readonly, nonatomic, nullable) id value; + +/** + * Gets the number of children for this DataSnapshot. + * + * @return An integer indicating the number of children. + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Gets a FIRDatabaseReference for the location that this data came from. + * + * @return A FIRDatabaseReference instance for the location of this data. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +/** + * The key of the location that generated this FIRDataSnapshot. + * + * @return An NSString containing the key for the location of this + * FIRDataSnapshot. + */ +@property(strong, readonly, nonatomic) NSString *key; + +/** + * An iterator for snapshots of the child nodes in this snapshot. + * You can use the native for..in syntax: + * + * for (FIRDataSnapshot* child in snapshot.children) { + * ... + * } + * + * @return An NSEnumerator of the children. + */ +@property(strong, readonly, nonatomic) + NSEnumerator *children; + +/** + * The priority of the data in this FIRDataSnapshot. + * + * @return The priority as a string, or nil if no priority was set. + */ +@property(strong, readonly, nonatomic, nullable) id priority; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h new file mode 100644 index 0000000..02af8c7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h @@ -0,0 +1,182 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The entry point for accessing a Firebase Database. You can get an instance + * by calling [FIRDatabase database]. To access a location in the database and + * read or write data, use [FIRDatabase reference]. + */ +NS_SWIFT_NAME(Database) +@interface FIRDatabase : NSObject + +/** + * The NSObject initializer that has been marked as unavailable. Use the + * `database` method instead + * + * @return An instancetype instance + */ +- (instancetype)init + __attribute__((unavailable("use the database method instead"))); + +/** + * Gets the instance of FIRDatabase for the default FIRApp. + * + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)database NS_SWIFT_NAME(database()); + +/** + * Gets a FirebaseDatabase instance for the specified URL. + * + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseWithURL:(NSString *)url NS_SWIFT_NAME(database(url:)); + +/** + * Gets a FirebaseDatabase instance for the specified URL, using the specified + * FirebaseApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ +// clang-format off ++ (FIRDatabase *)databaseForApp:(FIRApp *)app + URL:(NSString *)url NS_SWIFT_NAME(database(app:url:)); +// clang-format on + +/** + * Gets an instance of FIRDatabase for a specific FIRApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseForApp:(FIRApp *)app NS_SWIFT_NAME(database(app:)); + +/** The FIRApp instance to which this FIRDatabase belongs. */ +@property(weak, readonly, nonatomic) FIRApp *app; + +/** + * Gets a FIRDatabaseReference for the root of your Firebase Database. + */ +- (FIRDatabaseReference *)reference; + +/** + * Gets a FIRDatabaseReference for the provided path. + * + * @param path Path to a location in your Firebase Database. + * @return A FIRDatabaseReference pointing to the specified path. + */ +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path; + +/** + * Gets a FIRDatabaseReference for the provided URL. The URL must be a URL to a + * path within this Firebase Database. To create a FIRDatabaseReference to a + * different database, create a FIRApp} with a FIROptions object configured with + * the appropriate database URL. + * + * @param databaseUrl A URL to a path within your database. + * @return A FIRDatabaseReference for the provided URL. + */ +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl; + +/** + * The Firebase Database client automatically queues writes and sends them to + * the server at the earliest opportunity, depending on network connectivity. In + * some cases (e.g. offline usage) there may be a large number of writes waiting + * to be sent. Calling this method will purge all outstanding writes so they are + * abandoned. + * + * All writes will be purged, including transactions and onDisconnect writes. + * The writes will be rolled back locally, perhaps triggering events for + * affected event listeners, and the client will not (re-)send them to the + * Firebase Database backend. + */ +- (void)purgeOutstandingWrites; + +/** + * Shuts down our connection to the Firebase Database backend until goOnline is + * called. + */ +- (void)goOffline; + +/** + * Resumes our connection to the Firebase Database backend after a previous + * goOffline call. + */ +- (void)goOnline; + +/** + * The Firebase Database client will cache synchronized data and keep track of + * all writes you've initiated while your application is running. It seamlessly + * handles intermittent network connections and re-sends write operations when + * the network connection is restored. + * + * However by default your write operations and cached data are only stored + * in-memory and will be lost when your app restarts. By setting this value to + * `YES`, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first Database reference and only needs to be called once per + * application. + * + */ +@property(nonatomic) BOOL persistenceEnabled NS_SWIFT_NAME(isPersistenceEnabled) + ; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. Cache sizes smaller than 1 MB or + * greater than 100 MB are not supported. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + * + * Note that this must be set before creating your first Database reference. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +/** + * Enables verbose diagnostic logging. + * + * @param enabled YES to enable logging, NO to disable. + */ ++ (void)setLoggingEnabled:(BOOL)enabled; + +/** Retrieve the Firebase Database SDK version. */ ++ (NSString *)sdkVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h new file mode 100644 index 0000000..82057aa --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h @@ -0,0 +1,395 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRDatabaseHandle is used to identify listeners of Firebase Database + * events. These handles are returned by observeEventType: and can later be + * passed to removeObserverWithHandle: to stop receiving updates. + */ +typedef NSUInteger FIRDatabaseHandle NS_SWIFT_NAME(DatabaseHandle); + +/** + * A FIRDatabaseQuery instance represents a query over the data at a particular + * location. + * + * You create one by calling one of the query methods (queryOrderedByChild:, + * queryStartingAtValue:, etc.) on a FIRDatabaseReference. The query methods can + * be chained to further specify the data you are interested in observing + */ +NS_SWIFT_NAME(DatabaseQuery) +@interface FIRDatabaseQuery : NSObject + +#pragma mark - Attach observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * Detach all blocks previously attached to this Firebase Database location with + * observeEventType:withBlock: + */ +- (void)removeAllObservers; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByValue: is used to generate a reference to a view of the data + * that's been sorted by child value. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child value. + */ +- (FIRDatabaseQuery *)queryOrderedByValue; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. This is most useful when implementing pagination in a + * case where multiple nodes can match the startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. This is most useful when implementing pagination in a case where + * multiple nodes can match the endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument and with their key equal to childKey. There will be + * at most one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The name of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the location of this query. + * + * @return A FIRDatabaseReference for the location of this query. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h new file mode 100644 index 0000000..c80b2f8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h @@ -0,0 +1,861 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabase; + +/** + * A FIRDatabaseReference represents a particular location in your Firebase + * Database and can be used for reading or writing data to that Firebase + * Database location. + * + * This class is the starting point for all Firebase Database operations. After + * you've obtained your first FIRDatabaseReference via [FIRDatabase reference], + * you can use it to read data (ie. observeEventType:withBlock:), write data + * (ie. setValue:), and to create new FIRDatabaseReferences (ie. child:). + */ +NS_SWIFT_NAME(DatabaseReference) +@interface FIRDatabaseReference : FIRDatabaseQuery + +#pragma mark - Getting references to children locations + +/** + * Gets a FIRDatabaseReference for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') or a + * deeper slash-separated path (e.g. 'fred/name/first'). + * + * @param pathString A relative path from this location to the desired child + * location. + * @return A FIRDatabaseReference for the specified relative path. + */ +- (FIRDatabaseReference *)child:(NSString *)pathString; + +/** + * childByAutoId generates a new child location using a unique key and returns a + * FIRDatabaseReference to it. This is useful when the children of a Firebase + * Database location represent a list of items. + * + * The unique key generated by childByAutoId: is prefixed with a + * client-generated timestamp so that the resulting list will be + * chronologically-sorted. + * + * @return A FIRDatabaseReference for the generated location. + */ +- (FIRDatabaseReference *)childByAutoId; + +#pragma mark - Writing data + +/** Write data to this Firebase Database location. + +This will overwrite any data at this location and all child locations. + +Data types that can be set are: + +- NSString -- @"Hello World" +- NSNumber (also includes boolean) -- @YES, @43, @4.333 +- NSDictionary -- @{@"key": @"value", @"nested": @{@"another": @"value"} } +- NSArray + +The effect of the write will be visible immediately and the corresponding +events will be triggered. Synchronization of the data to the Firebase Database +servers will also be started. + +Passing null for the new value is equivalent to calling remove:; +all data at this location or any child location will be deleted. + +Note that setValue: will remove any priority stored at this location, so if +priority is meant to be preserved, you should use setValue:andPriority: instead. + +@param value The value to be written. + */ +- (void)setValue:(nullable id)value; + +/** + * The same as setValue: with a block that gets triggered after the write + * operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * The same as setValue: with an additional priority to be attached to the data + * being written. Priorities are used to order items. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + */ +- (void)setValue:(nullable id)value andPriority:(nullable id)priority; + +/** + * The same as setValue:andPriority: with a block that gets triggered after the + * write operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Remove the data at this Firebase Database location. Any data at child + * locations will also be deleted. + * + * The effect of the delete will be visible immediately and the corresponding + * events will be triggered. Synchronization of the delete to the Firebase + * Database servers will also be started. + * + * remove: is equivalent to calling setValue:nil + */ +- (void)removeValue; + +/** + * The same as remove: with a block that gets triggered after the remove + * operation has been committed to the Firebase Database servers. + * + * @param block The block to be called after the remove has been committed to + * the Firebase Database servers. + */ +- (void)removeValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Sets a priority for the data at this Firebase Database location. + * Priorities can be used to provide a custom ordering for the children at a + * location (if no priorities are specified, the children are ordered by key). + * + * You cannot set a priority on an empty location. For this reason + * setValue:andPriority: should be used when setting initial data with a + * specific priority and setPriority: should be used when updating the priority + * of existing data. + * + * Children are sorted based on this priority using the following rules: + * + * Children with no priority come first. + * Children with a number as their priority come next. They are sorted + * numerically by priority (small to large). Children with a string as their + * priority come last. They are sorted lexicographically by priority. Whenever + * two children have the same priority (including no priority), they are sorted + * by key. Numeric keys come first (sorted numerically), followed by the + * remaining keys (sorted lexicographically). + * + * Note that priorities are parsed and ordered as IEEE 754 double-precision + * floating-point numbers. Keys are always stored as strings and are treated as + * numbers only when they can be parsed as a 32-bit integer + * + * @param priority The priority to set at the specified location. + */ +- (void)setPriority:(nullable id)priority; + +/** + * The same as setPriority: with a block that is called once the priority has + * been committed to the Firebase Database servers. + * + * @param priority The priority to set at the specified location. + * @param block The block that is triggered after the priority has been written + * on the servers. + */ +- (void)setPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Updates the values at the specified paths in the dictionary without + * overwriting other keys at this location. + * + * @param values A dictionary of the keys to change and their new values + */ +- (void)updateChildValues:(NSDictionary *)values; + +/** + * The same as update: with a block that is called once the update has been + * committed to the Firebase Database servers + * + * @param values A dictionary of the keys to change and their new values + * @param block The block that is triggered after the update has been written on + * the Firebase Database servers + */ +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +#pragma mark - Attaching observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +/** + * Removes all observers at the current reference, but does not remove any + * observers at child references. removeAllObservers must be called again for + * each child reference where a listener was established to remove the + * observers. + */ +- (void)removeAllObservers; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument with a key equal to childKey. There will be at most + * one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The key of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Managing presence + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * onDisconnectSetValue: is especially useful for implementing "presence" + * systems, where a value should be changed or cleared when a user disconnects + * so that he appears "offline" to other users. + * + * @param value The value to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value; + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value andPriority:(id)priority; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValue is especially useful for implementing "presence" + * systems. + */ +- (void)onDisconnectRemoveValue; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValueWithCompletionBlock: is especially useful for + * implementing "presence" systems. + * + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectRemoveValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + * @param block A block that will be called once the operation has been queued + * up on the Firebase Database servers + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + */ +- (void)cancelDisconnectOperations; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + * + * @param block A block that will be triggered once the Firebase Database + * servers have acknowledged the cancel request. + */ +- (void)cancelDisconnectOperationsWithCompletionBlock: + (nullable void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +#pragma mark - Manual Connection Management + +/** + * Manually disconnect the Firebase Database client from the server and disable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * While offline, the Firebase Database client will no longer receive data + * updates from the server. However, all database operations performed locally + * will continue to immediately fire events, allowing your application to + * continue behaving normally. Additionally, each operation performed locally + * will automatically be queued and retried upon reconnection to the Firebase + * Database server. + * + * To reconnect to the Firebase Database server and begin receiving remote + * events, see goOnline( ). Once the connection is reestablished, the Firebase + * Database client will transmit the appropriate data and fire the appropriate + * events so that your client "catches up" automatically. + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOffline; + +/** + * Manually reestablish a connection to the Firebase Database server and enable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * This method should be used after invoking goOffline( ) to disable the active + * connection. Once reconnected, the Firebase Database client will automatically + * transmit the proper data and fire the appropriate events so that your client + * "catches up" automatically. + * + * To disconnect from the Firebase Database server, see goOffline( ). + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOnline; + +#pragma mark - Transactions + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot))completionBlock; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by return + * [FIRTransactionResult abort]. + * + * Since your block may be run multiple times, this client could see several + * immediate states that don't exist on the server. You can suppress those + * immediate states until the server confirms the final state of the + * transaction. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + * @param localEvents Set this to NO to suppress events raised for intermediate + * states, and only get events based on the final state of the transaction. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (nullable void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot)) + completionBlock + withLocalEvents:(BOOL)localEvents; + +#pragma mark - Retrieving String Representation + +/** + * Gets the absolute URL of this Firebase Database location. + * + * @return The absolute URL of the referenced Firebase Database location. + */ +- (NSString *)description; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the parent location. + * If this instance refers to the root of your Firebase Database, it has no + * parent, and therefore parent( ) will return null. + * + * @return A FIRDatabaseReference for the parent location. + */ +@property(strong, readonly, nonatomic, nullable) FIRDatabaseReference *parent; + +/** + * Gets a FIRDatabaseReference for the root location + * + * @return A new FIRDatabaseReference to root location. + */ +@property(strong, readonly, nonatomic) FIRDatabaseReference *root; + +/** + * Gets the last token in a Firebase Database location (e.g. 'fred' in + * https://SampleChat.firebaseIO-demo.com/users/fred) + * + * @return The key of the location this reference points to. + */ +@property(strong, readonly, nonatomic, nullable) NSString *key; + +/** + * Gets the URL for the Firebase Database location referenced by this + * FIRDatabaseReference. + * + * @return The url of the location this reference points to. + */ +@property(strong, readonly, nonatomic) NSString *URL; + +/** + * Gets the FIRDatabase instance associated with this reference. + * + * @return The FIRDatabase object for this reference. + */ +@property(strong, readonly, nonatomic) FIRDatabase *database; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h new file mode 100644 index 0000000..9797a67 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h @@ -0,0 +1,128 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRMutableData instance is populated with data from a Firebase Database + * location. When you are using runTransactionBlock:, you will be given an + * instance containing the current data at that location. Your block will be + * responsible for updating that instance to the data you wish to save at that + * location, and then returning using [FIRTransactionResult successWithValue:]. + * + * To modify the data, set its value property to any of the native types support + * by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that changes made to a child FIRMutableData instance will be visible to + * the parent. + */ +NS_SWIFT_NAME(MutableData) +@interface FIRMutableData : NSObject + +#pragma mark - Inspecting and navigating the data + +/** + * Returns boolean indicating whether this mutable data has children. + * + * @return YES if this data contains child nodes. + */ +- (BOOL)hasChildren; + +/** + * Indicates whether this mutable data has a child at the given path. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return YES if this data contains a child at the specified relative path + */ +- (BOOL)hasChildAtPath:(NSString *)path; + +/** + * Used to obtain a FIRMutableData instance that encapsulates the data at the + * given relative path. Note that changes made to the child will be visible to + * the parent. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return A FIRMutableData instance containing the data at the given path + */ +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path; + +#pragma mark - Properties + +/** + * To modify the data contained by this instance of FIRMutableData, set this to + * any of the native types supported by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that setting this value will override the priority at this location. + * + * @return The current data at this location as a native object + */ +@property(strong, nonatomic, nullable) id value; + +/** + * Set this property to update the priority of the data at this location. Can be + * set to the following types: + * + * + NSNumber + * + NSString + * + nil / NSNull to remove the priority + * + * @return The priority of the data at this location + */ +@property(strong, nonatomic, nullable) id priority; + +/** + * @return The number of child nodes at this location + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Used to iterate over the children at this location. You can use the native + * for .. in syntax: + * + * for (FIRMutableData* child in data.children) { + * ... + * } + * + * Note that this enumerator operates on an immutable copy of the child list. + * So, you can modify the instance during iteration, but the new additions will + * not be visible until you get a new enumerator. + */ +@property(readonly, nonatomic, strong) NSEnumerator *children; + +/** + * @return The key name of this node, or nil if it is the top-most location + */ +@property(readonly, nonatomic, strong, nullable) NSString *key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h new file mode 100644 index 0000000..8fca5e0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Placeholder values you may write into Firebase Database as a value or + * priority that will automatically be populated by the Firebase Database + * server. + */ +NS_SWIFT_NAME(ServerValue) +@interface FIRServerValue : NSObject + +/** + * Placeholder value for the number of milliseconds since the Unix epoch + */ ++ (NSDictionary *)timestamp; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h new file mode 100644 index 0000000..7f5ccc1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Used for runTransactionBlock:. An FIRTransactionResult instance is a + * container for the results of the transaction. + */ +NS_SWIFT_NAME(TransactionResult) +@interface FIRTransactionResult : NSObject + +/** + * Used for runTransactionBlock:. Indicates that the new value should be saved + * at this location + * + * @param value A FIRMutableData instance containing the new value to be set + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value; + +/** + * Used for runTransactionBlock:. Indicates that the current transaction should + * no longer proceed. + * + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)abort; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h new file mode 100644 index 0000000..ae6b933 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FirebaseDatabase_h +#define FirebaseDatabase_h + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +#endif /* FirebaseDatabase_h */ diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h new file mode 100644 index 0000000..7198615 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import "FWebSocketConnection.h" +#import + +@protocol FConnectionDelegate; + +@interface FConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive; + +// FWebSocketDelegate delegate methods +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end + +typedef enum { + DISCONNECT_REASON_SERVER_RESET = 0, + DISCONNECT_REASON_OTHER = 1 +} FDisconnectReason; + +@protocol FConnectionDelegate + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m new file mode 100644 index 0000000..a33ebd7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m @@ -0,0 +1,234 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FConstants.h" +#import + +typedef enum { + REALTIME_STATE_CONNECTING = 0, + REALTIME_STATE_CONNECTED = 1, + REALTIME_STATE_DISCONNECTED = 2, +} FConnectionState; + +@interface FConnection () { + FConnectionState state; +} + +@property(nonatomic, strong) FWebSocketConnection *conn; +@property(nonatomic, strong) FRepoInfo *repoInfo; + +@end + +#pragma mark - +#pragma mark FConnection implementation + +@implementation FConnection + +@synthesize delegate; +@synthesize conn; +@synthesize repoInfo; + +#pragma mark - +#pragma mark Initializers + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + state = REALTIME_STATE_CONNECTING; + self.repoInfo = aRepoInfo; + self.conn = [[FWebSocketConnection alloc] initWith:self.repoInfo + andQueue:queue + lastSessionID:lastSessionID]; + self.conn.delegate = self; + } + return self; +} + +#pragma mark - +#pragma mark Public method implementation + +- (void)open { + FFLog(@"I-RDB082001", @"Calling open in FConnection"); + [self.conn open]; +} + +- (void)closeWithReason:(FDisconnectReason)reason { + if (state != REALTIME_STATE_DISCONNECTED) { + FFLog(@"I-RDB082002", @"Closing realtime connection."); + state = REALTIME_STATE_DISCONNECTED; + + if (self.conn) { + FFLog(@"I-RDB082003", @"Calling close again."); + [self.conn close]; + self.conn = nil; + } + + [self.delegate onDisconnect:self withReason:reason]; + } +} + +- (void)close { + [self closeWithReason:DISCONNECT_REASON_OTHER]; +} + +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive { + // since this came from the persistent connection, wrap it in a data message + // envelope + NSDictionary *msg = @{ + kFWPRequestType : kFWPRequestTypeData, + kFWPRequestDataPayload : dataMsg + }; + [self sendData:msg sensitive:sensitive]; +} + +#pragma mark - +#pragma mark Helpers + +- (void)sendData:(NSDictionary *)data sensitive:(BOOL)sensitive { + if (state != REALTIME_STATE_CONNECTED) { + @throw [[NSException alloc] + initWithName:@"InvalidConnectionState" + reason:@"Tried to send data on an unconnected FConnection" + userInfo:nil]; + } else { + if (sensitive) { + FFLog(@"I-RDB082004", @"Sending data (contents hidden)"); + } else { + FFLog(@"I-RDB082005", @"Sending: %@", data); + } + [self.conn send:data]; + } +} + +#pragma mark - +#pragma mark FWebSocketConnectinDelegate implementation + +// Corresponds to onConnectionLost in JS +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected { + + self.conn = nil; + if (!everConnected && state == REALTIME_STATE_CONNECTING) { + FFLog(@"I-RDB082006", @"Realtime connection failed."); + + // Since we failed to connect at all, clear any cached entry for this + // namespace in case the machine went away + [self.repoInfo clearInternalHostCache]; + } else if (state == REALTIME_STATE_CONNECTED) { + FFLog(@"I-RDB082007", @"Realtime connection lost."); + } + + [self close]; +} + +// Corresponds to onMessageReceived in JS +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message { + NSString *rawMessageType = + [message objectForKey:kFWPAsyncServerEnvelopeType]; + if (rawMessageType != nil) { + if ([rawMessageType isEqualToString:kFWPAsyncServerDataMessage]) { + [self onDataMessage:[message + objectForKey:kFWPAsyncServerEnvelopeData]]; + } else if ([rawMessageType + isEqualToString:kFWPAsyncServerControlMessage]) { + [self onControl:[message objectForKey:kFWPAsyncServerEnvelopeData]]; + } else { + FFLog(@"I-RDB082008", @"Unrecognized server packet type: %@", + rawMessageType); + } + } else { + FFLog(@"I-RDB082009", @"Unrecognized raw server packet received: %@", + message); + } +} + +- (void)onDataMessage:(NSDictionary *)message { + // we don't do anything with data messages, just kick them up a level + FFLog(@"I-RDB082010", @"Got data message: %@", message); + [self.delegate onDataMessage:self withMessage:message]; +} + +- (void)onControl:(NSDictionary *)message { + FFLog(@"I-RDB082011", @"Got control message: %@", message); + NSString *type = [message objectForKey:kFWPAsyncServerControlMessageType]; + if ([type isEqualToString:kFWPAsyncServerControlMessageShutdown]) { + NSString *reason = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onConnectionShutdownWithReason:reason]; + } else if ([type isEqualToString:kFWPAsyncServerControlMessageReset]) { + NSString *host = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onReset:host]; + } else if ([type isEqualToString:kFWPAsyncServerHello]) { + NSDictionary *handshakeData = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onHandshake:handshakeData]; + } else { + FFLog(@"I-RDB082012", + @"Unknown control message returned from server: %@", message); + } +} + +- (void)onConnectionShutdownWithReason:(NSString *)reason { + FFLog(@"I-RDB082013", + @"Connection shutdown command received. Shutting down..."); + + [self.delegate onKill:self withReason:reason]; + [self close]; +} + +- (void)onHandshake:(NSDictionary *)handshake { + NSNumber *timestamp = + [handshake objectForKey:kFWPAsyncServerHelloTimestamp]; + // NSString* version = [handshake + // objectForKey:kFWPAsyncServerHelloVersion]; + NSString *host = [handshake objectForKey:kFWPAsyncServerHelloConnectedHost]; + NSString *sessionID = [handshake objectForKey:kFWPAsyncServerHelloSession]; + + self.repoInfo.internalHost = host; + + if (state == REALTIME_STATE_CONNECTING) { + [self.conn start]; + [self onConnection:self.conn readyAtTime:timestamp sessionID:sessionID]; + } +} + +- (void)onConnection:(FWebSocketConnection *)conn + readyAtTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB082014", @"Realtime connection established"); + state = REALTIME_STATE_CONNECTED; + + [self.delegate onReady:self atTime:timestamp sessionID:sessionID]; +} + +- (void)onReset:(NSString *)host { + FFLog( + @"I-RDB082015", + @"Got a reset; killing connection to: %@; Updating internalHost to: %@", + repoInfo.internalHost, host); + self.repoInfo.internalHost = host; + + // Explicitly close the connection with SERVER_RESET so calling code knows + // to reconnect immediately. + [self closeWithReason:DISCONNECT_REASON_SERVER_RESET]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h new file mode 100644 index 0000000..abb7474 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSRWebSocket.h" +#import "FUtilities.h" +#import + +@protocol FWebSocketDelegate; + +@interface FWebSocketConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)start; +- (void)send:(NSDictionary *)dictionary; + +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean; + +@end + +@protocol FWebSocketDelegate + +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m new file mode 100644 index 0000000..edcae09 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m @@ -0,0 +1,346 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. + +#import + +#import "FConstants.h" +#import "FIRDatabaseReference.h" +#import "FIRDatabase_Private.h" +#import "FStringUtilities.h" +#import "FWebSocketConnection.h" +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FWebSocketConnection () { + NSMutableString *frame; + BOOL everConnected; + BOOL isClosed; + NSTimer *keepAlive; +} + +- (void)shutdown; +- (void)onClosed; +- (void)closeIfNeverConnected; + +@property(nonatomic, strong) FSRWebSocket *webSocket; +@property(nonatomic, strong) NSNumber *connectionId; +@property(nonatomic, readwrite) int totalFrames; +@property(nonatomic, readonly) BOOL buffering; +@property(nonatomic, readonly) NSString *userAgent; +@property(nonatomic) dispatch_queue_t dispatchQueue; + +- (void)nop:(NSTimer *)timer; + +@end + +@implementation FWebSocketConnection + +@synthesize delegate; +@synthesize webSocket; +@synthesize connectionId; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + everConnected = NO; + isClosed = NO; + self.connectionId = [FUtilities LUIDGenerator]; + self.totalFrames = 0; + self.dispatchQueue = queue; + frame = nil; + + NSString *connectionUrl = + [repoInfo connectionURLWithLastSessionID:lastSessionID]; + NSString *ua = [self userAgent]; + FFLog(@"I-RDB083001", @"(wsc:%@) Connecting to: %@ as %@", + self.connectionId, connectionUrl, ua); + + NSURLRequest *req = [[NSURLRequest alloc] + initWithURL:[[NSURL alloc] initWithString:connectionUrl]]; + self.webSocket = [[FSRWebSocket alloc] initWithURLRequest:req + queue:queue + andUserAgent:ua]; + [self.webSocket setDelegateDispatchQueue:queue]; + self.webSocket.delegate = self; + } + return self; +} + +- (NSString *)userAgent { + NSString *systemVersion; + NSString *deviceName; + BOOL hasUiDeviceClass = NO; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + Class uiDeviceClass = NSClassFromString(@"UIDevice"); + if (uiDeviceClass) { + systemVersion = [uiDeviceClass currentDevice].systemVersion; + deviceName = [uiDeviceClass currentDevice].model; + hasUiDeviceClass = YES; + } +#endif + + if (!hasUiDeviceClass) { + NSDictionary *systemVersionDictionary = [NSDictionary + dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + systemVersion = + [systemVersionDictionary objectForKey:@"ProductVersion"]; + deviceName = [systemVersionDictionary objectForKey:@"ProductName"]; + } + + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + + // Sanitize '/'s in deviceName and bundleIdentifier for stats + deviceName = [FStringUtilities sanitizedForUserAgent:deviceName]; + bundleIdentifier = + [FStringUtilities sanitizedForUserAgent:bundleIdentifier]; + + // Firebase/5/__//{device model / + // os (Mac OS X, iPhone, etc.}_ + NSString *ua = [NSString + stringWithFormat:@"Firebase/%@/%@/%@/%@_%@", kWebsocketProtocolVersion, + [FIRDatabase buildVersion], systemVersion, deviceName, + bundleIdentifier]; + return ua; +} + +- (BOOL)buffering { + return frame != nil; +} + +#pragma mark - +#pragma mark Public FWebSocketConnection methods + +- (void)open { + FFLog(@"I-RDB083002", @"(wsc:%@) FWebSocketConnection open.", + self.connectionId); + assert(delegate); + everConnected = NO; + // TODO Assert url + [self.webSocket open]; + dispatch_time_t when = dispatch_time( + DISPATCH_TIME_NOW, kWebsocketConnectTimeout * NSEC_PER_SEC); + dispatch_after(when, self.dispatchQueue, ^{ + [self closeIfNeverConnected]; + }); +} + +- (void)close { + FFLog(@"I-RDB083003", @"(wsc:%@) FWebSocketConnection is being closed.", + self.connectionId); + isClosed = YES; + [self.webSocket close]; +} + +- (void)start { + // Start is a no-op for websockets. +} + +- (void)send:(NSDictionary *)dictionary { + + [self resetKeepAlive]; + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary + options:kNilOptions + error:nil]; + + NSString *data = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + + NSArray *dataSegs = [FUtilities splitString:data + intoMaxSize:kWebsocketMaxFrameSize]; + + // First send the header so the server knows how many segments are + // forthcoming + if (dataSegs.count > 1) { + [self.webSocket + send:[NSString + stringWithFormat:@"%u", (unsigned int)dataSegs.count]]; + } + + // Then, actually send the segments. + for (NSString *segment in dataSegs) { + [self.webSocket send:segment]; + } +} + +- (void)nop:(NSTimer *)timer { + if (!isClosed) { + FFLog(@"I-RDB083004", @"(wsc:%@) nop", self.connectionId); + [self.webSocket send:@"0"]; + } else { + FFLog(@"I-RDB083005", + @"(wsc:%@) No more websocket; invalidating nop timer.", + self.connectionId); + [timer invalidate]; + } +} + +- (void)handleNewFrameCount:(int)numFrames { + self.totalFrames = numFrames; + frame = [[NSMutableString alloc] initWithString:@""]; + FFLog(@"I-RDB083006", @"(wsc:%@) handleNewFrameCount: %d", + self.connectionId, self.totalFrames); +} + +- (NSString *)extractFrameCount:(NSString *)message { + if ([message length] <= 4) { + int frameCount = [message intValue]; + if (frameCount > 0) { + [self handleNewFrameCount:frameCount]; + return nil; + } + } + [self handleNewFrameCount:1]; + return message; +} + +- (void)appendFrame:(NSString *)message { + [frame appendString:message]; + self.totalFrames = self.totalFrames - 1; + + if (self.totalFrames == 0) { + // Call delegate and pass an immutable version of the frame + NSDictionary *json = [NSJSONSerialization + JSONObjectWithData:[frame dataUsingEncoding:NSUTF8StringEncoding] + options:kNilOptions + error:nil]; + frame = nil; + FFLog(@"I-RDB083007", + @"(wsc:%@) handleIncomingFrame sending complete frame: %d", + self.connectionId, self.totalFrames); + + @autoreleasepool { + [self.delegate onMessage:self withMessage:json]; + } + } +} + +- (void)handleIncomingFrame:(NSString *)message { + [self resetKeepAlive]; + if (self.buffering) { + [self appendFrame:message]; + } else { + NSString *remaining = [self extractFrameCount:message]; + if (remaining) { + [self appendFrame:remaining]; + } + } +} + +#pragma mark - +#pragma mark SRWebSocketDelegate implementation +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message { + [self handleIncomingFrame:message]; +} + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket { + FFLog(@"I-RDB083008", @"(wsc:%@) webSocketDidOpen", self.connectionId); + + everConnected = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + self->keepAlive = + [NSTimer scheduledTimerWithTimeInterval:kWebsocketKeepaliveInterval + target:self + selector:@selector(nop:) + userInfo:nil + repeats:YES]; + FFLog(@"I-RDB083009", @"(wsc:%@) nop timer kicked off", + self.connectionId); + }); +} + +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error { + FFLog(@"I-RDB083010", @"(wsc:%@) didFailWithError didFailWithError: %@", + self.connectionId, [error description]); + [self onClosed]; +} + +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean { + FFLog(@"I-RDB083011", @"(wsc:%@) didCloseWithCode: %ld %@", + self.connectionId, (long)code, reason); + [self onClosed]; +} + +#pragma mark - +#pragma mark Private methods + +/** + * Note that the close / onClosed / shutdown cycle here is a little different + * from the javascript client. In order to properly handle deallocation, no + * close-related action is taken at a higher level until we have received + * notification from the websocket itself that it is closed. Otherwise, we end + * up deallocating this class and the FConnection class before the websocket has + * a change to call some of its delegate methods. So, since close is the + * external close handler, we just set a flag saying not to call our own + * delegate method and close the websocket. That will trigger a callback into + * this class that can then do things like clean up the keepalive timer. + */ + +- (void)closeIfNeverConnected { + if (!everConnected) { + FFLog(@"I-RDB083012", @"(wsc:%@) Websocket timed out on connect", + self.connectionId); + [self.webSocket close]; + } +} + +- (void)shutdown { + isClosed = YES; + + // Call delegate methods + [self.delegate onDisconnect:self wasEverConnected:everConnected]; +} + +- (void)onClosed { + if (!isClosed) { + FFLog(@"I-RDB083013", @"Websocket is closing itself"); + [self shutdown]; + } + self.webSocket = nil; + if (keepAlive.isValid) { + [keepAlive invalidate]; + } +} + +- (void)resetKeepAlive { + NSDate *newTime = + [NSDate dateWithTimeIntervalSinceNow:kWebsocketKeepaliveInterval]; + // Calling setFireDate is actually kinda' expensive, so wait at least 5 + // seconds before updating it. + if ([newTime timeIntervalSinceDate:keepAlive.fireDate] > 5) { + FFLog(@"I-RDB083014", @"(wsc:%@) resetting keepalive, to %@ ; old: %@", + self.connectionId, newTime, [keepAlive fireDate]); + [keepAlive setFireDate:newTime]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h new file mode 100644 index 0000000..cc3239e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FNode.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@class FNamedNode; + +@interface FChildrenNode : NSObject + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren; +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren; + +// FChildrenNode specific methods + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +@property(nonatomic, strong) FImmutableSortedDictionary *children; +@property(nonatomic, strong) id priorityNode; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m new file mode 100644 index 0000000..bd02bf8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m @@ -0,0 +1,418 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPriorityIndex.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FTransformedEnumerator.h" +#import "FUtilities.h" + +@interface FChildrenNode () +@property(nonatomic, strong) NSString *lazyHash; +@end + +@implementation FChildrenNode + +// Note: The only reason we allow nil priority is to for EmptyNode, since we +// can't use EmptyNode as the priority of EmptyNode. We might want to consider +// making EmptyNode its own class instead of an empty ChildrenNode. + +- (id)init { + return [self + initWithPriority:nil + children:[FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities + keyComparator]]]; +} + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren { + return [self initWithPriority:nil children:someChildren]; +} + +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren { + if (someChildren.isEmpty && aPriority != nil && ![aPriority isEmpty]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't create empty node with priority!"]; + } + self = [super init]; + if (self) { + self.children = someChildren; + self.priorityNode = aPriority; + } + return self; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return NO; +} + +- (id)getPriority { + if (self.priorityNode) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)updatePriority:(id)aPriority { + if ([self.children isEmpty]) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:aPriority + children:self.children]; + } +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + id child = [self.children objectForKey:childName]; + return (child == nil) ? [FEmptyNode emptyNode] : child; + } +} + +- (id)getChild:(FPath *)path { + NSString *front = [path getFront]; + if (front == nil) { + return self; + } else { + return [[self getImmediateChild:front] getChild:[path popFront]]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return ![self getImmediateChild:childName].isEmpty; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + NSAssert(newChildNode != nil, @"Should always be passing nodes."); + + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else { + FImmutableSortedDictionary *newChildren; + if (newChildNode.isEmpty) { + newChildren = [self.children removeObjectForKey:childName]; + } else { + newChildren = [self.children setObject:newChildNode + forKey:childName]; + } + if (newChildren.isEmpty) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:self.getPriority + children:newChildren]; + } + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + id newImmediateChild = + [[self getImmediateChild:front] updateChild:[path popFront] + withNewChild:newChildNode]; + return [self updateImmediateChild:front withNewChild:newImmediateChild]; + } +} + +- (BOOL)isEmpty { + return [self.children isEmpty]; +} + +- (int)numChildren { + return [self.children count]; +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if ([self isEmpty]) { + return [NSNull null]; + } + + __block int numKeys = 0; + __block NSInteger maxKey = 0; + __block BOOL allIntegerKeys = YES; + + NSMutableDictionary *obj = + [[NSMutableDictionary alloc] initWithCapacity:[self.children count]]; + [self enumerateChildrenUsingBlock:^(NSString *key, id childNode, + BOOL *stop) { + [obj setObject:[childNode valForExport:exp] forKey:key]; + + numKeys++; + + // If we already found a string key, don't bother with any of this + if (!allIntegerKeys) { + return; + } + + // Treat leading zeroes that are not exactly "0" as strings + NSString *firstChar = [key substringWithRange:NSMakeRange(0, 1)]; + if ([firstChar isEqualToString:@"0"] && [key length] > 1) { + allIntegerKeys = NO; + } else { + NSNumber *keyAsNum = [FUtilities intForString:key]; + if (keyAsNum != nil) { + NSInteger keyAsInt = [keyAsNum integerValue]; + if (keyAsInt > maxKey) { + maxKey = keyAsInt; + } + } else { + allIntegerKeys = NO; + } + } + }]; + + if (!exp && allIntegerKeys && maxKey < 2 * numKeys) { + // convert to an array + NSMutableArray *array = + [[NSMutableArray alloc] initWithCapacity:maxKey + 1]; + for (int i = 0; i <= maxKey; ++i) { + NSString *keyString = [NSString stringWithFormat:@"%i", i]; + id child = obj[keyString]; + if (child != nil) { + [array addObject:child]; + } else { + [array addObject:[NSNull null]]; + } + } + return array; + } else { + + if (exp && [self getPriority] != nil && !self.getPriority.isEmpty) { + obj[kPayloadPriority] = [self.getPriority val]; + } + + return obj; + } +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + + if (!self.getPriority.isEmpty) { + [toHash appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:(FLeafNode *) + self.getPriority + toString:toHash + hashVersion:FDataHashVersionV1]; + [toHash appendString:@":"]; + } + + __block BOOL sawPriority = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + sawPriority = sawPriority || [[node getPriority] isEmpty]; + *stop = sawPriority; + }]; + if (sawPriority) { + NSMutableArray *array = [NSMutableArray array]; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + FNamedNode *namedNode = [[FNamedNode alloc] initWithName:key + andNode:node]; + [array addObject:namedNode]; + }]; + [array sortUsingComparator:^NSComparisonResult( + FNamedNode *namedNode1, FNamedNode *namedNode2) { + return + [[FPriorityIndex priorityIndex] compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + [array enumerateObjectsUsingBlock:^(FNamedNode *namedNode, + NSUInteger idx, BOOL *stop) { + NSString *childHash = [namedNode.node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", namedNode.name, childHash]; + } + }]; + } else { + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + NSString *childHash = [node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", key, childHash]; + } + }]; + } + self.lazyHash = [toHash isEqualToString:@""] + ? @"" + : [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + // children nodes come last, unless this is actually an empty node, then we + // come first. + if (self.isEmpty) { + if (other.isEmpty) { + return NSOrderedSame; + } else { + return NSOrderedAscending; + } + } else if (other.isLeafNode || other.isEmpty) { + return NSOrderedDescending; + } else if (other == [FMaxNode maxNode]) { + return NSOrderedAscending; + } else { + // Must be another node with children. + return NSOrderedSame; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other == nil) { + return NO; + } else if (other.isLeafNode) { + return NO; + } else if (self.isEmpty && [other isEmpty]) { + // Empty nodes do not have priority + return YES; + } else { + FChildrenNode *otherChildrenNode = other; + if (![self.getPriority isEqual:other.getPriority]) { + return NO; + } else if (self.children.count == otherChildrenNode.children.count) { + __block BOOL equal = YES; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + id child = [otherChildrenNode getImmediateChild:key]; + if (![child isEqual:node]) { + equal = NO; + *stop = YES; + } + }]; + return equal; + } else { + return NO; + } + } +} + +- (NSUInteger)hash { + __block NSUInteger hashCode = 0; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + hashCode = 31 * hashCode + key.hash; + hashCode = 17 * hashCode + node.hash; + }]; + return 17 * hashCode + self.priorityNode.hash; +} + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + if ([self.getPriority isEmpty]) { + [self enumerateChildrenUsingBlock:block]; + } else { + __block BOOL passedPriorityKey = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (!passedPriorityKey && + [FUtilities compareKey:key + toKey:@".priority"] == NSOrderedDescending) { + passedPriorityKey = YES; + BOOL stopAfterPriority = NO; + block(@".priority", [self getPriority], &stopAfterPriority); + if (stopAfterPriority) + return; + } + block(key, node, stop); + }]; + } +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + [self.children enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self.children enumerateKeysAndObjectsReverse:reverse usingBlock:block]; +} + +- (NSEnumerator *)childEnumerator { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.children.keyEnumerator + andTransform:^id(NSString *key) { + return [FNamedNode nodeWithName:key + node:[self getImmediateChild:key]]; + }]; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return [self.children getPredecessorKey:childKey]; +} + +#pragma mark - +#pragma mark FChildrenNode specific methods + +- (id)childrenGetter:(id)key { + return [self.children objectForKey:key]; +} + +- (FNamedNode *)firstChild { + NSString *childKey = self.children.minKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +- (FNamedNode *)lastChild { + NSString *childKey = self.children.maxKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h new file mode 100644 index 0000000..47de66f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableTree; +@protocol FNode; +@class FPath; + +/** + * This class holds a collection of writes that can be applied to nodes in + * unison. It abstracts away the logic with dealing with priority writes and + * multiple nested writes. At any given path, there is only allowed to be one + * write modifying that path. Any write to an existing path or shadowing an + * existing path will modify that existing write to reflect the write added. + */ +@interface FCompoundWrite : NSObject + +- (id)initWithWriteTree:(FImmutableTree *)tree; + +/** + * Creates a compound write with NSDictionary from path string to object + */ ++ (FCompoundWrite *)compoundWriteWithValueDictionary:(NSDictionary *)dictionary; +/** + * Creates a compound write with NSDictionary from path string to node + */ ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary; + ++ (FCompoundWrite *)emptyWrite; + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path; +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key; +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)node + atPath:(FPath *)path; +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path; +- (id)rootWrite; +- (BOOL)hasCompleteWriteAtPath:(FPath *)path; +- (id)completeNodeAtPath:(FPath *)path; +- (NSArray *)completeChildren; +- (NSDictionary *)childCompoundWrites; +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path; +- (id)applyToNode:(id)node; +- (void)enumerateWrites:(void (^)(FPath *path, id node, + BOOL *stop))block; + +- (NSDictionary *)valForExport:(BOOL)exportFormat; + +- (BOOL)isEmpty; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m new file mode 100644 index 0000000..bc40b2b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundWrite.h" +#import "FImmutableTree.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" + +@interface FCompoundWrite () +@property(nonatomic, strong) FImmutableTree *writeTree; +@end + +@implementation FCompoundWrite + +- (id)initWithWriteTree:(FImmutableTree *)tree { + self = [super init]; + if (self) { + self.writeTree = tree; + } + return self; +} + ++ (FCompoundWrite *)compoundWriteWithValueDictionary: + (NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id value, BOOL *stop) { + id node = [FSnapshotUtilities nodeFrom:value]; + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id node, BOOL *stop) { + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)emptyWrite { + static dispatch_once_t pred = 0; + static FCompoundWrite *empty = nil; + dispatch_once(&pred, ^{ + empty = [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:nil]]; + }); + return empty; +} + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path { + if (path.isEmpty) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:node]]; + } else { + FTuplePathValue *rootMost = + [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path + to:path]; + id value = [rootMost.value updateChild:relativePath + withNewChild:node]; + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree setValue:value + atPath:rootMost.path]]; + } else { + FImmutableTree *subtree = + [[FImmutableTree alloc] initWithValue:node]; + FImmutableTree *newWriteTree = [self.writeTree setTree:subtree + atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } + } +} + +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key { + return [self addWrite:node atPath:[[FPath alloc] initWith:key]]; +} + +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)compoundWrite + atPath:(FPath *)path { + __block FCompoundWrite *newWrite = self; + [compoundWrite.writeTree forEach:^(FPath *childPath, id value) { + newWrite = [newWrite addWrite:value atPath:[path child:childPath]]; + }]; + return newWrite; +} + +/** + * Will remove a write at the given path and deeper paths. This will + * not modify a write at a higher location, which must be removed by + * calling this method with that path. + * @param path The path at which a write and all deeper writes should be + * removed. + * @return The new FWriteCompound with the removed path. + */ +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return [FCompoundWrite emptyWrite]; + } else { + FImmutableTree *newWriteTree = + [self.writeTree setTree:[FImmutableTree empty] atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } +} + +/** + * Returns whether this FCompoundWrite will fully overwrite a node at a given + * location and can therefore be considered "complete". + * @param path The path to check for + * @return Whether there is a complete write at that path. + */ +- (BOOL)hasCompleteWriteAtPath:(FPath *)path { + return [self completeNodeAtPath:path] != nil; +} + +/** + * Returns a node for a path if and only if the node is a "complete" overwrite + * at that path. This will not aggregate writes from depeer paths, but will + * return child nodes from a more shallow path. + * @param path The path to get a complete write + * @return The node if complete at that path, or nil otherwise. + */ +- (id)completeNodeAtPath:(FPath *)path { + FTuplePathValue *rootMost = [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path to:path]; + return [rootMost.value getChild:relativePath]; + } else { + return nil; + } +} + +// TODO: change into traversal method... +- (NSArray *)completeChildren { + NSMutableArray *children = [[NSMutableArray alloc] init]; + if (self.writeTree.value != nil) { + id node = self.writeTree.value; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [children addObject:[[FNamedNode alloc] initWithName:key + andNode:node]]; + }]; + } else { + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value != nil) { + [children addObject:[[FNamedNode alloc] + initWithName:childKey + andNode:childTree.value]]; + } + }]; + } + return children; +} + +// TODO: change into enumarate method +- (NSDictionary *)childCompoundWrites { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *childWrite, BOOL *stop) { + dict[key] = [[FCompoundWrite alloc] initWithWriteTree:childWrite]; + }]; + return dict; +} + +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + id shadowingNode = [self completeNodeAtPath:path]; + if (shadowingNode != nil) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] + initWithValue:shadowingNode]]; + } else { + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree subtreeAtPath:path]]; + } + } +} + +- (id)applySubtreeWrite:(FImmutableTree *)subtreeWrite + atPath:(FPath *)relativePath + toNode:(id)node { + if (subtreeWrite.value != nil) { + // Since a write there is always a leaf, we're done here. + return [node updateChild:relativePath withNewChild:subtreeWrite.value]; + } else { + __block id priorityWrite = nil; + __block id blockNode = node; + [subtreeWrite.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childKey isEqualToString:@".priority"]) { + // Apply priorities at the end so we don't update priorities + // for either empty nodes or forget to apply priorities to + // empty nodes that are later filled. + NSAssert(childTree.value != nil, + @"Priority writes must always be leaf nodes"); + priorityWrite = childTree.value; + } else { + blockNode = [self + applySubtreeWrite:childTree + atPath:[relativePath childFromString:childKey] + toNode:blockNode]; + } + }]; + // If there was a priority write, we only apply it if the node is not + // empty + if (![blockNode getChild:relativePath].isEmpty && + priorityWrite != nil) { + blockNode = [blockNode + updateChild:[relativePath childFromString:@".priority"] + withNewChild:priorityWrite]; + } + return blockNode; + } +} + +- (void)enumerateWrites:(void (^)(FPath *, id, BOOL *))block { + __block BOOL stop = NO; + // TODO: add stop to tree iterator... + [self.writeTree forEach:^(FPath *path, id value) { + if (!stop) { + block(path, value, &stop); + } + }]; +} + +/** + * Applies this FCompoundWrite to a node. The node is returned with all writes + * from this FCompoundWrite applied to the node. + * @param node The node to apply this FCompoundWrite to + * @return The node with all writes applied + */ +- (id)applyToNode:(id)node { + return [self applySubtreeWrite:self.writeTree + atPath:[FPath empty] + toNode:node]; +} + +/** + * Return true if this CompoundWrite is empty and therefore does not modify any + * nodes. + * @return Whether this CompoundWrite is empty + */ +- (BOOL)isEmpty { + return self.writeTree.isEmpty; +} + +- (id)rootWrite { + return self.writeTree.value; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FCompoundWrite class]]) { + return NO; + } + FCompoundWrite *other = (FCompoundWrite *)object; + return + [[self valForExport:YES] isEqualToDictionary:[other valForExport:YES]]; +} + +- (NSUInteger)hash { + return [[self valForExport:YES] hash]; +} + +- (NSDictionary *)valForExport:(BOOL)exportFormat { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + [self.writeTree forEach:^(FPath *path, id value) { + dictionary[path.wireFormat] = [value valForExport:exportFormat]; + }]; + return dictionary; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h new file mode 100644 index 0000000..d002df0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FEmptyNode : NSObject + ++ (id)emptyNode; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m new file mode 100644 index 0000000..bde3a8a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEmptyNode.h" +#import "FChildrenNode.h" + +@implementation FEmptyNode + ++ (id)emptyNode { + static FChildrenNode *empty = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + empty = [[FChildrenNode alloc] init]; + }); + return empty; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h new file mode 100644 index 0000000..b161dea --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" + +/** + * Represents a node together with an index. The index and node are updated in + * unison. In the case where the index does not affect the ordering (i.e. the + * ordering is identical to the key ordering) this class uses a fallback index + * to save memory. Everything operating on the index must special case the + * fallback index. + */ +@interface FIndexedNode : NSObject + +@property(nonatomic, strong, readonly) id node; + ++ (FIndexedNode *)indexedNodeWithNode:(id)node; ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index; + +- (BOOL)hasIndex:(id)index; +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode; +- (FIndexedNode *)updatePriority:(id)priority; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index; + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m new file mode 100644 index 0000000..dafe9c3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m @@ -0,0 +1,218 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedNode.h" + +#import "FChildrenNode.h" +#import "FImmutableSortedSet.h" +#import "FIndex.h" +#import "FKeyIndex.h" +#import "FPriorityIndex.h" + +static FImmutableSortedSet *FALLBACK_INDEX; + +@interface FIndexedNode () + +@property(nonatomic, strong) id node; +/** + * The indexed set is initialized lazily to prevent creation when it is not + * needed + */ +@property(nonatomic, strong) FImmutableSortedSet *indexed; +@property(nonatomic, strong) id index; + +@end + +@implementation FIndexedNode + ++ (FImmutableSortedSet *)fallbackIndex { + static FImmutableSortedSet *fallbackIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + fallbackIndex = [[FImmutableSortedSet alloc] init]; + }); + return fallbackIndex; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node { + return [[FIndexedNode alloc] initWithNode:node + index:[FPriorityIndex priorityIndex]]; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index { + return [[FIndexedNode alloc] initWithNode:node index:index]; +} + +- (id)initWithNode:(id)node index:(id)index { + // Initialize indexed lazily + return [self initWithNode:node index:index indexed:nil]; +} + +- (id)initWithNode:(id)node + index:(id)index + indexed:(FImmutableSortedSet *)indexed { + self = [super init]; + if (self != nil) { + self->_node = node; + self->_index = index; + self->_indexed = indexed; + } + return self; +} + +- (void)ensureIndexed { + if (!self.indexed) { + if ([self.index isEqual:[FKeyIndex keyIndex]]) { + self.indexed = [FIndexedNode fallbackIndex]; + } else { + __block BOOL sawChild = NO; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + sawChild = sawChild || [self.index isDefinedOn:node]; + *stop = sawChild; + }]; + if (sawChild) { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FNamedNode *namedNode = + [[FNamedNode alloc] initWithName:key andNode:node]; + dict[namedNode] = [NSNull null]; + }]; + // Make sure to assign index here, because the comparator will + // be retained and using self will cause a cycle + id index = self.index; + self.indexed = [FImmutableSortedSet + setWithKeysFromDictionary:dict + comparator:^NSComparisonResult( + FNamedNode *namedNode1, + FNamedNode *namedNode2) { + return [index compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + } else { + self.indexed = [FIndexedNode fallbackIndex]; + } + } + } +} + +- (BOOL)hasIndex:(id)index { + return [self.index isEqual:index]; +} + +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode { + id newNode = [self.node updateImmediateChild:key + withNewChild:newChildNode]; + if (self.indexed == [FIndexedNode fallbackIndex] && + ![self.index isDefinedOn:newChildNode]) { + // doesn't affect the index, no need to create an index + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:[FIndexedNode fallbackIndex]]; + } else if (!self.indexed || self.indexed == [FIndexedNode fallbackIndex]) { + // No need to index yet, index lazily + return [[FIndexedNode alloc] initWithNode:newNode index:self.index]; + } else { + id oldChild = [self.node getImmediateChild:key]; + FImmutableSortedSet *newIndexed = [self.indexed + removeObject:[FNamedNode nodeWithName:key node:oldChild]]; + if (![newChildNode isEmpty]) { + newIndexed = [newIndexed + addObject:[FNamedNode nodeWithName:key node:newChildNode]]; + } + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:newIndexed]; + } +} + +- (FIndexedNode *)updatePriority:(id)priority { + return + [[FIndexedNode alloc] initWithNode:[self.node updatePriority:priority] + index:self.index + indexed:self.indexed]; +} + +- (FNamedNode *)firstChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) firstChild]; + } else { + return self.indexed.firstObject; + } + } +} + +- (FNamedNode *)lastChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) lastChild]; + } else { + return self.indexed.lastObject; + } + } +} + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index { + if (![self.index isEqual:index]) { + [NSException raise:NSInvalidArgumentException + format:@"Index not available in IndexedNode!"]; + } + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node predecessorChildKey:childKey]; + } else { + FNamedNode *node = [self.indexed + predecessorEntry:[FNamedNode nodeWithName:childKey node:childNode]]; + return node.name; + } +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + [self.node enumerateChildrenReverse:reverse usingBlock:block]; + } else { + [self.indexed + enumerateObjectsReverse:reverse + usingBlock:^(FNamedNode *namedNode, BOOL *stop) { + block(namedNode.name, namedNode.node, stop); + }]; + } +} + +- (NSEnumerator *)childEnumerator { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node childEnumerator]; + } else { + return [self.indexed objectEnumerator]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h new file mode 100644 index 0000000..6bd2862 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FLeafNode : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue withPriority:(id)aPriority; + +@property(nonatomic, strong) id value; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m new file mode 100644 index 0000000..e741fd9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLeafNode.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FImmutableSortedDictionary.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" + +@interface FLeafNode () +@property(nonatomic, strong) id priorityNode; +@property(nonatomic, strong) NSString *lazyHash; + +@end + +@implementation FLeafNode + +@synthesize value; +@synthesize priorityNode; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.priorityNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)initWithValue:(id)aValue withPriority:(id)aPriority { + self = [super init]; + if (self) { + self.value = aValue; + [FSnapshotUtilities validatePriorityNode:aPriority]; + self.priorityNode = aPriority; + } + return self; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return YES; +} + +- (id)getPriority { + return self.priorityNode; +} + +- (id)updatePriority:(id)aPriority { + return [[FLeafNode alloc] initWithValue:self.value withPriority:aPriority]; +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)getChild:(FPath *)path { + if (path.getFront == nil) { + return self; + } else if ([[path getFront] isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return + [childName isEqualToString:@".priority"] && ![self getPriority].isEmpty; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return nil; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else if (newChildNode.isEmpty) { + return self; + } else { + FChildrenNode *childrenNode = [[FChildrenNode alloc] init]; + childrenNode = [childrenNode updateImmediateChild:childName + withNewChild:newChildNode]; + childrenNode = [childrenNode updatePriority:self.priorityNode]; + return childrenNode; + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else if (newChildNode.isEmpty && ![front isEqualToString:@".priority"]) { + return self; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + return [self updateImmediateChild:front + withNewChild:[[FEmptyNode emptyNode] + updateChild:[path popFront] + withNewChild:newChildNode]]; + } +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if (exp && !self.getPriority.isEmpty) { + return @{ + kPayloadValue : self.value, + kPayloadPriority : [[self getPriority] val] + }; + } else { + return self.value; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other.isLeafNode) { + FLeafNode *otherLeaf = other; + if ([FUtilities getJavascriptType:self.value] != + [FUtilities getJavascriptType:otherLeaf.value]) { + return NO; + } + return [otherLeaf.value isEqual:self.value] && + [otherLeaf.priorityNode isEqual:self.priorityNode]; + } else { + return NO; + } +} + +- (NSUInteger)hash { + return [self.value hash] * 17 + self.priorityNode.hash; +} + +- (id)withIndex:(id)index { + return self; +} + +- (BOOL)isIndexed:(id)index { + return YES; +} + +- (BOOL)isEmpty { + return NO; +} + +- (int)numChildren { + return 0; +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + // Nothing to iterate over +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + // Nothing to iterate over +} + +- (NSEnumerator *)childEnumerator { + // Nothing to iterate over + return [@[] objectEnumerator]; +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:self + toString:toHash + hashVersion:FDataHashVersionV1]; + + self.lazyHash = [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + if (other == [FEmptyNode emptyNode]) { + return NSOrderedDescending; + } else if ([other isKindOfClass:[FChildrenNode class]]) { + return NSOrderedAscending; + } else { + NSAssert(other.isLeafNode, @"Compared against unknown type of node."); + return [self compareToLeafNode:(FLeafNode *)other]; + } +} + ++ (NSArray *)valueTypeOrder { + static NSArray *valueOrder = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueOrder = @[ + kJavaScriptObject, kJavaScriptBoolean, kJavaScriptNumber, + kJavaScriptString + ]; + }); + return valueOrder; +} + +- (NSComparisonResult)compareToLeafNode:(FLeafNode *)other { + NSString *thisLeafType = [FUtilities getJavascriptType:self.value]; + NSString *otherLeafType = [FUtilities getJavascriptType:other.value]; + NSUInteger thisIndex = + [[FLeafNode valueTypeOrder] indexOfObject:thisLeafType]; + NSUInteger otherIndex = + [[FLeafNode valueTypeOrder] indexOfObject:otherLeafType]; + assert(thisIndex >= 0 && otherIndex >= 0); + if (otherIndex == thisIndex) { + // Same type. Compare values. + if (thisLeafType == kJavaScriptObject) { + // Deferred value nodes are all equal, but we should also never get + // to this point... + return NSOrderedSame; + } else if (thisLeafType == kJavaScriptString) { + return [self.value compare:other.value options:NSLiteralSearch]; + } else { + return [self.value compare:other.value]; + } + } else { + return thisIndex > otherIndex ? NSOrderedDescending + : NSOrderedAscending; + } +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +- (void)forEachChildDo:(fbt_bool_nsstring_node)action { + // There are no children, so there is nothing to do. + return; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h new file mode 100644 index 0000000..ea251b6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@protocol FIndex; + +@protocol FNode + +- (BOOL)isLeafNode; +- (id)getPriority; +- (id)updatePriority:(id)priority; +- (id)getImmediateChild:(NSString *)childKey; +- (id)getChild:(FPath *)path; +- (NSString *)predecessorChildKey:(NSString *)childKey; +- (id)updateImmediateChild:(NSString *)childKey + withNewChild:(id)newChildNode; +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode; +- (BOOL)hasChild:(NSString *)childKey; +- (BOOL)isEmpty; +- (int)numChildren; +- (id)val; +- (id)valForExport:(BOOL)exp; +- (NSString *)dataHash; +- (NSComparisonResult)compare:(id)other; +- (BOOL)isEqual:(id)other; +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h new file mode 100644 index 0000000..bf44660 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@class FImmutableSortedDictionary; +@class FCompoundWrite; +@class FLeafNode; +@protocol FNode; + +typedef NS_ENUM(NSInteger, FDataHashVersion) { + FDataHashVersionV1, + FDataHashVersionV2, +}; + +@interface FSnapshotUtilities : NSObject + ++ (id)nodeFrom:(id)val; ++ (id)nodeFrom:(id)val priority:(id)priority; ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn; ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn; ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn; ++ (void)validatePriorityNode:(id)priorityNode; ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)val + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion; ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString; + ++ (NSUInteger)estimateSerializedNodeSize:(id)node; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m new file mode 100644 index 0000000..f3f9ed5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m @@ -0,0 +1,394 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotUtilities.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FUtilities.h" +#import "FValidation.h" + +@implementation FSnapshotUtilities + ++ (id)nodeFrom:(id)val { + return [FSnapshotUtilities nodeFrom:val priority:nil]; +} + ++ (id)nodeFrom:(id)val priority:(id)priority { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:@"nodeFrom:priority:"]; +} + ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val priority:nil withValidationFrom:fn]; +} + ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:fn + atDepth:0 + path:[[NSMutableArray alloc] init]]; +} + ++ (id)nodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + @autoreleasepool { + return [FSnapshotUtilities internalNodeFrom:val + priority:aPriority + withValidationFrom:fn + atDepth:depth + path:path]; + } +} + ++ (id)internalNodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + + if (depth > kFirebaseMaxObjectDepth) { + NSRange range; + range.location = 0; + range.length = 100; + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Max object depth exceeded: %@...", + fn, pathString] + userInfo:nil]; + } + + if (val == nil || val == [NSNull null]) { + // Null is a valid type to store + return [FEmptyNode emptyNode]; + } + + [FValidation validateFrom:fn isValidPriorityValue:aPriority withPath:path]; + id priority = [FSnapshotUtilities nodeFrom:aPriority]; + + id value = val; + BOOL isLeafNode = NO; + + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = val; + if (dict[kPayloadPriority] != nil) { + id rawPriority = [dict objectForKey:kPayloadPriority]; + [FValidation validateFrom:fn + isValidPriorityValue:rawPriority + withPath:path]; + priority = [FSnapshotUtilities nodeFrom:rawPriority]; + } + + if (dict[kPayloadValue] != nil) { + value = [dict objectForKey:kPayloadValue]; + if ([FValidation validateFrom:fn + isValidLeafValue:value + withPath:path]) { + isLeafNode = YES; + } else { + @throw [[NSException alloc] + initWithName:@"InvalidLeafValueType" + reason:[NSString stringWithFormat: + @"(%@) Invalid data type used " + @"with .value. Can only use " + "NSString and NSNumber or be " + "null. Found %@ instead.", + fn, [[value class] description]] + userInfo:nil]; + } + } + } + + if ([FValidation validateFrom:fn isValidLeafValue:value withPath:path]) { + isLeafNode = YES; + } + + if (isLeafNode) { + return [[FLeafNode alloc] initWithValue:value withPriority:priority]; + } + + // Unlike with JS, we have to handle the dictionary and array cases + // separately. + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = (NSDictionary *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:dval.count]; + + // Avoid creating a million newPaths by appending to old one + for (id keyId in dval) { + [FValidation validateFrom:fn + validDictionaryKey:keyId + withPath:path]; + NSString *key = (NSString *)keyId; + + if (![key hasPrefix:kPayloadMetadataPrefix]) { + [path addObject:key]; + id childNode = [FSnapshotUtilities nodeFrom:dval[key] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *aval = (NSArray *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:aval.count]; + + for (int i = 0; i < [aval count]; i++) { + NSString *key = [NSString stringWithFormat:@"%i", i]; + [path addObject:key]; + id childNode = + [FSnapshotUtilities nodeFrom:[aval objectAtIndex:i] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store object of type %@ at %@. " + "Can only store objects of type NSNumber, " + "NSString, NSDictionary, and NSArray.", + fn, [[value class] description], pathString] + userInfo:nil]; + } +} + ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn { + FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + + NSMutableArray *updatePaths = + [NSMutableArray arrayWithCapacity:values.count]; + for (NSString *keyId in values) { + id value = values[keyId]; + [FValidation validateFrom:fn + validUpdateDictionaryKey:keyId + withValue:value]; + + FPath *path = [FPath pathWithString:keyId]; + id node = [FSnapshotUtilities nodeFrom:value + withValidationFrom:fn]; + + [updatePaths addObject:path]; + compoundWrite = [compoundWrite addWrite:node atPath:path]; + } + + // Check that the update paths are not descendants of each other. + [updatePaths + sortUsingComparator:^NSComparisonResult(FPath *left, FPath *right) { + return [left compare:right]; + }]; + FPath *prevPath = nil; + for (FPath *path in updatePaths) { + if (prevPath != nil && [prevPath contains:path]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid path in object. Path " + @"(%@) is an ancestor of (%@).", + fn, prevPath, path] + userInfo:nil]; + } + prevPath = path; + } + + return compoundWrite; +} + ++ (void)validatePriorityNode:(id)priorityNode { + assert(priorityNode != nil); + if (priorityNode.isLeafNode) { + id val = priorityNode.val; + if ([val isKindOfClass:[NSDictionary class]]) { + NSDictionary *valDict __unused = (NSDictionary *)val; + NSAssert(valDict[kServerValueSubKey] != nil, + @"Priority can't be object unless it's a deferred value"); + } else { + NSString *jsType __unused = [FUtilities getJavascriptType:val]; + NSAssert(jsType == kJavaScriptString || jsType == kJavaScriptNumber, + @"Priority of unexpected type."); + } + } else { + NSAssert(priorityNode == [FMaxNode maxNode] || priorityNode.isEmpty, + @"Priority of unexpected type."); + } + // Don't call getPriority() on MAX_NODE to avoid hitting assertion. + NSAssert(priorityNode == [FMaxNode maxNode] || + priorityNode.getPriority.isEmpty, + @"Priority nodes can't have a priority of their own."); +} + ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)leafNode + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion { + NSAssert(hashVersion == FDataHashVersionV1 || + hashVersion == FDataHashVersionV2, + @"Unknown hash version: %lu", (unsigned long)hashVersion); + if (!leafNode.getPriority.isEmpty) { + [string appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode.getPriority + toString:string + hashVersion:hashVersion]; + [string appendString:@":"]; + } + + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + [string appendString:jsType]; + [string appendString:@":"]; + + if (jsType == kJavaScriptBoolean) { + NSString *boolString = + [leafNode.val boolValue] ? kJavaScriptTrue : kJavaScriptFalse; + [string appendString:boolString]; + } else if (jsType == kJavaScriptNumber) { + NSString *numberString = + [FUtilities ieee754StringForNumber:leafNode.val]; + [string appendString:numberString]; + } else if (jsType == kJavaScriptString) { + if (hashVersion == FDataHashVersionV1) { + [string appendString:leafNode.val]; + } else { + NSAssert(hashVersion == FDataHashVersionV2, + @"Invalid hash version found"); + [FSnapshotUtilities appendHashV2RepresentationForString:leafNode.val + toString:string]; + } + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown value for hashing: %@", leafNode]; + } +} + ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString { + string = [string stringByReplacingOccurrencesOfString:@"\\" + withString:@"\\\\"]; + string = [string stringByReplacingOccurrencesOfString:@"\"" + withString:@"\\\""]; + [mutableString appendString:@"\""]; + [mutableString appendString:string]; + [mutableString appendString:@"\""]; +} + ++ (NSUInteger)estimateLeafNodeSize:(FLeafNode *)leafNode { + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + // These values are somewhat arbitrary, but we don't need an exact value so + // prefer performance over exact value + NSUInteger valueSize; + if (jsType == kJavaScriptNumber) { + valueSize = 8; // estimate each float with 8 bytes + } else if (jsType == kJavaScriptBoolean) { + valueSize = 4; // true or false need roughly 4 bytes + } else if (jsType == kJavaScriptString) { + valueSize = 2 + [leafNode.val length]; // add 2 for quotes + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown leaf type: %@", leafNode]; + return 0; + } + + if (leafNode.getPriority.isEmpty) { + return valueSize; + } else { + // Account for extra overhead due to the extra JSON object and the + // ".value" and ".priority" keys, colons, comma + NSUInteger leafPriorityOverhead = 2 + 8 + 11 + 2 + 1; + return leafPriorityOverhead + valueSize + + [FSnapshotUtilities estimateLeafNodeSize:leafNode.getPriority]; + } +} + ++ (NSUInteger)estimateSerializedNodeSize:(id)node { + if ([node isEmpty]) { + return 4; // null keyword + } else if ([node isLeafNode]) { + return [FSnapshotUtilities estimateLeafNodeSize:node]; + } else { + NSAssert([node isKindOfClass:[FChildrenNode class]], + @"Unexpected node type: %@", [node class]); + __block NSUInteger sum = 1; // opening brackets + [((FChildrenNode *)node) enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id child, + BOOL *stop) { + sum += key.length; + sum += + 4; // quotes around key and colon and (comma or closing bracket) + sum += [FSnapshotUtilities estimateSerializedNodeSize:child]; + }]; + return sum; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h new file mode 100644 index 0000000..b8668d2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FAtomicNumber : NSObject + +- (NSNumber *)getAndIncrement; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m new file mode 100644 index 0000000..20cfd8d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAtomicNumber.h" + +@interface FAtomicNumber () { + unsigned long number; +} + +@property(nonatomic, strong) NSLock *lock; + +@end + +@implementation FAtomicNumber + +@synthesize lock; + +- (id)init { + self = [super init]; + if (self) { + number = 1; + self.lock = [[NSLock alloc] init]; + } + return self; +} + +- (NSNumber *)getAndIncrement { + NSNumber *result; + + // See: + // http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW14 + // to improve, etc. + + [self.lock lock]; + result = [NSNumber numberWithUnsignedLong:number]; + number = number + 1; + [self.lock unlock]; + + return result; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h new file mode 100644 index 0000000..fc19ca7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseQuery.h" +#import "FTypedefs_Private.h" + +@interface FEventEmitter : NSObject + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue; + +- (id)getInitialEventForType:(NSString *)eventType; +- (void)triggerEventType:(NSString *)eventType data:(id)data; + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block; +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle; + +- (void)validateEventType:(NSString *)eventType; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m new file mode 100644 index 0000000..7d02239 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m @@ -0,0 +1,161 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventEmitter.h" +#import "FIRDatabaseQuery_Private.h" +#import "FRepoManager.h" +#import "FUtilities.h" + +@interface FEventListener : NSObject + +@property(nonatomic, copy) fbt_void_id userCallback; +@property(nonatomic) FIRDatabaseHandle handle; + +@end + +@implementation FEventListener + +@synthesize userCallback; +@synthesize handle; + +@end + +@interface FEventEmitter () + +@property(nonatomic, strong) NSArray *allowedEvents; +@property(nonatomic, strong) NSMutableDictionary *listeners; +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +@implementation FEventEmitter + +@synthesize allowedEvents; +@synthesize listeners; + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue { + if (theAllowedEvents == nil || [theAllowedEvents count] == 0) { + @throw [NSException + exceptionWithName:@"AllowedEventsValidation" + reason:@"FEventEmitters must be initialized with at " + @"least one valid event." + userInfo:nil]; + } + + self = [super init]; + + if (self) { + self.allowedEvents = [theAllowedEvents copy]; + self.listeners = [[NSMutableDictionary alloc] init]; + self.queue = queue; + } + + return self; +} + +- (id)getInitialEventForType:(NSString *)eventType { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"You must override getInitialEvent: " + @"when subclassing FEventEmitter" + userInfo:nil]; +} + +- (void)triggerEventType:(NSString *)eventType data:(id)data { + [self validateEventType:eventType]; + NSMutableDictionary *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in eventTypeListeners) { + [self triggerListener:listener withData:data]; + } +} + +- (void)triggerListener:(FEventListener *)listener withData:(id)data { + // TODO, should probably get this from FRepo or something although it ends + // up being the same. (Except maybe for testing) + if (listener.userCallback) { + dispatch_async(self.queue, ^{ + listener.userCallback(data); + }); + } +} + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block { + [self validateEventType:eventType]; + + // Create listener + FEventListener *listener = [[FEventListener alloc] init]; + listener.handle = [[FUtilities LUIDGenerator] integerValue]; + listener.userCallback = block; // copies block automatically + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self addEventListener:listener forEventType:eventType]; + }); + + return listener.handle; +} + +- (void)addEventListener:(FEventListener *)listener + forEventType:(NSString *)eventType { + // Get or initializer listeners map [FIRDatabaseHandle -> callback block] + // for eventType + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + if (eventTypeListeners == nil) { + eventTypeListeners = [[NSMutableArray alloc] init]; + [self.listeners setObject:eventTypeListeners forKey:eventType]; + } + + // Add listener and fire the current event for this listener + [eventTypeListeners addObject:listener]; + id initialData = [self getInitialEventForType:eventType]; + [self triggerListener:listener withData:initialData]; +} + +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle { + [self validateEventType:eventType]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self removeEventListenerWithHandle:handle forEventType:eventType]; + }); +} + +- (void)removeEventListenerWithHandle:(FIRDatabaseHandle)handle + forEventType:(NSString *)eventType { + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in [eventTypeListeners copy]) { + if (handle == NSNotFound || handle == listener.handle) { + [eventTypeListeners removeObject:listener]; + } + } +} + +- (void)validateEventType:(NSString *)eventType { + if ([self.allowedEvents indexOfObject:eventType] == NSNotFound) { + @throw [NSException + exceptionWithName:@"InvalidEventType" + reason:[NSString stringWithFormat: + @"%@ is not a valid event type. %@ " + @"is the list of valid events.", + eventType, self.allowedEvents] + userInfo:nil]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h new file mode 100644 index 0000000..5a66196 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FNextPushId : NSObject + ++ (NSString *)get:(NSTimeInterval)now; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m new file mode 100644 index 0000000..864e147 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNextPushId.h" +#import "FUtilities.h" + +static NSString *const PUSH_CHARS = + @"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; + +@implementation FNextPushId + ++ (NSString *)get:(NSTimeInterval)currentTime { + static long long lastPushTime = 0; + static int lastRandChars[12]; + + long long now = (long long)(currentTime * 1000); + + BOOL duplicateTime = now == lastPushTime; + lastPushTime = now; + + unichar timeStampChars[8]; + for (int i = 7; i >= 0; i--) { + timeStampChars[i] = [PUSH_CHARS characterAtIndex:(now % 64)]; + now = (long long)floor(now / 64); + } + + NSMutableString *id = [[NSMutableString alloc] init]; + [id appendString:[NSString stringWithCharacters:timeStampChars length:8]]; + + if (!duplicateTime) { + for (int i = 0; i < 12; i++) { + lastRandChars[i] = (int)floor(arc4random() % 64); + } + } else { + int i = 0; + for (i = 11; i >= 0 && lastRandChars[i] == 63; i--) { + lastRandChars[i] = 0; + } + lastRandChars[i]++; + } + + for (int i = 0; i < 12; i++) { + [id appendFormat:@"%C", [PUSH_CHARS characterAtIndex:lastRandChars[i]]]; + } + + return [NSString stringWithString:id]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h new file mode 100644 index 0000000..1c07284 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FRepoInfo.h" + +@interface FParsedUrl : NSObject + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPath *path; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m new file mode 100644 index 0000000..eb83330 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FParsedUrl.h" + +@implementation FParsedUrl + +@synthesize repoInfo; +@synthesize path; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h new file mode 100644 index 0000000..f7d19b6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FStringUtilities : NSObject + ++ (NSString *)base64EncodedSha1:(NSString *)str; ++ (NSString *)urlDecoded:(NSString *)url; ++ (NSString *)urlEncoded:(NSString *)url; ++ (NSString *)sanitizedForUserAgent:(NSString *)str; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m new file mode 100644 index 0000000..2515257 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FStringUtilities.h" +#import "NSData+SRB64Additions.h" +#import + +@implementation FStringUtilities + +// http://stackoverflow.com/questions/3468268/objective-c-sha1 +// http://stackoverflow.com/questions/7310457/ios-objective-c-sha-1-and-base64-problem ++ (NSString *)base64EncodedSha1:(NSString *)str { + const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding]; + // NSString reports length in characters, but we want it in bytes, which + // strlen will give us. + unsigned long dataLen = strlen(cstr); + NSData *data = [NSData dataWithBytes:cstr length:dataLen]; + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes, (unsigned int)data.length, digest); + NSData *output = [[NSData alloc] initWithBytes:digest + length:CC_SHA1_DIGEST_LENGTH]; + return [FSRUtilities base64EncodedStringFromData:output]; +} + ++ (NSString *)urlDecoded:(NSString *)url { + NSString *replaced = [url stringByReplacingOccurrencesOfString:@"+" + withString:@" "]; + NSString *decoded = [replaced stringByRemovingPercentEncoding]; + // This is kind of a hack, but is generally how the js client works. We + // could run into trouble if some piece is a correctly escaped %-sequence, + // and another isn't. But, that's bad input anyways... + if (decoded) { + return decoded; + } else { + return replaced; + } +} + ++ (NSString *)urlEncoded:(NSString *)url { + // Didn't seem like there was an Apple NSCharacterSet that had our version + // of the encoding So I made my own, following RFC 2396 + // https://www.ietf.org/rfc/rfc2396.txt allowedCharacters = alphanum | "-" | + // "_" | "~" + NSCharacterSet *allowedCharacters = [NSCharacterSet + characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGH" + @"IJKLMNOPQRSTUVWXYZ0123456789-_~"]; + return [url + stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; +} + ++ (NSString *)sanitizedForUserAgent:(NSString *)str { + return + [str stringByReplacingOccurrencesOfString:@"/|_" + withString:@"|" + options:NSRegularExpressionSearch + range:NSMakeRange(0, [str length])]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h new file mode 100644 index 0000000..56d97ff --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef Firebase_FTypedefs_h +#define Firebase_FTypedefs_h + +/** + * Stub... + */ +@class FIRDataSnapshot; +@class FIRDatabaseReference; +@class FAuthData; +@protocol FNode; + +// fbt = Firebase Block Typedef + +typedef void (^fbt_void_void)(void); +typedef void (^fbt_void_datasnapshot_nsstring)(FIRDataSnapshot *snapshot, + NSString *prevName); +typedef void (^fbt_void_datasnapshot)(FIRDataSnapshot *snapshot); +typedef void (^fbt_void_user)(FAuthData *user); +typedef void (^fbt_void_nsstring_id)(NSString *status, id data); +typedef void (^fbt_void_nserror_id)(NSError *error, id data); +typedef void (^fbt_void_nserror)(NSError *error); +typedef void (^fbt_void_nserror_ref)(NSError *error, FIRDatabaseReference *ref); +typedef void (^fbt_void_nserror_user)(NSError *error, FAuthData *user); +typedef void (^fbt_void_nserror_json)(NSError *error, NSDictionary *json); +typedef void (^fbt_void_nsdictionary)(NSDictionary *data); +typedef id (^fbt_id_node_nsstring)(id node, NSString *childName); + +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h new file mode 100644 index 0000000..9458f24 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FParsedUrl.h" + +@interface FUtilities : NSObject + ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size; ++ (NSNumber *)LUIDGenerator; ++ (FParsedUrl *)parseUrl:(NSString *)url; ++ (NSString *)getJavascriptType:(id)obj; ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason; ++ (NSNumber *)intForString:(NSString *)string; ++ (NSString *)ieee754StringForNumber:(NSNumber *)val; ++ (void)setLoggingEnabled:(BOOL)enabled; ++ (BOOL)getLoggingEnabled; + ++ (NSString *)minName; ++ (NSString *)maxName; ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b; ++ (NSComparator)stringComparator; ++ (NSComparator)keyComparator; + ++ (double)randomDouble; + +@end + +typedef enum { + FLogLevelDebug = 1, + FLogLevelInfo = 2, + FLogLevelWarn = 3, + FLogLevelError = 4, + FLogLevelNone = 5 +} FLogLevel; + +// Log tags +FOUNDATION_EXPORT NSString *const kFPersistenceLogTag; + +#define FFLog(code, format, ...) FFDebug((code), (format), ##__VA_ARGS__) + +#define FFDebug(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelDebug)) { \ + FIRLogDebug(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFInfo(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelInfo)) { \ + FIRLogError(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFWarn(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelWarn)) { \ + FIRLogWarning(kFIRLoggerDatabase, (code), (format), \ + ##__VA_ARGS__); \ + } \ + } while (0) + +extern FIRLoggerService kFIRLoggerDatabase; +BOOL FFIsLoggingEnabled(FLogLevel logLevel); +void firebaseUncaughtExceptionHandler(NSException *exception); +void firebaseJobsTroll(void); diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m new file mode 100644 index 0000000..a24c134 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m @@ -0,0 +1,433 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FUtilities.h" +#import "FAtomicNumber.h" +#import "FConstants.h" +#import "FStringUtilities.h" +#import + +#define ARC4RANDOM_MAX 0x100000000 +#define INTEGER_32_MIN (-2147483648) +#define INTEGER_32_MAX 2147483647 + +#pragma mark - +#pragma mark C functions + +FIRLoggerService kFIRLoggerDatabase = @"[Firebase/Database]"; +static FLogLevel logLevel = FLogLevelInfo; // Default log level is info +static NSMutableDictionary *options = nil; + +BOOL FFIsLoggingEnabled(FLogLevel level) { return level >= logLevel; } + +void firebaseJobsTroll(void) { + FFLog(@"I-RDB095001", + @"password super secret; JFK conspiracy; Hello there! Having fun " + @"digging through Firebase? We're always hiring! jobs@firebase.com"); +} + +#pragma mark - +#pragma mark Private property and singleton specification + +@interface FUtilities () { +} + +@property(nonatomic, strong) FAtomicNumber *localUid; + ++ (FUtilities *)singleton; + +@end + +@implementation FUtilities + +@synthesize localUid; + +- (id)init { + self = [super init]; + if (self) { + self.localUid = [[FAtomicNumber alloc] init]; + } + return self; +} + +// TODO: We really want to be able to set the log level ++ (void)setLoggingEnabled:(BOOL)enabled { + logLevel = enabled ? FLogLevelDebug : FLogLevelInfo; +} + ++ (BOOL)getLoggingEnabled { + return logLevel == FLogLevelDebug; +} + ++ (FUtilities *)singleton { + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +// Refactor as a category of NSString ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size { + if (str.length <= size) { + return [NSArray arrayWithObject:str]; + } + + NSMutableArray *dataSegs = [[NSMutableArray alloc] init]; + for (int c = 0; c < str.length; c += size) { + if (c + size > str.length) { + int rangeStart = c; + unsigned long rangeLength = size - ((c + size) - str.length); + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } else { + int rangeStart = c; + int rangeLength = size; + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } + } + return dataSegs; +} + ++ (NSNumber *)LUIDGenerator { + FUtilities *f = [FUtilities singleton]; + return [f.localUid getAndIncrement]; +} + ++ (NSString *)decodePath:(NSString *)pathString { + NSMutableArray *decodedPieces = [[NSMutableArray alloc] init]; + NSArray *pieces = [pathString componentsSeparatedByString:@"/"]; + for (NSString *piece in pieces) { + if (piece.length > 0) { + [decodedPieces addObject:[FStringUtilities urlDecoded:piece]]; + } + } + return [NSString + stringWithFormat:@"/%@", [decodedPieces componentsJoinedByString:@"/"]]; +} + ++ (NSString *)extractPathFromUrlString:(NSString *)url { + NSString *path = url; + + NSRange schemeIndex = [path rangeOfString:@"//"]; + if (schemeIndex.location != NSNotFound) { + path = [path substringFromIndex:schemeIndex.location + 2]; + } + + NSUInteger pathIndex = [path rangeOfString:@"/"].location; + if (pathIndex != NSNotFound) { + path = [path substringFromIndex:pathIndex + 1]; + } else { + path = @""; + } + + NSUInteger queryParamIndex = [path rangeOfString:@"?"].location; + if (queryParamIndex != NSNotFound) { + path = [path substringToIndex:queryParamIndex]; + } + + return path; +} + ++ (FParsedUrl *)parseUrl:(NSString *)url { + // For backwards compatibility, support URLs without schemes on iOS. + if (![url containsString:@"://"]) { + url = [@"http://" stringByAppendingString:url]; + } + + NSString *originalPathString = [self extractPathFromUrlString:url]; + + // Sanitize the database URL by removing the path component, which may + // contain invalid URL characters. + NSString *sanitizedUrlWithoutPath = + [url stringByReplacingOccurrencesOfString:originalPathString + withString:@""]; + NSURLComponents *urlComponents = + [NSURLComponents componentsWithString:sanitizedUrlWithoutPath]; + if (!urlComponents) { + [NSException raise:@"Failed to parse database URL" + format:@"Failed to parse database URL: %@", url]; + } + + NSString *host = [urlComponents.host lowercaseString]; + NSString *namespace; + bool secure; + + if (urlComponents.port != nil) { + secure = [urlComponents.scheme isEqualToString:@"https"] || + [urlComponents.scheme isEqualToString:@"wss"]; + host = [host stringByAppendingFormat:@":%@", urlComponents.port]; + } else { + secure = YES; + }; + + NSArray *parts = [urlComponents.host componentsSeparatedByString:@"."]; + if ([parts count] == 3) { + namespace = [parts[0] lowercaseString]; + } else { + // Attempt to extract namespace from "ns" query param. + NSArray *queryItems = urlComponents.queryItems; + for (NSURLQueryItem *item in queryItems) { + if ([item.name isEqualToString:@"ns"]) { + namespace = item.value; + break; + } + } + + if (!namespace) { + namespace = [parts[0] lowercaseString]; + } + } + + NSString *pathString = [self + decodePath:[NSString stringWithFormat:@"/%@", originalPathString]]; + FPath *path = [[FPath alloc] initWith:pathString]; + FRepoInfo *repoInfo = [[FRepoInfo alloc] initWithHost:host + isSecure:secure + withNamespace:namespace]; + + FFLog(@"I-RDB095002", @"---> Parsed (%@) to: (%@,%@); ns=(%@); path=(%@)", + url, [repoInfo description], [repoInfo connectionURL], + repoInfo.namespace, [path description]); + + FParsedUrl *parsedUrl = [[FParsedUrl alloc] init]; + parsedUrl.repoInfo = repoInfo; + parsedUrl.path = path; + + return parsedUrl; +} + +/* + case str: JString => priString + "string:" + str.s; + case bool: JBool => priString + "boolean:" + bool.value; + case double: JDouble => priString + "number:" + double.num; + case int: JInt => priString + "number:" + int.num; + case _ => { + error("Leaf node has value '" + data.value + "' of invalid type '" + + data.value.getClass.toString + "'"); + ""; + } + */ + ++ (NSString *)getJavascriptType:(id)obj { + if ([obj isKindOfClass:[NSDictionary class]]) { + return kJavaScriptObject; + } else if ([obj isKindOfClass:[NSString class]]) { + return kJavaScriptString; + } else if ([obj isKindOfClass:[NSNumber class]]) { + // We used to just compare to @encode(BOOL) as suggested at + // http://stackoverflow.com/questions/2518761/get-type-of-nsnumber, but + // on arm64, @encode(BOOL) returns "B" instead of "c" even though + // objCType still returns 'c' (signed char). So check both. + if (strcmp([obj objCType], @encode(BOOL)) == 0 || + strcmp([obj objCType], @encode(signed char)) == 0) { + return kJavaScriptBoolean; + } else { + return kJavaScriptNumber; + } + } else { + return kJavaScriptNull; + } +} + ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason { + static dispatch_once_t pred = 0; + __strong static NSDictionary *errorMap = nil; + __strong static NSDictionary *errorCodes = nil; + dispatch_once(&pred, ^{ + errorMap = @{ + @"permission_denied" : @"Permission Denied", + @"unavailable" : @"Service is unavailable", + kFErrorWriteCanceled : @"Write cancelled by user" + }; + errorCodes = @{ + @"permission_denied" : @1, + @"unavailable" : @2, + kFErrorWriteCanceled : @3 + }; + }); + + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + return nil; + } else { + NSInteger code; + NSString *desc = nil; + if (reason) { + desc = reason; + } else if ([errorMap objectForKey:status] != nil) { + desc = [errorMap objectForKey:status]; + } else { + desc = status; + } + + if ([errorCodes objectForKey:status] != nil) { + NSNumber *num = [errorCodes objectForKey:status]; + code = [num integerValue]; + } else { + // XXX what to do here? + code = 9999; + } + + return [[NSError alloc] + initWithDomain:kFErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : desc}]; + } +} + ++ (NSNumber *)intForString:(NSString *)string { + static NSCharacterSet *notDigits = nil; + if (!notDigits) { + notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + } + if ([string rangeOfCharacterFromSet:notDigits].length == 0) { + NSInteger num; + NSScanner *scanner = [NSScanner scannerWithString:string]; + if ([scanner scanInteger:&num]) { + return [NSNumber numberWithInteger:num]; + } + } + return nil; +} + ++ (NSString *)ieee754StringForNumber:(NSNumber *)val { + double d = [val doubleValue]; + NSData *data = [NSData dataWithBytes:&d length:sizeof(double)]; + NSMutableString *str = [[NSMutableString alloc] init]; + const unsigned char *buffer = (const unsigned char *)[data bytes]; + for (int i = 0; i < data.length; i++) { + unsigned char byte = buffer[7 - i]; + [str appendFormat:@"%02x", byte]; + } + return str; +} + +static inline BOOL tryParseStringToInt(__unsafe_unretained NSString *str, + NSInteger *integer) { + // First do some cheap checks (NOTE: The below checks are significantly + // faster than an equivalent regex :-( ). + NSUInteger length = str.length; + if (length > 11 || length == 0) { + return NO; + } + long long value = 0; + BOOL negative = NO; + NSUInteger i = 0; + if ([str characterAtIndex:0] == '-') { + if (length == 1) { + return NO; + } + negative = YES; + i = 1; + } + for (; i < length; i++) { + unichar c = [str characterAtIndex:i]; + // Must be a digit, or '-' if it's the first char. + if (c < '0' || c > '9') { + return NO; + } else { + int charValue = c - '0'; + value = value * 10 + charValue; + } + } + + value = (negative) ? -value : value; + + if (value < INTEGER_32_MIN || value > INTEGER_32_MAX) { + return NO; + } else { + *integer = (NSInteger)value; + return YES; + } +} + ++ (NSString *)maxName { + static dispatch_once_t once; + static NSString *maxName; + dispatch_once(&once, ^{ + maxName = [[NSString alloc] initWithFormat:@"[MAX_NAME]"]; + }); + return maxName; +} + ++ (NSString *)minName { + static dispatch_once_t once; + static NSString *minName; + dispatch_once(&once, ^{ + minName = [[NSString alloc] initWithFormat:@"[MIN_NAME]"]; + }); + return minName; +} + ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b { + if (a == b) { + return NSOrderedSame; + } else if (a == [FUtilities minName] || b == [FUtilities maxName]) { + return NSOrderedAscending; + } else if (b == [FUtilities minName] || a == [FUtilities maxName]) { + return NSOrderedDescending; + } else { + NSInteger aAsInt, bAsInt; + if (tryParseStringToInt(a, &aAsInt)) { + if (tryParseStringToInt(b, &bAsInt)) { + if (aAsInt > bAsInt) { + return NSOrderedDescending; + } else if (aAsInt < bAsInt) { + return NSOrderedAscending; + } else if (a.length > b.length) { + return NSOrderedDescending; + } else if (a.length < b.length) { + return NSOrderedAscending; + } else { + return NSOrderedSame; + } + } else { + return (NSComparisonResult)NSOrderedAscending; + } + } else if (tryParseStringToInt(b, &bAsInt)) { + return (NSComparisonResult)NSOrderedDescending; + } else { + // Perform literal character by character search to prevent a > b && + // b > a issues. Note that calling -(NSString + // *)decomposedStringWithCanonicalMapping also works. + return [a compare:b options:NSLiteralSearch]; + } + } +} + ++ (NSComparator)keyComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [FUtilities compareKey:a toKey:b]; + }; +} + ++ (NSComparator)stringComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [a compare:b]; + }; +} + ++ (double)randomDouble { + return ((double)arc4random() / ARC4RANDOM_MAX); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h new file mode 100644 index 0000000..276eb26 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FParsedUrl.h" +#import "FPath.h" +#import "FTypedefs.h" +#import + +@interface FValidation : NSObject + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path; ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event; ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key; ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl; + ++ (void)validateToken:(NSString *)token; + +// Functions for handling passing errors back ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback; ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback; + +// Functions used for validating while creating snapshots in FSnapshotUtilities ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value; ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path; ++ (BOOL)validatePriorityValue:value; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m new file mode 100644 index 0000000..c700b9c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m @@ -0,0 +1,461 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValidation.h" +#import "FConstants.h" +#import "FParsedUrl.h" +#import "FTypedefs.h" + +// Have to escape: * ? + [ ( ) { } ^ $ | \ . / +// See: +// https://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html + +NSString *const kInvalidPathCharacters = @"[].#$"; +NSString *const kInvalidKeyCharacters = @"[].#$/"; + +@implementation FValidation + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path { + if ([[path getFront] isEqualToString:kDotInfoPrefix]) { + @throw [[NSException alloc] + initWithName:@"WritablePathValidation" + reason:[NSString + stringWithFormat:@"(%@) failed to path %@: Can't " + @"modify data under %@", + fn, [path description], + kDotInfoPrefix] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event { + switch (event) { + case FIRDataEventTypeValue: + case FIRDataEventTypeChildAdded: + case FIRDataEventTypeChildChanged: + case FIRDataEventTypeChildMoved: + case FIRDataEventTypeChildRemoved: + return; + break; + default: + @throw [[NSException alloc] + initWithName:@"KnownEventTypeValidation" + reason:[NSString + stringWithFormat:@"(%@) Unknown event type: %d", + fn, (int)event] + userInfo:nil]; + break; + } +} + ++ (BOOL)isValidPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSCharacterSet *badPathChars = nil; + dispatch_once(&token, ^{ + badPathChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidPathCharacters]; + }); + return pathString != nil && [pathString length] != 0 && + [pathString rangeOfCharacterFromSet:badPathChars].location == + NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString { + if (![self isValidPathString:pathString]) { + @throw [[NSException alloc] + initWithName:@"InvalidPathValidation" + reason:[NSString stringWithFormat: + @"(%@) Must be a non-empty string and " + @"not contain '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSRegularExpression *dotInfoRegex = nil; + dispatch_once(&token, ^{ + dotInfoRegex = [NSRegularExpression + regularExpressionWithPattern:@"^\\/*\\.info(\\/|$)" + options:0 + error:nil]; + }); + + NSString *tempPath = pathString; + // HACK: Obj-C regex are kinda' slow. Do a plain string search first before + // bothering with the regex. + if ([pathString rangeOfString:@".info"].location != NSNotFound) { + tempPath = [dotInfoRegex + stringByReplacingMatchesInString:pathString + options:0 + range:NSMakeRange(0, pathString.length) + withTemplate:@"/"]; + } + [self validateFrom:fn validPathString:tempPath]; +} + ++ (BOOL)isValidKey:(NSString *)key { + static dispatch_once_t token; + static NSCharacterSet *badKeyChars = nil; + dispatch_once(&token, ^{ + badKeyChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidKeyCharacters]; + }); + return key != nil && key.length > 0 && + [key rangeOfCharacterFromSet:badKeyChars].location == NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key { + if (![self isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidKeyValidation" + reason:[NSString + stringWithFormat: + @"(%@) Must be a non-empty string and not " + @"contain '/' '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl { + NSString *pathString = [parsedUrl.path description]; + [self validateFrom:fn validRootPathString:pathString]; +} + +#pragma mark - +#pragma mark Authentication validation + ++ (BOOL)stringNonempty:(NSString *)str { + return str != nil && ![str isKindOfClass:[NSNull class]] && str.length > 0; +} + ++ (void)validateToken:(NSString *)token { + if (![FValidation stringNonempty:token]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't have empty string or nil for custom token"]; + } +} + +#pragma mark - +#pragma mark Handling authentication errors + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback { + if (userCallback) { + userCallback(error, nil); + } +} + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback { + if (userCallback) { + userCallback(error); + } +} + +#pragma mark - +#pragma mark Snapshot validation + ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path { + if ([value isKindOfClass:[NSString class]]) { + // Try to avoid conversion to bytes if possible + NSString *theString = value; + if ([theString maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize && + [theString lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) String exceeds max " + @"size of %u utf8 bytes: %@", + fn, (int)kFirebaseMaxLeafSize, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSNumber class]]) { + // Cannot store NaN, but otherwise can store NSNumbers. + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store NaN at path: %@.", fn, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys.%@.", + fn, pathString] + userInfo:nil]; + } + return YES; + } + return NO; + } + + else if (value == [NSNull null] || value == nil) { + // Null is valid type to store at leaf + return YES; + } + + return NO; +} + ++ (NSString *)parseAndValidateKey:(id)keyId + fromFunction:(NSString *)fn + path:(NSArray *)path { + if (![keyId isKindOfClass:[NSString class]]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) Non-string keys are not " + @"allowed in object at path: %@", + fn, pathString] + userInfo:nil]; + } + return (NSString *)keyId; +} + ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path { + NSString *key = [self parseAndValidateKey:keyId fromFunction:fn path:path]; + if (![key isEqualToString:kPayloadPriority] && + ![key isEqualToString:kPayloadValue] && + ![key isEqualToString:kServerValueSubKey] && + ![FValidation isValidKey:key]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid key in object at path: " + @"%@. Keys must be non-empty and cannot " + @"contain '/' '.' '#' '$' '[' or ']'", + fn, pathString] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value { + FPath *path = [FPath pathWithString:[self parseAndValidateKey:keyId + fromFunction:fn + path:@[]]]; + __block NSInteger keyNum = 0; + [path enumerateComponentsUsingBlock:^void(NSString *key, BOOL *stop) { + if ([key isEqualToString:kPayloadPriority] && + keyNum == [path length] - 1) { + [self validateFrom:fn isValidPriorityValue:value withPath:@[]]; + } else { + keyNum++; + + if (![FValidation isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Invalid key in object. Keys must " + @"be non-empty and cannot contain '.' " + @"'#' '$' '[' or ']'", + fn] + userInfo:nil]; + } + } + }]; +} + ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path { + [self validateFrom:fn + isValidPriorityValue:value + withPath:path + throwError:YES]; +} + +/** + * Returns YES if priority is valid. + */ ++ (BOOL)validatePriorityValue:value { + return [self validateFrom:nil + isValidPriorityValue:value + withPath:nil + throwError:NO]; +} + +/** + * Helper for validating priorities. If passed YES for throwError, it'll throw + * descriptive errors on validation problems. Else, it'll just return YES/NO. + */ ++ (BOOL)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path + throwError:(BOOL)throwError { + if ([value isKindOfClass:[NSNumber class]]) { + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store NaN as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } else if (value == (id)kCFBooleanFalse || + value == (id)kCFBooleanTrue) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store true/false " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store an NSDictionary " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSArray class]]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store an NSArray as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + + // It's valid! + return YES; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h new file mode 100644 index 0000000..f5c0859 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import + +@interface FTupleBoolBlock : NSObject + +@property(nonatomic, readwrite) BOOL boolean; +@property(nonatomic, copy) fbt_void_void block; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m new file mode 100644 index 0000000..c4cd8bf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleBoolBlock.h" + +@implementation FTupleBoolBlock + +@synthesize boolean; +@synthesize block; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h new file mode 100644 index 0000000..bd8c4a9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleCallbackStatus : NSObject +@property(nonatomic, copy) fbt_void_nsstring_nsstring block; +@property(nonatomic) NSString *status; +@property(nonatomic) NSString *errorReason; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m new file mode 100644 index 0000000..05914bf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleCallbackStatus.h" + +@implementation FTupleCallbackStatus +@synthesize block; +@synthesize status; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h new file mode 100644 index 0000000..5e41f9e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@interface FTupleFirebase : NSObject + +@property(nonatomic, strong) FIRDatabaseReference *one; +@property(nonatomic, strong) FIRDatabaseReference *two; +@property(nonatomic, strong) FIRDatabaseReference *three; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m new file mode 100644 index 0000000..3956f8b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleFirebase.h" + +@implementation FTupleFirebase + +@synthesize one; +@synthesize two; +@synthesize three; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h new file mode 100644 index 0000000..19b5217 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import + +@interface FTupleNodePath : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m new file mode 100644 index 0000000..620ae76 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleNodePath.h" + +@implementation FTupleNodePath + +@synthesize path; +@synthesize node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.path = aPath; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h new file mode 100644 index 0000000..1717a22 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleObjectNode : NSObject + +- (id)initWithObject:(id)aObj andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) id obj; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m new file mode 100644 index 0000000..4c533b0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "FTupleObjectNode.h" + +@implementation FTupleObjectNode + +@synthesize obj; +@synthesize node; + +- (id)initWithObject:(id)aObj andNode:(id)aNode { + self = [super init]; + if (self) { + self.obj = aObj; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h new file mode 100644 index 0000000..05b3141 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleObjects : NSObject + +@property(nonatomic, strong) id objA; +@property(nonatomic, strong) id objB; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m new file mode 100644 index 0000000..a9e4c88 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleObjects.h" + +@implementation FTupleObjects + +@synthesize objA; +@synthesize objB; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h new file mode 100644 index 0000000..e68ab71 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleOnDisconnect : NSObject + +@property(strong, nonatomic) NSString *pathString; +@property(strong, nonatomic) NSString *action; +@property(strong, nonatomic) id data; +@property(strong, nonatomic) fbt_void_nsstring_nsstring onComplete; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m new file mode 100644 index 0000000..bd45822 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleOnDisconnect.h" + +@implementation FTupleOnDisconnect + +@synthesize pathString; +@synthesize action; +@synthesize data; +@synthesize onComplete; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h new file mode 100644 index 0000000..b0a515c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FTuplePathValue : NSObject +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id value; +- (id)initWithPath:(FPath *)aPath value:(id)aValue; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m new file mode 100644 index 0000000..91de883 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTuplePathValue.h" +#import "FPath.h" + +@interface FTuplePathValue () +@property(nonatomic, strong, readwrite) id value; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FTuplePathValue +@synthesize path; +@synthesize value; + +- (id)initWithPath:(FPath *)aPath value:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.path = aPath; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h new file mode 100644 index 0000000..7269c2f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleRemovedQueriesEvents : NSObject +/** + * `FIRDatabaseQuery`s removed with [SyncPoint removeEventRegistration:] + */ +@property(nonatomic, strong, readonly) NSArray *removedQueries; +/** + * cancel events as FEvent + */ +@property(nonatomic, strong, readonly) NSArray *cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events; +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m new file mode 100644 index 0000000..324cfcb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleRemovedQueriesEvents.h" + +@interface FTupleRemovedQueriesEvents () +@property(nonatomic, strong, readwrite) NSArray *removedQueries; +@property(nonatomic, strong, readwrite) NSArray *cancelEvents; +@end + +@implementation FTupleRemovedQueriesEvents +@synthesize removedQueries; +@synthesize cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events { + self = [super init]; + if (self) { + self.removedQueries = removed; + self.cancelEvents = events; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h new file mode 100644 index 0000000..337f8d6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +@interface FTupleSetIdPath : NSObject + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath; + +@property(strong, nonatomic) NSNumber *setId; +@property(strong, nonatomic) FPath *path; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m new file mode 100644 index 0000000..2763c83 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleSetIdPath.h" + +@implementation FTupleSetIdPath + +@synthesize path; +@synthesize setId; + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.setId = aSetId; + self.path = aPath; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h new file mode 100644 index 0000000..0e3d7fa --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleStringNode : NSObject + +- (id)initWithString:(NSString *)aString andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) NSString *string; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m new file mode 100644 index 0000000..d820ef8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" + +@implementation FTupleStringNode + +@synthesize string; +@synthesize node; + +- (id)initWithString:(NSString *)aString andNode:(id)aNode { + self = [super init]; + if (self) { + self.string = aString; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h new file mode 100644 index 0000000..b1052da --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" +#import + +@interface FTupleTSN : NSObject + +@property(nonatomic, strong) FTupleStringNode *from; +@property(nonatomic, strong) FTupleStringNode *to; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m new file mode 100644 index 0000000..348c319 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTSN.h" + +@implementation FTupleTSN + +@synthesize from; +@synthesize to; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h new file mode 100644 index 0000000..82f4495 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@interface FTupleTransaction : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, copy) fbt_transactionresult_mutabledata update; +@property(nonatomic, copy) fbt_void_nserror_bool_datasnapshot onComplete; +@property(nonatomic) FTransactionStatus status; + +/** + * Used when combining transaction at different locations to figure out which + * one goes first. + */ +@property(nonatomic, strong) NSNumber *order; +/** + * Whether to raise local events for this transaction + */ +@property(nonatomic) BOOL applyLocally; + +/** + * Count how many times we've retried the transaction + */ +@property(nonatomic) int retryCount; + +/** + * Function to call to clean up our listener + */ +@property(nonatomic, copy) fbt_void_void unwatcher; + +/** + * Stores why a transaction was aborted + */ +@property(nonatomic, strong, readonly) NSString *abortStatus; +@property(nonatomic, strong, readonly) NSString *abortReason; + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason; +- (NSError *)abortError; + +@property(nonatomic, strong) NSNumber *currentWriteId; + +/** + * Stores the input snapshot, before the update + */ +@property(nonatomic, strong) id currentInputSnapshot; + +/** + * Stores the unresolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotRaw; + +/** + * Stores the resolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotResolved; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m new file mode 100644 index 0000000..68977ef --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTransaction.h" +#import "FUtilities.h" + +@interface FTupleTransaction () + +@property(nonatomic, strong) NSString *abortStatus; +@property(nonatomic, strong) NSString *abortReason; + +@end + +@implementation FTupleTransaction + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason { + self.abortStatus = abortStatus; + self.abortReason = reason; +} + +- (NSError *)abortError { + return (self.abortStatus != nil) + ? [FUtilities errorForStatus:self.abortStatus + andReason:self.abortReason] + : nil; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h new file mode 100644 index 0000000..b94eef6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FTypedefs.h" +#import + +@interface FTupleUserCallback : NSObject + +- (id)initWithHandle:(NSUInteger)handle; + +@property(nonatomic, copy) + fbt_void_datasnapshot_nsstring datasnapshotPrevnameCallback; +@property(nonatomic, copy) fbt_void_datasnapshot datasnapshotCallback; +@property(nonatomic, copy) fbt_void_nserror cancelCallback; +@property(nonatomic, copy) FQueryParams *queryParams; +@property(nonatomic) NSUInteger handle; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m new file mode 100644 index 0000000..ba5861f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleUserCallback.h" + +@implementation FTupleUserCallback + +@synthesize datasnapshotCallback; +@synthesize datasnapshotPrevnameCallback; +@synthesize cancelCallback; +@synthesize queryParams; +@synthesize handle; + +- (id)initWithHandle:(NSUInteger)theHandle { + self = [super init]; + if (self) { + self.handle = theHandle; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h new file mode 100644 index 0000000..3ab7476 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h @@ -0,0 +1,21 @@ +#import +#import "FImmutableSortedDictionary.h" + +/** + * This is an array backed implementation of FImmutableSortedDictionary. It uses arrays and linear lookups to achieve + * good memory efficiency while maintaining good performance for small collections. It also uses less allocations than + * a comparable red black tree. To avoid degrading performance with increasing collection size it will automatically + * convert to a FTreeSortedDictionary after an insert call above a certain threshold. + */ +@interface FArraySortedDictionary : FImmutableSortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (id)initWithComparator:(NSComparator)comparator; + +#pragma mark - +#pragma mark Properties + +@property (nonatomic, copy, readonly) NSComparator comparator; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m new file mode 100644 index 0000000..15d2d8b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m @@ -0,0 +1,266 @@ +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +@interface FArraySortedDictionaryEnumerator : NSEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse; +- (id)nextObject; + +@property (nonatomic) NSInteger pos; +@property (nonatomic) BOOL reverse; +@property (nonatomic, strong) NSArray *keys; + +@end + +@implementation FArraySortedDictionaryEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse +{ + self = [super init]; + if (self != nil) { + self->_pos = pos; + self->_reverse = reverse; + self->_keys = keys; + } + return self; +} + +- (id)nextObject +{ + NSInteger pos = self->_pos; + if (pos >= 0 && pos < self.keys.count) { + if (self.reverse) { + self->_pos--; + } else { + self->_pos++; + } + return self.keys[pos]; + } else { + return nil; + } +} + +@end + +@interface FArraySortedDictionary () + +- (id)initWithComparator:(NSComparator)comparator; + +@property (nonatomic, copy, readwrite) NSComparator comparator; +@property (nonatomic, strong) NSArray *keys; +@property (nonatomic, strong) NSArray *values; + +@end + +@implementation FArraySortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + NSMutableArray *keys = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [keys addObject:key]; + }]; + [keys sortUsingComparator:comparator]; + + [keys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(keys[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + NSMutableArray *values = [NSMutableArray arrayWithCapacity:keys.count]; + NSInteger pos = 0; + for (id key in keys) { + values[pos++] = dictionary[key]; + } + NSAssert(values.count == keys.count, @"We added as many keys as values"); + return [[FArraySortedDictionary alloc] initWithComparator:comparator keys:keys values:values]; +} + +- (id)initWithComparator:(NSComparator)comparator +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = [NSArray array]; + self->_values = [NSArray array]; + } + return self; +} + +- (id)initWithComparator:(NSComparator)comparator keys:(NSArray *)keys values:(NSArray *)values +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = keys; + self->_values = values; + } + return self; +} + +- (NSInteger) findInsertPositionForKey:(id)key +{ + NSInteger newPos = 0; + while (newPos < self.keys.count && self.comparator(self.keys[newPos], key) < NSOrderedSame) { + newPos++; + } + return newPos; +} + +- (NSInteger) findKey:(id)key +{ + if (key == nil) { + return NSNotFound; + } + for (NSInteger pos = 0; pos < self.keys.count; pos++) { + NSComparisonResult result = self.comparator(key, self.keys[pos]); + if (result == NSOrderedSame) { + return pos; + } else if (result == NSOrderedAscending) { + return NSNotFound; + } + } + return NSNotFound; +} + +- (FImmutableSortedDictionary *) insertKey:(id)key withValue:(id)value +{ + NSInteger pos = [self findKey:key]; + + if (pos == NSNotFound) { + /* + * If we're above the threshold we want to convert it to a tree backed implementation to not have + * degrading performance + */ + if (self.count >= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:self.count]; + for (NSInteger i = 0; i < self.keys.count; i++) { + dict[self.keys[i]] = self.values[i]; + } + dict[key] = value; + return [FTreeSortedDictionary fromDictionary:dict withComparator:self.comparator]; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + NSInteger newPos = [self findInsertPositionForKey:key]; + [newKeys insertObject:key atIndex:newPos]; + [newValues insertObject:value atIndex:newPos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + newKeys[pos] = key; + newValues[pos] = value; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (FImmutableSortedDictionary *) removeKey:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return self; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + [newKeys removeObjectAtIndex:pos]; + [newValues removeObjectAtIndex:pos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (id) get:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return nil; + } else { + return self.values[pos]; + } +} + +- (id) getPredecessorKey:(id) key { + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + [NSException raise:NSInternalInconsistencyException format:@"Can't get predecessor key for non-existent key"]; + return nil; + } else if (pos == 0) { + return nil; + } else { + return self.keys[pos - 1]; + } +} + +- (BOOL) isEmpty { + return self.keys.count == 0; +} + +- (int) count +{ + return (int)self.keys.count; +} + +- (id) minKey +{ + return [self.keys firstObject]; +} + +- (id) maxKey +{ + return [self.keys lastObject]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + BOOL stop = NO; + for (NSInteger i = self.keys.count - 1; i >= 0; i--) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } else { + BOOL stop = NO; + for (NSInteger i = 0; i < self.keys.count; i++) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } +} + +- (BOOL) contains:(id)key { + return [self findKey:key] != NSNotFound; +} + +- (NSEnumerator *) keyEnumerator { + return [self.keys objectEnumerator]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [self.keys reverseObjectEnumerator]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + // if there's no exact match, findKeyOrInsertPosition will return the index *after* the closest match, but + // since this is a reverse iterator, we want to start just *before* the closest match. + if (startPos >= self.keys.count || self.comparator(self.keys[startPos], startKey) != NSOrderedSame) { + startPos -= 1; + } + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:YES]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h new file mode 100644 index 0000000..d6687d8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h @@ -0,0 +1,54 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import + +/** + * The size threshold where we use a tree backed sorted map instead of an array backed sorted map. + * This is a more or less arbitrary chosen value, that was chosen to be large enough to fit most of object kind + * of Firebase data, but small enough to not notice degradation in performance for inserting and lookups. + * Feel free to empirically determine this constant, but don't expect much gain in real world performance. + */ +#define SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD 25 + +@interface FImmutableSortedDictionary : NSObject + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator; ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FImmutableSortedDictionary *) removeKey:(id)aKey; +- (id) get:(id) key; +- (id) getPredecessorKey:(id) key; +- (BOOL) isEmpty; +- (int) count; +- (id) minKey; +- (id) maxKey; +- (void) enumerateKeysAndObjectsUsingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (BOOL) contains:(id)key; +- (NSEnumerator *) keyEnumerator; +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey; +- (NSEnumerator *) reverseKeyEnumerator; +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey; + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(id)anObject forKey:(id)aKey; +- (id) objectForKey:(id)key; +- (FImmutableSortedDictionary *) removeObjectForKey:(id)aKey; + +@end + diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m new file mode 100644 index 0000000..659c63b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m @@ -0,0 +1,142 @@ +#import "FImmutableSortedDictionary.h" +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +#define THROW_ABSTRACT_METHOD_EXCEPTION(sel) do { \ + @throw [NSException exceptionWithName:NSInternalInconsistencyException \ + reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(sel)] \ + userInfo:nil]; \ +} while(0) + +@implementation FImmutableSortedDictionary + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator +{ + return [[FArraySortedDictionary alloc] initWithComparator:comparator]; +} + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + if (dictionary.count <= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + return [FArraySortedDictionary fromDictionary:dictionary withComparator:comparator]; + } else { + return [FTreeSortedDictionary fromDictionary:dictionary withComparator:comparator]; + } +} + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(insertKey:withValue:)); +} + +- (FImmutableSortedDictionary *) removeKey:(id)aKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(removeKey:)); +} + +- (id) get:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(get:)); +} + +- (id) getPredecessorKey:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(getPredecessorKey:)); +} + +- (BOOL) isEmpty { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(isEmpty)); +} + +- (int) count { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector((count))); +} + +- (id) minKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(minKey)); +} + +- (id) maxKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(maxKey)); +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsUsingBlock:)); +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsReverse:usingBlock:)); +} + +- (BOOL) contains:(id)key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(contains:)); +} + +- (NSEnumerator *) keyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumerator)); +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumeratorFrom:)); +} + +- (NSEnumerator *) reverseKeyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumerator)); +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumeratorFrom:)); +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableSortedDictionary class]]) { + return NO; + } + FImmutableSortedDictionary *other = (FImmutableSortedDictionary *)object; + if (self.count != other.count) { + return NO; + } + __block BOOL isEqual = YES; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + id otherValue = [other objectForKey:key]; + isEqual = isEqual && (value == otherValue || [value isEqual:otherValue]); + *stop = !isEqual; + }]; + return isEqual; +} + +- (NSUInteger)hash { + __block NSUInteger hash = 0; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + hash = (hash * 31 + [key hash]) * 17 + [value hash]; + }]; + return hash; +} + +- (NSString *)description { + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"{ "]; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@: %@", key, value]]; + }]; + [str appendString:@" }"]; + return str; +} + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(__unsafe_unretained id)anObject forKey:(__unsafe_unretained id)aKey { + return [self insertKey:aKey withValue:anObject]; +} + +- (FImmutableSortedDictionary *) removeObjectForKey:(__unsafe_unretained id)aKey { + return [self removeKey:aKey]; +} + +- (id) objectForKey:(__unsafe_unretained id)key { + return [self get:key]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h new file mode 100644 index 0000000..ac15c2f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h @@ -0,0 +1,22 @@ +#import + +@interface FImmutableSortedSet : NSObject + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)array comparator:(NSComparator)comparator; + +- (BOOL)containsObject:(id)object; +- (FImmutableSortedSet *)addObject:(id)object; +- (FImmutableSortedSet *)removeObject:(id)object; +- (id)firstObject; +- (id)lastObject; +- (NSUInteger)count; +- (BOOL)isEmpty; + +- (id)predecessorEntry:(id)entry; + +- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block; +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id obj, BOOL *stop))block; + +- (NSEnumerator *)objectEnumerator; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m new file mode 100644 index 0000000..1953af1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m @@ -0,0 +1,115 @@ +#import "FImmutableSortedSet.h" +#import "FImmutableSortedDictionary.h" + +@interface FImmutableSortedSet () + +@property (nonatomic, strong) FImmutableSortedDictionary *dictionary; + +@end + +@implementation FImmutableSortedSet + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)dictionary comparator:(NSComparator)comparator +{ + FImmutableSortedDictionary *setDict = [FImmutableSortedDictionary fromDictionary:dictionary withComparator:comparator]; + return [[FImmutableSortedSet alloc] initWithDictionary:setDict]; +} + +- (id)initWithDictionary:(FImmutableSortedDictionary *)dictionary +{ + self = [super init]; + if (self != nil) { + self->_dictionary = dictionary; + } + return self; +} + +- (BOOL)contains:(id)object +{ + return [self.dictionary contains:object]; +} + +- (FImmutableSortedSet *)addObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary insertKey:object withValue:[NSNull null]]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (FImmutableSortedSet *)removeObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary removeObjectForKey:object]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (BOOL)containsObject:(id)object +{ + return [self.dictionary contains:object]; +} + +- (id)firstObject +{ + return [self.dictionary minKey]; +} + +- (id)lastObject +{ + return [self.dictionary maxKey]; +} + +- (id)predecessorEntry:(id)entry +{ + return [self.dictionary getPredecessorKey:entry]; +} + +- (NSUInteger)count +{ + return [self.dictionary count]; +} + +- (BOOL)isEmpty +{ + return [self.dictionary isEmpty]; +} + +- (void)enumerateObjectsUsingBlock:(void (^)(id, BOOL *))block +{ + [self enumerateObjectsReverse:NO usingBlock:block]; +} + +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, BOOL *))block +{ + [self.dictionary enumerateKeysAndObjectsReverse:reverse usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; +} + +- (NSEnumerator *)objectEnumerator +{ + return [self.dictionary keyEnumerator]; +} + +- (NSString *)description +{ + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"FImmutableSortedSet ( "]; + [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@", obj]]; + }]; + [str appendString:@" )"]; + return str; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h new file mode 100644 index 0000000..833f2a5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h @@ -0,0 +1,27 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBEmptyNode : NSObject + ++ (id)emptyNode; + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m new file mode 100644 index 0000000..3ca6f06 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m @@ -0,0 +1,72 @@ +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" + +@implementation FLLRBEmptyNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + ++ (id)emptyNode +{ + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight { + return self; +} + +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator { + FLLRBValueNode* result = [[FLLRBValueNode alloc] initWithKey:aKey withValue:aValue withColor:nil withLeft:nil withRight:nil]; + return result; +} + +- (id) remove:(id) key withComparator:(NSComparator)aComparator { + return self; +} + +- (int) count { + return 0; +} + +- (BOOL) isEmpty { + return YES; +} + +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (id) min { + return self; +} + +- (id) minKey { + return nil; +} + +- (id) maxKey { + return nil; +} + +- (BOOL) isRed { + return NO; +} + +- (int) check { + return 0; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h new file mode 100644 index 0000000..09b234c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h @@ -0,0 +1,29 @@ +#import + +#define RED @true +#define BLACK @false + +typedef NSNumber FLLRBColor; + +@protocol FLLRBNode + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) key withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h new file mode 100644 index 0000000..50438bb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h @@ -0,0 +1,29 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBValueNode : NSObject + + +- (id)initWithKey:(id) key withValue:(id) value withColor:(FLLRBColor*) color withLeft:(id)left withRight:(id)right; +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +- (BOOL) checkMaxDepth; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m new file mode 100644 index 0000000..831b97f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m @@ -0,0 +1,230 @@ +#import "FLLRBValueNode.h" +#import "FLLRBEmptyNode.h" + +@implementation FLLRBValueNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + +- (id)initWithKey:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight +{ + self = [super init]; + if (self) { + self.key = aKey; + self.value = aValue; + self.color = aColor != nil ? aColor : RED; + self.left = aLeft != nil ? aLeft : [FLLRBEmptyNode emptyNode]; + self.right = aRight != nil ? aRight : [FLLRBEmptyNode emptyNode]; + } + return self; +} + +- (id)copyWith:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight { + return [[FLLRBValueNode alloc] initWithKey:(aKey != nil) ? aKey : self.key + withValue:(aValue != nil) ? aValue : self.value + withColor:(aColor != nil) ? aColor : self.color + withLeft:(aLeft != nil) ? aLeft : self.left + withRight:(aRight != nil) ? aRight : self.right]; +} + +- (int) count { + return [self.left count] + 1 + [self.right count]; +} + +- (BOOL) isEmpty { + return NO; +} + +/** +* Early terminates if aciton returns YES. +* @return The first truthy value returned by action, or the last falsey value returned by action. +*/ +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return [self.left inorderTraversal:action] || + action(self.key, self.value) || + [self.right inorderTraversal:action]; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return [self.right reverseTraversal:action] || + action(self.key, self.value) || + [self.left reverseTraversal:action]; +} + +- (id) min { + if([self.left isEmpty]) { + return self; + } + else { + return [self.left min]; + } +} + +- (id) minKey { + return [[self min] key]; +} + +- (id) maxKey { + if([self.right isEmpty]) { + return self.key; + } + else { + return [self.right maxKey]; + } +} + +- (id) insertKey:(__unsafe_unretained id) aKey forValue:(__unsafe_unretained id)aValue withComparator:(NSComparator)aComparator { + NSComparisonResult cmp = aComparator(aKey, self.key); + FLLRBValueNode* n = self; + + if(cmp == NSOrderedAscending) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left insertKey:aKey forValue:aValue withComparator:aComparator] withRight:nil]; + } + else if(cmp == NSOrderedSame) { + n = [n copyWith:nil withValue:aValue withColor:nil withLeft:nil withRight:nil]; + } + else { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right insertKey:aKey forValue:aValue withComparator:aComparator]]; + } + + return [n fixUp]; +} + +- (id) removeMin { + + if([self.left isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + + FLLRBValueNode* n = self; + if(! [n.left isRed] && ! [n.left.left isRed]) { + n = [n moveRedLeft]; + } + + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[(FLLRBValueNode*)n.left removeMin] withRight:nil]; + return [n fixUp]; +} + + +- (id) fixUp { + FLLRBValueNode* n = self; + if([n.right isRed] && ! [n.left isRed]) n = [n rotateLeft]; + if([n.left isRed] && [n.left.left isRed]) n = [n rotateRight]; + if([n.left isRed] && [n.right isRed]) n = [n colorFlip]; + return n; +} + +- (FLLRBValueNode*) moveRedLeft { + FLLRBValueNode* n = [self colorFlip]; + if([n.right.left isRed]) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right rotateRight]]; + n = [n rotateLeft]; + n = [n colorFlip]; + } + return n; +} + +- (FLLRBValueNode*) moveRedRight { + FLLRBValueNode* n = [self colorFlip]; + if([n.left.left isRed]) { + n = [n rotateRight]; + n = [n colorFlip]; + } + return n; +} + +- (id) rotateLeft { + id nl = [self copyWith:nil withValue:nil withColor:RED withLeft:nil withRight:self.right.left]; + return [self.right copyWith:nil withValue:nil withColor:self.color withLeft:nl withRight:nil];; +} + +- (id) rotateRight { + id nr = [self copyWith:nil withValue:nil withColor:RED withLeft:self.left.right withRight:nil]; + return [self.left copyWith:nil withValue:nil withColor:self.color withLeft:nil withRight:nr]; +} + +- (id) colorFlip { + id nleft = [self.left copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.left.color boolValue]] withLeft:nil withRight:nil]; + id nright = [self.right copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.right.color boolValue]] withLeft:nil withRight:nil]; + + return [self copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.color boolValue]] withLeft:nleft withRight:nright]; +} + +- (id) remove:(__unsafe_unretained id) aKey withComparator:(NSComparator)comparator { + id smallest; + FLLRBValueNode* n = self; + + if(comparator(aKey, n.key) == NSOrderedAscending) { + if(![n.left isEmpty] && ![n.left isRed] && ![n.left.left isRed]) { + n = [n moveRedLeft]; + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left remove:aKey withComparator:comparator] withRight:nil]; + } + else { + if([n.left isRed]) { + n = [n rotateRight]; + } + + if(![n.right isEmpty] && ![n.right isRed] && ![n.right.left isRed]) { + n = [n moveRedRight]; + } + + if(comparator(aKey, n.key) == NSOrderedSame) { + if([n.right isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + else { + smallest = [n.right min]; + n = [n copyWith:smallest.key withValue:smallest.value withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right removeMin]]; + } + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right remove:aKey withComparator:comparator]]; + } + return [n fixUp]; +} + +- (BOOL) isRed { + return [self.color boolValue]; +} + +- (BOOL) checkMaxDepth { + int blackDepth = [self check]; + if(pow(2.0, blackDepth) <= ([self count] + 1)) { + return YES; + } + else { + return NO; + } +} + +- (int) check { + int blackDepth = 0; + + if([self isRed] && [self.left isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Red node has a red child" userInfo:nil]; + } + + if([self.right isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Right child is red" userInfo:nil]; + } + + blackDepth = [self.left check]; +// NSLog(err); + if(blackDepth != [self.right check]) { + NSString* err = [NSString stringWithFormat:@"(%@ -> %@)blackDepth: %d ; self.right check: %d", self.value, [self.color boolValue] ? @"red" : @"black", blackDepth, [self.right check]]; +// return 10; + @throw [[NSException alloc] initWithName:@"check" reason:err userInfo:nil]; + } + else { + int ret = blackDepth + ([self isRed] ? 0 : 1); +// NSLog(@"black depth is: %d; other is: %d, ret is: %d", blackDepth, ([self isRed] ? 0 : 1), ret); + return ret; + } +} + + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h new file mode 100644 index 0000000..934ca8b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h @@ -0,0 +1,30 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import +#import "FImmutableSortedDictionary.h" +#import "FLLRBNode.h" + +@interface FTreeSortedDictionary : FImmutableSortedDictionary + +@property (nonatomic, copy, readonly) NSComparator comparator; +@property (nonatomic, strong, readonly) id root; + +- (id)initWithComparator:(NSComparator)aComparator; + +// Override methods to return subtype +- (FTreeSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FTreeSortedDictionary *) removeKey:(id)aKey; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m new file mode 100644 index 0000000..e9f0683 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m @@ -0,0 +1,326 @@ +#import "FTreeSortedDictionary.h" +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FTreeSortedDictionaryEnumerator.h" + +typedef void (^fbt_void_nsnumber_int)(NSNumber* color, NSUInteger chunkSize); + +@interface FTreeSortedDictionary () + +@property (nonatomic, strong) id root; +@property (nonatomic, copy, readwrite) NSComparator comparator; + +@end + +@implementation FTreeSortedDictionary + +- (id)initWithComparator:(NSComparator)aComparator { + self = [super init]; + if (self) { + self.root = [FLLRBEmptyNode emptyNode]; + self.comparator = aComparator; + } + return self; +} + +- (id)initWithComparator:(NSComparator)aComparator withRoot:(__unsafe_unretained id)aRoot { + self = [super init]; + if (self) { + self.root = aRoot; + self.comparator = aComparator; + } + return self; +} + +/** + * Returns a copy of the map, with the specified key/value added or replaced. + */ +- (FTreeSortedDictionary *) insertKey:(__unsafe_unretained id)aKey withValue:(__unsafe_unretained id)aValue { + return [[FTreeSortedDictionary alloc] initWithComparator:self.comparator + withRoot:[[self.root insertKey:aKey forValue:aValue withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; +} + + +- (FTreeSortedDictionary *) removeKey:(__unsafe_unretained id)aKey { + // Remove is somewhat expensive even if the key doesn't exist (the tree does rebalancing and stuff). So avoid it. + if (![self contains:aKey]) { + return self; + } else { + return [[FTreeSortedDictionary alloc] + initWithComparator:self.comparator + withRoot:[[self.root remove:aKey withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; + } +} + +- (id) get:(__unsafe_unretained id) key { + if (key == nil) { + return nil; + } + NSComparisonResult cmp; + id node = self.root; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + return node.value; + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else { + node = node.right; + } + } + return nil; +} + +- (id) getPredecessorKey:(__unsafe_unretained id) key { + NSComparisonResult cmp; + id node = self.root; + id rightParent = nil; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + if(![node.left isEmpty]) { + node = node.left; + while(! [node.right isEmpty]) { + node = node.right; + } + return node.key; + } + else if (rightParent != nil) { + return rightParent.key; + } + else { + return nil; + } + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else if (cmp == NSOrderedDescending) { + rightParent = node; + node = node.right; + } + } + @throw [NSException exceptionWithName:@"NonexistentKey" reason:@"getPredecessorKey called with nonexistent key." userInfo:@{@"key": [key description] }]; +} + +- (BOOL) isEmpty { + return [self.root isEmpty]; +} + +- (int) count { + return [self.root count]; +} + +- (id) minKey { + return [self.root minKey]; +} + +- (id) maxKey { + return [self.root maxKey]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + __block BOOL stop = NO; + [self.root reverseTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } else { + __block BOOL stop = NO; + [self.root inorderTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } +} + +- (BOOL) contains:(__unsafe_unretained id)key { + return ([self objectForKey:key] != nil); +} + +- (NSEnumerator *) keyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:NO]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:YES]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:YES]; +} + + +#pragma mark - +#pragma mark Tree Builder + +// Code to efficiently build a RB Tree +typedef struct _base1_2list { + unsigned int bits; + unsigned short count; + unsigned short current; +} Base1_2List; + +Base1_2List *base1_2List_new(unsigned int length); +void base1_2List_free(Base1_2List* list); +unsigned int log_base2(unsigned int num); +BOOL base1_2List_next(Base1_2List* list); + +unsigned int log_base2(unsigned int num) { + return (unsigned int)(log(num) / log(2)); +} + +/** + * Works like an iterator, so it moves to the next bit. Do not call more than list->count times. + * @return whether or not the next bit is a 1 in base {1,2}. + */ +BOOL base1_2List_next(Base1_2List* list) { + BOOL result = !(list->bits & (0x1 << list->current)); + list->current--; + return result; +} + +static inline unsigned bit_mask(int x) { + return (x >= sizeof(unsigned) * CHAR_BIT) ? (unsigned) -1 : (1U << x) - 1; +} + +/** + * We represent the base{1,2} number as the combination of a binary number and a number of bits that we care about + * We iterate backwards, from most significant bit to least, to build up the llrb nodes. 0 base 2 => 1 base {1,2}, 1 base 2 => 2 base {1,2} + */ +Base1_2List *base1_2List_new(unsigned int length) { + size_t sz = sizeof(Base1_2List); + Base1_2List* list = calloc(1, sz); + // Calculate the number of bits that we care about + list->count = (unsigned short)log_base2(length + 1); + unsigned int mask = bit_mask(list->count); + list->bits = (length + 1) & mask; + list->current = list->count - 1; + return list; +} + + +void base1_2List_free(Base1_2List* list) { + free(list); +} + ++ (id) buildBalancedTree:(NSArray *)keys dictionary:(NSDictionary *)dictionary subArrayStartIndex:(NSUInteger)startIndex length:(NSUInteger)length { + length = MIN(keys.count - startIndex, length); // Bound length by the actual length of the array + if (length == 0) { + return nil; + } else if (length == 1) { + id key = keys[startIndex]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:nil withRight:nil]; + } else { + NSUInteger middle = length / 2; + id left = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:startIndex length:middle]; + id right = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:(startIndex+middle+1) length:middle]; + id key = keys[startIndex + middle]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:left withRight:right]; + } +} + ++ (id) rootFrom12List:(Base1_2List *)base1_2List keyList:(NSArray *)keyList dictionary:(NSDictionary *)dictionary { + __block id root = nil; + __block id node = nil; + __block NSUInteger index = keyList.count; + + fbt_void_nsnumber_int buildPennant = ^(NSNumber* color, NSUInteger chunkSize) { + NSUInteger startIndex = index - chunkSize + 1; + index -= chunkSize; + id key = keyList[index]; + id childTree = [self buildBalancedTree:keyList dictionary:dictionary subArrayStartIndex:startIndex length:(chunkSize - 1)]; + id pennant = [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:color withLeft:nil withRight:childTree]; + //attachPennant(pennant); + if (node) { + node.left = pennant; + node = pennant; + } else { + root = pennant; + node = pennant; + } + }; + + for (int i = 0; i < base1_2List->count; ++i) { + BOOL isOne = base1_2List_next(base1_2List); + NSUInteger chunkSize = (NSUInteger)pow(2.0, base1_2List->count - (i + 1)); + if (isOne) { + buildPennant(BLACK, chunkSize); + } else { + buildPennant(BLACK, chunkSize); + buildPennant(RED, chunkSize); + } + } + return root; +} + +/** + * Uses the algorithm linked here: + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458 + */ + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + // Steps: + // 0. Sort the array + // 1. Calculate the 1-2 number + // 2. Build From 1-2 number + // 0. for each digit in 1-2 number + // 0. calculate chunk size + // 1. build 1 or 2 pennants of that size + // 2. attach pennants and update node pointer + // 1. return root + NSMutableArray *sortedKeyList = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [sortedKeyList addObject:key]; + }]; + [sortedKeyList sortUsingComparator:comparator]; + + [sortedKeyList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(sortedKeyList[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + Base1_2List* list = base1_2List_new((unsigned int)sortedKeyList.count); + id root = [self rootFrom12List:list keyList:sortedKeyList dictionary:dictionary]; + base1_2List_free(list); + + if (root != nil) { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator withRoot:root]; + } else { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator]; + } +} + +@end + diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h new file mode 100644 index 0000000..d79fe8e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h @@ -0,0 +1,9 @@ +#import +#import "FTreeSortedDictionary.h" + +@interface FTreeSortedDictionaryEnumerator : NSEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict startKey:(id)startKey isReverse:(BOOL)reverse; +- (id)nextObject; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m new file mode 100644 index 0000000..2aca86e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m @@ -0,0 +1,83 @@ +#import "FTreeSortedDictionaryEnumerator.h" + +@interface FTreeSortedDictionaryEnumerator() +@property (nonatomic, strong) FTreeSortedDictionary* immutableSortedDictionary; +@property (nonatomic, strong) NSMutableArray* stack; +@property (nonatomic) BOOL isReverse; + +@end + +@implementation FTreeSortedDictionaryEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict + startKey:(id)startKey isReverse:(BOOL)reverse { + self = [super init]; + if (self) { + self.immutableSortedDictionary = aDict; + self.stack = [[NSMutableArray alloc] init]; + self.isReverse = reverse; + + NSComparator comparator = aDict.comparator; + id node = self.immutableSortedDictionary.root; + + NSInteger cmp; + while(![node isEmpty]) { + cmp = startKey ? comparator(node.key, startKey) : 1; + // flip the comparison if we're going in reverse + if (self.isReverse) cmp *= -1; + + if (cmp < 0) { + // This node is less than our start key. Ignore it. + if (self.isReverse) { + node = node.left; + } else { + node = node.right; + } + } else if (cmp == 0) { + // This node is exactly equal to our start key. Push it on the stack, but stop iterating: + [self.stack addObject:node]; + break; + } else { + // This node is greater than our start key, add it to the stack and move on to the next one. + [self.stack addObject:node]; + if (self.isReverse) { + node = node.right; + } else { + node = node.left; + } + } + } + } + return self; +} + +- (id)nextObject { + if([self.stack count] == 0) { + return nil; + } + + id node = nil; + @synchronized(self.stack) { + node = [self.stack lastObject]; + [self.stack removeLastObject]; + } + id result = node.key; + + if (self.isReverse) { + node = node.left; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.right; + } + } else { + node = node.right; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.left; + } + } + + return result; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h new file mode 100644 index 0000000..1ca1815 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h @@ -0,0 +1,107 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import + +typedef enum { + SR_CONNECTING = 0, + SR_OPEN = 1, + SR_CLOSING = 2, + SR_CLOSED = 3, + +} FSRReadyState; + +@class FSRWebSocket; + +extern NSString *const FSRWebSocketErrorDomain; + +@protocol FSRWebSocketDelegate; + +@interface FSRWebSocket : NSObject + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, readonly) FSRReadyState readyState; +@property (nonatomic, readonly, retain) NSURL *url; + +// This returns the negotiated protocol. +// It will be niluntil after the handshake completes. +@property (nonatomic, readonly, copy) NSString *protocol; + +// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request; + +// Some helper constructors +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +- (id)initWithURL:(NSURL *)url; + +// Delegate queue will be dispatch_main_queue by default. +// You cannot set both OperationQueue and dispatch_queue. +- (void)setDelegateOperationQueue:(NSOperationQueue*) queue; +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; + +// By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes. +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; + +// SRWebSockets are intended one-time-use only. Open should be called once and only once +- (void)open; + +- (void)close; +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; + +// Send a UTF8 String or Data +- (void)send:(id)data; + +@end + +@protocol FSRWebSocketDelegate + +// message will either be an NSString if the server is using text +// or NSData if the server is using binary +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; + +@optional + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; + +@end + + +@interface NSURLRequest (FCertificateAdditions) + +@property (nonatomic, retain, readonly) NSArray *FSR_SSLPinnedCertificates; + +@end + + +@interface NSMutableURLRequest (FCertificateAdditions) + +@property (nonatomic, retain) NSArray *FSR_SSLPinnedCertificates; + +@end + +@interface NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m new file mode 100644 index 0000000..92d9d55 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m @@ -0,0 +1,1858 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FSRWebSocket.h" + +#if __has_include() +#define HAS_ICU +#endif + +#import + +#ifdef HAS_ICU +#import +#endif + +#if __has_include() +#import +#else +#import +#endif + +#import +#import +#import "fbase64.h" +#import "NSData+SRB64Additions.h" + +#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE +#define sr_dispatch_retain(x) +#define sr_dispatch_release(x) +#define maybe_bridge(x) ((__bridge void *) x) +#else +#define sr_dispatch_retain(x) dispatch_retain(x) +#define sr_dispatch_release(x) dispatch_release(x) +#define maybe_bridge(x) (x) +#endif + +typedef enum { + SROpCodeTextFrame = 0x1, + SROpCodeBinaryFrame = 0x2, + //3-7Reserved + SROpCodeConnectionClose = 0x8, + SROpCodePing = 0x9, + SROpCodePong = 0xA, + //B-F reserved +} FSROpCode; + +typedef enum { + SRStatusCodeNormal = 1000, + SRStatusCodeGoingAway = 1001, + SRStatusCodeProtocolError = 1002, + SRStatusCodeUnhandledType = 1003, + // 1004 reserved + SRStatusNoStatusReceived = 1005, + // 1004-1006 reserved + SRStatusCodeInvalidUTF8 = 1007, + SRStatusCodePolicyViolated = 1008, + SRStatusCodeMessageTooBig = 1009, +} FSRStatusCode; + +typedef struct { + BOOL fin; +// BOOL rsv1; +// BOOL rsv2; +// BOOL rsv3; + uint8_t opcode; + BOOL masked; + uint64_t payload_length; +} frame_header; + +static NSString *const SRWebSocketAppendToSecKeyString = @"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + +static inline int32_t validate_dispatch_data_partial_string(NSData *data); +static inline void SRFastLog(NSString *format, ...); + +@interface NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSURL (FSRWebSocket) + +// The origin isn't really applicable for a native application +// So instead, just map ws -> http and wss -> https +- (NSString *)SR_origin; + +@end + +@interface _FSRRunLoopThread : NSThread + +@property (nonatomic, readonly) NSRunLoop *runLoop; + +@end + +static NSString *newSHA1String(const char *bytes, size_t length) { + uint8_t md[CC_SHA1_DIGEST_LENGTH]; + + CC_SHA1(bytes, (int)length, md); + + size_t buffer_size = ((sizeof(md) * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(md, CC_SHA1_DIGEST_LENGTH, buffer, buffer_size); + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSASCIIStringEncoding freeWhenDone:YES]; + } +} + +@implementation NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.bytes, self.length); +} + +@end + + +@implementation NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.UTF8String, self.length); +} + +@end + +NSString *const FSRWebSocketErrorDomain = @"FSRWebSocketErrorDomain"; + +// Returns number of bytes consumed. returning 0 means you didn't match. +// Sends bytes to callback handler; +typedef size_t (^stream_scanner)(NSData *collected_data); + +typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data); + +@interface FSRIOConsumer : NSObject { + stream_scanner _scanner; + data_callback _handler; + size_t _bytesNeeded; + BOOL _readToCurrentFrame; + BOOL _unmaskBytes; +} +@property (nonatomic, copy, readonly) stream_scanner consumer; +@property (nonatomic, copy, readonly) data_callback handler; +@property (nonatomic, assign) size_t bytesNeeded; +@property (nonatomic, assign, readonly) BOOL readToCurrentFrame; +@property (nonatomic, assign, readonly) BOOL unmaskBytes; + +@end + +// This class is not thread-safe, and is expected to always be run on the same queue. +@interface FSRIOConsumerPool : NSObject + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)returnConsumer:(FSRIOConsumer *)consumer; + +@end + +@interface FSRWebSocket () + +- (void)_writeData:(NSData *)data; +- (void)_closeWithProtocolError:(NSString *)message; +- (void)_failWithError:(NSError *)error; + +- (void)_disconnect; + +- (void)_readFrameNew; +- (void)_readFrameContinue; + +- (void)_pumpScanner; + +- (void)_pumpWriting; + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +- (void)_SR_commonInit; + +- (void)_initializeStreams; +- (void)_connect; + +@property (nonatomic) FSRReadyState readyState; + +@property (nonatomic) NSOperationQueue *delegateOperationQueue; +@property (nonatomic) dispatch_queue_t delegateDispatchQueue; + +@end + + +@implementation FSRWebSocket { + NSInteger _webSocketVersion; + + NSOperationQueue *_delegateOperationQueue; + dispatch_queue_t _delegateDispatchQueue; + dispatch_queue_t _workQueue; + NSMutableArray *_consumers; + + NSInputStream *_inputStream; + NSOutputStream *_outputStream; + + NSMutableData *_readBuffer; + NSInteger _readBufferOffset; + + NSMutableData *_outputBuffer; + NSInteger _outputBufferOffset; + + uint8_t _currentFrameOpcode; + size_t _currentFrameCount; + size_t _readOpCount; + uint32_t _currentStringScanPosition; + NSMutableData *_currentFrameData; + + NSString *_closeReason; + + NSString *_secKey; + + BOOL _pinnedCertFound; + + uint8_t _currentReadMaskKey[4]; + size_t _currentReadMaskOffset; + + BOOL _consumerStopped; + + BOOL _closeWhenFinishedWriting; + BOOL _failed; + + BOOL _secure; + NSURLRequest *_urlRequest; + NSString *_userAgent; + + CFHTTPMessageRef _receivedHTTPHeaders; + + BOOL _sentClose; + BOOL _didFail; + BOOL _cleanupScheduled; + int _closeCode; + + BOOL _isPumping; + + NSMutableSet *_scheduledRunloops; + + // We use this to retain ourselves. + __strong FSRWebSocket *_selfRetain; + + NSArray *_requestedProtocols; + FSRIOConsumerPool *_consumerPool; +} + +@synthesize delegate = _delegate; +@synthesize url = _url; +@synthesize readyState = _readyState; +@synthesize protocol = _protocol; + +static __strong NSData *CRLFCRLF; + ++ (void)initialize; +{ + CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +{ + self = [super init]; + if (self) { + assert(request.URL); + _url = request.URL; + NSString *scheme = [_url scheme]; + + _requestedProtocols = [protocols copy]; + _userAgent = userAgent; + + assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]); + _urlRequest = request; + + if ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]) { + _secure = YES; + } + + if (!queue) { + _delegateDispatchQueue = dispatch_get_main_queue(); + } else { + _delegateDispatchQueue = queue; + } + + [self _SR_commonInit]; + } + + return self; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +{ + return [self initWithURLRequest:request protocols:nil queue:nil andUserAgent:nil]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +{ + return [self initWithURLRequest:request protocols:nil queue:queue andUserAgent:userAgent]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request; +{ + return [self initWithURLRequest:request protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url; +{ + return [self initWithURL:url protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +{ + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + return [self initWithURLRequest:request protocols:protocols]; +} + +- (void)_SR_commonInit; +{ + _readyState = SR_CONNECTING; + + _consumerStopped = YES; + + _webSocketVersion = 13; + + _workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + + // Going to set a specific on the queue so we can validate we're on the work queue + dispatch_queue_set_specific(_workQueue, (__bridge void *)self, maybe_bridge(_workQueue), NULL); + + sr_dispatch_retain(_delegateDispatchQueue); + + _readBuffer = [[NSMutableData alloc] init]; + _outputBuffer = [[NSMutableData alloc] init]; + + _currentFrameData = [[NSMutableData alloc] init]; + + _consumers = [[NSMutableArray alloc] init]; + + _consumerPool = [[FSRIOConsumerPool alloc] init]; + + _scheduledRunloops = [[NSMutableSet alloc] init]; + + [self _initializeStreams]; + + // default handlers +} + +- (void)assertOnWorkQueue; +{ + assert(dispatch_get_specific((__bridge void *)self) == maybe_bridge(_workQueue)); +} + +- (void)dealloc +{ + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + [_inputStream close]; + [_outputStream close]; + + sr_dispatch_release(_workQueue); + _workQueue = NULL; + + if (_receivedHTTPHeaders) { + CFRelease(_receivedHTTPHeaders); + _receivedHTTPHeaders = NULL; + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + _delegateDispatchQueue = NULL; + } +} + +#ifndef NDEBUG + +- (void)setReadyState:(FSRReadyState)aReadyState; +{ + [self willChangeValueForKey:@"readyState"]; + assert(aReadyState > _readyState); + _readyState = aReadyState; + [self didChangeValueForKey:@"readyState"]; +} + +#endif + +- (void)open; +{ + assert(_url); + NSAssert(_readyState == SR_CONNECTING, @"Cannot call -(void)open on SRWebSocket more than once"); + + _selfRetain = self; + + [self _connect]; +} + +// Calls block on delegate queue +- (void)_performDelegateBlock:(dispatch_block_t)block; +{ + if (_delegateOperationQueue) { + [_delegateOperationQueue addOperationWithBlock:block]; + } else { + assert(_delegateDispatchQueue); + dispatch_async(_delegateDispatchQueue, block); + } +} + +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; +{ + if (queue) { + sr_dispatch_retain(queue); + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + } + + _delegateDispatchQueue = queue; +} + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +{ + NSString *acceptHeader = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(httpMessage, CFSTR("Sec-WebSocket-Accept"))); + + if (acceptHeader == nil) { + return NO; + } + + NSString *concattedString = [_secKey stringByAppendingString:SRWebSocketAppendToSecKeyString]; + NSString *expectedAccept = [concattedString stringBySHA1ThenBase64Encoding]; + + return [acceptHeader isEqualToString:expectedAccept]; +} + +- (void)_HTTPHeadersDidFinish; +{ + NSInteger responseCode = CFHTTPMessageGetResponseStatusCode(_receivedHTTPHeaders); + + if (responseCode >= 400) { + SRFastLog(@"Request failed with response code %d", responseCode); + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2132 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"received bad response code from server %u", (int)responseCode] forKey:NSLocalizedDescriptionKey]]]; + return; + + } + + if(![self _checkHandshake:_receivedHTTPHeaders]) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Invalid Sec-WebSocket-Accept response"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + NSString *negotiatedProtocol = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(_receivedHTTPHeaders, CFSTR("Sec-WebSocket-Protocol"))); + if (negotiatedProtocol) { + // Make sure we requested the protocol + if ([_requestedProtocols indexOfObject:negotiatedProtocol] == NSNotFound) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Server specified Sec-WebSocket-Protocol that wasn't requested"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _protocol = negotiatedProtocol; + } + + self.readyState = SR_OPEN; + + if (!_didFail) { + [self _readFrameNew]; + } + + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocketDidOpen:)]) { + [self.delegate webSocketDidOpen:self]; + }; + }]; +} + + +- (void)_readHTTPHeader; +{ + if (_receivedHTTPHeaders == NULL) { + _receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO); + } + + [self _readUntilHeaderCompleteWithCallback:^(FSRWebSocket *self, NSData *data) { + CFHTTPMessageAppendBytes(self->_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length); + + if (CFHTTPMessageIsHeaderComplete(self->_receivedHTTPHeaders)) { + SRFastLog(@"Finished reading headers %@", CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(self->_receivedHTTPHeaders))); + [self _HTTPHeadersDidFinish]; + } else { + [self _readHTTPHeader]; + } + }]; +} + +- (void)didConnect +{ + SRFastLog(@"Connected"); + CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1); + + // Set host first so it defaults + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef) + (_url.port != nil ? [NSString stringWithFormat:@"%@:%@", + _url.host, _url.port] : _url.host)); + + NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16]; + int result = SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes); + assert(result == 0); + _secKey = [FSRUtilities base64EncodedStringFromData:keyBytes]; + assert([_secKey length] == 24); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Upgrade"), CFSTR("websocket")); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Upgrade")); + if (_userAgent) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("User-Agent"), (__bridge CFStringRef)_userAgent); + } + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%u", (int)_webSocketVersion]); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.SR_origin); + + if (_requestedProtocols) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]); + } + + [_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj); + }]; + + NSData *message = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(request)); + + CFRelease(request); + + [self _writeData:message]; + [self _readHTTPHeader]; +} + +//- (void)_connectToHost:(NSString *)host port:(NSInteger)port; +- (void)_initializeStreams; +{ + NSInteger port = _url.port.integerValue; + if (port == 0) { + if (!_secure) { + port = 80; + } else { + port = 443; + } + } + NSString *host = _url.host; + + CFReadStreamRef readStream = NULL; + CFWriteStreamRef writeStream = NULL; + + CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, (int)port, &readStream, &writeStream); + + // XXX + CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + + _outputStream = CFBridgingRelease(writeStream); + _inputStream = CFBridgingRelease(readStream); + + + if (_secure) { + NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init]; + + [_outputStream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel]; + + // If we're using pinned certs, don't validate the certificate chain + if ([_urlRequest FSR_SSLPinnedCertificates].count) { + [SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain]; + } + + [_outputStream setProperty:SSLOptions + forKey:(__bridge id)kCFStreamPropertySSLSettings]; + } + + _inputStream.delegate = self; + _outputStream.delegate = self; + + [_outputStream open]; + [_inputStream open]; +} + +- (void)_connect; +{ + if (!_scheduledRunloops.count) { + [self scheduleInRunLoop:[NSRunLoop FSR_networkRunLoop] forMode:NSDefaultRunLoopMode]; + } + + + [_outputStream open]; + [_inputStream open]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream scheduleInRunLoop:aRunLoop forMode:mode]; + [_inputStream scheduleInRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops addObject:@[aRunLoop, mode]]; +} + +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream removeFromRunLoop:aRunLoop forMode:mode]; + [_inputStream removeFromRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops removeObject:@[aRunLoop, mode]]; +} + +- (void)close; +{ + [self closeWithCode:-1 reason:nil]; +} + +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; +{ + assert(code); + dispatch_async(_workQueue, ^{ + if (self.readyState == SR_CLOSING || self.readyState == SR_CLOSED) { + return; + } + + BOOL wasConnecting = self.readyState == SR_CONNECTING; + + self.readyState = SR_CLOSING; + + SRFastLog(@"Closing with code %d reason %@", code, reason); + + if (wasConnecting) { + [self _disconnect]; + return; + } + + size_t maxMsgSize = [reason maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSMutableData *mutablePayload = [[NSMutableData alloc] initWithLength:sizeof(uint16_t) + maxMsgSize]; + NSData *payload = mutablePayload; + + ((uint16_t *)mutablePayload.mutableBytes)[0] = EndianU16_BtoN(code); + + if (reason) { + NSRange remainingRange = {0}; + + NSUInteger usedLength = 0; + + BOOL success = [reason getBytes:(char *)mutablePayload.mutableBytes + sizeof(uint16_t) maxLength:payload.length - sizeof(uint16_t) usedLength:&usedLength encoding:NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0, reason.length) remainingRange:&remainingRange]; + + assert(success); + assert(remainingRange.length == 0); + + if (usedLength != maxMsgSize) { + payload = [payload subdataWithRange:NSMakeRange(0, usedLength + sizeof(uint16_t))]; + } + } + + + [self _sendFrameWithOpcode:SROpCodeConnectionClose data:payload]; + }); +} + +- (void)_closeWithProtocolError:(NSString *)message; +{ + // Need to shunt this on the _callbackQueue first to see if they received any messages + [self _performDelegateBlock:^{ + [self closeWithCode:SRStatusCodeProtocolError reason:message]; + dispatch_async(self->_workQueue, ^{ + [self _disconnect]; + }); + }]; +} + +- (void)_failWithError:(NSError *)error; +{ + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self->_failed = YES; + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) { + [self.delegate webSocket:self didFailWithError:error]; + } + }]; + + self.readyState = SR_CLOSED; + + SRFastLog(@"Failing with error %@", error.localizedDescription); + + [self _disconnect]; + [self _scheduleCleanup]; + } + }); +} + +- (void)_writeData:(NSData *)data; +{ + [self assertOnWorkQueue]; + + if (_closeWhenFinishedWriting) { + return; + } + [_outputBuffer appendData:data]; + [self _pumpWriting]; +} +- (void)send:(id)data; +{ + SRFastLog(@"Sending data %@", data); + NSAssert(self.readyState != SR_CONNECTING, @"Invalid State: Cannot call send: until connection is open"); + // TODO: maybe not copy this for performance + data = [data copy]; + dispatch_async(_workQueue, ^{ + if ([data isKindOfClass:[NSString class]]) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:[(NSString *)data dataUsingEncoding:NSUTF8StringEncoding]]; + } else if ([data isKindOfClass:[NSData class]]) { + [self _sendFrameWithOpcode:SROpCodeBinaryFrame data:data]; + } else if (data == nil) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:data]; + } else { + assert(NO); + } + }); +} + +- (void)handlePing:(NSData *)pingData; +{ + // Need to pingpong this off _callbackQueue first to make sure messages happen in order + [self _performDelegateBlock:^{ + dispatch_async(self->_workQueue, ^{ + [self _sendFrameWithOpcode:SROpCodePong data:pingData]; + }); + }]; +} + +- (void)handlePong; +{ + // NOOP +} + +- (void)_handleMessage:(id)message +{ + SRFastLog(@"Received message"); + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)]) { + [self.delegate webSocket:self didReceiveMessage:message]; + } + }]; +} + + +static inline BOOL closeCodeIsValid(int closeCode) { + if (closeCode < 1000) { + return NO; + } + + if (closeCode >= 1000 && closeCode <= 1011) { + if (closeCode == 1004 || + closeCode == 1005 || + closeCode == 1006) { + return NO; + } + return YES; + } + + if (closeCode >= 3000 && closeCode <= 3999) { + return YES; + } + + if (closeCode >= 4000 && closeCode <= 4999) { + return YES; + } + + return NO; +} + +// Note from RFC: +// +// If there is a body, the first two +// bytes of the body MUST be a 2-byte unsigned integer (in network byte +// order) representing a status code with value /code/ defined in +// Section 7.4. Following the 2-byte integer the body MAY contain UTF-8 +// encoded data with value /reason/, the interpretation of which is not +// defined by this specification. + +- (void)handleCloseWithData:(NSData *)data; +{ + size_t dataSize = data.length; + __block uint16_t closeCode = 0; + + SRFastLog(@"Received close frame"); + + if (dataSize == 1) { + // TODO handle error + [self _closeWithProtocolError:@"Payload for close must be larger than 2 bytes"]; + return; + } else if (dataSize >= 2) { + [data getBytes:&closeCode length:sizeof(closeCode)]; + _closeCode = EndianU16_BtoN(closeCode); + if (!closeCodeIsValid(_closeCode)) { + [self _closeWithProtocolError:[NSString stringWithFormat:@"Cannot have close code of %d", _closeCode]]; + return; + } + if (dataSize > 2) { + _closeReason = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(2, dataSize - 2)] encoding:NSUTF8StringEncoding]; + if (!_closeReason) { + [self _closeWithProtocolError:@"Close reason MUST be valid UTF-8"]; + return; + } + } + } else { + _closeCode = SRStatusNoStatusReceived; + } + + [self assertOnWorkQueue]; + + if (self.readyState == SR_OPEN) { + [self closeWithCode:1000 reason:nil]; + } + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); +} + +- (void)_disconnect; +{ + [self assertOnWorkQueue]; + SRFastLog(@"Trying to disconnect"); + _closeWhenFinishedWriting = YES; + [self _pumpWriting]; +} + +- (void)_handleFrameWithData:(NSData *)frameData opCode:(NSInteger)opcode; +{ + // Check that the current data is valid UTF8 + + BOOL isControlFrame = (opcode == SROpCodePing || opcode == SROpCodePong || opcode == SROpCodeConnectionClose); + if (!isControlFrame) { + [self _readFrameNew]; + } else { + dispatch_async(_workQueue, ^{ + [self _readFrameContinue]; + }); + } + + switch (opcode) { + case SROpCodeTextFrame: { + NSString *str = [[NSString alloc] initWithData:frameData encoding:NSUTF8StringEncoding]; + if (str == nil && frameData) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + + return; + } + [self _handleMessage:str]; + break; + } + case SROpCodeBinaryFrame: + [self _handleMessage:[frameData copy]]; + break; + case SROpCodeConnectionClose: + [self handleCloseWithData:frameData]; + break; + case SROpCodePing: + [self handlePing:frameData]; + break; + case SROpCodePong: + [self handlePong]; + break; + default: + [self _closeWithProtocolError:[NSString stringWithFormat:@"Unknown opcode %u", (int)opcode]]; + // TODO: Handle invalid opcode + break; + } +} + +- (void)_handleFrameHeader:(frame_header)frame_header curData:(NSData *)curData; +{ + assert(frame_header.opcode != 0); + + if (self.readyState != SR_OPEN) { + return; + } + + + BOOL isControlFrame = (frame_header.opcode == SROpCodePing || frame_header.opcode == SROpCodePong || frame_header.opcode == SROpCodeConnectionClose); + + if (isControlFrame && !frame_header.fin) { + [self _closeWithProtocolError:@"Fragmented control frames not allowed"]; + return; + } + + if (isControlFrame && frame_header.payload_length >= 126) { + [self _closeWithProtocolError:@"Control frames cannot have payloads larger than 126 bytes"]; + return; + } + + if (!isControlFrame) { + _currentFrameOpcode = frame_header.opcode; + _currentFrameCount += 1; + } + + if (frame_header.payload_length == 0) { + if (isControlFrame) { + [self _handleFrameWithData:curData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + } + } else { + [self _addConsumerWithDataLength:(size_t)frame_header.payload_length callback:^(FSRWebSocket *self, NSData *newData) { + if (isControlFrame) { + [self _handleFrameWithData:newData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:self->_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + + } + } readToCurrentFrame:!isControlFrame unmaskBytes:frame_header.masked]; + } +} + +/* From RFC: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16/64) | + |N|V|V|V| |S| | (if payload len==126/127) | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Extended payload length continued, if payload len == 127 | + + - - - - - - - - - - - - - - - +-------------------------------+ + | |Masking-key, if MASK set to 1 | + +-------------------------------+-------------------------------+ + | Masking-key (continued) | Payload Data | + +-------------------------------- - - - - - - - - - - - - - - - + + : Payload Data continued ... : + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + | Payload Data continued ... | + +---------------------------------------------------------------+ + */ + +static const uint8_t SRFinMask = 0x80; +static const uint8_t SROpCodeMask = 0x0F; +static const uint8_t SRRsvMask = 0x70; +static const uint8_t SRMaskMask = 0x80; +static const uint8_t SRPayloadLenMask = 0x7F; + + +- (void)_readFrameContinue; +{ + assert((_currentFrameCount == 0 && _currentFrameOpcode == 0) || (_currentFrameCount > 0 && _currentFrameOpcode > 0)); + + [self _addConsumerWithDataLength:2 callback:^(FSRWebSocket *self, NSData *data) { + __block frame_header header = {0}; + + const uint8_t *headerBuffer = data.bytes; + assert(data.length >= 2); + + if (headerBuffer[0] & SRRsvMask) { + [self _closeWithProtocolError:@"Server used RSV bits"]; + return; + } + + uint8_t receivedOpcode = (SROpCodeMask & headerBuffer[0]); + + BOOL isControlFrame = (receivedOpcode == SROpCodePing || receivedOpcode == SROpCodePong || receivedOpcode == SROpCodeConnectionClose); + + if (!isControlFrame && receivedOpcode != 0 && self->_currentFrameCount > 0) { + [self _closeWithProtocolError:@"all data frames after the initial data frame must have opcode 0"]; + return; + } + + if (receivedOpcode == 0 && self->_currentFrameCount == 0) { + [self _closeWithProtocolError:@"cannot continue a message"]; + return; + } + + header.opcode = receivedOpcode == 0 ? self->_currentFrameOpcode : receivedOpcode; + + header.fin = !!(SRFinMask & headerBuffer[0]); + + + header.masked = !!(SRMaskMask & headerBuffer[1]); + header.payload_length = SRPayloadLenMask & headerBuffer[1]; + + headerBuffer = NULL; + + if (header.masked) { + [self _closeWithProtocolError:@"Client must receive unmasked data"]; + } + + size_t extra_bytes_needed = header.masked ? sizeof(self->_currentReadMaskKey) : 0; + + if (header.payload_length == 126) { + extra_bytes_needed += sizeof(uint16_t); + } else if (header.payload_length == 127) { + extra_bytes_needed += sizeof(uint64_t); + } + + if (extra_bytes_needed == 0) { + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } else { + [self _addConsumerWithDataLength:extra_bytes_needed callback:^(FSRWebSocket *self, NSData *data) { + size_t mapped_size = data.length; + const void *mapped_buffer = data.bytes; + size_t offset = 0; + + if (header.payload_length == 126) { + assert(mapped_size >= sizeof(uint16_t)); + uint16_t newLen = EndianU16_BtoN(*(uint16_t *)(mapped_buffer)); + header.payload_length = newLen; + offset += sizeof(uint16_t); + } else if (header.payload_length == 127) { + assert(mapped_size >= sizeof(uint64_t)); + header.payload_length = EndianU64_BtoN(*(uint64_t *)(mapped_buffer)); + offset += sizeof(uint64_t); + } else { + assert(header.payload_length < 126 && header.payload_length >= 0); + } + + + if (header.masked) { + assert(mapped_size >= sizeof(self->_currentReadMaskOffset) + offset); + memcpy(self->_currentReadMaskKey, ((uint8_t *)mapped_buffer) + offset, sizeof(self->_currentReadMaskKey)); + } + + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } readToCurrentFrame:NO unmaskBytes:NO]; + } + } readToCurrentFrame:NO unmaskBytes:NO]; +} + +- (void)_readFrameNew; +{ + dispatch_async(_workQueue, ^{ + [self->_currentFrameData setLength:0]; + + self->_currentFrameOpcode = 0; + self->_currentFrameCount = 0; + self->_readOpCount = 0; + self->_currentStringScanPosition = 0; + + [self _readFrameContinue]; + }); +} + +- (void)_pumpWriting; +{ + [self assertOnWorkQueue]; + + NSUInteger dataLength = _outputBuffer.length; + if (dataLength - _outputBufferOffset > 0 && _outputStream.hasSpaceAvailable) { + NSUInteger bytesWritten = [_outputStream write:_outputBuffer.bytes + _outputBufferOffset maxLength:dataLength - _outputBufferOffset]; + if (bytesWritten == -1) { + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2145 userInfo:[NSDictionary dictionaryWithObject:@"Error writing to stream" forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _outputBufferOffset += bytesWritten; + + if (_outputBufferOffset > 4096 && _outputBufferOffset > (_outputBuffer.length >> 1)) { + _outputBuffer = [[NSMutableData alloc] initWithBytes:(char *)_outputBuffer.bytes + _outputBufferOffset length:_outputBuffer.length - _outputBufferOffset]; + _outputBufferOffset = 0; + } + } + + if (_closeWhenFinishedWriting && + _outputBuffer.length - _outputBufferOffset == 0 && + (_inputStream.streamStatus != NSStreamStatusNotOpen && + _inputStream.streamStatus != NSStreamStatusClosed) && + !_sentClose) { + _sentClose = YES; + + @synchronized (self) { + [_outputStream close]; + [_inputStream close]; + + // TODO: Why are we missing the SocketRocket code to call unscheduleFromRunLoop??? + } + + if (!_failed) { + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:self->_closeCode reason:self->_closeReason wasClean:YES]; + } + }]; + } + [self _scheduleCleanup]; + } +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +{ + [self assertOnWorkQueue]; + [self _addConsumerWithScanner:consumer callback:callback dataLength:0]; +} + +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + [self assertOnWorkQueue]; + assert(dataLength); + + [_consumers addObject:[_consumerPool consumerWithScanner:nil handler:callback bytesNeeded:dataLength readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]]; + [self _pumpScanner]; +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +{ + [self assertOnWorkQueue]; + [_consumers addObject:[_consumerPool consumerWithScanner:consumer handler:callback bytesNeeded:dataLength readToCurrentFrame:NO unmaskBytes:NO]]; + [self _pumpScanner]; +} + + +- (void)_scheduleCleanup +{ + @synchronized(self) { + if (_cleanupScheduled) { + return; + } + + _cleanupScheduled = YES; + + // Cleanup NSStream delegate's in the same RunLoop used by the streams themselves: + // This way we'll prevent race conditions between handleEvent and SRWebsocket's dealloc + NSTimer *timer = [NSTimer timerWithTimeInterval:(0.0f) target:self selector:@selector(_cleanupSelfReference:) userInfo:nil repeats:NO]; + [[NSRunLoop FSR_networkRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; + } +} + +- (void)_cleanupSelfReference:(NSTimer *)timer +{ + @synchronized(self) { + // Nuke NSStream delegate's + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + // Remove the streams, right now, from the networkRunLoop + [_inputStream close]; + [_outputStream close]; + } + + // Cleanup selfRetain in the same GCD queue as usual + dispatch_async(_workQueue, ^{ + self->_selfRetain = nil; + }); +} + + +static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'}; + +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; +{ + [self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler]; +} + +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +{ + // TODO optimize so this can continue from where we last searched + stream_scanner consumer = ^size_t(NSData *data) { + __block size_t found_size = 0; + __block size_t match_count = 0; + + size_t size = data.length; + const unsigned char *buffer = data.bytes; + for (int i = 0; i < size; i++ ) { + if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) { + match_count += 1; + if (match_count == length) { + found_size = i + 1; + break; + } + } else { + match_count = 0; + } + } + return found_size; + }; + [self _addConsumerWithScanner:consumer callback:dataHandler]; +} + + +// Returns true if did work +- (BOOL)_innerPumpScanner { + + BOOL didWork = NO; + + if (self.readyState >= SR_CLOSING) { + return didWork; + } + + if (!_consumers.count) { + return didWork; + } + + size_t curSize = _readBuffer.length - _readBufferOffset; + if (!curSize) { + return didWork; + } + + FSRIOConsumer *consumer = [_consumers objectAtIndex:0]; + + size_t bytesNeeded = consumer.bytesNeeded; + + size_t foundSize = 0; + if (consumer.consumer) { + NSData *tempView = [NSData dataWithBytesNoCopy:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset freeWhenDone:NO]; + foundSize = consumer.consumer(tempView); + } else { + assert(consumer.bytesNeeded); + if (curSize >= bytesNeeded) { + foundSize = bytesNeeded; + } else if (consumer.readToCurrentFrame) { + foundSize = curSize; + } + } + + NSData *slice = nil; + if (consumer.readToCurrentFrame || foundSize) { + NSRange sliceRange = NSMakeRange(_readBufferOffset, foundSize); + slice = [_readBuffer subdataWithRange:sliceRange]; + + _readBufferOffset += foundSize; + + if (_readBufferOffset > 4096 && _readBufferOffset > (_readBuffer.length >> 1)) { + _readBuffer = [[NSMutableData alloc] initWithBytes:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset]; _readBufferOffset = 0; + } + + if (consumer.unmaskBytes) { + NSMutableData *mutableSlice = [slice mutableCopy]; + + NSUInteger len = mutableSlice.length; + uint8_t *bytes = mutableSlice.mutableBytes; + + for (int i = 0; i < len; i++) { + bytes[i] = bytes[i] ^ _currentReadMaskKey[_currentReadMaskOffset % sizeof(_currentReadMaskKey)]; + _currentReadMaskOffset += 1; + } + + slice = mutableSlice; + } + + if (consumer.readToCurrentFrame) { + [_currentFrameData appendData:slice]; + + _readOpCount += 1; + + if (_currentFrameOpcode == SROpCodeTextFrame) { + // Validate UTF8 stuff. + size_t currentDataSize = _currentFrameData.length; + if (_currentFrameOpcode == SROpCodeTextFrame && currentDataSize > 0) { + // TODO: Optimize the crap out of this. Don't really have to copy all the data each time + + size_t scanSize = currentDataSize - _currentStringScanPosition; + + NSData *scan_data = [_currentFrameData subdataWithRange:NSMakeRange(_currentStringScanPosition, scanSize)]; + int32_t valid_utf8_size = validate_dispatch_data_partial_string(scan_data); + + if (valid_utf8_size == -1) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + return didWork; + } else { + _currentStringScanPosition += valid_utf8_size; + } + } + + } + + consumer.bytesNeeded -= foundSize; + + if (consumer.bytesNeeded == 0) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, nil); + didWork = YES; + } + } else if (foundSize) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, slice); + didWork = YES; + } + } + return didWork; +} + +-(void)_pumpScanner; +{ + [self assertOnWorkQueue]; + + if (!_isPumping) { + _isPumping = YES; + } else { + return; + } + + while ([self _innerPumpScanner]) { + + } + + _isPumping = NO; +} + +//#define NOMASK + +static const size_t SRFrameHeaderOverhead = 32; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; +{ + [self assertOnWorkQueue]; + + if (data == nil) { + return; + } + + NSAssert([data isKindOfClass:[NSData class]] || [data isKindOfClass:[NSString class]], @"Function expects nil, NSString or NSData"); + + size_t payloadLength = [data isKindOfClass:[NSString class]] ? [(NSString *)data lengthOfBytesUsingEncoding:NSUTF8StringEncoding] : [data length]; + + NSMutableData *frame = [[NSMutableData alloc] initWithLength:payloadLength + SRFrameHeaderOverhead]; + if (!frame) { + [self closeWithCode:SRStatusCodeMessageTooBig reason:@"Message too big"]; + return; + } + uint8_t *frame_buffer = (uint8_t *)[frame mutableBytes]; + + // set fin + frame_buffer[0] = SRFinMask | opcode; + + BOOL useMask = YES; +#ifdef NOMASK + useMask = NO; +#endif + + if (useMask) { + // set the mask and header + frame_buffer[1] |= SRMaskMask; + } + + size_t frame_buffer_size = 2; + + const uint8_t *unmasked_payload = NULL; + if ([data isKindOfClass:[NSData class]]) { + unmasked_payload = (uint8_t *)[data bytes]; + } else if ([data isKindOfClass:[NSString class]]) { + unmasked_payload = (const uint8_t *)[data UTF8String]; + } else { + assert(NO); + } + + if (payloadLength < 126) { + frame_buffer[1] |= payloadLength; + } else if (payloadLength <= UINT16_MAX) { + frame_buffer[1] |= 126; + *((uint16_t *)(frame_buffer + frame_buffer_size)) = EndianU16_BtoN((uint16_t)payloadLength); + frame_buffer_size += sizeof(uint16_t); + } else { + frame_buffer[1] |= 127; + *((uint64_t *)(frame_buffer + frame_buffer_size)) = EndianU64_BtoN((uint64_t)payloadLength); + frame_buffer_size += sizeof(uint64_t); + } + + if (!useMask) { + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i]; + frame_buffer_size += 1; + } + } else { + uint8_t *mask_key = frame_buffer + frame_buffer_size; + int result = SecRandomCopyBytes(kSecRandomDefault, sizeof(uint32_t), (uint8_t *)mask_key); + assert(result == 0); + frame_buffer_size += sizeof(uint32_t); + + // TODO: could probably optimize this with SIMD + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i] ^ mask_key[i % sizeof(uint32_t)]; + frame_buffer_size += 1; + } + } + + assert(frame_buffer_size <= [frame length]); + frame.length = frame_buffer_size; + + [self _writeData:frame]; +} + +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode; +{ + __weak __typeof__(self) weakSelf = self; + + // turn on keep-alive for the output stream. + if (eventCode == NSStreamEventOpenCompleted && aStream == _outputStream) { + CFDataRef socketData = CFWriteStreamCopyProperty((CFWriteStreamRef)_outputStream, kCFStreamPropertySocketNativeHandle); + // In rare cases socketData might be nil (there are crash reports out there), in which case we'll have to just + // live without keep-alive :( + if (socketData != nil) { + CFSocketNativeHandle socket; + CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket); + CFRelease(socketData); + + int keepAliveOn = 1; + if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepAliveOn, sizeof(keepAliveOn)) == -1) { + SRFastLog(@"Failed to turn on TCP keepalive for websocket"); + } + } + } + + if (_secure && !_pinnedCertFound && (eventCode == NSStreamEventHasBytesAvailable || eventCode == NSStreamEventHasSpaceAvailable)) { + + NSArray *sslCerts = [_urlRequest FSR_SSLPinnedCertificates]; + if (sslCerts) { + SecTrustRef secTrust = (__bridge SecTrustRef)[aStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust]; + if (secTrust) { + NSInteger numCerts = SecTrustGetCertificateCount(secTrust); + for (NSInteger i = 0; i < numCerts && !_pinnedCertFound; i++) { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrust, i); + NSData *certData = CFBridgingRelease(SecCertificateCopyData(cert)); + + for (id ref in sslCerts) { + SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref; + NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert)); + + if ([trustedCertData isEqualToData:certData]) { + _pinnedCertFound = YES; + break; + } + } + } + } + + if (!_pinnedCertFound) { + dispatch_async(_workQueue, ^{ + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"Invalid server cert" }; + [weakSelf _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:23556 userInfo:userInfo]]; + }); + return; + } + } + } + + // SRFastLog(@"%@ Got stream event %d", aStream, eventCode); + dispatch_async(_workQueue, ^{ + [weakSelf safeHandleEvent:eventCode stream:aStream]; + }); +} + +- (void)safeHandleEvent:(NSStreamEvent)eventCode stream:(NSStream *)aStream +{ + switch (eventCode) { + case NSStreamEventOpenCompleted: { + SRFastLog(@"NSStreamEventOpenCompleted %@", aStream); + if (self.readyState >= SR_CLOSING) { + return; + } + + + assert(_readBuffer); + + if (self.readyState == SR_CONNECTING && aStream == _inputStream) { + [self didConnect]; + } + [self _pumpWriting]; + [self _pumpScanner]; + break; + } + + case NSStreamEventErrorOccurred: { + // Note: The upstream code for SocketRocket logs the error message, but this causes + // crashes on iOS 13 (https://github.com/firebase/firebase-ios-sdk/issues/3950) + SRFastLog(@"NSStreamEventErrorOccurred %@", aStream); + /// TODO specify error better! + [self _failWithError:aStream.streamError]; + _readBufferOffset = 0; + [_readBuffer setLength:0]; + break; + + } + + case NSStreamEventEndEncountered: { + [self _pumpScanner]; + SRFastLog(@"NSStreamEventEndEncountered %@", aStream); + if (aStream.streamError) { + [self _failWithError:aStream.streamError]; + } else { + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self.readyState = SR_CLOSED; + [self _scheduleCleanup]; + } + + if (!self->_sentClose && !self->_failed) { + self->_sentClose = YES; + // If we get closed in this state it's probably not clean because we should be sending this when we send messages + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:0 reason:@"Stream end encountered" wasClean:NO]; + } + }]; + } + }); + } + + break; + } + + case NSStreamEventHasBytesAvailable: { + SRFastLog(@"NSStreamEventHasBytesAvailable %@", aStream); + const NSUInteger bufferSize = 2048; + uint8_t buffer[bufferSize]; + + while (_inputStream.hasBytesAvailable) { + NSInteger bytes_read = [_inputStream read:buffer maxLength:bufferSize]; + + if (bytes_read > 0) { + [_readBuffer appendBytes:buffer length:bytes_read]; + } else if (bytes_read < 0) { + [self _failWithError:_inputStream.streamError]; + } + + if (bytes_read != bufferSize) { + break; + } + }; + [self _pumpScanner]; + break; + } + + case NSStreamEventHasSpaceAvailable: { + SRFastLog(@"NSStreamEventHasSpaceAvailable %@", aStream); + [self _pumpWriting]; + break; + } + + default: + SRFastLog(@"(default) %@", aStream); + break; + } +} + +@end + + +@implementation FSRIOConsumer + +@synthesize bytesNeeded = _bytesNeeded; +@synthesize consumer = _scanner; +@synthesize handler = _handler; +@synthesize readToCurrentFrame = _readToCurrentFrame; +@synthesize unmaskBytes = _unmaskBytes; + +- (void)setupWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + _scanner = [scanner copy]; + _handler = [handler copy]; + _bytesNeeded = bytesNeeded; + _readToCurrentFrame = readToCurrentFrame; + _unmaskBytes = unmaskBytes; + assert(_scanner || _bytesNeeded); +} + +@end + +@implementation FSRIOConsumerPool { + NSUInteger _poolSize; + NSMutableArray *_bufferedConsumers; +} + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; +{ + self = [super init]; + if (self) { + _poolSize = poolSize; + _bufferedConsumers = [[NSMutableArray alloc] initWithCapacity:poolSize]; + } + return self; +} + +- (id)init +{ + return [self initWithBufferCapacity:8]; +} + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + FSRIOConsumer *consumer = nil; + if (_bufferedConsumers.count) { + consumer = [_bufferedConsumers lastObject]; + [_bufferedConsumers removeLastObject]; + } else { + consumer = [[FSRIOConsumer alloc] init]; + } + + [consumer setupWithScanner:scanner handler:handler bytesNeeded:bytesNeeded readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]; + + return consumer; +} + +- (void)returnConsumer:(FSRIOConsumer *)consumer; +{ + if (_bufferedConsumers.count < _poolSize) { + [_bufferedConsumers addObject:consumer]; + } +} + +@end + +@implementation NSURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSMutableURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +- (void)setFSR_SSLPinnedCertificates:(NSArray *)FSR_SSLPinnedCertificates; +{ + [NSURLProtocol setProperty:FSR_SSLPinnedCertificates forKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSURL (FSRWebSocket) + +- (NSString *)SR_origin; +{ + NSString *scheme = [self.scheme lowercaseString]; + + if ([scheme isEqualToString:@"wss"]) { + scheme = @"https"; + } else if ([scheme isEqualToString:@"ws"]) { + scheme = @"http"; + } + + if (self.port != nil) { + return [NSString stringWithFormat:@"%@://%@:%@/", scheme, self.host, self.port]; + } else { + return [NSString stringWithFormat:@"%@://%@/", scheme, self.host]; + } +} + +@end + +// #define SR_ENABLE_LOG + +static inline void SRFastLog(NSString *format, ...) { +#ifdef SR_ENABLE_LOG + __block va_list arg_list; + va_start (arg_list, format); + + NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list]; + + va_end(arg_list); + + NSLog(@"[SR] %@", formattedString); +#endif +} + + +#ifdef HAS_ICU + +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + + const void * contents = [data bytes]; + long size = [data length]; + + const uint8_t *str = (const uint8_t *)contents; + + + UChar32 codepoint = 1; + int32_t offset = 0; + int32_t lastOffset = 0; + while(offset < size && codepoint > 0) { + lastOffset = offset; + U8_NEXT(str, offset, size, codepoint); + } + + if (codepoint == -1) { + // Check to see if the last byte is valid or whether it was just continuing + if (!U8_IS_LEAD(str[lastOffset]) || U8_COUNT_TRAIL_BYTES(str[lastOffset]) + lastOffset < (int32_t)size) { + + size = -1; + } else { + uint8_t leadByte = str[lastOffset]; + U8_MASK_LEAD_BYTE(leadByte, U8_COUNT_TRAIL_BYTES(leadByte)); + + for (int i = lastOffset + 1; i < offset; i++) { + + if (U8_IS_SINGLE(str[i]) || U8_IS_LEAD(str[i]) || !U8_IS_TRAIL(str[i])) { + size = -1; + } + } + + if (size != -1) { + size = lastOffset; + } + } + } + + if (size != -1 && ![[NSString alloc] initWithBytesNoCopy:(char *)[data bytes] length:size encoding:NSUTF8StringEncoding freeWhenDone:NO]) { + size = -1; + } + + return (int32_t)size; +} + +#else + +// This is a hack, and probably not optimal +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + static const int maxCodepointSize = 3; + + for (int i = 0; i < maxCodepointSize; i++) { + NSString *str = [[NSString alloc] initWithBytesNoCopy:(char *)data.bytes length:data.length - i encoding:NSUTF8StringEncoding freeWhenDone:NO]; + if (str) { + return (int)(data.length - i); + } + } + + return -1; +} + +#endif + +static _FSRRunLoopThread *networkThread = nil; +static NSRunLoop *networkRunLoop = nil; + +@implementation NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + networkThread = [[_FSRRunLoopThread alloc] init]; + networkThread.name = @"com.squareup.SocketRocket.NetworkThread"; + [networkThread start]; + networkRunLoop = networkThread.runLoop; + }); + + return networkRunLoop; +} + +@end + + +@implementation _FSRRunLoopThread { + dispatch_group_t _waitGroup; +} + +@synthesize runLoop = _runLoop; + +- (void)dealloc +{ + sr_dispatch_release(_waitGroup); +} + +- (id)init +{ + self = [super init]; + if (self) { + _waitGroup = dispatch_group_create(); + dispatch_group_enter(_waitGroup); + } + return self; +} + + +/** + * This is the main method of the thread on which the socket events are scheduled in a run loop. + */ +- (void)main; +{ + @autoreleasepool { + _runLoop = [NSRunLoop currentRunLoop]; + dispatch_group_leave(_waitGroup); + + // Add an empty run loop source to prevent runloop from spinning. + CFRunLoopSourceContext sourceCtx = { + .version = 0, + .info = NULL, + .retain = NULL, + .release = NULL, + .copyDescription = NULL, + .equal = NULL, + .hash = NULL, + .schedule = NULL, + .cancel = NULL, + .perform = NULL + }; + CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + CFRelease(source); + + while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { + + } + assert(NO); + } +} + +- (NSRunLoop *)runLoop; +{ + dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER); + return _runLoop; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h new file mode 100644 index 0000000..bac393b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h @@ -0,0 +1,23 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface FSRUtilities : NSObject + ++ (NSString *)base64EncodedStringFromData:(NSData *)data; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m new file mode 100644 index 0000000..2be1d84 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m @@ -0,0 +1,37 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "NSData+SRB64Additions.h" +#import "fbase64.h" + +@implementation FSRUtilities + ++ (NSString *)base64EncodedStringFromData:(NSData *)data { + size_t buffer_size = ((data.length * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(data.bytes, data.length, buffer, buffer_size); + + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSUTF8StringEncoding freeWhenDone:YES]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c new file mode 100644 index 0000000..238c23c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c @@ -0,0 +1,318 @@ +/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ + + +// +// Distributed with modifications by Firebase ( https://www.firebase.com ) +// + +#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "fbase64.h" + +static const char Base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) +int +f_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + u_int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int)(datalength); +} +#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ + +#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +f_b64_pton(char const *src, u_char *target, size_t targsize) +{ + u_int tarindex, state; + int ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + +#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h new file mode 100644 index 0000000..a9bf142 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h @@ -0,0 +1,33 @@ +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FSocketRocket_base64_h +#define FSocketRocket_base64_h + +#include + +extern int +f_b64_ntop(u_char const *src, + size_t srclength, + char *target, + size_t targsize); + +extern int +f_b64_pton(char const *src, + u_char *target, + size_t targsize); + + +#endif diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h new file mode 100644 index 0000000..c0baa22 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h @@ -0,0 +1,105 @@ +// +// APLevelDB.h +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +extern NSString * const APLevelDBErrorDomain; + +@class APLevelDBIterator; +@protocol APLevelDBWriteBatch; + +@interface APLevelDB : NSObject + +@property (nonatomic, readonly, strong) NSString *path; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing*)errorOut; +- (void)close; + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key; +- (BOOL)setString:(NSString *)str forKey:(NSString *)key; + +- (NSData *)dataForKey:(NSString *)key; +- (NSString *)stringForKey:(NSString *)key; + +- (BOOL)removeKey:(NSString *)key; + +- (NSArray *)allKeys; + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix usingBlock:(void (^)(NSString *key, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to; +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to; + +// Objective-C Subscripting Support: +// The database object supports subscripting for string-string and string-data key-value access and assignment. +// Examples: +// db[@"key"] = @"value"; +// db[@"key"] = [NSData data]; +// NSString *s = db[@"key"]; +// An NSInvalidArgumentException is raised if the key is not an NSString, or if the assigned object is not an +// instance of NSString or NSData. +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; + +// Batch write/atomic update support: +- (id)beginWriteBatch; + +@end + + +@interface APLevelDBIterator : NSObject + ++ (id)iteratorWithLevelDB:(APLevelDB *)db; + +// Designated initializer: +- (id)initWithLevelDB:(APLevelDB *)db; + +- (BOOL)seekToKey:(NSString *)key; +- (NSString *)nextKey; +- (NSString *)key; +- (NSString *)valueAsString; +- (NSData *)valueAsData; + +@end + + +@protocol APLevelDBWriteBatch + +- (void)setData:(NSData *)data forKey:(NSString *)key; +- (void)setString:(NSString *)str forKey:(NSString *)key; + +- (void)removeKey:(NSString *)key; + +// Remove all of the buffered sets and removes: +- (void)clear; +- (BOOL)commit; + +@end diff --git a/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm new file mode 100644 index 0000000..cdecce6 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm @@ -0,0 +1,500 @@ +// +// APLevelDB.m +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +// Portions of APLevelDB are based on LevelDB-ObjC: +// https://github.com/hoisie/LevelDB-ObjC +// Specifically the SliceFromString/StringFromSlice macros, and the structure of +// the enumeration methods. License for those potions follows: +// +// Copyright (c) 2011 Pave Labs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "APLevelDB.h" + +#import "leveldb/db.h" +#import "leveldb/options.h" +#import "leveldb/write_batch.h" + +NSString * const APLevelDBErrorDomain = @"APLevelDBErrorDomain"; + +#define SliceFromString(_string_) (leveldb::Slice((char *)[_string_ UTF8String], [_string_ lengthOfBytesUsingEncoding:NSUTF8StringEncoding])) +#define StringFromSlice(_slice_) ([[NSString alloc] initWithBytes:_slice_.data() length:_slice_.size() encoding:NSUTF8StringEncoding]) + + +@interface APLevelDBWriteBatch : NSObject { + @package + leveldb::WriteBatch _batch; +} + +@property (nonatomic, strong) APLevelDB *levelDB; + +- (id)initWithLevelDB:(APLevelDB *)levelDB; +@end + + +#pragma mark - APLevelDB + +@interface APLevelDB () { + leveldb::DB *_db; + leveldb::ReadOptions _readOptions; + leveldb::WriteOptions _writeOptions; +} +- (id)initWithPath:(NSString *)path error:(NSError **)errorOut; ++ (leveldb::Options)defaultCreateOptions; +@property (nonatomic, readonly) leveldb::DB *db; +@end + + +@implementation APLevelDB + +@synthesize path = _path; +@synthesize db = _db; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + return [[APLevelDB alloc] initWithPath:path error:errorOut]; +} + +- (id)initWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + if ((self = [super init])) + { + _path = path; + + leveldb::Options options = [[self class] defaultCreateOptions]; + + leveldb::Status status = leveldb::DB::Open(options, [_path UTF8String], &_db); + + if (!status.ok()) + { + if (errorOut) + { + NSString *statusString = [[NSString alloc] initWithCString:status.ToString().c_str() encoding:NSUTF8StringEncoding]; + *errorOut = [NSError errorWithDomain:APLevelDBErrorDomain + code:0 + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:statusString, NSLocalizedDescriptionKey, nil]]; + } + return nil; + } + + _writeOptions.sync = false; + } + return self; +} + +- (void)close { + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + +- (void)dealloc +{ + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + ++ (leveldb::Options)defaultCreateOptions +{ + leveldb::Options options; + options.create_if_missing = true; + return options; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (BOOL)setString:(NSString *)str forKey:(NSString *)key +{ + // This could have been based on + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (NSData *)dataForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + if (!status.ok()) + return nil; + else + return [NSData dataWithBytes:valueCPPString.data() length:valueCPPString.size()]; +} + +- (NSString *)stringForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + // We assume (dangerously?) UTF-8 string encoding: + if (!status.ok()) + return nil; + else + return [[NSString alloc] initWithBytes:valueCPPString.data() length:valueCPPString.size() encoding:NSUTF8StringEncoding]; +} + +- (BOOL)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Status status = _db->Delete(_writeOptions, keySlice); + return (status.ok() == true); +} + +- (NSArray *)allKeys +{ + NSMutableArray *keys = [NSMutableArray array]; + [self enumerateKeys:^(NSString *key, BOOL *stop) { + [keys addObject:key]; + }]; + return keys; +} + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asStrings:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asStrings:(void (^)(NSString *, NSString *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSString *v = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding]; + block(k, v, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" usingBlock:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString usingBlock:(void (^)(NSString *key, BOOL *stop))block; +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Slice prefix = SliceFromString(prefixString); + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + block(k, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *data, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asData:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asData:(void (^)(NSString *, NSData *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSData *data = [NSData dataWithBytes:value.data() length:value.size()]; + block(k, data, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to { + NSUInteger size = 0; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + iter->Seek(fromSlice); + while (iter->Valid() && iter->key().compare(toSlice) <= 0) { + size += iter->value().size(); + iter->Next(); + } + delete iter; + return size; +} + + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to { + leveldb::Range ranges[1]; + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + ranges[0] = leveldb::Range(fromSlice, toSlice); + uint64_t sizes[1]; + _db->GetApproximateSizes(ranges, 1, sizes); + return (NSUInteger)sizes[0]; +} + +#pragma mark - Subscripting Support + +- (id)objectForKeyedSubscript:(id)key +{ + if (![key respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be an NSString"]; + } + return [self stringForKey:key]; +} +- (void)setObject:(id)thing forKeyedSubscript:(id)key +{ + id idKey = (id) key; + if (![idKey respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be NSString or NSData"]; + } + + if ([thing respondsToSelector:@selector(componentsSeparatedByString:)]) + [self setString:thing forKey:(NSString *)key]; + else if ([thing respondsToSelector:@selector(subdataWithRange:)]) + [self setData:thing forKey:(NSString *)key]; + else + [NSException raise:NSInvalidArgumentException format:@"object must be NSString or NSData"]; +} + +#pragma mark - Atomic Updates + +- (id)beginWriteBatch +{ + APLevelDBWriteBatch *batch = [[APLevelDBWriteBatch alloc] initWithLevelDB:self]; + return batch; +} + +- (BOOL)commitWriteBatch:(id)theBatch +{ + if (!theBatch) + return NO; + + APLevelDBWriteBatch *batch = theBatch; + + leveldb::Status status; + status = _db->Write(_writeOptions, &batch->_batch); + return (status.ok() == true); +} + +@end + + +#pragma mark - APLevelDBIterator + +@interface APLevelDBIterator () { + leveldb::Iterator *_iter; +} + +@property (nonatomic, strong) APLevelDB *levelDB; +@end + + + +@implementation APLevelDBIterator + ++ (id)iteratorWithLevelDB:(APLevelDB *)db +{ + APLevelDBIterator *iter = [[[self class] alloc] initWithLevelDB:db]; + return iter; +} + +- (id)initWithLevelDB:(APLevelDB *)db +{ + if ((self = [super init])) + { + // Hold on to the database so it doesn't get deallocated before the iterator is deallocated + self->_levelDB = db; + _iter = db.db->NewIterator(leveldb::ReadOptions()); + _iter->SeekToFirst(); + if (!_iter->Valid()) + return nil; + } + return self; +} + +- (id)init +{ + [NSException raise:@"BadInitializer" format:@"Use the designated initializer, -initWithLevelDB:, instead."]; + return nil; +} + +- (void)dealloc +{ + self->_levelDB = nil; + delete _iter; + _iter = NULL; +} + +- (BOOL)seekToKey:(NSString *)key +{ + leveldb::Slice target = SliceFromString(key); + _iter->Seek(target); + return _iter->Valid() == true; +} + +- (void)seekToFirst +{ + _iter->SeekToFirst(); +} + +- (void)seekToLast +{ + _iter->SeekToLast(); +} + +- (NSString *)nextKey +{ + _iter->Next(); + return [self key]; +} + +- (NSString *)key +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->key(); + return StringFromSlice(value); +} + +- (NSString *)valueAsString +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return StringFromSlice(value); +} + +- (NSData *)valueAsData +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return [NSData dataWithBytes:value.data() length:value.size()]; +} + +@end + + + +#pragma mark - APLevelDBWriteBatch + +@implementation APLevelDBWriteBatch + +- (id)initWithLevelDB:(APLevelDB *)levelDB { + self = [super init]; + if (self != nil) { + self->_levelDB = levelDB; + } + return self; +} + +- (void)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + _batch.Put(keySlice, valueSlice); +} +- (void)setString:(NSString *)str forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + _batch.Put(keySlice, valueSlice); +} + +- (void)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + _batch.Delete(keySlice); +} + +- (void)clear +{ + _batch.Clear(); +} + +- (BOOL)commit { + return [self.levelDB commitWriteBatch:self]; +} + +@end + diff --git a/PediatricPancreas/Pods/FirebaseDatabase/LICENSE b/PediatricPancreas/Pods/FirebaseDatabase/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseDatabase/README.md b/PediatricPancreas/Pods/FirebaseDatabase/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseDatabase/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h new file mode 100644 index 0000000..5bc21a1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class FIRInstallationsHTTPError; + +NS_ASSUME_NONNULL_BEGIN + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer); + +@interface FIRInstallationsErrorUtil : NSObject + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception; ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error; + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status; + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName; + ++ (NSError *)JSONSerializationError:(NSError *)error; + ++ (NSError *)networkErrorWithError:(NSError *)error; + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName; + ++ (NSError *)corruptedIIDTokenData; + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data; ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode; + +/** + * Returns the passed error if it is already in the public domain or a new error with the passed + * error at `NSUnderlyingErrorKey`. + */ ++ (NSError *)publicDomainErrorWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m new file mode 100644 index 0000000..f85923a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m @@ -0,0 +1,124 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsErrorUtil.h" + +#import "FIRInstallationsHTTPError.h" + +NSString *const kFirebaseInstallationsErrorDomain = @"com.firebase.installations"; + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer) { + if (pointer != NULL) { + *pointer = error; + } +} + +@implementation FIRInstallationsErrorUtil + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"NSKeyedArchiver error."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:error]; +} + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status { + NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeKeychain + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *failureReason = + [NSString stringWithFormat:@"Installation for appID %@ appName %@ not found", appID, appName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)corruptedIIDTokenData { + NSString *failureReason = + @"IID token data stored in Keychain is corrupted or in an incompatible format."; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:HTTPResponse data:data]; +} + ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + return [(FIRInstallationsHTTPError *)error HTTPResponse].statusCode == HTTPCode; +} + ++ (NSError *)JSONSerializationError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"Failed to serialize JSON data."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName { + NSString *failureReason = [NSString + stringWithFormat:@"A required response field with name %@ is missing", missingFieldName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)networkErrorWithError:(NSError *)error { + return [self installationsErrorWithCode:FIRInstallationsErrorCodeServerUnreachable + failureReason:@"Network connection error." + underlyingError:error]; +} + ++ (NSError *)publicDomainErrorWithError:(NSError *)error { + if ([error.domain isEqualToString:kFirebaseInstallationsErrorDomain]) { + return error; + } + + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:nil + underlyingError:error]; +} + ++ (NSError *)installationsErrorWithCode:(FIRInstallationsErrorCode)code + failureReason:(nullable NSString *)failureReason + underlyingError:(nullable NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + userInfo[NSUnderlyingErrorKey] = underlyingError; + userInfo[NSLocalizedFailureReasonErrorKey] = failureReason; + + return [NSError errorWithDomain:kFirebaseInstallationsErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h new file mode 100644 index 0000000..ad0eb8c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Represents an error caused by an unexpected API response. */ +@interface FIRInstallationsHTTPError : NSError + +@property(nonatomic, readonly) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic, readonly, nonnull) NSData *data; + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse data:(nullable NSData *)data; + +@end + +NS_ASSUME_NONNULL_END + +typedef NS_ENUM(NSInteger, FIRInstallationsHTTPCodes) { + FIRInstallationsHTTPCodesTooManyRequests = 429, + FIRInstallationsHTTPCodesServerInternalError = 500, +}; + +/** Possible response HTTP codes for `CreateInstallation` API request. */ +typedef NS_ENUM(NSInteger, FIRInstallationsRegistrationHTTPCode) { + FIRInstallationsRegistrationHTTPCodeSuccess = 201, + FIRInstallationsRegistrationHTTPCodeInvalidArgument = 400, + FIRInstallationsRegistrationHTTPCodeInvalidAPIKey = 401, + FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch = 403, + FIRInstallationsRegistrationHTTPCodeProjectNotFound = 404, + FIRInstallationsRegistrationHTTPCodeTooManyRequests = 429, + FIRInstallationsRegistrationHTTPCodeServerInternalError = 500 +}; + +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenHTTPCode) { + FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication = 401, + FIRInstallationsAuthTokenHTTPCodeFIDNotFound = 404, +}; diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m new file mode 100644 index 0000000..5b3eae2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m @@ -0,0 +1,78 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsErrorUtil.h" + +@implementation FIRInstallationsHTTPError + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSDictionary *userInfo = [FIRInstallationsHTTPError userInfoWithHTTPResponse:HTTPResponse + data:data]; + self = [super + initWithDomain:kFirebaseInstallationsErrorDomain + code:[FIRInstallationsHTTPError errorCodeWithHTTPCode:HTTPResponse.statusCode] + userInfo:userInfo]; + if (self) { + _HTTPResponse = HTTPResponse; + _data = data; + } + return self; +} + ++ (FIRInstallationsErrorCode)errorCodeWithHTTPCode:(NSInteger)HTTPCode { + return FIRInstallationsErrorCodeUnknown; +} + ++ (NSDictionary *)userInfoWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSString *failureReason = [NSString + stringWithFormat:@"The server responded with an error. HTTP response: %@\nResponse body: %@", + HTTPResponse, responseString]; + return @{NSLocalizedFailureReasonErrorKey : failureReason}; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:self.HTTPResponse data:self.data]; +} + +#pragma mark - NSSecureCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)coder { + NSHTTPURLResponse *HTTPResponse = [coder decodeObjectOfClass:[NSHTTPURLResponse class] + forKey:@"HTTPResponse"]; + if (!HTTPResponse) { + return nil; + } + NSData *data = [coder decodeObjectOfClass:[NSData class] forKey:@"data"]; + + return [self initWithHTTPResponse:HTTPResponse data:data]; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.HTTPResponse forKey:@"HTTPResponse"]; + [coder encodeObject:self.data forKey:@"data"]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m new file mode 100644 index 0000000..71e7dd4 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m @@ -0,0 +1,248 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import +#import +#import +#import +#import + +#import "FIRInstallationsAuthTokenResultInternal.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIDController.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsVersion.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol FIRInstallationsInstanceProvider +@end + +@interface FIRInstallations () +@property(nonatomic, readonly) FIROptions *appOptions; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsIDController *installationsIDController; + +@end + +@implementation FIRInstallations + +#pragma mark - Firebase component + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-install" + withVersion:[NSString stringWithUTF8String:FIRInstallationsVersionStr]]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + FIRInstallations *installations = [[FIRInstallations alloc] initWithApp:container.app]; + return installations; + }; + + FIRComponent *installationsProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstallationsInstanceProvider) + instantiationTiming:FIRInstantiationTimingAlwaysEager + dependencies:@[] + creationBlock:creationBlock]; + return @[ installationsProvider ]; +} + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWitAppOptions:app.options appName:app.name]; +} + +- (instancetype)initWitAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + FIRInstallationsIDController *IDController = + [[FIRInstallationsIDController alloc] initWithGoogleAppID:appOptions.googleAppID + appName:appName + APIKey:appOptions.APIKey + projectID:appOptions.projectID + GCMSenderID:appOptions.GCMSenderID + accessGroup:appOptions.appGroupID]; + return [self initWithAppOptions:appOptions + appName:appName + installationsIDController:IDController + prefetchAuthToken:YES]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithAppOptions:(FIROptions *)appOptions + appName:(NSString *)appName + installationsIDController:(FIRInstallationsIDController *)installationsIDController + prefetchAuthToken:(BOOL)prefetchAuthToken { + self = [super init]; + if (self) { + [[self class] validateAppOptions:appOptions appName:appName]; + [[self class] assertCompatibleIIDVersion]; + + _appOptions = [appOptions copy]; + _appName = [appName copy]; + _installationsIDController = installationsIDController; + + // Pre-fetch auth token. + if (prefetchAuthToken) { + [self authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error){ + }]; + } + } + return self; +} + ++ (void)validateAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + NSMutableArray *missingFields = [NSMutableArray array]; + if (appName.length < 1) { + [missingFields addObject:@"`FirebaseApp.name`"]; + } + if (appOptions.APIKey.length < 1) { + [missingFields addObject:@"`FirebaseOptions.APIKey`"]; + } + if (appOptions.googleAppID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.googleAppID`"]; + } + + // TODO(#4692): Check for `appOptions.projectID.length < 1` only. + // We can use `GCMSenderID` instead of `projectID` temporary. + if (appOptions.projectID.length < 1 && appOptions.GCMSenderID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.projectID`"]; + } + + if (missingFields.count > 0) { + [NSException + raise:kFirebaseInstallationsErrorDomain + format: + @"%@[%@] Could not configure Firebase Installations due to invalid FirebaseApp " + @"options. The following parameters are nil or empty: %@. If you use " + @"GoogleServices-Info.plist please download the most recent version from the Firebase " + @"Console. If you configure Firebase in code, please make sure you specify all " + @"required parameters.", + kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseAppOptions, + [missingFields componentsJoinedByString:@", "]]; + } +} + +#pragma mark - Public + ++ (FIRInstallations *)installations { + FIRApp *defaultApp = [FIRApp defaultApp]; + if (!defaultApp) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"The default FirebaseApp instance must be configured before the default" + @"FirebaseApp instance can be initialized. One way to ensure that is to " + @"call `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) in the App" + @" Delegate's `application:didFinishLaunchingWithOptions:` " + @"(`application(_:didFinishLaunchingWithOptions:)` in Swift)."]; + } + + return [self installationsWithApp:defaultApp]; +} + ++ (FIRInstallations *)installationsWithApp:(FIRApp *)app { + id installations = + FIR_COMPONENT(FIRInstallationsInstanceProvider, app.container); + return (FIRInstallations *)installations; +} + +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion { + [self.installationsIDController getInstallationItem] + .then(^id(FIRInstallationsItem *installation) { + completion(installation.firebaseInstallationID, nil); + return nil; + }) + .catch(^(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion { + [self authTokenForcingRefresh:NO completion:completion]; +} + +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion { + [self.installationsIDController getAuthTokenForcingRefresh:forceRefresh] + .then(^FIRInstallationsAuthTokenResult *(FIRInstallationsItem *installation) { + FIRInstallationsAuthTokenResult *result = [[FIRInstallationsAuthTokenResult alloc] + initWithToken:installation.authToken.token + expirationDate:installation.authToken.expirationDate]; + return result; + }) + .then(^id(FIRInstallationsAuthTokenResult *token) { + completion(token, nil); + return nil; + }) + .catch(^void(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion { + [self.installationsIDController deleteInstallation] + .then(^id(id result) { + completion(nil); + return nil; + }) + .catch(^void(NSError *error) { + completion([FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +#pragma mark - IID version compatibility + ++ (void)assertCompatibleIIDVersion { + // We use this flag to disable IID compatibility exception for unit tests. +#ifdef FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION + return; +#else + if (![self isIIDVersionCompatible]) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"FirebaseInstallations will not work correctly with current version of " + @"Firebase Instance ID. Please update your Firebase Instance ID version."]; + } +#endif +} + ++ (BOOL)isIIDVersionCompatible { + Class IIDClass = NSClassFromString(@"FIRInstanceID"); + if (IIDClass == nil) { + // It is OK if there is no IID at all. + return YES; + } + // We expect a compatible version having the method `+[FIRInstanceID usesFIS]` defined. + BOOL isCompatibleVersion = [IIDClass respondsToSelector:NSSelectorFromString(@"usesFIS")]; + return isCompatibleVersion; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m new file mode 100644 index 0000000..92e5fab --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAuthTokenResultInternal.h" + +@implementation FIRInstallationsAuthTokenResult + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationDate { + self = [super init]; + if (self) { + _authToken = [token copy]; + _expirationDate = expirationDate; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h new file mode 100644 index 0000000..0c959db --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsAuthTokenResult (Internal) + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationTime; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h new file mode 100644 index 0000000..95fdf83 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredItem; +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class represents the required installation ID and auth token data including possible states. + * The data is stored to Keychain via `FIRInstallationsStoredItem` which has only the storage + * relevant data and does not contain any logic. `FIRInstallationsItem` must be used on the logic + * level (not `FIRInstallationsStoredItem`). + */ +@interface FIRInstallationsItem : NSObject + +/// A `FirebaseApp` identifier. +@property(nonatomic, readonly) NSString *appID; +/// A `FirebaseApp` name. +@property(nonatomic, readonly) NSString *firebaseAppName; +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic, assign) FIRInstallationsStatus registrationStatus; + +/// Instance ID default token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName; + +/** + * Populates `FIRInstallationsItem` properties with data from `FIRInstallationsStoredItem`. + * @param item An instance of `FIRInstallationsStoredItem` to get data from. + */ +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item; + +/** + * Creates a stored item with data from the object. + * @return Returns a `FIRInstallationsStoredItem` instance with the data from the object. + */ +- (FIRInstallationsStoredItem *)storedItem; + +/** + * The installation identifier. + * @return Returns a string uniquely identifying the installation. + */ +- (NSString *)identifier; + +/** + * The installation identifier. + * @param appID A `FirebaseApp` identifier. + * @param appName A `FirebaseApp` name. + * @return Returns a string uniquely identifying the installation. + */ ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName; + +/** + * Generate a new Firebase Installation Identifier. + * @return Returns a 22 characters long globally unique string created based on UUID. + */ ++ (NSString *)generateFID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m new file mode 100644 index 0000000..bc819bf --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m @@ -0,0 +1,104 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsStoredItem.h" + +@implementation FIRInstallationsItem + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName { + self = [super init]; + if (self) { + _appID = [appID copy]; + _firebaseAppName = [firebaseAppName copy]; + } + return self; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsItem *clone = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.firebaseAppName]; + clone.firebaseInstallationID = [self.firebaseInstallationID copy]; + clone.refreshToken = [self.refreshToken copy]; + clone.authToken = [self.authToken copy]; + clone.registrationStatus = self.registrationStatus; + + return clone; +} + +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item { + self.firebaseInstallationID = item.firebaseInstallationID; + self.refreshToken = item.refreshToken; + self.authToken = item.authToken; + self.registrationStatus = item.registrationStatus; + self.IIDDefaultToken = item.IIDDefaultToken; +} + +- (FIRInstallationsStoredItem *)storedItem { + FIRInstallationsStoredItem *storedItem = [[FIRInstallationsStoredItem alloc] init]; + storedItem.firebaseInstallationID = self.firebaseInstallationID; + storedItem.refreshToken = self.refreshToken; + storedItem.authToken = self.authToken; + storedItem.registrationStatus = self.registrationStatus; + storedItem.IIDDefaultToken = self.IIDDefaultToken; + return storedItem; +} + +- (nonnull NSString *)identifier { + return [[self class] identifierWithAppID:self.appID appName:self.firebaseAppName]; +} + ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName { + return [appID stringByAppendingString:appName]; +} + ++ (NSString *)generateFID { + NSUUID *UUID = [NSUUID UUID]; + uuid_t UUIDBytes; + [UUID getUUIDBytes:UUIDBytes]; + + NSUInteger UUIDLength = sizeof(uuid_t); + NSData *UUIDData = [NSData dataWithBytes:UUIDBytes length:UUIDLength]; + + uint8_t UUIDLast4Bits = UUIDBytes[UUIDLength - 1] & 0b00001111; + + // FID first 4 bits must be `0111`. The last 4 UUID bits will be cut later to form a proper FID. + // To keep 16 random bytes we copy these last 4 UUID to the FID 1st byte after `0111` prefix. + uint8_t FIDPrefix = 0b01110000 | UUIDLast4Bits; + NSMutableData *FIDData = [NSMutableData dataWithBytes:&FIDPrefix length:1]; + + [FIDData appendData:UUIDData]; + NSString *FIDString = [self base64URLEncodedStringWithData:FIDData]; + + // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5 bytes. + // Our generated ID has 16 bytes UUID + 1 byte prefix which after encoding with base64 will become + // 23 characters plus 1 character for "=" padding. + + // Remove the 23rd character that was added because of the extra 4 bits at the + // end of our 17 byte data and the '=' padding. + return [FIDString substringWithRange:NSMakeRange(0, 22)]; +} + ++ (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + return string; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h new file mode 100644 index 0000000..baeadb2 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +extern FIRLoggerService kFIRLoggerInstallations; + +// FIRInstallationsAPIService.m +extern NSString *const kFIRInstallationsMessageCodeSendAPIRequest; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeParsingAPIResponse; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed; + +// FIRInstallationsIDController.m +extern NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration; + +// FIRInstallationsStoredItem.m +extern NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch; + +// FIRInstallationsStoredAuthToken.m +extern NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch; + +// FIRInstallationsStoredIIDCheckin.m +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch; +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode; + +// FIRInstallations.m +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions; diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m new file mode 100644 index 0000000..c2bdf37 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsLogger.h" + +FIRLoggerService kFIRLoggerInstallations = @"[Firebase/Installations]"; + +// FIRInstallationsAPIService.m +NSString *const kFIRInstallationsMessageCodeSendAPIRequest = @"I-FIS001001"; +NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError = @"I-FIS001002"; +NSString *const kFIRInstallationsMessageCodeAPIRequestResponse = @"I-FIS001003"; +NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse = @"I-FIS001004"; +NSString *const kFIRInstallationsMessageCodeParsingAPIResponse = @"I-FIS001005"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed = @"I-FIS001006"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed = @"I-FIS001007"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed = @"I-FIS001008"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed = @"I-FIS001009"; + +// FIRInstallationsIDController.m +NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated = @"I-FIS002000"; +NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated = @"I-FIS002001"; +NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated = @"I-FIS002002"; +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration = @"I-FIS002003"; + +// FIRInstallationsStoredItem.m +NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch = @"I-FIS003000"; + +// FIRInstallationsStoredAuthToken.m +NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch = @"I-FIS004000"; + +// FIRInstallationsStoredIIDCheckin.m +NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch = @"I-FIS007000"; +NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode = @"I-FIS007001"; + +// FIRInstallations.m +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions = @"I-FIS008000"; diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m new file mode 100644 index 0000000..a75e3f5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m @@ -0,0 +1,23 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsVersion.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRInstallationsVersionStr = (const char *const)STR(FIRInstallations_LIB_VERSION); diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h new file mode 100644 index 0000000..e2408ca --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** The class encapsulates a port of a piece FirebaseInstanceID logic required to migrate IID. */ +@interface FIRInstallationsIIDStore : NSObject + +/** + * Retrieves existing IID if present. + * @return Returns a promise that is resolved with IID string if IID has been found or rejected with + * an error otherwise. + */ +- (FBLPromise *)existingIID; + +/** + * Deletes existing IID if present. + * @return Returns a promise that is resolved with `[NSNull null]` if the IID was successfully. + * deleted or was not found. The promise is rejected otherwise. + */ +- (FBLPromise *)deleteExistingIID; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m new file mode 100644 index 0000000..1f3a82a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m @@ -0,0 +1,236 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import "FIRInstallationsErrorUtil.h" + +static NSString *const kFIRInstallationsIIDKeyPairPublicTagPrefix = + @"com.google.iid.keypair.public-"; +static NSString *const kFIRInstallationsIIDKeyPairPrivateTagPrefix = + @"com.google.iid.keypair.private-"; +static NSString *const kFIRInstallationsIIDCreationTimePlistKey = @"|S|cre"; + +@implementation FIRInstallationsIIDStore + +- (FBLPromise *)existingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + if (![self hasPlistIIDFlag]) { + return nil; + } + + NSData *IIDPublicKeyData = [self IIDPublicKeyData]; + return [self IIDWithPublicKeyData:IIDPublicKeyData]; + }] + .validate(^BOOL(NSString *_Nullable IID) { + return IID.length > 0; + }); +} + +- (FBLPromise *)deleteExistingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + NSError *error; + if (![self deleteIIDFlagFromPlist:&error]) { + return error; + } + + if (![self deleteIID:&error]) { + return error; + } + + return [NSNull null]; + }]; +} + +#pragma mark - IID decoding + +- (NSString *)IIDWithPublicKeyData:(NSData *)publicKeyData { + NSData *publicKeySHA1 = [self sha1WithData:publicKeyData]; + + const uint8_t *bytes = publicKeySHA1.bytes; + NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1]; + + uint8_t b0 = bytes[0]; + // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0 + // and then adding 0x70 to it. + b0 = 0x70 + (0xF & b0); + // failsafe should give you back b0 itself + b0 = (b0 & 0xFF); + [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0]; + NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))]; + return [self base64URLEncodedStringWithData:data]; +} + +- (NSData *)sha1WithData:(NSData *)data { + unsigned char output[CC_SHA1_DIGEST_LENGTH]; + unsigned int length = (unsigned int)[data length]; + + CC_SHA1(data.bytes, length, output); + return [NSData dataWithBytes:output length:CC_SHA1_DIGEST_LENGTH]; +} + +- (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + string = [string stringByReplacingOccurrencesOfString:@"=" withString:@""]; + return string; +} + +#pragma mark - Keychain + +- (NSData *)IIDPublicKeyData { + NSString *tag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *query = [self keyPairQueryWithTag:tag returnData:YES]; + + CFTypeRef keyRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + return nil; + } + + return (__bridge NSData *)keyRef; +} + +- (BOOL)deleteIID:(NSError **)outError { + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix + error:outError]) { + return NO; + } + + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPrivateTagPrefix + error:outError]) { + return NO; + } + + return YES; +} + +- (BOOL)deleteKeychainKeyWithTagPrefix:(NSString *)tagPrefix error:(NSError **)outError { + NSString *keyTag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *keyQuery = [self keyPairQueryWithTag:keyTag returnData:NO]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keyQuery); + + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete" status:status], + outError); + return NO; + } + + return YES; +} + +- (NSDictionary *)keyPairQueryWithTag:(NSString *)tag returnData:(BOOL)shouldReturnData { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + query[(__bridge id)kSecClass] = (__bridge id)kSecClassKey; + query[(__bridge id)kSecAttrApplicationTag] = tagData; + query[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA; + if (shouldReturnData) { + query[(__bridge id)kSecReturnData] = @(YES); + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +- (NSString *)keychainKeyTagWithPrefix:(NSString *)prefix { + NSString *mainAppBundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (mainAppBundleID.length == 0) { + return nil; + } + return [NSString stringWithFormat:@"%@%@", prefix, mainAppBundleID]; +} + +- (NSString *)mainbundleIdentifier { + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleIdentifier.length) { + return nil; + } + return bundleIdentifier; +} + +#pragma mark - Plist + +- (BOOL)deleteIIDFlagFromPlist:(NSError **)outError { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return YES; + } + + NSMutableDictionary *plistContent = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; + plistContent[kFIRInstallationsIIDCreationTimePlistKey] = nil; + + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + return [plistContent writeToURL:[NSURL fileURLWithPath:path] error:outError]; + } + + return [plistContent writeToFile:path atomically:YES]; +} + +- (BOOL)hasPlistIIDFlag { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return NO; + } + + NSDictionary *plistContent = [[NSDictionary alloc] initWithContentsOfFile:path]; + return plistContent[kFIRInstallationsIIDCreationTimePlistKey] != nil; +} + +- (NSString *)plistPath { + NSString *plistNameWithExtension = @"com.google.iid-keypair.plist"; + NSString *_subDirectoryName = @"Google/FirebaseInstanceID"; + + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h new file mode 100644 index 0000000..ed98e3d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class reads a default IID token from IID store if available. + */ +@interface FIRInstallationsIIDTokenStore : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID; + +- (FBLPromise *)existingIIDDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m new file mode 100644 index 0000000..1c9dbab --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m @@ -0,0 +1,157 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDTokenStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsKeychainUtils.h" + +static NSString *const kFIRInstallationsIIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstallationsIIDTokenInfo : NSObject +@property(nonatomic, nullable, copy) NSString *token; +@end + +@implementation FIRInstallationsIIDTokenInfo + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)coder { +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { + self = [super init]; + if (self) { + _token = [coder decodeObjectOfClass:[NSString class] forKey:@"token"]; + } + return self; +} + +@end + +@interface FIRInstallationsIIDTokenStore () +@property(nonatomic, readonly) NSString *GCMSenderID; +@end + +@implementation FIRInstallationsIIDTokenStore + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + _GCMSenderID = GCMSenderID; + } + return self; +} + +- (FBLPromise *)existingIIDDefaultToken { + return [[FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + return [self IIDDefaultTokenData]; + }] onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + then:^id _Nullable(NSData *_Nullable keychainData) { + return [self IIDCheckinWithData:keychainData]; + }]; +} + +- (FBLPromise *)IIDCheckinWithData:(NSData *)data { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSError *archiverError; + NSKeyedUnarchiver *unarchiver; + if (@available(iOS 11.0, tvOS 11.0, macOS 10.13, *)) { + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&archiverError]; + } else { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + archiverError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + + if (!unarchiver) { + NSError *error = archiverError ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:error]; + return resultPromise; + } + + [unarchiver setClass:[FIRInstallationsIIDTokenInfo class] forClassName:@"FIRInstanceIDTokenInfo"]; + FIRInstallationsIIDTokenInfo *IIDTokenInfo = + [unarchiver decodeObjectOfClass:[FIRInstallationsIIDTokenInfo class] + forKey:NSKeyedArchiveRootObjectKey]; + + if (IIDTokenInfo.token.length < 1) { + [resultPromise reject:[FIRInstallationsErrorUtil corruptedIIDTokenData]]; + return resultPromise; + } + + [resultPromise fulfill:IIDTokenInfo.token]; + + return resultPromise; +} + +- (FBLPromise *)IIDDefaultTokenData { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSMutableDictionary *keychainQuery = [self IIDDefaultTokenDataKeychainQuery]; + NSError *error; + NSData *data = [FIRInstallationsKeychainUtils getItemWithQuery:keychainQuery error:&error]; + + if (data) { + [resultPromise fulfill:data]; + return resultPromise; + } else { + NSError *outError = error ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:outError]; + return resultPromise; + } +} + +- (NSMutableDictionary *)IIDDefaultTokenDataKeychainQuery { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + finalQuery[(__bridge NSString *)kSecAttrGeneric] = kFIRInstallationsIIDTokenKeychainId; + + NSString *account = [self IIDAppIdentifier]; + if ([account length]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + + finalQuery[(__bridge NSString *)kSecAttrService] = + [self serviceKeyForAuthorizedEntity:self.GCMSenderID scope:@"*"]; + return finalQuery; +} + +- (NSString *)IIDAppIdentifier { + return [[NSBundle mainBundle] bundleIdentifier] ?: @""; +} + +- (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h new file mode 100644 index 0000000..b45475d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstallationsUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstallationsHeartbeatKey; + +/** + * The class is responsible for interacting with HTTP REST API for Installations. + */ +@interface FIRInstallationsAPIService : NSObject + +/** + * The default initializer. + * @param APIKey The Firebase project API key (see `FIROptions.APIKey`). + * @param projectID The Firebase project ID (see `FIROptions.projectID`). + */ +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID; + +/** + * Sends a request to register a new FID to get auth and refresh tokens. + * @param installation The `FIRInstallationsItem` instance with the FID to register. + * @return A promise that is resolved with a new `FIRInstallationsItem` instance with valid tokens. + * It is rejected with an error in case of a failure. + */ +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation; + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation; + +/** + * Sends a request to delete the installation, related auth tokens and all related data from the + * server. + * @param installation The installation to delete. + * @return Returns a promise that is resolved with the passed installation on successful deletion or + * is rejected with an error otherwise. + */ +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m new file mode 100644 index 0000000..5bd7e3b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m @@ -0,0 +1,346 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAPIService.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem+RegisterInstallationAPI.h" +#import "FIRInstallationsLogger.h" + +NSString *const kFIRInstallationsAPIBaseURL = @"https://firebaseinstallations.googleapis.com"; +NSString *const kFIRInstallationsAPIKey = @"X-Goog-Api-Key"; +NSString *const kFIRInstallationsBundleId = @"X-Ios-Bundle-Identifier"; +NSString *const kFIRInstallationsIIDMigrationAuthHeader = @"x-goog-fis-ios-iid-migration-auth"; +NSString *const kFIRInstallationsHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstallationsHeartbeatTag = @"fire-installations"; +NSString *const kFIRInstallationsUserAgentKey = @"X-firebase-client"; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsURLSessionResponse : NSObject +@property(nonatomic) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic) NSData *data; + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data; +@end + +@implementation FIRInstallationsURLSessionResponse + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data { + self = [super init]; + if (self) { + _HTTPResponse = response; + _data = data ?: [NSData data]; + } + return self; +} + +@end + +@interface FIRInstallationsAPIService () +@property(nonatomic, readonly) NSURLSession *URLSession; +@property(nonatomic, readonly) NSString *APIKey; +@property(nonatomic, readonly) NSString *projectID; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstallationsAPIService + +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID { + NSURLSession *URLSession = [NSURLSession + sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + return [self initWithURLSession:URLSession APIKey:APIKey projectID:projectID]; +} + +/// The initializer for tests. +- (instancetype)initWithURLSession:(NSURLSession *)URLSession + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID { + self = [super init]; + if (self) { + _URLSession = URLSession; + _APIKey = [APIKey copy]; + _projectID = [projectID copy]; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation { + NSURLRequest *request = [self registerRequestWithInstallation:installation]; + return [self sendURLRequest:request].then( + ^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self registeredInstallationWithInstallation:installation serverResponse:response]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + NSURLRequest *request = [self authTokenRequestWithInstallation:installation]; + return [self sendURLRequest:request] + .then(^FBLPromise *( + FIRInstallationsURLSessionResponse *response) { + return [self authTokenWithServerResponse:response]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsStoredAuthToken *authToken) { + FIRInstallationsItem *updatedInstallation = [installation copy]; + updatedInstallation.authToken = authToken; + return updatedInstallation; + }); +} + +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation { + NSURLRequest *request = [self deleteInstallationRequestWithInstallation:installation]; + return [[self sendURLRequest:request] + then:^id _Nullable(FIRInstallationsURLSessionResponse *_Nullable value) { + // Return the original installation on success. + return installation; + }]; +} + +#pragma mark - Register Installation + +- (NSURLRequest *)registerRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/", + kFIRInstallationsAPIBaseURL, self.projectID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{ + @"fid" : installation.firebaseInstallationID, + @"authVersion" : @"FIS_v2", + @"appId" : installation.appID, + @"sdkVersion" : [self SDKVersion] + }; + + NSDictionary *headers; + if (installation.IIDDefaultToken) { + headers = @{kFIRInstallationsIIDMigrationAuthHeader : installation.IIDDefaultToken}; + } + + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:nil + additionalHeaders:headers]; +} + +- (FBLPromise *) + registeredInstallationWithInstallation:(FIRInstallationsItem *)installation + serverResponse:(FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsItem *registeredInstallation = + [installation registeredInstallationWithJSONData:response.data + date:[NSDate date] + error:&error]; + if (registeredInstallation == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed, + @"Failed to parse FIRInstallationsItem: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed, + @"FIRInstallationsItem parsed successfully."); + return registeredInstallation; + }]; +} + +#pragma mark - Auth token + +- (NSURLRequest *)authTokenRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = + [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/authTokens:generate", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{@"installation" : @{@"sdkVersion" : [self SDKVersion]}}; + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:installation.refreshToken]; +} + +- (FBLPromise *)authTokenWithServerResponse: + (FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsStoredAuthToken *token = + [FIRInstallationsItem authTokenWithGenerateTokenAPIJSONData:response.data + date:[NSDate date] + error:&error]; + if (token == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed, + @"Failed to parse FIRInstallationsStoredAuthToken: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed, + @"FIRInstallationsStoredAuthToken parsed successfully."); + return token; + }]; +} + +#pragma mark - Delete Installation + +- (NSURLRequest *)deleteInstallationRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + return [self requestWithURL:URL + HTTPMethod:@"DELETE" + bodyDict:@{} + refreshToken:installation.refreshToken]; +} + +#pragma mark - URL Request +- (NSURLRequest *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken { + return [self requestWithURL:requestURL + HTTPMethod:HTTPMethod + bodyDict:bodyDict + refreshToken:refreshToken + additionalHeaders:nil]; +} + +- (NSURLRequest *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken + additionalHeaders: + (nullable NSDictionary *)additionalHeaders { + __block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL]; + request.HTTPMethod = HTTPMethod; + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + [request addValue:self.APIKey forHTTPHeaderField:kFIRInstallationsAPIKey]; + [request addValue:bundleIdentifier forHTTPHeaderField:kFIRInstallationsBundleId]; + [self setJSONHTTPBody:bodyDict forRequest:request]; + if (refreshToken) { + NSString *authHeader = [NSString stringWithFormat:@"FIS_v2 %@", refreshToken]; + [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; + } + // User agent Header. + [request setValue:[FIRApp firebaseUserAgent] forHTTPHeaderField:kFIRInstallationsUserAgentKey]; + // Heartbeat Header. + [request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstallationsHeartbeatTag]) + .stringValue + forHTTPHeaderField:kFIRInstallationsHeartbeatKey]; + [additionalHeaders enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull key, NSString *_Nonnull obj, BOOL *_Nonnull stop) { + [request setValue:obj forHTTPHeaderField:key]; + }]; + + return [request copy]; +} + +- (FBLPromise *)URLRequestPromise:(NSURLRequest *)request { + return [[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeSendAPIRequest, + @"Sending request: %@, body:%@, headers: %@.", request, + [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding], + request.allHTTPHeaderFields); + [[self.URLSession + dataTaskWithRequest:request + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIRequestNetworkError, + @"Request failed: %@, error: %@.", request, error); + reject(error); + } else { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeAPIRequestResponse, + @"Request response received: %@, error: %@, body: %@.", request, error, + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + fulfill([[FIRInstallationsURLSessionResponse alloc] + initWithResponse:(NSHTTPURLResponse *)response + data:data]); + } + }] resume]; + }] then:^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self validateHTTPResponseStatusCode:response]; + }]; +} + +- (FBLPromise *)validateHTTPResponseStatusCode: + (FIRInstallationsURLSessionResponse *)response { + NSInteger statusCode = response.HTTPResponse.statusCode; + return [FBLPromise do:^id _Nullable { + if (statusCode < 200 || statusCode >= 300) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse, + @"Unexpected API response: %@, body: %@.", response.HTTPResponse, + [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]); + return [FIRInstallationsErrorUtil APIErrorWithHTTPResponse:response.HTTPResponse + data:response.data]; + } + return response; + }]; +} + +- (FBLPromise *)sendURLRequest:(NSURLRequest *)request { + return [FBLPromise attempts:1 + delay:1 + condition:^BOOL(NSInteger remainingAttempts, NSError *_Nonnull error) { + return [FIRInstallationsErrorUtil isAPIError:error withHTTPCode:500]; + } + retry:^id _Nullable { + return [self URLRequestPromise:request]; + }]; +} + +- (NSString *)SDKVersion { + return [NSString stringWithFormat:@"i:%s", FIRInstallationsVersionStr]; +} + +#pragma mark - JSON + +- (void)setJSONHTTPBody:(NSDictionary *)body + forRequest:(NSMutableURLRequest *)request { + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + + NSError *error; + NSData *JSONData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error]; + if (JSONData == nil) { + // TODO: Log or return an error. + } + request.HTTPBody = JSONData; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h new file mode 100644 index 0000000..cc6b543 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +@class FIRInstallationsStoredAuthToken; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsItem (RegisterInstallationAPI) + +/** + * Parses and validates the Register Installation API response and returns a corresponding + * `FIRInstallationsItem` instance on success. + * @param JSONData The data with JSON encoded API response. + * @param date The Auth Token expiration date will be calculated as `date` + + * `response.authToken.expiresIn`. For most of the cases `[NSDate date]` should be passed there. A + * different value may be passed e.g. for unit tests. + * @param outError A pointer to assign a specific `NSError` instance in case of failure. No error is + * assigned in case of success. + * @return Returns a new `FIRInstallationsItem` instance in the success case or `nil` otherwise. + */ +- (nullable FIRInstallationsItem *)registeredInstallationWithJSONData:(NSData *)JSONData + date:(NSDate *)date + error: + (NSError *_Nullable *)outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m new file mode 100644 index 0000000..569e35b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m @@ -0,0 +1,142 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem+RegisterInstallationAPI.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsStoredAuthToken.h" + +@implementation FIRInstallationsItem (RegisterInstallationAPI) + +- (nullable FIRInstallationsItem *) + registeredInstallationWithJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError *__autoreleasing _Nullable *_Nullable)outError { + NSDictionary *responseJSON = [FIRInstallationsItem dictionaryFromJSONData:data error:outError]; + if (!responseJSON) { + return nil; + } + + NSString *refreshToken = [FIRInstallationsItem validStringOrNilForKey:@"refreshToken" + fromDict:responseJSON]; + if (refreshToken == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"refreshToken"], + outError); + return nil; + } + + NSDictionary *authTokenDict = responseJSON[@"authToken"]; + if (![authTokenDict isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken"], + outError); + return nil; + } + + FIRInstallationsStoredAuthToken *authToken = + [FIRInstallationsItem authTokenWithJSONDict:authTokenDict date:date error:outError]; + if (authToken == nil) { + return nil; + } + + FIRInstallationsItem *installation = + [[FIRInstallationsItem alloc] initWithAppID:self.appID firebaseAppName:self.firebaseAppName]; + NSString *installationID = [FIRInstallationsItem validStringOrNilForKey:@"fid" + fromDict:responseJSON]; + installation.firebaseInstallationID = installationID ?: self.firebaseInstallationID; + installation.refreshToken = refreshToken; + installation.authToken = authToken; + installation.registrationStatus = FIRInstallationStatusRegistered; + + return installation; +} + +#pragma mark - Auth token + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError { + NSDictionary *dict = [self dictionaryFromJSONData:data error:outError]; + if (!dict) { + return nil; + } + + return [self authTokenWithJSONDict:dict date:date error:outError]; +} + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError { + NSString *token = [self validStringOrNilForKey:@"token" fromDict:dict]; + if (token == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken.token"], + outError); + return nil; + } + + NSString *expiresInString = [self validStringOrNilForKey:@"expiresIn" fromDict:dict]; + if (expiresInString == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil + FIDRegistrationErrorWithResponseMissingField:@"authToken.expiresIn"], + outError); + return nil; + } + + // The response should contain the string in format like "604800s". + // The server should never response with anything else except seconds. + // Just drop the last character and parse a number from string. + NSString *expiresInSeconds = [expiresInString substringToIndex:expiresInString.length - 1]; + NSTimeInterval expiresIn = [expiresInSeconds doubleValue]; + NSDate *expirationDate = [date dateByAddingTimeInterval:expiresIn]; + + FIRInstallationsStoredAuthToken *authToken = [[FIRInstallationsStoredAuthToken alloc] init]; + authToken.status = FIRInstallationsAuthTokenStatusTokenReceived; + authToken.token = token; + authToken.expirationDate = expirationDate; + + return authToken; +} + +#pragma mark - JSON + ++ (nullable NSDictionary *)dictionaryFromJSONData:(NSData *)data + error:(NSError **)outError { + NSError *error; + NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + + if (![responseJSON isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer([FIRInstallationsErrorUtil JSONSerializationError:error], + outError); + return nil; + } + + return responseJSON; +} + ++ (NSString *)validStringOrNilForKey:(NSString *)key fromDict:(NSDictionary *)dict { + NSString *string = dict[key]; + if ([string isKindOfClass:[NSString class]] && string.length > 0) { + return string; + } + return nil; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h new file mode 100644 index 0000000..ab2092d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBLPromise; +@class FIRInstallationsItem; + +/** + * The class is responsible for managing FID for a given `FIRApp`. + */ +@interface FIRInstallationsIDController : NSObject + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(nullable NSString *)accessGroup; + +- (FBLPromise *)getInstallationItem; + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh; + +- (FBLPromise *)deleteInstallation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m new file mode 100644 index 0000000..1982a57 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m @@ -0,0 +1,458 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIDController.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import + +#import "FIRInstallationsAPIService.h" +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIIDStore.h" +#import "FIRInstallationsIIDTokenStore.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsSingleOperationPromiseCache.h" +#import "FIRInstallationsStore.h" +#import "FIRSecureStorage.h" + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsStoredAuthToken.h" + +const NSNotificationName FIRInstallationIDDidChangeNotification = + @"FIRInstallationIDDidChangeNotification"; +NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey = + @"FIRInstallationIDDidChangeNotification"; + +NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 hour. + +@interface FIRInstallationsIDController () +@property(nonatomic, readonly) NSString *appID; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsStore *installationsStore; +@property(nonatomic, readonly) FIRInstallationsIIDStore *IIDStore; +@property(nonatomic, readonly) FIRInstallationsIIDTokenStore *IIDTokenStore; + +@property(nonatomic, readonly) FIRInstallationsAPIService *APIService; + +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *getInstallationPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *authTokenPromiseCache; +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *authTokenForcingRefreshPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *deleteInstallationPromiseCache; +@end + +@implementation FIRInstallationsIDController + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(NSString *)accessGroup { + FIRSecureStorage *secureStorage = [[FIRSecureStorage alloc] init]; + FIRInstallationsStore *installationsStore = + [[FIRInstallationsStore alloc] initWithSecureStorage:secureStorage accessGroup:accessGroup]; + + // Use `GCMSenderID` as project identifier when `projectID` is not available. + NSString *APIServiceProjectID = (projectID.length > 0) ? projectID : GCMSenderID; + FIRInstallationsAPIService *apiService = + [[FIRInstallationsAPIService alloc] initWithAPIKey:APIKey projectID:APIServiceProjectID]; + + FIRInstallationsIIDStore *IIDStore = [[FIRInstallationsIIDStore alloc] init]; + FIRInstallationsIIDTokenStore *IIDCheckingStore = + [[FIRInstallationsIIDTokenStore alloc] initWithGCMSenderID:GCMSenderID]; + + return [self initWithGoogleAppID:appID + appName:appName + installationsStore:installationsStore + APIService:apiService + IIDStore:IIDStore + IIDTokenStore:IIDCheckingStore]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + installationsStore:(FIRInstallationsStore *)installationsStore + APIService:(FIRInstallationsAPIService *)APIService + IIDStore:(FIRInstallationsIIDStore *)IIDStore + IIDTokenStore:(FIRInstallationsIIDTokenStore *)IIDTokenStore { + self = [super init]; + if (self) { + _appID = appID; + _appName = appName; + _installationsStore = installationsStore; + _APIService = APIService; + _IIDStore = IIDStore; + _IIDTokenStore = IIDTokenStore; + + __weak FIRInstallationsIDController *weakSelf = self; + + _getInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createGetInstallationItemPromise]; + }]; + + _authTokenPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:NO]; + }]; + + _authTokenForcingRefreshPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:YES]; + }]; + + _deleteInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createDeleteInstallationPromise]; + }]; + } + return self; +} + +#pragma mark - Get Installation. + +- (FBLPromise *)getInstallationItem { + return [self.getInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createGetInstallationItemPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewGetInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + FBLPromise *installationItemPromise = + [self getStoredInstallation].recover(^id(NSError *error) { + return [self createAndSaveFID]; + }); + + // Initiate registration process on success if needed, but return the installation without waiting + // for it. + installationItemPromise.then(^id(FIRInstallationsItem *installation) { + [self getAuthTokenForcingRefresh:NO]; + return nil; + }); + + return installationItemPromise; +} + +- (FBLPromise *)getStoredInstallation { + return [self.installationsStore installationForAppID:self.appID appName:self.appName].validate( + ^BOOL(FIRInstallationsItem *installation) { + BOOL isValid = NO; + switch (installation.registrationStatus) { + case FIRInstallationStatusUnregistered: + case FIRInstallationStatusRegistered: + isValid = YES; + break; + + case FIRInstallationStatusUnknown: + isValid = NO; + break; + } + + return isValid; + }); +} + +- (FBLPromise *)createAndSaveFID { + return [self migrateOrGenerateInstallation] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self saveInstallation:installation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *installation) { + [self postFIDDidChangeNotification]; + return installation; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installation { + return [self.installationsStore saveInstallation:installation].then( + ^FIRInstallationsItem *(NSNull *result) { + return installation; + }); +} + +/** + * Tries to migrate IID data stored by FirebaseInstanceID SDK or generates a new Installation ID if + * not found. + */ +- (FBLPromise *)migrateOrGenerateInstallation { + if (![self isDefaultApp]) { + // Existing IID should be used only for default FirebaseApp. + FIRInstallationsItem *installation = + [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + return [FBLPromise resolvedWith:installation]; + } + + return [[[FBLPromise + all:@[ [self.IIDStore existingIID], [self.IIDTokenStore existingIIDDefaultToken] ]] + then:^id _Nullable(NSArray *_Nullable results) { + NSString *existingIID = results[0]; + NSString *IIDDefaultToken = results[1]; + + return [self createInstallationWithFID:existingIID IIDDefaultToken:IIDDefaultToken]; + }] recover:^id _Nullable(NSError *_Nonnull error) { + return [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + }]; +} + +- (FIRInstallationsItem *)createInstallationWithFID:(NSString *)FID + IIDDefaultToken:(nullable NSString *)IIDDefaultToken { + FIRInstallationsItem *installation = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.appName]; + installation.firebaseInstallationID = FID; + installation.IIDDefaultToken = IIDDefaultToken; + installation.registrationStatus = FIRInstallationStatusUnregistered; + return installation; +} + +#pragma mark - FID registration + +- (FBLPromise *)registerInstallationIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusRegistered: + // Already registered. Do nothing. + return [FBLPromise resolvedWith:installation]; + + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // Registration required. Proceed. + break; + } + + return [self.APIService registerInstallation:installation] + .catch(^(NSError *_Nonnull error) { + if ([self doesRegistrationErrorRequireConfigChange:error]) { + FIRLogError(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInvalidFirebaseConfiguration, + @"Firebase Installation registration failed for app with name: %@, error: " + @"%@\nPlease make sure you use valid GoogleService-Info.plist", + self.appName, error); + } + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + return [self saveInstallation:registeredInstallation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *registeredInstallation) { + // Server may respond with a different FID if the sent one cannot be accepted. + if (![registeredInstallation.firebaseInstallationID + isEqualToString:installation.firebaseInstallationID]) { + [self postFIDDidChangeNotification]; + } + return registeredInstallation; + }); +} + +- (BOOL)doesRegistrationErrorRequireConfigChange:(NSError *)error { + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + if (![HTTPError isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + switch (HTTPError.HTTPResponse.statusCode) { + // These are the errors that require Firebase configuration change. + case FIRInstallationsRegistrationHTTPCodeInvalidArgument: + case FIRInstallationsRegistrationHTTPCodeInvalidAPIKey: + case FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch: + case FIRInstallationsRegistrationHTTPCodeProjectNotFound: + return YES; + + default: + return NO; + } +} + +#pragma mark - Auth Token + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh { + if (forceRefresh || [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] != nil) { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingOrCreateNewPromise]; + } else { + return [self.authTokenPromiseCache getExistingPendingOrCreateNewPromise]; + } +} + +- (FBLPromise *)installationWithValidAuthTokenForcingRefresh: + (BOOL)forceRefresh { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated, + @"-[FIRInstallationsIDController installationWithValidAuthTokenForcingRefresh:%@], " + @"appName: %@", + @(forceRefresh), self.appName); + + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self registerInstallationIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + BOOL isTokenExpiredOrExpiresSoon = + [registeredInstallation.authToken.expirationDate timeIntervalSinceDate:[NSDate date]] < + kFIRInstallationsTokenExpirationThreshold; + if (forceRefresh || isTokenExpiredOrExpiresSoon) { + return [self refreshAuthTokenForInstallation:registeredInstallation]; + } else { + return registeredInstallation; + } + }) + .recover(^id(NSError *error) { + return [self regenerateFIDOnRefreshTokenErrorIfNeeded:error]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + return [[self.APIService refreshAuthTokenForInstallation:installation] + then:^id _Nullable(FIRInstallationsItem *_Nullable refreshedInstallation) { + return [self saveInstallation:refreshedInstallation]; + }]; +} + +- (id)regenerateFIDOnRefreshTokenErrorIfNeeded:(NSError *)error { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + // No recovery possible. Return the same error. + return error; + } + + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + switch (HTTPError.HTTPResponse.statusCode) { + case FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication: + case FIRInstallationsAuthTokenHTTPCodeFIDNotFound: + // The stored installation was damaged or blocked by the server. + // Delete the stored installation then generate and register a new one. + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self deleteInstallationLocally:installation]; + }) + .then(^FBLPromise *(id result) { + return [self installationWithValidAuthTokenForcingRefresh:NO]; + }); + + default: + // No recovery possible. Return the same error. + return error; + } +} + +#pragma mark - Delete FID + +- (FBLPromise *)deleteInstallation { + return [self.deleteInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createDeleteInstallationPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + // Check for ongoing requests first, if there is no a request, then check local storage for + // existing installation. + FBLPromise *currentInstallationPromise = + [self mostRecentInstallationOperation] ?: [self getStoredInstallation]; + + return currentInstallationPromise + .then(^id(FIRInstallationsItem *installation) { + return [self sendDeleteInstallationRequestIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *installation) { + // Remove the installation from the local storage. + return [self deleteInstallationLocally:installation]; + }); +} + +- (FBLPromise *)deleteInstallationLocally:(FIRInstallationsItem *)installation { + return [self.installationsStore removeInstallationForAppID:installation.appID + appName:installation.firebaseAppName] + .then(^FBLPromise *(NSNull *result) { + return [self deleteExistingIIDIfNeeded]; + }) + .then(^NSNull *(NSNull *result) { + [self postFIDDidChangeNotification]; + return result; + }); +} + +- (FBLPromise *)sendDeleteInstallationRequestIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // The installation is not registered, so it is safe to be deleted as is, so return early. + return [FBLPromise resolvedWith:installation]; + break; + + case FIRInstallationStatusRegistered: + // Proceed to de-register the installation on the server. + break; + } + + return [self.APIService deleteInstallation:installation].recover(^id(NSError *APIError) { + if ([FIRInstallationsErrorUtil isAPIError:APIError withHTTPCode:404]) { + // The installation was not found on the server. + // Return success. + return installation; + } else { + // Re-throw the error otherwise. + return APIError; + } + }); +} + +- (FBLPromise *)deleteExistingIIDIfNeeded { + if ([self isDefaultApp]) { + return [self.IIDStore deleteExistingIID]; + } else { + return [FBLPromise resolvedWith:[NSNull null]]; + } +} + +- (nullable FBLPromise *)mostRecentInstallationOperation { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] + ?: [self.authTokenPromiseCache getExistingPendingPromise] + ?: [self.getInstallationPromiseCache getExistingPendingPromise]; +} + +#pragma mark - Notifications + +- (void)postFIDDidChangeNotification { + [[NSNotificationCenter defaultCenter] + postNotificationName:FIRInstallationIDDidChangeNotification + object:nil + userInfo:@{kFIRInstallationIDDidChangeNotificationAppNameKey : self.appName}]; +} + +#pragma mark - Default App + +- (BOOL)isDefaultApp { + return [self.appName isEqualToString:kFIRDefaultAppName]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h new file mode 100644 index 0000000..aeb54e5 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class makes sure the a single operation (represented by a promise) is performed at a time. If + * there is an ongoing operation, then its existing corresponding promise will be returned instead + * of starting a new operation. + */ +@interface FIRInstallationsSingleOperationPromiseCache<__covariant ResultType> : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The designated initializer. + * @param newOperationHandler The block that must return a new promise representing the + * single-at-a-time operation. The promise should be fulfilled when the operation is completed. The + * factory block will be used to create a new promise when needed. + */ +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler NS_DESIGNATED_INITIALIZER; + +/** + * Creates a new promise or returns an existing pending one. + * @return Returns and existing pending promise if exists. If the pending promise does not exist + * then a new one will be created using the `factory` block passed in the initializer. Once the + * pending promise gets resolved, it is removed, so calling the method again will lead to creating + * and caching another promise. + */ +- (FBLPromise *)getExistingPendingOrCreateNewPromise; + +/** + * Returns an existing pending promise or `nil`. + * @return Returns an existing pending promise if there is one or `nil` otherwise. + */ +- (nullable FBLPromise *)getExistingPendingPromise; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m new file mode 100644 index 0000000..dfccfe3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsSingleOperationPromiseCache.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +@interface FIRInstallationsSingleOperationPromiseCache () +@property(nonatomic, readonly) FBLPromise *_Nonnull (^newOperationHandler)(void); +@property(nonatomic, nullable) FBLPromise *pendingPromise; +@end + +@implementation FIRInstallationsSingleOperationPromiseCache + +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler { + if (newOperationHandler == nil) { + [NSException raise:NSInvalidArgumentException + format:@"`newOperationHandler` must not be `nil`."]; + } + + self = [super init]; + if (self) { + _newOperationHandler = [newOperationHandler copy]; + } + return self; +} + +- (FBLPromise *)getExistingPendingOrCreateNewPromise { + @synchronized(self) { + if (!self.pendingPromise) { + self.pendingPromise = self.newOperationHandler(); + + self.pendingPromise + .then(^id(id result) { + @synchronized(self) { + self.pendingPromise = nil; + return nil; + } + }) + .catch(^void(NSError *error) { + @synchronized(self) { + self.pendingPromise = nil; + } + }); + } + + return self.pendingPromise; + } +} + +- (nullable FBLPromise *)getExistingPendingPromise { + @synchronized(self) { + return self.pendingPromise; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h new file mode 100644 index 0000000..3edc692 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The enum represent possible states of the installation ID. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredItem`. Modification + * of it can lead to incompatibility with previous version. Any modification must be evaluated and, + * if it is really needed, the `storageVersion` must be bumped and proper migration code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsStatus) { + /** Represents either an initial status when a FIRInstallationsItem instance was created but not + * stored to Keychain or an undefined status (e.g. when the status failed to deserialize). + */ + FIRInstallationStatusUnknown, + /// The Firebase Installation has not yet been registered with FIS. + FIRInstallationStatusUnregistered, + /// The Firebase Installation has successfully been registered with FIS. + FIRInstallationStatusRegistered, +}; diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h new file mode 100644 index 0000000..5334cc9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; +@class FIRSecureStorage; + +NS_ASSUME_NONNULL_BEGIN + +/// The user defaults suite name used to store data. +extern NSString *const kFIRInstallationsStoreUserDefaultsID; + +/// The class is responsible for storing and accessing the installations data. +@interface FIRInstallationsStore : NSObject + +/** + * The default initializer. + * @param storage The secure storage to save installations data. + * @param accessGroup The Keychain Access Group to store and request the installations data. + */ +- (instancetype)initWithSecureStorage:(FIRSecureStorage *)storage + accessGroup:(nullable NSString *)accessGroup; + +/** + * Retrieves existing installation ID if there is. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a `FBLPromise` instance. The promise is resolved with a FIRInstallationsItem + * instance if there is a valid installation stored for `appID` and `appName`. The promise is + * rejected with a specific error when the installation has not been found or with another possible + * error. + */ +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName; + +/** + * Saves the given installation. + * + * @param installationItem The installation data. + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem; + +/** + * Removes installation data for the given app parameters. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m new file mode 100644 index 0000000..9fcfd74 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m @@ -0,0 +1,125 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStore.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsStoredItem.h" +#import "FIRSecureStorage.h" + +NSString *const kFIRInstallationsStoreUserDefaultsID = @"com.firebase.FIRInstallations"; + +@interface FIRInstallationsStore () +@property(nonatomic, readonly) FIRSecureStorage *secureStorage; +@property(nonatomic, readonly, nullable) NSString *accessGroup; +@property(nonatomic, readonly) dispatch_queue_t queue; +@property(nonatomic, readonly) GULUserDefaults *userDefaults; +@end + +@implementation FIRInstallationsStore + +- (instancetype)initWithSecureStorage:(FIRSecureStorage *)storage + accessGroup:(NSString *)accessGroup { + self = [super init]; + if (self) { + _secureStorage = storage; + _accessGroup = [accessGroup copy]; + _queue = dispatch_queue_create("com.firebase.FIRInstallationsStore", DISPATCH_QUEUE_SERIAL); + + NSString *userDefaultsSuiteName = _accessGroup ?: kFIRInstallationsStoreUserDefaultsID; + _userDefaults = [[GULUserDefaults alloc] initWithSuiteName:userDefaultsSuiteName]; + } + return self; +} + +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName { + NSString *itemID = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self installationExistsForAppID:appID appName:appName] + .then(^id(id result) { + return [self.secureStorage getObjectForKey:itemID + objectClass:[FIRInstallationsStoredItem class] + accessGroup:self.accessGroup]; + }) + .then(^id(FIRInstallationsStoredItem *_Nullable storedItem) { + if (storedItem == nil) { + return [FIRInstallationsErrorUtil installationItemNotFoundForAppID:appID appName:appName]; + } + + FIRInstallationsItem *item = [[FIRInstallationsItem alloc] initWithAppID:appID + firebaseAppName:appName]; + [item updateWithStoredItem:storedItem]; + return item; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem { + FIRInstallationsStoredItem *storedItem = [installationItem storedItem]; + NSString *identifier = [installationItem identifier]; + + return + [self.secureStorage setObject:storedItem forKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:YES forItemWithIdentifier:identifier]; + }); +} + +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self.secureStorage removeObjectForKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:NO forItemWithIdentifier:identifier]; + }); +} + +#pragma mark - User defaults + +- (FBLPromise *)installationExistsForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + return [[self userDefaults] objectForKey:identifier] != nil + ? [NSNull null] + : [FIRInstallationsErrorUtil + installationItemNotFoundForAppID:appID + appName:appName]; + }]; +} + +- (FBLPromise *)setInstallationExists:(BOOL)exists + forItemWithIdentifier:(NSString *)identifier { + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + if (exists) { + [[self userDefaults] setBool:YES forKey:identifier]; + } else { + [[self userDefaults] removeObjectForKey:identifier]; + } + + return [NSNull null]; + }]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h new file mode 100644 index 0000000..f6e4282 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The enum represent possible states of the installation auth token. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredAuthToken`. + * Modification of it can lead to incompatibility with previous version. Any modification must be + * evaluated and, if it is really needed, the `storageVersion` must be bumped and proper migration + * code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenStatus) { + /// An initial status or an undefined value. + FIRInstallationsAuthTokenStatusUnknown, + /// The auth token has been received from the server. + FIRInstallationsAuthTokenStatusTokenReceived +}; + +/** + * This class serializes and deserializes the installation data into/from `NSData` to be stored in + * Keychain. This class is primarily used by `FIRInstallationsStore`. It is also used on the logic + * level as a data object (see `FIRInstallationsItem.authToken`). + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredAuthToken : NSObject +@property FIRInstallationsAuthTokenStatus status; + +/// The token that can be used to authorize requests to Firebase backend. +@property(nullable, copy) NSString *token; +/// The date when the auth token expires. +@property(nullable, copy) NSDate *expirationDate; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m new file mode 100644 index 0000000..b21f6dd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredAuthToken.h" + +#import "FIRInstallationsLogger.h" + +NSString *const kFIRInstallationsStoredAuthTokenStatusKey = @"status"; +NSString *const kFIRInstallationsStoredAuthTokenTokenKey = @"token"; +NSString *const kFIRInstallationsStoredAuthTokenExpirationDateKey = @"expirationDate"; +NSString *const kFIRInstallationsStoredAuthTokenStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredAuthTokenStorageVersion = 1; + +@implementation FIRInstallationsStoredAuthToken + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredAuthTokenStorageVersion; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsStoredAuthToken *clone = [[FIRInstallationsStoredAuthToken alloc] init]; + clone.status = self.status; + clone.token = [self.token copy]; + clone.expirationDate = self.expirationDate; + return clone; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeInteger:self.status forKey:kFIRInstallationsStoredAuthTokenStatusKey]; + [aCoder encodeObject:self.token forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + [aCoder encodeObject:self.expirationDate + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + [aCoder encodeInteger:self.storageVersion + forKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; + if (storageVersion > kFIRInstallationsStoredAuthTokenStorageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch, + @"FIRInstallationsStoredAuthToken was encoded by a newer coder version %ld. " + @"Current coder version is %ld. Some auth token data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredAuthTokenStorageVersion); + } + + FIRInstallationsStoredAuthToken *object = [[FIRInstallationsStoredAuthToken alloc] init]; + object.status = [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStatusKey]; + object.token = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + object.expirationDate = + [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + + return object; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h new file mode 100644 index 0000000..4926588 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class is supposed to be used by `FIRInstallationsStore` only. It is required to + * serialize/deserialize the installation data into/from `NSData` to be stored in Keychain. + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredItem : NSObject + +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic) FIRInstallationsStatus registrationStatus; + +/// Instance ID default auth token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m new file mode 100644 index 0000000..0c7655c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredItem.h" + +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" + +NSString *const kFIRInstallationsStoredItemFirebaseInstallationIDKey = @"firebaseInstallationID"; +NSString *const kFIRInstallationsStoredItemRefreshTokenKey = @"refreshToken"; +NSString *const kFIRInstallationsStoredItemAuthTokenKey = @"authToken"; +NSString *const kFIRInstallationsStoredItemRegistrationStatusKey = @"registrationStatus"; +NSString *const kFIRInstallationsStoredItemIIDDefaultTokenKey = @"IIDDefaultToken"; +NSString *const kFIRInstallationsStoredItemStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredItemStorageVersion = 1; + +@implementation FIRInstallationsStoredItem + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredItemStorageVersion; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:self.firebaseInstallationID + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + [aCoder encodeObject:self.refreshToken forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + [aCoder encodeObject:self.authToken forKey:kFIRInstallationsStoredItemAuthTokenKey]; + [aCoder encodeInteger:self.registrationStatus + forKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + [aCoder encodeObject:self.IIDDefaultToken forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + [aCoder encodeInteger:self.storageVersion forKey:kFIRInstallationsStoredItemStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemStorageVersionKey]; + if (storageVersion > self.storageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInstallationCoderVersionMismatch, + @"FIRInstallationsStoredItem was encoded by a newer coder version %ld. Current " + @"coder version is %ld. Some installation data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredItemStorageVersion); + } + + FIRInstallationsStoredItem *item = [[FIRInstallationsStoredItem alloc] init]; + item.firebaseInstallationID = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + item.refreshToken = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + item.authToken = [aDecoder decodeObjectOfClass:[FIRInstallationsStoredAuthToken class] + forKey:kFIRInstallationsStoredItemAuthTokenKey]; + item.registrationStatus = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + item.IIDDefaultToken = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + + return item; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h new file mode 100644 index 0000000..4839b4e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRInstallationsAuthTokenResult; + +NS_ASSUME_NONNULL_BEGIN + +/** A notification with this name is sent each time an installation is created or deleted. */ +FOUNDATION_EXPORT const NSNotificationName FIRInstallationIDDidChangeNotification; +/** `userInfo` key for the `FirebaseApp.name` in `FIRInstallationIDDidChangeNotification`. */ +FOUNDATION_EXPORT NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey; + +/** + * An installation ID handler block. + * @param identifier The installation ID string if exists or `nil` otherwise. + * @param error The error when `identifier == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsIDHandler)(NSString *__nullable identifier, + NSError *__nullable error) + NS_SWIFT_NAME(InstallationsIDHandler); + +/** + * An authorization token handler block. + * @param tokenResult An instance of `InstallationsAuthTokenResult` in case of success or `nil` + * otherwise. + * @param error The error when `tokenResult == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsTokenHandler)( + FIRInstallationsAuthTokenResult *__nullable tokenResult, NSError *__nullable error) + NS_SWIFT_NAME(InstallationsTokenHandler); + +/** + * The class provides API for Firebase Installations. + * Each configured `FirebaseApp` has a corresponding single instance of `Installations`. + * An instance of the class provides access to the installation info for the `FirebaseApp` as well + * as the ability to delete it. A Firebase Installation is unique by `FirebaseApp.name` and + * `FirebaseApp.options.googleAppID` . + */ +NS_SWIFT_NAME(Installations) +@interface FIRInstallations : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Returns a default instance of `Installations`. + * @returns An instance of `Installations` for `FirebaseApp.defaultApp(). + * @throw Throws an exception if the default app is not configured yet or required `FirebaseApp` + * options are missing. + */ ++ (FIRInstallations *)installations NS_SWIFT_NAME(installations()); + +/** + * Returns an instance of `Installations` for an application. + * @param application A configured `FirebaseApp` instance. + * @returns An instance of `Installations` corresponding to the passed application. + * @throw Throws an exception if required `FirebaseApp` options are missing. + */ ++ (FIRInstallations *)installationsWithApp:(FIRApp *)application NS_SWIFT_NAME(installations(app:)); + +/** + * The method creates or retrieves an installation ID. The installation ID is a stable identifier + * that uniquely identifies the app instance. NOTE: If the application already has an existing + * FirebaseInstanceID then the InstanceID identifier will be used. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsIDHandler` for additional details. + */ +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion; + +/** + * Retrieves (locally if it exists or from the server) a valid authorization token. An existing + * token may be invalidated or expired, so it is recommended to fetch the auth token before each + * server request. The method does the same as `Installations.authTokenForcingRefresh(:, + * completion:)` with forcing refresh `NO`. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion; + +/** + * Retrieves (locally or from the server depending on `forceRefresh` value) a valid authorization + * token. An existing token may be invalidated or expire, so it is recommended to fetch the auth + * token before each server request. This method should be used with `forceRefresh == YES` when e.g. + * a request with the previously fetched auth token failed with "Not Authorized" error. + * @param forceRefresh If `YES` then the locally cached auth token will be ignored and a new one + * will be requested from the server. If `NO`, then the locally cached auth token will be returned + * if exists and has not expired yet. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion; + +/** + * Deletes all the installation data including the unique identifier, auth tokens and + * all related data on the server side. A network connection is required for the method to + * succeed. If fails, the existing installation data remains untouched. + * @param completion A completion handler which is invoked when the operation completes. `error == + * nil` indicates success. + */ +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h new file mode 100644 index 0000000..7753132 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class represents a result of the auth token request. */ +NS_SWIFT_NAME(InstallationsAuthTokenResult) +@interface FIRInstallationsAuthTokenResult : NSObject + +/** The authorization token string. */ +@property(nonatomic, readonly) NSString *authToken; + +/** The auth token expiration date. */ +@property(nonatomic, readonly) NSDate *expirationDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h new file mode 100644 index 0000000..d0c3b99 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *const kFirebaseInstallationsErrorDomain; + +typedef NS_ENUM(NSUInteger, FIRInstallationsErrorCode) { + /** Unknown error. See `userInfo` for details. */ + FIRInstallationsErrorCodeUnknown = 0, + + /** Keychain error. See `userInfo` for details. */ + FIRInstallationsErrorCodeKeychain = 1, + + /** Server unreachable. A network error or server is unavailable. See `userInfo` for details. */ + FIRInstallationsErrorCodeServerUnreachable = 2, + + /** FirebaseApp configuration issues e.g. invalid GMP-App-ID, etc. See `userInfo` for details. */ + FIRInstallationsErrorCodeInvalidConfiguration = 3, + +} NS_SWIFT_NAME(InstallationsErrorCode); diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h new file mode 100644 index 0000000..8cdf677 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h @@ -0,0 +1,19 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT const char *const FIRInstallationsVersionStr; diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h new file mode 100644 index 0000000..accc9ac --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h @@ -0,0 +1,20 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h new file mode 100644 index 0000000..4d73ec0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Helper functions to access Keychain. +@interface FIRInstallationsKeychainUtils : NSObject + ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m new file mode 100644 index 0000000..51da86a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsKeychainUtils.h" + +#import "FIRInstallationsErrorUtil.h" + +@implementation FIRInstallationsKeychainUtils + ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *mutableQuery = [query mutableCopy]; + + mutableQuery[(__bridge id)kSecReturnData] = @YES; + mutableQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFDataRef result = NULL; + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)mutableQuery, (CFTypeRef *)&result); + + if (status == errSecSuccess && result != NULL) { + if (outError) { + *outError = nil; + } + + return (__bridge_transfer NSData *)result; + } + + if (status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + } else { + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemCopyMatching" + status:status]; + } + } + return nil; +} + ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSData *existingItem = [self getItemWithQuery:query error:outError]; + if (outError && *outError) { + return NO; + } + + NSMutableDictionary *mutableQuery = [query mutableCopy]; + mutableQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status; + if (!existingItem) { + mutableQuery[(__bridge id)kSecValueData] = item; + status = SecItemAdd((__bridge CFDictionaryRef)mutableQuery, NULL); + } else { + NSDictionary *attributes = @{(__bridge id)kSecValueData : item}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + + if (status == noErr) { + if (outError) { + *outError = nil; + } + return YES; + } + + NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd"; + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:function status:status]; + } + return NO; +} + ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + + if (status == noErr || status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + return YES; + } + + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete" + status:status]; + } + return NO; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h new file mode 100644 index 0000000..5548e3e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/// The class provides a convenient abstraction on top of the iOS Keychain API to save data. +@interface FIRSecureStorage : NSObject + +/** + * Get an object by key. + * @param key The key. + * @param objectClass The expected object class required by `NSSecureCoding`. + * @param accessGroup The Keychain Access Group. + * + * @return Returns a promise. It is resolved with an object stored by key if exists. It is resolved + * with `nil` when the object not found. It fails on a Keychain error. + */ +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup; + +/** + * Saves the given object by the given key. + * @param object The object to store. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +/** + * Removes the object by the given key. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m new file mode 100644 index 0000000..543e848 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m @@ -0,0 +1,255 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRSecureStorage.h" +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsKeychainUtils.h" + +@interface FIRSecureStorage () +@property(nonatomic, readonly) dispatch_queue_t keychainQueue; +@property(nonatomic, readonly) dispatch_queue_t inMemoryCacheQueue; +@property(nonatomic, readonly) NSString *service; +@property(nonatomic, readonly) NSCache> *inMemoryCache; +@end + +@implementation FIRSecureStorage + +- (instancetype)init { + NSCache *cache = [[NSCache alloc] init]; + // Cache up to 5 installations. + cache.countLimit = 5; + return [self initWithService:@"com.firebase.FIRInstallations.installations" cache:cache]; +} + +- (instancetype)initWithService:(NSString *)service cache:(NSCache *)cache { + self = [super init]; + if (self) { + _keychainQueue = dispatch_queue_create( + "com.firebase.FIRInstallations.FIRSecureStorage.Keychain", DISPATCH_QUEUE_SERIAL); + _inMemoryCacheQueue = dispatch_queue_create( + "com.firebase.FIRInstallations.FIRSecureStorage.InMemoryCache", DISPATCH_QUEUE_SERIAL); + _service = [service copy]; + _inMemoryCache = cache; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Return cached object or fail otherwise. + id object = [self.inMemoryCache objectForKey:key]; + return object + ?: [[NSError alloc] + initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }] + .recover(^id _Nullable(NSError *error) { + // Look for the object in the keychain. + return [self getObjectFromKeychainForKey:key + objectClass:objectClass + accessGroup:accessGroup]; + }); +} + +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Save to the in-memory cache first. + [self.inMemoryCache setObject:object forKey:[key copy]]; + return [NSNull null]; + }] + .thenOn(self.keychainQueue, ^id(id result) { + // Then store the object to the keychain. + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = [self archiveDataForObject:object error:&error]; + if (!encodedObject) { + return error; + } + + if (![FIRInstallationsKeychainUtils setItem:encodedObject withQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + [self.inMemoryCache removeObjectForKey:key]; + return nil; + }] + .thenOn(self.keychainQueue, ^id(id result) { + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + + NSError *error; + if (![FIRInstallationsKeychainUtils removeItemWithQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +#pragma mark - Private + +- (FBLPromise> *)getObjectFromKeychainForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + // Look for the object in the keychain. + return [FBLPromise onQueue:self.keychainQueue + do:^id { + NSDictionary *query = [self keychainQueryWithKey:key + accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = + [FIRInstallationsKeychainUtils getItemWithQuery:query error:&error]; + + if (error) { + return error; + } + if (!encodedObject) { + return nil; + } + id object = [self unarchivedObjectOfClass:objectClass + fromData:encodedObject + error:&error]; + if (error) { + return error; + } + + return object; + }] + .thenOn(self.inMemoryCacheQueue, + ^id _Nullable(id _Nullable object) { + // Save object to the in-memory cache if exists and return the object. + if (object) { + [self.inMemoryCache setObject:object forKey:[key copy]]; + } + return object; + }); +} + +- (void)resetInMemoryCache { + [self.inMemoryCache removeAllObjects]; +} + +#pragma mark - Keychain + +- (NSMutableDictionary *)keychainQueryWithKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + + query[(__bridge NSString *)kSecClass] = (__bridge NSString *)kSecClassGenericPassword; + query[(__bridge NSString *)kSecAttrService] = self.service; + query[(__bridge NSString *)kSecAttrAccount] = key; + + if (accessGroup) { + query[(__bridge NSString *)kSecAttrAccessGroup] = accessGroup; + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecUseKeychain] = (__bridge id)(self.keychainRef); + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +- (nullable NSData *)archiveDataForObject:(id)object error:(NSError **)outError { + NSData *archiveData; + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + archiveData = [NSKeyedArchiver archivedDataWithRootObject:object + requiringSecureCoding:YES + error:&error]; + if (error && outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithError:error]; + } + } else { + @try { + NSMutableData *data = [NSMutableData data]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + archiver.requiresSecureCoding = YES; + + [archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey]; + [archiver finishEncoding]; + + archiveData = [data copy]; + } @catch (NSException *exception) { + if (outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + } + + return archiveData; +} + +- (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError { + id object; + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + object = [NSKeyedUnarchiver unarchivedObjectOfClass:class fromData:data error:&error]; + if (error && outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithError:error]; + } + } else { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + unarchiver.requiresSecureCoding = YES; + + object = [unarchiver decodeObjectOfClass:class forKey:NSKeyedArchiveRootObjectKey]; + } @catch (NSException *exception) { + if (outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + } + + return object; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstallations/LICENSE b/PediatricPancreas/Pods/FirebaseInstallations/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseInstallations/README.md b/PediatricPancreas/Pods/FirebaseInstallations/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstallations/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h new file mode 100644 index 0000000..e3e36e9 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h @@ -0,0 +1,150 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// The format of the debug code will show in the log as: e.g. +// for code 1000, it will show as I-IID001000. +typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) { + // DO NOT USE 2000, 2002. + kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000 + kFIRInstanceIDMessageCodeFIRApp001 = 1001, + kFIRInstanceIDMessageCodeFIRApp002 = 1002, + kFIRInstanceIDMessageCodeInternal001 = 2001, + kFIRInstanceIDMessageCodeInternal002 = 2002, + // FIRInstanceID.m + // DO NOT USE 4000. + kFIRInstanceIDMessageCodeInstanceID000 = 3000, + kFIRInstanceIDMessageCodeInstanceID001 = 3001, + kFIRInstanceIDMessageCodeInstanceID002 = 3002, + kFIRInstanceIDMessageCodeInstanceID003 = 3003, + kFIRInstanceIDMessageCodeInstanceID004 = 3004, + kFIRInstanceIDMessageCodeInstanceID005 = 3005, + kFIRInstanceIDMessageCodeInstanceID006 = 3006, + kFIRInstanceIDMessageCodeInstanceID007 = 3007, + kFIRInstanceIDMessageCodeInstanceID008 = 3008, + kFIRInstanceIDMessageCodeInstanceID009 = 3009, + kFIRInstanceIDMessageCodeInstanceID010 = 3010, + kFIRInstanceIDMessageCodeInstanceID011 = 3011, + kFIRInstanceIDMessageCodeInstanceID012 = 3012, + kFIRInstanceIDMessageCodeInstanceID013 = 3013, + kFIRInstanceIDMessageCodeInstanceID014 = 3014, + kFIRInstanceIDMessageCodeInstanceID015 = 3015, + kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016, + kFIRInstanceIDMessageCodeInstanceID017 = 3017, + kFIRInstanceIDMessageCodeInstanceID018 = 3018, + // FIRInstanceIDAuthService.m + kFIRInstanceIDMessageCodeAuthService000 = 5000, + kFIRInstanceIDMessageCodeAuthService001 = 5001, + kFIRInstanceIDMessageCodeAuthService002 = 5002, + kFIRInstanceIDMessageCodeAuthService003 = 5003, + kFIRInstanceIDMessageCodeAuthService004 = 5004, + kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004, + + // FIRInstanceIDBackupExcludedPlist.m + // Do NOT USE 6003 + kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000, + kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001, + kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002, + // FIRInstanceIDCheckinService.m + kFIRInstanceIDMessageCodeService000 = 7000, + kFIRInstanceIDMessageCodeService001 = 7001, + kFIRInstanceIDMessageCodeService002 = 7002, + kFIRInstanceIDMessageCodeService003 = 7003, + kFIRInstanceIDMessageCodeService004 = 7004, + kFIRInstanceIDMessageCodeService005 = 7005, + kFIRInstanceIDMessageCodeService006 = 7006, + kFIRInstanceIDInvalidNetworkSession = 7007, + kFIRInstanceIDInvalidSettingResponse = 7008, + // FIRInstanceIDCheckinStore.m + // DO NOT USE 8002, 8004 - 8008 + kFIRInstanceIDMessageCodeCheckinStore000 = 8000, + kFIRInstanceIDMessageCodeCheckinStore001 = 8001, + kFIRInstanceIDMessageCodeCheckinStore003 = 8003, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010, + + // DO NOT USE 9000 - 9006 + + // DO NOT USE 10000 - 10009 + + // DO NOT USE 11000 - 11002 + + // DO NOT USE 12000 - 12014 + + // FIRInstanceIDStore.m + // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014 + kFIRInstanceIDMessageCodeStore000 = 13000, + kFIRInstanceIDMessageCodeStore001 = 13001, + kFIRInstanceIDMessageCodeStore002 = 13002, + kFIRInstanceIDMessageCodeStore003 = 13003, + kFIRInstanceIDMessageCodeStore006 = 13006, + kFIRInstanceIDMessageCodeStore009 = 13009, + kFIRInstanceIDMessageCodeStore012 = 13012, + // FIRInstanceIDTokenManager.m + // DO NOT USE 14002, 14005 + kFIRInstanceIDMessageCodeTokenManager000 = 14000, + kFIRInstanceIDMessageCodeTokenManager001 = 14001, + kFIRInstanceIDMessageCodeTokenManager003 = 14003, + kFIRInstanceIDMessageCodeTokenManager004 = 14004, + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006, + kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007, + kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008, + kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009, + kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010, + kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011, + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012, + // FIRInstanceIDTokenStore.m + // DO NOT USE 15002 - 15013 + kFIRInstanceIDMessageCodeTokenStore000 = 15000, + kFIRInstanceIDMessageCodeTokenStore001 = 15001, + kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015, + + // DO NOT USE 16000, 18004 + + // FIRInstanceIDUtilities.m + kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000, + kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001, + kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002, + kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003, + // FIRInstanceIDTokenOperation.m + kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000, + // FIRInstanceIDTokenFetchOperation.m + // DO NOT USE 20004, 20005 + kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000, + kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001, + kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002, + kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003, + // FIRInstanceIDTokenDeleteOperation.m + kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000, + kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001, + kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002, + // FIRInstanceIDTokenInfo.m + kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000, + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001, + kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002, + // FIRInstanceIDKeychain.m + kFIRInstanceIDKeychainReadItemError = 23000, + kFIRInstanceIDKeychainAddItemError = 23001, + kFIRInstanceIDKeychainDeleteItemError = 23002, + kFIRInstanceIDKeychainCreateKeyPairError = 23003, + kFIRInstanceIDKeychainUpdateItemError = 23004, + + // FIRInstanceIDStringEncoding.m + kFIRInstanceIDStringEncodingBufferUnderflow = 24000, + kFIRInstanceIDStringEncodingBufferOverflow = 24001, + +}; diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m new file mode 100644 index 0000000..c5ffe7a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID+Private.h" + +#import + +#import +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDTokenManager.h" + +@class FIRInstallations; + +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager; + +@end + +@implementation FIRInstanceID (Private) + +// This method just wraps our pre-configured auth service to make the request. +// This method is only needed by first-party users, like Remote Config. +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler { + [self.tokenManager.authService fetchCheckinInfoWithHandler:handler]; +} + +// TODO(#4486): Delete the method, `self.firebaseInstallationsID` and related +// code for Firebase 7 release. +- (NSString *)appInstanceID:(NSError **)outError { + return self.firebaseInstallationsID; +} + +#pragma mark - Firebase Installations Compatibility + +/// Presence of this method indicates that this version of IID uses FirebaseInstallations under the +/// hood. It is checked by FirebaseInstallations SDK. ++ (BOOL)usesFIS { + return YES; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m new file mode 100644 index 0000000..f9cba4f --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m @@ -0,0 +1,1130 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import + +#import +#import +#import +#import +#import +#import +#import +#import "FIRInstanceID+Private.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCombinedHandler.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenManager.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +// Public constants +NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName kFIRInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +#else +NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler."; + +// Private constants +int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes +int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds +// we retry only a max 5 times. +// TODO(chliangGoogle): If we still fail we should listen for the network change notification +// since GCM would have started Reachability. We only start retrying after we see a configuration +// change. +NSInteger const kMaxRetryCountForDefaultToken = 5; + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH +static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment"; +#else +static NSString *const kEntitlementsAPSEnvironmentKey = + @"Entitlements.com.apple.developer.aps-environment"; +#endif +static NSString *const kAPSEnvironmentDevelopmentValue = @"development"; +/// FIRMessaging selector that returns the current FIRMessaging auto init +/// enabled flag. +static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = + @"isAutoInitEnabledWithUserDefaults:"; + +static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType"; +static NSString *const kFIRIIDAppReadyToConfigureSDKNotification = + @"FIRAppReadyToConfigureSDKNotification"; +static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey"; +static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid"; +static NSString *const kFIRIIDServiceInstanceID = @"InstanceID"; + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * InstanceID will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * This must match FIRMessagingAPNSTokenType in FIRMessaging.h + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) { + /// Unknown token type. + FIRInstanceIDAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRInstanceIDAPNSTokenTypeSandbox, + /// Production token type. + FIRInstanceIDAPNSTokenTypeProd, +} NS_SWIFT_NAME(InstanceIDAPNSTokenType); + +@interface FIRInstanceIDResult () +@property(nonatomic, readwrite, copy) NSString *instanceID; +@property(nonatomic, readwrite, copy) NSString *token; +@end + +@interface FIRInstanceID () + +// FIRApp configuration objects. +@property(nonatomic, readwrite, copy) NSString *fcmSenderID; +@property(nonatomic, readwrite, copy) NSString *firebaseAppID; + +// Raw APNS token data +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; + +@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType; +// String-based, internal representation of APNS token +@property(nonatomic, readwrite, copy) NSString *APNSTupleString; +// Token fetched from the server automatically for the default app. +@property(nonatomic, readwrite, copy) NSString *defaultFCMToken; + +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readwrite, strong) FIRInstallations *installations; + +// backoff and retry for default token +@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken; +@property(atomic, strong, nullable) + FIRInstanceIDCombinedHandler *defaultTokenFetchHandler; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, copy, nullable) NSString *firebaseInstallationsID; + +@end + +// InstanceID doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRInstanceIDInstanceProvider +@end + +@interface FIRInstanceID () +@end + +@implementation FIRInstanceIDResult +- (id)copyWithZone:(NSZone *)zone { + FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init]; + result.instanceID = self.instanceID; + result.token = self.token; + return result; +} +@end + +@implementation FIRInstanceID + +// File static to support InstanceID tests that call [FIRInstanceID instanceID] after +// [FIRInstanceID instanceIDForTests]. +static FIRInstanceID *gInstanceID; + ++ (instancetype)instanceID { + // If the static instance was created, return it. This should only be set in tests and we should + // eventually use proper dependency injection for a better test structure. + if (gInstanceID != nil) { + return gInstanceID; + } + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + FIRInstanceID *instanceID = + (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container); + return instanceID; +} + +- (instancetype)initPrivately { + self = [super init]; + if (self != nil) { + // Use automatic detection of sandbox, unless otherwise set by developer + _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown; + } + return self; +} + ++ (FIRInstanceID *)instanceIDForTests { + gInstanceID = [[FIRInstanceID alloc] initPrivately]; + [gInstanceID start]; + return gInstanceID; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Tokens + +- (NSString *)token { + if (!self.fcmSenderID.length) { + return nil; + } + + NSString *cachedToken = [self cachedTokenIfAvailable]; + + if (cachedToken) { + return cachedToken; + } else { + // If we've never had a cached default token, we should fetch one because unrelatedly, + // this request will help us determine whether the locally-generated Instance ID keypair is not + // unique, and therefore generate a new one. + [self defaultTokenWithHandler:nil]; + return nil; + } +} + +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler { + FIRInstanceID_WEAKIFY(self); + [self getIDWithHandler:^(NSString *identity, NSError *error) { + FIRInstanceID_STRONGIFY(self); + // This is in main queue already + if (error) { + if (handler) { + handler(nil, error); + } + return; + } + FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init]; + result.instanceID = identity; + NSString *cachedToken = [self cachedTokenIfAvailable]; + if (cachedToken) { + if (handler) { + result.token = cachedToken; + handler(result, nil); + } + // If no handler, simply return since client has generated iid and token. + return; + } + [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) { + if (handler) { + if (error) { + handler(nil, error); + return; + } + result.token = token; + handler(result, nil); + } + }]; + }]; +} + +- (NSString *)cachedTokenIfAvailable { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope]; + return cachedTokenInfo.token; +} + +- (void)setDefaultFCMToken:(NSString *)defaultFCMToken { + if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) { + return; + } + + _defaultFCMToken = defaultFCMToken; + + // Sending this notification out will ensure that FIRMessaging has the updated + // default FCM token. + NSNotification *internalDefaultTokenNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification + object:_defaultFCMToken]; + [[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification + postingStyle:NSPostASAP]; +} + +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + // Add internal options + NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary]; + if (options.count) { + [tokenOptions addEntriesFromDictionary:options]; + } + + NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey; + NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) { + // APNS key was given, but server type is missing. Supply the server type with automatic + // checking. This can happen when the token is requested from FCM, which does not include a + // server type during its request. + tokenOptions[serverTypeKey] = @([self isSandboxApp]); + } + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) { + errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken; + } else if (FIRInstanceIDIsValidGCMScope(scope) && + ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) { + errorCode = kFIRInstanceIDErrorCodeInvalidRequest; + } else if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(token, error); + }); + }; + + if (errorCode != noError) { + newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, + NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(nil, error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(nil, newError); + + } else { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; + if (cachedTokenInfo) { + FIRInstanceIDAPNSInfo *optionsAPNSInfo = + [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions]; + // Check if APNS Info is changed + if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) || + [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) { + // check if token is fresh + if ([cachedTokenInfo isFreshWithIID:identifier]) { + newHandler(cachedTokenInfo.token, nil); + return; + } + } + } + [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy] + scope:[scope copy] + instanceID:identifier + options:tokenOptions + handler:newHandler]; + } + }]; + }]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001, + kFIRInstanceIDInvalidNilHandlerError); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + + if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) { + // If a default token is deleted successfully, reset the defaultFCMToken too. + if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] && + [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + self.defaultFCMToken = nil; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (errorCode != noError) { + newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(newError); + + } else { + [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity + scope:scope + instanceID:identifier + handler:newHandler]; + } + }]; + }]; +} + +#pragma mark - Identity + +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + // When getID is explicitly called, trigger getToken to make sure token always exists. + // This is to avoid ID conflict (ID is not checked for conflict until we generate a token) + if (identifier) { + [self token]; + } + handler(identifier, error); + }]; +} + +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) { + if ([NSThread isMainThread]) { + handler(error); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (!self.installations) { + FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart; + callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]); + return; + } + + FIRInstanceID_WEAKIFY(self); + void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + callHandlerOnMainThread(error); + return; + } + [self deleteIdentityWithHandler:^(NSError *error) { + callHandlerOnMainThread(error); + }]; + }; + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + callHandlerOnMainThread(newError); + } else { + [self.tokenManager deleteAllTokensWithInstanceID:identifier handler:deleteTokensHandler]; + } + }]; +} + +- (void)notifyIdentityReset { + [self deleteIdentityWithHandler:nil]; +} + +// Delete all the local cache checkin, IID and token. +- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler { + // Delete tokens. + [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) { + // Reset FCM token. + self.defaultFCMToken = nil; + if (deleteTokenError) { + if (handler) { + handler(deleteTokenError); + } + return; + } + + // Delete Instance ID. + [self.installations deleteWithCompletion:^(NSError *_Nullable error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + + [self.tokenManager.authService resetCheckinWithHandler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + // Only request new token if FCM auto initialization is + // enabled. + if ([self isFCMAutoInitEnabled]) { + // Deletion succeeds! Requesting new checkin, IID and token. + // TODO(chliangGoogle) see if dispatch_after is necessary + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self defaultTokenWithHandler:nil]; + }); + } + if (handler) { + handler(nil); + } + }]; + }]; + }]; +} + +#pragma mark - Checkin + +- (BOOL)tryToLoadValidCheckinInfo { + FIRInstanceIDCheckinPreferences *checkinPreferences = + [self.tokenManager.authService checkinPreferences]; + return [checkinPreferences hasValidCheckinInfo]; +} + +- (NSString *)deviceAuthID { + return [self.tokenManager.authService checkinPreferences].deviceID; +} + +- (NSString *)secretToken { + return [self.tokenManager.authService checkinPreferences].secretToken; +} + +- (NSString *)versionInfo { + return [self.tokenManager.authService checkinPreferences].versionInfo; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-iid" + withVersion:FIRInstanceIDCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // InstanceID only works with the default app. + if (!container.app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002, + @"Firebase Instance ID only works with the default app."); + return nil; + } + + // Ensure it's cached so it returns the same instance every time instanceID is called. + *isCacheable = YES; + FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately]; + [instanceID start]; + [instanceID configureInstanceIDWithOptions:container.app.options]; + return instanceID; + }; + FIRComponent *instanceIDProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider) + instantiationTiming:FIRInstantiationTimingEagerInDefaultApp + dependencies:@[] + creationBlock:creationBlock]; + return @[ instanceIDProvider ]; +} + +- (void)configureInstanceIDWithOptions:(FIROptions *)options { + NSString *GCMSenderID = options.GCMSenderID; + if (!GCMSenderID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000, + @"Firebase not set up correctly, nil or empty senderID."); + [NSException raise:kFIRIIDErrorDomain + format:@"Could not configure Firebase InstanceID. GCMSenderID must not be nil or " + @"empty."]; + } + + self.fcmSenderID = GCMSenderID; + self.firebaseAppID = options.googleAppID; + + [self updateFirebaseInstallationID]; + + // FCM generates a FCM token during app start for sending push notification to device. + // This is not needed for app extension except for watch. +#if TARGET_OS_WATCH + [self didCompleteConfigure]; +#else + if (![GULAppEnvironmentUtil isAppExtension]) { + [self didCompleteConfigure]; + } +#endif +} + +// This is used to start any operations when we receive FirebaseSDK setup notification +// from FIRCore. +- (void)didCompleteConfigure { + NSString *cachedToken = [self cachedTokenIfAvailable]; + // When there is a cached token, do the token refresh. + if (cachedToken) { + // Clean up expired tokens by checking the token refresh policy. + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + if ([self.tokenManager checkTokenRefreshPolicyWithIID:identifier]) { + // Default token is expired, fetch default token from server. + [self defaultTokenWithHandler:nil]; + } + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + }]; + } else if ([self isFCMAutoInitEnabled]) { + // When there is no cached token, must check auto init is enabled. + // If it's disabled, don't initiate token generation/refresh. + // If no cache token and auto init is enabled, fetch a token from server. + [self defaultTokenWithHandler:nil]; + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } + // ONLY checkin when auto data collection is turned on. + if ([self isFCMAutoInitEnabled]) { + [self.tokenManager.authService scheduleCheckin:YES]; + } +} + +- (BOOL)isFCMAutoInitEnabled { + Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + // Firebase Messaging is not installed, auto init should be disabled since it's for FCM. + if (!messagingClass) { + return NO; + } + + // Messaging doesn't have the class method, auto init should be enabled since FCM exists. + SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled); + if (![messagingClass respondsToSelector:autoInitSelector]) { + return YES; + } + + // Get the autoInitEnabled class method. + IMP isAutoInitEnabledIMP = [messagingClass methodForSelector:autoInitSelector]; + BOOL(*isAutoInitEnabled) + (Class, SEL, GULUserDefaults *) = (BOOL(*)(id, SEL, GULUserDefaults *))isAutoInitEnabledIMP; + + // Check FCM's isAutoInitEnabled property. + return isAutoInitEnabled(messagingClass, autoInitSelector, + [GULUserDefaults standardUserDefaults]); +} + +// Actually makes InstanceID instantiate both the IID and Token-related subsystems. +- (void)start { + if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) { + [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName]; + } + + [self setupTokenManager]; + self.installations = [FIRInstallations installations]; + [self setupNotificationListeners]; +} + +// Creates the token manager, which is used for fetching, caching, and retrieving tokens. +- (void)setupTokenManager { + self.tokenManager = [[FIRInstanceIDTokenManager alloc] init]; +} + +- (void)setupNotificationListeners { + // To prevent double notifications remove observer from all events during setup. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + [center addObserver:self + selector:@selector(notifyIdentityReset) + name:kFIRInstanceIDIdentityInvalidatedNotification + object:nil]; + [center addObserver:self + selector:@selector(notifyAPNSTokenIsSet:) + name:kFIRInstanceIDAPNSTokenNotification + object:nil]; + [self observeFirebaseInstallationIDChanges]; +} + +#pragma mark - Private Helpers +/// Maximum retry count to fetch the default token. ++ (int64_t)maxRetryCountForDefaultToken { + return kMaxRetryCountForDefaultToken; +} + +/// Minimum interval in seconds between retries to fetch the default token. ++ (int64_t)minIntervalForDefaultTokenRetry { + return kMinRetryIntervalForDefaultTokenInSeconds; +} + +/// Maximum retry interval between retries to fetch default token. ++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds { + return kMaxRetryIntervalForDefaultTokenInSeconds; +} + +- (NSInteger)retryIntervalToFetchDefaultToken { + if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) { + return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds]; + } + // exponential backoff with a fixed initial retry time + // 11s, 22s, 44s, 88s ... + int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry]; + return (NSInteger)MIN( + (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken, + kMaxRetryIntervalForDefaultTokenInSeconds); +} + +- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler { + [self defaultTokenWithRetry:NO handler:aHandler]; +} + +/** + * @param retry Indicates if the method is called to perform a retry after a failed attempt. + * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler != + * nil` + */ +- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler { + BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil; + + if (!self.defaultTokenFetchHandler) { + self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler alloc] init]; + } + + if (aHandler) { + [self.defaultTokenFetchHandler addHandler:aHandler]; + } + + if (!shouldPerformRequest) { + return; + } + + NSDictionary *instanceIDOptions = @{}; + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging && self.apnsTokenData) { + BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + instanceIDOptions = @{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp), + }; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009, + @"Failed to fetch default token %@", error); + + // This notification can be sent multiple times since we can't guarantee success at any point + // of time. + NSNotification *tokenFetchFailNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification + object:[error copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification + postingStyle:NSPostASAP]; + + self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1, + [[self class] maxRetryCountForDefaultToken]); + + // Do not retry beyond the maximum limit. + if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) { + NSInteger retryInterval = [self retryIntervalToFetchDefaultToken]; + [self retryGetDefaultTokenAfter:retryInterval]; + } else { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007, + @"Failed to retrieve the default FCM token after %ld retries", + (long)self.retryCountForDefaultToken); + [self performDefaultTokenHandlerWithToken:nil error:error]; + } + } else { + // If somebody updated IID with APNS token while our initial request did not have it + // set we need to update it on the server. + NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey]; + BOOL isSandboxInRequest = + [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue]; + // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil + NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + deviceTokenInRequest, isSandboxInRequest); + // If the APNs value either remained nil, or was the same non-nil value, the APNs value + // did not change. + BOOL APNSRemainedSameDuringFetch = + (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) || + ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]); + if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) { + // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs + // value. + [self retryGetDefaultTokenAfter:0]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS, + @"Received APNS token while fetching default token. " + @"Refetching default token."); + // Do not notify and handle completion handler since this is a retry. + // Simply return. + return; + } else { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010, + @"Successfully fetched default token."); + } + // Post the required notifications if somebody is waiting. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@", + token); + NSString *previousFCMToken = self.defaultFCMToken; + self.defaultFCMToken = token; + + // Only notify of token refresh if we have a new valid token that's different than before + if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) { + NSNotification *tokenRefreshNotification = + [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification + object:[self.defaultFCMToken copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification + postingStyle:NSPostASAP]; + } + + [self performDefaultTokenHandlerWithToken:token error:nil]; + } + }; + + [self tokenWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope + options:instanceIDOptions + handler:newHandler]; +} + +/** + * + */ +- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error { + if (!self.defaultTokenFetchHandler) { + return; + } + + [self.defaultTokenFetchHandler combinedHandler](token, error); + self.defaultTokenFetchHandler = nil; +} + +- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval { + FIRInstanceID_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + // Pass nil: no new handlers to be added, currently existing handlers + // will be called + [self defaultTokenWithRetry:YES handler:nil]; + }); +} + +#pragma mark - APNS Token +// This should only be triggered from FCM. +- (void)notifyAPNSTokenIsSet:(NSNotification *)notification { + NSData *token = notification.object; + if (!token || ![token isKindOfClass:[NSData class]]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue]; + + // The APNS token is being added, or has changed (rare) + if ([self.apnsTokenData isEqualToData:token]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011, + @"Trying to reset APNS token to the same value. Will return"); + return; + } + // Use this token type for when we have to automatically fetch tokens in the future + self.apnsTokenType = type; + BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + self.apnsTokenData = [token copy]; + self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp); + + // Pro-actively invalidate the default token, if the APNs change makes it + // invalid. Previously, we invalidated just before fetching the token. + NSArray *invalidatedTokens = + [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp]; + + // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that + // they are up-to-date. + if (invalidatedTokens.count > 0) { + FIRInstanceID_WEAKIFY(self); + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (self == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID017, + @"Instance ID shut down during token reset. Aborting"); + return; + } + if (self.apnsTokenData == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID018, + @"apnsTokenData was set to nil during token reset. Aborting"); + return; + } + + NSMutableDictionary *tokenOptions = [@{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp) + } mutableCopy]; + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) { + if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) { + // We will perform a special fetch for the default FCM token, so that the delegate + // methods are called. For all others, we will do an internal re-fetch. + [self defaultTokenWithHandler:nil]; + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope + instanceID:identifier + options:tokenOptions + handler:^(NSString *_Nullable token, + NSError *_Nullable error){ + + }]; + } + } + }]; + } +} + +- (BOOL)isSandboxApp { + static BOOL isSandboxApp = YES; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isSandboxApp = ![self isProductionApp]; + }); + return isSandboxApp; +} + +- (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + if ([GULAppEnvironmentUtil isSimulator]) { + [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. " + @"Use prod profile by default."]; + return defaultAppTypeProd; + } + + if ([GULAppEnvironmentUtil isFromAppStore]) { + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + return defaultAppTypeProd; + } +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; +#elif TARGET_OS_OSX + NSString *path = [[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent] + stringByAppendingPathComponent:@"embedded.provisionprofile"]; +#endif + + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) { + // Distributed via TestFlight + return defaultAppTypeProd; + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@""]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"]; + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + NSString *errorString = + [NSString stringWithFormat:@"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012, + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey]; + NSString *debugString __unused = + [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning " + @"profiles. If testing on a simulator this is fine since APNS " + @"doesn't work on the simulator."]; + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) { + return NO; + } + + return defaultAppTypeProd; +} + +/// Log error messages only when Messaging exists in the pod. +- (void)logAPNSConfigurationError:(NSString *)errorString { + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString); + } +} + +#pragma mark - Sync InstanceID + +- (void)updateFirebaseInstallationID { + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable installationID, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + self.firebaseInstallationsID = installationID; + }]; +} + +- (void)installationIDDidChangeNotificationReceived:(NSNotification *)notification { + NSString *installationAppID = + notification.userInfo[kFIRInstallationIDDidChangeNotificationAppNameKey]; + if ([installationAppID isKindOfClass:[NSString class]] && + [installationAppID isEqual:self.firebaseAppID]) { + [self updateFirebaseInstallationID]; + } +} + +- (void)observeFirebaseInstallationIDChanges { + [[NSNotificationCenter defaultCenter] removeObserver:self + name:FIRInstallationIDDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(installationIDDidChangeNotificationReceived:) + name:FIRInstallationIDDidChangeNotification + object:nil]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h new file mode 100644 index 0000000..92b2469 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an APNS device token and whether its environment is for sandbox. + * It can read from and write to an NSDictionary for simple serialization. + */ +@interface FIRInstanceIDAPNSInfo : NSObject + +/// The APNs device token, provided by the OS to the application delegate +@property(nonatomic, readonly, strong) NSData *deviceToken; +/// Represents whether or not this is deviceToken is for the sandbox +/// environment, or production. +@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox; + +/** + * Initializes the receiver with an APNs device token, and boolean + * representing whether that token is for the sandbox environment. + * + * @param deviceToken The APNs device token typically provided by the + * operating system. + * @param isSandbox YES if the APNs device token is for the sandbox + * environment, or NO if it is for production. + * @return An instance of FIRInstanceIDAPNSInfo. + */ +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox; + +/** + * Initializes the receiver from a token options dictionary containing data + * within the `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an + * NSData blob, and the sandbox value should be an NSNumber + * representing a boolean value. + * + * @param dictionary A dictionary containing values under the keys + * `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`. + * @return An instance of FIRInstanceIDAPNSInfo, or nil if the + * dictionary data was invalid or missing. + */ +- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary; + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m new file mode 100644 index 0000000..d1f9d08 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAPNSInfo.h" + +#import "FIRInstanceIDConstants.h" + +/// The key used to find the APNs device token in an archive. +NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token"; +/// The key used to find the sandbox value in an archive. +NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox"; + +@implementation FIRInstanceIDAPNSInfo + +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox { + self = [super init]; + if (self) { + _deviceToken = [deviceToken copy]; + _sandbox = isSandbox; + } + return self; +} + +- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary { + id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + + id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if (![isSandbox isKindOfClass:[NSNumber class]]) { + return nil; + } + self = [super init]; + if (self) { + _deviceToken = (NSData *)deviceToken; + _sandbox = ((NSNumber *)isSandbox).boolValue; + } + return self; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey]; + return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey]; + [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey]; +} + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo { + if ([super isEqual:otherInfo]) { + return YES; + } + return ([self.deviceToken isEqualToData:otherInfo.deviceToken] && + self.isSandbox == otherInfo.isSandbox); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h new file mode 100644 index 0000000..8d453b8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper around storing FCM auth data in iOS keychain. + */ +@interface FIRInstanceIDAuthKeychain : NSObject + +/** + * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier` + * as the `kSecAttrGeneric`. + * + * @param identifier The generic attribute to be used by the keychain. + * + * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + * Get keychain items matching the given service and account. The service and/or account + * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query + * will include all items matching any services and/or accounts. + * + * @param service The kSecAttrService used to save the password. Can be wildcard. + * @param account The kSecAttrAccount used to save the password. Can be wildcard. + * + * @return An array of |NSData|s matching the provided inputs. + */ +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account; + +/** + * Get keychain item for a given service and account. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * + * @return A cached keychain item for a given account and service, or nil if it was not + * found or could not be retrieved. + */ +- (NSData *)dataForService:(NSString *)service account:(NSString *)account; + +/** + * Remove the cached items from the keychain matching the service, account and access group. + * In case the items do not exist, YES is returned but with a valid error object with code + * `errSecItemNotFound`. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * @param handler The callback handler which is invoked when the remove operation is complete, with + * an error if there is any. + */ +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *error))handler; + +/** + * Set the data for a given service and account. + * We use `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` which + * prevents backup and restore to iCloud, and works for app extension that can + * execute right after a device is restarted (and not unlocked). + * + * @param data The data to save. + * @param service The `kSecAttrService` used to save the password. + * @param account The `kSecAttrAccount` used to save the password. + * @param handler The callback handler which is invoked when the add operation is complete, + * with an error if there is any. + * + */ +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m new file mode 100644 index 0000000..dfce2f7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m @@ -0,0 +1,216 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" + +/** + * The error type representing why we couldn't read data from the keychain. + */ +typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) { + kFIRInstanceIDKeychainErrorBadArguments = -1301, +}; + +NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*"; + +@interface FIRInstanceIDAuthKeychain () + +@property(nonatomic, copy) NSString *generic; +// cachedKeychainData is keyed by service and account, the value is an array of NSData. +// It is used to cache the tokens per service, per account, as well as checkin data per service, +// per account inside the keychain. +@property(nonatomic) + NSMutableDictionary *> *> + *cachedKeychainData; + +@end + +@implementation FIRInstanceIDAuthKeychain + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _generic = [identifier copy]; + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } + return self; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service + account:(NSString *)account + generic:(NSString *)generic { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) { + finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic; + } + if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) { + finalQuery[(__bridge NSString *)kSecAttrService] = service; + } + return finalQuery; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account generic:self.generic]; +} + +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account { + // If query wildcard service, it asks for all the results, which always query from keychain. + if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + _cachedKeychainData[service][account]) { + // As long as service, account array exist, even it's empty, it means we've queried it before, + // returns the cache value. + return _cachedKeychainData[service][account]; + } + + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + NSMutableArray *results; + keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; +#if TARGET_OS_IOS || TARGET_OS_TV + keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here. + NSArray *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#elif TARGET_OS_OSX || TARGET_OS_WATCH + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + NSData *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#endif + + if (!passwordInfos) { + // Nothing was found, simply return from this sync block. + // Make sure to label the cache entry empty, signaling that we've queried this entry. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return @[]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + return @[]; + } + results = [[NSMutableArray alloc] init]; +#if TARGET_OS_IOS || TARGET_OS_TV + NSInteger numPasswords = passwordInfos.count; + for (NSUInteger i = 0; i < numPasswords; i++) { + NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i]; + if (passwordInfo[(__bridge id)kSecValueData]) { + [results addObject:passwordInfo[(__bridge id)kSecValueData]]; + } + } +#elif TARGET_OS_OSX || TARGET_OS_WATCH + [results addObject:passwordInfos]; +#endif + // We query the keychain because it didn't exist in cache, now query is done, update the result in + // the cache. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return [results copy]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:[results copy] forKey:account]; + } else { + NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy]; + [_cachedKeychainData setObject:entry forKey:service]; + } + return [results copy]; +} + +- (NSData *)dataForService:(NSString *)service account:(NSString *)account { + NSArray *items = [self itemsMatchingService:service account:account]; + // If items is nil or empty, nil will be returned. + return items.firstObject; +} + +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *error))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all keychain items. + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all entries under service, + if (_cachedKeychainData[service]) { + _cachedKeychainData[service] = [[NSMutableDictionary alloc] init]; + } + } else if (_cachedKeychainData[service]) { + // We should keep the service/account entry instead of nil so we know + // it's "empty entry" instead of "not query from keychain yet". + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler]; +} + +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + if (handler) { + handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:kFIRInstanceIDKeychainErrorBadArguments + userInfo:nil]); + } + return; + } + [self removeItemsMatchingService:service + account:account + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (data.length > 0) { + NSMutableDictionary *keychainQuery = + [self keychainQueryForService:service account:account]; + keychainQuery[(__bridge id)kSecValueData] = data; + + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + [[FIRInstanceIDKeychain sharedInstance] + addItemWithQuery:keychainQuery + handler:handler]; + } + }]; + // Set the cache value. This must happen after removeItemsMatchingService:account:handler was + // called, so the cache value was reset before setting a new value. + if (_cachedKeychainData[service]) { + if (_cachedKeychainData[service][account]) { + _cachedKeychainData[service][account] = @[ data ]; + } else { + [_cachedKeychainData[service] setObject:@[ data ] forKey:account]; + } + } else { + [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h new file mode 100644 index 0000000..1fb715e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FIRInstanceIDCheckinService.h" + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDStore; + +/** + * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info + * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the + * checkin request until it is successful. A checkin can also be requested directly, with a + * completion handler. + */ +@interface FIRInstanceIDAuthService : NSObject + +/** + * Used only for testing. In addition to taking a store (for locally caching the checkin info), it + * also takes a checkinService. + */ +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store; + +/** + * Initializes the auth service given a store (which provides the local caching of checkin info). + * This initializer will create its own instance of FIRInstanceIDCheckinService. + */ +- (instancetype)initWithStore:(FIRInstanceIDStore *)store; + +#pragma mark - Checkin Service + +/** + * Checks if the current deviceID and secret are valid or not. + * + * @return YES if the checkin credentials are valid else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Fetch checkin info from the server. This would usually refresh the existing + * checkin credentials for the current app. + * + * @param handler The completion handler to invoke once the checkin info has been + * refreshed. + */ +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Schedule checkin. Will hit the network only if the currently loaded checkin + * preferences are stale. + * + * @param immediately YES if we want it to be scheduled immediately else NO. + */ +- (void)scheduleCheckin:(BOOL)immediately; + +/** + * Returns the checkin preferences currently loaded in memory. The Checkin preferences + * can be either valid or invalid. + * + * @return The checkin preferences loaded in memory. + */ +- (FIRInstanceIDCheckinPreferences *)checkinPreferences; + +/** + * Cancels any ongoing checkin fetch, if any. + */ +- (void)stopCheckinRequest; + +/** + * Resets the checkin information. + * + * @param handler The callback handler which is invoked when checkin reset is complete, + * with an error if there is any. + */ +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m new file mode 100644 index 0000000..8c33c44 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m @@ -0,0 +1,302 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "NSError+FIRInstanceID.h" + +// Max time interval between checkin retry in seconds. +static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5; + +@interface FIRInstanceIDAuthService () + +// Used to retrieve and cache the checkin info to disk and Keychain. +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store; +// Used to perform single checkin fetches. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService; +// The current checkin info. It will be compared to what is retrieved to determine whether it is +// different than what is in the cache. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; + +// This array will track multiple handlers waiting for checkin to be performed. When a checkin +// request completes, all the handlers will be notified. +// Changes to the checkinHandlers array should happen in a thread-safe manner. +@property(nonatomic, readonly, strong) + NSMutableArray *checkinHandlers; + +// This is set to true if there is a checkin request in-flight. +@property(atomic, readwrite, assign) BOOL isCheckinInProgress; +// This timer is used a perform checkin retries. It is cancellable. +@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer; +// The number of times checkin has been retried during a scheduled checkin. +@property(atomic, readwrite, assign) int checkinRetryCount; + +@end + +@implementation FIRInstanceIDAuthService + +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store { + self = [super init]; + if (self) { + _store = store; + _checkinPreferences = [_store cachedCheckinPreferences]; + _checkinService = checkinService; + _checkinHandlers = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc { + [_scheduledCheckinTimer invalidate]; +} + +- (instancetype)initWithStore:(FIRInstanceIDStore *)store { + FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init]; + return [self initWithCheckinService:checkinService store:store]; +} + +#pragma mark - Schedule Checkin + +- (void)scheduleCheckin:(BOOL)immediately { + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + // Checkin is already scheduled, so this (non-immediate) request can be ignored. + if (!immediately && [self.scheduledCheckinTimer isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000, + @"Checkin sync already scheduled. Will not schedule."); + return; + } + + if (immediately) { + [self performScheduledCheckin]; + } else { + int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds]; + [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration]; + } +} + +- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration { + self.scheduledCheckinTimer = + [NSTimer scheduledTimerWithTimeInterval:timerDuration + target:self + selector:@selector(onScheduledCheckinTimerFired:) + userInfo:nil + repeats:NO]; + // Add some tolerance to the timer, to allow iOS to be more flexible with this timer + self.scheduledCheckinTimer.tolerance = 0.5; +} + +- (void)clearScheduledCheckinTimer { + [self.scheduledCheckinTimer invalidate]; + self.scheduledCheckinTimer = nil; +} + +- (void)onScheduledCheckinTimerFired:(NSTimer *)timer { + [self performScheduledCheckin]; +} + +- (void)performScheduledCheckin { + // No checkin scheduled as of now. + [self clearScheduledCheckinTimer]; + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + FIRInstanceID_WEAKIFY(self); + [self + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + self.checkinRetryCount++; + + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.", + error); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Schedule another checkin + [self scheduleCheckin:NO]; + }); + + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success."); + } + }]; +} + +- (int64_t)calculateNextCheckinRetryIntervalInSeconds { + // persistent failures can lead to overflow prevent that. + if (self.checkinRetryCount >= 10) { + return kMaxCheckinRetryIntervalInSeconds; + } + return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds); +} + +#pragma mark - Checkin Service + +- (BOOL)hasValidCheckinInfo { + return [self.checkinPreferences hasValidCheckinInfo]; +} + +- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler { + // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way. + @synchronized(self) { + [self.checkinHandlers addObject:handler]; + + if (_isCheckinInProgress) { + // Nothing more to do until our checkin request is done + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress, + @"Checkin is in progress\n"); + return; + } + } + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil]; + return; + } + + @synchronized(self) { + _isCheckinInProgress = YES; + } + [self.checkinService + checkinWithExistingCheckin:self.checkinPreferences + completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences, + NSError *error) { + @synchronized(self) { + self->_isCheckinInProgress = NO; + } + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003, + @"Failed to checkin device %@", error); + [self notifyCheckinHandlersWithCheckin:nil error:error]; + return; + } + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004, + @"Successfully got checkin credentials"); + BOOL hasSameCachedPreferences = + [self cachedCheckinMatchesCheckin:checkinPreferences]; + checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences; + + // Update to the most recent checkin preferences + self.checkinPreferences = checkinPreferences; + + // Save the checkin info to disk + // Keychain might not be accessible, so confirm that checkin preferences can + // be saved + [self.store + saveCheckinPreferences:checkinPreferences + handler:^(NSError *checkinSaveError) { + if (checkinSaveError && !hasSameCachedPreferences) { + // The checkin info was new, but it couldn't be + // written to the Keychain. Delete any stuff that was + // cached in memory. This doesn't delete any + // previously persisted preferences. + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeService004, + @"Unable to save checkin info, resetting " + @"checkin preferences " + "in memory."); + [checkinPreferences reset]; + [self + notifyCheckinHandlersWithCheckin:nil + error: + checkinSaveError]; + } else { + // The checkin is either new, or it was the same (and + // it couldn't be saved). Either way, report that the + // checkin preferences were received successfully. + [self notifyCheckinHandlersWithCheckin: + checkinPreferences + error:nil]; + if (!hasSameCachedPreferences) { + // Checkin is new. + // Notify any listeners that might be waiting for + // checkin to be fetched, such as Firebase + // Messaging (for its MCS connection). + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] + postNotificationName: + kFIRInstanceIDCheckinFetchedNotification + object:nil]; + }); + } + } + }]; + }]; +} + +- (FIRInstanceIDCheckinPreferences *)checkinPreferences { + return _checkinPreferences; +} + +- (void)stopCheckinRequest { + [self.checkinService stopFetching]; +} + +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler { + [self.store removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + self.checkinPreferences = nil; + } + if (handler) { + handler(error); + } + }]; +} + +#pragma mark - Private + +/** + * Goes through the current list of checkin handlers and fires them with the same checkin and/or + * error info. The checkin handlers will get cleared after. + */ +- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin + error:(nullable NSError *)error { + @synchronized(self) { + for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) { + handler(checkin, error); + } + [self.checkinHandlers removeAllObjects]; + } +} + +/** + * Given a |checkin|, it will compare it to the current checkinPreferences to see if the + * deviceID and secretToken are the same. + */ +- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + if (self.checkinPreferences && checkin) { + return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] && + [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]); + } + return NO; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h new file mode 100644 index 0000000..bccaced --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDBackupExcludedPlist : NSObject + +/** + * Caches the plist contents in memory so we don't hit the disk each time we want + * to query something in the plist. This is loaded lazily i.e. if you write to the + * plist the contents you want to write will be stored here if the write was + * successful. The other case where it is loaded is if you read the plist contents + * by calling `contentAsDictionary`. + * + * In case you write to the plist and then try to read the file using + * `contentAsDictionary` we would just return the cachedPlistContents since it would + * represent the disk contents. + */ +@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents; + +/** + * Init a backup excluded plist file. + * + * @param fileName The filename for the plist file. + * @param subDirectory The subdirectory in Application Support to save the plist. + * + * @return Helper which allows to read write data to a backup excluded plist. + */ +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory; + +/** + * Write dictionary data to the backup excluded plist file. If the file does not exist + * it would be created before writing to it. + * + * @param dict The data to be written to the plist. + * @param error The error object if any while writing the data. + * + * @return YES if the write was successful else NO. + */ +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error; + +/** + * Delete the backup excluded plist created with the above filename. + * + * @param error The error object if any while deleting the file. + * + * @return YES If the delete was successful else NO. + */ +- (BOOL)deleteFile:(NSError **)error; + +/** + * The contents of the plist file. We also store the contents of the file in-memory. + * If the in-memory contents are valid we return the in-memory contents else we read + * the file from disk. + * + * @return A dictionary object that contains the contents of the plist file if the file + * exists else nil. + */ +- (NSDictionary *)contentAsDictionary; + +/** + * Check if the plist exists on the disk or not. + * + * @return YES if the file exists on the disk else NO. + */ +- (BOOL)doesFileExist; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m new file mode 100644 index 0000000..c1085ca --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDBackupExcludedPlist.h" + +#import "FIRInstanceIDLogger.h" + +@interface FIRInstanceIDBackupExcludedPlist () + +@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy) NSString *subDirectoryName; +@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents; + +@end + +@implementation FIRInstanceIDBackupExcludedPlist + +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory { + self = [super init]; + if (self) { + _fileName = [fileName copy]; + _subDirectoryName = [subDirectory copy]; + } + return self; +} + +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error { + NSString *path = [self plistPathInDirectory]; + if (![dict writeToFile:path atomically:YES]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000, + @"Failed to write to %@.plist", self.fileName); + return NO; + } + + // Successfully wrote contents -- change the in-memory contents + self.cachedPlistContents = [dict copy]; + + NSURL *URL = [NSURL fileURLWithPath:path]; + if (error) { + *error = nil; + } + + NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ] + error:error]; + if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) { + return YES; + } + + BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error]; + if (!success) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001, + @"Error excluding %@ from backup, %@", [URL lastPathComponent], + error ? *error : @""); + } + return success; +} + +- (BOOL)deleteFile:(NSError **)error { + BOOL success = YES; + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + success = [[NSFileManager defaultManager] removeItemAtPath:path error:error]; + } + // remove the in-memory contents + self.cachedPlistContents = nil; + return success; +} + +- (NSDictionary *)contentAsDictionary { + if (!self.cachedPlistContents) { + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path]; + } + } + return self.cachedPlistContents; +} + +- (BOOL)doesFileExist { + NSString *path = [self plistPathInDirectory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +#pragma mark - Private + +- (NSString *)plistPathInDirectory { + NSArray *directoryPaths; + NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", self.fileName]; + directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h new file mode 100644 index 0000000..d2f286d --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDCheckinPreferences (Internal) + +/** + * Parse the checkin auth credentials saved in the Keychain to initialize checkin + * preferences. + * + * @param keychainContent The checkin auth credentials saved in the Keychain. + * + * @return A valid checkin preferences object if the checkin auth credentials in the + * keychain can be parsed successfully else nil. + */ ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent; + +/** + * Default initializer for InstanceID checkin preferences. + * + * @param deviceID The deviceID for the app. + * @param secretToken The secret token the app uses to authenticate with the server. + * + * @return A checkin preferences object with given deviceID and secretToken. + */ +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken; + +/** + * Update checkin preferences from the preferences dict persisted as a plist. The dict contains + * all the checkin preferences retrieved from the server except the deviceID and secret which + * are stored in the Keychain. + * + * @param checkinPlistContent The checkin preferences saved in a plist on the disk. + */ +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent; + +/** + * Reset the current checkin preferences object. + */ +- (void)reset; + +/** + * The string that contains the checkin auth credentials i.e. deviceID and secret. This + * needs to be stored in the Keychain. + * + * @return The checkin auth credential string containing the deviceID and secret. + */ +- (NSString *)checkinKeychainContent; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m new file mode 100644 index 0000000..88cc40a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences+Internal.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kCheckinKeychainContentSeparatorString = @"|"; + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +@end + +@implementation FIRInstanceIDCheckinPreferences (Internal) + ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent { + NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent]; + NSString *secret = [self checkinSecretFromKeychainContent:keychainContent]; + if ([deviceID length] && [secret length]) { + return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret]; + } else { + return nil; + } +} + +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken { + self = [super init]; + if (self) { + self.deviceID = [deviceID copy]; + self.secretToken = [secretToken copy]; + } + return self; +} + +- (void)reset { + self.deviceID = nil; + self.secretToken = nil; + self.digest = nil; + self.versionInfo = nil; + self.gServicesData = nil; + self.deviceDataVersion = nil; + self.lastCheckinTimestampMillis = 0; +} + +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent { + for (NSString *key in checkinPlistContent) { + if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) { + self.digest = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) { + self.versionInfo = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) { + self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue]; + } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) { + self.gServicesData = [checkinPlistContent[key] mutableCopy]; + } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) { + self.deviceDataVersion = [checkinPlistContent[key] copy]; + } + // Otherwise we have some keys we don't care about + } +} + +- (NSString *)checkinKeychainContent { + if ([self.deviceID length] && [self.secretToken length]) { + return [NSString stringWithFormat:@"%@%@%@", self.deviceID, + kCheckinKeychainContentSeparatorString, self.secretToken]; + } else { + return nil; + } +} + ++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:0]; +} + ++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:1]; +} + ++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index { + NSArray *keychainComponents = + [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString]; + if (index >= 0 && index < 2 && [keychainComponents count] == 2) { + return keychainComponents[index]; + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m new file mode 100644 index 0000000..2f3c55e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +#import +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days. + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +// This flag indicates that we have already saved the above deviceID and secret +// to our keychain and hence we don't need to save again. This is helpful since +// on checkin refresh we can avoid writing to the Keychain which can sometimes +// be very buggy. For info check this https://forums.developer.apple.com/thread/4743 +@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials; + +@end + +@implementation FIRInstanceIDCheckinPreferences + +- (NSDictionary *)checkinPlistContents { + NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary]; + checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @""; + checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @""; + checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @""; + checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis); + checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] = + [self.gServicesData count] ? self.gServicesData : @{}; + return checkinPlistContents; +} + +- (BOOL)hasCheckinInfo { + return (self.deviceID.length && self.secretToken.length); +} + +- (BOOL)hasValidCheckinInfo { + int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis; + + BOOL hasCheckinInfo = [self hasCheckinInfo]; + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + // If it's app's first time open and checkin is already fetched and no locale information is + // stored, then checkin info is valid. We should not checkin again because locale is considered + // "changed". + if (hasCheckinInfo && !lastLocale) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return YES; + } + + // If locale has changed, checkin info is no longer valid. + // Also update locale information if changed. (Only do it here not in token refresh) + if (FIRInstanceIDHasLocaleChanged()) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return NO; + } + + return (hasCheckinInfo && + (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval)); +} + +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials { + _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h new file mode 100644 index 0000000..9c5850b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** Checkin refresh interval. **/ +FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval; + +@interface FIRInstanceIDCheckinPreferences () + +- (BOOL)hasPreCachedAuthCredentials; +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h new file mode 100644 index 0000000..e14b51c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +// keys in Checkin preferences +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey; + +@class FIRInstanceIDCheckinPreferences; + +/** + * Register the device with Checkin Service and get back the `authID`, `secret + * token` etc. for the client. Checkin results are cached in the + * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale. + * Each client needs to register with checkin before registering with InstanceID. + */ +@interface FIRInstanceIDCheckinService : NSObject + +/** + * Execute a device checkin request to obtain an deviceID, secret token, + * gService data. + * + * @param existingCheckin An existing checkin preference object, if available. + * @param completion Completion hander called on success or failure of device checkin. + */ +- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion; + +/** + * This would stop any request that the service made to the checkin backend and also + * release any callback handlers that it holds. + */ +- (void)stopFetching; + +/** + * Set test block for mock testing network requests. + * + * @param block The block to invoke as a mock response from the network. + */ ++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m new file mode 100644 index 0000000..d3ace54 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin"; + +// keys in Checkin preferences +NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey"; +NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey"; +NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey"; +NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey"; +NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo"; +NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData"; +NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion"; + +static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto +static NSUInteger const kCheckinVersion = 2; +static NSUInteger const kFragment = 0; + +static FIRInstanceIDURLRequestTestBlock testBlock; + +@interface FIRInstanceIDCheckinService () + +@property(nonatomic, readwrite, strong) NSURLSession *session; + +@end + +@implementation FIRInstanceIDCheckinService +; + +- (instancetype)init { + self = [super init]; + if (self) { + // Create an URLSession once, even though checkin should happen about once a day + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + config.allowsCellularAccess = YES; + _session = [NSURLSession sessionWithConfiguration:config]; + _session.sessionDescription = @"com.google.iid-checkin"; + } + return self; +} + +- (void)dealloc { + testBlock = nil; + [self.session invalidateAndCancel]; +} + +- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion { + if (self.session == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDInvalidNetworkSession, + @"Inconsistent state: NSURLSession has been invalidated"); + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]; + if (completion) { + completion(nil, error); + } + return; + } + + NSURL *url = [NSURL URLWithString:kDeviceCheckinURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; + NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin]; + NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters + options:0 + error:nil]; + request.HTTPMethod = @"POST"; + request.HTTPBody = checkinData; + + void (^handler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000, + @"Device checkin HTTP fetch error. Error Code: %ld", + (long)error.code); + if (completion) { + completion(nil, error); + } + return; + } + + NSError *serializationError; + NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&serializationError]; + if (serializationError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001, + @"Error serializing json object. Error Code: %ld", + _FIRInstanceID_L(serializationError.code)); + if (completion) { + completion(nil, serializationError); + } + return; + } + + NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue]; + NSString *secretToken = [dataResponse[@"security_token"] stringValue]; + if ([deviceAuthID length] == 0) { + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest]; + if (completion) { + completion(nil, error); + } + return; + } + + int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue]; + int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + // Somehow the server clock gets out of sync with the device clock. + // Reset the last checkin timestamp in case this happens. + if (lastCheckinTimestampMillis > currentTimestampMillis) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.", + [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]); + lastCheckinTimestampMillis = currentTimestampMillis; + } + + NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @""; + NSString *digest = dataResponse[@"digest"] ?: @""; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003, + @"Checkin successful with authId: %@, " + @"digest: %@, " + @"lastCheckinTimestamp: %lld", + deviceAuthID, digest, lastCheckinTimestampMillis); + + NSString *versionInfo = dataResponse[@"version_info"] ?: @""; + NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary]; + + // Read gServices data. + NSArray *flatSettings = dataResponse[@"setting"]; + for (NSDictionary *dict in flatSettings) { + if (dict[@"name"] && dict[@"value"]) { + gservicesData[dict[@"name"]] = dict[@"value"]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDInvalidSettingResponse, + @"Invalid setting in checkin response: (%@: %@)", + dict[@"name"], dict[@"value"]); + } + } + + FIRInstanceIDCheckinPreferences *checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID + secretToken:secretToken]; + NSDictionary *preferences = @{ + kFIRInstanceIDDigestStringKey : digest, + kFIRInstanceIDVersionInfoStringKey : versionInfo, + kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis), + kFIRInstanceIDGServicesDictionaryKey : gservicesData, + kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo, + }; + [checkinPreferences updateWithCheckinPlistContents:preferences]; + if (completion) { + completion(checkinPreferences, nil); + } + }; + // Test block + if (testBlock) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005, + @"Test block set, will not hit the server"); + testBlock(request, handler); + return; + } + + NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler]; + [task resume]; +} + +- (void)stopFetching { + [self.session invalidateAndCancel]; + // The session cannot be reused after invalidation. Dispose it to prevent accident reusing. + self.session = nil; +} + +#pragma mark - Private + +- (NSDictionary *)checkinParametersWithExistingCheckin: + (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences { + NSString *deviceModel = FIRInstanceIDDeviceModel(); + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion]; + + // Get locale from GCM if GCM exists else use system API. + NSString *locale = FIRInstanceIDCurrentLocale(); + + NSInteger userNumber = 0; // Multi Profile may change this. + NSInteger userSerialNumber = 0; // Multi Profile may change this + + NSString *timeZone = [NSTimeZone localTimeZone].name; + int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis; + + NSDictionary *checkinParameters = @{ + @"checkin" : @{ + @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion}, + @"type" : @(kCheckinType), + @"user_number" : @(userNumber), + @"last_checkin_msec" : @(lastCheckingTimestampMillis), + }, + @"fragment" : @(kFragment), + @"locale" : locale, + @"version" : @(kCheckinVersion), + @"digest" : checkinPreferences.digest ?: @"", + @"time_zone" : timeZone, + @"user_serial_number" : @(userSerialNumber), + @"id" : @([checkinPreferences.deviceID longLongValue]), + @"security_token" : @([checkinPreferences.secretToken longLongValue]), + }; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@", + checkinParameters); + return checkinParameters; +} + ++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block { + testBlock = [block copy]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h new file mode 100644 index 0000000..5e1b119 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; + +// These values exposed for testing +extern NSString *const kFIRInstanceIDCheckinKeychainService; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainService; + +/** + * Checkin preferences backing store. + */ +@interface FIRInstanceIDCheckinStore : NSObject + +/** + * Designated Initializer. Initialize a checkin store with the given backup excluded + * plist filename. + * + * @param checkinFilename The backup excluded plist filename to persist checkin + * preferences. + * + * @param subDirectoryName Sub-directory in standard directory where we write + * InstanceID plist. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName; + +/** + * Initialize a checkin store with the given backup excluded plist and keychain. + * + * @param plist The backup excluded plist to persist checkin preferences. + * @param keychain The keychain used to persist checkin auth preferences. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain; + +/** + * Checks whether the backup excluded checkin preferences are present on the disk or not. + * + * @return YES if the backup excluded checkin plist exists on the disks else NO. + */ +- (BOOL)hasCheckinPlist; + +#pragma mark - Save + +/** + * Save the checkin preferences to backing store. + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler; + +#pragma mark - Delete + +/** + * Remove the cached checkin preferences. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler; + +#pragma mark - Get + +/** + * Get the cached device secret. If we cannot access it for some reason we + * return the appropriate error object. + * + * @return The cached checkin preferences if present else nil. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Migrate the checkin item from old service/account to the new one. + * The new account is dynamic as it uses bundle ID. + * This is to ensure checkin is not shared across apps, but still the same + * if app has used GCM before. + * This call should only happen once. + * + */ +- (void)migrateCheckinItemIfNeeded; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m new file mode 100644 index 0000000..1142778 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m @@ -0,0 +1,236 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid"; + +NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount = @"com.google.iid.checkin-account"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainService = @"com.google.iid.checkin-service"; + +// Checkin plist used to have the deviceID and secret stored in them and that's why they +// had 6 items in it. Since the deviceID and secret have been moved to the keychain +// there would only be 4 items. +static const NSInteger kOldCheckinPlistCount = 6; + +@interface FIRInstanceIDCheckinStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; +// Checkin will store items under +// Keychain account: , +// Keychain service: |kFIRInstanceIDCheckinKeychainService| +@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount; + +@end + +@implementation FIRInstanceIDCheckinStore + +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName { + FIRInstanceIDBackupExcludedPlist *plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename + subDirectory:subDirectoryName]; + + FIRInstanceIDAuthKeychain *keychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric]; + return [self initWithCheckinPlist:plist keychain:keychain]; +} + +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _plist = plist; + _keychain = keychain; + } + return self; +} + +- (BOOL)hasCheckinPlist { + return [self.plist doesFileExist]; +} + +- (NSString *)bundleIdentifierForKeychainAccount { + static NSString *bundleIdentifier; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundleIdentifier = FIRInstanceIDAppIdentifier(); + }); + return bundleIdentifier; +} + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + NSDictionary *checkinPlistContents = [preferences checkinPlistContents]; + NSString *checkinKeychainContent = [preferences checkinKeychainContent]; + + if (![checkinKeychainContent length]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000, + @"Failed to get checkin keychain content from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + if (![checkinPlistContents count]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001, + @"Failed to get checkin plist contents from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + + // Save all other checkin preferences in a plist + NSError *error; + if (![self.plist writeDictionary:checkinPlistContents error:&error]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003, + @"Failed to save checkin plist contents." + @"Will delete auth credentials"); + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + if (handler) { + handler(error); + } + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved, + @"Checkin plist file is saved"); + + // Save the deviceID and secret in the Keychain + if (!preferences.hasPreCachedAuthCredentials) { + NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding]; + [self.keychain setData:data + forService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + } else { + handler(nil); + } +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler { + // Delete the checkin preferences plist first to avoid delay. + NSError *deletePlistError; + if (![self.plist deleteFile:&deletePlistError]) { + handler(deletePlistError); + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted, + @"Deleted checkin plist file."); + // Remove deviceID and secret from Keychain + [self.keychain + removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + // Try to remove from old location as well because migration + // is no longer needed. Consider this is either a fresh install + // or an identity wipe. + [self.keychain + removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + handler(error); + }]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + // Query the keychain for deviceID and secret + NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount]; + + // Check info found in keychain + NSString *checkinKeychainContent = [[NSString alloc] initWithData:item + encoding:NSUTF8StringEncoding]; + FIRInstanceIDCheckinPreferences *checkinPreferences = + [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent]; + + NSDictionary *checkinPlistContents = [self.plist contentAsDictionary]; + + NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey]; + NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey]; + + // If deviceID and secret not found in the keychain verify that we don't have them in the + // checkin preferences plist. + if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) { + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + // Couldn't find checkin credentials in keychain but found them in the plist. + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } else { + // Couldn't find checkin credentials in keychain nor plist + return nil; + } + } else if (kOldCheckinPlistCount == checkinPlistContents.count) { + // same check as above but just to be extra sure that we cover all upgrade cases properly. + // TODO(chliangGoogle): Remove this case, after verifying it's not needed + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } + } + + [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents]; + return checkinPreferences; +} + +- (void)migrateCheckinItemIfNeeded { + // Check for checkin in the old location, using the legacy keys + // Query the keychain for deviceID and secret + NSData *dataInOldLocation = + [self.keychain dataForService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount]; + if (dataInOldLocation) { + // Save to new location + [self.keychain setData:dataInOldLocation + forService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + // Remove from old location + [self.keychain removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + } +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h new file mode 100644 index 0000000..dcb5429 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A generic class to combine several handler blocks into a single block in a thread-safe manner + */ +@interface FIRInstanceIDCombinedHandler : NSObject + +- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler; +- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m new file mode 100644 index 0000000..bc6be6c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCombinedHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error); + +@interface FIRInstanceIDCombinedHandler () +@property(atomic, readonly, strong) NSMutableArray *handlers; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstanceIDCombinedHandler + +- (instancetype)init { + self = [super init]; + if (self) { + _handlers = [NSMutableArray array]; + } + return self; +} + +- (void)addHandler:(FIRInstanseIDHandler)handler { + if (!handler) { + return; + } + + @synchronized(self) { + [self.handlers addObject:handler]; + } +} + +- (FIRInstanseIDHandler)combinedHandler { + FIRInstanseIDHandler combinedHandler = nil; + + @synchronized(self) { + NSArray *handlers = [self.handlers copy]; + combinedHandler = ^(id result, NSError *error) { + for (FIRInstanseIDHandler handler in handlers) { + handler(result, error); + } + }; + } + + return combinedHandler; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h new file mode 100644 index 0000000..cd2e131 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#pragma mark - Commands + +/** + * Value included in a structured response or GCM message from IID, indicating + * an identity reset. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST; + +#pragma mark - Notifications + +/// Notification used to deliver GCM messages for InstanceID. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification; + +#pragma mark - Miscellaneous + +/// The scope used to save the IID "*" scope token. This is used for saving the +/// IID auth token that we receive from the server. This feature was never +/// implemented on the server side. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier; +/// The scope used to save the IID "*" scope token. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope; + +/// Subdirectory in search path directory to store InstanceID preferences. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName; + +/// The key for APNS token in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey; + +/// The key for APNS token environment type in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + +/// The key for GMP AppID sent in registration requests. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey; + +/// The key to enable auto-register by swizzling AppDelegate's methods. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey; + +/// Error code for missing entitlements in Keychain. iOS Keychain error +/// https://forums.developer.apple.com/thread/4743 +FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode; diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m new file mode 100644 index 0000000..81f4620 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDConstants.h" + +// Commands +NSString *const kFIRInstanceID_CMD_RST = @"RST"; + +// NOTIFICATIONS +NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification = + @"com.firebase.iid.notif.fcm-token-fail"; + +NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid"; + +// Miscellaneous +NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all"; +NSString *const kFIRInstanceIDDefaultTokenScope = @"*"; +NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID"; + +// Registration Options +NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token"; +NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox"; +NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id"; + +NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +// iOS Keychain error https://forums.developer.apple.com/thread/4743 +// An undocumented error code hence need to be redeclared. +const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018; diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h new file mode 100644 index 0000000..ccc25b3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h +#define FIRInstanceIDLib_FIRInstanceIDDefines_h + +#define _FIRInstanceID_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRInstanceID_VERBOSE_LOGGING) +#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRInstanceID_DEV_VERBOSE_LOG(...) \ + do { \ + } while (0) +#endif // VERBOSE_LOGGING + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_ + +#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR); + +#define FIRInstanceID_STRONGIFY(VAR) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \ + _Pragma("clang diagnostic pop") + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRInstanceID_L +#define _FIRInstanceID_L(v) (long)(v) +#endif + +#endif diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h new file mode 100644 index 0000000..1c80d8e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/* The Keychain error domain */ +extern NSString *const kFIRInstanceIDKeychainErrorDomain; + +/* + * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation + * blocking main queue. + */ +@interface FIRInstanceIDKeychain : NSObject + +/** + * FIRInstanceIDKeychain. + * + * @return A shared instance of FIRInstanceIDKeychain. + */ ++ (instancetype)sharedInstance; + +/** + * Get keychain items matching the given a query. + * + * @param keychainQuery The keychain query. + * + * @return An CFTypeRef result matching the provided inputs. + */ +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery; + +/** + * Remove the cached items from the keychain matching the query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the remove operation is + * complete, with an error if there is any. + */ +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler; + +/** + * Add the item with a given query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the add operation is + * complete, with an error if there is any. + */ +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m new file mode 100644 index 0000000..df1b4f7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m @@ -0,0 +1,114 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeychain.h" + +#import "FIRInstanceIDLogger.h" + +NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid"; + +@interface FIRInstanceIDKeychain () { + dispatch_queue_t _keychainOperationQueue; +} + +@end + +@implementation FIRInstanceIDKeychain + ++ (instancetype)sharedInstance { + static FIRInstanceIDKeychain *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRInstanceIDKeychain alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _keychainOperationQueue = + dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery { + __block SecKeyRef keyRef = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError, + @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@", + (int)status, keychainQuery); + } + }); + return keyRef; +} + +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery + handler:(void (^)(NSError *error))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery); + if (status != noErr) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDKeychainDeleteItemError, + @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@", + (int)status, keychainQuery); + } + + if (handler) { + NSError *error; + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); + + if (handler) { + NSError *error; + if (status != noErr) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError, + @"Couldn't add item to Keychain OSStatus: %d", (int)status); + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h new file mode 100644 index 0000000..ab93976 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRIMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRInstanceIDLoggerInfo + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to FIRInstanceIDLogger. +#define FIRInstanceIDLoggerDebug(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerInfo(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerNotice(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerWarning(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerError(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRInstanceIDLoggerInfo) + +@interface FIRInstanceIDLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared GTMLogger used exclusively + * for InstanceID log messages. + * @return the shared GTMLogger instance + */ +FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void); diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m new file mode 100644 index 0000000..2600d3b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDLogger.h" + +#import + +// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target +NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]"; + +@implementation FIRInstanceIDLogger + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode { + return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRInstanceIDLogger *FIRInstanceIDSharedLogger() { + static dispatch_once_t onceToken; + static FIRInstanceIDLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [[FIRInstanceIDLogger alloc] init]; + }); + + return logger; +} diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h new file mode 100644 index 0000000..d1f2634 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h @@ -0,0 +1,183 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDCheckinStore; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDTokenStore; + +@class FIRInstanceIDStore; +@protocol FIRInstanceIDStoreDelegate + +/** + * This is called when the store has decided to invalide its tokens associated with the + * previous checkin credentials. After deleting the tokens locally, it calls this method + * to notify the delegate of the change. If possible, the delegate should use this time + * to request the invalidation of the tokens on the server as well. + */ +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +@end + +/** + * Used to persist the InstanceID tokens. This is also used to cache the Checkin + * credentials. The store also checks for stale entries in the store and + * let's us know if things in the store are stale or not. It does not however + * acts on stale entries in anyway. + */ +@interface FIRInstanceIDStore : NSObject + +/** + * The delegate set in the initializer which is notified of changes in the store. + */ +@property(nonatomic, readonly, weak) NSObject *delegate; + +- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead."))); + +/** + * Initialize a default store to persist InstanceID tokens and options. + * + * @param delegate The delegate with which to be notified of changes in the store. + * @return Store to persist InstanceID tokens. + */ +- (instancetype)initWithDelegate:(NSObject *)delegate; + +/** + * Initialize a store with the token store used to persist tokens, and a checkin store. + * Used for testing. + * + * @param checkinStore Persistent store that persists checkin preferences. + * @param tokenStore Persistent store that persists tokens. + * + * @return Store to persist InstanceID tokens and options. + */ +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Save +/** + * Save the instanceID token info to the store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler; + +#pragma mark - Get + +/** + * Get the cached token info. + * + * @param authorizedEntity The authorized entity for which we want the token. + * @param scope The scope for which we want the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * returns nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Delete + +/** + * Remove the cached token for a given authorizedEntity and scope. If the token was never + * cached or deleted from the cache before this is a no-op. + * + * @param authorizedEntity The authorizedEntity for the cached token. + * @param scope The scope for the cached token + */ +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Removes all cached tokens from the persistent store. In case deleting the cached tokens + * fails we try to delete the backup excluded plist that stores the tokens. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + * + */ +- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Persisting Checkin Preferences + +/** + * Save the checkin preferences + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(nullable void (^)(NSError *error))handler; + +/** + * Return the cached checkin preferences. + * + * @return Checkin preferences. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Remove the cached checkin preferences from the store. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Standard Directory sub-directory + +/** + * Check if supported directory has InstanceID subdirectory + * + * @return YES if the Application Support directory has InstanceID subdirectory else NO. + */ ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName; + +/** + * Create InstanceID subdirectory in Application support directory. + * + * @return YES if the subdirectory was created successfully else NO. + */ ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName; + +/** + * Removes Application Support subdirectory for InstanceID. + * + * @param error The error object if any while trying to delete the sub-directory. + * + * @return YES if the deletion was successful else NO. + */ ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m new file mode 100644 index 0000000..1c7a0d0 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDStore.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinStore.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenStore.h" +#import "FIRInstanceIDVersionUtilities.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kCheckinFileName = @"g-checkin"; + +// APNS token (use the old key value i.e. with prefix GMS) +static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version"; + +@interface FIRInstanceIDStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore; + +@end + +@implementation FIRInstanceIDStore + +- (instancetype)initWithDelegate:(NSObject *)delegate { + FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc] + initWithCheckinPlistFileName:kCheckinFileName + subDirectoryName:kFIRInstanceIDSubDirectoryName]; + + FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore]; + + return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate]; +} + +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate { + self = [super init]; + if (self) { + _checkinStore = checkinStore; + _tokenStore = tokenStore; + _delegate = delegate; + [self resetCredentialsIfNeeded]; + } + return self; +} + +#pragma mark - Upgrades + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + ++ (NSString *)pathForSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[ dirPath, subDirectoryName ]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore000, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore001, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error { + if ([self hasSubDirectory:subDirectoryName]) { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return [[NSFileManager defaultManager] removeItemAtPath:subDirectoryPath error:error]; + } + } + return YES; +} + +/** + * Reset the keychain preferences if the app had been deleted earlier and then reinstalled. + * Keychain preferences are not cleared in the above scenario so explicitly clear them. + * + * In case of an iCloud backup and restore the Keychain preferences should already be empty + * since the Keychain items are marked with `*BackupThisDeviceOnly`. + */ +- (void)resetCredentialsIfNeeded { + BOOL checkinPlistExists = [self.checkinStore hasCheckinPlist]; + // Checkin info existed in backup excluded plist. Should not be a fresh install. + if (checkinPlistExists) { + // FCM user can still have the old version of checkin, migration should only happen once. + [self.checkinStore migrateCheckinItemIfNeeded]; + return; + } + + // reset checkin in keychain if a fresh install. + // set the old checkin preferences to unregister pre-registered tokens + FIRInstanceIDCheckinPreferences *oldCheckinPreferences = + [self.checkinStore cachedCheckinPreferences]; + + if (oldCheckinPreferences) { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeStore002, + @"Removed cached checkin preferences from Keychain because this is a fresh install."); + } else { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeStore003, + @"Couldn't remove cached checkin preferences for a fresh install. Error: %@", error); + } + if (oldCheckinPreferences.deviceID.length && oldCheckinPreferences.secretToken.length) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore006, + @"App reset detected. Will delete server registrations."); + // We don't really need to delete old FCM tokens created via IID auth tokens since + // those tokens are already hashed by APNS token as the has so creating a new + // token should automatically delete the old-token. + [self.delegate store:self didDeleteFCMScopedTokensForCheckin:oldCheckinPreferences]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore009, + @"App reset detected but no valid checkin auth preferences found." + @" Will not delete server registrations."); + } + }]; + } +} + +#pragma mark - Get + +- (FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from + // the keychain. This is because not having the plist signifies a backup and restore operation. + // In case the keychain has any tokens these would now be stale and therefore should be + // deleted. + if (![authorizedEntity length] || ![scope length]) { + return nil; + } + FIRInstanceIDTokenInfo *info = [self.tokenStore tokenInfoWithAuthorizedEntity:authorizedEntity + scope:scope]; + return info; +} + +- (NSArray *)cachedTokenInfos { + return [self.tokenStore cachedTokenInfos]; +} + +#pragma mark - Save + +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *error))handler { + [self.tokenStore saveTokenInfo:tokenInfo handler:handler]; +} + +#pragma mark - Delete + +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + if (![authorizedEntity length] || ![scope length]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore012, + @"Will not delete token with invalid entity: %@, scope: %@", + authorizedEntity, scope); + return; + } + [self.tokenStore removeTokenWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)removeAllCachedTokensWithHandler:(void (^)(NSError *error))handler { + [self.tokenStore removeAllTokensWithHandler:handler]; +} + +#pragma mark - FIRInstanceIDCheckinCache protocol + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + [self.checkinStore saveCheckinPreferences:preferences handler:handler]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.checkinStore cachedCheckinPreferences]; +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *))handler { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (handler) { + handler(error); + } + }]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h new file mode 100644 index 0000000..8f2f369 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h @@ -0,0 +1,66 @@ +// +// GTMStringEncoding.h +// +// Copyright 2010 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import + +// A generic class for arbitrary base-2 to 128 string encoding and decoding. +@interface FIRInstanceIDStringEncoding : NSObject { + @private + NSData *charMapData_; + char *charMap_; + int reverseCharMap_[128]; + int shift_; + unsigned int mask_; + BOOL doPad_; + char paddingChar_; + int padLen_; +} + ++ (id)rfc4648Base64WebsafeStringEncoding; + +// Create a new, autoreleased GTMStringEncoding object with the given string, +// as described below. ++ (id)stringEncodingWithString:(NSString *)string; + +// Initialize a new GTMStringEncoding object with the string. +// +// The length of the string must be a power of 2, at least 2 and at most 128. +// Only 7-bit ASCII characters are permitted in the string. +// +// These characters are the canonical set emitted during encoding. +// If the characters have alternatives (e.g. case, easily transposed) then use +// addDecodeSynonyms: to configure them. +- (id)initWithString:(NSString *)string; + +// Indicates whether padding is performed during encoding. +- (BOOL)doPad; +- (void)setDoPad:(BOOL)doPad; + +// Sets the padding character to use during encoding. +- (void)setPaddingChar:(char)c; + +// Encode a raw binary buffer to a 7-bit ASCII string. +- (NSString *)encode:(NSData *)data; + +// Decode a 7-bit ASCII string to a raw binary buffer. +- (NSData *)decode:(NSString *)string; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m new file mode 100644 index 0000000..e1ab269 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m @@ -0,0 +1,208 @@ +// +// FIRInstanceIDStringEncoding.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import "FIRInstanceIDStringEncoding.h" + +#import "FIRInstanceIDLogger.h" + +enum { kUnknownChar = -1, kPaddingChar = -2, kIgnoreChar = -3 }; + +@implementation FIRInstanceIDStringEncoding + ++ (id)rfc4648Base64WebsafeStringEncoding { + FIRInstanceIDStringEncoding *ret = [self + stringEncodingWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]; + + [ret setPaddingChar:'=']; + [ret setDoPad:YES]; + return ret; +} + +static inline int lcm(int a, int b) { + for (int aa = a, bb = b;;) { + if (aa == bb) + return aa; + else if (aa < bb) + aa += a; + else + bb += b; + } +} + ++ (id)stringEncodingWithString:(NSString *)string { + return [[FIRInstanceIDStringEncoding alloc] initWithString:string]; +} + +- (id)initWithString:(NSString *)string { + if ((self = [super init])) { + charMapData_ = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (!charMapData_) { + // Unable to convert string to ASCII + return nil; + } + charMap_ = (char *)[charMapData_ bytes]; + NSUInteger length = [charMapData_ length]; + if (length < 2 || length > 128 || length & (length - 1)) { + // Length not a power of 2 between 2 and 128 + return nil; + } + + memset(reverseCharMap_, kUnknownChar, sizeof(reverseCharMap_)); + for (unsigned int i = 0; i < length; i++) { + if (reverseCharMap_[(int)charMap_[i]] != kUnknownChar) { + // Duplicate character at |i| + return nil; + } + reverseCharMap_[(int)charMap_[i]] = i; + } + + for (NSUInteger i = 1; i < length; i <<= 1) shift_++; + mask_ = (1 << shift_) - 1; + padLen_ = lcm(8, shift_) / shift_; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"", 1 << shift_, charMapData_]; +} + +- (BOOL)doPad { + return doPad_; +} + +- (void)setDoPad:(BOOL)doPad { + doPad_ = doPad; +} + +- (void)setPaddingChar:(char)c { + paddingChar_ = c; + reverseCharMap_[(int)c] = kPaddingChar; +} + +- (NSString *)encode:(NSData *)inData { + NSUInteger inLen = [inData length]; + if (inLen <= 0) { + // Empty input + return @""; + } + unsigned char *inBuf = (unsigned char *)[inData bytes]; + NSUInteger inPos = 0; + + NSUInteger outLen = (inLen * 8 + shift_ - 1) / shift_; + if (doPad_) { + outLen = ((outLen + padLen_ - 1) / padLen_) * padLen_; + } + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + unsigned int buffer = inBuf[inPos++]; + int bitsLeft = 8; + while (bitsLeft > 0 || inPos < inLen) { + if (bitsLeft < shift_) { + if (inPos < inLen) { + buffer <<= 8; + buffer |= (inBuf[inPos++] & 0xff); + bitsLeft += 8; + } else { + int pad = shift_ - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + unsigned int idx = (buffer >> (bitsLeft - shift_)) & mask_; + bitsLeft -= shift_; + outBuf[outPos++] = charMap_[idx]; + } + + if (doPad_) { + while (outPos < outLen) outBuf[outPos++] = paddingChar_; + } + + if (outPos != outLen) { + FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferUnderflow, + @"Underflowed output buffer"); + return nil; + } + [outData setLength:outPos]; + + return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding]; +} + +- (NSData *)decode:(NSString *)inString { + char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding]; + if (!inBuf) { + // Unable to convert buffer to ASCII + return nil; + } + NSUInteger inLen = strlen(inBuf); + + NSUInteger outLen = inLen * shift_ / 8; + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + int buffer = 0; + int bitsLeft = 0; + BOOL expectPad = NO; + for (NSUInteger i = 0; i < inLen; i++) { + int val = reverseCharMap_[(int)inBuf[i]]; + switch (val) { + case kIgnoreChar: + break; + case kPaddingChar: + expectPad = YES; + break; + case kUnknownChar: + // Unexpected data at input pos |i| + return nil; + default: + if (expectPad) { + // Expected further padding characters + return nil; + } + buffer <<= shift_; + buffer |= val & mask_; + bitsLeft += shift_; + if (bitsLeft >= 8) { + outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8)); + bitsLeft -= 8; + } + break; + } + } + + if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) { + // Incomplete trailing data + return nil; + } + + // Shorten buffer if needed due to padding chars + if (outPos > outLen) { + FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferOverflow, @"Overflowed buffer"); + } + [outData setLength:outPos]; + + return outData; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h new file mode 100644 index 0000000..b6723fd --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenDeleteOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(nullable NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(nullable NSString *)instanceID + action:(FIRInstanceIDTokenAction)action; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m new file mode 100644 index 0000000..34511c4 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m @@ -0,0 +1,118 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenDeleteOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +@implementation FIRInstanceIDTokenDeleteOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + self = [super initWithAction:action + forAuthorizedEntity:authorizedEntity + scope:scope + options:nil + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [FIRInstanceIDTokenOperation standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"delete" value:@"true"]]; + if (self.action == FIRInstanceIDTokenActionDeleteTokenAndIID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"iid-operation" + value:@"delete"]]; + } + if (self.authorizedEntity) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + } + // Typically we include our public key-signed url items, but in some cases (like deleting all FCM + // tokens), we don't. + if (self.instanceID.length > 0) { + [queryItems addObjectsFromArray:[self queryItemsWithInstanceID:self.instanceID]]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest, + @"Unregister request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError, + @"Device unregister HTTP fetch error. Error code: %ld", + _FIRInstanceID_L(error.code)); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + if (![dataResponse hasPrefix:@"deleted="] && ![dataResponse hasPrefix:@"token="]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse, + @"Invalid unregister response %@", response); + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil]; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h new file mode 100644 index 0000000..6fa800e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseHeartbeatKey; + +@interface FIRInstanceIDTokenFetchOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +@end +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m new file mode 100644 index 0000000..bdc8701 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m @@ -0,0 +1,207 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenFetchOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +#import +#import + +// We can have a static int since this error should theoretically only +// happen once (for the first time). If it repeats there is something +// else that is wrong. +static int phoneRegistrationErrorRetryCount = 0; +static const int kMaxPhoneRegistrationErrorRetryCount = 10; +NSString *const kFIRInstanceIDFirebaseUserAgentKey = @"X-firebase-client"; +NSString *const kFIRInstanceIDFirebaseHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstanceIDHeartbeatTag = @"fire-iid"; + +@implementation FIRInstanceIDTokenFetchOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super initWithAction:FIRInstanceIDTokenActionFetch + forAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + NSString *checkinVersionInfo = self.checkinPreferences.versionInfo; + [request setValue:checkinVersionInfo forHTTPHeaderField:@"info"]; + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstanceIDFirebaseUserAgentKey]; + [request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstanceIDHeartbeatTag]).stringValue + forHTTPHeaderField:kFIRInstanceIDFirebaseHeartbeatKey]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [[self class] standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-subtype" + value:self.authorizedEntity]]; + + [queryItems addObjectsFromArray:[self queryItemsWithInstanceID:self.instanceID]]; + + // Create query items from passed-in options + id apnsTokenData = self.options[kFIRInstanceIDTokenOptionsAPNSKey]; + id apnsSandboxValue = self.options[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if ([apnsTokenData isKindOfClass:[NSData class]] && + [apnsSandboxValue isKindOfClass:[NSNumber class]]) { + NSString *APNSString = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + apnsTokenData, ((NSNumber *)apnsSandboxValue).boolValue); + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsAPNSKey + value:APNSString]; + [queryItems addObject:item]; + } + id firebaseAppID = self.options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + if ([firebaseAppID isKindOfClass:[NSString class]]) { + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsFirebaseAppIDKey + value:(NSString *)firebaseAppID]; + [queryItems addObject:item]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest, + @"Register request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +#pragma mark - Request Handling + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationRequestError, + @"Token fetch HTTP error. Error Code: %ld", (long)error.code); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSDictionary *parsedResponse = [self parseFetchTokenResponse:dataResponse]; + + if ([parsedResponse[@"token"] length]) { + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded + token:parsedResponse[@"token"] + error:nil]; + return; + } + + NSString *errorValue = parsedResponse[@"Error"]; + NSError *responseError; + if (errorValue.length) { + NSArray *errorComponents = [errorValue componentsSeparatedByString:@":"]; + // HACK (Kansas replication delay), PHONE_REGISTRATION_ERROR on App + // uninstall and reinstall. + if ([errorComponents containsObject:@"PHONE_REGISTRATION_ERROR"]) { + // Encountered issue http://b/27043795 + // Retry register until successful or another error encountered or a + // certain number of tries are over. + + if (phoneRegistrationErrorRetryCount < kMaxPhoneRegistrationErrorRetryCount) { + const int nextRetryInterval = 1 << phoneRegistrationErrorRetryCount; + FIRInstanceID_WEAKIFY(self); + + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(nextRetryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + phoneRegistrationErrorRetryCount++; + [self performTokenOperation]; + }); + return; + } + } else if ([errorComponents containsObject:kFIRInstanceID_CMD_RST]) { + // Server detected the identity we use is no longer valid. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:kFIRInstanceIDIdentityInvalidatedNotification object:nil]; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal001, + @"Identity is invalid. Server request identity reset."); + responseError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidIdentity]; + } + } + if (!responseError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse, + @"Invalid fetch response, expected 'token' or 'Error' key"); + responseError = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:responseError]; +} + +// expect a response e.g. "token=\nGOOG.ttl=123" +- (NSDictionary *)parseFetchTokenResponse:(NSString *)response { + NSArray *lines = [response componentsSeparatedByString:@"\n"]; + NSMutableDictionary *parsedResponse = [NSMutableDictionary dictionary]; + for (NSString *line in lines) { + NSArray *keyAndValue = [line componentsSeparatedByString:@"="]; + if ([keyAndValue count] > 1) { + parsedResponse[keyAndValue[0]] = keyAndValue[1]; + } + } + return parsedResponse; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h new file mode 100644 index 0000000..3b752a3 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDAPNSInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an Instance ID token, and all of the relevant information + * associated with it. It can read from and write to an NSDictionary object, for + * simple serialization. + */ +@interface FIRInstanceIDTokenInfo : NSObject + +/// The authorized entity (also known as Sender ID), associated with the token. +@property(nonatomic, readonly, copy) NSString *authorizedEntity; +/// The scope associated with the token. This is an arbitrary string, typically "*". +@property(nonatomic, readonly, copy) NSString *scope; +/// The token value itself, with which all other properties are associated. +@property(nonatomic, readonly, copy) NSString *token; + +// These properties are nullable because they might not exist for tokens fetched from +// legacy storage formats. + +/// The app version that this token represents. +@property(nonatomic, readonly, copy, nullable) NSString *appVersion; +/// The Firebase app ID (also known as GMP App ID), that this token is associated with. +@property(nonatomic, readonly, copy, nullable) NSString *firebaseAppID; + +/// Tokens may not always be associated with an APNs token, and may be associated after +/// being created. +@property(nonatomic, strong, nullable) FIRInstanceIDAPNSInfo *APNSInfo; +/// The time that this token info was updated. The cache time is writeable, since in +/// some cases the token info may be refreshed from the server. In those situations, +/// the cacheTime would be updated. +@property(nonatomic, copy, nullable) NSDate *cacheTime; + +/** + * Initializes a FIRInstanceIDTokenInfo object with the required parameters. These + * parameters represent all the relevant associated data with a token. + * + * @param authorizedEntity The authorized entity (also known as Sender ID). + * @param scope The scope of the token, typically "*" meaning + * it's a "default scope". + * @param token The token value itself. + * @param appVersion The application version that this token is associated with. + * @param firebaseAppID The Firebase app ID which this token is associated with. + * @return An instance of FIRInstanceIDTokenInfo. + */ +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(nullable NSString *)appVersion + firebaseAppID:(nullable NSString *)firebaseAppID; + +/** + * Check whether the token is still fresh based on: + * 1. Last fetch token is within the 7 days. + * 2. Language setting is not changed. + * 3. App version is current. + * 4. GMP App ID is current. + * 5. token is consistent with the current IID. + * 6. APNS info has changed. + * @param IID The app identifiier that is used to check if token is prefixed with. + * @return If token is fresh. + * + */ +- (BOOL)isFreshWithIID:(NSString *)IID; + +/* + * Check whether the token is default token. + */ +- (BOOL)isDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m new file mode 100644 index 0000000..59b0e92 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m @@ -0,0 +1,212 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenInfo.h" + +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" + +/** + * @enum Token Info Dictionary Key Constants + * @discussion The keys that are checked when a token info is + * created from a dictionary. The same keys are used + * when decoding/encoding an archive. + */ +/// Specifies a dictonary key whose value represents the authorized entity, or +/// Sender ID for the token. +static NSString *const kFIRInstanceIDAuthorizedEntityKey = @"authorized_entity"; +/// Specifies a dictionary key whose value represents the scope of the token, +/// typically "*". +static NSString *const kFIRInstanceIDScopeKey = @"scope"; +/// Specifies a dictionary key which represents the token value itself. +static NSString *const kFIRInstanceIDTokenKey = @"token"; +/// Specifies a dictionary key which represents the app version associated +/// with the token. +static NSString *const kFIRInstanceIDAppVersionKey = @"app_version"; +/// Specifies a dictionary key which represents the GMP App ID associated with +/// the token. +static NSString *const kFIRInstanceIDFirebaseAppIDKey = @"firebase_app_id"; +/// Specifies a dictionary key representing an archive for a +/// `FIRInstanceIDAPNSInfo` object. +static NSString *const kFIRInstanceIDAPNSInfoKey = @"apns_info"; +/// Specifies a dictionary key representing the "last cached" time for the token. +static NSString *const kFIRInstanceIDCacheTimeKey = @"cache_time"; +/// Default interval that token stays fresh. +const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60; // 7 days. + +@implementation FIRInstanceIDTokenInfo + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(NSString *)appVersion + firebaseAppID:(NSString *)firebaseAppID { + self = [super init]; + if (self) { + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _token = [token copy]; + _appVersion = [appVersion copy]; + _firebaseAppID = [firebaseAppID copy]; + } + return self; +} + +- (BOOL)isFreshWithIID:(NSString *)IID { + // Last fetch token cache time could be null if token is from legacy storage format. Then token is + // considered not fresh and should be refreshed and overwrite with the latest storage format. + if (!IID) { + return NO; + } + if (!_cacheTime) { + return NO; + } + + // Check if it's consistent with IID + if (![self.token hasPrefix:IID]) { + return NO; + } + + // Check if app has just been updated to a new version. + NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion(); + if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004, + @"Invalidating cached token for %@ (%@) due to app version change.", + _authorizedEntity, _scope); + return NO; + } + + // Check if GMP App ID has changed + NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID(); + if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged, + @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID, + currentFirebaseAppID); + return NO; + } + + // Check whether locale has changed, if yes, token needs to be updated with server for locale + // information. + if (FIRInstanceIDHasLocaleChanged()) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged, + @"Invalidating cached token due to locale change"); + return NO; + } + + // Locale is not changed, check whether token has been fetched within 7 days. + NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970]; + NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds(); + NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp; + return (timeSinceLastFetchToken < kDefaultFetchTokenInterval); +} + +- (BOOL)isDefaultToken { + return [self.scope isEqualToString:kFIRInstanceIDDefaultTokenScope]; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + // These value cannot be nil + + id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey]; + if (![authorizedEntity isKindOfClass:[NSString class]]) { + return nil; + } + + id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey]; + if (![scope isKindOfClass:[NSString class]]) { + return nil; + } + + id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey]; + if (![token isKindOfClass:[NSString class]]) { + return nil; + } + + // These values are nullable, so only fail the decode if the type does not match + + id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey]; + if (appVersion && ![appVersion isKindOfClass:[NSString class]]) { + return nil; + } + + id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey]; + if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) { + return nil; + } + + id rawAPNSInfo = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoKey]; + if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[NSData class]]) { + return nil; + } + + FIRInstanceIDAPNSInfo *APNSInfo = nil; + if (rawAPNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + APNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:rawAPNSInfo]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo, + @"Could not parse raw APNS Info while parsing archived token info."); + APNSInfo = nil; + } @finally { + } + } + + id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey]; + if (cacheTime && ![cacheTime isKindOfClass:[NSDate class]]) { + return nil; + } + + self = [super init]; + if (self) { + _authorizedEntity = authorizedEntity; + _scope = scope; + _token = token; + _appVersion = appVersion; + _firebaseAppID = firebaseAppID; + _APNSInfo = APNSInfo; + _cacheTime = cacheTime; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.authorizedEntity forKey:kFIRInstanceIDAuthorizedEntityKey]; + [aCoder encodeObject:self.scope forKey:kFIRInstanceIDScopeKey]; + [aCoder encodeObject:self.token forKey:kFIRInstanceIDTokenKey]; + [aCoder encodeObject:self.appVersion forKey:kFIRInstanceIDAppVersionKey]; + [aCoder encodeObject:self.firebaseAppID forKey:kFIRInstanceIDFirebaseAppIDKey]; + NSData *rawAPNSInfo; + if (self.APNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + rawAPNSInfo = [NSKeyedArchiver archivedDataWithRootObject:self.APNSInfo]; +#pragma clang diagnostic pop + + [aCoder encodeObject:rawAPNSInfo forKey:kFIRInstanceIDAPNSInfoKey]; + } + [aCoder encodeObject:self.cacheTime forKey:kFIRInstanceIDCacheTimeKey]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h new file mode 100644 index 0000000..46e1ac8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +@class FIRInstanceIDAuthService; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDStore; + +typedef NS_OPTIONS(NSUInteger, FIRInstanceIDInvalidTokenReason) { + FIRInstanceIDInvalidTokenReasonNone = 0, // 0 + FIRInstanceIDInvalidTokenReasonAppVersion = (1 << 0), // 0...00001 + FIRInstanceIDInvalidTokenReasonAPNSToken = (1 << 1), // 0...00010 +}; + +/** + * Manager for the InstanceID token requests i.e `newToken` and `deleteToken`. This + * manages the overall interaction of the `InstanceIDStore`, the token register + * service and the callbacks associated with `GCMInstanceID`. + */ +@interface FIRInstanceIDTokenManager : NSObject + +/// Expose the auth service, so it can be used by others +@property(nonatomic, readonly, strong) FIRInstanceIDAuthService *authService; + +/** + * Fetch new token for the given authorizedEntity and scope. This makes an + * asynchronous request to the InstanceID backend to create a new token for + * the service and returns it. This will replace any old token for the given + * authorizedEntity and scope that has been cached before. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param options The options to be added to the fetch request. + * @param handler The handler to be invoked once we have the token or the + * fetch request to InstanceID backend results in an error. Also + * since it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Return the cached token info, if one exists, for the given authorizedEntity and scope. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info, if available, matching the parameters. + */ +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Delete the token for the given authorizedEntity and scope. If the token has + * been cached, it will be deleted from the store. It will also make an + * asynchronous request to the InstanceID backend to invalidate the token. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to + * InstanceID backend has returned. If the request was + * successful we invoke the handler with a nil error; + * otherwise we call it with an appropriate error. Also since + * it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. This method should only be triggered + * when InstanceID is deleted + * + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to InstanceID backend + * has returned. If the request was successful we invoke the handler with + * a nil error; else we pass in an appropriate error. This should be non-nil + * and be called asynchronously. + */ +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler; + +/** + * Stop any ongoing token operations. + */ +- (void)stopAllTokenOperations; + +#pragma mark - Invalidating Cached Tokens + +/** + * Invalidate any cached tokens, if the app version has changed since last launch or if the token + * is cached for more than 7 days. + * @param IID The cached instanceID, check if token is prefixed by such IID. + * + * @return Whether we should fetch default token from server. + * + * @discussion This should safely be called prior to any tokens being retrieved from + * the cache or being fetched from the network. + */ +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID; + +/** + * Upon being provided with different APNs or sandbox, any locally cached tokens + * should be deleted, and the new APNs token should be cached. + * + * @discussion It is possible for this method to be called while token operations are + * in-progress or queued. In this case, the in-flight token operations will have stale + * APNs information. The default token is checked for being out-of-date by Instance ID, + * and re-fetched. Custom tokens are not currently checked. + * + * @param deviceToken The APNS device token, provided by the operating system. + * @param isSandbox YES if the device token is for the sandbox environment, NO otherwise. + * + * @return The array of FIRInstanceIDTokenInfo objects which were invalidated. + */ +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m new file mode 100644 index 0000000..0ebcfc8 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m @@ -0,0 +1,340 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenManager.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenDeleteOperation.h" +#import "FIRInstanceIDTokenFetchOperation.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenOperation.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDTokenManager () + +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *instanceIDStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthService *authService; +@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations; + +@property(nonatomic, readwrite, strong) FIRInstanceIDAPNSInfo *currentAPNSInfo; + +@end + +@implementation FIRInstanceIDTokenManager + +- (instancetype)init { + self = [super init]; + if (self) { + _instanceIDStore = [[FIRInstanceIDStore alloc] initWithDelegate:self]; + _authService = [[FIRInstanceIDAuthService alloc] initWithStore:_instanceIDStore]; + [self configureTokenOperations]; + } + return self; +} + +- (void)dealloc { + [self stopAllTokenOperations]; +} + +- (void)configureTokenOperations { + _tokenOperations = [[NSOperationQueue alloc] init]; + _tokenOperations.name = @"com.google.iid-token-operations"; + // For now, restrict the operations to be serial, because in some cases (like if the + // authorized entity and scope are the same), order matters. + // If we have to deal with several different token requests simultaneously, it would be a good + // idea to add some better intelligence around this (performing unrelated token operations + // simultaneously, etc.). + _tokenOperations.maxConcurrentOperationCount = 1; + if ([_tokenOperations respondsToSelector:@selector(qualityOfService)]) { + _tokenOperations.qualityOfService = NSOperationQualityOfServiceUtility; + } +} + +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager000, + @"Fetch new token for authorizedEntity: %@, scope: %@", authorizedEntity, + scope); + FIRInstanceIDTokenFetchOperation *operation = + [self createFetchOperationWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + instanceID:instanceID]; + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenOperationCompletion completion = + ^(FIRInstanceIDTokenOperationResult result, NSString *_Nullable token, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + handler(nil, error); + return; + } + NSString *firebaseAppID = options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + FIRInstanceIDTokenInfo *tokenInfo = [[FIRInstanceIDTokenInfo alloc] + initWithAuthorizedEntity:authorizedEntity + scope:scope + token:token + appVersion:FIRInstanceIDCurrentAppVersion() + firebaseAppID:firebaseAppID]; + tokenInfo.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:options]; + + [self.instanceIDStore + saveTokenInfo:tokenInfo + handler:^(NSError *error) { + if (!error) { + // Do not send the token back in case the save was unsuccessful. Since with + // the new asychronous fetch mechanism this can lead to infinite loops, for + // example, we will return a valid token even though we weren't able to store + // it in our cache. The first token will lead to a onTokenRefresh callback + // wherein the user again calls `getToken` but since we weren't able to save + // it we won't hit the cache but hit the server again leading to an infinite + // loop. + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManager001, + @"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", + token, authorizedEntity, scope); + + if (handler) { + handler(token, nil); + } + } else { + if (handler) { + handler(nil, error); + } + } + }]; + }; + // Add completion handler, and ensure it's called on the main queue + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(result, token, error); + }); + }]; + [self.tokenOperations addOperation:operation]; +} + +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + return [self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if ([self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:authorizedEntity scope:scope]; + } + // Does not matter if we cannot find it in the cache. Still make an effort to unregister + // from the server. + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteToken]; + + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler { + // delete all tokens + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + if (!checkinPreferences) { + // The checkin is already deleted. No need to trigger the token delete operation as client no + // longer has the checkin information for server to delete. + dispatch_async(dispatch_get_main_queue(), ^{ + handler(nil); + }); + return; + } + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:kFIRInstanceIDKeychainWildcardIdentifier + scope:kFIRInstanceIDKeychainWildcardIdentifier + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteTokenAndIID]; + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler { + [self.instanceIDStore removeAllCachedTokensWithHandler:handler]; +} + +- (void)stopAllTokenOperations { + [self.authService stopCheckinRequest]; + [self.tokenOperations cancelAllOperations]; +} + +#pragma mark - FIRInstanceIDStoreDelegate + +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + // Make a best effort try to delete the old client related state on the FCM server. This is + // required to delete old pubusb registrations which weren't cleared when the app was deleted. + // + // This is only a one time effort. If this call fails the client would still receive duplicate + // pubsub notifications if he is again subscribed to the same topic. + // + // The client state should be cleared on the server for the provided checkin preferences. + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:nil + scope:nil + checkinPreferences:checkin + instanceID:nil + action:FIRInstanceIDTokenActionDeleteToken]; + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + FIRInstanceIDMessageCode code = + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset; + FIRInstanceIDLoggerDebug(code, @"Failed to delete GCM server registrations on app reset."); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset, + @"Successfully deleted GCM server registrations on app reset"); + } + }]; + + [self.tokenOperations addOperation:operation]; +} + +#pragma mark - Unit Testing Stub Helpers +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenFetchOperation *) + createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + instanceID:(NSString *)instanceID { + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenFetchOperation *operation = + [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + return operation; +} + +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenDeleteOperation *) + createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + FIRInstanceIDTokenDeleteOperation *operation = + [[FIRInstanceIDTokenDeleteOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:action]; + return operation; +} + +#pragma mark - Invalidating Cached Tokens +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID { + // We know at least one cached token exists. + BOOL shouldFetchDefaultToken = NO; + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *tokenInfo in tokenInfos) { + if ([tokenInfo isFreshWithIID:IID]) { + // Token is fresh and in right format, do nothing + continue; + } + if ([tokenInfo isDefaultToken]) { + // Default token is expired, do not mark for deletion. Fetch directly from server to + // replace the current one. + shouldFetchDefaultToken = YES; + } else { + // Non-default token is expired, mark for deletion. + [tokenInfosToDelete addObject:tokenInfo]; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken, + @"Invalidating cached token for %@ (%@) due to token is no longer fresh.", + tokenInfo.authorizedEntity, tokenInfo.scope); + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return shouldFetchDefaultToken; +} + +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox { + // Each cached IID token that is missing an APNSInfo, or has an APNSInfo associated should be + // checked and invalidated if needed. + FIRInstanceIDAPNSInfo *APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:deviceToken + isSandbox:isSandbox]; + if ([self.currentAPNSInfo isEqualToAPNSInfo:APNSInfo]) { + return @[]; + } + self.currentAPNSInfo = APNSInfo; + + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *cachedTokenInfo in tokenInfos) { + // Check if the cached APNSInfo is nil, or if it is an old APNSInfo. + if (!cachedTokenInfo.APNSInfo || + ![cachedTokenInfo.APNSInfo isEqualToAPNSInfo:self.currentAPNSInfo]) { + // Mark for invalidation. + [tokenInfosToDelete addObject:cachedTokenInfo]; + } + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated, + @"Invalidating cached token for %@ (%@) due to APNs token change.", + tokenInfoToDelete.authorizedEntity, tokenInfoToDelete.scope); + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return tokenInfosToDelete; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h new file mode 100644 index 0000000..3383875 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h @@ -0,0 +1,69 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDUtilities.h" + +@class FIRInstanceIDURLQueryItem; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenOperation (Private) + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + ++ (NSURLSession *)sharedURLSession; + +#pragma mark - Initialization +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +#pragma mark - Request Construction ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope; +- (NSMutableURLRequest *)tokenRequest; +- (NSArray *)queryItemsWithInstanceID:(NSString *)instanceID; + +#pragma mark - HTTP Headers +/** + * Given a valid checkin preferences object, it will return a string that can be used + * in the "Authorization" HTTP header to authenticate this request. + * + * @param checkin The valid checkin preferences object, with a deviceID and secretToken. + */ ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +#pragma mark - Result +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error; + +#pragma mark - Methods to override +- (void)performTokenOperation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h new file mode 100644 index 0000000..fa8ad08 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h @@ -0,0 +1,72 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDCheckinPreferences; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on an FCM token. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenAction) { + FIRInstanceIDTokenActionFetch, + FIRInstanceIDTokenActionDeleteToken, + FIRInstanceIDTokenActionDeleteTokenAndIID, +}; + +/** + * Represents the possible results of a token operation. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenOperationResult) { + FIRInstanceIDTokenOperationSucceeded, + FIRInstanceIDTokenOperationError, + FIRInstanceIDTokenOperationCancelled, +}; + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param result The result of the operation. + * @param token If the action for fetching a token and the request was successful, this will hold + * the value of the token. Otherwise nil. + * @param error The error which occurred while performing the token operation. This will be nil + * in case the operation was successful, or if the operation was cancelled. + */ +typedef void (^FIRInstanceIDTokenOperationCompletion)(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, + NSError *_Nullable error); + +@interface FIRInstanceIDTokenOperation : NSOperation + +@property(nonatomic, readonly) FIRInstanceIDTokenAction action; +@property(nonatomic, readonly, nullable) NSString *authorizedEntity; +@property(nonatomic, readonly, nullable) NSString *scope; +@property(nonatomic, readonly, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readonly, strong) NSString *instanceID; + +@property(nonatomic, readonly) FIRInstanceIDTokenOperationResult result; + +- (instancetype)init NS_UNAVAILABLE; + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m new file mode 100644 index 0000000..aa0f75e --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m @@ -0,0 +1,258 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2; + +static NSString *const kFIRInstanceIDParamInstanceID = @"appid"; +// Scope parameter that defines the service using the token +static NSString *const kFIRInstanceIDParamScope = @"X-scope"; +// Defines the SDK version +static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv"; + +@interface FIRInstanceIDTokenOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readwrite, strong) NSString *instanceID; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +@property(atomic, strong, nullable) NSString *FISAuthToken; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + +@end + +@implementation FIRInstanceIDTokenOperation + ++ (NSURLSession *)sharedURLSession { + static NSURLSession *tokenOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session"; + }); + return tokenOperationSharedSession; +} + +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super init]; + if (self) { + _action = action; + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _options = [options copy]; + _checkinPreferences = checkinPreferences; + _instanceID = instanceID; + _completionHandlers = [NSMutableArray array]; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _testBlock = nil; + _authorizedEntity = nil; + _scope = nil; + _options = nil; + _checkinPreferences = nil; + _instanceID = nil; + [_completionHandlers removeAllObjects]; + _completionHandlers = nil; +} + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler { + [self.completionHandlers addObject:handler]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; + return; + } + + // Quickly validate whether or not the operation has all it needs to begin + BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo]; + if (!checkinfoAvailable) { + FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn; + [self finishWithResult:FIRInstanceIDTokenOperationError + token:nil + error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]]; + return; + } + + [self setExecuting:YES]; + + [[FIRInstallations installations] + authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) { + if (tokenResult.authToken.length > 0) { + self.FISAuthToken = tokenResult.authToken; + [self performTokenOperation]; + } else { + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + } + }]; +} + +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + _result = result; + // TODO(chliangGoogle): Call these in the main thread? + for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) { + completionHandler(result, token, error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; +} + +- (void)performTokenOperation { +} + +- (NSMutableURLRequest *)tokenRequest { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + return [[self class] requestWithAuthHeader:authHeader FISAuthToken:self.FISAuthToken]; +} + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString + FISAuthToken:(NSString *)FISAuthToken { + NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + // Add HTTP headers + [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"]; + [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"]; + if (FISAuthToken) { + [request setValue:FISAuthToken forHTTPHeaderField:@"x-goog-firebase-installations-auth"]; + } + request.HTTPMethod = @"POST"; + return request; +} + ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope { + NSMutableArray *queryItems = [NSMutableArray arrayWithCapacity:8]; + + // E.g. X-osv=10.2.1 + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]]; + // E.g. device= + if (deviceID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]]; + } + // E.g. X-scope=fcm + if (scope) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope + value:scope]]; + } + // E.g. plat=2 + NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]]; + // E.g. app=com.myapp.foo + NSString *appIdentifier = FIRInstanceIDAppIdentifier(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]]; + // E.g. app_ver=1.5 + NSString *appVersion = FIRInstanceIDCurrentAppVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]]; + // E.g. X-cliv=fiid-1.2.3 + NSString *fcmLibraryVersion = + [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()]; + if (fcmLibraryVersion.length) { + FIRInstanceIDURLQueryItem *gcmLibVersion = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion + value:fcmLibraryVersion]; + [queryItems addObject:gcmLibVersion]; + } + + return queryItems; +} + +- (NSArray *)queryItemsWithInstanceID:(NSString *)instanceID { + return @[ [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:instanceID] ]; +} + +#pragma mark - HTTP Header + ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + NSString *deviceID = checkin.deviceID; + NSString *secret = checkin.secretToken; + return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret]; +} +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h new file mode 100644 index 0000000..861c87b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAPNSInfo; +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDTokenInfo; + +/** + * This class is responsible for retrieving and saving `FIRInstanceIDTokenInfo` objects from the + * keychain. The keychain keys that are used are: + * Account:
(e.g. com.mycompany.myapp) + * Service: : (e.g. 1234567890:*) + */ +@interface FIRInstanceIDTokenStore : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * Create a default InstanceID token store. Uses a valid Keychain object as it's + * persistent backing store. + * + * @return A valid token store object. + */ ++ (instancetype)defaultStore; + +- (instancetype)init __attribute__((unavailable("Use -initWithKeychain: instead."))); + +/** + * Initialize a token store object with a Keychain object. Used for testing. + * + * @param keychain The Keychain object to use as the backing store for tokens. + * + * @return A valid token store object with the given Keychain as backing store. + */ +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain; + +#pragma mark - Get + +/** + * Get the cached token from the Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Save + +/** + * Save the instanceID token info to the persistent store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when token saving is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(nullable void (^)(NSError *))handler; + +#pragma mark - Delete + +/** + * Remove the cached token from Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + */ +- (void)removeTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Remove all the cached tokens from the Keychain. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)removeAllTokensWithHandler:(nullable void (^)(NSError *))handler; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m new file mode 100644 index 0000000..f97f932 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m @@ -0,0 +1,143 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kFIRInstanceIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstanceIDTokenStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; + +@end + +@implementation FIRInstanceIDTokenStore + ++ (instancetype)defaultStore { + FIRInstanceIDAuthKeychain *tokenKeychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDTokenKeychainId]; + return [[FIRInstanceIDTokenStore alloc] initWithKeychain:tokenKeychain]; +} + +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _keychain = keychain; + } + return self; +} + +#pragma mark - Get + ++ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + NSData *item = [self.keychain dataForService:service account:account]; + if (!item) { + return nil; + } + // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo. + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + return tokenInfo; +} + +- (NSArray *)cachedTokenInfos { + NSString *account = FIRInstanceIDAppIdentifier(); + NSArray *items = + [self.keychain itemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier account:account]; + NSMutableArray *tokenInfos = + [NSMutableArray arrayWithCapacity:items.count]; + for (NSData *item in items) { + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + if (tokenInfo) { + [tokenInfos addObject:tokenInfo]; + } + } + return tokenInfos; +} + ++ (nullable FIRInstanceIDTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item { + // Check if it is saved as an archived FIRInstanceIDTokenInfo, otherwise return nil. + FIRInstanceIDTokenInfo *tokenInfo = nil; + // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged + // in the console on iOS 10 and below. Avoid by checking item.data's existence. + if (item) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item]; +#pragma clang diagnostic pop + + } @catch (NSException *exception) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo, + @"Unable to parse token info from Keychain item; item was in an " + @"invalid format"); + tokenInfo = nil; + } @finally { + } + } + return tokenInfo; +} + +#pragma mark - Save +// Token Infos will be saved under these Keychain keys: +// Account:
(e.g. com.mycompany.myapp) +// Service: : (e.g. 1234567890:*) +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *))handler { // Keep the cachetime up-to-date. + tokenInfo.cacheTime = [NSDate date]; + // Always write to the Keychain, so that the cacheTime is up-to-date. + NSData *tokenInfoData; + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo]; +#pragma clang diagnostic pop + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope]; + [self.keychain setData:tokenInfoData forService:service account:account handler:handler]; +} + +#pragma mark - Delete + +- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity + scope:(nonnull NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + [self.keychain removeItemsMatchingService:service account:account handler:nil]; +} + +- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler { + NSString *account = FIRInstanceIDAppIdentifier(); + [self.keychain removeItemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier + account:account + handler:handler]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h new file mode 100644 index 0000000..3a3a1d7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Stand-in for NSURLQueryItem, which is only available on iOS 8.0 and up. +@interface FIRInstanceIDURLQueryItem : NSObject + +@property(nonatomic, readonly) NSString *name; +@property(nonatomic, readonly) NSString *value; + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value; +- (instancetype)initWithName:(NSString *)name value:(NSString *)value; + +@end + +/** + * Given an array of query items, construct a URL query. On iOS 8.0 and above, this will use + * NSURLQueryItems internally to perform the string creation, and will be done manually in iOS + * 7 and below. + */ +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m new file mode 100644 index 0000000..59b4865 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDURLQueryItem.h" + +@implementation FIRInstanceIDURLQueryItem + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value { + return [[[self class] alloc] initWithName:name value:value]; +} + +- (instancetype)initWithName:(NSString *)name value:(NSString *)value { + self = [super init]; + if (self) { + _name = [name copy]; + _value = [value copy]; + } + return self; +} +@end + +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems) { + if ([NSURLQueryItem class]) { + // We are iOS 8.0 and above. Convert to NSURLQueryItems and get query that way + // to take advantage of any automatic encoding + NSMutableArray *urlItems = + [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [urlItems addObject:[NSURLQueryItem queryItemWithName:queryItem.name value:queryItem.value]]; + } + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = urlItems; + return components.query; + } else { + // We are on iOS 7.0. Manually create the query string + NSMutableArray *pairs = [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [pairs addObject:[NSString stringWithFormat:@"%@=%@", queryItem.name, queryItem.value]]; + } + return [pairs componentsJoinedByString:@"&"]; + } +} diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h new file mode 100644 index 0000000..da6ebad --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFCMSDKClassString; + +/// locale key stored in GULUserDefaults +FOUNDATION_EXPORT NSString *const kFIRInstanceIDUserDefaultsKeyLocale; + +#pragma mark - Test Blocks + +/** + * Response block for mock registration requests made during tests. + * + * @param data The data as returned by the mock request. + * @param response The response as returned by the mock request. + * @param error The error if any as returned by the mock request. + */ +typedef void (^FIRInstanceIDURLRequestTestResponseBlock)(NSData *data, + NSURLResponse *response, + NSError *error); + +/** + * Test block to mock registration requests response. + * + * @param request The request to mock response for. + * @param response The response block for the mocked request. + */ +typedef void (^FIRInstanceIDURLRequestTestBlock)(NSURLRequest *request, + FIRInstanceIDURLRequestTestResponseBlock response); + +#pragma mark - URL Helpers + +FOUNDATION_EXPORT NSString *FIRInstanceIDRegisterServer(void); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentifier(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDFirebaseAppID(void); + +#pragma mark - Device Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDDeviceModel(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDOperatingSystemVersion(void); +FOUNDATION_EXPORT BOOL FIRInstanceIDHasLocaleChanged(void); + +#pragma mark - Helpers + +FOUNDATION_EXPORT BOOL FIRInstanceIDIsValidGCMScope(NSString *scope); +FOUNDATION_EXPORT NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken); +FOUNDATION_EXPORT NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, + BOOL isSandbox); + +#pragma mark - GCM Helpers +/// Returns the current GCM version if GCM library is found else returns nil. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentGCMVersion(void); + +/// Returns the current locale. If GCM is present it queries GCM for a +/// Context Manager specific locale. Otherwise, it returns the system's first +/// preferred language (which may be set independently from locale). If the +/// system returns no preferred languages, this method returns the most common +/// language for the user's given locale. Guaranteed to return a nonnull value. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLocale(void); diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m new file mode 100644 index 0000000..9eaafa7 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m @@ -0,0 +1,208 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDUtilities.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif +#import + +#import +#import +#import "FIRInstanceID.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kFIRInstanceIDAPNSSandboxPrefix = @"s_"; +static NSString *const kFIRInstanceIDAPNSProdPrefix = @"p_"; + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +NSString *const kFIRInstanceIDFCMSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRInstanceIDFCMSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRInstanceIDFCMSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; + +NSString *const kFIRInstanceIDUserDefaultsKeyLocale = + @"com.firebase.instanceid.user_defaults.locale"; // locale key stored in GULUserDefaults + +/// Static values which will be populated once retrieved using +/// |FIRInstanceIDRetrieveEnvironmentInfoFromFirebaseCore|. +static NSString *operatingSystemVersion; +static NSString *hardwareDeviceModel; + +#pragma mark - URL Helpers + +NSString *FIRInstanceIDRegisterServer() { + return @"https://fcmtoken.googleapis.com/register"; +} + +#pragma mark - Time + +int64_t FIRInstanceIDCurrentTimestampInSeconds() { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRInstanceIDCurrentTimestampInMilliseconds() { + return (int64_t)(FIRInstanceIDCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRInstanceIDCurrentAppVersion() { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + return @""; + } + return version; +} + +NSString *FIRInstanceIDBundleIDByRemovingLastPartFrom(NSString *bundleID) { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleID componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +NSString *FIRInstanceIDAppIdentifier() { + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier, + @"The mainBundle's bundleIdentifier returned '%@'. Bundle identifier " + @"expected to be non-empty.", + bundleID); + return @""; + } +#if TARGET_OS_WATCH + return FIRInstanceIDBundleIDByRemovingLastPartFrom(bundleID); +#endif + return bundleID; +} + +NSString *FIRInstanceIDFirebaseAppID() { + return [FIROptions defaultOptions].googleAppID; +} + +#pragma mark - Device Info +// Get the device model from Firebase Core's App Environment Util +NSString *FIRInstanceIDDeviceModel() { + static dispatch_once_t once; + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + hardwareDeviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return hardwareDeviceModel; +} + +// Get the system version from Firebase Core's App Environment Util +NSString *FIRInstanceIDOperatingSystemVersion() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_WATCH + return [NSProcessInfo processInfo].operatingSystemVersionString; +#endif +} + +BOOL FIRInstanceIDHasLocaleChanged() { + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + if (lastLocale) { + if ([currentLocale isEqualToString:lastLocale]) { + return NO; + } + } + return YES; +} + +#pragma mark - Helpers + +BOOL FIRInstanceIDIsValidGCMScope(NSString *scope) { + return [scope compare:kFIRInstanceIDScopeFirebaseMessaging + options:NSCaseInsensitiveSearch] == NSOrderedSame; +} + +NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken) { + NSMutableString *APNSToken = [NSMutableString string]; + unsigned char *bytes = (unsigned char *)[deviceToken bytes]; + for (int i = 0; i < (int)deviceToken.length; i++) { + [APNSToken appendFormat:@"%02x", bytes[i]]; + } + return APNSToken; +} + +NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) { + if (deviceToken == nil) { + // A nil deviceToken leads to an invalid tuple string, so return nil. + return nil; + } + NSString *prefix = isSandbox ? kFIRInstanceIDAPNSSandboxPrefix : kFIRInstanceIDAPNSProdPrefix; + NSString *APNSString = FIRInstanceIDStringForAPNSDeviceToken(deviceToken); + NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString]; + + return APNSTupleString; +} + +#pragma mark - GCM Helpers + +NSString *FIRInstanceIDCurrentGCMVersion() { + Class versionClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL versionSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKVersionSelectorString); + if ([versionClass respondsToSelector:versionSelector]) { + IMP getVersionIMP = [versionClass methodForSelector:versionSelector]; + NSString *(*getVersion)(id, SEL) = (void *)getVersionIMP; + return getVersion(versionClass, versionSelector); + } + return nil; +} + +NSString *FIRInstanceIDCurrentLocale() { + Class localeClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL localeSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKLocaleSelectorString); + + if ([localeClass respondsToSelector:localeSelector]) { + IMP getLocaleIMP = [localeClass methodForSelector:localeSelector]; + NSString *(*getLocale)(id, SEL) = (void *)getLocaleIMP; + NSString *fcmLocale = getLocale(localeClass, localeSelector); + if (fcmLocale != nil) { + return fcmLocale; + } + } + + NSString *systemLanguage = [[NSLocale preferredLanguages] firstObject]; + if (systemLanguage != nil) { + return systemLanguage; + } + + if (@available(macOS 10.12, iOS 10.0, *)) { + return [NSLocale currentLocale].languageCode; + } else { + return nil; + } +} diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h new file mode 100644 index 0000000..ec5a76c --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for InstanceID Library versions. InstanceID lib follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLibraryVersion(void); +/// Returns the current Major version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRInstanceIDCurrentLibraryVersionIsBeta(void); diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m new file mode 100644 index 0000000..c2e532a --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDVersionUtilities.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; + +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRInstanceIDParseCurrentLibraryVersion() { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = + [NSMutableString stringWithUTF8String:STR(FIRInstanceID_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRInstanceIDCurrentLibraryVersion() { + FIRInstanceIDParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMajor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMinor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionPatch() { + FIRInstanceIDParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRInstanceIDCurrentLibraryVersionIsBeta() { + FIRInstanceIDParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h new file mode 100644 index 0000000..b533dc4 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDomain; + +typedef NS_ENUM(NSUInteger, FIRInstanceIDErrorCode) { + // Unknown error. + kFIRInstanceIDErrorCodeUnknown = 0, + + // Http related errors. + kFIRInstanceIDErrorCodeAuthentication = 1, + kFIRInstanceIDErrorCodeNoAccess = 2, + kFIRInstanceIDErrorCodeTimeout = 3, + kFIRInstanceIDErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRInstanceIDErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRInstanceIDErrorCodeInvalidRequest = 7, + + // InstanceID generic errors + kFIRInstanceIDErrorCodeMissingDeviceID = 501, + + // InstanceID Token specific errors + kFIRInstanceIDErrorCodeMissingAPNSToken = 1001, + kFIRInstanceIDErrorCodeMissingAPNSServerType = 1002, + kFIRInstanceIDErrorCodeInvalidAuthorizedEntity = 1003, + kFIRInstanceIDErrorCodeInvalidScope = 1004, + kFIRInstanceIDErrorCodeInvalidStart = 1005, + kFIRInstanceIDErrorCodeInvalidKeyPair = 1006, + + // InstanceID Identity specific errors + // Generic InstanceID keypair error + kFIRInstanceIDErrorCodeMissingKeyPair = 2001, + kFIRInstanceIDErrorCodeInvalidKeyPairTags = 2002, + kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime = 2005, + kFIRInstanceIDErrorCodeInvalidIdentity = 2006, + +}; + +@interface NSError (FIRInstanceID) + +@property(nonatomic, readonly) FIRInstanceIDErrorCode instanceIDErrorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo; + ++ (NSError *)FIRInstanceIDErrorMissingCheckin; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m new file mode 100644 index 0000000..560a5df --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRInstanceID.h" + +NSString *const kFIRInstanceIDDomain = @"com.firebase.iid"; + +@implementation NSError (FIRInstanceID) + +- (FIRInstanceIDErrorCode)instanceIDErrorCode { + return (FIRInstanceIDErrorCode)self.code; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode { + return [NSError errorWithFIRInstanceIDErrorCode:errorCode userInfo:nil]; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRInstanceIDDomain code:errorCode userInfo:userInfo]; +} + ++ (NSError *)FIRInstanceIDErrorMissingCheckin { + NSDictionary *userInfo = @{@"msg" : @"Missing device credentials. Retry later."}; + + return [NSError errorWithDomain:kFIRInstanceIDDomain + code:kFIRInstanceIDErrorCodeMissingDeviceID + userInfo:userInfo]; +} + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h new file mode 100644 index 0000000..632e21b --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/** + * @related FIRInstanceIDCheckinService + * + * The completion handler invoked once the fetch from Checkin server finishes. + * For successful fetches we returned checkin information by the checkin service + * and `nil` error, else we return the appropriate error object as reported by the + * Checkin Service. + * + * @param checkinPreferences The checkin preferences as fetched from the server. + * @param error The error object which fetching GServices data. + */ +typedef void (^FIRInstanceIDDeviceCheckinCompletion)( + FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error); + +/** + * Private API used by Firebase SDK teams by calling in reflection or internal teams. + */ +@interface FIRInstanceID (Private) + +/** + * Fetches checkin info for the app. If the app has valid cached checkin preferences + * they are returned instead of making a network request. + * + * @param handler The completion handler to invoke once the request has completed. + */ +- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Get the InstanceID for the app. If an ID was created before and cached + * successfully we will return that ID. If no cached ID exists we create + * a new ID, cache it and return that. + * + * This is a blocking call and should not really be called on the main thread. + * + * @param error The error object that represents the error while trying to + * retrieve the instance id. + * + * @return The InstanceID for the app. + */ +- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error + DEPRECATED_MSG_ATTRIBUTE("Please use getID(handler:) for Swift or " + "getIDWithHandler: for Objective-C instead."); + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h new file mode 100644 index 0000000..be3ec57 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin + * provides is used to authenticate all future requests to the server. Besides the deviceID + * and secret the other information that checkin provides is stored in a plist on the device. + * The deviceID and secret are persisted in the device keychain. + */ +@interface FIRInstanceIDCheckinPreferences : NSObject + +/** + * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain. + */ +@property(nonatomic, readonly, copy) NSString *deviceID; +@property(nonatomic, readonly, copy) NSString *secretToken; + +/** + * All the other checkin preferences other than deviceID and secret are stored in a plist. + */ +@property(nonatomic, readonly, copy) NSString *deviceDataVersion; +@property(nonatomic, readonly, copy) NSString *digest; +@property(nonatomic, readonly, copy) NSString *versionInfo; +@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis; + +/** + * The content retrieved from checkin server that should be persisted in a plist. This + * doesn't contain the deviceID and secret which are stored in the Keychain since they + * should be more private. + * + * @return The checkin preferences that should be persisted in a plist. + */ +- (NSDictionary *)checkinPlistContents; + +/** + * Return whether checkin info exists, valid or not. + */ +- (BOOL)hasCheckinInfo; + +/** + * Verify if checkin preferences are valid or not. + * + * @return YES if valid checkin preferences else NO. + */ +- (BOOL)hasValidCheckinInfo; + +@end diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h new file mode 100644 index 0000000..c343f88 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h @@ -0,0 +1,74 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstallations; + +/** + * Private API used by other Firebase SDKs. + */ +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; +@property(nonatomic, readonly, strong) NSString *versionInfo; + +@property(nonatomic, readonly, strong) FIRInstallations *installations; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, readonly, copy, nullable) NSString *firebaseInstallationsID; + +/** + * Private initializer. + */ +- (instancetype)initPrivately; + +/** + * Returns a Firebase Messaging scoped token for the firebase app. + * + * @return Returns the stored token if the device has registered with Firebase Messaging, otherwise + * returns nil. + */ +- (nullable NSString *)token; + +/** + * Verify if valid checkin preferences have been loaded in memory. + * + * @return YES if valid checkin preferences exist in memory else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Try to load prefetched checkin preferences from the cache. This supports the use case where + * InstanceID library has already obtained a valid checkin and we should be using that. + * + * This should be used as a last gasp effort to retreive any cached checkin preferences before + * hitting the FIRMessaging backend to retrieve new preferences. + * + * Note this is only required because InstanceID and FIRMessaging both require checkin preferences + * which need to be synced with each other. + * + * @return YES if successfully loaded cached checkin preferences into memory else NO. + */ +- (BOOL)tryToLoadValidCheckinInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h new file mode 100644 index 0000000..0f96d91 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h @@ -0,0 +1,312 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDResult; +/** + * @memberof FIRInstanceID + * + * The scope to be used when fetching/deleting a token for Firebase Messaging. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDScopeFirebaseMessaging + NS_SWIFT_NAME(InstanceIDScopeFirebaseMessaging); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT const NSNotificationName kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefresh); +#else +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefreshNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID token returns. If + * the call fails we return the appropriate `error code` as described below. + * + * @param token The valid token as returned by InstanceID backend. + * + * @param error The error describing why generating a new token + * failed. See the error codes below for a more detailed + * description. + */ +typedef void (^FIRInstanceIDTokenHandler)(NSString *__nullable token, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID `deleteToken` returns. If + * the call fails we return the appropriate `error code` as described below + * + * @param error The error describing why deleting the token failed. + * See the error codes below for a more detailed description. + */ +typedef void (^FIRInstanceIDDeleteTokenHandler)(NSError *error) + NS_SWIFT_NAME(InstanceIDDeleteTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity is created. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param identity A valid identity for the app instance, nil if there was an error + * while creating an identity. + * @param error The error if fetching the identity fails else nil. + */ +typedef void (^FIRInstanceIDHandler)(NSString *__nullable identity, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and all the tokens associated + * with it are deleted. Returns a valid error object in case of failure else nil. + * + * @param error The error if deleting the identity and all the tokens associated with + * it fails else nil. + */ +typedef void (^FIRInstanceIDDeleteHandler)(NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDDeleteHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and token are fetched. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param result The result containing an identity for the app instance and a valid token, + * nil if there was an error while creating the result. + * @param error The error if fetching the identity or token fails else nil. + */ +typedef void (^FIRInstanceIDResultHandler)(FIRInstanceIDResult *__nullable result, + NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDResultHandler); + +/** + * Public errors produced by InstanceID. + */ +typedef NS_ENUM(NSUInteger, FIRInstanceIDError) { + // Http related errors. + + /// Unknown error. + FIRInstanceIDErrorUnknown = 0, + + /// Auth Error -- GCM couldn't validate request from this client. + FIRInstanceIDErrorAuthentication = 1, + + /// NoAccess -- InstanceID service cannot be accessed. + FIRInstanceIDErrorNoAccess = 2, + + /// Timeout -- Request to InstanceID backend timed out. + FIRInstanceIDErrorTimeout = 3, + + /// Network -- No network available to reach the servers. + FIRInstanceIDErrorNetwork = 4, + + /// OperationInProgress -- Another similar operation in progress, + /// bailing this one. + FIRInstanceIDErrorOperationInProgress = 5, + + /// InvalidRequest -- Some parameters of the request were invalid. + FIRInstanceIDErrorInvalidRequest = 7, +} NS_SWIFT_NAME(InstanceIDError); + +/** + * A class contains the results of InstanceID and token query. + */ +NS_SWIFT_NAME(InstanceIDResult) +@interface FIRInstanceIDResult : NSObject + +/** + * An instanceID uniquely identifies the app instance. + */ +@property(nonatomic, readonly, copy) NSString *instanceID; + +/* + * Returns a Firebase Messaging scoped token for the firebase app. + */ +@property(nonatomic, readonly, copy) NSString *token; + +@end + +/** + * Instance ID provides a unique identifier for each app instance and a mechanism + * to authenticate and authorize actions (for example, sending an FCM message). + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * Instance ID is long lived but, may be reset if the device is not used for + * a long time or the Instance ID service detects a problem. + * If Instance ID is reset, the app will be notified via + * `kFIRInstanceIDTokenRefreshNotification`. + * + * If the Instance ID has become invalid, the app can request a new one and + * send it to the app server. + * To prove ownership of Instance ID and to allow servers to access data or + * services associated with the app, call + * `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + */ +NS_SWIFT_NAME(InstanceID) +@interface FIRInstanceID : NSObject + +/** + * FIRInstanceID. + * + * @return A shared instance of FIRInstanceID. + */ ++ (instancetype)instanceID NS_SWIFT_NAME(instanceID()); + +/** + * Unavailable. Use +instanceID instead. + */ +- (instancetype)init __attribute__((unavailable("Use +instanceID instead."))); + +#pragma mark - Tokens + +/** + * Returns a result of app instance identifier InstanceID and a Firebase Messaging scoped token. + * param handler The callback handler invoked when an app instanceID and a default token + * are generated and returned. If instanceID and token fetching fail for some + * reason the callback is invoked with nil `result` and the appropriate error. + */ +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler; + +/** + * Returns a token that authorizes an Entity (example: cloud service) to perform + * an action on behalf of the application identified by Instance ID. + * + * This is similar to an OAuth2 token except, it applies to the + * application instance instead of a user. + * + * This is an asynchronous call. If the token fetching fails for some reason + * we invoke the completion callback with nil `token` and the appropriate + * error. + * + * This generates an Instance ID if it does not exist yet, which starts periodically sending + * information to the Firebase backend (see `[FIRInstanceID getIDWithHandler:]`). + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at any point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an + * error with code `OperationInProgress`. + * + * @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler: + * + * @param authorizedEntity Entity authorized by the token. + * @param scope Action authorized for authorizedEntity. + * @param options The extra options to be sent with your token request. The + * value for the `apns_token` should be the NSData object + * passed to the UIApplicationDelegate's + * `didRegisterForRemoteNotificationsWithDeviceToken` method. + * The value for `apns_sandbox` should be a boolean (or an + * NSNumber representing a BOOL in Objective-C) set to true if + * your app is a debug build, which means that the APNs + * device token is for the sandbox environment. It should be + * set to false otherwise. If the `apns_sandbox` key is not + * provided, an automatically-detected value shall be used. + * @param handler The callback handler which is invoked when the token is + * successfully fetched. In case of success a valid `token` and + * `nil` error are returned. In case of any error the `token` + * is nil and a valid `error` is returned. The valid error + * codes have been documented above. + */ +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Revokes access to a scope (action) for an entity previously + * authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + * + * This is an asynchronous call. Call this on the main thread since InstanceID lib + * is not thread safe. In case token deletion fails for some reason we invoke the + * `handler` callback passed in with the appropriate error code. + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at a point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an error + * with code `OperationInProgress`. + * + * @param authorizedEntity Entity that must no longer have access. + * @param scope Action that entity is no longer authorized to perform. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of error an appropriate error object is returned + * else error is nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +#pragma mark - Identity + +/** + * Asynchronously fetch a stable identifier that uniquely identifies the app + * instance. If the identifier has been revoked or has expired, this method will + * return a new identifier. + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * @param handler The handler to invoke once the identifier has been fetched. + * In case of error an appropriate error object is returned else + * a valid identifier is returned and a valid identifier for the + * application instance. + */ +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler NS_SWIFT_NAME(getID(handler:)); + +/** + * Resets Instance ID and revokes all tokens. + * + * This method also triggers a request to fetch a new Instance ID and Firebase Messaging scope + * token. Please listen to kFIRInstanceIDTokenRefreshNotification when the new ID and token are + * ready. + * + * This stops the periodic sending of data to the Firebase backend that began when the Instance ID + * was generated. No more data is sent until another library calls Instance ID internally again + * (like FCM, RemoteConfig or Analytics) or user explicitly calls Instance ID APIs to get an + * Instance ID and token again. + */ +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler NS_SWIFT_NAME(deleteID(handler:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h new file mode 100644 index 0000000..78c9ef1 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/LICENSE b/PediatricPancreas/Pods/FirebaseInstanceID/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/FirebaseInstanceID/README.md b/PediatricPancreas/Pods/FirebaseInstanceID/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas/Pods/FirebaseInstanceID/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement new file mode 100755 index 0000000..de27b25 Binary files /dev/null and b/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap b/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap new file mode 100755 index 0000000..de80e9e --- /dev/null +++ b/PediatricPancreas/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module GoogleAppMeasurement { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m new file mode 100644 index 0000000..3e5f57b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORAssert.h" + +GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) { + // This class is only compiled in by unit tests, and this should fail quickly in optimized builds. + Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper"); + if (__builtin_expect(!!GDTCORAssertClass, 0)) { + SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock"); + if (assertionBlockSEL) { + IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL]; + if (assertionBlockIMP) { + GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)( + GDTCORAssertClass, assertionBlockSEL); + if (assertionBlock) { + return assertionBlock; + } + } + } + } + return NULL; +} diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m new file mode 100644 index 0000000..f0ea8ab --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m @@ -0,0 +1,164 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORClock.h" + +#import + +// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all +// are subject to drift. That it to say, multiple consecutive calls do not always result in a +// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external +// factors. This class attempts to determine the wall-clock time at the time of the event by +// capturing the kernel start and time since boot to determine a wallclock time in UTC. +// +// Timezone offsets at the time of a snapshot are also captured in order to provide local-time +// details. Other classes in this library depend on comparing times at some time in the future to +// a time captured in the past, and this class needs to provide a mechanism to do that. +// +// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide +// a monotonic clock mechanism to accurately check if some clock snapshot was before or after +// by using a shared reference point (kernel boot time). +// +// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be +// difficult to unit test. + +/** Returns the kernel boottime property from sysctl. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The KERN_BOOTTIME property from sysctl, in nanoseconds. + */ +static int64_t KernelBootTimeInNanoseconds() { + // Caching the result is not possible because clock drift would not be accounted for. + struct timeval boottime; + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + size_t size = sizeof(boottime); + int rc = sysctl(mib, 2, &boottime, &size, NULL, 0); + if (rc != 0) { + return 0; + } + return (int64_t)boottime.tv_sec * NSEC_PER_MSEC + (int64_t)boottime.tv_usec; +} + +/** Returns value of gettimeofday, in nanoseconds. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The value of gettimeofday, in nanoseconds. + */ +static int64_t UptimeInNanoseconds() { + int64_t before_now; + int64_t after_now; + struct timeval now; + + before_now = KernelBootTimeInNanoseconds(); + // Addresses a race condition in which the system time has updated, but the boottime has not. + do { + gettimeofday(&now, NULL); + after_now = KernelBootTimeInNanoseconds(); + } while (after_now != before_now); + return (int64_t)now.tv_sec * NSEC_PER_MSEC + (int64_t)now.tv_usec - before_now; +} + +// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE. +@implementation GDTCORClock + +- (instancetype)init { + self = [super init]; + if (self) { + _kernelBootTime = KernelBootTimeInNanoseconds(); + _uptime = UptimeInNanoseconds(); + _timeMillis = + (int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC); + CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem(); + _timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0); + CFRelease(timeZoneRef); + } + return self; +} + ++ (GDTCORClock *)snapshot { + return [[GDTCORClock alloc] init]; +} + ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture { + GDTCORClock *snapshot = [self snapshot]; + snapshot->_timeMillis += millisInTheFuture; + return snapshot; +} + +- (BOOL)isAfter:(GDTCORClock *)otherClock { + // These clocks are trivially comparable when they share a kernel boot time. + if (_kernelBootTime == otherClock->_kernelBootTime) { + int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) - + (otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds); + return timeDiff > 0; + } else { + int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime; + // This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO + // is returned. This can be altered by changing the system time and rebooting. + return kernelBootTimeDiff < 0 ? YES : NO; + } +} + +- (NSUInteger)hash { + return [@(_kernelBootTime) hash] ^ [@(_uptime) hash] ^ [@(_timeMillis) hash] ^ + [@(_timezoneOffsetSeconds) hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - NSSecureCoding + +/** NSKeyedCoder key for timeMillis property. */ +static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis"; + +/** NSKeyedCoder key for timezoneOffsetMillis property. */ +static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds"; + +/** NSKeyedCoder key for _kernelBootTime ivar. */ +static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime"; + +/** NSKeyedCoder key for _uptime ivar. */ +static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + // TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and + // uptimeMillis ivars + _timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey]; + _timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds]; + _kernelBootTime = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime]; + _uptime = [aDecoder decodeInt64ForKey:kGDTCORClockUptime]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey]; + [aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds]; + [aCoder encodeInt64:_kernelBootTime forKey:kGDTCORClockKernelBootTime]; + [aCoder encodeInt64:_uptime forKey:kGDTCORClockUptime]; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m new file mode 100644 index 0000000..6df92a5 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h" + +/** The console logger prefix. */ +static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]"; + +NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) { + return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code]; +} + +void GDTCORLog(GDTCORMessageCode code, NSString *format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); +#endif // !NDEBUG +} diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m new file mode 100644 index 0000000..33c3f15 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@implementation GDTCORDataFuture + +- (instancetype)initWithFileURL:(NSURL *)fileURL { + self = [super init]; + if (self) { + _fileURL = fileURL; + } + return self; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (NSUInteger)hash { + // In reality, only one of these should be populated. + return [_fileURL hash] ^ [_originalData hash]; +} + +#pragma mark - NSSecureCoding + +/** Coding key for _fileURL ivar. */ +static NSString *kGDTCORDataFutureFileURLKey = @"GDTCORDataFutureFileURLKey"; + +/** Coding key for _data ivar. */ +static NSString *kGDTCORDataFutureDataKey = @"GDTCORDataFutureDataKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_fileURL forKey:kGDTCORDataFutureFileURLKey]; + [aCoder encodeObject:_originalData forKey:kGDTCORDataFutureDataKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [self init]; + if (self) { + _fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTCORDataFutureFileURLKey]; + _originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTCORDataFutureDataKey]; + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m new file mode 100644 index 0000000..ed0c8e8 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m @@ -0,0 +1,123 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" + +@implementation GDTCOREvent + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _target = target; + _qosTier = GDTCOREventQosDefault; + } + GDTCORLogDebug("Event %@ created. mappingID: %@ target:%ld qos:%ld", self, _mappingID, + (long)_target, (long)_qosTier); + return self; +} + +- (instancetype)copy { + GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; + copy.dataObject = _dataObject; + copy.dataObjectTransportBytes = _dataObjectTransportBytes; + copy.qosTier = _qosTier; + copy.clockSnapshot = _clockSnapshot; + copy.customPrioritizationParams = _customPrioritizationParams; + GDTCORLogDebug("Copying event %@ to event %@", self, copy); + return copy; +} + +- (NSUInteger)hash { + // This loses some precision, but it's probably fine. + NSUInteger mappingIDHash = [_mappingID hash]; + NSUInteger timeHash = [_clockSnapshot hash]; + NSUInteger dataObjectTransportBytesHash = [_dataObjectTransportBytes hash]; + return mappingIDHash ^ _target ^ dataObjectTransportBytesHash ^ _qosTier ^ timeHash; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (void)setDataObject:(id)dataObject { + // If you're looking here because of a performance issue in -transportBytes slowing the assignment + // of -dataObject, one way to address this is to add a queue to this class, + // dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync. + if (dataObject != _dataObject) { + _dataObject = dataObject; + _dataObjectTransportBytes = [dataObject transportBytes]; + } +} + +- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture { + return [[GDTCORStoredEvent alloc] initWithEvent:self dataFuture:dataFuture]; +} + +#pragma mark - NSSecureCoding and NSCoding Protocols + +/** NSCoding key for mappingID property. */ +static NSString *mappingIDKey = @"_mappingID"; + +/** NSCoding key for target property. */ +static NSString *targetKey = @"_target"; + +/** NSCoding key for dataObjectTransportBytes property. */ +static NSString *dataObjectTransportBytesKey = @"_dataObjectTransportBytesKey"; + +/** NSCoding key for qosTier property. */ +static NSString *qosTierKey = @"_qosTier"; + +/** NSCoding key for clockSnapshot property. */ +static NSString *clockSnapshotKey = @"_clockSnapshot"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + NSString *mappingID = [aDecoder decodeObjectOfClass:[NSObject class] forKey:mappingIDKey]; + NSInteger target = [aDecoder decodeIntegerForKey:targetKey]; + self = [self initWithMappingID:mappingID target:target]; + if (self) { + _dataObjectTransportBytes = [aDecoder decodeObjectOfClass:[NSData class] + forKey:dataObjectTransportBytesKey]; + _qosTier = [aDecoder decodeIntegerForKey:qosTierKey]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_mappingID forKey:mappingIDKey]; + [aCoder encodeInteger:_target forKey:targetKey]; + [aCoder encodeObject:_dataObjectTransportBytes forKey:dataObjectTransportBytesKey]; + [aCoder encodeInteger:_qosTier forKey:qosTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:clockSnapshotKey]; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m new file mode 100644 index 0000000..cd554ad --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m @@ -0,0 +1,132 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORLifecycle.h" + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +@implementation GDTCORLifecycle + ++ (void)load { + [self sharedInstance]; +} + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance { + static GDTCORLifecycle *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORLifecycle alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:kGDTCORApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(applicationWillEnterForeground:) + name:kGDTCORApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = kGDTCORApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(applicationWillTerminate:) + name:name + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)applicationDidEnterBackground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is backgrounding."); + [[GDTCORTransformer sharedInstance] appWillBackground:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is backgrounding."); + [[GDTCORStorage sharedInstance] appWillBackground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is backgrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillBackground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is backgrounding."); + [[GDTCORRegistrar sharedInstance] appWillBackground:application]; + } +} + +- (void)applicationWillEnterForeground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is foregrounding."); + [[GDTCORTransformer sharedInstance] appWillForeground:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is foregrounding."); + [[GDTCORStorage sharedInstance] appWillForeground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is foregrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillForeground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is foregrounding."); + [[GDTCORRegistrar sharedInstance] appWillForeground:application]; + } +} + +- (void)applicationWillTerminate:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is terminating."); + [[GDTCORTransformer sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is terminating."); + [[GDTCORStorage sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is terminating."); + [[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is terminating."); + [[GDTCORRegistrar sharedInstance] appWillTerminate:application]; + } +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m new file mode 100644 index 0000000..778ced9 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m @@ -0,0 +1,222 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#ifdef GDTCOR_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION); +#else +NSString *const kGDTCORVersion = @"Unknown"; +#endif // GDTCOR_VERSION + +const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0; + +NSString *const kGDTCORApplicationDidEnterBackgroundNotification = + @"GDTCORApplicationDidEnterBackgroundNotification"; + +NSString *const kGDTCORApplicationWillEnterForegroundNotification = + @"GDTCORApplicationWillEnterForegroundNotification"; + +NSString *const kGDTCORApplicationWillTerminateNotification = + @"GDTCORApplicationWillTerminateNotification"; +#if !TARGET_OS_WATCH +BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) { +#if TARGET_OS_IOS + return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN; +#else + return NO; +#endif // TARGET_OS_IOS +} +#endif // !TARGET_OS_WATCH + +@interface GDTCORApplication () +/** + Private flag to match the existing `readonly` public flag. This will be accurate for all platforms, + since we handle each platform's lifecycle notifications separately. + */ +@property(atomic, readwrite) BOOL isRunningInBackground; + +@end + +@implementation GDTCORApplication + ++ (void)load { + GDTCORLogDebug( + "%@", @"GDT is initializing. Please note that if you quit the app via the " + "debugger and not through a lifecycle event, event data will remain on disk but " + "storage won't have a reference to them since the singleton wasn't saved to disk."); +#if TARGET_OS_IOS || TARGET_OS_TV + // If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues. + GDTCORFatalAssert( + GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid, + @"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same."); +#endif + [self sharedApplication]; +} + ++ (nullable GDTCORApplication *)sharedApplication { + static GDTCORApplication *application; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + application = [[GDTCORApplication alloc] init]; + }); + return application; +} + +- (instancetype)init { + self = [super init]; + if (self) { + // This class will be instantiated in the foreground. + _isRunningInBackground = NO; + +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = UIApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillTerminate:) + name:name + object:nil]; + +#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13, tvOS 13.0, *)) { + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UISceneWillEnterForegroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UISceneWillDeactivateNotification + object:nil]; + } +#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + +#elif TARGET_OS_OSX + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(macOSApplicationWillTerminate:) + name:NSApplicationWillTerminateNotification + object:nil]; +#endif // TARGET_OS_IOS || TARGET_OS_TV + } + return self; +} + +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^)(void))handler { + GDTCORBackgroundIdentifier bgID = + [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name + expirationHandler:handler]; +#if !NDEBUG + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug("Creating background task with name:%@ bgID:%ld", name, (long)bgID); + } +#endif // !NDEBUG + return bgID; +} + +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID { + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug("Ending background task with ID:%ld was successful", (long)bgID); + [[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID]; + return; + } +} + +#pragma mark - App environment helpers + +- (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + +/** Returns a UIApplication instance if on the appropriate platform. + * + * @return The shared UIApplication if on the appropriate platform. + */ +#if TARGET_OS_IOS || TARGET_OS_TV +- (nullable UIApplication *)sharedApplicationForBackgroundTask { +#else +- (nullable id)sharedApplicationForBackgroundTask { +#endif + if ([self isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif { + _isRunningInBackground = YES; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is backgrounding."); + [notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil]; +} + +- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif { + _isRunningInBackground = NO; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is foregrounding."); + [notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil]; +} + +- (void)iOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - NSApplicationDelegate + +#if TARGET_OS_OSX +- (void)macOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_OSX + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m new file mode 100644 index 0000000..1c6555a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m @@ -0,0 +1,118 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORReachability.h" +#import "GDTCORLibrary/Private/GDTCORReachability_Private.h" +#if !TARGET_OS_WATCH + +#import + +#import + +/** Sets the _callbackFlag ivar whenever the network changes. + * + * @param reachability The reachability object calling back. + * @param flags The new flag values. + * @param info Any data that might be passed in by the callback. + */ +static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +@implementation GDTCORReachability { + /** The reachability object. */ + SCNetworkReachabilityRef _reachabilityRef; + + /** The queue on which callbacks and all work will occur. */ + dispatch_queue_t _reachabilityQueue; + + /** Flags specified by reachability callbacks. */ + SCNetworkConnectionFlags _callbackFlags; +} + ++ (void)load { + [self sharedInstance]; +} + ++ (instancetype)sharedInstance { + static GDTCORReachability *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORReachability alloc] init]; + }); + return sharedInstance; +} + ++ (SCNetworkReachabilityFlags)currentFlags { + __block SCNetworkReachabilityFlags currentFlags; + dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{ + GDTCORReachability *reachability = [GDTCORReachability sharedInstance]; + currentFlags = reachability->_flags ? reachability->_flags : reachability->_callbackFlags; + GDTCORLogDebug("Initial reachability flags determined: %d", currentFlags); + }); + return currentFlags; +} + +- (instancetype)init { + self = [super init]; + if (self) { + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + _reachabilityQueue = + dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL); + _reachabilityRef = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set."); + } + success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", + @"The reachability callback wasn't set."); + } + + // Get the initial set of flags. + dispatch_async(_reachabilityQueue, ^{ + Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags); + if (!valid) { + GDTCORLogDebug("%@", @"Determining reachability failed."); + self->_flags = 0; + } + }); + } + return self; +} + +- (void)setCallbackFlags:(SCNetworkReachabilityFlags)flags { + if (_callbackFlags != flags) { + self->_callbackFlags = flags; + } +} + +@end + +static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GDTCORLogDebug("Reachability changed, new flags: %d", flags); + [[GDTCORReachability sharedInstance] setCallbackFlags:flags]; +} + +#endif diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m new file mode 100644 index 0000000..1440376 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m @@ -0,0 +1,142 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORRegistrar.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#import + +@implementation GDTCORRegistrar { + /** Backing ivar for targetToUploader property. */ + NSMutableDictionary> *_targetToUploader; + + /** Backing ivar for targetToPrioritizer property. */ + NSMutableDictionary> *_targetToPrioritizer; +} + ++ (instancetype)sharedInstance { + static GDTCORRegistrar *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORRegistrar alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _registrarQueue = dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_SERIAL); + _targetToPrioritizer = [[NSMutableDictionary alloc] init]; + _targetToUploader = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)registerUploader:(id)backend target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug("Registered an uploader: %@ for target:%ld", backend, (long)target); + strongSelf->_targetToUploader[@(target)] = backend; + } + }); +} + +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug("Registered a prioritizer: %@ for target:%ld", prioritizer, (long)target); + strongSelf->_targetToPrioritizer[@(target)] = prioritizer; + } + }); +} + +- (NSMutableDictionary> *)targetToUploader { + __block NSMutableDictionary> *targetToUploader; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToUploader = strongSelf->_targetToUploader; + } + }); + return targetToUploader; +} + +- (NSMutableDictionary> *)targetToPrioritizer { + __block NSMutableDictionary> *targetToPrioritizer; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToPrioritizer = strongSelf->_targetToPrioritizer; + } + }); + return targetToPrioritizer; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillBackground:(nonnull GDTCORApplication *)app { + dispatch_async(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillBackground:)]) { + [uploader appWillBackground:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) { + [prioritizer appWillBackground:app]; + } + } + }); +} + +- (void)appWillForeground:(nonnull GDTCORApplication *)app { + dispatch_async(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillForeground:)]) { + [uploader appWillForeground:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) { + [prioritizer appWillForeground:app]; + } + } + }); +} + +- (void)appWillTerminate:(nonnull GDTCORApplication *)app { + dispatch_sync(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillTerminate:)]) { + [uploader appWillTerminate:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) { + [prioritizer appWillTerminate:app]; + } + } + }); +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m new file mode 100644 index 0000000..a694471 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m @@ -0,0 +1,345 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORStorage.h" +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" + +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +/** Creates and/or returns a singleton NSString that is the shared storage path. + * + * @return The SDK event storage path. + */ +static NSString *GDTCORStoragePath() { + static NSString *storagePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cachePath = + NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; + storagePath = [NSString stringWithFormat:@"%@/google-sdks-events", cachePath]; + GDTCORLogDebug("Events will be saved to %@", storagePath); + }); + return storagePath; +} + +@implementation GDTCORStorage + ++ (NSString *)archivePath { + static NSString *archivePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + archivePath = [GDTCORStoragePath() stringByAppendingPathComponent:@"GDTCORStorageArchive"]; + }); + return archivePath; +} + ++ (instancetype)sharedInstance { + static GDTCORStorage *sharedStorage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedStorage = [[GDTCORStorage alloc] init]; + }); + return sharedStorage; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _storageQueue = dispatch_queue_create("com.google.GDTCORStorage", DISPATCH_QUEUE_SERIAL); + _targetToEventSet = [[NSMutableDictionary alloc] init]; + _storedEvents = [[NSMutableOrderedSet alloc] init]; + _uploadCoordinator = [GDTCORUploadCoordinator sharedInstance]; + } + return self; +} + +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion { + GDTCORLogDebug("Saving event: %@", event); + if (event == nil) { + GDTCORLogDebug("%@", @"The event was nil, so it was not saved."); + return; + } + if (!completion) { + completion = ^(BOOL wasWritten, NSError *error) { + }; + } + + [self createEventDirectoryIfNotExists]; + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + // End the background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + dispatch_async(_storageQueue, ^{ + // Check that a backend implementation is available for this target. + NSInteger target = event.target; + + // Check that a prioritizer is available for this target. + id prioritizer = + [GDTCORRegistrar sharedInstance].targetToPrioritizer[@(target)]; + GDTCORAssert(prioritizer, @"There's no prioritizer registered for the given target. Are you " + @"sure you've added the support library for the backend you need?"); + + // Write the transport bytes to disk, get a filename. + GDTCORAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes"); + NSError *error = nil; + NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes + eventHash:event.hash + error:&error]; + GDTCORLogDebug("Event saved to disk: %@", eventFile); + GDTCORDataFuture *dataFuture = [[GDTCORDataFuture alloc] initWithFileURL:eventFile]; + GDTCORStoredEvent *storedEvent = [event storedEventWithDataFuture:dataFuture]; + completion(eventFile != nil, error); + + // Add event to tracking collections. + [self addEventToTrackingCollections:storedEvent]; + + // Have the prioritizer prioritize the event. + [prioritizer prioritizeEvent:storedEvent]; + + // Check the QoS, if it's high priority, notify the target that it has a high priority event. + if (event.qosTier == GDTCOREventQoSFast) { + [self.uploadCoordinator forceUploadForTarget:target]; + } + + // Write state to disk if we're in the background. + if ([[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORLogDebug("%@", @"Saving storage state because the app is running in the background"); + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } + } + + // Cancel or end the associated background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + GDTCORLogDebug("Event %@ is stored. There are %ld events stored on disk", event, + (unsigned long)self->_storedEvents.count); + }); +} + +- (void)removeEvents:(NSSet *)events { + NSSet *eventsToRemove = [events copy]; + dispatch_async(_storageQueue, ^{ + for (GDTCORStoredEvent *event in eventsToRemove) { + // Remove from disk, first and foremost. + NSError *error; + if (event.dataFuture.fileURL) { + NSURL *fileURL = event.dataFuture.fileURL; + [[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error]; + GDTCORAssert(error == nil, @"There was an error removing an event file: %@", error); + GDTCORLogDebug("Removed event from disk: %@", fileURL); + } + + // Remove from the tracking collections. + [self.storedEvents removeObject:event]; + [self.targetToEventSet[event.target] removeObject:event]; + } + }); +} + +#pragma mark - Private helper methods + +/** Creates the storage directory if it does not exist. */ +- (void)createEventDirectoryIfNotExists { + NSError *error; + BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:GDTCORStoragePath() + withIntermediateDirectories:YES + attributes:0 + error:&error]; + if (!result || error) { + GDTCORLogError(GDTCORMCEDirectoryCreationError, @"Error creating the directory: %@", error); + } +} + +/** Saves the event's dataObjectTransportBytes to a file using NSData mechanisms. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param transportBytes The transport bytes of the event. + * @param eventHash The hash value of the event. + * @return The filename + */ +- (NSURL *)saveEventBytesToDisk:(NSData *)transportBytes + eventHash:(NSUInteger)eventHash + error:(NSError **)error { + NSString *storagePath = GDTCORStoragePath(); + NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash]; + NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]]; + + GDTCORAssert(![[NSFileManager defaultManager] fileExistsAtPath:eventFilePath.path], + @"An event shouldn't already exist at this path: %@", eventFilePath.path); + + BOOL writingSuccess = [transportBytes writeToURL:eventFilePath + options:NSDataWritingAtomic + error:error]; + if (!writingSuccess) { + GDTCORLogError(GDTCORMCEFileWriteError, @"An event file could not be written: %@", + eventFilePath); + } + + return eventFilePath; +} + +/** Adds the event to internal tracking collections. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param event The event to track. + */ +- (void)addEventToTrackingCollections:(GDTCORStoredEvent *)event { + [_storedEvents addObject:event]; + NSMutableSet *events = self.targetToEventSet[event.target]; + events = events ? events : [[NSMutableSet alloc] init]; + [events addObject:event]; + _targetToEventSet[event.target] = events; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSData dataWithContentsOfFile:[GDTCORStorage archivePath]]; + if (data) { + [NSKeyedUnarchiver unarchivedObjectOfClass:[GDTCORStorage class] fromData:data error:&error]; + } + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedUnarchiver unarchiveObjectWithFile:[GDTCORStorage archivePath]]; +#endif + } +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_storageQueue, ^{ + // Immediately request a background task to run until the end of the current queue of work, and + // cancel it once the work is done. + __block GDTCORBackgroundIdentifier bgID = + [app beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } + + // End the background task if it's still valid. + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } +} + +#pragma mark - NSSecureCoding + +/** The NSKeyedCoder key for the storedEvents property. */ +static NSString *const kGDTCORStorageStoredEventsKey = @"GDTCORStorageStoredEventsKey"; + +/** The NSKeyedCoder key for the targetToEventSet property. */ +static NSString *const kGDTCORStorageTargetToEventSetKey = @"GDTCORStorageTargetToEventSetKey"; + +/** The NSKeyedCoder key for the uploadCoordinator property. */ +static NSString *const kGDTCORStorageUploadCoordinatorKey = @"GDTCORStorageUploadCoordinatorKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + // Create the singleton and populate its ivars. + GDTCORStorage *sharedInstance = [self.class sharedInstance]; + dispatch_sync(sharedInstance.storageQueue, ^{ + NSSet *classes = + [NSSet setWithObjects:[NSMutableOrderedSet class], [GDTCORStoredEvent class], nil]; + sharedInstance->_storedEvents = [aDecoder decodeObjectOfClasses:classes + forKey:kGDTCORStorageStoredEventsKey]; + classes = [NSSet setWithObjects:[NSMutableDictionary class], [NSMutableSet class], + [GDTCORStoredEvent class], nil]; + sharedInstance->_targetToEventSet = + [aDecoder decodeObjectOfClasses:classes forKey:kGDTCORStorageTargetToEventSetKey]; + sharedInstance->_uploadCoordinator = + [aDecoder decodeObjectOfClass:[GDTCORUploadCoordinator class] + forKey:kGDTCORStorageUploadCoordinatorKey]; + }); + return sharedInstance; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + GDTCORStorage *sharedInstance = [self.class sharedInstance]; + NSMutableOrderedSet *storedEvents = sharedInstance->_storedEvents; + if (storedEvents) { + [aCoder encodeObject:storedEvents forKey:kGDTCORStorageStoredEventsKey]; + } + NSMutableDictionary *> *targetToEventSet = + sharedInstance->_targetToEventSet; + if (targetToEventSet) { + [aCoder encodeObject:targetToEventSet forKey:kGDTCORStorageTargetToEventSetKey]; + } + GDTCORUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator; + if (uploadCoordinator) { + [aCoder encodeObject:uploadCoordinator forKey:kGDTCORStorageUploadCoordinatorKey]; + } +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m new file mode 100644 index 0000000..a243394 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" + +@implementation GDTCORStoredEvent + +- (instancetype)initWithEvent:(GDTCOREvent *)event + dataFuture:(nonnull GDTCORDataFuture *)dataFuture { + self = [super init]; + if (self) { + _dataFuture = dataFuture; + _mappingID = event.mappingID; + _target = @(event.target); + _qosTier = event.qosTier; + _clockSnapshot = event.clockSnapshot; + _customPrioritizationParams = event.customPrioritizationParams; + } + return self; +} + +#pragma mark - NSSecureCoding + +/** Coding key for the dataFuture ivar. */ +static NSString *kDataFutureKey = @"GDTCORStoredEventDataFutureKey"; + +/** Coding key for mappingID ivar. */ +static NSString *kMappingIDKey = @"GDTCORStoredEventMappingIDKey"; + +/** Coding key for target ivar. */ +static NSString *kTargetKey = @"GDTCORStoredEventTargetKey"; + +/** Coding key for qosTier ivar. */ +static NSString *kQosTierKey = @"GDTCORStoredEventQosTierKey"; + +/** Coding key for clockSnapshot ivar. */ +static NSString *kClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey"; + +/** Coding key for customPrioritizationParams ivar. */ +static NSString *kCustomPrioritizationParamsKey = @"GDTCORStoredEventcustomPrioritizationParamsKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_dataFuture forKey:kDataFutureKey]; + [aCoder encodeObject:_mappingID forKey:kMappingIDKey]; + [aCoder encodeObject:_target forKey:kTargetKey]; + [aCoder encodeObject:@(_qosTier) forKey:kQosTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:kClockSnapshotKey]; + [aCoder encodeObject:_customPrioritizationParams forKey:kCustomPrioritizationParamsKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [self init]; + if (self) { + _dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture class] forKey:kDataFutureKey]; + _mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey]; + _target = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kTargetKey]; + NSNumber *qosTier = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kQosTierKey]; + _qosTier = [qosTier intValue]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey]; + _customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class] + forKey:kCustomPrioritizationParamsKey]; + } + return self; +} + +- (BOOL)isEqual:(GDTCORStoredEvent *)other { + return [self hash] == [other hash]; +} + +- (NSUInteger)hash { + return [_dataFuture hash] ^ [_mappingID hash] ^ [_target hash] ^ [_clockSnapshot hash] ^ _qosTier; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m new file mode 100644 index 0000000..a794cf3 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m @@ -0,0 +1,98 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" + +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@implementation GDTCORTransformer + ++ (instancetype)sharedInstance { + static GDTCORTransformer *eventTransformer; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventTransformer = [[self alloc] init]; + }); + return eventTransformer; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _eventWritingQueue = + dispatch_queue_create("com.google.GDTCORTransformer", DISPATCH_QUEUE_SERIAL); + _storageInstance = [GDTCORStorage sharedInstance]; + } + return self; +} + +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(NSArray> *)transformers + onComplete:(nonnull void (^)(BOOL wasWritten, NSError *error))completion { + GDTCORAssert(event, @"You can't write a nil event"); + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTTransformer" + expirationHandler:^{ + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + dispatch_async(_eventWritingQueue, ^{ + GDTCOREvent *transformedEvent = event; + for (id transformer in transformers) { + if ([transformer respondsToSelector:@selector(transform:)]) { + GDTCORLogDebug("Applying a transformer to event %@", event); + transformedEvent = [transformer transform:transformedEvent]; + if (!transformedEvent) { + completion(NO, nil); + return; + } + } else { + GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform, + @"Transformer doesn't implement transform: %@", transformer); + completion(NO, nil); + return; + } + } + [self.storageInstance storeEvent:transformedEvent onComplete:completion]; + + // The work is done, cancel the background task if it's valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + // Flush the queue immediately. + dispatch_sync(_eventWritingQueue, ^{ + }); +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m new file mode 100644 index 0000000..c63c262 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "GDTCORLibrary/Private/GDTCORTransport_Private.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +@implementation GDTCORTransport + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _transformers = transformers; + _target = target; + _transformerInstance = [GDTCORTransformer sharedInstance]; + } + GDTCORLogDebug("Transport object created. mappingID:%@ transformers:%@ target:%ld", _mappingID, + _transformers, (long)_target); + return self; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion { + event.qosTier = GDTCOREventQoSTelemetry; + [self sendEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + GDTCORLogDebug("Telemetry event sent: %@", event); + if (completion) { + completion(wasWritten, nil); + } + }]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please."); + [self sendEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + GDTCORLogDebug("Data event sent: %@", event); + if (completion) { + completion(wasWritten, nil); + } + }]; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event { + [self sendTelemetryEvent:event + onComplete:^(BOOL wasWritten, NSError *_Nullable error){ + }]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event { + [self sendDataEvent:event + onComplete:^(BOOL wasWritten, NSError *_Nullable error){ + }]; +} + +- (GDTCOREvent *)eventForTransport { + return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; +} + +#pragma mark - Private helper methods + +/** Sends the given event through the transport pipeline. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion { + // TODO: Determine if sending an event before registration is allowed. + GDTCORAssert(event, @"You can't send a nil event"); + GDTCOREvent *copiedEvent = [event copy]; + copiedEvent.clockSnapshot = [GDTCORClock snapshot]; + [self.transformerInstance transformEvent:copiedEvent + withTransformers:_transformers + onComplete:completion]; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m new file mode 100644 index 0000000..7ebef6b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m @@ -0,0 +1,274 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORReachability.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@implementation GDTCORUploadCoordinator + ++ (instancetype)sharedInstance { + static GDTCORUploadCoordinator *sharedUploader; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedUploader = [[GDTCORUploadCoordinator alloc] init]; + [sharedUploader startTimer]; + }); + return sharedUploader; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _coordinationQueue = + dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL); + _registrar = [GDTCORRegistrar sharedInstance]; + _timerInterval = 30 * NSEC_PER_SEC; + _timerLeeway = 5 * NSEC_PER_SEC; + _targetToInFlightPackages = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)forceUploadForTarget:(GDTCORTarget)target { + dispatch_async(_coordinationQueue, ^{ + GDTCORLogDebug("Forcing an upload of target %ld", (long)target); + GDTCORUploadConditions conditions = [self uploadConditions]; + conditions |= GDTCORUploadConditionHighPriority; + [self uploadTargets:@[ @(target) ] conditions:conditions]; + }); +} + +#pragma mark - Property overrides + +// GDTCORStorage and GDTCORUploadCoordinator +sharedInstance methods call each other, so this breaks +// the loop. +- (GDTCORStorage *)storage { + if (!_storage) { + _storage = [GDTCORStorage sharedInstance]; + } + return _storage; +} + +#pragma mark - Private helper methods + +/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will + * check the next-upload clocks of all targets to determine if an upload attempt can be made. + */ +- (void)startTimer { + dispatch_sync(_coordinationQueue, ^{ + self->_timer = + dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue); + dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval, + self->_timerLeeway); + dispatch_source_set_event_handler(self->_timer, ^{ + if (![[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORUploadConditions conditions = [self uploadConditions]; + GDTCORLogDebug("%@", @"Upload timer fired"); + [self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions]; + } + }); + GDTCORLogDebug("%@", @"Upload timer started"); + dispatch_resume(self->_timer); + }); +} + +/** Stops the currently running timer. */ +- (void)stopTimer { + if (_timer) { + dispatch_source_cancel(_timer); + } +} + +/** Triggers the uploader implementations for the given targets to upload. + * + * @param targets An array of targets to trigger. + * @param conditions The set of upload conditions. + */ +- (void)uploadTargets:(NSArray *)targets conditions:(GDTCORUploadConditions)conditions { + dispatch_async(_coordinationQueue, ^{ + if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) { + return; + } + for (NSNumber *target in targets) { + // Don't trigger uploads for targets that have an in-flight package already. + if (self->_targetToInFlightPackages[target]) { + GDTCORLogDebug("Target %@ will not upload, there's an upload in flight", target); + continue; + } + // Ask the uploader if they can upload and do so, if it can. + id uploader = self.registrar.targetToUploader[target]; + if ([uploader readyToUploadTarget:target.intValue conditions:conditions]) { + id prioritizer = self.registrar.targetToPrioritizer[target]; + GDTCORUploadPackage *package = [prioritizer uploadPackageWithTarget:target.intValue + conditions:conditions]; + if (package.events.count) { + self->_targetToInFlightPackages[target] = package; + GDTCORLogDebug("Package of %ld events is being handed over to an uploader", + (long)package.events.count); + [uploader uploadPackage:package]; + } else { + [package completeDelivery]; + } + } + GDTCORLogDebug("Target %@ is not ready to upload", target); + } + }); +} + +/** Returns the current upload conditions after making determinations about the network connection. + * + * @return The current upload conditions. + */ +- (GDTCORUploadConditions)uploadConditions { +#if TARGET_OS_WATCH + return GDTCORUploadConditionNoNetwork; +#else + SCNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags]; + BOOL reachable = + (currentFlags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable; + BOOL connectionRequired = (currentFlags & kSCNetworkReachabilityFlagsConnectionRequired) == + kSCNetworkReachabilityFlagsConnectionRequired; + BOOL networkConnected = reachable && !connectionRequired; + + if (!networkConnected) { + return GDTCORUploadConditionNoNetwork; + } + + BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags); + if (isWWAN) { + return GDTCORUploadConditionMobileData; + } else { + return GDTCORUploadConditionWifiData; + } +#endif +} + +#pragma mark - NSSecureCoding support + +/** The NSKeyedCoder key for the targetToInFlightPackages property. */ +static NSString *const ktargetToInFlightPackagesKey = + @"GDTCORUploadCoordinatortargetToInFlightPackages"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + GDTCORUploadCoordinator *sharedCoordinator = [GDTCORUploadCoordinator sharedInstance]; + dispatch_sync(sharedCoordinator->_coordinationQueue, ^{ + @try { + sharedCoordinator->_targetToInFlightPackages = + [aDecoder decodeObjectOfClass:[NSMutableDictionary class] + forKey:ktargetToInFlightPackagesKey]; + + } @catch (NSException *exception) { + sharedCoordinator->_targetToInFlightPackages = [NSMutableDictionary dictionary]; + } + }); + return sharedCoordinator; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + dispatch_sync(_coordinationQueue, ^{ + // All packages that have been given to uploaders need to be tracked so that their expiration + // timers can be called. + if (self->_targetToInFlightPackages.count > 0) { + [aCoder encodeObject:self->_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey]; + } + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + // Not entirely thread-safe, but it should be fine. + [self startTimer]; +} + +- (void)appWillBackground:(GDTCORApplication *)app { + // Should be thread-safe. If it ends up not being, put this in a dispatch_sync. + [self stopTimer]; +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + if (!prioritizer) { + GDTCORLogError(GDTCORMCEPrioritizerError, + @"A prioritizer should be registered for this target: %@", targetNumber); + } + if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) { + [prioritizer packageDelivered:package successful:successful]; + } + } + if (package.events != nil) { + [self.storage removeEvents:package.events]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + id uploader = registrar.targetToUploader[targetNumber]; + if ([prioritizer respondsToSelector:@selector(packageExpired:)]) { + [prioritizer packageExpired:package]; + } + if ([uploader respondsToSelector:@selector(packageExpired:)]) { + [uploader packageExpired:package]; + } + } + }); +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m new file mode 100644 index 0000000..6ac5f4f --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m @@ -0,0 +1,159 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +@implementation GDTCORUploadPackage { + /** If YES, the package's -completeDelivery method has been called. */ + BOOL _isDelivered; + + /** If YES, is being handled by the handler. */ + BOOL _isHandled; + + /** A timer that will regularly check to see whether this package has expired or not. */ + NSTimer *_expirationTimer; +} + +- (instancetype)initWithTarget:(GDTCORTarget)target { + self = [super init]; + if (self) { + _target = target; + _storage = [GDTCORStorage sharedInstance]; + _deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000]; + _handler = [GDTCORUploadCoordinator sharedInstance]; + _expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 + target:self + selector:@selector(checkIfPackageIsExpired:) + userInfo:nil + repeats:YES]; + } + GDTCORLogDebug("Upload package created %@", self); + return self; +} + +- (instancetype)copy { + GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] initWithTarget:_target]; + newPackage->_events = [_events copy]; + GDTCORLogDebug("Copying UploadPackage %@ to %@", self, newPackage); + return newPackage; +} + +- (NSUInteger)hash { + return [_events hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (void)dealloc { + [_expirationTimer invalidate]; +} + +- (void)setStorage:(GDTCORStorage *)storage { + if (storage != _storage) { + _storage = storage; + } +} + +- (void)completeDelivery { + if (_isDelivered) { + GDTCORLogError(GDTCORMCEDeliverTwice, @"%@", + @"It's an API violation to call -completeDelivery twice."); + } + _isDelivered = YES; + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + [_expirationTimer invalidate]; + _isHandled = YES; + [_handler packageDelivered:self successful:YES]; + } + GDTCORLogDebug("Upload package delivered: %@", self); +} + +- (void)retryDeliveryInTheFuture { + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + [_expirationTimer invalidate]; + _isHandled = YES; + [_handler packageDelivered:self successful:NO]; + } + GDTCORLogDebug("Upload package will retry in the future: %@", self); +} + +- (void)checkIfPackageIsExpired:(NSTimer *)timer { + if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) { + if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) { + _isHandled = YES; + [_expirationTimer invalidate]; + GDTCORLogDebug("Upload package expired: %@", self); + [_handler packageExpired:self]; + } + } +} + +#pragma mark - NSSecureCoding + +/** The keyed archiver key for the events property. */ +static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey"; + +/** The keyed archiver key for the _isHandled property. */ +static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey"; + +/** The keyed archiver key for the _isHandled ivar. */ +static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey"; + +/** The keyed archiver key for the handler property. */ +static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey"; + +/** The keyed archiver key for the target property. */ +static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_events forKey:kEventsKey]; + [aCoder encodeObject:_deliverByTime forKey:kDeliverByTimeKey]; + [aCoder encodeBool:_isHandled forKey:kIsHandledKey]; + [aCoder encodeObject:_handler forKey:kHandlerKey]; + [aCoder encodeInteger:_target forKey:kTargetKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey]; + self = [self initWithTarget:target]; + if (self) { + NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCORStoredEvent class], nil]; + _events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey]; + _deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey]; + _isHandled = [aDecoder decodeBoolForKey:kIsHandledKey]; + // _handler isn't technically NSSecureCoding, because we don't know the class of this object. + // but it gets decoded anyway. + } + return self; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h new file mode 100644 index 0000000..f7f8a28 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCOREvent () + +/** The serialized bytes of the event data object. */ +@property(nonatomic) NSData *dataObjectTransportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h new file mode 100644 index 0000000..7879b59 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if !TARGET_OS_WATCH +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** This class helps determine upload conditions by determining connectivity. */ +@interface GDTCORReachability : NSObject +#if !TARGET_OS_WATCH +/** The current set flags indicating network conditions */ ++ (SCNetworkReachabilityFlags)currentFlags; +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h new file mode 100644 index 0000000..5d3ddaf --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORReachability.h" + +@interface GDTCORReachability () + +#if !TARGET_OS_WATCH +/** Allows manually setting the flags for testing purposes. */ +@property(nonatomic, readwrite) SCNetworkReachabilityFlags flags; +#endif + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h new file mode 100644 index 0000000..074fc11 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GDTCORRegistrar () + +NS_ASSUME_NONNULL_BEGIN + +/** The concurrent queue on which all registration occurs. */ +@property(nonatomic, readonly) dispatch_queue_t registrarQueue; + +/** A map of targets to backend implementations. */ +@property(atomic, readonly) NSMutableDictionary> *targetToUploader; + +/** A map of targets to prioritizer implementations. */ +@property(atomic, readonly) + NSMutableDictionary> *targetToPrioritizer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h new file mode 100644 index 0000000..bbb3778 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h @@ -0,0 +1,52 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the storage of events. This class is thread-safe. */ +@interface GDTCORStorage : NSObject + +/** Creates and/or returns the storage singleton. + * + * @return The storage singleton. + */ ++ (instancetype)sharedInstance; + +/** Stores event.dataObjectTransportBytes into a shared on-device folder and tracks the event via + * a GDTCORStoredEvent instance. + * + * @param event The event to store. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion; + +/** Removes a set of events from storage specified by their hash. + * + * @param events The set of stored events to remove. + */ +- (void)removeEvents:(NSSet *)events; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h new file mode 100644 index 0000000..24569fd --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h @@ -0,0 +1,47 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@class GDTCORUploadCoordinator; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORStorage () + +/** The queue on which all storage work will occur. */ +@property(nonatomic) dispatch_queue_t storageQueue; + +/** A map of targets to a set of stored events. */ +@property(nonatomic) + NSMutableDictionary *> *targetToEventSet; + +/** All the events that have been stored. */ +@property(readonly, nonatomic) NSMutableOrderedSet *storedEvents; + +/** The upload coordinator instance used by this storage instance. */ +@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator; + +/** Returns the path to the keyed archive of the singleton. This is where the singleton is saved + * to disk during certain app lifecycle events. + * + * @return File path to serialized singleton. + */ ++ (NSString *)archivePath; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h new file mode 100644 index 0000000..9da9fc3 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +@protocol GDTCOREventTransformer; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the transforming of events. It's desirable for this to be its own class + * because running all events through a single instance ensures that transformers are thread-safe. + * Having a per-transport queue to run on isn't sufficient because transformer objects could + * maintain state (or at least, there's nothing to stop them from doing that) and the same instances + * may be used across multiple instances. + */ +@interface GDTCORTransformer : NSObject + +/** Instantiates or returns the event transformer singleton. + * + * @return The singleton instance of the event transformer. + */ ++ (instancetype)sharedInstance; + +/** Writes the result of applying the given transformers' -transform method on the given event. + * + * @note If the app is suspended, a background task will be created to complete work in-progress, + * but this method will not send any further events until the app is resumed. + * + * @param event The event to apply transformers on. + * @param transformers The list of transformers to apply. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(nullable NSArray> *)transformers + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h new file mode 100644 index 0000000..fcdae34 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h @@ -0,0 +1,33 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +@class GDTCORStorage; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransformer () + +/** The queue on which all work will occur. */ +@property(nonatomic) dispatch_queue_t eventWritingQueue; + +/** The storage instance used to store events. Should only be used to inject a testing fake. */ +@property(nonatomic) GDTCORStorage *storageInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h new file mode 100644 index 0000000..71f73a6 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCORTransformer; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport () + +/** The mapping identifier that the target backend will use to map the transport bytes to proto. */ +@property(nonatomic) NSString *mappingID; + +/** The transformers that will operate on events sent by this transport. */ +@property(nonatomic) NSArray> *transformers; + +/** The target backend of this transport. */ +@property(nonatomic) NSInteger target; + +/** The transformer instance to used to transform events. Allows injecting a fake during testing. */ +@property(nonatomic) GDTCORTransformer *transformerInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h new file mode 100644 index 0000000..b1d708c --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h @@ -0,0 +1,77 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +@class GDTCORClock; +@class GDTCORStorage; + +NS_ASSUME_NONNULL_BEGIN + +/** This class connects storage and uploader implementations, providing events to an uploader + * and informing the storage what events were successfully uploaded or not. + */ +@interface GDTCORUploadCoordinator + : NSObject + +/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */ +/** Creates and/or returrns the singleton. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; +@property(nonatomic, readonly) dispatch_queue_t coordinationQueue; + +/** A timer that will causes regular checks for events to upload. */ +@property(nonatomic, readonly) dispatch_source_t timer; + +/** The interval the timer will fire. */ +@property(nonatomic, readonly) uint64_t timerInterval; + +/** Some leeway given to libdispatch for the timer interval event. */ +@property(nonatomic, readonly) uint64_t timerLeeway; + +/** The map of targets to in-flight packages. */ +@property(nonatomic, readonly) + NSMutableDictionary *targetToInFlightPackages; + +/** The storage object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORStorage *storage; + +/** The registrar object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORRegistrar *registrar; + +/** Forces the backend specified by the target to upload the provided set of events. This should + * only ever happen when the QoS tier of an event requires it. + * + * @param target The target that should force an upload. + */ +- (void)forceUploadForTarget:(GDTCORTarget)target; + +/** Starts the upload timer. */ +- (void)startTimer; + +/** Stops the upload timer from running. */ +- (void)stopTimer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h new file mode 100644 index 0000000..1eb58d4 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCORStorage; + +@interface GDTCORUploadPackage () + +/** The storage object this upload package will use to resolve event hashes to files. */ +@property(nonatomic) GDTCORStorage *storage; + +/** A handler that will receive callbacks for certain events. */ +@property(nonatomic) id handler; + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h new file mode 100644 index 0000000..5dfe192 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +/** A block type that could be run instead of normal assertion logging. No return type, no params. + */ +typedef void (^GDTCORAssertionBlock)(void); + +/** Returns the result of executing a soft-linked method present in unit tests that allows a block + * to be run instead of normal assertion logging. This helps ameliorate issues with catching + * exceptions that occur on a dispatch_queue. + * + * @return A block that can be run instead of normal assert printing. + */ +FOUNDATION_EXPORT GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void); + +#if defined(NS_BLOCK_ASSERTIONS) + +#define GDTCORAssert(condition, ...) \ + do { \ + } while (0); + +#define GDTCORFatalAssert(condition, ...) \ + do { \ + } while (0); + +#else // defined(NS_BLOCK_ASSERTIONS) + +/** Asserts using a console log, unless a block was specified to be run instead. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORAssert(condition, ...) \ + do { \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogError(GDTCORMCEGeneralError, @"Assertion failed (%@:%d): %@,", __assert_file__, \ + __LINE__, ##__VA_ARGS__); \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not + * defined. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORFatalAssert(condition, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogError(GDTCORMCEFatalAssertion, \ + @"Fatal assertion encountered, please open an issue at " \ + "https://github.com/firebase/firebase-ios-sdk/issues " \ + "(%@:%d): %@,", \ + __assert_file__, __LINE__, ##__VA_ARGS__); \ + [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ + object:self \ + file:__assert_file__ \ + lineNumber:__LINE__ \ + description:@"%@", ##__VA_ARGS__]; \ + } \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } while (0); + +#endif // defined(NS_BLOCK_ASSERTIONS) diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h new file mode 100644 index 0000000..01de21a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class manages the device clock and produces snapshots of the current time. */ +@interface GDTCORClock : NSObject + +/** The wallclock time, UTC, in milliseconds. */ +@property(nonatomic, readonly) int64_t timeMillis; + +/** The offset from UTC in seconds. */ +@property(nonatomic, readonly) int64_t timezoneOffsetSeconds; + +/** The kernel boot time when this clock was created. */ +@property(nonatomic, readonly) int64_t kernelBootTime; + +/** The device uptime when this clock was created. */ +@property(nonatomic, readonly) int64_t uptime; + +/** Creates a GDTCORClock object using the current time and offsets. + * + * @return A new GDTCORClock object representing the current time state. + */ ++ (instancetype)snapshot; + +/** Creates a GDTCORClock object representing a time in the future, relative to now. + * + * @param millisInTheFuture The millis in the future from now this clock should represent. + * @return An instance representing a future time. + */ ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture; + +/** Compares one clock with another, returns YES if the caller is after the parameter. + * + * @return YES if the calling clock's time is after the given clock's time. + */ +- (BOOL)isAfter:(GDTCORClock *)otherClock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h new file mode 100644 index 0000000..c70706b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Set this to 1 to have the library print out as much as possible about what GDT is doing. +#define GDT_VERBOSE_LOGGING 0 + +/** A list of message codes to print in the logger that help to correspond printed messages with + * code locations. + * + * Prefixes: + * - MCW => MessageCodeWarning + * - MCE => MessageCodeError + */ +typedef NS_ENUM(NSInteger, GDTCORMessageCode) { + + /** For warning messages concerning transportBytes: not being implemented by a data object. */ + GDTCORMCWDataObjectMissingBytesImpl = 1, + + /** For warning messages concerning a failed event upload. */ + GDTCORMCWUploadFailed = 2, + + /** For warning messages concerning a forced event upload. */ + GDTCORMCWForcedUpload = 3, + + /** For warning messages concerning a failed reachability call. */ + GDTCORMCWReachabilityFailed = 4, + + /** For error messages concerning transform: not being implemented by an event transformer. */ + GDTCORMCETransformerDoesntImplementTransform = 1000, + + /** For error messages concerning the creation of a directory failing. */ + GDTCORMCEDirectoryCreationError = 1001, + + /** For error messages concerning the writing of a event file. */ + GDTCORMCEFileWriteError = 1002, + + /** For error messages concerning the lack of a prioritizer for a given backend. */ + GDTCORMCEPrioritizerError = 1003, + + /** For error messages concerning a package delivery API violation. */ + GDTCORMCEDeliverTwice = 1004, + + /** For error messages concerning an error in an implementation of -transportBytes. */ + GDTCORMCETransportBytesError = 1005, + + /** For general purpose error messages in a dependency. */ + GDTCORMCEGeneralError = 1006, + + /** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open + * an issue if you encounter an error with this code. + */ + GDTCORMCEFatalAssertion = 1007 +}; + +/** */ +FOUNDATION_EXPORT +void GDTCORLog(GDTCORMessageCode code, NSString *_Nonnull format, ...); + +/** Returns the string that represents some message code. + * + * @param code The code to convert to a string. + * @return The string representing the message code. + */ +FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code); + +// A define to wrap GULLogWarning with slightly more convenient usage. +#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogError with slightly more convenient usage and a failing assert. +#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap NSLog for verbose console logs only useful for local debugging. +#if GDT_VERBOSE_LOGGING == 1 +#define GDTCORLogDebug(FORMAT, ...) NSLog(@"GDT: " FORMAT, __VA_ARGS__); +#else +#define GDTCORLogDebug(...) +#endif // GDT_VERBOSE_LOGGING == 1 diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h new file mode 100644 index 0000000..07f428f --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class represents a future data object, determined at instantiation time. */ +@interface GDTCORDataFuture : NSObject + +/** The data, computed on-demand, depending on the initializer. */ +@property(nullable, readonly, nonatomic) NSData *data; + +/** If not nil, this data future was instantiated with this file URL. */ +@property(nullable, readonly, nonatomic) NSURL *fileURL; + +/** If not nil, this data future was instantiated with this NSData instance. */ +@property(nullable, readonly, nonatomic) NSData *originalData; + +/** Initializes an instance with the given the fileURL. + * + * @param fileURL The fileURL containing the data to return in -data. + * @return An instance of this class. + */ +- (instancetype)initWithFileURL:(NSURL *)fileURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h new file mode 100644 index 0000000..1ab55de --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCORClock; +@class GDTCORDataFuture; +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCOREventQoS) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCOREventQoSUnknown = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCOREventQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCOREventQoSDaily = 2, + + /** This event should be sent when requested by the uploader. */ + GDTCOREventQosDefault = 3, + + /** This event should be sent immediately along with any other data that can be batched. */ + GDTCOREventQoSFast = 4, + + /** This event should only be uploaded on wifi. */ + GDTCOREventQoSWifiOnly = 5, +}; + +@interface GDTCOREvent : NSObject + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) NSInteger target; + +/** The data object encapsulated in the transport of your choice, as long as it implements + * the GDTCOREventDataObject protocol. */ +@property(nullable, nonatomic) id dataObject; + +/** The quality of service tier this event belongs to. */ +@property(nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(nonatomic) GDTCORClock *clockSnapshot; + +/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. It will be + * retained by a copy in -copy, but not used for -hash. + * + * @note Ensure that classes contained therein implement NSSecureCoding to prevent loss of data. + */ +@property(nullable, nonatomic) NSDictionary *customPrioritizationParams; + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes an instance using the given mappingID. + * + * @param mappingID The mapping identifier. + * @param target The event's target identifier. + * @return An instance of this class. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +/** Returns the GDTCORStoredEvent equivalent of self. + * + * @param dataFuture The data future representing the transport bytes of the original event. + * @return An equivalent GDTCORStoredEvent. + */ +- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h new file mode 100644 index 0000000..34ef624 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface that event protos should implement regardless of the + * underlying transport technology (protobuf, nanopb, etc). + */ +@protocol GDTCOREventDataObject + +@required + +/** Returns the serialized proto bytes of the implementing event proto. + * + * @return the serialized proto bytes of the implementing event proto. + */ +- (NSData *)transportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h new file mode 100644 index 0000000..29f9592 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Defines the API that event transformers must adopt. */ +@protocol GDTCOREventTransformer + +@required + +/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in + * instances where the event should be sampled. + * + * @param event The event to transform. + * @return A transformed event, or nil if the transformation dropped the event. + */ +- (nullable GDTCOREvent *)transform:(GDTCOREvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h new file mode 100644 index 0000000..4d61a21 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** A protocol defining the lifecycle events objects in the library must respond to immediately. */ +@protocol GDTCORLifecycleProtocol + +@optional + +/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has + * been called. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillTerminate:(GDTCORApplication *)app; + +/** Indicates that the app is moving to background and eventual suspension or the current UIScene is + * deactivating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillBackground:(GDTCORApplication *)app; + +/** Indicates that the app is resuming operation or a UIScene is activating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillForeground:(GDTCORApplication *)app; + +@end + +/** This class manages the library's response to app lifecycle events. + * + * When backgrounding, the library doesn't stop processing events, it's just that several background + * tasks will end up being created for every event that's sent, and the stateful objects of the + * library (GDTCORStorage and GDTCORUploadCoordinator singletons) will deserialize themselves from + * and to disk before and after every operation, respectively. + */ +@interface GDTCORLifecycle : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h new file mode 100644 index 0000000..d72c2c9 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h @@ -0,0 +1,98 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if !TARGET_OS_WATCH +#import +#endif +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +NS_ASSUME_NONNULL_BEGIN + +/** The GoogleDataTransport library version. */ +FOUNDATION_EXPORT NSString *const kGDTCORVersion; + +/** A notification sent out if the app is backgrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification; + +/** A notification sent out if the app is foregrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification; + +/** A notification sent out if the app is terminating. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification; + +#if !TARGET_OS_WATCH +/** Compares flags with the WWAN reachability flag, if available, and returns YES if present. + * + * @param flags The set of reachability flags. + * @return YES if the WWAN flag is set, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags); +#endif + +/** A typedef identify background identifiers. */ +typedef volatile NSUInteger GDTCORBackgroundIdentifier; + +/** A background task's invalid sentinel value. */ +FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid; + +#if TARGET_OS_IOS || TARGET_OS_TV +/** A protocol that wraps UIApplicationDelegate or NSObject protocol, depending on the platform. */ +@protocol GDTCORApplicationDelegate +#elif TARGET_OS_OSX +@protocol GDTCORApplicationDelegate +#else +@protocol GDTCORApplicationDelegate +#endif // TARGET_OS_IOS || TARGET_OS_TV + +@end + +/** A cross-platform application class. */ +@interface GDTCORApplication : NSObject + +/** Flag to determine if the application is running in the background. */ +@property(atomic, readonly) BOOL isRunningInBackground; + +/** Creates and/or returns the shared application instance. + * + * @return The shared application instance. + */ ++ (nullable GDTCORApplication *)sharedApplication; + +/** Creates a background task with the returned identifier if on a suitable platform. + * + * @name name The name of the task, useful for debugging which background tasks are running. + * @param handler The handler block that is called if the background task expires. + * @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one + * couldn't be created. + */ +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^__nullable)(void))handler; + +/** Ends the background task if the identifier is valid. + * + * @param bgID The background task to end. + */ +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h new file mode 100644 index 0000000..583e84d --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Options that define a set of upload conditions. This is used to help minimize end user data + * consumption impact. + */ +typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) { + + /** An upload shouldn't be attempted, because there's no network. */ + GDTCORUploadConditionNoNetwork = 1 << 0, + + /** An upload would likely use mobile data. */ + GDTCORUploadConditionMobileData = 1 << 1, + + /** An upload would likely use wifi data. */ + GDTCORUploadConditionWifiData = 1 << 2, + + /** An upload uses some sort of network connection, but it's unclear which. */ + GDTCORUploadConditionUnclearConnection = 1 << 3, + + /** A high priority event has occurred. */ + GDTCORUploadConditionHighPriority = 1 << 4, +}; + +/** This protocol defines the common interface of event prioritization. Prioritizers are + * stateful objects that prioritize events upon insertion into storage and remain prepared to return + * a set of filenames to the storage system. + */ +@protocol GDTCORPrioritizer + +@required + +/** Accepts an event and uses the event metadata to make choices on how to prioritize the event. + * This method exists as a way to help prioritize which events should be sent, which is dependent on + * the request proto structure of your backend. + * + * @param event The event to prioritize. + */ +- (void)prioritizeEvent:(GDTCORStoredEvent *)event; + +/** Returns a set of events to upload given a set of conditions. + * + * @param target The target to create an upload package for. + * @param conditions A bit mask specifying the current upload conditions. + * @return An object to be used by the uploader to determine file URLs to upload with respect to the + * current conditions. + */ +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h new file mode 100644 index 0000000..0a8fbb0 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the registration of targets with the transport SDK. */ +@interface GDTCORRegistrar : NSObject + +/** Creates and/or returns the singleton instance. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** Registers a backend implementation with the GoogleDataTransport infrastructure. + * + * @param backend The backend object to register. + * @param target The target this backend object will be responsible for. + */ +- (void)registerUploader:(id)backend target:(GDTCORTarget)target; + +/** Registers a event prioritizer implementation with the GoogleDataTransport infrastructure. + * + * @param prioritizer The prioritizer object to register. + * @param target The target this prioritizer object will be responsible for. + */ +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h new file mode 100644 index 0000000..647b220 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORStoredEvent : NSObject + +/** The data future representing the original event's transport bytes. */ +@property(readonly, nonatomic) GDTCORDataFuture *dataFuture; + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) NSNumber *target; + +/** The quality of service tier this event belongs to. */ +@property(readonly, nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(readonly, nonatomic) GDTCORClock *clockSnapshot; + +/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. + * + * @note Ensure that custom classes in this dict implement NSSecureCoding to prevent loss of data. + */ +@property(readonly, nullable, nonatomic) NSDictionary *customPrioritizationParams; + +/** Initializes a stored event with the given URL and event. + * + * @param event The event this stored event represents. + * @param dataFuture The dataFuture this event represents. + * @return An instance of this class. + */ +- (instancetype)initWithEvent:(GDTCOREvent *)event dataFuture:(GDTCORDataFuture *)dataFuture; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h new file mode 100644 index 0000000..5db8852 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The list of targets supported by the shared transport infrastructure. If adding a new target, + * please use the previous value +1. + */ +typedef NS_ENUM(NSInteger, GDTCORTarget) { + + /** A target only used in testing. */ + kGDTCORTargetTest = 999, + + /** The CCT target. */ + kGDTCORTargetCCT = 1000, + + /** The FLL target. */ + kGDTCORTargetFLL = 1001, + + /** The CSH target. The CSH target is a special-purpose backend. Please do not use it without + * permission. + */ + kGDTCORTargetCSH = 1002 +}; diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h new file mode 100644 index 0000000..9c72115 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport : NSObject + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes a new transport that will send events to the given target backend. + * + * @param mappingID The mapping identifier used by the backend to map the data object transport + * bytes to a proto. + * @param transformers A list of transformers to be applied to events that are sent. + * @param target The target backend of this transport. + * @return A transport that will send events. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendDataEvent:(GDTCOREvent *)event; + +/** Creates an event for use by this transport. + * + * @return An event that is suited for use by this transport. + */ +- (GDTCOREvent *)eventForTransport; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h new file mode 100644 index 0000000..46a676b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCORClock; +@class GDTCORStoredEvent; +@class GDTCORUploadPackage; + +/** A protocol that allows a handler to respond to package lifecycle events. */ +@protocol GDTCORUploadPackageProtocol + +@optional + +/** Indicates that the package has expired. + * + * @note Package expiration will only be checked every 5 seconds. + * + * @param package The package that has expired. + */ +- (void)packageExpired:(GDTCORUploadPackage *)package; + +/** Indicates that the package was successfully delivered. + * + * @param package The package that was delivered. + */ +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful; + +@end + +/** This class is a container that's handed off to uploaders. */ +@interface GDTCORUploadPackage : NSObject + +/** The set of stored events in this upload package. */ +@property(nonatomic) NSSet *events; + +/** The expiration time. If [[GDTCORClock snapshot] isAfter:deliverByTime] this package has expired. + * + * @note By default, the expiration time will be 3 minutes from creation. + */ +@property(nonatomic) GDTCORClock *deliverByTime; + +/** The target of this package. */ +@property(nonatomic, readonly) GDTCORTarget target; + +/** Initializes a package instance. + * + * @param target The target/destination of this package. + * @return An instance of this class. + */ +- (instancetype)initWithTarget:(GDTCORTarget)target NS_DESIGNATED_INITIALIZER; + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Completes delivery of the package. + * + * @note This *needs* to be called by an uploader for the package to not expire. + */ +- (void)completeDelivery; + +/** Sends the package back, indicating that delivery should be attempted again in the future. */ +- (void)retryDeliveryInTheFuture; + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h new file mode 100644 index 0000000..cadee47 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface for uploader implementations. */ +@protocol GDTCORUploader + +@required + +/** Returns YES if the uploader can make an upload attempt, NO otherwise. + * + * @param target The target being checked. + * @param conditions The conditions that the upload attempt is likely to occur under. + * @return YES if the uploader can make an upload attempt, NO otherwise. + */ +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions; + +/** Uploads events to the backend using this specific backend's chosen format. + * + * @param package The event package to upload. Make sure to call -completeDelivery. + */ +- (void)uploadPackage:(GDTCORUploadPackage *)package; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h new file mode 100644 index 0000000..e46a385 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCORDataFuture.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORRegistrar.h" +#import "GDTCORStoredEvent.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploadPackage.h" +#import "GDTCORUploader.h" diff --git a/PediatricPancreas/Pods/GoogleDataTransport/LICENSE b/PediatricPancreas/Pods/GoogleDataTransport/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/GoogleDataTransport/README.md b/PediatricPancreas/Pods/GoogleDataTransport/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransport/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m new file mode 100644 index 0000000..6ae115d --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m @@ -0,0 +1,96 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" + +#import + +@implementation GDTCCTCompressionHelper + ++ (nullable NSData *)gzippedData:(NSData *)data { +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (data.length > UINT_MAX) { + return nil; + } +#endif + + const uint kChunkSize = 1024; + + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + ++ (BOOL)isGzipped:(NSData *)data { + const UInt8 *bytes = (const UInt8 *)data.bytes; + return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m new file mode 100644 index 0000000..2afb823 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m @@ -0,0 +1,198 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#pragma mark - General purpose encoders + +pb_bytes_array_t *GDTCCTEncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return GDTCCTEncodeData(stringBytes); +} + +pb_bytes_array_t *GDTCCTEncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +#pragma mark - CCT object constructors + +NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + CFDataSetLength(dataRef, ostream.bytes_written); + + return CFBridgingRelease(dataRef); +} + +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet) { + gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default; + NSUInteger numberOfLogRequests = logMappingIDToLogSet.count; + gdt_cct_LogRequest *logRequests = malloc(sizeof(gdt_cct_LogRequest) * numberOfLogRequests); + + __block int i = 0; + [logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull logMappingID, + NSSet *_Nonnull logSet, BOOL *_Nonnull stop) { + int32_t logSource = [logMappingID intValue]; + gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet); + logRequests[i] = logRequest; + i++; + }]; + + batchedLogRequest.log_request = logRequests; + batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests; + return batchedLogRequest; +} + +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, + NSSet *_Nonnull logSet) { + if (logSet.count == 0) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"An empty event set can't be serialized to proto."); + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + return logRequest; + } + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + logRequest.log_source = logSource; + logRequest.has_log_source = 1; + logRequest.client_info = GDTCCTConstructClientInfo(); + logRequest.has_client_info = 1; + logRequest.log_event = malloc(sizeof(gdt_cct_LogEvent) * logSet.count); + int i = 0; + for (GDTCORStoredEvent *log in logSet) { + gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log); + logRequest.log_event[i] = logEvent; + i++; + } + logRequest.log_event_count = (pb_size_t)logSet.count; + + GDTCORClock *currentTime = [GDTCORClock snapshot]; + logRequest.request_time_ms = currentTime.timeMillis; + logRequest.has_request_time_ms = 1; + logRequest.request_uptime_ms = currentTime.uptime; + logRequest.has_request_uptime_ms = 1; + + return logRequest; +} + +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCORStoredEvent *event) { + gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default; + logEvent.event_time_ms = event.clockSnapshot.timeMillis; + logEvent.has_event_time_ms = 1; + logEvent.event_uptime_ms = event.clockSnapshot.uptime; + logEvent.has_event_uptime_ms = 1; + logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds; + logEvent.has_timezone_offset_seconds = 1; + // TODO: Read network_connection_info from the custom params dict. + + NSError *error; + NSData *extensionBytes = [NSData dataWithContentsOfURL:event.dataFuture.fileURL + options:0 + error:&error]; + if (error) { + GDTCORLogError(GDTCORMCEGeneralError, + @"There was an error reading extension bytes from disk: %@", error); + return logEvent; + } + logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file. + return logEvent; +} + +gdt_cct_ClientInfo GDTCCTConstructClientInfo() { + gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default; + clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE; + clientInfo.has_client_type = 1; +#if TARGET_OS_IOS || TARGET_OS_TV + clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo(); + clientInfo.has_ios_client_info = 1; +#elif TARGET_OS_OSX + // TODO(mikehaney24): Expand the proto to include macOS client info. +#endif + return clientInfo; +} + +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() { + gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default; +#if TARGET_OS_IOS || TARGET_OS_TV + UIDevice *device = [UIDevice currentDevice]; + NSBundle *bundle = [NSBundle mainBundle]; + NSLocale *locale = [NSLocale currentLocale]; + iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion); + NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."]; + iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]); + NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; + if (version) { + iOSClientInfo.application_build = GDTCCTEncodeString(version); + } + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + if (countryCode) { + iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]); + } + iOSClientInfo.model = GDTCCTEncodeString(device.model); + NSString *languageCode = bundle.preferredLocalizations.firstObject; + iOSClientInfo.language_code = + languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en"); + iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier); +#endif + return iOSClientInfo; +} + +#pragma mark - CCT Object decoders + +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) { + gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default; + pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]); + if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) { + NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)]; + NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error}; + if (error != NULL) { + *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo]; + } + response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default; + } + return response; +} diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m new file mode 100644 index 0000000..3e2906c --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m @@ -0,0 +1,252 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import +#import +#import +#import +#import + +const static int64_t kMillisPerDay = 8.64e+7; + +@implementation GDTCCTPrioritizer + ++ (void)load { + GDTCCTPrioritizer *prioritizer = [GDTCCTPrioritizer sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTPrioritizer *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTPrioritizer alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _queue = dispatch_queue_create("com.google.GDTCCTPrioritizer", DISPATCH_QUEUE_SERIAL); + _CCTEvents = [[NSMutableSet alloc] init]; + _FLLEvents = [[NSMutableSet alloc] init]; + _CSHEvents = [[NSMutableSet alloc] init]; + } + return self; +} + +#pragma mark - GDTCORPrioritizer Protocol + +- (void)prioritizeEvent:(GDTCORStoredEvent *)event { + dispatch_async(_queue, ^{ + switch (event.target.intValue) { + case kGDTCORTargetCCT: + [self.CCTEvents addObject:event]; + break; + + case kGDTCORTargetFLL: + [self.FLLEvents addObject:event]; + break; + + case kGDTCORTargetCSH: + [self.CSHEvents addObject:event]; + break; + + default: + GDTCORLogDebug("GDTCCTPrioritizer doesn't support target %d", event.target.intValue); + break; + } + }); +} + +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORUploadPackage *package = [[GDTCORUploadPackage alloc] initWithTarget:target]; + dispatch_sync(_queue, ^{ + NSSet *eventsThatWillBeSent = [self eventsForTarget:target + conditions:conditions]; + package.events = eventsThatWillBeSent; + }); + GDTCORLogDebug("CCT: %lu events are in the upload package", (unsigned long)package.events.count); + return package; +} + +#pragma mark - Private helper methods + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCCTQoSTier) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCCTQoSDefault = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCCTQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCCTQoSDaily = 2, + + /** This event should only be uploaded on wifi. */ + GDTCCTQoSWifiOnly = 5, +}; + +/** Converts a GDTCOREventQoS to a GDTCCTQoS tier. + * + * @param qosTier The GDTCOREventQoS value. + * @return A static NSNumber that represents the CCT QoS tier. + */ +FOUNDATION_STATIC_INLINE +NSNumber *GDTCCTQosTierFromGDTCOREventQosTier(GDTCOREventQoS qosTier) { + switch (qosTier) { + case GDTCOREventQoSWifiOnly: + return @(GDTCCTQoSWifiOnly); + break; + + case GDTCOREventQoSTelemetry: + // falls through. + case GDTCOREventQoSDaily: + return @(GDTCCTQoSDaily); + break; + + default: + return @(GDTCCTQoSDefault); + break; + } +} + +/** Constructs a set of events for upload to CCT, FLL, or CSH backends. These backends are + * request-proto and batching compatible, so they construct event batches the same way. + * + * @param conditions The set of conditions the upload package should be made under. + * @param target The target backend. + * @return A set of events for the target. + */ +- (NSSet *)eventsForTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORClock __strong **timeOfLastDailyUpload = NULL; + NSSet *eventsToFilter; + switch (target) { + case kGDTCORTargetCCT: + eventsToFilter = self.CCTEvents; + timeOfLastDailyUpload = &self->_CCTTimeOfLastDailyUpload; + break; + + case kGDTCORTargetFLL: + eventsToFilter = self.FLLEvents; + timeOfLastDailyUpload = &self->_FLLOfLastDailyUpload; + break; + + case kGDTCORTargetCSH: + // This backend doesn't batch and uploads all events as soon as possible without respect to + // any upload condition. + return self.CSHEvents; + break; + + default: + // Return an empty set. + return [[NSSet alloc] init]; + break; + } + + NSMutableSet *eventsThatWillBeSent = [[NSMutableSet alloc] init]; + // A high priority event effectively flushes all events to be sent. + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + GDTCORLogDebug("%@", @"CCT: A high priority event is flushing all events."); + return eventsToFilter; + } + + // If on wifi, upload logs that are ok to send on wifi. + if ((conditions & GDTCORUploadConditionWifiData) == GDTCORUploadConditionWifiData) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnWifi:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send on wifi are being added to the upload package"); + } else { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnMobileData:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send on mobile are being added to the upload package"); + } + + // If it's been > 24h since the last daily upload, upload logs with the daily QoS. + if (*timeOfLastDailyUpload) { + int64_t millisSinceLastUpload = + [GDTCORClock snapshot].timeMillis - (*timeOfLastDailyUpload).timeMillis; + if (millisSinceLastUpload > kMillisPerDay) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send daily are being added to the upload package"); + } + } else { + *timeOfLastDailyUpload = [GDTCORClock snapshot]; + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send daily are being added to the upload package"); + } + return eventsThatWillBeSent; +} + +/** Returns a set of logs that are ok to upload whilst on mobile data. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on mobile data. + */ +- (NSSet *)logEventsOkToSendOnMobileData:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDefault)]; + }]; +} + +/** Returns a set of logs that are ok to upload whilst on wifi. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on wifi. + */ +- (NSSet *)logEventsOkToSendOnWifi:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + NSNumber *qosTier = GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier); + return [qosTier isEqual:@(GDTCCTQoSDefault)] || [qosTier isEqual:@(GDTCCTQoSWifiOnly)] || + [qosTier isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +/** Returns a set of logs that only should have a single upload attempt per day. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload only once per day. + */ +- (NSSet *)logEventsOkToSendDaily:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + dispatch_async(_queue, ^{ + NSSet *events = [package.events copy]; + for (GDTCORStoredEvent *event in events) { + // We don't know what collection the event was contained in, so attempt removal from all. + [self.CCTEvents removeObject:event]; + [self.FLLEvents removeObject:event]; + [self.CSHEvents removeObject:event]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + [self packageDelivered:package successful:YES]; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m new file mode 100644 index 0000000..7c6d4f5 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m @@ -0,0 +1,450 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTUploader.h" + +#import +#import +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +#ifdef GDTCCTSUPPORT_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static NSString *const kGDTCCTSupportSDKVersion = @STR(GDTCCTSUPPORT_VERSION); +#else +static NSString *const kGDTCCTSupportSDKVersion = @"UNKNOWN"; +#endif // GDTCCTSUPPORT_VERSION + +#if !NDEBUG +NSNotificationName const GDTCCTUploadCompleteNotification = @"com.GDTCCTUploader.UploadComplete"; +#endif // #if !NDEBUG + +@interface GDTCCTUploader () + +// Redeclared as readwrite. +@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask; + +@end + +@implementation GDTCCTUploader + ++ (void)load { + GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTUploader *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTUploader alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL); + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + _uploaderSession = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + } + return self; +} + +/** + * + */ +- (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target { + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + static NSURL *CCTServerURL; + static dispatch_once_t CCTOnceToken; + dispatch_once(&CCTOnceToken, ^{ + const char *p1 = "hts/frbslgiggolai.o/0clgbth"; + const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac"; + const char URL[54] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'}; + CCTServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *FLLServerURL; + static dispatch_once_t FLLOnceToken; + dispatch_once(&FLLOnceToken, ^{ + const char *p1 = "hts/frbslgigp.ogepscmv/ieo/eaybtho"; + const char *p2 = "tp:/ieaeogn-agolai.o/1frlglgc/aclg"; + const char URL[69] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], '\0'}; + FLLServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *CSHServerURL; + static dispatch_once_t CSHOnceToken; + dispatch_once(&CSHOnceToken, ^{ + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + const char *p1 = "hts/cahyiseot-agolai.o/1frlglgc/aclg"; + const char *p2 = "tp:/rsltcrprsp.ogepscmv/ieo/eaybtho"; + const char URL[72] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], p1[34], p2[34], p1[35], '\0'}; + CSHServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + +#if !NDEBUG + if (_testServerURL) { + return _testServerURL; + } +#endif // !NDEBUG + + switch (target) { + case kGDTCORTargetCCT: + return CCTServerURL; + + case kGDTCORTargetFLL: + return FLLServerURL; + + case kGDTCORTargetCSH: + return CSHServerURL; + + default: + GDTCORLogDebug("GDTCCTUploader doesn't support target %ld", (long)target); + return nil; + break; + } +} + +- (NSString *)FLLAndCSHAPIKey { + static NSString *defaultServerKey; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // These strings should be interleaved to construct the real key. + const char *p1 = "AzSBG0honD6A-PxV5nBc"; + const char *p2 = "Iay44Iwtu2vV0AOrz1C"; + const char defaultKey[40] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], + p1[4], p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], + p1[8], p2[8], p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], + p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], + p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'}; + defaultServerKey = [NSString stringWithUTF8String:defaultKey]; + }); + return defaultServerKey; +} + +- (void)uploadPackage:(GDTCORUploadPackage *)package { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTCCTUploader-upload" + expirationHandler:^{ + if (bgID != GDTCORBackgroundIdentifierInvalid) { + // Cancel the upload and complete delivery. + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + + // End the background task. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + } + }]; + + dispatch_async(_uploaderQueue, ^{ + if (self->_currentTask || self->_currentUploadPackage) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"%@", + @"An upload shouldn't be initiated with another in progress."); + return; + } + GDTCORTarget target = package.target; + id completionHandler = ^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + GDTCORLogDebug("%@", @"CCT: request completed"); + if (error) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"There was an error uploading events: %@", error); + } + NSError *decodingError; + if (data) { + gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError); + if (!decodingError && logResponse.has_next_request_wait_millis) { + GDTCORLogDebug( + "CCT: The backend responded asking to not upload for %lld millis from now.", + logResponse.next_request_wait_millis); + GDTCORClock *futureUploadTime = + [GDTCORClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis]; + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + default: + break; + } + } else { + GDTCORLogDebug("%@", @"CCT: The backend response failed to parse, so the next request " + @"won't occur until 15 minutes from now"); + // 15 minutes from now. + GDTCORClock *futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:15 * 60 * 1000]; + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + break; + + default: + break; + } + } + pb_release(gdt_cct_LogResponse_fields, &logResponse); + } + + // Only retry if one of these codes is returned. + if (((NSHTTPURLResponse *)response).statusCode == 429 || + ((NSHTTPURLResponse *)response).statusCode == 503) { + [package retryDeliveryInTheFuture]; + } else { +#if !NDEBUG + // Post a notification when in DEBUG mode to state how many packages were uploaded. Useful + // for validation during tests. + [[NSNotificationCenter defaultCenter] postNotificationName:GDTCCTUploadCompleteNotification + object:@(package.events.count)]; +#endif // #if !NDEBUG + GDTCORLogDebug("%@", @"CCT: package delivered"); + [package completeDelivery]; + } + + // End the background task if there was one. + if (bgID != GDTCORBackgroundIdentifierInvalid) { + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + } + self.currentTask = nil; + self.currentUploadPackage = nil; + }; + self->_currentUploadPackage = package; + NSData *requestProtoData = + [self constructRequestProtoFromPackage:(GDTCORUploadPackage *)package]; + NSData *gzippedData = [GDTCCTCompressionHelper gzippedData:requestProtoData]; + BOOL usingGzipData = gzippedData != nil && gzippedData.length < requestProtoData.length; + NSData *dataToSend = usingGzipData ? gzippedData : requestProtoData; + NSURLRequest *request = [self constructRequestForTarget:target data:dataToSend]; + GDTCORLogDebug("CTT: request created: %@", request); + self.currentTask = [self.uploaderSession uploadTaskWithRequest:request + fromData:dataToSend + completionHandler:completionHandler]; + GDTCORLogDebug("%@", @"CCT: The upload task is about to begin."); + [self.currentTask resume]; + }); +} + +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions { + __block BOOL result = NO; + dispatch_sync(_uploaderQueue, ^{ + if (target == kGDTCORTargetCSH && [GDTCCTPrioritizer sharedInstance].CSHEvents.count > 0) { + result = YES; + return; + } + if (self->_currentUploadPackage) { + result = NO; + GDTCORLogDebug("%@", @"CCT: can't upload because a package is in flight"); + return; + } + if (self->_currentTask) { + result = NO; + GDTCORLogDebug("%@", @"CCT: can't upload because a task is in progress"); + return; + } + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + result = YES; + GDTCORLogDebug("%@", @"CCT: a high priority event is allowing an upload"); + return; + } + switch (target) { + case kGDTCORTargetCCT: + if (self->_CCTNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_CCTNextUploadTime]; + } + break; + + case kGDTCORTargetFLL: + if (self->_FLLNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_FLLNextUploadTime]; + } + break; + + default: + // The CSH backend should be handled above. + break; + } + if (result) { + GDTCORLogDebug("CCT: can upload to target %ld because the request wait time has transpired", + (long)target); + } else { + GDTCORLogDebug("CCT: can't upload to target %ld because the backend asked to wait", + (long)target); + } + result = YES; + GDTCORLogDebug("CCT: can upload to target %ld because nothing is preventing it", (long)target); + }); + return result; +} + +#pragma mark - Private helper methods + +/** Constructs data given an upload package. + * + * @param package The upload package used to construct the request proto bytes. + * @return Proto bytes representing a gdt_cct_LogRequest object. + */ +- (nonnull NSData *)constructRequestProtoFromPackage:(GDTCORUploadPackage *)package { + // Segment the log events by log type. + NSMutableDictionary *> *logMappingIDToLogSet = + [[NSMutableDictionary alloc] init]; + [package.events + enumerateObjectsUsingBlock:^(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID]; + logSet = logSet ? logSet : [[NSMutableSet alloc] init]; + [logSet addObject:event]; + logMappingIDToLogSet[event.mappingID] = logSet; + }]; + + gdt_cct_BatchedLogRequest batchedLogRequest = + GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet); + + NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest); + pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest); + return data ? data : [[NSData alloc] init]; +} + +/** Constructs a request to FLL given a URL and request body data. + * + * @param target The target backend to send the request to. + * @param data The request body data. + * @return A new NSURLRequest ready to be sent to FLL. + */ +- (NSURLRequest *)constructRequestForTarget:(GDTCORTarget)target data:(NSData *)data { + NSURL *URL = [self serverURLForTarget:target]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + NSString *targetString; + switch (target) { + case kGDTCORTargetCCT: + targetString = @"cct"; + break; + + case kGDTCORTargetFLL: + targetString = @"fll"; + break; + + case kGDTCORTargetCSH: + targetString = @"csh"; + break; + + default: + targetString = @"unknown"; + break; + } + NSString *userAgent = + [NSString stringWithFormat:@"datatransport/%@ %@support/%@ apple/", kGDTCORVersion, + targetString, kGDTCCTSupportSDKVersion]; + if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) { + [request setValue:[self FLLAndCSHAPIKey] forHTTPHeaderField:@"X-Goog-Api-Key"]; + } + if ([GDTCCTCompressionHelper isGzipped:data]) { + [request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + } + [request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + request.HTTPMethod = @"POST"; + [request setHTTPBody:data]; + return request; +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageExpired:(GDTCORUploadPackage *)package { + dispatch_async(_uploaderQueue, ^{ + [self.currentTask cancel]; + self.currentTask = nil; + self.currentUploadPackage = nil; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_uploaderQueue, ^{ + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + }); +} + +#pragma mark - NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { + if (!completionHandler) { + return; + } + if (response.statusCode == 302 || response.statusCode == 301) { + if ([request.URL isEqual:[self serverURLForTarget:kGDTCORTargetFLL]]) { + NSURLRequest *newRequest = [self constructRequestForTarget:kGDTCORTargetCCT + data:task.originalRequest.HTTPBody]; + completionHandler(newRequest); + } + } else { + completionHandler(request); + } +} + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h new file mode 100644 index 0000000..08d0a4b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A class with methods to help with gzipped data. */ +@interface GDTCCTCompressionHelper : NSObject + +/** Compresses the given data and returns a new data object. + * + * @note Reduced version from GULNSData+zlib.m of GoogleUtilities. + * @return Compressed data, or nil if there was an error. + */ ++ (nullable NSData *)gzippedData:(NSData *)data; + +/** Returns YES if the data looks like it was gzip compressed by checking for the gzip magic number. + * + * @note: From https://en.wikipedia.org/wiki/Gzip, gzip's magic number is 1f 8b. + * @return YES if the data appears gzipped, NO otherwise. + */ ++ (BOOL)isGzipped:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h new file mode 100644 index 0000000..08081cc --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - General purpose encoders + +/** Converts an NSString* to a pb_bytes_array_t*. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param string The string to convert. + * @return A newly allocated array of bytes representing the UTF8 encoding of the string. + */ +pb_bytes_array_t *GDTCCTEncodeString(NSString *string); + +/** Converts an NSData to a pb_bytes_array_t*. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param data The data to convert. + * @return A newly allocated array of bytes with [data bytes] copied into it. + */ +pb_bytes_array_t *GDTCCTEncodeData(NSData *data); + +#pragma mark - CCT object constructors + +/** Encodes a batched log request. + * + * @note Ensure that pb_release is called on the batchedLogRequest param. + * + * @param batchedLogRequest A pointer to the log batch to encode to bytes. + * @return An NSData object representing the bytes of the log request batch. + */ +FOUNDATION_EXPORT +NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest); + +/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch. + * @return A newly created gdt_cct_BatchedLogRequest. + */ +FOUNDATION_EXPORT +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet); + +/** Constructs a log request given a log source and a set of events. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * @param logSource The CCT log source to put into the log request. + * @param logSet The set of events to send in this log request. + */ +FOUNDATION_EXPORT +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet *logSet); + +/** Constructs a gdt_cct_LogEvent given a GDTCORStoredEvent*. + * + * @param event The GDTCORStoredEvent to convert. + * @return The new gdt_cct_LogEvent object. + */ +FOUNDATION_EXPORT +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCORStoredEvent *event); + +/** Constructs a gdt_cct_ClientInfo representing the client device. + * + * @return The new gdt_cct_ClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_ClientInfo GDTCCTConstructClientInfo(void); + +/** Constructs a gdt_cct_IosClientInfo representing the client device. + * + * @return The new gdt_cct_IosClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void); + +#pragma mark - CCT object decoders + +/** Decodes a gdt_cct_LogResponse given proto bytes. + * + * @note malloc is called in this method. Ensure that pb_release is called on the return value. + * + * @param data The proto bytes of the gdt_cct_LogResponse. + * @param error An error that will be populated if something went wrong during decoding. + * @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly. + */ +FOUNDATION_EXPORT +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h new file mode 100644 index 0000000..22414e2 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the prioritization of events from GoogleDataTransport. */ +@interface GDTCCTPrioritizer : NSObject + +/** The queue on which this prioritizer operates. */ +@property(nonatomic) dispatch_queue_t queue; + +/** All CCT events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CCTEvents; + +/** All FLL events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *FLLEvents; + +/** All CSH events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CSHEvents; + +/** The most recent attempted upload of CCT daily uploaded logs. */ +@property(nonatomic) GDTCORClock *CCTTimeOfLastDailyUpload; + +/** The most recent attempted upload of FLL daily uploaded logs*/ +@property(nonatomic) GDTCORClock *FLLOfLastDailyUpload; + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h new file mode 100644 index 0000000..cdc322d --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +#if !NDEBUG +/** A notification fired when uploading is complete, detailing the number of events uploaded. */ +extern NSNotificationName const GDTCCTUploadCompleteNotification; +#endif // #if !NDEBUG + +/** Class capable of uploading events to the CCT backend. */ +@interface GDTCCTUploader : NSObject + +/** The queue on which all CCT uploading will occur. */ +@property(nonatomic, readonly) dispatch_queue_t uploaderQueue; + +/** The URL session that will attempt upload. */ +@property(nonatomic, readonly) NSURLSession *uploaderSession; + +/** The current upload task. */ +@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask; + +/** Current upload package. */ +@property(nullable, nonatomic) GDTCORUploadPackage *currentUploadPackage; + +/** The next upload time for the CCT target. */ +@property(nullable, nonatomic) GDTCORClock *CCTNextUploadTime; + +/** The next upload time for the FLL target. */ +@property(nullable, nonatomic) GDTCORClock *FLLNextUploadTime; + +#if !NDEBUG +/** An upload URL used across all targets. For testing only. */ +@property(nullable, nonatomic) NSURL *testServerURL; + +#endif // !NDEBUG + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c new file mode 100644 index 0000000..95846e6 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c @@ -0,0 +1,128 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 */ + +#include "cct.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE; +const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; +const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT; +const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0; + + +const pb_field_t gdt_cct_LogEvent_fields[7] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0), + PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0), + PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0), + PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0), + PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = { + PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default), + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_IosClientInfo_fields[8] = { + PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0), + PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0), + PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0), + PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0), + PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0), + PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_ClientInfo_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogRequest_fields[7] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0), + PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields), + PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0), + PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0), + PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = { + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0), + PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTiersOverride_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogResponse_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields), + PB_LAST_FIELD +}; + + + + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h new file mode 100644 index 0000000..a6d4cfb --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h @@ -0,0 +1,281 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 */ + +#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType { + gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5, + gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6, + gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7, + gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8, + gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15, + gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16, + gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17 +} gdt_cct_NetworkConnectionInfo_NetworkType; +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN +#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1)) + +typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype { + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2, + gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3, + gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6, + gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16, + gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19, + gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100 +} gdt_cct_NetworkConnectionInfo_MobileSubtype; +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1)) + +typedef enum _gdt_cct_ClientInfo_ClientType { + gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0, + gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15 +} gdt_cct_ClientInfo_ClientType; +#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN +#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE +#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1)) + +typedef enum _gdt_cct_QosTierConfiguration_QosTier { + gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2, + gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3, + gdt_cct_QosTierConfiguration_QosTier_NEVER = 4 +} gdt_cct_QosTierConfiguration_QosTier; +#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT +#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER +#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1)) + +/* Struct definitions */ +typedef struct _gdt_cct_BatchedLogRequest { + pb_size_t log_request_count; + struct _gdt_cct_LogRequest *log_request; +/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */ +} gdt_cct_BatchedLogRequest; + +typedef struct _gdt_cct_IosClientInfo { + pb_bytes_array_t *os_major_version; + pb_bytes_array_t *os_full_version; + pb_bytes_array_t *application_build; + pb_bytes_array_t *country; + pb_bytes_array_t *model; + pb_bytes_array_t *language_code; + pb_bytes_array_t *application_bundle_id; +/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */ +} gdt_cct_IosClientInfo; + +typedef struct _gdt_cct_ClientInfo { + bool has_client_type; + gdt_cct_ClientInfo_ClientType client_type; + bool has_ios_client_info; + gdt_cct_IosClientInfo ios_client_info; +/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */ +} gdt_cct_ClientInfo; + +typedef struct _gdt_cct_NetworkConnectionInfo { + bool has_network_type; + gdt_cct_NetworkConnectionInfo_NetworkType network_type; + bool has_mobile_subtype; + gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype; +/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */ +} gdt_cct_NetworkConnectionInfo; + +typedef struct _gdt_cct_QosTierConfiguration { + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; + bool has_log_source; + int32_t log_source; +/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */ +} gdt_cct_QosTierConfiguration; + +typedef struct _gdt_cct_QosTiersOverride { + pb_size_t qos_tier_configuration_count; + struct _gdt_cct_QosTierConfiguration *qos_tier_configuration; + bool has_qos_tier_fingerprint; + int64_t qos_tier_fingerprint; +/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */ +} gdt_cct_QosTiersOverride; + +typedef struct _gdt_cct_LogEvent { + bool has_event_time_ms; + int64_t event_time_ms; + pb_bytes_array_t *source_extension; + bool has_event_code; + int32_t event_code; + bool has_timezone_offset_seconds; + int64_t timezone_offset_seconds; + bool has_event_uptime_ms; + int64_t event_uptime_ms; + bool has_network_connection_info; + gdt_cct_NetworkConnectionInfo network_connection_info; +/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */ +} gdt_cct_LogEvent; + +typedef struct _gdt_cct_LogRequest { + bool has_client_info; + gdt_cct_ClientInfo client_info; + bool has_log_source; + int32_t log_source; + pb_size_t log_event_count; + struct _gdt_cct_LogEvent *log_event; + bool has_request_time_ms; + int64_t request_time_ms; + bool has_request_uptime_ms; + int64_t request_uptime_ms; + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */ +} gdt_cct_LogRequest; + +typedef struct _gdt_cct_LogResponse { + bool has_next_request_wait_millis; + int64_t next_request_wait_millis; + bool has_qos_tier; + gdt_cct_QosTiersOverride qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */ +} gdt_cct_LogResponse; + +/* Default values for struct fields */ +extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default; +extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default; +extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default; +extern const int32_t gdt_cct_QosTierConfiguration_log_source_default; + +/* Initializer values for message structs */ +#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default} +#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE} +#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default} +#define gdt_cct_BatchedLogRequest_init_default {0, NULL} +#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT} +#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default} +#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero} +#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN} +#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero} +#define gdt_cct_BatchedLogRequest_init_zero {0, NULL} +#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN} +#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define gdt_cct_BatchedLogRequest_log_request_tag 1 +#define gdt_cct_IosClientInfo_os_major_version_tag 3 +#define gdt_cct_IosClientInfo_os_full_version_tag 4 +#define gdt_cct_IosClientInfo_application_build_tag 5 +#define gdt_cct_IosClientInfo_country_tag 6 +#define gdt_cct_IosClientInfo_model_tag 7 +#define gdt_cct_IosClientInfo_language_code_tag 8 +#define gdt_cct_IosClientInfo_application_bundle_id_tag 11 +#define gdt_cct_ClientInfo_client_type_tag 1 +#define gdt_cct_ClientInfo_ios_client_info_tag 4 +#define gdt_cct_NetworkConnectionInfo_network_type_tag 1 +#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2 +#define gdt_cct_QosTierConfiguration_qos_tier_tag 2 +#define gdt_cct_QosTierConfiguration_log_source_tag 3 +#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1 +#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2 +#define gdt_cct_LogEvent_event_time_ms_tag 1 +#define gdt_cct_LogEvent_event_code_tag 11 +#define gdt_cct_LogEvent_event_uptime_ms_tag 17 +#define gdt_cct_LogEvent_source_extension_tag 6 +#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15 +#define gdt_cct_LogEvent_network_connection_info_tag 23 +#define gdt_cct_LogRequest_request_time_ms_tag 4 +#define gdt_cct_LogRequest_request_uptime_ms_tag 8 +#define gdt_cct_LogRequest_client_info_tag 1 +#define gdt_cct_LogRequest_log_source_tag 2 +#define gdt_cct_LogRequest_log_event_tag 3 +#define gdt_cct_LogRequest_qos_tier_tag 9 +#define gdt_cct_LogResponse_next_request_wait_millis_tag 1 +#define gdt_cct_LogResponse_qos_tier_tag 3 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t gdt_cct_LogEvent_fields[7]; +extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3]; +extern const pb_field_t gdt_cct_IosClientInfo_fields[8]; +extern const pb_field_t gdt_cct_ClientInfo_fields[3]; +extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2]; +extern const pb_field_t gdt_cct_LogRequest_fields[7]; +extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3]; +extern const pb_field_t gdt_cct_QosTiersOverride_fields[3]; +extern const pb_field_t gdt_cct_LogResponse_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* gdt_cct_LogEvent_size depends on runtime parameters */ +#define gdt_cct_NetworkConnectionInfo_size 13 +/* gdt_cct_IosClientInfo_size depends on runtime parameters */ +/* gdt_cct_ClientInfo_size depends on runtime parameters */ +/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */ +/* gdt_cct_LogRequest_size depends on runtime parameters */ +#define gdt_cct_QosTierConfiguration_size 13 +/* gdt_cct_QosTiersOverride_size depends on runtime parameters */ +/* gdt_cct_LogResponse_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CCT_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/LICENSE b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/README.md b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleDataTransportCCTSupport/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m new file mode 100644 index 0000000..173a776 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -0,0 +1,1038 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import +#import +#import +#import "GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h" +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +#import + +// Implementations need to be typed before calling the implementation directly to cast the +// arguments and the return types correctly. Otherwise, it will crash the app. +typedef BOOL (*GULRealOpenURLSourceApplicationAnnotationIMP)( + id, SEL, GULApplication *, NSURL *, NSString *, id); + +typedef BOOL (*GULRealOpenURLOptionsIMP)( + id, SEL, GULApplication *, NSURL *, NSDictionary *); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( + id, SEL, GULApplication *, NSString *, void (^)()); +#pragma clang diagnostic pop + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef BOOL (*GULRealContinueUserActivityIMP)( + id, SEL, GULApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); +#pragma clang diagnostic pop + +typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, GULApplication *, NSData *); + +typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, + SEL, + GULApplication *, + NSError *); + +typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, GULApplication *, NSDictionary *); + +// TODO: Since we don't support iOS 7 anymore, see if we can remove the check below. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( + id, SEL, GULApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +typedef void (^GULAppDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; + +static NSString *const kGULAppDelegateKeyPath = @"delegate"; + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/AppDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseAppDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the App Delegate. */ +static NSString *const kGULAppDelegatePrefix = @"GUL_"; + +/** The original instance of App Delegate. */ +static id gOriginalAppDelegate; + +/** The original App Delegate class */ +static Class gOriginalAppDelegateClass; + +/** The subclass of the original App Delegate. */ +static Class gAppDelegateSubclass; + +/** Remote notification methods selectors + * + * We have to opt out of referencing APNS related App Delegate methods directly to prevent + * an Apple review warning email about missing Push Notification Entitlement + * (like here: https://github.com/firebase/firebase-ios-sdk/issues/2807). From our experience, the + * warning is triggered when any of the symbols is present in the application sent to review, even + * if the code is never executed. Because GULAppDelegateSwizzler may be used by applications that + * are not using APNS we have to refer to the methods indirectly using selector constructed from + * string. + * + * NOTE: None of the methods is proxied unless it is explicitly requested by calling the method + * +[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods] + */ +static NSString *const kGULDidRegisterForRemoteNotificationsSEL = + @"application:didRegisterForRemoteNotificationsWithDeviceToken:"; +static NSString *const kGULDidFailToRegisterForRemoteNotificationsSEL = + @"application:didFailToRegisterForRemoteNotificationsWithError:"; +static NSString *const kGULDidReceiveRemoteNotificationSEL = + @"application:didReceiveRemoteNotification:"; +static NSString *const kGULDidReceiveRemoteNotificationWithCompletionSEL = + @"application:didReceiveRemoteNotification:fetchCompletionHandler:"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULZeroingWeakContainer +@end + +@interface GULAppDelegateObserver : NSObject +@end + +@implementation GULAppDelegateObserver { + BOOL _isObserving; +} + ++ (GULAppDelegateObserver *)sharedInstance { + static GULAppDelegateObserver *instance; + static dispatch_once_t once; + dispatch_once(&once, ^{ + instance = [[GULAppDelegateObserver alloc] init]; + }); + return instance; +} + +- (void)observeUIApplication { + if (_isObserving) { + return; + } + [[GULAppDelegateSwizzler sharedApplication] + addObserver:self + forKeyPath:kGULAppDelegateKeyPath + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:nil]; + _isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqual:kGULAppDelegateKeyPath]) { + id newValue = change[NSKeyValueChangeNewKey]; + id oldValue = change[NSKeyValueChangeOldKey]; + if ([newValue isEqual:oldValue]) { + return; + } + // Free the stored app delegate instance because it has been changed to a different instance to + // avoid keeping it alive forever. + if ([oldValue isEqual:gOriginalAppDelegate]) { + gOriginalAppDelegate = nil; + // Remove the observer. Parse it to NSObject to avoid warning. + [[GULAppDelegateSwizzler sharedApplication] removeObserver:self + forKeyPath:kGULAppDelegateKeyPath]; + _isObserving = NO; + } + } +} + +@end + +@implementation GULAppDelegateSwizzler + +static dispatch_once_t sProxyAppDelegateOnceToken; +static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; + +#pragma mark - Public methods + ++ (BOOL)isAppDelegateProxyEnabled { + NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; + + id isFirebaseProxyEnabledPlistValue = infoDictionary[kGULFirebaseAppDelegateProxyEnabledPlistKey]; + id isGoogleProxyEnabledPlistValue = + infoDictionary[kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey]; + + // Enabled by default. + BOOL isFirebaseAppDelegateProxyEnabled = YES; + BOOL isGoogleUtilitiesAppDelegateProxyEnabled = YES; + + if ([isFirebaseProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isFirebaseAppDelegateProxyEnabled = [isFirebaseProxyEnabledPlistValue boolValue]; + } + + if ([isGoogleProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isGoogleUtilitiesAppDelegateProxyEnabled = [isGoogleProxyEnabledPlistValue boolValue]; + } + + // Only deactivate the proxy if it is explicitly disabled by app developers using either one of + // the plist flags. + return isFirebaseAppDelegateProxyEnabled && isGoogleUtilitiesAppDelegateProxyEnabled; +} + ++ (GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor { + NSAssert(interceptor, @"AppDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(GULApplicationDelegate)], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling000], + @"AppDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling001], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = [NSString stringWithFormat:@"%@%p", kGULAppDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling002], + @"AppDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULZeroingWeakContainer *weakObject = [[GULZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULAppDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"AppDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"AppDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling003], + @"AppDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULZeroingWeakContainer *weakContainer = [GULAppDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling004], + @"AppDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + ++ (void)proxyOriginalDelegate { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + dispatch_once(&sProxyAppDelegateOnceToken, ^{ + id originalDelegate = + [GULAppDelegateSwizzler sharedApplication].delegate; + [GULAppDelegateSwizzler proxyAppDelegate:originalDelegate]; + }); +} + ++ (void)proxyOriginalDelegateIncludingAPNSMethods { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + [self proxyOriginalDelegate]; + + dispatch_once(&sProxyAppDelegateRemoteNotificationOnceToken, ^{ + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; + + NSMutableDictionary *realImplementationsBySelector = + [objc_getAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey) mutableCopy]; + + [self proxyRemoteNotificationsMethodsWithAppDelegateSubClass:gAppDelegateSubclass + realClass:gOriginalAppDelegateClass + appDelegate:appDelegate + realImplementationsBySelector:realImplementationsBySelector]; + + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN); + [self reassignAppDelegate]; + }); +} + +#pragma mark - Create proxy + ++ (GULApplication *)sharedApplication { + if ([GULAppEnvironmentUtil isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(kGULApplicationClassName); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - Override default methods + +/** Creates a new subclass of the class of the given object and sets the isa value of the given + * object to the new subclass. Additionally this copies methods to that new subclass that allow us + * to intercept UIApplicationDelegate methods. This is better known as isa swizzling. + * + * @param appDelegate The object to which you want to isa swizzle. This has to conform to the + * UIApplicationDelegate subclass. + * @return Returns the new subclass. + */ ++ (nullable Class)createSubclassWithObject:(id)appDelegate { + Class realClass = [appDelegate class]; + + // Create GUL__ + NSString *classNameWithPrefix = + [kGULAppDelegatePrefix stringByAppendingString:NSStringFromClass(realClass)]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling005], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: %@", + NSStringFromClass(realClass), newClassName); + return nil; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class appDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (appDelegateSubClass == Nil) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling006], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: Nil", + NSStringFromClass(realClass)); + return nil; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For application:continueUserActivity:restorationHandler: + SEL continueUserActivitySEL = @selector(application:continueUserActivity:restorationHandler:); + [self proxyDestinationSelector:continueUserActivitySEL + implementationsFromSourceSelector:continueUserActivitySEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + +#if TARGET_OS_IOS || TARGET_OS_TV + // Add the following methods from GULAppDelegate class, and store the real implementation so it + // can forward to the real one. + // For application:openURL:options: + SEL applicationOpenURLOptionsSEL = @selector(application:openURL:options:); + if ([appDelegate respondsToSelector:applicationOpenURLOptionsSEL]) { + // Only add the application:openURL:options: method if the original AppDelegate implements it. + // This fixes a bug if an app only implements application:openURL:sourceApplication:annotation: + // (if we add the `options` method, iOS sees that one exists and does not call the + // `sourceApplication` method, which in this case is the only one the app implements). + + [self proxyDestinationSelector:applicationOpenURLOptionsSEL + implementationsFromSourceSelector:applicationOpenURLOptionsSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + + // For application:handleEventsForBackgroundURLSession:completionHandler: + SEL handleEventsForBackgroundURLSessionSEL = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + [self proxyDestinationSelector:handleEventsForBackgroundURLSessionSEL + implementationsFromSourceSelector:handleEventsForBackgroundURLSessionSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + // For application:openURL:sourceApplication:annotation: + SEL openURLSourceApplicationAnnotationSEL = @selector(application: + openURL:sourceApplication:annotation:); + + [self proxyDestinationSelector:openURLSourceApplicationAnnotationSEL + implementationsFromSourceSelector:openURLSourceApplicationAnnotationSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS + + // Override the description too so the custom class name will not show up. + [GULAppDelegateSwizzler addInstanceMethodWithDestinationSelector:@selector(description) + withImplementationFromSourceSelector:@selector(fakeDescription) + fromClass:[self class] + toClass:appDelegateSubClass]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(appDelegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(appDelegateSubClass)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling007], + @"Cannot create subclass of App Delegate, because the created subclass is not the " + @"same size. %@", + NSStringFromClass(realClass)); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return nil; + } + + // Make the newly created class to be the subclass of the real App Delegate class. + objc_registerClassPair(appDelegateSubClass); + if (object_setClass(appDelegate, appDelegateSubClass)) { + GULLogDebug(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling008], + @"Successfully created App Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULAppDelegateSwizzler correctAppDelegateProxyKey]); + } + + return appDelegateSubClass; +} + ++ (void)proxyRemoteNotificationsMethodsWithAppDelegateSubClass:(Class)appDelegateSubClass + realClass:(Class)realClass + appDelegate:(id)appDelegate + realImplementationsBySelector: + (NSMutableDictionary *)realImplementationsBySelector { + if (realClass == nil || appDelegateSubClass == nil || appDelegate == nil || + realImplementationsBySelector == nil) { + // The App Delegate has not been swizzled. + return; + } + + // For application:didRegisterForRemoteNotificationsWithDeviceToken: + SEL didRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + SEL didRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didRegisterForRemoteNotificationsWithDeviceToken:); + + [self proxyDestinationSelector:didRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didFailToRegisterForRemoteNotificationsWithError: + SEL didFailToRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + SEL didFailToRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didFailToRegisterForRemoteNotificationsWithError:); + + [self proxyDestinationSelector:didFailToRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didFailToRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification: + SEL didReceiveRemoteNotificationSEL = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + SEL didReceiveRemoteNotificationDonotSEL = @selector(application: + donor_didReceiveRemoteNotification:); + + [self proxyDestinationSelector:didReceiveRemoteNotificationSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationDonotSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification:fetchCompletionHandler: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + if ([GULAppEnvironmentUtil isIOS7OrHigher]) { + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). + + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + } +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +} + +/// We have to do this to invalidate the cache that caches the original respondsToSelector of +/// openURL handlers. Without this, it won't call the default implementations because the system +/// checks and caches them. +/// Register KVO only once. Otherwise, the observing method will be called as many times as +/// being registered. ++ (void)reassignAppDelegate { +#if !TARGET_OS_WATCH + id delegate = [self sharedApplication].delegate; + [self sharedApplication].delegate = nil; + [self sharedApplication].delegate = delegate; + gOriginalAppDelegate = delegate; + [[GULAppDelegateObserver sharedInstance] observeUIApplication]; +#endif +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULAppDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULAppDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULAppDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULAppDelegateInterceptorCallback)callback { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULAppDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeAppDelegateSwizzling010], + @"AppDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + +// The methods below are donor methods which are added to the dynamic subclass of the App Delegate. +// They are called within the scope of the real App Delegate so |self| does not refer to the +// GULAppDelegateSwizzler instance but the real App Delegate instance. + +#pragma mark - [Donor Methods] Overridden instance description method + +- (NSString *)fakeDescription { + Class realClass = objc_getAssociatedObject(self, &kGULRealClassKey); + return [NSString stringWithFormat:@"<%@: %p>", realClass, self]; +} + +#pragma mark - [Donor Methods] URL overridden handler methods +#if TARGET_OS_IOS || TARGET_OS_TV + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options { + SEL methodSelector = @selector(application:openURL:options:); + // Call the real implementation if the real App Delegate has any. + NSValue *openURLIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLOptionsIMP openURLOptionsIMP = [openURLIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + +// This is needed to for the library to be warning free on iOS versions < 9. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + openURL:url + options:options]; + }]; +#pragma clang diagnostic pop + if (openURLOptionsIMP) { + returnedValue |= openURLOptionsIMP(self, methodSelector, application, url, options); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { + SEL methodSelector = @selector(application:openURL:sourceApplication:annotation:); + + // Call the real implementation if the real App Delegate has any. + NSValue *openURLSourceAppAnnotationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLSourceApplicationAnnotationIMP openURLSourceApplicationAnnotationIMP = + [openURLSourceAppAnnotationIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + returnedValue |= [interceptor application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#pragma clang diagnostic pop + }]; + if (openURLSourceApplicationAnnotationIMP) { + returnedValue |= openURLSourceApplicationAnnotationIMP(self, methodSelector, application, url, + sourceApplication, annotation); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS + +#pragma mark - [Donor Methods] Network overridden handler methods + +#if TARGET_OS_IOS || TARGET_OS_TV + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +- (void)application:(GULApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(void (^)())completionHandler API_AVAILABLE(ios(7.0)) { +#pragma clang diagnostic pop + SEL methodSelector = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + NSValue *handleBackgroundSessionPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealHandleEventsForBackgroundURLSessionIMP handleBackgroundSessionIMP = + [handleBackgroundSessionPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + [interceptor application:application + handleEventsForBackgroundURLSession:identifier + completionHandler:completionHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (handleBackgroundSessionIMP) { + handleBackgroundSessionIMP(self, methodSelector, application, identifier, completionHandler); + } +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - [Donor Methods] User Activities overridden handler methods + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (BOOL)application:(GULApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + SEL methodSelector = @selector(application:continueUserActivity:restorationHandler:); + NSValue *continueUserActivityIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealContinueUserActivityIMP continueUserActivityIMP = + continueUserActivityIMPPointer.pointerValue; + + __block BOOL returnedValue = NO; +#if !TARGET_OS_WATCH + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; + }]; +#endif + // Call the real implementation if the real App Delegate has any. + if (continueUserActivityIMP) { + returnedValue |= continueUserActivityIMP(self, methodSelector, application, userActivity, + restorationHandler); + } + return returnedValue; +} +#pragma clang diagnostic pop + +#pragma mark - [Donor Methods] Remote Notifications + +- (void)application:(GULApplication *)application + donor_didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + SEL methodSelector = NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + + NSValue *didRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidRegisterForRemoteNotificationsIMP didRegisterForRemoteNotificationsIMP = + [didRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&deviceToken) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didRegisterForRemoteNotificationsIMP) { + didRegisterForRemoteNotificationsIMP(self, methodSelector, application, deviceToken); + } +} + +- (void)application:(GULApplication *)application + donor_didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + SEL methodSelector = NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + NSValue *didFailToRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidFailToRegisterForRemoteNotificationsIMP didFailToRegisterForRemoteNotificationsIMP = + [didFailToRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&error) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didFailToRegisterForRemoteNotificationsIMP) { + didFailToRegisterForRemoteNotificationsIMP(self, methodSelector, application, error); + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + NSValue *didReceiveRemoteNotificationWithCompletionIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationWithCompletionIMP + didReceiveRemoteNotificationWithCompletionIMP = + [didReceiveRemoteNotificationWithCompletionIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation setArgument:(void *)(&completionHandler) atIndex:4]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationWithCompletionIMP) { + didReceiveRemoteNotificationWithCompletionIMP(self, methodSelector, application, userInfo, + completionHandler); + } +} +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + NSValue *didReceiveRemoteNotificationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationIMP didReceiveRemoteNotificationIMP = + [didReceiveRemoteNotificationIMPPointer pointerValue]; + + // Notify interceptors. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation invoke]; + }]; +#pragma clang diagnostic pop + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationIMP) { + didReceiveRemoteNotificationIMP(self, methodSelector, application, userInfo); + } +} + ++ (nullable NSInvocation *)appDelegateInvocationForSelector:(SEL)selector { + struct objc_method_description methodDescription = + protocol_getMethodDescription(@protocol(GULApplicationDelegate), selector, NO, YES); + if (methodDescription.types == NULL) { + return nil; + } + + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSInvocation invocationWithMethodSignature:signature]; +} + ++ (void)proxyAppDelegate:(id)appDelegate { + if (![appDelegate conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogNotice( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate], + @"App Delegate does not conform to UIApplicationDelegate protocol. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + id originalDelegate = appDelegate; + // Do not create a subclass if it is not enabled. + if (![GULAppDelegateSwizzler isAppDelegateProxyEnabled]) { + GULLogNotice(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling011], + @"App Delegate Proxy is disabled. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + // Do not accept nil delegate. + if (!originalDelegate) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling012], + @"Cannot create App Delegate Proxy because App Delegate instance is nil. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + @try { + gOriginalAppDelegateClass = [originalDelegate class]; + gAppDelegateSubclass = [self createSubclassWithObject:originalDelegate]; + [self reassignAppDelegate]; + } @catch (NSException *exception) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling013], + @"Cannot create App Delegate Proxy. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } +} + +#pragma mark - Methods to print correct debug logs + ++ (NSString *)correctAppDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseAppDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey; +} + ++ (NSString *)correctAlternativeWhenAppDelegateProxyNotCreated { + return NSClassFromString(@"FIRCore") + ? @"To log deep link campaigns manually, call the methods in " + @"FIRAnalytics+AppDelegate.h." + : @""; +} + +#pragma mark - Private Methods for Testing + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (void)resetProxyOriginalDelegateOnceToken { + sProxyAppDelegateOnceToken = 0; + sProxyAppDelegateRemoteNotificationOnceToken = 0; +} + ++ (id)originalDelegate { + return gOriginalAppDelegate; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h new file mode 100644 index 0000000..d7ebd86 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -0,0 +1,55 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +@class GULApplication; + +NS_ASSUME_NONNULL_BEGIN + +@interface GULAppDelegateSwizzler () + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param appDelegate The object that needs to be isa swizzled. This should conform to the + * application delegate protocol. + */ ++ (void)proxyAppDelegate:(id)appDelegate; + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */ ++ (void)resetProxyOriginalDelegateOnceToken; + +/** Returns the original app delegate that was proxied. + * + * @return The original app delegate instance that was proxied. + */ ++ (id)originalDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h new file mode 100644 index 0000000..c1b2d6e --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULAppDelegateInterceptorID; + +/** This class contains methods that isa swizzle the app delegate. */ +@interface GULAppDelegateSwizzler : NSProxy + +/** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the + * original app delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor; + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID; + +/** This method ensures that the original app delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the app delegate once). + * + * This method doesn't proxy APNS related methods: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * To proxy these methods use +[GULAppDelegateSwizzler + * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to + * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g. + * https://github.com/firebase/firebase-ios-sdk/issues/2807) + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegateIncludingAPNSMethods + */ ++ (void)proxyOriginalDelegate; + +/** This method ensures that the original app delegate has been proxied including APNS related + * methods. Call this before registering your interceptor. This method is safe to call multiple + * times (but it only proxies the app delegate once) or + * after +[GULAppDelegateSwizzler proxyOriginalDelegate] + * + * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood. + * After calling this method the following App Delegate methods will be proxied in addition to + * the methods proxied by proxyOriginalDelegate: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegate + */ ++ (void)proxyOriginalDelegateIncludingAPNSMethods; + +/** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if AppDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isAppDelegateProxyEnabled; + +/** Returns the current sharedApplication. + * + * @return the current application instance if in an app, or nil if in extension or if it doesn't + * exist. + */ ++ (nullable GULApplication *)sharedApplication; + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h new file mode 100644 index 0000000..8067212 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_TV + +#import + +#define GULApplication UIApplication +#define GULApplicationDelegate UIApplicationDelegate +#define GULUserActivityRestoring UIUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"UIApplication"; + +#elif TARGET_OS_OSX + +#import + +#define GULApplication NSApplication +#define GULApplicationDelegate NSApplicationDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"NSApplication"; + +#elif TARGET_OS_WATCH + +#import + +// We match the according watchOS API but swizzling should not work in watch +#define GULApplication WKExtension +#define GULApplicationDelegate WKExtensionDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"WKExtension"; + +#endif diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h new file mode 100644 index 0000000..053ce84 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) { + // App Delegate Swizzling. + kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000 + kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001 + kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002 + kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003 + kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004 + kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005 + kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006 + kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007 + kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008 + kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009 + kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010 + kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011 + kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012 + kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013 + kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014 + + // Scene Delegate Swizzling. + kGULSwizzlerMessageCodeSceneDelegateSwizzling000 = 1100, // I-SWZ001100 + kGULSwizzlerMessageCodeSceneDelegateSwizzling001 = 1101, // I-SWZ001101 + kGULSwizzlerMessageCodeSceneDelegateSwizzling002 = 1102, // I-SWZ001102 + kGULSwizzlerMessageCodeSceneDelegateSwizzling003 = 1103, // I-SWZ001103 + kGULSwizzlerMessageCodeSceneDelegateSwizzling004 = 1104, // I-SWZ001104 + kGULSwizzlerMessageCodeSceneDelegateSwizzling005 = 1105, // I-SWZ001105 + kGULSwizzlerMessageCodeSceneDelegateSwizzling006 = 1106, // I-SWZ001106 + kGULSwizzlerMessageCodeSceneDelegateSwizzling007 = 1107, // I-SWZ001107 + kGULSwizzlerMessageCodeSceneDelegateSwizzling008 = 1108, // I-SWZ001108 + kGULSwizzlerMessageCodeSceneDelegateSwizzling009 = 1109, // I-SWZ001109 + kGULSwizzlerMessageCodeSceneDelegateSwizzling010 = 1110, // I-SWZ001110 + kGULSwizzlerMessageCodeSceneDelegateSwizzling011 = 1111, // I-SWZ001111 + kGULSwizzlerMessageCodeSceneDelegateSwizzling012 = 1112, // I-SWZ001112 + kGULSwizzlerMessageCodeSceneDelegateSwizzling013 = 1113, // I-SWZ001113 + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate = 1114, // I-SWZ001114 + + // Method Swizzling. + kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000 +}; diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m new file mode 100644 index 0000000..483c859 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m @@ -0,0 +1,140 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@interface GULHeartbeatDateStorage () +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) NSFileCoordinator *fileCoordinator; +@end + +@implementation GULHeartbeatDateStorage + +- (instancetype)initWithFileName:(NSString *)fileName { + if (fileName == nil) { + return nil; + } + + self = [super init]; + if (self) { + _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *directoryURL = [[self class] directoryPathURL]; + [[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator]; + _fileURL = [directoryURL URLByAppendingPathComponent:fileName]; + } + return self; +} + +/** Returns the URL path of the Application Support folder. + * @return the URL path of Application Support. + */ ++ (NSURL *)directoryPathURL { + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSArray *components = @[ paths.lastObject, @"Google/FIRApp" ]; + NSString *directoryString = [NSString pathWithComponents:components]; + NSURL *directoryURL = [NSURL fileURLWithPath:directoryString]; + return directoryURL; +} + +/** Checks and creates a directory for the directory specified by the + * directory url + * @param directoryPathURL The path to the directory which needs to be created. + * @param fileCoordinator The fileCoordinator object to coordinate writes to the directory. + */ ++ (void)checkAndCreateDirectory:(NSURL *)directoryPathURL + fileCoordinator:(NSFileCoordinator *)fileCoordinator { + NSError *fileCoordinatorError = nil; + [fileCoordinator + coordinateWritingItemAtURL:directoryPathURL + options:0 + error:&fileCoordinatorError + byAccessor:^(NSURL *writingDirectoryURL) { + NSError *error; + if (![writingDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + // If fail creating the Application Support directory, log warning. + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtURL:writingDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&error]; + } + }]; +} + +- (nullable NSMutableDictionary *)heartbeatDictionaryWithFileURL:(NSURL *)readingFileURL { + NSError *error; + NSMutableDictionary *dict; + NSData *objectData = [NSData dataWithContentsOfURL:readingFileURL options:0 error:&error]; + if (objectData == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } else { + dict = [GULSecureCoding + unarchivedObjectOfClasses:[NSSet setWithArray:@[ NSDictionary.class, NSDate.class ]] + fromData:objectData + error:&error]; + if (dict == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } + } + return dict; +} + +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag { + __block NSMutableDictionary *dict; + NSError *error; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL) { + dict = [self heartbeatDictionaryWithFileURL:readingURL]; + }]; + return dict[tag]; +} + +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag { + NSError *error; + __block BOOL isSuccess = false; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + writingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL, NSURL *writingURL) { + NSMutableDictionary *dictionary = + [self heartbeatDictionaryWithFileURL:readingURL]; + dictionary[tag] = date; + NSError *error; + isSuccess = [self writeDictionary:dictionary + forWritingURL:writingURL + error:&error]; + }]; + return isSuccess; +} + +- (BOOL)writeDictionary:(NSMutableDictionary *)dictionary + forWritingURL:(NSURL *)writingFileURL + error:(NSError **)outError { + NSData *data = [GULSecureCoding archivedDataWithRootObject:dictionary error:outError]; + if (*outError != nil) { + return false; + } else { + return [data writeToURL:writingFileURL atomically:YES]; + } +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m new file mode 100644 index 0000000..ebfb808 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m @@ -0,0 +1,103 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/Public/GULSecureCoding.h" + +NSString *const kGULSecureCodingError = @"GULSecureCodingError"; + +@implementation GULSecureCoding + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError { + id object; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + object = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:data error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + unarchiver.requiresSecureCoding = YES; + + object = [unarchiver decodeObjectOfClasses:classes forKey:NSKeyedArchiveRootObjectKey]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + + if (object == nil && outError && *outError == nil) { + NSString *failureReason = @"NSKeyedUnarchiver failed to unarchive data."; + *outError = [NSError errorWithDomain:kGULSecureCodingError + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : failureReason}]; + } + } + + return object; +} + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError { + return [self unarchivedObjectOfClasses:[NSSet setWithObject:class] fromData:data error:outError]; +} + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError { + NSData *archiveData; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + archiveData = [NSKeyedArchiver archivedDataWithRootObject:object + requiringSecureCoding:YES + error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { + NSMutableData *data = [NSMutableData data]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + archiver.requiresSecureCoding = YES; + + [archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey]; + [archiver finishEncoding]; + + archiveData = [data copy]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + } + + return archiveData; +} + ++ (NSError *)archivingErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + NSDictionary *errorUserInfo = @{NSLocalizedFailureReasonErrorKey : failureReason}; + + return [NSError errorWithDomain:kGULSecureCodingError code:-1 userInfo:errorUserInfo]; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h new file mode 100644 index 0000000..9432dfc --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Stores either a date or a dictionary to a specified file. +@interface GULHeartbeatDateStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, readonly) NSURL *fileURL; + +/** + * Default initializer. + * @param fileName The name of the file to store the date information. + * exist, it will be created if needed. + */ +- (instancetype)initWithFileName:(NSString *)fileName; + +/** + * Reads the date from the specified file for the given tag. + * @return Returns date if exists, otherwise `nil`. + */ +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag; + +/** + * Saves the date for the specified tag in the specified file. + * @return YES on success, NO otherwise. + */ +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h new file mode 100644 index 0000000..8484b39 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class wraps `NSKeyedArchiver` and `NSKeyedUnarchiver` API to provide a unified secure coding + * methods for iOS versions before and after 11. + */ +@interface GULSecureCoding : NSObject + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h new file mode 100644 index 0000000..d550264 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m new file mode 100644 index 0000000..6442941 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -0,0 +1,263 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h" + +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import +#endif + +/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from +/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just +/// provide the definitions here. +#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) +#define LC_ENCRYPTION_INFO 0x21 +struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; +}; +#endif + +@implementation GULAppEnvironmentUtil + +/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. +/// This will affect your data integrity when using Firebase Analytics, as it will disable some +/// necessary checks. +static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = + @"FirebaseAppStoreReceiptURLCheckEnabled"; + +/// The file name of the sandbox receipt. This is available on iOS >= 8.0 +static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; + +/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. +/// +/// Copyright (c) 2017 Landon J. Fuller +/// All rights reserved. +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +/// and associated documentation files (the "Software"), to deal in the Software without +/// restriction, including without limitation the rights to use, copy, modify, merge, publish, +/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +/// Software is furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in all copies or +/// substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/// +/// Comment from iPhone Dev Wiki +/// Crack Prevention: +/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so +/// that decryption keys are needed in order to make the binary readable. When iOS executes the +/// binary, the decryption keys are used to decrypt the binary into a readable state where it is +/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the +/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero +/// value then the binary is encrypted. +/// +/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into +/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as +/// codesignature validation has been removed. Resigning takes place because while the codesignature +/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have +/// AppSync or similar to disable codesignature checks. +/// +/// More information at Landon Fuller's blog +static BOOL IsAppEncrypted() { + const struct mach_header *executableHeader = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *header = _dyld_get_image_header(i); + if (header && header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + + if (!executableHeader) { + return NO; + } + + BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); + uintptr_t cursor = (uintptr_t)executableHeader + + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); + const struct segment_command *segmentCommand = NULL; + uint32_t i = 0; + + while (i++ < executableHeader->ncmds) { + segmentCommand = (struct segment_command *)cursor; + + if (!segmentCommand) { + continue; + } + + if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || + (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { + if (is64bit) { + struct encryption_info_command_64 *cryptCmd = + (struct encryption_info_command_64 *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } else { + struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } + } + cursor += segmentCommand->cmdsize; + } + + return NO; +} + +static BOOL HasSCInfoFolder() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *bundlePath = [NSBundle mainBundle].bundlePath; + NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; + return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; +#elif TARGET_OS_OSX + return NO; +#endif +} + +static BOOL HasEmbeddedMobileProvision() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isFromAppStore { + static dispatch_once_t isEncryptedOnce; + static BOOL isEncrypted = NO; + + dispatch_once(&isEncryptedOnce, ^{ + isEncrypted = IsAppEncrypted(); + }); + + if ([GULAppEnvironmentUtil isSimulator]) { + return NO; + } + + // If an app contain the sandboxReceipt file, it means its coming from TestFlight + // This must be checked before the SCInfo Folder check below since TestFlight apps may + // also have an SCInfo folder. + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { + return NO; + } + + if (HasSCInfoFolder()) { + // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the + // main SC_Info directory. + return YES; + } + + // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read + // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. + // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when + // the app is submitted to store, then it is highly likely that it is from Apple Store. + return isEncrypted && !HasEmbeddedMobileProvision(); +} + ++ (BOOL)isAppStoreReceiptSandbox { + // Since checking the App Store's receipt URL can be memory intensive, check the option in the + // Info.plist if developers opted out of this check. + id enableSandboxCheck = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; + if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && + ![enableSandboxCheck boolValue]) { + return NO; + } +// The #else is for pre Xcode 9 where @available is not yet implemented. +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; + } + return NO; +} + ++ (BOOL)isSimulator { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *platform = [GULAppEnvironmentUtil deviceModel]; + return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; +#elif TARGET_OS_OSX + return NO; +#endif + return NO; +} + ++ (NSString *)deviceModel { + static dispatch_once_t once; + static NSString *deviceModel; + + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return deviceModel; +} + ++ (NSString *)systemVersion { +#if TARGET_OS_IOS + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_TV || TARGET_OS_WATCH + // Assemble the systemVersion, excluding the patch version if it's 0. + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + NSMutableString *versionString = [[NSMutableString alloc] + initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; + if (osVersion.patchVersion != 0) { + [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; + } + return versionString; +#endif +} + ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + // Documented by Apple + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isIOS7OrHigher { +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + return YES; + } + + return NO; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/LICENSE b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/LICENSE new file mode 100644 index 0000000..30a8f72 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/LICENSE @@ -0,0 +1,247 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m new file mode 100644 index 0000000..0a512da --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -0,0 +1,214 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Logger/Private/GULLogger.h" + +#include + +#import +#import + +/// ASL client facility name used by GULLogger. +const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; + +static dispatch_once_t sGULLoggerOnceToken; + +static aslclient sGULLoggerClient; + +static dispatch_queue_t sGULClientQueue; + +static BOOL sGULLoggerDebugMode; + +static GULLoggerLevel sGULLoggerMaximumLevel; + +// Allow clients to register a version to include in the log. +static const char *sVersion = ""; + +static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void GULLoggerInitializeASL(void) { + dispatch_once(&sGULLoggerOnceToken, ^{ + NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; + uint32_t aslOptions = ASL_OPT_STDERR; +#if TARGET_OS_SIMULATOR + // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 11) { + aslOptions = 0; + } +#else + // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 10) { + aslOptions = 0; + } +#endif // TARGET_OS_SIMULATOR + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated + // Initialize the ASL client handle. + sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); + sGULLoggerMaximumLevel = GULLoggerLevelNotice; + + // Set the filter used by system/device log. Initialize in default mode. + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); + + sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(sGULClientQueue, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); +#ifdef DEBUG + sMessageCodeRegex = [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern + options:0 + error:NULL]; +#endif + }); +} + +void GULLoggerEnableSTDERR(void) { + asl_add_log_file(sGULLoggerClient, STDERR_FILENO); +} + +void GULLoggerForceDebug(void) { + // We should enable debug mode if we're not running from App Store. + if (![GULAppEnvironmentUtil isFromAppStore]) { + sGULLoggerDebugMode = YES; + GULSetLoggerLevel(GULLoggerLevelDebug); + } +} + +__attribute__((no_sanitize("thread"))) void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { + if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { + GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", + (long)loggerLevel); + return; + } + GULLoggerInitializeASL(); + // We should not raise the logger level if we are running from App Store. + if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { + return; + } + + sGULLoggerMaximumLevel = loggerLevel; + dispatch_async(sGULClientQueue, ^{ + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); + }); +} + +/** + * Check if the level is high enough to be loggable. + */ +__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { + GULLoggerInitializeASL(); + if (sGULLoggerDebugMode) { + return YES; + } + return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); +} + +#ifdef DEBUG +void GULResetLogger() { + sGULLoggerOnceToken = 0; +} + +aslclient getGULLoggerClient() { + return sGULLoggerClient; +} + +dispatch_queue_t getGULClientQueue() { + return sGULClientQueue; +} + +BOOL getGULLoggerDebugMode() { + return sGULLoggerDebugMode; +} +#endif + +void GULLoggerRegisterVersion(const char *version) { + sVersion = version; +} + +void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + GULLoggerInitializeASL(); + if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { + return; + } + +#ifdef DEBUG + NSCAssert(messageCode.length == 11, @"Incorrect message code length."); + NSRange messageCodeRange = NSMakeRange(0, messageCode.length); + NSUInteger numberOfMatches = [sMessageCodeRegex numberOfMatchesInString:messageCode + options:0 + range:messageCodeRange]; + NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); +#endif + NSString *logMsg; + if (args_ptr == NULL) { + logMsg = message; + } else { + logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; + } + logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; + dispatch_async(sGULClientQueue, ^{ + asl_log(sGULLoggerClient, NULL, (int)level, "%s", logMsg.UTF8String); + }); +} +#pragma clang diagnostic pop + +/** + * Generates the logging functions using macros. + * + * Calling GULLogError({service}, @"I-XYZ000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure blah failed. + * Calling GULLogDebug({service}, @"I-XYZ000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure succeed. + */ +#define GUL_LOGGING_FUNCTION(level) \ + void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ + NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +GUL_LOGGING_FUNCTION(Error) +GUL_LOGGING_FUNCTION(Warning) +GUL_LOGGING_FUNCTION(Notice) +GUL_LOGGING_FUNCTION(Info) +GUL_LOGGING_FUNCTION(Debug) + +#undef GUL_MAKE_LOGGER + +#pragma mark - GULLoggerWrapper + +@implementation GULLoggerWrapper + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + GULLogBasic(level, service, NO, messageCode, message, args); +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h new file mode 100644 index 0000000..ff42576 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The services used in the logger. + */ +typedef NSString *const GULLoggerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initialize GULLogger. + */ +extern void GULLoggerInitializeASL(void); + +/** + * Override log level to Debug. + */ +void GULLoggerForceDebug(void); + +/** + * Turn on logging to STDERR. + */ +extern void GULLoggerEnableSTDERR(void); + +/** + * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. + * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); + +/** + * Register version to include in logs. + * (required) version + */ +extern void GULLoggerRegisterVersion(const char *version); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type GULLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void GULLogError(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogWarning(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogNotice(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogInfo(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogDebug(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface GULLoggerWrapper : NSObject + +/** + * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h new file mode 100644 index 0000000..f0ee435 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, GULLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + GULLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + GULLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + GULLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + GULLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + GULLoggerLevelDebug = 7, + /** Minimum log level. */ + GULLoggerLevelMin = GULLoggerLevelError, + /** Maximum log level. */ + GULLoggerLevelMax = GULLoggerLevelDebug +} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m new file mode 100644 index 0000000..27d48bb --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -0,0 +1,153 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h" + +#import + +#ifdef DEBUG +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]"; +#endif + +dispatch_queue_t GetGULSwizzlingQueue(void) { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +@implementation GULSwizzler + ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block { + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + Class resolvedClass = aClass; + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + resolvedClass = object_getClass(aClass); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + IMP newImp = imp_implementationWithBlock(block); +#ifdef DEBUG + IMP currentImp = class_getMethodImplementation(resolvedClass, selector); + Class class = NSClassFromString(@"GULSwizzlingCache"); + if (class) { + SEL cacheSelector = NSSelectorFromString(@"cacheCurrentIMP:forNewIMP:forClass:withSelector:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:cacheSelector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:cacheSelector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv setArgument:&(newImp) atIndex:3]; + [inv setArgument:&(resolvedClass) atIndex:4]; + [inv setArgument:(void *_Nonnull) & (selector) atIndex:5]; + [inv invoke]; + } + } +#endif + + const char *typeEncoding = method_getTypeEncoding(method); + __unused IMP originalImpOfClass = + class_replaceMethod(resolvedClass, selector, newImp, typeEncoding); + +#ifdef DEBUG + // If !originalImpOfClass, then the IMP came from a superclass. + if (originalImpOfClass) { + SEL selector = NSSelectorFromString(@"originalIMPOfCurrentIMP:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:selector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv invoke]; + IMP testOriginal; + [inv getReturnValue:&testOriginal]; + if (originalImpOfClass != testOriginal) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeMethodSwizzling000], + @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + } + } + } +#endif + }); +} + ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + if (selector == NULL || aClass == nil) { + return nil; + } + __block IMP currentIMP = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + if (method == nil) { + return; + } + currentIMP = method_getImplementation(method); + NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + }); + return currentIMP; +} + ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector { + Method method = isClassSelector ? class_getClassMethod(aClass, selector) + : class_getInstanceMethod(aClass, selector); + return method != nil; +} + ++ (NSArray *)ivarObjectsForObject:(id)object { + NSMutableArray *array = [NSMutableArray array]; + unsigned int count; + Ivar *vars = class_copyIvarList([object class], &count); + for (NSUInteger i = 0; i < count; i++) { + const char *typeEncoding = ivar_getTypeEncoding(vars[i]); + // Check to see if the ivar is an object. + if (strncmp(typeEncoding, "@", 1) == 0) { + id ivarObject = object_getIvar(object, vars[i]); + [array addObject:ivarObject]; + } + } + free(vars); + return array; +} +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h new file mode 100644 index 0000000..a33262a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h @@ -0,0 +1,207 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GULOriginalIMPConvenienceMacros.h + * + * This header contains convenience macros for invoking the original IMP of a swizzled method. + */ + +/** + * Invokes original IMP when the original selector takes no arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + */ +#define GUL_INVOKE_ORIGINAL_IMP0(__receivingObject, __swizzledSEL, __returnType, __originalIMP) \ + ((__returnType(*)(id, SEL))__originalIMP)(__receivingObject, __swizzledSEL) + +/** + * Invokes original IMP when the original selector takes 1 argument. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP1(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1)))__originalIMP)(__receivingObject, __swizzledSEL, \ + __arg1) + +/** + * Invokes original IMP when the original selector takes 2 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP2(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2) + +/** + * Invokes original IMP when the original selector takes 3 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP3(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), \ + __typeof__(__arg3)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3) + +/** + * Invokes original IMP when the original selector takes 4 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP4(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3, __arg4) + +/** + * Invokes original IMP when the original selector takes 5 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP5(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5) + +/** + * Invokes original IMP when the original selector takes 6 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP6(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) + +/** + * Invokes original IMP when the original selector takes 7 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP7(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) + +/** + * Invokes original IMP when the original selector takes 8 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP8(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8) + +/** + * Invokes original IMP when the original selector takes 9 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + * @param __arg9 The ninth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP9(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, \ + __arg9) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8), __typeof__(__arg9)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8, __arg9) diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h new file mode 100644 index 0000000..26949c8 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class handles the runtime manipulation necessary to instrument selectors. It stores the + * classes and selectors that have been swizzled, and runs all operations on its own queue. + */ +@interface GULSwizzler : NSObject + +/** Manipulates the Objective-C runtime to replace the original IMP with the supplied block. + * + * @param aClass The class to swizzle. + * @param selector The selector of the class to swizzle. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @param block The block that replaces the original IMP. + */ ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block; + +/** Returns the current IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime. + */ ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Checks the runtime to see if a selector exists on a class. If a property is declared as + * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists + * only in concrete subclasses, and NOT in the superclass. We can detect that situation using + * this helper method. Similarly, we can detect situations where a class doesn't implement a + * protocol method. + * + * @param selector The selector to check for. + * @param aClass The class to check. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return YES if the method was found in this selector/class combination, NO otherwise. + */ ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector; + +/** Returns a list of all Objective-C (and not primitive) ivars contained by the given object. + * + * @param object The object whose ivars will be iterated. + * @return The list of ivar objects. + */ ++ (NSArray *)ivarObjectsForObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h new file mode 100644 index 0000000..36f94a7 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h @@ -0,0 +1,49 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. + +// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given +// such data. To handle data of that size you really should be streaming it rather then doing it all +// in memory. + +@interface NSData (GULGzip) + +/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must +/// be a gzipped payloads. ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; + +/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default +/// compression level. ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; + +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber +FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber + +typedef NS_ENUM(NSInteger, GULNSDataZlibError) { + GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, + // An internal zlib error. + // GULNSDataZlibErrorKey will contain the error value. + // NSLocalizedDescriptionKey may contain an error string from zlib. + // Look in zlib.h for list of errors. + GULNSDataZlibErrorInternal, + // There was left over data in the buffer that was not used. + // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. + GULNSDataZlibErrorDataRemaining +}; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m new file mode 100644 index 0000000..5a77bb8 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -0,0 +1,207 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/NSData+zlib/GULNSData+zlib.h" + +#import + +#define kChunkSize 1024 +#define Z_DEFAULT_COMPRESSION (-1) + +NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; +NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; +NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; + +@implementation NSData (GULGzip) + ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 4x the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; + unsigned char output[kChunkSize]; + + // Loop to collect the data. + do { + // Update what we're passing in. + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + if (strm.msg) { + NSString *message = [NSString stringWithUTF8String:strm.msg]; + if (message) { + [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; + } + } + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + inflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // Make sure there wasn't more data tacked onto the end of a valid compressed stream. + if (strm.avail_in != 0) { + if (error) { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] + forKey:GULNSDataZlibRemainingBytesKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorDataRemaining + userInfo:userInfo]; + } + result = nil; + } + // The only way out of the loop was by hitting the end of the stream. + NSAssert(retCode == Z_STREAM_END, + @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + inflateEnd(&strm); + + return result; +} + ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + if (error) { + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorGreaterThan32BitsToCompress + userInfo:nil]; + } + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m new file mode 100644 index 0000000..4389660 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m @@ -0,0 +1,101 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" + +@implementation GULMutableDictionary { + /// The mutable dictionary. + NSMutableDictionary *_objects; + + /// Serial synchronization queue. All reads should use dispatch_sync, while writes use + /// dispatch_async. + dispatch_queue_t _queue; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _objects = [[NSMutableDictionary alloc] init]; + _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (NSString *)description { + __block NSString *description; + dispatch_sync(_queue, ^{ + description = self->_objects.description; + }); + return description; +} + +- (id)objectForKey:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = [self->_objects objectForKey:key]; + }); + return object; +} + +- (void)setObject:(id)object forKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects setObject:object forKey:key]; + }); +} + +- (void)removeObjectForKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_async(_queue, ^{ + [self->_objects removeAllObjects]; + }); +} + +- (NSUInteger)count { + __block NSUInteger count; + dispatch_sync(_queue, ^{ + count = self->_objects.count; + }); + return count; +} + +- (id)objectForKeyedSubscript:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = self->_objects[key]; + }); + return object; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + dispatch_async(_queue, ^{ + self->_objects[key] = obj; + }); +} + +- (NSDictionary *)dictionary { + __block NSDictionary *dictionary; + dispatch_sync(_queue, ^{ + dictionary = [self->_objects copy]; + }); + return dictionary; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m new file mode 100644 index 0000000..9d78e0e --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -0,0 +1,389 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetwork.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +#import +#import +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +/// Constant string for request header Content-Encoding. +static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; + +/// Constant string for request header Content-Encoding value. +static NSString *const kGULNetworkContentCompressionValue = @"gzip"; + +/// Constant string for request header Content-Length. +static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; + +/// Constant string for request header Content-Type. +static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; + +/// Constant string for request header Content-Type value. +static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; + +/// Constant string for GET request method. +static NSString *const kGULNetworkGETRequestMethod = @"GET"; + +/// Constant string for POST request method. +static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; + +/// Default constant string as a prefix for network logger. +static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; + +@interface GULNetwork () +@end + +@implementation GULNetwork { + /// Network reachability. + GULReachabilityChecker *_reachability; + + /// The dictionary of requests by session IDs { NSString : id }. + GULMutableDictionary *_requests; +} + +- (instancetype)init { + return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; +} + +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { + self = [super init]; + if (self) { + // Setup reachability. + _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:reachabilityHost]; + if (![_reachability start]) { + return nil; + } + + _requests = [[GULMutableDictionary alloc] init]; + _timeoutInterval = kGULNetworkTimeOutInterval; + } + return self; +} + +- (void)dealloc { + _reachability.reachabilityDelegate = nil; + [_reachability stop]; +} + +#pragma mark - External Methods + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { + [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID + completionHandler:completionHandler]; +} + +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + NSError *compressError = nil; + NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; + if (!compressedData || compressError) { + if (compressError || payload.length > 0) { + // If the payload is not empty but it fails to compress the payload, something has been wrong. + [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression + queue:queue + withHandler:handler]; + return nil; + } + compressedData = [[NSData alloc] init]; + } + + NSString *postLength = @(compressedData.length).stringValue; + + // Set up the request with the compressed data. + [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; + request.HTTPBody = compressedData; + request.HTTPMethod = kGULNetworkPOSTRequestMethod; + [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; + [request setValue:kGULNetworkContentCompressionValue + forHTTPHeaderField:kGULNetworkContentCompressionKey]; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncPOSTRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, + NSString *sessionID, NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork000 + message:@"Uploading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + request.HTTPMethod = kGULNetworkGETRequestMethod; + request.allHTTPHeaderFields = headers; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncGETRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, + NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork001 + message:@"Downloading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (BOOL)hasUploadInProgress { + return _requests.count > 0; +} + +#pragma mark - Network Reachability + +/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network +/// reachability has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); + [_reachabilityDelegate reachabilityDidChange]; +} + +#pragma mark - Network logger delegate + +- (void)setLoggerDelegate:(id)loggerDelegate { + // Explicitly check whether the delegate responds to the methods because conformsToProtocol does + // not work correctly even though the delegate does respond to the methods. + if (!loggerDelegate || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:contexts:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:context:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:)]) { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], + @"Cannot set the network logger delegate: delegate does not conform to the network " + "logger protocol."); + return; + } + _loggerDelegate = loggerDelegate; +} + +#pragma mark - Private methods + +/// Handles network error and calls completion handler with the error. +- (void)handleErrorWithCode:(NSInteger)code + queue:(dispatch_queue_t)queue + withHandler:(GULNetworkCompletionHandler)handler { + NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; + NSError *error = [[NSError alloc] initWithDomain:kGULNetworkErrorDomain + code:code + userInfo:userInfo]; + [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeNetwork002 + message:@"Failed to create network request. Code, error" + contexts:@[ @(code), error ]]; + if (handler) { + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + handler(nil, nil, error); + }); + } +} + +#pragma mark - Network logger + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts { + // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log + // errors/warnings/info messages to the console log. + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + contexts:contexts]; + return; + } + if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || + logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { + NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); + NSLog(@"%@", formattedMessage); + GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, + NULL); + } +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + context:context]; + return; + } + NSArray *contexts = context ? @[ context ] : @[]; + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; + return; + } + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; +} + +/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). +static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { + static NSDictionary *levelNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelNames = @{ + @(kGULNetworkLogLevelError) : @"ERROR", + @(kGULNetworkLogLevelWarning) : @"WARNING", + @(kGULNetworkLogLevelInfo) : @"INFO", + @(kGULNetworkLogLevelDebug) : @"DEBUG" + }; + }); + return levelNames[@(logLevel)]; +} + +/// Returns a formatted string to be used for console logging. +static NSString *GULStringWithLogMessage(NSString *message, + GULNetworkLogLevel logLevel, + NSArray *contexts) { + if (!message) { + message = @"(Message was nil)"; + } else if (!message.length) { + message = @"(Message was empty)"; + } + NSMutableString *result = [[NSMutableString alloc] + initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), + message]; + + if (!contexts.count) { + return result; + } + + NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; + for (id item in contexts) { + [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; + } + + [result appendString:@": "]; + [result appendString:[formattedContexts componentsJoinedByString:@", "]]; + return result; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m new file mode 100644 index 0000000..dea8dbd --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m @@ -0,0 +1,40 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +#import + +NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; +NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; +NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; +const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour +const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. +NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; +NSString *const kGULNetworkErrorContext = @"Context"; + +const int kGULNetworkHTTPStatusOK = 200; +const int kGULNetworkHTTPStatusNoContent = 204; +const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; +const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; +const int kGULNetworkHTTPStatusCodeFound = 302; +const int kGULNetworkHTTPStatusCodeNotModified = 304; +const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; +const int kGULNetworkHTTPStatusCodeNotFound = 404; +const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; +const int kGULNetworkHTTPStatusCodeUnavailable = 503; + +NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; + +GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m new file mode 100644 index 0000000..df8bf46 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -0,0 +1,762 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h" + +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +@interface GULNetworkURLSession () +@end + +@implementation GULNetworkURLSession { + /// The handler to be called when the request completes or error has occurs. + GULNetworkURLSessionCompletionHandler _completionHandler; + + /// Session ID generated randomly with a fixed prefix. + NSString *_sessionID; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + /// The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer. + NSURLSessionConfiguration *_sessionConfig; + + /// The current NSURLSession. + NSURLSession *__weak _Nullable _URLSession; +#pragma clang diagnostic pop + + /// The path to the directory where all temporary files are stored before uploading. + NSURL *_networkDirectoryURL; + + /// The downloaded data from fetching. + NSData *_downloadedData; + + /// The path to the temporary file which stores the uploading data. + NSURL *_uploadingFileURL; + + /// The current request. + NSURLRequest *_request; +} + +#pragma mark - Init + +- (instancetype)initWithNetworkLoggerDelegate:(id)networkLoggerDelegate { + self = [super init]; + if (self) { + // Create URL to the directory where all temporary files to upload have to be stored. + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportDirectory = paths.firstObject; + NSArray *tempPathComponents = @[ + applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, + kGULNetworkTempDirectoryName + ]; + _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; + _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, + [[NSUUID UUID] UUIDString]]; + _loggerDelegate = networkLoggerDelegate; + } + return self; +} + +#pragma mark - External Methods + +#pragma mark - To be called from AppDelegate + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler: + (GULNetworkSystemCompletionHandler)systemCompletionHandler { + // The session may not be Analytics background. Ignore those that do not have the prefix. + if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + return; + } + GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; + if (fetcher != nil) { + [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; + } else { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], + @"Failed to retrieve background session with ID %@ after app is relaunched.", + sessionID); + } +} + +#pragma mark - External Methods + +/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the +/// connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + // NSURLSessionUploadTask does not work with NSData in the background. + // To avoid this issue, write the data to a temporary file to upload it. + // Make a temporary file with the data subset. + _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; + NSError *writeError; + NSURLSessionUploadTask *postRequestTask; + NSURLSession *session; + BOOL didWriteFile = NO; + + // Clean up the entire temp folder to avoid temp files that remain in case the previous session + // crashed and did not clean up. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // If there is no background network enabled, no need to write to file. This will allow default + // network session which runs on the foreground. + if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { + didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path + options:NSDataWritingAtomic + error:&writeError]; + + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession000 + message:@"Failed to write request data to file" + context:writeError]; + } + } + + if (didWriteFile) { + // Exclude this file from backing up to iTunes. There are conflicting reports that excluding + // directory from backing up does not exclude files of that directory from backing up. + [self excludeFromBackupForURL:_uploadingFileURL]; + + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; + } else { + // If we cannot write to file, just send it in the foreground. + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; + } + + if (!session || !postRequestTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + // Store completion handler because background session does not accept handler block but custom + // delegate. + _completionHandler = [handler copy]; + [postRequestTask resume]; + + return _sessionID; +} + +/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + if (_backgroundNetworkEnabled) { + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + } else { + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + } + + [self populateSessionConfig:_sessionConfig withRequest:request]; + + // Do not cache the GET request. + _sessionConfig.URLCache = nil; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; + + if (!session || !downloadTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + _completionHandler = [handler copy]; + [downloadTask resume]; + + return _sessionID; +} + +#pragma mark - NSURLSessionDataDelegate + +/// Called by the NSURLSession when the data task has received some of the expected data. +/// Once the session is completed, URLSession:task:didCompleteWithError will be called and the +/// completion handler will be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + @synchronized(self) { + NSMutableData *mutableData = [[NSMutableData alloc] init]; + if (_downloadedData) { + mutableData = _downloadedData.mutableCopy; + } + [mutableData appendData:data]; + _downloadedData = mutableData; + } +} + +#pragma mark - NSURLSessionTaskDelegate + +/// Called by the NSURLSession once the download task is completed. The file is saved in the +/// provided URL so we need to read the data and store into _downloadedData. Once the session is +/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will +/// be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:(NSURL *)url API_AVAILABLE(ios(7.0)) { + if (!url.path) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession001 + message:@"Unable to read downloaded data from empty temp path"]; + _downloadedData = nil; + return; + } + + NSError *error; + _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; + + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession002 + message:@"Cannot read the content of downloaded data" + context:error]; + _downloadedData = nil; + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session + API_AVAILABLE(ios(7.0)) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession003 + message:@"Background session finished" + context:session.configuration.identifier]; + [self callSystemCompletionHandler:session.configuration.identifier]; +} +#endif + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(7.0)) { + // Avoid any chance of recursive behavior leading to it being used repeatedly. + GULNetworkURLSessionCompletionHandler handler = _completionHandler; + _completionHandler = nil; + + if (task.response) { + // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. + NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); + + // The server responded so ignore the error created by the system. + error = nil; + } else if (!error) { + error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkInvalidResponse + userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; + } + + [self callCompletionHandler:handler + withResponse:(NSHTTPURLResponse *)task.response + data:_downloadedData + error:error]; + + // Remove the temp file to avoid trashing devices with lots of temp files. + [self removeTempItemAtURL:_uploadingFileURL]; + + // Try to clean up stale files again. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // This is called without checking the sessionID here since non-background sessions + // won't have an ID. + [session finishTasksAndInvalidate]; + + // Explicitly remove the session so it won't be reused. The weak map table should + // remove the session on deallocation, but dealloc may not happen immediately after + // calling `finishTasksAndInvalidate`. + NSString *sessionID = session.configuration.identifier; + [[self class] setSessionInFetcherMap:nil forSessionID:sessionID]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential))completionHandler + API_AVAILABLE(ios(7.0)) { + // The handling is modeled after GTMSessionFetcher. + if ([challenge.protectionSpace.authenticationMethod + isEqualToString:NSURLAuthenticationMethodServerTrust]) { + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession004 + message:@"Received empty server trust for host. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + if (!credential) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession005 + message:@"Unable to verify server identity. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession006 + message:@"Received SSL challenge for host. Host" + context:_request.URL]; + + void (^callback)(BOOL) = ^(BOOL allow) { + if (allow) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + [self->_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession007 + message:@"Cancelling authentication challenge for host. Host" + context:self->_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_async(evaluateBackgroundQueue, ^{ + SecTrustResultType trustEval = kSecTrustResultInvalid; + BOOL shouldAllow; + OSStatus trustError; + + @synchronized([GULNetworkURLSession class]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + trustError = SecTrustEvaluate(serverTrust, &trustEval); +#pragma clang dianostic pop + } + + if (trustError != errSecSuccess) { + [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession008 + message:@"Cannot evaluate server trust. Error, host" + contexts:@[ @(trustError), self->_request.URL ]]; + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + shouldAllow = + (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); + } + + // Call the call back with the permission. + callback(shouldAllow); + + CFRelease(serverTrust); + }); + return; + } + + // Default handling for other Auth Challenges. + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + +#pragma mark - Internal Methods + +/// Stores system completion handler with session ID as key. +- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler + forSession:(NSString *)identifier { + if (!handler) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession009 + message:@"Cannot store nil system completion handler in network"]; + return; + } + + if (!identifier.length) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession010 + message:@"Cannot store system completion handler with empty network " + "session identifier"]; + return; + } + + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + if (systemCompletionHandlers[identifier]) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession011 + message:@"Got multiple system handlers for a single session ID" + context:identifier]; + } + + systemCompletionHandlers[identifier] = handler; +} + +/// Calls the system provided completion handler with the session ID stored in the dictionary. +/// The handler will be removed from the dictionary after being called. +- (void)callSystemCompletionHandler:(NSString *)identifier { + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; + + if (handler) { + [systemCompletionHandlers removeObjectForKey:identifier]; + + dispatch_async(dispatch_get_main_queue(), ^{ + handler(); + }); + } +} + +/// Sets or updates the session ID of this session. +- (void)setSessionID:(NSString *)sessionID { + _sessionID = [sessionID copy]; +} + +/// Creates a background session configuration with the session ID using the supported method. +- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID + API_AVAILABLE(ios(7.0)) { +#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ + TARGET_OS_TV || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) + + // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; + +#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) + + // Do a runtime check to avoid a deprecation warning about using + // +backgroundSessionConfiguration: on iOS 8. + if ([NSURLSessionConfiguration + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + // Running on iOS 8+/OS X 10.10+. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; +#pragma clang diagnostic pop + } else { + // Running on iOS 7/OS X 10.9. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; + } + +#else + // Building with an SDK earlier than iOS 8/OS X 10.10. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; +#endif +} + +- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { + if (!folderURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + NSArray *properties = @[ NSURLCreationDateKey ]; + NSArray *directoryContent = + [fileManager contentsOfDirectoryAtURL:folderURL + includingPropertiesForKeys:properties + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants + error:&error]; + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession012 + message:@"Cannot get files from the temporary network folder. Error" + context:error]; + return; + } + + if (!directoryContent.count) { + return; + } + + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + for (NSURL *tempFile in directoryContent) { + NSDate *creationDate; + BOOL getCreationDate = [tempFile getResourceValue:&creationDate + forKey:NSURLCreationDateKey + error:NULL]; + if (!getCreationDate) { + continue; + } + NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; + if (fabs(now - creationTimeInterval) > staleTime) { + [self removeTempItemAtURL:tempFile]; + } + } +} + +/// Removes the temporary file written to disk for sending the request. It has to be cleaned up +/// after the session is done. +- (void)removeTempItemAtURL:(NSURL *)fileURL { + if (!fileURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession013 + message:@"Failed to remove temporary uploading data file. Error" + context:error.localizedDescription]; + } +} + +/// Gets the fetcher with the session ID. ++ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID:sessionIdentifier]; + if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; + [session setSessionID:sessionIdentifier]; + [self setSessionInFetcherMap:session forSessionID:sessionIdentifier]; + } + return session; +} + +/// Returns a map of the fetcher by session ID. Creates a map if it is not created. +/// When reading and writing from/to the session map, don't use this method directly. +/// To avoid thread safety issues, use one of the helper methods at the bottom of the +/// file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID: ++ (NSMapTable *)sessionIDToFetcherMap { + static NSMapTable *sessionIDToFetcherMap; + + static dispatch_once_t sessionMapOnceToken; + dispatch_once(&sessionMapOnceToken, ^{ + sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return sessionIDToFetcherMap; +} + ++ (NSLock *)sessionIDToFetcherMapReadWriteLock { + static NSLock *lock; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + return lock; +} + +/// Returns a map of system provided completion handler by session ID. Creates a map if it is not +/// created. ++ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { + static GULMutableDictionary *systemCompletionHandlers; + + static dispatch_once_t systemCompletionHandlerOnceToken; + dispatch_once(&systemCompletionHandlerOnceToken, ^{ + systemCompletionHandlers = [[GULMutableDictionary alloc] init]; + }); + return systemCompletionHandlers; +} + +- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { + NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; + return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; +} + +/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns +/// YES. If there is anything wrong, returns NO. +- (BOOL)ensureTemporaryDirectoryExists { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + // Create a temporary directory if it does not exist or was deleted. + if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + return YES; + } + + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession014 + message:@"Error while trying to access Network temp folder. Error" + context:error]; + } + + NSError *writeError = nil; + + [fileManager createDirectoryAtURL:_networkDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&writeError]; + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession015 + message:@"Cannot create temporary directory. Error" + context:writeError]; + return NO; + } + + // Set the iCloud exclusion attribute on the Documents URL. + [self excludeFromBackupForURL:_networkDirectoryURL]; + + return YES; +} + +- (void)excludeFromBackupForURL:(NSURL *)url { + if (!url.path) { + return; + } + + // Set the iCloud exclusion attribute on the Documents URL. + NSError *preventBackupError = nil; + [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; + if (preventBackupError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession016 + message:@"Cannot exclude temporary folder from iTunes backup"]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler API_AVAILABLE(ios(7.0)) { + NSArray *nonAllowedRedirectionCodes = @[ + @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), + @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) + ]; + + // Allow those not in the non allowed list to be followed. + if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { + completionHandler(request); + return; + } + + // Do not allow redirection if the response code is in the non-allowed list. + NSURLRequest *newRequest = request; + + if (response) { + newRequest = nil; + } + + completionHandler(newRequest); +} + +#pragma mark - Helper Methods + ++ (void)setSessionInFetcherMap:(GULNetworkURLSession *)session forSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *existingSession = + [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + if (existingSession) { + if (session) { + NSString *message = [NSString stringWithFormat:@"Discarding session: %@", existingSession]; + [existingSession->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelInfo + messageCode:kGULNetworkMessageCodeURLSession019 + message:message]; + } + [existingSession->_URLSession finishTasksAndInvalidate]; + } + if (session) { + [[[self class] sessionIDToFetcherMap] setObject:session forKey:sessionID]; + } else { + [[[self class] sessionIDToFetcherMap] removeObjectForKey:sessionID]; + } + [[self sessionIDToFetcherMapReadWriteLock] unlock]; +} + ++ (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *session = [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + [[self sessionIDToFetcherMapReadWriteLock] unlock]; + return session; +} + +- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler + withResponse:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession017 + message:@"Encounter network error. Code, error" + contexts:@[ @(error.code), error ]]; + } + + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(response, data, self->_sessionID, error); + }); + } +} + +// Always use the request parameters even if the default session configuration is more restrictive. +- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig + withRequest:(NSURLRequest *)request API_AVAILABLE(ios(7.0)) { + sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; + sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; + sessionConfig.timeoutIntervalForResource = request.timeoutInterval; + sessionConfig.requestCachePolicy = request.cachePolicy; +} + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h new file mode 100644 index 0000000..a8cc45b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// A mutable dictionary that provides atomic accessor and mutators. +@interface GULMutableDictionary : NSObject + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKey:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)object forKey:(id)key; + +/// Removes the object given its session ID from the dictionary. +- (void)removeObjectForKey:(id)key; + +/// Removes all objects. +- (void)removeAllObjects; + +/// Returns the number of current objects in the dictionary. +- (NSUInteger)count; + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKeyedSubscript:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key; + +/// Returns the immutable dictionary. +- (NSDictionary *)dictionary; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h new file mode 100644 index 0000000..0e75ae5 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkConstants.h" +#import "GULNetworkLoggerProtocol.h" +#import "GULNetworkURLSession.h" + +/// Delegate protocol for GULNetwork events. +@protocol GULNetworkReachabilityDelegate + +/// Tells the delegate to handle events when the network reachability changes to connected or not +/// connected. +- (void)reachabilityDidChange; + +@end + +/// The Network component that provides network status and handles network requests and responses. +/// This is not thread safe. +/// +/// NOTE: +/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the +/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: +@interface GULNetwork : NSObject + +/// Indicates if network connectivity is available. +@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; + +/// Indicates if there are any uploads in progress. +@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; + +/// An optional delegate that can be used in the event when network reachability changes. +@property(nonatomic, weak) id reachabilityDelegate; + +/// An optional delegate that can be used to log messages, warnings or errors that occur in the +/// network operations. +@property(nonatomic, weak) id loggerDelegate; + +/// Indicates whether the logger should display debug messages. +@property(nonatomic, assign) BOOL isDebugModeEnabled; + +/// The time interval in seconds for the network request to timeout. +@property(nonatomic, assign) NSTimeInterval timeoutInterval; + +/// Initializes with the default reachability host. +- (instancetype)init; + +/// Initializes with a custom reachability host. +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; + +/// Handles events when background session with the given ID has finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Compresses and sends a POST request with the provided data to the URL. The session will be +/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default +/// session. Returns a session ID or nil if an error occurs. +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +/// Sends a GET request with the provided data to the URL. The session will be background session +/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a +/// session ID or nil if an error occurs. +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h new file mode 100644 index 0000000..44d440b --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Error codes in Firebase Network error domain. +/// Note: these error codes should never change. It would make it harder to decode the errors if +/// we inadvertently altered any of these codes in a future SDK version. +typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { + /// Unknown error. + GULNetworkErrorCodeUnknown = 0, + /// Error occurs when the request URL is invalid. + GULErrorCodeNetworkInvalidURL = 1, + /// Error occurs when request cannot be constructed. + GULErrorCodeNetworkRequestCreation = 2, + /// Error occurs when payload cannot be compressed. + GULErrorCodeNetworkPayloadCompression = 3, + /// Error occurs when session task cannot be created. + GULErrorCodeNetworkSessionTaskCreation = 4, + /// Error occurs when there is no response. + GULErrorCodeNetworkInvalidResponse = 5 +}; + +#pragma mark - Network constants + +/// The prefix of the ID of the background session. +extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; + +/// The sub directory to store the files of data that is being uploaded in the background. +extern NSString *const kGULNetworkApplicationSupportSubdirectory; + +/// Name of the temporary directory that stores files for background uploading. +extern NSString *const kGULNetworkTempDirectoryName; + +/// The period when the temporary uploading file can stay. +extern const NSTimeInterval kGULNetworkTempFolderExpireTime; + +/// The default network request timeout interval. +extern const NSTimeInterval kGULNetworkTimeOutInterval; + +/// The host to check the reachability of the network. +extern NSString *const kGULNetworkReachabilityHost; + +/// The key to get the error context of the UserInfo. +extern NSString *const kGULNetworkErrorContext; + +#pragma mark - Network Status Code + +extern const int kGULNetworkHTTPStatusOK; +extern const int kGULNetworkHTTPStatusNoContent; +extern const int kGULNetworkHTTPStatusCodeMultipleChoices; +extern const int kGULNetworkHTTPStatusCodeMovedPermanently; +extern const int kGULNetworkHTTPStatusCodeFound; +extern const int kGULNetworkHTTPStatusCodeNotModified; +extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; +extern const int kGULNetworkHTTPStatusCodeNotFound; +extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; +extern const int kGULNetworkHTTPStatusCodeUnavailable; + +#pragma mark - Error Domain + +extern NSString *const kGULNetworkErrorDomain; + +/// The logger service for GULNetwork. +extern GULLoggerService kGULLoggerNetwork; diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h new file mode 100644 index 0000000..f1be590 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GULNetworkMessageCode.h" + +/// The log levels used by GULNetworkLogger. +typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { + kGULNetworkLogLevelError = GULLoggerLevelError, + kGULNetworkLogLevelWarning = GULLoggerLevelWarning, + kGULNetworkLogLevelInfo = GULLoggerLevelInfo, + kGULNetworkLogLevelDebug = GULLoggerLevelDebug, +}; + +@protocol GULNetworkLoggerDelegate + +@required +/// Tells the delegate to log a message with an array of contexts and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts; + +/// Tells the delegate to log a message with a context and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context; + +/// Tells the delegate to log a message with the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h new file mode 100644 index 0000000..507bc5a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { + // GULNetwork.m + kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 + kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 + kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 + kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 + // GULNetworkURLSession.m + kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 + kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 + kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 + kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 + kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 + kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 + kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 + kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 + kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 + kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 + kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 + kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 + kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 + kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 + kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 + kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 + kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 + kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 + kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 + kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019 +}; diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h new file mode 100644 index 0000000..3f9f7f9 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkLoggerProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSError *_Nullable error); +typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSString *sessionID, + NSError *_Nullable error); +typedef void (^GULNetworkSystemCompletionHandler)(void); + +/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. +@interface GULNetworkURLSession : NSObject + +/// Indicates whether the background network is enabled. Default value is NO. +@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; + +/// The logger delegate to log message, errors or warnings that occur during the network operations. +@property(nonatomic, weak, nullable) id loggerDelegate; + +/// Calls the system provided completion handler after the background session is finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Initializes with logger delegate. +- (instancetype)initWithNetworkLoggerDelegate: + (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Sends an asynchronous POST request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session/connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +/// Sends an asynchronous GET request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +NS_ASSUME_NONNULL_END +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h new file mode 100644 index 0000000..8aabc8a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, + const char *host); + +typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context); +typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); +typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); + +typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); + +struct GULReachabilityApi { + GULReachabilityCreateWithNameFn createWithNameFn; + GULReachabilitySetCallbackFn setCallbackFn; + GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; + GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; + GULReachabilityReleaseFn releaseFn; +}; +#endif +@interface GULReachabilityChecker (Internal) + +- (const struct GULReachabilityApi *)reachabilityApi; +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m new file mode 100644 index 0000000..a334c1a --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -0,0 +1,263 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h" + +#import +#import + +static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +static const struct GULReachabilityApi kGULDefaultReachabilityApi = { + SCNetworkReachabilityCreateWithName, + SCNetworkReachabilitySetCallback, + SCNetworkReachabilityScheduleWithRunLoop, + SCNetworkReachabilityUnscheduleFromRunLoop, + CFRelease, +}; + +static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; +static NSString *const kGULReachabilityConnectedStatus = @"Connected"; +static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; +#endif +@interface GULReachabilityChecker () + +@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; +@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; +@property(nonatomic, copy) NSString *host; +#if !TARGET_OS_WATCH +@property(nonatomic, assign) SCNetworkReachabilityRef reachability; +#endif + +@end + +@implementation GULReachabilityChecker + +@synthesize reachabilityApi = reachabilityApi_; +#if !TARGET_OS_WATCH +@synthesize reachability = reachability_; +#endif + +- (const struct GULReachabilityApi *)reachabilityApi { + return reachabilityApi_; +} + +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { +#if !TARGET_OS_WATCH + if (reachability_) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], + @"Cannot change reachability API while reachability is running. " + @"Call stop first."); + return; + } + reachabilityApi_ = reachabilityApi; +#endif +} + +@synthesize reachabilityStatus = reachabilityStatus_; +@synthesize host = host_; +@synthesize reachabilityDelegate = reachabilityDelegate_; + +- (BOOL)isActive { +#if !TARGET_OS_WATCH + return reachability_ != nil; +#else + return NO; +#endif +} + +- (void)setReachabilityDelegate:(id)reachabilityDelegate { + if (reachabilityDelegate && + (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], + @"Reachability delegate doesn't conform to Reachability protocol."); + return; + } + reachabilityDelegate_ = reachabilityDelegate; +} + +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host { + self = [super init]; + + if (!host || !host.length) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], + @"Invalid host specified"); + return nil; + } + if (self) { +#if !TARGET_OS_WATCH + [self setReachabilityDelegate:reachabilityDelegate]; + reachabilityApi_ = &kGULDefaultReachabilityApi; + reachabilityStatus_ = kGULReachabilityUnknown; + host_ = [host copy]; + reachability_ = nil; +#endif + } + return self; +} + +- (void)dealloc { + reachabilityDelegate_ = nil; + [self stop]; +} + +- (BOOL)start { +#if TARGET_OS_WATCH + return NO; +#else + + if (!reachability_) { + reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); + if (!reachability_) { + return NO; + } + SCNetworkReachabilityContext context = { + 0, /* version */ + (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ + NULL, /* retain */ + NULL, /* release */ + NULL /* copyDescription */ + }; + if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || + !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes)) { + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], + @"Failed to start reachability handle"); + return NO; + } + } + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], + @"Monitoring the network status"); + return YES; +#endif +} + +- (void)stop { +#if !TARGET_OS_WATCH + if (reachability_) { + reachabilityStatus_ = kGULReachabilityUnknown; + reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes); + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + } +#endif +} + +#if !TARGET_OS_WATCH +- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = kGULReachabilityNotReachable; + // If the Reachable flag is not set, we definitely don't have connectivity. + if (flags & kSCNetworkReachabilityFlagsReachable) { + // Reachable flag is set. Check further flags. + if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { +// Connection required flag is not set, so we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | + kSCNetworkReachabilityFlagsConnectionOnTraffic)) && + !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { +// If the connection on demand or connection on traffic flag is set, and user intervention +// is not required, we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } + } + return status; +} + +- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = [self statusForFlags:flags]; + if (reachabilityStatus_ != status) { + NSString *reachabilityStatusString; + if (status == kGULReachabilityUnknown) { + reachabilityStatusString = kGULReachabilityUnknownStatus; + } else { + reachabilityStatusString = (status == kGULReachabilityNotReachable) + ? kGULReachabilityDisconnectedStatus + : kGULReachabilityConnectedStatus; + } + + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], + @"Network status has changed. Code:%@, status:%@", @(status), + reachabilityStatusString); + reachabilityStatus_ = status; + [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; + } +} + +#endif +@end + +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; + [checker reachabilityFlagsChanged:flags]; +} +#endif + +// This function used to be at the top of the file, but it was moved here +// as a workaround for a suspected compiler bug. When compiled in Release mode +// and run on an iOS device with WiFi disabled, the reachability code crashed +// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. +// After unsuccessfully trying to diagnose the cause of the crash, it was +// discovered that moving this function to the end of the file magically fixed +// the crash. If you are going to edit this file, exercise caution and make sure +// to test thoroughly with an iOS device under various network conditions. +const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { + switch (status) { + case kGULReachabilityUnknown: + return @"Reachability Unknown"; + + case kGULReachabilityNotReachable: + return @"Not reachable"; + + case kGULReachabilityViaWifi: + return @"Reachable via Wifi"; + + case kGULReachabilityViaCellular: + return @"Reachable via Cellular Data"; + + default: + return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; + } +} diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h new file mode 100644 index 0000000..0c70c05 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +#import +#endif + +/// Reachability Status +typedef enum { + kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. + kGULReachabilityNotReachable, ///< Host is not reachable. + kGULReachabilityViaWifi, ///< Host is reachable via Wifi. + kGULReachabilityViaCellular, ///< Host is reachable via cellular. +} GULReachabilityStatus; + +const NSString *GULReachabilityStatusString(GULReachabilityStatus status); + +@class GULReachabilityChecker; + +/// Google Analytics iOS Reachability Checker. +@protocol GULReachabilityDelegate +@required +/// Called when network status has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status; +@end + +/// Google Analytics iOS Network Status Checker. +@interface GULReachabilityChecker : NSObject + +/// The last known reachability status, or GULReachabilityStatusUnknown if the +/// checker is not active. +@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; +/// The host to which reachability status is to be checked. +@property(nonatomic, copy, readonly) NSString *host; +/// The delegate to be notified of reachability status changes. +@property(nonatomic, weak) id reachabilityDelegate; +/// `YES` if the reachability checker is active, `NO` otherwise. +@property(nonatomic, readonly) BOOL isActive; + +/// Initialize the reachability checker. Note that you must call start to begin checking for and +/// receiving notifications about network status changes. +/// +/// @param reachabilityDelegate The delegate to be notified when reachability status to host +/// changes. +/// +/// @param host The name of the host. +/// +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host; + +- (instancetype)init NS_UNAVAILABLE; + +/// Start checking for reachability to the specified host. This has no effect if the status +/// checker is already checking for connectivity. +/// +/// @return `YES` if initiating status checking was successful or the status checking has already +/// been initiated, `NO` otherwise. +- (BOOL)start; + +/// Stop checking for reachability to the specified host. This has no effect if the status +/// checker is not checking for connectivity. +- (void)stop; + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h new file mode 100644 index 0000000..373e0af --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) { + // GULReachabilityChecker.m + kGULReachabilityMessageCode000 = 902000, // I-NET902000 + kGULReachabilityMessageCode001 = 902001, // I-NET902001 + kGULReachabilityMessageCode002 = 902002, // I-NET902002 + kGULReachabilityMessageCode003 = 902003, // I-NET902003 + kGULReachabilityMessageCode004 = 902004, // I-NET902004 + kGULReachabilityMessageCode005 = 902005, // I-NET902005 + kGULReachabilityMessageCode006 = 902006, // I-NET902006 +}; diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m new file mode 100644 index 0000000..b80e2af --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m @@ -0,0 +1,438 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TargetConditionals.h" + +#import +#import +#import +#import +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h" + +#import + +#if UISCENE_SUPPORTED +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (*GULOpenURLContextsIMP)(id, SEL, UIScene *, NSSet *); + +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (^GULSceneDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; +#endif // UISCENE_SUPPORTED + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/SceneDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseSceneDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the Scene Delegate. */ +static NSString *const kGULSceneDelegatePrefix = @"GUL_"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULSceneZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULSceneZeroingWeakContainer +@end + +@implementation GULSceneDelegateSwizzler + +#pragma mark - Public methods + ++ (BOOL)isSceneDelegateProxyEnabled { + return [GULAppDelegateSwizzler isAppDelegateProxyEnabled]; +} + ++ (void)proxyOriginalSceneDelegate { +#if UISCENE_SUPPORTED + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (@available(iOS 13.0, tvOS 13.0, *)) { + if (![GULSceneDelegateSwizzler isSceneDelegateProxyEnabled]) { + return; + } + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleSceneWillConnectToNotification:) + name:UISceneWillConnectNotification + object:nil]; + } + }); +#endif // UISCENE_SUPPORTED +} + +#if UISCENE_SUPPORTED ++ (GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor:(id)interceptor { + NSAssert(interceptor, @"SceneDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(UISceneDelegate)], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling000], + @"SceneDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(UISceneDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling001], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = + [NSString stringWithFormat:@"%@%p", kGULSceneDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling002], + @"SceneDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULSceneZeroingWeakContainer *weakObject = [[GULSceneZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULSceneDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"SceneDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling003], + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULSceneZeroingWeakContainer *weakContainer = + [GULSceneDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling004], + @"SceneDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULSceneDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULSceneDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULSceneDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULSceneDelegateInterceptorCallback)callback + API_AVAILABLE(ios(13.0)) { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULSceneDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULSceneZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling010], + @"SceneDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + ++ (void)handleSceneWillConnectToNotification:(NSNotification *)notification { + if (@available(iOS 13.0, tvOS 13.0, *)) { + if ([notification.object isKindOfClass:[UIScene class]]) { + UIScene *scene = (UIScene *)notification.object; + [GULSceneDelegateSwizzler proxySceneDelegateIfNeeded:scene]; + } + } +} + +#pragma mark - [Donor Methods] UISceneDelegate URL handler + +- (void)scene:(UIScene *)scene + openURLContexts:(NSSet *)URLContexts API_AVAILABLE(ios(13.0), tvos(13.0)) { + if (@available(iOS 13.0, tvOS 13.0, *)) { + SEL methodSelector = @selector(scene:openURLContexts:); + // Call the real implementation if the real Scene Delegate has any. + NSValue *openURLContextsIMPPointer = + [GULSceneDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULOpenURLContextsIMP openURLContextsIMP = [openURLContextsIMPPointer pointerValue]; + + [GULSceneDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + if ([interceptor + conformsToProtocol:@protocol(UISceneDelegate)]) { + id sceneInterceptor = + (id)interceptor; + [sceneInterceptor scene:scene openURLContexts:URLContexts]; + } + }]; + + if (openURLContextsIMP) { + openURLContextsIMP(self, methodSelector, scene, URLContexts); + } + } +} + ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene { + Class realClass = [scene.delegate class]; + NSString *className = NSStringFromClass(realClass); + + // Skip proxying if failed to get the delegate class name for some reason (e.g. `delegate == nil`) + // or the class has a prefix of kGULAppDelegatePrefix, which means it has been proxied before. + if (className == nil || [className hasPrefix:kGULSceneDelegatePrefix]) { + return; + } + + NSString *classNameWithPrefix = [kGULSceneDelegatePrefix stringByAppendingString:className]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: %@", + className, newClassName); + return; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class sceneDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (sceneDelegateSubClass == Nil) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: Nil", + className); + return; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For scene:openURLContexts: + SEL openURLContextsSEL = @selector(scene:openURLContexts:); + [self proxyDestinationSelector:openURLContextsSEL + implementationsFromSourceSelector:openURLContextsSEL + fromClass:[GULSceneDelegateSwizzler class] + toClass:sceneDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(scene.delegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(scene.delegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(sceneDelegateSubClass)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create subclass of Scene Delegate, because the created subclass is not the " + @"same size. %@", + className); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return; + } + + // Make the newly created class to be the subclass of the real Scene Delegate class. + objc_registerClassPair(sceneDelegateSubClass); + if (object_setClass(scene.delegate, sceneDelegateSubClass)) { + GULLogDebug( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Successfully created Scene Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULSceneDelegateSwizzler correctSceneDelegateProxyKey]); + } +} + ++ (NSString *)correctSceneDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseSceneDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey; +} + +#endif // UISCENE_SUPPORTED + +@end diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h new file mode 100644 index 0000000..a2439eb --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GULSceneDelegateSwizzler () + +#if UISCENE_SUPPORTED + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param scene The scene whose delegate needs to be isa swizzled. This should conform to the + * scene delegate protocol. + */ ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)); + +#endif // UISCENE_SUPPORTED + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h new file mode 100644 index 0000000..420b3e7 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !TARGET_OS_OSX +#import +#endif // !TARGET_OS_OSX + +#if ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000)) +#define UISCENE_SUPPORTED 1 +#endif + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULSceneDelegateInterceptorID; + +/** This class contains methods that isa swizzle the scene delegate. */ +@interface GULSceneDelegateSwizzler : NSProxy + +#if UISCENE_SUPPORTED + +/** Registers a scene delegate interceptor whose methods will be invoked as they're invoked on the + * original scene delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULSceneDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor: + (id)interceptor API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID + API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +#endif // UISCENE_SUPPORTED + +/** This method ensures that the original scene delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the scene delegate once). + * + * The method has no effect for extensions. + */ ++ (void)proxyOriginalSceneDelegate; + +/** Indicates whether scene delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if SceneDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isSceneDelegateProxyEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m new file mode 100644 index 0000000..47ac35d --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -0,0 +1,213 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULUserDefaults.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSTimeInterval const kGULSynchronizeInterval = 1.0; + +static NSString *const kGULLogFormat = @"I-GUL%06ld"; + +static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]"; + +typedef NS_ENUM(NSInteger, GULUDMessageCode) { + GULUDMessageCodeInvalidKeyGet = 1, + GULUDMessageCodeInvalidKeySet = 2, + GULUDMessageCodeInvalidObjectSet = 3, + GULUDMessageCodeSynchronizeFailed = 4, +}; + +@interface GULUserDefaults () + +/// Equivalent to the suite name for NSUserDefaults. +@property(readonly) CFStringRef appNameRef; + +@property(atomic) BOOL isPreferenceFileExcluded; + +@end + +@implementation GULUserDefaults { + // The application name is the same with the suite name of the NSUserDefaults, and it is used for + // preferences. + CFStringRef _appNameRef; +} + ++ (GULUserDefaults *)standardUserDefaults { + static GULUserDefaults *standardUserDefaults; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[GULUserDefaults alloc] init]; + }); + return standardUserDefaults; +} + +- (instancetype)init { + return [self initWithSuiteName:nil]; +} + +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName { + self = [super init]; + + NSString *name = [suiteName copy]; + + if (self) { + // `kCFPreferencesCurrentApplication` maps to the same defaults database as + // `[NSUserDefaults standardUserDefaults]`. + _appNameRef = + name.length ? (__bridge_retained CFStringRef)name : kCFPreferencesCurrentApplication; + } + + return self; +} + +- (void)dealloc { + // If we're using a custom `_appNameRef` it needs to be released. If it's a constant, it shouldn't + // need to be released since we don't own it. + if (CFStringCompare(_appNameRef, kCFPreferencesCurrentApplication, 0) != kCFCompareEqualTo) { + CFRelease(_appNameRef); + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; +} + +- (nullable id)objectForKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(@"", NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet], + @"Cannot get object for invalid user default key."); + return nil; + } + return (__bridge_transfer id)CFPreferencesCopyAppValue((__bridge CFStringRef)key, _appNameRef); +} + +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet], + @"Cannot set object for invalid user default key."); + return; + } + if (!value) { + CFPreferencesSetAppValue((__bridge CFStringRef)key, NULL, _appNameRef); + [self scheduleSynchronize]; + return; + } + BOOL isAcceptableValue = + [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || + [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || + [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]]; + if (!isAcceptableValue) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet], + @"Cannot set invalid object to user defaults. Must be a string, number, array, " + @"dictionary, date, or data. Value: %@", + value); + return; + } + + CFPreferencesSetAppValue((__bridge CFStringRef)key, (__bridge CFStringRef)value, _appNameRef); + [self scheduleSynchronize]; +} + +- (void)removeObjectForKey:(NSString *)key { + [self setObject:nil forKey:key]; +} + +#pragma mark - Getters + +- (NSInteger)integerForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.integerValue; +} + +- (float)floatForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.floatValue; +} + +- (double)doubleForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.doubleValue; +} + +- (BOOL)boolForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.boolValue; +} + +- (nullable NSString *)stringForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +#pragma mark - Setters + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName { + [self setObject:@(integer) forKey:defaultName]; +} + +- (void)setFloat:(float)value forKey:(NSString *)defaultName { + [self setObject:@(value) forKey:defaultName]; +} + +- (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName { + [self setObject:@(doubleNumber) forKey:defaultName]; +} + +- (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName { + [self setObject:@(boolValue) forKey:defaultName]; +} + +#pragma mark - Save data + +- (void)synchronize { + if (!CFPreferencesAppSynchronize(_appNameRef)) { + GULLogError(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeSynchronizeFailed], + @"Cannot synchronize user defaults to disk"); + } +} + +#pragma mark - Private methods + +- (void)scheduleSynchronize { + // Synchronize data using a timer so that multiple set... calls can be coalesced under one + // synchronize. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; + // This method may be called on multiple queues (due to set... methods can be called on any queue) + // synchronize can be scheduled on different queues, so make sure that it does not crash. If this + // instance goes away, self will be released also, no one will retain it and the schedule won't be + // called. + [self performSelector:@selector(synchronize) withObject:nil afterDelay:kGULSynchronizeInterval]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 0000000..0d04781 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/GoogleUtilities/README.md b/PediatricPancreas/Pods/GoogleUtilities/README.md new file mode 100644 index 0000000..5097a89 --- /dev/null +++ b/PediatricPancreas/Pods/GoogleUtilities/README.md @@ -0,0 +1,254 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas/Pods/Headers/Private/Firebase/Firebase.h b/PediatricPancreas/Pods/Headers/Private/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Private/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h b/PediatricPancreas/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h new file mode 120000 index 0000000..0253e25 --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h @@ -0,0 +1 @@ +../../../FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h new file mode 120000 index 0000000..ce646ec --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h new file mode 120000 index 0000000..07d83d7 --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Public/Firebase/Firebase.h b/PediatricPancreas/Pods/Headers/Public/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Public/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h b/PediatricPancreas/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h new file mode 120000 index 0000000..0253e25 --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h @@ -0,0 +1 @@ +../../../FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h new file mode 120000 index 0000000..ce646ec --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h new file mode 120000 index 0000000..07d83d7 --- /dev/null +++ b/PediatricPancreas/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/PediatricPancreas/Pods/Manifest.lock b/PediatricPancreas/Pods/Manifest.lock new file mode 100644 index 0000000..6858f88 --- /dev/null +++ b/PediatricPancreas/Pods/Manifest.lock @@ -0,0 +1,124 @@ +PODS: + - Firebase/Core (6.17.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.2.2) + - Firebase/CoreOnly (6.17.0): + - FirebaseCore (= 6.6.2) + - Firebase/Database (6.17.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.1.4) + - FirebaseAnalytics (6.2.2): + - FirebaseCore (~> 6.6) + - FirebaseInstanceID (~> 4.3) + - GoogleAppMeasurement (= 6.2.2) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAuthInterop (1.0.0) + - FirebaseCore (6.6.2): + - FirebaseCoreDiagnostics (~> 1.2) + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.2.0): + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleDataTransportCCTSupport (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.2.0) + - FirebaseDatabase (6.1.4): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.1.0): + - FirebaseCore (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.5) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.3.1): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - GoogleAppMeasurement (6.2.2): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (4.0.0) + - GoogleDataTransportCCTSupport (1.4.0): + - GoogleDataTransport (~> 4.0) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.5.1) + - GoogleUtilities/Logger (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.5.1): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.5.1)" + - GoogleUtilities/Reachability (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.5.1): + - GoogleUtilities/Logger + - leveldb-library (1.22) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - PromisesObjC (1.2.8) + +DEPENDENCIES: + - Firebase/Core + - Firebase/Database + +SPEC REPOS: + trunk: + - Firebase + - FirebaseAnalytics + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop + - FirebaseDatabase + - FirebaseInstallations + - FirebaseInstanceID + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + Firebase: 2672e5636b42f977177716317e68346ae5e9de25 + FirebaseAnalytics: cf95d3aab897612783020fbd98401d5366f135ee + FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc + FirebaseCore: a1dd9dd6355a8356dd30a8f076839e242285a81c + FirebaseCoreDiagnostics: 5e78803ab276bc5b50340e3c539c06c3de35c649 + FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 + FirebaseDatabase: 0144e0706a4761f1b0e8679572eba8095ddb59be + FirebaseInstallations: 575cd32f2aec0feeb0e44f5d0110a09e5e60b47b + FirebaseInstanceID: 031d7d0c8e7b5c030bbeb4d2a690550375e83fec + GoogleAppMeasurement: d0560d915abf15e692e8538ba1d58442217b6aff + GoogleDataTransport: 47fe3b8e1673e5187dfd615656a3c5034f150d69 + GoogleDataTransportCCTSupport: 36f69887fd212db6d7ef4dd45ba44523717a434e + GoogleUtilities: 06eb53bb579efe7099152735900dd04bf09e7275 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 + +PODFILE CHECKSUM: c4ea62e4deb9d9bae7aab1df7399af99eb57d649 + +COCOAPODS: 1.9.0 diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/project.pbxproj b/PediatricPancreas/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..5da88b1 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,6466 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 8DD977517C248319451DB85AB81E48C6 /* Build configuration list for PBXAggregateTarget "Firebase" */; + buildPhases = ( + ); + dependencies = ( + 51BDCE72D635910F59F8BE2D085ECF27 /* PBXTargetDependency */, + C472727A0907C53BCDFF109E5F28DAAB /* PBXTargetDependency */, + 2697D23F9C78EE842EE420E263473F39 /* PBXTargetDependency */, + ); + name = Firebase; + }; + 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 456EAC6805E9895E0DAF29D274E62DC0 /* Build configuration list for PBXAggregateTarget "FirebaseCoreDiagnosticsInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseCoreDiagnosticsInterop; + }; + 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B06332DA5A203A349B875007390EFEC7 /* Build configuration list for PBXAggregateTarget "FirebaseAuthInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseAuthInterop; + }; + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */ = { + isa = PBXAggregateTarget; + buildConfigurationList = B4E31387BEF7D6F4FD8B312C9578BAE0 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */; + buildPhases = ( + ); + dependencies = ( + 1405C190ED9E1E16D2CF759D59C68D1A /* PBXTargetDependency */, + 68F495FD6399571335232AD5B7DEB78E /* PBXTargetDependency */, + ); + name = GoogleAppMeasurement; + }; + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 9CC09DAFA09AB5D8EBE5B10BB259F60F /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */; + buildPhases = ( + ); + dependencies = ( + 926485F7A1D02636A6267356E7EA2FF1 /* PBXTargetDependency */, + 5EA7EE3FB0C96B611E8BD457D7FE7BA2 /* PBXTargetDependency */, + 19635AAE0A3094A8088E910E1AD3B6CD /* PBXTargetDependency */, + 50896A4EAEB7FA22D435704BA89EE5CB /* PBXTargetDependency */, + 0C6BD3144A335F632CCF4C99D070816B /* PBXTargetDependency */, + ); + name = FirebaseAnalytics; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 001A2AE41501B7F822B899233A40BF1A /* GULAppEnvironmentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 52EEB6148AFFBEE7152B90E633612CC6 /* GULAppEnvironmentUtil.m */; }; + 0021862FD43EABE9787FA2D7FC7CD7D5 /* FListenComplete.m in Sources */ = {isa = PBXBuildFile; fileRef = 874C68D17B12C1F819AD0ADEA831EAFE /* FListenComplete.m */; }; + 00913F81181EB89B9C3FAED5C7446DE0 /* GDTCORStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = FDBEE362A1AC58BB9A15CC82604155A6 /* GDTCORStoredEvent.m */; }; + 00EDAEC0ECFF39FEC894E3A5CD68E307 /* FNamedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C9144733820350361C79FCC0FC4E76D /* FNamedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 00F48B92E55005586F5577535A35C44D /* db_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = A88033DCEC6D14ED10C3F3C8FF7981C7 /* db_impl.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 03F01BC83070ABBD518F5AA17D4DCB40 /* FLimitedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8157CF91D79E2D82F9E3A84E1F373B78 /* FLimitedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 03F771627DD26DE3A46A3A0AA9238D96 /* FCancelEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B3B9333C2F6435557A422A0630F1F5 /* FCancelEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 04D9EEB121FAFA473B84577842DE28AA /* FCompoundHash.h in Headers */ = {isa = PBXBuildFile; fileRef = B6243AA00C08AE7508A9487E0DD106A5 /* FCompoundHash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 04FCBCEA9CCA44E9E2F7122847E00864 /* FPersistenceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB189ECD5A6C97091EA2695A36F518F /* FPersistenceManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0537BB4CC2A926C9541D222B9AC3924C /* GULApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = A4166E7662CC5AAA26F1AB619EC69E13 /* GULApplication.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 06186994A01F0DCBC0552F2CF8F875A4 /* FWriteRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D3557174B66202482C8BDA5E3AC8D6C /* FWriteRecord.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 061AD4AFD8DA76779BFEAF73508E47D7 /* FTupleUserCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 451BB6FC86F30A7B6E5B472C474F44FD /* FTupleUserCallback.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0647A006023CF684A264CDD07D28FA91 /* FIRInstanceIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 3659B8E0DA938B031AD879C0B213C188 /* FIRInstanceIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 06E4D83044D85D240C9388809944C6C6 /* FBLPromise+Async.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 14DD85EA7D746AA0ABA6E66DA54FE552 /* FBLPromise+Async.h */; }; + 06F8B2D110E3D85C99D7694C88D4AACC /* FTupleStringNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3E8AF3E7C471E6553CFB71867A370455 /* FTupleStringNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 078B94AA0304E225E31E0B54C10D1931 /* FBLPromise+Reduce.m in Sources */ = {isa = PBXBuildFile; fileRef = 15C61D66067C8460216C517BBD011E18 /* FBLPromise+Reduce.m */; }; + 087C55FF14BBD7924D2604E362E05E2B /* FEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D6AD17FB8B70E3033CE0DB1763A1A7B2 /* FEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 08F09B2728494409BD2DC9C7FD33C7E7 /* FCompoundHash.m in Sources */ = {isa = PBXBuildFile; fileRef = C4E576228987A62E57731963B7FD5E31 /* FCompoundHash.m */; }; + 0A01FF0884FAF5689C189235DFDEE9F3 /* FViewProcessorResult.h in Headers */ = {isa = PBXBuildFile; fileRef = CB79FD41C8FFFB07B28E71D46260F99A /* FViewProcessorResult.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0A396C7F83D1C18BCE1E32C9B0200B96 /* FAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 39C731E683F6797282C44B7CD3D51841 /* FAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0A91224F2F6B47A058CB360227247938 /* FValueEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = E21218A3B8A841CFC4A0716AC72E30B0 /* FValueEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0B2CA41FD4EA7B966543471C816C8B31 /* GDTCORClock.m in Sources */ = {isa = PBXBuildFile; fileRef = 4333D276EEF0EDA615A614467B65F6F7 /* GDTCORClock.m */; }; + 0B6FF9ED432353167CCE5CAFEBB59A6E /* GULNetworkConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = A4556B043AB0DAFFE7F063B549ECF6AD /* GULNetworkConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0BFBD5419A81C51C524FE08FC0E3F3EE /* FMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = CA4C73E47837B0E3511A487AFC38A70B /* FMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0BFFFE564365C57BC41A964ECB45931F /* FTrackedQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = E42CD6D50EE4BFF16E3DD5C5F9977780 /* FTrackedQuery.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0C2D81BD99725431007AC6CF94264D1C /* FBLPromise+Delay.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 6F120332D2F3AADB20BE6BD46DB04B5C /* FBLPromise+Delay.h */; }; + 0C3B9F787581B3D00B36863B40419CB5 /* version_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AC6BC15BEF7347E79C01F3CC6F1AEA3 /* version_set.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0DA6A4EBE519B3DE88E0E007577BDAE8 /* FOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 695657C468C5D2CF227BD8AA9F4FF226 /* FOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E0145B2EAB107CE51DB7AC3B81888B5 /* pb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = E77DB5111675718C49A01EBA83BAF493 /* pb_common.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0E65E4EA24D5CD3372CDA747C99B7B50 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B79D7F54E520AF3904F5139432C278C /* FIRDependency.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0EB6B0D639DA75E20A759A4449BE3AFE /* GULLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 015383D9B573A7E4A25B73CA5E2E2C36 /* GULLogger.m */; }; + 0F912F50E354B79E92EAF43C711F60F1 /* bloom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 623D671CA43E7F78C56956E343D5657D /* bloom.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0FB8CFC18E7A14D4380B157FBC3A38E5 /* PromisesObjC-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 723017E29BE5FD9D38BE7477D5D6FFF4 /* PromisesObjC-dummy.m */; }; + 0FC683562FA07E8AF2EF55D8B2167960 /* FKeyIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 50204171185C6765C11FF190A8E90F7D /* FKeyIndex.m */; }; + 101FEB4979AEF5F7A706990B49E2497E /* FIRInstallationsIIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = CBD27D618C4A13D97B4E96A9741DF66A /* FIRInstallationsIIDTokenStore.m */; }; + 102A0195119AFFB4140DEE02B986A551 /* pb.h in Headers */ = {isa = PBXBuildFile; fileRef = B3288029B62F60168CD0B5922E5D3F0B /* pb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 10C1738591FDCE0FF984AAC9EEE47CD3 /* FPendingPut.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A4733A66A4533BC54CA3576C71F03DE /* FPendingPut.m */; }; + 11591143402FAF6EC0EB1BC89B59DF2B /* FIRErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EF616070C58259A27E8EEAA63F9E462 /* FIRErrors.m */; }; + 11D6258E24BA267419F96E4515902AC1 /* FTupleTSN.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A38C98F33FDE148ED5D38379F735D1 /* FTupleTSN.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 12F011A1AC64F875E04D2EFF3DC2CB42 /* FListenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 2BA1EAA89F969D9D4D52536B5BCE43FC /* FListenProvider.m */; }; + 1318A638736A3BD7872115F0EB6097E4 /* FIRInstanceIDAuthKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = D022F7FBC81242923E8D67CA2E289BA0 /* FIRInstanceIDAuthKeyChain.m */; }; + 1352B4E082BF49B40EBB0C5931EE9A92 /* FIRInstanceIDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C666511B4072152AD025B2D4C721AAC /* FIRInstanceIDKeychain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1419FEDD91A2D4BA6C8A5CCA708DD5F1 /* FirebaseCore-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F13CEF2BDCB6C7ABD864E400468E55B /* FirebaseCore-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1457F63F4F792B63938CAD3B54079E57 /* FIRVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = CBA16637DCCE5CC8B2C6EE6EF4523671 /* FIRVersion.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 14589D6DA4F621EEA8357F7B8D36F415 /* dumpfile.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6FACDBC1AFD69E2F70800AFC30CFAFE7 /* dumpfile.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 14A82A4E92B4D8451F67924EFB51B52F /* FValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = B63C250262739AA04B6D0027DDF4902F /* FValidation.m */; }; + 1553DE80C6D82A7F0E003AE2BE477206 /* db_iter.h in Headers */ = {isa = PBXBuildFile; fileRef = D9975934F005271D708CDC03FEA060AF /* db_iter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 159FAD44AAB2F5AB322049B4A6626285 /* repair.cc in Sources */ = {isa = PBXBuildFile; fileRef = B01E3EBC54F74EB224BC9FAB87F151F2 /* repair.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 167D0E24C4EB049C4651FD62969846AE /* FDataEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA5606127C7AB07769D229E6BA594FA /* FDataEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1692463D9972897A8CF0552FC3BB787B /* GDTCORLifecycle.h in Headers */ = {isa = PBXBuildFile; fileRef = C85E4E623B4A72E522D791D20293F655 /* GDTCORLifecycle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 16C02EC101DCB7C2DC5E0F60CE1829CB /* GULNetworkLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 55EB03E6D00F93919813AFF8047C700D /* GULNetworkLoggerProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 170291315218C7F7BE01AFC29CB9F16E /* FirebaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = EC43FEF1CA9773F7407B76F3B8CE500E /* FirebaseCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173ECFDD03584D1EACB89B1AFEDBBFFE /* FBLPromise+Retry.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = F10C76FEC7DE64107890BCD0E69DE428 /* FBLPromise+Retry.h */; }; + 177B7DEC27752E27FA06328B2A123A69 /* table.cc in Sources */ = {isa = PBXBuildFile; fileRef = 058600A9D546320B88F62E2A82AE2143 /* table.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 184B2AFC33A53E3110998B6DBAD6C67F /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = 3884BBAFEA06415C2E4E1D75F152F2B4 /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 18A932D04692B43A9F8BE0F8AF0C6B54 /* format.cc in Sources */ = {isa = PBXBuildFile; fileRef = EF6C6710B2B163CE881A5BAE36D20B5D /* format.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 18BD1985750D26745C9038760103F75B /* skiplist.h in Headers */ = {isa = PBXBuildFile; fileRef = FA39C6D824C47D10541A5DB3BBDE2263 /* skiplist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1933D4AF091889C3E94CE3F7D433209B /* memtable.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B69A11D9AE8DE28BEEBBDB6FD309B45 /* memtable.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 195CB37779AABA083FB30D80D4000651 /* FBLPromise+All.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 90C235774B7FEFA58692D00424C37A4B /* FBLPromise+All.h */; }; + 19EF3A4FE2897DFDDDB0B78C95A838F3 /* FBLPromise+Delay.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F120332D2F3AADB20BE6BD46DB04B5C /* FBLPromise+Delay.h */; }; + 19F765EA7211C1AB6CAA21972C191E67 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 1A01FE1CA710160C1016DD3A299FD0EA /* FIRInstanceIDTokenFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C1E706ED5710A5F8B33A3B743E963A /* FIRInstanceIDTokenFetchOperation.m */; }; + 1A2F7B017E1D536C49FE43D267EB5019 /* FKeepSyncedEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 562AEAF410E4ECCAF9B77166BA77E3A3 /* FKeepSyncedEventRegistration.m */; }; + 1A7A6C79F42DBB21F8120F3CAED13DFE /* GoogleUtilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DBFBC879C80096896F5050F43D67974 /* GoogleUtilities-dummy.m */; }; + 1BE1B577C737CD0E8EE51B11CD199F8F /* FTupleObjectNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7CC5F567A3E69A2FF89366D3265864D0 /* FTupleObjectNode.m */; }; + 1C2516CB0209BB6C75307C0FF8392883 /* FConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = FA75AD53B36E8DAD1847CE0D8C8A15A9 /* FConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1C2FBF72347EB561D0E30E50848D97FF /* FBLPromise+Race.h in Headers */ = {isa = PBXBuildFile; fileRef = 63AAC507B0C7EE188A57BC2455B04E4D /* FBLPromise+Race.h */; }; + 1C57452B6C5DCA13A84F0A6E2A8640CC /* FBLPromise+Validate.m in Sources */ = {isa = PBXBuildFile; fileRef = F777C5E65C22D85894FAC33B1AEB107D /* FBLPromise+Validate.m */; }; + 1E7F350E9A6AA211C53A28F58D22A9F7 /* FCancelEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = A30D980013D4A49BB4B9AF281EC66F68 /* FCancelEvent.m */; }; + 1E895BA1D1C67BA6B467D4FE91D5DBCB /* FImmutableSortedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E90F2517A7D54AE0A6DA5690C006A4 /* FImmutableSortedSet.m */; }; + 1EB9E61D79FD9E9A446FA26A9F1F6E0F /* FTupleBoolBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 6DD1E26CF8A05FA5B014E91EF56ED45D /* FTupleBoolBlock.m */; }; + 1EEF95AEF137498F6F6A4E21125B0DA4 /* db_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D0C04076DA35AE3B33CF8AD8BAF984A /* db_impl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1F8CA46274574BF041AD357C27838B08 /* FUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D407C321863CD7FA24AC53D85CA2966 /* FUtilities.m */; }; + 1FB8B47D82C12825FC29C374954DB686 /* FIRInstallations.m in Sources */ = {isa = PBXBuildFile; fileRef = EE347F70A1C0E9F79BF1982AA0AE5276 /* FIRInstallations.m */; }; + 1FBE9EF2264A5C7C48EB98A6E5E88BB1 /* FIRApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 02E4DD3DCDB31EC1648CA6C98780E009 /* FIRApp.m */; }; + 20245E269E9A77D9BC7ED27B259787A9 /* FIRInstanceID+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 443C8A9A533DD8E2A9D01F4F78EBE443 /* FIRInstanceID+Private.m */; }; + 20C074AF377D311FF0D86684614A5433 /* FirebaseInstanceID-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EEF250FBAA16E776552020D11B9C8A66 /* FirebaseInstanceID-dummy.m */; }; + 2196D83376D82F08143CBCAA87292D0F /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = EE1781250E9DF101BDFB90CB850C386F /* logging.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 2289E1B5D0115CBA01E425E5026FAF88 /* FIRApp.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A16BACD8F0BE6703DDD5DFA6AF4F0F /* FIRApp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 229CA40BADF357EDC88F7D08BAC54CB5 /* testutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 9509AC17857ED363396A3E274326F0BC /* testutil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 232462B42CFB86A76B2E3EF883CCBB96 /* FTupleRemovedQueriesEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = 80CE823A231F46D35C99B77FE37C2680 /* FTupleRemovedQueriesEvents.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 23819399B031293AA3D85828F7CE6FDD /* GULAppDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = A98E3F14C60B35AC913D88C97E2B5972 /* GULAppDelegateSwizzler.m */; }; + 23BCA5D9E3074CAC2793EF3705AD4B8F /* FStringUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 6270DF1BFF55ADC2D337AC78BD921C52 /* FStringUtilities.m */; }; + 23CD4E9048AE540E63359773CD360CA2 /* FCachePolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = E161DB825968B6D1274F18BC57F7781D /* FCachePolicy.m */; }; + 240D90495B7E45169CD3835E05512B21 /* FBLPromisePrivate.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = 2C628E92632EDA6D9E0BF833B6E84CEC /* FBLPromisePrivate.h */; }; + 2435103B6E32D5B5A5E612755C06DCCE /* FIRTransactionResult_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F27706885AB7D265A16236A0B089793 /* FIRTransactionResult_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 24DB26FDC5B66C423CC7980DC7E02C5E /* FBLPromise+Then.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = EE99BAF073CA1D81781B1B25C847608F /* FBLPromise+Then.h */; }; + 24E938D0969282690C6E5BE66BC8DB9A /* FValueIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 8091FFAE87FD3FA3AE8ED56E6859B4F0 /* FValueIndex.m */; }; + 256379D9DD965C592CEA8B9286B6AB53 /* filter_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA1D3CE763B4DFB39712DC2D0F9C6C96 /* filter_policy.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 2571C011C254F39E5677463DF34E0C06 /* cct.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F1F2773CA1EAE4D8A704AEEFD180CCD /* cct.nanopb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 25F1A579A6F66973599A4FEA187A71E0 /* histogram.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C22FCC38A85E7F7852BF44E2551FDC4 /* histogram.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2611134890F39153D53E85E22CC94D76 /* FArraySortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = B35084C018CB2A2FAF2A8E47B9341A94 /* FArraySortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 26116DEE25197E11B25680286A045C4C /* iterator_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 34F03D87EA8B176419ECB12B051736B1 /* iterator_wrapper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2631D9F5AF10BE4FEC1A6611198C8B27 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 282A2B1557E034CC4DDBBB528FBA6D9D /* nanopb-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 19ECFA906B835C74272E23F478123821 /* nanopb-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 28A0A9FD9BC4B00D1705BC37EF081DEE /* GDTCORReachability_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B5399854B710AA8DCDC59D42010EBE33 /* GDTCORReachability_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 28FCD20369581072CB088A4F39A0A325 /* GULOriginalIMPConvenienceMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = D3EF925BD0923A808B3AF3593EA2ABDB /* GULOriginalIMPConvenienceMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2999DE7CB85A63BA6EAE75A0D6E7E701 /* FEventRaiser.h in Headers */ = {isa = PBXBuildFile; fileRef = C8B26599A4CA608F5B170B0769926191 /* FEventRaiser.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 29C166E258DF103E2740944FF34B37A0 /* GDTCORConsoleLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 010EB3293303194FAFD89055A4E91CE3 /* GDTCORConsoleLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2A7332632039562A0CA53B0746DD5614 /* FIROptions.h in Headers */ = {isa = PBXBuildFile; fileRef = F189BAAA0B343A34C79A53561EF6E895 /* FIROptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2AE7E02AC0A6367CBE71A89850AAB78A /* GDTCCTUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B51CD46764C9CB5026CB65386897AD8 /* GDTCCTUploader.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 2B95F0E51928C723FAF9D747321D3B18 /* db.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C9AD50E9DF223C0BC44EDCA95E412DF /* db.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2C01F8F00BEB3D530924839C498CBD05 /* logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 546AA55159CBCDB057982CCAAF150602 /* logging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C3B184BED83E687B4532E6E142BB9F0 /* FTransformedEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 65CD61911DCF7CD7FCCBB65A9CEEE323 /* FTransformedEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C48C1B2EF74AD4B05566974D8F98ACB /* FTuplePathValue.m in Sources */ = {isa = PBXBuildFile; fileRef = FE6DB08072CCBBA9657F29B2A4B18F2A /* FTuplePathValue.m */; }; + 2C4E0F78ACD35425AC6724A860526F37 /* FIRLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CAABEE8F7F783A6B7FD09ACA8A04842 /* FIRLogger.m */; }; + 2C8F1F07505A5559AFEC2E38754B9029 /* GDTCORAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E76D9053038A33CDEBFAE625CC5BADE /* GDTCORAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2CA030D81C45AE701078A106F8B8DFE0 /* GDTCORReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = E48B1808AA40A73BA3D46EA4AE5B3927 /* GDTCORReachability.m */; }; + 2CB53881B52015395E5B96C1201895DF /* FIRInstanceIDCombinedHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 364EAEA6E2087584E3FAC61220152886 /* FIRInstanceIDCombinedHandler.m */; }; + 2EDCA6497C659F1F5A624586E4B7FFC8 /* FBLPromiseError.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 7DA049BCB41CCA3C4CC0998EE845FC32 /* FBLPromiseError.h */; }; + 2F1E55E897210AEDB50F9DF6979F938A /* c.cc in Sources */ = {isa = PBXBuildFile; fileRef = AD600D36912F30C50EFC184EE3D04F7E /* c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 2F60C9EB675A361CE11F3EFB4954DCDA /* GDTCORTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = AF06957A0771C86EF3C7DBAF75A4F553 /* GDTCORTransformer.m */; }; + 2F7ACB9C3474E5F8977D9685B600E363 /* FIRInstanceIDCheckinStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C4F0248287DB8D03D320A8A1FBA6BC8 /* FIRInstanceIDCheckinStore.m */; }; + 301955A8C9DDB9D6E910AAA2068F674F /* FViewProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C40715AAB90D82EBE8B88B6DEC64F64 /* FViewProcessor.m */; }; + 3039C2C0C98A44B60136E507C77E915F /* FIRInstallationsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = CB76A092BCA0D0C1E846F7D5856AA5EF /* FIRInstallationsStore.m */; }; + 303E8921DA22E167791ADF29196C2840 /* GULReachabilityChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = BB5C170B61C645EBD115F14EB5249AF0 /* GULReachabilityChecker.m */; }; + 30E6C0B5D27FDD48D60BB0259010B33F /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */; }; + 3108F662E409C22082872D0CF11C5385 /* FIRInstanceIDCheckinPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A88A869CED3ECCE7D333B05DFD0CDEC /* FIRInstanceIDCheckinPreferences.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3138786FD0F60F0C415E6BD851240611 /* FIRInstallationsAuthTokenResult.m in Sources */ = {isa = PBXBuildFile; fileRef = B560A05DDD10C41F219BD93A94B08293 /* FIRInstallationsAuthTokenResult.m */; }; + 316AF39205CFD0A9865FC10D4C3B30E5 /* GoogleUtilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9466A7E6EE64E7107817BB3DD4AB65AE /* GoogleUtilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 32A9C57D813527201AB8236B8151591D /* FTupleTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 31537E08EC2179F2189D3BDDA257E569 /* FTupleTransaction.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 32B07380C1AAF5AF6D51208E94E877E7 /* FIRInstallationsStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 3FCB115B6E3E19E6E714CE31F8C48CC4 /* FIRInstallationsStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 32D4873D9CE7533E2B8FB5A5A780AFC4 /* FImmutableSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 581326EBD90729AEB63DC7E39FAAACB7 /* FImmutableSortedDictionary.m */; }; + 335794B41F65E19C1872A69C350EA142 /* FCompleteChildSource.h in Headers */ = {isa = PBXBuildFile; fileRef = ADD2FCA292915B2E6B0381A7040CB1E6 /* FCompleteChildSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3440F277E50EEF9650620F3FA2671DAB /* GDTCORStoredEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = BE21DDFAF668870C165692DA4385D672 /* GDTCORStoredEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 34638F413AEAB4A39890C6BE7CAFC7A7 /* FBLPromise+Validate.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = E8528848BDEDC26C42D1B3137E78486D /* FBLPromise+Validate.h */; }; + 35C9DE578E2AB847D7D877558E43F828 /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = D5C117A339CC3C9E15D400EB57AE4176 /* snapshot.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 35E06A30663DF152AF0B2CBE90A8D113 /* GULMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = D3EA4FED70C955814D3060BCA5FCD84D /* GULMutableDictionary.m */; }; + 3627B32161C61600B72B8131AEA45CA0 /* slice.h in Headers */ = {isa = PBXBuildFile; fileRef = 64927969944CC6B0EF7ABBF8A9D6B982 /* slice.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 36857AACBBD006017DAEA55E0C153ED0 /* cct.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = 33023881967395B122B2547507E8354C /* cct.nanopb.c */; }; + 3714B6A3B2108658EDD63F97A6F25291 /* FIRDataSnapshot_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 81C33A153E19967E3445E344E55BED54 /* FIRDataSnapshot_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 37745085A5593D67CC5D9610EDE79FD1 /* GULSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C563C7E60320BE9BE84B966C5A1702F /* GULSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3800B0DE275B049A18AC23B9DBE4A8B0 /* FBLPromise+Timeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 714CACEB6E4D9CE23EF7D85F0B7804A4 /* FBLPromise+Timeout.h */; }; + 38B7B99B0D2365F522BA602C9141FF91 /* crc32c.h in Headers */ = {isa = PBXBuildFile; fileRef = 31A3DA146C85F0E4208EDF51D635374E /* crc32c.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 38D345C64A36B3C9EB2AAC69906CAF27 /* FBLPromise+Await.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4A14479C1990437D603C775E0838399D /* FBLPromise+Await.h */; }; + 38EDCB6B0C1491BC14B16B4E986DA00E /* FTupleSetIdPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 469188005111468BDAB623C15E021952 /* FTupleSetIdPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3A8E7FC71B4E275869756EBC863BAE05 /* FArraySortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 171EA63C3E77121BBC849D8ED2882074 /* FArraySortedDictionary.m */; }; + 3ABA3B497CD34014B40A742D3513F1AD /* FIndexedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A41F2D2C55B5704983865EFEBB72419 /* FIndexedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3ACD266E0A1B28DAA25CBC1322E6A0AF /* FIRInstanceIDVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = C3AAC69E6988F1A4299931B9F19FDAB9 /* FIRInstanceIDVersionUtilities.m */; }; + 3AF47855221B8317A519B7089F5B7962 /* FImmutableTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F74BD3D7622AD541A03B2EDF917C25A /* FImmutableTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3BC2C5DFB1D965CA2DD0DC4D72405FE9 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B4C695F884374A04733A8358081E649 /* FIRInstanceIDCheckinPreferences+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C2CAC2C64AC199613434D9712AB67CD /* FLLRBNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A87C58D697F019156D54455DEF3DA75 /* FLLRBNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C3238DC28C8CCC7E0E17A3772F13BD5 /* FIRInstallationsItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 084AA7F2510FE8410D65BB1A2A992F48 /* FIRInstallationsItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3CBB2887C1CF4A11343EE9B17F2A8FF2 /* FIRInstanceIDTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A455526C11611056459A460492697E5 /* FIRInstanceIDTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3D62AF01A5143EBCA5218704AF6064CF /* FIRDiagnosticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = B422450B8B9A222431185AE041CCA41D /* FIRDiagnosticsData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3E402733BBC6CB51F219ACA5C74ACAFC /* FLevelDBStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 28976708F04BF0E8AD3DF8D772A5E9C8 /* FLevelDBStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3E725E644BD03962B59F11CD52FEB12E /* FTupleOnDisconnect.m in Sources */ = {isa = PBXBuildFile; fileRef = B48FF961E99ECC80C015283501933E9F /* FTupleOnDisconnect.m */; }; + 3E9DD3D7A6AB68776A8B16AAA853A80F /* FBLPromise.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4B5719CDCE6B2A2F1216F9C92E6D02C8 /* FBLPromise.h */; }; + 3FBAE9D1BD17763A5C3A1BD1253EEE1C /* options.h in Headers */ = {isa = PBXBuildFile; fileRef = CB0616FB9FF2AAD7A912C19A189655DE /* options.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4048E2501D46CBF2761C248E0957DF57 /* env_posix_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = BCDBC9E6585A6FC8409A7900F72E6143 /* env_posix_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 40601A4D3779E3D643749E6379AAB8C8 /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A013D2FB3A60D77460B97E98790815 /* FIRInstallationsItem+RegisterInstallationAPI.m */; }; + 40BBCE59B55AF4DACDD206A0A4D9F68D /* FTransformedEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = ABFA60EA6B3C819ADA0E147A88E113E0 /* FTransformedEnumerator.m */; }; + 40E5F48D173FC8A5A47F91D1BCFC7A6B /* FTreeSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 789BC906E9C7035CD6F53282CE3AA453 /* FTreeSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 41A81452441B42D5FA63B6F7DF2B8E34 /* FConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = EB5FE81C882FC64F8753116A5B70F2E6 /* FConstants.m */; }; + 41AABBF5FAA79DB754B17E3177777F0C /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4601FE5C4C1B22A2499A3C8CFD4147 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 42542065ED59364C2DD90417D7157E7F /* FAtomicNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 848DF70F7272DBB5E881092F5958348A /* FAtomicNumber.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4262D25247B12F48A0FDE5B4E1B8BC7E /* FIRComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = D5A546058E77F0752995F315FBF8385F /* FIRComponent.m */; }; + 42A4E95D960E07E9141C6ADE411F9B59 /* FRepoInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = C17FA7E29878F0A856A40B1BEC779C9F /* FRepoInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4346A89B7AF2440D62CB3A1323E9F399 /* FViewCache.m in Sources */ = {isa = PBXBuildFile; fileRef = AF3E068B4B32BE9AA15D6F3ABDDA7325 /* FViewCache.m */; }; + 43FFF7833C563543060BFBC31DB3AF02 /* table_cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = E2A08AAB5D65AB79EB24EC26404117B7 /* table_cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4418CD739AC0D463A5F8E5D65ECB16F9 /* FIRInstanceIDConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 852C7911EDA4AF68E0A658A3B70F5D0B /* FIRInstanceIDConstants.m */; }; + 441C94CC068CB85B1EE962C7DBB0CCE3 /* FIRInstanceIDTokenDeleteOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 801F763C867E44EE28B55C1FBA1D58CE /* FIRInstanceIDTokenDeleteOperation.m */; }; + 448F087F0DC22F891D5C3815CD4FD089 /* FRepo.h in Headers */ = {isa = PBXBuildFile; fileRef = 21481E35761ADCCC2C9056C42954B6C0 /* FRepo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 450DB46D3AB4A2DB30B67F3617E3A77A /* Pods-PediatricPancreas-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4990C45303FADD6DD0B9FD280C5B5FE4 /* Pods-PediatricPancreas-dummy.m */; }; + 451CC5C8BC9A08A786B81A3B4C4024E8 /* GULNetworkConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 3006D62C40726EA8DD299E82CEC1BD7A /* GULNetworkConstants.m */; }; + 453D09C210A62983622D9B3033351E47 /* fbase64.c in Sources */ = {isa = PBXBuildFile; fileRef = 469E4EE0DF63B70B17207AF1F945B600 /* fbase64.c */; }; + 458166723E07E34E95EC91DC422D2DFA /* FIRInstallationsErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 7478BC8F13E25643BF62665659255636 /* FIRInstallationsErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4693044AAE649819BFFAFAF181E5F194 /* FIRDataSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = AFF7787A89CE9402712586AA44B4A30B /* FIRDataSnapshot.m */; }; + 469B9DA599A5FCC6C177A5D471627099 /* FValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 726B3EC39B72F88C33B457410776DF31 /* FValidation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46CD75B822E8AD2C51BE1039C2BB80F3 /* FOperationSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 00B9C533AF486EDF4C205EBBEC465607 /* FOperationSource.m */; }; + 46DB3B00C18339C9001A96947F8354CD /* FStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EE088A364492A317A7C4FA99BC16B32 /* FStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 471980AEC51B1D14E068B57ACD4D5F04 /* FIndexedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = EE8845E0152C938810B709F01172891E /* FIndexedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4743C0A7362C70144DA8902ECB6A107F /* FIRComponentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EB8FAE52E1EE34C048C2E25D084AACF /* FIRComponentType.m */; }; + 476270E22168C78721C89A072EF9DA5F /* nanopb-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = DF6767ED8AFFE68E3C7BEDECCCEEF733 /* nanopb-dummy.m */; }; + 47735DF27A3BC5E368CEA1586232FB3E /* FBLPromise+Any.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 89EF1757A361BC3BE2727F86201C94F8 /* FBLPromise+Any.h */; }; + 47F57B37033CB9AE138264B78F352789 /* APLevelDB.mm in Sources */ = {isa = PBXBuildFile; fileRef = 52B29770DEBEF1203AB8B5BF1A64AEC1 /* APLevelDB.mm */; }; + 480A04FCEB9F74A462DCF3E4E65AEC64 /* GULHeartbeatDateStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FF27C9FA28C17B538FE3D79E5568EFB /* GULHeartbeatDateStorage.m */; }; + 48279784E05FCDAA6A1AC5FDD4BC5EE4 /* FPersistentConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D7A7A1F332FB4CB78EEFE0D5645D882 /* FPersistentConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4855B819ACCD8E101955F99EC1A255E1 /* GDTCORUploadCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = F04EDF68A0FB407E446327F460FEDF03 /* GDTCORUploadCoordinator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 489BE597AE9353534CC9F3FD9AF61951 /* FIRInstallationsKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = D85B0BBD6B9929A743D2EFEF5F5A089B /* FIRInstallationsKeychainUtils.m */; }; + 48FE6B43AEBC4D0E5934CD1F05CFA8A9 /* port_example.h in Headers */ = {isa = PBXBuildFile; fileRef = 522F207349FC0C3AEBE0DC5C8D0F6A5E /* port_example.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 490A2A7CEE593B12A2591ECC7AD538A8 /* FSparseSnapshotTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F12565B717E28C3CE4FAA319DAB3D7F /* FSparseSnapshotTree.m */; }; + 491D4AA6161DD56B372AE8859D9EB5D8 /* FIRInstallationsIDController.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AFED41CC4D9C2FD5B2C41C3E970AD3 /* FIRInstallationsIDController.m */; }; + 493DE807724DFCD68FCAE1178577A0F6 /* FIRVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D2B2318949D5A383E68777964C87251 /* FIRVersion.m */; }; + 49E5C9957A73B815E9B4EFAED0929321 /* FIRInstanceIDCheckinPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 855AA79FFF7DE13C4E817A31871AFEE6 /* FIRInstanceIDCheckinPreferences.m */; }; + 49F5B82C29710453011ED5F892B91B96 /* FRepoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A0AC30DE0C12BC52B4BD10F6121DDF /* FRepoManager.m */; }; + 49FA9CFB7506743456F5027040F01EEA /* FViewProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 025546DBE96632B34B63790615A3BDC3 /* FViewProcessor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4A2499CF744F2DA84A696B775C4A4D2B /* db_iter.cc in Sources */ = {isa = PBXBuildFile; fileRef = E83A950C90FADE82C6C50AB81CA86027 /* db_iter.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4ADE3210B6FBF7F2B6B42F8933F5D21F /* env.h in Headers */ = {isa = PBXBuildFile; fileRef = 975851733C4EF17619E794A66DD652A8 /* env.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4B7F0184DD074841956989FF999155F3 /* GDTCORClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 69378FC37B1DFB015522CAFAF6EC4001 /* GDTCORClock.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BC329728DAA96B1C5CC084201689945 /* GULMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 589C384C3A628D4954C3FDE4FB7B6A43 /* GULMutableDictionary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4BC8B7D684A6E5E15EF10F120622DF86 /* FIRInstallationsErrorUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DA5D3B64A2899A7E1B92B478EF70F9C /* FIRInstallationsErrorUtil.m */; }; + 4C8DC5BA6AEFBABEAC2BA78ABD76C05E /* FIRDatabaseComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CECAFFA8C44526C632EEA97E2699B33 /* FIRDatabaseComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4CB86817A316CD4A9F3EAE62FB4ACB96 /* FValueIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = E6E84A81CE2FF3E0A915DAE54B7DAF41 /* FValueIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4E2B9CC4DC53413EFD971C628FEBC58B /* FPathIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 747CA32386AB55EC174C9FE0E0C1A2B4 /* FPathIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4E522AB2C46E792F9289878E85D1DA06 /* PromisesObjC-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 393480CCC4702D3A5CC9CAF98AF4E723 /* PromisesObjC-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4E98A0CCC93D4BE2753CC91F92F303CB /* env_windows_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = D5EB776A6BFE1187D7EC5CC46FE6F740 /* env_windows_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4ED2955C86A5C26309952FF8FFC09569 /* FCachePolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 22A60F60CFF8C2C8A3624904C2D5A7DA /* FCachePolicy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4ED40DC2D90361334824EA94C69DAC8A /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = DFF3F389C5FFC9338529BC11F026588E /* FIRInstanceIDCheckinPreferences+Internal.m */; }; + 4EF14159271332EE075771C3585198CB /* FQueryParams.m in Sources */ = {isa = PBXBuildFile; fileRef = F7F36453D48EB7DB0A3070832408980B /* FQueryParams.m */; }; + 4EF25A23AD2C3121B8FAC312055528F4 /* FTypedefs.h in Headers */ = {isa = PBXBuildFile; fileRef = 4AF07C1AFB9C5EDF8416071371D15C6D /* FTypedefs.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4F9E52E01C723BBB86A2F3306563369C /* table.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CEA8AD862EBD0CBF7BEF03AA3752A1E /* table.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4FC706C02447823974080F724C244754 /* FTypedefs_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D41CCAE0E65DD892BC17B14CD65AE6F /* FTypedefs_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 503446234DE2F6A868F2A1C33A87AC29 /* FIRInstanceIDCombinedHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86A0153033585BE52A436ADC9565571C /* FIRInstanceIDCombinedHandler.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 504921BD2B0D4F5B15580FC30F69098D /* filename.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1ACFD04FDEBFD059B55BE1FA713972C2 /* filename.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 50553464F21122B6CE26E8360F3CEE0E /* FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 73B33C24AB2B2C938EE0534A6B039DA1 /* FIRInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 509F33BADA937F1FA75BE86611E08911 /* FIRDatabaseReference.h in Headers */ = {isa = PBXBuildFile; fileRef = C03A03D30012B27E690AA4629A1913A9 /* FIRDatabaseReference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 50A9A9634C01403BBD8F48F6F860DD23 /* FIRInstanceIDTokenFetchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CFAD347C460AFFC4F90B3045452C74D /* FIRInstanceIDTokenFetchOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 50ECA21E528DB9D880C7ACABDED9A9F0 /* FChildEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = F5343AFD79945A13C37E1EC1B6E62B25 /* FChildEventRegistration.m */; }; + 51CFE79D0A35972C408CACE75B5E318A /* coding.cc in Sources */ = {isa = PBXBuildFile; fileRef = 30E60BB59ABCAB6163E9F312DCAA82C6 /* coding.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 528C67FBF5D6319DC04886F582D0D428 /* FBLPromise+Wrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 83F1C74FCB7D27EEDD0F20E80317A163 /* FBLPromise+Wrap.m */; }; + 52B36E9BD0987C1C076179244C715689 /* FTrackedQueryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CC03C75A089757D74469A154727F5CD /* FTrackedQueryManager.m */; }; + 53059A83D1093C0526B67908130488CD /* GDTCORTransport_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FA603E46D511623D3630CAE0F5C1F3 /* GDTCORTransport_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5393FECDEA4955E523BDAFFD9ED07EBC /* FUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = A65321EB88EA8A0A7B7F1D040CDBDE0A /* FUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 53CECFA59A5B245E70074845D4780B9E /* FKeepSyncedEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C61360E2B0972E9BCF8D71772010A94 /* FKeepSyncedEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5423F9E7441C74D9CAB0158790D84C70 /* FBLPromise+Await.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A14479C1990437D603C775E0838399D /* FBLPromise+Await.h */; }; + 54AC263C74BDE2D01365DDA2CAFA46B0 /* GDTCOREvent_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D3F8923F8BF7B696F0F826E15C1D08E1 /* GDTCOREvent_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 54C7E3021017AF76BDE7BC5DEC678DBD /* GDTCORPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC19607EAE0661F18ACB5A03636690B /* GDTCORPrioritizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 54F084CA1A6FCA5878B5B017B585A1B7 /* FSnapshotUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BC630AE6D6E92874C62C4D23F10958E /* FSnapshotUtilities.m */; }; + 5597DEC5A26E41DDC9AD5B0C63F30822 /* FSyncTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 74B732861F4DBB7D074BD0EBEAE05218 /* FSyncTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 55EB4BD5AA489C1B932393E9CD151E6F /* FPriorityIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 24E3248B95B1AC14B851DD22D5CBADE2 /* FPriorityIndex.m */; }; + 562A21D201918AC5858CFC82E8DB7C91 /* GDTCCTCompressionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A2927D87478BAC6E0BF0481759116A7F /* GDTCCTCompressionHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 564A2437B3F4348585F16872DD3A18CF /* FBLPromise+Recover.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A680F32866E1A09336694B099C04AF81 /* FBLPromise+Recover.h */; }; + 56525F830586E04FCC3EB27BD9D37255 /* FBLPromises.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = CCF0CDBF79119FF6820FFA131F04236F /* FBLPromises.h */; }; + 572D63DEB6D5CE940424A804F3BACEDF /* FIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D952F927F793C8D050294553BA6A78D /* FIndex.m */; }; + 5786FA7AC828B7B61B0D963AA344ACDB /* NSError+FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AF055035432D0F1EB1F9ED475A81A00 /* NSError+FIRInstanceID.m */; }; + 579867C7A940E08AE0EBD5A014F14763 /* FIRInstanceIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AC10901C2F79CFA82FEAE4AAF01ABED /* FIRInstanceIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 585432A81A1445BE160730C4D6A6EEE4 /* GDTCCTUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = B17CF74C10270725403C6592D2382E9E /* GDTCCTUploader.m */; }; + 5897F0A8E4D00174A944E698AEA6EBF3 /* FIRInstallationsVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 36C7915A295EC650C0F2F336452EF3C2 /* FIRInstallationsVersion.m */; }; + 58A44043BCC0225FFFA5CDEC7322A2E1 /* comparator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6E5AB98A277B1CB96C5A1CB204FA77FE /* comparator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 599FED6060274B5F71E088500A84E5B5 /* FTupleNodePath.h in Headers */ = {isa = PBXBuildFile; fileRef = F8E21755762B362FCA620ED488970ADF /* FTupleNodePath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 59B832BF2DCA30E869E024E410B4FD13 /* FIRInstanceIDTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 45BBE0220D0AA28216B74B4EECE15457 /* FIRInstanceIDTokenManager.m */; }; + 59C1A5BCD90F5014BB332BE28207B49E /* FLeafNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 25107E5C61245A8D44F02161C92B9A9F /* FLeafNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5A47B09C86EE1E3AC3ABE08A52C6A280 /* FSnapshotHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 19298FBBC7572398E1E2B6F1B0ED04B5 /* FSnapshotHolder.m */; }; + 5A51CA1A353626C080186F2915B3B374 /* FIRInstanceIDTokenOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = B189B07C114807A1945A3116776D2A43 /* FIRInstanceIDTokenOperation.m */; }; + 5B32957659AFC9CD2F8925DE7FA655B7 /* GDTCORLifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F8C417906B62E8422D71968C8EEBF1E /* GDTCORLifecycle.m */; }; + 5B77D1E30B25C23CF4E6FF171ACCB2A6 /* FIRInstallationsErrorUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 10E088517E88ECCC3CA4D7857ABC459E /* FIRInstallationsErrorUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5B9FFC2E882ACF13D5495485653E9E75 /* GULNetworkMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 404A14083B530908C5B3506B9F2CF75A /* GULNetworkMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5C3CCE52E087B4B8E603FA64DAF9DA73 /* FIRInstallationsStoredAuthToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 039D485AD0B1A9C9BB6FE228FF40844A /* FIRInstallationsStoredAuthToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5CB4D9C34075C194E6F4ED76E1B7D927 /* GULReachabilityChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = FF8DF3F9B8EAE9DF3404C063DF67AE24 /* GULReachabilityChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5D574DE590E3828C62C092888E7BD04E /* FListenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 686EDFE931F5DA103D7A9B9031A68467 /* FListenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5E0C75B90D56AF1C6F39D808DC7778A7 /* FIRInstallationsVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B77C44CC1FDF8D7B46080AE7D97ADA /* FIRInstallationsVersion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5E0F436EB98F3C615BB612216EE8904B /* hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = 12D88D855D9F5F1FB41B1CF4A0280262 /* hash.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 5E2CAB2BFF770FB45251BE3DE5B0525A /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */; }; + 5E34D8191F84A951DD68BAB0CA7DBECA /* FIRInstanceIDVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EE99081D914925E41102736BBD49557 /* FIRInstanceIDVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5EBE509B62EC6ED972B747240326E420 /* FImmutableTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 6526C1D31492B1E021287A00A46E4DB0 /* FImmutableTree.m */; }; + 5F0C5E4C1DFAEBD8491F3148EBD90EF6 /* crc32c.cc in Sources */ = {isa = PBXBuildFile; fileRef = E653C151D9C6CAC8F8FB64B0774210D0 /* crc32c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 5FC48233A9A091A5AD41F48C246425B6 /* FTupleObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = 878E027D5C73EDA05B5D73F2457F6E20 /* FTupleObjects.m */; }; + 604A6E676D3E9F0B60D498B29087440F /* FListenComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = DB8DBDD015B9A7C63AD7FF51FCD1CED6 /* FListenComplete.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 60734CF9B2C36DF651BFE9BD86BFDB5F /* FIRInstallationsIDController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D3C1F79FCD48F9D503D56F37E60FE8A /* FIRInstallationsIDController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 610DAA599D1DF02C373356724FD8A5E8 /* FIRInstallationsStoredItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 8CE91982EF784FDD0B9C73AE4E76797D /* FIRInstallationsStoredItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 615327D18C1FCF157702F317C0C0E6C2 /* block.h in Headers */ = {isa = PBXBuildFile; fileRef = DE20B3C2547CB5DDA522FADAB581891D /* block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 61C9CE120191BD6EA53D299A4EDE90DD /* FIROptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E9580AEFCE0FFB8EB4D0165A208A7EF /* FIROptions.m */; }; + 61F58417D58890BB6F2020D13F704CC9 /* GULAppDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = B3CBA0DE4566EF24CD679F6D52B2AF0E /* GULAppDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6224C68BA5B4C2D47B103D306B74341E /* FBLPromise+Then.h in Headers */ = {isa = PBXBuildFile; fileRef = EE99BAF073CA1D81781B1B25C847608F /* FBLPromise+Then.h */; }; + 622B3C041AD5D25276A5D9B283DC0323 /* FIRInstanceID_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E0495142F4CB62FD6FD98EA2E14AA08 /* FIRInstanceID_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 625277FA73B61F7DE91BCE4481C32E9F /* FIRInstanceIDStringEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AFCCCAB65ABF466748E9D04F3ED6026 /* FIRInstanceIDStringEncoding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 62BC8EE3772D71C39FB6F17E0C02FDB5 /* FLLRBEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0008E34A7746A0E1A2D5583DA0348CBA /* FLLRBEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 63A6EF89158BA0342A88A70BCDB53F0C /* FirebaseDatabase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9EC147AA53DDCE9113303230BAA16823 /* FirebaseDatabase-dummy.m */; }; + 63ADBDE9EBE05200679C68820BCD29D4 /* FBLPromise+Timeout.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 714CACEB6E4D9CE23EF7D85F0B7804A4 /* FBLPromise+Timeout.h */; }; + 63B505F0D182477E19F4155AB797A8DC /* FBLPromise+Always.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = FB8A36424CE63AB822739A749BB71C82 /* FBLPromise+Always.h */; }; + 640B42CA70E9ABF7F582CB9E0CFDAED1 /* FServerValues.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C788D48944FAEAB4862F3DB0F76AB84 /* FServerValues.m */; }; + 645B4A5E78A6930440C419B5DB349749 /* GULSceneDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 00CB870A9CD0CEB91A8EEB4E2DF570D6 /* GULSceneDelegateSwizzler.m */; }; + 6517CD45A16C90958AD60CEC2F40D4C4 /* FIRInstanceIDCheckinStore.h in Headers */ = {isa = PBXBuildFile; fileRef = F81A7101C3F68C1D5685C0AC60237A70 /* FIRInstanceIDCheckinStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 65239E2753AB78105DA3B5E7354FEAA0 /* Pods-PediatricPancreas-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AFB0D7EB1E556FEB7B8B8BABE4313A1B /* Pods-PediatricPancreas-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 657237B8B4F32B13EDF3F4C2DC948AB2 /* FTupleRemovedQueriesEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D77CDFE1F279E8808BC2B957E413C69 /* FTupleRemovedQueriesEvents.m */; }; + 6573DD72CD06404672E18390A2602965 /* FStringUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B48B8EAD733AA93D56EC86DF4E5EC0 /* FStringUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6595BA905B0AABEB781AEC9D767E3E7B /* FIRNoopAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D8AFA1CE839BF7B31F847CE180844A5 /* FIRNoopAuthTokenProvider.m */; }; + 65F1C5585A06E9F3A63A2527509AB776 /* FBLPromise+Race.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 63AAC507B0C7EE188A57BC2455B04E4D /* FBLPromise+Race.h */; }; + 6659F5CD6E5F6D09291FA0707217AC98 /* FIRComponentContainerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 141F97B030083310E1B66925EBA42F52 /* FIRComponentContainerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6670C57E9946D6F6E1E4261CEC4CFA73 /* FIRInstallationsAuthTokenResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 03741108F4DCC70F6CA8C9C139C8C1B7 /* FIRInstallationsAuthTokenResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 68D8A43AE7F71E71D650B6D9571BA4BC /* FIRLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ABDCEADCDB0A5F734C40BD872DD9C0B /* FIRLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6916DB010C26CB84795B779931BCC477 /* FNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8471B9B04CF93EE03047131EA36E6938 /* FNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 69186B1E9ED43ACAD2F35E1945261F36 /* mutexlock.h in Headers */ = {isa = PBXBuildFile; fileRef = CD33D7886791A925EDD3E12E07C16039 /* mutexlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 69D81130D8B7B9D7748BC1A9A8FD268D /* FImmutableSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CEA9F60ABECD586463154A10B2288F8 /* FImmutableSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B222B03F3BC8345CBFE9802D8770AD7 /* posix_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = EBB7BB312BA46B435C86D22D545460A6 /* posix_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B4D5A61549502A1A5A033028F44FB03 /* FEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 027C0282396A56D8390E23CEF590CD5A /* FEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6C607B38D06C6BB8D7B5B3972D9E2A61 /* GDTCORDataFuture.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F8A01B76B2056EA8629ED6314AA7FBF /* GDTCORDataFuture.m */; }; + 6CB0FB8CDEBA44EA97F54C01AC1D5EA3 /* FConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 6897BF9DB6AA2AEFA17C83D1CC46505F /* FConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6CB1633C99EB08C62B0EEBB2FCC37928 /* FIRTransactionResult.h in Headers */ = {isa = PBXBuildFile; fileRef = DD144C3EC4E9FF7960E6B2C281A11227 /* FIRTransactionResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6D93687073718546736A98A061859937 /* FIRInstanceIDCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BD6E0B555B8B7001FA7C0534B5316D8 /* FIRInstanceIDCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6D93BE021B3BB3E5085568DA6B00C125 /* GDTCORTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = E61B535DAB4A7B24C60731AB49DF519A /* GDTCORTargets.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6DC14A98DA70552D1F41941379E1C12F /* FPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 97AEA888054F9AC998F31369474D10B3 /* FPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6E39108A97275B02B75E1AF6BFD8E477 /* comparator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A820887FD76849A2C54FED3B31C6E2E /* comparator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6EC0A404C503642B9540E4D86DE133DC /* FChildrenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = AF74E221F17A2E24C2B42D1BC778DAC6 /* FChildrenNode.m */; }; + 6ED483CC1CFBA7C89E08DB039E89AC57 /* FIRInstallationsItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C9B859F2BEDA3BE876C74D5B9F07E4D /* FIRInstallationsItem.m */; }; + 6F0A67A608E04456C0B5030EE47172D4 /* GULNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B445347E43C90E24AE0CFABC51EB3F9 /* GULNetwork.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6F318885B392F65A5B1ABE15D11E5E54 /* FOverwrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 09BC891B2774FDA333795F1FA34727ED /* FOverwrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6F53DEEC73A0B0613D86DF003E28CF6D /* FEventRaiser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7158411B4EA467277676C39BCC4E56CE /* FEventRaiser.m */; }; + 70D63115866856277EECF9C957267C52 /* FBLPromise+Testing.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A51275DED8B5876B1EB201F7E40D4517 /* FBLPromise+Testing.h */; }; + 725187D3F8C64CAB2CE5CBC0213D8318 /* FIRInstanceIDAuthService.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EFEFAB171B0614C38F1C781DB2D1FE3 /* FIRInstanceIDAuthService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7284B96124EB53659E5A38AB5BFD20F7 /* FCacheNode.m in Sources */ = {isa = PBXBuildFile; fileRef = C7DA56AEC2BBB09F0B17C011D33EFD87 /* FCacheNode.m */; }; + 72E7BB1C714620C56A727A1A738E407E /* FAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = BB2BA88758CD8F3F42FDA4887D47257A /* FAuthTokenProvider.m */; }; + 7317B7F1DFE34E13DD05E12C850C8E07 /* FAckUserWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = B9D9A71F70ACC4A28A21C50E73140250 /* FAckUserWrite.m */; }; + 732320404F09A7A234C0554FE5C1AACC /* pb_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 881C688EF05D37FB42E12434920FDBF4 /* pb_decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 733AAF70FA2B5DDC0CD79A50F9C3F6A7 /* FNextPushId.m in Sources */ = {isa = PBXBuildFile; fileRef = AE5599B51674FD217CF4064C4D6DDFF5 /* FNextPushId.m */; }; + 73403591BF9BED66D7BF53BEE9C97933 /* FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F93B1E527C47BC19CC33DF9E2E21D44 /* FIRInstanceID.m */; }; + 73520D786C7F855AE3D651D3621D0CBB /* FBLPromise+Async.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DD85EA7D746AA0ABA6E66DA54FE552 /* FBLPromise+Async.h */; }; + 737E8608EC1F9E6A3E60E465EFB49494 /* GDTCORUploadPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = F5977632C28C8A80798C83831080ACC9 /* GDTCORUploadPackage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7385D9509941D28582315B957132D207 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 73EFD42008D8497C7AFCBEECD373B207 /* FBLPromise+Reduce.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = D90F32A060B026F6D87B7D74D28DC97C /* FBLPromise+Reduce.h */; }; + 73F18C354CA89D79D302A0817D8D62E7 /* FCompoundWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C698FE3E8F0E520BE6B395F5CAA16F6 /* FCompoundWrite.m */; }; + 757A5DB44AB15400A4E91877C6192F27 /* windows_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 71F1E99218E565E5F99716E1FF698721 /* windows_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 760D02A90FD244628BDF690A02428E16 /* GDTCOREventTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 08DDE3680AB4A3C8926B96415B4152F9 /* GDTCOREventTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 761AD4B367A2C280D954D8F6F6EDAB10 /* GDTCORAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = D29F1B6F2D210493CE1B350B9E1190A6 /* GDTCORAssert.m */; }; + 76859CC0102F8E2B0F88A618987DD54E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 7704DBEB4FD8833D2EC2965CF68761D6 /* FIRHeartbeatInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 533EB989EB34349FC33B5C0C9C22EF78 /* FIRHeartbeatInfo.m */; }; + 772DE42A9C5A47247E8D29118F0F1618 /* FParsedUrl.h in Headers */ = {isa = PBXBuildFile; fileRef = 722C7D69C7C7A86DB9326799FB70F05B /* FParsedUrl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 774179338BE4754263738DCE7E7E9358 /* write_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 19F174A0B87E27B10889237216A3FA55 /* write_batch.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 775DC12DA620A40118722073684E911E /* GDTCCTPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 656F06CD541DEA906BAE925398B67D0B /* GDTCCTPrioritizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 77E3E9EBA0F53BA60BF6853FE7AD8DD7 /* FBLPromise+Any.m in Sources */ = {isa = PBXBuildFile; fileRef = DDC164F6102A008EB68780B6F360A50A /* FBLPromise+Any.m */; }; + 782A253D94DA7F5E7FB4FB8AA086BB0C /* FIRAnalyticsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = F345B60ED7E3934E7012324272612AE2 /* FIRAnalyticsConfiguration.m */; }; + 7841AA457BA7BF9D0C92B611AAC1934E /* FBLPromise+Delay.m in Sources */ = {isa = PBXBuildFile; fileRef = 793FDF0150561467E6DDF33320B696A9 /* FBLPromise+Delay.m */; }; + 78E6638048B07AFD81DC7CDAACAE5B64 /* FIRInstanceIDUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = E6908625F5FB22DD281BF38879C7EDCE /* FIRInstanceIDUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 78EFD0D62AD99147E88485CCA6870FDB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 7958F051CAD9CB7D57D28FFE63E74827 /* iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4236FF19FECDA313AEEBB197D87F13BA /* iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 79C2937BB9C843004E552AC86CA18351 /* FSparseSnapshotTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 20B54EE31B858742F3D0FDC1F9359591 /* FSparseSnapshotTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7A4194F77634B66169BD29A13A685D42 /* GULSceneDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = CC9FBF9F202D0BA6D21D1A878140A6E7 /* GULSceneDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7A5C6D925F727EE2EB6FAAA9FADD0D0F /* GDTCORUploadPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 764063E4BDC2B2AC40BEFF95355FD7FC /* GDTCORUploadPackage.m */; }; + 7A8B2F9B9F3DD506F1A7DA32601995E6 /* firebasecore.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = A1AE308C5F0E074A28931424B649BFB6 /* firebasecore.nanopb.c */; }; + 7B77E6A110A4E9545928F520B380CFC5 /* FIRInstanceIDBackupExcludedPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C00A27614E9B023E9AF2E860B568B7B /* FIRInstanceIDBackupExcludedPlist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7BB8F10847144EF9E81AE39013F71A2B /* table_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = AAA8E1EFC2A415EAD47ED600FEDFB8A0 /* table_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7C0DA843726761FFE3436536D5D3B2C3 /* testharness.h in Headers */ = {isa = PBXBuildFile; fileRef = 813307FB7EF7DEF7EB26B719D22EC86A /* testharness.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7CA1CA32D0BA9A285C8B818BAC037538 /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 45FE005CA2C4A3AEF54D0E39D139568C /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7CB3E37A6635240A46A9B6F644ABD018 /* FIRInstanceIDAPNSInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = D3FC34E39CBFCA6990DA3BF467AD6C7D /* FIRInstanceIDAPNSInfo.m */; }; + 7D61E609B0D8B4BF0DED821DC50DF226 /* FBLPromises.h in Headers */ = {isa = PBXBuildFile; fileRef = CCF0CDBF79119FF6820FFA131F04236F /* FBLPromises.h */; }; + 7D9056D2435322919EABCFA398BC86A4 /* FBLPromise+Do.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 713F262D1F922BE2029360D4072ACDE0 /* FBLPromise+Do.h */; }; + 7DAE8BCE3F5F06E3C2A5D0DBBC0C9AC2 /* GULNSData+zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = 93CDDE38F05478019E633026BB5DF3F8 /* GULNSData+zlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7E2C639C00F2A49D67EFEDDAED713874 /* FIRInstanceIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = C55FA61E2BD999842193CE4030989F59 /* FIRInstanceIDLogger.m */; }; + 7E5BE70443E370E84BECD288D939F429 /* FTupleTSN.m in Sources */ = {isa = PBXBuildFile; fileRef = F26B1F10B563CB6B30369228E750B277 /* FTupleTSN.m */; }; + 7EC8F372099B7B93703D558822D9F5C0 /* Pods-PediatricPancreasTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CE1AAC4069551B0743B4F75F9A76348 /* Pods-PediatricPancreasTests-dummy.m */; }; + 7F170BA72C35DCF119134104398EFB11 /* FPruneForest.h in Headers */ = {isa = PBXBuildFile; fileRef = 15F2FE55B0E52C26E5CD1A45A048429C /* FPruneForest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7FF09AAD3D6EF0664BB9EBBE4702F5AA /* FBLPromise+Then.m in Sources */ = {isa = PBXBuildFile; fileRef = 7983B3F70324C775988EB7A1E3932685 /* FBLPromise+Then.m */; }; + 802025F836213842AD971BFA04320D76 /* FBLPromise+Do.h in Headers */ = {isa = PBXBuildFile; fileRef = 713F262D1F922BE2029360D4072ACDE0 /* FBLPromise+Do.h */; }; + 80985B6C5CF33E0C7D5B4BA38BC05467 /* FIRInstanceIDStringEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 528792C9F0D3800EAF0C1D2F84EF8873 /* FIRInstanceIDStringEncoding.m */; }; + 8173F266B34AB78112BDC9F1178464A5 /* two_level_iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = FA46E5D5E0C2FA73D96E33137632ECAA /* two_level_iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 81BFE9029052A2492D6B7215EE10E58A /* FIRInstallationsSingleOperationPromiseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 253F8E2E2AE73606EC13FCD055710E21 /* FIRInstallationsSingleOperationPromiseCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 81E527E426B62E40558145D83400A12D /* table_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = CBB4910A187E43ED4826B25BAD824F43 /* table_builder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81E9978708F6226709BAB53EE2CF9C63 /* GULNetworkURLSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D47D02F704DF255E65A5CD36CF9D48E /* GULNetworkURLSession.m */; }; + 826630E04AD591A0443002398BEA5516 /* GULLoggerCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 7148DF98940A6E8CC17E6FFA5DCCFEBA /* GULLoggerCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 82E23046F043EDDE41FF879C5E81CB2A /* FIRDatabaseQuery_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = A5C471E66465A3AD8773DDA0113CF313 /* FIRDatabaseQuery_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 83856F7D562625FBF40DCEC1EA44B636 /* FIRInstallationsLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 24297E436652A516BEDF07C2BD03A52E /* FIRInstallationsLogger.m */; }; + 845714625E3473FE314FFC542B720ACE /* FNextPushId.h in Headers */ = {isa = PBXBuildFile; fileRef = 5737AA49AB6F7A70ACA5A20ADAC6B4A8 /* FNextPushId.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 84D0A43392ADACD2101C33407BEBB28D /* FIRDependency.m in Sources */ = {isa = PBXBuildFile; fileRef = 43015EB8E78629BAA11B46C1B2E9867D /* FIRDependency.m */; }; + 853279E9E5069291C7441613E6FFD021 /* FSyncTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D11FF29A1A4C44B50A32EA588B64D0FA /* FSyncTree.m */; }; + 85CA11CF7AB83ED7C9A7718A6302711A /* block.cc in Sources */ = {isa = PBXBuildFile; fileRef = ED529DE57D865F4DC7EE0F3956AAB7DB /* block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 864152069263E017EFA1C9E1E24148E4 /* FIRInstanceIDAPNSInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A6B9E9907DBF37ECD0FE8FC82FEB737 /* FIRInstanceIDAPNSInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 865223A402543238B142F54E0CC704C1 /* FAckUserWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C87D643C4C45D5110216216D030EBF5 /* FAckUserWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 866D20297FA8631B5FF700CB55A9F6AB /* GDTCORUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = E17BBB66CE95AF16025FD900BDAC46D7 /* GDTCORUploader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 869817FC3DE2BAA4B7A06F2BD17137D6 /* FNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A8F66572B286F803446413533812835C /* FNodeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 86CFAC06AA8D34293212722D18F00D06 /* FTreeSortedDictionaryEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FF0E752DEBBB329AED0426B5DBA6F030 /* FTreeSortedDictionaryEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 86D43E37DB4D8A2789294AAD41B0EEBA /* GULSecureCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = B6AB2E6D2B1419D09CFF28AED2C2B388 /* GULSecureCoding.m */; }; + 86E1163A90BC6A5E152C9C107A904085 /* FIRServerValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 832796FD22EEC1442E1D5058AE06473C /* FIRServerValue.m */; }; + 8703D25BE9A09A0DE8AEA23D81B22277 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 87424F09F2D4D76BC60F4E6135BF5E86 /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = F5CEB151BEA86559CC6F1B460E2A6456 /* hash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 877A82D57495B03675001EDD5F992FDA /* FClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 636D1E4BE951AF743DF68225F83ED03A /* FClock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 87E5203F27F981D453D08EDD52531A39 /* FEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 428713B30E973E48B3E6C248827A08FD /* FEventEmitter.m */; }; + 889D99A65CAB43057FA68D35CC3BD003 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 895587832DCDA70BF99226F5EFDF6168 /* FirebaseInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 020C390E50662AFEC68A60C7164199DD /* FirebaseInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 898A085D4E57B4FFA229AAB41E8ABFFB /* FIRAnalyticsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 9426AF07444B347C55EF8E50812A5EAB /* FIRAnalyticsConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 89BCC371F12999B9A8196A75146D76AD /* Pods-PediatricPancreasTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E48BE45942FA887A32872ECE30375ADB /* Pods-PediatricPancreasTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 89DBDFDBC60677DB58E108B7E0FB80AA /* FIRNoopAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FAE51763CF4E8A796748ED633EB69 /* FIRNoopAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8A15F2E0F27073273B9F005AD2DD87D3 /* FBLPromise+All.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F05E89B63938864335C55A44A0A73B7 /* FBLPromise+All.m */; }; + 8A20C3885DBB6729AB0D563A850B471F /* FTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FFBDB88B2DD90C42C6967F3B1D569324 /* FTreeNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8A330C9F1BA929109DE4BD3CCDF1738B /* FBLPromiseError.m in Sources */ = {isa = PBXBuildFile; fileRef = E1804140830E73C79880D6687271FAC9 /* FBLPromiseError.m */; }; + 8A3B53C1CA2FBA6587E34180D670BC9D /* GDTCCTNanopbHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AE0A767C52FD5794347BB98E80936166 /* GDTCCTNanopbHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8A4F0BDF204FDF791CEBC681038BEDC8 /* FIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 28B6BD3200BA33A9C4373D012238E16F /* FIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8A5EA394F778ED3582918A9CC6E81C8C /* FIRSecureStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1194FDC2AD891229F89FEF50221D4828 /* FIRSecureStorage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8AA5066C8726135716180F7B48E2A0AA /* FBLPromisePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2C628E92632EDA6D9E0BF833B6E84CEC /* FBLPromisePrivate.h */; }; + 8AA6733A89BB718EF7A4AF3F9C55BAD3 /* FIRInstanceIDConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 88A9B676AACC9D2E626E041CFCDA7772 /* FIRInstanceIDConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8B177AD6DA5699A3AB1164ED3F38C392 /* FBLPromise+Any.h in Headers */ = {isa = PBXBuildFile; fileRef = 89EF1757A361BC3BE2727F86201C94F8 /* FBLPromise+Any.h */; }; + 8B88C39196D031B2E65C59D29A9514D5 /* merger.cc in Sources */ = {isa = PBXBuildFile; fileRef = 92B0F3647F558C2051897581E20E8AA5 /* merger.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8BFCA8C54D6CCCBA9C872CCFF9B2A6F8 /* FirebaseDatabase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = EB69E36490C39B4946BAF571B5E6621E /* FirebaseDatabase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8C65CC5681A16CCCAF784C04883343BB /* FIRInstallationsStoredItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 885E13D41349DE2BB195AC2FC78B3D8C /* FIRInstallationsStoredItem.m */; }; + 8C6E929AEA67F66FD713B496EE2CBE64 /* FirebaseInstallations-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 258A1335EA6E5FABE7B63118A7825690 /* FirebaseInstallations-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8CB426C640194460BC76964273A677C7 /* FBLPromise+Validate.h in Headers */ = {isa = PBXBuildFile; fileRef = E8528848BDEDC26C42D1B3137E78486D /* FBLPromise+Validate.h */; }; + 8CC21B72E7F7E7AFAF3E93DD08B5478B /* FIRMutableData_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C9FA0D3CC8310231FD8E879E9F9FB2F /* FIRMutableData_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8DBD7194811092541DF71B9C8A023E2C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 8DF88FE5020589CBED594CC31C6A0867 /* GULSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 220C198B5B0BF924872B6F4E2D39EC90 /* GULSwizzler.m */; }; + 8F2443BF8A7D5DB547C9509341E9FD18 /* filter_block.cc in Sources */ = {isa = PBXBuildFile; fileRef = 39FF3E51D669385E3E87BD2ACCFC4ED8 /* filter_block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8F318A282CA275D436FCDC2C029315B6 /* FIRCoreDiagnostics.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B299D83AE65375BAF9C04BB63EB71 /* FIRCoreDiagnostics.m */; }; + 9009D8B79DE9849F5B0C2EB6773416C4 /* GDTCORDataFuture.h in Headers */ = {isa = PBXBuildFile; fileRef = C4050A6B53B6F2A1D68A2112D200D0C5 /* GDTCORDataFuture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9023EDC814EAC5D91060D88BBA0B2D97 /* FIRTransactionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 8387D908A0D8C85843E77A633F96933F /* FIRTransactionResult.m */; }; + 902823B2683DA4C24070B2974910324F /* FIRInstanceIDURLQueryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B87C45F3772C3A9902A4E9D16C60C9 /* FIRInstanceIDURLQueryItem.m */; }; + 91A48DACCC1B2FE301525CF24EC7693C /* FIRInstanceIDTokenDeleteOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 237B8AFB55BB3BE9CA62127AA18FB403 /* FIRInstanceIDTokenDeleteOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 91FE0AD7E1B01C145635712FBFE22A23 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4584B1E56CACAFB4FE9D377A31CB04 /* FIRLibrary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 91FFE8F13D0A292915F7DBEB0C1725C5 /* GDTCORStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = F4A3B19D1538DD146880608D2DA1FCAA /* GDTCORStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 92016BDC3C9C896AA3455626CA5FF37F /* FServerValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 00C87AD738B62445FF58BEA587E511E7 /* FServerValues.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 92375B897539D155FD76BCBEDE43BC6C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 9250971DA13DDF4E7F27C7BFDF16612E /* export.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F7A917CF1ED84B125E53F79C218D36C /* export.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 92FB390E9E6955EC5AA928ACBF8C78BD /* FImmutableSortedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D863A092BC7BF7CDCF10C9A29826E62 /* FImmutableSortedSet.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 939DD4BD42800E7A5CEB47528F0F7635 /* FTupleTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = F690E86D8C72F9C55C2E8AB28B37E07D /* FTupleTransaction.m */; }; + 942656920C39F8D9A85B8BBFE965446D /* FQueryParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 8839E366E23EFB0A1D7CAA675A691EE8 /* FQueryParams.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 962E953C11BC8DFEF369AE6E249BB805 /* FWriteTreeRef.m in Sources */ = {isa = PBXBuildFile; fileRef = BA096BF345BE538F99DE48F146E7B6AE /* FWriteTreeRef.m */; }; + 965459A010FB7FD56029C223E54F3AF5 /* FAtomicNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = DF85A3A3AE8C4D175D5C543F24DF2FB4 /* FAtomicNumber.m */; }; + 969AAAE7A07E4BF8FAF311DB24B9CCFA /* FIRDatabase_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 017FF39FEE7393BA61DE14D73E902FA8 /* FIRDatabase_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 96A0C993563F84620746904C97A55DE6 /* FLevelDBStorageEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E72C91BD55A89072F9977C2F1A152D1 /* FLevelDBStorageEngine.m */; }; + 96DD7F303C2D0A8605B4294F30EDE393 /* dbformat.cc in Sources */ = {isa = PBXBuildFile; fileRef = 34D792D28402E4437C7860AAC976A3A7 /* dbformat.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 977A2BDF4E2F55BEE8A7D29E094FD6E0 /* FWebSocketConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B6742E1E1A93B363D50D9289D741621 /* FWebSocketConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 97B631CEC171F7EF158F229A5C2CA7C2 /* FIRConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C1D2B97EE131D32FFE68B5D4797D618 /* FIRConfiguration.m */; }; + 9845FE55931EFF372DFA1F7131FC2FAD /* log_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 83E6D3617089AEC1DD83534C656365C9 /* log_writer.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 9909838A3051674F444C6A8A23A64284 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CAC4510A566921C9F90A3C21FB371DA /* FIRComponent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 992EB0408FB677ED04369E5AA806F1A9 /* FBLPromise+Always.h in Headers */ = {isa = PBXBuildFile; fileRef = FB8A36424CE63AB822739A749BB71C82 /* FBLPromise+Always.h */; }; + 99B96C475814E67892434BB4236B0545 /* GDTCCTNanopbHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = EBC953A34508AE16186590261C12C687 /* GDTCCTNanopbHelpers.m */; }; + 99BD4AA0965DFAEB48961EED629EBBAB /* GDTCORTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A9A12A16AB2EE91241EFB10A5E623ED /* GDTCORTransformer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9A1BDDF47635DBEA58A6C35A7492B80E /* FBLPromise+Race.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A603CA5B006121B694846787D7BAD9 /* FBLPromise+Race.m */; }; + 9A6631F9BE2D1C8642A54921EB210A4B /* FSyncPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 38BDD50A689DAC3E054B5FD55707AA2F /* FSyncPoint.m */; }; + 9A75B070DA97F71D65FD8CA829F04E2B /* GULReachabilityChecker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 91714649A9785EF95152BD5F0A1B1F45 /* GULReachabilityChecker+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9A979CE5E7B5CC50A899C7806E6CA50D /* GULAppDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 36F6CC5035C5136DAE4AA2DA5F82F358 /* GULAppDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9A9EC7789D5B83042D5CBC34880C0BA0 /* FBLPromise+Testing.h in Headers */ = {isa = PBXBuildFile; fileRef = A51275DED8B5876B1EB201F7E40D4517 /* FBLPromise+Testing.h */; }; + 9AA87747892902F9D2BE78D1405F0102 /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 30663E00087519FA3686DFE7783369E9 /* cache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9AD6029ED89AA028361A0A4A0DAF7E98 /* FIRServerValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 725CAC1516DCD4072C47A01FC5EEE271 /* FIRServerValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9ADC7DFCBEA7BB3394E5F9157191C54F /* FIRInstallationsAPIService.h in Headers */ = {isa = PBXBuildFile; fileRef = 108535B306732FA4B7C62DB68E5B4FF0 /* FIRInstallationsAPIService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9AEF54170F7BD7F27A35B8E230877EAF /* FClock.m in Sources */ = {isa = PBXBuildFile; fileRef = 444973A3DB4BB3F60FCF797B60B726E7 /* FClock.m */; }; + 9B599B5EB8D6C2E97B0A4B7E6B9E2418 /* FPersistenceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 85BFB0EA5C7CE6AD700F7323053A5AB3 /* FPersistenceManager.m */; }; + 9B79B99B4B3CEEB12792BBCD929A10B3 /* FLLRBValueNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F0E17F44674DD5323FABD14840F7D509 /* FLLRBValueNode.m */; }; + 9BA54EC27C0B83C5521AB4AC61FCEC9C /* dbformat.h in Headers */ = {isa = PBXBuildFile; fileRef = 3EEFAECB1EA225E89728D68E7EE8A8A0 /* dbformat.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9BF494DE481214C27A18490564FA62F9 /* write_batch_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = DF667BD0C719334D242C99243B7287FE /* write_batch_internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9CB2F238AB2FB6E3D5B0BD71B0DD9AA1 /* FIRDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 27CEB21BECB905A6D672FCB27BC8D325 /* FIRDatabase.m */; }; + 9CB63266275054887263D021A95BD648 /* FTreeSortedDictionaryEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A6B7D017E8C22F0382985F7884DF8B8 /* FTreeSortedDictionaryEnumerator.m */; }; + 9CD834F1AF935270B890BA341CA08CBB /* FCompoundWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 8625031D0810B04DC3327766C1F960D3 /* FCompoundWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D0A5CCD79BC7F1274940275B524A1B6 /* GDTCORUploadCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 89EFDC2FBFA53532A9CAAEA608E7C222 /* GDTCORUploadCoordinator.m */; }; + 9DA25B2EF34CDA3DEEA777AC54AF9B6E /* FIndexedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = B001400E85F272915939718E17EBFD25 /* FIndexedFilter.m */; }; + 9DD235CBC46DA99444A765A1E299C212 /* FIRMutableData.m in Sources */ = {isa = PBXBuildFile; fileRef = D131FCC82D07749BA8F453BE243E3308 /* FIRMutableData.m */; }; + 9DEF1AE276B2DD9342452E37582698D0 /* FIRInstallationsStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 6597CE9AFDA1AF2FA603A486F757ADCC /* FIRInstallationsStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9E11ECDE24EA28C39FF20042B69C3738 /* GDTCORTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = C9FDFEE5B3671FA221FDBC8ACFFA3041 /* GDTCORTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9EC476993DA7B5AB5152043817A315FD /* GULUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E9F51951C4877C29BD86424B88DBA62 /* GULUserDefaults.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9EE47330FA51209EC3AB5B386B301E09 /* FWriteTree.h in Headers */ = {isa = PBXBuildFile; fileRef = D68AE5E7D4434A5A3C27FE2C33DEF374 /* FWriteTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9EF9F716AFB202E33AF3B0EE68FEA9A2 /* FIRInstanceIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 4891EB1830F4333011011F6DBFE08CA2 /* FIRInstanceIDTokenStore.m */; }; + 9F044ABB685C274B0BC394C5172D6396 /* GDTCOREvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 954224218DA6DB484D27DFDAEF45E7B4 /* GDTCOREvent.m */; }; + 9F0F8AAD6CCBE7182BF318ED1CA88F3F /* FIRDataSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 45A016B308E76BE7B4FEF78FD4654397 /* FIRDataSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F88ED341CFE6C501D0524C0BB885C36 /* FViewCache.h in Headers */ = {isa = PBXBuildFile; fileRef = BF9C8E91EB9306CDE7F9886606461EE0 /* FViewCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9FB86EE0B96D3B5DA2B6E80203DCA4E3 /* c.h in Headers */ = {isa = PBXBuildFile; fileRef = C3731E4990AAEF341E76DB0A3AB7E6B0 /* c.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A00CA354751C5B824D1C4FBC48A46DE0 /* GULNetworkURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A49B8B76E453094FFA6318AAA24AA4EE /* GULNetworkURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A0D51DF76B678A5EDA312BD7B4C19EB6 /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DB8C5BAA46113C178F139DA567DEC18F /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A11271539C8A49D53324308D5D29867F /* FIRInstallationsLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 38F29B71648AE8453095366BF1C520A8 /* FIRInstallationsLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A138F5766F60A8D08498D9E4C6183523 /* FIRInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = BDEAF60599B3C1E34E2CA1FC766785CB /* FIRInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A1420741FBF706E542E2EC84D19D0938 /* GoogleDataTransport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 271E908860FE391339504340784BC551 /* GoogleDataTransport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A15A279420A8705EE038A02827E0CBDD /* FIRBundleUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = A0CBF92D27BF20F0173D84B2D7B5BDB7 /* FIRBundleUtil.m */; }; + A17698BC6EEF1C8B99D51B8A9F260E44 /* FIRDatabaseQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 4245217ADD8651375C7C87461D2BAC11 /* FIRDatabaseQuery.m */; }; + A197A576946A28350D93810CA9590805 /* FSnapshotHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B8BFC8D45246220FC9E22CEC5021251 /* FSnapshotHolder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A1C24EA775DF38CFB1B6C7F53896CECB /* FBLPromise+All.h in Headers */ = {isa = PBXBuildFile; fileRef = 90C235774B7FEFA58692D00424C37A4B /* FBLPromise+All.h */; }; + A21B19FCB0DFABCE9E33BC8C108708F5 /* FChange.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BCD2A51AB838CC30EACE2C5FE09CD59 /* FChange.m */; }; + A231C3D11FEFF60FB796E0318CBD27E0 /* FTuplePathValue.h in Headers */ = {isa = PBXBuildFile; fileRef = F74A247A080EE95B1E78BEB99DA8AAA2 /* FTuplePathValue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A2FE22471CDC277C80E9BB61C6FF513B /* FIRIMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 50223B484C12AFEA943E8C2C1EDCB3EC /* FIRIMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A3A9C4FEC12A11770E8EB2715C47FA40 /* GDTCORStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = C1830DD3C00085399D281E078B5A7CE1 /* GDTCORStorage.m */; }; + A3C87A043886D3BF5ACC8414B77771EE /* FirebaseDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 56DC4A494823934F36EC73C1FCC0EBF4 /* FirebaseDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A433B40763ADD23052776B2808E2F47B /* FIRDiagnosticsData.m in Sources */ = {isa = PBXBuildFile; fileRef = DE49548AE3469F15EC0F3A8E7C0E12CA /* FIRDiagnosticsData.m */; }; + A4D5CFED4998E8124647922CA2F6045A /* GDTCORPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = CD82CF0A8D09569DA4154DBE971388CB /* GDTCORPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A4D9734ACE1883DB16AEF9776C8197F6 /* FPath.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2C02F438734C5492E0887B31D61B29 /* FPath.m */; }; + A4F1F77F509D1EB47AAE79A666BABBBF /* FLimitedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F0CD1B3CF10F405D4D6DCC033E61ACF /* FLimitedFilter.m */; }; + A52B25BEF516CA038540C86CD68B4602 /* FLeafNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6284DEE9BBC353DD2F3E29CFF97AF0EF /* FLeafNode.m */; }; + A56FD686C400F83D7827CA2AE781F2F9 /* FChildrenNode.h in Headers */ = {isa = PBXBuildFile; fileRef = A09D01D4E0A074E9C10E52E070322766 /* FChildrenNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A580D8D31AB1CE2135E12415F6DF4EE3 /* FPersistentConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = E7737C5E82B493FFA4C523BF0F15C33B /* FPersistentConnection.m */; }; + A5D882CD9E5E0B52B0759B783A8402C8 /* GULNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = 32E7893D49BF9AB5CB50A68EC77DF323 /* GULNetwork.m */; }; + A6102533A842F7FCF889738B18425940 /* FIRInstallationsIIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 892DFA98C0B6B4BA1A9DA101054D73CD /* FIRInstallationsIIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A6801ADAA631C909DB0EF52A19E3A2D9 /* FRepo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FB7F5B838DF85F6A767CB414C4359375 /* FRepo_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A6B67E9EB789DEE46ADB74C10AFB81CF /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 9878778F95F524E3A075A234B58960B9 /* FIRInstallationsItem+RegisterInstallationAPI.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A6FD535D1DABEFB37CD9A52052DBBBAD /* GDTCCTPrioritizer.m in Sources */ = {isa = PBXBuildFile; fileRef = A2D7E4828D2181423CA7DD6FA9418C84 /* GDTCCTPrioritizer.m */; }; + A7BA41C74ADD243922D02E12F57C54EF /* GDTCORRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = 832DEDF9B8FB5DB7840D30D124CC4856 /* GDTCORRegistrar.m */; }; + A7CB993D569BC43F150B2DD794A57E76 /* FChildChangeAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EAB5FF47F39A44B872B1E1191579AEA /* FChildChangeAccumulator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A86820C5CD61665C39E4D5D43C65CA8D /* FTupleFirebase.m in Sources */ = {isa = PBXBuildFile; fileRef = B121F2A73420BD133A4CBD674492FC12 /* FTupleFirebase.m */; }; + AA0F319DEAFD81B260F9CA9529F6C60E /* FIRInstallationsAPIService.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA340141092E3961C06B4C346F61E9F /* FIRInstallationsAPIService.m */; }; + AA3BB18CA32179B9E3D0332754DA6FD7 /* GDTCORRegistrar_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CF3E3945EDFC777942BE90AA282A705 /* GDTCORRegistrar_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AA63E624F9FE3BDED9FD586CBBEC6B55 /* FBLPromise+Recover.h in Headers */ = {isa = PBXBuildFile; fileRef = A680F32866E1A09336694B099C04AF81 /* FBLPromise+Recover.h */; }; + AA80ECEF61E729BEB073D1DAB31C395F /* FTupleCallbackStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F2DB045C06893A8DEADE59EA4E7FDF /* FTupleCallbackStatus.m */; }; + AAF40409B6582A25EBF6DDAF248528B1 /* FIRDatabaseComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 156BFD884F1693CF4050DF9EEAE24F4A /* FIRDatabaseComponent.m */; }; + AB21722890ECFBC7FEAACA77CCAAB134 /* NSError+FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = E4573AE1A9FBC7C15F78874BA9847666 /* NSError+FIRInstanceID.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AB6FEE7F98E3F2AC22F81FC98DB4D526 /* FIRInstanceIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BA535C000530A7DB6D708C0024FE808 /* FIRInstanceIDStore.m */; }; + AB973E87F1C50F9A44CE2391340CFB8D /* FirebaseInstanceID-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F459ED3E4C3C9D6C2650EEAF63B3FEDF /* FirebaseInstanceID-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ABBE590B50F0AC97EEA56EA2881486C6 /* FPathIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 199EB0AF8519A748873EAEF746674CAA /* FPathIndex.m */; }; + ABD104FE4926258ACBCA8AF01C763714 /* FWriteRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 911A01616C728841C697AB49826AC324 /* FWriteRecord.m */; }; + ACEE8B9AF12952DFE6883AD1524E1B95 /* FChildChangeAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = A3D64D73BE83CC3A36E53B1E36DC26BE /* FChildChangeAccumulator.m */; }; + AD40351A186EDE06359FE72DE397299A /* GDTCOREvent.h in Headers */ = {isa = PBXBuildFile; fileRef = A9A07FADE7126A2EBA873664735E0563 /* GDTCOREvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AD57DD9E23538462F0324FC0163E4687 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + AE00643A94C60CD83D43060803F6E3A6 /* format.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FE91D249283827126AA99EAB18DC0A /* format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE0E3346877C8D3DDAFE7CE8D0F595F5 /* FEventEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E5C112CB6CC03482709D541E5DF2517 /* FEventEmitter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AE8C52AA4BB23F1700B8423A56460A55 /* leveldb-library-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9857113D2F1E85DDF6449FFE23D64413 /* leveldb-library-dummy.m */; }; + AEB4660C1A1A40DB69A73928D6DC5D7B /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 73F0B382A1404222E1C60352DFF7BB72 /* FIRLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AED6299AF75D2418193FC6B715D97188 /* FBLPromise+Catch.m in Sources */ = {isa = PBXBuildFile; fileRef = 90229CCE5D34D7A531E16765B37ABE39 /* FBLPromise+Catch.m */; }; + AF19EFADE8BE01147CC94A86B4667A83 /* FBLPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B5719CDCE6B2A2F1216F9C92E6D02C8 /* FBLPromise.h */; }; + AF6C482B18C9E693BCBAAF2B4523514D /* log_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4B531F7005792C54B07D84507A34E3AB /* log_reader.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + AFD04677C3352C023D0258FF28F550B7 /* FTreeNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B29E9518D65490F1E33B2B30B23ADCB /* FTreeNode.m */; }; + AFEDA85C2ACE6902C5CA86036E2D1B20 /* FLLRBValueNode.h in Headers */ = {isa = PBXBuildFile; fileRef = F79F298B4FF02587B6E3978DDC7D3FED /* FLLRBValueNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B01B7D75DB7763EA2C3296984C14FF80 /* FIRBundleUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = DFCB1951C0F24D4ACC2A38DAECEA2065 /* FIRBundleUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B0A4CD547FC897EAF040F0BA4678CE52 /* FIRDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 756DE87D6FE64F0049E1627934D587F7 /* FIRDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B109D7D2A695A4E374C1BD28E6C15628 /* FBLPromise+Catch.h in Headers */ = {isa = PBXBuildFile; fileRef = 99CB6929C9B9E330102E12BC10ADBE67 /* FBLPromise+Catch.h */; }; + B120EB6E9B4AAF6673812E04509CC24F /* GULSecureCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 5460CEF22218F0CDDD2B043F5F7855AB /* GULSecureCoding.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B175CAD91120F2AE08446C985E44ECD0 /* FEventGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 782C6082710A31FBBFE0FF40C496D80F /* FEventGenerator.m */; }; + B19F4223C39993C7275EE555162E2180 /* FTupleObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E443A6931785BEEAF7DC2C354926B51 /* FTupleObjects.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B1C9CAF5F65E34EE5B504002C03E9246 /* iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A32910BBD1B9FC60DD70E012F4F8065F /* iterator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B2CA90A68FBE428C49128EAE88BB2AC2 /* FIRAppAssociationRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EA0F7CE6EB64CFF17CB11ABEC8CDF16 /* FIRAppAssociationRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B359866B4F605EE2749F613848029764 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = A2BABC8EE3398D6E3B11BEBB4BDDA527 /* port.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B3C042786A70C2216566529189C6CCA3 /* env.cc in Sources */ = {isa = PBXBuildFile; fileRef = 220B0328CECBE9CE20EC4490CB388622 /* env.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B40ED35DC8F3525BBC9260C97979B9D3 /* leveldb-library-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 205F67811189387CB12408CE5D08FB85 /* leveldb-library-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B49453448E3FA02DF440EFA065B95A38 /* table_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AEFE796A73D36A9215F664981D72C70 /* table_cache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B51FE96C5980296027D229A6080E3FC2 /* NSData+SRB64Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = A236AD4499A5E6DCBA8204CB68484B08 /* NSData+SRB64Additions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B54AAF339502800C6F39457FE3960E31 /* FKeyIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F71B5A123DF00AD98FAF2759DD9F983 /* FKeyIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B55278BC6C9DBFC08FD066AAD693E419 /* FIRCoreDiagnosticsConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = 52041C725712526A753AF310EC5E0271 /* FIRCoreDiagnosticsConnector.m */; }; + B59BF3BADBD587B5AF03B45B57BA926A /* GDTCOREventDataObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A6C32388BA9394C95A78AE1D39EDD150 /* GDTCOREventDataObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B5DFE329CADA639BF99EC0E61E8F36D9 /* FIRInstanceIDLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = EED1AC6242127BDAA6E48B5C7662BA95 /* FIRInstanceIDLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B694024900B3873914C9B5BECA4F2FCC /* GULReachabilityMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 24A02E9A2F6D74E292328F6A46B242A0 /* GULReachabilityMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B716C65DD09AF6E98190284B67A268F7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + B7F1DEB0A7CFC79BCA5D17E4490A732B /* FIRAppAssociationRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D25D46D0D17BB9DBF55A909B2D119F /* FIRAppAssociationRegistration.m */; }; + B82BF56465E4FEA663175FA28A559E80 /* FIRInstanceIDUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F71D48BEB6D4E6FD4232B3FBFE360494 /* FIRInstanceIDUtilities.m */; }; + B848F96AE5C190DE716CB228963F0A22 /* filename.h in Headers */ = {isa = PBXBuildFile; fileRef = 371CBDB9F2F452BB9341C8D0395B8A2E /* filename.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B8736B358DD65B4E7D974BE0A3C19FDB /* coding.h in Headers */ = {isa = PBXBuildFile; fileRef = DF1AE6443E291955DE6DE481F41F5408 /* coding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B889A468E8E56AD353F03BB42B5A7A4F /* testharness.cc in Sources */ = {isa = PBXBuildFile; fileRef = E6C8EE55738FAA4E95659CF5A409F9D9 /* testharness.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B8E9F8BF35F3206D2E807E34BEE29DCE /* FBLPromise+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = 31EB496C4974C87B5DD9A5C3D20FA2C7 /* FBLPromise+Testing.m */; }; + B950E749FC38D40DA5F0E41AA70AD644 /* FirebaseInstallations-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FA7F98EE4D30B47DE6F7455BC33991D /* FirebaseInstallations-dummy.m */; }; + B9B9A35BC327CD12D2EA39A732385060 /* FBLPromise+Wrap.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 57018189681D84C262FEFABC79A46C04 /* FBLPromise+Wrap.h */; }; + BA1C29BA7381A7A52D09622981A8E6B2 /* builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 47DD04AD61421A996DEAE095AA51E77F /* builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + BA6597B1BC8ACF9295CE01AFCF4C7F7B /* FIRInstanceIDTokenOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 12478891F3E769E22DD83E49512CD0F2 /* FIRInstanceIDTokenOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BA81227041AB29C9C59B46E2AD30CF5C /* APLevelDB.h in Headers */ = {isa = PBXBuildFile; fileRef = C2718A77E9D1B7AAB8B1E89B2B9AD22D /* APLevelDB.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BB31A0898441B79D97551F92DA331318 /* FIRComponentContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 54475272A64C46FD9B044CD0B03D1F16 /* FIRComponentContainer.m */; }; + BB7267913ABFB33F15AAC006C881A596 /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 06023D1734B2E0EC0F1A8AFA0E532F6F /* NSData+SRB64Additions.m */; }; + BBC0AACCCDBBC8CA76718C2EE0E1E44A /* FEventGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = D64EAECB9AE75FAD65FC8D0B02422580 /* FEventGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC71D66AA194EABC5188F55A969EDA43 /* FEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = E5D99095828A99E2D1AC9636C56E65CC /* FEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC94EE9013468F13B1EFC548E5C02FA1 /* FTupleFirebase.h in Headers */ = {isa = PBXBuildFile; fileRef = B922785EA83E6FEB9DA16973EBF01646 /* FTupleFirebase.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BD3C303BC87D428AFA1679E509C40962 /* GDTCORPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = EBDC269E1E8CFA6578C1F1FC4F7C4728 /* GDTCORPlatform.m */; }; + BD422B9575A29EB2217618E12CA084CD /* FBLPromise+Reduce.h in Headers */ = {isa = PBXBuildFile; fileRef = D90F32A060B026F6D87B7D74D28DC97C /* FBLPromise+Reduce.h */; }; + BD826E7437E5D46F55E6B115FF4C22B1 /* FIndexedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = FBC8005390271EA0A8E1814D471860C1 /* FIndexedNode.m */; }; + BDFBF6C03DA9FDA91EFDB3E73C4FBFB1 /* arena.cc in Sources */ = {isa = PBXBuildFile; fileRef = 0994919D6FF1636BBE1892696E9DA4A2 /* arena.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + BE4DB0ECDCB7C539FA09D6ADD1D14D2E /* FRangedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 45FCEB89C8FEB1D4760D9155DC0E584C /* FRangedFilter.m */; }; + BE63D66EDC0CF985AADC754E638E1B27 /* GULLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 6362D3C5139CB0F2ADC38869A8AF6338 /* GULLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BE6F9C947012AC55EF5F579DE446596E /* status.cc in Sources */ = {isa = PBXBuildFile; fileRef = D4B8BE02734895C466C402F08AFCFE27 /* status.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + BE896A5DDFD39DBEEDE89C02C6D2E4FC /* FMaxNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 60674E85B85501474862591F4FFCEF7E /* FMaxNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BEB2433EE42F253066747816CE237BBB /* GDTCORUploadPackage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 89D3EEC62CA2D9B28936A1B89A9733C8 /* GDTCORUploadPackage_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BFA8341CD1440D5ADBD440B26C8076B9 /* GULHeartbeatDateStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 67373B6F54F16182D369B74E58D5F536 /* GULHeartbeatDateStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BFFAA2BE866BF90941ABEA5E71037B9B /* GDTCORTransformer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 483ED7857A31966E18E87385A1A58AD8 /* GDTCORTransformer_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C0083E25EC2B54DC6F3F0615958F4B1F /* histogram.cc in Sources */ = {isa = PBXBuildFile; fileRef = 6BA701D49705278AE2504369CB8FCBB3 /* histogram.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + C04BC8EBF1E3A0C816AB8BFB7694AB82 /* FTrackedQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 14494CAC35D8D269643EA5CB8934BF45 /* FTrackedQuery.m */; }; + C0A3AE805627AEE1EEA1CA4B975C8CDE /* no_destructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 6132BBDB4E6F8E0B4E9B5E3C9850E8DE /* no_destructor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C12EB6D2E322D9664BBD627B922E960D /* GDTCCTCompressionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CD37FD280133AB42ABA89D293273149 /* GDTCCTCompressionHelper.m */; }; + C183F302CB97260A6AA2C8DE557EF956 /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = B880DC9BE4C9FE6FDA8BF6D351C8595A /* random.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C22660680F678BC5FE5331F25B2E86D6 /* FConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 09DE94F55E8798B33321639491D9EFC6 /* FConnection.m */; }; + C26A8673C32726942B774BA1FD2BFD6D /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 2387E0CA88C9075A7D7612E4CA20875F /* pb_encode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + C3B70F07EFE4F953953E203FD3AC47B0 /* FIRConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F42AC0B1D0F68847E4A548E94AD9268 /* FIRConfigurationInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C41A7FDD9E0A7FE8D6CA954594939E00 /* FIRInstanceIDAuthKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = D54A5395DBB67ECB6B503D7CCDCAE2A3 /* FIRInstanceIDAuthKeyChain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C46AB2F9D6A7C9DF279E7A635CE1AD5C /* log_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0640ADF2E74C8DFB07534BE9B3BBAD /* log_writer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C58F38BE65DA76A0B8C6DA31E6E43B2E /* filter_policy.h in Headers */ = {isa = PBXBuildFile; fileRef = 560FEF99670CDFC70E4F9F5F8268CFF7 /* filter_policy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C663FCE8963BFA8E0CBE7503FD659760 /* FOverwrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E67DE3F4605BE94ED95546F293188D3 /* FOverwrite.m */; }; + C751BB8850702F0799370D6437A38A5D /* FView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C2D17D624A2FB0F013DC69FEE7F9531 /* FView.m */; }; + C77963B29BF253A51295B5759F0FEC3F /* FirebaseInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = 77CBE6E614F5EBEABF6E32AB2EAA8A52 /* FirebaseInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C83DB743E6A963EF7CFD94C23A2B2124 /* GDTCORTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 61902C839F537E39C79EBD06E14DD2C4 /* GDTCORTransport.m */; }; + C84A2B8C7FC45AE4AE0FFF312F866AF6 /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = A3C2A80012BC975B349FB09DA77B8850 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C98328C34C776617F077E50D7DDCEE35 /* GULUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = CF0903B3B61A95E960B197B8585D0B44 /* GULUserDefaults.m */; }; + CA49350D90B4A272890D567E817134A1 /* GoogleDataTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = FC08F6EF38191BE8F7E4F4CF74AF46C2 /* GoogleDataTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CAB5ED5AF21CB3DD3C96A76C2FD37BF9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + CB73D4286965C2A7A8F732E8BD3BF5E6 /* builder.h in Headers */ = {isa = PBXBuildFile; fileRef = 687462B2466B5822E171E11E94D99E9F /* builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CC187C6A88BE4B72F318125E1F36DB9F /* options.cc in Sources */ = {isa = PBXBuildFile; fileRef = BBEA5A247884A7C3F759610363D9FD71 /* options.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + CC4509E5F4073C7ADBC9D40396CDA58B /* FIRRetryHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F757C6CD54BFEF3CFB0766836A5F414 /* FIRRetryHelper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CCB8E583CA5F3953D0E5BFEE2E350A8D /* FTupleStringNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 14767AA509DD2B355C7598A3E158E242 /* FTupleStringNode.m */; }; + CD1F27DA93DD3248CCD6D4C074F00F0B /* pb_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = E337B401A2FCBCB3359E2A38291B7B4F /* pb_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDB3CFF531DAF96C8551FBB1B4CE58E3 /* status.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D5175073773047C9EBB484D43935067 /* status.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CDE0196E899CC7D402DF1102115E4C0A /* FBLPromise+Await.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E620741BA858DAFC95CA5490B42CB4B /* FBLPromise+Await.m */; }; + CDE1E9926CFB694F40C1E2FA5D3161CE /* port_stdcxx.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F51779B334E9D371C089C2D84A4C309 /* port_stdcxx.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CED64AD03A2C96DE7DDB42735483808B /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = FFD1A868DDA411E233111E156FB11FAD /* FIRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + CEE94B65B2B0DD84E6286E114C15A000 /* FIRInstanceIDBackupExcludedPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F58773864AC25F46EB2AA354F987C57 /* FIRInstanceIDBackupExcludedPlist.m */; }; + CF503615323A99589846E4E202EDC060 /* FIRInstallationsAuthTokenResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CDF3A3DACF1F0F35334E584A81142A8 /* FIRInstallationsAuthTokenResultInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CF6AC92992AA1428D74B4A4A98B5F17B /* FTupleObjectNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 181E3F131300BC5D6914C8698DBFFEFD /* FTupleObjectNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CF7797BD4D4295C41355DA0C8E13A118 /* GULAppEnvironmentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C251CBEB0F513BF966974089FB9C542 /* GULAppEnvironmentUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + CF86354528716B46ACC9AFE6FCD90025 /* arena.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A48322D21C211FB16E7DB64E6B5AB6E /* arena.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D0798123D484EA3D9DD80C21DE672FB3 /* GDTCORStorage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EA45B5C00F15C4CCF12F75EEA5288FA /* GDTCORStorage_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D0F5342589821DF33F6A14D99A906CCE /* FIRInstanceID+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F197642A1C79AF964CAAA015E860AC3 /* FIRInstanceID+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D1019928427B03120CDA22A4DDB3416A /* FIRInstanceIDAuthService.m in Sources */ = {isa = PBXBuildFile; fileRef = C8B01D89754271F61E72A781D8CE2571 /* FIRInstanceIDAuthService.m */; }; + D1D4A221AF823CB0B3200E50B460462C /* FRepo.m in Sources */ = {isa = PBXBuildFile; fileRef = BAD71520F0592D6FFF74F12C378D529F /* FRepo.m */; }; + D1FEDD3F09D5720913C1A26ABDC691EF /* FLLRBEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E61B1F736CF3923FDCC8C3E49CA7E3E /* FLLRBEmptyNode.m */; }; + D22DA4596686C8BB2B7769D432743ABA /* FBLPromise+Always.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E7463DD70BAEAA5C553A05777352958 /* FBLPromise+Always.m */; }; + D37E73F03077BA5CFBC58965DDF89E80 /* FCacheNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 64DE81935684B37F8499BD626088D702 /* FCacheNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D39B5FF909B620DE847ED31168A6FC2F /* env_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = F8FAAC19C9BC593A8592BFA3F979E482 /* env_posix.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D4DA2E39C21EAFFAF70A67F1DF7DE018 /* Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 72D52576F67BF816A679DF6B1DDBFB79 /* Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m */; }; + D5AEF294389709ECF3AC35A4EB868F74 /* FRepoInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD1150B6BD9EFAE172F16CD4B82379A /* FRepoInfo.m */; }; + D643135906372122446C44E57884193B /* memtable.cc in Sources */ = {isa = PBXBuildFile; fileRef = 35E008788331AAF58516A9A5082B6334 /* memtable.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D67161BBCAF4CBE6CB2AFD3040584C4E /* dumpfile.h in Headers */ = {isa = PBXBuildFile; fileRef = E45F8CF91067F02738B6EA753E318E1E /* dumpfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D6B9D7A2DFA77050AD5CFF09CFFE75FA /* FirebaseCoreDiagnostics-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = FC13A073E2E6654C9515F95CD5BAC0E8 /* FirebaseCoreDiagnostics-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D6E03D071285D729E25229B2C668C2C6 /* GoogleDataTransport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B1ED778C9852BEF45C9DB36A28CC3F74 /* GoogleDataTransport-dummy.m */; }; + D6FB5EAE6DA7E3D7BA463BC4B50C9EC0 /* FIRDatabaseConfig_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CE70B8F0872CD5F6701BE7EE2B37F8E8 /* FIRDatabaseConfig_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D86B30E9596A9BC61958788C91F5F50A /* FIRInstanceIDKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 59393315B83DEB88FEAFAE711D920582 /* FIRInstanceIDKeychain.m */; }; + D86E06A60351F43DD7880CF935A31683 /* thread_annotations.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B4E576722528645372A7E3DABD88704 /* thread_annotations.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D877459D45EEBDAB1E2D149E52DC34F0 /* FMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9061DB724B0A4703E5CFCB88C87A4A /* FMerge.m */; }; + D8AB19E0518BB4BC5276C2DF9357E982 /* FIRInstanceIDTokenOperation+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E3CBD22B698222D11A402DA18253A70 /* FIRInstanceIDTokenOperation+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D8AB4C4B61FB111307EEC525C7BA7083 /* FSRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CA1876DE760D48C7C370BC1CB02071A /* FSRWebSocket.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D8BE368CE172CD2E06EEB5C1A98AD707 /* FTupleSetIdPath.m in Sources */ = {isa = PBXBuildFile; fileRef = AE0CD47B189B10242AD0B8643930F413 /* FTupleSetIdPath.m */; }; + D9800CEE2FBF66C326E6E78A90A84EDB /* FTupleBoolBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FAAC0625B206D4D02719ABD6BAC099 /* FTupleBoolBlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DA3CB05AFFF892FE3B1433ADB6B64A42 /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = 2CCEBF3760A2D010F801CCCF4EF351A8 /* pb_decode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + DA4B9607E3EAD4183AEE60CBC133AD75 /* FIRSecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 33238801326949DAC00EC88289C9E167 /* FIRSecureStorage.m */; }; + DADF5C8F6686404E5C704C8B0B154B70 /* FTupleOnDisconnect.h in Headers */ = {isa = PBXBuildFile; fileRef = FB991BB4D89DAB85EDF7100FBAFA1A13 /* FTupleOnDisconnect.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DB3F17AD95C07E11740436162B8720BC /* filter_block.h in Headers */ = {isa = PBXBuildFile; fileRef = C7DEE606CBB9A67C91F550224BCB72D8 /* filter_block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DB47E56AE089298BE3E3095055C3A120 /* FBLPromise+Do.m in Sources */ = {isa = PBXBuildFile; fileRef = 1321F309AB4B1BB45EEC3789A76939DA /* FBLPromise+Do.m */; }; + DBC33C39A9ABFDCFBD370F4E354CBCE9 /* cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 448011007D98317BF4F7C1098DC99366 /* cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + DCC34F4CC38D374C98B5D07038E9E061 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + DD0D2B219445705DFFEC30E53B90CE3B /* FRangeMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = 903B2BDF7FCE5660EC3EF7289DAFB10E /* FRangeMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DD16D5A7EB3F4B888F5D6863A3CBC520 /* FTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 768C30DB00B3D3283040ADCD760D66B2 /* FTree.m */; }; + DDC5BA7722D5AA379459704FBBE3513E /* GDTCORReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A06B13C9427E8DC216B2155A9A4C51 /* GDTCORReachability.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DE2CFDFAE25548213B8540ED406A1120 /* FView.h in Headers */ = {isa = PBXBuildFile; fileRef = 84AB4D11B745E92F4CDD206AFE2E0660 /* FView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DE5F44DAECF248CE9C781B2C1E462F75 /* FQuerySpec.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EA7330D3CB1E19057AB60A9618336C8 /* FQuerySpec.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DF51C380D05B32F3FC8B69D3096A0D98 /* FTreeSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = B7EC032D36A1A28E006B92BAF996CC3E /* FTreeSortedDictionary.m */; }; + DF55CC21D55E0C4FCF28F49DA032AC4A /* FIRMutableData.h in Headers */ = {isa = PBXBuildFile; fileRef = B8EAECB74DB46EE2F89DFCA3A335276C /* FIRMutableData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DFC90DAF4138CC9B0FDBA54D1E4BA4EC /* FViewProcessorResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 9508F4557EAC2FA9BC5AE4521AE1415A /* FViewProcessorResult.m */; }; + DFEC09AD2041549CB68FD873BA3BD35D /* FValueEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD615F709C03B469833C0AD4EC286D9 /* FValueEventRegistration.m */; }; + E0AD22194E0117CE517A6DDFC7EA3649 /* FParsedUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 22745D074BDC5C547FA32DCF913B5ED6 /* FParsedUrl.m */; }; + E1DDF9D8AA9539216D0B192D480B0DF3 /* FIRDatabaseQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = FEF9959C504C1429615F19DA2FA0DF5F /* FIRDatabaseQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E22804F8B066EE82FFF359DB2D60FCC6 /* block_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = CAD8EC4ABB74DAEA13817229074C883F /* block_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E23D13EB8979456AE2CA5809A28CA6D5 /* firebasecore.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = D162B1331B24ACB706028A659E347607 /* firebasecore.nanopb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E27BF263AA7947104D42690CB618C55C /* FIRInstallationsStoredAuthToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E01539529DD344C874CC0055A2F12BE /* FIRInstallationsStoredAuthToken.m */; }; + E35D6EFB453EB460D8A523FE4E0B3F38 /* FIRDataEventType.h in Headers */ = {isa = PBXBuildFile; fileRef = ADE3D3BC42C093C1B8BBB0454B40B83E /* FIRDataEventType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E3C9B29A2D69D6BABC0CA201BD468665 /* FPendingPut.h in Headers */ = {isa = PBXBuildFile; fileRef = CB8195D549670F26815B3858895AC0DD /* FPendingPut.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E4E7BA8B1B6890D1F626D48424D6AE38 /* FIRInstanceIDCheckinPreferences_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 20E2602A98267FAC13549447297B1CF6 /* FIRInstanceIDCheckinPreferences_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E6330EB50A0B5F249B737153EB619465 /* FSRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F5AF25E215A81CF2173475193C34EB0 /* FSRWebSocket.m */; }; + E688DCDF4BDA185BDAF4895EDA15C78A /* log_format.h in Headers */ = {isa = PBXBuildFile; fileRef = 25CDFCEB95D5E7B062D672C75F8ECBD5 /* log_format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E6C65AF381AE066080720D0D04A3F5EC /* GoogleDataTransportCCTSupport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4141BEDF9F22F8F20F34FBEC3C8754A1 /* GoogleDataTransportCCTSupport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E6EF7C214F730588B9E93A2C319AC9E4 /* FTrackedQueryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = B61358592FDB40CF8A657BFD252B3416 /* FTrackedQueryManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E7294BFB81C9230F1F3F709A75B7BC66 /* FBLPromise+Recover.m in Sources */ = {isa = PBXBuildFile; fileRef = EC6076EA5FF19E6726A6FEB3836F7451 /* FBLPromise+Recover.m */; }; + E7A3BF0D4825F31F00C515FA1BF1049B /* GDTCORConsoleLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = FE8952D00BD256B9079E38ED3637F926 /* GDTCORConsoleLogger.m */; }; + E7B214D43C6DFF40B8062BCE77FFBB4B /* FBLPromise+Catch.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 99CB6929C9B9E330102E12BC10ADBE67 /* FBLPromise+Catch.h */; }; + E7EF884C02037AE839574120C4768FAC /* log_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = 416C805A18279EC4D3465411DD4D472E /* log_reader.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E7F131F127CAC8569841468FF5899DB5 /* GULSceneDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 48D577F0C8A3766C9F607FEB903B8660 /* GULSceneDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E8AC86C0D05DA3F36759612843B60FA9 /* FIRInstanceIDCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = F3959B61A1A4E4F8AE1134134BC3F7B1 /* FIRInstanceIDCheckinService.m */; }; + E8E039615A0EE503F1BF21AB15A89C82 /* version_set.cc in Sources */ = {isa = PBXBuildFile; fileRef = B7B9AFFBA75FF2D8A831275F9A83318F /* version_set.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E986ED3BC90614CFA3534C6BA1058EA0 /* FIRDatabaseReference_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7213970830A3E5E01229377CCD602D /* FIRDatabaseReference_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E9EF5B931F4D833CB15D9211E4AA2D50 /* FSyncPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 05801D5FF061F264B1CE44110016F58F /* FSyncPoint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA3F2D65D8B8D3075E037ED5706AD660 /* fbase64.h in Headers */ = {isa = PBXBuildFile; fileRef = 98306E8E1C87D94B702DACAAB6768B53 /* fbase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EAB7C94331469362F19A16C3D03A2B19 /* FDataEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = EA4707415187157C356E56CCEAB4A5B4 /* FDataEvent.m */; }; + EAF532BDB50195BDAF699D5317AE2C53 /* FIRInstallationsSingleOperationPromiseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 73C3A2B897419E5CB0BA2CB0D02C24CB /* FIRInstallationsSingleOperationPromiseCache.m */; }; + EB3720D59974F576ADCF3449D97795D6 /* FTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E21DCEE277E88B08FB8F3329FD5F48A /* FTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EB9CD95B07AAD3C35FB2E300BED18C59 /* FIRInstallationsIIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = CDD59F6FF7CD1CF4D22C5C4DD5A519F3 /* FIRInstallationsIIDStore.m */; }; + EC1982A7AFA80D6175FBDF2F2B5510A9 /* FIRInstallationsKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FADF1444F7ACFA3CDAF40D40C22292A /* FIRInstallationsKeychainUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EC42C06469C51FF4C436869FC638A270 /* GDTCORRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = B833EBA86E1C3BE131AB895BCDE61AA1 /* GDTCORRegistrar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECDE82202A3862051B9B7CB6D5B4E3FC /* FPriorityIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 84105C2E03C766F137C523748AFABA19 /* FPriorityIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ED38DE7518BE3172FE57374616F3EA97 /* FBLPromiseError.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DA049BCB41CCA3C4CC0998EE845FC32 /* FBLPromiseError.h */; }; + ED6EBC6B0D6818AE784AEF5DACCF1CB8 /* FBLPromise+Retry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6219B0FFB8044BA7B94076BAB77DB1D3 /* FBLPromise+Retry.m */; }; + EE066EED402B361F7BB6FEA5EA25FA91 /* FPruneForest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62BA41319E7AA21A5F414BB6901E2EAA /* FPruneForest.m */; }; + EE676F7DB6F01DF5BB726B0B49B09D60 /* FRangedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = D887D5D2E2B630D2E0ECB4034734F45A /* FRangedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EED9CB4174EAF0FDECF0515A3567C9F3 /* FIRInstanceIDTokenInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = E7431CBAB5161E552D3F5FD4A6A4B48C /* FIRInstanceIDTokenInfo.m */; }; + EF16144559221600FFB4A709DA70DC09 /* version_edit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E2242D1AEC32106B5EC1B6007F11512 /* version_edit.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F01A6B9A1243C34DA764908E9BC2552C /* two_level_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6C3EBCD2C9B78F9071C9BA34584A60 /* two_level_iterator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F099CB27DAFA4893909B6955263235EA /* FWriteTreeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 3732562635D3675F3AC5870C2EA64563 /* FWriteTreeRef.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F14E4F88AC46BE87F1AA30D7DAACD352 /* FEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 6007C861D262EE9CFD533D5392F386E8 /* FEmptyNode.m */; }; + F171CCA20D1D69E03EB49FFBD519238C /* FTupleCallbackStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = BE12109DCA730DE54BFFE4D8BAAD3272 /* FTupleCallbackStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F17ECD4A234169F69D7132C3EDF1DEE5 /* FBLPromise+Retry.h in Headers */ = {isa = PBXBuildFile; fileRef = F10C76FEC7DE64107890BCD0E69DE428 /* FBLPromise+Retry.h */; }; + F195966D55C322389496205A7E7C10ED /* FWriteTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 61F7711DCE64F1713DFA6FCCC11690C8 /* FWriteTree.m */; }; + F1C0B322C183AE921828174D35466A4A /* FIRInstanceIDURLQueryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 98C983DA955E0638D50257AEF6623BC4 /* FIRInstanceIDURLQueryItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F1CF64AB22A45DD7A4ACCF5B6D5CFAA5 /* FChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 064118602FB22DFA8143649846D646DD /* FChange.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F1D455C68A9B476EFF47977B6ECC54ED /* FIRRetryHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7733F0D190599F8D103BA7AC9BF61FB2 /* FIRRetryHelper.m */; }; + F20E8DA6C901C65A0BD86B872BEC2DC4 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E32B2315E2CC544C7D95BA6F99EC432 /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F259FC486D219CCF52DE0760C24C8363 /* GoogleDataTransportCCTSupport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E0234DBF69A61BF3660F4C6F95F41E80 /* GoogleDataTransportCCTSupport-dummy.m */; }; + F261DF6379AD624C530E8AFE2326CDE9 /* FTupleUserCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 41C1F0E633134DD86A4BD84D71BFC499 /* FTupleUserCallback.m */; }; + F2A624FF84956172105446D07DE074FF /* FIRInstanceIDTokenInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F1E98655F6E57D3EBFA5F4C3BFD52EEB /* FIRInstanceIDTokenInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F2FE0C3C57205C18F4A06AC4291717B3 /* FWebSocketConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = A9364051DE6DB776B1CFB70C96D51F3A /* FWebSocketConnection.m */; }; + F39CD698A419074BC74CF01175D286E1 /* FBLPromise+Timeout.m in Sources */ = {isa = PBXBuildFile; fileRef = FBBACCFC3B4FD853FC952CC223D94ED0 /* FBLPromise+Timeout.m */; }; + F456D94FB73E2B1813F015710FC9D7FF /* block_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = F61EB68986A7759962C52C309AF151B2 /* block_builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F4B8EC1DADBE0FC6199486B0B926B1DA /* FirebaseCoreDiagnostics-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B475A67F01481B39D7F5EBD1FADD957 /* FirebaseCoreDiagnostics-dummy.m */; }; + F4D11903D0482C4B89BF1AFA5764EBEF /* FBLPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FD52FD8826F32BA541D72467BE7B21B /* FBLPromise.m */; }; + F50E434C7DDA75507CC632B0AD9FA9E9 /* Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BA7A11DD2C5A7EB1CBDB888741E122AF /* Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F519E6BF09016D910B15D8D98F02E8DC /* FirebaseCore-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D0D828D2BA50C9617AE06268B44A354 /* FirebaseCore-dummy.m */; }; + F5BD8C8AD011B82A642571F8C2704EE1 /* GULLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = A1045E08CCC93351443EF0041C65E071 /* GULLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F6A82FE7D50B0D1B89714BE51CA9C0DF /* FTupleNodePath.m in Sources */ = {isa = PBXBuildFile; fileRef = FDE125C0FE65AF0DB95E2AE362D9BE5B /* FTupleNodePath.m */; }; + F77DFDE1967EE41BBA0FFB375FDCB21B /* FBLPromise+Wrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 57018189681D84C262FEFABC79A46C04 /* FBLPromise+Wrap.h */; }; + FA0C467B67A198087FB902188804E853 /* FIRInstanceIDDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AD1456814B75D3A95FA64D7320BA8CC /* FIRInstanceIDDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FA2B48FB9EC42F6DB921371DA2C78828 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7498B69B8CAE5DD507C2F5F97F17CE08 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FA42C8426D72EA20F0E1DCED5E79F2FF /* write_batch.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B8FA4B0B8B53577758148C4B29CB05F /* write_batch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FA8EDE1CAC8FD33B9CDB16C6EC60814E /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 8320D8163EAA29B0F855EB271690E30F /* pb_common.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc -fno-objc-arc"; }; }; + FB39F2E1BD5DF5585E3CED648A1A7022 /* FMaxNode.m in Sources */ = {isa = PBXBuildFile; fileRef = E26C56006D98BED71A283F0AC2E12786 /* FMaxNode.m */; }; + FBDDD54632922897706042348C5264B0 /* FChildEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = E5508FE08B3CA077BE34943206E069B5 /* FChildEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FBF07D649518FB33E6E57ED937D4138A /* FSnapshotUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EDC2B524719FB084B2E682316BE65C /* FSnapshotUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FC59BACAD99E5424954E9281DCDEB028 /* FOperationSource.h in Headers */ = {isa = PBXBuildFile; fileRef = EC3E044ABC83D63EDD13785CC93A4B4A /* FOperationSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FC64278EBB2D553FA002035E06834E7C /* FIRDatabaseConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 37680EC5B6E6AB38998D8F2E60743D0B /* FIRDatabaseConfig.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FCAD17281B08C0CAEF51C89DFF306766 /* FRepoManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1588032FA5B9336704BAFFEA1C7E2FCE /* FRepoManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FCC5E382E981CF1B5FFE9813E0FE0250 /* FBLPromise+Async.m in Sources */ = {isa = PBXBuildFile; fileRef = F4F07B58CF53D2FCABD8B03E53455CE5 /* FBLPromise+Async.m */; }; + FD0E361D9C432483D23BD8FE51271A1F /* FNamedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 540836500C5F901B23F465C564B553C2 /* FNamedNode.m */; }; + FD9ACE888DA2168238688C213668BB05 /* FQuerySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 2034D03795150369FA9B06580B7517F7 /* FQuerySpec.m */; }; + FDE96333ADA56EDF32AA11220073E35D /* merger.h in Headers */ = {isa = PBXBuildFile; fileRef = 19C7D0C7517E9CAF071A59368C48A735 /* merger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FE292D46FC3D91B1471CEBB770AED860 /* FIRConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = E0C3B65AB5EB25B07B491A17C3CBDACB /* FIRConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FE99F20F6F9985221393A13ACFF850CC /* FIRInstallationsHTTPError.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D66A0887A41593C21A1C19F871DD901 /* FIRInstallationsHTTPError.m */; }; + FECEF5ADD8A45941A91DCCE5BD0E5087 /* FRangeMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = FFA9F0218DE9786B2346ABEDC657B815 /* FRangeMerge.m */; }; + FEF0C471E46E7016F356300F587C60C6 /* FIRInstallationsIIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 594443A20669265EDD8B986F8494B7C1 /* FIRInstallationsIIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FEFF99D7C71855800215B7CF93878B2C /* version_edit.cc in Sources */ = {isa = PBXBuildFile; fileRef = C6F3604157287623FC134D9C84D970BF /* version_edit.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + FF0129B4B2CC30780B422D399C2D351B /* FIRDatabaseConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AA212DD1CD76575F40EB8CABCA92FF1A /* FIRDatabaseConfig.m */; }; + FF2B2C133B5DD5F5AB0A75483F35B5EE /* FIRDatabaseReference.m in Sources */ = {isa = PBXBuildFile; fileRef = ACF43B6D0673E47C821DE97D5D2237CB /* FIRDatabaseReference.m */; }; + FF313F9C558D47363F41404E308713E1 /* FIRInstallationsHTTPError.h in Headers */ = {isa = PBXBuildFile; fileRef = D23943CEFBF68D1DA83A20CA208EE0D0 /* FIRInstallationsHTTPError.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FF68D5CBACC4F96B50387F3FEC9C0C84 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + FFDA6E8C874151778929453550A2A0CB /* GULNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = 10DECCDC1A8262E47115B287809143A7 /* GULNSData+zlib.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0144F5CACFD77356E43678B3FAE334FA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + 01C3D6F90D5CFE8B3F61DB9064D8DD94 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + 01DD8A646592BAA427E2EFF7F4F38B96 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 04F55738408FF0B3986DFC0CEFCC0043 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 0B1562EB2F2DBE0977EC05D8EC9CEBF9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + 0B7842CD919BEA86E41C5EA382BD9695 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + 0E1817B5AF7C26EDA3F32C76520A5117 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + 135574C1AC9B96C13F65DA376FA66ECB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + 1D5B95B2076D719B64A22444A521AE8D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 224878850BC853E940428569925BADD2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 25D8491B094007D1503A22D44A6AF8DF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 298F4CE8468DC4D69441012A13756B9A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + 2B936F10D58E10DC3BA3305120F31349 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 306F3643D17DC54C17E825B313DFC5A3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 30FE43B1567CF74AF6456BE5707316D0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 336A7EACA49FB1B8D7C3E265EE7EB0C6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + 371FF20F62038C2EA1489358A3341E0B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 477FE2FAD124CFD3151D0C58A5246FBD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 4A54388B54F2980C54C8E656A9B416CE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + 5197DC46CE5C1E0A2A35C9E3C05BA05F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 542F1DE0BF918C2EFC3B5EF9FEC93711 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 55DF0DD9BBEC9E654F05912E546E3FEA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + 5DAB5E2BA4DB163CEC1881FA1CF2B311 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 613F80DEF8505BEE8F168AE00B0A344A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 618456ACDB574AF051E97F34159722B1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 61CF77C232064A77915FDAF556BD3780 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 65D7363EBCE24720C7A576693856A663 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + 67664D372030762D2683EC54CAF48029 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + 676814A783F3923FBCA272BD787789B9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8A7E9E78EB0B7B5A38DBA30283079B9F; + remoteInfo = "Pods-PediatricPancreas"; + }; + 67DDAB29B20A0AC750DC1D391A2564D9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 68E4BD480814634B9F76A9EE24FFE617 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 6ACC2C1E104C5C879107CA9F53EE5F6F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 7190AB6B712F20360B7FC488CF4516DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + 7CBBE25681088124AF83361708BEBE9F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + 8010D3FBC1FB35FD88AB6285A82CB373 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 821F6A6BD3EEB8DC5EDB2552B7AD76E9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 8226E03D7C24AECFE91CB84CCEC6831B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 86294ABE4F8ABF6D8CAA0C2AB8A712D1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + 8AAE3563786DF886A389110F2E837794 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 8B9DBD04238080114146BEF8EE130975 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 8CB50BF08D8BB29322EBC81643A8EFA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 94383ED2A49C303C28844CEA3D754E5D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 9635B8090E964ADEFD5BB3219470C388 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + 9D7A685459C8A2DD0A08EA7C402C391B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + A0F0437B6668EAAFC28E758C26E756D3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + B1D1DEEA5D63E4D75CFF546F3F83DA46 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + B1D879E56B8975E2D0F855D3AF60A7FA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + B31E14489793CB24F96924F288B4B307 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + B3F265E60F142AF26A2E9F37D6AF3FBA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + B521A4436617C9306BC6510C1E1E4E47 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + C2E208823F026C7D492A8D5AACE76E18 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + CDF422BBF53A976E3240A02AC581F2DD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + D25E1B89D7A51ECE955BCC5D1CE27FF2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + D35FD17C818961EC9C90DB83F6CEFDDD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + DC5319A4FA6ED9BF675397886D49C86D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + E8878B5BF04A719823FA1A33FCF7DA12 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + EA2ED1A2B35D5E2B0B1CDF0D72F33C92 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + F2FDFFB0AF4F2605D7656D95768757D9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + F572B46CD233D12F42888F1D2FD23CA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + FD191C31AEB003D245EF173182D85974 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + FDBD5C32BF0821031B12D52C27BB6437 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 90341189EAFB3E7577366457746B55C4 /* Copy . Private Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PRIVATE_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + 240D90495B7E45169CD3835E05512B21 /* FBLPromisePrivate.h in Copy . Private Headers */, + ); + name = "Copy . Private Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; + A3D1FF1B28B92965F930693E26704E92 /* Copy . Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + 195CB37779AABA083FB30D80D4000651 /* FBLPromise+All.h in Copy . Public Headers */, + 63B505F0D182477E19F4155AB797A8DC /* FBLPromise+Always.h in Copy . Public Headers */, + 47735DF27A3BC5E368CEA1586232FB3E /* FBLPromise+Any.h in Copy . Public Headers */, + 06E4D83044D85D240C9388809944C6C6 /* FBLPromise+Async.h in Copy . Public Headers */, + 38D345C64A36B3C9EB2AAC69906CAF27 /* FBLPromise+Await.h in Copy . Public Headers */, + E7B214D43C6DFF40B8062BCE77FFBB4B /* FBLPromise+Catch.h in Copy . Public Headers */, + 0C2D81BD99725431007AC6CF94264D1C /* FBLPromise+Delay.h in Copy . Public Headers */, + 7D9056D2435322919EABCFA398BC86A4 /* FBLPromise+Do.h in Copy . Public Headers */, + 65F1C5585A06E9F3A63A2527509AB776 /* FBLPromise+Race.h in Copy . Public Headers */, + 564A2437B3F4348585F16872DD3A18CF /* FBLPromise+Recover.h in Copy . Public Headers */, + 73EFD42008D8497C7AFCBEECD373B207 /* FBLPromise+Reduce.h in Copy . Public Headers */, + 173ECFDD03584D1EACB89B1AFEDBBFFE /* FBLPromise+Retry.h in Copy . Public Headers */, + 70D63115866856277EECF9C957267C52 /* FBLPromise+Testing.h in Copy . Public Headers */, + 24DB26FDC5B66C423CC7980DC7E02C5E /* FBLPromise+Then.h in Copy . Public Headers */, + 63ADBDE9EBE05200679C68820BCD29D4 /* FBLPromise+Timeout.h in Copy . Public Headers */, + 34638F413AEAB4A39890C6BE7CAFC7A7 /* FBLPromise+Validate.h in Copy . Public Headers */, + B9B9A35BC327CD12D2EA39A732385060 /* FBLPromise+Wrap.h in Copy . Public Headers */, + 3E9DD3D7A6AB68776A8B16AAA853A80F /* FBLPromise.h in Copy . Public Headers */, + 2EDCA6497C659F1F5A624586E4B7FFC8 /* FBLPromiseError.h in Copy . Public Headers */, + 56525F830586E04FCC3EB27BD9D37255 /* FBLPromises.h in Copy . Public Headers */, + ); + name = "Copy . Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0008E34A7746A0E1A2D5583DA0348CBA /* FLLRBEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBEmptyNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h; sourceTree = ""; }; + 00B9C533AF486EDF4C205EBBEC465607 /* FOperationSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOperationSource.m; path = Firebase/Database/Core/Operation/FOperationSource.m; sourceTree = ""; }; + 00C87AD738B62445FF58BEA587E511E7 /* FServerValues.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FServerValues.h; path = Firebase/Database/Core/FServerValues.h; sourceTree = ""; }; + 00CB870A9CD0CEB91A8EEB4E2DF570D6 /* GULSceneDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSceneDelegateSwizzler.m; path = GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m; sourceTree = ""; }; + 010EB3293303194FAFD89055A4E91CE3 /* GDTCORConsoleLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORConsoleLogger.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h; sourceTree = ""; }; + 015383D9B573A7E4A25B73CA5E2E2C36 /* GULLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULLogger.m; path = GoogleUtilities/Logger/GULLogger.m; sourceTree = ""; }; + 017FF39FEE7393BA61DE14D73E902FA8 /* FIRDatabase_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase_Private.h; path = Firebase/Database/Api/Private/FIRDatabase_Private.h; sourceTree = ""; }; + 01B3B9333C2F6435557A422A0630F1F5 /* FCancelEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCancelEvent.h; path = Firebase/Database/Core/View/FCancelEvent.h; sourceTree = ""; }; + 020C390E50662AFEC68A60C7164199DD /* FirebaseInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstanceID.h; path = Firebase/InstanceID/Public/FirebaseInstanceID.h; sourceTree = ""; }; + 025546DBE96632B34B63790615A3BDC3 /* FViewProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessor.h; path = Firebase/Database/FViewProcessor.h; sourceTree = ""; }; + 027C0282396A56D8390E23CEF590CD5A /* FEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEvent.h; path = Firebase/Database/Core/View/FEvent.h; sourceTree = ""; }; + 02E4DD3DCDB31EC1648CA6C98780E009 /* FIRApp.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRApp.m; path = FirebaseCore/Sources/FIRApp.m; sourceTree = ""; }; + 03741108F4DCC70F6CA8C9C139C8C1B7 /* FIRInstallationsAuthTokenResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResult.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h; sourceTree = ""; }; + 039D485AD0B1A9C9BB6FE228FF40844A /* FIRInstallationsStoredAuthToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredAuthToken.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h; sourceTree = ""; }; + 05801D5FF061F264B1CE44110016F58F /* FSyncPoint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncPoint.h; path = Firebase/Database/Core/FSyncPoint.h; sourceTree = ""; }; + 058600A9D546320B88F62E2A82AE2143 /* table.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table.cc; path = table/table.cc; sourceTree = ""; }; + 06023D1734B2E0EC0F1A8AFA0E532F6F /* NSData+SRB64Additions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+SRB64Additions.m"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m"; sourceTree = ""; }; + 064118602FB22DFA8143649846D646DD /* FChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChange.h; path = Firebase/Database/Core/View/FChange.h; sourceTree = ""; }; + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = nanopb.framework; path = nanopb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 07B77C44CC1FDF8D7B46080AE7D97ADA /* FIRInstallationsVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsVersion.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h; sourceTree = ""; }; + 084AA7F2510FE8410D65BB1A2A992F48 /* FIRInstallationsItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsItem.h; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.h; sourceTree = ""; }; + 08DDE3680AB4A3C8926B96415B4152F9 /* GDTCOREventTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h; sourceTree = ""; }; + 0994919D6FF1636BBE1892696E9DA4A2 /* arena.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = arena.cc; path = util/arena.cc; sourceTree = ""; }; + 09BBDA18467B7C62A9271E288A82ED29 /* FirebaseCoreDiagnostics.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCoreDiagnostics.modulemap; sourceTree = ""; }; + 09BC891B2774FDA333795F1FA34727ED /* FOverwrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOverwrite.h; path = Firebase/Database/Core/Operation/FOverwrite.h; sourceTree = ""; }; + 09DE94F55E8798B33321639491D9EFC6 /* FConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConnection.m; path = Firebase/Database/Realtime/FConnection.m; sourceTree = ""; }; + 0A455526C11611056459A460492697E5 /* FIRInstanceIDTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenManager.h; path = Firebase/InstanceID/FIRInstanceIDTokenManager.h; sourceTree = ""; }; + 0A6B42B21F0C1F8665483A4BB4946268 /* GoogleDataTransportCCTSupport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransportCCTSupport.debug.xcconfig; sourceTree = ""; }; + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = leveldb.framework; path = "leveldb-library.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AFCCCAB65ABF466748E9D04F3ED6026 /* FIRInstanceIDStringEncoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStringEncoding.h; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.h; sourceTree = ""; }; + 0C40715AAB90D82EBE8B88B6DEC64F64 /* FViewProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessor.m; path = Firebase/Database/FViewProcessor.m; sourceTree = ""; }; + 0C4F0248287DB8D03D320A8A1FBA6BC8 /* FIRInstanceIDCheckinStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinStore.m; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.m; sourceTree = ""; }; + 0C9144733820350361C79FCC0FC4E76D /* FNamedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNamedNode.h; path = Firebase/Database/FNamedNode.h; sourceTree = ""; }; + 0C9AD50E9DF223C0BC44EDCA95E412DF /* db.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db.h; path = include/leveldb/db.h; sourceTree = ""; }; + 0CAABEE8F7F783A6B7FD09ACA8A04842 /* FIRLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRLogger.m; path = FirebaseCore/Sources/FIRLogger.m; sourceTree = ""; }; + 0D3C1F79FCD48F9D503D56F37E60FE8A /* FIRInstallationsIDController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIDController.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h; sourceTree = ""; }; + 0D863A092BC7BF7CDCF10C9A29826E62 /* FImmutableSortedSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedSet.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h; sourceTree = ""; }; + 0DBFBC879C80096896F5050F43D67974 /* GoogleUtilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleUtilities-dummy.m"; sourceTree = ""; }; + 0E998FD134CA2B57FE5787B01602A4C5 /* Firebase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.release.xcconfig; sourceTree = ""; }; + 0EA0F7CE6EB64CFF17CB11ABEC8CDF16 /* FIRAppAssociationRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppAssociationRegistration.h; path = FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h; sourceTree = ""; }; + 0EB8FAE52E1EE34C048C2E25D084AACF /* FIRComponentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentType.m; path = FirebaseCore/Sources/FIRComponentType.m; sourceTree = ""; }; + 0F0CD1B3CF10F405D4D6DCC033E61ACF /* FLimitedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLimitedFilter.m; path = Firebase/Database/Core/View/Filter/FLimitedFilter.m; sourceTree = ""; }; + 0F9FAE51763CF4E8A796748ED633EB69 /* FIRNoopAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRNoopAuthTokenProvider.h; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.h; sourceTree = ""; }; + 108535B306732FA4B7C62DB68E5B4FF0 /* FIRInstallationsAPIService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAPIService.h; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h; sourceTree = ""; }; + 10DECCDC1A8262E47115B287809143A7 /* GULNSData+zlib.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GULNSData+zlib.m"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.m"; sourceTree = ""; }; + 10E088517E88ECCC3CA4D7857ABC459E /* FIRInstallationsErrorUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrorUtil.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h; sourceTree = ""; }; + 1194FDC2AD891229F89FEF50221D4828 /* FIRSecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSecureStorage.h; path = FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h; sourceTree = ""; }; + 12478891F3E769E22DD83E49512CD0F2 /* FIRInstanceIDTokenOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.h; sourceTree = ""; }; + 12D88D855D9F5F1FB41B1CF4A0280262 /* hash.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = hash.cc; path = util/hash.cc; sourceTree = ""; }; + 1321F309AB4B1BB45EEC3789A76939DA /* FBLPromise+Do.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Do.m"; path = "Sources/FBLPromises/FBLPromise+Do.m"; sourceTree = ""; }; + 13C3D6047848E764C26BAD1410172F7C /* PromisesObjC.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PromisesObjC.modulemap; sourceTree = ""; }; + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstallations.framework; path = FirebaseInstallations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 141F97B030083310E1B66925EBA42F52 /* FIRComponentContainerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainerInternal.h; path = FirebaseCore/Sources/Private/FIRComponentContainerInternal.h; sourceTree = ""; }; + 14494CAC35D8D269643EA5CB8934BF45 /* FTrackedQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQuery.m; path = Firebase/Database/Persistence/FTrackedQuery.m; sourceTree = ""; }; + 14767AA509DD2B355C7598A3E158E242 /* FTupleStringNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleStringNode.m; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.m; sourceTree = ""; }; + 14DD85EA7D746AA0ABA6E66DA54FE552 /* FBLPromise+Async.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Async.h"; path = "Sources/FBLPromises/include/FBLPromise+Async.h"; sourceTree = ""; }; + 156BFD884F1693CF4050DF9EEAE24F4A /* FIRDatabaseComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseComponent.m; path = Firebase/Database/Api/FIRDatabaseComponent.m; sourceTree = ""; }; + 1588032FA5B9336704BAFFEA1C7E2FCE /* FRepoManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoManager.h; path = Firebase/Database/Core/FRepoManager.h; sourceTree = ""; }; + 15C61D66067C8460216C517BBD011E18 /* FBLPromise+Reduce.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Reduce.m"; path = "Sources/FBLPromises/FBLPromise+Reduce.m"; sourceTree = ""; }; + 15F2FE55B0E52C26E5CD1A45A048429C /* FPruneForest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPruneForest.h; path = Firebase/Database/Persistence/FPruneForest.h; sourceTree = ""; }; + 171EA63C3E77121BBC849D8ED2882074 /* FArraySortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FArraySortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m; sourceTree = ""; }; + 181E3F131300BC5D6914C8698DBFFEFD /* FTupleObjectNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjectNode.h; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.h; sourceTree = ""; }; + 18B48B8EAD733AA93D56EC86DF4E5EC0 /* FStringUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStringUtilities.h; path = Firebase/Database/Utilities/FStringUtilities.h; sourceTree = ""; }; + 19298FBBC7572398E1E2B6F1B0ED04B5 /* FSnapshotHolder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotHolder.m; path = Firebase/Database/Core/FSnapshotHolder.m; sourceTree = ""; }; + 199EB0AF8519A748873EAEF746674CAA /* FPathIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPathIndex.m; path = Firebase/Database/FPathIndex.m; sourceTree = ""; }; + 19C7D0C7517E9CAF071A59368C48A735 /* merger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = merger.h; path = table/merger.h; sourceTree = ""; }; + 19ECFA906B835C74272E23F478123821 /* nanopb-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-umbrella.h"; sourceTree = ""; }; + 19F174A0B87E27B10889237216A3FA55 /* write_batch.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = write_batch.cc; path = db/write_batch.cc; sourceTree = ""; }; + 1ACFD04FDEBFD059B55BE1FA713972C2 /* filename.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filename.cc; path = db/filename.cc; sourceTree = ""; }; + 1BC5FF4DE07A6C7B013179FEBB457872 /* Pods-PediatricPancreas-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PediatricPancreas-frameworks.sh"; sourceTree = ""; }; + 1C9B859F2BEDA3BE876C74D5B9F07E4D /* FIRInstallationsItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsItem.m; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.m; sourceTree = ""; }; + 1CA1876DE760D48C7C370BC1CB02071A /* FSRWebSocket.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSRWebSocket.h; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.h; sourceTree = ""; }; + 1D2B2318949D5A383E68777964C87251 /* FIRVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVersion.m; path = FirebaseCore/Sources/FIRVersion.m; sourceTree = ""; }; + 1E21DCEE277E88B08FB8F3329FD5F48A /* FTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTree.h; path = Firebase/Database/Core/Utilities/FTree.h; sourceTree = ""; }; + 1E30CFB2462172C3B6FD5FF8283FA7AB /* PromisesObjC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PromisesObjC.debug.xcconfig; sourceTree = ""; }; + 1E620741BA858DAFC95CA5490B42CB4B /* FBLPromise+Await.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Await.m"; path = "Sources/FBLPromises/FBLPromise+Await.m"; sourceTree = ""; }; + 1E76D9053038A33CDEBFAE625CC5BADE /* GDTCORAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORAssert.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h; sourceTree = ""; }; + 1E8B299D83AE65375BAF9C04BB63EB71 /* FIRCoreDiagnostics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnostics.m; path = Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m; sourceTree = ""; }; + 1F5AF25E215A81CF2173475193C34EB0 /* FSRWebSocket.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSRWebSocket.m; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.m; sourceTree = ""; }; + 1FA5606127C7AB07769D229E6BA594FA /* FDataEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FDataEvent.h; path = Firebase/Database/Core/View/FDataEvent.h; sourceTree = ""; }; + 1FC19607EAE0661F18ACB5A03636690B /* GDTCORPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPrioritizer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h; sourceTree = ""; }; + 1FF27C9FA28C17B538FE3D79E5568EFB /* GULHeartbeatDateStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULHeartbeatDateStorage.m; path = GoogleUtilities/Environment/GULHeartbeatDateStorage.m; sourceTree = ""; }; + 2034D03795150369FA9B06580B7517F7 /* FQuerySpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQuerySpec.m; path = Firebase/Database/Core/FQuerySpec.m; sourceTree = ""; }; + 205F67811189387CB12408CE5D08FB85 /* leveldb-library-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-umbrella.h"; sourceTree = ""; }; + 20B54EE31B858742F3D0FDC1F9359591 /* FSparseSnapshotTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSparseSnapshotTree.h; path = Firebase/Database/Core/FSparseSnapshotTree.h; sourceTree = ""; }; + 20E2602A98267FAC13549447297B1CF6 /* FIRInstanceIDCheckinPreferences_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences_Private.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h; sourceTree = ""; }; + 21481E35761ADCCC2C9056C42954B6C0 /* FRepo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo.h; path = Firebase/Database/Core/FRepo.h; sourceTree = ""; }; + 21C1E706ED5710A5F8B33A3B743E963A /* FIRInstanceIDTokenFetchOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenFetchOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m; sourceTree = ""; }; + 220B0328CECBE9CE20EC4490CB388622 /* env.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env.cc; path = util/env.cc; sourceTree = ""; }; + 220C198B5B0BF924872B6F4E2D39EC90 /* GULSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSwizzler.m; path = GoogleUtilities/MethodSwizzler/GULSwizzler.m; sourceTree = ""; }; + 22745D074BDC5C547FA32DCF913B5ED6 /* FParsedUrl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FParsedUrl.m; path = Firebase/Database/Utilities/FParsedUrl.m; sourceTree = ""; }; + 22A60F60CFF8C2C8A3624904C2D5A7DA /* FCachePolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCachePolicy.h; path = Firebase/Database/Persistence/FCachePolicy.h; sourceTree = ""; }; + 237B8AFB55BB3BE9CA62127AA18FB403 /* FIRInstanceIDTokenDeleteOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenDeleteOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h; sourceTree = ""; }; + 2387E0CA88C9075A7D7612E4CA20875F /* pb_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_encode.c; sourceTree = ""; }; + 23C79734BF195C12C8CA32C05F9DC901 /* FirebaseCoreDiagnosticsInterop.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnosticsInterop.release.xcconfig; sourceTree = ""; }; + 24297E436652A516BEDF07C2BD03A52E /* FIRInstallationsLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsLogger.m; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.m; sourceTree = ""; }; + 24A02E9A2F6D74E292328F6A46B242A0 /* GULReachabilityMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityMessageCode.h; path = GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h; sourceTree = ""; }; + 24E3248B95B1AC14B851DD22D5CBADE2 /* FPriorityIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPriorityIndex.m; path = Firebase/Database/FPriorityIndex.m; sourceTree = ""; }; + 25107E5C61245A8D44F02161C92B9A9F /* FLeafNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLeafNode.h; path = Firebase/Database/Snapshot/FLeafNode.h; sourceTree = ""; }; + 253F8E2E2AE73606EC13FCD055710E21 /* FIRInstallationsSingleOperationPromiseCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsSingleOperationPromiseCache.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h; sourceTree = ""; }; + 258A1335EA6E5FABE7B63118A7825690 /* FirebaseInstallations-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstallations-umbrella.h"; sourceTree = ""; }; + 25CDFCEB95D5E7B062D672C75F8ECBD5 /* log_format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_format.h; path = db/log_format.h; sourceTree = ""; }; + 2648E6918B81AE29038CC5644F02BA5D /* nanopb-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "nanopb-Info.plist"; sourceTree = ""; }; + 271E908860FE391339504340784BC551 /* GoogleDataTransport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransport-umbrella.h"; sourceTree = ""; }; + 27CEB21BECB905A6D672FCB27BC8D325 /* FIRDatabase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabase.m; path = Firebase/Database/Api/FIRDatabase.m; sourceTree = ""; }; + 27F2DB045C06893A8DEADE59EA4E7FDF /* FTupleCallbackStatus.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleCallbackStatus.m; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m; sourceTree = ""; }; + 28976708F04BF0E8AD3DF8D772A5E9C8 /* FLevelDBStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLevelDBStorageEngine.h; path = Firebase/Database/Persistence/FLevelDBStorageEngine.h; sourceTree = ""; }; + 28B6BD3200BA33A9C4373D012238E16F /* FIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndex.h; path = Firebase/Database/FIndex.h; sourceTree = ""; }; + 28E81AF81E32C892833C90AE15DC296A /* Pods-PediatricPancreas-PediatricPancreasUITests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PediatricPancreas-PediatricPancreasUITests.modulemap"; sourceTree = ""; }; + 28F14DA020DF94A85C5154772920D6F0 /* nanopb.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.release.xcconfig; sourceTree = ""; }; + 2A6B9E9907DBF37ECD0FE8FC82FEB737 /* FIRInstanceIDAPNSInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAPNSInfo.h; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.h; sourceTree = ""; }; + 2A88A869CED3ECCE7D333B05DFD0CDEC /* FIRInstanceIDCheckinPreferences.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences.h; path = Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h; sourceTree = ""; }; + 2B51CD46764C9CB5026CB65386897AD8 /* GDTCCTUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTUploader.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h; sourceTree = ""; }; + 2B6742E1E1A93B363D50D9289D741621 /* FWebSocketConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWebSocketConnection.h; path = Firebase/Database/Realtime/FWebSocketConnection.h; sourceTree = ""; }; + 2BA1EAA89F969D9D4D52536B5BCE43FC /* FListenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenProvider.m; path = Firebase/Database/Core/FListenProvider.m; sourceTree = ""; }; + 2BE2D2C1742A0A5FD7AA60074322F8F2 /* leveldb-library.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "leveldb-library.debug.xcconfig"; sourceTree = ""; }; + 2C22FCC38A85E7F7852BF44E2551FDC4 /* histogram.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = histogram.h; path = util/histogram.h; sourceTree = ""; }; + 2C61360E2B0972E9BCF8D71772010A94 /* FKeepSyncedEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeepSyncedEventRegistration.h; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.h; sourceTree = ""; }; + 2C628E92632EDA6D9E0BF833B6E84CEC /* FBLPromisePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromisePrivate.h; path = Sources/FBLPromises/include/FBLPromisePrivate.h; sourceTree = ""; }; + 2C86C31F45C132250286638F6D488663 /* Pods_PediatricPancreas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PediatricPancreas.framework; path = "Pods-PediatricPancreas.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2CCEBF3760A2D010F801CCCF4EF351A8 /* pb_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_decode.c; sourceTree = ""; }; + 2D8BDFC58A9D05BCE6AA0A666C2C3E44 /* FirebaseInstanceID.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstanceID.debug.xcconfig; sourceTree = ""; }; + 2D952F927F793C8D050294553BA6A78D /* FIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndex.m; path = Firebase/Database/FIndex.m; sourceTree = ""; }; + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstanceID.framework; path = FirebaseInstanceID.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DA5D3B64A2899A7E1B92B478EF70F9C /* FIRInstallationsErrorUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsErrorUtil.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m; sourceTree = ""; }; + 2E61B1F736CF3923FDCC8C3E49CA7E3E /* FLLRBEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBEmptyNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m; sourceTree = ""; }; + 2E7463DD70BAEAA5C553A05777352958 /* FBLPromise+Always.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Always.m"; path = "Sources/FBLPromises/FBLPromise+Always.m"; sourceTree = ""; }; + 2EA7330D3CB1E19057AB60A9618336C8 /* FQuerySpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQuerySpec.h; path = Firebase/Database/Core/FQuerySpec.h; sourceTree = ""; }; + 2EE088A364492A317A7C4FA99BC16B32 /* FStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStorageEngine.h; path = Firebase/Database/Persistence/FStorageEngine.h; sourceTree = ""; }; + 2F12565B717E28C3CE4FAA319DAB3D7F /* FSparseSnapshotTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSparseSnapshotTree.m; path = Firebase/Database/Core/FSparseSnapshotTree.m; sourceTree = ""; }; + 2F74BD3D7622AD541A03B2EDF917C25A /* FImmutableTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableTree.h; path = Firebase/Database/Core/Utilities/FImmutableTree.h; sourceTree = ""; }; + 2F7A917CF1ED84B125E53F79C218D36C /* export.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = export.h; path = include/leveldb/export.h; sourceTree = ""; }; + 2F8A01B76B2056EA8629ED6314AA7FBF /* GDTCORDataFuture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORDataFuture.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m; sourceTree = ""; }; + 2FA7F98EE4D30B47DE6F7455BC33991D /* FirebaseInstallations-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstallations-dummy.m"; sourceTree = ""; }; + 3006D62C40726EA8DD299E82CEC1BD7A /* GULNetworkConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkConstants.m; path = GoogleUtilities/Network/GULNetworkConstants.m; sourceTree = ""; }; + 30663E00087519FA3686DFE7783369E9 /* cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cache.h; path = include/leveldb/cache.h; sourceTree = ""; }; + 30E60BB59ABCAB6163E9F312DCAA82C6 /* coding.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = coding.cc; path = util/coding.cc; sourceTree = ""; }; + 31452DF8E1090D9AC6ADE92C32F5BC2A /* FirebaseCore-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCore-Info.plist"; sourceTree = ""; }; + 31537E08EC2179F2189D3BDDA257E569 /* FTupleTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTransaction.h; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.h; sourceTree = ""; }; + 31A3DA146C85F0E4208EDF51D635374E /* crc32c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = crc32c.h; path = util/crc32c.h; sourceTree = ""; }; + 31C383A5D52590F19530998CE602FE17 /* GoogleUtilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleUtilities-Info.plist"; sourceTree = ""; }; + 31EB496C4974C87B5DD9A5C3D20FA2C7 /* FBLPromise+Testing.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Testing.m"; path = "Sources/FBLPromises/FBLPromise+Testing.m"; sourceTree = ""; }; + 31ECE032F2B1D1C931F783C363CEA9D3 /* Pods-PediatricPancreasTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PediatricPancreasTests-acknowledgements.markdown"; sourceTree = ""; }; + 3250A298087DD89728C3E5E2CCA32C78 /* FirebaseInstanceID.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstanceID.release.xcconfig; sourceTree = ""; }; + 32E7893D49BF9AB5CB50A68EC77DF323 /* GULNetwork.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetwork.m; path = GoogleUtilities/Network/GULNetwork.m; sourceTree = ""; }; + 33023881967395B122B2547507E8354C /* cct.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = cct.nanopb.c; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c; sourceTree = ""; }; + 33238801326949DAC00EC88289C9E167 /* FIRSecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSecureStorage.m; path = FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m; sourceTree = ""; }; + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FBLPromises.framework; path = PromisesObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + 34D792D28402E4437C7860AAC976A3A7 /* dbformat.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dbformat.cc; path = db/dbformat.cc; sourceTree = ""; }; + 34F03D87EA8B176419ECB12B051736B1 /* iterator_wrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator_wrapper.h; path = table/iterator_wrapper.h; sourceTree = ""; }; + 35E008788331AAF58516A9A5082B6334 /* memtable.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = memtable.cc; path = db/memtable.cc; sourceTree = ""; }; + 364EAEA6E2087584E3FAC61220152886 /* FIRInstanceIDCombinedHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCombinedHandler.m; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.m; sourceTree = ""; }; + 36564ACDC189BBCFE100D9CED8658730 /* nanopb.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.debug.xcconfig; sourceTree = ""; }; + 3659B8E0DA938B031AD879C0B213C188 /* FIRInstanceIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenStore.h; path = Firebase/InstanceID/FIRInstanceIDTokenStore.h; sourceTree = ""; }; + 36C7915A295EC650C0F2F336452EF3C2 /* FIRInstallationsVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsVersion.m; path = FirebaseInstallations/Source/Library/FIRInstallationsVersion.m; sourceTree = ""; }; + 36F6CC5035C5136DAE4AA2DA5F82F358 /* GULAppDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler_Private.h; path = GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h; sourceTree = ""; }; + 371CBDB9F2F452BB9341C8D0395B8A2E /* filename.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filename.h; path = db/filename.h; sourceTree = ""; }; + 3732562635D3675F3AC5870C2EA64563 /* FWriteTreeRef.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTreeRef.h; path = Firebase/Database/Core/FWriteTreeRef.h; sourceTree = ""; }; + 37680EC5B6E6AB38998D8F2E60743D0B /* FIRDatabaseConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig.h; path = Firebase/Database/Api/FIRDatabaseConfig.h; sourceTree = ""; }; + 382B9EE58EBB9AFB9485174E53DED76A /* FirebaseCoreDiagnostics.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnostics.release.xcconfig; sourceTree = ""; }; + 3884BBAFEA06415C2E4E1D75F152F2B4 /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + 38BDD50A689DAC3E054B5FD55707AA2F /* FSyncPoint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncPoint.m; path = Firebase/Database/Core/FSyncPoint.m; sourceTree = ""; }; + 38C4B97EC12F8B9C3DE1220BCB4A109E /* FirebaseCoreDiagnostics-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCoreDiagnostics-Info.plist"; sourceTree = ""; }; + 38EBB4AB7E209E3659BF7E9B889F7423 /* FirebaseDatabase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseDatabase.debug.xcconfig; sourceTree = ""; }; + 38F29B71648AE8453095366BF1C520A8 /* FIRInstallationsLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsLogger.h; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.h; sourceTree = ""; }; + 393480CCC4702D3A5CC9CAF98AF4E723 /* PromisesObjC-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PromisesObjC-umbrella.h"; sourceTree = ""; }; + 39C731E683F6797282C44B7CD3D51841 /* FAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAuthTokenProvider.h; path = Firebase/Database/Login/FAuthTokenProvider.h; sourceTree = ""; }; + 39FF3E51D669385E3E87BD2ACCFC4ED8 /* filter_block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_block.cc; path = table/filter_block.cc; sourceTree = ""; }; + 3A3ACA8424CC6D8AF0F54BE91DFA0A80 /* nanopb.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = nanopb.modulemap; sourceTree = ""; }; + 3B41A267A51E2D1204B721F1B7DF81D1 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig"; sourceTree = ""; }; + 3BD6E0B555B8B7001FA7C0534B5316D8 /* FIRInstanceIDCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinService.h; path = Firebase/InstanceID/FIRInstanceIDCheckinService.h; sourceTree = ""; }; + 3C251CBEB0F513BF966974089FB9C542 /* GULAppEnvironmentUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppEnvironmentUtil.h; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h; sourceTree = ""; }; + 3CC724DC78CD413A599BC4051FDFB089 /* FirebaseDatabase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseDatabase.modulemap; sourceTree = ""; }; + 3CD37FD280133AB42ABA89D293273149 /* GDTCCTCompressionHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTCompressionHelper.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m; sourceTree = ""; }; + 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 3D77CDFE1F279E8808BC2B957E413C69 /* FTupleRemovedQueriesEvents.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleRemovedQueriesEvents.m; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m; sourceTree = ""; }; + 3D78108544D29EC6204FBFD22A285626 /* Pods-PediatricPancreasTests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreasTests-Info.plist"; sourceTree = ""; }; + 3E8AF3E7C471E6553CFB71867A370455 /* FTupleStringNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleStringNode.h; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.h; sourceTree = ""; }; + 3E96F5CFCE90C3487B8CD0E4FD6B85C1 /* FirebaseInstallations-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstallations-Info.plist"; sourceTree = ""; }; + 3EEFAECB1EA225E89728D68E7EE8A8A0 /* dbformat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dbformat.h; path = db/dbformat.h; sourceTree = ""; }; + 3F197642A1C79AF964CAAA015E860AC3 /* FIRInstanceID+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceID+Private.h"; path = "Firebase/InstanceID/Private/FIRInstanceID+Private.h"; sourceTree = ""; }; + 3F27706885AB7D265A16236A0B089793 /* FIRTransactionResult_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult_Private.h; path = Firebase/Database/Api/Private/FIRTransactionResult_Private.h; sourceTree = ""; }; + 3FCB115B6E3E19E6E714CE31F8C48CC4 /* FIRInstallationsStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStatus.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h; sourceTree = ""; }; + 3FD52FD8826F32BA541D72467BE7B21B /* FBLPromise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromise.m; path = Sources/FBLPromises/FBLPromise.m; sourceTree = ""; }; + 404A14083B530908C5B3506B9F2CF75A /* GULNetworkMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkMessageCode.h; path = GoogleUtilities/Network/Private/GULNetworkMessageCode.h; sourceTree = ""; }; + 4141BEDF9F22F8F20F34FBEC3C8754A1 /* GoogleDataTransportCCTSupport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransportCCTSupport-umbrella.h"; sourceTree = ""; }; + 416C805A18279EC4D3465411DD4D472E /* log_reader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_reader.h; path = db/log_reader.h; sourceTree = ""; }; + 41C1F0E633134DD86A4BD84D71BFC499 /* FTupleUserCallback.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleUserCallback.m; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.m; sourceTree = ""; }; + 4236FF19FECDA313AEEBB197D87F13BA /* iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = iterator.cc; path = table/iterator.cc; sourceTree = ""; }; + 4245217ADD8651375C7C87461D2BAC11 /* FIRDatabaseQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseQuery.m; path = Firebase/Database/Api/FIRDatabaseQuery.m; sourceTree = ""; }; + 428713B30E973E48B3E6C248827A08FD /* FEventEmitter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventEmitter.m; path = Firebase/Database/Utilities/FEventEmitter.m; sourceTree = ""; }; + 43015EB8E78629BAA11B46C1B2E9867D /* FIRDependency.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDependency.m; path = FirebaseCore/Sources/FIRDependency.m; sourceTree = ""; }; + 4333D276EEF0EDA615A614467B65F6F7 /* GDTCORClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORClock.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORClock.m; sourceTree = ""; }; + 433556677AD5081DFD4E9FA881C05F15 /* FIRCoreDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsData.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h; sourceTree = ""; }; + 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 4424C23BA8BD950C7B96DC874B777989 /* Firebase.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.debug.xcconfig; sourceTree = ""; }; + 443C8A9A533DD8E2A9D01F4F78EBE443 /* FIRInstanceID+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceID+Private.m"; path = "Firebase/InstanceID/FIRInstanceID+Private.m"; sourceTree = ""; }; + 444973A3DB4BB3F60FCF797B60B726E7 /* FClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FClock.m; path = Firebase/Database/FClock.m; sourceTree = ""; }; + 448011007D98317BF4F7C1098DC99366 /* cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = cache.cc; path = util/cache.cc; sourceTree = ""; }; + 451BB6FC86F30A7B6E5B472C474F44FD /* FTupleUserCallback.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleUserCallback.h; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.h; sourceTree = ""; }; + 45A016B308E76BE7B4FEF78FD4654397 /* FIRDataSnapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot.h; path = Firebase/Database/Public/FIRDataSnapshot.h; sourceTree = ""; }; + 45BBE0220D0AA28216B74B4EECE15457 /* FIRInstanceIDTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenManager.m; path = Firebase/InstanceID/FIRInstanceIDTokenManager.m; sourceTree = ""; }; + 45FCEB89C8FEB1D4760D9155DC0E584C /* FRangedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangedFilter.m; path = Firebase/Database/FRangedFilter.m; sourceTree = ""; }; + 45FE005CA2C4A3AEF54D0E39D139568C /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + 46149FED4D72A781404735F743191B7A /* Pods-PediatricPancreas-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas-acknowledgements.plist"; sourceTree = ""; }; + 469188005111468BDAB623C15E021952 /* FTupleSetIdPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleSetIdPath.h; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h; sourceTree = ""; }; + 469E4EE0DF63B70B17207AF1F945B600 /* fbase64.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fbase64.c; path = Firebase/Database/third_party/SocketRocket/fbase64.c; sourceTree = ""; }; + 47DD04AD61421A996DEAE095AA51E77F /* builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = builder.cc; path = db/builder.cc; sourceTree = ""; }; + 483ED7857A31966E18E87385A1A58AD8 /* GDTCORTransformer_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h; sourceTree = ""; }; + 4891EB1830F4333011011F6DBFE08CA2 /* FIRInstanceIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenStore.m; path = Firebase/InstanceID/FIRInstanceIDTokenStore.m; sourceTree = ""; }; + 48D577F0C8A3766C9F607FEB903B8660 /* GULSceneDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler_Private.h; path = GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h; sourceTree = ""; }; + 4990C45303FADD6DD0B9FD280C5B5FE4 /* Pods-PediatricPancreas-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PediatricPancreas-dummy.m"; sourceTree = ""; }; + 4A14479C1990437D603C775E0838399D /* FBLPromise+Await.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Await.h"; path = "Sources/FBLPromises/include/FBLPromise+Await.h"; sourceTree = ""; }; + 4A41F2D2C55B5704983865EFEBB72419 /* FIndexedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedNode.h; path = Firebase/Database/Snapshot/FIndexedNode.h; sourceTree = ""; }; + 4A4733A66A4533BC54CA3576C71F03DE /* FPendingPut.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPendingPut.m; path = Firebase/Database/Persistence/FPendingPut.m; sourceTree = ""; }; + 4A87C58D697F019156D54455DEF3DA75 /* FLLRBNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h; sourceTree = ""; }; + 4A9A12A16AB2EE91241EFB10A5E623ED /* GDTCORTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h; sourceTree = ""; }; + 4AC6BC15BEF7347E79C01F3CC6F1AEA3 /* version_set.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_set.h; path = db/version_set.h; sourceTree = ""; }; + 4AF07C1AFB9C5EDF8416071371D15C6D /* FTypedefs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs.h; path = Firebase/Database/Utilities/FTypedefs.h; sourceTree = ""; }; + 4B531F7005792C54B07D84507A34E3AB /* log_reader.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_reader.cc; path = db/log_reader.cc; sourceTree = ""; }; + 4B5719CDCE6B2A2F1216F9C92E6D02C8 /* FBLPromise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromise.h; path = Sources/FBLPromises/include/FBLPromise.h; sourceTree = ""; }; + 4B79D7F54E520AF3904F5139432C278C /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 4CEA8AD862EBD0CBF7BEF03AA3752A1E /* table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table.h; path = include/leveldb/table.h; sourceTree = ""; }; + 4D0D828D2BA50C9617AE06268B44A354 /* FirebaseCore-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCore-dummy.m"; sourceTree = ""; }; + 4DC21506550FA18E27B3273C19EE1878 /* FirebaseInstallations.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstallations.release.xcconfig; sourceTree = ""; }; + 4E5C112CB6CC03482709D541E5DF2517 /* FEventEmitter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventEmitter.h; path = Firebase/Database/Utilities/FEventEmitter.h; sourceTree = ""; }; + 4E67DE3F4605BE94ED95546F293188D3 /* FOverwrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOverwrite.m; path = Firebase/Database/Core/Operation/FOverwrite.m; sourceTree = ""; }; + 4F13CEF2BDCB6C7ABD864E400468E55B /* FirebaseCore-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCore-umbrella.h"; sourceTree = ""; }; + 4F42AC0B1D0F68847E4A548E94AD9268 /* FIRConfigurationInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfigurationInternal.h; path = FirebaseCore/Sources/Private/FIRConfigurationInternal.h; sourceTree = ""; }; + 4FADF1444F7ACFA3CDAF40D40C22292A /* FIRInstallationsKeychainUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsKeychainUtils.h; path = FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h; sourceTree = ""; }; + 4FC8EE8B7162AC6DE3CF2A1F8F8BB473 /* GoogleDataTransport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransport.modulemap; sourceTree = ""; }; + 50204171185C6765C11FF190A8E90F7D /* FKeyIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeyIndex.m; path = Firebase/Database/FKeyIndex.m; sourceTree = ""; }; + 502076027B4DCEB843DC38B97A94887B /* FirebaseCore.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.debug.xcconfig; sourceTree = ""; }; + 50223B484C12AFEA943E8C2C1EDCB3EC /* FIRIMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRIMessageCode.h; path = Firebase/InstanceID/FIRIMessageCode.h; sourceTree = ""; }; + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseDatabase.framework; path = FirebaseDatabase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 518C77022625AF3F201451F80ACA198B /* Pods-PediatricPancreas.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas.release.xcconfig"; sourceTree = ""; }; + 51D30EA04D793B10FED533DBFC51398A /* Pods-PediatricPancreas-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PediatricPancreas-acknowledgements.markdown"; sourceTree = ""; }; + 51EDC2B524719FB084B2E682316BE65C /* FSnapshotUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotUtilities.h; path = Firebase/Database/Snapshot/FSnapshotUtilities.h; sourceTree = ""; }; + 52041C725712526A753AF310EC5E0271 /* FIRCoreDiagnosticsConnector.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnosticsConnector.m; path = FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m; sourceTree = ""; }; + 522F207349FC0C3AEBE0DC5C8D0F6A5E /* port_example.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_example.h; path = port/port_example.h; sourceTree = ""; }; + 528792C9F0D3800EAF0C1D2F84EF8873 /* FIRInstanceIDStringEncoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStringEncoding.m; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.m; sourceTree = ""; }; + 52B29770DEBEF1203AB8B5BF1A64AEC1 /* APLevelDB.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = APLevelDB.mm; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm"; sourceTree = ""; }; + 52EEB6148AFFBEE7152B90E633612CC6 /* GULAppEnvironmentUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppEnvironmentUtil.m; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m; sourceTree = ""; }; + 533EB989EB34349FC33B5C0C9C22EF78 /* FIRHeartbeatInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRHeartbeatInfo.m; path = FirebaseCore/Sources/FIRHeartbeatInfo.m; sourceTree = ""; }; + 53FAAC0625B206D4D02719ABD6BAC099 /* FTupleBoolBlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleBoolBlock.h; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h; sourceTree = ""; }; + 540836500C5F901B23F465C564B553C2 /* FNamedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNamedNode.m; path = Firebase/Database/FNamedNode.m; sourceTree = ""; }; + 54475272A64C46FD9B044CD0B03D1F16 /* FIRComponentContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentContainer.m; path = FirebaseCore/Sources/FIRComponentContainer.m; sourceTree = ""; }; + 5460CEF22218F0CDDD2B043F5F7855AB /* GULSecureCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSecureCoding.h; path = GoogleUtilities/Environment/Public/GULSecureCoding.h; sourceTree = ""; }; + 546AA55159CBCDB057982CCAAF150602 /* logging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = logging.h; path = util/logging.h; sourceTree = ""; }; + 5552D0C170F2A442665A8F97BB64E4F0 /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PediatricPancreas_PediatricPancreasUITests.framework; path = "Pods-PediatricPancreas-PediatricPancreasUITests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 55EB03E6D00F93919813AFF8047C700D /* GULNetworkLoggerProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkLoggerProtocol.h; path = GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h; sourceTree = ""; }; + 55FD8F26EA01FA0EE0F08CDB51E724A6 /* Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown"; sourceTree = ""; }; + 560FEF99670CDFC70E4F9F5F8268CFF7 /* filter_policy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_policy.h; path = include/leveldb/filter_policy.h; sourceTree = ""; }; + 562AEAF410E4ECCAF9B77166BA77E3A3 /* FKeepSyncedEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeepSyncedEventRegistration.m; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.m; sourceTree = ""; }; + 566267F9A313143EE6BDD499F3866124 /* Pods-PediatricPancreasTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreasTests.debug.xcconfig"; sourceTree = ""; }; + 56DC4A494823934F36EC73C1FCC0EBF4 /* FirebaseDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseDatabase.h; path = Firebase/Database/Public/FirebaseDatabase.h; sourceTree = ""; }; + 57018189681D84C262FEFABC79A46C04 /* FBLPromise+Wrap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Wrap.h"; path = "Sources/FBLPromises/include/FBLPromise+Wrap.h"; sourceTree = ""; }; + 5737AA49AB6F7A70ACA5A20ADAC6B4A8 /* FNextPushId.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNextPushId.h; path = Firebase/Database/Utilities/FNextPushId.h; sourceTree = ""; }; + 581326EBD90729AEB63DC7E39FAAACB7 /* FImmutableSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m; sourceTree = ""; }; + 589C384C3A628D4954C3FDE4FB7B6A43 /* GULMutableDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULMutableDictionary.h; path = GoogleUtilities/Network/Private/GULMutableDictionary.h; sourceTree = ""; }; + 59393315B83DEB88FEAFAE711D920582 /* FIRInstanceIDKeychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeychain.m; path = Firebase/InstanceID/FIRInstanceIDKeychain.m; sourceTree = ""; }; + 594443A20669265EDD8B986F8494B7C1 /* FIRInstallationsIIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDTokenStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h; sourceTree = ""; }; + 59C9B1EC6DD625C6D01C030834CF246E /* Pods-PediatricPancreasTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreasTests-acknowledgements.plist"; sourceTree = ""; }; + 5B69A11D9AE8DE28BEEBBDB6FD309B45 /* memtable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = memtable.h; path = db/memtable.h; sourceTree = ""; }; + 5B8BFC8D45246220FC9E22CEC5021251 /* FSnapshotHolder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotHolder.h; path = Firebase/Database/Core/FSnapshotHolder.h; sourceTree = ""; }; + 5C1D2B97EE131D32FFE68B5D4797D618 /* FIRConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRConfiguration.m; path = FirebaseCore/Sources/FIRConfiguration.m; sourceTree = ""; }; + 5C4601FE5C4C1B22A2499A3C8CFD4147 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + 5C666511B4072152AD025B2D4C721AAC /* FIRInstanceIDKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeychain.h; path = Firebase/InstanceID/FIRInstanceIDKeychain.h; sourceTree = ""; }; + 5C87D643C4C45D5110216216D030EBF5 /* FAckUserWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAckUserWrite.h; path = Firebase/Database/Core/Operation/FAckUserWrite.h; sourceTree = ""; }; + 5CD246213E4E717E503D47F79BBB2439 /* FirebaseCoreDiagnostics.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnostics.debug.xcconfig; sourceTree = ""; }; + 5CDF3A3DACF1F0F35334E584A81142A8 /* FIRInstallationsAuthTokenResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResultInternal.h; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h; sourceTree = ""; }; + 5CEA9F60ABECD586463154A10B2288F8 /* FImmutableSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h; sourceTree = ""; }; + 5CECAFFA8C44526C632EEA97E2699B33 /* FIRDatabaseComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseComponent.h; path = Firebase/Database/Api/FIRDatabaseComponent.h; sourceTree = ""; }; + 5D7A7A1F332FB4CB78EEFE0D5645D882 /* FPersistentConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistentConnection.h; path = Firebase/Database/Core/FPersistentConnection.h; sourceTree = ""; }; + 5E01539529DD344C874CC0055A2F12BE /* FIRInstallationsStoredAuthToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredAuthToken.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m; sourceTree = ""; }; + 5E0495142F4CB62FD6FD98EA2E14AA08 /* FIRInstanceID_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID_Private.h; path = Firebase/InstanceID/Private/FIRInstanceID_Private.h; sourceTree = ""; }; + 5E29BD1F7221E4AB0C4A4ED785D7608C /* GoogleDataTransportCCTSupport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransportCCTSupport.release.xcconfig; sourceTree = ""; }; + 5E443A6931785BEEAF7DC2C354926B51 /* FTupleObjects.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjects.h; path = Firebase/Database/Utilities/Tuples/FTupleObjects.h; sourceTree = ""; }; + 5E72C91BD55A89072F9977C2F1A152D1 /* FLevelDBStorageEngine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLevelDBStorageEngine.m; path = Firebase/Database/Persistence/FLevelDBStorageEngine.m; sourceTree = ""; }; + 5EF616070C58259A27E8EEAA63F9E462 /* FIRErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRErrors.m; path = FirebaseCore/Sources/FIRErrors.m; sourceTree = ""; }; + 5F58773864AC25F46EB2AA354F987C57 /* FIRInstanceIDBackupExcludedPlist.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDBackupExcludedPlist.m; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m; sourceTree = ""; }; + 5F8C417906B62E8422D71968C8EEBF1E /* GDTCORLifecycle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORLifecycle.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m; sourceTree = ""; }; + 6005E4C85596FC45C8FC9F41724E5808 /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Frameworks/FIRAnalyticsConnector.framework; sourceTree = ""; }; + 6007C861D262EE9CFD533D5392F386E8 /* FEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEmptyNode.m; path = Firebase/Database/Snapshot/FEmptyNode.m; sourceTree = ""; }; + 60674E85B85501474862591F4FFCEF7E /* FMaxNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMaxNode.h; path = Firebase/Database/FMaxNode.h; sourceTree = ""; }; + 60C14C6B81499F57816A85B725572902 /* FirebaseDatabase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseDatabase-Info.plist"; sourceTree = ""; }; + 6132BBDB4E6F8E0B4E9B5E3C9850E8DE /* no_destructor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = no_destructor.h; path = util/no_destructor.h; sourceTree = ""; }; + 61902C839F537E39C79EBD06E14DD2C4 /* GDTCORTransport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransport.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m; sourceTree = ""; }; + 61A0AC30DE0C12BC52B4BD10F6121DDF /* FRepoManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoManager.m; path = Firebase/Database/Core/FRepoManager.m; sourceTree = ""; }; + 61F7711DCE64F1713DFA6FCCC11690C8 /* FWriteTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTree.m; path = Firebase/Database/Core/FWriteTree.m; sourceTree = ""; }; + 6219B0FFB8044BA7B94076BAB77DB1D3 /* FBLPromise+Retry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Retry.m"; path = "Sources/FBLPromises/FBLPromise+Retry.m"; sourceTree = ""; }; + 623D671CA43E7F78C56956E343D5657D /* bloom.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = bloom.cc; path = util/bloom.cc; sourceTree = ""; }; + 6270DF1BFF55ADC2D337AC78BD921C52 /* FStringUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FStringUtilities.m; path = Firebase/Database/Utilities/FStringUtilities.m; sourceTree = ""; }; + 62761239096B210D4241701FA2FB1D97 /* GoogleDataTransportCCTSupport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransportCCTSupport-Info.plist"; sourceTree = ""; }; + 6284DEE9BBC353DD2F3E29CFF97AF0EF /* FLeafNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLeafNode.m; path = Firebase/Database/Snapshot/FLeafNode.m; sourceTree = ""; }; + 62BA41319E7AA21A5F414BB6901E2EAA /* FPruneForest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPruneForest.m; path = Firebase/Database/Persistence/FPruneForest.m; sourceTree = ""; }; + 62E90F2517A7D54AE0A6DA5690C006A4 /* FImmutableSortedSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedSet.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m; sourceTree = ""; }; + 6362D3C5139CB0F2ADC38869A8AF6338 /* GULLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerLevel.h; path = GoogleUtilities/Logger/Public/GULLoggerLevel.h; sourceTree = ""; }; + 636D1E4BE951AF743DF68225F83ED03A /* FClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FClock.h; path = Firebase/Database/FClock.h; sourceTree = ""; }; + 63AAC507B0C7EE188A57BC2455B04E4D /* FBLPromise+Race.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Race.h"; path = "Sources/FBLPromises/include/FBLPromise+Race.h"; sourceTree = ""; }; + 63F238CF5864F2FD8C60BAD8AC561C34 /* GoogleUtilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-prefix.pch"; sourceTree = ""; }; + 64927969944CC6B0EF7ABBF8A9D6B982 /* slice.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = slice.h; path = include/leveldb/slice.h; sourceTree = ""; }; + 64DE81935684B37F8499BD626088D702 /* FCacheNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCacheNode.h; path = Firebase/Database/Core/View/FCacheNode.h; sourceTree = ""; }; + 6526C1D31492B1E021287A00A46E4DB0 /* FImmutableTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableTree.m; path = Firebase/Database/Core/Utilities/FImmutableTree.m; sourceTree = ""; }; + 656F06CD541DEA906BAE925398B67D0B /* GDTCCTPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTPrioritizer.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h; sourceTree = ""; }; + 6597CE9AFDA1AF2FA603A486F757ADCC /* FIRInstallationsStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStore.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h; sourceTree = ""; }; + 65CD61911DCF7CD7FCCBB65A9CEEE323 /* FTransformedEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTransformedEnumerator.h; path = Firebase/Database/FTransformedEnumerator.h; sourceTree = ""; }; + 67373B6F54F16182D369B74E58D5F536 /* GULHeartbeatDateStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULHeartbeatDateStorage.h; path = GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h; sourceTree = ""; }; + 686EDFE931F5DA103D7A9B9031A68467 /* FListenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenProvider.h; path = Firebase/Database/Core/FListenProvider.h; sourceTree = ""; }; + 687462B2466B5822E171E11E94D99E9F /* builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = builder.h; path = db/builder.h; sourceTree = ""; }; + 6897BF9DB6AA2AEFA17C83D1CC46505F /* FConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConnection.h; path = Firebase/Database/Realtime/FConnection.h; sourceTree = ""; }; + 69378FC37B1DFB015522CAFAF6EC4001 /* GDTCORClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORClock.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h; sourceTree = ""; }; + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransportCCTSupport.framework; path = GoogleDataTransportCCTSupport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 695657C468C5D2CF227BD8AA9F4FF226 /* FOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperation.h; path = Firebase/Database/Core/Operation/FOperation.h; sourceTree = ""; }; + 69749DD73C4D1A25AB8A0938B17D6E2C /* leveldb-library-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "leveldb-library-Info.plist"; sourceTree = ""; }; + 69A38C98F33FDE148ED5D38379F735D1 /* FTupleTSN.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTSN.h; path = Firebase/Database/Utilities/Tuples/FTupleTSN.h; sourceTree = ""; }; + 6B4E576722528645372A7E3DABD88704 /* thread_annotations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = thread_annotations.h; path = port/thread_annotations.h; sourceTree = ""; }; + 6BA535C000530A7DB6D708C0024FE808 /* FIRInstanceIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStore.m; path = Firebase/InstanceID/FIRInstanceIDStore.m; sourceTree = ""; }; + 6BA701D49705278AE2504369CB8FCBB3 /* histogram.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = histogram.cc; path = util/histogram.cc; sourceTree = ""; }; + 6C00A27614E9B023E9AF2E860B568B7B /* FIRInstanceIDBackupExcludedPlist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDBackupExcludedPlist.h; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h; sourceTree = ""; }; + 6C788D48944FAEAB4862F3DB0F76AB84 /* FServerValues.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FServerValues.m; path = Firebase/Database/Core/FServerValues.m; sourceTree = ""; }; + 6C9FA0D3CC8310231FD8E879E9F9FB2F /* FIRMutableData_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData_Private.h; path = Firebase/Database/Api/Private/FIRMutableData_Private.h; sourceTree = ""; }; + 6CE1AAC4069551B0743B4F75F9A76348 /* Pods-PediatricPancreasTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PediatricPancreasTests-dummy.m"; sourceTree = ""; }; + 6CF3E3945EDFC777942BE90AA282A705 /* GDTCORRegistrar_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h; sourceTree = ""; }; + 6D0C04076DA35AE3B33CF8AD8BAF984A /* db_impl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_impl.h; path = db/db_impl.h; sourceTree = ""; }; + 6D3557174B66202482C8BDA5E3AC8D6C /* FWriteRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteRecord.h; path = Firebase/Database/Core/FWriteRecord.h; sourceTree = ""; }; + 6D407C321863CD7FA24AC53D85CA2966 /* FUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUtilities.m; path = Firebase/Database/Utilities/FUtilities.m; sourceTree = ""; }; + 6D66A0887A41593C21A1C19F871DD901 /* FIRInstallationsHTTPError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsHTTPError.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m; sourceTree = ""; }; + 6DD1E26CF8A05FA5B014E91EF56ED45D /* FTupleBoolBlock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleBoolBlock.m; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m; sourceTree = ""; }; + 6E2242D1AEC32106B5EC1B6007F11512 /* version_edit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_edit.h; path = db/version_edit.h; sourceTree = ""; }; + 6E5AB98A277B1CB96C5A1CB204FA77FE /* comparator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = comparator.cc; path = util/comparator.cc; sourceTree = ""; }; + 6E9580AEFCE0FFB8EB4D0165A208A7EF /* FIROptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROptions.m; path = FirebaseCore/Sources/FIROptions.m; sourceTree = ""; }; + 6F120332D2F3AADB20BE6BD46DB04B5C /* FBLPromise+Delay.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Delay.h"; path = "Sources/FBLPromises/include/FBLPromise+Delay.h"; sourceTree = ""; }; + 6F757C6CD54BFEF3CFB0766836A5F414 /* FIRRetryHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRRetryHelper.h; path = Firebase/Database/Core/Utilities/FIRRetryHelper.h; sourceTree = ""; }; + 6F93B1E527C47BC19CC33DF9E2E21D44 /* FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceID.m; path = Firebase/InstanceID/FIRInstanceID.m; sourceTree = ""; }; + 6FACDBC1AFD69E2F70800AFC30CFAFE7 /* dumpfile.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dumpfile.cc; path = db/dumpfile.cc; sourceTree = ""; }; + 713F262D1F922BE2029360D4072ACDE0 /* FBLPromise+Do.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Do.h"; path = "Sources/FBLPromises/include/FBLPromise+Do.h"; sourceTree = ""; }; + 7148DF98940A6E8CC17E6FFA5DCCFEBA /* GULLoggerCodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerCodes.h; path = GoogleUtilities/Common/GULLoggerCodes.h; sourceTree = ""; }; + 714CACEB6E4D9CE23EF7D85F0B7804A4 /* FBLPromise+Timeout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Timeout.h"; path = "Sources/FBLPromises/include/FBLPromise+Timeout.h"; sourceTree = ""; }; + 7158411B4EA467277676C39BCC4E56CE /* FEventRaiser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventRaiser.m; path = Firebase/Database/Core/View/FEventRaiser.m; sourceTree = ""; }; + 71A013D2FB3A60D77460B97E98790815 /* FIRInstallationsItem+RegisterInstallationAPI.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstallationsItem+RegisterInstallationAPI.m"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m"; sourceTree = ""; }; + 71A603CA5B006121B694846787D7BAD9 /* FBLPromise+Race.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Race.m"; path = "Sources/FBLPromises/FBLPromise+Race.m"; sourceTree = ""; }; + 71F1E99218E565E5F99716E1FF698721 /* windows_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = windows_logger.h; path = util/windows_logger.h; sourceTree = ""; }; + 722C7D69C7C7A86DB9326799FB70F05B /* FParsedUrl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FParsedUrl.h; path = Firebase/Database/Utilities/FParsedUrl.h; sourceTree = ""; }; + 723017E29BE5FD9D38BE7477D5D6FFF4 /* PromisesObjC-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PromisesObjC-dummy.m"; sourceTree = ""; }; + 725CAC1516DCD4072C47A01FC5EEE271 /* FIRServerValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRServerValue.h; path = Firebase/Database/Public/FIRServerValue.h; sourceTree = ""; }; + 726B3EC39B72F88C33B457410776DF31 /* FValidation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValidation.h; path = Firebase/Database/Utilities/FValidation.h; sourceTree = ""; }; + 72D52576F67BF816A679DF6B1DDBFB79 /* Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m"; sourceTree = ""; }; + 7371FD5514980F9343B6D988BB4EBD0C /* FIRAuthInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInterop.h; path = Interop/Auth/Public/FIRAuthInterop.h; sourceTree = ""; }; + 73B33C24AB2B2C938EE0534A6B039DA1 /* FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID.h; path = Firebase/InstanceID/Public/FIRInstanceID.h; sourceTree = ""; }; + 73C3A2B897419E5CB0BA2CB0D02C24CB /* FIRInstallationsSingleOperationPromiseCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsSingleOperationPromiseCache.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m; sourceTree = ""; }; + 73F0B382A1404222E1C60352DFF7BB72 /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + 7478BC8F13E25643BF62665659255636 /* FIRInstallationsErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrors.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h; sourceTree = ""; }; + 747CA32386AB55EC174C9FE0E0C1A2B4 /* FPathIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPathIndex.h; path = Firebase/Database/FPathIndex.h; sourceTree = ""; }; + 7498B69B8CAE5DD507C2F5F97F17CE08 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + 74B732861F4DBB7D074BD0EBEAE05218 /* FSyncTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncTree.h; path = Firebase/Database/Core/FSyncTree.h; sourceTree = ""; }; + 7501A42EFA5935C6D3C245650F4D9879 /* GoogleDataTransport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransport-Info.plist"; sourceTree = ""; }; + 756DE87D6FE64F0049E1627934D587F7 /* FIRDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase.h; path = Firebase/Database/Public/FIRDatabase.h; sourceTree = ""; }; + 764063E4BDC2B2AC40BEFF95355FD7FC /* GDTCORUploadPackage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadPackage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m; sourceTree = ""; }; + 768C30DB00B3D3283040ADCD760D66B2 /* FTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTree.m; path = Firebase/Database/Core/Utilities/FTree.m; sourceTree = ""; }; + 7733F0D190599F8D103BA7AC9BF61FB2 /* FIRRetryHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRRetryHelper.m; path = Firebase/Database/Core/Utilities/FIRRetryHelper.m; sourceTree = ""; }; + 77CBE6E614F5EBEABF6E32AB2EAA8A52 /* FirebaseInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstallations.h; path = FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h; sourceTree = ""; }; + 782C6082710A31FBBFE0FF40C496D80F /* FEventGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventGenerator.m; path = Firebase/Database/FEventGenerator.m; sourceTree = ""; }; + 789BC906E9C7035CD6F53282CE3AA453 /* FTreeSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h; sourceTree = ""; }; + 793FDF0150561467E6DDF33320B696A9 /* FBLPromise+Delay.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Delay.m"; path = "Sources/FBLPromises/FBLPromise+Delay.m"; sourceTree = ""; }; + 7960FB1C76F2424FD931382B8D99FE6A /* Pods-PediatricPancreas.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas.debug.xcconfig"; sourceTree = ""; }; + 7983B3F70324C775988EB7A1E3932685 /* FBLPromise+Then.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Then.m"; path = "Sources/FBLPromises/FBLPromise+Then.m"; sourceTree = ""; }; + 7A820887FD76849A2C54FED3B31C6E2E /* comparator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = comparator.h; path = include/leveldb/comparator.h; sourceTree = ""; }; + 7B29E9518D65490F1E33B2B30B23ADCB /* FTreeNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeNode.m; path = Firebase/Database/Core/Utilities/FTreeNode.m; sourceTree = ""; }; + 7C563C7E60320BE9BE84B966C5A1702F /* GULSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSwizzler.h; path = GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h; sourceTree = ""; }; + 7C698FE3E8F0E520BE6B395F5CAA16F6 /* FCompoundWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundWrite.m; path = Firebase/Database/Snapshot/FCompoundWrite.m; sourceTree = ""; }; + 7CC5F567A3E69A2FF89366D3265864D0 /* FTupleObjectNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjectNode.m; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.m; sourceTree = ""; }; + 7D41CCAE0E65DD892BC17B14CD65AE6F /* FTypedefs_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs_Private.h; path = Firebase/Database/Api/Private/FTypedefs_Private.h; sourceTree = ""; }; + 7DA049BCB41CCA3C4CC0998EE845FC32 /* FBLPromiseError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromiseError.h; path = Sources/FBLPromises/include/FBLPromiseError.h; sourceTree = ""; }; + 7E0C77D04FB7F6ADF79B05024865F975 /* FirebaseCore.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCore.modulemap; sourceTree = ""; }; + 7E160A281F114096E68F71EE98DB00F8 /* Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh"; sourceTree = ""; }; + 7E32B2315E2CC544C7D95BA6F99EC432 /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + 7EA45B5C00F15C4CCF12F75EEA5288FA /* GDTCORStorage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStorage_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h; sourceTree = ""; }; + 7EE99081D914925E41102736BBD49557 /* FIRInstanceIDVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDVersionUtilities.h; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.h; sourceTree = ""; }; + 7EFEFAB171B0614C38F1C781DB2D1FE3 /* FIRInstanceIDAuthService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthService.h; path = Firebase/InstanceID/FIRInstanceIDAuthService.h; sourceTree = ""; }; + 7F71B5A123DF00AD98FAF2759DD9F983 /* FKeyIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeyIndex.h; path = Firebase/Database/FKeyIndex.h; sourceTree = ""; }; + 7FA340141092E3961C06B4C346F61E9F /* FIRInstallationsAPIService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAPIService.m; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m; sourceTree = ""; }; + 801F763C867E44EE28B55C1FBA1D58CE /* FIRInstanceIDTokenDeleteOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenDeleteOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m; sourceTree = ""; }; + 8091FFAE87FD3FA3AE8ED56E6859B4F0 /* FValueIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueIndex.m; path = Firebase/Database/FValueIndex.m; sourceTree = ""; }; + 80CE823A231F46D35C99B77FE37C2680 /* FTupleRemovedQueriesEvents.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleRemovedQueriesEvents.h; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h; sourceTree = ""; }; + 813307FB7EF7DEF7EB26B719D22EC86A /* testharness.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testharness.h; path = util/testharness.h; sourceTree = ""; }; + 8157CF91D79E2D82F9E3A84E1F373B78 /* FLimitedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLimitedFilter.h; path = Firebase/Database/Core/View/Filter/FLimitedFilter.h; sourceTree = ""; }; + 81C33A153E19967E3445E344E55BED54 /* FIRDataSnapshot_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot_Private.h; path = Firebase/Database/Api/Private/FIRDataSnapshot_Private.h; sourceTree = ""; }; + 8245B1F254DC9F182514403D6091F777 /* GoogleDataTransport.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransport.debug.xcconfig; sourceTree = ""; }; + 82C4CF4D53142C0C4CF6949E22FC3124 /* FirebaseAuthInterop.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAuthInterop.release.xcconfig; sourceTree = ""; }; + 8320D8163EAA29B0F855EB271690E30F /* pb_common.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_common.c; sourceTree = ""; }; + 832796FD22EEC1442E1D5058AE06473C /* FIRServerValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRServerValue.m; path = Firebase/Database/Api/FIRServerValue.m; sourceTree = ""; }; + 832DEDF9B8FB5DB7840D30D124CC4856 /* GDTCORRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORRegistrar.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m; sourceTree = ""; }; + 8387D908A0D8C85843E77A633F96933F /* FIRTransactionResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRTransactionResult.m; path = Firebase/Database/Api/FIRTransactionResult.m; sourceTree = ""; }; + 83E6D3617089AEC1DD83534C656365C9 /* log_writer.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_writer.cc; path = db/log_writer.cc; sourceTree = ""; }; + 83F1C74FCB7D27EEDD0F20E80317A163 /* FBLPromise+Wrap.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Wrap.m"; path = "Sources/FBLPromises/FBLPromise+Wrap.m"; sourceTree = ""; }; + 84105C2E03C766F137C523748AFABA19 /* FPriorityIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPriorityIndex.h; path = Firebase/Database/FPriorityIndex.h; sourceTree = ""; }; + 8471B9B04CF93EE03047131EA36E6938 /* FNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNode.h; path = Firebase/Database/Snapshot/FNode.h; sourceTree = ""; }; + 848DF70F7272DBB5E881092F5958348A /* FAtomicNumber.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAtomicNumber.h; path = Firebase/Database/Utilities/FAtomicNumber.h; sourceTree = ""; }; + 84A06B13C9427E8DC216B2155A9A4C51 /* GDTCORReachability.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h; sourceTree = ""; }; + 84AB4D11B745E92F4CDD206AFE2E0660 /* FView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FView.h; path = Firebase/Database/Core/View/FView.h; sourceTree = ""; }; + 852C7911EDA4AF68E0A658A3B70F5D0B /* FIRInstanceIDConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDConstants.m; path = Firebase/InstanceID/FIRInstanceIDConstants.m; sourceTree = ""; }; + 855AA79FFF7DE13C4E817A31871AFEE6 /* FIRInstanceIDCheckinPreferences.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinPreferences.m; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m; sourceTree = ""; }; + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransport.framework; path = GoogleDataTransport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 857C2725A4F0AF79A30DEC50DA6A0E48 /* PromisesObjC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PromisesObjC.release.xcconfig; sourceTree = ""; }; + 85BFB0EA5C7CE6AD700F7323053A5AB3 /* FPersistenceManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistenceManager.m; path = Firebase/Database/Persistence/FPersistenceManager.m; sourceTree = ""; }; + 8625031D0810B04DC3327766C1F960D3 /* FCompoundWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundWrite.h; path = Firebase/Database/Snapshot/FCompoundWrite.h; sourceTree = ""; }; + 86A0153033585BE52A436ADC9565571C /* FIRInstanceIDCombinedHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCombinedHandler.h; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.h; sourceTree = ""; }; + 87305E67A3F0888418FD5FB15A3AACE9 /* GoogleAppMeasurement.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.debug.xcconfig; sourceTree = ""; }; + 874C68D17B12C1F819AD0ADEA831EAFE /* FListenComplete.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenComplete.m; path = Firebase/Database/FListenComplete.m; sourceTree = ""; }; + 878E027D5C73EDA05B5D73F2457F6E20 /* FTupleObjects.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjects.m; path = Firebase/Database/Utilities/Tuples/FTupleObjects.m; sourceTree = ""; }; + 881C688EF05D37FB42E12434920FDBF4 /* pb_decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_decode.h; sourceTree = ""; }; + 8839E366E23EFB0A1D7CAA675A691EE8 /* FQueryParams.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQueryParams.h; path = Firebase/Database/Core/FQueryParams.h; sourceTree = ""; }; + 885E13D41349DE2BB195AC2FC78B3D8C /* FIRInstallationsStoredItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredItem.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m; sourceTree = ""; }; + 88A9B676AACC9D2E626E041CFCDA7772 /* FIRInstanceIDConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDConstants.h; path = Firebase/InstanceID/FIRInstanceIDConstants.h; sourceTree = ""; }; + 892DFA98C0B6B4BA1A9DA101054D73CD /* FIRInstallationsIIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h; sourceTree = ""; }; + 89D3EEC62CA2D9B28936A1B89A9733C8 /* GDTCORUploadPackage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h; sourceTree = ""; }; + 89EF1757A361BC3BE2727F86201C94F8 /* FBLPromise+Any.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Any.h"; path = "Sources/FBLPromises/include/FBLPromise+Any.h"; sourceTree = ""; }; + 89EFDC2FBFA53532A9CAAEA608E7C222 /* GDTCORUploadCoordinator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadCoordinator.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m; sourceTree = ""; }; + 8ABDCEADCDB0A5F734C40BD872DD9C0B /* FIRLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLoggerLevel.h; path = FirebaseCore/Sources/Public/FIRLoggerLevel.h; sourceTree = ""; }; + 8AC10901C2F79CFA82FEAE4AAF01ABED /* FIRInstanceIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStore.h; path = Firebase/InstanceID/FIRInstanceIDStore.h; sourceTree = ""; }; + 8AEFE796A73D36A9215F664981D72C70 /* table_cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_cache.h; path = db/table_cache.h; sourceTree = ""; }; + 8B445347E43C90E24AE0CFABC51EB3F9 /* GULNetwork.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetwork.h; path = GoogleUtilities/Network/Private/GULNetwork.h; sourceTree = ""; }; + 8B475A67F01481B39D7F5EBD1FADD957 /* FirebaseCoreDiagnostics-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCoreDiagnostics-dummy.m"; sourceTree = ""; }; + 8B8FA4B0B8B53577758148C4B29CB05F /* write_batch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch.h; path = include/leveldb/write_batch.h; sourceTree = ""; }; + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCoreDiagnostics.framework; path = FirebaseCoreDiagnostics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CE91982EF784FDD0B9C73AE4E76797D /* FIRInstallationsStoredItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredItem.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h; sourceTree = ""; }; + 8CFAD347C460AFFC4F90B3045452C74D /* FIRInstanceIDTokenFetchOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenFetchOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h; sourceTree = ""; }; + 8D47D02F704DF255E65A5CD36CF9D48E /* GULNetworkURLSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkURLSession.m; path = GoogleUtilities/Network/GULNetworkURLSession.m; sourceTree = ""; }; + 8D5175073773047C9EBB484D43935067 /* status.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = status.h; path = include/leveldb/status.h; sourceTree = ""; }; + 8D8AFA1CE839BF7B31F847CE180844A5 /* FIRNoopAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRNoopAuthTokenProvider.m; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.m; sourceTree = ""; }; + 8DBA7964674155E29C594DE8DB9611B6 /* nanopb-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-prefix.pch"; sourceTree = ""; }; + 8E9F51951C4877C29BD86424B88DBA62 /* GULUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULUserDefaults.h; path = GoogleUtilities/UserDefaults/Private/GULUserDefaults.h; sourceTree = ""; }; + 8EAB5FF47F39A44B872B1E1191579AEA /* FChildChangeAccumulator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildChangeAccumulator.h; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h; sourceTree = ""; }; + 8F05E89B63938864335C55A44A0A73B7 /* FBLPromise+All.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+All.m"; path = "Sources/FBLPromises/FBLPromise+All.m"; sourceTree = ""; }; + 8F51779B334E9D371C089C2D84A4C309 /* port_stdcxx.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_stdcxx.h; path = port/port_stdcxx.h; sourceTree = ""; }; + 90229CCE5D34D7A531E16765B37ABE39 /* FBLPromise+Catch.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Catch.m"; path = "Sources/FBLPromises/FBLPromise+Catch.m"; sourceTree = ""; }; + 903B2BDF7FCE5660EC3EF7289DAFB10E /* FRangeMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangeMerge.h; path = Firebase/Database/Core/FRangeMerge.h; sourceTree = ""; }; + 90C235774B7FEFA58692D00424C37A4B /* FBLPromise+All.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+All.h"; path = "Sources/FBLPromises/include/FBLPromise+All.h"; sourceTree = ""; }; + 911A01616C728841C697AB49826AC324 /* FWriteRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteRecord.m; path = Firebase/Database/Core/FWriteRecord.m; sourceTree = ""; }; + 91714649A9785EF95152BD5F0A1B1F45 /* GULReachabilityChecker+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULReachabilityChecker+Internal.h"; path = "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h"; sourceTree = ""; }; + 92B0F3647F558C2051897581E20E8AA5 /* merger.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = merger.cc; path = table/merger.cc; sourceTree = ""; }; + 93CDDE38F05478019E633026BB5DF3F8 /* GULNSData+zlib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULNSData+zlib.h"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"; sourceTree = ""; }; + 9426AF07444B347C55EF8E50812A5EAB /* FIRAnalyticsConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsConfiguration.h; path = FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h; sourceTree = ""; }; + 9466A7E6EE64E7107817BB3DD4AB65AE /* GoogleUtilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-umbrella.h"; sourceTree = ""; }; + 9508F4557EAC2FA9BC5AE4521AE1415A /* FViewProcessorResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessorResult.m; path = Firebase/Database/FViewProcessorResult.m; sourceTree = ""; }; + 9509AC17857ED363396A3E274326F0BC /* testutil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testutil.h; path = util/testutil.h; sourceTree = ""; }; + 954224218DA6DB484D27DFDAEF45E7B4 /* GDTCOREvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCOREvent.m; path = GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m; sourceTree = ""; }; + 975851733C4EF17619E794A66DD652A8 /* env.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env.h; path = include/leveldb/env.h; sourceTree = ""; }; + 97AEA888054F9AC998F31369474D10B3 /* FPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPath.h; path = Firebase/Database/Core/Utilities/FPath.h; sourceTree = ""; }; + 98306E8E1C87D94B702DACAAB6768B53 /* fbase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fbase64.h; path = Firebase/Database/third_party/SocketRocket/fbase64.h; sourceTree = ""; }; + 9857113D2F1E85DDF6449FFE23D64413 /* leveldb-library-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "leveldb-library-dummy.m"; sourceTree = ""; }; + 9878778F95F524E3A075A234B58960B9 /* FIRInstallationsItem+RegisterInstallationAPI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstallationsItem+RegisterInstallationAPI.h"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h"; sourceTree = ""; }; + 98C983DA955E0638D50257AEF6623BC4 /* FIRInstanceIDURLQueryItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDURLQueryItem.h; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.h; sourceTree = ""; }; + 99CB6929C9B9E330102E12BC10ADBE67 /* FBLPromise+Catch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Catch.h"; path = "Sources/FBLPromises/include/FBLPromise+Catch.h"; sourceTree = ""; }; + 9A48322D21C211FB16E7DB64E6B5AB6E /* arena.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = arena.h; path = util/arena.h; sourceTree = ""; }; + 9A6B7D017E8C22F0382985F7884DF8B8 /* FTreeSortedDictionaryEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionaryEnumerator.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m; sourceTree = ""; }; + 9AD1150B6BD9EFAE172F16CD4B82379A /* FRepoInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoInfo.m; path = Firebase/Database/Core/FRepoInfo.m; sourceTree = ""; }; + 9AD1456814B75D3A95FA64D7320BA8CC /* FIRInstanceIDDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDDefines.h; path = Firebase/InstanceID/FIRInstanceIDDefines.h; sourceTree = ""; }; + 9AF055035432D0F1EB1F9ED475A81A00 /* NSError+FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRInstanceID.m"; path = "Firebase/InstanceID/NSError+FIRInstanceID.m"; sourceTree = ""; }; + 9B4C695F884374A04733A8358081E649 /* FIRInstanceIDCheckinPreferences+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDCheckinPreferences+Internal.h"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"; sourceTree = ""; }; + 9BC630AE6D6E92874C62C4D23F10958E /* FSnapshotUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotUtilities.m; path = Firebase/Database/Snapshot/FSnapshotUtilities.m; sourceTree = ""; }; + 9BCD2A51AB838CC30EACE2C5FE09CD59 /* FChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChange.m; path = Firebase/Database/Core/View/FChange.m; sourceTree = ""; }; + 9C2D17D624A2FB0F013DC69FEE7F9531 /* FView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FView.m; path = Firebase/Database/Core/View/FView.m; sourceTree = ""; }; + 9CAC4510A566921C9F90A3C21FB371DA /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + 9CC03C75A089757D74469A154727F5CD /* FTrackedQueryManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQueryManager.m; path = Firebase/Database/Persistence/FTrackedQueryManager.m; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9DB4215D54529564ADDF9449A77C3C99 /* FirebaseInstallations.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstallations.debug.xcconfig; sourceTree = ""; }; + 9DD615F709C03B469833C0AD4EC286D9 /* FValueEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueEventRegistration.m; path = Firebase/Database/Core/View/FValueEventRegistration.m; sourceTree = ""; }; + 9E3CBD22B698222D11A402DA18253A70 /* FIRInstanceIDTokenOperation+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDTokenOperation+Private.h"; path = "Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h"; sourceTree = ""; }; + 9EC147AA53DDCE9113303230BAA16823 /* FirebaseDatabase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseDatabase-dummy.m"; sourceTree = ""; }; + 9F1F2773CA1EAE4D8A704AEEFD180CCD /* cct.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cct.nanopb.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h; sourceTree = ""; }; + 9FFAA5D9CE88732904C77C404AC91429 /* leveldb-library.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "leveldb-library.modulemap"; sourceTree = ""; }; + A09D01D4E0A074E9C10E52E070322766 /* FChildrenNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildrenNode.h; path = Firebase/Database/Snapshot/FChildrenNode.h; sourceTree = ""; }; + A0CBF92D27BF20F0173D84B2D7B5BDB7 /* FIRBundleUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRBundleUtil.m; path = FirebaseCore/Sources/FIRBundleUtil.m; sourceTree = ""; }; + A1045E08CCC93351443EF0041C65E071 /* GULLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLogger.h; path = GoogleUtilities/Logger/Private/GULLogger.h; sourceTree = ""; }; + A1AE308C5F0E074A28931424B649BFB6 /* firebasecore.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = firebasecore.nanopb.c; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c; sourceTree = ""; }; + A236AD4499A5E6DCBA8204CB68484B08 /* NSData+SRB64Additions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+SRB64Additions.h"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h"; sourceTree = ""; }; + A2927D87478BAC6E0BF0481759116A7F /* GDTCCTCompressionHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTCompressionHelper.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h; sourceTree = ""; }; + A2BABC8EE3398D6E3B11BEBB4BDDA527 /* port.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port.h; path = port/port.h; sourceTree = ""; }; + A2D7E4828D2181423CA7DD6FA9418C84 /* GDTCCTPrioritizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTPrioritizer.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m; sourceTree = ""; }; + A30D980013D4A49BB4B9AF281EC66F68 /* FCancelEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCancelEvent.m; path = Firebase/Database/Core/View/FCancelEvent.m; sourceTree = ""; }; + A32910BBD1B9FC60DD70E012F4F8065F /* iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator.h; path = include/leveldb/iterator.h; sourceTree = ""; }; + A3C2A80012BC975B349FB09DA77B8850 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + A3D64D73BE83CC3A36E53B1E36DC26BE /* FChildChangeAccumulator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildChangeAccumulator.m; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m; sourceTree = ""; }; + A3FA603E46D511623D3630CAE0F5C1F3 /* GDTCORTransport_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h; sourceTree = ""; }; + A4166E7662CC5AAA26F1AB619EC69E13 /* GULApplication.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULApplication.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h; sourceTree = ""; }; + A4556B043AB0DAFFE7F063B549ECF6AD /* GULNetworkConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkConstants.h; path = GoogleUtilities/Network/Private/GULNetworkConstants.h; sourceTree = ""; }; + A49B8B76E453094FFA6318AAA24AA4EE /* GULNetworkURLSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkURLSession.h; path = GoogleUtilities/Network/Private/GULNetworkURLSession.h; sourceTree = ""; }; + A51275DED8B5876B1EB201F7E40D4517 /* FBLPromise+Testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Testing.h"; path = "Sources/FBLPromises/include/FBLPromise+Testing.h"; sourceTree = ""; }; + A51F851D55A40196F404D20CC95BAD99 /* FirebaseCoreDiagnosticsInterop.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnosticsInterop.debug.xcconfig; sourceTree = ""; }; + A5C471E66465A3AD8773DDA0113CF313 /* FIRDatabaseQuery_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h; sourceTree = ""; }; + A60A55723949183FAB49E5B3D9577924 /* GoogleDataTransport.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransport.release.xcconfig; sourceTree = ""; }; + A65321EB88EA8A0A7B7F1D040CDBDE0A /* FUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUtilities.h; path = Firebase/Database/Utilities/FUtilities.h; sourceTree = ""; }; + A680F32866E1A09336694B099C04AF81 /* FBLPromise+Recover.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Recover.h"; path = "Sources/FBLPromises/include/FBLPromise+Recover.h"; sourceTree = ""; }; + A6C32388BA9394C95A78AE1D39EDD150 /* GDTCOREventDataObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventDataObject.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h; sourceTree = ""; }; + A88033DCEC6D14ED10C3F3C8FF7981C7 /* db_impl.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_impl.cc; path = db/db_impl.cc; sourceTree = ""; }; + A8F66572B286F803446413533812835C /* FNodeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNodeFilter.h; path = Firebase/Database/Core/View/Filter/FNodeFilter.h; sourceTree = ""; }; + A9364051DE6DB776B1CFB70C96D51F3A /* FWebSocketConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWebSocketConnection.m; path = Firebase/Database/Realtime/FWebSocketConnection.m; sourceTree = ""; }; + A98E3F14C60B35AC913D88C97E2B5972 /* GULAppDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppDelegateSwizzler.m; path = GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m; sourceTree = ""; }; + A9A07FADE7126A2EBA873664735E0563 /* GDTCOREvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h; sourceTree = ""; }; + AA212DD1CD76575F40EB8CABCA92FF1A /* FIRDatabaseConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseConfig.m; path = Firebase/Database/Api/FIRDatabaseConfig.m; sourceTree = ""; }; + AAA8E1EFC2A415EAD47ED600FEDFB8A0 /* table_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_builder.cc; path = table/table_builder.cc; sourceTree = ""; }; + ABFA60EA6B3C819ADA0E147A88E113E0 /* FTransformedEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTransformedEnumerator.m; path = Firebase/Database/FTransformedEnumerator.m; sourceTree = ""; }; + ACF43B6D0673E47C821DE97D5D2237CB /* FIRDatabaseReference.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseReference.m; path = Firebase/Database/FIRDatabaseReference.m; sourceTree = ""; }; + AD600D36912F30C50EFC184EE3D04F7E /* c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = c.cc; path = db/c.cc; sourceTree = ""; }; + ADD2FCA292915B2E6B0381A7040CB1E6 /* FCompleteChildSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompleteChildSource.h; path = Firebase/Database/Core/View/Filter/FCompleteChildSource.h; sourceTree = ""; }; + ADE3D3BC42C093C1B8BBB0454B40B83E /* FIRDataEventType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataEventType.h; path = Firebase/Database/Public/FIRDataEventType.h; sourceTree = ""; }; + AE0A767C52FD5794347BB98E80936166 /* GDTCCTNanopbHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTNanopbHelpers.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h; sourceTree = ""; }; + AE0CD47B189B10242AD0B8643930F413 /* FTupleSetIdPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleSetIdPath.m; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m; sourceTree = ""; }; + AE5599B51674FD217CF4064C4D6DDFF5 /* FNextPushId.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNextPushId.m; path = Firebase/Database/Utilities/FNextPushId.m; sourceTree = ""; }; + AF06957A0771C86EF3C7DBAF75A4F553 /* GDTCORTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransformer.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m; sourceTree = ""; }; + AF3E068B4B32BE9AA15D6F3ABDDA7325 /* FViewCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewCache.m; path = Firebase/Database/Core/View/FViewCache.m; sourceTree = ""; }; + AF6C3EBCD2C9B78F9071C9BA34584A60 /* two_level_iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = two_level_iterator.h; path = table/two_level_iterator.h; sourceTree = ""; }; + AF74E221F17A2E24C2B42D1BC778DAC6 /* FChildrenNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildrenNode.m; path = Firebase/Database/Snapshot/FChildrenNode.m; sourceTree = ""; }; + AFB0D7EB1E556FEB7B8B8BABE4313A1B /* Pods-PediatricPancreas-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PediatricPancreas-umbrella.h"; sourceTree = ""; }; + AFF7787A89CE9402712586AA44B4A30B /* FIRDataSnapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDataSnapshot.m; path = Firebase/Database/Api/FIRDataSnapshot.m; sourceTree = ""; }; + B001400E85F272915939718E17EBFD25 /* FIndexedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedFilter.m; path = Firebase/Database/Core/View/Filter/FIndexedFilter.m; sourceTree = ""; }; + B01E3EBC54F74EB224BC9FAB87F151F2 /* repair.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = repair.cc; path = db/repair.cc; sourceTree = ""; }; + B121F2A73420BD133A4CBD674492FC12 /* FTupleFirebase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleFirebase.m; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.m; sourceTree = ""; }; + B16323EDF0B3CD0A257043DF559E872F /* FirebaseCore.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.release.xcconfig; sourceTree = ""; }; + B17CF74C10270725403C6592D2382E9E /* GDTCCTUploader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTUploader.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m; sourceTree = ""; }; + B189B07C114807A1945A3116776D2A43 /* FIRInstanceIDTokenOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.m; sourceTree = ""; }; + B1D25D46D0D17BB9DBF55A909B2D119F /* FIRAppAssociationRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAppAssociationRegistration.m; path = FirebaseCore/Sources/FIRAppAssociationRegistration.m; sourceTree = ""; }; + B1E88FA45FE369396DDE94F30F4EC58D /* FirebaseInstallations.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstallations.modulemap; sourceTree = ""; }; + B1ED778C9852BEF45C9DB36A28CC3F74 /* GoogleDataTransport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransport-dummy.m"; sourceTree = ""; }; + B24AD89FADA9EEF707A29719300BBAE7 /* FirebaseAnalytics.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.debug.xcconfig; sourceTree = ""; }; + B3288029B62F60168CD0B5922E5D3F0B /* pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb.h; sourceTree = ""; }; + B35084C018CB2A2FAF2A8E47B9341A94 /* FArraySortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FArraySortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h; sourceTree = ""; }; + B3CBA0DE4566EF24CD679F6D52B2AF0E /* GULAppDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h; sourceTree = ""; }; + B422450B8B9A222431185AE041CCA41D /* FIRDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDiagnosticsData.h; path = FirebaseCore/Sources/Private/FIRDiagnosticsData.h; sourceTree = ""; }; + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleUtilities.framework; path = GoogleUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B48FF961E99ECC80C015283501933E9F /* FTupleOnDisconnect.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleOnDisconnect.m; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m; sourceTree = ""; }; + B4AFED41CC4D9C2FD5B2C41C3E970AD3 /* FIRInstallationsIDController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIDController.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m; sourceTree = ""; }; + B5399854B710AA8DCDC59D42010EBE33 /* GDTCORReachability_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h; sourceTree = ""; }; + B560A05DDD10C41F219BD93A94B08293 /* FIRInstallationsAuthTokenResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAuthTokenResult.m; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m; sourceTree = ""; }; + B61358592FDB40CF8A657BFD252B3416 /* FTrackedQueryManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQueryManager.h; path = Firebase/Database/Persistence/FTrackedQueryManager.h; sourceTree = ""; }; + B6243AA00C08AE7508A9487E0DD106A5 /* FCompoundHash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundHash.h; path = Firebase/Database/Core/FCompoundHash.h; sourceTree = ""; }; + B63C250262739AA04B6D0027DDF4902F /* FValidation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValidation.m; path = Firebase/Database/Utilities/FValidation.m; sourceTree = ""; }; + B6AB2E6D2B1419D09CFF28AED2C2B388 /* GULSecureCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSecureCoding.m; path = GoogleUtilities/Environment/GULSecureCoding.m; sourceTree = ""; }; + B7B9AFFBA75FF2D8A831275F9A83318F /* version_set.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_set.cc; path = db/version_set.cc; sourceTree = ""; }; + B7EC032D36A1A28E006B92BAF996CC3E /* FTreeSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m; sourceTree = ""; }; + B833EBA86E1C3BE131AB895BCDE61AA1 /* GDTCORRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h; sourceTree = ""; }; + B880DC9BE4C9FE6FDA8BF6D351C8595A /* random.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = random.h; path = util/random.h; sourceTree = ""; }; + B8EAECB74DB46EE2F89DFCA3A335276C /* FIRMutableData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData.h; path = Firebase/Database/Public/FIRMutableData.h; sourceTree = ""; }; + B922785EA83E6FEB9DA16973EBF01646 /* FTupleFirebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleFirebase.h; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.h; sourceTree = ""; }; + B9D9A71F70ACC4A28A21C50E73140250 /* FAckUserWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAckUserWrite.m; path = Firebase/Database/Core/Operation/FAckUserWrite.m; sourceTree = ""; }; + BA096BF345BE538F99DE48F146E7B6AE /* FWriteTreeRef.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTreeRef.m; path = Firebase/Database/Core/FWriteTreeRef.m; sourceTree = ""; }; + BA1D3CE763B4DFB39712DC2D0F9C6C96 /* filter_policy.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_policy.cc; path = util/filter_policy.cc; sourceTree = ""; }; + BA7A11DD2C5A7EB1CBDB888741E122AF /* Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h"; sourceTree = ""; }; + BAD71520F0592D6FFF74F12C378D529F /* FRepo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepo.m; path = Firebase/Database/Core/FRepo.m; sourceTree = ""; }; + BB2BA88758CD8F3F42FDA4887D47257A /* FAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAuthTokenProvider.m; path = Firebase/Database/Login/FAuthTokenProvider.m; sourceTree = ""; }; + BB5C170B61C645EBD115F14EB5249AF0 /* GULReachabilityChecker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULReachabilityChecker.m; path = GoogleUtilities/Reachability/GULReachabilityChecker.m; sourceTree = ""; }; + BBC3359829EE0F378AD8D40332B7FFB9 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; + BBEA5A247884A7C3F759610363D9FD71 /* options.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = options.cc; path = util/options.cc; sourceTree = ""; }; + BCDBC9E6585A6FC8409A7900F72E6143 /* env_posix_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_posix_test_helper.h; path = util/env_posix_test_helper.h; sourceTree = ""; }; + BDEAF60599B3C1E34E2CA1FC766785CB /* FIRInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallations.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallations.h; sourceTree = ""; }; + BE12109DCA730DE54BFFE4D8BAAD3272 /* FTupleCallbackStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleCallbackStatus.h; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h; sourceTree = ""; }; + BE21DDFAF668870C165692DA4385D672 /* GDTCORStoredEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStoredEvent.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h; sourceTree = ""; }; + BE2D52670C14C984DFC35B074D8D9E05 /* Pods-PediatricPancreasTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PediatricPancreasTests.modulemap"; sourceTree = ""; }; + BF9C8E91EB9306CDE7F9886606461EE0 /* FViewCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewCache.h; path = Firebase/Database/Core/View/FViewCache.h; sourceTree = ""; }; + BFCA9E7603A4EBE52A899B3964CCB141 /* FirebaseAuthInterop.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAuthInterop.debug.xcconfig; sourceTree = ""; }; + C03A03D30012B27E690AA4629A1913A9 /* FIRDatabaseReference.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference.h; path = Firebase/Database/Public/FIRDatabaseReference.h; sourceTree = ""; }; + C099348FF2762A50FC42CDA312B9414B /* Pods-PediatricPancreasTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreasTests.release.xcconfig"; sourceTree = ""; }; + C0A16BACD8F0BE6703DDD5DFA6AF4F0F /* FIRApp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRApp.h; path = FirebaseCore/Sources/Public/FIRApp.h; sourceTree = ""; }; + C17FA7E29878F0A856A40B1BEC779C9F /* FRepoInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoInfo.h; path = Firebase/Database/Core/FRepoInfo.h; sourceTree = ""; }; + C1830DD3C00085399D281E078B5A7CE1 /* GDTCORStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORStorage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m; sourceTree = ""; }; + C1D0CF348FD58D4E6F51BC58089A8946 /* FirebaseDatabase.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseDatabase.release.xcconfig; sourceTree = ""; }; + C2718A77E9D1B7AAB8B1E89B2B9AD22D /* APLevelDB.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = APLevelDB.h; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h"; sourceTree = ""; }; + C3731E4990AAEF341E76DB0A3AB7E6B0 /* c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = c.h; path = include/leveldb/c.h; sourceTree = ""; }; + C3AAC69E6988F1A4299931B9F19FDAB9 /* FIRInstanceIDVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDVersionUtilities.m; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.m; sourceTree = ""; }; + C4050A6B53B6F2A1D68A2112D200D0C5 /* GDTCORDataFuture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORDataFuture.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h; sourceTree = ""; }; + C4E576228987A62E57731963B7FD5E31 /* FCompoundHash.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundHash.m; path = Firebase/Database/Core/FCompoundHash.m; sourceTree = ""; }; + C55FA61E2BD999842193CE4030989F59 /* FIRInstanceIDLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDLogger.m; path = Firebase/InstanceID/FIRInstanceIDLogger.m; sourceTree = ""; }; + C6F3604157287623FC134D9C84D970BF /* version_edit.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_edit.cc; path = db/version_edit.cc; sourceTree = ""; }; + C7DA56AEC2BBB09F0B17C011D33EFD87 /* FCacheNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCacheNode.m; path = Firebase/Database/Core/View/FCacheNode.m; sourceTree = ""; }; + C7DEE606CBB9A67C91F550224BCB72D8 /* filter_block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_block.h; path = table/filter_block.h; sourceTree = ""; }; + C85E4E623B4A72E522D791D20293F655 /* GDTCORLifecycle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORLifecycle.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h; sourceTree = ""; }; + C8B01D89754271F61E72A781D8CE2571 /* FIRInstanceIDAuthService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthService.m; path = Firebase/InstanceID/FIRInstanceIDAuthService.m; sourceTree = ""; }; + C8B26599A4CA608F5B170B0769926191 /* FEventRaiser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRaiser.h; path = Firebase/Database/Core/View/FEventRaiser.h; sourceTree = ""; }; + C971FDA3436CE4F78017B79B4063F5B2 /* leveldb-library.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "leveldb-library.release.xcconfig"; sourceTree = ""; }; + C9FDFEE5B3671FA221FDBC8ACFFA3041 /* GDTCORTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h; sourceTree = ""; }; + CA4C73E47837B0E3511A487AFC38A70B /* FMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMerge.h; path = Firebase/Database/Core/Operation/FMerge.h; sourceTree = ""; }; + CAD8EC4ABB74DAEA13817229074C883F /* block_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block_builder.cc; path = table/block_builder.cc; sourceTree = ""; }; + CB0616FB9FF2AAD7A912C19A189655DE /* options.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = options.h; path = include/leveldb/options.h; sourceTree = ""; }; + CB76A092BCA0D0C1E846F7D5856AA5EF /* FIRInstallationsStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStore.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m; sourceTree = ""; }; + CB79FD41C8FFFB07B28E71D46260F99A /* FViewProcessorResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessorResult.h; path = Firebase/Database/FViewProcessorResult.h; sourceTree = ""; }; + CB8195D549670F26815B3858895AC0DD /* FPendingPut.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPendingPut.h; path = Firebase/Database/Persistence/FPendingPut.h; sourceTree = ""; }; + CBA16637DCCE5CC8B2C6EE6EF4523671 /* FIRVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVersion.h; path = FirebaseCore/Sources/FIRVersion.h; sourceTree = ""; }; + CBB4910A187E43ED4826B25BAD824F43 /* table_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_builder.h; path = include/leveldb/table_builder.h; sourceTree = ""; }; + CBD27D618C4A13D97B4E96A9741DF66A /* FIRInstallationsIIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDTokenStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m; sourceTree = ""; }; + CC9FBF9F202D0BA6D21D1A878140A6E7 /* GULSceneDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler.h; path = GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h; sourceTree = ""; }; + CCF0CDBF79119FF6820FFA131F04236F /* FBLPromises.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromises.h; path = Sources/FBLPromises/include/FBLPromises.h; sourceTree = ""; }; + CD33D7886791A925EDD3E12E07C16039 /* mutexlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mutexlock.h; path = util/mutexlock.h; sourceTree = ""; }; + CD82CF0A8D09569DA4154DBE971388CB /* GDTCORPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPlatform.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h; sourceTree = ""; }; + CDD59F6FF7CD1CF4D22C5C4DD5A519F3 /* FIRInstallationsIIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m; sourceTree = ""; }; + CE70B8F0872CD5F6701BE7EE2B37F8E8 /* FIRDatabaseConfig_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig_Private.h; path = Firebase/Database/FIRDatabaseConfig_Private.h; sourceTree = ""; }; + CE981CCC7DE79FE32665CA534CDF326E /* Firebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Firebase.h; path = CoreOnly/Sources/Firebase.h; sourceTree = ""; }; + CF0903B3B61A95E960B197B8585D0B44 /* GULUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULUserDefaults.m; path = GoogleUtilities/UserDefaults/GULUserDefaults.m; sourceTree = ""; }; + CF26A853FCB235F746C7983DA67400B6 /* FirebaseInstanceID-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstanceID-Info.plist"; sourceTree = ""; }; + D022F7FBC81242923E8D67CA2E289BA0 /* FIRInstanceIDAuthKeyChain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthKeyChain.m; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m; sourceTree = ""; }; + D0B87C45F3772C3A9902A4E9D16C60C9 /* FIRInstanceIDURLQueryItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDURLQueryItem.m; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.m; sourceTree = ""; }; + D0ED6BAA2501018C4E87CD44859D6608 /* Pods-PediatricPancreas-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas-Info.plist"; sourceTree = ""; }; + D11FF29A1A4C44B50A32EA588B64D0FA /* FSyncTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncTree.m; path = Firebase/Database/Core/FSyncTree.m; sourceTree = ""; }; + D131FCC82D07749BA8F453BE243E3308 /* FIRMutableData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMutableData.m; path = Firebase/Database/Api/FIRMutableData.m; sourceTree = ""; }; + D162B1331B24ACB706028A659E347607 /* firebasecore.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = firebasecore.nanopb.h; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h; sourceTree = ""; }; + D23943CEFBF68D1DA83A20CA208EE0D0 /* FIRInstallationsHTTPError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsHTTPError.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h; sourceTree = ""; }; + D29F1B6F2D210493CE1B350B9E1190A6 /* GDTCORAssert.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORAssert.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m; sourceTree = ""; }; + D3EA4FED70C955814D3060BCA5FCD84D /* GULMutableDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULMutableDictionary.m; path = GoogleUtilities/Network/GULMutableDictionary.m; sourceTree = ""; }; + D3EF925BD0923A808B3AF3593EA2ABDB /* GULOriginalIMPConvenienceMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULOriginalIMPConvenienceMacros.h; path = GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h; sourceTree = ""; }; + D3F8923F8BF7B696F0F826E15C1D08E1 /* GDTCOREvent_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h; sourceTree = ""; }; + D3FC34E39CBFCA6990DA3BF467AD6C7D /* FIRInstanceIDAPNSInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAPNSInfo.m; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.m; sourceTree = ""; }; + D4B8BE02734895C466C402F08AFCFE27 /* status.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = status.cc; path = util/status.cc; sourceTree = ""; }; + D54A5395DBB67ECB6B503D7CCDCAE2A3 /* FIRInstanceIDAuthKeyChain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthKeyChain.h; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h; sourceTree = ""; }; + D5A546058E77F0752995F315FBF8385F /* FIRComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponent.m; path = FirebaseCore/Sources/FIRComponent.m; sourceTree = ""; }; + D5C117A339CC3C9E15D400EB57AE4176 /* snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = snapshot.h; path = db/snapshot.h; sourceTree = ""; }; + D5EB776A6BFE1187D7EC5CC46FE6F740 /* env_windows_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_windows_test_helper.h; path = util/env_windows_test_helper.h; sourceTree = ""; }; + D64EAECB9AE75FAD65FC8D0B02422580 /* FEventGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventGenerator.h; path = Firebase/Database/FEventGenerator.h; sourceTree = ""; }; + D68AE5E7D4434A5A3C27FE2C33DEF374 /* FWriteTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTree.h; path = Firebase/Database/Core/FWriteTree.h; sourceTree = ""; }; + D6AD17FB8B70E3033CE0DB1763A1A7B2 /* FEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEmptyNode.h; path = Firebase/Database/Snapshot/FEmptyNode.h; sourceTree = ""; }; + D85B0BBD6B9929A743D2EFEF5F5A089B /* FIRInstallationsKeychainUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsKeychainUtils.m; path = FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m; sourceTree = ""; }; + D887D5D2E2B630D2E0ECB4034734F45A /* FRangedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangedFilter.h; path = Firebase/Database/FRangedFilter.h; sourceTree = ""; }; + D8D77E896ACB460AC316ABCB1831F855 /* GoogleDataTransportCCTSupport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransportCCTSupport.modulemap; sourceTree = ""; }; + D90F32A060B026F6D87B7D74D28DC97C /* FBLPromise+Reduce.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Reduce.h"; path = "Sources/FBLPromises/include/FBLPromise+Reduce.h"; sourceTree = ""; }; + D9975934F005271D708CDC03FEA060AF /* db_iter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_iter.h; path = db/db_iter.h; sourceTree = ""; }; + DA6701FC5AB530406CBCD86ED01A7743 /* GoogleUtilities.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.debug.xcconfig; sourceTree = ""; }; + DB8C5BAA46113C178F139DA567DEC18F /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + DB8DBDD015B9A7C63AD7FF51FCD1CED6 /* FListenComplete.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenComplete.h; path = Firebase/Database/FListenComplete.h; sourceTree = ""; }; + DD144C3EC4E9FF7960E6B2C281A11227 /* FIRTransactionResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult.h; path = Firebase/Database/Public/FIRTransactionResult.h; sourceTree = ""; }; + DD26F8C71729674B441938E34E892134 /* GoogleAppMeasurement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleAppMeasurement.framework; path = Frameworks/GoogleAppMeasurement.framework; sourceTree = ""; }; + DDC164F6102A008EB68780B6F360A50A /* FBLPromise+Any.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Any.m"; path = "Sources/FBLPromises/FBLPromise+Any.m"; sourceTree = ""; }; + DE2016AF3072FDA306C33F4E0AFD83EC /* Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist"; sourceTree = ""; }; + DE20B3C2547CB5DDA522FADAB581891D /* block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block.h; path = table/block.h; sourceTree = ""; }; + DE49548AE3469F15EC0F3A8E7C0E12CA /* FIRDiagnosticsData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDiagnosticsData.m; path = FirebaseCore/Sources/FIRDiagnosticsData.m; sourceTree = ""; }; + DF0640ADF2E74C8DFB07534BE9B3BBAD /* log_writer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_writer.h; path = db/log_writer.h; sourceTree = ""; }; + DF1AE6443E291955DE6DE481F41F5408 /* coding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = coding.h; path = util/coding.h; sourceTree = ""; }; + DF667BD0C719334D242C99243B7287FE /* write_batch_internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch_internal.h; path = db/write_batch_internal.h; sourceTree = ""; }; + DF6767ED8AFFE68E3C7BEDECCCEEF733 /* nanopb-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "nanopb-dummy.m"; sourceTree = ""; }; + DF809DE6C9A673EBFDF59916F28E5826 /* Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist"; sourceTree = ""; }; + DF85A3A3AE8C4D175D5C543F24DF2FB4 /* FAtomicNumber.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAtomicNumber.m; path = Firebase/Database/Utilities/FAtomicNumber.m; sourceTree = ""; }; + DFCB1951C0F24D4ACC2A38DAECEA2065 /* FIRBundleUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRBundleUtil.h; path = FirebaseCore/Sources/FIRBundleUtil.h; sourceTree = ""; }; + DFF3F389C5FFC9338529BC11F026588E /* FIRInstanceIDCheckinPreferences+Internal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceIDCheckinPreferences+Internal.m"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m"; sourceTree = ""; }; + E0234DBF69A61BF3660F4C6F95F41E80 /* GoogleDataTransportCCTSupport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransportCCTSupport-dummy.m"; sourceTree = ""; }; + E0C3B65AB5EB25B07B491A17C3CBDACB /* FIRConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfiguration.h; path = FirebaseCore/Sources/Public/FIRConfiguration.h; sourceTree = ""; }; + E161DB825968B6D1274F18BC57F7781D /* FCachePolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCachePolicy.m; path = Firebase/Database/Persistence/FCachePolicy.m; sourceTree = ""; }; + E17BBB66CE95AF16025FD900BDAC46D7 /* GDTCORUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploader.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h; sourceTree = ""; }; + E1804140830E73C79880D6687271FAC9 /* FBLPromiseError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromiseError.m; path = Sources/FBLPromises/FBLPromiseError.m; sourceTree = ""; }; + E21218A3B8A841CFC4A0716AC72E30B0 /* FValueEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueEventRegistration.h; path = Firebase/Database/Core/View/FValueEventRegistration.h; sourceTree = ""; }; + E26C56006D98BED71A283F0AC2E12786 /* FMaxNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMaxNode.m; path = Firebase/Database/FMaxNode.m; sourceTree = ""; }; + E2A08AAB5D65AB79EB24EC26404117B7 /* table_cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_cache.cc; path = db/table_cache.cc; sourceTree = ""; }; + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCore.framework; path = FirebaseCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E337B401A2FCBCB3359E2A38291B7B4F /* pb_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_encode.h; sourceTree = ""; }; + E42CD6D50EE4BFF16E3DD5C5F9977780 /* FTrackedQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQuery.h; path = Firebase/Database/Persistence/FTrackedQuery.h; sourceTree = ""; }; + E4573AE1A9FBC7C15F78874BA9847666 /* NSError+FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRInstanceID.h"; path = "Firebase/InstanceID/NSError+FIRInstanceID.h"; sourceTree = ""; }; + E45F8CF91067F02738B6EA753E318E1E /* dumpfile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dumpfile.h; path = include/leveldb/dumpfile.h; sourceTree = ""; }; + E467841A32C8128E295B54A295D58D2E /* FirebaseAnalytics.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.release.xcconfig; sourceTree = ""; }; + E48B1808AA40A73BA3D46EA4AE5B3927 /* GDTCORReachability.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORReachability.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m; sourceTree = ""; }; + E48BE45942FA887A32872ECE30375ADB /* Pods-PediatricPancreasTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PediatricPancreasTests-umbrella.h"; sourceTree = ""; }; + E54CC79A075D9902E781D44FAB846BA8 /* FIRCoreDiagnosticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsInterop.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h; sourceTree = ""; }; + E5508FE08B3CA077BE34943206E069B5 /* FChildEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildEventRegistration.h; path = Firebase/Database/Core/View/FChildEventRegistration.h; sourceTree = ""; }; + E5D99095828A99E2D1AC9636C56E65CC /* FEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRegistration.h; path = Firebase/Database/Core/View/FEventRegistration.h; sourceTree = ""; }; + E61B535DAB4A7B24C60731AB49DF519A /* GDTCORTargets.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTargets.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h; sourceTree = ""; }; + E653C151D9C6CAC8F8FB64B0774210D0 /* crc32c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = crc32c.cc; path = util/crc32c.cc; sourceTree = ""; }; + E6908625F5FB22DD281BF38879C7EDCE /* FIRInstanceIDUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDUtilities.h; path = Firebase/InstanceID/FIRInstanceIDUtilities.h; sourceTree = ""; }; + E6C8EE55738FAA4E95659CF5A409F9D9 /* testharness.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = testharness.cc; path = util/testharness.cc; sourceTree = ""; }; + E6E84A81CE2FF3E0A915DAE54B7DAF41 /* FValueIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueIndex.h; path = Firebase/Database/FValueIndex.h; sourceTree = ""; }; + E7431CBAB5161E552D3F5FD4A6A4B48C /* FIRInstanceIDTokenInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenInfo.m; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.m; sourceTree = ""; }; + E7737C5E82B493FFA4C523BF0F15C33B /* FPersistentConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistentConnection.m; path = Firebase/Database/Core/FPersistentConnection.m; sourceTree = ""; }; + E77DB5111675718C49A01EBA83BAF493 /* pb_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_common.h; sourceTree = ""; }; + E83A950C90FADE82C6C50AB81CA86027 /* db_iter.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_iter.cc; path = db/db_iter.cc; sourceTree = ""; }; + E8528848BDEDC26C42D1B3137E78486D /* FBLPromise+Validate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Validate.h"; path = "Sources/FBLPromises/include/FBLPromise+Validate.h"; sourceTree = ""; }; + EA4707415187157C356E56CCEAB4A5B4 /* FDataEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FDataEvent.m; path = Firebase/Database/Core/View/FDataEvent.m; sourceTree = ""; }; + EA54A83590F15D08BA0EA2F09D24D2D3 /* GoogleAppMeasurement.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.release.xcconfig; sourceTree = ""; }; + EA66CFA4C0F8440600B673FB72ABD385 /* leveldb-library-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-prefix.pch"; sourceTree = ""; }; + EB5FE81C882FC64F8753116A5B70F2E6 /* FConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConstants.m; path = Firebase/Database/Constants/FConstants.m; sourceTree = ""; }; + EB69E36490C39B4946BAF571B5E6621E /* FirebaseDatabase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseDatabase-umbrella.h"; sourceTree = ""; }; + EB6CC861AA6CD619090F1C484BEFADA5 /* PromisesObjC-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "PromisesObjC-Info.plist"; sourceTree = ""; }; + EBB7BB312BA46B435C86D22D545460A6 /* posix_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = posix_logger.h; path = util/posix_logger.h; sourceTree = ""; }; + EBC953A34508AE16186590261C12C687 /* GDTCCTNanopbHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTNanopbHelpers.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m; sourceTree = ""; }; + EBDC269E1E8CFA6578C1F1FC4F7C4728 /* GDTCORPlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORPlatform.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m; sourceTree = ""; }; + EC3E044ABC83D63EDD13785CC93A4B4A /* FOperationSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperationSource.h; path = Firebase/Database/Core/Operation/FOperationSource.h; sourceTree = ""; }; + EC43FEF1CA9773F7407B76F3B8CE500E /* FirebaseCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCore.h; path = FirebaseCore/Sources/Public/FirebaseCore.h; sourceTree = ""; }; + EC6076EA5FF19E6726A6FEB3836F7451 /* FBLPromise+Recover.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Recover.m"; path = "Sources/FBLPromises/FBLPromise+Recover.m"; sourceTree = ""; }; + ED529DE57D865F4DC7EE0F3956AAB7DB /* block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block.cc; path = table/block.cc; sourceTree = ""; }; + EE1781250E9DF101BDFB90CB850C386F /* logging.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = logging.cc; path = util/logging.cc; sourceTree = ""; }; + EE347F70A1C0E9F79BF1982AA0AE5276 /* FIRInstallations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallations.m; path = FirebaseInstallations/Source/Library/FIRInstallations.m; sourceTree = ""; }; + EE8845E0152C938810B709F01172891E /* FIndexedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedFilter.h; path = Firebase/Database/Core/View/Filter/FIndexedFilter.h; sourceTree = ""; }; + EE99BAF073CA1D81781B1B25C847608F /* FBLPromise+Then.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Then.h"; path = "Sources/FBLPromises/include/FBLPromise+Then.h"; sourceTree = ""; }; + EED1AC6242127BDAA6E48B5C7662BA95 /* FIRInstanceIDLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDLogger.h; path = Firebase/InstanceID/FIRInstanceIDLogger.h; sourceTree = ""; }; + EEF250FBAA16E776552020D11B9C8A66 /* FirebaseInstanceID-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstanceID-dummy.m"; sourceTree = ""; }; + EF6C6710B2B163CE881A5BAE36D20B5D /* format.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = format.cc; path = table/format.cc; sourceTree = ""; }; + F04EDF68A0FB407E446327F460FEDF03 /* GDTCORUploadCoordinator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadCoordinator.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h; sourceTree = ""; }; + F0E17F44674DD5323FABD14840F7D509 /* FLLRBValueNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBValueNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m; sourceTree = ""; }; + F10C76FEC7DE64107890BCD0E69DE428 /* FBLPromise+Retry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Retry.h"; path = "Sources/FBLPromises/include/FBLPromise+Retry.h"; sourceTree = ""; }; + F189BAAA0B343A34C79A53561EF6E895 /* FIROptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptions.h; path = FirebaseCore/Sources/Public/FIROptions.h; sourceTree = ""; }; + F1E98655F6E57D3EBFA5F4C3BFD52EEB /* FIRInstanceIDTokenInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenInfo.h; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.h; sourceTree = ""; }; + F26B1F10B563CB6B30369228E750B277 /* FTupleTSN.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTSN.m; path = Firebase/Database/Utilities/Tuples/FTupleTSN.m; sourceTree = ""; }; + F345B60ED7E3934E7012324272612AE2 /* FIRAnalyticsConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAnalyticsConfiguration.m; path = FirebaseCore/Sources/FIRAnalyticsConfiguration.m; sourceTree = ""; }; + F3959B61A1A4E4F8AE1134134BC3F7B1 /* FIRInstanceIDCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinService.m; path = Firebase/InstanceID/FIRInstanceIDCheckinService.m; sourceTree = ""; }; + F3FE91D249283827126AA99EAB18DC0A /* format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = format.h; path = table/format.h; sourceTree = ""; }; + F459ED3E4C3C9D6C2650EEAF63B3FEDF /* FirebaseInstanceID-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstanceID-umbrella.h"; sourceTree = ""; }; + F4A3B19D1538DD146880608D2DA1FCAA /* GDTCORStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStorage.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h; sourceTree = ""; }; + F4F07B58CF53D2FCABD8B03E53455CE5 /* FBLPromise+Async.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Async.m"; path = "Sources/FBLPromises/FBLPromise+Async.m"; sourceTree = ""; }; + F51F769F4128614EC9AACBDED917D441 /* GoogleUtilities.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.release.xcconfig; sourceTree = ""; }; + F5343AFD79945A13C37E1EC1B6E62B25 /* FChildEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildEventRegistration.m; path = Firebase/Database/Core/View/FChildEventRegistration.m; sourceTree = ""; }; + F5977632C28C8A80798C83831080ACC9 /* GDTCORUploadPackage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h; sourceTree = ""; }; + F5B061141C7129BEE54C767270F97A96 /* Pods-PediatricPancreas.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PediatricPancreas.modulemap"; sourceTree = ""; }; + F5CEB151BEA86559CC6F1B460E2A6456 /* hash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = hash.h; path = util/hash.h; sourceTree = ""; }; + F61EB68986A7759962C52C309AF151B2 /* block_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block_builder.h; path = table/block_builder.h; sourceTree = ""; }; + F66F8E423E7A327C613AC805E253BB2F /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig"; sourceTree = ""; }; + F690E86D8C72F9C55C2E8AB28B37E07D /* FTupleTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTransaction.m; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.m; sourceTree = ""; }; + F71D48BEB6D4E6FD4232B3FBFE360494 /* FIRInstanceIDUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDUtilities.m; path = Firebase/InstanceID/FIRInstanceIDUtilities.m; sourceTree = ""; }; + F74A247A080EE95B1E78BEB99DA8AAA2 /* FTuplePathValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTuplePathValue.h; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.h; sourceTree = ""; }; + F777C5E65C22D85894FAC33B1AEB107D /* FBLPromise+Validate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Validate.m"; path = "Sources/FBLPromises/FBLPromise+Validate.m"; sourceTree = ""; }; + F79F298B4FF02587B6E3978DDC7D3FED /* FLLRBValueNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBValueNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h; sourceTree = ""; }; + F7F36453D48EB7DB0A3070832408980B /* FQueryParams.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQueryParams.m; path = Firebase/Database/Core/FQueryParams.m; sourceTree = ""; }; + F81A7101C3F68C1D5685C0AC60237A70 /* FIRInstanceIDCheckinStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinStore.h; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.h; sourceTree = ""; }; + F8E21755762B362FCA620ED488970ADF /* FTupleNodePath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleNodePath.h; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.h; sourceTree = ""; }; + F8FAAC19C9BC593A8592BFA3F979E482 /* env_posix.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env_posix.cc; path = util/env_posix.cc; sourceTree = ""; }; + F92D9CADD5265FD05D46F23EF0586CDF /* GoogleUtilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleUtilities.modulemap; sourceTree = ""; }; + F9CF4195F4E2D294C22312BCBCB5F019 /* FirebaseInstanceID.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstanceID.modulemap; sourceTree = ""; }; + FA39C6D824C47D10541A5DB3BBDE2263 /* skiplist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = skiplist.h; path = db/skiplist.h; sourceTree = ""; }; + FA46E5D5E0C2FA73D96E33137632ECAA /* two_level_iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = two_level_iterator.cc; path = table/two_level_iterator.cc; sourceTree = ""; }; + FA75AD53B36E8DAD1847CE0D8C8A15A9 /* FConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConstants.h; path = Firebase/Database/Constants/FConstants.h; sourceTree = ""; }; + FAB189ECD5A6C97091EA2695A36F518F /* FPersistenceManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistenceManager.h; path = Firebase/Database/Persistence/FPersistenceManager.h; sourceTree = ""; }; + FB7F5B838DF85F6A767CB414C4359375 /* FRepo_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo_Private.h; path = Firebase/Database/Core/FRepo_Private.h; sourceTree = ""; }; + FB8A36424CE63AB822739A749BB71C82 /* FBLPromise+Always.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Always.h"; path = "Sources/FBLPromises/include/FBLPromise+Always.h"; sourceTree = ""; }; + FB9061DB724B0A4703E5CFCB88C87A4A /* FMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMerge.m; path = Firebase/Database/Core/Operation/FMerge.m; sourceTree = ""; }; + FB991BB4D89DAB85EDF7100FBAFA1A13 /* FTupleOnDisconnect.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleOnDisconnect.h; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h; sourceTree = ""; }; + FBBACCFC3B4FD853FC952CC223D94ED0 /* FBLPromise+Timeout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Timeout.m"; path = "Sources/FBLPromises/FBLPromise+Timeout.m"; sourceTree = ""; }; + FBC8005390271EA0A8E1814D471860C1 /* FIndexedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedNode.m; path = Firebase/Database/Snapshot/FIndexedNode.m; sourceTree = ""; }; + FC08F6EF38191BE8F7E4F4CF74AF46C2 /* GoogleDataTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GoogleDataTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h; sourceTree = ""; }; + FC13A073E2E6654C9515F95CD5BAC0E8 /* FirebaseCoreDiagnostics-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCoreDiagnostics-umbrella.h"; sourceTree = ""; }; + FC7213970830A3E5E01229377CCD602D /* FIRDatabaseReference_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseReference_Private.h; sourceTree = ""; }; + FDBEE362A1AC58BB9A15CC82604155A6 /* GDTCORStoredEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORStoredEvent.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m; sourceTree = ""; }; + FDE125C0FE65AF0DB95E2AE362D9BE5B /* FTupleNodePath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleNodePath.m; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.m; sourceTree = ""; }; + FE000DCA7D5E753082D9590F1EAC1696 /* Pods_PediatricPancreasTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PediatricPancreasTests.framework; path = "Pods-PediatricPancreasTests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + FE4584B1E56CACAFB4FE9D377A31CB04 /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + FE6DB08072CCBBA9657F29B2A4B18F2A /* FTuplePathValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTuplePathValue.m; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.m; sourceTree = ""; }; + FE8952D00BD256B9079E38ED3637F926 /* GDTCORConsoleLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORConsoleLogger.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m; sourceTree = ""; }; + FEF9959C504C1429615F19DA2FA0DF5F /* FIRDatabaseQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery.h; path = Firebase/Database/Public/FIRDatabaseQuery.h; sourceTree = ""; }; + FF0E752DEBBB329AED0426B5DBA6F030 /* FTreeSortedDictionaryEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionaryEnumerator.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h; sourceTree = ""; }; + FF2C02F438734C5492E0887B31D61B29 /* FPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPath.m; path = Firebase/Database/Core/Utilities/FPath.m; sourceTree = ""; }; + FF8DF3F9B8EAE9DF3404C063DF67AE24 /* GULReachabilityChecker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityChecker.h; path = GoogleUtilities/Reachability/Private/GULReachabilityChecker.h; sourceTree = ""; }; + FFA9F0218DE9786B2346ABEDC657B815 /* FRangeMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangeMerge.m; path = Firebase/Database/Core/FRangeMerge.m; sourceTree = ""; }; + FFBDB88B2DD90C42C6967F3B1D569324 /* FTreeNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeNode.h; path = Firebase/Database/Core/Utilities/FTreeNode.h; sourceTree = ""; }; + FFD1A868DDA411E233111E156FB11FAD /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1C1298073446E5DEF7DB06E81CCE934F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 92375B897539D155FD76BCBEDE43BC6C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4303B8E8FA98891B596CE8DCC3372E19 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 76859CC0102F8E2B0F88A618987DD54E /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5802FFE25E6DDADD18C579CB17F03F14 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7385D9509941D28582315B957132D207 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 65510BFAC5CC2ED301641328162277E3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 78EFD0D62AD99147E88485CCA6870FDB /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6746E84F116799083DDDD3D615E81F17 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FF68D5CBACC4F96B50387F3FEC9C0C84 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 78D3FDA7EDCAD3EC546D3EC67A071821 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AD57DD9E23538462F0324FC0163E4687 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7BA7500DBB489DEFDD7CC1FAE6073065 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 19F765EA7211C1AB6CAA21972C191E67 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7D3A22040002E8F97398A6954D9F003A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2631D9F5AF10BE4FEC1A6611198C8B27 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 976E51A906BC5FF2EF5F3F9150364146 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B716C65DD09AF6E98190284B67A268F7 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B7D024CD4C070FA492DF42423B9C36C6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DCC34F4CC38D374C98B5D07038E9E061 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C632C1FE3CF19809F363112B57451E42 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DBD7194811092541DF71B9C8A023E2C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C78B2CE08206D9277C54EDF7D9C1B12D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 889D99A65CAB43057FA68D35CC3BD003 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB0EC5A1ADE5082A47339C126D970A82 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CAB5ED5AF21CB3DD3C96A76C2FD37BF9 /* Foundation.framework in Frameworks */, + 30E6C0B5D27FDD48D60BB0259010B33F /* Security.framework in Frameworks */, + 5E2CAB2BFF770FB45251BE3DE5B0525A /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F46A0EDAAA4E82EDBC0DB972F383AB30 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8703D25BE9A09A0DE8AEA23D81B22277 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00100BD28A3574D53A3451A58001DAE3 /* Pods */ = { + isa = PBXGroup; + children = ( + 67EF017CDF1EDC8BD048E67812E428FB /* Firebase */, + DB02DB0D7CC7668A03149C0E6A9A3150 /* FirebaseAnalytics */, + F79F78D66361EA6A8DB031AE13A5612E /* FirebaseAuthInterop */, + E97659F6327147F3C472C0C44FC5E1DD /* FirebaseCore */, + EBAAC1048CCF89CDC1AB4771762F3408 /* FirebaseCoreDiagnostics */, + CDE93E2CC3F828D6C0968192CD21055D /* FirebaseCoreDiagnosticsInterop */, + 0853DA60B217E7D15BDC5109A3A62C10 /* FirebaseDatabase */, + 5D5AFEBE4175D665324BD43180EF6DDF /* FirebaseInstallations */, + 0EF416A27BF6A867557FDCF4E53580D7 /* FirebaseInstanceID */, + 12A21E0E8F00C6E39C1A704F6D11EDA2 /* GoogleAppMeasurement */, + AFFBDE675567ED91B8C4E488E594266C /* GoogleDataTransport */, + BA33A7C1755346DD3ABAADEE9D268D88 /* GoogleDataTransportCCTSupport */, + AA339D736EE834251F9F281A55AD01AD /* GoogleUtilities */, + A40521D209F62D834D87D4F4264DED64 /* leveldb-library */, + 594C88FCDE19DF7D7BC563584D48E702 /* nanopb */, + D91D9CB3653EE01DCB65AE420B69E3F4 /* PromisesObjC */, + ); + name = Pods; + sourceTree = ""; + }; + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0D606D6935B2A17CA59AEFF7E234E6FD /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0853DA60B217E7D15BDC5109A3A62C10 /* FirebaseDatabase */ = { + isa = PBXGroup; + children = ( + C2718A77E9D1B7AAB8B1E89B2B9AD22D /* APLevelDB.h */, + 52B29770DEBEF1203AB8B5BF1A64AEC1 /* APLevelDB.mm */, + 5C87D643C4C45D5110216216D030EBF5 /* FAckUserWrite.h */, + B9D9A71F70ACC4A28A21C50E73140250 /* FAckUserWrite.m */, + B35084C018CB2A2FAF2A8E47B9341A94 /* FArraySortedDictionary.h */, + 171EA63C3E77121BBC849D8ED2882074 /* FArraySortedDictionary.m */, + 848DF70F7272DBB5E881092F5958348A /* FAtomicNumber.h */, + DF85A3A3AE8C4D175D5C543F24DF2FB4 /* FAtomicNumber.m */, + 39C731E683F6797282C44B7CD3D51841 /* FAuthTokenProvider.h */, + BB2BA88758CD8F3F42FDA4887D47257A /* FAuthTokenProvider.m */, + 469E4EE0DF63B70B17207AF1F945B600 /* fbase64.c */, + 98306E8E1C87D94B702DACAAB6768B53 /* fbase64.h */, + 64DE81935684B37F8499BD626088D702 /* FCacheNode.h */, + C7DA56AEC2BBB09F0B17C011D33EFD87 /* FCacheNode.m */, + 22A60F60CFF8C2C8A3624904C2D5A7DA /* FCachePolicy.h */, + E161DB825968B6D1274F18BC57F7781D /* FCachePolicy.m */, + 01B3B9333C2F6435557A422A0630F1F5 /* FCancelEvent.h */, + A30D980013D4A49BB4B9AF281EC66F68 /* FCancelEvent.m */, + 064118602FB22DFA8143649846D646DD /* FChange.h */, + 9BCD2A51AB838CC30EACE2C5FE09CD59 /* FChange.m */, + 8EAB5FF47F39A44B872B1E1191579AEA /* FChildChangeAccumulator.h */, + A3D64D73BE83CC3A36E53B1E36DC26BE /* FChildChangeAccumulator.m */, + E5508FE08B3CA077BE34943206E069B5 /* FChildEventRegistration.h */, + F5343AFD79945A13C37E1EC1B6E62B25 /* FChildEventRegistration.m */, + A09D01D4E0A074E9C10E52E070322766 /* FChildrenNode.h */, + AF74E221F17A2E24C2B42D1BC778DAC6 /* FChildrenNode.m */, + 636D1E4BE951AF743DF68225F83ED03A /* FClock.h */, + 444973A3DB4BB3F60FCF797B60B726E7 /* FClock.m */, + ADD2FCA292915B2E6B0381A7040CB1E6 /* FCompleteChildSource.h */, + B6243AA00C08AE7508A9487E0DD106A5 /* FCompoundHash.h */, + C4E576228987A62E57731963B7FD5E31 /* FCompoundHash.m */, + 8625031D0810B04DC3327766C1F960D3 /* FCompoundWrite.h */, + 7C698FE3E8F0E520BE6B395F5CAA16F6 /* FCompoundWrite.m */, + 6897BF9DB6AA2AEFA17C83D1CC46505F /* FConnection.h */, + 09DE94F55E8798B33321639491D9EFC6 /* FConnection.m */, + FA75AD53B36E8DAD1847CE0D8C8A15A9 /* FConstants.h */, + EB5FE81C882FC64F8753116A5B70F2E6 /* FConstants.m */, + 1FA5606127C7AB07769D229E6BA594FA /* FDataEvent.h */, + EA4707415187157C356E56CCEAB4A5B4 /* FDataEvent.m */, + D6AD17FB8B70E3033CE0DB1763A1A7B2 /* FEmptyNode.h */, + 6007C861D262EE9CFD533D5392F386E8 /* FEmptyNode.m */, + 027C0282396A56D8390E23CEF590CD5A /* FEvent.h */, + 4E5C112CB6CC03482709D541E5DF2517 /* FEventEmitter.h */, + 428713B30E973E48B3E6C248827A08FD /* FEventEmitter.m */, + D64EAECB9AE75FAD65FC8D0B02422580 /* FEventGenerator.h */, + 782C6082710A31FBBFE0FF40C496D80F /* FEventGenerator.m */, + C8B26599A4CA608F5B170B0769926191 /* FEventRaiser.h */, + 7158411B4EA467277676C39BCC4E56CE /* FEventRaiser.m */, + E5D99095828A99E2D1AC9636C56E65CC /* FEventRegistration.h */, + 5CEA9F60ABECD586463154A10B2288F8 /* FImmutableSortedDictionary.h */, + 581326EBD90729AEB63DC7E39FAAACB7 /* FImmutableSortedDictionary.m */, + 0D863A092BC7BF7CDCF10C9A29826E62 /* FImmutableSortedSet.h */, + 62E90F2517A7D54AE0A6DA5690C006A4 /* FImmutableSortedSet.m */, + 2F74BD3D7622AD541A03B2EDF917C25A /* FImmutableTree.h */, + 6526C1D31492B1E021287A00A46E4DB0 /* FImmutableTree.m */, + 28B6BD3200BA33A9C4373D012238E16F /* FIndex.h */, + 2D952F927F793C8D050294553BA6A78D /* FIndex.m */, + EE8845E0152C938810B709F01172891E /* FIndexedFilter.h */, + B001400E85F272915939718E17EBFD25 /* FIndexedFilter.m */, + 4A41F2D2C55B5704983865EFEBB72419 /* FIndexedNode.h */, + FBC8005390271EA0A8E1814D471860C1 /* FIndexedNode.m */, + 756DE87D6FE64F0049E1627934D587F7 /* FIRDatabase.h */, + 27CEB21BECB905A6D672FCB27BC8D325 /* FIRDatabase.m */, + 017FF39FEE7393BA61DE14D73E902FA8 /* FIRDatabase_Private.h */, + 5CECAFFA8C44526C632EEA97E2699B33 /* FIRDatabaseComponent.h */, + 156BFD884F1693CF4050DF9EEAE24F4A /* FIRDatabaseComponent.m */, + 37680EC5B6E6AB38998D8F2E60743D0B /* FIRDatabaseConfig.h */, + AA212DD1CD76575F40EB8CABCA92FF1A /* FIRDatabaseConfig.m */, + CE70B8F0872CD5F6701BE7EE2B37F8E8 /* FIRDatabaseConfig_Private.h */, + FEF9959C504C1429615F19DA2FA0DF5F /* FIRDatabaseQuery.h */, + 4245217ADD8651375C7C87461D2BAC11 /* FIRDatabaseQuery.m */, + A5C471E66465A3AD8773DDA0113CF313 /* FIRDatabaseQuery_Private.h */, + C03A03D30012B27E690AA4629A1913A9 /* FIRDatabaseReference.h */, + ACF43B6D0673E47C821DE97D5D2237CB /* FIRDatabaseReference.m */, + FC7213970830A3E5E01229377CCD602D /* FIRDatabaseReference_Private.h */, + ADE3D3BC42C093C1B8BBB0454B40B83E /* FIRDataEventType.h */, + 45A016B308E76BE7B4FEF78FD4654397 /* FIRDataSnapshot.h */, + AFF7787A89CE9402712586AA44B4A30B /* FIRDataSnapshot.m */, + 81C33A153E19967E3445E344E55BED54 /* FIRDataSnapshot_Private.h */, + 56DC4A494823934F36EC73C1FCC0EBF4 /* FirebaseDatabase.h */, + B8EAECB74DB46EE2F89DFCA3A335276C /* FIRMutableData.h */, + D131FCC82D07749BA8F453BE243E3308 /* FIRMutableData.m */, + 6C9FA0D3CC8310231FD8E879E9F9FB2F /* FIRMutableData_Private.h */, + 0F9FAE51763CF4E8A796748ED633EB69 /* FIRNoopAuthTokenProvider.h */, + 8D8AFA1CE839BF7B31F847CE180844A5 /* FIRNoopAuthTokenProvider.m */, + 6F757C6CD54BFEF3CFB0766836A5F414 /* FIRRetryHelper.h */, + 7733F0D190599F8D103BA7AC9BF61FB2 /* FIRRetryHelper.m */, + 725CAC1516DCD4072C47A01FC5EEE271 /* FIRServerValue.h */, + 832796FD22EEC1442E1D5058AE06473C /* FIRServerValue.m */, + DD144C3EC4E9FF7960E6B2C281A11227 /* FIRTransactionResult.h */, + 8387D908A0D8C85843E77A633F96933F /* FIRTransactionResult.m */, + 3F27706885AB7D265A16236A0B089793 /* FIRTransactionResult_Private.h */, + 2C61360E2B0972E9BCF8D71772010A94 /* FKeepSyncedEventRegistration.h */, + 562AEAF410E4ECCAF9B77166BA77E3A3 /* FKeepSyncedEventRegistration.m */, + 7F71B5A123DF00AD98FAF2759DD9F983 /* FKeyIndex.h */, + 50204171185C6765C11FF190A8E90F7D /* FKeyIndex.m */, + 25107E5C61245A8D44F02161C92B9A9F /* FLeafNode.h */, + 6284DEE9BBC353DD2F3E29CFF97AF0EF /* FLeafNode.m */, + 28976708F04BF0E8AD3DF8D772A5E9C8 /* FLevelDBStorageEngine.h */, + 5E72C91BD55A89072F9977C2F1A152D1 /* FLevelDBStorageEngine.m */, + 8157CF91D79E2D82F9E3A84E1F373B78 /* FLimitedFilter.h */, + 0F0CD1B3CF10F405D4D6DCC033E61ACF /* FLimitedFilter.m */, + DB8DBDD015B9A7C63AD7FF51FCD1CED6 /* FListenComplete.h */, + 874C68D17B12C1F819AD0ADEA831EAFE /* FListenComplete.m */, + 686EDFE931F5DA103D7A9B9031A68467 /* FListenProvider.h */, + 2BA1EAA89F969D9D4D52536B5BCE43FC /* FListenProvider.m */, + 0008E34A7746A0E1A2D5583DA0348CBA /* FLLRBEmptyNode.h */, + 2E61B1F736CF3923FDCC8C3E49CA7E3E /* FLLRBEmptyNode.m */, + 4A87C58D697F019156D54455DEF3DA75 /* FLLRBNode.h */, + F79F298B4FF02587B6E3978DDC7D3FED /* FLLRBValueNode.h */, + F0E17F44674DD5323FABD14840F7D509 /* FLLRBValueNode.m */, + 60674E85B85501474862591F4FFCEF7E /* FMaxNode.h */, + E26C56006D98BED71A283F0AC2E12786 /* FMaxNode.m */, + CA4C73E47837B0E3511A487AFC38A70B /* FMerge.h */, + FB9061DB724B0A4703E5CFCB88C87A4A /* FMerge.m */, + 0C9144733820350361C79FCC0FC4E76D /* FNamedNode.h */, + 540836500C5F901B23F465C564B553C2 /* FNamedNode.m */, + 5737AA49AB6F7A70ACA5A20ADAC6B4A8 /* FNextPushId.h */, + AE5599B51674FD217CF4064C4D6DDFF5 /* FNextPushId.m */, + 8471B9B04CF93EE03047131EA36E6938 /* FNode.h */, + A8F66572B286F803446413533812835C /* FNodeFilter.h */, + 695657C468C5D2CF227BD8AA9F4FF226 /* FOperation.h */, + EC3E044ABC83D63EDD13785CC93A4B4A /* FOperationSource.h */, + 00B9C533AF486EDF4C205EBBEC465607 /* FOperationSource.m */, + 09BC891B2774FDA333795F1FA34727ED /* FOverwrite.h */, + 4E67DE3F4605BE94ED95546F293188D3 /* FOverwrite.m */, + 722C7D69C7C7A86DB9326799FB70F05B /* FParsedUrl.h */, + 22745D074BDC5C547FA32DCF913B5ED6 /* FParsedUrl.m */, + 97AEA888054F9AC998F31369474D10B3 /* FPath.h */, + FF2C02F438734C5492E0887B31D61B29 /* FPath.m */, + 747CA32386AB55EC174C9FE0E0C1A2B4 /* FPathIndex.h */, + 199EB0AF8519A748873EAEF746674CAA /* FPathIndex.m */, + CB8195D549670F26815B3858895AC0DD /* FPendingPut.h */, + 4A4733A66A4533BC54CA3576C71F03DE /* FPendingPut.m */, + FAB189ECD5A6C97091EA2695A36F518F /* FPersistenceManager.h */, + 85BFB0EA5C7CE6AD700F7323053A5AB3 /* FPersistenceManager.m */, + 5D7A7A1F332FB4CB78EEFE0D5645D882 /* FPersistentConnection.h */, + E7737C5E82B493FFA4C523BF0F15C33B /* FPersistentConnection.m */, + 84105C2E03C766F137C523748AFABA19 /* FPriorityIndex.h */, + 24E3248B95B1AC14B851DD22D5CBADE2 /* FPriorityIndex.m */, + 15F2FE55B0E52C26E5CD1A45A048429C /* FPruneForest.h */, + 62BA41319E7AA21A5F414BB6901E2EAA /* FPruneForest.m */, + 8839E366E23EFB0A1D7CAA675A691EE8 /* FQueryParams.h */, + F7F36453D48EB7DB0A3070832408980B /* FQueryParams.m */, + 2EA7330D3CB1E19057AB60A9618336C8 /* FQuerySpec.h */, + 2034D03795150369FA9B06580B7517F7 /* FQuerySpec.m */, + D887D5D2E2B630D2E0ECB4034734F45A /* FRangedFilter.h */, + 45FCEB89C8FEB1D4760D9155DC0E584C /* FRangedFilter.m */, + 903B2BDF7FCE5660EC3EF7289DAFB10E /* FRangeMerge.h */, + FFA9F0218DE9786B2346ABEDC657B815 /* FRangeMerge.m */, + 21481E35761ADCCC2C9056C42954B6C0 /* FRepo.h */, + BAD71520F0592D6FFF74F12C378D529F /* FRepo.m */, + FB7F5B838DF85F6A767CB414C4359375 /* FRepo_Private.h */, + C17FA7E29878F0A856A40B1BEC779C9F /* FRepoInfo.h */, + 9AD1150B6BD9EFAE172F16CD4B82379A /* FRepoInfo.m */, + 1588032FA5B9336704BAFFEA1C7E2FCE /* FRepoManager.h */, + 61A0AC30DE0C12BC52B4BD10F6121DDF /* FRepoManager.m */, + 00C87AD738B62445FF58BEA587E511E7 /* FServerValues.h */, + 6C788D48944FAEAB4862F3DB0F76AB84 /* FServerValues.m */, + 5B8BFC8D45246220FC9E22CEC5021251 /* FSnapshotHolder.h */, + 19298FBBC7572398E1E2B6F1B0ED04B5 /* FSnapshotHolder.m */, + 51EDC2B524719FB084B2E682316BE65C /* FSnapshotUtilities.h */, + 9BC630AE6D6E92874C62C4D23F10958E /* FSnapshotUtilities.m */, + 20B54EE31B858742F3D0FDC1F9359591 /* FSparseSnapshotTree.h */, + 2F12565B717E28C3CE4FAA319DAB3D7F /* FSparseSnapshotTree.m */, + 1CA1876DE760D48C7C370BC1CB02071A /* FSRWebSocket.h */, + 1F5AF25E215A81CF2173475193C34EB0 /* FSRWebSocket.m */, + 2EE088A364492A317A7C4FA99BC16B32 /* FStorageEngine.h */, + 18B48B8EAD733AA93D56EC86DF4E5EC0 /* FStringUtilities.h */, + 6270DF1BFF55ADC2D337AC78BD921C52 /* FStringUtilities.m */, + 05801D5FF061F264B1CE44110016F58F /* FSyncPoint.h */, + 38BDD50A689DAC3E054B5FD55707AA2F /* FSyncPoint.m */, + 74B732861F4DBB7D074BD0EBEAE05218 /* FSyncTree.h */, + D11FF29A1A4C44B50A32EA588B64D0FA /* FSyncTree.m */, + E42CD6D50EE4BFF16E3DD5C5F9977780 /* FTrackedQuery.h */, + 14494CAC35D8D269643EA5CB8934BF45 /* FTrackedQuery.m */, + B61358592FDB40CF8A657BFD252B3416 /* FTrackedQueryManager.h */, + 9CC03C75A089757D74469A154727F5CD /* FTrackedQueryManager.m */, + 65CD61911DCF7CD7FCCBB65A9CEEE323 /* FTransformedEnumerator.h */, + ABFA60EA6B3C819ADA0E147A88E113E0 /* FTransformedEnumerator.m */, + 1E21DCEE277E88B08FB8F3329FD5F48A /* FTree.h */, + 768C30DB00B3D3283040ADCD760D66B2 /* FTree.m */, + FFBDB88B2DD90C42C6967F3B1D569324 /* FTreeNode.h */, + 7B29E9518D65490F1E33B2B30B23ADCB /* FTreeNode.m */, + 789BC906E9C7035CD6F53282CE3AA453 /* FTreeSortedDictionary.h */, + B7EC032D36A1A28E006B92BAF996CC3E /* FTreeSortedDictionary.m */, + FF0E752DEBBB329AED0426B5DBA6F030 /* FTreeSortedDictionaryEnumerator.h */, + 9A6B7D017E8C22F0382985F7884DF8B8 /* FTreeSortedDictionaryEnumerator.m */, + 53FAAC0625B206D4D02719ABD6BAC099 /* FTupleBoolBlock.h */, + 6DD1E26CF8A05FA5B014E91EF56ED45D /* FTupleBoolBlock.m */, + BE12109DCA730DE54BFFE4D8BAAD3272 /* FTupleCallbackStatus.h */, + 27F2DB045C06893A8DEADE59EA4E7FDF /* FTupleCallbackStatus.m */, + B922785EA83E6FEB9DA16973EBF01646 /* FTupleFirebase.h */, + B121F2A73420BD133A4CBD674492FC12 /* FTupleFirebase.m */, + F8E21755762B362FCA620ED488970ADF /* FTupleNodePath.h */, + FDE125C0FE65AF0DB95E2AE362D9BE5B /* FTupleNodePath.m */, + 181E3F131300BC5D6914C8698DBFFEFD /* FTupleObjectNode.h */, + 7CC5F567A3E69A2FF89366D3265864D0 /* FTupleObjectNode.m */, + 5E443A6931785BEEAF7DC2C354926B51 /* FTupleObjects.h */, + 878E027D5C73EDA05B5D73F2457F6E20 /* FTupleObjects.m */, + FB991BB4D89DAB85EDF7100FBAFA1A13 /* FTupleOnDisconnect.h */, + B48FF961E99ECC80C015283501933E9F /* FTupleOnDisconnect.m */, + F74A247A080EE95B1E78BEB99DA8AAA2 /* FTuplePathValue.h */, + FE6DB08072CCBBA9657F29B2A4B18F2A /* FTuplePathValue.m */, + 80CE823A231F46D35C99B77FE37C2680 /* FTupleRemovedQueriesEvents.h */, + 3D77CDFE1F279E8808BC2B957E413C69 /* FTupleRemovedQueriesEvents.m */, + 469188005111468BDAB623C15E021952 /* FTupleSetIdPath.h */, + AE0CD47B189B10242AD0B8643930F413 /* FTupleSetIdPath.m */, + 3E8AF3E7C471E6553CFB71867A370455 /* FTupleStringNode.h */, + 14767AA509DD2B355C7598A3E158E242 /* FTupleStringNode.m */, + 31537E08EC2179F2189D3BDDA257E569 /* FTupleTransaction.h */, + F690E86D8C72F9C55C2E8AB28B37E07D /* FTupleTransaction.m */, + 69A38C98F33FDE148ED5D38379F735D1 /* FTupleTSN.h */, + F26B1F10B563CB6B30369228E750B277 /* FTupleTSN.m */, + 451BB6FC86F30A7B6E5B472C474F44FD /* FTupleUserCallback.h */, + 41C1F0E633134DD86A4BD84D71BFC499 /* FTupleUserCallback.m */, + 4AF07C1AFB9C5EDF8416071371D15C6D /* FTypedefs.h */, + 7D41CCAE0E65DD892BC17B14CD65AE6F /* FTypedefs_Private.h */, + A65321EB88EA8A0A7B7F1D040CDBDE0A /* FUtilities.h */, + 6D407C321863CD7FA24AC53D85CA2966 /* FUtilities.m */, + 726B3EC39B72F88C33B457410776DF31 /* FValidation.h */, + B63C250262739AA04B6D0027DDF4902F /* FValidation.m */, + E21218A3B8A841CFC4A0716AC72E30B0 /* FValueEventRegistration.h */, + 9DD615F709C03B469833C0AD4EC286D9 /* FValueEventRegistration.m */, + E6E84A81CE2FF3E0A915DAE54B7DAF41 /* FValueIndex.h */, + 8091FFAE87FD3FA3AE8ED56E6859B4F0 /* FValueIndex.m */, + 84AB4D11B745E92F4CDD206AFE2E0660 /* FView.h */, + 9C2D17D624A2FB0F013DC69FEE7F9531 /* FView.m */, + BF9C8E91EB9306CDE7F9886606461EE0 /* FViewCache.h */, + AF3E068B4B32BE9AA15D6F3ABDDA7325 /* FViewCache.m */, + 025546DBE96632B34B63790615A3BDC3 /* FViewProcessor.h */, + 0C40715AAB90D82EBE8B88B6DEC64F64 /* FViewProcessor.m */, + CB79FD41C8FFFB07B28E71D46260F99A /* FViewProcessorResult.h */, + 9508F4557EAC2FA9BC5AE4521AE1415A /* FViewProcessorResult.m */, + 2B6742E1E1A93B363D50D9289D741621 /* FWebSocketConnection.h */, + A9364051DE6DB776B1CFB70C96D51F3A /* FWebSocketConnection.m */, + 6D3557174B66202482C8BDA5E3AC8D6C /* FWriteRecord.h */, + 911A01616C728841C697AB49826AC324 /* FWriteRecord.m */, + D68AE5E7D4434A5A3C27FE2C33DEF374 /* FWriteTree.h */, + 61F7711DCE64F1713DFA6FCCC11690C8 /* FWriteTree.m */, + 3732562635D3675F3AC5870C2EA64563 /* FWriteTreeRef.h */, + BA096BF345BE538F99DE48F146E7B6AE /* FWriteTreeRef.m */, + A236AD4499A5E6DCBA8204CB68484B08 /* NSData+SRB64Additions.h */, + 06023D1734B2E0EC0F1A8AFA0E532F6F /* NSData+SRB64Additions.m */, + 8AD37DEA100AB103849E4DCA01F0341B /* Support Files */, + ); + name = FirebaseDatabase; + path = FirebaseDatabase; + sourceTree = ""; + }; + 0AC35FB677FF63258C49DEDF3E802184 /* MethodSwizzler */ = { + isa = PBXGroup; + children = ( + D3EF925BD0923A808B3AF3593EA2ABDB /* GULOriginalIMPConvenienceMacros.h */, + 7C563C7E60320BE9BE84B966C5A1702F /* GULSwizzler.h */, + 220C198B5B0BF924872B6F4E2D39EC90 /* GULSwizzler.m */, + ); + name = MethodSwizzler; + sourceTree = ""; + }; + 0BA1F38C813F1D73921602BE4FE2DFE6 /* Network */ = { + isa = PBXGroup; + children = ( + 589C384C3A628D4954C3FDE4FB7B6A43 /* GULMutableDictionary.h */, + D3EA4FED70C955814D3060BCA5FCD84D /* GULMutableDictionary.m */, + 8B445347E43C90E24AE0CFABC51EB3F9 /* GULNetwork.h */, + 32E7893D49BF9AB5CB50A68EC77DF323 /* GULNetwork.m */, + A4556B043AB0DAFFE7F063B549ECF6AD /* GULNetworkConstants.h */, + 3006D62C40726EA8DD299E82CEC1BD7A /* GULNetworkConstants.m */, + 55EB03E6D00F93919813AFF8047C700D /* GULNetworkLoggerProtocol.h */, + 404A14083B530908C5B3506B9F2CF75A /* GULNetworkMessageCode.h */, + A49B8B76E453094FFA6318AAA24AA4EE /* GULNetworkURLSession.h */, + 8D47D02F704DF255E65A5CD36CF9D48E /* GULNetworkURLSession.m */, + ); + name = Network; + sourceTree = ""; + }; + 0C0A7EAE7589B78EBA226ECFEC1266B9 /* Support Files */ = { + isa = PBXGroup; + children = ( + 4FC8EE8B7162AC6DE3CF2A1F8F8BB473 /* GoogleDataTransport.modulemap */, + B1ED778C9852BEF45C9DB36A28CC3F74 /* GoogleDataTransport-dummy.m */, + 7501A42EFA5935C6D3C245650F4D9879 /* GoogleDataTransport-Info.plist */, + 271E908860FE391339504340784BC551 /* GoogleDataTransport-umbrella.h */, + 8245B1F254DC9F182514403D6091F777 /* GoogleDataTransport.debug.xcconfig */, + A60A55723949183FAB49E5B3D9577924 /* GoogleDataTransport.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransport"; + sourceTree = ""; + }; + 0D606D6935B2A17CA59AEFF7E234E6FD /* iOS */ = { + isa = PBXGroup; + children = ( + 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */, + 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */, + 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 0EF416A27BF6A867557FDCF4E53580D7 /* FirebaseInstanceID */ = { + isa = PBXGroup; + children = ( + 020C390E50662AFEC68A60C7164199DD /* FirebaseInstanceID.h */, + 50223B484C12AFEA943E8C2C1EDCB3EC /* FIRIMessageCode.h */, + 73B33C24AB2B2C938EE0534A6B039DA1 /* FIRInstanceID.h */, + 6F93B1E527C47BC19CC33DF9E2E21D44 /* FIRInstanceID.m */, + 3F197642A1C79AF964CAAA015E860AC3 /* FIRInstanceID+Private.h */, + 443C8A9A533DD8E2A9D01F4F78EBE443 /* FIRInstanceID+Private.m */, + 5E0495142F4CB62FD6FD98EA2E14AA08 /* FIRInstanceID_Private.h */, + 2A6B9E9907DBF37ECD0FE8FC82FEB737 /* FIRInstanceIDAPNSInfo.h */, + D3FC34E39CBFCA6990DA3BF467AD6C7D /* FIRInstanceIDAPNSInfo.m */, + D54A5395DBB67ECB6B503D7CCDCAE2A3 /* FIRInstanceIDAuthKeyChain.h */, + D022F7FBC81242923E8D67CA2E289BA0 /* FIRInstanceIDAuthKeyChain.m */, + 7EFEFAB171B0614C38F1C781DB2D1FE3 /* FIRInstanceIDAuthService.h */, + C8B01D89754271F61E72A781D8CE2571 /* FIRInstanceIDAuthService.m */, + 6C00A27614E9B023E9AF2E860B568B7B /* FIRInstanceIDBackupExcludedPlist.h */, + 5F58773864AC25F46EB2AA354F987C57 /* FIRInstanceIDBackupExcludedPlist.m */, + 2A88A869CED3ECCE7D333B05DFD0CDEC /* FIRInstanceIDCheckinPreferences.h */, + 855AA79FFF7DE13C4E817A31871AFEE6 /* FIRInstanceIDCheckinPreferences.m */, + 9B4C695F884374A04733A8358081E649 /* FIRInstanceIDCheckinPreferences+Internal.h */, + DFF3F389C5FFC9338529BC11F026588E /* FIRInstanceIDCheckinPreferences+Internal.m */, + 20E2602A98267FAC13549447297B1CF6 /* FIRInstanceIDCheckinPreferences_Private.h */, + 3BD6E0B555B8B7001FA7C0534B5316D8 /* FIRInstanceIDCheckinService.h */, + F3959B61A1A4E4F8AE1134134BC3F7B1 /* FIRInstanceIDCheckinService.m */, + F81A7101C3F68C1D5685C0AC60237A70 /* FIRInstanceIDCheckinStore.h */, + 0C4F0248287DB8D03D320A8A1FBA6BC8 /* FIRInstanceIDCheckinStore.m */, + 86A0153033585BE52A436ADC9565571C /* FIRInstanceIDCombinedHandler.h */, + 364EAEA6E2087584E3FAC61220152886 /* FIRInstanceIDCombinedHandler.m */, + 88A9B676AACC9D2E626E041CFCDA7772 /* FIRInstanceIDConstants.h */, + 852C7911EDA4AF68E0A658A3B70F5D0B /* FIRInstanceIDConstants.m */, + 9AD1456814B75D3A95FA64D7320BA8CC /* FIRInstanceIDDefines.h */, + 5C666511B4072152AD025B2D4C721AAC /* FIRInstanceIDKeychain.h */, + 59393315B83DEB88FEAFAE711D920582 /* FIRInstanceIDKeychain.m */, + EED1AC6242127BDAA6E48B5C7662BA95 /* FIRInstanceIDLogger.h */, + C55FA61E2BD999842193CE4030989F59 /* FIRInstanceIDLogger.m */, + 8AC10901C2F79CFA82FEAE4AAF01ABED /* FIRInstanceIDStore.h */, + 6BA535C000530A7DB6D708C0024FE808 /* FIRInstanceIDStore.m */, + 0AFCCCAB65ABF466748E9D04F3ED6026 /* FIRInstanceIDStringEncoding.h */, + 528792C9F0D3800EAF0C1D2F84EF8873 /* FIRInstanceIDStringEncoding.m */, + 237B8AFB55BB3BE9CA62127AA18FB403 /* FIRInstanceIDTokenDeleteOperation.h */, + 801F763C867E44EE28B55C1FBA1D58CE /* FIRInstanceIDTokenDeleteOperation.m */, + 8CFAD347C460AFFC4F90B3045452C74D /* FIRInstanceIDTokenFetchOperation.h */, + 21C1E706ED5710A5F8B33A3B743E963A /* FIRInstanceIDTokenFetchOperation.m */, + F1E98655F6E57D3EBFA5F4C3BFD52EEB /* FIRInstanceIDTokenInfo.h */, + E7431CBAB5161E552D3F5FD4A6A4B48C /* FIRInstanceIDTokenInfo.m */, + 0A455526C11611056459A460492697E5 /* FIRInstanceIDTokenManager.h */, + 45BBE0220D0AA28216B74B4EECE15457 /* FIRInstanceIDTokenManager.m */, + 12478891F3E769E22DD83E49512CD0F2 /* FIRInstanceIDTokenOperation.h */, + B189B07C114807A1945A3116776D2A43 /* FIRInstanceIDTokenOperation.m */, + 9E3CBD22B698222D11A402DA18253A70 /* FIRInstanceIDTokenOperation+Private.h */, + 3659B8E0DA938B031AD879C0B213C188 /* FIRInstanceIDTokenStore.h */, + 4891EB1830F4333011011F6DBFE08CA2 /* FIRInstanceIDTokenStore.m */, + 98C983DA955E0638D50257AEF6623BC4 /* FIRInstanceIDURLQueryItem.h */, + D0B87C45F3772C3A9902A4E9D16C60C9 /* FIRInstanceIDURLQueryItem.m */, + E6908625F5FB22DD281BF38879C7EDCE /* FIRInstanceIDUtilities.h */, + F71D48BEB6D4E6FD4232B3FBFE360494 /* FIRInstanceIDUtilities.m */, + 7EE99081D914925E41102736BBD49557 /* FIRInstanceIDVersionUtilities.h */, + C3AAC69E6988F1A4299931B9F19FDAB9 /* FIRInstanceIDVersionUtilities.m */, + E4573AE1A9FBC7C15F78874BA9847666 /* NSError+FIRInstanceID.h */, + 9AF055035432D0F1EB1F9ED475A81A00 /* NSError+FIRInstanceID.m */, + 1A4856B74007FC0F4B2E8CA50789DC23 /* Support Files */, + ); + name = FirebaseInstanceID; + path = FirebaseInstanceID; + sourceTree = ""; + }; + 12A21E0E8F00C6E39C1A704F6D11EDA2 /* GoogleAppMeasurement */ = { + isa = PBXGroup; + children = ( + 3C893F2F4FEB14619BC5BE8B1872BA5E /* Frameworks */, + 4BB752E8967C4D67BDBEC7F2EA973F51 /* Support Files */, + ); + name = GoogleAppMeasurement; + path = GoogleAppMeasurement; + sourceTree = ""; + }; + 19B8489ED1B89D93FDAE24B44BE77769 /* Support Files */ = { + isa = PBXGroup; + children = ( + BFCA9E7603A4EBE52A899B3964CCB141 /* FirebaseAuthInterop.debug.xcconfig */, + 82C4CF4D53142C0C4CF6949E22FC3124 /* FirebaseAuthInterop.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAuthInterop"; + sourceTree = ""; + }; + 1A4856B74007FC0F4B2E8CA50789DC23 /* Support Files */ = { + isa = PBXGroup; + children = ( + F9CF4195F4E2D294C22312BCBCB5F019 /* FirebaseInstanceID.modulemap */, + EEF250FBAA16E776552020D11B9C8A66 /* FirebaseInstanceID-dummy.m */, + CF26A853FCB235F746C7983DA67400B6 /* FirebaseInstanceID-Info.plist */, + F459ED3E4C3C9D6C2650EEAF63B3FEDF /* FirebaseInstanceID-umbrella.h */, + 2D8BDFC58A9D05BCE6AA0A666C2C3E44 /* FirebaseInstanceID.debug.xcconfig */, + 3250A298087DD89728C3E5E2CCA32C78 /* FirebaseInstanceID.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstanceID"; + sourceTree = ""; + }; + 1A50345281AB6F5D30CA6EE11F5C5108 /* Support Files */ = { + isa = PBXGroup; + children = ( + B1E88FA45FE369396DDE94F30F4EC58D /* FirebaseInstallations.modulemap */, + 2FA7F98EE4D30B47DE6F7455BC33991D /* FirebaseInstallations-dummy.m */, + 3E96F5CFCE90C3487B8CD0E4FD6B85C1 /* FirebaseInstallations-Info.plist */, + 258A1335EA6E5FABE7B63118A7825690 /* FirebaseInstallations-umbrella.h */, + 9DB4215D54529564ADDF9449A77C3C99 /* FirebaseInstallations.debug.xcconfig */, + 4DC21506550FA18E27B3273C19EE1878 /* FirebaseInstallations.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstallations"; + sourceTree = ""; + }; + 3C893F2F4FEB14619BC5BE8B1872BA5E /* Frameworks */ = { + isa = PBXGroup; + children = ( + DD26F8C71729674B441938E34E892134 /* GoogleAppMeasurement.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 400CF04A63F797AAEC4259932D7BD6BD /* UserDefaults */ = { + isa = PBXGroup; + children = ( + 8E9F51951C4877C29BD86424B88DBA62 /* GULUserDefaults.h */, + CF0903B3B61A95E960B197B8585D0B44 /* GULUserDefaults.m */, + ); + name = UserDefaults; + sourceTree = ""; + }; + 43250CE12EE95C10950348E8C7E40C92 /* NSData+zlib */ = { + isa = PBXGroup; + children = ( + 93CDDE38F05478019E633026BB5DF3F8 /* GULNSData+zlib.h */, + 10DECCDC1A8262E47115B287809143A7 /* GULNSData+zlib.m */, + ); + name = "NSData+zlib"; + sourceTree = ""; + }; + 45EB47C565CADF2303CB7A0FF15AEAC0 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 8E1B54CBD2C39B17030CEF35043F77F5 /* Pods-PediatricPancreas */, + D3263F50C53E400245FA7FD90B60BD0F /* Pods-PediatricPancreas-PediatricPancreasUITests */, + C81B6CBE1E849E2F53A17EC7CCD1A566 /* Pods-PediatricPancreasTests */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 47F766F56A846D3BF9F2174CCDC75CA3 /* Logger */ = { + isa = PBXGroup; + children = ( + A1045E08CCC93351443EF0041C65E071 /* GULLogger.h */, + 015383D9B573A7E4A25B73CA5E2E2C36 /* GULLogger.m */, + 6362D3C5139CB0F2ADC38869A8AF6338 /* GULLoggerLevel.h */, + ); + name = Logger; + sourceTree = ""; + }; + 4BB752E8967C4D67BDBEC7F2EA973F51 /* Support Files */ = { + isa = PBXGroup; + children = ( + 87305E67A3F0888418FD5FB15A3AACE9 /* GoogleAppMeasurement.debug.xcconfig */, + EA54A83590F15D08BA0EA2F09D24D2D3 /* GoogleAppMeasurement.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleAppMeasurement"; + sourceTree = ""; + }; + 536D93C9EB1D7A375834114EB7D34C59 /* AppDelegateSwizzler */ = { + isa = PBXGroup; + children = ( + B3CBA0DE4566EF24CD679F6D52B2AF0E /* GULAppDelegateSwizzler.h */, + A98E3F14C60B35AC913D88C97E2B5972 /* GULAppDelegateSwizzler.m */, + 36F6CC5035C5136DAE4AA2DA5F82F358 /* GULAppDelegateSwizzler_Private.h */, + A4166E7662CC5AAA26F1AB619EC69E13 /* GULApplication.h */, + 7148DF98940A6E8CC17E6FFA5DCCFEBA /* GULLoggerCodes.h */, + CC9FBF9F202D0BA6D21D1A878140A6E7 /* GULSceneDelegateSwizzler.h */, + 00CB870A9CD0CEB91A8EEB4E2DF570D6 /* GULSceneDelegateSwizzler.m */, + 48D577F0C8A3766C9F607FEB903B8660 /* GULSceneDelegateSwizzler_Private.h */, + ); + name = AppDelegateSwizzler; + sourceTree = ""; + }; + 58703A3E10570BD9107E38E453ECA846 /* Support Files */ = { + isa = PBXGroup; + children = ( + 3A3ACA8424CC6D8AF0F54BE91DFA0A80 /* nanopb.modulemap */, + DF6767ED8AFFE68E3C7BEDECCCEEF733 /* nanopb-dummy.m */, + 2648E6918B81AE29038CC5644F02BA5D /* nanopb-Info.plist */, + 8DBA7964674155E29C594DE8DB9611B6 /* nanopb-prefix.pch */, + 19ECFA906B835C74272E23F478123821 /* nanopb-umbrella.h */, + 36564ACDC189BBCFE100D9CED8658730 /* nanopb.debug.xcconfig */, + 28F14DA020DF94A85C5154772920D6F0 /* nanopb.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/nanopb"; + sourceTree = ""; + }; + 594C88FCDE19DF7D7BC563584D48E702 /* nanopb */ = { + isa = PBXGroup; + children = ( + B3288029B62F60168CD0B5922E5D3F0B /* pb.h */, + 8320D8163EAA29B0F855EB271690E30F /* pb_common.c */, + E77DB5111675718C49A01EBA83BAF493 /* pb_common.h */, + 2CCEBF3760A2D010F801CCCF4EF351A8 /* pb_decode.c */, + 881C688EF05D37FB42E12434920FDBF4 /* pb_decode.h */, + 2387E0CA88C9075A7D7612E4CA20875F /* pb_encode.c */, + E337B401A2FCBCB3359E2A38291B7B4F /* pb_encode.h */, + 9E8B5C93FD16351758350E5643FC5DA2 /* decode */, + A68DC60BD3729713553C1C27BA04377C /* encode */, + 58703A3E10570BD9107E38E453ECA846 /* Support Files */, + ); + name = nanopb; + path = nanopb; + sourceTree = ""; + }; + 5D5AFEBE4175D665324BD43180EF6DDF /* FirebaseInstallations */ = { + isa = PBXGroup; + children = ( + 77CBE6E614F5EBEABF6E32AB2EAA8A52 /* FirebaseInstallations.h */, + BDEAF60599B3C1E34E2CA1FC766785CB /* FIRInstallations.h */, + EE347F70A1C0E9F79BF1982AA0AE5276 /* FIRInstallations.m */, + 108535B306732FA4B7C62DB68E5B4FF0 /* FIRInstallationsAPIService.h */, + 7FA340141092E3961C06B4C346F61E9F /* FIRInstallationsAPIService.m */, + 03741108F4DCC70F6CA8C9C139C8C1B7 /* FIRInstallationsAuthTokenResult.h */, + B560A05DDD10C41F219BD93A94B08293 /* FIRInstallationsAuthTokenResult.m */, + 5CDF3A3DACF1F0F35334E584A81142A8 /* FIRInstallationsAuthTokenResultInternal.h */, + 7478BC8F13E25643BF62665659255636 /* FIRInstallationsErrors.h */, + 10E088517E88ECCC3CA4D7857ABC459E /* FIRInstallationsErrorUtil.h */, + 2DA5D3B64A2899A7E1B92B478EF70F9C /* FIRInstallationsErrorUtil.m */, + D23943CEFBF68D1DA83A20CA208EE0D0 /* FIRInstallationsHTTPError.h */, + 6D66A0887A41593C21A1C19F871DD901 /* FIRInstallationsHTTPError.m */, + 0D3C1F79FCD48F9D503D56F37E60FE8A /* FIRInstallationsIDController.h */, + B4AFED41CC4D9C2FD5B2C41C3E970AD3 /* FIRInstallationsIDController.m */, + 892DFA98C0B6B4BA1A9DA101054D73CD /* FIRInstallationsIIDStore.h */, + CDD59F6FF7CD1CF4D22C5C4DD5A519F3 /* FIRInstallationsIIDStore.m */, + 594443A20669265EDD8B986F8494B7C1 /* FIRInstallationsIIDTokenStore.h */, + CBD27D618C4A13D97B4E96A9741DF66A /* FIRInstallationsIIDTokenStore.m */, + 084AA7F2510FE8410D65BB1A2A992F48 /* FIRInstallationsItem.h */, + 1C9B859F2BEDA3BE876C74D5B9F07E4D /* FIRInstallationsItem.m */, + 9878778F95F524E3A075A234B58960B9 /* FIRInstallationsItem+RegisterInstallationAPI.h */, + 71A013D2FB3A60D77460B97E98790815 /* FIRInstallationsItem+RegisterInstallationAPI.m */, + 4FADF1444F7ACFA3CDAF40D40C22292A /* FIRInstallationsKeychainUtils.h */, + D85B0BBD6B9929A743D2EFEF5F5A089B /* FIRInstallationsKeychainUtils.m */, + 38F29B71648AE8453095366BF1C520A8 /* FIRInstallationsLogger.h */, + 24297E436652A516BEDF07C2BD03A52E /* FIRInstallationsLogger.m */, + 253F8E2E2AE73606EC13FCD055710E21 /* FIRInstallationsSingleOperationPromiseCache.h */, + 73C3A2B897419E5CB0BA2CB0D02C24CB /* FIRInstallationsSingleOperationPromiseCache.m */, + 3FCB115B6E3E19E6E714CE31F8C48CC4 /* FIRInstallationsStatus.h */, + 6597CE9AFDA1AF2FA603A486F757ADCC /* FIRInstallationsStore.h */, + CB76A092BCA0D0C1E846F7D5856AA5EF /* FIRInstallationsStore.m */, + 039D485AD0B1A9C9BB6FE228FF40844A /* FIRInstallationsStoredAuthToken.h */, + 5E01539529DD344C874CC0055A2F12BE /* FIRInstallationsStoredAuthToken.m */, + 8CE91982EF784FDD0B9C73AE4E76797D /* FIRInstallationsStoredItem.h */, + 885E13D41349DE2BB195AC2FC78B3D8C /* FIRInstallationsStoredItem.m */, + 07B77C44CC1FDF8D7B46080AE7D97ADA /* FIRInstallationsVersion.h */, + 36C7915A295EC650C0F2F336452EF3C2 /* FIRInstallationsVersion.m */, + 1194FDC2AD891229F89FEF50221D4828 /* FIRSecureStorage.h */, + 33238801326949DAC00EC88289C9E167 /* FIRSecureStorage.m */, + 1A50345281AB6F5D30CA6EE11F5C5108 /* Support Files */, + ); + name = FirebaseInstallations; + path = FirebaseInstallations; + sourceTree = ""; + }; + 6457947CBEECA74209183CA1DE4F6BC0 /* Support Files */ = { + isa = PBXGroup; + children = ( + 7E0C77D04FB7F6ADF79B05024865F975 /* FirebaseCore.modulemap */, + 4D0D828D2BA50C9617AE06268B44A354 /* FirebaseCore-dummy.m */, + 31452DF8E1090D9AC6ADE92C32F5BC2A /* FirebaseCore-Info.plist */, + 4F13CEF2BDCB6C7ABD864E400468E55B /* FirebaseCore-umbrella.h */, + 502076027B4DCEB843DC38B97A94887B /* FirebaseCore.debug.xcconfig */, + B16323EDF0B3CD0A257043DF559E872F /* FirebaseCore.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCore"; + sourceTree = ""; + }; + 65CB0807B05DCA4D4738AD1BD640C2DA /* Support Files */ = { + isa = PBXGroup; + children = ( + D8D77E896ACB460AC316ABCB1831F855 /* GoogleDataTransportCCTSupport.modulemap */, + E0234DBF69A61BF3660F4C6F95F41E80 /* GoogleDataTransportCCTSupport-dummy.m */, + 62761239096B210D4241701FA2FB1D97 /* GoogleDataTransportCCTSupport-Info.plist */, + 4141BEDF9F22F8F20F34FBEC3C8754A1 /* GoogleDataTransportCCTSupport-umbrella.h */, + 0A6B42B21F0C1F8665483A4BB4946268 /* GoogleDataTransportCCTSupport.debug.xcconfig */, + 5E29BD1F7221E4AB0C4A4ED785D7608C /* GoogleDataTransportCCTSupport.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransportCCTSupport"; + sourceTree = ""; + }; + 67EF017CDF1EDC8BD048E67812E428FB /* Firebase */ = { + isa = PBXGroup; + children = ( + B1B1C14E8E0775C48A58F4FC523806F7 /* CoreOnly */, + F208968178D72B99311B28D5389B58FE /* Support Files */, + ); + name = Firebase; + path = Firebase; + sourceTree = ""; + }; + 6B810DD0025EE3B8FCE4216CD1BABA20 /* Support Files */ = { + isa = PBXGroup; + children = ( + 9FFAA5D9CE88732904C77C404AC91429 /* leveldb-library.modulemap */, + 9857113D2F1E85DDF6449FFE23D64413 /* leveldb-library-dummy.m */, + 69749DD73C4D1A25AB8A0938B17D6E2C /* leveldb-library-Info.plist */, + EA66CFA4C0F8440600B673FB72ABD385 /* leveldb-library-prefix.pch */, + 205F67811189387CB12408CE5D08FB85 /* leveldb-library-umbrella.h */, + 2BE2D2C1742A0A5FD7AA60074322F8F2 /* leveldb-library.debug.xcconfig */, + C971FDA3436CE4F78017B79B4063F5B2 /* leveldb-library.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/leveldb-library"; + sourceTree = ""; + }; + 82B6472C41FB7671F1461938B44AF889 /* Support Files */ = { + isa = PBXGroup; + children = ( + B24AD89FADA9EEF707A29719300BBAE7 /* FirebaseAnalytics.debug.xcconfig */, + E467841A32C8128E295B54A295D58D2E /* FirebaseAnalytics.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalytics"; + sourceTree = ""; + }; + 8AD37DEA100AB103849E4DCA01F0341B /* Support Files */ = { + isa = PBXGroup; + children = ( + 3CC724DC78CD413A599BC4051FDFB089 /* FirebaseDatabase.modulemap */, + 9EC147AA53DDCE9113303230BAA16823 /* FirebaseDatabase-dummy.m */, + 60C14C6B81499F57816A85B725572902 /* FirebaseDatabase-Info.plist */, + EB69E36490C39B4946BAF571B5E6621E /* FirebaseDatabase-umbrella.h */, + 38EBB4AB7E209E3659BF7E9B889F7423 /* FirebaseDatabase.debug.xcconfig */, + C1D0CF348FD58D4E6F51BC58089A8946 /* FirebaseDatabase.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseDatabase"; + sourceTree = ""; + }; + 8C501B4FDE4B2444C33C37F529DB0849 /* Support Files */ = { + isa = PBXGroup; + children = ( + F92D9CADD5265FD05D46F23EF0586CDF /* GoogleUtilities.modulemap */, + 0DBFBC879C80096896F5050F43D67974 /* GoogleUtilities-dummy.m */, + 31C383A5D52590F19530998CE602FE17 /* GoogleUtilities-Info.plist */, + 63F238CF5864F2FD8C60BAD8AC561C34 /* GoogleUtilities-prefix.pch */, + 9466A7E6EE64E7107817BB3DD4AB65AE /* GoogleUtilities-umbrella.h */, + DA6701FC5AB530406CBCD86ED01A7743 /* GoogleUtilities.debug.xcconfig */, + F51F769F4128614EC9AACBDED917D441 /* GoogleUtilities.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleUtilities"; + sourceTree = ""; + }; + 8E1B54CBD2C39B17030CEF35043F77F5 /* Pods-PediatricPancreas */ = { + isa = PBXGroup; + children = ( + F5B061141C7129BEE54C767270F97A96 /* Pods-PediatricPancreas.modulemap */, + 51D30EA04D793B10FED533DBFC51398A /* Pods-PediatricPancreas-acknowledgements.markdown */, + 46149FED4D72A781404735F743191B7A /* Pods-PediatricPancreas-acknowledgements.plist */, + 4990C45303FADD6DD0B9FD280C5B5FE4 /* Pods-PediatricPancreas-dummy.m */, + 1BC5FF4DE07A6C7B013179FEBB457872 /* Pods-PediatricPancreas-frameworks.sh */, + D0ED6BAA2501018C4E87CD44859D6608 /* Pods-PediatricPancreas-Info.plist */, + AFB0D7EB1E556FEB7B8B8BABE4313A1B /* Pods-PediatricPancreas-umbrella.h */, + 7960FB1C76F2424FD931382B8D99FE6A /* Pods-PediatricPancreas.debug.xcconfig */, + 518C77022625AF3F201451F80ACA198B /* Pods-PediatricPancreas.release.xcconfig */, + ); + name = "Pods-PediatricPancreas"; + path = "Target Support Files/Pods-PediatricPancreas"; + sourceTree = ""; + }; + 905F6F16733327C28C57190B7AC788EA /* Products */ = { + isa = PBXGroup; + children = ( + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */, + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */, + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */, + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */, + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */, + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */, + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */, + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */, + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */, + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */, + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */, + 2C86C31F45C132250286638F6D488663 /* Pods_PediatricPancreas.framework */, + 5552D0C170F2A442665A8F97BB64E4F0 /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */, + FE000DCA7D5E753082D9590F1EAC1696 /* Pods_PediatricPancreasTests.framework */, + ); + name = Products; + sourceTree = ""; + }; + 9E8B5C93FD16351758350E5643FC5DA2 /* decode */ = { + isa = PBXGroup; + children = ( + ); + name = decode; + sourceTree = ""; + }; + A40521D209F62D834D87D4F4264DED64 /* leveldb-library */ = { + isa = PBXGroup; + children = ( + 0994919D6FF1636BBE1892696E9DA4A2 /* arena.cc */, + 9A48322D21C211FB16E7DB64E6B5AB6E /* arena.h */, + ED529DE57D865F4DC7EE0F3956AAB7DB /* block.cc */, + DE20B3C2547CB5DDA522FADAB581891D /* block.h */, + CAD8EC4ABB74DAEA13817229074C883F /* block_builder.cc */, + F61EB68986A7759962C52C309AF151B2 /* block_builder.h */, + 623D671CA43E7F78C56956E343D5657D /* bloom.cc */, + 47DD04AD61421A996DEAE095AA51E77F /* builder.cc */, + 687462B2466B5822E171E11E94D99E9F /* builder.h */, + AD600D36912F30C50EFC184EE3D04F7E /* c.cc */, + C3731E4990AAEF341E76DB0A3AB7E6B0 /* c.h */, + 448011007D98317BF4F7C1098DC99366 /* cache.cc */, + 30663E00087519FA3686DFE7783369E9 /* cache.h */, + 30E60BB59ABCAB6163E9F312DCAA82C6 /* coding.cc */, + DF1AE6443E291955DE6DE481F41F5408 /* coding.h */, + 6E5AB98A277B1CB96C5A1CB204FA77FE /* comparator.cc */, + 7A820887FD76849A2C54FED3B31C6E2E /* comparator.h */, + E653C151D9C6CAC8F8FB64B0774210D0 /* crc32c.cc */, + 31A3DA146C85F0E4208EDF51D635374E /* crc32c.h */, + 0C9AD50E9DF223C0BC44EDCA95E412DF /* db.h */, + A88033DCEC6D14ED10C3F3C8FF7981C7 /* db_impl.cc */, + 6D0C04076DA35AE3B33CF8AD8BAF984A /* db_impl.h */, + E83A950C90FADE82C6C50AB81CA86027 /* db_iter.cc */, + D9975934F005271D708CDC03FEA060AF /* db_iter.h */, + 34D792D28402E4437C7860AAC976A3A7 /* dbformat.cc */, + 3EEFAECB1EA225E89728D68E7EE8A8A0 /* dbformat.h */, + 6FACDBC1AFD69E2F70800AFC30CFAFE7 /* dumpfile.cc */, + E45F8CF91067F02738B6EA753E318E1E /* dumpfile.h */, + 220B0328CECBE9CE20EC4490CB388622 /* env.cc */, + 975851733C4EF17619E794A66DD652A8 /* env.h */, + F8FAAC19C9BC593A8592BFA3F979E482 /* env_posix.cc */, + BCDBC9E6585A6FC8409A7900F72E6143 /* env_posix_test_helper.h */, + D5EB776A6BFE1187D7EC5CC46FE6F740 /* env_windows_test_helper.h */, + 2F7A917CF1ED84B125E53F79C218D36C /* export.h */, + 1ACFD04FDEBFD059B55BE1FA713972C2 /* filename.cc */, + 371CBDB9F2F452BB9341C8D0395B8A2E /* filename.h */, + 39FF3E51D669385E3E87BD2ACCFC4ED8 /* filter_block.cc */, + C7DEE606CBB9A67C91F550224BCB72D8 /* filter_block.h */, + BA1D3CE763B4DFB39712DC2D0F9C6C96 /* filter_policy.cc */, + 560FEF99670CDFC70E4F9F5F8268CFF7 /* filter_policy.h */, + EF6C6710B2B163CE881A5BAE36D20B5D /* format.cc */, + F3FE91D249283827126AA99EAB18DC0A /* format.h */, + 12D88D855D9F5F1FB41B1CF4A0280262 /* hash.cc */, + F5CEB151BEA86559CC6F1B460E2A6456 /* hash.h */, + 6BA701D49705278AE2504369CB8FCBB3 /* histogram.cc */, + 2C22FCC38A85E7F7852BF44E2551FDC4 /* histogram.h */, + 4236FF19FECDA313AEEBB197D87F13BA /* iterator.cc */, + A32910BBD1B9FC60DD70E012F4F8065F /* iterator.h */, + 34F03D87EA8B176419ECB12B051736B1 /* iterator_wrapper.h */, + 25CDFCEB95D5E7B062D672C75F8ECBD5 /* log_format.h */, + 4B531F7005792C54B07D84507A34E3AB /* log_reader.cc */, + 416C805A18279EC4D3465411DD4D472E /* log_reader.h */, + 83E6D3617089AEC1DD83534C656365C9 /* log_writer.cc */, + DF0640ADF2E74C8DFB07534BE9B3BBAD /* log_writer.h */, + EE1781250E9DF101BDFB90CB850C386F /* logging.cc */, + 546AA55159CBCDB057982CCAAF150602 /* logging.h */, + 35E008788331AAF58516A9A5082B6334 /* memtable.cc */, + 5B69A11D9AE8DE28BEEBBDB6FD309B45 /* memtable.h */, + 92B0F3647F558C2051897581E20E8AA5 /* merger.cc */, + 19C7D0C7517E9CAF071A59368C48A735 /* merger.h */, + CD33D7886791A925EDD3E12E07C16039 /* mutexlock.h */, + 6132BBDB4E6F8E0B4E9B5E3C9850E8DE /* no_destructor.h */, + BBEA5A247884A7C3F759610363D9FD71 /* options.cc */, + CB0616FB9FF2AAD7A912C19A189655DE /* options.h */, + A2BABC8EE3398D6E3B11BEBB4BDDA527 /* port.h */, + 522F207349FC0C3AEBE0DC5C8D0F6A5E /* port_example.h */, + 8F51779B334E9D371C089C2D84A4C309 /* port_stdcxx.h */, + EBB7BB312BA46B435C86D22D545460A6 /* posix_logger.h */, + B880DC9BE4C9FE6FDA8BF6D351C8595A /* random.h */, + B01E3EBC54F74EB224BC9FAB87F151F2 /* repair.cc */, + FA39C6D824C47D10541A5DB3BBDE2263 /* skiplist.h */, + 64927969944CC6B0EF7ABBF8A9D6B982 /* slice.h */, + D5C117A339CC3C9E15D400EB57AE4176 /* snapshot.h */, + D4B8BE02734895C466C402F08AFCFE27 /* status.cc */, + 8D5175073773047C9EBB484D43935067 /* status.h */, + 058600A9D546320B88F62E2A82AE2143 /* table.cc */, + 4CEA8AD862EBD0CBF7BEF03AA3752A1E /* table.h */, + AAA8E1EFC2A415EAD47ED600FEDFB8A0 /* table_builder.cc */, + CBB4910A187E43ED4826B25BAD824F43 /* table_builder.h */, + E2A08AAB5D65AB79EB24EC26404117B7 /* table_cache.cc */, + 8AEFE796A73D36A9215F664981D72C70 /* table_cache.h */, + E6C8EE55738FAA4E95659CF5A409F9D9 /* testharness.cc */, + 813307FB7EF7DEF7EB26B719D22EC86A /* testharness.h */, + 9509AC17857ED363396A3E274326F0BC /* testutil.h */, + 6B4E576722528645372A7E3DABD88704 /* thread_annotations.h */, + FA46E5D5E0C2FA73D96E33137632ECAA /* two_level_iterator.cc */, + AF6C3EBCD2C9B78F9071C9BA34584A60 /* two_level_iterator.h */, + C6F3604157287623FC134D9C84D970BF /* version_edit.cc */, + 6E2242D1AEC32106B5EC1B6007F11512 /* version_edit.h */, + B7B9AFFBA75FF2D8A831275F9A83318F /* version_set.cc */, + 4AC6BC15BEF7347E79C01F3CC6F1AEA3 /* version_set.h */, + 71F1E99218E565E5F99716E1FF698721 /* windows_logger.h */, + 19F174A0B87E27B10889237216A3FA55 /* write_batch.cc */, + 8B8FA4B0B8B53577758148C4B29CB05F /* write_batch.h */, + DF667BD0C719334D242C99243B7287FE /* write_batch_internal.h */, + 6B810DD0025EE3B8FCE4216CD1BABA20 /* Support Files */, + ); + name = "leveldb-library"; + path = "leveldb-library"; + sourceTree = ""; + }; + A5628005C9161B49943C23EC721BE330 /* Environment */ = { + isa = PBXGroup; + children = ( + 3C251CBEB0F513BF966974089FB9C542 /* GULAppEnvironmentUtil.h */, + 52EEB6148AFFBEE7152B90E633612CC6 /* GULAppEnvironmentUtil.m */, + 67373B6F54F16182D369B74E58D5F536 /* GULHeartbeatDateStorage.h */, + 1FF27C9FA28C17B538FE3D79E5568EFB /* GULHeartbeatDateStorage.m */, + 5460CEF22218F0CDDD2B043F5F7855AB /* GULSecureCoding.h */, + B6AB2E6D2B1419D09CFF28AED2C2B388 /* GULSecureCoding.m */, + ); + name = Environment; + sourceTree = ""; + }; + A68DC60BD3729713553C1C27BA04377C /* encode */ = { + isa = PBXGroup; + children = ( + ); + name = encode; + sourceTree = ""; + }; + AA339D736EE834251F9F281A55AD01AD /* GoogleUtilities */ = { + isa = PBXGroup; + children = ( + 536D93C9EB1D7A375834114EB7D34C59 /* AppDelegateSwizzler */, + A5628005C9161B49943C23EC721BE330 /* Environment */, + 47F766F56A846D3BF9F2174CCDC75CA3 /* Logger */, + 0AC35FB677FF63258C49DEDF3E802184 /* MethodSwizzler */, + 0BA1F38C813F1D73921602BE4FE2DFE6 /* Network */, + 43250CE12EE95C10950348E8C7E40C92 /* NSData+zlib */, + C24AE16F7B830D07B209FCF9F363CB70 /* Reachability */, + 8C501B4FDE4B2444C33C37F529DB0849 /* Support Files */, + 400CF04A63F797AAEC4259932D7BD6BD /* UserDefaults */, + ); + name = GoogleUtilities; + path = GoogleUtilities; + sourceTree = ""; + }; + AC72501E32AAB71453557EFCEAB1FDC5 /* Support Files */ = { + isa = PBXGroup; + children = ( + 09BBDA18467B7C62A9271E288A82ED29 /* FirebaseCoreDiagnostics.modulemap */, + 8B475A67F01481B39D7F5EBD1FADD957 /* FirebaseCoreDiagnostics-dummy.m */, + 38C4B97EC12F8B9C3DE1220BCB4A109E /* FirebaseCoreDiagnostics-Info.plist */, + FC13A073E2E6654C9515F95CD5BAC0E8 /* FirebaseCoreDiagnostics-umbrella.h */, + 5CD246213E4E717E503D47F79BBB2439 /* FirebaseCoreDiagnostics.debug.xcconfig */, + 382B9EE58EBB9AFB9485174E53DED76A /* FirebaseCoreDiagnostics.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCoreDiagnostics"; + sourceTree = ""; + }; + AFFBDE675567ED91B8C4E488E594266C /* GoogleDataTransport */ = { + isa = PBXGroup; + children = ( + 1E76D9053038A33CDEBFAE625CC5BADE /* GDTCORAssert.h */, + D29F1B6F2D210493CE1B350B9E1190A6 /* GDTCORAssert.m */, + 69378FC37B1DFB015522CAFAF6EC4001 /* GDTCORClock.h */, + 4333D276EEF0EDA615A614467B65F6F7 /* GDTCORClock.m */, + 010EB3293303194FAFD89055A4E91CE3 /* GDTCORConsoleLogger.h */, + FE8952D00BD256B9079E38ED3637F926 /* GDTCORConsoleLogger.m */, + C4050A6B53B6F2A1D68A2112D200D0C5 /* GDTCORDataFuture.h */, + 2F8A01B76B2056EA8629ED6314AA7FBF /* GDTCORDataFuture.m */, + A9A07FADE7126A2EBA873664735E0563 /* GDTCOREvent.h */, + 954224218DA6DB484D27DFDAEF45E7B4 /* GDTCOREvent.m */, + D3F8923F8BF7B696F0F826E15C1D08E1 /* GDTCOREvent_Private.h */, + A6C32388BA9394C95A78AE1D39EDD150 /* GDTCOREventDataObject.h */, + 08DDE3680AB4A3C8926B96415B4152F9 /* GDTCOREventTransformer.h */, + C85E4E623B4A72E522D791D20293F655 /* GDTCORLifecycle.h */, + 5F8C417906B62E8422D71968C8EEBF1E /* GDTCORLifecycle.m */, + CD82CF0A8D09569DA4154DBE971388CB /* GDTCORPlatform.h */, + EBDC269E1E8CFA6578C1F1FC4F7C4728 /* GDTCORPlatform.m */, + 1FC19607EAE0661F18ACB5A03636690B /* GDTCORPrioritizer.h */, + 84A06B13C9427E8DC216B2155A9A4C51 /* GDTCORReachability.h */, + E48B1808AA40A73BA3D46EA4AE5B3927 /* GDTCORReachability.m */, + B5399854B710AA8DCDC59D42010EBE33 /* GDTCORReachability_Private.h */, + B833EBA86E1C3BE131AB895BCDE61AA1 /* GDTCORRegistrar.h */, + 832DEDF9B8FB5DB7840D30D124CC4856 /* GDTCORRegistrar.m */, + 6CF3E3945EDFC777942BE90AA282A705 /* GDTCORRegistrar_Private.h */, + F4A3B19D1538DD146880608D2DA1FCAA /* GDTCORStorage.h */, + C1830DD3C00085399D281E078B5A7CE1 /* GDTCORStorage.m */, + 7EA45B5C00F15C4CCF12F75EEA5288FA /* GDTCORStorage_Private.h */, + BE21DDFAF668870C165692DA4385D672 /* GDTCORStoredEvent.h */, + FDBEE362A1AC58BB9A15CC82604155A6 /* GDTCORStoredEvent.m */, + E61B535DAB4A7B24C60731AB49DF519A /* GDTCORTargets.h */, + 4A9A12A16AB2EE91241EFB10A5E623ED /* GDTCORTransformer.h */, + AF06957A0771C86EF3C7DBAF75A4F553 /* GDTCORTransformer.m */, + 483ED7857A31966E18E87385A1A58AD8 /* GDTCORTransformer_Private.h */, + C9FDFEE5B3671FA221FDBC8ACFFA3041 /* GDTCORTransport.h */, + 61902C839F537E39C79EBD06E14DD2C4 /* GDTCORTransport.m */, + A3FA603E46D511623D3630CAE0F5C1F3 /* GDTCORTransport_Private.h */, + F04EDF68A0FB407E446327F460FEDF03 /* GDTCORUploadCoordinator.h */, + 89EFDC2FBFA53532A9CAAEA608E7C222 /* GDTCORUploadCoordinator.m */, + E17BBB66CE95AF16025FD900BDAC46D7 /* GDTCORUploader.h */, + F5977632C28C8A80798C83831080ACC9 /* GDTCORUploadPackage.h */, + 764063E4BDC2B2AC40BEFF95355FD7FC /* GDTCORUploadPackage.m */, + 89D3EEC62CA2D9B28936A1B89A9733C8 /* GDTCORUploadPackage_Private.h */, + FC08F6EF38191BE8F7E4F4CF74AF46C2 /* GoogleDataTransport.h */, + 0C0A7EAE7589B78EBA226ECFEC1266B9 /* Support Files */, + ); + name = GoogleDataTransport; + path = GoogleDataTransport; + sourceTree = ""; + }; + B1B1C14E8E0775C48A58F4FC523806F7 /* CoreOnly */ = { + isa = PBXGroup; + children = ( + CE981CCC7DE79FE32665CA534CDF326E /* Firebase.h */, + ); + name = CoreOnly; + sourceTree = ""; + }; + BA33A7C1755346DD3ABAADEE9D268D88 /* GoogleDataTransportCCTSupport */ = { + isa = PBXGroup; + children = ( + 33023881967395B122B2547507E8354C /* cct.nanopb.c */, + 9F1F2773CA1EAE4D8A704AEEFD180CCD /* cct.nanopb.h */, + A2927D87478BAC6E0BF0481759116A7F /* GDTCCTCompressionHelper.h */, + 3CD37FD280133AB42ABA89D293273149 /* GDTCCTCompressionHelper.m */, + AE0A767C52FD5794347BB98E80936166 /* GDTCCTNanopbHelpers.h */, + EBC953A34508AE16186590261C12C687 /* GDTCCTNanopbHelpers.m */, + 656F06CD541DEA906BAE925398B67D0B /* GDTCCTPrioritizer.h */, + A2D7E4828D2181423CA7DD6FA9418C84 /* GDTCCTPrioritizer.m */, + 2B51CD46764C9CB5026CB65386897AD8 /* GDTCCTUploader.h */, + B17CF74C10270725403C6592D2382E9E /* GDTCCTUploader.m */, + 65CB0807B05DCA4D4738AD1BD640C2DA /* Support Files */, + ); + name = GoogleDataTransportCCTSupport; + path = GoogleDataTransportCCTSupport; + sourceTree = ""; + }; + C24AE16F7B830D07B209FCF9F363CB70 /* Reachability */ = { + isa = PBXGroup; + children = ( + FF8DF3F9B8EAE9DF3404C063DF67AE24 /* GULReachabilityChecker.h */, + BB5C170B61C645EBD115F14EB5249AF0 /* GULReachabilityChecker.m */, + 91714649A9785EF95152BD5F0A1B1F45 /* GULReachabilityChecker+Internal.h */, + 24A02E9A2F6D74E292328F6A46B242A0 /* GULReachabilityMessageCode.h */, + ); + name = Reachability; + sourceTree = ""; + }; + C594D977D3AC8BE913F5AC2902CA13DA /* Support Files */ = { + isa = PBXGroup; + children = ( + A51F851D55A40196F404D20CC95BAD99 /* FirebaseCoreDiagnosticsInterop.debug.xcconfig */, + 23C79734BF195C12C8CA32C05F9DC901 /* FirebaseCoreDiagnosticsInterop.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCoreDiagnosticsInterop"; + sourceTree = ""; + }; + C81B6CBE1E849E2F53A17EC7CCD1A566 /* Pods-PediatricPancreasTests */ = { + isa = PBXGroup; + children = ( + BE2D52670C14C984DFC35B074D8D9E05 /* Pods-PediatricPancreasTests.modulemap */, + 31ECE032F2B1D1C931F783C363CEA9D3 /* Pods-PediatricPancreasTests-acknowledgements.markdown */, + 59C9B1EC6DD625C6D01C030834CF246E /* Pods-PediatricPancreasTests-acknowledgements.plist */, + 6CE1AAC4069551B0743B4F75F9A76348 /* Pods-PediatricPancreasTests-dummy.m */, + 3D78108544D29EC6204FBFD22A285626 /* Pods-PediatricPancreasTests-Info.plist */, + E48BE45942FA887A32872ECE30375ADB /* Pods-PediatricPancreasTests-umbrella.h */, + 566267F9A313143EE6BDD499F3866124 /* Pods-PediatricPancreasTests.debug.xcconfig */, + C099348FF2762A50FC42CDA312B9414B /* Pods-PediatricPancreasTests.release.xcconfig */, + ); + name = "Pods-PediatricPancreasTests"; + path = "Target Support Files/Pods-PediatricPancreasTests"; + sourceTree = ""; + }; + CDE93E2CC3F828D6C0968192CD21055D /* FirebaseCoreDiagnosticsInterop */ = { + isa = PBXGroup; + children = ( + 433556677AD5081DFD4E9FA881C05F15 /* FIRCoreDiagnosticsData.h */, + E54CC79A075D9902E781D44FAB846BA8 /* FIRCoreDiagnosticsInterop.h */, + C594D977D3AC8BE913F5AC2902CA13DA /* Support Files */, + ); + name = FirebaseCoreDiagnosticsInterop; + path = FirebaseCoreDiagnosticsInterop; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */, + 00100BD28A3574D53A3451A58001DAE3 /* Pods */, + 905F6F16733327C28C57190B7AC788EA /* Products */, + 45EB47C565CADF2303CB7A0FF15AEAC0 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D3263F50C53E400245FA7FD90B60BD0F /* Pods-PediatricPancreas-PediatricPancreasUITests */ = { + isa = PBXGroup; + children = ( + 28E81AF81E32C892833C90AE15DC296A /* Pods-PediatricPancreas-PediatricPancreasUITests.modulemap */, + 55FD8F26EA01FA0EE0F08CDB51E724A6 /* Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown */, + DE2016AF3072FDA306C33F4E0AFD83EC /* Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist */, + 72D52576F67BF816A679DF6B1DDBFB79 /* Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m */, + 7E160A281F114096E68F71EE98DB00F8 /* Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh */, + DF809DE6C9A673EBFDF59916F28E5826 /* Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist */, + BA7A11DD2C5A7EB1CBDB888741E122AF /* Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h */, + F66F8E423E7A327C613AC805E253BB2F /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */, + 3B41A267A51E2D1204B721F1B7DF81D1 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */, + ); + name = "Pods-PediatricPancreas-PediatricPancreasUITests"; + path = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests"; + sourceTree = ""; + }; + D91D9CB3653EE01DCB65AE420B69E3F4 /* PromisesObjC */ = { + isa = PBXGroup; + children = ( + 4B5719CDCE6B2A2F1216F9C92E6D02C8 /* FBLPromise.h */, + 3FD52FD8826F32BA541D72467BE7B21B /* FBLPromise.m */, + 90C235774B7FEFA58692D00424C37A4B /* FBLPromise+All.h */, + 8F05E89B63938864335C55A44A0A73B7 /* FBLPromise+All.m */, + FB8A36424CE63AB822739A749BB71C82 /* FBLPromise+Always.h */, + 2E7463DD70BAEAA5C553A05777352958 /* FBLPromise+Always.m */, + 89EF1757A361BC3BE2727F86201C94F8 /* FBLPromise+Any.h */, + DDC164F6102A008EB68780B6F360A50A /* FBLPromise+Any.m */, + 14DD85EA7D746AA0ABA6E66DA54FE552 /* FBLPromise+Async.h */, + F4F07B58CF53D2FCABD8B03E53455CE5 /* FBLPromise+Async.m */, + 4A14479C1990437D603C775E0838399D /* FBLPromise+Await.h */, + 1E620741BA858DAFC95CA5490B42CB4B /* FBLPromise+Await.m */, + 99CB6929C9B9E330102E12BC10ADBE67 /* FBLPromise+Catch.h */, + 90229CCE5D34D7A531E16765B37ABE39 /* FBLPromise+Catch.m */, + 6F120332D2F3AADB20BE6BD46DB04B5C /* FBLPromise+Delay.h */, + 793FDF0150561467E6DDF33320B696A9 /* FBLPromise+Delay.m */, + 713F262D1F922BE2029360D4072ACDE0 /* FBLPromise+Do.h */, + 1321F309AB4B1BB45EEC3789A76939DA /* FBLPromise+Do.m */, + 63AAC507B0C7EE188A57BC2455B04E4D /* FBLPromise+Race.h */, + 71A603CA5B006121B694846787D7BAD9 /* FBLPromise+Race.m */, + A680F32866E1A09336694B099C04AF81 /* FBLPromise+Recover.h */, + EC6076EA5FF19E6726A6FEB3836F7451 /* FBLPromise+Recover.m */, + D90F32A060B026F6D87B7D74D28DC97C /* FBLPromise+Reduce.h */, + 15C61D66067C8460216C517BBD011E18 /* FBLPromise+Reduce.m */, + F10C76FEC7DE64107890BCD0E69DE428 /* FBLPromise+Retry.h */, + 6219B0FFB8044BA7B94076BAB77DB1D3 /* FBLPromise+Retry.m */, + A51275DED8B5876B1EB201F7E40D4517 /* FBLPromise+Testing.h */, + 31EB496C4974C87B5DD9A5C3D20FA2C7 /* FBLPromise+Testing.m */, + EE99BAF073CA1D81781B1B25C847608F /* FBLPromise+Then.h */, + 7983B3F70324C775988EB7A1E3932685 /* FBLPromise+Then.m */, + 714CACEB6E4D9CE23EF7D85F0B7804A4 /* FBLPromise+Timeout.h */, + FBBACCFC3B4FD853FC952CC223D94ED0 /* FBLPromise+Timeout.m */, + E8528848BDEDC26C42D1B3137E78486D /* FBLPromise+Validate.h */, + F777C5E65C22D85894FAC33B1AEB107D /* FBLPromise+Validate.m */, + 57018189681D84C262FEFABC79A46C04 /* FBLPromise+Wrap.h */, + 83F1C74FCB7D27EEDD0F20E80317A163 /* FBLPromise+Wrap.m */, + 7DA049BCB41CCA3C4CC0998EE845FC32 /* FBLPromiseError.h */, + E1804140830E73C79880D6687271FAC9 /* FBLPromiseError.m */, + 2C628E92632EDA6D9E0BF833B6E84CEC /* FBLPromisePrivate.h */, + CCF0CDBF79119FF6820FFA131F04236F /* FBLPromises.h */, + F28088526F8EADB110C6449E3B837A59 /* Support Files */, + ); + name = PromisesObjC; + path = PromisesObjC; + sourceTree = ""; + }; + DB02DB0D7CC7668A03149C0E6A9A3150 /* FirebaseAnalytics */ = { + isa = PBXGroup; + children = ( + EC35E5BCF46E68F25915D6E00041E19E /* Frameworks */, + 82B6472C41FB7671F1461938B44AF889 /* Support Files */, + ); + name = FirebaseAnalytics; + path = FirebaseAnalytics; + sourceTree = ""; + }; + E97659F6327147F3C472C0C44FC5E1DD /* FirebaseCore */ = { + isa = PBXGroup; + children = ( + 9426AF07444B347C55EF8E50812A5EAB /* FIRAnalyticsConfiguration.h */, + F345B60ED7E3934E7012324272612AE2 /* FIRAnalyticsConfiguration.m */, + C0A16BACD8F0BE6703DDD5DFA6AF4F0F /* FIRApp.h */, + 02E4DD3DCDB31EC1648CA6C98780E009 /* FIRApp.m */, + 0EA0F7CE6EB64CFF17CB11ABEC8CDF16 /* FIRAppAssociationRegistration.h */, + B1D25D46D0D17BB9DBF55A909B2D119F /* FIRAppAssociationRegistration.m */, + 5C4601FE5C4C1B22A2499A3C8CFD4147 /* FIRAppInternal.h */, + DFCB1951C0F24D4ACC2A38DAECEA2065 /* FIRBundleUtil.h */, + A0CBF92D27BF20F0173D84B2D7B5BDB7 /* FIRBundleUtil.m */, + 9CAC4510A566921C9F90A3C21FB371DA /* FIRComponent.h */, + D5A546058E77F0752995F315FBF8385F /* FIRComponent.m */, + A3C2A80012BC975B349FB09DA77B8850 /* FIRComponentContainer.h */, + 54475272A64C46FD9B044CD0B03D1F16 /* FIRComponentContainer.m */, + 141F97B030083310E1B66925EBA42F52 /* FIRComponentContainerInternal.h */, + 7498B69B8CAE5DD507C2F5F97F17CE08 /* FIRComponentType.h */, + 0EB8FAE52E1EE34C048C2E25D084AACF /* FIRComponentType.m */, + E0C3B65AB5EB25B07B491A17C3CBDACB /* FIRConfiguration.h */, + 5C1D2B97EE131D32FFE68B5D4797D618 /* FIRConfiguration.m */, + 4F42AC0B1D0F68847E4A548E94AD9268 /* FIRConfigurationInternal.h */, + 3884BBAFEA06415C2E4E1D75F152F2B4 /* FIRCoreDiagnosticsConnector.h */, + 52041C725712526A753AF310EC5E0271 /* FIRCoreDiagnosticsConnector.m */, + 4B79D7F54E520AF3904F5139432C278C /* FIRDependency.h */, + 43015EB8E78629BAA11B46C1B2E9867D /* FIRDependency.m */, + B422450B8B9A222431185AE041CCA41D /* FIRDiagnosticsData.h */, + DE49548AE3469F15EC0F3A8E7C0E12CA /* FIRDiagnosticsData.m */, + EC43FEF1CA9773F7407B76F3B8CE500E /* FirebaseCore.h */, + 7E32B2315E2CC544C7D95BA6F99EC432 /* FIRErrorCode.h */, + FFD1A868DDA411E233111E156FB11FAD /* FIRErrors.h */, + 5EF616070C58259A27E8EEAA63F9E462 /* FIRErrors.m */, + DB8C5BAA46113C178F139DA567DEC18F /* FIRHeartbeatInfo.h */, + 533EB989EB34349FC33B5C0C9C22EF78 /* FIRHeartbeatInfo.m */, + FE4584B1E56CACAFB4FE9D377A31CB04 /* FIRLibrary.h */, + 73F0B382A1404222E1C60352DFF7BB72 /* FIRLogger.h */, + 0CAABEE8F7F783A6B7FD09ACA8A04842 /* FIRLogger.m */, + 8ABDCEADCDB0A5F734C40BD872DD9C0B /* FIRLoggerLevel.h */, + F189BAAA0B343A34C79A53561EF6E895 /* FIROptions.h */, + 6E9580AEFCE0FFB8EB4D0165A208A7EF /* FIROptions.m */, + 45FE005CA2C4A3AEF54D0E39D139568C /* FIROptionsInternal.h */, + CBA16637DCCE5CC8B2C6EE6EF4523671 /* FIRVersion.h */, + 1D2B2318949D5A383E68777964C87251 /* FIRVersion.m */, + 6457947CBEECA74209183CA1DE4F6BC0 /* Support Files */, + ); + name = FirebaseCore; + path = FirebaseCore; + sourceTree = ""; + }; + EBAAC1048CCF89CDC1AB4771762F3408 /* FirebaseCoreDiagnostics */ = { + isa = PBXGroup; + children = ( + 1E8B299D83AE65375BAF9C04BB63EB71 /* FIRCoreDiagnostics.m */, + A1AE308C5F0E074A28931424B649BFB6 /* firebasecore.nanopb.c */, + D162B1331B24ACB706028A659E347607 /* firebasecore.nanopb.h */, + AC72501E32AAB71453557EFCEAB1FDC5 /* Support Files */, + ); + name = FirebaseCoreDiagnostics; + path = FirebaseCoreDiagnostics; + sourceTree = ""; + }; + EC35E5BCF46E68F25915D6E00041E19E /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6005E4C85596FC45C8FC9F41724E5808 /* FIRAnalyticsConnector.framework */, + BBC3359829EE0F378AD8D40332B7FFB9 /* FirebaseAnalytics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + F208968178D72B99311B28D5389B58FE /* Support Files */ = { + isa = PBXGroup; + children = ( + 4424C23BA8BD950C7B96DC874B777989 /* Firebase.debug.xcconfig */, + 0E998FD134CA2B57FE5787B01602A4C5 /* Firebase.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Firebase"; + sourceTree = ""; + }; + F28088526F8EADB110C6449E3B837A59 /* Support Files */ = { + isa = PBXGroup; + children = ( + 13C3D6047848E764C26BAD1410172F7C /* PromisesObjC.modulemap */, + 723017E29BE5FD9D38BE7477D5D6FFF4 /* PromisesObjC-dummy.m */, + EB6CC861AA6CD619090F1C484BEFADA5 /* PromisesObjC-Info.plist */, + 393480CCC4702D3A5CC9CAF98AF4E723 /* PromisesObjC-umbrella.h */, + 1E30CFB2462172C3B6FD5FF8283FA7AB /* PromisesObjC.debug.xcconfig */, + 857C2725A4F0AF79A30DEC50DA6A0E48 /* PromisesObjC.release.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/PromisesObjC"; + sourceTree = ""; + }; + F79F78D66361EA6A8DB031AE13A5612E /* FirebaseAuthInterop */ = { + isa = PBXGroup; + children = ( + 7371FD5514980F9343B6D988BB4EBD0C /* FIRAuthInterop.h */, + 19B8489ED1B89D93FDAE24B44BE77769 /* Support Files */, + ); + name = FirebaseAuthInterop; + path = FirebaseAuthInterop; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0B999D039D6C059647B762E2231AB32B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 898A085D4E57B4FFA229AAB41E8ABFFB /* FIRAnalyticsConfiguration.h in Headers */, + 2289E1B5D0115CBA01E425E5026FAF88 /* FIRApp.h in Headers */, + B2CA90A68FBE428C49128EAE88BB2AC2 /* FIRAppAssociationRegistration.h in Headers */, + 41AABBF5FAA79DB754B17E3177777F0C /* FIRAppInternal.h in Headers */, + B01B7D75DB7763EA2C3296984C14FF80 /* FIRBundleUtil.h in Headers */, + 9909838A3051674F444C6A8A23A64284 /* FIRComponent.h in Headers */, + C84A2B8C7FC45AE4AE0FFF312F866AF6 /* FIRComponentContainer.h in Headers */, + 6659F5CD6E5F6D09291FA0707217AC98 /* FIRComponentContainerInternal.h in Headers */, + FA2B48FB9EC42F6DB921371DA2C78828 /* FIRComponentType.h in Headers */, + FE292D46FC3D91B1471CEBB770AED860 /* FIRConfiguration.h in Headers */, + C3B70F07EFE4F953953E203FD3AC47B0 /* FIRConfigurationInternal.h in Headers */, + 184B2AFC33A53E3110998B6DBAD6C67F /* FIRCoreDiagnosticsConnector.h in Headers */, + 0E65E4EA24D5CD3372CDA747C99B7B50 /* FIRDependency.h in Headers */, + 3D62AF01A5143EBCA5218704AF6064CF /* FIRDiagnosticsData.h in Headers */, + 1419FEDD91A2D4BA6C8A5CCA708DD5F1 /* FirebaseCore-umbrella.h in Headers */, + 170291315218C7F7BE01AFC29CB9F16E /* FirebaseCore.h in Headers */, + F20E8DA6C901C65A0BD86B872BEC2DC4 /* FIRErrorCode.h in Headers */, + CED64AD03A2C96DE7DDB42735483808B /* FIRErrors.h in Headers */, + A0D51DF76B678A5EDA312BD7B4C19EB6 /* FIRHeartbeatInfo.h in Headers */, + 91FE0AD7E1B01C145635712FBFE22A23 /* FIRLibrary.h in Headers */, + AEB4660C1A1A40DB69A73928D6DC5D7B /* FIRLogger.h in Headers */, + 68D8A43AE7F71E71D650B6D9571BA4BC /* FIRLoggerLevel.h in Headers */, + 2A7332632039562A0CA53B0746DD5614 /* FIROptions.h in Headers */, + 7CA1CA32D0BA9A285C8B818BAC037538 /* FIROptionsInternal.h in Headers */, + 1457F63F4F792B63938CAD3B54079E57 /* FIRVersion.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 12ED1C5EBF526EEC00EDD3169D857A4C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A1C24EA775DF38CFB1B6C7F53896CECB /* FBLPromise+All.h in Headers */, + 992EB0408FB677ED04369E5AA806F1A9 /* FBLPromise+Always.h in Headers */, + 8B177AD6DA5699A3AB1164ED3F38C392 /* FBLPromise+Any.h in Headers */, + 73520D786C7F855AE3D651D3621D0CBB /* FBLPromise+Async.h in Headers */, + 5423F9E7441C74D9CAB0158790D84C70 /* FBLPromise+Await.h in Headers */, + B109D7D2A695A4E374C1BD28E6C15628 /* FBLPromise+Catch.h in Headers */, + 19EF3A4FE2897DFDDDB0B78C95A838F3 /* FBLPromise+Delay.h in Headers */, + 802025F836213842AD971BFA04320D76 /* FBLPromise+Do.h in Headers */, + 1C2FBF72347EB561D0E30E50848D97FF /* FBLPromise+Race.h in Headers */, + AA63E624F9FE3BDED9FD586CBBEC6B55 /* FBLPromise+Recover.h in Headers */, + BD422B9575A29EB2217618E12CA084CD /* FBLPromise+Reduce.h in Headers */, + F17ECD4A234169F69D7132C3EDF1DEE5 /* FBLPromise+Retry.h in Headers */, + 9A9EC7789D5B83042D5CBC34880C0BA0 /* FBLPromise+Testing.h in Headers */, + 6224C68BA5B4C2D47B103D306B74341E /* FBLPromise+Then.h in Headers */, + 3800B0DE275B049A18AC23B9DBE4A8B0 /* FBLPromise+Timeout.h in Headers */, + 8CB426C640194460BC76964273A677C7 /* FBLPromise+Validate.h in Headers */, + F77DFDE1967EE41BBA0FFB375FDCB21B /* FBLPromise+Wrap.h in Headers */, + AF19EFADE8BE01147CC94A86B4667A83 /* FBLPromise.h in Headers */, + ED38DE7518BE3172FE57374616F3EA97 /* FBLPromiseError.h in Headers */, + 8AA5066C8726135716180F7B48E2A0AA /* FBLPromisePrivate.h in Headers */, + 7D61E609B0D8B4BF0DED821DC50DF226 /* FBLPromises.h in Headers */, + 4E522AB2C46E792F9289878E85D1DA06 /* PromisesObjC-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 242D284DC38937970FCA29C675FACF6C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + F50E434C7DDA75507CC632B0AD9FA9E9 /* Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 246D170714300284136B606F8C814022 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CF86354528716B46ACC9AFE6FCD90025 /* arena.h in Headers */, + 615327D18C1FCF157702F317C0C0E6C2 /* block.h in Headers */, + F456D94FB73E2B1813F015710FC9D7FF /* block_builder.h in Headers */, + CB73D4286965C2A7A8F732E8BD3BF5E6 /* builder.h in Headers */, + 9FB86EE0B96D3B5DA2B6E80203DCA4E3 /* c.h in Headers */, + 9AA87747892902F9D2BE78D1405F0102 /* cache.h in Headers */, + B8736B358DD65B4E7D974BE0A3C19FDB /* coding.h in Headers */, + 6E39108A97275B02B75E1AF6BFD8E477 /* comparator.h in Headers */, + 38B7B99B0D2365F522BA602C9141FF91 /* crc32c.h in Headers */, + 2B95F0E51928C723FAF9D747321D3B18 /* db.h in Headers */, + 1EEF95AEF137498F6F6A4E21125B0DA4 /* db_impl.h in Headers */, + 1553DE80C6D82A7F0E003AE2BE477206 /* db_iter.h in Headers */, + 9BA54EC27C0B83C5521AB4AC61FCEC9C /* dbformat.h in Headers */, + D67161BBCAF4CBE6CB2AFD3040584C4E /* dumpfile.h in Headers */, + 4ADE3210B6FBF7F2B6B42F8933F5D21F /* env.h in Headers */, + 4048E2501D46CBF2761C248E0957DF57 /* env_posix_test_helper.h in Headers */, + 4E98A0CCC93D4BE2753CC91F92F303CB /* env_windows_test_helper.h in Headers */, + 9250971DA13DDF4E7F27C7BFDF16612E /* export.h in Headers */, + B848F96AE5C190DE716CB228963F0A22 /* filename.h in Headers */, + DB3F17AD95C07E11740436162B8720BC /* filter_block.h in Headers */, + C58F38BE65DA76A0B8C6DA31E6E43B2E /* filter_policy.h in Headers */, + AE00643A94C60CD83D43060803F6E3A6 /* format.h in Headers */, + 87424F09F2D4D76BC60F4E6135BF5E86 /* hash.h in Headers */, + 25F1A579A6F66973599A4FEA187A71E0 /* histogram.h in Headers */, + B1C9CAF5F65E34EE5B504002C03E9246 /* iterator.h in Headers */, + 26116DEE25197E11B25680286A045C4C /* iterator_wrapper.h in Headers */, + B40ED35DC8F3525BBC9260C97979B9D3 /* leveldb-library-umbrella.h in Headers */, + E688DCDF4BDA185BDAF4895EDA15C78A /* log_format.h in Headers */, + E7EF884C02037AE839574120C4768FAC /* log_reader.h in Headers */, + C46AB2F9D6A7C9DF279E7A635CE1AD5C /* log_writer.h in Headers */, + 2C01F8F00BEB3D530924839C498CBD05 /* logging.h in Headers */, + 1933D4AF091889C3E94CE3F7D433209B /* memtable.h in Headers */, + FDE96333ADA56EDF32AA11220073E35D /* merger.h in Headers */, + 69186B1E9ED43ACAD2F35E1945261F36 /* mutexlock.h in Headers */, + C0A3AE805627AEE1EEA1CA4B975C8CDE /* no_destructor.h in Headers */, + 3FBAE9D1BD17763A5C3A1BD1253EEE1C /* options.h in Headers */, + B359866B4F605EE2749F613848029764 /* port.h in Headers */, + 48FE6B43AEBC4D0E5934CD1F05CFA8A9 /* port_example.h in Headers */, + CDE1E9926CFB694F40C1E2FA5D3161CE /* port_stdcxx.h in Headers */, + 6B222B03F3BC8345CBFE9802D8770AD7 /* posix_logger.h in Headers */, + C183F302CB97260A6AA2C8DE557EF956 /* random.h in Headers */, + 18BD1985750D26745C9038760103F75B /* skiplist.h in Headers */, + 3627B32161C61600B72B8131AEA45CA0 /* slice.h in Headers */, + 35C9DE578E2AB847D7D877558E43F828 /* snapshot.h in Headers */, + CDB3CFF531DAF96C8551FBB1B4CE58E3 /* status.h in Headers */, + 4F9E52E01C723BBB86A2F3306563369C /* table.h in Headers */, + 81E527E426B62E40558145D83400A12D /* table_builder.h in Headers */, + B49453448E3FA02DF440EFA065B95A38 /* table_cache.h in Headers */, + 7C0DA843726761FFE3436536D5D3B2C3 /* testharness.h in Headers */, + 229CA40BADF357EDC88F7D08BAC54CB5 /* testutil.h in Headers */, + D86E06A60351F43DD7880CF935A31683 /* thread_annotations.h in Headers */, + F01A6B9A1243C34DA764908E9BC2552C /* two_level_iterator.h in Headers */, + EF16144559221600FFB4A709DA70DC09 /* version_edit.h in Headers */, + 0C3B9F787581B3D00B36863B40419CB5 /* version_set.h in Headers */, + 757A5DB44AB15400A4E91877C6192F27 /* windows_logger.h in Headers */, + FA42C8426D72EA20F0E1DCED5E79F2FF /* write_batch.h in Headers */, + 9BF494DE481214C27A18490564FA62F9 /* write_batch_internal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2C189050966085C04BC79FECBF29137A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 89BCC371F12999B9A8196A75146D76AD /* Pods-PediatricPancreasTests-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2D6D4C4F606C303B4DC6976367144DBE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + BA81227041AB29C9C59B46E2AD30CF5C /* APLevelDB.h in Headers */, + 865223A402543238B142F54E0CC704C1 /* FAckUserWrite.h in Headers */, + 2611134890F39153D53E85E22CC94D76 /* FArraySortedDictionary.h in Headers */, + 42542065ED59364C2DD90417D7157E7F /* FAtomicNumber.h in Headers */, + 0A396C7F83D1C18BCE1E32C9B0200B96 /* FAuthTokenProvider.h in Headers */, + EA3F2D65D8B8D3075E037ED5706AD660 /* fbase64.h in Headers */, + D37E73F03077BA5CFBC58965DDF89E80 /* FCacheNode.h in Headers */, + 4ED2955C86A5C26309952FF8FFC09569 /* FCachePolicy.h in Headers */, + 03F771627DD26DE3A46A3A0AA9238D96 /* FCancelEvent.h in Headers */, + F1CF64AB22A45DD7A4ACCF5B6D5CFAA5 /* FChange.h in Headers */, + A7CB993D569BC43F150B2DD794A57E76 /* FChildChangeAccumulator.h in Headers */, + FBDDD54632922897706042348C5264B0 /* FChildEventRegistration.h in Headers */, + A56FD686C400F83D7827CA2AE781F2F9 /* FChildrenNode.h in Headers */, + 877A82D57495B03675001EDD5F992FDA /* FClock.h in Headers */, + 335794B41F65E19C1872A69C350EA142 /* FCompleteChildSource.h in Headers */, + 04D9EEB121FAFA473B84577842DE28AA /* FCompoundHash.h in Headers */, + 9CD834F1AF935270B890BA341CA08CBB /* FCompoundWrite.h in Headers */, + 6CB0FB8CDEBA44EA97F54C01AC1D5EA3 /* FConnection.h in Headers */, + 1C2516CB0209BB6C75307C0FF8392883 /* FConstants.h in Headers */, + 167D0E24C4EB049C4651FD62969846AE /* FDataEvent.h in Headers */, + 087C55FF14BBD7924D2604E362E05E2B /* FEmptyNode.h in Headers */, + 6B4D5A61549502A1A5A033028F44FB03 /* FEvent.h in Headers */, + AE0E3346877C8D3DDAFE7CE8D0F595F5 /* FEventEmitter.h in Headers */, + BBC0AACCCDBBC8CA76718C2EE0E1E44A /* FEventGenerator.h in Headers */, + 2999DE7CB85A63BA6EAE75A0D6E7E701 /* FEventRaiser.h in Headers */, + BC71D66AA194EABC5188F55A969EDA43 /* FEventRegistration.h in Headers */, + 69D81130D8B7B9D7748BC1A9A8FD268D /* FImmutableSortedDictionary.h in Headers */, + 92FB390E9E6955EC5AA928ACBF8C78BD /* FImmutableSortedSet.h in Headers */, + 3AF47855221B8317A519B7089F5B7962 /* FImmutableTree.h in Headers */, + 8A4F0BDF204FDF791CEBC681038BEDC8 /* FIndex.h in Headers */, + 471980AEC51B1D14E068B57ACD4D5F04 /* FIndexedFilter.h in Headers */, + 3ABA3B497CD34014B40A742D3513F1AD /* FIndexedNode.h in Headers */, + B0A4CD547FC897EAF040F0BA4678CE52 /* FIRDatabase.h in Headers */, + 969AAAE7A07E4BF8FAF311DB24B9CCFA /* FIRDatabase_Private.h in Headers */, + 4C8DC5BA6AEFBABEAC2BA78ABD76C05E /* FIRDatabaseComponent.h in Headers */, + FC64278EBB2D553FA002035E06834E7C /* FIRDatabaseConfig.h in Headers */, + D6FB5EAE6DA7E3D7BA463BC4B50C9EC0 /* FIRDatabaseConfig_Private.h in Headers */, + E1DDF9D8AA9539216D0B192D480B0DF3 /* FIRDatabaseQuery.h in Headers */, + 82E23046F043EDDE41FF879C5E81CB2A /* FIRDatabaseQuery_Private.h in Headers */, + 509F33BADA937F1FA75BE86611E08911 /* FIRDatabaseReference.h in Headers */, + E986ED3BC90614CFA3534C6BA1058EA0 /* FIRDatabaseReference_Private.h in Headers */, + E35D6EFB453EB460D8A523FE4E0B3F38 /* FIRDataEventType.h in Headers */, + 9F0F8AAD6CCBE7182BF318ED1CA88F3F /* FIRDataSnapshot.h in Headers */, + 3714B6A3B2108658EDD63F97A6F25291 /* FIRDataSnapshot_Private.h in Headers */, + 8BFCA8C54D6CCCBA9C872CCFF9B2A6F8 /* FirebaseDatabase-umbrella.h in Headers */, + A3C87A043886D3BF5ACC8414B77771EE /* FirebaseDatabase.h in Headers */, + DF55CC21D55E0C4FCF28F49DA032AC4A /* FIRMutableData.h in Headers */, + 8CC21B72E7F7E7AFAF3E93DD08B5478B /* FIRMutableData_Private.h in Headers */, + 89DBDFDBC60677DB58E108B7E0FB80AA /* FIRNoopAuthTokenProvider.h in Headers */, + CC4509E5F4073C7ADBC9D40396CDA58B /* FIRRetryHelper.h in Headers */, + 9AD6029ED89AA028361A0A4A0DAF7E98 /* FIRServerValue.h in Headers */, + 6CB1633C99EB08C62B0EEBB2FCC37928 /* FIRTransactionResult.h in Headers */, + 2435103B6E32D5B5A5E612755C06DCCE /* FIRTransactionResult_Private.h in Headers */, + 53CECFA59A5B245E70074845D4780B9E /* FKeepSyncedEventRegistration.h in Headers */, + B54AAF339502800C6F39457FE3960E31 /* FKeyIndex.h in Headers */, + 59C1A5BCD90F5014BB332BE28207B49E /* FLeafNode.h in Headers */, + 3E402733BBC6CB51F219ACA5C74ACAFC /* FLevelDBStorageEngine.h in Headers */, + 03F01BC83070ABBD518F5AA17D4DCB40 /* FLimitedFilter.h in Headers */, + 604A6E676D3E9F0B60D498B29087440F /* FListenComplete.h in Headers */, + 5D574DE590E3828C62C092888E7BD04E /* FListenProvider.h in Headers */, + 62BC8EE3772D71C39FB6F17E0C02FDB5 /* FLLRBEmptyNode.h in Headers */, + 3C2CAC2C64AC199613434D9712AB67CD /* FLLRBNode.h in Headers */, + AFEDA85C2ACE6902C5CA86036E2D1B20 /* FLLRBValueNode.h in Headers */, + BE896A5DDFD39DBEEDE89C02C6D2E4FC /* FMaxNode.h in Headers */, + 0BFBD5419A81C51C524FE08FC0E3F3EE /* FMerge.h in Headers */, + 00EDAEC0ECFF39FEC894E3A5CD68E307 /* FNamedNode.h in Headers */, + 845714625E3473FE314FFC542B720ACE /* FNextPushId.h in Headers */, + 6916DB010C26CB84795B779931BCC477 /* FNode.h in Headers */, + 869817FC3DE2BAA4B7A06F2BD17137D6 /* FNodeFilter.h in Headers */, + 0DA6A4EBE519B3DE88E0E007577BDAE8 /* FOperation.h in Headers */, + FC59BACAD99E5424954E9281DCDEB028 /* FOperationSource.h in Headers */, + 6F318885B392F65A5B1ABE15D11E5E54 /* FOverwrite.h in Headers */, + 772DE42A9C5A47247E8D29118F0F1618 /* FParsedUrl.h in Headers */, + 6DC14A98DA70552D1F41941379E1C12F /* FPath.h in Headers */, + 4E2B9CC4DC53413EFD971C628FEBC58B /* FPathIndex.h in Headers */, + E3C9B29A2D69D6BABC0CA201BD468665 /* FPendingPut.h in Headers */, + 04FCBCEA9CCA44E9E2F7122847E00864 /* FPersistenceManager.h in Headers */, + 48279784E05FCDAA6A1AC5FDD4BC5EE4 /* FPersistentConnection.h in Headers */, + ECDE82202A3862051B9B7CB6D5B4E3FC /* FPriorityIndex.h in Headers */, + 7F170BA72C35DCF119134104398EFB11 /* FPruneForest.h in Headers */, + 942656920C39F8D9A85B8BBFE965446D /* FQueryParams.h in Headers */, + DE5F44DAECF248CE9C781B2C1E462F75 /* FQuerySpec.h in Headers */, + EE676F7DB6F01DF5BB726B0B49B09D60 /* FRangedFilter.h in Headers */, + DD0D2B219445705DFFEC30E53B90CE3B /* FRangeMerge.h in Headers */, + 448F087F0DC22F891D5C3815CD4FD089 /* FRepo.h in Headers */, + A6801ADAA631C909DB0EF52A19E3A2D9 /* FRepo_Private.h in Headers */, + 42A4E95D960E07E9141C6ADE411F9B59 /* FRepoInfo.h in Headers */, + FCAD17281B08C0CAEF51C89DFF306766 /* FRepoManager.h in Headers */, + 92016BDC3C9C896AA3455626CA5FF37F /* FServerValues.h in Headers */, + A197A576946A28350D93810CA9590805 /* FSnapshotHolder.h in Headers */, + FBF07D649518FB33E6E57ED937D4138A /* FSnapshotUtilities.h in Headers */, + 79C2937BB9C843004E552AC86CA18351 /* FSparseSnapshotTree.h in Headers */, + D8AB4C4B61FB111307EEC525C7BA7083 /* FSRWebSocket.h in Headers */, + 46DB3B00C18339C9001A96947F8354CD /* FStorageEngine.h in Headers */, + 6573DD72CD06404672E18390A2602965 /* FStringUtilities.h in Headers */, + E9EF5B931F4D833CB15D9211E4AA2D50 /* FSyncPoint.h in Headers */, + 5597DEC5A26E41DDC9AD5B0C63F30822 /* FSyncTree.h in Headers */, + 0BFFFE564365C57BC41A964ECB45931F /* FTrackedQuery.h in Headers */, + E6EF7C214F730588B9E93A2C319AC9E4 /* FTrackedQueryManager.h in Headers */, + 2C3B184BED83E687B4532E6E142BB9F0 /* FTransformedEnumerator.h in Headers */, + EB3720D59974F576ADCF3449D97795D6 /* FTree.h in Headers */, + 8A20C3885DBB6729AB0D563A850B471F /* FTreeNode.h in Headers */, + 40E5F48D173FC8A5A47F91D1BCFC7A6B /* FTreeSortedDictionary.h in Headers */, + 86CFAC06AA8D34293212722D18F00D06 /* FTreeSortedDictionaryEnumerator.h in Headers */, + D9800CEE2FBF66C326E6E78A90A84EDB /* FTupleBoolBlock.h in Headers */, + F171CCA20D1D69E03EB49FFBD519238C /* FTupleCallbackStatus.h in Headers */, + BC94EE9013468F13B1EFC548E5C02FA1 /* FTupleFirebase.h in Headers */, + 599FED6060274B5F71E088500A84E5B5 /* FTupleNodePath.h in Headers */, + CF6AC92992AA1428D74B4A4A98B5F17B /* FTupleObjectNode.h in Headers */, + B19F4223C39993C7275EE555162E2180 /* FTupleObjects.h in Headers */, + DADF5C8F6686404E5C704C8B0B154B70 /* FTupleOnDisconnect.h in Headers */, + A231C3D11FEFF60FB796E0318CBD27E0 /* FTuplePathValue.h in Headers */, + 232462B42CFB86A76B2E3EF883CCBB96 /* FTupleRemovedQueriesEvents.h in Headers */, + 38EDCB6B0C1491BC14B16B4E986DA00E /* FTupleSetIdPath.h in Headers */, + 06F8B2D110E3D85C99D7694C88D4AACC /* FTupleStringNode.h in Headers */, + 32A9C57D813527201AB8236B8151591D /* FTupleTransaction.h in Headers */, + 11D6258E24BA267419F96E4515902AC1 /* FTupleTSN.h in Headers */, + 061AD4AFD8DA76779BFEAF73508E47D7 /* FTupleUserCallback.h in Headers */, + 4EF25A23AD2C3121B8FAC312055528F4 /* FTypedefs.h in Headers */, + 4FC706C02447823974080F724C244754 /* FTypedefs_Private.h in Headers */, + 5393FECDEA4955E523BDAFFD9ED07EBC /* FUtilities.h in Headers */, + 469B9DA599A5FCC6C177A5D471627099 /* FValidation.h in Headers */, + 0A91224F2F6B47A058CB360227247938 /* FValueEventRegistration.h in Headers */, + 4CB86817A316CD4A9F3EAE62FB4ACB96 /* FValueIndex.h in Headers */, + DE2CFDFAE25548213B8540ED406A1120 /* FView.h in Headers */, + 9F88ED341CFE6C501D0524C0BB885C36 /* FViewCache.h in Headers */, + 49FA9CFB7506743456F5027040F01EEA /* FViewProcessor.h in Headers */, + 0A01FF0884FAF5689C189235DFDEE9F3 /* FViewProcessorResult.h in Headers */, + 977A2BDF4E2F55BEE8A7D29E094FD6E0 /* FWebSocketConnection.h in Headers */, + 06186994A01F0DCBC0552F2CF8F875A4 /* FWriteRecord.h in Headers */, + 9EE47330FA51209EC3AB5B386B301E09 /* FWriteTree.h in Headers */, + F099CB27DAFA4893909B6955263235EA /* FWriteTreeRef.h in Headers */, + B51FE96C5980296027D229A6080E3FC2 /* NSData+SRB64Additions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3771B2C7C6856B3430625D5A8A37E18B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 282A2B1557E034CC4DDBBB528FBA6D9D /* nanopb-umbrella.h in Headers */, + 102A0195119AFFB4140DEE02B986A551 /* pb.h in Headers */, + 0E0145B2EAB107CE51DB7AC3B81888B5 /* pb_common.h in Headers */, + 732320404F09A7A234C0554FE5C1AACC /* pb_decode.h in Headers */, + CD1F27DA93DD3248CCD6D4C074F00F0B /* pb_encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3CFDE4E3DB3E5ECC4F507D5112BCFC66 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + AB973E87F1C50F9A44CE2391340CFB8D /* FirebaseInstanceID-umbrella.h in Headers */, + 895587832DCDA70BF99226F5EFDF6168 /* FirebaseInstanceID.h in Headers */, + A2FE22471CDC277C80E9BB61C6FF513B /* FIRIMessageCode.h in Headers */, + D0F5342589821DF33F6A14D99A906CCE /* FIRInstanceID+Private.h in Headers */, + 50553464F21122B6CE26E8360F3CEE0E /* FIRInstanceID.h in Headers */, + 622B3C041AD5D25276A5D9B283DC0323 /* FIRInstanceID_Private.h in Headers */, + 864152069263E017EFA1C9E1E24148E4 /* FIRInstanceIDAPNSInfo.h in Headers */, + C41A7FDD9E0A7FE8D6CA954594939E00 /* FIRInstanceIDAuthKeyChain.h in Headers */, + 725187D3F8C64CAB2CE5CBC0213D8318 /* FIRInstanceIDAuthService.h in Headers */, + 7B77E6A110A4E9545928F520B380CFC5 /* FIRInstanceIDBackupExcludedPlist.h in Headers */, + 3BC2C5DFB1D965CA2DD0DC4D72405FE9 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */, + 3108F662E409C22082872D0CF11C5385 /* FIRInstanceIDCheckinPreferences.h in Headers */, + E4E7BA8B1B6890D1F626D48424D6AE38 /* FIRInstanceIDCheckinPreferences_Private.h in Headers */, + 6D93687073718546736A98A061859937 /* FIRInstanceIDCheckinService.h in Headers */, + 6517CD45A16C90958AD60CEC2F40D4C4 /* FIRInstanceIDCheckinStore.h in Headers */, + 503446234DE2F6A868F2A1C33A87AC29 /* FIRInstanceIDCombinedHandler.h in Headers */, + 8AA6733A89BB718EF7A4AF3F9C55BAD3 /* FIRInstanceIDConstants.h in Headers */, + FA0C467B67A198087FB902188804E853 /* FIRInstanceIDDefines.h in Headers */, + 1352B4E082BF49B40EBB0C5931EE9A92 /* FIRInstanceIDKeychain.h in Headers */, + B5DFE329CADA639BF99EC0E61E8F36D9 /* FIRInstanceIDLogger.h in Headers */, + 579867C7A940E08AE0EBD5A014F14763 /* FIRInstanceIDStore.h in Headers */, + 625277FA73B61F7DE91BCE4481C32E9F /* FIRInstanceIDStringEncoding.h in Headers */, + 91A48DACCC1B2FE301525CF24EC7693C /* FIRInstanceIDTokenDeleteOperation.h in Headers */, + 50A9A9634C01403BBD8F48F6F860DD23 /* FIRInstanceIDTokenFetchOperation.h in Headers */, + F2A624FF84956172105446D07DE074FF /* FIRInstanceIDTokenInfo.h in Headers */, + 3CBB2887C1CF4A11343EE9B17F2A8FF2 /* FIRInstanceIDTokenManager.h in Headers */, + D8AB19E0518BB4BC5276C2DF9357E982 /* FIRInstanceIDTokenOperation+Private.h in Headers */, + BA6597B1BC8ACF9295CE01AFCF4C7F7B /* FIRInstanceIDTokenOperation.h in Headers */, + 0647A006023CF684A264CDD07D28FA91 /* FIRInstanceIDTokenStore.h in Headers */, + F1C0B322C183AE921828174D35466A4A /* FIRInstanceIDURLQueryItem.h in Headers */, + 78E6638048B07AFD81DC7CDAACAE5B64 /* FIRInstanceIDUtilities.h in Headers */, + 5E34D8191F84A951DD68BAB0CA7DBECA /* FIRInstanceIDVersionUtilities.h in Headers */, + AB21722890ECFBC7FEAACA77CCAAB134 /* NSError+FIRInstanceID.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4AA3C5F40045B8CEF70020E4BD927F2E /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 316AF39205CFD0A9865FC10D4C3B30E5 /* GoogleUtilities-umbrella.h in Headers */, + 61F58417D58890BB6F2020D13F704CC9 /* GULAppDelegateSwizzler.h in Headers */, + 9A979CE5E7B5CC50A899C7806E6CA50D /* GULAppDelegateSwizzler_Private.h in Headers */, + CF7797BD4D4295C41355DA0C8E13A118 /* GULAppEnvironmentUtil.h in Headers */, + 0537BB4CC2A926C9541D222B9AC3924C /* GULApplication.h in Headers */, + BFA8341CD1440D5ADBD440B26C8076B9 /* GULHeartbeatDateStorage.h in Headers */, + F5BD8C8AD011B82A642571F8C2704EE1 /* GULLogger.h in Headers */, + 826630E04AD591A0443002398BEA5516 /* GULLoggerCodes.h in Headers */, + BE63D66EDC0CF985AADC754E638E1B27 /* GULLoggerLevel.h in Headers */, + 4BC329728DAA96B1C5CC084201689945 /* GULMutableDictionary.h in Headers */, + 6F0A67A608E04456C0B5030EE47172D4 /* GULNetwork.h in Headers */, + 0B6FF9ED432353167CCE5CAFEBB59A6E /* GULNetworkConstants.h in Headers */, + 16C02EC101DCB7C2DC5E0F60CE1829CB /* GULNetworkLoggerProtocol.h in Headers */, + 5B9FFC2E882ACF13D5495485653E9E75 /* GULNetworkMessageCode.h in Headers */, + A00CA354751C5B824D1C4FBC48A46DE0 /* GULNetworkURLSession.h in Headers */, + 7DAE8BCE3F5F06E3C2A5D0DBBC0C9AC2 /* GULNSData+zlib.h in Headers */, + 28FCD20369581072CB088A4F39A0A325 /* GULOriginalIMPConvenienceMacros.h in Headers */, + 9A75B070DA97F71D65FD8CA829F04E2B /* GULReachabilityChecker+Internal.h in Headers */, + 5CB4D9C34075C194E6F4ED76E1B7D927 /* GULReachabilityChecker.h in Headers */, + B694024900B3873914C9B5BECA4F2FCC /* GULReachabilityMessageCode.h in Headers */, + 7A4194F77634B66169BD29A13A685D42 /* GULSceneDelegateSwizzler.h in Headers */, + E7F131F127CAC8569841468FF5899DB5 /* GULSceneDelegateSwizzler_Private.h in Headers */, + B120EB6E9B4AAF6673812E04509CC24F /* GULSecureCoding.h in Headers */, + 37745085A5593D67CC5D9610EDE79FD1 /* GULSwizzler.h in Headers */, + 9EC476993DA7B5AB5152043817A315FD /* GULUserDefaults.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A655C7C2A632841CA923433D1E961F0B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2571C011C254F39E5677463DF34E0C06 /* cct.nanopb.h in Headers */, + 562A21D201918AC5858CFC82E8DB7C91 /* GDTCCTCompressionHelper.h in Headers */, + 8A3B53C1CA2FBA6587E34180D670BC9D /* GDTCCTNanopbHelpers.h in Headers */, + 775DC12DA620A40118722073684E911E /* GDTCCTPrioritizer.h in Headers */, + 2AE7E02AC0A6367CBE71A89850AAB78A /* GDTCCTUploader.h in Headers */, + E6C65AF381AE066080720D0D04A3F5EC /* GoogleDataTransportCCTSupport-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B94FB19024C83F7896D6ED48757500B4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + E23D13EB8979456AE2CA5809A28CA6D5 /* firebasecore.nanopb.h in Headers */, + D6B9D7A2DFA77050AD5CFF09CFFE75FA /* FirebaseCoreDiagnostics-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CC0DEACA903F7867FE86AD607FC6E761 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C6E929AEA67F66FD713B496EE2CBE64 /* FirebaseInstallations-umbrella.h in Headers */, + C77963B29BF253A51295B5759F0FEC3F /* FirebaseInstallations.h in Headers */, + A138F5766F60A8D08498D9E4C6183523 /* FIRInstallations.h in Headers */, + 9ADC7DFCBEA7BB3394E5F9157191C54F /* FIRInstallationsAPIService.h in Headers */, + 6670C57E9946D6F6E1E4261CEC4CFA73 /* FIRInstallationsAuthTokenResult.h in Headers */, + CF503615323A99589846E4E202EDC060 /* FIRInstallationsAuthTokenResultInternal.h in Headers */, + 458166723E07E34E95EC91DC422D2DFA /* FIRInstallationsErrors.h in Headers */, + 5B77D1E30B25C23CF4E6FF171ACCB2A6 /* FIRInstallationsErrorUtil.h in Headers */, + FF313F9C558D47363F41404E308713E1 /* FIRInstallationsHTTPError.h in Headers */, + 60734CF9B2C36DF651BFE9BD86BFDB5F /* FIRInstallationsIDController.h in Headers */, + A6102533A842F7FCF889738B18425940 /* FIRInstallationsIIDStore.h in Headers */, + FEF0C471E46E7016F356300F587C60C6 /* FIRInstallationsIIDTokenStore.h in Headers */, + A6B67E9EB789DEE46ADB74C10AFB81CF /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */, + 3C3238DC28C8CCC7E0E17A3772F13BD5 /* FIRInstallationsItem.h in Headers */, + EC1982A7AFA80D6175FBDF2F2B5510A9 /* FIRInstallationsKeychainUtils.h in Headers */, + A11271539C8A49D53324308D5D29867F /* FIRInstallationsLogger.h in Headers */, + 81BFE9029052A2492D6B7215EE10E58A /* FIRInstallationsSingleOperationPromiseCache.h in Headers */, + 32B07380C1AAF5AF6D51208E94E877E7 /* FIRInstallationsStatus.h in Headers */, + 9DEF1AE276B2DD9342452E37582698D0 /* FIRInstallationsStore.h in Headers */, + 5C3CCE52E087B4B8E603FA64DAF9DA73 /* FIRInstallationsStoredAuthToken.h in Headers */, + 610DAA599D1DF02C373356724FD8A5E8 /* FIRInstallationsStoredItem.h in Headers */, + 5E0C75B90D56AF1C6F39D808DC7778A7 /* FIRInstallationsVersion.h in Headers */, + 8A5EA394F778ED3582918A9CC6E81C8C /* FIRSecureStorage.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DDD38D8C27A238EEB4BBFC648C9A37AA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2C8F1F07505A5559AFEC2E38754B9029 /* GDTCORAssert.h in Headers */, + 4B7F0184DD074841956989FF999155F3 /* GDTCORClock.h in Headers */, + 29C166E258DF103E2740944FF34B37A0 /* GDTCORConsoleLogger.h in Headers */, + 9009D8B79DE9849F5B0C2EB6773416C4 /* GDTCORDataFuture.h in Headers */, + AD40351A186EDE06359FE72DE397299A /* GDTCOREvent.h in Headers */, + 54AC263C74BDE2D01365DDA2CAFA46B0 /* GDTCOREvent_Private.h in Headers */, + B59BF3BADBD587B5AF03B45B57BA926A /* GDTCOREventDataObject.h in Headers */, + 760D02A90FD244628BDF690A02428E16 /* GDTCOREventTransformer.h in Headers */, + 1692463D9972897A8CF0552FC3BB787B /* GDTCORLifecycle.h in Headers */, + A4D5CFED4998E8124647922CA2F6045A /* GDTCORPlatform.h in Headers */, + 54C7E3021017AF76BDE7BC5DEC678DBD /* GDTCORPrioritizer.h in Headers */, + DDC5BA7722D5AA379459704FBBE3513E /* GDTCORReachability.h in Headers */, + 28A0A9FD9BC4B00D1705BC37EF081DEE /* GDTCORReachability_Private.h in Headers */, + EC42C06469C51FF4C436869FC638A270 /* GDTCORRegistrar.h in Headers */, + AA3BB18CA32179B9E3D0332754DA6FD7 /* GDTCORRegistrar_Private.h in Headers */, + 91FFE8F13D0A292915F7DBEB0C1725C5 /* GDTCORStorage.h in Headers */, + D0798123D484EA3D9DD80C21DE672FB3 /* GDTCORStorage_Private.h in Headers */, + 3440F277E50EEF9650620F3FA2671DAB /* GDTCORStoredEvent.h in Headers */, + 6D93BE021B3BB3E5085568DA6B00C125 /* GDTCORTargets.h in Headers */, + 99BD4AA0965DFAEB48961EED629EBBAB /* GDTCORTransformer.h in Headers */, + BFFAA2BE866BF90941ABEA5E71037B9B /* GDTCORTransformer_Private.h in Headers */, + 9E11ECDE24EA28C39FF20042B69C3738 /* GDTCORTransport.h in Headers */, + 53059A83D1093C0526B67908130488CD /* GDTCORTransport_Private.h in Headers */, + 4855B819ACCD8E101955F99EC1A255E1 /* GDTCORUploadCoordinator.h in Headers */, + 866D20297FA8631B5FF700CB55A9F6AB /* GDTCORUploader.h in Headers */, + 737E8608EC1F9E6A3E60E465EFB49494 /* GDTCORUploadPackage.h in Headers */, + BEB2433EE42F253066747816CE237BBB /* GDTCORUploadPackage_Private.h in Headers */, + A1420741FBF706E542E2EC84D19D0938 /* GoogleDataTransport-umbrella.h in Headers */, + CA49350D90B4A272890D567E817134A1 /* GoogleDataTransport.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDF382F8357240550C86EF3CB0A16985 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 65239E2753AB78105DA3B5E7354FEAA0 /* Pods-PediatricPancreas-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */ = { + isa = PBXNativeTarget; + buildConfigurationList = 43C26ABBE9DC4E233EC8499C10B70042 /* Build configuration list for PBXNativeTarget "PromisesObjC" */; + buildPhases = ( + 12ED1C5EBF526EEC00EDD3169D857A4C /* Headers */, + 90341189EAFB3E7577366457746B55C4 /* Copy . Private Headers */, + A3D1FF1B28B92965F930693E26704E92 /* Copy . Public Headers */, + 2E49770D9B170D53DC3F65488AA72C6B /* Sources */, + 7D3A22040002E8F97398A6954D9F003A /* Frameworks */, + C2F99A84E419FF78D862AFD3A5300816 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PromisesObjC; + productName = PromisesObjC; + productReference = 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */; + productType = "com.apple.product-type.framework"; + }; + 3105BA8C83A060B69BAE853EA4E8C340 /* Pods-PediatricPancreasTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F6D83BB6092005AFC8CB075E28930EB7 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreasTests" */; + buildPhases = ( + 2C189050966085C04BC79FECBF29137A /* Headers */, + 4585E1157BA71EE219BC8F11323324ED /* Sources */, + 78D3FDA7EDCAD3EC546D3EC67A071821 /* Frameworks */, + F1C994B1ABDBCC50C4F87FCD22AFF949 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CDD8708FF4BC6CF44914BADDAA1051F5 /* PBXTargetDependency */, + ); + name = "Pods-PediatricPancreasTests"; + productName = "Pods-PediatricPancreasTests"; + productReference = FE000DCA7D5E753082D9590F1EAC1696 /* Pods_PediatricPancreasTests.framework */; + productType = "com.apple.product-type.framework"; + }; + 35259CB2578AACC9EB0E8EEC58935820 /* Pods-PediatricPancreas-PediatricPancreasUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A50DCC391E886E3336A6977292720DE7 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas-PediatricPancreasUITests" */; + buildPhases = ( + 242D284DC38937970FCA29C675FACF6C /* Headers */, + D8390D070FFC7E4E4271928DE78B6495 /* Sources */, + C78B2CE08206D9277C54EDF7D9C1B12D /* Frameworks */, + 1FDDAA6809B47FFC3B4FA17C07BBB4E0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 16F3D58024BB21F695935DA0DAD2B792 /* PBXTargetDependency */, + 82BB54BD09FD3492EDC3EAB7F8319744 /* PBXTargetDependency */, + FDA6E390AD4A330B2C0D716D0A79D59B /* PBXTargetDependency */, + D6B0A0F91F5F385BF853F0F370DEBD0D /* PBXTargetDependency */, + B655229A63479803B5798F6F4862E720 /* PBXTargetDependency */, + 1A735670E932913B3739B130B29BCEFE /* PBXTargetDependency */, + 45F353EC09C313F0B5A9631BCF1604B0 /* PBXTargetDependency */, + 94E625C0654FD5965D513AB143010125 /* PBXTargetDependency */, + 62305F374C4C5059DBD1483A3323EDA8 /* PBXTargetDependency */, + C08C781D810593A2CE1E56C6FC06400D /* PBXTargetDependency */, + 769F7393D871F666672BE9EB5FDFE138 /* PBXTargetDependency */, + 9156E284938A0D0BE126C93F73CBC909 /* PBXTargetDependency */, + D380A2798F3887C211368F99B7C367DA /* PBXTargetDependency */, + 3C1E541454C9B47A74B5B7C7E0C9CB1C /* PBXTargetDependency */, + B3FBD5800B1E0144A1F5F1D6D4FEE80D /* PBXTargetDependency */, + 5F2DAB5DD876EFF04AB33FEDDC642C76 /* PBXTargetDependency */, + ); + name = "Pods-PediatricPancreas-PediatricPancreasUITests"; + productName = "Pods-PediatricPancreas-PediatricPancreasUITests"; + productReference = 5552D0C170F2A442665A8F97BB64E4F0 /* Pods_PediatricPancreas_PediatricPancreasUITests.framework */; + productType = "com.apple.product-type.framework"; + }; + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = B689081FB906519ACAD19D7FC6F23A92 /* Build configuration list for PBXNativeTarget "FirebaseCore" */; + buildPhases = ( + 0B999D039D6C059647B762E2231AB32B /* Headers */, + EEA8947D055418381BDA26E78B4577A3 /* Sources */, + F46A0EDAAA4E82EDBC0DB972F383AB30 /* Frameworks */, + 16B602477B60700805DD009DE8994B35 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6FBF1497BBA407FB369A0DD22CCD5566 /* PBXTargetDependency */, + 91A2F9949849A92A1C71E53754F9CD74 /* PBXTargetDependency */, + 80502E36CF51F684EE9239228201D901 /* PBXTargetDependency */, + ); + name = FirebaseCore; + productName = FirebaseCore; + productReference = E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8744A71516AEF576C6D6958B54BBDFB5 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */; + buildPhases = ( + DDD38D8C27A238EEB4BBFC648C9A37AA /* Headers */, + A2FB996CF2FA483BE84681914240B7FD /* Sources */, + 5802FFE25E6DDADD18C579CB17F03F14 /* Frameworks */, + 60CCCDED749690A0BF4A07D16D3525F2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleDataTransport; + productName = GoogleDataTransport; + productReference = 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */; + productType = "com.apple.product-type.framework"; + }; + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */ = { + isa = PBXNativeTarget; + buildConfigurationList = 58E94B7FB6E0686AD93AF7BC1156F389 /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */; + buildPhases = ( + B94FB19024C83F7896D6ED48757500B4 /* Headers */, + F5DF007BAA1C39039238B8500939188D /* Sources */, + 4303B8E8FA98891B596CE8DCC3372E19 /* Frameworks */, + B3D2E5E0A367A5DE3387497D04A37C46 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 3FAF8BC099B914107FD7729D8CC3FBFE /* PBXTargetDependency */, + 1E5AC8537F4CE552884E6905FABFE1DF /* PBXTargetDependency */, + 2DE901163BC34DE7855D4423B689D7CD /* PBXTargetDependency */, + 9F65DEC27AA4C81FF09CF5E514792B9C /* PBXTargetDependency */, + ); + name = FirebaseCoreDiagnostics; + productName = FirebaseCoreDiagnostics; + productReference = 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */; + productType = "com.apple.product-type.framework"; + }; + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */ = { + isa = PBXNativeTarget; + buildConfigurationList = CE7EDF042F1D503B96A8DFFD05267C70 /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */; + buildPhases = ( + 2D6D4C4F606C303B4DC6976367144DBE /* Headers */, + 092903E837A60E3B1B40C22FBA50FE0B /* Sources */, + B7D024CD4C070FA492DF42423B9C36C6 /* Frameworks */, + 15D8850E6779AB4584AB8DC01D323E4E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0D2C6E7B9AB0ACA41D4DC7E4D79F0CF9 /* PBXTargetDependency */, + 4BDD54DE84523FD142113987337A776F /* PBXTargetDependency */, + 7F7F948B21FE240EDC29385EBEF9183A /* PBXTargetDependency */, + ); + name = FirebaseDatabase; + productName = FirebaseDatabase; + productReference = 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */; + productType = "com.apple.product-type.framework"; + }; + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */ = { + isa = PBXNativeTarget; + buildConfigurationList = C1983DB33A942214A80E06F4A2BC9CB4 /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */; + buildPhases = ( + CC0DEACA903F7867FE86AD607FC6E761 /* Headers */, + 99C3DE4D60FE4A4C8A54E45359FCEB05 /* Sources */, + 1C1298073446E5DEF7DB06E81CCE934F /* Frameworks */, + B554F6214E08CF2F2A68A6A6F9CFA213 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 77F88BF4D201EEB058A96EE26A885132 /* PBXTargetDependency */, + 5DBC369ABE0DE46E6B294739601C4B85 /* PBXTargetDependency */, + 85F8C10667F91A5415950BFB7DF60B2B /* PBXTargetDependency */, + ); + name = FirebaseInstallations; + productName = FirebaseInstallations; + productReference = 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */; + productType = "com.apple.product-type.framework"; + }; + 8A7E9E78EB0B7B5A38DBA30283079B9F /* Pods-PediatricPancreas */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0D60FBF4A3563D9B9A8626B8486F1347 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas" */; + buildPhases = ( + FDF382F8357240550C86EF3CB0A16985 /* Headers */, + CA0F94698E18CAAB9042A56581D002FD /* Sources */, + 65510BFAC5CC2ED301641328162277E3 /* Frameworks */, + 891F3ED9152AAACE0554726A9B7AE37C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 24D4748F270241EEFDA258DAF729D027 /* PBXTargetDependency */, + BDE7CB53A57C718C77AA8C14C2DFDA79 /* PBXTargetDependency */, + 05D842E53602BB1DF432DBCC2ABA3372 /* PBXTargetDependency */, + C45C2EC7764643102CE493AF6ABFF69E /* PBXTargetDependency */, + 5E2D75CF712A30AD19D02CFBA9609541 /* PBXTargetDependency */, + EBDB50EA5915A344EDCF79B88DE2C310 /* PBXTargetDependency */, + A1543F036F8DA36656A816076F259FCA /* PBXTargetDependency */, + DDC522A4C9D21A8D07AC77910A400385 /* PBXTargetDependency */, + 7EDA800ED0C497BB44B2FE613941C4F0 /* PBXTargetDependency */, + 176EEFB0452E4F5CE51548153C88EDAA /* PBXTargetDependency */, + C07CCD661BB0EC97B07D537842981A2E /* PBXTargetDependency */, + EB05FCC745537DDC437B3B6B9C591FED /* PBXTargetDependency */, + E0E18C912765D2D0ACE9275EB93FE611 /* PBXTargetDependency */, + 74442856B39755028E7EB80C418347BA /* PBXTargetDependency */, + 5459331521249E216D6EE546528473AA /* PBXTargetDependency */, + 7873705F7362CB707D163F2F5C6F1C25 /* PBXTargetDependency */, + ); + name = "Pods-PediatricPancreas"; + productName = "Pods-PediatricPancreas"; + productReference = 2C86C31F45C132250286638F6D488663 /* Pods_PediatricPancreas.framework */; + productType = "com.apple.product-type.framework"; + }; + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5889EFDAC639033660B767DFB79C0B17 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */; + buildPhases = ( + 4AA3C5F40045B8CEF70020E4BD927F2E /* Headers */, + 19DD17E85A44DEC061B80F617A5026BC /* Sources */, + DB0EC5A1ADE5082A47339C126D970A82 /* Frameworks */, + 59B8C42A6615BE2B1271BF7FBCDF5DF9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleUtilities; + productName = GoogleUtilities; + productReference = B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */; + productType = "com.apple.product-type.framework"; + }; + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2ED8A72DB7F84BD892A32A461B4808A5 /* Build configuration list for PBXNativeTarget "leveldb-library" */; + buildPhases = ( + 246D170714300284136B606F8C814022 /* Headers */, + 220FDCEB2CE1D6759A3A2F61F5448C1F /* Sources */, + 7BA7500DBB489DEFDD7CC1FAE6073065 /* Frameworks */, + 25ADC29A7A650A29DEF02D589631C248 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "leveldb-library"; + productName = "leveldb-library"; + productReference = 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */; + productType = "com.apple.product-type.framework"; + }; + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */ = { + isa = PBXNativeTarget; + buildConfigurationList = F362EAC4ECF0734220A524D18E1E841C /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */; + buildPhases = ( + 3CFDE4E3DB3E5ECC4F507D5112BCFC66 /* Headers */, + 16575CAD34F48EF3D7DFECF12D56CBA5 /* Sources */, + 976E51A906BC5FF2EF5F3F9150364146 /* Frameworks */, + EA9676208E4AA61F34AE72955A52849B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4D89E1C759D45D05758FB69B690BA072 /* PBXTargetDependency */, + 0E8A25403333F0205E16BFEC267DB922 /* PBXTargetDependency */, + FDF91132B921A52CB4F146E1625A615A /* PBXTargetDependency */, + ); + name = FirebaseInstanceID; + productName = FirebaseInstanceID; + productReference = 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */; + productType = "com.apple.product-type.framework"; + }; + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */ = { + isa = PBXNativeTarget; + buildConfigurationList = E65B70641EE44AF0CCBD0B75C656BACF /* Build configuration list for PBXNativeTarget "nanopb" */; + buildPhases = ( + 3771B2C7C6856B3430625D5A8A37E18B /* Headers */, + B700E84A73D9A81FD6EFF378D4861A9B /* Sources */, + 6746E84F116799083DDDD3D615E81F17 /* Frameworks */, + E60D3E06DE4CB97539E847CF26265A23 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = nanopb; + productName = nanopb; + productReference = 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */; + productType = "com.apple.product-type.framework"; + }; + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4354311CC4C1FA1C205834FC9996237 /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */; + buildPhases = ( + A655C7C2A632841CA923433D1E961F0B /* Headers */, + 6F3A3D6AD1E42EE428CD03BE69DFFCA6 /* Sources */, + C632C1FE3CF19809F363112B57451E42 /* Frameworks */, + 7EFBC0609C60F5631774E91252E4ADA4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 98EC313982438CDA09DBA1872B7C3374 /* PBXTargetDependency */, + 982CB806C0927639A0756C623361FB86 /* PBXTargetDependency */, + ); + name = GoogleDataTransportCCTSupport; + productName = GoogleDataTransportCCTSupport; + productReference = 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = 905F6F16733327C28C57190B7AC788EA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */, + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */, + 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */, + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */, + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */, + 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */, + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */, + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */, + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */, + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */, + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */, + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */, + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */, + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */, + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */, + 8A7E9E78EB0B7B5A38DBA30283079B9F /* Pods-PediatricPancreas */, + 35259CB2578AACC9EB0E8EEC58935820 /* Pods-PediatricPancreas-PediatricPancreasUITests */, + 3105BA8C83A060B69BAE853EA4E8C340 /* Pods-PediatricPancreasTests */, + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 15D8850E6779AB4584AB8DC01D323E4E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 16B602477B60700805DD009DE8994B35 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1FDDAA6809B47FFC3B4FA17C07BBB4E0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 25ADC29A7A650A29DEF02D589631C248 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 59B8C42A6615BE2B1271BF7FBCDF5DF9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 60CCCDED749690A0BF4A07D16D3525F2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7EFBC0609C60F5631774E91252E4ADA4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 891F3ED9152AAACE0554726A9B7AE37C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B3D2E5E0A367A5DE3387497D04A37C46 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B554F6214E08CF2F2A68A6A6F9CFA213 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2F99A84E419FF78D862AFD3A5300816 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E60D3E06DE4CB97539E847CF26265A23 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EA9676208E4AA61F34AE72955A52849B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F1C994B1ABDBCC50C4F87FCD22AFF949 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 092903E837A60E3B1B40C22FBA50FE0B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 47F57B37033CB9AE138264B78F352789 /* APLevelDB.mm in Sources */, + 7317B7F1DFE34E13DD05E12C850C8E07 /* FAckUserWrite.m in Sources */, + 3A8E7FC71B4E275869756EBC863BAE05 /* FArraySortedDictionary.m in Sources */, + 965459A010FB7FD56029C223E54F3AF5 /* FAtomicNumber.m in Sources */, + 72E7BB1C714620C56A727A1A738E407E /* FAuthTokenProvider.m in Sources */, + 453D09C210A62983622D9B3033351E47 /* fbase64.c in Sources */, + 7284B96124EB53659E5A38AB5BFD20F7 /* FCacheNode.m in Sources */, + 23CD4E9048AE540E63359773CD360CA2 /* FCachePolicy.m in Sources */, + 1E7F350E9A6AA211C53A28F58D22A9F7 /* FCancelEvent.m in Sources */, + A21B19FCB0DFABCE9E33BC8C108708F5 /* FChange.m in Sources */, + ACEE8B9AF12952DFE6883AD1524E1B95 /* FChildChangeAccumulator.m in Sources */, + 50ECA21E528DB9D880C7ACABDED9A9F0 /* FChildEventRegistration.m in Sources */, + 6EC0A404C503642B9540E4D86DE133DC /* FChildrenNode.m in Sources */, + 9AEF54170F7BD7F27A35B8E230877EAF /* FClock.m in Sources */, + 08F09B2728494409BD2DC9C7FD33C7E7 /* FCompoundHash.m in Sources */, + 73F18C354CA89D79D302A0817D8D62E7 /* FCompoundWrite.m in Sources */, + C22660680F678BC5FE5331F25B2E86D6 /* FConnection.m in Sources */, + 41A81452441B42D5FA63B6F7DF2B8E34 /* FConstants.m in Sources */, + EAB7C94331469362F19A16C3D03A2B19 /* FDataEvent.m in Sources */, + F14E4F88AC46BE87F1AA30D7DAACD352 /* FEmptyNode.m in Sources */, + 87E5203F27F981D453D08EDD52531A39 /* FEventEmitter.m in Sources */, + B175CAD91120F2AE08446C985E44ECD0 /* FEventGenerator.m in Sources */, + 6F53DEEC73A0B0613D86DF003E28CF6D /* FEventRaiser.m in Sources */, + 32D4873D9CE7533E2B8FB5A5A780AFC4 /* FImmutableSortedDictionary.m in Sources */, + 1E895BA1D1C67BA6B467D4FE91D5DBCB /* FImmutableSortedSet.m in Sources */, + 5EBE509B62EC6ED972B747240326E420 /* FImmutableTree.m in Sources */, + 572D63DEB6D5CE940424A804F3BACEDF /* FIndex.m in Sources */, + 9DA25B2EF34CDA3DEEA777AC54AF9B6E /* FIndexedFilter.m in Sources */, + BD826E7437E5D46F55E6B115FF4C22B1 /* FIndexedNode.m in Sources */, + 9CB2F238AB2FB6E3D5B0BD71B0DD9AA1 /* FIRDatabase.m in Sources */, + AAF40409B6582A25EBF6DDAF248528B1 /* FIRDatabaseComponent.m in Sources */, + FF0129B4B2CC30780B422D399C2D351B /* FIRDatabaseConfig.m in Sources */, + A17698BC6EEF1C8B99D51B8A9F260E44 /* FIRDatabaseQuery.m in Sources */, + FF2B2C133B5DD5F5AB0A75483F35B5EE /* FIRDatabaseReference.m in Sources */, + 4693044AAE649819BFFAFAF181E5F194 /* FIRDataSnapshot.m in Sources */, + 63A6EF89158BA0342A88A70BCDB53F0C /* FirebaseDatabase-dummy.m in Sources */, + 9DD235CBC46DA99444A765A1E299C212 /* FIRMutableData.m in Sources */, + 6595BA905B0AABEB781AEC9D767E3E7B /* FIRNoopAuthTokenProvider.m in Sources */, + F1D455C68A9B476EFF47977B6ECC54ED /* FIRRetryHelper.m in Sources */, + 86E1163A90BC6A5E152C9C107A904085 /* FIRServerValue.m in Sources */, + 9023EDC814EAC5D91060D88BBA0B2D97 /* FIRTransactionResult.m in Sources */, + 1A2F7B017E1D536C49FE43D267EB5019 /* FKeepSyncedEventRegistration.m in Sources */, + 0FC683562FA07E8AF2EF55D8B2167960 /* FKeyIndex.m in Sources */, + A52B25BEF516CA038540C86CD68B4602 /* FLeafNode.m in Sources */, + 96A0C993563F84620746904C97A55DE6 /* FLevelDBStorageEngine.m in Sources */, + A4F1F77F509D1EB47AAE79A666BABBBF /* FLimitedFilter.m in Sources */, + 0021862FD43EABE9787FA2D7FC7CD7D5 /* FListenComplete.m in Sources */, + 12F011A1AC64F875E04D2EFF3DC2CB42 /* FListenProvider.m in Sources */, + D1FEDD3F09D5720913C1A26ABDC691EF /* FLLRBEmptyNode.m in Sources */, + 9B79B99B4B3CEEB12792BBCD929A10B3 /* FLLRBValueNode.m in Sources */, + FB39F2E1BD5DF5585E3CED648A1A7022 /* FMaxNode.m in Sources */, + D877459D45EEBDAB1E2D149E52DC34F0 /* FMerge.m in Sources */, + FD0E361D9C432483D23BD8FE51271A1F /* FNamedNode.m in Sources */, + 733AAF70FA2B5DDC0CD79A50F9C3F6A7 /* FNextPushId.m in Sources */, + 46CD75B822E8AD2C51BE1039C2BB80F3 /* FOperationSource.m in Sources */, + C663FCE8963BFA8E0CBE7503FD659760 /* FOverwrite.m in Sources */, + E0AD22194E0117CE517A6DDFC7EA3649 /* FParsedUrl.m in Sources */, + A4D9734ACE1883DB16AEF9776C8197F6 /* FPath.m in Sources */, + ABBE590B50F0AC97EEA56EA2881486C6 /* FPathIndex.m in Sources */, + 10C1738591FDCE0FF984AAC9EEE47CD3 /* FPendingPut.m in Sources */, + 9B599B5EB8D6C2E97B0A4B7E6B9E2418 /* FPersistenceManager.m in Sources */, + A580D8D31AB1CE2135E12415F6DF4EE3 /* FPersistentConnection.m in Sources */, + 55EB4BD5AA489C1B932393E9CD151E6F /* FPriorityIndex.m in Sources */, + EE066EED402B361F7BB6FEA5EA25FA91 /* FPruneForest.m in Sources */, + 4EF14159271332EE075771C3585198CB /* FQueryParams.m in Sources */, + FD9ACE888DA2168238688C213668BB05 /* FQuerySpec.m in Sources */, + BE4DB0ECDCB7C539FA09D6ADD1D14D2E /* FRangedFilter.m in Sources */, + FECEF5ADD8A45941A91DCCE5BD0E5087 /* FRangeMerge.m in Sources */, + D1D4A221AF823CB0B3200E50B460462C /* FRepo.m in Sources */, + D5AEF294389709ECF3AC35A4EB868F74 /* FRepoInfo.m in Sources */, + 49F5B82C29710453011ED5F892B91B96 /* FRepoManager.m in Sources */, + 640B42CA70E9ABF7F582CB9E0CFDAED1 /* FServerValues.m in Sources */, + 5A47B09C86EE1E3AC3ABE08A52C6A280 /* FSnapshotHolder.m in Sources */, + 54F084CA1A6FCA5878B5B017B585A1B7 /* FSnapshotUtilities.m in Sources */, + 490A2A7CEE593B12A2591ECC7AD538A8 /* FSparseSnapshotTree.m in Sources */, + E6330EB50A0B5F249B737153EB619465 /* FSRWebSocket.m in Sources */, + 23BCA5D9E3074CAC2793EF3705AD4B8F /* FStringUtilities.m in Sources */, + 9A6631F9BE2D1C8642A54921EB210A4B /* FSyncPoint.m in Sources */, + 853279E9E5069291C7441613E6FFD021 /* FSyncTree.m in Sources */, + C04BC8EBF1E3A0C816AB8BFB7694AB82 /* FTrackedQuery.m in Sources */, + 52B36E9BD0987C1C076179244C715689 /* FTrackedQueryManager.m in Sources */, + 40BBCE59B55AF4DACDD206A0A4D9F68D /* FTransformedEnumerator.m in Sources */, + DD16D5A7EB3F4B888F5D6863A3CBC520 /* FTree.m in Sources */, + AFD04677C3352C023D0258FF28F550B7 /* FTreeNode.m in Sources */, + DF51C380D05B32F3FC8B69D3096A0D98 /* FTreeSortedDictionary.m in Sources */, + 9CB63266275054887263D021A95BD648 /* FTreeSortedDictionaryEnumerator.m in Sources */, + 1EB9E61D79FD9E9A446FA26A9F1F6E0F /* FTupleBoolBlock.m in Sources */, + AA80ECEF61E729BEB073D1DAB31C395F /* FTupleCallbackStatus.m in Sources */, + A86820C5CD61665C39E4D5D43C65CA8D /* FTupleFirebase.m in Sources */, + F6A82FE7D50B0D1B89714BE51CA9C0DF /* FTupleNodePath.m in Sources */, + 1BE1B577C737CD0E8EE51B11CD199F8F /* FTupleObjectNode.m in Sources */, + 5FC48233A9A091A5AD41F48C246425B6 /* FTupleObjects.m in Sources */, + 3E725E644BD03962B59F11CD52FEB12E /* FTupleOnDisconnect.m in Sources */, + 2C48C1B2EF74AD4B05566974D8F98ACB /* FTuplePathValue.m in Sources */, + 657237B8B4F32B13EDF3F4C2DC948AB2 /* FTupleRemovedQueriesEvents.m in Sources */, + D8BE368CE172CD2E06EEB5C1A98AD707 /* FTupleSetIdPath.m in Sources */, + CCB8E583CA5F3953D0E5BFEE2E350A8D /* FTupleStringNode.m in Sources */, + 939DD4BD42800E7A5CEB47528F0F7635 /* FTupleTransaction.m in Sources */, + 7E5BE70443E370E84BECD288D939F429 /* FTupleTSN.m in Sources */, + F261DF6379AD624C530E8AFE2326CDE9 /* FTupleUserCallback.m in Sources */, + 1F8CA46274574BF041AD357C27838B08 /* FUtilities.m in Sources */, + 14A82A4E92B4D8451F67924EFB51B52F /* FValidation.m in Sources */, + DFEC09AD2041549CB68FD873BA3BD35D /* FValueEventRegistration.m in Sources */, + 24E938D0969282690C6E5BE66BC8DB9A /* FValueIndex.m in Sources */, + C751BB8850702F0799370D6437A38A5D /* FView.m in Sources */, + 4346A89B7AF2440D62CB3A1323E9F399 /* FViewCache.m in Sources */, + 301955A8C9DDB9D6E910AAA2068F674F /* FViewProcessor.m in Sources */, + DFC90DAF4138CC9B0FDBA54D1E4BA4EC /* FViewProcessorResult.m in Sources */, + F2FE0C3C57205C18F4A06AC4291717B3 /* FWebSocketConnection.m in Sources */, + ABD104FE4926258ACBCA8AF01C763714 /* FWriteRecord.m in Sources */, + F195966D55C322389496205A7E7C10ED /* FWriteTree.m in Sources */, + 962E953C11BC8DFEF369AE6E249BB805 /* FWriteTreeRef.m in Sources */, + BB7267913ABFB33F15AAC006C881A596 /* NSData+SRB64Additions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 16575CAD34F48EF3D7DFECF12D56CBA5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 20C074AF377D311FF0D86684614A5433 /* FirebaseInstanceID-dummy.m in Sources */, + 20245E269E9A77D9BC7ED27B259787A9 /* FIRInstanceID+Private.m in Sources */, + 73403591BF9BED66D7BF53BEE9C97933 /* FIRInstanceID.m in Sources */, + 7CB3E37A6635240A46A9B6F644ABD018 /* FIRInstanceIDAPNSInfo.m in Sources */, + 1318A638736A3BD7872115F0EB6097E4 /* FIRInstanceIDAuthKeyChain.m in Sources */, + D1019928427B03120CDA22A4DDB3416A /* FIRInstanceIDAuthService.m in Sources */, + CEE94B65B2B0DD84E6286E114C15A000 /* FIRInstanceIDBackupExcludedPlist.m in Sources */, + 4ED40DC2D90361334824EA94C69DAC8A /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */, + 49E5C9957A73B815E9B4EFAED0929321 /* FIRInstanceIDCheckinPreferences.m in Sources */, + E8AC86C0D05DA3F36759612843B60FA9 /* FIRInstanceIDCheckinService.m in Sources */, + 2F7ACB9C3474E5F8977D9685B600E363 /* FIRInstanceIDCheckinStore.m in Sources */, + 2CB53881B52015395E5B96C1201895DF /* FIRInstanceIDCombinedHandler.m in Sources */, + 4418CD739AC0D463A5F8E5D65ECB16F9 /* FIRInstanceIDConstants.m in Sources */, + D86B30E9596A9BC61958788C91F5F50A /* FIRInstanceIDKeychain.m in Sources */, + 7E2C639C00F2A49D67EFEDDAED713874 /* FIRInstanceIDLogger.m in Sources */, + AB6FEE7F98E3F2AC22F81FC98DB4D526 /* FIRInstanceIDStore.m in Sources */, + 80985B6C5CF33E0C7D5B4BA38BC05467 /* FIRInstanceIDStringEncoding.m in Sources */, + 441C94CC068CB85B1EE962C7DBB0CCE3 /* FIRInstanceIDTokenDeleteOperation.m in Sources */, + 1A01FE1CA710160C1016DD3A299FD0EA /* FIRInstanceIDTokenFetchOperation.m in Sources */, + EED9CB4174EAF0FDECF0515A3567C9F3 /* FIRInstanceIDTokenInfo.m in Sources */, + 59B832BF2DCA30E869E024E410B4FD13 /* FIRInstanceIDTokenManager.m in Sources */, + 5A51CA1A353626C080186F2915B3B374 /* FIRInstanceIDTokenOperation.m in Sources */, + 9EF9F716AFB202E33AF3B0EE68FEA9A2 /* FIRInstanceIDTokenStore.m in Sources */, + 902823B2683DA4C24070B2974910324F /* FIRInstanceIDURLQueryItem.m in Sources */, + B82BF56465E4FEA663175FA28A559E80 /* FIRInstanceIDUtilities.m in Sources */, + 3ACD266E0A1B28DAA25CBC1322E6A0AF /* FIRInstanceIDVersionUtilities.m in Sources */, + 5786FA7AC828B7B61B0D963AA344ACDB /* NSError+FIRInstanceID.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 19DD17E85A44DEC061B80F617A5026BC /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A7A6C79F42DBB21F8120F3CAED13DFE /* GoogleUtilities-dummy.m in Sources */, + 23819399B031293AA3D85828F7CE6FDD /* GULAppDelegateSwizzler.m in Sources */, + 001A2AE41501B7F822B899233A40BF1A /* GULAppEnvironmentUtil.m in Sources */, + 480A04FCEB9F74A462DCF3E4E65AEC64 /* GULHeartbeatDateStorage.m in Sources */, + 0EB6B0D639DA75E20A759A4449BE3AFE /* GULLogger.m in Sources */, + 35E06A30663DF152AF0B2CBE90A8D113 /* GULMutableDictionary.m in Sources */, + A5D882CD9E5E0B52B0759B783A8402C8 /* GULNetwork.m in Sources */, + 451CC5C8BC9A08A786B81A3B4C4024E8 /* GULNetworkConstants.m in Sources */, + 81E9978708F6226709BAB53EE2CF9C63 /* GULNetworkURLSession.m in Sources */, + FFDA6E8C874151778929453550A2A0CB /* GULNSData+zlib.m in Sources */, + 303E8921DA22E167791ADF29196C2840 /* GULReachabilityChecker.m in Sources */, + 645B4A5E78A6930440C419B5DB349749 /* GULSceneDelegateSwizzler.m in Sources */, + 86D43E37DB4D8A2789294AAD41B0EEBA /* GULSecureCoding.m in Sources */, + 8DF88FE5020589CBED594CC31C6A0867 /* GULSwizzler.m in Sources */, + C98328C34C776617F077E50D7DDCEE35 /* GULUserDefaults.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 220FDCEB2CE1D6759A3A2F61F5448C1F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BDFBF6C03DA9FDA91EFDB3E73C4FBFB1 /* arena.cc in Sources */, + 85CA11CF7AB83ED7C9A7718A6302711A /* block.cc in Sources */, + E22804F8B066EE82FFF359DB2D60FCC6 /* block_builder.cc in Sources */, + 0F912F50E354B79E92EAF43C711F60F1 /* bloom.cc in Sources */, + BA1C29BA7381A7A52D09622981A8E6B2 /* builder.cc in Sources */, + 2F1E55E897210AEDB50F9DF6979F938A /* c.cc in Sources */, + DBC33C39A9ABFDCFBD370F4E354CBCE9 /* cache.cc in Sources */, + 51CFE79D0A35972C408CACE75B5E318A /* coding.cc in Sources */, + 58A44043BCC0225FFFA5CDEC7322A2E1 /* comparator.cc in Sources */, + 5F0C5E4C1DFAEBD8491F3148EBD90EF6 /* crc32c.cc in Sources */, + 00F48B92E55005586F5577535A35C44D /* db_impl.cc in Sources */, + 4A2499CF744F2DA84A696B775C4A4D2B /* db_iter.cc in Sources */, + 96DD7F303C2D0A8605B4294F30EDE393 /* dbformat.cc in Sources */, + 14589D6DA4F621EEA8357F7B8D36F415 /* dumpfile.cc in Sources */, + B3C042786A70C2216566529189C6CCA3 /* env.cc in Sources */, + D39B5FF909B620DE847ED31168A6FC2F /* env_posix.cc in Sources */, + 504921BD2B0D4F5B15580FC30F69098D /* filename.cc in Sources */, + 8F2443BF8A7D5DB547C9509341E9FD18 /* filter_block.cc in Sources */, + 256379D9DD965C592CEA8B9286B6AB53 /* filter_policy.cc in Sources */, + 18A932D04692B43A9F8BE0F8AF0C6B54 /* format.cc in Sources */, + 5E0F436EB98F3C615BB612216EE8904B /* hash.cc in Sources */, + C0083E25EC2B54DC6F3F0615958F4B1F /* histogram.cc in Sources */, + 7958F051CAD9CB7D57D28FFE63E74827 /* iterator.cc in Sources */, + AE8C52AA4BB23F1700B8423A56460A55 /* leveldb-library-dummy.m in Sources */, + AF6C482B18C9E693BCBAAF2B4523514D /* log_reader.cc in Sources */, + 9845FE55931EFF372DFA1F7131FC2FAD /* log_writer.cc in Sources */, + 2196D83376D82F08143CBCAA87292D0F /* logging.cc in Sources */, + D643135906372122446C44E57884193B /* memtable.cc in Sources */, + 8B88C39196D031B2E65C59D29A9514D5 /* merger.cc in Sources */, + CC187C6A88BE4B72F318125E1F36DB9F /* options.cc in Sources */, + 159FAD44AAB2F5AB322049B4A6626285 /* repair.cc in Sources */, + BE6F9C947012AC55EF5F579DE446596E /* status.cc in Sources */, + 177B7DEC27752E27FA06328B2A123A69 /* table.cc in Sources */, + 7BB8F10847144EF9E81AE39013F71A2B /* table_builder.cc in Sources */, + 43FFF7833C563543060BFBC31DB3AF02 /* table_cache.cc in Sources */, + B889A468E8E56AD353F03BB42B5A7A4F /* testharness.cc in Sources */, + 8173F266B34AB78112BDC9F1178464A5 /* two_level_iterator.cc in Sources */, + FEFF99D7C71855800215B7CF93878B2C /* version_edit.cc in Sources */, + E8E039615A0EE503F1BF21AB15A89C82 /* version_set.cc in Sources */, + 774179338BE4754263738DCE7E7E9358 /* write_batch.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2E49770D9B170D53DC3F65488AA72C6B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8A15F2E0F27073273B9F005AD2DD87D3 /* FBLPromise+All.m in Sources */, + D22DA4596686C8BB2B7769D432743ABA /* FBLPromise+Always.m in Sources */, + 77E3E9EBA0F53BA60BF6853FE7AD8DD7 /* FBLPromise+Any.m in Sources */, + FCC5E382E981CF1B5FFE9813E0FE0250 /* FBLPromise+Async.m in Sources */, + CDE0196E899CC7D402DF1102115E4C0A /* FBLPromise+Await.m in Sources */, + AED6299AF75D2418193FC6B715D97188 /* FBLPromise+Catch.m in Sources */, + 7841AA457BA7BF9D0C92B611AAC1934E /* FBLPromise+Delay.m in Sources */, + DB47E56AE089298BE3E3095055C3A120 /* FBLPromise+Do.m in Sources */, + 9A1BDDF47635DBEA58A6C35A7492B80E /* FBLPromise+Race.m in Sources */, + E7294BFB81C9230F1F3F709A75B7BC66 /* FBLPromise+Recover.m in Sources */, + 078B94AA0304E225E31E0B54C10D1931 /* FBLPromise+Reduce.m in Sources */, + ED6EBC6B0D6818AE784AEF5DACCF1CB8 /* FBLPromise+Retry.m in Sources */, + B8E9F8BF35F3206D2E807E34BEE29DCE /* FBLPromise+Testing.m in Sources */, + 7FF09AAD3D6EF0664BB9EBBE4702F5AA /* FBLPromise+Then.m in Sources */, + F39CD698A419074BC74CF01175D286E1 /* FBLPromise+Timeout.m in Sources */, + 1C57452B6C5DCA13A84F0A6E2A8640CC /* FBLPromise+Validate.m in Sources */, + 528C67FBF5D6319DC04886F582D0D428 /* FBLPromise+Wrap.m in Sources */, + F4D11903D0482C4B89BF1AFA5764EBEF /* FBLPromise.m in Sources */, + 8A330C9F1BA929109DE4BD3CCDF1738B /* FBLPromiseError.m in Sources */, + 0FB8CFC18E7A14D4380B157FBC3A38E5 /* PromisesObjC-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4585E1157BA71EE219BC8F11323324ED /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7EC8F372099B7B93703D558822D9F5C0 /* Pods-PediatricPancreasTests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F3A3D6AD1E42EE428CD03BE69DFFCA6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 36857AACBBD006017DAEA55E0C153ED0 /* cct.nanopb.c in Sources */, + C12EB6D2E322D9664BBD627B922E960D /* GDTCCTCompressionHelper.m in Sources */, + 99B96C475814E67892434BB4236B0545 /* GDTCCTNanopbHelpers.m in Sources */, + A6FD535D1DABEFB37CD9A52052DBBBAD /* GDTCCTPrioritizer.m in Sources */, + 585432A81A1445BE160730C4D6A6EEE4 /* GDTCCTUploader.m in Sources */, + F259FC486D219CCF52DE0760C24C8363 /* GoogleDataTransportCCTSupport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 99C3DE4D60FE4A4C8A54E45359FCEB05 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B950E749FC38D40DA5F0E41AA70AD644 /* FirebaseInstallations-dummy.m in Sources */, + 1FB8B47D82C12825FC29C374954DB686 /* FIRInstallations.m in Sources */, + AA0F319DEAFD81B260F9CA9529F6C60E /* FIRInstallationsAPIService.m in Sources */, + 3138786FD0F60F0C415E6BD851240611 /* FIRInstallationsAuthTokenResult.m in Sources */, + 4BC8B7D684A6E5E15EF10F120622DF86 /* FIRInstallationsErrorUtil.m in Sources */, + FE99F20F6F9985221393A13ACFF850CC /* FIRInstallationsHTTPError.m in Sources */, + 491D4AA6161DD56B372AE8859D9EB5D8 /* FIRInstallationsIDController.m in Sources */, + EB9CD95B07AAD3C35FB2E300BED18C59 /* FIRInstallationsIIDStore.m in Sources */, + 101FEB4979AEF5F7A706990B49E2497E /* FIRInstallationsIIDTokenStore.m in Sources */, + 40601A4D3779E3D643749E6379AAB8C8 /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */, + 6ED483CC1CFBA7C89E08DB039E89AC57 /* FIRInstallationsItem.m in Sources */, + 489BE597AE9353534CC9F3FD9AF61951 /* FIRInstallationsKeychainUtils.m in Sources */, + 83856F7D562625FBF40DCEC1EA44B636 /* FIRInstallationsLogger.m in Sources */, + EAF532BDB50195BDAF699D5317AE2C53 /* FIRInstallationsSingleOperationPromiseCache.m in Sources */, + 3039C2C0C98A44B60136E507C77E915F /* FIRInstallationsStore.m in Sources */, + E27BF263AA7947104D42690CB618C55C /* FIRInstallationsStoredAuthToken.m in Sources */, + 8C65CC5681A16CCCAF784C04883343BB /* FIRInstallationsStoredItem.m in Sources */, + 5897F0A8E4D00174A944E698AEA6EBF3 /* FIRInstallationsVersion.m in Sources */, + DA4B9607E3EAD4183AEE60CBC133AD75 /* FIRSecureStorage.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A2FB996CF2FA483BE84681914240B7FD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 761AD4B367A2C280D954D8F6F6EDAB10 /* GDTCORAssert.m in Sources */, + 0B2CA41FD4EA7B966543471C816C8B31 /* GDTCORClock.m in Sources */, + E7A3BF0D4825F31F00C515FA1BF1049B /* GDTCORConsoleLogger.m in Sources */, + 6C607B38D06C6BB8D7B5B3972D9E2A61 /* GDTCORDataFuture.m in Sources */, + 9F044ABB685C274B0BC394C5172D6396 /* GDTCOREvent.m in Sources */, + 5B32957659AFC9CD2F8925DE7FA655B7 /* GDTCORLifecycle.m in Sources */, + BD3C303BC87D428AFA1679E509C40962 /* GDTCORPlatform.m in Sources */, + 2CA030D81C45AE701078A106F8B8DFE0 /* GDTCORReachability.m in Sources */, + A7BA41C74ADD243922D02E12F57C54EF /* GDTCORRegistrar.m in Sources */, + A3A9C4FEC12A11770E8EB2715C47FA40 /* GDTCORStorage.m in Sources */, + 00913F81181EB89B9C3FAED5C7446DE0 /* GDTCORStoredEvent.m in Sources */, + 2F60C9EB675A361CE11F3EFB4954DCDA /* GDTCORTransformer.m in Sources */, + C83DB743E6A963EF7CFD94C23A2B2124 /* GDTCORTransport.m in Sources */, + 9D0A5CCD79BC7F1274940275B524A1B6 /* GDTCORUploadCoordinator.m in Sources */, + 7A5C6D925F727EE2EB6FAAA9FADD0D0F /* GDTCORUploadPackage.m in Sources */, + D6E03D071285D729E25229B2C668C2C6 /* GoogleDataTransport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B700E84A73D9A81FD6EFF378D4861A9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 476270E22168C78721C89A072EF9DA5F /* nanopb-dummy.m in Sources */, + FA8EDE1CAC8FD33B9CDB16C6EC60814E /* pb_common.c in Sources */, + DA3CB05AFFF892FE3B1433ADB6B64A42 /* pb_decode.c in Sources */, + C26A8673C32726942B774BA1FD2BFD6D /* pb_encode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CA0F94698E18CAAB9042A56581D002FD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 450DB46D3AB4A2DB30B67F3617E3A77A /* Pods-PediatricPancreas-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D8390D070FFC7E4E4271928DE78B6495 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4DA2E39C21EAFFAF70A67F1DF7DE018 /* Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EEA8947D055418381BDA26E78B4577A3 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 782A253D94DA7F5E7FB4FB8AA086BB0C /* FIRAnalyticsConfiguration.m in Sources */, + 1FBE9EF2264A5C7C48EB98A6E5E88BB1 /* FIRApp.m in Sources */, + B7F1DEB0A7CFC79BCA5D17E4490A732B /* FIRAppAssociationRegistration.m in Sources */, + A15A279420A8705EE038A02827E0CBDD /* FIRBundleUtil.m in Sources */, + 4262D25247B12F48A0FDE5B4E1B8BC7E /* FIRComponent.m in Sources */, + BB31A0898441B79D97551F92DA331318 /* FIRComponentContainer.m in Sources */, + 4743C0A7362C70144DA8902ECB6A107F /* FIRComponentType.m in Sources */, + 97B631CEC171F7EF158F229A5C2CA7C2 /* FIRConfiguration.m in Sources */, + B55278BC6C9DBFC08FD066AAD693E419 /* FIRCoreDiagnosticsConnector.m in Sources */, + 84D0A43392ADACD2101C33407BEBB28D /* FIRDependency.m in Sources */, + A433B40763ADD23052776B2808E2F47B /* FIRDiagnosticsData.m in Sources */, + F519E6BF09016D910B15D8D98F02E8DC /* FirebaseCore-dummy.m in Sources */, + 11591143402FAF6EC0EB1BC89B59DF2B /* FIRErrors.m in Sources */, + 7704DBEB4FD8833D2EC2965CF68761D6 /* FIRHeartbeatInfo.m in Sources */, + 2C4E0F78ACD35425AC6724A860526F37 /* FIRLogger.m in Sources */, + 61C9CE120191BD6EA53D299A4EDE90DD /* FIROptions.m in Sources */, + 493DE807724DFCD68FCAE1178577A0F6 /* FIRVersion.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F5DF007BAA1C39039238B8500939188D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F318A282CA275D436FCDC2C029315B6 /* FIRCoreDiagnostics.m in Sources */, + 7A8B2F9B9F3DD506F1A7DA32601995E6 /* firebasecore.nanopb.c in Sources */, + F4B8EC1DADBE0FC6199486B0B926B1DA /* FirebaseCoreDiagnostics-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 05D842E53602BB1DF432DBCC2ABA3372 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = 0B1562EB2F2DBE0977EC05D8EC9CEBF9 /* PBXContainerItemProxy */; + }; + 0C6BD3144A335F632CCF4C99D070816B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = F572B46CD233D12F42888F1D2FD23CA4 /* PBXContainerItemProxy */; + }; + 0D2C6E7B9AB0ACA41D4DC7E4D79F0CF9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = DC5319A4FA6ED9BF675397886D49C86D /* PBXContainerItemProxy */; + }; + 0E8A25403333F0205E16BFEC267DB922 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = 01C3D6F90D5CFE8B3F61DB9064D8DD94 /* PBXContainerItemProxy */; + }; + 1405C190ED9E1E16D2CF759D59C68D1A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 613F80DEF8505BEE8F168AE00B0A344A /* PBXContainerItemProxy */; + }; + 16F3D58024BB21F695935DA0DAD2B792 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 68E4BD480814634B9F76A9EE24FFE617 /* PBXContainerItemProxy */; + }; + 176EEFB0452E4F5CE51548153C88EDAA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = B1D879E56B8975E2D0F855D3AF60A7FA /* PBXContainerItemProxy */; + }; + 19635AAE0A3094A8088E910E1AD3B6CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = FDBD5C32BF0821031B12D52C27BB6437 /* PBXContainerItemProxy */; + }; + 1A735670E932913B3739B130B29BCEFE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 94383ED2A49C303C28844CEA3D754E5D /* PBXContainerItemProxy */; + }; + 1E5AC8537F4CE552884E6905FABFE1DF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = 55DF0DD9BBEC9E654F05912E546E3FEA /* PBXContainerItemProxy */; + }; + 24D4748F270241EEFDA258DAF729D027 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 821F6A6BD3EEB8DC5EDB2552B7AD76E9 /* PBXContainerItemProxy */; + }; + 2697D23F9C78EE842EE420E263473F39 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = 0E1817B5AF7C26EDA3F32C76520A5117 /* PBXContainerItemProxy */; + }; + 2DE901163BC34DE7855D4423B689D7CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 8AAE3563786DF886A389110F2E837794 /* PBXContainerItemProxy */; + }; + 3C1E541454C9B47A74B5B7C7E0C9CB1C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 04F55738408FF0B3986DFC0CEFCC0043 /* PBXContainerItemProxy */; + }; + 3FAF8BC099B914107FD7729D8CC3FBFE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = B1D1DEEA5D63E4D75CFF546F3F83DA46 /* PBXContainerItemProxy */; + }; + 45F353EC09C313F0B5A9631BCF1604B0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = 0144F5CACFD77356E43678B3FAE334FA /* PBXContainerItemProxy */; + }; + 4BDD54DE84523FD142113987337A776F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 618456ACDB574AF051E97F34159722B1 /* PBXContainerItemProxy */; + }; + 4D89E1C759D45D05758FB69B690BA072 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 01DD8A646592BAA427E2EFF7F4F38B96 /* PBXContainerItemProxy */; + }; + 50896A4EAEB7FA22D435704BA89EE5CB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 5197DC46CE5C1E0A2A35C9E3C05BA05F /* PBXContainerItemProxy */; + }; + 51BDCE72D635910F59F8BE2D085ECF27 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = C2E208823F026C7D492A8D5AACE76E18 /* PBXContainerItemProxy */; + }; + 5459331521249E216D6EE546528473AA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = B3F265E60F142AF26A2E9F37D6AF3FBA /* PBXContainerItemProxy */; + }; + 5DBC369ABE0DE46E6B294739601C4B85 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 371FF20F62038C2EA1489358A3341E0B /* PBXContainerItemProxy */; + }; + 5E2D75CF712A30AD19D02CFBA9609541 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = EA2ED1A2B35D5E2B0B1CDF0D72F33C92 /* PBXContainerItemProxy */; + }; + 5EA7EE3FB0C96B611E8BD457D7FE7BA2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 65D7363EBCE24720C7A576693856A663 /* PBXContainerItemProxy */; + }; + 5F2DAB5DD876EFF04AB33FEDDC642C76 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 8226E03D7C24AECFE91CB84CCEC6831B /* PBXContainerItemProxy */; + }; + 62305F374C4C5059DBD1483A3323EDA8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = B521A4436617C9306BC6510C1E1E4E47 /* PBXContainerItemProxy */; + }; + 68F495FD6399571335232AD5B7DEB78E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 67DDAB29B20A0AC750DC1D391A2564D9 /* PBXContainerItemProxy */; + }; + 6FBF1497BBA407FB369A0DD22CCD5566 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 1D5B95B2076D719B64A22444A521AE8D /* PBXContainerItemProxy */; + }; + 74442856B39755028E7EB80C418347BA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 6ACC2C1E104C5C879107CA9F53EE5F6F /* PBXContainerItemProxy */; + }; + 769F7393D871F666672BE9EB5FDFE138 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = 0B7842CD919BEA86E41C5EA382BD9695 /* PBXContainerItemProxy */; + }; + 77F88BF4D201EEB058A96EE26A885132 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = F2FDFFB0AF4F2605D7656D95768757D9 /* PBXContainerItemProxy */; + }; + 7873705F7362CB707D163F2F5C6F1C25 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 30FE43B1567CF74AF6456BE5707316D0 /* PBXContainerItemProxy */; + }; + 7EDA800ED0C497BB44B2FE613941C4F0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = CDF422BBF53A976E3240A02AC581F2DD /* PBXContainerItemProxy */; + }; + 7F7F948B21FE240EDC29385EBEF9183A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = 7190AB6B712F20360B7FC488CF4516DA /* PBXContainerItemProxy */; + }; + 80502E36CF51F684EE9239228201D901 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 542F1DE0BF918C2EFC3B5EF9FEC93711 /* PBXContainerItemProxy */; + }; + 82BB54BD09FD3492EDC3EAB7F8319744 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = 9635B8090E964ADEFD5BB3219470C388 /* PBXContainerItemProxy */; + }; + 85F8C10667F91A5415950BFB7DF60B2B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 224878850BC853E940428569925BADD2 /* PBXContainerItemProxy */; + }; + 9156E284938A0D0BE126C93F73CBC909 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = 67664D372030762D2683EC54CAF48029 /* PBXContainerItemProxy */; + }; + 91A2F9949849A92A1C71E53754F9CD74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 2B936F10D58E10DC3BA3305120F31349 /* PBXContainerItemProxy */; + }; + 926485F7A1D02636A6267356E7EA2FF1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = A0F0437B6668EAAFC28E758C26E756D3 /* PBXContainerItemProxy */; + }; + 94E625C0654FD5965D513AB143010125 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = 336A7EACA49FB1B8D7C3E265EE7EB0C6 /* PBXContainerItemProxy */; + }; + 982CB806C0927639A0756C623361FB86 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 61CF77C232064A77915FDAF556BD3780 /* PBXContainerItemProxy */; + }; + 98EC313982438CDA09DBA1872B7C3374 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = 7CBBE25681088124AF83361708BEBE9F /* PBXContainerItemProxy */; + }; + 9F65DEC27AA4C81FF09CF5E514792B9C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 8B9DBD04238080114146BEF8EE130975 /* PBXContainerItemProxy */; + }; + A1543F036F8DA36656A816076F259FCA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = 86294ABE4F8ABF6D8CAA0C2AB8A712D1 /* PBXContainerItemProxy */; + }; + B3FBD5800B1E0144A1F5F1D6D4FEE80D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = E8878B5BF04A719823FA1A33FCF7DA12 /* PBXContainerItemProxy */; + }; + B655229A63479803B5798F6F4862E720 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 306F3643D17DC54C17E825B313DFC5A3 /* PBXContainerItemProxy */; + }; + BDE7CB53A57C718C77AA8C14C2DFDA79 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = D35FD17C818961EC9C90DB83F6CEFDDD /* PBXContainerItemProxy */; + }; + C07CCD661BB0EC97B07D537842981A2E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = 4A54388B54F2980C54C8E656A9B416CE /* PBXContainerItemProxy */; + }; + C08C781D810593A2CE1E56C6FC06400D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = FD191C31AEB003D245EF173182D85974 /* PBXContainerItemProxy */; + }; + C45C2EC7764643102CE493AF6ABFF69E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 5DAB5E2BA4DB163CEC1881FA1CF2B311 /* PBXContainerItemProxy */; + }; + C472727A0907C53BCDFF109E5F28DAAB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = B31E14489793CB24F96924F288B4B307 /* PBXContainerItemProxy */; + }; + CDD8708FF4BC6CF44914BADDAA1051F5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Pods-PediatricPancreas"; + target = 8A7E9E78EB0B7B5A38DBA30283079B9F /* Pods-PediatricPancreas */; + targetProxy = 676814A783F3923FBCA272BD787789B9 /* PBXContainerItemProxy */; + }; + D380A2798F3887C211368F99B7C367DA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 8CB50BF08D8BB29322EBC81643A8EFA4 /* PBXContainerItemProxy */; + }; + D6B0A0F91F5F385BF853F0F370DEBD0D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D25E1B89D7A51ECE955BCC5D1CE27FF2 /* PBXContainerItemProxy */; + }; + DDC522A4C9D21A8D07AC77910A400385 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = 9D7A685459C8A2DD0A08EA7C402C391B /* PBXContainerItemProxy */; + }; + E0E18C912765D2D0ACE9275EB93FE611 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 477FE2FAD124CFD3151D0C58A5246FBD /* PBXContainerItemProxy */; + }; + EB05FCC745537DDC437B3B6B9C591FED /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = 298F4CE8468DC4D69441012A13756B9A /* PBXContainerItemProxy */; + }; + EBDB50EA5915A344EDCF79B88DE2C310 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 8010D3FBC1FB35FD88AB6285A82CB373 /* PBXContainerItemProxy */; + }; + FDA6E390AD4A330B2C0D716D0A79D59B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = 135574C1AC9B96C13F65DA376FA66ECB /* PBXContainerItemProxy */; + }; + FDF91132B921A52CB4F146E1625A615A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 25D8491B094007D1503A22D44A6AF8DF /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0A20B7CBF518C73C4F9C96AE9F60D977 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DA6701FC5AB530406CBCD86ED01A7743 /* GoogleUtilities.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0EA8B3F3AA10B7B85C684A48399DAC04 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2D8BDFC58A9D05BCE6AA0A666C2C3E44 /* FirebaseInstanceID.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 11A567A3C4DE07DA10613002A8190EE9 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E30CFB2462172C3B6FD5FF8283FA7AB /* PromisesObjC.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 203D45C40E68A458E1AEC216CD30533D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7960FB1C76F2424FD931382B8D99FE6A /* Pods-PediatricPancreas.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 233179116A3A3229A12251D27EEB0E02 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 857C2725A4F0AF79A30DEC50DA6A0E48 /* PromisesObjC.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 23F21B0CD99C8AED1AA1A6A0B5DE089A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 28F14DA020DF94A85C5154772920D6F0 /* nanopb.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 259BFC1400EA28E3974AE8701B684E03 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 382B9EE58EBB9AFB9485174E53DED76A /* FirebaseCoreDiagnostics.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 27D0EF10F7E7214F9F324643819406C5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 23C79734BF195C12C8CA32C05F9DC901 /* FirebaseCoreDiagnosticsInterop.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 30BA1E1A21C3DA3251D4BE5369159E0B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B16323EDF0B3CD0A257043DF559E872F /* FirebaseCore.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 332E6496D7767FB6664DE21703748913 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 566267F9A313143EE6BDD499F3866124 /* Pods-PediatricPancreasTests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 33546E303A916BE164A4758A0FE16EDC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5CD246213E4E717E503D47F79BBB2439 /* FirebaseCoreDiagnostics.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 3A29896D95F356520F220A812028B002 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0E998FD134CA2B57FE5787B01602A4C5 /* Firebase.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3B4D25B9D541D1138A55B974EC152B16 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2BE2D2C1742A0A5FD7AA60074322F8F2 /* leveldb-library.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 469B24DC7586CECD5EA2F813CCC39186 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8245B1F254DC9F182514403D6091F777 /* GoogleDataTransport.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 49273B90B63C41A627C98B56C08C8969 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F51F769F4128614EC9AACBDED917D441 /* GoogleUtilities.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 4D291CAB9316C3007BC11B02BE95EBD5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 38EBB4AB7E209E3659BF7E9B889F7423 /* FirebaseDatabase.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4E2A62E78E87198761041A9528B1F84D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C971FDA3436CE4F78017B79B4063F5B2 /* leveldb-library.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 5B9DB234BACB84D4C3C851B0D7389AF2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = EA54A83590F15D08BA0EA2F09D24D2D3 /* GoogleAppMeasurement.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 5D88A521AE9A93C4B07F2DA8976C2F2B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 518C77022625AF3F201451F80ACA198B /* Pods-PediatricPancreas.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 62EF3747F748726B66FAAAAA230DDD66 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B24AD89FADA9EEF707A29719300BBAE7 /* FirebaseAnalytics.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 7EFDCAB9D4553BB7D70BF93A6EC5DF8E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BFCA9E7603A4EBE52A899B3964CCB141 /* FirebaseAuthInterop.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 83DD460DD603E8FBA71D481067636076 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E467841A32C8128E295B54A295D58D2E /* FirebaseAnalytics.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8B4C96148F6206474E0464BBAA58A71D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B41A267A51E2D1204B721F1B7DF81D1 /* Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8D1ACC0151ABC14CABD3BED725D88768 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 87305E67A3F0888418FD5FB15A3AACE9 /* GoogleAppMeasurement.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 939F1A8F6BCEB7F9F64D9EEE50CAE014 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + A599FD54C55A11EFF169AC31F1166D47 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F66F8E423E7A327C613AC805E253BB2F /* Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + ADBE608408CA71DE17CF9AC9BD791A28 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4424C23BA8BD950C7B96DC874B777989 /* Firebase.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B3619FD3D7C0901825025445E1F61B51 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0A6B42B21F0C1F8665483A4BB4946268 /* GoogleDataTransportCCTSupport.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + B4C00F436572076FA238D12D636A1166 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 82C4CF4D53142C0C4CF6949E22FC3124 /* FirebaseAuthInterop.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + BA1079574A3E7E32FEF655DF363B41C1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5E29BD1F7221E4AB0C4A4ED785D7608C /* GoogleDataTransportCCTSupport.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + C2BE92907424FA4786CF54001020CD74 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C099348FF2762A50FC42CDA312B9414B /* Pods-PediatricPancreasTests.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D609AC0A065F8F0084FD48530B457391 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9DB4215D54529564ADDF9449A77C3C99 /* FirebaseInstallations.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D83C54D03E0DBA13578846C84F31B79C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A60A55723949183FAB49E5B3D9577924 /* GoogleDataTransport.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D97FB945128B95984D37AD6E59B9BA63 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 36564ACDC189BBCFE100D9CED8658730 /* nanopb.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + E136BA0FB40EE2DD34B0594CA490693B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3250A298087DD89728C3E5E2CCA32C78 /* FirebaseInstanceID.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + E188492E376D372A7EEBA89BCA0BE1BE /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 502076027B4DCEB843DC38B97A94887B /* FirebaseCore.debug.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + E20E7C54923B2A26CB90F28AD0DFD4EB /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4DC21506550FA18E27B3273C19EE1878 /* FirebaseInstallations.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + EA3C07A983947E4A59E6429151C98D84 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C1D0CF348FD58D4E6F51BC58089A8946 /* FirebaseDatabase.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + ECB437504DF805BD96CAABF97400B526 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + FA737E855277963CD9D5DCAE40C8537E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A51F851D55A40196F404D20CC95BAD99 /* FirebaseCoreDiagnosticsInterop.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0D60FBF4A3563D9B9A8626B8486F1347 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 203D45C40E68A458E1AEC216CD30533D /* Debug */, + 5D88A521AE9A93C4B07F2DA8976C2F2B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2ED8A72DB7F84BD892A32A461B4808A5 /* Build configuration list for PBXNativeTarget "leveldb-library" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3B4D25B9D541D1138A55B974EC152B16 /* Debug */, + 4E2A62E78E87198761041A9528B1F84D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 43C26ABBE9DC4E233EC8499C10B70042 /* Build configuration list for PBXNativeTarget "PromisesObjC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 11A567A3C4DE07DA10613002A8190EE9 /* Debug */, + 233179116A3A3229A12251D27EEB0E02 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 456EAC6805E9895E0DAF29D274E62DC0 /* Build configuration list for PBXAggregateTarget "FirebaseCoreDiagnosticsInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FA737E855277963CD9D5DCAE40C8537E /* Debug */, + 27D0EF10F7E7214F9F324643819406C5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 939F1A8F6BCEB7F9F64D9EEE50CAE014 /* Debug */, + ECB437504DF805BD96CAABF97400B526 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5889EFDAC639033660B767DFB79C0B17 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0A20B7CBF518C73C4F9C96AE9F60D977 /* Debug */, + 49273B90B63C41A627C98B56C08C8969 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 58E94B7FB6E0686AD93AF7BC1156F389 /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33546E303A916BE164A4758A0FE16EDC /* Debug */, + 259BFC1400EA28E3974AE8701B684E03 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8744A71516AEF576C6D6958B54BBDFB5 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 469B24DC7586CECD5EA2F813CCC39186 /* Debug */, + D83C54D03E0DBA13578846C84F31B79C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8DD977517C248319451DB85AB81E48C6 /* Build configuration list for PBXAggregateTarget "Firebase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ADBE608408CA71DE17CF9AC9BD791A28 /* Debug */, + 3A29896D95F356520F220A812028B002 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9CC09DAFA09AB5D8EBE5B10BB259F60F /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 62EF3747F748726B66FAAAAA230DDD66 /* Debug */, + 83DD460DD603E8FBA71D481067636076 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A50DCC391E886E3336A6977292720DE7 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas-PediatricPancreasUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A599FD54C55A11EFF169AC31F1166D47 /* Debug */, + 8B4C96148F6206474E0464BBAA58A71D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B06332DA5A203A349B875007390EFEC7 /* Build configuration list for PBXAggregateTarget "FirebaseAuthInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7EFDCAB9D4553BB7D70BF93A6EC5DF8E /* Debug */, + B4C00F436572076FA238D12D636A1166 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B4E31387BEF7D6F4FD8B312C9578BAE0 /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D1ACC0151ABC14CABD3BED725D88768 /* Debug */, + 5B9DB234BACB84D4C3C851B0D7389AF2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B689081FB906519ACAD19D7FC6F23A92 /* Build configuration list for PBXNativeTarget "FirebaseCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E188492E376D372A7EEBA89BCA0BE1BE /* Debug */, + 30BA1E1A21C3DA3251D4BE5369159E0B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C1983DB33A942214A80E06F4A2BC9CB4 /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D609AC0A065F8F0084FD48530B457391 /* Debug */, + E20E7C54923B2A26CB90F28AD0DFD4EB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CE7EDF042F1D503B96A8DFFD05267C70 /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4D291CAB9316C3007BC11B02BE95EBD5 /* Debug */, + EA3C07A983947E4A59E6429151C98D84 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D4354311CC4C1FA1C205834FC9996237 /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B3619FD3D7C0901825025445E1F61B51 /* Debug */, + BA1079574A3E7E32FEF655DF363B41C1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E65B70641EE44AF0CCBD0B75C656BACF /* Build configuration list for PBXNativeTarget "nanopb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D97FB945128B95984D37AD6E59B9BA63 /* Debug */, + 23F21B0CD99C8AED1AA1A6A0B5DE089A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F362EAC4ECF0734220A524D18E1E841C /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0EA8B3F3AA10B7B85C684A48399DAC04 /* Debug */, + E136BA0FB40EE2DD34B0594CA490693B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F6D83BB6092005AFC8CB075E28930EB7 /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreasTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 332E6496D7767FB6664DE21703748913 /* Debug */, + C2BE92907424FA4786CF54001020CD74 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Firebase.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Firebase.xcscheme new file mode 100644 index 0000000..ab9e834 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Firebase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme new file mode 100644 index 0000000..3eba3b7 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme new file mode 100644 index 0000000..7202e6b --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCore.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCore.xcscheme new file mode 100644 index 0000000..a4c140c --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCore.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme new file mode 100644 index 0000000..21f827d --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme new file mode 100644 index 0000000..7a77896 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme new file mode 100644 index 0000000..0756d3d --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme new file mode 100644 index 0000000..68d579e --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme new file mode 100644 index 0000000..35d5ec7 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme new file mode 100644 index 0000000..3b0614e --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme new file mode 100644 index 0000000..6208c32 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme new file mode 100644 index 0000000..968a5eb --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleUtilities.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleUtilities.xcscheme new file mode 100644 index 0000000..3915f21 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/GoogleUtilities.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme new file mode 100644 index 0000000..038cad5 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme new file mode 100644 index 0000000..b5c95b6 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme new file mode 100644 index 0000000..1bc1725 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/PromisesObjC.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/PromisesObjC.xcscheme new file mode 100644 index 0000000..ae3daf9 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/PromisesObjC.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/leveldb-library.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/leveldb-library.xcscheme new file mode 100644 index 0000000..d97b061 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/leveldb-library.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/nanopb.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/nanopb.xcscheme new file mode 100644 index 0000000..2183889 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/nanopb.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..8c20ad3 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,106 @@ + + + + + SchemeUserState + + Firebase.xcscheme + + isShown + + + FirebaseAnalytics.xcscheme + + isShown + + + FirebaseAuthInterop.xcscheme + + isShown + + + FirebaseCore.xcscheme + + isShown + + + FirebaseCoreDiagnostics.xcscheme + + isShown + + + FirebaseCoreDiagnosticsInterop.xcscheme + + isShown + + + FirebaseDatabase.xcscheme + + isShown + + + FirebaseInstallations.xcscheme + + isShown + + + FirebaseInstanceID.xcscheme + + isShown + + + GoogleAppMeasurement.xcscheme + + isShown + + + GoogleDataTransport.xcscheme + + isShown + + + GoogleDataTransportCCTSupport.xcscheme + + isShown + + + GoogleUtilities.xcscheme + + isShown + + + Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme + + isShown + + + Pods-PediatricPancreas.xcscheme + + isShown + + + Pods-PediatricPancreasTests.xcscheme + + isShown + + + PromisesObjC.xcscheme + + isShown + + + leveldb-library.xcscheme + + isShown + + + nanopb.xcscheme + + isShown + + + + SuppressBuildableAutocreation + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme new file mode 100644 index 0000000..ab9e834 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme new file mode 100644 index 0000000..3eba3b7 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme new file mode 100644 index 0000000..7202e6b --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme new file mode 100644 index 0000000..a4c140c --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme new file mode 100644 index 0000000..21f827d --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme new file mode 100644 index 0000000..7a77896 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme new file mode 100644 index 0000000..0756d3d --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme new file mode 100644 index 0000000..68d579e --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme new file mode 100644 index 0000000..35d5ec7 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme new file mode 100644 index 0000000..3b0614e --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme new file mode 100644 index 0000000..6208c32 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme new file mode 100644 index 0000000..968a5eb --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme new file mode 100644 index 0000000..3915f21 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme new file mode 100644 index 0000000..e0d0094 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme new file mode 100644 index 0000000..827acbf --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme new file mode 100644 index 0000000..64e04ef --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreasTests.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme new file mode 100644 index 0000000..d1487d6 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme new file mode 100644 index 0000000..b199804 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme new file mode 100644 index 0000000..2183889 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..d1d2d68 --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,144 @@ + + + + + SchemeUserState + + Firebase.xcscheme + + isShown + + orderHint + 8 + + FirebaseAnalytics.xcscheme + + isShown + + orderHint + 9 + + FirebaseAuthInterop.xcscheme + + isShown + + orderHint + 10 + + FirebaseCore.xcscheme + + isShown + + orderHint + 11 + + FirebaseCoreDiagnostics.xcscheme + + isShown + + orderHint + 12 + + FirebaseCoreDiagnosticsInterop.xcscheme + + isShown + + orderHint + 13 + + FirebaseDatabase.xcscheme + + isShown + + orderHint + 14 + + FirebaseInstallations.xcscheme + + isShown + + orderHint + 15 + + FirebaseInstanceID.xcscheme + + isShown + + orderHint + 16 + + GoogleAppMeasurement.xcscheme + + isShown + + orderHint + 17 + + GoogleDataTransport.xcscheme + + isShown + + orderHint + 18 + + GoogleDataTransportCCTSupport.xcscheme + + isShown + + orderHint + 19 + + GoogleUtilities.xcscheme + + isShown + + orderHint + 20 + + Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme + + isShown + + orderHint + 24 + + Pods-PediatricPancreas.xcscheme + + isShown + + orderHint + 23 + + Pods-PediatricPancreasTests.xcscheme + + isShown + + orderHint + 25 + + PromisesObjC.xcscheme + + isShown + + orderHint + 26 + + leveldb-library.xcscheme + + isShown + + orderHint + 21 + + nanopb.xcscheme + + isShown + + orderHint + 22 + + + SuppressBuildableAutocreation + + + diff --git a/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..e55df1c --- /dev/null +++ b/PediatricPancreas/Pods/Pods.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,104 @@ + + + + + SchemeUserState + + Firebase.xcscheme_^#shared#^_ + + orderHint + 9 + + FirebaseAnalytics.xcscheme_^#shared#^_ + + orderHint + 10 + + FirebaseAuthInterop.xcscheme_^#shared#^_ + + orderHint + 11 + + FirebaseCore.xcscheme_^#shared#^_ + + orderHint + 12 + + FirebaseCoreDiagnostics.xcscheme_^#shared#^_ + + orderHint + 13 + + FirebaseCoreDiagnosticsInterop.xcscheme_^#shared#^_ + + orderHint + 14 + + FirebaseDatabase.xcscheme_^#shared#^_ + + orderHint + 15 + + FirebaseInstallations.xcscheme_^#shared#^_ + + orderHint + 16 + + FirebaseInstanceID.xcscheme_^#shared#^_ + + orderHint + 17 + + GoogleAppMeasurement.xcscheme_^#shared#^_ + + orderHint + 18 + + GoogleDataTransport.xcscheme_^#shared#^_ + + orderHint + 19 + + GoogleDataTransportCCTSupport.xcscheme_^#shared#^_ + + orderHint + 20 + + GoogleUtilities.xcscheme_^#shared#^_ + + orderHint + 21 + + Pods-PediatricPancreas-PediatricPancreasUITests.xcscheme_^#shared#^_ + + orderHint + 25 + + Pods-PediatricPancreas.xcscheme_^#shared#^_ + + orderHint + 24 + + Pods-PediatricPancreasTests.xcscheme_^#shared#^_ + + orderHint + 26 + + PromisesObjC.xcscheme_^#shared#^_ + + orderHint + 27 + + leveldb-library.xcscheme_^#shared#^_ + + orderHint + 22 + + nanopb.xcscheme_^#shared#^_ + + orderHint + 23 + + + + diff --git a/PediatricPancreas/Pods/PromisesObjC/LICENSE b/PediatricPancreas/Pods/PromisesObjC/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas/Pods/PromisesObjC/README.md b/PediatricPancreas/Pods/PromisesObjC/README.md new file mode 100644 index 0000000..0eecbb1 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/README.md @@ -0,0 +1,60 @@ +[![Apache +License](https://img.shields.io/github/license/google/promises.svg)](LICENSE) +[![Travis](https://api.travis-ci.org/google/promises.svg?branch=master)](https://travis-ci.org/google/promises) +[![Gitter Chat](https://badges.gitter.im/google/promises.svg)](https://gitter.im/google/promises) + +![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-blue.svg?longCache=true&style=flat) +![Languages](https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg?longCache=true&style=flat) +![Package Managers](https://img.shields.io/badge/supports-Bazel%20%7C%20SwiftPM%20%7C%20CocoaPods%20%7C%20Carthage-yellow.svg?longCache=true&style=flat) + +# Promises + +Promises is a modern framework that provides a synchronization construct for +Objective-C and Swift to facilitate writing asynchronous code. + +* [Introduction](g3doc/index.md) + * [The problem with async + code](g3doc/index.md#the-problem-with-async-code) + * [Promises to the rescue](g3doc/index.md#promises-to-the-rescue) + * [What is a promise?](g3doc/index.md#what-is-a-promise) +* [Framework](g3doc/index.md#framework) + * [Features](g3doc/index.md#features) + * [Benchmark](g3doc/index.md#benchmark) +* [Getting started](g3doc/index.md#getting-started) + * [Add dependency](g3doc/index.md#add-dependency) + * [Import](g3doc/index.md#import) + * [Adopt](g3doc/index.md#adopt) +* [Basics](g3doc/index.md#basics) + * [Creating promises](g3doc/index.md#creating-promises) + * [Async](g3doc/index.md#async) + * [Do](g3doc/index.md#do) + * [Pending](g3doc/index.md#pending) + * [Resolved](g3doc/index.md#create-a-resolved-promise) + * [Observing fulfillment](g3doc/index.md#observing-fulfillment) + * [Then](g3doc/index.md#then) + * [Observing rejection](g3doc/index.md#observing-rejection) + * [Catch](g3doc/index.md#catch) +* [Extensions](g3doc/index.md#extensions) + * [All](g3doc/index.md#all) + * [Always](g3doc/index.md#always) + * [Any](g3doc/index.md#any) + * [Await](g3doc/index.md#await) + * [Delay](g3doc/index.md#delay) + * [Race](g3doc/index.md#race) + * [Recover](g3doc/index.md#recover) + * [Reduce](g3doc/index.md#reduce) + * [Retry](g3doc/index.md#retry) + * [Timeout](g3doc/index.md#timeout) + * [Validate](g3doc/index.md#validate) + * [Wrap](g3doc/index.md#wrap) +* [Advanced topics](g3doc/index.md#advanced-topics) + * [Default dispatch queue](g3doc/index.md#default-dispatch-queue) + * [Ownership and retain + cycles](g3doc/index.md#ownership-and-retain-cycles) + * [Testing](g3doc/index.md#testing) + * [Objective-C <-> Swift + interoperability](g3doc/index.md#objective-c---swift-interoperability) + * [Dot-syntax in Objective-C](g3doc/index.md#dot-syntax-in-objective-c) +* [Anti-patterns](g3doc/index.md#anti-patterns) + * [Broken chain](g3doc/index.md#broken-chain) + * [Nested promises](g3doc/index.md#nested-promises) diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m new file mode 100644 index 0000000..c21f30e --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m @@ -0,0 +1,86 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AllAdditions) + ++ (FBLPromise *)all:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue all:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue all:(NSArray *)allPromises { + NSParameterAssert(queue); + NSParameterAssert(allPromises); + + if (allPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [allPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else if ([promise isKindOfClass:[NSError class]]) { + reject(promise); + return; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are fulfilled. + for (FBLPromise *promise in promises) { + if (!promise.isFulfilled) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill([promises valueForKey:NSStringFromSelector(@selector(value))]); + } + reject:^(NSError *error) { + reject(error); + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all { + return ^(NSArray *promises) { + return [self all:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue all:promises]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m new file mode 100644 index 0000000..6927442 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m @@ -0,0 +1,58 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Always.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AlwaysAdditions) + +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue always:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue always:(FBLPromiseAlwaysWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue + chainedFulfill:^id(id value) { + work(); + return value; + } + chainedReject:^id(NSError *error) { + work(); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AlwaysAdditions) + +- (FBLPromise * (^)(FBLPromiseAlwaysWorkBlock))always { + return ^(FBLPromiseAlwaysWorkBlock work) { + return [self always:work]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn { + return ^(dispatch_queue_t queue, FBLPromiseAlwaysWorkBlock work) { + return [self onQueue:queue always:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m new file mode 100644 index 0000000..e101c98 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m @@ -0,0 +1,112 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Any.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +static NSArray *FBLPromiseCombineValuesAndErrors(NSArray *promises) { + NSMutableArray *combinedValuesAndErrors = [[NSMutableArray alloc] init]; + for (FBLPromise *promise in promises) { + if (promise.isFulfilled) { + [combinedValuesAndErrors addObject:promise.value ?: [NSNull null]]; + continue; + } + if (promise.isRejected) { + [combinedValuesAndErrors addObject:promise.error]; + continue; + } + assert(!promise.isPending); + }; + return combinedValuesAndErrors; +} + +@implementation FBLPromise (AnyAdditions) + ++ (FBLPromise *)any:(NSArray *)promises { + return [self onQueue:FBLPromise.defaultDispatchQueue any:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue any:(NSArray *)anyPromises { + NSParameterAssert(queue); + NSParameterAssert(anyPromises); + + if (anyPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [anyPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are resolved. + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } + reject:^(NSError *error) { + BOOL atLeastOneIsFulfilled = NO; + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + if (promise.isFulfilled) { + atLeastOneIsFulfilled = YES; + } + } + if (atLeastOneIsFulfilled) { + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } else { + reject(error); + } + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any { + return ^(NSArray *promises) { + return [self any:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue any:promises]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m new file mode 100644 index 0000000..249158c --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m @@ -0,0 +1,70 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Async.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AsyncAdditions) + ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue async:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue async:(FBLPromiseAsyncWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + work( + ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }, + ^(NSError *error) { + [promise reject:error]; + }); + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async { + return ^(FBLPromiseAsyncWorkBlock work) { + return [self async:work]; + }; +} + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn { + return ^(dispatch_queue_t queue, FBLPromiseAsyncWorkBlock work) { + return [self onQueue:queue async:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m new file mode 100644 index 0000000..ea3b87a --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m @@ -0,0 +1,48 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Await.h" + +#import "FBLPromisePrivate.h" + +id __nullable FBLPromiseAwait(FBLPromise *promise, NSError **outError) { + assert(promise); + + static dispatch_once_t onceToken; + static dispatch_queue_t queue; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.FBLPromises.Await", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + id __block resolution; + NSError __block *blockError; + [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + resolution = value; + dispatch_semaphore_signal(semaphore); + return value; + } + chainedReject:^id(NSError *error) { + blockError = error; + dispatch_semaphore_signal(semaphore); + return error; + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if (outError) { + *outError = blockError; + } + return resolution; +} diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m new file mode 100644 index 0000000..25e8ce6 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Catch.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (CatchAdditions) + +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject { + return [self onQueue:FBLPromise.defaultDispatchQueue catch:reject]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue catch:(FBLPromiseCatchWorkBlock)reject { + NSParameterAssert(queue); + NSParameterAssert(reject); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + reject(error); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch { + return ^(FBLPromiseCatchWorkBlock catch) { + return [self catch:catch]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn { + return ^(dispatch_queue_t queue, FBLPromiseCatchWorkBlock catch) { + return [self onQueue:queue catch:catch]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m new file mode 100644 index 0000000..ce94c33 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Delay.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DelayAdditions) + +- (FBLPromise *)delay:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue delay:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue delay:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + [promise fulfill:value]; + }); + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay { + return ^(NSTimeInterval interval) { + return [self delay:interval]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue delay:interval]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m new file mode 100644 index 0000000..eb7e10d --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Do.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DoAdditions) + ++ (instancetype)do:(FBLPromiseDoWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue do:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DoAdditions) + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn { + return ^(dispatch_queue_t queue, FBLPromiseDoWorkBlock work) { + return [self onQueue:queue do:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m new file mode 100644 index 0000000..b5bd9f1 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m @@ -0,0 +1,65 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Race.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RaceAdditions) + ++ (instancetype)race:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue race:promises]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)racePromises { + NSParameterAssert(queue); + NSAssert(racePromises.count > 0, @"No promises to observe"); + + NSArray *promises = [racePromises copy]; + return [FBLPromise onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (id promise in promises) { + if (![promise isKindOfClass:self]) { + fulfill(promise); + return; + } + } + // Subscribe all, but only the first one to resolve will change + // the resulting promise's state. + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue fulfill:fulfill reject:reject]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race { + return ^(NSArray *promises) { + return [self race:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue race:promises]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m new file mode 100644 index 0000000..0c9326a --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Recover.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RecoverAdditions) + +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery { + return [self onQueue:FBLPromise.defaultDispatchQueue recover:recovery]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue recover:(FBLPromiseRecoverWorkBlock)recovery { + NSParameterAssert(queue); + NSParameterAssert(recovery); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + return recovery(error); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover { + return ^(FBLPromiseRecoverWorkBlock recovery) { + return [self recover:recovery]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn { + return ^(dispatch_queue_t queue, FBLPromiseRecoverWorkBlock recovery) { + return [self onQueue:queue recover:recovery]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m new file mode 100644 index 0000000..1f3fc50 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m @@ -0,0 +1,61 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Reduce.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ReduceAdditions) + +- (FBLPromise *)reduce:(NSArray *)items combine:(FBLPromiseReducerBlock)reducer { + return [self onQueue:FBLPromise.defaultDispatchQueue reduce:items combine:reducer]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer { + NSParameterAssert(queue); + NSParameterAssert(items); + NSParameterAssert(reducer); + + FBLPromise *promise = self; + for (id item in items) { + promise = [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + return reducer(value, item); + } + chainedReject:nil]; + } + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce { + return ^(NSArray *items, FBLPromiseReducerBlock reducer) { + return [self reduce:items combine:reducer]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn { + return ^(dispatch_queue_t queue, NSArray *items, FBLPromiseReducerBlock reducer) { + return [self onQueue:queue reduce:items combine:reducer]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m new file mode 100644 index 0000000..37c5576 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m @@ -0,0 +1,128 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Retry.h" + +#import "FBLPromisePrivate.h" + +NSInteger const FBLPromiseRetryDefaultAttemptsCount = 1; +NSTimeInterval const FBLPromiseRetryDefaultDelayInterval = 1.0; + +static void FBLPromiseRetryAttempt(FBLPromise *promise, dispatch_queue_t queue, NSInteger count, + NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + __auto_type retrier = ^(id __nullable value) { + if ([value isKindOfClass:[NSError class]]) { + if (count <= 0 || (predicate && !predicate(count, value))) { + [promise reject:value]; + } else { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + FBLPromiseRetryAttempt(promise, queue, count - 1, interval, predicate, work); + }); + } + } else { + [promise fulfill:value]; + } + }; + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue fulfill:retrier reject:retrier]; + } else { + retrier(value); + } +} + +@implementation FBLPromise (RetryAdditions) + ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue attempts:FBLPromiseRetryDefaultAttemptsCount retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue attempts:count retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue + attempts:count + delay:FBLPromiseRetryDefaultDelayInterval + condition:nil + retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue + attempts:count + delay:interval + condition:predicate + retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + FBLPromiseRetryAttempt(promise, queue, count, interval, predicate, work); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry { + return ^id(FBLPromiseRetryWorkBlock work) { + return [self retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn { + return ^id(dispatch_queue_t queue, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue retry:work]; + }; +} + ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgain { + return ^id(NSInteger count, NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + return [self attempts:count delay:interval condition:predicate retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgainOn { + return ^id(dispatch_queue_t queue, NSInteger count, NSTimeInterval interval, + FBLPromiseRetryPredicateBlock predicate, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue attempts:count delay:interval condition:predicate retry:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m new file mode 100644 index 0000000..27e8e6c --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m @@ -0,0 +1,56 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) { + BOOL isTimedOut = NO; + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout]; + static NSTimeInterval const minimalTimeout = 0.01; + static int64_t const minimalTimeToWait = (int64_t)(minimalTimeout * NSEC_PER_SEC); + dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, minimalTimeToWait); + dispatch_group_t dispatchGroup = FBLPromise.dispatchGroup; + NSRunLoop *runLoop = NSRunLoop.currentRunLoop; + while (dispatch_group_wait(dispatchGroup, waitTime)) { + isTimedOut = timeoutDate.timeIntervalSinceNow < 0.0; + if (isTimedOut) { + break; + } + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:minimalTimeout]]; + } + return !isTimedOut; +} + +@implementation FBLPromise (TestingAdditions) + +// These properties are implemented in the FBLPromise class itself. +@dynamic isPending; +@dynamic isFulfilled; +@dynamic isRejected; +@dynamic pendingObjects; +@dynamic value; +@dynamic error; + ++ (dispatch_group_t)dispatchGroup { + static dispatch_group_t gDispatchGroup; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gDispatchGroup = dispatch_group_create(); + }); + return gDispatchGroup; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m new file mode 100644 index 0000000..ab03bd1 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m @@ -0,0 +1,50 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Then.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ThenAdditions) + +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue then:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue then:(FBLPromiseThenWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue chainedFulfill:work chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then { + return ^(FBLPromiseThenWorkBlock work) { + return [self then:work]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn { + return ^(dispatch_queue_t queue, FBLPromiseThenWorkBlock work) { + return [self onQueue:queue then:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m new file mode 100644 index 0000000..a2252e6 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m @@ -0,0 +1,64 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Timeout.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (TimeoutAdditions) + +- (FBLPromise *)timeout:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue timeout:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue timeout:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + typeof(self) __weak weakPromise = promise; + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + NSError *timedOutError = [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeTimedOut + userInfo:nil]; + [weakPromise reject:timedOutError]; + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout { + return ^(NSTimeInterval interval) { + return [self timeout:interval]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue timeout:interval]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m new file mode 100644 index 0000000..1e21e81 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m @@ -0,0 +1,56 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Validate.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ValidateAdditions) + +- (FBLPromise*)validate:(FBLPromiseValidateWorkBlock)predicate { + return [self onQueue:FBLPromise.defaultDispatchQueue validate:predicate]; +} + +- (FBLPromise*)onQueue:(dispatch_queue_t)queue validate:(FBLPromiseValidateWorkBlock)predicate { + NSParameterAssert(queue); + NSParameterAssert(predicate); + + FBLPromiseChainedFulfillBlock chainedFulfill = ^id(id value) { + return predicate(value) ? value : + [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }; + return [self chainOnQueue:queue chainedFulfill:chainedFulfill chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ValidateAdditions) + +- (FBLPromise* (^)(FBLPromiseValidateWorkBlock))validate { + return ^(FBLPromiseValidateWorkBlock predicate) { + return [self validate:predicate]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn { + return ^(dispatch_queue_t queue, FBLPromiseValidateWorkBlock predicate) { + return [self onQueue:queue validate:predicate]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m new file mode 100644 index 0000000..3d3341e --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m @@ -0,0 +1,420 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Wrap.h" + +#import "FBLPromise+Async.h" + +@implementation FBLPromise (WrapAdditions) + ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^{ + fulfill(nil); + }); + }]; +} + ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(id __nullable value) { + fulfill(value); + }); + }]; +} + ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(nil); + } + }); + }]; +} + ++ (instancetype)wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectOrErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (instancetype)wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorOrObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error, id __nullable value) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (FBLPromise *)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrap2ObjectsOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value1, id __nullable value2, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@[ value1, value2 ]); + } + }); + }]; +} + ++ (FBLPromise *)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(BOOL value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(BOOL value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(NSInteger value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSInteger value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:(dispatch_queue_t)queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(double value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(double value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_WrapAdditions) + ++ (FBLPromise * (^)(void (^)(FBLPromiseCompletion)))wrapCompletion { + return ^(void (^work)(FBLPromiseCompletion)) { + return [self wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseCompletion)) { + return [self onQueue:queue wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion { + return ^(void (^work)(FBLPromiseObjectCompletion)) { + return [self wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectCompletion)) { + return [self onQueue:queue wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion { + return ^(void (^work)(FBLPromiseErrorCompletion)) { + return [self wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorCompletion)) { + return [self onQueue:queue wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion { + return ^(void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self onQueue:queue wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion { + return ^(void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self onQueue:queue wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion { + return ^(void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self onQueue:queue wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion { + return ^(void (^work)(FBLPromiseBoolCompletion)) { + return [self wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolCompletion)) { + return [self onQueue:queue wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletion { + return ^(void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self onQueue:queue wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion { + return ^(void (^work)(FBLPromiseIntegerCompletion)) { + return [self wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerCompletion)) { + return [self onQueue:queue wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion { + return ^(void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self onQueue:queue wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion { + return ^(void (^work)(FBLPromiseDoubleCompletion)) { + return [self wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleCompletion)) { + return [self onQueue:queue wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion { + return ^(void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self wrapDoubleOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self onQueue:queue wrapDoubleOrErrorCompletion:work]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m new file mode 100644 index 0000000..0837b04 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m @@ -0,0 +1,297 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromisePrivate.h" + +/** All states a promise can be in. */ +typedef NS_ENUM(NSInteger, FBLPromiseState) { + FBLPromiseStatePending = 0, + FBLPromiseStateFulfilled, + FBLPromiseStateRejected, +}; + +typedef void (^FBLPromiseObserver)(FBLPromiseState state, id __nullable resolution); + +static dispatch_queue_t gFBLPromiseDefaultDispatchQueue; + +@implementation FBLPromise { + /** Current state of the promise. */ + FBLPromiseState _state; + /** + Set of arbitrary objects to keep strongly while the promise is pending. + Becomes nil after the promise has been resolved. + */ + NSMutableSet *__nullable _pendingObjects; + /** + Value to fulfill the promise with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ + id __nullable _value; + /** + Error to reject the promise with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ + NSError *__nullable _error; + /** List of observers to notify when the promise gets resolved. */ + NSMutableArray *_observers; +} + ++ (void)initialize { + if (self == [FBLPromise class]) { + gFBLPromiseDefaultDispatchQueue = dispatch_get_main_queue(); + } +} + ++ (dispatch_queue_t)defaultDispatchQueue { + @synchronized(self) { + return gFBLPromiseDefaultDispatchQueue; + } +} + ++ (void)setDefaultDispatchQueue:(dispatch_queue_t)queue { + NSParameterAssert(queue); + + @synchronized(self) { + gFBLPromiseDefaultDispatchQueue = queue; + } +} + ++ (instancetype)pendingPromise { + return [[self alloc] initPending]; +} + ++ (instancetype)resolvedWith:(nullable id)resolution { + return [[self alloc] initWithResolution:resolution]; +} + +- (void)fulfill:(nullable id)value { + if ([value isKindOfClass:[NSError class]]) { + [self reject:(NSError *)value]; + } else { + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateFulfilled; + _value = value; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _value); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } + } +} + +- (void)reject:(NSError *)error { + NSAssert([error isKindOfClass:[NSError class]], @"Invalid error type."); + + if (![error isKindOfClass:[NSError class]]) { + // Give up on invalid error type in Release mode. + @throw error; // NOLINT + } + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateRejected; + _error = error; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _error); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } +} + +#pragma mark - NSObject + +- (NSString *)description { + if (self.isFulfilled) { + return [NSString stringWithFormat:@"<%@ %p> Fulfilled: %@", NSStringFromClass([self class]), + self, self.value]; + } + if (self.isRejected) { + return [NSString stringWithFormat:@"<%@ %p> Rejected: %@", NSStringFromClass([self class]), + self, self.error]; + } + return [NSString stringWithFormat:@"<%@ %p> Pending", NSStringFromClass([self class]), self]; +} + +#pragma mark - Private + +- (instancetype)initPending { + self = [super init]; + if (self) { + dispatch_group_enter(FBLPromise.dispatchGroup); + } + return self; +} + +- (instancetype)initWithResolution:(nullable id)resolution { + self = [super init]; + if (self) { + if ([resolution isKindOfClass:[NSError class]]) { + _state = FBLPromiseStateRejected; + _error = (NSError *)resolution; + } else { + _state = FBLPromiseStateFulfilled; + _value = resolution; + } + } + return self; +} + +- (void)dealloc { + if (_state == FBLPromiseStatePending) { + dispatch_group_leave(FBLPromise.dispatchGroup); + } +} + +- (BOOL)isPending { + @synchronized(self) { + return _state == FBLPromiseStatePending; + } +} + +- (BOOL)isFulfilled { + @synchronized(self) { + return _state == FBLPromiseStateFulfilled; + } +} + +- (BOOL)isRejected { + @synchronized(self) { + return _state == FBLPromiseStateRejected; + } +} + +- (nullable id)value { + @synchronized(self) { + return _value; + } +} + +- (NSError *__nullable)error { + @synchronized(self) { + return _error; + } +} + +- (NSMutableSet *__nullable)pendingObjects { + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + if (!_pendingObjects) { + _pendingObjects = [[NSMutableSet alloc] init]; + } + } + return _pendingObjects; + } +} + +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject { + NSParameterAssert(queue); + NSParameterAssert(onFulfill); + NSParameterAssert(onReject); + + @synchronized(self) { + switch (_state) { + case FBLPromiseStatePending: { + if (!_observers) { + _observers = [[NSMutableArray alloc] init]; + } + [_observers addObject:^(FBLPromiseState state, id __nullable resolution) { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + switch (state) { + case FBLPromiseStatePending: + break; + case FBLPromiseStateFulfilled: + onFulfill(resolution); + break; + case FBLPromiseStateRejected: + onReject(resolution); + break; + } + }); + }]; + break; + } + case FBLPromiseStateFulfilled: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onFulfill(self->_value); + }); + break; + } + case FBLPromiseStateRejected: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onReject(self->_error); + }); + break; + } + } + } +} + +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + __auto_type resolver = ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + value = chainedFulfill ? chainedFulfill(value) : value; + resolver(value); + } + reject:^(NSError *error) { + id value = chainedReject ? chainedReject(error) : error; + resolver(value); + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntaxAdditions) + ++ (instancetype (^)(void))pending { + return ^(void) { + return [self pendingPromise]; + }; +} + ++ (instancetype (^)(id __nullable))resolved { + return ^(id resolution) { + return [self resolvedWith:resolution]; + }; +} + +@end diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m new file mode 100644 index 0000000..1cc181a --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m @@ -0,0 +1,19 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NSErrorDomain const FBLPromiseErrorDomain = @"com.google.FBLPromises.Error"; diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h new file mode 100644 index 0000000..9c0090e --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AllAdditions) + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)all:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected FBLPromise correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + all:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `all` operators. + Usage: FBLPromise.all(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h new file mode 100644 index 0000000..13000f5 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AlwaysAdditions) + +typedef void (^FBLPromiseAlwaysWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to dispatch on. + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + always:(FBLPromiseAlwaysWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `always` operators. + Usage: promise.always(^{...}) + */ +@interface FBLPromise(DotSyntax_AlwaysAdditions) + +- (FBLPromise* (^)(FBLPromiseAlwaysWorkBlock))always FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h new file mode 100644 index 0000000..82875bf --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h @@ -0,0 +1,69 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AnyAdditions) + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSErrors`, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)any:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSError`s, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + any:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `any` operators. + Usage: FBLPromise.any(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h new file mode 100644 index 0000000..0588a9e --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AsyncAdditions) + +typedef void (^FBLPromiseFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseAsyncWorkBlock)(FBLPromiseFulfillBlock fulfill, + FBLPromiseRejectBlock reject) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + async:(FBLPromiseAsyncWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `async` operators. + Usage: FBLPromise.async(^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { ... }) + */ +@interface FBLPromise(DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h new file mode 100644 index 0000000..c97a1ba --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for promise resolution. The current thread blocks until the promise is resolved. + + @param promise Promise to wait for. + @param error Error the promise was rejected with, or `nil` if the promise was fulfilled. + @return Value the promise was fulfilled with. If the promise was rejected, the return value + is always `nil`, but the error out arg is not. + */ +FOUNDATION_EXTERN id __nullable FBLPromiseAwait(FBLPromise *promise, + NSError **error) NS_REFINED_FOR_SWIFT; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h new file mode 100644 index 0000000..a9ff170 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(CatchAdditions) + +typedef void (^FBLPromiseCatchWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously. + + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously on the given queue. + + @param queue A queue to invoke the `reject` block on. + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + catch:(FBLPromiseCatchWorkBlock)reject NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `catch` operators. + Usage: promise.catch(^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h new file mode 100644 index 0000000..557df48 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DelayAdditions) + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)delay:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + delay:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `delay` operators. + Usage: promise.delay(...) + */ +@interface FBLPromise(DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h new file mode 100644 index 0000000..6838e0a --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DoAdditions) + +typedef id __nullable (^FBLPromiseDoWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)do:(FBLPromiseDoWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `do` operators. + Usage: FBLPromise.doOn(queue, ^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_DoAdditions) + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h new file mode 100644 index 0000000..2f67258 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h @@ -0,0 +1,62 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RaceAdditions) + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)race:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `race` operators. + Usage: FBLPromise.race(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h new file mode 100644 index 0000000..bb7df7e --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RecoverAdditions) + +typedef id __nullable (^FBLPromiseRecoverWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param queue A queue to dispatch on. + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + recover:(FBLPromiseRecoverWorkBlock)recovery NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `recover` operators. + Usage: promise.recover(^id(NSError *error) {...}) + */ +@interface FBLPromise(DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h new file mode 100644 index 0000000..5bb1eee --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h @@ -0,0 +1,71 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ReduceAdditions) + +typedef id __nullable (^FBLPromiseReducerBlock)(Value __nullable partial, id next) + NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param queue A queue to dispatch on. + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `reduce` operators. + Usage: promise.reduce(values, ^id(id partial, id next) { ... }) + */ +@interface FBLPromise(DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h new file mode 100644 index 0000000..98ef558 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h @@ -0,0 +1,165 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** The default number of retry attempts is 1. */ +FOUNDATION_EXTERN NSInteger const FBLPromiseRetryDefaultAttemptsCount NS_REFINED_FOR_SWIFT; + +/** The default delay interval before making a retry attempt is 1.0 second. */ +FOUNDATION_EXTERN NSTimeInterval const FBLPromiseRetryDefaultDelayInterval NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(RetryAdditions) + +typedef id __nullable (^FBLPromiseRetryWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); +typedef BOOL (^FBLPromiseRetryPredicateBlock)(NSInteger, NSError *) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on rejection where the + `work` block is retried after a delay of `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on + rejection where the `work` block is retried on the given `queue` after a delay of + `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param queue A queue to invoke the `work` block on. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. On rejection, the `work` block is retried after the given delay `interval` and will + continue to retry until the number of specified attempts have been exhausted or will bail early if + the given condition is not met. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. On rejection, the `work` block is retried after the given + delay `interval` and will continue to retry until the number of specified attempts have been + exhausted or will bail early if the given condition is not met. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise+Retry` operators. + Usage: FBLPromise.retry(^id { ... }) + */ +@interface FBLPromise(DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgain FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, + FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgainOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h new file mode 100644 index 0000000..07a65ec --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for all scheduled promises blocks. + + @param timeout Maximum time to wait. + @return YES if all promises blocks have completed before the timeout and NO otherwise. + */ +FOUNDATION_EXTERN BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(TestingAdditions) + +/** + Dispatch group for promises that is typically used to wait for all scheduled blocks. + */ +@property(class, nonatomic, readonly) dispatch_group_t dispatchGroup NS_REFINED_FOR_SWIFT; + +/** + Properties to get the current state of the promise. + */ +@property(nonatomic, readonly) BOOL isPending NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isFulfilled NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isRejected NS_REFINED_FOR_SWIFT; + +/** + Set of arbitrary objects to keep strongly while the promise is pending. + Becomes nil after the promise has been resolved. + */ +@property(nonatomic, readonly, nullable) NSMutableSet *pendingObjects NS_REFINED_FOR_SWIFT; + +/** + Value the promise was fulfilled with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ +@property(nonatomic, readonly, nullable) Value value NS_REFINED_FOR_SWIFT; + +/** + Error the promise was rejected with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ +@property(nonatomic, readonly, nullable) NSError *error NS_REFINED_FOR_SWIFT; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h new file mode 100644 index 0000000..32027e6 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ThenAdditions) + +typedef id __nullable (^FBLPromiseThenWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously only + when the receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with + the same error. + + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously when the + receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with the same + error. + + @param queue A queue to invoke the `work` block on. + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + then:(FBLPromiseThenWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `then` operators. + Usage: promise.then(^id(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h new file mode 100644 index 0000000..184ba16 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h @@ -0,0 +1,57 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(TimeoutAdditions) + +/** + Waits for a promise with the specified `timeout`. + + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)timeout:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Waits for a promise with the specified `timeout`. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + timeout:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `timeout` operators. + Usage: promise.timeout(...) + */ +@interface FBLPromise(DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h new file mode 100644 index 0000000..9dfa2f1 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ValidateAdditions) + +typedef BOOL (^FBLPromiseValidateWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)validate:(FBLPromiseValidateWorkBlock)predicate NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param queue A queue to dispatch on. + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + validate:(FBLPromiseValidateWorkBlock)predicate NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `validate` operators. + Usage: promise.validate(^BOOL(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ValidateAdditions) + +- (FBLPromise * (^)(FBLPromiseValidateWorkBlock))validate FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h new file mode 100644 index 0000000..664e1bb --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h @@ -0,0 +1,316 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Different types of completion handlers available to be wrapped with promise. + */ +typedef void (^FBLPromiseCompletion)(void) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectCompletion)(id __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorCompletion)(NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectOrErrorCompletion)(id __nullable, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorOrObjectCompletion)(NSError* __nullable, id __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromise2ObjectsOrErrorCompletion)(id __nullable, id __nullable, + NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolCompletion)(BOOL) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolOrErrorCompletion)(BOOL, NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerCompletion)(NSInteger) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerOrErrorCompletion)(NSInteger, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleCompletion)(double) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleOrErrorCompletion)(double, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); + +/** + Provides an easy way to convert methods that use common callback patterns into promises. + */ +@interface FBLPromise(WrapAdditions) + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)wrapObjectOrErrorCompletion: + (void (^)(FBLPromiseObjectOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)wrapErrorOrObjectCompletion: + (void (^)(FBLPromiseErrorOrObjectCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `wrap` operators. + Usage: FBLPromise.wrapCompletion(^(FBLPromiseCompletion handler) {...}) + */ +@interface FBLPromise(DotSyntax_WrapAdditions) + ++ (FBLPromise* (^)(void (^)(FBLPromiseCompletion)))wrapCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h new file mode 100644 index 0000000..cec6336 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h @@ -0,0 +1,82 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Promises synchronization construct in Objective-C. + */ +@interface FBLPromise<__covariant Value> : NSObject + +/** + Default dispatch queue used for `FBLPromise`, which is `main` if a queue is not specified. + */ +@property(class) dispatch_queue_t defaultDispatchQueue NS_REFINED_FOR_SWIFT; + +/** + Creates a pending promise. + */ ++ (instancetype)pendingPromise NS_REFINED_FOR_SWIFT; + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ ++ (instancetype)resolvedWith:(nullable id)resolution NS_REFINED_FOR_SWIFT; + +/** + Synchronously fulfills the promise with a value. + + @param value An arbitrary value to fulfill the promise with, including `nil`. + */ +- (void)fulfill:(nullable Value)value NS_REFINED_FOR_SWIFT; + +/** + Synchronously rejects the promise with an error. + + @param error An error to reject the promise with. + */ +- (void)reject:(NSError *)error NS_REFINED_FOR_SWIFT; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@end + +#ifdef FBL_PROMISES_DOT_SYNTAX_IS_DEPRECATED +#define FBL_PROMISES_DOT_SYNTAX __attribute__((deprecated)) +#else +#define FBL_PROMISES_DOT_SYNTAX +#endif + +@interface FBLPromise(DotSyntaxAdditions) + +/** + Convenience dot-syntax wrappers for FBLPromise. + Usage: FBLPromise.pending() + FBLPromise.resolved(value) + + */ ++ (instancetype (^)(void))pending FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (instancetype (^)(id __nullable))resolved FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h new file mode 100644 index 0000000..d37af53 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h @@ -0,0 +1,43 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXTERN NSErrorDomain const FBLPromiseErrorDomain NS_REFINED_FOR_SWIFT; + +/** + Possible error codes in `FBLPromiseErrorDomain`. + */ +typedef NS_ENUM(NSInteger, FBLPromiseErrorCode) { + /** Promise failed to resolve in time. */ + FBLPromiseErrorCodeTimedOut = 1, + /** Validation predicate returned false. */ + FBLPromiseErrorCodeValidationFailure = 2, +} NS_REFINED_FOR_SWIFT; + +NS_INLINE BOOL FBLPromiseErrorIsTimedOut(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeTimedOut; +} + +NS_INLINE BOOL FBLPromiseErrorIsValidationFailure(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeValidationFailure; +} + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h new file mode 100644 index 0000000..7a132f2 --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h @@ -0,0 +1,66 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Miscellaneous low-level private interfaces available to extend standard FBLPromise functionality. + */ +@interface FBLPromise() + +typedef void (^FBLPromiseOnFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseOnRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedFulfillBlock)(Value __nullable value) + NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedRejectBlock)(NSError *error) + NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise. + */ +- (instancetype)initPending NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ +- (instancetype)initWithResolution:(nullable id)resolution NS_SWIFT_UNAVAILABLE(""); + +/** + Invokes `fulfill` and `reject` blocks on `queue` when the receiver gets either fulfilled or + rejected respectively. + */ +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject NS_SWIFT_UNAVAILABLE(""); + +/** + Returns a new promise which gets resolved with the return value of `chainedFulfill` or + `chainedReject` blocks respectively. The blocks are invoked when the receiver gets either + fulfilled or rejected. If `nil` is passed to either block arg, the returned promise is resolved + with the same resolution as the receiver. + */ +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h new file mode 100644 index 0000000..2d90bad --- /dev/null +++ b/PediatricPancreas/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" diff --git a/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig new file mode 100644 index 0000000..b087b1d --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.release.xcconfig new file mode 100644 index 0000000..b087b1d --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.xcconfig b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.xcconfig new file mode 100644 index 0000000..b087b1d --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Firebase/Firebase.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig new file mode 100644 index 0000000..c9dc3f6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig new file mode 100644 index 0000000..c9dc3f6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig new file mode 100644 index 0000000..c9dc3f6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.debug.xcconfig new file mode 100644 index 0000000..316604a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuthInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuthInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.release.xcconfig new file mode 100644 index 0000000..316604a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuthInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuthInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig new file mode 100644 index 0000000..316604a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuthInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuthInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist new file mode 100644 index 0000000..43ee74c --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.6.2 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m new file mode 100644 index 0000000..4f1eb27 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCore : NSObject +@end +@implementation PodsDummy_FirebaseCore +@end diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h new file mode 100644 index 0000000..102aecb --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FirebaseCore.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" + +FOUNDATION_EXPORT double FirebaseCoreVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig new file mode 100644 index 0000000..861154b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.debug.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.6.2 Firebase_VERSION=6.17.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap new file mode 100644 index 0000000..4c38b87 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCore { + umbrella header "FirebaseCore-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig new file mode 100644 index 0000000..861154b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.release.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.6.2 Firebase_VERSION=6.17.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig new file mode 100644 index 0000000..861154b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.6.2 Firebase_VERSION=6.17.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist new file mode 100644 index 0000000..2a9158a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m new file mode 100644 index 0000000..224d263 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCoreDiagnostics : NSObject +@end +@implementation PodsDummy_FirebaseCoreDiagnostics +@end diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h new file mode 100644 index 0000000..d6c0706 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "firebasecore.nanopb.h" + +FOUNDATION_EXPORT double FirebaseCoreDiagnosticsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreDiagnosticsVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig new file mode 100644 index 0000000..08d790f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap new file mode 100644 index 0000000..d9cad8b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCoreDiagnostics { + umbrella header "FirebaseCoreDiagnostics-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig new file mode 100644 index 0000000..08d790f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig new file mode 100644 index 0000000..08d790f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.debug.xcconfig new file mode 100644 index 0000000..66fd960 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.release.xcconfig new file mode 100644 index 0000000..66fd960 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig new file mode 100644 index 0000000..66fd960 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist new file mode 100644 index 0000000..059bf7b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.1.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m new file mode 100644 index 0000000..40813e7 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseDatabase : NSObject +@end +@implementation PodsDummy_FirebaseDatabase +@end diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h new file mode 100644 index 0000000..b9b40ff --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h @@ -0,0 +1,25 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FirebaseDatabase.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +FOUNDATION_EXPORT double FirebaseDatabaseVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseDatabaseVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig new file mode 100644 index 0000000..293f459 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.1.4 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap new file mode 100644 index 0000000..7424a95 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseDatabase { + umbrella header "FirebaseDatabase-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig new file mode 100644 index 0000000..293f459 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.1.4 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig new file mode 100644 index 0000000..293f459 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.1.4 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist new file mode 100644 index 0000000..21a30b4 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m new file mode 100644 index 0000000..ae19551 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstallations : NSObject +@end +@implementation PodsDummy_FirebaseInstallations +@end diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h new file mode 100644 index 0000000..78e5979 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstallations.h" +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" + +FOUNDATION_EXPORT double FirebaseInstallationsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstallationsVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig new file mode 100644 index 0000000..bf477db --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.1.0 FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap new file mode 100644 index 0000000..f6e2a29 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstallations { + umbrella header "FirebaseInstallations-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig new file mode 100644 index 0000000..bf477db --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.1.0 FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig new file mode 100644 index 0000000..bf477db --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.1.0 FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist new file mode 100644 index 0000000..33563de --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.3.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m new file mode 100644 index 0000000..937a03d --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstanceID : NSObject +@end +@implementation PodsDummy_FirebaseInstanceID +@end diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h new file mode 100644 index 0000000..90ba5de --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstanceID.h" +#import "FIRInstanceID.h" + +FOUNDATION_EXPORT double FirebaseInstanceIDVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstanceIDVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.debug.xcconfig new file mode 100644 index 0000000..f24d49f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstanceID_LIB_VERSION=4.3.1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstanceID +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap new file mode 100644 index 0000000..ff5248f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstanceID { + umbrella header "FirebaseInstanceID-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.release.xcconfig new file mode 100644 index 0000000..f24d49f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstanceID_LIB_VERSION=4.3.1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstanceID +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig new file mode 100644 index 0000000..f24d49f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstanceID_LIB_VERSION=4.3.1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstanceID +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig new file mode 100644 index 0000000..b2e9274 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.debug.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig new file mode 100644 index 0000000..b2e9274 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.release.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig new file mode 100644 index 0000000..b2e9274 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist new file mode 100644 index 0000000..3424ca6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m new file mode 100644 index 0000000..9a08ec3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransport : NSObject +@end +@implementation PodsDummy_GoogleDataTransport +@end diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h new file mode 100644 index 0000000..6b79543 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h @@ -0,0 +1,33 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GDTCORAssert.h" +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCORDataFuture.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPlatform.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORRegistrar.h" +#import "GDTCORStoredEvent.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploader.h" +#import "GDTCORUploadPackage.h" +#import "GoogleDataTransport.h" + +FOUNDATION_EXPORT double GoogleDataTransportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig new file mode 100644 index 0000000..67373ab --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.debug.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=4.0.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap new file mode 100644 index 0000000..8a67414 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransport { + umbrella header "GoogleDataTransport-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig new file mode 100644 index 0000000..67373ab --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.release.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=4.0.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig new file mode 100644 index 0000000..67373ab --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=4.0.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist new file mode 100644 index 0000000..7b6b52a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m new file mode 100644 index 0000000..3c7f556 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransportCCTSupport : NSObject +@end +@implementation PodsDummy_GoogleDataTransportCCTSupport +@end diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h new file mode 100644 index 0000000..7f5ac1c --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "cct.nanopb.h" + +FOUNDATION_EXPORT double GoogleDataTransportCCTSupportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportCCTSupportVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig new file mode 100644 index 0000000..d54ea79 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.debug.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=1.4.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap new file mode 100644 index 0000000..7cec8f0 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransportCCTSupport { + umbrella header "GoogleDataTransportCCTSupport-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig new file mode 100644 index 0000000..d54ea79 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.release.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=1.4.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig new file mode 100644 index 0000000..d54ea79 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=1.4.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist new file mode 100644 index 0000000..07e37a2 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.5.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m new file mode 100644 index 0000000..98ac4e9 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleUtilities : NSObject +@end +@implementation PodsDummy_GoogleUtilities +@end diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h new file mode 100644 index 0000000..508e631 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GULLoggerLevel.h" +#import "GULLoggerCodes.h" +#import "GULNSData+zlib.h" + +FOUNDATION_EXPORT double GoogleUtilitiesVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleUtilitiesVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig new file mode 100644 index 0000000..4604138 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.debug.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap new file mode 100644 index 0000000..491dd0a --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap @@ -0,0 +1,6 @@ +framework module GoogleUtilities { + umbrella header "GoogleUtilities-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig new file mode 100644 index 0000000..4604138 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.release.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig new file mode 100644 index 0000000..4604138 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown new file mode 100644 index 0000000..d65fe28 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.markdown @@ -0,0 +1,2583 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Firebase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseAnalytics + +Copyright 2020 Google + +## FirebaseAuthInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnostics + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnosticsInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseDatabase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstallations + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstanceID + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2020 Google + +## GoogleDataTransport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleDataTransportCCTSupport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog + + +## PromisesObjC + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## leveldb-library + +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Generated by CocoaPods - https://cocoapods.org diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist new file mode 100644 index 0000000..0abd950 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-acknowledgements.plist @@ -0,0 +1,2705 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAuthInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnostics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnosticsInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseDatabase + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstallations + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstanceID + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransportCCTSupport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller <landon@landonf.org> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +<a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev Wiki +Crack Prevention</a>: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at <a href="http://landonf.org/2009/02/index.html">Landon +Fuller's blog</a> + + License + Apache + Title + GoogleUtilities + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + PromisesObjC + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + New BSD + Title + leveldb-library + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m new file mode 100644 index 0000000..628ea02 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PediatricPancreas_PediatricPancreasUITests : NSObject +@end +@implementation PodsDummy_Pods_PediatricPancreas_PediatricPancreasUITests +@end diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-input-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..745ec30 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,5 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-output-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..4dc74c3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,4 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-input-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..745ec30 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,5 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-output-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..4dc74c3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,4 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh new file mode 100755 index 0000000..ef3a79f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-frameworks.sh @@ -0,0 +1,213 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +install_artifact() { + artifact="$1" + base="$(basename "$artifact")" + case $base in + *.framework) + install_framework "$artifact" + ;; + *.dSYM) + # Suppress arch warnings since XCFrameworks will include many dSYM files + install_dsym "$artifact" "false" + ;; + *.bcsymbolmap) + install_bcsymbolmap "$artifact" + ;; + *) + echo "error: Unrecognized artifact "$artifact"" + ;; + esac +} + +copy_artifacts() { + file_list="$1" + while read artifact; do + install_artifact "$artifact" + done <$file_list +} + +ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" +if [ -r "${ARTIFACT_LIST_FILE}" ]; then + copy_artifacts "${ARTIFACT_LIST_FILE}" +fi + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h new file mode 100644 index 0000000..1dcbc3d --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PediatricPancreas_PediatricPancreasUITestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PediatricPancreas_PediatricPancreasUITestsVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig new file mode 100644 index 0000000..c8c8487 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.modulemap b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.modulemap new file mode 100644 index 0000000..4b84104 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PediatricPancreas_PediatricPancreasUITests { + umbrella header "Pods-PediatricPancreas-PediatricPancreasUITests-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig new file mode 100644 index 0000000..c8c8487 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas-PediatricPancreasUITests/Pods-PediatricPancreas-PediatricPancreasUITests.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-Info.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.markdown b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.markdown new file mode 100644 index 0000000..d65fe28 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.markdown @@ -0,0 +1,2583 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Firebase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseAnalytics + +Copyright 2020 Google + +## FirebaseAuthInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnostics + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnosticsInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseDatabase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstallations + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstanceID + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2020 Google + +## GoogleDataTransport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleDataTransportCCTSupport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog + + +## PromisesObjC + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## leveldb-library + +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Generated by CocoaPods - https://cocoapods.org diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.plist new file mode 100644 index 0000000..0abd950 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-acknowledgements.plist @@ -0,0 +1,2705 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAuthInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnostics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnosticsInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseDatabase + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstallations + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstanceID + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransportCCTSupport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller <landon@landonf.org> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +<a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev Wiki +Crack Prevention</a>: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at <a href="http://landonf.org/2009/02/index.html">Landon +Fuller's blog</a> + + License + Apache + Title + GoogleUtilities + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + PromisesObjC + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + New BSD + Title + leveldb-library + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-dummy.m b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-dummy.m new file mode 100644 index 0000000..771fd86 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PediatricPancreas : NSObject +@end +@implementation PodsDummy_Pods_PediatricPancreas +@end diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-input-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..6dfcc6e --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,5 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-output-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..4dc74c3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,4 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-input-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..6dfcc6e --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,5 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-output-files.xcfilelist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..4dc74c3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,4 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh new file mode 100755 index 0000000..ef3a79f --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-frameworks.sh @@ -0,0 +1,213 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + warn_missing_arch=${2:-true} + if [ -r "$source" ]; then + # Copy the dSYM into the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .dSYM "$source")" + binary_name="$(ls "$source/Contents/Resources/DWARF")" + binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" "$warn_missing_arch" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + warn_missing_arch=${2:-true} + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + if [[ "$warn_missing_arch" == "true" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + fi + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + +install_artifact() { + artifact="$1" + base="$(basename "$artifact")" + case $base in + *.framework) + install_framework "$artifact" + ;; + *.dSYM) + # Suppress arch warnings since XCFrameworks will include many dSYM files + install_dsym "$artifact" "false" + ;; + *.bcsymbolmap) + install_bcsymbolmap "$artifact" + ;; + *) + echo "error: Unrecognized artifact "$artifact"" + ;; + esac +} + +copy_artifacts() { + file_list="$1" + while read artifact; do + install_artifact "$artifact" + done <$file_list +} + +ARTIFACT_LIST_FILE="${BUILT_PRODUCTS_DIR}/cocoapods-artifacts-${CONFIGURATION}.txt" +if [ -r "${ARTIFACT_LIST_FILE}" ]; then + copy_artifacts "${ARTIFACT_LIST_FILE}" +fi + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-umbrella.h b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-umbrella.h new file mode 100644 index 0000000..452271c --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PediatricPancreasVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PediatricPancreasVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.debug.xcconfig new file mode 100644 index 0000000..c8c8487 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.modulemap b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.modulemap new file mode 100644 index 0000000..927e712 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PediatricPancreas { + umbrella header "Pods-PediatricPancreas-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.release.xcconfig new file mode 100644 index 0000000..c8c8487 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreas/Pods-PediatricPancreas.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "Foundation" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-Info.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.markdown b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.markdown new file mode 100644 index 0000000..102af75 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.markdown @@ -0,0 +1,3 @@ +# Acknowledgements +This application makes use of the following third party libraries: +Generated by CocoaPods - https://cocoapods.org diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.plist b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.plist new file mode 100644 index 0000000..7acbad1 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-acknowledgements.plist @@ -0,0 +1,29 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-dummy.m b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-dummy.m new file mode 100644 index 0000000..f7e1bb1 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PediatricPancreasTests : NSObject +@end +@implementation PodsDummy_Pods_PediatricPancreasTests +@end diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-umbrella.h b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-umbrella.h new file mode 100644 index 0000000..824ddb3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PediatricPancreasTestsVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PediatricPancreasTestsVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.debug.xcconfig new file mode 100644 index 0000000..3d6a937 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.debug.xcconfig @@ -0,0 +1,9 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "Foundation" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.modulemap b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.modulemap new file mode 100644 index 0000000..ebca4f9 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PediatricPancreasTests { + umbrella header "Pods-PediatricPancreasTests-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.release.xcconfig new file mode 100644 index 0000000..3d6a937 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/Pods-PediatricPancreasTests/Pods-PediatricPancreasTests.release.xcconfig @@ -0,0 +1,9 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "Foundation" -framework "GoogleUtilities" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist new file mode 100644 index 0000000..f5f78f7 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.8 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m new file mode 100644 index 0000000..ab1f210 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PromisesObjC : NSObject +@end +@implementation PodsDummy_PromisesObjC +@end diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h new file mode 100644 index 0000000..5b014a8 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h @@ -0,0 +1,36 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Testing.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" +#import "FBLPromise.h" +#import "FBLPromiseError.h" +#import "FBLPromises.h" + +FOUNDATION_EXPORT double FBLPromisesVersionNumber; +FOUNDATION_EXPORT const unsigned char FBLPromisesVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig new file mode 100644 index 0000000..dac127e --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.debug.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap new file mode 100644 index 0000000..7d485cd --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap @@ -0,0 +1,6 @@ +framework module FBLPromises { + umbrella header "PromisesObjC-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig new file mode 100644 index 0000000..dac127e --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.release.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig new file mode 100644 index 0000000..dac127e --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist new file mode 100644 index 0000000..da1bc00 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.22.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m new file mode 100644 index 0000000..dba1492 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_leveldb_library : NSObject +@end +@implementation PodsDummy_leveldb_library +@end diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h new file mode 100644 index 0000000..6a45902 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h @@ -0,0 +1,31 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "c.h" +#import "cache.h" +#import "comparator.h" +#import "db.h" +#import "dumpfile.h" +#import "env.h" +#import "export.h" +#import "filter_policy.h" +#import "iterator.h" +#import "options.h" +#import "slice.h" +#import "status.h" +#import "table.h" +#import "table_builder.h" +#import "write_batch.h" + +FOUNDATION_EXPORT double leveldbVersionNumber; +FOUNDATION_EXPORT const unsigned char leveldbVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig new file mode 100644 index 0000000..d1992a1 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.debug.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap new file mode 100644 index 0000000..fd77435 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap @@ -0,0 +1,6 @@ +framework module leveldb { + umbrella header "leveldb-library-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig new file mode 100644 index 0000000..d1992a1 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.release.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig new file mode 100644 index 0000000..d1992a1 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-Info.plist b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-Info.plist new file mode 100644 index 0000000..bcc2778 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.3.9011 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-dummy.m b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-dummy.m new file mode 100644 index 0000000..b3fa595 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_nanopb : NSObject +@end +@implementation PodsDummy_nanopb +@end diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-prefix.pch b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-umbrella.h b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-umbrella.h new file mode 100644 index 0000000..07e77b3 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "pb.h" +#import "pb_common.h" +#import "pb_decode.h" +#import "pb_encode.h" +#import "pb.h" +#import "pb_decode.h" +#import "pb_common.h" +#import "pb.h" +#import "pb_encode.h" +#import "pb_common.h" + +FOUNDATION_EXPORT double nanopbVersionNumber; +FOUNDATION_EXPORT const unsigned char nanopbVersionString[]; + diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig new file mode 100644 index 0000000..8e7193b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.debug.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.modulemap b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.modulemap new file mode 100644 index 0000000..e8d4b53 --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.modulemap @@ -0,0 +1,6 @@ +framework module nanopb { + umbrella header "nanopb-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.release.xcconfig b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.release.xcconfig new file mode 100644 index 0000000..8e7193b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.release.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.xcconfig b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.xcconfig new file mode 100644 index 0000000..8e7193b --- /dev/null +++ b/PediatricPancreas/Pods/Target Support Files/nanopb/nanopb.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas/Pods/leveldb-library/LICENSE b/PediatricPancreas/Pods/leveldb-library/LICENSE new file mode 100644 index 0000000..8e80208 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/PediatricPancreas/Pods/leveldb-library/README.md b/PediatricPancreas/Pods/leveldb-library/README.md new file mode 100644 index 0000000..0b660ae --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/README.md @@ -0,0 +1,225 @@ +**LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.** + +[![Build Status](https://travis-ci.org/google/leveldb.svg?branch=master)](https://travis-ci.org/google/leveldb) +[![Build status](https://ci.appveyor.com/api/projects/status/g2j5j4rfkda6eyw5/branch/master?svg=true)](https://ci.appveyor.com/project/pwnall/leveldb) + +Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) + +# Features + + * Keys and values are arbitrary byte arrays. + * Data is stored sorted by key. + * Callers can provide a custom comparison function to override the sort order. + * The basic operations are `Put(key,value)`, `Get(key)`, `Delete(key)`. + * Multiple changes can be made in one atomic batch. + * Users can create a transient snapshot to get a consistent view of data. + * Forward and backward iteration is supported over the data. + * Data is automatically compressed using the [Snappy compression library](http://google.github.io/snappy/). + * External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions. + +# Documentation + + [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code. + +# Limitations + + * This is not a SQL database. It does not have a relational data model, it does not support SQL queries, and it has no support for indexes. + * Only a single process (possibly multi-threaded) can access a particular database at a time. + * There is no client-server support builtin to the library. An application that needs such support will have to wrap their own server around the library. + +# Building + +This project supports [CMake](https://cmake.org/) out of the box. + +### Build for POSIX + +Quick start: + +```bash +mkdir -p build && cd build +cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . +``` + +### Building for Windows + +First generate the Visual Studio 2017 project/solution files: + +```cmd +mkdir build +cd build +cmake -G "Visual Studio 15" .. +``` +The default default will build for x86. For 64-bit run: + +```cmd +cmake -G "Visual Studio 15 Win64" .. +``` + +To compile the Windows solution from the command-line: + +```cmd +devenv /build Debug leveldb.sln +``` + +or open leveldb.sln in Visual Studio and build from within. + +Please see the CMake documentation and `CMakeLists.txt` for more advanced usage. + +# Contributing to the leveldb Project + +The leveldb project welcomes contributions. leveldb's primary goal is to be +a reliable and fast key/value store. Changes that are in line with the +features/limitations outlined above, and meet the requirements below, +will be considered. + +Contribution requirements: + +1. **Tested platforms only**. We _generally_ will only accept changes for + platforms that are compiled and tested. This means POSIX (for Linux and + macOS) or Windows. Very small changes will sometimes be accepted, but + consider that more of an exception than the rule. + +2. **Stable API**. We strive very hard to maintain a stable API. Changes that + require changes for projects using leveldb _might_ be rejected without + sufficient benefit to the project. + +3. **Tests**: All changes must be accompanied by a new (or changed) test, or + a sufficient explanation as to why a new (or changed) test is not required. + +4. **Consistent Style**: This project conforms to the + [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html). + To ensure your changes are properly formatted please run: + + ``` + clang-format -i --style=file + ``` + +## Submitting a Pull Request + +Before any pull request will be accepted the author must first sign a +Contributor License Agreement (CLA) at https://cla.developers.google.com/. + +In order to keep the commit timeline linear +[squash](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Squashing-Commits) +your changes down to a single commit and [rebase](https://git-scm.com/docs/git-rebase) +on google/leveldb/master. This keeps the commit timeline linear and more easily sync'ed +with the internal repository at Google. More information at GitHub's +[About Git rebase](https://help.github.com/articles/about-git-rebase/) page. + +# Performance + +Here is a performance report (with explanations) from the run of the +included db_bench program. The results are somewhat noisy, but should +be enough to get a ballpark performance estimate. + +## Setup + +We use a database with a million entries. Each entry has a 16 byte +key, and a 100 byte value. Values used by the benchmark compress to +about half their original size. + + LevelDB: version 1.1 + Date: Sun May 1 12:11:26 2011 + CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz + CPUCache: 4096 KB + Keys: 16 bytes each + Values: 100 bytes each (50 bytes after compression) + Entries: 1000000 + Raw Size: 110.6 MB (estimated) + File Size: 62.9 MB (estimated) + +## Write performance + +The "fill" benchmarks create a brand new database, in either +sequential, or random order. The "fillsync" benchmark flushes data +from the operating system to the disk after every operation; the other +write operations leave the data sitting in the operating system buffer +cache for a while. The "overwrite" benchmark does random writes that +update existing keys in the database. + + fillseq : 1.765 micros/op; 62.7 MB/s + fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops) + fillrandom : 2.460 micros/op; 45.0 MB/s + overwrite : 2.380 micros/op; 46.5 MB/s + +Each "op" above corresponds to a write of a single key/value pair. +I.e., a random write benchmark goes at approximately 400,000 writes per second. + +Each "fillsync" operation costs much less (0.3 millisecond) +than a disk seek (typically 10 milliseconds). We suspect that this is +because the hard disk itself is buffering the update in its memory and +responding before the data has been written to the platter. This may +or may not be safe based on whether or not the hard disk has enough +power to save its memory in the event of a power failure. + +## Read performance + +We list the performance of reading sequentially in both the forward +and reverse direction, and also the performance of a random lookup. +Note that the database created by the benchmark is quite small. +Therefore the report characterizes the performance of leveldb when the +working set fits in memory. The cost of reading a piece of data that +is not present in the operating system buffer cache will be dominated +by the one or two disk seeks needed to fetch the data from disk. +Write performance will be mostly unaffected by whether or not the +working set fits in memory. + + readrandom : 16.677 micros/op; (approximately 60,000 reads per second) + readseq : 0.476 micros/op; 232.3 MB/s + readreverse : 0.724 micros/op; 152.9 MB/s + +LevelDB compacts its underlying storage data in the background to +improve read performance. The results listed above were done +immediately after a lot of random writes. The results after +compactions (which are usually triggered automatically) are better. + + readrandom : 11.602 micros/op; (approximately 85,000 reads per second) + readseq : 0.423 micros/op; 261.8 MB/s + readreverse : 0.663 micros/op; 166.9 MB/s + +Some of the high cost of reads comes from repeated decompression of blocks +read from disk. If we supply enough cache to the leveldb so it can hold the +uncompressed blocks in memory, the read performance improves again: + + readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) + readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) + +## Repository contents + +See [doc/index.md](doc/index.md) for more explanation. See +[doc/impl.md](doc/impl.md) for a brief overview of the implementation. + +The public interface is in include/*.h. Callers should not include or +rely on the details of any other header files in this package. Those +internal APIs may be changed without warning. + +Guide to header files: + +* **include/db.h**: Main interface to the DB: Start here + +* **include/options.h**: Control over the behavior of an entire database, +and also control over the behavior of individual reads and writes. + +* **include/comparator.h**: Abstraction for user-specified comparison function. +If you want just bytewise comparison of keys, you can use the default +comparator, but clients can write their own comparator implementations if they +want custom ordering (e.g. to handle different character encodings, etc.) + +* **include/iterator.h**: Interface for iterating over data. You can get +an iterator from a DB object. + +* **include/write_batch.h**: Interface for atomically applying multiple +updates to a database. + +* **include/slice.h**: A simple module for maintaining a pointer and a +length into some other byte array. + +* **include/status.h**: Status is returned from many of the public interfaces +and is used to report success and various kinds of errors. + +* **include/env.h**: +Abstraction of the OS environment. A posix implementation of this interface is +in util/env_posix.cc + +* **include/table.h, include/table_builder.h**: Lower-level modules that most +clients probably won't use directly diff --git a/PediatricPancreas/Pods/leveldb-library/db/builder.cc b/PediatricPancreas/Pods/leveldb-library/db/builder.cc new file mode 100644 index 0000000..9520ee4 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/builder.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/builder.h" + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta) { + Status s; + meta->file_size = 0; + iter->SeekToFirst(); + + std::string fname = TableFileName(dbname, meta->number); + if (iter->Valid()) { + WritableFile* file; + s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + + TableBuilder* builder = new TableBuilder(options, file); + meta->smallest.DecodeFrom(iter->key()); + for (; iter->Valid(); iter->Next()) { + Slice key = iter->key(); + meta->largest.DecodeFrom(key); + builder->Add(key, iter->value()); + } + + // Finish and check for builder errors + s = builder->Finish(); + if (s.ok()) { + meta->file_size = builder->FileSize(); + assert(meta->file_size > 0); + } + delete builder; + + // Finish and check for file errors + if (s.ok()) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (s.ok()) { + // Verify that the table is usable + Iterator* it = table_cache->NewIterator(ReadOptions(), meta->number, + meta->file_size); + s = it->status(); + delete it; + } + } + + // Check for input iterator errors + if (!iter->status().ok()) { + s = iter->status(); + } + + if (s.ok() && meta->file_size > 0) { + // Keep it + } else { + env->DeleteFile(fname); + } + return s; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/builder.h b/PediatricPancreas/Pods/leveldb-library/db/builder.h new file mode 100644 index 0000000..7bd0b80 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/builder.h @@ -0,0 +1,30 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ +#define STORAGE_LEVELDB_DB_BUILDER_H_ + +#include "leveldb/status.h" + +namespace leveldb { + +struct Options; +struct FileMetaData; + +class Env; +class Iterator; +class TableCache; +class VersionEdit; + +// Build a Table file from the contents of *iter. The generated file +// will be named according to meta->number. On success, the rest of +// *meta will be filled with metadata about the generated table. +// If no data is present in *iter, meta->file_size will be set to +// zero, and no Table file will be produced. +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/c.cc b/PediatricPancreas/Pods/leveldb-library/db/c.cc new file mode 100644 index 0000000..e0f3367 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/c.cc @@ -0,0 +1,566 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/c.h" + +#include + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::FilterPolicy; +using leveldb::Iterator; +using leveldb::kMajorVersion; +using leveldb::kMinorVersion; +using leveldb::Logger; +using leveldb::NewBloomFilterPolicy; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; + +extern "C" { + +struct leveldb_t { + DB* rep; +}; +struct leveldb_iterator_t { + Iterator* rep; +}; +struct leveldb_writebatch_t { + WriteBatch rep; +}; +struct leveldb_snapshot_t { + const Snapshot* rep; +}; +struct leveldb_readoptions_t { + ReadOptions rep; +}; +struct leveldb_writeoptions_t { + WriteOptions rep; +}; +struct leveldb_options_t { + Options rep; +}; +struct leveldb_cache_t { + Cache* rep; +}; +struct leveldb_seqfile_t { + SequentialFile* rep; +}; +struct leveldb_randomfile_t { + RandomAccessFile* rep; +}; +struct leveldb_writablefile_t { + WritableFile* rep; +}; +struct leveldb_logger_t { + Logger* rep; +}; +struct leveldb_filelock_t { + FileLock* rep; +}; + +struct leveldb_comparator_t : public Comparator { + virtual ~leveldb_comparator_t() { (*destructor_)(state_); } + + virtual int Compare(const Slice& a, const Slice& b) const { + return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); + } + + virtual const char* Name() const { return (*name_)(state_); } + + // No-ops since the C binding does not support key shortening methods. + virtual void FindShortestSeparator(std::string*, const Slice&) const {} + virtual void FindShortSuccessor(std::string* key) const {} + + void* state_; + void (*destructor_)(void*); + int (*compare_)(void*, const char* a, size_t alen, const char* b, + size_t blen); + const char* (*name_)(void*); +}; + +struct leveldb_filterpolicy_t : public FilterPolicy { + virtual ~leveldb_filterpolicy_t() { (*destructor_)(state_); } + + virtual const char* Name() const { return (*name_)(state_); } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + std::vector key_pointers(n); + std::vector key_sizes(n); + for (int i = 0; i < n; i++) { + key_pointers[i] = keys[i].data(); + key_sizes[i] = keys[i].size(); + } + size_t len; + char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); + dst->append(filter, len); + free(filter); + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return (*key_match_)(state_, key.data(), key.size(), filter.data(), + filter.size()); + } + + void* state_; + void (*destructor_)(void*); + const char* (*name_)(void*); + char* (*create_)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length); + unsigned char (*key_match_)(void*, const char* key, size_t length, + const char* filter, size_t filter_length); +}; + +struct leveldb_env_t { + Env* rep; + bool is_default; +}; + +static bool SaveError(char** errptr, const Status& s) { + assert(errptr != nullptr); + if (s.ok()) { + return false; + } else if (*errptr == nullptr) { + *errptr = strdup(s.ToString().c_str()); + } else { + // TODO(sanjay): Merge with existing error? + free(*errptr); + *errptr = strdup(s.ToString().c_str()); + } + return true; +} + +static char* CopyString(const std::string& str) { + char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); + memcpy(result, str.data(), sizeof(char) * str.size()); + return result; +} + +leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name, + char** errptr) { + DB* db; + if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { + return nullptr; + } + leveldb_t* result = new leveldb_t; + result->rep = db; + return result; +} + +void leveldb_close(leveldb_t* db) { + delete db->rep; + delete db; +} + +void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, + db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); +} + +void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); +} + +void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr) { + SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); +} + +char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr) { + char* result = nullptr; + std::string tmp; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + } else { + *vallen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options) { + leveldb_iterator_t* result = new leveldb_iterator_t; + result->rep = db->rep->NewIterator(options->rep); + return result; +} + +const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db) { + leveldb_snapshot_t* result = new leveldb_snapshot_t; + result->rep = db->rep->GetSnapshot(); + return result; +} + +void leveldb_release_snapshot(leveldb_t* db, + const leveldb_snapshot_t* snapshot) { + db->rep->ReleaseSnapshot(snapshot->rep); + delete snapshot; +} + +char* leveldb_property_value(leveldb_t* db, const char* propname) { + std::string tmp; + if (db->rep->GetProperty(Slice(propname), &tmp)) { + // We use strdup() since we expect human readable output. + return strdup(tmp.c_str()); + } else { + return nullptr; + } +} + +void leveldb_approximate_sizes(leveldb_t* db, int num_ranges, + const char* const* range_start_key, + const size_t* range_start_key_len, + const char* const* range_limit_key, + const size_t* range_limit_key_len, + uint64_t* sizes) { + Range* ranges = new Range[num_ranges]; + for (int i = 0; i < num_ranges; i++) { + ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); + ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); + } + db->rep->GetApproximateSizes(ranges, num_ranges, sizes); + delete[] ranges; +} + +void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, const char* limit_key, + size_t limit_key_len) { + Slice a, b; + db->rep->CompactRange( + // Pass null Slice if corresponding "const char*" is null + (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr), + (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr)); +} + +void leveldb_destroy_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, DestroyDB(name, options->rep)); +} + +void leveldb_repair_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, RepairDB(name, options->rep)); +} + +void leveldb_iter_destroy(leveldb_iterator_t* iter) { + delete iter->rep; + delete iter; +} + +unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { + return iter->rep->Valid(); +} + +void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { + iter->rep->SeekToFirst(); +} + +void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { + iter->rep->SeekToLast(); +} + +void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { + iter->rep->Seek(Slice(k, klen)); +} + +void leveldb_iter_next(leveldb_iterator_t* iter) { iter->rep->Next(); } + +void leveldb_iter_prev(leveldb_iterator_t* iter) { iter->rep->Prev(); } + +const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { + Slice s = iter->rep->key(); + *klen = s.size(); + return s.data(); +} + +const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { + Slice s = iter->rep->value(); + *vlen = s.size(); + return s.data(); +} + +void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { + SaveError(errptr, iter->rep->status()); +} + +leveldb_writebatch_t* leveldb_writebatch_create() { + return new leveldb_writebatch_t; +} + +void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { delete b; } + +void leveldb_writebatch_clear(leveldb_writebatch_t* b) { b->rep.Clear(); } + +void leveldb_writebatch_put(leveldb_writebatch_t* b, const char* key, + size_t klen, const char* val, size_t vlen) { + b->rep.Put(Slice(key, klen), Slice(val, vlen)); +} + +void leveldb_writebatch_delete(leveldb_writebatch_t* b, const char* key, + size_t klen) { + b->rep.Delete(Slice(key, klen)); +} + +void leveldb_writebatch_iterate(const leveldb_writebatch_t* b, void* state, + void (*put)(void*, const char* k, size_t klen, + const char* v, size_t vlen), + void (*deleted)(void*, const char* k, + size_t klen)) { + class H : public WriteBatch::Handler { + public: + void* state_; + void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); + void (*deleted_)(void*, const char* k, size_t klen); + virtual void Put(const Slice& key, const Slice& value) { + (*put_)(state_, key.data(), key.size(), value.data(), value.size()); + } + virtual void Delete(const Slice& key) { + (*deleted_)(state_, key.data(), key.size()); + } + }; + H handler; + handler.state_ = state; + handler.put_ = put; + handler.deleted_ = deleted; + b->rep.Iterate(&handler); +} + +void leveldb_writebatch_append(leveldb_writebatch_t* destination, + const leveldb_writebatch_t* source) { + destination->rep.Append(source->rep); +} + +leveldb_options_t* leveldb_options_create() { return new leveldb_options_t; } + +void leveldb_options_destroy(leveldb_options_t* options) { delete options; } + +void leveldb_options_set_comparator(leveldb_options_t* opt, + leveldb_comparator_t* cmp) { + opt->rep.comparator = cmp; +} + +void leveldb_options_set_filter_policy(leveldb_options_t* opt, + leveldb_filterpolicy_t* policy) { + opt->rep.filter_policy = policy; +} + +void leveldb_options_set_create_if_missing(leveldb_options_t* opt, + unsigned char v) { + opt->rep.create_if_missing = v; +} + +void leveldb_options_set_error_if_exists(leveldb_options_t* opt, + unsigned char v) { + opt->rep.error_if_exists = v; +} + +void leveldb_options_set_paranoid_checks(leveldb_options_t* opt, + unsigned char v) { + opt->rep.paranoid_checks = v; +} + +void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { + opt->rep.env = (env ? env->rep : nullptr); +} + +void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { + opt->rep.info_log = (l ? l->rep : nullptr); +} + +void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { + opt->rep.write_buffer_size = s; +} + +void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { + opt->rep.max_open_files = n; +} + +void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { + opt->rep.block_cache = c->rep; +} + +void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { + opt->rep.block_size = s; +} + +void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { + opt->rep.block_restart_interval = n; +} + +void leveldb_options_set_max_file_size(leveldb_options_t* opt, size_t s) { + opt->rep.max_file_size = s; +} + +void leveldb_options_set_compression(leveldb_options_t* opt, int t) { + opt->rep.compression = static_cast(t); +} + +leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)) { + leveldb_comparator_t* result = new leveldb_comparator_t; + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->name_ = name; + return result; +} + +void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { delete cmp; } + +leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)) { + leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; + result->state_ = state; + result->destructor_ = destructor; + result->create_ = create_filter; + result->key_match_ = key_may_match; + result->name_ = name; + return result; +} + +void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { + delete filter; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { + // Make a leveldb_filterpolicy_t, but override all of its methods so + // they delegate to a NewBloomFilterPolicy() instead of user + // supplied C functions. + struct Wrapper : public leveldb_filterpolicy_t { + static void DoNothing(void*) {} + + ~Wrapper() { delete rep_; } + const char* Name() const { return rep_->Name(); } + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + return rep_->CreateFilter(keys, n, dst); + } + bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return rep_->KeyMayMatch(key, filter); + } + + const FilterPolicy* rep_; + }; + Wrapper* wrapper = new Wrapper; + wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); + wrapper->state_ = nullptr; + wrapper->destructor_ = &Wrapper::DoNothing; + return wrapper; +} + +leveldb_readoptions_t* leveldb_readoptions_create() { + return new leveldb_readoptions_t; +} + +void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { delete opt; } + +void leveldb_readoptions_set_verify_checksums(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.verify_checksums = v; +} + +void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.fill_cache = v; +} + +void leveldb_readoptions_set_snapshot(leveldb_readoptions_t* opt, + const leveldb_snapshot_t* snap) { + opt->rep.snapshot = (snap ? snap->rep : nullptr); +} + +leveldb_writeoptions_t* leveldb_writeoptions_create() { + return new leveldb_writeoptions_t; +} + +void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { delete opt; } + +void leveldb_writeoptions_set_sync(leveldb_writeoptions_t* opt, + unsigned char v) { + opt->rep.sync = v; +} + +leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { + leveldb_cache_t* c = new leveldb_cache_t; + c->rep = NewLRUCache(capacity); + return c; +} + +void leveldb_cache_destroy(leveldb_cache_t* cache) { + delete cache->rep; + delete cache; +} + +leveldb_env_t* leveldb_create_default_env() { + leveldb_env_t* result = new leveldb_env_t; + result->rep = Env::Default(); + result->is_default = true; + return result; +} + +void leveldb_env_destroy(leveldb_env_t* env) { + if (!env->is_default) delete env->rep; + delete env; +} + +char* leveldb_env_get_test_directory(leveldb_env_t* env) { + std::string result; + if (!env->rep->GetTestDirectory(&result).ok()) { + return nullptr; + } + + char* buffer = static_cast(malloc(result.size() + 1)); + memcpy(buffer, result.data(), result.size()); + buffer[result.size()] = '\0'; + return buffer; +} + +void leveldb_free(void* ptr) { free(ptr); } + +int leveldb_major_version() { return kMajorVersion; } + +int leveldb_minor_version() { return kMinorVersion; } + +} // end extern "C" diff --git a/PediatricPancreas/Pods/leveldb-library/db/db_impl.cc b/PediatricPancreas/Pods/leveldb-library/db/db_impl.cc new file mode 100644 index 0000000..761ebf6 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/db_impl.cc @@ -0,0 +1,1550 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "db/builder.h" +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/mutexlock.h" + +namespace leveldb { + +const int kNumNonTableCacheFiles = 10; + +// Information kept for every waiting writer +struct DBImpl::Writer { + explicit Writer(port::Mutex* mu) + : batch(nullptr), sync(false), done(false), cv(mu) {} + + Status status; + WriteBatch* batch; + bool sync; + bool done; + port::CondVar cv; +}; + +struct DBImpl::CompactionState { + // Files produced by compaction + struct Output { + uint64_t number; + uint64_t file_size; + InternalKey smallest, largest; + }; + + Output* current_output() { return &outputs[outputs.size() - 1]; } + + explicit CompactionState(Compaction* c) + : compaction(c), + smallest_snapshot(0), + outfile(nullptr), + builder(nullptr), + total_bytes(0) {} + + Compaction* const compaction; + + // Sequence numbers < smallest_snapshot are not significant since we + // will never have to service a snapshot below smallest_snapshot. + // Therefore if we have seen a sequence number S <= smallest_snapshot, + // we can drop all entries for the same key with sequence numbers < S. + SequenceNumber smallest_snapshot; + + std::vector outputs; + + // State kept for output being generated + WritableFile* outfile; + TableBuilder* builder; + + uint64_t total_bytes; +}; + +// Fix user-supplied options to be reasonable +template +static void ClipToRange(T* ptr, V minvalue, V maxvalue) { + if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; + if (static_cast(*ptr) < minvalue) *ptr = minvalue; +} +Options SanitizeOptions(const std::string& dbname, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src) { + Options result = src; + result.comparator = icmp; + result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr; + ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); + ClipToRange(&result.write_buffer_size, 64 << 10, 1 << 30); + ClipToRange(&result.max_file_size, 1 << 20, 1 << 30); + ClipToRange(&result.block_size, 1 << 10, 4 << 20); + if (result.info_log == nullptr) { + // Open a log file in the same directory as the db + src.env->CreateDir(dbname); // In case it does not exist + src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname)); + Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log); + if (!s.ok()) { + // No place suitable for logging + result.info_log = nullptr; + } + } + if (result.block_cache == nullptr) { + result.block_cache = NewLRUCache(8 << 20); + } + return result; +} + +static int TableCacheSize(const Options& sanitized_options) { + // Reserve ten files or so for other uses and give the rest to TableCache. + return sanitized_options.max_open_files - kNumNonTableCacheFiles; +} + +DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) + : env_(raw_options.env), + internal_comparator_(raw_options.comparator), + internal_filter_policy_(raw_options.filter_policy), + options_(SanitizeOptions(dbname, &internal_comparator_, + &internal_filter_policy_, raw_options)), + owns_info_log_(options_.info_log != raw_options.info_log), + owns_cache_(options_.block_cache != raw_options.block_cache), + dbname_(dbname), + table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))), + db_lock_(nullptr), + shutting_down_(false), + background_work_finished_signal_(&mutex_), + mem_(nullptr), + imm_(nullptr), + has_imm_(false), + logfile_(nullptr), + logfile_number_(0), + log_(nullptr), + seed_(0), + tmp_batch_(new WriteBatch), + background_compaction_scheduled_(false), + manual_compaction_(nullptr), + versions_(new VersionSet(dbname_, &options_, table_cache_, + &internal_comparator_)) {} + +DBImpl::~DBImpl() { + // Wait for background work to finish. + mutex_.Lock(); + shutting_down_.store(true, std::memory_order_release); + while (background_compaction_scheduled_) { + background_work_finished_signal_.Wait(); + } + mutex_.Unlock(); + + if (db_lock_ != nullptr) { + env_->UnlockFile(db_lock_); + } + + delete versions_; + if (mem_ != nullptr) mem_->Unref(); + if (imm_ != nullptr) imm_->Unref(); + delete tmp_batch_; + delete log_; + delete logfile_; + delete table_cache_; + + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } +} + +Status DBImpl::NewDB() { + VersionEdit new_db; + new_db.SetComparatorName(user_comparator()->Name()); + new_db.SetLogNumber(0); + new_db.SetNextFile(2); + new_db.SetLastSequence(0); + + const std::string manifest = DescriptorFileName(dbname_, 1); + WritableFile* file; + Status s = env_->NewWritableFile(manifest, &file); + if (!s.ok()) { + return s; + } + { + log::Writer log(file); + std::string record; + new_db.EncodeTo(&record); + s = log.AddRecord(record); + if (s.ok()) { + s = file->Close(); + } + } + delete file; + if (s.ok()) { + // Make "CURRENT" file that points to the new manifest file. + s = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(manifest); + } + return s; +} + +void DBImpl::MaybeIgnoreError(Status* s) const { + if (s->ok() || options_.paranoid_checks) { + // No change needed + } else { + Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); + *s = Status::OK(); + } +} + +void DBImpl::DeleteObsoleteFiles() { + mutex_.AssertHeld(); + + if (!bg_error_.ok()) { + // After a background error, we don't know whether a new version may + // or may not have been committed, so we cannot safely garbage collect. + return; + } + + // Make a set of all of the live files + std::set live = pending_outputs_; + versions_->AddLiveFiles(&live); + + std::vector filenames; + env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + bool keep = true; + switch (type) { + case kLogFile: + keep = ((number >= versions_->LogNumber()) || + (number == versions_->PrevLogNumber())); + break; + case kDescriptorFile: + // Keep my manifest file, and any newer incarnations' + // (in case there is a race that allows other incarnations) + keep = (number >= versions_->ManifestFileNumber()); + break; + case kTableFile: + keep = (live.find(number) != live.end()); + break; + case kTempFile: + // Any temp files that are currently being written to must + // be recorded in pending_outputs_, which is inserted into "live" + keep = (live.find(number) != live.end()); + break; + case kCurrentFile: + case kDBLockFile: + case kInfoLogFile: + keep = true; + break; + } + + if (!keep) { + if (type == kTableFile) { + table_cache_->Evict(number); + } + Log(options_.info_log, "Delete type=%d #%lld\n", static_cast(type), + static_cast(number)); + env_->DeleteFile(dbname_ + "/" + filenames[i]); + } + } + } +} + +Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) { + mutex_.AssertHeld(); + + // Ignore error from CreateDir since the creation of the DB is + // committed only when the descriptor is created, and this directory + // may already exist from a previous failed creation attempt. + env_->CreateDir(dbname_); + assert(db_lock_ == nullptr); + Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); + if (!s.ok()) { + return s; + } + + if (!env_->FileExists(CurrentFileName(dbname_))) { + if (options_.create_if_missing) { + s = NewDB(); + if (!s.ok()) { + return s; + } + } else { + return Status::InvalidArgument( + dbname_, "does not exist (create_if_missing is false)"); + } + } else { + if (options_.error_if_exists) { + return Status::InvalidArgument(dbname_, + "exists (error_if_exists is true)"); + } + } + + s = versions_->Recover(save_manifest); + if (!s.ok()) { + return s; + } + SequenceNumber max_sequence(0); + + // Recover from all newer log files than the ones named in the + // descriptor (new log files may have been added by the previous + // incarnation without registering them in the descriptor). + // + // Note that PrevLogNumber() is no longer used, but we pay + // attention to it in case we are recovering a database + // produced by an older version of leveldb. + const uint64_t min_log = versions_->LogNumber(); + const uint64_t prev_log = versions_->PrevLogNumber(); + std::vector filenames; + s = env_->GetChildren(dbname_, &filenames); + if (!s.ok()) { + return s; + } + std::set expected; + versions_->AddLiveFiles(&expected); + uint64_t number; + FileType type; + std::vector logs; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + expected.erase(number); + if (type == kLogFile && ((number >= min_log) || (number == prev_log))) + logs.push_back(number); + } + } + if (!expected.empty()) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d missing files; e.g.", + static_cast(expected.size())); + return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin()))); + } + + // Recover in the order in which the logs were generated + std::sort(logs.begin(), logs.end()); + for (size_t i = 0; i < logs.size(); i++) { + s = RecoverLogFile(logs[i], (i == logs.size() - 1), save_manifest, edit, + &max_sequence); + if (!s.ok()) { + return s; + } + + // The previous incarnation may not have written any MANIFEST + // records after allocating this log number. So we manually + // update the file number allocation counter in VersionSet. + versions_->MarkFileNumberUsed(logs[i]); + } + + if (versions_->LastSequence() < max_sequence) { + versions_->SetLastSequence(max_sequence); + } + + return Status::OK(); +} + +Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log, + bool* save_manifest, VersionEdit* edit, + SequenceNumber* max_sequence) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // null if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == nullptr ? "(ignoring error) " : ""), fname, + static_cast(bytes), s.ToString().c_str()); + if (this->status != nullptr && this->status->ok()) *this->status = s; + } + }; + + mutex_.AssertHeld(); + + // Open the log file + std::string fname = LogFileName(dbname_, log_number); + SequentialFile* file; + Status status = env_->NewSequentialFile(fname, &file); + if (!status.ok()) { + MaybeIgnoreError(&status); + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : nullptr); + // We intentionally make log::Reader do checksumming even if + // paranoid_checks==false so that corruptions cause entire commits + // to be skipped instead of propagating bad information (like overly + // large sequence numbers). + log::Reader reader(file, &reporter, true /*checksum*/, 0 /*initial_offset*/); + Log(options_.info_log, "Recovering log #%llu", + (unsigned long long)log_number); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + int compactions = 0; + MemTable* mem = nullptr; + while (reader.ReadRecord(&record, &scratch) && status.ok()) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + + if (mem == nullptr) { + mem = new MemTable(internal_comparator_); + mem->Ref(); + } + status = WriteBatchInternal::InsertInto(&batch, mem); + MaybeIgnoreError(&status); + if (!status.ok()) { + break; + } + const SequenceNumber last_seq = WriteBatchInternal::Sequence(&batch) + + WriteBatchInternal::Count(&batch) - 1; + if (last_seq > *max_sequence) { + *max_sequence = last_seq; + } + + if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) { + compactions++; + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + mem->Unref(); + mem = nullptr; + if (!status.ok()) { + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + break; + } + } + } + + delete file; + + // See if we should keep reusing the last log file. + if (status.ok() && options_.reuse_logs && last_log && compactions == 0) { + assert(logfile_ == nullptr); + assert(log_ == nullptr); + assert(mem_ == nullptr); + uint64_t lfile_size; + if (env_->GetFileSize(fname, &lfile_size).ok() && + env_->NewAppendableFile(fname, &logfile_).ok()) { + Log(options_.info_log, "Reusing old log %s \n", fname.c_str()); + log_ = new log::Writer(logfile_, lfile_size); + logfile_number_ = log_number; + if (mem != nullptr) { + mem_ = mem; + mem = nullptr; + } else { + // mem can be nullptr if lognum exists but was empty. + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + } + } + } + + if (mem != nullptr) { + // mem did not get reused; compact it. + if (status.ok()) { + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + } + mem->Unref(); + } + + return status; +} + +Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, + Version* base) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + Log(options_.info_log, "Level-0 table #%llu: started", + (unsigned long long)meta.number); + + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + mutex_.Lock(); + } + + Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", + (unsigned long long)meta.number, (unsigned long long)meta.file_size, + s.ToString().c_str()); + delete iter; + pending_outputs_.erase(meta.number); + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + const Slice min_user_key = meta.smallest.user_key(); + const Slice max_user_key = meta.largest.user_key(); + if (base != nullptr) { + level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); + } + edit->AddFile(level, meta.number, meta.file_size, meta.smallest, + meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats_[level].Add(stats); + return s; +} + +void DBImpl::CompactMemTable() { + mutex_.AssertHeld(); + assert(imm_ != nullptr); + + // Save the contents of the memtable as a new Table + VersionEdit edit; + Version* base = versions_->current(); + base->Ref(); + Status s = WriteLevel0Table(imm_, &edit, base); + base->Unref(); + + if (s.ok() && shutting_down_.load(std::memory_order_acquire)) { + s = Status::IOError("Deleting DB during memtable compaction"); + } + + // Replace immutable memtable with the generated Table + if (s.ok()) { + edit.SetPrevLogNumber(0); + edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed + s = versions_->LogAndApply(&edit, &mutex_); + } + + if (s.ok()) { + // Commit to the new state + imm_->Unref(); + imm_ = nullptr; + has_imm_.store(false, std::memory_order_release); + DeleteObsoleteFiles(); + } else { + RecordBackgroundError(s); + } +} + +void DBImpl::CompactRange(const Slice* begin, const Slice* end) { + int max_level_with_files = 1; + { + MutexLock l(&mutex_); + Version* base = versions_->current(); + for (int level = 1; level < config::kNumLevels; level++) { + if (base->OverlapInLevel(level, begin, end)) { + max_level_with_files = level; + } + } + } + TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap + for (int level = 0; level < max_level_with_files; level++) { + TEST_CompactRange(level, begin, end); + } +} + +void DBImpl::TEST_CompactRange(int level, const Slice* begin, + const Slice* end) { + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + + InternalKey begin_storage, end_storage; + + ManualCompaction manual; + manual.level = level; + manual.done = false; + if (begin == nullptr) { + manual.begin = nullptr; + } else { + begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); + manual.begin = &begin_storage; + } + if (end == nullptr) { + manual.end = nullptr; + } else { + end_storage = InternalKey(*end, 0, static_cast(0)); + manual.end = &end_storage; + } + + MutexLock l(&mutex_); + while (!manual.done && !shutting_down_.load(std::memory_order_acquire) && + bg_error_.ok()) { + if (manual_compaction_ == nullptr) { // Idle + manual_compaction_ = &manual; + MaybeScheduleCompaction(); + } else { // Running either my compaction or another compaction. + background_work_finished_signal_.Wait(); + } + } + if (manual_compaction_ == &manual) { + // Cancel my manual compaction since we aborted early for some reason. + manual_compaction_ = nullptr; + } +} + +Status DBImpl::TEST_CompactMemTable() { + // nullptr batch means just wait for earlier writes to be done + Status s = Write(WriteOptions(), nullptr); + if (s.ok()) { + // Wait until the compaction completes + MutexLock l(&mutex_); + while (imm_ != nullptr && bg_error_.ok()) { + background_work_finished_signal_.Wait(); + } + if (imm_ != nullptr) { + s = bg_error_; + } + } + return s; +} + +void DBImpl::RecordBackgroundError(const Status& s) { + mutex_.AssertHeld(); + if (bg_error_.ok()) { + bg_error_ = s; + background_work_finished_signal_.SignalAll(); + } +} + +void DBImpl::MaybeScheduleCompaction() { + mutex_.AssertHeld(); + if (background_compaction_scheduled_) { + // Already scheduled + } else if (shutting_down_.load(std::memory_order_acquire)) { + // DB is being deleted; no more background compactions + } else if (!bg_error_.ok()) { + // Already got an error; no more changes + } else if (imm_ == nullptr && manual_compaction_ == nullptr && + !versions_->NeedsCompaction()) { + // No work to be done + } else { + background_compaction_scheduled_ = true; + env_->Schedule(&DBImpl::BGWork, this); + } +} + +void DBImpl::BGWork(void* db) { + reinterpret_cast(db)->BackgroundCall(); +} + +void DBImpl::BackgroundCall() { + MutexLock l(&mutex_); + assert(background_compaction_scheduled_); + if (shutting_down_.load(std::memory_order_acquire)) { + // No more background work when shutting down. + } else if (!bg_error_.ok()) { + // No more background work after a background error. + } else { + BackgroundCompaction(); + } + + background_compaction_scheduled_ = false; + + // Previous compaction may have produced too many files in a level, + // so reschedule another compaction if needed. + MaybeScheduleCompaction(); + background_work_finished_signal_.SignalAll(); +} + +void DBImpl::BackgroundCompaction() { + mutex_.AssertHeld(); + + if (imm_ != nullptr) { + CompactMemTable(); + return; + } + + Compaction* c; + bool is_manual = (manual_compaction_ != nullptr); + InternalKey manual_end; + if (is_manual) { + ManualCompaction* m = manual_compaction_; + c = versions_->CompactRange(m->level, m->begin, m->end); + m->done = (c == nullptr); + if (c != nullptr) { + manual_end = c->input(0, c->num_input_files(0) - 1)->largest; + } + Log(options_.info_log, + "Manual compaction at level-%d from %s .. %s; will stop at %s\n", + m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"), + (m->end ? m->end->DebugString().c_str() : "(end)"), + (m->done ? "(end)" : manual_end.DebugString().c_str())); + } else { + c = versions_->PickCompaction(); + } + + Status status; + if (c == nullptr) { + // Nothing to do + } else if (!is_manual && c->IsTrivialMove()) { + // Move file to next level + assert(c->num_input_files(0) == 1); + FileMetaData* f = c->input(0, 0); + c->edit()->DeleteFile(c->level(), f->number); + c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest, + f->largest); + status = versions_->LogAndApply(c->edit(), &mutex_); + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", + static_cast(f->number), c->level() + 1, + static_cast(f->file_size), + status.ToString().c_str(), versions_->LevelSummary(&tmp)); + } else { + CompactionState* compact = new CompactionState(c); + status = DoCompactionWork(compact); + if (!status.ok()) { + RecordBackgroundError(status); + } + CleanupCompaction(compact); + c->ReleaseInputs(); + DeleteObsoleteFiles(); + } + delete c; + + if (status.ok()) { + // Done + } else if (shutting_down_.load(std::memory_order_acquire)) { + // Ignore compaction errors found during shutting down + } else { + Log(options_.info_log, "Compaction error: %s", status.ToString().c_str()); + } + + if (is_manual) { + ManualCompaction* m = manual_compaction_; + if (!status.ok()) { + m->done = true; + } + if (!m->done) { + // We only compacted part of the requested range. Update *m + // to the range that is left to be compacted. + m->tmp_storage = manual_end; + m->begin = &m->tmp_storage; + } + manual_compaction_ = nullptr; + } +} + +void DBImpl::CleanupCompaction(CompactionState* compact) { + mutex_.AssertHeld(); + if (compact->builder != nullptr) { + // May happen if we get a shutdown call in the middle of compaction + compact->builder->Abandon(); + delete compact->builder; + } else { + assert(compact->outfile == nullptr); + } + delete compact->outfile; + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + pending_outputs_.erase(out.number); + } + delete compact; +} + +Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { + assert(compact != nullptr); + assert(compact->builder == nullptr); + uint64_t file_number; + { + mutex_.Lock(); + file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + CompactionState::Output out; + out.number = file_number; + out.smallest.Clear(); + out.largest.Clear(); + compact->outputs.push_back(out); + mutex_.Unlock(); + } + + // Make the output file + std::string fname = TableFileName(dbname_, file_number); + Status s = env_->NewWritableFile(fname, &compact->outfile); + if (s.ok()) { + compact->builder = new TableBuilder(options_, compact->outfile); + } + return s; +} + +Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, + Iterator* input) { + assert(compact != nullptr); + assert(compact->outfile != nullptr); + assert(compact->builder != nullptr); + + const uint64_t output_number = compact->current_output()->number; + assert(output_number != 0); + + // Check for iterator errors + Status s = input->status(); + const uint64_t current_entries = compact->builder->NumEntries(); + if (s.ok()) { + s = compact->builder->Finish(); + } else { + compact->builder->Abandon(); + } + const uint64_t current_bytes = compact->builder->FileSize(); + compact->current_output()->file_size = current_bytes; + compact->total_bytes += current_bytes; + delete compact->builder; + compact->builder = nullptr; + + // Finish and check for file errors + if (s.ok()) { + s = compact->outfile->Sync(); + } + if (s.ok()) { + s = compact->outfile->Close(); + } + delete compact->outfile; + compact->outfile = nullptr; + + if (s.ok() && current_entries > 0) { + // Verify that the table is usable + Iterator* iter = + table_cache_->NewIterator(ReadOptions(), output_number, current_bytes); + s = iter->status(); + delete iter; + if (s.ok()) { + Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes", + (unsigned long long)output_number, compact->compaction->level(), + (unsigned long long)current_entries, + (unsigned long long)current_bytes); + } + } + return s; +} + +Status DBImpl::InstallCompactionResults(CompactionState* compact) { + mutex_.AssertHeld(); + Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), compact->compaction->level() + 1, + static_cast(compact->total_bytes)); + + // Add compaction outputs + compact->compaction->AddInputDeletions(compact->compaction->edit()); + const int level = compact->compaction->level(); + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size, + out.smallest, out.largest); + } + return versions_->LogAndApply(compact->compaction->edit(), &mutex_); +} + +Status DBImpl::DoCompactionWork(CompactionState* compact) { + const uint64_t start_micros = env_->NowMicros(); + int64_t imm_micros = 0; // Micros spent doing imm_ compactions + + Log(options_.info_log, "Compacting %d@%d + %d@%d files", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1); + + assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); + assert(compact->builder == nullptr); + assert(compact->outfile == nullptr); + if (snapshots_.empty()) { + compact->smallest_snapshot = versions_->LastSequence(); + } else { + compact->smallest_snapshot = snapshots_.oldest()->sequence_number(); + } + + // Release mutex while we're actually doing the compaction work + mutex_.Unlock(); + + Iterator* input = versions_->MakeInputIterator(compact->compaction); + input->SeekToFirst(); + Status status; + ParsedInternalKey ikey; + std::string current_user_key; + bool has_current_user_key = false; + SequenceNumber last_sequence_for_key = kMaxSequenceNumber; + for (; input->Valid() && !shutting_down_.load(std::memory_order_acquire);) { + // Prioritize immutable compaction work + if (has_imm_.load(std::memory_order_relaxed)) { + const uint64_t imm_start = env_->NowMicros(); + mutex_.Lock(); + if (imm_ != nullptr) { + CompactMemTable(); + // Wake up MakeRoomForWrite() if necessary. + background_work_finished_signal_.SignalAll(); + } + mutex_.Unlock(); + imm_micros += (env_->NowMicros() - imm_start); + } + + Slice key = input->key(); + if (compact->compaction->ShouldStopBefore(key) && + compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + + // Handle key/value, add to state, etc. + bool drop = false; + if (!ParseInternalKey(key, &ikey)) { + // Do not hide error keys + current_user_key.clear(); + has_current_user_key = false; + last_sequence_for_key = kMaxSequenceNumber; + } else { + if (!has_current_user_key || + user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) != + 0) { + // First occurrence of this user key + current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + has_current_user_key = true; + last_sequence_for_key = kMaxSequenceNumber; + } + + if (last_sequence_for_key <= compact->smallest_snapshot) { + // Hidden by an newer entry for same user key + drop = true; // (A) + } else if (ikey.type == kTypeDeletion && + ikey.sequence <= compact->smallest_snapshot && + compact->compaction->IsBaseLevelForKey(ikey.user_key)) { + // For this user key: + // (1) there is no data in higher levels + // (2) data in lower levels will have larger sequence numbers + // (3) data in layers that are being compacted here and have + // smaller sequence numbers will be dropped in the next + // few iterations of this loop (by rule (A) above). + // Therefore this deletion marker is obsolete and can be dropped. + drop = true; + } + + last_sequence_for_key = ikey.sequence; + } +#if 0 + Log(options_.info_log, + " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " + "%d smallest_snapshot: %d", + ikey.user_key.ToString().c_str(), + (int)ikey.sequence, ikey.type, kTypeValue, drop, + compact->compaction->IsBaseLevelForKey(ikey.user_key), + (int)last_sequence_for_key, (int)compact->smallest_snapshot); +#endif + + if (!drop) { + // Open output file if necessary + if (compact->builder == nullptr) { + status = OpenCompactionOutputFile(compact); + if (!status.ok()) { + break; + } + } + if (compact->builder->NumEntries() == 0) { + compact->current_output()->smallest.DecodeFrom(key); + } + compact->current_output()->largest.DecodeFrom(key); + compact->builder->Add(key, input->value()); + + // Close output file if it is big enough + if (compact->builder->FileSize() >= + compact->compaction->MaxOutputFileSize()) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + } + + input->Next(); + } + + if (status.ok() && shutting_down_.load(std::memory_order_acquire)) { + status = Status::IOError("Deleting DB during compaction"); + } + if (status.ok() && compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + } + if (status.ok()) { + status = input->status(); + } + delete input; + input = nullptr; + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros - imm_micros; + for (int which = 0; which < 2; which++) { + for (int i = 0; i < compact->compaction->num_input_files(which); i++) { + stats.bytes_read += compact->compaction->input(which, i)->file_size; + } + } + for (size_t i = 0; i < compact->outputs.size(); i++) { + stats.bytes_written += compact->outputs[i].file_size; + } + + mutex_.Lock(); + stats_[compact->compaction->level() + 1].Add(stats); + + if (status.ok()) { + status = InstallCompactionResults(compact); + } + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp)); + return status; +} + +namespace { + +struct IterState { + port::Mutex* const mu; + Version* const version GUARDED_BY(mu); + MemTable* const mem GUARDED_BY(mu); + MemTable* const imm GUARDED_BY(mu); + + IterState(port::Mutex* mutex, MemTable* mem, MemTable* imm, Version* version) + : mu(mutex), version(version), mem(mem), imm(imm) {} +}; + +static void CleanupIteratorState(void* arg1, void* arg2) { + IterState* state = reinterpret_cast(arg1); + state->mu->Lock(); + state->mem->Unref(); + if (state->imm != nullptr) state->imm->Unref(); + state->version->Unref(); + state->mu->Unlock(); + delete state; +} + +} // anonymous namespace + +Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, + SequenceNumber* latest_snapshot, + uint32_t* seed) { + mutex_.Lock(); + *latest_snapshot = versions_->LastSequence(); + + // Collect together all needed child iterators + std::vector list; + list.push_back(mem_->NewIterator()); + mem_->Ref(); + if (imm_ != nullptr) { + list.push_back(imm_->NewIterator()); + imm_->Ref(); + } + versions_->current()->AddIterators(options, &list); + Iterator* internal_iter = + NewMergingIterator(&internal_comparator_, &list[0], list.size()); + versions_->current()->Ref(); + + IterState* cleanup = new IterState(&mutex_, mem_, imm_, versions_->current()); + internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr); + + *seed = ++seed_; + mutex_.Unlock(); + return internal_iter; +} + +Iterator* DBImpl::TEST_NewInternalIterator() { + SequenceNumber ignored; + uint32_t ignored_seed; + return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed); +} + +int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { + MutexLock l(&mutex_); + return versions_->MaxNextLevelOverlappingBytes(); +} + +Status DBImpl::Get(const ReadOptions& options, const Slice& key, + std::string* value) { + Status s; + MutexLock l(&mutex_); + SequenceNumber snapshot; + if (options.snapshot != nullptr) { + snapshot = + static_cast(options.snapshot)->sequence_number(); + } else { + snapshot = versions_->LastSequence(); + } + + MemTable* mem = mem_; + MemTable* imm = imm_; + Version* current = versions_->current(); + mem->Ref(); + if (imm != nullptr) imm->Ref(); + current->Ref(); + + bool have_stat_update = false; + Version::GetStats stats; + + // Unlock while reading from files and memtables + { + mutex_.Unlock(); + // First look in the memtable, then in the immutable memtable (if any). + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + // Done + } else if (imm != nullptr && imm->Get(lkey, value, &s)) { + // Done + } else { + s = current->Get(options, lkey, value, &stats); + have_stat_update = true; + } + mutex_.Lock(); + } + + if (have_stat_update && current->UpdateStats(stats)) { + MaybeScheduleCompaction(); + } + mem->Unref(); + if (imm != nullptr) imm->Unref(); + current->Unref(); + return s; +} + +Iterator* DBImpl::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + uint32_t seed; + Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed); + return NewDBIterator(this, user_comparator(), iter, + (options.snapshot != nullptr + ? static_cast(options.snapshot) + ->sequence_number() + : latest_snapshot), + seed); +} + +void DBImpl::RecordReadSample(Slice key) { + MutexLock l(&mutex_); + if (versions_->current()->RecordReadSample(key)) { + MaybeScheduleCompaction(); + } +} + +const Snapshot* DBImpl::GetSnapshot() { + MutexLock l(&mutex_); + return snapshots_.New(versions_->LastSequence()); +} + +void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) { + MutexLock l(&mutex_); + snapshots_.Delete(static_cast(snapshot)); +} + +// Convenience methods +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + return DB::Put(o, key, val); +} + +Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { + return DB::Delete(options, key); +} + +Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) { + Writer w(&mutex_); + w.batch = updates; + w.sync = options.sync; + w.done = false; + + MutexLock l(&mutex_); + writers_.push_back(&w); + while (!w.done && &w != writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + // May temporarily unlock and wait. + Status status = MakeRoomForWrite(updates == nullptr); + uint64_t last_sequence = versions_->LastSequence(); + Writer* last_writer = &w; + if (status.ok() && updates != nullptr) { // nullptr batch is for compactions + WriteBatch* updates = BuildBatchGroup(&last_writer); + WriteBatchInternal::SetSequence(updates, last_sequence + 1); + last_sequence += WriteBatchInternal::Count(updates); + + // Add to log and apply to memtable. We can release the lock + // during this phase since &w is currently responsible for logging + // and protects against concurrent loggers and concurrent writes + // into mem_. + { + mutex_.Unlock(); + status = log_->AddRecord(WriteBatchInternal::Contents(updates)); + bool sync_error = false; + if (status.ok() && options.sync) { + status = logfile_->Sync(); + if (!status.ok()) { + sync_error = true; + } + } + if (status.ok()) { + status = WriteBatchInternal::InsertInto(updates, mem_); + } + mutex_.Lock(); + if (sync_error) { + // The state of the log file is indeterminate: the log record we + // just added may or may not show up when the DB is re-opened. + // So we force the DB into a mode where all future writes fail. + RecordBackgroundError(status); + } + } + if (updates == tmp_batch_) tmp_batch_->Clear(); + + versions_->SetLastSequence(last_sequence); + } + + while (true) { + Writer* ready = writers_.front(); + writers_.pop_front(); + if (ready != &w) { + ready->status = status; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + + // Notify new head of write queue + if (!writers_.empty()) { + writers_.front()->cv.Signal(); + } + + return status; +} + +// REQUIRES: Writer list must be non-empty +// REQUIRES: First writer must have a non-null batch +WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + Writer* first = writers_.front(); + WriteBatch* result = first->batch; + assert(result != nullptr); + + size_t size = WriteBatchInternal::ByteSize(first->batch); + + // Allow the group to grow up to a maximum size, but if the + // original write is small, limit the growth so we do not slow + // down the small write too much. + size_t max_size = 1 << 20; + if (size <= (128 << 10)) { + max_size = size + (128 << 10); + } + + *last_writer = first; + std::deque::iterator iter = writers_.begin(); + ++iter; // Advance past "first" + for (; iter != writers_.end(); ++iter) { + Writer* w = *iter; + if (w->sync && !first->sync) { + // Do not include a sync write into a batch handled by a non-sync write. + break; + } + + if (w->batch != nullptr) { + size += WriteBatchInternal::ByteSize(w->batch); + if (size > max_size) { + // Do not make batch too big + break; + } + + // Append to *result + if (result == first->batch) { + // Switch to temporary batch instead of disturbing caller's batch + result = tmp_batch_; + assert(WriteBatchInternal::Count(result) == 0); + WriteBatchInternal::Append(result, first->batch); + } + WriteBatchInternal::Append(result, w->batch); + } + *last_writer = w; + } + return result; +} + +// REQUIRES: mutex_ is held +// REQUIRES: this thread is currently at the front of the writer queue +Status DBImpl::MakeRoomForWrite(bool force) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + bool allow_delay = !force; + Status s; + while (true) { + if (!bg_error_.ok()) { + // Yield previous error + s = bg_error_; + break; + } else if (allow_delay && versions_->NumLevelFiles(0) >= + config::kL0_SlowdownWritesTrigger) { + // We are getting close to hitting a hard limit on the number of + // L0 files. Rather than delaying a single write by several + // seconds when we hit the hard limit, start delaying each + // individual write by 1ms to reduce latency variance. Also, + // this delay hands over some CPU to the compaction thread in + // case it is sharing the same core as the writer. + mutex_.Unlock(); + env_->SleepForMicroseconds(1000); + allow_delay = false; // Do not delay a single write more than once + mutex_.Lock(); + } else if (!force && + (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { + // There is room in current memtable + break; + } else if (imm_ != nullptr) { + // We have filled up the current memtable, but the previous + // one is still being compacted, so we wait. + Log(options_.info_log, "Current memtable full; waiting...\n"); + background_work_finished_signal_.Wait(); + } else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) { + // There are too many level-0 files. + Log(options_.info_log, "Too many L0 files; waiting...\n"); + background_work_finished_signal_.Wait(); + } else { + // Attempt to switch to a new memtable and trigger compaction of old + assert(versions_->PrevLogNumber() == 0); + uint64_t new_log_number = versions_->NewFileNumber(); + WritableFile* lfile = nullptr; + s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); + if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); + break; + } + delete log_; + delete logfile_; + logfile_ = lfile; + logfile_number_ = new_log_number; + log_ = new log::Writer(lfile); + imm_ = mem_; + has_imm_.store(true, std::memory_order_release); + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + force = false; // Do not force another compaction if have room + MaybeScheduleCompaction(); + } + } + return s; +} + +bool DBImpl::GetProperty(const Slice& property, std::string* value) { + value->clear(); + + MutexLock l(&mutex_); + Slice in = property; + Slice prefix("leveldb."); + if (!in.starts_with(prefix)) return false; + in.remove_prefix(prefix.size()); + + if (in.starts_with("num-files-at-level")) { + in.remove_prefix(strlen("num-files-at-level")); + uint64_t level; + bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); + if (!ok || level >= config::kNumLevels) { + return false; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "%d", + versions_->NumLevelFiles(static_cast(level))); + *value = buf; + return true; + } + } else if (in == "stats") { + char buf[200]; + snprintf(buf, sizeof(buf), + " Compactions\n" + "Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n" + "--------------------------------------------------\n"); + value->append(buf); + for (int level = 0; level < config::kNumLevels; level++) { + int files = versions_->NumLevelFiles(level); + if (stats_[level].micros > 0 || files > 0) { + snprintf(buf, sizeof(buf), "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", level, + files, versions_->NumLevelBytes(level) / 1048576.0, + stats_[level].micros / 1e6, + stats_[level].bytes_read / 1048576.0, + stats_[level].bytes_written / 1048576.0); + value->append(buf); + } + } + return true; + } else if (in == "sstables") { + *value = versions_->current()->DebugString(); + return true; + } else if (in == "approximate-memory-usage") { + size_t total_usage = options_.block_cache->TotalCharge(); + if (mem_) { + total_usage += mem_->ApproximateMemoryUsage(); + } + if (imm_) { + total_usage += imm_->ApproximateMemoryUsage(); + } + char buf[50]; + snprintf(buf, sizeof(buf), "%llu", + static_cast(total_usage)); + value->append(buf); + return true; + } + + return false; +} + +void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { + // TODO(opt): better implementation + Version* v; + { + MutexLock l(&mutex_); + versions_->current()->Ref(); + v = versions_->current(); + } + + for (int i = 0; i < n; i++) { + // Convert user_key into a corresponding internal key. + InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); + uint64_t start = versions_->ApproximateOffsetOf(v, k1); + uint64_t limit = versions_->ApproximateOffsetOf(v, k2); + sizes[i] = (limit >= start ? limit - start : 0); + } + + { + MutexLock l(&mutex_); + v->Unref(); + } +} + +// Default implementations of convenience methods that subclasses of DB +// can call if they wish +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { + WriteBatch batch; + batch.Put(key, value); + return Write(opt, &batch); +} + +Status DB::Delete(const WriteOptions& opt, const Slice& key) { + WriteBatch batch; + batch.Delete(key); + return Write(opt, &batch); +} + +DB::~DB() {} + +Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) { + *dbptr = nullptr; + + DBImpl* impl = new DBImpl(options, dbname); + impl->mutex_.Lock(); + VersionEdit edit; + // Recover handles create_if_missing, error_if_exists + bool save_manifest = false; + Status s = impl->Recover(&edit, &save_manifest); + if (s.ok() && impl->mem_ == nullptr) { + // Create new log and a corresponding memtable. + uint64_t new_log_number = impl->versions_->NewFileNumber(); + WritableFile* lfile; + s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), + &lfile); + if (s.ok()) { + edit.SetLogNumber(new_log_number); + impl->logfile_ = lfile; + impl->logfile_number_ = new_log_number; + impl->log_ = new log::Writer(lfile); + impl->mem_ = new MemTable(impl->internal_comparator_); + impl->mem_->Ref(); + } + } + if (s.ok() && save_manifest) { + edit.SetPrevLogNumber(0); // No older logs needed after recovery. + edit.SetLogNumber(impl->logfile_number_); + s = impl->versions_->LogAndApply(&edit, &impl->mutex_); + } + if (s.ok()) { + impl->DeleteObsoleteFiles(); + impl->MaybeScheduleCompaction(); + } + impl->mutex_.Unlock(); + if (s.ok()) { + assert(impl->mem_ != nullptr); + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +Snapshot::~Snapshot() {} + +Status DestroyDB(const std::string& dbname, const Options& options) { + Env* env = options.env; + std::vector filenames; + Status result = env->GetChildren(dbname, &filenames); + if (!result.ok()) { + // Ignore error in case directory does not exist + return Status::OK(); + } + + FileLock* lock; + const std::string lockname = LockFileName(dbname); + result = env->LockFile(lockname, &lock); + if (result.ok()) { + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type != kDBLockFile) { // Lock file will be deleted at end + Status del = env->DeleteFile(dbname + "/" + filenames[i]); + if (result.ok() && !del.ok()) { + result = del; + } + } + } + env->UnlockFile(lock); // Ignore error since state is already gone + env->DeleteFile(lockname); + env->DeleteDir(dbname); // Ignore error in case dir contains other files + } + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/db_impl.h b/PediatricPancreas/Pods/leveldb-library/db/db_impl.h new file mode 100644 index 0000000..ae87d6e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/db_impl.h @@ -0,0 +1,216 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_H_ + +#include +#include +#include +#include + +#include "db/dbformat.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +class MemTable; +class TableCache; +class Version; +class VersionEdit; +class VersionSet; + +class DBImpl : public DB { + public: + DBImpl(const Options& options, const std::string& dbname); + + DBImpl(const DBImpl&) = delete; + DBImpl& operator=(const DBImpl&) = delete; + + virtual ~DBImpl(); + + // Implementations of the DB interface + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); + virtual Status Delete(const WriteOptions&, const Slice& key); + virtual Status Write(const WriteOptions& options, WriteBatch* updates); + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + virtual const Snapshot* GetSnapshot(); + virtual void ReleaseSnapshot(const Snapshot* snapshot); + virtual bool GetProperty(const Slice& property, std::string* value); + virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); + virtual void CompactRange(const Slice* begin, const Slice* end); + + // Extra methods (for testing) that are not in the public DB interface + + // Compact any files in the named level that overlap [*begin,*end] + void TEST_CompactRange(int level, const Slice* begin, const Slice* end); + + // Force current memtable contents to be compacted. + Status TEST_CompactMemTable(); + + // Return an internal iterator over the current state of the database. + // The keys of this iterator are internal keys (see format.h). + // The returned iterator should be deleted when no longer needed. + Iterator* TEST_NewInternalIterator(); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t TEST_MaxNextLevelOverlappingBytes(); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. + void RecordReadSample(Slice key); + + private: + friend class DB; + struct CompactionState; + struct Writer; + + // Information for a manual compaction + struct ManualCompaction { + int level; + bool done; + const InternalKey* begin; // null means beginning of key range + const InternalKey* end; // null means end of key range + InternalKey tmp_storage; // Used to keep track of compaction progress + }; + + // Per level compaction stats. stats_[level] stores the stats for + // compactions that produced data for the specified "level". + struct CompactionStats { + CompactionStats() : micros(0), bytes_read(0), bytes_written(0) {} + + void Add(const CompactionStats& c) { + this->micros += c.micros; + this->bytes_read += c.bytes_read; + this->bytes_written += c.bytes_written; + } + + int64_t micros; + int64_t bytes_read; + int64_t bytes_written; + }; + + Iterator* NewInternalIterator(const ReadOptions&, + SequenceNumber* latest_snapshot, + uint32_t* seed); + + Status NewDB(); + + // Recover the descriptor from persistent storage. May do a significant + // amount of work to recover recently logged updates. Any changes to + // be made to the descriptor are added to *edit. + Status Recover(VersionEdit* edit, bool* save_manifest) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void MaybeIgnoreError(Status* s) const; + + // Delete any unneeded files and stale in-memory entries. + void DeleteObsoleteFiles() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Compact the in-memory write buffer to disk. Switches to a new + // log-file/memtable and writes a new descriptor iff successful. + // Errors are recorded in bg_error_. + void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status RecoverLogFile(uint64_t log_number, bool last_log, bool* save_manifest, + VersionEdit* edit, SequenceNumber* max_sequence) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status MakeRoomForWrite(bool force /* compact even if there is room? */) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + WriteBatch* BuildBatchGroup(Writer** last_writer) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void RecordBackgroundError(const Status& s); + + void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + static void BGWork(void* db); + void BackgroundCall(); + void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void CleanupCompaction(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + Status DoCompactionWork(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status OpenCompactionOutputFile(CompactionState* compact); + Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); + Status InstallCompactionResults(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + const Comparator* user_comparator() const { + return internal_comparator_.user_comparator(); + } + + // Constant after construction + Env* const env_; + const InternalKeyComparator internal_comparator_; + const InternalFilterPolicy internal_filter_policy_; + const Options options_; // options_.comparator == &internal_comparator_ + const bool owns_info_log_; + const bool owns_cache_; + const std::string dbname_; + + // table_cache_ provides its own synchronization + TableCache* const table_cache_; + + // Lock over the persistent DB state. Non-null iff successfully acquired. + FileLock* db_lock_; + + // State below is protected by mutex_ + port::Mutex mutex_; + std::atomic shutting_down_; + port::CondVar background_work_finished_signal_ GUARDED_BY(mutex_); + MemTable* mem_; + MemTable* imm_ GUARDED_BY(mutex_); // Memtable being compacted + std::atomic has_imm_; // So bg thread can detect non-null imm_ + WritableFile* logfile_; + uint64_t logfile_number_ GUARDED_BY(mutex_); + log::Writer* log_; + uint32_t seed_ GUARDED_BY(mutex_); // For sampling. + + // Queue of writers. + std::deque writers_ GUARDED_BY(mutex_); + WriteBatch* tmp_batch_ GUARDED_BY(mutex_); + + SnapshotList snapshots_ GUARDED_BY(mutex_); + + // Set of table files to protect from deletion because they are + // part of ongoing compactions. + std::set pending_outputs_ GUARDED_BY(mutex_); + + // Has a background compaction been scheduled or is running? + bool background_compaction_scheduled_ GUARDED_BY(mutex_); + + ManualCompaction* manual_compaction_ GUARDED_BY(mutex_); + + VersionSet* const versions_; + + // Have we encountered a background error in paranoid mode? + Status bg_error_ GUARDED_BY(mutex_); + + CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_); +}; + +// Sanitize db options. The caller should delete result.info_log if +// it is not equal to src.info_log. +Options SanitizeOptions(const std::string& db, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/db_iter.cc b/PediatricPancreas/Pods/leveldb-library/db/db_iter.cc new file mode 100644 index 0000000..8ff288e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/db_iter.cc @@ -0,0 +1,309 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_iter.h" + +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/random.h" + +namespace leveldb { + +#if 0 +static void DumpInternalIter(Iterator* iter) { + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey k; + if (!ParseInternalKey(iter->key(), &k)) { + fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); + } else { + fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); + } + } +} +#endif + +namespace { + +// Memtables and sstables that make the DB representation contain +// (userkey,seq,type) => uservalue entries. DBIter +// combines multiple entries for the same userkey found in the DB +// representation into a single entry while accounting for sequence +// numbers, deletion markers, overwrites, etc. +class DBIter : public Iterator { + public: + // Which direction is the iterator currently moving? + // (1) When moving forward, the internal iterator is positioned at + // the exact entry that yields this->key(), this->value() + // (2) When moving backwards, the internal iterator is positioned + // just before all entries whose user key == this->key(). + enum Direction { kForward, kReverse }; + + DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s, + uint32_t seed) + : db_(db), + user_comparator_(cmp), + iter_(iter), + sequence_(s), + direction_(kForward), + valid_(false), + rnd_(seed), + bytes_until_read_sampling_(RandomCompactionPeriod()) {} + + DBIter(const DBIter&) = delete; + DBIter& operator=(const DBIter&) = delete; + + virtual ~DBIter() { delete iter_; } + virtual bool Valid() const { return valid_; } + virtual Slice key() const { + assert(valid_); + return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; + } + virtual Slice value() const { + assert(valid_); + return (direction_ == kForward) ? iter_->value() : saved_value_; + } + virtual Status status() const { + if (status_.ok()) { + return iter_->status(); + } else { + return status_; + } + } + + virtual void Next(); + virtual void Prev(); + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + + private: + void FindNextUserEntry(bool skipping, std::string* skip); + void FindPrevUserEntry(); + bool ParseKey(ParsedInternalKey* key); + + inline void SaveKey(const Slice& k, std::string* dst) { + dst->assign(k.data(), k.size()); + } + + inline void ClearSavedValue() { + if (saved_value_.capacity() > 1048576) { + std::string empty; + swap(empty, saved_value_); + } else { + saved_value_.clear(); + } + } + + // Picks the number of bytes that can be read until a compaction is scheduled. + size_t RandomCompactionPeriod() { + return rnd_.Uniform(2 * config::kReadBytesPeriod); + } + + DBImpl* db_; + const Comparator* const user_comparator_; + Iterator* const iter_; + SequenceNumber const sequence_; + Status status_; + std::string saved_key_; // == current key when direction_==kReverse + std::string saved_value_; // == current raw value when direction_==kReverse + Direction direction_; + bool valid_; + Random rnd_; + size_t bytes_until_read_sampling_; +}; + +inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { + Slice k = iter_->key(); + + size_t bytes_read = k.size() + iter_->value().size(); + while (bytes_until_read_sampling_ < bytes_read) { + bytes_until_read_sampling_ += RandomCompactionPeriod(); + db_->RecordReadSample(k); + } + assert(bytes_until_read_sampling_ >= bytes_read); + bytes_until_read_sampling_ -= bytes_read; + + if (!ParseInternalKey(k, ikey)) { + status_ = Status::Corruption("corrupted internal key in DBIter"); + return false; + } else { + return true; + } +} + +void DBIter::Next() { + assert(valid_); + + if (direction_ == kReverse) { // Switch directions? + direction_ = kForward; + // iter_ is pointing just before the entries for this->key(), + // so advance into the range of entries for this->key() and then + // use the normal skipping code below. + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } else { + iter_->Next(); + } + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + return; + } + // saved_key_ already contains the key to skip past. + } else { + // Store in saved_key_ the current key so we skip it below. + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + } + + FindNextUserEntry(true, &saved_key_); +} + +void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { + // Loop until we hit an acceptable entry to yield + assert(iter_->Valid()); + assert(direction_ == kForward); + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + switch (ikey.type) { + case kTypeDeletion: + // Arrange to skip all upcoming entries for this key since + // they are hidden by this deletion. + SaveKey(ikey.user_key, skip); + skipping = true; + break; + case kTypeValue: + if (skipping && + user_comparator_->Compare(ikey.user_key, *skip) <= 0) { + // Entry hidden + } else { + valid_ = true; + saved_key_.clear(); + return; + } + break; + } + } + iter_->Next(); + } while (iter_->Valid()); + saved_key_.clear(); + valid_ = false; +} + +void DBIter::Prev() { + assert(valid_); + + if (direction_ == kForward) { // Switch directions? + // iter_ is pointing at the current entry. Scan backwards until + // the key changes so we can use the normal reverse scanning code. + assert(iter_->Valid()); // Otherwise valid_ would have been false + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + while (true) { + iter_->Prev(); + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + return; + } + if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) < + 0) { + break; + } + } + direction_ = kReverse; + } + + FindPrevUserEntry(); +} + +void DBIter::FindPrevUserEntry() { + assert(direction_ == kReverse); + + ValueType value_type = kTypeDeletion; + if (iter_->Valid()) { + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + if ((value_type != kTypeDeletion) && + user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { + // We encountered a non-deleted value in entries for previous keys, + break; + } + value_type = ikey.type; + if (value_type == kTypeDeletion) { + saved_key_.clear(); + ClearSavedValue(); + } else { + Slice raw_value = iter_->value(); + if (saved_value_.capacity() > raw_value.size() + 1048576) { + std::string empty; + swap(empty, saved_value_); + } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + saved_value_.assign(raw_value.data(), raw_value.size()); + } + } + iter_->Prev(); + } while (iter_->Valid()); + } + + if (value_type == kTypeDeletion) { + // End + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + direction_ = kForward; + } else { + valid_ = true; + } +} + +void DBIter::Seek(const Slice& target) { + direction_ = kForward; + ClearSavedValue(); + saved_key_.clear(); + AppendInternalKey(&saved_key_, + ParsedInternalKey(target, sequence_, kValueTypeForSeek)); + iter_->Seek(saved_key_); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToFirst() { + direction_ = kForward; + ClearSavedValue(); + iter_->SeekToFirst(); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToLast() { + direction_ = kReverse; + ClearSavedValue(); + iter_->SeekToLast(); + FindPrevUserEntry(); +} + +} // anonymous namespace + +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed) { + return new DBIter(db, user_key_comparator, internal_iter, sequence, seed); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/db_iter.h b/PediatricPancreas/Pods/leveldb-library/db/db_iter.h new file mode 100644 index 0000000..fd93e91 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/db_iter.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ +#define STORAGE_LEVELDB_DB_DB_ITER_H_ + +#include + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class DBImpl; + +// Return a new iterator that converts internal keys (yielded by +// "*internal_iter") that were live at the specified "sequence" number +// into appropriate user keys. +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/dbformat.cc b/PediatricPancreas/Pods/leveldb-library/db/dbformat.cc new file mode 100644 index 0000000..69e8dc6 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/dbformat.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/dbformat.h" + +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { + +static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { + assert(seq <= kMaxSequenceNumber); + assert(t <= kValueTypeForSeek); + return (seq << 8) | t; +} + +void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { + result->append(key.user_key.data(), key.user_key.size()); + PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); +} + +std::string ParsedInternalKey::DebugString() const { + char buf[50]; + snprintf(buf, sizeof(buf), "' @ %llu : %d", (unsigned long long)sequence, + int(type)); + std::string result = "'"; + result += EscapeString(user_key.ToString()); + result += buf; + return result; +} + +std::string InternalKey::DebugString() const { + std::string result; + ParsedInternalKey parsed; + if (ParseInternalKey(rep_, &parsed)) { + result = parsed.DebugString(); + } else { + result = "(bad)"; + result.append(EscapeString(rep_)); + } + return result; +} + +const char* InternalKeyComparator::Name() const { + return "leveldb.InternalKeyComparator"; +} + +int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { + // Order by: + // increasing user key (according to user-supplied comparator) + // decreasing sequence number + // decreasing type (though sequence# should be enough to disambiguate) + int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); + if (r == 0) { + const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); + const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); + if (anum > bnum) { + r = -1; + } else if (anum < bnum) { + r = +1; + } + } + return r; +} + +void InternalKeyComparator::FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Attempt to shorten the user portion of the key + Slice user_start = ExtractUserKey(*start); + Slice user_limit = ExtractUserKey(limit); + std::string tmp(user_start.data(), user_start.size()); + user_comparator_->FindShortestSeparator(&tmp, user_limit); + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*start, tmp) < 0); + assert(this->Compare(tmp, limit) < 0); + start->swap(tmp); + } +} + +void InternalKeyComparator::FindShortSuccessor(std::string* key) const { + Slice user_key = ExtractUserKey(*key); + std::string tmp(user_key.data(), user_key.size()); + user_comparator_->FindShortSuccessor(&tmp); + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*key, tmp) < 0); + key->swap(tmp); + } +} + +const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); } + +void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, + std::string* dst) const { + // We rely on the fact that the code in table.cc does not mind us + // adjusting keys[]. + Slice* mkey = const_cast(keys); + for (int i = 0; i < n; i++) { + mkey[i] = ExtractUserKey(keys[i]); + // TODO(sanjay): Suppress dups? + } + user_policy_->CreateFilter(keys, n, dst); +} + +bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { + return user_policy_->KeyMayMatch(ExtractUserKey(key), f); +} + +LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { + size_t usize = user_key.size(); + size_t needed = usize + 13; // A conservative estimate + char* dst; + if (needed <= sizeof(space_)) { + dst = space_; + } else { + dst = new char[needed]; + } + start_ = dst; + dst = EncodeVarint32(dst, usize + 8); + kstart_ = dst; + memcpy(dst, user_key.data(), usize); + dst += usize; + EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); + dst += 8; + end_ = dst; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/dbformat.h b/PediatricPancreas/Pods/leveldb-library/db/dbformat.h new file mode 100644 index 0000000..013028a --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/dbformat.h @@ -0,0 +1,218 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_ +#define STORAGE_LEVELDB_DB_DBFORMAT_H_ + +#include + +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "leveldb/slice.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +// Grouping of constants. We may want to make some of these +// parameters set via options. +namespace config { +static const int kNumLevels = 7; + +// Level-0 compaction is started when we hit this many files. +static const int kL0_CompactionTrigger = 4; + +// Soft limit on number of level-0 files. We slow down writes at this point. +static const int kL0_SlowdownWritesTrigger = 8; + +// Maximum number of level-0 files. We stop writes at this point. +static const int kL0_StopWritesTrigger = 12; + +// Maximum level to which a new compacted memtable is pushed if it +// does not create overlap. We try to push to level 2 to avoid the +// relatively expensive level 0=>1 compactions and to avoid some +// expensive manifest file operations. We do not push all the way to +// the largest level since that can generate a lot of wasted disk +// space if the same key space is being repeatedly overwritten. +static const int kMaxMemCompactLevel = 2; + +// Approximate gap in bytes between samples of data read during iteration. +static const int kReadBytesPeriod = 1048576; + +} // namespace config + +class InternalKey; + +// Value types encoded as the last component of internal keys. +// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk +// data structures. +enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 }; +// kValueTypeForSeek defines the ValueType that should be passed when +// constructing a ParsedInternalKey object for seeking to a particular +// sequence number (since we sort sequence numbers in decreasing order +// and the value type is embedded as the low 8 bits in the sequence +// number in internal keys, we need to use the highest-numbered +// ValueType, not the lowest). +static const ValueType kValueTypeForSeek = kTypeValue; + +typedef uint64_t SequenceNumber; + +// We leave eight bits empty at the bottom so a type and sequence# +// can be packed together into 64-bits. +static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1); + +struct ParsedInternalKey { + Slice user_key; + SequenceNumber sequence; + ValueType type; + + ParsedInternalKey() {} // Intentionally left uninitialized (for speed) + ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) + : user_key(u), sequence(seq), type(t) {} + std::string DebugString() const; +}; + +// Return the length of the encoding of "key". +inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { + return key.user_key.size() + 8; +} + +// Append the serialization of "key" to *result. +void AppendInternalKey(std::string* result, const ParsedInternalKey& key); + +// Attempt to parse an internal key from "internal_key". On success, +// stores the parsed data in "*result", and returns true. +// +// On error, returns false, leaves "*result" in an undefined state. +bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result); + +// Returns the user key portion of an internal key. +inline Slice ExtractUserKey(const Slice& internal_key) { + assert(internal_key.size() >= 8); + return Slice(internal_key.data(), internal_key.size() - 8); +} + +// A comparator for internal keys that uses a specified comparator for +// the user key portion and breaks ties by decreasing sequence number. +class InternalKeyComparator : public Comparator { + private: + const Comparator* user_comparator_; + + public: + explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {} + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + const Comparator* user_comparator() const { return user_comparator_; } + + int Compare(const InternalKey& a, const InternalKey& b) const; +}; + +// Filter policy wrapper that converts from internal keys to user keys +class InternalFilterPolicy : public FilterPolicy { + private: + const FilterPolicy* const user_policy_; + + public: + explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {} + virtual const char* Name() const; + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; +}; + +// Modules in this directory should keep internal keys wrapped inside +// the following class instead of plain strings so that we do not +// incorrectly use string comparisons instead of an InternalKeyComparator. +class InternalKey { + private: + std::string rep_; + + public: + InternalKey() {} // Leave rep_ as empty to indicate it is invalid + InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { + AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); + } + + void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } + Slice Encode() const { + assert(!rep_.empty()); + return rep_; + } + + Slice user_key() const { return ExtractUserKey(rep_); } + + void SetFrom(const ParsedInternalKey& p) { + rep_.clear(); + AppendInternalKey(&rep_, p); + } + + void Clear() { rep_.clear(); } + + std::string DebugString() const; +}; + +inline int InternalKeyComparator::Compare(const InternalKey& a, + const InternalKey& b) const { + return Compare(a.Encode(), b.Encode()); +} + +inline bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result) { + const size_t n = internal_key.size(); + if (n < 8) return false; + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + result->sequence = num >> 8; + result->type = static_cast(c); + result->user_key = Slice(internal_key.data(), n - 8); + return (c <= static_cast(kTypeValue)); +} + +// A helper class useful for DBImpl::Get() +class LookupKey { + public: + // Initialize *this for looking up user_key at a snapshot with + // the specified sequence number. + LookupKey(const Slice& user_key, SequenceNumber sequence); + + LookupKey(const LookupKey&) = delete; + LookupKey& operator=(const LookupKey&) = delete; + + ~LookupKey(); + + // Return a key suitable for lookup in a MemTable. + Slice memtable_key() const { return Slice(start_, end_ - start_); } + + // Return an internal key (suitable for passing to an internal iterator) + Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } + + // Return the user key + Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } + + private: + // We construct a char array of the form: + // klength varint32 <-- start_ + // userkey char[klength] <-- kstart_ + // tag uint64 + // <-- end_ + // The array is a suitable MemTable key. + // The suffix starting with "userkey" can be used as an InternalKey. + const char* start_; + const char* kstart_; + const char* end_; + char space_[200]; // Avoid allocation for short keys +}; + +inline LookupKey::~LookupKey() { + if (start_ != space_) delete[] start_; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DBFORMAT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/dumpfile.cc b/PediatricPancreas/Pods/leveldb-library/db/dumpfile.cc new file mode 100644 index 0000000..9d22d58 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/dumpfile.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/dumpfile.h" + +#include + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "util/logging.h" + +namespace leveldb { + +namespace { + +bool GuessType(const std::string& fname, FileType* type) { + size_t pos = fname.rfind('/'); + std::string basename; + if (pos == std::string::npos) { + basename = fname; + } else { + basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1); + } + uint64_t ignored; + return ParseFileName(basename, &ignored, type); +} + +// Notified when log reader encounters corruption. +class CorruptionReporter : public log::Reader::Reporter { + public: + virtual void Corruption(size_t bytes, const Status& status) { + std::string r = "corruption: "; + AppendNumberTo(&r, bytes); + r += " bytes; "; + r += status.ToString(); + r.push_back('\n'); + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Print contents of a log file. (*func)() is called on every record. +Status PrintLogContents(Env* env, const std::string& fname, + void (*func)(uint64_t, Slice, WritableFile*), + WritableFile* dst) { + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + CorruptionReporter reporter; + reporter.dst_ = dst; + log::Reader reader(file, &reporter, true, 0); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch)) { + (*func)(reader.LastRecordOffset(), record, dst); + } + delete file; + return Status::OK(); +} + +// Called on every item found in a WriteBatch. +class WriteBatchItemPrinter : public WriteBatch::Handler { + public: + virtual void Put(const Slice& key, const Slice& value) { + std::string r = " put '"; + AppendEscapedStringTo(&r, key); + r += "' '"; + AppendEscapedStringTo(&r, value); + r += "'\n"; + dst_->Append(r); + } + virtual void Delete(const Slice& key) { + std::string r = " del '"; + AppendEscapedStringTo(&r, key); + r += "'\n"; + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Called on every log record (each one of which is a WriteBatch) +// found in a kLogFile. +static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + if (record.size() < 12) { + r += "log record length "; + AppendNumberTo(&r, record.size()); + r += " is too small\n"; + dst->Append(r); + return; + } + WriteBatch batch; + WriteBatchInternal::SetContents(&batch, record); + r += "sequence "; + AppendNumberTo(&r, WriteBatchInternal::Sequence(&batch)); + r.push_back('\n'); + dst->Append(r); + WriteBatchItemPrinter batch_item_printer; + batch_item_printer.dst_ = dst; + Status s = batch.Iterate(&batch_item_printer); + if (!s.ok()) { + dst->Append(" error: " + s.ToString() + "\n"); + } +} + +Status DumpLog(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, WriteBatchPrinter, dst); +} + +// Called on every log record (each one of which is a WriteBatch) +// found in a kDescriptorFile. +static void VersionEditPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + VersionEdit edit; + Status s = edit.DecodeFrom(record); + if (!s.ok()) { + r += s.ToString(); + r.push_back('\n'); + } else { + r += edit.DebugString(); + } + dst->Append(r); +} + +Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, VersionEditPrinter, dst); +} + +Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) { + uint64_t file_size; + RandomAccessFile* file = nullptr; + Table* table = nullptr; + Status s = env->GetFileSize(fname, &file_size); + if (s.ok()) { + s = env->NewRandomAccessFile(fname, &file); + } + if (s.ok()) { + // We use the default comparator, which may or may not match the + // comparator used in this database. However this should not cause + // problems since we only use Table operations that do not require + // any comparisons. In particular, we do not call Seek or Prev. + s = Table::Open(Options(), file, file_size, &table); + } + if (!s.ok()) { + delete table; + delete file; + return s; + } + + ReadOptions ro; + ro.fill_cache = false; + Iterator* iter = table->NewIterator(ro); + std::string r; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + r.clear(); + ParsedInternalKey key; + if (!ParseInternalKey(iter->key(), &key)) { + r = "badkey '"; + AppendEscapedStringTo(&r, iter->key()); + r += "' => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } else { + r = "'"; + AppendEscapedStringTo(&r, key.user_key); + r += "' @ "; + AppendNumberTo(&r, key.sequence); + r += " : "; + if (key.type == kTypeDeletion) { + r += "del"; + } else if (key.type == kTypeValue) { + r += "val"; + } else { + AppendNumberTo(&r, key.type); + } + r += " => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } + } + s = iter->status(); + if (!s.ok()) { + dst->Append("iterator error: " + s.ToString() + "\n"); + } + + delete iter; + delete table; + delete file; + return Status::OK(); +} + +} // namespace + +Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) { + FileType ftype; + if (!GuessType(fname, &ftype)) { + return Status::InvalidArgument(fname + ": unknown file type"); + } + switch (ftype) { + case kLogFile: + return DumpLog(env, fname, dst); + case kDescriptorFile: + return DumpDescriptor(env, fname, dst); + case kTableFile: + return DumpTable(env, fname, dst); + default: + break; + } + return Status::InvalidArgument(fname + ": not a dump-able file type"); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/filename.cc b/PediatricPancreas/Pods/leveldb-library/db/filename.cc new file mode 100644 index 0000000..85de45c --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/filename.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include +#include + +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "util/logging.h" + +namespace leveldb { + +// A utility routine: write "data" to the named file and Sync() it. +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname); + +static std::string MakeFileName(const std::string& dbname, uint64_t number, + const char* suffix) { + char buf[100]; + snprintf(buf, sizeof(buf), "/%06llu.%s", + static_cast(number), suffix); + return dbname + buf; +} + +std::string LogFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "log"); +} + +std::string TableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "ldb"); +} + +std::string SSTTableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "sst"); +} + +std::string DescriptorFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + char buf[100]; + snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", + static_cast(number)); + return dbname + buf; +} + +std::string CurrentFileName(const std::string& dbname) { + return dbname + "/CURRENT"; +} + +std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; } + +std::string TempFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "dbtmp"); +} + +std::string InfoLogFileName(const std::string& dbname) { + return dbname + "/LOG"; +} + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname) { + return dbname + "/LOG.old"; +} + +// Owned filenames have the form: +// dbname/CURRENT +// dbname/LOCK +// dbname/LOG +// dbname/LOG.old +// dbname/MANIFEST-[0-9]+ +// dbname/[0-9]+.(log|sst|ldb) +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type) { + Slice rest(filename); + if (rest == "CURRENT") { + *number = 0; + *type = kCurrentFile; + } else if (rest == "LOCK") { + *number = 0; + *type = kDBLockFile; + } else if (rest == "LOG" || rest == "LOG.old") { + *number = 0; + *type = kInfoLogFile; + } else if (rest.starts_with("MANIFEST-")) { + rest.remove_prefix(strlen("MANIFEST-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kDescriptorFile; + *number = num; + } else { + // Avoid strtoull() to keep filename format independent of the + // current locale + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + Slice suffix = rest; + if (suffix == Slice(".log")) { + *type = kLogFile; + } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) { + *type = kTableFile; + } else if (suffix == Slice(".dbtmp")) { + *type = kTempFile; + } else { + return false; + } + *number = num; + } + return true; +} + +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number) { + // Remove leading "dbname/" and add newline to manifest file name + std::string manifest = DescriptorFileName(dbname, descriptor_number); + Slice contents = manifest; + assert(contents.starts_with(dbname + "/")); + contents.remove_prefix(dbname.size() + 1); + std::string tmp = TempFileName(dbname, descriptor_number); + Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); + if (s.ok()) { + s = env->RenameFile(tmp, CurrentFileName(dbname)); + } + if (!s.ok()) { + env->DeleteFile(tmp); + } + return s; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/filename.h b/PediatricPancreas/Pods/leveldb-library/db/filename.h new file mode 100644 index 0000000..524e813 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/filename.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// File names used by DB code + +#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ +#define STORAGE_LEVELDB_DB_FILENAME_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +enum FileType { + kLogFile, + kDBLockFile, + kTableFile, + kDescriptorFile, + kCurrentFile, + kTempFile, + kInfoLogFile // Either the current one, or an old one +}; + +// Return the name of the log file with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string LogFileName(const std::string& dbname, uint64_t number); + +// Return the name of the sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string TableFileName(const std::string& dbname, uint64_t number); + +// Return the legacy file name for an sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string SSTTableFileName(const std::string& dbname, uint64_t number); + +// Return the name of the descriptor file for the db named by +// "dbname" and the specified incarnation number. The result will be +// prefixed with "dbname". +std::string DescriptorFileName(const std::string& dbname, uint64_t number); + +// Return the name of the current file. This file contains the name +// of the current manifest file. The result will be prefixed with +// "dbname". +std::string CurrentFileName(const std::string& dbname); + +// Return the name of the lock file for the db named by +// "dbname". The result will be prefixed with "dbname". +std::string LockFileName(const std::string& dbname); + +// Return the name of a temporary file owned by the db named "dbname". +// The result will be prefixed with "dbname". +std::string TempFileName(const std::string& dbname, uint64_t number); + +// Return the name of the info log file for "dbname". +std::string InfoLogFileName(const std::string& dbname); + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname); + +// If filename is a leveldb file, store the type of the file in *type. +// The number encoded in the filename is stored in *number. If the +// filename was successfully parsed, returns true. Else return false. +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type); + +// Make the CURRENT file point to the descriptor file with the +// specified number. +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/log_format.h b/PediatricPancreas/Pods/leveldb-library/db/log_format.h new file mode 100644 index 0000000..356e69f --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/log_format.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Log format information shared by reader and writer. +// See ../doc/log_format.md for more detail. + +#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ +#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ + +namespace leveldb { +namespace log { + +enum RecordType { + // Zero is reserved for preallocated files + kZeroType = 0, + + kFullType = 1, + + // For fragments + kFirstType = 2, + kMiddleType = 3, + kLastType = 4 +}; +static const int kMaxRecordType = kLastType; + +static const int kBlockSize = 32768; + +// Header is checksum (4 bytes), length (2 bytes), type (1 byte). +static const int kHeaderSize = 4 + 2 + 1; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/log_reader.cc b/PediatricPancreas/Pods/leveldb-library/db/log_reader.cc new file mode 100644 index 0000000..f472723 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/log_reader.cc @@ -0,0 +1,274 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Reader::Reporter::~Reporter() {} + +Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset) + : file_(file), + reporter_(reporter), + checksum_(checksum), + backing_store_(new char[kBlockSize]), + buffer_(), + eof_(false), + last_record_offset_(0), + end_of_buffer_offset_(0), + initial_offset_(initial_offset), + resyncing_(initial_offset > 0) {} + +Reader::~Reader() { delete[] backing_store_; } + +bool Reader::SkipToInitialBlock() { + const size_t offset_in_block = initial_offset_ % kBlockSize; + uint64_t block_start_location = initial_offset_ - offset_in_block; + + // Don't search a block if we'd be in the trailer + if (offset_in_block > kBlockSize - 6) { + block_start_location += kBlockSize; + } + + end_of_buffer_offset_ = block_start_location; + + // Skip to start of first block that can contain the initial record + if (block_start_location > 0) { + Status skip_status = file_->Skip(block_start_location); + if (!skip_status.ok()) { + ReportDrop(block_start_location, skip_status); + return false; + } + } + + return true; +} + +bool Reader::ReadRecord(Slice* record, std::string* scratch) { + if (last_record_offset_ < initial_offset_) { + if (!SkipToInitialBlock()) { + return false; + } + } + + scratch->clear(); + record->clear(); + bool in_fragmented_record = false; + // Record offset of the logical record that we're reading + // 0 is a dummy value to make compilers happy + uint64_t prospective_record_offset = 0; + + Slice fragment; + while (true) { + const unsigned int record_type = ReadPhysicalRecord(&fragment); + + // ReadPhysicalRecord may have only had an empty trailer remaining in its + // internal buffer. Calculate the offset of the next physical record now + // that it has returned, properly accounting for its header size. + uint64_t physical_record_offset = + end_of_buffer_offset_ - buffer_.size() - kHeaderSize - fragment.size(); + + if (resyncing_) { + if (record_type == kMiddleType) { + continue; + } else if (record_type == kLastType) { + resyncing_ = false; + continue; + } else { + resyncing_ = false; + } + } + + switch (record_type) { + case kFullType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(1)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->clear(); + *record = fragment; + last_record_offset_ = prospective_record_offset; + return true; + + case kFirstType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(2)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->assign(fragment.data(), fragment.size()); + in_fragmented_record = true; + break; + + case kMiddleType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(1)"); + } else { + scratch->append(fragment.data(), fragment.size()); + } + break; + + case kLastType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(2)"); + } else { + scratch->append(fragment.data(), fragment.size()); + *record = Slice(*scratch); + last_record_offset_ = prospective_record_offset; + return true; + } + break; + + case kEof: + if (in_fragmented_record) { + // This can be caused by the writer dying immediately after + // writing a physical record but before completing the next; don't + // treat it as a corruption, just ignore the entire logical record. + scratch->clear(); + } + return false; + + case kBadRecord: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "error in middle of record"); + in_fragmented_record = false; + scratch->clear(); + } + break; + + default: { + char buf[40]; + snprintf(buf, sizeof(buf), "unknown record type %u", record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + buf); + in_fragmented_record = false; + scratch->clear(); + break; + } + } + } + return false; +} + +uint64_t Reader::LastRecordOffset() { return last_record_offset_; } + +void Reader::ReportCorruption(uint64_t bytes, const char* reason) { + ReportDrop(bytes, Status::Corruption(reason)); +} + +void Reader::ReportDrop(uint64_t bytes, const Status& reason) { + if (reporter_ != nullptr && + end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { + reporter_->Corruption(static_cast(bytes), reason); + } +} + +unsigned int Reader::ReadPhysicalRecord(Slice* result) { + while (true) { + if (buffer_.size() < kHeaderSize) { + if (!eof_) { + // Last read was a full read, so this is a trailer to skip + buffer_.clear(); + Status status = file_->Read(kBlockSize, &buffer_, backing_store_); + end_of_buffer_offset_ += buffer_.size(); + if (!status.ok()) { + buffer_.clear(); + ReportDrop(kBlockSize, status); + eof_ = true; + return kEof; + } else if (buffer_.size() < kBlockSize) { + eof_ = true; + } + continue; + } else { + // Note that if buffer_ is non-empty, we have a truncated header at the + // end of the file, which can be caused by the writer crashing in the + // middle of writing the header. Instead of considering this an error, + // just report EOF. + buffer_.clear(); + return kEof; + } + } + + // Parse the header + const char* header = buffer_.data(); + const uint32_t a = static_cast(header[4]) & 0xff; + const uint32_t b = static_cast(header[5]) & 0xff; + const unsigned int type = header[6]; + const uint32_t length = a | (b << 8); + if (kHeaderSize + length > buffer_.size()) { + size_t drop_size = buffer_.size(); + buffer_.clear(); + if (!eof_) { + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + // If the end of the file has been reached without reading |length| bytes + // of payload, assume the writer died in the middle of writing the record. + // Don't report a corruption. + return kEof; + } + + if (type == kZeroType && length == 0) { + // Skip zero length record without reporting any drops since + // such records are produced by the mmap based writing code in + // env_posix.cc that preallocates file regions. + buffer_.clear(); + return kBadRecord; + } + + // Check crc + if (checksum_) { + uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); + uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); + if (actual_crc != expected_crc) { + // Drop the rest of the buffer since "length" itself may have + // been corrupted and if we trust it, we could find some + // fragment of a real log record that just happens to look + // like a valid log record. + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "checksum mismatch"); + return kBadRecord; + } + } + + buffer_.remove_prefix(kHeaderSize + length); + + // Skip physical record that started before initial_offset_ + if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < + initial_offset_) { + result->clear(); + return kBadRecord; + } + + *result = Slice(header + kHeaderSize, length); + return type; + } +} + +} // namespace log +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/log_reader.h b/PediatricPancreas/Pods/leveldb-library/db/log_reader.h new file mode 100644 index 0000000..001da89 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/log_reader.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ +#define STORAGE_LEVELDB_DB_LOG_READER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class SequentialFile; + +namespace log { + +class Reader { + public: + // Interface for reporting errors. + class Reporter { + public: + virtual ~Reporter(); + + // Some corruption was detected. "size" is the approximate number + // of bytes dropped due to the corruption. + virtual void Corruption(size_t bytes, const Status& status) = 0; + }; + + // Create a reader that will return log records from "*file". + // "*file" must remain live while this Reader is in use. + // + // If "reporter" is non-null, it is notified whenever some data is + // dropped due to a detected corruption. "*reporter" must remain + // live while this Reader is in use. + // + // If "checksum" is true, verify checksums if available. + // + // The Reader will start reading at the first record located at physical + // position >= initial_offset within the file. + Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset); + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + ~Reader(); + + // Read the next record into *record. Returns true if read + // successfully, false if we hit end of the input. May use + // "*scratch" as temporary storage. The contents filled in *record + // will only be valid until the next mutating operation on this + // reader or the next mutation to *scratch. + bool ReadRecord(Slice* record, std::string* scratch); + + // Returns the physical offset of the last record returned by ReadRecord. + // + // Undefined before the first call to ReadRecord. + uint64_t LastRecordOffset(); + + private: + // Extend record types with the following special values + enum { + kEof = kMaxRecordType + 1, + // Returned whenever we find an invalid physical record. + // Currently there are three situations in which this happens: + // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) + // * The record is a 0-length record (No drop is reported) + // * The record is below constructor's initial_offset (No drop is reported) + kBadRecord = kMaxRecordType + 2 + }; + + // Skips all blocks that are completely before "initial_offset_". + // + // Returns true on success. Handles reporting. + bool SkipToInitialBlock(); + + // Return type, or one of the preceding special values + unsigned int ReadPhysicalRecord(Slice* result); + + // Reports dropped bytes to the reporter. + // buffer_ must be updated to remove the dropped bytes prior to invocation. + void ReportCorruption(uint64_t bytes, const char* reason); + void ReportDrop(uint64_t bytes, const Status& reason); + + SequentialFile* const file_; + Reporter* const reporter_; + bool const checksum_; + char* const backing_store_; + Slice buffer_; + bool eof_; // Last Read() indicated EOF by returning < kBlockSize + + // Offset of the last record returned by ReadRecord. + uint64_t last_record_offset_; + // Offset of the first location past the end of buffer_. + uint64_t end_of_buffer_offset_; + + // Offset at which to start looking for the first record to return + uint64_t const initial_offset_; + + // True if we are resynchronizing after a seek (initial_offset_ > 0). In + // particular, a run of kMiddleType and kLastType records can be silently + // skipped in this mode + bool resyncing_; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/log_writer.cc b/PediatricPancreas/Pods/leveldb-library/db/log_writer.cc new file mode 100644 index 0000000..5e83f6a --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/log_writer.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_writer.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +static void InitTypeCrc(uint32_t* type_crc) { + for (int i = 0; i <= kMaxRecordType; i++) { + char t = static_cast(i); + type_crc[i] = crc32c::Value(&t, 1); + } +} + +Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) { + InitTypeCrc(type_crc_); +} + +Writer::Writer(WritableFile* dest, uint64_t dest_length) + : dest_(dest), block_offset_(dest_length % kBlockSize) { + InitTypeCrc(type_crc_); +} + +Writer::~Writer() {} + +Status Writer::AddRecord(const Slice& slice) { + const char* ptr = slice.data(); + size_t left = slice.size(); + + // Fragment the record if necessary and emit it. Note that if slice + // is empty, we still want to iterate once to emit a single + // zero-length record + Status s; + bool begin = true; + do { + const int leftover = kBlockSize - block_offset_; + assert(leftover >= 0); + if (leftover < kHeaderSize) { + // Switch to a new block + if (leftover > 0) { + // Fill the trailer (literal below relies on kHeaderSize being 7) + static_assert(kHeaderSize == 7, ""); + dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); + } + block_offset_ = 0; + } + + // Invariant: we never leave < kHeaderSize bytes in a block. + assert(kBlockSize - block_offset_ - kHeaderSize >= 0); + + const size_t avail = kBlockSize - block_offset_ - kHeaderSize; + const size_t fragment_length = (left < avail) ? left : avail; + + RecordType type; + const bool end = (left == fragment_length); + if (begin && end) { + type = kFullType; + } else if (begin) { + type = kFirstType; + } else if (end) { + type = kLastType; + } else { + type = kMiddleType; + } + + s = EmitPhysicalRecord(type, ptr, fragment_length); + ptr += fragment_length; + left -= fragment_length; + begin = false; + } while (s.ok() && left > 0); + return s; +} + +Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, + size_t length) { + assert(length <= 0xffff); // Must fit in two bytes + assert(block_offset_ + kHeaderSize + length <= kBlockSize); + + // Format the header + char buf[kHeaderSize]; + buf[4] = static_cast(length & 0xff); + buf[5] = static_cast(length >> 8); + buf[6] = static_cast(t); + + // Compute the crc of the record type and the payload. + uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length); + crc = crc32c::Mask(crc); // Adjust for storage + EncodeFixed32(buf, crc); + + // Write the header and the payload + Status s = dest_->Append(Slice(buf, kHeaderSize)); + if (s.ok()) { + s = dest_->Append(Slice(ptr, length)); + if (s.ok()) { + s = dest_->Flush(); + } + } + block_offset_ += kHeaderSize + length; + return s; +} + +} // namespace log +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/log_writer.h b/PediatricPancreas/Pods/leveldb-library/db/log_writer.h new file mode 100644 index 0000000..c0a2114 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/log_writer.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ +#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +namespace log { + +class Writer { + public: + // Create a writer that will append data to "*dest". + // "*dest" must be initially empty. + // "*dest" must remain live while this Writer is in use. + explicit Writer(WritableFile* dest); + + // Create a writer that will append data to "*dest". + // "*dest" must have initial length "dest_length". + // "*dest" must remain live while this Writer is in use. + Writer(WritableFile* dest, uint64_t dest_length); + + Writer(const Writer&) = delete; + Writer& operator=(const Writer&) = delete; + + ~Writer(); + + Status AddRecord(const Slice& slice); + + private: + Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); + + WritableFile* dest_; + int block_offset_; // Current offset in block + + // crc32c values for all supported record types. These are + // pre-computed to reduce the overhead of computing the crc of the + // record type stored in the header. + uint32_t type_crc_[kMaxRecordType + 1]; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/memtable.cc b/PediatricPancreas/Pods/leveldb-library/db/memtable.cc new file mode 100644 index 0000000..c91405c --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/memtable.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/memtable.h" +#include "db/dbformat.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +static Slice GetLengthPrefixedSlice(const char* data) { + uint32_t len; + const char* p = data; + p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted + return Slice(p, len); +} + +MemTable::MemTable(const InternalKeyComparator& comparator) + : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {} + +MemTable::~MemTable() { assert(refs_ == 0); } + +size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } + +int MemTable::KeyComparator::operator()(const char* aptr, + const char* bptr) const { + // Internal keys are encoded as length-prefixed strings. + Slice a = GetLengthPrefixedSlice(aptr); + Slice b = GetLengthPrefixedSlice(bptr); + return comparator.Compare(a, b); +} + +// Encode a suitable internal key target for "target" and return it. +// Uses *scratch as scratch space, and the returned pointer will point +// into this scratch space. +static const char* EncodeKey(std::string* scratch, const Slice& target) { + scratch->clear(); + PutVarint32(scratch, target.size()); + scratch->append(target.data(), target.size()); + return scratch->data(); +} + +class MemTableIterator : public Iterator { + public: + explicit MemTableIterator(MemTable::Table* table) : iter_(table) {} + + virtual bool Valid() const { return iter_.Valid(); } + virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } + virtual void SeekToFirst() { iter_.SeekToFirst(); } + virtual void SeekToLast() { iter_.SeekToLast(); } + virtual void Next() { iter_.Next(); } + virtual void Prev() { iter_.Prev(); } + virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } + virtual Slice value() const { + Slice key_slice = GetLengthPrefixedSlice(iter_.key()); + return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); + } + + virtual Status status() const { return Status::OK(); } + + private: + MemTable::Table::Iterator iter_; + std::string tmp_; // For passing to EncodeKey + + // No copying allowed + MemTableIterator(const MemTableIterator&); + void operator=(const MemTableIterator&); +}; + +Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); } + +void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, + const Slice& value) { + // Format of an entry is concatenation of: + // key_size : varint32 of internal_key.size() + // key bytes : char[internal_key.size()] + // value_size : varint32 of value.size() + // value bytes : char[value.size()] + size_t key_size = key.size(); + size_t val_size = value.size(); + size_t internal_key_size = key_size + 8; + const size_t encoded_len = VarintLength(internal_key_size) + + internal_key_size + VarintLength(val_size) + + val_size; + char* buf = arena_.Allocate(encoded_len); + char* p = EncodeVarint32(buf, internal_key_size); + memcpy(p, key.data(), key_size); + p += key_size; + EncodeFixed64(p, (s << 8) | type); + p += 8; + p = EncodeVarint32(p, val_size); + memcpy(p, value.data(), val_size); + assert(p + val_size == buf + encoded_len); + table_.Insert(buf); +} + +bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { + Slice memkey = key.memtable_key(); + Table::Iterator iter(&table_); + iter.Seek(memkey.data()); + if (iter.Valid()) { + // entry format is: + // klength varint32 + // userkey char[klength] + // tag uint64 + // vlength varint32 + // value char[vlength] + // Check that it belongs to same user key. We do not check the + // sequence number since the Seek() call above should have skipped + // all entries with overly large sequence numbers. + const char* entry = iter.key(); + uint32_t key_length; + const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); + if (comparator_.comparator.user_comparator()->Compare( + Slice(key_ptr, key_length - 8), key.user_key()) == 0) { + // Correct user key + const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); + switch (static_cast(tag & 0xff)) { + case kTypeValue: { + Slice v = GetLengthPrefixedSlice(key_ptr + key_length); + value->assign(v.data(), v.size()); + return true; + } + case kTypeDeletion: + *s = Status::NotFound(Slice()); + return true; + } + } + } + return false; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/memtable.h b/PediatricPancreas/Pods/leveldb-library/db/memtable.h new file mode 100644 index 0000000..9d986b1 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/memtable.h @@ -0,0 +1,87 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ +#define STORAGE_LEVELDB_DB_MEMTABLE_H_ + +#include + +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "leveldb/db.h" +#include "util/arena.h" + +namespace leveldb { + +class InternalKeyComparator; +class MemTableIterator; + +class MemTable { + public: + // MemTables are reference counted. The initial reference count + // is zero and the caller must call Ref() at least once. + explicit MemTable(const InternalKeyComparator& comparator); + + MemTable(const MemTable&) = delete; + MemTable& operator=(const MemTable&) = delete; + + // Increase reference count. + void Ref() { ++refs_; } + + // Drop reference count. Delete if no more references exist. + void Unref() { + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + delete this; + } + } + + // Returns an estimate of the number of bytes of data in use by this + // data structure. It is safe to call when MemTable is being modified. + size_t ApproximateMemoryUsage(); + + // Return an iterator that yields the contents of the memtable. + // + // The caller must ensure that the underlying MemTable remains live + // while the returned iterator is live. The keys returned by this + // iterator are internal keys encoded by AppendInternalKey in the + // db/format.{h,cc} module. + Iterator* NewIterator(); + + // Add an entry into memtable that maps key to value at the + // specified sequence number and with the specified type. + // Typically value will be empty if type==kTypeDeletion. + void Add(SequenceNumber seq, ValueType type, const Slice& key, + const Slice& value); + + // If memtable contains a value for key, store it in *value and return true. + // If memtable contains a deletion for key, store a NotFound() error + // in *status and return true. + // Else, return false. + bool Get(const LookupKey& key, std::string* value, Status* s); + + private: + friend class MemTableIterator; + friend class MemTableBackwardIterator; + + struct KeyComparator { + const InternalKeyComparator comparator; + explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {} + int operator()(const char* a, const char* b) const; + }; + + typedef SkipList Table; + + ~MemTable(); // Private since only Unref() should be used to delete it + + KeyComparator comparator_; + int refs_; + Arena arena_; + Table table_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/repair.cc b/PediatricPancreas/Pods/leveldb-library/db/repair.cc new file mode 100644 index 0000000..3c676ca --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/repair.cc @@ -0,0 +1,450 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// We recover the contents of the descriptor from the other files we find. +// (1) Any log files are first converted to tables +// (2) We scan every table to compute +// (a) smallest/largest for the table +// (b) largest sequence number in the table +// (3) We generate descriptor contents: +// - log number is set to zero +// - next-file-number is set to 1 + largest file number we found +// - last-sequence-number is set to largest sequence# found across +// all tables (see 2c) +// - compaction pointers are cleared +// - every table file is added at level 0 +// +// Possible optimization 1: +// (a) Compute total size and use to pick appropriate max-level M +// (b) Sort tables by largest sequence# in the table +// (c) For each table: if it overlaps earlier table, place in level-0, +// else place in level-M. +// Possible optimization 2: +// Store per-table metadata (smallest, largest, largest-seq#, ...) +// in the table's meta section to speed up ScanTable. + +#include "db/builder.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" + +namespace leveldb { + +namespace { + +class Repairer { + public: + Repairer(const std::string& dbname, const Options& options) + : dbname_(dbname), + env_(options.env), + icmp_(options.comparator), + ipolicy_(options.filter_policy), + options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), + owns_info_log_(options_.info_log != options.info_log), + owns_cache_(options_.block_cache != options.block_cache), + next_file_number_(1) { + // TableCache can be small since we expect each table to be opened once. + table_cache_ = new TableCache(dbname_, options_, 10); + } + + ~Repairer() { + delete table_cache_; + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } + } + + Status Run() { + Status status = FindFiles(); + if (status.ok()) { + ConvertLogFilesToTables(); + ExtractMetaData(); + status = WriteDescriptor(); + } + if (status.ok()) { + unsigned long long bytes = 0; + for (size_t i = 0; i < tables_.size(); i++) { + bytes += tables_[i].meta.file_size; + } + Log(options_.info_log, + "**** Repaired leveldb %s; " + "recovered %d files; %llu bytes. " + "Some data may have been lost. " + "****", + dbname_.c_str(), static_cast(tables_.size()), bytes); + } + return status; + } + + private: + struct TableInfo { + FileMetaData meta; + SequenceNumber max_sequence; + }; + + Status FindFiles() { + std::vector filenames; + Status status = env_->GetChildren(dbname_, &filenames); + if (!status.ok()) { + return status; + } + if (filenames.empty()) { + return Status::IOError(dbname_, "repair found no files"); + } + + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + if (type == kDescriptorFile) { + manifests_.push_back(filenames[i]); + } else { + if (number + 1 > next_file_number_) { + next_file_number_ = number + 1; + } + if (type == kLogFile) { + logs_.push_back(number); + } else if (type == kTableFile) { + table_numbers_.push_back(number); + } else { + // Ignore other files + } + } + } + } + return status; + } + + void ConvertLogFilesToTables() { + for (size_t i = 0; i < logs_.size(); i++) { + std::string logname = LogFileName(dbname_, logs_[i]); + Status status = ConvertLogToTable(logs_[i]); + if (!status.ok()) { + Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", + (unsigned long long)logs_[i], status.ToString().c_str()); + } + ArchiveFile(logname); + } + } + + Status ConvertLogToTable(uint64_t log) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + uint64_t lognum; + virtual void Corruption(size_t bytes, const Status& s) { + // We print error messages for corruption, but continue repairing. + Log(info_log, "Log #%llu: dropping %d bytes; %s", + (unsigned long long)lognum, static_cast(bytes), + s.ToString().c_str()); + } + }; + + // Open the log file + std::string logname = LogFileName(dbname_, log); + SequentialFile* lfile; + Status status = env_->NewSequentialFile(logname, &lfile); + if (!status.ok()) { + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.lognum = log; + // We intentionally make log::Reader do checksumming so that + // corruptions cause entire commits to be skipped instead of + // propagating bad information (like overly large sequence + // numbers). + log::Reader reader(lfile, &reporter, false /*do not checksum*/, + 0 /*initial_offset*/); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = new MemTable(icmp_); + mem->Ref(); + int counter = 0; + while (reader.ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + status = WriteBatchInternal::InsertInto(&batch, mem); + if (status.ok()) { + counter += WriteBatchInternal::Count(&batch); + } else { + Log(options_.info_log, "Log #%llu: ignoring %s", + (unsigned long long)log, status.ToString().c_str()); + status = Status::OK(); // Keep going with rest of file + } + } + delete lfile; + + // Do not record a version edit for this conversion to a Table + // since ExtractMetaData() will also generate edits. + FileMetaData meta; + meta.number = next_file_number_++; + Iterator* iter = mem->NewIterator(); + status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + delete iter; + mem->Unref(); + mem = nullptr; + if (status.ok()) { + if (meta.file_size > 0) { + table_numbers_.push_back(meta.number); + } + } + Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", + (unsigned long long)log, counter, (unsigned long long)meta.number, + status.ToString().c_str()); + return status; + } + + void ExtractMetaData() { + for (size_t i = 0; i < table_numbers_.size(); i++) { + ScanTable(table_numbers_[i]); + } + } + + Iterator* NewTableIterator(const FileMetaData& meta) { + // Same as compaction iterators: if paranoid_checks are on, turn + // on checksum verification. + ReadOptions r; + r.verify_checksums = options_.paranoid_checks; + return table_cache_->NewIterator(r, meta.number, meta.file_size); + } + + void ScanTable(uint64_t number) { + TableInfo t; + t.meta.number = number; + std::string fname = TableFileName(dbname_, number); + Status status = env_->GetFileSize(fname, &t.meta.file_size); + if (!status.ok()) { + // Try alternate file name. + fname = SSTTableFileName(dbname_, number); + Status s2 = env_->GetFileSize(fname, &t.meta.file_size); + if (s2.ok()) { + status = Status::OK(); + } + } + if (!status.ok()) { + ArchiveFile(TableFileName(dbname_, number)); + ArchiveFile(SSTTableFileName(dbname_, number)); + Log(options_.info_log, "Table #%llu: dropped: %s", + (unsigned long long)t.meta.number, status.ToString().c_str()); + return; + } + + // Extract metadata by scanning through table. + int counter = 0; + Iterator* iter = NewTableIterator(t.meta); + bool empty = true; + ParsedInternalKey parsed; + t.max_sequence = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + if (!ParseInternalKey(key, &parsed)) { + Log(options_.info_log, "Table #%llu: unparsable key %s", + (unsigned long long)t.meta.number, EscapeString(key).c_str()); + continue; + } + + counter++; + if (empty) { + empty = false; + t.meta.smallest.DecodeFrom(key); + } + t.meta.largest.DecodeFrom(key); + if (parsed.sequence > t.max_sequence) { + t.max_sequence = parsed.sequence; + } + } + if (!iter->status().ok()) { + status = iter->status(); + } + delete iter; + Log(options_.info_log, "Table #%llu: %d entries %s", + (unsigned long long)t.meta.number, counter, status.ToString().c_str()); + + if (status.ok()) { + tables_.push_back(t); + } else { + RepairTable(fname, t); // RepairTable archives input file. + } + } + + void RepairTable(const std::string& src, TableInfo t) { + // We will copy src contents to a new table and then rename the + // new table over the source. + + // Create builder. + std::string copy = TableFileName(dbname_, next_file_number_++); + WritableFile* file; + Status s = env_->NewWritableFile(copy, &file); + if (!s.ok()) { + return; + } + TableBuilder* builder = new TableBuilder(options_, file); + + // Copy data. + Iterator* iter = NewTableIterator(t.meta); + int counter = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + builder->Add(iter->key(), iter->value()); + counter++; + } + delete iter; + + ArchiveFile(src); + if (counter == 0) { + builder->Abandon(); // Nothing to save + } else { + s = builder->Finish(); + if (s.ok()) { + t.meta.file_size = builder->FileSize(); + } + } + delete builder; + builder = nullptr; + + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (counter > 0 && s.ok()) { + std::string orig = TableFileName(dbname_, t.meta.number); + s = env_->RenameFile(copy, orig); + if (s.ok()) { + Log(options_.info_log, "Table #%llu: %d entries repaired", + (unsigned long long)t.meta.number, counter); + tables_.push_back(t); + } + } + if (!s.ok()) { + env_->DeleteFile(copy); + } + } + + Status WriteDescriptor() { + std::string tmp = TempFileName(dbname_, 1); + WritableFile* file; + Status status = env_->NewWritableFile(tmp, &file); + if (!status.ok()) { + return status; + } + + SequenceNumber max_sequence = 0; + for (size_t i = 0; i < tables_.size(); i++) { + if (max_sequence < tables_[i].max_sequence) { + max_sequence = tables_[i].max_sequence; + } + } + + edit_.SetComparatorName(icmp_.user_comparator()->Name()); + edit_.SetLogNumber(0); + edit_.SetNextFile(next_file_number_); + edit_.SetLastSequence(max_sequence); + + for (size_t i = 0; i < tables_.size(); i++) { + // TODO(opt): separate out into multiple levels + const TableInfo& t = tables_[i]; + edit_.AddFile(0, t.meta.number, t.meta.file_size, t.meta.smallest, + t.meta.largest); + } + + // fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); + { + log::Writer log(file); + std::string record; + edit_.EncodeTo(&record); + status = log.AddRecord(record); + } + if (status.ok()) { + status = file->Close(); + } + delete file; + file = nullptr; + + if (!status.ok()) { + env_->DeleteFile(tmp); + } else { + // Discard older manifests + for (size_t i = 0; i < manifests_.size(); i++) { + ArchiveFile(dbname_ + "/" + manifests_[i]); + } + + // Install new manifest + status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); + if (status.ok()) { + status = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(tmp); + } + } + return status; + } + + void ArchiveFile(const std::string& fname) { + // Move into another directory. E.g., for + // dir/foo + // rename to + // dir/lost/foo + const char* slash = strrchr(fname.c_str(), '/'); + std::string new_dir; + if (slash != nullptr) { + new_dir.assign(fname.data(), slash - fname.data()); + } + new_dir.append("/lost"); + env_->CreateDir(new_dir); // Ignore error + std::string new_file = new_dir; + new_file.append("/"); + new_file.append((slash == nullptr) ? fname.c_str() : slash + 1); + Status s = env_->RenameFile(fname, new_file); + Log(options_.info_log, "Archiving %s: %s\n", fname.c_str(), + s.ToString().c_str()); + } + + const std::string dbname_; + Env* const env_; + InternalKeyComparator const icmp_; + InternalFilterPolicy const ipolicy_; + const Options options_; + bool owns_info_log_; + bool owns_cache_; + TableCache* table_cache_; + VersionEdit edit_; + + std::vector manifests_; + std::vector table_numbers_; + std::vector logs_; + std::vector tables_; + uint64_t next_file_number_; +}; +} // namespace + +Status RepairDB(const std::string& dbname, const Options& options) { + Repairer repairer(dbname, options); + return repairer.Run(); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/skiplist.h b/PediatricPancreas/Pods/leveldb-library/db/skiplist.h new file mode 100644 index 0000000..a59b45b --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/skiplist.h @@ -0,0 +1,382 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_ +#define STORAGE_LEVELDB_DB_SKIPLIST_H_ + +// Thread safety +// ------------- +// +// Writes require external synchronization, most likely a mutex. +// Reads require a guarantee that the SkipList will not be destroyed +// while the read is in progress. Apart from that, reads progress +// without any internal locking or synchronization. +// +// Invariants: +// +// (1) Allocated nodes are never deleted until the SkipList is +// destroyed. This is trivially guaranteed by the code since we +// never delete any skip list nodes. +// +// (2) The contents of a Node except for the next/prev pointers are +// immutable after the Node has been linked into the SkipList. +// Only Insert() modifies the list, and it is careful to initialize +// a node and use release-stores to publish the nodes in one or +// more lists. +// +// ... prev vs. next pointer ordering ... + +#include +#include +#include + +#include "util/arena.h" +#include "util/random.h" + +namespace leveldb { + +class Arena; + +template +class SkipList { + private: + struct Node; + + public: + // Create a new SkipList object that will use "cmp" for comparing keys, + // and will allocate memory using "*arena". Objects allocated in the arena + // must remain allocated for the lifetime of the skiplist object. + explicit SkipList(Comparator cmp, Arena* arena); + + SkipList(const SkipList&) = delete; + SkipList& operator=(const SkipList&) = delete; + + // Insert key into the list. + // REQUIRES: nothing that compares equal to key is currently in the list. + void Insert(const Key& key); + + // Returns true iff an entry that compares equal to key is in the list. + bool Contains(const Key& key) const; + + // Iteration over the contents of a skip list + class Iterator { + public: + // Initialize an iterator over the specified list. + // The returned iterator is not valid. + explicit Iterator(const SkipList* list); + + // Returns true iff the iterator is positioned at a valid node. + bool Valid() const; + + // Returns the key at the current position. + // REQUIRES: Valid() + const Key& key() const; + + // Advances to the next position. + // REQUIRES: Valid() + void Next(); + + // Advances to the previous position. + // REQUIRES: Valid() + void Prev(); + + // Advance to the first entry with a key >= target + void Seek(const Key& target); + + // Position at the first entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToFirst(); + + // Position at the last entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToLast(); + + private: + const SkipList* list_; + Node* node_; + // Intentionally copyable + }; + + private: + enum { kMaxHeight = 12 }; + + inline int GetMaxHeight() const { + return max_height_.load(std::memory_order_relaxed); + } + + Node* NewNode(const Key& key, int height); + int RandomHeight(); + bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } + + // Return true if key is greater than the data stored in "n" + bool KeyIsAfterNode(const Key& key, Node* n) const; + + // Return the earliest node that comes at or after key. + // Return nullptr if there is no such node. + // + // If prev is non-null, fills prev[level] with pointer to previous + // node at "level" for every level in [0..max_height_-1]. + Node* FindGreaterOrEqual(const Key& key, Node** prev) const; + + // Return the latest node with a key < key. + // Return head_ if there is no such node. + Node* FindLessThan(const Key& key) const; + + // Return the last node in the list. + // Return head_ if list is empty. + Node* FindLast() const; + + // Immutable after construction + Comparator const compare_; + Arena* const arena_; // Arena used for allocations of nodes + + Node* const head_; + + // Modified only by Insert(). Read racily by readers, but stale + // values are ok. + std::atomic max_height_; // Height of the entire list + + // Read/written only by Insert(). + Random rnd_; +}; + +// Implementation details follow +template +struct SkipList::Node { + explicit Node(const Key& k) : key(k) {} + + Key const key; + + // Accessors/mutators for links. Wrapped in methods so we can + // add the appropriate barriers as necessary. + Node* Next(int n) { + assert(n >= 0); + // Use an 'acquire load' so that we observe a fully initialized + // version of the returned Node. + return next_[n].load(std::memory_order_acquire); + } + void SetNext(int n, Node* x) { + assert(n >= 0); + // Use a 'release store' so that anybody who reads through this + // pointer observes a fully initialized version of the inserted node. + next_[n].store(x, std::memory_order_release); + } + + // No-barrier variants that can be safely used in a few locations. + Node* NoBarrier_Next(int n) { + assert(n >= 0); + return next_[n].load(std::memory_order_relaxed); + } + void NoBarrier_SetNext(int n, Node* x) { + assert(n >= 0); + next_[n].store(x, std::memory_order_relaxed); + } + + private: + // Array of length equal to the node height. next_[0] is lowest level link. + std::atomic next_[1]; +}; + +template +typename SkipList::Node* SkipList::NewNode( + const Key& key, int height) { + char* const node_memory = arena_->AllocateAligned( + sizeof(Node) + sizeof(std::atomic) * (height - 1)); + return new (node_memory) Node(key); +} + +template +inline SkipList::Iterator::Iterator(const SkipList* list) { + list_ = list; + node_ = nullptr; +} + +template +inline bool SkipList::Iterator::Valid() const { + return node_ != nullptr; +} + +template +inline const Key& SkipList::Iterator::key() const { + assert(Valid()); + return node_->key; +} + +template +inline void SkipList::Iterator::Next() { + assert(Valid()); + node_ = node_->Next(0); +} + +template +inline void SkipList::Iterator::Prev() { + // Instead of using explicit "prev" links, we just search for the + // last node that falls before key. + assert(Valid()); + node_ = list_->FindLessThan(node_->key); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +inline void SkipList::Iterator::Seek(const Key& target) { + node_ = list_->FindGreaterOrEqual(target, nullptr); +} + +template +inline void SkipList::Iterator::SeekToFirst() { + node_ = list_->head_->Next(0); +} + +template +inline void SkipList::Iterator::SeekToLast() { + node_ = list_->FindLast(); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +int SkipList::RandomHeight() { + // Increase height with probability 1 in kBranching + static const unsigned int kBranching = 4; + int height = 1; + while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { + height++; + } + assert(height > 0); + assert(height <= kMaxHeight); + return height; +} + +template +bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { + // null n is considered infinite + return (n != nullptr) && (compare_(n->key, key) < 0); +} + +template +typename SkipList::Node* +SkipList::FindGreaterOrEqual(const Key& key, + Node** prev) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (KeyIsAfterNode(key, next)) { + // Keep searching in this list + x = next; + } else { + if (prev != nullptr) prev[level] = x; + if (level == 0) { + return next; + } else { + // Switch to next list + level--; + } + } + } +} + +template +typename SkipList::Node* +SkipList::FindLessThan(const Key& key) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + assert(x == head_ || compare_(x->key, key) < 0); + Node* next = x->Next(level); + if (next == nullptr || compare_(next->key, key) >= 0) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +typename SkipList::Node* SkipList::FindLast() + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (next == nullptr) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +SkipList::SkipList(Comparator cmp, Arena* arena) + : compare_(cmp), + arena_(arena), + head_(NewNode(0 /* any key will do */, kMaxHeight)), + max_height_(1), + rnd_(0xdeadbeef) { + for (int i = 0; i < kMaxHeight; i++) { + head_->SetNext(i, nullptr); + } +} + +template +void SkipList::Insert(const Key& key) { + // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() + // here since Insert() is externally synchronized. + Node* prev[kMaxHeight]; + Node* x = FindGreaterOrEqual(key, prev); + + // Our data structure does not allow duplicate insertion + assert(x == nullptr || !Equal(key, x->key)); + + int height = RandomHeight(); + if (height > GetMaxHeight()) { + for (int i = GetMaxHeight(); i < height; i++) { + prev[i] = head_; + } + // It is ok to mutate max_height_ without any synchronization + // with concurrent readers. A concurrent reader that observes + // the new value of max_height_ will see either the old value of + // new level pointers from head_ (nullptr), or a new value set in + // the loop below. In the former case the reader will + // immediately drop to the next level since nullptr sorts after all + // keys. In the latter case the reader will use the new node. + max_height_.store(height, std::memory_order_relaxed); + } + + x = NewNode(key, height); + for (int i = 0; i < height; i++) { + // NoBarrier_SetNext() suffices since we will add a barrier when + // we publish a pointer to "x" in prev[i]. + x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); + prev[i]->SetNext(i, x); + } +} + +template +bool SkipList::Contains(const Key& key) const { + Node* x = FindGreaterOrEqual(key, nullptr); + if (x != nullptr && Equal(key, x->key)) { + return true; + } else { + return false; + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/snapshot.h b/PediatricPancreas/Pods/leveldb-library/db/snapshot.h new file mode 100644 index 0000000..9f1d664 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/snapshot.h @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ +#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class SnapshotList; + +// Snapshots are kept in a doubly-linked list in the DB. +// Each SnapshotImpl corresponds to a particular sequence number. +class SnapshotImpl : public Snapshot { + public: + SnapshotImpl(SequenceNumber sequence_number) + : sequence_number_(sequence_number) {} + + SequenceNumber sequence_number() const { return sequence_number_; } + + private: + friend class SnapshotList; + + // SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList + // implementation operates on the next/previous fields direcly. + SnapshotImpl* prev_; + SnapshotImpl* next_; + + const SequenceNumber sequence_number_; + +#if !defined(NDEBUG) + SnapshotList* list_ = nullptr; +#endif // !defined(NDEBUG) +}; + +class SnapshotList { + public: + SnapshotList() : head_(0) { + head_.prev_ = &head_; + head_.next_ = &head_; + } + + bool empty() const { return head_.next_ == &head_; } + SnapshotImpl* oldest() const { + assert(!empty()); + return head_.next_; + } + SnapshotImpl* newest() const { + assert(!empty()); + return head_.prev_; + } + + // Creates a SnapshotImpl and appends it to the end of the list. + SnapshotImpl* New(SequenceNumber sequence_number) { + assert(empty() || newest()->sequence_number_ <= sequence_number); + + SnapshotImpl* snapshot = new SnapshotImpl(sequence_number); + +#if !defined(NDEBUG) + snapshot->list_ = this; +#endif // !defined(NDEBUG) + snapshot->next_ = &head_; + snapshot->prev_ = head_.prev_; + snapshot->prev_->next_ = snapshot; + snapshot->next_->prev_ = snapshot; + return snapshot; + } + + // Removes a SnapshotImpl from this list. + // + // The snapshot must have been created by calling New() on this list. + // + // The snapshot pointer should not be const, because its memory is + // deallocated. However, that would force us to change DB::ReleaseSnapshot(), + // which is in the API, and currently takes a const Snapshot. + void Delete(const SnapshotImpl* snapshot) { +#if !defined(NDEBUG) + assert(snapshot->list_ == this); +#endif // !defined(NDEBUG) + snapshot->prev_->next_ = snapshot->next_; + snapshot->next_->prev_ = snapshot->prev_; + delete snapshot; + } + + private: + // Dummy head of doubly-linked list of snapshots + SnapshotImpl head_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/table_cache.cc b/PediatricPancreas/Pods/leveldb-library/db/table_cache.cc new file mode 100644 index 0000000..73f05fd --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/table_cache.cc @@ -0,0 +1,120 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/table_cache.h" + +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/coding.h" + +namespace leveldb { + +struct TableAndFile { + RandomAccessFile* file; + Table* table; +}; + +static void DeleteEntry(const Slice& key, void* value) { + TableAndFile* tf = reinterpret_cast(value); + delete tf->table; + delete tf->file; + delete tf; +} + +static void UnrefEntry(void* arg1, void* arg2) { + Cache* cache = reinterpret_cast(arg1); + Cache::Handle* h = reinterpret_cast(arg2); + cache->Release(h); +} + +TableCache::TableCache(const std::string& dbname, const Options& options, + int entries) + : env_(options.env), + dbname_(dbname), + options_(options), + cache_(NewLRUCache(entries)) {} + +TableCache::~TableCache() { delete cache_; } + +Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, + Cache::Handle** handle) { + Status s; + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + Slice key(buf, sizeof(buf)); + *handle = cache_->Lookup(key); + if (*handle == nullptr) { + std::string fname = TableFileName(dbname_, file_number); + RandomAccessFile* file = nullptr; + Table* table = nullptr; + s = env_->NewRandomAccessFile(fname, &file); + if (!s.ok()) { + std::string old_fname = SSTTableFileName(dbname_, file_number); + if (env_->NewRandomAccessFile(old_fname, &file).ok()) { + s = Status::OK(); + } + } + if (s.ok()) { + s = Table::Open(options_, file, file_size, &table); + } + + if (!s.ok()) { + assert(table == nullptr); + delete file; + // We do not cache error results so that if the error is transient, + // or somebody repairs the file, we recover automatically. + } else { + TableAndFile* tf = new TableAndFile; + tf->file = file; + tf->table = table; + *handle = cache_->Insert(key, tf, 1, &DeleteEntry); + } + } + return s; +} + +Iterator* TableCache::NewIterator(const ReadOptions& options, + uint64_t file_number, uint64_t file_size, + Table** tableptr) { + if (tableptr != nullptr) { + *tableptr = nullptr; + } + + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (!s.ok()) { + return NewErrorIterator(s); + } + + Table* table = reinterpret_cast(cache_->Value(handle))->table; + Iterator* result = table->NewIterator(options); + result->RegisterCleanup(&UnrefEntry, cache_, handle); + if (tableptr != nullptr) { + *tableptr = table; + } + return result; +} + +Status TableCache::Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (s.ok()) { + Table* t = reinterpret_cast(cache_->Value(handle))->table; + s = t->InternalGet(options, k, arg, handle_result); + cache_->Release(handle); + } + return s; +} + +void TableCache::Evict(uint64_t file_number) { + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + cache_->Erase(Slice(buf, sizeof(buf))); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/table_cache.h b/PediatricPancreas/Pods/leveldb-library/db/table_cache.h new file mode 100644 index 0000000..93069c8 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/table_cache.h @@ -0,0 +1,58 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread-safe (provides internal synchronization) + +#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ +#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ + +#include + +#include + +#include "db/dbformat.h" +#include "leveldb/cache.h" +#include "leveldb/table.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +class TableCache { + public: + TableCache(const std::string& dbname, const Options& options, int entries); + ~TableCache(); + + // Return an iterator for the specified file number (the corresponding + // file length must be exactly "file_size" bytes). If "tableptr" is + // non-null, also sets "*tableptr" to point to the Table object + // underlying the returned iterator, or to nullptr if no Table object + // underlies the returned iterator. The returned "*tableptr" object is owned + // by the cache and should not be deleted, and is valid for as long as the + // returned iterator is live. + Iterator* NewIterator(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, Table** tableptr = nullptr); + + // If a seek to internal key "k" in specified file finds an entry, + // call (*handle_result)(arg, found_key, found_value). + Status Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, const Slice&)); + + // Evict any entry for the specified file number + void Evict(uint64_t file_number); + + private: + Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); + + Env* const env_; + const std::string dbname_; + const Options& options_; + Cache* cache_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/version_edit.cc b/PediatricPancreas/Pods/leveldb-library/db/version_edit.cc new file mode 100644 index 0000000..44a4d02 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/version_edit.cc @@ -0,0 +1,260 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" + +#include "db/version_set.h" +#include "util/coding.h" + +namespace leveldb { + +// Tag numbers for serialized VersionEdit. These numbers are written to +// disk and should not be changed. +enum Tag { + kComparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, + // 8 was used for large value refs + kPrevLogNumber = 9 +}; + +void VersionEdit::Clear() { + comparator_.clear(); + log_number_ = 0; + prev_log_number_ = 0; + last_sequence_ = 0; + next_file_number_ = 0; + has_comparator_ = false; + has_log_number_ = false; + has_prev_log_number_ = false; + has_next_file_number_ = false; + has_last_sequence_ = false; + deleted_files_.clear(); + new_files_.clear(); +} + +void VersionEdit::EncodeTo(std::string* dst) const { + if (has_comparator_) { + PutVarint32(dst, kComparator); + PutLengthPrefixedSlice(dst, comparator_); + } + if (has_log_number_) { + PutVarint32(dst, kLogNumber); + PutVarint64(dst, log_number_); + } + if (has_prev_log_number_) { + PutVarint32(dst, kPrevLogNumber); + PutVarint64(dst, prev_log_number_); + } + if (has_next_file_number_) { + PutVarint32(dst, kNextFileNumber); + PutVarint64(dst, next_file_number_); + } + if (has_last_sequence_) { + PutVarint32(dst, kLastSequence); + PutVarint64(dst, last_sequence_); + } + + for (size_t i = 0; i < compact_pointers_.size(); i++) { + PutVarint32(dst, kCompactPointer); + PutVarint32(dst, compact_pointers_[i].first); // level + PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); + } + + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + PutVarint32(dst, kDeletedFile); + PutVarint32(dst, iter->first); // level + PutVarint64(dst, iter->second); // file number + } + + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + PutVarint32(dst, kNewFile); + PutVarint32(dst, new_files_[i].first); // level + PutVarint64(dst, f.number); + PutVarint64(dst, f.file_size); + PutLengthPrefixedSlice(dst, f.smallest.Encode()); + PutLengthPrefixedSlice(dst, f.largest.Encode()); + } +} + +static bool GetInternalKey(Slice* input, InternalKey* dst) { + Slice str; + if (GetLengthPrefixedSlice(input, &str)) { + dst->DecodeFrom(str); + return true; + } else { + return false; + } +} + +static bool GetLevel(Slice* input, int* level) { + uint32_t v; + if (GetVarint32(input, &v) && v < config::kNumLevels) { + *level = v; + return true; + } else { + return false; + } +} + +Status VersionEdit::DecodeFrom(const Slice& src) { + Clear(); + Slice input = src; + const char* msg = nullptr; + uint32_t tag; + + // Temporary storage for parsing + int level; + uint64_t number; + FileMetaData f; + Slice str; + InternalKey key; + + while (msg == nullptr && GetVarint32(&input, &tag)) { + switch (tag) { + case kComparator: + if (GetLengthPrefixedSlice(&input, &str)) { + comparator_ = str.ToString(); + has_comparator_ = true; + } else { + msg = "comparator name"; + } + break; + + case kLogNumber: + if (GetVarint64(&input, &log_number_)) { + has_log_number_ = true; + } else { + msg = "log number"; + } + break; + + case kPrevLogNumber: + if (GetVarint64(&input, &prev_log_number_)) { + has_prev_log_number_ = true; + } else { + msg = "previous log number"; + } + break; + + case kNextFileNumber: + if (GetVarint64(&input, &next_file_number_)) { + has_next_file_number_ = true; + } else { + msg = "next file number"; + } + break; + + case kLastSequence: + if (GetVarint64(&input, &last_sequence_)) { + has_last_sequence_ = true; + } else { + msg = "last sequence number"; + } + break; + + case kCompactPointer: + if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) { + compact_pointers_.push_back(std::make_pair(level, key)); + } else { + msg = "compaction pointer"; + } + break; + + case kDeletedFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &number)) { + deleted_files_.insert(std::make_pair(level, number)); + } else { + msg = "deleted file"; + } + break; + + case kNewFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) && + GetVarint64(&input, &f.file_size) && + GetInternalKey(&input, &f.smallest) && + GetInternalKey(&input, &f.largest)) { + new_files_.push_back(std::make_pair(level, f)); + } else { + msg = "new-file entry"; + } + break; + + default: + msg = "unknown tag"; + break; + } + } + + if (msg == nullptr && !input.empty()) { + msg = "invalid tag"; + } + + Status result; + if (msg != nullptr) { + result = Status::Corruption("VersionEdit", msg); + } + return result; +} + +std::string VersionEdit::DebugString() const { + std::string r; + r.append("VersionEdit {"); + if (has_comparator_) { + r.append("\n Comparator: "); + r.append(comparator_); + } + if (has_log_number_) { + r.append("\n LogNumber: "); + AppendNumberTo(&r, log_number_); + } + if (has_prev_log_number_) { + r.append("\n PrevLogNumber: "); + AppendNumberTo(&r, prev_log_number_); + } + if (has_next_file_number_) { + r.append("\n NextFile: "); + AppendNumberTo(&r, next_file_number_); + } + if (has_last_sequence_) { + r.append("\n LastSeq: "); + AppendNumberTo(&r, last_sequence_); + } + for (size_t i = 0; i < compact_pointers_.size(); i++) { + r.append("\n CompactPointer: "); + AppendNumberTo(&r, compact_pointers_[i].first); + r.append(" "); + r.append(compact_pointers_[i].second.DebugString()); + } + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + r.append("\n DeleteFile: "); + AppendNumberTo(&r, iter->first); + r.append(" "); + AppendNumberTo(&r, iter->second); + } + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + r.append("\n AddFile: "); + AppendNumberTo(&r, new_files_[i].first); + r.append(" "); + AppendNumberTo(&r, f.number); + r.append(" "); + AppendNumberTo(&r, f.file_size); + r.append(" "); + r.append(f.smallest.DebugString()); + r.append(" .. "); + r.append(f.largest.DebugString()); + } + r.append("\n}\n"); + return r; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/version_edit.h b/PediatricPancreas/Pods/leveldb-library/db/version_edit.h new file mode 100644 index 0000000..2dadda7 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/version_edit.h @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ +#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ + +#include +#include +#include + +#include "db/dbformat.h" + +namespace leveldb { + +class VersionSet; + +struct FileMetaData { + FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) {} + + int refs; + int allowed_seeks; // Seeks allowed until compaction + uint64_t number; + uint64_t file_size; // File size in bytes + InternalKey smallest; // Smallest internal key served by table + InternalKey largest; // Largest internal key served by table +}; + +class VersionEdit { + public: + VersionEdit() { Clear(); } + ~VersionEdit() {} + + void Clear(); + + void SetComparatorName(const Slice& name) { + has_comparator_ = true; + comparator_ = name.ToString(); + } + void SetLogNumber(uint64_t num) { + has_log_number_ = true; + log_number_ = num; + } + void SetPrevLogNumber(uint64_t num) { + has_prev_log_number_ = true; + prev_log_number_ = num; + } + void SetNextFile(uint64_t num) { + has_next_file_number_ = true; + next_file_number_ = num; + } + void SetLastSequence(SequenceNumber seq) { + has_last_sequence_ = true; + last_sequence_ = seq; + } + void SetCompactPointer(int level, const InternalKey& key) { + compact_pointers_.push_back(std::make_pair(level, key)); + } + + // Add the specified file at the specified number. + // REQUIRES: This version has not been saved (see VersionSet::SaveTo) + // REQUIRES: "smallest" and "largest" are smallest and largest keys in file + void AddFile(int level, uint64_t file, uint64_t file_size, + const InternalKey& smallest, const InternalKey& largest) { + FileMetaData f; + f.number = file; + f.file_size = file_size; + f.smallest = smallest; + f.largest = largest; + new_files_.push_back(std::make_pair(level, f)); + } + + // Delete the specified "file" from the specified "level". + void DeleteFile(int level, uint64_t file) { + deleted_files_.insert(std::make_pair(level, file)); + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(const Slice& src); + + std::string DebugString() const; + + private: + friend class VersionSet; + + typedef std::set > DeletedFileSet; + + std::string comparator_; + uint64_t log_number_; + uint64_t prev_log_number_; + uint64_t next_file_number_; + SequenceNumber last_sequence_; + bool has_comparator_; + bool has_log_number_; + bool has_prev_log_number_; + bool has_next_file_number_; + bool has_last_sequence_; + + std::vector > compact_pointers_; + DeletedFileSet deleted_files_; + std::vector > new_files_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/version_set.cc b/PediatricPancreas/Pods/leveldb-library/db/version_set.cc new file mode 100644 index 0000000..96a92cc --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/version_set.cc @@ -0,0 +1,1585 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include + +#include + +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +static size_t TargetFileSize(const Options* options) { + return options->max_file_size; +} + +// Maximum bytes of overlaps in grandparent (i.e., level+2) before we +// stop building a single file in a level->level+1 compaction. +static int64_t MaxGrandParentOverlapBytes(const Options* options) { + return 10 * TargetFileSize(options); +} + +// Maximum number of bytes in all compacted files. We avoid expanding +// the lower level file set of a compaction if it would make the +// total compaction cover more than this many bytes. +static int64_t ExpandedCompactionByteSizeLimit(const Options* options) { + return 25 * TargetFileSize(options); +} + +static double MaxBytesForLevel(const Options* options, int level) { + // Note: the result for level zero is not really used since we set + // the level-0 compaction threshold based on number of files. + + // Result for both level-0 and level-1 + double result = 10. * 1048576.0; + while (level > 1) { + result *= 10; + level--; + } + return result; +} + +static uint64_t MaxFileSizeForLevel(const Options* options, int level) { + // We could vary per level to reduce number of files? + return TargetFileSize(options); +} + +static int64_t TotalFileSize(const std::vector& files) { + int64_t sum = 0; + for (size_t i = 0; i < files.size(); i++) { + sum += files[i]->file_size; + } + return sum; +} + +Version::~Version() { + assert(refs_ == 0); + + // Remove from linked list + prev_->next_ = next_; + next_->prev_ = prev_; + + // Drop references to files + for (int level = 0; level < config::kNumLevels; level++) { + for (size_t i = 0; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + assert(f->refs > 0); + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } +} + +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key) { + uint32_t left = 0; + uint32_t right = files.size(); + while (left < right) { + uint32_t mid = (left + right) / 2; + const FileMetaData* f = files[mid]; + if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { + // Key at "mid.largest" is < "target". Therefore all + // files at or before "mid" are uninteresting. + left = mid + 1; + } else { + // Key at "mid.largest" is >= "target". Therefore all files + // after "mid" are uninteresting. + right = mid; + } + } + return right; +} + +static bool AfterFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs before all keys and is therefore never after *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->largest.user_key()) > 0); +} + +static bool BeforeFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs after all keys and is therefore never before *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->smallest.user_key()) < 0); +} + +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + const Comparator* ucmp = icmp.user_comparator(); + if (!disjoint_sorted_files) { + // Need to check against all files + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + if (AfterFile(ucmp, smallest_user_key, f) || + BeforeFile(ucmp, largest_user_key, f)) { + // No overlap + } else { + return true; // Overlap + } + } + return false; + } + + // Binary search over file list + uint32_t index = 0; + if (smallest_user_key != nullptr) { + // Find the earliest possible internal key for smallest_user_key + InternalKey small_key(*smallest_user_key, kMaxSequenceNumber, + kValueTypeForSeek); + index = FindFile(icmp, files, small_key.Encode()); + } + + if (index >= files.size()) { + // beginning of range is after all files, so no overlap. + return false; + } + + return !BeforeFile(ucmp, largest_user_key, files[index]); +} + +// An internal iterator. For a given version/level pair, yields +// information about the files in the level. For a given entry, key() +// is the largest key that occurs in the file, and value() is an +// 16-byte value containing the file number and file size, both +// encoded using EncodeFixed64. +class Version::LevelFileNumIterator : public Iterator { + public: + LevelFileNumIterator(const InternalKeyComparator& icmp, + const std::vector* flist) + : icmp_(icmp), flist_(flist), index_(flist->size()) { // Marks as invalid + } + virtual bool Valid() const { return index_ < flist_->size(); } + virtual void Seek(const Slice& target) { + index_ = FindFile(icmp_, *flist_, target); + } + virtual void SeekToFirst() { index_ = 0; } + virtual void SeekToLast() { + index_ = flist_->empty() ? 0 : flist_->size() - 1; + } + virtual void Next() { + assert(Valid()); + index_++; + } + virtual void Prev() { + assert(Valid()); + if (index_ == 0) { + index_ = flist_->size(); // Marks as invalid + } else { + index_--; + } + } + Slice key() const { + assert(Valid()); + return (*flist_)[index_]->largest.Encode(); + } + Slice value() const { + assert(Valid()); + EncodeFixed64(value_buf_, (*flist_)[index_]->number); + EncodeFixed64(value_buf_ + 8, (*flist_)[index_]->file_size); + return Slice(value_buf_, sizeof(value_buf_)); + } + virtual Status status() const { return Status::OK(); } + + private: + const InternalKeyComparator icmp_; + const std::vector* const flist_; + uint32_t index_; + + // Backing store for value(). Holds the file number and size. + mutable char value_buf_[16]; +}; + +static Iterator* GetFileIterator(void* arg, const ReadOptions& options, + const Slice& file_value) { + TableCache* cache = reinterpret_cast(arg); + if (file_value.size() != 16) { + return NewErrorIterator( + Status::Corruption("FileReader invoked with unexpected value")); + } else { + return cache->NewIterator(options, DecodeFixed64(file_value.data()), + DecodeFixed64(file_value.data() + 8)); + } +} + +Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, + int level) const { + return NewTwoLevelIterator( + new LevelFileNumIterator(vset_->icmp_, &files_[level]), &GetFileIterator, + vset_->table_cache_, options); +} + +void Version::AddIterators(const ReadOptions& options, + std::vector* iters) { + // Merge all level zero files together since they may overlap + for (size_t i = 0; i < files_[0].size(); i++) { + iters->push_back(vset_->table_cache_->NewIterator( + options, files_[0][i]->number, files_[0][i]->file_size)); + } + + // For levels > 0, we can use a concatenating iterator that sequentially + // walks through the non-overlapping files in the level, opening them + // lazily. + for (int level = 1; level < config::kNumLevels; level++) { + if (!files_[level].empty()) { + iters->push_back(NewConcatenatingIterator(options, level)); + } + } +} + +// Callback from TableCache::Get() +namespace { +enum SaverState { + kNotFound, + kFound, + kDeleted, + kCorrupt, +}; +struct Saver { + SaverState state; + const Comparator* ucmp; + Slice user_key; + std::string* value; +}; +} // namespace +static void SaveValue(void* arg, const Slice& ikey, const Slice& v) { + Saver* s = reinterpret_cast(arg); + ParsedInternalKey parsed_key; + if (!ParseInternalKey(ikey, &parsed_key)) { + s->state = kCorrupt; + } else { + if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { + s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; + if (s->state == kFound) { + s->value->assign(v.data(), v.size()); + } + } + } +} + +static bool NewestFirst(FileMetaData* a, FileMetaData* b) { + return a->number > b->number; +} + +void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)) { + // TODO(sanjay): Change Version::Get() to use this function. + const Comparator* ucmp = vset_->icmp_.user_comparator(); + + // Search level-0 in order from newest to oldest. + std::vector tmp; + tmp.reserve(files_[0].size()); + for (uint32_t i = 0; i < files_[0].size(); i++) { + FileMetaData* f = files_[0][i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (!tmp.empty()) { + std::sort(tmp.begin(), tmp.end(), NewestFirst); + for (uint32_t i = 0; i < tmp.size(); i++) { + if (!(*func)(arg, 0, tmp[i])) { + return; + } + } + } + + // Search other levels. + for (int level = 1; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Binary search to find earliest index whose largest key >= internal_key. + uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); + if (index < num_files) { + FileMetaData* f = files_[level][index]; + if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { + // All of "f" is past any data for user_key + } else { + if (!(*func)(arg, level, f)) { + return; + } + } + } + } +} + +Status Version::Get(const ReadOptions& options, const LookupKey& k, + std::string* value, GetStats* stats) { + Slice ikey = k.internal_key(); + Slice user_key = k.user_key(); + const Comparator* ucmp = vset_->icmp_.user_comparator(); + Status s; + + stats->seek_file = nullptr; + stats->seek_file_level = -1; + FileMetaData* last_file_read = nullptr; + int last_file_read_level = -1; + + // We can search level-by-level since entries never hop across + // levels. Therefore we are guaranteed that if we find data + // in a smaller level, later levels are irrelevant. + std::vector tmp; + FileMetaData* tmp2; + for (int level = 0; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Get the list of files to search in this level + FileMetaData* const* files = &files_[level][0]; + if (level == 0) { + // Level-0 files may overlap each other. Find all files that + // overlap user_key and process them in order from newest to oldest. + tmp.reserve(num_files); + for (uint32_t i = 0; i < num_files; i++) { + FileMetaData* f = files[i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (tmp.empty()) continue; + + std::sort(tmp.begin(), tmp.end(), NewestFirst); + files = &tmp[0]; + num_files = tmp.size(); + } else { + // Binary search to find earliest index whose largest key >= ikey. + uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); + if (index >= num_files) { + files = nullptr; + num_files = 0; + } else { + tmp2 = files[index]; + if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { + // All of "tmp2" is past any data for user_key + files = nullptr; + num_files = 0; + } else { + files = &tmp2; + num_files = 1; + } + } + } + + for (uint32_t i = 0; i < num_files; ++i) { + if (last_file_read != nullptr && stats->seek_file == nullptr) { + // We have had more than one seek for this read. Charge the 1st file. + stats->seek_file = last_file_read; + stats->seek_file_level = last_file_read_level; + } + + FileMetaData* f = files[i]; + last_file_read = f; + last_file_read_level = level; + + Saver saver; + saver.state = kNotFound; + saver.ucmp = ucmp; + saver.user_key = user_key; + saver.value = value; + s = vset_->table_cache_->Get(options, f->number, f->file_size, ikey, + &saver, SaveValue); + if (!s.ok()) { + return s; + } + switch (saver.state) { + case kNotFound: + break; // Keep searching in other files + case kFound: + return s; + case kDeleted: + s = Status::NotFound(Slice()); // Use empty error message for speed + return s; + case kCorrupt: + s = Status::Corruption("corrupted key for ", user_key); + return s; + } + } + } + + return Status::NotFound(Slice()); // Use an empty error message for speed +} + +bool Version::UpdateStats(const GetStats& stats) { + FileMetaData* f = stats.seek_file; + if (f != nullptr) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } + } + return false; +} + +bool Version::RecordReadSample(Slice internal_key) { + ParsedInternalKey ikey; + if (!ParseInternalKey(internal_key, &ikey)) { + return false; + } + + struct State { + GetStats stats; // Holds first matching file + int matches; + + static bool Match(void* arg, int level, FileMetaData* f) { + State* state = reinterpret_cast(arg); + state->matches++; + if (state->matches == 1) { + // Remember first match. + state->stats.seek_file = f; + state->stats.seek_file_level = level; + } + // We can stop iterating once we have a second match. + return state->matches < 2; + } + }; + + State state; + state.matches = 0; + ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match); + + // Must have at least two matches since we want to merge across + // files. But what if we have a single file that contains many + // overwrites and deletions? Should we have another mechanism for + // finding such files? + if (state.matches >= 2) { + // 1MB cost is about 1 seek (see comment in Builder::Apply). + return UpdateStats(state.stats); + } + return false; +} + +void Version::Ref() { ++refs_; } + +void Version::Unref() { + assert(this != &vset_->dummy_versions_); + assert(refs_ >= 1); + --refs_; + if (refs_ == 0) { + delete this; + } +} + +bool Version::OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key) { + return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], + smallest_user_key, largest_user_key); +} + +int Version::PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key) { + int level = 0; + if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { + // Push to next level if there is no overlap in next level, + // and the #bytes overlapping in the level after that are limited. + InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey limit(largest_user_key, 0, static_cast(0)); + std::vector overlaps; + while (level < config::kMaxMemCompactLevel) { + if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { + break; + } + if (level + 2 < config::kNumLevels) { + // Check that file does not overlap too many grandparent bytes. + GetOverlappingInputs(level + 2, &start, &limit, &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > MaxGrandParentOverlapBytes(vset_->options_)) { + break; + } + } + level++; + } + } + return level; +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +void Version::GetOverlappingInputs(int level, const InternalKey* begin, + const InternalKey* end, + std::vector* inputs) { + assert(level >= 0); + assert(level < config::kNumLevels); + inputs->clear(); + Slice user_begin, user_end; + if (begin != nullptr) { + user_begin = begin->user_key(); + } + if (end != nullptr) { + user_end = end->user_key(); + } + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + for (size_t i = 0; i < files_[level].size();) { + FileMetaData* f = files_[level][i++]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (begin != nullptr && user_cmp->Compare(file_limit, user_begin) < 0) { + // "f" is completely before specified range; skip it + } else if (end != nullptr && user_cmp->Compare(file_start, user_end) > 0) { + // "f" is completely after specified range; skip it + } else { + inputs->push_back(f); + if (level == 0) { + // Level-0 files may overlap each other. So check if the newly + // added file has expanded the range. If so, restart search. + if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) { + user_begin = file_start; + inputs->clear(); + i = 0; + } else if (end != nullptr && + user_cmp->Compare(file_limit, user_end) > 0) { + user_end = file_limit; + inputs->clear(); + i = 0; + } + } + } + } +} + +std::string Version::DebugString() const { + std::string r; + for (int level = 0; level < config::kNumLevels; level++) { + // E.g., + // --- level 1 --- + // 17:123['a' .. 'd'] + // 20:43['e' .. 'g'] + r.append("--- level "); + AppendNumberTo(&r, level); + r.append(" ---\n"); + const std::vector& files = files_[level]; + for (size_t i = 0; i < files.size(); i++) { + r.push_back(' '); + AppendNumberTo(&r, files[i]->number); + r.push_back(':'); + AppendNumberTo(&r, files[i]->file_size); + r.append("["); + r.append(files[i]->smallest.DebugString()); + r.append(" .. "); + r.append(files[i]->largest.DebugString()); + r.append("]\n"); + } + } + return r; +} + +// A helper class so we can efficiently apply a whole sequence +// of edits to a particular state without creating intermediate +// Versions that contain full copies of the intermediate state. +class VersionSet::Builder { + private: + // Helper to sort by v->files_[file_number].smallest + struct BySmallestKey { + const InternalKeyComparator* internal_comparator; + + bool operator()(FileMetaData* f1, FileMetaData* f2) const { + int r = internal_comparator->Compare(f1->smallest, f2->smallest); + if (r != 0) { + return (r < 0); + } else { + // Break ties by file number + return (f1->number < f2->number); + } + } + }; + + typedef std::set FileSet; + struct LevelState { + std::set deleted_files; + FileSet* added_files; + }; + + VersionSet* vset_; + Version* base_; + LevelState levels_[config::kNumLevels]; + + public: + // Initialize a builder with the files from *base and other info from *vset + Builder(VersionSet* vset, Version* base) : vset_(vset), base_(base) { + base_->Ref(); + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + levels_[level].added_files = new FileSet(cmp); + } + } + + ~Builder() { + for (int level = 0; level < config::kNumLevels; level++) { + const FileSet* added = levels_[level].added_files; + std::vector to_unref; + to_unref.reserve(added->size()); + for (FileSet::const_iterator it = added->begin(); it != added->end(); + ++it) { + to_unref.push_back(*it); + } + delete added; + for (uint32_t i = 0; i < to_unref.size(); i++) { + FileMetaData* f = to_unref[i]; + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + base_->Unref(); + } + + // Apply all of the edits in *edit to the current state. + void Apply(VersionEdit* edit) { + // Update compaction pointers + for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { + const int level = edit->compact_pointers_[i].first; + vset_->compact_pointer_[level] = + edit->compact_pointers_[i].second.Encode().ToString(); + } + + // Delete files + const VersionEdit::DeletedFileSet& del = edit->deleted_files_; + for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); + iter != del.end(); ++iter) { + const int level = iter->first; + const uint64_t number = iter->second; + levels_[level].deleted_files.insert(number); + } + + // Add new files + for (size_t i = 0; i < edit->new_files_.size(); i++) { + const int level = edit->new_files_[i].first; + FileMetaData* f = new FileMetaData(edit->new_files_[i].second); + f->refs = 1; + + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = static_cast((f->file_size / 16384U)); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + + levels_[level].deleted_files.erase(f->number); + levels_[level].added_files->insert(f); + } + } + + // Save the current state in *v. + void SaveTo(Version* v) { + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + // Merge the set of added files with the set of pre-existing files. + // Drop any deleted files. Store the result in *v. + const std::vector& base_files = base_->files_[level]; + std::vector::const_iterator base_iter = base_files.begin(); + std::vector::const_iterator base_end = base_files.end(); + const FileSet* added = levels_[level].added_files; + v->files_[level].reserve(base_files.size() + added->size()); + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); ++added_iter) { + // Add all smaller files listed in base_ + for (std::vector::const_iterator bpos = + std::upper_bound(base_iter, base_end, *added_iter, cmp); + base_iter != bpos; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + + MaybeAddFile(v, level, *added_iter); + } + + // Add remaining base files + for (; base_iter != base_end; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + +#ifndef NDEBUG + // Make sure there is no overlap in levels > 0 + if (level > 0) { + for (uint32_t i = 1; i < v->files_[level].size(); i++) { + const InternalKey& prev_end = v->files_[level][i - 1]->largest; + const InternalKey& this_begin = v->files_[level][i]->smallest; + if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { + fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", + prev_end.DebugString().c_str(), + this_begin.DebugString().c_str()); + abort(); + } + } + } +#endif + } + } + + void MaybeAddFile(Version* v, int level, FileMetaData* f) { + if (levels_[level].deleted_files.count(f->number) > 0) { + // File is deleted: do nothing + } else { + std::vector* files = &v->files_[level]; + if (level > 0 && !files->empty()) { + // Must not overlap + assert(vset_->icmp_.Compare((*files)[files->size() - 1]->largest, + f->smallest) < 0); + } + f->refs++; + files->push_back(f); + } + } +}; + +VersionSet::VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, + const InternalKeyComparator* cmp) + : env_(options->env), + dbname_(dbname), + options_(options), + table_cache_(table_cache), + icmp_(*cmp), + next_file_number_(2), + manifest_file_number_(0), // Filled by Recover() + last_sequence_(0), + log_number_(0), + prev_log_number_(0), + descriptor_file_(nullptr), + descriptor_log_(nullptr), + dummy_versions_(this), + current_(nullptr) { + AppendVersion(new Version(this)); +} + +VersionSet::~VersionSet() { + current_->Unref(); + assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty + delete descriptor_log_; + delete descriptor_file_; +} + +void VersionSet::AppendVersion(Version* v) { + // Make "v" current + assert(v->refs_ == 0); + assert(v != current_); + if (current_ != nullptr) { + current_->Unref(); + } + current_ = v; + v->Ref(); + + // Append to linked list + v->prev_ = dummy_versions_.prev_; + v->next_ = &dummy_versions_; + v->prev_->next_ = v; + v->next_->prev_ = v; +} + +Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) { + if (edit->has_log_number_) { + assert(edit->log_number_ >= log_number_); + assert(edit->log_number_ < next_file_number_); + } else { + edit->SetLogNumber(log_number_); + } + + if (!edit->has_prev_log_number_) { + edit->SetPrevLogNumber(prev_log_number_); + } + + edit->SetNextFile(next_file_number_); + edit->SetLastSequence(last_sequence_); + + Version* v = new Version(this); + { + Builder builder(this, current_); + builder.Apply(edit); + builder.SaveTo(v); + } + Finalize(v); + + // Initialize new descriptor log file if necessary by creating + // a temporary file that contains a snapshot of the current version. + std::string new_manifest_file; + Status s; + if (descriptor_log_ == nullptr) { + // No reason to unlock *mu here since we only hit this path in the + // first call to LogAndApply (when opening the database). + assert(descriptor_file_ == nullptr); + new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); + edit->SetNextFile(next_file_number_); + s = env_->NewWritableFile(new_manifest_file, &descriptor_file_); + if (s.ok()) { + descriptor_log_ = new log::Writer(descriptor_file_); + s = WriteSnapshot(descriptor_log_); + } + } + + // Unlock during expensive MANIFEST log write + { + mu->Unlock(); + + // Write new record to MANIFEST log + if (s.ok()) { + std::string record; + edit->EncodeTo(&record); + s = descriptor_log_->AddRecord(record); + if (s.ok()) { + s = descriptor_file_->Sync(); + } + if (!s.ok()) { + Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); + } + } + + // If we just created a new descriptor file, install it by writing a + // new CURRENT file that points to it. + if (s.ok() && !new_manifest_file.empty()) { + s = SetCurrentFile(env_, dbname_, manifest_file_number_); + } + + mu->Lock(); + } + + // Install the new version + if (s.ok()) { + AppendVersion(v); + log_number_ = edit->log_number_; + prev_log_number_ = edit->prev_log_number_; + } else { + delete v; + if (!new_manifest_file.empty()) { + delete descriptor_log_; + delete descriptor_file_; + descriptor_log_ = nullptr; + descriptor_file_ = nullptr; + env_->DeleteFile(new_manifest_file); + } + } + + return s; +} + +Status VersionSet::Recover(bool* save_manifest) { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Read "CURRENT" file, which contains a pointer to the current manifest file + std::string current; + Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); + if (!s.ok()) { + return s; + } + if (current.empty() || current[current.size() - 1] != '\n') { + return Status::Corruption("CURRENT file does not end with newline"); + } + current.resize(current.size() - 1); + + std::string dscname = dbname_ + "/" + current; + SequentialFile* file; + s = env_->NewSequentialFile(dscname, &file); + if (!s.ok()) { + if (s.IsNotFound()) { + return Status::Corruption("CURRENT points to a non-existent file", + s.ToString()); + } + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(file, &reporter, true /*checksum*/, + 0 /*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit; + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + " does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + delete file; + file = nullptr; + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + + // See if we can reuse the existing MANIFEST file. + if (ReuseManifest(dscname, current)) { + // No need to save new manifest + } else { + *save_manifest = true; + } + } + + return s; +} + +bool VersionSet::ReuseManifest(const std::string& dscname, + const std::string& dscbase) { + if (!options_->reuse_logs) { + return false; + } + FileType manifest_type; + uint64_t manifest_number; + uint64_t manifest_size; + if (!ParseFileName(dscbase, &manifest_number, &manifest_type) || + manifest_type != kDescriptorFile || + !env_->GetFileSize(dscname, &manifest_size).ok() || + // Make new compacted MANIFEST if old one is too big + manifest_size >= TargetFileSize(options_)) { + return false; + } + + assert(descriptor_file_ == nullptr); + assert(descriptor_log_ == nullptr); + Status r = env_->NewAppendableFile(dscname, &descriptor_file_); + if (!r.ok()) { + Log(options_->info_log, "Reuse MANIFEST: %s\n", r.ToString().c_str()); + assert(descriptor_file_ == nullptr); + return false; + } + + Log(options_->info_log, "Reusing MANIFEST %s\n", dscname.c_str()); + descriptor_log_ = new log::Writer(descriptor_file_, manifest_size); + manifest_file_number_ = manifest_number; + return true; +} + +void VersionSet::MarkFileNumberUsed(uint64_t number) { + if (next_file_number_ <= number) { + next_file_number_ = number + 1; + } +} + +void VersionSet::Finalize(Version* v) { + // Precomputed best level for next compaction + int best_level = -1; + double best_score = -1; + + for (int level = 0; level < config::kNumLevels - 1; level++) { + double score; + if (level == 0) { + // We treat level-0 specially by bounding the number of files + // instead of number of bytes for two reasons: + // + // (1) With larger write-buffer sizes, it is nice not to do too + // many level-0 compactions. + // + // (2) The files in level-0 are merged on every read and + // therefore we wish to avoid too many files when the individual + // file size is small (perhaps because of a small write-buffer + // setting, or very high compression ratios, or lots of + // overwrites/deletions). + score = v->files_[level].size() / + static_cast(config::kL0_CompactionTrigger); + } else { + // Compute the ratio of current size to size limit. + const uint64_t level_bytes = TotalFileSize(v->files_[level]); + score = + static_cast(level_bytes) / MaxBytesForLevel(options_, level); + } + + if (score > best_score) { + best_level = level; + best_score = score; + } + } + + v->compaction_level_ = best_level; + v->compaction_score_ = best_score; +} + +Status VersionSet::WriteSnapshot(log::Writer* log) { + // TODO: Break up into multiple records to reduce memory usage on recovery? + + // Save metadata + VersionEdit edit; + edit.SetComparatorName(icmp_.user_comparator()->Name()); + + // Save compaction pointers + for (int level = 0; level < config::kNumLevels; level++) { + if (!compact_pointer_[level].empty()) { + InternalKey key; + key.DecodeFrom(compact_pointer_[level]); + edit.SetCompactPointer(level, key); + } + } + + // Save files + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = current_->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); + } + } + + std::string record; + edit.EncodeTo(&record); + return log->AddRecord(record); +} + +int VersionSet::NumLevelFiles(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return current_->files_[level].size(); +} + +const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { + // Update code if kNumLevels changes + static_assert(config::kNumLevels == 7, ""); + snprintf(scratch->buffer, sizeof(scratch->buffer), + "files[ %d %d %d %d %d %d %d ]", int(current_->files_[0].size()), + int(current_->files_[1].size()), int(current_->files_[2].size()), + int(current_->files_[3].size()), int(current_->files_[4].size()), + int(current_->files_[5].size()), int(current_->files_[6].size())); + return scratch->buffer; +} + +uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { + uint64_t result = 0; + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + if (icmp_.Compare(files[i]->largest, ikey) <= 0) { + // Entire file is before "ikey", so just add the file size + result += files[i]->file_size; + } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { + // Entire file is after "ikey", so ignore + if (level > 0) { + // Files other than level 0 are sorted by meta->smallest, so + // no further files in this level will contain data for + // "ikey". + break; + } + } else { + // "ikey" falls in the range for this table. Add the + // approximate offset of "ikey" within the table. + Table* tableptr; + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); + if (tableptr != nullptr) { + result += tableptr->ApproximateOffsetOf(ikey.Encode()); + } + delete iter; + } + } + } + return result; +} + +void VersionSet::AddLiveFiles(std::set* live) { + for (Version* v = dummy_versions_.next_; v != &dummy_versions_; + v = v->next_) { + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } + } +} + +int64_t VersionSet::NumLevelBytes(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return TotalFileSize(current_->files_[level]); +} + +int64_t VersionSet::MaxNextLevelOverlappingBytes() { + int64_t result = 0; + std::vector overlaps; + for (int level = 1; level < config::kNumLevels - 1; level++) { + for (size_t i = 0; i < current_->files_[level].size(); i++) { + const FileMetaData* f = current_->files_[level][i]; + current_->GetOverlappingInputs(level + 1, &f->smallest, &f->largest, + &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > result) { + result = sum; + } + } + } + return result; +} + +// Stores the minimal range that covers all entries in inputs in +// *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange(const std::vector& inputs, + InternalKey* smallest, InternalKey* largest) { + assert(!inputs.empty()); + smallest->Clear(); + largest->Clear(); + for (size_t i = 0; i < inputs.size(); i++) { + FileMetaData* f = inputs[i]; + if (i == 0) { + *smallest = f->smallest; + *largest = f->largest; + } else { + if (icmp_.Compare(f->smallest, *smallest) < 0) { + *smallest = f->smallest; + } + if (icmp_.Compare(f->largest, *largest) > 0) { + *largest = f->largest; + } + } + } +} + +// Stores the minimal range that covers all entries in inputs1 and inputs2 +// in *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest) { + std::vector all = inputs1; + all.insert(all.end(), inputs2.begin(), inputs2.end()); + GetRange(all, smallest, largest); +} + +Iterator* VersionSet::MakeInputIterator(Compaction* c) { + ReadOptions options; + options.verify_checksums = options_->paranoid_checks; + options.fill_cache = false; + + // Level-0 files have to be merged together. For other levels, + // we will make a concatenating iterator per level. + // TODO(opt): use concatenating iterator for level-0 if there is no overlap + const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); + Iterator** list = new Iterator*[space]; + int num = 0; + for (int which = 0; which < 2; which++) { + if (!c->inputs_[which].empty()) { + if (c->level() + which == 0) { + const std::vector& files = c->inputs_[which]; + for (size_t i = 0; i < files.size(); i++) { + list[num++] = table_cache_->NewIterator(options, files[i]->number, + files[i]->file_size); + } + } else { + // Create concatenating iterator for the files from this level + list[num++] = NewTwoLevelIterator( + new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), + &GetFileIterator, table_cache_, options); + } + } + } + assert(num <= space); + Iterator* result = NewMergingIterator(&icmp_, list, num); + delete[] list; + return result; +} + +Compaction* VersionSet::PickCompaction() { + Compaction* c; + int level; + + // We prefer compactions triggered by too much data in a level over + // the compactions triggered by seeks. + const bool size_compaction = (current_->compaction_score_ >= 1); + const bool seek_compaction = (current_->file_to_compact_ != nullptr); + if (size_compaction) { + level = current_->compaction_level_; + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + c = new Compaction(options_, level); + + // Pick the first file that comes after compact_pointer_[level] + for (size_t i = 0; i < current_->files_[level].size(); i++) { + FileMetaData* f = current_->files_[level][i]; + if (compact_pointer_[level].empty() || + icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) { + c->inputs_[0].push_back(f); + break; + } + } + if (c->inputs_[0].empty()) { + // Wrap-around to the beginning of the key space + c->inputs_[0].push_back(current_->files_[level][0]); + } + } else if (seek_compaction) { + level = current_->file_to_compact_level_; + c = new Compaction(options_, level); + c->inputs_[0].push_back(current_->file_to_compact_); + } else { + return nullptr; + } + + c->input_version_ = current_; + c->input_version_->Ref(); + + // Files in level 0 may overlap each other, so pick up all overlapping ones + if (level == 0) { + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + // Note that the next call will discard the file we placed in + // c->inputs_[0] earlier and replace it with an overlapping set + // which will include the picked file. + current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); + assert(!c->inputs_[0].empty()); + } + + SetupOtherInputs(c); + + return c; +} + +// Finds the largest key in a vector of files. Returns true if files it not +// empty. +bool FindLargestKey(const InternalKeyComparator& icmp, + const std::vector& files, + InternalKey* largest_key) { + if (files.empty()) { + return false; + } + *largest_key = files[0]->largest; + for (size_t i = 1; i < files.size(); ++i) { + FileMetaData* f = files[i]; + if (icmp.Compare(f->largest, *largest_key) > 0) { + *largest_key = f->largest; + } + } + return true; +} + +// Finds minimum file b2=(l2, u2) in level file for which l2 > u1 and +// user_key(l2) = user_key(u1) +FileMetaData* FindSmallestBoundaryFile( + const InternalKeyComparator& icmp, + const std::vector& level_files, + const InternalKey& largest_key) { + const Comparator* user_cmp = icmp.user_comparator(); + FileMetaData* smallest_boundary_file = nullptr; + for (size_t i = 0; i < level_files.size(); ++i) { + FileMetaData* f = level_files[i]; + if (icmp.Compare(f->smallest, largest_key) > 0 && + user_cmp->Compare(f->smallest.user_key(), largest_key.user_key()) == + 0) { + if (smallest_boundary_file == nullptr || + icmp.Compare(f->smallest, smallest_boundary_file->smallest) < 0) { + smallest_boundary_file = f; + } + } + } + return smallest_boundary_file; +} + +// Extracts the largest file b1 from |compaction_files| and then searches for a +// b2 in |level_files| for which user_key(u1) = user_key(l2). If it finds such a +// file b2 (known as a boundary file) it adds it to |compaction_files| and then +// searches again using this new upper bound. +// +// If there are two blocks, b1=(l1, u1) and b2=(l2, u2) and +// user_key(u1) = user_key(l2), and if we compact b1 but not b2 then a +// subsequent get operation will yield an incorrect result because it will +// return the record from b2 in level i rather than from b1 because it searches +// level by level for records matching the supplied user key. +// +// parameters: +// in level_files: List of files to search for boundary files. +// in/out compaction_files: List of files to extend by adding boundary files. +void AddBoundaryInputs(const InternalKeyComparator& icmp, + const std::vector& level_files, + std::vector* compaction_files) { + InternalKey largest_key; + + // Quick return if compaction_files is empty. + if (!FindLargestKey(icmp, *compaction_files, &largest_key)) { + return; + } + + bool continue_searching = true; + while (continue_searching) { + FileMetaData* smallest_boundary_file = + FindSmallestBoundaryFile(icmp, level_files, largest_key); + + // If a boundary file was found advance largest_key, otherwise we're done. + if (smallest_boundary_file != NULL) { + compaction_files->push_back(smallest_boundary_file); + largest_key = smallest_boundary_file->largest; + } else { + continue_searching = false; + } + } +} + +void VersionSet::SetupOtherInputs(Compaction* c) { + const int level = c->level(); + InternalKey smallest, largest; + + AddBoundaryInputs(icmp_, current_->files_[level], &c->inputs_[0]); + GetRange(c->inputs_[0], &smallest, &largest); + + current_->GetOverlappingInputs(level + 1, &smallest, &largest, + &c->inputs_[1]); + + // Get entire range covered by compaction + InternalKey all_start, all_limit; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if (!c->inputs_[1].empty()) { + std::vector expanded0; + current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0); + AddBoundaryInputs(icmp_, current_->files_[level], &expanded0); + const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); + const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); + const int64_t expanded0_size = TotalFileSize(expanded0); + if (expanded0.size() > c->inputs_[0].size() && + inputs1_size + expanded0_size < + ExpandedCompactionByteSizeLimit(options_)) { + InternalKey new_start, new_limit; + GetRange(expanded0, &new_start, &new_limit); + std::vector expanded1; + current_->GetOverlappingInputs(level + 1, &new_start, &new_limit, + &expanded1); + if (expanded1.size() == c->inputs_[1].size()) { + Log(options_->info_log, + "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", + level, int(c->inputs_[0].size()), int(c->inputs_[1].size()), + long(inputs0_size), long(inputs1_size), int(expanded0.size()), + int(expanded1.size()), long(expanded0_size), long(inputs1_size)); + smallest = new_start; + largest = new_limit; + c->inputs_[0] = expanded0; + c->inputs_[1] = expanded1; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if (level + 2 < config::kNumLevels) { + current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, + &c->grandparents_); + } + + // Update the place where we will do the next compaction for this level. + // We update this immediately instead of waiting for the VersionEdit + // to be applied so that if the compaction fails, we will try a different + // key range next time. + compact_pointer_[level] = largest.Encode().ToString(); + c->edit_.SetCompactPointer(level, largest); +} + +Compaction* VersionSet::CompactRange(int level, const InternalKey* begin, + const InternalKey* end) { + std::vector inputs; + current_->GetOverlappingInputs(level, begin, end, &inputs); + if (inputs.empty()) { + return nullptr; + } + + // Avoid compacting too much in one shot in case the range is large. + // But we cannot do this for level-0 since level-0 files can overlap + // and we must not pick one file and drop another older file if the + // two files overlap. + if (level > 0) { + const uint64_t limit = MaxFileSizeForLevel(options_, level); + uint64_t total = 0; + for (size_t i = 0; i < inputs.size(); i++) { + uint64_t s = inputs[i]->file_size; + total += s; + if (total >= limit) { + inputs.resize(i + 1); + break; + } + } + } + + Compaction* c = new Compaction(options_, level); + c->input_version_ = current_; + c->input_version_->Ref(); + c->inputs_[0] = inputs; + SetupOtherInputs(c); + return c; +} + +Compaction::Compaction(const Options* options, int level) + : level_(level), + max_output_file_size_(MaxFileSizeForLevel(options, level)), + input_version_(nullptr), + grandparent_index_(0), + seen_key_(false), + overlapped_bytes_(0) { + for (int i = 0; i < config::kNumLevels; i++) { + level_ptrs_[i] = 0; + } +} + +Compaction::~Compaction() { + if (input_version_ != nullptr) { + input_version_->Unref(); + } +} + +bool Compaction::IsTrivialMove() const { + const VersionSet* vset = input_version_->vset_; + // Avoid a move if there is lots of overlapping grandparent data. + // Otherwise, the move could create a parent file that will require + // a very expensive merge later on. + return (num_input_files(0) == 1 && num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= + MaxGrandParentOverlapBytes(vset->options_)); +} + +void Compaction::AddInputDeletions(VersionEdit* edit) { + for (int which = 0; which < 2; which++) { + for (size_t i = 0; i < inputs_[which].size(); i++) { + edit->DeleteFile(level_ + which, inputs_[which][i]->number); + } + } +} + +bool Compaction::IsBaseLevelForKey(const Slice& user_key) { + // Maybe use binary search to find right entry instead of linear search? + const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); + for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) { + const std::vector& files = input_version_->files_[lvl]; + for (; level_ptrs_[lvl] < files.size();) { + FileMetaData* f = files[level_ptrs_[lvl]]; + if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { + // We've advanced far enough + if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { + // Key falls in this file's range, so definitely not base level + return false; + } + break; + } + level_ptrs_[lvl]++; + } + } + return true; +} + +bool Compaction::ShouldStopBefore(const Slice& internal_key) { + const VersionSet* vset = input_version_->vset_; + // Scan to find earliest grandparent file that contains key. + const InternalKeyComparator* icmp = &vset->icmp_; + while (grandparent_index_ < grandparents_.size() && + icmp->Compare(internal_key, + grandparents_[grandparent_index_]->largest.Encode()) > + 0) { + if (seen_key_) { + overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; + } + grandparent_index_++; + } + seen_key_ = true; + + if (overlapped_bytes_ > MaxGrandParentOverlapBytes(vset->options_)) { + // Too much overlap for current output; start new output + overlapped_bytes_ = 0; + return true; + } else { + return false; + } +} + +void Compaction::ReleaseInputs() { + if (input_version_ != nullptr) { + input_version_->Unref(); + input_version_ = nullptr; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/version_set.h b/PediatricPancreas/Pods/leveldb-library/db/version_set.h new file mode 100644 index 0000000..69f3d70 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/version_set.h @@ -0,0 +1,393 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// The representation of a DBImpl consists of a set of Versions. The +// newest version is called "current". Older versions may be kept +// around to provide a consistent view to live iterators. +// +// Each Version keeps track of a set of Table files per level. The +// entire set of versions is maintained in a VersionSet. +// +// Version,VersionSet are thread-compatible, but require external +// synchronization on all accesses. + +#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ +#define STORAGE_LEVELDB_DB_VERSION_SET_H_ + +#include +#include +#include + +#include "db/dbformat.h" +#include "db/version_edit.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +namespace log { +class Writer; +} + +class Compaction; +class Iterator; +class MemTable; +class TableBuilder; +class TableCache; +class Version; +class VersionSet; +class WritableFile; + +// Return the smallest index i such that files[i]->largest >= key. +// Return files.size() if there is no such file. +// REQUIRES: "files" contains a sorted list of non-overlapping files. +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key); + +// Returns true iff some file in "files" overlaps the user key range +// [*smallest,*largest]. +// smallest==nullptr represents a key smaller than all keys in the DB. +// largest==nullptr represents a key largest than all keys in the DB. +// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges +// in sorted order. +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key); + +class Version { + public: + // Lookup the value for key. If found, store it in *val and + // return OK. Else return a non-OK status. Fills *stats. + // REQUIRES: lock is not held + struct GetStats { + FileMetaData* seek_file; + int seek_file_level; + }; + + // Append to *iters a sequence of iterators that will + // yield the contents of this Version when merged together. + // REQUIRES: This version has been saved (see VersionSet::SaveTo) + void AddIterators(const ReadOptions&, std::vector* iters); + + Status Get(const ReadOptions&, const LookupKey& key, std::string* val, + GetStats* stats); + + // Adds "stats" into the current state. Returns true if a new + // compaction may need to be triggered, false otherwise. + // REQUIRES: lock is held + bool UpdateStats(const GetStats& stats); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. Returns true if a new compaction may need to be triggered. + // REQUIRES: lock is held + bool RecordReadSample(Slice key); + + // Reference count management (so Versions do not disappear out from + // under live iterators) + void Ref(); + void Unref(); + + void GetOverlappingInputs( + int level, + const InternalKey* begin, // nullptr means before all keys + const InternalKey* end, // nullptr means after all keys + std::vector* inputs); + + // Returns true iff some file in the specified level overlaps + // some part of [*smallest_user_key,*largest_user_key]. + // smallest_user_key==nullptr represents a key smaller than all the DB's keys. + // largest_user_key==nullptr represents a key largest than all the DB's keys. + bool OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key); + + // Return the level at which we should place a new memtable compaction + // result that covers the range [smallest_user_key,largest_user_key]. + int PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key); + + int NumFiles(int level) const { return files_[level].size(); } + + // Return a human readable string that describes this version's contents. + std::string DebugString() const; + + private: + friend class Compaction; + friend class VersionSet; + + class LevelFileNumIterator; + + explicit Version(VersionSet* vset) + : vset_(vset), + next_(this), + prev_(this), + refs_(0), + file_to_compact_(nullptr), + file_to_compact_level_(-1), + compaction_score_(-1), + compaction_level_(-1) {} + + Version(const Version&) = delete; + Version& operator=(const Version&) = delete; + + ~Version(); + + Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; + + // Call func(arg, level, f) for every file that overlaps user_key in + // order from newest to oldest. If an invocation of func returns + // false, makes no more calls. + // + // REQUIRES: user portion of internal_key == user_key. + void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)); + + VersionSet* vset_; // VersionSet to which this Version belongs + Version* next_; // Next version in linked list + Version* prev_; // Previous version in linked list + int refs_; // Number of live refs to this version + + // List of files per level + std::vector files_[config::kNumLevels]; + + // Next file to compact based on seek stats. + FileMetaData* file_to_compact_; + int file_to_compact_level_; + + // Level that should be compacted next and its compaction score. + // Score < 1 means compaction is not strictly needed. These fields + // are initialized by Finalize(). + double compaction_score_; + int compaction_level_; +}; + +class VersionSet { + public: + VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, const InternalKeyComparator*); + VersionSet(const VersionSet&) = delete; + VersionSet& operator=(const VersionSet&) = delete; + + ~VersionSet(); + + // Apply *edit to the current version to form a new descriptor that + // is both saved to persistent state and installed as the new + // current version. Will release *mu while actually writing to the file. + // REQUIRES: *mu is held on entry. + // REQUIRES: no other thread concurrently calls LogAndApply() + Status LogAndApply(VersionEdit* edit, port::Mutex* mu) + EXCLUSIVE_LOCKS_REQUIRED(mu); + + // Recover the last saved descriptor from persistent storage. + Status Recover(bool* save_manifest); + + // Return the current version. + Version* current() const { return current_; } + + // Return the current manifest file number + uint64_t ManifestFileNumber() const { return manifest_file_number_; } + + // Allocate and return a new file number + uint64_t NewFileNumber() { return next_file_number_++; } + + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + + // Return the number of Table files at the specified level. + int NumLevelFiles(int level) const; + + // Return the combined file size of all files at the specified level. + int64_t NumLevelBytes(int level) const; + + // Return the last sequence number. + uint64_t LastSequence() const { return last_sequence_; } + + // Set the last sequence number to s. + void SetLastSequence(uint64_t s) { + assert(s >= last_sequence_); + last_sequence_ = s; + } + + // Mark the specified file number as used. + void MarkFileNumberUsed(uint64_t number); + + // Return the current log file number. + uint64_t LogNumber() const { return log_number_; } + + // Return the log file number for the log file that is currently + // being compacted, or zero if there is no such log file. + uint64_t PrevLogNumber() const { return prev_log_number_; } + + // Pick level and inputs for a new compaction. + // Returns nullptr if there is no compaction to be done. + // Otherwise returns a pointer to a heap-allocated object that + // describes the compaction. Caller should delete the result. + Compaction* PickCompaction(); + + // Return a compaction object for compacting the range [begin,end] in + // the specified level. Returns nullptr if there is nothing in that + // level that overlaps the specified range. Caller should delete + // the result. + Compaction* CompactRange(int level, const InternalKey* begin, + const InternalKey* end); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t MaxNextLevelOverlappingBytes(); + + // Create an iterator that reads over the compaction inputs for "*c". + // The caller should delete the iterator when no longer needed. + Iterator* MakeInputIterator(Compaction* c); + + // Returns true iff some level needs a compaction. + bool NeedsCompaction() const { + Version* v = current_; + return (v->compaction_score_ >= 1) || (v->file_to_compact_ != nullptr); + } + + // Add all files listed in any live version to *live. + // May also mutate some internal state. + void AddLiveFiles(std::set* live); + + // Return the approximate offset in the database of the data for + // "key" as of version "v". + uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); + + // Return a human-readable short (single-line) summary of the number + // of files per level. Uses *scratch as backing store. + struct LevelSummaryStorage { + char buffer[100]; + }; + const char* LevelSummary(LevelSummaryStorage* scratch) const; + + private: + class Builder; + + friend class Compaction; + friend class Version; + + bool ReuseManifest(const std::string& dscname, const std::string& dscbase); + + void Finalize(Version* v); + + void GetRange(const std::vector& inputs, InternalKey* smallest, + InternalKey* largest); + + void GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest); + + void SetupOtherInputs(Compaction* c); + + // Save current contents to *log + Status WriteSnapshot(log::Writer* log); + + void AppendVersion(Version* v); + + Env* const env_; + const std::string dbname_; + const Options* const options_; + TableCache* const table_cache_; + const InternalKeyComparator icmp_; + uint64_t next_file_number_; + uint64_t manifest_file_number_; + uint64_t last_sequence_; + uint64_t log_number_; + uint64_t prev_log_number_; // 0 or backing store for memtable being compacted + + // Opened lazily + WritableFile* descriptor_file_; + log::Writer* descriptor_log_; + Version dummy_versions_; // Head of circular doubly-linked list of versions. + Version* current_; // == dummy_versions_.prev_ + + // Per-level key at which the next compaction at that level should start. + // Either an empty string, or a valid InternalKey. + std::string compact_pointer_[config::kNumLevels]; +}; + +// A Compaction encapsulates information about a compaction. +class Compaction { + public: + ~Compaction(); + + // Return the level that is being compacted. Inputs from "level" + // and "level+1" will be merged to produce a set of "level+1" files. + int level() const { return level_; } + + // Return the object that holds the edits to the descriptor done + // by this compaction. + VersionEdit* edit() { return &edit_; } + + // "which" must be either 0 or 1 + int num_input_files(int which) const { return inputs_[which].size(); } + + // Return the ith input file at "level()+which" ("which" must be 0 or 1). + FileMetaData* input(int which, int i) const { return inputs_[which][i]; } + + // Maximum size of files to build during this compaction. + uint64_t MaxOutputFileSize() const { return max_output_file_size_; } + + // Is this a trivial compaction that can be implemented by just + // moving a single input file to the next level (no merging or splitting) + bool IsTrivialMove() const; + + // Add all inputs to this compaction as delete operations to *edit. + void AddInputDeletions(VersionEdit* edit); + + // Returns true if the information we have available guarantees that + // the compaction is producing data in "level+1" for which no data exists + // in levels greater than "level+1". + bool IsBaseLevelForKey(const Slice& user_key); + + // Returns true iff we should stop building the current output + // before processing "internal_key". + bool ShouldStopBefore(const Slice& internal_key); + + // Release the input version for the compaction, once the compaction + // is successful. + void ReleaseInputs(); + + private: + friend class Version; + friend class VersionSet; + + Compaction(const Options* options, int level); + + int level_; + uint64_t max_output_file_size_; + Version* input_version_; + VersionEdit edit_; + + // Each compaction reads inputs from "level_" and "level_+1" + std::vector inputs_[2]; // The two sets of inputs + + // State used to check for number of overlapping grandparent files + // (parent == level_ + 1, grandparent == level_ + 2) + std::vector grandparents_; + size_t grandparent_index_; // Index in grandparent_starts_ + bool seen_key_; // Some output key has been seen + int64_t overlapped_bytes_; // Bytes of overlap between current output + // and grandparent files + + // State for implementing IsBaseLevelForKey + + // level_ptrs_ holds indices into input_version_->levels_: our state + // is that we are positioned at one of the file ranges for each + // higher level than the ones involved in this compaction (i.e. for + // all L >= level_ + 2). + size_t level_ptrs_[config::kNumLevels]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/db/write_batch.cc b/PediatricPancreas/Pods/leveldb-library/db/write_batch.cc new file mode 100644 index 0000000..2dec642 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/write_batch.cc @@ -0,0 +1,150 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch::rep_ := +// sequence: fixed64 +// count: fixed32 +// data: record[count] +// record := +// kTypeValue varstring varstring | +// kTypeDeletion varstring +// varstring := +// len: varint32 +// data: uint8[len] + +#include "leveldb/write_batch.h" + +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "util/coding.h" + +namespace leveldb { + +// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. +static const size_t kHeader = 12; + +WriteBatch::WriteBatch() { Clear(); } + +WriteBatch::~WriteBatch() {} + +WriteBatch::Handler::~Handler() {} + +void WriteBatch::Clear() { + rep_.clear(); + rep_.resize(kHeader); +} + +size_t WriteBatch::ApproximateSize() const { return rep_.size(); } + +Status WriteBatch::Iterate(Handler* handler) const { + Slice input(rep_); + if (input.size() < kHeader) { + return Status::Corruption("malformed WriteBatch (too small)"); + } + + input.remove_prefix(kHeader); + Slice key, value; + int found = 0; + while (!input.empty()) { + found++; + char tag = input[0]; + input.remove_prefix(1); + switch (tag) { + case kTypeValue: + if (GetLengthPrefixedSlice(&input, &key) && + GetLengthPrefixedSlice(&input, &value)) { + handler->Put(key, value); + } else { + return Status::Corruption("bad WriteBatch Put"); + } + break; + case kTypeDeletion: + if (GetLengthPrefixedSlice(&input, &key)) { + handler->Delete(key); + } else { + return Status::Corruption("bad WriteBatch Delete"); + } + break; + default: + return Status::Corruption("unknown WriteBatch tag"); + } + } + if (found != WriteBatchInternal::Count(this)) { + return Status::Corruption("WriteBatch has wrong count"); + } else { + return Status::OK(); + } +} + +int WriteBatchInternal::Count(const WriteBatch* b) { + return DecodeFixed32(b->rep_.data() + 8); +} + +void WriteBatchInternal::SetCount(WriteBatch* b, int n) { + EncodeFixed32(&b->rep_[8], n); +} + +SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { + return SequenceNumber(DecodeFixed64(b->rep_.data())); +} + +void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { + EncodeFixed64(&b->rep_[0], seq); +} + +void WriteBatch::Put(const Slice& key, const Slice& value) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + PutLengthPrefixedSlice(&rep_, value); +} + +void WriteBatch::Delete(const Slice& key) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeDeletion)); + PutLengthPrefixedSlice(&rep_, key); +} + +void WriteBatch::Append(const WriteBatch& source) { + WriteBatchInternal::Append(this, &source); +} + +namespace { +class MemTableInserter : public WriteBatch::Handler { + public: + SequenceNumber sequence_; + MemTable* mem_; + + virtual void Put(const Slice& key, const Slice& value) { + mem_->Add(sequence_, kTypeValue, key, value); + sequence_++; + } + virtual void Delete(const Slice& key) { + mem_->Add(sequence_, kTypeDeletion, key, Slice()); + sequence_++; + } +}; +} // namespace + +Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) { + MemTableInserter inserter; + inserter.sequence_ = WriteBatchInternal::Sequence(b); + inserter.mem_ = memtable; + return b->Iterate(&inserter); +} + +void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { + assert(contents.size() >= kHeader); + b->rep_.assign(contents.data(), contents.size()); +} + +void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { + SetCount(dst, Count(dst) + Count(src)); + assert(src->rep_.size() >= kHeader); + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/db/write_batch_internal.h b/PediatricPancreas/Pods/leveldb-library/db/write_batch_internal.h new file mode 100644 index 0000000..fce86e3 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/db/write_batch_internal.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ +#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ + +#include "db/dbformat.h" +#include "leveldb/write_batch.h" + +namespace leveldb { + +class MemTable; + +// WriteBatchInternal provides static methods for manipulating a +// WriteBatch that we don't want in the public WriteBatch interface. +class WriteBatchInternal { + public: + // Return the number of entries in the batch. + static int Count(const WriteBatch* batch); + + // Set the count for the number of entries in the batch. + static void SetCount(WriteBatch* batch, int n); + + // Return the sequence number for the start of this batch. + static SequenceNumber Sequence(const WriteBatch* batch); + + // Store the specified number as the sequence number for the start of + // this batch. + static void SetSequence(WriteBatch* batch, SequenceNumber seq); + + static Slice Contents(const WriteBatch* batch) { return Slice(batch->rep_); } + + static size_t ByteSize(const WriteBatch* batch) { return batch->rep_.size(); } + + static void SetContents(WriteBatch* batch, const Slice& contents); + + static Status InsertInto(const WriteBatch* batch, MemTable* memtable); + + static void Append(WriteBatch* dst, const WriteBatch* src); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/c.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/c.h new file mode 100644 index 0000000..8e0d592 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/c.h @@ -0,0 +1,270 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. + + C bindings for leveldb. May be useful as a stable ABI that can be + used by programs that keep leveldb in a shared library, or for + a JNI api. + + Does not support: + . getters for the option types + . custom comparators that implement key shortening + . custom iter, db, env, cache implementations using just the C bindings + + Some conventions: + + (1) We expose just opaque struct pointers and functions to clients. + This allows us to change internal representations without having to + recompile clients. + + (2) For simplicity, there is no equivalent to the Slice type. Instead, + the caller has to pass the pointer and length as separate + arguments. + + (3) Errors are represented by a null-terminated c string. NULL + means no error. All operations that can raise an error are passed + a "char** errptr" as the last argument. One of the following must + be true on entry: + *errptr == NULL + *errptr points to a malloc()ed null-terminated error message + (On Windows, *errptr must have been malloc()-ed by this library.) + On success, a leveldb routine leaves *errptr unchanged. + On failure, leveldb frees the old value of *errptr and + set *errptr to a malloc()ed error message. + + (4) Bools have the type unsigned char (0 == false; rest == true) + + (5) All of the pointer arguments must be non-NULL. +*/ + +#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ +#define STORAGE_LEVELDB_INCLUDE_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "leveldb/export.h" + +/* Exported types */ + +typedef struct leveldb_t leveldb_t; +typedef struct leveldb_cache_t leveldb_cache_t; +typedef struct leveldb_comparator_t leveldb_comparator_t; +typedef struct leveldb_env_t leveldb_env_t; +typedef struct leveldb_filelock_t leveldb_filelock_t; +typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; +typedef struct leveldb_iterator_t leveldb_iterator_t; +typedef struct leveldb_logger_t leveldb_logger_t; +typedef struct leveldb_options_t leveldb_options_t; +typedef struct leveldb_randomfile_t leveldb_randomfile_t; +typedef struct leveldb_readoptions_t leveldb_readoptions_t; +typedef struct leveldb_seqfile_t leveldb_seqfile_t; +typedef struct leveldb_snapshot_t leveldb_snapshot_t; +typedef struct leveldb_writablefile_t leveldb_writablefile_t; +typedef struct leveldb_writebatch_t leveldb_writebatch_t; +typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; + +/* DB operations */ + +LEVELDB_EXPORT leveldb_t* leveldb_open(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_close(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_put(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr); + +LEVELDB_EXPORT void leveldb_delete(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr); + +LEVELDB_EXPORT void leveldb_write(leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr); + +/* Returns NULL if not found. A malloc()ed array otherwise. + Stores the length of the array in *vallen. */ +LEVELDB_EXPORT char* leveldb_get(leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr); + +LEVELDB_EXPORT leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options); + +LEVELDB_EXPORT const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_release_snapshot( + leveldb_t* db, const leveldb_snapshot_t* snapshot); + +/* Returns NULL if property name is unknown. + Else returns a pointer to a malloc()-ed null-terminated value. */ +LEVELDB_EXPORT char* leveldb_property_value(leveldb_t* db, + const char* propname); + +LEVELDB_EXPORT void leveldb_approximate_sizes( + leveldb_t* db, int num_ranges, const char* const* range_start_key, + const size_t* range_start_key_len, const char* const* range_limit_key, + const size_t* range_limit_key_len, uint64_t* sizes); + +LEVELDB_EXPORT void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, + const char* limit_key, + size_t limit_key_len); + +/* Management operations */ + +LEVELDB_EXPORT void leveldb_destroy_db(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_repair_db(const leveldb_options_t* options, + const char* name, char** errptr); + +/* Iterator */ + +LEVELDB_EXPORT void leveldb_iter_destroy(leveldb_iterator_t*); +LEVELDB_EXPORT unsigned char leveldb_iter_valid(const leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_first(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_last(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek(leveldb_iterator_t*, const char* k, + size_t klen); +LEVELDB_EXPORT void leveldb_iter_next(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_prev(leveldb_iterator_t*); +LEVELDB_EXPORT const char* leveldb_iter_key(const leveldb_iterator_t*, + size_t* klen); +LEVELDB_EXPORT const char* leveldb_iter_value(const leveldb_iterator_t*, + size_t* vlen); +LEVELDB_EXPORT void leveldb_iter_get_error(const leveldb_iterator_t*, + char** errptr); + +/* Write batch */ + +LEVELDB_EXPORT leveldb_writebatch_t* leveldb_writebatch_create(); +LEVELDB_EXPORT void leveldb_writebatch_destroy(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_clear(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_put(leveldb_writebatch_t*, + const char* key, size_t klen, + const char* val, size_t vlen); +LEVELDB_EXPORT void leveldb_writebatch_delete(leveldb_writebatch_t*, + const char* key, size_t klen); +LEVELDB_EXPORT void leveldb_writebatch_iterate( + const leveldb_writebatch_t*, void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)); +LEVELDB_EXPORT void leveldb_writebatch_append( + leveldb_writebatch_t* destination, const leveldb_writebatch_t* source); + +/* Options */ + +LEVELDB_EXPORT leveldb_options_t* leveldb_options_create(); +LEVELDB_EXPORT void leveldb_options_destroy(leveldb_options_t*); +LEVELDB_EXPORT void leveldb_options_set_comparator(leveldb_options_t*, + leveldb_comparator_t*); +LEVELDB_EXPORT void leveldb_options_set_filter_policy(leveldb_options_t*, + leveldb_filterpolicy_t*); +LEVELDB_EXPORT void leveldb_options_set_create_if_missing(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_error_if_exists(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_paranoid_checks(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); +LEVELDB_EXPORT void leveldb_options_set_info_log(leveldb_options_t*, + leveldb_logger_t*); +LEVELDB_EXPORT void leveldb_options_set_write_buffer_size(leveldb_options_t*, + size_t); +LEVELDB_EXPORT void leveldb_options_set_max_open_files(leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_cache(leveldb_options_t*, + leveldb_cache_t*); +LEVELDB_EXPORT void leveldb_options_set_block_size(leveldb_options_t*, size_t); +LEVELDB_EXPORT void leveldb_options_set_block_restart_interval( + leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*, + size_t); + +enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 }; +LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int); + +/* Comparator */ + +LEVELDB_EXPORT leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_comparator_destroy(leveldb_comparator_t*); + +/* Filter policy */ + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( + int bits_per_key); + +/* Read options */ + +LEVELDB_EXPORT leveldb_readoptions_t* leveldb_readoptions_create(); +LEVELDB_EXPORT void leveldb_readoptions_destroy(leveldb_readoptions_t*); +LEVELDB_EXPORT void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t*, unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_snapshot(leveldb_readoptions_t*, + const leveldb_snapshot_t*); + +/* Write options */ + +LEVELDB_EXPORT leveldb_writeoptions_t* leveldb_writeoptions_create(); +LEVELDB_EXPORT void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); +LEVELDB_EXPORT void leveldb_writeoptions_set_sync(leveldb_writeoptions_t*, + unsigned char); + +/* Cache */ + +LEVELDB_EXPORT leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); +LEVELDB_EXPORT void leveldb_cache_destroy(leveldb_cache_t* cache); + +/* Env */ + +LEVELDB_EXPORT leveldb_env_t* leveldb_create_default_env(); +LEVELDB_EXPORT void leveldb_env_destroy(leveldb_env_t*); + +/* If not NULL, the returned buffer must be released using leveldb_free(). */ +LEVELDB_EXPORT char* leveldb_env_get_test_directory(leveldb_env_t*); + +/* Utility */ + +/* Calls free(ptr). + REQUIRES: ptr was malloc()-ed and returned by one of the routines + in this file. Note that in certain cases (typically on Windows), you + may need to call this routine instead of free(ptr) to dispose of + malloc()-ed memory returned by this library. */ +LEVELDB_EXPORT void leveldb_free(void* ptr); + +/* Return the major version number for this release. */ +LEVELDB_EXPORT int leveldb_major_version(); + +/* Return the minor version number for this release. */ +LEVELDB_EXPORT int leveldb_minor_version(); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/cache.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/cache.h new file mode 100644 index 0000000..7d1a221 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/cache.h @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Cache is an interface that maps keys to values. It has internal +// synchronization and may be safely accessed concurrently from +// multiple threads. It may automatically evict entries to make room +// for new entries. Values have a specified charge against the cache +// capacity. For example, a cache where the values are variable +// length strings, may use the length of the string as the charge for +// the string. +// +// A builtin cache implementation with a least-recently-used eviction +// policy is provided. Clients may use their own implementations if +// they want something more sophisticated (like scan-resistance, a +// custom eviction policy, variable cache sizing, etc.) + +#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ +#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Cache; + +// Create a new cache with a fixed size capacity. This implementation +// of Cache uses a least-recently-used eviction policy. +LEVELDB_EXPORT Cache* NewLRUCache(size_t capacity); + +class LEVELDB_EXPORT Cache { + public: + Cache() = default; + + Cache(const Cache&) = delete; + Cache& operator=(const Cache&) = delete; + + // Destroys all existing entries by calling the "deleter" + // function that was passed to the constructor. + virtual ~Cache(); + + // Opaque handle to an entry stored in the cache. + struct Handle {}; + + // Insert a mapping from key->value into the cache and assign it + // the specified charge against the total cache capacity. + // + // Returns a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + // + // When the inserted entry is no longer needed, the key and + // value will be passed to "deleter". + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) = 0; + + // If the cache has no mapping for "key", returns nullptr. + // + // Else return a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + virtual Handle* Lookup(const Slice& key) = 0; + + // Release a mapping returned by a previous Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void Release(Handle* handle) = 0; + + // Return the value encapsulated in a handle returned by a + // successful Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void* Value(Handle* handle) = 0; + + // If the cache contains entry for key, erase it. Note that the + // underlying entry will be kept around until all existing handles + // to it have been released. + virtual void Erase(const Slice& key) = 0; + + // Return a new numeric id. May be used by multiple clients who are + // sharing the same cache to partition the key space. Typically the + // client will allocate a new id at startup and prepend the id to + // its cache keys. + virtual uint64_t NewId() = 0; + + // Remove all cache entries that are not actively in use. Memory-constrained + // applications may wish to call this method to reduce memory usage. + // Default implementation of Prune() does nothing. Subclasses are strongly + // encouraged to override the default implementation. A future release of + // leveldb may change Prune() to a pure abstract method. + virtual void Prune() {} + + // Return an estimate of the combined charges of all elements stored in the + // cache. + virtual size_t TotalCharge() const = 0; + + private: + void LRU_Remove(Handle* e); + void LRU_Append(Handle* e); + void Unref(Handle* e); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_CACHE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/comparator.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/comparator.h new file mode 100644 index 0000000..a85b51e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/comparator.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +// A Comparator object provides a total order across slices that are +// used as keys in an sstable or a database. A Comparator implementation +// must be thread-safe since leveldb may invoke its methods concurrently +// from multiple threads. +class LEVELDB_EXPORT Comparator { + public: + virtual ~Comparator(); + + // Three-way comparison. Returns value: + // < 0 iff "a" < "b", + // == 0 iff "a" == "b", + // > 0 iff "a" > "b" + virtual int Compare(const Slice& a, const Slice& b) const = 0; + + // The name of the comparator. Used to check for comparator + // mismatches (i.e., a DB created with one comparator is + // accessed using a different comparator. + // + // The client of this package should switch to a new name whenever + // the comparator implementation changes in a way that will cause + // the relative ordering of any two keys to change. + // + // Names starting with "leveldb." are reserved and should not be used + // by any clients of this package. + virtual const char* Name() const = 0; + + // Advanced functions: these are used to reduce the space requirements + // for internal data structures like index blocks. + + // If *start < limit, changes *start to a short string in [start,limit). + // Simple comparator implementations may return with *start unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const = 0; + + // Changes *key to a short string >= *key. + // Simple comparator implementations may return with *key unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortSuccessor(std::string* key) const = 0; +}; + +// Return a builtin comparator that uses lexicographic byte-wise +// ordering. The result remains the property of this module and +// must not be deleted. +LEVELDB_EXPORT const Comparator* BytewiseComparator(); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/db.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/db.h new file mode 100644 index 0000000..ea3d9e5 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/db.h @@ -0,0 +1,167 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ +#define STORAGE_LEVELDB_INCLUDE_DB_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" + +namespace leveldb { + +// Update CMakeLists.txt if you change these +static const int kMajorVersion = 1; +static const int kMinorVersion = 22; + +struct Options; +struct ReadOptions; +struct WriteOptions; +class WriteBatch; + +// Abstract handle to particular state of a DB. +// A Snapshot is an immutable object and can therefore be safely +// accessed from multiple threads without any external synchronization. +class LEVELDB_EXPORT Snapshot { + protected: + virtual ~Snapshot(); +}; + +// A range of keys +struct LEVELDB_EXPORT Range { + Range() {} + Range(const Slice& s, const Slice& l) : start(s), limit(l) {} + + Slice start; // Included in the range + Slice limit; // Not included in the range +}; + +// A DB is a persistent ordered map from keys to values. +// A DB is safe for concurrent access from multiple threads without +// any external synchronization. +class LEVELDB_EXPORT DB { + public: + // Open the database with the specified "name". + // Stores a pointer to a heap-allocated database in *dbptr and returns + // OK on success. + // Stores nullptr in *dbptr and returns a non-OK status on error. + // Caller should delete *dbptr when it is no longer needed. + static Status Open(const Options& options, const std::string& name, + DB** dbptr); + + DB() = default; + + DB(const DB&) = delete; + DB& operator=(const DB&) = delete; + + virtual ~DB(); + + // Set the database entry for "key" to "value". Returns OK on success, + // and a non-OK status on error. + // Note: consider setting options.sync = true. + virtual Status Put(const WriteOptions& options, const Slice& key, + const Slice& value) = 0; + + // Remove the database entry (if any) for "key". Returns OK on + // success, and a non-OK status on error. It is not an error if "key" + // did not exist in the database. + // Note: consider setting options.sync = true. + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + + // Apply the specified updates to the database. + // Returns OK on success, non-OK on failure. + // Note: consider setting options.sync = true. + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + + // If the database contains an entry for "key" store the + // corresponding value in *value and return OK. + // + // If there is no entry for "key" leave *value unchanged and return + // a status for which Status::IsNotFound() returns true. + // + // May return some other Status on an error. + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value) = 0; + + // Return a heap-allocated iterator over the contents of the database. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + // + // Caller should delete the iterator when it is no longer needed. + // The returned iterator should be deleted before this db is deleted. + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + + // Return a handle to the current DB state. Iterators created with + // this handle will all observe a stable snapshot of the current DB + // state. The caller must call ReleaseSnapshot(result) when the + // snapshot is no longer needed. + virtual const Snapshot* GetSnapshot() = 0; + + // Release a previously acquired snapshot. The caller must not + // use "snapshot" after this call. + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + + // DB implementations can export properties about their state + // via this method. If "property" is a valid property understood by this + // DB implementation, fills "*value" with its current value and returns + // true. Otherwise returns false. + // + // + // Valid property names include: + // + // "leveldb.num-files-at-level" - return the number of files at level , + // where is an ASCII representation of a level number (e.g. "0"). + // "leveldb.stats" - returns a multi-line string that describes statistics + // about the internal operation of the DB. + // "leveldb.sstables" - returns a multi-line string that describes all + // of the sstables that make up the db contents. + // "leveldb.approximate-memory-usage" - returns the approximate number of + // bytes of memory in use by the DB. + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + + // For each i in [0,n-1], store in "sizes[i]", the approximate + // file system space used by keys in "[range[i].start .. range[i].limit)". + // + // Note that the returned sizes measure file system space usage, so + // if the user data compresses by a factor of ten, the returned + // sizes will be one-tenth the size of the corresponding user data size. + // + // The results may not include the sizes of recently written data. + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + + // Compact the underlying storage for the key range [*begin,*end]. + // In particular, deleted and overwritten versions are discarded, + // and the data is rearranged to reduce the cost of operations + // needed to access the data. This operation should typically only + // be invoked by users who understand the underlying implementation. + // + // begin==nullptr is treated as a key before all keys in the database. + // end==nullptr is treated as a key after all keys in the database. + // Therefore the following call will compact the entire database: + // db->CompactRange(nullptr, nullptr); + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; +}; + +// Destroy the contents of the specified database. +// Be very careful using this method. +// +// Note: For backwards compatibility, if DestroyDB is unable to list the +// database files, Status::OK() will still be returned masking this failure. +LEVELDB_EXPORT Status DestroyDB(const std::string& name, + const Options& options); + +// If a DB cannot be opened, you may attempt to call this method to +// resurrect as much of the contents of the database as possible. +// Some data may be lost, so be careful when calling this function +// on a database that contains important information. +LEVELDB_EXPORT Status RepairDB(const std::string& dbname, + const Options& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/dumpfile.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/dumpfile.h new file mode 100644 index 0000000..a58bc6b --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/dumpfile.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ +#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ + +#include + +#include "leveldb/env.h" +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +// Dump the contents of the file named by fname in text format to +// *dst. Makes a sequence of dst->Append() calls; each call is passed +// the newline-terminated text corresponding to a single item found +// in the file. +// +// Returns a non-OK result if fname does not name a leveldb storage +// file, or if the file cannot be read. +LEVELDB_EXPORT Status DumpFile(Env* env, const std::string& fname, + WritableFile* dst); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/env.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/env.h new file mode 100644 index 0000000..112fe96 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/env.h @@ -0,0 +1,387 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An Env is an interface used by the leveldb implementation to access +// operating system functionality like the filesystem etc. Callers +// may wish to provide a custom Env object when opening a database to +// get fine gain control; e.g., to rate limit file system operations. +// +// All Env implementations are safe for concurrent access from +// multiple threads without any external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ +#define STORAGE_LEVELDB_INCLUDE_ENV_H_ + +#include +#include + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +#if defined(_WIN32) +// The leveldb::Env class below contains a DeleteFile method. +// At the same time, , a fairly popular header +// file for Windows applications, defines a DeleteFile macro. +// +// Without any intervention on our part, the result of this +// unfortunate coincidence is that the name of the +// leveldb::Env::DeleteFile method seen by the compiler depends on +// whether was included before or after the LevelDB +// headers. +// +// To avoid headaches, we undefined DeleteFile (if defined) and +// redefine it at the bottom of this file. This way +// can be included before this file (or not at all) and the +// exported method will always be leveldb::Env::DeleteFile. +#if defined(DeleteFile) +#undef DeleteFile +#define LEVELDB_DELETEFILE_UNDEFINED +#endif // defined(DeleteFile) +#endif // defined(_WIN32) + +namespace leveldb { + +class FileLock; +class Logger; +class RandomAccessFile; +class SequentialFile; +class Slice; +class WritableFile; + +class LEVELDB_EXPORT Env { + public: + Env() = default; + + Env(const Env&) = delete; + Env& operator=(const Env&) = delete; + + virtual ~Env(); + + // Return a default environment suitable for the current operating + // system. Sophisticated users may wish to provide their own Env + // implementation instead of relying on this default environment. + // + // The result of Default() belongs to leveldb and must never be deleted. + static Env* Default(); + + // Create an object that sequentially reads the file with the specified name. + // On success, stores a pointer to the new file in *result and returns OK. + // On failure stores nullptr in *result and returns non-OK. If the file does + // not exist, returns a non-OK status. Implementations should return a + // NotFound status when the file does not exist. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) = 0; + + // Create an object supporting random-access reads from the file with the + // specified name. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. If the file does not exist, returns a non-OK + // status. Implementations should return a NotFound status when the file does + // not exist. + // + // The returned file may be concurrently accessed by multiple threads. + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) = 0; + + // Create an object that writes to a new file with the specified + // name. Deletes any existing file with the same name and creates a + // new file. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) = 0; + + // Create an object that either appends to an existing file, or + // writes to a new file (if the file does not exist to begin with). + // On success, stores a pointer to the new file in *result and + // returns OK. On failure stores nullptr in *result and returns + // non-OK. + // + // The returned file will only be accessed by one thread at a time. + // + // May return an IsNotSupportedError error if this Env does + // not allow appending to an existing file. Users of Env (including + // the leveldb implementation) must be prepared to deal with + // an Env that does not support appending. + virtual Status NewAppendableFile(const std::string& fname, + WritableFile** result); + + // Returns true iff the named file exists. + virtual bool FileExists(const std::string& fname) = 0; + + // Store in *result the names of the children of the specified directory. + // The names are relative to "dir". + // Original contents of *results are dropped. + virtual Status GetChildren(const std::string& dir, + std::vector* result) = 0; + + // Delete the named file. + virtual Status DeleteFile(const std::string& fname) = 0; + + // Create the specified directory. + virtual Status CreateDir(const std::string& dirname) = 0; + + // Delete the specified directory. + virtual Status DeleteDir(const std::string& dirname) = 0; + + // Store the size of fname in *file_size. + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; + + // Rename file src to target. + virtual Status RenameFile(const std::string& src, + const std::string& target) = 0; + + // Lock the specified file. Used to prevent concurrent access to + // the same db by multiple processes. On failure, stores nullptr in + // *lock and returns non-OK. + // + // On success, stores a pointer to the object that represents the + // acquired lock in *lock and returns OK. The caller should call + // UnlockFile(*lock) to release the lock. If the process exits, + // the lock will be automatically released. + // + // If somebody else already holds the lock, finishes immediately + // with a failure. I.e., this call does not wait for existing locks + // to go away. + // + // May create the named file if it does not already exist. + virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; + + // Release the lock acquired by a previous successful call to LockFile. + // REQUIRES: lock was returned by a successful LockFile() call + // REQUIRES: lock has not already been unlocked. + virtual Status UnlockFile(FileLock* lock) = 0; + + // Arrange to run "(*function)(arg)" once in a background thread. + // + // "function" may run in an unspecified thread. Multiple functions + // added to the same Env may run concurrently in different threads. + // I.e., the caller may not assume that background work items are + // serialized. + virtual void Schedule(void (*function)(void* arg), void* arg) = 0; + + // Start a new thread, invoking "function(arg)" within the new thread. + // When "function(arg)" returns, the thread will be destroyed. + virtual void StartThread(void (*function)(void* arg), void* arg) = 0; + + // *path is set to a temporary directory that can be used for testing. It may + // or may not have just been created. The directory may or may not differ + // between runs of the same process, but subsequent calls will return the + // same directory. + virtual Status GetTestDirectory(std::string* path) = 0; + + // Create and return a log file for storing informational messages. + virtual Status NewLogger(const std::string& fname, Logger** result) = 0; + + // Returns the number of micro-seconds since some fixed point in time. Only + // useful for computing deltas of time. + virtual uint64_t NowMicros() = 0; + + // Sleep/delay the thread for the prescribed number of micro-seconds. + virtual void SleepForMicroseconds(int micros) = 0; +}; + +// A file abstraction for reading sequentially through a file +class LEVELDB_EXPORT SequentialFile { + public: + SequentialFile() = default; + + SequentialFile(const SequentialFile&) = delete; + SequentialFile& operator=(const SequentialFile&) = delete; + + virtual ~SequentialFile(); + + // Read up to "n" bytes from the file. "scratch[0..n-1]" may be + // written by this routine. Sets "*result" to the data that was + // read (including if fewer than "n" bytes were successfully read). + // May set "*result" to point at data in "scratch[0..n-1]", so + // "scratch[0..n-1]" must be live when "*result" is used. + // If an error was encountered, returns a non-OK status. + // + // REQUIRES: External synchronization + virtual Status Read(size_t n, Slice* result, char* scratch) = 0; + + // Skip "n" bytes from the file. This is guaranteed to be no + // slower that reading the same data, but may be faster. + // + // If end of file is reached, skipping will stop at the end of the + // file, and Skip will return OK. + // + // REQUIRES: External synchronization + virtual Status Skip(uint64_t n) = 0; +}; + +// A file abstraction for randomly reading the contents of a file. +class LEVELDB_EXPORT RandomAccessFile { + public: + RandomAccessFile() = default; + + RandomAccessFile(const RandomAccessFile&) = delete; + RandomAccessFile& operator=(const RandomAccessFile&) = delete; + + virtual ~RandomAccessFile(); + + // Read up to "n" bytes from the file starting at "offset". + // "scratch[0..n-1]" may be written by this routine. Sets "*result" + // to the data that was read (including if fewer than "n" bytes were + // successfully read). May set "*result" to point at data in + // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when + // "*result" is used. If an error was encountered, returns a non-OK + // status. + // + // Safe for concurrent use by multiple threads. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const = 0; +}; + +// A file abstraction for sequential writing. The implementation +// must provide buffering since callers may append small fragments +// at a time to the file. +class LEVELDB_EXPORT WritableFile { + public: + WritableFile() = default; + + WritableFile(const WritableFile&) = delete; + WritableFile& operator=(const WritableFile&) = delete; + + virtual ~WritableFile(); + + virtual Status Append(const Slice& data) = 0; + virtual Status Close() = 0; + virtual Status Flush() = 0; + virtual Status Sync() = 0; +}; + +// An interface for writing log messages. +class LEVELDB_EXPORT Logger { + public: + Logger() = default; + + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; + + virtual ~Logger(); + + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap) = 0; +}; + +// Identifies a locked file. +class LEVELDB_EXPORT FileLock { + public: + FileLock() = default; + + FileLock(const FileLock&) = delete; + FileLock& operator=(const FileLock&) = delete; + + virtual ~FileLock(); +}; + +// Log the specified data to *info_log if info_log is non-null. +void Log(Logger* info_log, const char* format, ...) +#if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +// A utility routine: write "data" to the named file. +LEVELDB_EXPORT Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname); + +// A utility routine: read contents of named file into *data +LEVELDB_EXPORT Status ReadFileToString(Env* env, const std::string& fname, + std::string* data); + +// An implementation of Env that forwards all calls to another Env. +// May be useful to clients who wish to override just part of the +// functionality of another Env. +class LEVELDB_EXPORT EnvWrapper : public Env { + public: + // Initialize an EnvWrapper that delegates all calls to *t. + explicit EnvWrapper(Env* t) : target_(t) {} + virtual ~EnvWrapper(); + + // Return the target to which this Env forwards all calls. + Env* target() const { return target_; } + + // The following text is boilerplate that forwards all methods to target(). + Status NewSequentialFile(const std::string& f, SequentialFile** r) override { + return target_->NewSequentialFile(f, r); + } + Status NewRandomAccessFile(const std::string& f, + RandomAccessFile** r) override { + return target_->NewRandomAccessFile(f, r); + } + Status NewWritableFile(const std::string& f, WritableFile** r) override { + return target_->NewWritableFile(f, r); + } + Status NewAppendableFile(const std::string& f, WritableFile** r) override { + return target_->NewAppendableFile(f, r); + } + bool FileExists(const std::string& f) override { + return target_->FileExists(f); + } + Status GetChildren(const std::string& dir, + std::vector* r) override { + return target_->GetChildren(dir, r); + } + Status DeleteFile(const std::string& f) override { + return target_->DeleteFile(f); + } + Status CreateDir(const std::string& d) override { + return target_->CreateDir(d); + } + Status DeleteDir(const std::string& d) override { + return target_->DeleteDir(d); + } + Status GetFileSize(const std::string& f, uint64_t* s) override { + return target_->GetFileSize(f, s); + } + Status RenameFile(const std::string& s, const std::string& t) override { + return target_->RenameFile(s, t); + } + Status LockFile(const std::string& f, FileLock** l) override { + return target_->LockFile(f, l); + } + Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); } + void Schedule(void (*f)(void*), void* a) override { + return target_->Schedule(f, a); + } + void StartThread(void (*f)(void*), void* a) override { + return target_->StartThread(f, a); + } + Status GetTestDirectory(std::string* path) override { + return target_->GetTestDirectory(path); + } + Status NewLogger(const std::string& fname, Logger** result) override { + return target_->NewLogger(fname, result); + } + uint64_t NowMicros() override { return target_->NowMicros(); } + void SleepForMicroseconds(int micros) override { + target_->SleepForMicroseconds(micros); + } + + private: + Env* target_; +}; + +} // namespace leveldb + +// Redefine DeleteFile if necessary. +#if defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) +#if defined(UNICODE) +#define DeleteFile DeleteFileW +#else +#define DeleteFile DeleteFileA +#endif // defined(UNICODE) +#endif // defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) + +#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/export.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/export.h new file mode 100644 index 0000000..6ba9b18 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/export.h @@ -0,0 +1,33 @@ +// Copyright (c) 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_EXPORT_H_ +#define STORAGE_LEVELDB_INCLUDE_EXPORT_H_ + +#if !defined(LEVELDB_EXPORT) + +#if defined(LEVELDB_SHARED_LIBRARY) +#if defined(_WIN32) + +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __declspec(dllexport) +#else +#define LEVELDB_EXPORT __declspec(dllimport) +#endif // defined(LEVELDB_COMPILE_LIBRARY) + +#else // defined(_WIN32) +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __attribute__((visibility("default"))) +#else +#define LEVELDB_EXPORT +#endif +#endif // defined(_WIN32) + +#else // defined(LEVELDB_SHARED_LIBRARY) +#define LEVELDB_EXPORT +#endif + +#endif // !defined(LEVELDB_EXPORT) + +#endif // STORAGE_LEVELDB_INCLUDE_EXPORT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/filter_policy.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/filter_policy.h new file mode 100644 index 0000000..49c8eda --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/filter_policy.h @@ -0,0 +1,72 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A database can be configured with a custom FilterPolicy object. +// This object is responsible for creating a small filter from a set +// of keys. These filters are stored in leveldb and are consulted +// automatically by leveldb to decide whether or not to read some +// information from disk. In many cases, a filter can cut down the +// number of disk seeks form a handful to a single disk seek per +// DB::Get() call. +// +// Most people will want to use the builtin bloom filter support (see +// NewBloomFilterPolicy() below). + +#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ +#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT FilterPolicy { + public: + virtual ~FilterPolicy(); + + // Return the name of this policy. Note that if the filter encoding + // changes in an incompatible way, the name returned by this method + // must be changed. Otherwise, old incompatible filters may be + // passed to methods of this type. + virtual const char* Name() const = 0; + + // keys[0,n-1] contains a list of keys (potentially with duplicates) + // that are ordered according to the user supplied comparator. + // Append a filter that summarizes keys[0,n-1] to *dst. + // + // Warning: do not change the initial contents of *dst. Instead, + // append the newly constructed filter to *dst. + virtual void CreateFilter(const Slice* keys, int n, + std::string* dst) const = 0; + + // "filter" contains the data appended by a preceding call to + // CreateFilter() on this class. This method must return true if + // the key was in the list of keys passed to CreateFilter(). + // This method may return true or false if the key was not on the + // list, but it should aim to return false with a high probability. + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; +}; + +// Return a new filter policy that uses a bloom filter with approximately +// the specified number of bits per key. A good value for bits_per_key +// is 10, which yields a filter with ~ 1% false positive rate. +// +// Callers must delete the result after any database that is using the +// result has been closed. +// +// Note: if you are using a custom comparator that ignores some parts +// of the keys being compared, you must not use NewBloomFilterPolicy() +// and must provide your own FilterPolicy that also ignores the +// corresponding parts of the keys. For example, if the comparator +// ignores trailing spaces, it would be incorrect to use a +// FilterPolicy (like NewBloomFilterPolicy) that does not ignore +// trailing spaces in keys. +LEVELDB_EXPORT const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/iterator.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/iterator.h new file mode 100644 index 0000000..bb9a5df --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/iterator.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An iterator yields a sequence of key/value pairs from a source. +// The following class defines the interface. Multiple implementations +// are provided by this library. In particular, iterators are provided +// to access the contents of a Table or a DB. +// +// Multiple threads can invoke const methods on an Iterator without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Iterator must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ + +#include "leveldb/export.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class LEVELDB_EXPORT Iterator { + public: + Iterator(); + + Iterator(const Iterator&) = delete; + Iterator& operator=(const Iterator&) = delete; + + virtual ~Iterator(); + + // An iterator is either positioned at a key/value pair, or + // not valid. This method returns true iff the iterator is valid. + virtual bool Valid() const = 0; + + // Position at the first key in the source. The iterator is Valid() + // after this call iff the source is not empty. + virtual void SeekToFirst() = 0; + + // Position at the last key in the source. The iterator is + // Valid() after this call iff the source is not empty. + virtual void SeekToLast() = 0; + + // Position at the first key in the source that is at or past target. + // The iterator is Valid() after this call iff the source contains + // an entry that comes at or past target. + virtual void Seek(const Slice& target) = 0; + + // Moves to the next entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the last entry in the source. + // REQUIRES: Valid() + virtual void Next() = 0; + + // Moves to the previous entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the first entry in source. + // REQUIRES: Valid() + virtual void Prev() = 0; + + // Return the key for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice key() const = 0; + + // Return the value for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice value() const = 0; + + // If an error has occurred, return it. Else return an ok status. + virtual Status status() const = 0; + + // Clients are allowed to register function/arg1/arg2 triples that + // will be invoked when this iterator is destroyed. + // + // Note that unlike all of the preceding methods, this method is + // not abstract and therefore clients should not override it. + using CleanupFunction = void (*)(void* arg1, void* arg2); + void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); + + private: + // Cleanup functions are stored in a single-linked list. + // The list's head node is inlined in the iterator. + struct CleanupNode { + // True if the node is not used. Only head nodes might be unused. + bool IsEmpty() const { return function == nullptr; } + // Invokes the cleanup function. + void Run() { + assert(function != nullptr); + (*function)(arg1, arg2); + } + + // The head node is used if the function pointer is not null. + CleanupFunction function; + void* arg1; + void* arg2; + CleanupNode* next; + }; + CleanupNode cleanup_head_; +}; + +// Return an empty iterator (yields nothing). +LEVELDB_EXPORT Iterator* NewEmptyIterator(); + +// Return an empty iterator with the specified status. +LEVELDB_EXPORT Iterator* NewErrorIterator(const Status& status); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/options.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/options.h new file mode 100644 index 0000000..b748772 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/options.h @@ -0,0 +1,187 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ +#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Cache; +class Comparator; +class Env; +class FilterPolicy; +class Logger; +class Snapshot; + +// DB contents are stored in a set of blocks, each of which holds a +// sequence of key,value pairs. Each block may be compressed before +// being stored in a file. The following enum describes which +// compression method (if any) is used to compress a block. +enum CompressionType { + // NOTE: do not change the values of existing entries, as these are + // part of the persistent format on disk. + kNoCompression = 0x0, + kSnappyCompression = 0x1 +}; + +// Options to control the behavior of a database (passed to DB::Open) +struct LEVELDB_EXPORT Options { + // Create an Options object with default values for all fields. + Options(); + + // ------------------- + // Parameters that affect behavior + + // Comparator used to define the order of keys in the table. + // Default: a comparator that uses lexicographic byte-wise ordering + // + // REQUIRES: The client must ensure that the comparator supplied + // here has the same name and orders keys *exactly* the same as the + // comparator provided to previous open calls on the same DB. + const Comparator* comparator; + + // If true, the database will be created if it is missing. + bool create_if_missing = false; + + // If true, an error is raised if the database already exists. + bool error_if_exists = false; + + // If true, the implementation will do aggressive checking of the + // data it is processing and will stop early if it detects any + // errors. This may have unforeseen ramifications: for example, a + // corruption of one DB entry may cause a large number of entries to + // become unreadable or for the entire DB to become unopenable. + bool paranoid_checks = false; + + // Use the specified object to interact with the environment, + // e.g. to read/write files, schedule background work, etc. + // Default: Env::Default() + Env* env; + + // Any internal progress/error information generated by the db will + // be written to info_log if it is non-null, or to a file stored + // in the same directory as the DB contents if info_log is null. + Logger* info_log = nullptr; + + // ------------------- + // Parameters that affect performance + + // Amount of data to build up in memory (backed by an unsorted log + // on disk) before converting to a sorted on-disk file. + // + // Larger values increase performance, especially during bulk loads. + // Up to two write buffers may be held in memory at the same time, + // so you may wish to adjust this parameter to control memory usage. + // Also, a larger write buffer will result in a longer recovery time + // the next time the database is opened. + size_t write_buffer_size = 4 * 1024 * 1024; + + // Number of open files that can be used by the DB. You may need to + // increase this if your database has a large working set (budget + // one open file per 2MB of working set). + int max_open_files = 1000; + + // Control over blocks (user data is stored in a set of blocks, and + // a block is the unit of reading from disk). + + // If non-null, use the specified cache for blocks. + // If null, leveldb will automatically create and use an 8MB internal cache. + Cache* block_cache = nullptr; + + // Approximate size of user data packed per block. Note that the + // block size specified here corresponds to uncompressed data. The + // actual size of the unit read from disk may be smaller if + // compression is enabled. This parameter can be changed dynamically. + size_t block_size = 4 * 1024; + + // Number of keys between restart points for delta encoding of keys. + // This parameter can be changed dynamically. Most clients should + // leave this parameter alone. + int block_restart_interval = 16; + + // Leveldb will write up to this amount of bytes to a file before + // switching to a new one. + // Most clients should leave this parameter alone. However if your + // filesystem is more efficient with larger files, you could + // consider increasing the value. The downside will be longer + // compactions and hence longer latency/performance hiccups. + // Another reason to increase this parameter might be when you are + // initially populating a large database. + size_t max_file_size = 2 * 1024 * 1024; + + // Compress blocks using the specified compression algorithm. This + // parameter can be changed dynamically. + // + // Default: kSnappyCompression, which gives lightweight but fast + // compression. + // + // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: + // ~200-500MB/s compression + // ~400-800MB/s decompression + // Note that these speeds are significantly faster than most + // persistent storage speeds, and therefore it is typically never + // worth switching to kNoCompression. Even if the input data is + // incompressible, the kSnappyCompression implementation will + // efficiently detect that and will switch to uncompressed mode. + CompressionType compression = kSnappyCompression; + + // EXPERIMENTAL: If true, append to existing MANIFEST and log files + // when a database is opened. This can significantly speed up open. + // + // Default: currently false, but may become true later. + bool reuse_logs = false; + + // If non-null, use the specified filter policy to reduce disk reads. + // Many applications will benefit from passing the result of + // NewBloomFilterPolicy() here. + const FilterPolicy* filter_policy = nullptr; +}; + +// Options that control read operations +struct LEVELDB_EXPORT ReadOptions { + ReadOptions() = default; + + // If true, all data read from underlying storage will be + // verified against corresponding checksums. + bool verify_checksums = false; + + // Should the data read for this iteration be cached in memory? + // Callers may wish to set this field to false for bulk scans. + bool fill_cache = true; + + // If "snapshot" is non-null, read as of the supplied snapshot + // (which must belong to the DB that is being read and which must + // not have been released). If "snapshot" is null, use an implicit + // snapshot of the state at the beginning of this read operation. + const Snapshot* snapshot = nullptr; +}; + +// Options that control write operations +struct LEVELDB_EXPORT WriteOptions { + WriteOptions() = default; + + // If true, the write will be flushed from the operating system + // buffer cache (by calling WritableFile::Sync()) before the write + // is considered complete. If this flag is true, writes will be + // slower. + // + // If this flag is false, and the machine crashes, some recent + // writes may be lost. Note that if it is just the process that + // crashes (i.e., the machine does not reboot), no writes will be + // lost even if sync==false. + // + // In other words, a DB write with sync==false has similar + // crash semantics as the "write()" system call. A DB write + // with sync==true has similar crash semantics to a "write()" + // system call followed by "fsync()". + bool sync = false; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/slice.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/slice.h new file mode 100644 index 0000000..2df417d --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/slice.h @@ -0,0 +1,115 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ +#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ + +#include +#include +#include + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class LEVELDB_EXPORT Slice { + public: + // Create an empty slice. + Slice() : data_(""), size_(0) {} + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) {} + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) {} + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) {} + + // Intentionally copyable. + Slice(const Slice&) = default; + Slice& operator=(const Slice&) = default; + + // Return a pointer to the beginning of the referenced data + const char* data() const { return data_; } + + // Return the length (in bytes) of the referenced data + size_t size() const { return size_; } + + // Return true iff the length of the referenced data is zero + bool empty() const { return size_ == 0; } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { + data_ = ""; + size_ = 0; + } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString() const { return std::string(data_, size_); } + + // Three-way comparison. Returns value: + // < 0 iff "*this" < "b", + // == 0 iff "*this" == "b", + // > 0 iff "*this" > "b" + int compare(const Slice& b) const; + + // Return true iff "x" is a prefix of "*this" + bool starts_with(const Slice& x) const { + return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0)); + } + + private: + const char* data_; + size_t size_; +}; + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); } + +inline int Slice::compare(const Slice& b) const { + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + if (r == 0) { + if (size_ < b.size_) + r = -1; + else if (size_ > b.size_) + r = +1; + } + return r; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/status.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/status.h new file mode 100644 index 0000000..e327314 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/status.h @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Status encapsulates the result of an operation. It may indicate success, +// or it may indicate an error with an associated error message. +// +// Multiple threads can invoke const methods on a Status without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Status must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Status { + public: + // Create a success status. + Status() noexcept : state_(nullptr) {} + ~Status() { delete[] state_; } + + Status(const Status& rhs); + Status& operator=(const Status& rhs); + + Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; } + Status& operator=(Status&& rhs) noexcept; + + // Return a success status. + static Status OK() { return Status(); } + + // Return error status of an appropriate type. + static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotFound, msg, msg2); + } + static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kCorruption, msg, msg2); + } + static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotSupported, msg, msg2); + } + static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kInvalidArgument, msg, msg2); + } + static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kIOError, msg, msg2); + } + + // Returns true iff the status indicates success. + bool ok() const { return (state_ == nullptr); } + + // Returns true iff the status indicates a NotFound error. + bool IsNotFound() const { return code() == kNotFound; } + + // Returns true iff the status indicates a Corruption error. + bool IsCorruption() const { return code() == kCorruption; } + + // Returns true iff the status indicates an IOError. + bool IsIOError() const { return code() == kIOError; } + + // Returns true iff the status indicates a NotSupportedError. + bool IsNotSupportedError() const { return code() == kNotSupported; } + + // Returns true iff the status indicates an InvalidArgument. + bool IsInvalidArgument() const { return code() == kInvalidArgument; } + + // Return a string representation of this status suitable for printing. + // Returns the string "OK" for success. + std::string ToString() const; + + private: + enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5 + }; + + Code code() const { + return (state_ == nullptr) ? kOk : static_cast(state_[4]); + } + + Status(Code code, const Slice& msg, const Slice& msg2); + static const char* CopyState(const char* s); + + // OK status has a null state_. Otherwise, state_ is a new[] array + // of the following form: + // state_[0..3] == length of message + // state_[4] == code + // state_[5..] == message + const char* state_; +}; + +inline Status::Status(const Status& rhs) { + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); +} +inline Status& Status::operator=(const Status& rhs) { + // The following condition catches both aliasing (when this == &rhs), + // and the common case where both rhs and *this are ok. + if (state_ != rhs.state_) { + delete[] state_; + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); + } + return *this; +} +inline Status& Status::operator=(Status&& rhs) noexcept { + std::swap(state_, rhs.state_); + return *this; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/table.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/table.h new file mode 100644 index 0000000..25c6013 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/table.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +class Block; +class BlockHandle; +class Footer; +struct Options; +class RandomAccessFile; +struct ReadOptions; +class TableCache; + +// A Table is a sorted map from strings to strings. Tables are +// immutable and persistent. A Table may be safely accessed from +// multiple threads without external synchronization. +class LEVELDB_EXPORT Table { + public: + // Attempt to open the table that is stored in bytes [0..file_size) + // of "file", and read the metadata entries necessary to allow + // retrieving data from the table. + // + // If successful, returns ok and sets "*table" to the newly opened + // table. The client should delete "*table" when no longer needed. + // If there was an error while initializing the table, sets "*table" + // to nullptr and returns a non-ok status. Does not take ownership of + // "*source", but the client must ensure that "source" remains live + // for the duration of the returned table's lifetime. + // + // *file must remain live while this Table is in use. + static Status Open(const Options& options, RandomAccessFile* file, + uint64_t file_size, Table** table); + + Table(const Table&) = delete; + Table& operator=(const Table&) = delete; + + ~Table(); + + // Returns a new iterator over the table contents. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + Iterator* NewIterator(const ReadOptions&) const; + + // Given a key, return an approximate byte offset in the file where + // the data for that key begins (or would begin if the key were + // present in the file). The returned value is in terms of file + // bytes, and so includes effects like compression of the underlying data. + // E.g., the approximate offset of the last key in the table will + // be close to the file length. + uint64_t ApproximateOffsetOf(const Slice& key) const; + + private: + friend class TableCache; + struct Rep; + + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); + + explicit Table(Rep* rep) : rep_(rep) {} + + // Calls (*handle_result)(arg, ...) with the entry found after a call + // to Seek(key). May not make such a call if filter policy says + // that key is not present. + Status InternalGet(const ReadOptions&, const Slice& key, void* arg, + void (*handle_result)(void* arg, const Slice& k, + const Slice& v)); + + void ReadMeta(const Footer& footer); + void ReadFilter(const Slice& filter_handle_value); + + Rep* const rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/table_builder.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/table_builder.h new file mode 100644 index 0000000..7d8896b --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/table_builder.h @@ -0,0 +1,93 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// TableBuilder provides the interface used to build a Table +// (an immutable and sorted map from keys to values). +// +// Multiple threads can invoke const methods on a TableBuilder without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same TableBuilder must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/options.h" +#include "leveldb/status.h" + +namespace leveldb { + +class BlockBuilder; +class BlockHandle; +class WritableFile; + +class LEVELDB_EXPORT TableBuilder { + public: + // Create a builder that will store the contents of the table it is + // building in *file. Does not close the file. It is up to the + // caller to close the file after calling Finish(). + TableBuilder(const Options& options, WritableFile* file); + + TableBuilder(const TableBuilder&) = delete; + TableBuilder& operator=(const TableBuilder&) = delete; + + // REQUIRES: Either Finish() or Abandon() has been called. + ~TableBuilder(); + + // Change the options used by this builder. Note: only some of the + // option fields can be changed after construction. If a field is + // not allowed to change dynamically and its value in the structure + // passed to the constructor is different from its value in the + // structure passed to this method, this method will return an error + // without changing any fields. + Status ChangeOptions(const Options& options); + + // Add key,value to the table being constructed. + // REQUIRES: key is after any previously added key according to comparator. + // REQUIRES: Finish(), Abandon() have not been called + void Add(const Slice& key, const Slice& value); + + // Advanced operation: flush any buffered key/value pairs to file. + // Can be used to ensure that two adjacent entries never live in + // the same data block. Most clients should not need to use this method. + // REQUIRES: Finish(), Abandon() have not been called + void Flush(); + + // Return non-ok iff some error has been detected. + Status status() const; + + // Finish building the table. Stops using the file passed to the + // constructor after this function returns. + // REQUIRES: Finish(), Abandon() have not been called + Status Finish(); + + // Indicate that the contents of this builder should be abandoned. Stops + // using the file passed to the constructor after this function returns. + // If the caller is not going to call Finish(), it must call Abandon() + // before destroying this builder. + // REQUIRES: Finish(), Abandon() have not been called + void Abandon(); + + // Number of calls to Add() so far. + uint64_t NumEntries() const; + + // Size of the file generated so far. If invoked after a successful + // Finish() call, returns the size of the final generated file. + uint64_t FileSize() const; + + private: + bool ok() const { return status().ok(); } + void WriteBlock(BlockBuilder* block, BlockHandle* handle); + void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/include/leveldb/write_batch.h b/PediatricPancreas/Pods/leveldb-library/include/leveldb/write_batch.h new file mode 100644 index 0000000..94d4115 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/include/leveldb/write_batch.h @@ -0,0 +1,83 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch holds a collection of updates to apply atomically to a DB. +// +// The updates are applied in the order in which they are added +// to the WriteBatch. For example, the value of "key" will be "v3" +// after the following batch is written: +// +// batch.Put("key", "v1"); +// batch.Delete("key"); +// batch.Put("key", "v2"); +// batch.Put("key", "v3"); +// +// Multiple threads can invoke const methods on a WriteBatch without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same WriteBatch must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT WriteBatch { + public: + class LEVELDB_EXPORT Handler { + public: + virtual ~Handler(); + virtual void Put(const Slice& key, const Slice& value) = 0; + virtual void Delete(const Slice& key) = 0; + }; + + WriteBatch(); + + // Intentionally copyable. + WriteBatch(const WriteBatch&) = default; + WriteBatch& operator=(const WriteBatch&) = default; + + ~WriteBatch(); + + // Store the mapping "key->value" in the database. + void Put(const Slice& key, const Slice& value); + + // If the database contains a mapping for "key", erase it. Else do nothing. + void Delete(const Slice& key); + + // Clear all updates buffered in this batch. + void Clear(); + + // The size of the database changes caused by this batch. + // + // This number is tied to implementation details, and may change across + // releases. It is intended for LevelDB usage metrics. + size_t ApproximateSize() const; + + // Copies the operations in "source" to this batch. + // + // This runs in O(source size) time. However, the constant factor is better + // than calling Iterate() over the source batch with a Handler that replicates + // the operations into this batch. + void Append(const WriteBatch& source); + + // Support for iterating over the contents of a batch. + Status Iterate(Handler* handler) const; + + private: + friend class WriteBatchInternal; + + std::string rep_; // See comment in write_batch.cc for the format of rep_ +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/port/port.h b/PediatricPancreas/Pods/leveldb-library/port/port.h new file mode 100644 index 0000000..4b247f7 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/port/port.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_H_ +#define STORAGE_LEVELDB_PORT_PORT_H_ + +#include + +// Include the appropriate platform specific file below. If you are +// porting to a new platform, see "port_example.h" for documentation +// of what the new port_.h file must provide. +#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS) +#include "port/port_stdcxx.h" +#elif defined(LEVELDB_PLATFORM_CHROMIUM) +#include "port/port_chromium.h" +#endif + +#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/port/port_example.h b/PediatricPancreas/Pods/leveldb-library/port/port_example.h new file mode 100644 index 0000000..1a8fca2 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/port/port_example.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// This file contains the specification, but not the implementations, +// of the types/operations/etc. that should be defined by a platform +// specific port_.h file. Use this file as a reference for +// how to port this package to a new platform. + +#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ +#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +// TODO(jorlow): Many of these belong more in the environment class rather than +// here. We should try moving them and see if it affects perf. + +// The following boolean constant must be true on a little-endian machine +// and false otherwise. +static const bool kLittleEndian = true /* or some other expression */; + +// ------------------ Threading ------------------- + +// A Mutex represents an exclusive lock. +class LOCKABLE Mutex { + public: + Mutex(); + ~Mutex(); + + // Lock the mutex. Waits until other lockers have exited. + // Will deadlock if the mutex is already locked by this thread. + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + + // Unlock the mutex. + // REQUIRES: This mutex was locked by this thread. + void Unlock() UNLOCK_FUNCTION(); + + // Optionally crash if this thread does not hold this mutex. + // The implementation must be fast, especially if NDEBUG is + // defined. The implementation is allowed to skip all checks. + void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + + // Atomically release *mu and block on this condition variable until + // either a call to SignalAll(), or a call to Signal() that picks + // this thread to wakeup. + // REQUIRES: this thread holds *mu + void Wait(); + + // If there are some threads waiting, wake up at least one of them. + void Signal(); + + // Wake up all waiting threads. + void SignallAll(); +}; + +// ------------------ Compression ------------------- + +// Store the snappy compression of "input[0,input_length-1]" in *output. +// Returns false if snappy is not supported by this port. +bool Snappy_Compress(const char* input, size_t input_length, + std::string* output); + +// If input[0,input_length-1] looks like a valid snappy compressed +// buffer, store the size of the uncompressed data in *result and +// return true. Else return false. +bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result); + +// Attempt to snappy uncompress input[0,input_length-1] into *output. +// Returns true if successful, false if the input is invalid lightweight +// compressed data. +// +// REQUIRES: at least the first "n" bytes of output[] must be writable +// where "n" is the result of a successful call to +// Snappy_GetUncompressedLength. +bool Snappy_Uncompress(const char* input_data, size_t input_length, + char* output); + +// ------------------ Miscellaneous ------------------- + +// If heap profiling is not supported, returns false. +// Else repeatedly calls (*func)(arg, data, n) and then returns true. +// The concatenation of all "data[0,n-1]" fragments is the heap profile. +bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); + +// Extend the CRC to include the first n bytes of buf. +// +// Returns zero if the CRC cannot be extended using acceleration, else returns +// the newly extended CRC value (which may also be zero). +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/port/port_stdcxx.h b/PediatricPancreas/Pods/leveldb-library/port/port_stdcxx.h new file mode 100644 index 0000000..e9cb0e5 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/port/port_stdcxx.h @@ -0,0 +1,153 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ +#define STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ + +// port/port_config.h availability is automatically detected via __has_include +// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the +// configuration detection. +#if defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if LEVELDB_HAS_PORT_CONFIG_H +#include "port/port_config.h" +#endif // LEVELDB_HAS_PORT_CONFIG_H + +#elif defined(__has_include) + +#if __has_include("port/port_config.h") +#include "port/port_config.h" +#endif // __has_include("port/port_config.h") + +#endif // defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if HAVE_CRC32C +#include +#endif // HAVE_CRC32C +#if HAVE_SNAPPY +#include +#endif // HAVE_SNAPPY + +#include +#include // NOLINT +#include +#include +#include // NOLINT +#include + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +static const bool kLittleEndian = !LEVELDB_IS_BIG_ENDIAN; + +class CondVar; + +// Thinly wraps std::mutex. +class LOCKABLE Mutex { + public: + Mutex() = default; + ~Mutex() = default; + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); } + void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); } + void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {} + + private: + friend class CondVar; + std::mutex mu_; +}; + +// Thinly wraps std::condition_variable. +class CondVar { + public: + explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); } + ~CondVar() = default; + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Wait() { + std::unique_lock lock(mu_->mu_, std::adopt_lock); + cv_.wait(lock); + lock.release(); + } + void Signal() { cv_.notify_one(); } + void SignalAll() { cv_.notify_all(); } + + private: + std::condition_variable cv_; + Mutex* const mu_; +}; + +inline bool Snappy_Compress(const char* input, size_t length, + std::string* output) { +#if HAVE_SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; +#endif // HAVE_SNAPPY + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#if HAVE_SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)result; + return false; +#endif // HAVE_SNAPPY +} + +inline bool Snappy_Uncompress(const char* input, size_t length, char* output) { +#if HAVE_SNAPPY + return snappy::RawUncompress(input, length, output); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; + return false; +#endif // HAVE_SNAPPY +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + // Silence compiler warnings about unused arguments. + (void)func; + (void)arg; + return false; +} + +inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) { +#if HAVE_CRC32C + return ::crc32c::Extend(crc, reinterpret_cast(buf), size); +#else + // Silence compiler warnings about unused arguments. + (void)crc; + (void)buf; + (void)size; + return 0; +#endif // HAVE_CRC32C +} + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/port/thread_annotations.h b/PediatricPancreas/Pods/leveldb-library/port/thread_annotations.h new file mode 100644 index 0000000..1547df9 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/port/thread_annotations.h @@ -0,0 +1,108 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ +#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ + +// Use Clang's thread safety analysis annotations when available. In other +// environments, the macros receive empty definitions. +// Usage documentation: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + +#if !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#if defined(__clang__) + +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#endif // !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#ifndef GUARDED_BY +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) +#endif + +#ifndef PT_GUARDED_BY +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) +#endif + +#ifndef ACQUIRED_AFTER +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) +#endif + +#ifndef ACQUIRED_BEFORE +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_LOCKS_REQUIRED +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCKS_REQUIRED +#define SHARED_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) +#endif + +#ifndef LOCKS_EXCLUDED +#define LOCKS_EXCLUDED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) +#endif + +#ifndef LOCK_RETURNED +#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) +#endif + +#ifndef LOCKABLE +#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable) +#endif + +#ifndef SCOPED_LOCKABLE +#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) +#endif + +#ifndef EXCLUSIVE_LOCK_FUNCTION +#define EXCLUSIVE_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCK_FUNCTION +#define SHARED_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_TRYLOCK_FUNCTION +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_TRYLOCK_FUNCTION +#define SHARED_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) +#endif + +#ifndef UNLOCK_FUNCTION +#define UNLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) +#endif + +#ifndef NO_THREAD_SAFETY_ANALYSIS +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) +#endif + +#ifndef ASSERT_EXCLUSIVE_LOCK +#define ASSERT_EXCLUSIVE_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) +#endif + +#ifndef ASSERT_SHARED_LOCK +#define ASSERT_SHARED_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) +#endif + +#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/block.cc b/PediatricPancreas/Pods/leveldb-library/table/block.cc new file mode 100644 index 0000000..ad0ee98 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/block.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Decodes the blocks generated by block_builder.cc. + +#include "table/block.h" + +#include +#include + +#include "leveldb/comparator.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +inline uint32_t Block::NumRestarts() const { + assert(size_ >= sizeof(uint32_t)); + return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); +} + +Block::Block(const BlockContents& contents) + : data_(contents.data.data()), + size_(contents.data.size()), + owned_(contents.heap_allocated) { + if (size_ < sizeof(uint32_t)) { + size_ = 0; // Error marker + } else { + size_t max_restarts_allowed = (size_ - sizeof(uint32_t)) / sizeof(uint32_t); + if (NumRestarts() > max_restarts_allowed) { + // The size is too small for NumRestarts() + size_ = 0; + } else { + restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); + } + } +} + +Block::~Block() { + if (owned_) { + delete[] data_; + } +} + +// Helper routine: decode the next block entry starting at "p", +// storing the number of shared key bytes, non_shared key bytes, +// and the length of the value in "*shared", "*non_shared", and +// "*value_length", respectively. Will not dereference past "limit". +// +// If any errors are detected, returns nullptr. Otherwise, returns a +// pointer to the key delta (just past the three decoded values). +static inline const char* DecodeEntry(const char* p, const char* limit, + uint32_t* shared, uint32_t* non_shared, + uint32_t* value_length) { + if (limit - p < 3) return nullptr; + *shared = reinterpret_cast(p)[0]; + *non_shared = reinterpret_cast(p)[1]; + *value_length = reinterpret_cast(p)[2]; + if ((*shared | *non_shared | *value_length) < 128) { + // Fast path: all three values are encoded in one byte each + p += 3; + } else { + if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr; + } + + if (static_cast(limit - p) < (*non_shared + *value_length)) { + return nullptr; + } + return p; +} + +class Block::Iter : public Iterator { + private: + const Comparator* const comparator_; + const char* const data_; // underlying block contents + uint32_t const restarts_; // Offset of restart array (list of fixed32) + uint32_t const num_restarts_; // Number of uint32_t entries in restart array + + // current_ is offset in data_ of current entry. >= restarts_ if !Valid + uint32_t current_; + uint32_t restart_index_; // Index of restart block in which current_ falls + std::string key_; + Slice value_; + Status status_; + + inline int Compare(const Slice& a, const Slice& b) const { + return comparator_->Compare(a, b); + } + + // Return the offset in data_ just past the end of the current entry. + inline uint32_t NextEntryOffset() const { + return (value_.data() + value_.size()) - data_; + } + + uint32_t GetRestartPoint(uint32_t index) { + assert(index < num_restarts_); + return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); + } + + void SeekToRestartPoint(uint32_t index) { + key_.clear(); + restart_index_ = index; + // current_ will be fixed by ParseNextKey(); + + // ParseNextKey() starts at the end of value_, so set value_ accordingly + uint32_t offset = GetRestartPoint(index); + value_ = Slice(data_ + offset, 0); + } + + public: + Iter(const Comparator* comparator, const char* data, uint32_t restarts, + uint32_t num_restarts) + : comparator_(comparator), + data_(data), + restarts_(restarts), + num_restarts_(num_restarts), + current_(restarts_), + restart_index_(num_restarts_) { + assert(num_restarts_ > 0); + } + + virtual bool Valid() const { return current_ < restarts_; } + virtual Status status() const { return status_; } + virtual Slice key() const { + assert(Valid()); + return key_; + } + virtual Slice value() const { + assert(Valid()); + return value_; + } + + virtual void Next() { + assert(Valid()); + ParseNextKey(); + } + + virtual void Prev() { + assert(Valid()); + + // Scan backwards to a restart point before current_ + const uint32_t original = current_; + while (GetRestartPoint(restart_index_) >= original) { + if (restart_index_ == 0) { + // No more entries + current_ = restarts_; + restart_index_ = num_restarts_; + return; + } + restart_index_--; + } + + SeekToRestartPoint(restart_index_); + do { + // Loop until end of current entry hits the start of original entry + } while (ParseNextKey() && NextEntryOffset() < original); + } + + virtual void Seek(const Slice& target) { + // Binary search in restart array to find the last restart point + // with a key < target + uint32_t left = 0; + uint32_t right = num_restarts_ - 1; + while (left < right) { + uint32_t mid = (left + right + 1) / 2; + uint32_t region_offset = GetRestartPoint(mid); + uint32_t shared, non_shared, value_length; + const char* key_ptr = + DecodeEntry(data_ + region_offset, data_ + restarts_, &shared, + &non_shared, &value_length); + if (key_ptr == nullptr || (shared != 0)) { + CorruptionError(); + return; + } + Slice mid_key(key_ptr, non_shared); + if (Compare(mid_key, target) < 0) { + // Key at "mid" is smaller than "target". Therefore all + // blocks before "mid" are uninteresting. + left = mid; + } else { + // Key at "mid" is >= "target". Therefore all blocks at or + // after "mid" are uninteresting. + right = mid - 1; + } + } + + // Linear search (within restart block) for first key >= target + SeekToRestartPoint(left); + while (true) { + if (!ParseNextKey()) { + return; + } + if (Compare(key_, target) >= 0) { + return; + } + } + } + + virtual void SeekToFirst() { + SeekToRestartPoint(0); + ParseNextKey(); + } + + virtual void SeekToLast() { + SeekToRestartPoint(num_restarts_ - 1); + while (ParseNextKey() && NextEntryOffset() < restarts_) { + // Keep skipping + } + } + + private: + void CorruptionError() { + current_ = restarts_; + restart_index_ = num_restarts_; + status_ = Status::Corruption("bad entry in block"); + key_.clear(); + value_.clear(); + } + + bool ParseNextKey() { + current_ = NextEntryOffset(); + const char* p = data_ + current_; + const char* limit = data_ + restarts_; // Restarts come right after data + if (p >= limit) { + // No more entries to return. Mark as invalid. + current_ = restarts_; + restart_index_ = num_restarts_; + return false; + } + + // Decode next entry + uint32_t shared, non_shared, value_length; + p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); + if (p == nullptr || key_.size() < shared) { + CorruptionError(); + return false; + } else { + key_.resize(shared); + key_.append(p, non_shared); + value_ = Slice(p + non_shared, value_length); + while (restart_index_ + 1 < num_restarts_ && + GetRestartPoint(restart_index_ + 1) < current_) { + ++restart_index_; + } + return true; + } + } +}; + +Iterator* Block::NewIterator(const Comparator* comparator) { + if (size_ < sizeof(uint32_t)) { + return NewErrorIterator(Status::Corruption("bad block contents")); + } + const uint32_t num_restarts = NumRestarts(); + if (num_restarts == 0) { + return NewEmptyIterator(); + } else { + return new Iter(comparator, data_, restart_offset_, num_restarts); + } +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/block.h b/PediatricPancreas/Pods/leveldb-library/table/block.h new file mode 100644 index 0000000..c8f1f7b --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/block.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_H_ + +#include +#include + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct BlockContents; +class Comparator; + +class Block { + public: + // Initialize the block with the specified contents. + explicit Block(const BlockContents& contents); + + Block(const Block&) = delete; + Block& operator=(const Block&) = delete; + + ~Block(); + + size_t size() const { return size_; } + Iterator* NewIterator(const Comparator* comparator); + + private: + class Iter; + + uint32_t NumRestarts() const; + + const char* data_; + size_t size_; + uint32_t restart_offset_; // Offset in data_ of restart array + bool owned_; // Block owns data_[] +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/block_builder.cc b/PediatricPancreas/Pods/leveldb-library/table/block_builder.cc new file mode 100644 index 0000000..f7cb1b0 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/block_builder.cc @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// BlockBuilder generates blocks where keys are prefix-compressed: +// +// When we store a key, we drop the prefix shared with the previous +// string. This helps reduce the space requirement significantly. +// Furthermore, once every K keys, we do not apply the prefix +// compression and store the entire key. We call this a "restart +// point". The tail end of the block stores the offsets of all of the +// restart points, and can be used to do a binary search when looking +// for a particular key. Values are stored as-is (without compression) +// immediately following the corresponding key. +// +// An entry for a particular key-value pair has the form: +// shared_bytes: varint32 +// unshared_bytes: varint32 +// value_length: varint32 +// key_delta: char[unshared_bytes] +// value: char[value_length] +// shared_bytes == 0 for restart points. +// +// The trailer of the block has the form: +// restarts: uint32[num_restarts] +// num_restarts: uint32 +// restarts[i] contains the offset within the block of the ith restart point. + +#include "table/block_builder.h" + +#include + +#include + +#include "leveldb/comparator.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" + +namespace leveldb { + +BlockBuilder::BlockBuilder(const Options* options) + : options_(options), restarts_(), counter_(0), finished_(false) { + assert(options->block_restart_interval >= 1); + restarts_.push_back(0); // First restart point is at offset 0 +} + +void BlockBuilder::Reset() { + buffer_.clear(); + restarts_.clear(); + restarts_.push_back(0); // First restart point is at offset 0 + counter_ = 0; + finished_ = false; + last_key_.clear(); +} + +size_t BlockBuilder::CurrentSizeEstimate() const { + return (buffer_.size() + // Raw data buffer + restarts_.size() * sizeof(uint32_t) + // Restart array + sizeof(uint32_t)); // Restart array length +} + +Slice BlockBuilder::Finish() { + // Append restart array + for (size_t i = 0; i < restarts_.size(); i++) { + PutFixed32(&buffer_, restarts_[i]); + } + PutFixed32(&buffer_, restarts_.size()); + finished_ = true; + return Slice(buffer_); +} + +void BlockBuilder::Add(const Slice& key, const Slice& value) { + Slice last_key_piece(last_key_); + assert(!finished_); + assert(counter_ <= options_->block_restart_interval); + assert(buffer_.empty() // No values yet? + || options_->comparator->Compare(key, last_key_piece) > 0); + size_t shared = 0; + if (counter_ < options_->block_restart_interval) { + // See how much sharing to do with previous string + const size_t min_length = std::min(last_key_piece.size(), key.size()); + while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { + shared++; + } + } else { + // Restart compression + restarts_.push_back(buffer_.size()); + counter_ = 0; + } + const size_t non_shared = key.size() - shared; + + // Add "" to buffer_ + PutVarint32(&buffer_, shared); + PutVarint32(&buffer_, non_shared); + PutVarint32(&buffer_, value.size()); + + // Add string delta to buffer_ followed by value + buffer_.append(key.data() + shared, non_shared); + buffer_.append(value.data(), value.size()); + + // Update state + last_key_.resize(shared); + last_key_.append(key.data() + shared, non_shared); + assert(Slice(last_key_) == key); + counter_++; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/block_builder.h b/PediatricPancreas/Pods/leveldb-library/table/block_builder.h new file mode 100644 index 0000000..f91f5e6 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/block_builder.h @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ + +#include + +#include + +#include "leveldb/slice.h" + +namespace leveldb { + +struct Options; + +class BlockBuilder { + public: + explicit BlockBuilder(const Options* options); + + BlockBuilder(const BlockBuilder&) = delete; + BlockBuilder& operator=(const BlockBuilder&) = delete; + + // Reset the contents as if the BlockBuilder was just constructed. + void Reset(); + + // REQUIRES: Finish() has not been called since the last call to Reset(). + // REQUIRES: key is larger than any previously added key + void Add(const Slice& key, const Slice& value); + + // Finish building the block and return a slice that refers to the + // block contents. The returned slice will remain valid for the + // lifetime of this builder or until Reset() is called. + Slice Finish(); + + // Returns an estimate of the current (uncompressed) size of the block + // we are building. + size_t CurrentSizeEstimate() const; + + // Return true iff no entries have been added since the last Reset() + bool empty() const { return buffer_.empty(); } + + private: + const Options* options_; + std::string buffer_; // Destination buffer + std::vector restarts_; // Restart points + int counter_; // Number of entries emitted since restart + bool finished_; // Has Finish() been called? + std::string last_key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/filter_block.cc b/PediatricPancreas/Pods/leveldb-library/table/filter_block.cc new file mode 100644 index 0000000..09ec009 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/filter_block.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" + +namespace leveldb { + +// See doc/table_format.md for an explanation of the filter block format. + +// Generate new filter every 2KB of data +static const size_t kFilterBaseLg = 11; +static const size_t kFilterBase = 1 << kFilterBaseLg; + +FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) + : policy_(policy) {} + +void FilterBlockBuilder::StartBlock(uint64_t block_offset) { + uint64_t filter_index = (block_offset / kFilterBase); + assert(filter_index >= filter_offsets_.size()); + while (filter_index > filter_offsets_.size()) { + GenerateFilter(); + } +} + +void FilterBlockBuilder::AddKey(const Slice& key) { + Slice k = key; + start_.push_back(keys_.size()); + keys_.append(k.data(), k.size()); +} + +Slice FilterBlockBuilder::Finish() { + if (!start_.empty()) { + GenerateFilter(); + } + + // Append array of per-filter offsets + const uint32_t array_offset = result_.size(); + for (size_t i = 0; i < filter_offsets_.size(); i++) { + PutFixed32(&result_, filter_offsets_[i]); + } + + PutFixed32(&result_, array_offset); + result_.push_back(kFilterBaseLg); // Save encoding parameter in result + return Slice(result_); +} + +void FilterBlockBuilder::GenerateFilter() { + const size_t num_keys = start_.size(); + if (num_keys == 0) { + // Fast path if there are no keys for this filter + filter_offsets_.push_back(result_.size()); + return; + } + + // Make list of keys from flattened key structure + start_.push_back(keys_.size()); // Simplify length computation + tmp_keys_.resize(num_keys); + for (size_t i = 0; i < num_keys; i++) { + const char* base = keys_.data() + start_[i]; + size_t length = start_[i + 1] - start_[i]; + tmp_keys_[i] = Slice(base, length); + } + + // Generate filter for current set of keys and append to result_. + filter_offsets_.push_back(result_.size()); + policy_->CreateFilter(&tmp_keys_[0], static_cast(num_keys), &result_); + + tmp_keys_.clear(); + keys_.clear(); + start_.clear(); +} + +FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, + const Slice& contents) + : policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) { + size_t n = contents.size(); + if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array + base_lg_ = contents[n - 1]; + uint32_t last_word = DecodeFixed32(contents.data() + n - 5); + if (last_word > n - 5) return; + data_ = contents.data(); + offset_ = data_ + last_word; + num_ = (n - 5 - last_word) / 4; +} + +bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { + uint64_t index = block_offset >> base_lg_; + if (index < num_) { + uint32_t start = DecodeFixed32(offset_ + index * 4); + uint32_t limit = DecodeFixed32(offset_ + index * 4 + 4); + if (start <= limit && limit <= static_cast(offset_ - data_)) { + Slice filter = Slice(data_ + start, limit - start); + return policy_->KeyMayMatch(key, filter); + } else if (start == limit) { + // Empty filters do not match any keys + return false; + } + } + return true; // Errors are treated as potential matches +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/filter_block.h b/PediatricPancreas/Pods/leveldb-library/table/filter_block.h new file mode 100644 index 0000000..73b5399 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/filter_block.h @@ -0,0 +1,69 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A filter block is stored near the end of a Table file. It contains +// filters (e.g., bloom filters) for all data blocks in the table combined +// into a single filter block. + +#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ + +#include +#include + +#include +#include + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +class FilterPolicy; + +// A FilterBlockBuilder is used to construct all of the filters for a +// particular Table. It generates a single string which is stored as +// a special block in the Table. +// +// The sequence of calls to FilterBlockBuilder must match the regexp: +// (StartBlock AddKey*)* Finish +class FilterBlockBuilder { + public: + explicit FilterBlockBuilder(const FilterPolicy*); + + FilterBlockBuilder(const FilterBlockBuilder&) = delete; + FilterBlockBuilder& operator=(const FilterBlockBuilder&) = delete; + + void StartBlock(uint64_t block_offset); + void AddKey(const Slice& key); + Slice Finish(); + + private: + void GenerateFilter(); + + const FilterPolicy* policy_; + std::string keys_; // Flattened key contents + std::vector start_; // Starting index in keys_ of each key + std::string result_; // Filter data computed so far + std::vector tmp_keys_; // policy_->CreateFilter() argument + std::vector filter_offsets_; +}; + +class FilterBlockReader { + public: + // REQUIRES: "contents" and *policy must stay live while *this is live. + FilterBlockReader(const FilterPolicy* policy, const Slice& contents); + bool KeyMayMatch(uint64_t block_offset, const Slice& key); + + private: + const FilterPolicy* policy_; + const char* data_; // Pointer to filter data (at block-start) + const char* offset_; // Pointer to beginning of offset array (at block-end) + size_t num_; // Number of entries in offset array + size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/format.cc b/PediatricPancreas/Pods/leveldb-library/table/format.cc new file mode 100644 index 0000000..e183977 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/format.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/format.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "table/block.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +void BlockHandle::EncodeTo(std::string* dst) const { + // Sanity check that all fields have been set + assert(offset_ != ~static_cast(0)); + assert(size_ != ~static_cast(0)); + PutVarint64(dst, offset_); + PutVarint64(dst, size_); +} + +Status BlockHandle::DecodeFrom(Slice* input) { + if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) { + return Status::OK(); + } else { + return Status::Corruption("bad block handle"); + } +} + +void Footer::EncodeTo(std::string* dst) const { + const size_t original_size = dst->size(); + metaindex_handle_.EncodeTo(dst); + index_handle_.EncodeTo(dst); + dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding + PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); + PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); + assert(dst->size() == original_size + kEncodedLength); + (void)original_size; // Disable unused variable warning. +} + +Status Footer::DecodeFrom(Slice* input) { + const char* magic_ptr = input->data() + kEncodedLength - 8; + const uint32_t magic_lo = DecodeFixed32(magic_ptr); + const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); + const uint64_t magic = ((static_cast(magic_hi) << 32) | + (static_cast(magic_lo))); + if (magic != kTableMagicNumber) { + return Status::Corruption("not an sstable (bad magic number)"); + } + + Status result = metaindex_handle_.DecodeFrom(input); + if (result.ok()) { + result = index_handle_.DecodeFrom(input); + } + if (result.ok()) { + // We skip over any leftover data (just padding for now) in "input" + const char* end = magic_ptr + 8; + *input = Slice(end, input->data() + input->size() - end); + } + return result; +} + +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result) { + result->data = Slice(); + result->cachable = false; + result->heap_allocated = false; + + // Read the block contents as well as the type/crc footer. + // See table_builder.cc for the code that built this structure. + size_t n = static_cast(handle.size()); + char* buf = new char[n + kBlockTrailerSize]; + Slice contents; + Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); + if (!s.ok()) { + delete[] buf; + return s; + } + if (contents.size() != n + kBlockTrailerSize) { + delete[] buf; + return Status::Corruption("truncated block read"); + } + + // Check the crc of the type and the block contents + const char* data = contents.data(); // Pointer to where Read put the data + if (options.verify_checksums) { + const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); + const uint32_t actual = crc32c::Value(data, n + 1); + if (actual != crc) { + delete[] buf; + s = Status::Corruption("block checksum mismatch"); + return s; + } + } + + switch (data[n]) { + case kNoCompression: + if (data != buf) { + // File implementation gave us pointer to some other data. + // Use it directly under the assumption that it will be live + // while the file is open. + delete[] buf; + result->data = Slice(data, n); + result->heap_allocated = false; + result->cachable = false; // Do not double-cache + } else { + result->data = Slice(buf, n); + result->heap_allocated = true; + result->cachable = true; + } + + // Ok + break; + case kSnappyCompression: { + size_t ulength = 0; + if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { + delete[] buf; + return Status::Corruption("corrupted compressed block contents"); + } + char* ubuf = new char[ulength]; + if (!port::Snappy_Uncompress(data, n, ubuf)) { + delete[] buf; + delete[] ubuf; + return Status::Corruption("corrupted compressed block contents"); + } + delete[] buf; + result->data = Slice(ubuf, ulength); + result->heap_allocated = true; + result->cachable = true; + break; + } + default: + delete[] buf; + return Status::Corruption("bad block type"); + } + + return Status::OK(); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/format.h b/PediatricPancreas/Pods/leveldb-library/table/format.h new file mode 100644 index 0000000..2ad145c --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/format.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ +#define STORAGE_LEVELDB_TABLE_FORMAT_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "leveldb/table_builder.h" + +namespace leveldb { + +class Block; +class RandomAccessFile; +struct ReadOptions; + +// BlockHandle is a pointer to the extent of a file that stores a data +// block or a meta block. +class BlockHandle { + public: + // Maximum encoding length of a BlockHandle + enum { kMaxEncodedLength = 10 + 10 }; + + BlockHandle(); + + // The offset of the block in the file. + uint64_t offset() const { return offset_; } + void set_offset(uint64_t offset) { offset_ = offset; } + + // The size of the stored block + uint64_t size() const { return size_; } + void set_size(uint64_t size) { size_ = size; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + uint64_t offset_; + uint64_t size_; +}; + +// Footer encapsulates the fixed information stored at the tail +// end of every table file. +class Footer { + public: + // Encoded length of a Footer. Note that the serialization of a + // Footer will always occupy exactly this many bytes. It consists + // of two block handles and a magic number. + enum { kEncodedLength = 2 * BlockHandle::kMaxEncodedLength + 8 }; + + Footer() {} + + // The block handle for the metaindex block of the table + const BlockHandle& metaindex_handle() const { return metaindex_handle_; } + void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } + + // The block handle for the index block of the table + const BlockHandle& index_handle() const { return index_handle_; } + void set_index_handle(const BlockHandle& h) { index_handle_ = h; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + BlockHandle metaindex_handle_; + BlockHandle index_handle_; +}; + +// kTableMagicNumber was picked by running +// echo http://code.google.com/p/leveldb/ | sha1sum +// and taking the leading 64 bits. +static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; + +// 1-byte type + 32-bit crc +static const size_t kBlockTrailerSize = 5; + +struct BlockContents { + Slice data; // Actual contents of data + bool cachable; // True iff data can be cached + bool heap_allocated; // True iff caller should delete[] data.data() +}; + +// Read the block identified by "handle" from "file". On failure +// return non-OK. On success fill *result and return OK. +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result); + +// Implementation details follow. Clients should ignore, + +inline BlockHandle::BlockHandle() + : offset_(~static_cast(0)), size_(~static_cast(0)) {} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/iterator.cc b/PediatricPancreas/Pods/leveldb-library/table/iterator.cc new file mode 100644 index 0000000..dfef083 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/iterator.cc @@ -0,0 +1,76 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/iterator.h" + +namespace leveldb { + +Iterator::Iterator() { + cleanup_head_.function = nullptr; + cleanup_head_.next = nullptr; +} + +Iterator::~Iterator() { + if (!cleanup_head_.IsEmpty()) { + cleanup_head_.Run(); + for (CleanupNode* node = cleanup_head_.next; node != nullptr;) { + node->Run(); + CleanupNode* next_node = node->next; + delete node; + node = next_node; + } + } +} + +void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { + assert(func != nullptr); + CleanupNode* node; + if (cleanup_head_.IsEmpty()) { + node = &cleanup_head_; + } else { + node = new CleanupNode(); + node->next = cleanup_head_.next; + cleanup_head_.next = node; + } + node->function = func; + node->arg1 = arg1; + node->arg2 = arg2; +} + +namespace { + +class EmptyIterator : public Iterator { + public: + EmptyIterator(const Status& s) : status_(s) {} + ~EmptyIterator() override = default; + + bool Valid() const override { return false; } + void Seek(const Slice& target) override {} + void SeekToFirst() override {} + void SeekToLast() override {} + void Next() override { assert(false); } + void Prev() override { assert(false); } + Slice key() const override { + assert(false); + return Slice(); + } + Slice value() const override { + assert(false); + return Slice(); + } + Status status() const override { return status_; } + + private: + Status status_; +}; + +} // anonymous namespace + +Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); } + +Iterator* NewErrorIterator(const Status& status) { + return new EmptyIterator(status); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/iterator_wrapper.h b/PediatricPancreas/Pods/leveldb-library/table/iterator_wrapper.h new file mode 100644 index 0000000..c230572 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/iterator_wrapper.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ +#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ + +#include "leveldb/iterator.h" +#include "leveldb/slice.h" + +namespace leveldb { + +// A internal wrapper class with an interface similar to Iterator that +// caches the valid() and key() results for an underlying iterator. +// This can help avoid virtual function calls and also gives better +// cache locality. +class IteratorWrapper { + public: + IteratorWrapper() : iter_(nullptr), valid_(false) {} + explicit IteratorWrapper(Iterator* iter) : iter_(nullptr) { Set(iter); } + ~IteratorWrapper() { delete iter_; } + Iterator* iter() const { return iter_; } + + // Takes ownership of "iter" and will delete it when destroyed, or + // when Set() is invoked again. + void Set(Iterator* iter) { + delete iter_; + iter_ = iter; + if (iter_ == nullptr) { + valid_ = false; + } else { + Update(); + } + } + + // Iterator interface methods + bool Valid() const { return valid_; } + Slice key() const { + assert(Valid()); + return key_; + } + Slice value() const { + assert(Valid()); + return iter_->value(); + } + // Methods below require iter() != nullptr + Status status() const { + assert(iter_); + return iter_->status(); + } + void Next() { + assert(iter_); + iter_->Next(); + Update(); + } + void Prev() { + assert(iter_); + iter_->Prev(); + Update(); + } + void Seek(const Slice& k) { + assert(iter_); + iter_->Seek(k); + Update(); + } + void SeekToFirst() { + assert(iter_); + iter_->SeekToFirst(); + Update(); + } + void SeekToLast() { + assert(iter_); + iter_->SeekToLast(); + Update(); + } + + private: + void Update() { + valid_ = iter_->Valid(); + if (valid_) { + key_ = iter_->key(); + } + } + + Iterator* iter_; + bool valid_; + Slice key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/merger.cc b/PediatricPancreas/Pods/leveldb-library/table/merger.cc new file mode 100644 index 0000000..1bbc6cf --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/merger.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/merger.h" + +#include "leveldb/comparator.h" +#include "leveldb/iterator.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { +class MergingIterator : public Iterator { + public: + MergingIterator(const Comparator* comparator, Iterator** children, int n) + : comparator_(comparator), + children_(new IteratorWrapper[n]), + n_(n), + current_(nullptr), + direction_(kForward) { + for (int i = 0; i < n; i++) { + children_[i].Set(children[i]); + } + } + + virtual ~MergingIterator() { delete[] children_; } + + virtual bool Valid() const { return (current_ != nullptr); } + + virtual void SeekToFirst() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToFirst(); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void SeekToLast() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToLast(); + } + FindLargest(); + direction_ = kReverse; + } + + virtual void Seek(const Slice& target) { + for (int i = 0; i < n_; i++) { + children_[i].Seek(target); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void Next() { + assert(Valid()); + + // Ensure that all children are positioned after key(). + // If we are moving in the forward direction, it is already + // true for all of the non-current_ children since current_ is + // the smallest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kForward) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid() && + comparator_->Compare(key(), child->key()) == 0) { + child->Next(); + } + } + } + direction_ = kForward; + } + + current_->Next(); + FindSmallest(); + } + + virtual void Prev() { + assert(Valid()); + + // Ensure that all children are positioned before key(). + // If we are moving in the reverse direction, it is already + // true for all of the non-current_ children since current_ is + // the largest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kReverse) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid()) { + // Child is at first entry >= key(). Step back one to be < key() + child->Prev(); + } else { + // Child has no entries >= key(). Position at last entry. + child->SeekToLast(); + } + } + } + direction_ = kReverse; + } + + current_->Prev(); + FindLargest(); + } + + virtual Slice key() const { + assert(Valid()); + return current_->key(); + } + + virtual Slice value() const { + assert(Valid()); + return current_->value(); + } + + virtual Status status() const { + Status status; + for (int i = 0; i < n_; i++) { + status = children_[i].status(); + if (!status.ok()) { + break; + } + } + return status; + } + + private: + // Which direction is the iterator moving? + enum Direction { kForward, kReverse }; + + void FindSmallest(); + void FindLargest(); + + // We might want to use a heap in case there are lots of children. + // For now we use a simple array since we expect a very small number + // of children in leveldb. + const Comparator* comparator_; + IteratorWrapper* children_; + int n_; + IteratorWrapper* current_; + Direction direction_; +}; + +void MergingIterator::FindSmallest() { + IteratorWrapper* smallest = nullptr; + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (smallest == nullptr) { + smallest = child; + } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { + smallest = child; + } + } + } + current_ = smallest; +} + +void MergingIterator::FindLargest() { + IteratorWrapper* largest = nullptr; + for (int i = n_ - 1; i >= 0; i--) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (largest == nullptr) { + largest = child; + } else if (comparator_->Compare(child->key(), largest->key()) > 0) { + largest = child; + } + } + } + current_ = largest; +} +} // namespace + +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n) { + assert(n >= 0); + if (n == 0) { + return NewEmptyIterator(); + } else if (n == 1) { + return children[0]; + } else { + return new MergingIterator(comparator, children, n); + } +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/merger.h b/PediatricPancreas/Pods/leveldb-library/table/merger.h new file mode 100644 index 0000000..41cedc5 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/merger.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ +#define STORAGE_LEVELDB_TABLE_MERGER_H_ + +namespace leveldb { + +class Comparator; +class Iterator; + +// Return an iterator that provided the union of the data in +// children[0,n-1]. Takes ownership of the child iterators and +// will delete them when the result iterator is deleted. +// +// The result does no duplicate suppression. I.e., if a particular +// key is present in K child iterators, it will be yielded K times. +// +// REQUIRES: n >= 0 +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/table/table.cc b/PediatricPancreas/Pods/leveldb-library/table/table.cc new file mode 100644 index 0000000..b07bc88 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/table.cc @@ -0,0 +1,273 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" + +namespace leveldb { + +struct Table::Rep { + ~Rep() { + delete filter; + delete[] filter_data; + delete index_block; + } + + Options options; + Status status; + RandomAccessFile* file; + uint64_t cache_id; + FilterBlockReader* filter; + const char* filter_data; + + BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer + Block* index_block; +}; + +Status Table::Open(const Options& options, RandomAccessFile* file, + uint64_t size, Table** table) { + *table = nullptr; + if (size < Footer::kEncodedLength) { + return Status::Corruption("file is too short to be an sstable"); + } + + char footer_space[Footer::kEncodedLength]; + Slice footer_input; + Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, + &footer_input, footer_space); + if (!s.ok()) return s; + + Footer footer; + s = footer.DecodeFrom(&footer_input); + if (!s.ok()) return s; + + // Read the index block + BlockContents index_block_contents; + if (s.ok()) { + ReadOptions opt; + if (options.paranoid_checks) { + opt.verify_checksums = true; + } + s = ReadBlock(file, opt, footer.index_handle(), &index_block_contents); + } + + if (s.ok()) { + // We've successfully read the footer and the index block: we're + // ready to serve requests. + Block* index_block = new Block(index_block_contents); + Rep* rep = new Table::Rep; + rep->options = options; + rep->file = file; + rep->metaindex_handle = footer.metaindex_handle(); + rep->index_block = index_block; + rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0); + rep->filter_data = nullptr; + rep->filter = nullptr; + *table = new Table(rep); + (*table)->ReadMeta(footer); + } + + return s; +} + +void Table::ReadMeta(const Footer& footer) { + if (rep_->options.filter_policy == nullptr) { + return; // Do not need any metadata + } + + // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates + // it is an empty block. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents contents; + if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) { + // Do not propagate errors since meta info is not needed for operation + return; + } + Block* meta = new Block(contents); + + Iterator* iter = meta->NewIterator(BytewiseComparator()); + std::string key = "filter."; + key.append(rep_->options.filter_policy->Name()); + iter->Seek(key); + if (iter->Valid() && iter->key() == Slice(key)) { + ReadFilter(iter->value()); + } + delete iter; + delete meta; +} + +void Table::ReadFilter(const Slice& filter_handle_value) { + Slice v = filter_handle_value; + BlockHandle filter_handle; + if (!filter_handle.DecodeFrom(&v).ok()) { + return; + } + + // We might want to unify with ReadBlock() if we start + // requiring checksum verification in Table::Open. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents block; + if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) { + return; + } + if (block.heap_allocated) { + rep_->filter_data = block.data.data(); // Will need to delete later + } + rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); +} + +Table::~Table() { delete rep_; } + +static void DeleteBlock(void* arg, void* ignored) { + delete reinterpret_cast(arg); +} + +static void DeleteCachedBlock(const Slice& key, void* value) { + Block* block = reinterpret_cast(value); + delete block; +} + +static void ReleaseBlock(void* arg, void* h) { + Cache* cache = reinterpret_cast(arg); + Cache::Handle* handle = reinterpret_cast(h); + cache->Release(handle); +} + +// Convert an index iterator value (i.e., an encoded BlockHandle) +// into an iterator over the contents of the corresponding block. +Iterator* Table::BlockReader(void* arg, const ReadOptions& options, + const Slice& index_value) { + Table* table = reinterpret_cast(arg); + Cache* block_cache = table->rep_->options.block_cache; + Block* block = nullptr; + Cache::Handle* cache_handle = nullptr; + + BlockHandle handle; + Slice input = index_value; + Status s = handle.DecodeFrom(&input); + // We intentionally allow extra stuff in index_value so that we + // can add more features in the future. + + if (s.ok()) { + BlockContents contents; + if (block_cache != nullptr) { + char cache_key_buffer[16]; + EncodeFixed64(cache_key_buffer, table->rep_->cache_id); + EncodeFixed64(cache_key_buffer + 8, handle.offset()); + Slice key(cache_key_buffer, sizeof(cache_key_buffer)); + cache_handle = block_cache->Lookup(key); + if (cache_handle != nullptr) { + block = reinterpret_cast(block_cache->Value(cache_handle)); + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + if (contents.cachable && options.fill_cache) { + cache_handle = block_cache->Insert(key, block, block->size(), + &DeleteCachedBlock); + } + } + } + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + } + } + } + + Iterator* iter; + if (block != nullptr) { + iter = block->NewIterator(table->rep_->options.comparator); + if (cache_handle == nullptr) { + iter->RegisterCleanup(&DeleteBlock, block, nullptr); + } else { + iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); + } + } else { + iter = NewErrorIterator(s); + } + return iter; +} + +Iterator* Table::NewIterator(const ReadOptions& options) const { + return NewTwoLevelIterator( + rep_->index_block->NewIterator(rep_->options.comparator), + &Table::BlockReader, const_cast(this), options); +} + +Status Table::InternalGet(const ReadOptions& options, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Status s; + Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); + iiter->Seek(k); + if (iiter->Valid()) { + Slice handle_value = iiter->value(); + FilterBlockReader* filter = rep_->filter; + BlockHandle handle; + if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() && + !filter->KeyMayMatch(handle.offset(), k)) { + // Not found + } else { + Iterator* block_iter = BlockReader(this, options, iiter->value()); + block_iter->Seek(k); + if (block_iter->Valid()) { + (*handle_result)(arg, block_iter->key(), block_iter->value()); + } + s = block_iter->status(); + delete block_iter; + } + } + if (s.ok()) { + s = iiter->status(); + } + delete iiter; + return s; +} + +uint64_t Table::ApproximateOffsetOf(const Slice& key) const { + Iterator* index_iter = + rep_->index_block->NewIterator(rep_->options.comparator); + index_iter->Seek(key); + uint64_t result; + if (index_iter->Valid()) { + BlockHandle handle; + Slice input = index_iter->value(); + Status s = handle.DecodeFrom(&input); + if (s.ok()) { + result = handle.offset(); + } else { + // Strange: we can't decode the block handle in the index block. + // We'll just return the offset of the metaindex block, which is + // close to the whole file size for this case. + result = rep_->metaindex_handle.offset(); + } + } else { + // key is past the last key in the file. Approximate the offset + // by returning the offset of the metaindex block (which is + // right near the end of the file). + result = rep_->metaindex_handle.offset(); + } + delete index_iter; + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/table_builder.cc b/PediatricPancreas/Pods/leveldb-library/table/table_builder.cc new file mode 100644 index 0000000..278febf --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/table_builder.cc @@ -0,0 +1,265 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table_builder.h" + +#include + +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block_builder.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +struct TableBuilder::Rep { + Rep(const Options& opt, WritableFile* f) + : options(opt), + index_block_options(opt), + file(f), + offset(0), + data_block(&options), + index_block(&index_block_options), + num_entries(0), + closed(false), + filter_block(opt.filter_policy == nullptr + ? nullptr + : new FilterBlockBuilder(opt.filter_policy)), + pending_index_entry(false) { + index_block_options.block_restart_interval = 1; + } + + Options options; + Options index_block_options; + WritableFile* file; + uint64_t offset; + Status status; + BlockBuilder data_block; + BlockBuilder index_block; + std::string last_key; + int64_t num_entries; + bool closed; // Either Finish() or Abandon() has been called. + FilterBlockBuilder* filter_block; + + // We do not emit the index entry for a block until we have seen the + // first key for the next data block. This allows us to use shorter + // keys in the index block. For example, consider a block boundary + // between the keys "the quick brown fox" and "the who". We can use + // "the r" as the key for the index block entry since it is >= all + // entries in the first block and < all entries in subsequent + // blocks. + // + // Invariant: r->pending_index_entry is true only if data_block is empty. + bool pending_index_entry; + BlockHandle pending_handle; // Handle to add to index block + + std::string compressed_output; +}; + +TableBuilder::TableBuilder(const Options& options, WritableFile* file) + : rep_(new Rep(options, file)) { + if (rep_->filter_block != nullptr) { + rep_->filter_block->StartBlock(0); + } +} + +TableBuilder::~TableBuilder() { + assert(rep_->closed); // Catch errors where caller forgot to call Finish() + delete rep_->filter_block; + delete rep_; +} + +Status TableBuilder::ChangeOptions(const Options& options) { + // Note: if more fields are added to Options, update + // this function to catch changes that should not be allowed to + // change in the middle of building a Table. + if (options.comparator != rep_->options.comparator) { + return Status::InvalidArgument("changing comparator while building table"); + } + + // Note that any live BlockBuilders point to rep_->options and therefore + // will automatically pick up the updated options. + rep_->options = options; + rep_->index_block_options = options; + rep_->index_block_options.block_restart_interval = 1; + return Status::OK(); +} + +void TableBuilder::Add(const Slice& key, const Slice& value) { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->num_entries > 0) { + assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); + } + + if (r->pending_index_entry) { + assert(r->data_block.empty()); + r->options.comparator->FindShortestSeparator(&r->last_key, key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + + if (r->filter_block != nullptr) { + r->filter_block->AddKey(key); + } + + r->last_key.assign(key.data(), key.size()); + r->num_entries++; + r->data_block.Add(key, value); + + const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); + if (estimated_block_size >= r->options.block_size) { + Flush(); + } +} + +void TableBuilder::Flush() { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->data_block.empty()) return; + assert(!r->pending_index_entry); + WriteBlock(&r->data_block, &r->pending_handle); + if (ok()) { + r->pending_index_entry = true; + r->status = r->file->Flush(); + } + if (r->filter_block != nullptr) { + r->filter_block->StartBlock(r->offset); + } +} + +void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { + // File format contains a sequence of blocks where each block has: + // block_data: uint8[n] + // type: uint8 + // crc: uint32 + assert(ok()); + Rep* r = rep_; + Slice raw = block->Finish(); + + Slice block_contents; + CompressionType type = r->options.compression; + // TODO(postrelease): Support more compression options: zlib? + switch (type) { + case kNoCompression: + block_contents = raw; + break; + + case kSnappyCompression: { + std::string* compressed = &r->compressed_output; + if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && + compressed->size() < raw.size() - (raw.size() / 8u)) { + block_contents = *compressed; + } else { + // Snappy not supported, or compressed less than 12.5%, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + } + WriteRawBlock(block_contents, type, handle); + r->compressed_output.clear(); + block->Reset(); +} + +void TableBuilder::WriteRawBlock(const Slice& block_contents, + CompressionType type, BlockHandle* handle) { + Rep* r = rep_; + handle->set_offset(r->offset); + handle->set_size(block_contents.size()); + r->status = r->file->Append(block_contents); + if (r->status.ok()) { + char trailer[kBlockTrailerSize]; + trailer[0] = type; + uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); + crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type + EncodeFixed32(trailer + 1, crc32c::Mask(crc)); + r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); + if (r->status.ok()) { + r->offset += block_contents.size() + kBlockTrailerSize; + } + } +} + +Status TableBuilder::status() const { return rep_->status; } + +Status TableBuilder::Finish() { + Rep* r = rep_; + Flush(); + assert(!r->closed); + r->closed = true; + + BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; + + // Write filter block + if (ok() && r->filter_block != nullptr) { + WriteRawBlock(r->filter_block->Finish(), kNoCompression, + &filter_block_handle); + } + + // Write metaindex block + if (ok()) { + BlockBuilder meta_index_block(&r->options); + if (r->filter_block != nullptr) { + // Add mapping from "filter.Name" to location of filter data + std::string key = "filter."; + key.append(r->options.filter_policy->Name()); + std::string handle_encoding; + filter_block_handle.EncodeTo(&handle_encoding); + meta_index_block.Add(key, handle_encoding); + } + + // TODO(postrelease): Add stats and other meta blocks + WriteBlock(&meta_index_block, &metaindex_block_handle); + } + + // Write index block + if (ok()) { + if (r->pending_index_entry) { + r->options.comparator->FindShortSuccessor(&r->last_key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + WriteBlock(&r->index_block, &index_block_handle); + } + + // Write footer + if (ok()) { + Footer footer; + footer.set_metaindex_handle(metaindex_block_handle); + footer.set_index_handle(index_block_handle); + std::string footer_encoding; + footer.EncodeTo(&footer_encoding); + r->status = r->file->Append(footer_encoding); + if (r->status.ok()) { + r->offset += footer_encoding.size(); + } + } + return r->status; +} + +void TableBuilder::Abandon() { + Rep* r = rep_; + assert(!r->closed); + r->closed = true; +} + +uint64_t TableBuilder::NumEntries() const { return rep_->num_entries; } + +uint64_t TableBuilder::FileSize() const { return rep_->offset; } + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.cc b/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.cc new file mode 100644 index 0000000..5340a4d --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.cc @@ -0,0 +1,171 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/two_level_iterator.h" + +#include "leveldb/table.h" +#include "table/block.h" +#include "table/format.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); + +class TwoLevelIterator : public Iterator { + public: + TwoLevelIterator(Iterator* index_iter, BlockFunction block_function, + void* arg, const ReadOptions& options); + + virtual ~TwoLevelIterator(); + + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + virtual void Next(); + virtual void Prev(); + + virtual bool Valid() const { return data_iter_.Valid(); } + virtual Slice key() const { + assert(Valid()); + return data_iter_.key(); + } + virtual Slice value() const { + assert(Valid()); + return data_iter_.value(); + } + virtual Status status() const { + // It'd be nice if status() returned a const Status& instead of a Status + if (!index_iter_.status().ok()) { + return index_iter_.status(); + } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) { + return data_iter_.status(); + } else { + return status_; + } + } + + private: + void SaveError(const Status& s) { + if (status_.ok() && !s.ok()) status_ = s; + } + void SkipEmptyDataBlocksForward(); + void SkipEmptyDataBlocksBackward(); + void SetDataIterator(Iterator* data_iter); + void InitDataBlock(); + + BlockFunction block_function_; + void* arg_; + const ReadOptions options_; + Status status_; + IteratorWrapper index_iter_; + IteratorWrapper data_iter_; // May be nullptr + // If data_iter_ is non-null, then "data_block_handle_" holds the + // "index_value" passed to block_function_ to create the data_iter_. + std::string data_block_handle_; +}; + +TwoLevelIterator::TwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) + : block_function_(block_function), + arg_(arg), + options_(options), + index_iter_(index_iter), + data_iter_(nullptr) {} + +TwoLevelIterator::~TwoLevelIterator() {} + +void TwoLevelIterator::Seek(const Slice& target) { + index_iter_.Seek(target); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.Seek(target); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToFirst() { + index_iter_.SeekToFirst(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToLast() { + index_iter_.SeekToLast(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::Next() { + assert(Valid()); + data_iter_.Next(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::Prev() { + assert(Valid()); + data_iter_.Prev(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::SkipEmptyDataBlocksForward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Next(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + } +} + +void TwoLevelIterator::SkipEmptyDataBlocksBackward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Prev(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + } +} + +void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { + if (data_iter_.iter() != nullptr) SaveError(data_iter_.status()); + data_iter_.Set(data_iter); +} + +void TwoLevelIterator::InitDataBlock() { + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + } else { + Slice handle = index_iter_.value(); + if (data_iter_.iter() != nullptr && + handle.compare(data_block_handle_) == 0) { + // data_iter_ is already constructed with this iterator, so + // no need to change anything + } else { + Iterator* iter = (*block_function_)(arg_, options_, handle); + data_block_handle_.assign(handle.data(), handle.size()); + SetDataIterator(iter); + } + } +} + +} // namespace + +Iterator* NewTwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) { + return new TwoLevelIterator(index_iter, block_function, arg, options); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.h b/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.h new file mode 100644 index 0000000..81ffe80 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/table/two_level_iterator.h @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ +#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct ReadOptions; + +// Return a new two level iterator. A two-level iterator contains an +// index iterator whose values point to a sequence of blocks where +// each block is itself a sequence of key,value pairs. The returned +// two-level iterator yields the concatenation of all key/value pairs +// in the sequence of blocks. Takes ownership of "index_iter" and +// will delete it when no longer needed. +// +// Uses a supplied function to convert an index_iter value into +// an iterator over the contents of the corresponding block. +Iterator* NewTwoLevelIterator( + Iterator* index_iter, + Iterator* (*block_function)(void* arg, const ReadOptions& options, + const Slice& index_value), + void* arg, const ReadOptions& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/arena.cc b/PediatricPancreas/Pods/leveldb-library/util/arena.cc new file mode 100644 index 0000000..46e3b2e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/arena.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" + +namespace leveldb { + +static const int kBlockSize = 4096; + +Arena::Arena() + : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {} + +Arena::~Arena() { + for (size_t i = 0; i < blocks_.size(); i++) { + delete[] blocks_[i]; + } +} + +char* Arena::AllocateFallback(size_t bytes) { + if (bytes > kBlockSize / 4) { + // Object is more than a quarter of our block size. Allocate it separately + // to avoid wasting too much space in leftover bytes. + char* result = AllocateNewBlock(bytes); + return result; + } + + // We waste the remaining space in the current block. + alloc_ptr_ = AllocateNewBlock(kBlockSize); + alloc_bytes_remaining_ = kBlockSize; + + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; +} + +char* Arena::AllocateAligned(size_t bytes) { + const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; + static_assert((align & (align - 1)) == 0, + "Pointer size should be a power of 2"); + size_t current_mod = reinterpret_cast(alloc_ptr_) & (align - 1); + size_t slop = (current_mod == 0 ? 0 : align - current_mod); + size_t needed = bytes + slop; + char* result; + if (needed <= alloc_bytes_remaining_) { + result = alloc_ptr_ + slop; + alloc_ptr_ += needed; + alloc_bytes_remaining_ -= needed; + } else { + // AllocateFallback always returned aligned memory + result = AllocateFallback(bytes); + } + assert((reinterpret_cast(result) & (align - 1)) == 0); + return result; +} + +char* Arena::AllocateNewBlock(size_t block_bytes) { + char* result = new char[block_bytes]; + blocks_.push_back(result); + memory_usage_.fetch_add(block_bytes + sizeof(char*), + std::memory_order_relaxed); + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/arena.h b/PediatricPancreas/Pods/leveldb-library/util/arena.h new file mode 100644 index 0000000..68fc55d --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/arena.h @@ -0,0 +1,71 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ +#define STORAGE_LEVELDB_UTIL_ARENA_H_ + +#include +#include +#include +#include +#include + +namespace leveldb { + +class Arena { + public: + Arena(); + + Arena(const Arena&) = delete; + Arena& operator=(const Arena&) = delete; + + ~Arena(); + + // Return a pointer to a newly allocated memory block of "bytes" bytes. + char* Allocate(size_t bytes); + + // Allocate memory with the normal alignment guarantees provided by malloc. + char* AllocateAligned(size_t bytes); + + // Returns an estimate of the total memory usage of data allocated + // by the arena. + size_t MemoryUsage() const { + return memory_usage_.load(std::memory_order_relaxed); + } + + private: + char* AllocateFallback(size_t bytes); + char* AllocateNewBlock(size_t block_bytes); + + // Allocation state + char* alloc_ptr_; + size_t alloc_bytes_remaining_; + + // Array of new[] allocated memory blocks + std::vector blocks_; + + // Total memory usage of the arena. + // + // TODO(costan): This member is accessed via atomics, but the others are + // accessed without any locking. Is this OK? + std::atomic memory_usage_; +}; + +inline char* Arena::Allocate(size_t bytes) { + // The semantics of what to return are a bit messy if we allow + // 0-byte allocations, so we disallow them here (we don't need + // them for our internal use). + assert(bytes > 0); + if (bytes <= alloc_bytes_remaining_) { + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; + } + return AllocateFallback(bytes); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/bloom.cc b/PediatricPancreas/Pods/leveldb-library/util/bloom.cc new file mode 100644 index 0000000..7f97464 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/bloom.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +namespace { +static uint32_t BloomHash(const Slice& key) { + return Hash(key.data(), key.size(), 0xbc9f1d34); +} + +class BloomFilterPolicy : public FilterPolicy { + public: + explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) { + // We intentionally round down to reduce probing cost a little bit + k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2) + if (k_ < 1) k_ = 1; + if (k_ > 30) k_ = 30; + } + + virtual const char* Name() const { return "leveldb.BuiltinBloomFilter2"; } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Compute bloom filter size (in both bits and bytes) + size_t bits = n * bits_per_key_; + + // For small n, we can see a very high false positive rate. Fix it + // by enforcing a minimum bloom filter length. + if (bits < 64) bits = 64; + + size_t bytes = (bits + 7) / 8; + bits = bytes * 8; + + const size_t init_size = dst->size(); + dst->resize(init_size + bytes, 0); + dst->push_back(static_cast(k_)); // Remember # of probes in filter + char* array = &(*dst)[init_size]; + for (int i = 0; i < n; i++) { + // Use double-hashing to generate a sequence of hash values. + // See analysis in [Kirsch,Mitzenmacher 2006]. + uint32_t h = BloomHash(keys[i]); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k_; j++) { + const uint32_t bitpos = h % bits; + array[bitpos / 8] |= (1 << (bitpos % 8)); + h += delta; + } + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { + const size_t len = bloom_filter.size(); + if (len < 2) return false; + + const char* array = bloom_filter.data(); + const size_t bits = (len - 1) * 8; + + // Use the encoded k so that we can read filters generated by + // bloom filters created using different parameters. + const size_t k = array[len - 1]; + if (k > 30) { + // Reserved for potentially new encodings for short bloom filters. + // Consider it a match. + return true; + } + + uint32_t h = BloomHash(key); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k; j++) { + const uint32_t bitpos = h % bits; + if ((array[bitpos / 8] & (1 << (bitpos % 8))) == 0) return false; + h += delta; + } + return true; + } + + private: + size_t bits_per_key_; + size_t k_; +}; +} // namespace + +const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { + return new BloomFilterPolicy(bits_per_key); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/cache.cc b/PediatricPancreas/Pods/leveldb-library/util/cache.cc new file mode 100644 index 0000000..0f801cc --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/cache.cc @@ -0,0 +1,400 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/cache.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/hash.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Cache::~Cache() {} + +namespace { + +// LRU cache implementation +// +// Cache entries have an "in_cache" boolean indicating whether the cache has a +// reference on the entry. The only ways that this can become false without the +// entry being passed to its "deleter" are via Erase(), via Insert() when +// an element with a duplicate key is inserted, or on destruction of the cache. +// +// The cache keeps two linked lists of items in the cache. All items in the +// cache are in one list or the other, and never both. Items still referenced +// by clients but erased from the cache are in neither list. The lists are: +// - in-use: contains the items currently referenced by clients, in no +// particular order. (This list is used for invariant checking. If we +// removed the check, elements that would otherwise be on this list could be +// left as disconnected singleton lists.) +// - LRU: contains the items not currently referenced by clients, in LRU order +// Elements are moved between these lists by the Ref() and Unref() methods, +// when they detect an element in the cache acquiring or losing its only +// external reference. + +// An entry is a variable length heap-allocated structure. Entries +// are kept in a circular doubly linked list ordered by access time. +struct LRUHandle { + void* value; + void (*deleter)(const Slice&, void* value); + LRUHandle* next_hash; + LRUHandle* next; + LRUHandle* prev; + size_t charge; // TODO(opt): Only allow uint32_t? + size_t key_length; + bool in_cache; // Whether entry is in the cache. + uint32_t refs; // References, including cache reference, if present. + uint32_t hash; // Hash of key(); used for fast sharding and comparisons + char key_data[1]; // Beginning of key + + Slice key() const { + // next_ is only equal to this if the LRU handle is the list head of an + // empty list. List heads never have meaningful keys. + assert(next != this); + + return Slice(key_data, key_length); + } +}; + +// We provide our own simple hash table since it removes a whole bunch +// of porting hacks and is also faster than some of the built-in hash +// table implementations in some of the compiler/runtime combinations +// we have tested. E.g., readrandom speeds up by ~5% over the g++ +// 4.4.3's builtin hashtable. +class HandleTable { + public: + HandleTable() : length_(0), elems_(0), list_(nullptr) { Resize(); } + ~HandleTable() { delete[] list_; } + + LRUHandle* Lookup(const Slice& key, uint32_t hash) { + return *FindPointer(key, hash); + } + + LRUHandle* Insert(LRUHandle* h) { + LRUHandle** ptr = FindPointer(h->key(), h->hash); + LRUHandle* old = *ptr; + h->next_hash = (old == nullptr ? nullptr : old->next_hash); + *ptr = h; + if (old == nullptr) { + ++elems_; + if (elems_ > length_) { + // Since each cache entry is fairly large, we aim for a small + // average linked list length (<= 1). + Resize(); + } + } + return old; + } + + LRUHandle* Remove(const Slice& key, uint32_t hash) { + LRUHandle** ptr = FindPointer(key, hash); + LRUHandle* result = *ptr; + if (result != nullptr) { + *ptr = result->next_hash; + --elems_; + } + return result; + } + + private: + // The table consists of an array of buckets where each bucket is + // a linked list of cache entries that hash into the bucket. + uint32_t length_; + uint32_t elems_; + LRUHandle** list_; + + // Return a pointer to slot that points to a cache entry that + // matches key/hash. If there is no such cache entry, return a + // pointer to the trailing slot in the corresponding linked list. + LRUHandle** FindPointer(const Slice& key, uint32_t hash) { + LRUHandle** ptr = &list_[hash & (length_ - 1)]; + while (*ptr != nullptr && ((*ptr)->hash != hash || key != (*ptr)->key())) { + ptr = &(*ptr)->next_hash; + } + return ptr; + } + + void Resize() { + uint32_t new_length = 4; + while (new_length < elems_) { + new_length *= 2; + } + LRUHandle** new_list = new LRUHandle*[new_length]; + memset(new_list, 0, sizeof(new_list[0]) * new_length); + uint32_t count = 0; + for (uint32_t i = 0; i < length_; i++) { + LRUHandle* h = list_[i]; + while (h != nullptr) { + LRUHandle* next = h->next_hash; + uint32_t hash = h->hash; + LRUHandle** ptr = &new_list[hash & (new_length - 1)]; + h->next_hash = *ptr; + *ptr = h; + h = next; + count++; + } + } + assert(elems_ == count); + delete[] list_; + list_ = new_list; + length_ = new_length; + } +}; + +// A single shard of sharded cache. +class LRUCache { + public: + LRUCache(); + ~LRUCache(); + + // Separate from constructor so caller can easily make an array of LRUCache + void SetCapacity(size_t capacity) { capacity_ = capacity; } + + // Like Cache methods, but with an extra "hash" parameter. + Cache::Handle* Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, void* value)); + Cache::Handle* Lookup(const Slice& key, uint32_t hash); + void Release(Cache::Handle* handle); + void Erase(const Slice& key, uint32_t hash); + void Prune(); + size_t TotalCharge() const { + MutexLock l(&mutex_); + return usage_; + } + + private: + void LRU_Remove(LRUHandle* e); + void LRU_Append(LRUHandle* list, LRUHandle* e); + void Ref(LRUHandle* e); + void Unref(LRUHandle* e); + bool FinishErase(LRUHandle* e) EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Initialized before use. + size_t capacity_; + + // mutex_ protects the following state. + mutable port::Mutex mutex_; + size_t usage_ GUARDED_BY(mutex_); + + // Dummy head of LRU list. + // lru.prev is newest entry, lru.next is oldest entry. + // Entries have refs==1 and in_cache==true. + LRUHandle lru_ GUARDED_BY(mutex_); + + // Dummy head of in-use list. + // Entries are in use by clients, and have refs >= 2 and in_cache==true. + LRUHandle in_use_ GUARDED_BY(mutex_); + + HandleTable table_ GUARDED_BY(mutex_); +}; + +LRUCache::LRUCache() : capacity_(0), usage_(0) { + // Make empty circular linked lists. + lru_.next = &lru_; + lru_.prev = &lru_; + in_use_.next = &in_use_; + in_use_.prev = &in_use_; +} + +LRUCache::~LRUCache() { + assert(in_use_.next == &in_use_); // Error if caller has an unreleased handle + for (LRUHandle* e = lru_.next; e != &lru_;) { + LRUHandle* next = e->next; + assert(e->in_cache); + e->in_cache = false; + assert(e->refs == 1); // Invariant of lru_ list. + Unref(e); + e = next; + } +} + +void LRUCache::Ref(LRUHandle* e) { + if (e->refs == 1 && e->in_cache) { // If on lru_ list, move to in_use_ list. + LRU_Remove(e); + LRU_Append(&in_use_, e); + } + e->refs++; +} + +void LRUCache::Unref(LRUHandle* e) { + assert(e->refs > 0); + e->refs--; + if (e->refs == 0) { // Deallocate. + assert(!e->in_cache); + (*e->deleter)(e->key(), e->value); + free(e); + } else if (e->in_cache && e->refs == 1) { + // No longer in use; move to lru_ list. + LRU_Remove(e); + LRU_Append(&lru_, e); + } +} + +void LRUCache::LRU_Remove(LRUHandle* e) { + e->next->prev = e->prev; + e->prev->next = e->next; +} + +void LRUCache::LRU_Append(LRUHandle* list, LRUHandle* e) { + // Make "e" newest entry by inserting just before *list + e->next = list; + e->prev = list->prev; + e->prev->next = e; + e->next->prev = e; +} + +Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Lookup(key, hash); + if (e != nullptr) { + Ref(e); + } + return reinterpret_cast(e); +} + +void LRUCache::Release(Cache::Handle* handle) { + MutexLock l(&mutex_); + Unref(reinterpret_cast(handle)); +} + +Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, + void* value)) { + MutexLock l(&mutex_); + + LRUHandle* e = + reinterpret_cast(malloc(sizeof(LRUHandle) - 1 + key.size())); + e->value = value; + e->deleter = deleter; + e->charge = charge; + e->key_length = key.size(); + e->hash = hash; + e->in_cache = false; + e->refs = 1; // for the returned handle. + memcpy(e->key_data, key.data(), key.size()); + + if (capacity_ > 0) { + e->refs++; // for the cache's reference. + e->in_cache = true; + LRU_Append(&in_use_, e); + usage_ += charge; + FinishErase(table_.Insert(e)); + } else { // don't cache. (capacity_==0 is supported and turns off caching.) + // next is read by key() in an assert, so it must be initialized + e->next = nullptr; + } + while (usage_ > capacity_ && lru_.next != &lru_) { + LRUHandle* old = lru_.next; + assert(old->refs == 1); + bool erased = FinishErase(table_.Remove(old->key(), old->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } + + return reinterpret_cast(e); +} + +// If e != nullptr, finish removing *e from the cache; it has already been +// removed from the hash table. Return whether e != nullptr. +bool LRUCache::FinishErase(LRUHandle* e) { + if (e != nullptr) { + assert(e->in_cache); + LRU_Remove(e); + e->in_cache = false; + usage_ -= e->charge; + Unref(e); + } + return e != nullptr; +} + +void LRUCache::Erase(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + FinishErase(table_.Remove(key, hash)); +} + +void LRUCache::Prune() { + MutexLock l(&mutex_); + while (lru_.next != &lru_) { + LRUHandle* e = lru_.next; + assert(e->refs == 1); + bool erased = FinishErase(table_.Remove(e->key(), e->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } +} + +static const int kNumShardBits = 4; +static const int kNumShards = 1 << kNumShardBits; + +class ShardedLRUCache : public Cache { + private: + LRUCache shard_[kNumShards]; + port::Mutex id_mutex_; + uint64_t last_id_; + + static inline uint32_t HashSlice(const Slice& s) { + return Hash(s.data(), s.size(), 0); + } + + static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); } + + public: + explicit ShardedLRUCache(size_t capacity) : last_id_(0) { + const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards; + for (int s = 0; s < kNumShards; s++) { + shard_[s].SetCapacity(per_shard); + } + } + virtual ~ShardedLRUCache() {} + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); + } + virtual Handle* Lookup(const Slice& key) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Lookup(key, hash); + } + virtual void Release(Handle* handle) { + LRUHandle* h = reinterpret_cast(handle); + shard_[Shard(h->hash)].Release(handle); + } + virtual void Erase(const Slice& key) { + const uint32_t hash = HashSlice(key); + shard_[Shard(hash)].Erase(key, hash); + } + virtual void* Value(Handle* handle) { + return reinterpret_cast(handle)->value; + } + virtual uint64_t NewId() { + MutexLock l(&id_mutex_); + return ++(last_id_); + } + virtual void Prune() { + for (int s = 0; s < kNumShards; s++) { + shard_[s].Prune(); + } + } + virtual size_t TotalCharge() const { + size_t total = 0; + for (int s = 0; s < kNumShards; s++) { + total += shard_[s].TotalCharge(); + } + return total; + } +}; + +} // end anonymous namespace + +Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); } + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/coding.cc b/PediatricPancreas/Pods/leveldb-library/util/coding.cc new file mode 100644 index 0000000..e2089df --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/coding.cc @@ -0,0 +1,192 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +namespace leveldb { + +void EncodeFixed32(char* dst, uint32_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + } +} + +void EncodeFixed64(char* dst, uint64_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + dst[4] = (value >> 32) & 0xff; + dst[5] = (value >> 40) & 0xff; + dst[6] = (value >> 48) & 0xff; + dst[7] = (value >> 56) & 0xff; + } +} + +void PutFixed32(std::string* dst, uint32_t value) { + char buf[sizeof(value)]; + EncodeFixed32(buf, value); + dst->append(buf, sizeof(buf)); +} + +void PutFixed64(std::string* dst, uint64_t value) { + char buf[sizeof(value)]; + EncodeFixed64(buf, value); + dst->append(buf, sizeof(buf)); +} + +char* EncodeVarint32(char* dst, uint32_t v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(dst); + static const int B = 128; + if (v < (1 << 7)) { + *(ptr++) = v; + } else if (v < (1 << 14)) { + *(ptr++) = v | B; + *(ptr++) = v >> 7; + } else if (v < (1 << 21)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = v >> 14; + } else if (v < (1 << 28)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = v >> 21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = (v >> 21) | B; + *(ptr++) = v >> 28; + } + return reinterpret_cast(ptr); +} + +void PutVarint32(std::string* dst, uint32_t v) { + char buf[5]; + char* ptr = EncodeVarint32(buf, v); + dst->append(buf, ptr - buf); +} + +char* EncodeVarint64(char* dst, uint64_t v) { + static const int B = 128; + unsigned char* ptr = reinterpret_cast(dst); + while (v >= B) { + *(ptr++) = v | B; + v >>= 7; + } + *(ptr++) = static_cast(v); + return reinterpret_cast(ptr); +} + +void PutVarint64(std::string* dst, uint64_t v) { + char buf[10]; + char* ptr = EncodeVarint64(buf, v); + dst->append(buf, ptr - buf); +} + +void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { + PutVarint32(dst, value.size()); + dst->append(value.data(), value.size()); +} + +int VarintLength(uint64_t v) { + int len = 1; + while (v >= 128) { + v >>= 7; + len++; + } + return len; +} + +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value) { + uint32_t result = 0; + for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { + uint32_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint32(Slice* input, uint32_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint32Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { + uint64_t result = 0; + for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { + uint64_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint64(Slice* input, uint64_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint64Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetLengthPrefixedSlice(const char* p, const char* limit, + Slice* result) { + uint32_t len; + p = GetVarint32Ptr(p, limit, &len); + if (p == nullptr) return nullptr; + if (p + len > limit) return nullptr; + *result = Slice(p, len); + return p + len; +} + +bool GetLengthPrefixedSlice(Slice* input, Slice* result) { + uint32_t len; + if (GetVarint32(input, &len) && input->size() >= len) { + *result = Slice(input->data(), len); + input->remove_prefix(len); + return true; + } else { + return false; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/coding.h b/PediatricPancreas/Pods/leveldb-library/util/coding.h new file mode 100644 index 0000000..d9eeaa3 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/coding.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Endian-neutral encoding: +// * Fixed-length numbers are encoded with least-significant byte first +// * In addition we support variable length "varint" encoding +// * Strings are encoded prefixed by their length in varint format + +#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ +#define STORAGE_LEVELDB_UTIL_CODING_H_ + +#include +#include + +#include + +#include "leveldb/slice.h" +#include "port/port.h" + +namespace leveldb { + +// Standard Put... routines append to a string +void PutFixed32(std::string* dst, uint32_t value); +void PutFixed64(std::string* dst, uint64_t value); +void PutVarint32(std::string* dst, uint32_t value); +void PutVarint64(std::string* dst, uint64_t value); +void PutLengthPrefixedSlice(std::string* dst, const Slice& value); + +// Standard Get... routines parse a value from the beginning of a Slice +// and advance the slice past the parsed value. +bool GetVarint32(Slice* input, uint32_t* value); +bool GetVarint64(Slice* input, uint64_t* value); +bool GetLengthPrefixedSlice(Slice* input, Slice* result); + +// Pointer-based variants of GetVarint... These either store a value +// in *v and return a pointer just past the parsed value, or return +// nullptr on error. These routines only look at bytes in the range +// [p..limit-1] +const char* GetVarint32Ptr(const char* p, const char* limit, uint32_t* v); +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* v); + +// Returns the length of the varint32 or varint64 encoding of "v" +int VarintLength(uint64_t v); + +// Lower-level versions of Put... that write directly into a character buffer +// REQUIRES: dst has enough space for the value being written +void EncodeFixed32(char* dst, uint32_t value); +void EncodeFixed64(char* dst, uint64_t value); + +// Lower-level versions of Put... that write directly into a character buffer +// and return a pointer just past the last byte written. +// REQUIRES: dst has enough space for the value being written +char* EncodeVarint32(char* dst, uint32_t value); +char* EncodeVarint64(char* dst, uint64_t value); + +// Lower-level versions of Get... that read directly from a character buffer +// without any bounds checking. + +inline uint32_t DecodeFixed32(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint32_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) | + (static_cast(static_cast(ptr[1])) << 8) | + (static_cast(static_cast(ptr[2])) << 16) | + (static_cast(static_cast(ptr[3])) << 24)); + } +} + +inline uint64_t DecodeFixed64(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint64_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + uint64_t lo = DecodeFixed32(ptr); + uint64_t hi = DecodeFixed32(ptr + 4); + return (hi << 32) | lo; + } +} + +// Internal routine for use by fallback path of GetVarint32Ptr +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value); +inline const char* GetVarint32Ptr(const char* p, const char* limit, + uint32_t* value) { + if (p < limit) { + uint32_t result = *(reinterpret_cast(p)); + if ((result & 128) == 0) { + *value = result; + return p + 1; + } + } + return GetVarint32PtrFallback(p, limit, value); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/comparator.cc b/PediatricPancreas/Pods/leveldb-library/util/comparator.cc new file mode 100644 index 0000000..26d1eb3 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/comparator.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/comparator.h" +#include "leveldb/slice.h" +#include "util/logging.h" +#include "util/no_destructor.h" + +namespace leveldb { + +Comparator::~Comparator() {} + +namespace { +class BytewiseComparatorImpl : public Comparator { + public: + BytewiseComparatorImpl() {} + + virtual const char* Name() const { return "leveldb.BytewiseComparator"; } + + virtual int Compare(const Slice& a, const Slice& b) const { + return a.compare(b); + } + + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Find length of common prefix + size_t min_length = std::min(start->size(), limit.size()); + size_t diff_index = 0; + while ((diff_index < min_length) && + ((*start)[diff_index] == limit[diff_index])) { + diff_index++; + } + + if (diff_index >= min_length) { + // Do not shorten if one string is a prefix of the other + } else { + uint8_t diff_byte = static_cast((*start)[diff_index]); + if (diff_byte < static_cast(0xff) && + diff_byte + 1 < static_cast(limit[diff_index])) { + (*start)[diff_index]++; + start->resize(diff_index + 1); + assert(Compare(*start, limit) < 0); + } + } + } + + virtual void FindShortSuccessor(std::string* key) const { + // Find first character that can be incremented + size_t n = key->size(); + for (size_t i = 0; i < n; i++) { + const uint8_t byte = (*key)[i]; + if (byte != static_cast(0xff)) { + (*key)[i] = byte + 1; + key->resize(i + 1); + return; + } + } + // *key is a run of 0xffs. Leave it alone. + } +}; +} // namespace + +const Comparator* BytewiseComparator() { + static NoDestructor singleton; + return singleton.get(); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/crc32c.cc b/PediatricPancreas/Pods/leveldb-library/util/crc32c.cc new file mode 100644 index 0000000..c2e61f7 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/crc32c.cc @@ -0,0 +1,380 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c. + +#include "util/crc32c.h" + +#include +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { +namespace crc32c { + +namespace { + +const uint32_t kByteExtensionTable[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, + 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, + 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, + 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, + 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, + 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, + 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, + 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, + 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, + 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, + 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, + 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, + 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, + 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, + 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, + 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, + 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, + 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, + 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, + 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, + 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, + 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351}; + +const uint32_t kStrideExtensionTable0[256] = { + 0x00000000, 0x30d23865, 0x61a470ca, 0x517648af, 0xc348e194, 0xf39ad9f1, + 0xa2ec915e, 0x923ea93b, 0x837db5d9, 0xb3af8dbc, 0xe2d9c513, 0xd20bfd76, + 0x4035544d, 0x70e76c28, 0x21912487, 0x11431ce2, 0x03171d43, 0x33c52526, + 0x62b36d89, 0x526155ec, 0xc05ffcd7, 0xf08dc4b2, 0xa1fb8c1d, 0x9129b478, + 0x806aa89a, 0xb0b890ff, 0xe1ced850, 0xd11ce035, 0x4322490e, 0x73f0716b, + 0x228639c4, 0x125401a1, 0x062e3a86, 0x36fc02e3, 0x678a4a4c, 0x57587229, + 0xc566db12, 0xf5b4e377, 0xa4c2abd8, 0x941093bd, 0x85538f5f, 0xb581b73a, + 0xe4f7ff95, 0xd425c7f0, 0x461b6ecb, 0x76c956ae, 0x27bf1e01, 0x176d2664, + 0x053927c5, 0x35eb1fa0, 0x649d570f, 0x544f6f6a, 0xc671c651, 0xf6a3fe34, + 0xa7d5b69b, 0x97078efe, 0x8644921c, 0xb696aa79, 0xe7e0e2d6, 0xd732dab3, + 0x450c7388, 0x75de4bed, 0x24a80342, 0x147a3b27, 0x0c5c750c, 0x3c8e4d69, + 0x6df805c6, 0x5d2a3da3, 0xcf149498, 0xffc6acfd, 0xaeb0e452, 0x9e62dc37, + 0x8f21c0d5, 0xbff3f8b0, 0xee85b01f, 0xde57887a, 0x4c692141, 0x7cbb1924, + 0x2dcd518b, 0x1d1f69ee, 0x0f4b684f, 0x3f99502a, 0x6eef1885, 0x5e3d20e0, + 0xcc0389db, 0xfcd1b1be, 0xada7f911, 0x9d75c174, 0x8c36dd96, 0xbce4e5f3, + 0xed92ad5c, 0xdd409539, 0x4f7e3c02, 0x7fac0467, 0x2eda4cc8, 0x1e0874ad, + 0x0a724f8a, 0x3aa077ef, 0x6bd63f40, 0x5b040725, 0xc93aae1e, 0xf9e8967b, + 0xa89eded4, 0x984ce6b1, 0x890ffa53, 0xb9ddc236, 0xe8ab8a99, 0xd879b2fc, + 0x4a471bc7, 0x7a9523a2, 0x2be36b0d, 0x1b315368, 0x096552c9, 0x39b76aac, + 0x68c12203, 0x58131a66, 0xca2db35d, 0xfaff8b38, 0xab89c397, 0x9b5bfbf2, + 0x8a18e710, 0xbacadf75, 0xebbc97da, 0xdb6eafbf, 0x49500684, 0x79823ee1, + 0x28f4764e, 0x18264e2b, 0x18b8ea18, 0x286ad27d, 0x791c9ad2, 0x49cea2b7, + 0xdbf00b8c, 0xeb2233e9, 0xba547b46, 0x8a864323, 0x9bc55fc1, 0xab1767a4, + 0xfa612f0b, 0xcab3176e, 0x588dbe55, 0x685f8630, 0x3929ce9f, 0x09fbf6fa, + 0x1baff75b, 0x2b7dcf3e, 0x7a0b8791, 0x4ad9bff4, 0xd8e716cf, 0xe8352eaa, + 0xb9436605, 0x89915e60, 0x98d24282, 0xa8007ae7, 0xf9763248, 0xc9a40a2d, + 0x5b9aa316, 0x6b489b73, 0x3a3ed3dc, 0x0aecebb9, 0x1e96d09e, 0x2e44e8fb, + 0x7f32a054, 0x4fe09831, 0xddde310a, 0xed0c096f, 0xbc7a41c0, 0x8ca879a5, + 0x9deb6547, 0xad395d22, 0xfc4f158d, 0xcc9d2de8, 0x5ea384d3, 0x6e71bcb6, + 0x3f07f419, 0x0fd5cc7c, 0x1d81cddd, 0x2d53f5b8, 0x7c25bd17, 0x4cf78572, + 0xdec92c49, 0xee1b142c, 0xbf6d5c83, 0x8fbf64e6, 0x9efc7804, 0xae2e4061, + 0xff5808ce, 0xcf8a30ab, 0x5db49990, 0x6d66a1f5, 0x3c10e95a, 0x0cc2d13f, + 0x14e49f14, 0x2436a771, 0x7540efde, 0x4592d7bb, 0xd7ac7e80, 0xe77e46e5, + 0xb6080e4a, 0x86da362f, 0x97992acd, 0xa74b12a8, 0xf63d5a07, 0xc6ef6262, + 0x54d1cb59, 0x6403f33c, 0x3575bb93, 0x05a783f6, 0x17f38257, 0x2721ba32, + 0x7657f29d, 0x4685caf8, 0xd4bb63c3, 0xe4695ba6, 0xb51f1309, 0x85cd2b6c, + 0x948e378e, 0xa45c0feb, 0xf52a4744, 0xc5f87f21, 0x57c6d61a, 0x6714ee7f, + 0x3662a6d0, 0x06b09eb5, 0x12caa592, 0x22189df7, 0x736ed558, 0x43bced3d, + 0xd1824406, 0xe1507c63, 0xb02634cc, 0x80f40ca9, 0x91b7104b, 0xa165282e, + 0xf0136081, 0xc0c158e4, 0x52fff1df, 0x622dc9ba, 0x335b8115, 0x0389b970, + 0x11ddb8d1, 0x210f80b4, 0x7079c81b, 0x40abf07e, 0xd2955945, 0xe2476120, + 0xb331298f, 0x83e311ea, 0x92a00d08, 0xa272356d, 0xf3047dc2, 0xc3d645a7, + 0x51e8ec9c, 0x613ad4f9, 0x304c9c56, 0x009ea433}; + +const uint32_t kStrideExtensionTable1[256] = { + 0x00000000, 0x54075546, 0xa80eaa8c, 0xfc09ffca, 0x55f123e9, 0x01f676af, + 0xfdff8965, 0xa9f8dc23, 0xabe247d2, 0xffe51294, 0x03eced5e, 0x57ebb818, + 0xfe13643b, 0xaa14317d, 0x561dceb7, 0x021a9bf1, 0x5228f955, 0x062fac13, + 0xfa2653d9, 0xae21069f, 0x07d9dabc, 0x53de8ffa, 0xafd77030, 0xfbd02576, + 0xf9cabe87, 0xadcdebc1, 0x51c4140b, 0x05c3414d, 0xac3b9d6e, 0xf83cc828, + 0x043537e2, 0x503262a4, 0xa451f2aa, 0xf056a7ec, 0x0c5f5826, 0x58580d60, + 0xf1a0d143, 0xa5a78405, 0x59ae7bcf, 0x0da92e89, 0x0fb3b578, 0x5bb4e03e, + 0xa7bd1ff4, 0xf3ba4ab2, 0x5a429691, 0x0e45c3d7, 0xf24c3c1d, 0xa64b695b, + 0xf6790bff, 0xa27e5eb9, 0x5e77a173, 0x0a70f435, 0xa3882816, 0xf78f7d50, + 0x0b86829a, 0x5f81d7dc, 0x5d9b4c2d, 0x099c196b, 0xf595e6a1, 0xa192b3e7, + 0x086a6fc4, 0x5c6d3a82, 0xa064c548, 0xf463900e, 0x4d4f93a5, 0x1948c6e3, + 0xe5413929, 0xb1466c6f, 0x18beb04c, 0x4cb9e50a, 0xb0b01ac0, 0xe4b74f86, + 0xe6add477, 0xb2aa8131, 0x4ea37efb, 0x1aa42bbd, 0xb35cf79e, 0xe75ba2d8, + 0x1b525d12, 0x4f550854, 0x1f676af0, 0x4b603fb6, 0xb769c07c, 0xe36e953a, + 0x4a964919, 0x1e911c5f, 0xe298e395, 0xb69fb6d3, 0xb4852d22, 0xe0827864, + 0x1c8b87ae, 0x488cd2e8, 0xe1740ecb, 0xb5735b8d, 0x497aa447, 0x1d7df101, + 0xe91e610f, 0xbd193449, 0x4110cb83, 0x15179ec5, 0xbcef42e6, 0xe8e817a0, + 0x14e1e86a, 0x40e6bd2c, 0x42fc26dd, 0x16fb739b, 0xeaf28c51, 0xbef5d917, + 0x170d0534, 0x430a5072, 0xbf03afb8, 0xeb04fafe, 0xbb36985a, 0xef31cd1c, + 0x133832d6, 0x473f6790, 0xeec7bbb3, 0xbac0eef5, 0x46c9113f, 0x12ce4479, + 0x10d4df88, 0x44d38ace, 0xb8da7504, 0xecdd2042, 0x4525fc61, 0x1122a927, + 0xed2b56ed, 0xb92c03ab, 0x9a9f274a, 0xce98720c, 0x32918dc6, 0x6696d880, + 0xcf6e04a3, 0x9b6951e5, 0x6760ae2f, 0x3367fb69, 0x317d6098, 0x657a35de, + 0x9973ca14, 0xcd749f52, 0x648c4371, 0x308b1637, 0xcc82e9fd, 0x9885bcbb, + 0xc8b7de1f, 0x9cb08b59, 0x60b97493, 0x34be21d5, 0x9d46fdf6, 0xc941a8b0, + 0x3548577a, 0x614f023c, 0x635599cd, 0x3752cc8b, 0xcb5b3341, 0x9f5c6607, + 0x36a4ba24, 0x62a3ef62, 0x9eaa10a8, 0xcaad45ee, 0x3eced5e0, 0x6ac980a6, + 0x96c07f6c, 0xc2c72a2a, 0x6b3ff609, 0x3f38a34f, 0xc3315c85, 0x973609c3, + 0x952c9232, 0xc12bc774, 0x3d2238be, 0x69256df8, 0xc0ddb1db, 0x94dae49d, + 0x68d31b57, 0x3cd44e11, 0x6ce62cb5, 0x38e179f3, 0xc4e88639, 0x90efd37f, + 0x39170f5c, 0x6d105a1a, 0x9119a5d0, 0xc51ef096, 0xc7046b67, 0x93033e21, + 0x6f0ac1eb, 0x3b0d94ad, 0x92f5488e, 0xc6f21dc8, 0x3afbe202, 0x6efcb744, + 0xd7d0b4ef, 0x83d7e1a9, 0x7fde1e63, 0x2bd94b25, 0x82219706, 0xd626c240, + 0x2a2f3d8a, 0x7e2868cc, 0x7c32f33d, 0x2835a67b, 0xd43c59b1, 0x803b0cf7, + 0x29c3d0d4, 0x7dc48592, 0x81cd7a58, 0xd5ca2f1e, 0x85f84dba, 0xd1ff18fc, + 0x2df6e736, 0x79f1b270, 0xd0096e53, 0x840e3b15, 0x7807c4df, 0x2c009199, + 0x2e1a0a68, 0x7a1d5f2e, 0x8614a0e4, 0xd213f5a2, 0x7beb2981, 0x2fec7cc7, + 0xd3e5830d, 0x87e2d64b, 0x73814645, 0x27861303, 0xdb8fecc9, 0x8f88b98f, + 0x267065ac, 0x727730ea, 0x8e7ecf20, 0xda799a66, 0xd8630197, 0x8c6454d1, + 0x706dab1b, 0x246afe5d, 0x8d92227e, 0xd9957738, 0x259c88f2, 0x719bddb4, + 0x21a9bf10, 0x75aeea56, 0x89a7159c, 0xdda040da, 0x74589cf9, 0x205fc9bf, + 0xdc563675, 0x88516333, 0x8a4bf8c2, 0xde4cad84, 0x2245524e, 0x76420708, + 0xdfbadb2b, 0x8bbd8e6d, 0x77b471a7, 0x23b324e1}; + +const uint32_t kStrideExtensionTable2[256] = { + 0x00000000, 0x678efd01, 0xcf1dfa02, 0xa8930703, 0x9bd782f5, 0xfc597ff4, + 0x54ca78f7, 0x334485f6, 0x3243731b, 0x55cd8e1a, 0xfd5e8919, 0x9ad07418, + 0xa994f1ee, 0xce1a0cef, 0x66890bec, 0x0107f6ed, 0x6486e636, 0x03081b37, + 0xab9b1c34, 0xcc15e135, 0xff5164c3, 0x98df99c2, 0x304c9ec1, 0x57c263c0, + 0x56c5952d, 0x314b682c, 0x99d86f2f, 0xfe56922e, 0xcd1217d8, 0xaa9cead9, + 0x020fedda, 0x658110db, 0xc90dcc6c, 0xae83316d, 0x0610366e, 0x619ecb6f, + 0x52da4e99, 0x3554b398, 0x9dc7b49b, 0xfa49499a, 0xfb4ebf77, 0x9cc04276, + 0x34534575, 0x53ddb874, 0x60993d82, 0x0717c083, 0xaf84c780, 0xc80a3a81, + 0xad8b2a5a, 0xca05d75b, 0x6296d058, 0x05182d59, 0x365ca8af, 0x51d255ae, + 0xf94152ad, 0x9ecfafac, 0x9fc85941, 0xf846a440, 0x50d5a343, 0x375b5e42, + 0x041fdbb4, 0x639126b5, 0xcb0221b6, 0xac8cdcb7, 0x97f7ee29, 0xf0791328, + 0x58ea142b, 0x3f64e92a, 0x0c206cdc, 0x6bae91dd, 0xc33d96de, 0xa4b36bdf, + 0xa5b49d32, 0xc23a6033, 0x6aa96730, 0x0d279a31, 0x3e631fc7, 0x59ede2c6, + 0xf17ee5c5, 0x96f018c4, 0xf371081f, 0x94fff51e, 0x3c6cf21d, 0x5be20f1c, + 0x68a68aea, 0x0f2877eb, 0xa7bb70e8, 0xc0358de9, 0xc1327b04, 0xa6bc8605, + 0x0e2f8106, 0x69a17c07, 0x5ae5f9f1, 0x3d6b04f0, 0x95f803f3, 0xf276fef2, + 0x5efa2245, 0x3974df44, 0x91e7d847, 0xf6692546, 0xc52da0b0, 0xa2a35db1, + 0x0a305ab2, 0x6dbea7b3, 0x6cb9515e, 0x0b37ac5f, 0xa3a4ab5c, 0xc42a565d, + 0xf76ed3ab, 0x90e02eaa, 0x387329a9, 0x5ffdd4a8, 0x3a7cc473, 0x5df23972, + 0xf5613e71, 0x92efc370, 0xa1ab4686, 0xc625bb87, 0x6eb6bc84, 0x09384185, + 0x083fb768, 0x6fb14a69, 0xc7224d6a, 0xa0acb06b, 0x93e8359d, 0xf466c89c, + 0x5cf5cf9f, 0x3b7b329e, 0x2a03aaa3, 0x4d8d57a2, 0xe51e50a1, 0x8290ada0, + 0xb1d42856, 0xd65ad557, 0x7ec9d254, 0x19472f55, 0x1840d9b8, 0x7fce24b9, + 0xd75d23ba, 0xb0d3debb, 0x83975b4d, 0xe419a64c, 0x4c8aa14f, 0x2b045c4e, + 0x4e854c95, 0x290bb194, 0x8198b697, 0xe6164b96, 0xd552ce60, 0xb2dc3361, + 0x1a4f3462, 0x7dc1c963, 0x7cc63f8e, 0x1b48c28f, 0xb3dbc58c, 0xd455388d, + 0xe711bd7b, 0x809f407a, 0x280c4779, 0x4f82ba78, 0xe30e66cf, 0x84809bce, + 0x2c139ccd, 0x4b9d61cc, 0x78d9e43a, 0x1f57193b, 0xb7c41e38, 0xd04ae339, + 0xd14d15d4, 0xb6c3e8d5, 0x1e50efd6, 0x79de12d7, 0x4a9a9721, 0x2d146a20, + 0x85876d23, 0xe2099022, 0x878880f9, 0xe0067df8, 0x48957afb, 0x2f1b87fa, + 0x1c5f020c, 0x7bd1ff0d, 0xd342f80e, 0xb4cc050f, 0xb5cbf3e2, 0xd2450ee3, + 0x7ad609e0, 0x1d58f4e1, 0x2e1c7117, 0x49928c16, 0xe1018b15, 0x868f7614, + 0xbdf4448a, 0xda7ab98b, 0x72e9be88, 0x15674389, 0x2623c67f, 0x41ad3b7e, + 0xe93e3c7d, 0x8eb0c17c, 0x8fb73791, 0xe839ca90, 0x40aacd93, 0x27243092, + 0x1460b564, 0x73ee4865, 0xdb7d4f66, 0xbcf3b267, 0xd972a2bc, 0xbefc5fbd, + 0x166f58be, 0x71e1a5bf, 0x42a52049, 0x252bdd48, 0x8db8da4b, 0xea36274a, + 0xeb31d1a7, 0x8cbf2ca6, 0x242c2ba5, 0x43a2d6a4, 0x70e65352, 0x1768ae53, + 0xbffba950, 0xd8755451, 0x74f988e6, 0x137775e7, 0xbbe472e4, 0xdc6a8fe5, + 0xef2e0a13, 0x88a0f712, 0x2033f011, 0x47bd0d10, 0x46bafbfd, 0x213406fc, + 0x89a701ff, 0xee29fcfe, 0xdd6d7908, 0xbae38409, 0x1270830a, 0x75fe7e0b, + 0x107f6ed0, 0x77f193d1, 0xdf6294d2, 0xb8ec69d3, 0x8ba8ec25, 0xec261124, + 0x44b51627, 0x233beb26, 0x223c1dcb, 0x45b2e0ca, 0xed21e7c9, 0x8aaf1ac8, + 0xb9eb9f3e, 0xde65623f, 0x76f6653c, 0x1178983d}; + +const uint32_t kStrideExtensionTable3[256] = { + 0x00000000, 0xf20c0dfe, 0xe1f46d0d, 0x13f860f3, 0xc604aceb, 0x3408a115, + 0x27f0c1e6, 0xd5fccc18, 0x89e52f27, 0x7be922d9, 0x6811422a, 0x9a1d4fd4, + 0x4fe183cc, 0xbded8e32, 0xae15eec1, 0x5c19e33f, 0x162628bf, 0xe42a2541, + 0xf7d245b2, 0x05de484c, 0xd0228454, 0x222e89aa, 0x31d6e959, 0xc3dae4a7, + 0x9fc30798, 0x6dcf0a66, 0x7e376a95, 0x8c3b676b, 0x59c7ab73, 0xabcba68d, + 0xb833c67e, 0x4a3fcb80, 0x2c4c517e, 0xde405c80, 0xcdb83c73, 0x3fb4318d, + 0xea48fd95, 0x1844f06b, 0x0bbc9098, 0xf9b09d66, 0xa5a97e59, 0x57a573a7, + 0x445d1354, 0xb6511eaa, 0x63add2b2, 0x91a1df4c, 0x8259bfbf, 0x7055b241, + 0x3a6a79c1, 0xc866743f, 0xdb9e14cc, 0x29921932, 0xfc6ed52a, 0x0e62d8d4, + 0x1d9ab827, 0xef96b5d9, 0xb38f56e6, 0x41835b18, 0x527b3beb, 0xa0773615, + 0x758bfa0d, 0x8787f7f3, 0x947f9700, 0x66739afe, 0x5898a2fc, 0xaa94af02, + 0xb96ccff1, 0x4b60c20f, 0x9e9c0e17, 0x6c9003e9, 0x7f68631a, 0x8d646ee4, + 0xd17d8ddb, 0x23718025, 0x3089e0d6, 0xc285ed28, 0x17792130, 0xe5752cce, + 0xf68d4c3d, 0x048141c3, 0x4ebe8a43, 0xbcb287bd, 0xaf4ae74e, 0x5d46eab0, + 0x88ba26a8, 0x7ab62b56, 0x694e4ba5, 0x9b42465b, 0xc75ba564, 0x3557a89a, + 0x26afc869, 0xd4a3c597, 0x015f098f, 0xf3530471, 0xe0ab6482, 0x12a7697c, + 0x74d4f382, 0x86d8fe7c, 0x95209e8f, 0x672c9371, 0xb2d05f69, 0x40dc5297, + 0x53243264, 0xa1283f9a, 0xfd31dca5, 0x0f3dd15b, 0x1cc5b1a8, 0xeec9bc56, + 0x3b35704e, 0xc9397db0, 0xdac11d43, 0x28cd10bd, 0x62f2db3d, 0x90fed6c3, + 0x8306b630, 0x710abbce, 0xa4f677d6, 0x56fa7a28, 0x45021adb, 0xb70e1725, + 0xeb17f41a, 0x191bf9e4, 0x0ae39917, 0xf8ef94e9, 0x2d1358f1, 0xdf1f550f, + 0xcce735fc, 0x3eeb3802, 0xb13145f8, 0x433d4806, 0x50c528f5, 0xa2c9250b, + 0x7735e913, 0x8539e4ed, 0x96c1841e, 0x64cd89e0, 0x38d46adf, 0xcad86721, + 0xd92007d2, 0x2b2c0a2c, 0xfed0c634, 0x0cdccbca, 0x1f24ab39, 0xed28a6c7, + 0xa7176d47, 0x551b60b9, 0x46e3004a, 0xb4ef0db4, 0x6113c1ac, 0x931fcc52, + 0x80e7aca1, 0x72eba15f, 0x2ef24260, 0xdcfe4f9e, 0xcf062f6d, 0x3d0a2293, + 0xe8f6ee8b, 0x1afae375, 0x09028386, 0xfb0e8e78, 0x9d7d1486, 0x6f711978, + 0x7c89798b, 0x8e857475, 0x5b79b86d, 0xa975b593, 0xba8dd560, 0x4881d89e, + 0x14983ba1, 0xe694365f, 0xf56c56ac, 0x07605b52, 0xd29c974a, 0x20909ab4, + 0x3368fa47, 0xc164f7b9, 0x8b5b3c39, 0x795731c7, 0x6aaf5134, 0x98a35cca, + 0x4d5f90d2, 0xbf539d2c, 0xacabfddf, 0x5ea7f021, 0x02be131e, 0xf0b21ee0, + 0xe34a7e13, 0x114673ed, 0xc4babff5, 0x36b6b20b, 0x254ed2f8, 0xd742df06, + 0xe9a9e704, 0x1ba5eafa, 0x085d8a09, 0xfa5187f7, 0x2fad4bef, 0xdda14611, + 0xce5926e2, 0x3c552b1c, 0x604cc823, 0x9240c5dd, 0x81b8a52e, 0x73b4a8d0, + 0xa64864c8, 0x54446936, 0x47bc09c5, 0xb5b0043b, 0xff8fcfbb, 0x0d83c245, + 0x1e7ba2b6, 0xec77af48, 0x398b6350, 0xcb876eae, 0xd87f0e5d, 0x2a7303a3, + 0x766ae09c, 0x8466ed62, 0x979e8d91, 0x6592806f, 0xb06e4c77, 0x42624189, + 0x519a217a, 0xa3962c84, 0xc5e5b67a, 0x37e9bb84, 0x2411db77, 0xd61dd689, + 0x03e11a91, 0xf1ed176f, 0xe215779c, 0x10197a62, 0x4c00995d, 0xbe0c94a3, + 0xadf4f450, 0x5ff8f9ae, 0x8a0435b6, 0x78083848, 0x6bf058bb, 0x99fc5545, + 0xd3c39ec5, 0x21cf933b, 0x3237f3c8, 0xc03bfe36, 0x15c7322e, 0xe7cb3fd0, + 0xf4335f23, 0x063f52dd, 0x5a26b1e2, 0xa82abc1c, 0xbbd2dcef, 0x49ded111, + 0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa}; + +// CRCs are pre- and post- conditioned by xoring with all ones. +static constexpr const uint32_t kCRC32Xor = static_cast(0xffffffffU); + +// Reads a little-endian 32-bit integer from a 32-bit-aligned buffer. +inline uint32_t ReadUint32LE(const uint8_t* buffer) { + return DecodeFixed32(reinterpret_cast(buffer)); +} + +// Returns the smallest address >= the given address that is aligned to N bytes. +// +// N must be a power of two. +template +constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) { + return reinterpret_cast( + (reinterpret_cast(pointer) + (N - 1)) & + ~static_cast(N - 1)); +} + +} // namespace + +// Determine if the CPU running this program can accelerate the CRC32C +// calculation. +static bool CanAccelerateCRC32C() { + // port::AcceleretedCRC32C returns zero when unable to accelerate. + static const char kTestCRCBuffer[] = "TestCRCBuffer"; + static const char kBufSize = sizeof(kTestCRCBuffer) - 1; + static const uint32_t kTestCRCValue = 0xdcbc59fa; + + return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue; +} + +uint32_t Extend(uint32_t crc, const char* data, size_t n) { + static bool accelerate = CanAccelerateCRC32C(); + if (accelerate) { + return port::AcceleratedCRC32C(crc, data, n); + } + + const uint8_t* p = reinterpret_cast(data); + const uint8_t* e = p + n; + uint32_t l = crc ^ kCRC32Xor; + +// Process one byte at a time. +#define STEP1 \ + do { \ + int c = (l & 0xff) ^ *p++; \ + l = kByteExtensionTable[c] ^ (l >> 8); \ + } while (0) + +// Process one of the 4 strides of 4-byte data. +#define STEP4(s) \ + do { \ + crc##s = ReadUint32LE(p + s * 4) ^ kStrideExtensionTable3[crc##s & 0xff] ^ \ + kStrideExtensionTable2[(crc##s >> 8) & 0xff] ^ \ + kStrideExtensionTable1[(crc##s >> 16) & 0xff] ^ \ + kStrideExtensionTable0[crc##s >> 24]; \ + } while (0) + +// Process a 16-byte swath of 4 strides, each of which has 4 bytes of data. +#define STEP16 \ + do { \ + STEP4(0); \ + STEP4(1); \ + STEP4(2); \ + STEP4(3); \ + p += 16; \ + } while (0) + +// Process 4 bytes that were already loaded into a word. +#define STEP4W(w) \ + do { \ + w ^= l; \ + for (size_t i = 0; i < 4; ++i) { \ + w = (w >> 8) ^ kByteExtensionTable[w & 0xff]; \ + } \ + l = w; \ + } while (0) + + // Point x at first 4-byte aligned byte in the buffer. This might be past the + // end of the buffer. + const uint8_t* x = RoundUp<4>(p); + if (x <= e) { + // Process bytes p is 4-byte aligned. + while (p != x) { + STEP1; + } + } + + if ((e - p) >= 16) { + // Load a 16-byte swath into the stride partial results. + uint32_t crc0 = ReadUint32LE(p + 0 * 4) ^ l; + uint32_t crc1 = ReadUint32LE(p + 1 * 4); + uint32_t crc2 = ReadUint32LE(p + 2 * 4); + uint32_t crc3 = ReadUint32LE(p + 3 * 4); + p += 16; + + // It is possible to get better speeds (at least on x86) by interleaving + // prefetching 256 bytes ahead with processing 64 bytes at a time. See the + // portable implementation in https://github.com/google/crc32c/. + + // Process one 16-byte swath at a time. + while ((e - p) >= 16) { + STEP16; + } + + // Advance one word at a time as far as possible. + while ((e - p) >= 4) { + STEP4(0); + uint32_t tmp = crc0; + crc0 = crc1; + crc1 = crc2; + crc2 = crc3; + crc3 = tmp; + p += 4; + } + + // Combine the 4 partial stride results. + l = 0; + STEP4W(crc0); + STEP4W(crc1); + STEP4W(crc2); + STEP4W(crc3); + } + + // Process the last few bytes. + while (p != e) { + STEP1; + } +#undef STEP4W +#undef STEP16 +#undef STEP4 +#undef STEP1 + return l ^ kCRC32Xor; +} + +} // namespace crc32c +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/crc32c.h b/PediatricPancreas/Pods/leveldb-library/util/crc32c.h new file mode 100644 index 0000000..98fabb0 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/crc32c.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ +#define STORAGE_LEVELDB_UTIL_CRC32C_H_ + +#include +#include + +namespace leveldb { +namespace crc32c { + +// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the +// crc32c of some string A. Extend() is often used to maintain the +// crc32c of a stream of data. +uint32_t Extend(uint32_t init_crc, const char* data, size_t n); + +// Return the crc32c of data[0,n-1] +inline uint32_t Value(const char* data, size_t n) { return Extend(0, data, n); } + +static const uint32_t kMaskDelta = 0xa282ead8ul; + +// Return a masked representation of crc. +// +// Motivation: it is problematic to compute the CRC of a string that +// contains embedded CRCs. Therefore we recommend that CRCs stored +// somewhere (e.g., in files) should be masked before being stored. +inline uint32_t Mask(uint32_t crc) { + // Rotate right by 15 bits and add a constant. + return ((crc >> 15) | (crc << 17)) + kMaskDelta; +} + +// Return the crc whose masked representation is masked_crc. +inline uint32_t Unmask(uint32_t masked_crc) { + uint32_t rot = masked_crc - kMaskDelta; + return ((rot >> 17) | (rot << 15)); +} + +} // namespace crc32c +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/env.cc b/PediatricPancreas/Pods/leveldb-library/util/env.cc new file mode 100644 index 0000000..6cd5f2e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/env.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +namespace leveldb { + +Env::~Env() {} + +Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) { + return Status::NotSupported("NewAppendableFile", fname); +} + +SequentialFile::~SequentialFile() {} + +RandomAccessFile::~RandomAccessFile() {} + +WritableFile::~WritableFile() {} + +Logger::~Logger() {} + +FileLock::~FileLock() {} + +void Log(Logger* info_log, const char* format, ...) { + if (info_log != nullptr) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +static Status DoWriteStringToFile(Env* env, const Slice& data, + const std::string& fname, bool should_sync) { + WritableFile* file; + Status s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + s = file->Append(data); + if (s.ok() && should_sync) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; // Will auto-close if we did not close above + if (!s.ok()) { + env->DeleteFile(fname); + } + return s; +} + +Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, false); +} + +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, true); +} + +Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { + data->clear(); + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + static const int kBufferSize = 8192; + char* space = new char[kBufferSize]; + while (true) { + Slice fragment; + s = file->Read(kBufferSize, &fragment, space); + if (!s.ok()) { + break; + } + data->append(fragment.data(), fragment.size()); + if (fragment.empty()) { + break; + } + } + delete[] space; + delete file; + return s; +} + +EnvWrapper::~EnvWrapper() {} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/env_posix.cc b/PediatricPancreas/Pods/leveldb-library/util/env_posix.cc new file mode 100644 index 0000000..8c74f5a --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/env_posix.cc @@ -0,0 +1,876 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/env_posix_test_helper.h" +#include "util/posix_logger.h" + +namespace leveldb { + +namespace { + +// Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles(). +int g_open_read_only_file_limit = -1; + +// Up to 1000 mmap regions for 64-bit binaries; none for 32-bit. +constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0; + +// Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit. +int g_mmap_limit = kDefaultMmapLimit; + +constexpr const size_t kWritableFileBufferSize = 65536; + +Status PosixError(const std::string& context, int error_number) { + if (error_number == ENOENT) { + return Status::NotFound(context, std::strerror(error_number)); + } else { + return Status::IOError(context, std::strerror(error_number)); + } +} + +// Helper class to limit resource usage to avoid exhaustion. +// Currently used to limit read-only file descriptors and mmap file usage +// so that we do not run out of file descriptors or virtual memory, or run into +// kernel performance problems for very large databases. +class Limiter { + public: + // Limit maximum number of resources to |max_acquires|. + Limiter(int max_acquires) : acquires_allowed_(max_acquires) {} + + Limiter(const Limiter&) = delete; + Limiter operator=(const Limiter&) = delete; + + // If another resource is available, acquire it and return true. + // Else return false. + bool Acquire() { + int old_acquires_allowed = + acquires_allowed_.fetch_sub(1, std::memory_order_relaxed); + + if (old_acquires_allowed > 0) return true; + + acquires_allowed_.fetch_add(1, std::memory_order_relaxed); + return false; + } + + // Release a resource acquired by a previous call to Acquire() that returned + // true. + void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); } + + private: + // The number of available resources. + // + // This is a counter and is not tied to the invariants of any other class, so + // it can be operated on safely using std::memory_order_relaxed. + std::atomic acquires_allowed_; +}; + +// Implements sequential read access in a file using read(). +// +// Instances of this class are thread-friendly but not thread-safe, as required +// by the SequentialFile API. +class PosixSequentialFile final : public SequentialFile { + public: + PosixSequentialFile(std::string filename, int fd) + : fd_(fd), filename_(filename) {} + ~PosixSequentialFile() override { close(fd_); } + + Status Read(size_t n, Slice* result, char* scratch) override { + Status status; + while (true) { + ::ssize_t read_size = ::read(fd_, scratch, n); + if (read_size < 0) { // Read error. + if (errno == EINTR) { + continue; // Retry + } + status = PosixError(filename_, errno); + break; + } + *result = Slice(scratch, read_size); + break; + } + return status; + } + + Status Skip(uint64_t n) override { + if (::lseek(fd_, n, SEEK_CUR) == static_cast(-1)) { + return PosixError(filename_, errno); + } + return Status::OK(); + } + + private: + const int fd_; + const std::string filename_; +}; + +// Implements random read access in a file using pread(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixRandomAccessFile final : public RandomAccessFile { + public: + // The new instance takes ownership of |fd|. |fd_limiter| must outlive this + // instance, and will be used to determine if . + PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter) + : has_permanent_fd_(fd_limiter->Acquire()), + fd_(has_permanent_fd_ ? fd : -1), + fd_limiter_(fd_limiter), + filename_(std::move(filename)) { + if (!has_permanent_fd_) { + assert(fd_ == -1); + ::close(fd); // The file will be opened on every read. + } + } + + ~PosixRandomAccessFile() override { + if (has_permanent_fd_) { + assert(fd_ != -1); + ::close(fd_); + fd_limiter_->Release(); + } + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + int fd = fd_; + if (!has_permanent_fd_) { + fd = ::open(filename_.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename_, errno); + } + } + + assert(fd != -1); + + Status status; + ssize_t read_size = ::pread(fd, scratch, n, static_cast(offset)); + *result = Slice(scratch, (read_size < 0) ? 0 : read_size); + if (read_size < 0) { + // An error: return a non-ok status. + status = PosixError(filename_, errno); + } + if (!has_permanent_fd_) { + // Close the temporary file descriptor opened earlier. + assert(fd != fd_); + ::close(fd); + } + return status; + } + + private: + const bool has_permanent_fd_; // If false, the file is opened on every read. + const int fd_; // -1 if has_permanent_fd_ is false. + Limiter* const fd_limiter_; + const std::string filename_; +}; + +// Implements random read access in a file using mmap(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixMmapReadableFile final : public RandomAccessFile { + public: + // mmap_base[0, length-1] points to the memory-mapped contents of the file. It + // must be the result of a successful call to mmap(). This instances takes + // over the ownership of the region. + // + // |mmap_limiter| must outlive this instance. The caller must have already + // aquired the right to use one mmap region, which will be released when this + // instance is destroyed. + PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length, + Limiter* mmap_limiter) + : mmap_base_(mmap_base), + length_(length), + mmap_limiter_(mmap_limiter), + filename_(std::move(filename)) {} + + ~PosixMmapReadableFile() override { + ::munmap(static_cast(mmap_base_), length_); + mmap_limiter_->Release(); + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + if (offset + n > length_) { + *result = Slice(); + return PosixError(filename_, EINVAL); + } + + *result = Slice(mmap_base_ + offset, n); + return Status::OK(); + } + + private: + char* const mmap_base_; + const size_t length_; + Limiter* const mmap_limiter_; + const std::string filename_; +}; + +class PosixWritableFile final : public WritableFile { + public: + PosixWritableFile(std::string filename, int fd) + : pos_(0), + fd_(fd), + is_manifest_(IsManifest(filename)), + filename_(std::move(filename)), + dirname_(Dirname(filename_)) {} + + ~PosixWritableFile() override { + if (fd_ >= 0) { + // Ignoring any potential errors + Close(); + } + } + + Status Append(const Slice& data) override { + size_t write_size = data.size(); + const char* write_data = data.data(); + + // Fit as much as possible into buffer. + size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_); + std::memcpy(buf_ + pos_, write_data, copy_size); + write_data += copy_size; + write_size -= copy_size; + pos_ += copy_size; + if (write_size == 0) { + return Status::OK(); + } + + // Can't fit in buffer, so need to do at least one write. + Status status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + // Small writes go to buffer, large writes are written directly. + if (write_size < kWritableFileBufferSize) { + std::memcpy(buf_, write_data, write_size); + pos_ = write_size; + return Status::OK(); + } + return WriteUnbuffered(write_data, write_size); + } + + Status Close() override { + Status status = FlushBuffer(); + const int close_result = ::close(fd_); + if (close_result < 0 && status.ok()) { + status = PosixError(filename_, errno); + } + fd_ = -1; + return status; + } + + Status Flush() override { return FlushBuffer(); } + + Status Sync() override { + // Ensure new files referred to by the manifest are in the filesystem. + // + // This needs to happen before the manifest file is flushed to disk, to + // avoid crashing in a state where the manifest refers to files that are not + // yet on disk. + Status status = SyncDirIfManifest(); + if (!status.ok()) { + return status; + } + + status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + return SyncFd(fd_, filename_); + } + + private: + Status FlushBuffer() { + Status status = WriteUnbuffered(buf_, pos_); + pos_ = 0; + return status; + } + + Status WriteUnbuffered(const char* data, size_t size) { + while (size > 0) { + ssize_t write_result = ::write(fd_, data, size); + if (write_result < 0) { + if (errno == EINTR) { + continue; // Retry + } + return PosixError(filename_, errno); + } + data += write_result; + size -= write_result; + } + return Status::OK(); + } + + Status SyncDirIfManifest() { + Status status; + if (!is_manifest_) { + return status; + } + + int fd = ::open(dirname_.c_str(), O_RDONLY); + if (fd < 0) { + status = PosixError(dirname_, errno); + } else { + status = SyncFd(fd, dirname_); + ::close(fd); + } + return status; + } + + // Ensures that all the caches associated with the given file descriptor's + // data are flushed all the way to durable media, and can withstand power + // failures. + // + // The path argument is only used to populate the description string in the + // returned Status if an error occurs. + static Status SyncFd(int fd, const std::string& fd_path) { +#if HAVE_FULLFSYNC + // On macOS and iOS, fsync() doesn't guarantee durability past power + // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some + // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to + // fsync(). + if (::fcntl(fd, F_FULLFSYNC) == 0) { + return Status::OK(); + } +#endif // HAVE_FULLFSYNC + +#if HAVE_FDATASYNC + bool sync_success = ::fdatasync(fd) == 0; +#else + bool sync_success = ::fsync(fd) == 0; +#endif // HAVE_FDATASYNC + + if (sync_success) { + return Status::OK(); + } + return PosixError(fd_path, errno); + } + + // Returns the directory name in a path pointing to a file. + // + // Returns "." if the path does not contain any directory separator. + static std::string Dirname(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return std::string("."); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return filename.substr(0, separator_pos); + } + + // Extracts the file name from a path pointing to a file. + // + // The returned Slice points to |filename|'s data buffer, so it is only valid + // while |filename| is alive and unchanged. + static Slice Basename(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return Slice(filename); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return Slice(filename.data() + separator_pos + 1, + filename.length() - separator_pos - 1); + } + + // True if the given file is a manifest file. + static bool IsManifest(const std::string& filename) { + return Basename(filename).starts_with("MANIFEST"); + } + + // buf_[0, pos_ - 1] contains data to be written to fd_. + char buf_[kWritableFileBufferSize]; + size_t pos_; + int fd_; + + const bool is_manifest_; // True if the file's name starts with MANIFEST. + const std::string filename_; + const std::string dirname_; // The directory of filename_. +}; + +int LockOrUnlock(int fd, bool lock) { + errno = 0; + struct ::flock file_lock_info; + std::memset(&file_lock_info, 0, sizeof(file_lock_info)); + file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK); + file_lock_info.l_whence = SEEK_SET; + file_lock_info.l_start = 0; + file_lock_info.l_len = 0; // Lock/unlock entire file. + return ::fcntl(fd, F_SETLK, &file_lock_info); +} + +// Instances are thread-safe because they are immutable. +class PosixFileLock : public FileLock { + public: + PosixFileLock(int fd, std::string filename) + : fd_(fd), filename_(std::move(filename)) {} + + int fd() const { return fd_; } + const std::string& filename() const { return filename_; } + + private: + const int fd_; + const std::string filename_; +}; + +// Tracks the files locked by PosixEnv::LockFile(). +// +// We maintain a separate set instead of relying on fcntrl(F_SETLK) because +// fcntl(F_SETLK) does not provide any protection against multiple uses from the +// same process. +// +// Instances are thread-safe because all member data is guarded by a mutex. +class PosixLockTable { + public: + bool Insert(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + bool succeeded = locked_files_.insert(fname).second; + mu_.Unlock(); + return succeeded; + } + void Remove(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + locked_files_.erase(fname); + mu_.Unlock(); + } + + private: + port::Mutex mu_; + std::set locked_files_ GUARDED_BY(mu_); +}; + +class PosixEnv : public Env { + public: + PosixEnv(); + ~PosixEnv() override { + static char msg[] = "PosixEnv singleton destroyed. Unsupported behavior!\n"; + std::fwrite(msg, 1, sizeof(msg), stderr); + std::abort(); + } + + Status NewSequentialFile(const std::string& filename, + SequentialFile** result) override { + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixSequentialFile(filename, fd); + return Status::OK(); + } + + Status NewRandomAccessFile(const std::string& filename, + RandomAccessFile** result) override { + *result = nullptr; + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!mmap_limiter_.Acquire()) { + *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_); + return Status::OK(); + } + + uint64_t file_size; + Status status = GetFileSize(filename, &file_size); + if (status.ok()) { + void* mmap_base = + ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); + if (mmap_base != MAP_FAILED) { + *result = new PosixMmapReadableFile(filename, + reinterpret_cast(mmap_base), + file_size, &mmap_limiter_); + } else { + status = PosixError(filename, errno); + } + } + ::close(fd); + if (!status.ok()) { + mmap_limiter_.Release(); + } + return status; + } + + Status NewWritableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_TRUNC | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + Status NewAppendableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + bool FileExists(const std::string& filename) override { + return ::access(filename.c_str(), F_OK) == 0; + } + + Status GetChildren(const std::string& directory_path, + std::vector* result) override { + result->clear(); + ::DIR* dir = ::opendir(directory_path.c_str()); + if (dir == nullptr) { + return PosixError(directory_path, errno); + } + struct ::dirent* entry; + while ((entry = ::readdir(dir)) != nullptr) { + result->emplace_back(entry->d_name); + } + ::closedir(dir); + return Status::OK(); + } + + Status DeleteFile(const std::string& filename) override { + if (::unlink(filename.c_str()) != 0) { + return PosixError(filename, errno); + } + return Status::OK(); + } + + Status CreateDir(const std::string& dirname) override { + if (::mkdir(dirname.c_str(), 0755) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status DeleteDir(const std::string& dirname) override { + if (::rmdir(dirname.c_str()) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status GetFileSize(const std::string& filename, uint64_t* size) override { + struct ::stat file_stat; + if (::stat(filename.c_str(), &file_stat) != 0) { + *size = 0; + return PosixError(filename, errno); + } + *size = file_stat.st_size; + return Status::OK(); + } + + Status RenameFile(const std::string& from, const std::string& to) override { + if (std::rename(from.c_str(), to.c_str()) != 0) { + return PosixError(from, errno); + } + return Status::OK(); + } + + Status LockFile(const std::string& filename, FileLock** lock) override { + *lock = nullptr; + + int fd = ::open(filename.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!locks_.Insert(filename)) { + ::close(fd); + return Status::IOError("lock " + filename, "already held by process"); + } + + if (LockOrUnlock(fd, true) == -1) { + int lock_errno = errno; + ::close(fd); + locks_.Remove(filename); + return PosixError("lock " + filename, lock_errno); + } + + *lock = new PosixFileLock(fd, filename); + return Status::OK(); + } + + Status UnlockFile(FileLock* lock) override { + PosixFileLock* posix_file_lock = static_cast(lock); + if (LockOrUnlock(posix_file_lock->fd(), false) == -1) { + return PosixError("unlock " + posix_file_lock->filename(), errno); + } + locks_.Remove(posix_file_lock->filename()); + ::close(posix_file_lock->fd()); + delete posix_file_lock; + return Status::OK(); + } + + void Schedule(void (*background_work_function)(void* background_work_arg), + void* background_work_arg) override; + + void StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) override; + + Status GetTestDirectory(std::string* result) override { + const char* env = std::getenv("TEST_TMPDIR"); + if (env && env[0] != '\0') { + *result = env; + } else { + char buf[100]; + std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", + static_cast(::geteuid())); + *result = buf; + } + + // The CreateDir status is ignored because the directory may already exist. + CreateDir(*result); + + return Status::OK(); + } + + Status NewLogger(const std::string& filename, Logger** result) override { + std::FILE* fp = std::fopen(filename.c_str(), "w"); + if (fp == nullptr) { + *result = nullptr; + return PosixError(filename, errno); + } else { + *result = new PosixLogger(fp); + return Status::OK(); + } + } + + uint64_t NowMicros() override { + static constexpr uint64_t kUsecondsPerSecond = 1000000; + struct ::timeval tv; + ::gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec; + } + + void SleepForMicroseconds(int micros) override { ::usleep(micros); } + + private: + void BackgroundThreadMain(); + + static void BackgroundThreadEntryPoint(PosixEnv* env) { + env->BackgroundThreadMain(); + } + + // Stores the work item data in a Schedule() call. + // + // Instances are constructed on the thread calling Schedule() and used on the + // background thread. + // + // This structure is thread-safe beacuse it is immutable. + struct BackgroundWorkItem { + explicit BackgroundWorkItem(void (*function)(void* arg), void* arg) + : function(function), arg(arg) {} + + void (*const function)(void*); + void* const arg; + }; + + port::Mutex background_work_mutex_; + port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_); + bool started_background_thread_ GUARDED_BY(background_work_mutex_); + + std::queue background_work_queue_ + GUARDED_BY(background_work_mutex_); + + PosixLockTable locks_; // Thread-safe. + Limiter mmap_limiter_; // Thread-safe. + Limiter fd_limiter_; // Thread-safe. +}; + +// Return the maximum number of concurrent mmaps. +int MaxMmaps() { return g_mmap_limit; } + +// Return the maximum number of read-only files to keep open. +int MaxOpenFiles() { + if (g_open_read_only_file_limit >= 0) { + return g_open_read_only_file_limit; + } + struct ::rlimit rlim; + if (::getrlimit(RLIMIT_NOFILE, &rlim)) { + // getrlimit failed, fallback to hard-coded default. + g_open_read_only_file_limit = 50; + } else if (rlim.rlim_cur == RLIM_INFINITY) { + g_open_read_only_file_limit = std::numeric_limits::max(); + } else { + // Allow use of 20% of available file descriptors for read-only files. + g_open_read_only_file_limit = rlim.rlim_cur / 5; + } + return g_open_read_only_file_limit; +} + +} // namespace + +PosixEnv::PosixEnv() + : background_work_cv_(&background_work_mutex_), + started_background_thread_(false), + mmap_limiter_(MaxMmaps()), + fd_limiter_(MaxOpenFiles()) {} + +void PosixEnv::Schedule( + void (*background_work_function)(void* background_work_arg), + void* background_work_arg) { + background_work_mutex_.Lock(); + + // Start the background thread, if we haven't done so already. + if (!started_background_thread_) { + started_background_thread_ = true; + std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this); + background_thread.detach(); + } + + // If the queue is empty, the background thread may be waiting for work. + if (background_work_queue_.empty()) { + background_work_cv_.Signal(); + } + + background_work_queue_.emplace(background_work_function, background_work_arg); + background_work_mutex_.Unlock(); +} + +void PosixEnv::BackgroundThreadMain() { + while (true) { + background_work_mutex_.Lock(); + + // Wait until there is work to be done. + while (background_work_queue_.empty()) { + background_work_cv_.Wait(); + } + + assert(!background_work_queue_.empty()); + auto background_work_function = background_work_queue_.front().function; + void* background_work_arg = background_work_queue_.front().arg; + background_work_queue_.pop(); + + background_work_mutex_.Unlock(); + background_work_function(background_work_arg); + } +} + +namespace { + +// Wraps an Env instance whose destructor is never created. +// +// Intended usage: +// using PlatformSingletonEnv = SingletonEnv; +// void ConfigurePosixEnv(int param) { +// PlatformSingletonEnv::AssertEnvNotInitialized(); +// // set global configuration flags. +// } +// Env* Env::Default() { +// static PlatformSingletonEnv default_env; +// return default_env.env(); +// } +template +class SingletonEnv { + public: + SingletonEnv() { +#if !defined(NDEBUG) + env_initialized_.store(true, std::memory_order::memory_order_relaxed); +#endif // !defined(NDEBUG) + static_assert(sizeof(env_storage_) >= sizeof(EnvType), + "env_storage_ will not fit the Env"); + static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType), + "env_storage_ does not meet the Env's alignment needs"); + new (&env_storage_) EnvType(); + } + ~SingletonEnv() = default; + + SingletonEnv(const SingletonEnv&) = delete; + SingletonEnv& operator=(const SingletonEnv&) = delete; + + Env* env() { return reinterpret_cast(&env_storage_); } + + static void AssertEnvNotInitialized() { +#if !defined(NDEBUG) + assert(!env_initialized_.load(std::memory_order::memory_order_relaxed)); +#endif // !defined(NDEBUG) + } + + private: + typename std::aligned_storage::type + env_storage_; +#if !defined(NDEBUG) + static std::atomic env_initialized_; +#endif // !defined(NDEBUG) +}; + +#if !defined(NDEBUG) +template +std::atomic SingletonEnv::env_initialized_; +#endif // !defined(NDEBUG) + +using PosixDefaultEnv = SingletonEnv; + +} // namespace + +void PosixEnv::StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) { + std::thread new_thread(thread_main, thread_main_arg); + new_thread.detach(); +} + +void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_open_read_only_file_limit = limit; +} + +void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_mmap_limit = limit; +} + +Env* Env::Default() { + static PosixDefaultEnv env_container; + return env_container.env(); +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/env_posix_test_helper.h b/PediatricPancreas/Pods/leveldb-library/util/env_posix_test_helper.h new file mode 100644 index 0000000..0386960 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/env_posix_test_helper.h @@ -0,0 +1,28 @@ +// Copyright 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ + +namespace leveldb { + +class EnvPosixTest; + +// A helper for the POSIX Env to facilitate testing. +class EnvPosixTestHelper { + private: + friend class EnvPosixTest; + + // Set the maximum number of read-only files that will be opened. + // Must be called before creating an Env. + static void SetReadOnlyFDLimit(int limit); + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/env_windows_test_helper.h b/PediatricPancreas/Pods/leveldb-library/util/env_windows_test_helper.h new file mode 100644 index 0000000..e6f6020 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/env_windows_test_helper.h @@ -0,0 +1,25 @@ +// Copyright 2018 (c) The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ + +namespace leveldb { + +class EnvWindowsTest; + +// A helper for the Windows Env to facilitate testing. +class EnvWindowsTestHelper { + private: + friend class CorruptionTest; + friend class EnvWindowsTest; + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/filter_policy.cc b/PediatricPancreas/Pods/leveldb-library/util/filter_policy.cc new file mode 100644 index 0000000..90fd754 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/filter_policy.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +namespace leveldb { + +FilterPolicy::~FilterPolicy() {} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/hash.cc b/PediatricPancreas/Pods/leveldb-library/util/hash.cc new file mode 100644 index 0000000..67dc134 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/hash.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/hash.h" + +#include + +#include "util/coding.h" + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels. The real definition should be provided externally. +// This one is a fallback version for unsupported compilers. +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed) { + // Similar to murmur hash + const uint32_t m = 0xc6a4a793; + const uint32_t r = 24; + const char* limit = data + n; + uint32_t h = seed ^ (n * m); + + // Pick up four bytes at a time + while (data + 4 <= limit) { + uint32_t w = DecodeFixed32(data); + data += 4; + h += w; + h *= m; + h ^= (h >> 16); + } + + // Pick up remaining bytes + switch (limit - data) { + case 3: + h += static_cast(data[2]) << 16; + FALLTHROUGH_INTENDED; + case 2: + h += static_cast(data[1]) << 8; + FALLTHROUGH_INTENDED; + case 1: + h += static_cast(data[0]); + h *= m; + h ^= (h >> r); + break; + } + return h; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/hash.h b/PediatricPancreas/Pods/leveldb-library/util/hash.h new file mode 100644 index 0000000..74bdb6e --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/hash.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Simple hash function used for internal data structures + +#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ +#define STORAGE_LEVELDB_UTIL_HASH_H_ + +#include +#include + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/histogram.cc b/PediatricPancreas/Pods/leveldb-library/util/histogram.cc new file mode 100644 index 0000000..65092c8 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/histogram.cc @@ -0,0 +1,272 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/histogram.h" + +#include +#include + +#include "port/port.h" + +namespace leveldb { + +const double Histogram::kBucketLimit[kNumBuckets] = { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 12, + 14, + 16, + 18, + 20, + 25, + 30, + 35, + 40, + 45, + 50, + 60, + 70, + 80, + 90, + 100, + 120, + 140, + 160, + 180, + 200, + 250, + 300, + 350, + 400, + 450, + 500, + 600, + 700, + 800, + 900, + 1000, + 1200, + 1400, + 1600, + 1800, + 2000, + 2500, + 3000, + 3500, + 4000, + 4500, + 5000, + 6000, + 7000, + 8000, + 9000, + 10000, + 12000, + 14000, + 16000, + 18000, + 20000, + 25000, + 30000, + 35000, + 40000, + 45000, + 50000, + 60000, + 70000, + 80000, + 90000, + 100000, + 120000, + 140000, + 160000, + 180000, + 200000, + 250000, + 300000, + 350000, + 400000, + 450000, + 500000, + 600000, + 700000, + 800000, + 900000, + 1000000, + 1200000, + 1400000, + 1600000, + 1800000, + 2000000, + 2500000, + 3000000, + 3500000, + 4000000, + 4500000, + 5000000, + 6000000, + 7000000, + 8000000, + 9000000, + 10000000, + 12000000, + 14000000, + 16000000, + 18000000, + 20000000, + 25000000, + 30000000, + 35000000, + 40000000, + 45000000, + 50000000, + 60000000, + 70000000, + 80000000, + 90000000, + 100000000, + 120000000, + 140000000, + 160000000, + 180000000, + 200000000, + 250000000, + 300000000, + 350000000, + 400000000, + 450000000, + 500000000, + 600000000, + 700000000, + 800000000, + 900000000, + 1000000000, + 1200000000, + 1400000000, + 1600000000, + 1800000000, + 2000000000, + 2500000000.0, + 3000000000.0, + 3500000000.0, + 4000000000.0, + 4500000000.0, + 5000000000.0, + 6000000000.0, + 7000000000.0, + 8000000000.0, + 9000000000.0, + 1e200, +}; + +void Histogram::Clear() { + min_ = kBucketLimit[kNumBuckets - 1]; + max_ = 0; + num_ = 0; + sum_ = 0; + sum_squares_ = 0; + for (int i = 0; i < kNumBuckets; i++) { + buckets_[i] = 0; + } +} + +void Histogram::Add(double value) { + // Linear search is fast enough for our usage in db_bench + int b = 0; + while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) { + b++; + } + buckets_[b] += 1.0; + if (min_ > value) min_ = value; + if (max_ < value) max_ = value; + num_++; + sum_ += value; + sum_squares_ += (value * value); +} + +void Histogram::Merge(const Histogram& other) { + if (other.min_ < min_) min_ = other.min_; + if (other.max_ > max_) max_ = other.max_; + num_ += other.num_; + sum_ += other.sum_; + sum_squares_ += other.sum_squares_; + for (int b = 0; b < kNumBuckets; b++) { + buckets_[b] += other.buckets_[b]; + } +} + +double Histogram::Median() const { return Percentile(50.0); } + +double Histogram::Percentile(double p) const { + double threshold = num_ * (p / 100.0); + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + sum += buckets_[b]; + if (sum >= threshold) { + // Scale linearly within this bucket + double left_point = (b == 0) ? 0 : kBucketLimit[b - 1]; + double right_point = kBucketLimit[b]; + double left_sum = sum - buckets_[b]; + double right_sum = sum; + double pos = (threshold - left_sum) / (right_sum - left_sum); + double r = left_point + (right_point - left_point) * pos; + if (r < min_) r = min_; + if (r > max_) r = max_; + return r; + } + } + return max_; +} + +double Histogram::Average() const { + if (num_ == 0.0) return 0; + return sum_ / num_; +} + +double Histogram::StandardDeviation() const { + if (num_ == 0.0) return 0; + double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); + return sqrt(variance); +} + +std::string Histogram::ToString() const { + std::string r; + char buf[200]; + snprintf(buf, sizeof(buf), "Count: %.0f Average: %.4f StdDev: %.2f\n", num_, + Average(), StandardDeviation()); + r.append(buf); + snprintf(buf, sizeof(buf), "Min: %.4f Median: %.4f Max: %.4f\n", + (num_ == 0.0 ? 0.0 : min_), Median(), max_); + r.append(buf); + r.append("------------------------------------------------------\n"); + const double mult = 100.0 / num_; + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + if (buckets_[b] <= 0.0) continue; + sum += buckets_[b]; + snprintf(buf, sizeof(buf), "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ", + ((b == 0) ? 0.0 : kBucketLimit[b - 1]), // left + kBucketLimit[b], // right + buckets_[b], // count + mult * buckets_[b], // percentage + mult * sum); // cumulative percentage + r.append(buf); + + // Add hash marks based on percentage; 20 marks for 100%. + int marks = static_cast(20 * (buckets_[b] / num_) + 0.5); + r.append(marks, '#'); + r.push_back('\n'); + } + return r; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/histogram.h b/PediatricPancreas/Pods/leveldb-library/util/histogram.h new file mode 100644 index 0000000..4da60fb --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/histogram.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ +#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ + +#include + +namespace leveldb { + +class Histogram { + public: + Histogram() {} + ~Histogram() {} + + void Clear(); + void Add(double value); + void Merge(const Histogram& other); + + std::string ToString() const; + + private: + enum { kNumBuckets = 154 }; + + double Median() const; + double Percentile(double p) const; + double Average() const; + double StandardDeviation() const; + + static const double kBucketLimit[kNumBuckets]; + + double min_; + double max_; + double num_; + double sum_; + double sum_squares_; + + double buckets_[kNumBuckets]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/logging.cc b/PediatricPancreas/Pods/leveldb-library/util/logging.cc new file mode 100644 index 0000000..1ad8f1c --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/logging.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/logging.h" + +#include +#include +#include +#include + +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" + +namespace leveldb { + +void AppendNumberTo(std::string* str, uint64_t num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); + str->append(buf); +} + +void AppendEscapedStringTo(std::string* str, const Slice& value) { + for (size_t i = 0; i < value.size(); i++) { + char c = value[i]; + if (c >= ' ' && c <= '~') { + str->push_back(c); + } else { + char buf[10]; + snprintf(buf, sizeof(buf), "\\x%02x", + static_cast(c) & 0xff); + str->append(buf); + } + } +} + +std::string NumberToString(uint64_t num) { + std::string r; + AppendNumberTo(&r, num); + return r; +} + +std::string EscapeString(const Slice& value) { + std::string r; + AppendEscapedStringTo(&r, value); + return r; +} + +bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { + // Constants that will be optimized away. + constexpr const uint64_t kMaxUint64 = std::numeric_limits::max(); + constexpr const char kLastDigitOfMaxUint64 = + '0' + static_cast(kMaxUint64 % 10); + + uint64_t value = 0; + + // reinterpret_cast-ing from char* to unsigned char* to avoid signedness. + const unsigned char* start = + reinterpret_cast(in->data()); + + const unsigned char* end = start + in->size(); + const unsigned char* current = start; + for (; current != end; ++current) { + const unsigned char ch = *current; + if (ch < '0' || ch > '9') break; + + // Overflow check. + // kMaxUint64 / 10 is also constant and will be optimized away. + if (value > kMaxUint64 / 10 || + (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) { + return false; + } + + value = (value * 10) + (ch - '0'); + } + + *val = value; + const size_t digits_consumed = current - start; + in->remove_prefix(digits_consumed); + return digits_consumed != 0; +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/logging.h b/PediatricPancreas/Pods/leveldb-library/util/logging.h new file mode 100644 index 0000000..8ff2da8 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/logging.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Must not be included from any .h files to avoid polluting the namespace +// with macros. + +#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ +#define STORAGE_LEVELDB_UTIL_LOGGING_H_ + +#include +#include + +#include + +#include "port/port.h" + +namespace leveldb { + +class Slice; +class WritableFile; + +// Append a human-readable printout of "num" to *str +void AppendNumberTo(std::string* str, uint64_t num); + +// Append a human-readable printout of "value" to *str. +// Escapes any non-printable characters found in "value". +void AppendEscapedStringTo(std::string* str, const Slice& value); + +// Return a human-readable printout of "num" +std::string NumberToString(uint64_t num); + +// Return a human-readable version of "value". +// Escapes any non-printable characters found in "value". +std::string EscapeString(const Slice& value); + +// Parse a human-readable number from "*in" into *value. On success, +// advances "*in" past the consumed number and sets "*val" to the +// numeric value. Otherwise, returns false and leaves *in in an +// unspecified state. +bool ConsumeDecimalNumber(Slice* in, uint64_t* val); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/mutexlock.h b/PediatricPancreas/Pods/leveldb-library/util/mutexlock.h new file mode 100644 index 0000000..0cb2e25 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/mutexlock.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ +#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ + +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +// Helper class that locks a mutex on construction and unlocks the mutex when +// the destructor of the MutexLock object is invoked. +// +// Typical usage: +// +// void MyClass::MyMethod() { +// MutexLock l(&mu_); // mu_ is an instance variable +// ... some complex code, possibly with multiple return paths ... +// } + +class SCOPED_LOCKABLE MutexLock { + public: + explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + port::Mutex* const mu_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/no_destructor.h b/PediatricPancreas/Pods/leveldb-library/util/no_destructor.h new file mode 100644 index 0000000..a0d3b87 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/no_destructor.h @@ -0,0 +1,46 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ +#define STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ + +#include +#include + +namespace leveldb { + +// Wraps an instance whose destructor is never called. +// +// This is intended for use with function-level static variables. +template +class NoDestructor { + public: + template + explicit NoDestructor(ConstructorArgTypes&&... constructor_args) { + static_assert(sizeof(instance_storage_) >= sizeof(InstanceType), + "instance_storage_ is not large enough to hold the instance"); + static_assert( + alignof(decltype(instance_storage_)) >= alignof(InstanceType), + "instance_storage_ does not meet the instance's alignment requirement"); + new (&instance_storage_) + InstanceType(std::forward(constructor_args)...); + } + + ~NoDestructor() = default; + + NoDestructor(const NoDestructor&) = delete; + NoDestructor& operator=(const NoDestructor&) = delete; + + InstanceType* get() { + return reinterpret_cast(&instance_storage_); + } + + private: + typename std::aligned_storage::type instance_storage_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/options.cc b/PediatricPancreas/Pods/leveldb-library/util/options.cc new file mode 100644 index 0000000..62de5bf --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/options.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/options.h" + +#include "leveldb/comparator.h" +#include "leveldb/env.h" + +namespace leveldb { + +Options::Options() : comparator(BytewiseComparator()), env(Env::Default()) {} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/posix_logger.h b/PediatricPancreas/Pods/leveldb-library/util/posix_logger.h new file mode 100644 index 0000000..28e15d1 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/posix_logger.h @@ -0,0 +1,130 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class PosixLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~PosixLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + struct ::timeval now_timeval; + ::gettimeofday(&now_timeval, nullptr); + const std::time_t now_seconds = now_timeval.tv_sec; + struct std::tm now_components; + ::localtime_r(&now_seconds, &now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.tm_year + 1900, now_components.tm_mon + 1, + now_components.tm_mday, now_components.tm_hour, now_components.tm_min, + now_components.tm_sec, static_cast(now_timeval.tv_usec), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/random.h b/PediatricPancreas/Pods/leveldb-library/util/random.h new file mode 100644 index 0000000..76f7daf --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/random.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ +#define STORAGE_LEVELDB_UTIL_RANDOM_H_ + +#include + +namespace leveldb { + +// A very simple random number generator. Not especially good at +// generating truly random bits, but good enough for our needs in this +// package. +class Random { + private: + uint32_t seed_; + + public: + explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { + // Avoid bad seeds. + if (seed_ == 0 || seed_ == 2147483647L) { + seed_ = 1; + } + } + uint32_t Next() { + static const uint32_t M = 2147483647L; // 2^31-1 + static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64_t product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = static_cast((product >> 31) + (product & M)); + // The first reduction may overflow by 1 bit, so we may need to + // repeat. mod == M is not possible; using > allows the faster + // sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; + } + // Returns a uniformly distributed value in the range [0..n-1] + // REQUIRES: n > 0 + uint32_t Uniform(int n) { return Next() % n; } + + // Randomly returns true ~"1/n" of the time, and false otherwise. + // REQUIRES: n > 0 + bool OneIn(int n) { return (Next() % n) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with exponential bias towards smaller numbers. + uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/status.cc b/PediatricPancreas/Pods/leveldb-library/util/status.cc new file mode 100644 index 0000000..6ca8da6 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/status.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/status.h" + +#include + +#include "port/port.h" + +namespace leveldb { + +const char* Status::CopyState(const char* state) { + uint32_t size; + memcpy(&size, state, sizeof(size)); + char* result = new char[size + 5]; + memcpy(result, state, size + 5); + return result; +} + +Status::Status(Code code, const Slice& msg, const Slice& msg2) { + assert(code != kOk); + const uint32_t len1 = msg.size(); + const uint32_t len2 = msg2.size(); + const uint32_t size = len1 + (len2 ? (2 + len2) : 0); + char* result = new char[size + 5]; + memcpy(result, &size, sizeof(size)); + result[4] = static_cast(code); + memcpy(result + 5, msg.data(), len1); + if (len2) { + result[5 + len1] = ':'; + result[6 + len1] = ' '; + memcpy(result + 7 + len1, msg2.data(), len2); + } + state_ = result; +} + +std::string Status::ToString() const { + if (state_ == nullptr) { + return "OK"; + } else { + char tmp[30]; + const char* type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kNotFound: + type = "NotFound: "; + break; + case kCorruption: + type = "Corruption: "; + break; + case kNotSupported: + type = "Not implemented: "; + break; + case kInvalidArgument: + type = "Invalid argument: "; + break; + case kIOError: + type = "IO error: "; + break; + default: + snprintf(tmp, sizeof(tmp), + "Unknown code(%d): ", static_cast(code())); + type = tmp; + break; + } + std::string result(type); + uint32_t length; + memcpy(&length, state_, sizeof(length)); + result.append(state_ + 5, length); + return result; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/testharness.cc b/PediatricPancreas/Pods/leveldb-library/util/testharness.cc new file mode 100644 index 0000000..318ecfa --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/testharness.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testharness.h" + +#include +#include +#include + +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { +namespace test { + +namespace { +struct Test { + const char* base; + const char* name; + void (*func)(); +}; +std::vector* tests; +} // namespace + +bool RegisterTest(const char* base, const char* name, void (*func)()) { + if (tests == nullptr) { + tests = new std::vector; + } + Test t; + t.base = base; + t.name = name; + t.func = func; + tests->push_back(t); + return true; +} + +int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + + int num = 0; + if (tests != nullptr) { + for (size_t i = 0; i < tests->size(); i++) { + const Test& t = (*tests)[i]; + if (matcher != nullptr) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == nullptr) { + continue; + } + } + fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); + (*t.func)(); + ++num; + } + } + fprintf(stderr, "==== PASSED %d tests\n", num); + return 0; +} + +std::string TmpDir() { + std::string dir; + Status s = Env::Default()->GetTestDirectory(&dir); + ASSERT_TRUE(s.ok()) << s.ToString(); + return dir; +} + +int RandomSeed() { + const char* env = getenv("TEST_RANDOM_SEED"); + int result = (env != nullptr ? atoi(env) : 301); + if (result <= 0) { + result = 301; + } + return result; +} + +} // namespace test +} // namespace leveldb diff --git a/PediatricPancreas/Pods/leveldb-library/util/testharness.h b/PediatricPancreas/Pods/leveldb-library/util/testharness.h new file mode 100644 index 0000000..72cd162 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/testharness.h @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ +#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ + +#include +#include + +#include + +#include "leveldb/status.h" + +namespace leveldb { +namespace test { + +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// +// Returns 0 if all tests pass. +// Dies or returns a non-zero value if some test fails. +int RunAllTests(); + +// Return the directory to use for temporary storage. +std::string TmpDir(); + +// Return a randomization seed for this run. Typically returns the +// same number on repeated invocations of this binary, but automated +// runs may be able to vary the seed. +int RandomSeed(); + +// An instance of Tester is allocated to hold temporary state during +// the execution of an assertion. +class Tester { + private: + bool ok_; + const char* fname_; + int line_; + std::stringstream ss_; + + public: + Tester(const char* f, int l) : ok_(true), fname_(f), line_(l) {} + + ~Tester() { + if (!ok_) { + fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); + exit(1); + } + } + + Tester& Is(bool b, const char* msg) { + if (!b) { + ss_ << " Assertion failure " << msg; + ok_ = false; + } + return *this; + } + + Tester& IsOk(const Status& s) { + if (!s.ok()) { + ss_ << " " << s.ToString(); + ok_ = false; + } + return *this; + } + +#define BINARY_OP(name, op) \ + template \ + Tester& name(const X& x, const Y& y) { \ + if (!(x op y)) { \ + ss_ << " failed: " << x << (" " #op " ") << y; \ + ok_ = false; \ + } \ + return *this; \ + } + + BINARY_OP(IsEq, ==) + BINARY_OP(IsNe, !=) + BINARY_OP(IsGe, >=) + BINARY_OP(IsGt, >) + BINARY_OP(IsLe, <=) + BINARY_OP(IsLt, <) +#undef BINARY_OP + + // Attach the specified value to the error message if an error has occurred + template + Tester& operator<<(const V& value) { + if (!ok_) { + ss_ << " " << value; + } + return *this; + } +}; + +#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) +#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) +#define ASSERT_EQ(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a), (b)) +#define ASSERT_NE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a), (b)) +#define ASSERT_GE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a), (b)) +#define ASSERT_GT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a), (b)) +#define ASSERT_LE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a), (b)) +#define ASSERT_LT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a), (b)) + +#define TCONCAT(a, b) TCONCAT1(a, b) +#define TCONCAT1(a, b) a##b + +#define TEST(base, name) \ + class TCONCAT(_Test_, name) : public base { \ + public: \ + void _Run(); \ + static void _RunIt() { \ + TCONCAT(_Test_, name) t; \ + t._Run(); \ + } \ + }; \ + bool TCONCAT(_Test_ignored_, name) = ::leveldb::test::RegisterTest( \ + #base, #name, &TCONCAT(_Test_, name)::_RunIt); \ + void TCONCAT(_Test_, name)::_Run() + +// Register the specified test. Typically not used directly, but +// invoked via the macro expansion of TEST. +bool RegisterTest(const char* base, const char* name, void (*func)()); + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/testutil.h b/PediatricPancreas/Pods/leveldb-library/util/testutil.h new file mode 100644 index 0000000..bb4051b --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/testutil.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ +#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ + +#include "helpers/memenv/memenv.h" +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Store in *dst a random string of length "len" and return a Slice that +// references the generated data. +Slice RandomString(Random* rnd, int len, std::string* dst); + +// Return a random key with the specified length that may contain interesting +// characters (e.g. \x00, \xff, etc.). +std::string RandomKey(Random* rnd, int len); + +// Store in *dst a string of length "len" that will compress to +// "N*compressed_fraction" bytes and return a Slice that references +// the generated data. +Slice CompressibleString(Random* rnd, double compressed_fraction, size_t len, + std::string* dst); + +// A wrapper that allows injection of errors. +class ErrorEnv : public EnvWrapper { + public: + bool writable_file_error_; + int num_writable_file_errors_; + + ErrorEnv() + : EnvWrapper(NewMemEnv(Env::Default())), + writable_file_error_(false), + num_writable_file_errors_(0) {} + ~ErrorEnv() override { delete target(); } + + Status NewWritableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewWritableFile(fname, result); + } + + Status NewAppendableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewAppendableFile(fname, result); + } +}; + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/PediatricPancreas/Pods/leveldb-library/util/windows_logger.h b/PediatricPancreas/Pods/leveldb-library/util/windows_logger.h new file mode 100644 index 0000000..9296063 --- /dev/null +++ b/PediatricPancreas/Pods/leveldb-library/util/windows_logger.h @@ -0,0 +1,124 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation for the Windows platform. + +#ifndef STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class WindowsLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit WindowsLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~WindowsLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + SYSTEMTIME now_components; + ::GetLocalTime(&now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.wYear, now_components.wMonth, now_components.wDay, + now_components.wHour, now_components.wMinute, now_components.wSecond, + static_cast(now_components.wMilliseconds * 1000), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ diff --git a/PediatricPancreas/Pods/nanopb/LICENSE.txt b/PediatricPancreas/Pods/nanopb/LICENSE.txt new file mode 100644 index 0000000..d11c9af --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/PediatricPancreas/Pods/nanopb/README.md b/PediatricPancreas/Pods/nanopb/README.md new file mode 100644 index 0000000..07860f0 --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/README.md @@ -0,0 +1,71 @@ +Nanopb - Protocol Buffers for Embedded Systems +============================================== + +[![Build Status](https://travis-ci.org/nanopb/nanopb.svg?branch=master)](https://travis-ci.org/nanopb/nanopb) + +Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is +especially suitable for use in microcontrollers, but fits any memory +restricted system. + +* **Homepage:** https://jpa.kapsi.fi/nanopb/ +* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/ +* **Downloads:** https://jpa.kapsi.fi/nanopb/download/ +* **Forum:** https://groups.google.com/forum/#!forum/nanopb + + + +Using the nanopb library +------------------------ +To use the nanopb library, you need to do two things: + +1. Compile your .proto files for nanopb, using protoc. +2. Include pb_encode.c, pb_decode.c and pb_common.c in your project. + +The easiest way to get started is to study the project in "examples/simple". +It contains a Makefile, which should work directly under most Linux systems. +However, for any other kind of build system, see the manual steps in +README.txt in that folder. + + + +Using the Protocol Buffers compiler (protoc) +-------------------------------------------- +The nanopb generator is implemented as a plugin for the Google's own protoc +compiler. This has the advantage that there is no need to reimplement the +basic parsing of .proto files. However, it does mean that you need the +Google's protobuf library in order to run the generator. + +If you have downloaded a binary package for nanopb (either Windows, Linux or +Mac OS X version), the 'protoc' binary is included in the 'generator-bin' +folder. In this case, you are ready to go. Simply run this command: + + generator-bin/protoc --nanopb_out=. myprotocol.proto + +However, if you are using a git checkout or a plain source distribution, you +need to provide your own version of protoc and the Google's protobuf library. +On Linux, the necessary packages are protobuf-compiler and python-protobuf. +On Windows, you can either build Google's protobuf library from source or use +one of the binary distributions of it. In either case, if you use a separate +protoc, you need to manually give the path to nanopb generator: + + protoc --plugin=protoc-gen-nanopb=nanopb/generator/protoc-gen-nanopb ... + + + +Running the tests +----------------- +If you want to perform further development of the nanopb core, or to verify +its functionality using your compiler and platform, you'll want to run the +test suite. The build rules for the test suite are implemented using Scons, +so you need to have that installed. To run the tests: + + cd tests + scons + +This will show the progress of various test cases. If the output does not +end in an error, the test cases were successful. + +Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually +supporting the same command line options as gcc does. To run tests on +Mac OS X, use: "scons CC=clang CXX=clang". Same way can be used to run +tests with different compilers on any platform. diff --git a/PediatricPancreas/Pods/nanopb/pb.h b/PediatricPancreas/Pods/nanopb/pb.h new file mode 100644 index 0000000..174a84b --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb.h @@ -0,0 +1,593 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.3.9.1 + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#else +#define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x04 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x05 + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x06 + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x07 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x08 + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0A +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside an union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. + */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for repeated static fixed count fields.*/ +#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + 0, \ + pb_membersize(message, field[0]), \ + pb_arraysize(message, field), ptr} + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#endif diff --git a/PediatricPancreas/Pods/nanopb/pb_common.c b/PediatricPancreas/Pods/nanopb/pb_common.c new file mode 100644 index 0000000..4fb7186 --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_common.c @@ -0,0 +1,97 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + { + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos++; + + if (iter->pos->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } + else + { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && + iter->pos->data_offset == PB_SIZE_MAX) + { + /* Don't advance pointers inside unions */ + return true; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + { + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + { + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + { + /* Found the wanted field */ + return true; + } + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + + diff --git a/PediatricPancreas/Pods/nanopb/pb_common.h b/PediatricPancreas/Pods/nanopb/pb_common.h new file mode 100644 index 0000000..60b3d37 --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_common.h @@ -0,0 +1,42 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/PediatricPancreas/Pods/nanopb/pb_decode.c b/PediatricPancreas/Pods/nanopb/pb_decode.c new file mode 100644 index 0000000..4b80e81 --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_decode.c @@ -0,0 +1,1508 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) + { + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + (*size)++; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)iter->pSize; + char *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + + if ((*size)++ >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(pItem, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + } + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = iter->pos->tag; + } + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + { + return func(stream, iter->pos, iter->pData); + } + else + { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, iter->pos, *(void**)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1; + + if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size)) + return false; + + pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)iter->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)iter->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData); + } + else if (iter->pos->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + } + else + { + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + const pb_field_t *fixed_count_field = NULL; + pb_size_t fixed_count_size = 0; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED + && iter.pSize == iter.pData) + { + if (fixed_count_field != iter.pos) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.pos; + fixed_count_size = 0; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned req_field_count; + pb_type_t last_type; + unsigned i; + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_noinit(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + pItem = *(void**)iter->pData; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) { + /* No _count field so use size of the array */ + count = iter->pos->array_size; + } else { + count = *(pb_size_t*)iter->pSize; + } + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + { + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } + } + + if (pItem) + { + while (count--) + { + pb_release((const pb_field_t*)iter->pos->ptr, pItem); + pItem = (char*)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)iter->pSize = 0; + } + + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} +#endif + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t*)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(dest, 0, field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)dest, field->data_size); +} diff --git a/PediatricPancreas/Pods/nanopb/pb_decode.h b/PediatricPancreas/Pods/nanopb/pb_decode.h new file mode 100644 index 0000000..398b24a --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_decode.h @@ -0,0 +1,175 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PediatricPancreas/Pods/nanopb/pb_encode.c b/PediatricPancreas/Pods/nanopb/pb_encode.c new file mode 100644 index 0000000..089172c --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_encode.c @@ -0,0 +1,869 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t + +static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; + size_t size; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + p = pData; + for (i = 0; i < count; i++) + { + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) + { + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + } + else + { + p = pData; + for (i = 0; i < count; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + if (!func(stream, field, *(const void* const*)p)) + return false; + } + else + { + if (!func(stream, field, p)) + return false; + } + p = (const char*)p + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) +{ + pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) + { + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool*)pSize == false; + } + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) + { + do + { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + { + /* Static optional, repeated or oneof field */ + pSize = (const char*)pData + field->size_offset; + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + } + else + { + /* Required field, always present */ + implicit_has = true; + } + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool*)pSize) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: { + pb_size_t count; + if (field->size_offset != 0) { + count = *(const pb_size_t*)pSize; + } else { + count = field->array_size; + } + if (!encode_array(stream, field, pData, count, func)) + return false; + break; + } + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) + { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); + } + else + { + return encode_field(stream, field, extension->dest); + } +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +#ifdef PB_WITHOUT_64BIT +bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + if (compensation) + { + /* re-set all the compensation bits we can or need */ + size_t bits = compensation > 7 ? 7 : compensation; + value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */ + compensation -= bits; + } + i++; + } + buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} +#endif + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) + { + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); + } + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + +#ifdef PB_WITHOUT_64BIT + if (value < 0) + return pb_encode_negative_varint(stream, (pb_uint64_t)value); + else +#endif + return pb_encode_varint(stream, (pb_uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)src; + + if (src == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char*)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t*)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); +} + diff --git a/PediatricPancreas/Pods/nanopb/pb_encode.h b/PediatricPancreas/Pods/nanopb/pb_encode.h new file mode 100644 index 0000000..8bf78dd --- /dev/null +++ b/PediatricPancreas/Pods/nanopb/pb_encode.h @@ -0,0 +1,170 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PediatricPancreas_Storyboard/.DS_Store b/PediatricPancreas_Storyboard/.DS_Store new file mode 100644 index 0000000..67b1926 Binary files /dev/null and b/PediatricPancreas_Storyboard/.DS_Store differ diff --git a/PediatricPancreas_Storyboard/.gitignore b/PediatricPancreas_Storyboard/.gitignore new file mode 100644 index 0000000..b956c19 --- /dev/null +++ b/PediatricPancreas_Storyboard/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +.DS_Store? + +#Cocoapods +Pods diff --git a/PediatricPancreas_Storyboard/CareKit-master/.gitignore b/PediatricPancreas_Storyboard/CareKit-master/.gitignore new file mode 100755 index 0000000..8ff16c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/.gitignore @@ -0,0 +1,26 @@ +# Xcode +# +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +.DS_Store +*.pyc +*.xcscmblueprint + +# SPM +.build/ \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/.travis.yml b/PediatricPancreas_Storyboard/CareKit-master/.travis.yml new file mode 100755 index 0000000..9342599 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/.travis.yml @@ -0,0 +1,5 @@ +language: swift +osx_image: xcode11 +xcode_workspace: CKWorkspace.xcworkspace +xcode_scheme: CareKit +xcode_destination: platform=iOS Simulator,OS=13.0,name=iPhone 11 Pro Max diff --git a/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..cf91e94 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDETemplateMacros.plist b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDETemplateMacros.plist new file mode 100755 index 0000000..58f0593 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDETemplateMacros.plist @@ -0,0 +1,37 @@ + + + + + FILEHEADER + +/* + Copyright (c) ___YEAR___, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 0000000..f9b0d7c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CKWorkspace.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CONTRIBUTING.md b/PediatricPancreas_Storyboard/CareKit-master/CONTRIBUTING.md new file mode 100755 index 0000000..7238ef3 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CONTRIBUTING.md @@ -0,0 +1,171 @@ +Contributing to the CareKit Framework +=========================== + +This page focuses on code contributions to the existing +codebase. However, other types of contributions are welcome too, in +keeping with the CareKit™ framework [best practices](../../wiki/Best-Practices). + + +Contributing software +--------------------- + +This page assumes you already know how to check out and build the +code. Contributions to the CareKit framework are expected to comply with the +[CareKit Contribution Terms and License Policy](#contribution); please familiarize yourself +with this policy prior to submitting a pull request. For any contribution, ensure that you own +the rights or have permission from the copyright holder. (e.g. code, images, surveys, videos +and other content you may include) + +To contribute to CareKit: + +1. [Choose or create an issue to work on.](#create) +2. [Create a personal fork of the CareKit framework.](#fork) +3. [Develop your changes in your fork.](#develop) +4. [Run the unit tests.](#test) +5. [Submit a pull request.](#request) +6. Make any changes requested by the reviewer, and update your pull request as needed. +7. Once accepted, your pull request will be merged into master. + +Choosing an issue to work on +---------------------------- + +To find an issue to work on, either pick something that you need for +your app, or select one of the issues from our [issue list](../../issues). + +If in doubt, bring your idea up on [Issues](../../issues). + +Creating a personal fork +------------------------ + +On GitHub, it's easy to create a personal fork. Just tap the "Fork" +button on the top right, and clone your new repository. + + +Develop your changes in your fork +--------------------------------- + +Develop your changes using your normal development process. If you +already have code from an existing project, you may need to adjust its +style to more closely match the coding style. + +New components may need to expose new public or internal methods or properties. +Use public access level for APIs that are likely to be a stable +part of the interface of the CareKit framework. Private and internal access levels +are for APIs that are only leveraged internally to the framework. + +Please review and ensure that any contributions you make comply with +the [CareKit Contribution Terms and License Policy](#contribution). + +Add automated tests for your feature, where it is possible to do +so. For UI driven components where it is harder to write automated +tests, add UI to at least one test application so that the new +features can be reviewed and tested. Consider also whether to add new +code to other existing demo apps to exercise your feature. + +When adding UI driven components, make sure that they are accessible. +Follow the steps outlined in the [Best Practices](../../wiki/Best-Practices) +section under Accessibility. Before submitting the pull request, you should +audit your components with Voice Over (or other relevant assistive technologies) +enabled. + +Keep changes that fix different issues separate. For bug fixes, +separate bugs should be submitted as separate pull requests. A good +way to do this is to create a new branch in your fork for each new +bug work on. + +Any new user-visible strings should be included in the English +`CareKit.strings` table so that they can be picked up and +localized in the next release cycle. + + +Run the tests +------------- + +All unit tests should pass, and there should be no warnings. Also +verify that test apps run on both device and simulator. + +Where your code affects UI presentation, also test: + +* Multiple device form factors (for instance, iPhone 4S, iPhone 5, iPhone 6, iPhone 6 Plus). +* Dynamic text, especially at the "Large" setting. +* Rotation between portrait and landscape, where appropriate. + +You can use the apps in the `Testing` and `samples` directories to +test your changes. + +Submit a pull request +--------------------- + +The reviewers may request changes. Make the changes, and update your +pull request as needed. Reviews will focus on coding style, +correctness, and design consistency. + +After acceptance +---------------- + +Once your pull request has been accepted, your changes will be merged +to master. You are still responsible for your change after it is +accepted. Stay in contact, in case bugs are detected that may require +your attention. + +When the project is next branched for release, your changes will be +incorporated. Queries may come back to you regarding localization, +documentation, or other issues during this process. + + + + +Release process +----------------- + +The `master` branch is used for work in progress. On `master`: + +* All test apps should build and run error free. +* Unit tests should all pass. +* Everything should be continuously in working order in English (the + base language). + + The project will make periodic releases. When preparing a stable release, we + will branch from `master` to a convergence branch. During this process, + changes will be made first to the convergence branch, and then merged into + `master`. On the convergence branch, changes will be made only to: + + * Fix high priority issues. + * Update documentation. + * Bring localization up to date. + * Ensure good behavior across all supported devices. + + After the converging process is completed, we will merge everything to the + `stable` branch and tag with a new release number. The most recent release + will be highlighted in the [README](../..). + + +CareKit Contribution Terms and License Policy +======================================= + + Thank you for your interest in contributing to the CareKit + community. In order to maintain consistency and license compatibility + throughout the project, all contributions must comply with our + licensing policy and terms for contributing code to the CareKit + project: + + 1. If you are submitting a patch to the existing codebase, you + represent that you have the right to license the patch, including + all code and content, to Apple and the community, and agree by + submitting the patch that your changes are + licensed under the existing license terms of the file you are + modifying (i.e., [CareKit BSD license](LICENSE)). + You confirm that you have added your copyright (name and year) to + the relevant files for changes that are more than 10 lines of code. + 2. If you are submitting a new file for inclusion in the CareKit + framework (no code or other content is copied from another source), you + have included your copyright (name and year) and a copy of the CareKit + BSD license. By submitting your new file you represent that you have the + right to license your file to Apple and the community, and agree that your + file submission is licensed under the CareKit BSD license. + 3. If you aren't the author of the patch, you agree that you have + the right to submit the patch, and have included the original copyright + notices and licensing terms with it, to the extent that they exist. + If there wasn't a copyright notice or license, please make a note of it + in your response. Generally we can only take in patches that are + BSD-licensed in order to maintain license compatibility within the project. diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit.xctestplan b/PediatricPancreas_Storyboard/CareKit-master/CareKit.xctestplan new file mode 100755 index 0000000..8a33777 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit.xctestplan @@ -0,0 +1,143 @@ +{ + "configurations" : [ + { + "id" : "28C2AC89-B957-4FB0-9242-53AEB9E6D4B0", + "name" : "Default", + "options" : { + + } + }, + { + "id" : "42D7C666-B3E1-4F36-88FB-E0B87436BB05", + "name" : "Germany", + "options" : { + "language" : "de", + "locationScenario" : { + "identifier" : "London, England", + "referenceType" : "built-in" + }, + "region" : "DE" + } + }, + { + "id" : "76269B8E-AEA1-4864-AA9A-F583B2F54AF1", + "name" : "Africa", + "options" : { + "locationScenario" : { + "identifier" : "Johannesburg, South Africa", + "referenceType" : "built-in" + }, + "region" : "EG" + } + }, + { + "id" : "34F9B126-5A5C-4F0A-A861-84C9B2376FA2", + "name" : "Australia", + "options" : { + "language" : "en-AU", + "locationScenario" : { + "identifier" : "Sydney, Australia", + "referenceType" : "built-in" + }, + "region" : "AU" + } + }, + { + "id" : "05B1E279-40AF-49C6-8BAC-86779932468D", + "name" : "England", + "options" : { + "language" : "en-GB", + "locationScenario" : { + "identifier" : "London, England", + "referenceType" : "built-in" + }, + "region" : "GB" + } + }, + { + "id" : "F4D2A746-C1E8-4D5A-BCD7-EEEC3D73CEC5", + "name" : "Japan", + "options" : { + "language" : "ja", + "locationScenario" : { + "identifier" : "Tokyo, Japan", + "referenceType" : "built-in" + }, + "region" : "JP" + } + }, + { + "id" : "4DB57CAB-36AB-4D1A-8259-C918197191CE", + "name" : "Hong Kong", + "options" : { + "language" : "zh-HK", + "locationScenario" : { + "identifier" : "Hong Kong, China", + "referenceType" : "built-in" + }, + "region" : "HK" + } + }, + { + "id" : "2DEE87AE-1E91-4B64-BA06-8B37298B2A16", + "name" : "Mexico", + "options" : { + "language" : "es-419", + "locationScenario" : { + "identifier" : "Mexico City, Mexico", + "referenceType" : "built-in" + }, + "region" : "MX" + } + } + ], + "defaultOptions" : { + "codeCoverage" : { + "targets" : [ + { + "containerPath" : "container:CareKit.xcodeproj", + "identifier" : "8605A5B91C4F04EC00DD65FF", + "name" : "CareKit" + }, + { + "containerPath" : "container:CareKitCarePlanStore\/CareKitCarePlanStore.xcodeproj", + "identifier" : "E784B8F72232EED600736CA5", + "name" : "CareKitStore" + } + ] + }, + "targetForVariableExpansion" : { + "containerPath" : "container:CareKit.xcodeproj", + "identifier" : "8605A5B91C4F04EC00DD65FF", + "name" : "CareKit" + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:CareKit.xcodeproj", + "identifier" : "5196C7F8226F8F8F00F1C2A2", + "name" : "CareKitTests" + } + }, + { + "skippedTests" : [ + "TestSchedule\/testEventGenerationPerformanceBasicSchedule()", + "TestSchedule\/testEventGenerationPerformanceHeavySchedule()" + ], + "target" : { + "containerPath" : "container:..\/CareKitStore\/CareKitStore.xcodeproj", + "identifier" : "E784B9002232EED600736CA5", + "name" : "CareKitStoreTests" + } + }, + { + "target" : { + "containerPath" : "container:..\/CareKitUI\/CareKitUI.xcodeproj", + "identifier" : "512B012D22C2F82900ABCB1D", + "name" : "CareKitUITests" + } + } + ], + "version" : 1 +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/CareKit.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/CareKit.swift new file mode 100755 index 0000000..dbd3439 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/CareKit.swift @@ -0,0 +1,32 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@_exported import CareKitStore +@_exported import CareKitUI diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Details/OCKDetailViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Details/OCKDetailViewController.swift new file mode 100755 index 0000000..a1294f4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Details/OCKDetailViewController.swift @@ -0,0 +1,62 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitUI +import UIKit + +/// A view controller that can be customized to display the details of another view. +/// The detail view's content stack view can be populated with arbitrary content. +open class OCKDetailViewController: UIViewController { + private lazy var doneButton: UIBarButtonItem = { + let item = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissViewController)) + return item + }() + + /// A detailed content view. + public var detailView: OCKDetailView { + guard let view = view as? OCKDetailView else { fatalError("Unsupported view.") } + return view + } + + @available(*, unavailable) + override open func loadView() { + view = OCKDetailView() + } + + override open func viewDidLoad() { + super.viewDidLoad() + navigationItem.rightBarButtonItem = doneButton + } + + @objc + private func dismissViewController() { + dismiss(animated: true, completion: nil) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/Calendar+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/Calendar+Extensions.swift new file mode 100755 index 0000000..b1bf554 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/Calendar+Extensions.swift @@ -0,0 +1,71 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension Calendar { + + /// Returns a date interval that spans the entire week of the given date. The difference between this method and the + /// Foundation `Calendar.dateInterval(of:for:)` method is that this method produces non-overlapping + /// intervals. + func dateIntervalOfWeek(for date: Date) -> DateInterval { + var interval = Calendar.current.dateInterval(of: .weekOfYear, for: date)! + interval.duration -= 1 // The default interval contains 1 second of the next day after the interval. Subtract that off + return interval + } + + /// Returns string representations of the weekdays, in the order the weekdays occur on the local calendar. + /// This differs with the Foundation `Calendar.veryShortWeekdaySymbols` in that the ordering is changed such + /// that the first element of the array corresponds to the first weekday in the current locale, instead of Sunday. + /// + /// This method is required for handling certain regions in which the first day of the week is Monday. + func orderedWeekdaySymbolsVeryShort() -> [String] { + var symbols = veryShortWeekdaySymbols + Array(1.. [String] { + var symbols = weekdaySymbols + Array(1.. NSLayoutConstraint { + priority = new + return self + } +} + +extension UIView { + func setContentHuggingPriorities(_ new: UILayoutPriority) { + setContentHuggingPriority(new, for: .horizontal) + setContentHuggingPriority(new, for: .vertical) + } + + func setContentCompressionResistancePriorities(_ new: UILayoutPriority) { + setContentCompressionResistancePriority(new, for: .horizontal) + setContentCompressionResistancePriority(new, for: .vertical) + } + + func constraints(equalTo other: UIView, directions: LayoutDirection = .all, + priority: UILayoutPriority = .required) -> [NSLayoutConstraint] { + var constraints: [NSLayoutConstraint] = [] + if directions.contains(.top) { + constraints.append(topAnchor.constraint(equalTo: other.topAnchor).withPriority(priority)) + } + if directions.contains(.leading) { + constraints.append(leadingAnchor.constraint(equalTo: other.leadingAnchor).withPriority(priority)) + } + if directions.contains(.bottom) { + constraints.append(bottomAnchor.constraint(equalTo: other.bottomAnchor).withPriority(priority)) + } + if directions.contains(.trailing) { + constraints.append(trailingAnchor.constraint(equalTo: other.trailingAnchor).withPriority(priority)) + } + return constraints + } + + func constraints(equalTo layoutGuide: UILayoutGuide, directions: LayoutDirection = .all, + priority: UILayoutPriority = .required) -> [NSLayoutConstraint] { + var constraints: [NSLayoutConstraint] = [] + if directions.contains(.top) { + constraints.append(topAnchor.constraint(equalTo: layoutGuide.topAnchor).withPriority(priority)) + } + if directions.contains(.leading) { + constraints.append(leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).withPriority(priority)) + } + if directions.contains(.bottom) { + constraints.append(bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).withPriority(priority)) + } + if directions.contains(.trailing) { + constraints.append(trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).withPriority(priority)) + } + return constraints + } + + var isRightToLeft: Bool { + return UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKAnyEvent+Extension.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKAnyEvent+Extension.swift new file mode 100755 index 0000000..db17a0e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKAnyEvent+Extension.swift @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension OCKAnyEvent { + + /// Sort outcome values by descending updated/created date + func sortedOutcomeValuesByRecency() -> OCKAnyEvent { + guard + var newOutcome = outcome, + !newOutcome.values.isEmpty else { return self } + + let sortedValues = newOutcome.values.sorted { + guard + let date1 = $0.updatedDate ?? $0.createdDate, + let date2 = $1.updatedDate ?? $0.createdDate else { return false } + return date1 > date2 + } + + newOutcome.values = sortedValues + return OCKAnyEvent(task: task, outcome: newOutcome, scheduleEvent: scheduleEvent) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKContact+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKContact+Extensions.swift new file mode 100755 index 0000000..59955d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/OCKContact+Extensions.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Contacts +import Foundation + +private extension OCKLabeledValue { + func toLabeledString() -> CNLabeledValue { CNLabeledValue(label: label, value: NSString(string: value)) } + func toLabeledPhoneNumber() -> CNLabeledValue { CNLabeledValue(label: label, value: CNPhoneNumber(stringValue: label)) } +} + +private extension OCKPostalAddress { + func toCNLabeledValue() -> CNLabeledValue { CNLabeledValue(label: "", value: self) } +} + + +extension CNMutableContact { + convenience init(from contact: OCKAnyContact) { + self.init() + if let value = contact.organization { organizationName = value } + if let value = contact.phoneNumbers { phoneNumbers = value.map { $0.toLabeledPhoneNumber() } } + if let value = contact.address { postalAddresses = [value.toCNLabeledValue()] } + if let value = contact.emailAddresses { emailAddresses = value.map { $0.toLabeledString() } } + if let value = contact.title { jobTitle = value } + if let value = contact.role { note = value } + if let value = contact.organization { departmentName = value } + if let value = contact.emailAddresses { emailAddresses = value.map { $0.toLabeledString() } } + if let value = contact.name.familyName { familyName = value } + if let value = contact.name.givenName { givenName = value } + if let value = contact.name.middleName { middleName = value } + if let value = contact.name.namePrefix { namePrefix = value } + if let value = contact.name.nameSuffix { nameSuffix = value } + if let value = contact.name.nickname { nickname = value } + + if let value = contact.name.phoneticRepresentation?.familyName { phoneticFamilyName = value } + if let value = contact.name.phoneticRepresentation?.givenName { phoneticGivenName = value } + if let value = contact.name.phoneticRepresentation?.middleName { phoneticMiddleName = value } + } +} + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/UIViewController+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/UIViewController+Extensions.swift new file mode 100755 index 0000000..0d8809f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Extensions/UIViewController+Extensions.swift @@ -0,0 +1,52 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitUI +import UIKit + +internal extension UIViewController { + func clearContainment() { + willMove(toParent: nil) + removeFromParent() + view.removeFromSuperview() + } + + func setupContainment(in containerViewController: UIViewController, stackView: OCKStackView, animated: Bool = false) { + containerViewController.addChild(self) + stackView.addArrangedSubview(view, animated: animated) + didMove(toParent: containerViewController) + } + + func setupContainment(in containerViewController: UIViewController, stackView: OCKStackView, at index: Int, animated: Bool = false) { + containerViewController.addChild(self) + stackView.insertArrangedSubview(view, at: index, animated: animated) + didMove(toParent: containerViewController) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Info.plist new file mode 100755 index 0000000..602d864 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKContactsListViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKContactsListViewController.swift new file mode 100755 index 0000000..bd7ef97 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKContactsListViewController.swift @@ -0,0 +1,110 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import Foundation + +/// Classes that conform to this protocol can recieve updates about the state of +/// the `OCKContactsListViewControllerDelegate`. +public protocol OCKContactsListViewControllerDelegate: AnyObject { + func contactsListViewController(_ viewController: OCKContactsListViewController, didEncounterError: Error) +} + +/// An `OCKListViewController` that automatically queries and displays contacts in the `Store` using +/// `OCKDetailedContactViewController`s. +open class OCKContactsListViewController: OCKListViewController { + + // MARK: Properties + + /// The manager of the `Store` from which the `Contact` data is fetched. + public let storeManager: OCKSynchronizedStoreManager + + /// If set, the delegate will receive callbacks when important events happen at the list view controller level. + public weak var delegate: OCKContactsListViewControllerDelegate? + + /// If set, the delegate will receive callbacks when important events happen inside the contact view controllers. + public weak var contactDelegate: OCKContactViewControllerDelegate? + + private var subscription: Cancellable? + + // MARK: - Life Cycle + + /// Initialize using a store manager. All of the contacts in the store manager will be queried and dispalyed. + /// + /// - Parameters: + /// - storeManager: The store manager owning the store whose contacts should be displayed. + public init(storeManager: OCKSynchronizedStoreManager) { + self.storeManager = storeManager + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func viewDidLoad() { + super.viewDidLoad() + navigationController?.navigationBar.prefersLargeTitles = true + title = loc("CONTACTS") + subscribe() + fetchContacts() + } + + // MARK: - Methods + + private func subscribe() { + subscription?.cancel() + subscription = storeManager.contactsPublisher(categories: [.add, .update]).sink { _ in + self.fetchContacts() + } + } + + /// `fetchContacts` asynchronously retrieves an array of contacts stored in a `Result` + /// and makes corresponding `OCKDetailedContactViewController`s. + private func fetchContacts() { + storeManager.store.fetchAnyContacts(query: OCKContactQuery(), callbackQueue: .main) { [weak self] result in + guard let self = self else { return } + switch result { + case .failure(let error): + self.delegate?.contactsListViewController(self, didEncounterError: error) + case .success(let contacts): + self.clear() + for contact in contacts { + let contactViewController = OCKDetailedContactViewController(contact: contact, storeManager: self.storeManager) + contactViewController.delegate = self.contactDelegate + self.appendViewController(contactViewController, animated: false) + } + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyPageViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyPageViewController.swift new file mode 100755 index 0000000..7939b3c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyPageViewController.swift @@ -0,0 +1,262 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Conform to this protocol to receive callbacks when important events occur in an `OCKDailyPageViewController`. +public protocol OCKDailyPageViewControllerDelegate: AnyObject { + /// This method will be called anytime an unhandled error is encountered. + /// + /// - Parameters: + /// - dailyPageViewController: The daily page view controller in which the error occurred. + /// - error: The error that occurred + func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, didFailWithError error: Error) +} + +public extension OCKDailyPageViewControllerDelegate { + /// This method will be called anytime an unhandled error is encountered. + /// + /// - Parameters: + /// - dailyPageViewController: The daily page view controller in which the error occurred. + /// - error: The error that occurred + func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, didFailWithError error: Error) {} +} + +/// Any class that can provide content for an `OCKDailyPageViewController` should conform to this protocol. +public protocol OCKDailyPageViewControllerDataSource: AnyObject { + /// - Parameters: + /// - dailyPageViewController: The daily page view controller for which content should be provided. + /// - listViewController: The list view controller that should be populated with content. + /// - date: A date that should be used to determine what content to insert into the list view controller. + func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, + prepare listViewController: OCKListViewController, for date: Date) +} + +/// Displays a calendar page view controller in the header, and a view controllers in the body. The view controllers must +/// be manually queried and set from outside of the class. +open class OCKDailyPageViewController: UIViewController, +OCKDailyPageViewControllerDataSource, OCKDailyPageViewControllerDelegate, OCKWeekCalendarPageViewControllerDelegate, +UIPageViewControllerDataSource, UIPageViewControllerDelegate { + + // MARK: Properties + + public weak var dataSource: OCKDailyPageViewControllerDataSource? + public weak var delegate: OCKDailyPageViewControllerDelegate? + + public var selectedDate: Date { + return calendarWeekPageViewController.selectedDate + } + + /// The store manager the view controller uses for synchronization + public let storeManager: OCKSynchronizedStoreManager + + /// Page view managing ListViewControllers. + private let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) + + /// The calendar view controller in the header. + private let calendarWeekPageViewController: OCKWeekCalendarPageViewController + + // MARK: - Life cycle + + /// Create an instance of the view controller. Will hook up the calendar to the tasks collection, + /// and query and display the tasks. + /// + /// - Parameter storeManager: The store from which to query the tasks. + /// - Parameter adherenceAggregator: An aggregator that will be used to compute the adherence values shown at the top of the view. + public init(storeManager: OCKSynchronizedStoreManager, adherenceAggregator: OCKAdherenceAggregator = .compareTargetValues) { + self.storeManager = storeManager + self.calendarWeekPageViewController = .init(storeManager: storeManager, aggregator: adherenceAggregator) + super.init(nibName: nil, bundle: nil) + self.calendarWeekPageViewController.dataSource = self + self.pageViewController.dataSource = self + self.pageViewController.delegate = self + self.dataSource = self + self.delegate = self + } + + @available(*, unavailable) + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Properties + + override open func viewSafeAreaInsetsDidChange() { + updateScrollViewInsets() + } + + override open func loadView() { + [calendarWeekPageViewController, pageViewController].forEach { addChild($0) } + view = OCKHeaderBodyView(headerView: calendarWeekPageViewController.view, bodyView: pageViewController.view) + [calendarWeekPageViewController, pageViewController].forEach { $0.didMove(toParent: self) } + } + + override open func viewDidLoad() { + super.viewDidLoad() + let now = Date() + calendarWeekPageViewController.calendarDelegate = self + calendarWeekPageViewController.selectDate(now, animated: false) + pageViewController.setViewControllers([makePage(date: now)], direction: .forward, animated: false, completion: nil) + pageViewController.accessibilityHint = loc("THREE_FINGER_SWIPE_DAY") + navigationItem.leftBarButtonItem = UIBarButtonItem(title: loc("TODAY"), style: .plain, target: self, action: #selector(pressedToday(sender:))) + } + + private func makePage(date: Date) -> OCKDatedListViewController { + let listViewController = OCKDatedListViewController(date: date) + let dateLabel = OCKDateLabel(textStyle: .title2, weight: .bold) + dateLabel.setDate(date) + dateLabel.accessibilityTraits = .header + + listViewController.insertView(dateLabel, at: 0, animated: false) + + setInsets(for: listViewController) + dataSource?.dailyPageViewController(self, prepare: listViewController, for: date) + return listViewController + } + + @objc + private func pressedToday(sender: UIBarButtonItem) { + let previousDate = selectedDate + let currentDate = Date() + guard !Calendar.current.isDate(previousDate, inSameDayAs: currentDate) else { return } + calendarWeekPageViewController.selectDate(currentDate, animated: true) + weekCalendarPageViewController(calendarWeekPageViewController, didSelectDate: currentDate, previousDate: previousDate) + } + + private func updateScrollViewInsets() { + pageViewController.viewControllers?.forEach({ child in + guard let listVC = child as? OCKListViewController else { fatalError("Unexpected type") } + setInsets(for: listVC) + }) + } + + private func setInsets(for listViewController: OCKListViewController) { + guard let listView = listViewController.view as? OCKListView else { fatalError("Unexpected type") } + guard let headerView = view as? OCKHeaderBodyView else { fatalError("Unexpected type") } + let insets = UIEdgeInsets(top: headerView.headerInset, left: 0, bottom: 0, right: 0) + listView.scrollView.contentInset = insets + listView.scrollView.scrollIndicatorInsets = insets + } + + // MARK: - OCKCalendarPageViewControllerDelegate + + public func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didSelectDate date: Date, previousDate: Date) { + let newComponents = Calendar.current.dateComponents([.weekday, .weekOfYear, .year], from: date) + let oldComponents = Calendar.current.dateComponents([.weekday, .weekOfYear, .year], from: previousDate) + guard newComponents != oldComponents else { return } // do nothing if we have selected a date for the same day of the year + let moveLeft = date < previousDate + let listViewController = makePage(date: date) + pageViewController.setViewControllers([listViewController], direction: moveLeft ? .reverse : .forward, animated: true, completion: nil) + } + + public func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didChangeDateInterval interval: DateInterval) {} + + public func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didEncounterError error: Error) { + delegate?.dailyPageViewController(self, didFailWithError: error) + } + + // MARK: OCKDailyPageViewControllerDataSource & Delegate + + open func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, + prepare listViewController: OCKListViewController, for date: Date) {} + + open func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, didFailWithError error: Error) {} + + // MARK: - UIPageViewControllerDelegate + + open func pageViewController(_ pageViewController: UIPageViewController, + viewControllerBefore viewController: UIViewController) -> UIViewController? { + guard let currentViewController = viewController as? OCKDatedListViewController else { fatalError("Unexpected type") } + let targetDate = Calendar.current.date(byAdding: .day, value: -1, to: currentViewController.date)! + return makePage(date: targetDate) + } + + open func pageViewController(_ pageViewController: UIPageViewController, + viewControllerAfter viewController: UIViewController) -> UIViewController? { + guard let currentViewController = viewController as? OCKDatedListViewController else { fatalError("Unexpected type") } + let targetDate = Calendar.current.date(byAdding: .day, value: 1, to: currentViewController.date)! + return makePage(date: targetDate) + } + + // MARK: - UIPageViewControllerDataSource + + open func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, + previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { + guard completed else { return } + guard let listViewController = pageViewController.viewControllers?.first as? OCKDatedListViewController else { fatalError("Unexpected type") } + calendarWeekPageViewController.selectDate(listViewController.date, animated: true) + } +} + +// This is private subclass of the list view controller that imbues it with a date that can be uesd by the page view controller to determine +// which direction was just swiped. +private class OCKDatedListViewController: OCKListViewController { + let date: Date + + init(date: Date) { + self.date = date + super.init(nibName: nil, bundle: nil) + listView.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +private class OCKDateLabel: OCKLabel { + private static let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .medium + return formatter + }() + + func setDate(_ date: Date) { + text = OCKDateLabel.dateFormatter.string(from: date) + } + + override init(textStyle: UIFont.TextStyle, weight: UIFont.Weight) { + super.init(textStyle: textStyle, weight: weight) + styleDidChange() + } + + @available(*, unavailable) + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func styleDidChange() { + super.styleDidChange() + textColor = style().color.label + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyTasksPageViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyTasksPageViewController.swift new file mode 100755 index 0000000..4d30cfa --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKDailyTasksPageViewController.swift @@ -0,0 +1,180 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import UIKit + +/// Handles events related to an `OCKDailyTasksPageViewController`. +public protocol OCKDailyTasksPageViewControllerDelegate: OCKTaskViewControllerDelegate { + + /// Return a view controller to display for the given task and events. + /// - Parameters: + /// - viewController: The view controller displaying the returned view controller. + /// - task: The task to be displayed by the returned view controller. + /// - events: The events to be displayed by the returned view controller. + /// - eventQuery: The query used to retrieve the events for the task. + func dailyTasksPageViewController(_ viewController: OCKDailyTasksPageViewController, viewControllerForTask task: OCKAnyTask, + events: [OCKAnyEvent], eventQuery: OCKEventQuery) -> UIViewController? +} + +/// Displays a calendar page view controller in the header, and a collection of tasks +/// in the body. The tasks are automatically queried based on the selection in the calendar. +open class OCKDailyTasksPageViewController: OCKDailyPageViewController, OCKDailyTasksPageViewControllerDelegate { + private let emptyLabelMargin: CGFloat = 4 + + // MARK: Properties + + /// If set, the delegate will receive callbacks when important events happen at the task view controller level. + public weak var tasksDelegate: OCKDailyTasksPageViewControllerDelegate? + + // MARK: - Life Cycle + + override open func viewDidLoad() { + super.viewDidLoad() + tasksDelegate = self + } + + // MARK: - Methods + + private func fetchTasks(for date: Date, andPopulateIn listViewController: OCKListViewController) { + let taskQuery = OCKTaskQuery(for: date) + storeManager.store.fetchAnyTasks(query: taskQuery, callbackQueue: .main) { [weak self] result in + guard let self = self else { return } + switch result { + case .failure(let error): self.delegate?.dailyPageViewController(self, didFailWithError: error) + case .success(let tasks): + + // Show an empty label if there are no tasks + guard !tasks.isEmpty else { + listViewController.listView.stackView.spacing = self.emptyLabelMargin + let emptyLabel = OCKEmptyLabel(textStyle: .subheadline, weight: .medium) + listViewController.appendView(emptyLabel, animated: false) + return + } + + // Aggregate the view controllers returned after fetching the events + let group = DispatchGroup() + var viewControllers: [UIViewController] = [] + tasks.forEach { + group.enter() + self.viewController(forTask: $0, fromQuery: taskQuery) { viewController in + viewController.map { viewControllers.append($0) } + group.leave() + } + } + + // Add the view controllers to the view + group.notify(queue: .main) { + viewControllers.forEach { listViewController.appendViewController($0, animated: false) } + } + } + } + } + + // Fetch events and return a view controller to display the data + private func viewController(forTask task: OCKAnyTask, fromQuery query: OCKTaskQuery, + result: @escaping (UIViewController?) -> Void) { + guard let dateInterval = query.dateInterval else { fatalError("Task query should have a set date") } + let eventQuery = OCKEventQuery(dateInterval: dateInterval) + self.storeManager.store.fetchAnyEvents(taskID: task.id, query: eventQuery, callbackQueue: .main) { [weak self] fetchResult in + guard let self = self else { return } + switch fetchResult { + case .failure(let error): self.delegate?.dailyPageViewController(self, didFailWithError: error) + case .success(let events): + let viewController = + self.tasksDelegate?.dailyTasksPageViewController(self, viewControllerForTask: task, events: events, eventQuery: eventQuery) ?? + self.dailyTasksPageViewController(self, viewControllerForTask: task, events: events, eventQuery: eventQuery) + result(viewController) + } + } + } + + override open func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, + prepare listViewController: OCKListViewController, for date: Date) { + fetchTasks(for: date, andPopulateIn: listViewController) + } + + // MARK: - OCKDailyTasksPageViewControllerDelegate + + open func dailyTasksPageViewController(_ viewController: OCKDailyTasksPageViewController, viewControllerForTask task: OCKAnyTask, + events: [OCKAnyEvent], eventQuery: OCKEventQuery) -> UIViewController? { + // Show the button log if the task does not impact adherence + if !task.impactsAdherence { + let taskViewController = OCKButtonLogTaskViewController(controller: .init(storeManager: self.storeManager), + viewSynchronizer: .init()) + taskViewController.setup(withEvents: events, task: task, eventQuery: eventQuery, delegate: self.tasksDelegate) + return taskViewController + + // Show the simple if there is only one event. Visually this is the best style for a single event. + } else if events.count == 1 { + let taskViewController = OCKSimpleTaskViewController(controller: .init(storeManager: self.storeManager), + viewSynchronizer: .init()) + taskViewController.setup(withEvents: events, task: task, eventQuery: eventQuery, delegate: self.tasksDelegate) + return taskViewController + + // Else default to the grid + } else { + let taskViewController = OCKGridTaskViewController(controller: .init(storeManager: self.storeManager), + viewSynchronizer: .init()) + taskViewController.setup(withEvents: events, task: task, eventQuery: eventQuery, delegate: self.tasksDelegate) + return taskViewController + } + } + + open func taskViewController(_ viewController: OCKTaskViewController, + didEncounterError: Error) where C: OCKTaskControllerProtocol, VS: OCKTaskViewSynchronizerProtocol {} +} + +private extension OCKTaskViewController where Controller: OCKTaskController { + func setup(withEvents events: [OCKAnyEvent], task: OCKAnyTask, eventQuery: OCKEventQuery, delegate: OCKTaskViewControllerDelegate?) { + controller.updateViewModel(withEvents: events) + controller.subscribeTo(eventsBelongingToTask: task, eventQuery: eventQuery) + self.delegate = delegate + } +} + +private class OCKEmptyLabel: OCKLabel { + override init(textStyle: UIFont.TextStyle, weight: UIFont.Weight) { + super.init(textStyle: textStyle, weight: weight) + text = loc("NO_TASKS") + } + + @available(*, unavailable) + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func styleDidChange() { + super.styleDidChange() + textColor = style().color.label + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKListViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKListViewController.swift new file mode 100755 index 0000000..5652df8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/Controller/OCKListViewController.swift @@ -0,0 +1,119 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// A view controller displaying views in an `OCKListView`. +/// `OCKDailyPageViewController` uses `OCKListViewController`s to display scrollable stacks of +/// embedded view controllers. +open class OCKListViewController: UIViewController { + + // MARK: Properties + + /// The list view that displays the view controller's views. + var listView: OCKListView { + guard let view = self.view as? OCKListView else { fatalError("Unsupported view type.") } + return view + } + + // MARK: - Life cycle + + override open func loadView() { + view = OCKListView() + } + + // MARK: - Methods + + /// Sets up the containment of `viewController` in OCKListViewController and appends its view + /// to the vertical stack of listed views. + /// + /// - Parameters: + /// - viewController: The view controller with the view to append. If the new child view controller + /// is already the child of a container view controller, it is removed from that container before being appended.. + /// - animated: Pass `true` to animate the addition of the `viewController`'s view. + open func appendViewController(_ viewController: UIViewController, animated: Bool) { + viewController.setupContainment(in: self, stackView: listView.stackView, animated: animated) + } + + /// Appends `view` to the vertical stack of listed views. + /// + /// - Parameters: + /// - view: The view to append to the current end of the list. + /// - animated: Pass `true` to animate the addition of the view. + open func appendView(_ view: UIView, animated: Bool) { + listView.stackView.addArrangedSubview(view, animated: animated) + } + + /// Sets up the containment of `viewController` in OCKListViewController and inserts its view + /// in the vertical stack of listed views at the specified index. + /// + /// - Parameters: + /// - viewController: The view controller with the view to insert. If the view controller is already the child of + /// a container view controller, it is removed from that container before being inserted. + /// - index: The index at which to insert the `viewController`'s view. This value must not be greater + /// than the number of views in the `OCKListViewController`. If the index is out of bounds, this method + /// throws an internalInconsistencyException exception. + /// - animated: Pass `true` to animate the insertion of `viewController`'s view. + open func insertViewController(_ viewController: UIViewController, at index: Int, animated: Bool) { + viewController.setupContainment(in: self, stackView: listView.stackView, at: index, animated: animated) + } + + /// Inserts a view in the vertical stack of listed views at the specified index. + /// + /// - Parameters: + /// - view: The view to insert in the list. + /// - index: The index at which to insert `view`. This value must not be greater than the number of views + /// in the `OCKListViewController`. If the index is out of bounds, this method throws an + /// internalInconsistencyException exception. + /// - animated: Pass `true` to animate the insertion of `view`. + open func insertView(_ view: UIView, at index: Int, animated: Bool) { + listView.stackView.insertArrangedSubview(view, at: index, animated: animated) + } + + /// Removes the view located at `index`. + /// + /// - Parameter index: The index of the view to be removed. This must be a valid index in the number of views listed. + open func remove(at index: Int) { + let view = listView.stackView.arrangedSubviews[index] + if let viewController = children.first(where: { $0.view == view }) { + viewController.clearContainment() + } else { + view.removeFromSuperview() + } + } + + /// Removes all displayed views without animation. + open func clear() { + listView.stackView.arrangedSubviews.forEach { $0.removeFromSuperview() } + children.forEach { $0.clearContainment() } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKHeaderBodyView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKHeaderBodyView.swift new file mode 100755 index 0000000..169f9b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKHeaderBodyView.swift @@ -0,0 +1,113 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitUI +import UIKit + +internal class OCKHeaderBodyView: OCKView { + + enum Constants { + static let headerContentHeight: CGFloat = 60 + static let topMargin: CGFloat = 20 + static let margin: CGFloat = 16 + } + + // MARK: Properties + + var headerHeight: CGFloat { + return Constants.headerContentHeight + 2 * Constants.margin + } + + var headerInset: CGFloat { + return headerHeight + Constants.topMargin + } + + private let headerView: UIView + private let bodyView: UIView + + private let headerBackgroundView: UIView = { + let view = UIView() + return view + }() + + private let separatorView = OCKSeparatorView() + + // MARK: Life cycle + + init(headerView: UIView, bodyView: UIView) { + self.headerView = headerView + self.bodyView = bodyView + super.init() + setup() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Methods + + private func setup() { + addSubviews() + constrainSubviews() + } + + private func addSubviews() { + [bodyView, headerBackgroundView, separatorView, headerView].forEach { addSubview($0) } + } + + private func constrainSubviews() { + [headerBackgroundView, separatorView, bodyView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate([ + headerView.centerYAnchor.constraint(equalTo: headerBackgroundView.centerYAnchor), + headerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), + headerView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), + headerView.heightAnchor.constraint(equalToConstant: Constants.headerContentHeight), + + headerBackgroundView.leadingAnchor.constraint(equalTo: leadingAnchor), + headerBackgroundView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + headerBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor), + headerBackgroundView.heightAnchor.constraint(equalToConstant: headerHeight), + + separatorView.bottomAnchor.constraint(equalTo: headerBackgroundView.bottomAnchor), + separatorView.leadingAnchor.constraint(equalTo: headerBackgroundView.leadingAnchor), + separatorView.trailingAnchor.constraint(equalTo: headerBackgroundView.trailingAnchor) + ] + bodyView.constraints(equalTo: self)) + } + + override func styleDidChange() { + super.styleDidChange() + let style = self.style() + backgroundColor = style.color.customGroupedBackground + headerBackgroundView.backgroundColor = style.color.customGroupedBackground + directionalLayoutMargins = style.dimension.directionalInsets1 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKListView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKListView.swift new file mode 100755 index 0000000..6374e79 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Lists/View/OCKListView.swift @@ -0,0 +1,103 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A view enclosing a scrollable stack view. +internal class OCKListView: OCKView { + + // MARK: Properties + + /// The stack view embedded inside the scroll view. + let stackView: OCKStackView = { + let stackView = OCKStackView() + stackView.axis = .vertical + return stackView + }() + + /// The scroll view that contains the stack view. + let scrollView = UIScrollView() + + private let contentView = UIView() + + // MARK: - Life Cycle + + override init() { + super.init() + setup() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + // MARK: Methods + + private func setup() { + addSubviews() + styleSubviews() + constrainSubviews() + } + + private func styleSubviews() { + scrollView.backgroundColor = contentView.backgroundColor + scrollView.alwaysBounceVertical = true + } + + private func addSubviews() { + addSubview(scrollView) + scrollView.addSubview(contentView) + contentView.addSubview(stackView) + } + + private func constrainSubviews() { + [scrollView, contentView, stackView].forEach { $0?.translatesAutoresizingMaskIntoConstraints = false } + + NSLayoutConstraint.activate([ + contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor), + + stackView.topAnchor.constraint(equalTo: contentView.topAnchor), + stackView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), + stackView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), + stackView.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor) + ] + scrollView.constraints(equalTo: self) + + contentView.constraints(equalTo: scrollView)) + } + + override func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + contentView.directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + backgroundColor = cachedStyle.color.customGroupedBackground + contentView.backgroundColor = cachedStyle.color.customGroupedBackground + stackView.spacing = cachedStyle.dimension.directionalInsets1.top + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Localization/en.lproj/locversion.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Localization/en.lproj/locversion.plist new file mode 100755 index 0000000..b8e7e78 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Localization/en.lproj/locversion.plist @@ -0,0 +1,14 @@ + + + + + LprojCompatibleVersion + 29 + LprojLocale + en + LprojRevisionLevel + 1 + LprojVersion + 31 + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarController.swift new file mode 100755 index 0000000..e8c04dc --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarController.swift @@ -0,0 +1,138 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import Foundation +import UIKit + +/// A basic controller capable of updating a calendar. +open class OCKCalendarController: OCKCalendarControllerProtocol, ObservableObject { + + // MARK: OCKCalendarControllerProtocol + + public var store: OCKAnyEventStore { storeManager.store } + public let objectWillChange: CurrentValueSubject<[OCKCompletionRingButton.CompletionState], Never> + + // MARK: - Properties + + /// The store manager against which the calendar will be synchronized. + public let storeManager: OCKSynchronizedStoreManager + + /// The date interval displayed by the calendar. + public let dateInterval: DateInterval + + private var subscription: AnyCancellable? + + // MARK: - Life Cycle + + /// Initialize the controller. + /// - Parameter dateInterval: The date interval for the adherence range. + /// - Parameter storeManager: Wraps the store that contains the adherence data. + public required init(dateInterval: DateInterval, storeManager: OCKSynchronizedStoreManager) { + self.dateInterval = dateInterval + self.storeManager = storeManager + self.objectWillChange = .init([]) + } + + // MARK: - Methods + + /// Begin observing adherence in the calendar's date interval. + /// + /// - Parameters: + /// - aggregator: An aggregator that will be used to compute adherence. + open func fetchAndObserveAdherence(usingAggregator aggregator: OCKAdherenceAggregator, errorHandler: ((OCKStoreError) -> Void)? = nil) { + + // Set the view model when outcomes change + subscription = storeManager.notificationPublisher + .compactMap { $0 as? OCKOutcomeNotification } + .sink(receiveValue: { [weak self] _ in self?.fetchAdherence(usingAggregator: aggregator, completion: { result in + if case let .failure(error) = result { + errorHandler?(error) + } + }) }) + + // Fetch adherence and set the view model + fetchAdherence(usingAggregator: aggregator) { result in + if case let .failure(error) = result { + errorHandler?(error) + } + } + } + + private func makeAdherenceQuery(withAggregator aggregator: OCKAdherenceAggregator) -> OCKAdherenceQuery { + var adherenceQuery = OCKAdherenceQuery(taskIDs: [], dateInterval: dateInterval) + adherenceQuery.aggregator = aggregator + return adherenceQuery + } + + private func convertAdherenceToCompletionRingState(adherence: [OCKAdherence], + query: OCKAdherenceQuery) -> [OCKCompletionRingButton.CompletionState] { + return zip(query.dateInterval.dates(), adherence).map { date, adherence in + let isInFuture = date > Date() && !Calendar.current.isDateInToday(date) + switch adherence { + case .noTasks: return .dimmed + case .noEvents: return .empty + case .progress(let value): + if value > 0 { return .progress(CGFloat(value)) } + return isInFuture ? .empty : .zero + } + } + } + + /// Fetch the adherence state for the days in the calendar and set the view model. + private func fetchAdherence(usingAggregator aggregator: OCKAdherenceAggregator, + completion: OCKResultClosure<[OCKCompletionRingButton.CompletionState]>?) { + let query = makeAdherenceQuery(withAggregator: aggregator) + storeManager.store.fetchAdherence(query: query) { [weak self] result in + guard let self = self else { return } + switch result { + case .failure(let error): completion?(.failure(error)) + case .success(let adherence): + let states = self.convertAdherenceToCompletionRingState(adherence: adherence, query: query) + self.objectWillChange.value = states + completion?(.success(states)) + } + } + } +} + +private extension DateInterval { + func dates() -> [Date] { + var dates = [Date]() + var currentDate = start + while currentDate < end { + dates.append(currentDate) + currentDate = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)! + } + return dates + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarControllerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarControllerProtocol.swift new file mode 100755 index 0000000..8f8d356 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKCalendarControllerProtocol.swift @@ -0,0 +1,44 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import Foundation + +/// Describes an object capable of tracking the state of a calendar. +public protocol OCKCalendarControllerProtocol: AnyObject { + + /// A reference to a store that can be used to fetch and update events. + var store: OCKAnyEventStore { get } + + /// A publisher that publishes completion ring states when events change in the store. + var objectWillChange: CurrentValueSubject<[OCKCompletionRingButton.CompletionState], Never> { get } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKWeekCalendarController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKWeekCalendarController.swift new file mode 100755 index 0000000..25aa5ed --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Controllers/OCKWeekCalendarController.swift @@ -0,0 +1,57 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Combine +import Foundation + +/// A calendar controller that handles a calendar showing a single week. +open class OCKWeekCalendarController: OCKCalendarController { + + public init(weekOfDate date: Date, storeManager: OCKSynchronizedStoreManager) { + var weekInterval = Calendar.current.dateInterval(of: .weekOfYear, for: date)! + weekInterval.duration -= 1 // Note: Default interval includes the first second of the next week + super.init(dateInterval: weekInterval, storeManager: storeManager) + } + + public required init(dateInterval: DateInterval, storeManager: OCKSynchronizedStoreManager) { + var weekInterval = Calendar.current.dateInterval(of: .weekOfYear, for: Date())! + weekInterval.duration -= 1 // Note: Default interval includes the first second of the next week + guard Self.dateIntervalIsValid(dateInterval) else { fatalError("Date interval should be one week long") } + super.init(dateInterval: dateInterval, storeManager: storeManager) + } + + // Date interval is valid if it spans one week + private static func dateIntervalIsValid(_ dateInterval: DateInterval) -> Bool { + var weekInterval = Calendar.current.dateInterval(of: .weekOfYear, for: dateInterval.start)! + weekInterval.duration -= 1 // Note: Default interval includes the first second of the next week + + return weekInterval.start == dateInterval.start && weekInterval.end == dateInterval.end + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Paging/OCKWeekCalendarPageViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Paging/OCKWeekCalendarPageViewController.swift new file mode 100755 index 0000000..2168f96 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Paging/OCKWeekCalendarPageViewController.swift @@ -0,0 +1,202 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Handles events related to an `OCKWeekCalendarPageViewController`. +public protocol OCKWeekCalendarPageViewControllerDelegate: AnyObject { + /// Called when a date in the calendar has been selected. + /// - Parameter viewController: The view controller that displays the calendar. + /// - Parameter date: The newly selected date. + /// - Parameter previousDate: The previously selected date. + func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didSelectDate date: Date, previousDate: Date) + + /// Called when the date interval in the calendar has been changed. + /// - Parameter viewController: The view controller that displays the calendar. + /// - Parameter interval: The new date interval. + func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didChangeDateInterval interval: DateInterval) + + func weekCalendarPageViewController(_ viewController: OCKWeekCalendarPageViewController, didEncounterError error: Error) +} + +/// A view controller that allows paging through adjacent weeks of task adherence content. +open class OCKWeekCalendarPageViewController: +UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, OCKCalendarViewDelegate { + // MARK: Properties + + /// Handles events related to an `OCKCalendarPageViewController`. + public weak var calendarDelegate: OCKWeekCalendarPageViewControllerDelegate? + + /// The currently selected date in the calendar. + public var selectedDate: Date { + return currentViewController?.calendarView.selectedDate ?? Date() + } + + /// The date interval currently being displayed. + public var dateInterval: DateInterval? { + return currentViewController?.calendarView.dateInterval + } + + private let aggregator: OCKAdherenceAggregator + private var previouslySelectedDate = Date() + private let storeManager: OCKSynchronizedStoreManager + + var currentViewController: OCKWeekCalendarViewController? { + guard + let viewControllers = viewControllers, + !viewControllers.isEmpty else { return nil } + + guard let viewController = viewControllers.first! as? OCKWeekCalendarViewController else { fatalError("Unsupported type") } + return viewController + } + + // MARK: - Life Cycle + + public init(storeManager: OCKSynchronizedStoreManager, aggregator: OCKAdherenceAggregator) { + self.storeManager = storeManager + self.aggregator = aggregator + super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func viewDidLoad() { + super.viewDidLoad() + dataSource = self + delegate = self + + // Create the first view controller + let viewController = makeViewController(forDate: previouslySelectedDate) + viewController.calendarView.delegate = self + viewController.calendarView.selectDate(previouslySelectedDate) + setViewControllers([viewController], direction: .forward, animated: false, completion: nil) + } + + // MARK: - Methods + + private func makeViewController(forDate date: Date) -> OCKWeekCalendarViewController { + let viewController = OCKWeekCalendarViewController(weekOfDate: date, aggregator: aggregator, storeManager: storeManager) + + let interval = Calendar.current.dateInterval(of: .weekOfYear, for: date)! + viewController.calendarView.showDate(interval.start) + return viewController + } + + // Send errors through to the calendarDelegate + private func handleResult(_ result: Result<[OCKCompletionRingButton.CompletionState], OCKStoreError>) { + switch result { + case .failure(let error): calendarDelegate?.weekCalendarPageViewController(self, didEncounterError: error) + case .success: break + } + } + + /// Select a date in the calendar. If the date is not in the current date interval being displayed, the view controller will automatically + /// page to the date interval that contains the new date. + /// - Parameter date: The new date to select. + /// - Parameter animated: True to animate selection of the new date. + open func selectDate(_ date: Date, animated: Bool) { + guard let currentVC = currentViewController else { return } + if currentVC.calendarView.dateInterval.contains(date) { + currentVC.calendarView.selectDate(date) + return + } + + // Create the next view controller + let nextVC = makeViewController(forDate: date) + nextVC.calendarView.delegate = self + let isLeft = currentVC.calendarView.dateInterval.start > date + nextVC.calendarView.selectDate(date) + setViewControllers([nextVC], direction: isLeft ? .reverse : .forward, animated: animated, completion: nil ) + } + + // MARK: UIPageViewController DataSource & Delegate + + open func pageViewController(_ pageViewController: UIPageViewController, + viewControllerBefore viewController: UIViewController) -> UIViewController? { + guard let typedViewController = viewController as? OCKWeekCalendarViewController else { fatalError("Unsupported type") } + let dateInterval = typedViewController.calendarView.dateInterval + let previousDate = Calendar.current.date(byAdding: .weekOfYear, value: -1, to: dateInterval.start)! + let previousPage = makeViewController(forDate: previousDate) + previousPage.calendarView.delegate = self + return previousPage + } + + open func pageViewController(_ pageViewController: UIPageViewController, + viewControllerAfter viewController: UIViewController) -> UIViewController? { + guard let typedViewController = viewController as? OCKWeekCalendarViewController else { fatalError("Unsupported type") } + let dateInterval = typedViewController.calendarView.dateInterval + let nextDate = Calendar.current.date(byAdding: .weekOfYear, value: 1, to: dateInterval.start)! + let nextPage = makeViewController(forDate: nextDate) + nextPage.calendarView.delegate = self + return nextPage + } + + open func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, + previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { + guard + completed, + let previousViewController = previousViewControllers.first, + let currentViewController = currentViewController, + let currentWeek = dateInterval + else { return } + guard let typedPreviousViewController = previousViewController as? OCKWeekCalendarViewController else { fatalError("Unsupported type") } + + let didMoveForwards = typedPreviousViewController.calendarView.dateInterval < currentViewController.calendarView.dateInterval + let offset = didMoveForwards ? 1 : -1 + let previousSelectedDate = typedPreviousViewController.calendarView.selectedDate + let newSelectedDate = Calendar.current.date(byAdding: .weekOfYear, value: offset, + to: typedPreviousViewController.calendarView.selectedDate)! + currentViewController.calendarView.selectDate(newSelectedDate) + calendarDelegate?.weekCalendarPageViewController(self, didChangeDateInterval: currentWeek) + calendarDelegate?.weekCalendarPageViewController(self, didSelectDate: newSelectedDate, previousDate: previousSelectedDate) + } + + // MARK: OCKCalendarViewDelegate + + /// Called when a particular date in the calendar was selected. + /// - Parameter calendarView: The view displaying the calendar. + /// - Parameter date: The date that was selected. + /// - Parameter index: The index of the date that was selected with respect to the collection of days in the current `dateInterval`. + /// - Parameter sender: The sender that initiated the selection. + open func calendarView(_ calendarView: UIView & OCKCalendarDisplayable, didSelectDate date: Date, at index: Int, sender: Any?) { + guard + let startOfWeek = dateInterval?.start, + let dateInterval = dateInterval else { return } + let comparison = Calendar.current.compare(dateInterval.start, to: startOfWeek, toGranularity: .weekOfYear) + guard comparison == .orderedSame else { return } + calendarDelegate?.weekCalendarPageViewController(self, didSelectDate: date, previousDate: previouslySelectedDate) + previouslySelectedDate = date + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKCalendarViewSynchronizerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKCalendarViewSynchronizerProtocol.swift new file mode 100755 index 0000000..1193723 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKCalendarViewSynchronizerProtocol.swift @@ -0,0 +1,49 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Describes a view synchronizer for calendars. +public protocol OCKCalendarViewSynchronizerProtocol { + + /// The type of the view that will be synchronized + associatedtype View: UIView & OCKCalendarDisplayable + + /// Initialize a view to be synchronized. + func makeView() -> View + + /// Update a view using the given context. + /// - Parameters: + /// - view: The view to be updated. + /// - context: Information about the update that is occurring. + func updateView(_ view: View, context: OCKSynchronizationContext<[OCKCompletionRingButton.CompletionState]>) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKWeekCalendarViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKWeekCalendarViewSynchronizer.swift new file mode 100755 index 0000000..b702c6e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/Synchronizers/OCKWeekCalendarViewSynchronizer.swift @@ -0,0 +1,55 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A view synchronizer that creates and updates an `OCKWeekCalendarView`. +open class OCKWeekCalendarViewSynchronizer: OCKCalendarViewSynchronizerProtocol { + + private let date: Date + + /// Initialize by specifying a date. The calendar will show the entire week that + /// the provided date falls within. + public init(weekOfDate date: Date) { + self.date = date + } + + open func makeView() -> OCKWeekCalendarView { + let view = OCKWeekCalendarView(weekOfDate: date) + view.accessibilityHint = loc("THREE_FINGER_SWIPE_WEEK") + return view + } + + open func updateView(_ view: OCKWeekCalendarView, context: OCKSynchronizationContext<[OCKCompletionRingButton.CompletionState]>) { + view.updateWith(states: context.viewModel, animated: context.animated) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKCalendarViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKCalendarViewController.swift new file mode 100755 index 0000000..ee48d99 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKCalendarViewController.swift @@ -0,0 +1,137 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import MessageUI +import UIKit + +/// Types wishing to receive updates from calendar view controllers can conform to this protocol. +public protocol OCKCalendarViewControllerDelegate: AnyObject { + + /// Called when an unhandled error is encountered in a calendar view controller. + /// - Parameters: + /// - viewController: The view controller in which the error was encountered. + /// - didEncounterError: The error that was unhandled. + func calendarViewController( + _ viewController: OCKCalendarViewController, didEncounterError: Error) +} + +/// A view controller that displays a calendar view and keep it synchronized with a store. +open class OCKCalendarViewController: +UIViewController, OCKCalendarViewDelegate { + + // MARK: Properties + + /// If set, the delegate will receive updates when import events happen + public weak var delegate: OCKCalendarViewControllerDelegate? + + /// Handles the responsibility of updating the view when data in the store changes. + public let viewSynchronizer: ViewSynchronizer + + /// Handles the responsibility of interacting with data from the store. + public let controller: Controller + + /// The view that is being synchronized against the store. + public var calendarView: ViewSynchronizer.View { + guard let view = self.view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + return view + } + + private var viewDidLoadCompletion: (() -> Void)? + private var viewModelSubscription: AnyCancellable? + + // MARK: - Life Cycle + + /// Initialize with a controller and a synchronizer + public init(controller: Controller, viewSynchronizer: ViewSynchronizer) { + self.controller = controller + self.viewSynchronizer = viewSynchronizer + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @available(*, unavailable) + override open func loadView() { + view = viewSynchronizer.makeView() + } + + override open func viewDidLoad() { + super.viewDidLoad() + calendarView.delegate = self + + // Begin listening for changes in the view model. Note, when we subscribe to the view model, it sends its current value through the stream + startObservingViewModel() + + viewDidLoadCompletion?() + } + + // MARK: - Methods + + // Create a subscription that updates the view when the view model is updated. + private func startObservingViewModel() { + viewModelSubscription?.cancel() + viewModelSubscription = controller.objectWillChange + .context() + .sink { [view] context in + guard let typedView = view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + self.viewSynchronizer.updateView(typedView, context: context) + } + } + + // MARK: - OCKCalendarViewDelegate + + open func calendarView(_ calendarView: UIView & OCKCalendarDisplayable, didSelectDate date: Date, at index: Int, sender: Any?) {} +} + +public extension OCKCalendarViewController where Controller: OCKCalendarController { + + /// Initialize a view controller that displays adherence. Fetches and stays synchronized with the adherence data. + /// - Parameter viewSynchronizer: Manages the calendar view. + /// - Parameter dateInterval: The date interval for the adherence range. + /// - Parameter aggregator: Used to aggregate adherence over the date interval. + /// - Parameter storeManager: Wraps the store that contains the adherence data. + convenience init(viewSynchronizer: ViewSynchronizer, dateInterval: DateInterval, + aggregator: OCKAdherenceAggregator, storeManager: OCKSynchronizedStoreManager) { + let controller = Controller(dateInterval: dateInterval, storeManager: storeManager) + self.init(controller: controller, viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveAdherence(usingAggregator: aggregator, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.calendarViewController(self, didEncounterError: error) + }) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKWeekCalendarViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKWeekCalendarViewController.swift new file mode 100755 index 0000000..de58ede --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Calendar/View Controllers/OCKWeekCalendarViewController.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation + +public typealias OCKWeekCalendarViewController = OCKCalendarViewController + +public extension OCKCalendarViewController where Controller: OCKWeekCalendarController, ViewSynchronizer == OCKWeekCalendarViewSynchronizer { + + /// Initialize a view controller that displays adherence. Fetches and stays synchronized with the adherence data. + /// - Parameter weekOfDate: A date in the week for which adherence will be fetched. + /// - Parameter aggregator: Used to aggregate adherence over the date interval. + /// - Parameter storeManager: Wraps the store that contains the adherence data. + convenience init(weekOfDate date: Date, aggregator: OCKAdherenceAggregator, storeManager: OCKSynchronizedStoreManager) { + var weekInterval = Calendar.current.dateInterval(of: .weekOfYear, for: date)! + weekInterval.duration -= 1 // Standard interval returns 1 second of the next week + let viewSynchronizer = ViewSynchronizer(weekOfDate: date) + self.init(viewSynchronizer: viewSynchronizer, dateInterval: weekInterval, aggregator: aggregator, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKCartesianChartController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKCartesianChartController.swift new file mode 100755 index 0000000..18d1ec0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKCartesianChartController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKCartesianChartController = OCKChartController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartController.swift new file mode 100755 index 0000000..7cfffd1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartController.swift @@ -0,0 +1,128 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import Foundation +import UIKit + +/// A basic controller capable of updating charts. +open class OCKChartController: OCKChartControllerProtocol, ObservableObject { + + // MARK: OCKChartControllerProtocol + public var store: OCKAnyEventStore { storeManager.store } + public let objectWillChange: CurrentValueSubject<[OCKDataSeries], Never> + + /// The store manager against which the chart will be synchronized. + public let storeManager: OCKSynchronizedStoreManager + + // MARK: Properties + + private let eventQuery: OCKEventQuery + private var cancellables: Set = Set() + + // MARK: - Life Cycle + + /// Initialize the controller. + /// - Parameter weekOfDate: A date in the week of the insights range. + /// - Parameter storeManager: Wraps the store that contains the insight data. + public required init(weekOfDate: Date, storeManager: OCKSynchronizedStoreManager) { + self.eventQuery = OCKEventQuery(dateInterval: Calendar.current.dateIntervalOfWeek(for: weekOfDate)) + self.storeManager = storeManager + self.objectWillChange = .init([]) + } + + // MARK: - Methods + + /// Begin observing an array of data series configurations. + /// - Parameters: + /// - configurations: An array of configurations to be plotted. + open func fetchAndObserveInsights(forConfigurations configurations: [OCKDataSeriesConfiguration], + errorHandler: ((Error) -> Void)? = nil) { + cancellables = Set() + configurations.forEach { config in + store.fetchAnyEvents(taskID: config.taskID, query: eventQuery, callbackQueue: .main) { result in + switch result { + case let .failure(error): errorHandler?(error) + case let .success(events): + self.refetchEvents(configurations: configurations, completion: nil) + events.forEach { event in + self.storeManager + .publisher(forEvent: event, categories: [.add, .update, .delete]) + .sink(receiveValue: { _ in + self.refetchEvents(configurations: configurations) { result in + if case let .failure(error) = result { + errorHandler?(error) + } + } + }) + .store(in: &self.cancellables) + } + } + } + } + } + + private func refetchEvents(configurations: [OCKDataSeriesConfiguration], + completion: OCKResultClosure<[OCKDataSeries]>?) { + var allDataSeries = [OCKDataSeries]() + let group = DispatchGroup() + + // Aggregate events, then set the view model + for config in configurations { + let insightsQuery = OCKInsightQuery(taskID: config.taskID, dateInterval: eventQuery.dateInterval, aggregator: config.aggregator) + group.enter() + storeManager.store.fetchInsights(query: insightsQuery, callbackQueue: .main) { result in + switch result { + case .failure(let error): + completion?(.failure(error)) + return + case .success(let values): + var series = OCKDataSeries(values: values.map { CGFloat($0) }, title: config.legendTitle, + gradientStartColor: config.gradientStartColor, gradientEndColor: config.gradientEndColor, + size: config.markerSize) + + let accessibilityLabels = zip(Calendar.current.orderedWeekdaySymbols(), values).map { "\(config.legendTitle), \($0), \($1)" } + series.accessibilityLabels = accessibilityLabels + allDataSeries.append(series) + } + group.leave() + } + } + + // Wait for the events to be aggregated, then set the view model + group.notify(queue: .main) { [weak self] in + guard let self = self else { return } + self.objectWillChange.value = allDataSeries + completion?(.success(allDataSeries)) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartControllerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartControllerProtocol.swift new file mode 100755 index 0000000..2821d6d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKChartControllerProtocol.swift @@ -0,0 +1,43 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine + +/// Describes an object capable of tracking and updating the state of a chart. +public protocol OCKChartControllerProtocol: AnyObject { + + /// A reference to a writable store. + var store: OCKAnyTaskStore & OCKAnyEventStore { get } + + /// A publisher that publishers new values when the watched data series change in the store. + var objectWillChange: CurrentValueSubject<[OCKDataSeries], Never> { get } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKDataSeriesConfiguration.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKDataSeriesConfiguration.swift new file mode 100755 index 0000000..cc48c57 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Controller/OCKDataSeriesConfiguration.swift @@ -0,0 +1,75 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import UIKit + +/// A configuration object that specifies which data should be queried and how it should be displayed by the graph. +public struct OCKDataSeriesConfiguration { + /// A user-provided unique id for a task. + public var taskID: String + + /// The title that will be used to represent this data series in the legend. + public var legendTitle: String + + /// The first of two colors that will be used in the gradient when plotting the data. + public var gradientStartColor: UIColor + + /// The second of two colors that will be used in the gradient when plotting the data. + public var gradientEndColor: UIColor + + /// The marker size determines the size of the line, bar, or scatter plot elements. The precise behavior is different for each type of plot. + /// - For line plots, it will be the width of the line. + /// - For scatter plots, it will be the radius of the markers. + /// - For bar plots, it will be the width of the bar. + public var markerSize: CGFloat + + /// A closure that accepts as an argument a day's worth of events and returns a y-axis value for that day. + public var aggregator: OCKEventAggregator + + /// Initialize a new `OCKDataSeriesConfiguration`. + /// + /// - Parameters: + /// - taskID: A user-provided unique id for a task. + /// - legendTitle: The title that will be used to represent this data series in the legend. + /// - gradientStartColor: The first of two colors that will be used in the gradient when plotting the data. + /// - gradientEndColor: The second of two colors that will be used in the gradient when plotting the data. + /// - markerSize: The marker size determines the size of the line, bar, or scatter plot elements. The precise behavior varies by plot type. + /// - eventAggregator: A an aggregator that accepts as an argument a day's worth of events and returns a y-axis value for that day. + public init(taskID: String, legendTitle: String, gradientStartColor: UIColor, gradientEndColor: UIColor, + markerSize: CGFloat, eventAggregator: OCKEventAggregator) { + self.taskID = taskID + self.legendTitle = legendTitle + self.gradientStartColor = gradientStartColor + self.gradientEndColor = gradientEndColor + self.markerSize = markerSize + self.aggregator = eventAggregator + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKCartesianChartViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKCartesianChartViewSynchronizer.swift new file mode 100755 index 0000000..05c3f05 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKCartesianChartViewSynchronizer.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A chart view controller capable of displaying charts drawn on a Cartesian coordinate system. +open class OCKCartesianChartViewSynchronizer: OCKChartViewSynchronizerProtocol { + + /// The type of the plot that this view controller displays. + public let plotType: OCKCartesianGraphView.PlotType + + /// The currently selected date. + public let selectedDate: Date + + /// Initialize by providing a chart type and date. + public required init(plotType: OCKCartesianGraphView.PlotType, selectedDate: Date) { + self.plotType = plotType + self.selectedDate = selectedDate + } + + open func updateView(_ view: OCKCartesianChartView, context: OCKSynchronizationContext<[OCKDataSeries]>) { + view.updateWith(dataSeries: context.viewModel, animated: context.animated) + } + + open func makeView() -> OCKCartesianChartView { + let chartView = OCKCartesianChartView(type: plotType) + let currentWeekday = Calendar.current.component(.weekday, from: selectedDate) + let firstWeekday = Calendar.current.firstWeekday + var offset = (currentWeekday - 1) - (firstWeekday - 1) + if offset < 0 { + offset += 7 + } + chartView.graphView.selectedIndex = offset + chartView.graphView.horizontalAxisMarkers = Calendar.current.orderedWeekdaySymbolsVeryShort() + return chartView + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKChartViewSynchronizerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKChartViewSynchronizerProtocol.swift new file mode 100755 index 0000000..77c2279 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/Synchronizers/OCKChartViewSynchronizerProtocol.swift @@ -0,0 +1,49 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Describes a view synchronizer for charts. +public protocol OCKChartViewSynchronizerProtocol { + + /// The type of the view that will be synchronized + associatedtype View: UIView & OCKChartDisplayable + + /// Initialize a view to be synchronized. + func makeView() -> View + + /// Update a view using the given context. + /// - Parameters: + /// - view: The view to be updated. + /// - context: Information about the update that is occurring. + func updateView(_ view: View, context: OCKSynchronizationContext<[OCKDataSeries]>) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKCartesianChartViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKCartesianChartViewController.swift new file mode 100755 index 0000000..35fae5f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKCartesianChartViewController.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKCartesianChartViewController = OCKChartViewController + +public extension OCKChartViewController where Controller: OCKCartesianChartController, ViewSynchronizer == OCKCartesianChartViewSynchronizer { + + /// Initialize a view controller that displays a chart. Fetches and stays synchronized with insights. + /// - Parameter weekOfDate: A date in the week of the insights range to fetch. + /// - Parameter configurations: Configurations used to fetch the insights ad display the data. + /// - Parameter storeManager: Wraps the store that contains the insight data to fetch. + convenience init(plotType: OCKCartesianGraphView.PlotType, selectedDate: Date, + configurations: [OCKDataSeriesConfiguration], storeManager: OCKSynchronizedStoreManager) { + let viewSynchronizer = ViewSynchronizer(plotType: plotType, selectedDate: selectedDate) + self.init(viewSynchronizer: viewSynchronizer, weekOfDate: selectedDate, configurations: configurations, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKChartViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKChartViewController.swift new file mode 100755 index 0000000..dc1da8a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Chart/View Controllers/OCKChartViewController.swift @@ -0,0 +1,136 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import MessageUI +import UIKit + +/// Types wishing to receive updates from chart view controllers can conform to this protocol. +public protocol OCKChartViewControllerDelegate: AnyObject { + + /// Called when an unhandled error is encountered in a calendar view controller. + /// - Parameters: + /// - viewController: The view controller in which the error was encountered. + /// - didEncounterError: The error that was unhandled. + func chartViewController( + _ viewController: OCKChartViewController, didEncounterError: Error) +} + +/// A view controller that displays a chart view and keep it synchronized with a store. +open class OCKChartViewController: +UIViewController, OCKChartViewDelegate { + + // MARK: Properties + + /// If set, the delegate will receive updates when import events happen + public weak var delegate: OCKChartViewControllerDelegate? + + /// Handles the responsibility of updating the view when data in the store changes. + public let viewSynchronizer: ViewSynchronizer + + /// Handles the responsibility of interacting with data from the store. + public let controller: Controller + + /// The view that is being synchronized against the store. + public var chartView: ViewSynchronizer.View { + guard let view = self.view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + return view + } + + private var viewDidLoadCompletion: (() -> Void)? + private var viewModelSubscription: AnyCancellable? + + // MARK: - Life Cycle + + public init(controller: Controller, viewSynchronizer: ViewSynchronizer) { + self.controller = controller + self.viewSynchronizer = viewSynchronizer + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @available(*, unavailable) + override open func loadView() { + view = viewSynchronizer.makeView() + } + + override open func viewDidLoad() { + super.viewDidLoad() + chartView.delegate = self + + // Begin listening for changes in the view model. Note, when we subscribe to the view model, it sends its current value through the stream + startObservingViewModel() + + viewDidLoadCompletion?() + } + + // MARK: - Methods + + // Create a subscription that updates the view when the view model is updated. + private func startObservingViewModel() { + viewModelSubscription?.cancel() + viewModelSubscription = controller.objectWillChange + .context() + .sink { [view] context in + guard let typedView = view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + self.viewSynchronizer.updateView(typedView, context: context) + } + } + + // MARK: - OCKChartViewDelegate + + open func didSelectChartView(_ chartView: UIView & OCKChartDisplayable) {} +} + +public extension OCKChartViewController where Controller: OCKChartController { + + /// Initialize a view controller that displays a chart. Fetches and stays synchronized with insights. + /// - Parameter viewSynchronizer: Manages the chart view. + /// - Parameter weekOfDate: A date in the week of the insights range to fetch. + /// - Parameter configurations: Configurations used to fetch the insights ad display the data. + /// - Parameter storeManager: Wraps the store that contains the insight data to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, weekOfDate: Date, + configurations: [OCKDataSeriesConfiguration], storeManager: OCKSynchronizedStoreManager) { + let controller = Controller(weekOfDate: weekOfDate, storeManager: storeManager) + self.init(controller: controller, viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveInsights(forConfigurations: configurations, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.chartViewController(self, didEncounterError: error) + }) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactController.swift new file mode 100755 index 0000000..3ac783f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactController.swift @@ -0,0 +1,121 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Foundation +import MapKit +import MessageUI + +/// A basic controller capable of watching and updating contacts. +open class OCKContactController: OCKContactControllerProtocol, ObservableObject { + + // MARK: OCKContactControllerProtocol + + public var store: OCKAnyContactStore { storeManager.store } + public let objectWillChange: CurrentValueSubject + + // MARK: - Properties + + /// The store manager against which the task will be synchronized. + public let storeManager: OCKSynchronizedStoreManager + + private var subscription: AnyCancellable? + + // MARK: - Life Cycle + + /// Initialize with a store manager. + public required init(storeManager: OCKSynchronizedStoreManager) { + self.objectWillChange = .init(nil) + self.storeManager = storeManager + } + + // MARK: - Methods + + /// Begin observing a contact. + /// + /// - Parameter contact: The contact to watch for changes. + open func observeContact(_ contact: OCKAnyContact) { + objectWillChange.value = contact + + // Set the view model when the contact changes + subscription = storeManager.publisher(forContact: contact, categories: [.update, .add], fetchImmediately: false) + .sink { [weak self] newValue in + self?.objectWillChange.value = newValue + } + } + + /// Fetch and begin observing the first contact described by a query. + /// + /// - Parameters: + /// - query: Any contact query describing the contact to be fetched. + /// + /// - Note: If the query matches multiple contacts, the first one returned will be used. + open func fetchAndObserveContact(forQuery query: OCKAnyContactQuery, errorHandler: ((OCKStoreError) -> Void)? = nil) { + + // Fetch the contact to set as the view model value + storeManager.store.fetchAnyContacts(query: query, callbackQueue: .main) { [weak self] result in + guard let self = self else { return } + switch result { + case .failure(let error): errorHandler?(error) + case .success(let contacts): + self.objectWillChange.value = contacts.first + + // Set the view model when the contact changes + guard let id = self.objectWillChange.value?.id else { return } + self.subscription = self.storeManager.publisher(forContactID: id, categories: [.update, .add]).sink { [weak self] newValue in + self?.objectWillChange.value = newValue + } + } + } + } + + /// Fetch and begin observing the contact with the given identifier. + /// + /// - Parameters: + /// - id: The user-defined unique identifier for the contact. + open func fetchAndObserveContact(withID id: String, errorHandler: ((OCKStoreError) -> Void)? = nil) { + + // Fetch the contact to set as the view model value + storeManager.store.fetchAnyContact(withID: id, callbackQueue: .main) { [weak self] result in + guard let self = self else { return } + switch result { + case .failure(let error): errorHandler?(error) + case .success(let contact): + self.objectWillChange.value = contact + + // Set the view model when the contact changes + self.subscription = self.storeManager.publisher(forContactID: contact.id, categories: [.update, .add]).sink { [weak self] newValue in + self?.objectWillChange.value = newValue + } + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol+Methods.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol+Methods.swift new file mode 100755 index 0000000..4a7ca09 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol+Methods.swift @@ -0,0 +1,169 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Contacts +import ContactsUI +import Foundation +import MapKit +import MessageUI + +public extension OCKContactControllerProtocol { + + func initiateCall() throws -> URL { + let contact = try validateContact() + + // Ensure the contact has a phone number to call + guard let phoneNumber = contact.phoneNumbers?.first?.value else { + throw OCKContactControllerError.invalidPhoneNumber(nil) + } + + // Generate the URL to call the phone number + let filteredNumber = filteredDigits(for: phoneNumber) + guard let url = URL(string: "tel://" + filteredNumber) else { + throw OCKContactControllerError.invalidPhoneNumber(phoneNumber) + } + return url + } + + func initiateMessage() throws -> MFMessageComposeViewController { + let contact = try validateContact() + + // Ensure the contact has a phone number to message + guard let messageNumber = contact.messagingNumbers?.first?.value else { + throw OCKContactControllerError.invalidPhoneNumber(nil) + } + + // Ensure we can send messages + guard MFMessageComposeViewController.canSendText() else { + throw OCKContactControllerError.cannotSendMessages + } + + // Generate the message view controller + let filteredNumber = filteredDigits(for: messageNumber) + let composeViewController = MFMessageComposeViewController() + composeViewController.recipients = [filteredNumber] + return composeViewController + } + + func initiateEmail() throws -> MFMailComposeViewController { + let contact = try validateContact() + + // Ensure the contact has an email + guard let email = contact.emailAddresses?.first?.value else { + throw OCKContactControllerError.invalidEmail(nil) + } + + // Ensure we can send emails + guard MFMailComposeViewController.canSendMail() else { + throw OCKContactControllerError.cannotSendMail + } + + // Generate the mail view controller + let viewController = MFMailComposeViewController() + viewController.setToRecipients([email]) + return viewController + } + + func initiateAddressLookup(completion: @escaping (Result) -> Void) { + let contact: OCKAnyContact + do { + contact = try validateContact() + } catch { + completion(.failure(error)) + return + } + + // Ensure the contact has an address + guard let address = contact.address else { + completion(.failure(OCKContactControllerError.invalidAddress(nil))) + return + } + + // Generate the map item that pinpoints the contact's address + let geoloc = CLGeocoder() + geoloc.geocodePostalAddress(address) { placemarks, _ in + guard let placemark = placemarks?.first else { + completion(.failure(OCKContactControllerError.invalidAddress(address))) + return + } + let mkPlacemark = MKPlacemark(placemark: placemark) + completion(.success(MKMapItem(placemark: mkPlacemark))) + } + } + + func initiateSystemContactLookup() throws -> CNContactViewController { + let contact = try validateContact() + + // Create a CNMutableContact from an OCKAnyContact + let mutableContact = CNMutableContact(from: contact) + + // Create a view controller that displays the contact + let contactViewController = CNContactViewController(forUnknownContact: mutableContact) + contactViewController.contactStore = CNContactStore() + contactViewController.allowsEditing = false + contactViewController.view.backgroundColor = OCKStyle().color.customGroupedBackground + return contactViewController + } + + // Remove non-numeric characters + private func filteredDigits(for value: String) -> String { + return value.filter("0123456789".contains) + } + + private func validateContact() throws -> OCKAnyContact { + guard let contact = objectWillChange.value else { + throw OCKContactControllerError.nilContact + } + return contact + } +} + +private enum OCKContactControllerError: Error, LocalizedError { + case nilContact + case invalidAddress(_ address: OCKPostalAddress?) + case invalidPhoneNumber(_ phoneNumber: String?) + case invalidMessageNumber(_ messageNumber: String?) + case invalidEmail(_ email: String?) + case cannotSendMail + case cannotSendMessages + + var errorDescription: String? { + switch self { + case .nilContact: return "Contact view model is nil" + case .invalidAddress(let address): return "Invalid address: \(String(describing: address))" + case .invalidPhoneNumber(let phoneNumber): return "Invalid phone number: \(String(describing: phoneNumber))" + case .invalidMessageNumber(let messageNumber): return "Invalid message number: \(String(describing: messageNumber))" + case .invalidEmail(let email): return "Invalid email: \(String(describing: email))" + case .cannotSendMail: return "Cannot send mail" + case .cannotSendMessages: return "Cannot send messages" + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol.swift new file mode 100755 index 0000000..6eba2f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKContactControllerProtocol.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Contacts +import ContactsUI +import Foundation +import MapKit +import MessageUI + +/// Describes an object capable of tracking and updating the state of a contact. +public protocol OCKContactControllerProtocol { + + /// A reference to a writable store. + var store: OCKAnyContactStore { get } + + /// A publisher that publishers new values when the watched contact changes in the store. + var objectWillChange: CurrentValueSubject { get } + + // MARK: Implementation Provided + + /// Initiate a phone call and return the URL to be dialed. + func initiateCall() throws -> URL + + /// Initiate a message and return the `MFMessageComposeViewController` that needs to be presented. + func initiateMessage() throws -> MFMessageComposeViewController + + /// Initiate an email and return the `MFMailComposeViewController` that should be presented. + func initiateEmail() throws -> MFMailComposeViewController + + /// Lookup the address of the current contact. + /// - Parameter completion: A closure to be called with the result + func initiateAddressLookup(completion: @escaping (Result) -> Void) + + /// Attempt to find contact in the system contacts and return a `CNContactViewController` to display it. + func initiateSystemContactLookup() throws -> CNContactViewController +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKDetailedContactController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKDetailedContactController.swift new file mode 100755 index 0000000..0a50250 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKDetailedContactController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKDetailedContactController = OCKContactController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKSimpleContactController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKSimpleContactController.swift new file mode 100755 index 0000000..9bd1ea4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Controllers/OCKSimpleContactController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKSimpleContactController = OCKContactController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKContactViewSynchronizerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKContactViewSynchronizerProtocol.swift new file mode 100755 index 0000000..6152621 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKContactViewSynchronizerProtocol.swift @@ -0,0 +1,73 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Describes a type erased view synchronizer for contacts. +public protocol OCKAnyContactViewSynchronizerProtocol { + + /// Initialize a view to be synchronized. + func makeAnyView() -> UIView & OCKContactDisplayable + + /// Update a view using the given context + /// - Parameters: + /// - view: The view to be updated + /// - context: Information about the update that is occurring. + func updateAnyView(_ view: UIView & OCKContactDisplayable, context: OCKSynchronizationContext) +} + +/// Describes a view synchronizer for contacts. +public protocol OCKContactViewSynchronizerProtocol: OCKAnyContactViewSynchronizerProtocol { + + /// The type of the view that will be synchronized + associatedtype View: UIView & OCKContactDisplayable + + /// Initialize a view to be synchronized. + func makeView() -> View + + /// Update a view using the given context. + /// - Parameters: + /// - view: The view to be updated. + /// - context: Information about the update that is occurring. + func updateView(_ view: View, context: OCKSynchronizationContext) +} + +public extension OCKContactViewSynchronizerProtocol { + func makeAnyView() -> UIView & OCKContactDisplayable { + return makeView() + } + + func updateAnyView(_ view: UIView & OCKContactDisplayable, context: OCKSynchronizationContext) { + guard let typedView = view as? View else { fatalError("Type mismatch") } + updateView(typedView, context: context) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKDetailedContactViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKDetailedContactViewSynchronizer.swift new file mode 100755 index 0000000..2de1504 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKDetailedContactViewSynchronizer.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A view synchroinzer that creates and updates an `OCKDetailedContactView`. +open class OCKDetailedContactViewSynchronizer: OCKContactViewSynchronizerProtocol { + + public init() {} + + open func updateView(_ view: OCKDetailedContactView, context: OCKSynchronizationContext) { + view.updateWith(contact: context.viewModel, animated: context.animated) + } + + open func makeView() -> OCKDetailedContactView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKSimpleContactViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKSimpleContactViewSynchronizer.swift new file mode 100755 index 0000000..1df147b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/Synchronizers/OCKSimpleContactViewSynchronizer.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A view synchronizer that creates and updates an `OCKSimpleContactView`. +open class OCKSimpleContactViewSynchronizer: OCKContactViewSynchronizerProtocol { + + public init() {} + + open func updateView(_ view: OCKSimpleContactView, context: OCKSynchronizationContext) { + view.updateWith(contact: context.viewModel, animated: context.animated) + } + + open func makeView() -> OCKSimpleContactView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKContactViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKContactViewController.swift new file mode 100755 index 0000000..4f6284f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKContactViewController.swift @@ -0,0 +1,241 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import MessageUI +import UIKit + +/// Types wishing to receive updates from contact view controllers can conform to this protocol. +public protocol OCKContactViewControllerDelegate: AnyObject { + + /// Called when an unhandled error is encountered in a contact view controller. + /// - Parameters: + /// - viewController: The view controller in which the error was encountered. + /// - didEncounterError: The error that was unhandled. + func contactViewController( + _ viewController: OCKContactViewController, didEncounterError: Error) +} + +/// A view controller that displays a contact view and keep it synchronized with a store. +open class OCKContactViewController: +UIViewController, OCKContactViewDelegate, MFMessageComposeViewControllerDelegate, MFMailComposeViewControllerDelegate { + + // MARK: Properties + + /// If set, the delegate will receive updates when import events happen + public weak var delegate: OCKContactViewControllerDelegate? + + /// Handles the responsibility of updating the view when data in the store changes. + public let viewSynchronizer: ViewSynchronizer + + /// Handles the responsibility of interacting with data from the store. + public let controller: Controller + + /// The view that is being synchronized against the store. + public var contactView: ViewSynchronizer.View { + guard let view = self.view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + return view + } + + private var viewDidLoadCompletion: (() -> Void)? + private var viewModelSubscription: AnyCancellable? + + // MARK: - Life Cycle + + /// Initialize with a controller and synchronizer. + public init(controller: Controller, viewSynchronizer: ViewSynchronizer) { + self.controller = controller + self.viewSynchronizer = viewSynchronizer + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + override open func loadView() { + view = viewSynchronizer.makeView() + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func viewDidLoad() { + super.viewDidLoad() + contactView.delegate = self + + // Begin listening for changes in the view model. Note, when we subscribe to the view model, it sends its current value through the stream + startObservingViewModel() + + viewDidLoadCompletion?() + } + + // MARK: - Methods + + // Create a subscription that updates the view when the view model is updated. + private func startObservingViewModel() { + viewModelSubscription?.cancel() + viewModelSubscription = controller.objectWillChange + .context() + .sink { [view] context in + guard let typedView = view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + self.viewSynchronizer.updateView(typedView, context: context) + } + } + + @objc + private func dismissViewController() { + dismiss(animated: true, completion: nil) + } + + func handleResult(_ result: Result, successCompletion: (_ value: Success) -> Void) { + switch result { + case .failure(let error): delegate?.contactViewController(self, didEncounterError: error) + case .success(let value): successCompletion(value) + } + } + + func handleThrowable(method: () throws -> T, success: (T) -> Void) { + do { + let result = try method() + success(result) + } catch { + delegate?.contactViewController(self, didEncounterError: error) + } + } + + // MARK: - OCKContactViewDelegate + + /// Present an alert to call the contact. By default, calls the first phone number in the contact's list of phone numbers. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the call process. + open func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateCall sender: Any?) { + handleThrowable(method: controller.initiateCall) { url in + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } + } + + /// Present the UI to message the contact. By default, the first messaging number will be used. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the messaging process. + open func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateMessage sender: Any?) { + handleThrowable(method: controller.initiateMessage) { [weak self] viewController in + guard let self = self else { return } + viewController.messageComposeDelegate = self + self.present(viewController, animated: true, completion: nil) + } + } + + /// Present the UI to email the contact. By default, the first email address will be used. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the email process. + open func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateEmail sender: Any?) { + handleThrowable(method: controller.initiateEmail) { [weak self] viewController in + guard let self = self else { return } + viewController.mailComposeDelegate = self + self.present(viewController, animated: true, completion: nil) + } + } + + /// Present a map with a marker on the contact's address. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the address lookup process. + open func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateAddressLookup sender: Any?) { + controller.initiateAddressLookup { [weak self] result in + self?.handleResult(result) { mapItem in + mapItem.openInMaps(launchOptions: nil) + } + } + } + + open func didSelectContactView(_ contactView: UIView & OCKContactDisplayable) { + handleThrowable(method: controller.initiateSystemContactLookup) { [weak self] contactViewController in + contactViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, + action: #selector(dismissViewController)) + let navigationController = UINavigationController(rootViewController: contactViewController) + present(navigationController, animated: true, completion: nil) + } + } + + // MARK: - MFMessageComposeViewControllerDelegate + + open func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { + controller.dismiss(animated: true, completion: nil) + } + + // MARK: - MFMailComposeViewControllerDelegate + + open func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { + controller.dismiss(animated: true, completion: nil) + } +} + +public extension OCKContactViewController where Controller: OCKContactController { + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter viewSynchronizer: Manages the contact view. + /// - Parameter query: Used to fetch the contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, query: OCKAnyContactQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(controller: .init(storeManager: storeManager), viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveContact(forQuery: query, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.contactViewController(self, didEncounterError: error) + }) + } + } + + /// Initialize a view controller that displays a contact in the store. Stays synchronized with the provided contact. + /// - Parameter viewSynchronizer: Manages the contact view. + /// - Parameter contact: The contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, contact: OCKAnyContact, storeManager: OCKSynchronizedStoreManager) { + self.init(controller: .init(storeManager: storeManager), viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.observeContact(contact) + } + } + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter viewSynchronizer: Manages the contact view. + /// - Parameter contactID: The user-defined unique identifier for the contact to fetch. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, contactID: String, storeManager: OCKSynchronizedStoreManager) { + self.init(controller: .init(storeManager: storeManager), viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveContact(withID: contactID, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.contactViewController(self, didEncounterError: error) + }) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKDetailedContactViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKDetailedContactViewController.swift new file mode 100755 index 0000000..030a88d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKDetailedContactViewController.swift @@ -0,0 +1,57 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKDetailedContactViewController = OCKContactViewController + +public extension OCKContactViewController where Controller: OCKSimpleContactController, ViewSynchronizer == OCKDetailedContactViewSynchronizer { + + /// Initialize a view controller that displays a contact in the store. Stays synchronized with the provided contact. + /// - Parameter contact: The contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(contact: OCKAnyContact, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), contact: contact, storeManager: storeManager) + } + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter query: Used to fetch the contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(query: OCKAnyContactQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), query: query, storeManager: storeManager) + } + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter contactID: The user-defined unique identifier for the contact to fetch. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(contactID: String, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), contactID: contactID, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKSimpleContactViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKSimpleContactViewController.swift new file mode 100755 index 0000000..cc9b937 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Contact/View Controllers/OCKSimpleContactViewController.swift @@ -0,0 +1,58 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation + +public typealias OCKSimpleContactViewController = OCKContactViewController + +public extension OCKContactViewController where Controller: OCKSimpleContactController, ViewSynchronizer == OCKSimpleContactViewSynchronizer { + + /// Initialize a view controller that displays a contact in the store. Stays synchronized with the provided contact. + /// - Parameter contact: The contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(contact: OCKAnyContact, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), contact: contact, storeManager: storeManager) + } + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter query: Used to fetch the contact to display. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(query: OCKAnyContactQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), query: query, storeManager: storeManager) + } + + /// Initialize a view controller that displays a contact. Fetches and stays synchronized with the contact. + /// - Parameter contactID: The user-defined unique identifier for the contact to fetch. + /// - Parameter storeManager: Wraps the store that contains the contact to fetch. + convenience init(contactID: String, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), contactID: contactID, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKStoreNotifications.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKStoreNotifications.swift new file mode 100755 index 0000000..15dbe7a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKStoreNotifications.swift @@ -0,0 +1,70 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation + +protocol OCKStoreNotification {} + +enum OCKStoreNotificationCategory { + case add + case update + case delete +} + +struct OCKPatientNotification: OCKStoreNotification { + let patient: OCKAnyPatient + let category: OCKStoreNotificationCategory + let storeManager: OCKSynchronizedStoreManager +} + +struct OCKCarePlanNotification: OCKStoreNotification { + let carePlan: OCKAnyCarePlan + let category: OCKStoreNotificationCategory + let storeManager: OCKSynchronizedStoreManager +} + +struct OCKContactNotification: OCKStoreNotification { + let contact: OCKAnyContact + let category: OCKStoreNotificationCategory + let storeManager: OCKSynchronizedStoreManager +} + +struct OCKTaskNotification: OCKStoreNotification { + let task: OCKAnyTask + let category: OCKStoreNotificationCategory + let storeManager: OCKSynchronizedStoreManager +} + +struct OCKOutcomeNotification: OCKStoreNotification { + let outcome: OCKAnyOutcome + let category: OCKStoreNotificationCategory + let storeManager: OCKSynchronizedStoreManager +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizationContext.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizationContext.swift new file mode 100755 index 0000000..72a141a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizationContext.swift @@ -0,0 +1,76 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Combine +import Foundation + +/// Provides context for a view model value. +public struct OCKSynchronizationContext { + /// The current view model value. + public let viewModel: ViewModel + + /// The previous view model value. + public let oldViewModel: ViewModel + + /// Animated flag. + public let animated: Bool + + public init(viewModel: ViewModel, oldViewModel: ViewModel, animated: Bool) { + self.viewModel = viewModel + self.oldViewModel = oldViewModel + self.animated = animated + } +} + +protocol OptionalProtocol { + func isSome() -> Bool +} + +extension Optional: OptionalProtocol { + func isSome() -> Bool { + switch self { + case .some: return true + default: return false + } + } +} + +extension CurrentValueSubject { + func context() -> Publishers.Scan, OCKSynchronizationContext> { + // If the `Output` is an optional, only animate if the preious value was nil. This helps stops animations from occuring on the initial load. + let animated = value as? OptionalProtocol != nil ? (value as? OptionalProtocol)!.isSome() : true + let context = OCKSynchronizationContext(viewModel: value, oldViewModel: value, animated: animated) + return scan(context) { previousContext, newValue -> OCKSynchronizationContext in + let animated = previousContext.viewModel as? OptionalProtocol != nil ? + (previousContext.viewModel as? OptionalProtocol)!.isSome() : true + return OCKSynchronizationContext(viewModel: newValue, oldViewModel: previousContext.viewModel, animated: animated) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager+Publishers.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager+Publishers.swift new file mode 100755 index 0000000..46ba162 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager+Publishers.swift @@ -0,0 +1,169 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Foundation + +extension OCKSynchronizedStoreManager { + + // MARK: Patients + + func publisher(forPatient patient: OCKAnyPatient, + categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + let presentValuePublisher = Future({ completion in + self.store.fetchAnyPatient(withID: patient.id) { result in + completion(.success((try? result.get()) ?? patient)) + } + }) + + return AnyPublisher(notificationPublisher + .compactMap { $0 as? OCKPatientNotification } + .filter { $0.patient.id == patient.id && categories.contains($0.category) } + .map { $0.patient } + .prepend(presentValuePublisher)) + } + + // MARK: CarePlans + + func publisher(forCarePlan plan: OCKAnyCarePlan, + categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + let presentValuePublisher = Future { completion in + self.store.fetchAnyCarePlan(withID: plan.id) { result in + completion(.success((try? result.get()) ?? plan)) + } + } + + return AnyPublisher(notificationPublisher + .compactMap { $0 as? OCKCarePlanNotification } + .filter { $0.carePlan.id == plan.id && categories.contains($0.category) } + .map { $0.carePlan } + .prepend(presentValuePublisher)) + } + + // MARK: Contacts + + func contactsPublisher(categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + return AnyPublisher(notificationPublisher + .compactMap { $0 as? OCKContactNotification } + .filter { categories.contains($0.category) } + .map { $0.contact }) + } + + func publisher(forContactID id: String, + categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + return notificationPublisher + .compactMap { $0 as? OCKContactNotification } + .filter { $0.contact.id == id && categories.contains($0.category) } + .map { $0.contact } + .eraseToAnyPublisher() + } + + func publisher(forContact contact: OCKAnyContact, + categories: [OCKStoreNotificationCategory], + fetchImmediately: Bool = true) -> AnyPublisher { + let presentValuePublisher = Future({ completion in + self.store.fetchAnyContact(withID: contact.id) { result in + completion(.success((try? result.get()) ?? contact)) + } + }) + + let changePublisher = notificationPublisher + .compactMap { $0 as? OCKContactNotification } + .filter { $0.contact.id == contact.id && categories.contains($0.category) } + .map { $0.contact } + + return fetchImmediately ? AnyPublisher(changePublisher.prepend(presentValuePublisher)) : AnyPublisher(changePublisher) + } + + // MARK: Tasks + + func publisher(forTask task: OCKAnyTask, categories: [OCKStoreNotificationCategory], + fetchImmediately: Bool = true) -> AnyPublisher { + let presentValuePublisher = Future({ completion in + self.store.fetchAnyTask(withID: task.id) { result in + completion(.success((try? result.get()) ?? task)) + } + }) + + let publisher = notificationPublisher + .compactMap { $0 as? OCKTaskNotification } + .filter { $0.task.id == task.id && categories.contains($0.category) } + .map { $0.task } + + return fetchImmediately ? AnyPublisher(publisher.append(presentValuePublisher)) : AnyPublisher(publisher) + } + + func publisher(forEventsBelongingToTask task: OCKAnyTask, + categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + return AnyPublisher(notificationPublisher + .compactMap { $0 as? OCKOutcomeNotification } + .filter { $0.outcome.belongs(to: task) && categories.contains($0.category) } + .map { self.makeEvent(task: task, outcome: $0.outcome, keepOutcome: $0.category != .delete) }) + } + + func publisher(forEventsBelongingToTask task: OCKAnyTask, query: OCKEventQuery, + categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + + let validIndices = task.schedule.events(from: query.dateInterval.start, to: query.dateInterval.end) + .map { $0.occurrence } + + return publisher(forEventsBelongingToTask: task, categories: categories) + .filter { validIndices.contains($0.scheduleEvent.occurrence) } + .eraseToAnyPublisher() + } + + private func makeEvent(task: OCKAnyTask, outcome: OCKAnyOutcome, keepOutcome: Bool) -> OCKAnyEvent { + guard let scheduleEvent = task.schedule.event(forOccurrenceIndex: outcome.taskOccurrenceIndex) else { + fatalError("The outcome had an index of \(outcome.taskOccurrenceIndex), but the task's schedule doesn't have that many events.") + } + return OCKAnyEvent(task: task, outcome: keepOutcome ? outcome : nil, scheduleEvent: scheduleEvent) + } + + // MARK: Events + + func publisher(forEvent event: OCKAnyEvent, categories: [OCKStoreNotificationCategory]) -> AnyPublisher { + let presentValuePublisher = Future({ completion in + self.store.fetchAnyEvent(forTask: event.task, occurrence: event.scheduleEvent.occurrence, callbackQueue: .main) { result in + completion(.success((try? result.get()) ?? event)) + } + }) + + return AnyPublisher(notificationPublisher + .compactMap { $0 as? OCKOutcomeNotification } + .filter { self.outcomeMatchesEvent(outcome: $0.outcome, event: event) } + .map { self.makeEvent(task: event.task, outcome: $0.outcome, keepOutcome: $0.category != .delete) } + .prepend(presentValuePublisher)) + } + + private func outcomeMatchesEvent(outcome: OCKAnyOutcome, event: OCKAnyEvent) -> Bool { + outcome.belongs(to: event.task) && event.scheduleEvent.occurrence == outcome.taskOccurrenceIndex + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager.swift new file mode 100755 index 0000000..6b85545 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Synchronization/OCKSynchronizedStoreManager.swift @@ -0,0 +1,180 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Foundation + +/// An `OCKSynchronizedStoreManager` wraps any store that conforms to `OCKStore` and provides synchronization to CareKit view +/// controllers by listening in on the store's activity by setting itself as the store delegate. +open class OCKSynchronizedStoreManager: +OCKPatientStoreDelegate, OCKCarePlanStoreDelegate, OCKContactStoreDelegate, OCKTaskStoreDelegate, OCKOutcomeStoreDelegate { + + /// The underlying database. + public let store: OCKAnyStoreProtocol + + internal lazy var subject = PassthroughSubject() + internal private (set) lazy var notificationPublisher = subject.share() + + /// Initialize by wrapping a store. + /// + /// - Parameters: + /// - store: Any object that conforms to `OCKStoreProtocol`. + /// + /// - SeeAlso: `OCKStore` + public init(wrapping store: OCKAnyStoreProtocol) { + self.store = store + self.store.patientDelegate = self + self.store.carePlanDelegate = self + self.store.contactDelegate = self + self.store.taskDelegate = self + self.store.outcomeDelegate = self + } + + // MARK: OCKStoreDelegate Patients + + open func patientStore(_ store: OCKAnyReadOnlyPatientStore, didAddPatients patients: [OCKAnyPatient]) { + dispatchPatientNotifications(category: .add, patients: patients) + } + + open func patientStore(_ store: OCKAnyReadOnlyPatientStore, didUpdatePatients patients: [OCKAnyPatient]) { + dispatchPatientNotifications(category: .update, patients: patients) + } + + open func patientStore(_ store: OCKAnyReadOnlyPatientStore, didDeletePatients patients: [OCKAnyPatient]) { + dispatchPatientNotifications(category: .delete, patients: patients) + } + + private func dispatchPatientNotifications(category: OCKStoreNotificationCategory, patients: [OCKAnyPatient]) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + patients.forEach { + let notifications = OCKPatientNotification(patient: $0, category: category, storeManager: self) + self.subject.send(notifications) + } + } + } + + // MARK: OCKStoreDelegate CarePlans + + open func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didAddCarePlans carePlans: [OCKAnyCarePlan]) { + dispatchCarePlanNotifications(category: .add, plans: carePlans) + } + + open func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didUpdateCarePlans carePlans: [OCKAnyCarePlan]) { + dispatchCarePlanNotifications(category: .update, plans: carePlans) + } + + open func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didDeleteCarePlans carePlans: [OCKAnyCarePlan]) { + dispatchCarePlanNotifications(category: .delete, plans: carePlans) + } + + private func dispatchCarePlanNotifications(category: OCKStoreNotificationCategory, plans: [OCKAnyCarePlan]) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + plans.forEach { + let notification = OCKCarePlanNotification(carePlan: $0, category: category, storeManager: self) + self.subject.send(notification) + } + } + } + + // MARK: OCKStoreDelegate Contacts + + open func contactStore(_ store: OCKAnyReadOnlyContactStore, didAddContacts contacts: [OCKAnyContact]) { + dispatchContactNotifications(category: .add, contacts: contacts) + } + + open func contactStore(_ store: OCKAnyReadOnlyContactStore, didUpdateContacts contacts: [OCKAnyContact]) { + dispatchContactNotifications(category: .update, contacts: contacts) + } + + open func contactStore(_ store: OCKAnyReadOnlyContactStore, didDeleteContacts contacts: [OCKAnyContact]) { + dispatchContactNotifications(category: .delete, contacts: contacts) + } + + private func dispatchContactNotifications(category: OCKStoreNotificationCategory, contacts: [OCKAnyContact]) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + contacts.forEach { + let notification = OCKContactNotification(contact: $0, category: category, storeManager: self) + self.subject.send(notification) + } + } + } + + // MARK: OCKStoreDelegate Tasks + + open func taskStore(_ store: OCKAnyReadOnlyTaskStore, didAddTasks tasks: [OCKAnyTask]) { + dispatchTaskNotifications(category: .add, tasks: tasks) + } + + open func taskStore(_ store: OCKAnyReadOnlyTaskStore, didUpdateTasks tasks: [OCKAnyTask]) { + dispatchTaskNotifications(category: .update, tasks: tasks) + } + + open func taskStore(_ store: OCKAnyReadOnlyTaskStore, didDeleteTasks tasks: [OCKAnyTask]) { + dispatchTaskNotifications(category: .delete, tasks: tasks) + } + + private func dispatchTaskNotifications(category: OCKStoreNotificationCategory, tasks: [OCKAnyTask]) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + tasks.forEach { + let notification = OCKTaskNotification(task: $0, category: category, storeManager: self) + self.subject.send(notification) + } + } + } + + // MARK: OCKStoreDelegate Outcomes + + open func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didAddOutcomes outcomes: [OCKAnyOutcome]) { + dispatchOutcomeNotifications(category: .add, outcomes: outcomes) + } + + open func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didUpdateOutcomes outcomes: [OCKAnyOutcome]) { + dispatchOutcomeNotifications(category: .update, outcomes: outcomes) + } + + open func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didDeleteOutcomes outcomes: [OCKAnyOutcome]) { + dispatchOutcomeNotifications(category: .delete, outcomes: outcomes) + } + + private func dispatchOutcomeNotifications(category: OCKStoreNotificationCategory, outcomes: [OCKAnyOutcome]) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + outcomes.forEach { + let notification = OCKOutcomeNotification(outcome: $0, category: category, storeManager: self) + self.subject.send(notification) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKButtonLogTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKButtonLogTaskController.swift new file mode 100755 index 0000000..b857b8c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKButtonLogTaskController.swift @@ -0,0 +1,39 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine + +/// A task controller that keeps a record of events sorted by their dates. +open class OCKButtonLogTaskController: OCKTaskController { + override func modified(event: OCKAnyEvent) -> OCKAnyEvent { + return event.sortedOutcomeValuesByRecency() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKChecklistTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKChecklistTaskController.swift new file mode 100755 index 0000000..c96fb7e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKChecklistTaskController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKChecklistTaskController = OCKTaskController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKGridTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKGridTaskController.swift new file mode 100755 index 0000000..2c57baa --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKGridTaskController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKGridTaskController = OCKTaskController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKInstructionsTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKInstructionsTaskController.swift new file mode 100755 index 0000000..2e30351 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKInstructionsTaskController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKInstructionsTaskController = OCKTaskController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKSimpleTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKSimpleTaskController.swift new file mode 100755 index 0000000..6a4799d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKSimpleTaskController.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKSimpleTaskController = OCKTaskController diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskController.swift new file mode 100755 index 0000000..251ef23 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskController.swift @@ -0,0 +1,139 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Foundation + +/// A basic controller capable of watching and updating tasks. +open class OCKTaskController: OCKTaskControllerProtocol, ObservableObject { + + // MARK: OCKTaskControllerProtocol + + public let objectWillChange: CurrentValueSubject + public var store: OCKAnyOutcomeStore { storeManager.store } + + // MARK: - Properties + + /// The store manager against which the task will be synchronized. + public let storeManager: OCKSynchronizedStoreManager + + private var subscription: AnyCancellable? + + // MARK: - Life Cycle + + /// Initialize with a store manager. + public required init(storeManager: OCKSynchronizedStoreManager) { + self.storeManager = storeManager + self.objectWillChange = .init(nil) + } + + // MARK: - Methods + + /// Begin observing a task. + /// + /// - Parameters: + /// - task: The task to watch for changes. + /// - eventQuery: A query describing the date range over which to watch for changes. + open func fetchAndObserveEvents(forTask task: OCKAnyTask, eventQuery: OCKEventQuery, errorHandler: ((Error) -> Void)? = nil) { + fetchAndSubscribeToEvents(forTask: task, query: eventQuery, errorHandler: errorHandler) + } + + /// Begin watching events from multiple tasks for changes. + /// + /// - Parameters: + /// - taskIDs: The user-chosen unique identifiers for the tasks to be watched. + /// - eventQuery: A query describing the date range over which to watch for changes. + open func fetchAndObserveEvents(forTaskIDs taskIDs: [String], eventQuery: OCKEventQuery, errorHandler: ((Error) -> Void)? = nil) { + + // Build the task query from the event query + var taskQuery = OCKTaskQuery(dateInterval: eventQuery.dateInterval) + taskQuery.ids = taskIDs + + // Fetch the tasks, then fetch and subscribe to events for the tasks + storeManager.store.fetchAnyTasks(query: taskQuery, callbackQueue: .main) { [weak self] result in + switch result { + case .failure(let error): errorHandler?(error) + case .success(let tasks): + tasks.forEach { + self?.fetchAndSubscribeToEvents(forTask: $0, query: eventQuery, errorHandler: errorHandler) + } + } + } + } + + /// Begin watching a single task's events for changes. + /// + /// - Parameters: + /// - taskID: The user-chosen unique identifier for the task to be watched. + /// - eventQuery: A query describing the date range over which to watch for changes. + open func fetchAndObserveEvents(forTaskID taskID: String, eventQuery: OCKEventQuery, errorHandler: ((Error) -> Void)? = nil) { + fetchAndObserveEvents(forTaskIDs: [taskID], eventQuery: eventQuery, errorHandler: errorHandler) + } + + func updateViewModel(withEvents events: [OCKAnyEvent]) { + let taskIds = events.map { $0.task.id } + assert(taskIds.dropFirst().allSatisfy { $0 == taskIds.first }, "Events should belong to the same task.") + + // Add each event to the view model and set the view model value + var viewModel = self.objectWillChange.value ?? OCKTaskEvents() + events.map { self.modified(event: $0) } + .sorted(by: { $0.scheduleEvent.start < $1.scheduleEvent.start }) + .forEach { viewModel.addEvent($0) } + self.objectWillChange.value = viewModel + } + + func modified(event: OCKAnyEvent) -> OCKAnyEvent { + return event + } + + // Update the view model when events for a particular task change + func subscribeTo(eventsBelongingToTask task: OCKAnyTask, eventQuery: OCKEventQuery) { + subscription = storeManager.publisher(forEventsBelongingToTask: task, query: eventQuery, categories: [.update, .add, .delete]) + .sink { [weak self] newValue in + guard let self = self else { return } + let modifiedEvent = self.modified(event: newValue) + self.objectWillChange.value?.containsEvent(modifiedEvent) ?? false ? + self.objectWillChange.value?.updateEvent(modifiedEvent) : + self.objectWillChange.value?.addEvent(modifiedEvent) + } + } + + private func fetchAndSubscribeToEvents(forTask task: OCKAnyTask, query: OCKEventQuery, errorHandler: ((Error) -> Void)? = nil) { + storeManager.store.fetchAnyEvents(taskID: task.id, query: query, callbackQueue: .main) { [weak self] result in + switch result { + case .failure(let error): errorHandler?(error) + case .success(let events): + self?.updateViewModel(withEvents: events) + self?.subscribeTo(eventsBelongingToTask: task, eventQuery: query) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol+Methods.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol+Methods.swift new file mode 100755 index 0000000..57dce11 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol+Methods.swift @@ -0,0 +1,194 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import UIKit + +public extension OCKTaskControllerProtocol { + + func initiateDetailsViewController(forIndexPath indexPath: IndexPath) throws -> OCKDetailViewController { + _ = try validatedViewModel() + let task = try validatedEvent(forIndexPath: indexPath).task + + let detailViewController = OCKDetailViewController() + detailViewController.detailView.titleLabel.text = task.title + detailViewController.detailView.instructionsLabel.text = task.instructions + return detailViewController + } + + func setEvent(atIndexPath indexPath: IndexPath, isComplete: Bool, completion: ((Result) -> Void)?) { + let event: OCKAnyEvent + do { + _ = try validatedViewModel() + event = try validatedEvent(forIndexPath: indexPath) + } catch { + completion?(.failure(error)) + return + } + + // If the event is complete, create an outcome with a `true` value + if isComplete { + do { + let outcome = try makeOutcomeFor(event: event, withValues: [.init(true)]) + store.addAnyOutcome(outcome) { result in + switch result { + case .failure(let error): completion?(.failure(error)) + case .success(let outcome): completion?(.success(outcome)) + } + } + } catch { + completion?(.failure(error)) + } + + // if the event is incomplete, delete the outcome + } else { + guard let outcome = event.outcome else { return } + store.deleteAnyOutcome(outcome) { result in + switch result { + case .failure(let error): completion?(.failure(error)) + case .success(let outcome): completion?(.success(outcome)) + } + } + } + } + + func appendOutcomeValue(withType underlyingType: OCKOutcomeValueUnderlyingType, at indexPath: IndexPath, + completion: ((Result) -> Void)?) { + let event: OCKAnyEvent + do { + _ = try validatedViewModel() + event = try validatedEvent(forIndexPath: indexPath) + } catch { + completion?(.failure(error)) + return + } + + let value = OCKOutcomeValue(underlyingType) + + // Update the outcome with the new value + if var outcome = event.outcome { + outcome.values.append(value) + store.updateAnyOutcome(outcome, callbackQueue: .main) { result in + completion?(result.mapError { $0 as Error }) + } + + // Else Save a new outcome if one does not exist + } else { + do { + let outcome = try makeOutcomeFor(event: event, withValues: [value]) + store.addAnyOutcome(outcome, callbackQueue: .main) { result in + completion?(result.mapError { $0 as Error }) + } + } catch { + completion?(.failure(error)) + } + } + } + + func initiateDeletionForOutcomeValue(atIndex index: Int, eventIndexPath: IndexPath, + deletionCompletion: ((Result) -> Void)?) throws -> UIAlertController { + _ = try validatedViewModel() + let event = try validatedEvent(forIndexPath: eventIndexPath) + + // Make sure there is an outcome value to delete + guard + let outcome = event.outcome, + index < outcome.values.count else { + throw OCKTaskControllerError.noOutcomeValueForEvent(event, index) + } + + // Make an action sheet to delete the outcome value + let actionSheet = UIAlertController(title: loc("LOG_ENTRY"), message: nil, preferredStyle: .actionSheet) + let cancel = UIAlertAction(title: loc("CANCEL"), style: .default, handler: nil) + let delete = UIAlertAction(title: loc("DELETE"), style: .destructive) { [weak self] _ in + self?.deleteOutcomeValue(at: index, for: outcome, completion: deletionCompletion) + } + [delete, cancel].forEach { actionSheet.addAction($0) } + return actionSheet + } + + func makeOutcomeFor(event: OCKAnyEvent, withValues values: [OCKOutcomeValue]) throws -> OCKAnyOutcome { + guard + let task = event.task as? OCKTask, + let taskID = task.localDatabaseID else { throw OCKTaskControllerError.cannotMakeOutcomeFor(event) } + return OCKOutcome(taskID: taskID, taskOccurrenceIndex: event.scheduleEvent.occurrence, values: values) + } + + func eventFor(indexPath: IndexPath) -> OCKAnyEvent? { + return objectWillChange.value?.event(forIndexPath: indexPath) + } + + func validatedViewModel() throws -> OCKTaskEvents { + guard let taskEvents = objectWillChange.value else { + throw OCKTaskControllerError.nilTaskEvent + } + return taskEvents + } + + func validatedEvent(forIndexPath indexPath: IndexPath) throws -> OCKAnyEvent { + guard let event = eventFor(indexPath: indexPath) else { + throw OCKTaskControllerError.invalidIndexPath(indexPath) + } + return event + } + + private func deleteOutcomeValue(at index: Int, for outcome: OCKAnyOutcome, completion: ((Result) -> Void)?) { + // delete the whole outcome if there is only one outcome value remaining + guard outcome.values.count > 1 else { + store.deleteAnyOutcome(outcome, callbackQueue: .main) { result in + completion?(result.mapError { $0 as Error }) + } + return + } + + // Else delete the value from the outcome + var newOutcome = outcome + newOutcome.values.remove(at: index) + store.updateAnyOutcome(newOutcome, callbackQueue: .main) { result in + completion?(result.mapError { $0 as Error }) + } + } +} + +enum OCKTaskControllerError: Error, LocalizedError { + case nilTaskEvent + case invalidIndexPath(_ indexPath: IndexPath) + case noOutcomeValueForEvent(_ event: OCKAnyEvent, _ index: Int) + case cannotMakeOutcomeFor(_ event: OCKAnyEvent) + + var errorDescription: String? { + switch self { + case .nilTaskEvent: return "Task events view model is nil" + case let .noOutcomeValueForEvent(event, index): return "Event has no outcome value at index \(index): \(event)" + case .invalidIndexPath(let indexPath): return "Invalid index path \(indexPath)" + case .cannotMakeOutcomeFor(let event): return "Cannot make outcome for event: \(event)" + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol.swift new file mode 100755 index 0000000..ee8a0e8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskControllerProtocol.swift @@ -0,0 +1,83 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Combine +import Foundation +import UIKit + +/// Describes an object capable of tracking and updating the state of a task. +public protocol OCKTaskControllerProtocol: AnyObject { + + /// A reference to a writable store. + var store: OCKAnyOutcomeStore { get } + + /// A publisher that publishers new values when the watched task changes in the store. + var objectWillChange: CurrentValueSubject { get } + + // MARK: Implementation Provided + + /// Create a detail view that dispays information about a task. + /// - Parameter indexPath: Index path of the event whose task should be displayed. + func initiateDetailsViewController(forIndexPath indexPath: IndexPath) throws -> OCKDetailViewController + + /// Set the completion state for an event. + /// - Parameters: + /// - indexPath: Index path of the event. + /// - isComplete: True if the event is complete. + /// - completion: Result after etting the completion for the event. + func setEvent(atIndexPath indexPath: IndexPath, isComplete: Bool, completion: ((Result) -> Void)?) + + /// Append an outcome value to an event's outcome. + /// - Parameters: + /// - underlyingType: The value for the outcome value that is being created. + /// - indexPath: Index path of the event to which the outcome will be added. + /// - completion: Result after creating the outcome value. + func appendOutcomeValue(withType underlyingType: OCKOutcomeValueUnderlyingType, at indexPath: IndexPath, + completion: ((Result) -> Void)?) + + /// Create a view with an option to delete an outcome value. + /// - Parameters: + /// - index: The index of the outcome value to delete. + /// - eventIndexPath: The index path of the event for which the outcome value will be deleted. + /// - deletionCompletion: The result from attempting to delete the outcome value. + func initiateDeletionForOutcomeValue(atIndex index: Int, eventIndexPath: IndexPath, + deletionCompletion: ((Result) -> Void)?) throws -> UIAlertController + + /// Make an outcome for an event with the given outcome values. + /// - Parameters: + /// - event: The event for which to create the outcome. + /// - values: The outcome values to attach to the outcome. + func makeOutcomeFor(event: OCKAnyEvent, withValues values: [OCKOutcomeValue]) throws -> OCKAnyOutcome + + /// Return an event for a particular index path. Customize this method to define the indec path behavior used by other functions in this protocol. + /// - Parameter indexPath: The index path used to locate a particular event. + func eventFor(indexPath: IndexPath) -> OCKAnyEvent? +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskEvents.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskEvents.swift new file mode 100755 index 0000000..50d2bbd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Controllers/OCKTaskEvents.swift @@ -0,0 +1,108 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation + +private extension OCKAnyEvent { + + // Check if an event matches another event + func matches(_ other: OCKAnyEvent) -> Bool { + return + other.scheduleEvent.occurrence == scheduleEvent.occurrence && + other.task.id == task.id + } +} + +/// A data structure that holds events from a multiplicity of tasks. +public struct OCKTaskEvents { + + private var events: [String: [OCKAnyEvent]] = [:] // Maps a task identifier to a list of events belonging to that task + private var sortedKeys: [String] = [] // Task identifiers used to index `events`. Sorted by most recently added. + + /// Returns the first event, if any, among the events for all tasks. + public var firstEvent: OCKAnyEvent? { + return event(forIndexPath: .init(row: 0, section: 0)) + } + + /// Returns the events for the first task. + public var firstEvents: [OCKAnyEvent]? { + return events(forSection: 0) + } + + /// Adds an event. + public mutating func addEvent(_ event: OCKAnyEvent) { + let id = event.task.id + let modifiedEvent = event + + // Add the event to the dictionary based on the task identifier + if events[id] != nil { + guard events[id]!.allSatisfy({ !$0.matches(event) }) else { return } // Check for duplicates + events[id]?.append(modifiedEvent) + + // Else create a new dictionary key for the event + } else { + events[id] = [modifiedEvent] + sortedKeys.append(id) + } + } + + /// Updates an event, if it already exists, otherwise does nothing. + public mutating func updateEvent(_ event: OCKAnyEvent) { + let id = event.task.id + guard let index = events[id]?.firstIndex(where: { $0.matches(event) }) else { return } + events[id]?[index] = event + } + + /// Returns the event at an index path, where the section represents the task and the item corresponds to the event index. + public func event(forIndexPath indexPath: IndexPath) -> OCKAnyEvent? { + guard let events = events(forSection: indexPath.section) else { return nil } + guard indexPath.row < events.count else { return nil } + return events[indexPath.row] + } + + /// Returns all the events for the task in a section. + public func events(forSection section: Int) -> [OCKAnyEvent]? { + guard section < sortedKeys.count else { return nil } + guard let events = self.events[sortedKeys[section]] else { fatalError("Sorted key not found in dictionary") } + return events + } + + /// Returns true if the given event is already present. + public func containsEvent(_ event: OCKAnyEvent) -> Bool { + let id = event.task.id + for storedEvent in events[id] ?? [] { + if storedEvent.matches(event) { + return true + } + } + return false + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKButtonLogTaskViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKButtonLogTaskViewSynchronizer.swift new file mode 100755 index 0000000..393f696 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKButtonLogTaskViewSynchronizer.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A synchronizer that creates and updates an `OCKButtonLogTaskView`. +open class OCKButtonLogTaskViewSynchronizer: OCKTaskViewSynchronizerProtocol { + public init() {} + + open func updateView(_ view: OCKButtonLogTaskView, context: OCKSynchronizationContext) { + view.updateWith(event: context.viewModel?.firstEvent, animated: context.animated) + } + + open func makeView() -> OCKButtonLogTaskView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKChecklistTaskViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKChecklistTaskViewSynchronizer.swift new file mode 100755 index 0000000..db998bb --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKChecklistTaskViewSynchronizer.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A synchronizer specialized for the `OCKChecklistTaskView` +open class OCKChecklistTaskViewSynchronizer: OCKTaskViewSynchronizerProtocol { + public init() {} + + open func updateView(_ view: OCKChecklistTaskView, context: OCKSynchronizationContext) { + view.updateWith(events: context.viewModel?.firstEvents, animated: context.animated) + } + + open func makeView() -> OCKChecklistTaskView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKGridTaskViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKGridTaskViewSynchronizer.swift new file mode 100755 index 0000000..11de45f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKGridTaskViewSynchronizer.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A view synchronizer that creates and updates an `OCKGridTaskView`. +open class OCKGridTaskViewSynchronizer: OCKTaskViewSynchronizerProtocol { + public init() {} + + open func updateView(_ view: OCKGridTaskView, context: OCKSynchronizationContext) { + view.updateWith(events: context.viewModel?.firstEvents, animated: context.animated) + } + + open func makeView() -> OCKGridTaskView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKInstructionsTaskViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKInstructionsTaskViewSynchronizer.swift new file mode 100755 index 0000000..21494cf --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKInstructionsTaskViewSynchronizer.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A synchronizer specialized for the `OCKInstructionsTaskView` +open class OCKInstructionsTaskViewSynchronizer: OCKTaskViewSynchronizerProtocol { + public init() {} + + open func updateView(_ view: OCKInstructionsTaskView, context: OCKSynchronizationContext) { + view.updateWith(event: context.viewModel?.firstEvent, animated: context.animated) + } + + open func makeView() -> OCKInstructionsTaskView { + return .init() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKSimpleTaskViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKSimpleTaskViewSynchronizer.swift new file mode 100755 index 0000000..dff5523 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKSimpleTaskViewSynchronizer.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Foundation + +/// A synchronizer specialized for the `OCKSimpleTaskView` +open class OCKSimpleTaskViewSynchronizer: OCKTaskViewSynchronizerProtocol { + public init() {} + + open func makeView() -> OCKSimpleTaskView { + .init() + } + + open func updateView(_ view: OCKSimpleTaskView, context: OCKSynchronizationContext) { + view.updateWith(event: context.viewModel?.firstEvent, animated: context.animated) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKTaskViewSynchronizerProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKTaskViewSynchronizerProtocol.swift new file mode 100755 index 0000000..718c6f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/Synchronizers/OCKTaskViewSynchronizerProtocol.swift @@ -0,0 +1,74 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +/// Describes a type erased view synchronizer for tasks. +public protocol OCKAnyTaskViewSynchronizerProtocol { + + /// Initialize a view to be synchronized. + func makeAnyView() -> UIView & OCKTaskDisplayable + + /// Update a view using the given context + /// - Parameters: + /// - view: The view to be updated + /// - context: Information about the update that is occurring. + func updateAnyView(_ view: UIView & OCKTaskDisplayable, context: OCKSynchronizationContext) +} + +/// Describes a view synchronizer for tasks. +public protocol OCKTaskViewSynchronizerProtocol: OCKAnyTaskViewSynchronizerProtocol { + + /// The type of the view that will be synchronized + associatedtype View: UIView & OCKTaskDisplayable + + /// Initialize a view to be synchronized. + func makeView() -> View + + /// Update a view using the given context. + /// - Parameters: + /// - view: The view to be updated. + /// - context: Information about the update that is occurring. + func updateView(_ view: View, context: OCKSynchronizationContext) +} + +public extension OCKTaskViewSynchronizerProtocol { + func makeAnyView() -> UIView & OCKTaskDisplayable { + let view: View = makeView() + return view + } + + func updateAnyView(_ view: UIView & OCKTaskDisplayable, context: OCKSynchronizationContext) { + guard let typedView = view as? View else { fatalError("Type mismatch") } + updateView(typedView, context: context) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKButtonLogViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKButtonLogViewController.swift new file mode 100755 index 0000000..538e404 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKButtonLogViewController.swift @@ -0,0 +1,61 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKButtonLogTaskViewController = OCKTaskViewController + +public extension OCKTaskViewController where Controller: OCKTaskController, ViewSynchronizer == OCKButtonLogTaskViewSynchronizer { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), task: task, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskIDs: taskIDs, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskID: taskID, eventQuery: eventQuery, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKChecklistTaskViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKChecklistTaskViewController.swift new file mode 100755 index 0000000..f583757 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKChecklistTaskViewController.swift @@ -0,0 +1,61 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKChecklistTaskViewController = OCKTaskViewController + +public extension OCKTaskViewController where Controller: OCKTaskController, ViewSynchronizer == OCKChecklistTaskViewSynchronizer { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), task: task, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskIDs: taskIDs, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskID: taskID, eventQuery: eventQuery, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKGridTaskViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKGridTaskViewController.swift new file mode 100755 index 0000000..fa47dc4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKGridTaskViewController.swift @@ -0,0 +1,82 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitUI +import Combine +import UIKit + +/// A task view controller that displays multiple events in a grid collection view. +open class OCKGridTaskViewController: OCKTaskViewController, UICollectionViewDataSource { + + override open func viewDidLoad() { + super.viewDidLoad() + taskView.collectionView.dataSource = self + } + + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return controller.objectWillChange.value?.firstEvents?.count ?? 0 + } + + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OCKGridTaskView.defaultCellIdentifier, for: indexPath) + guard let typedCell = cell as? OCKGridTaskView.DefaultCellType else { return cell } + let event = controller.objectWillChange.value?.event(forIndexPath: indexPath) + typedCell.updateWith(event: event, animated: false) + return cell + } +} + +public extension OCKTaskViewController where Controller: OCKTaskController, ViewSynchronizer == OCKGridTaskViewSynchronizer { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), task: task, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskIDs: taskIDs, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskID: taskID, eventQuery: eventQuery, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKInstructionsTaskViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKInstructionsTaskViewController.swift new file mode 100755 index 0000000..b53ea4f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKInstructionsTaskViewController.swift @@ -0,0 +1,61 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKInstructionsTaskViewController = OCKTaskViewController + +public extension OCKTaskViewController where Controller: OCKTaskController, ViewSynchronizer == OCKInstructionsTaskViewSynchronizer { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), task: task, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskIDs: taskIDs, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskID: taskID, eventQuery: eventQuery, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKSimpleTaskViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKSimpleTaskViewController.swift new file mode 100755 index 0000000..4d42987 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKSimpleTaskViewController.swift @@ -0,0 +1,62 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A view controller that display and updates a single event that can be completed or uncompleted by tapping a large button. +open class OCKSimpleTaskViewController: OCKTaskViewController {} + +public extension OCKTaskViewController where Controller: OCKTaskController, ViewSynchronizer == OCKSimpleTaskViewSynchronizer { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), task: task, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskIDs: taskIDs, eventQuery: eventQuery, storeManager: storeManager) + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + self.init(viewSynchronizer: ViewSynchronizer(), taskID: taskID, eventQuery: eventQuery, storeManager: storeManager) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKTaskViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKTaskViewController.swift new file mode 100755 index 0000000..227bb9e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Task/View Controllers/OCKTaskViewController.swift @@ -0,0 +1,207 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import Combine +import UIKit + +/// Types wishing to receive updates from task view controllers can conform to this protocol. +public protocol OCKTaskViewControllerDelegate: AnyObject { + + /// Called when an unhandled error is encountered in a task view controller. + /// - Parameters: + /// - viewController: The view controller in which the error was encountered. + /// - didEncounterError: The error that was unhandled. + func taskViewController( + _ viewController: OCKTaskViewController, didEncounterError: Error) +} + +/// A view controller that displays a task view and keep it synchronized with a store. +open class OCKTaskViewController: +UIViewController, OCKTaskViewDelegate { + + // MARK: Properties + + /// If set, the delegate will receive updates when import events happen + public weak var delegate: OCKTaskViewControllerDelegate? + + /// Handles the responsibility of updating the view when data in the store changes. + public let viewSynchronizer: ViewSynchronizer + + /// Handles the responsibility of interacting with data from the store. + public let controller: Controller + + /// The view that is being synchronized against the store. + public var taskView: ViewSynchronizer.View { + guard let view = self.view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + return view + } + + private var viewModelSubscription: AnyCancellable? + private var viewDidLoadCompletion: (() -> Void)? + + // MARK: - Life Cycle + + /// Initialize with a controller and synchronizer. + public init(controller: Controller, viewSynchronizer: ViewSynchronizer) { + self.controller = controller + self.viewSynchronizer = viewSynchronizer + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @available(*, unavailable) + override open func loadView() { + view = viewSynchronizer.makeView() + } + + override open func viewDidLoad() { + super.viewDidLoad() + taskView.delegate = self + + // Begin listening for changes in the view model. Note, when we subscribe to the view model, it sends its current value through the stream + startObservingViewModel() + + viewDidLoadCompletion?() + } + + // MARK: - Methods + + // Create a subscription that updates the view when the view model is updated. + private func startObservingViewModel() { + viewModelSubscription?.cancel() + viewModelSubscription = controller.objectWillChange + .context() + .sink { [view] context in + guard let typedView = view as? ViewSynchronizer.View else { fatalError("View should be of type \(ViewSynchronizer.View.self)") } + self.viewSynchronizer.updateView(typedView, context: context) + } + } + + // Reset view state on a failure + // Note: This is needed because the UI assumes user interactions (lke button taps) will be successful, and displays the corresponding + // state immedately. When the interaction is actually unsuccessful, we need to reset the UI. + func resetViewState() { + controller.objectWillChange.value = controller.objectWillChange.value // triggers an update to the view + } + + func notifyDelegateAndResetViewOnError(result: Result) { + if case let .failure(error) = result { + delegate?.taskViewController(self, didEncounterError: error) + resetViewState() + } + } + + // MARK: - OCKTaskViewDelegate + + open func taskView(_ taskView: UIView & OCKTaskDisplayable, didCompleteEvent isComplete: Bool, at indexPath: IndexPath, sender: Any?) { + controller.setEvent(atIndexPath: indexPath, isComplete: isComplete, completion: notifyDelegateAndResetViewOnError) + } + + open func taskView(_ taskView: UIView & OCKTaskDisplayable, didSelectOutcomeValueAt index: Int, eventIndexPath: IndexPath, sender: Any?) { + do { + let alert = try controller.initiateDeletionForOutcomeValue(atIndex: index, eventIndexPath: eventIndexPath, + deletionCompletion: notifyDelegateAndResetViewOnError) + present(alert, animated: true, completion: nil) + } catch { + delegate?.taskViewController(self, didEncounterError: error) + } + } + + open func taskView(_ taskView: UIView & OCKTaskDisplayable, didCreateOutcomeValueAt index: Int, eventIndexPath: IndexPath, sender: Any?) { + controller.appendOutcomeValue(withType: true, at: eventIndexPath, completion: notifyDelegateAndResetViewOnError) + } + + open func didSelectTaskView(_ taskView: UIView & OCKTaskDisplayable, eventIndexPath: IndexPath) { + do { + let detailsViewController = try controller.initiateDetailsViewController(forIndexPath: eventIndexPath) + let navigationController = UINavigationController(rootViewController: detailsViewController) + present(navigationController, animated: true, completion: nil) + } catch { + delegate?.taskViewController(self, didEncounterError: error) + } + } +} + +public extension OCKTaskViewController where Controller: OCKTaskController { + + /// Initialize a view controller that displays a task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter task: The task to display. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the events to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, task: OCKAnyTask, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + let controller = Controller(storeManager: storeManager) + self.init(controller: controller, viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveEvents(forTask: task, eventQuery: eventQuery, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.taskViewController(self, didEncounterError: error) + }) + } + } + + /// Initialize a view controller that displays tasks. Fetches and stays synchronized with events for the tasks. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskIDs: User defined ids for the tasks to fetch. + /// - Parameter eventQuery: Used to fetch events for the tasks. + /// - Parameter storeManager: Wraps the store that contains the tasks and events to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, taskIDs: [String], eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + let controller = Controller(storeManager: storeManager) + self.init(controller: controller, viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveEvents(forTaskIDs: taskIDs, eventQuery: eventQuery, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.taskViewController(self, didEncounterError: error) + }) + } + } + + /// Initialize a view controller that displays task. Fetches and stays synchronized with events for the task. + /// - Parameter viewSynchronizer: Manages the task view. + /// - Parameter taskID: User defined id of the task to fetch. + /// - Parameter eventQuery: Used to fetch events for the task. + /// - Parameter storeManager: Wraps the store that contains the task and events to fetch. + convenience init(viewSynchronizer: ViewSynchronizer, taskID: String, eventQuery: OCKEventQuery, storeManager: OCKSynchronizedStoreManager) { + let controller = Controller(storeManager: storeManager) + self.init(controller: controller, viewSynchronizer: viewSynchronizer) + viewDidLoadCompletion = { [weak self] in + self?.controller.fetchAndObserveEvents(forTaskID: taskID, eventQuery: eventQuery, errorHandler: { [weak self] error in + guard let self = self else { return } + self.delegate?.taskViewController(self, didEncounterError: error) + }) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKContactUtility.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKContactUtility.swift new file mode 100755 index 0000000..afd707f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKContactUtility.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Contacts +import MapKit +import UIKit + +struct OCKContactUtility { + private static let addressFormatter: CNPostalAddressFormatter = { + let formatter = CNPostalAddressFormatter() + formatter.style = .mailingAddress + return formatter + }() + + private static let nameFormatter: PersonNameComponentsFormatter = { + let nameFormatter = PersonNameComponentsFormatter() + nameFormatter.style = .medium + return nameFormatter + }() + + static func string(from address: CNPostalAddress?) -> String? { + guard let address = address else { return nil } + return addressFormatter.string(from: address) + } + + static func string(from components: PersonNameComponents?) -> String? { + guard let components = components else { return nil } + return nameFormatter.string(from: components) + } + + static func image(from asset: String?) -> UIImage? { + guard let asset = asset else { return nil } + + // We can't be sure if the image they provide is in the assets folder, in the bundle, or in a directory. + // We can check all 3 possibilities and then choose whichever is non-nil. + let symbol = UIImage(systemName: asset) + let appAssetsImage = UIImage(named: asset) + let otherUrlImage = UIImage(contentsOfFile: asset) + return otherUrlImage ?? appAssetsImage ?? symbol + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKScheduleUtility.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKScheduleUtility.swift new file mode 100755 index 0000000..340fe0a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/Synchronized View Controllers/Utilities/OCKScheduleUtility.swift @@ -0,0 +1,132 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation + +struct OCKScheduleUtility { + + private static let timeFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.timeStyle = .short + return formatter + }() + + private static let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "M/d" + return formatter + }() + + static func scheduleLabel(for events: [OCKAnyEvent]) -> String? { + let result = [completionLabel(for: events), dateLabel(for: events)] + .compactMap { $0 } + .joined(separator: " ") + return !result.isEmpty ? result : nil + } + + static func scheduleLabel(for event: OCKAnyEvent) -> String? { + let result = [ + timeLabel(for: event), + dateLabel(forStart: event.scheduleEvent.start, end: event.scheduleEvent.end) + ] + .compactMap { $0 } + .joined(separator: " ") + + return !result.isEmpty ? result : nil + } + + static func timeLabel(for event: OCKAnyEvent, includesEnd: Bool = true) -> String { + switch event.scheduleEvent.element.duration { + + case .allDay: return "all day" + case .seconds: + if includesEnd && event.scheduleEvent.start != event.scheduleEvent.end { + let start = event.scheduleEvent.start + let end = event.scheduleEvent.end + return "\(timeFormatter.string(from: start)) to \(timeFormatter.string(from: end))" + } + } + let label = timeFormatter.string(from: event.scheduleEvent.start).description + return label + } + + static func completedTimeLabel(for event: OCKAnyEvent) -> String? { + guard let completedDate = event.outcome?.values + .max(by: { isMoreRecent(lhs: $0.createdDate, rhs: $1.createdDate) })? + .createdDate + else { return nil } + return timeFormatter.string(from: completedDate) + } + + private static func dateLabel(for events: [OCKAnyEvent]) -> String? { + guard !events.isEmpty else { return nil } + if events.count > 1 { + let schedule = events.first!.scheduleEvent + return dateLabel(forStart: schedule.start, end: schedule.end) + } + return dateLabel(forStart: events.first!.scheduleEvent.start, end: events.last!.scheduleEvent.end) + } + + private static func isMoreRecent(lhs: Date?, rhs: Date?) -> Bool { + guard let lhs = lhs else { return false } + guard let rhs = rhs else { return true } + return lhs > rhs + } + + private static func dateLabel(forStart start: Date, end: Date) -> String? { + let datesAreInSameDay = Calendar.current.isDate(start, inSameDayAs: end) + if datesAreInSameDay { + let datesAreToday = Calendar.current.isDateInToday(start) + return !datesAreToday ? "on \(label(for: start))" : nil + } + return "from \(label(for: start)) to \(label(for: end))" + } + + private static func label(for date: Date) -> String { + if Calendar.current.isDateInToday(date) { + return loc("TODAY") + } + let label = dateFormatter.string(from: date) + return label + } + + private static func completionLabel(for events: [OCKAnyEvent]) -> String? { + guard !events.isEmpty else { return nil } + let completed = events.filter { $0.outcome != nil }.count + let remaining = events.count - completed + let format = OCKLocalization.localized("EVENTS_REMAINING", + tableName: "Localizable", + bundle: nil, + value: "", + comment: "The number of events that the user has not yet marked completed") + return String.localizedStringWithFormat(format, remaining) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Calendar/OCKWeekCalendarView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Calendar/OCKWeekCalendarView+Updatable.swift new file mode 100755 index 0000000..ac3194c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Calendar/OCKWeekCalendarView+Updatable.swift @@ -0,0 +1,70 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitUI +import Foundation + +extension OCKWeekCalendarView: OCKCompletionStatesUpdatable { + func updateWith(states: [OCKCompletionRingButton.CompletionState], animated: Bool) { + // clear the view + guard !states.isEmpty else { + completionRingButtons.forEach { + $0.setState(.dimmed, animated: true) + $0.accessibilityLabel = nil + $0.accessibilityValue = nil + } + return + } + + // Else update the ring states + guard states.count == completionRingButtons.count else { + fatalError("Number of states and completions rings do not match") + } + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .short + + completionRingButtons.enumerated().forEach { index, ring in + let date = Calendar.current.date(byAdding: .day, value: index, to: dateInterval.start)! + ring.setState(states[index], animated: true) + ring.accessibilityValue = makeAccessibilityValue(for: states[index]) + ring.accessibilityLabel = dateFormatter.string(from: date) + ring.accessibilityTraits = ring.isSelected ? [.button, .selected] : [.button] + } + } + + private func makeAccessibilityValue(for state: OCKCompletionRingButton.CompletionState) -> String { + switch state { + case .dimmed: return loc("NO_TASKS") + case .empty: return loc("NO_EVENTS") + case .zero: return "0" + case .progress(let percent): return "\(Int(percent * 100))%" + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Chart/OCKCartesianChartView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Chart/OCKCartesianChartView+Updatable.swift new file mode 100755 index 0000000..59188b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Chart/OCKCartesianChartView+Updatable.swift @@ -0,0 +1,38 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI + +extension OCKCartesianChartView: OCKDataSeriesUpdatable { + func updateWith(dataSeries: [OCKDataSeries], animated: Bool) { + graphView.dataSeries = dataSeries + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKDetailedContactView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKDetailedContactView+Updatable.swift new file mode 100755 index 0000000..cfeaa57 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKDetailedContactView+Updatable.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +extension OCKDetailedContactView: OCKContactUpdatable { + func updateWith(contact: OCKAnyContact?, animated: Bool) { + headerView.updateWith(contact: contact, animated: animated) + + guard let contact = contact else { + clearView(animated: animated) + return + } + + instructionsLabel.text = contact.role + addressButton.detailLabel.text = OCKContactUtility.string(from: contact.address) + + // Show the contact buttons if the contact has relevant data + addressButton.setIsHiddenIfNeeded(contact.address == nil) + emailButton.setIsHiddenIfNeeded(contact.emailAddresses?.isEmpty ?? true) + messageButton.setIsHiddenIfNeeded(contact.messagingNumbers?.isEmpty ?? true) + callButton.setIsHiddenIfNeeded(contact.phoneNumbers?.isEmpty ?? true) + } + + private func clearView(animated: Bool) { + instructionsLabel.text = nil + addressButton.detailLabel.text = nil + [addressButton, callButton, emailButton, messageButton].forEach { $0.isHidden = true } + } +} + +private extension UIView { + func setIsHiddenIfNeeded(_ isHidden: Bool) { + guard self.isHidden != isHidden else { return } + self.isHidden = isHidden + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKSimpleContactView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKSimpleContactView+Updatable.swift new file mode 100755 index 0000000..976f26e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Contact/OCKSimpleContactView+Updatable.swift @@ -0,0 +1,38 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI + +extension OCKSimpleContactView: OCKContactUpdatable { + func updateWith(contact: OCKAnyContact?, animated: Bool) { + headerView.updateWith(contact: contact, animated: animated) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/OCKHeaderView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/OCKHeaderView+Updatable.swift new file mode 100755 index 0000000..b65dd49 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/OCKHeaderView+Updatable.swift @@ -0,0 +1,79 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI +import UIKit + +extension OCKHeaderView: OCKEventUpdatable, OCKTaskUpdatable, OCKContactUpdatable { + func updateWith(event: OCKAnyEvent?, animated: Bool) { + guard let event = event else { + clearView(animated: animated) + return + } + + titleLabel.text = event.task.title + detailLabel.text = OCKScheduleUtility.scheduleLabel(for: event) + updateAccessibilityLabel() + } + + func updateWith(events: [OCKAnyEvent]?, animated: Bool) { + guard let events = events, !events.isEmpty else { + clearView(animated: animated) + return + } + + titleLabel.text = events.first!.task.title + detailLabel.text = OCKScheduleUtility.scheduleLabel(for: events) + updateAccessibilityLabel() + } + + func updateWith(contact: OCKAnyContact?, animated: Bool) { + guard let contact = contact else { + clearView(animated: animated) + return + } + + titleLabel.text = OCKContactUtility.string(from: contact.name) + detailLabel.text = contact.title + iconImageView?.image = OCKContactUtility.image(from: contact.asset) ?? UIImage(systemName: "person.crop.circle") + updateAccessibilityLabel() + } + + private func clearView(animated: Bool) { + [titleLabel, detailLabel].forEach { $0.text = nil } + iconImageView?.image = UIImage(systemName: "person.crop.circle") + accessibilityLabel = nil + } + + private func updateAccessibilityLabel() { + accessibilityLabel = "\(titleLabel.text ?? ""), \(detailLabel.text ?? "")" + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKButtonLogTaskView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKButtonLogTaskView+Updatable.swift new file mode 100755 index 0000000..6ebf75b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKButtonLogTaskView+Updatable.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension OCKButtonLogTaskView: OCKEventUpdatable { + func updateWith(event: OCKAnyEvent?, animated: Bool) { + headerView.updateWith(event: event, animated: animated) + + guard let event = event else { + clearView(animated: animated) + return + } + + instructionsLabel.text = event.task.instructions + updateItems(withOutcomeValues: event.outcome?.values ?? [], animated: animated) + } + + private func clearView(animated: Bool) { + instructionsLabel.text = nil + clearItems(animated: animated) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKChecklistTaskView+Updatable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKChecklistTaskView+Updatable.swift new file mode 100755 index 0000000..5c20ff2 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKit/View Updaters/Task/OCKChecklistTaskView+Updatable.swift @@ -0,0 +1,73 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import CareKitUI + +extension OCKChecklistTaskView: OCKTaskUpdatable { + func updateWith(events: [OCKAnyEvent]?, animated: Bool) { + headerView.updateWith(events: events, animated: animated) + + guard let events = events, !events.isEmpty else { + clearView(animated: animated) + return + } + + instructionsLabel.text = events.first!.task.instructions + + // Update the items based on the new events + for (index, event) in events.enumerated() { + let title = event.scheduleEvent.element.text ?? OCKScheduleUtility.timeLabel(for: event) + if index < items.count { + let item = updateItem(at: index, withTitle: title) + item?.isSelected = event.outcome != nil + } else { + let item = appendItem(withTitle: title, animated: animated) + item.isSelected = event.outcome != nil + } + } + + // Remove any extraneous items + trimItems(given: events, animated: animated) + } + + private func clearView(animated: Bool) { + instructionsLabel.text = nil + clearItems(animated: animated) + } + + // Remove any items that aren't needed + private func trimItems(given events: [OCKAnyEvent], animated: Bool) { + let countToRemove = items.count - events.count + for _ in 0.. OCKWeekCalendarView { + return super.makeView() + } + + override func updateView(_ view: OCKWeekCalendarView, context: OCKSynchronizationContext<[OCKCompletionRingButton.CompletionState]>) { + super.updateView(view, context: context) + } +} + +private class MockCalendarView: UILabel, OCKCalendarDisplayable { + weak var delegate: OCKCalendarViewDelegate? + var completionStates: [OCKCompletionRingButton.CompletionState] = [] +} + +private class CustomCalendarViewSynchronizer: OCKCalendarViewSynchronizerProtocol { + func makeView() -> MockCalendarView { + return .init() + } + + func updateView(_ view: MockCalendarView, context: OCKSynchronizationContext<[OCKCompletionRingButton.CompletionState]>) { + view.completionStates = context.viewModel + } +} + +class TestCustomCalendarViewSynchronizer: XCTestCase { + + private var viewSynchronizer: CustomCalendarViewSynchronizer! + private var view: MockCalendarView! + + override func setUp() { + super.setUp() + viewSynchronizer = .init() + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertTrue(view.completionStates.isEmpty) + } + + // View should fill with data + func testDoesUpdate() { + let states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + XCTAssertEqual(view.completionStates, states) + } + + // View should be cleared after updating with a no data + func testDoesClear() { + let states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + XCTAssertFalse(view.completionStates.isEmpty) + + // Update with a no data + viewSynchronizer.updateView(view, context: .init(viewModel: [], oldViewModel: [], animated: false)) + XCTAssertTrue(view.completionStates.isEmpty) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Calendar/TestWeekCalendarViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Calendar/TestWeekCalendarViewSynchronizer.swift new file mode 100755 index 0000000..e1d7bc0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Calendar/TestWeekCalendarViewSynchronizer.swift @@ -0,0 +1,134 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation +import XCTest + +class TestWeekCalendarViewSynchronizer: XCTestCase { + + let dateFormatter: DateFormatter = { + let dateFormatter = DateFormatter() + dateFormatter.dateStyle = .short + return dateFormatter + }() + + var viewSynchronizer: OCKWeekCalendarViewSynchronizer! + var view: OCKWeekCalendarView! + + override func setUp() { + super.setUp() + viewSynchronizer = .init(weekOfDate: Date()) + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + view.completionRingButtons.forEach { + XCTAssertEqual($0.completionState, .dimmed) + } + } + + // View should fill with data + func testDoesUpdate() { + var states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.completionState, .empty) + } + + states = + Array(repeating: .empty, count: 3) + + Array(repeating: .progress(0.5), count: 4) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.enumerated().forEach { + XCTAssertEqual($1.completionState, states[$0]) + } + } + + // View should be cleared after updating with no data + func testDoesClear() { + let states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertNotEqual($0.completionState, .dimmed) + } + + viewSynchronizer.updateView(view, context: .init(viewModel: [], oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.completionState, .dimmed) + } + } + + func testAccessibilityInInitialState() { + view.accessibilityHint = loc("THREE_FINGER_SWIPE_WEEK") + view.completionRingButtons.enumerated().forEach { + XCTAssertNil($1.accessibilityValue) + XCTAssertNil($1.accessibilityLabel) + XCTAssertEqual($1.accessibilityTraits, .none) + } + } + + func testAccessibilityValueAfterUpdate() { + var states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.accessibilityValue, loc("NO_EVENTS")) + } + + states = Array(repeating: .dimmed, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.accessibilityValue, loc("NO_TASKS")) + } + + states = Array(repeating: .zero, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.accessibilityValue, loc("0")) + } + + states = Array(repeating: .progress(0.5), count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.forEach { + XCTAssertEqual($0.accessibilityValue, loc("50%")) + } + } + + func testAccessibilityAfterUpdate() { + let states: [OCKCompletionRingButton.CompletionState] = Array(repeating: .empty, count: 7) + viewSynchronizer.updateView(view, context: .init(viewModel: states, oldViewModel: [], animated: false)) + view.completionRingButtons.enumerated().forEach { + let date = Calendar.current.date(byAdding: DateComponents(day: $0), to: view.dateInterval.start)! + XCTAssertEqual($1.accessibilityLabel, dateFormatter.string(from: date)) + XCTAssertEqual($1.accessibilityTraits, $1.isSelected ? [.button, .selected] : [.button]) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCartesianChartViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCartesianChartViewSynchronizer.swift new file mode 100755 index 0000000..ef78832 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCartesianChartViewSynchronizer.swift @@ -0,0 +1,85 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation +import XCTest + +class TestCartesianChartViewSynchronizer: XCTestCase { + + var viewSynchronizer: OCKCartesianChartViewSynchronizer! + var view: OCKCartesianChartView! + let firstDayOfWeek = Calendar.current.dateInterval(of: .weekOfYear, for: Date())!.start + + override func setUp() { + super.setUp() + viewSynchronizer = .init(plotType: .bar, selectedDate: firstDayOfWeek) + view = viewSynchronizer.makeView() + } + + func testSelectedIndex() { + for offset in 0..<7 { + let date = Calendar.current.date(byAdding: DateComponents(day: offset), to: firstDayOfWeek)! + let viewSynchronizer = OCKCartesianChartViewSynchronizer(plotType: .bar, selectedDate: date) + let view = viewSynchronizer.makeView() + XCTAssertEqual(view.graphView.selectedIndex, offset) + } + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertEqual(view.graphView.selectedIndex, 0) + XCTAssertTrue(view.graphView.dataSeries.isEmpty) + } + + // View should fill with data + func testDoesUpdate() { + let dataSeries = [OCKDataSeries.mock] + viewSynchronizer.updateView(view, context: .init(viewModel: dataSeries, oldViewModel: [], animated: false)) + XCTAssertEqual(view.graphView.dataSeries, dataSeries) + } + + // View should be cleared after updating with no data + func testDoesClear() { + let dataSeries = [OCKDataSeries.mock] + viewSynchronizer.updateView(view, context: .init(viewModel: dataSeries, oldViewModel: [], animated: false)) + XCTAssertFalse(view.graphView.dataSeries.isEmpty) + + // Update with no data + viewSynchronizer.updateView(view, context: .init(viewModel: [], oldViewModel: [], animated: false)) + XCTAssertTrue(view.graphView.dataSeries.isEmpty) + } +} + +private extension OCKDataSeries { + static var mock: OCKDataSeries { + return OCKDataSeries(dataPoints: [], title: "") + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCustomChartViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCustomChartViewController.swift new file mode 100755 index 0000000..2d053d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Chart/TestCustomChartViewController.swift @@ -0,0 +1,99 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation +import XCTest + +// Just testing access level +private class CustomCartesianChartViewSynchronizer: OCKCartesianChartViewSynchronizer { + override func makeView() -> OCKCartesianChartView { + return super.makeView() + } + + override func updateView(_ view: OCKCartesianChartView, context: OCKSynchronizationContext<[OCKDataSeries]>) { + super.updateView(view, context: context) + } +} + +private class CustomChartView: UILabel, OCKChartDisplayable { + weak var delegate: OCKChartViewDelegate? +} + +private class CustomChartViewSynchronizer: OCKChartViewSynchronizerProtocol { + func makeView() -> CustomChartView { + return .init() + } + + func updateView(_ view: CustomChartView, context: OCKSynchronizationContext<[OCKDataSeries]>) { + view.text = context.viewModel.first?.title + } +} + +class TestCustomChartViewSynchronizer: XCTestCase { + + private var viewSynchronizer: CustomChartViewSynchronizer! + private var view: CustomChartView! + + override func setUp() { + super.setUp() + viewSynchronizer = .init() + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertNil(view.text) + } + + // View should fill with contact data + func testDoesUpdate() { + let dataSeries = [OCKDataSeries.mock] + viewSynchronizer.updateView(view, context: .init(viewModel: dataSeries, oldViewModel: [], animated: false)) + XCTAssertEqual(view.text, dataSeries.first?.title) + } + + // View should be cleared after updating with a nil contact + func testDoesClear() { + let dataSeries = [OCKDataSeries.mock] + viewSynchronizer.updateView(view, context: .init(viewModel: dataSeries, oldViewModel: [], animated: false)) + XCTAssertNotNil(view.text) + + // Update with a nil contact + viewSynchronizer.updateView(view, context: .init(viewModel: [], oldViewModel: [], animated: false)) + XCTAssertNil(view.text) + } +} + +private extension OCKDataSeries { + static var mock: OCKDataSeries { + return OCKDataSeries(dataPoints: [], title: "") + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestCustomContactViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestCustomContactViewSynchronizer.swift new file mode 100755 index 0000000..b506e18 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestCustomContactViewSynchronizer.swift @@ -0,0 +1,112 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation +import XCTest + +// Just testing access level +private class CustomSimpleContactViewSynchronizer: OCKSimpleContactViewSynchronizer { + override func makeView() -> OCKSimpleContactView { + return super.makeView() + } + + override func updateView(_ view: OCKSimpleContactView, context: OCKSynchronizationContext) { + super.updateView(view, context: context) + } +} + +// Just testing access level +private class CustomDetailedContactViewSynchronizer: OCKDetailedContactViewSynchronizer { + override func makeView() -> OCKDetailedContactView { + return super.makeView() + } + + override func updateView(_ view: OCKDetailedContactView, context: OCKSynchronizationContext) { + super.updateView(view, context: context) + } +} + +private class MockContactLabel: UILabel, OCKContactDisplayable { + weak var delegate: OCKContactViewDelegate? +} + +private class CustomContactViewSynchronizer: OCKContactViewSynchronizerProtocol { + func makeView() -> MockContactLabel { + return .init() + } + + func updateView(_ view: MockContactLabel, context: OCKSynchronizationContext) { + view.text = context.viewModel?.title + } +} + +private extension OCKContact { + static func mock() -> OCKContact { + var contact = OCKContact(id: "lexi-torres", givenName: "Lexi", familyName: "Torres", carePlanID: nil) + contact.title = "Family Practice" + return contact + } +} + +class TestCustomContactViewSynchronizer: XCTestCase { + + private var viewSynchronizer: CustomContactViewSynchronizer! + private var view: MockContactLabel! + + override func setUp() { + super.setUp() + viewSynchronizer = .init() + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertNil(view.text) + } + + // View should fill with contact data + func testDoesUpdate() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertEqual(view.text, contact.title) + } + + // View should be cleared after updating with a nil contact + func testDoesClear() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertNotNil(view.text) + + // Update with a nil contact + viewSynchronizer.updateView(view, context: .init(viewModel: nil, oldViewModel: nil, animated: false)) + XCTAssertNil(view.text) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestDetailedContactViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestDetailedContactViewSynchronizer.swift new file mode 100755 index 0000000..4d9870d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestDetailedContactViewSynchronizer.swift @@ -0,0 +1,165 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Contacts +import Foundation +import XCTest + +private extension OCKContact { + static func mock() -> OCKContact { + var contact = OCKContact(id: "lexi-torres", givenName: "Lexi", familyName: "Torres", carePlanID: nil) + contact.role = "Dr. Torres is a family practice doctor with over 20 years of experience." + let phoneNumbers = [OCKLabeledValue(label: "work", value: "2135558479")] + contact.phoneNumbers = phoneNumbers + contact.title = "Family Practice" + contact.messagingNumbers = phoneNumbers + contact.emailAddresses = [OCKLabeledValue(label: "work", value: "lexitorres@icloud.com")] + let address = OCKPostalAddress() + address.street = "26 E Centerline Rd" + address.city = "Victor" + address.state = "MI" + address.postalCode = "48848" + contact.address = address + return contact + } +} + +class TestDetailedContactViewSynchronizer: XCTestCase { + + let nameFormatter: PersonNameComponentsFormatter = { + let nameFormatter = PersonNameComponentsFormatter() + nameFormatter.style = .medium + return nameFormatter + }() + + let addressFormatter: CNPostalAddressFormatter = { + let formatter = CNPostalAddressFormatter() + formatter.style = .mailingAddress + return formatter + }() + + var viewSynchronizer: OCKDetailedContactViewSynchronizer! + var view: OCKDetailedContactView! + + override func setUp() { + super.setUp() + viewSynchronizer = .init() + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertNil(view.headerView.titleLabel.text) + XCTAssertNil(view.headerView.detailLabel.text) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + XCTAssertNil(view.instructionsLabel.text) + XCTAssertNil(view.addressButton.detailLabel.text) + XCTAssertFalse(view.addressButton.isHidden) + XCTAssertFalse(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertFalse(view.messageButton.isHidden) + } + + // View should fill with contact data + func testDoesUpdate() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertEqual(view.headerView.titleLabel.text, nameFormatter.string(from: contact.name)) + XCTAssertEqual(view.headerView.detailLabel.text, contact.title) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + XCTAssertEqual(view.instructionsLabel.text, contact.role) + XCTAssertEqual(view.addressButton.detailLabel.text, addressFormatter.string(from: contact.address!)) + XCTAssertFalse(view.addressButton.isHidden) + XCTAssertFalse(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertFalse(view.messageButton.isHidden) + } + + // Contact button should hide when the corresponding data is missing + func testHidesContactButtons() { + var contact = OCKContact.mock() + + contact.address = nil + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertTrue(view.addressButton.isHidden) + XCTAssertFalse(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertFalse(view.messageButton.isHidden) + + contact.messagingNumbers = nil + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertTrue(view.addressButton.isHidden) + XCTAssertFalse(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertTrue(view.messageButton.isHidden) + + contact.phoneNumbers = nil + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertTrue(view.addressButton.isHidden) + XCTAssertTrue(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertTrue(view.messageButton.isHidden) + + contact.emailAddresses = nil + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertTrue(view.addressButton.isHidden) + XCTAssertTrue(view.callButton.isHidden) + XCTAssertTrue(view.emailButton.isHidden) + XCTAssertTrue(view.messageButton.isHidden) + } + + // View should be cleared after updating with a nil contact + func testDoesClear() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertNotNil(view.headerView.titleLabel.text) + XCTAssertNotNil(view.headerView.detailLabel.text) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + XCTAssertNotNil(view.instructionsLabel.text) + XCTAssertNotNil(view.addressButton.detailLabel.text) + XCTAssertFalse(view.addressButton.isHidden) + XCTAssertFalse(view.callButton.isHidden) + XCTAssertFalse(view.emailButton.isHidden) + XCTAssertFalse(view.messageButton.isHidden) + + // Update with a nil contact + viewSynchronizer.updateView(view, context: .init(viewModel: nil, oldViewModel: nil, animated: false)) + XCTAssertNil(view.headerView.titleLabel.text) + XCTAssertNil(view.headerView.detailLabel.text) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + XCTAssertNil(view.instructionsLabel.text) + XCTAssertNil(view.addressButton.detailLabel.text) + XCTAssertTrue(view.addressButton.isHidden) + XCTAssertTrue(view.callButton.isHidden) + XCTAssertTrue(view.emailButton.isHidden) + XCTAssertTrue(view.messageButton.isHidden) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestSimpleContactViewSynchronizer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestSimpleContactViewSynchronizer.swift new file mode 100755 index 0000000..6b3ddb6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Contact/TestSimpleContactViewSynchronizer.swift @@ -0,0 +1,90 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation +import XCTest + +private extension OCKContact { + static func mock() -> OCKContact { + var contact = OCKContact(id: "lexi-torres", givenName: "Lexi", familyName: "Torres", carePlanID: nil) + contact.title = "Family Practice" + return contact + } +} + +class TestSimpleContactViewSynchronizer: XCTestCase { + + let nameFormatter: PersonNameComponentsFormatter = { + let nameFormatter = PersonNameComponentsFormatter() + nameFormatter.style = .medium + return nameFormatter + }() + + var viewSynchronizer: OCKSimpleContactViewSynchronizer! + var view: OCKSimpleContactView! + + override func setUp() { + super.setUp() + viewSynchronizer = .init() + view = viewSynchronizer.makeView() + } + + // View should be cleared in the initial state + func testInitialStateIsEmpty() { + XCTAssertNil(view.headerView.titleLabel.text) + XCTAssertNil(view.headerView.detailLabel.text) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + } + + // View should fill with contact data + func testDoesUpdate() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertEqual(view.headerView.titleLabel.text, nameFormatter.string(from: contact.name)) + XCTAssertEqual(view.headerView.detailLabel.text, contact.title) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + } + + // View should be cleared after updating with a nil contact + func testDoesClear() { + let contact = OCKContact.mock() + viewSynchronizer.updateView(view, context: .init(viewModel: contact, oldViewModel: nil, animated: false)) + XCTAssertNotNil(view.headerView.titleLabel.text) + XCTAssertNotNil(view.headerView.detailLabel.text) + XCTAssertNotNil(view.headerView.iconImageView) + + // Update with a nil contact + viewSynchronizer.updateView(view, context: .init(viewModel: nil, oldViewModel: nil, animated: false)) + XCTAssertNil(view.headerView.titleLabel.text) + XCTAssertNil(view.headerView.detailLabel.text) + XCTAssertEqual(view.headerView.iconImageView?.image, UIImage(systemName: "person.crop.circle")) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Info.plist new file mode 100755 index 0000000..6c40a6c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestDailyTasksPageViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestDailyTasksPageViewController.swift new file mode 100755 index 0000000..8a65430 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestDailyTasksPageViewController.swift @@ -0,0 +1,105 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKit +import Foundation +import XCTest + +private extension OCKTask { + static func mockWithEvents(forDate date: Date, impactsAdherence: Bool, eventCount: Int) -> (OCKTask, [OCKAnyEvent]) { + let startOfDay = Calendar.current.startOfDay(for: date) + let schedules = (1...eventCount).map { + OCKSchedule.dailyAtTime(hour: $0, minutes: 0, start: startOfDay, end: nil, text: nil) + } + var task = OCKTask(id: "doxylamine", title: "Doxylamine", carePlanID: nil, schedule: .init(composing: schedules)) + task.impactsAdherence = impactsAdherence + let events = schedules.enumerated().map { + return OCKAnyEvent(task: task, outcome: nil, scheduleEvent: $1.event(forOccurrenceIndex: $0)!) + } + return (task, events) + } +} + +class TestDailyTasksPageViewController: XCTestCase { + + var viewController: OCKDailyTasksPageViewController! + + override func setUp() { + super.setUp() + let store = OCKStore(name: "test-store", type: .inMemory) + viewController = .init(storeManager: .init(wrapping: store)) + } + + func testDelegate() { + viewController.loadViewIfNeeded() + XCTAssertTrue(viewController.tasksDelegate === viewController) + } + + func testViewControllerForTask() { + // Expecting a grid filled with the correct data + var (task, events) = OCKTask.mockWithEvents(forDate: Date(), impactsAdherence: true, eventCount: 2) + var observedViewController = viewController.dailyTasksPageViewController(viewController, viewControllerForTask: task, events: events, + eventQuery: .init(for: Date())) + let expectedViewController1 = observedViewController as? OCKGridTaskViewController + XCTAssertNotNil(expectedViewController1) + XCTAssertEqual(events.count, expectedViewController1?.controller.objectWillChange.value?.firstEvents?.count) + events.enumerated().forEach { offset, expectedEvent in + let observedEvent = expectedViewController1?.controller.objectWillChange.value?.event(forIndexPath: .init(row: offset, section: 0)) + XCTAssertEqual(expectedEvent.task.id, observedEvent?.task.id) + XCTAssertEqual(expectedEvent.scheduleEvent.occurrence, observedEvent?.scheduleEvent.occurrence) + } + + // Expecting a button log filled with the correct data + (task, events) = OCKTask.mockWithEvents(forDate: Date(), impactsAdherence: false, eventCount: 2) + observedViewController = viewController.dailyTasksPageViewController(viewController, viewControllerForTask: task, events: events, + eventQuery: .init(for: Date())) + let expectedViewController2 = observedViewController as? OCKButtonLogTaskViewController + XCTAssertNotNil(expectedViewController2) + XCTAssertEqual(events.count, expectedViewController2?.controller.objectWillChange.value?.firstEvents?.count) + events.enumerated().forEach { offset, expectedEvent in + let observedEvent = expectedViewController2?.controller.objectWillChange.value?.event(forIndexPath: .init(row: offset, section: 0)) + XCTAssertEqual(expectedEvent.task.id, observedEvent?.task.id) + XCTAssertEqual(expectedEvent.scheduleEvent.occurrence, observedEvent?.scheduleEvent.occurrence) + } + + // Expecting a simple log filled with the correct data + (task, events) = OCKTask.mockWithEvents(forDate: Date(), impactsAdherence: true, eventCount: 1) + observedViewController = viewController.dailyTasksPageViewController(viewController, viewControllerForTask: task, events: events, + eventQuery: .init(for: Date())) + let expectedViewController3 = observedViewController as? OCKSimpleTaskViewController + XCTAssertNotNil(expectedViewController3) + XCTAssertEqual(events.count, expectedViewController3?.controller.objectWillChange.value?.firstEvents?.count) + events.enumerated().forEach { offset, expectedEvent in + let observedEvent = expectedViewController3?.controller.objectWillChange.value?.event(forIndexPath: .init(row: offset, section: 0)) + XCTAssertEqual(expectedEvent.task.id, observedEvent?.task.id) + XCTAssertEqual(expectedEvent.scheduleEvent.occurrence, observedEvent?.scheduleEvent.occurrence) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestSynchronizedContext.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestSynchronizedContext.swift new file mode 100755 index 0000000..ef13971 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKit/CareKitTests/TestSynchronizedContext.swift @@ -0,0 +1,103 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKit +import Combine +import XCTest + +class TestSynchronizedContext: XCTestCase { + + var subscription: AnyCancellable? + var subject: CurrentValueSubject! + + override func setUp() { + super.setUp() + subject = CurrentValueSubject(nil) + } + + // Old value should be nil, current value should be nil + func testInitialState() { + let initialState = XCTestExpectation(description: "Initial state is valid") + subscription = subject.context().sink { context in + XCTAssertNil(context.viewModel) + XCTAssertNil(context.oldViewModel) + XCTAssertFalse(context.animated) + initialState.fulfill() + } + wait(for: [initialState], timeout: 2) + } + + // Old value should be nil, current value should be set + func testUpdatedOnce() { + let updatedState = XCTestExpectation(description: "Updated state is valid") + updatedState.expectedFulfillmentCount = 2 + var updateCount = 0 + subscription = subject.context().sink { context in + updateCount += 1 + updatedState.fulfill() + if updateCount == 2 { + XCTAssertEqual(context.viewModel, 3) + XCTAssertNil(context.oldViewModel) + XCTAssertFalse(context.animated) + } + } + subject.value = 3 + wait(for: [updatedState], timeout: 2) + } + + // Old value should be set, current value should be set + func testUpdatedTwice() { + let updatedState = XCTestExpectation(description: "Updated state is valid") + updatedState.expectedFulfillmentCount = 3 + var updateCount = 0 + subscription = subject.context().sink { context in + updateCount += 1 + updatedState.fulfill() + if updateCount == 3 { + XCTAssertEqual(context.viewModel, 4) + XCTAssertEqual(context.oldViewModel, 3) + XCTAssertTrue(context.animated) + } + } + subject.value = 3 + subject.value = 4 + wait(for: [updatedState], timeout: 2) + } + + func testNonNilViewModelAnimates() { + let subject = CurrentValueSubject(1) + let animates = XCTestExpectation(description: "Animates updates") + subscription = subject.context().sink { context in + XCTAssertTrue(context.animated) + animates.fulfill() + } + wait(for: [animates], timeout: 2) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDCarePlan.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDCarePlan.swift new file mode 100755 index 0000000..98e3326 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDCarePlan.swift @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +@objc(OCKCDCarePlan) +class OCKCDCarePlan: OCKCDVersionedObject { + @NSManaged var patient: OCKCDPatient? + @NSManaged var tasks: Set + @NSManaged var title: String + + override func validateRelationships() throws { + if !allowsMissingRelationships && patient == nil { + throw OCKStoreError.invalidValue(reason: "An OCKCDCarePlan's patient relationship may not be empty") + } + } +} + +extension OCKCDCarePlan { + override func awakeFromInsert() { + super.awakeFromInsert() + tasks = Set() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDContact.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDContact.swift new file mode 100755 index 0000000..a6fbcf6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDContact.swift @@ -0,0 +1,92 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Contacts +import Foundation + +@objc(OCKCDContact) +class OCKCDContact: OCKCDVersionedObject { + @NSManaged var carePlan: OCKCDCarePlan? + @NSManaged var name: OCKCDPersonName + @NSManaged var address: OCKCDPostalAddress? + @NSManaged var organization: String? + @NSManaged var title: String? + @NSManaged var role: String? + @NSManaged var category: String? + + @NSManaged private var emailAddressesDictionary: [String: String]? + @NSManaged private var messagingNumbersDictionary: [String: String]? + @NSManaged private var phoneNumbersDictionary: [String: String]? + @NSManaged private var otherContactInfoDictionary: [String: String]? + + var messagingNumbers: [OCKLabeledValue]? { + get { messagingNumbersDictionary?.asLabeledValues() } + set { messagingNumbersDictionary = newValue?.asDictionary() } + } + + var emailAddresses: [OCKLabeledValue]? { + get { emailAddressesDictionary?.asLabeledValues() } + set { emailAddressesDictionary = newValue?.asDictionary() } + } + + var phoneNumbers: [OCKLabeledValue]? { + get { phoneNumbersDictionary?.asLabeledValues() } + set { phoneNumbersDictionary = newValue?.asDictionary() } + } + + var otherContactInfo: [OCKLabeledValue]? { + get { otherContactInfoDictionary?.asLabeledValues() } + set { otherContactInfoDictionary = newValue?.asDictionary() } + } + + override func validateRelationships() throws { + try super.validateRelationships() + if !allowsMissingRelationships && carePlan == nil { + throw OCKStoreError.invalidValue(reason: "Care Plan relationship may not be nil!") + } + } +} + +private extension Dictionary where Key == String, Value == String { + func asLabeledValues() -> [OCKLabeledValue] { + let sortedKeys = keys.sorted() + return sortedKeys.map { OCKLabeledValue(label: $0, value: self[$0]!) } + } +} + +private extension Array where Element == OCKLabeledValue { + func asDictionary() -> [String: String] { + var dictionary = [String: String]() + for labeldValue in self { + dictionary[labeldValue.label] = labeldValue.value + } + return dictionary + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDHealthKitLinkage.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDHealthKitLinkage.swift new file mode 100755 index 0000000..e6fccd9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDHealthKitLinkage.swift @@ -0,0 +1,39 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDHealthKitLinkage) +class OCKCDHealthKitLinkage: NSManagedObject { + @NSManaged var quantityIdentifier: String + @NSManaged var quantityType: String + @NSManaged var unitString: String +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDNote.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDNote.swift new file mode 100755 index 0000000..e70b838 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDNote.swift @@ -0,0 +1,42 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +@objc(OCKCDNote) +class OCKCDNote: OCKCDObject { + @NSManaged var author: String? + @NSManaged var title: String? + @NSManaged var content: String? + + @NSManaged var patient: OCKCDPatient? + @NSManaged var plan: OCKCDCarePlan? + @NSManaged var task: OCKCDTask? +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDObject.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDObject.swift new file mode 100755 index 0000000..ce7d187 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDObject.swift @@ -0,0 +1,84 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDObject) +class OCKCDObject: NSManagedObject { + @NSManaged var createdDate: Date + @NSManaged var updatedDate: Date + @NSManaged var remoteID: String? + @NSManaged var userInfo: [String: String]? + @NSManaged var groupIdentifier: String? + @NSManaged var tags: [String]? + @NSManaged var source: String? + @NSManaged var asset: String? + @NSManaged var notes: Set? + @NSManaged var schemaVersion: String + @NSManaged var timezoneIdentifier: String + + var localDatabaseID: OCKLocalVersionID? { + guard !objectID.isTemporaryID else { return nil } + return OCKLocalVersionID(objectID.uriRepresentation().absoluteString) + } + + override func awakeFromInsert() { + super.awakeFromInsert() + createdDate = Date() + updatedDate = Date() + notes = Set() + timezoneIdentifier = TimeZone.current.identifier + } + + func copyValues(from other: OCKObjectCompatible) { + guard let context = managedObjectContext else { fatalError("Managed object context should never be nil!") } + createdDate = other.createdDate ?? Date() + updatedDate = other.updatedDate ?? Date() + groupIdentifier = other.groupIdentifier + tags = other.tags + source = other.source + remoteID = other.remoteID + userInfo = other.userInfo + asset = other.asset + timezoneIdentifier = other.timezone.identifier + notes = { + guard let otherNotes = other.notes else { return nil } + return Set(otherNotes.map { + let note = OCKCDNote(context: context) + note.author = $0.author + note.title = $0.title + note.content = $0.content + note.copyValues(from: $0) + return note + }) + }() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcome.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcome.swift new file mode 100755 index 0000000..8c1f8ec --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcome.swift @@ -0,0 +1,73 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDOutcome) +class OCKCDOutcome: OCKCDObject, OCKCDManageable { + @NSManaged var taskOccurrenceIndex: Int + @NSManaged var task: OCKCDTask? + @NSManaged var values: Set + @NSManaged var date: Date + + static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \OCKCDOutcome.createdDate, ascending: false)] + } + + override func validateForInsert() throws { + try super.validateForInsert() + try validateNoDuplicates() + } + + override func validateForUpdate() throws { + try super.validateForUpdate() + try validateNoDuplicates() + } + + private func validateNoDuplicates() throws { + guard let task = task else { throw OCKStoreError.invalidValue(reason: "Outcomes must have a task!") } + guard let context = managedObjectContext else { throw OCKStoreError.invalidValue(reason: "Context was nil!") } + let predicate = NSPredicate(format: "%K == %@ AND %K == %d AND self != %@", + #keyPath(OCKCDOutcome.task), task, + #keyPath(OCKCDOutcome.taskOccurrenceIndex), taskOccurrenceIndex, + self) + let request = OCKCDOutcome.sortedFetchRequest(withPredicate: predicate) + let numberOfDuplicates = try context.count(for: request) + if numberOfDuplicates > 0 { throw OCKStoreError.invalidValue(reason: "Duplicate outcome!") } + } +} + +extension OCKCDOutcome { + override func awakeFromInsert() { + super.awakeFromInsert() + values = Set() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcomeValue.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcomeValue.swift new file mode 100755 index 0000000..438dcc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDOutcomeValue.swift @@ -0,0 +1,111 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +@objc(OCKCDOutcomeValue) +class OCKCDOutcomeValue: OCKCDObject { + @NSManaged var kind: String? // blood sugar, body weight, etc. + @NSManaged var units: String? + @NSManaged var index: NSNumber? + @NSManaged var outcome: OCKCDOutcome? + + @NSManaged private var typeString: String + var type: OCKOutcomeValueType { + get { return OCKOutcomeValueType(rawValue: typeString)! } + set { typeString = newValue.rawValue } + } + + @NSManaged var textValue: String? + @NSManaged var binaryValue: Data? + @NSManaged var booleanValue: Bool + @NSManaged var integerValue: Int + @NSManaged var doubleValue: Double + @NSManaged var dateValue: Date? + + var value: OCKOutcomeValueUnderlyingType { + get { + switch type { + case .integer: return integerValue + case .double: return doubleValue + case .boolean: return booleanValue + case .text: return textValue! + case .binary: return binaryValue! + case .date: return dateValue! + } + } + + set { + switch newValue { + case let int as Int: + reset() + integerValue = int + type = .integer + + case let double as Double: + reset() + doubleValue = double + type = .double + + case let bool as Bool: + reset() + booleanValue = bool + type = .boolean + + case let text as String: + reset() + textValue = text + type = .text + + case let binary as Data: + reset() + binaryValue = binary + type = .binary + + case let date as Date: + reset() + dateValue = date + type = .date + + default: fatalError("Unexpected type!") + } + } + } + + private func reset() { + textValue = nil + binaryValue = nil + booleanValue = false + integerValue = 0 + doubleValue = 0 + dateValue = nil + index = nil + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPatient.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPatient.swift new file mode 100755 index 0000000..695ec36 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPatient.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDPatient) +class OCKCDPatient: OCKCDVersionedObject { + @NSManaged var name: OCKCDPersonName + @NSManaged var sex: String? + @NSManaged var birthday: Date? + @NSManaged var allergies: [String]? + @NSManaged var carePlans: Set +} + +extension OCKCDPatient { + override func awakeFromInsert() { + super.awakeFromInsert() + carePlans = Set() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPersonName.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPersonName.swift new file mode 100755 index 0000000..49f7b5e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPersonName.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDPersonName) +class OCKCDPersonName: NSManagedObject { + @NSManaged var namePrefix: String? + @NSManaged var givenName: String? + @NSManaged var middleName: String? + @NSManaged var familyName: String? + @NSManaged var nameSuffix: String? + @NSManaged var nickname: String? + @NSManaged var phoneticRepresentation: OCKCDPersonName? + + func copyPersonNameComponents(_ components: PersonNameComponents) { + namePrefix = components.namePrefix + givenName = components.givenName + middleName = components.middleName + familyName = components.familyName + nameSuffix = components.nameSuffix + nickname = components.nickname + + if let phonetic = components.phoneticRepresentation, let context = managedObjectContext { + phoneticRepresentation = OCKCDPersonName(context: context) + phoneticRepresentation?.copyPersonNameComponents(phonetic) + } + } + + func makeComponents() -> PersonNameComponents { + var components = PersonNameComponents() + components.namePrefix = namePrefix + components.givenName = givenName + components.familyName = familyName + components.nameSuffix = nameSuffix + components.nickname = nickname + components.phoneticRepresentation = phoneticRepresentation?.makeComponents() + return components + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPostalAddress.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPostalAddress.swift new file mode 100755 index 0000000..531c068 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDPostalAddress.swift @@ -0,0 +1,43 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +@objc(OCKCDPostalAddress) +class OCKCDPostalAddress: NSManagedObject { + @NSManaged var street: String + @NSManaged var subLocality: String + @NSManaged var city: String + @NSManaged var subAdministrativeArea: String + @NSManaged var state: String + @NSManaged var postalCode: String + @NSManaged var country: String + @NSManaged var isoCountryCode: String +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDScheduleElement.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDScheduleElement.swift new file mode 100755 index 0000000..94b17c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDScheduleElement.swift @@ -0,0 +1,111 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +@objc(OCKCDScheduleElement) +class OCKCDScheduleElement: OCKCDObject { + @NSManaged var text: String? + @NSManaged var task: OCKCDTask? + @NSManaged var targetValues: Set + + @NSManaged var startDate: Date + @NSManaged var endDate: Date? + + @NSManaged var secondsInterval: Int + @NSManaged var minutesInterval: Int + @NSManaged var hoursInterval: Int + @NSManaged var daysInterval: Int + @NSManaged var weeksInterval: Int + @NSManaged var monthsInterval: Int + @NSManaged var yearsInterval: Int + + // These 3 are controlled by the `duration` computed property. + @NSManaged private var durationInSeconds: Double + @NSManaged private var isAllDay: Bool + + var duration: OCKScheduleElement.Duration { + get { isAllDay ? .allDay : .seconds(durationInSeconds) } + set { + isAllDay = newValue == .allDay + durationInSeconds = newValue.seconds + } + } + + var interval: DateComponents { + get { + var interval = DateComponents() + interval.year = yearsInterval + interval.month = monthsInterval + interval.weekOfYear = weeksInterval + interval.day = daysInterval + interval.hour = hoursInterval + interval.minute = minutesInterval + interval.second = secondsInterval + return interval + } + + set { + yearsInterval = newValue.year ?? 0 + monthsInterval = newValue.month ?? 0 + weeksInterval = newValue.weekOfYear ?? 0 + daysInterval = newValue.day ?? 0 + hoursInterval = newValue.hour ?? 0 + minutesInterval = newValue.minute ?? 0 + secondsInterval = newValue.second ?? 0 + } + } +} + +extension OCKCDScheduleElement { + override func awakeFromInsert() { + super.awakeFromInsert() + targetValues = Set() + } + + override func validateForInsert() throws { + try super.validateForInsert() + try validateForConsistency() + } + + override func validateForUpdate() throws { + try super.validateForUpdate() + try validateForConsistency() + } + + private func validateForConsistency() throws { + if !atLeastOneIntervalIsNonZero { throw OCKStoreError.invalidValue(reason: "OCKScheduleElement must have at least 1 non-zero interval") } + if task == nil && targetValues.isEmpty { throw OCKStoreError.invalidValue(reason: "OCKScheduleElement must be associated with a task!") } + } + + private var atLeastOneIntervalIsNonZero: Bool { + return secondsInterval + minutesInterval + hoursInterval + daysInterval + weeksInterval + monthsInterval + yearsInterval > 0 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDTask.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDTask.swift new file mode 100755 index 0000000..7a9a1a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDTask.swift @@ -0,0 +1,55 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +@objc(OCKCDTask) +class OCKCDTask: OCKCDVersionedObject { + @NSManaged var title: String? + @NSManaged var instructions: String? + @NSManaged var impactsAdherence: Bool + @NSManaged var carePlan: OCKCDCarePlan? + @NSManaged var scheduleElements: Set + @NSManaged var outcomes: Set + @NSManaged var healthKitLinkage: OCKCDHealthKitLinkage? + + override func validateRelationships() throws { + if !allowsMissingRelationships && carePlan == nil { + throw OCKStoreError.invalidValue(reason: "An OCKCDTask's carePlan relationship may not be nil") + } + } + + override func awakeFromInsert() { + super.awakeFromInsert() + scheduleElements = Set() + outcomes = Set() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDVersionedObject.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDVersionedObject.swift new file mode 100755 index 0000000..678e3f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKCDVersionedObject.swift @@ -0,0 +1,136 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +class OCKCDVersionedObject: OCKCDObject, OCKCDManageable { + @NSManaged var id: String + @NSManaged var previous: OCKCDVersionedObject? + @NSManaged var allowsMissingRelationships: Bool + @NSManaged var effectiveDate: Date + @NSManaged var deletedDate: Date? + @NSManaged private(set) weak var next: OCKCDVersionedObject? + + var nextVersionID: OCKLocalVersionID? { + return next?.localDatabaseID + } + + var previousVersionID: OCKLocalVersionID? { + return previous?.localDatabaseID + } + + func validateRelationships() throws { + } + + static var defaultSortDescriptors: [NSSortDescriptor] { + return [NSSortDescriptor(keyPath: \OCKCDVersionedObject.effectiveDate, ascending: false)] + } + + static func fetchHeads(ids: [String], in context: NSManagedObjectContext) -> [T] { + return fetchFromStore(in: context, where: headerPredicate(for: ids)) { request in + request.fetchLimit = ids.count + request.returnsObjectsAsFaults = false + }.compactMap { $0 as? T } + } + + static var notDeletedPredicate: NSPredicate { + NSPredicate(format: "%K == nil", #keyPath(OCKCDVersionedObject.deletedDate)) + } + + static func headerPredicate(for ids: [String]) -> NSPredicate { + return NSCompoundPredicate(andPredicateWithSubpredicates: [ + NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), ids), + headerPredicate() + ]) + } + + static func headerPredicate() -> NSPredicate { + return NSCompoundPredicate(andPredicateWithSubpredicates: [ + notDeletedPredicate, + NSPredicate(format: "%K == nil", #keyPath(OCKCDVersionedObject.deletedDate)) + ]) + } + + static func newestVersionPredicate(in interval: DateInterval) -> NSPredicate { + let startsBeforeEndOfQuery = NSPredicate(format: "%K < %@", + #keyPath(OCKCDVersionedObject.effectiveDate), + interval.end as NSDate) + + let noNextVersion = NSPredicate(format: "%K == nil OR %K.effectiveDate >= %@", + #keyPath(OCKCDVersionedObject.next), + #keyPath(OCKCDVersionedObject.next), + interval.end as NSDate) + + return NSCompoundPredicate(andPredicateWithSubpredicates: [ + startsBeforeEndOfQuery, + noNextVersion + ]) + } + + static func validateNewIDs(_ ids: [String], in context: NSManagedObjectContext) throws { + guard Set(ids).count == ids.count else { + throw OCKStoreError.invalidValue(reason: "Identifiers contains duplicate values! [\(ids)]") + } + + let existingPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), ids) + let existingIDs = fetchFromStore(in: context, where: existingPredicate, configureFetchRequest: { request in + request.propertiesToFetch = [#keyPath(OCKCDVersionedObject.id)] + }).map { $0.id } + + guard existingIDs.isEmpty else { + let objectClass = String(describing: type(of: self)) + throw OCKStoreError.invalidValue(reason: "\(objectClass) with IDs [\(Set(existingIDs))] already exists!") + } + } + + static func validateUpdateIdentifiers(_ ids: [String], in context: NSManagedObjectContext) throws { + guard Set(ids).count == ids.count else { + throw OCKStoreError.invalidValue(reason: "Identifiers contains duplicate values! [\(ids)]") + } + } + + override func validateForInsert() throws { + try super.validateForInsert() + try validateRelationships() + } + + override func validateForUpdate() throws { + try super.validateForUpdate() + try validateRelationships() + } + + func copyVersionInfo(from other: OCKVersionedObjectCompatible) { + id = other.id + deletedDate = other.deletedDate + effectiveDate = other.effectiveDate + copyValues(from: other) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKManagedObjectModel.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKManagedObjectModel.swift new file mode 100755 index 0000000..18c9505 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKManagedObjectModel.swift @@ -0,0 +1,1105 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +// This file defines the CoreData database schema used by `OCKStore`. The following diagram is provided +// to help help visualize the relationships between the major entities. +// +// Patient <-------->> Care Plan <----->> Task <------>> Outcome <---->> OutcomeValue +// | | | +// |<----> Name | |<--->> ScheduleElement <--->> OutcomeValue +// | | +// | |<----> HealthKitLinkage +// | +// |<----->> Contact +// | +// |<---> Name +// |<---> Address +// +// Versioned Entities: +// - Patient +// - CarePlan +// - Contact +// - Task +// + +private let secureUnarchiver = "NSSecureUnarchiveFromData" +private let schemaVersion = OCKSemanticVersion(majorVersion: 2, minorVersion: 0, patchNumber: 1) + +private func makeManagedObjectModel() -> NSManagedObjectModel { + let managedObjectModel = NSManagedObjectModel() + + // Create entities and their attributes + let patient = makePatientEntity() + let carePlan = makeCarePlanEntity() + let contact = makeContactEntity() + let task = makeTaskEntity() + let schedule = makeScheduleEntity() + let outcome = makeOutcomeEntity() + let outcomeValue = makeOutcomeValueEntity() + let note = makeNoteEntity() + let name = makePersonNameEntity() + let address = makeAddressEntity() + let healthLink = makeHealthKitLinkageEntity() + + // MARK: Patient Relationships + + let patientToCarePlan = NSRelationshipDescription() + patientToCarePlan.name = "carePlans" + patientToCarePlan.destinationEntity = carePlan + patientToCarePlan.isOptional = true + patientToCarePlan.minCount = 0 + patientToCarePlan.maxCount = 0 + patientToCarePlan.deleteRule = .cascadeDeleteRule + + let patientToName = NSRelationshipDescription() + patientToName.name = "name" + patientToName.destinationEntity = name + patientToName.isOptional = false + patientToName.minCount = 1 + patientToName.maxCount = 1 + patientToName.deleteRule = .denyDeleteRule + + let patientToNote = NSRelationshipDescription() + patientToNote.name = "notes" + patientToNote.destinationEntity = note + patientToNote.isOptional = true + patientToNote.minCount = 0 + patientToNote.maxCount = 0 + patientToNote.deleteRule = .cascadeDeleteRule + + let patientNextVersion = NSRelationshipDescription() + patientNextVersion.name = "next" + patientNextVersion.destinationEntity = patient + patientNextVersion.isOptional = true + patientNextVersion.minCount = 0 + patientNextVersion.maxCount = 1 + patientNextVersion.deleteRule = .cascadeDeleteRule + + let patientPrevVersion = NSRelationshipDescription() + patientPrevVersion.name = "previous" + patientPrevVersion.destinationEntity = patient + patientPrevVersion.isOptional = true + patientPrevVersion.minCount = 0 + patientPrevVersion.maxCount = 1 + patientPrevVersion.deleteRule = .cascadeDeleteRule + + // MARK: Care Plan Relationships + + let carePlanToPatient = NSRelationshipDescription() + carePlanToPatient.name = "patient" + carePlanToPatient.destinationEntity = patient + carePlanToPatient.isOptional = true + carePlanToPatient.minCount = 0 + carePlanToPatient.maxCount = 1 + carePlanToPatient.deleteRule = .nullifyDeleteRule + + let carePlanToContact = NSRelationshipDescription() + carePlanToContact.name = "contacts" + carePlanToContact.destinationEntity = contact + carePlanToContact.isOptional = true + carePlanToContact.minCount = 0 + carePlanToContact.maxCount = 0 + carePlanToContact.deleteRule = .cascadeDeleteRule + + let carePlanToTask = NSRelationshipDescription() + carePlanToTask.name = "tasks" + carePlanToTask.destinationEntity = task + carePlanToTask.isOptional = true + carePlanToTask.minCount = 0 + carePlanToTask.maxCount = 0 + carePlanToTask.deleteRule = .cascadeDeleteRule + + let carePlanToNote = NSRelationshipDescription() + carePlanToNote.name = "notes" + carePlanToNote.destinationEntity = note + carePlanToNote.isOptional = true + carePlanToNote.minCount = 0 + carePlanToNote.maxCount = 0 + carePlanToNote.deleteRule = .cascadeDeleteRule + + let carePlanNextVersion = NSRelationshipDescription() + carePlanNextVersion.name = "next" + carePlanNextVersion.destinationEntity = carePlan + carePlanNextVersion.isOptional = true + carePlanNextVersion.minCount = 0 + carePlanNextVersion.maxCount = 1 + carePlanNextVersion.deleteRule = .cascadeDeleteRule + + let carePlanPrevVersion = NSRelationshipDescription() + carePlanPrevVersion.name = "previous" + carePlanPrevVersion.destinationEntity = carePlan + carePlanPrevVersion.isOptional = true + carePlanPrevVersion.minCount = 0 + carePlanPrevVersion.maxCount = 1 + carePlanPrevVersion.deleteRule = .cascadeDeleteRule + + // MARK: Conctact Relationships + + let contactToCarePlan = NSRelationshipDescription() + contactToCarePlan.name = "carePlan" + contactToCarePlan.destinationEntity = carePlan + contactToCarePlan.isOptional = true + contactToCarePlan.minCount = 0 + contactToCarePlan.maxCount = 1 + contactToCarePlan.deleteRule = .nullifyDeleteRule + + let contactToAddress = NSRelationshipDescription() + contactToAddress.name = "address" + contactToAddress.destinationEntity = address + contactToAddress.isOptional = true + contactToAddress.minCount = 0 + contactToAddress.maxCount = 1 + contactToAddress.deleteRule = .cascadeDeleteRule + + let contactToName = NSRelationshipDescription() + contactToName.name = "name" + contactToName.destinationEntity = name + contactToName.isOptional = false + contactToName.minCount = 1 + contactToName.maxCount = 1 + contactToName.deleteRule = .denyDeleteRule + + let contactToNote = NSRelationshipDescription() + contactToNote.name = "notes" + contactToNote.destinationEntity = note + contactToNote.isOptional = true + contactToNote.minCount = 0 + contactToNote.maxCount = 0 + contactToNote.deleteRule = .cascadeDeleteRule + + let contactNextVersion = NSRelationshipDescription() + contactNextVersion.name = "next" + contactNextVersion.destinationEntity = contact + contactNextVersion.isOptional = true + contactNextVersion.minCount = 0 + contactNextVersion.maxCount = 1 + contactNextVersion.deleteRule = .cascadeDeleteRule + + let contactPrevVersion = NSRelationshipDescription() + contactPrevVersion.name = "previous" + contactPrevVersion.destinationEntity = contact + contactPrevVersion.isOptional = true + contactPrevVersion.minCount = 0 + contactPrevVersion.maxCount = 1 + contactPrevVersion.deleteRule = .cascadeDeleteRule + + // MARK: Task Relationships + + let taskToCarePlan = NSRelationshipDescription() + taskToCarePlan.name = "carePlan" + taskToCarePlan.destinationEntity = carePlan + taskToCarePlan.isOptional = true + taskToCarePlan.minCount = 0 + taskToCarePlan.maxCount = 1 + taskToCarePlan.deleteRule = .nullifyDeleteRule + + let taskToSchedule = NSRelationshipDescription() + taskToSchedule.name = "scheduleElements" + taskToSchedule.destinationEntity = schedule + taskToSchedule.isOptional = false + taskToSchedule.minCount = 1 + taskToSchedule.maxCount = 0 + taskToSchedule.deleteRule = .cascadeDeleteRule + + let taskToOutcome = NSRelationshipDescription() + taskToOutcome.name = "outcomes" + taskToOutcome.destinationEntity = outcome + taskToOutcome.isOptional = true + taskToOutcome.minCount = 0 + taskToOutcome.maxCount = 0 + taskToOutcome.deleteRule = .cascadeDeleteRule + + let taskToHealth = NSRelationshipDescription() + taskToHealth.name = "healthKitLinkage" + taskToHealth.destinationEntity = healthLink + taskToHealth.isOptional = true + taskToHealth.minCount = 0 + taskToHealth.maxCount = 1 + taskToHealth.deleteRule = .cascadeDeleteRule + + let taskToNote = NSRelationshipDescription() + taskToNote.name = "notes" + taskToNote.destinationEntity = note + taskToNote.isOptional = true + taskToNote.minCount = 0 + taskToNote.maxCount = 0 + taskToNote.deleteRule = .cascadeDeleteRule + + let taskNextVersion = NSRelationshipDescription() + taskNextVersion.name = "next" + taskNextVersion.destinationEntity = task + taskNextVersion.isOptional = true + taskNextVersion.minCount = 0 + taskNextVersion.maxCount = 1 + taskNextVersion.deleteRule = .cascadeDeleteRule + + let taskPrevVersion = NSRelationshipDescription() + taskPrevVersion.name = "previous" + taskPrevVersion.destinationEntity = task + taskPrevVersion.isOptional = true + taskPrevVersion.minCount = 0 + taskPrevVersion.maxCount = 1 + taskPrevVersion.deleteRule = .cascadeDeleteRule + + // MARK: Schedule Relationships + + let scheduleToValue = NSRelationshipDescription() + scheduleToValue.name = "targetValues" + scheduleToValue.destinationEntity = outcomeValue + scheduleToValue.isOptional = true + scheduleToValue.minCount = 0 + scheduleToValue.maxCount = 0 + scheduleToValue.deleteRule = .cascadeDeleteRule + + let scheduleToTask = NSRelationshipDescription() + scheduleToTask.name = "task" + scheduleToTask.destinationEntity = task + scheduleToTask.isOptional = true + scheduleToTask.minCount = 0 + scheduleToTask.maxCount = 1 + scheduleToTask.deleteRule = .denyDeleteRule + + let scheduleToNote = NSRelationshipDescription() + scheduleToNote.name = "notes" + scheduleToNote.destinationEntity = note + scheduleToNote.isOptional = true + scheduleToNote.minCount = 0 + scheduleToNote.maxCount = 0 + scheduleToNote.deleteRule = .cascadeDeleteRule + + // MARK: Outcome Relationships + + let outcomeToTask = NSRelationshipDescription() + outcomeToTask.name = "task" + outcomeToTask.destinationEntity = task + outcomeToTask.isOptional = true + outcomeToTask.minCount = 0 + outcomeToTask.maxCount = 1 + outcomeToTask.deleteRule = .nullifyDeleteRule + + let outcomeToValue = NSRelationshipDescription() + outcomeToValue.name = "values" + outcomeToValue.destinationEntity = outcomeValue + outcomeToValue.isOptional = true + outcomeToValue.minCount = 0 + outcomeToValue.maxCount = 0 + outcomeToValue.deleteRule = .cascadeDeleteRule + + let outcomeToNote = NSRelationshipDescription() + outcomeToNote.name = "notes" + outcomeToNote.destinationEntity = note + outcomeToNote.isOptional = true + outcomeToNote.minCount = 0 + outcomeToNote.maxCount = 0 + outcomeToNote.deleteRule = .cascadeDeleteRule + + // MARK: OutcomeValue Relationships + + let outcomeValueToOutcome = NSRelationshipDescription() + outcomeValueToOutcome.name = "outcome" + outcomeValueToOutcome.destinationEntity = outcome + outcomeValueToOutcome.isOptional = true + outcomeValueToOutcome.minCount = 0 + outcomeValueToOutcome.maxCount = 1 + outcomeValueToOutcome.deleteRule = .nullifyDeleteRule + + let outcomeValueToSchedule = NSRelationshipDescription() + outcomeValueToSchedule.name = "scheduleElement" + outcomeValueToSchedule.destinationEntity = schedule + outcomeValueToSchedule.isOptional = true + outcomeValueToSchedule.minCount = 0 + outcomeValueToSchedule.maxCount = 1 + outcomeValueToSchedule.deleteRule = .nullifyDeleteRule + + let outcomeValueToNote = NSRelationshipDescription() + outcomeValueToNote.name = "notes" + outcomeValueToNote.destinationEntity = note + outcomeValueToNote.isOptional = true + outcomeValueToNote.minCount = 0 + outcomeValueToNote.maxCount = 0 + outcomeValueToNote.deleteRule = .cascadeDeleteRule + + // MARK: Note Relationships + + let noteToPatient = NSRelationshipDescription() + noteToPatient.name = "patient" + noteToPatient.destinationEntity = patient + noteToPatient.isOptional = true + noteToPatient.minCount = 0 + noteToPatient.maxCount = 1 + noteToPatient.deleteRule = .nullifyDeleteRule + + let noteToCarePlan = NSRelationshipDescription() + noteToCarePlan.name = "plan" + noteToCarePlan.destinationEntity = carePlan + noteToCarePlan.isOptional = true + noteToCarePlan.minCount = 0 + noteToCarePlan.maxCount = 1 + noteToCarePlan.deleteRule = .nullifyDeleteRule + + let noteToContact = NSRelationshipDescription() + noteToContact.name = "contact" + noteToContact.destinationEntity = contact + noteToContact.isOptional = true + noteToContact.minCount = 0 + noteToContact.maxCount = 1 + noteToContact.deleteRule = .nullifyDeleteRule + + let noteToTask = NSRelationshipDescription() + noteToTask.name = "task" + noteToTask.destinationEntity = task + noteToTask.isOptional = true + noteToTask.minCount = 0 + noteToTask.maxCount = 0 + noteToTask.deleteRule = .nullifyDeleteRule + + let noteToOutcome = NSRelationshipDescription() + noteToOutcome.name = "outcome" + noteToOutcome.destinationEntity = outcome + noteToOutcome.isOptional = true + noteToOutcome.minCount = 0 + noteToOutcome.maxCount = 1 + noteToOutcome.deleteRule = .nullifyDeleteRule + + let noteToOutcomeValue = NSRelationshipDescription() + noteToOutcomeValue.name = "response" + noteToOutcomeValue.destinationEntity = outcomeValue + noteToOutcomeValue.isOptional = true + noteToOutcomeValue.minCount = 0 + noteToOutcomeValue.maxCount = 1 + noteToOutcomeValue.deleteRule = .nullifyDeleteRule + + let noteToSchedule = NSRelationshipDescription() + noteToSchedule.name = "scheduleElement" + noteToSchedule.destinationEntity = schedule + noteToSchedule.isOptional = true + noteToSchedule.minCount = 0 + noteToSchedule.maxCount = 1 + noteToSchedule.deleteRule = .nullifyDeleteRule + + let noteToChildNote = NSRelationshipDescription() + noteToChildNote.name = "notes" + noteToChildNote.destinationEntity = note + noteToChildNote.isOptional = true + noteToChildNote.minCount = 0 + noteToChildNote.maxCount = 0 + noteToChildNote.deleteRule = .cascadeDeleteRule + + let noteToParentNote = NSRelationshipDescription() + noteToParentNote.name = "parentNote" + noteToParentNote.destinationEntity = note + noteToParentNote.isOptional = true + noteToParentNote.minCount = 0 + noteToParentNote.maxCount = 1 + noteToParentNote.deleteRule = .nullifyDeleteRule + + // MARK: Name Relationships + + let nameToPatient = NSRelationshipDescription() + nameToPatient.name = "patient" + nameToPatient.destinationEntity = patient + nameToPatient.isOptional = true + nameToPatient.minCount = 0 + nameToPatient.maxCount = 1 + nameToPatient.deleteRule = .denyDeleteRule + + let nameToContact = NSRelationshipDescription() + nameToContact.name = "contact" + nameToContact.destinationEntity = contact + nameToContact.isOptional = true + nameToContact.minCount = 0 + nameToContact.maxCount = 1 + nameToContact.deleteRule = .denyDeleteRule + + let nameToPhoneticName = NSRelationshipDescription() + nameToPhoneticName.name = "phoneticRepresentation" + nameToPhoneticName.destinationEntity = name + nameToPhoneticName.isOptional = true + nameToPhoneticName.minCount = 0 + nameToPhoneticName.maxCount = 1 + nameToPhoneticName.deleteRule = .cascadeDeleteRule + + let nameToParentName = NSRelationshipDescription() + nameToParentName.name = "parent" + nameToParentName.destinationEntity = name + nameToParentName.isOptional = true + nameToParentName.minCount = 0 + nameToParentName.maxCount = 1 + nameToParentName.deleteRule = .nullifyDeleteRule + + // MARK: Address Relationships + + let addressToContact = NSRelationshipDescription() + addressToContact.name = "contact" + addressToContact.destinationEntity = contact + addressToContact.isOptional = false + addressToContact.minCount = 1 + addressToContact.maxCount = 1 + addressToContact.deleteRule = .nullifyDeleteRule + + // MARK: HealthKitLinkage Relationships + + let healthToTask = NSRelationshipDescription() + healthToTask.name = "task" + healthToTask.destinationEntity = task + healthToTask.isOptional = false + healthToTask.minCount = 1 + healthToTask.maxCount = 1 + healthToTask.deleteRule = .nullifyDeleteRule + + // MARK: Inverse Relationships + + patientToCarePlan.inverseRelationship = carePlanToPatient + patientToName.inverseRelationship = nameToPatient + patientToNote.inverseRelationship = noteToPatient + patientNextVersion.inverseRelationship = patientPrevVersion + patientPrevVersion.inverseRelationship = patientNextVersion + + carePlanToPatient.inverseRelationship = patientToCarePlan + carePlanToContact.inverseRelationship = contactToCarePlan + carePlanToTask.inverseRelationship = taskToCarePlan + carePlanToNote.inverseRelationship = noteToCarePlan + carePlanNextVersion.inverseRelationship = carePlanPrevVersion + carePlanPrevVersion.inverseRelationship = carePlanNextVersion + + contactToCarePlan.inverseRelationship = carePlanToContact + contactToAddress.inverseRelationship = addressToContact + contactToName.inverseRelationship = nameToContact + contactToNote.inverseRelationship = noteToContact + contactNextVersion.inverseRelationship = contactPrevVersion + contactPrevVersion.inverseRelationship = contactNextVersion + + taskToCarePlan.inverseRelationship = carePlanToTask + taskToNote.inverseRelationship = noteToTask + taskToOutcome.inverseRelationship = outcomeToTask + taskToHealth.inverseRelationship = healthToTask + taskToSchedule.inverseRelationship = scheduleToTask + taskNextVersion.inverseRelationship = taskPrevVersion + taskPrevVersion.inverseRelationship = taskNextVersion + + outcomeToTask.inverseRelationship = taskToOutcome + outcomeToValue.inverseRelationship = outcomeValueToOutcome + outcomeToNote.inverseRelationship = noteToOutcome + + outcomeValueToOutcome.inverseRelationship = outcomeToValue + outcomeValueToSchedule.inverseRelationship = scheduleToValue + outcomeValueToNote.inverseRelationship = noteToOutcomeValue + + noteToPatient.inverseRelationship = patientToNote + noteToCarePlan.inverseRelationship = carePlanToNote + noteToContact.inverseRelationship = contactToNote + noteToTask.inverseRelationship = taskToNote + noteToOutcome.inverseRelationship = outcomeToNote + noteToOutcomeValue.inverseRelationship = outcomeValueToNote + noteToSchedule.inverseRelationship = scheduleToNote + noteToChildNote.inverseRelationship = noteToParentNote + noteToParentNote.inverseRelationship = noteToChildNote + + nameToPatient.inverseRelationship = patientToName + nameToContact.inverseRelationship = contactToName + nameToPhoneticName.inverseRelationship = nameToParentName + nameToParentName.inverseRelationship = nameToPhoneticName + + scheduleToValue.inverseRelationship = outcomeValueToSchedule + scheduleToTask.inverseRelationship = taskToSchedule + scheduleToNote.inverseRelationship = noteToSchedule + + addressToContact.inverseRelationship = contactToAddress + + healthToTask.inverseRelationship = taskToHealth + + // Add relationship properties to entities + + patient.properties += [ + patientToCarePlan, patientToName, patientToNote, + patientNextVersion, patientPrevVersion + ] + + carePlan.properties += [ + carePlanToPatient, carePlanToNote, carePlanToContact, + carePlanToTask, carePlanNextVersion, carePlanPrevVersion + ] + + contact.properties += [ + contactToCarePlan, contactToNote, contactToName, + contactToAddress, contactNextVersion, contactPrevVersion + ] + + task.properties += [taskToCarePlan, taskToOutcome, taskToHealth, taskToSchedule, taskToNote, taskNextVersion, taskPrevVersion] + + outcome.properties += [outcomeToTask, outcomeToValue, outcomeToNote] + + outcomeValue.properties += [outcomeValueToOutcome, outcomeValueToSchedule, outcomeValueToNote] + + schedule.properties += [scheduleToTask, scheduleToNote, scheduleToValue] + + address.properties += [addressToContact] + + healthLink.properties += [healthToTask] + + name.properties += [nameToPatient, nameToContact, nameToPhoneticName, nameToParentName] + + note.properties += [ + noteToPatient, noteToCarePlan, noteToContact, noteToTask, noteToSchedule, + noteToOutcome, noteToOutcomeValue, noteToChildNote, noteToParentNote + ] + + managedObjectModel.entities = [ + patient, carePlan, contact, task, outcome, + outcomeValue, schedule, note, name, address, + healthLink + ] + + return managedObjectModel +} + +// MARK: Entities + +private func makePatientEntity() -> NSEntityDescription { + let patientEntity = NSEntityDescription() + patientEntity.name = String(describing: OCKCDPatient.self) + patientEntity.managedObjectClassName = String(describing: OCKCDPatient.self) + + let birthday = NSAttributeDescription() + birthday.name = "birthday" + birthday.attributeType = .dateAttributeType + birthday.isOptional = true + + let sex = NSAttributeDescription() + sex.name = "sex" + sex.attributeType = .stringAttributeType + sex.isOptional = true + + let allergies = NSAttributeDescription() + allergies.name = "allergies" + allergies.attributeType = .transformableAttributeType + allergies.valueTransformerName = secureUnarchiver + allergies.isOptional = true + + patientEntity.properties = makeObjectAttributes() + makeVersionedAttributes() + [birthday, sex, allergies] + return patientEntity +} + +private func makeCarePlanEntity() -> NSEntityDescription { + let planEntity = NSEntityDescription() + planEntity.name = String(describing: OCKCDCarePlan.self) + planEntity.managedObjectClassName = String(describing: OCKCDCarePlan.self) + + let title = NSAttributeDescription() + title.name = "title" + title.attributeType = .stringAttributeType + title.isOptional = false + + planEntity.properties = makeObjectAttributes() + makeVersionedAttributes() + [title] + return planEntity +} + +private func makeContactEntity() -> NSEntityDescription { + let contactEntity = NSEntityDescription() + contactEntity.name = String(describing: OCKCDContact.self) + contactEntity.managedObjectClassName = String(describing: OCKCDContact.self) + + let organization = NSAttributeDescription() + organization.name = "organization" + organization.attributeType = .stringAttributeType + organization.isOptional = true + + let title = NSAttributeDescription() + title.name = "title" + title.attributeType = .stringAttributeType + title.isOptional = true + + let role = NSAttributeDescription() + role.name = "role" + role.attributeType = .stringAttributeType + role.isOptional = true + + let category = NSAttributeDescription() + category.name = "category" + category.attributeType = .stringAttributeType + category.isOptional = true + + let email = NSAttributeDescription() + email.name = "emailAddressesDictionary" + email.attributeType = .transformableAttributeType + email.isOptional = true + email.valueTransformerName = secureUnarchiver + + let message = NSAttributeDescription() + message.name = "messagingNumbersDictionary" + message.attributeType = .transformableAttributeType + message.isOptional = true + message.valueTransformerName = secureUnarchiver + + let phone = NSAttributeDescription() + phone.name = "phoneNumbersDictionary" + phone.attributeType = .transformableAttributeType + phone.isOptional = true + phone.valueTransformerName = secureUnarchiver + + let other = NSAttributeDescription() + other.name = "otherContactInfoDictionary" + other.attributeType = .transformableAttributeType + other.isOptional = true + other.valueTransformerName = secureUnarchiver + + contactEntity.properties = makeObjectAttributes() + makeVersionedAttributes() + [ + organization, title, role, category, email, message, phone, other + ] + return contactEntity +} + +private func makeTaskEntity() -> NSEntityDescription { + let taskEntity = NSEntityDescription() + taskEntity.name = String(describing: OCKCDTask.self) + taskEntity.managedObjectClassName = String(describing: OCKCDTask.self) + + let title = NSAttributeDescription() + title.name = "title" + title.attributeType = .stringAttributeType + title.isOptional = true + + let instructions = NSAttributeDescription() + instructions.name = "instructions" + instructions.attributeType = .stringAttributeType + instructions.isOptional = true + + let impactsAdherence = NSAttributeDescription() + impactsAdherence.name = "impactsAdherence" + impactsAdherence.attributeType = .booleanAttributeType + impactsAdherence.isOptional = false + impactsAdherence.defaultValue = true + + taskEntity.properties = makeObjectAttributes() + makeVersionedAttributes() + [ + title, instructions, impactsAdherence + ] + + return taskEntity +} + +private func makeScheduleEntity() -> NSEntityDescription { + let scheduleEntity = NSEntityDescription() + scheduleEntity.name = String(describing: OCKCDScheduleElement.self) + scheduleEntity.managedObjectClassName = String(describing: OCKCDScheduleElement.self) + + let text = NSAttributeDescription() + text.name = "text" + text.attributeType = .stringAttributeType + text.isOptional = true + + let duration = NSAttributeDescription() + duration.name = "durationInSeconds" + duration.attributeType = .doubleAttributeType + duration.isOptional = false + duration.defaultValue = 0 + + let isAllDay = NSAttributeDescription() + isAllDay.name = "isAllDay" + isAllDay.attributeType = .booleanAttributeType + isAllDay.isOptional = false + isAllDay.defaultValue = false + + let start = NSAttributeDescription() + start.name = "startDate" + start.attributeType = .dateAttributeType + start.isOptional = false + + let end = NSAttributeDescription() + end.name = "endDate" + end.attributeType = .dateAttributeType + end.isOptional = true + + let seconds = NSAttributeDescription() + seconds.name = "secondsInterval" + seconds.attributeType = .integer64AttributeType + seconds.isOptional = false + seconds.defaultValue = 0 + + let minutes = NSAttributeDescription() + minutes.name = "minutesInterval" + minutes.attributeType = .integer64AttributeType + minutes.isOptional = false + minutes.defaultValue = 0 + + let hours = NSAttributeDescription() + hours.name = "hoursInterval" + hours.attributeType = .integer64AttributeType + hours.isOptional = false + hours.defaultValue = 0 + + let days = NSAttributeDescription() + days.name = "daysInterval" + days.attributeType = .integer64AttributeType + days.isOptional = false + days.defaultValue = 0 + + let weeks = NSAttributeDescription() + weeks.name = "weeksInterval" + weeks.attributeType = .integer64AttributeType + weeks.isOptional = false + weeks.defaultValue = 0 + + let months = NSAttributeDescription() + months.name = "monthsInterval" + months.attributeType = .integer64AttributeType + months.isOptional = false + months.defaultValue = 0 + + let years = NSAttributeDescription() + years.name = "yearsInterval" + years.attributeType = .integer64AttributeType + years.isOptional = false + years.defaultValue = 0 + + scheduleEntity.properties = makeObjectAttributes() + [ + text, duration, isAllDay, start, end, seconds, + minutes, hours, days, weeks, months, years + ] + + return scheduleEntity +} + +private func makeOutcomeEntity() -> NSEntityDescription { + let outcomeEntity = NSEntityDescription() + outcomeEntity.name = String(describing: OCKCDOutcome.self) + outcomeEntity.managedObjectClassName = String(describing: OCKCDOutcome.self) + + let index = NSAttributeDescription() + index.name = "taskOccurrenceIndex" + index.attributeType = .integer64AttributeType + index.isOptional = false + + let date = NSAttributeDescription() + date.name = "date" + date.attributeType = .dateAttributeType + date.isOptional = false + + outcomeEntity.properties = makeObjectAttributes() + [index, date] + return outcomeEntity +} + +private func makeOutcomeValueEntity() -> NSEntityDescription { + let valueEntity = NSEntityDescription() + valueEntity.name = String(describing: OCKCDOutcomeValue.self) + valueEntity.managedObjectClassName = String(describing: OCKCDOutcomeValue.self) + + let kind = NSAttributeDescription() + kind.name = "kind" + kind.attributeType = .stringAttributeType + kind.isOptional = true + + let units = NSAttributeDescription() + units.name = "units" + units.attributeType = .stringAttributeType + units.isOptional = true + + let index = NSAttributeDescription() + index.name = "index" + index.attributeType = .integer64AttributeType + index.isOptional = true + + let type = NSAttributeDescription() + type.name = "typeString" + type.attributeType = .stringAttributeType + type.isOptional = false + + let text = NSAttributeDescription() + text.name = "textValue" + text.attributeType = .stringAttributeType + text.isOptional = true + + let binary = NSAttributeDescription() + binary.name = "binaryValue" + binary.attributeType = .binaryDataAttributeType + binary.isOptional = true + + let bool = NSAttributeDescription() + bool.name = "booleanValue" + bool.attributeType = .booleanAttributeType + bool.isOptional = true + + let integer = NSAttributeDescription() + integer.name = "integerValue" + integer.attributeType = .integer64AttributeType + integer.isOptional = true + + let double = NSAttributeDescription() + double.name = "doubleValue" + double.attributeType = .doubleAttributeType + double.isOptional = true + + let date = NSAttributeDescription() + date.name = "dateValue" + date.attributeType = .dateAttributeType + date.isOptional = true + + valueEntity.properties = makeObjectAttributes() + + [kind, units, index, type, text, binary, bool, integer, double, date] + return valueEntity +} + +private func makeNoteEntity() -> NSEntityDescription { + let noteEntity = NSEntityDescription() + noteEntity.name = String(describing: OCKCDNote.self) + noteEntity.managedObjectClassName = String(describing: OCKCDNote.self) + + let author = NSAttributeDescription() + author.name = "author" + author.attributeType = .stringAttributeType + author.isOptional = true + + let content = NSAttributeDescription() + content.name = "content" + content.attributeType = .stringAttributeType + content.isOptional = true + + let title = NSAttributeDescription() + title.name = "title" + title.attributeType = .stringAttributeType + title.isOptional = true + + noteEntity.properties = makeObjectAttributes() + [author, content, title] + return noteEntity +} + +private func makePersonNameEntity() -> NSEntityDescription { + let nameEntity = NSEntityDescription() + nameEntity.name = String(describing: OCKCDPersonName.self) + nameEntity.managedObjectClassName = String(describing: OCKCDPersonName.self) + + let prefix = NSAttributeDescription() + prefix.name = "namePrefix" + prefix.attributeType = .stringAttributeType + prefix.isOptional = true + + let given = NSAttributeDescription() + given.name = "givenName" + given.attributeType = .stringAttributeType + given.isOptional = true + + let middle = NSAttributeDescription() + middle.name = "middleName" + middle.attributeType = .stringAttributeType + middle.isOptional = true + + let family = NSAttributeDescription() + family.name = "familyName" + family.attributeType = .stringAttributeType + family.isOptional = true + + let suffix = NSAttributeDescription() + suffix.name = "nameSuffix" + suffix.attributeType = .stringAttributeType + suffix.isOptional = true + + let nickname = NSAttributeDescription() + nickname.name = "nickname" + nickname.attributeType = .stringAttributeType + nickname.isOptional = true + + nameEntity.properties = [prefix, given, middle, family, suffix, nickname] + return nameEntity +} + +private func makeAddressEntity() -> NSEntityDescription { + let addressEntity = NSEntityDescription() + addressEntity.name = String(describing: OCKCDPostalAddress.self) + addressEntity.managedObjectClassName = String(describing: OCKCDPostalAddress.self) + + let street = NSAttributeDescription() + street.name = "street" + street.attributeType = .stringAttributeType + street.isOptional = false + street.defaultValue = "" + + let subLocality = NSAttributeDescription() + subLocality.name = "subLocality" + subLocality.attributeType = .stringAttributeType + subLocality.isOptional = false + subLocality.defaultValue = "" + + let city = NSAttributeDescription() + city.name = "city" + city.attributeType = .stringAttributeType + city.isOptional = false + city.defaultValue = "" + + let subAdminArea = NSAttributeDescription() + subAdminArea.name = "subAdministrativeArea" + subAdminArea.attributeType = .stringAttributeType + subAdminArea.isOptional = false + subAdminArea.defaultValue = "" + + let state = NSAttributeDescription() + state.name = "state" + state.attributeType = .stringAttributeType + state.isOptional = false + state.defaultValue = "" + + let zip = NSAttributeDescription() + zip.name = "postalCode" + zip.attributeType = .stringAttributeType + zip.isOptional = false + zip.defaultValue = "" + + let country = NSAttributeDescription() + country.name = "country" + country.attributeType = .stringAttributeType + country.isOptional = false + country.defaultValue = "" + + let isoCode = NSAttributeDescription() + isoCode.name = "isoCountryCode" + isoCode.attributeType = .stringAttributeType + isoCode.isOptional = false + isoCode.defaultValue = "" + + addressEntity.properties = [street, subLocality, city, subAdminArea, state, zip, country, isoCode] + + return addressEntity +} + +private func makeHealthKitLinkageEntity() -> NSEntityDescription { + let linkEntity = NSEntityDescription() + linkEntity.name = String(describing: OCKCDHealthKitLinkage.self) + linkEntity.managedObjectClassName = String(describing: OCKCDHealthKitLinkage.self) + + let quanityID = NSAttributeDescription() + quanityID.name = "quantityIdentifier" + quanityID.attributeType = .stringAttributeType + quanityID.isOptional = false + + let quantityType = NSAttributeDescription() + quantityType.name = "quantityType" + quantityType.attributeType = .stringAttributeType + quantityType.isOptional = false + + let unit = NSAttributeDescription() + unit.name = "unitString" + unit.attributeType = .stringAttributeType + unit.isOptional = false + + linkEntity.properties = [quanityID, quantityType, unit] + + return linkEntity +} + + +// MARK: Attributes + +private func makeVersionedAttributes() -> [NSAttributeDescription] { + let id = NSAttributeDescription() + id.name = "id" + id.attributeType = .stringAttributeType + id.isOptional = false + + let deletedDate = NSAttributeDescription() + deletedDate.name = "deletedDate" + deletedDate.attributeType = .dateAttributeType + deletedDate.isOptional = true + + let effectiveDate = NSAttributeDescription() + effectiveDate.name = "effectiveDate" + effectiveDate.attributeType = .dateAttributeType + effectiveDate.isOptional = false + + return [id, effectiveDate, deletedDate] +} + +private func makeObjectAttributes() -> [NSAttributeDescription] { + let allowsMissingRelationships = NSAttributeDescription() + allowsMissingRelationships.name = "allowsMissingRelationships" + allowsMissingRelationships.attributeType = .booleanAttributeType + allowsMissingRelationships.defaultValue = true + allowsMissingRelationships.isOptional = false + + let asset = NSAttributeDescription() + asset.name = "asset" + asset.attributeType = .stringAttributeType + asset.isOptional = true + asset.defaultValue = nil + + let createdDate = NSAttributeDescription() + createdDate.name = "createdDate" + createdDate.attributeType = .dateAttributeType + createdDate.isOptional = false + + let groupIdentifier = NSAttributeDescription() + groupIdentifier.name = "groupIdentifier" + groupIdentifier.attributeType = .stringAttributeType + groupIdentifier.isOptional = true + + let remoteID = NSAttributeDescription() + remoteID.name = "remoteID" + remoteID.attributeType = .stringAttributeType + remoteID.isOptional = true + + let source = NSAttributeDescription() + source.name = "source" + source.attributeType = .stringAttributeType + source.isOptional = true + + let tags = NSAttributeDescription() + tags.name = "tags" + tags.attributeType = .transformableAttributeType + tags.valueTransformerName = secureUnarchiver + tags.isOptional = true + + let updatedDate = NSAttributeDescription() + updatedDate.name = "updatedDate" + updatedDate.attributeType = .dateAttributeType + updatedDate.isOptional = true + + let userInfo = NSAttributeDescription() + userInfo.name = "userInfo" + userInfo.attributeType = .transformableAttributeType + userInfo.isOptional = true + userInfo.valueTransformerName = secureUnarchiver + + let schema = NSAttributeDescription() + schema.name = "schemaVersion" + schema.attributeType = .stringAttributeType + schema.isOptional = false + schema.defaultValue = schemaVersion.description + + let timezone = NSAttributeDescription() + timezone.name = "timezoneIdentifier" + timezone.attributeType = .stringAttributeType + timezone.isOptional = false + + return [allowsMissingRelationships, asset, createdDate, schema, + groupIdentifier, remoteID, source, tags, updatedDate, + userInfo, timezone] +} + +let sharedManagedObjectModel = makeManagedObjectModel() + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+CarePlans.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+CarePlans.swift new file mode 100755 index 0000000..f5e9216 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+CarePlans.swift @@ -0,0 +1,210 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +extension OCKStore { + + /// Determines whether or not this store is intended to handle adding, updating, and deleting a certain care plan. + /// - Parameter plan: The care plan that is about to be modified. + /// - Note: `OCKStore` returns true for all care plans. + open func shouldHandleCarePlan(_ plan: OCKAnyCarePlan) -> Bool { true } + + /// Determines whether or not this store is intended to handle fetching for a certain query. + /// - Parameter query: The query that will be performed. + /// - Note: `OCKStore` returns true for all cases. + open func shouldHandleCarePlanQuery(query: OCKAnyCarePlanQuery) -> Bool { true } + + open func fetchCarePlans(query: OCKCarePlanQuery = OCKCarePlanQuery(), + callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[OCKCarePlan], OCKStoreError>) -> Void) { + context.perform { + do { + let predicate = try self.buildPredicate(for: query) + let persistedPlans = OCKCDCarePlan.fetchFromStore(in: self.context, where: predicate) { fetchRequest in + fetchRequest.fetchLimit = query.limit ?? 0 + fetchRequest.fetchOffset = query.offset + fetchRequest.sortDescriptors = self.buildSortDescriptors(from: query) + } + + let plans = persistedPlans.map(self.makePlan) + callbackQueue.async { completion(.success(plans)) } + } catch { + self.context.rollback() + callbackQueue.async { completion(.failure(.fetchFailed(reason: "Building predicate failed: \(error.localizedDescription)"))) } + } + } + } + + open func addCarePlans(_ plans: [OCKCarePlan], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKCarePlan], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try OCKCDCarePlan.validateNewIDs(plans.map { $0.id }, in: self.context) + let persistablePlans = plans.map(self.createCarePlan) + try self.context.save() + let addedPlans = persistablePlans.map(self.makePlan) + callbackQueue.async { + self.carePlanDelegate?.carePlanStore(self, didAddCarePlans: addedPlans) + completion?(.success(addedPlans)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.addFailed(reason: "Failed to add OCKCarePlans: [\(plans)]. \(error.localizedDescription)"))) + } + } + } + } + + open func updateCarePlans(_ plans: [OCKCarePlan], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKCarePlan], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let ids = plans.map { $0.id } + try OCKCDCarePlan.validateUpdateIdentifiers(ids, in: self.context) + let updatedPlans = try self.performVersionedUpdate(values: plans, addNewVersion: self.createCarePlan) + try self.context.save() + let plans = updatedPlans.map(self.makePlan) + callbackQueue.async { + self.carePlanDelegate?.carePlanStore(self, didUpdateCarePlans: plans) + completion?(.success(updatedPlans.map(self.makePlan))) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.updateFailed(reason: "Failed to update OCKCarePlans: \(plans). \(error.localizedDescription)"))) + } + } + } + } + + open func deleteCarePlans(_ plans: [OCKCarePlan], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKCarePlan], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let markedPlans: [OCKCDCarePlan] = try self.performDeletion(values: plans) + try self.context.save() + let deletedPlans = markedPlans.map(self.makePlan) + callbackQueue.async { + self.carePlanDelegate?.carePlanStore(self, didDeleteCarePlans: deletedPlans) + completion?(.success(deletedPlans)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.deleteFailed(reason: "Failed to update OCKCarePlans: [\(plans)]. \(error.localizedDescription)"))) + } + } + } + } + + // MARK: Private + + /// - Remark: This does not commit the transaction. After calling this function one or more times, you must call `context.save()` in order to + /// persist the changes to disk. This is an optimization to allow batching. + /// - Remark: You should verify that the object does not already exist in the database and validate its values before calling this method. + private func createCarePlan(from plan: OCKCarePlan) -> OCKCDCarePlan { + let persistablePlan = OCKCDCarePlan(context: context) + persistablePlan.copyVersionInfo(from: plan) + persistablePlan.allowsMissingRelationships = configuration.allowsEntitiesWithMissingRelationships + persistablePlan.title = plan.title + if let patientId = plan.patientID { persistablePlan.patient = try? fetchObject(havingLocalID: patientId) } + return persistablePlan + } + + /// - Remark: This method is intended to create a value type struct from a *persisted* NSManagedObject. Calling this method with an + /// object that is not yet commited is a programmer error. + private func makePlan(from object: OCKCDCarePlan) -> OCKCarePlan { + assert(object.localDatabaseID != nil, "Don't this method with an object that isn't saved yet") + var plan = OCKCarePlan(id: object.id, title: object.title, patientID: object.patient?.localDatabaseID) + plan.copyVersionedValues(from: object) + return plan + } + + private func buildPredicate(for query: OCKCarePlanQuery) throws -> NSPredicate { + var predicate = OCKCDVersionedObject.notDeletedPredicate + + if let interval = query.dateInterval { + let intervalPredicate = OCKCDVersionedObject.newestVersionPredicate(in: interval) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, intervalPredicate]) + } + + if !query.ids.isEmpty { + let idPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), query.ids) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, idPredicate]) + } + + if !query.versionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "self IN %@", try query.versionIDs.map(objectID)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.remoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDObject.remoteID), query.remoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.patientIDs.isEmpty { + let patientPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDCarePlan.patient.id), query.patientIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, patientPredicate]) + } + + if !query.patientVersionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDCarePlan.patient), try query.patientVersionIDs.map(fetchObject)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.patientRemoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDCarePlan.patient.remoteID), query.patientRemoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.groupIdentifiers.isEmpty { + predicate = predicate.including(groupIdentifiers: query.groupIdentifiers) + } + + if !query.tags.isEmpty { + predicate = predicate.including(tags: query.tags) + } + + return predicate + } + + private func buildSortDescriptors(from query: OCKCarePlanQuery?) -> [NSSortDescriptor] { + guard let orders = query?.extendedSortDescriptors else { return [] } + return orders.map { order -> NSSortDescriptor in + switch order { + case .effectiveDate(let ascending): return NSSortDescriptor(keyPath: \OCKCDCarePlan.effectiveDate, ascending: ascending) + case .title(let ascending): return NSSortDescriptor(keyPath: \OCKCDCarePlan.title, ascending: ascending) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Contacts.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Contacts.swift new file mode 100755 index 0000000..bd10671 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Contacts.swift @@ -0,0 +1,247 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +extension OCKStore { + + open func fetchContacts(query: OCKContactQuery = OCKContactQuery(), callbackQueue: DispatchQueue = .main, + completion: @escaping (Result<[OCKContact], OCKStoreError>) -> Void) { + context.perform { + do { + let predicate = try self.buildPredicate(for: query) + let persistedContacts = OCKCDContact.fetchFromStore(in: self.context, where: predicate) { fetchRequest in + fetchRequest.fetchLimit = query.limit ?? 0 + fetchRequest.fetchOffset = query.offset + fetchRequest.sortDescriptors = self.buildSortDescriptors(for: query) + } + + let contacts = persistedContacts.map(self.makeContact) + callbackQueue.async { completion(.success(contacts)) } + } catch { + callbackQueue.async { completion(.failure(.fetchFailed(reason: "Failed to fetch contacts. Error: \(error.localizedDescription)"))) } + } + } + } + + open func addContacts(_ contacts: [OCKContact], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKContact], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try OCKCDContact.validateNewIDs(contacts.map { $0.id }, in: self.context) + let persistableContacts = contacts.map(self.createContact) + try self.context.save() + let savedContacts = persistableContacts.map(self.makeContact) + callbackQueue.async { + self.contactDelegate?.contactStore(self, didAddContacts: savedContacts) + completion?(.success(savedContacts)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.addFailed(reason: "Failed to insert contacts: [\(contacts)]. \(error.localizedDescription)"))) + } + } + } + } + + open func updateContacts(_ contacts: [OCKContact], callbackQueue: DispatchQueue = .main, completion: OCKResultClosure<[OCKContact]>? = nil) { + context.perform { + do { + try OCKCDContact.validateUpdateIdentifiers(contacts.map { $0.id }, in: self.context) + let updatedContacts = try self.performVersionedUpdate(values: contacts, addNewVersion: self.createContact) + try self.context.save() + let contacts = updatedContacts.map(self.makeContact) + callbackQueue.async { + self.contactDelegate?.contactStore(self, didUpdateContacts: contacts) + completion?(.success(contacts)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.updateFailed(reason: "Failed to update contacts: [\(contacts)]. \(error.localizedDescription)"))) + } + } + } + } + + open func deleteContacts(_ contacts: [OCKContact], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKContact], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let markedDeleted: [OCKCDContact] = try self.performDeletion(values: contacts) + try self.context.save() + let deletedContacts = markedDeleted.map(self.makeContact) + callbackQueue.async { + self.contactDelegate?.contactStore(self, didDeleteContacts: deletedContacts) + completion?(.success(deletedContacts)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.deleteFailed(reason: "Failed to delete contacts: [\(contacts)]. \(error.localizedDescription)"))) + } + } + } + } + + private func createContact(from contact: OCKContact) -> OCKCDContact { + let persistableContact = OCKCDContact(context: context) + persistableContact.name = OCKCDPersonName(context: context) + persistableContact.copyVersionInfo(from: contact) + persistableContact.allowsMissingRelationships = configuration.allowsEntitiesWithMissingRelationships + persistableContact.name.copyPersonNameComponents(contact.name) + persistableContact.emailAddresses = contact.emailAddresses + persistableContact.messagingNumbers = contact.messagingNumbers + persistableContact.phoneNumbers = contact.phoneNumbers + persistableContact.otherContactInfo = contact.otherContactInfo + persistableContact.organization = contact.organization + persistableContact.title = contact.title + persistableContact.role = contact.role + persistableContact.category = contact.category?.rawValue + + if let carePlanID = contact.carePlanID { persistableContact.carePlan = try? fetchObject(havingLocalID: carePlanID) } + if let address = contact.address { + if let postalAddress = persistableContact.address { + copyPostalAddress(address, to: postalAddress) + } else { + persistableContact.address = createPostalAddress(from: address) + } + } else { + persistableContact.address = nil + } + return persistableContact + } + + private func createPostalAddress(from address: OCKPostalAddress) -> OCKCDPostalAddress { + let persistableAddress = OCKCDPostalAddress(context: context) + copyPostalAddress(address, to: persistableAddress) + return persistableAddress + } + + private func copyPostalAddress(_ address: OCKPostalAddress, to persitableAddress: OCKCDPostalAddress) { + persitableAddress.street = address.street + persitableAddress.subLocality = address.subLocality + persitableAddress.city = address.city + persitableAddress.subAdministrativeArea = address.subAdministrativeArea + persitableAddress.state = address.state + persitableAddress.postalCode = address.postalCode + persitableAddress.country = address.country + persitableAddress.isoCountryCode = address.isoCountryCode + } + + private func makeContact(from object: OCKCDContact) -> OCKContact { + var contact = OCKContact(id: object.id, name: object.name.makeComponents(), carePlanID: object.carePlan?.localDatabaseID) + contact.copyVersionedValues(from: object) + contact.address = object.address.map(makePostalAddress) + contact.emailAddresses = object.emailAddresses + contact.messagingNumbers = object.messagingNumbers + contact.phoneNumbers = object.phoneNumbers + contact.otherContactInfo = object.otherContactInfo + contact.organization = object.organization + contact.title = object.title + contact.role = object.role + if let rawValue = object.category { contact.category = OCKContactCategory(rawValue: rawValue) } + return contact + } + + private func makePostalAddress(from object: OCKCDPostalAddress) -> OCKPostalAddress { + let address = OCKPostalAddress() + address.street = object.street + address.subLocality = object.subLocality + address.city = object.city + address.subAdministrativeArea = object.subAdministrativeArea + address.state = object.state + address.postalCode = object.postalCode + address.country = object.country + address.isoCountryCode = object.isoCountryCode + return address + } + + private func buildPredicate(for query: OCKContactQuery) throws -> NSPredicate { + var predicate = OCKCDVersionedObject.notDeletedPredicate + + if let interval = query.dateInterval { + let intervalPredicate = OCKCDVersionedObject.newestVersionPredicate(in: interval) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, intervalPredicate]) + } + + if !query.ids.isEmpty { + let idPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), query.ids) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, idPredicate]) + } + + if !query.versionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "self IN %@", try query.versionIDs.map(objectID)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.remoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDObject.remoteID), query.remoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.carePlanIDs.isEmpty { + let planPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDContact.carePlan.id), query.carePlanIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, planPredicate]) + } + + if !query.carePlanVersionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDContact.carePlan), try query.carePlanVersionIDs.map(fetchObject)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.carePlanRemoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDContact.carePlan.remoteID), query.carePlanRemoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.groupIdentifiers.isEmpty { + predicate = predicate.including(groupIdentifiers: query.groupIdentifiers) + } + + if !query.tags.isEmpty { + predicate = predicate.including(tags: query.tags) + } + + return predicate + } + + private func buildSortDescriptors(for query: OCKContactQuery?) -> [NSSortDescriptor] { + guard let orders = query?.extendedSortDescriptors else { return [] } + return orders.map { order -> NSSortDescriptor in + switch order { + case .effectiveDate(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.effectiveDate, ascending: ascending) + case .familyName(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.name.familyName, ascending: ascending) + case .givenName(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDContact.name.givenName, ascending: ascending) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Outcomes.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Outcomes.swift new file mode 100755 index 0000000..b8eb47f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Outcomes.swift @@ -0,0 +1,244 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension OCKStore { + + open func fetchOutcomes(query: OCKOutcomeQuery = OCKOutcomeQuery(), callbackQueue: DispatchQueue = .main, + completion: @escaping (Result<[OCKOutcome], OCKStoreError>) -> Void) { + context.perform { + do { + let predicate = try self.buildPredicate(for: query) + let objects = OCKCDOutcome.fetchFromStore(in: self.context, where: predicate) { fetchRequest in + fetchRequest.fetchLimit = query.limit ?? 0 + fetchRequest.fetchOffset = query.offset + fetchRequest.sortDescriptors = self.buildSortDescriptors(for: query) + } + + let outcomes = try objects.map(self.makeOutcome) + callbackQueue.async { completion(.success(outcomes)) } + } catch { + self.context.rollback() + let reason = "Failed to fetch outcomes with query: \(String(describing: query)). \(error.localizedDescription)" + callbackQueue.async { completion(.failure(.fetchFailed(reason: reason))) } + } + } + } + + open func addOutcomes(_ outcomes: [OCKOutcome], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKOutcome], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try self.confirmOutcomesAreInValidRegionOfTaskVersionChain(outcomes) + let persistableOutcomes = outcomes.map(self.createOutcome) + try self.context.save() + let updatedOutcomes = try persistableOutcomes.map(self.makeOutcome) + callbackQueue.async { + self.outcomeDelegate?.outcomeStore(self, didAddOutcomes: updatedOutcomes) + completion?(.success(updatedOutcomes)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.addFailed(reason: "Failed to insert OKCOutomes: [\(outcomes)]. \(error.localizedDescription)"))) + } + } + } + } + + open func updateOutcomes(_ outcomes: [OCKOutcome], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKOutcome], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try self.confirmOutcomesAreInValidRegionOfTaskVersionChain(outcomes) + let objectIDs = try self.retrieveObjectIDs(for: outcomes) + let predicate = NSPredicate(format: "self IN %@", objectIDs) + let currentOutcomes = OCKCDOutcome.fetchFromStore(in: self.context, where: predicate) + for (outcomeIndex, objectID) in objectIDs.enumerated() { + guard let index = currentOutcomes.firstIndex(where: { $0.objectID == objectID }) else { + throw OCKStoreError.updateFailed(reason: "No OCKOutcome with matching ID could be found: \(objectID)") + } + self.copyOutcome(outcomes[outcomeIndex], to: currentOutcomes[index]) + } + try self.context.save() + let updatedOutcomes = try currentOutcomes.map(self.makeOutcome) + callbackQueue.async { + self.outcomeDelegate?.outcomeStore(self, didUpdateOutcomes: updatedOutcomes) + completion?(.success(updatedOutcomes)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.updateFailed(reason: "Failed to update OCKOutcomes: [\(outcomes)]. \(error.localizedDescription)"))) + } + } + } + } + + open func deleteOutcomes(_ outcomes: [OCKOutcome], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKOutcome], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let objectIDs = try self.retrieveObjectIDs(for: outcomes) + let predicate = NSPredicate(format: "self IN %@", objectIDs) + let persistableOutcomes: [OCKCDOutcome] = OCKCDOutcome.fetchFromStore(in: self.context, where: predicate) { request in + request.fetchLimit = outcomes.count + } + guard persistableOutcomes.count == outcomes.count else { + throw OCKStoreError.deleteFailed(reason: "Not all OCKOutcomes could be found to be deleted") + } + persistableOutcomes.forEach { self.context.delete($0) } + try self.context.save() + callbackQueue.async { + self.outcomeDelegate?.outcomeStore(self, didDeleteOutcomes: outcomes) + completion?(.success(outcomes)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.deleteFailed(reason: "Failed to delete OCKOutcomes: [\(outcomes)]. \(error.localizedDescription)"))) + } + } + } + } + + // MARK: Private + + // Confirms that outcomes cannot be added to past versions of a task in regions covered by a newer version. + // + // |<------------- Time Line --------------->| + // TaskV1 a-------b-------------------> + // V2 ----------> + // V3------------------> + // + // Throws an error if the outcome is added to V1 outside the region between `a` and `b`. + // Throws an error if the outcome is added to V2 anywhere because V2 is fully eclipsed. + // Does not throw an error for outcomes to added to V3 because V3 is the newest version. + private func confirmOutcomesAreInValidRegionOfTaskVersionChain(_ outcomes: [Outcome]) throws { + for outcome in outcomes { + let taskID = try objectID(for: outcome.taskID) + guard var task = context.object(with: taskID) as? OCKCDTask else { fatalError("taskID pointed to a non-task class") } + let schedule = makeSchedule(elements: Array(task.scheduleElements)) + while let nextVersion = task.next as? OCKCDTask { + let outcomeDate = schedule.event(forOccurrenceIndex: outcome.taskOccurrenceIndex)!.start + if nextVersion.effectiveDate <= outcomeDate { + throw OCKStoreError.invalidValue(reason: """ + Tried to place an outcome in a date range overshadowed by a future version of task. + The outcome is dated \(outcomeDate), but a newer version of the task starts on \(nextVersion.effectiveDate). + """) + } + task = nextVersion + } + } + } + + private func createOutcome(from outcome: OCKOutcome) -> OCKCDOutcome { + let persistableOutcome = OCKCDOutcome(context: context) + copyOutcome(outcome, to: persistableOutcome) + return persistableOutcome + } + + private func copyOutcome(_ outcome: OCKOutcome, to persistableOutcome: OCKCDOutcome) { + persistableOutcome.copyValues(from: outcome) + persistableOutcome.values = Set(outcome.values.map(createValue)) + persistableOutcome.taskOccurrenceIndex = outcome.taskOccurrenceIndex + if let task: OCKCDTask = try? fetchObject(havingLocalID: outcome.taskID) { + let schedule = makeSchedule(elements: Array(task.scheduleElements)) + persistableOutcome.date = schedule.event(forOccurrenceIndex: outcome.taskOccurrenceIndex)!.start + persistableOutcome.task = task + } + } + + /// - Remark: This method is intended to create a value type struct from a *persisted* NSManagedObject. Calling this method with an + /// object that is not yet commited is a programmer error. + private func makeOutcome(from object: OCKCDOutcome) throws -> OCKOutcome { + assert(object.localDatabaseID != nil, "You shouldn't be calling this method with an object that hasn't been saved yet!") + guard let taskID = object.task?.localDatabaseID else { throw OCKStoreError.invalidValue(reason: "Couldn't find a task for the outcome!") } + let responses = object.values.map(makeValue) + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: object.taskOccurrenceIndex, values: responses) + outcome.copyCommonValues(from: object) + return outcome + } + + private func buildPredicate(for query: OCKOutcomeQuery) throws -> NSPredicate { + var predicate = NSPredicate(value: true) + + if let interval = query.dateInterval { + let afterPredicate = NSPredicate(format: "%K >= %@", #keyPath(OCKCDOutcome.date), interval.start as NSDate) + let beforePredicate = NSPredicate(format: "%K < %@", #keyPath(OCKCDOutcome.date), interval.end as NSDate) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, afterPredicate, beforePredicate]) + } + + if !query.localIDs.isEmpty { + let localPredicate = NSPredicate(format: "self IN %@", try query.localIDs.map { try objectID(for: $0) }) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, localPredicate]) + } + + if !query.remoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.remoteID), query.remoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.taskIDs.isEmpty { + let taskPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDOutcome.task.id), query.taskIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, taskPredicate]) + } + + if !query.taskVersionIDs.isEmpty { + let taskPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDOutcome.task), try query.taskVersionIDs.map { try objectID(for: $0) }) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, taskPredicate]) + } + + if !query.taskRemoteIDs.isEmpty { + let taskPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDOutcome.task.remoteID), query.taskRemoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, taskPredicate]) + } + + if !query.groupIdentifiers.isEmpty { + predicate = predicate.including(groupIdentifiers: query.groupIdentifiers) + } + + if !query.tags.isEmpty { + predicate = predicate.including(tags: query.tags) + } + + return predicate + } + + private func buildSortDescriptors(for query: OCKOutcomeQuery?) -> [NSSortDescriptor] { + guard let orders = query?.extendedSortDescriptors else { return [] } + return orders.map { order -> NSSortDescriptor in + switch order { + case .date(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDOutcome.date, ascending: ascending) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Patients.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Patients.swift new file mode 100755 index 0000000..32f02c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Patients.swift @@ -0,0 +1,206 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension OCKStore { + + open func fetchPatients(query: OCKPatientQuery = OCKPatientQuery(), callbackQueue: DispatchQueue = .main, + completion: @escaping (Result<[OCKPatient], OCKStoreError>) -> Void) { + context.perform { + do { + let predicate = try self.buildPredicate(for: query) + let patientsObjects = OCKCDPatient.fetchFromStore(in: self.context, where: predicate) { fetchRequest in + fetchRequest.fetchLimit = query.limit ?? 0 + fetchRequest.fetchOffset = query.offset + fetchRequest.sortDescriptors = self.buildSortDescriptors(from: query) + } + + let patients = patientsObjects.map(self.makePatient) + callbackQueue.async { completion(.success(patients)) } + } catch { + self.context.rollback() + let message = "Failed to fetch patients with query: \(String(describing: query)). \(error.localizedDescription)" + callbackQueue.async { completion(.failure(.fetchFailed(reason: message))) } + } + } + } + + open func addPatients(_ patients: [OCKPatient], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKPatient], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try self.validateNumberOfPatients() + try OCKCDPatient.validateNewIDs(patients.map { $0.id }, in: self.context) + let persistablePatients = patients.map(self.createPatient) + try self.context.save() + let updatedPatients = persistablePatients.map(self.makePatient) + callbackQueue.async { + self.patientDelegate?.patientStore(self, didAddPatients: updatedPatients) + completion?(.success(updatedPatients)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.addFailed(reason: "Failed to insert OCKPatients: [\(patients)]. \(error.localizedDescription)"))) + } + } + } + } + + open func updatePatients(_ patients: [OCKPatient], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKPatient], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let ids = patients.map { $0.id } + try OCKCDPatient.validateUpdateIdentifiers(ids, in: self.context) + let updatedPatients = try self.performVersionedUpdate(values: patients, addNewVersion: self.createPatient) + try self.context.save() + let patients = updatedPatients.map(self.makePatient) + callbackQueue.async { + self.patientDelegate?.patientStore(self, didUpdatePatients: patients) + completion?(.success(patients)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.updateFailed(reason: "Failed to update OCKPatients: [\(patients)]. \(error.localizedDescription)"))) + } + } + } + } + + open func deletePatients(_ patients: [OCKPatient], callbackQueue: DispatchQueue = .main, + completion: ((Result<[OCKPatient], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let markedDeleted: [OCKCDPatient] = try self.performDeletion(values: patients) + try self.context.save() + let deletedPatients = markedDeleted.map(self.makePatient) + callbackQueue.async { + self.patientDelegate?.patientStore(self, didDeletePatients: deletedPatients) + completion?(.success(deletedPatients)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.deleteFailed(reason: "Failed to delete OCKPatients: [\(patients)]. \(error.localizedDescription)"))) + } + } + } + } + + // MARK: Private + + /// - Remark: This does not commit the transaction. After calling this function one or more times, you must call `context.save()` in order to + /// persist the changes to disk. This is an optimization to allow batching. + /// - Remark: You should verify that the object does not already exist in the database and validate its values before calling this method. + private func createPatient(from patient: OCKPatient) -> OCKCDPatient { + let persistablePatient = OCKCDPatient(context: context) + persistablePatient.name = OCKCDPersonName(context: context) + persistablePatient.copyVersionInfo(from: patient) + persistablePatient.allowsMissingRelationships = configuration.allowsEntitiesWithMissingRelationships + persistablePatient.name.copyPersonNameComponents(patient.name) + persistablePatient.sex = patient.sex?.rawValue + persistablePatient.birthday = patient.birthday + persistablePatient.allergies = patient.allergies + return persistablePatient + } + + /// - Remark: This method is intended to create a value type struct from a *persisted* NSManagedObject. Calling this method with an + /// object that is not yet commited is a programmer error. + private func makePatient(from object: OCKCDPatient) -> OCKPatient { + assert(object.localDatabaseID != nil, "Do not create a patient from an object that isn't persisted yet!") + var patient = OCKPatient(id: object.id, name: object.name.makeComponents()) + patient.sex = object.sex == nil ? nil : OCKBiologicalSex(rawValue: object.sex!) + patient.birthday = object.birthday + patient.allergies = object.allergies + patient.copyVersionedValues(from: object) + return patient + } + + private func buildPredicate(for query: OCKPatientQuery) throws -> NSPredicate { + var predicate = OCKCDVersionedObject.notDeletedPredicate + + if let interval = query.dateInterval { + let intervalPredicate = OCKCDVersionedObject.newestVersionPredicate(in: interval) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, intervalPredicate]) + } + + if !query.ids.isEmpty { + let idPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), query.ids) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, idPredicate]) + } + + if !query.versionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "self IN %@", try query.versionIDs.map(objectID)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.remoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDObject.remoteID), query.remoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.groupIdentifiers.isEmpty { + predicate = predicate.including(groupIdentifiers: query.groupIdentifiers) + } + + if !query.tags.isEmpty { + predicate = predicate.including(tags: query.tags) + } + + return predicate + } + + private func buildSortDescriptors(from query: OCKPatientQuery?) -> [NSSortDescriptor] { + guard let orders = query?.extendedSortDescriptors else { return [] } + return orders.map { order -> NSSortDescriptor in + switch order { + case .effectiveDate(let ascending): return NSSortDescriptor(keyPath: \OCKCDPatient.effectiveDate, ascending: ascending) + case .givenName(let ascending): return NSSortDescriptor(keyPath: \OCKCDPatient.name.givenName, ascending: ascending) + case .familyName(let ascending): return NSSortDescriptor(keyPath: \OCKCDPatient.name.familyName, ascending: ascending) + case .groupIdentifier(let ascending): return NSSortDescriptor(keyPath: \OCKCDPatient.groupIdentifier, ascending: ascending) + } + } + } + + private func validateNumberOfPatients() throws { + let fetchRequest = OCKCDPatient.fetchRequest() + let numberOfPatients = try context.count(for: fetchRequest) + if numberOfPatients > 0 { + let explanation = """ + OCKStore` only supports one patient per store. + If you would like to have more than one patient, create a new store for that patient. + """ + throw OCKStoreError.addFailed(reason: explanation) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Tasks.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Tasks.swift new file mode 100755 index 0000000..733237e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore+Tasks.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import HealthKit + +extension OCKStore: OCKCoreDataTaskStoreProtocol { + + // MARK: OCKCoreDataTaskStoreProtocol + public typealias Task = OCKTask + + /// - Remark: This method is intended to create a value type struct from a *persisted* NSManagedObject. Calling this method with an + /// object that is not yet commited is a programmer error. + internal func makeTask(from object: OCKCDTask) -> OCKTask { + assert(object.localDatabaseID != nil, "This should never be called on an unpersisted object") + let schedule = makeSchedule(elements: Array(object.scheduleElements)) + let task = OCKTask(id: object.id, + title: object.title, + carePlanID: object.carePlan?.localDatabaseID, + schedule: schedule) + return copyTaskValues(from: object, to: task) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore.swift new file mode 100755 index 0000000..a0ed1fd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/CoreData/OCKStore.swift @@ -0,0 +1,103 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import Foundation + +/// The default store used in CareKit. The underlying database used is CoreData. +open class OCKStore: OCKStoreProtocol, OCKCoreDataStoreProtocol, Equatable { + + /// The delegate receives callbacks when the contents of the patient store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + public weak var patientDelegate: OCKPatientStoreDelegate? + + /// The delegate receives callbacks when the contents of the care plan store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + public weak var carePlanDelegate: OCKCarePlanStoreDelegate? + + /// The delegate receives callbacks when the contents of the contacts store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + public weak var contactDelegate: OCKContactStoreDelegate? + + /// The delegate receives callbacks when the contents of the tasks store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + public weak var taskDelegate: OCKTaskStoreDelegate? + + /// The delegate receives callbacks when the contents of the outcome store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + public weak var outcomeDelegate: OCKOutcomeStoreDelegate? + + /// The configuration can be modified to enable or disable versioning of database entities. + public var configuration = OCKStoreConfiguration() + + /// Two instances of `OCKStore` are considered to be equal if they have the same name and store type. + public static func == (lhs: OCKStore, rhs: OCKStore) -> Bool { + lhs.name == rhs.name && lhs.storeType == rhs.storeType + } + + /// The name of the store. When the store type is `onDisk`, this name will be used for the SQLite filename. + public let name: String + + /// The store type determines where data is stored. Generally `onDisk` should be chosen in order to persist data, but `inMemory` may be useful + /// for development and testing purposes. + internal let storeType: OCKCoreDataStoreType + + /// Initialize a new store by specifying its name and store type. Store's with conflicting names and types must not be created. + /// + /// - Parameters: + /// - name: A unique name for the store. It will be used for the filename if stored on disk. + /// - type: The type of store to be used. + public init(name: String, type: OCKCoreDataStoreType = .onDisk) { + self.storeType = type + self.name = name + } + + // MARK: Internal + + internal lazy var persistentContainer: NSPersistentContainer = { + makePersistentContainer() + }() + + internal lazy var context: NSManagedObjectContext = { + return self.persistentContainer.newBackgroundContext() + }() +} + +internal extension NSPredicate { + func including(groupIdentifiers: [String]) -> NSPredicate { + let groupPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDObject.groupIdentifier), groupIdentifiers) + return NSCompoundPredicate(andPredicateWithSubpredicates: [self, groupPredicate]) + } + + func including(tags: [String]) -> NSPredicate { + let tagsPredicate = NSPredicate(format: "SOME %K IN %@", #keyPath(OCKCDObject.tags), tags) + return NSCompoundPredicate(andPredicateWithSubpredicates: [self, tagsPredicate]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Info.plist new file mode 100755 index 0000000..e1fe4cf --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKAdherenceAggregator.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKAdherenceAggregator.swift new file mode 100755 index 0000000..01f4073 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKAdherenceAggregator.swift @@ -0,0 +1,150 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An enumerator that specifies a number of methods for computing an adherence value given an array of events. +public enum OCKAdherenceAggregator { + + /// Computes a percentage by checking if the outcome for each event exists. Any event with a non-nil outcome will be counted + /// as 100% complete, and any event without an outcome will be counted as 0% complete. The average completion across all events + /// will be returned. + case outcomeExists + + /// Computes a percentage for each event by dividing the number of outcomes values by the number of expected outcomes values. + /// The average completion across all events will be returned. + case percentOfOutcomeValuesThatExist + + /// Computes a percentage for each event that is either 1.0 or 0.0 depending on if the outcomes values match or exceed the target values. + /// If no target values are specified on the event, then the existence of an outcome will result in a value of 1.0. + /// The average completion across all events will be returned. + case compareTargetValues + + /// Computes an analog percentage for each event as the number of met target values divided by the total number of target goals. + /// The average completion accross all events will be returned. + case percentOfTargetValuesMet + + /// Specifies a custom closure that operates on a day's worth of events and returns an adherence value + case custom(_ closure: ([OCKAnyEvent]) -> OCKAdherence) + + /// Aggregates an array of events into an adherence score. + /// + /// - Parameters: + /// - events: An array of events + public func aggregate(events: [OCKAnyEvent]) -> OCKAdherence { + switch self { + case .outcomeExists: return computeAverageCompletion(for: events, usingMetric: computeOutcomeExistsCompletion) + case .percentOfOutcomeValuesThatExist: return computeAverageCompletion(for: events, usingMetric: computePercentOfExpectedValuesThatExist) + case .compareTargetValues: return computeAverageCompletion(for: events, usingMetric: computeTargetValueBinaryCompletion) + case .percentOfTargetValuesMet: return computeAverageCompletion(for: events, usingMetric: computePercentOfTargetsMet) + case .custom(let closure): return closure(events) + } + } + + // Applies a metric to an array of events and averages the results + private func computeAverageCompletion(for events: [OCKAnyEvent], + usingMetric computeMetric: (_ event: OCKAnyEvent) -> Double) -> OCKAdherence { + guard !events.isEmpty else { return .noEvents } + let percentsComplete = events.map(computeMetric) + let average = percentsComplete.reduce(0, +) / Double(events.count) + return .progress(average) + } + + // Returns 1 or 0 based on whether or not an outcome exists + private func computeOutcomeExistsCompletion(for event: OCKAnyEvent) -> Double { + event.outcome != nil ? 1 : 0 + } + + // Returns (number of outcome values present) / (number of target values) + private func computePercentOfExpectedValuesThatExist(for event: OCKAnyEvent) -> Double { + let expectedValues = event.scheduleEvent.element.targetValues + let valuesRequiredForComplete = !expectedValues.isEmpty ? expectedValues.count : 1 + let valueCount = event.outcome?.values.count ?? 0 + let fractionComplete = min(1.0, Double(valueCount) / Double(valuesRequiredForComplete)) + return fractionComplete + } + + // Returns either 0 or 1 based on whether or not all target values have been met. + // If there are no target values, always returns 1. + private func computeTargetValueBinaryCompletion(for event: OCKAnyEvent) -> Double { + guard let outcome = event.outcome else { return 0 } + let targetValues = event.scheduleEvent.element.targetValues + guard targetValues.count <= outcome.values.count else { return 0 } + let indiciesToCheck = Array(0.. Double { + guard let outcome = event.outcome else { return 0 } + let targetValues = event.scheduleEvent.element.targetValues + guard !targetValues.isEmpty else { return outcome.values.isEmpty ? 0 : 1 } + let actualValues = outcome.values + let indicesToCheck = Array(0.. Bool { + assert(value.type == target.type, "Actual outcome value and target value should not have different types!") + guard value.type == target.type else { return false } + + switch value.type { + case .binary: return checkEquality(lhs: value, rhs: target, keyPath: \.dateValue) + case .boolean: return checkEquality(lhs: value, rhs: target, keyPath: \.booleanValue) + case .text: return checkEquality(lhs: value, rhs: target, keyPath: \.stringValue) + case .double: return compare(lhs: value, greaterThanOrEqualTo: target, keyPath: \.doubleValue) + case .date: return compare(lhs: value, greaterThanOrEqualTo: target, keyPath: \.dateValue) + case .integer: return compare(lhs: value, greaterThanOrEqualTo: target, keyPath: \.integerValue) + } + } + + private func checkEquality(lhs: OCKOutcomeValue, + rhs: OCKOutcomeValue, + keyPath: KeyPath) -> Bool { + guard let lhsValue = lhs[keyPath: keyPath], let rhsValue = rhs[keyPath: keyPath] else { return false } + return lhsValue == rhsValue + } + + private func compare(lhs: OCKOutcomeValue, + greaterThanOrEqualTo rhs: OCKOutcomeValue, + keyPath: KeyPath) -> Bool { + guard let lhsValue = lhs[keyPath: keyPath], let rhsValue = rhs[keyPath: keyPath] else { return false } + return lhsValue >= rhsValue + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKEventAggregator.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKEventAggregator.swift new file mode 100755 index 0000000..215e67b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKEventAggregator.swift @@ -0,0 +1,57 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Foundation + +/// An enumerator that specifies a number of methods for computing a value given an array of events that occurred on some day. +public enum OCKEventAggregator { + /// Counts the total number of outcome values in the entire array of events. + case countOutcomeValues + + /// Count the total number of outcomes in the entire array of events. + case countOutcomes + + /// Custom logic that operates a day's worth of events and returns a y-axis value. + case custom(_ closure: ([OCKAnyEvent]) -> Double) + + /// Aggregates an array of events into an adherence score. + /// + /// - Parameters: + /// - events: An array of events + public func aggregate(events: [OCKAnyEvent]) -> Double { + switch self { + case .countOutcomeValues: + return Double(events.map { $0.outcome?.values.count ?? 0 }.reduce(0, +)) + case .countOutcomes: + return Double(events.map { $0.outcome != nil ? 1 : 0 }.reduce(0, +)) + case .custom(let closure): + return closure(events) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKResultClosure.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKResultClosure.swift new file mode 100755 index 0000000..0b8b76b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKResultClosure.swift @@ -0,0 +1,33 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public typealias OCKResultClosure = (Result) -> Void diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKStoreError.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKStoreError.swift new file mode 100755 index 0000000..d921abd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKStoreError.swift @@ -0,0 +1,64 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// `OCKStoreError`s will be emitted from `OCKStoreProtocol` conformers if there is problem during a transaction. +public enum OCKStoreError: LocalizedError { + /// Occurs when a fetch fails. + case fetchFailed(reason: String) + + /// Occurs when adding an entity fails. + case addFailed(reason: String) + + /// Occurs when an update to an existing entity fails. + case updateFailed(reason: String) + + /// Occurs when deleting an existing entity fails. + case deleteFailed(reason: String) + + /// Occurs when an invalid value is provided. + case invalidValue(reason: String) + + /// Occurs when an asynchronous action takes too long. + /// - Note: This is intended for use by remote databases. + case timedOut(reason: String) + + public var errorDescription: String? { + switch self { + case .fetchFailed(let reason): return "Failed to fetch: \(reason)" + case .addFailed(let reason): return "Failed to add: \(reason)" + case .updateFailed(let reason): return "Failed to update: \(reason)" + case .deleteFailed(let reason): return "Failed to delete: \(reason)" + case .timedOut(let reason): return "Timed out: \(reason)" + case .invalidValue(let reason): return "Invalid value: \(reason)" + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKUtilities.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKUtilities.swift new file mode 100755 index 0000000..0ef9697 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/OCKUtilities.swift @@ -0,0 +1,94 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +func chooseFirst(then singularResultClosure: OCKResultClosure?, replacementError: OCKStoreError) -> OCKResultClosure<[T]> { + return { arrayResult in + switch arrayResult { + case .failure(let error): + singularResultClosure?(.failure(error)) + case .success(let array): + if let first = array.first { singularResultClosure?(.success(first)); return } + singularResultClosure?(.failure(replacementError)) + } + } +} + +// Performs an array of operations and completes with the aggregated results or an an error, if any any occurs. +func aggregate(_ closures: [(@escaping OCKResultClosure<[U]>) -> Void], callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[U]>) { + let group = DispatchGroup() + var error: OCKStoreError? + var values: [U] = [] + + for closure in closures { + group.enter() + closure({ result in + switch result { + case .failure(let storeError): error = storeError + case .success(let storeValues): values.append(contentsOf: storeValues) + } + group.leave() + }) + } + + group.notify(queue: callbackQueue) { + if let error = error { completion(.failure(error)); return } + completion(.success(values)) + } + } + +// Performs an array of operations and completes with the first result. +func getFirstValidResult(_ closures: [(@escaping OCKResultClosure) -> Void], callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure) { + let group = DispatchGroup() + var values: [T] = [] + + for closure in closures { + group.enter() + closure({ result in + switch result { + case .failure: break + case .success(let fetchedValue): + values.append(fetchedValue) + } + group.leave() + }) + } + + group.notify(queue: callbackQueue) { + guard let firstValue = values.first else { + completion(.failure(.invalidValue(reason: "All of the operations failed."))) + return + } + completion(.success(firstValue)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlan.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlan.swift new file mode 100755 index 0000000..c941f99 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlan.swift @@ -0,0 +1,55 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Conforming a type to `OCKAnyCarePlan` allows it to be queried and displayed by CareKit. +public protocol OCKAnyCarePlan { + + /// A user-defined unique identifier, typically human readable. + var id: String { get } + + /// A title describing this care plan. + var title: String { get } + + /// An identifier for this care plan in a remote store. + var remoteID: String? { get } + + /// An identifier that can be uesd to group this care plan with others. + var groupIdentifier: String? { get } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get } + + /// Determines if this care plan belongs to the given patiehtn. + /// + /// - Parameter patient: A patient which may or may not own this care plan. + func belongs(to patient: OCKAnyPatient) -> Bool +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlanStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlanStore.swift new file mode 100755 index 0000000..bf15c30 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKAnyCarePlanStore.swift @@ -0,0 +1,147 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which types conforming to `OCKAnyCarePlan` can be queried is considered `OCKAnyReadOnlyCarePlanStore`. +public protocol OCKAnyReadOnlyCarePlanStore: AnyObject { + + /// The delegate receives callbacks when the contents of the care plan store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + var carePlanDelegate: OCKCarePlanStoreDelegate? { get set } + + /// `fetchCarePlans` asynchronously retrieves an array of care plans from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyCarePlans(query: OCKAnyCarePlanQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyCarePlan]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchCarePlan` asynchronously retrieves a single care plans from the store. + /// + /// - Parameters: + /// - id: The identifier of the item to be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyCarePlan(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) + +} + +/// Any store able to write to one ore more types conforming to `OCKAnyCarePlan` is considered an `OCKAnyCarePlanStore`. +public protocol OCKAnyCarePlanStore: OCKAnyReadOnlyCarePlanStore { + + /// `addCarePlans` asynchronously adds an array of care plans to the store. + /// + /// - Parameters: + /// - plans: An array of plans to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) + + /// `updateCarePlans` asynchronously updates an array of care plans in the store. + /// + /// - Parameters: + /// - plans: An array of care plans to be updated. The care plans must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) + + /// `deleteCarePlans` asynchronously deletes an array of care plans from the store. + /// + /// - Parameters: + /// - plans: An array of care plans to be deleted. The care plans must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) + + // MARK: Singular Methods - Implementation Provided + + /// `addAnyCarePlan` asynchronously adds a single care plan to the store. + /// + /// - Parameters: + /// - plan: A single plan to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateCarePlan` asynchronously updates a single care plan in the store. + /// + /// - Parameters: + /// - plan: A single care plan to be updated. The care plans must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteCarePlan` asynchronously deletes a single care plan from the store. + /// + /// - Parameters: + /// - plans: An single care plan to be deleted. The care plans must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKAnyReadOnlyCarePlanStore + +public extension OCKAnyReadOnlyCarePlanStore { + func fetchAnyCarePlan(withID id: String, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + var query = OCKCarePlanQuery(for: Date()) + query.limit = 1 + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + + fetchAnyCarePlans(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No care plan with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKAnyCarePlanStore + +public extension OCKAnyCarePlanStore { + func addAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addAnyCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add care plan: \(plan)"))) + } + + func updateAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateAnyCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update care plan: \(plan)"))) + } + + func deleteAnyCarePlan(_ plan: OCKAnyCarePlan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteAnyCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete care plan: \(plan)"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStore.swift new file mode 100755 index 0000000..3c0690c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStore.swift @@ -0,0 +1,184 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +import Foundation + +/// Any store from which a single type conforming to `OCKAnyCarePlan` can be queried is considered `OCKAnyReadOnlyCarePlanStore`. +public protocol OCKReadableCarePlanStore: OCKAnyReadOnlyCarePlanStore { + associatedtype Plan: OCKAnyCarePlan & Equatable & Identifiable + associatedtype PlanQuery: OCKAnyCarePlanQuery + + /// `fetchCarePlans` asynchronously retrieves an array of care plans from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchCarePlans(query: PlanQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Plan]>) + + // MARK: Implementation Provided + + /// `fetchCarePlan` asynchronously retrieves a care plan from the store using its user-defined unique identifier. If a care plan with the + /// specified identifier is not found, the completion handler will be called with an error. + /// + /// - Parameters: + /// - id: A unique user-defined identifier + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchCarePlan(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store that can perform read and write operations on a single type conforming to `OCKAnyCarePlan` is considered an `OCKCarePlanStore`. +public protocol OCKCarePlanStore: OCKReadableCarePlanStore, OCKAnyCarePlanStore { + + /// `addCarePlans` asynchronously adds an array of care plans to the store. + /// + /// - Parameters: + /// - plans: An array of plans to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addCarePlans(_ plans: [Plan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Plan]>?) + + /// `updateCarePlans` asynchronously updates an array of care plans in the store. + /// + /// - Parameters: + /// - plans: An array of care plans to be updated. The care plans must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateCarePlans(_ plans: [Plan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Plan]>?) + + /// `deleteCarePlans` asynchronously deletes an array of care plans from the store. + /// + /// - Parameters: + /// - plans: An array of care plans to be deleted. The care plans must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteCarePlans(_ plans: [Plan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Plan]>?) + + // MARK: Implementation Provided + + /// `addCarePlan` asynchronously adds a care plans to the store. + /// + /// - Parameters: + /// - plan: A care plan to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addCarePlan(_ plan: Plan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateCarePlan` asynchronously updates a care plan in the store. + /// + /// - Parameters: + /// - plan: A care plan to be updated. The care plan must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateCarePlan(_ plan: Plan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteCarePlan` asynchronously deletes a care plan from the store. + /// + /// - Parameters: + /// - plan: A care plan to be deleted. The care plan must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteCarePlan(_ plan: Plan, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKReadableCarePlanStore + +public extension OCKReadableCarePlanStore { + func fetchCarePlan(withID id: String, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure) { + var query = OCKCarePlanQuery(for: Date()) + query.limit = 1 + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + + fetchCarePlans(query: PlanQuery(query), callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No care plan with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKCarePlanStoreProtocol + +public extension OCKCarePlanStore { + + func addCarePlan(_ plan: Plan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add care plan: \(plan)"))) + } + + func updateCarePlan(_ plan: Plan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update care plan: \(plan)"))) + } + + func deleteCarePlan(_ plan: Plan, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteCarePlans([plan], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete care plan: \(plan)"))) + } +} + +// MARK: OCKAnyReadOnlyCarePlanStore conformance for OCKReadableCarePlanStore + +public extension OCKReadableCarePlanStore { + func fetchAnyCarePlans(query: OCKAnyCarePlanQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyCarePlan]>) { + let planQuery = PlanQuery(query) + fetchCarePlans(query: planQuery, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0 as OCKAnyCarePlan } }) } + } +} + +// MARK: OCKAnyCarePlanStore conformance for OCKCarePlanStore + +public extension OCKCarePlanStore { + func addAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) { + guard let plans = plans as? [Plan] else { + let message = "Failed to add plans. Not all plans were of the correct type: \(Plan.self)." + callbackQueue.async { completion?(.failure(.addFailed(reason: message))) } + return + } + addCarePlans(plans, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyCarePlan } }) } + } + + func updateAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) { + guard let plans = plans as? [Plan] else { + let message = "Failed to update plans. Not all plans were of the correct type: \(Plan.self)." + callbackQueue.async { completion?(.failure(.updateFailed(reason: message))) } + return + } + updateCarePlans(plans, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyCarePlan } }) } + } + + func deleteAnyCarePlans(_ plans: [OCKAnyCarePlan], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyCarePlan]>?) { + guard let plans = plans as? [Plan] else { + let message = "Failed to delete plans. Not all plans were of the correct type: \(Plan.self)." + callbackQueue.async { completion?(.failure(.deleteFailed(reason: message))) } + return + } + deleteCarePlans(plans, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyCarePlan } }) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStoreDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStoreDelegate.swift new file mode 100755 index 0000000..e7f17bb --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CarePlans/OCKCarePlanStoreDelegate.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Types conforming to this protocol can receive callbacks from care plan stores. +public protocol OCKCarePlanStoreDelegate: AnyObject { + + /// Called each time care plans are added to the store. + /// - Parameter store: The store which was modified. + /// - Parameter carePlans: The care plans that were added. + func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didAddCarePlans carePlans: [OCKAnyCarePlan]) + + /// Called each time care plans are updated in the store. + /// - Parameter store: The store which was modified. + /// - Parameter carePlans: The care plans that were updated. + func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didUpdateCarePlans carePlans: [OCKAnyCarePlan]) + + /// Called each time care plans are deleted from the store. + /// - Parameter store: The store which was modified. + /// - Parameter carePlans: The care plans that were deleted. + func carePlanStore(_ store: OCKAnyReadOnlyCarePlanStore, didDeleteCarePlans carePlans: [OCKAnyCarePlan]) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContact.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContact.swift new file mode 100755 index 0000000..08452b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContact.swift @@ -0,0 +1,93 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An enumerator specifying which group a contact belongs to. +public enum OCKContactCategory: String, Codable { + case careProvider + case friendsAndFamily +} + +/// Conforming a type to `OCKAnyContact` allows it to be queried and displayed by CareKit. +public protocol OCKAnyContact { + + /// A user-defined unique identifier, typically human readable. + var id: String { get } + + /// The contact's name. + var name: PersonNameComponents { get } + + /// The contact's postal address. + var address: OCKPostalAddress? { get } + + /// An array of the contact's email addresses. + var emailAddresses: [OCKLabeledValue]? { get } + + /// An array of numbers that the contact can be messaged at. + /// The number strings may contains non-numeric characters. + var messagingNumbers: [OCKLabeledValue]? { get } + + /// An array of the contact's phone numbers. + /// The number strings may contains non-numeric characters. + var phoneNumbers: [OCKLabeledValue]? { get } + + /// An array of other information that could be used reach this contact. + var otherContactInfo: [OCKLabeledValue]? { get } + + /// The organization this contact belongs to. + var organization: String? { get } + + /// A title for this contact. + var title: String? { get } + + /// A description of what this contact's role is. + var role: String? { get } + + /// A string representation of an asset. + var asset: String? { get } + + /// Indicates if this contact is care provider or if they are a friend or family member. + var category: OCKContactCategory? { get } + + /// An identifier for this contact in a remote store. + var remoteID: String? { get } + + /// An identifier that can be uesd to group this contact with others. + var groupIdentifier: String? { get } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get } + + /// Determines if this contact belongs to the given care plan. + /// + /// - Parameter plan: A care plan which may or may not own this contact. + func belongs(to plan: OCKAnyCarePlan) -> Bool +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContactStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContactStore.swift new file mode 100755 index 0000000..8c13a09 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKAnyContactStore.swift @@ -0,0 +1,146 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which types conforming to `OCKAnyContact` can be queried is considered `OCKAnyReadOnlyContactStore`. +public protocol OCKAnyReadOnlyContactStore: AnyObject { + + /// The delegate receives callbacks when the contents of the care plan store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + var contactDelegate: OCKContactStoreDelegate? { get set } + + /// `fetchAnyContacts` asynchronously retrieves an array of contacts from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyContacts(query: OCKAnyContactQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[OCKAnyContact]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchAnyContact` asynchronously retrieves a single contact from the store. + /// + /// - Parameters: + /// - id: The identifier of the item to be fetched. + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyContact(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store able to write to one ore more types conforming to `OCKAnyContact` is considered an `OCKAnyContactStore`. +public protocol OCKAnyContactStore: OCKAnyReadOnlyContactStore { + + /// `addAnyContacts` asynchronously adds an array of contacts to the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) + + /// `updateAnyContacts` asynchronously updates an array of contacts in the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be updated. The contacts must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) + + /// `deleteAnyContacts` asynchronously deletes an array of contacts from the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be deleted. The contacts must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) + + // MARK: Singular Methods - Implementation Privided + + /// `addAnyContact` asynchronously adds a single contact to the store. + /// + /// - Parameters: + /// - contact: A single contact to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateAnyContact` asynchronously update single contact in the store. + /// + /// - Parameters: + /// - contact: A single contact to be updated. The contact must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteAnyContact` asynchronously deletes a single contact from the store. + /// + /// - Parameters: + /// - contact: An single contact to be deleted. The contact must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKAnyReadOnlyContactStore + +public extension OCKAnyReadOnlyContactStore { + func fetchAnyContact(withID id: String, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + var query = OCKContactQuery(for: Date()) + query.limit = 1 + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + + fetchAnyContacts(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No contact with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKAnyContactStore + +public extension OCKAnyContactStore { + func addAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addAnyContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add contact: \(contact)"))) + } + + func updateAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateAnyContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update contact: \(contact)"))) + } + + func deleteAnyContact(_ contact: OCKAnyContact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteAnyContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete contact: \(contact)"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStore.swift new file mode 100755 index 0000000..6b1c4a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStore.swift @@ -0,0 +1,183 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +import Foundation + +/// Any store from which a single type conforming to `OCKAnyContact` can be queried is considered `OCKAReadableCarePlanStore`. +public protocol OCKReadableContactStore: OCKAnyReadOnlyContactStore { + associatedtype Contact: OCKAnyContact & Equatable & Identifiable + associatedtype ContactQuery: OCKAnyContactQuery + + /// `fetchContacts` asynchronously retrieves an array of contacts from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchContacts(query: ContactQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Contact]>) + + // MARK: Implementation Provided + + /// `fetchContact` asynchronously retrieves a contact from the store using its user-defined unique identifier. If a contact with the + /// specified identifier is not found, the completion handler will be called with an error. + /// + /// - Parameters: + /// - id: A unique user-defined identifier. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchContact(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store that can perform read and write operations on a single type conforming to `OCKAnyContact` is considered an `OCKCarePlanStore`. +public protocol OCKContactStore: OCKReadableContactStore, OCKAnyContactStore { + + /// `addContacts` asynchronously adds an array of contacts to the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addContacts(_ contacts: [Contact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Contact]>?) + + /// `updateContacts` asynchronously updates an array of contacts in the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be updated. The contacts must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateContacts(_ contacts: [Contact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Contact]>?) + + /// `deleteContacts` asynchronously deletes an array of contacts from the store. + /// + /// - Parameters: + /// - contacts: An array of contacts to be deleted. The contacts must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteContacts(_ contacts: [Contact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Contact]>?) + + // MARK: Implementation Provided + + /// `addContact` asynchronously adds a contact to the store. + /// + /// - Parameters: + /// - contact: A contact to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addContact(_ contact: Contact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateContact` asynchronously updates a contacts in the store. + /// + /// - Parameters: + /// - contact: A contact to be updated. The contact must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateContact(_ contact: Contact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteContact` asynchronously deletes a contact from the store. + /// + /// - Parameters: + /// - contact: A contact to be deleted. The contact must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteContact(_ contact: Contact, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKReadableContactStore +public extension OCKReadableContactStore { + func fetchContact(withID id: String, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + var query = OCKContactQuery(for: Date()) + query.limit = 1 + query.ids = [id] + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + + fetchContacts(query: ContactQuery(query), callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No contact with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKContactStore + +public extension OCKContactStore { + func addContact(_ contact: Contact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add contact: \(contact)"))) + } + + func updateContact(_ contact: Contact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update contact: \(contact)"))) + } + + func deleteContact(_ contact: Contact, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteContacts([contact], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete contact: \(contact)"))) + } +} + +// MARK: OCKAnyReadbaleContactStore conformance for OCKReadableContactStore + +public extension OCKReadableContactStore { + func fetchAnyContacts(query: OCKAnyContactQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyContact]>) { + let contactQuery = ContactQuery(query) + fetchContacts(query: contactQuery, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0 as OCKAnyContact } }) } + } +} + +// MARK: OCKAnyContactStore conformance for OCKContactStore + +public extension OCKContactStore { + func addAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) { + guard let contacts = contacts as? [Contact] else { + let message = "Failed to add contacts. Not all contact were the correct type: \(Contact.self)." + callbackQueue.async { completion?(.failure(.addFailed(reason: message))) } + return + } + addContacts(contacts, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyContact } }) } + } + + func updateAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) { + guard let contacts = contacts as? [Contact] else { + let message = "Failed to update contacts. Not all contact were the correct type: \(Contact.self)." + callbackQueue.async { completion?(.failure(.updateFailed(reason: message))) } + return + } + updateContacts(contacts, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyContact } }) } + } + + func deleteAnyContacts(_ contacts: [OCKAnyContact], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyContact]>?) { + guard let contacts = contacts as? [Contact] else { + let message = "Failed to delete contacts. Not all contact were the correct type: \(Contact.self)." + callbackQueue.async { completion?(.failure(.deleteFailed(reason: message))) } + return + } + deleteContacts(contacts, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyContact } }) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStoreDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStoreDelegate.swift new file mode 100755 index 0000000..53e62b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Contacts/OCKContactStoreDelegate.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Types conforming to this protocol can receive callbacks from contact stores. +public protocol OCKContactStoreDelegate: AnyObject { + + /// Called each time contacts are added to the store. + /// - Parameter store: The store which was modified. + /// - Parameter contacts: The contacts that were added to the store. + func contactStore(_ store: OCKAnyReadOnlyContactStore, didAddContacts contacts: [OCKAnyContact]) + + /// Called each time contacts are updated in the store. + /// - Parameter store: The store which was modified. + /// - Parameter contacts: The contacts that were updated in the store. + func contactStore(_ store: OCKAnyReadOnlyContactStore, didUpdateContacts contacts: [OCKAnyContact]) + + /// Called each time contacts are deleted from the store. + /// - Parameter store: The store which was modified. + /// - Parameter contacts: The contacts that were deleted from the store. + func contactStore(_ store: OCKAnyReadOnlyContactStore, didDeleteContacts contacts: [OCKAnyContact]) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataStoreProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataStoreProtocol.swift new file mode 100755 index 0000000..18f1fe8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataStoreProtocol.swift @@ -0,0 +1,127 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +/// An enumerator specifying the type of stores that may be chosen. +public enum OCKCoreDataStoreType { + + /// An in memory store runs in RAM. It is very fast, but cannot support large datasets and is not persisted between app launches. + /// Its primary use case is for testing. + case inMemory + + /// A store that persists data to disk. This option should be in almost all cases. + case onDisk + + internal var stringValue: String { + switch self { + case .inMemory: return NSInMemoryStoreType + case .onDisk: return NSSQLiteStoreType + } + } +} + +internal protocol OCKCoreDataStoreProtocol { + var name: String { get } + var storeType: OCKCoreDataStoreType { get } + var context: NSManagedObjectContext { get } + var configuration: OCKStoreConfiguration { get } +} + +extension OCKCoreDataStoreProtocol { + + func makePersistentContainer() -> NSPersistentContainer { + let container = NSPersistentContainer(name: self.name, managedObjectModel: sharedManagedObjectModel) + let descriptor = NSPersistentStoreDescription() + descriptor.url = NSPersistentContainer.defaultDirectoryURL().appendingPathComponent(name + ".sqlite") + descriptor.type = storeType.stringValue + descriptor.shouldAddStoreAsynchronously = false + descriptor.setOption(FileProtectionType.complete as NSObject, forKey: NSPersistentStoreFileProtectionKey) + container.persistentStoreDescriptions = [descriptor] + container.loadPersistentStores(completionHandler: { _, error in + if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } + if self.storeType == .onDisk { + do { + guard var storeUrl = descriptor.url else { throw OCKStoreError.invalidValue(reason: "Bad URL") } + var resourceValues = URLResourceValues() + resourceValues.isExcludedFromBackup = true + try storeUrl.setResourceValues(resourceValues) + } catch { + fatalError("Failed to setup security for the care store. \(error)") + } + } + }) + return container + } + + func objectID(for versionID: OCKLocalVersionID) throws -> NSManagedObjectID { + guard let coordinator = context.persistentStoreCoordinator else { + throw OCKStoreError.invalidValue(reason: "Store coordinator not initialized") } + guard let url = URL(string: versionID.stringValue) else { + throw OCKStoreError.invalidValue(reason: "versionID is not a URL: \(versionID)") } + guard let objectId = coordinator.managedObjectID(forURIRepresentation: url) + else { throw OCKStoreError.fetchFailed(reason: "No matching NSManagedObjectID for versionID: \(versionID)") } + return objectId + } + + func fetchObject(havingLocalID versionID: OCKLocalVersionID) throws -> T { + guard let object = try context.existingObject(with: try objectID(for: versionID)) as? T else { + throw OCKStoreError.invalidValue(reason: "versionID could not be converted to NSManagedObjectID: \(versionID)") + } + return object + } + + func retrieveObjectIDs(for objects: [T]) throws -> [NSManagedObjectID] where T: OCKObjectCompatible { + let localIDs = objects.compactMap { $0.localDatabaseID } + guard localIDs.count == objects.count else { throw OCKStoreError.invalidValue(reason: "Missing localDatabaseID!") } + return try localIDs.map(objectID) + } + + func performVersionedUpdate(values: [Value], addNewVersion: (Value) -> Object) throws -> [Object] + where Value: OCKVersionedObjectCompatible, Object: OCKCDVersionedObject { + + let currentVersions: [Object] = Object.fetchHeads(ids: values.map { $0.id }, in: context) + return try values.map { value -> Object in + guard let current = currentVersions.first(where: { $0.id == value.id }) else { + throw OCKStoreError.invalidValue(reason: "No matching object could be found for id: \(value.id)") + } + let newVersion = addNewVersion(value) + newVersion.previous = current + return newVersion + } + } + + func performDeletion(values: [Value]) throws -> [Object] + where Value: OCKVersionedObjectCompatible, Object: OCKCDVersionedObject { + let currentVersions: [Object] = Object.fetchHeads(ids: values.map { $0.id }, in: context) + currentVersions.forEach { $0.deletedDate = Date() } + return currentVersions + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataTaskStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataTaskStore.swift new file mode 100755 index 0000000..dcaeb30 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/CoreData/OCKCoreDataTaskStore.swift @@ -0,0 +1,326 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData +import HealthKit + +protocol OCKCDTaskCompatible: OCKAnyMutableTask, OCKVersionedObjectCompatible { + var carePlanID: OCKLocalVersionID? { get set } + var optionalHealthKitLinkage: OCKHealthKitLinkage? { get set } +} + +extension OCKTask: OCKCDTaskCompatible { + var optionalHealthKitLinkage: OCKHealthKitLinkage? { + get { nil } + set { /* No-op */ } + } +} + + +protocol OCKCoreDataTaskStoreProtocol: OCKCoreDataStoreProtocol, OCKTaskStore where Task: OCKCDTaskCompatible { + func makeTask(from task: OCKCDTask) -> Task +} + +// MARK: Conformance to OCKTasStore + +extension OCKCoreDataTaskStoreProtocol { + public func fetchTasks(query: OCKTaskQuery = OCKTaskQuery(), callbackQueue: DispatchQueue = .main, + completion: @escaping (Result<[Task], OCKStoreError>) -> Void) { + context.perform { + do { + let predicate = try self.buildPredicate(for: query) + let tasks = OCKCDTask + .fetchFromStore(in: self.context, where: predicate) { fetchRequest in + fetchRequest.fetchLimit = query.limit ?? 0 + fetchRequest.fetchOffset = query.offset + fetchRequest.sortDescriptors = self.buildSortDescriptors(for: query) + } + .map(self.makeTask) + .filtered(against: query) + + callbackQueue.async { + completion(.success(tasks)) + } + } catch { + self.context.rollback() + callbackQueue.async { + let message = "Failed to fetch tasks with query: \(String(describing: query)). " + completion(.failure(.fetchFailed(reason: message + error.localizedDescription))) + } + } + } + } + + public func addTasks(_ tasks: [Task], callbackQueue: DispatchQueue = .main, + completion: ((Result<[Task], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + try OCKCDTask.validateNewIDs(tasks.map { $0.id }, in: self.context) + let persistableTasks = tasks.map { self.createTask(from: $0) } + try self.context.save() + let addedTasks = persistableTasks.map(self.makeTask) + callbackQueue.async { + self.taskDelegate?.taskStore(self, didAddTasks: addedTasks) + completion?(.success(addedTasks)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.addFailed(reason: "Failed to add OCKTasks: [\(tasks)]. \(error.localizedDescription)"))) + } + } + } + } + + public func updateTasks(_ tasks: [Task], callbackQueue: DispatchQueue = .main, + completion: ((Result<[Task], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let ids = tasks.map { $0.id } + try OCKCDTask.validateUpdateIdentifiers(ids, in: self.context) + try self.confirmUpdateWillNotCauseDataLoss(tasks: tasks) + let updatedTasks = try self.performVersionedUpdate(values: tasks, addNewVersion: self.createTask) + try self.context.save() + let tasks = updatedTasks.map(self.makeTask) + callbackQueue.async { + self.taskDelegate?.taskStore(self, didUpdateTasks: tasks) + completion?(.success(tasks)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.updateFailed(reason: "\(error.localizedDescription)"))) + } + } + } + } + + public func deleteTasks(_ tasks: [Task], callbackQueue: DispatchQueue = .main, + completion: ((Result<[Task], OCKStoreError>) -> Void)? = nil) { + context.perform { + do { + let ids = tasks.map { $0.id } + try OCKCDTask.validateUpdateIdentifiers(ids, in: self.context) + let markedTasks: [OCKCDTask] = try self.performDeletion(values: tasks) + try self.context.save() + let deletedTasks = markedTasks.map(self.makeTask) + callbackQueue.async { + self.taskDelegate?.taskStore(self, didDeleteTasks: deletedTasks) + completion?(.success(deletedTasks)) + } + } catch { + self.context.rollback() + callbackQueue.async { + completion?(.failure(.deleteFailed(reason: "Failed to delete OCKTasks: [\(tasks)]. \(error.localizedDescription)"))) + } + } + } + } + + private func createTask(from task: Task) -> OCKCDTask { + let persistableTask = OCKCDTask(context: context) + persistableTask.copyVersionInfo(from: task) + persistableTask.allowsMissingRelationships = configuration.allowsEntitiesWithMissingRelationships + persistableTask.title = task.title + persistableTask.instructions = task.instructions + persistableTask.impactsAdherence = task.impactsAdherence + persistableTask.scheduleElements = Set(createScheduleElements(from: task.schedule)) + persistableTask.healthKitLinkage = task.optionalHealthKitLinkage == nil ? nil : createHealthKitLinkage(from: task.optionalHealthKitLinkage!) + if let planId = task.carePlanID { persistableTask.carePlan = try? fetchObject(havingLocalID: planId) } + + return persistableTask + } + + internal func copyTaskValues(from other: OCKCDTask, to task: T) -> T { + var mutable = task + mutable.copyVersionedValues(from: other) + mutable.carePlanID = other.carePlan?.localDatabaseID + mutable.optionalHealthKitLinkage = makeHealthKitLinkage(from: other.healthKitLinkage) + mutable.title = other.title + mutable.instructions = other.instructions + mutable.impactsAdherence = other.impactsAdherence + mutable.schedule = makeSchedule(elements: Array(other.scheduleElements)) + return mutable + } + + private func createScheduleElements(from schedule: OCKSchedule) -> [OCKCDScheduleElement] { + return schedule.elements.map { element -> OCKCDScheduleElement in + let scheduleElement = OCKCDScheduleElement(context: context) + scheduleElement.interval = element.interval + scheduleElement.startDate = element.start + scheduleElement.endDate = element.end + scheduleElement.duration = element.duration + scheduleElement.interval = element.interval + scheduleElement.text = element.text + scheduleElement.targetValues = Set(element.targetValues.map(createValue)) + scheduleElement.copyValues(from: element) + return scheduleElement + } + } + + private func createHealthKitLinkage(from link: OCKHealthKitLinkage?) -> OCKCDHealthKitLinkage? { + guard let link = link else { return nil } + let linkage = OCKCDHealthKitLinkage(context: context) + linkage.quantityIdentifier = link.quantityIdentifier.rawValue + linkage.quantityType = link.quantityType.rawValue + linkage.unitString = link.unitString + return linkage + } + + internal func createValue(from value: OCKOutcomeValue) -> OCKCDOutcomeValue { + let object = OCKCDOutcomeValue(context: context) + object.copyValues(from: value) + object.value = value.value + object.kind = value.kind + object.units = value.units + object.index = value.index == nil ? nil : NSNumber(value: value.index!) + return object + } + + func makeSchedule(elements: [OCKCDScheduleElement]) -> OCKSchedule { + OCKSchedule(composing: elements.map { object -> OCKScheduleElement in + OCKScheduleElement(start: object.startDate, end: object.endDate, + interval: object.interval, text: object.text, + targetValues: object.targetValues.map(makeValue), + duration: object.duration) + }) + } + + func makeValue(persistableValue: OCKCDOutcomeValue) -> OCKOutcomeValue { + assert(persistableValue.localDatabaseID != nil, "You shouldn't be calling this method with an object that hasn't been saved yet!") + var value = OCKOutcomeValue(persistableValue.value, units: persistableValue.units) + value.index = persistableValue.index?.intValue + value.copyCommonValues(from: persistableValue) + return value + } + + func makeHealthKitLinkage(from linkage: OCKCDHealthKitLinkage?) -> OCKHealthKitLinkage? { + guard let linkage = linkage else { return nil } + guard let quantity = OCKHealthKitLinkage.QuantityType(rawValue: linkage.quantityType) else { fatalError("Invlaid quantity type!") } + let identifier = HKQuantityTypeIdentifier(rawValue: linkage.quantityIdentifier) + let unit = HKUnit(from: linkage.unitString) + return OCKHealthKitLinkage(quantityIdentifier: identifier, quantityType: quantity, unit: unit) + } + + // Ensure that new versions of tasks do not overwrite regions of previous + // versions that already have outcomes saved to them. + // + // |<------------- Time Line --------------->| + // TaskV1 ------x-------------------> + // V2 ----------> + // V3------------------> + // + // Throws an error when updating to V3 from V2 if V1 has outcomes after `x`. + // Throws an error when updating to V3 from V2 if V2 has any outcomes. + // Does not trow when updating to V3 from V2 if V1 has outcomes before `x`. + private func confirmUpdateWillNotCauseDataLoss(tasks: [Task]) throws { + let heads: [OCKCDTask] = OCKCDTask.fetchHeads(ids: tasks.map { $0.id }, in: context) + for task in heads { + + // For each task, gather all outcomes + var allOutcomes: Set = [] + var currentVersion: OCKCDTask? = task + while let version = currentVersion { + allOutcomes = allOutcomes.union(version.outcomes) + currentVersion = version.previous as? OCKCDTask + } + + // Get the date highest date on which an outcome exists. + // If there are no outcomes, then any update is safe. + guard let latestDate = allOutcomes.map({ $0.date }).max() + else { continue } + + guard let proposedUpdate = tasks.first(where: { $0.id == task.id }) + else { fatalError("Fetched an OCKCDTask for which an update was not proposed.") } + + if proposedUpdate.effectiveDate <= latestDate { + throw OCKStoreError.updateFailed(reason: """ + Updating task \(task.id) failed. The new version of the task takes effect on \(task.effectiveDate), but an outcome for a + previous version of the task exists on \(latestDate). To prevent implicit data loss, you must explicitly delete all outcomes + that exist after the new version's `effectiveDate` before applying the update, or move the new version's `effectiveDate` to + some date past the latest outcome's date. + """ + ) + } + } + } + + func buildPredicate(for query: OCKTaskQuery) throws -> NSPredicate { + var predicate = OCKCDVersionedObject.notDeletedPredicate + + if let interval = query.dateInterval { + let headPredicate = OCKCDVersionedObject.newestVersionPredicate(in: interval) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, headPredicate]) + } + + if !query.ids.isEmpty { + let idPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDVersionedObject.id), query.ids) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, idPredicate]) + } + + if !query.versionIDs.isEmpty { + let versionPredicate = NSPredicate(format: "self IN %@", try query.versionIDs.map(objectID)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, versionPredicate]) + } + + if !query.remoteIDs.isEmpty { + let remotePredicate = NSPredicate(format: "%K in %@", #keyPath(OCKCDVersionedObject.remoteID), query.remoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, remotePredicate]) + } + + if !query.carePlanIDs.isEmpty { + let planPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDTask.carePlan.id), query.carePlanIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, planPredicate]) + } + + if !query.carePlanVersionIDs.isEmpty { + let planPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDTask.carePlan), try query.carePlanVersionIDs.map(objectID)) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, planPredicate]) + } + + if !query.carePlanRemoteIDs.isEmpty { + let planPredicate = NSPredicate(format: "%K IN %@", #keyPath(OCKCDTask.carePlan.remoteID), query.carePlanRemoteIDs) + predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate, planPredicate]) + } + + return predicate + } + + func buildSortDescriptors(for query: OCKTaskQuery?) -> [NSSortDescriptor] { + guard let orders = query?.extendedSortDescriptors else { return [] } + return orders.map { order -> NSSortDescriptor in + switch order { + case .effectiveDate(ascending: let ascending): return NSSortDescriptor(keyPath: \OCKCDTask.effectiveDate, ascending: ascending) + case .title(let ascending): return NSSortDescriptor(keyPath: \OCKCDTask.title, ascending: ascending) + case .groupIdentifier(let ascending): return NSSortDescriptor(keyPath: \OCKCDTask.groupIdentifier, ascending: ascending) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEvent.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEvent.swift new file mode 100755 index 0000000..3d92ea3 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEvent.swift @@ -0,0 +1,64 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An event represents a single occassion on which a task was scheduled to occur. It contains a copy of the task itself as well as the +/// schedule event and an outcome that will be non-nil if progress was made on the task. +public struct OCKAnyEvent { + + /// The task that this event is associated with + public let task: OCKAnyTask + + /// The outcome for this event. If the outcome is empty, that means that no actions were recorded. + /// + /// - Note: The outcome may be non-nil even if if the task was not completed, so simply checking the presence of an outcome is not sufficient + /// to determing whether or not the task was completed. Examples of times when the outcome is non-nil but the task was not completed could + /// include, among others + /// 1. The user created a note specifying why they weren't able to complete the task. + /// 2. The user completed the task, but then deleted all the values they recorded. + /// 3. The user only partially completed the task. + public let outcome: OCKAnyOutcome? + + /// The schedule event for this task occurrence. It contains information about the start, duration, occurrence number, and schedule element that + /// resulted in this event. + public let scheduleEvent: OCKScheduleEvent + + /// Initialize by specifying a task, schedule event, and optional outcome. + /// + /// - Parameter task: The task associated with this event. + /// - Parameter outcome: The outcome associated with this event, or nil if no outcome exists yet. + /// - Parameter scheduleEvent: The schedule event that resulted in this event. + public init(task: OCKAnyTask, outcome: OCKAnyOutcome?, scheduleEvent: OCKScheduleEvent) { + self.task = task + self.outcome = outcome + self.scheduleEvent = scheduleEvent + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEventStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEventStore.swift new file mode 100755 index 0000000..0e63a53 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKAnyEventStore.swift @@ -0,0 +1,163 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which `OCKAnyEvent`s can be queried is considered `OCKAnyReadOnlyEventStore`. +public protocol OCKAnyReadOnlyEventStore: OCKAnyReadOnlyTaskStore, OCKAnyReadOnlyOutcomeStore { + + /// `fetchAnyEvents` retrieves all the occurrences of the speficied task in the interval specified by the provided query. + /// + /// - Parameters: + /// - taskID: A user-defined unique identifier for the task. + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyEvents(taskID: String, query: OCKEventQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyEvent]>) + + /// `fetchAnyEvent` retrieves a single occurrence of the speficied task. + /// + /// - Parameter task: The task for which to retrieve an event. + /// - Parameter occurrence: The occurrence index of the desired event. + /// - Parameter queue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - Parameter completion: A callback that will fire on the specified queue. + func fetchAnyEvent(forTask task: OCKAnyTask, occurrence: Int, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) + + /// `fetchAnyAdherence` retrieves all the events and calculates the percent of tasks completed for every day between two dates. + /// + /// The way completion is computed depends on how many `expectedValues` a task has. If it has no expected values, + /// then having an outcome with at least one value will count as complete. If a task has expected values, completion + /// will be computed as ratio of the number of outcome values to the number of expected values. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. The result contains an array with one value for each day. + func fetchAdherence(query: OCKAdherenceQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[OCKAdherence]>) + + /// `fetchInsights` computes a metric for a given task between two dates using the provided closure. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchInsights(query: OCKInsightQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Double]>) +} + +/// Any store from which `OCKAnyEvent`s can be queried and also written is considered `OCKAnyEventStore`. +public protocol OCKAnyEventStore: OCKAnyReadOnlyEventStore, OCKAnyTaskStore, OCKAnyOutcomeStore { + +} + +// MARK: Adherence and Insights Methods for OCKAnyReadOnlyEventStore + +public extension OCKAnyReadOnlyEventStore where Self: OCKAnyReadOnlyTaskStore, Self: OCKAnyReadOnlyOutcomeStore { + + func fetchAdherence(query: OCKAdherenceQuery, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure<[OCKAdherence]>) { + var taskQuery = OCKTaskQuery(dateInterval: query.dateInterval) + taskQuery.ids = query.taskIDs + + fetchAnyTasks(query: taskQuery, callbackQueue: callbackQueue) { result in + switch result { + case .failure(let error): completion(.failure(.fetchFailed(reason: "Failed to fetch adherence. \(error.localizedDescription)"))) + case .success(let tasks): + let tasks = tasks.filter { $0.impactsAdherence } + guard !tasks.isEmpty else { + let adherences = query.dates().map { _ in OCKAdherence.noTasks } + completion(.success(adherences)) + return + } + let group = DispatchGroup() + var error: Error? + var events: [OCKAnyEvent] = [] + for id in tasks.map({ $0.id }) { + group.enter() + let query = OCKEventQuery(dateInterval: query.dateInterval) + self.fetchAnyEvents(taskID: id, query: query, callbackQueue: callbackQueue, completion: { result in + switch result { + case .failure(let fetchError): error = fetchError + case .success(let fetchedEvents): events.append(contentsOf: fetchedEvents) + } + group.leave() + }) + } + group.notify(queue: .global(qos: .userInitiated), execute: { + if let error = error { + callbackQueue.async { + completion(.failure(.fetchFailed(reason: "Failed to fetch completion for tasks! \(error.localizedDescription)"))) + } + return + } + let groupedEvents = self.groupEventsByDate(events: events, after: query.dateInterval.start, before: query.dateInterval.end) + var adherenceValues = [OCKAdherence](repeating: .noTasks, count: groupedEvents.count) + let indicesWithTasks = self.datesWithTasks(query: query, tasks: tasks).enumerated().compactMap { $1 ? $0 : nil } + indicesWithTasks.forEach { adherenceValues[$0] = query.aggregator.aggregate(events: groupedEvents[$0]) } + callbackQueue.async { completion(.success(adherenceValues)) } + }) + } + } + } + + func fetchInsights(query: OCKInsightQuery, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure<[Double]>) { + let eventQuery = OCKEventQuery(dateInterval: query.dateInterval) + fetchAnyEvents(taskID: query.taskID, query: eventQuery, callbackQueue: callbackQueue) { result in + switch result { + case .failure(let error): completion(.failure(.fetchFailed(reason: "Failed to fetch insights. \(error.localizedDescription)"))) + case .success(let events): + let eventsByDay = self.groupEventsByDate(events: events, after: query.dateInterval.start, before: query.dateInterval.end) + let valuesByDay = eventsByDay.map(query.aggregator.aggregate) + completion(.success(valuesByDay)) + } + } + } + + private func groupEventsByDate(events: [OCKAnyEvent], after start: Date, before end: Date) -> [[OCKAnyEvent]] { + var days: [[OCKAnyEvent]] = [] + let grabDayIndex = { (date: Date) in Calendar.current.dateComponents(Set([.day]), from: start, to: date).day! } + let numberOfDays = grabDayIndex(end) + 1 + for _ in 0.. [Bool] { + query.dates().map { date in tasks.map { $0.schedule.exists(onDay: date) }.contains(true) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKEventStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKEventStore.swift new file mode 100755 index 0000000..7195460 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Events/OCKEventStore.swift @@ -0,0 +1,229 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which a single event type can be queried is considered a `OCKReadOnlyEventStore`. +public protocol OCKReadOnlyEventStore: OCKAnyReadOnlyEventStore, OCKReadableTaskStore, OCKReadableOutcomeStore { + typealias Event = OCKEvent + + // MARK: Implementation Provided when Task == OCKTask and Outcome == OCKOutcome + + /// `fetchEvents` retrieves all the occurrences of the specified task in the interval specified by the provided query. + /// + /// - Parameters: + /// - taskID: A user-defined unique identifier for the task. + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchEvents(taskID: String, query: OCKEventQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[Event]>) + + /// `fetchEvent` retrieves a single occurrence of the speficied task. + /// + /// - Parameter task: The task for which to retrieve an event. + /// - Parameter occurrence: The occurrence index of the desired event. + /// - Parameter queue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - Parameter completion: A callback that will fire on the specified queue. + func fetchEvent(forTask task: Task, occurrence: Int, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store in which a single event type can be both queried and written is considered a `OCKEventStore`. +public protocol OCKEventStore: OCKReadOnlyEventStore, OCKTaskStore, OCKOutcomeStore, OCKAnyEventStore {} + +// MARK: OCKAnyReadOnlyEventStore conformance for OCKReadOnlyEventStore + +public extension OCKReadOnlyEventStore { + func fetchAnyEvents(taskID: String, query: OCKEventQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyEvent]>) { + fetchEvents(taskID: taskID, query: query, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0.anyEvent } }) } + } + + func fetchAnyEvent(forTask task: OCKAnyTask, occurrence: Int, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) { + guard let typedTask = task as? Task else { + callbackQueue.async { + let message = "Store of type \(type(of: self)) cannot fetch event with task type \(type(of: task))." + completion(.failure(.fetchFailed(reason: message))) + } + return + } + fetchEvent(forTask: typedTask, occurrence: occurrence, callbackQueue: callbackQueue) { completion($0.map { $0.anyEvent }) } + } +} + +// MARK: OCKReadOnlyEventStore Implementations for Task: OCKAnyTableBackedTask, Outcome == OCKOutcome, OutcomeQuery == OCKOutcomeQuery + +public extension OCKReadOnlyEventStore where Task: OCKAnyVersionableTask, Outcome == OCKOutcome, OutcomeQuery == OCKOutcomeQuery { + + // MARK: Events + + func fetchEvents(taskID: String, query: OCKEventQuery, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure<[OCKEvent]>) { + var taskQuery = OCKTaskQuery() + taskQuery.dateInterval = query.dateInterval + taskQuery.limit = 1 + taskQuery.extendedSortDescriptors = [.effectiveDate(ascending: true)] + taskQuery.ids = [taskID] + + fetchTasks(query: TaskQuery(taskQuery), callbackQueue: callbackQueue, completion: chooseFirst(then: { result in + switch result { + case .failure(let error): + completion(.failure(error)) + case .success(let task): + self.fetchEvents(task: task, query: query, previousEvents: [], callbackQueue: callbackQueue, completion: completion) + } + }, replacementError: .fetchFailed(reason: "No task with id: \(taskID) for query: \(taskQuery)"))) + } + + func fetchEvent(forTask task: Task, occurrence: Int, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure) { + guard let taskID = task.localDatabaseID else { + callbackQueue.async { + let message = "Cannot fetch events for a task that hasn't been persisted yet!" + completion(.failure(.fetchFailed(reason: message))) + } + return + } + fetchEvent(withTaskVersionID: taskID, occurrenceIndex: occurrence, callbackQueue: callbackQueue, completion: completion) + } + + private func fetchEvent(withTaskVersionID taskVersionID: OCKLocalVersionID, occurrenceIndex: Int, + callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure>) { + fetchTask(withVersionID: taskVersionID, callbackQueue: callbackQueue, completion: { (result: Result) in + switch result { + case .failure(let error): completion(.failure(.fetchFailed(reason: "Failed to fetch task. \(error.localizedDescription)"))) + case .success(let task): + guard let scheduleEvent = task.schedule.event(forOccurrenceIndex: occurrenceIndex) else { + completion(.failure(.fetchFailed(reason: "Invalid occurrence \(occurrenceIndex) for task with version ID: \(taskVersionID)"))) + return + } + let early = scheduleEvent.start.addingTimeInterval(-1) + let late = scheduleEvent.end.addingTimeInterval(1) + var query = OCKOutcomeQuery(dateInterval: DateInterval(start: early, end: late)) + query.taskVersionIDs = [taskVersionID] + self.fetchOutcome(query: query, callbackQueue: callbackQueue, completion: { result in + switch result { + case .failure(let error): completion(.failure(.fetchFailed(reason: "Couldn't find outcome. \(error.localizedDescription)"))) + case .success(let outcome): + let event = OCKEvent(task: task, outcome: outcome, scheduleEvent: scheduleEvent) + completion(.success(event)) + } + }) + } + }) + } + + // This is a recursive async function that gets all events within a query for a given task, examining all past versions of the task + private func fetchEvents(task: Task, query: OCKEventQuery, previousEvents: [Event], + callbackQueue: DispatchQueue = .main, completion: @escaping (Result<[Event], OCKStoreError>) -> Void) { + guard let versionID = task.localDatabaseID else { completion(.failure(.fetchFailed(reason: "Task didn't have a versionID"))); return } + let start = max(task.effectiveDate, query.dateInterval.start) + let scheduledEndDate = task.schedule.endDate() + let end = scheduledEndDate == nil ? query.dateInterval.end : min(scheduledEndDate!, query.dateInterval.end) + let scheduleEvents = task.schedule.events(from: start, to: end) + var outcomeQuery = OCKOutcomeQuery(dateInterval: DateInterval(start: start, end: end)) + outcomeQuery.taskVersionIDs = [versionID] + self.fetchOutcomes(query: outcomeQuery, callbackQueue: callbackQueue, completion: { result in + switch result { + case .failure(let error): completion(.failure(error)) + case .success(let outcomes): + let events = self.join(task: task, with: outcomes, and: scheduleEvents) + previousEvents + + // If the query doesn't go back in time beyond the start of this version of the task, we're done. + guard query.dateInterval.start < task.effectiveDate else { + completion(.success(events)) + return + } + + self.fetchNextValidPreviousVersion(for: task, callbackQueue: callbackQueue) { result in + switch result { + case .failure(let error): completion(.failure(error)) + case .success(let previousVersion): + + // If there is no previous version, then we're done fetching all events. + guard let previousVersion = previousVersion else { + completion(.success(events)) + return + } + + // If there is a previous version, fetch the events for it that don't overlap with + // any of the versions we've already fetched events for. + let nextEndDate = task.effectiveDate + let nextStartDate = max(query.dateInterval.start, previousVersion.effectiveDate) + let nextInterval = DateInterval(start: nextStartDate, end: nextEndDate) + let nextQuery = OCKEventQuery(dateInterval: nextInterval) + self.fetchEvents(task: previousVersion, query: nextQuery, previousEvents: events, + callbackQueue: callbackQueue, completion: completion) + } + + } + } + }) + } + + private func fetchNextValidPreviousVersion(for task: Task, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) { + + guard let versionID = task.previousVersionID else { + completion(.success(nil)) + return + } + + fetchTask(withVersionID: versionID, callbackQueue: callbackQueue) { result in + switch result { + case .failure(let error): completion(.failure(error)) + case .success(let previousVersion): + + // If the newer version goes back further in time than the pervious version, skip fetching events for the older version. + if task.effectiveDate <= previousVersion.effectiveDate { + self.fetchNextValidPreviousVersion(for: previousVersion, callbackQueue: callbackQueue, completion: completion) + return + } + + completion(.success(previousVersion)) + } + } + } + + private func fetchTask(withVersionID versionID: OCKLocalVersionID, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) { + var query = OCKTaskQuery() + query.versionIDs = [versionID] + fetchTasks(query: TaskQuery(query), callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No task with versionID: \(versionID)"))) + } + + private func join(task: Task, with outcomes: [Outcome], and scheduleEvents: [OCKScheduleEvent]) -> [OCKEvent] { + guard !scheduleEvents.isEmpty else { return [] } + let offset = scheduleEvents[0].occurrence + var events = scheduleEvents.map { OCKEvent(task: task, outcome: nil, scheduleEvent: $0) } + for outcome in outcomes { + events[outcome.taskOccurrenceIndex - offset].outcome = outcome + } + return events + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKCDManageable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKCDManageable.swift new file mode 100755 index 0000000..b918fed --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKCDManageable.swift @@ -0,0 +1,71 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CoreData + +protocol OCKCDManageable: AnyObject, NSFetchRequestResult { + static var entityName: String { get } + static var defaultSortDescriptors: [NSSortDescriptor] { get } +} + +extension OCKCDManageable { + static var sortedFetchRequest: NSFetchRequest { + let request = NSFetchRequest(entityName: entityName) + request.sortDescriptors = defaultSortDescriptors + return request + } + + static func sortedFetchRequest(withPredicate predicate: NSPredicate) -> NSFetchRequest { + let request = sortedFetchRequest + request.predicate = predicate + return request + } +} + +extension OCKCDManageable where Self: NSManagedObject { + static var entityName: String { return entity().name! } + + /// Fetches all objects from the store matching the provided predicate. This method queries all the way down + /// to the database layer because while we may be able to find some objects matching the query in memory, we + /// cannot guarantee that there aren't more yet to be loaded from the database + /// + /// - Parameters: + /// - context: the context in which to search + /// - predicate: a predicate to match against + /// - configureFetchRequest: a closure in which you may customize the fetch request + /// - Returns: all objects matching the give predicate + static func fetchFromStore(in context: NSManagedObjectContext, where predicate: NSPredicate, + configureFetchRequest: ((NSFetchRequest) -> Void)? = nil) -> [Self] { + let request = sortedFetchRequest(withPredicate: predicate) + configureFetchRequest?(request) + guard let results = try? context.fetch(request) else { fatalError("This should never fail") } + return results + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKObjectCompatible.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKObjectCompatible.swift new file mode 100755 index 0000000..974f687 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKObjectCompatible.swift @@ -0,0 +1,130 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +internal protocol OCKObjectCompatible { + /// The date at which the object was first persisted to the database. + /// It will be nil for unpersisted values and objects. + var createdDate: Date? { get set } + + /// The last date at which the object was updated. + /// It will be nil for unpersisted values and objects. + var updatedDate: Date? { get set } + + /// A user-defined group identifer that can be used both for querying and sorting results. + /// Examples may include: "medications", "exercises", "family", "males", "diabetics", etc. + var groupIdentifier: String? { get set } + + /// An array of user-defined tags that can be used to sort or classify objects or values. + var tags: [String]? { get set } + + /// A unique id used by the local database. Its precise format will be determined + /// by the underlying database, but it is generally not expected to be human readable. + var localDatabaseID: OCKLocalVersionID? { get set } + + /// A unique id optionally used by a remote database. Its precise format will be + /// determined by the remote database, but it is generally not expected to be human readable. + var remoteID: String? { get set } + + /// A dictionary of information that can be provided by developers to support their own unique + /// use cases. + var userInfo: [String: String]? { get set } + + /// Specifies where this object originated from. It could contain information about the device + /// used to record the data, its software version, or the person who recorded the data. + var source: String? { get set } + + /// Specifies the location of some asset associated with this object. It could be the URL for + /// an image or video, the bundle name of a audio asset, or any other representation the + /// developer chooses. + var asset: String? { get set } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get set } + + /// The semantic version of the database schema when this object was created. + /// The value will be nil for objects that have not yet been persisted. + var schemaVersion: OCKSemanticVersion? { get set } + + /// The timezone this record was created in. + var timezone: TimeZone { get set } +} + +internal protocol OCKVersionedObjectCompatible: OCKObjectCompatible { + /// A human readable unique identifier. It is used strictly by the developer and will never be shown to a user. + var id: String { get } + + /// The database ID of the previous version of this object, or nil if there is no previous version. + var previousVersionID: OCKLocalVersionID? { get set } + + /// The database ID of the next version of this object, or nil if there is no next version. + var nextVersionID: OCKLocalVersionID? { get set } + + /// The date that this version of the object begins to take precedence over the previous version. + /// Often this will be the same as the `createdDate`, but is not required to be. + var effectiveDate: Date { get set } + + /// The date on which this object was marked deleted. Note that objects are never actually deleted, + /// but rather they are marked deleted and will no longer be returned from queries. + var deletedDate: Date? { get set } +} + +extension OCKObjectCompatible { + mutating func copyCommonValues(from other: OCKCDObject) { + createdDate = other.createdDate + updatedDate = other.updatedDate + schemaVersion = OCKSemanticVersion(other.schemaVersion) + groupIdentifier = other.groupIdentifier + tags = other.tags + source = other.source + localDatabaseID = other.localDatabaseID + remoteID = other.remoteID + userInfo = other.userInfo + asset = other.asset + timezone = TimeZone(identifier: other.timezoneIdentifier)! + notes = other.notes?.map { + var note = OCKNote(author: $0.author, title: $0.title, content: $0.content) + note.copyCommonValues(from: $0) + return note + } + } +} + +extension OCKVersionedObjectCompatible { + mutating func copyVersionedValues(from other: OCKCDVersionedObject) { + deletedDate = other.deletedDate + effectiveDate = other.effectiveDate + localDatabaseID = other.localDatabaseID + nextVersionID = other.next?.localDatabaseID + previousVersionID = other.previous?.localDatabaseID + copyCommonValues(from: other) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol+Synchronous.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol+Synchronous.swift new file mode 100755 index 0000000..a8860c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol+Synchronous.swift @@ -0,0 +1,300 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +// This is helper method wraps stores' asychronous methods to make them synchronous. +internal func performSynchronously(_ closure: (@escaping (Result) -> Void) -> Void) throws -> T { + let timeout: TimeInterval = 10.0 + let dispatchGroup = DispatchGroup() + var closureResult: Result = .failure(.timedOut(reason: "Timed out after \(timeout) seconds.")) + dispatchGroup.enter() + closure { result in + closureResult = result + dispatchGroup.leave() + } + _ = dispatchGroup.wait(timeout: .now() + timeout) + return try closureResult.get() +} + +private let backgroundQueue = DispatchQueue(label: "CareKit", qos: .background) + +// WARNING: These extensions are intended for use exclusively in unit tests. + +extension OCKAnyReadOnlyPatientStore { + func fetchAnyPatientsAndWait(query: OCKAnyPatientQuery) throws -> [OCKAnyPatient] { + try performSynchronously { fetchAnyPatients(query: query, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKAnyPatientStore { + + @discardableResult + func addAnyPatientsAndWait(_ patients: [OCKAnyPatient]) throws -> [OCKAnyPatient] { + try performSynchronously { addAnyPatients(patients, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addAnyPatientAndWait(_ patient: OCKAnyPatient) throws -> OCKAnyPatient { + try performSynchronously { addAnyPatient(patient, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadablePatientStore { + func fetchPatientsAndWait(query: PatientQuery = PatientQuery()) throws -> [Patient] { + try performSynchronously { fetchPatients(query: query, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func fetchPatientAndWait(id: String) throws -> Patient { + try performSynchronously { fetchPatient(withID: id, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKPatientStore { + @discardableResult + func addPatientsAndWait(_ patients: [Patient]) throws -> [Patient] { + try performSynchronously { addPatients(patients, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addPatientAndWait(_ patient: Patient) throws -> Patient { + try performSynchronously { addPatient(patient, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updatePatientsAndWait(_ patients: [Patient]) throws -> [Patient] { + try performSynchronously { updatePatients(patients, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updatePatientAndWait(_ patient: Patient) throws -> Patient { + try performSynchronously { updatePatient(patient, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deletePatientsAndWait(_ patients: [Patient]) throws -> [Patient] { + try performSynchronously { deletePatients(patients, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deletePatientAndWait(_ patient: Patient) throws -> Patient { + try performSynchronously { deletePatient(patient, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadableCarePlanStore { + func fetchCarePlansAndWait(query: PlanQuery = PlanQuery()) throws -> [Plan] { + try performSynchronously { fetchCarePlans(query: query, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func fetchCarePlanAndWait(id: String) throws -> Plan? { + try performSynchronously { fetchCarePlan(withID: id, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKCarePlanStore { + @discardableResult + func addCarePlansAndWait(_ plans: [Plan]) throws -> [Plan] { + try performSynchronously { addCarePlans(plans, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addCarePlanAndWait(_ plan: Plan) throws -> Plan { + try performSynchronously { addCarePlan(plan, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateCarePlansAndWait(_ plans: [Plan]) throws -> [Plan] { + try performSynchronously { updateCarePlans(plans, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateCarePlanAndWait(_ plan: Plan) throws -> Plan { + try performSynchronously { updateCarePlan(plan, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteCarePlansAndWait(_ plans: [Plan]) throws -> [Plan] { + try performSynchronously { deleteCarePlans(plans, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteCarePlanAndWait(_ plan: Plan) throws -> Plan { + try performSynchronously { deleteCarePlan(plan, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadableContactStore { + func fetchContactAndWait(id: String) throws -> Contact? { + try performSynchronously { fetchContact(withID: id, callbackQueue: backgroundQueue, completion: $0) } + } + + func fetchContactsAndWait(query: ContactQuery = ContactQuery()) throws -> [Contact] { + try performSynchronously { fetchContacts(query: query, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKContactStore { + @discardableResult + func addContactsAndWait(_ contacts: [Contact]) throws -> [Contact] { + return try performSynchronously { addContacts(contacts, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addContactAndWait(_ contact: Contact) throws -> Contact { + try performSynchronously { addContact(contact, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateContactsAndWait(_ contacts: [Contact]) throws -> [Contact] { + try performSynchronously { updateContacts(contacts, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateContactAndWait(_ contact: Contact) throws -> Contact { + try performSynchronously { updateContact(contact, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteContactsAndWait(_ contacts: [Contact]) throws -> [Contact] { + try performSynchronously { deleteContacts(contacts, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteContactAndWait(_ contact: Contact) throws -> Contact { + try performSynchronously { deleteContact(contact, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadableTaskStore { + func fetchTasksAndWait(query: TaskQuery = TaskQuery()) throws -> [Task] { + try performSynchronously { fetchTasks(query: query, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKTaskStore { + @discardableResult + func addTasksAndWait(_ tasks: [Task]) throws -> [Task] { + try performSynchronously { addTasks(tasks, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addTaskAndWait(_ task: Task) throws -> Task { + try performSynchronously { addTask(task, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateTasksAndWait(_ tasks: [Task]) throws -> [Task] { + try performSynchronously { updateTasks(tasks, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateTaskAndWait(_ task: Task) throws -> Task { + try performSynchronously { updateTask(task, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteTasksAndWait(_ tasks: [Task]) throws -> [Task] { + try performSynchronously { deleteTasks(tasks, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteTaskAndWait(_ task: Task) throws -> Task { + try performSynchronously { deleteTask(task, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadableOutcomeStore { + func fetchOutcomesAndWait(query: OutcomeQuery = OutcomeQuery()) throws -> [Outcome] { + try performSynchronously { fetchOutcomes(query: query, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKOutcomeStore { + @discardableResult + func addOutcomesAndWait(_ outcomes: [Outcome]) throws -> [Outcome] { + try performSynchronously { addOutcomes(outcomes, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func addOutcomeAndWait(_ outcome: Outcome) throws -> Outcome { + try performSynchronously { addOutcome(outcome, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateOutcomesAndWait(_ outcomes: [Outcome]) throws -> [Outcome] { + try performSynchronously { updateOutcomes(outcomes, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func updateOutcomeAndWait(_ outcome: Outcome) throws -> Outcome { + try performSynchronously { updateOutcome(outcome, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteOutcomesAndWait(_ outcomes: [Outcome]) throws -> [Outcome] { + try performSynchronously { deleteOutcomes(outcomes, callbackQueue: backgroundQueue, completion: $0) } + } + + @discardableResult + func deleteOutcomeAndWait(_ outcome: Outcome) throws -> Outcome { + try performSynchronously { deleteOutcome(outcome, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKReadOnlyEventStore { + func fetchEventsAndWait(taskID: String, query: OCKEventQuery) throws -> [OCKEvent] { + try performSynchronously { fetchEvents(taskID: taskID, query: query, callbackQueue: backgroundQueue, completion: $0) } + } + + func fetchEventAndWait(forTask task: Task, occurrence: Int) throws -> Event { + try performSynchronously { fetchEvent(forTask: task, occurrence: occurrence, callbackQueue: backgroundQueue, completion: $0) } + } + + // MARK: Adherence + + func fetchAdherenceAndWait(query: OCKAdherenceQuery) throws -> [OCKAdherence] { + try performSynchronously { fetchAdherence(query: query, callbackQueue: backgroundQueue, completion: $0) } + } + + // MARK: Insights + + func fetchInsightsAndWait(query: OCKInsightQuery) throws -> [Double] { + try performSynchronously { fetchInsights(query: query, callbackQueue: backgroundQueue, completion: $0) } + } +} + +extension OCKAnyTaskStore { + func addAnyTaskAndWait(_ task: OCKAnyTask) throws -> OCKAnyTask { + try performSynchronously { addAnyTask(task, callbackQueue: backgroundQueue, completion: $0) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol.swift new file mode 100755 index 0000000..a9a85b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/OCKStoreProtocol.swift @@ -0,0 +1,45 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Foundation + +/// CareKit can support any store that conforms to this protocol. The `OCKStore` class included in CareKit is a CoreData store that the implements +/// `OCKStoreProtocol` to provide on device storage. Support for other databases such as JSON files, REST API's, websockets, and 3rd part databases +/// can be added by conforming them to `OCKStoreProtocol`. +/// +/// `OCKStoreProtocol` requires that a minimum level of functionality be provided, and then provides enhanced functionality via protocol extensions. +/// The methods provided by protocol extensions are naive implementations and are not efficient. Developers may wish to use the customization points +/// on `OCKStoreProtocol` to provide more efficient implementations that take advantage of the underlying database's native features. +/// +/// - Remark: All methods defined in this protocol are required to be implemented as batch operations and should function as transactions. +/// If any one operation should fail, the state of the store should be returned to the state it was in before the transaction began. For example, +/// if an attempt to save an array of 10 outcomes fails on the 6th outcome, the first successfully persisted 6 outcomes must be rolled back to restore +/// the store to the state it was in prior to the transaction. +public typealias OCKStoreProtocol = OCKPatientStore & OCKCarePlanStore & OCKContactStore & OCKEventStore +public typealias OCKAnyStoreProtocol = OCKAnyPatientStore & OCKAnyCarePlanStore & OCKAnyContactStore & OCKAnyEventStore diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcome.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcome.swift new file mode 100755 index 0000000..61b475e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcome.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Conforming a type to `OCKAnyOutcome` allows it to be queried and displayed by CareKit. +public protocol OCKAnyOutcome { + + /// A user-defined unique identifier, typically human readable. + var id: String { get } + + /// Specifies how many events occured before this outcome was created. For example, if a task is schedule to happen twice per day, then + /// the 2nd outcome on the 2nd day will have a `taskOccurrenceIndex` of 3. + /// + /// - Note: The task occurrence references a specific version of a task, so if a new version the task is created, the task occurrence index + /// will start again from 0. + var taskOccurrenceIndex: Int { get } + + /// An array of values associated with this outcome. Most outcomes will have 0 or 1 values, but some may have more. + /// - Examples: + /// - A task to call a physician might have 0 values, or 1 value containing the time stamp of when the call was placed. + /// - A task to walk 2,000 steps might have 1 value, with that value being the number of steps that were actually taken. + /// - A task to complete a survey might have multiple values corresponding to the answers to the questions in the survey. + var values: [OCKOutcomeValue] { get set } + + /// An identifier for this outcome in a remote store. + var remoteID: String? { get } + + /// An identifier that can be uesd to group this outcome with others. + var groupIdentifier: String? { get } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get } + + /// Determines if this outcome is associated with the given task. + /// + /// - Parameter task: A task which may or may not own this outcome. + func belongs(to task: OCKAnyTask) -> Bool +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcomeStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcomeStore.swift new file mode 100755 index 0000000..6cfc81a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKAnyOutcomeStore.swift @@ -0,0 +1,142 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public protocol OCKAnyReadOnlyOutcomeStore: AnyObject { + + /// The delegate receives callbacks when the contents of the care plan store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + var outcomeDelegate: OCKOutcomeStoreDelegate? { get set } + + /// `fetchAnyOutcomes` asynchronously retrieves an array of outcomes from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyOutcomes(query: OCKAnyOutcomeQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyOutcome]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchAnyOutcome` asynchronously retrieves a single outcome from the store. If more than one outcome matches the query, only the first + /// will be returned. If no matching outcomes exist, the completion handler will be called with an error. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyOutcome(query: OCKAnyOutcomeQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure) +} + +public protocol OCKAnyOutcomeStore: OCKAnyReadOnlyOutcomeStore { + + /// `addOutcomes` asynchronously adds an array of outcomes to the store. + /// + /// - Parameters: + /// - outcomes: An array of outcomes to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) + + /// `updateOutcomes` asynchronously updates an array of outcomes in the store. + /// + /// - Parameters: + /// - contacts: An array of outcomes to be updated. The outcomes must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) + + /// `deleteOutcomes` asynchronously deletes an array of outcomes from the store. + /// + /// - Parameters: + /// - outcomes: An array of outcomes to be deleted. The outcomes must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) + + // MARK: Singular Methods - Implementation Provided + + /// `addOutcome` asynchronously adds an outcome to the store. + /// + /// - Parameters: + /// - outcome: An outcome to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateOutcome` asynchronously updates an outcome in the store. + /// + /// - Parameters: + /// - outcome: An outcome to be updated. The outcome must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteOutcome` asynchronously deletes an outcome from the store. + /// + /// - Parameters: + /// - outcome: An outcome to be deleted. The outcome must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKAnyReadOnlyOutcomeStore + +public extension OCKAnyReadOnlyOutcomeStore { + func fetchAnyOutcome(query: OCKAnyOutcomeQuery, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + fetchAnyOutcomes(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No matching outcome found"))) + } +} + +// MARK: Singular Methods for OCKAnyOutcomeStore + +public extension OCKAnyOutcomeStore { + + func addAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addAnyOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add outcome: \(outcome)"))) + } + + func updateAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateAnyOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update outcome: \(outcome)"))) + } + + func deleteAnyOutcome(_ outcome: OCKAnyOutcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteAnyOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete outcome: \(outcome)"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStore.swift new file mode 100755 index 0000000..5dfc64d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStore.swift @@ -0,0 +1,178 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Foundation + +/// Any store from which a single type conforming to `OCKAnyTask` can be queried is considered a `OCKReadableOutcomeStore`. +public protocol OCKReadableOutcomeStore: OCKAnyReadOnlyOutcomeStore { + associatedtype Outcome: OCKAnyOutcome & Equatable & Identifiable + associatedtype OutcomeQuery: OCKAnyOutcomeQuery + + /// `fetchOutcomes` asynchronously retrieves an array of outcomes from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchOutcomes(query: OutcomeQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[Outcome]>) + + /// `fetchOutcome` asynchronously retrieves a single outcome from the store. If more than one outcome matches the query, only the first + /// will be returned. If no matching outcomes exist, the completion handler will be called with an error. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchOutcome(query: OutcomeQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure) +} + +public protocol OCKOutcomeStore: OCKAnyOutcomeStore & OCKReadableOutcomeStore { + + /// `addOutcomes` asynchronously adds an array of outcomes to the store. + /// + /// - Parameters: + /// - outcomes: An array of outcomes to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addOutcomes(_ outcomes: [Outcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Outcome]>?) + + /// `updateOutcomes` asynchronously updates an array of outcomes in the store. + /// + /// - Parameters: + /// - contacts: An array of outcomes to be updated. The outcomes must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateOutcomes(_ outcomes: [Outcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Outcome]>?) + + /// `deleteOutcomes` asynchronously deletes an array of outcomes from the store. + /// + /// - Parameters: + /// - outcomes: An array of outcomes to be deleted. The outcomes must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteOutcomes(_ outcomes: [Outcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Outcome]>?) + + // MARK: Implementation Provided + + /// `addOutcome` asynchronously adds an outcome to the store. + /// + /// - Parameters: + /// - outcome: An outcome to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateOutcome` asynchronously updates an outcome in the store. + /// + /// - Parameters: + /// - outcome: An outcome to be updated. The outcome must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteOutcome` asynchronously deletes an outcome from the store. + /// + /// - Parameters: + /// - outcome: An outcome to be deleted. The outcome must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKReadableOutcomeStore + +public extension OCKReadableOutcomeStore { + func fetchOutcome(query: OutcomeQuery, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + fetchOutcomes(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No matching outcome found"))) + } +} + +// MARK: Singular Methods for OCKOutcomeStore + +public extension OCKOutcomeStore { + func addOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add outcome: \(outcome)"))) + } + + func updateOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update outcome: \(outcome)"))) + } + + func deleteOutcome(_ outcome: Outcome, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteOutcomes([outcome], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete outcome: \(outcome)"))) + } +} + +// MARK: OCKAnyReadOnlyStore conformance for OCKReadableOutcomeStore + +public extension OCKReadableOutcomeStore { + func fetchAnyOutcomes(query: OCKAnyOutcomeQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyOutcome]>) { + let outcomeQuery = OutcomeQuery(query) + fetchOutcomes(query: outcomeQuery, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0 as OCKAnyOutcome } }) } + } +} + +// MARK: OCKAnyStore conformance for OCKOutcomeStore + +public extension OCKOutcomeStore { + func addAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) { + guard let outcomes = outcomes as? [Outcome] else { + let message = "Failed to add outcomes. Not all outcomes were the correct type, \(Outcome.self)." + callbackQueue.async { completion?(.failure(.addFailed(reason: message))) } + return + } + addOutcomes(outcomes, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyOutcome } }) } + } + + func updateAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) { + guard let outcomes = outcomes as? [Outcome] else { + let message = "Failed to update outcomes. Not all outcomes were the correct type, \(Outcome.self)." + callbackQueue.async { completion?(.failure(.updateFailed(reason: message))) } + return + } + updateOutcomes(outcomes, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyOutcome } }) } + } + + func deleteAnyOutcomes(_ outcomes: [OCKAnyOutcome], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyOutcome]>?) { + guard let outcomes = outcomes as? [Outcome] else { + let message = "Failed to delete outcomes. Not all outcomes were the correct type, \(Outcome.self)." + callbackQueue.async { completion?(.failure(.deleteFailed(reason: message))) } + return + } + deleteOutcomes(outcomes, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyOutcome } }) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStoreDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStoreDelegate.swift new file mode 100755 index 0000000..c4024b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Outcomes/OCKOutcomeStoreDelegate.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Types conforming to this protocol can receive callbacks from outcome stores. +public protocol OCKOutcomeStoreDelegate: AnyObject { + + /// Called each time outcomes are added to the store. + /// - Parameter store: The store which was modified. + /// - Parameter outcomes: The outcomes that were added to the store. + func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didAddOutcomes outcomes: [OCKAnyOutcome]) + + /// Called each time outcomes are updated in the store. + /// - Parameter store: The store which was modified. + /// - Parameter outcomes: The outcomes that were updated in the store. + func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didUpdateOutcomes outcomes: [OCKAnyOutcome]) + + /// Called each time outcomes are added to the store. + /// - Parameter store: The store which was modified. + /// - Parameter outcomes: The outcomes that were deleted from the store. + func outcomeStore(_ store: OCKAnyReadOnlyOutcomeStore, didDeleteOutcomes outcomes: [OCKAnyOutcome]) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatient.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatient.swift new file mode 100755 index 0000000..4a50492 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatient.swift @@ -0,0 +1,59 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Conforming a type to `OCKAnyPatient` allows it to be queried and displayed by CareKit. +public protocol OCKAnyPatient { + + /// A user-defined unique identifier, typically human readable. + var id: String { get } + + /// The patient's name. + var name: PersonNameComponents { get } + + /// The patient's biological sex. + var sex: OCKBiologicalSex? { get } + + /// The patient's birthday, used to compute their age. + var birthday: Date? { get } + + /// A list of substances this patient is allergic to. + var allergies: [String]? { get } + + /// An identifier for this patient in a remote store. + var remoteID: String? { get } + + /// An identifier that can be uesd to group this patient with others. + var groupIdentifier: String? { get } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatientStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatientStore.swift new file mode 100755 index 0000000..d477d0c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKAnyPatientStore.swift @@ -0,0 +1,147 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which types conforming to `OCKAnyPatient` can be queried is considered `OCKAnyReadOnlyPatientStore`. +public protocol OCKAnyReadOnlyPatientStore: AnyObject { + + /// The delegate receives callbacks when the contents of the patient store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + var patientDelegate: OCKPatientStoreDelegate? { get set } + + /// `fetchAnyPatients` asynchronously retrieves an array of patients from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyPatients(query: OCKAnyPatientQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyPatient]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchAnyPatient` asynchronously retrieves a single patient from the store. + /// + /// - Parameters: + /// - id: The identifier of the item to be fetched. + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyPatient(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store able to write to one ore more types conforming to `OCKAnyPatient` is considered an `OCKAnyPatientStore`. +public protocol OCKAnyPatientStore: OCKAnyReadOnlyPatientStore { + + /// `addAnyPatients` asynchronously adds an array of patients to the store. + /// + /// - Parameters: + /// - patients: A array of patients to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) + + /// `updateAnyPatients` asynchronously updates an array of patients in the store. + /// + /// - Parameters: + /// - patients: An array of patients to be updated. The patients must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) + + /// `deleteAnyPatients` asynchronously deletes an array of patients from the store. + /// + /// - Parameters: + /// - patients: An array of patients to be deleted. The patients must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) + + // MARK: Singular Methods - Implementation Provided + + /// `addAnyPatient` asynchronously adds a single patient to the store. + /// + /// - Parameters: + /// - patient: A single patient to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateAnyPatient` asynchronously updates a single patient in the store. + /// + /// - Parameters: + /// - patient: An single patient to be updated. The patients must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteAnyPatient` asynchronously deletes a single patient from the store. + /// + /// - Parameters: + /// - patients: A single patient to be deleted. The patients must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKAnyReadOnlyPatientStore + +public extension OCKAnyReadOnlyPatientStore { + func fetchAnyPatient(withID id: String, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + var query = OCKPatientQuery(for: Date()) + query.limit = 1 + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + + fetchAnyPatients(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No patient with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKAnyPatientStore + +public extension OCKAnyPatientStore { + func addAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addAnyPatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add patient: \(patient)"))) + } + + func updateAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateAnyPatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update patient: \(patient)"))) + } + + func deleteAnyPatient(_ patient: OCKAnyPatient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteAnyPatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete patient: \(patient)"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStore.swift new file mode 100755 index 0000000..d7d7af7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStore.swift @@ -0,0 +1,187 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +import Foundation + +/// Any store from which a single type conforming to `OCKAnyPatient` can be queried is considered `OCKAnyReadOnlyPatientStore`. +public protocol OCKReadablePatientStore: OCKAnyReadOnlyPatientStore { + associatedtype Patient: OCKAnyPatient & Equatable & Identifiable + associatedtype PatientQuery: OCKAnyPatientQuery + + /// `fetchPatients` asynchronously retrieves an array of patients from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchPatients(query: PatientQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[Patient]>) + + // MARK: Implementation Provided + + /// `fetchPatient` asynchronously fetches a single patient from the store using its user-defined identifier. If a patient with the specified + /// identifier does not exist, the completion handler will be called with an error. + /// + /// - Parameters: + /// - id: A unique user-defined identifier + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchPatient(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store that can perform read and write operations on a single type conforming to `OCKAnyPatient` is considered an `OCKPatientStore`. +public protocol OCKPatientStore: OCKReadablePatientStore, OCKAnyPatientStore { + + /// `addPatients` asynchronously adds an array of patients to the store. + /// + /// - Parameters: + /// - patients: An array of patients to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addPatients(_ patients: [Patient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Patient]>?) + + /// `updatePatients` asynchronously updates an array of patients in the store. + /// + /// - Parameters: + /// - patients: An array of patients to be updated. The patients must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updatePatients(_ patients: [Patient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Patient]>?) + + /// `deletePatients` asynchronously deletes an array of patients from the store. + /// + /// - Parameters: + /// - patients: An array of patients to be deleted. The patients must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deletePatients(_ patients: [Patient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Patient]>?) + + // MARK: Implementation Provided + + /// `addPatient` asynchronously adds a patient to the store. + /// + /// - Parameters: + /// - patient: A patient to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addPatient(_ patient: Patient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updatePatient` asynchronously updates a patient in the store. + /// + /// - Parameters: + /// - patient: Apatients to be updated. The patient must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updatePatient(_ patient: Patient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deletePatient` asynchronously deletes a patient from the store. + /// + /// - Parameters: + /// - patient: A patient to be deleted. The patient must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deletePatient(_ patient: Patient, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKReadablePatientStore + +public extension OCKReadablePatientStore { + func fetchPatient(withID id: String, callbackQueue: DispatchQueue = .main, + completion: @escaping OCKResultClosure) { + var query = OCKPatientQuery(for: Date()) + query.limit = 1 + query.ids = [id] + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + + fetchPatients(query: PatientQuery(query), callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No patient with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKPatientStoreProtocol + +public extension OCKPatientStore { + + func addPatient(_ patient: Patient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addPatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add patient: \(patient)"))) + } + + func updatePatient(_ patient: Patient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updatePatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update patient: \(patient)"))) + } + + func deletePatient(_ patient: Patient, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deletePatients([patient], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete patient: \(patient)"))) + } +} + +// MARK: OCKAnyReadOnlyPatientStore implementations for OCKReadablePatientStore + +public extension OCKReadablePatientStore { + func fetchAnyPatients(query: OCKAnyPatientQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyPatient]>) { + let patientQuery = PatientQuery(query) + fetchPatients(query: patientQuery, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0 as OCKAnyPatient } }) } + } +} + +// MARK: OCKAnyPatientStore implementations for OCKPatientStoreProtocol + +public extension OCKPatientStore { + + func addAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) { + guard let patients = patients as? [Patient] else { + let message = "Failed to add patients. Not all patients were of the correct type: \(Patient.self)" + callbackQueue.async { completion?(.failure(.addFailed(reason: message))) } + return + } + addPatients(patients, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyPatient } }) } + } + + func updateAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) { + guard let patients = patients as? [Patient] else { + let message = "Failed to update patients. Not all patients were of the correct type: \(Patient.self)" + callbackQueue.async { completion?(.failure(.updateFailed(reason: message))) } + return + } + updatePatients(patients, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyPatient } }) } + } + + func deleteAnyPatients(_ patients: [OCKAnyPatient], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyPatient]>?) { + guard let patients = patients as? [Patient] else { + let message = "Failed to delete patients. Not all patients were of the correct type: \(Patient.self)" + callbackQueue.async { completion?(.failure(.deleteFailed(reason: message))) } + return + } + deletePatients(patients, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyPatient } }) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStoreDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStoreDelegate.swift new file mode 100755 index 0000000..1a21dfc --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Patients/OCKPatientStoreDelegate.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Types conforming to this protocol can receive callbacks from patient stores. +public protocol OCKPatientStoreDelegate: AnyObject { + + /// Called each time patients are added into the store. + /// - Parameter store: The store which was modified. + /// - Parameter patients: The patients that were added. + func patientStore(_ store: OCKAnyReadOnlyPatientStore, didAddPatients patients: [OCKAnyPatient]) + + /// Called each time patients are updated the store. + /// - Parameter store: The store which was modified. + /// - Parameter patients: The patients that were updated. + func patientStore(_ store: OCKAnyReadOnlyPatientStore, didUpdatePatients patients: [OCKAnyPatient]) + + /// Called each time patients are deleted from the store. + /// - Parameter store: The store which was modified. + /// - Parameter patients: The patients that were deleted. + func patientStore(_ store: OCKAnyReadOnlyPatientStore, didDeletePatients patients: [OCKAnyPatient]) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTask.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTask.swift new file mode 100755 index 0000000..e83c99a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTask.swift @@ -0,0 +1,72 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Conforming a type to `OCKAnyTask` allows it to be queried and displayed by CareKit. +public protocol OCKAnyTask { + + /// A user-defined unique identifier, typically human readable. + var id: String { get } + + /// A title that will be used to represent this care plan to the patient. + var title: String? { get } + + /// Instructions about how this task should be performed. + var instructions: String? { get } + + /// If true, completion of this task will be factored into the patient's overall adherence. True by default. + var impactsAdherence: Bool { get } + + /// A schedule that specifies how often this task occurs. + var schedule: OCKSchedule { get } + + /// A user-defined group identifer that can be used both for querying and sorting results. + /// Examples may include: "medications", "exercises", "family", "males", "diabetics", etc. + var groupIdentifier: String? { get } + + /// An identifier for this patient in a remote store. + var remoteID: String? { get } + + /// Any array of notes associated with this object. + var notes: [OCKNote]? { get } + + /// Determines if this task belongs to the given care plan. + /// + /// - Parameter plan: A care plan that may or may not own this task. + func belongs(to plan: OCKAnyCarePlan) -> Bool +} + +internal protocol OCKAnyMutableTask: OCKAnyTask { + var title: String? { get set } + var instructions: String? { get set } + var impactsAdherence: Bool { get set } + var schedule: OCKSchedule { get set } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTaskStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTaskStore.swift new file mode 100755 index 0000000..e8eefd4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyTaskStore.swift @@ -0,0 +1,146 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any store from which types conforming to `OCKAnyTask` can be queried is considered `OCKAnyReadOnlyTaskStore`. +public protocol OCKAnyReadOnlyTaskStore: AnyObject { + + /// The delegate receives callbacks when the contents of the care plan store are modified. + /// In `CareKit` apps, the delegate will be set automatically, and it should not be modified. + var taskDelegate: OCKTaskStoreDelegate? { get set } + + /// `fetchAnyTasks` asynchronously retrieves an array of tasks from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyTasks(query: OCKAnyTaskQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyTask]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchAnyTask` asynchronously retrieves an array of tasks from the store using its user-defined unique identifier. If a task with the + /// specified identifier is not found, the completion handler will be called with an error. + /// + /// - Parameters: + /// - id: A unique user-defined identifier + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchAnyTask(withID id: String, callbackQueue: DispatchQueue, + completion: @escaping (Result) -> Void) +} + +/// Any store able to write to one ore more types conforming to `OCKAnyTask` is considered an `OCKAnyTaskStore`. +public protocol OCKAnyTaskStore: OCKAnyReadOnlyTaskStore { + + /// `addAnyTasks` asynchronously adds an array of tasks to the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) + + /// `updateAnyTasks` asynchronously updates an array of tasks in the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be updated. The tasks must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) + + /// `deleteAnyTasks` asynchronously deletes an array of tasks from the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be deleted. The tasks must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) + + // MARK: Implementation Provided + + /// `addAnyTask` asynchronously adds a task to the store. + /// + /// - Parameters: + /// - task: A task to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue, completion: ((Result) -> Void)?) + + /// `updateAnyTask` asynchronously updates a task in the store. + /// + /// - Parameters: + /// - contact: A task to be updated. The task must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue, completion: ((Result) -> Void)?) + + /// `deleteTask` asynchronously deletes a task from the store. + /// + /// - Parameters: + /// - task: A task to be deleted. The task must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue, completion: ((Result) -> Void)?) +} + +// MARK: Singular Methods for OCKAnyReadOnlyTaskStore + +public extension OCKAnyReadOnlyTaskStore { + func fetchAnyTask(withID id: String, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure) { + var query = OCKTaskQuery(for: Date()) + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + query.limit = 1 + fetchAnyTasks(query: query, callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No task with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKAnyTaskStore + +public extension OCKAnyTaskStore { + func addAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addAnyTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add task \(task)"))) + } + + func updateAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateAnyTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update task: \(task)"))) + } + + func deleteAnyTask(_ task: OCKAnyTask, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteAnyTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete task: \(task)"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyVersionableTask.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyVersionableTask.swift new file mode 100755 index 0000000..e4cb669 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKAnyVersionableTask.swift @@ -0,0 +1,49 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any task that has a notion of versioning and is persisted in a database. +/// Conforming a store's task type to this protocol allows CareKit to provide +/// default implementations for `OCKReadOnlyEventStore` methods. +public protocol OCKAnyVersionableTask: OCKAnyTask { + + /// An identifier that uniquely identifies a specific version of the task in a database. + var localDatabaseID: OCKLocalVersionID? { get } + + /// An identifer that uniquely identifies the previous version of the task in a database. + var previousVersionID: OCKLocalVersionID? { get } + + /// An identifier that uniquely identifies the next version of the task in a database. + var nextVersionID: OCKLocalVersionID? { get } + + /// A date specifying when this version of the task begins taking effect. + var effectiveDate: Date { get } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStore.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStore.swift new file mode 100755 index 0000000..202c738 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStore.swift @@ -0,0 +1,183 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +import Foundation + +/// Any store from which a single type conforming to `OCKAnyTask` can be queried is considered a `OCKReadableTaskStore`. +public protocol OCKReadableTaskStore: OCKAnyReadOnlyTaskStore { + associatedtype Task: OCKAnyTask & Equatable & Identifiable + associatedtype TaskQuery: OCKAnyTaskQuery + + /// `fetchTasks` asynchronously retrieves an array of tasks from the store. + /// + /// - Parameters: + /// - query: A query used to constrain the values that will be fetched. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchTasks(query: TaskQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Task]>) + + // MARK: Singular Methods - Implementation Provided + + /// `fetchTask` asynchronously retrieves an array of tasks from the store using its user-defined unique identifier. If a task with the + /// specified identifier is not found, the completion handler will be called with an error. + /// + /// - Parameters: + /// - id: A unique user-defined identifier + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func fetchTask(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +} + +/// Any store that can perform read and write operations on a single type conforming to `OCKAnyTask` is considered an `OCKTaskStore`. +public protocol OCKTaskStore: OCKReadableTaskStore, OCKAnyTaskStore { + + /// `addTasks` asynchronously adds an array of tasks to the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) + + /// `updateTasks` asynchronously updates an array of tasks in the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be updated. The tasks must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) + + /// `deleteTasks` asynchronously deletes an array of tasks from the store. + /// + /// - Parameters: + /// - tasks: An array of tasks to be deleted. The tasks must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) + + // MARK: Implementation Provided + + /// `addTask` asynchronously adds a task to the store. + /// + /// - Parameters: + /// - task: A task to be added to the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func addTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `updateTask` asynchronously updates a task in the store. + /// + /// - Parameters: + /// - contact: A task to be updated. The task must already exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func updateTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) + + /// `deleteTask` asynchronously deletes a task from the store. + /// + /// - Parameters: + /// - task: A task to be deleted. The task must exist in the store. + /// - callbackQueue: The queue that the completion closure should be called on. In most cases this should be the main queue. + /// - completion: A callback that will fire on the provided callback queue. + func deleteTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +} + +// MARK: Singular Methods for OCKReadableTaskStore + +public extension OCKReadableTaskStore { + func fetchTask(withID id: String, callbackQueue: DispatchQueue = .main, completion: @escaping OCKResultClosure) { + var query = OCKTaskQuery(for: Date()) + query.extendedSortDescriptors = [.effectiveDate(ascending: true)] + query.ids = [id] + query.limit = 1 + + fetchTasks(query: TaskQuery(query), callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .fetchFailed(reason: "No task with ID: \(id)"))) + } +} + +// MARK: Singular Methods for OCKTaskStore + +public extension OCKTaskStore { + func addTask(_ task: Task, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + addTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .addFailed(reason: "Failed to add task \(task)"))) + } + + func updateTask(_ task: Task, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + updateTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .updateFailed(reason: "Failed to update task: \(task)"))) + } + + func deleteTask(_ task: Task, callbackQueue: DispatchQueue = .main, completion: OCKResultClosure? = nil) { + deleteTasks([task], callbackQueue: callbackQueue, completion: + chooseFirst(then: completion, replacementError: .deleteFailed(reason: "Failed to delete task: \(task)"))) + } +} + +// MARK: OCKAnyReadOnlyStore conformance for OCKReadableStore + +public extension OCKReadableTaskStore { + func fetchAnyTasks(query: OCKAnyTaskQuery, callbackQueue: DispatchQueue, + completion: @escaping OCKResultClosure<[OCKAnyTask]>) { + let taskQuery = TaskQuery(query) + fetchTasks(query: taskQuery, callbackQueue: callbackQueue) { completion($0.map { $0.map { $0 as OCKAnyTask } }) } + } +} + +// MARK: OCKAnyStore conformance for OCKTaskStore + +public extension OCKTaskStore { + func addAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) { + guard let tasks = tasks as? [Task] else { + let message = "Failed to add tasks. Not all tasks were of the correct type, \(Task.self)." + callbackQueue.async { completion?(.failure(.addFailed(reason: message))) } + return + } + addTasks(tasks, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyTask } }) } + } + + func updateAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) { + guard let tasks = tasks as? [Task] else { + let message = "Failed to update tasks. Not all tasks were of the correct type, \(Task.self)." + callbackQueue.async { completion?(.failure(.updateFailed(reason: message))) } + return + } + updateTasks(tasks, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyTask } }) } + } + + func deleteAnyTasks(_ tasks: [OCKAnyTask], callbackQueue: DispatchQueue, completion: OCKResultClosure<[OCKAnyTask]>?) { + guard let tasks = tasks as? [Task] else { + let message = "Failed to delete tasks. Not all tasks were of the correct type, \(Task.self)." + callbackQueue.async { completion?(.failure(.deleteFailed(reason: message))) } + return + } + deleteTasks(tasks, callbackQueue: callbackQueue) { completion?($0.map { $0.map { $0 as OCKAnyTask } }) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStoreDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStoreDelegate.swift new file mode 100755 index 0000000..28fe0de --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Protocols/Tasks/OCKTaskStoreDelegate.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Types conforming to this protocol can receive callbacks from task stores. +public protocol OCKTaskStoreDelegate: AnyObject { + + /// Called each time tasks are added to the store. + /// - Parameter store: The store which was modified. + /// - Parameter tasks: The tasks that were added to the store. + func taskStore(_ store: OCKAnyReadOnlyTaskStore, didAddTasks tasks: [OCKAnyTask]) + + /// Called each time tasks are updated in the store. + /// - Parameter store: The store which was modified. + /// - Parameter tasks: The tasks that were updated in the store. + func taskStore(_ store: OCKAnyReadOnlyTaskStore, didUpdateTasks tasks: [OCKAnyTask]) + + /// Called each time tasks are deleted from the store. + /// - Parameter store: The store which was modified. + /// - Parameter tasks: The tasks that were deleted from the store. + func taskStore(_ store: OCKAnyReadOnlyTaskStore, didDeleteTasks tasks: [OCKAnyTask]) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKAdherence.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKAdherence.swift new file mode 100755 index 0000000..ce176a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKAdherence.swift @@ -0,0 +1,43 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// `OCKAdherence` specifies how many of their assigned tasks a patient has completed. +public enum OCKAdherence: Equatable { + /// Indicates that there were no tasks scheduled anytime during the interval in which adherence was computed. + case noTasks + + /// Indicates that tasks were scheduled, but there were no events suring the interval in which adherence was computed. + case noEvents + + /// Inidates that events were found, and a fraction of them betwee 0 and 1 was completd. + case progress(Double) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKBiologicalSex.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKBiologicalSex.swift new file mode 100755 index 0000000..67d2961 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKBiologicalSex.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +private let maleStringRepresentation = "male" +private let femaleStringRepresentation = "female" + +/// Represents a person's biological sex. +public enum OCKBiologicalSex: RawRepresentable, Codable, Equatable { + case male + case female + case other(String) + + public var rawValue: String { + switch self { + case .male: return maleStringRepresentation + case .female: return femaleStringRepresentation + case .other(let value): return value + } + } + + public init?(rawValue: String) { + switch rawValue { + case maleStringRepresentation: self = .male + case femaleStringRepresentation: self = .female + default: self = .other(rawValue) + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let rawValue = try container.decode(String.self) + self = OCKBiologicalSex(rawValue: rawValue)! + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(rawValue) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKCarePlan.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKCarePlan.swift new file mode 100755 index 0000000..927a08f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKCarePlan.swift @@ -0,0 +1,84 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An `OCKCarePlan` represents a set of tasks, including both interventions and assesments, that a patient is supposed to complete as part of his +/// or her treatment for a specific condition. For example, a care plan for obesity may include tasks requiring the patient to exercise, record their +/// weight, and log meals. As the care plan evolves with the patient's progress, the care provider may modify the exercises and include notes each +/// time about why the changes were made. +public struct OCKCarePlan: Codable, Equatable, Identifiable, OCKAnyCarePlan, OCKVersionedObjectCompatible { + + /// The version id in the local database of the patient to whom this care plan belongs. + public var patientID: OCKLocalVersionID? + + // MARK: OCKAnyCarePlan + public let id: String + public var title: String + + // MARK: OCKVersionable + public var effectiveDate: Date + public internal(set) var deletedDate: Date? + public internal(set) var localDatabaseID: OCKLocalVersionID? + public internal(set) var nextVersionID: OCKLocalVersionID? + public internal(set) var previousVersionID: OCKLocalVersionID? + + // MARK: OCKObjectCompatible + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var groupIdentifier: String? + public var tags: [String]? + public var remoteID: String? + public var userInfo: [String: String]? + public var source: String? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Initialize a care plan with a title, id, and optional patient version. + /// + /// - Parameters: + /// - id: A user-defined id for the care plane. + /// - title: A title for the care plan. + /// - patientID: The version id in the local database of the patient to whom this care plan belongs. + public init(id: String, title: String, patientID: OCKLocalVersionID?) { + self.title = title + self.id = id + self.patientID = patientID + self.effectiveDate = Date() + self.timezone = TimeZone.current + } + + public func belongs(to patient: OCKAnyPatient) -> Bool { + guard let other = patient as? OCKPatient, let otherID = other.localDatabaseID else { return false } + return patientID == otherID + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKContact.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKContact.swift new file mode 100755 index 0000000..98ead25 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKContact.swift @@ -0,0 +1,108 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Contacts +import Foundation + +/// An `OCKContact` represents a contact that a user may want to get in touch with. A contact may be a care provider, a friend, or a family +/// member. Contacts must have at least a name, and may optionally have numerous other addresses at which to be contacted. +public struct OCKContact: Codable, Equatable, Identifiable, OCKAnyContact, OCKVersionedObjectCompatible { + + /// The version id in the local database for the care plan associated with this contact. + public var carePlanID: OCKLocalVersionID? + + // MARK: OCKAnyContact + public let id: String + public var name: PersonNameComponents + public var address: OCKPostalAddress? + public var emailAddresses: [OCKLabeledValue]? + public var messagingNumbers: [OCKLabeledValue]? + public var phoneNumbers: [OCKLabeledValue]? + public var otherContactInfo: [OCKLabeledValue]? + public var organization: String? + public var title: String? + public var role: String? + public var category: OCKContactCategory? + + // MARK: OCKVersionable + public var effectiveDate: Date + public internal(set) var deletedDate: Date? + public internal(set) var localDatabaseID: OCKLocalVersionID? + public internal(set) var nextVersionID: OCKLocalVersionID? + public internal(set) var previousVersionID: OCKLocalVersionID? + + // MARK: OCKObjectCompatible + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var groupIdentifier: String? + public var tags: [String]? + public var remoteID: String? + public var userInfo: [String: String]? + public var source: String? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Initialize a new `OCKContact` with a user-defined id, a name, and an optional care plan version ID. + /// + /// - Parameters: + /// - id: A user-defined id + /// - name: The contact's name + /// - carePlanID: The local database id of the careplan with which this contact is associated. + public init(id: String, name: PersonNameComponents, carePlanID: OCKLocalVersionID?) { + self.id = id + self.name = name + self.carePlanID = carePlanID + self.effectiveDate = Date() + self.timezone = TimeZone.current + } + + /// Initialize a new `OCKContact` with a user-defined id, a name, and an optional care plan version ID. + /// + /// - Parameters: + /// - id: A user-defined id + /// - name: The contact's name + /// - carePlanID: The local database id of the careplan with which this contact is associated. + public init(id: String, givenName: String, familyName: String, carePlanID: OCKLocalVersionID?) { + self.name = PersonNameComponents() + self.name.givenName = givenName + self.name.familyName = familyName + self.id = id + self.carePlanID = carePlanID + self.effectiveDate = Date() + self.timezone = TimeZone.current + } + + public func belongs(to plan: OCKAnyCarePlan) -> Bool { + guard let plan = plan as? OCKCarePlan, let planID = plan.localDatabaseID else { return false } + return carePlanID == planID + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKEvent.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKEvent.swift new file mode 100755 index 0000000..b7eca03 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKEvent.swift @@ -0,0 +1,62 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An `OCKEvent` represents a single occassion on which a task was scheduled to occur. It contains a copy of the task itself as well as the +/// schedule event and an outcome that will be non-nil if progress was made on the task. +public struct OCKEvent { + + /// A fully typed version of the task associated with this event. + public let task: Task + + /// A fully typed version of the outcome associated with this event. + public var outcome: Outcome? + + /// A value containing scheduling information for this event. + public let scheduleEvent: OCKScheduleEvent + + /// Initialize an `OCKEvent` with a task, optional outcome, and schedule event. + /// + /// - Parameters: + /// - task: The task associated with this event. + /// - outcome: The outcome associated with this event. + /// - scheduleEvent: The schedule event. + public init(task: Task, outcome: Outcome?, scheduleEvent: OCKScheduleEvent) { + self.task = task + self.outcome = outcome + self.scheduleEvent = scheduleEvent + } + + /// Creates an `OCKAnyEvent` from this event. + var anyEvent: OCKAnyEvent { + OCKAnyEvent(task: task, outcome: outcome, scheduleEvent: scheduleEvent) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKHealthKitLinkage.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKHealthKitLinkage.swift new file mode 100755 index 0000000..f6dcfdb --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKHealthKitLinkage.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import HealthKit + +extension HKQuantityTypeIdentifier: Codable {} + +/// Describes how a task outcome values should be retrieved from HealthKit. +internal struct OCKHealthKitLinkage: Equatable, Codable { + + internal enum QuantityType: String, Codable { + /// Quantities that are defined over a period of time, such as step count or calories burned. + case cumulative + + /// Quantities that are defined at a single point in time, such as heart rate or blood oxygen level. + case discrete + } + + /// A HealthKitQuantityIdentifier that describes the outcome's data type. + internal let quantityIdentifier: HKQuantityTypeIdentifier + + /// Determines what kind of query will be used to fetch data from HealthKit. + internal let quantityType: QuantityType + + /// A HealthKit unit that will be associated with outcomes saved to and fetched from HealthKit. + internal let unitString: String // Should map to an HKUnit + + /// Initialize by specifying HealthKit types. + /// + /// - Parameter quantityIdentifier: A HealthKitQuantityIdentifier that describes the outcome's data type. + /// - Parameter quantityType: Determines what kind of query will be used to fetch data from HealthKit. + /// - Parameter unit: A HealthKit unit that will be associated with outcomes saved to and fetched from HealthKit. + internal init(quantityIdentifier: HKQuantityTypeIdentifier, quantityType: QuantityType, unit: HKUnit) { + self.quantityIdentifier = quantityIdentifier + self.quantityType = quantityType + self.unitString = unit.unitString + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLabeledValue.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLabeledValue.swift new file mode 100755 index 0000000..064b7f1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLabeledValue.swift @@ -0,0 +1,54 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An optional label paired with a value used to represent contact information. +/// The label will typically indicate what kind of information the value carries. +public struct OCKLabeledValue: Codable, Equatable { + // Note: We cannot simply subclass `CNLabeledValue` the same we do with `CNMutablePostalAddress` because it is a generic class and not visible + // to @objc. Instead, we use this struct and convert to and from `CNLabeledValue` when required. This is all to get `Codable`. + + /// A description of what the label is, i.e. "Home Email", "Office Phone" + public var label: String + + /// The actual contact information, i.e. a phone number or email address. + public var value: String + + /// Initialize with an optional label and a value. + /// + /// - Parameters: + /// - label: A description of what the label is, i.e. "Home Email", "Office Phone" + /// - value: The actual contact information, i.e. a phone number or email address. + public init(label: String, value: String) { + self.label = label + self.value = value + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLocalVersionID.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLocalVersionID.swift new file mode 100755 index 0000000..1dbb6f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKLocalVersionID.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public struct OCKLocalVersionID: Equatable, Comparable, Hashable, Codable, CustomStringConvertible { + public static func < (lhs: OCKLocalVersionID, rhs: OCKLocalVersionID) -> Bool { + return lhs.stringValue < rhs.stringValue + } + + public var description: String { + return stringValue + } + + public let stringValue: String + + public init(_ id: String) { + self.stringValue = id + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKNote.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKNote.swift new file mode 100755 index 0000000..0af03fe --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKNote.swift @@ -0,0 +1,72 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// `OCKNote` can be attached to all other CareKit objects and values. Use cases may include a physician leaving a note on a task when it is modified +/// to explain why a medication dose was changed, or a note left from a patient to a care provider explaining why they weren't able to complete a +/// task on a certain occassion. +public struct OCKNote: Codable, Equatable, OCKObjectCompatible { + /// The person who created the note. + public var author: String? + + /// A title for the note. + public var title: String? + + /// The note content. + public var content: String? + + // MARK: OCKObjectCompatible + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public internal (set) var localDatabaseID: OCKLocalVersionID? + public var groupIdentifier: String? + public var tags: [String]? + public var remoteID: String? + public var userInfo: [String: String]? + public var source: String? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Initialize a new note with an optional author, title, and content. + /// + /// - Parameters: + /// - author: The person who created the note. + /// - title: The title of the note. + /// - content: The note's text content. + public init(author: String?, title: String?, content: String?) { + self.author = author + self.title = title + self.content = content + self.timezone = TimeZone.current + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcome.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcome.swift new file mode 100755 index 0000000..4c27cc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcome.swift @@ -0,0 +1,77 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An `OCKOutcome` represents the outcome of an event corresponding to a task. An outcome may have 0 or more values associated with it. +/// For example, a task that asks a patient to measure their temperature will have events whose outcome will contain a single value representing +/// the patient's tempature. +public struct OCKOutcome: Codable, Equatable, Identifiable, OCKAnyOutcome, OCKObjectCompatible { + + /// The version ID of the task to which this outcomes belongs. + public var taskID: OCKLocalVersionID + + // MARK: OCKAnyOutcome + public var id: String { taskID.stringValue + "_\(taskOccurrenceIndex)" } + public var taskOccurrenceIndex: Int + public var values: [OCKOutcomeValue] + + // MARK: OCKObjectCompatible + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public internal(set) var localDatabaseID: OCKLocalVersionID? + public var remoteID: String? + public var groupIdentifier: String? + public var tags: [String]? + public var source: String? + public var userInfo: [String: String]? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Initialize by specifying the version of the task that owns this outcome, how many events have occured before this outcome, and the values. + /// + /// - Parameters: + /// - taskID: The version ID of the task that owns this outcome. This ID can be retrieved from any task that has been queried from the store. + /// - taskOccurrenceIndex: The number of events that occurred before the event this outcome corresponds to. + /// - values: An array outcome values. + public init(taskID: OCKLocalVersionID, taskOccurrenceIndex: Int, values: [OCKOutcomeValue]) { + self.taskID = taskID + self.taskOccurrenceIndex = taskOccurrenceIndex + self.values = values + self.timezone = TimeZone.current + } + + public func belongs(to task: OCKAnyTask) -> Bool { + guard let task = task as? OCKTask else { return false } + return task.localDatabaseID == taskID + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcomeValue.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcomeValue.swift new file mode 100755 index 0000000..3056910 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKOutcomeValue.swift @@ -0,0 +1,230 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Any value that can be persisted to `OCKStore` must conform to this protocol. +public protocol OCKOutcomeValueUnderlyingType: Codable {} + +extension Int: OCKOutcomeValueUnderlyingType {} +extension Double: OCKOutcomeValueUnderlyingType {} +extension Bool: OCKOutcomeValueUnderlyingType {} +extension String: OCKOutcomeValueUnderlyingType {} +extension Data: OCKOutcomeValueUnderlyingType {} +extension Date: OCKOutcomeValueUnderlyingType {} + +/// An enumerator specifying the types of values that can be saved to an `OCKStore`. +public enum OCKOutcomeValueType: String, Codable { + case integer + case double + case boolean + case text + case binary + case date +} + +/// An `OCKOutcomeValue` is a representation of any response of measurement that a user gives in response to a task. The underlying type could be +/// any of a number of types including integers, booleans, dates, text, and binary data, among others. +public struct OCKOutcomeValue: Codable, Equatable, OCKObjectCompatible, CustomStringConvertible { + // MARK: Codable + enum CodingKeys: CodingKey, CaseIterable { + case + kind, units, localDatabaseID, value, type, index, + createdDate, updatedDate, schemaVersion, tags, group, remoteID, userInfo, source, timezone // OCKObjectCompatible + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let valueType = try container.decode(OCKOutcomeValueType.self, forKey: CodingKeys.type) + + switch valueType { + case .integer: + value = try container.decode(Int.self, forKey: CodingKeys.value) + case .double: + value = try container.decode(Double.self, forKey: CodingKeys.value) + case .boolean: + value = try container.decode(Bool.self, forKey: CodingKeys.value) + case .text: + value = try container.decode(String.self, forKey: CodingKeys.value) + case .binary: + value = try container.decode(Data.self, forKey: CodingKeys.value) + case .date: + value = try container.decode(Date.self, forKey: CodingKeys.value) + } + + kind = try container.decode(String?.self, forKey: CodingKeys.kind) + units = try container.decode(String?.self, forKey: CodingKeys.units) + index = try container.decode(Int?.self, forKey: CodingKeys.index) + localDatabaseID = try container.decode(OCKLocalVersionID?.self, forKey: CodingKeys.localDatabaseID) + createdDate = try container.decode(Date?.self, forKey: CodingKeys.createdDate) + updatedDate = try container.decode(Date?.self, forKey: CodingKeys.updatedDate) + schemaVersion = try container.decode(OCKSemanticVersion?.self, forKey: CodingKeys.schemaVersion) + groupIdentifier = try container.decode(String?.self, forKey: CodingKeys.group) + tags = try container.decode([String]?.self, forKey: CodingKeys.tags) + remoteID = try container.decode(String?.self, forKey: CodingKeys.remoteID) + source = try container.decode(String?.self, forKey: CodingKeys.source) + userInfo = try container.decode([String: String]?.self, forKey: CodingKeys.userInfo) + timezone = try container.decode(TimeZone.self, forKey: CodingKeys.timezone) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(type, forKey: .type) + try container.encode(kind, forKey: .kind) + try container.encode(units, forKey: .units) + try container.encode(index, forKey: .index) + try container.encode(localDatabaseID, forKey: .localDatabaseID) + + var encodedValue = false + if let value = integerValue { try container.encode(value, forKey: .value); encodedValue = true } else + if let value = doubleValue { try container.encode(value, forKey: .value); encodedValue = true } else + if let value = stringValue { try container.encode(value, forKey: .value); encodedValue = true } else + if let value = booleanValue { try container.encode(value, forKey: .value); encodedValue = true } else + if let value = dataValue { try container.encode(value, forKey: .value); encodedValue = true } else + if let value = dateValue { try container.encode(value, forKey: .value); encodedValue = true } + + guard encodedValue else { + let message = "Value could not be converted to a concrete type." + throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [CodingKeys.value], debugDescription: message)) + } + + try container.encode(updatedDate, forKey: .updatedDate) + try container.encode(createdDate, forKey: .createdDate) + try container.encode(schemaVersion, forKey: .schemaVersion) + try container.encode(groupIdentifier, forKey: .group) + try container.encode(tags, forKey: .tags) + try container.encode(remoteID, forKey: .remoteID) + try container.encode(source, forKey: .source) + try container.encode(userInfo, forKey: .userInfo) + try container.encode(timezone, forKey: .timezone) + } + + public var description: String { + switch type { + case .integer: return "\(value as! Int)" + case .double: return "\(value as! Double)" + case .boolean: return "\(value as! Bool)" + case .text: return "\(value as! String)" + case .binary: return "\(value as! Data)" + case .date: return "\(value as! Date)" + } + } + + /// An optional property that can be used to specify what kind of value this is (e.g. blood pressure, qualatative stress, weight) + public var kind: String? + + /// The units for this measurement. + public var units: String? + + /// The underlying value. + public var value: OCKOutcomeValueUnderlyingType + + /// The underlying value as an integer. + public var integerValue: Int? { return value as? Int } + + /// The underlying value as a floating point number. + public var doubleValue: Double? { return value as? Double } + + /// The underlying value as a boolean. + public var booleanValue: Bool? { return value as? Bool } + + /// The underlying value as text. + public var stringValue: String? { return value as? String } + + /// The underlying value as binary data. + public var dataValue: Data? { return value as? Data } + + /// The underlying value as a date. + public var dateValue: Date? { return value as? Date } + + /// The index can be used to track the order or arrangement of outcomes values, when relevant. + public var index: Int? + + // MARK: OCKObjectCompatible + public internal(set) var localDatabaseID: OCKLocalVersionID? + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var groupIdentifier: String? + public var tags: [String]? + public var remoteID: String? + public var source: String? + public var userInfo: [String: String]? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Holds information about the type of this value. + public var type: OCKOutcomeValueType { + if value is Int { return .integer } + if value is Double { return .double } + if value is Bool { return .boolean } + if value is String { return .text } + if value is Data { return .binary } + if value is Date { return .date } + fatalError("Unknown type!") + } + + /// Initialize by specifying a value and an optional unit + public init(_ value: OCKOutcomeValueUnderlyingType, units: String? = nil) { + self.value = value + self.units = units + self.timezone = TimeZone.current + } + + public static func == (lhs: OCKOutcomeValue, rhs: OCKOutcomeValue) -> Bool { + lhs.hasSameValueAs(rhs) && + lhs.type == rhs.type && + lhs.localDatabaseID == rhs.localDatabaseID && + lhs.remoteID == rhs.remoteID && + lhs.userInfo == rhs.userInfo && + lhs.asset == rhs.asset && + lhs.kind == rhs.kind && + lhs.index == rhs.index && + lhs.timezone == rhs.timezone && + lhs.notes == rhs.notes && + lhs.groupIdentifier == rhs.groupIdentifier && + lhs.tags == rhs.tags && + lhs.source == rhs.source + } + + /// Checks if two `OCKOutcomeValue`s have equal value properties, without checking their other properties. + func hasSameValueAs(_ other: OCKOutcomeValue) -> Bool { + switch type { + case .binary: return dataValue == other.dataValue + case .boolean: return booleanValue == other.booleanValue + case .date: return dateValue == other.dateValue + case .double: return doubleValue == other.doubleValue + case .integer: return integerValue == other.integerValue + case .text: return stringValue == other.stringValue + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPatient.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPatient.swift new file mode 100755 index 0000000..d30065d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPatient.swift @@ -0,0 +1,96 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Represents a patient +public struct OCKPatient: Codable, Equatable, Identifiable, OCKAnyPatient, OCKVersionedObjectCompatible { + + // MARK: OCKAnyPatient + public let id: String + public var name: PersonNameComponents + public var sex: OCKBiologicalSex? + public var birthday: Date? + public var allergies: [String]? + + // MARK: OCKVersionedObjectCompatible + public var effectiveDate: Date + public internal(set) var deletedDate: Date? + public internal(set) var nextVersionID: OCKLocalVersionID? + public internal(set) var previousVersionID: OCKLocalVersionID? + + // MARK: OCKObjectCompatible + public internal(set) var localDatabaseID: OCKLocalVersionID? + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var groupIdentifier: String? + public var tags: [String]? + public var remoteID: String? + public var source: String? + public var userInfo: [String: String]? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Initialize a patient with an id, a first name, and a last name. + /// + /// - Parameters: + /// - id: A user-defined id unique to this patient. + /// - givenName: The patient's given name. + /// - familyName: The patient's family name. + public init(id: String, givenName: String, familyName: String) { + var components = PersonNameComponents() + components.givenName = givenName + components.familyName = familyName + self.name = components + self.id = id + self.effectiveDate = Date() + self.timezone = TimeZone.current + } + + /// Initialize a new patient with an id and a name. + /// + /// - Parameters: + /// - id: A user-defined id unique to this patient. + /// - name: The name components for the patient's name. + public init(id: String, name: PersonNameComponents) { + self.name = name + self.id = id + self.effectiveDate = Date() + self.timezone = TimeZone.current + } + + /// The patient's age in years, as of the current date. + public var age: Int? { + guard let birthday = birthday else { return nil } + return Calendar.current.dateComponents(Set([.year]), from: birthday, to: Date()).year + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPostalAddress.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPostalAddress.swift new file mode 100755 index 0000000..3a44a83 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKPostalAddress.swift @@ -0,0 +1,34 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Contacts + +/// A `Codable` subclass of `CNMutablePostalAddress`. +@objc // We subclass for sole purpose of adding conformance to Codable. +public class OCKPostalAddress: CNMutablePostalAddress, Codable {} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSchedule.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSchedule.swift new file mode 100755 index 0000000..37e3e22 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSchedule.swift @@ -0,0 +1,168 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An implementation of `OCKSchedulable` that can be created by composing together any number of other +/// `OCKSchedulable` objects, including other instance of `OCKSchedule`. This allows for the creation +/// of arbitrarily complex schedules. +/// +/// - Note: A variety of initializers are provided to quickly create commonly used schedules. Used in +/// combination with the offset method, building up complex schedules can be performed quite +/// efficiently. +public struct OCKSchedule: Codable, Equatable { + + /// The constituent components this schedule was built from. + public let elements: [OCKScheduleElement] + + /// Create a new schedule by combining an array of other `OCKSchedule` objects. + public init(composing schedules: [OCKSchedule]) { + assert(!schedules.isEmpty, "You cannot create a schedule with 0 elements") + self.elements = schedules.flatMap { $0.elements } + } + + /// Create a new schedule by combining an array of other `OCKSchedule` objects. + public init(composing elements: [OCKScheduleElement]) { + assert(!elements.isEmpty, "You cannot create a schedule with 0 elements") + self.elements = elements.flatMap { $0.elements } + } + + /// Returns the Nth event of this schedule. + /// + /// - Parameter occurrence: The Nth occurrence. + public subscript(occurrence: Int) -> OCKScheduleEvent { + return event(forOccurrenceIndex: occurrence)! + } + + /// The date of the first event of this schedule. + /// + /// - Note: This operation has an upperbound complexity of O(NlogN). + public func startDate() -> Date { + guard let earliestStartDate = elements.map({ $0.start }).sorted().min() + else { fatalError("OCKSchedule should always have at least 1 element!") } + return earliestStartDate + } + + /// The date of the last event of this schedule, or nil if the schedule is of infinite length. + /// + /// - Note: This operation has an upperbound complexity of O(NlogN) + public func endDate() -> Date? { + let endDates = elements.map { $0.end } + if endDates.contains(nil) { return nil } + let finiteEndDates = endDates.compactMap({ $0 }).sorted() + guard let lastEndDate = finiteEndDates.last else { fatalError("OCKSchedule should always have at least 1 element!") } + return lastEndDate + } + + /// Computes an array of events between two dates. + /// The lower bound is inclusive and the upper bound is exclusive. + /// + /// - Parameters: + /// - start: The earliest date at which an event could be returned. Inclusive. + /// - end: The latest date at which an event could be returned. Exclusive. + public func events(from start: Date, to end: Date) -> [OCKScheduleEvent] { + var allEvents = elements + .flatMap { $0.events(from: self.startDate(), to: end) } + .sorted() + for index in 0..= Calendar.current.startOfDay(for: start) + } + return event.start + event.element.duration.seconds >= start + } + } + + /// Create a new schedule by shifting this schedule. + /// + /// - Parameter dateComponents: The amount of time to offset this schedule by. + /// - Returns: A new instance of with all event times offset by the given value. + public func offset(by dateComponents: DateComponents) -> OCKSchedule { + return OCKSchedule(composing: elements.compactMap { $0.offset(by: dateComponents) }) + } + + /// Create a schedule that happens once per day, every day, at a fixed time. + public static func dailyAtTime(hour: Int, minutes: Int, start: Date, end: Date?, + text: String?, duration: OCKScheduleElement.Duration = .hours(1), + targetValues: [OCKOutcomeValue] = []) -> OCKSchedule { + let interval = DateComponents(day: 1) + let startTime = Calendar.current.date(bySettingHour: hour, minute: minutes, second: 0, of: start)! + let element = OCKScheduleElement(start: startTime, end: end, interval: interval, + text: text, targetValues: targetValues, duration: duration) + return OCKSchedule(composing: [element]) + } + + /// Create a schedule that happens once per week, every week, at a fixed time. + public static func weeklyAtTime(weekday: Int, hours: Int, minutes: Int, start: Date, end: Date?, targetValues: [OCKOutcomeValue], + text: String?, duration: OCKScheduleElement.Duration = .hours(1)) -> OCKSchedule { + let interval = DateComponents(weekOfYear: 1) + var startTime = Calendar.current.date(bySettingHour: hours, minute: minutes, second: 0, of: start)! + startTime = Calendar.current.date(bySetting: .weekday, value: weekday, of: startTime)! + let element = OCKScheduleElement(start: startTime, end: end, interval: interval, + text: text, targetValues: targetValues, duration: duration) + return OCKSchedule(composing: [element]) + } + + /// Computes the date of the Nth occurrence of a schedule element. If the Nth occurrence is beyond the end date, then nil will be returned. + public func event(forOccurrenceIndex occurrence: Int) -> OCKScheduleEvent? { + // This could be optimized. It is not an efficient algorithm. + assert(occurrence >= 0, "Schedule events cannot have negative occurrence indices") + let events = elements.flatMap { $0.events(betweenOccurrenceIndex: 0, and: occurrence + 1) } + let sortedEvents = events.sorted { eventA, eventB -> Bool in + if let eventA = eventA, let eventB = eventB { + return eventA < eventB + } else { + return eventA != nil && eventB == nil + } + } + guard let localEvent = sortedEvents[occurrence] else { return nil } + let globalEvent = OCKScheduleEvent(start: localEvent.start, end: localEvent.end, + element: localEvent.element, occurrence: occurrence) + return globalEvent + } + + func exists(onDay date: Date) -> Bool { + let firstMomentOfTheDay = Calendar.current.startOfDay(for: date) + let lastMomentOfTheDay = Calendar.current.date(byAdding: DateComponents(day: 1, second: -1), to: firstMomentOfTheDay)! + + // If there is no end date, we just have to check that it starts before the end of the given day. + guard let end = endDate() else { + return startDate() <= lastMomentOfTheDay + } + + // If there is an end date, the we need to ensure that it has already started, and hasn't ended yet. + let startedOnTime = startDate() < lastMomentOfTheDay + let didntEndTooEarly = end > firstMomentOfTheDay + + return startedOnTime && didntEndTooEarly + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleElement.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleElement.swift new file mode 100755 index 0000000..a793e12 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleElement.swift @@ -0,0 +1,252 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// The simplest possible `OCKSchedulable`, representing a single event that repeats at +/// fixed intervals. It may have fixed duration or repeat indefinitely. +public struct OCKScheduleElement: Codable, Equatable, OCKObjectCompatible { + + // Disabled because nested types are an internal implementation detail. + + /// A duration describing the length of an event. Options include all day, or a deterministic number of hours, minutes, or seconds. + public enum Duration: Codable, Equatable { + /// Describes an duration that fills an entire date + case allDay + + /// Describes a fixed duration in seconds + case seconds(Double) + + /// Creates a duration that represents a given number of hours. + public static func hours(_ hours: Double) -> Duration { + .seconds(60 * 60 * hours) + } + + /// Creates a duration that represents a given number of minutes. + public static func minutes(_ minutes: Double) -> Duration { + .seconds(60 * minutes) + } + + private enum CodingKeys: CodingKey { + case isAllDay + case seconds + } + + var seconds: TimeInterval { + switch self { + case .allDay: return 0 + case .seconds(let seconds): return seconds + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self == .allDay, forKey: .isAllDay) + if case .seconds(let seconds) = self { + try container.encode(seconds, forKey: .seconds) + } + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if try container.decodeIfPresent(Bool.self, forKey: .isAllDay) == true { + self = .allDay + } + if let seconds = try container.decodeIfPresent(Double.self, forKey: .seconds) { + self = .seconds(seconds) + } + throw DecodingError.dataCorruptedError(forKey: CodingKeys.seconds, in: container, debugDescription: "No seconds or allDay key was found!") + } + } + + /// An text about the time this element represents. + /// e.g. before breakfast on Tuesdays, 5PM every day, etc. + public var text: String? + + /// The amount of time that the event should take, in seconds. + public var duration: Duration + + /// The date and time the first event occurs. + // Note: This must remain a constant because its value is modified by the `isAllDay` flag during initialization. + public let start: Date + + /// The latest possible time for an event to occur. + /// - Note: Depending on the interval chosen, it is not guaranteed that an event + /// will fall on this date. + /// - Note: If no date is provided, the schedule will repeat indefinitely. + public var end: Date? + + /// The amount of time between events specified using `DateCoponents`. + /// - Note: `DateComponents` are chose over `TimeInterval` to account for edge + /// edge cases like daylight savings time and leap years. + public var interval: DateComponents + + /// An array of values that specify what values the user is expected to record. + /// For example, for a medcation, it may be the dose that the patient is expected to take. + public var targetValues: [OCKOutcomeValue] + + // MARK: OCKObjectCompatible + internal var localDatabaseID: OCKLocalVersionID? + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var groupIdentifier: String? + public var tags: [String]? + public var versionID: OCKLocalVersionID? + public var remoteID: String? + public var source: String? + public var userInfo: [String: String]? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Create a `ScheduleElement` by specying the start date, end date, and interval. + /// + /// - Parameters: + /// - start: Date specifying the exact day and time that the first occurrence of this task happens. + /// - end: Date specifying when the task ends. The end date is not inclusive. + /// - interval: DateComponents specifying the frequency at which the schedule repeats. + /// - text: A textual representation of this schedule element. Examples: "After breakfast", "08:00", "As needed throughout the day". + /// - targetValues: An array of values that represents goals for this schedule element. + /// - duration: A duration in seconds specifying how long the window to complete this event is. + public init(start: Date, end: Date?, interval: DateComponents, text: String? = nil, + targetValues: [OCKOutcomeValue] = [], duration: Duration = .hours(0)) { + assert(end == nil || start < end!, "Start date must be before the end date!") + assert(interval.movesForwardInTime, "Interval must not progress backwards in time!") + + self.start = duration == .allDay ? Calendar.current.startOfDay(for: start) : start + self.end = end + self.interval = interval + self.text = text + self.duration = duration + self.targetValues = targetValues + self.timezone = TimeZone.current + } + + /// Returns the Nth event of this schedule. + /// + /// - Parameter occurrence: The Nth occurrence. + public subscript(occurrence: Int) -> OCKScheduleEvent { + makeScheduleEvent(on: date(ofOccurrence: occurrence)!, for: occurrence) + } + + public var elements: [OCKScheduleElement] { + return [self] + } + + /// - Returns: a new instance of with all event times offset by the given value. + public func offset(by dateComponents: DateComponents) -> OCKScheduleElement { + let newStart = Calendar.current.date(byAdding: dateComponents, to: start)! + let newEnd = end == nil ? nil : Calendar.current.date(byAdding: dateComponents, to: end!)! + return OCKScheduleElement(start: newStart, end: newEnd, interval: interval, + text: text, targetValues: targetValues, duration: duration) + } + + /// - Returns: An array containing either an schedule event or nil + /// - Remark: Lower bound is inclusive, upper bound is exclusive. + public func events(betweenOccurrenceIndex startIndex: Int, and stopIndex: Int) -> [OCKScheduleEvent?] { + assert(stopIndex > startIndex, "Stop index must be greater than or equal to start index") + let numberOfEvents = stopIndex - startIndex + var currentOccurrence = 0 + var events = [OCKScheduleEvent?](repeating: nil, count: numberOfEvents) + + // Move to start index + var currentDate = start + for _ in 0.. endDate { continue } + events[index] = makeScheduleEvent(on: currentDate, for: currentOccurrence) + currentDate = Calendar.current.date(byAdding: interval, to: currentDate)! + currentOccurrence += 1 + } + return events + } + + public func events(from start: Date, to end: Date) -> [OCKScheduleEvent] { + let stopDate = determineStopDate(onOrBefore: end) + var current = self.start + var dates = [Date]() + while current < stopDate { + dates.append(current) + current = Calendar.current.date(byAdding: interval, to: current)! + } + let events = dates.enumerated().map { index, date in makeScheduleEvent(on: date, for: index) } + return events.filter { event in + if duration == .allDay { return true } + return event.start + duration.seconds >= start + } + } + + /// Computes the date of the Nth occurrence of a schedule element. If the Nth occurrence is beyond the end date, then nil will be returned. + public func date(ofOccurrence occurrence: Int) -> Date? { + assert(occurrence >= 0, "Schedule events cannot have negative occurrence indices") + var currentDate = start + for _ in 0.. Date { + if duration == .allDay { + let stopDay = end ?? date + let morningOfStopDay = Calendar.current.startOfDay(for: stopDay) + let endOfStopDay = Calendar.current.date(byAdding: .init(day: 1, second: -1), to: morningOfStopDay)! + return endOfStopDay + } + + guard let endDate = end else { return date } + return min(endDate, date) + } + + private func makeScheduleEvent(on date: Date, for occurrence: Int) -> OCKScheduleEvent { + let startDate = duration == .allDay ? Calendar.current.startOfDay(for: date) : date + let endDate = duration == .allDay ? + Calendar.current.date(byAdding: DateComponents(day: 1, second: -1), to: startDate)! : + startDate.addingTimeInterval(duration.seconds) + return OCKScheduleEvent(start: startDate, end: endDate, element: self, occurrence: occurrence) + } +} + +private extension DateComponents { + var movesForwardInTime: Bool { + let now = Date() + let then = Calendar.current.date(byAdding: self, to: now)! + return then > now + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleEvent.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleEvent.swift new file mode 100755 index 0000000..7a7e665 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKScheduleEvent.swift @@ -0,0 +1,53 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +public struct OCKScheduleEvent: Equatable, Comparable { + public let start: Date + public let end: Date + public let element: OCKScheduleElement + public let occurrence: Int + + public static func < (lhs: OCKScheduleEvent, rhs: OCKScheduleEvent) -> Bool { + return lhs.start < rhs.start + } + + internal init(start: Date, end: Date, element: OCKScheduleElement, occurrence: Int) { + self.start = start + self.end = end + self.element = element + self.occurrence = occurrence + } + + internal func changing(occurrenceIndex index: Int) -> OCKScheduleEvent { + return OCKScheduleEvent(start: start, end: end, element: element, occurrence: index) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSemanticVersion.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSemanticVersion.swift new file mode 100755 index 0000000..cec2231 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKSemanticVersion.swift @@ -0,0 +1,113 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A semantic version with major, minor, and patch version numbers. Semantic versions parsed from strings and compared. +public struct OCKSemanticVersion: Codable, Equatable, Comparable, LosslessStringConvertible { + + /// The major version number, i.e. the *3* in 3.11.2. + public let majorVersion: Int + + /// The minor version number, i.e. the *11* in 3.11.2. + public let minorVersion: Int + + /// The patch number, i.e. the *2* in 3.11.2. + public let patchNumber: Int + + /// The errors that could occur while atttempting to parse a string into an `OCKSemanticVersion`. + public enum ParsingError: Error { + case emptyString + case tooManySeparators + case invalidMajorVersion + case invalidMinorVersion + case invalidPatchVersion + } + + /// Initialize by specifying the major, minor, and patch versions. + public init(majorVersion: Int, minorVersion: Int = 0, patchNumber: Int = 0) { + self.majorVersion = majorVersion + self.minorVersion = minorVersion + self.patchNumber = patchNumber + } + + /// Initialize from a string description of the semantic version. This init will fail and return nil if the provided string is + /// not a valid semantic version. + public init?(_ description: String) { + do { + self = try OCKSemanticVersion.parse(description) + } catch { + return nil + } + } + + public var description: String { "\(majorVersion).\(minorVersion).\(patchNumber)" } + + public static func < (lhs: OCKSemanticVersion, rhs: OCKSemanticVersion) -> Bool { + // Major versions are unequal + if lhs.majorVersion < rhs.majorVersion { return true } + if lhs.majorVersion > rhs.majorVersion { return false } + + // Major versions are equal, minor versions are unequal + if lhs.minorVersion < rhs.minorVersion { return true } + if lhs.minorVersion > rhs.minorVersion { return false } + + // Major and minor versions are equal, patch numbers are unequal + if lhs.patchNumber < rhs.patchNumber { return true } + if lhs.patchNumber > rhs.patchNumber { return false } + + // Major, minor, and patch numbers all match + return false + } + + /// Parses a string into an `OCKSemanticVersion`. Throws if an error occurs. + /// - Parameter versionString: A string representing the semantic version, e.g. "3.11.2" + public static func parse(_ versionString: String) throws -> OCKSemanticVersion { + guard !versionString.isEmpty else { throw ParsingError.emptyString } + let parts = versionString.split(separator: ".").map { Int($0) } + guard parts.count <= 3 else { throw ParsingError.tooManySeparators } + + guard let major = parts[0] else { throw ParsingError.invalidMajorVersion } + + let minor: Int = try { + guard parts.count > 1 else { return 0 } + guard let minor = parts[1] else { throw ParsingError.invalidMinorVersion } + return minor + }() + + let patch: Int = try { + guard parts.count > 2 else { return 0 } + guard let patch = parts[2] else { throw ParsingError.invalidPatchVersion } + return patch + }() + + return OCKSemanticVersion(majorVersion: major, minorVersion: minor, patchNumber: patch) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKStoreConfiguration.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKStoreConfiguration.swift new file mode 100755 index 0000000..f1b8699 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKStoreConfiguration.swift @@ -0,0 +1,41 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/// Specifies options that can be applied to an `OCKStore`. +public struct OCKStoreConfiguration: Equatable { + + /// True by default. Setting to false will enforce that all database entities have the expected relationships. + /// Specifically, it will cause errors to be throw if any care plan's patient is not specified, and task's care + /// plan is not specified, any contact's care plan is not specified, or any outcome's task is not specified. + public var allowsEntitiesWithMissingRelationships = true + + /// Initialize a new `OCKStoreConfiguration` with default parameters. + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKTask.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKTask.swift new file mode 100755 index 0000000..877dc53 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/OCKTask.swift @@ -0,0 +1,88 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// An `OCKTask` represents some task or action that a patient is supposed to perform. Tasks are optionally associable with an `OCKCarePlan` +/// and must have a unique id and schedule. The schedule determines when and how often the task should be performed, and the +/// `impactsAdherence` flag may be used to specify whether or not the patients adherence to this task will affect their daily completion rings. +public struct OCKTask: Codable, Equatable, Identifiable, OCKAnyVersionableTask, OCKAnyMutableTask, OCKVersionedObjectCompatible { + + /// The version ID in the local database of the care plan to which this task belongs. + public var carePlanID: OCKLocalVersionID? + + // MARK: OCKAnyTask + public let id: String + public var title: String? + public var instructions: String? + public var impactsAdherence = true + public var schedule: OCKSchedule + public var groupIdentifier: String? + public var tags: [String]? + + // MARK: OCKVersionable + public var effectiveDate: Date + public internal(set) var deletedDate: Date? + public internal(set) var localDatabaseID: OCKLocalVersionID? + public internal(set) var nextVersionID: OCKLocalVersionID? + public internal(set) var previousVersionID: OCKLocalVersionID? + + // MARK: OCKObjectCompatible + public internal(set) var createdDate: Date? + public internal(set) var updatedDate: Date? + public internal(set) var schemaVersion: OCKSemanticVersion? + public var remoteID: String? + public var source: String? + public var userInfo: [String: String]? + public var asset: String? + public var notes: [OCKNote]? + public var timezone: TimeZone + + /// Instantiate a new `OCKCarePlan` + /// + /// - Parameters: + /// - id: A unique id for this care plan chosen by the developer. + /// - title: A title that will be used to represent this care plan to the patient. + /// - carePlanID: The versioned ID in the local database of the care plan that this task belongs to. + /// - schedule: A schedule specifying when this task is to be completed. + public init(id: String, title: String?, carePlanID: OCKLocalVersionID?, schedule: OCKSchedule) { + self.id = id + self.title = title + self.carePlanID = carePlanID + self.schedule = schedule + self.effectiveDate = schedule.startDate() + self.timezone = TimeZone.current + } + + public func belongs(to plan: OCKAnyCarePlan) -> Bool { + guard let plan = plan as? OCKCarePlan, let planID = plan.localDatabaseID else { return false } + return carePlanID == planID + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKAdherenceQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKAdherenceQuery.swift new file mode 100755 index 0000000..78330ae --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKAdherenceQuery.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// `OCKAdherenceQuery` is used to constrain the results returned when fetching adherence from a store. +public struct OCKAdherenceQuery { + + /// The IDs of the tasks for which adherence should be calculated. + public var taskIDs: [String] + + /// The date interval for which to return adherence information. + public var dateInterval: DateInterval + + /// An aggregator used to derive an adherence value from a series of events. + public var aggregator: OCKAdherenceAggregator + + /// Initialize a new query by specifying the taskIDs, dates, and aggregator. + /// - Parameters: + /// - taskIDs: The identifiers of the tasks for which adherence should be computed. + /// - dateInterval: The date interval for which to return adherence information. + /// - aggregator: An aggregator that will be used to compute adherence. Uses `.outcomesExists` by default. + public init(taskIDs: [String], dateInterval: DateInterval, aggregator: OCKAdherenceAggregator = .outcomeExists) { + self.taskIDs = taskIDs + self.dateInterval = dateInterval + self.aggregator = aggregator + } + + func dates() -> [Date] { + var dates = [Date]() + var currentDate = dateInterval.start + while currentDate < dateInterval.end { + dates.append(currentDate) + currentDate = Calendar.current.date(byAdding: .day, value: 1, to: currentDate)! + } + return dates + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKCarePlanQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKCarePlanQuery.swift new file mode 100755 index 0000000..43c7d55 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKCarePlanQuery.swift @@ -0,0 +1,116 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A protocol that all care plan queries are expected to conform to. +public protocol OCKAnyCarePlanQuery: OCKEntityQuery { + + /// The identifiers of patients for which care plans should match. + var patientIDs: [String] { get set } + + /// The order in which the results will be sorted when returned from the query. + var sortDescriptors: [OCKCarePlanSortDescriptor] { get set } +} + +public extension OCKAnyCarePlanQuery { + init(_ query: OCKAnyCarePlanQuery) { + if let other = query as? Self { + self = other + return + } + self = Self(query as OCKEntityQuery) + self.patientIDs = query.patientIDs + self.sortDescriptors = query.sortDescriptors + } +} + +/// Describes the order in which care plans can be sorted when queried. +public enum OCKCarePlanSortDescriptor: Equatable { + case title(ascending: Bool) + + fileprivate var customVersion: OCKCarePlanQuery.SortDescriptor { + switch self { + case .title(let ascending): return .title(ascending: ascending) + } + } +} + +/// A query that limits which care plans will be returned when fetching. +public struct OCKCarePlanQuery: OCKAnyCarePlanQuery, Equatable { + + /// Specifies the order in which query results will be sorted. + enum SortDescriptor: Equatable { + case title(ascending: Bool) + case effectiveDate(ascending: Bool) + + fileprivate var basicVersion: OCKCarePlanSortDescriptor? { + switch self { + case .title(let ascending): return .title(ascending: ascending) + case .effectiveDate: return nil + } + } + } + + /// Specific versions to be included in the query results. + public var versionIDs: [OCKLocalVersionID] = [] + + /// The version of the patients for which care plans should match. + public var patientVersionIDs: [OCKLocalVersionID] = [] + + /// The remote ID of patients for which care plans should match. + public var patientRemoteIDs: [String] = [] + + /// The order in which the results will be sorted when returned from the query. + public var sortDescriptors: [OCKCarePlanSortDescriptor] { + get { extendedSortDescriptors.compactMap { $0.basicVersion } } + set { extendedSortDescriptors = newValue.map { $0.customVersion } } + } + + /// The order in which the results will be sorted when returned from the query. This property supports + /// additional sort descriptors unique to `OCKStore`. + internal var extendedSortDescriptors: [SortDescriptor] = [] + + /// An array of group identifiers to match against. + public var groupIdentifiers: [String] = [] + + /// An array of tags to match against. If an object's tags contains one or more of entries, it will match the query. + public var tags: [String] = [] + + // MARK: OCKAnyCarePlanQuery + public var patientIDs: [String] = [] + public var dateInterval: DateInterval? + public var ids: [String] = [] + public var remoteIDs: [String] = [] + public var offset: Int = 0 + public var limit: Int? + + public init() { } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKContactQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKContactQuery.swift new file mode 100755 index 0000000..fa38fff --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKContactQuery.swift @@ -0,0 +1,120 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A protocol that all contact queries are expected to conform to. +public protocol OCKAnyContactQuery: OCKEntityQuery { + + /// The identifiers of care plans for which contacts should match. + var carePlanIDs: [String] { get set } + + /// The order in which the results will be sorted when returned from the query. + var sortDescriptors: [OCKContactSortDescriptor] { get set } +} + +public extension OCKAnyContactQuery { + init(_ query: OCKAnyContactQuery) { + if let other = query as? Self { + self = other + return + } + self = Self(query as OCKEntityQuery) + self.carePlanIDs = query.carePlanIDs + self.sortDescriptors = query.sortDescriptors + } +} + +/// Describes the order in which contacts can be sorted when queried. +public enum OCKContactSortDescriptor: Equatable { + case givenName(ascending: Bool) + case familyName(ascending: Bool) + + fileprivate var extendedVersion: OCKContactQuery.SortDescriptor { + switch self { + case .givenName(let ascending): return .givenName(ascending: ascending) + case .familyName(let ascending): return .familyName(ascending: ascending) + } + } +} + +/// A query that limits which contacts will be returned when fetching. +public struct OCKContactQuery: OCKAnyContactQuery, Equatable { + + /// Specifies the order in which query results will be sorted. + enum SortDescriptor: Equatable { + case givenName(ascending: Bool) + case familyName(ascending: Bool) + case effectiveDate(ascending: Bool) + + fileprivate var basicVersion: OCKContactSortDescriptor? { + switch self { + case .givenName(let ascending): return .givenName(ascending: ascending) + case .familyName(let ascending): return .familyName(ascending: ascending) + case .effectiveDate: return nil + } + } + } + + /// Specific versions to be included in the query results. + public var versionIDs: [OCKLocalVersionID] = [] + + /// The version of the care plans for which contacts should match. + public var carePlanVersionIDs: [OCKLocalVersionID] = [] + + /// The remote ID of care plans for which contacts should match. + public var carePlanRemoteIDs: [String] = [] + + /// The order in which the results will be sorted when returned from the query. + public var sortDescriptors: [OCKContactSortDescriptor] { + get { extendedSortDescriptors.compactMap { $0.basicVersion } } + set { extendedSortDescriptors = newValue.map { $0.extendedVersion } } + } + + /// The order in which the results will be sorted when returned from the query. This property supports + /// additional sort descriptors unique to `OCKStore`. + internal var extendedSortDescriptors: [SortDescriptor] = [] + + /// An array of group identifiers to match against. + public var groupIdentifiers: [String] = [] + + /// An array of tags to match against. If an object's tags contains one or more of entries, it will match the query. + public var tags: [String] = [] + + // MARK: OCKAnyContactQuery + public var ids: [String] = [] + public var remoteIDs: [String] = [] + public var carePlanIDs: [String] = [] + public var dateInterval: DateInterval? + public var limit: Int? + public var offset: Int = 0 + + public init() { } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEntityQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEntityQuery.swift new file mode 100755 index 0000000..4e98491 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEntityQuery.swift @@ -0,0 +1,89 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Foundation + +/// All queries that return non-ephemeral entities from the store are expected to conform to this protocol. +/// Examples of non-ephemeral entites are patients, care plans, contacts, tasks, and outcomes. +/// Ephemeral entities include events, adherence, and insights. +public protocol OCKEntityQuery { + + /// An array of unique identifiers belonging to the entities which should match the query. + var ids: [String] { get set } + + /// An array of remote IDs for entities that should match the query. + var remoteIDs: [String] { get set } + + /// An array of group identifers that should match the query. + var groupIdentifiers: [String] { get set } + + /// A date interval for entities that should match the query. + var dateInterval: DateInterval? { get set } + + /// The maximum number of results that will be returned by the query. A nil value indicates no upper limit. + var limit: Int? { get set } + + /// An offset that can be used to paginate results. + var offset: Int { get set } + + /// Initialize a new query with default properties. + init() +} + +public extension OCKEntityQuery { + + /// Create a query that spans an explicit date interval. + init(dateInterval: DateInterval) { + self = Self() + self.dateInterval = dateInterval + } + + /// Create a query to retrieve an entity with the specified unique identifier. + init(id: String) { + self = Self() + self.ids = [id] + } + + /// Create a query with that spans the entire day on the date given. + init(for date: Date) { + let startOfDay = Calendar.current.startOfDay(for: date) + let endOfDay = Calendar.current.date(byAdding: DateComponents(day: 1, second: -1), to: startOfDay)! + self = Self(dateInterval: DateInterval(start: startOfDay, end: endOfDay)) + } + + /// Create a new query from any other entity query. Properties common to both queries will be copied. + init(_ query: OCKEntityQuery) { + self = Self() + self.ids = query.ids + self.remoteIDs = query.remoteIDs + self.limit = query.limit + self.offset = query.offset + self.dateInterval = query.dateInterval + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEventQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEventQuery.swift new file mode 100755 index 0000000..1739be4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKEventQuery.swift @@ -0,0 +1,56 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A query that limits which events will be returned when fetching. +public struct OCKEventQuery { + + /// The date interval in which outcomes should match. + public var dateInterval: DateInterval + + /// Initialize a new `OCKEventQuery` by specifying the start and end dates. + /// + /// - Parameters: + /// - dateInterval: The date interval in which outcomes should match. + public init(dateInterval: DateInterval) { + self.dateInterval = dateInterval + } + + /// Initialize a new `OCKEventQuery` by specifying a particular date. + /// + /// - Parameters: + /// - date: The date from which the date interval will be created. + public init(for date: Date) { + let startOfDay = Calendar.current.startOfDay(for: date) + let endOfDay = Calendar.current.date(byAdding: DateComponents(day: 1, second: -1), to: startOfDay)! + self = Self(dateInterval: DateInterval(start: startOfDay, end: endOfDay)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKInsightQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKInsightQuery.swift new file mode 100755 index 0000000..4126ae1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKInsightQuery.swift @@ -0,0 +1,55 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A query that limits which events will be returned when computing insights. +public struct OCKInsightQuery { + + /// The identifier of the task for which insights should be queried. + public var taskID: String + + /// The date interval in which outcomes should match. + public var dateInterval: DateInterval + + /// An aggregator used to derive an insight from a series of events. + public var aggregator: OCKEventAggregator + + /// Initialize a new `OCKInsightsQuery` by specifying the start and end dates. + /// + /// - Parameters: + /// - start: The earliest date at which events should match. + /// - endDate: The latest date at which events should match. + public init(taskID: String, dateInterval: DateInterval, aggregator: OCKEventAggregator = .countOutcomeValues) { + self.taskID = taskID + self.dateInterval = dateInterval + self.aggregator = aggregator + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKOutcomeQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKOutcomeQuery.swift new file mode 100755 index 0000000..5588596 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKOutcomeQuery.swift @@ -0,0 +1,114 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A protocol that all outcome queries are expected to conform to. +public protocol OCKAnyOutcomeQuery: OCKEntityQuery { + + /// Any array of local database IDs of tass for which outcomes should be returned. + var taskIDs: [String] { get set } + + /// The order in which the results will be sorted when returned from the query. + var sortDescriptors: [OCKOutcomeSortDescriptor] { get set } +} + +public extension OCKAnyOutcomeQuery { + init(_ query: OCKAnyOutcomeQuery) { + if let other = query as? Self { + self = other + return + } + self = Self(query as OCKEntityQuery) + self.taskIDs = query.taskIDs + self.sortDescriptors = query.sortDescriptors + } +} + +/// Describes the order in which tasks can be sorted when queried. +public enum OCKOutcomeSortDescriptor: Equatable { + case date(ascending: Bool) + + fileprivate var extendedVersion: OCKOutcomeQuery.SortDescriptor { + switch self { + case .date(let ascending): return .date(ascending: ascending) + } + } +} + +/// A query that limits which outcomes will be returned when fetching. +public struct OCKOutcomeQuery: OCKAnyOutcomeQuery, Equatable { + + /// Specifies the order in which query results will be sorted. + enum SortDescriptor: Equatable { + case date(ascending: Bool) + + fileprivate var basicVersion: OCKOutcomeSortDescriptor? { + switch self { + case .date(let ascending): return .date(ascending: ascending) + } + } + } + + /// An array of local database version identifiers specifying the versions to be returned. + public var localIDs: [OCKLocalVersionID] = [] + + /// An array of local database IDs of tasks for which outcomes should be returned. + public var taskVersionIDs: [OCKLocalVersionID] = [] + + /// An array of remote IDs of tasks for which outcomes should be returned. + public var taskRemoteIDs: [String] = [] + + /// An array of group identifiers to match against. + public var groupIdentifiers: [String] = [] + + /// The order in which the results will be sorted when returned from the query. + public var sortDescriptors: [OCKOutcomeSortDescriptor] { + get { extendedSortDescriptors.compactMap { $0.basicVersion } } + set { extendedSortDescriptors = newValue.map { $0.extendedVersion } } + } + + /// The order in which the results will be sorted when returned from the query. This property supports + /// additional sort descriptors unique to `OCKStore`. + internal var extendedSortDescriptors: [SortDescriptor] = [] + + /// An array of tags to match against. If an object's tags contains one or more of entries, it will match the query. + public var tags: [String] = [] + + // MARK: OCKAnyOutcomeQuery + public var ids: [String] = [] + public var remoteIDs: [String] = [] + public var taskIDs: [String] = [] + public var dateInterval: DateInterval? + public var limit: Int? + public var offset: Int = 0 + + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKPatientQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKPatientQuery.swift new file mode 100755 index 0000000..1ed0988 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKPatientQuery.swift @@ -0,0 +1,110 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A protocol that all patient queries are expected to conform to. +public protocol OCKAnyPatientQuery: OCKEntityQuery { + + /// The order in which the results will be sorted when returned from the query. + var sortDescriptors: [OCKPatientSortDescriptor] { get set } +} + +public extension OCKAnyPatientQuery { + init(_ query: OCKAnyPatientQuery) { + if let other = query as? Self { + self = other + return + } + self = Self(query as OCKEntityQuery) + self.sortDescriptors = query.sortDescriptors + } +} + +/// Describes the order in which patients can be sorted when queried. +public enum OCKPatientSortDescriptor: Equatable { + case givenName(ascending: Bool) + case familyName(ascending: Bool) + + fileprivate var extendedVersion: OCKPatientQuery.SortDescriptor { + switch self { + case .familyName(let ascending): return .familyName(ascending: ascending) + case .givenName(let ascending): return .givenName(ascending: ascending) + } + } +} + +/// A query that limits which patients will be returned when fetching. +public struct OCKPatientQuery: OCKAnyPatientQuery, Equatable { + + /// Specifies the order in which query results will be sorted. + enum SortDescriptor: Equatable { + case groupIdentifier(ascending: Bool) + case givenName(ascending: Bool) + case familyName(ascending: Bool) + case effectiveDate(ascending: Bool) + + fileprivate var basicVersion: OCKPatientSortDescriptor? { + switch self { + case .givenName(let ascending): return .givenName(ascending: ascending) + case .familyName(let ascending): return .familyName(ascending: ascending) + default: return nil + } + } + } + + /// Specific versions to be included in the query results. + public var versionIDs: [OCKLocalVersionID] = [] + + /// The order in which the results will be sorted when returned from the query. + public var sortDescriptors: [OCKPatientSortDescriptor] { + get { extendedSortDescriptors.compactMap { $0.basicVersion } } + set { extendedSortDescriptors = newValue.map { $0.extendedVersion } } + } + + /// The order in which the results will be sorted when returned from the query. This property supports + /// additional sort descriptors unique to `OCKStore`. + internal var extendedSortDescriptors: [SortDescriptor] = [] + + /// An array of group identifiers to match against. + public var groupIdentifiers: [String] = [] + + /// An array of tags to match against. If an object's tags contains one or more of entries, it will match the query. + public var tags: [String] = [] + + // MARK: OCKAnyPatientQuery + public var ids: [String] = [] + public var remoteIDs: [String] = [] + public var dateInterval: DateInterval? + public var limit: Int? + public var offset: Int = 0 + + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKTaskQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKTaskQuery.swift new file mode 100755 index 0000000..d36ba3f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStore/Structs/Queries/OCKTaskQuery.swift @@ -0,0 +1,172 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A protocol that all task queries are expected to conform to. +public protocol OCKAnyTaskQuery: OCKEntityQuery { + + /// The IDs of care plans for which tasks should match. + var carePlanIDs: [String] { get set } + + /// The order in which the results will be sorted when returned from the query. + var sortDescriptors: [OCKTaskSortDescriptor] { get set } +} + +public extension OCKAnyTaskQuery { + init(_ query: OCKAnyTaskQuery) { + if let other = query as? Self { + self = other + return + } + self = Self(query as OCKEntityQuery) + self.carePlanIDs = query.carePlanIDs + self.sortDescriptors = query.sortDescriptors + } +} + +/// Describes the order in which tasks can be sorted when queried. +public enum OCKTaskSortDescriptor: Equatable { + case groupIdentifier(ascending: Bool) + case title(ascending: Bool) + + fileprivate var extendedVersion: OCKTaskQuery.SortDescriptor { + switch self { + case .groupIdentifier(let ascending): return .groupIdentifier(ascending: ascending) + case .title(let ascending): return .title(ascending: ascending) + } + } +} + +/// A query that limits which tasks will be returned when fetching. +public struct OCKTaskQuery: OCKAnyTaskQuery, Equatable { + + /// Specifies the order in which query results will be sorted. + enum SortDescriptor: Equatable { + case effectiveDate(ascending: Bool) + case groupIdentifier(ascending: Bool) + case title(ascending: Bool) + + fileprivate var basicVersion: OCKTaskSortDescriptor? { + switch self { + case .groupIdentifier(let ascending): return .groupIdentifier(ascending: ascending) + case .title(let ascending): return .title(ascending: ascending) + case .effectiveDate: return nil + } + } + } + + /// The version of the care plans for which tasks should match. + public var carePlanVersionIDs: [OCKLocalVersionID] = [] + + /// The remote IDs of the care plans for which tasks should match. + public var carePlanRemoteIDs: [String] = [] + + /// Determines if tasks with no events should be included in the query results or not. False be default. + public var excludesTasksWithNoEvents: Bool = false + + /// The order in which the results will be sorted when returned from the query. + public var sortDescriptors: [OCKTaskSortDescriptor] { + get { extendedSortDescriptors.compactMap { $0.basicVersion } } + set { extendedSortDescriptors = newValue.map { $0.extendedVersion } } + } + + /// The order in which the results will be sorted when returned from the query. This property supports + /// additional sort descriptors unique to `OCKStore`. + internal var extendedSortDescriptors: [SortDescriptor] = [] + + /// An array of group identifiers to match against. + public var groupIdentifiers: [String] = [] + + /// An array of tags to match against. If an object's tags contains one or more of entries, it will match the query. + public var tags: [String] = [] + + // MARK: OCKAnyTaskQuery + public var ids: [String] = [] + public var versionIDs: [OCKLocalVersionID] = [] + public var remoteIDs: [String] = [] + public var carePlanIDs: [String] = [] + public var dateInterval: DateInterval? + public var limit: Int? + public var offset: Int = 0 + + public init() {} +} + +internal extension Array where Element: OCKCDTaskCompatible { + func filtered(against query: OCKTaskQuery) -> [Element] { + + var remaining = self + + if let dateInterval = query.dateInterval { + remaining = filter(against: dateInterval, excludeTasksWithNoEvents: query.excludesTasksWithNoEvents) + } + + return remaining.filter { task -> Bool in + + if !query.tags.isEmpty { + let taskTags = task.tags ?? [] + let matchesExist = taskTags.map { query.tags.contains($0) }.contains(true) + if !matchesExist { return false } + } + + if !query.groupIdentifiers.isEmpty { + guard let taskGroupIdentifier = task.groupIdentifier else { return false } + if !query.groupIdentifiers.contains(taskGroupIdentifier) { return false } + } + + return true + } + } + + func filter(against dateInterval: DateInterval, excludeTasksWithNoEvents: Bool) -> [Element] { + filter { task -> Bool in + let events = task.schedule.events(from: dateInterval.start, to: dateInterval.end) + + if excludeTasksWithNoEvents && events.isEmpty { return false } + + // Schedule with finite duration + if let scheduleEnd = task.schedule.endDate() { + let taskBeginsAfterQueryStarts = scheduleEnd >= dateInterval.start + let taskBeginsBeforeQueryEnds = task.effectiveDate <= dateInterval.end + guard taskBeginsAfterQueryStarts && taskBeginsBeforeQueryEnds else { + return false + } + } + + // Schedule with infinite duration + else if events.isEmpty && task.effectiveDate > dateInterval.end { + return false + } + + return true + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CareKitStore.xctestplan b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CareKitStore.xctestplan new file mode 100755 index 0000000..9d43dd5 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CareKitStore.xctestplan @@ -0,0 +1,33 @@ +{ + "configurations" : [ + { + "id" : "5E58A793-A721-42C8-8A91-318D8D05AB0F", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false, + "targetForVariableExpansion" : { + "containerPath" : "container:CareKitStore.xcodeproj", + "identifier" : "E784B8F72232EED600736CA5", + "name" : "CareKitStore" + } + }, + "testTargets" : [ + { + "skippedTests" : [ + "TestSchedule\/testEventGenerationPerformanceBasicSchedule()", + "TestSchedule\/testEventGenerationPerformanceHeavySchedule()" + ], + "target" : { + "containerPath" : "container:CareKitStore.xcodeproj", + "identifier" : "E784B9002232EED600736CA5", + "name" : "CareKitStoreTests" + } + } + ], + "version" : 1 +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchame+HealthKitLinkage.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchame+HealthKitLinkage.swift new file mode 100755 index 0000000..f89f15e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchame+HealthKitLinkage.swift @@ -0,0 +1,72 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithHealthKitLinkage: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveHealthKitLinkage() { + let scheduleElement = OCKCDScheduleElement(context: store.context) + scheduleElement.startDate = Date() + scheduleElement.daysInterval = 1 + scheduleElement.duration = .seconds(42) + + let task1 = OCKCDTask(context: store.context) + task1.id = "task_1" + task1.effectiveDate = Date() + task1.allowsMissingRelationships = true + task1.scheduleElements = Set([scheduleElement]) + + let linkage = OCKCDHealthKitLinkage(context: store.context) + linkage.quantityIdentifier = "steps" + linkage.quantityType = "cumulative" + linkage.unitString = "count" + + task1.healthKitLinkage = linkage + + XCTAssertNoThrow(try store.context.save()) + } + + func testCannotSaveHealthKitLinkageThatIsNotAssociatedWithATask() { + let linkage = OCKCDHealthKitLinkage(context: store.context) + linkage.quantityIdentifier = "steps" + linkage.quantityType = "cumulative" + linkage.unitString = "count" + + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+CarePlans.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+CarePlans.swift new file mode 100755 index 0000000..624e7dc --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+CarePlans.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithCarePlan: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveCarePlan() { + let plan1 = OCKCDCarePlan(context: store.context) + plan1.title = "Plan 1" + plan1.id = "plan_1" + plan1.effectiveDate = Date() + plan1.allowsMissingRelationships = true + XCTAssertNoThrow(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Contacts.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Contacts.swift new file mode 100755 index 0000000..f0f3e20 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Contacts.swift @@ -0,0 +1,78 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Contacts +import XCTest + +class TestCoreDataSchemaWithContacts: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveContact() { + let contact = OCKCDContact(context: store.context) + contact.allowsMissingRelationships = true + contact.id = "Katie Abeles" + contact.title = "Dr. Abeles" + contact.effectiveDate = Date() + contact.name = OCKCDPersonName(context: store.context) + contact.name.givenName = "Katie" + contact.name.familyName = "Abeles" + + let address = OCKCDPostalAddress(context: store.context) + address.country = "US" + address.city = "IN" + address.street = "311 Sharon Lane" + address.postalCode = "46601" + + contact.address = address + contact.phoneNumbers = [OCKLabeledValue(label: CNLabelWork, value: "+1 (574) 555-0164")] + contact.emailAddresses = [OCKLabeledValue(label: CNLabelHome, value: "kabeles@icloud.com")] + contact.otherContactInfo = [OCKLabeledValue(label: CNLabelOther, value: "https://en.wikipedia.org/wiki/Dr.Kabeles")] + contact.organization = "FakeOrg" + contact.role = "Doctor" + contact.category = "Health Industry" + + XCTAssertNoThrow(try store.context.save()) + XCTAssert(contact.name.givenName == "Katie") + XCTAssert(contact.name.familyName == "Abeles") + } + + func testCannotSaveWithoutCarePlan() { + let contact = OCKCDContact(context: store.context) + contact.effectiveDate = Date() + contact.allowsMissingRelationships = false + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Notes.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Notes.swift new file mode 100755 index 0000000..f93b2ad --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Notes.swift @@ -0,0 +1,54 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithNotes: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveNote() { + let note = OCKCDNote(context: store.context) + note.author = "Katie Ball" + note.title = "Patient" + note.content = """ + I plan on doing a 30 minute run this evening. + If I'm lucky, I might see the mother of the swift + birds nesting in our front yard! + """ + + XCTAssertNoThrow(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Outcomes.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Outcomes.swift new file mode 100755 index 0000000..7a4bc38 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Outcomes.swift @@ -0,0 +1,86 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithOutcomes: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveOutcomeWithvalues() { + let scheduleElement = OCKCDScheduleElement(context: store.context) + scheduleElement.startDate = Date() + scheduleElement.daysInterval = 1 + scheduleElement.duration = .seconds(42) + + let task1 = OCKCDTask(context: store.context) + task1.id = "task_1" + task1.effectiveDate = Date() + task1.allowsMissingRelationships = true + task1.scheduleElements = Set([scheduleElement]) + + let value1 = OCKCDOutcomeValue(context: store.context) + value1.kind = "sleep-time" + value1.dateValue = Date() + value1.type = .date + + let value2 = OCKCDOutcomeValue(context: store.context) + value2.kind = "circumference-diameter-ratio" + value2.doubleValue = 3.14 + value2.type = .double + + let value3 = OCKCDOutcomeValue(context: store.context) + value3.kind = "favorite-japanese-food" + value3.integerValue = 8_929 + value3.type = .integer + + let outcome = OCKCDOutcome(context: store.context) + outcome.taskOccurrenceIndex = 0 + outcome.values = Set([value1, value2, value3]) + outcome.task = task1 + outcome.date = Date() + + XCTAssertNoThrow(try store.context.save()) + XCTAssert(outcome.values.count == 3) + } + + func testCannotSaveOutcomeWithoutAssociatingItWithATask() { + let outcome = OCKCDOutcome(context: store.context) + outcome.taskOccurrenceIndex = 0 + outcome.values = Set([]) + + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Patients.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Patients.swift new file mode 100755 index 0000000..7082eaa --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Patients.swift @@ -0,0 +1,57 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithPatient: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSavePatient() { + let patient = OCKCDPatient(context: store.context) + patient.id = "my_id" + patient.effectiveDate = Date() + patient.name = OCKCDPersonName(context: store.context) + patient.name.givenName = "Amy" + patient.name.familyName = "Frost" + patient.sex = "female" + patient.birthday = Date() + patient.allergies = ["latex"] + + XCTAssertNoThrow(try store.context.save()) + XCTAssert(patient.name.givenName == "Amy") + XCTAssert(patient.name.familyName == "Frost") + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+PostalAddress.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+PostalAddress.swift new file mode 100755 index 0000000..e3f343d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+PostalAddress.swift @@ -0,0 +1,80 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithPostalAddress: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveAddress() { + let contact = OCKCDContact(context: store.context) + contact.allowsMissingRelationships = true + contact.id = "Katie Abeles" + contact.title = "Dr. Abeles" + contact.effectiveDate = Date() + contact.name = OCKCDPersonName(context: store.context) + contact.name.givenName = "Katie" + contact.name.familyName = "Abeles" + + let address = OCKCDPostalAddress(context: store.context) + address.street = "A" + address.subLocality = "B" + address.city = "C" + address.subAdministrativeArea = "D" + address.state = "E" + address.postalCode = "F" + address.country = "G" + address.isoCountryCode = "H" + + contact.address = address + + XCTAssertNoThrow(try store.context.save()) + } + + func testCannotSaveAddressThatIsNotAssociatedWithAContact() { + let address = OCKCDPostalAddress(context: store.context) + address.street = "A" + address.subLocality = "B" + address.city = "C" + address.subAdministrativeArea = "D" + address.state = "E" + address.postalCode = "F" + address.country = "G" + address.isoCountryCode = "H" + + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+ScheduleElements.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+ScheduleElements.swift new file mode 100755 index 0000000..565df4f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+ScheduleElements.swift @@ -0,0 +1,72 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithScheduleElements: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCannotSaveScheduleElementsAllZeroIntervals() { + let element = OCKCDScheduleElement(context: store.context) + element.startDate = Date() + element.text = "Every day starting now" + XCTAssertThrowsError(try store.context.save()) + } + + func testCanSaveTargetValuesOnScheduleElement() { + let value = OCKCDOutcomeValue(context: store.context) + value.type = .boolean + value.booleanValue = true + value.units = nil + + let element = OCKCDScheduleElement(context: store.context) + element.startDate = Date() + element.interval = DateComponents(day: 1) + element.duration = .hours(1) + element.targetValues = Set([value]) + + XCTAssertNoThrow(try store.context.save()) + } + + func testCannotSaveScheduleElementsWithoutAnAssociatedTaskOrScheduleElement() { + let element = OCKCDScheduleElement(context: store.context) + element.startDate = Date() + element.interval = DateComponents(day: 1) + element.duration = .hours(1) + + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Tasks.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Tasks.swift new file mode 100755 index 0000000..c56013b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Tasks.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaWithTasks: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testCanSaveTask() { + let scheduleElement = OCKCDScheduleElement(context: store.context) + scheduleElement.startDate = Date() + scheduleElement.daysInterval = 1 + scheduleElement.duration = .seconds(42) + + let task1 = OCKCDTask(context: store.context) + task1.id = "task_1" + task1.effectiveDate = Date() + task1.allowsMissingRelationships = true + task1.scheduleElements = Set([scheduleElement]) + + XCTAssertNoThrow(try store.context.save()) + } + + func testCannotSaveTaskWithoutSchedule() { + let task1 = OCKCDTask(context: store.context) + task1.id = "task_1" + task1.effectiveDate = Date() + task1.allowsMissingRelationships = true + + XCTAssertThrowsError(try store.context.save()) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Versioning.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Versioning.swift new file mode 100755 index 0000000..28bad93 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchema+Versioning.swift @@ -0,0 +1,127 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +// This test case is for the abstract class `OCKCDVersionedObject`. Since it is an abstract class, +// we test it using a concrete subclass, but the code we're trying to cover is the parent class. +class TestCoreDataSchemaWithVersioning: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testVersioning() { + let patient1 = OCKCDPatient(context: store.context) + patient1.id = "my_id" + patient1.name = OCKCDPersonName(context: store.context) + patient1.name.familyName = "Frost1" + patient1.name.givenName = "Amy" + patient1.effectiveDate = Date() + + let patient2 = OCKCDPatient(context: store.context) + patient2.id = "my_id" + patient2.name = OCKCDPersonName(context: store.context) + patient2.name.familyName = "Foss2" + patient2.name.givenName = "Christopher" + patient2.effectiveDate = Date() + + let patient3 = OCKCDPatient(context: store.context) + patient3.id = "my_id" + patient3.name = OCKCDPersonName(context: store.context) + patient3.name.familyName = "Gosler3" + patient3.name.givenName = "Jared" + patient3.effectiveDate = Date() + + XCTAssert(patient1.previous == nil) + XCTAssert(patient1.next == nil) + + XCTAssert(patient2.previous == nil) + XCTAssert(patient2.next == nil) + + XCTAssert(patient3.previous == nil) + XCTAssert(patient3.next == nil) + + patient3.previous = patient2 + patient2.previous = patient1 + XCTAssertNoThrow(try store.context.save()) + + let head = OCKCDPatient.fetchHeads(ids: ["my_id"], in: store.context).first + XCTAssert(head == patient3) + XCTAssert(head?.next == nil) + XCTAssert(head?.previous == patient2) + XCTAssert(head?.previous?.previous == patient1) + XCTAssert(head?.previous?.previous?.previous == nil) + } + + func testAddVersionedObectsFailsIfIdentifersArentUnique() { + let patient1 = OCKPatient(id: "my_id", givenName: "John", familyName: "Appleseed") + let patient2 = OCKPatient(id: "my_id", givenName: "Jane", familyName: "Appleseed") + store.addPatients([patient1, patient2]) { result in + XCTAssertNil(try? result.get()) + } + } + + func testUpdateVersionedObjectsFailsIfIdentifiersArentUnique() { + let patient1 = OCKPatient(id: "my_id", givenName: "John", familyName: "Appleseed") + let patient2 = OCKPatient(id: "my_id", givenName: "Jane", familyName: "Appleseed") + store.updatePatients([patient1, patient2]) { result in + XCTAssertNil(try? result.get()) + } + } + + func testSavingUserInfo() throws { + let patient = OCKCDPatient(context: store.context) + patient.id = "my_id" + patient.name = OCKCDPersonName(context: store.context) + patient.name.nickname = "Wiggle Bogey" + patient.userInfo = ["name": "Wiggle Bogey"] + patient.effectiveDate = Date() + XCTAssertNoThrow(try store.context.save()) + + guard let fetchedPatient = try store.context.existingObject(with: patient.objectID) as? OCKCDPatient else { XCTFail("Bad type"); return } + XCTAssert(fetchedPatient.userInfo?["name"] == "Wiggle Bogey") + } + + func testSchemaVersionIsAutomaticallyAttached() { + let patient = OCKCDPatient(context: store.context) + patient.id = "my_id" + patient.name = OCKCDPersonName(context: store.context) + patient.name.familyName = "Frost1" + patient.name.givenName = "Amy" + patient.effectiveDate = Date() + + XCTAssertNoThrow(try store.context.save()) + XCTAssertNotNil(patient.schemaVersion) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchemaIntegration.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchemaIntegration.swift new file mode 100755 index 0000000..bfb594f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/CoreDataSchema/TestCoreDataSchemaIntegration.swift @@ -0,0 +1,87 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCoreDataSchemaIntegration: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "test", type: .inMemory) + } + + func testAllEntitiesCanBeChainedAndSavedInABatch() { + let patient = OCKCDPatient(context: store.context) + patient.id = "my_id" + patient.name = OCKCDPersonName(context: store.context) + patient.name.familyName = "Amy" + patient.name.givenName = "Frost" + patient.effectiveDate = Date() + + let plan = OCKCDCarePlan(context: store.context) + plan.title = "Post Operation Care Plan" + plan.id = "post-op-plan" + plan.patient = patient + plan.effectiveDate = Date() + + let task = OCKCDTask(context: store.context) + task.id = "measure-pulse" + task.instructions = "Take your pulse for a 60s and record in BPM" + task.carePlan = plan + task.effectiveDate = Date() + + let schedule = OCKCDScheduleElement(context: store.context) + schedule.text = "Once each day" + schedule.startDate = Date() + schedule.daysInterval = 1 + schedule.duration = .hours(1) + schedule.task = task + + let outcome = OCKCDOutcome(context: store.context) + outcome.taskOccurrenceIndex = 0 + outcome.task = task + outcome.date = Date() + + let value = OCKCDOutcomeValue(context: store.context) + value.kind = "pulse" + value.units = "BPM" + value.integerValue = 80 + value.type = .integer + value.outcome = outcome + + XCTAssertNoThrow(try store.context.save()) + XCTAssert(patient.carePlans.first == plan) + XCTAssert(task.scheduleElements.first == schedule) + XCTAssert(task.outcomes.first == outcome) + XCTAssert(outcome.values.first == value) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Info.plist new file mode 100755 index 0000000..6c40a6c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+CarePlans.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+CarePlans.swift new file mode 100755 index 0000000..fcfd7d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+CarePlans.swift @@ -0,0 +1,256 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +@testable import CareKitStore +import XCTest + +class TestStoreCarePlans: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: Relationship Validation + + func testStorePreventsMissingPatientRelationshipOnCarePlans() { + let plan = OCKCarePlan(id: "diabetes_type_1", title: "Diabetes Care Plan", patientID: nil) + store.configuration.allowsEntitiesWithMissingRelationships = false + XCTAssertThrowsError(try store.addCarePlanAndWait(plan)) + } + + func testStoreAllowsMissingPatientRelationshipOnCarePlans() { + let plan = OCKCarePlan(id: "diabetes_type_1", title: "Diabetes Care Plan", patientID: nil) + XCTAssertNoThrow(try store.addCarePlanAndWait(plan)) + } + + // MARK: Insertion + + func testAddAndFetchCarePlans() throws { + let plan = try store.addCarePlanAndWait(OCKCarePlan(id: "6789", title: "Diabetes Care Plan", patientID: nil)) + XCTAssertNotNil(plan.localDatabaseID) + XCTAssertNotNil(plan.schemaVersion) + } + + func testAddCarePlanFailsIfIdentifierAlreadyExists() throws { + let plan1 = OCKCarePlan(id: "id", title: "Diabetes Care Plan", patientID: nil) + let plan2 = OCKCarePlan(id: "id", title: "Obesity Care Plan", patientID: nil) + try store.addCarePlanAndWait(plan1) + XCTAssertThrowsError(try store.addCarePlanAndWait(plan2)) + } + + // MARK: Querying + + func testCarePlaneQueryByPatientIdentifier() throws { + let patient = try store.addPatientAndWait(.init(id: "A", givenName: "B", familyName: "C")) + let plan = try store.addCarePlanAndWait(.init(id: "F", title: "G", patientID: try patient.getLocalID())) + + var query = OCKCarePlanQuery() + query.patientIDs = [patient.id] + + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched == [plan]) + } + + func testCarePlanQueryGroupIdentifier() throws { + var plan1 = OCKCarePlan(id: "id_1", title: "Diabetes Care Plan", patientID: nil) + plan1.groupIdentifier = "1" + var plan2 = OCKCarePlan(id: "id_2", title: "Obesity Care Plan", patientID: nil) + plan2.groupIdentifier = "2" + try store.addCarePlansAndWait([plan1, plan2]) + var query = OCKCarePlanQuery(for: Date()) + query.groupIdentifiers = ["1"] + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.id == "id_1") + } + + func testCarePlanQueryLimit() throws { + let plan1 = OCKCarePlan(id: "A", title: "A", patientID: nil) + let plan2 = OCKCarePlan(id: "B", title: "B", patientID: nil) + try store.addCarePlansAndWait([plan1, plan2]) + var query = OCKCarePlanQuery(for: Date()) + query.limit = 1 + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.count == 1) + } + + func testCarePlanQuerySortedOffset() throws { + let plan1 = OCKCarePlan(id: "A", title: "A", patientID: nil) + let plan2 = OCKCarePlan(id: "B", title: "B", patientID: nil) + let plan3 = OCKCarePlan(id: "C", title: "C", patientID: nil) + try store.addCarePlansAndWait([plan1, plan2, plan3]) + var query = OCKCarePlanQuery(for: Date()) + query.extendedSortDescriptors = [.title(ascending: true)] + query.offset = 2 + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.id == "C") + } + + func testCarePlanQueryWithNilQueryReturnsAllCarePlans() throws { + let plan1 = OCKCarePlan(id: "1", title: "1", patientID: nil) + let plan2 = OCKCarePlan(id: "2", title: "2", patientID: nil) + let plan3 = OCKCarePlan(id: "3", title: "3", patientID: nil) + try store.addCarePlansAndWait([plan1, plan2, plan3]) + let plans = try store.fetchCarePlansAndWait() + XCTAssert(plans.count == 3) + } + + func testCarePlanQueryTags() throws { + var plan1 = OCKCarePlan(id: "A", title: "A", patientID: nil) + plan1.tags = ["1", "2"] + + var plan2 = OCKCarePlan(id: "B", title: "B", patientID: nil) + plan2.tags = ["1", "2", "3"] + + var plan3 = OCKCarePlan(id: "C", title: "C", patientID: nil) + plan3.tags = ["1"] + + try store.addCarePlansAndWait([plan1, plan2, plan3]) + + var query = OCKCarePlanQuery(for: Date()) + query.tags = ["2"] + query.extendedSortDescriptors = [.title(ascending: true)] + + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.map { $0.title } == ["A", "B"]) + } + + // MARK: Versioning + + func testUpdateCarePlanCreatesNewVersion() throws { + let plan = try store.addCarePlanAndWait(OCKCarePlan(id: "bronchitis", title: "Bronchitis", patientID: nil)) + let updatedPlan = try store.updateCarePlanAndWait(OCKCarePlan(id: "bronchitis", title: "Bronchitis Treatment", patientID: nil)) + XCTAssert(updatedPlan.title == "Bronchitis Treatment") + XCTAssert(updatedPlan.previousVersionID == plan.localDatabaseID) + } + + func testUpdateFailsForUnsavedCarePlans() { + XCTAssertThrowsError(try store.updateCarePlanAndWait( + OCKCarePlan(id: "bronchitis", title: "Bronchitis", patientID: nil))) + } + + func testCarePlanQueryWithNoDateOnlyReturnsLatestVersionOfACarePlan() throws { + let versionA = try store.addCarePlanAndWait(OCKCarePlan(id: "A", title: "Amy", patientID: nil)) + let versionB = try store.updateCarePlanAndWait(OCKCarePlan(id: "A", title: "Jared", patientID: nil)) + let fetched = try store.fetchCarePlanAndWait(id: versionA.id) + XCTAssert(fetched?.id == versionB.id) + XCTAssert(fetched?.previousVersionID == versionA.localDatabaseID) + } + + func testCarePlanQueryOnPastDateReturnsPastVersionOfACarePlan() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKCarePlan(id: "A", title: "a", patientID: nil) + versionA.effectiveDate = dateA + versionA = try store.addCarePlanAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKCarePlan(id: "A", title: "b", patientID: nil) + versionB.effectiveDate = dateB + versionB = try store.updateCarePlanAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(-10)) + let query = OCKCarePlanQuery(dateInterval: interval) + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.title == versionA.title) + } + + func testCarePlanQuerySpanningVersionsReturnsNewestVersionOnly() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKCarePlan(id: "A", title: "a", patientID: nil) + versionA.effectiveDate = dateA + versionA = try store.addCarePlanAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKCarePlan(id: "A", title: "b", patientID: nil) + versionB.effectiveDate = dateB + versionB = try store.updateCarePlanAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(10)) + let query = OCKCarePlanQuery(dateInterval: interval) + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.title == versionB.title) + } + + func testCarePlanQueryBeforeCarePlansWasCreatedReturnsNoResults() throws { + let dateA = Date() + try store.addCarePlanAndWait(OCKCarePlan(id: "A", title: "a", patientID: nil)) + let interval = DateInterval(start: dateA.addingTimeInterval(-100), end: dateA) + let query = OCKCarePlanQuery(dateInterval: interval) + let fetched = try store.fetchCarePlansAndWait(query: query) + XCTAssertTrue(fetched.isEmpty) + } + + func testQueryCarePlanByRemoteID() throws { + var plan = OCKCarePlan(id: "A", title: "Plan", patientID: nil) + plan.remoteID = "abc" + plan = try store.addCarePlanAndWait(plan) + var query = OCKCarePlanQuery(for: Date()) + query.remoteIDs = ["abc"] + let fetched = try store.fetchCarePlansAndWait(query: query).first + XCTAssert(plan == fetched) + } + + func testQueryCarePlanByPatientRemoteID() throws { + var patient = OCKPatient(id: "A", givenName: "B", familyName: "C") + patient.remoteID = "abc" + patient = try store.addPatientAndWait(patient) + + var plan = OCKCarePlan(id: "D", title: "E", patientID: patient.localDatabaseID) + plan = try store.addCarePlanAndWait(plan) + + var query = OCKCarePlanQuery(for: Date()) + query.patientRemoteIDs = ["abc"] + + let fetched = try store.fetchCarePlansAndWait(query: query).first + XCTAssert(fetched == plan) + } + // MARK: Deletion + + func testDeleteCarePlan() throws { + let plan = try store.addCarePlanAndWait(OCKCarePlan(id: "stinky_breath", title: "Gingivitus", patientID: nil)) + try store.deleteCarePlanAndWait(plan) + let fetched = try store.fetchCarePlansAndWait() + XCTAssert(fetched.isEmpty) + } + + func testDeleteCarePlanFailsIfCarePlanDoesntExist() { + let plan = OCKCarePlan(id: "stinky_breath", title: "Gingivitus", patientID: nil) + XCTAssertThrowsError(try store.deleteCarePlanAndWait(plan)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Contacts.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Contacts.swift new file mode 100755 index 0000000..1f1a852 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Contacts.swift @@ -0,0 +1,304 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestStoreContacts: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: Relationship Validation + + func testStoreAllowsMissingCarePlanRelationshipOnContacts() { + let contact = OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil) + XCTAssertNoThrow(try store.addContactAndWait(contact)) + } + + func testStorePreventsMissingCarePlanRelationshipOnContacts() { + let contact = OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil) + store.configuration.allowsEntitiesWithMissingRelationships = false + XCTAssertThrowsError(try store.addContactAndWait(contact)) + } + + // MARK: Insertion + + func testAddContact() throws { + var contact = OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil) + let address = OCKPostalAddress() + address.state = "CO" + address.country = "US" + address.street = "4693 Sweetwood Drive" + contact.address = address + contact.messagingNumbers = [OCKLabeledValue(label: "iPhone", value: "303-555-0194")] + contact.phoneNumbers = [OCKLabeledValue(label: "Home", value: "303-555-0108")] + contact.emailAddresses = [OCKLabeledValue(label: "Email", value: "amy_frost44@icloud.com")] + contact.otherContactInfo = [OCKLabeledValue(label: "Facetime", value: "303-555-0121")] + contact.organization = "Apple Dumplings Corp." + contact.title = "Manager of Apple Peeling" + contact.role = "Official Taste Tester" + + contact = try store.addContactAndWait(contact) + let fetchedConctacts = try store.fetchContactsAndWait() + XCTAssert([contact] == fetchedConctacts) + XCTAssert(contact.address?.state == "CO") + XCTAssert(contact.address?.country == "US") + XCTAssert(contact.address?.street == "4693 Sweetwood Drive") + XCTAssert(contact.messagingNumbers == [OCKLabeledValue(label: "iPhone", value: "303-555-0194")]) + XCTAssert(contact.phoneNumbers == [OCKLabeledValue(label: "Home", value: "303-555-0108")]) + XCTAssert(contact.emailAddresses == [OCKLabeledValue(label: "Email", value: "amy_frost44@icloud.com")]) + XCTAssert(contact.otherContactInfo == [OCKLabeledValue(label: "Facetime", value: "303-555-0121")]) + XCTAssert(contact.organization == "Apple Dumplings Corp.") + XCTAssert(contact.title == "Manager of Apple Peeling") + XCTAssert(contact.role == "Official Taste Tester") + XCTAssertNotNil(contact.schemaVersion) + } + + func testAddContactFailsIfIdentifierAlreadyExists() throws { + let contact1 = OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil) + let contact2 = OCKContact(id: "contact", givenName: "Jared", familyName: "Gosler", carePlanID: nil) + try store.addContactAndWait(contact1) + XCTAssertThrowsError(try store.addContactAndWait(contact2)) + } + + // MARK: Querying + + func testQueryContactsByIdentifier() throws { + let contact1 = try store.addContactAndWait(OCKContact(id: "contact1", givenName: "Amy", familyName: "Frost", carePlanID: nil)) + try store.addContactAndWait(OCKContact(id: "contact2", givenName: "Amy", familyName: "Frost", carePlanID: nil)) + let fetchedContacts = try store.fetchContactsAndWait(query: OCKContactQuery(id: "contact1")) + XCTAssert(fetchedContacts == [contact1]) + } + + func testQueryContactsByCarePlanID() throws { + let carePlan = try store.addCarePlanAndWait(OCKCarePlan(id: "B", title: "Care Plan A", patientID: nil)) + try store.addContactAndWait(OCKContact(id: "care plan 1", givenName: "Mark", familyName: "Brown", carePlanID: nil)) + var contact = OCKContact(id: "care plan 2", givenName: "Amy", familyName: "Frost", carePlanID: try carePlan.getLocalID()) + contact = try store.addContactAndWait(contact) + var query = OCKContactQuery() + query.carePlanIDs = [carePlan.id] + let fetchedContacts = try store.fetchContactsAndWait(query: query) + XCTAssert(fetchedContacts == [contact]) + } + + func testContactsQueryGroupIdentifiers() throws { + var contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + contactA.groupIdentifier = "Alpha" + var contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + contactB.groupIdentifier = "Beta" + try store.addContactsAndWait([contactA, contactB]) + var query = OCKContactQuery(for: Date()) + query.groupIdentifiers = ["Alpha"] + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.groupIdentifier == "Alpha") + } + + func testContactQueryTags() throws { + var contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + contactA.tags = ["A"] + var contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + contactB.tags = ["B", "C"] + var contactC = OCKContact(id: "C", givenName: "c", familyName: "cccc", carePlanID: nil) + contactC.tags = ["C"] + try store.addContactsAndWait([contactA, contactB, contactC]) + var query = OCKContactQuery(for: Date()) + query.tags = ["C"] + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.map { $0.id }.sorted() == ["B", "C"]) + } + + func testContactQueryLimited() throws { + let contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + let contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + let contactC = OCKContact(id: "C", givenName: "c", familyName: "cccc", carePlanID: nil) + try store.addContactsAndWait([contactA, contactB, contactC]) + var query = OCKContactQuery(for: Date()) + query.limit = 2 + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.count == 2) + } + + func testContactQueryOffset() throws { + let contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + let contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + let contactC = OCKContact(id: "C", givenName: "c", familyName: "cccc", carePlanID: nil) + try store.addContactsAndWait([contactA, contactB, contactC]) + var query = OCKContactQuery(for: Date()) + query.offset = 2 + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.count == 1) + } + + func testContactQuerySorted() throws { + let contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + let contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + let contactC = OCKContact(id: "C", givenName: "c", familyName: "cccc", carePlanID: nil) + try store.addContactsAndWait([contactA, contactB, contactC]) + var query = OCKContactQuery(for: Date()) + query.sortDescriptors = [.givenName(ascending: true)] + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.map { $0.name.givenName } == ["a", "b", "c"]) + } + + func testContactNilQueryReturnsAllContacts() throws { + let contactA = OCKContact(id: "A", givenName: "a", familyName: "aaa", carePlanID: nil) + let contactB = OCKContact(id: "B", givenName: "b", familyName: "bbb", carePlanID: nil) + let contactC = OCKContact(id: "C", givenName: "c", familyName: "cccc", carePlanID: nil) + try store.addContactsAndWait([contactA, contactB, contactC]) + let contacts = try store.fetchContactsAndWait() + XCTAssertNotNil(contacts.count == 3) + } + + func testQueryContactByRemoteID() throws { + var contact = OCKContact(id: "A", givenName: "B", familyName: "C", carePlanID: nil) + contact.remoteID = "abc" + contact = try store.addContactAndWait(contact) + var query = OCKContactQuery() + query.remoteIDs = ["abc"] + let fetched = try store.fetchContactsAndWait(query: query).first + XCTAssert(fetched == contact) + } + + func testQueryContactByCarePlanRemoteID() throws { + var plan = OCKCarePlan(id: "D", title: "", patientID: nil) + plan.remoteID = "abc" + plan = try store.addCarePlanAndWait(plan) + + var contact = OCKContact(id: "A", givenName: "B", familyName: "C", carePlanID: plan.localDatabaseID) + contact = try store.addContactAndWait(contact) + var query = OCKContactQuery(for: Date()) + query.carePlanRemoteIDs = ["abc"] + let fetched = try store.fetchContactsAndWait(query: query).first + XCTAssert(fetched == contact) + } + + func testQueryContactByCarePlanVersionID() throws { + let plan = try store.addCarePlanAndWait(OCKCarePlan(id: "A", title: "B", patientID: nil)) + let planID = try plan.getLocalID() + let contact = try store.addContactAndWait(OCKContact(id: "C", givenName: "D", familyName: "E", carePlanID: planID)) + var query = OCKContactQuery(for: Date()) + query.carePlanVersionIDs = [planID] + let fetched = try store.fetchContactsAndWait(query: query).first + XCTAssert(fetched == contact) + } + + // MARK: Versioning + + func testUpdateContactCreatesNewVersion() throws { + let contact = try store.addContactAndWait(OCKContact(id: "contact", givenName: "John", familyName: "Appleseed", carePlanID: nil)) + let updated = try store.updateContactAndWait(OCKContact(id: "contact", givenName: "Jane", familyName: "Appleseed", carePlanID: nil)) + XCTAssert(updated.name.givenName == "Jane") + XCTAssert(updated.localDatabaseID != contact.localDatabaseID) + XCTAssert(updated.previousVersionID == contact.localDatabaseID) + } + + func testUpdateFailsForUnsavedContacts() { + let patient = OCKContact(id: "careplan", givenName: "John", familyName: "Appleseed", carePlanID: nil) + XCTAssertThrowsError(try store.updateContactAndWait(patient)) + } + + func testContactQueryOnlyReturnsLatestVersionOfAContact() throws { + let versionA = try store.addContactAndWait(OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil)) + let versionB = try store.updateContactAndWait(OCKContact(id: "contact", givenName: "Mariana", familyName: "Lin", carePlanID: nil)) + let fetched = try store.fetchContactAndWait(id: versionA.id) + XCTAssert(fetched?.id == versionB.id) + XCTAssert(fetched?.name == versionB.name) + } + + func testContactQueryOnPastDateReturnsPastVersionOfAContact() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKContact(id: "A", givenName: "a", familyName: "b", carePlanID: nil) + versionA.effectiveDate = dateA + versionA = try store.addContactAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKContact(id: "A", givenName: "a", familyName: "c", carePlanID: nil) + versionB.effectiveDate = dateB + versionB = try store.updateContactAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(-10)) + let query = OCKContactQuery(dateInterval: interval) + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.name == versionA.name) + } + + func testContactQuerySpanningVersionsReturnsNewestVersionOnly() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKContact(id: "A", givenName: "a", familyName: "b", carePlanID: nil) + versionA.effectiveDate = dateA + versionA = try store.addContactAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKContact(id: "A", givenName: "a", familyName: "c", carePlanID: nil) + versionB.effectiveDate = dateB + versionB = try store.updateContactAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(10)) + let query = OCKContactQuery(dateInterval: interval) + + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.name == versionB.name) + } + + func testContactQueryBeforeContactWasCreatedReturnsNoResults() throws { + let dateA = Date() + try store.addContactAndWait(OCKContact(id: "A", givenName: "a", familyName: "b", carePlanID: nil)) + let interval = DateInterval(start: dateA.addingTimeInterval(-100), end: dateA) + let query = OCKContactQuery(dateInterval: interval) + let fetched = try store.fetchContactsAndWait(query: query) + XCTAssertTrue(fetched.isEmpty) + } + + // MARK: Deletion + + func testDeleteContact() throws { + let contact = try store.addContactAndWait(OCKContact(id: "contact", givenName: "Christopher", familyName: "Foss", carePlanID: nil)) + try store.deleteContactAndWait(contact) + let fetched = try store.fetchContactsAndWait() + XCTAssert(fetched.isEmpty) + } + + func testDeleteContactfailsIfContactDoesntExist() { + let contact = OCKContact(id: "contact", givenName: "Amy", familyName: "Frost", carePlanID: nil) + XCTAssertThrowsError(try store.deleteContactAndWait(contact)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Notes.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Notes.swift new file mode 100755 index 0000000..575b4b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Notes.swift @@ -0,0 +1,108 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestStoreNotes: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + func testCanAttachNotesToPatient() throws { + var patient = OCKPatient(id: "Mr. John", givenName: "John", familyName: "Appleseed") + patient.notes = [OCKNote(author: "Johnny", title: "My Diary", content: "Today I studied biochemistry!")] + let savedPatient = try store.addPatientAndWait(patient) + XCTAssert(savedPatient.notes?.count == 1) + } + + func testCanAttachNotesToCarePlan() throws { + var plan = OCKCarePlan(id: "obesity", title: "Obesity", patientID: nil) + plan.notes = [OCKNote(author: "Mariana", title: "Refrigerator Notes", content: "Butter, milk, eggs")] + let savedPlan = try store.addCarePlanAndWait(plan) + XCTAssert(savedPlan.notes?.count == 1) + } + + func testCanAttachNotesToTask() throws { + let schedule = OCKSchedule.dailyAtTime(hour: 06, minutes: 0, start: Date(), end: nil, text: nil) + var task = OCKTask(id: "id123", title: "prayer", carePlanID: nil, schedule: schedule) + task.notes = [OCKNote(author: "Jared", title: "Note", content: "Made some remarks")] + let savedTask = try store.addTaskAndWait(task) + XCTAssert(savedTask.notes?.count == 1) + } + + func testCanAttachNotesToOutcome() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + var outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: []) + outcome.notes = [OCKNote(author: "Jared", title: "My Recipe", content: "Bacon, eggs, and cheese")] + let savedOutcome = try store.addOutcomeAndWait(outcome) + XCTAssert(savedOutcome.notes?.count == 1) + } + + func testCanAttachNotesToOutcomeValues() throws { + var task = OCKTask(id: "A", title: "A", carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task = try store.addTaskAndWait(task) + + var value = OCKOutcomeValue(10.0) + value.notes = [OCKNote(author: "Amy", title: "High Temperature", + content: "Stopped taking medication because it gave me a fever")] + let outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: [value]) + let savedOutcome = try store.addOutcomeAndWait(outcome) + XCTAssertNotNil(savedOutcome.values.first?.notes?.first) + } + + func testCanSaveNotesOnNotes() throws { + var note = OCKNote(author: "Mr. A", title: "Title A", content: "Content A") + note.notes = [OCKNote(author: "Mr. B", title: "Title B", content: "Content B")] + var patient = OCKPatient(id: "johnny", givenName: "John", familyName: "Appleseed") + patient.notes = [note] + let savedPatient = try store.addPatientAndWait(patient) + XCTAssertNotNil(savedPatient.notes?.first?.notes?.first) + } + + func testPersistedNotesHaveTimeZones() throws { + let note = OCKNote(author: "Mr. A", title: "Title A", content: "Content A") + var patient = OCKPatient(id: "johnny", givenName: "John", familyName: "Appleseed") + patient.notes = [note] + + let savedPatient = try store.addPatientAndWait(patient) + XCTAssert(savedPatient.timezone == TimeZone.current) + XCTAssert(savedPatient.notes?.first?.timezone == TimeZone.current) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Outcomes.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Outcomes.swift new file mode 100755 index 0000000..d00b07d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Outcomes.swift @@ -0,0 +1,246 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestStoreOutcomes: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: Insertion + + func testAddAndFetchOutcomes() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + let value = OCKOutcomeValue(42) + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [value]) + outcome = try store.addOutcomeAndWait(outcome) + let outcomes = try store.fetchOutcomesAndWait() + XCTAssert(outcomes == [outcome]) + XCTAssertNotNil(outcomes.first?.localDatabaseID) + XCTAssertNotNil(outcomes.first?.schemaVersion) + } + + func testTestOutcomeValueIndexIsPersisted() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + var value = OCKOutcomeValue(42) + value.index = 2 + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [value]) + outcome = try store.addOutcomeAndWait(outcome) + let outcomes = try store.fetchOutcomesAndWait() + XCTAssert(outcomes.first?.values.first?.index == 2) + } + + func testAddOutcomeToTask() throws { + var task = OCKTask(id: "task", title: "My Task", carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task = try store.addTaskAndWait(task) + let taskID = try task.getLocalID() + + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 2, values: []) + outcome = try store.addOutcomeAndWait(outcome) + XCTAssert(outcome.taskID == taskID) + } + + func testTwoOutcomesWithoutSameTaskIDAndOccurrenceIndexCannotBeAdded() throws { + var task = OCKTask(id: "task", title: "My Task", carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task = try store.addTaskAndWait(task) + let taskID = try task.getLocalID() + + let outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 2, values: []) + XCTAssertThrowsError(try store.addOutcomesAndWait([outcome, outcome])) + } + + func testCannotAddOutcomeToCoveredRegionOfPreviousTaskVersion() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let schedule = OCKSchedule.mealTimesEachDay(start: thisMorning, end: nil) + let task = OCKTask(id: "meds", title: "Medications", carePlanID: nil, schedule: schedule) + let taskV1 = try store.addTaskAndWait(task) + let taskV2 = try store.updateTaskAndWait(task) + let value = OCKOutcomeValue(123) + let outcome = OCKOutcome(taskID: try taskV1.getLocalID(), taskOccurrenceIndex: 1, values: [value]) + XCTAssert(taskV2.previousVersionID == taskV1.localDatabaseID) + XCTAssertThrowsError(try store.addOutcomeAndWait(outcome)) + } + + func testCannotUpdateOutcomeToCoveredRegionOfPreviousTaskVersion() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let tomorrowMorning = Calendar.current.date(byAdding: .day, value: 1, to: thisMorning)! + let schedule = OCKSchedule.mealTimesEachDay(start: thisMorning, end: nil) + + var task = OCKTask(id: "meds", title: "Medications", carePlanID: nil, schedule: schedule) + let taskV1 = try store.addTaskAndWait(task) + + task.effectiveDate = tomorrowMorning + try store.updateTaskAndWait(task) + + let value = OCKOutcomeValue(123) + var outcome = OCKOutcome(taskID: try taskV1.getLocalID(), taskOccurrenceIndex: 0, values: [value]) + outcome = try store.addOutcomeAndWait(outcome) + outcome.taskOccurrenceIndex = 8 + XCTAssertThrowsError(try store.updateOutcomeAndWait(outcome)) + } + + // MARK: Querying + + func testOutcomeQueryGroupIdentifier() throws { + var task = OCKTask(id: "abc", title: "ABC", carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task = try store.addTaskAndWait(task) + let value = OCKOutcomeValue(42) + var outcomeA = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: [value]) + outcomeA.groupIdentifier = "A" + var outcomeB = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 1, values: [value]) + outcomeB.groupIdentifier = "B" + try store.addOutcomesAndWait([outcomeA, outcomeB]) + var query = OCKOutcomeQuery(for: Date()) + query.groupIdentifiers = ["A"] + let fetched = try store.fetchOutcomesAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.taskOccurrenceIndex == 0) + } + + func testQueryReturnsOnlyOutcomesInTheQueryDateRange() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + var task = OCKTask(id: "exercise", title: "Push Ups", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + let taskID = try task.getLocalID() + + let date1 = task.schedule[0].start.addingTimeInterval(-10) + let date2 = task.schedule[1].start.addingTimeInterval(-10) + let interval = DateInterval(start: date1, end: date2) + let outcome1 = try store.addOutcomeAndWait(OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [])) + let outcome2 = try store.addOutcomeAndWait(OCKOutcome(taskID: taskID, taskOccurrenceIndex: 1, values: [])) + var query = OCKOutcomeQuery(dateInterval: interval) + query.taskIDs = [task.id] + let outcomes = try store.fetchOutcomesAndWait(query: query) + XCTAssert(outcomes.count == 1) + XCTAssertTrue(outcomes.contains(outcome1)) + XCTAssertFalse(outcomes.contains(outcome2)) + } + + func testOutcomeQueryLimit() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + let outcomeA = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [OCKOutcomeValue(10)]) + let outcomeB = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 1, values: [OCKOutcomeValue(20)]) + try store.addOutcomesAndWait([outcomeA, outcomeB]) + var query = OCKOutcomeQuery(for: Date()) + query.limit = 1 + let fetched = try store.fetchOutcomesAndWait(query: query) + XCTAssert(fetched.count == 1) + } + + func testQueryOutcomesByRemoteID() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: []) + outcome.remoteID = "abc" + outcome = try store.addOutcomeAndWait(outcome) + + var query = OCKOutcomeQuery() + query.remoteIDs = ["abc"] + + let fetched = try store.fetchOutcomesAndWait(query: query).first + XCTAssert(fetched == outcome) + } + + func testQueryOutcomeByTaskRemoteID() throws { + var task = OCKTask(id: "A", title: nil, carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task.remoteID = "abc" + task = try store.addTaskAndWait(task) + + var outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: []) + outcome = try store.addOutcomeAndWait(outcome) + + var query = OCKOutcomeQuery(for: Date()) + query.taskRemoteIDs = ["abc"] + let fetched = try store.fetchOutcomesAndWait(query: query).first + XCTAssert(fetched == outcome) + } + + // MARK: Updating + + func testUpdateOutcomes() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + let outcomeA = try store.addOutcomeAndWait(OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [])) + let outcomeB = try store.updateOutcomeAndWait(outcomeA) + XCTAssert(outcomeB.localDatabaseID == outcomeA.localDatabaseID) + } + + func testUpdateFailsForUnsavedOutcomes() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + let outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: []) + XCTAssertThrowsError(try store.updateOutcomeAndWait(outcome)) + } + + // MARK: Deletion + + func testDeleteOutcome() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let taskID = try task.getLocalID() + + let outcome = try store.addOutcomeAndWait(OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [])) + try store.deleteOutcomeAndWait(outcome) + let fetched = try store.fetchOutcomesAndWait() + XCTAssert(fetched.isEmpty) + } + + func testDeleteOutcomeFailsIfOutcomeDoesntExist() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "A", carePlanID: nil, schedule: schedule)) + let outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: []) + XCTAssertThrowsError(try store.deleteOutcomeAndWait(outcome)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Patients.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Patients.swift new file mode 100755 index 0000000..4f8e14b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Patients.swift @@ -0,0 +1,244 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +class TestStorePatients: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: Relationship Validation + + // MARK: Insertion + + func testAddPatient() throws { + let patient = try store.addPatientAndWait(OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost")) + XCTAssertNotNil(patient.localDatabaseID) + XCTAssertNotNil(patient.schemaVersion) + } + + func testAddPatientForAnyPatientBeyondTheFirstPatient() throws { + let patient1 = OCKPatient(id: "id1", givenName: "Amy", familyName: "Frost") + let patient2 = OCKPatient(id: "id2", givenName: "Christopher", familyName: "Foss") + try store.addPatientAndWait(patient1) + XCTAssertThrowsError(try store.addPatientAndWait(patient2)) + } + + func testAddPatientFailsIfIdentifierAlreadyExists() throws { + let patient1 = OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost") + let patient2 = OCKPatient(id: "myID", givenName: "Jared", familyName: "Gosler") + try store.addPatientAndWait(patient1) + XCTAssertThrowsError(try store.addPatientAndWait(patient2)) + } + + // MARK: Querying + + func testPatientQueryGroupIdentifierFiltersOutPatients() throws { + let patient = OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost") + try store.addPatientAndWait(patient) + var query = OCKPatientQuery(for: Date()) + query.groupIdentifiers = ["children"] + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(fetched.isEmpty) + } + + func testPatientQueryGroupIdentifierIncludesPatients() throws { + var patient = OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost") + patient.groupIdentifier = "children" + try store.addPatientAndWait(patient) + var query = OCKPatientQuery(for: Date()) + query.groupIdentifiers = ["children"] + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(!fetched.isEmpty) + } + + func testPatientQueryTagIncludesPatient() throws { + var patient = OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost") + patient.tags = ["A", "B"] + try store.addPatientAndWait(patient) + var query = OCKPatientQuery(for: Date()) + query.tags = ["B", "C"] + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(!fetched.isEmpty) + } + + func testPatientQueryTagExcludesPatient() throws { + var patient = OCKPatient(id: "myID", givenName: "Amy", familyName: "Frost") + patient.tags = ["A", "B"] + try store.addPatientAndWait(patient) + var query = OCKPatientQuery(for: Date()) + query.tags = ["C"] + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(fetched.isEmpty) + } + + func testPatientQueryWithNilIdentifiersReturnsAllPatients() throws { + let patientA = OCKPatient(id: "A", givenName: "Amy", familyName: "Frost") + let patientB = OCKPatient(id: "B", givenName: "Christopher", familyName: "Foss") + let patientC = OCKPatient(id: "C", givenName: "Jared", familyName: "Gosler") + let patientD = OCKPatient(id: "D", givenName: "Joyce", familyName: "Sohn") + let patientE = OCKPatient(id: "E", givenName: "Lauren", familyName: "Trottier") + let patientF = OCKPatient(id: "F", givenName: "Mariana", familyName: "Lin") + try store.addPatientsAndWait([patientA, patientB, patientC, patientD, patientE, patientF]) + let patients = try store.fetchPatientsAndWait(query: OCKPatientQuery()) + XCTAssert(patients.count == 6) + } + + func testQueryPatientByRemoteID() throws { + var patient = OCKPatient(id: "A", givenName: "B", familyName: "C") + patient.remoteID = "abc" + patient = try store.addPatientAndWait(patient) + var query = OCKPatientQuery(for: Date()) + query.remoteIDs = ["abc"] + let fetched = try store.fetchPatientsAndWait(query: query).first + XCTAssert(fetched == patient) + } + + func testBiologicalSexIsPersistedCorrectly() throws { + var patient = OCKPatient(id: "A", givenName: "Amy", familyName: "Frost") + patient.sex = .female + patient = try store.addPatientAndWait(patient) + patient = try store.fetchPatientAndWait(id: "A") + XCTAssert(patient.sex == .female) + } + + func testBirthdayIsPersistedCorrectly() throws { + let now = Date() + var patient = OCKPatient(id: "A", givenName: "Amy", familyName: "Frost") + patient.birthday = now + patient = try store.addPatientAndWait(patient) + patient = try store.fetchPatientAndWait(id: "A") + XCTAssert(patient.birthday == now) + } + + func testAllergiesArePersistedCorrectly() throws { + var patient = OCKPatient(id: "A", givenName: "Amy", familyName: "Frost") + patient.allergies = ["A", "B", "C"] + patient = try store.addPatientAndWait(patient) + patient = try store.fetchPatientAndWait(id: "A") + XCTAssert(patient.allergies == ["A", "B", "C"]) + } + + // MARK: Versioning + + func testUpdatePatientCreatesNewVersion() throws { + let patient = try store.addPatientAndWait(OCKPatient(id: "myID", givenName: "Chris", familyName: "Saari")) + let updatedPatient = try store.updatePatientAndWait(OCKPatient(id: "myID", givenName: "Chris", familyName: "Sillers")) + XCTAssert(updatedPatient.name.familyName == "Sillers") + XCTAssert(updatedPatient.previousVersionID == patient.localDatabaseID) + } + + func testUpdateFailsForUnsavedPatient() { + XCTAssertThrowsError(try store.updatePatientAndWait(OCKPatient(id: "myID", givenName: "Christoper", familyName: "Foss"))) + } + + func testPatientQueryWithNoDateOnlyReturnsLatestVersionOfAPatient() throws { + let versionA = try store.addPatientAndWait(OCKPatient(id: "A", givenName: "Jared", familyName: "Gosler")) + let versionB = try store.updatePatientAndWait(OCKPatient(id: "A", givenName: "John", familyName: "Appleseed")) + let fetched = try store.fetchPatientAndWait(id: versionA.id) + XCTAssert(fetched == versionB) + } + + func testPatientQueryOnPastDateReturnsPastVersionOfAPatient() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKPatient(id: "A", givenName: "Jared", familyName: "Gosler") + versionA.effectiveDate = dateA + versionA = try store.addPatientAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKPatient(id: "A", givenName: "John", familyName: "Appleseed") + versionB.effectiveDate = dateB + versionB = try store.updatePatientAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(-10)) + var query = OCKPatientQuery(dateInterval: interval) + query.ids = ["A"] + + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.name == versionA.name) + } + + func testPatientQuerySpanningVersionsReturnsNewestVersionOnly() throws { + let dateA = Date().addingTimeInterval(-100) + var versionA = OCKPatient(id: "A", givenName: "Jared", familyName: "Gosler") + versionA.effectiveDate = dateA + versionA = try store.addPatientAndWait(versionA) + + let dateB = Date().addingTimeInterval(100) + var versionB = OCKPatient(id: "A", givenName: "John", familyName: "Appleseed") + versionB.effectiveDate = dateB + versionB = try store.updatePatientAndWait(versionB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(10)) + var query = OCKPatientQuery(dateInterval: interval) + query.ids = ["A"] + + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssert(fetched.count == 1) + XCTAssert(fetched.first?.name == versionB.name) + } + + func testPatientQueryBeforePatientWasCreatedReturnsNoResults() throws { + let dateA = Date() + try store.addPatientAndWait(OCKPatient(id: "A", givenName: "Jared", familyName: "Gosler")) + + let interval = DateInterval(start: dateA.addingTimeInterval(-100), end: dateA) + var query = OCKPatientQuery(dateInterval: interval) + query.ids = ["A"] + + let fetched = try store.fetchPatientsAndWait(query: query) + XCTAssertTrue(fetched.isEmpty) + } + + // MARK: Deletion + + func testDeletePatient() throws { + let patient = try store.addPatientAndWait(OCKPatient(id: "myID", givenName: "John", familyName: "Appleseed")) + try store.deletePatientAndWait(patient) + let fetched = try store.fetchPatientsAndWait(query: OCKPatientQuery()) + XCTAssert(fetched.isEmpty) + } + + func testDeletePatientFailsIfPatientDoesntExist() { + XCTAssertThrowsError(try store.deletePatientAndWait(OCKPatient(id: "myID", givenName: "John", familyName: "Appleseed"))) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Tasks.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Tasks.swift new file mode 100755 index 0000000..75f3f1f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/OCKStore/TestStore+Tasks.swift @@ -0,0 +1,394 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import HealthKit +import XCTest + +class TestStoreTasks: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: Relationship Validation + + func testStorePreventsMissingPlanRelationshipOnTasks() { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = OCKTask(id: "medicine", title: "Advil", carePlanID: nil, schedule: schedule) + store.configuration.allowsEntitiesWithMissingRelationships = false + XCTAssertThrowsError(try store.addTaskAndWait(task)) + } + + func testStoreAllowsMissingPlanRelationshipOnTasks() { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = OCKTask(id: "medicine", title: "Advil", carePlanID: nil, schedule: schedule) + XCTAssertNoThrow(try store.addTaskAndWait(task)) + } + + // MARK: Insertion + + func testAddTask() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil, targetValues: [OCKOutcomeValue(11.1)]) + var task = OCKTask(id: "squats", title: "Front Squats", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + XCTAssertNotNil(task.localDatabaseID) + XCTAssertNotNil(task.schemaVersion) + } + + func testScheduleDurationIsPersisted() throws { + let schedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: nil, duration: .seconds(123), targetValues: []) + var task = OCKTask(id: "lunges", title: "Lunges", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + XCTAssert(task.schedule.elements.allSatisfy { $0.duration == .seconds(123) }) + } + + func testAddTaskFailsIfIdentifierAlreadyExists() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = OCKTask(id: "exercise", title: "Push Ups", carePlanID: nil, schedule: schedule) + try store.addTaskAndWait(task) + XCTAssertThrowsError(try store.addTaskAndWait(task)) + } + + func testAllDaySchedulesArePersistedCorrectly() throws { + let element = OCKScheduleElement(start: Date(), end: nil, interval: DateComponents(day: 1), duration: .allDay) + let schedule = OCKSchedule(composing: [element]) + var task = OCKTask(id: "benadryl", title: "Benadryl", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + guard let fetchedElement = task.schedule.elements.first else { XCTFail("Bad schedule"); return } + XCTAssertTrue(fetchedElement.duration == .allDay) + } + + // MARK: Querying + + func testQueryTaskByIdentifier() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task1 = OCKTask(id: "squats", title: "Front Squats", carePlanID: nil, schedule: schedule) + let task2 = OCKTask(id: "lunges", title: "Forward Lunges", carePlanID: nil, schedule: schedule) + try store.addTasksAndWait([task1, task2]) + let tasks = try store.fetchTasksAndWait(query: OCKTaskQuery(id: task1.id)) + XCTAssert(tasks.count == 1) + XCTAssert(tasks.first?.id == task1.id) + } + + func testQueryTaskByCarePlanIdentifier() throws { + let carePlan = try store.addCarePlanAndWait(OCKCarePlan(id: "plan", title: "Plan", patientID: nil)) + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "Task", carePlanID: carePlan.localDatabaseID, schedule: schedule)) + var query = OCKTaskQuery() + query.carePlanIDs = [carePlan.id] + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched == [task]) + } + + func testQueryTaskByCarePlanVersionID() throws { + let carePlan = try store.addCarePlanAndWait(OCKCarePlan(id: "plan", title: "Plan", patientID: nil)) + guard let versionID = carePlan.localDatabaseID else { XCTFail("Missing versionID"); return } + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "A", title: "Task", carePlanID: carePlan.localDatabaseID, schedule: schedule)) + var query = OCKTaskQuery() + query.carePlanVersionIDs = [versionID] + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched == [task]) + } + + func testTaskQueryGroupIdentifier() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + var task1 = OCKTask(id: "squats", title: "Front Squats", carePlanID: nil, schedule: schedule) + let task2 = OCKTask(id: "lunges", title: "Forward Lunges", carePlanID: nil, schedule: schedule) + task1.groupIdentifier = "group1" + try store.addTasksAndWait([task1, task2]) + + let interval = DateInterval(start: Date(), end: Calendar.current.date(byAdding: .day, value: 2, to: Date())!) + var query = OCKTaskQuery(dateInterval: interval) + query.groupIdentifiers = ["group1"] + let tasks = try store.fetchTasksAndWait(query: query) + XCTAssert(tasks.count == 1) + XCTAssert(tasks.first?.id == task1.id) + } + + func testTaskQueryOrdered() throws { + let today = Calendar.current.startOfDay(for: Date()) + let schedule1 = OCKSchedule.mealTimesEachDay(start: today, end: nil) + let schedule2 = OCKSchedule.mealTimesEachDay(start: today, end: Calendar.current.date(byAdding: .day, value: 1, to: today)!) + let task1 = OCKTask(id: "aa", title: "aa", carePlanID: nil, schedule: schedule2) + let task2 = OCKTask(id: "bb", title: "bb", carePlanID: nil, schedule: schedule1) + let task3 = OCKTask(id: "cc", title: nil, carePlanID: nil, schedule: schedule2) + try store.addTasksAndWait([task1, task2, task3]) + + let interval = DateInterval(start: Date(), end: Calendar.current.date(byAdding: .day, value: 10, to: today)!) + var query = OCKTaskQuery(dateInterval: interval) + query.extendedSortDescriptors = [.title(ascending: true)] + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched.map { $0.title } == [nil, "aa", "bb"]) + } + + func testTaskQueryLimited() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task1 = OCKTask(id: "a", title: "a", carePlanID: nil, schedule: schedule) + let task2 = OCKTask(id: "b", title: "b", carePlanID: nil, schedule: schedule) + let task3 = OCKTask(id: "c", title: "c", carePlanID: nil, schedule: schedule) + try store.addTasksAndWait([task1, task2, task3]) + + let interval = DateInterval(start: Date(), end: Calendar.current.date(byAdding: .day, value: 2, to: Date())!) + var query = OCKTaskQuery(dateInterval: interval) + query.extendedSortDescriptors = [.title(ascending: true)] + query.limit = 1 + query.offset = 2 + + let tasks = try store.fetchTasksAndWait(query: query) + XCTAssert(tasks.count == 1) + XCTAssert(tasks.first?.id == task3.id) + } + + func testTaskQueryTags() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + var task1 = OCKTask(id: "a", title: "a", carePlanID: nil, schedule: schedule) + task1.tags = ["A"] + var task2 = OCKTask(id: "b", title: "b", carePlanID: nil, schedule: schedule) + task2.tags = ["A", "B"] + var task3 = OCKTask(id: "c", title: "c", carePlanID: nil, schedule: schedule) + task3.tags = ["A", "B", "C"] + try store.addTasksAndWait([task1, task2, task3]) + + let interval = DateInterval(start: Date(), end: Calendar.current.date(byAdding: .day, value: 2, to: Date())!) + var query = OCKTaskQuery(dateInterval: interval) + query.tags = ["B"] + query.extendedSortDescriptors = [.title(ascending: true)] + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched.map { $0.title } == ["b", "c"]) + } + + func testTaskQueryWithNilQueryReturnsAllTasks() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task1 = OCKTask(id: "a", title: "a", carePlanID: nil, schedule: schedule) + let task2 = OCKTask(id: "b", title: "b", carePlanID: nil, schedule: schedule) + let task3 = OCKTask(id: "c", title: "c", carePlanID: nil, schedule: schedule) + try store.addTasksAndWait([task1, task2, task3]) + let tasks = try store.fetchTasksAndWait(query: OCKTaskQuery()) + XCTAssert(tasks.count == 3) + } + + func testQueryTaskByRemoteID() throws { + var task = OCKTask(id: "A", title: nil, carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task.remoteID = "abc" + task = try store.addTaskAndWait(task) + + var query = OCKTaskQuery(for: Date()) + query.remoteIDs = ["abc"] + let fetched = try store.fetchTasksAndWait(query: query).first + XCTAssert(fetched == task) + } + + func testQueryTaskByCarePlanRemoteID() throws { + var plan = OCKCarePlan(id: "A", title: "B", patientID: nil) + plan.remoteID = "abc" + plan = try store.addCarePlanAndWait(plan) + + var task = OCKTask(id: "B", title: "C", carePlanID: plan.localDatabaseID, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task = try store.addTaskAndWait(task) + + var query = OCKTaskQuery(for: Date()) + query.carePlanRemoteIDs = ["abc"] + let fetched = try store.fetchTasksAndWait(query: query).first + XCTAssert(fetched == task) + } + // MARK: Versioning + + func testUpdateTaskCreateNewVersion() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule)) + let updatedTask = try store.updateTaskAndWait(OCKTask(id: "meds", title: "New Medication", carePlanID: nil, schedule: schedule)) + XCTAssert(updatedTask.title == "New Medication") + XCTAssert(updatedTask.previousVersionID == task.localDatabaseID) + } + + func testCanFetchEventsWhenCurrentTaskVersionStartsAtSameTimeOrEarlierThanThePreviousVersion() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let aFewDaysAgo = Calendar.current.date(byAdding: .day, value: -4, to: thisMorning)! + let manyDaysAgo = Calendar.current.date(byAdding: .day, value: -10, to: thisMorning)! + let scheduleV1 = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: manyDaysAgo, end: nil, text: nil) + let scheduleV2 = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: aFewDaysAgo, end: nil, text: nil) + let scheduleV3 = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: aFewDaysAgo, end: nil, text: nil) + + var nausea = OCKTask(id: "nausea", title: "V1", carePlanID: nil, schedule: scheduleV1) + let v1 = try store.addTaskAndWait(nausea) + XCTAssert(v1.effectiveDate == scheduleV1.startDate()) + + nausea.title = "V2" + nausea.schedule = scheduleV2 + nausea.effectiveDate = scheduleV2.startDate() + let v2 = try store.updateTaskAndWait(nausea) + XCTAssert(v2.effectiveDate == scheduleV2.startDate()) + + nausea.title = "V3" + nausea.schedule = scheduleV3 + nausea.effectiveDate = scheduleV3.startDate() + let v3 = try store.updateTaskAndWait(nausea) + XCTAssert(v3.effectiveDate == scheduleV3.startDate()) + + let query = OCKEventQuery(dateInterval: DateInterval(start: manyDaysAgo, end: thisMorning)) + let events = try store.fetchEventsAndWait(taskID: "nausea", query: query) + XCTAssert(events.count == 10, "Expected 10, but got \(events.count)") + XCTAssert(events.first?.task.title == "V1") + XCTAssert(events.last?.task.title == "V3") + } + + func testCannotUpdateTaskIfItResultsInImplicitDataLoss() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule)) + let outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 5, values: [OCKOutcomeValue(1)]) + try store.addOutcomesAndWait([outcome]) + XCTAssertThrowsError(try store.updateTaskAndWait(task)) + } + + func testCanUpdateTaskWithOutcomesIfDoesNotCauseDataLoss() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + var task = try store.addTaskAndWait(OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule)) + let outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 0, values: [OCKOutcomeValue(1)]) + try store.addOutcomesAndWait([outcome]) + task.effectiveDate = task.schedule[5].start + XCTAssertNoThrow(try store.updateTaskAndWait(task)) + } + + func testQueryUpdatedTasksEvents() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) // 7:30AM, 12:00PM, 5:30PM + let original = try store.addTaskAndWait(OCKTask(id: "meds", title: "Original", carePlanID: nil, schedule: schedule)) + + var updated = original + updated.effectiveDate = schedule[5].start // 5:30PM tomorrow + updated.title = "Updated" + updated = try store.updateTaskAndWait(updated) + let query = OCKEventQuery(for: schedule[5].start) // 0:00AM - 23:59.99PM tomorrow + let events = try store.fetchEventsAndWait(taskID: "meds", query: query) + + XCTAssert(events.count == 3) + XCTAssert(events[0].task.localDatabaseID == original.localDatabaseID) + XCTAssert(events[1].task.localDatabaseID == original.localDatabaseID) + XCTAssert(events[2].task.localDatabaseID == updated.localDatabaseID) + } + + func testUpdateFailsForUnsavedTasks() { + let task = OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + XCTAssertThrowsError(try store.updateTaskAndWait(task)) + } + + func testVersioningReturnsOldVersionForOldQueryRange() throws { + let today = Calendar.current.startOfDay(for: Date()) + let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)! + let lastWeek = Calendar.current.date(byAdding: .weekOfYear, value: -1, to: today)! + + let schedule1 = OCKSchedule.mealTimesEachDay(start: lastWeek, end: nil, targetValues: [OCKOutcomeValue(11.1)]) + let task1 = OCKTask(id: "squats", title: "Front Squats", carePlanID: nil, schedule: schedule1) + + let schedule2 = OCKSchedule.mealTimesEachDay(start: tomorrow, end: nil) + let task2 = OCKTask(id: "lunges", title: "Forward Lunges", carePlanID: nil, schedule: schedule2) + try store.addTasksAndWait([task1, task2]) + + let tasks = try store.fetchTasksAndWait(query: OCKTaskQuery(for: Date())) + XCTAssert(tasks.count == 1) + XCTAssert(tasks.first?.id == task1.id) + } + + func testTaskQueryOnPastDateReturnsPastVersionOfATask() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + + let dateA = Date().addingTimeInterval(-100) + var taskA = OCKTask(id: "A", title: "a", carePlanID: nil, schedule: schedule) + taskA.effectiveDate = dateA + taskA = try store.addTaskAndWait(OCKTask(id: "A", title: "a", carePlanID: nil, schedule: schedule)) + + let dateB = dateA.addingTimeInterval(100) + var taskB = OCKTask(id: "A", title: "b", carePlanID: nil, schedule: schedule) + taskB.effectiveDate = dateB + taskB = try store.updateTaskAndWait(taskB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(-10)) + let query = OCKTaskQuery(dateInterval: interval) + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched.count == 1, "Expected to get 1 task, but got \(fetched.count)") + XCTAssert(fetched.first?.title == taskA.title) + } + + func testTaskQueryStartingExactlyOnEffectiveDateOfNewVersion() throws { + let schedule = OCKSchedule.dailyAtTime(hour: 0, minutes: 0, start: Date(), end: nil, text: nil) + let query = OCKTaskQuery(dateInterval: DateInterval(start: schedule[5].start, end: schedule[5].end)) + + var task = try store.addTaskAndWait(OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule)) + task.effectiveDate = task.schedule[5].start + task = try store.updateTaskAndWait(task) + + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched.first == task) + } + + func testTaskQuerySpanningVersionsReturnsNewestVersionOnly() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + + let dateA = Date().addingTimeInterval(-100) + var taskA = OCKTask(id: "A", title: "a", carePlanID: nil, schedule: schedule) + taskA.effectiveDate = dateA + taskA = try store.addTaskAndWait(OCKTask(id: "A", title: "a", carePlanID: nil, schedule: schedule)) + + let dateB = Date().addingTimeInterval(100) + var taskB = OCKTask(id: "A", title: "b", carePlanID: nil, schedule: schedule) + taskB.effectiveDate = dateB + taskB = try store.updateTaskAndWait(taskB) + + let interval = DateInterval(start: dateA.addingTimeInterval(10), end: dateB.addingTimeInterval(10)) + let query = OCKTaskQuery(dateInterval: interval) + let fetched = try store.fetchTasksAndWait(query: query) + XCTAssert(fetched.count == 1, "Expected to get 1 task, but got \(fetched.count)") + XCTAssert(fetched.first?.title == taskB.title, "Expected title to be \(taskB.title ?? "nil"), but got \(fetched.first?.title ?? "nil")") + } + + // MARK: Deletion + + func testDeleteTask() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = try store.addTaskAndWait(OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule)) + try store.deleteTaskAndWait(task) + let fetched = try store.fetchTasksAndWait() + XCTAssert(fetched.isEmpty) + } + + func testDeleteTaskFailsIfTaskDoesntExist() { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = OCKTask(id: "meds", title: "Medication", carePlanID: nil, schedule: schedule) + XCTAssertThrowsError(try store.deleteTaskAndWait(task)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlan.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlan.swift new file mode 100755 index 0000000..a1c838c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlan.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestCarePlan: XCTestCase { + + func testBelongsToReturnsFalseWhenIDsDontMatch() { + let patient = OCKPatient(id: "A", givenName: "Mary", familyName: "Frost") + let plan = OCKCarePlan(id: "B", title: "obesity", patientID: nil) + XCTAssertFalse(plan.belongs(to: patient)) + } + + func testBelongsToReturnsTrueWHenIDsDoMatch() { + var patient = OCKPatient(id: "A", givenName: "Mary", familyName: "Frost") + patient.localDatabaseID = OCKLocalVersionID("abc") + let plan = OCKCarePlan(id: "B", title: "obesity", patientID: patient.localDatabaseID) + XCTAssertTrue(plan.belongs(to: patient)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlanQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlanQuery.swift new file mode 100755 index 0000000..c98c772 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestCarePlanQuery.swift @@ -0,0 +1,83 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +private struct MockQuery: OCKAnyCarePlanQuery { + + var ids: [String] = [] + var remoteIDs: [String] = [] + var groupIdentifiers: [String] = [] + var dateInterval: DateInterval? + var limit: Int? + var offset: Int = 0 + + var patientIDs: [String] = [] + var sortDescriptors: [OCKCarePlanSortDescriptor] = [] + + init() {} +} + +class TestCarePlanQuery: XCTestCase { + + func testSortOrderSetsExtendedSortOrder() { + var query = OCKCarePlanQuery() + query.sortDescriptors = [.title(ascending: true)] + XCTAssert(query.extendedSortDescriptors == [.title(ascending: true)]) + } + + func testExtendedSortOrderSetsSortOrder() { + var query = OCKCarePlanQuery() + query.extendedSortDescriptors = [.title(ascending: true)] + XCTAssert(query.sortDescriptors == [.title(ascending: true)]) + } + + func testInitializerCopiesOtherOCKCarePlanQueryExactly() { + var query1 = OCKCarePlanQuery() + query1.extendedSortDescriptors = [.effectiveDate(ascending: true)] + let query2 = OCKCarePlanQuery(query1) + XCTAssert(query1 == query2) + } + + func testInitializerCopiesIDsFromOtherPatientQuery() { + let query1 = MockQuery(id: "A") + let query2 = OCKCarePlanQuery(query1) + XCTAssert(query2.ids == ["A"]) + } + + func testInitializerCopiesSortOrderFromOtherPatientQuery() { + var query1 = MockQuery() + query1.sortDescriptors = [.title(ascending: true)] + let query2 = OCKCarePlanQuery(query1) + XCTAssert(query2.sortDescriptors == [.title(ascending: true)]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContact.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContact.swift new file mode 100755 index 0000000..61761ed --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContact.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestContact: XCTestCase { + + func testBelongsToReturnsFalseWhenIDsDontMatch() { + let plan = OCKCarePlan(id: "A", title: "Medication", patientID: nil) + let contact = OCKContact(id: "B", givenName: "Mary", familyName: "Frost", carePlanID: nil) + XCTAssertFalse(contact.belongs(to: plan)) + } + + func testBelongsToReturnsTrueWhenIDsDoMatach() { + var plan = OCKCarePlan(id: "A", title: "Medication", patientID: nil) + plan.localDatabaseID = OCKLocalVersionID("abc") + let contact = OCKContact(id: "B", givenName: "Mary", familyName: "Frost", carePlanID: plan.localDatabaseID) + XCTAssertTrue(contact.belongs(to: plan)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContactQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContactQuery.swift new file mode 100755 index 0000000..905765f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestContactQuery.swift @@ -0,0 +1,82 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +private struct MockQuery: OCKAnyContactQuery { + var ids: [String] = [] + var remoteIDs: [String] = [] + var groupIdentifiers: [String] = [] + var dateInterval: DateInterval? + var limit: Int? + var offset: Int = 0 + + var carePlanIDs: [String] = [] + var sortDescriptors: [OCKContactSortDescriptor] = [] + + init() {} +} + +class TestContactQuery: XCTestCase { + + func testSortOrderSetsExtendedSortOrder() { + var query = OCKContactQuery() + query.sortDescriptors = [.givenName(ascending: true)] + XCTAssert(query.extendedSortDescriptors == [.givenName(ascending: true)]) + } + + func testExtendedSortOrderSetsSortOrder() { + var query = OCKContactQuery() + query.extendedSortDescriptors = [.givenName(ascending: true)] + XCTAssert(query.sortDescriptors == [.givenName(ascending: true)]) + } + + func testInitializerCopiesOtherOCKContactQueryExactly() { + var query1 = OCKContactQuery() + query1.extendedSortDescriptors = [.effectiveDate(ascending: true)] + let query2 = OCKContactQuery(query1) + XCTAssert(query1 == query2) + } + + func testInitializerCopiesIDsFromOtherPatientQuery() { + let query1 = MockQuery(id: "A") + let query2 = OCKContactQuery(query1) + XCTAssert(query2.ids == ["A"]) + } + + func testInitializerCopiesSortOrderFromOtherPatientQuery() { + var query1 = MockQuery() + query1.sortDescriptors = [.givenName(ascending: true)] + let query2 = OCKContactQuery(query1) + XCTAssert(query2.sortDescriptors == [.givenName(ascending: true)]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcome.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcome.swift new file mode 100755 index 0000000..d17bafb --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcome.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestOutcome: XCTestCase { + + func testBelongsToReturnsFalseIfTaskIDsDontMatch() { + let outcome = OCKOutcome(taskID: OCKLocalVersionID("abc"), taskOccurrenceIndex: 0, values: []) + let task = OCKTask(id: "medicine", title: nil, carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + XCTAssert(outcome.belongs(to: task) == false) + } + + func testBelongsToReturnsTrueIfTasksIDsDoMatch() { + let outcome = OCKOutcome(taskID: OCKLocalVersionID("abc"), taskOccurrenceIndex: 0, values: []) + var task = OCKTask(id: "medicine", title: nil, carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + task.localDatabaseID = OCKLocalVersionID("abc") + XCTAssert(outcome.belongs(to: task)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeQuery.swift new file mode 100755 index 0000000..aacccc5 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeQuery.swift @@ -0,0 +1,82 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +private struct MockQuery: OCKAnyOutcomeQuery { + var ids: [String] = [] + var remoteIDs: [String] = [] + var groupIdentifiers: [String] = [] + var dateInterval: DateInterval? + var limit: Int? + var offset: Int = 0 + + var taskIDs: [String] = [] + var sortDescriptors: [OCKOutcomeSortDescriptor] = [] + + init() {} +} + +class TestOutcomeQuery: XCTestCase { + + func testSortOrderSetsExtendedSortOrder() { + var query = OCKOutcomeQuery() + query.sortDescriptors = [.date(ascending: true)] + XCTAssert(query.extendedSortDescriptors == [.date(ascending: true)]) + } + + func testExtendedSortOrderSetsSortOrder() { + var query = OCKOutcomeQuery() + query.extendedSortDescriptors = [.date(ascending: true)] + XCTAssert(query.sortDescriptors == [.date(ascending: true)]) + } + + func testInitializerCopiesOtherOCKOutcomeQueryExactly() { + var query1 = OCKOutcomeQuery() + query1.extendedSortDescriptors = [.date(ascending: true)] + let query2 = OCKOutcomeQuery(query1) + XCTAssert(query1 == query2) + } + + func testInitializerCopiesIDsFromOtherPatientQuery() { + let query1 = MockQuery(id: "A") + let query2 = OCKOutcomeQuery(query1) + XCTAssert(query2.ids == ["A"]) + } + + func testInitializerCopiesSortOrderFromOtherPatientQuery() { + var query1 = MockQuery() + query1.sortDescriptors = [.date(ascending: true)] + let query2 = OCKOutcomeQuery(query1) + XCTAssert(query2.sortDescriptors == [.date(ascending: true)]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeValue.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeValue.swift new file mode 100755 index 0000000..5656c86 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestOutcomeValue.swift @@ -0,0 +1,161 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestOutcomeValue: XCTestCase { + func testValueInitializer() { + var value = OCKOutcomeValue(37, units: "˚C") + XCTAssert(value.type == .integer) + XCTAssert(value.integerValue == 37) + + value.value = 98.3 + value.units = "˚F" + XCTAssert(value.type == .double) + XCTAssert(value.doubleValue == 98.3) + } + + func testValueEqualityUnique() { + let beforeAfterValuePairs: [(OCKOutcomeValueUnderlyingType, OCKOutcomeValueUnderlyingType)] = [ + (37, 29), + (22.3, 24.5), + (true, false), + ("dog", "cat"), + ("old".data(using: .utf8)!, "new".data(using: .utf8)!), + (Date(), Date().addingTimeInterval(10)) + ] + + for (before, after) in beforeAfterValuePairs { + let value1 = OCKOutcomeValue(before) + let value2 = OCKOutcomeValue(after) + XCTAssert(value1 != value2) + } + } + + func testValueEqualityForIdenticalEntries() { + let date = Date() + let beforeAfterValuePairs: [(OCKOutcomeValueUnderlyingType, OCKOutcomeValueUnderlyingType)] = [ + (37, 37), + (22.3, 22.3), + (true, true), + ("dog", "dog"), + ("test".data(using: .utf8)!, "test".data(using: .utf8)!), + (date, date) + ] + + for (left, right) in beforeAfterValuePairs { + let value1 = OCKOutcomeValue(left) + let value2 = OCKOutcomeValue(right) + XCTAssert(value1 == value2) + } + } + + func testCodingForSingleEntry() { + let beforeAfterValuePairs: [(OCKOutcomeValueUnderlyingType, OCKOutcomeValueUnderlyingType)] = [ + (37, 29), + (22.3, 24.5), + (true, false), + ("dog", "cat"), + ("old".data(using: .utf8)!, "new".data(using: .utf8)!), + (Date(), Date().addingTimeInterval(10)) + ] + + for (before, after) in beforeAfterValuePairs { + let value1 = OCKOutcomeValue(before) + let value2 = OCKOutcomeValue(after) + testPreservationOfCodingHelper(outcome: value1) + testPreservationOfCodingHelper(outcome: value2) + + testEqualityOfEncodings(outcome1: value1, outcome2: value1) + testEqualityOfEncodings(outcome1: value2, outcome2: value2) + } + } + + func testCodingForIdenticalEntries() { + let date = Date() + let beforeAfterValuePairs: [(OCKOutcomeValueUnderlyingType, OCKOutcomeValueUnderlyingType)] = [ + (37, 37), + (22.3, 22.3), + (true, true), + ("dog", "dog"), + ("test".data(using: .utf8)!, "test".data(using: .utf8)!), + (date, date) + ] + + for (left, right) in beforeAfterValuePairs { + let value1 = OCKOutcomeValue(left) + let value2 = OCKOutcomeValue(right) + testEqualityOfEncodings(outcome1: value1, outcome2: value2) + } + } + + func testEvolvingValue() { + var value = OCKOutcomeValue("abc") + let oldType = value.type + value.value = false + XCTAssert(oldType != value.type) + XCTAssert(oldType == .text) + XCTAssert(value.type == .boolean) + + value.value = Date() + XCTAssert(value.type == .date) + + value.value = 10.0 + XCTAssert(value.type == .double) + + value.value = Int(10) + XCTAssert(value.type == .integer) + } + + func testEqualityOfEncodings(outcome1: OCKOutcomeValue, outcome2: OCKOutcomeValue) { + let encoder = JSONEncoder() + do { + let encoded1 = try encoder.encode(outcome1) + let encoded2 = try encoder.encode(outcome2) + XCTAssert(encoded1 == encoded2, "OCKOutcomeValue encoding inequality") + } catch { + XCTFail("unable to encoder or decode OCKOutcomeValue") + } + } + + func testPreservationOfCodingHelper(outcome: OCKOutcomeValue) { + let encoder = JSONEncoder() + let decoder = JSONDecoder() + do { + let encoded = try encoder.encode(outcome) + let decoded = try decoder.decode(OCKOutcomeValue.self, from: encoded) + XCTAssert(decoded == outcome, "OCKOutcomeValue not preserved in coding") + testEqualityOfEncodings(outcome1: outcome, outcome2: decoded) + } catch { + XCTFail("unable to encode or decode OCKOutcomeValue") + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatient.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatient.swift new file mode 100755 index 0000000..b07bfd0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatient.swift @@ -0,0 +1,44 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation +import XCTest + +class TestPatient: XCTestCase { + + func testPatientAge() { + var patient = OCKPatient(id: "A", givenName: "Amy", familyName: "Frost") + XCTAssertNil(patient.age) + + patient.birthday = Calendar.current.date(byAdding: .year, value: -50, to: Date()) + XCTAssert(patient.age == 50) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatientQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatientQuery.swift new file mode 100755 index 0000000..291a3e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestPatientQuery.swift @@ -0,0 +1,81 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +private struct MockQuery: OCKAnyPatientQuery { + var ids: [String] = [] + var remoteIDs: [String] = [] + var groupIdentifiers: [String] = [] + var dateInterval: DateInterval? + var limit: Int? + var offset: Int = 0 + + var sortDescriptors: [OCKPatientSortDescriptor] = [] + + init() {} +} + +class TestPatientQuery: XCTestCase { + + func testSortOrderSetsExtendedSortOrder() { + var query = OCKPatientQuery() + query.sortDescriptors = [.givenName(ascending: true)] + XCTAssert(query.extendedSortDescriptors == [.givenName(ascending: true)]) + } + + func testExtendedSortOrderSetsSortOrder() { + var query = OCKPatientQuery() + query.extendedSortDescriptors = [.givenName(ascending: true)] + XCTAssert(query.sortDescriptors == [.givenName(ascending: true)]) + } + + func testInitializerCopiesOtherOCKPatientQueryExactly() { + var query1 = OCKPatientQuery() + query1.extendedSortDescriptors = [.effectiveDate(ascending: true)] + let query2 = OCKPatientQuery(query1) + XCTAssert(query1 == query2) + } + + func testInitializerCopiesIDsFromOtherPatientQuery() { + let query1 = MockQuery(id: "A") + let query2 = OCKPatientQuery(query1) + XCTAssert(query2.ids == ["A"]) + } + + func testInitializerCopiesSortOrderFromOtherPatientQuery() { + var query1 = MockQuery() + query1.sortDescriptors = [.givenName(ascending: true)] + let query2 = OCKPatientQuery(query1) + XCTAssert(query2.sortDescriptors == [.givenName(ascending: true)]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSchedule.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSchedule.swift new file mode 100755 index 0000000..eab384d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSchedule.swift @@ -0,0 +1,220 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import XCTest + +class TestSchedule: XCTestCase { + func testScheduleCreatedFromElementsIsEqualToThatSchedulesElements() { + let spacing = DateComponents(day: 1) + let element = OCKScheduleElement(start: Date(), end: nil, interval: spacing, text: nil, targetValues: []) + let schedule = OCKSchedule(composing: [element]) + XCTAssert(schedule.elements == [element], "The schedule elements was not equal to the elements that created it") + } + + func testDailySchedule() { + let schedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: nil) + for index in 0..<5 { + XCTAssert(schedule[index].start == Calendar.current.date(byAdding: DateComponents(day: index), to: schedule.startDate())) + } + } + + func testDailyScheduleOccurrenceIndices() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let threeDaysFromNow = Calendar.current.date(byAdding: .day, value: 3, to: thisMorning)! + let schedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: thisMorning, end: nil, text: nil) + let events = schedule.events(from: thisMorning, to: threeDaysFromNow) + XCTAssert(events.count == 3) + XCTAssert(events[0].occurrence == 0) + XCTAssert(events[1].occurrence == 1) + XCTAssert(events[2].occurrence == 2) + } + + func testAllDayEventsCapturedByEventsBetweenDates() { + let morning = Calendar.current.startOfDay(for: Date()) + let breakfast = Calendar.current.date(byAdding: .hour, value: 7, to: morning)! + let lunch = Calendar.current.date(byAdding: .hour, value: 12, to: morning)! + let dinner = Calendar.current.date(byAdding: .hour, value: 18, to: morning)! + let allDay = OCKScheduleElement(start: breakfast, end: nil, interval: DateComponents(day: 1), text: "Daily", duration: .allDay) + let schedule = OCKSchedule(composing: [allDay]) + let events = schedule.events(from: lunch, to: dinner) + XCTAssert(events.count == 1, "Expected 1 all day event, but got \(events.count)") + } + + func testWeeklySchedule() { + let schedule = OCKSchedule.weeklyAtTime(weekday: 1, hours: 0, minutes: 0, start: Date(), end: nil, targetValues: [], text: nil) + for index in 0..<5 { + XCTAssert(schedule[index].start == Calendar.current.date(byAdding: DateComponents(weekOfYear: index), to: schedule.startDate())) + } + } + + func testScheduleComposition() { + let components = DateComponents(year: 2_019, month: 1, day: 19, hour: 15, minute: 30) + let startDate = Calendar.current.date(from: components)! + let scheduleA = OCKSchedule.mealTimesEachDay(start: startDate, end: nil) + let scheduleB = OCKSchedule.mealTimesEachDay(start: startDate, end: nil) + let schedule = OCKSchedule(composing: [scheduleA, scheduleB]) + XCTAssert(schedule.elements.count == 6) + } + + func testStartDate() { + let earlyDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())! + let lateDate = Calendar.current.date(byAdding: .day, value: 1, to: Date())! + let scheduleA = OCKSchedule.dailyAtTime(hour: 10, minutes: 0, start: earlyDate, end: nil, text: nil) + let scheduleB = OCKSchedule.dailyAtTime(hour: 11, minutes: 0, start: lateDate, end: nil, text: nil) + let schedule = OCKSchedule(composing: [scheduleA, scheduleB]) + XCTAssert(schedule.startDate() == scheduleA.startDate()) + } + + func testEndDateIsNilIfAnyComponentHasANilStartDate() { + let earlyDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())! + let lateDate = Calendar.current.date(byAdding: .day, value: 1, to: Date())! + let scheduleA = OCKSchedule.dailyAtTime(hour: 10, minutes: 0, start: earlyDate, end: lateDate, text: nil) + let scheduleB = OCKSchedule.dailyAtTime(hour: 11, minutes: 0, start: lateDate, end: nil, text: nil) + let schedule = OCKSchedule(composing: [scheduleA, scheduleB]) + XCTAssert(schedule.endDate() == nil) + } + + func testEndDateIsNonNilAndMatchesLatestEndDateIfAllComponentsHaveFiniteEndDate() { + let earlyDate = Calendar.current.date(byAdding: .day, value: -1, to: Date())! + let lateDate = Calendar.current.date(byAdding: .day, value: 1, to: Date())! + let laterDate = Calendar.current.date(byAdding: .day, value: 2, to: Date())! + let scheduleA = OCKSchedule.dailyAtTime(hour: 10, minutes: 0, start: earlyDate, end: lateDate, text: nil) + let scheduleB = OCKSchedule.dailyAtTime(hour: 11, minutes: 0, start: earlyDate, end: laterDate, text: nil) + let schedule = OCKSchedule(composing: [scheduleA, scheduleB]) + XCTAssert(schedule.endDate() == scheduleB.endDate()) + XCTAssertNotNil(schedule.endDate()) + } + + func testScheduleOffset() { + let date = Date() + let originalSchedule = OCKSchedule.dailyAtTime(hour: 0, minutes: 0, start: date, end: nil, text: nil) + let offsetSchedule = originalSchedule.offset(by: DateComponents(hour: 1)) + let expectedSchedule = OCKSchedule.dailyAtTime(hour: 1, minutes: 0, start: date, end: nil, text: nil) + XCTAssert(offsetSchedule == expectedSchedule) + } + + func testScheduleEventsAreSortedByDate() { + let startDate = Date() + let endDate = Calendar.current.date(byAdding: .day, value: 10, to: startDate)! + + let scheduleA = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: startDate, end: nil, text: nil) + let scheduleB = OCKSchedule.mealTimesEachDay(start: startDate, end: nil) + let schedule = OCKSchedule(composing: [scheduleA, scheduleB]) + + let events = schedule.events(from: startDate, to: endDate) + for index in 0.. 3 { + XCTAssert(events[index] == nil) + } + } + } + + func testEventsBetweenDatesIncludesEventsThatStartedBeforeTheStartDateButAreAllDayEvents() { + let allDayElement = OCKScheduleElement(start: Calendar.current.startOfDay(for: Date()), end: nil, + interval: DateComponents(weekOfYear: 1), duration: .allDay) + + let afternoon = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60 * 12) // 12:00 + let evening = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60 * 20) // 20:00 + let events = allDayElement.events(from: afternoon, to: evening) + XCTAssert(events.count == 1, "Expected 1 event, but got: \(events.count)") + } + + func testEventsBetweenDatesIncludesEventsThatStartAfterTheEndDateButAreAllDayEvents() { + let morning = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60 * 6) // 06:00 + let afternoon = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60 * 12) // 12:00 + let evening = Calendar.current.startOfDay(for: Date()).addingTimeInterval(60 * 60 * 20) // 20:00 + + let allDayElement = OCKScheduleElement(start: evening, end: nil, + interval: DateComponents(weekOfYear: 1), duration: .allDay) + + let events = allDayElement.events(from: morning, to: afternoon) + XCTAssert(events.count == 1, "Expected 1 event, but got: \(events.count)") + } + + func testEventsBetweenDatesIncludeEventsWithMultidayDurationsThatStartedOnPreviousDays() { + let morning = Calendar.current.startOfDay(for: Date()) + let element = OCKScheduleElement(start: morning, end: nil, interval: DateComponents(day: 7), duration: .hours(24 * 3)) + let twoDaysLater = Calendar.current.date(byAdding: .day, value: 2, to: morning)! + let fourDaysLater = Calendar.current.date(byAdding: .day, value: 4, to: morning)! + let events = element.events(from: twoDaysLater, to: fourDaysLater) + XCTAssert(events.count == 1, "Expected 1 event, but got: \(events.count)") + } + + func testEventsBetweenDatesCanOverlap() { + let morning = Calendar.current.startOfDay(for: Date()) + let element = OCKScheduleElement(start: morning, end: nil, interval: DateComponents(hour: 1), duration: .hours(2)) + let queryStart = morning.addingTimeInterval(60 * 60 * 1.5) + let queryEnd = queryStart.addingTimeInterval(1) + let events = element.events(from: queryStart, to: queryEnd) + XCTAssert(events.count == 2) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestScheduleEvent.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestScheduleEvent.swift new file mode 100755 index 0000000..d2a8816 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestScheduleEvent.swift @@ -0,0 +1,71 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestScheduleEvent: XCTestCase { + func testComparisonOperator() { + let element = OCKScheduleElement(start: Date(), end: nil, interval: DateComponents(year: 1), + text: nil, targetValues: []) + XCTAssert(element[0] < element[1]) + } + + func testStartDateEndDateForEventWithNoDuration() { + let startDate = Date() + let endDate = Calendar.current.date(byAdding: .day, value: 7, to: startDate)! + let interval = DateComponents(day: 1) + let element = OCKScheduleElement(start: startDate, end: endDate, interval: interval, + text: nil, targetValues: []) + let event = element[0] + XCTAssert(event.start == event.end) + } + + func testStartDateEndDateForEventWithDuration() { + let startDate = Date() + let endDate = Calendar.current.date(byAdding: .day, value: 7, to: startDate)! + let interval = DateComponents(day: 1) + let element = OCKScheduleElement(start: startDate, end: endDate, interval: interval, + text: nil, targetValues: [], duration: .seconds(100)) + let event = element[0] + XCTAssert(event.end == event.start.addingTimeInterval(100)) + } + + func testStartDateEndDateForEventWithAllDayDuration() { + let startDate = Date() + let endDate = Calendar.current.date(byAdding: .day, value: 7, to: startDate)! + let interval = DateComponents(day: 1) + let element = OCKScheduleElement(start: startDate, end: endDate, interval: interval, + text: nil, targetValues: [], duration: .allDay) + let event = element[0] + XCTAssert(event.start == Calendar.current.startOfDay(for: startDate)) + XCTAssert(event.end == Calendar.current.date(byAdding: DateComponents(day: 1, second: -1), to: event.start)!) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSemanticVersion.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSemanticVersion.swift new file mode 100755 index 0000000..67a01d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestSemanticVersion.swift @@ -0,0 +1,130 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKitStore +import Foundation +import XCTest + +class TestSemanticVersion: XCTestCase { + func testCorrectlyParsesMajorVersion() throws { + let version = try OCKSemanticVersion.parse("3.0.1") + XCTAssert(version.majorVersion == 3) + } + + func testCorrectlyParsesMinorVersion() throws { + let version = try OCKSemanticVersion.parse("3.0.1") + XCTAssert(version.minorVersion == 0) + } + + func testCorrectlyParsesPatchVersion() throws { + let version = try OCKSemanticVersion.parse("3.0.1") + XCTAssert(version.patchNumber == 1) + } + + func testCorrectlyParsesImpliedMinorVersion() throws { + let version = try OCKSemanticVersion.parse("4") + XCTAssert(version.majorVersion == 4) + XCTAssert(version.minorVersion == 0) + XCTAssert(version.patchNumber == 0) + } + + func testCorrectlyParsesImpliedPatchNumber() throws { + let version = try OCKSemanticVersion.parse("4.3") + XCTAssert(version.majorVersion == 4) + XCTAssert(version.minorVersion == 3) + XCTAssert(version.patchNumber == 0) + } + + func testEquatability() { + let versionA = OCKSemanticVersion(majorVersion: 1, minorVersion: 0, patchNumber: 0) + let versionB = OCKSemanticVersion(majorVersion: 1, minorVersion: 0, patchNumber: 0) + let versionC = OCKSemanticVersion(majorVersion: 1, minorVersion: 0, patchNumber: 1) + XCTAssert(versionA == versionB) + XCTAssert(versionA != versionC) + } + + func testComparability() { + let versionA = OCKSemanticVersion(majorVersion: 1, minorVersion: 1, patchNumber: 1) + let versionB = OCKSemanticVersion(majorVersion: 1, minorVersion: 1, patchNumber: 1) + let versionC = OCKSemanticVersion(majorVersion: 1, minorVersion: 10, patchNumber: 1) + let versionD = OCKSemanticVersion(majorVersion: 2, minorVersion: 1, patchNumber: 1) + let versionE = OCKSemanticVersion(majorVersion: 2, minorVersion: 1, patchNumber: 2) + + XCTAssertFalse(versionA > versionB) + XCTAssertFalse(versionA < versionB) + + XCTAssertTrue(versionA >= versionB) + XCTAssertTrue(versionA <= versionB) + + XCTAssertTrue(versionA < versionC) + XCTAssertTrue(versionA <= versionC) + + XCTAssertTrue(versionA < versionD) + XCTAssertTrue(versionA <= versionD) + + XCTAssertTrue(versionD < versionE) + XCTAssertTrue(versionD <= versionE) + } + + func testParseThrowsWhenStringIsEmpty() { + XCTAssertThrowsError(try OCKSemanticVersion.parse(""), "Failed to throw when string is empty") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .emptyString) + } + } + func testParseThrowsWhenMissingSeparator() { + XCTAssertThrowsError(try OCKSemanticVersion.parse("puppy"), "Failed to throw when missing separator") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .invalidMajorVersion) + } + } + + func testParseThrowsWhenMajorVersionIsNotAnInt() { + XCTAssertThrowsError(try OCKSemanticVersion.parse("S.0.1"), "Failed to throw when major version is invalid") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .invalidMajorVersion) + } + } + + func testParseThrowsWhenMinorVersionIsNotAnInt() { + XCTAssertThrowsError(try OCKSemanticVersion.parse("1.S.1"), "Failed to throw when minor version is invalid") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .invalidMinorVersion) + } + } + + func testParseThrowsWhenPatchVersionIsNotAnInt() { + XCTAssertThrowsError(try OCKSemanticVersion.parse("1.1.S"), "Failed to throw when patch version is invalid") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .invalidPatchVersion) + } + } + + func testParseThrowsWhenThereAreToManyValues() { + XCTAssertThrowsError(try OCKSemanticVersion.parse("1.1.1.1"), "Failed to throw when there are too many separators") { error in + XCTAssert(error as? OCKSemanticVersion.ParsingError == .tooManySeparators) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTask.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTask.swift new file mode 100755 index 0000000..a3a45cf --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTask.swift @@ -0,0 +1,155 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestTask: XCTestCase { + + func testBelongsToReturnsFalseIfIDsDontMatch() { + let plan = OCKCarePlan(id: "A", title: "obesity", patientID: nil) + let task = OCKTask(id: "B", title: nil, carePlanID: nil, schedule: .mealTimesEachDay(start: Date(), end: nil)) + XCTAssertFalse(task.belongs(to: plan)) + } + + func testBelongsToReturnsTrueIfIDsDoMatch() { + var plan = OCKCarePlan(id: "A", title: "obesity", patientID: nil) + plan.localDatabaseID = OCKLocalVersionID("abc") + let task = OCKTask(id: "B", title: nil, carePlanID: plan.localDatabaseID, schedule: .mealTimesEachDay(start: Date(), end: nil)) + XCTAssertTrue(task.belongs(to: plan)) + } + + // MARK: Task Query Filtering + + func testFilteringIncludesEventsThatStartBeforeTheQueryButHaveADurationIntoTheQueryInterval() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let schedule = OCKSchedule.dailyAtTime(hour: 9, minutes: 0, start: thisMorning, end: nil, text: nil, duration: .hours(2)) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 1, to: schedule.startDate())! // 10:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 4, to: schedule.startDate())! // 13:00 + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringIncludesAllDayEventsThatStartBeforeTheQuery() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let element = OCKScheduleElement(start: thisMorning, end: nil, interval: DateComponents(weekOfYear: 1), text: nil, duration: .allDay) + let schedule = OCKSchedule(composing: [element]) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 10, to: thisMorning)! // 10:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 13, to: thisMorning)! // 13:00 + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringIncludesAllDayEventsThatStartAfterTheQuery() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let tonight = Calendar.current.date(byAdding: .hour, value: 20, to: thisMorning)! // 20:00 + let element = OCKScheduleElement(start: tonight, end: nil, interval: DateComponents(weekOfYear: 1), text: nil, duration: .allDay) + let schedule = OCKSchedule(composing: [element]) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 10, to: thisMorning)! // 10:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 13, to: thisMorning)! // 13:00 + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringIncludesTasksForWhichNoEventOccursDuringTheQueryRange() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let schedule = OCKSchedule.dailyAtTime(hour: 6, minutes: 0, start: thisMorning, end: nil, text: nil) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 10, to: thisMorning)! // 10:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 13, to: thisMorning)! // 13:00 + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringIncludesEventsThatStartedOnThePreviousDay() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: thisMorning)! + let schedule = OCKSchedule.dailyAtTime(hour: 11, minutes: 0, start: yesterday, end: nil, text: nil, duration: .hours(5)) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 1, to: thisMorning)! // 01:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 2, to: thisMorning)! + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringRespectsEffectiveDate() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: thisMorning)! + + let schedule = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: tomorrow, end: nil, text: nil) + var task = OCKTask(id: "A", title: "a", carePlanID: nil, schedule: schedule) + task.effectiveDate = thisMorning + + let query = OCKTaskQuery(dateInterval: DateInterval(start: thisMorning, end: tomorrow)) + XCTAssert([task].filtered(against: query) == [task]) + } + + func testFilteringExcludesTasksNotDefinedInTheQueryInterval() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let tomorrowMorning = Calendar.current.date(byAdding: .day, value: 1, to: thisMorning)! + let schedule = OCKSchedule.dailyAtTime(hour: 6, minutes: 0, start: thisMorning, end: tomorrowMorning, text: nil) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + let queryStart = Calendar.current.date(byAdding: .hour, value: 10, to: tomorrowMorning)! // 10:00 + let queryEnd = Calendar.current.date(byAdding: .hour, value: 13, to: tomorrowMorning)! // 13:00 + let query = OCKTaskQuery(dateInterval: DateInterval(start: queryStart, end: queryEnd)) + XCTAssert([task].filtered(against: query).isEmpty) + } + + func testThatAMultiDayEventIsIncludedByQueriesOnAllDays() { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let nextWeek = Calendar.current.date(byAdding: .weekOfYear, value: 1, to: thisMorning)! + let element = OCKScheduleElement(start: thisMorning, end: nextWeek, interval: DateComponents(day: 7), duration: .hours(24 * 3 + 1)) + let schedule = OCKSchedule(composing: [element]) + let task = OCKTask(id: "abc123", title: "TaskA", carePlanID: nil, schedule: schedule) + + for dayOffset in 0...3 { + let day = Calendar.current.date(byAdding: .day, value: dayOffset, to: thisMorning)! + var query = OCKTaskQuery(for: day) + query.excludesTasksWithNoEvents = true + XCTAssert([task].filtered(against: query) == [task], "Failed on offset: \(dayOffset)") + } + + for dayOffset in 4...7 { + let day = Calendar.current.date(byAdding: .day, value: dayOffset, to: thisMorning)! + var query = OCKTaskQuery(for: day) + query.excludesTasksWithNoEvents = true + XCTAssert([task].filtered(against: query) == [], "Failed on offset: \(dayOffset)") + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTaskQuery.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTaskQuery.swift new file mode 100755 index 0000000..735a9dd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestTaskQuery.swift @@ -0,0 +1,82 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation +import XCTest + +private struct MockQuery: OCKAnyTaskQuery { + var ids: [String] = [] + var remoteIDs: [String] = [] + var groupIdentifiers: [String] = [] + var dateInterval: DateInterval? + var limit: Int? + var offset: Int = 0 + + var carePlanIDs: [String] = [] + var sortDescriptors: [OCKTaskSortDescriptor] = [] + + init() {} +} + +class TestTaskQuery: XCTestCase { + + func testSortOrderSetsExtendedSortOrder() { + var query = OCKTaskQuery() + query.sortDescriptors = [.title(ascending: true)] + XCTAssert(query.extendedSortDescriptors == [.title(ascending: true)]) + } + + func testExtendedSortOrderSetsSortOrder() { + var query = OCKTaskQuery() + query.extendedSortDescriptors = [.title(ascending: true)] + XCTAssert(query.sortDescriptors == [.title(ascending: true)]) + } + + func testInitializerCopiesOtherOCKTaskQueryExactly() { + var query1 = OCKTaskQuery() + query1.extendedSortDescriptors = [.effectiveDate(ascending: true)] + let query2 = OCKTaskQuery(query1) + XCTAssert(query1 == query2) + } + + func testInitializerCopiesIDsFromOtherPatientQuery() { + let query1 = MockQuery(id: "A") + let query2 = OCKTaskQuery(query1) + XCTAssert(query2.ids == ["A"]) + } + + func testInitializerCopiesSortOrderFromOtherPatientQuery() { + var query1 = MockQuery() + query1.sortDescriptors = [.title(ascending: true)] + let query2 = OCKTaskQuery(query1) + XCTAssert(query2.sortDescriptors == [.title(ascending: true)]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestVersionable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestVersionable.swift new file mode 100755 index 0000000..bec7b7a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Structs/TestVersionable.swift @@ -0,0 +1,36 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import XCTest + +class TestVersionable: XCTestCase { + +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestAdherenceAggregator.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestAdherenceAggregator.swift new file mode 100755 index 0000000..26365e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestAdherenceAggregator.swift @@ -0,0 +1,124 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +@testable import CareKitStore +import Foundation +import XCTest + +class TestAdherenceAggregators: XCTestCase { + func makeEvents(outcomeValues: [OCKOutcomeValueUnderlyingType], targetValues: [OCKOutcomeValueUnderlyingType]) -> [OCKAnyEvent] { + let element = OCKScheduleElement(start: Date(), end: nil, interval: DateComponents(day: 1), + text: nil, targetValues: targetValues.map { OCKOutcomeValue($0) }, + duration: .seconds(100)) + let task = OCKTask(id: "A", title: "A", carePlanID: nil, schedule: OCKSchedule(composing: [element])) + let values = outcomeValues.map { OCKOutcomeValue($0) } + let outcome = OCKOutcome(taskID: OCKLocalVersionID("dummy"), taskOccurrenceIndex: 0, values: values) + let scheduleEvent = task.schedule[0] + let event1: OCKStore.Event = OCKEvent(task: task, outcome: outcome, scheduleEvent: scheduleEvent) + let event2: OCKStore.Event = OCKEvent(task: task, outcome: nil, scheduleEvent: scheduleEvent) + return [event1.anyEvent, event2.anyEvent] + } + + func testOutcomesExist() { + let events = makeEvents(outcomeValues: [0], targetValues: []) + let aggregator = OCKAdherenceAggregator.outcomeExists + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5, but got \(result)") + } + + func testPercentOfOutcomeValuesThatExist() { + let events = makeEvents(outcomeValues: [0], targetValues: [10, "test"]) + let aggregator = OCKAdherenceAggregator.percentOfOutcomeValuesThatExist + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.25), "Expected 0.25, but got \(result)") + } + + func testPercentOfOutcomesvaluesThatExistWithNoGoals() { + let events = makeEvents(outcomeValues: [0], targetValues: []) + let aggregator = OCKAdherenceAggregator.percentOfOutcomeValuesThatExist + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5, but got \(result)") + } + + func testCompareTargetValuesWithUnequalNumberOfValuesAndTargetValues() { + let events = makeEvents(outcomeValues: [10], targetValues: [10, "test"]) + let aggregator = OCKAdherenceAggregator.compareTargetValues + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.0), "Expected 0.0 but got \(result)") + } + + func testCompareTargetValuesWithUnmetGoal() { + let events = makeEvents(outcomeValues: [9, "test"], targetValues: [10, "test"]) + let aggregator = OCKAdherenceAggregator.compareTargetValues + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.0), "Expected 0.0 but got \(result)") + } + + func testCompareTargetValuesWithAllGoalsMet() { + let events = makeEvents(outcomeValues: [10, "test"], targetValues: [10, "test"]) + let aggregator = OCKAdherenceAggregator.compareTargetValues + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5 but got \(result)") + } + + func testCompareTargetValuesWithNoGoals() { + let events = makeEvents(outcomeValues: [10], targetValues: []) + let aggregator = OCKAdherenceAggregator.compareTargetValues + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5 but got \(result)") + } + + func testTargetCompletionPercentage() { + let events = makeEvents(outcomeValues: [10, "fail"], targetValues: [10, "fail"]) + let aggregator = OCKAdherenceAggregator.percentOfTargetValuesMet + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5 but got \(result)") + } + + func testTargetCompletionPercentWithNoOutcomeValues() { + let events = makeEvents(outcomeValues: [], targetValues: [10, "test"]) + let aggregator = OCKAdherenceAggregator.percentOfTargetValuesMet + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.0), "Expected 0.0 but got \(result)") + } + + func testTargetCompletionPercentWithNoTargetValues() { + let events = makeEvents(outcomeValues: [10, "test"], targetValues: []) + let aggregator = OCKAdherenceAggregator.percentOfTargetValuesMet + let result = aggregator.aggregate(events: events) + XCTAssert(result == .progress(0.5), "Expected 0.5 but got \(result)") + } + + func testCustomAggregator() { + let events = makeEvents(outcomeValues: [], targetValues: []) + let aggregator = OCKAdherenceAggregator.custom({ _ in .noTasks }) + let result = aggregator.aggregate(events: events) + XCTAssert(result == .noTasks, "Expected `noTasks` but got \(result)") + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestEventAggregator.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestEventAggregator.swift new file mode 100755 index 0000000..a7b5afa --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestEventAggregator.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +@testable import CareKitStore +import Foundation +import XCTest + +class TestEventAggregators: XCTestCase { + func makeEvents() -> [OCKAnyEvent] { + let element = OCKScheduleElement(start: Date(), end: nil, interval: DateComponents(day: 1), + text: nil, targetValues: [OCKOutcomeValue(10), OCKOutcomeValue("test")], + duration: .seconds(100)) + let task = OCKTask(id: "A", title: "A", carePlanID: nil, schedule: OCKSchedule(composing: [element])) + let taskID = OCKLocalVersionID("test") + let outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [OCKOutcomeValue(10), OCKOutcomeValue("test")]) + let scheduleEvent = task.schedule[0] + let event1: OCKStore.Event = OCKEvent(task: task, outcome: outcome, scheduleEvent: scheduleEvent) + let event2: OCKStore.Event = OCKEvent(task: task, outcome: nil, scheduleEvent: scheduleEvent) + return [event1.anyEvent, event2.anyEvent] + } + + func testCountOutcomes() { + let aggregator = OCKEventAggregator.countOutcomes + let result = aggregator.aggregate(events: makeEvents()) + XCTAssert(result == 1) + } + + func testCountOutcomeValues() { + let aggregator = OCKEventAggregator.countOutcomeValues + let result = aggregator.aggregate(events: makeEvents()) + XCTAssert(result == 2) + } + + func testCustomAggreator() { + let aggregator = OCKEventAggregator.custom({ events in Double(events.count) }) + let result = aggregator.aggregate(events: makeEvents()) + XCTAssert(result == 2) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestStoreProtocolExtensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestStoreProtocolExtensions.swift new file mode 100755 index 0000000..0e01785 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/TestStoreProtocolExtensions.swift @@ -0,0 +1,289 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +@testable import CareKitStore +import XCTest + +class TestStoreProtocolExtensions: XCTestCase { + var store: OCKStore! + + override func setUp() { + super.setUp() + store = OCKStore(name: "TestDatabase", type: .inMemory) + } + + override func tearDown() { + super.tearDown() + store = nil + } + + // MARK: - fetchEvents + + func testFetchEventsAcrossVersionsWithNoOverlap() throws { + let beginningOfDay = Calendar.current.startOfDay(for: Date()) + let queryStart = Calendar.current.date(byAdding: .day, value: -3, to: beginningOfDay)! + let startDate = Calendar.current.date(byAdding: .day, value: -10, to: beginningOfDay)! + let midDate = Calendar.current.date(byAdding: .day, value: 0, to: beginningOfDay)! + let endDate = Calendar.current.date(byAdding: .day, value: 3, to: beginningOfDay)! + + let schedule1 = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: startDate, end: midDate, text: nil) + let schedule2 = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: midDate, end: endDate, text: nil) + + let taskV1 = OCKTask(id: "task", title: "Version 1", carePlanID: nil, schedule: schedule1) + let taskV2 = OCKTask(id: "task", title: "Version 2", carePlanID: nil, schedule: schedule2) + + let query = OCKEventQuery(dateInterval: DateInterval(start: queryStart, end: endDate)) + try store.addTaskAndWait(taskV1) + try store.updateTaskAndWait(taskV2) + let events = try store.fetchEventsAndWait(taskID: "task", query: query) + guard events.count == 6 else { XCTFail("Expected 6 events, but got \(events.count)"); return } + for index in 0..<3 { XCTAssert(events[index].task.title == taskV1.title) } + for index in 3..<6 { XCTAssert(events[index].task.title == taskV2.title) } + } + + func testFetchEventsAcrossVersionsWithOverlappingInfiniteSchedules() throws { + let beginningOfDay = Calendar.current.startOfDay(for: Date()) + let date1 = Calendar.current.date(byAdding: .day, value: -3, to: beginningOfDay)! + let date2 = Calendar.current.date(byAdding: .day, value: -1, to: beginningOfDay)! + let date3 = Calendar.current.date(byAdding: .day, value: -0, to: beginningOfDay)! + let date4 = Calendar.current.date(byAdding: .day, value: 3, to: beginningOfDay)! + + let schedule1 = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: date1, end: nil, text: nil) + let schedule2 = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: date3, end: nil, text: nil) + + let taskV1 = OCKTask(id: "task", title: "Version 1", carePlanID: nil, schedule: schedule1) + let taskV2 = OCKTask(id: "task", title: "Version 2", carePlanID: nil, schedule: schedule2) + + let query = OCKEventQuery(dateInterval: DateInterval(start: date2, end: date4)) + try store.addTaskAndWait(taskV1) + try store.updateTaskAndWait(taskV2) + let events = try store.fetchEventsAndWait(taskID: "task", query: query) + guard events.count == 4 else { XCTFail("Expected 4 events, but got \(events.count)"); return } + for index in 0..<1 { XCTAssert(events[index].task.title == taskV1.title) } + for index in 1..<4 { XCTAssert(events[index].task.title == taskV2.title) } + } + + func testFetchEventsReturnsEventsWithTheCorrectOccurrenceIndex() throws { + let beginningOfDay = Calendar.current.startOfDay(for: Date()) + let date1 = Calendar.current.date(byAdding: .day, value: -3, to: beginningOfDay)! + let date2 = Calendar.current.date(byAdding: .day, value: -1, to: beginningOfDay)! + let date3 = Calendar.current.date(byAdding: .day, value: 3, to: beginningOfDay)! + + let schedule = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: date1, end: nil, text: nil) + var task = OCKTask(id: "task", title: "Medication", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + let outcome = OCKOutcome(taskID: try task.getLocalID(), taskOccurrenceIndex: 3, values: []) + try store.addOutcomeAndWait(outcome) + + let query = OCKEventQuery(dateInterval: DateInterval(start: date2, end: date3)) + let events = try store.fetchEventsAndWait(taskID: task.id, query: query) + XCTAssert(events.count == 4) + XCTAssert(events[0].scheduleEvent.occurrence == 2) + XCTAssert(events[1].scheduleEvent.occurrence == 3) + XCTAssert(events[2].scheduleEvent.occurrence == 4) + XCTAssert(events[3].scheduleEvent.occurrence == 5) + XCTAssert(events[1].outcome?.taskOccurrenceIndex == 3) + } + + func testFetchSingleEvent() throws { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + var task = OCKTask(id: "exercise", title: "Push Ups", carePlanID: nil, schedule: schedule) + task = try store.addTaskAndWait(task) + let taskID = try task.getLocalID() + var outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 5, values: []) + outcome = try store.addOutcomeAndWait(outcome) + let event = try store.fetchEventAndWait(forTask: task, occurrence: 5) + XCTAssert(event.outcome == outcome) + } + + func testFetchSingleEventFailsIfTaskIsNotPersistedYet() { + let schedule = OCKSchedule.mealTimesEachDay(start: Date(), end: nil) + let task = OCKTask(id: "exercise", title: "Push Ups", carePlanID: nil, schedule: schedule) + XCTAssertThrowsError(try store.fetchEventAndWait(forTask: task, occurrence: 0)) + } + + func testFetchEventsEveryOtherDay() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let startDate = Calendar.current.date(byAdding: DateComponents(day: -1, minute: 5), to: thisMorning)! + + let allDayEveryOtherDay = OCKSchedule(composing: [ + OCKScheduleElement(start: startDate, + end: nil, + interval: DateComponents(day: 2), + text: nil, + duration: .allDay) + ]) + + let oneSecondEveryOtherDay = OCKSchedule(composing: [ + OCKScheduleElement(start: startDate, + end: nil, + interval: DateComponents(day: 2), + text: nil, + duration: .seconds(1)) + ]) + let allDayRepeatingTask1 = OCKTask(id: "task1", title: "task1", carePlanID: nil, schedule: allDayEveryOtherDay) + let shortRepeatingTask2 = OCKTask(id: "task2", title: "task2", carePlanID: nil, schedule: oneSecondEveryOtherDay) + + try store.addTaskAndWait(allDayRepeatingTask1) + try store.addTaskAndWait(shortRepeatingTask2) + + // Yesterday's tasks - there should be 2 + let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())! + var yesterdayQuery = OCKTaskQuery(for: yesterday) + yesterdayQuery.excludesTasksWithNoEvents = true + var fetched = try store.fetchTasksAndWait(query: yesterdayQuery).map { $0.id } + XCTAssert(fetched.contains(allDayRepeatingTask1.id), "failed to fetch all day occurring event") + XCTAssert(fetched.contains(shortRepeatingTask2.id), "failed to fetch yesterday's day occurring event") + + // Today's tasks - there shouldn't be any + var todayQuery = OCKTaskQuery(for: Date()) + todayQuery.excludesTasksWithNoEvents = true + fetched = try store.fetchTasksAndWait(query: todayQuery).map { $0.id } + XCTAssert(fetched.isEmpty, "Expected 0, but got \(fetched)") + + // Tomorrow's tasks - there should be two + var tomorrowQuery = OCKTaskQuery(for: Date().addingTimeInterval(24 * 60 * 60)) + tomorrowQuery.excludesTasksWithNoEvents = true + fetched = try store.fetchTasksAndWait(query: tomorrowQuery).map { $0.id } + XCTAssert(fetched.contains(allDayRepeatingTask1.id), "failed to fetch all day occurring event") + XCTAssert(fetched.contains(shortRepeatingTask2.id), "failed to fetch yesterday's day occurring event") + } + + func testFetchEventAfterEnd() throws { + let endDate = Date().addingTimeInterval(1_000) + let afterEndDate = Date().addingTimeInterval(1_030) + let schedule = OCKSchedule(composing: [ + OCKScheduleElement(start: Date(), + end: endDate, + interval: DateComponents(second: 1)) + ]) + let task = OCKTask(id: "exercise", title: "Push Ups", carePlanID: nil, schedule: schedule) + try store.addTaskAndWait(task) + + let interval = DateInterval(start: afterEndDate, end: Date.distantFuture) + var query = OCKTaskQuery(dateInterval: interval) + query.excludesTasksWithNoEvents = true + let tasks = try store.fetchTasksAndWait(query: query) + XCTAssert(tasks.isEmpty) + } + + func testFetchEventsRespectsEffectiveDateDate() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: thisMorning)! + let nextWeek = Calendar.current.date(byAdding: .day, value: 7, to: thisMorning)! + + let scheduleA = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: thisMorning, end: nil, text: nil) + var versionA = OCKTask(id: "A", title: "a", carePlanID: nil, schedule: scheduleA) + versionA = try store.addTaskAndWait(versionA) + + let scheduleB = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: nextWeek, end: nil, text: nil) + var versionB = OCKTask(id: "A", title: "b", carePlanID: nil, schedule: scheduleB) + versionB.effectiveDate = tomorrow + versionB = try store.updateTaskAndWait(versionB) + + let interval = DateInterval(start: thisMorning, end: Calendar.current.date(byAdding: .day, value: 5, to: tomorrow)!) + let query = OCKEventQuery(dateInterval: interval) + let events = try store.fetchEventsAndWait(taskID: "A", query: query) + XCTAssert(events.count == 1, "Expected to get 1 event, but got \(events.count)") + XCTAssert(events.first?.task.title == versionA.title) + } + + func testFetchEventsReturnsOnlyTheNewerOfTwoEventsWhenTwoVersionsOfATaskHaveEventsAtQueryStart() throws { + let element = OCKScheduleElement(start: Date(), end: nil, interval: DateComponents(day: 1), + text: nil, targetValues: [], duration: .allDay) + let schedule = OCKSchedule(composing: [element]) + let versionA = OCKTask(id: "123", title: "A", carePlanID: nil, schedule: schedule) + try store.addTaskAndWait(versionA) + var versionB = OCKTask(id: "123", title: "B", carePlanID: nil, schedule: schedule) + versionB.effectiveDate = schedule[4].start + try store.updateTaskAndWait(versionB) + let events = try store.fetchEventsAndWait(taskID: "123", query: .init(for: schedule[4].start)) + XCTAssert(events.count == 1, "Expected 1, but got \(events.count)") + XCTAssert(events.first?.task.title == "B") + } + + // MARK: Adherence and Insights + + func testFetchAdherenceAggregatesEventsAcrossTasks() throws { + let start = Calendar.current.startOfDay(for: Date()) + let twoDaysEarly = Calendar.current.date(byAdding: .day, value: -2, to: start)! + let twoDaysLater = Calendar.current.date(byAdding: DateComponents(day: 2, second: -1), to: start)! + let element = OCKScheduleElement(start: start, end: nil, interval: DateComponents(day: 2)) + let schedule = OCKSchedule(composing: [element]) + let task1 = OCKTask(id: "meditate", title: "Medidate", carePlanID: nil, schedule: schedule) + let task2 = OCKTask(id: "sleep", title: "Nap", carePlanID: nil, schedule: schedule) + let task = try store.addTasksAndWait([task1, task2]).first! + let taskID = try task.getLocalID() + let value = OCKOutcomeValue(20.0, units: "minutes") + let outcome = OCKOutcome(taskID: taskID, taskOccurrenceIndex: 0, values: [value]) + try store.addOutcomeAndWait(outcome) + let query = OCKAdherenceQuery(taskIDs: [task1.id, task2.id], dateInterval: DateInterval(start: twoDaysEarly, end: twoDaysLater)) + let adherence = try store.fetchAdherenceAndWait(query: query) + XCTAssert(adherence == [.noTasks, .noTasks, .progress(0.5), .noEvents]) + } + + func testFetchAdherenceWithCustomAggregator() throws { + let start = Calendar.current.startOfDay(for: Date()) + let twoDaysEarly = Calendar.current.date(byAdding: .day, value: -2, to: start)! + let twoDaysLater = Calendar.current.date(byAdding: DateComponents(day: 2, second: -1), to: start)! + let schedule = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: start, end: nil, text: nil) + let task = OCKTask(id: "meditate", title: "Medidate", carePlanID: nil, schedule: schedule) + try store.addTaskAndWait(task) + var query = OCKAdherenceQuery(taskIDs: [task.id], dateInterval: DateInterval(start: twoDaysEarly, end: twoDaysLater)) + var timesCalled = 0 + query.aggregator = .custom({ _ in + timesCalled += 1 + return .progress(0.99) + }) + let adherence = try store.fetchAdherenceAndWait(query: query) + XCTAssert(adherence == [.noTasks, .noTasks, .progress(0.99), .progress(0.99)]) + XCTAssert(timesCalled == 2) + } + + func testFetchInsights() throws { + let thisMorning = Calendar.current.startOfDay(for: Date()) + let aWeekAgo = Calendar.current.date(byAdding: DateComponents(second: 1, weekOfYear: -1), to: thisMorning)! + let schedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: aWeekAgo, end: nil, text: nil) + let task = OCKTask(id: "walk", title: "Walk", carePlanID: nil, schedule: schedule) + let mockData: [Double] = [10, 20, 30, 40, 50, 60, 70] + try store.addTaskAndWait(task) + var index = -1 + let query = OCKInsightQuery(taskID: task.id, + dateInterval: DateInterval(start: aWeekAgo, end: thisMorning), + aggregator: .custom({ _ -> Double in + index += 1 + return mockData[index] + })) + let insights = try store.fetchInsightsAndWait(query: query) + XCTAssert(insights == mockData) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Utils.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Utils.swift new file mode 100755 index 0000000..42230d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitStore/CareKitStoreTests/Utils.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitStore +import Foundation + +extension Result { + var value: Success? { + switch self { + case .success(let value): return value + case .failure: return nil + } + } + + var error: Failure? { + switch self { + case .success: return nil + case .failure(let error): return error + } + } +} + +extension OCKSchedule { + static func mealTimesEachDay(start: Date, end: Date?, targetValues: [OCKOutcomeValue] = []) -> OCKSchedule { + let startDate = Calendar.current.startOfDay(for: start) + let breakfast = OCKSchedule.dailyAtTime(hour: 7, minutes: 30, start: startDate, end: end, + text: "Breakfast", targetValues: targetValues) + let lunch = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: startDate, end: end, + text: "Lunch", targetValues: targetValues) + let dinner = OCKSchedule.dailyAtTime(hour: 17, minutes: 30, start: startDate, end: end, + text: "Dinner", targetValues: targetValues) + return OCKSchedule(composing: [breakfast, lunch, dinner]) + } +} + +extension OCKObjectCompatible { + func getLocalID() throws -> OCKLocalVersionID { + guard let localID = localDatabaseID else { throw OCKStoreError.invalidValue(reason: "Missing local database ID") } + return localID + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKAnimatedButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKAnimatedButton.swift new file mode 100755 index 0000000..27ec958 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKAnimatedButton.swift @@ -0,0 +1,327 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +private extension UIColor { + func inverted() -> UIColor? { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else { return nil } + return .init(red: 1 - red, green: 1 - green, blue: 1 - blue, alpha: alpha) + } +} + +/// A highlightable and selectable button that can be animated. The `isHighlighted` state can be specified with options, and the `isSelected` state +/// can be handled automatically when the button is tapped. +/// +/// The content view can be injected into the button. By default, the content is contrained to the button's `layoutMarginGuide`. +open class OCKAnimatedButton: UIControl, OCKStylable { + + /// Options for displaying the the highlighted state of an `OCKAnimatedButton`. + public enum HighlightOption: Hashable { + + /// Draw an overlay over the button's content. + case overlay(alpha: CGFloat) + + /// Lower the alpha of the button. + case fade(alpha: CGFloat) + + /// Delay showing the highlighted state after the button is tapped. + case delayOnSelect(delay: TimeInterval) + + /// Draw an overlay over the button's content with a default alpha. + public static var defaultOverlay: HighlightOption { .overlay(alpha: 0.05) } + + /// Delay showing the highlighted state after the button is tapped by a default value. + public static var defaultFade: HighlightOption { .fade(alpha: 0.6) } + + /// Delay showing the highlighted state after the button is tapped by a default value. + public static var defaultDelayOnSelect: HighlightOption { .delayOnSelect(delay: 0.05) } + + public func hash(into hasher: inout Hasher) { + // Hash self without taking into account the associated values. + switch self { + case .overlay: hasher.combine(2) + case .fade: hasher.combine(3) + case .delayOnSelect: hasher.combine(4) + } + } + + // Check if self is `.overlay` and ignore the associated value. + var isOverlay: Bool { + switch self { + case .overlay: return true + default: return false + } + } + + // Check if self is `.delayOnSelect` and ignore the associated value. + var isDelayOnSelect: Bool { + switch self { + case .delayOnSelect: return true + default: return false + } + } + + // Check if self is `.fade` and ignore the associated value. + var isFade: Bool { + switch self { + case .fade: return true + default: return false + } + } + } + + // MARK: Properties + + /// Set the selected state for the button. By default the selected state is not animated. + override open var isSelected: Bool { + get { return super.isSelected } + set { return setSelected(newValue, animated: false) } + } + + /// Set the highlighted state for the button. By default the highlighted state is animated. + override open var isHighlighted: Bool { + get { return super.isHighlighted } + set { + if showsHighlight { + // Note: We animate by default because `isHighlighted` is set and managed internally by `UIControl`. + setHighlighted(newValue, animated: true, buttonWasTapped: true) + } else { + super.isHighlighted = newValue + } + } + } + + /// Handle the selection state automatically when the button is tapped. + public var handlesSelection: Bool = true + + /// The highlighted state options. + public let highlightOptions: Set + + /// The content inside the button. + public let contentView: Content? + + public var customStyle: OCKStyler? { + didSet { styleChildren() } + } + + // Overlay over the content during the highlighted state. + private lazy var overlayView: UIView = { + let view = UIView() + view.alpha = 0 + view.isUserInteractionEnabled = false + return view + }() + + private let highlightAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .easeOut, animations: nil) + private let selectAnimator = UIViewPropertyAnimator(duration: 0.1, curve: .easeOut, animations: nil) + private var showsHighlight: Bool { !highlightOptions.isEmpty } + + // MARK: - Life Cycle + + /// Creat an animated button with injected content. The content will automatically be constrained to the button's `layoutMarginGuide`. + /// - Parameter contentView: The content to be constrained to the button's `layoutMarginGuide`. + /// - Parameter highlightOptions: Options for displaying the highlighted state. Suppplying no options cause the button to show no highlighted + /// state + /// - Parameter handlesSelection: Automatically sets the selected state when the button is tapped. + public init(contentView: Content?, + highlightOptions: Set = [], + handlesSelection: Bool = true) { + self.contentView = contentView + self.handlesSelection = handlesSelection + self.highlightOptions = Set(highlightOptions) + super.init(frame: .zero) + setup() + } + + public required init?(coder: NSCoder) { + contentView = nil + highlightOptions = [] + super.init(coder: coder) + setup() + } + + // MARK: - Methods + + private func setup() { + addSubviews() + constrainSubviews() + styleDidChange() + + contentView?.isUserInteractionEnabled = false + } + + private func addSubviews() { + if let contentView = contentView { + addSubview(contentView) + } + + if highlightOptions.contains(where: { $0.isOverlay }) { + addSubview(overlayView) + } + } + + private func constrainSubviews() { + if highlightOptions.contains(where: { $0.isOverlay }) { + overlayView.frame = bounds + overlayView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } + + if let contentView = contentView { + contentView.frame = bounds + contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } + } + + private func highlightDelayValue(for options: Set) -> TimeInterval { + guard let index = options.firstIndex(where: { $0.isDelayOnSelect }) else { return 0 } + if case let HighlightOption.delayOnSelect(delay) = options[index] { + return delay + } + return 0 + } + + private func setHighlighted(_ isHighlighted: Bool, animated: Bool, buttonWasTapped: Bool) { + guard isHighlighted != super.isHighlighted else { return } + super.isHighlighted = isHighlighted + + // Ensure the button should show a highlighted state. If it should not, clear the state. + guard showsHighlight else { + if isHighlighted { + setStyleForSelectedState(false) + } + return + } + + // Set the state without an animation. + guard animated else { + highlightAnimator.stopAnimation(true) + setStyleForHighlightedState(isHighlighted) + return + } + + // Compute the delay value for showing the highlighted state. Only delay if the highlighted state is the result of a tap, and the highlight + // options specify a delay. + let delay: TimeInterval = buttonWasTapped && isHighlighted ? highlightDelayValue(for: highlightOptions) : 0 + + // Animate the highlighted state. + highlightAnimator.stopAnimation(true) + highlightAnimator.addAnimations { [unowned self] in + self.setStyleForHighlightedState(isHighlighted) + } + highlightAnimator.startAnimation(afterDelay: delay) + } + + private func isTouchInside(_ touches: Set, event: UIEvent?) -> Bool { + guard let touch = touches.first else { return false } + let position = touch.location(in: self) + return point(inside: position, with: event) + } + + override open func touchesEnded(_ touches: Set, with event: UIEvent?) { + super.touchesEnded(touches, with: event) + + // Automatically set the selected state when the button is tapped + guard handlesSelection && isTouchInside(touches, event: event) else { return } + setSelected(!isSelected, animated: true) + } + + /// Set the style for the highlighted state. This function may be called in an animation block if the state is being animated. + /// - Parameter isHighlighted: True if the button is in the highlighted state. + open func setStyleForHighlightedState(_ isHighlighted: Bool) { + for option in highlightOptions { + switch option { + case .overlay(let alpha): + overlayView.alpha = isHighlighted ? alpha : 0 + case .fade(let alpha): + self.alpha = isHighlighted ? alpha : 1 + case .delayOnSelect: + break + } + } + } + + /// Set the highlighted state and update the `isHighlighted` property. + /// - Parameter isHighlighted: True if the button is in the highlighted state. + /// - Parameter animated: Animate the highlighted state. + open func setHighlighted(_ isHighlighted: Bool, animated: Bool) { + setHighlighted(isHighlighted, animated: animated, buttonWasTapped: false) + } + + /// Set the style for the selected state. This function may be called in an animation block if the state is being animated. + /// - Parameter isSelected: True if the button is in the selected state. + open func setStyleForSelectedState(_ isSelected: Bool) { + assert(false, "Should override setStyleForSelectedState(isSelected:)") + } + + /// Set the selected state and update the `isSelected` property. + /// - Parameter isSelected: True if the button is in the selected state. + /// - Parameter animated: Animate the selected state. + open func setSelected(_ isSelected: Bool, animated: Bool) { + guard isSelected != self.isSelected else { return } + super.isSelected = isSelected + + // Set the state without an animation. + guard animated else { + selectAnimator.stopAnimation(true) + setStyleForSelectedState(isSelected) + return + } + + // Animate the selected state. + selectAnimator.stopAnimation(true) + selectAnimator.addAnimations { [unowned self] in + self.setStyleForSelectedState(isSelected) + } + selectAnimator.startAnimation() + } + + // MARK: - OCKStylable + + open func styleDidChange() { + let style = self.style() + overlayView.backgroundColor = UIColor { _ in + let customBackground = style.color.customBackground + return customBackground.inverted() ?? customBackground + } + directionalLayoutMargins = style.dimension.directionalInsets1 + } + + override open func didMoveToSuperview() { + super.didMoveToSuperview() + styleDidChange() + } + + override open func removeFromSuperview() { + super.removeFromSuperview() + styleChildren() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKCheckmarkButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKCheckmarkButton.swift new file mode 100755 index 0000000..388b48b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Controls/OCKCheckmarkButton.swift @@ -0,0 +1,150 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A button that shows a checkmark in the selected state, and an empty ring in the deselected state. +open class OCKCheckmarkButton: OCKAnimatedButton { + + override open var intrinsicContentSize: CGSize { + return .init(width: height.scaledValue, height: height.scaledValue) + } + + /// Checkmark image in the center of the view. + public let imageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "checkmark") + return imageView + }() + + lazy var height = OCKAccessibleValue(container: style(), keyPath: \.dimension.buttonHeight2) { [weak self] _ in + self?.invalidateIntrinsicContentSize() + } + + lazy var lineWidth = OCKAccessibleValue(container: style(), keyPath: \.appearance.borderWidth1) { [circleMaskBorderLayer] scaledValue in + circleMaskBorderLayer.lineWidth = scaledValue + } + + lazy var imageViewPointSize = OCKAccessibleValue(container: style(), keyPath: \.dimension.symbolPointSize3) { [imageView] scaledValue in + imageView.preferredSymbolConfiguration = .init(pointSize: scaledValue, weight: .bold) + } + + private let circleMaskBorderLayer: CAShapeLayer = { + let layer = CAShapeLayer() + layer.fillColor = UIColor.clear.cgColor + return layer + }() + + private let circleMask = CAShapeLayer() + + // MARK: Life cycle + + public init() { + super.init(contentView: imageView) + setup() + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func layoutSubviews() { + super.layoutSubviews() + updateMaskFor(rect: bounds) + } + + // MARK: Methods + + private func setup() { + constrainSubviews() + styleSubviews() + + layer.mask = circleMask + layer.addSublayer(circleMaskBorderLayer) + } + + private func styleSubviews() { + clipsToBounds = true + setStyleForSelectedState(false) + } + + private func constrainSubviews() { + imageView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + imageView.centerXAnchor.constraint(equalTo: centerXAnchor), + imageView.centerYAnchor.constraint(equalTo: centerYAnchor) + ]) + } + + private func updateMaskFor(rect: CGRect) { + circleMask.path = UIBezierPath(ovalIn: rect).cgPath + circleMaskBorderLayer.path = UIBezierPath(ovalIn: rect).cgPath + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + height.update(withContainer: style) + lineWidth.update(withContainer: style) + imageViewPointSize.update(withContainer: style) + if isSelected { + imageView.tintColor = style.color.customBackground + } + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + circleMaskBorderLayer.strokeColor = tintColor.cgColor + + if isSelected { + backgroundColor = tintColor + } + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if traitCollection.preferredContentSizeCategory != previousTraitCollection?.preferredContentSizeCategory { + [lineWidth, height, imageViewPointSize].forEach { $0.apply() } + } + } + + /// Set the style for the selected state. This function may be called in an animation block if the state is being animated. + /// - Parameter isSelected: True if the button is in the selected state. + override open func setStyleForSelectedState(_ isSelected: Bool) { + if isSelected { + imageView.tintColor = style().color.customBackground + backgroundColor = tintColor + } else { + imageView.tintColor = .clear + backgroundColor = .clear + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Calendar+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Calendar+Extensions.swift new file mode 100755 index 0000000..a62b3fd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Calendar+Extensions.swift @@ -0,0 +1,39 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +extension Calendar { + func dateIntervalOfWeek(for date: Date) -> DateInterval { + var interval = Calendar.current.dateInterval(of: .weekOfYear, for: date)! + interval.duration -= 1 // The default interval contains 1 second of the next day after the interval. Subtract that off + return interval + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/NSLayoutConstraint+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/NSLayoutConstraint+Extensions.swift new file mode 100755 index 0000000..35449bf --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/NSLayoutConstraint+Extensions.swift @@ -0,0 +1,110 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +struct LayoutDirection: OptionSet { + let rawValue: Int + + static let top = LayoutDirection(rawValue: 1 << 0) + static let bottom = LayoutDirection(rawValue: 1 << 1) + static let leading = LayoutDirection(rawValue: 1 << 2) + static let trailing = LayoutDirection(rawValue: 1 << 3) + + static let horizontal: LayoutDirection = [.leading, .trailing] + static let vertical: LayoutDirection = [.top, .bottom] + + static let all: LayoutDirection = [.horizontal, .vertical] +} + +extension UILayoutPriority { + static var almostRequired: UILayoutPriority { + return .required - 1 + } +} + +extension NSLayoutConstraint { + func withPriority(_ new: UILayoutPriority) -> NSLayoutConstraint { + priority = new + return self + } +} + +extension UIView { + func setContentHuggingPriorities(_ new: UILayoutPriority) { + setContentHuggingPriority(new, for: .horizontal) + setContentHuggingPriority(new, for: .vertical) + } + + func setContentCompressionResistancePriorities(_ new: UILayoutPriority) { + setContentCompressionResistancePriority(new, for: .horizontal) + setContentCompressionResistancePriority(new, for: .vertical) + } + + func constraints(equalTo other: UIView, directions: LayoutDirection = .all, + priority: UILayoutPriority = .required) -> [NSLayoutConstraint] { + var constraints: [NSLayoutConstraint] = [] + if directions.contains(.top) { + constraints.append(topAnchor.constraint(equalTo: other.topAnchor).withPriority(priority)) + } + if directions.contains(.leading) { + constraints.append(leadingAnchor.constraint(equalTo: other.leadingAnchor).withPriority(priority)) + } + if directions.contains(.bottom) { + constraints.append(bottomAnchor.constraint(equalTo: other.bottomAnchor).withPriority(priority)) + } + if directions.contains(.trailing) { + constraints.append(trailingAnchor.constraint(equalTo: other.trailingAnchor).withPriority(priority)) + } + return constraints + } + + func constraints(equalTo layoutGuide: UILayoutGuide, directions: LayoutDirection = .all, + priority: UILayoutPriority = .required) -> [NSLayoutConstraint] { + var constraints: [NSLayoutConstraint] = [] + if directions.contains(.top) { + constraints.append(topAnchor.constraint(equalTo: layoutGuide.topAnchor).withPriority(priority)) + } + if directions.contains(.leading) { + constraints.append(leadingAnchor.constraint(equalTo: layoutGuide.leadingAnchor).withPriority(priority)) + } + if directions.contains(.bottom) { + constraints.append(bottomAnchor.constraint(equalTo: layoutGuide.bottomAnchor).withPriority(priority)) + } + if directions.contains(.trailing) { + constraints.append(trailingAnchor.constraint(equalTo: layoutGuide.trailingAnchor).withPriority(priority)) + } + return constraints + } + + var isRightToLeft: Bool { + return UIView.userInterfaceLayoutDirection(for: semanticContentAttribute) == .rightToLeft + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Number+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Number+Extensions.swift new file mode 100755 index 0000000..52a9770 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/Number+Extensions.swift @@ -0,0 +1,43 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +extension Double { + var normalized: Double { + return max(0, min(self, 1)) + } +} + +extension CGFloat { + func scaled() -> CGFloat { + UIFontMetrics.default.scaledValue(for: self) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/UIFont+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/UIFont+Extensions.swift new file mode 100755 index 0000000..59f97af --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Extensions/UIFont+Extensions.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +extension UIFont { + static func preferredCustomFont(forTextStyle textStyle: TextStyle, weight: Weight) -> UIFont { + let defaultDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: textStyle) + let size = defaultDescriptor.pointSize + let fontDescriptor = UIFontDescriptor(fontAttributes: [ + UIFontDescriptor.AttributeName.size: size, + UIFontDescriptor.AttributeName.family: UIFont.systemFont(ofSize: size).familyName + ]) + + // Add the font weight to the descriptor + let weightedFontDescriptor = fontDescriptor.addingAttributes([ + UIFontDescriptor.AttributeName.traits: [ + UIFontDescriptor.TraitKey.weight: weight + ] + ]) + return UIFont(descriptor: weightedFontDescriptor, size: 0) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKCappedSizeLabel.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKCappedSizeLabel.swift new file mode 100755 index 0000000..95caf95 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKCappedSizeLabel.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// This is an internal subclass of `OCKLabel` that has a max font size that will be respected even if +/// the user increases font size or uses accessible sizes. It should be used sparingly and exposed +/// in public API's as its superclass `OCKLabel` +class OCKCappedSizeLabel: OCKLabel { + + var maxFontSize: CGFloat = 20 + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if font.pointSize > maxFontSize { + font = font.withSize(maxFontSize) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKLabel.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKLabel.swift new file mode 100755 index 0000000..9e196b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Labels/OCKLabel.swift @@ -0,0 +1,123 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A label that handles animating state changes and provides accessibilty features. +/// +/// To animate changes to the text, set `animatesTextChanges` to true. +/// +/// To have the label automatically change its text size whenever the accessibility content size changes, +/// use the initialzer that takes a `textStyle` and `weight`. +open class OCKLabel: UILabel, OCKStylable { + + // MARK: Properties + + public var customStyle: OCKStyler? { + didSet { styleChildren() } + } + + /// Flag determining whether to animate text changes. + public var animatesTextChanges = false + + override open var text: String? { + get { + return super.text + } set { + guard animatesTextChanges else { super.text = newValue; return; } + UIView.transition(with: self, duration: style().animation.stateChangeDuration, options: .transitionCrossDissolve, animations: { + super.text = newValue + }, completion: nil) + } + } + + private let textStyle: UIFont.TextStyle? + private let weight: UIFont.Weight? + + // MARK: Life Cycle + + /// Create an instance of and `OCKLabel`. By default, the label will not animate text changes and will not scale with + /// accessibility content size changes. + public init() { + textStyle = nil + weight = nil + super.init(frame: .zero) + setup() + } + + /// Create an instance of and `OCKLabel`. By default, the label will not animate text changes and will scale with + /// accessibility content size changes. + /// + /// - Parameters: + /// - textStyle: The style of the font. + /// - weight: The weight of the font. + public init(textStyle: UIFont.TextStyle, weight: UIFont.Weight) { + self.textStyle = textStyle + self.weight = weight + super.init(frame: .zero) + font = UIFont.preferredCustomFont(forTextStyle: textStyle, weight: weight) + setup() + } + + public required init?(coder aDecoder: NSCoder) { + textStyle = nil + weight = nil + super.init(coder: aDecoder) + setup() + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + guard + let textStyle = textStyle, let weight = weight, + traitCollection.preferredContentSizeCategory != previousTraitCollection?.preferredContentSizeCategory + else { return } + font = UIFont.preferredCustomFont(forTextStyle: textStyle, weight: weight) + } + + // MARK: Methods + + private func setup() { + preservesSuperviewLayoutMargins = true + adjustsFontForContentSizeCategory = false + styleDidChange() + } + + override open func didMoveToSuperview() { + super.didMoveToSuperview() + styleDidChange() + } + + override open func removeFromSuperview() { + super.removeFromSuperview() + styleChildren() + } + + open func styleDidChange() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Layout/OCKResponsiveLayout.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Layout/OCKResponsiveLayout.swift new file mode 100755 index 0000000..178d8c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Layout/OCKResponsiveLayout.swift @@ -0,0 +1,183 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import Foundation +import UIKit + +/// Accessible view configuration that contains layout information for different `UserInterfaceSizeClass` +/// and `UIContentSizeCategory` combinations. +public struct OCKResponsiveLayout { + + // MARK: - Instance Properties + + /// A default `SizeClassRuleSet` to apply for different `UIContentSizeCategory`'s when the + /// exact `UserInterfaceSizeClass` is not important. + public let defaultRuleSet: SizeClassRuleSet + + /// A set of `UserInterfaceSizeClass` specific rule sets to provide different accessible layouts + /// for specific size class combinations. + public let sizeClassSpecificRuleSets: [SizeClassRuleSet] + + /// A lightweight typealias for a horizontal and vertical `UIUserInterfaceSizeClass` definition. + /// + /// See [Adaptivity and Layout](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/adaptivity-and-layout/) + /// on the Human Interface Guidelines for all possible combinations. + public typealias SizeClass = (horizontal: UIUserInterfaceSizeClass, vertical: UIUserInterfaceSizeClass) + + // MARK: - Initializers + + /// Initialize a `OCKResponsiveLayout` with default and specific size class rules. + /// + /// - Parameter defaultRuleSet: The default layout rules for when no matching size class rule is + /// provided, usually when layouts need to support dynamic type, but not size class. + /// - Parameter sizeClassSpecificRuleSets: Size class specific layout rule sets + public init( + defaultLayout: LayoutOption, + anySizeClassRuleSet: [OCKResponsiveLayout.Rule], + sizeClassSpecificRuleSets: [SizeClassRuleSet] = []) { + + let defaultRule = Rule(layout: defaultLayout, greaterThanOrEqualToContentSizeCategory: .unspecified) + + self.defaultRuleSet = SizeClassRuleSet( + sizeClasses: [(horizontal: .unspecified, vertical: .unspecified)], + rules: [defaultRule] + anySizeClassRuleSet + ) + + self.sizeClassSpecificRuleSets = sizeClassSpecificRuleSets + } + + // MARK: - Nested Definitions + + /// A layout rule for a given `UIContentSizeCategory`. + public struct Rule { + + /// A selected `UIContentSizeCategory` for the given layout. + public let contentSizeCategory: UIContentSizeCategory + + /// A provided layout to display at or above the given `UIContentSizeCategory`. + public let layout: Layout + + /// Initialize a rule with a `Layout` defined by the user and a `UIContentSizeCategory` to display + /// the layout at. + /// - Parameter layout: The `Layout` to display at or above the given `UIContentSizeCategory` + /// - Parameter contentSizeCategory: The `UIContentSizeCategory` that this layout will display at + /// or above + public init( + layout: Layout, + greaterThanOrEqualToContentSizeCategory contentSizeCategory: UIContentSizeCategory = .extraSmall + ) { + self.contentSizeCategory = contentSizeCategory + self.layout = layout + } + } + + /// A set of `UIContentSizeCategory` specific rules for a given size class. + public struct SizeClassRuleSet { + + /// A set of rules (combinations of `UIUserInterFaceSizeClass` combinations and user defined layouts. + public let rules: [OCKResponsiveLayout.Rule] + + /// The valid size class combinations for this set of rules + public let sizeClasses: [SizeClass] + + /// Initialize a `SizeClassRuleSet` with a set of `UIUserInterfaceSizeClass` combinations and + /// `UIContentSizeCategory` specific rules. + /// - Parameter sizeClasses: The `SizeClass` horizontal and vertical definitions for the rules + /// - Parameter rules: The `UIContentSizeCategory` rules for these size classes + public init( + sizeClasses: [SizeClass], + rules: [OCKResponsiveLayout.Rule] + ) { + self.sizeClasses = sizeClasses + self.rules = rules + } + + /// Initialize a `SizeClassRuleSet` with a `UIUserInterfaceSizeClass` combination and + /// `UIContentSizeCategory` specific rules. + /// - Parameter sizeClass: The `SizeClass` horizontal and vertical definition for the rules + /// - Parameter rules: The `UIContentSizeCategory` rules for this size class + public init( + sizeClass: SizeClass = (horizontal: .unspecified, vertical: .unspecified), + rules: [OCKResponsiveLayout.Rule] + ) { + self.init(sizeClasses: [sizeClass], rules: rules) + } + } + + // MARK: - Instance Methods + + /// Get a generic `LayoutOption` that has been mapped to a `UserInterfaceSizeClass` and + /// `UIContentSizeCategory` for comparison provided by a given `UITraitCollection`. + /// - Parameter traitCollection: The trait collection to extract device and accessility information. + /// + /// A UITraitCollection contains additional size and accessibility information beyond + /// `UserInterfaceSizeClass` and `UIContentSizeCategory`. This class and method could be extended + /// to respond to other changes beyond these two, however these are `Comparable` and provide a balance + /// between convenient and flexibility. Consider creating additional factory methods instead of + /// extending this method to respond to `contentSize` or `contentInsets` to maintain this convenience. + public func responsiveLayoutRule(traitCollection: UITraitCollection) -> LayoutOption { + + func setContainsCurrentSizeClass(set: SizeClassRuleSet) -> Bool { + return set.sizeClasses.contains { width, height -> Bool in + return width == traitCollection.horizontalSizeClass && height == traitCollection.verticalSizeClass + } + } + + func largestMatchingRule(rules: [Rule]) -> Rule? { + return rules.last { rule -> Bool in + return rule.contentSizeCategory <= traitCollection.preferredContentSizeCategory + } + } + + func layoutOptionForLayoutRuleSet(set: SizeClassRuleSet) -> LayoutOption { + let sorted = set.rules.sorted(by: { $0.contentSizeCategory < $1.contentSizeCategory }) + + guard let layout = + largestMatchingRule(rules: sorted)?.layout + ?? largestMatchingRule(rules: self.defaultRuleSet.rules)?.layout else { + fatalError( + """ + A layout could not be determined which should be impossible due to `defaultLayout: LayoutOption` in the + OCKResponsiveLayout class being non-optional. + """ + ) + } + + return layout + } + + let ruleSet = self.sizeClassSpecificRuleSets + .first(where: { setContainsCurrentSizeClass(set: $0) }) + ?? defaultRuleSet + + return layoutOptionForLayoutRuleSet(set: ruleSet) + + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/OCKAccessibleValue.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/OCKAccessibleValue.swift new file mode 100755 index 0000000..ffec615 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/OCKAccessibleValue.swift @@ -0,0 +1,68 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A value that scales with the current content size category. +struct OCKAccessibleValue { + + /// The value before scaling for the content size category. + internal private(set) var rawValue: CGFloat { + didSet { apply() } + } + + /// The value after scaling for the content size category. + var scaledValue: CGFloat { return rawValue.scaled() } + + private var keyPath: KeyPath + private let applyScaledValue: (_ scaledValue: CGFloat) -> Void + + init(container: Container, keyPath: KeyPath, apply: @escaping (_ scaledValue: CGFloat) -> Void) { + self.keyPath = keyPath + rawValue = container[keyPath: keyPath] + self.applyScaledValue = apply + } + + /// Update the raw value with a new container. Will use the existing keypath to set the raw value. + mutating func update(withContainer container: Container) { + rawValue = container[keyPath: keyPath] + } + + /// Update the raw value with a new container and keypath to access the raw value. + mutating func update(withContainer container: Container, keyPath: KeyPath) { + self.keyPath = keyPath + rawValue = container[keyPath: keyPath] + } + + /// Apply the scaled value. + func apply() { + self.applyScaledValue(scaledValue) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Protocols/OCKCardable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Protocols/OCKCardable.swift new file mode 100755 index 0000000..b4079ed --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Protocols/OCKCardable.swift @@ -0,0 +1,69 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Has the ability to display one's self as a card. A card has a particular corner +/// radius and shadow. +public protocol OCKCardable { + /// View that will be styled as a card. Should hold the `contentView`. + var cardView: UIView { get } + + /// Holds the main content. Subviews should be added to this view. + var contentView: UIView { get } +} + +public extension OCKCardable { + /// Turn the card styling on/off. If this view is stylable, this method should be called from the `styleDidChange` method. Note that shadow + /// rastering is set on by default, and consequently a shadow cannot be set over a clear background. + /// - Parameter enabled: true to turn the card styling on. + /// - Parameter style: The style to use for the card. + func enableCardStyling(_ enabled: Bool, style: OCKStyler) { + cardView.backgroundColor = style.color.secondaryCustomGroupedBackground + cardView.layer.masksToBounds = false + cardView.layer.cornerCurve = .continuous + cardView.layer.cornerRadius = enabled ? style.appearance.cornerRadius2 : 0 + cardView.layer.shadowColor = enabled ? style.color.black.cgColor : UIColor.clear.cgColor + cardView.layer.shadowOffset = style.appearance.shadowOffset1 + cardView.layer.shadowRadius = enabled ? style.appearance.shadowRadius1 : 0 + cardView.layer.shadowOpacity = enabled ? style.appearance.shadowOpacity1 : 0 + cardView.layer.rasterizationScale = enabled ? UIScreen.main.scale : 0 + cardView.layer.shouldRasterize = enabled + + contentView.layer.cornerCurve = .continuous + contentView.layer.cornerRadius = cardView.layer.cornerRadius + } +} + +/// Auxiliary object to handle the `OCKCardable` protocol. +struct OCKCardBuilder: OCKCardable { + let cardView: UIView + let contentView: UIView +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStylable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStylable.swift new file mode 100755 index 0000000..be0737c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStylable.swift @@ -0,0 +1,93 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +// An object that can be styled. +public protocol OCKStylable: AnyObject { + /// Used to override the style. + var customStyle: OCKStyler? { get set } + + /// Returns in order of existence: This object's custom style, the first parent with a custom style, or the default style. + func style() -> OCKStyler + + /// Called when the style changes. + func styleDidChange() +} + +/// In order to propogate style through the view hierearchy: +/// 1. Call `styleChildren()` from a `didSet` observer on `customStyle`. +/// 2. Call `styleChildren()` from `removeFromSuperView()`. +/// 3. Call `styleDidChange()` from `didMoveToSuperview()`. +public extension OCKStylable where Self: UIView { + /// Returns in order of existence: This object's custom style, the first parent with a custom style, or the default style. + func style() -> OCKStyler { + return customStyle ?? getParentCustomStyle() ?? OCKStyle() + } + + /// Notify this view and subviews that the style has changed. Guarantees that the outermost view's `styleDidChange` method will be called after + /// that of inner views. + func styleChildren() { + recursiveStyleChildren() + styleDidChange() + } +} + +private extension UIView { + // Find the first custom style in the superview hierarchy. + func getParentCustomStyle() -> OCKStyler? { + guard let superview = superview else { return nil } + + // if the view has a custom style, return it + if let typedSuperview = superview as? OCKStylable, let customStyle = typedSuperview.customStyle { + return customStyle + } + + // else check if the superview has a custom style + return superview.getParentCustomStyle() + } + + // Recursively notify subviews that the style has changed. + func recursiveStyleChildren() { + for view in subviews { + // Propogate style through any `UIView`s + guard let typedView = view as? OCKStylable & UIView else { + view.recursiveStyleChildren() + continue + } + + // Propogate style to subviews that are not the child of a view that has set a custom style + if typedView.customStyle == nil { + typedView.recursiveStyleChildren() + typedView.styleDidChange() + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStyler.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStyler.swift new file mode 100755 index 0000000..a9d4dbe --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/OCKStyler.swift @@ -0,0 +1,52 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// Defines styling constants. +public protocol OCKStyler { + var color: OCKColorStyler { get } + var animation: OCKAnimationStyler { get } + var appearance: OCKAppearanceStyler { get } + var dimension: OCKDimensionStyler { get } +} + +/// Defines default values for style constants. +public extension OCKStyler { + var color: OCKColorStyler { OCKColorStyle() } + var animation: OCKAnimationStyler { OCKAnimationStyle() } + var appearance: OCKAppearanceStyler { OCKAppearanceStyle() } + var dimension: OCKDimensionStyler { OCKDimensionStyle() } +} + +// Concrete object that contains style constants +public struct OCKStyle: OCKStyler { + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAnimationStyler.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAnimationStyler.swift new file mode 100755 index 0000000..990eebe --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAnimationStyler.swift @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Defines constants for values used during animations. +public protocol OCKAnimationStyler { + var stateChangeDuration: Double { get } +} + +/// Default animation values. +public extension OCKAnimationStyler { + var stateChangeDuration: Double { 0.2 } +} + +/// Concrete object for animation constants. +public struct OCKAnimationStyle: OCKAnimationStyler { + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAppearanceStyler.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAppearanceStyler.swift new file mode 100755 index 0000000..78c5697 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKAppearanceStyler.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Defines constants for view appearance styling. +public protocol OCKAppearanceStyler { + var shadowOpacity1: Float { get } + var shadowRadius1: CGFloat { get } + var shadowOffset1: CGSize { get } + var opacity1: CGFloat { get } + var lineWidth1: CGFloat { get } + + var cornerRadius1: CGFloat { get } + var cornerRadius2: CGFloat { get } + + var borderWidth1: CGFloat { get } + var borderWidth2: CGFloat { get } +} + +/// Default appearance values. +public extension OCKAppearanceStyler { + var shadowOpacity1: Float { 0.15 } + var shadowRadius1: CGFloat { 8 } + var shadowOffset1: CGSize { CGSize(width: 0, height: 2) } + var opacity1: CGFloat { 0.45 } + var lineWidth1: CGFloat { 4 } + + var cornerRadius1: CGFloat { 15 } + var cornerRadius2: CGFloat { 12 } + + var borderWidth1: CGFloat { 3 } + var borderWidth2: CGFloat { 1 } +} + +/// Concrete object for appearance constants. +public struct OCKAppearanceStyle: OCKAppearanceStyler { + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKColorStyler.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKColorStyler.swift new file mode 100755 index 0000000..7308a9c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKColorStyler.swift @@ -0,0 +1,102 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Defines color constants. +public protocol OCKColorStyler { + var label: UIColor { get } + var secondaryLabel: UIColor { get } + var tertiaryLabel: UIColor { get } + + var customBackground: UIColor { get } + var secondaryCustomBackground: UIColor { get } + + var customGroupedBackground: UIColor { get } + var secondaryCustomGroupedBackground: UIColor { get } + var tertiaryCustomGroupedBackground: UIColor { get } + + var separator: UIColor { get } + + var customFill: UIColor { get } + var secondaryCustomFill: UIColor { get } + var tertiaryCustomFill: UIColor { get } + var quaternaryCustomFill: UIColor { get } + + var customBlue: UIColor { get } + + var customGray: UIColor { get } + var customGray2: UIColor { get } + var customGray3: UIColor { get } + var customGray4: UIColor { get } + var customGray5: UIColor { get } + + var black: UIColor { get } + var white: UIColor { get } + var clear: UIColor { get } +} + +/// Defines default values for color constants. +public extension OCKColorStyler { + var label: UIColor { .label } + var secondaryLabel: UIColor { .secondaryLabel } + var tertiaryLabel: UIColor { .tertiaryLabel } + + var customBackground: UIColor { .systemBackground } + var secondaryCustomBackground: UIColor { .secondarySystemBackground } + + var customGroupedBackground: UIColor { .systemGroupedBackground } + var secondaryCustomGroupedBackground: UIColor { .secondarySystemGroupedBackground } + var tertiaryCustomGroupedBackground: UIColor { .tertiarySystemGroupedBackground } + + var separator: UIColor { .separator } + + var customFill: UIColor { .tertiarySystemFill } + var secondaryCustomFill: UIColor { .secondarySystemFill } + var tertiaryCustomFill: UIColor { .tertiarySystemFill } + var quaternaryCustomFill: UIColor { .quaternarySystemFill } + + var customBlue: UIColor { .systemBlue } + + var customGray: UIColor { .systemGray } + var customGray2: UIColor { .systemGray2 } + var customGray3: UIColor { .systemGray3 } + var customGray4: UIColor { .systemGray4 } + var customGray5: UIColor { .systemGray5 } + + var white: UIColor { .white } + var black: UIColor { .black } + var clear: UIColor { .clear } +} + +/// Concrete object for color constants. +public struct OCKColorStyle: OCKColorStyler { + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKDimensionStyler.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKDimensionStyler.swift new file mode 100755 index 0000000..9816e11 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Style/Stylers/OCKDimensionStyler.swift @@ -0,0 +1,92 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A configurator that defines constants view sizes. +public protocol OCKDimensionStyler { + var separatorHeight: CGFloat { get } + + var lineWidth1: CGFloat { get } + var stackSpacing1: CGFloat { get } + + var imageHeight2: CGFloat { get } + var imageHeight1: CGFloat { get } + + var pointSize3: CGFloat { get } + var pointSize2: CGFloat { get } + var pointSize1: CGFloat { get } + + var buttonHeight3: CGFloat { get } + var buttonHeight2: CGFloat { get } + var buttonHeight1: CGFloat { get } + + var symbolPointSize5: CGFloat { get } + var symbolPointSize4: CGFloat { get } + var symbolPointSize3: CGFloat { get } + var symbolPointSize2: CGFloat { get } + var symbolPointSize1: CGFloat { get } + + var directionalInsets2: NSDirectionalEdgeInsets { get } + var directionalInsets1: NSDirectionalEdgeInsets { get } +} + +/// Default dimension values. +public extension OCKDimensionStyler { + var separatorHeight: CGFloat { 1.0 / UIScreen.main.scale } + + var lineWidth1: CGFloat { 4 } + var stackSpacing1: CGFloat { 8 } + + var imageHeight2: CGFloat { 40 } + var imageHeight1: CGFloat { 150 } + + var pointSize3: CGFloat { 11 } + var pointSize2: CGFloat { 14 } + var pointSize1: CGFloat { 17 } + + var buttonHeight3: CGFloat { 20 } + var buttonHeight2: CGFloat { 50 } + var buttonHeight1: CGFloat { 60 } + + var symbolPointSize5: CGFloat { 8 } + var symbolPointSize4: CGFloat { 12 } + var symbolPointSize3: CGFloat { 16 } + var symbolPointSize2: CGFloat { 20 } + var symbolPointSize1: CGFloat { 30 } + + var directionalInsets2: NSDirectionalEdgeInsets { .init(top: 8, leading: 9, bottom: 8, trailing: 8) } + var directionalInsets1: NSDirectionalEdgeInsets { .init(top: 16, leading: 16, bottom: 16, trailing: 16) } +} + +/// Concrete object for cdimesnion constants. +public struct OCKDimensionStyle: OCKDimensionStyler { + public init() {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKHeaderView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKHeaderView.swift new file mode 100755 index 0000000..50c4f5a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKHeaderView.swift @@ -0,0 +1,264 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A title and detail label. The view can also be configured to show a separator, +/// icon image, and a detail disclosure arrow. +/// +/// +----------------------------------------+ +/// | +----+ | +/// | |icon| Title [detail | +/// | |img | Detail disclosure] | +/// | +----+ | +/// | | +/// | ------------------------------------ | +/// | | +/// +----------------------------------------+ +/// +open class OCKHeaderView: OCKView { + + private enum Constants { + static let spacing: CGFloat = 4 + } + + /// Configuration for a header view. + public struct Configuration { + /// Flag to show a separator under the text in the view. + public var showsSeparator: Bool = false + + /// Flag to show an image on the trailing end of the view. The default image is an arrow. + public var showsDetailDisclosure: Bool = false + + /// Flag to show an image on the leading side of the text in the view. + public var showsIconImage: Bool = false + } + + // MARK: Properties + + /// Vertical stack view that holds the main content. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView(style: .plain) + stackView.axis = .vertical + return stackView + }() + + /// The image on the trialing end of the view. The default image is an arrow. Depending on the configuration, this may be nil. + public let detailDisclosureImage: UIImageView? + + /// Multi-line title label above `detailLabel` + public let titleLabel: OCKLabel = { + let label = OCKLabel(textStyle: .headline, weight: .bold) + label.numberOfLines = 0 + label.animatesTextChanges = true + return label + }() + + /// Multi-line detail label below `titleLabel`. + public let detailLabel: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .medium) + label.numberOfLines = 0 + label.animatesTextChanges = true + return label + }() + + /// The image on the leading end of the text in the view. Depending on the configuration, this may be ni. + public let iconImageView: UIImageView? + + /// The configuration for the view. + private let configuration: Configuration + + /// Stack view that holds the text content in the header. + private let headerTextStackView = OCKStackView.vertical() + + /// Stack view that holds the content in the header. + private let headerStackView: OCKStackView = { + let stackView = OCKStackView.horizontal() + stackView.alignment = .center + return stackView + }() + + private var iconImageHeightConstraint: NSLayoutConstraint? + + private lazy var iconHeight = OCKAccessibleValue(container: style(), keyPath: \.dimension.imageHeight2) { [weak self] newHeight in + self?.iconImageHeightConstraint?.constant = newHeight + } + + private lazy var detailDisclosurePointSize = OCKAccessibleValue(container: style(), + keyPath: \.dimension.symbolPointSize4) { [detailDisclosureImage] newPointSize in + detailDisclosureImage?.preferredSymbolConfiguration = .init(pointSize: newPointSize) + } + + /// Separator between the header and the body. + private let separatorView: OCKSeparatorView? + + // MARK: Life Cycle + + /// Create the view with a configuration block. The configuration block determines which views the header should show. + public init(configurationHandler: (inout Configuration) -> Void = { _ in }) { + var configuration = Configuration() + configurationHandler(&configuration) + self.configuration = configuration + + iconImageView = configuration.showsIconImage ? OCKHeaderView.makeIconImageView() : nil + detailDisclosureImage = configuration.showsDetailDisclosure ? OCKHeaderView.makeDetailDisclosureImage() : nil + separatorView = configuration.showsSeparator ? OCKSeparatorView() : nil + super.init() + + accessibilityTraits = configuration.showsDetailDisclosure ? [.header, .button] : [.header] + } + + public required init?(coder aDecoder: NSCoder) { + self.configuration = Configuration() + iconImageView = nil + detailDisclosureImage = nil + separatorView = nil + super.init(coder: aDecoder) + } + + // MARK: Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + styleSubviews() + isAccessibilityElement = true + } + + private func addSubviews() { + [titleLabel, detailLabel].forEach { headerTextStackView.addArrangedSubview($0) } + [headerTextStackView].forEach { headerStackView.addArrangedSubview($0) } + [headerStackView].forEach { contentStackView.addArrangedSubview($0) } + + // Setup dynamic views based on the configuration + if let separatorView = separatorView { contentStackView.addArrangedSubview(separatorView) } + if let detailDisclosureImage = detailDisclosureImage { headerStackView.addArrangedSubview(detailDisclosureImage) } + if let iconImageView = iconImageView { headerStackView.insertArrangedSubview(iconImageView, at: 0) } + + addSubview(contentStackView) + } + + private func styleSubviews() { + let margin = style().dimension.directionalInsets1.top + contentStackView.spacing = margin + headerStackView.spacing = margin / 2.0 + headerTextStackView.spacing = margin / 4.0 + contentStackView.setCustomSpacing(margin, after: headerStackView) + } + + private static func makeIconImageView() -> UIImageView { + let imageView = OCKCircleImageView() + imageView.contentMode = .scaleAspectFill + return imageView + } + + private static func makeDetailDisclosureImage() -> UIImageView { + let image = UIImage(systemName: "chevron.right") + let imageView = UIImageView(image: image) + return imageView + } + + private func constrainSubviews() { + contentStackView.translatesAutoresizingMaskIntoConstraints = false + detailDisclosureImage?.setContentHuggingPriority(.defaultHigh, for: .horizontal) + iconImageView?.setContentHuggingPriority(.defaultHigh, for: .horizontal) + var constraints = contentStackView.constraints(equalTo: self) + + if let imageView = iconImageView { + imageView.translatesAutoresizingMaskIntoConstraints = false + iconImageHeightConstraint = imageView.heightAnchor.constraint(equalToConstant: iconHeight.scaledValue) + constraints += [ + imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor), + iconImageHeightConstraint! + ] + } + + NSLayoutConstraint.activate(constraints) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + titleLabel.textColor = style.color.label + detailLabel.textColor = style.color.label + + detailDisclosureImage?.tintColor = style.color.customGray3 + iconImageView?.tintColor = style.color.customGray3 + + iconHeight.update(withContainer: style) + detailDisclosurePointSize.update(withContainer: style) + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { + [iconHeight, detailDisclosurePointSize].forEach { $0.apply() } + } + } +} + +private class OCKCircleImageView: UIImageView { + + private let maskLayer = CAShapeLayer() + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + override init(image: UIImage?) { + super.init(image: image) + setup() + } + + override init(image: UIImage?, highlightedImage: UIImage?) { + super.init(image: image, highlightedImage: highlightedImage) + setup() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + maskLayer.path = CGPath(ellipseIn: bounds, transform: nil) + maskLayer.backgroundColor = UIColor.black.cgColor + + layer.mask = maskLayer + clipsToBounds = true + } + + override func layoutSubviews() { + super.layoutSubviews() + maskLayer.path = CGPath(ellipseIn: bounds, transform: nil) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKSeparatorView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKSeparatorView.swift new file mode 100755 index 0000000..57c85c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKSeparatorView.swift @@ -0,0 +1,70 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import UIKit + +/// Horizontal separator view. +open class OCKSeparatorView: OCKView { + // MARK: Properties + + private var heightConstraint: NSLayoutConstraint? + + // MARK: Methods + + override func setup() { + super.setup() + constrainSubviews() + styleDidChange() + } + + private func constrainSubviews() { + translatesAutoresizingMaskIntoConstraints = false + heightConstraint = heightAnchor.constraint(equalToConstant: 0) + heightConstraint?.isActive = true + } + + override open func didMoveToSuperview() { + super.didMoveToSuperview() + styleDidChange() + } + + override open func removeFromSuperview() { + super.removeFromSuperview() + styleChildren() + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + backgroundColor = cachedStyle.color.separator + heightConstraint?.constant = cachedStyle.dimension.separatorHeight + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKStackView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKStackView.swift new file mode 100755 index 0000000..79e5161 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKStackView.swift @@ -0,0 +1,352 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A stack view that supports animating showing/hiding arranged subviews, +/// and has the option of dynamically creating separators when arranged subviews are added. +open class OCKStackView: UIStackView, OCKStylable { + + /// Types of animations that are applied to the stack view. + /// + /// - fade: Animate opacity. + /// - hidden: Animate the isHidden property. + enum Animation { + case fade, hidden + } + + // MARK: Properties + + public var customStyle: OCKStyler? { + didSet { styleChildren() } + } + + /// The style for the stack view. + /// + /// - plain: A normal stack view. + /// - separated: Creates separators between arranges subview. + public enum Style { + case plain, separated + } + + /// The style of the stack view. + public let style: Style + + /// Flag determines if the top and bottom separators are shown when the style of the stack view is separated + public var showsOuterSeparators = true { + didSet { + guard style == .separated else { return } + subviews.first?.removeFromSuperview() + subviews.last?.removeFromSuperview() + } + } + + // MARK: Life Cycle + + /// Create the stack view with a style. A plain style is a typical stack view. A separated + /// style will automatically create separators between arranged subviews whenever they're + /// added. + /// + /// - Parameter style: The style for the stack view. + public init(style: Style = .plain) { + self.style = style + super.init(frame: .zero) + if style == .separated { axis = .vertical } + preservesSuperviewLayoutMargins = true + styleDidChange() + } + + @available(*, unavailable) + public required init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + static func vertical() -> OCKStackView { + let stackView = OCKStackView() + stackView.axis = .vertical + return stackView + } + + static func horizontal() -> OCKStackView { + let stackView = OCKStackView() + stackView.axis = .horizontal + return stackView + } + + // MARK: Methods + + override open func didMoveToSuperview() { + super.didMoveToSuperview() + styleDidChange() + } + + override open func removeFromSuperview() { + super.removeFromSuperview() + styleChildren() + } + + open func styleDidChange() {} + + /// The ordered subviews. When the stack view is a separated style, this will not + /// include the separators. + override open var arrangedSubviews: [UIView] { + switch style { + case .plain: + return super.arrangedSubviews + case .separated: + return showsOuterSeparators ? + super.arrangedSubviews.enumerated().filter { $0.0 % 2 != 0 }.map { $0.1 } : // all odd subviews + super.arrangedSubviews.enumerated().filter { $0.0 % 2 == 0 }.map { $0.1 } // all even subviews + } + } + + /// Add a subview to the end of the stack view. If the style is separated, + /// separators will automatically be added. + /// + /// - Parameter view: The view to add. + override open func addArrangedSubview(_ view: UIView) { + switch style { + case .plain: + super.addArrangedSubview(view) + case .separated: + let viewsToAdd = makeSeparators(withView: view) + viewsToAdd.forEach { super.addArrangedSubview($0) } + } + } + + /// Add a subview to the end of the stack view. If the style is separated, + /// separators will automatically be added. Provides the option to animate + /// showing the new view. + /// + /// - Parameters: + /// - view: The view to add. + /// - animated: Flag that determines if the view should animated on screen. + open func addArrangedSubview(_ view: UIView, animated: Bool) { + guard animated else { + addArrangedSubview(view) + return + } + + let viewsToAdd = makeSeparators(withView: view) + viewsToAdd.forEach { + $0.isHidden = true + super.addArrangedSubview($0) + } + toggleViews(viewsToAdd, shouldShow: true, animated: animated) + } + + /// Insert an arranged subview at a particular index in the stack view. If the style is + /// separated, separators will be automatically added. Provides the option to animate + /// showing the new view. + /// + /// - Parameters: + /// - view: The view to add. + /// - stackIndex: Index in the stack view to add the view. + /// - animated: Flag that determines if the view should animated on screen. + open func insertArrangedSubview(_ view: UIView, at stackIndex: Int, animated: Bool) { + guard animated else { + insertArrangedSubview(view, at: stackIndex) + return + } + + let viewsToAdd = makeSeparators(withView: view) + for (index, view) in viewsToAdd.enumerated() { + view.isHidden = true + super.insertArrangedSubview(view, at: index + stackIndex) + } + toggleViews(viewsToAdd, shouldShow: true, animated: animated) + } + + /// Insert an arranged subview at a particular index in the stack view. If the style is + /// separated, separators will automatically be added. + /// + /// - Parameters: + /// - view: The view to add. + /// - stackIndex: Index in the stack view to add the view. + override open func insertArrangedSubview(_ view: UIView, at stackIndex: Int) { + switch style { + case .plain: + super.insertArrangedSubview(view, at: stackIndex) + case .separated: + let viewsToAdd = makeSeparators(withView: view) + for (index, view) in viewsToAdd.enumerated() { + super.insertArrangedSubview(view, at: index + stackIndex) + } + } + } + + /// Remove an arranged subview from the stack view. If the style is separated, + /// the separators will be automatically removed. + /// + /// - Parameter view: The view to remove. + override open func removeArrangedSubview(_ view: UIView) { + switch style { + case .plain: + super.removeArrangedSubview(view) + case .separated: + let viewsToRemove = getSeparators(withView: view) + viewsToRemove.forEach { $0.removeFromSuperview() } + } + } + + /// Remove an arranged subview from the stack view. If the style is separated, + /// the separators will be automatically removed. Option to animated the removal of the + /// view. + /// + /// - Parameters: + /// - view: The view to remove. + /// - animated: Flag that determines if the view removal should be animated. + open func removeArrangedSubview(_ view: UIView, animated: Bool) { + let viewsToRemove = getSeparators(withView: view) + + let removeBlock = { + viewsToRemove.forEach { + $0.removeFromSuperview() + $0.isHidden = false + $0.alpha = 1 + } + } + + guard UIView.areAnimationsEnabled && animated else { + removeBlock() + return + } + + toggleViews(viewsToRemove, shouldShow: false, animated: animated) { complete in + guard complete else { return } + removeBlock() + } + } + + /// Batch view plus any needed separators + private func makeSeparators(withView view: UIView) -> [UIView] { + switch style { + case .plain: return [view] + case .separated: + var views: [UIView] = [] + if super.arrangedSubviews.isEmpty && showsOuterSeparators { + views.append(OCKSeparatorView()) + } else if !super.arrangedSubviews.isEmpty && !showsOuterSeparators { + views.append(OCKSeparatorView()) + } + views.append(view) + if showsOuterSeparators { + views.append(OCKSeparatorView()) + } + return views + } + } + + /// Get the separators included with a view + private func getSeparators(withView view: UIView) -> [UIView] { + switch style { + case .plain: + return [view] + case .separated: + guard let index = subviews.firstIndex(of: view) else { return [] } + + if showsOuterSeparators && index == 0 { + return Array(subviews[..<3]) + } else if !showsOuterSeparators && index == 0 { + return [subviews[0]] + } else { + return Array(subviews[index - 1 ..< index + 1]) + } + } + } + + /// Clear the views in the stack view. + /// + /// - Parameter animated: Flag to animate the removal of the views. + public func clear(animated: Bool = false) { + let removeViewsBlock = { [weak self] in + self?.subviews.forEach { $0.removeFromSuperview() } + } + + guard UIView.areAnimationsEnabled && animated else { + removeViewsBlock() + return + } + + toggleViews(subviews, shouldShow: false, animated: true) { complete in + guard complete else { return } + removeViewsBlock() + } + } + + /// Hide or show the specified views in the stack view. + /// + /// - Parameters: + /// - views: The views to hide or show. + /// - shouldShow: True if the views should be shown, false to hide them. + /// - animated: Animate the visibility of the views. + /// - animations: The particular animations to use when toggling the visibility. + /// - completion: Block to run when the visibility toggling and any animations are complete. + func toggleViews( + _ views: [UIView], + shouldShow: Bool, + animated: Bool, + animations: [Animation] = [.fade, .hidden], + completion: ((Bool) -> Void)? = nil) { + views.forEach { guard $0.superview == self else { return } } + + // skip animation + guard animated else { + views.forEach { $0.isHidden = !shouldShow } + return + } + + var completionWillBeCalled = false + + if animations.contains(.hidden) { + let filteredViews = views.filter { $0.isHidden == shouldShow } // only animated views that are not yet animated + filteredViews.forEach { $0.isHidden = shouldShow } + + UIView.animate(withDuration: style().animation.stateChangeDuration, delay: 0, options: .curveEaseOut, animations: { + filteredViews.forEach { $0.isHidden = !shouldShow } + }, completion: { complete in + if !completionWillBeCalled { completion?(complete) } + completionWillBeCalled = true + }) + } + + if animations.contains(.fade) { + let filteredViews = views.filter { $0.alpha == (shouldShow ? 0 : 1) } // only animated views that are not yet animated + filteredViews.forEach { $0.alpha = shouldShow ? 0 : 1 } + + UIView.animate(withDuration: style().animation.stateChangeDuration, delay: 0, options: .curveEaseOut, animations: { + filteredViews.forEach { $0.alpha = shouldShow ? 1 : 0 } + }, completion: { complete in + if !completionWillBeCalled { completion?(complete) } + completionWillBeCalled = true + }) + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKView.swift new file mode 100755 index 0000000..8013fad --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Common/Views/OCKView.swift @@ -0,0 +1,64 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +open class OCKView: UIView, OCKStylable { + public var customStyle: OCKStyler? { + didSet { styleChildren() } + } + + public init() { + super.init(frame: .zero) + setup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + func setup() { + preservesSuperviewLayoutMargins = true + styleDidChange() + } + + open func styleDidChange() {} + + override open func didMoveToSuperview() { + super.didMoveToSuperview() + styleDidChange() + } + + override open func removeFromSuperview() { + super.removeFromSuperview() + styleChildren() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKCalendarDisplayable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKCalendarDisplayable.swift new file mode 100755 index 0000000..b6d5a5a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKCalendarDisplayable.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Any object that can display and handle interactions with a calendar. A calendar displays information about a specified range of days. +public protocol OCKCalendarDisplayable: AnyObject { + /// Handles events related to an `OCKCalendarDisplayable` object. + var delegate: OCKCalendarViewDelegate? { get set } +} + +/// Handles events related to an `OCKCalendarDisplayable` object. +public protocol OCKCalendarViewDelegate: AnyObject { + /// Called when a particular date in the calendar was selected. + /// - Parameter calendarView: The view displaying the calendar. + /// - Parameter date: The date that was selected. + /// - Parameter index: The index of the date that was selected with respect to the collection of days in the current `dateInterval`. + /// - Parameter sender: The sender that initiated the selection. + func calendarView(_ calendarView: UIView & OCKCalendarDisplayable, didSelectDate date: Date, at index: Int, sender: Any?) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKWeekCalendarView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKWeekCalendarView.swift new file mode 100755 index 0000000..6f20f56 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/OCKWeekCalendarView.swift @@ -0,0 +1,175 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A horizontal row of seven selectable completion rings and corresponding labels. +/// +/// +--------------------------------------+ +/// | [title] [title] [title] [title] | +/// | | +/// | o o o o o o o o | +/// | o o o o o o ... o o | +/// | o o o o o o o o | +/// +--------------------------------------+ +/// +open class OCKWeekCalendarView: OCKView, OCKCalendarDisplayable { + + // MARK: Properties + + /// The currently selected date in the calendar. + public private (set) var selectedDate = Date() + + /// Handles events related to an `OCKCalendarDisplayable` object. + public weak var delegate: OCKCalendarViewDelegate? + + /// The date interval of the week currently being displayed. + public private (set) var dateInterval = Calendar.current.dateIntervalOfWeek(for: Date()) + + /// The completion ring buttons in the view. There will be one ring for each day in the `dateInterval`. + public private (set) lazy var completionRingButtons: [OCKCompletionRingButton] = { + var rings = [OCKCompletionRingButton]() + let numberOfDays = Calendar.current.dateComponents([.day], from: dateInterval.start, to: dateInterval.end).day! + for _ in 0...numberOfDays { + let ringButton = OCKCompletionRingButton() + ringButton.handlesSelection = false + ringButton.setState(.dimmed, animated: false) + ringButton.addTarget(self, action: #selector(handleSelection(sender:)), for: .touchUpInside) + rings.append(ringButton) + } + return rings + }() + + /// Holds the completion ring buttons in the view. + private let stackView: OCKStackView = { + let stackView = OCKStackView.horizontal() + stackView.distribution = .fillEqually + return stackView + }() + + private let dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "dd" + return formatter + }() + + // MARK: - Life Cycle + + /// A view that displays interactable completion rings for each day in a week. The week is computed based on the provided date parameter. + /// - Parameters: + /// - date: Will display the week of the provided date. + public init(weekOfDate date: Date) { + self.dateInterval = Calendar.current.dateIntervalOfWeek(for: date) + selectedDate = date + super.init() + setup() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + // MARK: - Methods + + override func setup() { + super.setup() + addSubview(stackView) + + stackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate( + stackView.constraints(equalTo: layoutMarginsGuide, directions: [.horizontal]) + + stackView.constraints(equalTo: self, directions: [.vertical]) + ) + + completionRingButtons.forEach { stackView.addArrangedSubview($0) } + completionRingButtons.first?.sendActions(for: .touchUpInside) + updateRingLabels() + } + + private func updateRingLabels() { + let numberOfDays = Calendar.current.dateComponents([.day], from: dateInterval.start, to: dateInterval.end).day! + for index in 0...numberOfDays { + let date = Calendar.current.date(byAdding: .day, value: index, to: dateInterval.start)! + completionRingButtons[index].label.text = dateFormatter.string(from: date) + } + } + + private func dateAt(index: Int) -> Date { + return Calendar.current.date(byAdding: .day, value: index, to: dateInterval.start)! + } + + @objc + private func handleSelection(sender: UIControl) { + for ring in completionRingButtons where ring != sender { + ring.isSelected = false + } + sender.isSelected = true + guard let ringIndex = (completionRingButtons as [UIControl]).firstIndex(of: sender) else { fatalError("Unexpected button") } + selectedDate = dateAt(index: ringIndex) + delegate?.calendarView(self, didSelectDate: selectedDate, at: ringIndex, sender: sender) + } + + /// Select the completion ring that corresponds to the given date. + /// - Parameter date: The date of the ring to select. + public func selectDate(_ date: Date) { + completionRingButtons.first(where: { $0.isSelected })?.isSelected = false + if let ring = completionRingFor(date: date) { + ring.isSelected = true + selectedDate = date + } else { + showDate(date) + selectDate(date) + } + } + + /// Get the completion ring that corresponds to a particular date. + /// - Parameter date: The date that corresponds to the desired completion ring. + /// - Returns: The completion ring that matches the given date. + public func completionRingFor(date: Date) -> OCKCompletionRingButton? { + let offset = abs(Calendar.current.dateComponents([.day], from: dateInterval.start, to: date).day!) + guard offset < completionRingButtons.count else { return nil } + return completionRingButtons[offset] + } + + /// Display the week for the given date. Each ring will correspond to one day in the week. + /// - Parameter date: The date to display. + public func showDate(_ date: Date) { + dateInterval = Calendar.current.dateIntervalOfWeek(for: date) + updateRingLabels() + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + stackView.spacing = cachedStyle.dimension.directionalInsets1.leading + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Buttons/OCKCompletionRingButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Buttons/OCKCompletionRingButton.swift new file mode 100755 index 0000000..b54462e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Buttons/OCKCompletionRingButton.swift @@ -0,0 +1,129 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A selectable completion ring with an inner check view and a title label. +open class OCKCompletionRingButton: OCKAnimatedButton { + + // MARK: Properties + + /// Label above the completion ring. + public let label: OCKLabel = { + let label = OCKCappedSizeLabel(textStyle: .caption1, weight: .semibold) + label.maxFontSize = 20 + return label + }() + + /// A fillable ring view. + public let ring = OCKCompletionRingView() + + /// The completion state of the ring + public private (set) var completionState = CompletionState.empty + + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.alignment = .center + stackView.distribution = .fillProportionally + return stackView + }() + + public enum CompletionState: Equatable { + case dimmed + case empty + case zero + case progress(_ value: CGFloat) + } + + // MARK: - Life cycle + + public init() { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + public required init?(coder: NSCoder) { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + // MARK: - Methods + + override open func styleDidChange() { + super.styleDidChange() + updateRingColors() + ring.lineWidth = style().appearance.lineWidth1 + } + + override open func setStyleForSelectedState(_ isSelected: Bool) { + updateRingColors() + } + + /// Called when the tint color of the view changes. + override open func tintColorDidChange() { + updateRingColors() + ring.strokeColor = tintColor + } + + /// Changes the display state of the button + /// + /// - Parameters: + /// - state: The state that the completion ring button will be set to. + /// - animated: Determines if the change will be animated or instantaneous. + public func setState(_ state: CompletionState, animated: Bool) { + completionState = state + switch state { + case .dimmed: ring.setProgress(0, animated: animated) + case .empty: ring.setProgress(0, animated: animated) + case .zero: ring.setProgress(0.001, animated: animated) + case .progress(let value): ring.setProgress(value, animated: animated) + } + updateRingColors() + } + + private func setup() { + addSubviews() + } + + private func updateRingColors() { + let cachedStyle = style() + let grooveStrokeColor = completionState == .dimmed ? cachedStyle.color.customGray3 : cachedStyle.color.customGray + let deselectedLabelColor = completionState == .dimmed ? cachedStyle.color.tertiaryLabel : cachedStyle.color.label + + label.textColor = isSelected ? tintColor : deselectedLabelColor + ring.grooveView.strokeColor = grooveStrokeColor + ring.strokeColor = tintColor + } + + private func addSubviews() { + addSubview(contentStackView) + [label, ring].forEach { contentStackView.addArrangedSubview($0) } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKCompletionRingView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKCompletionRingView.swift new file mode 100755 index 0000000..d4bcab4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKCompletionRingView.swift @@ -0,0 +1,151 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A fillable ring with an inner checkmark. +open class OCKCompletionRingView: OCKView { + + // MARK: Properties + + override open var intrinsicContentSize: CGSize { + let height = style().dimension.buttonHeight2 + return CGSize(width: height, height: height) + } + + /// The progress value of the ring view. + public var progress: CGFloat { + return ringView.progress + } + + /// The duration for the ring and check view animations. + public var duration: TimeInterval { + get { return ringView.duration } + set { ringView.duration = newValue } + } + + /// The line width of the ring and check views. + public var lineWidth: CGFloat { + get { return ringView.lineWidth } + set { + grooveView.lineWidth = newValue + ringView.lineWidth = newValue + } + } + + /// The stroke color of the ring and check views. + public var strokeColor: UIColor = OCKStyle().color.customBlue { + didSet { + ringView.strokeColor = strokeColor + checkmarkImageView.tintColor = strokeColor + } + } + + private lazy var checkmarkAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.7) + + /// The fillable ring view. + let ringView = OCKRingView() + + /// The groove in which the fillable ring resides. + let grooveView = OCKRingView() + + /// The checkmark image view inside of the ring view. + let checkmarkImageView: UIImageView = { + let image = UIImage(systemName: "checkmark") + let imageView = UIImageView(image: image) + imageView.contentMode = .scaleAspectFit + return imageView + }() + + // MARK: - Methods + + /// Set the progress value for the ring view. The ring will fill accordingly, and if full + /// the checkmark will display. + /// + /// - Parameters: + /// - value: The progress value. + /// - animated: Flag for the ring and check view animations. + public func setProgress(_ value: CGFloat, animated: Bool = true) { + let isComplete = value >= 1.0 + if checkmarkAnimator.isRunning { + checkmarkAnimator.stopAnimation(true) + } + + let animationHandler: () -> Void = { [weak self] in + self?.checkmarkImageView.transform = isComplete ? CGAffineTransform(scaleX: 1, y: 1) : CGAffineTransform(scaleX: 0.1, y: 0.1) + self?.checkmarkImageView.alpha = isComplete ? 1 : 0 + } + + if animated { + checkmarkAnimator.addAnimations(animationHandler) + checkmarkAnimator.startAnimation() + } else { + animationHandler() + } + + ringView.setProgress(value, animated: animated) + } + + override open func styleDidChange() { + super.styleDidChange() + invalidateIntrinsicContentSize() + let style = self.style() + strokeColor = tintColor + grooveView.strokeColor = style.color.customGray3 + checkmarkImageView.preferredSymbolConfiguration = .init(pointSize: style.dimension.symbolPointSize4, weight: .bold) + } + + override func setup() { + super.setup() + grooveView.alpha = 0.25 + grooveView.setProgress(1.0, animated: false) + + setProgress(0, animated: false) + + checkmarkImageView.tintColor = strokeColor + ringView.strokeColor = strokeColor + + [grooveView, ringView, checkmarkImageView].forEach { + addSubview($0) + $0.translatesAutoresizingMaskIntoConstraints = false + } + + var constraints = + grooveView.constraints(equalTo: self) + + ringView.constraints(equalTo: self) + + constraints += [ + checkmarkImageView.centerXAnchor.constraint(equalTo: centerXAnchor), + checkmarkImageView.centerYAnchor.constraint(equalTo: centerYAnchor) + ] + + NSLayoutConstraint.activate(constraints) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKRingView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKRingView.swift new file mode 100755 index 0000000..c4bbd7d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Calendar/Ring/Views/OCKRingView.swift @@ -0,0 +1,131 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A fillable progress ring drawing. +class OCKRingView: OCKView { + + // MARK: Properties + + /// The progress of the ring between 0 and 1. The ring will fill based on the value. + private(set) var progress: CGFloat = 1.0 + + private let ringLayer: CAShapeLayer = { + let layer = CAShapeLayer() + layer.lineCap = .round + layer.fillColor = nil + layer.strokeStart = 0 + return layer + }() + + /// The line width of the ring. + var lineWidth: CGFloat = 10 { + didSet { ringLayer.lineWidth = lineWidth } + } + + /// The stroke color of the ring. + var strokeColor: UIColor = OCKStyle().color.customBlue { + didSet { ringLayer.strokeColor = strokeColor.cgColor } + } + + /// The start angle of the ring to begin drawing. + var startAngle: CGFloat = -.pi / 2 { + didSet { ringLayer.path = ringPath() } + } + + /// The end angle of the ring to end drawing. + var endAngle: CGFloat = 1.5 * .pi { + didSet { ringLayer.path = ringPath() } + } + + /// Duration of the ring's fill animation. + var duration: TimeInterval = 1.0 + + /// The radius oof the ring. + var radius: CGFloat { + return min(bounds.height, bounds.width) / 2 - lineWidth / 2 + } + + // MARK: Life Cycle + + override func layoutSubviews() { + super.layoutSubviews() + configureRing() + } + + // MARK: Methods + + override func setup() { + super.setup() + layer.addSublayer(ringLayer) + styleRingLayer() + } + + /// Set the progress value of the ring. The ring will fill based on the value. + /// + /// - Parameters: + /// - value: Progress value between 0 and 1. + /// - animated: Flag for the fill ring's animation. + func setProgress(_ value: CGFloat, animated: Bool) { + layoutIfNeeded() + + let oldValue = ringLayer.presentation()?.strokeEnd ?? progress + progress = value + ringLayer.strokeEnd = progress + guard animated else { return } + + let path = #keyPath(CAShapeLayer.strokeEnd) + let fill = CABasicAnimation(keyPath: path) + fill.fromValue = oldValue + fill.toValue = value + fill.duration = duration + fill.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) + ringLayer.add(fill, forKey: "fill") + } + + private func styleRingLayer() { + strokeColor = tintColor + ringLayer.strokeColor = strokeColor.cgColor + ringLayer.strokeEnd = min(progress, 1.0) + ringLayer.lineWidth = lineWidth + } + + private func configureRing() { + ringLayer.frame = bounds + ringLayer.path = ringPath() + } + + private func ringPath() -> CGPath { + let center = CGPoint(x: bounds.origin.x + frame.width / 2.0, y: bounds.origin.y + frame.height / 2.0) + let circlePath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true) + return circlePath.cgPath + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKBarPlotView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKBarPlotView.swift new file mode 100755 index 0000000..ce7d6d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKBarPlotView.swift @@ -0,0 +1,77 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A graph that displays one or more vertical bar plots. +class OCKBarPlotView: OCKGradientPlotView { + + override func resetLayers() { + let graphRect = graphBounds() + let offsets = computeBarOffsets() + resolveNumberOfLayers() + dataSeries.enumerated().forEach { index, series in + let layer = seriesLayers[index] + layer.dataPoints = series.dataPoints + layer.horizontalOffset = offsets[index] + layer.startColor = series.gradientStartColor ?? tintColor + layer.endColor = series.gradientEndColor ?? tintColor + layer.barWidth = series.size + layer.setPlotBounds(rect: graphRect) + layer.frame = bounds + } + } + + // Adjust the x coordinates of the data series so that the bar charts line up next to one another. + // This does take into account that bars might have different widths. + private func computeBarOffsets() -> [CGFloat] { + let barSizes = dataSeries.map { $0.size } + let groupWidth = barSizes.reduce(0, +) + let offset = -groupWidth / 2 + let adjustments = barSizes.enumerated().map { seriesIndex, size -> CGFloat in + let combinedWidthOfPreviousBars = barSizes[0.. dataSeries.count { + let oldLayer = seriesLayers.removeLast() + oldLayer.removeFromSuperlayer() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKGradientPlotView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKGradientPlotView.swift new file mode 100755 index 0000000..eaab20e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKGradientPlotView.swift @@ -0,0 +1,106 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +private let accessibilityElementBoundingBoxSize = CGSize(width: 10, height: 10) + +/// This is an abstract base class for plots that use a gradient mask. +class OCKGradientPlotView : UIView, OCKGradientPlotable, OCKMultiPlotable { + + let gradientLayer = CAGradientLayer() + let pointsLayer = CAShapeLayer() + + func makePath(points: [CGPoint]) -> CGPath { + return UIBezierPath().cgPath + } + + var dataSeries: [OCKDataSeries] = [] { + didSet { resetLayers() } + } + + var xMinimum: CGFloat? { + didSet { seriesLayers.forEach { $0.xMinimum = xMinimum } } + } + + var xMaximum: CGFloat? { + didSet { seriesLayers.forEach { $0.xMaximum = xMaximum } } + } + + var yMinimum: CGFloat? { + didSet { seriesLayers.forEach { $0.yMinimum = yMinimum } } + } + + var yMaximum: CGFloat? { + didSet { seriesLayers.forEach { $0.yMaximum = yMaximum } } + } + + var seriesLayers: [LayerType] = [] + + override var intrinsicContentSize: CGSize { + return CGSize(width: 200, height: 75) + } + + override func layoutSubviews() { + super.layoutSubviews() + seriesLayers.forEach { $0.frame = bounds } + resetAccessibilityElements() + } + + func resetLayers() { + fatalError("This method must be overridden in subclasses!") + } + + func resetAccessibilityElements() { + accessibilityElements = [] + + dataSeries.enumerated().forEach { seriesIndex, series in + series.dataPoints.enumerated().forEach { pointIndex, point in + + let pointInViewSpace = seriesLayers[seriesIndex].convert(graphSpacePoints: [point]).first! + let axOrigin = CGPoint(x: pointInViewSpace.x - accessibilityElementBoundingBoxSize.width / 2, + y: pointInViewSpace.y - accessibilityElementBoundingBoxSize.height / 2) + let axFrame = CGRect(origin: axOrigin, size: accessibilityElementBoundingBoxSize) + + // Create the labels for this data point + let useProvidedLabel = pointIndex < series.accessibilityLabels.count + let label = useProvidedLabel ? series.accessibilityLabels[pointIndex] : "\(series.title), \(point.x), \(point.y)" + + // Create an accessibility element for this singular data point + let element = UIAccessibilityElement(accessibilityContainer: self) + element.accessibilityFrameInContainerSpace = axFrame + element.accessibilityLabel = label + element.accessibilityTraits = UIAccessibilityTraits.staticText + + accessibilityElements?.append(element) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKLinePlotView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKLinePlotView.swift new file mode 100755 index 0000000..8ff6ccc --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKLinePlotView.swift @@ -0,0 +1,77 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Interactable line graph. The difference between this and `OCKLineGraphLayer` is that this has the +/// ability to respond to touches +class OCKLinePlotView: OCKGradientPlotView { + + override func resetLayers() { + let graphRect = graphBounds() + let offsets = computeLineOffsets() + resolveNumberOfLayers() + dataSeries.enumerated().forEach { index, series in + let layer = seriesLayers[index] + layer.dataPoints = series.dataPoints + layer.offset = offsets[index] + layer.startColor = series.gradientStartColor ?? tintColor + layer.endColor = series.gradientEndColor ?? tintColor + layer.lineWidth = series.size + layer.setPlotBounds(rect: graphRect) + layer.frame = bounds + } + } + + // Adjust the x coordinates of the data series so that two identical lines are slightly offset, so as to be distinguishable. + private func computeLineOffsets() -> [CGSize] { + guard !dataSeries.isEmpty else { return [] } + let spacing: CGFloat = 1.0 + let totalWidth = spacing * CGFloat(dataSeries.count - 1) + let startOffset = -totalWidth / 2 + var offsets = [CGSize]() + for index in 0.. dataSeries.count { + let oldLayer = seriesLayers.removeLast() + oldLayer.removeFromSuperlayer() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKScatterPlotView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKScatterPlotView.swift new file mode 100755 index 0000000..6f1fb78 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Gradient Plots/OCKScatterPlotView.swift @@ -0,0 +1,76 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A graph view that shows one or more scatter plots +class OCKScatterPlotView: OCKGradientPlotView { + + override func resetLayers() { + let graphRect = graphBounds() + let offsets = computeLineOffsets() + resolveNumberOfLayers() + dataSeries.enumerated().forEach { index, series in + let layer = seriesLayers[index] + layer.dataPoints = series.dataPoints + layer.offset = offsets[index] + layer.startColor = series.gradientStartColor ?? tintColor + layer.endColor = series.gradientEndColor ?? tintColor + layer.markerSize = series.size + layer.setPlotBounds(rect: graphRect) + layer.frame = bounds + } + } + + // Adjust the x coordinates of the data series so that two identical lines are slightly offset, so as to be distinguishable. + private func computeLineOffsets() -> [CGSize] { + guard !dataSeries.isEmpty else { return [] } + let spacing: CGFloat = 1.0 + let totalWidth = spacing * CGFloat(dataSeries.count - 1) + let startOffset = -totalWidth / 2 + var offsets = [CGSize]() + for index in 0.. dataSeries.count { + let oldLayer = seriesLayers.removeLast() + oldLayer.removeFromSuperlayer() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKBarLayer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKBarLayer.swift new file mode 100755 index 0000000..f6c0114 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKBarLayer.swift @@ -0,0 +1,105 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKBarLayer: OCKCartesianCoordinatesLayer, OCKGradientPlotable { + let gradientLayer = CAGradientLayer() + let pointsLayer = CAShapeLayer() + + var startColor: UIColor = OCKStyle().color.customGray { + didSet { gradientLayer.colors = [startColor.cgColor, endColor.cgColor] } + } + + var endColor: UIColor = OCKStyle().color.customGray { + didSet { gradientLayer.colors = [startColor.cgColor, endColor.cgColor] } + } + + var barWidth: CGFloat = 10 { + didSet { setNeedsLayout() } + } + + var horizontalOffset: CGFloat = 0 { + didSet { setNeedsLayout() } + } + + override init() { + super.init() + setupSublayers() + } + + override init(layer: Any) { + super.init(layer: layer) + setupSublayers() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupSublayers() + } + + private func setupSublayers() { + gradientLayer.colors = [startColor.cgColor, endColor.cgColor] + gradientLayer.startPoint = CGPoint(x: 0.5, y: 1) + gradientLayer.endPoint = CGPoint(x: 0.5, y: 0) + gradientLayer.mask = pointsLayer + addSublayer(gradientLayer) + + pointsLayer.fillColor = OCKStyle().color.customGray.cgColor + pointsLayer.strokeColor = nil + } + + override func layoutSublayers() { + super.layoutSublayers() + drawPoints(points) + } + + override func animateInGraphCoordinates(from oldPoints: [CGPoint], to newPoints: [CGPoint]) { + let grow = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) + grow.fromValue = pointsLayer.presentation()?.path ?? makePath(points: oldPoints) + grow.toValue = makePath(points: newPoints) + grow.timingFunction = CAMediaTimingFunction(name: .easeOut) + grow.duration = 1.0 + pointsLayer.add(grow, forKey: "grow") + } + + func makePath(points: [CGPoint]) -> CGPath { + let path = UIBezierPath() + for point in points { + let origin = CGPoint(x: point.x - barWidth / 2 + horizontalOffset, y: point.y) + let size = CGSize(width: barWidth, height: bounds.height - point.y) + let rectangle = CGRect(origin: origin, size: size) + let cornerRadii = CGSize(width: barWidth / 4, height: barWidth / 4) + let rectPath = UIBezierPath(roundedRect: rectangle, byRoundingCorners: [.topLeft, .topRight], cornerRadii: cornerRadii) + path.append(rectPath) + } + return path.cgPath + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKCartesianCoordinatesLayer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKCartesianCoordinatesLayer.swift new file mode 100755 index 0000000..f685a13 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKCartesianCoordinatesLayer.swift @@ -0,0 +1,207 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Base class that provides graph coordinates for use in plotting numeric data. +class OCKCartesianCoordinatesLayer: CALayer, OCKSinglePlotable { + static var defaultWidth: CGFloat { return 10.0 } + static var defaultHeight: CGFloat { return 10.0 } + + /// Data points for the graph. + var dataPoints: [CGPoint] = [] { + didSet { + orderedDataPoints = dataPoints.sorted { $0.x < $1.x } + let oldPoints = points + points = convert(graphSpacePoints: orderedDataPoints) + setNeedsLayout() + + // Don't animate if the data sets don't match. Prevents weird scaling animation the very first time data is set. + if oldPoints.count == points.count { + animateInGraphCoordinates(from: oldPoints, to: points) + } + } + } + + func animateInGraphCoordinates(from oldPoints: [CGPoint], to newPoints: [CGPoint]) {} + + func setPlotBounds(rect: CGRect) { + xMinimum = rect.minX + xMaximum = rect.maxX + yMinimum = rect.minY + yMaximum = rect.maxY + } + + /// Minimum x value dislpayed in the graph. + var xMinimum: CGFloat? { + didSet { setNeedsLayout() } + } + + /// Maximum x value displayed in the graph. + var xMaximum: CGFloat? { + didSet { setNeedsLayout() } + } + + /// Minimum y values displayed in the graph. + var yMinimum: CGFloat? { + didSet { setNeedsLayout() } + } + + /// Maximum y value displayed in the graph. + var yMaximum: CGFloat? { + didSet { setNeedsLayout() } + } + + /// Default width of the graph. + var defaultWidth: CGFloat { + return 100 + } + + /// Default height of the graph. + var defaultHeight: CGFloat { + return 100 + } + + private (set) var points: [CGPoint] = [] + private (set) var orderedDataPoints: [CGPoint] = [] + + /// Create an instance if a graoh layer. + override init() { + super.init() + setNeedsLayout() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setNeedsLayout() + } + + override init(layer: Any) { + super.init(layer: layer) + setNeedsLayout() + } + + override func layoutSublayers() { + super.layoutSublayers() + points = convert(graphSpacePoints: orderedDataPoints) + } + + /// Get the rectangle that will be displayed in graph space. + /// + /// - Returns: The rectangle in graph space. + func graphBounds() -> CGRect { + let xCoords = dataPoints.map { $0.x } + let xMin = xMinimum ?? xCoords.min() ?? 0 + let xMax = xMaximum ?? xCoords.max() ?? defaultWidth + let width = xMax - xMin + + let yCoords = dataPoints.map { $0.y } + let yMin = yMinimum ?? yCoords.min() ?? 0 + let yMax = yMaximum ?? yCoords.max() ?? defaultHeight + let height = yMax - yMin + + return CGRect(x: xMin, y: yMin, width: width, height: height) + } + + /// Convert a CGPoint to graph coordinates. + /// + /// - Parameter point: The point in screen space. + /// - Returns: The point in graph space. + func graphCoordinates(at point: CGPoint) -> CGPoint { + return convert(viewSpacePoints: [point]).first! + } + + /// Distance is calculated only in the horizontal direction + + /// Get the closest graph coordinates for a given view coordinate. + /// + /// - Parameter location: The coordinate in screen space. + /// - Returns: The closest coordinate in graph space, and the correspoing screen coordinate. + func closestDataPoint(toViewCoordinates location: CGPoint) -> (viewCoordinates: CGPoint, graphCoordinates: CGPoint)? { + guard !orderedDataPoints.isEmpty else { return nil } + let graphCoords = graphCoordinates(at: location) + let distances = orderedDataPoints.map { point -> CGFloat in + let dx = graphCoords.x - point.x + let distance = sqrt(pow(dx, 2)) + return distance + } + let minDistance = distances.min()! + let indexOfMin = distances.firstIndex(of: minDistance)! + let closestViewCoords = points[indexOfMin] + let closestGraphCoords = orderedDataPoints[indexOfMin] + return (closestViewCoords, closestGraphCoords) + } + + private struct Bounds { + let lower: CGFloat + let upper: CGFloat + } + + /// Converts points from graph space to view space + func convert(graphSpacePoints points: [CGPoint]) -> [CGPoint] { + let graphRect = graphBounds() + let viewRect = bounds + + let graphXBounds = Bounds(lower: graphRect.minX, upper: graphRect.maxX) + let viewXBounds = Bounds(lower: viewRect.minX, upper: viewRect.maxX) + let xMapper = make2DMapper(from: graphXBounds, to: viewXBounds) + + let graphYBounds = Bounds(lower: graphRect.minY, upper: graphRect.maxY) + let viewYBounds = Bounds(lower: viewRect.minY, upper: viewRect.maxY) + let yMapper = make2DMapper(from: graphYBounds, to: viewYBounds) + + return points.map { CGPoint(x: xMapper($0.x), y: viewRect.height - yMapper($0.y)) } + } + + /// Converts points from view space to graph space + private func convert(viewSpacePoints points: [CGPoint]) -> [CGPoint] { + let graphRect = graphBounds() + let viewRect = bounds + + let graphXBounds = Bounds(lower: graphRect.minX, upper: graphRect.maxX) + let viewXBounds = Bounds(lower: viewRect.minX, upper: viewRect.maxX) + let xMapper = make2DMapper(from: viewXBounds, to: graphXBounds) + + let graphYBounds = Bounds(lower: graphRect.minY, upper: graphRect.maxY) + let viewYBounds = Bounds(lower: viewRect.maxY, upper: viewRect.minY) + let yMapper = make2DMapper(from: viewYBounds, to: graphYBounds) + + return points.map { CGPoint(x: xMapper($0.x), y: yMapper($0.y)) } + } + + /// Creates a method that linearly interpolate between two sets of bounds + private func make2DMapper(from start: Bounds, to end: Bounds) -> ((CGFloat) -> CGFloat) { + let rise = end.upper - end.lower + let run = start.upper - start.lower + let slope = rise / run + let intercept = end.lower - start.lower * slope + return { slope * $0 + intercept } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKGridLayer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKGridLayer.swift new file mode 100755 index 0000000..61175c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKGridLayer.swift @@ -0,0 +1,175 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// This layer shows horizontal grid lines and is intended to be added as a background to various kinds of graphs. +class OCKGridLayer: OCKCartesianCoordinatesLayer { + private enum Constants { + static let margin: CGFloat = 16 + } + + /// The number of vertical lines in the grid. + var numberOfVerticalDivisions = 4 { + didSet { setNeedsLayout() } + } + + /// The color of the grid lines. + var gridLineColor: UIColor = OCKStyle().color.customGray { + didSet { + bottomGridLine.strokeColor = gridLineColor.cgColor + gridLines.strokeColor = gridLineColor.cgColor + } + } + + var gridLineWidth: CGFloat = 0.7 { + didSet { + gridLines.lineWidth = gridLineWidth + bottomGridLine.lineWidth = gridLineWidth + } + } + + var gridLineOpacity: CGFloat = 0.25 { + didSet { + gridLines.opacity = Float(gridLineOpacity) + bottomGridLine.opacity = Float(gridLineOpacity) + } + } + + var fontSize: CGFloat = 10 { + didSet { setNeedsLayout() } + } + + let gridLines = CAShapeLayer() + let bottomGridLine = CAShapeLayer() + let topValueLayer = CATextLayer() + let middleValueLayer = CATextLayer() + + /// Create an instance of a grid layer. + override init() { + super.init() + setup() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + /// Create an instance of a grid layer by specifying the layer class. + /// + /// - Parameter layer: Layer class to use as this object's layer. + override init(layer: Any) { + super.init(layer: layer) + setup() + } + + func setup() { + addSublayer(gridLines) + addSublayer(bottomGridLine) + addSublayer(topValueLayer) + addSublayer(middleValueLayer) + } + + override func layoutSublayers() { + super.layoutSublayers() + redraw() + } + + private func redraw() { + drawBottomGridLine() + drawMiddleGridLines() + drawTopValue() + drawMiddleValue() + } + + private func drawBottomGridLine() { + bottomGridLine.path = pathForBottomLine().cgPath + bottomGridLine.lineCap = .round + bottomGridLine.lineWidth = gridLineWidth + bottomGridLine.strokeColor = gridLineColor.cgColor + bottomGridLine.opacity = Float(gridLineOpacity) + bottomGridLine.fillColor = nil + bottomGridLine.frame = bounds + } + + private func drawMiddleGridLines() { + gridLines.path = pathForMiddleLines().cgPath + gridLines.lineDashPattern = [2, 2] + gridLines.lineWidth = gridLineWidth + gridLines.strokeColor = gridLineColor.cgColor + gridLines.opacity = Float(gridLineOpacity) + gridLines.fillColor = nil + gridLines.frame = bounds + } + + private func drawTopValue() { + topValueLayer.contentsScale = UIScreen.main.scale + topValueLayer.string = "\(graphBounds().height)" + topValueLayer.foregroundColor = gridLineColor.cgColor + topValueLayer.fontSize = fontSize + topValueLayer.frame = CGRect(origin: CGPoint(x: Constants.margin, y: 0), size: CGSize(width: 100, height: 44)) + } + + private func drawMiddleValue() { + middleValueLayer.contentsScale = UIScreen.main.scale + middleValueLayer.string = "\(graphBounds().height / 2)" + middleValueLayer.foregroundColor = gridLineColor.cgColor + middleValueLayer.fontSize = fontSize + middleValueLayer.frame = CGRect(origin: CGPoint(x: Constants.margin, y: bounds.height / 2), size: CGSize(width: 100, height: 44)) + } + + private func pathForBottomLine() -> UIBezierPath { + let bottomLeft = CGPoint(x: 0, y: bounds.height - gridLineWidth / 2) + let bottomRight = CGPoint(x: bounds.width, y: bounds.height - gridLineWidth / 2) + let path = UIBezierPath() + path.move(to: bottomLeft) + path.addLine(to: bottomRight) + return path + } + + private func pathForMiddleLines() -> UIBezierPath { + let path = UIBezierPath() + for heigth in middleLineHeights() { + path.move(to: CGPoint(x: 0, y: heigth)) + path.addLine(to: CGPoint(x: bounds.width, y: heigth)) + } + return path + } + + private func middleLineHeights() -> [CGFloat] { + let spacing = bounds.height / CGFloat(numberOfVerticalDivisions) + var heights = [CGFloat](repeating: 0, count: numberOfVerticalDivisions) + for index in 0.. CGPath { + let path = UIBezierPath() + guard let firstPoint = points.first else { return path.cgPath } + path.move(to: firstPoint) + for (index, point) in points.enumerated() { + guard index > 0 else { continue } + let adjustedPoint = CGPoint(x: point.x + offset.width, y: point.y + offset.height) + path.addLine(to: adjustedPoint) + + if index == points.count - 1 { + path.addArc(withCenter: adjustedPoint, radius: lineWidth, startAngle: 0, endAngle: 2 * .pi, clockwise: true) + } + } + return path.cgPath + } + + private func animateLine(from oldPoints: [CGPoint], to newPoints: [CGPoint]) { + let grow = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) + grow.fromValue = line.presentation()?.path ?? linePath(for: oldPoints) + grow.toValue = linePath(for: newPoints) + grow.duration = 1.0 + line.add(grow, forKey: "grow") + } + + private func animateOutline(from oldPoints: [CGPoint], to newPoints: [CGPoint]) { + let grow = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) + grow.fromValue = outline.presentation()?.path ?? linePath(for: oldPoints) + grow.toValue = linePath(for: newPoints) + grow.duration = 1.0 + outline.add(grow, forKey: "grow") + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKScatterLayer.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKScatterLayer.swift new file mode 100755 index 0000000..d4bbfca --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Layers/OCKScatterLayer.swift @@ -0,0 +1,101 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKScatterLayer: OCKCartesianCoordinatesLayer, OCKGradientPlotable { + let gradientLayer = CAGradientLayer() + let pointsLayer = CAShapeLayer() + + var markerSize: CGFloat = 3.0 { + didSet { pointsLayer.path = makePath(points: points) } + } + + var startColor: UIColor = OCKStyle().color.customGray { + didSet { gradientLayer.colors = [startColor.cgColor, endColor.cgColor] } + } + + var endColor: UIColor = OCKStyle().color.customGray { + didSet { gradientLayer.colors = [startColor.cgColor, endColor.cgColor] } + } + + var offset: CGSize = .zero { + didSet { setNeedsLayout() } + } + + override init() { + super.init() + setupSublayers() + } + + override init(layer: Any) { + super.init(layer: layer) + setupSublayers() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupSublayers() + } + + private func setupSublayers() { + pointsLayer.strokeColor = nil + addSublayer(pointsLayer) + + gradientLayer.colors = [startColor.cgColor, endColor.cgColor] + gradientLayer.startPoint = CGPoint(x: 0.5, y: 1) + gradientLayer.endPoint = CGPoint(x: 0.5, y: 0) + gradientLayer.mask = pointsLayer + addSublayer(gradientLayer) + } + + override func layoutSublayers() { + super.layoutSublayers() + drawPoints(points) + } + + override func animateInGraphCoordinates(from oldPoints: [CGPoint], to newPoints: [CGPoint]) { + let grow = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path)) + grow.fromValue = pointsLayer.presentation()?.path ?? makePath(points: oldPoints) + grow.toValue = makePath(points: newPoints) + grow.duration = 1.0 + pointsLayer.add(grow, forKey: "grow") + } + + func makePath(points: [CGPoint]) -> CGPath { + let path = UIBezierPath() + points.forEach { point in + let adjustedPoint = CGPoint(x: point.x + offset.width, y: point.y + offset.height) + path.move(to: adjustedPoint) + path.addArc(withCenter: adjustedPoint, radius: markerSize, startAngle: 0, endAngle: 2 * .pi, clockwise: true) + } + return path.cgPath + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianChartView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianChartView.swift new file mode 100755 index 0000000..c547489 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianChartView.swift @@ -0,0 +1,120 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import UIKit + +open class OCKCartesianChartView: OCKView, OCKChartDisplayable { + + // MARK: Properties + + private let contentView = OCKView() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + private let headerContainerView = UIView() + + /// Handles events related to an `OCKChartDisplayable` object. + public weak var delegate: OCKChartViewDelegate? + + /// Vertical stack view that + public let contentStackView: OCKStackView = { + let stackView = OCKStackView() + stackView.axis = .vertical + return stackView + }() + + /// A default `OCKHeaderView`. + public let headerView = OCKHeaderView() + + /// The main content of the view. + public let graphView: OCKCartesianGraphView + + // MARK: - Life Cycle + + /// Create a chart with a specified type. Available charts include bar, plot, and scatter. + /// + /// - Parameter type: The type of the chart. + public init(type: OCKCartesianGraphView.PlotType) { + graphView = OCKCartesianGraphView(type: type) + super.init() + setup() + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + setupGestures() + } + + private func setupGestures() { + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapHeader)) + headerView.addGestureRecognizer(tapGesture) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(contentStackView) + headerContainerView.addSubview(headerView) + [headerContainerView, graphView].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, contentStackView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentStackView.constraints(equalTo: self, directions: [.horizontal]) + + contentStackView.constraints(equalTo: layoutMarginsGuide, directions: [.vertical]) + + headerView.constraints(equalTo: headerContainerView.layoutMarginsGuide, directions: [.horizontal]) + + headerView.constraints(equalTo: headerContainerView, directions: [.vertical]) + + contentStackView.constraints(equalTo: contentView)) + } + + @objc + private func didTapHeader() { + delegate?.didSelectChartView(self) + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + cardBuilder.enableCardStyling(true, style: cachedStyle) + contentStackView.spacing = cachedStyle.dimension.directionalInsets1.top + directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + headerContainerView.directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianGraphView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianGraphView.swift new file mode 100755 index 0000000..4520782 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKCartesianGraphView.swift @@ -0,0 +1,195 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Displays a `OCKMultiGraphableView` above an axis. The initializer takes an enum `PlotType` that allows you to choose from +/// several common graph types. +/// +/// +-------------------------------------------------------+ +/// | | +/// | [title] | +/// | [detail] | +/// | | +/// | [graph] | +/// | | +/// +-------------------------------------------------------+ +/// +open class OCKCartesianGraphView: OCKView, OCKMultiPlotable { + + /// An enumerator specifying the types of plots this view can display. + public enum PlotType: String, CaseIterable { + case line + case scatter + case bar + } + + // MARK: Properties + + /// The data points displayed in the graph. + public var dataSeries: [OCKDataSeries] { + get { return plotView.dataSeries } + set { + updateScaling(for: newValue) + plotView.dataSeries = newValue + legend.setDataSeries(newValue) + } + } + + /// The labels for the horizontal axis. + public var horizontalAxisMarkers: [String] = [] { + didSet { axisView.axisMarkers = horizontalAxisMarkers } + } + + /// Get the bounds of the graph. + /// + /// - Returns: The bounds of the graph. + public func graphBounds() -> CGRect { + return plotView.graphBounds() + } + + /// The minimum x value in the graph. + public var xMinimum: CGFloat? { + get { return plotView.xMinimum } + set { + plotView.xMinimum = newValue + gridView.xMinimum = newValue + } + } + + /// The maximum x value in the graph. + public var xMaximum: CGFloat? { + get { return plotView.xMaximum } + set { + plotView.xMaximum = newValue + gridView.xMaximum = newValue + } + } + + /// The minimum y value in the graph. + public var yMinimum: CGFloat? { + get { return plotView.yMinimum } + set { + plotView.yMinimum = newValue + gridView.yMinimum = newValue + } + } + + /// The maximum y value in the graph. + public var yMaximum: CGFloat? { + get { return plotView.yMaximum } + set { + plotView.yMaximum = newValue + gridView.yMaximum = newValue + } + } + + /// The index of the selected label in the x-axis. + public var selectedIndex: Int? { + get { return axisView.selectedIndex } + set { axisView.selectedIndex = newValue } + } + + private let gridView: OCKGridView + private let plotView: UIView & OCKMultiPlotable + private let axisView: OCKGraphAxisView + private let axisHeight: CGFloat = 44 + private let horizontalPlotPadding: CGFloat = 50 + private let legend = OCKGraphLegendView() + + // MARK: - Life Cycle + + /// Create a graph view with the specified style. + /// + /// - Parameter plotType: The style of the graph view. + public init(type: PlotType) { + self.gridView = OCKGridView() + self.axisView = OCKGraphAxisView() + self.plotView = { + switch type { + case .line: return OCKLinePlotView() + case .scatter: return OCKScatterPlotView() + case .bar: return OCKBarPlotView() + } + }() + super.init() + setup() + } + + @available(*, unavailable) + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Methods + + override open func tintColorDidChange() { + super.tintColorDidChange() + axisView.tintColor = tintColor + } + + private func updateScaling(for dataSeries: [OCKDataSeries]) { + let maxValue = max(CGFloat(gridView.numberOfDivisions), dataSeries.flatMap { $0.dataPoints }.map { $0.y }.max() ?? 0) + let chartMax = ceil(maxValue / CGFloat(gridView.numberOfDivisions)) * CGFloat(gridView.numberOfDivisions) + plotView.yMaximum = chartMax + gridView.yMaximum = chartMax + } + + override func setup() { + super.setup() + [gridView, plotView, axisView, legend].forEach { addSubview($0) } + + gridView.xMinimum = plotView.xMinimum + gridView.xMaximum = plotView.xMaximum + gridView.yMinimum = plotView.yMinimum + gridView.yMaximum = plotView.yMaximum + + [gridView, plotView, axisView, legend].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + + NSLayoutConstraint.activate([ + gridView.topAnchor.constraint(equalTo: plotView.topAnchor), + gridView.leadingAnchor.constraint(equalTo: leadingAnchor), + gridView.trailingAnchor.constraint(equalTo: trailingAnchor), + gridView.bottomAnchor.constraint(equalTo: plotView.bottomAnchor), + plotView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: horizontalPlotPadding), + plotView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -horizontalPlotPadding), + plotView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + plotView.bottomAnchor.constraint(equalTo: axisView.topAnchor), + axisView.leadingAnchor.constraint(equalTo: plotView.leadingAnchor), + axisView.trailingAnchor.constraint(equalTo: plotView.trailingAnchor), + axisView.heightAnchor.constraint(equalToConstant: axisHeight), + axisView.bottomAnchor.constraint(equalTo: legend.topAnchor), + legend.leadingAnchor.constraint(greaterThanOrEqualTo: safeAreaLayoutGuide.leadingAnchor), + legend.trailingAnchor.constraint(lessThanOrEqualTo: safeAreaLayoutGuide.trailingAnchor), + legend.centerXAnchor.constraint(equalTo: centerXAnchor), + legend.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor) + ]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKDataSeries.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKDataSeries.swift new file mode 100755 index 0000000..113b56d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKDataSeries.swift @@ -0,0 +1,125 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Representa a single group of data to be plotted. In most cases, CareKit plots accept multiple data +/// series, allowing for for several data series to be plotted on a single axis for easy comparison. +/// - SeeAlso: `OCKGraphView` +public struct OCKDataSeries: Equatable { + /// An array of points given in plot space Cartesian coordinates + /// The plot origin (0, 0) is in the bottom left hand corner. + public var dataPoints: [CGPoint] + + /// A title for this data series that will be displayed in the plot legend. + public var title: String + + /// The start color of the gradient this data series will be plotted in. + public var gradientStartColor: UIColor? + + /// The end color of the gradient this data series will be plotted in. + public var gradientEndColor: UIColor? + + /// A size specifying how large this data series should appear on the plot. + /// Its precise interpretation may vary depending on plot type used. + public var size: CGFloat + + /// Used to set the accessibility labels of each of the data points. + /// This array should either be empty or contain the same number of elements as the data series array. + public var accessibilityLabels: [String] = [] + + /// Creates a new data series that can be passed to chart to be plotted. The series will be plotted in a single + /// solid color. Use this initialize if you wish to plot data at precise or irregular intervals. + /// + /// - Parameters: + /// - dataPoints: An array of points in graph space Cartesian coordinates. The origin is in bottom left corner. + /// - title: A title that will be used to represent this data series in the plot legend. + /// - color: A solid color to be used when plotting the data series. + /// - size: A size specifying how large this data series should appear on the plot. + public init(dataPoints: [CGPoint], title: String, size: CGFloat = 10, color: UIColor? = nil) { + self.dataPoints = dataPoints + self.title = title + self.gradientStartColor = color + self.gradientEndColor = color + self.size = size + } + + /// Creates a new data series that can be passed to chart to be plotted. The series will be plotted with a gradient + /// color scheme. Use this initialize if you wish to plot data at precise or irregular intervals. + /// + /// - Parameters: + /// - dataPoints: An array of points in graph space Cartesian coordinates. The origin is in bottom left corner. + /// - title: A title that will be used to represent this data series in the plot legend. + /// - gradientStartColor: The start color for the gradient. + /// - gradientEndColor: The end color for the gradient. + /// - size: A size specifying how large this data series should appear on the plot. + public init(dataPoints: [CGPoint], title: String, gradientStartColor: UIColor, gradientEndColor: UIColor, size: CGFloat = 10) { + self.dataPoints = dataPoints + self.title = title + self.size = size + self.gradientStartColor = gradientStartColor + self.gradientEndColor = gradientEndColor + } + + /// Creates a new data series that can be passed to chart to be plotted. The series will be plotted in a single solid color. + /// Values will be evenly spaced when displayed on a chart. Use this option when the x coordinate is not particularly + /// meaningful, such as when creating bar charts. + /// + /// - Parameters: + /// - values: An array of values in graph space Cartesian coordinates. + /// - title: A title that will be used to represent this data series in the plot legend. + /// - size: A size specifying how large this data series should appear on the plot. + /// - color: The color that this data series will be plotted in. + public init(values: [CGFloat], title: String, size: CGFloat = 10, color: UIColor? = nil) { + self.dataPoints = values.enumerated().map { CGPoint(x: CGFloat($0), y: $1) } + self.title = title + self.size = size + self.gradientStartColor = color + self.gradientEndColor = color + } + + /// Creates a new data series that can be passed to chart to be plotted. The series will be plotted with a gradient + /// color scheme. Values will be evenly spaced when displayed on a chart. Use this option when the x coordinate is not + /// particularly meaningful, such as when creating bar charts. + /// + /// - Parameters: + /// - values: An array of values in graph space Cartesian coordinates. + /// - title: A title that will be used to represent this data series in the plot legend. + /// - gradientStartColor: The start color for the gradient. + /// - gradientEndColor: The end color for the gradient. + /// - size: A size specifying how large this data series should appear on the plot. + public init(values: [CGFloat], title: String, gradientStartColor: UIColor, gradientEndColor: UIColor, size: CGFloat = 10) { + self.dataPoints = values.enumerated().map { CGPoint(x: CGFloat($0), y: $1) } + self.title = title + self.size = size + self.gradientStartColor = gradientStartColor + self.gradientEndColor = gradientEndColor + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphAxisView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphAxisView.swift new file mode 100755 index 0000000..a6cfd57 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphAxisView.swift @@ -0,0 +1,145 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKGraphAxisView: UIView { + var axisMarkers = [String]() { + didSet { redrawLabels() } + } + + var selectedIndex: Int? { + didSet { redrawLabels() } + } + + private var tickViews = [OCKCircleLabelView]() + + private func redrawLabels() { + tickViews.forEach { $0.removeFromSuperview() } + tickViews = axisMarkers.enumerated().map { index, text in + let view = OCKCircleLabelView(textStyle: .callout) + view.frame = frameForMarker(atIndex: index) + view.label.text = text + view.label.textAlignment = .center + view.label.isAccessibilityElement = false + view.isSelected = index == selectedIndex + return view + } + tickViews.forEach(addSubview) + } + + private func frameForMarker(atIndex index: Int) -> CGRect { + guard !axisMarkers.isEmpty else { return .zero } + guard axisMarkers.count > 1 else { return bounds } + let spacing = bounds.width / CGFloat(axisMarkers.count - 1) + let centerX = spacing * CGFloat(index) + let origin = CGPoint(x: centerX - spacing / 2, y: 0) + let size = CGSize(width: spacing, height: bounds.height) + let rect = CGRect(origin: origin, size: size) + return rect + } + + override func layoutSubviews() { + super.layoutSubviews() + tickViews.enumerated().forEach { index, view in + view.frame = frameForMarker(atIndex: index) + } + } +} + +private class OCKCircleLabelView: OCKView { + let label: OCKLabel + + var circleLayer: CAShapeLayer { + guard let layer = layer as? CAShapeLayer else { fatalError("Unsupported type.") } + return layer + } + + override class var layerClass: AnyClass { + return CAShapeLayer.self + } + + override func tintColorDidChange() { + super.tintColorDidChange() + circleLayer.fillColor = isSelected ? tintColor.cgColor : nil + } + + var isSelected: Bool = false { + didSet { + updateLabelColor() + circleLayer.fillColor = isSelected ? tintColor.cgColor : nil + } + } + + init(textStyle: UIFont.TextStyle) { + label = OCKCappedSizeLabel(textStyle: .caption1, weight: .medium) + super.init() + setup() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("Unsupported initializer") + } + + override func setup() { + super.setup() + addSubview(label) + updateLabelColor() + + label.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + label.centerXAnchor.constraint(equalTo: centerXAnchor), + label.centerYAnchor.constraint(equalTo: centerYAnchor), + label.widthAnchor.constraint(lessThanOrEqualTo: widthAnchor), + label.heightAnchor.constraint(lessThanOrEqualTo: heightAnchor) + ]) + } + + override func layoutSubviews() { + super.layoutSubviews() + let padding: CGFloat = 4.0 + let maxDimension = max(label.intrinsicContentSize.width, label.intrinsicContentSize.height) + padding + let size = CGSize(width: maxDimension, height: maxDimension) + let origin = CGPoint(x: label.center.x - maxDimension / 2, y: label.center.y - maxDimension / 2) + + circleLayer.path = UIBezierPath(ovalIn: CGRect(origin: origin, size: size)).cgPath + circleLayer.fillColor = isSelected ? tintColor.cgColor : nil + } + + private func updateLabelColor() { + label.textColor = isSelected ? style().color.customBackground : style().color.label + } + + override func styleDidChange() { + super.styleDidChange() + updateLabelColor() + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphLegendView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphLegendView.swift new file mode 100755 index 0000000..b7d744a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGraphLegendView.swift @@ -0,0 +1,120 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKGraphLegendView: UIStackView { + private enum Constants { + static let iconCornerRadius: CGFloat = 4.0 + static let iconPadding: CGFloat = 6.0 + static let keySpacing: CGFloat = 10.0 + } + + init() { + super.init(frame: .zero) + setup() + } + + required init(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + func setDataSeries(_ dataSeries: [OCKDataSeries]) { + arrangedSubviews.forEach { $0.removeFromSuperview() } + dataSeries.map(makeKey).forEach(addArrangedSubview) + } + + private func setup() { + axis = .horizontal + distribution = .fillEqually + spacing = Constants.keySpacing + } + + private func makeKey(for series: OCKDataSeries) -> UIView { + let icon = makeIcon(startColor: series.gradientStartColor ?? tintColor, endColor: series.gradientEndColor ?? tintColor) + let label = makeLabel(title: series.title, color: series.gradientStartColor ?? tintColor) + let stack = UIStackView(arrangedSubviews: [icon, label]) + stack.axis = .horizontal + stack.spacing = Constants.iconPadding + return stack + } + + private func makeLabel(title: String, color: UIColor) -> UIView { + let label = OCKCappedSizeLabel(textStyle: .caption1, weight: .regular) + label.textAlignment = .left + label.textColor = color + label.text = "\(title)" + label.clipsToBounds = true + label.isAccessibilityElement = false + return label + } + + private func makeIcon(startColor: UIColor, endColor: UIColor) -> UIView { + let icon = OCKGradientView() + icon.startColor = startColor + icon.endColor = endColor + icon.clipsToBounds = true + icon.layer.cornerRadius = Constants.iconCornerRadius + icon.translatesAutoresizingMaskIntoConstraints = false + icon.heightAnchor.constraint(equalTo: icon.widthAnchor).isActive = true + return icon + } +} + +private class OCKGradientView: OCKView { + var startColor: UIColor = OCKStyle().color.customGray2 { + didSet { gradient.colors = [startColor.cgColor, endColor.cgColor] } + } + + var endColor: UIColor = OCKStyle().color.customGray2 { + didSet { gradient.colors = [startColor.cgColor, endColor.cgColor] } + } + + private var gradient: CAGradientLayer { + guard let layer = layer as? CAGradientLayer else { fatalError("Unsupported type") } + return layer + } + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + override func setup() { + super.setup() + setupGradient() + } + + private func setupGradient() { + gradient.colors = [startColor.cgColor, endColor.cgColor] + gradient.startPoint = CGPoint(x: 0.5, y: 1) + gradient.endPoint = CGPoint(x: 0.5, y: 0) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGridView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGridView.swift new file mode 100755 index 0000000..bf2619d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/OCKGridView.swift @@ -0,0 +1,103 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKGridView: UIView, OCKCartesianGridProtocol { + override class var layerClass: AnyClass { + return OCKGridLayer.self + } + + private let layout = OCKResponsiveLayout( + defaultLayout: 4, + anySizeClassRuleSet: [ + .init(layout: 6, greaterThanOrEqualToContentSizeCategory: .small), + .init(layout: 8, greaterThanOrEqualToContentSizeCategory: .medium), + .init(layout: 10, greaterThanOrEqualToContentSizeCategory: .large), + .init(layout: 12, greaterThanOrEqualToContentSizeCategory: .extraLarge), + .init(layout: 14, greaterThanOrEqualToContentSizeCategory: .accessibilityMedium), + .init(layout: 16, greaterThanOrEqualToContentSizeCategory: .accessibilityLarge), + .init(layout: 18, greaterThanOrEqualToContentSizeCategory: .accessibilityExtraLarge) + ] + ) + + private var gridLayer: OCKGridLayer { + return layer as! OCKGridLayer + } + + var numberOfDivisions: Int { + return gridLayer.numberOfVerticalDivisions + } + + var xMinimum: CGFloat? { + get { return gridLayer.xMinimum } + set { gridLayer.xMinimum = newValue } + } + + var xMaximum: CGFloat? { + get { return gridLayer.xMaximum } + set { gridLayer.xMaximum = newValue } + } + + var yMinimum: CGFloat? { + get { return gridLayer.yMinimum } + set { gridLayer.yMinimum = newValue } + } + + var yMaximum: CGFloat? { + get { return gridLayer.yMaximum } + set { gridLayer.yMaximum = newValue } + } + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + private func setup() { + + let fontSize = layout.responsiveLayoutRule(traitCollection: traitCollection) + gridLayer.fontSize = fontSize + + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + let fontSize = layout.responsiveLayoutRule(traitCollection: traitCollection) + gridLayer.fontSize = fontSize + + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKChartDisplayable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKChartDisplayable.swift new file mode 100755 index 0000000..c8b556a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKChartDisplayable.swift @@ -0,0 +1,44 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Any object that can display and handle interactions with a chart. +public protocol OCKChartDisplayable: AnyObject { + /// Handles events related to an `OCKChartDisplayable` object. + var delegate: OCKChartViewDelegate? { get set } +} + +/// Handles events related to an `OCKChartDisplayable` object. +public protocol OCKChartViewDelegate: AnyObject { + /// Called when the view displaying the chart was selected. + /// - Parameter chartView: The view displaying the chart. + func didSelectChartView(_ chartView: UIView & OCKChartDisplayable) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKGraphable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKGraphable.swift new file mode 100755 index 0000000..a3111b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Charts/Protocols/OCKGraphable.swift @@ -0,0 +1,108 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Any view or layer that can be plotted on conforms to this protocol. +protocol OCKCartesianGridProtocol: AnyObject { + /// The smallest value shown on the x-axis. If not set, a reasonable default will be used. + var xMinimum: CGFloat? { get set } + + /// The largest value shown on the x-axis. If not set, a reasonable default will be used. + var xMaximum: CGFloat? { get set } + + /// The smallest value shown on the y-axis. If not set, a reasonable default will be used. + var yMinimum: CGFloat? { get set } + + /// The largest value shown on the y-axis. If not set, a reasonable default will be used. + var yMaximum: CGFloat? { get set } +} + +extension OCKCartesianGridProtocol { + /// The default width of the graph in plot space coordinates. + static var defaultWidth: CGFloat { return 100 } + + /// The default height of the graph area in plot space coordinates. + static var defaultHeight: CGFloat { return 100 } +} + +/// Any view that only supports plotting a single data series should conform to this protocol. +protocol OCKSinglePlotable: OCKCartesianGridProtocol { + var dataPoints: [CGPoint] { get set } +} + +/// Any view that supports plotting multiple data series should conform to this protocol. +protocol OCKMultiPlotable: OCKCartesianGridProtocol { + var dataSeries: [OCKDataSeries] { get set } +} + +extension OCKMultiPlotable { + /// Computes the bounds of the area shown on the graph in graph coordinate space. + func graphBounds() -> CGRect { + let xCoords = dataSeries.flatMap { $0.dataPoints }.map { $0.x } + let xMin = xMinimum ?? xCoords.min() ?? 0 + let xMax = xMaximum ?? xCoords.max() ?? Self.defaultWidth + let width = xMax - xMin + + let yCoords = dataSeries.flatMap { $0.dataPoints }.map { $0.y } + let yMin = yMinimum ?? yCoords.min() ?? 0 + let yMax = yMaximum ?? yCoords.max() ?? Self.defaultHeight + let height = yMax - yMin + + return CGRect(x: xMin, y: yMin, width: width, height: height) + } +} + +protocol OCKGradientPlotable { + var gradientLayer: CAGradientLayer { get } + var pointsLayer: CAShapeLayer { get } + + func makePath(points: [CGPoint]) -> CGPath +} + +extension OCKGradientPlotable where Self: CALayer { + func drawPoints(_ points: [CGPoint]) { + let path = makePath(points: points) + pointsLayer.path = path + + // Adjust the gradient's frame to capture the entire shape. It should clip top and bottom, but not sides. + let minX = min(0, path.boundingBoxOfPath.minX) + let maxX = max(bounds.width, path.boundingBoxOfPath.maxX) + let gradientFrame = CGRect(x: minX, y: 0, width: maxX - minX, height: bounds.height) + + gradientLayer.frame = gradientFrame + + // The points layer is positioned as a sublayer in the gradient, but it needs to appear + // in the same position it would if the gradient layer were exactly the same size as its parent. + let translation = CGAffineTransform(translationX: -gradientFrame.minX, y: 0) + let adjustedFrame = bounds.applying(translation) + pointsLayer.frame = adjustedFrame + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKAddressButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKAddressButton.swift new file mode 100755 index 0000000..3687a22 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKAddressButton.swift @@ -0,0 +1,138 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +open class OCKAddressButton: OCKAnimatedButton { + // MARK: Properties + + private enum Constants { + static let textSpacing: CGFloat = 2 + } + + private lazy var imageViewPointSize = OCKAccessibleValue(container: style(), keyPath: \.dimension.symbolPointSize3) { [imageView] scaledValue in + imageView.preferredSymbolConfiguration = .init(pointSize: scaledValue, weight: .regular) + } + + private let textStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.spacing = Constants.textSpacing + return stackView + }() + + /// Holds the main content in the button. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.horizontal() + stackView.alignment = .top + return stackView + }() + + /// Image in the corner of the view. The default image is set to the location icon. + public let imageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "location") + return imageView + }() + + /// The main text in the button. + public let titleLabel: OCKLabel = { + let label = OCKLabel(textStyle: .footnote, weight: .semibold) + label.numberOfLines = 0 + label.text = loc("ADDRESS") + return label + }() + + /// Below the main text in the button. + public let detailLabel: OCKLabel = { + let label = OCKLabel(textStyle: .footnote, weight: .regular) + label.numberOfLines = 0 + return label + }() + + // MARK: - Life Cycle + + public init() { + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + public required init?(coder: NSCoder) { + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + // MARK: Methods + + private func setup() { + styleSubviews() + addSubviews() + constrainSubviews() + } + + private func styleSubviews() { + accessibilityLabel = titleLabel.text + accessibilityHint = loc("DOUBLE_TAP_MAP") + } + + private func addSubviews() { + [titleLabel, detailLabel].forEach { textStackView.addArrangedSubview($0) } + [textStackView, imageView].forEach { contentStackView.addArrangedSubview($0) } + addSubview(contentStackView) + } + + private func constrainSubviews() { + [contentStackView, imageView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + imageView.setContentHuggingPriority(.defaultHigh, for: .horizontal) + NSLayoutConstraint.activate(contentStackView.constraints(equalTo: layoutMarginsGuide)) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + detailLabel.textColor = style.color.label + backgroundColor = style.color.quaternaryCustomFill + directionalLayoutMargins = style.dimension.directionalInsets1 + layer.cornerRadius = style.appearance.cornerRadius2 + imageViewPointSize.update(withContainer: style) + contentStackView.spacing = style.dimension.directionalInsets1.leading + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + titleLabel.textColor = tintColor + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { + imageViewPointSize.apply() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKContactButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKContactButton.swift new file mode 100755 index 0000000..46b2989 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/Buttons/OCKContactButton.swift @@ -0,0 +1,152 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +open class OCKContactButton: OCKAnimatedButton { + // MARK: Properties + + /// Determines the label text and image shown in the button. + public enum `Type`: String { + + /// Button for phone calls. + case call = "Call" + + /// Button for text messages. + case message = "Message" + + /// Button for emails. + case email = "E-mail" + + var image: UIImage? { + let image: UIImage? + switch self { + case .call: image = UIImage(systemName: "phone") + case .message: image = UIImage(systemName: "text.bubble") + case .email: image = UIImage(systemName: "envelope") + } + return image + } + } + + /// Image above the title label. + public let imageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFit + return imageView + }() + + /// Title label under the image. + public let label: OCKLabel = { + let label = OCKLabel(textStyle: .footnote, weight: .semibold) + label.textAlignment = .center + return label + }() + + /// Holds the main content for the view. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.spacing = 2 + stackView.isUserInteractionEnabled = false + return stackView + }() + + let type: Type + + private lazy var imageViewPointSize = OCKAccessibleValue(container: style(), keyPath: \.dimension.symbolPointSize2) { [imageView] scaledValue in + imageView.preferredSymbolConfiguration = .init(pointSize: scaledValue, weight: .regular) + } + + // MARK: Life cycle + + /// Initialize the button with a type. The type determines the label text and image. + /// - Parameter type: The type of the button. + public init(type: Type) { + self.type = type + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + public required init?(coder: NSCoder) { + self.type = .call + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + // MARK: Methods + + private func setup() { + styleSubviews() + addSubviews() + constrainSubviews() + } + + private func styleSubviews() { + imageView.image = type.image + label.text = type.rawValue + + switch type { + case .call: accessibilityLabel = loc("CALL") + case .email: accessibilityLabel = loc("EMAIL") + case .message: accessibilityLabel = loc("MESSAGE") + } + } + + private func addSubviews() { + [imageView, label].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentStackView, imageView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate(contentStackView.constraints(equalTo: layoutMarginsGuide)) + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + imageView.tintColor = tintColor + label.textColor = tintColor + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + backgroundColor = style.color.quaternaryCustomFill + layer.cornerRadius = style.appearance.cornerRadius2 + imageViewPointSize.update(withContainer: style) + directionalLayoutMargins = style.dimension.directionalInsets1 + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { + imageViewPointSize.apply() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKContactDisplayable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKContactDisplayable.swift new file mode 100755 index 0000000..db7449d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKContactDisplayable.swift @@ -0,0 +1,64 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Any object that can display and handle interactions with a contact. +public protocol OCKContactDisplayable: AnyObject { + /// Handles events related to an `OCKContactDisplayable` object. + var delegate: OCKContactViewDelegate? { get set } +} + +/// Handles events related to an `OCKContactDisplayable` object. +public protocol OCKContactViewDelegate: AnyObject { + /// Called when the user would like to call the contact. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the call process. + func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateCall sender: Any?) + + /// Called when the user would like to message the contact. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the messaging process. + func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateMessage sender: Any?) + + /// Called when the user would like to email the contact. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the email process. + func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateEmail sender: Any?) + + /// Called when the user would like to view the address of the contact. + /// - Parameter contactView: The view that displays the contact. + /// - Parameter sender: The sender that is initiating the address lookup process. + func contactView(_ contactView: UIView & OCKContactDisplayable, senderDidInitiateAddressLookup sender: Any?) + + /// Called when the view displaying the contact was selected. + /// - Parameter contactView: The view displaying the contact. + func didSelectContactView(_ contactView: UIView & OCKContactDisplayable) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKDetailedContactView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKDetailedContactView.swift new file mode 100755 index 0000000..07f457f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKDetailedContactView.swift @@ -0,0 +1,204 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays information for a contact. The header is an `OCKHeaderView` +/// The body contains a multi-line istructions label, and four buttons; call, message, +/// email, and address. The first three buttons have title labels and image views that can +/// be modified, while the last has a title label, body label, and image view. +/// +/// +-------------------------------------------------------+ +/// | +------+ | +/// | | icon | [title] | +/// | | img | [detail] | +/// | +------+ | +/// | | +/// | -------------------------------------------------- | +/// | | +/// | [Instructions] | +/// | | +/// | +------------+ +------------+ +------------+ | +/// | | [title] | | [title] | | [title] | | +/// | | | | | | | | +/// | +------------+ +------------+ +------------+ | +/// | | +/// | +---------------------------------------------------+ | +/// | | [title] | | +/// | | [detail] | | +/// | | | | +/// | +---------------------------------------------------+ | +/// +-------------------------------------------------------+ +/// +open class OCKDetailedContactView: OCKView, OCKContactDisplayable { + + // MARK: Properties + + /// Handles events related to an `OCKContactDisplayable` object. + public weak var delegate: OCKContactViewDelegate? + + /// A vertical stack view that holds the main content in the view. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.distribution = .fill + return stackView + }() + + /// Header stack view that shows an `iconImageView` and a separator. + public let headerView = OCKHeaderView { + $0.showsIconImage = true + $0.showsSeparator = true + } + + /// Multi-line label under the `headerView`. + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .medium) + label.numberOfLines = 0 + return label + }() + + /// Button with a phone image and title label. + /// Set the `isHidden` property to `false` to hide the button. + public let callButton = OCKContactButton(type: .call) + + /// Button with a messages images and title label. + /// Set the `isHidden` property to `false` to hide the button. + public let messageButton = OCKContactButton(type: .message) + + /// Button with an email image and title label. + /// Set the `isHidden` property to `false` to hide the button. + public let emailButton = OCKContactButton(type: .email) + + /// Button with a location image, title and detail labels. + /// Set the `isHidden` property to `false` to hide the button. + public let addressButton = OCKAddressButton() + + /// The default image that can be used as a placeholder for the `iconImageView` in the `headerView`. + public static let defaultImage = UIImage(systemName: "person.crop.circle")! + + let contentView = OCKView() + + private var buttons: [OCKAnimatedButton] { + return [addressButton, callButton, messageButton, emailButton] + } + + private var contactButtons: [OCKContactButton] { + return buttons.compactMap { $0 as? OCKContactButton } + } + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + /// Stack view that holds phone, message, and email contact action buttons. + private lazy var contactStackView: OCKStackView = { + let stackView = OCKStackView() + stackView.axis = self.contactStackAxisDirection() + stackView.distribution = .fillEqually + return stackView + }() + + /// Stack view that holds buttons in `contactStack` and `directionsButton`. + /// You may choose to add or hide buttons + private let buttonStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.distribution = .equalSpacing + return stackView + }() + + // MARK: - Methods + + /// Prepares interface after initialization + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + styleSubviews() + setupGestures() + } + + private func setupGestures() { + [messageButton, callButton, addressButton, emailButton].forEach { + $0.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside) + } + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(contentStackView) + [headerView, instructionsLabel, buttonStackView].forEach { contentStackView.addArrangedSubview($0) } + [callButton, messageButton, emailButton].forEach { contactStackView.addArrangedSubview($0) } + [contactStackView, addressButton].forEach { buttonStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, contentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: layoutMarginsGuide) + + contentStackView.constraints(equalTo: contentView) + ) + } + + private func styleSubviews() { + headerView.iconImageView?.image = OCKDetailedContactView.defaultImage // set default profile picture + } + + @objc + private func didTapButton(_ sender: UIControl) { + sender.isSelected = false // Immediately deselect since these buttons aren't intended to be toggleable + switch sender { + case messageButton: delegate?.contactView(self, senderDidInitiateMessage: sender) + case callButton: delegate?.contactView(self, senderDidInitiateCall: sender) + case addressButton: delegate?.contactView(self, senderDidInitiateAddressLookup: sender) + case emailButton: delegate?.contactView(self, senderDidInitiateEmail: sender) + default: fatalError("Target not set up properly") + } + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + cardBuilder.enableCardStyling(true, style: cachedStyle) + instructionsLabel.textColor = cachedStyle.color.label + directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + let topInset = cachedStyle.dimension.directionalInsets1.top + contentStackView.spacing = topInset + [contactStackView, buttonStackView].forEach { $0.spacing = topInset / 2.0 } + } + + // MARK: Accessibility Scaling + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + contactStackView.axis = contactStackAxisDirection() + } + + private func contactStackAxisDirection() -> NSLayoutConstraint.Axis { + traitCollection.preferredContentSizeCategory < .extraExtraLarge ? .horizontal : .vertical + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKSimpleContactView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKSimpleContactView.swift new file mode 100755 index 0000000..a0cedfb --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Contact/OCKSimpleContactView.swift @@ -0,0 +1,119 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays information for a contact. The header is an `OCKHeaderView`. +/// +/// +-------------------------------------------------------+ +/// | +------+ | +/// | | icon | [title] [detail | +/// | | img | [detail] disclosure] | +/// | +------+ | +/// +-------------------------------------------------------+ +/// +open class OCKSimpleContactView: OCKView, OCKContactDisplayable { + + // MARK: Properties + + /// Handles events related to an `OCKContactDisplayable` object. + public weak var delegate: OCKContactViewDelegate? + + /// A vertical stack view that holds the main content in the view. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.distribution = .fill + return stackView + }() + + /// Header stack view that shows an `iconImageView` and a separator. + public let headerView = OCKHeaderView { + $0.showsIconImage = true + $0.showsDetailDisclosure = true + } + + let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + // Button that displays the highlighted state for the view. + private lazy var backgroundButton = OCKAnimatedButton(contentView: contentStackView, highlightOptions: [.defaultOverlay, .defaultDelayOnSelect], + handlesSelection: false) + + // MARK: - Methods + + /// Prepares interface after initialization + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + setupGestures() + styleSubviews() + } + + private func setupGestures() { + backgroundButton.addTarget(self, action: #selector(viewTapped(_:)), for: .touchUpInside) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(backgroundButton) + contentStackView.addArrangedSubview(headerView) + } + + @objc + private func viewTapped(_ sender: UIControl) { + delegate?.didSelectContactView(self) + } + + private func styleSubviews() { + headerView.iconImageView?.image = UIImage(systemName: "person.crop.circle") + } + + private func constrainSubviews() { + [contentView, backgroundButton, contentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + backgroundButton.constraints(equalTo: contentView) + + contentStackView.constraints(equalTo: backgroundButton.layoutMarginsGuide)) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + directionalLayoutMargins = style.dimension.directionalInsets1 + contentStackView.spacing = style.dimension.directionalInsets1.top + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKChecklistItemButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKChecklistItemButton.swift new file mode 100755 index 0000000..2eb1a74 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKChecklistItemButton.swift @@ -0,0 +1,120 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import UIKit + +/// A button with an icon and title label. +/// +/// +--------------------------+ +/// | [Title] [Icon] | +/// +--------------------------+ +/// +open class OCKChecklistItemButton: OCKAnimatedButton { + + // MARK: Properties + + /// The label on the leading side of the button. + public let label: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .regular) + label.text = loc("EVENT") + return label + }() + + /// The checkmark button on the trailing end of the view. + public let checkmarkButton: OCKCheckmarkButton = { + let button = OCKCheckmarkButton() + button.isUserInteractionEnabled = false + return button + }() + + /// Holds the main content in the button. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.horizontal() + stackView.alignment = .center + return stackView + }() + + // MARK: - Life Cycle + + public init() { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + public required init?(coder: NSCoder) { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + // MARK: Methods + + private func setup() { + addSubviews() + constrainSubviews() + setupAccessibility() + } + + private func addSubviews() { + [label, checkmarkButton].forEach { contentStackView.addArrangedSubview($0) } + addSubview(contentStackView) + } + + private func constrainSubviews() { + [contentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + checkmarkButton.setContentHuggingPriority(.defaultHigh, for: .horizontal) + NSLayoutConstraint.activate( + contentStackView.constraints(equalTo: self, directions: [.horizontal]) + + contentStackView.constraints(equalTo: layoutMarginsGuide, directions: [.vertical]) + ) + } + + private func setupAccessibility() { + accessibilityValue = isSelected ? loc("COMPLETED") : loc("INCOMPLETE") + accessibilityHint = isSelected ? loc("DOUBLE_TAP_TO_COMPLETE") : loc("DOUBLE_TAP_TO_INCOMPLETE") + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + directionalLayoutMargins = style.dimension.directionalInsets1 + checkmarkButton.height.update(withContainer: style, keyPath: \.dimension.buttonHeight3) + checkmarkButton.imageViewPointSize.update(withContainer: style, keyPath: \.dimension.symbolPointSize5) + label.textColor = style.color.label + } + + override open func setSelected(_ isSelected: Bool, animated: Bool) { + super.setSelected(isSelected, animated: animated) + checkmarkButton.setSelected(isSelected, animated: animated) + setupAccessibility() + } + + override open func setStyleForSelectedState(_ isSelected: Bool) {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledButton.swift new file mode 100755 index 0000000..eaaf96c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledButton.swift @@ -0,0 +1,114 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A button with a filled background color. +/// +/// +--------------------------+ +/// | [Title] | +/// +--------------------------+ +/// +open class OCKLabeledButton: OCKAnimatedButton { + + // MARK: Properties + + /// Label in the center of the buttton. + public let label: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .medium) + label.text = loc("MARK_COMPLETE") + label.translatesAutoresizingMaskIntoConstraints = false + label.textAlignment = .center + label.numberOfLines = 0 + return label + }() + + // MARK: Life Cycle + + public init() { + super.init(contentView: label, handlesSelection: true) + constrainSubviews() + } + + @available(*, unavailable) + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Methods + + override open func setStyleForSelectedState(_ isSelected: Bool) { + let completionString = isSelected ? loc("COMPLETED") : loc("MARK_COMPLETE") + let attributedText = NSMutableAttributedString(string: completionString) + + // Set a checkmark next to the text if the button is in the completed state + if isSelected, let checkmark = UIImage.from(systemName: "checkmark") { + let attachment = NSTextAttachment(image: checkmark) + let checkmarkString = NSAttributedString(attachment: attachment) + attributedText.append(.init(string: " ")) + attributedText.append(checkmarkString) + } + + label.attributedText = attributedText + + updateColors() + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + updateColors() + layer.cornerRadius = style.appearance.cornerRadius2 + directionalLayoutMargins = style.dimension.directionalInsets1 + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + updateColors() + } + + private func constrainSubviews() { + NSLayoutConstraint.activate(label.constraints(equalTo: layoutMarginsGuide)) + } + + private func updateColors() { + let style = self.style() + backgroundColor = isSelected ? style.color.tertiaryCustomFill : tintColor + label.textColor = isSelected ? tintColor : style.color.white + } +} + +private extension UIImage { + static func from(systemName: String) -> UIImage? { + let image = UIImage(systemName: systemName) + assert(image != nil, "Unable to locate symbol for system name: \(systemName)") + return image + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledCheckmarkButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledCheckmarkButton.swift new file mode 100755 index 0000000..db9f0e0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLabeledCheckmarkButton.swift @@ -0,0 +1,106 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// OCKCheckmarkButton button with a label. +open class OCKLabeledCheckmarkButton: OCKAnimatedButton { + + // MARK: Properties + + /// The label underneath the checkmark button. + public let label: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .medium) + label.textAlignment = .center + return label + }() + + /// The checkmark button above the label. + public let checkmarkButton: OCKCheckmarkButton = { + let button = OCKCheckmarkButton() + button.isUserInteractionEnabled = false + return button + }() + + /// Holds the main content in the button. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.alignment = .center + return stackView + }() + + // MARK: - Life Cycle + + public init() { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + public required init?(coder: NSCoder) { + super.init(contentView: contentStackView, handlesSelection: true) + setup() + } + + // MARK: - Methods + + private func setup() { + addSubviews() + constrainSubviews() + } + + private func addSubviews() { + [checkmarkButton, label].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + contentStackView.translatesAutoresizingMaskIntoConstraints = false + checkmarkButton.setContentHuggingPriority(.defaultHigh, for: .vertical) + NSLayoutConstraint.activate(contentStackView.constraints(equalTo: self)) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + label.textColor = style.color.secondaryLabel + contentStackView.spacing = style.dimension.directionalInsets2.bottom + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + label.textColor = tintColor + } + + override open func setSelected(_ isSelected: Bool, animated: Bool) { + super.setSelected(isSelected, animated: animated) + checkmarkButton.setSelected(isSelected, animated: animated) + } + + override open func setStyleForSelectedState(_ isSelected: Bool) {} +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLogItemButton.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLogItemButton.swift new file mode 100755 index 0000000..d2e16b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Buttons/OCKLogItemButton.swift @@ -0,0 +1,120 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +open class OCKLogItemButton: OCKAnimatedButton { + + private enum Constants { + static let spacing: CGFloat = 3 + } + + // MARK: Properties + + /// The icon on the leading end of the button. + public let imageView: UIImageView = { + let imageView = UIImageView() + imageView.image = UIImage(systemName: "clock") + imageView.preferredSymbolConfiguration = .init(textStyle: .caption1) + return imageView + }() + + /// Main content label. + public let titleLabel: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .regular) + return label + }() + + /// Tinted accessory label. + public let detailLabel: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .regular) + return label + }() + + /// Holds the main content in the button. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.horizontal() + stackView.alignment = .center + stackView.distribution = .fill + return stackView + }() + + // MARK: - Life cycle + + public init() { + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + public required init?(coder: NSCoder) { + super.init(contentView: contentStackView, handlesSelection: false) + setup() + } + + // MARK: Methods + + private func setup() { + addSubviews() + constrainSubviews() + styleSubviews() + } + + private func styleSubviews() { + contentStackView.setCustomSpacing(Constants.spacing, after: imageView) + } + + private func addSubviews() { + addSubview(contentStackView) + [imageView, detailLabel, titleLabel].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentStackView].forEach { $0?.translatesAutoresizingMaskIntoConstraints = false } + detailLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal) + imageView.setContentHuggingPriority(.defaultHigh, for: .horizontal) + NSLayoutConstraint.activate( + contentStackView.constraints(equalTo: self, directions: [.horizontal]) + + contentStackView.constraints(equalTo: layoutMarginsGuide, directions: [.vertical]) + ) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + titleLabel.textColor = style.color.label + contentStackView.setCustomSpacing(style.dimension.directionalInsets1.top, after: detailLabel) + directionalLayoutMargins = style.dimension.directionalInsets1 + } + + override open func tintColorDidChange() { + super.tintColorDidChange() + detailLabel.textColor = tintColor + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKGridTaskCell.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKGridTaskCell.swift new file mode 100755 index 0000000..0d40540 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKGridTaskCell.swift @@ -0,0 +1,84 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A cell used in the `collectionView` of the `OCKGridTaskView`. The cell shows a circular `completionButton` that has an image and a +/// `titleLabel`. The default image is a checkmark. +open class OCKGridTaskCell: UICollectionViewCell { + + // MARK: Properties + + /// Circular button that shows an image and label. The default image is a checkmark when selected. + /// The text for the deselected state will automatically adapt to the `tintColor`. + public let completionButton = OCKLabeledCheckmarkButton() + + // MARK: Life cycle + + override public init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + // MARK: Methods + + override open func prepareForReuse() { + super.prepareForReuse() + completionButton.isSelected = false + completionButton.label.text = nil + accessibilityLabel = nil + accessibilityValue = nil + } + + private func setup() { + addSubviews() + constrainSubviews() + completionButton.isEnabled = false + isAccessibilityElement = true + accessibilityTraits = .button + } + + private func addSubviews() { + contentView.addSubview(completionButton) + } + + private func constrainSubviews() { + completionButton.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate( + completionButton.constraints(equalTo: contentView, directions: [.top, .leading]) + + completionButton.constraints(equalTo: contentView, directions: [.bottom, .trailing], priority: .almostRequired) + ) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKLogButtonCell.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKLogButtonCell.swift new file mode 100755 index 0000000..4e0d981 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKLogButtonCell.swift @@ -0,0 +1,93 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +private class OCKLogButton: OCKLabeledButton { + override init() { + super.init() + handlesSelection = false + label.text = loc("Log") + } +} + +open class OCKLogButtonCell: UICollectionViewCell { + + // MARK: Properties + + public let logButton: OCKLabeledButton = { + let button = OCKLogButton() + OCKLogButtonCell.resetLogButton(button) + return button + }() + + // MARK: - Life cycle + + override public init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setup() + } + + override open func prepareForReuse() { + super.prepareForReuse() + OCKLogButtonCell.resetLogButton(logButton) + } + + // MARK: - Methods + + /// Reset a log button to its original state + private static func resetLogButton(_ button: OCKLabeledButton) { + button.label.text = loc("LOG") + } + + private func setup() { + styleSubviews() + addSubviews() + constrainSubviews() + } + + private func styleSubviews() { + preservesSuperviewLayoutMargins = true + } + + private func addSubviews() { + contentView.addSubview(logButton) + } + + private func constrainSubviews() { + logButton.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate(logButton.constraints(equalTo: contentView)) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKSelfSizingCollectionView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKSelfSizingCollectionView.swift new file mode 100755 index 0000000..43b196a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/Collection View/OCKSelfSizingCollectionView.swift @@ -0,0 +1,64 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +class OCKSelfSizingCollectionView: UICollectionView { + + // MARK: Properties + + private var collectionViewHeightConstraint: NSLayoutConstraint? + + // MARK: Life cycle + + override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { + super.init(frame: frame, collectionViewLayout: layout) + constrainSubviews() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Methods + + override func layoutSubviews() { + super.layoutSubviews() + let height = collectionViewLayout.collectionViewContentSize.height + collectionViewHeightConstraint?.constant = max(1, height) + } + + private func constrainSubviews() { + translatesAutoresizingMaskIntoConstraints = false + collectionViewHeightConstraint = heightAnchor.constraint(equalToConstant: 1).withPriority(.almostRequired) + collectionViewHeightConstraint?.isActive = true + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKButtonLogTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKButtonLogTaskView.swift new file mode 100755 index 0000000..24bdcf0 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKButtonLogTaskView.swift @@ -0,0 +1,157 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays a header, multi-line label, a collection of log buttons, and a dynamic vertical stack of logged items. +/// In CareKit, this view is intended to display a particular event for a task. When the log button is presses, +/// a new outcome is created for the event. +/// +/// See `logButtonsCollectionView` to customize the layout or number of log buttons. +/// +/// To insert custom views vertically the view, see `contentStack`. To modify the logged items, see +/// `updateItem`, `appendItem`, `insertItem`, `removeItem` and `clearItems`. +/// +/// +-------------------------------------------------------+ +/// | | +/// | [title] [detail | +/// | [detail] disclosure] | +/// | | +/// | | +/// | -------------------------------------------------- | +/// | | +/// | [instructions] | +/// | | +/// | +-----------------------------------------------+ | +/// | | [log button] | | +/// | +-----------------------------------------------+ | +/// | | +/// | [img] [detail] [title] | +/// | ------------------------------------------------- | +/// | [img] [detail] [title] | +/// | ------------------------------------------------- | +/// | ... | +/// | ... | +/// | ------------------------------------------------- | +/// | [img] [detail] [title] | +/// | | +/// +-------------------------------------------------------+ +/// +open class OCKButtonLogTaskView: OCKLogTaskView, UICollectionViewDelegate, UICollectionViewDataSource { + + private enum Constants { + static let spacing: CGFloat = 16 + static let estimatedCellHeight: CGFloat = 44 + } + + // MARK: Properties + + /// The default cell type used for the `logButtonCollectionView`. + public typealias DefaultCellType = OCKLogButtonCell + + /// The identifier used for the default cell in the `logButtonCollectionView`. + public static let defaultCellIdentifier = "log-button-cell" + + /// Collection view holding the log buttons. + public private (set) var logButtonsCollectionView: UICollectionView! + + /// Multi-line label below the header. + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .medium) + label.numberOfLines = 0 + return label + }() + + // MARK: Methods + + private func makeCollectionView() -> UICollectionView { + let collectionView = OCKSelfSizingCollectionView(frame: .zero, collectionViewLayout: makeLayout()) + collectionView.backgroundColor = nil + collectionView.register(OCKButtonLogTaskView.DefaultCellType.self, forCellWithReuseIdentifier: OCKButtonLogTaskView.defaultCellIdentifier) + return collectionView + } + + private func makeLayout() -> UICollectionViewCompositionalLayout { + let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(Constants.estimatedCellHeight)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(Constants.estimatedCellHeight)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 1) + + let section = NSCollectionLayoutSection(group: group) + section.interGroupSpacing = directionalLayoutMargins.top + + let layout = UICollectionViewCompositionalLayout(section: section) + return layout + } + + @objc + private func didTapLogButton(_ sender: UIControl) { + delegate?.taskView(self, didCreateOutcomeValueAt: 0, eventIndexPath: .init(row: 0, section: 0), sender: sender) + } + + override func setup() { + logButtonsCollectionView = makeCollectionView() + logButtonsCollectionView.delegate = self + logButtonsCollectionView.dataSource = self + + super.setup() + } + + override func addSubviews() { + super.addSubviews() + [logButtonsCollectionView, instructionsLabel].forEach { contentStackView.insertArrangedSubview($0, at: 0) } + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + instructionsLabel.textColor = cachedStyle.color.label + contentStackView.setCustomSpacing(cachedStyle.dimension.directionalInsets2.top, after: logButtonsCollectionView) + } + + // MARK: - UICollectionViewDelegate & DataSource + + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return 1 + } + + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OCKButtonLogTaskView.defaultCellIdentifier, for: indexPath) + guard let typedCell = cell as? OCKButtonLogTaskView.DefaultCellType else { return cell } + typedCell.logButton.addTarget(self, action: #selector(didTapLogButton(_:)), for: .touchUpInside) + typedCell.logButton.label.text = loc("LOG") + typedCell.isAccessibilityElement = true + typedCell.accessibilityLabel = loc("LOG") + typedCell.accessibilityHint = loc("DOUBLE_TAP_TO_RECORD_EVENT") + typedCell.accessibilityTraits = .button + return cell + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKChecklistTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKChecklistTaskView.swift new file mode 100755 index 0000000..5f58aea --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKChecklistTaskView.swift @@ -0,0 +1,244 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays a vertically stacked checklist of items. In CareKit, this view is intended to display +/// multiple events for a particular task. +/// +/// To insert custom views vertically the view, see `contentStack`. The header is an `OCKHeaderView`. The body has a +/// stack of checklist items and an instructions label underneath. To access the checklist item buttons, for instance +/// to hook them up to target actions, see the `items` array. To modify the checklist, see +/// `updateItem`, `appendItem`, `insertItem`, `removeItem` and `clearItems`. +/// +/// +-------------------------------------------------------+ +/// | +------+ | +/// | | icon | [title] [detail | +/// | | img | [detail] disclosure] | +/// | +------+ | +/// | | +/// | -------------------------------------------------- | +/// | | +/// | +-------------------------------------------------+ | +/// | | [title] [img] | | +/// | +-------------------------------------------------+ | +/// | +-------------------------------------------------+ | +/// | | [title] [img] | | +/// | +-------------------------------------------------+ | +/// | . | +/// | . | +/// | . | +/// | +-------------------------------------------------+ | +/// | | [title] [img] | | +/// | +-------------------------------------------------+ | +/// | | +/// | [instructions] | +/// +-------------------------------------------------------+ +/// +open class OCKChecklistTaskView: OCKView, OCKTaskDisplayable { + + // MARK: Properties + + let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + private let checklistItemsStackView: OCKStackView = { + let stackView = OCKStackView(style: .separated) + stackView.axis = .vertical + return stackView + }() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + private let headerStackView = OCKStackView.vertical() + + private lazy var headerButton = OCKAnimatedButton(contentView: headerView, highlightOptions: [.defaultDelayOnSelect, .defaultOverlay], + handlesSelection: false) + + /// The vertical stack view that holds the main content in the view. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.isLayoutMarginsRelativeArrangement = true + return stackView + }() + + /// Handles events related to an `OCKTaskDisplayable` object. + public weak var delegate: OCKTaskViewDelegate? + + /// The header that shows a `detailDisclosureImage`. + public let headerView = OCKHeaderView { + $0.showsDetailDisclosure = true + } + + /// Multi-line label beneath the checklist items. + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .regular) + label.numberOfLines = 0 + return label + }() + + /// The buttons in the checklist. + public var items: [OCKChecklistItemButton] { + guard let items = checklistItemsStackView.arrangedSubviews as? [OCKChecklistItemButton] else { fatalError("Unsupported type.") } + return items + } + + // MARK: Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + styleSubviews() + setupGestures() + } + + private func setupGestures() { + headerButton.addTarget(self, action: #selector(didTapView), for: .touchUpInside) + } + + private func styleSubviews() { + contentStackView.setCustomSpacing(0, after: instructionsLabel) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(headerStackView) + [headerButton, contentStackView].forEach { headerStackView.addArrangedSubview($0) } + [checklistItemsStackView, instructionsLabel].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, headerStackView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + headerStackView.constraints(equalTo: contentView) + + headerView.constraints(equalTo: headerButton.layoutMarginsGuide)) + } + + @objc + private func didTapView() { + delegate?.didSelectTaskView(self, eventIndexPath: .init(row: 0, section: 0)) + } + + @objc + private func eventButtonTapped(_ sender: UIControl) { + guard let row = checklistItemsStackView.arrangedSubviews.firstIndex(of: sender) else { + fatalError("Invalid index") + } + delegate?.taskView(self, didCompleteEvent: !sender.isSelected, at: .init(row: row, section: 0), sender: sender) + } + + private func makeItem(withTitle title: String) -> OCKChecklistItemButton { + let button = OCKChecklistItemButton() + button.addTarget(self, action: #selector(eventButtonTapped(_:)), for: .touchUpInside) + button.label.text = title + button.accessibilityLabel = title + return button + } + + /// Update an item with text. + /// + /// - Parameters: + /// - index: The index of the item to update. + /// - title: The new text for the item. + /// - Returns: The item that was modified. + @discardableResult + public func updateItem(at index: Int, withTitle title: String) -> OCKChecklistItemButton? { + guard index < checklistItemsStackView.arrangedSubviews.count else { return nil } + let button = items[index] + button.label.text = title + return button + } + + /// Insert an item in the checklist. + /// + /// - Parameters: + /// - title: The text displayed in the item. + /// - index: The index at which to insert the item. + /// - animated: Animate the insertion of the view. + /// - Returns: The item that was inserted. + @discardableResult + public func insertItem(withTitle title: String, at index: Int, animated: Bool) -> OCKChecklistItemButton { + let button = makeItem(withTitle: title) + checklistItemsStackView.insertArrangedSubview(button, at: index, animated: animated) + return button + } + + /// Append an item to the checklist. + /// + /// - Parameters: + /// - title: The text displayed in the item. + /// - animated: Animate the appending of the view. + /// - Returns: The view that was appended. + @discardableResult + public func appendItem(withTitle title: String, animated: Bool) -> OCKChecklistItemButton { + let button = makeItem(withTitle: title) + checklistItemsStackView.addArrangedSubview(button, animated: animated) + return button + } + + /// Remove an item from the checkliist. + /// + /// - Parameters: + /// - index: The index for which to remove the item. + /// - animated: Animate the removal of the item. + /// - Returns: The item that was removed from the checklist. + @discardableResult + public func removeItem(at index: Int, animated: Bool) -> OCKChecklistItemButton? { + guard index < checklistItemsStackView.arrangedSubviews.count else { return nil } + let button = items[index] + checklistItemsStackView.removeArrangedSubview(button, animated: animated) + return button + } + + /// Clear all items from the checklist. + /// + /// - Parameter animated: Animate the removal of the items from the checklist. + public func clearItems(animated: Bool) { + checklistItemsStackView.clear(animated: animated) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + instructionsLabel.textColor = style.color.secondaryLabel + directionalLayoutMargins = style.dimension.directionalInsets1 + contentStackView.spacing = style.dimension.directionalInsets1.top + contentStackView.directionalLayoutMargins = .init(top: 0, + leading: style.dimension.directionalInsets1.leading, + bottom: style.dimension.directionalInsets1.bottom, + trailing: style.dimension.directionalInsets1.trailing) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKGridTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKGridTaskView.swift new file mode 100755 index 0000000..c3425af --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKGridTaskView.swift @@ -0,0 +1,252 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays a header, grid of buttons, and a multi-line label In CareKit, this view is intended to display +/// multiple events for a particular task. The state of each button in the grid indicates the completion state of the +/// corresponding event. +/// +/// To insert custom views vertically the view, see `contentStack`. To modify the data in the grid, set a `dataSource` +/// for the `collectionView`. +/// +/// +-------------------------------------------------------+ +/// | | +/// | [title] [detail | +/// | [detail] disclosure] | +/// | | +/// | | +/// | -------------------------------------------------- | +/// | o o o o o o o o | +/// | o o o o o o ... o o | +/// | o o o o o o o o | +/// | | +/// | [instructions] | +/// +-------------------------------------------------------+ +/// +open class OCKGridTaskView: OCKView, OCKTaskDisplayable, UICollectionViewDelegate { + + private enum Constants { + static let estimatedItemHeight: CGFloat = 70 + static let estimatedItemWidth: CGFloat = 80 + } + + // MARK: Properties + + /// The vertical stack view that holds the main content in the view. + public let contentStackView: OCKStackView = { + let stackView = OCKStackView.vertical() + stackView.isLayoutMarginsRelativeArrangement = true + return stackView + }() + + /// Handles events related to an `OCKTaskDisplayable` object. + public weak var delegate: OCKTaskViewDelegate? + + /// A header view that shows a separator and a `detailDisclosureImage`. + public let headerView = OCKHeaderView { + $0.showsSeparator = true + $0.showsDetailDisclosure = true + } + + /// The default cell identifier that is registered for the collection view. + public static let defaultCellIdentifier = "outcome-value" + + /// The default cell type that is used for the `collectionView`. + public typealias DefaultCellType = OCKGridTaskCell + + /// A collection view that sizes itself based on the size of its content. Cells used should have a constant width constraint. The + /// default cell that is used is an `OCKGridTaskView.DefaultCellType` (`OCKGridTaskCell`). Set a data source to control the content + /// of the grid. + public private(set) lazy var collectionView: UICollectionView = { + let collectionView = OCKSelfSizingCollectionView(frame: .zero, collectionViewLayout: makeLayout()) + collectionView.register(OCKGridTaskView.DefaultCellType.self, forCellWithReuseIdentifier: OCKGridTaskView.defaultCellIdentifier) + collectionView.showsVerticalScrollIndicator = false + collectionView.delegate = self + collectionView.backgroundColor = nil + return collectionView + }() + + /// Multi-line label below the `collectionView`. + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .caption1, weight: .regular) + label.numberOfLines = 0 + return label + }() + + let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + private let headerStackView = OCKStackView.vertical() + + private lazy var headerButton = OCKAnimatedButton(contentView: headerView, highlightOptions: [.defaultDelayOnSelect, .defaultOverlay], + handlesSelection: false) + + // MARK: Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + setupGestures() + } + + // Find the horizontal margin for a grid given the parameters. + func horizontalMargin(forContainerWidth containerWidth: CGFloat, itemWidth: CGFloat, interItemSpacing: CGFloat, itemCount: Int) -> CGFloat { + var margin = containerWidth + var columns: Int = 0 + // Find the optimal column count by increasing the columns while minimizing the margin. + while margin >= 0 { + + // Equation derived from: + // containerWidth = margin + spacingBetweenItems + widthOfAllItems + // Note: This equation ensure the margin decreases at each loop step + var newMargin = -containerWidth + (interItemSpacing * max(columns - 1, 0).float) + (itemWidth * columns.float) + newMargin.negate() + + // If the new margin has gone negative, the current margin is the minimum + if newMargin < 0 { return margin } + + // If we do not have enough items to fill more columns, stop early + if itemCount <= columns { return newMargin } + + margin = newMargin // Store the new minimum + columns += 1 // Increase the columns and try to further minimize the margin + } + return margin + } + + private func setupGestures() { + headerButton.addTarget(self, action: #selector(didTapView), for: .touchUpInside) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(headerStackView) + [headerButton, contentStackView].forEach { headerStackView.addArrangedSubview($0) } + [collectionView, instructionsLabel].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, headerStackView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + headerStackView.constraints(equalTo: contentView) + + headerView.constraints(equalTo: headerButton.layoutMarginsGuide, directions: [.horizontal, .top]) + + headerView.constraints(equalTo: headerButton, directions: [.bottom])) + } + + private func makeLayout() -> UICollectionViewLayout { + let layout = UICollectionViewCompositionalLayout { [weak self] _, configuration in + guard let self = self else { return nil } + let spacing = self.style().dimension.directionalInsets2.trailing + + // Scale the item dimensions based on the content size category + let scaledHeight = Constants.estimatedItemHeight.scaled() + let scaledWidth = Constants.estimatedItemWidth.scaled() + + let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(scaledWidth), heightDimension: .absolute(scaledHeight)) + let item = NSCollectionLayoutItem(layoutSize: itemSize) + + let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(scaledHeight)) + let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) + group.interItemSpacing = .fixed(spacing) + + let containerWidth = configuration.container.effectiveContentSize.width + let itemCount = self.collectionView.dataSource?.collectionView(self.collectionView, numberOfItemsInSection: 0) ?? 0 + // Create margins to center the content in the container + let margin = self.horizontalMargin(forContainerWidth: containerWidth, itemWidth: scaledWidth, + interItemSpacing: spacing, itemCount: itemCount) + + let section = NSCollectionLayoutSection(group: group) + section.interGroupSpacing = spacing + section.contentInsets = .init(top: 0, leading: margin / 2.0, bottom: 0, trailing: margin / 2.0) + return section + } + return layout + } + + @objc + private func didTapView() { + delegate?.didSelectTaskView(self, eventIndexPath: .init(row: 0, section: 0)) + } + + @objc + private func didTapCompletionButton(_ sender: UIControl) { + // Find the index path for the tapped button + collectionView.indexPathsForVisibleItems.forEach { + let cell = collectionView.cellForItem(at: $0) as? OCKGridTaskView.DefaultCellType + if cell?.completionButton === sender { + delegate?.taskView(self, didCompleteEvent: !sender.isSelected, at: $0, sender: sender) + return + } + } + } + + private func resetCollectionViewSizing() { + collectionView.collectionViewLayout.invalidateLayout() // To reset the margins and item spacing + } + + override open func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { + resetCollectionViewSizing() + } + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + instructionsLabel.textColor = style.color.secondaryLabel + contentStackView.spacing = style.dimension.directionalInsets1.top + directionalLayoutMargins = style.dimension.directionalInsets1 + contentStackView.directionalLayoutMargins = style.dimension.directionalInsets1 + resetCollectionViewSizing() + } + + // MARK: - UICollectionViewDelegate + + open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + guard let cell = collectionView.cellForItem(at: indexPath) as? OCKGridTaskView.DefaultCellType else { return } + // Assume the action is successfull and toggle the selected state + cell.completionButton.isSelected.toggle() + // Notify the delegate that an event has been toggled + delegate?.taskView(self, didCompleteEvent: cell.completionButton.isSelected, at: indexPath, sender: cell.completionButton) + } +} + +private extension Int { + var float: CGFloat { return CGFloat(self) } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKInstructionsTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKInstructionsTaskView.swift new file mode 100755 index 0000000..372906b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKInstructionsTaskView.swift @@ -0,0 +1,153 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays a header, multi-line label, and a completion button. In CareKit, this view is +/// intended to display a particular event for a task. The state of the completion button indicates +/// the completion state of the event. +/// +/// To insert custom views vertically the view, see `contentStack` +/// +/// +-------------------------------------------------------+ +/// | | +/// | [title] [detail | +/// | [detail] disclosure] | +/// | | +/// | | +/// | -------------------------------------------------- | +/// | | +/// | [instructions] | +/// | | +/// | +-------------------------------------------------+ | +/// | | [title] | | +/// | +-------------------------------------------------+ | +/// | | +/// +-------------------------------------------------------+ +/// +open class OCKInstructionsTaskView: OCKView, OCKTaskDisplayable { + + // MARK: Properties + + let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + private lazy var headerButton = OCKAnimatedButton(contentView: headerView, highlightOptions: [.defaultDelayOnSelect, .defaultOverlay], + handlesSelection: false) + + private let headerStackView = OCKStackView.vertical() + + /// A vertical stack view that holds the main content for the view. + public let contentStackView: OCKStackView = { + let stack = OCKStackView.vertical() + stack.isLayoutMarginsRelativeArrangement = true + return stack + }() + + /// Handles events related to an `OCKTaskDisplayable` object. + public weak var delegate: OCKTaskViewDelegate? + + /// The button on the bottom of the view. The background color is the `tintColor` when in a normal state. and gray when + /// in a selected state. + public let completionButton = OCKLabeledButton() + + /// Multi-line label over the `completionButton`. + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .medium) + label.numberOfLines = 0 + return label + }() + + /// A header view that tshows a separator and a `detailDisclosureImage`. + public let headerView = OCKHeaderView { + $0.showsSeparator = true + $0.showsDetailDisclosure = true + } + + // MARK: Methods + + override func setup() { + super.setup() + addSubviews() + styleSubviews() + constrainSubviews() + setupGestures() + } + + private func setupGestures() { + headerButton.addTarget(self, action: #selector(didTapView), for: .touchUpInside) + completionButton.addTarget(self, action: #selector(completionButtonTapped(_:)), for: .touchUpInside) + } + + private func styleSubviews() { + contentStackView.setCustomSpacing(0, after: completionButton) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(headerStackView) + [headerButton, contentStackView].forEach { headerStackView.addArrangedSubview($0) } + [instructionsLabel, completionButton].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, headerStackView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + headerStackView.constraints(equalTo: contentView) + + headerView.constraints(equalTo: headerButton.layoutMarginsGuide, directions: [.horizontal, .top]) + + headerView.constraints(equalTo: headerButton, directions: [.bottom])) + } + + @objc + private func didTapView() { + delegate?.didSelectTaskView(self, eventIndexPath: .init(row: 0, section: 0)) + } + + @objc + private func completionButtonTapped(_ sender: UIControl) { + delegate?.taskView(self, didCompleteEvent: !sender.isSelected, at: .init(row: 0, section: 0), sender: sender) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + instructionsLabel.textColor = style.color.label + contentStackView.spacing = style.dimension.directionalInsets1.top + directionalLayoutMargins = style.dimension.directionalInsets1 + contentStackView.directionalLayoutMargins = style.dimension.directionalInsets1 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKLogTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKLogTaskView.swift new file mode 100755 index 0000000..9cdd181 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKLogTaskView.swift @@ -0,0 +1,206 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Base class for all log view. Shows an `OCKHeaderView` and a dynamic stack view of log items. +open class OCKLogTaskView: OCKView, OCKTaskDisplayable { + + // MARK: Properties + + private let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + private lazy var headerButton = OCKAnimatedButton(contentView: headerView, highlightOptions: [.defaultDelayOnSelect, .defaultOverlay], + handlesSelection: false) + + private let headerStackView = OCKStackView.vertical() + + let logItemsStackView: OCKStackView = { + var stackView = OCKStackView(style: .separated) + stackView.showsOuterSeparators = false + return stackView + }() + + /// A vertical stack view that holds the main content for the view. + public let contentStackView: OCKStackView = { + let stack = OCKStackView.vertical() + stack.isLayoutMarginsRelativeArrangement = true + return stack + }() + + /// Handles events related to an `OCKTaskDisplayable` object. + public weak var delegate: OCKTaskViewDelegate? + + /// The header view that shows a separator and a `detailDisclosureImage`. + public let headerView = OCKHeaderView { + $0.showsSeparator = true + $0.showsDetailDisclosure = true + } + + /// The list of buttons in the log. + open var items: [OCKLogItemButton] { + guard let buttons = logItemsStackView.arrangedSubviews as? [OCKLogItemButton] else { fatalError("Unsupported type.") } + return buttons + } + + // MARK: - Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + setupGestures() + } + + func addSubviews() { + addSubview(contentView) + contentView.addSubview(headerStackView) + [headerButton, contentStackView].forEach { headerStackView.addArrangedSubview($0) } + [logItemsStackView].forEach { contentStackView.addArrangedSubview($0) } + } + + func constrainSubviews() { + [contentView, headerStackView, headerView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + headerStackView.constraints(equalTo: contentView) + + headerView.constraints(equalTo: headerButton.layoutMarginsGuide, directions: [.horizontal, .top]) + + headerView.constraints(equalTo: headerButton, directions: [.bottom])) + } + + private func setupGestures() { + headerButton.addTarget(self, action: #selector(didTapView), for: .touchUpInside) + } + + private func makeItem(withTitle title: String?, detail: String?) -> OCKLogItemButton { + let button = OCKLogItemButton() + button.addTarget(self, action: #selector(itemTapped(_:)), for: .touchUpInside) + button.titleLabel.text = title + button.detailLabel.text = detail + button.accessibilityLabel = (detail ?? "") + " " + (title ?? "") + button.accessibilityHint = loc("DOUBLE_TAP_TO_REMOVE_EVENT") + return button + } + + @objc + private func didTapView() { + delegate?.didSelectTaskView(self, eventIndexPath: .init(row: 0, section: 0)) + } + + @objc + private func itemTapped(_ sender: UIControl) { + guard let index = logItemsStackView.arrangedSubviews.firstIndex(of: sender) else { + fatalError("Target was not set up properly.") + } + delegate?.taskView(self, didSelectOutcomeValueAt: index, eventIndexPath: .init(row: 0, section: 0), sender: sender) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + contentStackView.spacing = style.dimension.directionalInsets1.top + directionalLayoutMargins = style.dimension.directionalInsets1 + contentStackView.directionalLayoutMargins = style.dimension.directionalInsets1 + } + + /// Update the text for an item at a particular index. + /// + /// - Parameters: + /// - index: The index of the item to update. + /// - title: The title text to display in the item. + /// - detail: The detail text to display in the item. The text is tinted by default. + /// - Returns: The item that was updated. + @discardableResult + open func updateItem(at index: Int, withTitle title: String?, detail: String?) -> OCKLogItemButton? { + guard index < logItemsStackView.arrangedSubviews.count else { return nil } + let button = items[index] + button.accessibilityLabel = title + button.titleLabel.text = title + button.detailLabel.text = detail + return button + } + + /// Insert an item in the list of logged items. + /// + /// - Parameters: + /// - title: The title text to display in the item. + /// - detail: The detail text to display in the item. The text is tinted by default. + /// - index: The index to insert the item in the list of logged items. + /// - animated: Animate the insertion of the logged item. + /// - Returns: The item that was inserted. + @discardableResult + open func insertItem(withTitle title: String?, detail: String?, at index: Int, animated: Bool) -> OCKLogItemButton { + let button = makeItem(withTitle: title, detail: detail) + logItemsStackView.insertArrangedSubview(button, at: index, animated: animated) + return button + } + + /// Append an item to the list of logged items. + /// + /// - Parameters: + /// - title: The detail text to display in the item. The text is tinted by default. + /// - detail: The detail text to display in the item. The text is tinted by default. + /// - animated: Animate appending the item. + /// - Returns: The item that was appended. + @discardableResult + open func appendItem(withTitle title: String?, detail: String?, animated: Bool) -> OCKLogItemButton { + let button = makeItem(withTitle: title, detail: detail) + logItemsStackView.addArrangedSubview(button, animated: animated) + return button + } + + /// Remove an item from the list of logged items. + /// + /// - Parameters: + /// - index: The index of the item to remove. + /// - animated: Animate the removal of the item. + /// - Returns: The item that was removed. + @discardableResult + open func removeItem(at index: Int, animated: Bool) -> OCKLogItemButton? { + guard index < logItemsStackView.arrangedSubviews.count else { return nil } + let button = items[index] + logItemsStackView.removeArrangedSubview(button, animated: animated) + return button + } + + /// Clear all items from the list of logged items. + /// + /// - Parameter animated: Animate clearing the items. + open func clearItems(animated: Bool) { + logItemsStackView.clear(animated: animated) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKSimpleTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKSimpleTaskView.swift new file mode 100755 index 0000000..e987b46 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKSimpleTaskView.swift @@ -0,0 +1,123 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A card that displays an `OCKHeaderView` and a circular checkmark button `completionButton`. +/// In CareKit, this view is intended to display a particular event for a task. The state of the `completionButton` +/// indicates the completion state of the event. +/// +/// To insert custom views vertically the view, see `contentStack` +/// +/// +-------------------------------------------------------+ +/// | | +/// | [title] [completion | +/// | [detail] button] | +/// | | +/// +-------------------------------------------------------+ +/// +open class OCKSimpleTaskView: OCKView, OCKTaskDisplayable { + + // MARK: Properties + + private let contentView: OCKView = { + let view = OCKView() + view.clipsToBounds = true + return view + }() + + // Button that displays the highlighted state for the view. + private lazy var backgroundButton = OCKAnimatedButton(contentView: horizontalContentStackView, handlesSelection: false) + + private lazy var cardBuilder = OCKCardBuilder(cardView: self, contentView: contentView) + + private let horizontalContentStackView: OCKStackView = { + let stack = OCKStackView.horizontal() + stack.alignment = .center + return stack + }() + + /// The button in the trailing end of the card. Has an image that is defaulted to a checkmark when selected. + public let completionButton: OCKCheckmarkButton = { + let button = OCKCheckmarkButton() + button.isUserInteractionEnabled = false + return button + }() + + /// Handles events related to an `OCKTaskDisplayable` object. + public weak var delegate: OCKTaskViewDelegate? + + /// A default version of an `OCKHeaderView`. + public let headerView = OCKHeaderView() + + // MARK: Methods + + override func setup() { + super.setup() + setupGestures() + addSubviews() + constrainSubviews() + + isAccessibilityElement = true + accessibilityTraits = .button + } + + private func setupGestures() { + backgroundButton.addTarget(self, action: #selector(didCompleteEvent(_:)), for: .touchUpInside) + } + + private func addSubviews() { + addSubview(contentView) + contentView.addSubview(backgroundButton) + [headerView, completionButton].forEach { horizontalContentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [contentView, backgroundButton, horizontalContentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + completionButton.setContentHuggingPriority(.defaultHigh, for: .horizontal) + NSLayoutConstraint.activate( + contentView.constraints(equalTo: self) + + backgroundButton.constraints(equalTo: contentView) + + horizontalContentStackView.constraints(equalTo: backgroundButton.layoutMarginsGuide)) + } + + @objc + private func didCompleteEvent(_ sender: UIControl) { + completionButton.setSelected(!completionButton.isSelected, animated: true) + delegate?.taskView(self, didCompleteEvent: completionButton.isSelected, at: .init(row: 0, section: 0), sender: sender) + } + + override open func styleDidChange() { + super.styleDidChange() + let style = self.style() + cardBuilder.enableCardStyling(true, style: style) + backgroundButton.directionalLayoutMargins = style.dimension.directionalInsets1 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKTaskDisplayable.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKTaskDisplayable.swift new file mode 100755 index 0000000..a332213 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Components/Task/OCKTaskDisplayable.swift @@ -0,0 +1,71 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// Any object that can display and handle interactions with a task. +public protocol OCKTaskDisplayable: AnyObject { + /// Handles events related to an `OCKTaskDisplayable` object. + var delegate: OCKTaskViewDelegate? { get set } +} + +/// Handles events related to an `OCKTaskDisplayable` object. +public protocol OCKTaskViewDelegate: AnyObject { + + /// Called when an event is completed. + /// - Parameters: + /// - taskView: View displaying the event. + /// - isComplete: True if the event is complete. + /// - indexPath: Index path of the event. + /// - sender: Sender that initiated the completion. + func taskView(_ taskView: UIView & OCKTaskDisplayable, didCompleteEvent isComplete: Bool, at indexPath: IndexPath, sender: Any?) + + /// Called when an outcome value was selected for a particular event. + /// - Parameters: + /// - taskView: View displaying the outcome value. + /// - index: Indec of the outcome value in the event's oucome. + /// - eventIndexPath: index path of the event. + /// - sender: Sender that initiated the selection. + func taskView(_ taskView: UIView & OCKTaskDisplayable, didSelectOutcomeValueAt index: Int, eventIndexPath: IndexPath, sender: Any?) + + /// Called when an outcome value has been created at a particular index. + /// - Parameters: + /// - taskView: View displaying the outcome. + /// - index: Index of the new outcome value. + /// - eventIndexPath: Index of the event. + /// - sender: Sender that initiated the outcome value creation. + func taskView(_ taskView: UIView & OCKTaskDisplayable, didCreateOutcomeValueAt index: Int, eventIndexPath: IndexPath, sender: Any?) + + /// Called when the task view has been selected. + /// - Parameters: + /// - taskView: The task view that has been selected. + /// - eventIndexPath: The index path of the event displayed by the task view. + func didSelectTaskView(_ taskView: UIView & OCKTaskDisplayable, eventIndexPath: IndexPath) +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Detail View/OCKDetailView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Detail View/OCKDetailView.swift new file mode 100755 index 0000000..aefa40a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Detail View/OCKDetailView.swift @@ -0,0 +1,109 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit + +/// A view intended to display fine grained details. The view contains a configurable image, title, and instructions. To add +/// custom views, insert into the `contentStackView`. +open class OCKDetailView: OCKView { + // MARK: Properties + + private var contentStackViewTopConstraint: NSLayoutConstraint? + private var imageViewHeightConstraint: NSLayoutConstraint? + + /// Configurable image that spans the width of the view. + public let imageView: UIImageView = { + let imageView = UIImageView() + imageView.contentMode = .scaleAspectFill + return imageView + }() + + /// Primary multi-line label. + public let titleLabel: OCKLabel = { + let titleLabel = OCKLabel(textStyle: .title2, weight: .semibold) + titleLabel.numberOfLines = 0 + return titleLabel + }() + + /// Secondary multi-line label + public let instructionsLabel: OCKLabel = { + let label = OCKLabel(textStyle: .subheadline, weight: .medium) + label.numberOfLines = 0 + return label + }() + + /// The vertical stack view that holds the main content for the view. + public let contentStackView = OCKStackView.vertical() + + // MARK: Methods + + override func setup() { + super.setup() + addSubviews() + constrainSubviews() + } + + private func addSubviews() { + [imageView, contentStackView].forEach { addSubview($0) } + [titleLabel, instructionsLabel].forEach { contentStackView.addArrangedSubview($0) } + } + + private func constrainSubviews() { + [imageView, contentStackView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false } + + imageViewHeightConstraint = imageView.heightAnchor.constraint(equalToConstant: 0) + contentStackViewTopConstraint = contentStackView.topAnchor.constraint(equalTo: imageView.bottomAnchor) + + NSLayoutConstraint.activate([ + imageView.leadingAnchor.constraint(equalTo: leadingAnchor), + imageView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor), + imageView.trailingAnchor.constraint(equalTo: trailingAnchor), + imageViewHeightConstraint!, + + contentStackViewTopConstraint!, + contentStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + contentStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + contentStackView.bottomAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.bottomAnchor) + ]) + } + + override open func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + backgroundColor = cachedStyle.color.customBackground + directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + instructionsLabel.textColor = cachedStyle.color.label + imageView.backgroundColor = cachedStyle.color.secondaryCustomFill + titleLabel.textColor = cachedStyle.color.label + imageViewHeightConstraint?.constant = cachedStyle.dimension.imageHeight1 + contentStackViewTopConstraint?.constant = cachedStyle.dimension.directionalInsets1.top + contentStackView.spacing = cachedStyle.dimension.directionalInsets1.top / 2.0 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Info.plist new file mode 100755 index 0000000..e1fe4cf --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/OCKLocalization.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/OCKLocalization.swift new file mode 100755 index 0000000..89a047d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/OCKLocalization.swift @@ -0,0 +1,98 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COP + YRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation + +/// A hook for the free function `loc` to access the framework bundle for localizations +public class OCKLocalization { + + /// An `NSLocalizedString` wrapper that searches for overrides in a main bundle before falling back to the framework provided strings + public static func localized( + _ key: String, + tableName: String? = nil, + bundle: Bundle? = nil, + value: String = "", + comment: String = "" + ) -> String { + + // Find a specified or main bundle override for the given `key` + let str: String = { + switch bundle { + case .some(let bundle): + return NSLocalizedString( + key, + tableName: tableName, + bundle: bundle, + value: value, + comment: comment + ) + case .none: + return NSLocalizedString( + key, + tableName: tableName, + value: value, + comment: comment + ) + } + }() + + // If the string does not equal the key, there was an override in the main bundle + guard str == key else { return str } + + // Use this framework's localizable strings if an override is not found + return NSLocalizedString( + key, + tableName: tableName, + bundle: Bundle(for: OCKLocalization.self), + value: value, + comment: comment + ) + + } + +} + +/// A localization string wrapper to access framework specific strings +/// - Parameter key: The `NSLocalizedString` key +/// - Parameter comment: The `NSLocalizedString` comment +/// +/// This is a free function for developer convenience. +public func loc(_ key: String, _ comment: String = "") -> String { + + return OCKLocalization.localized( + key, + tableName: nil, + bundle: nil, + value: "", + comment: comment + ) + +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.strings b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.strings new file mode 100755 index 0000000..189f9c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.strings @@ -0,0 +1,63 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +"ADDRESS" = "Address"; +"ANNOUNCE_EVENT_DELETED" = "Logged event was deleted"; +"CANCEL" = "Cancel"; +"CALL" = "Call"; +"COMPLETED" = "Completed"; +"CONTACTS" = "Contacts"; +"DELETE" = "Delete"; +"DONE" = "Done"; +"DOUBLE_TAP_MAP" = "Double-tap to open directions in Maps"; +"DOUBLE_TAP_TO_COMPLETE" = "Double-tap to mark as completed"; +"DOUBLE_TAP_TO_INCOMPLETE" = "Double-tap to mark as incomplete"; +"DOUBLE_TAP_TO_RECORD_EVENT" = "Double-tap to record an event"; +"DOUBLE_TAP_TO_REMOVE_EVENT" = "Double-tap to removed logged event"; +"EMAIL" = "E-mail"; +"EVENT" = "Event"; +"GOAL" = "Goal"; +"HIGH" = "High"; +"INCOMPLETE" = "Incomplete"; +"LOG" = "Log"; +"LOG_ENTRY" = "Log Entry"; +"LOGGING" = "Logging"; +"LOW" = "Low"; +"MARK_COMPLETE" = "Mark as Completed"; +"MESSAGE" = "Message"; +"NO_TASKS" = "No Tasks"; +"NO_EVENTS" = "No Events"; +"PROGRESS" = "Progress"; +"SEARCH" = "Search"; +"SELECTED" = "Selected"; +"TASKS" = "Tasks"; +"THREE_FINGER_SWIPE_DAY" = "Three-finger swipe to go to next or previous day"; +"THREE_FINGER_SWIPE_WEEK" = "Three-finger swipe to go to next or previous week"; +"TODAY" = "Today"; diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.stringsdict b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.stringsdict new file mode 100755 index 0000000..d823f17 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUI/Supporting Files/Localization/en.lproj/Localizable.stringsdict @@ -0,0 +1,30 @@ + + + + + EVENTS_REMAINING + + NSStringLocalizedFormatKey + %#@events_remaining@ + events_remaining + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + i + zero + 0 remaining + one + 1 remaining + two + + few + + many + + other + %i remaining + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/CareKitUI.xctestplan b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/CareKitUI.xctestplan new file mode 100755 index 0000000..558ddd3 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/CareKitUI.xctestplan @@ -0,0 +1,29 @@ +{ + "configurations" : [ + { + "id" : "F686CBA9-D127-405A-9EE0-ADAD9E5BDD49", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "codeCoverage" : false, + "targetForVariableExpansion" : { + "containerPath" : "container:CareKitUI.xcodeproj", + "identifier" : "5174225A224185290054E97C", + "name" : "CareKitUI" + } + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:CareKitUI.xcodeproj", + "identifier" : "512B012D22C2F82900ABCB1D", + "name" : "CareKitUITests" + } + } + ], + "version" : 1 +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/Info.plist new file mode 100755 index 0000000..64d65ca --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/OCKResponsiveLayoutTests.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/OCKResponsiveLayoutTests.swift new file mode 100755 index 0000000..6fb8a5d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/OCKResponsiveLayoutTests.swift @@ -0,0 +1,295 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +@testable import CareKitUI +import XCTest + +class OCKResponsiveLayoutTests: XCTestCase { + enum DefaultTestLayouts { + // Completely arbitrary + case spiral(Int), rotation(CGFloat) + } + + enum SizeClassTestLayouts { + case columns(Int), estimatedWidth(CGFloat), list + } + + let defaultTestLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .spiral(3), + anySizeClassRuleSet: [ + .init(layout: .spiral(5), greaterThanOrEqualToContentSizeCategory: .small), + .init(layout: .rotation(90), greaterThanOrEqualToContentSizeCategory: .large) + ] + ) + + let extraSmallTestLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .spiral(3), + anySizeClassRuleSet: [ + .init(layout: .spiral(4), greaterThanOrEqualToContentSizeCategory: .extraSmall), + .init(layout: .rotation(90), greaterThanOrEqualToContentSizeCategory: .large) + ] + ) + + let undefinedTestLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .spiral(3), + anySizeClassRuleSet: [ + .init(layout: .spiral(4), greaterThanOrEqualToContentSizeCategory: .small), + .init(layout: .rotation(90), greaterThanOrEqualToContentSizeCategory: .large) + ] + ) + + let sizeClassTestLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .estimatedWidth(200), + anySizeClassRuleSet: [ + .init(layout: .columns(3), greaterThanOrEqualToContentSizeCategory: .medium), + .init(layout: .columns(2), greaterThanOrEqualToContentSizeCategory: .extraLarge), + .init(layout: .list, greaterThanOrEqualToContentSizeCategory: .accessibilityMedium) + ], + + sizeClassSpecificRuleSets: [ + // ~ iPad + OCKResponsiveLayout.SizeClassRuleSet( + sizeClass: (horizontal: .regular, vertical: .regular), + rules: [ + .init(layout: .estimatedWidth(200)), + .init(layout: .estimatedWidth(300), greaterThanOrEqualToContentSizeCategory: .large), + .init(layout: .columns(3), greaterThanOrEqualToContentSizeCategory: .extraLarge), + .init(layout: .list, greaterThanOrEqualToContentSizeCategory: .accessibilityLarge) + ] + ), + + // ~ iPhone horizontal + OCKResponsiveLayout.SizeClassRuleSet( + sizeClass: (horizontal: .regular, vertical: .compact), + rules: [ + .init(layout: .estimatedWidth(150)), + .init(layout: .estimatedWidth(250), greaterThanOrEqualToContentSizeCategory: .large), + .init(layout: .columns(4), greaterThanOrEqualToContentSizeCategory: .extraLarge), + .init(layout: .list, greaterThanOrEqualToContentSizeCategory: .accessibilityLarge) + ] + ) + ] + ) + + func testDefaultLayoutUpperContentSizeCategory() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .large) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .rotation(let val): XCTAssert(val == 90) + default: XCTFail("Result was unepected value") + } + } + + func testDefaultLayoutAboveUpperContentSizeCategory() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraExtraLarge) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .rotation(let val): XCTAssert(val == 90) + default: XCTFail("Result was unepected value") + } + } + + func testDefaultLayoutLowerContentSizeCategory() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .extraSmall) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 3) + default: XCTFail("Result was unepected value") + } + } + + func testDefaultLayoutExactContentSizeCategory() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .small) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 5) + default: XCTFail("Result was unepected value") + } + } + + func testDefaultLayoutGapBetweenContentSizeCategories() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .medium) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 5) + default: XCTFail("Result was unepected value") + } + } + + func testDefaultLayoutGapBetweenContentSizeCategoriesFailure() { + let traitCollection = UITraitCollection(preferredContentSizeCategory: .medium) + let result = defaultTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssertFalse(val == 3) + default: break + } + } + + func testDefaultLayoutSize() { + let missingDefaultLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .spiral(5), + anySizeClassRuleSet: [ + .init(layout: .spiral(6), greaterThanOrEqualToContentSizeCategory: .small), + .init(layout: .rotation(90), greaterThanOrEqualToContentSizeCategory: .large) + ] + ) + + let traitCollection = UITraitCollection(preferredContentSizeCategory: .medium) + let result = missingDefaultLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 6) + default: XCTFail("Layout was unexpected value") + } + + let failureTraitCollection = UITraitCollection(preferredContentSizeCategory: .extraSmall) + + switch missingDefaultLayoutDefinition.responsiveLayoutRule(traitCollection: failureTraitCollection) { + case .spiral(let val): XCTAssert(val == 5) + default: XCTFail("Layout was unexpected value") + } + + } + + func testSizeClassMatch() { + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .regular), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .large) + ]) + + let result = sizeClassTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .estimatedWidth(let val): XCTAssert(val == 300) + default: XCTFail("Layout was unexpected value") + } + } + + func testOverValueSizeClassMatch() { + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .regular), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraExtraLarge) + ]) + + let result = sizeClassTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .list: break + default: XCTFail("Layout was unexpected value") + } + } + + func testOtherSizeClassMatch() { + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .compact), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .large) + ]) + + let result = sizeClassTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .estimatedWidth(250): break + default: XCTFail("Layout was unexpected value") + } + } + + func testExtraSmallOverrideDefault() { + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .compact), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .extraSmall) + ]) + + let result = extraSmallTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 4) + default: XCTFail("Layout was unexpected value") + } + } + + func testUndefinedDefault() { + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .compact), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .extraSmall) + ]) + + let result = undefinedTestLayoutDefinition.responsiveLayoutRule(traitCollection: traitCollection) + + switch result { + case .spiral(let val): XCTAssert(val == 3) + default: XCTFail("Layout was unexpected value") + } + } + + func testSizeClassMissingContentSizeCategory() { + let missingSizeClassTestLayoutDefinition = OCKResponsiveLayout( + defaultLayout: .estimatedWidth(200), + anySizeClassRuleSet: [], + sizeClassSpecificRuleSets: [ + // ~ iPad + OCKResponsiveLayout.SizeClassRuleSet( + sizeClass: (horizontal: .regular, vertical: .regular), + rules: [ + .init(layout: .estimatedWidth(300), greaterThanOrEqualToContentSizeCategory: .large), + .init(layout: .columns(3), greaterThanOrEqualToContentSizeCategory: .extraLarge), + .init(layout: .list, greaterThanOrEqualToContentSizeCategory: .accessibilityLarge) + ] + ) + ] + ) + + let traitCollection = UITraitCollection(traitsFrom: [ + UITraitCollection(verticalSizeClass: .regular), + UITraitCollection(horizontalSizeClass: .regular), + UITraitCollection(preferredContentSizeCategory: .extraSmall) + ]) + + let result = missingSizeClassTestLayoutDefinition.responsiveLayoutRule( + traitCollection: traitCollection + ) + + switch result { + case .estimatedWidth(let val): + XCTAssert(val == 200) + default: XCTFail("Layout was unexpected value") + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestGridTaskView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestGridTaskView.swift new file mode 100755 index 0000000..3b98c98 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestGridTaskView.swift @@ -0,0 +1,66 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitUI +import Foundation +import XCTest + +public class TestGridTaskView: XCTestCase { + + var view: OCKGridTaskView! + + override public func setUp() { + super.setUp() + view = .init() + } + + func testHorizontalMargin() { + var observed = view.horizontalMargin(forContainerWidth: 300, itemWidth: 50, interItemSpacing: 0, itemCount: 20) + XCTAssertEqual(observed, 0) + + observed = view.horizontalMargin(forContainerWidth: 300, itemWidth: 40, interItemSpacing: 0, itemCount: 20) + XCTAssertEqual(observed, 20) + + observed = view.horizontalMargin(forContainerWidth: 100, itemWidth: 40, interItemSpacing: 20, itemCount: 20) + XCTAssertEqual(observed, 0) + + observed = view.horizontalMargin(forContainerWidth: 100, itemWidth: 30, interItemSpacing: 20, itemCount: 20) + XCTAssertEqual(observed, 20) + + observed = view.horizontalMargin(forContainerWidth: 100, itemWidth: 40, interItemSpacing: 20, itemCount: 2) + XCTAssertEqual(observed, 0) + + observed = view.horizontalMargin(forContainerWidth: 100, itemWidth: 40, interItemSpacing: 20, itemCount: 1) + XCTAssertEqual(observed, 60) + + observed = view.horizontalMargin(forContainerWidth: 100, itemWidth: 40, interItemSpacing: 20, itemCount: 0) + XCTAssertEqual(observed, 100) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestStylableView.swift b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestStylableView.swift new file mode 100755 index 0000000..7608bd7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/CareKitUI/CareKitUITests/TestStylableView.swift @@ -0,0 +1,202 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@testable import CareKitUI +import XCTest + +private class MockStylableView: OCKView { + override func styleDidChange() { + super.styleDidChange() + layer.cornerRadius = style().appearance.cornerRadius1 + } +} + +private class MockOverridingView: OCKView { + static let cornerRadius: CGFloat = 2 + + override func styleDidChange() { + super.styleDidChange() + subviews.forEach { $0.layer.cornerRadius = MockOverridingView.cornerRadius } + } +} + +private struct MockAppearanceStyle: OCKAppearanceStyler { + var cornerRadius1: CGFloat { 1 } +} + +private struct MockStyle: OCKStyler { + var appearance: OCKAppearanceStyler { MockAppearanceStyle() } +} + +class TestStylableView: XCTestCase { + private let defaultStyle = OCKStyle() + private let customStyle = MockStyle() + + // Default style should exist on init + func testDefaultStyle() { + let view = MockStylableView() + XCTAssertNotNil(view.layer.cornerRadius) + XCTAssertEqual(view.layer.cornerRadius, defaultStyle.appearance.cornerRadius1) + } + + // Custom style should exist when set + func testCustomStyle() { + let view = MockStylableView() + view.customStyle = customStyle + XCTAssertNotNil(view.layer.cornerRadius) + XCTAssertEqual(view.layer.cornerRadius, customStyle.appearance.cornerRadius1) + } + + // Custom style can be reset to the default style + func testClearCustomStyle() { + let view = MockStylableView() + view.customStyle = customStyle + view.customStyle = nil + XCTAssertNotNil(view.layer.cornerRadius) + XCTAssertEqual(view.layer.cornerRadius, defaultStyle.appearance.cornerRadius1) + } + + // default style should pass linearly through subviews + func testDefaultLinearInheritance() { + let views = (0..<3).map { _ in MockStylableView() } + views[0].addSubview(views[1]) + views[1].addSubview(views[2]) + + views.enumerated().forEach { + let message = "Failed for view at index \($0)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, defaultStyle.appearance.cornerRadius1, message) + } + } + + // Custom style should pass linearly through subviews + func testCustomLinearInheritance() { + // On the first iteration, set the style then embed the view. On the second, embed the view then set the style + for iteration in (0..<2) { + let views = (0..<3).map { _ in MockStylableView() } + if iteration == 0 { views[0].customStyle = customStyle } + views[0].addSubview(views[1]) + views[1].addSubview(views[2]) + if iteration == 1 { views[0].customStyle = customStyle } + + views.enumerated().forEach { + let message = "Failed for view at index \($0), iteration: \(iteration)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, customStyle.appearance.cornerRadius1, message) + } + } + } + + // Custom style should pass linearly through subviews of the view whose custom style was set, without affecting its parents + func testCustomLinearNonInheritance() { + // On the first iteration, set the style then embed the view. On the second, embed the view then set the style + for iteration in (0..<2) { + let views = (0..<3).map { _ in MockStylableView() } + if iteration == 0 { views[1].customStyle = customStyle } + views[0].addSubview(views[1]) + views[1].addSubview(views[2]) + if iteration == 1 { views[1].customStyle = customStyle } + + views.enumerated().forEach { + let style: OCKStyler = $0 == 0 ? defaultStyle : customStyle + let message = "Failed for view at index \($0), iteration: \(iteration)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, style.appearance.cornerRadius1, message) + } + } + } + + // Custom style should switch back to default when a custom styled view is removed from a view hierarchy + func testCustomLinearRemoval() { + // On the first iteration, set the style then embed the view. On the second, embed the view then set the style + for iteration in (0..<2) { + let views = (0..<3).map { _ in MockStylableView() } + if iteration == 0 { views[0].customStyle = customStyle } + views[0].addSubview(views[1]) + views[1].addSubview(views[2]) + if iteration == 1 { views[0].customStyle = customStyle } + views[1].removeFromSuperview() + + views.enumerated().forEach { + let style: OCKStyler = $0 == 0 ? customStyle : defaultStyle + let message = "Failed for view at index \($0), iteration: \(iteration)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, style.appearance.cornerRadius1, message) + } + } + } + + // Custom style should propogate through view that has two children + func testCustomBranchingInheritance() { + // On the first iteration, set the style then embed the view. On the second, embed the view then set the style + for iteration in (0..<2) { + let views = (0..<3).map { _ in MockStylableView() } + if iteration == 0 { views[0].customStyle = customStyle } + views[0].addSubview(views[1]) + views[0].addSubview(views[2]) + if iteration == 1 { views[0].customStyle = customStyle } + + views.enumerated().forEach { + let message = "Failed for view at index \($0), iteration: \(iteration)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, customStyle.appearance.cornerRadius1, message) + } + } + } + + // View with multiple children should have default style when one child is custom styled + func testCustomBranchingNonInheritance() { + // On the first iteration, set the style then embed the view. On the second, embed the view then set the style + for iteration in (0..<2) { + let views = (0..<3).map { _ in MockStylableView() } + if iteration == 0 { views[1].customStyle = customStyle } + views[0].addSubview(views[1]) + views[0].addSubview(views[2]) + if iteration == 1 { views[1].customStyle = customStyle } + + views.enumerated().forEach { + let style: OCKStyler = $0 == 1 ? customStyle : defaultStyle + let message = "Failed for view at index \($0), iteration: \(iteration)" + XCTAssertNotNil($1.layer.cornerRadius, message) + XCTAssertEqual($1.layer.cornerRadius, style.appearance.cornerRadius1, message) + } + } + } + + // The `styleDidChange` method should be called from the inside out with respect to the view hierarchy + func testOverridingInnerStyle() { + let outerView = MockOverridingView() + let innerView = MockStylableView() + outerView.addSubview(innerView) + outerView.customStyle = customStyle + XCTAssertNotNil(innerView.layer.cornerRadius) + XCTAssertEqual(innerView.layer.cornerRadius, MockOverridingView.cornerRadius) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/LICENSE b/PediatricPancreas_Storyboard/CareKit-master/LICENSE new file mode 100755 index 0000000..89ed43a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2016, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.pbxproj new file mode 100755 index 0000000..cd5860d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.pbxproj @@ -0,0 +1,511 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 039A9EAA236B97B400158EDD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039A9EA9236B97B400158EDD /* SceneDelegate.swift */; }; + 03A2F78E237F51DF00A13638 /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F771237F51BA00A13638 /* CareKit.framework */; }; + 03A2F78F237F51DF00A13638 /* CareKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F771237F51BA00A13638 /* CareKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03A2F790237F51DF00A13638 /* CareKitStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7C8B1F0228A1B34000B68FB /* CareKitStore.framework */; }; + 03A2F791237F51DF00A13638 /* CareKitStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E7C8B1F0228A1B34000B68FB /* CareKitStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03A2F792237F51DF00A13638 /* CareKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F78D237F51DF00A13638 /* CareKitUI.framework */; }; + 03A2F793237F51DF00A13638 /* CareKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F78D237F51DF00A13638 /* CareKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03FEBEA2237A0C7E00ACB35E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 03FEBEA0237A0C7D00ACB35E /* Localizable.stringsdict */; }; + 03FEBEA3237A0C7E00ACB35E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03FEBEA1237A0C7E00ACB35E /* Localizable.strings */; }; + 51EF57C9229B21AA0071E2F6 /* OCKStore+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF57C8229B21AA0071E2F6 /* OCKStore+Extensions.swift */; }; + 51F81A4C227A6E660075AF70 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51F81A47227A6E660075AF70 /* RootViewController.swift */; }; + E7D010FC222498F400C008DE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D010FB222498F400C008DE /* AppDelegate.swift */; }; + E7D01103222498F400C008DE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E7D01102222498F400C008DE /* Assets.xcassets */; }; + E7D01106222498F400C008DE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E7D01104222498F400C008DE /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 03A2F770237F51BA00A13638 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 03A2F76B237F51BA00A13638 /* CareKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8605A5BA1C4F04EC00DD65FF; + remoteInfo = CareKit; + }; + 03A2F772237F51BA00A13638 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 03A2F76B237F51BA00A13638 /* CareKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5196C7F9226F8F8F00F1C2A2; + remoteInfo = CareKitTests; + }; + 5143E1FB22C2832600E32526 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = E7D010F0222498F400C008DE /* Project object */; + proxyType = 1; + remoteGlobalIDString = E7D010F7222498F400C008DE; + remoteInfo = OCKCatalog; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 516CD56823543678005E2779 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 03A2F791237F51DF00A13638 /* CareKitStore.framework in Embed Frameworks */, + 03A2F78F237F51DF00A13638 /* CareKit.framework in Embed Frameworks */, + 03A2F793237F51DF00A13638 /* CareKitUI.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 039A9EA9236B97B400158EDD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 03A2F76B237F51BA00A13638 /* CareKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CareKit.xcodeproj; path = ../CareKit/CareKit.xcodeproj; sourceTree = ""; }; + 03A2F78D237F51DF00A13638 /* CareKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 03FEBEA0237A0C7D00ACB35E /* Localizable.stringsdict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.stringsdict; path = Localizable.stringsdict; sourceTree = ""; }; + 03FEBEA1237A0C7E00ACB35E /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; + 1409475522B0261A005C1D16 /* CareKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5143E1F622C2832600E32526 /* OCKCatalogTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OCKCatalogTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5143E1FA22C2832600E32526 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 51D0ECFD2284894E00D24A76 /* CareKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 51EF57C8229B21AA0071E2F6 /* OCKStore+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OCKStore+Extensions.swift"; sourceTree = ""; }; + 51F81A47227A6E660075AF70 /* RootViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; + E7C8B1F0228A1B34000B68FB /* CareKitStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E7D010F8222498F400C008DE /* OCKCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OCKCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E7D010FB222498F400C008DE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E7D01102222498F400C008DE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E7D01105222498F400C008DE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + E7D01107222498F400C008DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 5143E1F322C2832600E32526 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7D010F5222498F400C008DE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 03A2F790237F51DF00A13638 /* CareKitStore.framework in Frameworks */, + 03A2F78E237F51DF00A13638 /* CareKit.framework in Frameworks */, + 03A2F792237F51DF00A13638 /* CareKitUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 03A2F76C237F51BA00A13638 /* Products */ = { + isa = PBXGroup; + children = ( + 03A2F771237F51BA00A13638 /* CareKit.framework */, + 03A2F773237F51BA00A13638 /* CareKitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 5143E1F722C2832600E32526 /* OCKCatalogTests */ = { + isa = PBXGroup; + children = ( + 5143E1FA22C2832600E32526 /* Info.plist */, + ); + path = OCKCatalogTests; + sourceTree = ""; + }; + 51D0ECFC2284894E00D24A76 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 03A2F78D237F51DF00A13638 /* CareKitUI.framework */, + 1409475522B0261A005C1D16 /* CareKit.framework */, + E7C8B1F0228A1B34000B68FB /* CareKitStore.framework */, + 51D0ECFD2284894E00D24A76 /* CareKitUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E7D010EF222498F400C008DE = { + isa = PBXGroup; + children = ( + 03A2F76B237F51BA00A13638 /* CareKit.xcodeproj */, + E7D010FA222498F400C008DE /* OCKCatalog */, + 5143E1F722C2832600E32526 /* OCKCatalogTests */, + E7D010F9222498F400C008DE /* Products */, + 51D0ECFC2284894E00D24A76 /* Frameworks */, + ); + sourceTree = ""; + }; + E7D010F9222498F400C008DE /* Products */ = { + isa = PBXGroup; + children = ( + E7D010F8222498F400C008DE /* OCKCatalog.app */, + 5143E1F622C2832600E32526 /* OCKCatalogTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + E7D010FA222498F400C008DE /* OCKCatalog */ = { + isa = PBXGroup; + children = ( + 51EF57C8229B21AA0071E2F6 /* OCKStore+Extensions.swift */, + 51F81A47227A6E660075AF70 /* RootViewController.swift */, + E7D010FB222498F400C008DE /* AppDelegate.swift */, + 039A9EA9236B97B400158EDD /* SceneDelegate.swift */, + E7D01107222498F400C008DE /* Info.plist */, + E7D01104222498F400C008DE /* LaunchScreen.storyboard */, + 03FEBEA1237A0C7E00ACB35E /* Localizable.strings */, + 03FEBEA0237A0C7D00ACB35E /* Localizable.stringsdict */, + E7D01102222498F400C008DE /* Assets.xcassets */, + ); + path = OCKCatalog; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 5143E1F522C2832600E32526 /* OCKCatalogTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5143E1FF22C2832600E32526 /* Build configuration list for PBXNativeTarget "OCKCatalogTests" */; + buildPhases = ( + 5143E1F222C2832600E32526 /* Sources */, + 5143E1F322C2832600E32526 /* Frameworks */, + 5143E1F422C2832600E32526 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5143E1FC22C2832600E32526 /* PBXTargetDependency */, + ); + name = OCKCatalogTests; + productName = OCKCatalogTests; + productReference = 5143E1F622C2832600E32526 /* OCKCatalogTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + E7D010F7222498F400C008DE /* OCKCatalog */ = { + isa = PBXNativeTarget; + buildConfigurationList = E7D0110A222498F400C008DE /* Build configuration list for PBXNativeTarget "OCKCatalog" */; + buildPhases = ( + 0588EAC82357CC4F00F2646B /* Fix SPM */, + E7D010F4222498F400C008DE /* Sources */, + E7D010F5222498F400C008DE /* Frameworks */, + E7D010F6222498F400C008DE /* Resources */, + 51936B1B22418DAA00F7B1DD /* ShellScript */, + 516CD56823543678005E2779 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCKCatalog; + packageProductDependencies = ( + ); + productName = OCK2SampleApp; + productReference = E7D010F8222498F400C008DE /* OCKCatalog.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E7D010F0222498F400C008DE /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = Apple; + TargetAttributes = { + 5143E1F522C2832600E32526 = { + CreatedOnToolsVersion = 11.0; + TestTargetID = E7D010F7222498F400C008DE; + }; + E7D010F7222498F400C008DE = { + CreatedOnToolsVersion = 10.1; + LastSwiftMigration = 1020; + }; + }; + }; + buildConfigurationList = E7D010F3222498F400C008DE /* Build configuration list for PBXProject "OCKCatalog" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = E7D010EF222498F400C008DE; + productRefGroup = E7D010F9222498F400C008DE /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 03A2F76C237F51BA00A13638 /* Products */; + ProjectRef = 03A2F76B237F51BA00A13638 /* CareKit.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + E7D010F7222498F400C008DE /* OCKCatalog */, + 5143E1F522C2832600E32526 /* OCKCatalogTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 03A2F771237F51BA00A13638 /* CareKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = CareKit.framework; + remoteRef = 03A2F770237F51BA00A13638 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 03A2F773237F51BA00A13638 /* CareKitTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = CareKitTests.xctest; + remoteRef = 03A2F772237F51BA00A13638 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 5143E1F422C2832600E32526 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7D010F6222498F400C008DE /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7D01106222498F400C008DE /* LaunchScreen.storyboard in Resources */, + 03FEBEA3237A0C7E00ACB35E /* Localizable.strings in Resources */, + E7D01103222498F400C008DE /* Assets.xcassets in Resources */, + 03FEBEA2237A0C7E00ACB35E /* Localizable.stringsdict in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0588EAC82357CC4F00F2646B /* Fix SPM */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Fix SPM"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -d \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" ] && [ \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" != \"${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/\" ] \nthen\n cp -f -R \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" \"${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/\"\nfi\n"; + }; + 51936B1B22418DAA00F7B1DD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5143E1F222C2832600E32526 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E7D010F4222498F400C008DE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 51F81A4C227A6E660075AF70 /* RootViewController.swift in Sources */, + E7D010FC222498F400C008DE /* AppDelegate.swift in Sources */, + 51EF57C9229B21AA0071E2F6 /* OCKStore+Extensions.swift in Sources */, + 039A9EAA236B97B400158EDD /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 5143E1FC22C2832600E32526 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = E7D010F7222498F400C008DE /* OCKCatalog */; + targetProxy = 5143E1FB22C2832600E32526 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + E7D01104222498F400C008DE /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + E7D01105222498F400C008DE /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 5143E1FD22C2832600E32526 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 7JYUG8QGJ3; + INFOPLIST_FILE = OCKCatalogTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = Apple.OCKCatalogTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OCKCatalog.app/OCKCatalog"; + }; + name = Debug; + }; + E7D01108222498F400C008DE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + FRAMEWORK_SEARCH_PATHS = "$(BUILD_DIR)/Debug-$(PLATFORM_NAME)"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + E7D0110B222498F400C008DE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/OCKCatalog/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.carekit-samplecode.OCKCatalog"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 5143E1FF22C2832600E32526 /* Build configuration list for PBXNativeTarget "OCKCatalogTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5143E1FD22C2832600E32526 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E7D010F3222498F400C008DE /* Build configuration list for PBXProject "OCKCatalog" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7D01108222498F400C008DE /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E7D0110A222498F400C008DE /* Build configuration list for PBXNativeTarget "OCKCatalog" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E7D0110B222498F400C008DE /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = E7D010F0222498F400C008DE /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/xcshareddata/xcschemes/OCKCatalog.xcscheme b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/xcshareddata/xcschemes/OCKCatalog.xcscheme new file mode 100755 index 0000000..0c87bfd --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog.xcodeproj/xcshareddata/xcschemes/OCKCatalog.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/AppDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/AppDelegate.swift new file mode 100755 index 0000000..f962b0b --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/AppDelegate.swift @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + let storeManager: OCKSynchronizedStoreManager = { + let store = OCKStore(name: "carekit-catalog") + store.fillWithDummyData() + return OCKSynchronizedStoreManager(wrapping: store) + }() + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + return true + } + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, + options: UIScene.ConnectionOptions) -> UISceneConfiguration { + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..d8db8d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/Contents.json b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Base.lproj/LaunchScreen.storyboard b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..bfa3612 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Info.plist new file mode 100755 index 0000000..3493411 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + OCKCatalog + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.strings b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.strings new file mode 100755 index 0000000..189f9c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.strings @@ -0,0 +1,63 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +"ADDRESS" = "Address"; +"ANNOUNCE_EVENT_DELETED" = "Logged event was deleted"; +"CANCEL" = "Cancel"; +"CALL" = "Call"; +"COMPLETED" = "Completed"; +"CONTACTS" = "Contacts"; +"DELETE" = "Delete"; +"DONE" = "Done"; +"DOUBLE_TAP_MAP" = "Double-tap to open directions in Maps"; +"DOUBLE_TAP_TO_COMPLETE" = "Double-tap to mark as completed"; +"DOUBLE_TAP_TO_INCOMPLETE" = "Double-tap to mark as incomplete"; +"DOUBLE_TAP_TO_RECORD_EVENT" = "Double-tap to record an event"; +"DOUBLE_TAP_TO_REMOVE_EVENT" = "Double-tap to removed logged event"; +"EMAIL" = "E-mail"; +"EVENT" = "Event"; +"GOAL" = "Goal"; +"HIGH" = "High"; +"INCOMPLETE" = "Incomplete"; +"LOG" = "Log"; +"LOG_ENTRY" = "Log Entry"; +"LOGGING" = "Logging"; +"LOW" = "Low"; +"MARK_COMPLETE" = "Mark as Completed"; +"MESSAGE" = "Message"; +"NO_TASKS" = "No Tasks"; +"NO_EVENTS" = "No Events"; +"PROGRESS" = "Progress"; +"SEARCH" = "Search"; +"SELECTED" = "Selected"; +"TASKS" = "Tasks"; +"THREE_FINGER_SWIPE_DAY" = "Three-finger swipe to go to next or previous day"; +"THREE_FINGER_SWIPE_WEEK" = "Three-finger swipe to go to next or previous week"; +"TODAY" = "Today"; diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.stringsdict b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.stringsdict new file mode 100755 index 0000000..d823f17 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/Localizable.stringsdict @@ -0,0 +1,30 @@ + + + + + EVENTS_REMAINING + + NSStringLocalizedFormatKey + %#@events_remaining@ + events_remaining + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + i + zero + 0 remaining + one + 1 remaining + two + + few + + many + + other + %i remaining + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/OCKStore+Extensions.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/OCKStore+Extensions.swift new file mode 100755 index 0000000..3bb5c65 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/OCKStore+Extensions.swift @@ -0,0 +1,109 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Foundation + +extension OCKSchedule { + /// Create a schedule that happens at meal times every day of the week. + static func mealTimesEachDay(start: Date, end: Date?) -> OCKSchedule { + let startDate = Calendar.current.startOfDay(for: start) + let breakfast = OCKSchedule.dailyAtTime(hour: 7, minutes: 30, start: startDate, end: end, text: "Breakfast") + let lunch = OCKSchedule.dailyAtTime(hour: 12, minutes: 0, start: startDate, end: end, text: "Lunch") + let dinner = OCKSchedule.dailyAtTime(hour: 17, minutes: 30, start: startDate, end: end, text: "Dinner") + return OCKSchedule(composing: [breakfast, lunch, dinner]) + } +} + +extension OCKStore { + func fillWithDummyData() { + // Note: If the tasks and contacts already exist in the store, these methods will fail. If you have modified the data and would like the + // changes to be reflected in the app, delete and reinstall the catalog app. + let aFewDaysAgo = Calendar.current.startOfDay(for: Calendar.current.date(byAdding: .day, value: -10, to: Date())!) + addTasks(makeTasks(on: aFewDaysAgo), callbackQueue: .main) { result in + switch result { + case .failure(let error): print("[ERROR] \(error.localizedDescription)") + case .success: break + } + } + + addContacts(makeContacts(), callbackQueue: .main) { result in + switch result { + case .failure(let error): print("[ERROR] \(error.localizedDescription)") + case .success: break + } + } + } + + private func makeTasks(on start: Date) -> [OCKTask] { + var task1 = OCKTask(id: "nausea", title: "Nausea", carePlanID: nil, + schedule: .dailyAtTime(hour: 7, minutes: 0, start: start, end: nil, text: nil)) + task1.instructions = "Log any time you experience nausea." + task1.impactsAdherence = false + + var task2 = OCKTask(id: "doxylamine", title: "Doxylamine", carePlanID: nil, + schedule: .mealTimesEachDay(start: start, end: nil)) + task2.instructions = "Take the tablet with a full glass of water." + + return [task1, task2] + } + + private func makeContacts() -> [OCKContact] { + var contact1 = OCKContact(id: "lexi-torres", givenName: "Lexi", familyName: "Torres", carePlanID: nil) + contact1.role = "Dr. Torres is a family practice doctor with over 20 years of experience." + let phoneNumbers1 = [OCKLabeledValue(label: "work", value: "2135558479")] + contact1.phoneNumbers = phoneNumbers1 + contact1.title = "Family Practice" + contact1.messagingNumbers = phoneNumbers1 + contact1.emailAddresses = [OCKLabeledValue(label: "work", value: "lexitorres@icloud.com")] + let address1 = OCKPostalAddress() + address1.street = "26 E Centerline Rd" + address1.city = "Victor" + address1.state = "MI" + address1.postalCode = "48848" + contact1.address = address1 + + var contact2 = OCKContact(id: "matthew-reiff", givenName: "Matthew", familyName: "Reiff", carePlanID: nil) + contact2.role = "Dr. Reiff is a family practice doctor with over 20 years of experience." + contact2.title = "Family Practice" + let phoneNumbers2 = [OCKLabeledValue(label: "work", value: "7745550146")] + contact2.phoneNumbers = phoneNumbers2 + contact2.messagingNumbers = phoneNumbers2 + contact2.emailAddresses = [OCKLabeledValue(label: "work", value: "matthewreiff@icloud.com")] + let address2 = OCKPostalAddress() + address2.street = "9391 Burkshire Avenue" + address2.city = "Cardiff" + address2.state = "CA" + address2.postalCode = "92007" + contact2.address = address2 + + return [contact1, contact2] + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/RootViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/RootViewController.swift new file mode 100755 index 0000000..37d871d --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/RootViewController.swift @@ -0,0 +1,229 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import UIKit + +class RootViewController: UITableViewController { + private enum Constants { + static let cellID = "cell" + static let untrackedTaskID = "nausea" + static let trackedTaskID = "doxylamine" + static let contactID = "lexi-torres" + } + + private enum Section: String, CaseIterable { + case task, contact, chart, list + } + + private enum TaskStyle: String, CaseIterable { + case grid, checklist + case simple, instructions, buttonLog = "button log" + } + + private enum ContactStyle: String, CaseIterable { + case simple, detailed + } + + private enum List: String, CaseIterable { + case tasks, contacts + } + + private let storeManager: OCKSynchronizedStoreManager + + init(storeManager: OCKSynchronizedStoreManager) { + self.storeManager = storeManager + super.init(style: .grouped) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + tableView.register(UITableViewCell.self, forCellReuseIdentifier: Constants.cellID) + tableView.tableFooterView = UIView() + clearsSelectionOnViewWillAppear = true + + navigationController?.navigationBar.prefersLargeTitles = true + title = "CareKit Catalog" + + tableView.reloadData() + } + + override func numberOfSections(in tableView: UITableView) -> Int { + return Section.allCases.count + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return Section.allCases[section].rawValue + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch Section.allCases[section] { + case .task: return TaskStyle.allCases.count + case .contact: return ContactStyle.allCases.count + case .chart: return OCKCartesianGraphView.PlotType.allCases.count + case .list: return List.allCases.count + } + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: Constants.cellID, for: indexPath) + let title: String + switch Section.allCases[indexPath.section] { + case .task: title = TaskStyle.allCases[indexPath.row].rawValue + case .contact: title = ContactStyle.allCases[indexPath.row].rawValue + case .chart: title = OCKCartesianGraphView.PlotType.allCases[indexPath.row].rawValue + case .list: title = List.allCases[indexPath.row].rawValue + } + cell.textLabel?.text = title.capitalized + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + var viewController: UIViewController + + let section = Section.allCases[indexPath.section] + switch section { + case .task: + let taskViewController = makeTaskViewController(withStyle: TaskStyle.allCases[indexPath.row], storeManager: storeManager) + let listController = OCKListViewController() + listController.appendViewController(taskViewController, animated: false) + viewController = listController + + case .contact: + let contactViewController = makeContactViewController(withStyle: ContactStyle.allCases[indexPath.row], storeManager: storeManager) + let listController = OCKListViewController() + listController.appendViewController(contactViewController, animated: false) + viewController = listController + + case .chart: + let chartViewController = makeChartViewController(withStyle: OCKCartesianGraphView.PlotType.allCases[indexPath.row], + storeManager: storeManager) + let listController = OCKListViewController() + listController.appendViewController(chartViewController, animated: false) + viewController = listController + + case .list: + switch List.allCases[indexPath.row] { + case .tasks: + let rootViewController = OCKDailyTasksPageViewController(storeManager: storeManager) + rootViewController.isModalInPresentation = true + rootViewController.navigationItem.rightBarButtonItem = .init(barButtonSystemItem: .done, + target: self, action: #selector(dismissViewController)) + viewController = UINavigationController(rootViewController: rootViewController) + + case .contacts: + let rootViewController = OCKContactsListViewController(storeManager: storeManager) + rootViewController.isModalInPresentation = true + rootViewController.navigationItem.rightBarButtonItem = .init(barButtonSystemItem: .done, + target: self, action: #selector(dismissViewController)) + viewController = UINavigationController(rootViewController: rootViewController) + } + } + if section == .list { + present(viewController, animated: true, completion: nil) + } else { + navigationController?.pushViewController(viewController, animated: true) + } + clearSelection() + } + + private func makeTaskViewController(withStyle style: TaskStyle, storeManager: OCKSynchronizedStoreManager) -> UIViewController { + switch style { + case .checklist: + return OCKChecklistTaskViewController(taskID: Constants.trackedTaskID, eventQuery: .init(for: Date()), storeManager: storeManager) + case .grid: + return OCKGridTaskViewController(taskID: Constants.trackedTaskID, eventQuery: .init(for: Date()), storeManager: storeManager) + case .simple: + return OCKSimpleTaskViewController(taskID: Constants.trackedTaskID, eventQuery: .init(for: Date()), storeManager: storeManager) + case .instructions: + return OCKInstructionsTaskViewController(taskID: Constants.trackedTaskID, eventQuery: .init(for: Date()), storeManager: storeManager) + case .buttonLog: + return OCKButtonLogTaskViewController(taskID: Constants.untrackedTaskID, eventQuery: .init(for: Date()), storeManager: storeManager) + } + } + + private func makeContactViewController(withStyle style: ContactStyle, storeManager: OCKSynchronizedStoreManager) -> UIViewController { + switch style { + case .simple: + let viewController = OCKSimpleContactViewController(contactID: Constants.contactID, storeManager: storeManager) + return viewController + + case .detailed: + let viewController = OCKDetailedContactViewController(contactID: Constants.contactID, storeManager: storeManager) + viewController.controller.fetchAndObserveContact(withID: Constants.contactID) + return viewController + } + } + + private func makeChartViewController(withStyle style: OCKCartesianGraphView.PlotType, + storeManager: OCKSynchronizedStoreManager) -> UIViewController { + let gradientStart = UIColor { traitCollection -> UIColor in + return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.3725490196, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.2630574384, blue: 0.2592858295, alpha: 1) + } + let gradientEnd = UIColor { traitCollection -> UIColor in + return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.4732026144, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.3598620686, blue: 0.2592858295, alpha: 1) + } + + let markerSize: CGFloat = style == .bar ? 10 : 2 + let startOfDay = Calendar.current.startOfDay(for: Date()) + let configurations = [ + OCKDataSeriesConfiguration( + taskID: Constants.trackedTaskID, + legendTitle: Constants.trackedTaskID.capitalized, + gradientStartColor: gradientStart, + gradientEndColor: gradientEnd, + markerSize: markerSize, + eventAggregator: .countOutcomeValues) + ] + + let chartViewController = OCKCartesianChartViewController(plotType: style, selectedDate: startOfDay, + configurations: configurations, storeManager: storeManager) + chartViewController.controller.fetchAndObserveInsights(forConfigurations: configurations) + chartViewController.chartView.headerView.titleLabel.text = Constants.trackedTaskID.capitalized + return chartViewController + } + + private func clearSelection() { + if let selectionPath = self.tableView.indexPathForSelectedRow { + self.tableView.deselectRow(at: selectionPath, animated: true) + } + } + + @objc + private func dismissViewController() { + dismiss(animated: true, completion: nil) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/SceneDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/SceneDelegate.swift new file mode 100755 index 0000000..44a6595 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalog/SceneDelegate.swift @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + + let appDelegate = UIApplication.shared.delegate as! AppDelegate + let rootViewController = RootViewController(storeManager: appDelegate.storeManager) + let navigationController = UINavigationController(rootViewController: rootViewController) + + if let windowScene = scene as? UIWindowScene { + window = UIWindow(windowScene: windowScene) + window?.rootViewController = navigationController + window?.tintColor = UIColor { $0.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.3725490196, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.2630574384, blue: 0.2592858295, alpha: 1) } + window?.makeKeyAndVisible() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalogTests/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalogTests/Info.plist new file mode 100755 index 0000000..64d65ca --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKCatalog/OCKCatalogTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.pbxproj new file mode 100755 index 0000000..d51bfab --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.pbxproj @@ -0,0 +1,400 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 03A2F787237F51D800A13638 /* CareKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F768237F51B400A13638 /* CareKit.framework */; }; + 03A2F788237F51D800A13638 /* CareKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F768237F51B400A13638 /* CareKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03A2F789237F51D800A13638 /* CareKitStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7C8B1F4228A1B41000B68FB /* CareKitStore.framework */; }; + 03A2F78A237F51D800A13638 /* CareKitStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E7C8B1F4228A1B41000B68FB /* CareKitStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03A2F78B237F51D800A13638 /* CareKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F786237F51D800A13638 /* CareKitUI.framework */; }; + 03A2F78C237F51D800A13638 /* CareKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 03A2F786237F51D800A13638 /* CareKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 03F0600A2331946600CCE09B /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F060092331946600CCE09B /* SceneDelegate.swift */; }; + 03FEBEC6237A0D6100ACB35E /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 03FEBEC4237A0D6100ACB35E /* Localizable.strings */; }; + 03FEBEC7237A0D6100ACB35E /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 03FEBEC5237A0D6100ACB35E /* Localizable.stringsdict */; }; + E72B2C0A226939E3009A9438 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E72B2C09226939E3009A9438 /* AppDelegate.swift */; }; + E72B2C14226939E4009A9438 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E72B2C12226939E4009A9438 /* LaunchScreen.storyboard */; }; + E7440E4F229477F7007AD30A /* CareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7440E4E229477F7007AD30A /* CareViewController.swift */; }; + E7C37849228F887800E982D8 /* TipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7C37848228F887800E982D8 /* TipView.swift */; }; + E7C4CA0B22809AD500ECC3D7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E7C4CA0A22809AD500ECC3D7 /* Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 03A2F767237F51B400A13638 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 03A2F762237F51B400A13638 /* CareKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8605A5BA1C4F04EC00DD65FF; + remoteInfo = CareKit; + }; + 03A2F769237F51B400A13638 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 03A2F762237F51B400A13638 /* CareKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5196C7F9226F8F8F00F1C2A2; + remoteInfo = CareKitTests; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 51F1E2592360F46C003D83FA /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 03A2F78A237F51D800A13638 /* CareKitStore.framework in Embed Frameworks */, + 03A2F788237F51D800A13638 /* CareKit.framework in Embed Frameworks */, + 03A2F78C237F51D800A13638 /* CareKitUI.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 03A2F762237F51B400A13638 /* CareKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CareKit.xcodeproj; path = ../CareKit/CareKit.xcodeproj; sourceTree = ""; }; + 03A2F786237F51D800A13638 /* CareKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 03F060092331946600CCE09B /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 03FEBEC4237A0D6100ACB35E /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = ""; }; + 03FEBEC5237A0D6100ACB35E /* Localizable.stringsdict */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.stringsdict; path = Localizable.stringsdict; sourceTree = ""; }; + 1409475222B025AD005C1D16 /* CareKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E72B2C06226939E3009A9438 /* OCKSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OCKSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + E72B2C09226939E3009A9438 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + E72B2C13226939E4009A9438 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + E72B2C15226939E4009A9438 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + E737105922862B7B005D3B03 /* CareKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E7440E4E229477F7007AD30A /* CareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CareViewController.swift; sourceTree = ""; }; + E7C37848228F887800E982D8 /* TipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TipView.swift; sourceTree = ""; }; + E7C4CA0A22809AD500ECC3D7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + E7C8B1F4228A1B41000B68FB /* CareKitStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CareKitStore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E72B2C03226939E3009A9438 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 03A2F789237F51D800A13638 /* CareKitStore.framework in Frameworks */, + 03A2F787237F51D800A13638 /* CareKit.framework in Frameworks */, + 03A2F78B237F51D800A13638 /* CareKitUI.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 03A2F763237F51B400A13638 /* Products */ = { + isa = PBXGroup; + children = ( + 03A2F768237F51B400A13638 /* CareKit.framework */, + 03A2F76A237F51B400A13638 /* CareKitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 71A79C8A2294FBA1002B96D3 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 03FEBEC4237A0D6100ACB35E /* Localizable.strings */, + 03FEBEC5237A0D6100ACB35E /* Localizable.stringsdict */, + E7C4CA0A22809AD500ECC3D7 /* Assets.xcassets */, + E72B2C12226939E4009A9438 /* LaunchScreen.storyboard */, + E72B2C15226939E4009A9438 /* Info.plist */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + E72B2BFD226939E3009A9438 = { + isa = PBXGroup; + children = ( + 03A2F762237F51B400A13638 /* CareKit.xcodeproj */, + E72B2C08226939E3009A9438 /* OCKSample */, + E72B2C07226939E3009A9438 /* Products */, + E72B2C2F22693C51009A9438 /* Frameworks */, + ); + sourceTree = ""; + }; + E72B2C07226939E3009A9438 /* Products */ = { + isa = PBXGroup; + children = ( + E72B2C06226939E3009A9438 /* OCKSample.app */, + ); + name = Products; + sourceTree = ""; + }; + E72B2C08226939E3009A9438 /* OCKSample */ = { + isa = PBXGroup; + children = ( + E72B2C09226939E3009A9438 /* AppDelegate.swift */, + 03F060092331946600CCE09B /* SceneDelegate.swift */, + E7440E4E229477F7007AD30A /* CareViewController.swift */, + E7C37848228F887800E982D8 /* TipView.swift */, + 71A79C8A2294FBA1002B96D3 /* Supporting Files */, + ); + path = OCKSample; + sourceTree = ""; + }; + E72B2C2F22693C51009A9438 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 03A2F786237F51D800A13638 /* CareKitUI.framework */, + 1409475222B025AD005C1D16 /* CareKit.framework */, + E7C8B1F4228A1B41000B68FB /* CareKitStore.framework */, + E737105922862B7B005D3B03 /* CareKitUI.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E72B2C05226939E3009A9438 /* OCKSample */ = { + isa = PBXNativeTarget; + buildConfigurationList = E72B2C18226939E4009A9438 /* Build configuration list for PBXNativeTarget "OCKSample" */; + buildPhases = ( + 05D4F0402357E0AA004F42DC /* Fix SPM */, + E72B2C02226939E3009A9438 /* Sources */, + E72B2C03226939E3009A9438 /* Frameworks */, + E72B2C04226939E3009A9438 /* Resources */, + 51F1E2592360F46C003D83FA /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OCKSample; + packageProductDependencies = ( + ); + productName = CareKitDemoApp; + productReference = E72B2C06226939E3009A9438 /* OCKSample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E72B2BFE226939E3009A9438 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1020; + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = Apple; + TargetAttributes = { + E72B2C05226939E3009A9438 = { + CreatedOnToolsVersion = 10.2; + }; + }; + }; + buildConfigurationList = E72B2C01226939E3009A9438 /* Build configuration list for PBXProject "OCKSample" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = E72B2BFD226939E3009A9438; + productRefGroup = E72B2C07226939E3009A9438 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 03A2F763237F51B400A13638 /* Products */; + ProjectRef = 03A2F762237F51B400A13638 /* CareKit.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + E72B2C05226939E3009A9438 /* OCKSample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 03A2F768237F51B400A13638 /* CareKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = CareKit.framework; + remoteRef = 03A2F767237F51B400A13638 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 03A2F76A237F51B400A13638 /* CareKitTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = CareKitTests.xctest; + remoteRef = 03A2F769237F51B400A13638 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + E72B2C04226939E3009A9438 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7C4CA0B22809AD500ECC3D7 /* Assets.xcassets in Resources */, + 03FEBEC7237A0D6100ACB35E /* Localizable.stringsdict in Resources */, + 03FEBEC6237A0D6100ACB35E /* Localizable.strings in Resources */, + E72B2C14226939E4009A9438 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 05D4F0402357E0AA004F42DC /* Fix SPM */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Fix SPM"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ -d \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" ] && [ \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" != \"${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/\" ] \nthen\n cp -f -R \"${SYMROOT}/Release${EFFECTIVE_PLATFORM_NAME}/\" \"${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}/\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + E72B2C02226939E3009A9438 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E7440E4F229477F7007AD30A /* CareViewController.swift in Sources */, + E72B2C0A226939E3009A9438 /* AppDelegate.swift in Sources */, + E7C37849228F887800E982D8 /* TipView.swift in Sources */, + 03F0600A2331946600CCE09B /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + E72B2C12226939E4009A9438 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + E72B2C13226939E4009A9438 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + E72B2C16226939E4009A9438 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_TREAT_WARNINGS_AS_ERRORS = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + E72B2C19226939E4009A9438 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 17; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/OCKSample/Supporting Files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.carekit-samplecode.OCKSample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E72B2C01226939E3009A9438 /* Build configuration list for PBXProject "OCKSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E72B2C16226939E4009A9438 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E72B2C18226939E4009A9438 /* Build configuration list for PBXNativeTarget "OCKSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E72B2C19226939E4009A9438 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = E72B2BFE226939E3009A9438 /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/xcshareddata/xcschemes/OCKSample.xcscheme b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/xcshareddata/xcschemes/OCKSample.xcscheme new file mode 100755 index 0000000..2525578 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample.xcodeproj/xcshareddata/xcschemes/OCKSample.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/AppDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/AppDelegate.swift new file mode 100755 index 0000000..f15f572 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/AppDelegate.swift @@ -0,0 +1,130 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import Contacts +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + // Manages synchronization of a CoreData store + lazy var synchronizedStoreManager: OCKSynchronizedStoreManager = { + let store = OCKStore(name: "SampleAppStore") + store.populateSampleData() + let manager = OCKSynchronizedStoreManager(wrapping: store) + return manager + }() + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + return true + } + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } +} + +private extension OCKStore { + + // Adds tasks and contacts into the store + func populateSampleData() { + + let thisMorning = Calendar.current.startOfDay(for: Date()) + let aFewDaysAgo = Calendar.current.date(byAdding: .day, value: -4, to: thisMorning)! + let beforeBreakfast = Calendar.current.date(byAdding: .hour, value: 8, to: aFewDaysAgo)! + let afterLunch = Calendar.current.date(byAdding: .hour, value: 14, to: aFewDaysAgo)! + + let schedule = OCKSchedule(composing: [ + OCKScheduleElement(start: beforeBreakfast, end: nil, + interval: DateComponents(day: 1)), + + OCKScheduleElement(start: afterLunch, end: nil, + interval: DateComponents(day: 2)) + ]) + + var doxylamine = OCKTask(id: "doxylamine", title: "Take Doxylamine", + carePlanID: nil, schedule: schedule) + doxylamine.instructions = "Take 25mg of doxylamine when you experience nausea." + + let nauseaSchedule = OCKSchedule(composing: [ + OCKScheduleElement(start: beforeBreakfast, end: nil, interval: DateComponents(day: 1), + text: "Anytime throughout the day", targetValues: [], duration: .allDay) + ]) + + var nausea = OCKTask(id: "nausea", title: "Track your nausea", + carePlanID: nil, schedule: nauseaSchedule) + nausea.impactsAdherence = false + nausea.instructions = "Tap the button below anytime you experience nausea." + + let kegelSchedule = OCKSchedule(composing: [OCKScheduleElement(start: beforeBreakfast, end: nil, interval: DateComponents(day: 2))]) + var kegels = OCKTask(id: "kegels", title: "Kegel Exercises", carePlanID: nil, schedule: kegelSchedule) + kegels.impactsAdherence = true + kegels.instructions = "Perform kegel exercies" + + addTasks([nausea, doxylamine, kegels], callbackQueue: .main, completion: nil) + + var contact1 = OCKContact(id: "jane", givenName: "Jane", + familyName: "Daniels", carePlanID: nil) + contact1.asset = "JaneDaniels" + contact1.title = "Family Practice Doctor" + contact1.role = "Dr. Daniels is a family practice doctor with 8 years of experience." + contact1.emailAddresses = [OCKLabeledValue(label: CNLabelEmailiCloud, value: "janedaniels@icloud.com")] + contact1.phoneNumbers = [OCKLabeledValue(label: CNLabelWork, value: "(324) 555-7415")] + contact1.messagingNumbers = [OCKLabeledValue(label: CNLabelWork, value: "(324) 555-7415")] + + contact1.address = { + let address = OCKPostalAddress() + address.street = "2598 Reposa Way" + address.city = "San Francisco" + address.state = "CA" + address.postalCode = "94127" + return address + }() + + var contact2 = OCKContact(id: "matthew", givenName: "Matthew", + familyName: "Reiff", carePlanID: nil) + contact2.asset = "MatthewReiff" + contact2.title = "OBGYN" + contact2.role = "Dr. Reiff is an OBGYN with 13 years of experience." + contact2.phoneNumbers = [OCKLabeledValue(label: CNLabelWork, value: "(324) 555-7415")] + contact2.messagingNumbers = [OCKLabeledValue(label: CNLabelWork, value: "(324) 555-7415")] + contact2.address = { + let address = OCKPostalAddress() + address.street = "396 El Verano Way" + address.city = "San Francisco" + address.state = "CA" + address.postalCode = "94127" + return address + }() + + addContacts([contact1, contact2]) + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/CareViewController.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/CareViewController.swift new file mode 100755 index 0000000..3c70660 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/CareViewController.swift @@ -0,0 +1,152 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import Foundation +import UIKit +import CareKit + +class CareViewController: OCKDailyPageViewController { + + override func viewDidLoad() { + super.viewDidLoad() + navigationItem.rightBarButtonItem = + UIBarButtonItem(title: "Care Team", style: .plain, target: self, + action: #selector(presentContactsListViewController)) + } + + @objc private func presentContactsListViewController() { + let viewController = OCKContactsListViewController(storeManager: storeManager) + viewController.title = "Care Team" + viewController.isModalInPresentation = true + viewController.navigationItem.rightBarButtonItem = + UIBarButtonItem(title: "Done", style: .plain, target: self, + action: #selector(dismissContactsListViewController)) + + let navigationController = UINavigationController(rootViewController: viewController) + present(navigationController, animated: true, completion: nil) + } + + @objc private func dismissContactsListViewController() { + dismiss(animated: true, completion: nil) + } + + // This will be called each time the selected date changes. + // Use this as an opportunity to rebuild the content shown to the user. + + override func dailyPageViewController(_ dailyPageViewController: OCKDailyPageViewController, + prepare listViewController: OCKListViewController, for date: Date) { + + let identifiers = ["doxylamine", "nausea", "kegels"] + var query = OCKTaskQuery(for: date) + query.ids = identifiers + query.excludesTasksWithNoEvents = true + + storeManager.store.fetchAnyTasks(query: query, callbackQueue: .main) { result in + switch result { + case .failure(let error): print("Error: \(error)") + case .success(let tasks): + + // Add a non-CareKit view into the list + let tipTitle = "Benefits of exercising" + let tipText = "Learn how activity can promote a healthy pregnancy." + + // Only show the tip view on the current date + if Calendar.current.isDate(date, inSameDayAs: Date()) { + let tipView = TipView() + tipView.headerView.titleLabel.text = tipTitle + tipView.headerView.detailLabel.text = tipText + tipView.imageView.image = UIImage(named: "exercise.jpg") + listViewController.appendView(tipView, animated: false) + } + + // Since the kegel task is only sheduled every other day, there will be cases + // where it is not contained in the tasks array returned from the query. + if let kegelsTask = tasks.first(where: { $0.id == "kegels" }) { + let kegelsCard = OCKSimpleTaskViewController(task: kegelsTask, eventQuery: .init(for: date), + storeManager: self.storeManager) + listViewController.appendViewController(kegelsCard, animated: false) + } + + // Create a card for the doxylamine task if there are events for it on this day. + if let doxylamineTask = tasks.first(where: { $0.id == "doxylamine" }) { + let doxylamineCard = OCKChecklistTaskViewController(task: doxylamineTask, eventQuery: .init(for: date), + storeManager: self.storeManager) + listViewController.appendViewController(doxylamineCard, animated: false) + } + + // Create a card for the nausea task if there are events for it on this day. + // Its OCKSchedule was defined to have daily events, so this task should be + // found in `tasks` every day after the task start date. + if let nauseaTask = tasks.first(where: { $0.id == "nausea" }) { + + // dynamic gradient colors + let nauseaGradientStart = UIColor { traitCollection -> UIColor in + return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.3725490196, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.2630574384, blue: 0.2592858295, alpha: 1) + } + let nauseaGradientEnd = UIColor { traitCollection -> UIColor in + return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.4732026144, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.3598620686, blue: 0.2592858295, alpha: 1) + } + + // Create a plot comparing nausea to medication adherence. + let nauseaDataSeries = OCKDataSeriesConfiguration( + taskID: "nausea", + legendTitle: "Nausea", + gradientStartColor: nauseaGradientStart, + gradientEndColor: nauseaGradientEnd, + markerSize: 10, + eventAggregator: OCKEventAggregator.countOutcomeValues) + + let doxylamineDataSeries = OCKDataSeriesConfiguration( + taskID: "doxylamine", + legendTitle: "Doxylamine", + gradientStartColor: .systemGray2, + gradientEndColor: .systemGray, + markerSize: 10, + eventAggregator: OCKEventAggregator.countOutcomeValues) + + let insightsCard = OCKCartesianChartViewController(plotType: .bar, selectedDate: date, + configurations: [nauseaDataSeries, doxylamineDataSeries], + storeManager: self.storeManager) + insightsCard.chartView.headerView.titleLabel.text = "Nausea & Doxylamine Intake" + insightsCard.chartView.headerView.detailLabel.text = "This Week" + insightsCard.chartView.headerView.accessibilityLabel = "Nausea & Doxylamine Intake, This Week" + listViewController.appendViewController(insightsCard, animated: false) + + // Also create a card that displays a single event. + // The event query passed into the initializer specifies that only + // today's log entries should be displayed by this log task view controller. + let nauseaCard = OCKButtonLogTaskViewController(task: nauseaTask, eventQuery: .init(for: date), + storeManager: self.storeManager) + listViewController.appendViewController(nauseaCard, animated: false) + } + } + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/SceneDelegate.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/SceneDelegate.swift new file mode 100755 index 0000000..fb69ba8 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/SceneDelegate.swift @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import CareKit +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + + let appDelegate = UIApplication.shared.delegate as! AppDelegate + let manager = appDelegate.synchronizedStoreManager + let careViewController = UINavigationController(rootViewController: CareViewController(storeManager: manager)) + + if let windowScene = scene as? UIWindowScene { + window = UIWindow(windowScene: windowScene) + window?.rootViewController = careViewController + window?.tintColor = UIColor { $0.userInterfaceStyle == .light ? #colorLiteral(red: 0.9960784314, green: 0.3725490196, blue: 0.368627451, alpha: 1) : #colorLiteral(red: 0.8627432641, green: 0.2630574384, blue: 0.2592858295, alpha: 1) } + window?.makeKeyAndVisible() + } + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..e045665 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,196 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x-2.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-Homescreen-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x-2.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + }, + { + "size" : "24x24", + "idiom" : "watch", + "filename" : "Icon-Homescreen-24x24@2x.png", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "38mm" + }, + { + "size" : "27.5x27.5", + "idiom" : "watch", + "filename" : "Icon-Homescreen-27.5x27.5@2x.png", + "scale" : "2x", + "role" : "notificationCenter", + "subtype" : "42mm" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-Homescreen-29x29@2x.png", + "role" : "companionSettings", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "watch", + "filename" : "Icon-Homescreen-29x29@3x-1.png", + "role" : "companionSettings", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "watch", + "filename" : "Icon-Homescreen-40x40@2x.png", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "38mm" + }, + { + "size" : "44x44", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "40mm" + }, + { + "size" : "50x50", + "idiom" : "watch", + "scale" : "2x", + "role" : "appLauncher", + "subtype" : "44mm" + }, + { + "size" : "86x86", + "idiom" : "watch", + "filename" : "Icon-Homescreen-86x86@2x.png", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "38mm" + }, + { + "size" : "98x98", + "idiom" : "watch", + "filename" : "Icon-Homescreen-98x98@2x.png", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "42mm" + }, + { + "size" : "108x108", + "idiom" : "watch", + "scale" : "2x", + "role" : "quickLook", + "subtype" : "44mm" + }, + { + "idiom" : "watch-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 0000000..14728df Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 0000000..daa9bbf Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png new file mode 100755 index 0000000..1bb713d Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 0000000..1bb713d Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 0000000..c0b60da Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 0000000..d9713f4 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png new file mode 100755 index 0000000..4304be2 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-2.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-2.png new file mode 100755 index 0000000..4304be2 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-2.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 0000000..c6c7ac6 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png new file mode 100755 index 0000000..2c7e444 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-2.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-2.png new file mode 100755 index 0000000..2c7e444 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-2.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 0000000..77acdb9 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 0000000..f76308b Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 0000000..9be3e3b Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 0000000..bd3131b Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 0000000..b813b5e Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 0000000..386f055 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-24x24@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-24x24@2x.png new file mode 100755 index 0000000..8a1260e Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-24x24@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-27.5x27.5@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-27.5x27.5@2x.png new file mode 100755 index 0000000..fdfd042 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-27.5x27.5@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@2x.png new file mode 100755 index 0000000..b2b0957 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png new file mode 100755 index 0000000..043aace Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x-1.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x.png new file mode 100755 index 0000000..043aace Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-29x29@3x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-40x40@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-40x40@2x.png new file mode 100755 index 0000000..f653126 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-40x40@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-86x86@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-86x86@2x.png new file mode 100755 index 0000000..645134d Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-86x86@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png new file mode 100755 index 0000000..e0d2b55 Binary files /dev/null and b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Icon-Homescreen-98x98@2x.png differ diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/Contents.json b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Base.lproj/LaunchScreen.storyboard b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..7e84a4f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Info.plist b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Info.plist new file mode 100755 index 0000000..da6219c --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Info.plist @@ -0,0 +1,60 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + OCKSample + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.strings b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.strings new file mode 100755 index 0000000..189f9c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.strings @@ -0,0 +1,63 @@ +/* +Copyright (c) 2019, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +"ADDRESS" = "Address"; +"ANNOUNCE_EVENT_DELETED" = "Logged event was deleted"; +"CANCEL" = "Cancel"; +"CALL" = "Call"; +"COMPLETED" = "Completed"; +"CONTACTS" = "Contacts"; +"DELETE" = "Delete"; +"DONE" = "Done"; +"DOUBLE_TAP_MAP" = "Double-tap to open directions in Maps"; +"DOUBLE_TAP_TO_COMPLETE" = "Double-tap to mark as completed"; +"DOUBLE_TAP_TO_INCOMPLETE" = "Double-tap to mark as incomplete"; +"DOUBLE_TAP_TO_RECORD_EVENT" = "Double-tap to record an event"; +"DOUBLE_TAP_TO_REMOVE_EVENT" = "Double-tap to removed logged event"; +"EMAIL" = "E-mail"; +"EVENT" = "Event"; +"GOAL" = "Goal"; +"HIGH" = "High"; +"INCOMPLETE" = "Incomplete"; +"LOG" = "Log"; +"LOG_ENTRY" = "Log Entry"; +"LOGGING" = "Logging"; +"LOW" = "Low"; +"MARK_COMPLETE" = "Mark as Completed"; +"MESSAGE" = "Message"; +"NO_TASKS" = "No Tasks"; +"NO_EVENTS" = "No Events"; +"PROGRESS" = "Progress"; +"SEARCH" = "Search"; +"SELECTED" = "Selected"; +"TASKS" = "Tasks"; +"THREE_FINGER_SWIPE_DAY" = "Three-finger swipe to go to next or previous day"; +"THREE_FINGER_SWIPE_WEEK" = "Three-finger swipe to go to next or previous week"; +"TODAY" = "Today"; diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.stringsdict b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.stringsdict new file mode 100755 index 0000000..d823f17 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/Supporting Files/Localizable.stringsdict @@ -0,0 +1,30 @@ + + + + + EVENTS_REMAINING + + NSStringLocalizedFormatKey + %#@events_remaining@ + events_remaining + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + i + zero + 0 remaining + one + 1 remaining + two + + few + + many + + other + %i remaining + + + + diff --git a/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/TipView.swift b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/TipView.swift new file mode 100755 index 0000000..b88b378 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/OCKSample/OCKSample/TipView.swift @@ -0,0 +1,115 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import UIKit +import CareKit + +class TipView: OCKView, OCKCardable { + + var cardView: UIView { self } + let contentView: UIView = OCKView() + let headerView = OCKHeaderView() + let imageView = UIImageView() + var imageHeightConstraint: NSLayoutConstraint! + + private let blurView: UIVisualEffectView = { + let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.regular) + return UIVisualEffectView(effect: blurEffect) + }() + + override init() { + super.init() + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup() { + headerView.detailLabel.textColor = .secondaryLabel + + imageView.contentMode = .scaleAspectFill + imageView.clipsToBounds = true + imageView.layer.cornerRadius = layer.cornerRadius + + blurView.clipsToBounds = true + blurView.layer.cornerRadius = layer.cornerRadius + blurView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + + contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + contentView.frame = bounds + + addSubview(contentView) + contentView.addSubview(imageView) + contentView.addSubview(blurView) + contentView.addSubview(headerView) + + imageView.translatesAutoresizingMaskIntoConstraints = false + blurView.translatesAutoresizingMaskIntoConstraints = false + headerView.translatesAutoresizingMaskIntoConstraints = false + imageHeightConstraint = imageView.heightAnchor.constraint(equalToConstant: scaledImageHeight(compatibleWith: traitCollection)) + + NSLayoutConstraint.activate([ + headerView.leadingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), + headerView.trailingAnchor.constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), + headerView.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor), + + blurView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + blurView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), + blurView.topAnchor.constraint(equalTo: contentView.topAnchor), + blurView.bottomAnchor.constraint(equalTo: headerView.bottomAnchor, constant: 16), + + imageView.topAnchor.constraint(equalTo: contentView.topAnchor), + imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), + imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + imageHeightConstraint + ]) + } + + func scaledImageHeight(compatibleWith traitCollection: UITraitCollection) -> CGFloat { + return UIFontMetrics.default.scaledValue(for: 200, compatibleWith: traitCollection) + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + if previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory { + imageHeightConstraint.constant = scaledImageHeight(compatibleWith: traitCollection) + } + } + + override func styleDidChange() { + super.styleDidChange() + let cachedStyle = style() + enableCardStyling(true, style: cachedStyle) + directionalLayoutMargins = cachedStyle.dimension.directionalInsets1 + } +} diff --git a/PediatricPancreas_Storyboard/CareKit-master/Package.swift b/PediatricPancreas_Storyboard/CareKit-master/Package.swift new file mode 100755 index 0000000..8b2fb8f --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/Package.swift @@ -0,0 +1,44 @@ +// swift-tools-version:5.1 +import PackageDescription + +let package = Package( + name: "CareKit", + platforms: [.iOS(.v13), .macOS(.v10_15)], + products: [ + .library( + name: "CareKit", + targets: ["CareKit"]), + + .library( + name: "CareKitUI", + targets: ["CareKitUI"]), + + .library( + name: "CareKitStore", + targets: ["CareKitStore"]) + ], + targets: [ + .target( + name: "CareKit", + dependencies: ["CareKitUI", "CareKitStore"], + path: "CareKit/CareKit"), + + .target( + name: "CareKitUI", + path: "CareKitUI/CareKitUI"), + + .target( + name: "CareKitStore", + path: "CareKitStore/CareKitStore"), + + .testTarget( + name: "CareKitStoreTests", + dependencies: ["CareKitStore"], + path: "CareKitStore/CareKitStoreTests"), + + .testTarget( + name: "CareKitTests", + dependencies: ["CareKit"], + path: "CareKit/CareKitTests") + ] +) diff --git a/PediatricPancreas_Storyboard/CareKit-master/README.md b/PediatricPancreas_Storyboard/CareKit-master/README.md new file mode 100755 index 0000000..2180a8e --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/README.md @@ -0,0 +1,620 @@ +![CareKit](https://user-images.githubusercontent.com/29666989/60061659-cf6acb00-96aa-11e9-90a0-459b08fc020d.png) + +# CareKit + +[![License](https://img.shields.io/badge/license-BSD-green.svg?style=flat)](https://github.com/carekit-apple/CareKit#license) ![Swift](https://img.shields.io/badge/swift-5.0-brightgreen.svg) ![Xcode 11.0+](https://img.shields.io/badge/Xcode-11.0%2B-blue.svg) ![iOS 13.0+](https://img.shields.io/badge/iOS-13.0%2B-blue.svg) [![SPM](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager) + +CareKit™ is an open source software framework for creating apps that help people better understand and manage their health. The framework provides modules that can be used out of the box, or extended and customized for more targeted use cases. It is composed of three SPM packages which can each be imported separately. + +* **CareKit:** This is the best place to start building your app. CareKit provides view controllers that tie CareKitUI and CareKitStore together. The view controllers leverage Combine to provide synchronization between the store and the views. + +* **CareKitUI:** Provides the views used across the framework. The views are subclasses of UIView that are open and extensible. Properties within the views are public allowing for full control over the content. + +* **CareKitStore:** Provides a Core Data solution for storing patient data. It also provides the ability to use a custom store, such as a third party database or API. + +# Table of Contents +* [Requirements](#requirements) +* [Getting Started](#getting-started) + * [OCKCatalog App](#ockcatalog-app) + * [OCKSample App](#ocksample-app) +* [CareKit](#carekit) + * [List View Controllers](#list-view-controllers) + * [Synchronized View Controllers](#synchronized-view-controllers) + * [Custom Synchronized View Controllers](#custom-synchronized-view-controllers) + * [SwiftUI](#swiftui) +* [CareKitUI](#carekitui) + * [Tasks](#tasks) + * [Charts](#charts) + * [Contacts](#contacts) + * [Styling](#styling) +* [CareKitStore](#carekitstore) + * [Store](#store) + * [Schema](#schema) + * [Scheduling](#scheduling) + * [Custom Stores and Types](#custom-stores-and-types) +* [Integrating with ResearchKit](#integrating-with-researchkit) +* [Getting Help](#getting-help) +* [License](#license) + +# Requirements + +The primary CareKit framework codebase supports iOS and requires Xcode 11.0 or newer. The CareKit framework has a Base SDK version of 13.0. + +# Getting Started + +* [Website](https://www.researchandcare.org) +* [Documentation](https://developer.apple.com/documentation/carekit) +* [WWDC: ResearchKit and CareKit Reimagined](https://developer.apple.com/videos/play/wwdc2019/217/) + +### Installation (Option One): SPM + +CareKit can be installed via SPM. Create a new Xcode project and navigate to `File > Swift Packages > Add Package Dependency`. Enter the url `https://github.com/carekit-apple/CareKit` and tap `Next`. Choose the master branch, and on the next screen, check off the packages as needed. + +To add localized strings to your project, add the strings file to your project: [English Strings](CareKitUI/CareKitUI/Supporting%20Files/Localization/en.lproj) + +### Installation (Option Two): Embedded Framework + +Download the project source code and drag in CareKit.xcodeproj, CareKitUI.xcodeproj, and CareKistStore.xcodeproj as needed. Then, embed the framework as a dynamic framework in your app, by adding it to the Embedded Binaries section of the General pane for your target as shown in the figure below. + +embedded-framework + +### OCKCatalog App + +The included catalog app demonstrates the different modules that are available in CareKit: [OCKCatalog](OCKCatalog) + +![ockcatalog](https://user-images.githubusercontent.com/51756298/69096972-66de0b00-0a0a-11ea-96f0-4605d04ab396.gif) + + +### OCKSampleApp + +The included sample app demonstrates a fully constructed CareKit app: [OCKSample](OCKSample) + +![ocksample](https://user-images.githubusercontent.com/51756298/69107801-7586eb00-0a27-11ea-8aa2-eca687602c76.gif) + +# CareKit + +CareKit is the overarching package that provides view controllers to tie CareKitUI and CareKitStore together. When importing CareKit, CareKitUI and CareKitStore will be imported under the hood. + +### List view controllers + +CareKit offers full screen view controllers for convenience. The view controllers query for and display data from a store, and stay synchronized with the data. + +* `OCKDailyTasksPageViewController`: Displays tasks for each day with a calendar to page through dates. + +* `OCKContactsListViewController`: Displays a list of contacts in the store. + +### Synchronized View Controllers + +For each card in CareKitUI there is a corresponding view controller in CareKit. The view controllers are self contained modules that can be placed anywhere by using standard view controller containment. The view controller for each card leverages Combine to provide synchronization between the view and the store. This is done with the help of an `OCKStoreManager`, which wraps a store. When the store is modified, the store manager will publish notifications of the change. View controllers listen for this notification, and update the views accordingly. + +To create a synchronized view controller: + +```swift +// Create a store to hold your data. +let store = OCKStore(named: "my-store", type: .onDisk) + +// Create a store manager to handle synchronization. Use this to instantiate all synchronized view controllers. +let storeManager = OCKSynchronizedStoreManager(wrapping: store) + +// Create a view controller that queries for and displays data. The view will update automatically whenever the data in the store changes. +let viewController = OCKSimpleTaskViewController(taskID: "doxylamine", eventQuery: OCKEventQuery(for: Date()), storeManager: storeManager) +``` + +All synchronized view controllers have a controller and a view synchronizer. The controller is responsible for performing business logic. The view synchronizer defines how to instantiate the view to display, and how to update the view when the data in the store changes. Controllers and view synchronizers are customizable, and can be injected into a view controller to perform custom behavior: + +```swift +// Define a custom view synchronizer. +class CustomSimpleTaskViewSynchronizer: OCKSimpleTaskViewSynchronizer { + + override func makeView() -> OCKSimpleTaskView { + let view = super.makeView() + // Customize the view when it is instantiated here... + return view + } + + override func updateView(_ view: OCKSimpleTaskView, context: OCKSynchronizationContext) { + super.updateView(view, context: context) + // Update the view when the data changes in the store here... + } +} + +// Define a custom controller. +class CustomSimpleTaskController: OCKSimpleTaskController { + // Override functions here to provide custom business logic for the view controller... +} + +// Instantiate the view controller with the custom classes, then fetch and observe data in the store. +let viewController = OCKSimpleTaskViewController(controller: CustomSimpleTaskController(storeManager: storeManager), viewSynchronizer: CustomSimpleTaskViewSynchronizer()) +viewController.controller.fetchAndObserveEvents(forTaskID: "Doxylamine", eventQuery: OCKEventQuery(for: Date())) +``` + +### Custom Synchronized View Controllers + +CareKit supports creating a custom view that can be paired with a synchronized view controller to synchronize the custom view and the data in the store. In the sample code below, notice that the custom view conforms to `OCKTaskDisplayable`. This allows the view to notify the view controller when to perform certain business logic. This also means that when creating a custom view, you only need to call methods on `OCKTaskDisplayable` from the view and the view controller will automatically react: + +``` swift +// Define a custom view that displays an event for a task. +class TaskButton: UIButton, OCKTaskDisplayable { + + weak var delegate: OCKTaskViewDelegate? + + override init(frame: CGRect) { + super.init(frame: frame) + addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside) + } + + @objc + func didTap(_ sender: UIButton) { + sender.isSelected.toggle() + + // Notify the view controller to mark the event for the task as completed. + delegate?.taskView(self, didCompleteEvent: sender.isSelected, at: IndexPath(row: 0, section: 0), sender: sender) + } +} + +// Define a controller for the view to perform custom business logic. +class TaskButtonController: OCKTaskController { + + // This function gets called as a result of the delegate call in the view. + func setEvent(atIndexPath indexPath: IndexPath, isComplete: Bool, completion: ((Result) -> Void)?) { + // Perform custom behavior here... + } +} + +// Define a view synchronizer for the custom view. +class TaskButtonViewSynchronizer: OCKTaskViewSynchronizerProtocol { + + typealias View = TaskButton + + // Instantiate the custom view. + func makeView() -> TaskButton { + return TaskButton(frame: CGRect(x: 0, y: 0, width: 200, height: 60)) + } + + // Update the custom view when the data in the store changes. + func updateView(_ view: TaskButton, context: OCKSynchronizationContext) { + let event = context.viewModel?.firstEvent + view.titleLabel?.text = event?.task.title + view.isSelected = event?.outcome != nil + } +} + +// Finally, define a view controller that ties everything together. +class TaskButtonViewController: OCKTaskViewController {} + +// Instantiate the view controller with the custom classes, then fetch and observe data in the store. +let viewController = TaskButtonViewController(controller: TaskButtonController(storeManager: storeManager), viewSynchronizer: TaskButtonViewSynchronizer()) +viewController.controller.fetchAndObserveEvents(forTaskID: "Doxylamine", eventQuery: OCKEventQuery(for: Date())) +``` + +### SwiftUI + +CareKit controllers are compatible with SwiftUI, and can help take care of synchronization with the store. Start by defining a SwiftUI view: + +```swift +struct ContentView: View { + + // Observe the view model in the controller. + @ObservedObject var controller: OCKSimpleTaskController + + // Define an event for convenience. + var event: OCKAnyEvent? { + controller.objectWillChange.value?.firstEvent + } + + var body: some View { + VStack(alignment: .center, spacing: 16) { + Text(event?.task.title ?? "") + Button(action: { + let isComplete = self.event?.outcome != nil + self.controller.setEvent(atIndexPath: IndexPath(row: 0, section: 0), isComplete: !isComplete, completion: nil) + }) { + self.event?.outcome != nil ? Text("Mark as Completed") : Text("Completed") + } + } + } +} +``` + +Next, create a controller and instantiate the view: + +```swift +let controller = OCKSimpleTaskController(storeManager: manager) +controller.fetchAndObserveEvents(forTaskID: "doxylamine", eventQuery: OCKEventQuery(for: Date())) +let contentView = ContentView(controller: controller) +``` + +# CareKitUI + +CareKitUI provides cards to represent tasks, charts, and contacts. There are multiple provided styles for each category of card. + +All cards are built in a similar pattern, making it easy to recognize and customize the properties of each. They contain a `headerView` at the top that displays labels and icons. The contents of the card is placed inside a vertical `contentStackView`, allowing easy placement of custom views into a card without having to worry about breaking existing constraints. + +For creating a card from scratch, see the `OCKCardable` protocol. Conforming to this protocol allows for styling a custom card to match the styling used across the framework. + +### Tasks + +Below are the available task card styles: + +![Task](https://user-images.githubusercontent.com/51756298/69107434-32784800-0a26-11ea-8075-0a8b8b57afd2.png) + +As an example, the instructions task card can be instantiated and customized like so: + +```swift +let taskView = OCKInstructionsTaskView() + +taskView.headerView.titleLabel.text = "Doxylamine" +taskView.headerView.detailLabel.text = "7:30 AM to 8:30 AM" + +taskView.instructionsLabel.text = "Take the tablet with a full glass of water." + +taskView.completionButton.isSelected = false +taskView.completionButton.label.text = "Mark as Completed" +``` + +### Charts + +Below are the available chart card styles: + +![Chart](https://user-images.githubusercontent.com/51756298/69107429-32784800-0a26-11ea-897d-0e3885c31e73.png) + +As an example, the bar chart can be instantiated and customized like so: + +```swift +let chartView = OCKCartesianChartView(type: .bar) + +chartView.headerView.titleLabel.text = "Doxylamine" + +chartView.graphView.dataSeries = [ + OCKDataSeries(values: [0, 1, 1, 2, 3, 3, 2], title: "Doxylamine") +] +``` + +### Contacts + +Below are the available contact card styles: + +![Contact](https://user-images.githubusercontent.com/51756298/69107430-32784800-0a26-11ea-98d2-9dcd06c0ab27.png) + +As an example, the simple contact card can be instantiated and customized like so: + +```swift +let contactView = OCKSimpleContactView() + +contactView.headerView.titleLabel.text = "Lexi Torres" +contactView.headerView.detailLabel.text = "Family Practice" +``` + +### Styling + +To easily provide custom styling or branding across the framework, see the `OCKStylable` protocol. All stylable views derive their appearance from a list of injected constants. This list of constants can be customized for quick and easy styling. + +For example, to customize the separator color in a view and all of it's descendents: + +```swift +// Define your custom separator color. +struct CustomColors: OCKColorStyler { + var separator: UIColor { .black } +} + +// Define a custom struct to hold your custom color. +struct CustomStyle: OCKStyler { + var color: OCKColorStyler { CustomColors() } +} + +// Apply the custom style to your view. +let view = OCKSimpleTaskView() +view.customStyle = CustomStyle() +```` + +Note that each view in CareKitUI is by default styled with `OCKStyle`. Setting a custom style on a view will propagate the custom style down to any subviews that do not already have a custom style set. The style propagation rules can be visualized in this diagram demonstrating three separate view hierarchies: + +![Styling](https://user-images.githubusercontent.com/51756298/69107433-32784800-0a26-11ea-9622-74bb30ce4abd.png) + +# CareKitStore + +The CareKitStore package defines the `OCKStoreProtocol` that CareKit uses to talk to data stores, and a concrete implementation that leverages CoreData, called `OCKStore`. +It also contains definitions of most of the core structures and data types that CareKit relies on, such `OCKAnyTask`, `OCKTaskQuery`, and `OCKSchedule`. + +### Store + +The `OCKStore` class is an append-only, versioned store packaged with CareKit. It is implemented on top of CoreData and provides fast, secure, on-device storage. +`OCKStore` was designed to integrate with CareKit's synchronized view controllers, but can be used in isolation as well. + +```swift +import CareKitStore + +let store = OCKStore(named: "my-store", type: .onDisk) +let breakfastSchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: "Breakfast") +let task = OCKTask(id: "doxylamine", title: "Doxylamine", carePlanID: nil, schedule: breakfastSchedule) + +store.addTask(task) { result in + switch result { + case .failure(let error): print("Error: \(error)") + case .success: print("Successfully saved a new task!") + } +} +``` + +The most important feature of `OCKStore` is that it is a versioned store with a notion of time. When querying the store using a date range, the result returned will be for the +state of the store during the interval specified. + +```swift +// On January 1st +let task = OCKTask(id: "doxylamine", title: "Take 1 tablet of Doxylamine", carePlanID: nil, schedule: breakfastSchedule) +store.addTask(task) + +// On January 10th +let task = OCKTask(id: "doxylamine", title: "Take 2 tablets of Doxylamine", carePlanID: nil, schedule: breakfastSchedule) +store.updateTask(task) + +// On some future date... + +let earlyQuery = OCKTaskQuery(dateInterval: /* Jan 1st - 5th */) +store.fetchTasks(query: earlyQuery, callbackQueue: .main) { result in + let title = try! result.get().first?.title // Take 1 Tablet of Doxylamine +} + +let laterQuery = OCKTaskQuery(dateInterval: /* Jan 12th - 17th */) +store.fetchTasks(query: laterQuery, callbackQueue: .main) { result in + let title = try! result.get().first?.title // Take 2 Tablets of Doxylamine +} + +// Queries return the newest version of the task during the query interval! +let midQuery = OCKTaskQuery(dateInterval: /* Jan 5th - 15th */) +store.fetchTasks(query: laterQuery, callbackQueue: .main) { result in + let title = try! result.get().first?.title // Take 2 Tablets of Doxylamine +} +``` + +### Schema + +CareKitStore defines six high level entities as illustrated in this diagram: + +![Schema](https://user-images.githubusercontent.com/51756298/69107431-32784800-0a26-11ea-83fc-8987d7ef2e15.png) + +* **Patient:** A patient represents the user of the app. + +* **Care Plan**: A patient may have zero or more care plans. A care plan organizes the contacts and tasks associated with a specific treatment. For example, a patient may have one care plan for heart disease and a second for obesity. + +* **Contact:** A care plan may have zero or more associated contacts. Contacts might include doctors, nurses, insurance providers, or family. + +* **Task:** A care plan may have zero or more tasks. A task represents some activity that the patient is supposed to perform. Examples may include taking a medication, exercising, journaling, or checking in with their doctor. + +* **Schedule:** Each task must have a schedule. The schedule defines occurrences of a task, and may optionally specify target or goal values, such as how much of a medication to take. + +* **Outcome:** Each occurrence of a task may or may not have an associated outcome. The absence of an outcome indicates no progress was made on that occurrence of the task. + +* **Outcome Value:** Each outcome may have zero or more values associated with it. A value might represent how much medication was taken, or a plurality of outcome values could represent the answers to a survey. + +It is important to note that tasks, contacts, and care plans can exist *without* a parent entity. Many CareKit apps are targeted to well defined use cases, and it can often be expedient to simply create tasks and contacts without defining a patient or care plan. + +### Scheduling + +The scheduling tools provided in CareKit allow very precise and customizable scheduling of tasks. Each instance of an `OCKSchedule` is created by composing one or more +`OCKScheduleElements`, which each define a single repeating interval. + +Static convenience methods exist to help with common use cases. + +```swift +let breakfastSchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: Date(), end: nil, text: "Breakfast") +let everySaturdayAtNoon = OCKSchedule.weeklyAtTime(weekday: 7, hours: 12, minutes: 0, start: Date(), end: nil) +``` + +Highly precise, complicated schedules can be created by combining schedule elements or other schedules. + +```swift +// Combining elements to create a complex schedule +let elementA = OCKScheduleElement(start: today, end: nextWeek, interval: DateComponents(hour: 36)) +let elementB = OCKScheduleElement(start: lastWeek, end: nil, interval: DateComponents(day: 2)) +let complexSchedule = OCKSchedule(composing: [elementA, elementB]) + +// Combing two schedules into a composed schedule +let dailySchedule = OCKSchedule.dailyAtTime(hour: 8, minutes: 0, start: tomorrow, end: nextYear, text: nil) +let crazySchedule = OCKSchedule(composing: [dailySchedule, complexSchedule]) +``` + +Schedules have a number of other useful properties that can be set, including target values, durations, and textual descriptions. + +```swift +let element = OCKScheduleElement( + start: today, // The date and time this schedule will begin + end: nextYear, // The date and time this schedule will end + interval: DateComponents(day: 3), // Occurs every 3 days + text: "Before bed", // "Before bed" will be show instead of clock time + targetValues: [OCKOutcomeValue(10, units: "mL")], // Specifies what counts as "complete" + duration: Duration = .hours(2) // The window of time to complete the task +) +``` + +* `text`: By default, CareKit view controllers will prompt users to perform tasks using clock time (e.g. "8:00PM"). If you provide a `text` property, then the text will be used to prompt the user instead ("Before bed"). + +* `duration`: If you provide a duration, CareKit will prompt the user to perform the scheduled task within a window (e.g. "8:00 - 10:00 PM"). The duration can also be set to `.allDay` if you do not wish to specify any time in particular. + +* `targetValues`: Target values are used by CareKit to determine if a user has completed a specific task or not. See `OCKAdherenceAggregator` for more details. + + +### Custom Stores and Types + +The `OCKStore` class provided with CareKit is a fast, secure, on-device store and will serve most use cases well. That said, we recognize it may not fully meet the needs of +all our developers, so CareKit also allows you to write your own store. For example, you could write a wrapper around a web server, or even a simple JSON file. Any class that +conforms to the `OCKStoreProtocol` can be used in place of the default store. + +Writing a CareKit store adapter requires defining the entities that will live in your store and implementing asynchronous **Create**, **Read**, **Update**, and **Delete** methods for each. +Stores are free to define their own types, as long as those types conform to a certain protocol. For example, if you are writing a store that can hold tasks, you might do it like this. + +```swift +import CareKitStore + +struct MyTask: OCKAnyTask & Equatable & Identifiable { + + // MARK: OCKAnyTask + let id: String + let title: String + let schedule: String + /* ... */ + + // MARK: Custom Properties + let difficulty: DifficultyRating + /* ... */ +} + +struct MyTaskQuery: OCKAnyTaskQuery { + + // MARK: OCKAnyTaskQuery + let ids: [String] + let carePlanIDs: [String] + /* ... */ + + // MARK: Custom Properties + let difficult: DifficultyRating? +} + +class MyStore: OCKStoreProtocol { + + typealias Task = MyTask + typealias TaskQuery = MyTaskQuery + /* ... */ + + // MARK: Task CRUD Methods + func fetchTasks(query: TaskQuery, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure<[Task]>) { /* ... */ } + func addTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ } + func updateTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ } + func deleteTasks(_ tasks: [Task], callbackQueue: DispatchQueue, completion: OCKResultClosure<[Task]>?) { /* ... */ } + + /* ... */ +} +``` + +Using the four basic CRUD methods you supply, CareKit is able to use protocol extensions to imbue your store with extra functionality. For example, a store that implements +the four CRUD methods for tasks automatically receives the following methods. + +```swift +func fetchTask(withID id: String, callbackQueue: DispatchQueue, completion: @escaping OCKResultClosure) +func addTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +func updateTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +func deleteTask(_ task: Task, callbackQueue: DispatchQueue, completion: OCKResultClosure?) +``` + +Methods provided via protocol extensions employ naive implementations. As the developer, you are free to provide your own implementations that leverage the capabilities of +your underlying data store to achieve greater performance or efficiency. + +If you are considering implementing your own store, read over the protocol notes and documentation carefully. + +# Integrating with ResearchKit + +CareKit and ResearchKit are sister frameworks and are designed to integrate well with one another. + +When integrating a ResearchKit into your CareKit app, there are a series of steps you will need to follow. + +1. Subclass an existing task view controller +2. Override the method that is called when the task is completed +3. Present a ResearchKit survey and wait for the user to complete it +4. Get the survey result and save it to CareKit's store + +Here is an example demonstrating how to prompt the user to rate their pain on a scale of 1-10. +Keep in mind as you're reading the code below that CareKit and ResearchKit both use the term "task", but that they are distinct. + + +```swift +// 1. Subclass a task view controller to customize the control flow and present a ResearchKit survey! +class SurveyViewController: OCKInstructionsTaskViewController, ORKTaskViewControllerDelegate { + + // 2. This method is called when the use taps the button! + override func taskView(_ taskView: UIView & OCKTaskDisplayable, didCompleteEvent isComplete: Bool, at indexPath: IndexPath, sender: Any?) { + + // 2a. If the task was marked incomplete, fall back on the super class's default behavior or deleting the outcome. + if !isComplete { + super.taskView(taskView, didCompleteEvent: isComplete, at: indexPath, sender: sender) + return + } + + // 2b. If the user attempted to mark the task complete, display a ResearchKit survey. + let answerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: 5, step: 1, vertical: false, + maximumValueDescription: "Very painful", minimumValueDescription: "No pain") + let painStep = ORKQuestionStep(identifier: "pain", title: "Pain Survey", question: "Rate your pain", answer: answerFormat) + let surveyTask = ORKOrderedTask(identifier: "survey", steps: [painStep]) + let surveyViewController = ORKTaskViewController(task: surveyTask, taskRun: nil) + surveyViewController.delegate = self + + // 3a. Present the survey to the user + present(surveyViewController, animated: true, completion: nil) + } + + // 3b. This method will be called when the user completes the survey. + func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + taskViewController.dismiss(animated: true, completion: nil) + guard reason == .completed else { + taskView.completionButton.isSelected = false + return + } + + // 4a. Retrieve the result from the ResearchKit survey + let survey = taskViewController.result.results!.first(where: { $0.identifier == "pain" }) as! ORKStepResult + let painResult = survey.results!.first as! ORKScaleQuestionResult + let answer = Int(truncating: painResult.scaleAnswer!) + + // 4b. Save the result into CareKit's store + controller.appendOutcomeValue(withType: answer, at: IndexPath(item: 0, section: 0), completion: nil) + } +} +``` + +Once you have defined this view controller, you can add it into your app as you would any other CareKit view controller! + +```swift +let todaysSurveyCard = SurveyViewController( + taskID: "survey", + eventQuery: OCKEventQuery(for: Date()), + storeManager: storeManager) + +present(surveyCard, animated: true, completion: nil) +``` + +You may also decide that you want the view to update to display the result of your survey instead of the default values used by the superclass. To change that, you can implement your own view synchronizer. + +```swift +class SurveyViewSynchronizer: OCKInstructionsTaskViewSynchronizer { + + // Customize the initial state of the view + override func makeView() -> OCKInstructionsTaskView { + let instructionsView = super.makeView() + instructionsView.completionButton.label.text = "Start Survey" + return instructionsView + } + + // Customize how the view updates + override func updateView(_ view: OCKInstructionsTaskView, + context: OCKSynchronizationContext) { + super.updateView(view, context: context) + + // Check if an answer exists or not and set the detail label accordingly + if let answer = context.viewModel?.firstEvent?.outcome?.values.first?.integerValue { + view.headerView.detailLabel.text = "Pain Rating: \(answer)" + } else { + view.headerView.detailLabel.text = "Rate your pain on a scale of 1 to 10" + } + } +} +``` + +Now, when you create an instance of your `SurveyViewController`, you can pass in your custom view synchronizer to change how the view updates. + +```swift +let surveyCard = SurveyViewController( + viewSynchronizer: SurveyViewSynchronizer(), + taskID: "survey", + eventQuery: OCKEventQuery(date: Date()), + storeManager: storeManager) + +present(surveyCard, animated: true, completion: nil) +``` + +# Getting Help + +GitHub is our primary forum for CareKit. Feel free to open up issues about questions, problems, or ideas. + +# License + +This project is made available under the terms of a BSD license. See the [LICENSE](LICENSE) file. + diff --git a/PediatricPancreas_Storyboard/CareKit-master/RELEASE-NOTES.md b/PediatricPancreas_Storyboard/CareKit-master/RELEASE-NOTES.md new file mode 100755 index 0000000..759b5b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/CareKit-master/RELEASE-NOTES.md @@ -0,0 +1,212 @@ +# CareKit Release Notes + +## CareKit 2.0 Release Notes + +*CareKit 2.0* supports *iOS* and requires *Xcode 11.0* or later. The minimum supported *Base SDK* is *13.0*. +*CareKit 2.0* includes the following new features and enhancements by Apple Inc. (https://github.com/carekit-apple) + +- **New Architecture** + +CareKit 2.0 has been rewritten from the ground up entirely in Swift 5. The new architecture has been reconstructed to allow for maximum customization and modularity. Splitting the framework out into various layers now enables users to tailor-make their care apps to the desired look and feel for their users. + +- **CareKitUI** + +Now a whole new separate project inside the CareKit repository, CareKitUI can be compiled and imported as a stand-alone framework without any dependencies on CareKit or the CareKitStore. CareKitUI consists of prepackaged views that developers can easily embed anywhere within their apps and populate it with personalized content. + +- **CareKitStore** + +Just like CareKitUI, the CareKitStore too can be imported in as a stand-alone framework without any dependencies. Built as a wrapper on top of CoreData, the CareKitStore offers an on-device datastore that is exclusive to your app. It comes with a predefined schema that facilitates persistence of Care Plans and associated Tasks. Developers can choose to update and modify the schema depending on their individual use cases. + +- **CareKit** + +CareKit, the framework, imports CareKitUI and CareKitStore under the hood. CareKit is all about providing complete synchronization between the UI and the underlying database and this synchronization is powered by the all new Combine feature available in Swift 5. Another key highlight of CareKit is its modularity. This modularity gives developers the freedom to utilize the CareKitStore or plug-in their own custom store that conforms to the OCKStore protocol in order to leverage the synchronization functionality for free. Additionally, developers can now use custom views or inject custom views that conform to our protocols to get the synchronization functionality at no cost. + +- **Tasks** + +The two entities previously know as Assessments and Interventions have been collapsed into a single Task entity. Tasks can be displayed in cards using any of a number of styles. Task card styles exist for a number of common use cases, simple tasks that only need to be performed once, tasks that should be performed several times, and tasks that can be performed any number of times. + +- **Charts** + +CareKit offers views and view controllers that display charts. The views can be styled and filled with custom data, and support multiple data series. The view controllers fetch and display data in the view, and update the view when the data changes. CareKit currently supports line, scatter, and bar charts. + +- **Contacts** + +CareKit offers views and view controllers that display contacts. The views can be styled and filled with custom data. The view controllers fetch and display data in the view, and update the view when the data changes. CareKit currently supports a simple and detailed contact view. + +- **List View Controllers** + +CareKit provides higher order view controllers that easily fetch and display data in a store. The first is a view controller that displays tasks and completion for a given day in the week. The second is a list of contacts. + +- **Styling** + +All CareKit views can be easily styled for a custom user interface by injecting a list of style constants. Views inherit the style of their parent, making it easy to quickly style or brand an app. + +- **Updated Database Schema** + +The database schema has been updated to handle new care-centric data types. The store now models Patients, Care Plans, Contacts, Tasks, Schedules, Outcomes, Outcome Values, and Notes. The store has been reinvented as an append only versioned database, and now allows you to keep a fully versioned history of key records. + +- **Scheduling** + +Task scheduling has been greatly improved in CareKit 2.0. It is now possible to create arbitrarily complex and precise schedules. + +- **Sample App** + +The Sample App (OCKSample project in CareKit's workspace) serves as a template application that combines different modules from the CareKit framework. It's a great starting point for your own CareKit apps. + +- **Catalog App** + +The Catalog App (OCKCatalog project in CareKit's workspace) showcases the views and controllers available in CareKit. It's an excellent reference for the visual building blocks available in CareKit, and is useful for designers and engineers who want to know what building blocks are available to them. + + +## CareKit 1.2 Release Notes + +*CareKit 1.2* supports *iOS* and requires *Xcode 8.0* or later. The minimum supported *Base SDK* is *9.0*. +*CareKit 1.2* includes the following new features and enhancements *by [Apple Inc.](https://github.com/carekit-apple)* + +- **Care Contents Card** + + The *Sample App* (OCKSample project in CareKit's workspace) now includes a Care Contents view controller, which allows for activities and interventions to be seen in the same place. You may still choose to use the *Care Card *and *Symptom Tracker* view controllers independently to separate out care “to-do’s” and measurement tracking if desired. + +- **Optional Activities** + + Intervention and assessment activity types can now be tagged as “optional”. Completion of optional activities do not contribute to a user’s daily completion goals, and are well suited for “take as needed” care activities – such as pain medications or optional physical activities. + +- **Read Only Activity Type** + + You can now create a new class of activity called “read only” by utilizing the ReadOnly initializer. Read only activities can be used to display information which do not require any action from the user. Examples can include day-of-surgery dietary instructions, or tricks and tips that might be interesting to share throughout a user’s care journey. + +- **Updated Header View and 28 Glyph Icons** + + The header view across *Care Card, Symptom Tracker and the New Care Contents* has been updated to display a daily ring view with customizable glyphs inside to represent completion of care activities. The Apple team has designed 28 icons that can be used within the ring view, and are compatible as Apple Watch complications. Once a user reaches 100%, the ring will fill in and a star badge will appear to easily identify days of full compliance. + +- **Updated Insights Tab with Thresholds** + + The *Insights* view controller has been updated to include the ability to display thresholds. You can now set thresholds in your assessment or intervention activities, and display alert UI and tint colors on the *Insights* view controller if thresholds are broken. + +- **Inbox Feature in Connect** + + We’ve updated the *Inbox* view controller to include UI for messaging between consumers and care teams, friends, and family members. Developers can choose to include this functionality in use cases where asynchronous messaging might play a crucial role in a consumer’s care journey. + +- **Cloud Bridge API** + + We’re making data sharing between CareKit apps even easier with the new addition of our Cloud Bridge API. The bridge API is an Abstract cloud API that conforms to the CareKit schema and enables data syncing without any additional configuration. It’s designed to allow CareKit based apps to seamlessly integrate with backend cloud solutions, and is based upon the current CareKit data model and architecture +The bridge API provides all of the necessary hooks through delegate functions for cloud bridge’s to seamlessly hook into the CareKit framework, allowing developers or current cloud providers to conform to the CareKit schema with reduced effort and create backend solutions that fit directly into the current framework architecture. + + +## CareKit 1.1 Release Notes + +*CareKit 1.1* supports *iOS* and requires *Xcode 8.0* or later. The minimum supported *Base SDK* is *9.0*. + +*CareKit 1.1* includes the following new features and enhancements. + +- **Care Card on Apple Watch** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Sample App* (OCKSample project in CareKit's workspace) now includes a watch app. The app works out of the box. Included in the Watch group is the *Watch Connectivity Manager* which abstracts the logic of communicating the *Care Card* data between the phone and the watch. + + The *Care Plan Store* has also been updated to support Apple Watch. + +- **New Test App** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *New Test App* is written entirely in Swift and provides extensive coverage for all CareKit Modules. + +- **Other Improvements** + + - **3D Touch Support** + + *Contributed by [Troy Tsubota](https://github.com/tktsubota).* + + The *Care Card* and *Connect* view controllers have been updated to support 3D Touch. In the *Care Card* view controller, a user can 3D Touch on an activity to peek and pop. In the *Connect* view controller, a user can peek, pop, and use perform actions right from the master screen. + + - **FaceTime in Connect** + + *Contributed by [Micah Hainline](https://github.com/micahhainline).* + + *FaceTime* calls can now be made from within the Connect module. Apart from *FaceTime* support, *Connect* now has the ability to create any custom method of communication (such as fax). + + +## CareKit 1.0 Release Notes + +*CareKit 1.0* supports *iOS* and requires *Xcode 6.3* or later. The minimum supported *Base SDK* is *9.0*. + +*CareKit 1.0* includes the following new features and enhancements. + +- **Care Plan Store** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + CareKit stores activities in a database called the *Care Plan Store*. This database is located at the URL provided by + the developer. The *Care Plan Store* is encrypted using standard file-system encryption. + + The *Care Plan Store* can store intervention and assessment activities. Each activity has a schedule that the *Care Plan Store* uses + to create event objects. The store can be dynamically updated and modified. + +- **Care Card** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + *Care Card* is a view controller that displays the intervention activities for a selected date. It provides a way to track activity + completion and user adherence. + + A developer can modify the *Care Plan Store* by adding, removing, or modifying an activity and the *Care Card* responds by automatically + updating the user interface. + + The mask image on the Care Card can be customized to provide a themed user experience. + +- **Symptom and Measurement Tracker** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + *Symptom and Measurement Tracker* is a view controller that displays the assessment activities for a selected date. It provides a way to monitor + subjective and objective measurements. + + A developer can modify the *Care Plan Store* by adding, removing, or modifying an activity and the *Symptom and Measurement Tracker* responds by + automatically updating the user interface. + +- **Insights Dashboard** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Insights Dashboard* is a view controller that displays message items, such as an alert or tip, and charts, such as the grouped + bar chart. + + A developer can subclass the OCKInsightItem and OCKChart classes to create new message items and charts. + +- **Grouped Bar Chart** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Grouped Bar Chart* displays a series of data grouped into categories. The chart can be used with the *Insights Dashboard* using the + *OCKBarChart* object, or it can be used directly using *OCKGroupedBarChartView*. + +- **Connect** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + *Connect* is a view controller that displays contact information for care team members, friends, and family. *Connect* supports + communicating with contacts through email, messaging, and phone. It also supports a user interface for sending reports that you + can create using the Document Exporter module + +- **Document Exporter** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Document Exporter* module supports creating an HTML or PDF document. Although you can provide any data you’d like, the intent is + to export data from the Care Plan Store. The exporter can display text, charts, images, and tables. + +- **Sample App** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Sample App* (OCKSample project in CareKit's workspace) serves as a template application that combines different modules + from the CareKit framework. It also shows how to use ResearchKit surveys and active tasks with CareKit. + +- **Test App** + + *Contributed by [Apple Inc.](https://github.com/carekit-apple).* + + The *Test App* (OCKTest project in CareKit's workspace) serves as an application to test different modules and features from + the CareKit framework. diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.pbxproj new file mode 100644 index 0000000..701a9dd --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.pbxproj @@ -0,0 +1,463 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 4A2D64E7240BDCAA0018BD41 /* InnerResourceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A2D64E6240BDCAA0018BD41 /* InnerResourceView.swift */; }; + 4AD625AC240672720003E88A /* ResourceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD625A9240672720003E88A /* ResourceCell.swift */; }; + 4AD625AD240672720003E88A /* MainResourceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD625AA240672720003E88A /* MainResourceView.swift */; }; + 4AD625AE240672720003E88A /* Resource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD625AB240672720003E88A /* Resource.swift */; }; + 4AD625B124067D460003E88A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4AD625AF24067D460003E88A /* Main.storyboard */; }; + 759E145D23FE0832001A2E7A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759E145C23FE0832001A2E7A /* AppDelegate.swift */; }; + 759E145F23FE0832001A2E7A /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759E145E23FE0832001A2E7A /* SceneDelegate.swift */; }; + 759E146123FE0832001A2E7A /* PDFViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759E146023FE0832001A2E7A /* PDFViewController.swift */; }; + 759E146623FE0833001A2E7A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 759E146523FE0833001A2E7A /* Assets.xcassets */; }; + 759E146923FE0834001A2E7A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 759E146723FE0834001A2E7A /* LaunchScreen.storyboard */; }; + 7BB1AAC723FE1BEE009FD83C /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7BB1AAC623FE1BEE009FD83C /* GoogleService-Info.plist */; }; + 7BE203F4240BB1EE00DF1A45 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE203F3240BB1EE00DF1A45 /* Utils.swift */; }; + C3FB0DA9240686B3006D0EB3 /* Folder.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3FB0DA6240686B3006D0EB3 /* Folder.swift */; }; + C3FB0DAB240686B3006D0EB3 /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3FB0DA8240686B3006D0EB3 /* File.swift */; }; + C3FB0DC3240C54BA006D0EB3 /* ResultsTableController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3FB0DC2240C54BA006D0EB3 /* ResultsTableController.swift */; }; + EBEE648A4B99E88BDBEE7BE3 /* Pods_PediatricPancreas_Storyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 223A3D0F2FAB24511D190436 /* Pods_PediatricPancreas_Storyboard.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 759E149A23FE08C9001A2E7A /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 223A3D0F2FAB24511D190436 /* Pods_PediatricPancreas_Storyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PediatricPancreas_Storyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4A2D64E6240BDCAA0018BD41 /* InnerResourceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InnerResourceView.swift; sourceTree = ""; }; + 4AD625A9240672720003E88A /* ResourceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResourceCell.swift; sourceTree = ""; }; + 4AD625AA240672720003E88A /* MainResourceView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainResourceView.swift; sourceTree = ""; }; + 4AD625AB240672720003E88A /* Resource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Resource.swift; sourceTree = ""; }; + 4AD625B024067D460003E88A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 759E145923FE0832001A2E7A /* PediatricPancreas_Storyboard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PediatricPancreas_Storyboard.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 759E145C23FE0832001A2E7A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 759E145E23FE0832001A2E7A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 759E146023FE0832001A2E7A /* PDFViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PDFViewController.swift; sourceTree = ""; }; + 759E146523FE0833001A2E7A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 759E146823FE0834001A2E7A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 759E146A23FE0834001A2E7A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 7BB1AAC623FE1BEE009FD83C /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 7BE203F3240BB1EE00DF1A45 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; + A6F5CA667EF6199DC8282977 /* Pods-PediatricPancreas_Storyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas_Storyboard.release.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.release.xcconfig"; sourceTree = ""; }; + BA0BC2D07EC9CF4FE884FD9E /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PediatricPancreas_Storyboard.debug.xcconfig"; path = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.debug.xcconfig"; sourceTree = ""; }; + C3FB0DA6240686B3006D0EB3 /* Folder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Folder.swift; sourceTree = ""; }; + C3FB0DA8240686B3006D0EB3 /* File.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = ""; }; + C3FB0DC2240C54BA006D0EB3 /* ResultsTableController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsTableController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 759E145623FE0832001A2E7A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + EBEE648A4B99E88BDBEE7BE3 /* Pods_PediatricPancreas_Storyboard.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2906BE01BEBD5CE1999E5BF5 /* Pods */ = { + isa = PBXGroup; + children = ( + BA0BC2D07EC9CF4FE884FD9E /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */, + A6F5CA667EF6199DC8282977 /* Pods-PediatricPancreas_Storyboard.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 759E145023FE0832001A2E7A = { + isa = PBXGroup; + children = ( + 759E145B23FE0832001A2E7A /* PediatricPancreas_Storyboard */, + 759E145A23FE0832001A2E7A /* Products */, + 759E149723FE08C9001A2E7A /* Frameworks */, + 2906BE01BEBD5CE1999E5BF5 /* Pods */, + ); + sourceTree = ""; + }; + 759E145A23FE0832001A2E7A /* Products */ = { + isa = PBXGroup; + children = ( + 759E145923FE0832001A2E7A /* PediatricPancreas_Storyboard.app */, + ); + name = Products; + sourceTree = ""; + }; + 759E145B23FE0832001A2E7A /* PediatricPancreas_Storyboard */ = { + isa = PBXGroup; + children = ( + 759E146523FE0833001A2E7A /* Assets.xcassets */, + 4AD625AB240672720003E88A /* Resource.swift */, + C3FB0DA6240686B3006D0EB3 /* Folder.swift */, + C3FB0DA8240686B3006D0EB3 /* File.swift */, + 4AD625A9240672720003E88A /* ResourceCell.swift */, + 4AD625AA240672720003E88A /* MainResourceView.swift */, + 4A2D64E6240BDCAA0018BD41 /* InnerResourceView.swift */, + 759E146023FE0832001A2E7A /* PDFViewController.swift */, + C3FB0DC2240C54BA006D0EB3 /* ResultsTableController.swift */, + 4AD625AF24067D460003E88A /* Main.storyboard */, + 759E146723FE0834001A2E7A /* LaunchScreen.storyboard */, + 759E145C23FE0832001A2E7A /* AppDelegate.swift */, + 759E145E23FE0832001A2E7A /* SceneDelegate.swift */, + 7BE203F3240BB1EE00DF1A45 /* Utils.swift */, + 759E146A23FE0834001A2E7A /* Info.plist */, + 7BB1AAC623FE1BEE009FD83C /* GoogleService-Info.plist */, + ); + path = PediatricPancreas_Storyboard; + sourceTree = ""; + }; + 759E149723FE08C9001A2E7A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 223A3D0F2FAB24511D190436 /* Pods_PediatricPancreas_Storyboard.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 759E145823FE0832001A2E7A /* PediatricPancreas_Storyboard */ = { + isa = PBXNativeTarget; + buildConfigurationList = 759E146D23FE0834001A2E7A /* Build configuration list for PBXNativeTarget "PediatricPancreas_Storyboard" */; + buildPhases = ( + 73ECC5DA37AE6D401D82BE9B /* [CP] Check Pods Manifest.lock */, + 759E145523FE0832001A2E7A /* Sources */, + 759E145623FE0832001A2E7A /* Frameworks */, + 759E145723FE0832001A2E7A /* Resources */, + 759E149A23FE08C9001A2E7A /* Embed Frameworks */, + 4DB37C3DAA31609D82F7A3C4 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PediatricPancreas_Storyboard; + productName = PediatricPancreas_Storyboard; + productReference = 759E145923FE0832001A2E7A /* PediatricPancreas_Storyboard.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 759E145123FE0832001A2E7A /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = "Example Company"; + TargetAttributes = { + 759E145823FE0832001A2E7A = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 759E145423FE0832001A2E7A /* Build configuration list for PBXProject "PediatricPancreas_Storyboard" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 759E145023FE0832001A2E7A; + productRefGroup = 759E145A23FE0832001A2E7A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 759E145823FE0832001A2E7A /* PediatricPancreas_Storyboard */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 759E145723FE0832001A2E7A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 759E146923FE0834001A2E7A /* LaunchScreen.storyboard in Resources */, + 759E146623FE0833001A2E7A /* Assets.xcassets in Resources */, + 7BB1AAC723FE1BEE009FD83C /* GoogleService-Info.plist in Resources */, + 4AD625B124067D460003E88A /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 4DB37C3DAA31609D82F7A3C4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 73ECC5DA37AE6D401D82BE9B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PediatricPancreas_Storyboard-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 759E145523FE0832001A2E7A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4A2D64E7240BDCAA0018BD41 /* InnerResourceView.swift in Sources */, + 759E146123FE0832001A2E7A /* PDFViewController.swift in Sources */, + C3FB0DAB240686B3006D0EB3 /* File.swift in Sources */, + C3FB0DC3240C54BA006D0EB3 /* ResultsTableController.swift in Sources */, + 4AD625AC240672720003E88A /* ResourceCell.swift in Sources */, + C3FB0DA9240686B3006D0EB3 /* Folder.swift in Sources */, + 7BE203F4240BB1EE00DF1A45 /* Utils.swift in Sources */, + 759E145D23FE0832001A2E7A /* AppDelegate.swift in Sources */, + 4AD625AE240672720003E88A /* Resource.swift in Sources */, + 4AD625AD240672720003E88A /* MainResourceView.swift in Sources */, + 759E145F23FE0832001A2E7A /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 4AD625AF24067D460003E88A /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 4AD625B024067D460003E88A /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 759E146723FE0834001A2E7A /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 759E146823FE0834001A2E7A /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 759E146B23FE0834001A2E7A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 759E146C23FE0834001A2E7A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 759E146E23FE0834001A2E7A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BA0BC2D07EC9CF4FE884FD9E /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CGA8BZRPF2; + INFOPLIST_FILE = PediatricPancreas_Storyboard/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.iHackHealth.PediatricPancreasStoryboard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 759E146F23FE0834001A2E7A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A6F5CA667EF6199DC8282977 /* Pods-PediatricPancreas_Storyboard.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = CGA8BZRPF2; + INFOPLIST_FILE = PediatricPancreas_Storyboard/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.iHackHealth.PediatricPancreasStoryboard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 759E145423FE0832001A2E7A /* Build configuration list for PBXProject "PediatricPancreas_Storyboard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 759E146B23FE0834001A2E7A /* Debug */, + 759E146C23FE0834001A2E7A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 759E146D23FE0834001A2E7A /* Build configuration list for PBXNativeTarget "PediatricPancreas_Storyboard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 759E146E23FE0834001A2E7A /* Debug */, + 759E146F23FE0834001A2E7A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 759E145123FE0832001A2E7A /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..83b35cf --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ebfe6d1 Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..f13a1b1 Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..0d11ba5 Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/project.xcworkspace/xcuserdata/reetmishra.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..e415c1c --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..0fbf1c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/administrator.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas_Storyboard.xcscheme_^#shared#^_ + + orderHint + 19 + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..0fbf1c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas_Storyboard.xcscheme_^#shared#^_ + + orderHint + 19 + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..0fbf1c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/koreanmelon.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas_Storyboard.xcscheme_^#shared#^_ + + orderHint + 19 + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/reetmishra.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/reetmishra.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ce67264 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcodeproj/xcuserdata/reetmishra.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + PediatricPancreas_Storyboard.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..0db3600 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..6b1e5d4 Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..7d45415 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Expressions.xcexplist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Expressions.xcexplist new file mode 100644 index 0000000..dd6da95 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/administrator.xcuserdatad/xcdebugger/Expressions.xcexplist @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..7c2fffa Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/jeffery.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..bc95852 Binary files /dev/null and b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard.xcworkspace/xcuserdata/koreanmelon.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/AppDelegate.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/AppDelegate.swift new file mode 100644 index 0000000..a8d6f03 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/AppDelegate.swift @@ -0,0 +1,43 @@ +// +// AppDelegate.swift +// PediatricPancreas_Storyboard +// +// Created by Reet Mishra on 2/19/20. +// Copyright © 2020 Example Company. All rights reserved. +// + +import UIKit +import Firebase + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + FirebaseApp.configure() + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + + + + + +} + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/Contents.json b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/LaunchScreen.storyboard b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/Main.storyboard b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/Main.storyboard new file mode 100644 index 0000000..7d1030e --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Base.lproj/Main.storyboard @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/File.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/File.swift new file mode 100644 index 0000000..944a771 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/File.swift @@ -0,0 +1,46 @@ +// +// Files.swift +// database +// +// Created by Administrator on 2/21/20. +// Copyright © 2020 JenniferZhou. All rights reserved. +// + +import Foundation + +class File: Resource { + static var allFiles: [File] = [] + + private var _name: String + private var _path: String + internal var _tags: [String] = [] + //insert variables associated with files here + + init() { + _name = ""; + _path = ""; + } + + init(name: String, path: String) { + _name = name + _path = path + File.allFiles.append(self) + } + + func getName() -> String { + return _name + } + + func getPath() -> String { + return _path + } + + func fetch() { + //gets : the file somehow + } +} + +enum fileError: +Error { + case nonexistentFile(message: String) +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Folder.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Folder.swift new file mode 100644 index 0000000..ed7d094 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Folder.swift @@ -0,0 +1,144 @@ +// +// main.swift +// database +// +// Created by jenny B) on 2/20/20. +// Copyright © 2020 JenniferZhou. All rights reserved. + +import Foundation + +class Folder: Resource { + static var allFolders: [Folder] = [] + + private var _name: String + private var _prev: Folder? + private var _subfolders: [Folder] = [] + private var _files: [File] = [] + internal var _tags: [String] = [] //listed in order of importance + + init() { + self._name = "" + self._subfolders = [] + self._tags = [] + self._files = [] + } + + /** Initializes a folder with name, list of subfolders, and tags. + Add this folder to the list of all folders. + Places self in the subfolders of other folders if needed. */ + init(name: String, subfolders: [Folder], files: [File], tags: [String], + parents: [String]) { + self._name = name + self._subfolders = subfolders + self._tags = tags + self._files = files + + Folder.allFolders.append(self) + + for parent in parents { + for folder in Folder.allFolders { + if parent == folder.getName() { + folder.addChild(child: self) + } + } + } + } + + /** Returns the name of the folder. */ + func getName() -> String { + return self._name + } + +// /** Returns index of specified tag, or -1 if tag does not exist. */ +// func hasTag(tag: String) -> Int { +// for index in 0.. Folder { + if _prev != nil { + return self._prev! + } + else { + throw folderError.nonexistentFolder(message: "There is no prevous folder. Stop.") + } + } + + /** Adds a folder to list of subfolders. */ + func addChild(child: Folder) { + self._subfolders.append(child) + } + + /** Removes specified folder from subfolders; returns 1 if successful, 0 if child was not found. */ + func removeChild(child: Folder) -> Int { + for index in 0.. Folder { + for folder in self._subfolders { + if folder.getName() == folderName { + folder.setPrev(previous: self) + return folder + } + } + throw folderError.nonexistentFolder(message: "There is no subfolder with this name. Stop.") + } + + /** + Returns all subfolders of this folder. + */ + func getSubfolders() -> [Folder] { + return self._subfolders + } + + + /** + Adds a file FILE to this folder. + */ + func addFile(file: File) { + _files.append(file) + } + + /** + Returns a file with FILENAME that is within this folder. + */ + func getFile(fileName: String) throws -> File { + for file in _files { + if file.getName() == fileName { + return file + } + } + throw fileError.nonexistentFile(message: "No such file exists. Stop.") + } + + /** + Returns all files within a folder. + */ + func getFiles() -> [File] { + return self._files + } + +} + +enum folderError: +Error { + case nonexistentFolder(message: String) +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/GoogleService-Info.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/GoogleService-Info.plist new file mode 100644 index 0000000..d584e47 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 158315296857-9mt2mbvk4qnqjnr0c8p95qvadlmf1lti.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.158315296857-9mt2mbvk4qnqjnr0c8p95qvadlmf1lti + API_KEY + AIzaSyCOuyD66ZZFJa3SMGCKJNzF1v5g-5t0Q4E + GCM_SENDER_ID + 158315296857 + PLIST_VERSION + 1 + BUNDLE_ID + com.iHackHealth.PediatricPancreasStoryboard + PROJECT_ID + pediatric-pancreatitis + STORAGE_BUCKET + pediatric-pancreatitis.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:158315296857:ios:9fa39035d6503e7ab5d948 + DATABASE_URL + https://pediatric-pancreatitis.firebaseio.com + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Info.plist b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Info.plist new file mode 100644 index 0000000..2a3483c --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/InnerResourceView.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/InnerResourceView.swift new file mode 100644 index 0000000..b91c228 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/InnerResourceView.swift @@ -0,0 +1,130 @@ +// +// InnerResourceListScreen.swift +// PediatricPancreas_Storyboard +// +// Created by Taewon Kim on 3/1/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import UIKit + +class InnerResourceView: UIViewController { + + /** + Outlets + */ + @IBOutlet weak var tableView: UITableView! + + /** + Variables + */ + var folderSelection = Folder(); // the current selected folder + var fileSelection = File(name: "", path: ""); // the file to be selected + var fileArray: [Resource] = []; // the array of files to be displayed on the screen + + var allFiles = [Resource]() + var filteredFiles = [Resource]() + + var searchController: UISearchController! + + /** + Loads the view. + */ + override func viewDidLoad() { + super.viewDidLoad() + fileArray = folderSelection.getFiles() + + // search features + searchController = UISearchController(searchResultsController: nil) + searchController.searchResultsUpdater = self + searchController.obscuresBackgroundDuringPresentation = false + searchController.definesPresentationContext = true + + navigationItem.searchController = searchController + + } + + /** + A method that will be run once the user selects a row (a file). + */ + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + // implement select/deselect animation + tableView.deselectRow(at: indexPath, animated: true) + + // the file that was selected + self.fileSelection = fileArray[indexPath.row] as! File + + // performs a segue to the next view + performSegue(withIdentifier: "PDFViewSegue", sender: self) + + } + + /** + This method is called right before performing a segue, passing along information from the current view. + */ + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + // cast the segue destination + let vc = segue.destination as! PDFViewController; + + // pass the current file selection to the next view + vc.fileSelection = self.fileSelection + + } + +} + +/** +DIsplays the current files for this view. +*/ +extension InnerResourceView: UITableViewDataSource, UITableViewDelegate { + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return fileArray.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let resource = fileArray[indexPath.row] + let cell = tableView.dequeueReusableCell(withIdentifier: "InnerResourceCell") as! ResourceCell + + cell.setResource(resource: resource) + + return cell + } + +} + +/** + Search functionality should be implemented here. + */ +extension InnerResourceView: UISearchResultsUpdating { + + /** Sets filteredList to be the files matching SEARCHTEXT and returns the number of valid files */ + private func filterFiles(for searchText: String) -> Int { + let lower = searchText.lowercased() + var count = 0 + + for file in allFiles { + if file.getName().lowercased().contains(lower) { + filteredFiles.append(file) + count += 1 + } else { + for tag in file.getTags() { + if tag.lowercased().contains(lower) { + filteredFiles.append(file) + count += 1 + break + } + } + } + } + return count + } + + func updateSearchResults(for searchController: UISearchController) { + filterFiles(for: searchController.searchBar.text ?? "") + } + + +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/MainResourceView.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/MainResourceView.swift new file mode 100644 index 0000000..93cc9e3 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/MainResourceView.swift @@ -0,0 +1,259 @@ +// +// MainResourceView.swift +// PediatricPancreas_Storyboard +// +// Created by Taewon Kim on 2/23/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import UIKit + +class MainResourceView: UIViewController { + + /** + Outlet + */ + @IBOutlet weak var tableView: UITableView! + + /** + Variables + */ + var folderSelection = Folder(); // the folder to be selected + var fileSelection = File(); + var folderArray: [Resource] = []; // the array of folders to be displayed on the screen + + var filteredFiles = [Resource](); // not sure what you need this for, but sure + + var searchController: UISearchController! + + private var resultsTableController: ResultsTableController! + + /** + Loads the view. + */ + override func viewDidLoad() { + super.viewDidLoad(); + folderArray = createArray(); + + + resultsTableController = + self.storyboard?.instantiateViewController(withIdentifier: "ResultsTableController") as? ResultsTableController + resultsTableController.tableView.delegate = self + + // search features + searchController = UISearchController(searchResultsController: resultsTableController) + searchController.delegate = self + searchController.searchResultsUpdater = self + searchController.searchBar.autocapitalizationType = .none + searchController.obscuresBackgroundDuringPresentation = false + searchController.searchBar.delegate = self + + navigationItem.searchController = searchController + navigationItem.hidesSearchBarWhenScrolling = false + definesPresentationContext = true + + } + + /** + Creates the array of folders that will be displayed. + */ + func createArray() -> [Resource] { + + var tempResources: [Resource] = []; // a temporary array + + // test folders + let res1 = Folder(name: "About Us", subfolders: [], files: [ + File(name: "Refer a patient.pdf", path: "Refer a patient.pdf") + ], tags: ["tag", "tag2"], parents: []); + let res2 = Folder(name: "Congenital Hyperinsulinism", subfolders: [], files: [ + File(name: "Hyperinsulinism info sheet.pdf", path: "Hyperinsulinism info sheet.pdf") + ], tags: ["tAg3", "taG"], parents: []); + let res3 = Folder(name: "Diabetes", subfolders: [], files: [ + ], tags: [], parents: []); + let res4 = Folder(name: "Helpful Contacts", subfolders: [], files: [ + File(name: "Helpful Numbers.pdf", path: "Helpful Numbers.pdf") + ], tags: [], parents: []); + let res5 = Folder(name: "Lab Tests", subfolders: [], files: [ + File(name: "Oral Glucose Tolerance Test (OGTT).pdf", path: "Testing/Oral Glucose Tolerance Test (OGTT).pdf"), + File(name: "Pancreatitis Genetic testing.pdf", path: "Testing/Pancreatitis Genetic testing.pdf"), + File(name: "Stool pancreatic elastase.pdf", path: "Testing/Stool pancreatic elastase.pdf"), + File(name: "Sweat chloride test.pdf", path: "Testing/Sweat chloride test.pdf") + ], tags: [], parents: []); + let res6 = Folder(name: "Pancreatitis", subfolders: [], files: [ + File(name: "Acute Pancreatitis.pdf", path: "Acute Pancreatitis.pdf"), + File(name: "Chronic pancreatitis.pdf", path: "Chronic pancreatitis.pdf"), + File(name: "EPI info sheet.pdf", path: "EPI info sheet.pdf"), + File(name: "Online resources handout .pdf", path: "Online resources handout .pdf"), + File(name: "Pain management and pancreatitis.pdf", path: "Pain management and pancreatitis.pdf"), + File(name: "Pancreas divisum handout.pdf", path: "Pancreas divisum handout.pdf"), + File(name: "Pancreatic Enzyme Medication.pdf", path: "Pancreatic Enzyme Medication.pdf"), + File(name: "Pancreatitis and Nutrition.pdf", path: "Pancreatitis and Nutrition.pdf"), + File(name: "Pancreatitis monitoring.pdf", path: "Pancreatitis monitoring.pdf") + ], tags: [], parents: []); + let res7 = Folder(name: "Procedures", subfolders: [], files: [ + File(name: "Colonoscopy.pdf", path: "Colonoscopy.pdf"), + File(name: "EGD info sheet.pdf", path: "EGD info sheet.pdf"), + File(name: "ERCP info sheet.pdf", path: "ERCP info sheet.pdf"), + File(name: "Gastric Emptying Study.pdf", path: "Gastric Emptying Study.pdf"), + File(name: "MRCP info sheet.pdf", path: "MRCP info sheet.pdf"), + File(name: "MRE info sheet.pdf", path: "MRE info sheet.pdf"), + File(name: "Upper GI.pdf", path: "Upper GI.pdf") + ], tags: [], parents: []); + let res8 = Folder(name: "School", subfolders: [], files: [ + ], tags: [], parents: []); + let res9 = Folder(name: "TPIAT", subfolders: [], files: [ + File(name: "Pediatric TPIAT Brief overview.pdf", path: "Pediatric TPIAT Brief overview.pdf"), + File(name: "TPIAT eval checklist.pdf", path: "TPIAT eval checklist.pdf") + ], tags: [], parents: []); + + tempResources.append(res1) + tempResources.append(res2) + tempResources.append(res3) + tempResources.append(res4) + tempResources.append(res5) + tempResources.append(res6) + tempResources.append(res7) + tempResources.append(res8) + tempResources.append(res9) + + return tempResources + + } + + /** + A method that will be run once the user selects a row (a folder). + */ + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + + // implement select/deselect animation + tableView.deselectRow(at: indexPath, animated: true); + + // Check to see which table view cell was selected. + if tableView === self.tableView { + // the folder that was selected + self.folderSelection = folderArray[indexPath.row] as! Folder; + performSegue(withIdentifier: "InnerResourceSegue", sender: self); + } else { + +// resultsTableController.tableView(self.tableView, didSelectRowAt: indexPath) +// + resultsTableController.fileSelection = resultsTableController.filteredFiles[indexPath.row] as! File; + + resultsTableController.performSegue(withIdentifier: "searchSegue", sender: self); + } + } + + /** + This method is called right before performing a segue, passing along information from the current view. + */ + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + + if segue.identifier == "InnerResourceSegue" { + let vc = segue.destination as! InnerResourceView; + vc.folderSelection = self.folderSelection; + } else { + let vc = segue.destination as! PDFViewController; + vc.fileSelection = self.fileSelection; + } + } + +} + +/** +DIsplays the current folders for this view. +*/ +extension MainResourceView: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, + numberOfRowsInSection section: Int) -> Int { + print(section) + return folderArray.count; + } + + internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let resource = folderArray[indexPath.row]; + let cell = tableView.dequeueReusableCell(withIdentifier: "ResourceCell") as! ResourceCell; + cell.setResource(resource: resource); + return cell; + } + +} + +extension MainResourceView: UISearchBarDelegate { + + func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { + searchBar.resignFirstResponder() + } + + func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { + updateSearchResults(for: searchController) + } + +} + +/** + Search functionality should be implemented here. + */ +extension MainResourceView: UISearchResultsUpdating { + + /** Sets filteredList to be the files matching SEARCHTEXT and returns the number of valid files */ + private func filterFiles(for searchText: String) -> Int { + let lower = searchText.lowercased() + var count = 0 + filteredFiles = [] + + for file in File.allFiles { + if file.getName().lowercased().contains(lower) { + filteredFiles.append(file) + count += 1 + } else { + for tag in file.getTags() { + if tag.lowercased().contains(lower) { + filteredFiles.append(file) + count += 1 + break + } + } + } + } + return count + } + + func updateSearchResults(for searchController: UISearchController) { + let count = filterFiles(for: searchController.searchBar.text ?? "") + + if let resultsController = searchController.searchResultsController as? ResultsTableController { + resultsController.filteredFiles = filteredFiles + resultsController.tableView.reloadData() + } + +// resultsTableController.resultsLabel.text = resultsTableController.filteredFiles.isEmpty ? +// NSLocalizedString("NoItemsFoundTitle", comment: "") : +// String(format: NSLocalizedString("Items found: %ld", comment: ""), +// resultsTableController.filteredFiles.count) + } +} + +extension MainResourceView: UISearchControllerDelegate { + +// func presentSearchController(_ searchController: UISearchController) { +// //Swift.debugPrint("UISearchControllerDelegate invoked method: \(#function).") +// } +// +// func willPresentSearchController(_ searchController: UISearchController) { +// //Swift.debugPrint("UISearchControllerDelegate invoked method: \(#function).") +// } +// +// func didPresentSearchController(_ searchController: UISearchController) { +// //Swift.debugPrint("UISearchControllerDelegate invoked method: \(#function).") +// } +// +// func willDismissSearchController(_ searchController: UISearchController) { +// //Swift.debugPrint("UISearchControllerDelegate invoked method: \(#function).") +// } +// +// func didDismissSearchController(_ searchController: UISearchController) { +// //Swift.debugPrint("UISearchControllerDelegate invoked method: \(#function).") +// } + +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/PDFViewController.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/PDFViewController.swift new file mode 100644 index 0000000..4e15216 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/PDFViewController.swift @@ -0,0 +1,67 @@ +// +// PDFViewController.swift +// PediatricPancreas_Storyboard +// +// Created by Reet Mishra on 2/19/20. +// Copyright © 2020 Example Company. All rights reserved. +// + +import UIKit +import Firebase +import FirebaseStorage +import PDFKit + +class PDFViewController: UIViewController { + + @IBOutlet weak var pdfView: PDFView! + + // Information from previous view controller. + // Please find a way to display this file. + + var fileSelection = File(); + + override func viewDidLoad() { + super.viewDidLoad() + + //declare storage refence + let storage = Storage.storage().reference() + + //getting file path on firebase + let path = fileSelection.getPath(); + //getting file on firebase + + let file = storage.child(path) + + //getting download URL of pdf + file.downloadURL{ url, error in + + if let error = error{ + + print(error.localizedDescription) + + } else { + + if let downloadURL = url{ + //download pdf through downloader in Utils + Utils.loadFileAsync(url: downloadURL) { (path, error) in + + print("PDF File downloaded to : \(path!)") + + //getting url with local file path + let fileUrl = URL.init(fileURLWithPath:path!) + + //initializing pdfView + if let pdfDocument = PDFDocument(url: fileUrl) { + self.pdfView.autoScales = true + self.pdfView.displayMode = .singlePageContinuous + self.pdfView.displayDirection = .vertical + self.pdfView.document = pdfDocument + } + } + } else { + print("error") + } + } + } + } +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Resource.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Resource.swift new file mode 100644 index 0000000..e26d378 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Resource.swift @@ -0,0 +1,39 @@ +// +// Resource.swift +// database +// +// Created by Administrator on 2/23/20. +// Copyright © 2020 JenniferZhou. All rights reserved. +// + +import Foundation + +protocol Resource { + + var _tags: [String] { get } + + /** Returns index of specified tag, or -1 if tag does not exist. */ + func hasTag(tag: String) -> Int + + /** Returns the name of the file or folder. */ + func getName() -> String + + /** Returns a list of all the tags of the file or folder */ + func getTags() -> [String] +} + +extension Resource { + + func hasTag(tag: String) -> Int { + for index in 0.. [String] { + return _tags + } +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResourceCell.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResourceCell.swift new file mode 100644 index 0000000..0a88b35 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResourceCell.swift @@ -0,0 +1,19 @@ +// +// ResourceCell.swift +// resources +// +// Created by Taewon Kim on 2/23/20. +// Copyright © 2020 Taewon Kim. All rights reserved. +// + +import UIKit + +class ResourceCell: UITableViewCell { + + @IBOutlet weak var resourceName: UILabel! + + func setResource(resource: Resource) { + resourceName.text = resource.getName() + } + +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResultsTableController.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResultsTableController.swift new file mode 100644 index 0000000..f6f2ede --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/ResultsTableController.swift @@ -0,0 +1,51 @@ +// +// ResultsTableController.swift +// PediatricPancreas_Storyboard +// +// Created by Administrator on 3/1/20. +// Copyright © 2020 Example Company. All rights reserved. +// + +import UIKit + +class ResultsTableController: UITableViewController { + + let tableViewCellIdentifier = "cellID" + + var filteredFiles = [Resource]() + + var fileSelection = File(); + + @IBOutlet weak var resultsLabel: UILabel! + + override func viewDidLoad() { + super.viewDidLoad() + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return filteredFiles.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: tableViewCellIdentifier, for: indexPath) + let file = filteredFiles[indexPath.row] + + cell.textLabel?.text = file.getName() + + return cell + } + + override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true); + self.fileSelection = filteredFiles[indexPath.row] as! File; + performSegue(withIdentifier: "searchSegue", sender: self); + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + let vc = segue.destination as! PDFViewController; + + vc.fileSelection = self.fileSelection; + } + + +} diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/SceneDelegate.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/SceneDelegate.swift new file mode 100644 index 0000000..e51352c --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/SceneDelegate.swift @@ -0,0 +1,53 @@ +// +// SceneDelegate.swift +// PediatricPancreas_Storyboard +// +// Created by Reet Mishra on 2/19/20. +// Copyright © 2020 Example Company. All rights reserved. +// + +import UIKit + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + guard let _ = (scene as? UIWindowScene) else { return } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Utils.swift b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Utils.swift new file mode 100644 index 0000000..dfa37c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/PediatricPancreas_Storyboard/Utils.swift @@ -0,0 +1,126 @@ +// +// Utils.swift +// PediatricPancreas_Storyboard +// +// Created by Jeffery Cheng on 2/29/20. +// Copyright © 2020 Example Company. All rights reserved. +// + +import Foundation +import FirebaseStorage +import FirebaseDatabase + +class Utils{ + + /* get downloada URL from firebase, runs asynchronously so doesn't work */ + static func getDownloadURL(storage : StorageReference, path : String) -> URL{ + let file = storage.child(path) + + var destination : [String] = [] + + file.downloadURL{ url, error in + print(error) + print(url) + destination.append(url!.absoluteString) + return + } + let url = URL.init(fileURLWithPath: destination[0]) + return url + } + /* download files synchronously */ + static func loadFileSync(url: URL, completion: @escaping (String?, Error?) -> Void){ + let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent) + + if FileManager().fileExists(atPath: destinationUrl.path) + { + print("File already exists [\(destinationUrl.path)]") + completion(destinationUrl.path, nil) + } + else if let dataFromURL = NSData(contentsOf: url) + { + if dataFromURL.write(to: destinationUrl, atomically: true) + { + print("file saved [\(destinationUrl.path)]") + completion(destinationUrl.path, nil) + } + else + { + print("error saving file") + let error = NSError(domain:"Error saving file", code:1001, userInfo:nil) + completion(destinationUrl.path, error) + } + } + else + { + let error = NSError(domain:"Error downloading file", code:1002, userInfo:nil) + completion(destinationUrl.path, error) + } + } + + /*download files asynchronously*/ + static func loadFileAsync(url: URL, completion: @escaping (String?, Error?) -> Void){ + let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + let destinationUrl = documentsUrl.appendingPathComponent(url.lastPathComponent) + + if FileManager().fileExists(atPath: destinationUrl.path) + { + print("File already exists [\(destinationUrl.path)]") + completion(destinationUrl.path, nil) + } + else + { + let session = URLSession(configuration: URLSessionConfiguration.default, delegate: nil, delegateQueue: nil) + var request = URLRequest(url: url) + request.httpMethod = "GET" + let task = session.dataTask(with: request, completionHandler: + { + data, response, error in + if error == nil + { + if let response = response as? HTTPURLResponse + { + if response.statusCode == 200 + { + if let data = data + { + if let _ = try? data.write(to: destinationUrl, options: Data.WritingOptions.atomic) + { + completion(destinationUrl.path, error) + } + else + { + completion(destinationUrl.path, error) + } + } + else + { + completion(destinationUrl.path, error) + } + } + } + } + else + { + completion(destinationUrl.path, error) + } + }) + task.resume() + } + } + +/*runs asynchronously in Firebase functions so it doesn't work*/ + static func getFileURL(downloadURL : URL) -> URL { + var fileURL : [String] = [] + loadFileAsync(url: downloadURL) { (path, error) in + print("PDF File downloaded to : \(path!)") + fileURL.append(path!) + } + let url = URL.init(fileURLWithPath: fileURL[0]) + return url + } + + +} diff --git a/PediatricPancreas_Storyboard/Podfile b/PediatricPancreas_Storyboard/Podfile new file mode 100644 index 0000000..46e12f8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Podfile @@ -0,0 +1,14 @@ +# Uncomment the next line to define a global platform for your project +# platform :ios, '9.0' + +target 'PediatricPancreas_Storyboard' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + + # Pods for PediatricPancreas_Storyboard + + pod 'Firebase/Core' + pod 'Firebase/Database' + pod 'Firebase/Storage' + +end diff --git a/PediatricPancreas_Storyboard/Podfile.lock b/PediatricPancreas_Storyboard/Podfile.lock new file mode 100644 index 0000000..3f3f2f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Podfile.lock @@ -0,0 +1,137 @@ +PODS: + - Firebase/Core (6.17.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.2.2) + - Firebase/CoreOnly (6.17.0): + - FirebaseCore (= 6.6.2) + - Firebase/Database (6.17.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.1.4) + - Firebase/Storage (6.17.0): + - Firebase/CoreOnly + - FirebaseStorage (~> 3.5.0) + - FirebaseAnalytics (6.2.2): + - FirebaseCore (~> 6.6) + - FirebaseInstanceID (~> 4.3) + - GoogleAppMeasurement (= 6.2.2) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAuthInterop (1.0.0) + - FirebaseCore (6.6.2): + - FirebaseCoreDiagnostics (~> 1.2) + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.2.0): + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleDataTransportCCTSupport (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.2.0) + - FirebaseDatabase (6.1.4): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.1.0): + - FirebaseCore (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.5) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.3.1): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - FirebaseStorage (3.5.0): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - GTMSessionFetcher/Core (~> 1.1) + - GoogleAppMeasurement (6.2.2): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (4.0.0) + - GoogleDataTransportCCTSupport (1.4.0): + - GoogleDataTransport (~> 4.0) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.5.1) + - GoogleUtilities/Logger (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.5.1): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.5.1)" + - GoogleUtilities/Reachability (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.5.1): + - GoogleUtilities/Logger + - GTMSessionFetcher/Core (1.3.1) + - leveldb-library (1.22) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - PromisesObjC (1.2.8) + +DEPENDENCIES: + - Firebase/Core + - Firebase/Database + - Firebase/Storage + +SPEC REPOS: + trunk: + - Firebase + - FirebaseAnalytics + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop + - FirebaseDatabase + - FirebaseInstallations + - FirebaseInstanceID + - FirebaseStorage + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - GTMSessionFetcher + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + Firebase: 2672e5636b42f977177716317e68346ae5e9de25 + FirebaseAnalytics: cf95d3aab897612783020fbd98401d5366f135ee + FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc + FirebaseCore: a1dd9dd6355a8356dd30a8f076839e242285a81c + FirebaseCoreDiagnostics: 5e78803ab276bc5b50340e3c539c06c3de35c649 + FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 + FirebaseDatabase: 0144e0706a4761f1b0e8679572eba8095ddb59be + FirebaseInstallations: 575cd32f2aec0feeb0e44f5d0110a09e5e60b47b + FirebaseInstanceID: 031d7d0c8e7b5c030bbeb4d2a690550375e83fec + FirebaseStorage: 6c5263796af3b1be82ed173598aade47535fe125 + GoogleAppMeasurement: d0560d915abf15e692e8538ba1d58442217b6aff + GoogleDataTransport: 47fe3b8e1673e5187dfd615656a3c5034f150d69 + GoogleDataTransportCCTSupport: 36f69887fd212db6d7ef4dd45ba44523717a434e + GoogleUtilities: 06eb53bb579efe7099152735900dd04bf09e7275 + GTMSessionFetcher: cea130bbfe5a7edc8d06d3f0d17288c32ffe9925 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 + +PODFILE CHECKSUM: 2b8aab10dc2ed1c09c0e116f72abd31d827654b1 + +COCOAPODS: 1.8.4 diff --git a/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/Firebase.h b/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/Firebase.h new file mode 100755 index 0000000..e5049ca --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/Firebase.h @@ -0,0 +1,172 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#if !defined(__has_include) + #error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \ + import the headers individually." +#else + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Dynamic Links works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase In App Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Messaging works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif +#endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Performance works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #if !__has_include() + #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #warning "FirebaseAnalytics.framework is not included in your target. Please add \ +`Firebase/Analytics` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \ +Firebase Remote Config works as intended." + #endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING + #endif + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + + #if __has_include() + #import + #endif + +#endif // defined(__has_include) diff --git a/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/module.modulemap b/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/module.modulemap new file mode 100755 index 0000000..3685b54 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Firebase/CoreOnly/Sources/module.modulemap @@ -0,0 +1,4 @@ +module Firebase { + export * + header "Firebase.h" +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Firebase/LICENSE b/PediatricPancreas_Storyboard/Pods/Firebase/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Firebase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/Firebase/README.md b/PediatricPancreas_Storyboard/Pods/Firebase/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Firebase/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector new file mode 100755 index 0000000..1a7eaec Binary files /dev/null and b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector differ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap new file mode 100755 index 0000000..99a4b1d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module FIRAnalyticsConnector { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics new file mode 100755 index 0000000..fa7ceb9 Binary files /dev/null and b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/FirebaseAnalytics differ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h new file mode 100755 index 0000000..d499af6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics+AppDelegate.h @@ -0,0 +1,62 @@ +#import + +#import "FIRAnalytics.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Provides App Delegate handlers to be used in your App Delegate. + * + * To save time integrating Firebase Analytics in an application, Firebase Analytics does not + * require delegation implementation from the AppDelegate. Instead this is automatically done by + * Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App + * Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting + * it to NO, and adding the methods in this category to corresponding delegation handlers. + * + * To handle Universal Links, you must return YES in + * [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. + */ +@interface FIRAnalytics (AppDelegate) + +/** + * Handles events related to a URL session that are waiting to be processed. + * + * For optimal use of Firebase Analytics, call this method from the + * [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler] + * method of the app delegate in your app. + * + * @param identifier The identifier of the URL session requiring attention. + * @param completionHandler The completion handler to call when you finish processing the events. + * Calling this completion handler lets the system know that your app's user interface is + * updated and a new snapshot can be taken. + */ ++ (void)handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(nullable void (^)(void))completionHandler; + +/** + * Handles the event when the app is launched by a URL. + * + * Call this method from [UIApplicationDelegate application:openURL:options:] (on iOS 9.0 and + * above), or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] (on + * iOS 8.x and below) in your app. + * + * @param url The URL resource to open. This resource can be a network resource or a file. + */ ++ (void)handleOpenURL:(NSURL *)url; + +/** + * Handles the event when the app receives data associated with user activity that includes a + * Universal Link (on iOS 9.0 and above). + * + * Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app + * delegate (on iOS 9.0 and above). + * + * @param userActivity The activity object containing the data associated with the task the user + * was performing. + */ ++ (void)handleUserActivity:(id)userActivity; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h new file mode 100755 index 0000000..be0b1fa --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRAnalytics.h @@ -0,0 +1,136 @@ +#import + +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" + +NS_ASSUME_NONNULL_BEGIN + +/// The top level Firebase Analytics singleton that provides methods for logging events and setting +/// user properties. See the developer guides for general +/// information on using Firebase Analytics in your apps. +/// +/// @note The Analytics SDK uses SQLite to persist events and other app-specific data. Calling +/// certain thread-unsafe global SQLite methods like `sqlite3_shutdown()` can result in +/// unexpected crashes at runtime. +NS_SWIFT_NAME(Analytics) +@interface FIRAnalytics : NSObject + +/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have +/// the same parameters. Up to 500 event names are supported. Using predefined events and/or +/// parameters is recommended for optimal reporting. +/// +/// The following event names are reserved and cannot be used: +///
    +///
  • ad_activeview
  • +///
  • ad_click
  • +///
  • ad_exposure
  • +///
  • ad_impression
  • +///
  • ad_query
  • +///
  • adunit_exposure
  • +///
  • app_clear_data
  • +///
  • app_remove
  • +///
  • app_update
  • +///
  • error
  • +///
  • first_open
  • +///
  • in_app_purchase
  • +///
  • notification_dismiss
  • +///
  • notification_foreground
  • +///
  • notification_open
  • +///
  • notification_receive
  • +///
  • os_update
  • +///
  • screen_view
  • +///
  • session_start
  • +///
  • user_engagement
  • +///
+/// +/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or +/// underscores. The name must start with an alphabetic character. Some event names are +/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are +/// case-sensitive and that logging two events whose names differ only in case will result in +/// two distinct events. +/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has +/// no parameters. Parameter names can be up to 40 characters long and must start with an +/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString +/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are +/// supported. NSString parameter values can be up to 100 characters long. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names. ++ (void)logEventWithName:(NSString *)name + parameters:(nullable NSDictionary *)parameters + NS_SWIFT_NAME(logEvent(_:parameters:)); + +/// Sets a user property to a given value. Up to 25 user property names are supported. Once set, +/// user property values persist throughout the app lifecycle and across sessions. +/// +/// The following user property names are reserved and cannot be used: +///
    +///
  • first_open_time
  • +///
  • last_deep_link_referrer
  • +///
  • user_id
  • +///
+/// +/// @param value The value of the user property. Values can be up to 36 characters long. Setting the +/// value to nil removes the user property. +/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters +/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and +/// "ga_" prefixes are reserved and should not be used for user property names. ++ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name + NS_SWIFT_NAME(setUserProperty(_:forName:)); + +/// Sets the user ID property. This feature must be used in accordance with +/// Google's Privacy Policy +/// +/// @param userID The user ID to ascribe to the user of this app on this device, which must be +/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID. ++ (void)setUserID:(nullable NSString *)userID; + +/// Sets the current screen name, which specifies the current visual context in your app. This helps +/// identify the areas in your app where users spend their time and how they interact with your app. +/// Must be called on the main thread. +/// +/// Note that screen reporting is enabled automatically and records the class name of the current +/// UIViewController for you without requiring you to call this method. If you implement +/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class +/// will not be automatically tracked. The class name can optionally be overridden by calling this +/// method in the viewDidAppear callback of your UIViewController and specifying the +/// screenClassOverride parameter. setScreenName:screenClass: must be called after +/// [super viewDidAppear:]. +/// +/// If your app does not use a distinct UIViewController for each screen, you should call this +/// method and specify a distinct screenName each time a new screen is presented to the user. +/// +/// The screen name and screen class remain in effect until the current UIViewController changes or +/// a new call to setScreenName:screenClass: is made. +/// +/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil +/// to clear the current screen name. +/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By +/// default this is the class name of the current UIViewController. Set to nil to revert to the +/// default class name. ++ (void)setScreenName:(nullable NSString *)screenName + screenClass:(nullable NSString *)screenClassOverride; + +/// Sets whether analytics collection is enabled for this app on this device. This setting is +/// persisted across app sessions. By default it is enabled. +/// +/// @param analyticsCollectionEnabled A flag that enables or disables Analytics collection. ++ (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets the interval of inactivity in seconds that terminates the current session. The default +/// value is 1800 seconds (30 minutes). +/// +/// @param sessionTimeoutInterval The custom time of inactivity in seconds before the current +/// session terminates. ++ (void)setSessionTimeoutInterval:(NSTimeInterval)sessionTimeoutInterval; + +/// The unique ID for this instance of the application. ++ (NSString *)appInstanceID; + +/// Clears all analytics data for this instance from the device and resets the app instance ID. +/// FIRAnalyticsConfiguration values will be reset to the default values. ++ (void)resetAnalyticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h new file mode 100755 index 0000000..c70c53e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIREventNames.h @@ -0,0 +1,407 @@ +/// @file FIREventNames.h +/// +/// Predefined event names. +/// +/// An Event is an important occurrence in your app that you want to measure. You can report up to +/// 500 different types of Events per app and you can associate up to 25 unique parameters with each +/// Event type. Some common events are suggested below, but you may also choose to specify custom +/// Event types that are associated with your specific app. Each event type is identified by a +/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_", +/// "google_", and "ga_" prefixes are reserved and should not be used. + +#import + +/// Add Payment Info event. This event signifies that a user has submitted their payment information +/// to your app. +static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) = + @"add_payment_info"; + +/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for +/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness +/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart"; + +/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist. +/// Use this event to identify popular gift items in your app. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) = + @"add_to_wishlist"; + +/// App Open event. By logging this event when an App becomes active, developers can understand how +/// often users leave and return during the course of a Session. Although Sessions are automatically +/// reported, this event can provide further clarification around the continuous engagement of +/// app-users. +static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open"; + +/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of +/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the +/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue +/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue +/// metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) = + @"begin_checkout"; + +/// Campaign Detail event. Log this event to supply the referral details of a re-engagement +/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource, +/// kFIRParameterMedium or kFIRParameterCampaign. Params: +/// +///
    +///
  • @c kFIRParameterSource (NSString)
  • +///
  • @c kFIRParameterMedium (NSString)
  • +///
  • @c kFIRParameterCampaign (NSString)
  • +///
  • @c kFIRParameterTerm (NSString) (optional)
  • +///
  • @c kFIRParameterContent (NSString) (optional)
  • +///
  • @c kFIRParameterAdNetworkClickID (NSString) (optional)
  • +///
  • @c kFIRParameterCP1 (NSString) (optional)
  • +///
+static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) = + @"campaign_details"; + +/// Checkout progress. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString) (optional)
  • +///
+static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) = + @"checkout_progress"; + +/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log +/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy. +/// Params: +/// +///
    +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventEarnVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency"; + +/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note: +/// This is different from the in-app purchase event, which is reported automatically for App +/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also +/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
  • @c kFIRParameterTax (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterShipping (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCoupon (NSString) (optional)
  • +///
  • @c kFIRParameterLocation (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) = + @"ecommerce_purchase"; + +/// Generate Lead event. Log this event when a lead has been generated in the app to understand the +/// efficacy of your install and re-engagement campaigns. Note: If you supply the +/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency +/// parameter so that revenue metrics can be computed accurately. Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) = + @"generate_lead"; + +/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use +/// this event to analyze how popular certain groups or social features are in your app. Params: +/// +///
    +///
  • @c kFIRParameterGroupID (NSString)
  • +///
+static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group"; + +/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can +/// help you gauge the level distribution of your userbase and help you identify certain levels that +/// are difficult to pass. Params: +/// +///
    +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up"; + +/// Login event. Apps with a login feature can report this event to signify that a user has logged +/// in. +static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login"; + +/// Post Score event. Log this event when the user posts a score in your gaming app. This event can +/// help you understand how users are actually performing in your game and it can help you correlate +/// high scores with certain audiences or behaviors. Params: +/// +///
    +///
  • @c kFIRParameterScore (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCharacter (NSString) (optional)
  • +///
+static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score"; + +/// Present Offer event. This event signifies that the app has presented a purchase offer to a user. +/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge +/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must +/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed +/// accurately. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
+static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) = + @"present_offer"; + +/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterTransactionID (NSString) (optional)
  • +///
+static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) = + @"purchase_refund"; + +/// Remove from cart event. Params: +/// +///
    +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
+static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) = + @"remove_from_cart"; + +/// Search event. Apps that support search features can use this event to contextualize search +/// operations by supplying the appropriate, corresponding parameters. This event can help you +/// identify the most popular content in your app. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// hotel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search"; + +/// Select Content event. This general purpose event signifies that a user has selected some content +/// of a certain type in an app. The content can be any object in your app. This event can help you +/// identify popular content and categories of content in your app. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) = + @"select_content"; + +/// Set checkout option. Params: +/// +///
    +///
  • @c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)
  • +///
  • @c kFIRParameterCheckoutOption (NSString)
  • +///
+static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) = + @"set_checkout_option"; + +/// Share event. Apps with social features can log the Share event to identify the most viral +/// content. Params: +/// +///
    +///
  • @c kFIRParameterContentType (NSString)
  • +///
  • @c kFIRParameterItemID (NSString)
  • +///
+static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share"; + +/// Sign Up event. This event indicates that a user has signed up for an account in your app. The +/// parameter signifies the method by which the user signed up. Use this event to understand the +/// different behaviors between logged in and logged out users. Params: +/// +///
    +///
  • @c kFIRParameterSignUpMethod (NSString)
  • +///
+static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up"; + +/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can +/// help you identify which virtual goods are the most popular objects of purchase. Params: +/// +///
    +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterVirtualCurrencyName (NSString)
  • +///
  • @c kFIRParameterValue (signed 64-bit integer or double as NSNumber)
  • +///
+static NSString *const kFIREventSpendVirtualCurrency + NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency"; + +/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use +/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this +/// process and move on to the full app experience. +static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) = + @"tutorial_begin"; + +/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding +/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your +/// on-boarding process. +static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) = + @"tutorial_complete"; + +/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your +/// game. Since achievements generally represent the breadth of a gaming experience, this event can +/// help you understand how many users are experiencing all that your game has to offer. Params: +/// +///
    +///
  • @c kFIRParameterAchievementID (NSString)
  • +///
+static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) = + @"unlock_achievement"; + +/// View Item event. This event signifies that some content was shown to the user. This content may +/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to +/// contextualize the event. Use this event to discover the most popular items viewed in your app. +/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the +/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately. +/// Params: +/// +///
    +///
  • @c kFIRParameterItemID (NSString)
  • +///
  • @c kFIRParameterItemName (NSString)
  • +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
  • @c kFIRParameterItemLocationID (NSString) (optional)
  • +///
  • @c kFIRParameterPrice (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)
  • +///
  • @c kFIRParameterCurrency (NSString) (optional)
  • +///
  • @c kFIRParameterValue (double as NSNumber) (optional)
  • +///
  • @c kFIRParameterStartDate (NSString) (optional)
  • +///
  • @c kFIRParameterEndDate (NSString) (optional)
  • +///
  • @c kFIRParameterFlightNumber (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional) +/// for travel bookings
  • +///
  • @c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for +/// travel bookings
  • +///
  • @c kFIRParameterOrigin (NSString) (optional)
  • +///
  • @c kFIRParameterDestination (NSString) (optional)
  • +///
  • @c kFIRParameterSearchTerm (NSString) (optional) for travel bookings
  • +///
  • @c kFIRParameterTravelClass (NSString) (optional) for travel bookings
  • +///
+static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item"; + +/// View Item List event. Log this event when the user has been presented with a list of items of a +/// certain category. Params: +/// +///
    +///
  • @c kFIRParameterItemCategory (NSString)
  • +///
+static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) = + @"view_item_list"; + +/// View Search Results event. Log this event when the user has been presented with the results of a +/// search. Params: +/// +///
    +///
  • @c kFIRParameterSearchTerm (NSString)
  • +///
+static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) = + @"view_search_results"; + +/// Level Start event. Log this event when the user starts a new level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
+static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) = + @"level_start"; + +/// Level End event. Log this event when the user finishes a level. Params: +/// +///
    +///
  • @c kFIRParameterLevelName (NSString)
  • +///
  • @c kFIRParameterSuccess (NSString)
  • +///
+static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h new file mode 100755 index 0000000..ad9fff7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRParameterNames.h @@ -0,0 +1,532 @@ +/// @file FIRParameterNames.h +/// +/// Predefined event parameter names. +/// +/// Params supply information that contextualize Events. You can associate up to 25 unique Params +/// with each Event type. Some Params are suggested below for certain common Events, but you are +/// not limited to these. You may supply extra Params for suggested Events or custom Params for +/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric +/// characters and underscores ("_"), and must start with an alphabetic character. Param values can +/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and +/// should not be used. + +#import + +/// Game achievement ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAchievementID : @"10_matches_won",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) = + @"achievement_id"; + +/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format. +///
+///     NSDictionary *params = @{
+///       kFIRParameterAdNetworkClickID : @"1234567",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAdNetworkClickID + NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid"; + +/// The store or affiliation from which this transaction occurred (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterAffiliation : @"Google Store",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) = + @"affiliation"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCampaign : @"winter_promotion",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Character used in game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCharacter : @"beat_boss",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) = + @"character"; + +/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutStep : @"1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) = + @"checkout_step"; + +/// Some option on a step in an ecommerce flow (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCheckoutOption : @"Visa",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCheckoutOption + NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option"; + +/// Campaign content (NSString). +static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content"; + +/// Type of content selected (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterContentType : @"news article",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) = + @"content_type"; + +/// Coupon code for a purchasable item (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCoupon : @"zz123",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon"; + +/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign. +/// Use varies by network. +///
+///     NSDictionary *params = @{
+///       kFIRParameterCP1 : @"custom_data",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1"; + +/// The name of a creative used in a promotional spot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeName : @"Summer Sale",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) = + @"creative_name"; + +/// The name of a creative slot (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCreativeSlot : @"summer_banner2",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) = + @"creative_slot"; + +/// Purchase currency in 3-letter +/// ISO_4217 format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterCurrency : @"USD",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) = + @"currency"; + +/// Flight or Travel destination (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterDestination : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) = + @"destination"; + +/// The arrival date, check-out date or rental end date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterEndDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date"; + +/// Flight number for travel events (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterFlightNumber : @"ZZ800",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) = + @"flight_number"; + +/// Group/clan/guild ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterGroupID : @"g1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id"; + +/// Index of an item in a list (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterIndex : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index"; + +/// Item brand (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemBrand : @"Google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) = + @"item_brand"; + +/// Item category (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemCategory : @"t-shirts",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) = + @"item_category"; + +/// Item ID (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemID : @"p7654",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id"; + +/// The Google Place ID (NSString) that +/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemLocationID + NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id"; + +/// Item name (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemName : @"abc",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) = + @"item_name"; + +/// The list in which the item was presented to the user (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemList : @"Search Results",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) = + @"item_list"; + +/// Item variant (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterItemVariant : @"Red",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) = + @"item_variant"; + +/// Level in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevel : @(42),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level"; + +/// Location (NSString). The Google Place ID +/// that corresponds to the associated event. Alternatively, you can supply your own custom +/// Location ID. +///
+///     NSDictionary *params = @{
+///       kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) = + @"location"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMedium : @"email",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// Number of nights staying at hotel (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfNights : @(3),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfNights + NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights"; + +/// Number of passengers traveling (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfPassengers : @(11),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfPassengers + NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers"; + +/// Number of rooms for travel events (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterNumberOfRooms : @(2),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) = + @"number_of_rooms"; + +/// Flight or Travel origin (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterOrigin : @"Mountain View, CA",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin"; + +/// Purchase price (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterPrice : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price"; + +/// Purchase quantity (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterQuantity : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) = + @"quantity"; + +/// Score in game (signed 64-bit integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterScore : @(4200),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score"; + +/// The search string/keywords used (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSearchTerm : @"periodic table",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) = + @"search_term"; + +/// Shipping cost (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterShipping : @(9.50),
+///       kFIRParameterCurrency : @"USD",  // e.g. $9.50 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) = + @"shipping"; + +/// Sign up method (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSignUpMethod : @"google",
+///       // ...
+///     };
+/// 
+/// +/// This constant has been deprecated. Use Method constant instead. +static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) = + @"sign_up_method"; + +/// A particular approach used in an operation; for example, "facebook" or "email" in the context +/// of a sign_up or login event. (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterMethod : @"google",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterMethod NS_SWIFT_NAME(AnalyticsParameterMethod) = @"method"; + +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSource : @"InMobi",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The departure date, check-in date or rental start date for the item. This should be in +/// YYYY-MM-DD format (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterStartDate : @"2015-09-14",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) = + @"start_date"; + +/// Tax amount (double as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTax : @(1.0),
+///       kFIRParameterCurrency : @"USD",  // e.g. $1.00 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax"; + +/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword +/// (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTerm : @"game",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term"; + +/// A single ID for a ecommerce group transaction (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTransactionID : @"ab7236dd9823",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) = + @"transaction_id"; + +/// Travel class (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterTravelClass : @"business",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) = + @"travel_class"; + +/// A context-specific numeric value which is accumulated automatically for each event type. This is +/// a general purpose parameter that is useful for accumulating a key metric that pertains to an +/// event. Examples include revenue, distance, time and points. Value should be specified as signed +/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events +/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be +/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is +/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the +/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid +/// currency code for conversion events will cause that +/// conversion to be omitted from reporting. +///
+///     NSDictionary *params = @{
+///       kFIRParameterValue : @(3.99),
+///       kFIRParameterCurrency : @"USD",  // e.g. $3.99 USD
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value"; + +/// Name of virtual currency type (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterVirtualCurrencyName + NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name"; + +/// The name of a level in a game (NSString). +///
+///     NSDictionary *params = @{
+///       kFIRParameterLevelName : @"room_1",
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) = + @"level_name"; + +/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned +/// integer as NSNumber). +///
+///     NSDictionary *params = @{
+///       kFIRParameterSuccess : @(1),
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success"; + +/// Indicates that the associated event should either extend the current session +/// or start a new session if no session was active when the event was logged. +/// Specify YES to extend the current session or to start a new session; any +/// other value will not extend or start a session. +///
+///     NSDictionary *params = @{
+///       kFIRParameterExtendSession : @YES,
+///       // ...
+///     };
+/// 
+static NSString *const kFIRParameterExtendSession NS_SWIFT_NAME(AnalyticsParameterExtendSession) = + @"extend_session"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h new file mode 100755 index 0000000..132aef7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FIRUserPropertyNames.h @@ -0,0 +1,29 @@ +/// @file FIRUserPropertyNames.h +/// +/// Predefined user property names. +/// +/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can +/// later analyze different behaviors of various segments of your userbase. You may supply up to 25 +/// unique UserProperties per app, and you can use the name and value of your choosing for each one. +/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and +/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to +/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not +/// be used. + +#import + +/// The method used to sign in. For example, "google", "facebook" or "twitter". +static NSString *const kFIRUserPropertySignUpMethod + NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method"; + +/// Indicates whether events logged by Google Analytics can be used to personalize ads for the user. +/// Set to "YES" to enable, or "NO" to disable. Default is enabled. See the +/// documentation for +/// more details and information about related settings. +/// +///
+///     [FIRAnalytics setUserPropertyString:@"NO"
+///                                 forName:kFIRUserPropertyAllowAdPersonalizationSignals];
+/// 
+static NSString *const kFIRUserPropertyAllowAdPersonalizationSignals + NS_SWIFT_NAME(AnalyticsUserPropertyAllowAdPersonalizationSignals) = @"allow_personalized_ads"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h new file mode 100755 index 0000000..ed7588a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers/FirebaseAnalytics.h @@ -0,0 +1,5 @@ +#import "FIRAnalytics+AppDelegate.h" +#import "FIRAnalytics.h" +#import "FIREventNames.h" +#import "FIRParameterNames.h" +#import "FIRUserPropertyNames.h" diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap new file mode 100755 index 0000000..d7c5905 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Modules/module.modulemap @@ -0,0 +1,12 @@ +framework module FirebaseAnalytics { + umbrella header "FirebaseAnalytics.h" + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h new file mode 100644 index 0000000..5c365a3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h @@ -0,0 +1,42 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRAuthInterop_h +#define FIRAuthInterop_h + +NS_ASSUME_NONNULL_BEGIN + +/** @typedef FIRTokenCallback + @brief The type of block which gets called when a token is ready. + */ +typedef void (^FIRTokenCallback)(NSString *_Nullable token, NSError *_Nullable error) + NS_SWIFT_NAME(TokenCallback); + +/// Common methods for Auth interoperability. +NS_SWIFT_NAME(AuthInterop) +@protocol FIRAuthInterop + +/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired. +- (void)getTokenForcingRefresh:(BOOL)forceRefresh withCallback:(FIRTokenCallback)callback; + +/// Get the current Auth user's UID. Returns nil if there is no user signed in. +- (nullable NSString *)getUserID; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRAuthInterop_h */ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/README.md new file mode 100644 index 0000000..4414b3e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseAuthInterop/README.md @@ -0,0 +1,179 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseAuth, FirebaseDatabase, FirebaseFirestore, +FirebaseFunctions, FirebaseMessaging and FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +An experimental Carthage distribution is now available. See +[Carthage](Carthage.md). + +## Development + +Follow the subsequent instructions to develop, debug, unit test, run integration +tests, and try out reference samples: + +``` +$ git clone git@github.com:firebase/firebase-ios-sdk.git +$ cd firebase-ios-sdk/Example +$ pod update +$ open Firebase.xcworkspace +``` + +Firestore and Functions have self contained Xcode projects. See +[Firestore/README.md](Firestore/README.md) and +[Functions/README.md](Functions/README.md). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[AuthSamples/README.md](AuthSamples/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### macOS and tvOS +FirebaseAuth, FirebaseCore, FirebaseDatabase and FirebaseStorage now compile, run unit tests, and +work on macOS and tvOS, thanks to contributions from the community. There are a few tweaks needed, +like ensuring iOS-only, macOS-only, or tvOS-only code is correctly guarded with checks for +`TARGET_OS_IOS`, `TARGET_OS_OSX` and `TARGET_OS_TV`. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS and tvOS are not officially supported by Firebase, and this repository is +actively developed primarily for iOS. While we can catch basic unit test issues with Travis, there +may be some changes where the SDK no longer works as expected on macOS or tvOS. If you encounter +this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +For installation instructions, see [above](README.md#accessing-firebase-source-snapshots). + +Note that the Firebase pod is not available for macOS and tvOS. Install a selection of the +`FirebaseAuth`, `FirebaseCore`, `FirebaseDatabase` and `FirebaseStorage` CocoaPods. + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m new file mode 100644 index 0000000..3a7d6de --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAnalyticsConfiguration.m @@ -0,0 +1,62 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" +@implementation FIRAnalyticsConfiguration +#pragma clang diagnostic pop + ++ (FIRAnalyticsConfiguration *)sharedInstance { + static FIRAnalyticsConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRAnalyticsConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (void)postNotificationName:(NSString *)name value:(id)value { + if (!name.length || !value) { + return; + } + [[NSNotificationCenter defaultCenter] postNotificationName:name + object:self + userInfo:@{name : value}]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled { + [self setAnalyticsCollectionEnabled:analyticsCollectionEnabled persistSetting:YES]; +} + +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist { + // Persist the measurementEnabledState. Use FIRAnalyticsEnabledState values instead of YES/NO. + FIRAnalyticsEnabledState analyticsEnabledState = + analyticsCollectionEnabled ? kFIRAnalyticsEnabledStateSetYes : kFIRAnalyticsEnabledStateSetNo; + if (shouldPersist) { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:@(analyticsEnabledState) + forKey:kFIRAPersistedConfigMeasurementEnabledStateKey]; + [userDefaults synchronize]; + } + + [self postNotificationName:kFIRAnalyticsConfigurationSetEnabledNotification + value:@(analyticsCollectionEnabled)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m new file mode 100644 index 0000000..02f3ac3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRApp.m @@ -0,0 +1,912 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#if __has_include() +#import +#endif + +#if __has_include() +#import +#endif + +#import + +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" +#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +#import + +#import + +// The kFIRService strings are only here while transitioning CoreDiagnostics from the Analytics +// pod to a Core dependency. These symbols are not used and should be deleted after the transition. +NSString *const kFIRServiceAdMob; +NSString *const kFIRServiceAuth; +NSString *const kFIRServiceAuthUI; +NSString *const kFIRServiceCrash; +NSString *const kFIRServiceDatabase; +NSString *const kFIRServiceDynamicLinks; +NSString *const kFIRServiceFirestore; +NSString *const kFIRServiceFunctions; +NSString *const kFIRServiceInstanceID; +NSString *const kFIRServiceInvites; +NSString *const kFIRServiceMessaging; +NSString *const kFIRServiceMeasurement; +NSString *const kFIRServicePerformance; +NSString *const kFIRServiceRemoteConfig; +NSString *const kFIRServiceStorage; +NSString *const kGGLServiceAnalytics; +NSString *const kGGLServiceSignIn; + +NSString *const kFIRDefaultAppName = @"__FIRAPP_DEFAULT"; +NSString *const kFIRAppReadyToConfigureSDKNotification = @"FIRAppReadyToConfigureSDKNotification"; +NSString *const kFIRAppDeleteNotification = @"FIRAppDeleteNotification"; +NSString *const kFIRAppIsDefaultAppKey = @"FIRAppIsDefaultAppKey"; +NSString *const kFIRAppNameKey = @"FIRAppNameKey"; +NSString *const kFIRGoogleAppIDKey = @"FIRGoogleAppIDKey"; + +NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat = + @"/google/firebase/global_data_collection_enabled:%@"; +NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey = + @"FirebaseDataCollectionDefaultEnabled"; + +NSString *const kFIRAppDiagnosticsNotification = @"FIRAppDiagnosticsNotification"; + +NSString *const kFIRAppDiagnosticsConfigurationTypeKey = @"ConfigType"; +NSString *const kFIRAppDiagnosticsErrorKey = @"Error"; +NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRApp"; +NSString *const kFIRAppDiagnosticsSDKNameKey = @"SDKName"; +NSString *const kFIRAppDiagnosticsSDKVersionKey = @"SDKVersion"; + +// Auth internal notification notification and key. +NSString *const FIRAuthStateDidChangeInternalNotification = + @"FIRAuthStateDidChangeInternalNotification"; +NSString *const FIRAuthStateDidChangeInternalNotificationAppKey = + @"FIRAuthStateDidChangeInternalNotificationAppKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey = + @"FIRAuthStateDidChangeInternalNotificationTokenKey"; +NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey = + @"FIRAuthStateDidChangeInternalNotificationUIDKey"; + +/** + * The URL to download plist files. + */ +static NSString *const kPlistURL = @"https://console.firebase.google.com/"; + +/** + * An array of all classes that registered as `FIRCoreConfigurable` in order to receive lifecycle + * events from Core. + */ +static NSMutableArray> *sRegisteredAsConfigurable; + +@interface FIRApp () + +#ifdef DEBUG +@property(nonatomic) BOOL alreadyOutputDataCollectionFlag; +#endif // DEBUG + +@end + +@implementation FIRApp + +// This is necessary since our custom getter prevents `_options` from being created. +@synthesize options = _options; + +static NSMutableDictionary *sAllApps; +static FIRApp *sDefaultApp; +static NSMutableDictionary *sLibraryVersions; +static dispatch_once_t sFirebaseUserAgentOnceToken; + ++ (void)configure { + FIROptions *options = [FIROptions defaultOptions]; + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"`[FIRApp configure];` (`FirebaseApp.configure()` in Swift) could not find " + @"a valid GoogleService-Info.plist in your project. Please download one " + @"from %@.", + kPlistURL]; + } + [FIRApp configureWithOptions:options]; +#if TARGET_OS_OSX || TARGET_OS_TV + FIRLogNotice(kFIRLoggerCore, @"I-COR000028", + @"tvOS and macOS SDK support is not part of the official Firebase product. " + @"Instead they are community supported. Details at " + @"https://github.com/firebase/firebase-ios-sdk/blob/master/README.md."); +#endif +} + ++ (void)configureWithOptions:(FIROptions *)options { + if (!options) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Options is nil. Please pass a valid options."]; + } + [FIRApp configureWithName:kFIRDefaultAppName options:options]; +} + ++ (NSCharacterSet *)applicationNameAllowedCharacters { + static NSCharacterSet *applicationNameAllowedCharacters; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableCharacterSet *allowedNameCharacters = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedNameCharacters addCharactersInString:@"-_"]; + applicationNameAllowedCharacters = [allowedNameCharacters copy]; + }); + return applicationNameAllowedCharacters; +} + ++ (void)configureWithName:(NSString *)name options:(FIROptions *)options { + if (!name || !options) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Neither name nor options can be nil."]; + } + if (name.length == 0) { + [NSException raise:kFirebaseCoreErrorDomain format:@"Name cannot be empty."]; + } + + if ([name isEqualToString:kFIRDefaultAppName]) { + if (sDefaultApp) { + // The default app already exixts. Handle duplicate `configure` calls and return. + [self appWasConfiguredTwice:sDefaultApp usingOptions:options]; + return; + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configuring the default app."); + } else { + // Validate the app name and ensure it hasn't been configured already. + NSCharacterSet *nameCharacters = [NSCharacterSet characterSetWithCharactersInString:name]; + + if (![[self applicationNameAllowedCharacters] isSupersetOfSet:nameCharacters]) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App name can only contain alphanumeric, " + @"hyphen (-), and underscore (_) characters"]; + } + + @synchronized(self) { + if (sAllApps && sAllApps[name]) { + // The app already exists. Handle a duplicate `configure` call and return. + [self appWasConfiguredTwice:sAllApps[name] usingOptions:options]; + return; + } + } + + FIRLogDebug(kFIRLoggerCore, @"I-COR000002", @"Configuring app named %@", name); + } + + @synchronized(self) { + FIRApp *app = [[FIRApp alloc] initInstanceWithName:name options:options]; + if (app.isDefaultApp) { + sDefaultApp = app; + } + + [FIRApp addAppToAppDictionary:app]; + + // The FIRApp instance is ready to go, `sDefaultApp` is assigned, other SDKs are now ready to be + // instantiated. + [app.container instantiateEagerComponents]; + [FIRApp sendNotificationsToSDKs:app]; + } +} + +/// Called when `configure` has been called multiple times for the same app. This can either throw +/// an exception (most cases) or ignore the duplicate configuration in situations where it's allowed +/// like an extension. ++ (void)appWasConfiguredTwice:(FIRApp *)app usingOptions:(FIROptions *)options { + // Only extensions should potentially be able to call `configure` more than once. + if (![GULAppEnvironmentUtil isAppExtension]) { + // Throw an exception since this is now an invalid state. + if (app.isDefaultApp) { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Default app has already been configured."]; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } + } + + // In an extension, the entry point could be called multiple times. As long as the options are + // identical we should allow multiple `configure` calls. + if ([options isEqual:app.options]) { + // Everything is identical but the extension's lifecycle triggered `configure` twice. + // Ignore duplicate calls and return since everything should still be in a valid state. + FIRLogDebug(kFIRLoggerCore, @"I-COR000035", + @"Ignoring second `configure` call in an extension."); + return; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"App named %@ has already been configured.", app.name]; + } +} + ++ (FIRApp *)defaultApp { + if (sDefaultApp) { + return sDefaultApp; + } + FIRLogError(kFIRLoggerCore, @"I-COR000003", + @"The default Firebase app has not yet been " + @"configured. Add `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) to your " + @"application initialization. Read more: https://goo.gl/ctyzm8."); + return nil; +} + ++ (FIRApp *)appNamed:(NSString *)name { + @synchronized(self) { + if (sAllApps) { + FIRApp *app = sAllApps[name]; + if (app) { + return app; + } + } + FIRLogError(kFIRLoggerCore, @"I-COR000004", @"App with name %@ does not exist.", name); + return nil; + } +} + ++ (NSDictionary *)allApps { + @synchronized(self) { + if (!sAllApps) { + FIRLogError(kFIRLoggerCore, @"I-COR000005", @"No app has been configured yet."); + } + return [sAllApps copy]; + } +} + +// Public only for tests ++ (void)resetApps { + @synchronized(self) { + sDefaultApp = nil; + [sAllApps removeAllObjects]; + sAllApps = nil; + [sLibraryVersions removeAllObjects]; + sLibraryVersions = nil; + sFirebaseUserAgentOnceToken = 0; + } +} + +- (void)deleteApp:(FIRAppVoidBoolCallback)completion { + @synchronized([self class]) { + if (sAllApps && sAllApps[self.name]) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000006", @"Deleting app named %@", self.name); + + // Remove all cached instances from the container before deleting the app. + [self.container removeAllCachedInstances]; + + [sAllApps removeObjectForKey:self.name]; + [self clearDataCollectionSwitchFromUserDefaults]; + if ([self.name isEqualToString:kFIRDefaultAppName]) { + sDefaultApp = nil; + } + NSDictionary *appInfoDict = @{kFIRAppNameKey : self.name}; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppDeleteNotification + object:[self class] + userInfo:appInfoDict]; + completion(YES); + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000007", @"App does not exist."); + completion(NO); + } + } +} + ++ (void)addAppToAppDictionary:(FIRApp *)app { + if (!sAllApps) { + sAllApps = [NSMutableDictionary dictionary]; + } + if ([app configureCore]) { + sAllApps[app.name] = app; + } else { + [NSException raise:kFirebaseCoreErrorDomain + format:@"Configuration fails. It may be caused by an invalid GOOGLE_APP_ID in " + @"GoogleService-Info.plist or set in the customized options."]; + } +} + +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options { + self = [super init]; + if (self) { + _name = [name copy]; + _options = [options copy]; + _options.editingLocked = YES; + _isDefaultApp = [name isEqualToString:kFIRDefaultAppName]; + _container = [[FIRComponentContainer alloc] initWithApp:self]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)configureCore { + [self checkExpectedBundleID]; + if (![self isAppIDValid]) { + return NO; + } + + [self logCoreTelemetryIfEnabled]; + +#if TARGET_OS_IOS + // Initialize the Analytics once there is a valid options under default app. Analytics should + // always initialize first by itself before the other SDKs. + if ([self.name isEqualToString:kFIRDefaultAppName]) { + Class firAnalyticsClass = NSClassFromString(@"FIRAnalytics"); + if (firAnalyticsClass) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL startWithConfigurationSelector = @selector(startWithConfiguration:options:); +#pragma clang diagnostic pop + if ([firAnalyticsClass respondsToSelector:startWithConfigurationSelector]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [firAnalyticsClass performSelector:startWithConfigurationSelector + withObject:[FIRConfiguration sharedInstance].analyticsConfiguration + withObject:_options]; +#pragma clang diagnostic pop + } + } + } +#endif + + [self subscribeForAppDidBecomeActiveNotifications]; + + return YES; +} + +- (FIROptions *)options { + return [_options copy]; +} + +- (void)setDataCollectionDefaultEnabled:(BOOL)dataCollectionDefaultEnabled { +#ifdef DEBUG + FIRLogDebug(kFIRLoggerCore, @"I-COR000034", @"Explicitly %@ data collection flag.", + dataCollectionDefaultEnabled ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; +#endif // DEBUG + + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] setBool:dataCollectionDefaultEnabled forKey:key]; + + // Core also controls the FirebaseAnalytics flag, so check if the Analytics flags are set + // within FIROptions and change the Analytics value if necessary. Analytics only works with the + // default app, so return if this isn't the default app. + if (!self.isDefaultApp) { + return; + } + + // Check if the Analytics flag is explicitly set. If so, no further actions are necessary. + if ([self.options isAnalyticsCollectionExplicitlySet]) { + return; + } + + // The Analytics flag has not been explicitly set, so update with the value being set. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[FIRAnalyticsConfiguration sharedInstance] + setAnalyticsCollectionEnabled:dataCollectionDefaultEnabled + persistSetting:NO]; +#pragma clang diagnostic pop +} + +- (BOOL)isDataCollectionDefaultEnabled { + // Check if it's been manually set before in code, and use that as the higher priority value. + NSNumber *defaultsObject = [[self class] readDataCollectionSwitchFromUserDefaultsForApp:self]; + if (defaultsObject != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000031", @"Data Collection flag is %@ in user defaults.", + [defaultsObject boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [defaultsObject boolValue]; + } + + // Read the Info.plist to see if the flag is set. If it's not set, it should default to `YES`. + // As per the implementation of `readDataCollectionSwitchFromPlist`, it's a cached value and has + // no performance impact calling multiple times. + NSNumber *collectionEnabledPlistValue = [[self class] readDataCollectionSwitchFromPlist]; + if (collectionEnabledPlistValue != nil) { +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000032", @"Data Collection flag is %@ in plist.", + [collectionEnabledPlistValue boolValue] ? @"enabled" : @"disabled"); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return [collectionEnabledPlistValue boolValue]; + } + +#ifdef DEBUG + if (!self.alreadyOutputDataCollectionFlag) { + FIRLogDebug(kFIRLoggerCore, @"I-COR000033", @"Data Collection flag is not set."); + self.alreadyOutputDataCollectionFlag = YES; + } +#endif // DEBUG + return YES; +} + +#pragma mark - private + ++ (void)sendNotificationsToSDKs:(FIRApp *)app { + // TODO: Remove this notification once all SDKs are registered with `FIRCoreConfigurable`. + NSNumber *isDefaultApp = [NSNumber numberWithBool:app.isDefaultApp]; + NSDictionary *appInfoDict = @{ + kFIRAppNameKey : app.name, + kFIRAppIsDefaultAppKey : isDefaultApp, + kFIRGoogleAppIDKey : app.options.googleAppID + }; + [[NSNotificationCenter defaultCenter] postNotificationName:kFIRAppReadyToConfigureSDKNotification + object:self + userInfo:appInfoDict]; + + // This is the new way of sending information to SDKs. + // TODO: Do we want this on a background thread, maybe? + @synchronized(self) { + for (Class library in sRegisteredAsConfigurable) { + [library configureWithApp:app]; + } + } +} + ++ (NSError *)errorForMissingOptions { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : + @"Unable to parse GoogleService-Info.plist in order to configure services.", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidPlistFile + userInfo:errorDict]; +} + ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason { + NSString *description = + [NSString stringWithFormat:@"Configuration failed for service %@.", service]; + NSDictionary *errorDict = + @{NSLocalizedDescriptionKey : description, NSLocalizedFailureReasonErrorKey : reason}; + return [NSError errorWithDomain:domain code:code userInfo:errorDict]; +} + ++ (NSError *)errorForInvalidAppID { + NSDictionary *errorDict = @{ + NSLocalizedDescriptionKey : @"Unable to validate Google App ID", + NSLocalizedRecoverySuggestionErrorKey : + @"Check formatting and location of GoogleService-Info.plist or GoogleAppID set in the " + @"customized options." + }; + return [NSError errorWithDomain:kFirebaseCoreErrorDomain + code:FIRErrorCodeInvalidAppID + userInfo:errorDict]; +} + ++ (BOOL)isDefaultAppConfigured { + return (sDefaultApp != nil); +} + ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version { + // Create the set of characters which aren't allowed, only if this feature is used. + NSMutableCharacterSet *allowedSet = [NSMutableCharacterSet alphanumericCharacterSet]; + [allowedSet addCharactersInString:@"-_."]; + NSCharacterSet *disallowedSet = [allowedSet invertedSet]; + // Make sure the library name and version strings do not contain unexpected characters, and + // add the name/version pair to the dictionary. + if ([name rangeOfCharacterFromSet:disallowedSet].location == NSNotFound && + [version rangeOfCharacterFromSet:disallowedSet].location == NSNotFound) { + @synchronized(self) { + if (!sLibraryVersions) { + sLibraryVersions = [[NSMutableDictionary alloc] init]; + } + sLibraryVersions[name] = version; + } + } else { + FIRLogError(kFIRLoggerCore, @"I-COR000027", + @"The library name (%@) or version number (%@) contain invalid characters. " + @"Only alphanumeric, dash, underscore and period characters are allowed.", + name, version); + } +} + ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version { + // This is called at +load time, keep the work to a minimum. + + // Ensure the class given conforms to the proper protocol. + if (![(Class)library conformsToProtocol:@protocol(FIRLibrary)] || + ![(Class)library respondsToSelector:@selector(componentsToRegister)]) { + [NSException raise:NSInvalidArgumentException + format:@"Class %@ attempted to register components, but it does not conform to " + @"`FIRLibrary or provide a `componentsToRegister:` method.", + library]; + } + + [FIRComponentContainer registerAsComponentRegistrant:library]; + if ([(Class)library respondsToSelector:@selector(configureWithApp:)]) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRegisteredAsConfigurable = [[NSMutableArray alloc] init]; + }); + @synchronized(self) { + [sRegisteredAsConfigurable addObject:library]; + } + } + [self registerLibrary:name withVersion:version]; +} + ++ (NSString *)firebaseUserAgent { + @synchronized(self) { + dispatch_once(&sFirebaseUserAgentOnceToken, ^{ + // Report FirebaseCore version for useragent string + [FIRApp registerLibrary:@"fire-ios" + withVersion:[NSString stringWithUTF8String:FIRCoreVersionString]]; + + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + NSString *xcodeVersion = info[@"DTXcodeBuild"]; + NSString *sdkVersion = info[@"DTSDKBuild"]; + if (xcodeVersion) { + [FIRApp registerLibrary:@"xcode" withVersion:xcodeVersion]; + } + if (sdkVersion) { + [FIRApp registerLibrary:@"apple-sdk" withVersion:sdkVersion]; + } + + NSString *swiftFlagValue = [self hasSwiftRuntime] ? @"true" : @"false"; + [FIRApp registerLibrary:@"swift" withVersion:swiftFlagValue]; + }); + + NSMutableArray *libraries = + [[NSMutableArray alloc] initWithCapacity:sLibraryVersions.count]; + for (NSString *libraryName in sLibraryVersions) { + [libraries addObject:[NSString stringWithFormat:@"%@/%@", libraryName, + sLibraryVersions[libraryName]]]; + } + [libraries sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + return [libraries componentsJoinedByString:@" "]; + } +} + ++ (BOOL)hasSwiftRuntime { + // The class + // [Swift._SwiftObject](https://github.com/apple/swift/blob/5eac3e2818eb340b11232aff83edfbd1c307fa03/stdlib/public/runtime/SwiftObject.h#L35) + // is a part of Swift runtime, so it should be present if Swift runtime is available. + + BOOL hasSwiftRuntime = + objc_lookUpClass("Swift._SwiftObject") != nil || + // Swift object class name before + // https://github.com/apple/swift/commit/9637b4a6e11ddca72f5f6dbe528efc7c92f14d01 + objc_getClass("_TtCs12_SwiftObject") != nil; + + return hasSwiftRuntime; +} + +- (void)checkExpectedBundleID { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *expectedBundleID = [self expectedBundleID]; + // The checking is only done when the bundle ID is provided in the serviceInfo dictionary for + // backward compatibility. + if (expectedBundleID != nil && ![FIRBundleUtil hasBundleIdentifierPrefix:expectedBundleID + inBundles:bundles]) { + FIRLogError(kFIRLoggerCore, @"I-COR000008", + @"The project's Bundle ID is inconsistent with " + @"either the Bundle ID in '%@.%@', or the Bundle ID in the options if you are " + @"using a customized options. To ensure that everything can be configured " + @"correctly, you may need to make the Bundle IDs consistent. To continue with this " + @"plist file, you may change your app's bundle identifier to '%@'. Or you can " + @"download a new configuration file that matches your bundle identifier from %@ " + @"and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + } +} + +#pragma mark - private - App ID Validation + +/** + * Validates the format and fingerprint of the app ID contained in GOOGLE_APP_ID in the plist file. + * This is the main method for validating app ID. + * + * @return YES if the app ID fulfills the expected format and fingerprint, NO otherwise. + */ +- (BOOL)isAppIDValid { + NSString *appID = _options.googleAppID; + BOOL isValid = [FIRApp validateAppID:appID]; + if (!isValid) { + NSString *expectedBundleID = [self expectedBundleID]; + FIRLogError(kFIRLoggerCore, @"I-COR000009", + @"The GOOGLE_APP_ID either in the plist file " + @"'%@.%@' or the one set in the customized options is invalid. If you are using " + @"the plist file, use the iOS version of bundle identifier to download the file, " + @"and do not manually edit the GOOGLE_APP_ID. You may change your app's bundle " + @"identifier to '%@'. Or you can download a new configuration file that matches " + @"your bundle identifier from %@ and replace the current one.", + kServiceInfoFileName, kServiceInfoFileType, expectedBundleID, kPlistURL); + }; + return isValid; +} + ++ (BOOL)validateAppID:(NSString *)appID { + // Failing validation only occurs when we are sure we are looking at a V2 app ID and it does not + // have a valid fingerprint, otherwise we just warn about the potential issue. + if (!appID.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + NSString *appIDVersion; + if (![stringScanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] + intoString:&appIDVersion]) { + return NO; + } + + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + NSArray *knownVersions = @[ @"1" ]; + if (![knownVersions containsObject:appIDVersion]) { + // Permit unknown yet properly formatted app ID versions. + FIRLogInfo(kFIRLoggerCore, @"I-COR000010", @"Unknown GOOGLE_APP_ID version: %@", appIDVersion); + return YES; + } + + if (![self validateAppIDFormat:appID withVersion:appIDVersion]) { + return NO; + } + + if (![self validateAppIDFingerprint:appID withVersion:appIDVersion]) { + return NO; + } + + return YES; +} + ++ (NSString *)actualBundleID { + return [[NSBundle mainBundle] bundleIdentifier]; +} + +/** + * Validates that the format of the app ID string is what is expected based on the supplied version. + * The version must end in ":". + * + * For v1 app ids the format is expected to be + * '::ios:'. + * + * This method does not verify that the contents of the app id are correct, just that they fulfill + * the expected format. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected format, NO otherwise. + */ ++ (BOOL)validateAppIDFormat:(NSString *)appID withVersion:(NSString *)version { + if (!appID.length || !version.length) { + return NO; + } + + NSScanner *stringScanner = [NSScanner scannerWithString:appID]; + stringScanner.charactersToBeSkipped = nil; + + // Skip version part + // '**::ios:' + if (![stringScanner scanString:version intoString:NULL]) { + // The version part is missing or mismatched + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '*:*:ios:' + if (![stringScanner scanString:@":" intoString:NULL]) { + // appIDVersion must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':**:ios:'. + NSInteger projectNumber = NSNotFound; + if (![stringScanner scanInteger:&projectNumber]) { + // NO project number found. + return NO; + } + + // Validate version part (see part between '*' symbols below) + // ':*:*ios:'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The project number must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::*ios*:'. + NSString *platform; + if (![stringScanner scanUpToString:@":" intoString:&platform]) { + return NO; + } + + if (![platform isEqualToString:@"ios"]) { + // The platform must be @"ios" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios*:*'. + if (![stringScanner scanString:@":" intoString:NULL]) { + // The platform must be separated by ":" + return NO; + } + + // Validate version part (see part between '*' symbols below) + // '::ios:**'. + unsigned long long fingerprint = NSNotFound; + if (![stringScanner scanHexLongLong:&fingerprint]) { + // Fingerprint part is missing + return NO; + } + + if (!stringScanner.isAtEnd) { + // There are not allowed characters in the fingerprint part + return NO; + } + + return YES; +} + +/** + * Validates that the fingerprint of the app ID string is what is expected based on the supplied + * version. + * + * Note that the v1 hash algorithm is not permitted on the client and cannot be fully validated. + * + * @param appID Contents of GOOGLE_APP_ID from the plist file. + * @param version Indicates what version of the app id format this string should be. + * @return YES if provided string fufills the expected fingerprint and the version is known, NO + * otherwise. + */ ++ (BOOL)validateAppIDFingerprint:(NSString *)appID withVersion:(NSString *)version { + // Extract the supplied fingerprint from the supplied app ID. + // This assumes the app ID format is the same for all known versions below. If the app ID format + // changes in future versions, the tokenizing of the app ID format will need to take into account + // the version of the app ID. + NSArray *components = [appID componentsSeparatedByString:@":"]; + if (components.count != 4) { + return NO; + } + + NSString *suppliedFingerprintString = components[3]; + if (!suppliedFingerprintString.length) { + return NO; + } + + uint64_t suppliedFingerprint; + NSScanner *scanner = [NSScanner scannerWithString:suppliedFingerprintString]; + if (![scanner scanHexLongLong:&suppliedFingerprint]) { + return NO; + } + + if ([version isEqual:@"1"]) { + // The v1 hash algorithm is not permitted on the client so the actual hash cannot be validated. + return YES; + } + + // Unknown version. + return NO; +} + +- (NSString *)expectedBundleID { + return _options.bundleID; +} + +// end App ID validation + +#pragma mark - Reading From Plist & User Defaults + +/** + * Clears the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ +- (void)clearDataCollectionSwitchFromUserDefaults { + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, self.name]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; +} + +/** + * Reads the data collection switch from the standard NSUserDefaults for easier testing and + * readability. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromUserDefaultsForApp:(FIRApp *)app { + // Read the object in user defaults, and only return if it's an NSNumber. + NSString *key = + [NSString stringWithFormat:kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat, app.name]; + id collectionEnabledDefaultsObject = [[NSUserDefaults standardUserDefaults] objectForKey:key]; + if ([collectionEnabledDefaultsObject isKindOfClass:[NSNumber class]]) { + return collectionEnabledDefaultsObject; + } + + return nil; +} + +/** + * Reads the data collection switch from the Info.plist for easier testing and readability. Will + * only read once from the plist and return the cached value. + */ ++ (nullable NSNumber *)readDataCollectionSwitchFromPlist { + static NSNumber *collectionEnabledPlistObject; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Read the data from the `Info.plist`, only assign it if it's there and an NSNumber. + id plistValue = [[NSBundle mainBundle] + objectForInfoDictionaryKey:kFIRGlobalAppDataCollectionEnabledPlistKey]; + if (plistValue && [plistValue isKindOfClass:[NSNumber class]]) { + collectionEnabledPlistObject = (NSNumber *)plistValue; + } + }); + + return collectionEnabledPlistObject; +} + +#pragma mark - Sending Logs + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error { + // Do nothing. Please remove calls to this method. +} +#pragma clang diagnostic pop + +#pragma mark - App Life Cycle + +- (void)subscribeForAppDidBecomeActiveNotifications { +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationName notificationName = UIApplicationDidBecomeActiveNotification; +#elif TARGET_OS_OSX + NSNotificationName notificationName = NSApplicationDidBecomeActiveNotification; +#endif + +#if !TARGET_OS_WATCH + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidBecomeActive:) + name:notificationName + object:nil]; +#endif +} + +- (void)appDidBecomeActive:(NSNotification *)notification { + [self logCoreTelemetryIfEnabled]; +} + +- (void)logCoreTelemetryIfEnabled { + if ([self isDataCollectionDefaultEnabled]) { + [FIRCoreDiagnosticsConnector logCoreTelemetryWithOptions:_options]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m new file mode 100644 index 0000000..e4125cd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRAppAssociationRegistration.m @@ -0,0 +1,47 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h" + +#import + +@implementation FIRAppAssociationRegistration + ++ (nullable id)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(id _Nullable (^)(void))creationBlock { + @synchronized(self) { + SEL dictKey = @selector(registeredObjectWithHost:key:creationBlock:); + NSMutableDictionary *objectsByKey = objc_getAssociatedObject(host, dictKey); + if (!objectsByKey) { + objectsByKey = [[NSMutableDictionary alloc] init]; + objc_setAssociatedObject(host, dictKey, objectsByKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + id obj = objectsByKey[key]; + NSValue *creationBlockBeingCalled = [NSValue valueWithPointer:dictKey]; + if (obj) { + if ([creationBlockBeingCalled isEqual:obj]) { + [NSException raise:@"Reentering registeredObjectWithHost:key:creationBlock: not allowed" + format:@"host: %@ key: %@", host, key]; + } + return obj; + } + objectsByKey[key] = creationBlockBeingCalled; + obj = creationBlock(); + objectsByKey[key] = obj; + return obj; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h new file mode 100644 index 0000000..d9475dd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * This class provides utilities for accessing resources in bundles. + */ +@interface FIRBundleUtil : NSObject + +/** + * Finds all relevant bundles, starting with [NSBundle mainBundle]. + */ ++ (NSArray *)relevantBundles; + +/** + * Reads the options dictionary from one of the provided bundles. + * + * @param resourceName The resource name, e.g. @"GoogleService-Info". + * @param fileType The file type (extension), e.g. @"plist". + * @param bundles The bundles to expect, in priority order. See also + * +[FIRBundleUtil relevantBundles]. + */ ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles; + +/** + * Finds URL schemes defined in all relevant bundles, starting with those from + * [NSBundle mainBundle]. + */ ++ (NSArray *)relevantURLSchemes; + +/** + * Checks if any of the given bundles have a matching bundle identifier prefix (removing extension + * suffixes). + */ ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m new file mode 100644 index 0000000..b858f14 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRBundleUtil.m @@ -0,0 +1,75 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" + +#import + +@implementation FIRBundleUtil + ++ (NSArray *)relevantBundles { + return @[ [NSBundle mainBundle], [NSBundle bundleForClass:[self class]] ]; +} + ++ (NSString *)optionsDictionaryPathWithResourceName:(NSString *)resourceName + andFileType:(NSString *)fileType + inBundles:(NSArray *)bundles { + // Loop through all bundles to find the config dict. + for (NSBundle *bundle in bundles) { + NSString *path = [bundle pathForResource:resourceName ofType:fileType]; + // Use the first one we find. + if (path) { + return path; + } + } + return nil; +} + ++ (NSArray *)relevantURLSchemes { + NSMutableArray *result = [[NSMutableArray alloc] init]; + for (NSBundle *bundle in [[self class] relevantBundles]) { + NSArray *urlTypes = [bundle objectForInfoDictionaryKey:@"CFBundleURLTypes"]; + for (NSDictionary *urlType in urlTypes) { + [result addObjectsFromArray:urlType[@"CFBundleURLSchemes"]]; + } + } + return result; +} + ++ (BOOL)hasBundleIdentifierPrefix:(NSString *)bundleIdentifier inBundles:(NSArray *)bundles { + for (NSBundle *bundle in bundles) { + // This allows app extensions that have the app's bundle as their prefix to pass this test. + NSString *applicationBundleIdentifier = + [GULAppEnvironmentUtil isAppExtension] + ? [self bundleIdentifierByRemovingLastPartFrom:bundle.bundleIdentifier] + : bundle.bundleIdentifier; + + if ([applicationBundleIdentifier isEqualToString:bundleIdentifier]) { + return YES; + } + } + return NO; +} + ++ (NSString *)bundleIdentifierByRemovingLastPartFrom:(NSString *)bundleIdentifier { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleIdentifier componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m new file mode 100644 index 0000000..9c1fbed --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponent.m @@ -0,0 +1,65 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponent.h" + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRComponent () + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock; + +@end + +@implementation FIRComponent + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[] + creationBlock:creationBlock]; +} + ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + return [[FIRComponent alloc] initWithProtocol:protocol + instantiationTiming:instantiationTiming + dependencies:dependencies + creationBlock:creationBlock]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock { + self = [super init]; + if (self) { + _protocol = protocol; + _instantiationTiming = instantiationTiming; + _dependencies = [dependencies copy]; + _creationBlock = creationBlock; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m new file mode 100644 index 0000000..9f91786 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentContainer.m @@ -0,0 +1,208 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer () + +/// The dictionary of components that are registered for a particular app. The key is an `NSString` +/// of the protocol. +@property(nonatomic, strong) NSMutableDictionary *components; + +/// Cached instances of components that requested to be cached. +@property(nonatomic, strong) NSMutableDictionary *cachedInstances; + +/// Protocols of components that have requested to be eagerly instantiated. +@property(nonatomic, strong, nullable) NSMutableArray *eagerProtocolsToInstantiate; + +@end + +@implementation FIRComponentContainer + +// Collection of all classes that register to provide components. +static NSMutableSet *sFIRComponentRegistrants; + +#pragma mark - Public Registration + ++ (void)registerAsComponentRegistrant:(Class)klass { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sFIRComponentRegistrants = [[NSMutableSet alloc] init]; + }); + + [self registerAsComponentRegistrant:klass inSet:sFIRComponentRegistrants]; +} + ++ (void)registerAsComponentRegistrant:(Class)klass + inSet:(NSMutableSet *)allRegistrants { + [allRegistrants addObject:klass]; +} + +#pragma mark - Internal Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWithApp:app registrants:sFIRComponentRegistrants]; +} + +- (instancetype)initWithApp:(FIRApp *)app registrants:(NSMutableSet *)allRegistrants { + self = [super init]; + if (self) { + _app = app; + _cachedInstances = [NSMutableDictionary dictionary]; + _components = [NSMutableDictionary dictionary]; + + [self populateComponentsFromRegisteredClasses:allRegistrants forApp:app]; + } + return self; +} + +- (void)populateComponentsFromRegisteredClasses:(NSSet *)classes forApp:(FIRApp *)app { + // Keep track of any components that need to eagerly instantiate after all components are added. + self.eagerProtocolsToInstantiate = [[NSMutableArray alloc] init]; + + // Loop through the verified component registrants and populate the components array. + for (Class klass in classes) { + // Loop through all the components being registered and store them as appropriate. + // Classes which do not provide functionality should use a dummy FIRComponentRegistrant + // protocol. + for (FIRComponent *component in [klass componentsToRegister]) { + // Check if the component has been registered before, and error out if so. + NSString *protocolName = NSStringFromProtocol(component.protocol); + if (self.components[protocolName]) { + FIRLogError(kFIRLoggerCore, @"I-COR000029", + @"Attempted to register protocol %@, but it already has an implementation.", + protocolName); + continue; + } + + // Store the creation block for later usage. + self.components[protocolName] = component.creationBlock; + + // Queue any protocols that should be eagerly instantiated. Don't instantiate them yet + // because they could depend on other components that haven't been added to the components + // array yet. + BOOL shouldInstantiateEager = + (component.instantiationTiming == FIRInstantiationTimingAlwaysEager); + BOOL shouldInstantiateDefaultEager = + (component.instantiationTiming == FIRInstantiationTimingEagerInDefaultApp && + [app isDefaultApp]); + if (shouldInstantiateEager || shouldInstantiateDefaultEager) { + [self.eagerProtocolsToInstantiate addObject:component.protocol]; + } + } + } +} + +#pragma mark - Instance Creation + +- (void)instantiateEagerComponents { + // After all components are registered, instantiate the ones that are requesting eager + // instantiation. + @synchronized(self) { + for (Protocol *protocol in self.eagerProtocolsToInstantiate) { + // Get an instance for the protocol, which will instantiate it since it couldn't have been + // cached yet. Ignore the instance coming back since we don't need it. + __unused id unusedInstance = [self instanceForProtocol:protocol]; + } + + // All eager instantiation is complete, clear the stored property now. + self.eagerProtocolsToInstantiate = nil; + } +} + +/// Instantiate an instance of a class that conforms to the specified protocol. +/// This will: +/// - Call the block to create an instance if possible, +/// - Validate that the instance returned conforms to the protocol it claims to, +/// - Cache the instance if the block requests it +/// +/// Note that this method assumes the caller already has @sychronized on self. +- (nullable id)instantiateInstanceForProtocol:(Protocol *)protocol + withBlock:(FIRComponentCreationBlock)creationBlock { + if (!creationBlock) { + return nil; + } + + // Create an instance using the creation block. + BOOL shouldCache = NO; + id instance = creationBlock(self, &shouldCache); + if (!instance) { + return nil; + } + + // An instance was created, validate that it conforms to the protocol it claims to. + NSString *protocolName = NSStringFromProtocol(protocol); + if (![instance conformsToProtocol:protocol]) { + FIRLogError(kFIRLoggerCore, @"I-COR000030", + @"An instance conforming to %@ was requested, but the instance provided does not " + @"conform to the protocol", + protocolName); + } + + // The instance is ready to be returned, but check if it should be cached first before returning. + if (shouldCache) { + self.cachedInstances[protocolName] = instance; + } + + return instance; +} + +#pragma mark - Internal Retrieval + +- (nullable id)instanceForProtocol:(Protocol *)protocol { + // Check if there is a cached instance, and return it if so. + NSString *protocolName = NSStringFromProtocol(protocol); + + id cachedInstance; + @synchronized(self) { + cachedInstance = self.cachedInstances[protocolName]; + if (!cachedInstance) { + // Use the creation block to instantiate an instance and return it. + FIRComponentCreationBlock creationBlock = self.components[protocolName]; + cachedInstance = [self instantiateInstanceForProtocol:protocol withBlock:creationBlock]; + } + } + return cachedInstance; +} + +#pragma mark - Lifecycle + +- (void)removeAllCachedInstances { + @synchronized(self) { + // Loop through the cache and notify each instance that is a maintainer to clean up after + // itself. + for (id instance in self.cachedInstances.allValues) { + if ([instance conformsToProtocol:@protocol(FIRComponentLifecycleMaintainer)] && + [instance respondsToSelector:@selector(appWillBeDeleted:)]) { + [instance appWillBeDeleted:self.app]; + } + } + + // Empty the cache. + [self.cachedInstances removeAllObjects]; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m new file mode 100644 index 0000000..6410f2e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRComponentType.m @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRComponentType.h" + +#import "FirebaseCore/Sources/Private/FIRComponentContainerInternal.h" + +@implementation FIRComponentType + ++ (id)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container { + // Forward the call to the container. + return [container instanceForProtocol:protocol]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m new file mode 100644 index 0000000..a1c9f4a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRConfiguration.m @@ -0,0 +1,46 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRConfigurationInternal.h" + +#import "FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h" + +extern void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +@implementation FIRConfiguration + ++ (instancetype)sharedInstance { + static FIRConfiguration *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRConfiguration alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _analyticsConfiguration = [FIRAnalyticsConfiguration sharedInstance]; + } + return self; +} + +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel { + NSAssert(loggerLevel <= FIRLoggerLevelMax && loggerLevel >= FIRLoggerLevelMin, + @"Invalid logger level, %ld", (long)loggerLevel); + FIRSetLoggerLevel(loggerLevel); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m new file mode 100644 index 0000000..4981ca1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h" + +#import + +#import + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Define the interop class symbol declared as an extern in FIRCoreDiagnosticsInterop. +Class FIRCoreDiagnosticsImplementation; + +@implementation FIRCoreDiagnosticsConnector + ++ (void)initialize { + if (!FIRCoreDiagnosticsImplementation) { + FIRCoreDiagnosticsImplementation = NSClassFromString(@"FIRCoreDiagnostics"); + if (FIRCoreDiagnosticsImplementation) { + NSAssert([FIRCoreDiagnosticsImplementation + conformsToProtocol:@protocol(FIRCoreDiagnosticsInterop)], + @"If FIRCoreDiagnostics is implemented, it must conform to the interop protocol."); + NSAssert( + [FIRCoreDiagnosticsImplementation respondsToSelector:@selector(sendDiagnosticsData:)], + @"If FIRCoreDiagnostics is implemented, it must implement +sendDiagnosticsData."); + } + } +} + ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options { + if (FIRCoreDiagnosticsImplementation) { + FIRDiagnosticsData *diagnosticsData = [[FIRDiagnosticsData alloc] init]; + [diagnosticsData insertValue:@(YES) forKey:kFIRCDIsDataCollectionDefaultEnabledKey]; + [diagnosticsData insertValue:[FIRApp firebaseUserAgent] forKey:kFIRCDFirebaseUserAgentKey]; + [diagnosticsData insertValue:@(FIRConfigTypeCore) forKey:kFIRCDConfigurationTypeKey]; + [diagnosticsData insertValue:options.googleAppID forKey:kFIRCDGoogleAppIDKey]; + [diagnosticsData insertValue:options.bundleID forKey:kFIRCDBundleIDKey]; + [diagnosticsData insertValue:@(options.usingOptionsFromDefaultPlist) + forKey:kFIRCDUsingOptionsFromDefaultPlistKey]; + [diagnosticsData insertValue:options.libraryVersionID forKey:kFIRCDLibraryVersionIDKey]; + [FIRCoreDiagnosticsImplementation sendDiagnosticsData:diagnosticsData]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m new file mode 100644 index 0000000..e1e2578 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDependency.m @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRDependency.h" + +@interface FIRDependency () + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +@end + +@implementation FIRDependency + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol { + return [[self alloc] initWithProtocol:protocol isRequired:YES]; +} + ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + return [[self alloc] initWithProtocol:protocol isRequired:required]; +} + +- (instancetype)initWithProtocol:(Protocol *)protocol isRequired:(BOOL)required { + self = [super init]; + if (self) { + _protocol = protocol; + _isRequired = required; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m new file mode 100644 index 0000000..bbe0561 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRDiagnosticsData.m @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseCore/Sources/Private/FIRDiagnosticsData.h" + +#import + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +@implementation FIRDiagnosticsData { + /** Backing ivar for the diagnosticObjects property. */ + NSMutableDictionary *_diagnosticObjects; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _diagnosticObjects = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)insertValue:(nullable id)value forKey:(NSString *)key { + if (key) { + _diagnosticObjects[key] = value; + } +} + +#pragma mark - FIRCoreDiagnosticsData + +- (NSDictionary *)diagnosticObjects { + if (!_diagnosticObjects[kFIRCDllAppsCountKey]) { + _diagnosticObjects[kFIRCDllAppsCountKey] = @([FIRApp allApps].count); + } + if (!_diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]) { + _diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey] = + @([[FIRApp defaultApp] isDataCollectionDefaultEnabled]); + } + if (!_diagnosticObjects[kFIRCDFirebaseUserAgentKey]) { + _diagnosticObjects[kFIRCDFirebaseUserAgentKey] = [FIRApp firebaseUserAgent]; + } + return _diagnosticObjects; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +- (void)setDiagnosticObjects:(NSDictionary *)diagnosticObjects { + NSAssert(NO, @"Please use -insertValue:forKey:"); +} +#pragma clang diagnostic pop + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m new file mode 100644 index 0000000..104eeb8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRErrors.m @@ -0,0 +1,21 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRErrors.h" + +NSString *const kFirebaseErrorDomain = @"com.firebase"; +NSString *const kFirebaseConfigErrorDomain = @"com.firebase.config"; +NSString *const kFirebaseCoreErrorDomain = @"com.firebase.core"; +NSString *const kFirebasePerfErrorDomain = @"com.firebase.perf"; +NSString *const kFirebaseStorageErrorDomain = @"com.firebase.storage"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m new file mode 100644 index 0000000..277b0f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRHeartbeatInfo.m @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import +#import + +const static long secondsInDay = 86400; +@implementation FIRHeartbeatInfo : NSObject + +/** Updates the storage with the heartbeat information corresponding to this tag. + * @param heartbeatTag Tag which could either be sdk specific tag or the global tag. + * @return Boolean representing whether the heartbeat needs to be sent for this tag or not. + */ ++ (BOOL)updateIfNeededHeartbeatDateForTag:(NSString *)heartbeatTag { + @synchronized(self) { + NSString *const kHeartbeatStorageFile = @"HEARTBEAT_INFO_STORAGE"; + GULHeartbeatDateStorage *dataStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kHeartbeatStorageFile]; + NSDate *heartbeatTime = [dataStorage heartbeatDateForTag:heartbeatTag]; + NSDate *currentDate = [NSDate date]; + if (heartbeatTime != nil) { + NSTimeInterval secondsBetween = [currentDate timeIntervalSinceDate:heartbeatTime]; + if (secondsBetween < secondsInDay) { + return false; + } + } + return [dataStorage setHearbeatDate:currentDate forTag:heartbeatTag]; + } +} + ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag { + NSString *globalTag = @"GLOBAL"; + BOOL isSdkHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:heartbeatTag]; + BOOL isGlobalHeartbeatNeeded = [FIRHeartbeatInfo updateIfNeededHeartbeatDateForTag:globalTag]; + if (!isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Both sdk and global heartbeat not needed. + return FIRHeartbeatInfoCodeNone; + } else if (isSdkHeartbeatNeeded && !isGlobalHeartbeatNeeded) { + // Only SDK heartbeat needed. + return FIRHeartbeatInfoCodeSDK; + } else if (!isSdkHeartbeatNeeded && isGlobalHeartbeatNeeded) { + // Only global heartbeat needed. + return FIRHeartbeatInfoCodeGlobal; + } else { + // Both sdk and global heartbeat are needed. + return FIRHeartbeatInfoCodeCombined; + } +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m new file mode 100644 index 0000000..ba2ee1f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRLogger.m @@ -0,0 +1,179 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/Private/FIRLogger.h" + +#import +#import +#import + +#import "FirebaseCore/Sources/FIRVersion.h" + +FIRLoggerService kFIRLoggerCore = @"[Firebase/Core]"; + +// All the FIRLoggerService definitions should be migrated to clients. Do not add new ones! +FIRLoggerService kFIRLoggerABTesting = @"[Firebase/ABTesting]"; +FIRLoggerService kFIRLoggerAdMob = @"[Firebase/AdMob]"; +FIRLoggerService kFIRLoggerAnalytics = @"[Firebase/Analytics]"; +FIRLoggerService kFIRLoggerAuth = @"[Firebase/Auth]"; +FIRLoggerService kFIRLoggerCrash = @"[Firebase/Crash]"; +FIRLoggerService kFIRLoggerMLKit = @"[Firebase/MLKit]"; +FIRLoggerService kFIRLoggerPerf = @"[Firebase/Performance]"; +FIRLoggerService kFIRLoggerRemoteConfig = @"[Firebase/RemoteConfig]"; + +/// Arguments passed on launch. +NSString *const kFIRDisableDebugModeApplicationArgument = @"-FIRDebugDisabled"; +NSString *const kFIREnableDebugModeApplicationArgument = @"-FIRDebugEnabled"; +NSString *const kFIRLoggerForceSDTERRApplicationArgument = @"-FIRLoggerForceSTDERR"; + +/// Key for the debug mode bit in NSUserDefaults. +NSString *const kFIRPersistedDebugModeKey = @"/google/firebase/debug_mode"; + +/// NSUserDefaults that should be used to store and read variables. If nil, `standardUserDefaults` +/// will be used. +static NSUserDefaults *sFIRLoggerUserDefaults; + +static dispatch_once_t sFIRLoggerOnceToken; + +// The sFIRAnalyticsDebugMode flag is here to support the -FIRDebugEnabled/-FIRDebugDisabled +// flags used by Analytics. Users who use those flags expect Analytics to log verbosely, +// while the rest of Firebase logs at the default level. This flag is introduced to support +// that behavior. +static BOOL sFIRAnalyticsDebugMode; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void FIRLoggerInitializeASL() { + dispatch_once(&sFIRLoggerOnceToken, ^{ + // Register Firebase Version with GULLogger. + GULLoggerRegisterVersion(FIRVersionString); + + // Override the aslOptions to ASL_OPT_STDERR if the override argument is passed in. + NSArray *arguments = [NSProcessInfo processInfo].arguments; + BOOL overrideSTDERR = [arguments containsObject:kFIRLoggerForceSDTERRApplicationArgument]; + + // Use the standard NSUserDefaults if it hasn't been explicitly set. + if (sFIRLoggerUserDefaults == nil) { + sFIRLoggerUserDefaults = [NSUserDefaults standardUserDefaults]; + } + + BOOL forceDebugMode = NO; + BOOL debugMode = [sFIRLoggerUserDefaults boolForKey:kFIRPersistedDebugModeKey]; + if ([arguments containsObject:kFIRDisableDebugModeApplicationArgument]) { // Default mode + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + } else if ([arguments containsObject:kFIREnableDebugModeApplicationArgument] || + debugMode) { // Debug mode + [sFIRLoggerUserDefaults setBool:YES forKey:kFIRPersistedDebugModeKey]; + forceDebugMode = YES; + } + GULLoggerInitializeASL(); + if (overrideSTDERR) { + GULLoggerEnableSTDERR(); + } + if (forceDebugMode) { + GULLoggerForceDebug(); + } + }); +} + +__attribute__((no_sanitize("thread"))) void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode) { + sFIRAnalyticsDebugMode = analyticsDebugMode; +} + +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel) { + FIRLoggerInitializeASL(); + GULSetLoggerLevel((GULLoggerLevel)loggerLevel); +} + +#ifdef DEBUG +void FIRResetLogger() { + extern void GULResetLogger(void); + sFIRLoggerOnceToken = 0; + [sFIRLoggerUserDefaults removeObjectForKey:kFIRPersistedDebugModeKey]; + sFIRLoggerUserDefaults = nil; + GULResetLogger(); +} + +void FIRSetLoggerUserDefaults(NSUserDefaults *defaults) { + sFIRLoggerUserDefaults = defaults; +} +#endif + +/** + * Check if the level is high enough to be loggable. + * + * Analytics can override the log level with an intentional race condition. + * Add the attribute to get a clean thread sanitizer run. + */ +__attribute__((no_sanitize("thread"))) BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, + BOOL analyticsComponent) { + FIRLoggerInitializeASL(); + if (sFIRAnalyticsDebugMode && analyticsComponent) { + return YES; + } + return GULIsLoggableLevel((GULLoggerLevel)loggerLevel); +} + +void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + FIRLoggerInitializeASL(); + GULLogBasic((GULLoggerLevel)level, service, + sFIRAnalyticsDebugMode && [kFIRLoggerAnalytics isEqualToString:service], messageCode, + message, args_ptr); +} + +/** + * Generates the logging functions using macros. + * + * Calling FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure blah failed. + * Calling FIRLogDebug(kFIRLoggerCore, @"I-COR000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [Firebase/Core][I-COR000001] Configure succeed. + */ +#define FIR_LOGGING_FUNCTION(level) \ + void FIRLog##level(FIRLoggerService service, NSString *messageCode, NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + FIRLogBasic(FIRLoggerLevel##level, service, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +FIR_LOGGING_FUNCTION(Error) +FIR_LOGGING_FUNCTION(Warning) +FIR_LOGGING_FUNCTION(Notice) +FIR_LOGGING_FUNCTION(Info) +FIR_LOGGING_FUNCTION(Debug) + +#undef FIR_MAKE_LOGGER + +#pragma mark - FIRLoggerWrapper + +@implementation FIRLoggerWrapper + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + FIRLogBasic(level, service, messageCode, message, args); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m new file mode 100644 index 0000000..d185330 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIROptions.m @@ -0,0 +1,490 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseCore/Sources/FIRBundleUtil.h" +#import "FirebaseCore/Sources/FIRVersion.h" +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" + +// Keys for the strings in the plist file. +NSString *const kFIRAPIKey = @"API_KEY"; +NSString *const kFIRTrackingID = @"TRACKING_ID"; +NSString *const kFIRGoogleAppID = @"GOOGLE_APP_ID"; +NSString *const kFIRClientID = @"CLIENT_ID"; +NSString *const kFIRGCMSenderID = @"GCM_SENDER_ID"; +NSString *const kFIRAndroidClientID = @"ANDROID_CLIENT_ID"; +NSString *const kFIRDatabaseURL = @"DATABASE_URL"; +NSString *const kFIRStorageBucket = @"STORAGE_BUCKET"; +// The key to locate the expected bundle identifier in the plist file. +NSString *const kFIRBundleID = @"BUNDLE_ID"; +// The key to locate the project identifier in the plist file. +NSString *const kFIRProjectID = @"PROJECT_ID"; + +NSString *const kFIRIsMeasurementEnabled = @"IS_MEASUREMENT_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionEnabled = @"FIREBASE_ANALYTICS_COLLECTION_ENABLED"; +NSString *const kFIRIsAnalyticsCollectionDeactivated = @"FIREBASE_ANALYTICS_COLLECTION_DEACTIVATED"; + +NSString *const kFIRIsAnalyticsEnabled = @"IS_ANALYTICS_ENABLED"; +NSString *const kFIRIsSignInEnabled = @"IS_SIGNIN_ENABLED"; + +// Library version ID formatted like: +// @"5" // Major version (one or more digits) +// @"04" // Minor version (exactly 2 digits) +// @"01" // Build number (exactly 2 digits) +// @"000"; // Fixed "000" +NSString *kFIRLibraryVersionID; + +// Plist file name. +NSString *const kServiceInfoFileName = @"GoogleService-Info"; +// Plist file type. +NSString *const kServiceInfoFileType = @"plist"; + +// Exception raised from attempting to modify a FIROptions after it's been copied to a FIRApp. +NSString *const kFIRExceptionBadModification = + @"Attempted to modify options after it's set on FIRApp. Please modify all properties before " + @"initializing FIRApp."; + +@interface FIROptions () + +/** + * This property maintains the actual configuration key-value pairs. + */ +@property(nonatomic, readwrite) NSMutableDictionary *optionsDictionary; + +/** + * Calls `analyticsOptionsDictionaryWithInfoDictionary:` using [NSBundle mainBundle].infoDictionary. + * It combines analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the main plist override values from the GoogleService-Info.plist. + */ +@property(nonatomic, readonly) NSDictionary *analyticsOptionsDictionary; + +/** + * Combination of analytics options from both the infoDictionary and the GoogleService-Info.plist. + * Values which are present in the infoDictionary override values from the GoogleService-Info.plist. + */ +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary; + +/** + * Throw exception if editing is locked when attempting to modify an option. + */ +- (void)checkEditingLocked; + +@end + +@implementation FIROptions { + /// Backing variable for self.analyticsOptionsDictionary. + NSDictionary *_analyticsOptionsDictionary; +} + +static FIROptions *sDefaultOptions = nil; +static NSDictionary *sDefaultOptionsDictionary = nil; + +#pragma mark - Public only for internal class methods + ++ (FIROptions *)defaultOptions { + if (sDefaultOptions != nil) { + return sDefaultOptions; + } + + NSDictionary *defaultOptionsDictionary = [self defaultOptionsDictionary]; + if (defaultOptionsDictionary == nil) { + return nil; + } + + sDefaultOptions = [[FIROptions alloc] initInternalWithOptionsDictionary:defaultOptionsDictionary]; + return sDefaultOptions; +} + +#pragma mark - Private class methods + ++ (NSDictionary *)defaultOptionsDictionary { + if (sDefaultOptionsDictionary != nil) { + return sDefaultOptionsDictionary; + } + NSString *plistFilePath = [FIROptions plistFilePathWithName:kServiceInfoFileName]; + if (plistFilePath == nil) { + return nil; + } + sDefaultOptionsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFilePath]; + if (sDefaultOptionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000011", + @"The configuration file is not a dictionary: " + @"'%@.%@'.", + kServiceInfoFileName, kServiceInfoFileType); + } + return sDefaultOptionsDictionary; +} + +// Returns the path of the plist file with a given file name. ++ (NSString *)plistFilePathWithName:(NSString *)fileName { + NSArray *bundles = [FIRBundleUtil relevantBundles]; + NSString *plistFilePath = + [FIRBundleUtil optionsDictionaryPathWithResourceName:fileName + andFileType:kServiceInfoFileType + inBundles:bundles]; + if (plistFilePath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000012", @"Could not locate configuration file: '%@.%@'.", + fileName, kServiceInfoFileType); + } + return plistFilePath; +} + ++ (void)resetDefaultOptions { + sDefaultOptions = nil; + sDefaultOptionsDictionary = nil; +} + +#pragma mark - Private instance methods + +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)optionsDictionary { + self = [super init]; + if (self) { + _optionsDictionary = [optionsDictionary mutableCopy]; + _usingOptionsFromDefaultPlist = YES; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + FIROptions *newOptions = [[[self class] allocWithZone:zone] init]; + if (newOptions) { + newOptions.optionsDictionary = self.optionsDictionary; + newOptions.deepLinkURLScheme = self.deepLinkURLScheme; + newOptions.appGroupID = self.appGroupID; + newOptions.editingLocked = self.isEditingLocked; + newOptions.usingOptionsFromDefaultPlist = self.usingOptionsFromDefaultPlist; + } + return newOptions; +} + +#pragma mark - Public instance methods + +- (instancetype)initWithContentsOfFile:(NSString *)plistPath { + self = [super init]; + if (self) { + if (plistPath == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000013", @"The plist file path is nil."); + return nil; + } + _optionsDictionary = [[NSDictionary dictionaryWithContentsOfFile:plistPath] mutableCopy]; + if (_optionsDictionary == nil) { + FIRLogError(kFIRLoggerCore, @"I-COR000014", + @"The configuration file at %@ does not exist or " + @"is not a well-formed plist file.", + plistPath); + return nil; + } + // TODO: Do we want to validate the dictionary here? It says we do that already in + // the public header. + } + return self; +} + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID GCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + NSMutableDictionary *mutableOptionsDict = [NSMutableDictionary dictionary]; + [mutableOptionsDict setValue:googleAppID forKey:kFIRGoogleAppID]; + [mutableOptionsDict setValue:GCMSenderID forKey:kFIRGCMSenderID]; + [mutableOptionsDict setValue:[[NSBundle mainBundle] bundleIdentifier] forKey:kFIRBundleID]; + self.optionsDictionary = mutableOptionsDict; + } + return self; +} + +- (NSString *)APIKey { + return self.optionsDictionary[kFIRAPIKey]; +} + +- (void)checkEditingLocked { + if (self.isEditingLocked) { + [NSException raise:kFirebaseCoreErrorDomain format:kFIRExceptionBadModification]; + } +} + +- (void)setAPIKey:(NSString *)APIKey { + [self checkEditingLocked]; + _optionsDictionary[kFIRAPIKey] = [APIKey copy]; +} + +- (NSString *)clientID { + return self.optionsDictionary[kFIRClientID]; +} + +- (void)setClientID:(NSString *)clientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRClientID] = [clientID copy]; +} + +- (NSString *)trackingID { + return self.optionsDictionary[kFIRTrackingID]; +} + +- (void)setTrackingID:(NSString *)trackingID { + [self checkEditingLocked]; + _optionsDictionary[kFIRTrackingID] = [trackingID copy]; +} + +- (NSString *)GCMSenderID { + return self.optionsDictionary[kFIRGCMSenderID]; +} + +- (void)setGCMSenderID:(NSString *)GCMSenderID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGCMSenderID] = [GCMSenderID copy]; +} + +- (NSString *)projectID { + return self.optionsDictionary[kFIRProjectID]; +} + +- (void)setProjectID:(NSString *)projectID { + [self checkEditingLocked]; + _optionsDictionary[kFIRProjectID] = [projectID copy]; +} + +- (NSString *)androidClientID { + return self.optionsDictionary[kFIRAndroidClientID]; +} + +- (void)setAndroidClientID:(NSString *)androidClientID { + [self checkEditingLocked]; + _optionsDictionary[kFIRAndroidClientID] = [androidClientID copy]; +} + +- (NSString *)googleAppID { + return self.optionsDictionary[kFIRGoogleAppID]; +} + +- (void)setGoogleAppID:(NSString *)googleAppID { + [self checkEditingLocked]; + _optionsDictionary[kFIRGoogleAppID] = [googleAppID copy]; +} + +- (NSString *)libraryVersionID { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The unit tests are set up to catch anything that does not properly convert. + NSString *version = [NSString stringWithUTF8String:FIRCoreVersionString]; + NSArray *components = [version componentsSeparatedByString:@"."]; + NSString *major = [components objectAtIndex:0]; + NSString *minor = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:1] intValue]]; + NSString *patch = [NSString stringWithFormat:@"%02d", [[components objectAtIndex:2] intValue]]; + kFIRLibraryVersionID = [NSString stringWithFormat:@"%@%@%@000", major, minor, patch]; + }); + return kFIRLibraryVersionID; +} + +- (void)setLibraryVersionID:(NSString *)libraryVersionID { + _optionsDictionary[kFIRLibraryVersionID] = [libraryVersionID copy]; +} + +- (NSString *)databaseURL { + return self.optionsDictionary[kFIRDatabaseURL]; +} + +- (void)setDatabaseURL:(NSString *)databaseURL { + [self checkEditingLocked]; + + _optionsDictionary[kFIRDatabaseURL] = [databaseURL copy]; +} + +- (NSString *)storageBucket { + return self.optionsDictionary[kFIRStorageBucket]; +} + +- (void)setStorageBucket:(NSString *)storageBucket { + [self checkEditingLocked]; + _optionsDictionary[kFIRStorageBucket] = [storageBucket copy]; +} + +- (void)setDeepLinkURLScheme:(NSString *)deepLinkURLScheme { + [self checkEditingLocked]; + _deepLinkURLScheme = [deepLinkURLScheme copy]; +} + +- (NSString *)bundleID { + return self.optionsDictionary[kFIRBundleID]; +} + +- (void)setBundleID:(NSString *)bundleID { + [self checkEditingLocked]; + _optionsDictionary[kFIRBundleID] = [bundleID copy]; +} + +- (void)setAppGroupID:(NSString *)appGroupID { + [self checkEditingLocked]; + _appGroupID = [appGroupID copy]; +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + if (!object || ![object isKindOfClass:[FIROptions class]]) { + return NO; + } + + return [self isEqualToOptions:(FIROptions *)object]; +} + +- (BOOL)isEqualToOptions:(FIROptions *)options { + // Skip any non-FIROptions classes. + if (![options isKindOfClass:[FIROptions class]]) { + return NO; + } + + // Check the internal dictionary and custom properties for differences. + if (![options.optionsDictionary isEqualToDictionary:self.optionsDictionary]) { + return NO; + } + + // Validate extra properties not contained in the dictionary. Only validate it if one of the + // objects has the property set. + if ((options.deepLinkURLScheme != nil || self.deepLinkURLScheme != nil) && + ![options.deepLinkURLScheme isEqualToString:self.deepLinkURLScheme]) { + return NO; + } + + if ((options.appGroupID != nil || self.appGroupID != nil) && + ![options.appGroupID isEqualToString:self.appGroupID]) { + return NO; + } + + // Validate the Analytics options haven't changed with the Info.plist. + if (![options.analyticsOptionsDictionary isEqualToDictionary:self.analyticsOptionsDictionary]) { + return NO; + } + + // We don't care about the `editingLocked` or `usingOptionsFromDefaultPlist` properties since + // those relate to lifecycle and construction, we only care if the contents of the options + // themselves are equal. + return YES; +} + +- (NSUInteger)hash { + // This is strongly recommended for any object that implements a custom `isEqual:` method to + // ensure that dictionary and set behavior matches other `isEqual:` checks. + // Note: `self.analyticsOptionsDictionary` was left out here since it solely relies on the + // contents of the main bundle's `Info.plist`. We should avoid reading that file and the contents + // should be identical. + return self.optionsDictionary.hash ^ self.deepLinkURLScheme.hash ^ self.appGroupID.hash; +} + +#pragma mark - Internal instance methods + +- (NSDictionary *)analyticsOptionsDictionaryWithInfoDictionary:(NSDictionary *)infoDictionary { + if (_analyticsOptionsDictionary == nil) { + NSMutableDictionary *tempAnalyticsOptions = [[NSMutableDictionary alloc] init]; + NSArray *measurementKeys = @[ + kFIRIsMeasurementEnabled, kFIRIsAnalyticsCollectionEnabled, + kFIRIsAnalyticsCollectionDeactivated + ]; + for (NSString *key in measurementKeys) { + id value = infoDictionary[key] ?: self.optionsDictionary[key] ?: nil; + if (!value) { + continue; + } + tempAnalyticsOptions[key] = value; + } + _analyticsOptionsDictionary = tempAnalyticsOptions; + } + return _analyticsOptionsDictionary; +} + +- (NSDictionary *)analyticsOptionsDictionary { + return [self analyticsOptionsDictionaryWithInfoDictionary:[NSBundle mainBundle].infoDictionary]; +} + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. This uses the old plist flag IS_MEASUREMENT_ENABLED, which should still + * be supported. + */ +- (BOOL)isMeasurementEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (value == nil) { + // TODO: This could probably be cleaned up since FIROptions shouldn't know about FIRApp or have + // to check if it's the default app. The FIROptions instance can't be modified after + // `+configure` is called, so it's not a good place to copy it either in case the flag is + // changed at runtime. + + // If no values are set for Analytics, fall back to the global collection switch in FIRApp. + // Analytics only supports the default FIRApp, so check that first. + if (![FIRApp isDefaultAppConfigured]) { + return NO; + } + + // Fall back to the default app's collection switch when the key is not in the dictionary. + return [FIRApp defaultApp].isDataCollectionDefaultEnabled; + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionExplicitlySet { + // If it's de-activated, it classifies as explicity set. If not, it's not a good enough indication + // that the developer wants FirebaseAnalytics enabled so continue checking. + if (self.isAnalyticsCollectionDeactivated) { + return YES; + } + + // Check if the current Analytics flag is set. + id collectionEnabledObject = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (collectionEnabledObject && [collectionEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // Check if the old measurement flag is set. + id measurementEnabledObject = self.analyticsOptionsDictionary[kFIRIsMeasurementEnabled]; + if (measurementEnabledObject && [measurementEnabledObject isKindOfClass:[NSNumber class]]) { + // It doesn't matter what the value is, it's explicitly set. + return YES; + } + + // No flags are set to explicitly enable or disable FirebaseAnalytics. + return NO; +} + +- (BOOL)isAnalyticsCollectionEnabled { + if (self.isAnalyticsCollectionDeactivated) { + return NO; + } + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionEnabled]; + if (value == nil) { + return self.isMeasurementEnabled; // Fall back to older plist flag. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsCollectionDeactivated { + NSNumber *value = self.analyticsOptionsDictionary[kFIRIsAnalyticsCollectionDeactivated]; + if (value == nil) { + return NO; // Analytics Collection is not deactivated when the key is not in the dictionary. + } + return [value boolValue]; +} + +- (BOOL)isAnalyticsEnabled { + return [self.optionsDictionary[kFIRIsAnalyticsEnabled] boolValue]; +} + +- (BOOL)isSignInEnabled { + return [self.optionsDictionary[kFIRIsSignInEnabled] boolValue]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h new file mode 100644 index 0000000..226efb1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The version of the Firebase SDK. */ +FOUNDATION_EXPORT const char *const FIRVersionString; + +/** The version of the FirebaseCore Component. */ +FOUNDATION_EXPORT const char *const FIRCoreVersionString; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m new file mode 100644 index 0000000..ec0f6ba --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/FIRVersion.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_VERSION +#error "Firebase_VERSION is not defined: add -DFirebase_VERSION=... to the build invocation" +#endif + +#ifndef FIRCore_VERSION +#error "FIRCore_VERSION is not defined: add -DFIRCore_VERSION=... to the build invocation" +#endif + +// The following two macros supply the incantation so that the C +// preprocessor does not try to parse the version as a floating +// point number. See +// https://www.guyrutenberg.com/2008/12/20/expanding-macros-into-string-constants-in-c/ +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRVersionString = (const char *const)STR(Firebase_VERSION); +const char *const FIRCoreVersionString = (const char *const)STR(FIRCore_VERSION); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h new file mode 100644 index 0000000..6429ac7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// Values stored in analyticsEnabledState. Never alter these constants since they must match with +/// values persisted to disk. +typedef NS_ENUM(int64_t, FIRAnalyticsEnabledState) { + // 0 is the default value for keys not found stored in persisted config, so it cannot represent + // kFIRAnalyticsEnabledStateSetNo. It must represent kFIRAnalyticsEnabledStateNotSet. + kFIRAnalyticsEnabledStateNotSet = 0, + kFIRAnalyticsEnabledStateSetYes = 1, + kFIRAnalyticsEnabledStateSetNo = 2, +}; + +/// The user defaults key for the persisted measurementEnabledState value. FIRAPersistedConfig reads +/// measurementEnabledState using this same key. +static NSString *const kFIRAPersistedConfigMeasurementEnabledStateKey = + @"/google/measurement/measurement_enabled_state"; + +static NSString *const kFIRAnalyticsConfigurationSetEnabledNotification = + @"FIRAnalyticsConfigurationSetEnabledNotification"; +static NSString *const kFIRAnalyticsConfigurationSetMinimumSessionIntervalNotification = + @"FIRAnalyticsConfigurationSetMinimumSessionIntervalNotification"; +static NSString *const kFIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification = + @"FIRAnalyticsConfigurationSetSessionTimeoutIntervalNotification"; + +@interface FIRAnalyticsConfiguration : NSObject + +/// Returns the shared instance of FIRAnalyticsConfiguration. ++ (FIRAnalyticsConfiguration *)sharedInstance; + +// Sets whether analytics collection is enabled for this app on this device. This setting is +// persisted across app sessions. By default it is enabled. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled; + +/// Sets whether analytics collection is enabled for this app on this device, and a flag to persist +/// the value or not. The setting should not be persisted if being set by the global data collection +/// flag. +- (void)setAnalyticsCollectionEnabled:(BOOL)analyticsCollectionEnabled + persistSetting:(BOOL)shouldPersist; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h new file mode 100644 index 0000000..3fc69c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// TODO: Remove this once Auth moves over to Core's instance registration system. +/** @class FIRAppAssociationRegistration + @brief Manages object associations as a singleton-dependent: At most one object is + registered for any given host/key pair, and the object shall be created on-the-fly when + asked for. + */ +@interface FIRAppAssociationRegistration : NSObject + +/** @fn registeredObjectWithHost:key:creationBlock: + @brief Retrieves the registered object with a particular host and key. + @param host The host object. + @param key The key to specify the registered object on the host. + @param creationBlock The block to return the object to be registered if not already. + The block is executed immediately before this method returns if it is executed at all. + It can also be executed multiple times across different method invocations if previous + execution of the block returns @c nil. + @return The registered object for the host/key pair, or @c nil if no object is registered + and @c creationBlock returns @c nil. + @remarks The method is thread-safe but non-reentrant in the sense that attempting to call this + method again within the @c creationBlock with the same host/key pair raises an exception. + The registered object is retained by the host. + */ ++ (nullable ObjectType)registeredObjectWithHost:(id)host + key:(NSString *)key + creationBlock:(ObjectType _Nullable (^)(void))creationBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 0000000..ad1a186 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,162 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 0000000..cb51ee7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 0000000..8dfab9c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h new file mode 100644 index 0000000..2b77981 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentContainerInternal.h @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRComponentContainer (Private) + +/// Initializes a container for a given app. This should only be called by the app itself. +- (instancetype)initWithApp:(FIRApp *)app; + +/// Retrieves an instance that conforms to the specified protocol. This will return `nil` if the +/// protocol wasn't registered, or if the instance couldn't be instantiated for the provided app. +- (nullable id)instanceForProtocol:(Protocol *)protocol NS_SWIFT_NAME(instance(for:)); + +/// Instantiates all the components that have registered as "eager" after initialization. +- (void)instantiateEagerComponents; + +/// Remove all of the cached instances stored and allow them to clean up after themselves. +- (void)removeAllCachedInstances; + +/// Register a class to provide components for the interoperability system. The class should conform +/// to `FIRComponentRegistrant` and provide an array of `FIRComponent` objects. ++ (void)registerAsComponentRegistrant:(Class)klass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 0000000..6f2aca7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h new file mode 100644 index 0000000..0d1a36f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRConfigurationInternal.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRAnalyticsConfiguration; + +@interface FIRConfiguration () + +/** + * The configuration class for Firebase Analytics. This should be removed once the logic for + * enabling and disabling Analytics is moved to Analytics. + */ +@property(nonatomic, readwrite) FIRAnalyticsConfiguration *analyticsConfiguration; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 0000000..76c0c05 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 0000000..46e9b7e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h new file mode 100644 index 0000000..ac5ef2c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRDiagnosticsData.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Implements the FIRCoreDiagnosticsData protocol to log diagnostics data. */ +@interface FIRDiagnosticsData : NSObject + +/** Inserts values into the diagnosticObjects dictionary if the value isn't nil. + * + * @param value The value to insert if it's not nil. + * @param key The key to associate it with. + */ +- (void)insertValue:(nullable id)value forKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 0000000..f77b3d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 0000000..19e4732 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 0000000..bfff73e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 0000000..af9d968 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import + +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 0000000..548e389 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,151 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 0000000..0660a3c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,114 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h new file mode 100644 index 0000000..e0dd6d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRApp.h @@ -0,0 +1,127 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** A block that takes a BOOL and has no return value. */ +typedef void (^FIRAppVoidBoolCallback)(BOOL success) NS_SWIFT_NAME(FirebaseAppVoidBoolCallback); + +/** + * The entry point of Firebase SDKs. + * + * Initialize and configure FIRApp using +[FIRApp configure] + * or other customized ways as shown below. + * + * The logging system has two modes: default mode and debug mode. In default mode, only logs with + * log level Notice, Warning and Error will be sent to device. In debug mode, all logs will be sent + * to device. The log levels that Firebase uses are consistent with the ASL log levels. + * + * Enable debug mode by passing the -FIRDebugEnabled argument to the application. You can add this + * argument in the application's Xcode scheme. When debug mode is enabled via -FIRDebugEnabled, + * further executions of the application will also be in debug mode. In order to return to default + * mode, you must explicitly disable the debug mode with the application argument -FIRDebugDisabled. + * + * It is also possible to change the default logging level in code by calling setLoggerLevel: on + * the FIRConfiguration interface. + */ +NS_SWIFT_NAME(FirebaseApp) +@interface FIRApp : NSObject + +/** + * Configures a default Firebase app. Raises an exception if any configuration step fails. The + * default app is named "__FIRAPP_DEFAULT". This method should be called after the app is launched + * and before using Firebase services. This method is thread safe and contains synchronous file I/O + * (reading GoogleService-Info.plist from disk). + */ ++ (void)configure; + +/** + * Configures the default Firebase app with the provided options. The default app is named + * "__FIRAPP_DEFAULT". Raises an exception if any configuration step fails. This method is thread + * safe. + * + * @param options The Firebase application options used to configure the service. + */ ++ (void)configureWithOptions:(FIROptions *)options NS_SWIFT_NAME(configure(options:)); + +/** + * Configures a Firebase app with the given name and options. Raises an exception if any + * configuration step fails. This method is thread safe. + * + * @param name The application's name given by the developer. The name should should only contain + Letters, Numbers and Underscore. + * @param options The Firebase application options used to configure the services. + */ +// clang-format off ++ (void)configureWithName:(NSString *)name + options:(FIROptions *)options NS_SWIFT_NAME(configure(name:options:)); +// clang-format on + +/** + * Returns the default app, or nil if the default app does not exist. + */ ++ (nullable FIRApp *)defaultApp NS_SWIFT_NAME(app()); + +/** + * Returns a previously created FIRApp instance with the given name, or nil if no such app exists. + * This method is thread safe. + */ ++ (nullable FIRApp *)appNamed:(NSString *)name NS_SWIFT_NAME(app(name:)); + +/** + * Returns the set of all extant FIRApp instances, or nil if there are no FIRApp instances. This + * method is thread safe. + */ +@property(class, readonly, nullable) NSDictionary *allApps; + +/** + * Cleans up the current FIRApp, freeing associated data and returning its name to the pool for + * future use. This method is thread safe. + */ +- (void)deleteApp:(FIRAppVoidBoolCallback)completion; + +/** + * FIRApp instances should not be initialized directly. Call +[FIRApp configure], + * +[FIRApp configureWithOptions:], or +[FIRApp configureWithNames:options:] directly. + */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Gets the name of this app. + */ +@property(nonatomic, copy, readonly) NSString *name; + +/** + * Gets a copy of the options for this app. These are non-modifiable. + */ +@property(nonatomic, copy, readonly) FIROptions *options; + +/** + * Gets or sets whether automatic data collection is enabled for all products. Defaults to `YES` + * unless `FirebaseDataCollectionDefaultEnabled` is set to `NO` in your app's Info.plist. This value + * is persisted across runs of the app so that it can be set once when users have consented to + * collection. + */ +@property(nonatomic, readwrite, getter=isDataCollectionDefaultEnabled) + BOOL dataCollectionDefaultEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h new file mode 100644 index 0000000..8de3b07 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRConfiguration.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This interface provides global level properties that the developer can tweak. + */ +NS_SWIFT_NAME(FirebaseConfiguration) +@interface FIRConfiguration : NSObject + +/** Returns the shared configuration object. */ +@property(class, nonatomic, readonly) FIRConfiguration *sharedInstance NS_SWIFT_NAME(shared); + +/** + * Sets the logging level for internal Firebase logging. Firebase will only log messages + * that are logged at or below loggerLevel. The messages are logged both to the Xcode + * console and to the device's log. Note that if an app is running from AppStore, it will + * never log above FIRLoggerLevelNotice even if loggerLevel is set to a higher (more verbose) + * setting. + * + * @param loggerLevel The maximum logging level. The default level is set to FIRLoggerLevelNotice. + */ +- (void)setLoggerLevel:(FIRLoggerLevel)loggerLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h new file mode 100644 index 0000000..dca3aa0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIRLoggerLevel.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Note that importing GULLoggerLevel.h will lead to a non-modular header +// import error. + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, FIRLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + FIRLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + FIRLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + FIRLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + FIRLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + FIRLoggerLevelDebug = 7, + /** Minimum log level. */ + FIRLoggerLevelMin = FIRLoggerLevelError, + /** Maximum log level. */ + FIRLoggerLevelMax = FIRLoggerLevelDebug +} NS_SWIFT_NAME(FirebaseLoggerLevel); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h new file mode 100644 index 0000000..67fbe5b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FIROptions.h @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class provides constant fields of Google APIs. + */ +NS_SWIFT_NAME(FirebaseOptions) +@interface FIROptions : NSObject + +/** + * Returns the default options. The first time this is called it synchronously reads + * GoogleService-Info.plist from disk. + */ ++ (nullable FIROptions *)defaultOptions NS_SWIFT_NAME(defaultOptions()); + +/** + * An iOS API key used for authenticating requests from your app, e.g. + * @"AIzaSyDdVgKwhZl0sTTTLZ7iTmt1r3N2cJLnaDk", used to identify your app to Google servers. + */ +@property(nonatomic, copy, nullable) NSString *APIKey NS_SWIFT_NAME(apiKey); + +/** + * The bundle ID for the application. Defaults to `[[NSBundle mainBundle] bundleID]` when not set + * manually or in a plist. + */ +@property(nonatomic, copy) NSString *bundleID; + +/** + * The OAuth2 client ID for iOS application used to authenticate Google users, for example + * @"12345.apps.googleusercontent.com", used for signing in with Google. + */ +@property(nonatomic, copy, nullable) NSString *clientID; + +/** + * The tracking ID for Google Analytics, e.g. @"UA-12345678-1", used to configure Google Analytics. + */ +@property(nonatomic, copy, nullable) NSString *trackingID; + +/** + * The Project Number from the Google Developer's console, for example @"012345678901", used to + * configure Google Cloud Messaging. + */ +@property(nonatomic, copy) NSString *GCMSenderID NS_SWIFT_NAME(gcmSenderID); + +/** + * The Project ID from the Firebase console, for example @"abc-xyz-123". + */ +@property(nonatomic, copy, nullable) NSString *projectID; + +/** + * The Android client ID used in Google AppInvite when an iOS app has its Android version, for + * example @"12345.apps.googleusercontent.com". + */ +@property(nonatomic, copy, nullable) NSString *androidClientID; + +/** + * The Google App ID that is used to uniquely identify an instance of an app. + */ +@property(nonatomic, copy) NSString *googleAppID; + +/** + * The database root URL, e.g. @"http://abc-xyz-123.firebaseio.com". + */ +@property(nonatomic, copy, nullable) NSString *databaseURL; + +/** + * The URL scheme used to set up Durable Deep Link service. + */ +@property(nonatomic, copy, nullable) NSString *deepLinkURLScheme; + +/** + * The Google Cloud Storage bucket name, e.g. @"abc-xyz-123.storage.firebase.com". + */ +@property(nonatomic, copy, nullable) NSString *storageBucket; + +/** + * The App Group identifier to share data between the application and the application extensions. + * The App Group must be configured in the application and on the Apple Developer Portal. Default + * value `nil`. + */ +@property(nonatomic, copy, nullable) NSString *appGroupID; + +/** + * Initializes a customized instance of FIROptions from the file at the given plist file path. This + * will read the file synchronously from disk. + * For example, + * NSString *filePath = + * [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"]; + * FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; + * Returns nil if the plist file does not exist or is invalid. + */ +- (nullable instancetype)initWithContentsOfFile:(NSString *)plistPath; + +/** + * Initializes a customized instance of FIROptions with required fields. Use the mutable properties + * to modify fields for configuring specific services. + */ +// clang-format off +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + GCMSenderID:(NSString *)GCMSenderID + NS_SWIFT_NAME(init(googleAppID:gcmSenderID:)); +// clang-format on + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h new file mode 100644 index 0000000..95119ae --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/FirebaseCore/Sources/Public/FirebaseCore.h @@ -0,0 +1,20 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseCore/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCore/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseCore/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCore/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m new file mode 100644 index 0000000..bb0326b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m @@ -0,0 +1,641 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#include + +#import +#import +#import +#import + +#import +#import +#import + +#import +#import + +#import +#import +#import + +#import "FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h" + +/** The logger service string to use when printing to the console. */ +static GULLoggerService kFIRCoreDiagnostics = @"[FirebaseCoreDiagnostics/FIRCoreDiagnostics]"; + +#ifdef FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = YES; +#else // FIREBASE_BUILD_ZIP_FILE +static BOOL kUsingZipFile = NO; +#endif // FIREBASE_BUILD_ZIP_FILE + +#ifdef FIREBASE_BUILD_CARTHAGE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE +#elif FIREBASE_BUILD_ZIP_FILE +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE +#else +#define kDeploymentType logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS +#endif + +static NSString *const kFIRServiceMLVisionOnDeviceAutoML = @"MLVisionOnDeviceAutoML"; +static NSString *const kFIRServiceMLVisionOnDeviceFace = @"MLVisionOnDeviceFace"; +static NSString *const kFIRServiceMLVisionOnDeviceBarcode = @"MLVisionOnDeviceBarcode"; +static NSString *const kFIRServiceMLVisionOnDeviceText = @"MLVisionOnDeviceText"; +static NSString *const kFIRServiceMLVisionOnDeviceLabel = @"MLVisionOnDeviceLabel"; +static NSString *const kFIRServiceMLVisionOnDeviceObjectDetection = + @"MLVisionOnDeviceObjectDetection"; +static NSString *const kFIRServiceMLModelInterpreter = @"MLModelInterpreter"; + +static NSString *const kFIRServiceAdMob = @"AdMob"; +static NSString *const kFIRServiceAuth = @"Auth"; +static NSString *const kFIRServiceAuthUI = @"AuthUI"; +static NSString *const kFIRServiceCrash = @"Crash"; +static NSString *const kFIRServiceDatabase = @"Database"; +static NSString *const kFIRServiceDynamicLinks = @"DynamicLinks"; +static NSString *const kFIRServiceFirestore = @"Firestore"; +static NSString *const kFIRServiceFunctions = @"Functions"; +static NSString *const kFIRServiceIAM = @"InAppMessaging"; +static NSString *const kFIRServiceInstanceID = @"InstanceID"; +static NSString *const kFIRServiceInvites = @"Invites"; +static NSString *const kFIRServiceMessaging = @"Messaging"; +static NSString *const kFIRServiceMeasurement = @"Measurement"; +static NSString *const kFIRServicePerformance = @"Performance"; +static NSString *const kFIRServiceRemoteConfig = @"RemoteConfig"; +static NSString *const kFIRServiceStorage = @"Storage"; +static NSString *const kGGLServiceAnalytics = @"Analytics"; +static NSString *const kGGLServiceSignIn = @"SignIn"; +static NSString *const kFIRAppDiagnosticsConfigurationTypeKey = + @"FIRAppDiagnosticsConfigurationTypeKey"; +static NSString *const kFIRAppDiagnosticsFIRAppKey = @"FIRAppDiagnosticsFIRAppKey"; +static NSString *const kFIRAppDiagnosticsSDKNameKey = @"FIRAppDiagnosticsSDKNameKey"; +static NSString *const kFIRAppDiagnosticsSDKVersionKey = @"FIRAppDiagnosticsSDKVersionKey"; +static NSString *const kFIRCoreDiagnosticsHeartbeatTag = @"FIRCoreDiagnostics"; + +/** + * The file name to the recent heartbeat date. + */ +NSString *const kFIRCoreDiagnosticsHeartbeatDateFileName = @"FIREBASE_DIAGNOSTICS_HEARTBEAT_DATE"; + +/** + * @note This should implement the GDTCOREventDataObject protocol, but can't because of + * weak-linking. + */ +@interface FIRCoreDiagnosticsLog : NSObject + +/** The config that will be converted to proto bytes. */ +@property(nonatomic) logs_proto_mobilesdk_ios_ICoreConfiguration config; + +@end + +@implementation FIRCoreDiagnosticsLog + +- (instancetype)initWithConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration)config { + self = [super init]; + if (self) { + _config = config; + } + return self; +} + +// Provided and required by the GDTCOREventDataObject protocol. +- (NSData *)transportBytes { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config)) { + GDTCORLogError(GDTCORMCETransportBytesError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + CFDataSetLength(dataRef, ostream.bytes_written); + + return CFBridgingRelease(dataRef); +} + +- (void)dealloc { + pb_release(logs_proto_mobilesdk_ios_ICoreConfiguration_fields, &_config); +} + +@end + +NS_ASSUME_NONNULL_BEGIN + +/** This class produces a protobuf containing diagnostics and usage data to be logged. */ +@interface FIRCoreDiagnostics : NSObject + +/** The queue on which all diagnostics collection will occur. */ +@property(nonatomic, readonly) dispatch_queue_t diagnosticsQueue; + +/** The transport object used to send data. */ +@property(nonatomic, readonly) GDTCORTransport *transport; + +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) GULHeartbeatDateStorage *heartbeatDateStorage; + +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRCoreDiagnostics + ++ (instancetype)sharedInstance { + static FIRCoreDiagnostics *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRCoreDiagnostics alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"137" + transformers:nil + target:kGDTCORTargetFLL]; + + GULHeartbeatDateStorage *dateStorage = + [[GULHeartbeatDateStorage alloc] initWithFileName:kFIRCoreDiagnosticsHeartbeatDateFileName]; + + return [self initWithTransport:transport heartbeatDateStorage:dateStorage]; +} + +/** Initializer for unit tests. + * + * @param transport A `GDTCORTransport` instance which that be used to send event. + * @param heartbeatDateStorage An instanse of date storage to track heartbeat sending. + * @return Returns the initialized `FIRCoreDiagnostics` instance. + */ +- (instancetype)initWithTransport:(GDTCORTransport *)transport + heartbeatDateStorage:(GULHeartbeatDateStorage *)heartbeatDateStorage { + self = [super init]; + if (self) { + _diagnosticsQueue = + dispatch_queue_create("com.google.FIRCoreDiagnostics", DISPATCH_QUEUE_SERIAL); + _transport = transport; + _heartbeatDateStorage = heartbeatDateStorage; + } + return self; +} + +#pragma mark - Metadata helpers + +/** Returns the model of iOS device. Sample platform strings are @"iPhone7,1" for iPhone 6 Plus, + * @"iPhone7,2" for iPhone 6, etc. Refer to the Hardware strings at + * https://en.wikipedia.org/wiki/List_of_iOS_devices + * + * @return The device model as an NSString. + */ ++ (NSString *)deviceModel { + static NSString *deviceModel = nil; + if (deviceModel == nil) { + struct utsname systemInfo; + uname(&systemInfo); + deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; + } + return deviceModel; +} + +#pragma mark - nanopb helper functions + +/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param string The string to encode as pb_bytes. + */ +pb_bytes_array_t *FIREncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return FIREncodeData(stringBytes); +} + +/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array. + * + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param data The data to copy into the new bytes array. + */ +pb_bytes_array_t *FIREncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +/** Maps a service string to the representative nanopb enum. + * + * @param serviceString The SDK service string to convert. + * @return The representative nanopb enum. + */ +logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType FIRMapFromServiceStringToTypeEnum( + NSString *serviceString) { + static NSDictionary *serviceStringToTypeEnum; + if (serviceStringToTypeEnum == nil) { + serviceStringToTypeEnum = @{ + kFIRServiceAdMob : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB), + kFIRServiceMessaging : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING), + kFIRServiceMeasurement : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT), + kFIRServiceRemoteConfig : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG), + kFIRServiceDatabase : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE), + kFIRServiceDynamicLinks : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS), + kFIRServiceAuth : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH), + kFIRServiceAuthUI : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI), + kFIRServiceFirestore : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE), + kFIRServiceFunctions : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS), + kFIRServicePerformance : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE), + kFIRServiceStorage : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE), + kFIRServiceMLVisionOnDeviceAutoML : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML), + kFIRServiceMLVisionOnDeviceFace : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE), + kFIRServiceMLVisionOnDeviceBarcode : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE), + kFIRServiceMLVisionOnDeviceText : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT), + kFIRServiceMLVisionOnDeviceLabel : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL), + kFIRServiceMLVisionOnDeviceObjectDetection : @( + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION), + kFIRServiceMLModelInterpreter : + @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER), + kGGLServiceAnalytics : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS), + kGGLServiceSignIn : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN), + kFIRServiceIAM : @(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING), + }; + } + if (serviceStringToTypeEnum[serviceString] != nil) { + return (int32_t)serviceStringToTypeEnum[serviceString].longLongValue; + } + return logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE; +} + +#pragma mark - Proto population functions + +/** Populates the given proto with data related to an SDK logDiagnostics call from the + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithInfoFromUserInfoParams(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + NSNumber *configurationType = diagnosticObjects[kFIRCDConfigurationTypeKey]; + if (configurationType != nil) { + switch (configurationType.integerValue) { + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE; + config->has_configuration_type = 1; + break; + case logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK: + config->configuration_type = + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK; + config->has_configuration_type = 1; + break; + default: + break; + } + } + + NSString *sdkName = diagnosticObjects[kFIRCDSdkNameKey]; + if (sdkName) { + config->sdk_name = FIRMapFromServiceStringToTypeEnum(sdkName); + config->has_sdk_name = 1; + } + + NSString *version = diagnosticObjects[kFIRCDSdkVersionKey]; + if (version) { + config->sdk_version = FIREncodeString(version); + } +} + +/** Populates the given proto with data from the calling FIRApp using the given + * diagnosticObjects dictionary. + * + * @param config The proto to populate + * @param diagnosticObjects The dictionary of diagnostics objects. + */ +void FIRPopulateProtoWithCommonInfoFromApp(logs_proto_mobilesdk_ios_ICoreConfiguration *config, + NSDictionary *diagnosticObjects) { + config->pod_name = logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE; + config->has_pod_name = 1; + + if (!diagnosticObjects[kFIRCDllAppsCountKey]) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"App count is a required value in the data dict."); + } + config->app_count = (int32_t)[diagnosticObjects[kFIRCDllAppsCountKey] integerValue]; + config->has_app_count = 1; + + NSString *googleAppID = diagnosticObjects[kFIRCDGoogleAppIDKey]; + if (googleAppID.length) { + config->app_id = FIREncodeString(googleAppID); + } + + NSString *bundleID = diagnosticObjects[kFIRCDBundleIDKey]; + if (bundleID.length) { + config->bundle_id = FIREncodeString(bundleID); + } + + NSString *firebaseUserAgent = diagnosticObjects[kFIRCDFirebaseUserAgentKey]; + if (firebaseUserAgent.length) { + config->platform_info = FIREncodeString(firebaseUserAgent); + } + + NSNumber *usingOptionsFromDefaultPlist = diagnosticObjects[kFIRCDUsingOptionsFromDefaultPlistKey]; + if (usingOptionsFromDefaultPlist != nil) { + config->use_default_app = [usingOptionsFromDefaultPlist boolValue]; + config->has_use_default_app = 1; + } + + NSString *libraryVersionID = diagnosticObjects[kFIRCDLibraryVersionIDKey]; + if (libraryVersionID) { + config->icore_version = FIREncodeString(libraryVersionID); + } + + NSString *deviceModel = [FIRCoreDiagnostics deviceModel]; + if (deviceModel.length) { + config->device_model = FIREncodeString(deviceModel); + } + + NSString *osVersion = [GULAppEnvironmentUtil systemVersion]; + if (osVersion.length) { + config->os_version = FIREncodeString(osVersion); + } + + config->using_zip_file = kUsingZipFile; + config->has_using_zip_file = 1; + config->deployment_type = kDeploymentType; + config->has_deployment_type = 1; + config->deployed_in_app_store = [GULAppEnvironmentUtil isFromAppStore]; + config->has_deployed_in_app_store = 1; +} + +/** Populates the given proto with installed services data. + * + * @param config The proto to populate + */ +void FIRPopulateProtoWithInstalledServices(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSMutableArray *sdkServiceInstalledArray = [NSMutableArray array]; + + // AdMob + if (NSClassFromString(@"GADBannerView") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAdMob))]; + } + // CloudMessaging + if (NSClassFromString(@"FIRMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMessaging))]; + } + // RemoteConfig + if (NSClassFromString(@"FIRRemoteConfig") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceRemoteConfig))]; + } + // Measurement/Analtyics + if (NSClassFromString(@"FIRAnalytics") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMeasurement))]; + } + // ML Vision On Device AutoML. + if (NSClassFromString(@"FIRVisionOnDeviceAutoMLImageLabelerOptions") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceAutoML))]; + } + // ML Vision On Device Face. + if (NSClassFromString(@"FIRVisionFaceDetector") != nil && + NSClassFromString(@"GMVFaceDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceFace))]; + } + // ML Vision On Device Barcode. + if (NSClassFromString(@"FIRVisionBarcodeDetector") != nil && + NSClassFromString(@"GMVBarcodeDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceBarcode))]; + } + // ML Vision On Device Text. + if (NSClassFromString(@"FIRVisionTextDetector") != nil && + NSClassFromString(@"GMVTextDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceText))]; + } + // ML Vision On Device Image Label. + if (NSClassFromString(@"FIRVisionLabelDetector") != nil && + NSClassFromString(@"GMVLabelDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceLabel))]; + } + // ML Vision On Device Object. + if (NSClassFromString(@"FIRVisionObjectDetector") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLVisionOnDeviceObjectDetection))]; + } + // ML Model Interpreter + if (NSClassFromString(@"FIRCustomModelInterpreter") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceMLModelInterpreter))]; + } + // Database + if (NSClassFromString(@"FIRDatabase") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDatabase))]; + } + // DynamicDeepLink + if (NSClassFromString(@"FIRDynamicLinks") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceDynamicLinks))]; + } + // Auth + if (NSClassFromString(@"FIRAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuth))]; + } + // AuthUI + if (NSClassFromString(@"FUIAuth") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceAuthUI))]; + } + // Firestore + if (NSClassFromString(@"FIRFirestore") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFirestore))]; + } + // Functions + if (NSClassFromString(@"FIRFunctions") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceFunctions))]; + } + // Performance + if (NSClassFromString(@"FIRPerformance") != nil) { + [sdkServiceInstalledArray + addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServicePerformance))]; + } + // Storage + if (NSClassFromString(@"FIRStorage") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceStorage))]; + } + // SignIn via Google pod + if (NSClassFromString(@"GIDSignIn") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceSignIn))]; + } + // Analytics via Google pod + if (NSClassFromString(@"GAI") != nil && NSClassFromString(@"GGLContext") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kGGLServiceAnalytics))]; + } + + // In-App Messaging + if (NSClassFromString(@"FIRInAppMessaging") != nil) { + [sdkServiceInstalledArray addObject:@(FIRMapFromServiceStringToTypeEnum(kFIRServiceIAM))]; + } + + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *servicesInstalled = + malloc(sizeof(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType) * + sdkServiceInstalledArray.count); + for (NSUInteger i = 0; i < sdkServiceInstalledArray.count; i++) { + NSNumber *typeEnum = sdkServiceInstalledArray[i]; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType serviceType = + (int32_t)typeEnum.integerValue; + servicesInstalled[i] = serviceType; + } + + config->sdk_service_installed = servicesInstalled; + config->sdk_service_installed_count = (int32_t)sdkServiceInstalledArray.count; +} + +/** Populates the proto with the number of linked frameworks. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithNumberOfLinkedFrameworks( + logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + int numFrameworks = -1; // Subtract the app binary itself. + unsigned int numImages; + const char **imageNames = objc_copyImageNames(&numImages); + for (unsigned int i = 0; i < numImages; i++) { + NSString *imageName = [NSString stringWithUTF8String:imageNames[i]]; + if ([imageName rangeOfString:@"System/Library"].length != 0 // Apple .frameworks + || [imageName rangeOfString:@"Developer/Library"].length != 0 // Xcode debug .frameworks + || [imageName rangeOfString:@"usr/lib"].length != 0) { // Public .dylibs + continue; + } + numFrameworks++; + } + free(imageNames); + config->dynamic_framework_count = numFrameworks; + config->has_dynamic_framework_count = 1; +} + +/** Populates the proto with Info.plist values. + * + * @param config The proto to populate. + */ +void FIRPopulateProtoWithInfoPlistValues(logs_proto_mobilesdk_ios_ICoreConfiguration *config) { + NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; + + NSString *xcodeVersion = info[@"DTXcodeBuild"] ?: @""; + NSString *sdkVersion = info[@"DTSDKBuild"] ?: @""; + NSString *combinedVersions = [NSString stringWithFormat:@"%@-%@", xcodeVersion, sdkVersion]; + config->apple_framework_version = FIREncodeString(combinedVersions); + + NSString *minVersion = info[@"MinimumOSVersion"]; + if (minVersion) { + config->min_supported_ios_version = FIREncodeString(minVersion); + } + + // Apps can turn off swizzling in the Info.plist, check if they've explicitly set the value and + // report it. It's enabled by default. + NSNumber *appDelegateSwizzledNum = info[@"FirebaseAppDelegateProxyEnabled"]; + BOOL appDelegateSwizzled = YES; + if ([appDelegateSwizzledNum isKindOfClass:[NSNumber class]]) { + appDelegateSwizzled = [appDelegateSwizzledNum boolValue]; + } + config->swizzling_enabled = appDelegateSwizzled; + config->has_swizzling_enabled = 1; +} + +#pragma mark - FIRCoreDiagnosticsInterop + ++ (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + FIRCoreDiagnostics *diagnostics = [FIRCoreDiagnostics sharedInstance]; + [diagnostics sendDiagnosticsData:diagnosticsData]; +} + +- (void)sendDiagnosticsData:(nonnull id)diagnosticsData { + dispatch_async(self.diagnosticsQueue, ^{ + NSDictionary *diagnosticObjects = diagnosticsData.diagnosticObjects; + NSNumber *isDataCollectionDefaultEnabled = + diagnosticObjects[kFIRCDIsDataCollectionDefaultEnabledKey]; + if (isDataCollectionDefaultEnabled && ![isDataCollectionDefaultEnabled boolValue]) { + return; + } + + // Create the proto. + logs_proto_mobilesdk_ios_ICoreConfiguration icore_config = + logs_proto_mobilesdk_ios_ICoreConfiguration_init_default; + + icore_config.using_gdt = 1; + icore_config.has_using_gdt = 1; + + // Populate the proto with information. + FIRPopulateProtoWithInfoFromUserInfoParams(&icore_config, diagnosticObjects); + FIRPopulateProtoWithCommonInfoFromApp(&icore_config, diagnosticObjects); + FIRPopulateProtoWithInstalledServices(&icore_config); + FIRPopulateProtoWithNumberOfLinkedFrameworks(&icore_config); + FIRPopulateProtoWithInfoPlistValues(&icore_config); + [self setHeartbeatFlagIfNeededToConfig:&icore_config]; + + // This log object is capable of converting the proto to bytes. + FIRCoreDiagnosticsLog *log = [[FIRCoreDiagnosticsLog alloc] initWithConfig:icore_config]; + + // Send the log as a telemetry event. + GDTCOREvent *event = [self.transport eventForTransport]; + event.dataObject = (id)log; + [self.transport sendTelemetryEvent:event]; + }); +} + +#pragma mark - Heartbeat + +- (void)setHeartbeatFlagIfNeededToConfig:(logs_proto_mobilesdk_ios_ICoreConfiguration *)config { + // Check if need to send a heartbeat. + NSDate *currentDate = [NSDate date]; + NSDate *lastCheckin = + [self.heartbeatDateStorage heartbeatDateForTag:kFIRCoreDiagnosticsHeartbeatTag]; + if (lastCheckin) { + // Ensure the previous checkin was on a different date in the past. + if ([self isDate:currentDate inSameDayOrBeforeThan:lastCheckin]) { + return; + } + } + + // Update heartbeat sent date. + [self.heartbeatDateStorage setHearbeatDate:currentDate forTag:kFIRCoreDiagnosticsHeartbeatTag]; + // Set the flag. + config->sdk_name = logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE; + config->has_sdk_name = 1; +} + +- (BOOL)isDate:(NSDate *)date1 inSameDayOrBeforeThan:(NSDate *)date2 { + return [[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2] || + [date1 compare:date2] == NSOrderedAscending; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c new file mode 100644 index 0000000..4b2ac2f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c @@ -0,0 +1,60 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 */ + +#include "firebasecore.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, logs_proto_mobilesdk_ios_ICoreConfiguration, configuration_type, configuration_type, 0), + PB_FIELD( 7, UENUM , REPEATED, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_service_installed, configuration_type, 0), + PB_FIELD( 9, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, device_model, sdk_service_installed, 0), + PB_FIELD( 10, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_id, device_model, 0), + PB_FIELD( 12, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, bundle_id, app_id, 0), + PB_FIELD( 16, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, pod_name, bundle_id, 0), + PB_FIELD( 18, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, icore_version, pod_name, 0), + PB_FIELD( 19, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_version, icore_version, 0), + PB_FIELD( 20, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, sdk_name, sdk_version, 0), + PB_FIELD( 21, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, app_count, sdk_name, 0), + PB_FIELD( 22, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, os_version, app_count, 0), + PB_FIELD( 24, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, min_supported_ios_version, os_version, 0), + PB_FIELD( 25, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, use_default_app, min_supported_ios_version, 0), + PB_FIELD( 26, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployed_in_app_store, use_default_app, 0), + PB_FIELD( 27, INT32 , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, dynamic_framework_count, deployed_in_app_store, 0), + PB_FIELD( 28, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, apple_framework_version, dynamic_framework_count, 0), + PB_FIELD( 29, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_zip_file, apple_framework_version, 0), + PB_FIELD( 30, UENUM , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, deployment_type, using_zip_file, 0), + PB_FIELD( 31, BYTES , OPTIONAL, POINTER , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, platform_info, deployment_type, 0), + PB_FIELD( 33, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, swizzling_enabled, platform_info, 0), + PB_FIELD( 36, BOOL , OPTIONAL, STATIC , OTHER, logs_proto_mobilesdk_ios_ICoreConfiguration, using_gdt, swizzling_enabled, 0), + PB_LAST_FIELD +}; + + + + + + + +/* @@protoc_insertion_point(eof) */ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h new file mode 100644 index 0000000..3e4c195 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h @@ -0,0 +1,193 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 */ + +#ifndef PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#define PB_LOGS_PROTO_MOBILESDK_IOS_FIREBASECORE_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_CORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_UNKNOWN_CONFIGURATION_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_SDK+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType { + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_INTERNAL = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_EAP = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD = 3 +} logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_UNKNOWN_BUILD_TYPE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType)(logs_proto_mobilesdk_ios_ICoreConfiguration_BuildType_PROD+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType { + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ICORE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ADMOB = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INVITE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SIGN_IN = 5, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_GCM = 6, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAPS = 7, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_SCION = 8, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ANALYTICS = 9, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_APP_INDEXING = 10, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CONFIG = 11, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DURABLE_DEEP_LINKS = 12, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_CRASH = 13, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH = 14, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DATABASE = 15, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_STORAGE = 16, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MESSAGING = 17, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MEASUREMENT = 18, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_REMOTE_CONFIG = 19, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_DYNAMIC_LINKS = 20, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_INVITES = 21, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_AUTH_UI = 22, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FIRESTORE = 23, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_PERFORMANCE = 24, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_FACE = 26, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_BARCODE = 27, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_TEXT = 28, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_LABEL = 29, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_MODEL_INTERPRETER = 30, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_IN_APP_MESSAGING = 31, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_FUNCTIONS = 32, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_NATURAL_LANGUAGE = 33, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_AUTOML = 34, + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION = 35 +} logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_UNKNOWN_SDK_SERVICE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType)(logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_ML_VISION_ON_DEVICE_OBJECT_DETECTION+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName { + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_GOOGLE = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE = 2 +} logs_proto_mobilesdk_ios_ICoreConfiguration_PodName; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_UNKNOWN_POD_NAME +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_PodName)(logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_FIREBASE+1)) + +typedef enum _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType { + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN = 0, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_COCOAPODS = 1, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ZIP_FILE = 2, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_CARTHAGE = 3, + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM = 4 +} logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType; +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_UNKNOWN +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MAX logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM +#define _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_ARRAYSIZE ((logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType)(logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_SPM+1)) + +/* Struct definitions */ +typedef struct _logs_proto_mobilesdk_ios_ICoreConfiguration { + bool has_configuration_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType configuration_type; + pb_size_t sdk_service_installed_count; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType *sdk_service_installed; + pb_bytes_array_t *device_model; + pb_bytes_array_t *app_id; + pb_bytes_array_t *bundle_id; + bool has_pod_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_PodName pod_name; + pb_bytes_array_t *icore_version; + pb_bytes_array_t *sdk_version; + bool has_sdk_name; + logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType sdk_name; + bool has_app_count; + int32_t app_count; + pb_bytes_array_t *os_version; + pb_bytes_array_t *min_supported_ios_version; + bool has_use_default_app; + bool use_default_app; + bool has_deployed_in_app_store; + bool deployed_in_app_store; + bool has_dynamic_framework_count; + int32_t dynamic_framework_count; + pb_bytes_array_t *apple_framework_version; + bool has_using_zip_file; + bool using_zip_file; + bool has_deployment_type; + logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType deployment_type; + pb_bytes_array_t *platform_info; + bool has_swizzling_enabled; + bool swizzling_enabled; + bool has_using_gdt; + bool using_gdt; +/* @@protoc_insertion_point(struct:logs_proto_mobilesdk_ios_ICoreConfiguration) */ +} logs_proto_mobilesdk_ios_ICoreConfiguration; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_default {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} +#define logs_proto_mobilesdk_ios_ICoreConfiguration_init_zero {false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ConfigurationType_MIN, 0, NULL, NULL, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_PodName_MIN, NULL, NULL, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_ServiceType_MIN, false, 0, NULL, NULL, false, 0, false, 0, false, 0, NULL, false, 0, false, _logs_proto_mobilesdk_ios_ICoreConfiguration_DeploymentType_MIN, NULL, false, 0, false, 0} + +/* Field tags (for use in manual encoding/decoding) */ +#define logs_proto_mobilesdk_ios_ICoreConfiguration_pod_name_tag 16 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_configuration_type_tag 1 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_icore_version_tag 18 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_version_tag 19 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_service_installed_tag 7 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_sdk_name_tag 20 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_device_model_tag 9 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_os_version_tag 22 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_id_tag 10 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_bundle_id_tag 12 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_min_supported_ios_version_tag 24 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_use_default_app_tag 25 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_app_count_tag 21 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployed_in_app_store_tag 26 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_dynamic_framework_count_tag 27 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_apple_framework_version_tag 28 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_zip_file_tag 29 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_deployment_type_tag 30 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_platform_info_tag 31 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_swizzling_enabled_tag 33 +#define logs_proto_mobilesdk_ios_ICoreConfiguration_using_gdt_tag 36 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t logs_proto_mobilesdk_ios_ICoreConfiguration_fields[22]; + +/* Maximum encoded size of messages (where known) */ +/* logs_proto_mobilesdk_ios_ICoreConfiguration_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define FIREBASECORE_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnostics/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h new file mode 100644 index 0000000..69c4072 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDIsDataCollectionDefaultEnabledKey @"FIRCDIsDataCollectionDefaultEnabledKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDConfigurationTypeKey @"FIRCDConfigurationTypeKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkNameKey @"FIRCDSdkNameKey" + +/** If present, is an NSString. */ +#define kFIRCDSdkVersionKey @"FIRCDSdkVersionKey" + +/** If present, is an int32_t wrapped in an NSNumber. */ +#define kFIRCDllAppsCountKey @"FIRCDllAppsCountKey" + +/** If present, is an NSString. */ +#define kFIRCDGoogleAppIDKey @"FIRCDGoogleAppIDKey" + +/** If present, is an NSString. */ +#define kFIRCDBundleIDKey @"FIRCDBundleID" + +/** If present, is a BOOL wrapped in an NSNumber. */ +#define kFIRCDUsingOptionsFromDefaultPlistKey @"FIRCDUsingOptionsFromDefaultPlistKey" + +/** If present, is an NSString. */ +#define kFIRCDLibraryVersionIDKey @"FIRCDLibraryVersionIDKey" + +/** If present, is an NSString. */ +#define kFIRCDFirebaseUserAgentKey @"FIRCDFirebaseUserAgentKey" + +/** Defines the interface of a data object needed to log diagnostics data. */ +@protocol FIRCoreDiagnosticsData + +@required + +/** A dictionary containing data (non-exhaustive) to be logged in diagnostics. */ +@property(nonatomic) NSDictionary *diagnosticObjects; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h new file mode 100644 index 0000000..2b0eb71 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRCoreDiagnosticsData.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Allows the interoperation of FirebaseCore and FirebaseCoreDiagnostics. */ +@protocol FIRCoreDiagnosticsInterop + +/** Sends the given diagnostics data. + * + * @param diagnosticsData The diagnostics data object to send. + */ ++ (void)sendDiagnosticsData:(id)diagnosticsData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseCoreDiagnosticsInterop/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m new file mode 100644 index 0000000..c1d48ec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDataSnapshot.m @@ -0,0 +1,105 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FChildrenNode.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseReference.h" +#import "FTransformedEnumerator.h" +#import "FValidation.h" + +@interface FIRDataSnapshot () +@property(nonatomic, strong) FIRDatabaseReference *ref; +@end + +@implementation FIRDataSnapshot + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node { + self = [super init]; + if (self != nil) { + self->_ref = ref; + self->_node = node; + } + return self; +} + +- (id)value { + return [self.node.node val]; +} + +- (id)valueInExportFormat { + return [self.node.node valForExport:YES]; +} + +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString { + [FValidation validateFrom:@"child:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + FIRDatabaseReference *childRef = [self.ref child:childPathString]; + + id childNode = [self.node.node getChild:childPath]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:childNode]]; +} + +- (BOOL)hasChild:(NSString *)childPathString { + [FValidation validateFrom:@"hasChild:" validPathString:childPathString]; + FPath *childPath = [[FPath alloc] initWith:childPathString]; + return ![[self.node.node getChild:childPath] isEmpty]; +} + +- (id)priority { + id priority = [self.node.node getPriority]; + return priority.val; +} + +- (BOOL)hasChildren { + if ([self.node.node isLeafNode]) { + return false; + } else { + return ![self.node.node isEmpty]; + } +} + +- (BOOL)exists { + return ![self.node.node isEmpty]; +} + +- (NSString *)key { + return [self.ref key]; +} + +- (NSUInteger)childrenCount { + return [self.node.node numChildren]; +} + +- (NSEnumerator *)children { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.node.childEnumerator + andTransform:^id(FNamedNode *node) { + FIRDatabaseReference *childRef = [self.ref child:node.name]; + return [[FIRDataSnapshot alloc] + initWithRef:childRef + indexedNode:[FIndexedNode indexedNodeWithNode:node.node]]; + }]; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"Snap (%@) %@", self.key, self.node.node]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m new file mode 100644 index 0000000..8957336 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabase.m @@ -0,0 +1,234 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import +#import +#import +#import + +#import "FIRDatabase.h" +#import "FIRDatabaseComponent.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoInfo.h" +#import "FValidation.h" + +@implementation FIRDatabase + +// The STR and STR_EXPAND macro allow a numeric version passed to he compiler +// driver with a -D to be treated as a string instead of an invalid floating +// point value. +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static const char *FIREBASE_SEMVER = (const char *)STR(FIRDatabase_VERSION); + ++ (FIRDatabase *)database { + if (![FIRApp isDefaultAppConfigured]) { + [NSException raise:@"FIRAppNotConfigured" + format:@"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp " + @"configure]` (`FirebaseApp.configure()` in Swift) " + @"before using " + @"Firebase Database."]; + } + return [FIRDatabase databaseForApp:[FIRApp defaultApp]]; +} + ++ (FIRDatabase *)databaseWithURL:(NSString *)url { + FIRApp *app = [FIRApp defaultApp]; + if (app == nil) { + [NSException + raise:@"FIRAppNotConfigured" + format: + @"Failed to get default Firebase Database instance. " + @"Must call `[FIRApp configure]` (`FirebaseApp.configure()` in " + @"Swift) before using Firebase Database."]; + } + return [FIRDatabase databaseForApp:app URL:url]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + return [FIRDatabase databaseForApp:app URL:app.options.databaseURL]; +} + ++ (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + @"Specify DatabaseURL within FIRApp or from your " + @"databaseForApp:URL: call."]; + } + id provider = + FIR_COMPONENT(FIRDatabaseProvider, app.container); + return [provider databaseForApp:app URL:url]; +} + ++ (NSString *)buildVersion { + // TODO: Restore git hash when build moves back to git + return [NSString stringWithFormat:@"%s_%s", FIREBASE_SEMVER, __DATE__]; +} + ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config { + FIRDatabase *db = [[FIRDatabase alloc] initWithApp:nil + repoInfo:repoInfo + config:config]; + [db ensureRepo]; + return db; +} + ++ (NSString *)sdkVersion { + return [NSString stringWithUTF8String:FIREBASE_SEMVER]; +} + ++ (void)setLoggingEnabled:(BOOL)enabled { + [FUtilities setLoggingEnabled:enabled]; + FFLog(@"I-RDB024001", @"BUILD Version: %@", [FIRDatabase buildVersion]); +} + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self != nil) { + self->_repoInfo = info; + self->_config = config; + self->_app = app; + } + return self; +} + +- (FIRDatabaseReference *)reference { + [self ensureRepo]; + + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:[FPath empty]]; +} + +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path { + [self ensureRepo]; + + [FValidation validateFrom:@"referenceWithPath" validRootPathString:path]; + FPath *childPath = [[FPath alloc] initWith:path]; + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:childPath]; +} + +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl { + [self ensureRepo]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"Invalid nil url passed to referenceFromURL:"]; + } + FParsedUrl *parsedUrl = [FUtilities parseUrl:databaseUrl]; + [FValidation validateFrom:@"referenceFromURL:" validURL:parsedUrl]; + if (![parsedUrl.repoInfo.host isEqualToString:_repoInfo.host]) { + [NSException + raise:@"InvalidDatabaseURL" + format: + @"Invalid URL (%@) passed to getReference(). URL was expected " + "to match configured Database URL: %@", + databaseUrl, [self reference].URL]; + } + return [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parsedUrl.path]; +} + +- (void)purgeOutstandingWrites { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo purgeOutstandingWrites]; + }); +} + +- (void)goOnline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo resume]; + }); +} + +- (void)goOffline { + [self ensureRepo]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo interrupt]; + }); +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen:@"setPersistenceEnabled"]; + self->_config.persistenceEnabled = persistenceEnabled; +} + +- (BOOL)persistenceEnabled { + return self->_config.persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen:@"setPersistenceCacheSizeBytes"]; + self->_config.persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (NSUInteger)persistenceCacheSizeBytes { + return self->_config.persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen:@"setCallbackQueue"]; + self->_config.callbackQueue = callbackQueue; +} + +- (dispatch_queue_t)callbackQueue { + return self->_config.callbackQueue; +} + +- (void)assertUnfrozen:(NSString *)methodName { + if (self.repo != nil) { + [NSException + raise:@"FIRDatabaseAlreadyInUse" + format:@"Calls to %@ must be made before any other usage of " + "FIRDatabase instance.", + methodName]; + } +} + +- (void)ensureRepo { + if (self.repo == nil) { + self.repo = [FRepoManager createRepo:self.repoInfo + config:self.config + database:self]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h new file mode 100644 index 0000000..9d8bdb2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.h @@ -0,0 +1,46 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRDatabase; + +NS_ASSUME_NONNULL_BEGIN + +/// This protocol is used in the interop registration process to register an +/// instance provider for individual FIRApps. +@protocol FIRDatabaseProvider + +/// Gets a FirebaseDatabase instance for the specified URL, using the specified +/// FirebaseApp. +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url; + +@end + +/// A concrete implementation for FIRDatabaseProvider to create Database +/// instances. +@interface FIRDatabaseComponent : NSObject + +/// The FIRApp that instances will be set up with. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable, use `databaseForApp:URL:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m new file mode 100644 index 0000000..8e44778 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseComponent.m @@ -0,0 +1,173 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseComponent.h" + +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepoManager.h" + +#import +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A NSMutableDictionary of FirebaseApp name and FRepoInfo to FirebaseDatabase + * instance. */ +typedef NSMutableDictionary FIRDatabaseDictionary; + +@interface FIRDatabaseComponent () +@property(nonatomic) FIRDatabaseDictionary *instances; +/// Internal intializer. +- (instancetype)initWithApp:(FIRApp *)app; +@end + +@implementation FIRDatabaseComponent + +#pragma mark - Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + self = [super init]; + if (self) { + _app = app; + _instances = [NSMutableDictionary dictionary]; + } + return self; +} + +#pragma mark - Lifecycle + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-db" + withVersion:[FIRDatabase sdkVersion]]; +} + +#pragma mark - FIRComponentRegistrant + ++ (NSArray *)componentsToRegister { + FIRDependency *authDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop) + isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + return [[FIRDatabaseComponent alloc] initWithApp:container.app]; + }; + FIRComponent *databaseProvider = + [FIRComponent componentWithProtocol:@protocol(FIRDatabaseProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ authDep ] + creationBlock:creationBlock]; + return @[ databaseProvider ]; +} + +#pragma mark - Instance management. + +- (void)appWillBeDeleted:(FIRApp *)app { + NSString *appName = app.name; + if (appName == nil) { + return; + } + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + // Clean up the deleted instance in an effort to remove any resources + // still in use. Note: Any leftover instances of this exact database + // will be invalid. + for (FIRDatabase *database in [instances allValues]) { + [FRepoManager disposeRepos:database.config]; + } + [instances removeAllObjects]; + } +} + +#pragma mark - FIRDatabaseProvider Conformance + +- (FIRDatabase *)databaseForApp:(FIRApp *)app URL:(NSString *)url { + if (app == nil) { + [NSException raise:@"InvalidFIRApp" + format:@"nil FIRApp instance passed to databaseForApp."]; + } + + if (url == nil) { + [NSException raise:@"MissingDatabaseURL" + format:@"Failed to get FirebaseDatabase instance: " + "Specify DatabaseURL within FIRApp or from your " + "databaseForApp:URL: call."]; + } + + NSURL *databaseUrl = [NSURL URLWithString:url]; + + if (databaseUrl == nil) { + [NSException raise:@"InvalidDatabaseURL" + format:@"The Database URL '%@' cannot be parsed. " + "Specify a valid DatabaseURL within FIRApp or from " + "your databaseForApp:URL: call.", + databaseUrl]; + } else if (![databaseUrl.path isEqualToString:@""] && + ![databaseUrl.path isEqualToString:@"/"]) { + [NSException + raise:@"InvalidDatabaseURL" + format:@"Configured Database URL '%@' is invalid. It should point " + "to the root of a Firebase Database but it includes a " + "path: %@", + databaseUrl, databaseUrl.path]; + } + + FIRDatabaseDictionary *instances = [self instances]; + @synchronized(instances) { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:databaseUrl.absoluteString]; + NSString *urlIndex = + [NSString stringWithFormat:@"%@:%@", parsedUrl.repoInfo.host, + [parsedUrl.path toString]]; + FIRDatabase *database = instances[urlIndex]; + if (!database) { + id authTokenProvider = [FAuthTokenProvider + authTokenProviderWithAuth:FIR_COMPONENT(FIRAuthInterop, + app.container)]; + + // If this is the default app, don't set the session persistence key + // so that we use our default ("default") instead of the FIRApp + // default ("[DEFAULT]") so that we preserve the default location + // used by the legacy Firebase SDK. + NSString *sessionIdentifier = @"default"; + if (![FIRApp isDefaultAppConfigured] || + app != [FIRApp defaultApp]) { + sessionIdentifier = app.name; + } + + FIRDatabaseConfig *config = [[FIRDatabaseConfig alloc] + initWithSessionIdentifier:sessionIdentifier + authTokenProvider:authTokenProvider]; + database = [[FIRDatabase alloc] initWithApp:app + repoInfo:parsedUrl.repoInfo + config:config]; + instances[urlIndex] = database; + } + + return database; + } +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h new file mode 100644 index 0000000..85399f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FAuthTokenProvider; + +NS_ASSUME_NONNULL_BEGIN + +/** + * TODO: Merge FIRDatabaseConfig into FIRDatabase. + */ +@interface FIRDatabaseConfig : NSObject + +- (id)initWithSessionIdentifier:(NSString *)identifier + authTokenProvider:(id)authTokenProvider; + +/** + * By default the Firebase Database client will keep data in memory while your + * application is running, but not when it is restarted. By setting this value + * to YES, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first FIRDatabaseReference and only needs to be called once per + * application. + * + * If your app uses Firebase Authentication, the client will automatically + * persist the user's authentication token across restarts, even without + * persistence enabled. But if the auth token expired while offline and you've + * enabled persistence, the client will pause write operations until you + * successfully re-authenticate (or explicitly unauthenticate) to prevent your + * writes from being sent unauthenticated and failing due to security rules. + */ +@property(nonatomic) BOOL persistenceEnabled; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m new file mode 100644 index 0000000..9e9f8b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseConfig.m @@ -0,0 +1,92 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRNoopAuthTokenProvider.h" + +@interface FIRDatabaseConfig (Private) + +@property(nonatomic, strong, readwrite) NSString *sessionIdentifier; + +@end + +@implementation FIRDatabaseConfig + +- (id)init { + [NSException raise:NSInvalidArgumentException + format:@"Can't create config objects!"]; + return nil; +} + +- (id)initWithSessionIdentifier:(NSString *)identifier + authTokenProvider:(id)authTokenProvider { + self = [super init]; + if (self != nil) { + self->_sessionIdentifier = identifier; + self->_callbackQueue = dispatch_get_main_queue(); + self->_persistenceCacheSizeBytes = + 10 * 1024 * 1024; // Default cache size is 10MB + self->_authTokenProvider = authTokenProvider; + } + return self; +} + +- (void)assertUnfrozen { + if (self.isFrozen) { + [NSException raise:NSGenericException + format:@"Can't modify config objects after they are in use " + @"for FIRDatabaseReferences."]; + } +} + +- (void)setAuthTokenProvider:(id)authTokenProvider { + [self assertUnfrozen]; + self->_authTokenProvider = authTokenProvider; +} + +- (void)setPersistenceEnabled:(BOOL)persistenceEnabled { + [self assertUnfrozen]; + self->_persistenceEnabled = persistenceEnabled; +} + +- (void)setPersistenceCacheSizeBytes:(NSUInteger)persistenceCacheSizeBytes { + [self assertUnfrozen]; + // Can't be less than 1MB + if (persistenceCacheSizeBytes < 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"The minimum cache size must be at least 1MB"]; + } + if (persistenceCacheSizeBytes > 100 * 1024 * 1024) { + [NSException raise:NSInvalidArgumentException + format:@"Firebase Database currently doesn't support a " + @"cache size larger than 100MB"]; + } + self->_persistenceCacheSizeBytes = persistenceCacheSizeBytes; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + [self assertUnfrozen]; + self->_callbackQueue = callbackQueue; +} + +- (void)freeze { + self->_isFrozen = YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m new file mode 100644 index 0000000..cd62979 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRDatabaseQuery.m @@ -0,0 +1,677 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FChildEventRegistration.h" +#import "FConstants.h" +#import "FIRDatabaseQuery_Private.h" +#import "FKeyIndex.h" +#import "FLeafNode.h" +#import "FPath.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FSnapshotUtilities.h" +#import "FValidation.h" +#import "FValueEventRegistration.h" +#import "FValueIndex.h" + +@implementation FIRDatabaseQuery + +@synthesize repo; +@synthesize path; +@synthesize queryParams; + +#define INVALID_QUERY_PARAM_ERROR @"InvalidQueryParameter" + ++ (dispatch_queue_t)sharedQueue { + // We use this shared queue across all of the FQueries so things happen FIFO + // (as opposed to dispatch_get_global_queue(0, 0) which is concurrent) + static dispatch_once_t pred; + static dispatch_queue_t sharedDispatchQueue; + + dispatch_once(&pred, ^{ + sharedDispatchQueue = dispatch_queue_create("FirebaseWorker", NULL); + }); + + return sharedDispatchQueue; +} + +- (id)initWithRepo:(FRepo *)theRepo path:(FPath *)thePath { + return [self initWithRepo:theRepo + path:thePath + params:nil + orderByCalled:NO + priorityMethodCalled:NO]; +} + +- (id)initWithRepo:(FRepo *)theRepo + path:(FPath *)thePath + params:(FQueryParams *)theParams + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled { + self = [super init]; + if (self) { + self.repo = theRepo; + self.path = thePath; + if (!theParams) { + theParams = [FQueryParams defaultInstance]; + } + if (![theParams isValid]) { + @throw [[NSException alloc] + initWithName:@"InvalidArgumentError" + reason:@"Queries are limited to two constraints" + userInfo:nil]; + } + self.queryParams = theParams; + self.orderByCalled = orderByCalled; + self.priorityMethodCalled = priorityMethodCalled; + } + return self; +} + +- (FQuerySpec *)querySpec { + return [[FQuerySpec alloc] initWithPath:self.path params:self.queryParams]; +} + +- (void)validateQueryEndpointsForParams:(FQueryParams *)params { + if ([params.index isEqual:[FKeyIndex keyIndex]]) { + if ([params hasStart]) { + if (params.indexStartKey != [FUtilities minName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryStartingAtValue:childKey: " + @"or queryEqualTo:andChildKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexStartValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryStartingAtValue: with other types " + @"than string in combination with queryOrderedByKey"]; + } + } + if ([params hasEnd]) { + if (params.indexEndKey != [FUtilities maxName]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't use queryEndingAtValue:childKey: or " + @"queryEqualToValue:childKey: in " + @"combination with queryOrderedByKey"]; + } + if (![params.indexEndValue.val isKindOfClass:[NSString class]]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't use queryEndingAtValue: with other types than " + @"string in combination with queryOrderedByKey"]; + } + } + } else if ([params.index isEqual:[FPriorityIndex priorityIndex]]) { + if (([params hasStart] && + ![FValidation validatePriorityValue:params.indexStartValue.val]) || + ([params hasEnd] && + ![FValidation validatePriorityValue:params.indexEndValue.val])) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format:@"When using queryOrderedByPriority, values provided to " + @"queryStartingAtValue:, queryEndingAtValue:, or " + @"queryEqualToValue: must be valid priorities."]; + } + } +} + +- (void)validateEqualToCall { + if ([self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryStartingAtValue:"]; + } + if ([self.queryParams hasEnd]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Cannot combine queryEqualToValue: and queryEndingAtValue:"]; + } +} + +- (void)validateNoPreviousOrderByCalled { + if (self.orderByCalled) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Cannot use multiple queryOrderedBy calls!"]; + } +} + +- (void)validateIndexValueType:(id)type fromMethod:(NSString *)method { + if (type != nil && ![type isKindOfClass:[NSNumber class]] && + ![type isKindOfClass:[NSString class]] && + ![type isKindOfClass:[NSNull class]]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"You can only pass nil, NSString or NSNumber to %@", + method]; + } +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [self queryStartingAtInternal:startValue + childKey:nil + from:@"queryStartingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryStartingAtValue: instead of " + @"queryStartingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + return [self queryStartingAtInternal:startValue + childKey:childKey + from:@"queryStartingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryStartingAtInternal:(id)startValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:startValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasStart]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryStartingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id startNode = [FSnapshotUtilities nodeFrom:startValue]; + FQueryParams *params = [self.queryParams startAt:startNode + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [self queryEndingAtInternal:endValue + childKey:nil + from:@"queryEndingAtValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEndingAtValue: instead of " + @"queryEndingAtValue:childKey: when using " + @"queryOrderedByKey:" + userInfo:nil]; + } + + return [self queryEndingAtInternal:endValue + childKey:childKey + from:@"queryEndingAtValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEndingAtInternal:(id)endValue + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:endValue fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd]) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call %@ after queryEndingAtValue or " + @"queryEqualToValue was previously called", + methodName]; + } + id endNode = [FSnapshotUtilities nodeFrom:endValue]; + FQueryParams *params = [self.queryParams endAt:endNode childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [self queryEqualToInternal:value + childKey:nil + from:@"queryEqualToValue:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + if ([self.queryParams.index isEqual:[FKeyIndex keyIndex]]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:@"You must use queryEqualToValue: instead of " + @"queryEqualTo:childKey: when using queryOrderedByKey:" + userInfo:nil]; + } + return [self queryEqualToInternal:value + childKey:childKey + from:@"queryEqualToValue:childKey:" + priorityMethod:NO]; +} + +- (FIRDatabaseQuery *)queryEqualToInternal:(id)value + childKey:(NSString *)childKey + from:(NSString *)methodName + priorityMethod:(BOOL)priorityMethod { + [self validateIndexValueType:value fromMethod:methodName]; + if (childKey != nil) { + [FValidation validateFrom:methodName validKey:childKey]; + } + if ([self.queryParams hasEnd] || [self.queryParams hasStart]) { + [NSException + raise:INVALID_QUERY_PARAM_ERROR + format: + @"Can't call %@ after queryStartingAtValue, queryEndingAtValue " + @"or queryEqualToValue was previously called", + methodName]; + } + id node = [FSnapshotUtilities nodeFrom:value]; + FQueryParams *params = [[self.queryParams startAt:node + childKey:childKey] endAt:node + childKey:childKey]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] + initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:priorityMethod || self.priorityMethodCalled]; +} + +- (void)validateLimitRange:(NSUInteger)limit { + // No need to check for negative ranges, since limit is unsigned + if (limit == 0) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit can't be zero"]; + } + if (limit >= 1ul << 31) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Limit must be less than 2,147,483,648"]; + } +} + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToFirst: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToFirst:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + if (self.queryParams.limitSet) { + [NSException raise:INVALID_QUERY_PARAM_ERROR + format:@"Can't call queryLimitedToLast: if a limit was " + @"previously set"]; + } + [self validateLimitRange:limit]; + FQueryParams *params = [self.queryParams limitToLast:limit]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:self.orderByCalled + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)indexPathString { + if ([indexPathString isEqualToString:@"$key"] || + [indexPathString isEqualToString:@".key"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByKey: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$priority"] || + [indexPathString isEqualToString:@".priority"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByPriority: instead.", + indexPathString] + userInfo:nil]; + } else if ([indexPathString isEqualToString:@"$value"] || + [indexPathString isEqualToString:@".value"]) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString stringWithFormat: + @"(queryOrderedByChild:) %@ is invalid. " + @" Use queryOrderedByValue: instead.", + indexPathString] + userInfo:nil]; + } + [self validateNoPreviousOrderByCalled]; + + [FValidation validateFrom:@"queryOrderedByChild:" + validPathString:indexPathString]; + FPath *indexPath = [FPath pathWithString:indexPathString]; + if (indexPath.isEmpty) { + @throw [[NSException alloc] + initWithName:INVALID_QUERY_PARAM_ERROR + reason:[NSString + stringWithFormat:@"(queryOrderedByChild:) with an " + @"empty path is invalid. Use " + @"queryOrderedByValue: instead."] + userInfo:nil]; + } + id index = [[FPathIndex alloc] initWithPath:indexPath]; + + FQueryParams *params = [self.queryParams orderBy:index]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FKeyIndex keyIndex]]; + [self validateQueryEndpointsForParams:params]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByValue { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = [self.queryParams orderBy:[FValueIndex valueIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + [self validateNoPreviousOrderByCalled]; + FQueryParams *params = + [self.queryParams orderBy:[FPriorityIndex priorityIndex]]; + return [[FIRDatabaseQuery alloc] initWithRepo:self.repo + path:self.path + params:params + orderByCalled:YES + priorityMethodCalled:self.priorityMethodCalled]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *))block { + [FValidation validateFrom:@"observeEventType:withBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [FValidation + validateFrom:@"observeEventType:andPreviousSiblingKeyWithBlock:" + knownEventType:eventType]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:withBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // Handle FIRDataEventTypeValue specially because they shouldn't have + // prevName callbacks + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + [self observeValueEventWithHandle:handle + withBlock:block + cancelCallback:cancelBlock]; + return handle; + } else { + // Wrap up the userCallback so we can treat everything as a callback + // that has a prevName + fbt_void_datasnapshot userCallback = [block copy]; + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (userCallback != nil) { + userCallback(snapshot); + } + } + withCancelBlock:cancelBlock]; + } +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [FValidation validateFrom:@"observeEventType:" + @"andPreviousSiblingKeyWithBlock:withCancelBlock:" + knownEventType:eventType]; + + if (eventType == FIRDataEventTypeValue) { + // TODO: This gets hit by observeSingleEventOfType. Need to fix. + /* + @throw [[NSException alloc] initWithName:@"InvalidEventTypeForObserver" + reason:@"(observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock:) + Cannot use + observeEventType:andPreviousSiblingKeyWithBlock:withCancelBlock: with + FIRDataEventTypeValue. Use observeEventType:withBlock:withCancelBlock: + instead." userInfo:nil]; + */ + } + + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + NSDictionary *callbacks = + @{[NSNumber numberWithInteger:eventType] : [block copy]}; + [self observeChildEventWithHandle:handle + withCallbacks:callbacks + cancelCallback:cancelBlock]; + + return handle; +} + +// If we want to distinguish between value event listeners and child event +// listeners, like in the Java client, we can consider exporting this. If we do, +// add argument validation. Otherwise, arguments are validated in the +// public-facing portions of the API. Also, move the FIRDatabaseHandle logic. +- (void)observeValueEventWithHandle:(FIRDatabaseHandle)handle + withBlock:(fbt_void_datasnapshot)block + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:block + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +// Note: as with the above method, we may wish to expose this at some point. +- (void)observeChildEventWithHandle:(FIRDatabaseHandle)handle + withCallbacks:(NSDictionary *)callbacks + cancelCallback:(fbt_void_nserror)cancelBlock { + // Note that we don't need to copy the callbacks here, FEventRegistration + // callback properties set to copy + FChildEventRegistration *registration = + [[FChildEventRegistration alloc] initWithRepo:self.repo + handle:handle + callbacks:callbacks + cancelCallback:cancelBlock]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo addEventRegistration:registration forQuery:self.querySpec]; + }); +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + FValueEventRegistration *event = + [[FValueEventRegistration alloc] initWithRepo:self.repo + handle:handle + callback:nil + cancelCallback:nil]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo removeEventRegistration:event forQuery:self.querySpec]; + }); +} + +- (void)removeAllObservers { + [self removeObserverWithHandle:NSNotFound]; +} + +- (void)keepSynced:(BOOL)keepSynced { + if ([self.path.getFront isEqualToString:kDotInfoPrefix]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't keep query on .info tree synced (this " + @"already is the case)."]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo keepQuery:self.querySpec synced:keepSynced]; + }); +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:^(FIRDataSnapshot *snapshot, + NSString *prevName) { + if (block != nil) { + block(snapshot); + } + } + withCancelBlock:cancelBlock]; +} + +/** + * Attaches a listener, waits for the first event, and then removes the listener + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + + // XXX: user reported memory leak in method + + // "When you copy a block, any references to other blocks from within that + // block are copied if necessary—an entire tree may be copied (from the + // top). If you have block variables and you reference a block from within + // the block, that block will be copied." + // http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1 + // So... we don't need to do this since inside the on: we copy this block + // off the stack to the heap. + // __block fbt_void_datasnapshot userCallback = [callback copy]; + + __block FIRDatabaseHandle handle; + __block BOOL firstCall = YES; + + fbt_void_datasnapshot_nsstring callback = [block copy]; + fbt_void_datasnapshot_nsstring wrappedCallback = + ^(FIRDataSnapshot *snap, NSString *prevName) { + if (firstCall) { + firstCall = NO; + [self removeObserverWithHandle:handle]; + callback(snap, prevName); + } + }; + + fbt_void_nserror cancelCallback = [cancelBlock copy]; + handle = [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:wrappedCallback + withCancelBlock:^(NSError *error) { + [self removeObserverWithHandle:handle]; + + if (cancelCallback) { + cancelCallback(error); + } + }]; +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"(%@ %@)", self.path, self.queryParams.description]; +} + +- (FIRDatabaseReference *)ref { + return [[FIRDatabaseReference alloc] initWithRepo:self.repo path:self.path]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m new file mode 100644 index 0000000..5da7fae --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRMutableData.m @@ -0,0 +1,149 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FChildrenNode.h" +#import "FIRMutableData_Private.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FTransformedEnumerator.h" + +@interface FIRMutableData () + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder; + +@property(strong, nonatomic) FSnapshotHolder *data; +@property(strong, nonatomic) FPath *prefixPath; + +@end + +@implementation FIRMutableData + +@synthesize data; +@synthesize prefixPath; + +- (id)initWithNode:(id)node { + FSnapshotHolder *holder = [[FSnapshotHolder alloc] init]; + FPath *path = [FPath empty]; + [holder updateSnapshot:path withNewSnapshot:node]; + return [self initWithPrefixPath:path andSnapshotHolder:holder]; +} + +- (id)initWithPrefixPath:(FPath *)path + andSnapshotHolder:(FSnapshotHolder *)snapshotHolder { + self = [super init]; + if (self) { + self.prefixPath = path; + self.data = snapshotHolder; + } + return self; +} + +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path { + FPath *wholePath = [self.prefixPath childFromString:path]; + return [[FIRMutableData alloc] initWithPrefixPath:wholePath + andSnapshotHolder:self.data]; +} + +- (FIRMutableData *)parent { + if ([self.prefixPath isEmpty]) { + return nil; + } else { + FPath *path = [self.prefixPath parent]; + return [[FIRMutableData alloc] initWithPrefixPath:path + andSnapshotHolder:self.data]; + } +} + +- (void)setValue:(id)aValue { + id node = [FSnapshotUtilities nodeFrom:aValue + withValidationFrom:@"setValue:"]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (void)setPriority:(id)aPriority { + id node = [self.data getNode:self.prefixPath]; + id pri = [FSnapshotUtilities nodeFrom:aPriority]; + node = [node updatePriority:pri]; + [self.data updateSnapshot:self.prefixPath withNewSnapshot:node]; +} + +- (id)value { + return [[self.data getNode:self.prefixPath] val]; +} + +- (id)priority { + return [[[self.data getNode:self.prefixPath] getPriority] val]; +} + +- (BOOL)hasChildren { + id node = [self.data getNode:self.prefixPath]; + return ![node isLeafNode] && ![(FChildrenNode *)node isEmpty]; +} + +- (BOOL)hasChildAtPath:(NSString *)path { + id node = [self.data getNode:self.prefixPath]; + FPath *childPath = [[FPath alloc] initWith:path]; + return ![[node getChild:childPath] isEmpty]; +} + +- (NSUInteger)childrenCount { + return [[self.data getNode:self.prefixPath] numChildren]; +} + +- (NSString *)key { + return [self.prefixPath getBack]; +} + +- (id)nodeValue { + return [self.data getNode:self.prefixPath]; +} + +- (NSEnumerator *)children { + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:self.nodeValue]; + return [[FTransformedEnumerator alloc] + initWithEnumerator:[indexedNode childEnumerator] + andTransform:^id(FNamedNode *node) { + FPath *childPath = [self.prefixPath childFromString:node.name]; + FIRMutableData *childData = + [[FIRMutableData alloc] initWithPrefixPath:childPath + andSnapshotHolder:self.data]; + return childData; + }]; +} + +- (BOOL)isEqualToData:(FIRMutableData *)other { + return self.data == other.data && + [[self.prefixPath description] + isEqualToString:[other.prefixPath description]]; +} + +- (NSString *)description { + if (self.key == nil) { + return [NSString + stringWithFormat:@"FIRMutableData (top-most transaction) %@ %@", + self.key, self.value]; + } else { + return [NSString + stringWithFormat:@"FIRMutableData (%@) %@", self.key, self.value]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m new file mode 100644 index 0000000..e5be5c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRServerValue.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRServerValue.h" +#import "FIRDatabaseReference.h" + +@implementation FIRServerValue + ++ (NSDictionary *)timestamp { + static NSDictionary *timestamp = nil; + if (timestamp == nil) { + timestamp = @{@".sv" : @"timestamp"}; + } + return timestamp; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m new file mode 100644 index 0000000..9fec862 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/FIRTransactionResult.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" + +@implementation FIRTransactionResult + +@synthesize update; +@synthesize isSuccess; + ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = YES; + result.update = value; + return result; +} + ++ (FIRTransactionResult *)abort { + FIRTransactionResult *result = [[FIRTransactionResult alloc] init]; + result.isSuccess = NO; + result.update = nil; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h new file mode 100644 index 0000000..ac23045 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDataSnapshot_Private.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIndexedNode.h" +#import "FTypedefs_Private.h" + +@interface FIRDataSnapshot () + +// in _Private for testing purposes +@property(nonatomic, strong) FIndexedNode *node; + +- (id)initWithRef:(FIRDatabaseReference *)ref indexedNode:(FIndexedNode *)node; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h new file mode 100644 index 0000000..30f19f0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseQuery.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseQuery () + ++ (dispatch_queue_t)sharedQueue; + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; +- (id)initWithRepo:(FRepo *)repo + path:(FPath *)path + params:(FQueryParams *)params + orderByCalled:(BOOL)orderByCalled + priorityMethodCalled:(BOOL)priorityMethodCalled; + +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) FQueryParams *queryParams; +@property(nonatomic) BOOL orderByCalled; +@property(nonatomic) BOOL priorityMethodCalled; + +- (FQuerySpec *)querySpec; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h new file mode 100644 index 0000000..1d7e37c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabaseReference_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseReference.h" +#import "FRepo.h" +#import "FTypedefs_Private.h" + +@interface FIRDatabaseReference () + +- (id)initWithConfig:(FIRDatabaseConfig *)config; +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h new file mode 100644 index 0000000..0ff3e70 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRDatabase_Private.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabase.h" + +@class FRepo; +@class FRepoInfo; +@class FIRDatabaseConfig; + +@interface FIRDatabase () + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic, strong) FRepo *repo; + +- (id)initWithApp:(FIRApp *)app + repoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config; + ++ (NSString *)buildVersion; ++ (FIRDatabase *)createDatabaseForTests:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h new file mode 100644 index 0000000..fded102 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRMutableData_Private.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FNode.h" + +@interface FIRMutableData () + +- (id)initWithNode:(id)node; +- (id)nodeValue; +- (BOOL)isEqualToData:(FIRMutableData *)other; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h new file mode 100644 index 0000000..bdf250a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FIRTransactionResult_Private.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import "FIRTransactionResult.h" + +@interface FIRTransactionResult () + +@property(nonatomic) BOOL isSuccess; +@property(nonatomic, strong) FIRMutableData *update; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h new file mode 100644 index 0000000..dac55bc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Api/Private/FTypedefs_Private.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __FTYPEDEFS_PRIVATE__ +#define __FTYPEDEFS_PRIVATE__ + +#import + +typedef NS_ENUM(NSInteger, FTransactionStatus) { + FTransactionInitializing, // 0 + FTransactionRun, // 1 + FTransactionSent, // 2 + FTransactionCompleted, // 3 + FTransactionSentNeedsAbort, // 4 + FTransactionNeedsAbort // 5 +}; + +@protocol FNode; +@class FPath; +@class FIRTransactionResult; +@class FIRMutableData; +@class FIRDataSnapshot; +@class FCompoundHash; + +typedef void (^fbt_void_nserror_bool_datasnapshot)(NSError *error, + BOOL committed, + FIRDataSnapshot *snapshot); +typedef FIRTransactionResult * (^fbt_transactionresult_mutabledata)( + FIRMutableData *currentData); +typedef void (^fbt_void_path_node)(FPath *, id); +typedef void (^fbt_void_nsstring)(NSString *); +typedef BOOL (^fbt_bool_nsstring_node)(NSString *, id); +typedef void (^fbt_void_path_node_marray)(FPath *, id, NSMutableArray *); +typedef BOOL (^fbt_bool_void)(void); +typedef void (^fbt_void_nsstring_nsstring)(NSString *str1, NSString *str2); +typedef void (^fbt_void_nsstring_nserror)(NSString *str, NSError *error); +typedef BOOL (^fbt_bool_path)(FPath *str); +typedef void (^fbt_void_id)(id data); +typedef NSString * (^fbt_nsstring_void)(void); +typedef FCompoundHash * (^fbt_compoundhash_void)(void); +typedef NSArray * (^fbt_nsarray_nsstring_id)(NSString *status, id Data); +typedef NSArray * (^fbt_nsarray_nsstring)(NSString *status); + +// WWDC 2012 session 712 starting in page 83 for saving blocks in properties +// (use @property (strong) type name). + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h new file mode 100644 index 0000000..4327a0d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.h @@ -0,0 +1,195 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FConstants_h +#define Firebase_FConstants_h + +#import + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestType; +FOUNDATION_EXPORT NSString *const kFWPRequestTypeData; +FOUNDATION_EXPORT NSString *const kFWPRequestDataPayload; +FOUNDATION_EXPORT NSString *const kFWPRequestNumber; +FOUNDATION_EXPORT NSString *const kFWPRequestPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPRequestError; +FOUNDATION_EXPORT NSString *const kFWPRequestAction; +FOUNDATION_EXPORT NSString *const kFWPResponseForRNData; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatus; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusOk; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionStatusDataStale; +FOUNDATION_EXPORT NSString *const kFWPResponseForActionData; +FOUNDATION_EXPORT NSString *const kFWPResponseDataWarnings; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAction; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerPayloadBody; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdate; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerAuthRevoked; +FOUNDATION_EXPORT NSString *const kFWPASyncServerListenCancelled; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerSecurityDebug; +FOUNDATION_EXPORT NSString + *const kFWPAsyncServerDataUpdateBodyPath; // {“a”: “d”, “b”: {“p”: “/”, “d”: + // “”}} +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateStartPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateEndPath; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateRangeMerge; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataUpdateBodyTag; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataQueries; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerEnvelopeData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessage; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageType; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageData; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerDataMessage; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHello; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloTimestamp; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloVersion; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloConnectedHost; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerHelloSession; + +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageShutdown; +FOUNDATION_EXPORT NSString *const kFWPAsyncServerControlMessageReset; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +FOUNDATION_EXPORT NSString *const kFWPRequestActionPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedListen; +FOUNDATION_EXPORT NSString *const kFWPRequestActionTaggedUnlisten; +FOUNDATION_EXPORT NSString + *const kFWPRequestActionListen; // {"t": "d", "d": {"r": 1, "a": "l", "b": { + // "p": "/" } } } +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnlisten; +FOUNDATION_EXPORT NSString *const kFWPRequestActionStats; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectPut; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectMerge; +FOUNDATION_EXPORT NSString *const kFWPRequestActionDisconnectCancel; +FOUNDATION_EXPORT NSString *const kFWPRequestActionAuth; +FOUNDATION_EXPORT NSString *const kFWPRequestActionUnauth; +FOUNDATION_EXPORT NSString *const kFWPRequestCredential; +FOUNDATION_EXPORT NSString *const kFWPRequestPath; +FOUNDATION_EXPORT NSString *const kFWPRequestCounters; +FOUNDATION_EXPORT NSString *const kFWPRequestQueries; +FOUNDATION_EXPORT NSString *const kFWPRequestTag; +FOUNDATION_EXPORT NSString *const kFWPRequestData; +FOUNDATION_EXPORT NSString *const kFWPRequestHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHash; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashPaths; +FOUNDATION_EXPORT NSString *const kFWPRequestCompoundHashHashes; +FOUNDATION_EXPORT NSString *const kFWPRequestStatus; + +#pragma mark - +#pragma mark Websock Transport Constants + +FOUNDATION_EXPORT NSString *const kWireProtocolVersionParam; +FOUNDATION_EXPORT NSString *const kWebsocketProtocolVersion; +FOUNDATION_EXPORT NSString *const kWebsocketServerKillPacket; +FOUNDATION_EXPORT const int kWebsocketMaxFrameSize; +FOUNDATION_EXPORT NSUInteger const kWebsocketKeepaliveInterval; +FOUNDATION_EXPORT NSUInteger const kWebsocketConnectTimeout; + +FOUNDATION_EXPORT float const kPersistentConnReconnectMinDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMaxDelay; +FOUNDATION_EXPORT float const kPersistentConnReconnectMultiplier; +FOUNDATION_EXPORT float const + kPersistentConnSuccessfulConnectionEstablishedDelay; + +#pragma mark - +#pragma mark Query / QueryParams constants + +FOUNDATION_EXPORT NSString *const kQueryDefault; +FOUNDATION_EXPORT NSString *const kQueryDefaultObject; +FOUNDATION_EXPORT NSString *const kViewManagerDictConstView; +FOUNDATION_EXPORT NSString *const kFQPIndexStartValue; +FOUNDATION_EXPORT NSString *const kFQPIndexStartName; +FOUNDATION_EXPORT NSString *const kFQPIndexEndValue; +FOUNDATION_EXPORT NSString *const kFQPIndexEndName; +FOUNDATION_EXPORT NSString *const kFQPLimit; +FOUNDATION_EXPORT NSString *const kFQPViewFrom; +FOUNDATION_EXPORT NSString *const kFQPViewFromLeft; +FOUNDATION_EXPORT NSString *const kFQPViewFromRight; +FOUNDATION_EXPORT NSString *const kFQPIndex; + +#pragma mark - +#pragma mark Interrupt Reasons + +FOUNDATION_EXPORT NSString *const kFInterruptReasonServerKill; +FOUNDATION_EXPORT NSString *const kFInterruptReasonWaitingForOpen; +FOUNDATION_EXPORT NSString *const kFInterruptReasonRepoInterrupt; +FOUNDATION_EXPORT NSString *const kFInterruptReasonAuthExpired; + +#pragma mark - +#pragma mark Payload constants + +FOUNDATION_EXPORT NSString *const kPayloadPriority; +FOUNDATION_EXPORT NSString *const kPayloadValue; +FOUNDATION_EXPORT NSString *const kPayloadMetadataPrefix; + +#pragma mark - +#pragma mark ServerValue constants + +FOUNDATION_EXPORT NSString *const kServerValueSubKey; +FOUNDATION_EXPORT NSString *const kServerValuePriority; + +#pragma mark - +#pragma mark.info/ constants + +FOUNDATION_EXPORT NSString *const kDotInfoPrefix; +FOUNDATION_EXPORT NSString *const kDotInfoConnected; +FOUNDATION_EXPORT NSString *const kDotInfoServerTimeOffset; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +FOUNDATION_EXPORT NSString *const kJavaScriptObject; +FOUNDATION_EXPORT NSString *const kJavaScriptString; +FOUNDATION_EXPORT NSString *const kJavaScriptBoolean; +FOUNDATION_EXPORT NSString *const kJavaScriptNumber; +FOUNDATION_EXPORT NSString *const kJavaScriptNull; +FOUNDATION_EXPORT NSString *const kJavaScriptTrue; +FOUNDATION_EXPORT NSString *const kJavaScriptFalse; + +#pragma mark - +#pragma mark Error handling constants + +FOUNDATION_EXPORT NSString *const kFErrorDomain; +FOUNDATION_EXPORT NSUInteger const kFAuthError; +FOUNDATION_EXPORT NSString *const kFErrorWriteCanceled; + +#pragma mark - +#pragma mark Validation Constants + +FOUNDATION_EXPORT NSUInteger const kFirebaseMaxObjectDepth; +FOUNDATION_EXPORT const unsigned int kFirebaseMaxLeafSize; + +#pragma mark - +#pragma mark Transaction Constants + +FOUNDATION_EXPORT NSUInteger const kFTransactionMaxRetries; +FOUNDATION_EXPORT NSString *const kFTransactionTooManyRetries; +FOUNDATION_EXPORT NSString *const kFTransactionNoData; +FOUNDATION_EXPORT NSString *const kFTransactionSet; +FOUNDATION_EXPORT NSString *const kFTransactionDisconnect; + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m new file mode 100644 index 0000000..1cf50ad --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Constants/FConstants.m @@ -0,0 +1,185 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConstants.h" + +#pragma mark - +#pragma mark Wire Protocol Envelope Constants + +NSString *const kFWPRequestType = @"t"; +NSString *const kFWPRequestTypeData = @"d"; +NSString *const kFWPRequestDataPayload = @"d"; +NSString *const kFWPRequestNumber = @"r"; +NSString *const kFWPRequestPayloadBody = @"b"; +NSString *const kFWPRequestError = @"error"; +NSString *const kFWPRequestAction = @"a"; +NSString *const kFWPResponseForRNData = @"b"; +NSString *const kFWPResponseForActionStatus = @"s"; +NSString *const kFWPResponseForActionStatusOk = @"ok"; +NSString *const kFWPResponseForActionStatusDataStale = @"datastale"; +NSString *const kFWPResponseForActionData = @"d"; +NSString *const kFWPResponseDataWarnings = @"w"; +NSString *const kFWPAsyncServerAction = @"a"; +NSString *const kFWPAsyncServerPayloadBody = @"b"; +NSString *const kFWPAsyncServerDataUpdate = @"d"; +NSString *const kFWPAsyncServerDataMerge = @"m"; +NSString *const kFWPAsyncServerDataRangeMerge = @"rm"; +NSString *const kFWPAsyncServerAuthRevoked = @"ac"; +NSString *const kFWPASyncServerListenCancelled = @"c"; +NSString *const kFWPAsyncServerSecurityDebug = @"sd"; +NSString *const kFWPAsyncServerDataUpdateBodyPath = + @"p"; // {“a”: “d”, “b”: {“p”: “/”, “d”: “”}} +NSString *const kFWPAsyncServerDataUpdateBodyData = @"d"; +NSString *const kFWPAsyncServerDataUpdateStartPath = @"s"; +NSString *const kFWPAsyncServerDataUpdateEndPath = @"e"; +NSString *const kFWPAsyncServerDataUpdateRangeMerge = @"m"; +NSString *const kFWPAsyncServerDataUpdateBodyTag = @"t"; +NSString *const kFWPAsyncServerDataQueries = @"q"; + +NSString *const kFWPAsyncServerEnvelopeType = @"t"; +NSString *const kFWPAsyncServerEnvelopeData = @"d"; +NSString *const kFWPAsyncServerControlMessage = @"c"; +NSString *const kFWPAsyncServerControlMessageType = @"t"; +NSString *const kFWPAsyncServerControlMessageData = @"d"; +NSString *const kFWPAsyncServerDataMessage = @"d"; + +NSString *const kFWPAsyncServerHello = @"h"; +NSString *const kFWPAsyncServerHelloTimestamp = @"ts"; +NSString *const kFWPAsyncServerHelloVersion = @"v"; +NSString *const kFWPAsyncServerHelloConnectedHost = @"h"; +NSString *const kFWPAsyncServerHelloSession = @"s"; + +NSString *const kFWPAsyncServerControlMessageShutdown = @"s"; +NSString *const kFWPAsyncServerControlMessageReset = @"r"; + +#pragma mark - +#pragma mark Wire Protocol Payload Constants + +NSString *const kFWPRequestActionPut = @"p"; +NSString *const kFWPRequestActionMerge = @"m"; +NSString *const kFWPRequestActionListen = + @"l"; // {"t": "d", "d": {"r": 1, "a": "l", "b": { "p": "/" } } } +NSString *const kFWPRequestActionUnlisten = @"u"; +NSString *const kFWPRequestActionStats = @"s"; +NSString *const kFWPRequestActionTaggedListen = @"q"; +NSString *const kFWPRequestActionTaggedUnlisten = @"n"; +NSString *const kFWPRequestActionDisconnectPut = @"o"; +NSString *const kFWPRequestActionDisconnectMerge = @"om"; +NSString *const kFWPRequestActionDisconnectCancel = @"oc"; +NSString *const kFWPRequestActionAuth = @"auth"; +NSString *const kFWPRequestActionUnauth = @"unauth"; +NSString *const kFWPRequestCredential = @"cred"; +NSString *const kFWPRequestPath = @"p"; +NSString *const kFWPRequestCounters = @"c"; +NSString *const kFWPRequestQueries = @"q"; +NSString *const kFWPRequestTag = @"t"; +NSString *const kFWPRequestData = @"d"; +NSString *const kFWPRequestHash = @"h"; +NSString *const kFWPRequestCompoundHash = @"ch"; +NSString *const kFWPRequestCompoundHashPaths = @"ps"; +NSString *const kFWPRequestCompoundHashHashes = @"hs"; +NSString *const kFWPRequestStatus = @"s"; + +#pragma mark - +#pragma mark Websock Transport Constants + +NSString *const kWireProtocolVersionParam = @"v"; +NSString *const kWebsocketProtocolVersion = @"5"; +NSString *const kWebsocketServerKillPacket = @"kill"; +const int kWebsocketMaxFrameSize = 16384; +NSUInteger const kWebsocketKeepaliveInterval = 45; +NSUInteger const kWebsocketConnectTimeout = 30; + +float const kPersistentConnReconnectMinDelay = 1.0; +float const kPersistentConnReconnectMaxDelay = 30.0; +float const kPersistentConnReconnectMultiplier = 1.3f; +float const kPersistentConnSuccessfulConnectionEstablishedDelay = 30.0; + +#pragma mark - +#pragma mark Query constants + +NSString *const kQueryDefault = @"default"; +NSString *const kQueryDefaultObject = @"{}"; +NSString *const kViewManagerDictConstView = @"view"; +NSString *const kFQPIndexStartValue = @"sp"; +NSString *const kFQPIndexStartName = @"sn"; +NSString *const kFQPIndexEndValue = @"ep"; +NSString *const kFQPIndexEndName = @"en"; +NSString *const kFQPLimit = @"l"; +NSString *const kFQPViewFrom = @"vf"; +NSString *const kFQPViewFromLeft = @"l"; +NSString *const kFQPViewFromRight = @"r"; +NSString *const kFQPIndex = @"i"; + +#pragma mark - +#pragma mark Interrupt Reasons + +NSString *const kFInterruptReasonServerKill = @"server_kill"; +NSString *const kFInterruptReasonWaitingForOpen = @"waiting_for_open"; +NSString *const kFInterruptReasonRepoInterrupt = @"repo_interrupt"; + +#pragma mark - +#pragma mark Payload constants + +NSString *const kPayloadPriority = @".priority"; +NSString *const kPayloadValue = @".value"; +NSString *const kPayloadMetadataPrefix = @"."; + +#pragma mark - +#pragma mark ServerValue constants + +NSString *const kServerValueSubKey = @".sv"; +NSString *const kServerValuePriority = @"timestamp"; + +#pragma mark - +#pragma mark.info/ constants + +NSString *const kDotInfoPrefix = @".info"; +NSString *const kDotInfoConnected = @"connected"; +NSString *const kDotInfoServerTimeOffset = @"serverTimeOffset"; + +#pragma mark - +#pragma mark ObjectiveC to JavaScript type constants + +NSString *const kJavaScriptObject = @"object"; +NSString *const kJavaScriptString = @"string"; +NSString *const kJavaScriptBoolean = @"boolean"; +NSString *const kJavaScriptNumber = @"number"; +NSString *const kJavaScriptNull = @"null"; +NSString *const kJavaScriptTrue = @"true"; +NSString *const kJavaScriptFalse = @"false"; + +#pragma mark - +#pragma mark Error handling constants + +NSString *const kFErrorDomain = @"com.firebase"; +NSUInteger const kFAuthError = 1; +NSString *const kFErrorWriteCanceled = @"write_canceled"; + +#pragma mark - +#pragma mark Validation Constants + +NSUInteger const kFirebaseMaxObjectDepth = 1000; +const unsigned int kFirebaseMaxLeafSize = 1024 * 1024 * 10; // 10 MB + +#pragma mark - +#pragma mark Transaction Constants + +NSUInteger const kFTransactionMaxRetries = 25; +NSString *const kFTransactionTooManyRetries = @"maxretry"; +NSString *const kFTransactionNoData = @"nodata"; +NSString *const kFTransactionSet = @"set"; +NSString *const kFTransactionDisconnect = @"disconnect"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h new file mode 100644 index 0000000..2453a81 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +@interface FCompoundHashBuilder : NSObject + +- (FPath *)currentPath; + +@end + +typedef BOOL (^FCompoundHashSplitStrategy)(FCompoundHashBuilder *builder); + +@interface FCompoundHash : NSObject + +@property(nonatomic, strong, readonly) NSArray *posts; +@property(nonatomic, strong, readonly) NSArray *hashes; + ++ (FCompoundHash *)fromNode:(id)node; ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m new file mode 100644 index 0000000..ced79cd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FCompoundHash.m @@ -0,0 +1,259 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundHash.h" +#import "FChildrenNode.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" + +@interface FCompoundHashBuilder () + +@property(nonatomic, strong) FCompoundHashSplitStrategy splitStrategy; + +@property(nonatomic, strong) NSMutableArray *currentPaths; +@property(nonatomic, strong) NSMutableArray *currentHashes; + +@end + +@implementation FCompoundHashBuilder { + + // NOTE: We use the existence of this to know if we've started building a + // range (i.e. encountered a leaf node). + NSMutableString *optHashValueBuilder; + + // The current path as a stack. This is used in combination with + // currentPathDepth to simultaneously store the last leaf node path. The + // depth is changed when descending and ascending, at the same time the + // current key is set for the current depth. Because the keys are left + // unchanged for ascending the path will also contain the path of the last + // visited leaf node (using lastLeafDepth elements) + NSMutableArray *currentPath; + NSInteger lastLeafDepth; + NSInteger currentPathDepth; + + BOOL needsComma; +} + +- (instancetype)initWithSplitStrategy:(FCompoundHashSplitStrategy)strategy { + self = [super init]; + if (self != nil) { + self->_splitStrategy = strategy; + self->optHashValueBuilder = nil; + self->currentPath = [NSMutableArray array]; + self->lastLeafDepth = -1; + self->currentPathDepth = 0; + self->needsComma = YES; + self->_currentPaths = [NSMutableArray array]; + self->_currentHashes = [NSMutableArray array]; + } + return self; +} + +- (BOOL)isBuildingRange { + return self->optHashValueBuilder != nil; +} + +- (NSUInteger)currentHashLength { + return self->optHashValueBuilder.length; +} + +- (FPath *)currentPath { + return [self currentPathWithDepth:self->currentPathDepth]; +} + +- (FPath *)currentPathWithDepth:(NSInteger)depth { + NSArray *pieces = + [self->currentPath subarrayWithRange:NSMakeRange(0, depth)]; + return [[FPath alloc] initWithPieces:pieces andPieceNum:0]; +} + +- (void)enumerateCurrentPathToDepth:(NSInteger)depth + withBlock:(void (^)(NSString *key))block { + for (NSInteger i = 0; i < depth; i++) { + block(self->currentPath[i]); + } +} + +- (void)appendKey:(NSString *)key toString:(NSMutableString *)string { + [FSnapshotUtilities appendHashV2RepresentationForString:key + toString:string]; +} + +- (void)ensureRange { + if (![self isBuildingRange]) { + optHashValueBuilder = [NSMutableString string]; + [optHashValueBuilder appendString:@"("]; + [self + enumerateCurrentPathToDepth:self->currentPathDepth + withBlock:^(NSString *key) { + [self appendKey:key + toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + }]; + self->needsComma = NO; + } +} + +- (void)processLeaf:(FLeafNode *)leafNode { + [self ensureRange]; + + self->lastLeafDepth = self->currentPathDepth; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode + toString:self->optHashValueBuilder + hashVersion:FDataHashVersionV2]; + self->needsComma = YES; + if (self.splitStrategy(self)) { + [self endRange]; + } +} + +- (void)startChild:(NSString *)key { + [self ensureRange]; + + if (self->needsComma) { + [self->optHashValueBuilder appendString:@","]; + } + [self appendKey:key toString:self->optHashValueBuilder]; + [self->optHashValueBuilder appendString:@":("]; + if (self->currentPathDepth == currentPath.count) { + [self->currentPath addObject:key]; + } else { + self->currentPath[self->currentPathDepth] = key; + } + self->currentPathDepth++; + self->needsComma = NO; +} + +- (void)endChild { + self->currentPathDepth--; + if ([self isBuildingRange]) { + [self->optHashValueBuilder appendString:@")"]; + } + self->needsComma = YES; +} + +- (void)finishHashing { + NSAssert(self->currentPathDepth == 0, + @"Can't finish hashing in the middle of processing a child"); + if ([self isBuildingRange]) { + [self endRange]; + } + + // Always close with the empty hash for the remaining range to allow simple + // appending + [self.currentHashes addObject:@""]; +} + +- (void)endRange { + NSAssert([self isBuildingRange], + @"Can't end range without starting a range!"); + // Add closing parenthesis for current depth + for (NSUInteger i = 0; i < currentPathDepth; i++) { + [self->optHashValueBuilder appendString:@")"]; + } + [self->optHashValueBuilder appendString:@")"]; + + FPath *lastLeafPath = [self currentPathWithDepth:self->lastLeafDepth]; + NSString *hash = + [FStringUtilities base64EncodedSha1:self->optHashValueBuilder]; + [self.currentHashes addObject:hash]; + [self.currentPaths addObject:lastLeafPath]; + + self->optHashValueBuilder = nil; +} + +@end + +@interface FCompoundHash () + +@property(nonatomic, strong, readwrite) NSArray *posts; +@property(nonatomic, strong, readwrite) NSArray *hashes; + +@end + +@implementation FCompoundHash + +- (id)initWithPosts:(NSArray *)posts hashes:(NSArray *)hashes { + self = [super init]; + if (self != nil) { + if (posts.count != hashes.count - 1) { + [NSException raise:NSInvalidArgumentException + format:@"Number of posts need to be n-1 for n hashes " + @"in FCompoundHash"]; + } + self.posts = posts; + self.hashes = hashes; + } + return self; +} + ++ (FCompoundHashSplitStrategy)simpleSizeSplitStrategyForNode:(id)node { + NSUInteger estimatedSize = + [FSnapshotUtilities estimateSerializedNodeSize:node]; + + // Splits for + // 1k -> 512 (2 parts) + // 5k -> 715 (7 parts) + // 100k -> 3.2k (32 parts) + // 500k -> 7k (71 parts) + // 5M -> 23k (228 parts) + NSUInteger splitThreshold = MAX(512, (NSUInteger)sqrt(estimatedSize * 100)); + + return ^BOOL(FCompoundHashBuilder *builder) { + // Never split on priorities + return [builder currentHashLength] > splitThreshold && + ![[[builder currentPath] getBack] isEqualToString:@".priority"]; + }; +} + ++ (FCompoundHash *)fromNode:(id)node { + return [FCompoundHash + fromNode:node + splitStrategy:[FCompoundHash simpleSizeSplitStrategyForNode:node]]; +} + ++ (FCompoundHash *)fromNode:(id)node + splitStrategy:(FCompoundHashSplitStrategy)strategy { + if ([node isEmpty]) { + return [[FCompoundHash alloc] initWithPosts:@[] hashes:@[ @"" ]]; + } else { + FCompoundHashBuilder *builder = + [[FCompoundHashBuilder alloc] initWithSplitStrategy:strategy]; + [FCompoundHash processNode:node builder:builder]; + [builder finishHashing]; + return [[FCompoundHash alloc] initWithPosts:builder.currentPaths + hashes:builder.currentHashes]; + } +} + ++ (void)processNode:(id)node builder:(FCompoundHashBuilder *)builder { + if ([node isLeafNode]) { + [builder processLeaf:node]; + } else { + NSAssert(![node isEmpty], @"Can't calculate hash on empty node!"); + FChildrenNode *childrenNode = (FChildrenNode *)node; + [childrenNode enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [builder startChild:key]; + [self processNode:node builder:builder]; + [builder endChild]; + }]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h new file mode 100644 index 0000000..8efd803 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" + +@class FQuerySpec; +@protocol FSyncTreeHash; + +typedef NSArray * (^fbt_startListeningBlock)(FQuerySpec *query, NSNumber *tagId, + id hash, + fbt_nsarray_nsstring onComplete); +typedef void (^fbt_stopListeningBlock)(FQuerySpec *query, NSNumber *tagId); + +@interface FListenProvider : NSObject + +@property(nonatomic, copy) fbt_startListeningBlock startListening; +@property(nonatomic, copy) fbt_stopListeningBlock stopListening; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m new file mode 100644 index 0000000..27da015 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FListenProvider.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenProvider.h" +#import "FIRDatabaseQuery.h" + +@implementation FListenProvider + +@synthesize startListening; +@synthesize stopListening; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h new file mode 100644 index 0000000..81836fd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.h @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FRepoInfo.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@protocol FPersistentConnectionDelegate; +@protocol FSyncTreeHash; +@class FQuerySpec; +@class FIRDatabaseConfig; + +@interface FPersistentConnection : NSObject + +@property(nonatomic, weak) id delegate; +@property(nonatomic) BOOL pauseWrites; + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)queue + config:(FIRDatabaseConfig *)config; + +- (void)open; + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete; +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete; + +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete; + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId; +- (void)refreshAuthToken:(NSString *)token; +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback; +- (void)ackPuts; +- (void)purgeOutstandingWrites; + +- (void)interruptForReason:(NSString *)reason; +- (void)resumeForReason:(NSString *)reason; +- (BOOL)isInterruptedForReason:(NSString *)reason; + +// FConnection delegate methods +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +// Testing methods +- (NSDictionary *)dumpListens; + +@end + +@protocol FPersistentConnectionDelegate + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)path + tagId:(NSNumber *)tag; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m new file mode 100644 index 0000000..69f52c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FPersistentConnection.m @@ -0,0 +1,1141 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import "FAtomicNumber.h" +#import "FAuthTokenProvider.h" +#import "FCompoundHash.h" +#import "FConstants.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseReference.h" +#import "FIRRetryHelper.h" +#import "FIndex.h" +#import "FPersistentConnection.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTupleCallbackStatus.h" +#import "FTupleOnDisconnect.h" +#import "FUtilities.h" +#import +#import +#import +#import + +@interface FOutstandingQuery : NSObject + +@property(nonatomic, strong) FQuerySpec *query; +@property(nonatomic, strong) NSNumber *tagId; +@property(nonatomic, strong) id syncTreeHash; +@property(nonatomic, copy) fbt_void_nsstring onComplete; + +@end + +@implementation FOutstandingQuery + +@end + +@interface FOutstandingPut : NSObject + +@property(nonatomic, strong) NSString *action; +@property(nonatomic, strong) NSDictionary *request; +@property(nonatomic, copy) fbt_void_nsstring_nsstring onCompleteBlock; +@property(nonatomic) BOOL sent; + +@end + +@implementation FOutstandingPut + +@end + +typedef enum { + ConnectionStateDisconnected, + ConnectionStateGettingToken, + ConnectionStateConnecting, + ConnectionStateAuthenticating, + ConnectionStateConnected +} ConnectionState; + +@interface FPersistentConnection () { + ConnectionState connectionState; + BOOL firstConnection; + NSTimeInterval reconnectDelay; + NSTimeInterval lastConnectionAttemptTime; + NSTimeInterval lastConnectionEstablishedTime; + SCNetworkReachabilityRef reachability; +} + +- (int)getNextRequestNumber; +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body; +- (void)handleTimestamp:(NSNumber *)timestamp; +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback; + +@property(nonatomic, strong) FConnection *realtime; +@property(nonatomic, strong) NSMutableDictionary *listens; +@property(nonatomic, strong) NSMutableDictionary *outstandingPuts; +@property(nonatomic, strong) NSMutableArray *onDisconnectQueue; +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FAtomicNumber *putCounter; +@property(nonatomic, strong) FAtomicNumber *requestNumber; +@property(nonatomic, strong) NSMutableDictionary *requestCBHash; +@property(nonatomic, strong) FIRDatabaseConfig *config; +@property(nonatomic) NSUInteger unackedListensCount; +@property(nonatomic, strong) NSMutableArray *putsToAck; +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic, strong) NSString *lastSessionID; +@property(nonatomic, strong) NSMutableSet *interruptReasons; +@property(nonatomic, strong) FIRRetryHelper *retryHelper; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) NSString *authToken; +@property(nonatomic) BOOL forceAuthTokenRefresh; +@property(nonatomic) NSUInteger currentFetchTokenAttempt; + +@end + +@implementation FPersistentConnection + +- (id)initWithRepoInfo:(FRepoInfo *)repoInfo + dispatchQueue:(dispatch_queue_t)dispatchQueue + config:(FIRDatabaseConfig *)config { + self = [super init]; + if (self) { + self->_config = config; + self->_repoInfo = repoInfo; + self->_dispatchQueue = dispatchQueue; + self->_authTokenProvider = config.authTokenProvider; + NSAssert(self->_authTokenProvider != nil, + @"Expected auth token provider"); + self.interruptReasons = [NSMutableSet set]; + + self.listens = [[NSMutableDictionary alloc] init]; + self.outstandingPuts = [[NSMutableDictionary alloc] init]; + self.onDisconnectQueue = [[NSMutableArray alloc] init]; + self.putCounter = [[FAtomicNumber alloc] init]; + self.requestNumber = [[FAtomicNumber alloc] init]; + self.requestCBHash = [[NSMutableDictionary alloc] init]; + self.unackedListensCount = 0; + self.putsToAck = [NSMutableArray array]; + connectionState = ConnectionStateDisconnected; + firstConnection = YES; + reconnectDelay = kPersistentConnReconnectMinDelay; + + self->_retryHelper = [[FIRRetryHelper alloc] + initWithDispatchQueue:dispatchQueue + minRetryDelayAfterFailure:kPersistentConnReconnectMinDelay + maxRetryDelay:kPersistentConnReconnectMaxDelay + retryExponent:kPersistentConnReconnectMultiplier + jitterFactor:0.7]; + + [self setupNotifications]; + // Make sure we don't actually connect until open is called + [self interruptForReason:kFInterruptReasonWaitingForOpen]; + } + // nb: The reason establishConnection isn't called here like the JS version + // is because callers need to set the delegate first. The ctor can be + // modified to accept the delegate but that deviates from normal ios + // conventions. After the delegate has been set, the caller is responsible + // for calling establishConnection: + return self; +} + +- (void)dealloc { + if (reachability) { + // Unschedule the notifications + SCNetworkReachabilitySetDispatchQueue(reachability, NULL); + CFRelease(reachability); + } +} + +#pragma mark - +#pragma mark Public methods + +- (void)open { + [self resumeForReason:kFInterruptReasonWaitingForOpen]; +} + +/** + * Note that the listens dictionary has a type of Map[String (pathString), + * Map[FQueryParams, FOutstandingQuery]] + * + * This means, for each path we care about, there are sets of queryParams that + * correspond to an FOutstandingQuery object. There can be multiple sets at a + * path since we overlap listens for a short time while adding or removing a + * query from a location in the tree. + */ +- (void)listen:(FQuerySpec *)query + tagId:(NSNumber *)tagId + hash:(id)hash + onComplete:(fbt_void_nsstring)onComplete { + FFLog(@"I-RDB034001", @"Listen called for %@", query); + + NSAssert(self.listens[query] == nil, + @"listen() called twice for the same query"); + NSAssert(query.isDefault || !query.loadsAllData, + @"listen called for non-default but complete query"); + FOutstandingQuery *outstanding = [[FOutstandingQuery alloc] init]; + outstanding.query = query; + outstanding.tagId = tagId; + outstanding.syncTreeHash = hash; + outstanding.onComplete = onComplete; + [self.listens setObject:outstanding forKey:query]; + if ([self connected]) { + [self sendListen:outstanding]; + } +} + +- (void)putData:(id)data + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionPut + forPath:pathString + withHash:hash + withCallback:onComplete]; +} + +- (void)mergeData:(id)data + forPath:(NSString *)pathString + withCallback:(fbt_void_nsstring_nsstring)onComplete { + [self putInternal:data + forAction:kFWPRequestActionMerge + forPath:pathString + withHash:nil + withCallback:onComplete]; +} + +- (void)onDisconnectPutData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectPut + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectPut; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectMergeData:(id)data + forPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectMerge + forPath:[path description] + withData:data + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectMerge; + tuple.data = data; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)onDisconnectCancelPath:(FPath *)path + withCallback:(fbt_void_nsstring_nsstring)callback { + if ([self canSendWrites]) { + [self sendOnDisconnectAction:kFWPRequestActionDisconnectCancel + forPath:[path description] + withData:[NSNull null] + andCallback:callback]; + } else { + FTupleOnDisconnect *tuple = [[FTupleOnDisconnect alloc] init]; + tuple.pathString = [path description]; + tuple.action = kFWPRequestActionDisconnectCancel; + tuple.data = [NSNull null]; + tuple.onComplete = callback; + [self.onDisconnectQueue addObject:tuple]; + } +} + +- (void)unlisten:(FQuerySpec *)query tagId:(NSNumber *)tagId { + FPath *path = query.path; + FFLog(@"I-RDB034002", @"Unlistening for %@", query); + + NSArray *outstanding = [self removeListen:query]; + if (outstanding.count > 0 && [self connected]) { + [self sendUnlisten:path queryParams:query.params tagId:tagId]; + } +} + +- (void)refreshAuthToken:(NSString *)token { + self.authToken = token; + if ([self connected]) { + if (token != nil) { + [self sendAuthAndRestoreStateAfterComplete:NO]; + } else { + [self sendUnauth]; + } + } +} + +#pragma mark - +#pragma mark Connection status + +- (BOOL)connected { + return self->connectionState == ConnectionStateAuthenticating || + self->connectionState == ConnectionStateConnected; +} + +- (BOOL)canSendWrites { + return self->connectionState == ConnectionStateConnected; +} + +#pragma mark - +#pragma mark FConnection delegate methods + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB034003", @"On ready"); + lastConnectionEstablishedTime = [[NSDate date] timeIntervalSince1970]; + [self handleTimestamp:timestamp]; + + if (firstConnection) { + [self sendConnectStats]; + } + + [self restoreAuth]; + firstConnection = NO; + self.lastSessionID = sessionID; + dispatch_async(self.dispatchQueue, ^{ + [self.delegate onConnect:self]; + }); +} + +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message { + if (message[kFWPRequestNumber] != nil) { + // this is a response to a request we sent + NSNumber *rn = [NSNumber + numberWithInt:[[message objectForKey:kFWPRequestNumber] intValue]]; + if ([self.requestCBHash objectForKey:rn]) { + void (^callback)(NSDictionary *) = + [self.requestCBHash objectForKey:rn]; + [self.requestCBHash removeObjectForKey:rn]; + + if (callback) { + // dispatch_async(self.dispatchQueue, ^{ + callback([message objectForKey:kFWPResponseForRNData]); + //}); + } + } + } else if (message[kFWPRequestError] != nil) { + NSString *error = [message objectForKey:kFWPRequestError]; + @throw [[NSException alloc] initWithName:@"FirebaseDatabaseServerError" + reason:error + userInfo:nil]; + } else if (message[kFWPAsyncServerAction] != nil) { + // this is a server push of some sort + NSString *action = [message objectForKey:kFWPAsyncServerAction]; + NSDictionary *body = [message objectForKey:kFWPAsyncServerPayloadBody]; + [self onDataPushWithAction:action andBody:body]; + } +} + +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason { + FFLog(@"I-RDB034004", @"Got on disconnect due to %s", + (reason == DISCONNECT_REASON_SERVER_RESET) ? "server_reset" + : "other"); + connectionState = ConnectionStateDisconnected; + // Drop the realtime connection + self.realtime = nil; + [self cancelSentTransactions]; + [self.requestCBHash removeAllObjects]; + self.unackedListensCount = 0; + if ([self shouldReconnect]) { + NSTimeInterval timeSinceLastConnectSucceeded = + [[NSDate date] timeIntervalSince1970] - + lastConnectionEstablishedTime; + BOOL lastConnectionWasSuccessful; + if (lastConnectionEstablishedTime > 0) { + lastConnectionWasSuccessful = + timeSinceLastConnectSucceeded > + kPersistentConnSuccessfulConnectionEstablishedDelay; + } else { + lastConnectionWasSuccessful = NO; + } + + if (reason == DISCONNECT_REASON_SERVER_RESET || + lastConnectionWasSuccessful) { + [self.retryHelper signalSuccess]; + } + [self tryScheduleReconnect]; + } + lastConnectionEstablishedTime = 0; + [self.delegate onDisconnect:self]; +} + +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason { + FFWarn(@"I-RDB034005", + @"Firebase Database connection was forcefully killed by the server. " + @" Will not attempt reconnect. Reason: %@", + reason); + [self interruptForReason:kFInterruptReasonServerKill]; +} + +#pragma mark - +#pragma mark Connection handling methods + +- (void)interruptForReason:(NSString *)reason { + FFLog(@"I-RDB034006", @"Connection interrupted for: %@", reason); + + [self.interruptReasons addObject:reason]; + if (self.realtime) { + // Will call onDisconnect and set the connection state to Disconnected + [self.realtime close]; + self.realtime = nil; + } else { + [self.retryHelper cancel]; + self->connectionState = ConnectionStateDisconnected; + } + // Reset timeouts + [self.retryHelper signalSuccess]; +} + +- (void)resumeForReason:(NSString *)reason { + FFLog(@"I-RDB034007", @"Connection no longer interrupted for: %@", reason); + [self.interruptReasons removeObject:reason]; + + if ([self shouldReconnect] && + connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } +} + +- (BOOL)shouldReconnect { + return self.interruptReasons.count == 0; +} + +- (BOOL)isInterruptedForReason:(NSString *)reason { + return [self.interruptReasons containsObject:reason]; +} + +#pragma mark - +#pragma mark Private methods + +- (void)tryScheduleReconnect { + if ([self shouldReconnect]) { + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + BOOL forceRefresh = self.forceAuthTokenRefresh; + self.forceAuthTokenRefresh = NO; + FFLog(@"I-RDB034008", @"Scheduling connection attempt"); + [self.retryHelper retry:^{ + FFLog(@"I-RDB034009", @"Trying to fetch auth token"); + NSAssert(self->connectionState == ConnectionStateDisconnected, + @"Not in disconnected state: %d", self->connectionState); + self->connectionState = ConnectionStateGettingToken; + self.currentFetchTokenAttempt++; + NSUInteger thisFetchTokenAttempt = self.currentFetchTokenAttempt; + [self.authTokenProvider + fetchTokenForcingRefresh:forceRefresh + withCallback:^(NSString *token, NSError *error) { + if (thisFetchTokenAttempt == + self.currentFetchTokenAttempt) { + if (error != nil) { + self->connectionState = + ConnectionStateDisconnected; + FFLog(@"I-RDB034010", + @"Error fetching token: %@", error); + [self tryScheduleReconnect]; + } else { + // Someone could have interrupted us while + // fetching the token, marking the + // connection as Disconnected + if (self->connectionState == + ConnectionStateGettingToken) { + FFLog(@"I-RDB034011", + @"Successfully fetched token, " + @"opening connection"); + [self openNetworkConnectionWithToken: + token]; + } else { + NSAssert( + self->connectionState == + ConnectionStateDisconnected, + @"Expected connection state " + @"disconnected, but got %d", + self->connectionState); + FFLog(@"I-RDB034012", + @"Not opening connection after " + @"token refresh, because " + @"connection was set to " + @"disconnected."); + } + } + } else { + FFLog(@"I-RDB034013", + @"Ignoring fetch token result, because " + @"this was not the latest attempt."); + } + }]; + }]; + } +} + +- (void)openNetworkConnectionWithToken:(NSString *)token { + NSAssert(self->connectionState == ConnectionStateGettingToken, + @"Trying to open network connection while in wrong state: %d", + self->connectionState); + self.authToken = token; + self->connectionState = ConnectionStateConnecting; + self.realtime = [[FConnection alloc] initWith:self.repoInfo + andDispatchQueue:self.dispatchQueue + lastSessionID:self.lastSessionID]; + self.realtime.delegate = self; + [self.realtime open]; +} + +static void reachabilityCallback(SCNetworkReachabilityRef ref, + SCNetworkReachabilityFlags flags, void *info) { + if (flags & kSCNetworkReachabilityFlagsReachable) { + FFLog(@"I-RDB034014", + @"Network became reachable. Trigger a connection attempt"); + FPersistentConnection *self = (__bridge FPersistentConnection *)info; + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + } else { + FFLog(@"I-RDB034015", @"Network is not reachable"); + } +} + +- (void)enteringForeground { + dispatch_async(self.dispatchQueue, ^{ + // Reset reconnect delay + [self.retryHelper signalSuccess]; + if (self->connectionState == ConnectionStateDisconnected) { + [self tryScheduleReconnect]; + } + }); +} + +- (void)setupNotifications { + + NSString *const *foregroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationWillEnterForegroundNotification"); + if (foregroundConstant) { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(enteringForeground) + name:*foregroundConstant + object:nil]; + } + // An empty address is interpreted a generic internet access + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + reachability = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + SCNetworkReachabilityContext ctx = {0, (__bridge void *)(self), NULL, NULL, + NULL}; + if (SCNetworkReachabilitySetCallback(reachability, reachabilityCallback, + &ctx)) { + SCNetworkReachabilitySetDispatchQueue(reachability, self.dispatchQueue); + } else { + FFLog(@"I-RDB034016", + @"Failed to set up network reachability monitoring"); + CFRelease(reachability); + reachability = NULL; + } +} + +- (void)sendAuthAndRestoreStateAfterComplete:(BOOL)restoreStateAfterComplete { + NSAssert([self connected], @"Must be connected to send auth"); + NSAssert(self.authToken != nil, + @"Can't send auth if there is no credential"); + + NSDictionary *requestData = @{kFWPRequestCredential : self.authToken}; + [self sendAction:kFWPRequestActionAuth + body:requestData + sensitive:YES + callback:^(NSDictionary *data) { + self->connectionState = ConnectionStateConnected; + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + id responseData = [data objectForKey:kFWPResponseForActionData]; + if (responseData == nil) { + responseData = @"error"; + } + + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (statusOk) { + if (restoreStateAfterComplete) { + [self restoreState]; + } + } else { + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034017", @"Authentication failed: %@ (%@)", + status, responseData); + } else { + FFWarn(@"I-RDB034018", @"Authentication failed: %@ (%@)", + status, responseData); + } + [self.realtime close]; + } + }]; +} + +- (void)sendUnauth { + [self sendAction:kFWPRequestActionUnauth + body:@{} + sensitive:NO + callback:nil]; +} + +- (void)onAuthRevokedWithStatus:(NSString *)status + andReason:(NSString *)reason { + // This might be for an earlier token than we just recently sent. But since + // we need to close the connection anyways, we can set it to null here and + // we will refresh the token later on reconnect + if ([status isEqualToString:@"expired_token"]) { + FFLog(@"I-RDB034019", @"Auth token revoked: %@ (%@)", status, reason); + } else { + FFWarn(@"I-RDB034020", @"Auth token revoked: %@ (%@)", status, reason); + } + self.authToken = nil; + self.forceAuthTokenRefresh = YES; + // Try reconnecting on auth revocation + [self.realtime close]; +} + +- (void)onListenRevoked:(FPath *)path { + NSArray *queries = [self removeAllListensAtPath:path]; + for (FOutstandingQuery *query in queries) { + query.onComplete(@"permission_denied"); + } +} + +- (void)sendOnDisconnectAction:(NSString *)action + forPath:(NSString *)pathString + withData:(id)data + andCallback:(fbt_void_nsstring_nsstring)callback { + + NSDictionary *request = + @{kFWPRequestPath : pathString, kFWPRequestData : data}; + FFLog(@"I-RDB034021", @"onDisconnect %@: %@", action, request); + + [self sendAction:action + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + callback(status, errorReason); + }]; +} + +- (void)sendPut:(NSNumber *)index { + NSAssert([self canSendWrites], + @"sendPut called when not able to send writes"); + FOutstandingPut *put = self.outstandingPuts[index]; + assert(put != nil); + fbt_void_nsstring_nsstring onComplete = put.onCompleteBlock; + + // Do not async this block; copying the block insinde sendAction: doesn't + // happen in time (or something) so coredumps + put.sent = YES; + [self sendAction:put.action + body:put.request + sensitive:NO + callback:^(NSDictionary *data) { + FOutstandingPut *currentPut = self.outstandingPuts[index]; + if (currentPut == put) { + [self.outstandingPuts removeObjectForKey:index]; + + if (onComplete != nil) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + if (self.unackedListensCount == 0) { + onComplete(status, errorReason); + } else { + FTupleCallbackStatus *putToAck = + [[FTupleCallbackStatus alloc] init]; + putToAck.block = onComplete; + putToAck.status = status; + putToAck.errorReason = errorReason; + [self.putsToAck addObject:putToAck]; + } + } + } else { + FFLog(@"I-RDB034022", + @"Ignoring on complete for put %@ because it was " + @"already removed", + index); + } + }]; +} + +- (void)sendUnlisten:(FPath *)path + queryParams:(FQueryParams *)queryParams + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB034023", @"Unlisten on %@ for %@", path, queryParams); + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:[path toString], kFWPRequestPath, nil]; + if (tagId != nil) { + [request setObject:queryParams.wireProtocolParams + forKey:kFWPRequestQueries]; + [request setObject:tagId forKey:kFWPRequestTag]; + } + + [self sendAction:kFWPRequestActionTaggedUnlisten + body:request + sensitive:NO + callback:nil]; +} + +- (void)putInternal:(id)data + forAction:(NSString *)action + forPath:(NSString *)pathString + withHash:(NSString *)hash + withCallback:(fbt_void_nsstring_nsstring)onComplete { + + NSMutableDictionary *request = [NSMutableDictionary + dictionaryWithObjectsAndKeys:pathString, kFWPRequestPath, data, + kFWPRequestData, nil]; + if (hash) { + [request setObject:hash forKey:kFWPRequestHash]; + } + + FOutstandingPut *put = [[FOutstandingPut alloc] init]; + put.action = action; + put.request = request; + put.onCompleteBlock = onComplete; + put.sent = NO; + + NSNumber *index = [self.putCounter getAndIncrement]; + self.outstandingPuts[index] = put; + + if ([self canSendWrites]) { + FFLog(@"I-RDB034024", @"Was connected, and added as index: %@", index); + [self sendPut:index]; + } else { + FFLog(@"I-RDB034025", + @"Wasn't connected or writes paused, so added to outstanding " + @"puts only. Path: %@", + pathString); + } +} + +- (void)sendListen:(FOutstandingQuery *)listenSpec { + FQuerySpec *query = listenSpec.query; + FFLog(@"I-RDB034026", @"Listen for %@", query); + NSMutableDictionary *request = + [NSMutableDictionary dictionaryWithObject:[query.path toString] + forKey:kFWPRequestPath]; + + // Only bother to send query if it's non-default + if (listenSpec.tagId != nil) { + [request setObject:[query.params wireProtocolParams] + forKey:kFWPRequestQueries]; + [request setObject:listenSpec.tagId forKey:kFWPRequestTag]; + } + + [request setObject:[listenSpec.syncTreeHash simpleHash] + forKey:kFWPRequestHash]; + if ([listenSpec.syncTreeHash includeCompoundHash]) { + FCompoundHash *compoundHash = [listenSpec.syncTreeHash compoundHash]; + NSMutableArray *posts = [NSMutableArray array]; + for (FPath *path in compoundHash.posts) { + [posts addObject:path.wireFormat]; + } + request[kFWPRequestCompoundHash] = @{ + kFWPRequestCompoundHashHashes : compoundHash.hashes, + kFWPRequestCompoundHashPaths : posts + }; + } + + fbt_void_nsdictionary onResponse = ^(NSDictionary *response) { + FFLog(@"I-RDB034027", @"Listen response %@", response); + // warn in any case, even if the listener was removed + [self warnOnListenWarningsForQuery:query + payload:response[kFWPResponseForActionData]]; + + FOutstandingQuery *currentListenSpec = self.listens[query]; + + // only trigger actions if the listen hasn't been removed (and maybe + // readded) + if (currentListenSpec == listenSpec) { + NSString *status = [response objectForKey:kFWPRequestStatus]; + if (![status isEqualToString:@"ok"]) { + [self removeListen:query]; + } + + if (listenSpec.onComplete) { + listenSpec.onComplete(status); + } + } + + self.unackedListensCount--; + NSAssert(self.unackedListensCount >= 0, + @"unackedListensCount decremented to be negative."); + if (self.unackedListensCount == 0) { + [self ackPuts]; + } + }; + + [self sendAction:kFWPRequestActionTaggedListen + body:request + sensitive:NO + callback:onResponse]; + + self.unackedListensCount++; +} + +- (void)warnOnListenWarningsForQuery:(FQuerySpec *)query payload:(id)payload { + if (payload != nil && [payload isKindOfClass:[NSDictionary class]]) { + NSDictionary *payloadDict = payload; + id warnings = payloadDict[kFWPResponseDataWarnings]; + if (warnings != nil && [warnings isKindOfClass:[NSArray class]]) { + NSArray *warningsArr = warnings; + if ([warningsArr containsObject:@"no_index"]) { + NSString *indexSpec = [NSString + stringWithFormat:@"\".indexOn\": \"%@\"", + [query.params.index queryDefinition]]; + NSString *indexPath = [query.path description]; + FFWarn(@"I-RDB034028", + @"Using an unspecified index. Your data will be " + @"downloaded and filtered on the client. " + "Consider adding %@ at %@ to your security rules for " + "better performance", + indexSpec, indexPath); + } + } + } +} + +- (int)getNextRequestNumber { + return [[self.requestNumber getAndIncrement] intValue]; +} + +- (void)sendAction:(NSString *)action + body:(NSDictionary *)message + sensitive:(BOOL)sensitive + callback:(void (^)(NSDictionary *data))onMessage { + // Hold onto the onMessage callback for this request before firing it off + NSNumber *rn = [NSNumber numberWithInt:[self getNextRequestNumber]]; + NSDictionary *msg = [NSDictionary + dictionaryWithObjectsAndKeys:rn, kFWPRequestNumber, action, + kFWPRequestAction, message, + kFWPRequestPayloadBody, nil]; + + [self.realtime sendRequest:msg sensitive:sensitive]; + + if (onMessage) { + // Debug message without a callback; bump the rn, but don't hold onto + // the cb + [self.requestCBHash setObject:[onMessage copy] forKey:rn]; + } +} + +- (void)cancelSentTransactions { + NSMutableDictionary + *cancelledOutstandingPuts = [[NSMutableDictionary alloc] init]; + + for (NSNumber *index in self.outstandingPuts) { + FOutstandingPut *put = self.outstandingPuts[index]; + if (put.request[kFWPRequestHash] && put.sent) { + // This is a sent transaction put. + cancelledOutstandingPuts[index] = put; + } + } + + [cancelledOutstandingPuts + enumerateKeysAndObjectsUsingBlock:^( + NSNumber *index, FOutstandingPut *outstandingPut, BOOL *stop) { + // `onCompleteBlock:` may invoke `rerunTransactionsForPath:` and + // enqueue new writes. We defer calling it until we have finished + // enumerating all existing writes. + outstandingPut.onCompleteBlock( + kFTransactionDisconnect, + @"Client was disconnected while running a transaction"); + [self.outstandingPuts removeObjectForKey:index]; + }]; +} + +- (void)onDataPushWithAction:(NSString *)action andBody:(NSDictionary *)body { + FFLog(@"I-RDB034029", @"handleServerMessage: %@, %@", action, body); + id delegate = self.delegate; + if ([action isEqualToString:kFWPAsyncServerDataUpdate] || + [action isEqualToString:kFWPAsyncServerDataMerge]) { + BOOL isMerge = [action isEqualToString:kFWPAsyncServerDataMerge]; + + if ([body objectForKey:kFWPAsyncServerDataUpdateBodyPath] && + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]) { + NSString *path = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + id payloadData = + [body objectForKey:kFWPAsyncServerDataUpdateBodyData]; + if (isMerge && [payloadData isKindOfClass:[NSDictionary class]] && + [payloadData count] == 0) { + // ignore empty merge + } else { + [delegate + onDataUpdate:self + forPath:path + message:payloadData + isMerge:isMerge + tagId:[body objectForKey: + kFWPAsyncServerDataUpdateBodyTag]]; + } + } else { + FFLog( + @"I-RDB034030", + @"Malformed data response from server missing path or data: %@", + body); + } + } else if ([action isEqualToString:kFWPAsyncServerDataRangeMerge]) { + NSString *path = body[kFWPAsyncServerDataUpdateBodyPath]; + NSArray *ranges = body[kFWPAsyncServerDataUpdateBodyData]; + NSNumber *tag = body[kFWPAsyncServerDataUpdateBodyTag]; + NSMutableArray *rangeMerges = [NSMutableArray array]; + for (NSDictionary *range in ranges) { + NSString *startString = range[kFWPAsyncServerDataUpdateStartPath]; + NSString *endString = range[kFWPAsyncServerDataUpdateEndPath]; + id updateData = range[kFWPAsyncServerDataUpdateRangeMerge]; + id updates = [FSnapshotUtilities nodeFrom:updateData]; + FPath *start = (startString != nil) + ? [[FPath alloc] initWith:startString] + : nil; + FPath *end = + (endString != nil) ? [[FPath alloc] initWith:endString] : nil; + FRangeMerge *merge = [[FRangeMerge alloc] initWithStart:start + end:end + updates:updates]; + [rangeMerges addObject:merge]; + } + [delegate onRangeMerge:rangeMerges forPath:path tagId:tag]; + } else if ([action isEqualToString:kFWPAsyncServerAuthRevoked]) { + NSString *status = [body objectForKey:kFWPResponseForActionStatus]; + NSString *reason = [body objectForKey:kFWPResponseForActionData]; + [self onAuthRevokedWithStatus:status andReason:reason]; + } else if ([action isEqualToString:kFWPASyncServerListenCancelled]) { + NSString *pathString = + [body objectForKey:kFWPAsyncServerDataUpdateBodyPath]; + [self onListenRevoked:[[FPath alloc] initWith:pathString]]; + } else if ([action isEqualToString:kFWPAsyncServerSecurityDebug]) { + NSString *msg = [body objectForKey:@"msg"]; + if (msg != nil) { + NSArray *msgs = [msg componentsSeparatedByString:@"\n"]; + for (NSString *m in msgs) { + FFWarn(@"I-RDB034031", @"%@", m); + } + } + } else { + // TODO: revoke listens, auth, security debug + FFLog(@"I-RDB034032", @"Unsupported action from server: %@", action); + } +} + +- (void)restoreAuth { + FFLog(@"I-RDB034033", @"Calling restore state"); + + NSAssert(self->connectionState == ConnectionStateConnecting, + @"Wanted to restore auth, but was in wrong state: %d", + self->connectionState); + if (self.authToken == nil) { + FFLog(@"I-RDB034034", @"Not restoring auth because token is nil"); + self->connectionState = ConnectionStateConnected; + [self restoreState]; + } else { + FFLog(@"I-RDB034035", @"Restoring auth"); + self->connectionState = ConnectionStateAuthenticating; + [self sendAuthAndRestoreStateAfterComplete:YES]; + } +} + +- (void)restoreState { + NSAssert(self->connectionState == ConnectionStateConnected, + @"Should be connected if we're restoring state, but we are: %d", + self->connectionState); + + [self.listens enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *query, FOutstandingQuery *outstandingListen, + BOOL *stop) { + FFLog(@"I-RDB034036", @"Restoring listen for %@", query); + [self sendListen:outstandingListen]; + }]; + + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (int i = 0; i < [keys count]; i++) { + if ([self.outstandingPuts objectForKey:[keys objectAtIndex:i]] != nil) { + FFLog(@"I-RDB034037", @"Restoring put: %d", i); + [self sendPut:[keys objectAtIndex:i]]; + } else { + FFLog(@"I-RDB034038", @"Restoring put: skipped nil: %d", i); + } + } + + for (FTupleOnDisconnect *tuple in self.onDisconnectQueue) { + [self sendOnDisconnectAction:tuple.action + forPath:tuple.pathString + withData:tuple.data + andCallback:tuple.onComplete]; + } + [self.onDisconnectQueue removeAllObjects]; +} + +- (NSArray *)removeListen:(FQuerySpec *)query { + NSAssert(query.isDefault || !query.loadsAllData, + @"removeListen called for non-default but complete query"); + + FOutstandingQuery *outstanding = self.listens[query]; + if (!outstanding) { + FFLog(@"I-RDB034039", + @"Trying to remove listener for query %@ but no listener exists", + query); + return @[]; + } else { + [self.listens removeObjectForKey:query]; + return @[ outstanding ]; + } +} + +- (NSArray *)removeAllListensAtPath:(FPath *)path { + FFLog(@"I-RDB034040", @"Removing all listens at path %@", path); + NSMutableArray *removed = [NSMutableArray array]; + NSMutableArray *toRemove = [NSMutableArray array]; + [self.listens + enumerateKeysAndObjectsUsingBlock:^( + FQuerySpec *spec, FOutstandingQuery *outstanding, BOOL *stop) { + if ([spec.path isEqual:path]) { + [removed addObject:outstanding]; + [toRemove addObject:spec]; + } + }]; + [self.listens removeObjectsForKeys:toRemove]; + return removed; +} + +- (void)purgeOutstandingWrites { + // We might have unacked puts in our queue that we need to ack now before we + // send out any cancels... + [self ackPuts]; + // Cancel in order + NSArray *keys = [[self.outstandingPuts allKeys] + sortedArrayUsingSelector:@selector(compare:)]; + for (NSNumber *key in keys) { + FOutstandingPut *put = self.outstandingPuts[key]; + if (put.onCompleteBlock != nil) { + put.onCompleteBlock(kFErrorWriteCanceled, nil); + } + } + for (FTupleOnDisconnect *onDisconnect in self.onDisconnectQueue) { + if (onDisconnect.onComplete != nil) { + onDisconnect.onComplete(kFErrorWriteCanceled, nil); + } + } + [self.outstandingPuts removeAllObjects]; + [self.onDisconnectQueue removeAllObjects]; +} + +- (void)ackPuts { + for (FTupleCallbackStatus *put in self.putsToAck) { + put.block(put.status, put.errorReason); + } + [self.putsToAck removeAllObjects]; +} + +- (void)handleTimestamp:(NSNumber *)timestamp { + FFLog(@"I-RDB034041", @"Handling timestamp: %@", timestamp); + double timestampDeltaMs = [timestamp doubleValue] - + ([[NSDate date] timeIntervalSince1970] * 1000); + [self.delegate onServerInfoUpdate:self + updates:@{ + kDotInfoServerTimeOffset : [NSNumber + numberWithDouble:timestampDeltaMs] + }]; +} + +- (void)sendStats:(NSDictionary *)stats { + if ([stats count] > 0) { + NSDictionary *request = @{kFWPRequestCounters : stats}; + [self sendAction:kFWPRequestActionStats + body:request + sensitive:NO + callback:^(NSDictionary *data) { + NSString *status = + [data objectForKey:kFWPResponseForActionStatus]; + NSString *errorReason = + [data objectForKey:kFWPResponseForActionData]; + BOOL statusOk = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (!statusOk) { + FFLog(@"I-RDB034042", @"Failed to send stats: %@", + errorReason); + } + }]; + } else { + FFLog(@"I-RDB034043", @"Not sending stats because stats are empty"); + } +} + +- (void)sendConnectStats { + NSMutableDictionary *stats = [NSMutableDictionary dictionary]; + +#if TARGET_OS_IOS || TARGET_OS_TV + if (self.config.persistenceEnabled) { + stats[@"persistence.ios.enabled"] = @1; + } +#elif TARGET_OS_OSX + if (self.config.persistenceEnabled) { + stats[@"persistence.osx.enabled"] = @1; + } +#endif + NSString *sdkVersion = + [[FIRDatabase sdkVersion] stringByReplacingOccurrencesOfString:@"." + withString:@"-"]; + NSString *sdkStatName = + [NSString stringWithFormat:@"sdk.objc.%@", sdkVersion]; + stats[sdkStatName] = @1; + FFLog(@"I-RDB034044", @"Sending first connection stats"); + [self sendStats:stats]; +} + +- (NSDictionary *)dumpListens { + return self.listens; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h new file mode 100644 index 0000000..5d957c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FIndex +, FNodeFilter, FNode; + +@interface FQueryParams : NSObject + +@property(nonatomic, readonly) BOOL limitSet; +@property(nonatomic, readonly) NSInteger limit; + +@property(nonatomic, strong, readonly) NSString *viewFrom; +@property(nonatomic, strong, readonly) id indexStartValue; +@property(nonatomic, strong, readonly) NSString *indexStartKey; +@property(nonatomic, strong, readonly) id indexEndValue; +@property(nonatomic, strong, readonly) NSString *indexEndKey; + +@property(nonatomic, strong, readonly) id index; + +- (BOOL)loadsAllData; +- (BOOL)isDefault; +- (BOOL)isValid; +- (BOOL)hasAnchoredLimit; + +- (FQueryParams *)limitTo:(NSInteger)limit; +- (FQueryParams *)limitToFirst:(NSInteger)newLimit; +- (FQueryParams *)limitToLast:(NSInteger)newLimit; + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)startAt:(id)indexValue; +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key; +- (FQueryParams *)endAt:(id)indexValue; + +- (FQueryParams *)orderBy:(id)index; + ++ (FQueryParams *)defaultInstance; ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict; + +- (BOOL)hasStart; +- (BOOL)hasEnd; + +- (NSDictionary *)wireProtocolParams; +- (BOOL)isViewFromLeft; +- (id)nodeFilter; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m new file mode 100644 index 0000000..c19cfba --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQueryParams.m @@ -0,0 +1,393 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FConstants.h" +#import "FIndex.h" +#import "FIndexedFilter.h" +#import "FLimitedFilter.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FPriorityIndex.h" +#import "FRangedFilter.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" + +@interface FQueryParams () + +@property(nonatomic, readwrite) BOOL limitSet; +@property(nonatomic, readwrite) NSInteger limit; + +@property(nonatomic, strong, readwrite) NSString *viewFrom; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexStartValue; +@property(nonatomic, strong, readwrite) NSString *indexStartKey; +/** + * indexStartValue is anything you can store as a priority / value. + */ +@property(nonatomic, strong, readwrite) id indexEndValue; +@property(nonatomic, strong, readwrite) NSString *indexEndKey; + +@property(nonatomic, strong, readwrite) id index; + +@end + +@implementation FQueryParams + ++ (FQueryParams *)defaultInstance { + static FQueryParams *defaultParams = nil; + static dispatch_once_t defaultParamsToken; + dispatch_once(&defaultParamsToken, ^{ + defaultParams = [[FQueryParams alloc] init]; + }); + return defaultParams; +} + +- (id)init { + self = [super init]; + if (self) { + self->_limitSet = NO; + self->_limit = 0; + + self->_viewFrom = nil; + self->_indexStartValue = nil; + self->_indexStartKey = nil; + self->_indexEndValue = nil; + self->_indexEndKey = nil; + + self->_index = [FPriorityIndex priorityIndex]; + } + return self; +} + +/** + * Only valid if hasStart is true + */ +- (id)indexStartValue { + NSAssert([self hasStart], @"Only valid if start has been set"); + return _indexStartValue; +} + +/** + * Only valid if hasStart is true. + * @return The starting key name for the range defined by these query parameters + */ +- (NSString *)indexStartKey { + NSAssert([self hasStart], @"Only valid if start has been set"); + if (_indexStartKey == nil) { + return [FUtilities minName]; + } else { + return _indexStartKey; + } +} + +/** + * Only valid if hasEnd is true. + */ +- (id)indexEndValue { + NSAssert([self hasEnd], @"Only valid if end has been set"); + return _indexEndValue; +} + +/** + * Only valid if hasEnd is true. + * @return The end key name for the range defined by these query parameters + */ +- (NSString *)indexEndKey { + NSAssert([self hasEnd], @"Only valid if end has been set"); + if (_indexEndKey == nil) { + return [FUtilities maxName]; + } else { + return _indexEndKey; + } +} + +/** + * @return true if a limit has been set and has been explicitly anchored + */ +- (BOOL)hasAnchoredLimit { + return self.limitSet && self.viewFrom != nil; +} + +/** + * Only valid to call if limitSet returns true + */ +- (NSInteger)limit { + NSAssert(self.limitSet, @"Only valid if limit has been set"); + return _limit; +} + +- (BOOL)hasStart { + return self->_indexStartValue != nil; +} + +- (BOOL)hasEnd { + return self->_indexEndValue != nil; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)mutableCopy { + FQueryParams *other = [[[self class] alloc] init]; + // Maybe need to do extra copying here + other->_limitSet = _limitSet; + other->_limit = _limit; + other->_indexStartValue = _indexStartValue; + other->_indexStartKey = _indexStartKey; + other->_indexEndValue = _indexEndValue; + other->_indexEndKey = _indexEndKey; + other->_viewFrom = _viewFrom; + other->_index = _index; + return other; +} + +- (FQueryParams *)limitTo:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = nil; + return newParams; +} + +- (FQueryParams *)limitToFirst:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromLeft; + return newParams; +} + +- (FQueryParams *)limitToLast:(NSInteger)newLimit { + FQueryParams *newParams = [self mutableCopy]; + newParams->_limitSet = YES; + newParams->_limit = newLimit; + newParams->_viewFrom = kFQPViewFromRight; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexStartValue = indexValue; + newParams->_indexStartKey = key; + return newParams; +} + +- (FQueryParams *)startAt:(id)indexValue { + return [self startAt:indexValue childKey:nil]; +} + +- (FQueryParams *)endAt:(id)indexValue childKey:(NSString *)key { + NSAssert([indexValue isLeafNode] || [indexValue isEmpty], nil); + FQueryParams *newParams = [self mutableCopy]; + newParams->_indexEndValue = indexValue; + newParams->_indexEndKey = key; + return newParams; +} + +- (FQueryParams *)endAt:(id)indexValue { + return [self endAt:indexValue childKey:nil]; +} + +- (FQueryParams *)orderBy:(id)newIndex { + FQueryParams *newParams = [self mutableCopy]; + newParams->_index = newIndex; + return newParams; +} + +- (NSDictionary *)wireProtocolParams { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + if ([self hasStart]) { + [dict setObject:[self.indexStartValue valForExport:YES] + forKey:kFQPIndexStartValue]; + + // Don't use property as it will be [MIN-NAME] + if (self->_indexStartKey != nil) { + [dict setObject:self->_indexStartKey forKey:kFQPIndexStartName]; + } + } + + if ([self hasEnd]) { + [dict setObject:[self.indexEndValue valForExport:YES] + forKey:kFQPIndexEndValue]; + + // Don't use property as it will be [MAX-NAME] + if (self->_indexEndKey != nil) { + [dict setObject:self->_indexEndKey forKey:kFQPIndexEndName]; + } + } + + if (self.limitSet) { + [dict setObject:[NSNumber numberWithInteger:self.limit] + forKey:kFQPLimit]; + NSString *vf = self.viewFrom; + if (vf == nil) { + // limit() rather than limitToFirst or limitToLast was called. + // This means that only one of startSet or endSet is true. Use them + // to calculate which side of the view to anchor to. If neither is + // set, Anchor to end + if ([self hasStart]) { + vf = kFQPViewFromLeft; + } else { + vf = kFQPViewFromRight; + } + } + [dict setObject:vf forKey:kFQPViewFrom]; + } + + // For now, priority index is the default, so we only specify if it's some + // other index. + if (![self.index isEqual:[FPriorityIndex priorityIndex]]) { + [dict setObject:[self.index queryDefinition] forKey:kFQPIndex]; + } + + return dict; +} + ++ (FQueryParams *)fromQueryObject:(NSDictionary *)dict { + if (dict.count == 0) { + return [FQueryParams defaultInstance]; + } + + FQueryParams *params = [[FQueryParams alloc] init]; + if (dict[kFQPLimit] != nil) { + params->_limitSet = YES; + params->_limit = [dict[kFQPLimit] integerValue]; + } + + if (dict[kFQPIndexStartValue] != nil) { + params->_indexStartValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexStartValue]]; + if (dict[kFQPIndexStartName] != nil) { + params->_indexStartKey = dict[kFQPIndexStartName]; + } + } + + if (dict[kFQPIndexEndValue] != nil) { + params->_indexEndValue = + [FSnapshotUtilities nodeFrom:dict[kFQPIndexEndValue]]; + if (dict[kFQPIndexEndName] != nil) { + params->_indexEndKey = dict[kFQPIndexEndName]; + } + } + + if (dict[kFQPViewFrom] != nil) { + NSString *viewFrom = dict[kFQPViewFrom]; + if (![viewFrom isEqualToString:kFQPViewFromLeft] && + ![viewFrom isEqualToString:kFQPViewFromRight]) { + [NSException raise:NSInvalidArgumentException + format:@"Unknown view from paramter: %@", viewFrom]; + } + params->_viewFrom = viewFrom; + } + + NSString *index = dict[kFQPIndex]; + if (index != nil) { + params->_index = [FIndex indexFromQueryDefinition:index]; + } + + return params; +} + +- (BOOL)isViewFromLeft { + if (self.viewFrom != nil) { + // Not null, we can just check + return [self.viewFrom isEqualToString:kFQPViewFromLeft]; + } else { + // If start is set, it's view from left. Otherwise not. + return self.hasStart; + } +} + +- (id)nodeFilter { + if (self.loadsAllData) { + return [[FIndexedFilter alloc] initWithIndex:self.index]; + } else if (self.limitSet) { + return [[FLimitedFilter alloc] initWithQueryParams:self]; + } else { + return [[FRangedFilter alloc] initWithQueryParams:self]; + } +} + +- (BOOL)isValid { + return !(self.hasStart && self.hasEnd && self.limitSet && + !self.hasAnchoredLimit); +} + +- (BOOL)loadsAllData { + return !(self.hasStart || self.hasEnd || self.limitSet); +} + +- (BOOL)isDefault { + return [self loadsAllData] && + [self.index isEqual:[FPriorityIndex priorityIndex]]; +} + +- (NSString *)description { + return [[self wireProtocolParams] description]; +} + +- (BOOL)isEqual:(id)obj { + if (self == obj) { + return YES; + } + if (![obj isKindOfClass:[self class]]) { + return NO; + } + FQueryParams *other = (FQueryParams *)obj; + if (self->_limitSet != other->_limitSet) + return NO; + if (self->_limit != other->_limit) + return NO; + if ((self->_index != other->_index) && ! + [self->_index isEqual:other->_index]) + return NO; + if ((self->_indexStartKey != other->_indexStartKey) && + ![self->_indexStartKey isEqualToString:other->_indexStartKey]) + return NO; + if ((self->_indexStartValue != other->_indexStartValue) && + ![self->_indexStartValue isEqual:other->_indexStartValue]) + return NO; + if ((self->_indexEndKey != other->_indexEndKey) && + ![self->_indexEndKey isEqualToString:other->_indexEndKey]) + return NO; + if ((self->_indexEndValue != other->_indexEndValue) && + ![self->_indexEndValue isEqual:other->_indexEndValue]) + return NO; + if ([self isViewFromLeft] != [other isViewFromLeft]) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger result = _limitSet ? _limit : 0; + result = 31 * result + ([self isViewFromLeft] ? 1231 : 1237); + result = 31 * result + [_indexStartKey hash]; + result = 31 * result + [_indexStartValue hash]; + result = 31 * result + [_indexEndKey hash]; + result = 31 * result + [_indexEndValue hash]; + result = 31 * result + [_index hash]; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h new file mode 100644 index 0000000..2eece87 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FQuerySpec : NSObject + +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FQueryParams *params; + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params; + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path; + +- (id)index; +- (BOOL)isDefault; +- (BOOL)loadsAllData; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m new file mode 100644 index 0000000..c408bf8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FQuerySpec.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQuerySpec.h" + +@interface FQuerySpec () + +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) FQueryParams *params; + +@end + +@implementation FQuerySpec + +- (id)initWithPath:(FPath *)path params:(FQueryParams *)params { + self = [super init]; + if (self != nil) { + self->_path = path; + self->_params = params; + } + return self; +} + ++ (FQuerySpec *)defaultQueryAtPath:(FPath *)path { + return [[FQuerySpec alloc] initWithPath:path + params:[FQueryParams defaultInstance]]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable + return self; +} + +- (id)index { + return self.params.index; +} + +- (BOOL)isDefault { + return self.params.isDefault; +} + +- (BOOL)loadsAllData { + return self.params.loadsAllData; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FQuerySpec class]]) { + return NO; + } + + FQuerySpec *other = (FQuerySpec *)object; + + if (![self.path isEqual:other.path]) { + return NO; + } + + return [self.params isEqual:other.params]; +} + +- (NSUInteger)hash { + return self.path.hash * 31 + self.params.hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FQuerySpec (path: %@, params: %@)", + self.path, self.params]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h new file mode 100644 index 0000000..5f7938a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FNode.h" + +/** + * Applies a merge of a snap for a given interval of paths. + * Each leaf in the current node which the relative path lies *after* (the + * optional) start and lies *before or at* (the optional) end will be deleted. + * Each leaf in snap that lies in the interval will be added to the resulting + * node. Nodes outside of the range are ignored. nil for start and end are + * sentinel values that represent -infinity and +infinity respectively (aka + * includes any path). Priorities of children nodes are treated as leaf children + * of that node. + */ +@interface FRangeMerge : NSObject + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates; + +- (id)applyToNode:(id)node; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m new file mode 100644 index 0000000..3dc1576 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRangeMerge.m @@ -0,0 +1,134 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangeMerge.h" + +#import "FEmptyNode.h" + +@interface FRangeMerge () + +@property(nonatomic, strong) FPath *optExclusiveStart; +@property(nonatomic, strong) FPath *optInclusiveEnd; +@property(nonatomic, strong) id updates; + +@end + +@implementation FRangeMerge + +- (instancetype)initWithStart:(FPath *)start + end:(FPath *)end + updates:(id)updates { + self = [super init]; + if (self != nil) { + self->_optExclusiveStart = start; + self->_optInclusiveEnd = end; + self->_updates = updates; + } + return self; +} + +- (id)applyToNode:(id)node { + return [self updateRangeInNode:[FPath empty] + node:node + updates:self.updates]; +} + +- (id)updateRangeInNode:(FPath *)currentPath + node:(id)node + updates:(id)updates { + NSComparisonResult startComparison = + (self.optExclusiveStart == nil) + ? NSOrderedDescending + : [currentPath compare:self.optExclusiveStart]; + NSComparisonResult endComparison = + (self.optInclusiveEnd == nil) + ? NSOrderedAscending + : [currentPath compare:self.optInclusiveEnd]; + BOOL startInNode = self.optExclusiveStart != nil && + [currentPath contains:self.optExclusiveStart]; + BOOL endInNode = self.optInclusiveEnd != nil && + [currentPath contains:self.optInclusiveEnd]; + if (startComparison == NSOrderedDescending && + endComparison == NSOrderedAscending && !endInNode) { + // child is completly contained + return updates; + } else if (startComparison == NSOrderedDescending && endInNode && + [updates isLeafNode]) { + return updates; + } else if (startComparison == NSOrderedDescending && + endComparison == NSOrderedSame) { + NSAssert(endInNode, @"End not in node"); + NSAssert(![updates isLeafNode], @"Found leaf node update, this case " + @"should have been handled above."); + if ([node isLeafNode]) { + // Update node was not a leaf node, so we can delete it + return [FEmptyNode emptyNode]; + } else { + // Unaffected by range, ignore + return node; + } + } else if (startInNode || endInNode) { + // There is a partial update we need to do, so collect all relevant + // children + NSMutableSet *allChildren = [NSMutableSet set]; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + [updates enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [allChildren addObject:key]; + }]; + + __block id newNode = node; + void (^action)(id, BOOL *) = ^void(NSString *key, BOOL *stop) { + id currentChild = [node getImmediateChild:key]; + id updatedChild = + [self updateRangeInNode:[currentPath childFromString:key] + node:currentChild + updates:[updates getImmediateChild:key]]; + // Only need to update if the node changed + if (updatedChild != currentChild) { + newNode = [newNode updateImmediateChild:key + withNewChild:updatedChild]; + } + }; + + [allChildren enumerateObjectsUsingBlock:action]; + + // Add priority last, so the node is not empty when applying + if (!updates.getPriority.isEmpty || !node.getPriority.isEmpty) { + BOOL stop = NO; + action(@".priority", &stop); + } + return newNode; + } else { + // Unaffected by this range + NSAssert(endComparison == NSOrderedDescending || + startComparison <= NSOrderedSame, + @"Invalid range for update"); + return node; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"RangeMerge (optExclusiveStart = %@, " + @"optExclusiveEng = %@, updates = %@)", + self.optExclusiveStart, + self.optInclusiveEnd, self.updates]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h new file mode 100644 index 0000000..4e3899a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.h @@ -0,0 +1,93 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FPersistentConnection.h" +#import "FRepoInfo.h" +#import "FTupleUserCallback.h" +#import + +@class FQuerySpec; +@class FPersistence; +@class FAuthenticationManager; +@class FIRDatabaseConfig; +@protocol FEventRegistration; +@class FCompoundWrite; +@protocol FClock; +@class FIRDatabase; + +@interface FRepo : NSObject + +@property(nonatomic, strong) FIRDatabaseConfig *config; + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete; +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; +- (void)purgeOutstandingWrites; + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced; + +- (NSString *)name; +- (NSTimeInterval)serverTime; + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)message + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId; +- (void)onConnect:(FPersistentConnection *)fpconnection; +- (void)onDisconnect:(FPersistentConnection *)fpconnection; + +// Disconnect methods +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback; +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)compoundWrite + withCallback:(fbt_void_nserror_ref)callback; + +// Connection Management. +- (void)interrupt; +- (void)resume; + +// Transactions +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally; + +// Testing methods +- (NSDictionary *)dumpListens; +- (void)dispose; +- (void)setHijackHash:(BOOL)hijack; + +@property(nonatomic, strong, readonly) FAuthenticationManager *auth; +@property(nonatomic, strong, readonly) FIRDatabase *database; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m new file mode 100644 index 0000000..5d894bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo.m @@ -0,0 +1,1450 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FAtomicNumber.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FIRDataSnapshot.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FIRMutableData.h" +#import "FIRMutableData_Private.h" +#import "FIRTransactionResult.h" +#import "FIRTransactionResult_Private.h" +#import "FLevelDBStorageEngine.h" +#import "FListenProvider.h" +#import "FPersistenceManager.h" +#import "FQuerySpec.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FRepo_Private.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncTree.h" +#import "FTree.h" +#import "FTupleNodePath.h" +#import "FTupleSetIdPath.h" +#import "FTupleTransaction.h" +#import "FValueEventRegistration.h" +#import "FWriteRecord.h" +#import +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FRepo () + +@property(nonatomic, strong) FOffsetClock *serverClock; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FIRDatabase *database; +@property(nonatomic, strong, readwrite) FAuthenticationManager *auth; +@property(nonatomic, strong) FSyncTree *infoSyncTree; +@property(nonatomic) NSInteger writeIdCounter; +@property(nonatomic) BOOL hijackHash; +@property(nonatomic, strong) FTree *transactionQueueTree; +@property(nonatomic) BOOL loggedTransactionPersistenceWarning; + +/** + * Test only. For load testing the server. + */ +@property(nonatomic, strong) id (^interceptServerDataCallback) + (NSString *pathString, id data); +@end + +@implementation FRepo + +- (id)initWithRepoInfo:(FRepoInfo *)info + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + self = [super init]; + if (self) { + self.repoInfo = info; + self.config = config; + self.database = database; + + // Access can occur outside of shared queue, so the clock needs to be + // initialized here + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] offset:0]; + + self.connection = [[FPersistentConnection alloc] + initWithRepoInfo:self.repoInfo + dispatchQueue:[FIRDatabaseQuery sharedQueue] + config:self.config]; + + // Needs to be called before authentication manager is instantiated + self.eventRaiser = + [[FEventRaiser alloc] initWithQueue:self.config.callbackQueue]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self deferredInit]; + }); + } + return self; +} + +- (void)deferredInit { + // TODO: cleanup on dealloc + __weak FRepo *weakSelf = self; + [self.config.authTokenProvider listenForTokenChanges:^(NSString *token) { + [weakSelf.connection refreshAuthToken:token]; + }]; + + // Open connection now so that by the time we are connected the deferred + // init has run This relies on the fact that all callbacks run on repos + // queue + self.connection.delegate = self; + [self.connection open]; + + self.dataUpdateCount = 0; + self.rangeMergeUpdateCount = 0; + self.interceptServerDataCallback = nil; + + if (self.config.persistenceEnabled) { + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", self.repoInfo.host, + self.repoInfo.namespace]; + NSString *persistencePrefix = + [NSString stringWithFormat:@"%@/%@", self.config.sessionIdentifier, + repoHashString]; + + id cachePolicy = [[FLRUCachePolicy alloc] + initWithMaxSize:self.config.persistenceCacheSizeBytes]; + + id engine; + if (self.config.forceStorageEngine != nil) { + engine = self.config.forceStorageEngine; + } else { + FLevelDBStorageEngine *levelDBEngine = + [[FLevelDBStorageEngine alloc] initWithPath:persistencePrefix]; + // We need the repo info to run the legacy migration. Future + // migrations will be managed by the database itself Remove this + // once we are confident that no-one is using legacy migration + // anymore... + [levelDBEngine runLegacyMigration:self.repoInfo]; + engine = levelDBEngine; + } + + self.persistenceManager = + [[FPersistenceManager alloc] initWithStorageEngine:engine + cachePolicy:cachePolicy]; + } else { + self.persistenceManager = nil; + } + + [self initTransactions]; + + // A list of data pieces and paths to be set when this client disconnects + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + self.infoData = [[FSnapshotHolder alloc] init]; + + FListenProvider *infoListenProvider = [[FListenProvider alloc] init]; + infoListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + NSArray *infoEvents = @[]; + FRepo *strongSelf = weakSelf; + id node = [strongSelf.infoData getNode:query.path]; + // This is possibly a hack, but we have different semantics for .info + // endpoints. We don't raise null events on initial data... + if (![node isEmpty]) { + infoEvents = + [strongSelf.infoSyncTree applyServerOverwriteAtPath:query.path + newData:node]; + [strongSelf.eventRaiser raiseCallback:^{ + onComplete(kFWPResponseForActionStatusOk); + }]; + } + return infoEvents; + }; + infoListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tagId) { + }; + self.infoSyncTree = + [[FSyncTree alloc] initWithListenProvider:infoListenProvider]; + + FListenProvider *serverListenProvider = [[FListenProvider alloc] init]; + serverListenProvider.startListening = + ^(FQuerySpec *query, NSNumber *tagId, id hash, + fbt_nsarray_nsstring onComplete) { + [weakSelf.connection listen:query + tagId:tagId + hash:hash + onComplete:^(NSString *status) { + NSArray *events = onComplete(status); + [weakSelf.eventRaiser raiseEvents:events]; + }]; + // No synchronous events for network-backed sync trees + return @[]; + }; + serverListenProvider.stopListening = ^(FQuerySpec *query, NSNumber *tag) { + [weakSelf.connection unlisten:query tagId:tag]; + }; + self.serverSyncTree = + [[FSyncTree alloc] initWithPersistenceManager:self.persistenceManager + listenProvider:serverListenProvider]; + + [self restoreWrites]; + + [self updateInfo:kDotInfoConnected withValue:@NO]; + + [self setupNotifications]; +} + +- (void)restoreWrites { + NSArray *writes = self.persistenceManager.userWrites; + + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + __block NSInteger lastWriteId = NSIntegerMin; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + NSInteger writeId = write.writeId; + fbt_void_nsstring_nsstring callback = + ^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:write.path + status:status + message:@"Persisted write"]; + [self ackWrite:writeId + rerunTransactionsAtPath:write.path + status:status]; + }; + if (lastWriteId >= writeId) { + [NSException raise:NSInternalInconsistencyException + format:@"Restored writes were not in order!"]; + } + lastWriteId = writeId; + self.writeIdCounter = writeId + 1; + if ([write isOverwrite]) { + FFLog(@"I-RDB038001", @"Restoring overwrite with id %ld", + (long)write.writeId); + [self.connection putData:[write.overwrite valForExport:YES] + forPath:[write.path toString] + withHash:nil + withCallback:callback]; + id resolved = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withServerValues:serverValues]; + [self.serverSyncTree applyUserOverwriteAtPath:write.path + newData:resolved + writeId:writeId + isVisible:YES]; + } else { + FFLog(@"I-RDB038002", @"Restoring merge with id %ld", + (long)write.writeId); + [self.connection mergeData:[write.merge valForExport:YES] + forPath:[write.path toString] + withCallback:callback]; + FCompoundWrite *resolved = + [FServerValues resolveDeferredValueCompoundWrite:write.merge + withServerValues:serverValues]; + [self.serverSyncTree applyUserMergeAtPath:write.path + changedChildren:resolved + writeId:writeId]; + } + }]; +} + +- (NSString *)name { + return self.repoInfo.namespace; +} + +- (NSString *)description { + return [self.repoInfo description]; +} + +- (void)interrupt { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; +} + +- (void)resume { + [self.connection resumeForReason:kFInterruptReasonRepoInterrupt]; +} + +// NOTE: Typically if you're calling this, you should be in an @autoreleasepool +// block to make sure that ARC kicks in and cleans up things no longer +// referenced (i.e. pendingPutsDB). +- (void)dispose { + [self.connection interruptForReason:kFInterruptReasonRepoInterrupt]; + + // We need to nil out any references to LevelDB, to make sure the + // LevelDB exclusive locks are released. + [self.persistenceManager close]; +} + +- (NSInteger)nextWriteId { + return self->_writeIdCounter++; +} + +- (NSTimeInterval)serverTime { + return [self.serverClock currentTime]; +} + +- (void)set:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)onComplete { + id value = [node valForExport:YES]; + FFLog(@"I-RDB038003", @"Setting: %@ with %@ pri: %@", [path toString], + [value description], [[node getPriority] val]); + + // TODO: Optimize this behavior to either (a) store flag to skip resolving + // where possible and / or (b) store unresolved paths on JSON parse + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id newNode = + [FServerValues resolveDeferredValueSnapshot:node + withServerValues:serverValues]; + + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserOverwrite:node + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserOverwriteAtPath:path + newData:newNode + writeId:writeId + isVisible:YES]; + [self.eventRaiser raiseEvents:events]; + + [self.connection putData:value + forPath:[path toString] + withHash:nil + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"setValue: or removeValue:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:onComplete + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + FPath *affectedPath = [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; +} + +- (void)update:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + NSDictionary *values = [nodes valForExport:YES]; + + FFLog(@"I-RDB038004", @"Updating: %@ with %@", [path toString], + [values description]); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + FCompoundWrite *resolved = + [FServerValues resolveDeferredValueCompoundWrite:nodes + withServerValues:serverValues]; + + if (!resolved.isEmpty) { + NSInteger writeId = [self nextWriteId]; + [self.persistenceManager saveUserMerge:nodes + atPath:path + writeId:writeId]; + NSArray *events = [self.serverSyncTree applyUserMergeAtPath:path + changedChildren:resolved + writeId:writeId]; + [self.eventRaiser raiseEvents:events]; + + [self.connection mergeData:values + forPath:[path description] + withCallback:^(NSString *status, NSString *errorReason) { + [self warnIfWriteFailedAtPath:path + status:status + message:@"updateChildValues:"]; + [self ackWrite:writeId + rerunTransactionsAtPath:path + status:status]; + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + + [nodes enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + FPath *pathFromRoot = [path child:childPath]; + FFLog(@"I-RDB038005", @"Cancelling transactions at path: %@", + pathFromRoot); + FPath *affectedPath = [self abortTransactionsAtPath:pathFromRoot + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + } else { + FFLog(@"I-RDB038006", @"update called with empty data. Doing nothing"); + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)onDisconnectCancel:(FPath *)path + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectCancelPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect forgetPath:path]; + } else { + FFLog(@"I-RDB038007", + @"cancelDisconnectOperations: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectSet:(FPath *)path + withNode:(id)node + withCallback:(fbt_void_nserror_ref)callback { + [self.connection + onDisconnectPutData:[node valForExport:YES] + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = + [status isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [self.onDisconnect rememberData:node onPath:path]; + } else { + FFWarn(@"I-RDB038008", + @"onDisconnectSetValue: or " + @"onDisconnectRemoveValue: at %@ failed: %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; +} + +- (void)onDisconnectUpdate:(FPath *)path + withNodes:(FCompoundWrite *)nodes + withCallback:(fbt_void_nserror_ref)callback { + if (!nodes.isEmpty) { + NSDictionary *values = [nodes valForExport:YES]; + + [self.connection + onDisconnectMergeData:values + forPath:path + withCallback:^(NSString *status, NSString *errorReason) { + BOOL success = [status + isEqualToString:kFWPResponseForActionStatusOk]; + if (success) { + [nodes enumerateWrites:^(FPath *relativePath, + id nodeUnresolved, + BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self.onDisconnect rememberData:nodeUnresolved + onPath:childPath]; + }]; + } else { + FFWarn(@"I-RDB038009", + @"onDisconnectUpdateChildValues: at %@ " + @"failed %@", + path, status); + } + + [self callOnComplete:callback + withStatus:status + errorReason:errorReason + andPath:path]; + }]; + } else { + // Do nothing, just call the callback + [self callOnComplete:callback + withStatus:@"ok" + errorReason:nil + andPath:path]; + } +} + +- (void)purgeOutstandingWrites { + FFLog(@"I-RDB038010", @"Purging outstanding writes"); + NSArray *events = [self.serverSyncTree removeAllWrites]; + [self.eventRaiser raiseEvents:events]; + // Abort any transactions + [self abortTransactionsAtPath:[FPath empty] error:kFErrorWriteCanceled]; + // Remove outstanding writes from connection + [self.connection purgeOutstandingWrites]; +} + +- (void)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } else { + events = [self.serverSyncTree addEventRegistration:eventRegistration + forQuery:query]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + // These are guaranteed not to raise events, since we're not passing in a + // cancelError. However we can future-proof a little bit by handling the + // return values anyways. + FFLog(@"I-RDB038011", @"Removing event registration with hande: %lu", + (unsigned long)eventRegistration.handle); + NSArray *events = nil; + if ([[query.path getFront] isEqualToString:kDotInfoPrefix]) { + events = [self.infoSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } else { + events = [self.serverSyncTree removeEventRegistration:eventRegistration + forQuery:query + cancelError:nil]; + } + [self.eventRaiser raiseEvents:events]; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)synced { + NSAssert(![[query.path getFront] isEqualToString:kDotInfoPrefix], + @"Can't keep .info tree synced!"); + [self.serverSyncTree keepQuery:query synced:synced]; +} + +- (void)updateInfo:(NSString *)pathString withValue:(id)value { + // hack to make serverTimeOffset available in a threadsafe way. Property is + // marked as atomic + if ([pathString isEqualToString:kDotInfoServerTimeOffset]) { + NSTimeInterval offset = [(NSNumber *)value doubleValue] / 1000.0; + self.serverClock = + [[FOffsetClock alloc] initWithClock:[FSystemClock clock] + offset:offset]; + } + + FPath *path = [[FPath alloc] + initWith:[NSString + stringWithFormat:@"%@/%@", kDotInfoPrefix, pathString]]; + id newNode = [FSnapshotUtilities nodeFrom:value]; + [self.infoData updateSnapshot:path withNewSnapshot:newNode]; + NSArray *events = [self.infoSyncTree applyServerOverwriteAtPath:path + newData:newNode]; + [self.eventRaiser raiseEvents:events]; +} + +- (void)callOnComplete:(fbt_void_nserror_ref)onComplete + withStatus:(NSString *)status + errorReason:(NSString *)errorReason + andPath:(FPath *)path { + if (onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + BOOL statusOk = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSError *err = nil; + if (!statusOk) { + err = [FUtilities errorForStatus:status andReason:errorReason]; + } + [self.eventRaiser raiseCallback:^{ + onComplete(err, ref); + }]; + } +} + +- (void)ackWrite:(NSInteger)writeId + rerunTransactionsAtPath:(FPath *)path + status:(NSString *)status { + if ([status isEqualToString:kFErrorWriteCanceled]) { + // This write was already removed, we just need to ignore it... + } else { + BOOL success = [status isEqualToString:kFWPResponseForActionStatusOk]; + NSArray *clearEvents = + [self.serverSyncTree ackUserWriteWithWriteId:writeId + revert:!success + persist:YES + clock:self.serverClock]; + if ([clearEvents count] > 0) { + [self rerunTransactionsForPath:path]; + } + [self.eventRaiser raiseEvents:clearEvents]; + } +} + +- (void)warnIfWriteFailedAtPath:(FPath *)path + status:(NSString *)status + message:(NSString *)message { + if (!([status isEqualToString:kFWPResponseForActionStatusOk] || + [status isEqualToString:kFErrorWriteCanceled])) { + FFWarn(@"I-RDB038012", @"%@ at %@ failed: %@", message, path, status); + } +} + +#pragma mark - +#pragma mark FPersistentConnectionDelegate methods + +- (void)onDataUpdate:(FPersistentConnection *)fpconnection + forPath:(NSString *)pathString + message:(id)data + isMerge:(BOOL)isMerge + tagId:(NSNumber *)tagId { + FFLog(@"I-RDB038013", @"onDataUpdateForPath: %@ withMessage: %@", + pathString, data); + + // For testing. + self.dataUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + data = self.interceptServerDataCallback + ? self.interceptServerDataCallback(pathString, data) + : data; + NSArray *events = nil; + + if (tagId != nil) { + if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *taggedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = + [self.serverSyncTree applyTaggedQueryMergeAtPath:path + changedChildren:taggedChildren + tagId:tagId]; + } else { + id taggedSnap = [FSnapshotUtilities nodeFrom:data]; + events = + [self.serverSyncTree applyTaggedQueryOverwriteAtPath:path + newData:taggedSnap + tagId:tagId]; + } + } else if (isMerge) { + NSDictionary *message = data; + FCompoundWrite *changedChildren = + [FCompoundWrite compoundWriteWithValueDictionary:message]; + events = [self.serverSyncTree applyServerMergeAtPath:path + changedChildren:changedChildren]; + } else { + id snap = [FSnapshotUtilities nodeFrom:data]; + events = [self.serverSyncTree applyServerOverwriteAtPath:path + newData:snap]; + } + + if ([events count] > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onRangeMerge:(NSArray *)ranges + forPath:(NSString *)pathString + tagId:(NSNumber *)tag { + FFLog(@"I-RDB038014", @"onRangeMerge: %@ => %@", pathString, ranges); + + // For testing + self.rangeMergeUpdateCount++; + + FPath *path = [[FPath alloc] initWith:pathString]; + NSArray *events; + if (tag != nil) { + events = [self.serverSyncTree applyTaggedServerRangeMergeAtPath:path + updates:ranges + tagId:tag]; + } else { + events = [self.serverSyncTree applyServerRangeMergeAtPath:path + updates:ranges]; + } + if (events.count > 0) { + // Since we have a listener outstanding for each transaction, receiving + // any events is a proxy for some change having occurred. + [self rerunTransactionsForPath:path]; + } + + [self.eventRaiser raiseEvents:events]; +} + +- (void)onConnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@YES]; +} + +- (void)onDisconnect:(FPersistentConnection *)fpconnection { + [self updateInfo:kDotInfoConnected withValue:@NO]; + [self runOnDisconnectEvents]; +} + +- (void)onServerInfoUpdate:(FPersistentConnection *)fpconnection + updates:(NSDictionary *)updates { + for (NSString *key in updates) { + id val = [updates objectForKey:key]; + [self updateInfo:key withValue:val]; + } +} + +- (void)setupNotifications { + NSString *const *backgroundConstant = (NSString *const *)dlsym( + RTLD_DEFAULT, "UIApplicationDidEnterBackgroundNotification"); + if (backgroundConstant) { + FFLog(@"I-RDB038015", @"Registering for background notification."); + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didEnterBackground) + name:*backgroundConstant + object:nil]; + } else { + FFLog(@"I-RDB038016", + @"Skipped registering for background notification."); + } +} + +- (void)didEnterBackground { + if (!self.config.persistenceEnabled) + return; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + // The idea is to wait until any outstanding sets get written to disk. Since + // the sets might still be in our dispatch queue, we wait for the dispatch + // queue to catch up and for persistence to catch up. This may be + // undesirable though. The dispatch queue might just be processing a bunch + // of incoming data or something. We might want to keep track of whether + // there are any unpersisted sets or something. + FFLog(@"I-RDB038017", + @"Entering background. Starting background task to finish work."); + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + assert(uiApplicationClass); // If we are here, we should be on iOS and + // UIApplication should be available. + + UIApplication *application = [uiApplicationClass sharedApplication]; + __block UIBackgroundTaskIdentifier bgTask = + [application beginBackgroundTaskWithExpirationHandler:^{ + [application endBackgroundTask:bgTask]; + }]; + + NSDate *start = [NSDate date]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + NSTimeInterval finishTime = [start timeIntervalSinceNow] * -1; + FFLog(@"I-RDB038018", @"Background task completed. Queue time: %f", + finishTime); + [application endBackgroundTask:bgTask]; + }); +#endif +} + +#pragma mark - +#pragma mark Internal methods + +/** + * Applies all the changes stored up in the onDisconnect tree + */ +- (void)runOnDisconnectEvents { + FFLog(@"I-RDB038019", @"Running onDisconnectEvents"); + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + FSparseSnapshotTree *resolvedTree = + [FServerValues resolveDeferredValueTree:self.onDisconnect + withServerValues:serverValues]; + NSMutableArray *events = [[NSMutableArray alloc] init]; + + [resolvedTree + forEachTreeAtPath:[FPath empty] + do:^(FPath *path, id node) { + [events addObjectsFromArray: + [self.serverSyncTree + applyServerOverwriteAtPath:path + newData:node]]; + FPath *affectedPath = + [self abortTransactionsAtPath:path + error:kFTransactionSet]; + [self rerunTransactionsForPath:affectedPath]; + }]; + + self.onDisconnect = [[FSparseSnapshotTree alloc] init]; + [self.eventRaiser raiseEvents:events]; +} + +- (NSDictionary *)dumpListens { + return [self.connection dumpListens]; +} + +#pragma mark - +#pragma mark Transactions + +/** + * Setup the transaction data structures + */ +- (void)initTransactions { + self.transactionQueueTree = [[FTree alloc] init]; + self.hijackHash = NO; + self.loggedTransactionPersistenceWarning = NO; +} + +/** + * Creates a new transaction, add its to the transactions we're tracking, and + * sends it to the server if possible + */ +- (void)startTransactionOnPath:(FPath *)path + update:(fbt_transactionresult_mutabledata)update + onComplete:(fbt_void_nserror_bool_datasnapshot)onComplete + withLocalEvents:(BOOL)applyLocally { + if (self.config.persistenceEnabled && + !self.loggedTransactionPersistenceWarning) { + self.loggedTransactionPersistenceWarning = YES; + FFInfo(@"I-RDB038020", + @"runTransactionBlock: usage detected while persistence is " + @"enabled. Please be aware that transactions " + @"*will not* be persisted across app restarts. " + @"See " + @"https://www.firebase.com/docs/ios/guide/" + @"offline-capabilities.html#section-handling-transactions-" + @"offline for more details."); + } + + FIRDatabaseReference *watchRef = + [[FIRDatabaseReference alloc] initWithRepo:self path:path]; + // make sure we're listening on this node + // Note: we can't do this asynchronously. To preserve event ordering, it has + // to be done in this block. This is ok, this block is guaranteed to be our + // own event loop + NSUInteger handle = [[FUtilities LUIDGenerator] integerValue]; + fbt_void_datasnapshot cb = ^(FIRDataSnapshot *snapshot) { + }; + FValueEventRegistration *registration = + [[FValueEventRegistration alloc] initWithRepo:self + handle:handle + callback:cb + cancelCallback:nil]; + [watchRef.repo addEventRegistration:registration + forQuery:watchRef.querySpec]; + fbt_void_void unwatcher = ^{ + [watchRef removeObserverWithHandle:handle]; + }; + + // Save all the data that represents this transaction + FTupleTransaction *transaction = [[FTupleTransaction alloc] init]; + transaction.path = path; + transaction.update = update; + transaction.onComplete = onComplete; + transaction.status = FTransactionInitializing; + transaction.order = [FUtilities LUIDGenerator]; + transaction.applyLocally = applyLocally; + transaction.retryCount = 0; + transaction.unwatcher = unwatcher; + transaction.currentWriteId = nil; + transaction.currentInputSnapshot = nil; + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + + // Run transaction initially + id currentState = [self latestStateAtPath:path excludeWriteIds:nil]; + transaction.currentInputSnapshot = currentState; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentState]; + FIRTransactionResult *result = transaction.update(mutableCurrent); + + if (!result.isSuccess) { + // Abort the transaction + transaction.unwatcher(); + transaction.currentOutputSnapshotRaw = nil; + transaction.currentOutputSnapshotResolved = nil; + if (transaction.onComplete) { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self + path:transaction.path]; + FIndexedNode *indexedNode = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + [self.eventRaiser raiseCallback:^{ + transaction.onComplete(nil, NO, snap); + }]; + } + } else { + // Note: different from js. We don't need to validate, FIRMutableData + // does validation. We also don't have to worry about priorities. Just + // mark as run and add to queue. + transaction.status = FTransactionRun; + FTree *queueNode = [self.transactionQueueTree subTree:transaction.path]; + NSMutableArray *nodeQueue = [queueNode getValue]; + if (nodeQueue == nil) { + nodeQueue = [[NSMutableArray alloc] init]; + } + [nodeQueue addObject:transaction]; + [queueNode setValue:nodeQueue]; + + // Update visibleData and raise events + // Note: We intentionally raise events after updating all of our + // transaction state, since the user could start new transactions from + // the event callbacks + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + id newValUnresolved = [result.update nodeValue]; + id newVal = + [FServerValues resolveDeferredValueSnapshot:newValUnresolved + withServerValues:serverValues]; + transaction.currentOutputSnapshotRaw = newValUnresolved; + transaction.currentOutputSnapshotResolved = newVal; + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + + NSArray *events = [self.serverSyncTree + applyUserOverwriteAtPath:path + newData:newVal + writeId:[transaction.currentWriteId integerValue] + isVisible:transaction.applyLocally]; + [self.eventRaiser raiseEvents:events]; + + [self sendAllReadyTransactions]; + } +} + +/** + * @param writeIdsToExclude A specific set to exclude + */ +- (id)latestStateAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + id latestState = + [self.serverSyncTree calcCompleteEventCacheAtPath:path + excludeWriteIds:writeIdsToExclude]; + return latestState ? latestState : [FEmptyNode emptyNode]; +} + +/** + * Sends any already-run transactions that aren't waiting for outstanding + * transactions to complete. + * + * Externally, call the version with no arguments. + * Internally, calls itself recursively with a particular transactionQueueTree + * node to recurse through the tree + */ +- (void)sendAllReadyTransactions { + FTree *node = self.transactionQueueTree; + + [self pruneCompletedTransactionsBelowNode:node]; + [self sendReadyTransactionsForTree:node]; +} + +- (void)sendReadyTransactionsForTree:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + queue = [self buildTransactionQueueAtNode:node]; + NSAssert([queue count] > 0, @"Sending zero length transaction queue"); + + NSUInteger notRunIndex = [queue + indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { + return ((FTupleTransaction *)obj).status != FTransactionRun; + }]; + + // If they're all run (and not sent), we can send them. Else, we must + // wait. + if (notRunIndex == NSNotFound) { + [self sendTransactionQueue:queue atPath:node.path]; + } + } else if ([node hasChildren]) { + [node forEachChild:^(FTree *child) { + [self sendReadyTransactionsForTree:child]; + }]; + } +} + +/** + * Given a list of run transactions, send them to the server and then handle the + * result (success or failure). + */ +- (void)sendTransactionQueue:(NSMutableArray *)queue atPath:(FPath *)path { + // Mark transactions as sent and bump the retry count + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + id latestState = [self latestStateAtPath:path + excludeWriteIds:writeIdsToExclude]; + id snapToSend = latestState; + NSString *latestHash = [latestState dataHash]; + for (FTupleTransaction *transaction in queue) { + NSAssert( + transaction.status == FTransactionRun, + @"[FRepo sendTransactionQueue:] items in queue should all be run."); + FFLog(@"I-RDB038021", @"Transaction at %@ set to SENT", + transaction.path); + transaction.status = FTransactionSent; + transaction.retryCount++; + FPath *relativePath = [FPath relativePathFrom:path to:transaction.path]; + // If we've gotten to this point, the output snapshot must be defined. + snapToSend = + [snapToSend updateChild:relativePath + withNewChild:transaction.currentOutputSnapshotRaw]; + } + + id dataToSend = [snapToSend valForExport:YES]; + NSString *pathToSend = [path description]; + latestHash = self.hijackHash ? @"badhash" : latestHash; + + // Send the put + [self.connection + putData:dataToSend + forPath:pathToSend + withHash:latestHash + withCallback:^(NSString *status, NSString *errorReason) { + FFLog(@"I-RDB038022", @"Transaction put response: %@ : %@", + pathToSend, status); + + NSMutableArray *events = [[NSMutableArray alloc] init]; + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + // Queue up the callbacks and fire them after cleaning up all of + // our transaction state, since the callback could trigger more + // transactions or sets. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionCompleted; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:NO + persist:NO + clock:self.serverClock]]; + if (transaction.onComplete) { + // We never unset the output snapshot, and given that this + // transaction is complete, it should be set + id node = + transaction.currentOutputSnapshotResolved; + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:node]; + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:indexedNode]; + fbt_void_void cb = ^{ + transaction.onComplete(nil, YES, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + transaction.unwatcher(); + } + + // Now remove the completed transactions. + [self + pruneCompletedTransactionsBelowNode:[self.transactionQueueTree + subTree:path]]; + // There may be pending transactions that we can now send. + [self sendAllReadyTransactions]; + + // Finally, trigger onComplete callbacks + [self.eventRaiser raiseCallbacks:callbacks]; + } else { + // transactions are no longer sent. Update their status + // appropriately. + if ([status + isEqualToString:kFWPResponseForActionStatusDataStale]) { + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + transaction.status = FTransactionNeedsAbort; + } else { + transaction.status = FTransactionRun; + } + } + } else { + FFWarn(@"I-RDB038023", + @"runTransactionBlock: at %@ failed: %@", path, + status); + for (FTupleTransaction *transaction in queue) { + transaction.status = FTransactionNeedsAbort; + [transaction setAbortStatus:status reason:errorReason]; + } + } + } + + [self rerunTransactionsForPath:path]; + [self.eventRaiser raiseEvents:events]; + }]; +} + +/** + * Finds all transactions dependent on the data at changed Path and reruns them. + * + * Should be called any time cached data changes. + * + * Return the highest path that was affected by rerunning transactions. This is + * the path at which events need to be raised for. + */ +- (FPath *)rerunTransactionsForPath:(FPath *)changedPath { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return changedPath; + } else { + FTree *rootMostTransactionNode = + [self getAncestorTransactionNodeForPath:changedPath]; + FPath *path = rootMostTransactionNode.path; + + NSArray *queue = + [self buildTransactionQueueAtNode:rootMostTransactionNode]; + [self rerunTransactionQueue:queue atPath:path]; + + return path; + } +} + +/** + * Does all the work of rerunning transactions (as well as cleans up aborted + * transactions and whatnot). + */ +- (void)rerunTransactionQueue:(NSArray *)queue atPath:(FPath *)path { + if (queue.count == 0) { + return; // nothing to do + } + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since the callback could trigger more transactions or + // sets. + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Ignore, by default, all of the sets in this queue, since we're re-running + // all of them. However, we want to include the results of new sets + // triggered as part of this re-run, so we don't want to ignore a range, + // just these specific sets. + NSMutableArray *writeIdsToExclude = [[NSMutableArray alloc] init]; + for (FTupleTransaction *transaction in queue) { + [writeIdsToExclude addObject:transaction.currentWriteId]; + } + + for (FTupleTransaction *transaction in queue) { + FPath *relativePath __unused = + [FPath relativePathFrom:path to:transaction.path]; + BOOL abortTransaction = NO; + NSAssert(relativePath != nil, @"[FRepo rerunTransactionsQueue:] " + @"relativePath should not be null."); + + if (transaction.status == FTransactionNeedsAbort) { + abortTransaction = YES; + if (![transaction.abortStatus + isEqualToString:kFErrorWriteCanceled]) { + NSArray *ackEvents = [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]; + [events addObjectsFromArray:ackEvents]; + } + } else if (transaction.status == FTransactionRun) { + if (transaction.retryCount >= kFTransactionMaxRetries) { + abortTransaction = YES; + [transaction setAbortStatus:kFTransactionTooManyRetries + reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[transaction.currentWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // This code reruns a transaction + id currentNode = + [self latestStateAtPath:transaction.path + excludeWriteIds:writeIdsToExclude]; + transaction.currentInputSnapshot = currentNode; + FIRMutableData *mutableCurrent = + [[FIRMutableData alloc] initWithNode:currentNode]; + FIRTransactionResult *result = + transaction.update(mutableCurrent); + if (result.isSuccess) { + NSNumber *oldWriteId = transaction.currentWriteId; + NSDictionary *serverValues = + [FServerValues generateServerValues:self.serverClock]; + + id newVal = [result.update nodeValue]; + id newValResolved = [FServerValues + resolveDeferredValueSnapshot:newVal + withServerValues:serverValues]; + + transaction.currentOutputSnapshotRaw = newVal; + transaction.currentOutputSnapshotResolved = newValResolved; + + transaction.currentWriteId = + [NSNumber numberWithInteger:[self nextWriteId]]; + // Mutates writeIdsToExclude in place + [writeIdsToExclude removeObject:oldWriteId]; + [events + addObjectsFromArray: + [self.serverSyncTree + applyUserOverwriteAtPath:transaction.path + newData: + transaction + .currentOutputSnapshotResolved + writeId: + [transaction.currentWriteId + integerValue] + isVisible:transaction + .applyLocally]]; + [events addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId:[oldWriteId + integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + abortTransaction = YES; + // The user aborted the transaction. JS treats ths as a + // "nodata" abort, but it's not an error, so we don't send + // them an error. + [transaction setAbortStatus:nil reason:nil]; + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } + } + } + + [self.eventRaiser raiseEvents:events]; + events = nil; + + if (abortTransaction) { + // Abort + transaction.status = FTransactionCompleted; + transaction.unwatcher(); + if (transaction.onComplete) { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self + path:transaction.path]; + FIndexedNode *lastInput = [FIndexedNode + indexedNodeWithNode:transaction.currentInputSnapshot]; + FIRDataSnapshot *snap = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:lastInput]; + fbt_void_void cb = ^{ + // Unlike JS, no need to check for "nodata" because ObjC has + // abortError = nil + transaction.onComplete(transaction.abortError, NO, snap); + }; + [callbacks addObject:[cb copy]]; + } + } + } + + // Note: unlike current js client, we don't need to preserve priority. Users + // can set priority via FIRMutableData + + // Clean up completed transactions. + [self pruneCompletedTransactionsBelowNode:self.transactionQueueTree]; + + // Now fire callbacks, now that we're in a good, known state. + [self.eventRaiser raiseCallbacks:callbacks]; + + // Try to send the transaction result to the server + [self sendAllReadyTransactions]; +} + +- (FTree *)getAncestorTransactionNodeForPath:(FPath *)path { + FTree *transactionNode = self.transactionQueueTree; + + while (![path isEmpty] && [transactionNode getValue] == nil) { + NSString *front = [path getFront]; + transactionNode = + [transactionNode subTree:[[FPath alloc] initWith:front]]; + path = [path popFront]; + } + + return transactionNode; +} + +- (NSMutableArray *)buildTransactionQueueAtNode:(FTree *)node { + NSMutableArray *queue = [[NSMutableArray alloc] init]; + [self aggregateTransactionQueuesForNode:node andQueue:queue]; + + [queue sortUsingComparator:^NSComparisonResult(FTupleTransaction *obj1, + FTupleTransaction *obj2) { + return [obj1.order compare:obj2.order]; + }]; + + return queue; +} + +- (void)aggregateTransactionQueuesForNode:(FTree *)node + andQueue:(NSMutableArray *)queue { + NSArray *nodeQueue = [node getValue]; + [queue addObjectsFromArray:nodeQueue]; + + [node forEachChild:^(FTree *child) { + [self aggregateTransactionQueuesForNode:child andQueue:queue]; + }]; +} + +/** + * Remove COMPLETED transactions at or below this node in the + * transactionQueueTree + */ +- (void)pruneCompletedTransactionsBelowNode:(FTree *)node { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + int i = 0; + // remove all of the completed transactions from the queue + while (i < queue.count) { + FTupleTransaction *transaction = [queue objectAtIndex:i]; + if (transaction.status == FTransactionCompleted) { + [queue removeObjectAtIndex:i]; + } else { + i++; + } + } + if (queue.count > 0) { + [node setValue:queue]; + } else { + [node setValue:nil]; + } + } + + [node forEachChildMutationSafe:^(FTree *child) { + [self pruneCompletedTransactionsBelowNode:child]; + }]; +} + +/** + * Aborts all transactions on ancestors or descendants of the specified path. + * Called when doing a setValue: or updateChildValues: since we consider them + * incompatible with transactions + * + * @param path path for which we want to abort related transactions. + */ +- (FPath *)abortTransactionsAtPath:(FPath *)path error:(NSString *)error { + // For the common case that there are no transactions going on, skip all + // this! + if ([self.transactionQueueTree isEmpty]) { + return path; + } else { + FPath *affectedPath = + [self getAncestorTransactionNodeForPath:path].path; + + FTree *transactionNode = [self.transactionQueueTree subTree:path]; + [transactionNode forEachAncestor:^BOOL(FTree *ancestor) { + [self abortTransactionsAtNode:ancestor error:error]; + return NO; + }]; + + [self abortTransactionsAtNode:transactionNode error:error]; + + [transactionNode forEachDescendant:^(FTree *child) { + [self abortTransactionsAtNode:child error:error]; + }]; + + return affectedPath; + } +} + +/** + * Abort transactions stored in this transactions queue node. + * + * @param node Node to abort transactions for. + */ +- (void)abortTransactionsAtNode:(FTree *)node error:(NSString *)error { + NSMutableArray *queue = [node getValue]; + if (queue != nil) { + + // Queue up the callbacks and fire them after cleaning up all of our + // transaction state, since can be immediately aborted and removed. + NSMutableArray *callbacks = [[NSMutableArray alloc] init]; + + // Go through queue. Any already-sent transactions must be marked for + // abort, while the unsent ones can be immediately aborted and removed + NSMutableArray *events = [[NSMutableArray alloc] init]; + int lastSent = -1; + // Note: all of the sent transactions will be at the front of the queue, + // so safe to increment lastSent + for (FTupleTransaction *transaction in queue) { + if (transaction.status == FTransactionSentNeedsAbort) { + // No-op. already marked. + } else if (transaction.status == FTransactionSent) { + // Mark this transaction for abort when it returns + lastSent++; + transaction.status = FTransactionSentNeedsAbort; + [transaction setAbortStatus:error reason:nil]; + } else { + // we can abort this immediately + transaction.unwatcher(); + if ([error isEqualToString:kFTransactionSet]) { + [events + addObjectsFromArray: + [self.serverSyncTree + ackUserWriteWithWriteId: + [transaction.currentWriteId integerValue] + revert:YES + persist:NO + clock:self.serverClock]]; + } else { + // If it was cancelled it was already removed from the sync + // tree, no need to ack + NSAssert([error isEqualToString:kFErrorWriteCanceled], nil); + } + + if (transaction.onComplete) { + NSError *abortReason = [FUtilities errorForStatus:error + andReason:nil]; + FIRDataSnapshot *snapshot = nil; + fbt_void_void cb = ^{ + transaction.onComplete(abortReason, NO, snapshot); + }; + [callbacks addObject:[cb copy]]; + } + } + } + if (lastSent == -1) { + // We're not waiting for any sent transactions. We can clear the + // queue. + [node setValue:nil]; + } else { + // Remove the transactions we aborted + NSRange theRange; + theRange.location = lastSent + 1; + theRange.length = queue.count - theRange.location; + [queue removeObjectsInRange:theRange]; + } + + // Now fire the callbacks + [self.eventRaiser raiseEvents:events]; + [self.eventRaiser raiseCallbacks:callbacks]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h new file mode 100644 index 0000000..46e9b8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FRepoInfo : NSObject + +@property(nonatomic, readonly, strong) NSString *host; +@property(nonatomic, readonly, strong) NSString *namespace; +@property(nonatomic, strong) NSString *internalHost; +@property(nonatomic, readonly) bool secure; + +- (id)initWithHost:(NSString *)host + isSecure:(bool)secure + withNamespace:(NSString *)namespace; + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID; +- (NSString *)connectionURL; +- (void)clearInternalHostCache; +- (BOOL)isDemoHost; +- (BOOL)isCustomHost; + +- (id)copyWithZone:(NSZone *)zone; +- (NSUInteger)hash; +- (BOOL)isEqual:(id)anObject; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m new file mode 100644 index 0000000..b2dd2e2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoInfo.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoInfo.h" +#import "FConstants.h" + +@interface FRepoInfo () + +@property(nonatomic, strong) NSString *domain; + +@end + +@implementation FRepoInfo + +@synthesize namespace; +@synthesize host; +@synthesize internalHost; +@synthesize secure; +@synthesize domain; + +- (id)initWithHost:(NSString *)aHost + isSecure:(bool)isSecure + withNamespace:(NSString *)aNamespace { + self = [super init]; + if (self) { + host = aHost; + domain = + [host containsString:@"."] + ? [host + substringFromIndex:[host rangeOfString:@"."].location + 1] + : host; + secure = isSecure; + namespace = aNamespace; + + // Get cached internal host if it exists + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSString *cachedInternalHost = [[NSUserDefaults standardUserDefaults] + stringForKey:internalHostKey]; + if (cachedInternalHost != nil) { + internalHost = cachedInternalHost; + } else { + internalHost = self.host; + } + } + return self; +} + +- (NSString *)description { + // The namespace is encoded in the hostname, so we can just return this. + return [NSString + stringWithFormat:@"http%@://%@", (self.secure ? @"s" : @""), self.host]; +} + +- (void)setInternalHost:(NSString *)newHost { + if (![internalHost isEqualToString:newHost]) { + internalHost = newHost; + + // Cache the internal host so we don't need to redirect later on + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache setObject:internalHost forKey:internalHostKey]; + [cache synchronize]; + } +} + +- (void)clearInternalHostCache { + internalHost = self.host; + + // Remove the cached entry + NSString *internalHostKey = + [NSString stringWithFormat:@"firebase:host:%@", self.host]; + NSUserDefaults *cache = [NSUserDefaults standardUserDefaults]; + [cache removeObjectForKey:internalHostKey]; + [cache synchronize]; +} + +- (BOOL)isDemoHost { + return [self.domain isEqualToString:@"firebaseio-demo.com"]; +} + +- (BOOL)isCustomHost { + return ![self.domain isEqualToString:@"firebaseio-demo.com"] && + ![self.domain isEqualToString:@"firebaseio.com"]; +} + +- (NSString *)connectionURL { + return [self connectionURLWithLastSessionID:nil]; +} + +- (NSString *)connectionURLWithLastSessionID:(NSString *)lastSessionID { + NSString *scheme; + if (self.secure) { + scheme = @"wss"; + } else { + scheme = @"ws"; + } + NSString *url = + [NSString stringWithFormat:@"%@://%@/.ws?%@=%@&ns=%@", scheme, + self.internalHost, kWireProtocolVersionParam, + kWebsocketProtocolVersion, self.namespace]; + + if (lastSessionID != nil) { + url = [NSString stringWithFormat:@"%@&ls=%@", url, lastSessionID]; + } + return url; +} + +- (id)copyWithZone:(NSZone *)zone; +{ + return self; // Immutable +} + +- (NSUInteger)hash { + NSUInteger result = host.hash; + result = 31 * result + (secure ? 1 : 0); + result = 31 * result + namespace.hash; + result = 31 * result + host.hash; + return result; +} + +- (BOOL)isEqual:(id)anObject { + if (![anObject isKindOfClass:[FRepoInfo class]]) + return NO; + FRepoInfo *other = (FRepoInfo *)anObject; + return secure == other.secure && [host isEqualToString:other.host] && + [namespace isEqualToString:other.namespace]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h new file mode 100644 index 0000000..ba8d1fc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FRepo.h" +#import "FRepoInfo.h" +#import + +@interface FRepoManager : NSObject + ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config; ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database; ++ (void)interruptAll; ++ (void)interrupt:(FIRDatabaseConfig *)config; ++ (void)resumeAll; ++ (void)resume:(FIRDatabaseConfig *)config; ++ (void)disposeRepos:(FIRDatabaseConfig *)config; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m new file mode 100644 index 0000000..54ad196 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepoManager.m @@ -0,0 +1,148 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepoManager.h" +#import "FAtomicNumber.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabase_Private.h" +#import "FRepo.h" +#import + +@implementation FRepoManager + +typedef NSMutableDictionary *> + FRepoDictionary; + ++ (FRepoDictionary *)configs { + static dispatch_once_t pred = 0; + static FRepoDictionary *configs; + dispatch_once(&pred, ^{ + configs = [NSMutableDictionary dictionary]; + }); + return configs; +} + +/** + * Used for legacy unit tests. The public API should go through + * FirebaseDatabase which calls createRepo. + */ ++ (FRepo *)getRepo:(FRepoInfo *)repoInfo config:(FIRDatabaseConfig *)config { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos || repos[repoInfo] == nil) { + // Calling this should create the repo. + [FIRDatabase createDatabaseForTests:repoInfo config:config]; + } + + return configs[config.sessionIdentifier][repoInfo]; + } +} + ++ (FRepo *)createRepo:(FRepoInfo *)repoInfo + config:(FIRDatabaseConfig *)config + database:(FIRDatabase *)database { + [config freeze]; + FRepoDictionary *configs = [FRepoManager configs]; + @synchronized(configs) { + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + if (!repos) { + repos = [NSMutableDictionary dictionary]; + configs[config.sessionIdentifier] = repos; + } + FRepo *repo = repos[repoInfo]; + if (repo == nil) { + repo = [[FRepo alloc] initWithRepoInfo:repoInfo + config:config + database:database]; + repos[repoInfo] = repo; + return repo; + } else { + [NSException + raise:@"RepoExists" + format:@"createRepo called for Repo that already exists."]; + return nil; + } + } +} + ++ (void)interrupt:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + }); +} + ++ (void)interruptAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo interrupt]; + } + } + }); +} + ++ (void)resume:(FIRDatabaseConfig *)config { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + NSMutableDictionary *repos = + configs[config.sessionIdentifier]; + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + }); +} + ++ (void)resumeAll { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + FRepoDictionary *configs = [FRepoManager configs]; + for (NSMutableDictionary *repos in + [configs allValues]) { + for (FRepo *repo in [repos allValues]) { + [repo resume]; + } + } + }); +} + ++ (void)disposeRepos:(FIRDatabaseConfig *)config { + // Do this synchronously to make sure we release our references to LevelDB + // before returning, allowing LevelDB to close and release its exclusive + // locks. + dispatch_sync([FIRDatabaseQuery sharedQueue], ^{ + FFLog(@"I-RDB040001", @"Disposing all repos for Config with name %@", + config.sessionIdentifier); + NSMutableDictionary *configs = [FRepoManager configs]; + for (FRepo *repo in [configs[config.sessionIdentifier] allValues]) { + [repo dispose]; + } + [configs removeObjectForKey:config.sessionIdentifier]; + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h new file mode 100644 index 0000000..8dc1350 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FRepo_Private.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRepo.h" +#import "FSparseSnapshotTree.h" + +@class FSyncTree; +@class FAtomicNumber; +@class FEventRaiser; +@class FSnapshotHolder; + +@interface FRepo () + +- (void)runOnDisconnectEvents; + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPersistentConnection *connection; +@property(nonatomic, strong) FSnapshotHolder *infoData; +@property(nonatomic, strong) FSparseSnapshotTree *onDisconnect; +@property(nonatomic, strong) FEventRaiser *eventRaiser; +@property(nonatomic, strong) FSyncTree *serverSyncTree; + +// For testing. +@property(nonatomic) long dataUpdateCount; +@property(nonatomic) long rangeMergeUpdateCount; + +- (NSInteger)nextWriteId; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h new file mode 100644 index 0000000..33d1e57 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FSparseSnapshotTree.h" +#import + +@interface FServerValues : NSObject + ++ (NSDictionary *)generateServerValues:(id)clock; ++ (id)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withServerValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueSnapshot:(id)node + withServerValues:(NSDictionary *)serverValues; ++ (id)resolveDeferredValueTree:(FSparseSnapshotTree *)tree + withServerValues:(NSDictionary *)serverValues; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m new file mode 100644 index 0000000..5519862 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FServerValues.m @@ -0,0 +1,115 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FServerValues.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FLeafNode.h" +#import "FSnapshotUtilities.h" + +@implementation FServerValues + ++ (NSDictionary *)generateServerValues:(id)clock { + long long millis = (long long)([clock currentTime] * 1000); + return @{@"timestamp" : [NSNumber numberWithLongLong:millis]}; +} + ++ (id)resolveDeferredValue:(id)val + withServerValues:(NSDictionary *)serverValues { + if ([val isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = val; + if (dict[kServerValueSubKey] != nil) { + NSString *serverValueType = [dict objectForKey:kServerValueSubKey]; + if (serverValues[serverValueType] != nil) { + return [serverValues objectForKey:serverValueType]; + } else { + // TODO: Throw unrecognizedServerValue error here + } + } + } + return val; +} + ++ (FCompoundWrite *)resolveDeferredValueCompoundWrite:(FCompoundWrite *)write + withServerValues: + (NSDictionary *)serverValues { + __block FCompoundWrite *resolved = write; + [write enumerateWrites:^(FPath *path, id node, BOOL *stop) { + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:node + withServerValues:serverValues]; + // Node actually changed, use pointer inequality here + if (resolvedNode != node) { + resolved = [resolved addWrite:resolvedNode atPath:path]; + } + }]; + return resolved; +} + ++ (id)resolveDeferredValueTree:(FSparseSnapshotTree *)tree + withServerValues:(NSDictionary *)serverValues { + FSparseSnapshotTree *resolvedTree = [[FSparseSnapshotTree alloc] init]; + [tree + forEachTreeAtPath:[FPath empty] + do:^(FPath *path, id node) { + [resolvedTree + rememberData: + [FServerValues + resolveDeferredValueSnapshot:node + withServerValues:serverValues] + onPath:path]; + }]; + return resolvedTree; +} + ++ (id)resolveDeferredValueSnapshot:(id)node + withServerValues:(NSDictionary *)serverValues { + id priorityVal = + [FServerValues resolveDeferredValue:[[node getPriority] val] + withServerValues:serverValues]; + id priority = [FSnapshotUtilities nodeFrom:priorityVal]; + + if ([node isLeafNode]) { + id value = [self resolveDeferredValue:[node val] + withServerValues:serverValues]; + if (![value isEqual:[node val]] || + ![priority isEqual:[node getPriority]]) { + return [[FLeafNode alloc] initWithValue:value + withPriority:priority]; + } else { + return node; + } + } else { + __block FChildrenNode *newNode = node; + if (![priority isEqual:[node getPriority]]) { + newNode = [newNode updatePriority:priority]; + } + + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + id newChildNode = + [FServerValues resolveDeferredValueSnapshot:childNode + withServerValues:serverValues]; + if (![newChildNode isEqual:childNode]) { + newNode = [newNode updateImmediateChild:childKey + withNewChild:newChildNode]; + } + }]; + return newNode; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h new file mode 100644 index 0000000..d682a8e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FSnapshotHolder : NSObject + +- (id)getNode:(FPath *)path; +- (void)updateSnapshot:(FPath *)path withNewSnapshot:(id)newSnapshotNode; + +@property(nonatomic, strong) id rootNode; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m new file mode 100644 index 0000000..59a7b52 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSnapshotHolder.m @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotHolder.h" +#import "FEmptyNode.h" + +@interface FSnapshotHolder () + +@end + +@implementation FSnapshotHolder + +@synthesize rootNode; + +- (id)init { + self = [super init]; + if (self) { + self.rootNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)getNode:(FPath *)path { + return [self.rootNode getChild:path]; +} + +- (void)updateSnapshot:(FPath *)path + withNewSnapshot:(id)newSnapshotNode { + self.rootNode = [self.rootNode updateChild:path + withNewChild:newSnapshotNode]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h new file mode 100644 index 0000000..dab5406 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@class FSparseSnapshotTree; + +typedef void (^fbt_void_nsstring_sstree)(NSString *, FSparseSnapshotTree *); + +@interface FSparseSnapshotTree : NSObject + +- (id)findPath:(FPath *)path; +- (void)rememberData:(id)data onPath:(FPath *)path; +- (BOOL)forgetPath:(FPath *)path; +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func; +- (void)forEachChild:(fbt_void_nsstring_sstree)func; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m new file mode 100644 index 0000000..6219309 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSparseSnapshotTree.m @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSparseSnapshotTree.h" +#import "FChildrenNode.h" + +@interface FSparseSnapshotTree () { + id value; + NSMutableDictionary *children; +} + +@end + +@implementation FSparseSnapshotTree + +- (id)init { + self = [super init]; + if (self) { + value = nil; + children = nil; + } + return self; +} + +- (id)findPath:(FPath *)path { + if (value != nil) { + return [value getChild:path]; + } else if (![path isEmpty] && children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + FSparseSnapshotTree *childTree = children[childKey]; + if (childTree != nil) { + return [childTree findPath:path]; + } else { + return nil; + } + } else { + return nil; + } +} + +- (void)rememberData:(id)data onPath:(FPath *)path { + if ([path isEmpty]) { + value = data; + children = nil; + } else if (value != nil) { + value = [value updateChild:path withNewChild:data]; + } else { + if (children == nil) { + children = [[NSMutableDictionary alloc] init]; + } + + NSString *childKey = [path getFront]; + if (children[childKey] == nil) { + children[childKey] = [[FSparseSnapshotTree alloc] init]; + } + + FSparseSnapshotTree *child = children[childKey]; + path = [path popFront]; + [child rememberData:data onPath:path]; + } +} + +- (BOOL)forgetPath:(FPath *)path { + if ([path isEmpty]) { + value = nil; + children = nil; + return YES; + } else { + if (value != nil) { + if ([value isLeafNode]) { + // non-empty path at leaf. the path leads to nowhere + return NO; + } else { + id tmp = value; + value = nil; + + [tmp enumerateChildrenUsingBlock:^(NSString *key, + id node, BOOL *stop) { + [self rememberData:node onPath:[[FPath alloc] initWith:key]]; + }]; + + // we've cleared out the value and set children. Call ourself + // again to hit the next case + return [self forgetPath:path]; + } + } else if (children != nil) { + NSString *childKey = [path getFront]; + path = [path popFront]; + + if (children[childKey] != nil) { + FSparseSnapshotTree *child = children[childKey]; + BOOL safeToRemove = [child forgetPath:path]; + if (safeToRemove) { + [children removeObjectForKey:childKey]; + } + } + + if ([children count] == 0) { + children = nil; + return YES; + } else { + return NO; + } + } else { + return YES; + } + } +} + +- (void)forEachTreeAtPath:(FPath *)prefixPath do:(fbt_void_path_node)func { + if (value != nil) { + func(prefixPath, value); + } else { + [self forEachChild:^(NSString *key, FSparseSnapshotTree *tree) { + FPath *path = [prefixPath childFromString:key]; + [tree forEachTreeAtPath:path do:func]; + }]; + } +} + +- (void)forEachChild:(fbt_void_nsstring_sstree)func { + if (children != nil) { + for (NSString *key in children) { + FSparseSnapshotTree *tree = [children objectForKey:key]; + func(key, tree); + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h new file mode 100644 index 0000000..a9bd4d9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.h @@ -0,0 +1,69 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FOperation; +@class FWriteTreeRef; +@protocol FNode; +@protocol FEventRegistration; +@class FQuerySpec; +@class FChildrenNode; +@class FTupleRemovedQueriesEvents; +@class FView; +@class FPath; +@class FCacheNode; +@class FPersistenceManager; + +@interface FSyncPoint : NSObject + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence; + +- (BOOL)isEmpty; + +/** + * Returns array of FEvent + */ +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; + +/** + * Returns array of FEvent + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache; + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query; + +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +/** + * Returns array of FViews + */ +- (NSArray *)queryViews; +- (id)completeServerCacheAtPath:(FPath *)path; +- (FView *)viewForQuery:(FQuerySpec *)query; +- (BOOL)viewExistsForQuery:(FQuerySpec *)query; +- (BOOL)hasCompleteView; +- (FView *)completeView; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m new file mode 100644 index 0000000..6496ae8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncPoint.m @@ -0,0 +1,302 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncPoint.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FDataEvent.h" +#import "FEmptyNode.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FView.h" +#import "FViewCache.h" +#import "FWriteTreeRef.h" + +/** + * SyncPoint represents a single location in a SyncTree with 1 or more event + * registrations, meaning we need to maintain 1 or more Views at this location + * to cache server data and raise appropriate events for server changes and user + * writes (set, transaction, update). + * + * It's responsible for: + * - Maintaining the set of 1 or more views necessary at this location (a + * SyncPoint with 0 views should be removed). + * - Proxying user / server operations to the views as appropriate (i.e. + * applyServerOverwrite, applyUserOverwrite, etc.) + */ +@interface FSyncPoint () +/** + * The Views being tracked at this location in the tree, stored as a map where + * the key is a queryParams and the value is the View for that query. + * + * NOTE: This list will be quite small (usually 1, but perhaps 2 or 3; any more + * is an odd use case). + * + * Maps NSString -> FView + */ +@property(nonatomic, strong) NSMutableDictionary *views; + +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@end + +@implementation FSyncPoint + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistence { + self = [super init]; + if (self) { + self.persistenceManager = persistence; + self.views = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (BOOL)isEmpty { + return [self.views count] == 0; +} + +- (NSArray *)applyOperation:(id)operation + toView:(FView *)view + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FViewOperationResult *result = [view applyOperation:operation + writesCache:writesCache + serverCache:optCompleteServerCache]; + if (!view.query.loadsAllData) { + NSMutableSet *removed = [NSMutableSet set]; + NSMutableSet *added = [NSMutableSet set]; + [result.changes enumerateObjectsUsingBlock:^( + FChange *change, NSUInteger idx, BOOL *stop) { + if (change.type == FIRDataEventTypeChildAdded) { + [added addObject:change.childKey]; + } else if (change.type == FIRDataEventTypeChildRemoved) { + [removed addObject:change.childKey]; + } + }]; + if ([removed count] > 0 || [added count] > 0) { + [self.persistenceManager + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQuery:view.query]; + } + } + return result.events; +} + +- (NSArray *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + FQueryParams *queryParams = operation.source.queryParams; + if (queryParams != nil) { + FView *view = [self.views objectForKey:queryParams]; + NSAssert(view != nil, @"SyncTree gave us an op for an invalid query."); + return [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + } else { + NSMutableArray *events = [[NSMutableArray alloc] init]; + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *key, FView *view, BOOL *stop) { + NSArray *eventsForView = [self applyOperation:operation + toView:view + writesCache:writesCache + serverCache:optCompleteServerCache]; + [events addObjectsFromArray:eventsForView]; + }]; + return events; + } +} + +/** + * Add an event callback for the specified query + * Returns Array of FEvent events to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forNonExistingViewForQuery:(FQuerySpec *)query + writesCache:(FWriteTreeRef *)writesCache + serverCache:(FCacheNode *)serverCache { + NSAssert(self.views[query.params] == nil, @"Found view for query: %@", + query.params); + // TODO: make writesCache take flag for complete server node + id eventCache = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + serverCache.isFullyInitialized ? serverCache.node : nil]; + BOOL eventCacheComplete; + if (eventCache != nil) { + eventCacheComplete = YES; + } else { + eventCache = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren:serverCache + .node]; + eventCacheComplete = NO; + } + + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:eventCache + index:query.index]; + FCacheNode *eventCacheNode = + [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:eventCacheComplete + isFiltered:NO]; + FViewCache *viewCache = + [[FViewCache alloc] initWithEventCache:eventCacheNode + serverCache:serverCache]; + FView *view = [[FView alloc] initWithQuery:query + initialViewCache:viewCache]; + // If this is a non-default query we need to tell persistence our current + // view of the data + if (!query.loadsAllData) { + NSMutableSet *allKeys = [NSMutableSet set]; + [view.eventCache enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + [allKeys addObject:key]; + }]; + [self.persistenceManager setTrackedQueryKeys:allKeys forQuery:query]; + } + self.views[query.params] = view; + return [self addEventRegistration:eventRegistration + forExistingViewForQuery:query]; +} + +- (NSArray *)addEventRegistration:(id)eventRegistration + forExistingViewForQuery:(FQuerySpec *)query { + FView *view = self.views[query.params]; + NSAssert(view != nil, @"No view for query: %@", query); + [view addEventRegistration:eventRegistration]; + return [view initialEvents:eventRegistration]; +} + +/** + * Remove event callback(s). Return cancelEvents if a cancelError is specified. + * + * If query is the default query, we'll check all views for the specified + * eventRegistration. If eventRegistration is nil, we'll remove all callbacks + * for the specified view(s). + * + * @return FTupleRemovedQueriesEvents removed queries and any cancel events + */ +- (FTupleRemovedQueriesEvents *)removeEventRegistration: + (id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + NSMutableArray *removedQueries = [[NSMutableArray alloc] init]; + __block NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + BOOL hadCompleteView = [self hasCompleteView]; + if ([query isDefault]) { + // When you do [ref removeObserverWithHandle:], we search all views for + // the registration to remove. + [self.views enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *viewQueryParams, FView *view, + BOOL *stop) { + [cancelEvents + addObjectsFromArray:[view + removeEventRegistration:eventRegistration + cancelError:cancelError]]; + if ([view isEmpty]) { + [self.views removeObjectForKey:viewQueryParams]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + }]; + } else { + // remove the callback from the specific view + FView *view = [self.views objectForKey:query.params]; + if (view != nil) { + [cancelEvents addObjectsFromArray: + [view removeEventRegistration:eventRegistration + cancelError:cancelError]]; + + if ([view isEmpty]) { + [self.views removeObjectForKey:query.params]; + + // We'll deal with complete views later + if (![view.query loadsAllData]) { + [removedQueries addObject:view.query]; + } + } + } + } + + if (hadCompleteView && ![self hasCompleteView]) { + // We removed our last complete view + [removedQueries addObject:[FQuerySpec defaultQueryAtPath:query.path]]; + } + + return [[FTupleRemovedQueriesEvents alloc] + initWithRemovedQueries:removedQueries + cancelEvents:cancelEvents]; +} + +- (NSArray *)queryViews { + __block NSMutableArray *filteredViews = [[NSMutableArray alloc] init]; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if (![view.query loadsAllData]) { + [filteredViews addObject:view]; + } + }]; + + return filteredViews; +} + +- (id)completeServerCacheAtPath:(FPath *)path { + __block id serverCache = nil; + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + serverCache = [view completeServerCacheFor:path]; + *stop = (serverCache != nil); + }]; + return serverCache; +} + +- (FView *)viewForQuery:(FQuerySpec *)query { + return [self.views objectForKey:query.params]; +} + +- (BOOL)viewExistsForQuery:(FQuerySpec *)query { + return [self viewForQuery:query] != nil; +} + +- (BOOL)hasCompleteView { + return [self completeView] != nil; +} + +- (FView *)completeView { + __block FView *completeView = nil; + + [self.views enumerateKeysAndObjectsUsingBlock:^(FQueryParams *key, + FView *view, BOOL *stop) { + if ([view.query loadsAllData]) { + completeView = view; + *stop = YES; + } + }]; + + return completeView; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h new file mode 100644 index 0000000..ef89774 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FListenProvider; +@protocol FNode; +@class FPath; +@protocol FEventRegistration; +@protocol FPersistedServerCache; +@class FQuerySpec; +@class FCompoundWrite; +@class FPersistenceManager; +@class FCompoundHash; +@protocol FClock; + +@protocol FSyncTreeHash + +- (NSString *)simpleHash; +- (FCompoundHash *)compoundHash; +- (BOOL)includeCompoundHash; + +@end + +@interface FSyncTree : NSObject + +- (id)initWithListenProvider:(FListenProvider *)provider; +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider; + +// These methods all return NSArray of FEvent +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock; +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData; +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren; +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges; +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId; +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId; +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query; +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError; +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced; +- (NSArray *)removeAllWrites; + +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m new file mode 100644 index 0000000..e7fa3dc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FSyncTree.m @@ -0,0 +1,1038 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSyncTree.h" +#import "FAckUserWrite.h" +#import "FAtomicNumber.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundHash.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FEventRaiser.h" +#import "FEventRegistration.h" +#import "FImmutableTree.h" +#import "FKeepSyncedEventRegistration.h" +#import "FListenComplete.h" +#import "FListenProvider.h" +#import "FMerge.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FPersistenceManager.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FRangeMerge.h" +#import "FServerValues.h" +#import "FSnapshotHolder.h" +#import "FSnapshotUtilities.h" +#import "FSyncPoint.h" +#import "FTupleRemovedQueriesEvents.h" +#import "FUtilities.h" +#import "FView.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" +#import "FWriteTreeRef.h" +#import + +// Size after which we start including the compound hash +static const NSUInteger kFSizeThresholdForCompoundHash = 1024; + +@interface FListenContainer : NSObject + +@property(nonatomic, strong) FView *view; +@property(nonatomic, copy) fbt_nsarray_nsstring onComplete; + +@end + +@implementation FListenContainer + +- (instancetype)initWithView:(FView *)view + onComplete:(fbt_nsarray_nsstring)onComplete { + self = [super init]; + if (self != nil) { + self->_view = view; + self->_onComplete = onComplete; + } + return self; +} + +- (id)serverCache { + return self.view.serverCache; +} + +- (FCompoundHash *)compoundHash { + return [FCompoundHash fromNode:[self serverCache]]; +} + +- (NSString *)simpleHash { + return [[self serverCache] dataHash]; +} + +- (BOOL)includeCompoundHash { + return [FSnapshotUtilities estimateSerializedNodeSize:[self serverCache]] > + kFSizeThresholdForCompoundHash; +} + +@end + +@interface FSyncTree () + +/** + * Tree of SyncPoints. There's a SyncPoint at any location that has 1 or more + * views. + */ +@property(nonatomic, strong) FImmutableTree *syncPointTree; + +/** + * A tree of all pending user writes (user-initiated set, transactions, updates, + * etc) + */ +@property(nonatomic, strong) FWriteTree *pendingWriteTree; + +/** + * Maps tagId -> FTuplePathQueryParams + */ +@property(nonatomic, strong) NSMutableDictionary *tagToQueryMap; +@property(nonatomic, strong) NSMutableDictionary *queryToTagMap; +@property(nonatomic, strong) FListenProvider *listenProvider; +@property(nonatomic, strong) FPersistenceManager *persistenceManager; +@property(nonatomic, strong) FAtomicNumber *queryTagCounter; +@property(nonatomic, strong) NSMutableSet *keepSyncedQueries; + +@end + +/** + * SyncTree is the central class for managing event callback registration, data + * caching, views (query processing), and event generation. There are typically + * two SyncTree instances for each Repo, one for the normal Firebase data, and + * one for the .info data. + * + * It has a number of responsibilities, including: + * - Tracking all user event callbacks (registered via addEventRegistration: + * and removeEventRegistration:). + * - Applying and caching data changes for user setValue:, + * runTransactionBlock:, and updateChildValues: calls + * (applyUserOverwriteAtPath:, applyUserMergeAtPath:). + * - Applying and caching data changes for server data changes + * (applyServerOverwriteAtPath:, applyServerMergeAtPath:). + * - Generating user-facing events for server and user changes (all of the + * apply* methods return the set of events that need to be raised as a result). + * - Maintaining the appropriate set of server listens to ensure we are always + * subscribed to the correct set of paths and queries to satisfy the current set + * of user event callbacks (listens are started/stopped using the provided + * listenProvider). + * + * NOTE: Although SyncTree tracks event callbacks and calculates events to + * raise, the actual events are returned to the caller rather than raised + * synchronously. + */ +@implementation FSyncTree + +- (id)initWithListenProvider:(FListenProvider *)provider { + return [self initWithPersistenceManager:nil listenProvider:provider]; +} + +- (id)initWithPersistenceManager:(FPersistenceManager *)persistenceManager + listenProvider:(FListenProvider *)provider { + self = [super init]; + if (self) { + self.syncPointTree = [FImmutableTree empty]; + self.pendingWriteTree = [[FWriteTree alloc] init]; + self.tagToQueryMap = [[NSMutableDictionary alloc] init]; + self.queryToTagMap = [[NSMutableDictionary alloc] init]; + self.listenProvider = provider; + self.persistenceManager = persistenceManager; + self.queryTagCounter = [[FAtomicNumber alloc] init]; + self.keepSyncedQueries = [NSMutableSet set]; + } + return self; +} + +#pragma mark - +#pragma mark Apply Operations + +/** + * Apply data changes for a user-generated setValue: runTransactionBlock: + * updateChildValues:, etc. + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + // Record pending write + [self.pendingWriteTree addOverwriteAtPath:path + newData:newData + writeId:writeId + isVisible:visible]; + if (!visible) { + return @[]; + } else { + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource userInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply the data from a user-generated updateChildValues: call + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyUserMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + // Record pending merge + [self.pendingWriteTree addMergeAtPath:path + changedChildren:changedChildren + writeId:writeId]; + + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource userInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Acknowledge a pending user write that was previously registered with + * applyUserOverwriteAtPath: or applyUserMergeAtPath: + * TODO[offline]: Taking a serverClock here is awkward, but server values are + * awkward. :-( + * @return NSArray of FEvent to raise. + */ +- (NSArray *)ackUserWriteWithWriteId:(NSInteger)writeId + revert:(BOOL)revert + persist:(BOOL)persist + clock:(id)clock { + FWriteRecord *write = [self.pendingWriteTree writeForId:writeId]; + BOOL needToReevaluate = [self.pendingWriteTree removeWriteId:writeId]; + if (write.visible) { + if (persist) { + [self.persistenceManager removeUserWrite:writeId]; + } + if (!revert) { + NSDictionary *serverValues = + [FServerValues generateServerValues:clock]; + if ([write isOverwrite]) { + id resolvedNode = + [FServerValues resolveDeferredValueSnapshot:write.overwrite + withServerValues:serverValues]; + [self.persistenceManager applyUserWrite:resolvedNode + toServerCacheAtPath:write.path]; + } else { + FCompoundWrite *resolvedMerge = [FServerValues + resolveDeferredValueCompoundWrite:write.merge + withServerValues:serverValues]; + [self.persistenceManager applyUserMerge:resolvedMerge + toServerCacheAtPath:write.path]; + } + } + } + if (!needToReevaluate) { + return @[]; + } else { + __block FImmutableTree *affectedTree = [FImmutableTree empty]; + if (write.isOverwrite) { + affectedTree = [affectedTree setValue:@YES atPath:[FPath empty]]; + } else { + [write.merge + enumerateWrites:^(FPath *path, id node, BOOL *stop) { + affectedTree = [affectedTree setValue:@YES atPath:path]; + }]; + } + FAckUserWrite *operation = + [[FAckUserWrite alloc] initWithPath:write.path + affectedTree:affectedTree + revert:revert]; + return [self applyOperationToSyncPoints:operation]; + } +} + +/** + * Apply new server data for the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerOverwriteAtPath:(FPath *)path + newData:(id)newData { + [self.persistenceManager + updateServerCacheWithNode:newData + forQuery:[FQuerySpec defaultQueryAtPath:path]]; + FOverwrite *operation = + [[FOverwrite alloc] initWithSource:[FOperationSource serverInstance] + path:path + snap:newData]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Applied new server data to be merged in at the specified path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyServerMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren { + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = + [[FMerge alloc] initWithSource:[FOperationSource serverInstance] + path:path + children:changedChildren]; + return [self applyOperationToSyncPoints:operation]; +} + +- (NSArray *)applyServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + // Removed view, so it's safe to just ignore this update + return @[]; + } else { + // This could be for any "complete" (unfiltered) view, and if there is + // more than one complete view, they should each have the same cache so + // it doesn't matter which one we use. + FView *view = [syncPoint completeView]; + if (view != nil) { + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyServerOverwriteAtPath:path newData:serverNode]; + } else { + // There doesn't exist a view for this update, so it was removed and + // it's safe to just ignore this range merge + return @[]; + } + } +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyListenCompleteAtPath:(FPath *)path { + [self.persistenceManager + setQueryComplete:[FQuerySpec defaultQueryAtPath:path]]; + id operation = [[FListenComplete alloc] + initWithSource:[FOperationSource serverInstance] + path:path]; + return [self applyOperationToSyncPoints:operation]; +} + +/** + * Apply a listen complete to a path + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedListenCompleteAtPath:(FPath *)path + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + [self.persistenceManager setQueryComplete:query]; + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + id op = [[FListenComplete alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath]; + return [self applyTaggedOperation:op atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Internal helper method to apply tagged operation + */ +- (NSArray *)applyTaggedOperation:(id)operation + atPath:(FPath *)path { + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + return [syncPoint applyOperation:operation + writesCache:writesCache + serverCache:nil]; +} + +/** + * Apply new server data for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryOverwriteAtPath:(FPath *)path + newData:(id)newData + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + FQuerySpec *queryToOverwrite = + relativePath.isEmpty ? query : [FQuerySpec defaultQueryAtPath:path]; + [self.persistenceManager updateServerCacheWithNode:newData + forQuery:queryToOverwrite]; + FOverwrite *operation = [[FOverwrite alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + snap:newData]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // Query must have been removed already + return @[]; + } +} + +/** + * Apply server data to be merged in for the specified tagged query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)applyTaggedQueryMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + FPath *relativePath = [FPath relativePathFrom:query.path to:path]; + [self.persistenceManager updateServerCacheWithMerge:changedChildren + atPath:path]; + FMerge *operation = [[FMerge alloc] + initWithSource:[FOperationSource forServerTaggedQuery:query.params] + path:relativePath + children:changedChildren]; + return [self applyTaggedOperation:operation atPath:query.path]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +- (NSArray *)applyTaggedServerRangeMergeAtPath:(FPath *)path + updates:(NSArray *)ranges + tagId:(NSNumber *)tagId { + FQuerySpec *query = [self queryForTag:tagId]; + if (query != nil) { + NSAssert([path isEqual:query.path], + @"Tagged update path and query path must match"); + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + NSAssert(syncPoint != nil, + @"Missing sync point for query tag that we're tracking."); + FView *view = [syncPoint viewForQuery:query]; + NSAssert(view != nil, + @"Missing view for query tag that we're tracking"); + id serverNode = [view serverCache]; + for (FRangeMerge *merge in ranges) { + serverNode = [merge applyToNode:serverNode]; + } + return [self applyTaggedQueryOverwriteAtPath:path + newData:serverNode + tagId:tagId]; + } else { + // We've already removed the query. No big deal, ignore the update. + return @[]; + } +} + +/** + * Add an event callback for the specified query + * @return NSArray of FEvent to raise. + */ +- (NSArray *)addEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query { + FPath *path = query.path; + + __block BOOL foundAncestorDefaultView = NO; + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + foundAncestorDefaultView = + foundAncestorDefaultView || [syncPoint hasCompleteView]; + return !foundAncestorDefaultView; + }]; + + [self.persistenceManager setQueryActive:query]; + + FSyncPoint *syncPoint = [self.syncPointTree valueAtPath:path]; + if (syncPoint == nil) { + syncPoint = [[FSyncPoint alloc] + initWithPersistenceManager:self.persistenceManager]; + self.syncPointTree = [self.syncPointTree setValue:syncPoint + atPath:path]; + } + + BOOL viewAlreadyExists = [syncPoint viewExistsForQuery:query]; + NSArray *events; + if (viewAlreadyExists) { + events = [syncPoint addEventRegistration:eventRegistration + forExistingViewForQuery:query]; + } else { + if (![query loadsAllData]) { + // We need to track a tag for this query + NSAssert(self.queryToTagMap[query] == nil, + @"View does not exist, but we have a tag"); + NSNumber *tagId = [self.queryTagCounter getAndIncrement]; + self.queryToTagMap[query] = tagId; + self.tagToQueryMap[tagId] = query; + } + + FWriteTreeRef *writesCache = + [self.pendingWriteTree childWritesForPath:path]; + FCacheNode *serverCache = [self serverCacheForQuery:query]; + events = [syncPoint addEventRegistration:eventRegistration + forNonExistingViewForQuery:query + writesCache:writesCache + serverCache:serverCache]; + + // There was no view and no default listen + if (!foundAncestorDefaultView) { + FView *view = [syncPoint viewForQuery:query]; + NSMutableArray *mutableEvents = [events mutableCopy]; + [mutableEvents + addObjectsFromArray:[self setupListenerOnQuery:query + view:view]]; + events = mutableEvents; + } + } + + return events; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + __block id serverCacheNode = nil; + + [self.syncPointTree + forEachOnPath:query.path + whileBlock:^BOOL(FPath *pathToSyncPoint, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathToSyncPoint + to:query.path]; + serverCacheNode = + [syncPoint completeServerCacheAtPath:relativePath]; + return serverCacheNode == nil; + }]; + + FCacheNode *serverCache; + if (serverCacheNode != nil) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + FCacheNode *persistenceServerCache = + [self.persistenceManager serverCacheForQuery:query]; + if (persistenceServerCache.isFullyInitialized) { + serverCache = persistenceServerCache; + } else { + serverCacheNode = [FEmptyNode emptyNode]; + + FImmutableTree *subtree = + [self.syncPointTree subtreeAtPath:query.path]; + [subtree + forEachChild:^(NSString *childKey, FSyncPoint *childSyncPoint) { + id completeCache = + [childSyncPoint completeServerCacheAtPath:[FPath empty]]; + if (completeCache) { + serverCacheNode = + [serverCacheNode updateImmediateChild:childKey + withNewChild:completeCache]; + } + }]; + // Fill the node with any available children we have + [persistenceServerCache.node + enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (![serverCacheNode hasChild:key]) { + serverCacheNode = + [serverCacheNode updateImmediateChild:key + withNewChild:node]; + } + }]; + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:serverCacheNode + index:query.index]; + serverCache = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:NO + isFiltered:NO]; + } + } + + return serverCache; +} + +/** + * Remove event callback(s). + * + * If query is the default query, we'll check all queries for the specified + * eventRegistration. If eventRegistration is null, we'll remove all callbacks + * for the specified query/queries. + * + * @param eventRegistration if nil, all callbacks are removed + * @param cancelError If provided, appropriate cancel events will be returned + * @return NSArray of FEvent to raise. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + forQuery:(FQuerySpec *)query + cancelError:(NSError *)cancelError { + // Find the syncPoint first. Then deal with whether or not it has matching + // listeners + FPath *path = query.path; + FSyncPoint *maybeSyncPoint = [self.syncPointTree valueAtPath:path]; + NSArray *cancelEvents = @[]; + + // A removal on a default query affects all queries at that location. A + // removal on an indexed query, even one without other query constraints, + // does *not* affect all queries at that location. So this check must be for + // 'default', and not loadsAllData: + if (maybeSyncPoint && + ([query isDefault] || [maybeSyncPoint viewExistsForQuery:query])) { + FTupleRemovedQueriesEvents *removedAndEvents = + [maybeSyncPoint removeEventRegistration:eventRegistration + forQuery:query + cancelError:cancelError]; + if ([maybeSyncPoint isEmpty]) { + self.syncPointTree = [self.syncPointTree removeValueAtPath:path]; + } + NSArray *removed = removedAndEvents.removedQueries; + cancelEvents = removedAndEvents.cancelEvents; + + // We may have just removed one of many listeners and can short-circuit + // this whole process We may also not have removed a default listener, + // in which case all of the descendant listeners should already be + // properly set up. + // + // Since indexed queries can shadow if they don't have other query + // constraints, check for loadsAllData: instead of isDefault: + NSUInteger defaultQueryIndex = [removed + indexOfObjectPassingTest:^BOOL(FQuerySpec *q, NSUInteger idx, + BOOL *stop) { + return [q loadsAllData]; + }]; + BOOL removingDefault = defaultQueryIndex != NSNotFound; + [removed enumerateObjectsUsingBlock:^(FQuerySpec *query, NSUInteger idx, + BOOL *stop) { + [self.persistenceManager setQueryInactive:query]; + }]; + NSNumber *covered = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *relativePath, + FSyncPoint *parentSyncPoint) { + return + [NSNumber numberWithBool:[parentSyncPoint hasCompleteView]]; + }]; + + if (removingDefault && ![covered boolValue]) { + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // There are potentially child listeners. Determine what if any + // listens we need to send before executing the removal + if (![subtree isEmpty]) { + // We need to fold over our subtree and collect the listeners to + // send + NSArray *newViews = + [self collectDistinctViewsForSubTree:subtree]; + + // Ok, we've collected all the listens we need. Set them up. + [newViews enumerateObjectsUsingBlock:^( + FView *view, NSUInteger idx, BOOL *stop) { + FQuerySpec *newQuery = view.query; + FListenContainer *listenContainer = + [self createListenerForView:view]; + self.listenProvider.startListening( + [self queryForListening:newQuery], + [self tagForQuery:newQuery], listenContainer, + listenContainer.onComplete); + }]; + } else { + // There's nothing below us, so nothing we need to start + // listening on + } + } + + // If we removed anything and we're not covered by a higher up listen, + // we need to stop listening on this query. The above block has us + // covered in terms of making sure we're set up on listens lower in the + // tree. Also, note that if we have a cancelError, it's already been + // removed at the provider level. + if (![covered boolValue] && [removed count] > 0 && cancelError == nil) { + // If we removed a default, then we weren't listening on any of the + // other queries here. Just cancel the one default. Otherwise, we + // need to iterate through and cancel each individual query + if (removingDefault) { + // We don't tag default listeners + self.listenProvider.stopListening( + [self queryForListening:query], nil); + } else { + [removed + enumerateObjectsUsingBlock:^(FQuerySpec *queryToRemove, + NSUInteger idx, BOOL *stop) { + NSNumber *tagToRemove = + [self.queryToTagMap objectForKey:queryToRemove]; + self.listenProvider.stopListening( + [self queryForListening:queryToRemove], tagToRemove); + }]; + } + } + // Now, clear all the tags we're tracking for the removed listens. + [self removeTags:removed]; + } else { + // No-op, this listener must've been already removed + } + return cancelEvents; +} + +- (void)keepQuery:(FQuerySpec *)query synced:(BOOL)keepSynced { + // Only do something if we actually need to add/remove an event registration + if (keepSynced && ![self.keepSyncedQueries containsObject:query]) { + [self addEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query]; + [self.keepSyncedQueries addObject:query]; + } else if (!keepSynced && [self.keepSyncedQueries containsObject:query]) { + [self removeEventRegistration:[FKeepSyncedEventRegistration instance] + forQuery:query + cancelError:nil]; + [self.keepSyncedQueries removeObject:query]; + } +} + +- (NSArray *)removeAllWrites { + [self.persistenceManager removeAllUserWrites]; + NSArray *removedWrites = [self.pendingWriteTree removeAllWrites]; + if (removedWrites.count > 0) { + FImmutableTree *affectedTree = + [[FImmutableTree empty] setValue:@YES atPath:[FPath empty]]; + return [self applyOperationToSyncPoints:[[FAckUserWrite alloc] + initWithPath:[FPath empty] + affectedTree:affectedTree + revert:YES]]; + } else { + return @[]; + } +} + +/** + * Returns a complete cache, if we have one, of the data at a particular path. + * The location must have a listener above it, but as this is only used by + * transaction code, that should always be the case anyways. + * + * Note: this method will *include* hidden writes from transaction with + * applyLocally set to false. + * @param path The path to the data we want + * @param writeIdsToExclude A specific set to be excluded + */ +- (id)calcCompleteEventCacheAtPath:(FPath *)path + excludeWriteIds:(NSArray *)writeIdsToExclude { + BOOL includeHiddenSets = YES; + FWriteTree *writeTree = self.pendingWriteTree; + id serverCache = [self.syncPointTree + findOnPath:path + andApplyBlock:^id(FPath *pathSoFar, FSyncPoint *syncPoint) { + FPath *relativePath = [FPath relativePathFrom:pathSoFar to:path]; + id serverCache = + [syncPoint completeServerCacheAtPath:relativePath]; + if (serverCache) { + return serverCache; + } else { + return nil; + } + }]; + return [writeTree calculateCompleteEventCacheAtPath:path + completeServerCache:serverCache + excludeWriteIds:writeIdsToExclude + includeHiddenWrites:includeHiddenSets]; +} + +#pragma mark - +#pragma mark Private Methods +/** + * This collapses multiple unfiltered views into a single view, since we only + * need a single listener for them. + * @return NSArray of FView + */ +- (NSArray *)collectDistinctViewsForSubTree:(FImmutableTree *)subtree { + return [subtree foldWithBlock:^NSArray *(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (maybeChildSyncPoint && [maybeChildSyncPoint hasCompleteView]) { + FView *completeView = [maybeChildSyncPoint completeView]; + return @[ completeView ]; + } else { + // No complete view here, flatten any deeper listens into an array + NSMutableArray *views = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint) { + views = [[maybeChildSyncPoint queryViews] mutableCopy]; + } + [childMap enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, NSArray *childViews, BOOL *stop) { + [views addObjectsFromArray:childViews]; + }]; + return views; + } + }]; +} + +/** + * @param queries NSArray of FQuerySpec + */ +- (void)removeTags:(NSArray *)queries { + [queries enumerateObjectsUsingBlock:^(FQuerySpec *removedQuery, + NSUInteger idx, BOOL *stop) { + if (![removedQuery loadsAllData]) { + // We should have a tag for this + NSNumber *removedQueryTag = self.queryToTagMap[removedQuery]; + [self.queryToTagMap removeObjectForKey:removedQuery]; + [self.tagToQueryMap removeObjectForKey:removedQueryTag]; + } + }]; +} + +- (FQuerySpec *)queryForListening:(FQuerySpec *)query { + if (query.loadsAllData && !query.isDefault) { + // We treat queries that load all data as default queries + return [FQuerySpec defaultQueryAtPath:query.path]; + } else { + return query; + } +} + +/** + * For a given new listen, manage the de-duplication of outstanding + * subscriptions. + * @return NSArray of FEvent events to support synchronous data sources + */ +- (NSArray *)setupListenerOnQuery:(FQuerySpec *)query view:(FView *)view { + FPath *path = query.path; + NSNumber *tagId = [self tagForQuery:query]; + FListenContainer *listenContainer = [self createListenerForView:view]; + + NSArray *events = self.listenProvider.startListening( + [self queryForListening:query], tagId, listenContainer, + listenContainer.onComplete); + + FImmutableTree *subtree = [self.syncPointTree subtreeAtPath:path]; + // The root of this subtree has our query. We're here because we definitely + // need to send a listen for that, but we may need to shadow other listens + // as well. + if (tagId != nil) { + NSAssert(![subtree.value hasCompleteView], + @"If we're adding a query, it shouldn't be shadowed"); + } else { + // Shadow everything at or below this location, this is a default + // listener. + NSArray *queriesToStop = + [subtree foldWithBlock:^id(FPath *relativePath, + FSyncPoint *maybeChildSyncPoint, + NSDictionary *childMap) { + if (![relativePath isEmpty] && maybeChildSyncPoint != nil && + [maybeChildSyncPoint hasCompleteView]) { + return @[ [maybeChildSyncPoint completeView].query ]; + } else { + // No default listener here, flatten any deeper queries into + // an array + NSMutableArray *queries = [[NSMutableArray alloc] init]; + if (maybeChildSyncPoint != nil) { + for (FView *view in [maybeChildSyncPoint queryViews]) { + [queries addObject:view.query]; + } + } + [childMap + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, NSArray *childQueries, BOOL *stop) { + [queries addObjectsFromArray:childQueries]; + }]; + return queries; + } + }]; + for (FQuerySpec *queryToStop in queriesToStop) { + self.listenProvider.stopListening( + [self queryForListening:queryToStop], + [self tagForQuery:queryToStop]); + } + } + return events; +} + +- (FListenContainer *)createListenerForView:(FView *)view { + FQuerySpec *query = view.query; + NSNumber *tagId = [self tagForQuery:query]; + + FListenContainer *listenContainer = [[FListenContainer alloc] + initWithView:view + onComplete:^(NSString *status) { + if ([status isEqualToString:@"ok"]) { + if (tagId != nil) { + return [self applyTaggedListenCompleteAtPath:query.path + tagId:tagId]; + } else { + return [self applyListenCompleteAtPath:query.path]; + } + } else { + // If a listen failed, kill all of the listeners here, not just + // the one that triggered the error. Note that this may need to + // be scoped to just this listener if we change permissions on + // filtered children + NSError *error = [FUtilities errorForStatus:status + andReason:nil]; + FFWarn(@"I-RDB038012", @"Listener at %@ failed: %@", query.path, + status); + return [self removeEventRegistration:nil + forQuery:query + cancelError:error]; + } + }]; + + return listenContainer; +} + +/** + * @return The query associated with the given tag, if we have one + */ +- (FQuerySpec *)queryForTag:(NSNumber *)tagId { + return self.tagToQueryMap[tagId]; +} + +/** + * @return The tag associated with the given query + */ +- (NSNumber *)tagForQuery:(FQuerySpec *)query { + return self.queryToTagMap[query]; +} + +#pragma mark - +#pragma mark applyOperation Helpers + +/** +* A helper method that visits all descendant and ancestor SyncPoints, applying +the operation. +* +* NOTES: +* - Descendant SyncPoints will be visited first (since we raise events +depth-first). + +* - We call applyOperation: on each SyncPoint passing three things: +* 1. A version of the Operation that has been made relative to the SyncPoint +location. +* 2. A WriteTreeRef of any writes we have cached at the SyncPoint location. +* 3. A snapshot Node with cached server data, if we have it. + +* - We concatenate all of the events returned by each SyncPoint and return the +result. +* +* @return Array of FEvent +*/ +- (NSArray *)applyOperationToSyncPoints:(id)operation { + return [self applyOperationHelper:operation + syncPointTree:self.syncPointTree + serverCache:nil + writesCache:[self.pendingWriteTree + childWritesForPath:[FPath empty]]]; +} + +/** + * Recursive helper for applyOperationToSyncPoints_ + */ +- (NSArray *)applyOperationHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + if ([operation.path isEmpty]) { + return [self applyOperationDescendantsHelper:operation + syncPointTree:syncPointTree + serverCache:serverCache + writesCache:writesCache]; + } else { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + if (serverCache == nil && syncPoint != nil) { + serverCache = [syncPoint completeServerCacheAtPath:[FPath empty]]; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + NSString *childKey = [operation.path getFront]; + id childOperation = [operation operationForChild:childKey]; + FImmutableTree *childTree = [syncPointTree.children get:childKey]; + if (childTree != nil && childOperation != nil) { + id childServerCache = + serverCache ? [serverCache getImmediateChild:childKey] : nil; + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + [events + addObjectsFromArray:[self + applyOperationHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + + if (syncPoint) { + [events addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:serverCache]]; + } + + return events; + } +} + +/** + * Recursive helper for applyOperationToSyncPoints: + */ +- (NSArray *)applyOperationDescendantsHelper:(id)operation + syncPointTree:(FImmutableTree *)syncPointTree + serverCache:(id)serverCache + writesCache:(FWriteTreeRef *)writesCache { + FSyncPoint *syncPoint = syncPointTree.value; + + // If we don't have cached server data, see if we can get it from this + // SyncPoint + id resolvedServerCache; + if (serverCache == nil & syncPoint != nil) { + resolvedServerCache = + [syncPoint completeServerCacheAtPath:[FPath empty]]; + } else { + resolvedServerCache = serverCache; + } + + NSMutableArray *events = [[NSMutableArray alloc] init]; + [syncPointTree.children enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, + BOOL *stop) { + id childServerCache = nil; + if (resolvedServerCache != nil) { + childServerCache = [resolvedServerCache getImmediateChild:childKey]; + } + FWriteTreeRef *childWritesCache = + [writesCache childWriteTreeRef:childKey]; + id childOperation = [operation operationForChild:childKey]; + if (childOperation != nil) { + [events addObjectsFromArray: + [self applyOperationDescendantsHelper:childOperation + syncPointTree:childTree + serverCache:childServerCache + writesCache:childWritesCache]]; + } + }]; + + if (syncPoint) { + [events + addObjectsFromArray:[syncPoint applyOperation:operation + writesCache:writesCache + serverCache:resolvedServerCache]]; + } + + return events; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h new file mode 100644 index 0000000..435fb6a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.h @@ -0,0 +1,45 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@class FCompoundWrite; +@protocol FNode; + +@interface FWriteRecord : NSObject + +- initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible; +- initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId; + +@property(nonatomic, readonly) NSInteger writeId; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id overwrite; +/** + * Maps NSString -> id + */ +@property(nonatomic, strong, readonly) FCompoundWrite *merge; +@property(nonatomic, readonly) BOOL visible; + +- (BOOL)isMerge; +- (BOOL)isOverwrite; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m new file mode 100644 index 0000000..be1816e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteRecord.m @@ -0,0 +1,139 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteRecord.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" + +@interface FWriteRecord () +@property(nonatomic, readwrite) NSInteger writeId; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong, readwrite) id overwrite; +@property(nonatomic, strong, readwrite) FCompoundWrite *merge; +@property(nonatomic, readwrite) BOOL visible; +@end + +@implementation FWriteRecord + +- (id)initWithPath:(FPath *)path + overwrite:(id)overwrite + writeId:(NSInteger)writeId + visible:(BOOL)isVisible { + self = [super init]; + if (self) { + self.path = path; + if (overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as overwrite parameter to an " + @"overwrite write record"]; + } + self.overwrite = overwrite; + self.merge = nil; + self.writeId = writeId; + self.visible = isVisible; + } + return self; +} + +- (id)initWithPath:(FPath *)path + merge:(FCompoundWrite *)merge + writeId:(NSInteger)writeId { + self = [super init]; + if (self) { + self.path = path; + if (merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't pass nil as merge parameter to an merge " + @"write record"]; + } + self.overwrite = nil; + self.merge = merge; + self.writeId = writeId; + self.visible = YES; + } + return self; +} + +- (id)overwrite { + if (self->_overwrite == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get overwrite for merge write record!"]; + } + return self->_overwrite; +} + +- (FCompoundWrite *)compoundWrite { + if (self->_merge == nil) { + [NSException raise:NSInvalidArgumentException + format:@"Can't get merge for overwrite write record!"]; + } + return self->_merge; +} + +- (BOOL)isMerge { + return self->_merge != nil; +} + +- (BOOL)isOverwrite { + return self->_overwrite != nil; +} + +- (NSString *)description { + if (self.isOverwrite) { + return + [NSString stringWithFormat:@"FWriteRecord { writeId = %lu, path = " + @"%@, overwrite = %@, visible = %d }", + (unsigned long)self.writeId, self.path, + self.overwrite, self.visible]; + } else { + return [NSString + stringWithFormat: + @"FWriteRecord { writeId = %lu, path = %@, merge = %@ }", + (unsigned long)self.writeId, self.path, self.merge]; + } +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[self class]]) { + return NO; + } + FWriteRecord *other = (FWriteRecord *)object; + if (self->_writeId != other->_writeId) + return NO; + if (self->_path != other->_path && ![self->_path isEqual:other->_path]) + return NO; + if (self->_overwrite != other->_overwrite && + ![self->_overwrite isEqual:other->_overwrite]) + return NO; + if (self->_merge != other->_merge && ![self->_merge isEqual:other->_merge]) + return NO; + if (self->_visible != other->_visible) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self->_writeId * 17; + hash = hash * 31 + self->_path.hash; + hash = hash * 31 + self->_overwrite.hash; + hash = hash * 31 + self->_merge.hash; + hash = hash * 31 + ((self->_visible) ? 1 : 0); + return hash; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h new file mode 100644 index 0000000..178946b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; +@protocol FNode; +@class FCompoundWrite; +@class FWriteTreeRef; +@class FChildrenNode; +@class FNamedNode; +@class FWriteRecord; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTree : NSObject + +- (FWriteTreeRef *)childWritesForPath:(FPath *)path; +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible; +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId; +- (BOOL)removeWriteId:(NSInteger)writeId; +- (NSArray *)removeAllWrites; +- (FWriteRecord *)writeForId:(NSInteger)writeId; + +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites; + +- (id)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap:(id)existingEventSnap + existingServerSnap:(id)existingServerSnap; + +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)path + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m new file mode 100644 index 0000000..d8592c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTree.m @@ -0,0 +1,577 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTree.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FImmutableTree.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTreeRef.h" + +@interface FWriteTree () +/** + * A tree tracking the results of applying all visible writes. This does not + * include transactions with applyLocally=false or writes that are completely + * shadowed by other writes. Contains id as values. + */ +@property(nonatomic, strong) FCompoundWrite *visibleWrites; +/** + * A list of pending writes, regardless of visibility and shadowed-ness. Used to + * calcuate arbitrary sets of the changed data, such as hidden writes (from + * transactions) or changes with certain writes excluded (also used by + * transactions). Contains FWriteRecords. + */ +@property(nonatomic, strong) NSMutableArray *allWrites; +@property(nonatomic) NSInteger lastWriteId; +@end + +/** + * FWriteTree tracks all pending user-initiated writes and has methods to + * calcuate the result of merging them with underlying server data (to create + * "event cache" data). Pending writes are added with addOverwriteAtPath: and + * addMergeAtPath: and removed with removeWriteId:. + */ +@implementation FWriteTree + +@synthesize allWrites; +@synthesize lastWriteId; + +- (id)init { + self = [super init]; + if (self) { + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [[NSMutableArray alloc] init]; + self.lastWriteId = -1; + } + return self; +} + +/** + * Create a new WriteTreeRef for the given path. For use with a new sync point + * at the given path. + */ +- (FWriteTreeRef *)childWritesForPath:(FPath *)path { + return [[FWriteTreeRef alloc] initWithPath:path writeTree:self]; +} + +/** + * Record a new overwrite from user code. + * @param visible Is set to false by some transactions. It should be excluded + * from event caches. + */ +- (void)addOverwriteAtPath:(FPath *)path + newData:(id)newData + writeId:(NSInteger)writeId + isVisible:(BOOL)visible { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older write on top of a newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + overwrite:newData + writeId:writeId + visible:visible]; + [self.allWrites addObject:record]; + + if (visible) { + self.visibleWrites = [self.visibleWrites addWrite:newData atPath:path]; + } + + self.lastWriteId = writeId; +} + +/** + * Record a new merge from user code. + * @param changedChildren maps NSString -> id + */ +- (void)addMergeAtPath:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writeId:(NSInteger)writeId { + NSAssert(writeId > self.lastWriteId, + @"Stacking an older merge on top of newer one"); + FWriteRecord *record = [[FWriteRecord alloc] initWithPath:path + merge:changedChildren + writeId:writeId]; + [self.allWrites addObject:record]; + + self.visibleWrites = [self.visibleWrites addCompoundWrite:changedChildren + atPath:path]; + self.lastWriteId = writeId; +} + +- (FWriteRecord *)writeForId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *write, NSUInteger idx, + BOOL *stop) { + return write.writeId == writeId; + }]; + return (index == NSNotFound) ? nil : self.allWrites[index]; +} + +/** + * Remove a write (either an overwrite or merge) that has been successfully + * acknowledged by the server. Recalculates the tree if necessary. We return the + * path of the write and whether it may have been visible, meaning views need to + * reevaluate. + * + * @return YES if the write may have been visible (meaning we'll need to + * reevaluate / raise events as a result). + */ +- (BOOL)removeWriteId:(NSInteger)writeId { + NSUInteger index = [self.allWrites + indexOfObjectPassingTest:^BOOL(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + if (record.writeId == writeId) { + return YES; + } else { + return NO; + } + }]; + NSAssert(index != NSNotFound, + @"[FWriteTree removeWriteId:] called with nonexistent writeId."); + FWriteRecord *writeToRemove = self.allWrites[index]; + [self.allWrites removeObjectAtIndex:index]; + + BOOL removedWriteWasVisible = writeToRemove.visible; + BOOL removedWriteOverlapsWithOtherWrites = NO; + NSInteger i = [self.allWrites count] - 1; + + while (removedWriteWasVisible && i >= 0) { + FWriteRecord *currentWrite = [self.allWrites objectAtIndex:i]; + if (currentWrite.visible) { + if (i >= index && [self record:currentWrite + containsPath:writeToRemove.path]) { + // The removed write was completely shadowed by a subsequent + // write. + removedWriteWasVisible = NO; + } else if ([writeToRemove.path contains:currentWrite.path]) { + // Either we're covering some writes or they're covering part of + // us (depending on which came first). + removedWriteOverlapsWithOtherWrites = YES; + } + } + i--; + } + + if (!removedWriteWasVisible) { + return NO; + } else if (removedWriteOverlapsWithOtherWrites) { + // There's some shadowing going on. Just rebuild the visible writes from + // scratch. + [self resetTree]; + return YES; + } else { + // There's no shadowing. We can safely just remove the write(s) from + // visibleWrites. + if ([writeToRemove isOverwrite]) { + self.visibleWrites = + [self.visibleWrites removeWriteAtPath:writeToRemove.path]; + } else { + FCompoundWrite *merge = writeToRemove.merge; + [merge enumerateWrites:^(FPath *path, id node, BOOL *stop) { + self.visibleWrites = [self.visibleWrites + removeWriteAtPath:[writeToRemove.path child:path]]; + }]; + } + return YES; + } +} + +- (NSArray *)removeAllWrites { + NSArray *writes = self.allWrites; + self.visibleWrites = [FCompoundWrite emptyWrite]; + self.allWrites = [NSMutableArray array]; + return writes; +} + +/** + * @return A complete snapshot for the given path if there's visible write data + * at that path, else nil. No server data is considered. + */ +- (id)completeWriteDataAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * Given optional, underlying server data, and an optional set of constraints + * (exclude some sets, include hidden writes), attempt to calculate a complete + * snapshot for the given path + * @param includeHiddenWrites Defaults to false, whether or not to layer on + * writes with visible set to false + */ +- (id)calculateCompleteEventCacheAtPath:(FPath *)treePath + completeServerCache:(id)completeServerCache + excludeWriteIds:(NSArray *)writeIdsToExclude + includeHiddenWrites:(BOOL)includeHiddenWrites { + if (writeIdsToExclude == nil && !includeHiddenWrites) { + id shadowingNode = + [self.visibleWrites completeNodeAtPath:treePath]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + // No cache here. Can't claim complete knowledge. + FCompoundWrite *subMerge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (subMerge.isEmpty) { + return completeServerCache; + } else if (completeServerCache == nil && + ![subMerge hasCompleteWriteAtPath:[FPath empty]]) { + // We wouldn't have a complete snapshot since there's no + // underlying data and no complete shadow + return nil; + } else { + id layeredCache = completeServerCache != nil + ? completeServerCache + : [FEmptyNode emptyNode]; + return [subMerge applyToNode:layeredCache]; + } + } + } else { + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + if (!includeHiddenWrites && merge.isEmpty) { + return completeServerCache; + } else { + // If the server cache is null and we don't have a complete cache, + // we need to return nil + if (!includeHiddenWrites && completeServerCache == nil && + ![merge hasCompleteWriteAtPath:[FPath empty]]) { + return nil; + } else { + BOOL (^filter)(FWriteRecord *) = ^(FWriteRecord *record) { + return (BOOL)( + (record.visible || includeHiddenWrites) && + (writeIdsToExclude == nil || + ![writeIdsToExclude + containsObject: + [NSNumber numberWithInteger:record.writeId]]) && + ([record.path contains:treePath] || + [treePath contains:record.path])); + }; + FCompoundWrite *mergeAtPath = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:filter + treeRoot:treePath]; + id layeredCache = completeServerCache + ? completeServerCache + : [FEmptyNode emptyNode]; + return [mergeAtPath applyToNode:layeredCache]; + } + } + } +} + +/** + * With optional, underlying server data, attempt to return a children node of + * children that we have complete data for. Used when creating new views, to + * pre-fill their complete event children snapshot. + */ +- (FChildrenNode *)calculateCompleteEventChildrenAtPath:(FPath *)treePath + completeServerChildren: + (id)completeServerChildren { + __block id completeChildren = [FEmptyNode emptyNode]; + id topLevelSet = [self.visibleWrites completeNodeAtPath:treePath]; + if (topLevelSet != nil) { + if (![topLevelSet isLeafNode]) { + // We're shadowing everything. Return the children. + FChildrenNode *topChildrenNode = topLevelSet; + [topChildrenNode enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + completeChildren = [completeChildren updateImmediateChild:key + withNewChild:node]; + }]; + } + return completeChildren; + } else { + // Layer any children we have on top of this + // We know we don't have a top-level set, so just enumerate existing + // children, and apply any updates + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + [completeServerChildren enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FCompoundWrite *childMerge = + [merge childCompoundWriteAtPath:[[FPath alloc] initWith:key]]; + id newChildNode = [childMerge applyToNode:node]; + completeChildren = + [completeChildren updateImmediateChild:key + withNewChild:newChildNode]; + }]; + // Add any complete children we have from the set. + for (FNamedNode *node in merge.completeChildren) { + completeChildren = + [completeChildren updateImmediateChild:node.name + withNewChild:node.node]; + } + return completeChildren; + } +} + +/** + * Given that the underlying server data has updated, determine what, if + * anything, needs to be applied to the event cache. + * + * Possibilities + * + * 1. No write are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some write is completely shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events .. + * + * Either existingEventSnap or existingServerSnap must exist. + */ +- (id)calculateEventCacheAfterServerOverwriteAtPath:(FPath *)treePath + childPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + NSAssert(existingEventSnap != nil || existingServerSnap != nil, + @"Either existingEventSnap or existingServerSanp must exist."); + + FPath *path = [treePath child:childPath]; + if ([self.visibleWrites hasCompleteWriteAtPath:path]) { + // At this point we can probably guarantee that we're in case 2, meaning + // no events May need to check visibility while doing the + // findRootMostValueAndPath call + return nil; + } else { + // This could be more efficient if the serverNode + updates doesn't + // change the eventSnap However this is tricky to find out, since user + // updates don't necessary change the server snap, e.g. priority updates + // on empty nodes, or deep deletes. Another special case is if the + // server adds nodes, but doesn't change any existing writes. It is + // therefore not enough to only check if the updates change the + // serverNode. Maybe check if the merge tree contains these special + // cases and only do a full overwrite in that case? + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + if (childMerge.isEmpty) { + // We're not shadowing at all. Case 1 + return [existingServerSnap getChild:childPath]; + } else { + return [childMerge + applyToNode:[existingServerSnap getChild:childPath]]; + } + } +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChildAtPath:(FPath *)treePath + childKey:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + FPath *path = [treePath childFromString:childKey]; + id shadowingNode = [self.visibleWrites completeNodeAtPath:path]; + if (shadowingNode != nil) { + return shadowingNode; + } else { + if ([existingServerCache isCompleteForChild:childKey]) { + FCompoundWrite *childMerge = + [self.visibleWrites childCompoundWriteAtPath:path]; + return [childMerge applyToNode:[existingServerCache.node + getImmediateChild:childKey]]; + } else { + return nil; + } + } +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns null if + * there is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.visibleWrites completeNodeAtPath:path]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that were outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + atPath:(FPath *)treePath + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + __block id toIterate; + FCompoundWrite *merge = + [self.visibleWrites childCompoundWriteAtPath:treePath]; + id shadowingNode = [merge completeNodeAtPath:[FPath empty]]; + if (shadowingNode != nil) { + toIterate = shadowingNode; + } else if (completeServerData != nil) { + toIterate = [merge applyToNode:completeServerData]; + } else { + return nil; + } + + __block NSString *currentNextKey = nil; + __block id currentNextNode = nil; + [toIterate enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if ([index compareKey:key + andNode:node + toOtherKey:post.name + andNode:post.node + reverse:reverse] > NSOrderedSame && + (!currentNextKey || [index compareKey:key + andNode:node + toOtherKey:currentNextKey + andNode:currentNextNode + reverse:reverse] < NSOrderedSame)) { + currentNextKey = key; + currentNextNode = node; + } + }]; + + if (currentNextKey != nil) { + return [FNamedNode nodeWithName:currentNextKey node:currentNextNode]; + } else { + return nil; + } +} + +#pragma mark - +#pragma mark Private Methods + +- (BOOL)record:(FWriteRecord *)record containsPath:(FPath *)path { + if ([record isOverwrite]) { + return [record.path contains:path]; + } else { + __block BOOL contains = NO; + [record.merge + enumerateWrites:^(FPath *childPath, id node, BOOL *stop) { + contains = [[record.path child:childPath] contains:path]; + *stop = contains; + }]; + return contains; + } +} + +/** + * Re-layer the writes and merges into a tree so we can efficiently calculate + * event snapshots + */ +- (void)resetTree { + self.visibleWrites = + [FWriteTree layerTreeFromWrites:self.allWrites + filter:[FWriteTree defaultFilter] + treeRoot:[FPath empty]]; + if ([self.allWrites count] > 0) { + FWriteRecord *lastRecord = self.allWrites[[self.allWrites count] - 1]; + self.lastWriteId = lastRecord.writeId; + } else { + self.lastWriteId = -1; + } +} + +/** + * The default filter used when constructing the tree. Keep everything that's + * visible. + */ ++ (BOOL (^)(FWriteRecord *record))defaultFilter { + static BOOL (^filter)(FWriteRecord *); + static dispatch_once_t filterToken; + dispatch_once(&filterToken, ^{ + filter = ^(FWriteRecord *record) { + return YES; + }; + }); + return filter; +} + +/** + * Static method. Given an array of WriteRecords, a filter for which ones to + * include, and a path, construct a merge at that path + * @return An FImmutableTree of ids. + */ ++ (FCompoundWrite *)layerTreeFromWrites:(NSArray *)writes + filter:(BOOL (^)(FWriteRecord *record))filter + treeRoot:(FPath *)treeRoot { + __block FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + [writes enumerateObjectsUsingBlock:^(FWriteRecord *record, NSUInteger idx, + BOOL *stop) { + // Theory, a later set will either: + // a) abort a relevant transaction, so no need to worry about excluding it + // from calculating that transaction b) not be relevant to a transaction + // (separate branch), so again will not affect the data for that + // transaction + if (filter(record)) { + FPath *writePath = record.path; + if ([record isOverwrite]) { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addWrite:record.overwrite + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + id child = [record.overwrite + getChild:[FPath relativePathFrom:writePath to:treeRoot]]; + compoundWrite = [compoundWrite addWrite:child + atPath:[FPath empty]]; + } else { + // There is no overlap between root path and write path, + // ignore write + } + } else { + if ([treeRoot contains:writePath]) { + FPath *relativePath = [FPath relativePathFrom:treeRoot + to:writePath]; + compoundWrite = [compoundWrite addCompoundWrite:record.merge + atPath:relativePath]; + } else if ([writePath contains:treeRoot]) { + FPath *relativePath = [FPath relativePathFrom:writePath + to:treeRoot]; + if (relativePath.isEmpty) { + compoundWrite = + [compoundWrite addCompoundWrite:record.merge + atPath:[FPath empty]]; + } else { + id child = + [record.merge completeNodeAtPath:relativePath]; + if (child != nil) { + // There exists a child in this node that matches the + // root path + id deepNode = + [child getChild:[relativePath popFront]]; + compoundWrite = + [compoundWrite addWrite:deepNode + atPath:[FPath empty]]; + } + } + } else { + // There is no overlap between root path and write path, + // ignore write + } + } + } + }]; + return compoundWrite; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h new file mode 100644 index 0000000..962ad5c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FChildrenNode; +@class FPath; +@class FNamedNode; +@class FWriteRecord; +@class FWriteTree; +@protocol FIndex; +@class FCacheNode; + +@interface FWriteTreeRef : NSObject + +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree; + +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache; + +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (FChildrenNode *)completeServerChildren; + +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap; + +- (id)shadowingWriteAtPath:(FPath *)path; + +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index; + +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache; + +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m new file mode 100644 index 0000000..809d1a9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/FWriteTreeRef.m @@ -0,0 +1,159 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FWriteTreeRef.h" +#import "FCacheNode.h" +#import "FChildrenNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FWriteRecord.h" +#import "FWriteTree.h" + +@interface FWriteTreeRef () +/** + * The path to this particular FWriteTreeRef. Used for calling methods on + * writeTree while exposing a simpler interface to callers. + */ +@property(nonatomic, strong) FPath *path; +/** + * A reference to the actual tree of the write data. All methods are + * pass-through to the tree, but with the appropriate path prefixed. + * + * This lets us make cheap references to points in the tree for sync points + * without having to copy and maintain all of the data. + */ +@property(nonatomic, strong) FWriteTree *writeTree; +@end + +/** + * A FWriteTreeRef wraps a FWriteTree and a FPath, for convenient access to a + * particular subtree. All the methods just proxy to the underlying FWriteTree. + */ +@implementation FWriteTreeRef +- (id)initWithPath:(FPath *)aPath writeTree:(FWriteTree *)tree { + self = [super init]; + if (self) { + self.path = aPath; + self.writeTree = tree; + } + return self; +} + +/** + * @return If possible, returns a complete event cache, using the underlying + * server data if possible. In addition, can be used to get a cache that + * includes hidden writes, and excludes arbitrary writes. Note that customizing + * the returned node can lead to a more expensive calculation. + */ +- (id)calculateCompleteEventCacheWithCompleteServerCache: + (id)completeServerCache { + return [self.writeTree calculateCompleteEventCacheAtPath:self.path + completeServerCache:completeServerCache + excludeWriteIds:nil + includeHiddenWrites:NO]; +} + +/** + * @return If possible, returns a children node containing all of the complete + * children we have data for. The returned data is a mix of the given server + * data and write data. + */ +- (FChildrenNode *)calculateCompleteEventChildrenWithCompleteServerChildren: + (id)completeServerChildren { + return [self.writeTree + calculateCompleteEventChildrenAtPath:self.path + completeServerChildren:completeServerChildren]; +} + +/** + * Given that either the underlying server data has updated or the outstanding + * writes have been updating, determine what, if anything, needs to be applied + * to the event cache. + * + * Possibilities: + * + * 1. No writes are shadowing. Events should be raised, the snap to be applied + * comes from the server data. + * + * 2. Some writes are completly shadowing. No events to be raised. + * + * 3. Is partially shadowed. Events should be raised. + * + * Either existingEventSnap or existingServerSnap must exist, this is validated + * via an assert. + */ +- (id) + calculateEventCacheAfterServerOverwriteWithChildPath:(FPath *)childPath + existingEventSnap: + (id)existingEventSnap + existingServerSnap: + (id)existingServerSnap { + return [self.writeTree + calculateEventCacheAfterServerOverwriteAtPath:self.path + childPath:childPath + existingEventSnap:existingEventSnap + existingServerSnap:existingServerSnap]; +} + +/** + * Returns a node if there is a complete overwrite for this path. More + * specifically, if there is a write at a higher path, this will return the + * child of that write relative to the write and this path. Returns nil if there + * is no write at this path. + */ +- (id)shadowingWriteAtPath:(FPath *)path { + return [self.writeTree shadowingWriteAtPath:[self.path child:path]]; +} + +/** + * This method is used when processing child remove events on a query. If we + * can, we pull in children that are outside the window, but may now be in the + * window. + */ +- (FNamedNode *)calculateNextNodeAfterPost:(FNamedNode *)post + completeServerData:(id)completeServerData + reverse:(BOOL)reverse + index:(id)index { + return [self.writeTree calculateNextNodeAfterPost:post + atPath:self.path + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +/** + * Returns a complete child for a given server snap after applying all user + * writes or nil if there is no complete child for this child key. + */ +- (id)calculateCompleteChild:(NSString *)childKey + cache:(FCacheNode *)existingServerCache { + return [self.writeTree calculateCompleteChildAtPath:self.path + childKey:childKey + cache:existingServerCache]; +} + +/** + * @return a WriteTreeref for a child. + */ +- (FWriteTreeRef *)childWriteTreeRef:(NSString *)childKey { + return + [[FWriteTreeRef alloc] initWithPath:[self.path childFromString:childKey] + writeTree:self.writeTree]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h new file mode 100644 index 0000000..97a23bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FPath; +@class FOperationSource; +@class FImmutableTree; + +@interface FAckUserWrite : NSObject + +- initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)affectedTree + revert:(BOOL)shouldRevert; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +// A FImmutableTree, containing @YES for each affected path. Affected paths +// can't overlap. +@property(nonatomic, strong, readonly) FImmutableTree *affectedTree; +@property(nonatomic, readonly) BOOL revert; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m new file mode 100644 index 0000000..2a1f287 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FAckUserWrite.m @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAckUserWrite.h" +#import "FImmutableTree.h" +#import "FOperationSource.h" +#import "FPath.h" + +@implementation FAckUserWrite + +- (id)initWithPath:(FPath *)operationPath + affectedTree:(FImmutableTree *)tree + revert:(BOOL)shouldRevert { + self = [super init]; + if (self) { + self->_source = [FOperationSource userInstance]; + self->_type = FOperationTypeAckUserWrite; + self->_path = operationPath; + self->_affectedTree = tree; + self->_revert = shouldRevert; + } + return self; +} + +- (FAckUserWrite *)operationForChild:(NSString *)childKey { + if (![self.path isEmpty]) { + NSAssert([self.path.getFront isEqualToString:childKey], + @"operationForChild called for unrelated child."); + return [[FAckUserWrite alloc] initWithPath:[self.path popFront] + affectedTree:self.affectedTree + revert:self.revert]; + } else if (self.affectedTree.value != nil) { + NSAssert(self.affectedTree.children.isEmpty, + @"affectedTree should not have overlapping affected paths."); + // All child locations are affected as well; just return same operation. + return self; + } else { + FImmutableTree *childTree = + [self.affectedTree subtreeAtPath:[[FPath alloc] initWith:childKey]]; + return [[FAckUserWrite alloc] initWithPath:[FPath empty] + affectedTree:childTree + revert:self.revert]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat: + @"FAckUserWrite { path=%@, revert=%d, affectedTree=%@ }", + self.path, self.revert, self.affectedTree]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h new file mode 100644 index 0000000..56fbec9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@class FCompoundWrite; + +@interface FMerge : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)children; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) FCompoundWrite *children; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m new file mode 100644 index 0000000..c344755 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FMerge.m @@ -0,0 +1,85 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMerge.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" + +@interface FMerge () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) FCompoundWrite *children; +@end + +@implementation FMerge + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize children; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + children:(FCompoundWrite *)someChildren { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeMerge; + self.path = aPath; + self.children = someChildren; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + FCompoundWrite *childTree = [self.children + childCompoundWriteAtPath:[[FPath alloc] initWith:childKey]]; + if (childTree.isEmpty) { + return nil; + } else if (childTree.rootWrite != nil) { + // We have a snapshot for the child in question. This becomes an + // overwrite of the child. + return [[FOverwrite alloc] initWithSource:self.source + path:[FPath empty] + snap:childTree.rootWrite]; + } else { + // This is a merge at a deeper level + return [[FMerge alloc] initWithSource:self.source + path:[FPath empty] + children:childTree]; + } + } else { + NSAssert( + [self.path.getFront isEqualToString:childKey], + @"Can't get a merge for a child not on the path of the operation"); + return [[FMerge alloc] initWithSource:self.source + path:[self.path popFront] + children:self.children]; + } +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"FMerge { path=%@, soruce=%@ children=%@}", + self.path, self.source, self.children]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h new file mode 100644 index 0000000..41f6054 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FOperationSource; +@class FPath; + +typedef NS_ENUM(NSInteger, FOperationType) { + FOperationTypeOverwrite = 0, + FOperationTypeMerge = 1, + FOperationTypeAckUserWrite = 2, + FOperationTypeListenComplete = 3 +}; + +@protocol FOperation +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +- (id)operationForChild:(NSString *)childKey; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h new file mode 100644 index 0000000..747487b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQueryParams; + +@interface FOperationSource : NSObject + +@property(nonatomic, readonly) BOOL fromUser; +@property(nonatomic, readonly) BOOL fromServer; +@property(nonatomic, readonly) BOOL isTagged; +@property(nonatomic, strong, readonly) FQueryParams *queryParams; + +- initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)isTagged; + ++ (FOperationSource *)userInstance; ++ (FOperationSource *)serverInstance; ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m new file mode 100644 index 0000000..92e3db8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOperationSource.m @@ -0,0 +1,86 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" + +@interface FOperationSource () +@property(nonatomic, readwrite) BOOL fromUser; +@property(nonatomic, readwrite) BOOL fromServer; +@property(nonatomic, readwrite) BOOL isTagged; +@property(nonatomic, strong, readwrite) FQueryParams *queryParams; +@end + +@implementation FOperationSource + +@synthesize fromUser; +@synthesize fromServer; +@synthesize queryParams; + +- (id)initWithFromUser:(BOOL)isFromUser + fromServer:(BOOL)isFromServer + queryParams:(FQueryParams *)params + tagged:(BOOL)tagged { + self = [super init]; + if (self) { + self.fromUser = isFromUser; + self.fromServer = isFromServer; + self.queryParams = params; + self.isTagged = tagged; + } + return self; +} + ++ (FOperationSource *)userInstance { + static FOperationSource *user = nil; + static dispatch_once_t userToken; + dispatch_once(&userToken, ^{ + user = [[FOperationSource alloc] initWithFromUser:YES + fromServer:NO + queryParams:nil + tagged:NO]; + }); + return user; +} + ++ (FOperationSource *)serverInstance { + static FOperationSource *server = nil; + static dispatch_once_t serverToken; + dispatch_once(&serverToken, ^{ + server = [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:nil + tagged:NO]; + }); + return server; +} + ++ (FOperationSource *)forServerTaggedQuery:(FQueryParams *)params { + return [[FOperationSource alloc] initWithFromUser:NO + fromServer:YES + queryParams:params + tagged:YES]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FOperationSource { fromUser=%d, " + @"fromServer=%d, queryId=%@, tagged=%d }", + self.fromUser, self.fromServer, + self.queryParams, self.isTagged]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h new file mode 100644 index 0000000..7d738ac --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" + +@protocol FNode; + +@interface FOverwrite : NSObject + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, readonly) FOperationType type; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id snap; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m new file mode 100644 index 0000000..ad4daec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Operation/FOverwrite.m @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOverwrite.h" +#import "FNode.h" +#import "FOperationSource.h" + +@interface FOverwrite () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, readwrite) FOperationType type; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, strong) id snap; +@end + +@implementation FOverwrite + +@synthesize source; +@synthesize type; +@synthesize path; +@synthesize snap; + +- (id)initWithSource:(FOperationSource *)aSource + path:(FPath *)aPath + snap:(id)aSnap { + self = [super init]; + if (self) { + self.source = aSource; + self.type = FOperationTypeOverwrite; + self.path = aPath; + self.snap = aSnap; + } + return self; +} + +- (FOverwrite *)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FOverwrite alloc] + initWithSource:self.source + path:[FPath empty] + snap:[self.snap getImmediateChild:childKey]]; + } else { + return [[FOverwrite alloc] initWithSource:self.source + path:[self.path popFront] + snap:self.snap]; + } +} + +- (NSString *)description { + return [NSString + stringWithFormat:@"FOverwrite { path=%@, source=%@, snapshot=%@ }", + self.path, self.source, self.snap]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h new file mode 100644 index 0000000..a63d0d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRRetryHelper : NSObject + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor; + +- (void)retry:(void (^)(void))block; + +- (void)cancel; + +- (void)signalSuccess; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m new file mode 100644 index 0000000..ef24d12 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FIRRetryHelper.m @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRRetryHelper.h" +#import "FUtilities.h" +#import + +@interface FIRRetryHelperTask : NSObject + +@property(nonatomic, strong) void (^block)(void); + +@end + +@implementation FIRRetryHelperTask + +- (instancetype)initWithBlock:(void (^)(void))block { + self = [super init]; + if (self != nil) { + self->_block = [block copy]; + } + return self; +} + +- (BOOL)isCanceled { + return self.block == nil; +} + +- (void)cancel { + self.block = nil; +} + +- (void)execute { + if (self.block) { + self.block(); + } +} + +@end + +@interface FIRRetryHelper () + +@property(nonatomic, strong) dispatch_queue_t dispatchQueue; +@property(nonatomic) NSTimeInterval minRetryDelayAfterFailure; +@property(nonatomic) NSTimeInterval maxRetryDelay; +@property(nonatomic) double retryExponent; +@property(nonatomic) double jitterFactor; + +@property(nonatomic) BOOL lastWasSuccess; +@property(nonatomic) NSTimeInterval currentRetryDelay; + +@property(nonatomic, strong) FIRRetryHelperTask *scheduledRetry; + +@end + +@implementation FIRRetryHelper + +- (instancetype)initWithDispatchQueue:(dispatch_queue_t)dispatchQueue + minRetryDelayAfterFailure:(NSTimeInterval)minRetryDelayAfterFailure + maxRetryDelay:(NSTimeInterval)maxRetryDelay + retryExponent:(double)retryExponent + jitterFactor:(double)jitterFactor { + self = [super init]; + if (self != nil) { + self->_dispatchQueue = dispatchQueue; + self->_minRetryDelayAfterFailure = minRetryDelayAfterFailure; + self->_maxRetryDelay = maxRetryDelay; + self->_retryExponent = retryExponent; + self->_jitterFactor = jitterFactor; + self->_lastWasSuccess = YES; + } + return self; +} + +- (void)retry:(void (^)(void))block { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054001", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } + + NSTimeInterval delay; + if (self.lastWasSuccess) { + delay = 0; + } else { + if (self.currentRetryDelay == 0) { + self.currentRetryDelay = self.minRetryDelayAfterFailure; + } else { + NSTimeInterval newDelay = + (self.currentRetryDelay * self.retryExponent); + self.currentRetryDelay = MIN(newDelay, self.maxRetryDelay); + } + + delay = ((1 - self.jitterFactor) * self.currentRetryDelay) + + (self.jitterFactor * self.currentRetryDelay * + [FUtilities randomDouble]); + FFLog(@"I-RDB054002", @"Scheduling retry in %fs", delay); + } + self.lastWasSuccess = NO; + FIRRetryHelperTask *task = [[FIRRetryHelperTask alloc] initWithBlock:block]; + self.scheduledRetry = task; + dispatch_time_t popTime = + dispatch_time(DISPATCH_TIME_NOW, (long long)(delay * NSEC_PER_SEC)); + dispatch_after(popTime, self.dispatchQueue, ^{ + if (![task isCanceled]) { + self.scheduledRetry = nil; + [task execute]; + } + }); +} + +- (void)signalSuccess { + self.lastWasSuccess = YES; + self.currentRetryDelay = 0; +} + +- (void)cancel { + if (self.scheduledRetry != nil) { + FFLog(@"I-RDB054003", @"Canceling existing retry attempt"); + [self.scheduledRetry cancel]; + self.scheduledRetry = nil; + } else { + FFLog(@"I-RDB054004", @"No existing retry attempt to cancel"); + } + self.currentRetryDelay = 0; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h new file mode 100644 index 0000000..e6d4961 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FTuplePathValue.h" + +@interface FImmutableTree : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap; + ++ (FImmutableTree *)empty; +- (BOOL)isEmpty; + +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id))predicate; +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath; +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath; +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath; +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath; +- (id)valueAtPath:(FPath *)relativePath; +- (id)rootMostValueOnPath:(FPath *)path; +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate; +- (id)leafMostValueOnPath:(FPath *)path; +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate; +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate; +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath; +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block; +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block; +- (FPath *)forEachOnPath:(FPath *)path + whileBlock:(BOOL (^)(FPath *path, id value))block; +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block; +- (void)forEach:(void (^)(FPath *path, id value))block; +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block; + +@property(nonatomic, strong, readonly) id value; +@property(nonatomic, strong, readonly) FImmutableSortedDictionary *children; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m new file mode 100644 index 0000000..34e62ae --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FImmutableTree.m @@ -0,0 +1,486 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableTree.h" +#import "FImmutableSortedDictionary.h" +#import "FPath.h" +#import "FUtilities.h" + +@interface FImmutableTree () +@property(nonatomic, strong, readwrite) id value; +/** + * Maps NSString -> FImmutableTree, where is type of value. + */ +@property(nonatomic, strong, readwrite) FImmutableSortedDictionary *children; +@end + +@implementation FImmutableTree +@synthesize value; +@synthesize children; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.children = [FImmutableTree emptyChildren]; + } + return self; +} + +- (id)initWithValue:(id)aValue + children:(FImmutableSortedDictionary *)childrenMap { + self = [super init]; + if (self) { + self.value = aValue; + self.children = childrenMap; + } + return self; +} + ++ (FImmutableSortedDictionary *)emptyChildren { + static dispatch_once_t emptyChildrenToken; + static FImmutableSortedDictionary *emptyChildren; + dispatch_once(&emptyChildrenToken, ^{ + emptyChildren = [FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities stringComparator]]; + }); + return emptyChildren; +} + ++ (FImmutableTree *)empty { + static dispatch_once_t emptyImmutableTreeToken; + static FImmutableTree *emptyTree = nil; + dispatch_once(&emptyImmutableTreeToken, ^{ + emptyTree = [[FImmutableTree alloc] initWithValue:nil]; + }); + return emptyTree; +} + +- (BOOL)isEmpty { + return self.value == nil && [self.children isEmpty]; +} + +/** + * Given a path and a predicate, return the first node and the path to that node + * where the predicate returns true + * // TODO Do a perf test. If we're creating a bunch of FTuplePathValue objects + * on the way back out, it may be better to pass down a pathSoFar FPath + */ +- (FTuplePathValue *)findRootMostMatchingPath:(FPath *)relativePath + predicate:(BOOL (^)(id value))predicate { + if (self.value != nil && predicate(self.value)) { + return [[FTuplePathValue alloc] initWithPath:[FPath empty] + value:self.value]; + } else { + if ([relativePath isEmpty]) { + return nil; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child != nil) { + FTuplePathValue *childExistingPathAndValue = + [child findRootMostMatchingPath:[relativePath popFront] + predicate:predicate]; + if (childExistingPathAndValue != nil) { + FPath *fullPath = [[[FPath alloc] initWith:front] + child:childExistingPathAndValue.path]; + return [[FTuplePathValue alloc] + initWithPath:fullPath + value:childExistingPathAndValue.value]; + } else { + return nil; + } + } else { + // No child matching path + return nil; + } + } + } +} + +/** + * Find, if it exists, the shortest subpath of the given path that points a + * defined value in the tree + */ +- (FTuplePathValue *)findRootMostValueAndPath:(FPath *)relativePath { + return [self findRootMostMatchingPath:relativePath + predicate:^BOOL(__unsafe_unretained id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path { + return [self rootMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)rootMostValueOnPath:(FPath *)path matching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return self.value; + } else if (path.isEmpty) { + return nil; + } else { + return [[self.children get:path.getFront] + rootMostValueOnPath:[path popFront] + matching:predicate]; + } +} + +- (id)leafMostValueOnPath:(FPath *)path { + return [self leafMostValueOnPath:path + matching:^BOOL(id value) { + return YES; + }]; +} + +- (id)leafMostValueOnPath:(FPath *)relativePath + matching:(BOOL (^)(id))predicate { + __block id currentValue = self.value; + __block FImmutableTree *currentTree = self; + [relativePath enumerateComponentsUsingBlock:^(NSString *key, BOOL *stop) { + currentTree = [currentTree.children get:key]; + if (currentTree == nil) { + *stop = YES; + } else { + id treeValue = currentTree.value; + if (treeValue != nil && predicate(treeValue)) { + currentValue = treeValue; + } + } + }]; + return currentValue; +} + +- (BOOL)containsValueMatching:(BOOL (^)(id))predicate { + if (self.value != nil && predicate(self.value)) { + return YES; + } else { + __block BOOL found = NO; + [self.children enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *subtree, BOOL *stop) { + found = [subtree containsValueMatching:predicate]; + if (found) + *stop = YES; + }]; + return found; + } +} + +- (FImmutableTree *)subtreeAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *childTree = [self.children get:front]; + if (childTree != nil) { + return [childTree subtreeAtPath:[relativePath popFront]]; + } else { + return [FImmutableTree empty]; + } + } +} + +/** + * Sets a value at the specified path + */ +- (FImmutableTree *)setValue:(id)newValue atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return [[FImmutableTree alloc] initWithValue:newValue + children:self.children]; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setValue:newValue + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren = + [self.children insertKey:front withValue:newChild]; + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Remove the value at the specified path + */ +- (FImmutableTree *)removeValueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + if ([self.children isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:nil + children:self.children]; + } + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + FImmutableTree *newChild = + [child removeValueAtPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front + withValue:newChild]; + } + if (self.value == nil && [newChildren isEmpty]) { + return [FImmutableTree empty]; + } else { + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } + } else { + return self; + } + } +} + +/** + * Gets a value from the tree + */ +- (id)valueAtPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return self.value; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child) { + return [child valueAtPath:[relativePath popFront]]; + } else { + return nil; + } + } +} + +/** + * Replaces the subtree at the specified path with the given new tree + */ +- (FImmutableTree *)setTree:(FImmutableTree *)newTree + atPath:(FPath *)relativePath { + if ([relativePath isEmpty]) { + return newTree; + } else { + NSString *front = [relativePath getFront]; + FImmutableTree *child = [self.children get:front]; + if (child == nil) { + child = [FImmutableTree empty]; + } + FImmutableTree *newChild = [child setTree:newTree + atPath:[relativePath popFront]]; + FImmutableSortedDictionary *newChildren; + if ([newChild isEmpty]) { + newChildren = [self.children removeKey:front]; + } else { + newChildren = [self.children insertKey:front withValue:newChild]; + } + return [[FImmutableTree alloc] initWithValue:self.value + children:newChildren]; + } +} + +/** + * Performs a depth first fold on this tree. Transforms a tree into a single + * value, given a function that operates on the path to a node, an optional + * current value, and a map of the child names to folded subtrees + */ +- (id)foldWithBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + return [self foldWithPathSoFar:[FPath empty] withBlock:block]; +} + +/** + * Recursive helper for public facing foldWithBlock: method + */ +- (id)foldWithPathSoFar:(FPath *)pathSoFar + withBlock:(id (^)(FPath *path, id value, + NSDictionary *foldedChildren))block { + __block NSMutableDictionary *accum = [[NSMutableDictionary alloc] init]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + accum[childKey] = + [childTree foldWithPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + return block(pathSoFar, self.value, accum); +} + +/** + * Find the first matching value on the given path. Return the result of + * applying block to it. + */ +- (id)findOnPath:(FPath *)path + andApplyBlock:(id (^)(FPath *path, id value))block { + return [self findOnPath:path pathSoFar:[FPath empty] andApplyBlock:block]; +} + +- (id)findOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + andApplyBlock:(id (^)(FPath *path, id value))block { + id result = self.value ? block(pathSoFar, self.value) : nil; + if (result != nil) { + return result; + } else { + if ([pathToFollow isEmpty]) { + return nil; + } else { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild != nil) { + return [nextChild findOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + andApplyBlock:block]; + } else { + return nil; + } + } + } +} +/** + * Call the block on each value along the path for as long as that function + * returns true + * @return The path to the deepest location inspected + */ +- (FPath *)forEachOnPath:(FPath *)path whileBlock:(BOOL (^)(FPath *, id))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] whileBlock:block]; +} + +- (FPath *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + whileBlock:(BOOL (^)(FPath *, id))block { + if ([pathToFollow isEmpty]) { + if (self.value) { + block(pathSoFar, self.value); + } + return pathSoFar; + } else { + BOOL shouldContinue = YES; + if (self.value) { + shouldContinue = block(pathSoFar, self.value); + } + if (shouldContinue) { + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return + [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + whileBlock:block]; + } else { + return pathSoFar; + } + } else { + return pathSoFar; + } + } +} + +- (FImmutableTree *)forEachOnPath:(FPath *)path + performBlock:(void (^)(FPath *path, id value))block { + return [self forEachOnPath:path pathSoFar:[FPath empty] performBlock:block]; +} + +- (FImmutableTree *)forEachOnPath:(FPath *)pathToFollow + pathSoFar:(FPath *)pathSoFar + performBlock:(void (^)(FPath *path, id value))block { + if ([pathToFollow isEmpty]) { + return self; + } else { + if (self.value) { + block(pathSoFar, self.value); + } + NSString *front = [pathToFollow getFront]; + FImmutableTree *nextChild = [self.children get:front]; + if (nextChild) { + return [nextChild forEachOnPath:[pathToFollow popFront] + pathSoFar:[pathSoFar childFromString:front] + performBlock:block]; + } else { + return [FImmutableTree empty]; + } + } +} +/** + * Calls the given block for each node in the tree that has a value. Called in + * depth-first order + */ +- (void)forEach:(void (^)(FPath *path, id value))block { + [self forEachPathSoFar:[FPath empty] withBlock:block]; +} + +- (void)forEachPathSoFar:(FPath *)pathSoFar + withBlock:(void (^)(FPath *path, id value))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [childTree forEachPathSoFar:[pathSoFar childFromString:childKey] + withBlock:block]; + }]; + if (self.value) { + block(pathSoFar, self.value); + } +} + +- (void)forEachChild:(void (^)(NSString *childKey, id childValue))block { + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value) { + block(childKey, childTree.value); + } + }]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableTree class]]) { + return NO; + } + FImmutableTree *other = (FImmutableTree *)object; + return (self.value == other.value || [self.value isEqual:other.value]) && + [self.children isEqual:other.children]; +} + +- (NSUInteger)hash { + return self.children.hash * 31 + [self.value hash]; +} + +- (NSString *)description { + NSMutableString *string = [[NSMutableString alloc] init]; + [string appendString:@"FImmutableTree { value="]; + [string appendString:(self.value ? [self.value description] : @"")]; + [string appendString:@", children={"]; + [self.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + [string appendString:@" "]; + [string appendString:childKey]; + [string appendString:@"="]; + [string appendString:[childTree.value description]]; + }]; + [string appendString:@" } }"]; + return [NSString stringWithString:string]; +} + +- (NSString *)debugDescription { + return [self description]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h new file mode 100644 index 0000000..cfa86aa --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FPath : NSObject + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner; ++ (FPath *)empty; ++ (FPath *)pathWithString:(NSString *)string; + +- (id)initWith:(NSString *)path; +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum; + +- (id)copyWithZone:(NSZone *)zone; + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *key, + BOOL *stop))block; +- (NSString *)getFront; +- (NSUInteger)length; +- (FPath *)popFront; +- (NSString *)getBack; +- (NSString *)toString; +- (NSString *)toStringWithTrailingSlash; +- (NSString *)wireFormat; +- (FPath *)parent; +- (FPath *)child:(FPath *)childPathObj; +- (FPath *)childFromString:(NSString *)childPath; +- (BOOL)isEmpty; +- (BOOL)contains:(FPath *)other; +- (NSComparisonResult)compare:(FPath *)other; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m new file mode 100644 index 0000000..f655240 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FPath.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" + +#import "FUtilities.h" + +@interface FPath () + +@property(nonatomic, readwrite, assign) NSInteger pieceNum; +@property(nonatomic, strong) NSArray *pieces; + +@end + +@implementation FPath + +#pragma mark - +#pragma mark Initializers + ++ (FPath *)relativePathFrom:(FPath *)outer to:(FPath *)inner { + NSString *outerFront = [outer getFront]; + NSString *innerFront = [inner getFront]; + if (outerFront == nil) { + return inner; + } else if ([outerFront isEqualToString:innerFront]) { + return [self relativePathFrom:[outer popFront] to:[inner popFront]]; + } else { + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:[NSString + stringWithFormat: + @"innerPath (%@) is not within outerPath (%@)", + inner, outer] + userInfo:nil]; + } +} + ++ (FPath *)pathWithString:(NSString *)string { + return [[FPath alloc] initWith:string]; +} + +- (id)initWith:(NSString *)path { + self = [super init]; + if (self) { + NSArray *pathPieces = [path componentsSeparatedByString:@"/"]; + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + self.pieces = newPieces; + self.pieceNum = 0; + } + return self; +} + +- (id)initWithPieces:(NSArray *)somePieces andPieceNum:(NSInteger)aPieceNum { + self = [super init]; + if (self) { + self.pieceNum = aPieceNum; + self.pieces = somePieces; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // Immutable, so it's safe to return self + return self; +} + +- (NSString *)description { + return [self toString]; +} + +#pragma mark - +#pragma mark Public methods + +- (NSString *)getFront { + if (self.pieceNum >= self.pieces.count) { + return nil; + } + return [self.pieces objectAtIndex:self.pieceNum]; +} + +/** + * @return The number of segments in this path + */ +- (NSUInteger)length { + return self.pieces.count - self.pieceNum; +} + +- (FPath *)popFront { + NSInteger newPieceNum = self.pieceNum; + if (newPieceNum < self.pieces.count) { + newPieceNum++; + } + return [[FPath alloc] initWithPieces:self.pieces andPieceNum:newPieceNum]; +} + +- (NSString *)getBack { + if (self.pieceNum < self.pieces.count) { + return [self.pieces lastObject]; + } else { + return nil; + } +} + +- (NSString *)toString { + return [self toStringWithTrailingSlash:NO]; +} + +- (NSString *)toStringWithTrailingSlash { + return [self toStringWithTrailingSlash:YES]; +} + +- (NSString *)toStringWithTrailingSlash:(BOOL)trailingSlash { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [pathString appendString:@"/"]; + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + if ([pathString length] == 0) { + return @"/"; + } else { + if (trailingSlash) { + [pathString appendString:@"/"]; + } + return pathString; + } +} + +- (NSString *)wireFormat { + if ([self isEmpty]) { + return @"/"; + } else { + NSMutableString *pathString = [[NSMutableString alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + if (i > self.pieceNum) { + [pathString appendString:@"/"]; + } + [pathString appendString:[self.pieces objectAtIndex:i]]; + } + return pathString; + } +} + +- (FPath *)parent { + if (self.pieceNum >= self.pieces.count) { + return nil; + } else { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count - 1; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; + } +} + +- (FPath *)child:(FPath *)childPathObj { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + for (NSInteger i = childPathObj.pieceNum; i < childPathObj.pieces.count; + i++) { + [newPieces addObject:[childPathObj.pieces objectAtIndex:i]]; + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +- (FPath *)childFromString:(NSString *)childPath { + NSMutableArray *newPieces = [[NSMutableArray alloc] init]; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + [newPieces addObject:[self.pieces objectAtIndex:i]]; + } + + NSArray *pathPieces = [childPath componentsSeparatedByString:@"/"]; + for (unsigned int i = 0; i < pathPieces.count; i++) { + NSString *piece = [pathPieces objectAtIndex:i]; + if (piece.length > 0) { + [newPieces addObject:piece]; + } + } + + return [[FPath alloc] initWithPieces:newPieces andPieceNum:0]; +} + +/** + * @return True if there are no segments in this path + */ +- (BOOL)isEmpty { + return self.pieceNum >= self.pieces.count; +} + +/** + * @return Singleton to represent an empty path + */ ++ (FPath *)empty { + static dispatch_once_t oneEmptyPath; + static FPath *emptyPath; + dispatch_once(&oneEmptyPath, ^{ + emptyPath = [[FPath alloc] initWith:@""]; + }); + return emptyPath; +} + +- (BOOL)contains:(FPath *)other { + if (self.length > other.length) { + return NO; + } + + NSInteger i = self.pieceNum; + NSInteger j = other.pieceNum; + while (i < self.pieces.count) { + NSString *thisSeg = [self.pieces objectAtIndex:i]; + NSString *otherSeg = [other.pieces objectAtIndex:j]; + if (![thisSeg isEqualToString:otherSeg]) { + return NO; + } + ++i; + ++j; + } + return YES; +} + +- (void)enumerateComponentsUsingBlock:(void (^)(NSString *, BOOL *))block { + BOOL stop = NO; + for (NSInteger i = self.pieceNum; !stop && i < self.pieces.count; i++) { + block(self.pieces[i], &stop); + } +} + +- (NSComparisonResult)compare:(FPath *)other { + NSInteger myCount = self.pieces.count; + NSInteger otherCount = other.pieces.count; + for (NSInteger i = self.pieceNum, j = other.pieceNum; + i < myCount && j < otherCount; i++, j++) { + NSComparisonResult comparison = [FUtilities compareKey:self.pieces[i] + toKey:other.pieces[j]]; + if (comparison != NSOrderedSame) { + return comparison; + } + } + if (self.length < other.length) { + return NSOrderedAscending; + } else if (other.length < self.length) { + return NSOrderedDescending; + } else { + NSAssert(self.length == other.length, + @"Paths must be the same lengths"); + return NSOrderedSame; + } +} + +/** + * @return YES if paths are the same + */ +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (!other || ![other isKindOfClass:[self class]]) { + return NO; + } + FPath *otherPath = (FPath *)other; + if (self.length != otherPath.length) { + return NO; + } + for (NSUInteger i = self.pieceNum, j = otherPath.pieceNum; + i < self.pieces.count; i++, j++) { + if (![self.pieces[i] isEqualToString:otherPath.pieces[j]]) { + return NO; + } + } + return YES; +} + +- (NSUInteger)hash { + NSUInteger hashCode = 0; + for (NSInteger i = self.pieceNum; i < self.pieces.count; i++) { + hashCode = hashCode * 37 + [self.pieces[i] hash]; + } + return hashCode; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h new file mode 100644 index 0000000..d5c77ab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTreeNode.h" +#import + +@interface FTree : NSObject + +- (id)init; +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode; + +- (FTree *)subTree:(FPath *)path; +- (id)getValue; +- (void)setValue:(id)value; +- (void)clear; +- (BOOL)hasChildren; +- (BOOL)isEmpty; +- (void)forEachChildMutationSafe:(void (^)(FTree *))action; +- (void)forEachChild:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action; +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action; +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf; +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action; +- (BOOL)valueExistsAtOrAbove:(FPath *)path; +- (FPath *)path; +- (void)updateParents; +- (void)updateChild:(NSString *)childName withNode:(FTree *)child; + +@property(nonatomic, strong) NSString *name; +@property(nonatomic, strong) FTree *parent; +@property(nonatomic, strong) FTreeNode *node; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m new file mode 100644 index 0000000..209b59f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTree.m @@ -0,0 +1,193 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTree.h" +#import "FPath.h" +#import "FTreeNode.h" +#import "FUtilities.h" + +@implementation FTree + +@synthesize name; +@synthesize parent; +@synthesize node; + +- (id)init { + self = [super init]; + if (self) { + self.name = @""; + self.parent = nil; + self.node = [[FTreeNode alloc] init]; + } + return self; +} + +- (id)initWithName:(NSString *)aName + withParent:(FTree *)aParent + withNode:(FTreeNode *)aNode { + self = [super init]; + if (self) { + self.name = aName != nil ? aName : @""; + self.parent = aParent != nil ? aParent : nil; + self.node = aNode != nil ? aNode : [[FTreeNode alloc] init]; + } + return self; +} + +- (FTree *)subTree:(FPath *)path { + FTree *child = self; + NSString *next = [path getFront]; + while (next != nil) { + FTreeNode *childNode = child.node.children[next]; + if (childNode == nil) { + childNode = [[FTreeNode alloc] init]; + } + child = [[FTree alloc] initWithName:next + withParent:child + withNode:childNode]; + path = [path popFront]; + next = [path getFront]; + } + return child; +} + +- (id)getValue { + return self.node.value; +} + +- (void)setValue:(id)value { + self.node.value = value; + [self updateParents]; +} + +- (void)clear { + self.node.value = nil; + [self.node.children removeAllObjects]; + self.node.childCount = 0; + [self updateParents]; +} + +- (BOOL)hasChildren { + return self.node.childCount > 0; +} + +- (BOOL)isEmpty { + return [self getValue] == nil && ![self hasChildren]; +} + +- (void)forEachChild:(void (^)(FTree *))action { + for (NSString *key in self.node.children) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachChildMutationSafe:(void (^)(FTree *))action { + for (NSString *key in [self.node.children copy]) { + action([[FTree alloc] + initWithName:key + withParent:self + withNode:[self.node.children objectForKey:key]]); + } +} + +- (void)forEachDescendant:(void (^)(FTree *))action { + [self forEachDescendant:action includeSelf:NO childrenFirst:NO]; +} + +- (void)forEachDescendant:(void (^)(FTree *))action + includeSelf:(BOOL)incSelf + childrenFirst:(BOOL)childFirst { + if (incSelf && !childFirst) { + action(self); + } + + [self forEachChild:^(FTree *child) { + [child forEachDescendant:action includeSelf:YES childrenFirst:childFirst]; + }]; + + if (incSelf && childFirst) { + action(self); + } +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action { + return [self forEachAncestor:action includeSelf:NO]; +} + +- (BOOL)forEachAncestor:(BOOL (^)(FTree *))action includeSelf:(BOOL)incSelf { + FTree *aNode = (incSelf) ? self : self.parent; + while (aNode != nil) { + if (action(aNode)) { + return YES; + } + aNode = aNode.parent; + } + return NO; +} + +- (void)forEachImmediateDescendantWithValue:(void (^)(FTree *))action { + [self forEachChild:^(FTree *child) { + if ([child getValue] != nil) { + action(child); + } else { + [child forEachImmediateDescendantWithValue:action]; + } + }]; +} + +- (BOOL)valueExistsAtOrAbove:(FPath *)path { + FTreeNode *aNode = self.node; + while (aNode != nil) { + if (aNode.value != nil) { + return YES; + } + aNode = [aNode.children objectForKey:path.getFront]; + path = [path popFront]; + } + // XXX Check with Michael if this is correct; deviates from JS. + return NO; +} + +- (FPath *)path { + return [[FPath alloc] + initWith:(self.parent == nil) + ? self.name + : [NSString stringWithFormat:@"%@/%@", [self.parent path], + self.name]]; +} + +- (void)updateParents { + [self.parent updateChild:self.name withNode:self]; +} + +- (void)updateChild:(NSString *)childName withNode:(FTree *)child { + BOOL childEmpty = [child isEmpty]; + BOOL childExists = self.node.children[childName] != nil; + if (childEmpty && childExists) { + [self.node.children removeObjectForKey:childName]; + self.node.childCount = self.node.childCount - 1; + [self updateParents]; + } else if (!childEmpty && !childExists) { + [self.node.children setObject:child.node forKey:childName]; + self.node.childCount = self.node.childCount + 1; + [self updateParents]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h new file mode 100644 index 0000000..549f3b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTreeNode : NSObject + +@property(nonatomic, strong) NSMutableDictionary *children; +@property(nonatomic, readwrite, assign) int childCount; +@property(nonatomic, strong) id value; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m new file mode 100644 index 0000000..bae6c62 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/Utilities/FTreeNode.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTreeNode.h" + +@implementation FTreeNode + +@synthesize children; +@synthesize childCount; +@synthesize value; + +- (id)init { + self = [super init]; + if (self) { + self.children = [[NSMutableDictionary alloc] init]; + self.childCount = 0; + self.value = nil; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h new file mode 100644 index 0000000..eff0cb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@class FPath; + +/** + * A cache node only stores complete children. Additionally it holds a flag + * whether the node can be considered fully initialized in the sense that we + * know at one point in time, this represented a valid state of the world, e.g. + * initialized with data from the server, or a complete overwrite by the client. + * It is not necessarily complete because it may have been from a tagged query. + * The filtered flag also tracks whether a node potentially had children removed + * due to a filter. + */ +@interface FCacheNode : NSObject + +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered; + +- (BOOL)isCompleteForPath:(FPath *)path; +- (BOOL)isCompleteForChild:(NSString *)childKey; + +@property(nonatomic, readonly) BOOL isFullyInitialized; +@property(nonatomic, readonly) BOOL isFiltered; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) id node; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m new file mode 100644 index 0000000..a991d52 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCacheNode.m @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FPath.h" + +@interface FCacheNode () +@property(nonatomic, readwrite) BOOL isFullyInitialized; +@property(nonatomic, readwrite) BOOL isFiltered; +@property(nonatomic, strong, readwrite) FIndexedNode *indexedNode; +@end + +@implementation FCacheNode +- (id)initWithIndexedNode:(FIndexedNode *)indexedNode + isFullyInitialized:(BOOL)fullyInitialized + isFiltered:(BOOL)filtered { + self = [super init]; + if (self) { + self.indexedNode = indexedNode; + self.isFullyInitialized = fullyInitialized; + self.isFiltered = filtered; + } + return self; +} + +- (BOOL)isCompleteForPath:(FPath *)path { + if (path.isEmpty) { + return self.isFullyInitialized && !self.isFiltered; + } else { + NSString *childKey = [path getFront]; + return [self isCompleteForChild:childKey]; + } +} + +- (BOOL)isCompleteForChild:(NSString *)childKey { + return (self.isFullyInitialized && !self.isFiltered) || + [self.node hasChild:childKey]; +} + +- (id)node { + return self.indexedNode.node; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h new file mode 100644 index 0000000..dd58642 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import + +@protocol FEventRegistration; + +@interface FCancelEvent : NSObject + +- initWithEventRegistration:(id)eventRegistration + error:(NSError *)error + path:(FPath *)path; + +@property(nonatomic, strong, readonly) NSError *error; +@property(nonatomic, strong, readonly) FPath *path; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m new file mode 100644 index 0000000..b069a71 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FCancelEvent.m @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCancelEvent.h" +#import "FEventRegistration.h" +#import "FPath.h" + +@interface FCancelEvent () +@property(nonatomic, strong) id eventRegistration; +@property(nonatomic, strong, readwrite) NSError *error; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FCancelEvent + +@synthesize eventRegistration; +@synthesize error; +@synthesize path; + +- (id)initWithEventRegistration:(id)registration + error:(NSError *)anError + path:(FPath *)aPath { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.error = anError; + self.path = aPath; + } + return self; +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return YES; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@: cancel", self.path]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h new file mode 100644 index 0000000..101ec8f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import + +@interface FChange : NSObject + +@property(nonatomic, readonly) FIRDataEventType type; +@property(nonatomic, strong, readonly) FIndexedNode *indexedNode; +@property(nonatomic, strong, readonly) NSString *childKey; +@property(nonatomic, strong, readonly) NSString *prevKey; +@property(nonatomic, strong, readonly) FIndexedNode *oldIndexedNode; + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey; +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode; + +- (FChange *)changeWithPrevKey:(NSString *)prevKey; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m new file mode 100644 index 0000000..8ad1cfc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChange.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" + +@interface FChange () + +@property(nonatomic, strong, readwrite) NSString *prevKey; + +@end + +@implementation FChange + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode { + return [self initWithType:type + indexedNode:indexedNode + childKey:nil + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey { + return [self initWithType:type + indexedNode:indexedNode + childKey:childKey + oldIndexedNode:nil]; +} + +- (id)initWithType:(FIRDataEventType)type + indexedNode:(FIndexedNode *)indexedNode + childKey:(NSString *)childKey + oldIndexedNode:(FIndexedNode *)oldIndexedNode { + self = [super init]; + if (self != nil) { + self->_type = type; + self->_indexedNode = indexedNode; + self->_childKey = childKey; + self->_oldIndexedNode = oldIndexedNode; + } + return self; +} + +- (FChange *)changeWithPrevKey:(NSString *)prevKey { + FChange *newChange = [[FChange alloc] initWithType:self.type + indexedNode:self.indexedNode + childKey:self.childKey + oldIndexedNode:self.oldIndexedNode]; + newChange.prevKey = prevKey; + return newChange; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event: %d, data: %@", (int)self.type, + [self.indexedNode.node val]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h new file mode 100644 index 0000000..0b0c633 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.h @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FChildEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +/** + * Maps FIRDataEventType (as NSNumber) to fbt_void_datasnapshot_nsstring + */ +@property(nonatomic, copy, readonly) NSDictionary *callbacks; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m new file mode 100644 index 0000000..1b688c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FChildEventRegistration.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import + +@interface FChildEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) NSDictionary *callbacks; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FChildEventRegistration + +- (id)initWithRepo:(id)repo + handle:(FIRDatabaseHandle)fHandle + callbacks:(NSDictionary *)callbackBlocks + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callbacks = callbackBlocks; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return self.callbacks != nil && + [self.callbacks + objectForKey:[NSNumber numberWithInteger:eventType]] != nil; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[query.path childFromString:change.childKey]]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:change.type + eventRegistration:self + dataSnapshot:snapshot + prevName:change.prevKey]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB061001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callbacks != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB061002", @"Raising event callback (%ld) on %@", + (long)dataEvent.eventType, dataEvent.path); + fbt_void_datasnapshot_nsstring callback = [self.callbacks + objectForKey:[NSNumber numberWithInteger:dataEvent.eventType]]; + + if (callback != nil) { + dispatch_async(queue, ^{ + callback(dataEvent.snapshot, dataEvent.prevName); + }); + } + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h new file mode 100644 index 0000000..a0d28f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEvent.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabaseReference.h" +#import "FTupleUserCallback.h" +#import + +@protocol FEventRegistration; +@protocol FIndex; + +@interface FDataEvent : NSObject + +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot; +- initWithEventType:(FIRDataEventType)type + eventRegistration:(id)eventRegistration + dataSnapshot:(FIRDataSnapshot *)snapshot + prevName:(NSString *)prevName; + +@property(nonatomic, strong, readonly) id eventRegistration; +@property(nonatomic, strong, readonly) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readonly) NSString *prevName; +@property(nonatomic, readonly) FIRDataEventType eventType; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m new file mode 100644 index 0000000..886a21e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FDataEvent.m @@ -0,0 +1,83 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FDataEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndex.h" + +@interface FDataEvent () +@property(nonatomic, strong, readwrite) id + eventRegistration; +@property(nonatomic, strong, readwrite) FIRDataSnapshot *snapshot; +@property(nonatomic, strong, readwrite) NSString *prevName; +@property(nonatomic, readwrite) FIRDataEventType eventType; +@end + +@implementation FDataEvent + +@synthesize eventRegistration; +@synthesize snapshot; +@synthesize prevName; +@synthesize eventType; + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot { + return [self initWithEventType:type + eventRegistration:registration + dataSnapshot:dataSnapshot + prevName:nil]; +} + +- (id)initWithEventType:(FIRDataEventType)type + eventRegistration:(id)registration + dataSnapshot:(FIRDataSnapshot *)dataSnapshot + prevName:(NSString *)previousName { + self = [super init]; + if (self) { + self.eventRegistration = registration; + self.snapshot = dataSnapshot; + self.prevName = previousName; + self.eventType = type; + } + return self; +} + +- (FPath *)path { + // Used for logging, so delay calculation + FIRDatabaseReference *ref = self.snapshot.ref; + if (self.eventType == FIRDataEventTypeValue) { + return ref.path; + } else { + return ref.parent.path; + } +} + +- (void)fireEventOnQueue:(dispatch_queue_t)queue { + [self.eventRegistration fireEvent:self queue:queue]; +} + +- (BOOL)isCancelEvent { + return NO; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"event %d, data: %@", (int)eventType, + [snapshot value]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h new file mode 100644 index 0000000..cddcf73 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEvent.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import + +@class FPath; + +@protocol FEvent +- (FPath *)path; +- (void)fireEventOnQueue:(dispatch_queue_t)queue; +- (BOOL)isCancelEvent; +- (NSString *)description; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h new file mode 100644 index 0000000..c46bff5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" + +@class FPath; +@class FRepo; +@class FIRDatabaseConfig; + +/** + * Left as instance methods rather than class methods so that we could + * potentially callback on different queues for different repos. This is + * semi-parallel to JS's FEventQueue + */ +@interface FEventRaiser : NSObject + +- (id)initWithQueue:(dispatch_queue_t)queue; + +- (void)raiseEvents:(NSArray *)eventDataList; +- (void)raiseCallback:(fbt_void_void)callback; +- (void)raiseCallbacks:(NSArray *)callbackList; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m new file mode 100644 index 0000000..d745358 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRaiser.m @@ -0,0 +1,74 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRaiser.h" +#import "FDataEvent.h" +#import "FRepo.h" +#import "FRepoManager.h" +#import "FTupleUserCallback.h" +#import "FTypedefs.h" +#import "FUtilities.h" + +@interface FEventRaiser () + +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +/** + * This class exists for symmetry with other clients, but since events are + * async, we don't need to do the complicated stuff the JS client does to + * preserve event order. + */ +@implementation FEventRaiser + +- (id)init { + [NSException raise:NSInternalInconsistencyException + format:@"Can't use default constructor"]; + return nil; +} + +- (id)initWithQueue:(dispatch_queue_t)queue { + self = [super init]; + if (self != nil) { + self->_queue = queue; + } + return self; +} + +- (void)raiseEvents:(NSArray *)eventDataList { + for (id event in eventDataList) { + [event fireEventOnQueue:self.queue]; + } +} + +- (void)raiseCallback:(fbt_void_void)callback { + dispatch_async(self.queue, callback); +} + +- (void)raiseCallbacks:(NSArray *)callbackList { + for (fbt_void_void callback in callbackList) { + dispatch_async(self.queue, callback); + } +} + ++ (void)raiseCallbacks:(NSArray *)callbackList queue:(dispatch_queue_t)queue { + for (fbt_void_void callback in callbackList) { + dispatch_async(queue, callback); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h new file mode 100644 index 0000000..79a2eb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FEventRegistration.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChange.h" +#import "FIRDataEventType.h" +#import + +@protocol FEvent; +@class FDataEvent; +@class FCancelEvent; +@class FQuerySpec; + +@protocol FEventRegistration +- (BOOL)responseTo:(FIRDataEventType)eventType; +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query; +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue; +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path; +/** + * Used to figure out what event registration match the event registration that + * needs to be removed. + */ +- (BOOL)matches:(id)other; +@property(nonatomic, readonly) FIRDatabaseHandle handle; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h new file mode 100644 index 0000000..d4dca60 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FEventRegistration.h" + +/** + * A singleton event registration to mark a query as keep synced + */ +@interface FKeepSyncedEventRegistration : NSObject + ++ (FKeepSyncedEventRegistration *)instance; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m new file mode 100644 index 0000000..1821829 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FKeepSyncedEventRegistration.m @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeepSyncedEventRegistration.h" + +@interface FKeepSyncedEventRegistration () + +@end + +@implementation FKeepSyncedEventRegistration + ++ (FKeepSyncedEventRegistration *)instance { + static dispatch_once_t onceToken; + static FKeepSyncedEventRegistration *keepSynced; + dispatch_once(&onceToken, ^{ + keepSynced = [[FKeepSyncedEventRegistration alloc] init]; + }); + return keepSynced; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return NO; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never create event for FKeepSyncedEventRegistration"]; + return nil; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + [NSException + raise:NSInternalInconsistencyException + format:@"Should never raise event for FKeepSyncedEventRegistration"]; +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + // Don't create cancel events.... + return nil; +} + +- (FIRDatabaseHandle)handle { + // TODO[offline]: returning arbitray, can't return NSNotFound since that is + // used to match other event registrations We should really redo this to + // match on different kind of events (single observer, all observers, + // cancelled) rather than on a NSNotFound handle... + return NSNotFound - 1; +} + +- (BOOL)matches:(id)other { + // Only matches singleton instance + return self == other; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h new file mode 100644 index 0000000..819febe --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.h @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventRegistration.h" +#import "FTypedefs.h" +#import + +@class FRepo; + +@interface FValueEventRegistration : NSObject + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock; + +@property(nonatomic, copy, readonly) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readonly) fbt_void_nserror cancelCallback; +@property(nonatomic, readonly) FIRDatabaseHandle handle; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m new file mode 100644 index 0000000..ad9368b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FValueEventRegistration.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueEventRegistration.h" +#import "FCancelEvent.h" +#import "FDataEvent.h" +#import "FIRDataSnapshot_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import + +@interface FValueEventRegistration () +@property(nonatomic, strong) FRepo *repo; +@property(nonatomic, copy, readwrite) fbt_void_datasnapshot callback; +@property(nonatomic, copy, readwrite) fbt_void_nserror cancelCallback; +@property(nonatomic, readwrite) FIRDatabaseHandle handle; +@end + +@implementation FValueEventRegistration + +- (id)initWithRepo:(FRepo *)repo + handle:(FIRDatabaseHandle)fHandle + callback:(fbt_void_datasnapshot)callbackBlock + cancelCallback:(fbt_void_nserror)cancelCallbackBlock { + self = [super init]; + if (self) { + self.repo = repo; + self.handle = fHandle; + self.callback = callbackBlock; + self.cancelCallback = cancelCallbackBlock; + } + return self; +} + +- (BOOL)responseTo:(FIRDataEventType)eventType { + return eventType == FIRDataEventTypeValue; +} + +- (FDataEvent *)createEventFrom:(FChange *)change query:(FQuerySpec *)query { + FIRDatabaseReference *ref = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:query.path]; + FIRDataSnapshot *snapshot = + [[FIRDataSnapshot alloc] initWithRef:ref + indexedNode:change.indexedNode]; + FDataEvent *eventData = + [[FDataEvent alloc] initWithEventType:FIRDataEventTypeValue + eventRegistration:self + dataSnapshot:snapshot]; + return eventData; +} + +- (void)fireEvent:(id)event queue:(dispatch_queue_t)queue { + if ([event isCancelEvent]) { + FCancelEvent *cancelEvent = event; + FFLog(@"I-RDB065001", @"Raising cancel value event on %@", event.path); + NSAssert( + self.cancelCallback != nil, + @"Raising a cancel event on a listener with no cancel callback"); + dispatch_async(queue, ^{ + self.cancelCallback(cancelEvent.error); + }); + } else if (self.callback != nil) { + FDataEvent *dataEvent = event; + FFLog(@"I-RDB065002", @"Raising value event on %@", + dataEvent.snapshot.key); + dispatch_async(queue, ^{ + self.callback(dataEvent.snapshot); + }); + } +} + +- (FCancelEvent *)createCancelEventFromError:(NSError *)error + path:(FPath *)path { + if (self.cancelCallback != nil) { + return [[FCancelEvent alloc] initWithEventRegistration:self + error:error + path:path]; + } else { + return nil; + } +} + +- (BOOL)matches:(id)other { + return self.handle == NSNotFound || other.handle == NSNotFound || + self.handle == other.handle; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h new file mode 100644 index 0000000..0b4b9d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@protocol FOperation; +@protocol FEventRegistration; +@class FWriteTreeRef; +@class FQuerySpec; +@class FChange; +@class FPath; +@class FViewCache; + +@interface FViewOperationResult : NSObject + +@property(nonatomic, strong, readonly) NSArray *changes; +@property(nonatomic, strong, readonly) NSArray *events; + +@end + +@interface FView : NSObject + +@property(nonatomic, strong, readonly) FQuerySpec *query; + +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache; + +- (id)eventCache; +- (id)serverCache; +- (id)completeServerCacheFor:(FPath *)path; +- (BOOL)isEmpty; + +- (void)addEventRegistration:(id)eventRegistration; +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError; + +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache; +- (NSArray *)initialEvents:(id)registration; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m new file mode 100644 index 0000000..a15e13d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FView.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FView.h" +#import "FCacheNode.h" +#import "FCancelEvent.h" +#import "FEmptyNode.h" +#import "FEventGenerator.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNode.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FPath.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" +#import "FViewCache.h" +#import "FViewProcessor.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +@interface FViewOperationResult () + +@property(nonatomic, strong, readwrite) NSArray *changes; +@property(nonatomic, strong, readwrite) NSArray *events; + +@end + +@implementation FViewOperationResult + +- (id)initWithChanges:(NSArray *)changes events:(NSArray *)events { + self = [super init]; + if (self != nil) { + self->_changes = changes; + self->_events = events; + } + return self; +} + +@end + +/** + * A view represents a specific location and query that has 1 or more event + * registrations. + * + * It does several things: + * - Maintains the list of event registration for this location/query. + * - Maintains a cache of the data visible for this location/query. + * - Applies new operations (via applyOperation), updates the cache, and based + * on the event registrations returns the set of events to be raised. + */ +@interface FView () + +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, strong) FViewProcessor *processor; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) NSMutableArray *eventRegistrations; +@property(nonatomic, strong) FEventGenerator *eventGenerator; + +@end + +@implementation FView +- (id)initWithQuery:(FQuerySpec *)query + initialViewCache:(FViewCache *)initialViewCache { + self = [super init]; + if (self) { + self.query = query; + + FIndexedFilter *indexFilter = + [[FIndexedFilter alloc] initWithIndex:query.index]; + id filter = query.params.nodeFilter; + self.processor = [[FViewProcessor alloc] initWithFilter:filter]; + FCacheNode *initialServerCache = initialViewCache.cachedServerSnap; + FCacheNode *initialEventCache = initialViewCache.cachedEventSnap; + + // Don't filter server node with other filter than index, wait for + // tagged listen + FIndexedNode *emptyIndexedNode = + [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:query.index]; + FIndexedNode *serverSnap = + [indexFilter updateFullNode:emptyIndexedNode + withNewNode:initialServerCache.indexedNode + accumulator:nil]; + FIndexedNode *eventSnap = + [filter updateFullNode:emptyIndexedNode + withNewNode:initialEventCache.indexedNode + accumulator:nil]; + FCacheNode *newServerCache = [[FCacheNode alloc] + initWithIndexedNode:serverSnap + isFullyInitialized:initialServerCache.isFullyInitialized + isFiltered:indexFilter.filtersNodes]; + FCacheNode *newEventCache = [[FCacheNode alloc] + initWithIndexedNode:eventSnap + isFullyInitialized:initialEventCache.isFullyInitialized + isFiltered:filter.filtersNodes]; + + self.viewCache = [[FViewCache alloc] initWithEventCache:newEventCache + serverCache:newServerCache]; + + self.eventRegistrations = [[NSMutableArray alloc] init]; + + self.eventGenerator = [[FEventGenerator alloc] initWithQuery:query]; + } + + return self; +} + +- (id)serverCache { + return self.viewCache.cachedServerSnap.node; +} + +- (id)eventCache { + return self.viewCache.cachedEventSnap.node; +} + +- (id)completeServerCacheFor:(FPath *)path { + id cache = self.viewCache.completeServerSnap; + if (cache) { + // If this isn't a "loadsAllData" view, then cache isn't actually a + // complete cache and we need to see if it contains the child we're + // interested in. + if ([self.query loadsAllData] || + (!path.isEmpty && + ![cache getImmediateChild:path.getFront].isEmpty)) { + return [cache getChild:path]; + } + } + return nil; +} + +- (BOOL)isEmpty { + return self.eventRegistrations.count == 0; +} + +- (void)addEventRegistration:(id)eventRegistration { + [self.eventRegistrations addObject:eventRegistration]; +} + +/** + * @param eventRegistration If null, remove all callbacks. + * @param cancelError If a cancelError is provided, appropriate cancel events + * will be returned. + * @return Cancel events, if cancelError was provided. + */ +- (NSArray *)removeEventRegistration:(id)eventRegistration + cancelError:(NSError *)cancelError { + NSMutableArray *cancelEvents = [[NSMutableArray alloc] init]; + if (cancelError != nil) { + NSAssert(eventRegistration == nil, + @"A cancel should cancel all event registrations."); + FPath *path = self.query.path; + for (id registration in self.eventRegistrations) { + FCancelEvent *maybeEvent = + [registration createCancelEventFromError:cancelError path:path]; + if (maybeEvent) { + [cancelEvents addObject:maybeEvent]; + } + } + } + + if (eventRegistration) { + NSUInteger i = 0; + while (i < self.eventRegistrations.count) { + id existing = self.eventRegistrations[i]; + if ([existing matches:eventRegistration]) { + [self.eventRegistrations removeObjectAtIndex:i]; + } else { + i++; + } + } + } else { + [self.eventRegistrations removeAllObjects]; + } + return cancelEvents; +} + +/** + * Applies the given Operation, updates our cache, and returns the appropriate + * events and changes + */ +- (FViewOperationResult *)applyOperation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)optCompleteServerCache { + if (operation.type == FOperationTypeMerge && + operation.source.queryParams != nil) { + NSAssert(self.viewCache.completeServerSnap != nil, + @"We should always have a full cache before handling merges"); + NSAssert(self.viewCache.completeEventSnap != nil, + @"Missing event cache, even though we have a server cache"); + } + FViewCache *oldViewCache = self.viewCache; + FViewProcessorResult *result = + [self.processor applyOperationOn:oldViewCache + operation:operation + writesCache:writesCache + completeCache:optCompleteServerCache]; + + NSAssert(result.viewCache.cachedServerSnap.isFullyInitialized || + !oldViewCache.cachedServerSnap.isFullyInitialized, + @"Once a server snap is complete, it should never go back."); + + self.viewCache = result.viewCache; + NSArray *events = [self + generateEventsForChanges:result.changes + eventCache:result.viewCache.cachedEventSnap.indexedNode + registration:nil]; + return [[FViewOperationResult alloc] initWithChanges:result.changes + events:events]; +} + +- (NSArray *)initialEvents:(id)registration { + FCacheNode *eventSnap = self.viewCache.cachedEventSnap; + NSMutableArray *initialChanges = [[NSMutableArray alloc] init]; + [eventSnap.indexedNode.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FIndexedNode *indexed = [FIndexedNode indexedNodeWithNode:node]; + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:indexed + childKey:key]; + [initialChanges addObject:change]; + }]; + if (eventSnap.isFullyInitialized) { + FChange *change = [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + [initialChanges addObject:change]; + } + return [self generateEventsForChanges:initialChanges + eventCache:eventSnap.indexedNode + registration:registration]; +} + +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + registration:(id)registration { + NSArray *registrations; + if (registration == nil) { + registrations = [[NSArray alloc] initWithArray:self.eventRegistrations]; + } else { + registrations = [[NSArray alloc] initWithObjects:registration, nil]; + } + return [self.eventGenerator generateEventsForChanges:changes + eventCache:eventCache + eventRegistrations:registrations]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FView (%@)", self.query]; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h new file mode 100644 index 0000000..62618d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.h @@ -0,0 +1,40 @@ +#/* +* Copyright 2017 Google +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#import + +@protocol FNode; +@class FCacheNode; +@class FIndexedNode; + +@interface FViewCache : NSObject + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache; + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered; + +@property(nonatomic, strong, readonly) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readonly) id completeEventSnap; +@property(nonatomic, strong, readonly) FCacheNode *cachedServerSnap; +@property(nonatomic, strong, readonly) id completeServerSnap; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m new file mode 100644 index 0000000..13e9283 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/FViewCache.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewCache.h" +#import "FCacheNode.h" +#import "FEmptyNode.h" +#import "FNode.h" + +@interface FViewCache () +@property(nonatomic, strong, readwrite) FCacheNode *cachedEventSnap; +@property(nonatomic, strong, readwrite) FCacheNode *cachedServerSnap; +@end + +@implementation FViewCache + +- (id)initWithEventCache:(FCacheNode *)eventCache + serverCache:(FCacheNode *)serverCache { + self = [super init]; + if (self) { + self.cachedEventSnap = eventCache; + self.cachedServerSnap = serverCache; + } + return self; +} + +- (FViewCache *)updateEventSnap:(FIndexedNode *)eventSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedEventCache = + [[FCacheNode alloc] initWithIndexedNode:eventSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:updatedEventCache + serverCache:self.cachedServerSnap]; +} + +- (FViewCache *)updateServerSnap:(FIndexedNode *)serverSnap + isComplete:(BOOL)complete + isFiltered:(BOOL)filtered { + FCacheNode *updatedServerCache = + [[FCacheNode alloc] initWithIndexedNode:serverSnap + isFullyInitialized:complete + isFiltered:filtered]; + return [[FViewCache alloc] initWithEventCache:self.cachedEventSnap + serverCache:updatedServerCache]; +} + +- (id)completeEventSnap { + return (self.cachedEventSnap.isFullyInitialized) ? self.cachedEventSnap.node + : nil; +} + +- (id)completeServerSnap { + return (self.cachedServerSnap.isFullyInitialized) + ? self.cachedServerSnap.node + : nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h new file mode 100644 index 0000000..bf25163 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FChange; + +@interface FChildChangeAccumulator : NSObject + +- (id)init; +- (void)trackChildChange:(FChange *)change; +- (NSArray *)changes; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m new file mode 100644 index 0000000..e35c2e2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m @@ -0,0 +1,99 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildChangeAccumulator.h" +#import "FChange.h" +#import "FIndex.h" + +@interface FChildChangeAccumulator () +@property(nonatomic, strong) NSMutableDictionary *changeMap; +@end + +@implementation FChildChangeAccumulator + +- (id)init { + self = [super init]; + if (self) { + self.changeMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)trackChildChange:(FChange *)change { + FIRDataEventType type = change.type; + NSString *childKey = change.childKey; + NSAssert(type == FIRDataEventTypeChildAdded || + type == FIRDataEventTypeChildChanged || + type == FIRDataEventTypeChildRemoved, + @"Only child changes supported for tracking."); + NSAssert(![change.childKey isEqualToString:@".priority"], + @"Changes not tracked on priority"); + if (self.changeMap[childKey] != nil) { + FChange *oldChange = [self.changeMap objectForKey:childKey]; + FIRDataEventType oldType = oldChange.type; + if (type == FIRDataEventTypeChildAdded && + oldType == FIRDataEventTypeChildRemoved) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.indexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildAdded) { + [self.changeMap removeObjectForKey:childKey]; + } else if (type == FIRDataEventTypeChildRemoved && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildRemoved + indexedNode:oldChange.oldIndexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildAdded) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildAdded + indexedNode:change.indexedNode + childKey:childKey]; + [self.changeMap setObject:newChange forKey:childKey]; + } else if (type == FIRDataEventTypeChildChanged && + oldType == FIRDataEventTypeChildChanged) { + FChange *newChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildChanged + indexedNode:change.indexedNode + childKey:childKey + oldIndexedNode:oldChange.oldIndexedNode]; + [self.changeMap setObject:newChange forKey:childKey]; + } else { + NSString *reason = [NSString + stringWithFormat: + @"Illegal combination of changes: %@ occurred after %@", + change, oldChange]; + @throw [[NSException alloc] + initWithName:@"FirebaseDatabaseInternalError" + reason:reason + userInfo:nil]; + } + } else { + [self.changeMap setObject:change forKey:childKey]; + } +} + +- (NSArray *)changes { + return [self.changeMap allValues]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h new file mode 100644 index 0000000..0c04bc1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FCompleteChildSource.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FNamedNode; +@protocol FIndex; + +@protocol FCompleteChildSource + +- (id)completeChild:(NSString *)childKey; +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h new file mode 100644 index 0000000..291e79a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@protocol FIndex; + +@interface FIndexedFilter : NSObject + +- (id)initWithIndex:(id)theIndex; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m new file mode 100644 index 0000000..f49af79 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FIndexedFilter.m @@ -0,0 +1,164 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FIndexedNode.h" +#import "FKeyIndex.h" +#import "FNode.h" + +@interface FIndexedFilter () +@property(nonatomic, strong, readwrite) id index; +@end + +@implementation FIndexedFilter +- (id)initWithIndex:(id)theIndex { + self = [super init]; + if (self) { + self.index = theIndex; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)indexedNode + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert([indexedNode hasIndex:self.index], + @"The index in FIndexedNode must match the index of the filter"); + id node = indexedNode.node; + id oldChildSnap = [node getImmediateChild:childKey]; + + // Check if anything actually changed. + if ([[oldChildSnap getChild:affectedPath] + isEqual:[newChildSnap getChild:affectedPath]]) { + // There's an edge case where a child can enter or leave the view + // because affectedPath was set to null. In this case, affectedPath will + // appear null in both the old and new snapshots. So we need to avoid + // treating these cases as "nothing changed." + if (oldChildSnap.isEmpty == newChildSnap.isEmpty) { +// Nothing changed. +#ifdef DEBUG + NSAssert([oldChildSnap isEqual:newChildSnap], + @"Old and new snapshots should be equal."); +#endif + + return indexedNode; + } + } + if (optChangeAccumulator) { + if (newChildSnap.isEmpty) { + if ([node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + NSAssert(node.isLeafNode, + @"A child remove without an old child only makes " + @"sense on a leaf node."); + } + } else if (oldChildSnap.isEmpty) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } + if (node.isLeafNode && newChildSnap.isEmpty) { + return indexedNode; + } else { + return [indexedNode updateChild:childKey withNewChild:newChildSnap]; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (optChangeAccumulator) { + [oldSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if (![newSnap.node hasChild:childKey]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *childKey, id childNode, BOOL *stop) { + if ([oldSnap.node hasChild:childKey]) { + id oldChildSnap = + [oldSnap.node getImmediateChild:childKey]; + if (![oldChildSnap isEqual:childNode]) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:childNode] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + } else { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:childNode] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + }]; + } + return newSnap; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + if ([oldSnap.node isEmpty]) { + return oldSnap; + } else { + return [oldSnap updatePriority:priority]; + } +} + +- (BOOL)filtersNodes { + return NO; +} + +- (id)indexedFilter { + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h new file mode 100644 index 0000000..0642e72 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; + +@interface FLimitedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m new file mode 100644 index 0000000..fab9aab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FLimitedFilter.m @@ -0,0 +1,285 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLimitedFilter.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FNamedNode.h" +#import "FQueryParams.h" +#import "FRangedFilter.h" +#import "FTreeSortedDictionary.h" + +@interface FLimitedFilter () +@property(nonatomic, strong) FRangedFilter *rangedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic) NSInteger limit; +@property(nonatomic) BOOL reverse; + +@end + +@implementation FLimitedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.rangedFilter = [[FRangedFilter alloc] initWithQueryParams:params]; + self.index = params.index; + self.limit = params.limit; + self.reverse = !params.isViewFromLeft; + } + return self; +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self.rangedFilter matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + if ([[oldSnap.node getImmediateChild:childKey] isEqual:newChildSnap]) { + // No change + return oldSnap; + } else if (oldSnap.node.numChildren < self.limit) { + return [[self.rangedFilter indexedFilter] + updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; + } else { + return [self fullLimitUpdateNode:oldSnap + forChildKey:childKey + newChild:newChildSnap + fromSource:source + accumulator:optChangeAccumulator]; + } +} + +- (FIndexedNode *)fullLimitUpdateNode:(FIndexedNode *)oldIndexed + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + NSAssert(oldIndexed.node.numChildren == self.limit, + @"Should have number of children equal to limit."); + + FNamedNode *windowBoundary = + self.reverse ? oldIndexed.firstChild : oldIndexed.lastChild; + + BOOL inRange = [self.rangedFilter matchesKey:childKey andNode:newChildSnap]; + if ([oldIndexed.node hasChild:childKey]) { + // `childKey` was already in `oldSnap`. Figure out if it remains in the + // window or needs to be replaced. + id oldChildSnap = [oldIndexed.node getImmediateChild:childKey]; + + // In case the `newChildSnap` falls outside the window, get the + // `nextChild` that might replace it. + FNamedNode *nextChild = [source childByIndex:self.index + afterChild:windowBoundary + isReverse:(BOOL)self.reverse]; + if (nextChild != nil && ([nextChild.name isEqualToString:childKey] || + [oldIndexed.node hasChild:nextChild.name])) { + // There is a weird edge case where a node is updated as part of a + // merge in the write tree, but hasn't been applied to the limited + // filter yet. Ignore this next child which will be updated later in + // the limited filter... + nextChild = [source childByIndex:self.index + afterChild:nextChild + isReverse:self.reverse]; + } + + // Figure out if `newChildSnap` is in range and ordered before + // `nextChild` + BOOL remainsInWindow = inRange && !newChildSnap.isEmpty; + remainsInWindow = remainsInWindow && + (!nextChild || [self.index compareKey:nextChild.name + andNode:nextChild.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= + NSOrderedSame); + if (remainsInWindow) { + // `newChildSnap` is ordered before `nextChild`, so it's a child + // changed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildChanged + indexedNode:[FIndexedNode + indexedNodeWithNode:newChildSnap] + childKey:childKey + oldIndexedNode:[FIndexedNode + indexedNodeWithNode:oldChildSnap]]; + [optChangeAccumulator trackChildChange:change]; + } + return [oldIndexed updateChild:childKey withNewChild:newChildSnap]; + } else { + // `newChildSnap` is ordered after `nextChild`, so it's a child + // removed event + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode indexedNodeWithNode:oldChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:change]; + } + FIndexedNode *newIndexed = + [oldIndexed updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + + // We need to check if the `nextChild` is actually in range before + // adding it + BOOL nextChildInRange = + (nextChild != nil) && + [self.rangedFilter matchesKey:nextChild.name + andNode:nextChild.node]; + if (nextChildInRange) { + if (optChangeAccumulator != nil) { + FChange *change = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode + indexedNodeWithNode:nextChild.node] + childKey:nextChild.name]; + [optChangeAccumulator trackChildChange:change]; + } + return [newIndexed updateChild:nextChild.name + withNewChild:nextChild.node]; + } else { + return newIndexed; + } + } + } else if (newChildSnap.isEmpty) { + // We're deleting a node, but it was not in the window, so ignore it. + return oldIndexed; + } else if (inRange) { + // `newChildSnap` is in range, but was ordered after `windowBoundary`. + // If this has changed, we bump out the `windowBoundary` and add the + // `newChildSnap` + if ([self.index compareKey:windowBoundary.name + andNode:windowBoundary.node + toOtherKey:childKey + andNode:newChildSnap + reverse:self.reverse] >= NSOrderedSame) { + if (optChangeAccumulator != nil) { + FChange *removedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildRemoved + indexedNode:[FIndexedNode + indexedNodeWithNode:windowBoundary.node] + childKey:windowBoundary.name]; + FChange *addedChange = [[FChange alloc] + initWithType:FIRDataEventTypeChildAdded + indexedNode:[FIndexedNode indexedNodeWithNode:newChildSnap] + childKey:childKey]; + [optChangeAccumulator trackChildChange:removedChange]; + [optChangeAccumulator trackChildChange:addedChange]; + } + return [[oldIndexed updateChild:childKey withNewChild:newChildSnap] + updateChild:windowBoundary.name + withNewChild:[FEmptyNode emptyNode]]; + } else { + return oldIndexed; + } + } else { + // `newChildSnap` was not in range and remains not in range, so ignore + // it. + return oldIndexed; + } +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode || newSnap.node.isEmpty) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + filtered = newSnap; + // Don't support priorities on queries. + filtered = [filtered updatePriority:[FEmptyNode emptyNode]]; + FNamedNode *startPost = nil; + FNamedNode *endPost = nil; + if (self.reverse) { + startPost = self.rangedFilter.endPost; + endPost = self.rangedFilter.startPost; + } else { + startPost = self.rangedFilter.startPost; + endPost = self.rangedFilter.endPost; + } + __block BOOL foundStartPost = NO; + __block NSUInteger count = 0; + [newSnap + enumerateChildrenReverse:self.reverse + usingBlock:^(NSString *childKey, id childNode, + BOOL *stop) { + if (!foundStartPost && + [self.index + compareKey:startPost.name + andNode:startPost.node + toOtherKey:childKey + andNode:childNode + reverse:self.reverse] <= NSOrderedSame) { + // Start adding + foundStartPost = YES; + } + BOOL inRange = foundStartPost && count < self.limit; + inRange = inRange && + [self.index compareKey:childKey + andNode:childNode + toOtherKey:endPost.name + andNode:endPost.node + reverse:self.reverse] <= + NSOrderedSame; + if (inRange) { + count++; + } else { + filtered = [filtered + updateChild:childKey + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries. + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +- (id)indexedFilter { + return self.rangedFilter.indexedFilter; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h new file mode 100644 index 0000000..d19c6fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Core/View/Filter/FNodeFilter.h @@ -0,0 +1,77 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FIndexedNode; +@protocol FCompleteChildSource; +@class FChildChangeAccumulator; +@protocol FIndex; +@class FPath; + +/** + * FNodeFilter is used to update nodes and complete children of nodes while + * applying queries on the fly and keeping track of any child changes. This + * class does not track value changes as value changes depend on more than just + * the node itself. Different kind of queries require different kind of + * implementations of this interface. + */ +@protocol FNodeFilter + +/** + * Update a single complete child in the snap. If the child equals the old child + * in the snap, this is a no-op. The method expects an indexed snap. + */ +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator:(FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update a node in full and output any resulting change from this complete + * update. + */ +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator; + +/** + * Update the priority of the root node + */ +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap; + +/** + * Returns true if children might be filtered due to query critiera + */ +- (BOOL)filtersNodes; + +/** + * Returns the index filter that this filter uses to get a NodeFilter that + * doesn't filter any children. + */ +@property(nonatomic, strong, readonly) id indexedFilter; + +/** + * Returns the index that this filter uses + */ +@property(nonatomic, strong, readonly) id index; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.h new file mode 100644 index 0000000..e85cb2a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FClock + +- (NSTimeInterval)currentTime; + +@end + +@interface FSystemClock : NSObject + ++ (FSystemClock *)clock; + +@end + +@interface FOffsetClock : NSObject + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.m new file mode 100644 index 0000000..5d9a9ec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FClock.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FClock.h" + +@implementation FSystemClock + +- (NSTimeInterval)currentTime { + return [[NSDate date] timeIntervalSince1970]; +} + ++ (FSystemClock *)clock { + static dispatch_once_t onceToken; + static FSystemClock *clock; + dispatch_once(&onceToken, ^{ + clock = [[FSystemClock alloc] init]; + }); + return clock; +} + +@end + +@interface FOffsetClock () + +@property(nonatomic, strong) id clock; +@property(nonatomic) NSTimeInterval offset; + +@end + +@implementation FOffsetClock + +- (NSTimeInterval)currentTime { + return [self.clock currentTime] + self.offset; +} + +- (id)initWithClock:(id)clock offset:(NSTimeInterval)offset { + self = [super init]; + if (self != nil) { + self->_clock = clock; + self->_offset = offset; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h new file mode 100644 index 0000000..443664e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; +@class FIndexedNode; +@protocol FNode; + +@interface FEventGenerator : NSObject +- (id)initWithQuery:(FQuerySpec *)query; +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m new file mode 100644 index 0000000..162b0ac --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FEventGenerator.m @@ -0,0 +1,169 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventGenerator.h" +#import "FChange.h" +#import "FDataEvent.h" +#import "FEvent.h" +#import "FEventRegistration.h" +#import "FIRDatabaseQuery_Private.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FQueryParams.h" +#import "FQuerySpec.h" + +@interface FEventGenerator () +@property(nonatomic, strong) FQuerySpec *query; +@end + +/** + * An EventGenerator is used to convert "raw" changes (fb.core.view.Change) as + * computed by the CacheDiffer into actual events (fb.core.view.Event) that can + * be raised. See generateEventsForChanges() for details. + */ +@implementation FEventGenerator + +- (id)initWithQuery:(FQuerySpec *)query { + self = [super init]; + if (self) { + self.query = query; + } + return self; +} + +/** + * Given a set of raw changes (no moved events, and prevName not specified yet), + * and a set of EventRegistrations that should be notified of these changes, + * generate the actual events to be raised. + * + * Notes: + * - child_moved events will be synthesized at this time for any child_changed + * events that affect our index + * - prevName will be calculated based on the index ordering + * + * @param changes NSArray of FChange, not necessarily in order. + * @param registrations is NSArray of FEventRegistration. + * @return NSArray of FEvent. + */ +- (NSArray *)generateEventsForChanges:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *events = [[NSMutableArray alloc] init]; + + // child_moved is index-specific, so check all our child_changed events to + // see if we need to materialize child_moved events with this view's index + NSMutableArray *moves = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == FIRDataEventTypeChildChanged && + [self.query.index + indexedValueChangedBetween:change.oldIndexedNode.node + and:change.indexedNode.node]) { + FChange *moveChange = + [[FChange alloc] initWithType:FIRDataEventTypeChildMoved + indexedNode:change.indexedNode + childKey:change.childKey + oldIndexedNode:nil]; + [moves addObject:moveChange]; + } + } + + [self generateEvents:events + forType:FIRDataEventTypeChildRemoved + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildAdded + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildMoved + changes:moves + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeChildChanged + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + [self generateEvents:events + forType:FIRDataEventTypeValue + changes:changes + eventCache:eventCache + eventRegistrations:registrations]; + + return events; +} + +- (void)generateEvents:(NSMutableArray *)events + forType:(FIRDataEventType)eventType + changes:(NSArray *)changes + eventCache:(FIndexedNode *)eventCache + eventRegistrations:(NSArray *)registrations { + NSMutableArray *filteredChanges = [[NSMutableArray alloc] init]; + for (FChange *change in changes) { + if (change.type == eventType) { + [filteredChanges addObject:change]; + } + } + + id index = self.query.index; + + [filteredChanges + sortUsingComparator:^NSComparisonResult(FChange *one, FChange *two) { + if (one.childKey == nil || two.childKey == nil) { + @throw [[NSException alloc] + initWithName:@"InternalInconsistencyError" + reason:@"Should only compare child_ events" + userInfo:nil]; + } + return [index compareKey:one.childKey + andNode:one.indexedNode.node + toOtherKey:two.childKey + andNode:two.indexedNode.node]; + }]; + + for (FChange *change in filteredChanges) { + for (id registration in registrations) { + if ([registration responseTo:eventType]) { + id event = [self generateEventForChange:change + registration:registration + eventCache:eventCache]; + [events addObject:event]; + } + } + } +} + +- (id)generateEventForChange:(FChange *)change + registration:(id)registration + eventCache:(FIndexedNode *)eventCache { + FChange *materializedChange; + if (change.type == FIRDataEventTypeValue || + change.type == FIRDataEventTypeChildRemoved) { + materializedChange = change; + } else { + NSString *prevChildKey = + [eventCache predecessorForChildKey:change.childKey + childNode:change.indexedNode.node + index:self.query.index]; + materializedChange = [change changeWithPrevKey:prevChildKey]; + } + return [registration createEventFrom:materializedChange query:self.query]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h new file mode 100644 index 0000000..ca2f34b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseConfig_Private.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import "FIRDatabaseConfig.h" + +@protocol FStorageEngine; + +@interface FIRDatabaseConfig () + +@property(nonatomic, readonly) BOOL isFrozen; +@property(nonatomic, strong, readonly) NSString *sessionIdentifier; +@property(nonatomic, strong) id authTokenProvider; +@property(nonatomic, strong) id forceStorageEngine; + +- (void)freeze; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m new file mode 100644 index 0000000..b3c0106 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIRDatabaseReference.m @@ -0,0 +1,528 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import "FIRDatabase.h" +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseConfig_Private.h" +#import "FIRDatabaseQuery_Private.h" +#import "FIRDatabaseReference_Private.h" +#import "FNextPushId.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" +#import "FValidation.h" +#import +#import + +@implementation FIRDatabaseReference + +#pragma mark - +#pragma mark Constructors + +- (id)initWithConfig:(FIRDatabaseConfig *)config { + FParsedUrl *parsedUrl = + [FUtilities parseUrl:[[FIRApp defaultApp] options].databaseURL]; + [FValidation validateFrom:@"initWithUrl:" validURL:parsedUrl]; + return [self initWithRepo:[FRepoManager getRepo:parsedUrl.repoInfo + config:config] + path:parsedUrl.path]; +} + +- (id)initWithRepo:(FRepo *)repo path:(FPath *)path { + return [super initWithRepo:repo + path:path + params:[FQueryParams defaultInstance] + orderByCalled:NO + priorityMethodCalled:NO]; +} + +#pragma mark - +#pragma mark Ancillary methods + +- (nullable NSString *)key { + if ([self.path isEmpty]) { + return nil; + } else { + return [self.path getBack]; + } +} + +- (FIRDatabase *)database { + return self.repo.database; +} + +- (FIRDatabaseReference *)parent { + FPath *parentPath = [self.path parent]; + FIRDatabaseReference *parent = nil; + if (parentPath != nil) { + parent = [[FIRDatabaseReference alloc] initWithRepo:self.repo + path:parentPath]; + } + return parent; +} + +- (NSString *)URL { + FIRDatabaseReference *parent = [self parent]; + return parent == nil + ? [self.repo description] + : [NSString + stringWithFormat:@"%@/%@", [parent description], + [FStringUtilities urlEncoded:self.key]]; +} + +- (NSString *)description { + return [self URL]; +} + +- (FIRDatabaseReference *)root { + return [[FIRDatabaseReference alloc] + initWithRepo:self.repo + path:[[FPath alloc] initWith:@""]]; +} + +#pragma mark - +#pragma mark Child methods + +- (FIRDatabaseReference *)child:(NSString *)pathString { + if ([self.path getFront] == nil) { + // we're at the root + [FValidation validateFrom:@"child:" validRootPathString:pathString]; + } else { + [FValidation validateFrom:@"child:" validPathString:pathString]; + } + FPath *path = [self.path childFromString:pathString]; + FIRDatabaseReference *firebaseRef = + [[FIRDatabaseReference alloc] initWithRepo:self.repo path:path]; + return firebaseRef; +} + +- (FIRDatabaseReference *)childByAutoId { + [FValidation validateFrom:@"childByAutoId:" writablePath:self.path]; + + NSString *name = [FNextPushId get:self.repo.serverTime]; + return [self child:name]; +} + +#pragma mark - +#pragma mark Basic write methods + +- (void)setValue:(id)value { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"setValue:"]; +} + +- (void)setValue:(id)value withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"setValue:withCompletionBlock:"]; +} + +- (void)setValue:(id)value andPriority:(id)priority { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"setValue:andPriority:"]; +} + +- (void)setValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"setValue:andPriority:withCompletionBlock:"]; +} + +- (void)setValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + id newNode = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:self.path withNode:newNode withCallback:userCallback]; + }); +} + +- (void)removeValue { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"removeValue:"]; +} + +- (void)removeValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self setValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"removeValueWithCompletionBlock:"]; +} + +- (void)setPriority:(id)priority { + [self setPriorityInternal:priority + withCompletionBlock:nil + from:@"setPriority:"]; +} + +- (void)setPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + + [self setPriorityInternal:priority + withCompletionBlock:block + from:@"setPriority:withCompletionBlock:"]; +} + +- (void)setPriorityInternal:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo set:[self.path childFromString:@".priority"] + withNode:[FSnapshotUtilities nodeFrom:priority] + withCallback:userCallback]; + }); +} + +- (void)updateChildValues:(NSDictionary *)values { + [self updateChildValuesInternal:values + withCompletionBlock:nil + from:@"updateChildValues:"]; +} + +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self updateChildValuesInternal:values + withCompletionBlock:block + from:@"updateChildValues:withCompletionBlock:"]; +} + +- (void)updateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo update:self.path withNodes:merge withCallback:userCallback]; + }); +} + +#pragma mark - +#pragma mark Disconnect Operations + +- (void)onDisconnectSetValue:(id)value { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectSetValue:"]; +} + +- (void)onDisconnectSetValue:(id)value + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectSetValue:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValue:(id)value andPriority:(id)priority { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:nil + from:@"onDisconnectSetValue:andPriority:"]; +} + +- (void)onDisconnectSetValue:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:value + andPriority:priority + withCompletionBlock:block + from:@"onDisconnectSetValue:andPriority:" + @"withCompletionBlock:"]; +} + +- (void)onDisconnectSetValueInternal:(id)value + andPriority:(id)priority + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + id newNodeUnresolved = [FSnapshotUtilities nodeFrom:value + priority:priority + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectSet:self.path + withNode:newNodeUnresolved + withCallback:userCallback]; + }); +} + +- (void)onDisconnectRemoveValue { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:nil + from:@"onDisconnectRemoveValue:"]; +} + +- (void)onDisconnectRemoveValueWithCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectSetValueInternal:nil + andPriority:nil + withCompletionBlock:block + from:@"onDisconnectRemoveValueWithCompletionB" + @"lock:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values { + [self + onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:nil + from: + @"onDisconnectUpdateChildValues:"]; +} + +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block { + [self onDisconnectUpdateChildValuesInternal:values + withCompletionBlock:block + from:@"onDisconnectUpdateChildValues" + @":withCompletionBlock:"]; +} + +- (void)onDisconnectUpdateChildValuesInternal:(NSDictionary *)values + withCompletionBlock:(fbt_void_nserror_ref)block + from:(NSString *)fn { + [FValidation validateFrom:fn writablePath:self.path]; + + FCompoundWrite *merge = + [FSnapshotUtilities compoundWriteFromDictionary:values + withValidationFrom:fn]; + + fbt_void_nserror_ref userCallback = [block copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectUpdate:self.path + withNodes:merge + withCallback:userCallback]; + }); +} + +- (void)cancelDisconnectOperations { + [self cancelDisconnectOperationsWithCompletionBlock:nil]; +} + +- (void)cancelDisconnectOperationsWithCompletionBlock: + (fbt_void_nserror_ref)block { + fbt_void_nserror_ref callback = nil; + if (block != nil) { + callback = [block copy]; + } + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo onDisconnectCancel:self.path withCallback:callback]; + }); +} + +#pragma mark - +#pragma mark Connection management methods + ++ (void)goOffline { + [FRepoManager interruptAll]; +} + ++ (void)goOnline { + [FRepoManager resumeAll]; +} + +#pragma mark - +#pragma mark Data reading methods deferred to FQuery + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + return [self observeEventType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + return [self observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + return [super observeEventType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle { + [super removeObserverWithHandle:handle]; +} + +- (void)removeAllObservers { + [super removeAllObservers]; +} + +- (void)keepSynced:(BOOL)keepSynced { + [super keepSynced:keepSynced]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block { + [self observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block { + [self observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:nil]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(fbt_void_datasnapshot)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + withBlock:block + withCancelBlock:cancelBlock]; +} + +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(fbt_void_datasnapshot_nsstring)block + withCancelBlock:(fbt_void_nserror)cancelBlock { + [super observeSingleEventOfType:eventType + andPreviousSiblingKeyWithBlock:block + withCancelBlock:cancelBlock]; +} + +#pragma mark - +#pragma mark Query methods +// These methods suppress warnings from having method definitions in +// FIRDatabaseReference.h for docs generation. + +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit { + return [super queryLimitedToFirst:limit]; +} + +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit { + return [super queryLimitedToLast:limit]; +} + +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key { + return [super queryOrderedByChild:key]; +} + +- (FIRDatabaseQuery *)queryOrderedByKey { + return [super queryOrderedByKey]; +} + +- (FIRDatabaseQuery *)queryOrderedByPriority { + return [super queryOrderedByPriority]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue { + return [super queryStartingAtValue:startValue]; +} + +- (FIRDatabaseQuery *)queryStartingAtValue:(id)startValue + childKey:(NSString *)childKey { + return [super queryStartingAtValue:startValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue { + return [super queryEndingAtValue:endValue]; +} + +- (FIRDatabaseQuery *)queryEndingAtValue:(id)endValue + childKey:(NSString *)childKey { + return [super queryEndingAtValue:endValue childKey:childKey]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value { + return [super queryEqualToValue:value]; +} + +- (FIRDatabaseQuery *)queryEqualToValue:(id)value + childKey:(NSString *)childKey { + return [super queryEqualToValue:value childKey:childKey]; +} + +#pragma mark - +#pragma mark Transaction methods + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block { + [FValidation validateFrom:@"runTransactionBlock:" writablePath:self.path]; + [self runTransactionBlock:block andCompletionBlock:nil withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)update + andCompletionBlock: + (fbt_void_nserror_bool_datasnapshot)completionBlock { + [FValidation validateFrom:@"runTransactionBlock:andCompletionBlock:" + writablePath:self.path]; + [self runTransactionBlock:update + andCompletionBlock:completionBlock + withLocalEvents:YES]; +} + +- (void)runTransactionBlock:(fbt_transactionresult_mutabledata)block + andCompletionBlock:(fbt_void_nserror_bool_datasnapshot)completionBlock + withLocalEvents:(BOOL)localEvents { + [FValidation + validateFrom:@"runTransactionBlock:andCompletionBlock:withLocalEvents:" + writablePath:self.path]; + fbt_transactionresult_mutabledata updateCopy = [block copy]; + fbt_void_nserror_bool_datasnapshot onCompleteCopy = [completionBlock copy]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self.repo startTransactionOnPath:self.path + update:updateCopy + onComplete:onCompleteCopy + withLocalEvents:localEvents]; + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.h new file mode 100644 index 0000000..89bec76 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableSortedDictionary; +@class FNamedNode; +@protocol FNode; + +@protocol FIndex +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2; + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse; + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2; + +- (BOOL)isDefinedOn:(id)node; +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode; +- (FNamedNode *)minPost; +- (FNamedNode *)maxPost; +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name; +- (NSString *)queryDefinition; + +@end + +@interface FIndex : NSObject + ++ (id)indexFromQueryDefinition:(NSString *)string; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.m new file mode 100644 index 0000000..0366399 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FIndex.m @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" + +#import "FKeyIndex.h" +#import "FPathIndex.h" +#import "FPriorityIndex.h" +#import "FValueIndex.h" + +@implementation FIndex + ++ (id)indexFromQueryDefinition:(NSString *)string { + if ([string isEqualToString:@".key"]) { + return [FKeyIndex keyIndex]; + } else if ([string isEqualToString:@".value"]) { + return [FValueIndex valueIndex]; + } else if ([string isEqualToString:@".priority"]) { + return [FPriorityIndex priorityIndex]; + } else { + return + [[FPathIndex alloc] initWithPath:[[FPath alloc] initWith:string]]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h new file mode 100644 index 0000000..281a5ac --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FKeyIndex : NSObject ++ (id)keyIndex; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m new file mode 100644 index 0000000..ac10829 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FKeyIndex.m @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FKeyIndex.h" +#import "FEmptyNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FKeyIndex () + +@property(nonatomic, strong) FNamedNode *maxPost; + +@end + +@implementation FKeyIndex + +- (id)init { + self = [super init]; + if (self) { + self.maxPost = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FEmptyNode emptyNode]]; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + return [FUtilities compareKey:key1 toKey:key2]; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return NO; // The key for a node never changes. +} + +- (FNamedNode *)minPost { + return [FNamedNode min]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + NSString *key = indexValue.val; + NSAssert([key isKindOfClass:[NSString class]], + @"KeyIndex indexValue must always be a string."); + // We just use empty node, but it'll never be compared, since our comparator + // only looks at name. + return [[FNamedNode alloc] initWithName:key andNode:[FEmptyNode emptyNode]]; +} + +- (NSString *)queryDefinition { + return @".key"; +} + +- (NSString *)description { + return @"FKeyIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".key" hash]; +} + ++ (id)keyIndex { + static id keyIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + keyIndex = [[FKeyIndex alloc] init]; + }); + return keyIndex; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h new file mode 100644 index 0000000..99aabf8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FOperation.h" +#import + +@interface FListenComplete : NSObject + +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath; + +@property(nonatomic, strong, readonly) FOperationSource *source; +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, readonly) FOperationType type; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m new file mode 100644 index 0000000..26370c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FListenComplete.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FListenComplete.h" +#import "FOperationSource.h" +#import "FPath.h" + +@interface FListenComplete () +@property(nonatomic, strong, readwrite) FOperationSource *source; +@property(nonatomic, strong, readwrite) FPath *path; +@property(nonatomic, readwrite) FOperationType type; +@end + +@implementation FListenComplete +- (id)initWithSource:(FOperationSource *)aSource path:(FPath *)aPath { + NSAssert(!aSource.fromUser, + @"Can't have a listen complete from a user source"); + self = [super init]; + if (self) { + self.source = aSource; + self.path = aPath; + self.type = FOperationTypeListenComplete; + } + return self; +} + +- (id)operationForChild:(NSString *)childKey { + if ([self.path isEmpty]) { + return [[FListenComplete alloc] initWithSource:self.source + path:[FPath empty]]; + } else { + return [[FListenComplete alloc] initWithSource:self.source + path:[self.path popFront]]; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FListenComplete { path=%@, source=%@ }", + self.path, self.source]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h new file mode 100644 index 0000000..c68137e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import + +@interface FMaxNode : FChildrenNode ++ (id)maxNode; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m new file mode 100644 index 0000000..28e7672 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FMaxNode.m @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FMaxNode.h" +#import "FEmptyNode.h" +#import "FUtilities.h" + +@implementation FMaxNode { +} +- (id)init { + self = [super init]; + if (self) { + } + return self; +} + ++ (id)maxNode { + static FMaxNode *maxNode = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + maxNode = [[FMaxNode alloc] init]; + }); + return maxNode; +} + +- (NSComparisonResult)compare:(id)other { + if (other == self) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + +- (BOOL)isEqual:(id)other { + return other == self; +} + +- (id)getImmediateChild:(NSString *)childName { + return [FEmptyNode emptyNode]; +} + +- (BOOL)isEmpty { + return NO; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h new file mode 100644 index 0000000..4414dfd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FNamedNode : NSObject + +@property(nonatomic, strong, readonly) NSString *name; +@property(nonatomic, strong, readonly) id node; + +- (id)initWithName:(NSString *)name andNode:(id)node; + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node; + ++ (FNamedNode *)min; ++ (FNamedNode *)max; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m new file mode 100644 index 0000000..3b2eaf7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FNamedNode.m @@ -0,0 +1,102 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNamedNode.h" +#import "FEmptyNode.h" +#import "FIndex.h" +#import "FMaxNode.h" +#import "FUtilities.h" + +@interface FNamedNode () +@property(nonatomic, strong, readwrite) NSString *name; +@property(nonatomic, strong, readwrite) id node; +@end + +@implementation FNamedNode + ++ (FNamedNode *)nodeWithName:(NSString *)name node:(id)node { + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (id)initWithName:(NSString *)name andNode:(id)node { + self = [super init]; + if (self) { + self.name = name; + self.node = node; + } + return self; +} + +- (id)copy { + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + ++ (FNamedNode *)min { + static FNamedNode *min = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + min = [[FNamedNode alloc] initWithName:[FUtilities minName] + andNode:[FEmptyNode emptyNode]]; + }); + return min; +} + ++ (FNamedNode *)max { + static FNamedNode *max = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + max = [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:[FMaxNode maxNode]]; + }); + return max; +} + +- (NSString *)description { + return + [NSString stringWithFormat:@"NamedNode[%@] %@", self.name, self.node]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (object == nil || ![object isKindOfClass:[FNamedNode class]]) { + return NO; + } + + FNamedNode *namedNode = object; + if (![self.name isEqualToString:namedNode.name]) { + return NO; + } + if (![self.node isEqual:namedNode.node]) { + return NO; + } + + return YES; +} + +- (NSUInteger)hash { + NSUInteger nameHash = [self.name hash]; + NSUInteger nodeHash = [self.node hash]; + NSUInteger result = 31 * nameHash + nodeHash; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h new file mode 100644 index 0000000..6ab9151 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import "FPath.h" +#import + +@interface FPathIndex : NSObject +- (id)initWithPath:(FPath *)path; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m new file mode 100644 index 0000000..214eab8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPathIndex.m @@ -0,0 +1,135 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPathIndex.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@interface FPathIndex () +@property(nonatomic, strong) FPath *path; +@end + +@implementation FPathIndex + +- (id)initWithPath:(FPath *)path { + self = [super init]; + if (self) { + if (path.isEmpty || [path.getFront isEqualToString:@".priority"]) { + [NSException raise:NSInvalidArgumentException + format:@"Invalid path for PathIndex: %@", path]; + } + _path = path; + } + return self; +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getChild:self.path]; + id child2 = [node2 getChild:self.path]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return ![node getChild:self.path].isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getChild:self.path]; + id newValue = [newNode getChild:self.path]; + return [oldValue compare:newValue] != NSOrderedSame; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + id maxNode = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:[FMaxNode maxNode]]; + + return [[FNamedNode alloc] initWithName:[FUtilities maxName] + andNode:maxNode]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FEmptyNode emptyNode] updateChild:self.path + withNewChild:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return [self.path wireFormat]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"FPathIndex(%@)", self.path]; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + if (![other isKindOfClass:[FPathIndex class]]) { + return NO; + } + return ([self.path isEqual:((FPathIndex *)other).path]); +} + +- (NSUInteger)hash { + return [self.path hash]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h new file mode 100644 index 0000000..1b4534e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" + +@interface FPriorityIndex : NSObject ++ (id)priorityIndex; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m new file mode 100644 index 0000000..0b33837 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FPriorityIndex.m @@ -0,0 +1,126 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPriorityIndex.h" + +#import "FEmptyNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FUtilities.h" + +// TODO: Abstract into some common base class? + +@implementation FPriorityIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + id child1 = [node1 getPriority]; + id child2 = [node2 getPriority]; + NSComparisonResult indexCmp = [child1 compare:child2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return !node.getPriority.isEmpty; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + id oldValue = [oldNode getPriority]; + id newValue = [newNode getPriority]; + return ![oldValue isEqual:newValue]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return [self makePost:[FMaxNode maxNode] name:[FUtilities maxName]]; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + id node = [[FLeafNode alloc] initWithValue:@"[PRIORITY-POST]" + withPriority:indexValue]; + return [[FNamedNode alloc] initWithName:name andNode:node]; +} + +- (NSString *)queryDefinition { + return @".priority"; +} + +- (NSString *)description { + return @"FPriorityIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + // Safe since we're immutable. + return self; +} + +- (BOOL)isEqual:(id)other { + return [other isKindOfClass:[FPriorityIndex class]]; +} + +- (NSUInteger)hash { + // chosen by a fair dice roll. Guaranteed to be random + return 3155577; +} + ++ (id)priorityIndex { + static id index; + static dispatch_once_t once; + dispatch_once(&once, ^{ + index = [[FPriorityIndex alloc] init]; + }); + + return index; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h new file mode 100644 index 0000000..3c1aadd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.h @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNodeFilter.h" +#import + +@class FQueryParams; +@class FNamedNode; + +@interface FRangedFilter : NSObject + +- (id)initWithQueryParams:(FQueryParams *)params; +- (BOOL)matchesKey:(NSString *)key andNode:(id)node; + +@property(nonatomic, strong, readonly) FNamedNode *startPost; +@property(nonatomic, strong, readonly) FNamedNode *endPost; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m new file mode 100644 index 0000000..bd8ef81 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FRangedFilter.m @@ -0,0 +1,129 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FRangedFilter.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FEmptyNode.h" +#import "FIndexedFilter.h" +#import "FIndexedNode.h" +#import "FNamedNode.h" +#import "FQueryParams.h" + +@interface FRangedFilter () +@property(nonatomic, strong, readwrite) id indexedFilter; +@property(nonatomic, strong, readwrite) id index; +@property(nonatomic, strong, readwrite) FNamedNode *startPost; +@property(nonatomic, strong, readwrite) FNamedNode *endPost; +@end + +@implementation FRangedFilter +- (id)initWithQueryParams:(FQueryParams *)params { + self = [super init]; + if (self) { + self.indexedFilter = + [[FIndexedFilter alloc] initWithIndex:params.index]; + self.index = params.index; + self.startPost = [FRangedFilter startPostFromQueryParams:params]; + self.endPost = [FRangedFilter endPostFromQueryParams:params]; + } + return self; +} + ++ (FNamedNode *)startPostFromQueryParams:(FQueryParams *)params { + if ([params hasStart]) { + NSString *startKey = params.indexStartKey; + return [params.index makePost:params.indexStartValue name:startKey]; + } else { + return params.index.minPost; + } +} + ++ (FNamedNode *)endPostFromQueryParams:(FQueryParams *)params { + if ([params hasEnd]) { + NSString *endKey = params.indexEndKey; + return [params.index makePost:params.indexEndValue name:endKey]; + } else { + return params.index.maxPost; + } +} + +- (BOOL)matchesKey:(NSString *)key andNode:(id)node { + return ([self.index compareKey:self.startPost.name + andNode:self.startPost.node + toOtherKey:key + andNode:node] <= NSOrderedSame && + [self.index compareKey:key + andNode:node + toOtherKey:self.endPost.name + andNode:self.endPost.node] <= NSOrderedSame); +} + +- (FIndexedNode *)updateChildIn:(FIndexedNode *)oldSnap + forChildKey:(NSString *)childKey + newChild:(id)newChildSnap + affectedPath:(FPath *)affectedPath + fromSource:(id)source + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + if (![self matchesKey:childKey andNode:newChildSnap]) { + newChildSnap = [FEmptyNode emptyNode]; + } + return [self.indexedFilter updateChildIn:oldSnap + forChildKey:childKey + newChild:newChildSnap + affectedPath:affectedPath + fromSource:source + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updateFullNode:(FIndexedNode *)oldSnap + withNewNode:(FIndexedNode *)newSnap + accumulator: + (FChildChangeAccumulator *)optChangeAccumulator { + __block FIndexedNode *filtered; + if (newSnap.node.isLeafNode) { + // Make sure we have a children node with the correct index, not a leaf + // node + filtered = [FIndexedNode indexedNodeWithNode:[FEmptyNode emptyNode] + index:self.index]; + } else { + // Dont' support priorities on queries + filtered = [newSnap updatePriority:[FEmptyNode emptyNode]]; + [newSnap.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + if (![self matchesKey:key andNode:node]) { + filtered = [filtered updateChild:key + withNewChild:[FEmptyNode emptyNode]]; + } + }]; + } + return [self.indexedFilter updateFullNode:oldSnap + withNewNode:filtered + accumulator:optChangeAccumulator]; +} + +- (FIndexedNode *)updatePriority:(id)priority + forNode:(FIndexedNode *)oldSnap { + // Don't support priorities on queries + return oldSnap; +} + +- (BOOL)filtersNodes { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h new file mode 100644 index 0000000..25a59b4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTransformedEnumerator : NSEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform; +- (id)nextObject; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m new file mode 100644 index 0000000..567e100 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FTransformedEnumerator.m @@ -0,0 +1,44 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTransformedEnumerator.h" + +@interface FTransformedEnumerator () +@property(nonatomic, strong) NSEnumerator *enumerator; +@property(nonatomic, copy) id (^transform)(id); +@end + +@implementation FTransformedEnumerator +- (id)initWithEnumerator:(NSEnumerator *)enumerator + andTransform:(id (^)(id))transform { + self = [super init]; + if (self) { + self.enumerator = enumerator; + self.transform = transform; + } + return self; +} + +- (id)nextObject { + id next = self.enumerator.nextObject; + if (next != nil) { + return self.transform(next); + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h new file mode 100644 index 0000000..a79f202 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndex.h" +#import + +@interface FValueIndex : NSObject ++ (id)valueIndex; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m new file mode 100644 index 0000000..61021c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FValueIndex.m @@ -0,0 +1,112 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValueIndex.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FSnapshotUtilities.h" +#import "FUtilities.h" + +@implementation FValueIndex + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 { + NSComparisonResult indexCmp = [node1 compare:node2]; + if (indexCmp == NSOrderedSame) { + return [FUtilities compareKey:key1 toKey:key2]; + } else { + return indexCmp; + } +} + +- (NSComparisonResult)compareKey:(NSString *)key1 + andNode:(id)node1 + toOtherKey:(NSString *)key2 + andNode:(id)node2 + reverse:(BOOL)reverse { + if (reverse) { + return [self compareKey:key2 + andNode:node2 + toOtherKey:key1 + andNode:node1]; + } else { + return [self compareKey:key1 + andNode:node1 + toOtherKey:key2 + andNode:node2]; + } +} + +- (NSComparisonResult)compareNamedNode:(FNamedNode *)namedNode1 + toNamedNode:(FNamedNode *)namedNode2 { + return [self compareKey:namedNode1.name + andNode:namedNode1.node + toOtherKey:namedNode2.name + andNode:namedNode2.node]; +} + +- (BOOL)isDefinedOn:(id)node { + return YES; +} + +- (BOOL)indexedValueChangedBetween:(id)oldNode and:(id)newNode { + return ![oldNode isEqual:newNode]; +} + +- (FNamedNode *)minPost { + return FNamedNode.min; +} + +- (FNamedNode *)maxPost { + return FNamedNode.max; +} + +- (FNamedNode *)makePost:(id)indexValue name:(NSString *)name { + return [[FNamedNode alloc] initWithName:name andNode:indexValue]; +} + +- (NSString *)queryDefinition { + return @".value"; +} + +- (NSString *)description { + return @"FValueIndex"; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)other { + // since we're a singleton. + return (other == self); +} + +- (NSUInteger)hash { + return [@".value" hash]; +} + ++ (id)valueIndex { + static id valueIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueIndex = [[FValueIndex alloc] init]; + }); + return valueIndex; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h new file mode 100644 index 0000000..ea6676e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; +@class FViewProcessorResult; +@class FChildChangeAccumulator; +@protocol FNode; +@class FWriteTreeRef; +@class FPath; +@protocol FOperation; +@protocol FNodeFilter; + +@interface FViewProcessor : NSObject + +- (id)initWithFilter:(id)nodeFilter; + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache; +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m new file mode 100644 index 0000000..5524996 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessor.m @@ -0,0 +1,831 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessor.h" +#import "FAckUserWrite.h" +#import "FCacheNode.h" +#import "FChange.h" +#import "FChildChangeAccumulator.h" +#import "FChildrenNode.h" +#import "FCompleteChildSource.h" +#import "FCompoundWrite.h" +#import "FEmptyNode.h" +#import "FIRDataEventType.h" +#import "FImmutableTree.h" +#import "FKeyIndex.h" +#import "FMerge.h" +#import "FNode.h" +#import "FNodeFilter.h" +#import "FOperation.h" +#import "FOperationSource.h" +#import "FOverwrite.h" +#import "FPath.h" +#import "FViewCache.h" +#import "FViewProcessorResult.h" +#import "FWriteTreeRef.h" + +/** + * An implementation of FCompleteChildSource that never returns any additional + * children + */ +@interface FNoCompleteChildSource : NSObject +@end + +@implementation FNoCompleteChildSource ++ (FNoCompleteChildSource *)instance { + static FNoCompleteChildSource *source = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + source = [[FNoCompleteChildSource alloc] init]; + }); + return source; +} + +- (id)completeChild:(NSString *)childKey { + return nil; +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + return nil; +} +@end + +/** + * An implementation of FCompleteChildSource that uses a FWriteTree in addition + * to any other server data or old event caches available to calculate complete + * children. + */ +@interface FWriteTreeCompleteChildSource : NSObject +@property(nonatomic, strong) FWriteTreeRef *writes; +@property(nonatomic, strong) FViewCache *viewCache; +@property(nonatomic, strong) id optCompleteServerCache; +@end + +@implementation FWriteTreeCompleteChildSource +- (id)initWithWrites:(FWriteTreeRef *)writes + viewCache:(FViewCache *)viewCache + serverCache:(id)optCompleteServerCache { + self = [super init]; + if (self) { + self.writes = writes; + self.viewCache = viewCache; + self.optCompleteServerCache = optCompleteServerCache; + } + return self; +} + +- (id)completeChild:(NSString *)childKey { + FCacheNode *node = self.viewCache.cachedEventSnap; + if ([node isCompleteForChild:childKey]) { + return [node.node getImmediateChild:childKey]; + } else { + FCacheNode *serverNode; + if (self.optCompleteServerCache) { + // Since we're only ever getting child nodes, we can use the key + // index here + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:self.optCompleteServerCache + index:[FKeyIndex keyIndex]]; + serverNode = [[FCacheNode alloc] initWithIndexedNode:indexed + isFullyInitialized:YES + isFiltered:NO]; + } else { + serverNode = self.viewCache.cachedServerSnap; + } + return [self.writes calculateCompleteChild:childKey cache:serverNode]; + } +} + +- (FNamedNode *)childByIndex:(id)index + afterChild:(FNamedNode *)child + isReverse:(BOOL)reverse { + id completeServerData = self.optCompleteServerCache != nil + ? self.optCompleteServerCache + : self.viewCache.completeServerSnap; + return [self.writes calculateNextNodeAfterPost:child + completeServerData:completeServerData + reverse:reverse + index:index]; +} + +@end + +@interface FViewProcessor () +@property(nonatomic, strong) id filter; +@end + +@implementation FViewProcessor + +- (id)initWithFilter:(id)nodeFilter { + self = [super init]; + if (self) { + self.filter = nodeFilter; + } + return self; +} + +- (FViewProcessorResult *)applyOperationOn:(FViewCache *)oldViewCache + operation:(id)operation + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache { + FChildChangeAccumulator *accumulator = + [[FChildChangeAccumulator alloc] init]; + FViewCache *newViewCache; + + if (operation.type == FOperationTypeOverwrite) { + FOverwrite *overwrite = (FOverwrite *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserOverwriteTo:oldViewCache + changePath:overwrite.path + changedSnap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, + @"Unknown source for overwrite."); + // We filter the node if it's a tagged update or the node has been + // previously filtered and the update is not at the root in which + // case it is ok (and necessary) to mark the node unfiltered again + BOOL filterServerNode = overwrite.source.isTagged || + (oldViewCache.cachedServerSnap.isFiltered && + !overwrite.path.isEmpty); + newViewCache = [self applyServerOverwriteTo:oldViewCache + changePath:overwrite.path + snap:overwrite.snap + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeMerge) { + FMerge *merge = (FMerge *)operation; + if (operation.source.fromUser) { + newViewCache = [self applyUserMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + NSAssert(operation.source.fromServer, @"Unknown source for merge."); + // We filter the node if it's a tagged update or the node has been + // previously filtered + BOOL filterServerNode = merge.source.isTagged || + oldViewCache.cachedServerSnap.isFiltered; + newViewCache = [self applyServerMergeTo:oldViewCache + path:merge.path + changedChildren:merge.children + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeAckUserWrite) { + FAckUserWrite *ackWrite = (FAckUserWrite *)operation; + if (!ackWrite.revert) { + newViewCache = [self ackUserWriteOn:oldViewCache + ackPath:ackWrite.path + affectedTree:ackWrite.affectedTree + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } else { + newViewCache = [self revertUserWriteOn:oldViewCache + path:ackWrite.path + writesCache:writesCache + completeCache:optCompleteCache + accumulator:accumulator]; + } + } else if (operation.type == FOperationTypeListenComplete) { + newViewCache = [self listenCompleteOldCache:oldViewCache + path:operation.path + writesCache:writesCache + serverCache:optCompleteCache + accumulator:accumulator]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Unknown operation encountered %ld.", (long)operation.type]; + return nil; + } + + NSArray *changes = [self maybeAddValueFromOldViewCache:oldViewCache + newViewCache:newViewCache + changes:accumulator.changes]; + FViewProcessorResult *results = + [[FViewProcessorResult alloc] initWithViewCache:newViewCache + changes:changes]; + return results; +} + +- (NSArray *)maybeAddValueFromOldViewCache:(FViewCache *)oldViewCache + newViewCache:(FViewCache *)newViewCache + changes:(NSArray *)changes { + NSArray *newChanges = changes; + FCacheNode *eventSnap = newViewCache.cachedEventSnap; + if (eventSnap.isFullyInitialized) { + BOOL isLeafOrEmpty = + eventSnap.node.isLeafNode || eventSnap.node.isEmpty; + if ([changes count] > 0 || + !oldViewCache.cachedEventSnap.isFullyInitialized || + (isLeafOrEmpty && + ![eventSnap.node isEqual:oldViewCache.completeEventSnap]) || + ![eventSnap.node.getPriority + isEqual:oldViewCache.completeEventSnap.getPriority]) { + FChange *valueChange = + [[FChange alloc] initWithType:FIRDataEventTypeValue + indexedNode:eventSnap.indexedNode]; + NSMutableArray *mutableChanges = [changes mutableCopy]; + [mutableChanges addObject:valueChange]; + newChanges = mutableChanges; + } + } + return newChanges; +} + +- (FViewCache *) + generateEventCacheAfterServerEvent:(FViewCache *)viewCache + path:(FPath *)changePath + writesCache:(FWriteTreeRef *)writesCache + source:(id)source + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = viewCache.cachedEventSnap; + if ([writesCache shadowingWriteAtPath:changePath] != nil) { + // we have a shadowing write, ignore changes. + return viewCache; + } else { + FIndexedNode *newEventCache; + if (changePath.isEmpty) { + // TODO: figure out how this plays with "sliding ack windows" + NSAssert( + viewCache.cachedServerSnap.isFullyInitialized, + @"If change path is empty, we must have complete server data"); + id nodeWithLocalWrites; + if (viewCache.cachedServerSnap.isFiltered) { + // We need to special case this, because we need to only apply + // writes to complete children, or we might end up raising + // events for incomplete children. If the server data is + // filtered deep writes cannot be guaranteed to be complete + id serverCache = viewCache.completeServerSnap; + FChildrenNode *completeChildren = + ([serverCache isKindOfClass:[FChildrenNode class]]) + ? serverCache + : [FEmptyNode emptyNode]; + nodeWithLocalWrites = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + completeChildren]; + } else { + nodeWithLocalWrites = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:nodeWithLocalWrites + index:self.filter.index]; + newEventCache = [self.filter + updateFullNode:viewCache.cachedEventSnap.indexedNode + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + NSAssert( + changePath.length == 1, + @"Can't have a priority with additional path components"); + id oldEventNode = oldEventSnap.node; + id serverNode = viewCache.cachedServerSnap.node; + // we might have overwrites for this priority + id updatedPriority = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventNode + existingServerSnap: + serverNode]; + if (updatedPriority != nil) { + newEventCache = + [self.filter updatePriority:updatedPriority + forNode:oldEventSnap.indexedNode]; + } else { + // priority didn't change, keep old node + newEventCache = oldEventSnap.indexedNode; + } + } else { + FPath *childChangePath = [changePath popFront]; + id newEventChild; + if ([oldEventSnap isCompleteForChild:childKey]) { + id serverNode = viewCache.cachedServerSnap.node; + id eventChildUpdate = [writesCache + calculateEventCacheAfterServerOverwriteWithChildPath: + changePath + existingEventSnap: + oldEventSnap.node + existingServerSnap: + serverNode]; + if (eventChildUpdate != nil) { + newEventChild = + [[oldEventSnap.node getImmediateChild:childKey] + updateChild:childChangePath + withNewChild:eventChildUpdate]; + } else { + // Nothing changed, just keep the old child + newEventChild = + [oldEventSnap.node getImmediateChild:childKey]; + } + } else { + newEventChild = [writesCache + calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + } + if (newEventChild != nil) { + newEventCache = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newEventChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + } else { + // No complete children available or no change + newEventCache = oldEventSnap.indexedNode; + } + } + } + return [viewCache updateEventSnap:newEventCache + isComplete:(oldEventSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)applyServerOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + snap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerSnap = oldViewCache.cachedServerSnap; + FIndexedNode *newServerCache; + id serverFilter = + filterServerNode ? self.filter : self.filter.indexedFilter; + + if (changePath.isEmpty) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:serverFilter.index]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else if (serverFilter.filtersNodes && !oldServerSnap.isFiltered) { + // We want to filter the server node, but we didn't filter the server + // node yet, so simulate a full update + NSAssert(![changePath isEmpty], + @"An empty path should been caught in the other branch"); + NSString *childKey = [changePath getFront]; + FPath *updatePath = [changePath popFront]; + id newChild = [[oldServerSnap.node getImmediateChild:childKey] + updateChild:updatePath + withNewChild:changedSnap]; + FIndexedNode *indexed = + [oldServerSnap.indexedNode updateChild:childKey + withNewChild:newChild]; + newServerCache = [serverFilter updateFullNode:oldServerSnap.indexedNode + withNewNode:indexed + accumulator:nil]; + } else { + NSString *childKey = [changePath getFront]; + if (![oldServerSnap isCompleteForPath:changePath] && + changePath.length > 1) { + // We don't update incomplete nodes with updates intended for other + // listeners. + return oldViewCache; + } + FPath *childChangePath = [changePath popFront]; + id childNode = [oldServerSnap.node getImmediateChild:childKey]; + id newChildNode = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + if ([childKey isEqualToString:@".priority"]) { + newServerCache = + [serverFilter updatePriority:newChildNode + forNode:oldServerSnap.indexedNode]; + } else { + newServerCache = + [serverFilter updateChildIn:oldServerSnap.indexedNode + forChildKey:childKey + newChild:newChildNode + affectedPath:childChangePath + fromSource:[FNoCompleteChildSource instance] + accumulator:nil]; + } + } + FViewCache *newViewCache = + [oldViewCache updateServerSnap:newServerCache + isComplete:(oldServerSnap.isFullyInitialized || + changePath.isEmpty) + isFiltered:serverFilter.filtersNodes]; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:newViewCache + serverCache:optCompleteCache]; + return [self generateEventCacheAfterServerEvent:newViewCache + path:changePath + writesCache:writesCache + source:source + accumulator:accumulator]; +} + +- (FViewCache *)applyUserOverwriteTo:(FViewCache *)oldViewCache + changePath:(FPath *)changePath + changedSnap:(id)changedSnap + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldEventSnap = oldViewCache.cachedEventSnap; + FViewCache *newViewCache; + id source = + [[FWriteTreeCompleteChildSource alloc] initWithWrites:writesCache + viewCache:oldViewCache + serverCache:optCompleteCache]; + if (changePath.isEmpty) { + FIndexedNode *newIndexed = + [FIndexedNode indexedNodeWithNode:changedSnap + index:self.filter.index]; + FIndexedNode *newEventCache = + [self.filter updateFullNode:oldEventSnap.indexedNode + withNewNode:newIndexed + accumulator:accumulator]; + newViewCache = [oldViewCache updateEventSnap:newEventCache + isComplete:YES + isFiltered:self.filter.filtersNodes]; + } else { + NSString *childKey = [changePath getFront]; + if ([childKey isEqualToString:@".priority"]) { + FIndexedNode *newEventCache = [self.filter + updatePriority:changedSnap + forNode:oldViewCache.cachedEventSnap.indexedNode]; + newViewCache = + [oldViewCache updateEventSnap:newEventCache + isComplete:oldEventSnap.isFullyInitialized + isFiltered:oldEventSnap.isFiltered]; + } else { + FPath *childChangePath = [changePath popFront]; + id oldChild = [oldEventSnap.node getImmediateChild:childKey]; + id newChild; + if (childChangePath.isEmpty) { + // Child overwrite, we can replace the child + newChild = changedSnap; + } else { + id childNode = [source completeChild:childKey]; + if (childNode != nil) { + if ([[childChangePath getBack] + isEqualToString:@".priority"] && + [childNode getChild:[childChangePath parent]].isEmpty) { + // This is a priority update on an empty node. If this + // node exists on the server, the server will send down + // the priority in the update, so ignore for now + newChild = childNode; + } else { + newChild = [childNode updateChild:childChangePath + withNewChild:changedSnap]; + } + } else { + newChild = [FEmptyNode emptyNode]; + } + } + if (![oldChild isEqual:newChild]) { + FIndexedNode *newEventSnap = + [self.filter updateChildIn:oldEventSnap.indexedNode + forChildKey:childKey + newChild:newChild + affectedPath:childChangePath + fromSource:source + accumulator:accumulator]; + newViewCache = [oldViewCache + updateEventSnap:newEventSnap + isComplete:oldEventSnap.isFullyInitialized + isFiltered:self.filter.filtersNodes]; + } else { + newViewCache = oldViewCache; + } + } + } + return newViewCache; +} + ++ (BOOL)cache:(FViewCache *)viewCache hasChild:(NSString *)childKey { + return [viewCache.cachedEventSnap isCompleteForChild:childKey]; +} + +/** + * @param changedChildren NSDictionary of child name (NSString*) to child value + * (id) + */ +- (FViewCache *)applyUserMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + accumulator:(FChildChangeAccumulator *)accumulator { + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if ([FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + [changedChildren enumerateWrites:^(FPath *relativePath, id childNode, + BOOL *stop) { + FPath *writePath = [path child:relativePath]; + if (![FViewProcessor cache:viewCache hasChild:[writePath getFront]]) { + curViewCache = [self applyUserOverwriteTo:curViewCache + changePath:writePath + changedSnap:childNode + writesCache:writesCache + completeCache:serverCache + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)applyServerMergeTo:(FViewCache *)viewCache + path:(FPath *)path + changedChildren:(FCompoundWrite *)changedChildren + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)serverCache + filterServerNode:(BOOL)filterServerNode + accumulator:(FChildChangeAccumulator *)accumulator { + // If we don't have a cache yet, this merge was intended for a previously + // listen in the same location. Ignore it and wait for the complete data + // update coming soon. + if (viewCache.cachedServerSnap.node.isEmpty && + !viewCache.cachedServerSnap.isFullyInitialized) { + return viewCache; + } + + // HACK: In the case of a limit query, there may be some changes that bump + // things out of the window leaving room for new items. It's important we + // process these changes first, so we iterate the changes twice, first + // processing any that affect items currently in view. + // TODO: I consider an item "in view" if cacheHasChild is true, which checks + // both the server and event snap. I'm not sure if this will result in edge + // cases when a child is in one but not the other. + __block FViewCache *curViewCache = viewCache; + FCompoundWrite *actualMerge; + if (path.isEmpty) { + actualMerge = changedChildren; + } else { + actualMerge = + [[FCompoundWrite emptyWrite] addCompoundWrite:changedChildren + atPath:path]; + } + id serverNode = viewCache.cachedServerSnap.node; + + NSDictionary *childCompoundWrites = actualMerge.childCompoundWrites; + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + if ([serverNode hasChild:childKey]) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + [childCompoundWrites + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FCompoundWrite *childMerge, BOOL *stop) { + bool isUnknownDeepMerge = + ![viewCache.cachedServerSnap isCompleteForChild:childKey] && + childMerge.rootWrite == nil; + if (![serverNode hasChild:childKey] && !isUnknownDeepMerge) { + id serverChild = + [viewCache.cachedServerSnap.node getImmediateChild:childKey]; + id newChild = [childMerge applyToNode:serverChild]; + curViewCache = + [self applyServerOverwriteTo:curViewCache + changePath:[[FPath alloc] initWith:childKey] + snap:newChild + writesCache:writesCache + completeCache:serverCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } + }]; + + return curViewCache; +} + +- (FViewCache *)ackUserWriteOn:(FViewCache *)viewCache + ackPath:(FPath *)ackPath + affectedTree:(FImmutableTree *)affectedTree + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + + if ([writesCache shadowingWriteAtPath:ackPath] != nil) { + return viewCache; + } + + // Only filter server node if it is currently filtered + BOOL filterServerNode = viewCache.cachedServerSnap.isFiltered; + + // Essentially we'll just get our existing server cache for the affected + // paths and re-apply it as a server update now that it won't be shadowed. + FCacheNode *serverCache = viewCache.cachedServerSnap; + if (affectedTree.value != nil) { + // This is an overwrite. + if ((ackPath.isEmpty && serverCache.isFullyInitialized) || + [serverCache isCompleteForPath:ackPath]) { + return + [self applyServerOverwriteTo:viewCache + changePath:ackPath + snap:[serverCache.node getChild:ackPath] + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else if (ackPath.isEmpty) { + // This is a goofy edge case where we are acking data at this + // location but don't have full data. We should just re-apply + // whatever we have in our cache as a merge. + FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + for (FNamedNode *child in serverCache.node.childEnumerator) { + changedChildren = [changedChildren addWrite:child.node + atKey:child.name]; + } + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } else { + return viewCache; + } + } else { + // This is a merge. + __block FCompoundWrite *changedChildren = [FCompoundWrite emptyWrite]; + [affectedTree forEach:^(FPath *mergePath, id value) { + FPath *serverCachePath = [ackPath child:mergePath]; + if ([serverCache isCompleteForPath:serverCachePath]) { + changedChildren = [changedChildren + addWrite:[serverCache.node getChild:serverCachePath] + atPath:mergePath]; + } + }]; + return [self applyServerMergeTo:viewCache + path:ackPath + changedChildren:changedChildren + writesCache:writesCache + completeCache:optCompleteCache + filterServerNode:filterServerNode + accumulator:accumulator]; + } +} + +- (FViewCache *)revertUserWriteOn:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + completeCache:(id)optCompleteCache + accumulator:(FChildChangeAccumulator *)accumulator { + if ([writesCache shadowingWriteAtPath:path] != nil) { + return viewCache; + } else { + id source = [[FWriteTreeCompleteChildSource alloc] + initWithWrites:writesCache + viewCache:viewCache + serverCache:optCompleteCache]; + FIndexedNode *oldEventCache = viewCache.cachedEventSnap.indexedNode; + FIndexedNode *newEventCache; + if (path.isEmpty || [[path getFront] isEqualToString:@".priority"]) { + id newNode; + if (viewCache.cachedServerSnap.isFullyInitialized) { + newNode = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + } else { + newNode = [writesCache + calculateCompleteEventChildrenWithCompleteServerChildren: + viewCache.cachedServerSnap.node]; + } + FIndexedNode *indexedNode = + [FIndexedNode indexedNodeWithNode:newNode + index:self.filter.index]; + newEventCache = [self.filter updateFullNode:oldEventCache + withNewNode:indexedNode + accumulator:accumulator]; + } else { + NSString *childKey = [path getFront]; + id newChild = + [writesCache calculateCompleteChild:childKey + cache:viewCache.cachedServerSnap]; + if (newChild == nil && + [viewCache.cachedServerSnap isCompleteForChild:childKey]) { + newChild = [oldEventCache.node getImmediateChild:childKey]; + } + if (newChild != nil) { + newEventCache = [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:newChild + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else if (newChild == nil && + [viewCache.cachedEventSnap.node hasChild:childKey]) { + // No complete child available, delete the existing one, if any + newEventCache = + [self.filter updateChildIn:oldEventCache + forChildKey:childKey + newChild:[FEmptyNode emptyNode] + affectedPath:[path popFront] + fromSource:source + accumulator:accumulator]; + } else { + newEventCache = oldEventCache; + } + if (newEventCache.node.isEmpty && + viewCache.cachedServerSnap.isFullyInitialized) { + // We might have reverted all child writes. Maybe the old event + // was a leaf node. + id complete = [writesCache + calculateCompleteEventCacheWithCompleteServerCache: + viewCache.completeServerSnap]; + if (complete.isLeafNode) { + FIndexedNode *indexed = + [FIndexedNode indexedNodeWithNode:complete]; + newEventCache = [self.filter updateFullNode:newEventCache + withNewNode:indexed + accumulator:accumulator]; + } + } + } + BOOL complete = viewCache.cachedServerSnap.isFullyInitialized || + [writesCache shadowingWriteAtPath:[FPath empty]] != nil; + return [viewCache updateEventSnap:newEventCache + isComplete:complete + isFiltered:self.filter.filtersNodes]; + } +} + +- (FViewCache *)listenCompleteOldCache:(FViewCache *)viewCache + path:(FPath *)path + writesCache:(FWriteTreeRef *)writesCache + serverCache:(id)servercache + accumulator:(FChildChangeAccumulator *)accumulator { + FCacheNode *oldServerNode = viewCache.cachedServerSnap; + FViewCache *newViewCache = [viewCache + updateServerSnap:oldServerNode.indexedNode + isComplete:(oldServerNode.isFullyInitialized || path.isEmpty) + isFiltered:oldServerNode.isFiltered]; + return [self + generateEventCacheAfterServerEvent:newViewCache + path:path + writesCache:writesCache + source:[FNoCompleteChildSource instance] + accumulator:accumulator]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h new file mode 100644 index 0000000..8d3e2ef --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FViewCache; + +@interface FViewProcessorResult : NSObject +@property(nonatomic, strong, readonly) FViewCache *viewCache; +/** + * List of FChanges. + */ +@property(nonatomic, strong, readonly) NSArray *changes; + +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m new file mode 100644 index 0000000..0d38947 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/FViewProcessorResult.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FViewProcessorResult.h" +#import "FViewCache.h" + +@interface FViewProcessorResult () +@property(nonatomic, strong, readwrite) FViewCache *viewCache; +@property(nonatomic, strong, readwrite) NSArray *changes; +@end + +@implementation FViewProcessorResult +- (id)initWithViewCache:(FViewCache *)viewCache changes:(NSArray *)changes { + self = [super init]; + if (self) { + self.viewCache = viewCache; + self.changes = changes; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h new file mode 100644 index 0000000..a4f8b15 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FTypedefs.h" +#import "FTypedefs_Private.h" + +@protocol FIRAuthInterop; + +@protocol FAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback; + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener; + +@end + +@interface FAuthTokenProvider : NSObject + ++ (id)authTokenProviderWithAuth:(id)auth; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m new file mode 100644 index 0000000..cd7fbe7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FAuthTokenProvider.m @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" + +#import +#import +#import +#import + +#import "FIRDatabaseQuery_Private.h" +#import "FIRNoopAuthTokenProvider.h" +#import "FUtilities.h" + +@interface FAuthStateListenerWrapper : NSObject + +@property(nonatomic, copy) fbt_void_nsstring listener; +@property(nonatomic, weak) id auth; + +@end + +@implementation FAuthStateListenerWrapper + +- (instancetype)initWithListener:(fbt_void_nsstring)listener + auth:(id)auth { + self = [super init]; + if (self != nil) { + self->_listener = listener; + self->_auth = auth; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(authStateDidChangeNotification:) + name:FIRAuthStateDidChangeInternalNotification + object:nil]; + } + return self; +} + +- (void)authStateDidChangeNotification:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + if (notification.object == self.auth) { + NSString *token = + userInfo[FIRAuthStateDidChangeInternalNotificationTokenKey]; + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + self.listener(token); + }); + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end + +@interface FIRFirebaseAuthTokenProvider : NSObject + +@property(nonatomic, strong) id auth; +/** Strong references to the auth listeners as they are only weak in + * FIRFirebaseApp */ +@property(nonatomic, strong) NSMutableArray *authListeners; + +- (instancetype)initWithAuth:(id)auth; + +@end + +@implementation FIRFirebaseAuthTokenProvider + +- (instancetype)initWithAuth:(id)auth { + self = [super init]; + if (self != nil) { + self->_auth = auth; + self->_authListeners = [NSMutableArray array]; + } + return self; +} + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + if (self.auth == nil) { + // Signal that Auth is not available by returning nil. + callback(nil, nil); + } else { + [self.auth getTokenForcingRefresh:forceRefresh + withCallback:^(NSString *_Nullable token, + NSError *_Nullable error) { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(token, error); + }); + }]; + } +} + +- (void)listenForTokenChanges:(_Nonnull fbt_void_nsstring)listener { + FAuthStateListenerWrapper *wrapper = + [[FAuthStateListenerWrapper alloc] initWithListener:listener + auth:self.auth]; + [self.authListeners addObject:wrapper]; +} + +@end + +@implementation FAuthTokenProvider + ++ (id)authTokenProviderWithAuth: + (id)authInterop { + return [[FIRFirebaseAuthTokenProvider alloc] initWithAuth:authInterop]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h new file mode 100644 index 0000000..137c0ce --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.h @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAuthTokenProvider.h" +#import + +@interface FIRNoopAuthTokenProvider : NSObject + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m new file mode 100644 index 0000000..c50d308 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Login/FIRNoopAuthTokenProvider.m @@ -0,0 +1,34 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRNoopAuthTokenProvider.h" +#import "FAuthTokenProvider.h" +#import "FIRDatabaseQuery_Private.h" + +@implementation FIRNoopAuthTokenProvider + +- (void)fetchTokenForcingRefresh:(BOOL)forceRefresh + withCallback:(fbt_void_nsstring_nserror)callback { + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + callback(nil, nil); + }); +} + +- (void)listenForTokenChanges:(fbt_void_nsstring)listener { + // no-op, because token never changes +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h new file mode 100644 index 0000000..6305d34 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FCachePolicy + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries; +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck; +- (float)percentOfQueriesToPruneAtOnce; +- (NSUInteger)maxNumberOfQueriesToKeep; + +@end + +@interface FLRUCachePolicy : NSObject + +@property(nonatomic, readonly) NSUInteger maxSize; + +- (id)initWithMaxSize:(NSUInteger)maxSize; + +@end + +@interface FNoCachePolicy : NSObject + ++ (FNoCachePolicy *)noCachePolicy; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m new file mode 100644 index 0000000..c1ecd98 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FCachePolicy.m @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCachePolicy.h" + +@interface FLRUCachePolicy () + +@property(nonatomic, readwrite) NSUInteger maxSize; + +@end + +static const NSUInteger kFServerUpdatesBetweenCacheSizeChecks = 1000; +static const NSUInteger kFMaxNumberOfPrunableQueriesToKeep = 1000; +static const float kFPercentOfQueriesToPruneAtOnce = 0.2f; + +@implementation FLRUCachePolicy + +- (id)initWithMaxSize:(NSUInteger)maxSize { + self = [super init]; + if (self != nil) { + self->_maxSize = maxSize; + } + return self; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return cacheSize > self.maxSize || + numTrackedQueries > kFMaxNumberOfPrunableQueriesToKeep; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return serverUpdatesSinceLastCheck > kFServerUpdatesBetweenCacheSizeChecks; +} + +- (float)percentOfQueriesToPruneAtOnce { + return kFPercentOfQueriesToPruneAtOnce; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return kFMaxNumberOfPrunableQueriesToKeep; +} + +@end + +@implementation FNoCachePolicy + ++ (FNoCachePolicy *)noCachePolicy { + return [[FNoCachePolicy alloc] init]; +} + +- (BOOL)shouldPruneCacheWithSize:(NSUInteger)cacheSize + numberOfTrackedQueries:(NSUInteger)numTrackedQueries { + return NO; +} + +- (BOOL)shouldCheckCacheSize:(NSUInteger)serverUpdatesSinceLastCheck { + return NO; +} + +- (float)percentOfQueriesToPruneAtOnce { + return 0; +} + +- (NSUInteger)maxNumberOfQueriesToKeep { + return NSUIntegerMax; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h new file mode 100644 index 0000000..6d32b98 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FPath.h" +#import "FQuerySpec.h" +#import "FStorageEngine.h" + +@class FCacheNode; +@class FTrackedQuery; +@class FPruneForest; +@class FRepoInfo; + +@interface FLevelDBStorageEngine : NSObject + ++ (NSString *)firebaseDir; + +- (id)initWithPath:(NSString *)path; + +- (void)runLegacyMigration:(FRepoInfo *)info; +- (void)purgeEverything; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m new file mode 100644 index 0000000..77a8303 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FLevelDBStorageEngine.m @@ -0,0 +1,990 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FLevelDBStorageEngine.h" + +#import "APLevelDB.h" +#import "FEmptyNode.h" +#import "FPendingPut.h" // For legacy migration +#import "FPruneForest.h" +#import "FQueryParams.h" +#import "FSnapshotUtilities.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import "FWriteRecord.h" +#import + +@interface FLevelDBStorageEngine () + +@property(nonatomic, strong) NSString *basePath; +@property(nonatomic, strong) APLevelDB *writesDB; +@property(nonatomic, strong) APLevelDB *serverCacheDB; + +@end + +// WARNING: If you change this, you need to write a migration script +static NSString *const kFPersistenceVersion = @"1"; + +static NSString *const kFServerDBPath = @"server_data"; +static NSString *const kFWritesDBPath = @"writes"; + +static NSString *const kFUserWriteId = @"id"; +static NSString *const kFUserWritePath = @"path"; +static NSString *const kFUserWriteOverwrite = @"o"; +static NSString *const kFUserWriteMerge = @"m"; + +static NSString *const kFTrackedQueryId = @"id"; +static NSString *const kFTrackedQueryPath = @"path"; +static NSString *const kFTrackedQueryParams = @"p"; +static NSString *const kFTrackedQueryLastUse = @"lu"; +static NSString *const kFTrackedQueryIsComplete = @"c"; +static NSString *const kFTrackedQueryIsActive = @"a"; + +static NSString *const kFServerCachePrefix = @"/server_cache/"; +// '~' is the last non-control character in the ASCII table until 127 +// We wan't the entire range of thing stored in the DB +static NSString *const kFServerCacheRangeEnd = @"/server_cache~"; +static NSString *const kFTrackedQueriesPrefix = @"/tracked_queries/"; +static NSString *const kFTrackedQueryKeysPrefix = @"/tracked_query_keys/"; + +// Failed to load JSON because a valid JSON turns out to be NaN while +// deserializing +static const NSInteger kFNanFailureCode = 3840; + +static NSString *writeRecordKey(NSUInteger writeId) { + return [NSString stringWithFormat:@"%lu", (unsigned long)(writeId)]; +} + +static NSString *serverCacheKey(FPath *path) { + return [NSString stringWithFormat:@"%@%@", kFServerCachePrefix, + ([path toStringWithTrailingSlash])]; +} + +static NSString *trackedQueryKey(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu", kFTrackedQueriesPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKeyPrefix(NSUInteger trackedQueryId) { + return [NSString stringWithFormat:@"%@%lu/", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId]; +} + +static NSString *trackedQueryKeysKey(NSUInteger trackedQueryId, NSString *key) { + return [NSString stringWithFormat:@"%@%lu/%@", kFTrackedQueryKeysPrefix, + (unsigned long)trackedQueryId, key]; +} + +@implementation FLevelDBStorageEngine +#pragma mark - Constructors + +- (id)initWithPath:(NSString *)dbPath { + self = [super init]; + if (self) { + self.basePath = [[FLevelDBStorageEngine firebaseDir] + stringByAppendingPathComponent:dbPath]; + /* For reference: + serverDataDB = [aPersistence createDbByName:@"server_data"]; + FPangolinDB *completenessDb = [aPersistence + createDbByName:@"server_complete"]; + */ + [FLevelDBStorageEngine ensureDir:self.basePath markAsDoNotBackup:YES]; + [self runMigration]; + [self openDatabases]; + } + return self; +} + +- (void)runMigration { + // Currently we're at version 1, so all we need to do is write that to a + // file + NSString *versionFile = + [self.basePath stringByAppendingPathComponent:@"version"]; + NSError *error; + NSString *oldVersion = + [NSString stringWithContentsOfFile:versionFile + encoding:NSUTF8StringEncoding + error:&error]; + if (!oldVersion) { + // This is probably fine, we don't have a version file yet + BOOL success = [kFPersistenceVersion writeToFile:versionFile + atomically:NO + encoding:NSUTF8StringEncoding + error:&error]; + if (!success) { + FFWarn(@"I-RDB076001", @"Failed to write version for database: %@", + error); + } + } else if ([oldVersion isEqualToString:kFPersistenceVersion]) { + // Everythings fine no need for migration + } else { + // If we add more versions in the future, we need to run migration here + [NSException raise:NSInternalInconsistencyException + format:@"Unrecognized database version: %@", oldVersion]; + } +} + +- (void)runLegacyMigration:(FRepoInfo *)info { + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + NSString *firebaseDir = + [documentsDir stringByAppendingPathComponent:@"firebase"]; + NSString *repoHashString = + [NSString stringWithFormat:@"%@_%@", info.host, info.namespace]; + NSString *legacyBaseDir = + [NSString stringWithFormat:@"%@/1/%@/v1", firebaseDir, repoHashString]; + if ([[NSFileManager defaultManager] fileExistsAtPath:legacyBaseDir]) { + FFWarn(@"I-RDB076002", @"Legacy database found, migrating..."); + // We only need to migrate writes + NSError *error = nil; + APLevelDB *writes = [APLevelDB + levelDBWithPath:[legacyBaseDir stringByAppendingPathComponent: + @"outstanding_puts"] + error:&error]; + if (writes != nil) { + __block NSUInteger numberOfWritesRestored = 0; + // Maybe we could use write batches, but what the heck, I'm sure + // it'll go fine :P + [writes enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + id pendingPut = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + if ([pendingPut isKindOfClass:[FPendingPut class]]) { + FPendingPut *put = pendingPut; + id newNode = + [FSnapshotUtilities nodeFrom:put.data + priority:put.priority]; + [self saveUserOverwrite:newNode + atPath:put.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut + isKindOfClass:[FPendingPutPriority class]]) { + // This is for backwards compatibility. Older clients will + // save FPendingPutPriority. New ones will need to read it and + // translate. + FPendingPutPriority *putPriority = pendingPut; + FPath *priorityPath = + [putPriority.path childFromString:@".priority"]; + id newNode = + [FSnapshotUtilities nodeFrom:putPriority.priority + priority:nil]; + [self saveUserOverwrite:newNode + atPath:priorityPath + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else if ([pendingPut isKindOfClass:[FPendingUpdate class]]) { + FPendingUpdate *update = pendingPut; + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:update.data]; + [self saveUserMerge:merge + atPath:update.path + writeId:[key integerValue]]; + numberOfWritesRestored++; + } else { + FFWarn(@"I-RDB076003", + @"Failed to migrate legacy write, meh!"); + } + }]; + FFWarn(@"I-RDB076004", @"Migrated %lu writes", + (unsigned long)numberOfWritesRestored); + [writes close]; + FFWarn(@"I-RDB076005", @"Deleting legacy database..."); + BOOL success = + [[NSFileManager defaultManager] removeItemAtPath:legacyBaseDir + error:&error]; + if (!success) { + FFWarn(@"I-RDB076006", @"Failed to delete legacy database: %@", + error); + } else { + FFWarn(@"I-RDB076007", @"Finished migrating legacy database."); + } + } else { + FFWarn(@"I-RDB076008", @"Failed to migrate old database: %@", + error); + } + } +} + +- (void)openDatabases { + self.serverCacheDB = [self createDB:kFServerDBPath]; + self.writesDB = [self createDB:kFWritesDBPath]; +} + +- (void)purgeDatabase:(NSString *)dbPath { + NSString *path = [self.basePath stringByAppendingPathComponent:dbPath]; + NSError *error; + FFWarn(@"I-RDB076009", @"Deleting database at path %@", path); + BOOL success = [[NSFileManager defaultManager] removeItemAtPath:path + error:&error]; + if (!success) { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to delete database files: %@", error]; + } +} + +- (void)purgeEverything { + [self close]; + [@[ kFServerDBPath, kFWritesDBPath ] + enumerateObjectsUsingBlock:^(NSString *dbPath, NSUInteger idx, + BOOL *stop) { + [self purgeDatabase:dbPath]; + }]; + + [self openDatabases]; +} + +- (void)close { + // autoreleasepool will cause deallocation which will close the DB + @autoreleasepool { + [self.serverCacheDB close]; + self.serverCacheDB = nil; + [self.writesDB close]; + self.writesDB = nil; + } +} + ++ (NSString *)firebaseDir { +#if TARGET_OS_IOS || TARGET_OS_TV + NSArray *dirPaths = NSSearchPathForDirectoriesInDomains( + NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [dirPaths objectAtIndex:0]; + return [documentsDir stringByAppendingPathComponent:@"firebase"]; +#elif TARGET_OS_OSX + return [NSHomeDirectory() stringByAppendingPathComponent:@".firebase"]; +#endif +} + +- (APLevelDB *)createDB:(NSString *)dbName { + NSError *err = nil; + NSString *path = [self.basePath stringByAppendingPathComponent:dbName]; + APLevelDB *db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + FFWarn(@"I-RDB076036", + @"Failed to read database persistence file '%@': %@", dbName, + [err localizedDescription]); + err = nil; + + // Delete the database and try again. + [self purgeDatabase:dbName]; + db = [APLevelDB levelDBWithPath:path error:&err]; + + if (err) { + NSString *reason = [NSString + stringWithFormat:@"Error initializing persistence: %@", + [err description]]; + @throw [NSException + exceptionWithName:@"FirebaseDatabasePersistenceFailure" + reason:reason + userInfo:nil]; + } + } + + return db; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteOverwrite : [node valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user overwrite: %@, (Error: %@)", + write, error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + NSDictionary *write = @{ + kFUserWriteId : @(writeId), + kFUserWritePath : [path toStringWithTrailingSlash], + kFUserWriteMerge : [merge valForExport:YES] + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:write + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize user merge: %@ (Error: %@)", write, + error); + [self.writesDB setData:data forKey:writeRecordKey(writeId)]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.writesDB removeKey:writeRecordKey(writeId)]; +} + +- (void)removeAllUserWrites { + __block NSUInteger count = 0; + NSDate *start = [NSDate date]; + id batch = [self.writesDB beginWriteBatch]; + [self.writesDB enumerateKeys:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + count++; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076010", @"Failed to remove all users writes on disk!"); + } else { + FFDebug(@"I-RDB076011", @"Removed %lu writes in %fms", + (unsigned long)count, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSArray *)userWrites { + NSDate *date = [NSDate date]; + NSMutableArray *writes = [NSMutableArray array]; + [self.writesDB enumerateKeysAndValuesAsData:^(NSString *key, NSData *data, + BOOL *stop) { + NSError *error = nil; + NSDictionary *writeJSON = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (writeJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076012", + @"Failed to deserialize write (%@), likely because of out " + @"of range doubles (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076013", @"Removing failed write with key %@", key); + [self.writesDB removeKey:key]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialize write: %@", error]; + } + } else { + NSInteger writeId = + ((NSNumber *)writeJSON[kFUserWriteId]).integerValue; + FPath *path = [FPath pathWithString:writeJSON[kFUserWritePath]]; + FWriteRecord *writeRecord; + if (writeJSON[kFUserWriteMerge] != nil) { + // It's a merge + FCompoundWrite *merge = [FCompoundWrite + compoundWriteWithValueDictionary:writeJSON[kFUserWriteMerge]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + merge:merge + writeId:writeId]; + } else { + // It's an overwrite + NSAssert(writeJSON[kFUserWriteOverwrite] != nil, + @"Persisted write did not contain merge or overwrite!"); + id node = + [FSnapshotUtilities nodeFrom:writeJSON[kFUserWriteOverwrite]]; + writeRecord = [[FWriteRecord alloc] initWithPath:path + overwrite:node + writeId:writeId + visible:YES]; + } + [writes addObject:writeRecord]; + } + }]; + // Make sure writes are sorted + [writes sortUsingComparator:^NSComparisonResult(FWriteRecord *one, + FWriteRecord *two) { + if (one.writeId < two.writeId) { + return NSOrderedAscending; + } else if (one.writeId > two.writeId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + FFDebug(@"I-RDB076014", @"Loaded %lu writes in %fms", + (unsigned long)writes.count, [date timeIntervalSinceNow] * -1000); + return writes; +} + +- (id)serverCacheAtPath:(FPath *)path { + NSDate *start = [NSDate date]; + id data = [self internalNestedDataForPath:path]; + id node = [FSnapshotUtilities nodeFrom:data]; + FFDebug(@"I-RDB076015", @"Loaded node with %d children at %@ in %fms", + [node numChildren], path, [start timeIntervalSinceNow] * -1000); + return node; +} + +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block id node = [FEmptyNode emptyNode]; + [keys enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + id data = [self internalNestedDataForPath:[path childFromString:key]]; + node = [node updateImmediateChild:key + withNewChild:[FSnapshotUtilities nodeFrom:data]]; + }]; + FFDebug(@"I-RDB076016", + @"Loaded node with %d children for %lu keys at %@ in %fms", + [node numChildren], (unsigned long)keys.count, path, + [start timeIntervalSinceNow] * -1000); + return node; +} + +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + __block NSUInteger counter = 0; + if (merge) { + // remove any children that exist + [node enumerateChildrenUsingBlock:^(NSString *childKey, + id childNode, BOOL *stop) { + FPath *childPath = [path childFromString:childKey]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:childNode + atPath:childPath + batch:batch + counter:&counter]; + }]; + } else { + // remove everything + [self removeAllWithPrefix:serverCacheKey(path) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node atPath:path batch:batch counter:&counter]; + } + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076017", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076018", @"Saved %lu leaf nodes for overwrite in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + NSDate *start = [NSDate date]; + __block NSUInteger counter = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + // Remove any leaf nodes that might be higher up + [self removeAllLeafNodesOnPath:path batch:batch]; + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + FPath *childPath = [path child:relativePath]; + [self removeAllWithPrefix:serverCacheKey(childPath) + batch:batch + database:self.serverCacheDB]; + [self saveNodeInternal:node + atPath:childPath + batch:batch + counter:&counter]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076019", @"Failed to update server cache on disk!"); + } else { + FFDebug(@"I-RDB076020", @"Saved %lu leaf nodes for merge in %fms", + (unsigned long)counter, [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveNodeInternal:(id)node + atPath:(FPath *)path + batch:(id)batch + counter:(NSUInteger *)counter { + id data = [node valForExport:YES]; + if (data != nil && ![data isKindOfClass:[NSNull class]]) { + [self internalSetNestedData:data + forKey:serverCacheKey(path) + withBatch:batch + counter:counter]; + } +} + +- (NSUInteger)serverCacheEstimatedSizeInBytes { + // Use the exact size, because for pruning the approximate size can lead to + // weird situations where we prune everything because no compaction is ever + // run + return [self.serverCacheDB exactSizeFrom:kFServerCachePrefix + to:kFServerCacheRangeEnd]; +} + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path { + // TODO: be more intelligent, don't scan entire database... + + __block NSUInteger pruned = 0; + __block NSUInteger kept = 0; + NSDate *start = [NSDate date]; + + NSString *prefix = serverCacheKey(path); + id batch = [self.serverCacheDB beginWriteBatch]; + + [self.serverCacheDB + enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *dbKey, BOOL *stop) { + NSString *pathStr = + [dbKey substringFromIndex:prefix.length]; + FPath *relativePath = [[FPath alloc] initWith:pathStr]; + if ([pruneForest shouldPruneUnkeptDescendantsAtPath: + relativePath]) { + pruned++; + [batch removeKey:dbKey]; + } else { + kept++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076021", @"Failed to prune cache on disk!"); + } else { + FFDebug(@"I-RDB076022", @"Pruned %lu paths, kept %lu paths in %fms", + (unsigned long)pruned, (unsigned long)kept, + [start timeIntervalSinceNow] * -1000); + } +} + +#pragma mark - Tracked Queries + +- (NSArray *)loadTrackedQueries { + NSDate *date = [NSDate date]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + [self.serverCacheDB + enumerateKeysWithPrefix:kFTrackedQueriesPrefix + asData:^(NSString *key, NSData *data, BOOL *stop) { + NSError *error = nil; + NSDictionary *queryJSON = + [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&error]; + if (queryJSON == nil) { + if (error.code == kFNanFailureCode) { + FFWarn( + @"I-RDB076023", + @"Failed to deserialize tracked query " + @"(%@), likely because of out of range " + @"doubles (Error: %@)", + [[NSString alloc] + initWithData:data + encoding:NSUTF8StringEncoding], + error); + FFWarn(@"I-RDB076024", + @"Removing failed tracked query with " + @"key %@", + key); + [self.serverCacheDB removeKey:key]; + } else { + [NSException + raise:NSInternalInconsistencyException + format:@"Failed to deserialize tracked " + @"query: %@", + error]; + } + } else { + NSUInteger queryId = + ((NSNumber *)queryJSON[kFTrackedQueryId]) + .unsignedIntegerValue; + FPath *path = + [FPath pathWithString: + queryJSON[kFTrackedQueryPath]]; + FQueryParams *params = [FQueryParams + fromQueryObject:queryJSON + [kFTrackedQueryParams]]; + FQuerySpec *query = + [[FQuerySpec alloc] initWithPath:path + params:params]; + BOOL isComplete = + [queryJSON[kFTrackedQueryIsComplete] + boolValue]; + BOOL isActive = + [queryJSON[kFTrackedQueryIsActive] + boolValue]; + NSTimeInterval lastUse = + [queryJSON[kFTrackedQueryLastUse] + doubleValue]; + + FTrackedQuery *trackedQuery = + [[FTrackedQuery alloc] + initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:isComplete]; + + [trackedQueries addObject:trackedQuery]; + } + }]; + FFDebug(@"I-RDB076025", @"Loaded %lu tracked queries in %fms", + (unsigned long)trackedQueries.count, + [date timeIntervalSinceNow] * -1000); + return trackedQueries; +} + +- (void)removeTrackedQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [batch removeKey:trackedQueryKey(queryId)]; + __block NSUInteger keyCount = 0; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + keyCount++; + }]; + + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076026", @"Failed to remove tracked query on disk!"); + } else { + FFDebug(@"I-RDB076027", + @"Removed query with id %lu (and removed %lu keys) in %fms", + (unsigned long)queryId, (unsigned long)keyCount, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)saveTrackedQuery:(FTrackedQuery *)query { + NSDate *start = [NSDate date]; + NSDictionary *trackedQuery = @{ + kFTrackedQueryId : @(query.queryId), + kFTrackedQueryPath : [query.query.path toStringWithTrailingSlash], + kFTrackedQueryParams : [query.query.params wireProtocolParams], + kFTrackedQueryLastUse : @(query.lastUse), + kFTrackedQueryIsComplete : @(query.isComplete), + kFTrackedQueryIsActive : @(query.isActive) + }; + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:trackedQuery + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize tracked query (Error: %@)", error); + [self.serverCacheDB setData:data forKey:trackedQueryKey(query.queryId)]; + FFDebug(@"I-RDB076028", @"Saved tracked query %lu in %fms", + (unsigned long)query.queryId, [start timeIntervalSinceNow] * -1000); +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + __block NSUInteger removed = 0; + __block NSUInteger added = 0; + id batch = [self.serverCacheDB beginWriteBatch]; + NSMutableSet *seenKeys = [NSMutableSet set]; + // First, delete any keys that might be stored and are not part of the + // current keys + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + if ([keys containsObject:actualKey]) { + // Already in DB + [seenKeys addObject:actualKey]; + } else { + // Not part of set, delete key + [batch removeKey:dbKey]; + removed++; + } + }]; + + // Next add any keys that are missing in the database + [keys enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + if (![seenKeys containsObject:childKey]) { + [batch setString:childKey + forKey:trackedQueryKeysKey(queryId, childKey)]; + added++; + } + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076029", @"Failed to set tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076030", + @"Set %lu tracked keys (%lu added, %lu removed) for query %lu " + @"in %fms", + (unsigned long)keys.count, (unsigned long)added, + (unsigned long)removed, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + } +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + id batch = [self.serverCacheDB beginWriteBatch]; + [removed enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:trackedQueryKeysKey(queryId, key)]; + }]; + [added enumerateObjectsUsingBlock:^(NSString *key, BOOL *stop) { + [batch setString:key forKey:trackedQueryKeysKey(queryId, key)]; + }]; + BOOL success = [batch commit]; + if (!success) { + FFWarn(@"I-RDB076031", @"Failed to update tracked queries on disk!"); + } else { + FFDebug(@"I-RDB076032", + @"Added %lu tracked keys, removed %lu for query %lu in %fms", + (unsigned long)added.count, (unsigned long)removed.count, + (unsigned long)queryId, [start timeIntervalSinceNow] * -1000); + } +} + +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId { + NSDate *start = [NSDate date]; + NSMutableSet *set = [NSMutableSet set]; + [self.serverCacheDB + enumerateKeysWithPrefix:trackedQueryKeysKeyPrefix(queryId) + asStrings:^(NSString *dbKey, NSString *actualKey, + BOOL *stop) { + [set addObject:actualKey]; + }]; + FFDebug(@"I-RDB076033", @"Loaded %lu tracked keys for query %lu in %fms", + (unsigned long)set.count, (unsigned long)queryId, + [start timeIntervalSinceNow] * -1000); + return set; +} + +#pragma mark - Internal methods + +- (void)removeAllLeafNodesOnPath:(FPath *)path + batch:(id)batch { + while (!path.isEmpty) { + [batch removeKey:serverCacheKey(path)]; + path = [path parent]; + } + // Make sure to delete any nodes at the root + [batch removeKey:serverCacheKey([FPath empty])]; +} + +- (void)removeAllWithPrefix:(NSString *)prefix + batch:(id)batch + database:(APLevelDB *)database { + assert(prefix != nil); + + [database enumerateKeysWithPrefix:prefix + usingBlock:^(NSString *key, BOOL *stop) { + [batch removeKey:key]; + }]; +} + +#pragma mark - Internal helper methods + +- (void)internalSetNestedData:(id)value + forKey:(NSString *)key + withBatch:(id)batch + counter:(NSUInteger *)counter { + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictionary = value; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id childKey, id obj, + BOOL *stop) { + assert(obj != nil); + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", key, childKey]; + [self internalSetNestedData:obj + forKey:childPath + withBatch:batch + counter:counter]; + }]; + } else { + NSData *data = [self serializePrimitive:value]; + [batch setData:data forKey:key]; + (*counter)++; + } +} + +- (id)internalNestedDataForPath:(FPath *)path { + NSAssert(path != nil, @"Path was nil!"); + + NSString *baseKey = serverCacheKey(path); + + // HACK to make sure iter is freed now to avoid race conditions (if self.db + // is deleted before iter, you get an access violation). + @autoreleasepool { + APLevelDBIterator *iter = + [APLevelDBIterator iteratorWithLevelDB:self.serverCacheDB]; + + [iter seekToKey:baseKey]; + if (iter.key == nil || ![iter.key hasPrefix:baseKey]) { + // No data. + return nil; + } else { + return [self internalNestedDataFromIterator:iter + andKeyPrefix:baseKey]; + } + } +} + +- (id)internalNestedDataFromIterator:(APLevelDBIterator *)iterator + andKeyPrefix:(NSString *)prefix { + NSString *key = iterator.key; + + if ([key isEqualToString:prefix]) { + id result = [self deserializePrimitive:iterator.valueAsData]; + [iterator nextKey]; + return result; + } else { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + while (key != nil && [key hasPrefix:prefix]) { + NSString *relativePath = [key substringFromIndex:prefix.length]; + NSArray *pathPieces = + [relativePath componentsSeparatedByString:@"/"]; + assert(pathPieces.count > 0); + NSString *childName = pathPieces[0]; + NSString *childPath = + [NSString stringWithFormat:@"%@%@/", prefix, childName]; + id childValue = [self internalNestedDataFromIterator:iterator + andKeyPrefix:childPath]; + [dict setValue:childValue forKey:childName]; + + key = iterator.key; + } + return dict; + } +} + +- (NSData *)serializePrimitive:(id)value { + // HACK: The built-in serialization only works on dicts and arrays. So we + // create an array and then strip off the leading / trailing byte (the [ and + // ]). + NSError *error = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:@[ value ] + options:0 + error:&error]; + NSAssert(data, @"Failed to serialize primitive: %@", error); + + return [data subdataWithRange:NSMakeRange(1, data.length - 2)]; +} + +- (id)fixDoubleParsing:(id)value + __attribute__((no_sanitize("float-cast-overflow"))) { + if ([value isKindOfClass:[NSDecimalNumber class]]) { + // In case the value is an NSDecimalNumber, we may be dealing with + // precisions that are higher than what can be represented in a double. + // In this case it does not suffice to check for integral numbers by + // casting the [value doubleValue] to an int64_t, because this will + // cause the compared values to be rounded to double precision. + // Coupled with a bug in [NSDecimalNumber longLongValue] that triggers + // when converting values with high precision, this would cause + // values of high precision, but with an integral 'doubleValue' + // representation to be converted to bogus values. + // A radar for the NSDecimalNumber issue can be found here: + // http://www.openradar.me/radar?id=5007005597040640 + // Consider the NSDecimalNumber value: 999.9999999999999487 + // This number has a 'doubleValue' of 1000. Using the previous version + // of this method would cause the value to be interpreted to be integral + // and then the resulting value would be based on the longLongValue + // which due to the NSDecimalNumber issue would turn out as -844. + // By using NSDecimal logic to test for integral values, + // 999.9999999999999487 will not be considered integral, and instead + // of triggering the 'longLongValue' issue, it will be returned as + // the 'doubleValue' representation (1000). + // Please note, that even without the NSDecimalNumber issue, the + // 'correct' longLongValue of 999.9999999999999487 is 999 and not 1000, + // so the previous code would cause issues even without the bug + // referenced in the radar. + NSDecimal original = [(NSDecimalNumber *)value decimalValue]; + NSDecimal rounded; + NSDecimalRound(&rounded, &original, 0, NSRoundPlain); + if (NSDecimalCompare(&original, &rounded) != NSOrderedSame) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } else if ([value isKindOfClass:[NSNumber class]]) { + // The parser for double values in JSONSerialization at the root takes + // some short-cuts and delivers wrong results (wrong rounding) for some + // double values, including 2.47. Because we use the exact bytes for + // hashing on the server this will lead to hash mismatches. The parser + // of NSNumber seems to be more in line with what the server expects, so + // we use that here + CFNumberType type = CFNumberGetType((CFNumberRef)value); + if (type == kCFNumberDoubleType || type == kCFNumberFloatType) { + // The NSJSON parser returns all numbers as double values, even + // those that contain no exponent. To make sure that the String + // conversion below doesn't unexpectedly reduce precision, we make + // sure that our number is indeed not an integer. + if ((double)(int64_t)[value doubleValue] != [value doubleValue]) { + NSString *doubleString = [value stringValue]; + return [NSNumber numberWithDouble:[doubleString doubleValue]]; + } else { + return [NSNumber numberWithLongLong:[value longLongValue]]; + } + } + } + return value; +} + +- (id)deserializePrimitive:(NSData *)data { + NSError *error = nil; + id result = + [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingAllowFragments + error:&error]; + if (result != nil) { + return [self fixDoubleParsing:result]; + } else { + if (error.code == kFNanFailureCode) { + FFWarn(@"I-RDB076034", + @"Failed to load primitive %@, likely because doubles where " + @"out of range (Error: %@)", + [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding], + error); + return [NSNull null]; + } else { + [NSException raise:NSInternalInconsistencyException + format:@"Failed to deserialiaze primitive: %@", error]; + return nil; + } + } +} + ++ (void)ensureDir:(NSString *)path markAsDoNotBackup:(BOOL)markAsDoNotBackup { + NSError *error; + BOOL success = + [[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (!success) { + @throw [NSException + exceptionWithName:@"FailedToCreatePersistenceDir" + reason:@"Failed to create persistence directory." + userInfo:@{@"path" : path}]; + } + + if (markAsDoNotBackup) { + NSURL *firebaseDirURL = [NSURL fileURLWithPath:path]; + success = [firebaseDirURL setResourceValue:@YES + forKey:NSURLIsExcludedFromBackupKey + error:&error]; + if (!success) { + FFWarn( + @"I-RDB076035", + @"Failed to mark firebase database folder as do not backup: %@", + error); + [NSException raise:@"Error marking as do not backup" + format:@"Failed to mark folder %@ as do not backup", + firebaseDirURL]; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h new file mode 100644 index 0000000..602bf8c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +// These are all legacy classes and are used to migrate older persistence data +// base to newer ones These classes should not be used in newer code + +@interface FPendingPut : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id data; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end + +@interface FPendingPutPriority : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; + +@end + +@interface FPendingUpdate : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) NSDictionary *data; + +- (id)initWithPath:(FPath *)aPath andData:(NSDictionary *)aData; +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m new file mode 100644 index 0000000..c519599 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPendingPut.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPendingPut.h" + +@implementation FPendingPut + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingPutPriority + +@synthesize path; +@synthesize priority; + +- (id)initWithPath:(FPath *)aPath andPriority:(id)aPriority { + self = [super init]; + if (self) { + self.path = aPath; + self.priority = aPriority; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.priority forKey:@"priority"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.priority = [aDecoder decodeObjectForKey:@"priority"]; + } + return self; +} + +@end + +@implementation FPendingUpdate + +@synthesize path; +@synthesize data; + +- (id)initWithPath:(FPath *)aPath andData:(id)aData { + self = [super init]; + if (self) { + self.path = aPath; + self.data = aData; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:[self.path description] forKey:@"path"]; + [aCoder encodeObject:self.data forKey:@"data"]; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + self.path = + [[FPath alloc] initWith:[aDecoder decodeObjectForKey:@"path"]]; + self.data = [aDecoder decodeObjectForKey:@"data"]; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h new file mode 100644 index 0000000..681c56d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FCacheNode.h" +#import "FCachePolicy.h" +#import "FCompoundWrite.h" +#import "FNode.h" +#import "FQuerySpec.h" +#import "FRepoInfo.h" +#import "FStorageEngine.h" + +@interface FPersistenceManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy; +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)spec; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path; +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path; + +- (void)setQueryComplete:(FQuerySpec *)spec; +- (void)setQueryActive:(FQuerySpec *)spec; +- (void)setQueryInactive:(FQuerySpec *)spec; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m new file mode 100644 index 0000000..8924802 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPersistenceManager.m @@ -0,0 +1,231 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPersistenceManager.h" +#import "FCacheNode.h" +#import "FClock.h" +#import "FIndexedNode.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FTrackedQueryManager.h" +#import "FUtilities.h" +#import + +@interface FPersistenceManager () + +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id cachePolicy; +@property(nonatomic, strong) FTrackedQueryManager *trackedQueryManager; +@property(nonatomic) NSUInteger serverCacheUpdatesSinceLastPruneCheck; + +@end + +@implementation FPersistenceManager + +- (id)initWithStorageEngine:(id)storageEngine + cachePolicy:(id)cachePolicy { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_cachePolicy = cachePolicy; + self->_trackedQueryManager = [[FTrackedQueryManager alloc] + initWithStorageEngine:self.storageEngine + clock:[FSystemClock clock]]; + } + return self; +} + +- (void)close { + [self.storageEngine close]; + self.storageEngine = nil; + self.trackedQueryManager = nil; +} + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserOverwrite:node atPath:path writeId:writeId]; +} + +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId { + [self.storageEngine saveUserMerge:merge atPath:path writeId:writeId]; +} + +- (void)removeUserWrite:(NSUInteger)writeId { + [self.storageEngine removeUserWrite:writeId]; +} + +- (void)removeAllUserWrites { + [self.storageEngine removeAllUserWrites]; +} + +- (NSArray *)userWrites { + return [self.storageEngine userWrites]; +} + +- (FCacheNode *)serverCacheForQuery:(FQuerySpec *)query { + NSSet *trackedKeys; + BOOL complete; + // TODO[offline]: Should we use trackedKeys to find out if this location is + // a child of a complete query? + if ([self.trackedQueryManager isQueryComplete:query]) { + complete = YES; + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + if (!query.loadsAllData && trackedQuery.isComplete) { + trackedKeys = [self.storageEngine + trackedQueryKeysForQuery:trackedQuery.queryId]; + } else { + trackedKeys = nil; + } + } else { + complete = NO; + trackedKeys = + [self.trackedQueryManager knownCompleteChildrenAtPath:query.path]; + } + + id node; + if (trackedKeys != nil) { + node = [self.storageEngine serverCacheForKeys:trackedKeys + atPath:query.path]; + } else { + node = [self.storageEngine serverCacheAtPath:query.path]; + } + + FIndexedNode *indexedNode = [FIndexedNode indexedNodeWithNode:node + index:query.index]; + return [[FCacheNode alloc] initWithIndexedNode:indexedNode + isFullyInitialized:complete + isFiltered:(trackedKeys != nil)]; +} + +- (void)updateServerCacheWithNode:(id)node forQuery:(FQuerySpec *)query { + BOOL merge = !query.loadsAllData; + [self.storageEngine updateServerCache:node atPath:query.path merge:merge]; + [self setQueryComplete:query]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge + atPath:(FPath *)path { + [self.storageEngine updateServerCacheWithMerge:merge atPath:path]; + [self doPruneCheckAfterServerUpdate]; +} + +- (void)applyUserMerge:(FCompoundWrite *)merge + toServerCacheAtPath:(FPath *)path { + // TODO[offline]: rework this to be more efficient + [merge enumerateWrites:^(FPath *relativePath, id node, BOOL *stop) { + [self applyUserWrite:node toServerCacheAtPath:[path child:relativePath]]; + }]; +} + +- (void)applyUserWrite:(id)write toServerCacheAtPath:(FPath *)path { + // This is a hack to guess whether we already cached this because we got a + // server data update for this write via an existing active default query. + // If we didn't, then we'll manually cache this and add a tracked query to + // mark it complete and keep it cached. Unfortunately this is just a guess + // and it's possible that we *did* get an update (e.g. via a filtered query) + // and by overwriting the cache here, we'll actually store an incorrect + // value (e.g. in the case that we wrote a ServerValue.TIMESTAMP and the + // server resolved it to a different value). + // TODO[offline]: Consider reworking. + if (![self.trackedQueryManager hasActiveDefaultQueryAtPath:path]) { + [self.storageEngine updateServerCache:write atPath:path merge:NO]; + [self.trackedQueryManager ensureCompleteTrackedQueryAtPath:path]; + } +} + +- (void)setQueryComplete:(FQuerySpec *)query { + if (query.loadsAllData) { + [self.trackedQueryManager setQueriesCompleteAtPath:query.path]; + } else { + [self.trackedQueryManager setQueryComplete:query]; + } +} + +- (void)setQueryActive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryActive:spec]; +} + +- (void)setQueryInactive:(FQuerySpec *)spec { + [self.trackedQueryManager setQueryInactive:spec]; +} + +- (void)doPruneCheckAfterServerUpdate { + self.serverCacheUpdatesSinceLastPruneCheck++; + if ([self.cachePolicy + shouldCheckCacheSize:self.serverCacheUpdatesSinceLastPruneCheck]) { + FFDebug(@"I-RDB078001", @"Reached prune check threshold. Checking..."); + NSDate *date = [NSDate date]; + self.serverCacheUpdatesSinceLastPruneCheck = 0; + BOOL canPrune = YES; + NSUInteger cacheSize = + [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078002", @"Server cache size: %lu", + (unsigned long)cacheSize); + while (canPrune && + [self.cachePolicy + shouldPruneCacheWithSize:cacheSize + numberOfTrackedQueries:self.trackedQueryManager + .numberOfPrunableQueries]) { + FPruneForest *pruneForest = + [self.trackedQueryManager pruneOldQueries:self.cachePolicy]; + if (pruneForest.prunesAnything) { + [self.storageEngine pruneCache:pruneForest + atPath:[FPath empty]]; + } else { + canPrune = NO; + } + cacheSize = [self.storageEngine serverCacheEstimatedSizeInBytes]; + FFDebug(@"I-RDB078003", @"Cache size after pruning: %lu", + (unsigned long)cacheSize); + } + FFDebug(@"I-RDB078004", @"Pruning round took %fms", + [date timeIntervalSinceNow] * -1000); + } +} + +- (void)setTrackedQueryKeys:(NSSet *)keys forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine setTrackedQueryKeys:keys + forQueryId:trackedQuery.queryId]; +} + +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData, + @"We should only track keys for filtered queries"); + FTrackedQuery *trackedQuery = + [self.trackedQueryManager findTrackedQuery:query]; + NSAssert(trackedQuery.isActive, + @"We only expect tracked keys for currently-active queries."); + [self.storageEngine + updateTrackedQueryKeysWithAddedKeys:added + removedKeys:removed + forQueryId:trackedQuery.queryId]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h new file mode 100644 index 0000000..9e77217 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FPruneForest : NSObject + ++ (FPruneForest *)empty; + +- (BOOL)prunesAnything; +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path; +- (BOOL)shouldKeepPath:(FPath *)path; +- (BOOL)affectsPath:(FPath *)path; +- (FPruneForest *)child:(NSString *)childKey; +- (FPruneForest *)childAtPath:(FPath *)childKey; +- (FPruneForest *)prunePath:(FPath *)path; +- (FPruneForest *)keepPath:(FPath *)path; +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path; +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path; + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *path))block; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m new file mode 100644 index 0000000..e795c69 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FPruneForest.m @@ -0,0 +1,194 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPruneForest.h" + +#import "FImmutableTree.h" + +@interface FPruneForest () + +@property(nonatomic, strong) FImmutableTree *pruneForest; + +@end + +@implementation FPruneForest + +static BOOL (^kFPrunePredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return [pruneValue boolValue]; +}; + +static BOOL (^kFKeepPredicate)(id) = ^BOOL(NSNumber *pruneValue) { + return ![pruneValue boolValue]; +}; + ++ (FImmutableTree *)pruneTree { + static dispatch_once_t onceToken; + static FImmutableTree *pruneTree; + dispatch_once(&onceToken, ^{ + pruneTree = [[FImmutableTree alloc] initWithValue:@YES]; + }); + return pruneTree; +} + ++ (FImmutableTree *)keepTree { + static dispatch_once_t onceToken; + static FImmutableTree *keepTree; + dispatch_once(&onceToken, ^{ + keepTree = [[FImmutableTree alloc] initWithValue:@NO]; + }); + return keepTree; +} + +- (id)initWithForest:(FImmutableTree *)tree { + self = [super init]; + if (self != nil) { + self->_pruneForest = tree; + } + return self; +} + ++ (FPruneForest *)empty { + static dispatch_once_t onceToken; + static FPruneForest *forest; + dispatch_once(&onceToken, ^{ + forest = [[FPruneForest alloc] initWithForest:[FImmutableTree empty]]; + }); + return forest; +} + +- (BOOL)prunesAnything { + return [self.pruneForest containsValueMatching:kFPrunePredicate]; +} + +- (BOOL)shouldPruneUnkeptDescendantsAtPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && [shouldPrune boolValue]; +} + +- (BOOL)shouldKeepPath:(FPath *)path { + NSNumber *shouldPrune = [self.pruneForest leafMostValueOnPath:path]; + return shouldPrune != nil && ![shouldPrune boolValue]; +} + +- (BOOL)affectsPath:(FPath *)path { + return [self.pruneForest rootMostValueOnPath:path] != nil || + ![[self.pruneForest subtreeAtPath:path] isEmpty]; +} + +- (FPruneForest *)child:(NSString *)childKey { + FImmutableTree *childPruneForest = [self.pruneForest.children get:childKey]; + if (childPruneForest == nil) { + if (self.pruneForest.value != nil) { + childPruneForest = [self.pruneForest.value boolValue] + ? [FPruneForest pruneTree] + : [FPruneForest keepTree]; + } else { + childPruneForest = [FImmutableTree empty]; + } + } else { + if (childPruneForest.value == nil && self.pruneForest.value != nil) { + childPruneForest = [childPruneForest setValue:self.pruneForest.value + atPath:[FPath empty]]; + } + } + return [[FPruneForest alloc] initWithForest:childPruneForest]; +} + +- (FPruneForest *)childAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + return [[self child:path.getFront] childAtPath:[path popFront]]; + } +} + +- (FPruneForest *)prunePath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest pruneTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + FImmutableTree *newPruneForest = + [self.pruneForest setTree:[FPruneForest keepTree] atPath:path]; + return [[FPruneForest alloc] initWithForest:newPruneForest]; + } +} + +- (FPruneForest *)keepAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + // This path will already be kept + return self; + } else { + return [self setPruneValue:[FPruneForest keepTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)pruneAll:(NSSet *)children atPath:(FPath *)path { + if ([self.pruneForest rootMostValueOnPath:path matching:kFKeepPredicate]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't prune path that was kept previously!"]; + } + if ([self.pruneForest rootMostValueOnPath:path matching:kFPrunePredicate]) { + // This path will already be pruned + return self; + } else { + return [self setPruneValue:[FPruneForest pruneTree] + forAll:children + atPath:path]; + } +} + +- (FPruneForest *)setPruneValue:(FImmutableTree *)pruneValue + forAll:(NSSet *)children + atPath:(FPath *)path { + FImmutableTree *subtree = [self.pruneForest subtreeAtPath:path]; + __block FImmutableSortedDictionary *childrenDictionary = subtree.children; + [children enumerateObjectsUsingBlock:^(NSString *childKey, BOOL *stop) { + childrenDictionary = [childrenDictionary insertKey:childKey + withValue:pruneValue]; + }]; + FImmutableTree *newSubtree = + [[FImmutableTree alloc] initWithValue:subtree.value + children:childrenDictionary]; + return [[FPruneForest alloc] + initWithForest:[self.pruneForest setTree:newSubtree atPath:path]]; +} + +- (void)enumarateKeptNodesUsingBlock:(void (^)(FPath *))block { + [self.pruneForest forEach:^(FPath *path, id value) { + if (value != nil && ![value boolValue]) { + block(path); + } + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h new file mode 100644 index 0000000..5f418b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FStorageEngine.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FNode; +@class FPruneForest; +@class FPath; +@class FCompoundWrite; +@class FQuerySpec; +@class FTrackedQuery; + +@protocol FStorageEngine + +- (void)close; + +- (void)saveUserOverwrite:(id)node + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)saveUserMerge:(FCompoundWrite *)merge + atPath:(FPath *)path + writeId:(NSUInteger)writeId; +- (void)removeUserWrite:(NSUInteger)writeId; +- (void)removeAllUserWrites; +- (NSArray *)userWrites; + +- (id)serverCacheAtPath:(FPath *)path; +- (id)serverCacheForKeys:(NSSet *)keys atPath:(FPath *)path; +- (void)updateServerCache:(id)node + atPath:(FPath *)path + merge:(BOOL)merge; +- (void)updateServerCacheWithMerge:(FCompoundWrite *)merge atPath:(FPath *)path; +- (NSUInteger)serverCacheEstimatedSizeInBytes; + +- (void)pruneCache:(FPruneForest *)pruneForest atPath:(FPath *)path; + +- (NSArray *)loadTrackedQueries; +- (void)removeTrackedQuery:(NSUInteger)queryId; +- (void)saveTrackedQuery:(FTrackedQuery *)query; + +- (void)setTrackedQueryKeys:(NSSet *)keys forQueryId:(NSUInteger)queryId; +- (void)updateTrackedQueryKeysWithAddedKeys:(NSSet *)added + removedKeys:(NSSet *)removed + forQueryId:(NSUInteger)queryId; +- (NSSet *)trackedQueryKeysForQuery:(NSUInteger)queryId; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h new file mode 100644 index 0000000..7413816 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FQuerySpec; + +@interface FTrackedQuery : NSObject + +@property(nonatomic, readonly) NSUInteger queryId; +@property(nonatomic, strong, readonly) FQuerySpec *query; +@property(nonatomic, readonly) NSTimeInterval lastUse; +@property(nonatomic, readonly) BOOL isComplete; +@property(nonatomic, readonly) BOOL isActive; + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive; +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete; + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse; +- (FTrackedQuery *)setComplete; +- (FTrackedQuery *)setActiveState:(BOOL)isActive; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m new file mode 100644 index 0000000..6ca7ec0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQuery.m @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQuery.h" + +#import "FQuerySpec.h" + +@interface FTrackedQuery () + +@property(nonatomic, readwrite) NSUInteger queryId; +@property(nonatomic, strong, readwrite) FQuerySpec *query; +@property(nonatomic, readwrite) NSTimeInterval lastUse; +@property(nonatomic, readwrite) BOOL isComplete; +@property(nonatomic, readwrite) BOOL isActive; + +@end + +@implementation FTrackedQuery + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive + isComplete:(BOOL)isComplete { + self = [super init]; + if (self != nil) { + self->_queryId = queryId; + self->_query = query; + self->_lastUse = lastUse; + self->_isComplete = isComplete; + self->_isActive = isActive; + } + return self; +} + +- (id)initWithId:(NSUInteger)queryId + query:(FQuerySpec *)query + lastUse:(NSTimeInterval)lastUse + isActive:(BOOL)isActive { + return [self initWithId:queryId + query:query + lastUse:lastUse + isActive:isActive + isComplete:NO]; +} + +- (FTrackedQuery *)updateLastUse:(NSTimeInterval)lastUse { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:lastUse + isActive:self.isActive + isComplete:self.isComplete]; +} + +- (FTrackedQuery *)setComplete { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:self.isActive + isComplete:YES]; +} + +- (FTrackedQuery *)setActiveState:(BOOL)isActive { + return [[FTrackedQuery alloc] initWithId:self.queryId + query:self.query + lastUse:self.lastUse + isActive:isActive + isComplete:self.isComplete]; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FTrackedQuery class]]) { + return NO; + } + FTrackedQuery *other = (FTrackedQuery *)object; + if (self.queryId != other.queryId) + return NO; + if (self.query != other.query && ![self.query isEqual:other.query]) + return NO; + if (self.lastUse != other.lastUse) + return NO; + if (self.isComplete != other.isComplete) + return NO; + if (self.isActive != other.isActive) + return NO; + + return YES; +} + +- (NSUInteger)hash { + NSUInteger hash = self.queryId; + hash = hash * 31 + self.query.hash; + hash = hash * 31 + (self.isActive ? 1 : 0); + hash = hash * 31 + (NSUInteger)self.lastUse; + hash = hash * 31 + (self.isComplete ? 1 : 0); + hash = hash * 31 + (self.isActive ? 1 : 0); + return hash; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h new file mode 100644 index 0000000..cd7d5a1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.h @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FStorageEngine; +@protocol FClock; +@protocol FCachePolicy; +@class FQuerySpec; +@class FPath; +@class FTrackedQuery; +@class FPruneForest; + +@interface FTrackedQueryManager : NSObject + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock; + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query; + +- (BOOL)isQueryComplete:(FQuerySpec *)query; + +- (void)removeTrackedQuery:(FQuerySpec *)query; +- (void)setQueryComplete:(FQuerySpec *)query; +- (void)setQueriesCompleteAtPath:(FPath *)path; +- (void)setQueryActive:(FQuerySpec *)query; +- (void)setQueryInactive:(FQuerySpec *)query; + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path; +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path; + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy; +- (NSUInteger)numberOfPrunableQueries; +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path; + +// For testing +- (void)verifyCache; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m new file mode 100644 index 0000000..26accaf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Persistence/FTrackedQueryManager.m @@ -0,0 +1,375 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTrackedQueryManager.h" +#import "FCachePolicy.h" +#import "FClock.h" +#import "FImmutableTree.h" +#import "FLevelDBStorageEngine.h" +#import "FPruneForest.h" +#import "FTrackedQuery.h" +#import "FUtilities.h" +#import + +@interface FTrackedQueryManager () + +@property(nonatomic, strong) FImmutableTree *trackedQueryTree; +@property(nonatomic, strong) id storageEngine; +@property(nonatomic, strong) id clock; +@property(nonatomic) NSUInteger currentQueryId; + +@end + +@implementation FTrackedQueryManager + +- (id)initWithStorageEngine:(id)storageEngine + clock:(id)clock { + self = [super init]; + if (self != nil) { + self->_storageEngine = storageEngine; + self->_clock = clock; + self->_trackedQueryTree = [FImmutableTree empty]; + + NSTimeInterval lastUse = [clock currentTime]; + + NSArray *trackedQueries = [self.storageEngine loadTrackedQueries]; + [trackedQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *trackedQuery, NSUInteger idx, + BOOL *stop) { + self.currentQueryId = + MAX(trackedQuery.queryId + 1, self.currentQueryId); + if (trackedQuery.isActive) { + trackedQuery = + [[trackedQuery setActiveState:NO] updateLastUse:lastUse]; + FFDebug( + @"I-RDB081001", + @"Setting active query %lu from previous app start inactive", + (unsigned long)trackedQuery.queryId); + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + [self cacheTrackedQuery:trackedQuery]; + }]; + } + return self; +} + ++ (void)assertValidTrackedQuery:(FQuerySpec *)query { + NSAssert(!query.loadsAllData || query.isDefault, + @"Can't have tracked non-default query that loads all data"); +} + ++ (FQuerySpec *)normalizeQuery:(FQuerySpec *)query { + return query.loadsAllData ? [FQuerySpec defaultQueryAtPath:query.path] + : query; +} + +- (FTrackedQuery *)findTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + NSDictionary *set = [self.trackedQueryTree valueAtPath:query.path]; + return set[query.params]; +} + +- (void)removeTrackedQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + NSAssert(trackedQuery, @"Tracked query must exist to be removed!"); + + [self.storageEngine removeTrackedQuery:trackedQuery.queryId]; + NSMutableDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + [trackedQueries removeObjectForKey:query.params]; +} + +- (void)setQueryActive:(FQuerySpec *)query { + [self setQueryActive:YES forQuery:query]; +} + +- (void)setQueryInactive:(FQuerySpec *)query { + [self setQueryActive:NO forQuery:query]; +} + +- (void)setQueryActive:(BOOL)isActive forQuery:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + + // Regardless of whether it's now active or no langer active, we update the + // lastUse time + NSTimeInterval lastUse = [self.clock currentTime]; + if (trackedQuery != nil) { + trackedQuery = + [[trackedQuery updateLastUse:lastUse] setActiveState:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } else { + NSAssert(isActive, @"If we're setting the query to inactive, we should " + @"already be tracking it!"); + trackedQuery = [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:lastUse + isActive:isActive]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + } + + [self cacheTrackedQuery:trackedQuery]; +} + +- (void)setQueryComplete:(FQuerySpec *)query { + query = [FTrackedQueryManager normalizeQuery:query]; + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (!trackedQuery) { + // We might have removed a query and pruned it before we got the + // complete message from the server... + FFWarn(@"I-RDB081002", + @"Trying to set a query complete that is not tracked!"); + } else if (!trackedQuery.isComplete) { + trackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } else { + // Nothing to do, already marked complete + } +} + +- (void)setQueriesCompleteAtPath:(FPath *)path { + [[self.trackedQueryTree subtreeAtPath:path] + forEach:^(FPath *childPath, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *parms, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isComplete) { + FTrackedQuery *newTrackedQuery = [trackedQuery setComplete]; + [self.storageEngine saveTrackedQuery:newTrackedQuery]; + [self cacheTrackedQuery:newTrackedQuery]; + } + }]; + }]; +} + +- (BOOL)isQueryComplete:(FQuerySpec *)query { + if ([self isIncludedInDefaultCompleteQuery:query]) { + return YES; + } else if (query.loadsAllData) { + // We didn't find a default complete query, so must not be complete. + return NO; + } else { + NSDictionary *trackedQueries = + [self.trackedQueryTree valueAtPath:query.path]; + return [trackedQueries[query.params] isComplete]; + } +} + +- (BOOL)hasActiveDefaultQueryAtPath:(FPath *)path { + return [self.trackedQueryTree + rootMostValueOnPath:path + matching:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isActive]; + }] != nil; +} + +- (void)ensureCompleteTrackedQueryAtPath:(FPath *)path { + FQuerySpec *query = [FQuerySpec defaultQueryAtPath:path]; + if (![self isIncludedInDefaultCompleteQuery:query]) { + FTrackedQuery *trackedQuery = [self findTrackedQuery:query]; + if (trackedQuery == nil) { + trackedQuery = + [[FTrackedQuery alloc] initWithId:self.currentQueryId++ + query:query + lastUse:[self.clock currentTime] + isActive:NO + isComplete:YES]; + } else { + NSAssert(!trackedQuery.isComplete, + @"This should have been handled above!"); + trackedQuery = [trackedQuery setComplete]; + } + [self.storageEngine saveTrackedQuery:trackedQuery]; + [self cacheTrackedQuery:trackedQuery]; + } +} + +- (BOOL)isIncludedInDefaultCompleteQuery:(FQuerySpec *)query { + return + [self.trackedQueryTree + findRootMostMatchingPath:query.path + predicate:^BOOL(NSDictionary *trackedQueries) { + return + [trackedQueries[[FQueryParams defaultInstance]] + isComplete]; + }] != nil; +} + +- (void)cacheTrackedQuery:(FTrackedQuery *)query { + [FTrackedQueryManager assertValidTrackedQuery:query.query]; + NSMutableDictionary *trackedDict = + [self.trackedQueryTree valueAtPath:query.query.path]; + if (trackedDict == nil) { + trackedDict = [NSMutableDictionary dictionary]; + self.trackedQueryTree = + [self.trackedQueryTree setValue:trackedDict + atPath:query.query.path]; + } + trackedDict[query.query.params] = query; +} + +- (NSUInteger)numberOfQueriesToPrune:(id)cachePolicy + prunableCount:(NSUInteger)numPrunable { + NSUInteger numPercent = (NSUInteger)ceilf( + numPrunable * [cachePolicy percentOfQueriesToPruneAtOnce]); + NSUInteger maxToKeep = [cachePolicy maxNumberOfQueriesToKeep]; + NSUInteger numMax = (numPrunable > maxToKeep) ? numPrunable - maxToKeep : 0; + // Make sure we get below number of max queries to prune + return MAX(numMax, numPercent); +} + +- (FPruneForest *)pruneOldQueries:(id)cachePolicy { + NSMutableArray *pruneableQueries = [NSMutableArray array]; + NSMutableArray *unpruneableQueries = [NSMutableArray array]; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + [pruneableQueries addObject:trackedQuery]; + } else { + [unpruneableQueries addObject:trackedQuery]; + } + }]; + }]; + [pruneableQueries sortUsingComparator:^NSComparisonResult( + FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.lastUse < q2.lastUse) { + return NSOrderedAscending; + } else if (q1.lastUse > q2.lastUse) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }]; + + __block FPruneForest *pruneForest = [FPruneForest empty]; + NSUInteger numToPrune = + [self numberOfQueriesToPrune:cachePolicy + prunableCount:pruneableQueries.count]; + + // TODO: do in transaction + for (NSUInteger i = 0; i < numToPrune; i++) { + FTrackedQuery *toPrune = pruneableQueries[i]; + pruneForest = [pruneForest prunePath:toPrune.query.path]; + [self removeTrackedQuery:toPrune.query]; + } + + // Keep the rest of the prunable queries + for (NSUInteger i = numToPrune; i < pruneableQueries.count; i++) { + FTrackedQuery *toKeep = pruneableQueries[i]; + pruneForest = [pruneForest keepPath:toKeep.query.path]; + } + + // Also keep unprunable queries + [unpruneableQueries enumerateObjectsUsingBlock:^( + FTrackedQuery *toKeep, NSUInteger idx, BOOL *stop) { + pruneForest = [pruneForest keepPath:toKeep.query.path]; + }]; + + return pruneForest; +} + +- (NSUInteger)numberOfPrunableQueries { + __block NSUInteger count = 0; + [self.trackedQueryTree + forEach:^(FPath *path, NSDictionary *trackedQueries) { + [trackedQueries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *trackedQuery, + BOOL *stop) { + if (!trackedQuery.isActive) { + count++; + } + }]; + }]; + return count; +} + +- (NSSet *)filteredQueryIdsAtPath:(FPath *)path { + NSDictionary *queries = [self.trackedQueryTree valueAtPath:path]; + if (queries) { + NSMutableSet *ids = [NSMutableSet set]; + [queries enumerateKeysAndObjectsUsingBlock:^( + FQueryParams *params, FTrackedQuery *query, BOOL *stop) { + if (!query.query.loadsAllData) { + [ids addObject:@(query.queryId)]; + } + }]; + return ids; + } else { + return [NSSet set]; + } +} + +- (NSSet *)knownCompleteChildrenAtPath:(FPath *)path { + NSAssert(![self isQueryComplete:[FQuerySpec defaultQueryAtPath:path]], + @"Path is fully complete"); + + NSMutableSet *completeChildren = [NSMutableSet set]; + // First, get complete children from any queries at this location. + NSSet *queryIds = [self filteredQueryIdsAtPath:path]; + [queryIds enumerateObjectsUsingBlock:^(NSNumber *queryId, BOOL *stop) { + NSSet *keys = [self.storageEngine + trackedQueryKeysForQuery:[queryId unsignedIntegerValue]]; + [completeChildren unionSet:keys]; + }]; + + // Second, get any complete default queries immediately below us. + [[[self.trackedQueryTree subtreeAtPath:path] children] + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childTree.value[[FQueryParams defaultInstance]] isComplete]) { + [completeChildren addObject:childKey]; + } + }]; + + return completeChildren; +} + +- (void)verifyCache { + NSArray *storedTrackedQueries = [self.storageEngine loadTrackedQueries]; + NSMutableArray *trackedQueries = [NSMutableArray array]; + + [self.trackedQueryTree forEach:^(FPath *path, NSDictionary *queryDict) { + [trackedQueries addObjectsFromArray:queryDict.allValues]; + }]; + NSComparator comparator = + ^NSComparisonResult(FTrackedQuery *q1, FTrackedQuery *q2) { + if (q1.queryId < q2.queryId) { + return NSOrderedAscending; + } else if (q1.queryId > q2.queryId) { + return NSOrderedDescending; + } else { + return NSOrderedSame; + } + }; + [trackedQueries sortUsingComparator:comparator]; + storedTrackedQueries = + [storedTrackedQueries sortedArrayUsingComparator:comparator]; + + if (![trackedQueries isEqualToArray:storedTrackedQueries]) { + [NSException + raise:NSInternalInconsistencyException + format:@"Tracked queries and queries stored on disk don't match"]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h new file mode 100644 index 0000000..3aecd81 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataEventType.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef Firebase_FIRDataEventType_h +#define Firebase_FIRDataEventType_h + +#import + +/** + * This enum is the set of events that you can observe at a Firebase Database + * location. + */ +typedef NS_ENUM(NSInteger, FIRDataEventType) { + /// A new child node is added to a location. + FIRDataEventTypeChildAdded, + /// A child node is removed from a location. + FIRDataEventTypeChildRemoved, + /// A child node at a location changes. + FIRDataEventTypeChildChanged, + /// A child node moves relative to the other child nodes at a location. + FIRDataEventTypeChildMoved, + /// Any data changes at a location or, recursively, at any child node. + FIRDataEventTypeValue +} NS_SWIFT_NAME(DataEventType); + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h new file mode 100644 index 0000000..e88febb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDataSnapshot.h @@ -0,0 +1,142 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabaseReference; + +/** + * A FIRDataSnapshot contains data from a Firebase Database location. Any time + * you read Firebase data, you receive the data as a FIRDataSnapshot. + * + * FIRDataSnapshots are passed to the blocks you attach with + * observeEventType:withBlock: or observeSingleEvent:withBlock:. They are + * efficiently-generated immutable copies of the data at a Firebase Database + * location. They can't be modified and will never change. To modify data at a + * location, use a FIRDatabaseReference (e.g. with setValue:). + */ +NS_SWIFT_NAME(DataSnapshot) +@interface FIRDataSnapshot : NSObject + +#pragma mark - Navigating and inspecting a snapshot + +/** + * Gets a FIRDataSnapshot for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') + * or a deeper slash-separated path (e.g. 'fred/name/first'). If the child + * location has no data, an empty FIRDataSnapshot is returned. + * + * @param childPathString A relative path to the location of child data. + * @return The FIRDataSnapshot for the child location. + */ +- (FIRDataSnapshot *)childSnapshotForPath:(NSString *)childPathString; + +/** + * Return YES if the specified child exists. + * + * @param childPathString A relative path to the location of a potential child. + * @return YES if data exists at the specified childPathString, else NO. + */ +- (BOOL)hasChild:(NSString *)childPathString; + +/** + * Return YES if the DataSnapshot has any children. + * + * @return YES if this snapshot has any children, else NO. + */ +- (BOOL)hasChildren; + +/** + * Return YES if the DataSnapshot contains a non-null value. + * + * @return YES if this snapshot contains a non-null value, else NO. + */ +- (BOOL)exists; + +#pragma mark - Data export + +/** + * Returns the raw value at this location, coupled with any metadata, such as + * priority. + * + * Priorities, where they exist, are accessible under the ".priority" key in + * instances of NSDictionary. For leaf locations with priorities, the value will + * be under the ".value" key. + */ +- (id __nullable)valueInExportFormat; + +#pragma mark - Properties + +/** + * Returns the contents of this data snapshot as native types. + * + * Data types returned: + * + NSDictionary + * + NSArray + * + NSNumber (also includes booleans) + * + NSString + * + * @return The data as a native object. + */ +@property(strong, readonly, nonatomic, nullable) id value; + +/** + * Gets the number of children for this DataSnapshot. + * + * @return An integer indicating the number of children. + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Gets a FIRDatabaseReference for the location that this data came from. + * + * @return A FIRDatabaseReference instance for the location of this data. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +/** + * The key of the location that generated this FIRDataSnapshot. + * + * @return An NSString containing the key for the location of this + * FIRDataSnapshot. + */ +@property(strong, readonly, nonatomic) NSString *key; + +/** + * An iterator for snapshots of the child nodes in this snapshot. + * You can use the native for..in syntax: + * + * for (FIRDataSnapshot* child in snapshot.children) { + * ... + * } + * + * @return An NSEnumerator of the children. + */ +@property(strong, readonly, nonatomic) + NSEnumerator *children; + +/** + * The priority of the data in this FIRDataSnapshot. + * + * @return The priority as a string, or nil if no priority was set. + */ +@property(strong, readonly, nonatomic, nullable) id priority; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h new file mode 100644 index 0000000..02af8c7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabase.h @@ -0,0 +1,182 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The entry point for accessing a Firebase Database. You can get an instance + * by calling [FIRDatabase database]. To access a location in the database and + * read or write data, use [FIRDatabase reference]. + */ +NS_SWIFT_NAME(Database) +@interface FIRDatabase : NSObject + +/** + * The NSObject initializer that has been marked as unavailable. Use the + * `database` method instead + * + * @return An instancetype instance + */ +- (instancetype)init + __attribute__((unavailable("use the database method instead"))); + +/** + * Gets the instance of FIRDatabase for the default FIRApp. + * + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)database NS_SWIFT_NAME(database()); + +/** + * Gets a FirebaseDatabase instance for the specified URL. + * + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseWithURL:(NSString *)url NS_SWIFT_NAME(database(url:)); + +/** + * Gets a FirebaseDatabase instance for the specified URL, using the specified + * FirebaseApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @param url The URL to the Firebase Database instance you want to access. + * @return A FIRDatabase instance. + */ +// clang-format off ++ (FIRDatabase *)databaseForApp:(FIRApp *)app + URL:(NSString *)url NS_SWIFT_NAME(database(app:url:)); +// clang-format on + +/** + * Gets an instance of FIRDatabase for a specific FIRApp. + * + * @param app The FIRApp to get a FIRDatabase for. + * @return A FIRDatabase instance. + */ ++ (FIRDatabase *)databaseForApp:(FIRApp *)app NS_SWIFT_NAME(database(app:)); + +/** The FIRApp instance to which this FIRDatabase belongs. */ +@property(weak, readonly, nonatomic) FIRApp *app; + +/** + * Gets a FIRDatabaseReference for the root of your Firebase Database. + */ +- (FIRDatabaseReference *)reference; + +/** + * Gets a FIRDatabaseReference for the provided path. + * + * @param path Path to a location in your Firebase Database. + * @return A FIRDatabaseReference pointing to the specified path. + */ +- (FIRDatabaseReference *)referenceWithPath:(NSString *)path; + +/** + * Gets a FIRDatabaseReference for the provided URL. The URL must be a URL to a + * path within this Firebase Database. To create a FIRDatabaseReference to a + * different database, create a FIRApp} with a FIROptions object configured with + * the appropriate database URL. + * + * @param databaseUrl A URL to a path within your database. + * @return A FIRDatabaseReference for the provided URL. + */ +- (FIRDatabaseReference *)referenceFromURL:(NSString *)databaseUrl; + +/** + * The Firebase Database client automatically queues writes and sends them to + * the server at the earliest opportunity, depending on network connectivity. In + * some cases (e.g. offline usage) there may be a large number of writes waiting + * to be sent. Calling this method will purge all outstanding writes so they are + * abandoned. + * + * All writes will be purged, including transactions and onDisconnect writes. + * The writes will be rolled back locally, perhaps triggering events for + * affected event listeners, and the client will not (re-)send them to the + * Firebase Database backend. + */ +- (void)purgeOutstandingWrites; + +/** + * Shuts down our connection to the Firebase Database backend until goOnline is + * called. + */ +- (void)goOffline; + +/** + * Resumes our connection to the Firebase Database backend after a previous + * goOffline call. + */ +- (void)goOnline; + +/** + * The Firebase Database client will cache synchronized data and keep track of + * all writes you've initiated while your application is running. It seamlessly + * handles intermittent network connections and re-sends write operations when + * the network connection is restored. + * + * However by default your write operations and cached data are only stored + * in-memory and will be lost when your app restarts. By setting this value to + * `YES`, the data will be persisted to on-device (disk) storage and will thus + * be available again when the app is restarted (even when there is no network + * connectivity at that time). Note that this property must be set before + * creating your first Database reference and only needs to be called once per + * application. + * + */ +@property(nonatomic) BOOL persistenceEnabled NS_SWIFT_NAME(isPersistenceEnabled) + ; + +/** + * By default the Firebase Database client will use up to 10MB of disk space to + * cache data. If the cache grows beyond this size, the client will start + * removing data that hasn't been recently used. If you find that your + * application caches too little or too much data, call this method to change + * the cache size. This property must be set before creating your first + * FIRDatabaseReference and only needs to be called once per application. + * + * Note that the specified cache size is only an approximation and the size on + * disk may temporarily exceed it at times. Cache sizes smaller than 1 MB or + * greater than 100 MB are not supported. + */ +@property(nonatomic) NSUInteger persistenceCacheSizeBytes; + +/** + * Sets the dispatch queue on which all events are raised. The default queue is + * the main queue. + * + * Note that this must be set before creating your first Database reference. + */ +@property(nonatomic, strong) dispatch_queue_t callbackQueue; + +/** + * Enables verbose diagnostic logging. + * + * @param enabled YES to enable logging, NO to disable. + */ ++ (void)setLoggingEnabled:(BOOL)enabled; + +/** Retrieve the Firebase Database SDK version. */ ++ (NSString *)sdkVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h new file mode 100644 index 0000000..82057aa --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseQuery.h @@ -0,0 +1,395 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRDatabaseHandle is used to identify listeners of Firebase Database + * events. These handles are returned by observeEventType: and can later be + * passed to removeObserverWithHandle: to stop receiving updates. + */ +typedef NSUInteger FIRDatabaseHandle NS_SWIFT_NAME(DatabaseHandle); + +/** + * A FIRDatabaseQuery instance represents a query over the data at a particular + * location. + * + * You create one by calling one of the query methods (queryOrderedByChild:, + * queryStartingAtValue:, etc.) on a FIRDatabaseReference. The query methods can + * be chained to further specify the data you are interested in observing + */ +NS_SWIFT_NAME(DatabaseQuery) +@interface FIRDatabaseQuery : NSObject + +#pragma mark - Attach observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * Detach all blocks previously attached to this Firebase Database location with + * observeEventType:withBlock: + */ +- (void)removeAllObservers; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByValue: is used to generate a reference to a view of the data + * that's been sorted by child value. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child value. + */ +- (FIRDatabaseQuery *)queryOrderedByValue; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. This is most useful when implementing pagination in a + * case where multiple nodes can match the startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. This is most useful when implementing pagination in a case where + * multiple nodes can match the endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument and with their key equal to childKey. There will be + * at most one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The name of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the location of this query. + * + * @return A FIRDatabaseReference for the location of this query. + */ +@property(nonatomic, readonly, strong) FIRDatabaseReference *ref; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h new file mode 100644 index 0000000..c80b2f8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRDatabaseReference.h @@ -0,0 +1,861 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRDatabase; + +/** + * A FIRDatabaseReference represents a particular location in your Firebase + * Database and can be used for reading or writing data to that Firebase + * Database location. + * + * This class is the starting point for all Firebase Database operations. After + * you've obtained your first FIRDatabaseReference via [FIRDatabase reference], + * you can use it to read data (ie. observeEventType:withBlock:), write data + * (ie. setValue:), and to create new FIRDatabaseReferences (ie. child:). + */ +NS_SWIFT_NAME(DatabaseReference) +@interface FIRDatabaseReference : FIRDatabaseQuery + +#pragma mark - Getting references to children locations + +/** + * Gets a FIRDatabaseReference for the location at the specified relative path. + * The relative path can either be a simple child key (e.g. 'fred') or a + * deeper slash-separated path (e.g. 'fred/name/first'). + * + * @param pathString A relative path from this location to the desired child + * location. + * @return A FIRDatabaseReference for the specified relative path. + */ +- (FIRDatabaseReference *)child:(NSString *)pathString; + +/** + * childByAutoId generates a new child location using a unique key and returns a + * FIRDatabaseReference to it. This is useful when the children of a Firebase + * Database location represent a list of items. + * + * The unique key generated by childByAutoId: is prefixed with a + * client-generated timestamp so that the resulting list will be + * chronologically-sorted. + * + * @return A FIRDatabaseReference for the generated location. + */ +- (FIRDatabaseReference *)childByAutoId; + +#pragma mark - Writing data + +/** Write data to this Firebase Database location. + +This will overwrite any data at this location and all child locations. + +Data types that can be set are: + +- NSString -- @"Hello World" +- NSNumber (also includes boolean) -- @YES, @43, @4.333 +- NSDictionary -- @{@"key": @"value", @"nested": @{@"another": @"value"} } +- NSArray + +The effect of the write will be visible immediately and the corresponding +events will be triggered. Synchronization of the data to the Firebase Database +servers will also be started. + +Passing null for the new value is equivalent to calling remove:; +all data at this location or any child location will be deleted. + +Note that setValue: will remove any priority stored at this location, so if +priority is meant to be preserved, you should use setValue:andPriority: instead. + +@param value The value to be written. + */ +- (void)setValue:(nullable id)value; + +/** + * The same as setValue: with a block that gets triggered after the write + * operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * The same as setValue: with an additional priority to be attached to the data + * being written. Priorities are used to order items. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + */ +- (void)setValue:(nullable id)value andPriority:(nullable id)priority; + +/** + * The same as setValue:andPriority: with a block that gets triggered after the + * write operation has been committed to the Firebase Database servers. + * + * @param value The value to be written. + * @param priority The priority to be attached to that data. + * @param block The block to be called after the write has been committed to the + * Firebase Database servers. + */ +- (void)setValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Remove the data at this Firebase Database location. Any data at child + * locations will also be deleted. + * + * The effect of the delete will be visible immediately and the corresponding + * events will be triggered. Synchronization of the delete to the Firebase + * Database servers will also be started. + * + * remove: is equivalent to calling setValue:nil + */ +- (void)removeValue; + +/** + * The same as remove: with a block that gets triggered after the remove + * operation has been committed to the Firebase Database servers. + * + * @param block The block to be called after the remove has been committed to + * the Firebase Database servers. + */ +- (void)removeValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Sets a priority for the data at this Firebase Database location. + * Priorities can be used to provide a custom ordering for the children at a + * location (if no priorities are specified, the children are ordered by key). + * + * You cannot set a priority on an empty location. For this reason + * setValue:andPriority: should be used when setting initial data with a + * specific priority and setPriority: should be used when updating the priority + * of existing data. + * + * Children are sorted based on this priority using the following rules: + * + * Children with no priority come first. + * Children with a number as their priority come next. They are sorted + * numerically by priority (small to large). Children with a string as their + * priority come last. They are sorted lexicographically by priority. Whenever + * two children have the same priority (including no priority), they are sorted + * by key. Numeric keys come first (sorted numerically), followed by the + * remaining keys (sorted lexicographically). + * + * Note that priorities are parsed and ordered as IEEE 754 double-precision + * floating-point numbers. Keys are always stored as strings and are treated as + * numbers only when they can be parsed as a 32-bit integer + * + * @param priority The priority to set at the specified location. + */ +- (void)setPriority:(nullable id)priority; + +/** + * The same as setPriority: with a block that is called once the priority has + * been committed to the Firebase Database servers. + * + * @param priority The priority to set at the specified location. + * @param block The block that is triggered after the priority has been written + * on the servers. + */ +- (void)setPriority:(nullable id)priority + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Updates the values at the specified paths in the dictionary without + * overwriting other keys at this location. + * + * @param values A dictionary of the keys to change and their new values + */ +- (void)updateChildValues:(NSDictionary *)values; + +/** + * The same as update: with a block that is called once the update has been + * committed to the Firebase Database servers + * + * @param values A dictionary of the keys to change and their new values + * @param block The block that is triggered after the update has been written on + * the Firebase Database servers + */ +- (void)updateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +#pragma mark - Attaching observers to read data + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * Use removeObserverWithHandle: to stop receiving updates. + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock: + (void (^)(FIRDataSnapshot *snapshot))block; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * observeEventType:withBlock: is used to listen for data changes at a + * particular location. This is the primary way to read data from the Firebase + * Database. Your block will be triggered for the initial data and again + * whenever the data changes. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * observeEventType:andPreviousSiblingKeyWithBlock: is used to listen for data + * changes at a particular location. This is the primary way to read data from + * the Firebase Database. Your block will be triggered for the initial data and + * again whenever the data changes. In addition, for FIRDataEventTypeChildAdded, + * FIRDataEventTypeChildMoved, and FIRDataEventTypeChildChanged events, your + * block will be passed the key of the previous node by priority order. + * + * The cancelBlock will be called if you will no longer receive new events due + * to no longer having permission. + * + * Use removeObserverWithHandle: to stop receiving updates. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called with initial data and updates. + * It is passed the data as a FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that should be called if this client no longer + * has permission to receive these events + * @return A handle used to unregister this block later using + * removeObserverWithHandle: + */ +- (FIRDatabaseHandle)observeEventType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock: + (void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + withBlock:(void (^)(FIRDataSnapshot *snapshot))block + withCancelBlock:(nullable void (^)(NSError *error))cancelBlock; + +/** + * This is equivalent to observeEventType:withBlock:, except the block is + * immediately canceled after the initial data is returned. In addition, for + * FIRDataEventTypeChildAdded, FIRDataEventTypeChildMoved, and + * FIRDataEventTypeChildChanged events, your block will be passed the key of the + * previous node by priority order. + * + * The cancelBlock will be called if you do not have permission to read data at + * this location. + * + * @param eventType The type of event to listen for. + * @param block The block that should be called. It is passed the data as a + * FIRDataSnapshot and the previous child's key. + * @param cancelBlock The block that will be called if you don't have permission + * to access this data + */ +- (void)observeSingleEventOfType:(FIRDataEventType)eventType + andPreviousSiblingKeyWithBlock:(void (^)(FIRDataSnapshot *snapshot, + NSString *__nullable prevKey))block + withCancelBlock: + (nullable void (^)(NSError *error))cancelBlock; + +#pragma mark - Detaching observers + +/** + * Detach a block previously attached with observeEventType:withBlock:. + * + * @param handle The handle returned by the call to observeEventType:withBlock: + * which we are trying to remove. + */ +- (void)removeObserverWithHandle:(FIRDatabaseHandle)handle; + +/** + * By calling `keepSynced:YES` on a location, the data for that location will + * automatically be downloaded and kept in sync, even when no listeners are + * attached for that location. Additionally, while a location is kept synced, it + * will not be evicted from the persistent disk cache. + * + * @param keepSynced Pass YES to keep this location synchronized, pass NO to + * stop synchronization. + */ +- (void)keepSynced:(BOOL)keepSynced; + +/** + * Removes all observers at the current reference, but does not remove any + * observers at child references. removeAllObservers must be called again for + * each child reference where a listener was established to remove the + * observers. + */ +- (void)removeAllObservers; + +#pragma mark - Querying and limiting + +/** + * queryLimitedToFirst: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToFirst: will respond to at most the first limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToFirst:(NSUInteger)limit; + +/** + * queryLimitedToLast: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryLimitedToLast: will respond to at most the last limit child nodes. + * + * @param limit The upper bound, inclusive, for the number of child nodes to + * receive events for + * @return A FIRDatabaseQuery instance, limited to at most limit child nodes. + */ +- (FIRDatabaseQuery *)queryLimitedToLast:(NSUInteger)limit; + +/** + * queryOrderBy: is used to generate a reference to a view of the data that's + * been sorted by the values of a particular child key. This method is intended + * to be used in combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @param key The child key to use in ordering data visible to the returned + * FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, ordered by the values of the specified + * child key. + */ +- (FIRDatabaseQuery *)queryOrderedByChild:(NSString *)key; + +/** + * queryOrderedByKey: is used to generate a reference to a view of the data + * that's been sorted by child key. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child keys. + */ +- (FIRDatabaseQuery *)queryOrderedByKey; + +/** + * queryOrderedByPriority: is used to generate a reference to a view of the data + * that's been sorted by child priority. This method is intended to be used in + * combination with queryStartingAtValue:, queryEndingAtValue:, or + * queryEqualToValue:. + * + * @return A FIRDatabaseQuery instance, ordered by child priorities. + */ +- (FIRDatabaseQuery *)queryOrderedByPriority; + +/** + * queryStartingAtValue: is used to generate a reference to a limited view of + * the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue: will respond to events at nodes with a value greater + * than or equal to startValue. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue; + +/** + * queryStartingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryStartingAtValue:childKey will respond to events at nodes with a value + * greater than startValue, or equal to startValue and with a key greater than + * or equal to childKey. + * + * @param startValue The lower bound, inclusive, for the value of data visible + * to the returned FIRDatabaseQuery + * @param childKey The lower bound, inclusive, for the key of nodes with value + * equal to startValue + * @return A FIRDatabaseQuery instance, limited to data with value greater than + * or equal to startValue + */ +- (FIRDatabaseQuery *)queryStartingAtValue:(nullable id)startValue + childKey:(nullable NSString *)childKey; + +/** + * queryEndingAtValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue: will respond to events at nodes with a value less than or + * equal to endValue. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue; + +/** + * queryEndingAtValue:childKey: is used to generate a reference to a limited + * view of the data at this location. The FIRDatabaseQuery instance returned by + * queryEndingAtValue:childKey will respond to events at nodes with a value less + * than endValue, or equal to endValue and with a key less than or equal to + * childKey. + * + * @param endValue The upper bound, inclusive, for the value of data visible to + * the returned FIRDatabaseQuery + * @param childKey The upper bound, inclusive, for the key of nodes with value + * equal to endValue + * @return A FIRDatabaseQuery instance, limited to data with value less than or + * equal to endValue + */ +- (FIRDatabaseQuery *)queryEndingAtValue:(nullable id)endValue + childKey:(nullable NSString *)childKey; + +/** + * queryEqualToValue: is used to generate a reference to a limited view of the + * data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue: will respond to events at nodes with a value equal to the + * supplied argument. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @return A FIRDatabaseQuery instance, limited to data with the supplied value. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value; + +/** + * queryEqualToValue:childKey: is used to generate a reference to a limited view + * of the data at this location. The FIRDatabaseQuery instance returned by + * queryEqualToValue:childKey will respond to events at nodes with a value equal + * to the supplied argument with a key equal to childKey. There will be at most + * one node that matches because child keys are unique. + * + * @param value The value that the data returned by this FIRDatabaseQuery will + * have + * @param childKey The key of nodes with the right value + * @return A FIRDatabaseQuery instance, limited to data with the supplied value + * and the key. + */ +- (FIRDatabaseQuery *)queryEqualToValue:(nullable id)value + childKey:(nullable NSString *)childKey; + +#pragma mark - Managing presence + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * onDisconnectSetValue: is especially useful for implementing "presence" + * systems, where a value should be changed or cleared when a user disconnects + * so that he appears "offline" to other users. + * + * @param value The value to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value; + +/** + * Ensure the data at this location is set to the specified value when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + */ +- (void)onDisconnectSetValue:(nullable id)value andPriority:(id)priority; + +/** + * Ensure the data at this location is set to the specified value and priority + * when the client is disconnected (due to closing the browser, navigating to a + * new page, or network issues). + * + * The completion block will be triggered when the operation has been + * successfully queued up on the Firebase Database servers + * + * @param value The value to be set after the connection is lost. + * @param priority The priority to be set after the connection is lost. + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectSetValue:(nullable id)value + andPriority:(nullable id)priority + withCompletionBlock:(void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValue is especially useful for implementing "presence" + * systems. + */ +- (void)onDisconnectRemoveValue; + +/** + * Ensure the data at this location is removed when + * the client is disconnected (due to closing the app, navigating + * to a new page, or network issues). + * + * onDisconnectRemoveValueWithCompletionBlock: is especially useful for + * implementing "presence" systems. + * + * @param block Block to be triggered when the operation has been queued up on + * the Firebase Database servers + */ +- (void)onDisconnectRemoveValueWithCompletionBlock: + (void (^)(NSError *__nullable error, FIRDatabaseReference *ref))block; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values; + +/** + * Ensure the data has the specified child values updated when + * the client is disconnected (due to closing the browser, navigating + * to a new page, or network issues). + * + * + * @param values A dictionary of child node keys and the values to set them to + * after the connection is lost. + * @param block A block that will be called once the operation has been queued + * up on the Firebase Database servers + */ +- (void)onDisconnectUpdateChildValues:(NSDictionary *)values + withCompletionBlock: + (void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + */ +- (void)cancelDisconnectOperations; + +/** + * Cancel any operations that are set to run on disconnect. If you previously + * called onDisconnectSetValue:, onDisconnectRemoveValue:, or + * onDisconnectUpdateChildValues:, and no longer want the values updated when + * the connection is lost, call cancelDisconnectOperations: + * + * @param block A block that will be triggered once the Firebase Database + * servers have acknowledged the cancel request. + */ +- (void)cancelDisconnectOperationsWithCompletionBlock: + (nullable void (^)(NSError *__nullable error, + FIRDatabaseReference *ref))block; + +#pragma mark - Manual Connection Management + +/** + * Manually disconnect the Firebase Database client from the server and disable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * While offline, the Firebase Database client will no longer receive data + * updates from the server. However, all database operations performed locally + * will continue to immediately fire events, allowing your application to + * continue behaving normally. Additionally, each operation performed locally + * will automatically be queued and retried upon reconnection to the Firebase + * Database server. + * + * To reconnect to the Firebase Database server and begin receiving remote + * events, see goOnline( ). Once the connection is reestablished, the Firebase + * Database client will transmit the appropriate data and fire the appropriate + * events so that your client "catches up" automatically. + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOffline; + +/** + * Manually reestablish a connection to the Firebase Database server and enable + * automatic reconnection. + * + * The Firebase Database client automatically maintains a persistent connection + * to the Firebase Database server, which will remain active indefinitely and + * reconnect when disconnected. However, the goOffline( ) and goOnline( ) + * methods may be used to manually control the client connection in cases where + * a persistent connection is undesirable. + * + * This method should be used after invoking goOffline( ) to disable the active + * connection. Once reconnected, the Firebase Database client will automatically + * transmit the proper data and fire the appropriate events so that your client + * "catches up" automatically. + * + * To disconnect from the Firebase Database server, see goOffline( ). + * + * Note: Invoking this method will impact all Firebase Database connections. + */ ++ (void)goOnline; + +#pragma mark - Transactions + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by returning + * [FIRTransactionResult abort]. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot))completionBlock; + +/** + * Performs an optimistic-concurrency transactional update to the data at this + * location. Your block will be called with a FIRMutableData instance that + * contains the current data at this location. Your block should update this + * data to the value you wish to write to this location, and then return an + * instance of FIRTransactionResult with the new data. + * + * If, when the operation reaches the server, it turns out that this client had + * stale data, your block will be run again with the latest data from the + * server. + * + * When your block is run, you may decide to abort the transaction by return + * [FIRTransactionResult abort]. + * + * Since your block may be run multiple times, this client could see several + * immediate states that don't exist on the server. You can suppress those + * immediate states until the server confirms the final state of the + * transaction. + * + * @param block This block receives the current data at this location and must + * return an instance of FIRTransactionResult + * @param completionBlock This block will be triggered once the transaction is + * complete, whether it was successful or not. It will indicate if there was an + * error, whether or not the data was committed, and what the current value of + * the data at this location is. + * @param localEvents Set this to NO to suppress events raised for intermediate + * states, and only get events based on the final state of the transaction. + */ +- (void)runTransactionBlock: + (FIRTransactionResult * (^)(FIRMutableData *currentData))block + andCompletionBlock: + (nullable void (^)(NSError *__nullable error, BOOL committed, + FIRDataSnapshot *__nullable snapshot)) + completionBlock + withLocalEvents:(BOOL)localEvents; + +#pragma mark - Retrieving String Representation + +/** + * Gets the absolute URL of this Firebase Database location. + * + * @return The absolute URL of the referenced Firebase Database location. + */ +- (NSString *)description; + +#pragma mark - Properties + +/** + * Gets a FIRDatabaseReference for the parent location. + * If this instance refers to the root of your Firebase Database, it has no + * parent, and therefore parent( ) will return null. + * + * @return A FIRDatabaseReference for the parent location. + */ +@property(strong, readonly, nonatomic, nullable) FIRDatabaseReference *parent; + +/** + * Gets a FIRDatabaseReference for the root location + * + * @return A new FIRDatabaseReference to root location. + */ +@property(strong, readonly, nonatomic) FIRDatabaseReference *root; + +/** + * Gets the last token in a Firebase Database location (e.g. 'fred' in + * https://SampleChat.firebaseIO-demo.com/users/fred) + * + * @return The key of the location this reference points to. + */ +@property(strong, readonly, nonatomic, nullable) NSString *key; + +/** + * Gets the URL for the Firebase Database location referenced by this + * FIRDatabaseReference. + * + * @return The url of the location this reference points to. + */ +@property(strong, readonly, nonatomic) NSString *URL; + +/** + * Gets the FIRDatabase instance associated with this reference. + * + * @return The FIRDatabase object for this reference. + */ +@property(strong, readonly, nonatomic) FIRDatabase *database; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h new file mode 100644 index 0000000..9797a67 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRMutableData.h @@ -0,0 +1,128 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRMutableData instance is populated with data from a Firebase Database + * location. When you are using runTransactionBlock:, you will be given an + * instance containing the current data at that location. Your block will be + * responsible for updating that instance to the data you wish to save at that + * location, and then returning using [FIRTransactionResult successWithValue:]. + * + * To modify the data, set its value property to any of the native types support + * by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that changes made to a child FIRMutableData instance will be visible to + * the parent. + */ +NS_SWIFT_NAME(MutableData) +@interface FIRMutableData : NSObject + +#pragma mark - Inspecting and navigating the data + +/** + * Returns boolean indicating whether this mutable data has children. + * + * @return YES if this data contains child nodes. + */ +- (BOOL)hasChildren; + +/** + * Indicates whether this mutable data has a child at the given path. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return YES if this data contains a child at the specified relative path + */ +- (BOOL)hasChildAtPath:(NSString *)path; + +/** + * Used to obtain a FIRMutableData instance that encapsulates the data at the + * given relative path. Note that changes made to the child will be visible to + * the parent. + * + * @param path A path string, consisting either of a single segment, like + * 'child', or multiple segments, 'a/deeper/child' + * @return A FIRMutableData instance containing the data at the given path + */ +- (FIRMutableData *)childDataByAppendingPath:(NSString *)path; + +#pragma mark - Properties + +/** + * To modify the data contained by this instance of FIRMutableData, set this to + * any of the native types supported by Firebase Database: + * + * + NSNumber (includes BOOL) + * + NSDictionary + * + NSArray + * + NSString + * + nil / NSNull to remove the data + * + * Note that setting this value will override the priority at this location. + * + * @return The current data at this location as a native object + */ +@property(strong, nonatomic, nullable) id value; + +/** + * Set this property to update the priority of the data at this location. Can be + * set to the following types: + * + * + NSNumber + * + NSString + * + nil / NSNull to remove the priority + * + * @return The priority of the data at this location + */ +@property(strong, nonatomic, nullable) id priority; + +/** + * @return The number of child nodes at this location + */ +@property(readonly, nonatomic) NSUInteger childrenCount; + +/** + * Used to iterate over the children at this location. You can use the native + * for .. in syntax: + * + * for (FIRMutableData* child in data.children) { + * ... + * } + * + * Note that this enumerator operates on an immutable copy of the child list. + * So, you can modify the instance during iteration, but the new additions will + * not be visible until you get a new enumerator. + */ +@property(readonly, nonatomic, strong) NSEnumerator *children; + +/** + * @return The key name of this node, or nil if it is the top-most location + */ +@property(readonly, nonatomic, strong, nullable) NSString *key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h new file mode 100644 index 0000000..8fca5e0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRServerValue.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Placeholder values you may write into Firebase Database as a value or + * priority that will automatically be populated by the Firebase Database + * server. + */ +NS_SWIFT_NAME(ServerValue) +@interface FIRServerValue : NSObject + +/** + * Placeholder value for the number of milliseconds since the Unix epoch + */ ++ (NSDictionary *)timestamp; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h new file mode 100644 index 0000000..7f5ccc1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FIRTransactionResult.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRMutableData.h" +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Used for runTransactionBlock:. An FIRTransactionResult instance is a + * container for the results of the transaction. + */ +NS_SWIFT_NAME(TransactionResult) +@interface FIRTransactionResult : NSObject + +/** + * Used for runTransactionBlock:. Indicates that the new value should be saved + * at this location + * + * @param value A FIRMutableData instance containing the new value to be set + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)successWithValue:(FIRMutableData *)value; + +/** + * Used for runTransactionBlock:. Indicates that the current transaction should + * no longer proceed. + * + * @return An FIRTransactionResult instance that can be used as a return value + * from the block given to runTransactionBlock: + */ ++ (FIRTransactionResult *)abort; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h new file mode 100644 index 0000000..ae6b933 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Public/FirebaseDatabase.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FirebaseDatabase_h +#define FirebaseDatabase_h + +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +#endif /* FirebaseDatabase_h */ diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h new file mode 100644 index 0000000..7198615 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import "FWebSocketConnection.h" +#import + +@protocol FConnectionDelegate; + +@interface FConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive; + +// FWebSocketDelegate delegate methods +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end + +typedef enum { + DISCONNECT_REASON_SERVER_RESET = 0, + DISCONNECT_REASON_OTHER = 1 +} FDisconnectReason; + +@protocol FConnectionDelegate + +- (void)onReady:(FConnection *)fconnection + atTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID; +- (void)onDataMessage:(FConnection *)fconnection + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FConnection *)fconnection + withReason:(FDisconnectReason)reason; +- (void)onKill:(FConnection *)fconnection withReason:(NSString *)reason; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m new file mode 100644 index 0000000..a33ebd7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FConnection.m @@ -0,0 +1,234 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FConnection.h" +#import "FConstants.h" +#import + +typedef enum { + REALTIME_STATE_CONNECTING = 0, + REALTIME_STATE_CONNECTED = 1, + REALTIME_STATE_DISCONNECTED = 2, +} FConnectionState; + +@interface FConnection () { + FConnectionState state; +} + +@property(nonatomic, strong) FWebSocketConnection *conn; +@property(nonatomic, strong) FRepoInfo *repoInfo; + +@end + +#pragma mark - +#pragma mark FConnection implementation + +@implementation FConnection + +@synthesize delegate; +@synthesize conn; +@synthesize repoInfo; + +#pragma mark - +#pragma mark Initializers + +- (id)initWith:(FRepoInfo *)aRepoInfo + andDispatchQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + state = REALTIME_STATE_CONNECTING; + self.repoInfo = aRepoInfo; + self.conn = [[FWebSocketConnection alloc] initWith:self.repoInfo + andQueue:queue + lastSessionID:lastSessionID]; + self.conn.delegate = self; + } + return self; +} + +#pragma mark - +#pragma mark Public method implementation + +- (void)open { + FFLog(@"I-RDB082001", @"Calling open in FConnection"); + [self.conn open]; +} + +- (void)closeWithReason:(FDisconnectReason)reason { + if (state != REALTIME_STATE_DISCONNECTED) { + FFLog(@"I-RDB082002", @"Closing realtime connection."); + state = REALTIME_STATE_DISCONNECTED; + + if (self.conn) { + FFLog(@"I-RDB082003", @"Calling close again."); + [self.conn close]; + self.conn = nil; + } + + [self.delegate onDisconnect:self withReason:reason]; + } +} + +- (void)close { + [self closeWithReason:DISCONNECT_REASON_OTHER]; +} + +- (void)sendRequest:(NSDictionary *)dataMsg sensitive:(BOOL)sensitive { + // since this came from the persistent connection, wrap it in a data message + // envelope + NSDictionary *msg = @{ + kFWPRequestType : kFWPRequestTypeData, + kFWPRequestDataPayload : dataMsg + }; + [self sendData:msg sensitive:sensitive]; +} + +#pragma mark - +#pragma mark Helpers + +- (void)sendData:(NSDictionary *)data sensitive:(BOOL)sensitive { + if (state != REALTIME_STATE_CONNECTED) { + @throw [[NSException alloc] + initWithName:@"InvalidConnectionState" + reason:@"Tried to send data on an unconnected FConnection" + userInfo:nil]; + } else { + if (sensitive) { + FFLog(@"I-RDB082004", @"Sending data (contents hidden)"); + } else { + FFLog(@"I-RDB082005", @"Sending: %@", data); + } + [self.conn send:data]; + } +} + +#pragma mark - +#pragma mark FWebSocketConnectinDelegate implementation + +// Corresponds to onConnectionLost in JS +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected { + + self.conn = nil; + if (!everConnected && state == REALTIME_STATE_CONNECTING) { + FFLog(@"I-RDB082006", @"Realtime connection failed."); + + // Since we failed to connect at all, clear any cached entry for this + // namespace in case the machine went away + [self.repoInfo clearInternalHostCache]; + } else if (state == REALTIME_STATE_CONNECTED) { + FFLog(@"I-RDB082007", @"Realtime connection lost."); + } + + [self close]; +} + +// Corresponds to onMessageReceived in JS +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message { + NSString *rawMessageType = + [message objectForKey:kFWPAsyncServerEnvelopeType]; + if (rawMessageType != nil) { + if ([rawMessageType isEqualToString:kFWPAsyncServerDataMessage]) { + [self onDataMessage:[message + objectForKey:kFWPAsyncServerEnvelopeData]]; + } else if ([rawMessageType + isEqualToString:kFWPAsyncServerControlMessage]) { + [self onControl:[message objectForKey:kFWPAsyncServerEnvelopeData]]; + } else { + FFLog(@"I-RDB082008", @"Unrecognized server packet type: %@", + rawMessageType); + } + } else { + FFLog(@"I-RDB082009", @"Unrecognized raw server packet received: %@", + message); + } +} + +- (void)onDataMessage:(NSDictionary *)message { + // we don't do anything with data messages, just kick them up a level + FFLog(@"I-RDB082010", @"Got data message: %@", message); + [self.delegate onDataMessage:self withMessage:message]; +} + +- (void)onControl:(NSDictionary *)message { + FFLog(@"I-RDB082011", @"Got control message: %@", message); + NSString *type = [message objectForKey:kFWPAsyncServerControlMessageType]; + if ([type isEqualToString:kFWPAsyncServerControlMessageShutdown]) { + NSString *reason = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onConnectionShutdownWithReason:reason]; + } else if ([type isEqualToString:kFWPAsyncServerControlMessageReset]) { + NSString *host = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onReset:host]; + } else if ([type isEqualToString:kFWPAsyncServerHello]) { + NSDictionary *handshakeData = + [message objectForKey:kFWPAsyncServerControlMessageData]; + [self onHandshake:handshakeData]; + } else { + FFLog(@"I-RDB082012", + @"Unknown control message returned from server: %@", message); + } +} + +- (void)onConnectionShutdownWithReason:(NSString *)reason { + FFLog(@"I-RDB082013", + @"Connection shutdown command received. Shutting down..."); + + [self.delegate onKill:self withReason:reason]; + [self close]; +} + +- (void)onHandshake:(NSDictionary *)handshake { + NSNumber *timestamp = + [handshake objectForKey:kFWPAsyncServerHelloTimestamp]; + // NSString* version = [handshake + // objectForKey:kFWPAsyncServerHelloVersion]; + NSString *host = [handshake objectForKey:kFWPAsyncServerHelloConnectedHost]; + NSString *sessionID = [handshake objectForKey:kFWPAsyncServerHelloSession]; + + self.repoInfo.internalHost = host; + + if (state == REALTIME_STATE_CONNECTING) { + [self.conn start]; + [self onConnection:self.conn readyAtTime:timestamp sessionID:sessionID]; + } +} + +- (void)onConnection:(FWebSocketConnection *)conn + readyAtTime:(NSNumber *)timestamp + sessionID:(NSString *)sessionID { + FFLog(@"I-RDB082014", @"Realtime connection established"); + state = REALTIME_STATE_CONNECTED; + + [self.delegate onReady:self atTime:timestamp sessionID:sessionID]; +} + +- (void)onReset:(NSString *)host { + FFLog( + @"I-RDB082015", + @"Got a reset; killing connection to: %@; Updating internalHost to: %@", + repoInfo.internalHost, host); + self.repoInfo.internalHost = host; + + // Explicitly close the connection with SERVER_RESET so calling code knows + // to reconnect immediately. + [self closeWithReason:DISCONNECT_REASON_SERVER_RESET]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h new file mode 100644 index 0000000..abb7474 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSRWebSocket.h" +#import "FUtilities.h" +#import + +@protocol FWebSocketDelegate; + +@interface FWebSocketConnection : NSObject + +@property(nonatomic, weak) id delegate; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID; + +- (void)open; +- (void)close; +- (void)start; +- (void)send:(NSDictionary *)dictionary; + +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean; + +@end + +@protocol FWebSocketDelegate + +- (void)onMessage:(FWebSocketConnection *)fwebSocket + withMessage:(NSDictionary *)message; +- (void)onDisconnect:(FWebSocketConnection *)fwebSocket + wasEverConnected:(BOOL)everConnected; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m new file mode 100644 index 0000000..edcae09 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Realtime/FWebSocketConnection.m @@ -0,0 +1,346 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. + +#import + +#import "FConstants.h" +#import "FIRDatabaseReference.h" +#import "FIRDatabase_Private.h" +#import "FStringUtilities.h" +#import "FWebSocketConnection.h" +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif + +@interface FWebSocketConnection () { + NSMutableString *frame; + BOOL everConnected; + BOOL isClosed; + NSTimer *keepAlive; +} + +- (void)shutdown; +- (void)onClosed; +- (void)closeIfNeverConnected; + +@property(nonatomic, strong) FSRWebSocket *webSocket; +@property(nonatomic, strong) NSNumber *connectionId; +@property(nonatomic, readwrite) int totalFrames; +@property(nonatomic, readonly) BOOL buffering; +@property(nonatomic, readonly) NSString *userAgent; +@property(nonatomic) dispatch_queue_t dispatchQueue; + +- (void)nop:(NSTimer *)timer; + +@end + +@implementation FWebSocketConnection + +@synthesize delegate; +@synthesize webSocket; +@synthesize connectionId; + +- (id)initWith:(FRepoInfo *)repoInfo + andQueue:(dispatch_queue_t)queue + lastSessionID:(NSString *)lastSessionID { + self = [super init]; + if (self) { + everConnected = NO; + isClosed = NO; + self.connectionId = [FUtilities LUIDGenerator]; + self.totalFrames = 0; + self.dispatchQueue = queue; + frame = nil; + + NSString *connectionUrl = + [repoInfo connectionURLWithLastSessionID:lastSessionID]; + NSString *ua = [self userAgent]; + FFLog(@"I-RDB083001", @"(wsc:%@) Connecting to: %@ as %@", + self.connectionId, connectionUrl, ua); + + NSURLRequest *req = [[NSURLRequest alloc] + initWithURL:[[NSURL alloc] initWithString:connectionUrl]]; + self.webSocket = [[FSRWebSocket alloc] initWithURLRequest:req + queue:queue + andUserAgent:ua]; + [self.webSocket setDelegateDispatchQueue:queue]; + self.webSocket.delegate = self; + } + return self; +} + +- (NSString *)userAgent { + NSString *systemVersion; + NSString *deviceName; + BOOL hasUiDeviceClass = NO; + +// Targetted compilation is ONLY for testing. UIKit is weak-linked in actual +// release build. +#if TARGET_OS_IOS || TARGET_OS_TV + Class uiDeviceClass = NSClassFromString(@"UIDevice"); + if (uiDeviceClass) { + systemVersion = [uiDeviceClass currentDevice].systemVersion; + deviceName = [uiDeviceClass currentDevice].model; + hasUiDeviceClass = YES; + } +#endif + + if (!hasUiDeviceClass) { + NSDictionary *systemVersionDictionary = [NSDictionary + dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + systemVersion = + [systemVersionDictionary objectForKey:@"ProductVersion"]; + deviceName = [systemVersionDictionary objectForKey:@"ProductName"]; + } + + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + + // Sanitize '/'s in deviceName and bundleIdentifier for stats + deviceName = [FStringUtilities sanitizedForUserAgent:deviceName]; + bundleIdentifier = + [FStringUtilities sanitizedForUserAgent:bundleIdentifier]; + + // Firebase/5/__//{device model / + // os (Mac OS X, iPhone, etc.}_ + NSString *ua = [NSString + stringWithFormat:@"Firebase/%@/%@/%@/%@_%@", kWebsocketProtocolVersion, + [FIRDatabase buildVersion], systemVersion, deviceName, + bundleIdentifier]; + return ua; +} + +- (BOOL)buffering { + return frame != nil; +} + +#pragma mark - +#pragma mark Public FWebSocketConnection methods + +- (void)open { + FFLog(@"I-RDB083002", @"(wsc:%@) FWebSocketConnection open.", + self.connectionId); + assert(delegate); + everConnected = NO; + // TODO Assert url + [self.webSocket open]; + dispatch_time_t when = dispatch_time( + DISPATCH_TIME_NOW, kWebsocketConnectTimeout * NSEC_PER_SEC); + dispatch_after(when, self.dispatchQueue, ^{ + [self closeIfNeverConnected]; + }); +} + +- (void)close { + FFLog(@"I-RDB083003", @"(wsc:%@) FWebSocketConnection is being closed.", + self.connectionId); + isClosed = YES; + [self.webSocket close]; +} + +- (void)start { + // Start is a no-op for websockets. +} + +- (void)send:(NSDictionary *)dictionary { + + [self resetKeepAlive]; + + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary + options:kNilOptions + error:nil]; + + NSString *data = [[NSString alloc] initWithData:jsonData + encoding:NSUTF8StringEncoding]; + + NSArray *dataSegs = [FUtilities splitString:data + intoMaxSize:kWebsocketMaxFrameSize]; + + // First send the header so the server knows how many segments are + // forthcoming + if (dataSegs.count > 1) { + [self.webSocket + send:[NSString + stringWithFormat:@"%u", (unsigned int)dataSegs.count]]; + } + + // Then, actually send the segments. + for (NSString *segment in dataSegs) { + [self.webSocket send:segment]; + } +} + +- (void)nop:(NSTimer *)timer { + if (!isClosed) { + FFLog(@"I-RDB083004", @"(wsc:%@) nop", self.connectionId); + [self.webSocket send:@"0"]; + } else { + FFLog(@"I-RDB083005", + @"(wsc:%@) No more websocket; invalidating nop timer.", + self.connectionId); + [timer invalidate]; + } +} + +- (void)handleNewFrameCount:(int)numFrames { + self.totalFrames = numFrames; + frame = [[NSMutableString alloc] initWithString:@""]; + FFLog(@"I-RDB083006", @"(wsc:%@) handleNewFrameCount: %d", + self.connectionId, self.totalFrames); +} + +- (NSString *)extractFrameCount:(NSString *)message { + if ([message length] <= 4) { + int frameCount = [message intValue]; + if (frameCount > 0) { + [self handleNewFrameCount:frameCount]; + return nil; + } + } + [self handleNewFrameCount:1]; + return message; +} + +- (void)appendFrame:(NSString *)message { + [frame appendString:message]; + self.totalFrames = self.totalFrames - 1; + + if (self.totalFrames == 0) { + // Call delegate and pass an immutable version of the frame + NSDictionary *json = [NSJSONSerialization + JSONObjectWithData:[frame dataUsingEncoding:NSUTF8StringEncoding] + options:kNilOptions + error:nil]; + frame = nil; + FFLog(@"I-RDB083007", + @"(wsc:%@) handleIncomingFrame sending complete frame: %d", + self.connectionId, self.totalFrames); + + @autoreleasepool { + [self.delegate onMessage:self withMessage:json]; + } + } +} + +- (void)handleIncomingFrame:(NSString *)message { + [self resetKeepAlive]; + if (self.buffering) { + [self appendFrame:message]; + } else { + NSString *remaining = [self extractFrameCount:message]; + if (remaining) { + [self appendFrame:remaining]; + } + } +} + +#pragma mark - +#pragma mark SRWebSocketDelegate implementation +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message { + [self handleIncomingFrame:message]; +} + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket { + FFLog(@"I-RDB083008", @"(wsc:%@) webSocketDidOpen", self.connectionId); + + everConnected = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + self->keepAlive = + [NSTimer scheduledTimerWithTimeInterval:kWebsocketKeepaliveInterval + target:self + selector:@selector(nop:) + userInfo:nil + repeats:YES]; + FFLog(@"I-RDB083009", @"(wsc:%@) nop timer kicked off", + self.connectionId); + }); +} + +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error { + FFLog(@"I-RDB083010", @"(wsc:%@) didFailWithError didFailWithError: %@", + self.connectionId, [error description]); + [self onClosed]; +} + +- (void)webSocket:(FSRWebSocket *)webSocket + didCloseWithCode:(NSInteger)code + reason:(NSString *)reason + wasClean:(BOOL)wasClean { + FFLog(@"I-RDB083011", @"(wsc:%@) didCloseWithCode: %ld %@", + self.connectionId, (long)code, reason); + [self onClosed]; +} + +#pragma mark - +#pragma mark Private methods + +/** + * Note that the close / onClosed / shutdown cycle here is a little different + * from the javascript client. In order to properly handle deallocation, no + * close-related action is taken at a higher level until we have received + * notification from the websocket itself that it is closed. Otherwise, we end + * up deallocating this class and the FConnection class before the websocket has + * a change to call some of its delegate methods. So, since close is the + * external close handler, we just set a flag saying not to call our own + * delegate method and close the websocket. That will trigger a callback into + * this class that can then do things like clean up the keepalive timer. + */ + +- (void)closeIfNeverConnected { + if (!everConnected) { + FFLog(@"I-RDB083012", @"(wsc:%@) Websocket timed out on connect", + self.connectionId); + [self.webSocket close]; + } +} + +- (void)shutdown { + isClosed = YES; + + // Call delegate methods + [self.delegate onDisconnect:self wasEverConnected:everConnected]; +} + +- (void)onClosed { + if (!isClosed) { + FFLog(@"I-RDB083013", @"Websocket is closing itself"); + [self shutdown]; + } + self.webSocket = nil; + if (keepAlive.isValid) { + [keepAlive invalidate]; + } +} + +- (void)resetKeepAlive { + NSDate *newTime = + [NSDate dateWithTimeIntervalSinceNow:kWebsocketKeepaliveInterval]; + // Calling setFireDate is actually kinda' expensive, so wait at least 5 + // seconds before updating it. + if ([newTime timeIntervalSinceDate:keepAlive.fireDate] > 5) { + FFLog(@"I-RDB083014", @"(wsc:%@) resetting keepalive, to %@ ; old: %@", + self.connectionId, newTime, [keepAlive fireDate]); + [keepAlive setFireDate:newTime]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h new file mode 100644 index 0000000..cc3239e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.h @@ -0,0 +1,42 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FImmutableSortedDictionary.h" +#import "FNode.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@class FNamedNode; + +@interface FChildrenNode : NSObject + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren; +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren; + +// FChildrenNode specific methods + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +@property(nonatomic, strong) FImmutableSortedDictionary *children; +@property(nonatomic, strong) id priorityNode; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m new file mode 100644 index 0000000..bd02bf8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FChildrenNode.m @@ -0,0 +1,418 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FPriorityIndex.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FTransformedEnumerator.h" +#import "FUtilities.h" + +@interface FChildrenNode () +@property(nonatomic, strong) NSString *lazyHash; +@end + +@implementation FChildrenNode + +// Note: The only reason we allow nil priority is to for EmptyNode, since we +// can't use EmptyNode as the priority of EmptyNode. We might want to consider +// making EmptyNode its own class instead of an empty ChildrenNode. + +- (id)init { + return [self + initWithPriority:nil + children:[FImmutableSortedDictionary + dictionaryWithComparator:[FUtilities + keyComparator]]]; +} + +- (id)initWithChildren:(FImmutableSortedDictionary *)someChildren { + return [self initWithPriority:nil children:someChildren]; +} + +- (id)initWithPriority:(id)aPriority + children:(FImmutableSortedDictionary *)someChildren { + if (someChildren.isEmpty && aPriority != nil && ![aPriority isEmpty]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't create empty node with priority!"]; + } + self = [super init]; + if (self) { + self.children = someChildren; + self.priorityNode = aPriority; + } + return self; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return NO; +} + +- (id)getPriority { + if (self.priorityNode) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)updatePriority:(id)aPriority { + if ([self.children isEmpty]) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:aPriority + children:self.children]; + } +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + id child = [self.children objectForKey:childName]; + return (child == nil) ? [FEmptyNode emptyNode] : child; + } +} + +- (id)getChild:(FPath *)path { + NSString *front = [path getFront]; + if (front == nil) { + return self; + } else { + return [[self getImmediateChild:front] getChild:[path popFront]]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return ![self getImmediateChild:childName].isEmpty; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + NSAssert(newChildNode != nil, @"Should always be passing nodes."); + + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else { + FImmutableSortedDictionary *newChildren; + if (newChildNode.isEmpty) { + newChildren = [self.children removeObjectForKey:childName]; + } else { + newChildren = [self.children setObject:newChildNode + forKey:childName]; + } + if (newChildren.isEmpty) { + return [FEmptyNode emptyNode]; + } else { + return [[FChildrenNode alloc] initWithPriority:self.getPriority + children:newChildren]; + } + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + id newImmediateChild = + [[self getImmediateChild:front] updateChild:[path popFront] + withNewChild:newChildNode]; + return [self updateImmediateChild:front withNewChild:newImmediateChild]; + } +} + +- (BOOL)isEmpty { + return [self.children isEmpty]; +} + +- (int)numChildren { + return [self.children count]; +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if ([self isEmpty]) { + return [NSNull null]; + } + + __block int numKeys = 0; + __block NSInteger maxKey = 0; + __block BOOL allIntegerKeys = YES; + + NSMutableDictionary *obj = + [[NSMutableDictionary alloc] initWithCapacity:[self.children count]]; + [self enumerateChildrenUsingBlock:^(NSString *key, id childNode, + BOOL *stop) { + [obj setObject:[childNode valForExport:exp] forKey:key]; + + numKeys++; + + // If we already found a string key, don't bother with any of this + if (!allIntegerKeys) { + return; + } + + // Treat leading zeroes that are not exactly "0" as strings + NSString *firstChar = [key substringWithRange:NSMakeRange(0, 1)]; + if ([firstChar isEqualToString:@"0"] && [key length] > 1) { + allIntegerKeys = NO; + } else { + NSNumber *keyAsNum = [FUtilities intForString:key]; + if (keyAsNum != nil) { + NSInteger keyAsInt = [keyAsNum integerValue]; + if (keyAsInt > maxKey) { + maxKey = keyAsInt; + } + } else { + allIntegerKeys = NO; + } + } + }]; + + if (!exp && allIntegerKeys && maxKey < 2 * numKeys) { + // convert to an array + NSMutableArray *array = + [[NSMutableArray alloc] initWithCapacity:maxKey + 1]; + for (int i = 0; i <= maxKey; ++i) { + NSString *keyString = [NSString stringWithFormat:@"%i", i]; + id child = obj[keyString]; + if (child != nil) { + [array addObject:child]; + } else { + [array addObject:[NSNull null]]; + } + } + return array; + } else { + + if (exp && [self getPriority] != nil && !self.getPriority.isEmpty) { + obj[kPayloadPriority] = [self.getPriority val]; + } + + return obj; + } +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + + if (!self.getPriority.isEmpty) { + [toHash appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:(FLeafNode *) + self.getPriority + toString:toHash + hashVersion:FDataHashVersionV1]; + [toHash appendString:@":"]; + } + + __block BOOL sawPriority = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + sawPriority = sawPriority || [[node getPriority] isEmpty]; + *stop = sawPriority; + }]; + if (sawPriority) { + NSMutableArray *array = [NSMutableArray array]; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + FNamedNode *namedNode = [[FNamedNode alloc] initWithName:key + andNode:node]; + [array addObject:namedNode]; + }]; + [array sortUsingComparator:^NSComparisonResult( + FNamedNode *namedNode1, FNamedNode *namedNode2) { + return + [[FPriorityIndex priorityIndex] compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + [array enumerateObjectsUsingBlock:^(FNamedNode *namedNode, + NSUInteger idx, BOOL *stop) { + NSString *childHash = [namedNode.node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", namedNode.name, childHash]; + } + }]; + } else { + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + NSString *childHash = [node dataHash]; + if (![childHash isEqualToString:@""]) { + [toHash appendFormat:@":%@:%@", key, childHash]; + } + }]; + } + self.lazyHash = [toHash isEqualToString:@""] + ? @"" + : [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + // children nodes come last, unless this is actually an empty node, then we + // come first. + if (self.isEmpty) { + if (other.isEmpty) { + return NSOrderedSame; + } else { + return NSOrderedAscending; + } + } else if (other.isLeafNode || other.isEmpty) { + return NSOrderedDescending; + } else if (other == [FMaxNode maxNode]) { + return NSOrderedAscending; + } else { + // Must be another node with children. + return NSOrderedSame; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other == nil) { + return NO; + } else if (other.isLeafNode) { + return NO; + } else if (self.isEmpty && [other isEmpty]) { + // Empty nodes do not have priority + return YES; + } else { + FChildrenNode *otherChildrenNode = other; + if (![self.getPriority isEqual:other.getPriority]) { + return NO; + } else if (self.children.count == otherChildrenNode.children.count) { + __block BOOL equal = YES; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + id child = [otherChildrenNode getImmediateChild:key]; + if (![child isEqual:node]) { + equal = NO; + *stop = YES; + } + }]; + return equal; + } else { + return NO; + } + } +} + +- (NSUInteger)hash { + __block NSUInteger hashCode = 0; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + hashCode = 31 * hashCode + key.hash; + hashCode = 17 * hashCode + node.hash; + }]; + return 17 * hashCode + self.priorityNode.hash; +} + +- (void)enumerateChildrenAndPriorityUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + if ([self.getPriority isEmpty]) { + [self enumerateChildrenUsingBlock:block]; + } else { + __block BOOL passedPriorityKey = NO; + [self enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + if (!passedPriorityKey && + [FUtilities compareKey:key + toKey:@".priority"] == NSOrderedDescending) { + passedPriorityKey = YES; + BOOL stopAfterPriority = NO; + block(@".priority", [self getPriority], &stopAfterPriority); + if (stopAfterPriority) + return; + } + block(key, node, stop); + }]; + } +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + [self.children enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self.children enumerateKeysAndObjectsReverse:reverse usingBlock:block]; +} + +- (NSEnumerator *)childEnumerator { + return [[FTransformedEnumerator alloc] + initWithEnumerator:self.children.keyEnumerator + andTransform:^id(NSString *key) { + return [FNamedNode nodeWithName:key + node:[self getImmediateChild:key]]; + }]; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return [self.children getPredecessorKey:childKey]; +} + +#pragma mark - +#pragma mark FChildrenNode specific methods + +- (id)childrenGetter:(id)key { + return [self.children objectForKey:key]; +} + +- (FNamedNode *)firstChild { + NSString *childKey = self.children.minKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +- (FNamedNode *)lastChild { + NSString *childKey = self.children.maxKey; + if (childKey) { + return + [[FNamedNode alloc] initWithName:childKey + andNode:[self getImmediateChild:childKey]]; + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h new file mode 100644 index 0000000..47de66f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.h @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FImmutableTree; +@protocol FNode; +@class FPath; + +/** + * This class holds a collection of writes that can be applied to nodes in + * unison. It abstracts away the logic with dealing with priority writes and + * multiple nested writes. At any given path, there is only allowed to be one + * write modifying that path. Any write to an existing path or shadowing an + * existing path will modify that existing write to reflect the write added. + */ +@interface FCompoundWrite : NSObject + +- (id)initWithWriteTree:(FImmutableTree *)tree; + +/** + * Creates a compound write with NSDictionary from path string to object + */ ++ (FCompoundWrite *)compoundWriteWithValueDictionary:(NSDictionary *)dictionary; +/** + * Creates a compound write with NSDictionary from path string to node + */ ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary; + ++ (FCompoundWrite *)emptyWrite; + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path; +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key; +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)node + atPath:(FPath *)path; +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path; +- (id)rootWrite; +- (BOOL)hasCompleteWriteAtPath:(FPath *)path; +- (id)completeNodeAtPath:(FPath *)path; +- (NSArray *)completeChildren; +- (NSDictionary *)childCompoundWrites; +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path; +- (id)applyToNode:(id)node; +- (void)enumerateWrites:(void (^)(FPath *path, id node, + BOOL *stop))block; + +- (NSDictionary *)valForExport:(BOOL)exportFormat; + +- (BOOL)isEmpty; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m new file mode 100644 index 0000000..bc40b2b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FCompoundWrite.m @@ -0,0 +1,304 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FCompoundWrite.h" +#import "FImmutableTree.h" +#import "FNamedNode.h" +#import "FNode.h" +#import "FPath.h" +#import "FSnapshotUtilities.h" + +@interface FCompoundWrite () +@property(nonatomic, strong) FImmutableTree *writeTree; +@end + +@implementation FCompoundWrite + +- (id)initWithWriteTree:(FImmutableTree *)tree { + self = [super init]; + if (self) { + self.writeTree = tree; + } + return self; +} + ++ (FCompoundWrite *)compoundWriteWithValueDictionary: + (NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id value, BOOL *stop) { + id node = [FSnapshotUtilities nodeFrom:value]; + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)compoundWriteWithNodeDictionary:(NSDictionary *)dictionary { + __block FImmutableTree *writeTree = [FImmutableTree empty]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *pathString, + id node, BOOL *stop) { + FImmutableTree *tree = [[FImmutableTree alloc] initWithValue:node]; + writeTree = [writeTree setTree:tree + atPath:[[FPath alloc] initWith:pathString]]; + }]; + return [[FCompoundWrite alloc] initWithWriteTree:writeTree]; +} + ++ (FCompoundWrite *)emptyWrite { + static dispatch_once_t pred = 0; + static FCompoundWrite *empty = nil; + dispatch_once(&pred, ^{ + empty = [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:nil]]; + }); + return empty; +} + +- (FCompoundWrite *)addWrite:(id)node atPath:(FPath *)path { + if (path.isEmpty) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] initWithValue:node]]; + } else { + FTuplePathValue *rootMost = + [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path + to:path]; + id value = [rootMost.value updateChild:relativePath + withNewChild:node]; + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree setValue:value + atPath:rootMost.path]]; + } else { + FImmutableTree *subtree = + [[FImmutableTree alloc] initWithValue:node]; + FImmutableTree *newWriteTree = [self.writeTree setTree:subtree + atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } + } +} + +- (FCompoundWrite *)addWrite:(id)node atKey:(NSString *)key { + return [self addWrite:node atPath:[[FPath alloc] initWith:key]]; +} + +- (FCompoundWrite *)addCompoundWrite:(FCompoundWrite *)compoundWrite + atPath:(FPath *)path { + __block FCompoundWrite *newWrite = self; + [compoundWrite.writeTree forEach:^(FPath *childPath, id value) { + newWrite = [newWrite addWrite:value atPath:[path child:childPath]]; + }]; + return newWrite; +} + +/** + * Will remove a write at the given path and deeper paths. This will + * not modify a write at a higher location, which must be removed by + * calling this method with that path. + * @param path The path at which a write and all deeper writes should be + * removed. + * @return The new FWriteCompound with the removed path. + */ +- (FCompoundWrite *)removeWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return [FCompoundWrite emptyWrite]; + } else { + FImmutableTree *newWriteTree = + [self.writeTree setTree:[FImmutableTree empty] atPath:path]; + return [[FCompoundWrite alloc] initWithWriteTree:newWriteTree]; + } +} + +/** + * Returns whether this FCompoundWrite will fully overwrite a node at a given + * location and can therefore be considered "complete". + * @param path The path to check for + * @return Whether there is a complete write at that path. + */ +- (BOOL)hasCompleteWriteAtPath:(FPath *)path { + return [self completeNodeAtPath:path] != nil; +} + +/** + * Returns a node for a path if and only if the node is a "complete" overwrite + * at that path. This will not aggregate writes from depeer paths, but will + * return child nodes from a more shallow path. + * @param path The path to get a complete write + * @return The node if complete at that path, or nil otherwise. + */ +- (id)completeNodeAtPath:(FPath *)path { + FTuplePathValue *rootMost = [self.writeTree findRootMostValueAndPath:path]; + if (rootMost != nil) { + FPath *relativePath = [FPath relativePathFrom:rootMost.path to:path]; + return [rootMost.value getChild:relativePath]; + } else { + return nil; + } +} + +// TODO: change into traversal method... +- (NSArray *)completeChildren { + NSMutableArray *children = [[NSMutableArray alloc] init]; + if (self.writeTree.value != nil) { + id node = self.writeTree.value; + [node enumerateChildrenUsingBlock:^(NSString *key, id node, + BOOL *stop) { + [children addObject:[[FNamedNode alloc] initWithName:key + andNode:node]]; + }]; + } else { + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if (childTree.value != nil) { + [children addObject:[[FNamedNode alloc] + initWithName:childKey + andNode:childTree.value]]; + } + }]; + } + return children; +} + +// TODO: change into enumarate method +- (NSDictionary *)childCompoundWrites { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.writeTree.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *key, FImmutableTree *childWrite, BOOL *stop) { + dict[key] = [[FCompoundWrite alloc] initWithWriteTree:childWrite]; + }]; + return dict; +} + +- (FCompoundWrite *)childCompoundWriteAtPath:(FPath *)path { + if (path.isEmpty) { + return self; + } else { + id shadowingNode = [self completeNodeAtPath:path]; + if (shadowingNode != nil) { + return [[FCompoundWrite alloc] + initWithWriteTree:[[FImmutableTree alloc] + initWithValue:shadowingNode]]; + } else { + return [[FCompoundWrite alloc] + initWithWriteTree:[self.writeTree subtreeAtPath:path]]; + } + } +} + +- (id)applySubtreeWrite:(FImmutableTree *)subtreeWrite + atPath:(FPath *)relativePath + toNode:(id)node { + if (subtreeWrite.value != nil) { + // Since a write there is always a leaf, we're done here. + return [node updateChild:relativePath withNewChild:subtreeWrite.value]; + } else { + __block id priorityWrite = nil; + __block id blockNode = node; + [subtreeWrite.children + enumerateKeysAndObjectsUsingBlock:^( + NSString *childKey, FImmutableTree *childTree, BOOL *stop) { + if ([childKey isEqualToString:@".priority"]) { + // Apply priorities at the end so we don't update priorities + // for either empty nodes or forget to apply priorities to + // empty nodes that are later filled. + NSAssert(childTree.value != nil, + @"Priority writes must always be leaf nodes"); + priorityWrite = childTree.value; + } else { + blockNode = [self + applySubtreeWrite:childTree + atPath:[relativePath childFromString:childKey] + toNode:blockNode]; + } + }]; + // If there was a priority write, we only apply it if the node is not + // empty + if (![blockNode getChild:relativePath].isEmpty && + priorityWrite != nil) { + blockNode = [blockNode + updateChild:[relativePath childFromString:@".priority"] + withNewChild:priorityWrite]; + } + return blockNode; + } +} + +- (void)enumerateWrites:(void (^)(FPath *, id, BOOL *))block { + __block BOOL stop = NO; + // TODO: add stop to tree iterator... + [self.writeTree forEach:^(FPath *path, id value) { + if (!stop) { + block(path, value, &stop); + } + }]; +} + +/** + * Applies this FCompoundWrite to a node. The node is returned with all writes + * from this FCompoundWrite applied to the node. + * @param node The node to apply this FCompoundWrite to + * @return The node with all writes applied + */ +- (id)applyToNode:(id)node { + return [self applySubtreeWrite:self.writeTree + atPath:[FPath empty] + toNode:node]; +} + +/** + * Return true if this CompoundWrite is empty and therefore does not modify any + * nodes. + * @return Whether this CompoundWrite is empty + */ +- (BOOL)isEmpty { + return self.writeTree.isEmpty; +} + +- (id)rootWrite { + return self.writeTree.value; +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FCompoundWrite class]]) { + return NO; + } + FCompoundWrite *other = (FCompoundWrite *)object; + return + [[self valForExport:YES] isEqualToDictionary:[other valForExport:YES]]; +} + +- (NSUInteger)hash { + return [[self valForExport:YES] hash]; +} + +- (NSDictionary *)valForExport:(BOOL)exportFormat { + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + [self.writeTree forEach:^(FPath *path, id value) { + dictionary[path.wireFormat] = [value valForExport:exportFormat]; + }]; + return dictionary; +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h new file mode 100644 index 0000000..d002df0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FEmptyNode : NSObject + ++ (id)emptyNode; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m new file mode 100644 index 0000000..bde3a8a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FEmptyNode.m @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEmptyNode.h" +#import "FChildrenNode.h" + +@implementation FEmptyNode + ++ (id)emptyNode { + static FChildrenNode *empty = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + empty = [[FChildrenNode alloc] init]; + }); + return empty; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h new file mode 100644 index 0000000..b161dea --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIndex.h" +#import "FNamedNode.h" +#import "FNode.h" + +/** + * Represents a node together with an index. The index and node are updated in + * unison. In the case where the index does not affect the ordering (i.e. the + * ordering is identical to the key ordering) this class uses a fallback index + * to save memory. Everything operating on the index must special case the + * fallback index. + */ +@interface FIndexedNode : NSObject + +@property(nonatomic, strong, readonly) id node; + ++ (FIndexedNode *)indexedNodeWithNode:(id)node; ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index; + +- (BOOL)hasIndex:(id)index; +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode; +- (FIndexedNode *)updatePriority:(id)priority; + +- (FNamedNode *)firstChild; +- (FNamedNode *)lastChild; + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index; + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m new file mode 100644 index 0000000..dafe9c3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FIndexedNode.m @@ -0,0 +1,218 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIndexedNode.h" + +#import "FChildrenNode.h" +#import "FImmutableSortedSet.h" +#import "FIndex.h" +#import "FKeyIndex.h" +#import "FPriorityIndex.h" + +static FImmutableSortedSet *FALLBACK_INDEX; + +@interface FIndexedNode () + +@property(nonatomic, strong) id node; +/** + * The indexed set is initialized lazily to prevent creation when it is not + * needed + */ +@property(nonatomic, strong) FImmutableSortedSet *indexed; +@property(nonatomic, strong) id index; + +@end + +@implementation FIndexedNode + ++ (FImmutableSortedSet *)fallbackIndex { + static FImmutableSortedSet *fallbackIndex; + static dispatch_once_t once; + dispatch_once(&once, ^{ + fallbackIndex = [[FImmutableSortedSet alloc] init]; + }); + return fallbackIndex; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node { + return [[FIndexedNode alloc] initWithNode:node + index:[FPriorityIndex priorityIndex]]; +} + ++ (FIndexedNode *)indexedNodeWithNode:(id)node index:(id)index { + return [[FIndexedNode alloc] initWithNode:node index:index]; +} + +- (id)initWithNode:(id)node index:(id)index { + // Initialize indexed lazily + return [self initWithNode:node index:index indexed:nil]; +} + +- (id)initWithNode:(id)node + index:(id)index + indexed:(FImmutableSortedSet *)indexed { + self = [super init]; + if (self != nil) { + self->_node = node; + self->_index = index; + self->_indexed = indexed; + } + return self; +} + +- (void)ensureIndexed { + if (!self.indexed) { + if ([self.index isEqual:[FKeyIndex keyIndex]]) { + self.indexed = [FIndexedNode fallbackIndex]; + } else { + __block BOOL sawChild = NO; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + sawChild = sawChild || [self.index isDefinedOn:node]; + *stop = sawChild; + }]; + if (sawChild) { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [self.node enumerateChildrenUsingBlock:^( + NSString *key, id node, BOOL *stop) { + FNamedNode *namedNode = + [[FNamedNode alloc] initWithName:key andNode:node]; + dict[namedNode] = [NSNull null]; + }]; + // Make sure to assign index here, because the comparator will + // be retained and using self will cause a cycle + id index = self.index; + self.indexed = [FImmutableSortedSet + setWithKeysFromDictionary:dict + comparator:^NSComparisonResult( + FNamedNode *namedNode1, + FNamedNode *namedNode2) { + return [index compareNamedNode:namedNode1 + toNamedNode:namedNode2]; + }]; + } else { + self.indexed = [FIndexedNode fallbackIndex]; + } + } + } +} + +- (BOOL)hasIndex:(id)index { + return [self.index isEqual:index]; +} + +- (FIndexedNode *)updateChild:(NSString *)key + withNewChild:(id)newChildNode { + id newNode = [self.node updateImmediateChild:key + withNewChild:newChildNode]; + if (self.indexed == [FIndexedNode fallbackIndex] && + ![self.index isDefinedOn:newChildNode]) { + // doesn't affect the index, no need to create an index + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:[FIndexedNode fallbackIndex]]; + } else if (!self.indexed || self.indexed == [FIndexedNode fallbackIndex]) { + // No need to index yet, index lazily + return [[FIndexedNode alloc] initWithNode:newNode index:self.index]; + } else { + id oldChild = [self.node getImmediateChild:key]; + FImmutableSortedSet *newIndexed = [self.indexed + removeObject:[FNamedNode nodeWithName:key node:oldChild]]; + if (![newChildNode isEmpty]) { + newIndexed = [newIndexed + addObject:[FNamedNode nodeWithName:key node:newChildNode]]; + } + return [[FIndexedNode alloc] initWithNode:newNode + index:self.index + indexed:newIndexed]; + } +} + +- (FIndexedNode *)updatePriority:(id)priority { + return + [[FIndexedNode alloc] initWithNode:[self.node updatePriority:priority] + index:self.index + indexed:self.indexed]; +} + +- (FNamedNode *)firstChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) firstChild]; + } else { + return self.indexed.firstObject; + } + } +} + +- (FNamedNode *)lastChild { + if (![self.node isKindOfClass:[FChildrenNode class]]) { + return nil; + } else { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [((FChildrenNode *)self.node) lastChild]; + } else { + return self.indexed.lastObject; + } + } +} + +- (NSString *)predecessorForChildKey:(NSString *)childKey + childNode:(id)childNode + index:(id)index { + if (![self.index isEqual:index]) { + [NSException raise:NSInvalidArgumentException + format:@"Index not available in IndexedNode!"]; + } + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node predecessorChildKey:childKey]; + } else { + FNamedNode *node = [self.indexed + predecessorEntry:[FNamedNode nodeWithName:childKey node:childNode]]; + return node.name; + } +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + [self.node enumerateChildrenReverse:reverse usingBlock:block]; + } else { + [self.indexed + enumerateObjectsReverse:reverse + usingBlock:^(FNamedNode *namedNode, BOOL *stop) { + block(namedNode.name, namedNode.node, stop); + }]; + } +} + +- (NSEnumerator *)childEnumerator { + [self ensureIndexed]; + if (self.indexed == [FIndexedNode fallbackIndex]) { + return [self.node childEnumerator]; + } else { + return [self.indexed objectEnumerator]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h new file mode 100644 index 0000000..6bd2862 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FLeafNode : NSObject + +- (id)initWithValue:(id)aValue; +- (id)initWithValue:(id)aValue withPriority:(id)aPriority; + +@property(nonatomic, strong) id value; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m new file mode 100644 index 0000000..e741fd9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FLeafNode.m @@ -0,0 +1,266 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FLeafNode.h" +#import "FChildrenNode.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FImmutableSortedDictionary.h" +#import "FSnapshotUtilities.h" +#import "FStringUtilities.h" +#import "FUtilities.h" + +@interface FLeafNode () +@property(nonatomic, strong) id priorityNode; +@property(nonatomic, strong) NSString *lazyHash; + +@end + +@implementation FLeafNode + +@synthesize value; +@synthesize priorityNode; + +- (id)initWithValue:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.priorityNode = [FEmptyNode emptyNode]; + } + return self; +} + +- (id)initWithValue:(id)aValue withPriority:(id)aPriority { + self = [super init]; + if (self) { + self.value = aValue; + [FSnapshotUtilities validatePriorityNode:aPriority]; + self.priorityNode = aPriority; + } + return self; +} + +#pragma mark - +#pragma mark FNode methods + +- (BOOL)isLeafNode { + return YES; +} + +- (id)getPriority { + return self.priorityNode; +} + +- (id)updatePriority:(id)aPriority { + return [[FLeafNode alloc] initWithValue:self.value withPriority:aPriority]; +} + +- (id)getImmediateChild:(NSString *)childName { + if ([childName isEqualToString:@".priority"]) { + return self.priorityNode; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (id)getChild:(FPath *)path { + if (path.getFront == nil) { + return self; + } else if ([[path getFront] isEqualToString:@".priority"]) { + return [self getPriority]; + } else { + return [FEmptyNode emptyNode]; + } +} + +- (BOOL)hasChild:(NSString *)childName { + return + [childName isEqualToString:@".priority"] && ![self getPriority].isEmpty; +} + +- (NSString *)predecessorChildKey:(NSString *)childKey { + return nil; +} + +- (id)updateImmediateChild:(NSString *)childName + withNewChild:(id)newChildNode { + if ([childName isEqualToString:@".priority"]) { + return [self updatePriority:newChildNode]; + } else if (newChildNode.isEmpty) { + return self; + } else { + FChildrenNode *childrenNode = [[FChildrenNode alloc] init]; + childrenNode = [childrenNode updateImmediateChild:childName + withNewChild:newChildNode]; + childrenNode = [childrenNode updatePriority:self.priorityNode]; + return childrenNode; + } +} + +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode { + NSString *front = [path getFront]; + if (front == nil) { + return newChildNode; + } else if (newChildNode.isEmpty && ![front isEqualToString:@".priority"]) { + return self; + } else { + NSAssert(![front isEqualToString:@".priority"] || path.length == 1, + @".priority must be the last token in a path."); + return [self updateImmediateChild:front + withNewChild:[[FEmptyNode emptyNode] + updateChild:[path popFront] + withNewChild:newChildNode]]; + } +} + +- (id)val { + return [self valForExport:NO]; +} + +- (id)valForExport:(BOOL)exp { + if (exp && !self.getPriority.isEmpty) { + return @{ + kPayloadValue : self.value, + kPayloadPriority : [[self getPriority] val] + }; + } else { + return self.value; + } +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } else if (other.isLeafNode) { + FLeafNode *otherLeaf = other; + if ([FUtilities getJavascriptType:self.value] != + [FUtilities getJavascriptType:otherLeaf.value]) { + return NO; + } + return [otherLeaf.value isEqual:self.value] && + [otherLeaf.priorityNode isEqual:self.priorityNode]; + } else { + return NO; + } +} + +- (NSUInteger)hash { + return [self.value hash] * 17 + self.priorityNode.hash; +} + +- (id)withIndex:(id)index { + return self; +} + +- (BOOL)isIndexed:(id)index { + return YES; +} + +- (BOOL)isEmpty { + return NO; +} + +- (int)numChildren { + return 0; +} + +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *, id, + BOOL *))block { + // Nothing to iterate over +} + +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock: + (void (^)(NSString *, id, BOOL *))block { + // Nothing to iterate over +} + +- (NSEnumerator *)childEnumerator { + // Nothing to iterate over + return [@[] objectEnumerator]; +} + +- (NSString *)dataHash { + if (self.lazyHash == nil) { + NSMutableString *toHash = [[NSMutableString alloc] init]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:self + toString:toHash + hashVersion:FDataHashVersionV1]; + + self.lazyHash = [FStringUtilities base64EncodedSha1:toHash]; + } + return self.lazyHash; +} + +- (NSComparisonResult)compare:(id)other { + if (other == [FEmptyNode emptyNode]) { + return NSOrderedDescending; + } else if ([other isKindOfClass:[FChildrenNode class]]) { + return NSOrderedAscending; + } else { + NSAssert(other.isLeafNode, @"Compared against unknown type of node."); + return [self compareToLeafNode:(FLeafNode *)other]; + } +} + ++ (NSArray *)valueTypeOrder { + static NSArray *valueOrder = nil; + static dispatch_once_t once; + dispatch_once(&once, ^{ + valueOrder = @[ + kJavaScriptObject, kJavaScriptBoolean, kJavaScriptNumber, + kJavaScriptString + ]; + }); + return valueOrder; +} + +- (NSComparisonResult)compareToLeafNode:(FLeafNode *)other { + NSString *thisLeafType = [FUtilities getJavascriptType:self.value]; + NSString *otherLeafType = [FUtilities getJavascriptType:other.value]; + NSUInteger thisIndex = + [[FLeafNode valueTypeOrder] indexOfObject:thisLeafType]; + NSUInteger otherIndex = + [[FLeafNode valueTypeOrder] indexOfObject:otherLeafType]; + assert(thisIndex >= 0 && otherIndex >= 0); + if (otherIndex == thisIndex) { + // Same type. Compare values. + if (thisLeafType == kJavaScriptObject) { + // Deferred value nodes are all equal, but we should also never get + // to this point... + return NSOrderedSame; + } else if (thisLeafType == kJavaScriptString) { + return [self.value compare:other.value options:NSLiteralSearch]; + } else { + return [self.value compare:other.value]; + } + } else { + return thisIndex > otherIndex ? NSOrderedDescending + : NSOrderedAscending; + } +} + +- (NSString *)description { + return [[self valForExport:YES] description]; +} + +- (void)forEachChildDo:(fbt_bool_nsstring_node)action { + // There are no children, so there is nothing to do. + return; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h new file mode 100644 index 0000000..ea251b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FNode.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs_Private.h" +#import + +@protocol FIndex; + +@protocol FNode + +- (BOOL)isLeafNode; +- (id)getPriority; +- (id)updatePriority:(id)priority; +- (id)getImmediateChild:(NSString *)childKey; +- (id)getChild:(FPath *)path; +- (NSString *)predecessorChildKey:(NSString *)childKey; +- (id)updateImmediateChild:(NSString *)childKey + withNewChild:(id)newChildNode; +- (id)updateChild:(FPath *)path withNewChild:(id)newChildNode; +- (BOOL)hasChild:(NSString *)childKey; +- (BOOL)isEmpty; +- (int)numChildren; +- (id)val; +- (id)valForExport:(BOOL)exp; +- (NSString *)dataHash; +- (NSComparisonResult)compare:(id)other; +- (BOOL)isEqual:(id)other; +- (void)enumerateChildrenUsingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; +- (void)enumerateChildrenReverse:(BOOL)reverse + usingBlock:(void (^)(NSString *key, id node, + BOOL *stop))block; + +- (NSEnumerator *)childEnumerator; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h new file mode 100644 index 0000000..bf44660 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.h @@ -0,0 +1,49 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@class FImmutableSortedDictionary; +@class FCompoundWrite; +@class FLeafNode; +@protocol FNode; + +typedef NS_ENUM(NSInteger, FDataHashVersion) { + FDataHashVersionV1, + FDataHashVersionV2, +}; + +@interface FSnapshotUtilities : NSObject + ++ (id)nodeFrom:(id)val; ++ (id)nodeFrom:(id)val priority:(id)priority; ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn; ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn; ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn; ++ (void)validatePriorityNode:(id)priorityNode; ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)val + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion; ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString; + ++ (NSUInteger)estimateSerializedNodeSize:(id)node; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m new file mode 100644 index 0000000..f3f9ed5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Snapshot/FSnapshotUtilities.m @@ -0,0 +1,394 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FSnapshotUtilities.h" +#import "FChildrenNode.h" +#import "FCompoundWrite.h" +#import "FConstants.h" +#import "FEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FLeafNode.h" +#import "FMaxNode.h" +#import "FNamedNode.h" +#import "FUtilities.h" +#import "FValidation.h" + +@implementation FSnapshotUtilities + ++ (id)nodeFrom:(id)val { + return [FSnapshotUtilities nodeFrom:val priority:nil]; +} + ++ (id)nodeFrom:(id)val priority:(id)priority { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:@"nodeFrom:priority:"]; +} + ++ (id)nodeFrom:(id)val withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val priority:nil withValidationFrom:fn]; +} + ++ (id)nodeFrom:(id)val + priority:(id)priority + withValidationFrom:(NSString *)fn { + return [FSnapshotUtilities nodeFrom:val + priority:priority + withValidationFrom:fn + atDepth:0 + path:[[NSMutableArray alloc] init]]; +} + ++ (id)nodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + @autoreleasepool { + return [FSnapshotUtilities internalNodeFrom:val + priority:aPriority + withValidationFrom:fn + atDepth:depth + path:path]; + } +} + ++ (id)internalNodeFrom:(id)val + priority:(id)aPriority + withValidationFrom:(NSString *)fn + atDepth:(int)depth + path:(NSMutableArray *)path { + + if (depth > kFirebaseMaxObjectDepth) { + NSRange range; + range.location = 0; + range.length = 100; + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Max object depth exceeded: %@...", + fn, pathString] + userInfo:nil]; + } + + if (val == nil || val == [NSNull null]) { + // Null is a valid type to store + return [FEmptyNode emptyNode]; + } + + [FValidation validateFrom:fn isValidPriorityValue:aPriority withPath:path]; + id priority = [FSnapshotUtilities nodeFrom:aPriority]; + + id value = val; + BOOL isLeafNode = NO; + + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = val; + if (dict[kPayloadPriority] != nil) { + id rawPriority = [dict objectForKey:kPayloadPriority]; + [FValidation validateFrom:fn + isValidPriorityValue:rawPriority + withPath:path]; + priority = [FSnapshotUtilities nodeFrom:rawPriority]; + } + + if (dict[kPayloadValue] != nil) { + value = [dict objectForKey:kPayloadValue]; + if ([FValidation validateFrom:fn + isValidLeafValue:value + withPath:path]) { + isLeafNode = YES; + } else { + @throw [[NSException alloc] + initWithName:@"InvalidLeafValueType" + reason:[NSString stringWithFormat: + @"(%@) Invalid data type used " + @"with .value. Can only use " + "NSString and NSNumber or be " + "null. Found %@ instead.", + fn, [[value class] description]] + userInfo:nil]; + } + } + } + + if ([FValidation validateFrom:fn isValidLeafValue:value withPath:path]) { + isLeafNode = YES; + } + + if (isLeafNode) { + return [[FLeafNode alloc] initWithValue:value withPriority:priority]; + } + + // Unlike with JS, we have to handle the dictionary and array cases + // separately. + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = (NSDictionary *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:dval.count]; + + // Avoid creating a million newPaths by appending to old one + for (id keyId in dval) { + [FValidation validateFrom:fn + validDictionaryKey:keyId + withPath:path]; + NSString *key = (NSString *)keyId; + + if (![key hasPrefix:kPayloadMetadataPrefix]) { + [path addObject:key]; + id childNode = [FSnapshotUtilities nodeFrom:dval[key] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *aval = (NSArray *)value; + NSMutableDictionary *children = + [NSMutableDictionary dictionaryWithCapacity:aval.count]; + + for (int i = 0; i < [aval count]; i++) { + NSString *key = [NSString stringWithFormat:@"%i", i]; + [path addObject:key]; + id childNode = + [FSnapshotUtilities nodeFrom:[aval objectAtIndex:i] + priority:nil + withValidationFrom:fn + atDepth:depth + 1 + path:path]; + [path removeLastObject]; + + if (![childNode isEmpty]) { + children[key] = childNode; + } + } + + if ([children count] == 0) { + return [FEmptyNode emptyNode]; + } else { + FImmutableSortedDictionary *childrenDict = + [FImmutableSortedDictionary + fromDictionary:children + withComparator:[FUtilities keyComparator]]; + return [[FChildrenNode alloc] initWithPriority:priority + children:childrenDict]; + } + } else { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store object of type %@ at %@. " + "Can only store objects of type NSNumber, " + "NSString, NSDictionary, and NSArray.", + fn, [[value class] description], pathString] + userInfo:nil]; + } +} + ++ (FCompoundWrite *)compoundWriteFromDictionary:(NSDictionary *)values + withValidationFrom:(NSString *)fn { + FCompoundWrite *compoundWrite = [FCompoundWrite emptyWrite]; + + NSMutableArray *updatePaths = + [NSMutableArray arrayWithCapacity:values.count]; + for (NSString *keyId in values) { + id value = values[keyId]; + [FValidation validateFrom:fn + validUpdateDictionaryKey:keyId + withValue:value]; + + FPath *path = [FPath pathWithString:keyId]; + id node = [FSnapshotUtilities nodeFrom:value + withValidationFrom:fn]; + + [updatePaths addObject:path]; + compoundWrite = [compoundWrite addWrite:node atPath:path]; + } + + // Check that the update paths are not descendants of each other. + [updatePaths + sortUsingComparator:^NSComparisonResult(FPath *left, FPath *right) { + return [left compare:right]; + }]; + FPath *prevPath = nil; + for (FPath *path in updatePaths) { + if (prevPath != nil && [prevPath contains:path]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid path in object. Path " + @"(%@) is an ancestor of (%@).", + fn, prevPath, path] + userInfo:nil]; + } + prevPath = path; + } + + return compoundWrite; +} + ++ (void)validatePriorityNode:(id)priorityNode { + assert(priorityNode != nil); + if (priorityNode.isLeafNode) { + id val = priorityNode.val; + if ([val isKindOfClass:[NSDictionary class]]) { + NSDictionary *valDict __unused = (NSDictionary *)val; + NSAssert(valDict[kServerValueSubKey] != nil, + @"Priority can't be object unless it's a deferred value"); + } else { + NSString *jsType __unused = [FUtilities getJavascriptType:val]; + NSAssert(jsType == kJavaScriptString || jsType == kJavaScriptNumber, + @"Priority of unexpected type."); + } + } else { + NSAssert(priorityNode == [FMaxNode maxNode] || priorityNode.isEmpty, + @"Priority of unexpected type."); + } + // Don't call getPriority() on MAX_NODE to avoid hitting assertion. + NSAssert(priorityNode == [FMaxNode maxNode] || + priorityNode.getPriority.isEmpty, + @"Priority nodes can't have a priority of their own."); +} + ++ (void)appendHashRepresentationForLeafNode:(FLeafNode *)leafNode + toString:(NSMutableString *)string + hashVersion:(FDataHashVersion)hashVersion { + NSAssert(hashVersion == FDataHashVersionV1 || + hashVersion == FDataHashVersionV2, + @"Unknown hash version: %lu", (unsigned long)hashVersion); + if (!leafNode.getPriority.isEmpty) { + [string appendString:@"priority:"]; + [FSnapshotUtilities + appendHashRepresentationForLeafNode:leafNode.getPriority + toString:string + hashVersion:hashVersion]; + [string appendString:@":"]; + } + + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + [string appendString:jsType]; + [string appendString:@":"]; + + if (jsType == kJavaScriptBoolean) { + NSString *boolString = + [leafNode.val boolValue] ? kJavaScriptTrue : kJavaScriptFalse; + [string appendString:boolString]; + } else if (jsType == kJavaScriptNumber) { + NSString *numberString = + [FUtilities ieee754StringForNumber:leafNode.val]; + [string appendString:numberString]; + } else if (jsType == kJavaScriptString) { + if (hashVersion == FDataHashVersionV1) { + [string appendString:leafNode.val]; + } else { + NSAssert(hashVersion == FDataHashVersionV2, + @"Invalid hash version found"); + [FSnapshotUtilities appendHashV2RepresentationForString:leafNode.val + toString:string]; + } + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown value for hashing: %@", leafNode]; + } +} + ++ (void)appendHashV2RepresentationForString:(NSString *)string + toString:(NSMutableString *)mutableString { + string = [string stringByReplacingOccurrencesOfString:@"\\" + withString:@"\\\\"]; + string = [string stringByReplacingOccurrencesOfString:@"\"" + withString:@"\\\""]; + [mutableString appendString:@"\""]; + [mutableString appendString:string]; + [mutableString appendString:@"\""]; +} + ++ (NSUInteger)estimateLeafNodeSize:(FLeafNode *)leafNode { + NSString *jsType = [FUtilities getJavascriptType:leafNode.val]; + // These values are somewhat arbitrary, but we don't need an exact value so + // prefer performance over exact value + NSUInteger valueSize; + if (jsType == kJavaScriptNumber) { + valueSize = 8; // estimate each float with 8 bytes + } else if (jsType == kJavaScriptBoolean) { + valueSize = 4; // true or false need roughly 4 bytes + } else if (jsType == kJavaScriptString) { + valueSize = 2 + [leafNode.val length]; // add 2 for quotes + } else { + [NSException raise:NSInvalidArgumentException + format:@"Unknown leaf type: %@", leafNode]; + return 0; + } + + if (leafNode.getPriority.isEmpty) { + return valueSize; + } else { + // Account for extra overhead due to the extra JSON object and the + // ".value" and ".priority" keys, colons, comma + NSUInteger leafPriorityOverhead = 2 + 8 + 11 + 2 + 1; + return leafPriorityOverhead + valueSize + + [FSnapshotUtilities estimateLeafNodeSize:leafNode.getPriority]; + } +} + ++ (NSUInteger)estimateSerializedNodeSize:(id)node { + if ([node isEmpty]) { + return 4; // null keyword + } else if ([node isLeafNode]) { + return [FSnapshotUtilities estimateLeafNodeSize:node]; + } else { + NSAssert([node isKindOfClass:[FChildrenNode class]], + @"Unexpected node type: %@", [node class]); + __block NSUInteger sum = 1; // opening brackets + [((FChildrenNode *)node) enumerateChildrenAndPriorityUsingBlock:^( + NSString *key, id child, + BOOL *stop) { + sum += key.length; + sum += + 4; // quotes around key and colon and (comma or closing bracket) + sum += [FSnapshotUtilities estimateSerializedNodeSize:child]; + }]; + return sum; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h new file mode 100644 index 0000000..b8668d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FAtomicNumber : NSObject + +- (NSNumber *)getAndIncrement; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m new file mode 100644 index 0000000..20cfd8d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FAtomicNumber.m @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FAtomicNumber.h" + +@interface FAtomicNumber () { + unsigned long number; +} + +@property(nonatomic, strong) NSLock *lock; + +@end + +@implementation FAtomicNumber + +@synthesize lock; + +- (id)init { + self = [super init]; + if (self) { + number = 1; + self.lock = [[NSLock alloc] init]; + } + return self; +} + +- (NSNumber *)getAndIncrement { + NSNumber *result; + + // See: + // http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW14 + // to improve, etc. + + [self.lock lock]; + result = [NSNumber numberWithUnsignedLong:number]; + number = number + 1; + [self.lock unlock]; + + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h new file mode 100644 index 0000000..fc19ca7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseConfig.h" +#import "FIRDatabaseQuery.h" +#import "FTypedefs_Private.h" + +@interface FEventEmitter : NSObject + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue; + +- (id)getInitialEventForType:(NSString *)eventType; +- (void)triggerEventType:(NSString *)eventType data:(id)data; + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block; +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle; + +- (void)validateEventType:(NSString *)eventType; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m new file mode 100644 index 0000000..7d02239 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FEventEmitter.m @@ -0,0 +1,161 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FEventEmitter.h" +#import "FIRDatabaseQuery_Private.h" +#import "FRepoManager.h" +#import "FUtilities.h" + +@interface FEventListener : NSObject + +@property(nonatomic, copy) fbt_void_id userCallback; +@property(nonatomic) FIRDatabaseHandle handle; + +@end + +@implementation FEventListener + +@synthesize userCallback; +@synthesize handle; + +@end + +@interface FEventEmitter () + +@property(nonatomic, strong) NSArray *allowedEvents; +@property(nonatomic, strong) NSMutableDictionary *listeners; +@property(nonatomic, strong) dispatch_queue_t queue; + +@end + +@implementation FEventEmitter + +@synthesize allowedEvents; +@synthesize listeners; + +- (id)initWithAllowedEvents:(NSArray *)theAllowedEvents + queue:(dispatch_queue_t)queue { + if (theAllowedEvents == nil || [theAllowedEvents count] == 0) { + @throw [NSException + exceptionWithName:@"AllowedEventsValidation" + reason:@"FEventEmitters must be initialized with at " + @"least one valid event." + userInfo:nil]; + } + + self = [super init]; + + if (self) { + self.allowedEvents = [theAllowedEvents copy]; + self.listeners = [[NSMutableDictionary alloc] init]; + self.queue = queue; + } + + return self; +} + +- (id)getInitialEventForType:(NSString *)eventType { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"You must override getInitialEvent: " + @"when subclassing FEventEmitter" + userInfo:nil]; +} + +- (void)triggerEventType:(NSString *)eventType data:(id)data { + [self validateEventType:eventType]; + NSMutableDictionary *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in eventTypeListeners) { + [self triggerListener:listener withData:data]; + } +} + +- (void)triggerListener:(FEventListener *)listener withData:(id)data { + // TODO, should probably get this from FRepo or something although it ends + // up being the same. (Except maybe for testing) + if (listener.userCallback) { + dispatch_async(self.queue, ^{ + listener.userCallback(data); + }); + } +} + +- (FIRDatabaseHandle)observeEventType:(NSString *)eventType + withBlock:(fbt_void_id)block { + [self validateEventType:eventType]; + + // Create listener + FEventListener *listener = [[FEventListener alloc] init]; + listener.handle = [[FUtilities LUIDGenerator] integerValue]; + listener.userCallback = block; // copies block automatically + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self addEventListener:listener forEventType:eventType]; + }); + + return listener.handle; +} + +- (void)addEventListener:(FEventListener *)listener + forEventType:(NSString *)eventType { + // Get or initializer listeners map [FIRDatabaseHandle -> callback block] + // for eventType + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + if (eventTypeListeners == nil) { + eventTypeListeners = [[NSMutableArray alloc] init]; + [self.listeners setObject:eventTypeListeners forKey:eventType]; + } + + // Add listener and fire the current event for this listener + [eventTypeListeners addObject:listener]; + id initialData = [self getInitialEventForType:eventType]; + [self triggerListener:listener withData:initialData]; +} + +- (void)removeObserverForEventType:(NSString *)eventType + withHandle:(FIRDatabaseHandle)handle { + [self validateEventType:eventType]; + + dispatch_async([FIRDatabaseQuery sharedQueue], ^{ + [self removeEventListenerWithHandle:handle forEventType:eventType]; + }); +} + +- (void)removeEventListenerWithHandle:(FIRDatabaseHandle)handle + forEventType:(NSString *)eventType { + NSMutableArray *eventTypeListeners = + [self.listeners objectForKey:eventType]; + for (FEventListener *listener in [eventTypeListeners copy]) { + if (handle == NSNotFound || handle == listener.handle) { + [eventTypeListeners removeObject:listener]; + } + } +} + +- (void)validateEventType:(NSString *)eventType { + if ([self.allowedEvents indexOfObject:eventType] == NSNotFound) { + @throw [NSException + exceptionWithName:@"InvalidEventType" + reason:[NSString stringWithFormat: + @"%@ is not a valid event type. %@ " + @"is the list of valid events.", + eventType, self.allowedEvents] + userInfo:nil]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h new file mode 100644 index 0000000..5a66196 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.h @@ -0,0 +1,23 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FNextPushId : NSObject + ++ (NSString *)get:(NSTimeInterval)now; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m new file mode 100644 index 0000000..864e147 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FNextPushId.m @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNextPushId.h" +#import "FUtilities.h" + +static NSString *const PUSH_CHARS = + @"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; + +@implementation FNextPushId + ++ (NSString *)get:(NSTimeInterval)currentTime { + static long long lastPushTime = 0; + static int lastRandChars[12]; + + long long now = (long long)(currentTime * 1000); + + BOOL duplicateTime = now == lastPushTime; + lastPushTime = now; + + unichar timeStampChars[8]; + for (int i = 7; i >= 0; i--) { + timeStampChars[i] = [PUSH_CHARS characterAtIndex:(now % 64)]; + now = (long long)floor(now / 64); + } + + NSMutableString *id = [[NSMutableString alloc] init]; + [id appendString:[NSString stringWithCharacters:timeStampChars length:8]]; + + if (!duplicateTime) { + for (int i = 0; i < 12; i++) { + lastRandChars[i] = (int)floor(arc4random() % 64); + } + } else { + int i = 0; + for (i = 11; i >= 0 && lastRandChars[i] == 63; i--) { + lastRandChars[i] = 0; + } + lastRandChars[i]++; + } + + for (int i = 0; i < 12; i++) { + [id appendFormat:@"%C", [PUSH_CHARS characterAtIndex:lastRandChars[i]]]; + } + + return [NSString stringWithString:id]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h new file mode 100644 index 0000000..1c07284 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FRepoInfo.h" + +@interface FParsedUrl : NSObject + +@property(nonatomic, strong) FRepoInfo *repoInfo; +@property(nonatomic, strong) FPath *path; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m new file mode 100644 index 0000000..eb83330 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FParsedUrl.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FParsedUrl.h" + +@implementation FParsedUrl + +@synthesize repoInfo; +@synthesize path; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h new file mode 100644 index 0000000..f7d19b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FStringUtilities : NSObject + ++ (NSString *)base64EncodedSha1:(NSString *)str; ++ (NSString *)urlDecoded:(NSString *)url; ++ (NSString *)urlEncoded:(NSString *)url; ++ (NSString *)sanitizedForUserAgent:(NSString *)str; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m new file mode 100644 index 0000000..2515257 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FStringUtilities.m @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FStringUtilities.h" +#import "NSData+SRB64Additions.h" +#import + +@implementation FStringUtilities + +// http://stackoverflow.com/questions/3468268/objective-c-sha1 +// http://stackoverflow.com/questions/7310457/ios-objective-c-sha-1-and-base64-problem ++ (NSString *)base64EncodedSha1:(NSString *)str { + const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding]; + // NSString reports length in characters, but we want it in bytes, which + // strlen will give us. + unsigned long dataLen = strlen(cstr); + NSData *data = [NSData dataWithBytes:cstr length:dataLen]; + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CC_SHA1(data.bytes, (unsigned int)data.length, digest); + NSData *output = [[NSData alloc] initWithBytes:digest + length:CC_SHA1_DIGEST_LENGTH]; + return [FSRUtilities base64EncodedStringFromData:output]; +} + ++ (NSString *)urlDecoded:(NSString *)url { + NSString *replaced = [url stringByReplacingOccurrencesOfString:@"+" + withString:@" "]; + NSString *decoded = [replaced stringByRemovingPercentEncoding]; + // This is kind of a hack, but is generally how the js client works. We + // could run into trouble if some piece is a correctly escaped %-sequence, + // and another isn't. But, that's bad input anyways... + if (decoded) { + return decoded; + } else { + return replaced; + } +} + ++ (NSString *)urlEncoded:(NSString *)url { + // Didn't seem like there was an Apple NSCharacterSet that had our version + // of the encoding So I made my own, following RFC 2396 + // https://www.ietf.org/rfc/rfc2396.txt allowedCharacters = alphanum | "-" | + // "_" | "~" + NSCharacterSet *allowedCharacters = [NSCharacterSet + characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGH" + @"IJKLMNOPQRSTUVWXYZ0123456789-_~"]; + return [url + stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; +} + ++ (NSString *)sanitizedForUserAgent:(NSString *)str { + return + [str stringByReplacingOccurrencesOfString:@"/|_" + withString:@"|" + options:NSRegularExpressionSearch + range:NSMakeRange(0, [str length])]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h new file mode 100644 index 0000000..56d97ff --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FTypedefs.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#ifndef Firebase_FTypedefs_h +#define Firebase_FTypedefs_h + +/** + * Stub... + */ +@class FIRDataSnapshot; +@class FIRDatabaseReference; +@class FAuthData; +@protocol FNode; + +// fbt = Firebase Block Typedef + +typedef void (^fbt_void_void)(void); +typedef void (^fbt_void_datasnapshot_nsstring)(FIRDataSnapshot *snapshot, + NSString *prevName); +typedef void (^fbt_void_datasnapshot)(FIRDataSnapshot *snapshot); +typedef void (^fbt_void_user)(FAuthData *user); +typedef void (^fbt_void_nsstring_id)(NSString *status, id data); +typedef void (^fbt_void_nserror_id)(NSError *error, id data); +typedef void (^fbt_void_nserror)(NSError *error); +typedef void (^fbt_void_nserror_ref)(NSError *error, FIRDatabaseReference *ref); +typedef void (^fbt_void_nserror_user)(NSError *error, FAuthData *user); +typedef void (^fbt_void_nserror_json)(NSError *error, NSDictionary *json); +typedef void (^fbt_void_nsdictionary)(NSDictionary *data); +typedef id (^fbt_id_node_nsstring)(id node, NSString *childName); + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h new file mode 100644 index 0000000..9458f24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.h @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +#import "FParsedUrl.h" + +@interface FUtilities : NSObject + ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size; ++ (NSNumber *)LUIDGenerator; ++ (FParsedUrl *)parseUrl:(NSString *)url; ++ (NSString *)getJavascriptType:(id)obj; ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason; ++ (NSNumber *)intForString:(NSString *)string; ++ (NSString *)ieee754StringForNumber:(NSNumber *)val; ++ (void)setLoggingEnabled:(BOOL)enabled; ++ (BOOL)getLoggingEnabled; + ++ (NSString *)minName; ++ (NSString *)maxName; ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b; ++ (NSComparator)stringComparator; ++ (NSComparator)keyComparator; + ++ (double)randomDouble; + +@end + +typedef enum { + FLogLevelDebug = 1, + FLogLevelInfo = 2, + FLogLevelWarn = 3, + FLogLevelError = 4, + FLogLevelNone = 5 +} FLogLevel; + +// Log tags +FOUNDATION_EXPORT NSString *const kFPersistenceLogTag; + +#define FFLog(code, format, ...) FFDebug((code), (format), ##__VA_ARGS__) + +#define FFDebug(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelDebug)) { \ + FIRLogDebug(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFInfo(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelInfo)) { \ + FIRLogError(kFIRLoggerDatabase, (code), (format), ##__VA_ARGS__); \ + } \ + } while (0) + +#define FFWarn(code, format, ...) \ + do { \ + if (FFIsLoggingEnabled(FLogLevelWarn)) { \ + FIRLogWarning(kFIRLoggerDatabase, (code), (format), \ + ##__VA_ARGS__); \ + } \ + } while (0) + +extern FIRLoggerService kFIRLoggerDatabase; +BOOL FFIsLoggingEnabled(FLogLevel logLevel); +void firebaseUncaughtExceptionHandler(NSException *exception); +void firebaseJobsTroll(void); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m new file mode 100644 index 0000000..a24c134 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FUtilities.m @@ -0,0 +1,433 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FUtilities.h" +#import "FAtomicNumber.h" +#import "FConstants.h" +#import "FStringUtilities.h" +#import + +#define ARC4RANDOM_MAX 0x100000000 +#define INTEGER_32_MIN (-2147483648) +#define INTEGER_32_MAX 2147483647 + +#pragma mark - +#pragma mark C functions + +FIRLoggerService kFIRLoggerDatabase = @"[Firebase/Database]"; +static FLogLevel logLevel = FLogLevelInfo; // Default log level is info +static NSMutableDictionary *options = nil; + +BOOL FFIsLoggingEnabled(FLogLevel level) { return level >= logLevel; } + +void firebaseJobsTroll(void) { + FFLog(@"I-RDB095001", + @"password super secret; JFK conspiracy; Hello there! Having fun " + @"digging through Firebase? We're always hiring! jobs@firebase.com"); +} + +#pragma mark - +#pragma mark Private property and singleton specification + +@interface FUtilities () { +} + +@property(nonatomic, strong) FAtomicNumber *localUid; + ++ (FUtilities *)singleton; + +@end + +@implementation FUtilities + +@synthesize localUid; + +- (id)init { + self = [super init]; + if (self) { + self.localUid = [[FAtomicNumber alloc] init]; + } + return self; +} + +// TODO: We really want to be able to set the log level ++ (void)setLoggingEnabled:(BOOL)enabled { + logLevel = enabled ? FLogLevelDebug : FLogLevelInfo; +} + ++ (BOOL)getLoggingEnabled { + return logLevel == FLogLevelDebug; +} + ++ (FUtilities *)singleton { + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +// Refactor as a category of NSString ++ (NSArray *)splitString:(NSString *)str intoMaxSize:(const unsigned int)size { + if (str.length <= size) { + return [NSArray arrayWithObject:str]; + } + + NSMutableArray *dataSegs = [[NSMutableArray alloc] init]; + for (int c = 0; c < str.length; c += size) { + if (c + size > str.length) { + int rangeStart = c; + unsigned long rangeLength = size - ((c + size) - str.length); + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } else { + int rangeStart = c; + int rangeLength = size; + [dataSegs + addObject:[str substringWithRange:NSMakeRange(rangeStart, + rangeLength)]]; + } + } + return dataSegs; +} + ++ (NSNumber *)LUIDGenerator { + FUtilities *f = [FUtilities singleton]; + return [f.localUid getAndIncrement]; +} + ++ (NSString *)decodePath:(NSString *)pathString { + NSMutableArray *decodedPieces = [[NSMutableArray alloc] init]; + NSArray *pieces = [pathString componentsSeparatedByString:@"/"]; + for (NSString *piece in pieces) { + if (piece.length > 0) { + [decodedPieces addObject:[FStringUtilities urlDecoded:piece]]; + } + } + return [NSString + stringWithFormat:@"/%@", [decodedPieces componentsJoinedByString:@"/"]]; +} + ++ (NSString *)extractPathFromUrlString:(NSString *)url { + NSString *path = url; + + NSRange schemeIndex = [path rangeOfString:@"//"]; + if (schemeIndex.location != NSNotFound) { + path = [path substringFromIndex:schemeIndex.location + 2]; + } + + NSUInteger pathIndex = [path rangeOfString:@"/"].location; + if (pathIndex != NSNotFound) { + path = [path substringFromIndex:pathIndex + 1]; + } else { + path = @""; + } + + NSUInteger queryParamIndex = [path rangeOfString:@"?"].location; + if (queryParamIndex != NSNotFound) { + path = [path substringToIndex:queryParamIndex]; + } + + return path; +} + ++ (FParsedUrl *)parseUrl:(NSString *)url { + // For backwards compatibility, support URLs without schemes on iOS. + if (![url containsString:@"://"]) { + url = [@"http://" stringByAppendingString:url]; + } + + NSString *originalPathString = [self extractPathFromUrlString:url]; + + // Sanitize the database URL by removing the path component, which may + // contain invalid URL characters. + NSString *sanitizedUrlWithoutPath = + [url stringByReplacingOccurrencesOfString:originalPathString + withString:@""]; + NSURLComponents *urlComponents = + [NSURLComponents componentsWithString:sanitizedUrlWithoutPath]; + if (!urlComponents) { + [NSException raise:@"Failed to parse database URL" + format:@"Failed to parse database URL: %@", url]; + } + + NSString *host = [urlComponents.host lowercaseString]; + NSString *namespace; + bool secure; + + if (urlComponents.port != nil) { + secure = [urlComponents.scheme isEqualToString:@"https"] || + [urlComponents.scheme isEqualToString:@"wss"]; + host = [host stringByAppendingFormat:@":%@", urlComponents.port]; + } else { + secure = YES; + }; + + NSArray *parts = [urlComponents.host componentsSeparatedByString:@"."]; + if ([parts count] == 3) { + namespace = [parts[0] lowercaseString]; + } else { + // Attempt to extract namespace from "ns" query param. + NSArray *queryItems = urlComponents.queryItems; + for (NSURLQueryItem *item in queryItems) { + if ([item.name isEqualToString:@"ns"]) { + namespace = item.value; + break; + } + } + + if (!namespace) { + namespace = [parts[0] lowercaseString]; + } + } + + NSString *pathString = [self + decodePath:[NSString stringWithFormat:@"/%@", originalPathString]]; + FPath *path = [[FPath alloc] initWith:pathString]; + FRepoInfo *repoInfo = [[FRepoInfo alloc] initWithHost:host + isSecure:secure + withNamespace:namespace]; + + FFLog(@"I-RDB095002", @"---> Parsed (%@) to: (%@,%@); ns=(%@); path=(%@)", + url, [repoInfo description], [repoInfo connectionURL], + repoInfo.namespace, [path description]); + + FParsedUrl *parsedUrl = [[FParsedUrl alloc] init]; + parsedUrl.repoInfo = repoInfo; + parsedUrl.path = path; + + return parsedUrl; +} + +/* + case str: JString => priString + "string:" + str.s; + case bool: JBool => priString + "boolean:" + bool.value; + case double: JDouble => priString + "number:" + double.num; + case int: JInt => priString + "number:" + int.num; + case _ => { + error("Leaf node has value '" + data.value + "' of invalid type '" + + data.value.getClass.toString + "'"); + ""; + } + */ + ++ (NSString *)getJavascriptType:(id)obj { + if ([obj isKindOfClass:[NSDictionary class]]) { + return kJavaScriptObject; + } else if ([obj isKindOfClass:[NSString class]]) { + return kJavaScriptString; + } else if ([obj isKindOfClass:[NSNumber class]]) { + // We used to just compare to @encode(BOOL) as suggested at + // http://stackoverflow.com/questions/2518761/get-type-of-nsnumber, but + // on arm64, @encode(BOOL) returns "B" instead of "c" even though + // objCType still returns 'c' (signed char). So check both. + if (strcmp([obj objCType], @encode(BOOL)) == 0 || + strcmp([obj objCType], @encode(signed char)) == 0) { + return kJavaScriptBoolean; + } else { + return kJavaScriptNumber; + } + } else { + return kJavaScriptNull; + } +} + ++ (NSError *)errorForStatus:(NSString *)status andReason:(NSString *)reason { + static dispatch_once_t pred = 0; + __strong static NSDictionary *errorMap = nil; + __strong static NSDictionary *errorCodes = nil; + dispatch_once(&pred, ^{ + errorMap = @{ + @"permission_denied" : @"Permission Denied", + @"unavailable" : @"Service is unavailable", + kFErrorWriteCanceled : @"Write cancelled by user" + }; + errorCodes = @{ + @"permission_denied" : @1, + @"unavailable" : @2, + kFErrorWriteCanceled : @3 + }; + }); + + if ([status isEqualToString:kFWPResponseForActionStatusOk]) { + return nil; + } else { + NSInteger code; + NSString *desc = nil; + if (reason) { + desc = reason; + } else if ([errorMap objectForKey:status] != nil) { + desc = [errorMap objectForKey:status]; + } else { + desc = status; + } + + if ([errorCodes objectForKey:status] != nil) { + NSNumber *num = [errorCodes objectForKey:status]; + code = [num integerValue]; + } else { + // XXX what to do here? + code = 9999; + } + + return [[NSError alloc] + initWithDomain:kFErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : desc}]; + } +} + ++ (NSNumber *)intForString:(NSString *)string { + static NSCharacterSet *notDigits = nil; + if (!notDigits) { + notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; + } + if ([string rangeOfCharacterFromSet:notDigits].length == 0) { + NSInteger num; + NSScanner *scanner = [NSScanner scannerWithString:string]; + if ([scanner scanInteger:&num]) { + return [NSNumber numberWithInteger:num]; + } + } + return nil; +} + ++ (NSString *)ieee754StringForNumber:(NSNumber *)val { + double d = [val doubleValue]; + NSData *data = [NSData dataWithBytes:&d length:sizeof(double)]; + NSMutableString *str = [[NSMutableString alloc] init]; + const unsigned char *buffer = (const unsigned char *)[data bytes]; + for (int i = 0; i < data.length; i++) { + unsigned char byte = buffer[7 - i]; + [str appendFormat:@"%02x", byte]; + } + return str; +} + +static inline BOOL tryParseStringToInt(__unsafe_unretained NSString *str, + NSInteger *integer) { + // First do some cheap checks (NOTE: The below checks are significantly + // faster than an equivalent regex :-( ). + NSUInteger length = str.length; + if (length > 11 || length == 0) { + return NO; + } + long long value = 0; + BOOL negative = NO; + NSUInteger i = 0; + if ([str characterAtIndex:0] == '-') { + if (length == 1) { + return NO; + } + negative = YES; + i = 1; + } + for (; i < length; i++) { + unichar c = [str characterAtIndex:i]; + // Must be a digit, or '-' if it's the first char. + if (c < '0' || c > '9') { + return NO; + } else { + int charValue = c - '0'; + value = value * 10 + charValue; + } + } + + value = (negative) ? -value : value; + + if (value < INTEGER_32_MIN || value > INTEGER_32_MAX) { + return NO; + } else { + *integer = (NSInteger)value; + return YES; + } +} + ++ (NSString *)maxName { + static dispatch_once_t once; + static NSString *maxName; + dispatch_once(&once, ^{ + maxName = [[NSString alloc] initWithFormat:@"[MAX_NAME]"]; + }); + return maxName; +} + ++ (NSString *)minName { + static dispatch_once_t once; + static NSString *minName; + dispatch_once(&once, ^{ + minName = [[NSString alloc] initWithFormat:@"[MIN_NAME]"]; + }); + return minName; +} + ++ (NSComparisonResult)compareKey:(NSString *)a toKey:(NSString *)b { + if (a == b) { + return NSOrderedSame; + } else if (a == [FUtilities minName] || b == [FUtilities maxName]) { + return NSOrderedAscending; + } else if (b == [FUtilities minName] || a == [FUtilities maxName]) { + return NSOrderedDescending; + } else { + NSInteger aAsInt, bAsInt; + if (tryParseStringToInt(a, &aAsInt)) { + if (tryParseStringToInt(b, &bAsInt)) { + if (aAsInt > bAsInt) { + return NSOrderedDescending; + } else if (aAsInt < bAsInt) { + return NSOrderedAscending; + } else if (a.length > b.length) { + return NSOrderedDescending; + } else if (a.length < b.length) { + return NSOrderedAscending; + } else { + return NSOrderedSame; + } + } else { + return (NSComparisonResult)NSOrderedAscending; + } + } else if (tryParseStringToInt(b, &bAsInt)) { + return (NSComparisonResult)NSOrderedDescending; + } else { + // Perform literal character by character search to prevent a > b && + // b > a issues. Note that calling -(NSString + // *)decomposedStringWithCanonicalMapping also works. + return [a compare:b options:NSLiteralSearch]; + } + } +} + ++ (NSComparator)keyComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [FUtilities compareKey:a toKey:b]; + }; +} + ++ (NSComparator)stringComparator { + return ^NSComparisonResult(__unsafe_unretained NSString *a, + __unsafe_unretained NSString *b) { + return [a compare:b]; + }; +} + ++ (double)randomDouble { + return ((double)arc4random() / ARC4RANDOM_MAX); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h new file mode 100644 index 0000000..276eb26 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.h @@ -0,0 +1,55 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDataEventType.h" +#import "FParsedUrl.h" +#import "FPath.h" +#import "FTypedefs.h" +#import + +@interface FValidation : NSObject + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path; ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event; ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString; ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key; ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl; + ++ (void)validateToken:(NSString *)token; + +// Functions for handling passing errors back ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback; ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback; + +// Functions used for validating while creating snapshots in FSnapshotUtilities ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path; ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value; ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path; ++ (BOOL)validatePriorityValue:value; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m new file mode 100644 index 0000000..c700b9c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/FValidation.m @@ -0,0 +1,461 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FValidation.h" +#import "FConstants.h" +#import "FParsedUrl.h" +#import "FTypedefs.h" + +// Have to escape: * ? + [ ( ) { } ^ $ | \ . / +// See: +// https://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html + +NSString *const kInvalidPathCharacters = @"[].#$"; +NSString *const kInvalidKeyCharacters = @"[].#$/"; + +@implementation FValidation + ++ (void)validateFrom:(NSString *)fn writablePath:(FPath *)path { + if ([[path getFront] isEqualToString:kDotInfoPrefix]) { + @throw [[NSException alloc] + initWithName:@"WritablePathValidation" + reason:[NSString + stringWithFormat:@"(%@) failed to path %@: Can't " + @"modify data under %@", + fn, [path description], + kDotInfoPrefix] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn knownEventType:(FIRDataEventType)event { + switch (event) { + case FIRDataEventTypeValue: + case FIRDataEventTypeChildAdded: + case FIRDataEventTypeChildChanged: + case FIRDataEventTypeChildMoved: + case FIRDataEventTypeChildRemoved: + return; + break; + default: + @throw [[NSException alloc] + initWithName:@"KnownEventTypeValidation" + reason:[NSString + stringWithFormat:@"(%@) Unknown event type: %d", + fn, (int)event] + userInfo:nil]; + break; + } +} + ++ (BOOL)isValidPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSCharacterSet *badPathChars = nil; + dispatch_once(&token, ^{ + badPathChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidPathCharacters]; + }); + return pathString != nil && [pathString length] != 0 && + [pathString rangeOfCharacterFromSet:badPathChars].location == + NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validPathString:(NSString *)pathString { + if (![self isValidPathString:pathString]) { + @throw [[NSException alloc] + initWithName:@"InvalidPathValidation" + reason:[NSString stringWithFormat: + @"(%@) Must be a non-empty string and " + @"not contain '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validRootPathString:(NSString *)pathString { + static dispatch_once_t token; + static NSRegularExpression *dotInfoRegex = nil; + dispatch_once(&token, ^{ + dotInfoRegex = [NSRegularExpression + regularExpressionWithPattern:@"^\\/*\\.info(\\/|$)" + options:0 + error:nil]; + }); + + NSString *tempPath = pathString; + // HACK: Obj-C regex are kinda' slow. Do a plain string search first before + // bothering with the regex. + if ([pathString rangeOfString:@".info"].location != NSNotFound) { + tempPath = [dotInfoRegex + stringByReplacingMatchesInString:pathString + options:0 + range:NSMakeRange(0, pathString.length) + withTemplate:@"/"]; + } + [self validateFrom:fn validPathString:tempPath]; +} + ++ (BOOL)isValidKey:(NSString *)key { + static dispatch_once_t token; + static NSCharacterSet *badKeyChars = nil; + dispatch_once(&token, ^{ + badKeyChars = [NSCharacterSet + characterSetWithCharactersInString:kInvalidKeyCharacters]; + }); + return key != nil && key.length > 0 && + [key rangeOfCharacterFromSet:badKeyChars].location == NSNotFound; +} + ++ (void)validateFrom:(NSString *)fn validKey:(NSString *)key { + if (![self isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidKeyValidation" + reason:[NSString + stringWithFormat: + @"(%@) Must be a non-empty string and not " + @"contain '/' '.' '#' '$' '[' or ']'", + fn] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn validURL:(FParsedUrl *)parsedUrl { + NSString *pathString = [parsedUrl.path description]; + [self validateFrom:fn validRootPathString:pathString]; +} + +#pragma mark - +#pragma mark Authentication validation + ++ (BOOL)stringNonempty:(NSString *)str { + return str != nil && ![str isKindOfClass:[NSNull class]] && str.length > 0; +} + ++ (void)validateToken:(NSString *)token { + if (![FValidation stringNonempty:token]) { + [NSException raise:NSInvalidArgumentException + format:@"Can't have empty string or nil for custom token"]; + } +} + +#pragma mark - +#pragma mark Handling authentication errors + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withUserCallback:(fbt_void_nserror_id)userCallback { + if (userCallback) { + userCallback(error, nil); + } +} + +/** + * This function immediately calls the callback. + * It assumes that it is not on FirebaseWorker thread. + * It assumes it's on a user-controlled thread. + */ ++ (void)handleError:(NSError *)error + withSuccessCallback:(fbt_void_nserror)userCallback { + if (userCallback) { + userCallback(error); + } +} + +#pragma mark - +#pragma mark Snapshot validation + ++ (BOOL)validateFrom:(NSString *)fn + isValidLeafValue:(id)value + withPath:(NSArray *)path { + if ([value isKindOfClass:[NSString class]]) { + // Try to avoid conversion to bytes if possible + NSString *theString = value; + if ([theString maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize && + [theString lengthOfBytesUsingEncoding:NSUTF8StringEncoding] > + kFirebaseMaxLeafSize) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) String exceeds max " + @"size of %u utf8 bytes: %@", + fn, (int)kFirebaseMaxLeafSize, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSNumber class]]) { + // Cannot store NaN, but otherwise can store NSNumbers. + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store NaN at path: %@.", fn, + pathString] + userInfo:nil]; + } + return YES; + } + + else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys.%@.", + fn, pathString] + userInfo:nil]; + } + return YES; + } + return NO; + } + + else if (value == [NSNull null] || value == nil) { + // Null is valid type to store at leaf + return YES; + } + + return NO; +} + ++ (NSString *)parseAndValidateKey:(id)keyId + fromFunction:(NSString *)fn + path:(NSArray *)path { + if (![keyId isKindOfClass:[NSString class]]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat:@"(%@) Non-string keys are not " + @"allowed in object at path: %@", + fn, pathString] + userInfo:nil]; + } + return (NSString *)keyId; +} + ++ (void)validateFrom:(NSString *)fn + validDictionaryKey:(id)keyId + withPath:(NSArray *)path { + NSString *key = [self parseAndValidateKey:keyId fromFunction:fn path:path]; + if (![key isEqualToString:kPayloadPriority] && + ![key isEqualToString:kPayloadValue] && + ![key isEqualToString:kServerValueSubKey] && + ![FValidation isValidKey:key]) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Invalid key in object at path: " + @"%@. Keys must be non-empty and cannot " + @"contain '/' '.' '#' '$' '[' or ']'", + fn, pathString] + userInfo:nil]; + } +} + ++ (void)validateFrom:(NSString *)fn + validUpdateDictionaryKey:(id)keyId + withValue:(id)value { + FPath *path = [FPath pathWithString:[self parseAndValidateKey:keyId + fromFunction:fn + path:@[]]]; + __block NSInteger keyNum = 0; + [path enumerateComponentsUsingBlock:^void(NSString *key, BOOL *stop) { + if ([key isEqualToString:kPayloadPriority] && + keyNum == [path length] - 1) { + [self validateFrom:fn isValidPriorityValue:value withPath:@[]]; + } else { + keyNum++; + + if (![FValidation isValidKey:key]) { + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Invalid key in object. Keys must " + @"be non-empty and cannot contain '.' " + @"'#' '$' '[' or ']'", + fn] + userInfo:nil]; + } + } + }]; +} + ++ (void)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path { + [self validateFrom:fn + isValidPriorityValue:value + withPath:path + throwError:YES]; +} + +/** + * Returns YES if priority is valid. + */ ++ (BOOL)validatePriorityValue:value { + return [self validateFrom:nil + isValidPriorityValue:value + withPath:nil + throwError:NO]; +} + +/** + * Helper for validating priorities. If passed YES for throwError, it'll throw + * descriptive errors on validation problems. Else, it'll just return YES/NO. + */ ++ (BOOL)validateFrom:(NSString *)fn + isValidPriorityValue:(id)value + withPath:(NSArray *)path + throwError:(BOOL)throwError { + if ([value isKindOfClass:[NSNumber class]]) { + if ([[NSDecimalNumber notANumber] isEqualToNumber:value]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store NaN as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } else if (value == (id)kCFBooleanFalse || + value == (id)kCFBooleanTrue) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store true/false " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *dval = value; + if (dval[kServerValueSubKey] != nil) { + if ([dval count] > 1) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store other keys " + @"with server value keys as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = [[path subarrayWithRange:range] + componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString + stringWithFormat: + @"(%@) Cannot store an NSDictionary " + @"as priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + } else if ([value isKindOfClass:[NSArray class]]) { + if (throwError) { + NSRange range; + range.location = 0; + range.length = MIN(path.count, 50); + NSString *pathString = + [[path subarrayWithRange:range] componentsJoinedByString:@"."]; + @throw [[NSException alloc] + initWithName:@"InvalidFirebaseData" + reason:[NSString stringWithFormat: + @"(%@) Cannot store an NSArray as " + @"priority at path: %@.", + fn, pathString] + userInfo:nil]; + } else { + return NO; + } + } + + // It's valid! + return YES; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h new file mode 100644 index 0000000..f5c0859 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs.h" +#import + +@interface FTupleBoolBlock : NSObject + +@property(nonatomic, readwrite) BOOL boolean; +@property(nonatomic, copy) fbt_void_void block; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m new file mode 100644 index 0000000..c4cd8bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleBoolBlock.h" + +@implementation FTupleBoolBlock + +@synthesize boolean; +@synthesize block; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h new file mode 100644 index 0000000..bd8c4a9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleCallbackStatus : NSObject +@property(nonatomic, copy) fbt_void_nsstring_nsstring block; +@property(nonatomic) NSString *status; +@property(nonatomic) NSString *errorReason; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m new file mode 100644 index 0000000..05914bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m @@ -0,0 +1,22 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleCallbackStatus.h" + +@implementation FTupleCallbackStatus +@synthesize block; +@synthesize status; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h new file mode 100644 index 0000000..5e41f9e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRDatabaseReference.h" +#import + +@interface FTupleFirebase : NSObject + +@property(nonatomic, strong) FIRDatabaseReference *one; +@property(nonatomic, strong) FIRDatabaseReference *two; +@property(nonatomic, strong) FIRDatabaseReference *three; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m new file mode 100644 index 0000000..3956f8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleFirebase.m @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleFirebase.h" + +@implementation FTupleFirebase + +@synthesize one; +@synthesize two; +@synthesize three; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h new file mode 100644 index 0000000..19b5217 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.h @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import "FPath.h" +#import + +@interface FTupleNodePath : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, strong) id node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m new file mode 100644 index 0000000..620ae76 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleNodePath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleNodePath.h" + +@implementation FTupleNodePath + +@synthesize path; +@synthesize node; + +- (id)initWithNode:(id)aNode andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.path = aPath; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h new file mode 100644 index 0000000..1717a22 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleObjectNode : NSObject + +- (id)initWithObject:(id)aObj andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) id obj; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m new file mode 100644 index 0000000..4c533b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjectNode.m @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import "FTupleObjectNode.h" + +@implementation FTupleObjectNode + +@synthesize obj; +@synthesize node; + +- (id)initWithObject:(id)aObj andNode:(id)aNode { + self = [super init]; + if (self) { + self.obj = aObj; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h new file mode 100644 index 0000000..05b3141 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleObjects : NSObject + +@property(nonatomic, strong) id objA; +@property(nonatomic, strong) id objB; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m new file mode 100644 index 0000000..a9e4c88 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleObjects.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleObjects.h" + +@implementation FTupleObjects + +@synthesize objA; +@synthesize objB; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h new file mode 100644 index 0000000..e68ab71 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTypedefs_Private.h" +#import + +@interface FTupleOnDisconnect : NSObject + +@property(strong, nonatomic) NSString *pathString; +@property(strong, nonatomic) NSString *action; +@property(strong, nonatomic) id data; +@property(strong, nonatomic) fbt_void_nsstring_nsstring onComplete; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m new file mode 100644 index 0000000..bd45822 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleOnDisconnect.h" + +@implementation FTupleOnDisconnect + +@synthesize pathString; +@synthesize action; +@synthesize data; +@synthesize onComplete; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h new file mode 100644 index 0000000..b0a515c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FPath; + +@interface FTuplePathValue : NSObject +@property(nonatomic, strong, readonly) FPath *path; +@property(nonatomic, strong, readonly) id value; +- (id)initWithPath:(FPath *)aPath value:(id)aValue; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m new file mode 100644 index 0000000..91de883 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTuplePathValue.m @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTuplePathValue.h" +#import "FPath.h" + +@interface FTuplePathValue () +@property(nonatomic, strong, readwrite) id value; +@property(nonatomic, strong, readwrite) FPath *path; +@end + +@implementation FTuplePathValue +@synthesize path; +@synthesize value; + +- (id)initWithPath:(FPath *)aPath value:(id)aValue { + self = [super init]; + if (self) { + self.value = aValue; + self.path = aPath; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h new file mode 100644 index 0000000..7269c2f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h @@ -0,0 +1,30 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FTupleRemovedQueriesEvents : NSObject +/** + * `FIRDatabaseQuery`s removed with [SyncPoint removeEventRegistration:] + */ +@property(nonatomic, strong, readonly) NSArray *removedQueries; +/** + * cancel events as FEvent + */ +@property(nonatomic, strong, readonly) NSArray *cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events; +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m new file mode 100644 index 0000000..324cfcb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m @@ -0,0 +1,37 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleRemovedQueriesEvents.h" + +@interface FTupleRemovedQueriesEvents () +@property(nonatomic, strong, readwrite) NSArray *removedQueries; +@property(nonatomic, strong, readwrite) NSArray *cancelEvents; +@end + +@implementation FTupleRemovedQueriesEvents +@synthesize removedQueries; +@synthesize cancelEvents; + +- (id)initWithRemovedQueries:(NSArray *)removed cancelEvents:(NSArray *)events { + self = [super init]; + if (self) { + self.removedQueries = removed; + self.cancelEvents = events; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h new file mode 100644 index 0000000..337f8d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import + +@interface FTupleSetIdPath : NSObject + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath; + +@property(strong, nonatomic) NSNumber *setId; +@property(strong, nonatomic) FPath *path; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m new file mode 100644 index 0000000..2763c83 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleSetIdPath.h" + +@implementation FTupleSetIdPath + +@synthesize path; +@synthesize setId; + +- (id)initWithSetId:(NSNumber *)aSetId andPath:(FPath *)aPath { + self = [super init]; + if (self) { + self.setId = aSetId; + self.path = aPath; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h new file mode 100644 index 0000000..0e3d7fa --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.h @@ -0,0 +1,27 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FNode.h" +#import + +@interface FTupleStringNode : NSObject + +- (id)initWithString:(NSString *)aString andNode:(id)aNode; + +@property(nonatomic, strong) id node; +@property(nonatomic, strong) NSString *string; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m new file mode 100644 index 0000000..d820ef8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleStringNode.m @@ -0,0 +1,33 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" + +@implementation FTupleStringNode + +@synthesize string; +@synthesize node; + +- (id)initWithString:(NSString *)aString andNode:(id)aNode { + self = [super init]; + if (self) { + self.string = aString; + self.node = aNode; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h new file mode 100644 index 0000000..b1052da --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.h @@ -0,0 +1,25 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleStringNode.h" +#import + +@interface FTupleTSN : NSObject + +@property(nonatomic, strong) FTupleStringNode *from; +@property(nonatomic, strong) FTupleStringNode *to; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m new file mode 100644 index 0000000..348c319 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTSN.m @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTSN.h" + +@implementation FTupleTSN + +@synthesize from; +@synthesize to; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h new file mode 100644 index 0000000..82f4495 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FPath.h" +#import "FTypedefs.h" +#import "FTypedefs_Private.h" +#import + +@interface FTupleTransaction : NSObject + +@property(nonatomic, strong) FPath *path; +@property(nonatomic, copy) fbt_transactionresult_mutabledata update; +@property(nonatomic, copy) fbt_void_nserror_bool_datasnapshot onComplete; +@property(nonatomic) FTransactionStatus status; + +/** + * Used when combining transaction at different locations to figure out which + * one goes first. + */ +@property(nonatomic, strong) NSNumber *order; +/** + * Whether to raise local events for this transaction + */ +@property(nonatomic) BOOL applyLocally; + +/** + * Count how many times we've retried the transaction + */ +@property(nonatomic) int retryCount; + +/** + * Function to call to clean up our listener + */ +@property(nonatomic, copy) fbt_void_void unwatcher; + +/** + * Stores why a transaction was aborted + */ +@property(nonatomic, strong, readonly) NSString *abortStatus; +@property(nonatomic, strong, readonly) NSString *abortReason; + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason; +- (NSError *)abortError; + +@property(nonatomic, strong) NSNumber *currentWriteId; + +/** + * Stores the input snapshot, before the update + */ +@property(nonatomic, strong) id currentInputSnapshot; + +/** + * Stores the unresolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotRaw; + +/** + * Stores the resolved (for server values) output snapshot, after the update + */ +@property(nonatomic, strong) id currentOutputSnapshotResolved; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m new file mode 100644 index 0000000..68977ef --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleTransaction.m @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleTransaction.h" +#import "FUtilities.h" + +@interface FTupleTransaction () + +@property(nonatomic, strong) NSString *abortStatus; +@property(nonatomic, strong) NSString *abortReason; + +@end + +@implementation FTupleTransaction + +- (void)setAbortStatus:(NSString *)abortStatus reason:(NSString *)reason { + self.abortStatus = abortStatus; + self.abortReason = reason; +} + +- (NSError *)abortError { + return (self.abortStatus != nil) + ? [FUtilities errorForStatus:self.abortStatus + andReason:self.abortReason] + : nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h new file mode 100644 index 0000000..b94eef6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.h @@ -0,0 +1,32 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FQueryParams.h" +#import "FTypedefs.h" +#import + +@interface FTupleUserCallback : NSObject + +- (id)initWithHandle:(NSUInteger)handle; + +@property(nonatomic, copy) + fbt_void_datasnapshot_nsstring datasnapshotPrevnameCallback; +@property(nonatomic, copy) fbt_void_datasnapshot datasnapshotCallback; +@property(nonatomic, copy) fbt_void_nserror cancelCallback; +@property(nonatomic, copy) FQueryParams *queryParams; +@property(nonatomic) NSUInteger handle; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m new file mode 100644 index 0000000..ba5861f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/Utilities/Tuples/FTupleUserCallback.m @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FTupleUserCallback.h" + +@implementation FTupleUserCallback + +@synthesize datasnapshotCallback; +@synthesize datasnapshotPrevnameCallback; +@synthesize cancelCallback; +@synthesize queryParams; +@synthesize handle; + +- (id)initWithHandle:(NSUInteger)theHandle { + self = [super init]; + if (self) { + self.handle = theHandle; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h new file mode 100644 index 0000000..3ab7476 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h @@ -0,0 +1,21 @@ +#import +#import "FImmutableSortedDictionary.h" + +/** + * This is an array backed implementation of FImmutableSortedDictionary. It uses arrays and linear lookups to achieve + * good memory efficiency while maintaining good performance for small collections. It also uses less allocations than + * a comparable red black tree. To avoid degrading performance with increasing collection size it will automatically + * convert to a FTreeSortedDictionary after an insert call above a certain threshold. + */ +@interface FArraySortedDictionary : FImmutableSortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (id)initWithComparator:(NSComparator)comparator; + +#pragma mark - +#pragma mark Properties + +@property (nonatomic, copy, readonly) NSComparator comparator; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m new file mode 100644 index 0000000..15d2d8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m @@ -0,0 +1,266 @@ +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +@interface FArraySortedDictionaryEnumerator : NSEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse; +- (id)nextObject; + +@property (nonatomic) NSInteger pos; +@property (nonatomic) BOOL reverse; +@property (nonatomic, strong) NSArray *keys; + +@end + +@implementation FArraySortedDictionaryEnumerator + +- (id)initWithKeys:(NSArray *)keys startPos:(NSInteger)pos isReverse:(BOOL)reverse +{ + self = [super init]; + if (self != nil) { + self->_pos = pos; + self->_reverse = reverse; + self->_keys = keys; + } + return self; +} + +- (id)nextObject +{ + NSInteger pos = self->_pos; + if (pos >= 0 && pos < self.keys.count) { + if (self.reverse) { + self->_pos--; + } else { + self->_pos++; + } + return self.keys[pos]; + } else { + return nil; + } +} + +@end + +@interface FArraySortedDictionary () + +- (id)initWithComparator:(NSComparator)comparator; + +@property (nonatomic, copy, readwrite) NSComparator comparator; +@property (nonatomic, strong) NSArray *keys; +@property (nonatomic, strong) NSArray *values; + +@end + +@implementation FArraySortedDictionary + ++ (FArraySortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + NSMutableArray *keys = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [keys addObject:key]; + }]; + [keys sortUsingComparator:comparator]; + + [keys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(keys[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + NSMutableArray *values = [NSMutableArray arrayWithCapacity:keys.count]; + NSInteger pos = 0; + for (id key in keys) { + values[pos++] = dictionary[key]; + } + NSAssert(values.count == keys.count, @"We added as many keys as values"); + return [[FArraySortedDictionary alloc] initWithComparator:comparator keys:keys values:values]; +} + +- (id)initWithComparator:(NSComparator)comparator +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = [NSArray array]; + self->_values = [NSArray array]; + } + return self; +} + +- (id)initWithComparator:(NSComparator)comparator keys:(NSArray *)keys values:(NSArray *)values +{ + self = [super init]; + if (self != nil) { + self->_comparator = comparator; + self->_keys = keys; + self->_values = values; + } + return self; +} + +- (NSInteger) findInsertPositionForKey:(id)key +{ + NSInteger newPos = 0; + while (newPos < self.keys.count && self.comparator(self.keys[newPos], key) < NSOrderedSame) { + newPos++; + } + return newPos; +} + +- (NSInteger) findKey:(id)key +{ + if (key == nil) { + return NSNotFound; + } + for (NSInteger pos = 0; pos < self.keys.count; pos++) { + NSComparisonResult result = self.comparator(key, self.keys[pos]); + if (result == NSOrderedSame) { + return pos; + } else if (result == NSOrderedAscending) { + return NSNotFound; + } + } + return NSNotFound; +} + +- (FImmutableSortedDictionary *) insertKey:(id)key withValue:(id)value +{ + NSInteger pos = [self findKey:key]; + + if (pos == NSNotFound) { + /* + * If we're above the threshold we want to convert it to a tree backed implementation to not have + * degrading performance + */ + if (self.count >= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:self.count]; + for (NSInteger i = 0; i < self.keys.count; i++) { + dict[self.keys[i]] = self.values[i]; + } + dict[key] = value; + return [FTreeSortedDictionary fromDictionary:dict withComparator:self.comparator]; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + NSInteger newPos = [self findInsertPositionForKey:key]; + [newKeys insertObject:key atIndex:newPos]; + [newValues insertObject:value atIndex:newPos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + newKeys[pos] = key; + newValues[pos] = value; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (FImmutableSortedDictionary *) removeKey:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return self; + } else { + NSMutableArray *newKeys = [NSMutableArray arrayWithArray:self.keys]; + NSMutableArray *newValues = [NSMutableArray arrayWithArray:self.values]; + [newKeys removeObjectAtIndex:pos]; + [newValues removeObjectAtIndex:pos]; + return [[FArraySortedDictionary alloc] initWithComparator:self.comparator keys:newKeys values:newValues]; + } +} + +- (id) get:(id)key +{ + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + return nil; + } else { + return self.values[pos]; + } +} + +- (id) getPredecessorKey:(id) key { + NSInteger pos = [self findKey:key]; + if (pos == NSNotFound) { + [NSException raise:NSInternalInconsistencyException format:@"Can't get predecessor key for non-existent key"]; + return nil; + } else if (pos == 0) { + return nil; + } else { + return self.keys[pos - 1]; + } +} + +- (BOOL) isEmpty { + return self.keys.count == 0; +} + +- (int) count +{ + return (int)self.keys.count; +} + +- (id) minKey +{ + return [self.keys firstObject]; +} + +- (id) maxKey +{ + return [self.keys lastObject]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + BOOL stop = NO; + for (NSInteger i = self.keys.count - 1; i >= 0; i--) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } else { + BOOL stop = NO; + for (NSInteger i = 0; i < self.keys.count; i++) { + block(self.keys[i], self.values[i], &stop); + if (stop) return; + } + } +} + +- (BOOL) contains:(id)key { + return [self findKey:key] != NSNotFound; +} + +- (NSEnumerator *) keyEnumerator { + return [self.keys objectEnumerator]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [self.keys reverseObjectEnumerator]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + NSInteger startPos = [self findInsertPositionForKey:startKey]; + // if there's no exact match, findKeyOrInsertPosition will return the index *after* the closest match, but + // since this is a reverse iterator, we want to start just *before* the closest match. + if (startPos >= self.keys.count || self.comparator(self.keys[startPos], startKey) != NSOrderedSame) { + startPos -= 1; + } + return [[FArraySortedDictionaryEnumerator alloc] initWithKeys:self.keys startPos:startPos isReverse:YES]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h new file mode 100644 index 0000000..d6687d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h @@ -0,0 +1,54 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import + +/** + * The size threshold where we use a tree backed sorted map instead of an array backed sorted map. + * This is a more or less arbitrary chosen value, that was chosen to be large enough to fit most of object kind + * of Firebase data, but small enough to not notice degradation in performance for inserting and lookups. + * Feel free to empirically determine this constant, but don't expect much gain in real world performance. + */ +#define SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD 25 + +@interface FImmutableSortedDictionary : NSObject + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator; ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator; + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FImmutableSortedDictionary *) removeKey:(id)aKey; +- (id) get:(id) key; +- (id) getPredecessorKey:(id) key; +- (BOOL) isEmpty; +- (int) count; +- (id) minKey; +- (id) maxKey; +- (void) enumerateKeysAndObjectsUsingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void(^)(id key, id value, BOOL *stop))block; +- (BOOL) contains:(id)key; +- (NSEnumerator *) keyEnumerator; +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey; +- (NSEnumerator *) reverseKeyEnumerator; +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey; + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(id)anObject forKey:(id)aKey; +- (id) objectForKey:(id)key; +- (FImmutableSortedDictionary *) removeObjectForKey:(id)aKey; + +@end + diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m new file mode 100644 index 0000000..659c63b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m @@ -0,0 +1,142 @@ +#import "FImmutableSortedDictionary.h" +#import "FArraySortedDictionary.h" +#import "FTreeSortedDictionary.h" + +#define THROW_ABSTRACT_METHOD_EXCEPTION(sel) do { \ + @throw [NSException exceptionWithName:NSInternalInconsistencyException \ + reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(sel)] \ + userInfo:nil]; \ +} while(0) + +@implementation FImmutableSortedDictionary + ++ (FImmutableSortedDictionary *)dictionaryWithComparator:(NSComparator)comparator +{ + return [[FArraySortedDictionary alloc] initWithComparator:comparator]; +} + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + if (dictionary.count <= SORTED_DICTIONARY_ARRAY_TO_RB_TREE_SIZE_THRESHOLD) { + return [FArraySortedDictionary fromDictionary:dictionary withComparator:comparator]; + } else { + return [FTreeSortedDictionary fromDictionary:dictionary withComparator:comparator]; + } +} + +- (FImmutableSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(insertKey:withValue:)); +} + +- (FImmutableSortedDictionary *) removeKey:(id)aKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(removeKey:)); +} + +- (id) get:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(get:)); +} + +- (id) getPredecessorKey:(id) key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(getPredecessorKey:)); +} + +- (BOOL) isEmpty { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(isEmpty)); +} + +- (int) count { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector((count))); +} + +- (id) minKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(minKey)); +} + +- (id) maxKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(maxKey)); +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsUsingBlock:)); +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(enumerateKeysAndObjectsReverse:usingBlock:)); +} + +- (BOOL) contains:(id)key { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(contains:)); +} + +- (NSEnumerator *) keyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumerator)); +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(keyEnumeratorFrom:)); +} + +- (NSEnumerator *) reverseKeyEnumerator { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumerator)); +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + THROW_ABSTRACT_METHOD_EXCEPTION(@selector(reverseKeyEnumeratorFrom:)); +} + +- (BOOL)isEqual:(id)object { + if (![object isKindOfClass:[FImmutableSortedDictionary class]]) { + return NO; + } + FImmutableSortedDictionary *other = (FImmutableSortedDictionary *)object; + if (self.count != other.count) { + return NO; + } + __block BOOL isEqual = YES; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + id otherValue = [other objectForKey:key]; + isEqual = isEqual && (value == otherValue || [value isEqual:otherValue]); + *stop = !isEqual; + }]; + return isEqual; +} + +- (NSUInteger)hash { + __block NSUInteger hash = 0; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + hash = (hash * 31 + [key hash]) * 17 + [value hash]; + }]; + return hash; +} + +- (NSString *)description { + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"{ "]; + [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@: %@", key, value]]; + }]; + [str appendString:@" }"]; + return str; +} + +#pragma mark - +#pragma mark Methods similar to NSMutableDictionary + +- (FImmutableSortedDictionary *) setObject:(__unsafe_unretained id)anObject forKey:(__unsafe_unretained id)aKey { + return [self insertKey:aKey withValue:anObject]; +} + +- (FImmutableSortedDictionary *) removeObjectForKey:(__unsafe_unretained id)aKey { + return [self removeKey:aKey]; +} + +- (id) objectForKey:(__unsafe_unretained id)key { + return [self get:key]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h new file mode 100644 index 0000000..ac15c2f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h @@ -0,0 +1,22 @@ +#import + +@interface FImmutableSortedSet : NSObject + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)array comparator:(NSComparator)comparator; + +- (BOOL)containsObject:(id)object; +- (FImmutableSortedSet *)addObject:(id)object; +- (FImmutableSortedSet *)removeObject:(id)object; +- (id)firstObject; +- (id)lastObject; +- (NSUInteger)count; +- (BOOL)isEmpty; + +- (id)predecessorEntry:(id)entry; + +- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block; +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id obj, BOOL *stop))block; + +- (NSEnumerator *)objectEnumerator; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m new file mode 100644 index 0000000..1953af1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m @@ -0,0 +1,115 @@ +#import "FImmutableSortedSet.h" +#import "FImmutableSortedDictionary.h" + +@interface FImmutableSortedSet () + +@property (nonatomic, strong) FImmutableSortedDictionary *dictionary; + +@end + +@implementation FImmutableSortedSet + ++ (FImmutableSortedSet *)setWithKeysFromDictionary:(NSDictionary *)dictionary comparator:(NSComparator)comparator +{ + FImmutableSortedDictionary *setDict = [FImmutableSortedDictionary fromDictionary:dictionary withComparator:comparator]; + return [[FImmutableSortedSet alloc] initWithDictionary:setDict]; +} + +- (id)initWithDictionary:(FImmutableSortedDictionary *)dictionary +{ + self = [super init]; + if (self != nil) { + self->_dictionary = dictionary; + } + return self; +} + +- (BOOL)contains:(id)object +{ + return [self.dictionary contains:object]; +} + +- (FImmutableSortedSet *)addObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary insertKey:object withValue:[NSNull null]]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (FImmutableSortedSet *)removeObject:(id)object +{ + FImmutableSortedDictionary *newDictionary = [self.dictionary removeObjectForKey:object]; + if (newDictionary != self.dictionary) { + return [[FImmutableSortedSet alloc] initWithDictionary:newDictionary]; + } else { + return self; + } +} + +- (BOOL)containsObject:(id)object +{ + return [self.dictionary contains:object]; +} + +- (id)firstObject +{ + return [self.dictionary minKey]; +} + +- (id)lastObject +{ + return [self.dictionary maxKey]; +} + +- (id)predecessorEntry:(id)entry +{ + return [self.dictionary getPredecessorKey:entry]; +} + +- (NSUInteger)count +{ + return [self.dictionary count]; +} + +- (BOOL)isEmpty +{ + return [self.dictionary isEmpty]; +} + +- (void)enumerateObjectsUsingBlock:(void (^)(id, BOOL *))block +{ + [self enumerateObjectsReverse:NO usingBlock:block]; +} + +- (void)enumerateObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, BOOL *))block +{ + [self.dictionary enumerateKeysAndObjectsReverse:reverse usingBlock:^(id key, id value, BOOL *stop) { + block(key, stop); + }]; +} + +- (NSEnumerator *)objectEnumerator +{ + return [self.dictionary keyEnumerator]; +} + +- (NSString *)description +{ + NSMutableString *str = [[NSMutableString alloc] init]; + __block BOOL first = YES; + [str appendString:@"FImmutableSortedSet ( "]; + [self enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { + if (!first) { + [str appendString:@", "]; + } + first = NO; + [str appendString:[NSString stringWithFormat:@"%@", obj]]; + }]; + [str appendString:@" )"]; + return str; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h new file mode 100644 index 0000000..833f2a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h @@ -0,0 +1,27 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBEmptyNode : NSObject + ++ (id)emptyNode; + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m new file mode 100644 index 0000000..3ca6f06 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m @@ -0,0 +1,72 @@ +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" + +@implementation FLLRBEmptyNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + ++ (id)emptyNode +{ + static dispatch_once_t pred = 0; + __strong static id _sharedObject = nil; + dispatch_once(&pred, ^{ + _sharedObject = [[self alloc] init]; // or some other init method + }); + return _sharedObject; +} + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight { + return self; +} + +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator { + FLLRBValueNode* result = [[FLLRBValueNode alloc] initWithKey:aKey withValue:aValue withColor:nil withLeft:nil withRight:nil]; + return result; +} + +- (id) remove:(id) key withComparator:(NSComparator)aComparator { + return self; +} + +- (int) count { + return 0; +} + +- (BOOL) isEmpty { + return YES; +} + +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return NO; +} + +- (id) min { + return self; +} + +- (id) minKey { + return nil; +} + +- (id) maxKey { + return nil; +} + +- (BOOL) isRed { + return NO; +} + +- (int) check { + return 0; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h new file mode 100644 index 0000000..09b234c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h @@ -0,0 +1,29 @@ +#import + +#define RED @true +#define BLACK @false + +typedef NSNumber FLLRBColor; + +@protocol FLLRBNode + +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) key withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h new file mode 100644 index 0000000..50438bb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h @@ -0,0 +1,29 @@ +#import +#import "FLLRBNode.h" + +@interface FLLRBValueNode : NSObject + + +- (id)initWithKey:(id) key withValue:(id) value withColor:(FLLRBColor*) color withLeft:(id)left withRight:(id)right; +- (id)copyWith:(id) aKey withValue:(id) aValue withColor:(FLLRBColor*) aColor withLeft:(id)aLeft withRight:(id)aRight; +- (id) insertKey:(id) aKey forValue:(id)aValue withComparator:(NSComparator)aComparator; +- (id) remove:(id) aKey withComparator:(NSComparator)aComparator; +- (int) count; +- (BOOL) isEmpty; +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action; +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action; +- (id) min; +- (id) minKey; +- (id) maxKey; +- (BOOL) isRed; +- (int) check; + +- (BOOL) checkMaxDepth; + +@property (nonatomic, strong) id key; +@property (nonatomic, strong) id value; +@property (nonatomic, strong) FLLRBColor* color; +@property (nonatomic, strong) id left; +@property (nonatomic, strong) id right; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m new file mode 100644 index 0000000..831b97f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m @@ -0,0 +1,230 @@ +#import "FLLRBValueNode.h" +#import "FLLRBEmptyNode.h" + +@implementation FLLRBValueNode + +@synthesize key, value, color, left, right; + +- (NSString *) description { + return [NSString stringWithFormat:@"[key=%@ val=%@ color=%@]", key, value, + (color != nil ? @"true" : @"false")]; +} + +- (id)initWithKey:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight +{ + self = [super init]; + if (self) { + self.key = aKey; + self.value = aValue; + self.color = aColor != nil ? aColor : RED; + self.left = aLeft != nil ? aLeft : [FLLRBEmptyNode emptyNode]; + self.right = aRight != nil ? aRight : [FLLRBEmptyNode emptyNode]; + } + return self; +} + +- (id)copyWith:(__unsafe_unretained id) aKey withValue:(__unsafe_unretained id) aValue withColor:(__unsafe_unretained FLLRBColor*) aColor withLeft:(__unsafe_unretained id)aLeft withRight:(__unsafe_unretained id)aRight { + return [[FLLRBValueNode alloc] initWithKey:(aKey != nil) ? aKey : self.key + withValue:(aValue != nil) ? aValue : self.value + withColor:(aColor != nil) ? aColor : self.color + withLeft:(aLeft != nil) ? aLeft : self.left + withRight:(aRight != nil) ? aRight : self.right]; +} + +- (int) count { + return [self.left count] + 1 + [self.right count]; +} + +- (BOOL) isEmpty { + return NO; +} + +/** +* Early terminates if aciton returns YES. +* @return The first truthy value returned by action, or the last falsey value returned by action. +*/ +- (BOOL) inorderTraversal:(BOOL (^)(id key, id value))action { + return [self.left inorderTraversal:action] || + action(self.key, self.value) || + [self.right inorderTraversal:action]; +} + +- (BOOL) reverseTraversal:(BOOL (^)(id key, id value))action { + return [self.right reverseTraversal:action] || + action(self.key, self.value) || + [self.left reverseTraversal:action]; +} + +- (id) min { + if([self.left isEmpty]) { + return self; + } + else { + return [self.left min]; + } +} + +- (id) minKey { + return [[self min] key]; +} + +- (id) maxKey { + if([self.right isEmpty]) { + return self.key; + } + else { + return [self.right maxKey]; + } +} + +- (id) insertKey:(__unsafe_unretained id) aKey forValue:(__unsafe_unretained id)aValue withComparator:(NSComparator)aComparator { + NSComparisonResult cmp = aComparator(aKey, self.key); + FLLRBValueNode* n = self; + + if(cmp == NSOrderedAscending) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left insertKey:aKey forValue:aValue withComparator:aComparator] withRight:nil]; + } + else if(cmp == NSOrderedSame) { + n = [n copyWith:nil withValue:aValue withColor:nil withLeft:nil withRight:nil]; + } + else { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right insertKey:aKey forValue:aValue withComparator:aComparator]]; + } + + return [n fixUp]; +} + +- (id) removeMin { + + if([self.left isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + + FLLRBValueNode* n = self; + if(! [n.left isRed] && ! [n.left.left isRed]) { + n = [n moveRedLeft]; + } + + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[(FLLRBValueNode*)n.left removeMin] withRight:nil]; + return [n fixUp]; +} + + +- (id) fixUp { + FLLRBValueNode* n = self; + if([n.right isRed] && ! [n.left isRed]) n = [n rotateLeft]; + if([n.left isRed] && [n.left.left isRed]) n = [n rotateRight]; + if([n.left isRed] && [n.right isRed]) n = [n colorFlip]; + return n; +} + +- (FLLRBValueNode*) moveRedLeft { + FLLRBValueNode* n = [self colorFlip]; + if([n.right.left isRed]) { + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right rotateRight]]; + n = [n rotateLeft]; + n = [n colorFlip]; + } + return n; +} + +- (FLLRBValueNode*) moveRedRight { + FLLRBValueNode* n = [self colorFlip]; + if([n.left.left isRed]) { + n = [n rotateRight]; + n = [n colorFlip]; + } + return n; +} + +- (id) rotateLeft { + id nl = [self copyWith:nil withValue:nil withColor:RED withLeft:nil withRight:self.right.left]; + return [self.right copyWith:nil withValue:nil withColor:self.color withLeft:nl withRight:nil];; +} + +- (id) rotateRight { + id nr = [self copyWith:nil withValue:nil withColor:RED withLeft:self.left.right withRight:nil]; + return [self.left copyWith:nil withValue:nil withColor:self.color withLeft:nil withRight:nr]; +} + +- (id) colorFlip { + id nleft = [self.left copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.left.color boolValue]] withLeft:nil withRight:nil]; + id nright = [self.right copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.right.color boolValue]] withLeft:nil withRight:nil]; + + return [self copyWith:nil withValue:nil withColor:[NSNumber numberWithBool:![self.color boolValue]] withLeft:nleft withRight:nright]; +} + +- (id) remove:(__unsafe_unretained id) aKey withComparator:(NSComparator)comparator { + id smallest; + FLLRBValueNode* n = self; + + if(comparator(aKey, n.key) == NSOrderedAscending) { + if(![n.left isEmpty] && ![n.left isRed] && ![n.left.left isRed]) { + n = [n moveRedLeft]; + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:[n.left remove:aKey withComparator:comparator] withRight:nil]; + } + else { + if([n.left isRed]) { + n = [n rotateRight]; + } + + if(![n.right isEmpty] && ![n.right isRed] && ![n.right.left isRed]) { + n = [n moveRedRight]; + } + + if(comparator(aKey, n.key) == NSOrderedSame) { + if([n.right isEmpty]) { + return [FLLRBEmptyNode emptyNode]; + } + else { + smallest = [n.right min]; + n = [n copyWith:smallest.key withValue:smallest.value withColor:nil withLeft:nil withRight:[(FLLRBValueNode*)n.right removeMin]]; + } + } + n = [n copyWith:nil withValue:nil withColor:nil withLeft:nil withRight:[n.right remove:aKey withComparator:comparator]]; + } + return [n fixUp]; +} + +- (BOOL) isRed { + return [self.color boolValue]; +} + +- (BOOL) checkMaxDepth { + int blackDepth = [self check]; + if(pow(2.0, blackDepth) <= ([self count] + 1)) { + return YES; + } + else { + return NO; + } +} + +- (int) check { + int blackDepth = 0; + + if([self isRed] && [self.left isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Red node has a red child" userInfo:nil]; + } + + if([self.right isRed]) { + @throw [[NSException alloc] initWithName:@"check" reason:@"Right child is red" userInfo:nil]; + } + + blackDepth = [self.left check]; +// NSLog(err); + if(blackDepth != [self.right check]) { + NSString* err = [NSString stringWithFormat:@"(%@ -> %@)blackDepth: %d ; self.right check: %d", self.value, [self.color boolValue] ? @"red" : @"black", blackDepth, [self.right check]]; +// return 10; + @throw [[NSException alloc] initWithName:@"check" reason:err userInfo:nil]; + } + else { + int ret = blackDepth + ([self isRed] ? 0 : 1); +// NSLog(@"black depth is: %d; other is: %d, ret is: %d", blackDepth, ([self isRed] ? 0 : 1), ret); + return ret; + } +} + + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h new file mode 100644 index 0000000..934ca8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h @@ -0,0 +1,30 @@ +/** + * @fileoverview Implementation of an immutable SortedMap using a Left-leaning + * Red-Black Tree, adapted from the implementation in Mugs + * (http://mads379.github.com/mugs/) by Mads Hartmann Jensen + * (mads379@gmail.com). + * + * Original paper on Left-leaning Red-Black Trees: + * http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf + * + * Invariant 1: No red node has a red child + * Invariant 2: Every leaf path has the same number of black nodes + * Invariant 3: Only the left child can be red (left leaning) + */ + +#import +#import "FImmutableSortedDictionary.h" +#import "FLLRBNode.h" + +@interface FTreeSortedDictionary : FImmutableSortedDictionary + +@property (nonatomic, copy, readonly) NSComparator comparator; +@property (nonatomic, strong, readonly) id root; + +- (id)initWithComparator:(NSComparator)aComparator; + +// Override methods to return subtype +- (FTreeSortedDictionary *) insertKey:(id)aKey withValue:(id)aValue; +- (FTreeSortedDictionary *) removeKey:(id)aKey; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m new file mode 100644 index 0000000..e9f0683 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m @@ -0,0 +1,326 @@ +#import "FTreeSortedDictionary.h" +#import "FLLRBEmptyNode.h" +#import "FLLRBValueNode.h" +#import "FTreeSortedDictionaryEnumerator.h" + +typedef void (^fbt_void_nsnumber_int)(NSNumber* color, NSUInteger chunkSize); + +@interface FTreeSortedDictionary () + +@property (nonatomic, strong) id root; +@property (nonatomic, copy, readwrite) NSComparator comparator; + +@end + +@implementation FTreeSortedDictionary + +- (id)initWithComparator:(NSComparator)aComparator { + self = [super init]; + if (self) { + self.root = [FLLRBEmptyNode emptyNode]; + self.comparator = aComparator; + } + return self; +} + +- (id)initWithComparator:(NSComparator)aComparator withRoot:(__unsafe_unretained id)aRoot { + self = [super init]; + if (self) { + self.root = aRoot; + self.comparator = aComparator; + } + return self; +} + +/** + * Returns a copy of the map, with the specified key/value added or replaced. + */ +- (FTreeSortedDictionary *) insertKey:(__unsafe_unretained id)aKey withValue:(__unsafe_unretained id)aValue { + return [[FTreeSortedDictionary alloc] initWithComparator:self.comparator + withRoot:[[self.root insertKey:aKey forValue:aValue withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; +} + + +- (FTreeSortedDictionary *) removeKey:(__unsafe_unretained id)aKey { + // Remove is somewhat expensive even if the key doesn't exist (the tree does rebalancing and stuff). So avoid it. + if (![self contains:aKey]) { + return self; + } else { + return [[FTreeSortedDictionary alloc] + initWithComparator:self.comparator + withRoot:[[self.root remove:aKey withComparator:self.comparator] + copyWith:nil + withValue:nil + withColor:BLACK + withLeft:nil + withRight:nil]]; + } +} + +- (id) get:(__unsafe_unretained id) key { + if (key == nil) { + return nil; + } + NSComparisonResult cmp; + id node = self.root; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + return node.value; + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else { + node = node.right; + } + } + return nil; +} + +- (id) getPredecessorKey:(__unsafe_unretained id) key { + NSComparisonResult cmp; + id node = self.root; + id rightParent = nil; + while(![node isEmpty]) { + cmp = self.comparator(key, node.key); + if(cmp == NSOrderedSame) { + if(![node.left isEmpty]) { + node = node.left; + while(! [node.right isEmpty]) { + node = node.right; + } + return node.key; + } + else if (rightParent != nil) { + return rightParent.key; + } + else { + return nil; + } + } + else if (cmp == NSOrderedAscending) { + node = node.left; + } + else if (cmp == NSOrderedDescending) { + rightParent = node; + node = node.right; + } + } + @throw [NSException exceptionWithName:@"NonexistentKey" reason:@"getPredecessorKey called with nonexistent key." userInfo:@{@"key": [key description] }]; +} + +- (BOOL) isEmpty { + return [self.root isEmpty]; +} + +- (int) count { + return [self.root count]; +} + +- (id) minKey { + return [self.root minKey]; +} + +- (id) maxKey { + return [self.root maxKey]; +} + +- (void) enumerateKeysAndObjectsUsingBlock:(void (^)(id, id, BOOL *))block +{ + [self enumerateKeysAndObjectsReverse:NO usingBlock:block]; +} + +- (void) enumerateKeysAndObjectsReverse:(BOOL)reverse usingBlock:(void (^)(id, id, BOOL *))block +{ + if (reverse) { + __block BOOL stop = NO; + [self.root reverseTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } else { + __block BOOL stop = NO; + [self.root inorderTraversal:^BOOL(id key, id value) { + block(key, value, &stop); + return stop; + }]; + } +} + +- (BOOL) contains:(__unsafe_unretained id)key { + return ([self objectForKey:key] != nil); +} + +- (NSEnumerator *) keyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:NO]; +} + +- (NSEnumerator *) keyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:NO]; +} + +- (NSEnumerator *) reverseKeyEnumerator { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:nil isReverse:YES]; +} + +- (NSEnumerator *) reverseKeyEnumeratorFrom:(id)startKey { + return [[FTreeSortedDictionaryEnumerator alloc] + initWithImmutableSortedDictionary:self startKey:startKey isReverse:YES]; +} + + +#pragma mark - +#pragma mark Tree Builder + +// Code to efficiently build a RB Tree +typedef struct _base1_2list { + unsigned int bits; + unsigned short count; + unsigned short current; +} Base1_2List; + +Base1_2List *base1_2List_new(unsigned int length); +void base1_2List_free(Base1_2List* list); +unsigned int log_base2(unsigned int num); +BOOL base1_2List_next(Base1_2List* list); + +unsigned int log_base2(unsigned int num) { + return (unsigned int)(log(num) / log(2)); +} + +/** + * Works like an iterator, so it moves to the next bit. Do not call more than list->count times. + * @return whether or not the next bit is a 1 in base {1,2}. + */ +BOOL base1_2List_next(Base1_2List* list) { + BOOL result = !(list->bits & (0x1 << list->current)); + list->current--; + return result; +} + +static inline unsigned bit_mask(int x) { + return (x >= sizeof(unsigned) * CHAR_BIT) ? (unsigned) -1 : (1U << x) - 1; +} + +/** + * We represent the base{1,2} number as the combination of a binary number and a number of bits that we care about + * We iterate backwards, from most significant bit to least, to build up the llrb nodes. 0 base 2 => 1 base {1,2}, 1 base 2 => 2 base {1,2} + */ +Base1_2List *base1_2List_new(unsigned int length) { + size_t sz = sizeof(Base1_2List); + Base1_2List* list = calloc(1, sz); + // Calculate the number of bits that we care about + list->count = (unsigned short)log_base2(length + 1); + unsigned int mask = bit_mask(list->count); + list->bits = (length + 1) & mask; + list->current = list->count - 1; + return list; +} + + +void base1_2List_free(Base1_2List* list) { + free(list); +} + ++ (id) buildBalancedTree:(NSArray *)keys dictionary:(NSDictionary *)dictionary subArrayStartIndex:(NSUInteger)startIndex length:(NSUInteger)length { + length = MIN(keys.count - startIndex, length); // Bound length by the actual length of the array + if (length == 0) { + return nil; + } else if (length == 1) { + id key = keys[startIndex]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:nil withRight:nil]; + } else { + NSUInteger middle = length / 2; + id left = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:startIndex length:middle]; + id right = [FTreeSortedDictionary buildBalancedTree:keys dictionary:dictionary subArrayStartIndex:(startIndex+middle+1) length:middle]; + id key = keys[startIndex + middle]; + return [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:BLACK withLeft:left withRight:right]; + } +} + ++ (id) rootFrom12List:(Base1_2List *)base1_2List keyList:(NSArray *)keyList dictionary:(NSDictionary *)dictionary { + __block id root = nil; + __block id node = nil; + __block NSUInteger index = keyList.count; + + fbt_void_nsnumber_int buildPennant = ^(NSNumber* color, NSUInteger chunkSize) { + NSUInteger startIndex = index - chunkSize + 1; + index -= chunkSize; + id key = keyList[index]; + id childTree = [self buildBalancedTree:keyList dictionary:dictionary subArrayStartIndex:startIndex length:(chunkSize - 1)]; + id pennant = [[FLLRBValueNode alloc] initWithKey:key withValue:dictionary[key] withColor:color withLeft:nil withRight:childTree]; + //attachPennant(pennant); + if (node) { + node.left = pennant; + node = pennant; + } else { + root = pennant; + node = pennant; + } + }; + + for (int i = 0; i < base1_2List->count; ++i) { + BOOL isOne = base1_2List_next(base1_2List); + NSUInteger chunkSize = (NSUInteger)pow(2.0, base1_2List->count - (i + 1)); + if (isOne) { + buildPennant(BLACK, chunkSize); + } else { + buildPennant(BLACK, chunkSize); + buildPennant(RED, chunkSize); + } + } + return root; +} + +/** + * Uses the algorithm linked here: + * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.46.1458 + */ + ++ (FImmutableSortedDictionary *)fromDictionary:(NSDictionary *)dictionary withComparator:(NSComparator)comparator +{ + // Steps: + // 0. Sort the array + // 1. Calculate the 1-2 number + // 2. Build From 1-2 number + // 0. for each digit in 1-2 number + // 0. calculate chunk size + // 1. build 1 or 2 pennants of that size + // 2. attach pennants and update node pointer + // 1. return root + NSMutableArray *sortedKeyList = [NSMutableArray arrayWithCapacity:dictionary.count]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [sortedKeyList addObject:key]; + }]; + [sortedKeyList sortUsingComparator:comparator]; + + [sortedKeyList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + if (idx > 0) { + if (comparator(sortedKeyList[idx - 1], obj) != NSOrderedAscending) { + [NSException raise:NSInvalidArgumentException format:@"Can't create FImmutableSortedDictionary with keys with same ordering!"]; + } + } + }]; + + Base1_2List* list = base1_2List_new((unsigned int)sortedKeyList.count); + id root = [self rootFrom12List:list keyList:sortedKeyList dictionary:dictionary]; + base1_2List_free(list); + + if (root != nil) { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator withRoot:root]; + } else { + return [[FTreeSortedDictionary alloc] initWithComparator:comparator]; + } +} + +@end + diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h new file mode 100644 index 0000000..d79fe8e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h @@ -0,0 +1,9 @@ +#import +#import "FTreeSortedDictionary.h" + +@interface FTreeSortedDictionaryEnumerator : NSEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict startKey:(id)startKey isReverse:(BOOL)reverse; +- (id)nextObject; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m new file mode 100644 index 0000000..2aca86e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m @@ -0,0 +1,83 @@ +#import "FTreeSortedDictionaryEnumerator.h" + +@interface FTreeSortedDictionaryEnumerator() +@property (nonatomic, strong) FTreeSortedDictionary* immutableSortedDictionary; +@property (nonatomic, strong) NSMutableArray* stack; +@property (nonatomic) BOOL isReverse; + +@end + +@implementation FTreeSortedDictionaryEnumerator + +- (id)initWithImmutableSortedDictionary:(FTreeSortedDictionary *)aDict + startKey:(id)startKey isReverse:(BOOL)reverse { + self = [super init]; + if (self) { + self.immutableSortedDictionary = aDict; + self.stack = [[NSMutableArray alloc] init]; + self.isReverse = reverse; + + NSComparator comparator = aDict.comparator; + id node = self.immutableSortedDictionary.root; + + NSInteger cmp; + while(![node isEmpty]) { + cmp = startKey ? comparator(node.key, startKey) : 1; + // flip the comparison if we're going in reverse + if (self.isReverse) cmp *= -1; + + if (cmp < 0) { + // This node is less than our start key. Ignore it. + if (self.isReverse) { + node = node.left; + } else { + node = node.right; + } + } else if (cmp == 0) { + // This node is exactly equal to our start key. Push it on the stack, but stop iterating: + [self.stack addObject:node]; + break; + } else { + // This node is greater than our start key, add it to the stack and move on to the next one. + [self.stack addObject:node]; + if (self.isReverse) { + node = node.right; + } else { + node = node.left; + } + } + } + } + return self; +} + +- (id)nextObject { + if([self.stack count] == 0) { + return nil; + } + + id node = nil; + @synchronized(self.stack) { + node = [self.stack lastObject]; + [self.stack removeLastObject]; + } + id result = node.key; + + if (self.isReverse) { + node = node.left; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.right; + } + } else { + node = node.right; + while (![node isEmpty]) { + [self.stack addObject:node]; + node = node.left; + } + } + + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h new file mode 100644 index 0000000..1ca1815 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.h @@ -0,0 +1,107 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import +#import + +typedef enum { + SR_CONNECTING = 0, + SR_OPEN = 1, + SR_CLOSING = 2, + SR_CLOSED = 3, + +} FSRReadyState; + +@class FSRWebSocket; + +extern NSString *const FSRWebSocketErrorDomain; + +@protocol FSRWebSocketDelegate; + +@interface FSRWebSocket : NSObject + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, readonly) FSRReadyState readyState; +@property (nonatomic, readonly, retain) NSURL *url; + +// This returns the negotiated protocol. +// It will be niluntil after the handshake completes. +@property (nonatomic, readonly, copy) NSString *protocol; + +// Protocols should be an array of strings that turn into Sec-WebSocket-Protocol +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +- (id)initWithURLRequest:(NSURLRequest *)request; + +// Some helper constructors +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +- (id)initWithURL:(NSURL *)url; + +// Delegate queue will be dispatch_main_queue by default. +// You cannot set both OperationQueue and dispatch_queue. +- (void)setDelegateOperationQueue:(NSOperationQueue*) queue; +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; + +// By default, it will schedule itself on +[NSRunLoop SR_networkRunLoop] using defaultModes. +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; + +// SRWebSockets are intended one-time-use only. Open should be called once and only once +- (void)open; + +- (void)close; +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; + +// Send a UTF8 String or Data +- (void)send:(id)data; + +@end + +@protocol FSRWebSocketDelegate + +// message will either be an NSString if the server is using text +// or NSData if the server is using binary +- (void)webSocket:(FSRWebSocket *)webSocket didReceiveMessage:(id)message; + +@optional + +- (void)webSocketDidOpen:(FSRWebSocket *)webSocket; +- (void)webSocket:(FSRWebSocket *)webSocket didFailWithError:(NSError *)error; +- (void)webSocket:(FSRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; + +@end + + +@interface NSURLRequest (FCertificateAdditions) + +@property (nonatomic, retain, readonly) NSArray *FSR_SSLPinnedCertificates; + +@end + + +@interface NSMutableURLRequest (FCertificateAdditions) + +@property (nonatomic, retain) NSArray *FSR_SSLPinnedCertificates; + +@end + +@interface NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m new file mode 100644 index 0000000..92d9d55 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/FSRWebSocket.m @@ -0,0 +1,1858 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "FSRWebSocket.h" + +#if __has_include() +#define HAS_ICU +#endif + +#import + +#ifdef HAS_ICU +#import +#endif + +#if __has_include() +#import +#else +#import +#endif + +#import +#import +#import "fbase64.h" +#import "NSData+SRB64Additions.h" + +#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE +#define sr_dispatch_retain(x) +#define sr_dispatch_release(x) +#define maybe_bridge(x) ((__bridge void *) x) +#else +#define sr_dispatch_retain(x) dispatch_retain(x) +#define sr_dispatch_release(x) dispatch_release(x) +#define maybe_bridge(x) (x) +#endif + +typedef enum { + SROpCodeTextFrame = 0x1, + SROpCodeBinaryFrame = 0x2, + //3-7Reserved + SROpCodeConnectionClose = 0x8, + SROpCodePing = 0x9, + SROpCodePong = 0xA, + //B-F reserved +} FSROpCode; + +typedef enum { + SRStatusCodeNormal = 1000, + SRStatusCodeGoingAway = 1001, + SRStatusCodeProtocolError = 1002, + SRStatusCodeUnhandledType = 1003, + // 1004 reserved + SRStatusNoStatusReceived = 1005, + // 1004-1006 reserved + SRStatusCodeInvalidUTF8 = 1007, + SRStatusCodePolicyViolated = 1008, + SRStatusCodeMessageTooBig = 1009, +} FSRStatusCode; + +typedef struct { + BOOL fin; +// BOOL rsv1; +// BOOL rsv2; +// BOOL rsv3; + uint8_t opcode; + BOOL masked; + uint64_t payload_length; +} frame_header; + +static NSString *const SRWebSocketAppendToSecKeyString = @"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + +static inline int32_t validate_dispatch_data_partial_string(NSData *data); +static inline void SRFastLog(NSString *format, ...); + +@interface NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; + +@end + + +@interface NSURL (FSRWebSocket) + +// The origin isn't really applicable for a native application +// So instead, just map ws -> http and wss -> https +- (NSString *)SR_origin; + +@end + +@interface _FSRRunLoopThread : NSThread + +@property (nonatomic, readonly) NSRunLoop *runLoop; + +@end + +static NSString *newSHA1String(const char *bytes, size_t length) { + uint8_t md[CC_SHA1_DIGEST_LENGTH]; + + CC_SHA1(bytes, (int)length, md); + + size_t buffer_size = ((sizeof(md) * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(md, CC_SHA1_DIGEST_LENGTH, buffer, buffer_size); + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSASCIIStringEncoding freeWhenDone:YES]; + } +} + +@implementation NSData (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.bytes, self.length); +} + +@end + + +@implementation NSString (FSRWebSocket) + +- (NSString *)stringBySHA1ThenBase64Encoding; +{ + return newSHA1String(self.UTF8String, self.length); +} + +@end + +NSString *const FSRWebSocketErrorDomain = @"FSRWebSocketErrorDomain"; + +// Returns number of bytes consumed. returning 0 means you didn't match. +// Sends bytes to callback handler; +typedef size_t (^stream_scanner)(NSData *collected_data); + +typedef void (^data_callback)(FSRWebSocket *webSocket, NSData *data); + +@interface FSRIOConsumer : NSObject { + stream_scanner _scanner; + data_callback _handler; + size_t _bytesNeeded; + BOOL _readToCurrentFrame; + BOOL _unmaskBytes; +} +@property (nonatomic, copy, readonly) stream_scanner consumer; +@property (nonatomic, copy, readonly) data_callback handler; +@property (nonatomic, assign) size_t bytesNeeded; +@property (nonatomic, assign, readonly) BOOL readToCurrentFrame; +@property (nonatomic, assign, readonly) BOOL unmaskBytes; + +@end + +// This class is not thread-safe, and is expected to always be run on the same queue. +@interface FSRIOConsumerPool : NSObject + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)returnConsumer:(FSRIOConsumer *)consumer; + +@end + +@interface FSRWebSocket () + +- (void)_writeData:(NSData *)data; +- (void)_closeWithProtocolError:(NSString *)message; +- (void)_failWithError:(NSError *)error; + +- (void)_disconnect; + +- (void)_readFrameNew; +- (void)_readFrameContinue; + +- (void)_pumpScanner; + +- (void)_pumpWriting; + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +- (void)_SR_commonInit; + +- (void)_initializeStreams; +- (void)_connect; + +@property (nonatomic) FSRReadyState readyState; + +@property (nonatomic) NSOperationQueue *delegateOperationQueue; +@property (nonatomic) dispatch_queue_t delegateDispatchQueue; + +@end + + +@implementation FSRWebSocket { + NSInteger _webSocketVersion; + + NSOperationQueue *_delegateOperationQueue; + dispatch_queue_t _delegateDispatchQueue; + dispatch_queue_t _workQueue; + NSMutableArray *_consumers; + + NSInputStream *_inputStream; + NSOutputStream *_outputStream; + + NSMutableData *_readBuffer; + NSInteger _readBufferOffset; + + NSMutableData *_outputBuffer; + NSInteger _outputBufferOffset; + + uint8_t _currentFrameOpcode; + size_t _currentFrameCount; + size_t _readOpCount; + uint32_t _currentStringScanPosition; + NSMutableData *_currentFrameData; + + NSString *_closeReason; + + NSString *_secKey; + + BOOL _pinnedCertFound; + + uint8_t _currentReadMaskKey[4]; + size_t _currentReadMaskOffset; + + BOOL _consumerStopped; + + BOOL _closeWhenFinishedWriting; + BOOL _failed; + + BOOL _secure; + NSURLRequest *_urlRequest; + NSString *_userAgent; + + CFHTTPMessageRef _receivedHTTPHeaders; + + BOOL _sentClose; + BOOL _didFail; + BOOL _cleanupScheduled; + int _closeCode; + + BOOL _isPumping; + + NSMutableSet *_scheduledRunloops; + + // We use this to retain ourselves. + __strong FSRWebSocket *_selfRetain; + + NSArray *_requestedProtocols; + FSRIOConsumerPool *_consumerPool; +} + +@synthesize delegate = _delegate; +@synthesize url = _url; +@synthesize readyState = _readyState; +@synthesize protocol = _protocol; + +static __strong NSData *CRLFCRLF; + ++ (void)initialize; +{ + CRLFCRLF = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +{ + self = [super init]; + if (self) { + assert(request.URL); + _url = request.URL; + NSString *scheme = [_url scheme]; + + _requestedProtocols = [protocols copy]; + _userAgent = userAgent; + + assert([scheme isEqualToString:@"ws"] || [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]); + _urlRequest = request; + + if ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]) { + _secure = YES; + } + + if (!queue) { + _delegateDispatchQueue = dispatch_get_main_queue(); + } else { + _delegateDispatchQueue = queue; + } + + [self _SR_commonInit]; + } + + return self; +} + +- (id)initWithURLRequest:(NSURLRequest *)request protocols:(NSArray *)protocols; +{ + return [self initWithURLRequest:request protocols:nil queue:nil andUserAgent:nil]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request queue:(dispatch_queue_t)queue andUserAgent:(NSString *)userAgent; +{ + return [self initWithURLRequest:request protocols:nil queue:queue andUserAgent:userAgent]; +} + +- (id)initWithURLRequest:(NSURLRequest *)request; +{ + return [self initWithURLRequest:request protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url; +{ + return [self initWithURL:url protocols:nil]; +} + +- (id)initWithURL:(NSURL *)url protocols:(NSArray *)protocols; +{ + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; + return [self initWithURLRequest:request protocols:protocols]; +} + +- (void)_SR_commonInit; +{ + _readyState = SR_CONNECTING; + + _consumerStopped = YES; + + _webSocketVersion = 13; + + _workQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); + + // Going to set a specific on the queue so we can validate we're on the work queue + dispatch_queue_set_specific(_workQueue, (__bridge void *)self, maybe_bridge(_workQueue), NULL); + + sr_dispatch_retain(_delegateDispatchQueue); + + _readBuffer = [[NSMutableData alloc] init]; + _outputBuffer = [[NSMutableData alloc] init]; + + _currentFrameData = [[NSMutableData alloc] init]; + + _consumers = [[NSMutableArray alloc] init]; + + _consumerPool = [[FSRIOConsumerPool alloc] init]; + + _scheduledRunloops = [[NSMutableSet alloc] init]; + + [self _initializeStreams]; + + // default handlers +} + +- (void)assertOnWorkQueue; +{ + assert(dispatch_get_specific((__bridge void *)self) == maybe_bridge(_workQueue)); +} + +- (void)dealloc +{ + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + [_inputStream close]; + [_outputStream close]; + + sr_dispatch_release(_workQueue); + _workQueue = NULL; + + if (_receivedHTTPHeaders) { + CFRelease(_receivedHTTPHeaders); + _receivedHTTPHeaders = NULL; + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + _delegateDispatchQueue = NULL; + } +} + +#ifndef NDEBUG + +- (void)setReadyState:(FSRReadyState)aReadyState; +{ + [self willChangeValueForKey:@"readyState"]; + assert(aReadyState > _readyState); + _readyState = aReadyState; + [self didChangeValueForKey:@"readyState"]; +} + +#endif + +- (void)open; +{ + assert(_url); + NSAssert(_readyState == SR_CONNECTING, @"Cannot call -(void)open on SRWebSocket more than once"); + + _selfRetain = self; + + [self _connect]; +} + +// Calls block on delegate queue +- (void)_performDelegateBlock:(dispatch_block_t)block; +{ + if (_delegateOperationQueue) { + [_delegateOperationQueue addOperationWithBlock:block]; + } else { + assert(_delegateDispatchQueue); + dispatch_async(_delegateDispatchQueue, block); + } +} + +- (void)setDelegateDispatchQueue:(dispatch_queue_t)queue; +{ + if (queue) { + sr_dispatch_retain(queue); + } + + if (_delegateDispatchQueue) { + sr_dispatch_release(_delegateDispatchQueue); + } + + _delegateDispatchQueue = queue; +} + +- (BOOL)_checkHandshake:(CFHTTPMessageRef)httpMessage; +{ + NSString *acceptHeader = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(httpMessage, CFSTR("Sec-WebSocket-Accept"))); + + if (acceptHeader == nil) { + return NO; + } + + NSString *concattedString = [_secKey stringByAppendingString:SRWebSocketAppendToSecKeyString]; + NSString *expectedAccept = [concattedString stringBySHA1ThenBase64Encoding]; + + return [acceptHeader isEqualToString:expectedAccept]; +} + +- (void)_HTTPHeadersDidFinish; +{ + NSInteger responseCode = CFHTTPMessageGetResponseStatusCode(_receivedHTTPHeaders); + + if (responseCode >= 400) { + SRFastLog(@"Request failed with response code %d", responseCode); + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2132 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"received bad response code from server %u", (int)responseCode] forKey:NSLocalizedDescriptionKey]]]; + return; + + } + + if(![self _checkHandshake:_receivedHTTPHeaders]) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Invalid Sec-WebSocket-Accept response"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + NSString *negotiatedProtocol = CFBridgingRelease(CFHTTPMessageCopyHeaderFieldValue(_receivedHTTPHeaders, CFSTR("Sec-WebSocket-Protocol"))); + if (negotiatedProtocol) { + // Make sure we requested the protocol + if ([_requestedProtocols indexOfObject:negotiatedProtocol] == NSNotFound) { + [self _failWithError:[NSError errorWithDomain:FSRWebSocketErrorDomain code:2133 userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"Server specified Sec-WebSocket-Protocol that wasn't requested"] forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _protocol = negotiatedProtocol; + } + + self.readyState = SR_OPEN; + + if (!_didFail) { + [self _readFrameNew]; + } + + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocketDidOpen:)]) { + [self.delegate webSocketDidOpen:self]; + }; + }]; +} + + +- (void)_readHTTPHeader; +{ + if (_receivedHTTPHeaders == NULL) { + _receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO); + } + + [self _readUntilHeaderCompleteWithCallback:^(FSRWebSocket *self, NSData *data) { + CFHTTPMessageAppendBytes(self->_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length); + + if (CFHTTPMessageIsHeaderComplete(self->_receivedHTTPHeaders)) { + SRFastLog(@"Finished reading headers %@", CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(self->_receivedHTTPHeaders))); + [self _HTTPHeadersDidFinish]; + } else { + [self _readHTTPHeader]; + } + }]; +} + +- (void)didConnect +{ + SRFastLog(@"Connected"); + CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1); + + // Set host first so it defaults + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef) + (_url.port != nil ? [NSString stringWithFormat:@"%@:%@", + _url.host, _url.port] : _url.host)); + + NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16]; + int result = SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes); + assert(result == 0); + _secKey = [FSRUtilities base64EncodedStringFromData:keyBytes]; + assert([_secKey length] == 24); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Upgrade"), CFSTR("websocket")); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Connection"), CFSTR("Upgrade")); + if (_userAgent) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("User-Agent"), (__bridge CFStringRef)_userAgent); + } + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)_secKey); + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)[NSString stringWithFormat:@"%u", (int)_webSocketVersion]); + + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Origin"), (__bridge CFStringRef)_url.SR_origin); + + if (_requestedProtocols) { + CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Sec-WebSocket-Protocol"), (__bridge CFStringRef)[_requestedProtocols componentsJoinedByString:@", "]); + } + + [_urlRequest.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + CFHTTPMessageSetHeaderFieldValue(request, (__bridge CFStringRef)key, (__bridge CFStringRef)obj); + }]; + + NSData *message = CFBridgingRelease(CFHTTPMessageCopySerializedMessage(request)); + + CFRelease(request); + + [self _writeData:message]; + [self _readHTTPHeader]; +} + +//- (void)_connectToHost:(NSString *)host port:(NSInteger)port; +- (void)_initializeStreams; +{ + NSInteger port = _url.port.integerValue; + if (port == 0) { + if (!_secure) { + port = 80; + } else { + port = 443; + } + } + NSString *host = _url.host; + + CFReadStreamRef readStream = NULL; + CFWriteStreamRef writeStream = NULL; + + CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, (int)port, &readStream, &writeStream); + + // XXX + CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); + + _outputStream = CFBridgingRelease(writeStream); + _inputStream = CFBridgingRelease(readStream); + + + if (_secure) { + NSMutableDictionary *SSLOptions = [[NSMutableDictionary alloc] init]; + + [_outputStream setProperty:(__bridge id)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel]; + + // If we're using pinned certs, don't validate the certificate chain + if ([_urlRequest FSR_SSLPinnedCertificates].count) { + [SSLOptions setValue:[NSNumber numberWithBool:NO] forKey:(__bridge id)kCFStreamSSLValidatesCertificateChain]; + } + + [_outputStream setProperty:SSLOptions + forKey:(__bridge id)kCFStreamPropertySSLSettings]; + } + + _inputStream.delegate = self; + _outputStream.delegate = self; + + [_outputStream open]; + [_inputStream open]; +} + +- (void)_connect; +{ + if (!_scheduledRunloops.count) { + [self scheduleInRunLoop:[NSRunLoop FSR_networkRunLoop] forMode:NSDefaultRunLoopMode]; + } + + + [_outputStream open]; + [_inputStream open]; +} + +- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream scheduleInRunLoop:aRunLoop forMode:mode]; + [_inputStream scheduleInRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops addObject:@[aRunLoop, mode]]; +} + +- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode; +{ + [_outputStream removeFromRunLoop:aRunLoop forMode:mode]; + [_inputStream removeFromRunLoop:aRunLoop forMode:mode]; + + [_scheduledRunloops removeObject:@[aRunLoop, mode]]; +} + +- (void)close; +{ + [self closeWithCode:-1 reason:nil]; +} + +- (void)closeWithCode:(NSInteger)code reason:(NSString *)reason; +{ + assert(code); + dispatch_async(_workQueue, ^{ + if (self.readyState == SR_CLOSING || self.readyState == SR_CLOSED) { + return; + } + + BOOL wasConnecting = self.readyState == SR_CONNECTING; + + self.readyState = SR_CLOSING; + + SRFastLog(@"Closing with code %d reason %@", code, reason); + + if (wasConnecting) { + [self _disconnect]; + return; + } + + size_t maxMsgSize = [reason maximumLengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSMutableData *mutablePayload = [[NSMutableData alloc] initWithLength:sizeof(uint16_t) + maxMsgSize]; + NSData *payload = mutablePayload; + + ((uint16_t *)mutablePayload.mutableBytes)[0] = EndianU16_BtoN(code); + + if (reason) { + NSRange remainingRange = {0}; + + NSUInteger usedLength = 0; + + BOOL success = [reason getBytes:(char *)mutablePayload.mutableBytes + sizeof(uint16_t) maxLength:payload.length - sizeof(uint16_t) usedLength:&usedLength encoding:NSUTF8StringEncoding options:NSStringEncodingConversionExternalRepresentation range:NSMakeRange(0, reason.length) remainingRange:&remainingRange]; + + assert(success); + assert(remainingRange.length == 0); + + if (usedLength != maxMsgSize) { + payload = [payload subdataWithRange:NSMakeRange(0, usedLength + sizeof(uint16_t))]; + } + } + + + [self _sendFrameWithOpcode:SROpCodeConnectionClose data:payload]; + }); +} + +- (void)_closeWithProtocolError:(NSString *)message; +{ + // Need to shunt this on the _callbackQueue first to see if they received any messages + [self _performDelegateBlock:^{ + [self closeWithCode:SRStatusCodeProtocolError reason:message]; + dispatch_async(self->_workQueue, ^{ + [self _disconnect]; + }); + }]; +} + +- (void)_failWithError:(NSError *)error; +{ + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self->_failed = YES; + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) { + [self.delegate webSocket:self didFailWithError:error]; + } + }]; + + self.readyState = SR_CLOSED; + + SRFastLog(@"Failing with error %@", error.localizedDescription); + + [self _disconnect]; + [self _scheduleCleanup]; + } + }); +} + +- (void)_writeData:(NSData *)data; +{ + [self assertOnWorkQueue]; + + if (_closeWhenFinishedWriting) { + return; + } + [_outputBuffer appendData:data]; + [self _pumpWriting]; +} +- (void)send:(id)data; +{ + SRFastLog(@"Sending data %@", data); + NSAssert(self.readyState != SR_CONNECTING, @"Invalid State: Cannot call send: until connection is open"); + // TODO: maybe not copy this for performance + data = [data copy]; + dispatch_async(_workQueue, ^{ + if ([data isKindOfClass:[NSString class]]) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:[(NSString *)data dataUsingEncoding:NSUTF8StringEncoding]]; + } else if ([data isKindOfClass:[NSData class]]) { + [self _sendFrameWithOpcode:SROpCodeBinaryFrame data:data]; + } else if (data == nil) { + [self _sendFrameWithOpcode:SROpCodeTextFrame data:data]; + } else { + assert(NO); + } + }); +} + +- (void)handlePing:(NSData *)pingData; +{ + // Need to pingpong this off _callbackQueue first to make sure messages happen in order + [self _performDelegateBlock:^{ + dispatch_async(self->_workQueue, ^{ + [self _sendFrameWithOpcode:SROpCodePong data:pingData]; + }); + }]; +} + +- (void)handlePong; +{ + // NOOP +} + +- (void)_handleMessage:(id)message +{ + SRFastLog(@"Received message"); + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)]) { + [self.delegate webSocket:self didReceiveMessage:message]; + } + }]; +} + + +static inline BOOL closeCodeIsValid(int closeCode) { + if (closeCode < 1000) { + return NO; + } + + if (closeCode >= 1000 && closeCode <= 1011) { + if (closeCode == 1004 || + closeCode == 1005 || + closeCode == 1006) { + return NO; + } + return YES; + } + + if (closeCode >= 3000 && closeCode <= 3999) { + return YES; + } + + if (closeCode >= 4000 && closeCode <= 4999) { + return YES; + } + + return NO; +} + +// Note from RFC: +// +// If there is a body, the first two +// bytes of the body MUST be a 2-byte unsigned integer (in network byte +// order) representing a status code with value /code/ defined in +// Section 7.4. Following the 2-byte integer the body MAY contain UTF-8 +// encoded data with value /reason/, the interpretation of which is not +// defined by this specification. + +- (void)handleCloseWithData:(NSData *)data; +{ + size_t dataSize = data.length; + __block uint16_t closeCode = 0; + + SRFastLog(@"Received close frame"); + + if (dataSize == 1) { + // TODO handle error + [self _closeWithProtocolError:@"Payload for close must be larger than 2 bytes"]; + return; + } else if (dataSize >= 2) { + [data getBytes:&closeCode length:sizeof(closeCode)]; + _closeCode = EndianU16_BtoN(closeCode); + if (!closeCodeIsValid(_closeCode)) { + [self _closeWithProtocolError:[NSString stringWithFormat:@"Cannot have close code of %d", _closeCode]]; + return; + } + if (dataSize > 2) { + _closeReason = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(2, dataSize - 2)] encoding:NSUTF8StringEncoding]; + if (!_closeReason) { + [self _closeWithProtocolError:@"Close reason MUST be valid UTF-8"]; + return; + } + } + } else { + _closeCode = SRStatusNoStatusReceived; + } + + [self assertOnWorkQueue]; + + if (self.readyState == SR_OPEN) { + [self closeWithCode:1000 reason:nil]; + } + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); +} + +- (void)_disconnect; +{ + [self assertOnWorkQueue]; + SRFastLog(@"Trying to disconnect"); + _closeWhenFinishedWriting = YES; + [self _pumpWriting]; +} + +- (void)_handleFrameWithData:(NSData *)frameData opCode:(NSInteger)opcode; +{ + // Check that the current data is valid UTF8 + + BOOL isControlFrame = (opcode == SROpCodePing || opcode == SROpCodePong || opcode == SROpCodeConnectionClose); + if (!isControlFrame) { + [self _readFrameNew]; + } else { + dispatch_async(_workQueue, ^{ + [self _readFrameContinue]; + }); + } + + switch (opcode) { + case SROpCodeTextFrame: { + NSString *str = [[NSString alloc] initWithData:frameData encoding:NSUTF8StringEncoding]; + if (str == nil && frameData) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + + return; + } + [self _handleMessage:str]; + break; + } + case SROpCodeBinaryFrame: + [self _handleMessage:[frameData copy]]; + break; + case SROpCodeConnectionClose: + [self handleCloseWithData:frameData]; + break; + case SROpCodePing: + [self handlePing:frameData]; + break; + case SROpCodePong: + [self handlePong]; + break; + default: + [self _closeWithProtocolError:[NSString stringWithFormat:@"Unknown opcode %u", (int)opcode]]; + // TODO: Handle invalid opcode + break; + } +} + +- (void)_handleFrameHeader:(frame_header)frame_header curData:(NSData *)curData; +{ + assert(frame_header.opcode != 0); + + if (self.readyState != SR_OPEN) { + return; + } + + + BOOL isControlFrame = (frame_header.opcode == SROpCodePing || frame_header.opcode == SROpCodePong || frame_header.opcode == SROpCodeConnectionClose); + + if (isControlFrame && !frame_header.fin) { + [self _closeWithProtocolError:@"Fragmented control frames not allowed"]; + return; + } + + if (isControlFrame && frame_header.payload_length >= 126) { + [self _closeWithProtocolError:@"Control frames cannot have payloads larger than 126 bytes"]; + return; + } + + if (!isControlFrame) { + _currentFrameOpcode = frame_header.opcode; + _currentFrameCount += 1; + } + + if (frame_header.payload_length == 0) { + if (isControlFrame) { + [self _handleFrameWithData:curData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + } + } else { + [self _addConsumerWithDataLength:(size_t)frame_header.payload_length callback:^(FSRWebSocket *self, NSData *newData) { + if (isControlFrame) { + [self _handleFrameWithData:newData opCode:frame_header.opcode]; + } else { + if (frame_header.fin) { + [self _handleFrameWithData:self->_currentFrameData opCode:frame_header.opcode]; + } else { + // TODO add assert that opcode is not a control; + [self _readFrameContinue]; + } + + } + } readToCurrentFrame:!isControlFrame unmaskBytes:frame_header.masked]; + } +} + +/* From RFC: + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16/64) | + |N|V|V|V| |S| | (if payload len==126/127) | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Extended payload length continued, if payload len == 127 | + + - - - - - - - - - - - - - - - +-------------------------------+ + | |Masking-key, if MASK set to 1 | + +-------------------------------+-------------------------------+ + | Masking-key (continued) | Payload Data | + +-------------------------------- - - - - - - - - - - - - - - - + + : Payload Data continued ... : + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + | Payload Data continued ... | + +---------------------------------------------------------------+ + */ + +static const uint8_t SRFinMask = 0x80; +static const uint8_t SROpCodeMask = 0x0F; +static const uint8_t SRRsvMask = 0x70; +static const uint8_t SRMaskMask = 0x80; +static const uint8_t SRPayloadLenMask = 0x7F; + + +- (void)_readFrameContinue; +{ + assert((_currentFrameCount == 0 && _currentFrameOpcode == 0) || (_currentFrameCount > 0 && _currentFrameOpcode > 0)); + + [self _addConsumerWithDataLength:2 callback:^(FSRWebSocket *self, NSData *data) { + __block frame_header header = {0}; + + const uint8_t *headerBuffer = data.bytes; + assert(data.length >= 2); + + if (headerBuffer[0] & SRRsvMask) { + [self _closeWithProtocolError:@"Server used RSV bits"]; + return; + } + + uint8_t receivedOpcode = (SROpCodeMask & headerBuffer[0]); + + BOOL isControlFrame = (receivedOpcode == SROpCodePing || receivedOpcode == SROpCodePong || receivedOpcode == SROpCodeConnectionClose); + + if (!isControlFrame && receivedOpcode != 0 && self->_currentFrameCount > 0) { + [self _closeWithProtocolError:@"all data frames after the initial data frame must have opcode 0"]; + return; + } + + if (receivedOpcode == 0 && self->_currentFrameCount == 0) { + [self _closeWithProtocolError:@"cannot continue a message"]; + return; + } + + header.opcode = receivedOpcode == 0 ? self->_currentFrameOpcode : receivedOpcode; + + header.fin = !!(SRFinMask & headerBuffer[0]); + + + header.masked = !!(SRMaskMask & headerBuffer[1]); + header.payload_length = SRPayloadLenMask & headerBuffer[1]; + + headerBuffer = NULL; + + if (header.masked) { + [self _closeWithProtocolError:@"Client must receive unmasked data"]; + } + + size_t extra_bytes_needed = header.masked ? sizeof(self->_currentReadMaskKey) : 0; + + if (header.payload_length == 126) { + extra_bytes_needed += sizeof(uint16_t); + } else if (header.payload_length == 127) { + extra_bytes_needed += sizeof(uint64_t); + } + + if (extra_bytes_needed == 0) { + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } else { + [self _addConsumerWithDataLength:extra_bytes_needed callback:^(FSRWebSocket *self, NSData *data) { + size_t mapped_size = data.length; + const void *mapped_buffer = data.bytes; + size_t offset = 0; + + if (header.payload_length == 126) { + assert(mapped_size >= sizeof(uint16_t)); + uint16_t newLen = EndianU16_BtoN(*(uint16_t *)(mapped_buffer)); + header.payload_length = newLen; + offset += sizeof(uint16_t); + } else if (header.payload_length == 127) { + assert(mapped_size >= sizeof(uint64_t)); + header.payload_length = EndianU64_BtoN(*(uint64_t *)(mapped_buffer)); + offset += sizeof(uint64_t); + } else { + assert(header.payload_length < 126 && header.payload_length >= 0); + } + + + if (header.masked) { + assert(mapped_size >= sizeof(self->_currentReadMaskOffset) + offset); + memcpy(self->_currentReadMaskKey, ((uint8_t *)mapped_buffer) + offset, sizeof(self->_currentReadMaskKey)); + } + + [self _handleFrameHeader:header curData:self->_currentFrameData]; + } readToCurrentFrame:NO unmaskBytes:NO]; + } + } readToCurrentFrame:NO unmaskBytes:NO]; +} + +- (void)_readFrameNew; +{ + dispatch_async(_workQueue, ^{ + [self->_currentFrameData setLength:0]; + + self->_currentFrameOpcode = 0; + self->_currentFrameCount = 0; + self->_readOpCount = 0; + self->_currentStringScanPosition = 0; + + [self _readFrameContinue]; + }); +} + +- (void)_pumpWriting; +{ + [self assertOnWorkQueue]; + + NSUInteger dataLength = _outputBuffer.length; + if (dataLength - _outputBufferOffset > 0 && _outputStream.hasSpaceAvailable) { + NSUInteger bytesWritten = [_outputStream write:_outputBuffer.bytes + _outputBufferOffset maxLength:dataLength - _outputBufferOffset]; + if (bytesWritten == -1) { + [self _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:2145 userInfo:[NSDictionary dictionaryWithObject:@"Error writing to stream" forKey:NSLocalizedDescriptionKey]]]; + return; + } + + _outputBufferOffset += bytesWritten; + + if (_outputBufferOffset > 4096 && _outputBufferOffset > (_outputBuffer.length >> 1)) { + _outputBuffer = [[NSMutableData alloc] initWithBytes:(char *)_outputBuffer.bytes + _outputBufferOffset length:_outputBuffer.length - _outputBufferOffset]; + _outputBufferOffset = 0; + } + } + + if (_closeWhenFinishedWriting && + _outputBuffer.length - _outputBufferOffset == 0 && + (_inputStream.streamStatus != NSStreamStatusNotOpen && + _inputStream.streamStatus != NSStreamStatusClosed) && + !_sentClose) { + _sentClose = YES; + + @synchronized (self) { + [_outputStream close]; + [_inputStream close]; + + // TODO: Why are we missing the SocketRocket code to call unscheduleFromRunLoop??? + } + + if (!_failed) { + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:self->_closeCode reason:self->_closeReason wasClean:YES]; + } + }]; + } + [self _scheduleCleanup]; + } +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback; +{ + [self assertOnWorkQueue]; + [self _addConsumerWithScanner:consumer callback:callback dataLength:0]; +} + +- (void)_addConsumerWithDataLength:(size_t)dataLength callback:(data_callback)callback readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + [self assertOnWorkQueue]; + assert(dataLength); + + [_consumers addObject:[_consumerPool consumerWithScanner:nil handler:callback bytesNeeded:dataLength readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]]; + [self _pumpScanner]; +} + +- (void)_addConsumerWithScanner:(stream_scanner)consumer callback:(data_callback)callback dataLength:(size_t)dataLength; +{ + [self assertOnWorkQueue]; + [_consumers addObject:[_consumerPool consumerWithScanner:consumer handler:callback bytesNeeded:dataLength readToCurrentFrame:NO unmaskBytes:NO]]; + [self _pumpScanner]; +} + + +- (void)_scheduleCleanup +{ + @synchronized(self) { + if (_cleanupScheduled) { + return; + } + + _cleanupScheduled = YES; + + // Cleanup NSStream delegate's in the same RunLoop used by the streams themselves: + // This way we'll prevent race conditions between handleEvent and SRWebsocket's dealloc + NSTimer *timer = [NSTimer timerWithTimeInterval:(0.0f) target:self selector:@selector(_cleanupSelfReference:) userInfo:nil repeats:NO]; + [[NSRunLoop FSR_networkRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; + } +} + +- (void)_cleanupSelfReference:(NSTimer *)timer +{ + @synchronized(self) { + // Nuke NSStream delegate's + _inputStream.delegate = nil; + _outputStream.delegate = nil; + + // Remove the streams, right now, from the networkRunLoop + [_inputStream close]; + [_outputStream close]; + } + + // Cleanup selfRetain in the same GCD queue as usual + dispatch_async(_workQueue, ^{ + self->_selfRetain = nil; + }); +} + + +static const char CRLFCRLFBytes[] = {'\r', '\n', '\r', '\n'}; + +- (void)_readUntilHeaderCompleteWithCallback:(data_callback)dataHandler; +{ + [self _readUntilBytes:CRLFCRLFBytes length:sizeof(CRLFCRLFBytes) callback:dataHandler]; +} + +- (void)_readUntilBytes:(const void *)bytes length:(size_t)length callback:(data_callback)dataHandler; +{ + // TODO optimize so this can continue from where we last searched + stream_scanner consumer = ^size_t(NSData *data) { + __block size_t found_size = 0; + __block size_t match_count = 0; + + size_t size = data.length; + const unsigned char *buffer = data.bytes; + for (int i = 0; i < size; i++ ) { + if (((const unsigned char *)buffer)[i] == ((const unsigned char *)bytes)[match_count]) { + match_count += 1; + if (match_count == length) { + found_size = i + 1; + break; + } + } else { + match_count = 0; + } + } + return found_size; + }; + [self _addConsumerWithScanner:consumer callback:dataHandler]; +} + + +// Returns true if did work +- (BOOL)_innerPumpScanner { + + BOOL didWork = NO; + + if (self.readyState >= SR_CLOSING) { + return didWork; + } + + if (!_consumers.count) { + return didWork; + } + + size_t curSize = _readBuffer.length - _readBufferOffset; + if (!curSize) { + return didWork; + } + + FSRIOConsumer *consumer = [_consumers objectAtIndex:0]; + + size_t bytesNeeded = consumer.bytesNeeded; + + size_t foundSize = 0; + if (consumer.consumer) { + NSData *tempView = [NSData dataWithBytesNoCopy:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset freeWhenDone:NO]; + foundSize = consumer.consumer(tempView); + } else { + assert(consumer.bytesNeeded); + if (curSize >= bytesNeeded) { + foundSize = bytesNeeded; + } else if (consumer.readToCurrentFrame) { + foundSize = curSize; + } + } + + NSData *slice = nil; + if (consumer.readToCurrentFrame || foundSize) { + NSRange sliceRange = NSMakeRange(_readBufferOffset, foundSize); + slice = [_readBuffer subdataWithRange:sliceRange]; + + _readBufferOffset += foundSize; + + if (_readBufferOffset > 4096 && _readBufferOffset > (_readBuffer.length >> 1)) { + _readBuffer = [[NSMutableData alloc] initWithBytes:(char *)_readBuffer.bytes + _readBufferOffset length:_readBuffer.length - _readBufferOffset]; _readBufferOffset = 0; + } + + if (consumer.unmaskBytes) { + NSMutableData *mutableSlice = [slice mutableCopy]; + + NSUInteger len = mutableSlice.length; + uint8_t *bytes = mutableSlice.mutableBytes; + + for (int i = 0; i < len; i++) { + bytes[i] = bytes[i] ^ _currentReadMaskKey[_currentReadMaskOffset % sizeof(_currentReadMaskKey)]; + _currentReadMaskOffset += 1; + } + + slice = mutableSlice; + } + + if (consumer.readToCurrentFrame) { + [_currentFrameData appendData:slice]; + + _readOpCount += 1; + + if (_currentFrameOpcode == SROpCodeTextFrame) { + // Validate UTF8 stuff. + size_t currentDataSize = _currentFrameData.length; + if (_currentFrameOpcode == SROpCodeTextFrame && currentDataSize > 0) { + // TODO: Optimize the crap out of this. Don't really have to copy all the data each time + + size_t scanSize = currentDataSize - _currentStringScanPosition; + + NSData *scan_data = [_currentFrameData subdataWithRange:NSMakeRange(_currentStringScanPosition, scanSize)]; + int32_t valid_utf8_size = validate_dispatch_data_partial_string(scan_data); + + if (valid_utf8_size == -1) { + [self closeWithCode:SRStatusCodeInvalidUTF8 reason:@"Text frames must be valid UTF-8"]; + dispatch_async(_workQueue, ^{ + [self _disconnect]; + }); + return didWork; + } else { + _currentStringScanPosition += valid_utf8_size; + } + } + + } + + consumer.bytesNeeded -= foundSize; + + if (consumer.bytesNeeded == 0) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, nil); + didWork = YES; + } + } else if (foundSize) { + [_consumers removeObjectAtIndex:0]; + consumer.handler(self, slice); + didWork = YES; + } + } + return didWork; +} + +-(void)_pumpScanner; +{ + [self assertOnWorkQueue]; + + if (!_isPumping) { + _isPumping = YES; + } else { + return; + } + + while ([self _innerPumpScanner]) { + + } + + _isPumping = NO; +} + +//#define NOMASK + +static const size_t SRFrameHeaderOverhead = 32; + +- (void)_sendFrameWithOpcode:(FSROpCode)opcode data:(id)data; +{ + [self assertOnWorkQueue]; + + if (data == nil) { + return; + } + + NSAssert([data isKindOfClass:[NSData class]] || [data isKindOfClass:[NSString class]], @"Function expects nil, NSString or NSData"); + + size_t payloadLength = [data isKindOfClass:[NSString class]] ? [(NSString *)data lengthOfBytesUsingEncoding:NSUTF8StringEncoding] : [data length]; + + NSMutableData *frame = [[NSMutableData alloc] initWithLength:payloadLength + SRFrameHeaderOverhead]; + if (!frame) { + [self closeWithCode:SRStatusCodeMessageTooBig reason:@"Message too big"]; + return; + } + uint8_t *frame_buffer = (uint8_t *)[frame mutableBytes]; + + // set fin + frame_buffer[0] = SRFinMask | opcode; + + BOOL useMask = YES; +#ifdef NOMASK + useMask = NO; +#endif + + if (useMask) { + // set the mask and header + frame_buffer[1] |= SRMaskMask; + } + + size_t frame_buffer_size = 2; + + const uint8_t *unmasked_payload = NULL; + if ([data isKindOfClass:[NSData class]]) { + unmasked_payload = (uint8_t *)[data bytes]; + } else if ([data isKindOfClass:[NSString class]]) { + unmasked_payload = (const uint8_t *)[data UTF8String]; + } else { + assert(NO); + } + + if (payloadLength < 126) { + frame_buffer[1] |= payloadLength; + } else if (payloadLength <= UINT16_MAX) { + frame_buffer[1] |= 126; + *((uint16_t *)(frame_buffer + frame_buffer_size)) = EndianU16_BtoN((uint16_t)payloadLength); + frame_buffer_size += sizeof(uint16_t); + } else { + frame_buffer[1] |= 127; + *((uint64_t *)(frame_buffer + frame_buffer_size)) = EndianU64_BtoN((uint64_t)payloadLength); + frame_buffer_size += sizeof(uint64_t); + } + + if (!useMask) { + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i]; + frame_buffer_size += 1; + } + } else { + uint8_t *mask_key = frame_buffer + frame_buffer_size; + int result = SecRandomCopyBytes(kSecRandomDefault, sizeof(uint32_t), (uint8_t *)mask_key); + assert(result == 0); + frame_buffer_size += sizeof(uint32_t); + + // TODO: could probably optimize this with SIMD + for (int i = 0; i < payloadLength; i++) { + frame_buffer[frame_buffer_size] = unmasked_payload[i] ^ mask_key[i % sizeof(uint32_t)]; + frame_buffer_size += 1; + } + } + + assert(frame_buffer_size <= [frame length]); + frame.length = frame_buffer_size; + + [self _writeData:frame]; +} + +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode; +{ + __weak __typeof__(self) weakSelf = self; + + // turn on keep-alive for the output stream. + if (eventCode == NSStreamEventOpenCompleted && aStream == _outputStream) { + CFDataRef socketData = CFWriteStreamCopyProperty((CFWriteStreamRef)_outputStream, kCFStreamPropertySocketNativeHandle); + // In rare cases socketData might be nil (there are crash reports out there), in which case we'll have to just + // live without keep-alive :( + if (socketData != nil) { + CFSocketNativeHandle socket; + CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket); + CFRelease(socketData); + + int keepAliveOn = 1; + if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &keepAliveOn, sizeof(keepAliveOn)) == -1) { + SRFastLog(@"Failed to turn on TCP keepalive for websocket"); + } + } + } + + if (_secure && !_pinnedCertFound && (eventCode == NSStreamEventHasBytesAvailable || eventCode == NSStreamEventHasSpaceAvailable)) { + + NSArray *sslCerts = [_urlRequest FSR_SSLPinnedCertificates]; + if (sslCerts) { + SecTrustRef secTrust = (__bridge SecTrustRef)[aStream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust]; + if (secTrust) { + NSInteger numCerts = SecTrustGetCertificateCount(secTrust); + for (NSInteger i = 0; i < numCerts && !_pinnedCertFound; i++) { + SecCertificateRef cert = SecTrustGetCertificateAtIndex(secTrust, i); + NSData *certData = CFBridgingRelease(SecCertificateCopyData(cert)); + + for (id ref in sslCerts) { + SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref; + NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert)); + + if ([trustedCertData isEqualToData:certData]) { + _pinnedCertFound = YES; + break; + } + } + } + } + + if (!_pinnedCertFound) { + dispatch_async(_workQueue, ^{ + NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"Invalid server cert" }; + [weakSelf _failWithError:[NSError errorWithDomain:@"org.lolrus.SocketRocket" code:23556 userInfo:userInfo]]; + }); + return; + } + } + } + + // SRFastLog(@"%@ Got stream event %d", aStream, eventCode); + dispatch_async(_workQueue, ^{ + [weakSelf safeHandleEvent:eventCode stream:aStream]; + }); +} + +- (void)safeHandleEvent:(NSStreamEvent)eventCode stream:(NSStream *)aStream +{ + switch (eventCode) { + case NSStreamEventOpenCompleted: { + SRFastLog(@"NSStreamEventOpenCompleted %@", aStream); + if (self.readyState >= SR_CLOSING) { + return; + } + + + assert(_readBuffer); + + if (self.readyState == SR_CONNECTING && aStream == _inputStream) { + [self didConnect]; + } + [self _pumpWriting]; + [self _pumpScanner]; + break; + } + + case NSStreamEventErrorOccurred: { + // Note: The upstream code for SocketRocket logs the error message, but this causes + // crashes on iOS 13 (https://github.com/firebase/firebase-ios-sdk/issues/3950) + SRFastLog(@"NSStreamEventErrorOccurred %@", aStream); + /// TODO specify error better! + [self _failWithError:aStream.streamError]; + _readBufferOffset = 0; + [_readBuffer setLength:0]; + break; + + } + + case NSStreamEventEndEncountered: { + [self _pumpScanner]; + SRFastLog(@"NSStreamEventEndEncountered %@", aStream); + if (aStream.streamError) { + [self _failWithError:aStream.streamError]; + } else { + dispatch_async(_workQueue, ^{ + if (self.readyState != SR_CLOSED) { + self.readyState = SR_CLOSED; + [self _scheduleCleanup]; + } + + if (!self->_sentClose && !self->_failed) { + self->_sentClose = YES; + // If we get closed in this state it's probably not clean because we should be sending this when we send messages + [self _performDelegateBlock:^{ + if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) { + [self.delegate webSocket:self didCloseWithCode:0 reason:@"Stream end encountered" wasClean:NO]; + } + }]; + } + }); + } + + break; + } + + case NSStreamEventHasBytesAvailable: { + SRFastLog(@"NSStreamEventHasBytesAvailable %@", aStream); + const NSUInteger bufferSize = 2048; + uint8_t buffer[bufferSize]; + + while (_inputStream.hasBytesAvailable) { + NSInteger bytes_read = [_inputStream read:buffer maxLength:bufferSize]; + + if (bytes_read > 0) { + [_readBuffer appendBytes:buffer length:bytes_read]; + } else if (bytes_read < 0) { + [self _failWithError:_inputStream.streamError]; + } + + if (bytes_read != bufferSize) { + break; + } + }; + [self _pumpScanner]; + break; + } + + case NSStreamEventHasSpaceAvailable: { + SRFastLog(@"NSStreamEventHasSpaceAvailable %@", aStream); + [self _pumpWriting]; + break; + } + + default: + SRFastLog(@"(default) %@", aStream); + break; + } +} + +@end + + +@implementation FSRIOConsumer + +@synthesize bytesNeeded = _bytesNeeded; +@synthesize consumer = _scanner; +@synthesize handler = _handler; +@synthesize readToCurrentFrame = _readToCurrentFrame; +@synthesize unmaskBytes = _unmaskBytes; + +- (void)setupWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + _scanner = [scanner copy]; + _handler = [handler copy]; + _bytesNeeded = bytesNeeded; + _readToCurrentFrame = readToCurrentFrame; + _unmaskBytes = unmaskBytes; + assert(_scanner || _bytesNeeded); +} + +@end + +@implementation FSRIOConsumerPool { + NSUInteger _poolSize; + NSMutableArray *_bufferedConsumers; +} + +- (id)initWithBufferCapacity:(NSUInteger)poolSize; +{ + self = [super init]; + if (self) { + _poolSize = poolSize; + _bufferedConsumers = [[NSMutableArray alloc] initWithCapacity:poolSize]; + } + return self; +} + +- (id)init +{ + return [self initWithBufferCapacity:8]; +} + +- (FSRIOConsumer *)consumerWithScanner:(stream_scanner)scanner handler:(data_callback)handler bytesNeeded:(size_t)bytesNeeded readToCurrentFrame:(BOOL)readToCurrentFrame unmaskBytes:(BOOL)unmaskBytes; +{ + FSRIOConsumer *consumer = nil; + if (_bufferedConsumers.count) { + consumer = [_bufferedConsumers lastObject]; + [_bufferedConsumers removeLastObject]; + } else { + consumer = [[FSRIOConsumer alloc] init]; + } + + [consumer setupWithScanner:scanner handler:handler bytesNeeded:bytesNeeded readToCurrentFrame:readToCurrentFrame unmaskBytes:unmaskBytes]; + + return consumer; +} + +- (void)returnConsumer:(FSRIOConsumer *)consumer; +{ + if (_bufferedConsumers.count < _poolSize) { + [_bufferedConsumers addObject:consumer]; + } +} + +@end + +@implementation NSURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSMutableURLRequest (FCertificateAdditions) + +- (NSArray *)FSR_SSLPinnedCertificates; +{ + return [NSURLProtocol propertyForKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +- (void)setFSR_SSLPinnedCertificates:(NSArray *)FSR_SSLPinnedCertificates; +{ + [NSURLProtocol setProperty:FSR_SSLPinnedCertificates forKey:@"FSR_SSLPinnedCertificates" inRequest:self]; +} + +@end + +@implementation NSURL (FSRWebSocket) + +- (NSString *)SR_origin; +{ + NSString *scheme = [self.scheme lowercaseString]; + + if ([scheme isEqualToString:@"wss"]) { + scheme = @"https"; + } else if ([scheme isEqualToString:@"ws"]) { + scheme = @"http"; + } + + if (self.port != nil) { + return [NSString stringWithFormat:@"%@://%@:%@/", scheme, self.host, self.port]; + } else { + return [NSString stringWithFormat:@"%@://%@/", scheme, self.host]; + } +} + +@end + +// #define SR_ENABLE_LOG + +static inline void SRFastLog(NSString *format, ...) { +#ifdef SR_ENABLE_LOG + __block va_list arg_list; + va_start (arg_list, format); + + NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list]; + + va_end(arg_list); + + NSLog(@"[SR] %@", formattedString); +#endif +} + + +#ifdef HAS_ICU + +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + + const void * contents = [data bytes]; + long size = [data length]; + + const uint8_t *str = (const uint8_t *)contents; + + + UChar32 codepoint = 1; + int32_t offset = 0; + int32_t lastOffset = 0; + while(offset < size && codepoint > 0) { + lastOffset = offset; + U8_NEXT(str, offset, size, codepoint); + } + + if (codepoint == -1) { + // Check to see if the last byte is valid or whether it was just continuing + if (!U8_IS_LEAD(str[lastOffset]) || U8_COUNT_TRAIL_BYTES(str[lastOffset]) + lastOffset < (int32_t)size) { + + size = -1; + } else { + uint8_t leadByte = str[lastOffset]; + U8_MASK_LEAD_BYTE(leadByte, U8_COUNT_TRAIL_BYTES(leadByte)); + + for (int i = lastOffset + 1; i < offset; i++) { + + if (U8_IS_SINGLE(str[i]) || U8_IS_LEAD(str[i]) || !U8_IS_TRAIL(str[i])) { + size = -1; + } + } + + if (size != -1) { + size = lastOffset; + } + } + } + + if (size != -1 && ![[NSString alloc] initWithBytesNoCopy:(char *)[data bytes] length:size encoding:NSUTF8StringEncoding freeWhenDone:NO]) { + size = -1; + } + + return (int32_t)size; +} + +#else + +// This is a hack, and probably not optimal +static inline int32_t validate_dispatch_data_partial_string(NSData *data) { + static const int maxCodepointSize = 3; + + for (int i = 0; i < maxCodepointSize; i++) { + NSString *str = [[NSString alloc] initWithBytesNoCopy:(char *)data.bytes length:data.length - i encoding:NSUTF8StringEncoding freeWhenDone:NO]; + if (str) { + return (int)(data.length - i); + } + } + + return -1; +} + +#endif + +static _FSRRunLoopThread *networkThread = nil; +static NSRunLoop *networkRunLoop = nil; + +@implementation NSRunLoop (FSRWebSocket) + ++ (NSRunLoop *)FSR_networkRunLoop { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + networkThread = [[_FSRRunLoopThread alloc] init]; + networkThread.name = @"com.squareup.SocketRocket.NetworkThread"; + [networkThread start]; + networkRunLoop = networkThread.runLoop; + }); + + return networkRunLoop; +} + +@end + + +@implementation _FSRRunLoopThread { + dispatch_group_t _waitGroup; +} + +@synthesize runLoop = _runLoop; + +- (void)dealloc +{ + sr_dispatch_release(_waitGroup); +} + +- (id)init +{ + self = [super init]; + if (self) { + _waitGroup = dispatch_group_create(); + dispatch_group_enter(_waitGroup); + } + return self; +} + + +/** + * This is the main method of the thread on which the socket events are scheduled in a run loop. + */ +- (void)main; +{ + @autoreleasepool { + _runLoop = [NSRunLoop currentRunLoop]; + dispatch_group_leave(_waitGroup); + + // Add an empty run loop source to prevent runloop from spinning. + CFRunLoopSourceContext sourceCtx = { + .version = 0, + .info = NULL, + .retain = NULL, + .release = NULL, + .copyDescription = NULL, + .equal = NULL, + .hash = NULL, + .schedule = NULL, + .cancel = NULL, + .perform = NULL + }; + CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx); + CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode); + CFRelease(source); + + while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) { + + } + assert(NO); + } +} + +- (NSRunLoop *)runLoop; +{ + dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER); + return _runLoop; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h new file mode 100644 index 0000000..bac393b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h @@ -0,0 +1,23 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +@interface FSRUtilities : NSObject + ++ (NSString *)base64EncodedStringFromData:(NSData *)data; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m new file mode 100644 index 0000000..2be1d84 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m @@ -0,0 +1,37 @@ +// +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "NSData+SRB64Additions.h" +#import "fbase64.h" + +@implementation FSRUtilities + ++ (NSString *)base64EncodedStringFromData:(NSData *)data { + size_t buffer_size = ((data.length * 3 + 2) / 2); + + char *buffer = (char *)malloc(buffer_size); + + int len = f_b64_ntop(data.bytes, data.length, buffer, buffer_size); + + if (len == -1) { + free(buffer); + return nil; + } else{ + return [[NSString alloc] initWithBytesNoCopy:buffer length:len encoding:NSUTF8StringEncoding freeWhenDone:YES]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c new file mode 100644 index 0000000..238c23c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.c @@ -0,0 +1,318 @@ +/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ + + +// +// Distributed with modifications by Firebase ( https://www.firebase.com ) +// + +#if (!defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP)) || (!defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON)) + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "fbase64.h" + +static const char Base64[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +#if !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) +int +f_b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + u_int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (int)(datalength); +} +#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ + +#if !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +f_b64_pton(char const *src, u_char *target, size_t targsize) +{ + u_int tarindex, state; + int ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + +#endif /* !defined(HAVE_B64_PTON) && !defined(HAVE___B64_PTON) */ +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h new file mode 100644 index 0000000..a9bf142 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/SocketRocket/fbase64.h @@ -0,0 +1,33 @@ +// Copyright 2012 Square Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef FSocketRocket_base64_h +#define FSocketRocket_base64_h + +#include + +extern int +f_b64_ntop(u_char const *src, + size_t srclength, + char *target, + size_t targsize); + +extern int +f_b64_pton(char const *src, + u_char *target, + size_t targsize); + + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h new file mode 100644 index 0000000..c0baa22 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h @@ -0,0 +1,105 @@ +// +// APLevelDB.h +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +extern NSString * const APLevelDBErrorDomain; + +@class APLevelDBIterator; +@protocol APLevelDBWriteBatch; + +@interface APLevelDB : NSObject + +@property (nonatomic, readonly, strong) NSString *path; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing*)errorOut; +- (void)close; + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key; +- (BOOL)setString:(NSString *)str forKey:(NSString *)key; + +- (NSData *)dataForKey:(NSString *)key; +- (NSString *)stringForKey:(NSString *)key; + +- (BOOL)removeKey:(NSString *)key; + +- (NSArray *)allKeys; + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix usingBlock:(void (^)(NSString *key, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; +- (void)enumerateKeysWithPrefix:(NSString *)prefix asData:(void (^)(NSString *key, NSData *value, BOOL *stop))block; + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to; +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to; + +// Objective-C Subscripting Support: +// The database object supports subscripting for string-string and string-data key-value access and assignment. +// Examples: +// db[@"key"] = @"value"; +// db[@"key"] = [NSData data]; +// NSString *s = db[@"key"]; +// An NSInvalidArgumentException is raised if the key is not an NSString, or if the assigned object is not an +// instance of NSString or NSData. +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; + +// Batch write/atomic update support: +- (id)beginWriteBatch; + +@end + + +@interface APLevelDBIterator : NSObject + ++ (id)iteratorWithLevelDB:(APLevelDB *)db; + +// Designated initializer: +- (id)initWithLevelDB:(APLevelDB *)db; + +- (BOOL)seekToKey:(NSString *)key; +- (NSString *)nextKey; +- (NSString *)key; +- (NSString *)valueAsString; +- (NSData *)valueAsData; + +@end + + +@protocol APLevelDBWriteBatch + +- (void)setData:(NSData *)data forKey:(NSString *)key; +- (void)setString:(NSString *)str forKey:(NSString *)key; + +- (void)removeKey:(NSString *)key; + +// Remove all of the buffered sets and removes: +- (void)clear; +- (BOOL)commit; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm new file mode 100644 index 0000000..cdecce6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm @@ -0,0 +1,500 @@ +// +// APLevelDB.m +// +// Created by Adam Preble on 1/23/12. +// Copyright (c) 2012 Adam Preble. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +// Portions of APLevelDB are based on LevelDB-ObjC: +// https://github.com/hoisie/LevelDB-ObjC +// Specifically the SliceFromString/StringFromSlice macros, and the structure of +// the enumeration methods. License for those potions follows: +// +// Copyright (c) 2011 Pave Labs +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "APLevelDB.h" + +#import "leveldb/db.h" +#import "leveldb/options.h" +#import "leveldb/write_batch.h" + +NSString * const APLevelDBErrorDomain = @"APLevelDBErrorDomain"; + +#define SliceFromString(_string_) (leveldb::Slice((char *)[_string_ UTF8String], [_string_ lengthOfBytesUsingEncoding:NSUTF8StringEncoding])) +#define StringFromSlice(_slice_) ([[NSString alloc] initWithBytes:_slice_.data() length:_slice_.size() encoding:NSUTF8StringEncoding]) + + +@interface APLevelDBWriteBatch : NSObject { + @package + leveldb::WriteBatch _batch; +} + +@property (nonatomic, strong) APLevelDB *levelDB; + +- (id)initWithLevelDB:(APLevelDB *)levelDB; +@end + + +#pragma mark - APLevelDB + +@interface APLevelDB () { + leveldb::DB *_db; + leveldb::ReadOptions _readOptions; + leveldb::WriteOptions _writeOptions; +} +- (id)initWithPath:(NSString *)path error:(NSError **)errorOut; ++ (leveldb::Options)defaultCreateOptions; +@property (nonatomic, readonly) leveldb::DB *db; +@end + + +@implementation APLevelDB + +@synthesize path = _path; +@synthesize db = _db; + ++ (APLevelDB *)levelDBWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + return [[APLevelDB alloc] initWithPath:path error:errorOut]; +} + +- (id)initWithPath:(NSString *)path error:(NSError *__autoreleasing *)errorOut +{ + if ((self = [super init])) + { + _path = path; + + leveldb::Options options = [[self class] defaultCreateOptions]; + + leveldb::Status status = leveldb::DB::Open(options, [_path UTF8String], &_db); + + if (!status.ok()) + { + if (errorOut) + { + NSString *statusString = [[NSString alloc] initWithCString:status.ToString().c_str() encoding:NSUTF8StringEncoding]; + *errorOut = [NSError errorWithDomain:APLevelDBErrorDomain + code:0 + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:statusString, NSLocalizedDescriptionKey, nil]]; + } + return nil; + } + + _writeOptions.sync = false; + } + return self; +} + +- (void)close { + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + +- (void)dealloc +{ + if (_db != NULL) { + delete _db; + _db = NULL; + } +} + ++ (leveldb::Options)defaultCreateOptions +{ + leveldb::Options options; + options.create_if_missing = true; + return options; +} + +- (BOOL)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (BOOL)setString:(NSString *)str forKey:(NSString *)key +{ + // This could have been based on + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); + return (status.ok() == true); +} + +- (NSData *)dataForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + if (!status.ok()) + return nil; + else + return [NSData dataWithBytes:valueCPPString.data() length:valueCPPString.size()]; +} + +- (NSString *)stringForKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + std::string valueCPPString; + leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); + + // We assume (dangerously?) UTF-8 string encoding: + if (!status.ok()) + return nil; + else + return [[NSString alloc] initWithBytes:valueCPPString.data() length:valueCPPString.size() encoding:NSUTF8StringEncoding]; +} + +- (BOOL)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Status status = _db->Delete(_writeOptions, keySlice); + return (status.ok() == true); +} + +- (NSArray *)allKeys +{ + NSMutableArray *keys = [NSMutableArray array]; + [self enumerateKeys:^(NSString *key, BOOL *stop) { + [keys addObject:key]; + }]; + return keys; +} + +- (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asStrings:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asStrings:(void (^)(NSString *, NSString *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSString *v = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding]; + block(k, v, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" usingBlock:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString usingBlock:(void (^)(NSString *key, BOOL *stop))block; +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Slice prefix = SliceFromString(prefixString); + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + block(k, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (void)enumerateKeysAndValuesAsData:(void (^)(NSString *key, NSData *data, BOOL *stop))block +{ + [self enumerateKeysWithPrefix:@"" asData:block]; +} + +- (void)enumerateKeysWithPrefix:(NSString *)prefixString asData:(void (^)(NSString *, NSData *, BOOL *))block +{ + @autoreleasepool { + BOOL stop = NO; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice prefix = SliceFromString(prefixString); + for (iter->Seek(prefix); iter->Valid(); iter->Next()) { + leveldb::Slice key = iter->key(), value = iter->value(); + if (key.starts_with(prefix)) { + NSString *k = StringFromSlice(key); + NSData *data = [NSData dataWithBytes:value.data() length:value.size()]; + block(k, data, &stop); + if (stop) + break; + } else { + break; + } + } + + delete iter; + } +} + +- (NSUInteger)exactSizeFrom:(NSString *)from to:(NSString *)to { + NSUInteger size = 0; + leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + iter->Seek(fromSlice); + while (iter->Valid() && iter->key().compare(toSlice) <= 0) { + size += iter->value().size(); + iter->Next(); + } + delete iter; + return size; +} + + +- (NSUInteger)approximateSizeFrom:(NSString *)from to:(NSString *)to { + leveldb::Range ranges[1]; + leveldb::Slice fromSlice = SliceFromString(from); + leveldb::Slice toSlice = SliceFromString(to); + ranges[0] = leveldb::Range(fromSlice, toSlice); + uint64_t sizes[1]; + _db->GetApproximateSizes(ranges, 1, sizes); + return (NSUInteger)sizes[0]; +} + +#pragma mark - Subscripting Support + +- (id)objectForKeyedSubscript:(id)key +{ + if (![key respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be an NSString"]; + } + return [self stringForKey:key]; +} +- (void)setObject:(id)thing forKeyedSubscript:(id)key +{ + id idKey = (id) key; + if (![idKey respondsToSelector: @selector(componentsSeparatedByString:)]) + { + [NSException raise:NSInvalidArgumentException format:@"key must be NSString or NSData"]; + } + + if ([thing respondsToSelector:@selector(componentsSeparatedByString:)]) + [self setString:thing forKey:(NSString *)key]; + else if ([thing respondsToSelector:@selector(subdataWithRange:)]) + [self setData:thing forKey:(NSString *)key]; + else + [NSException raise:NSInvalidArgumentException format:@"object must be NSString or NSData"]; +} + +#pragma mark - Atomic Updates + +- (id)beginWriteBatch +{ + APLevelDBWriteBatch *batch = [[APLevelDBWriteBatch alloc] initWithLevelDB:self]; + return batch; +} + +- (BOOL)commitWriteBatch:(id)theBatch +{ + if (!theBatch) + return NO; + + APLevelDBWriteBatch *batch = theBatch; + + leveldb::Status status; + status = _db->Write(_writeOptions, &batch->_batch); + return (status.ok() == true); +} + +@end + + +#pragma mark - APLevelDBIterator + +@interface APLevelDBIterator () { + leveldb::Iterator *_iter; +} + +@property (nonatomic, strong) APLevelDB *levelDB; +@end + + + +@implementation APLevelDBIterator + ++ (id)iteratorWithLevelDB:(APLevelDB *)db +{ + APLevelDBIterator *iter = [[[self class] alloc] initWithLevelDB:db]; + return iter; +} + +- (id)initWithLevelDB:(APLevelDB *)db +{ + if ((self = [super init])) + { + // Hold on to the database so it doesn't get deallocated before the iterator is deallocated + self->_levelDB = db; + _iter = db.db->NewIterator(leveldb::ReadOptions()); + _iter->SeekToFirst(); + if (!_iter->Valid()) + return nil; + } + return self; +} + +- (id)init +{ + [NSException raise:@"BadInitializer" format:@"Use the designated initializer, -initWithLevelDB:, instead."]; + return nil; +} + +- (void)dealloc +{ + self->_levelDB = nil; + delete _iter; + _iter = NULL; +} + +- (BOOL)seekToKey:(NSString *)key +{ + leveldb::Slice target = SliceFromString(key); + _iter->Seek(target); + return _iter->Valid() == true; +} + +- (void)seekToFirst +{ + _iter->SeekToFirst(); +} + +- (void)seekToLast +{ + _iter->SeekToLast(); +} + +- (NSString *)nextKey +{ + _iter->Next(); + return [self key]; +} + +- (NSString *)key +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->key(); + return StringFromSlice(value); +} + +- (NSString *)valueAsString +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return StringFromSlice(value); +} + +- (NSData *)valueAsData +{ + if (_iter->Valid() == false) + return nil; + leveldb::Slice value = _iter->value(); + return [NSData dataWithBytes:value.data() length:value.size()]; +} + +@end + + + +#pragma mark - APLevelDBWriteBatch + +@implementation APLevelDBWriteBatch + +- (id)initWithLevelDB:(APLevelDB *)levelDB { + self = [super init]; + if (self != nil) { + self->_levelDB = levelDB; + } + return self; +} + +- (void)setData:(NSData *)data forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); + _batch.Put(keySlice, valueSlice); +} +- (void)setString:(NSString *)str forKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + leveldb::Slice valueSlice = SliceFromString(str); + _batch.Put(keySlice, valueSlice); +} + +- (void)removeKey:(NSString *)key +{ + leveldb::Slice keySlice = SliceFromString(key); + _batch.Delete(keySlice); +} + +- (void)clear +{ + _batch.Clear(); +} + +- (BOOL)commit { + return [self.levelDB commitWriteBatch:self]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseDatabase/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h new file mode 100644 index 0000000..5bc21a1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class FIRInstallationsHTTPError; + +NS_ASSUME_NONNULL_BEGIN + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer); + +@interface FIRInstallationsErrorUtil : NSObject + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception; ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error; + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status; + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName; + ++ (NSError *)JSONSerializationError:(NSError *)error; + ++ (NSError *)networkErrorWithError:(NSError *)error; + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName; + ++ (NSError *)corruptedIIDTokenData; + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data; ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode; + +/** + * Returns the passed error if it is already in the public domain or a new error with the passed + * error at `NSUnderlyingErrorKey`. + */ ++ (NSError *)publicDomainErrorWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m new file mode 100644 index 0000000..f85923a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m @@ -0,0 +1,124 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsErrorUtil.h" + +#import "FIRInstallationsHTTPError.h" + +NSString *const kFirebaseInstallationsErrorDomain = @"com.firebase.installations"; + +void FIRInstallationsItemSetErrorToPointer(NSError *error, NSError **pointer) { + if (pointer != NULL) { + *pointer = error; + } +} + +@implementation FIRInstallationsErrorUtil + ++ (NSError *)keyedArchiverErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)keyedArchiverErrorWithError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"NSKeyedArchiver error."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:error]; +} + ++ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status { + NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeKeychain + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)installationItemNotFoundForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *failureReason = + [NSString stringWithFormat:@"Installation for appID %@ appName %@ not found", appID, appName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)corruptedIIDTokenData { + NSString *failureReason = + @"IID token data stored in Keychain is corrupted or in an incompatible format."; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (FIRInstallationsHTTPError *)APIErrorWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:HTTPResponse data:data]; +} + ++ (BOOL)isAPIError:(NSError *)error withHTTPCode:(NSInteger)HTTPCode { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + return [(FIRInstallationsHTTPError *)error HTTPResponse].statusCode == HTTPCode; +} + ++ (NSError *)JSONSerializationError:(NSError *)error { + NSString *failureReason = [NSString stringWithFormat:@"Failed to serialize JSON data."]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)FIDRegistrationErrorWithResponseMissingField:(NSString *)missingFieldName { + NSString *failureReason = [NSString + stringWithFormat:@"A required response field with name %@ is missing", missingFieldName]; + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:failureReason + underlyingError:nil]; +} + ++ (NSError *)networkErrorWithError:(NSError *)error { + return [self installationsErrorWithCode:FIRInstallationsErrorCodeServerUnreachable + failureReason:@"Network connection error." + underlyingError:error]; +} + ++ (NSError *)publicDomainErrorWithError:(NSError *)error { + if ([error.domain isEqualToString:kFirebaseInstallationsErrorDomain]) { + return error; + } + + return [self installationsErrorWithCode:FIRInstallationsErrorCodeUnknown + failureReason:nil + underlyingError:error]; +} + ++ (NSError *)installationsErrorWithCode:(FIRInstallationsErrorCode)code + failureReason:(nullable NSString *)failureReason + underlyingError:(nullable NSError *)underlyingError { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + userInfo[NSUnderlyingErrorKey] = underlyingError; + userInfo[NSLocalizedFailureReasonErrorKey] = failureReason; + + return [NSError errorWithDomain:kFirebaseInstallationsErrorDomain code:code userInfo:userInfo]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h new file mode 100644 index 0000000..ad0eb8c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Represents an error caused by an unexpected API response. */ +@interface FIRInstallationsHTTPError : NSError + +@property(nonatomic, readonly) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic, readonly, nonnull) NSData *data; + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse data:(nullable NSData *)data; + +@end + +NS_ASSUME_NONNULL_END + +typedef NS_ENUM(NSInteger, FIRInstallationsHTTPCodes) { + FIRInstallationsHTTPCodesTooManyRequests = 429, + FIRInstallationsHTTPCodesServerInternalError = 500, +}; + +/** Possible response HTTP codes for `CreateInstallation` API request. */ +typedef NS_ENUM(NSInteger, FIRInstallationsRegistrationHTTPCode) { + FIRInstallationsRegistrationHTTPCodeSuccess = 201, + FIRInstallationsRegistrationHTTPCodeInvalidArgument = 400, + FIRInstallationsRegistrationHTTPCodeInvalidAPIKey = 401, + FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch = 403, + FIRInstallationsRegistrationHTTPCodeProjectNotFound = 404, + FIRInstallationsRegistrationHTTPCodeTooManyRequests = 429, + FIRInstallationsRegistrationHTTPCodeServerInternalError = 500 +}; + +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenHTTPCode) { + FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication = 401, + FIRInstallationsAuthTokenHTTPCodeFIDNotFound = 404, +}; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m new file mode 100644 index 0000000..5b3eae2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m @@ -0,0 +1,78 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsErrorUtil.h" + +@implementation FIRInstallationsHTTPError + +- (instancetype)initWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSDictionary *userInfo = [FIRInstallationsHTTPError userInfoWithHTTPResponse:HTTPResponse + data:data]; + self = [super + initWithDomain:kFirebaseInstallationsErrorDomain + code:[FIRInstallationsHTTPError errorCodeWithHTTPCode:HTTPResponse.statusCode] + userInfo:userInfo]; + if (self) { + _HTTPResponse = HTTPResponse; + _data = data; + } + return self; +} + ++ (FIRInstallationsErrorCode)errorCodeWithHTTPCode:(NSInteger)HTTPCode { + return FIRInstallationsErrorCodeUnknown; +} + ++ (NSDictionary *)userInfoWithHTTPResponse:(NSHTTPURLResponse *)HTTPResponse + data:(nullable NSData *)data { + NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSString *failureReason = [NSString + stringWithFormat:@"The server responded with an error. HTTP response: %@\nResponse body: %@", + HTTPResponse, responseString]; + return @{NSLocalizedFailureReasonErrorKey : failureReason}; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone { + return [[FIRInstallationsHTTPError alloc] initWithHTTPResponse:self.HTTPResponse data:self.data]; +} + +#pragma mark - NSSecureCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)coder { + NSHTTPURLResponse *HTTPResponse = [coder decodeObjectOfClass:[NSHTTPURLResponse class] + forKey:@"HTTPResponse"]; + if (!HTTPResponse) { + return nil; + } + NSData *data = [coder decodeObjectOfClass:[NSData class] forKey:@"data"]; + + return [self initWithHTTPResponse:HTTPResponse data:data]; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.HTTPResponse forKey:@"HTTPResponse"]; + [coder encodeObject:self.data forKey:@"data"]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m new file mode 100644 index 0000000..71e7dd4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallations.m @@ -0,0 +1,248 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import +#import +#import +#import +#import + +#import "FIRInstallationsAuthTokenResultInternal.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIDController.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsVersion.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol FIRInstallationsInstanceProvider +@end + +@interface FIRInstallations () +@property(nonatomic, readonly) FIROptions *appOptions; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsIDController *installationsIDController; + +@end + +@implementation FIRInstallations + +#pragma mark - Firebase component + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-install" + withVersion:[NSString stringWithUTF8String:FIRInstallationsVersionStr]]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + *isCacheable = YES; + FIRInstallations *installations = [[FIRInstallations alloc] initWithApp:container.app]; + return installations; + }; + + FIRComponent *installationsProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstallationsInstanceProvider) + instantiationTiming:FIRInstantiationTimingAlwaysEager + dependencies:@[] + creationBlock:creationBlock]; + return @[ installationsProvider ]; +} + +- (instancetype)initWithApp:(FIRApp *)app { + return [self initWitAppOptions:app.options appName:app.name]; +} + +- (instancetype)initWitAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + FIRInstallationsIDController *IDController = + [[FIRInstallationsIDController alloc] initWithGoogleAppID:appOptions.googleAppID + appName:appName + APIKey:appOptions.APIKey + projectID:appOptions.projectID + GCMSenderID:appOptions.GCMSenderID + accessGroup:appOptions.appGroupID]; + return [self initWithAppOptions:appOptions + appName:appName + installationsIDController:IDController + prefetchAuthToken:YES]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithAppOptions:(FIROptions *)appOptions + appName:(NSString *)appName + installationsIDController:(FIRInstallationsIDController *)installationsIDController + prefetchAuthToken:(BOOL)prefetchAuthToken { + self = [super init]; + if (self) { + [[self class] validateAppOptions:appOptions appName:appName]; + [[self class] assertCompatibleIIDVersion]; + + _appOptions = [appOptions copy]; + _appName = [appName copy]; + _installationsIDController = installationsIDController; + + // Pre-fetch auth token. + if (prefetchAuthToken) { + [self authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error){ + }]; + } + } + return self; +} + ++ (void)validateAppOptions:(FIROptions *)appOptions appName:(NSString *)appName { + NSMutableArray *missingFields = [NSMutableArray array]; + if (appName.length < 1) { + [missingFields addObject:@"`FirebaseApp.name`"]; + } + if (appOptions.APIKey.length < 1) { + [missingFields addObject:@"`FirebaseOptions.APIKey`"]; + } + if (appOptions.googleAppID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.googleAppID`"]; + } + + // TODO(#4692): Check for `appOptions.projectID.length < 1` only. + // We can use `GCMSenderID` instead of `projectID` temporary. + if (appOptions.projectID.length < 1 && appOptions.GCMSenderID.length < 1) { + [missingFields addObject:@"`FirebaseOptions.projectID`"]; + } + + if (missingFields.count > 0) { + [NSException + raise:kFirebaseInstallationsErrorDomain + format: + @"%@[%@] Could not configure Firebase Installations due to invalid FirebaseApp " + @"options. The following parameters are nil or empty: %@. If you use " + @"GoogleServices-Info.plist please download the most recent version from the Firebase " + @"Console. If you configure Firebase in code, please make sure you specify all " + @"required parameters.", + kFIRLoggerInstallations, kFIRInstallationsMessageCodeInvalidFirebaseAppOptions, + [missingFields componentsJoinedByString:@", "]]; + } +} + +#pragma mark - Public + ++ (FIRInstallations *)installations { + FIRApp *defaultApp = [FIRApp defaultApp]; + if (!defaultApp) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"The default FirebaseApp instance must be configured before the default" + @"FirebaseApp instance can be initialized. One way to ensure that is to " + @"call `[FIRApp configure];` (`FirebaseApp.configure()` in Swift) in the App" + @" Delegate's `application:didFinishLaunchingWithOptions:` " + @"(`application(_:didFinishLaunchingWithOptions:)` in Swift)."]; + } + + return [self installationsWithApp:defaultApp]; +} + ++ (FIRInstallations *)installationsWithApp:(FIRApp *)app { + id installations = + FIR_COMPONENT(FIRInstallationsInstanceProvider, app.container); + return (FIRInstallations *)installations; +} + +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion { + [self.installationsIDController getInstallationItem] + .then(^id(FIRInstallationsItem *installation) { + completion(installation.firebaseInstallationID, nil); + return nil; + }) + .catch(^(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion { + [self authTokenForcingRefresh:NO completion:completion]; +} + +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion { + [self.installationsIDController getAuthTokenForcingRefresh:forceRefresh] + .then(^FIRInstallationsAuthTokenResult *(FIRInstallationsItem *installation) { + FIRInstallationsAuthTokenResult *result = [[FIRInstallationsAuthTokenResult alloc] + initWithToken:installation.authToken.token + expirationDate:installation.authToken.expirationDate]; + return result; + }) + .then(^id(FIRInstallationsAuthTokenResult *token) { + completion(token, nil); + return nil; + }) + .catch(^void(NSError *error) { + completion(nil, [FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion { + [self.installationsIDController deleteInstallation] + .then(^id(id result) { + completion(nil); + return nil; + }) + .catch(^void(NSError *error) { + completion([FIRInstallationsErrorUtil publicDomainErrorWithError:error]); + }); +} + +#pragma mark - IID version compatibility + ++ (void)assertCompatibleIIDVersion { + // We use this flag to disable IID compatibility exception for unit tests. +#ifdef FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION + return; +#else + if (![self isIIDVersionCompatible]) { + [NSException raise:kFirebaseInstallationsErrorDomain + format:@"FirebaseInstallations will not work correctly with current version of " + @"Firebase Instance ID. Please update your Firebase Instance ID version."]; + } +#endif +} + ++ (BOOL)isIIDVersionCompatible { + Class IIDClass = NSClassFromString(@"FIRInstanceID"); + if (IIDClass == nil) { + // It is OK if there is no IID at all. + return YES; + } + // We expect a compatible version having the method `+[FIRInstanceID usesFIS]` defined. + BOOL isCompatibleVersion = [IIDClass respondsToSelector:NSSelectorFromString(@"usesFIS")]; + return isCompatibleVersion; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m new file mode 100644 index 0000000..92e5fab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m @@ -0,0 +1,30 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAuthTokenResultInternal.h" + +@implementation FIRInstallationsAuthTokenResult + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationDate { + self = [super init]; + if (self) { + _authToken = [token copy]; + _expirationDate = expirationDate; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h new file mode 100644 index 0000000..0c959db --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsAuthTokenResult (Internal) + +- (instancetype)initWithToken:(NSString *)token expirationDate:(NSDate *)expirationTime; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h new file mode 100644 index 0000000..95fdf83 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.h @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredItem; +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class represents the required installation ID and auth token data including possible states. + * The data is stored to Keychain via `FIRInstallationsStoredItem` which has only the storage + * relevant data and does not contain any logic. `FIRInstallationsItem` must be used on the logic + * level (not `FIRInstallationsStoredItem`). + */ +@interface FIRInstallationsItem : NSObject + +/// A `FirebaseApp` identifier. +@property(nonatomic, readonly) NSString *appID; +/// A `FirebaseApp` name. +@property(nonatomic, readonly) NSString *firebaseAppName; +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic, assign) FIRInstallationsStatus registrationStatus; + +/// Instance ID default token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName; + +/** + * Populates `FIRInstallationsItem` properties with data from `FIRInstallationsStoredItem`. + * @param item An instance of `FIRInstallationsStoredItem` to get data from. + */ +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item; + +/** + * Creates a stored item with data from the object. + * @return Returns a `FIRInstallationsStoredItem` instance with the data from the object. + */ +- (FIRInstallationsStoredItem *)storedItem; + +/** + * The installation identifier. + * @return Returns a string uniquely identifying the installation. + */ +- (NSString *)identifier; + +/** + * The installation identifier. + * @param appID A `FirebaseApp` identifier. + * @param appName A `FirebaseApp` name. + * @return Returns a string uniquely identifying the installation. + */ ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName; + +/** + * Generate a new Firebase Installation Identifier. + * @return Returns a 22 characters long globally unique string created based on UUID. + */ ++ (NSString *)generateFID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m new file mode 100644 index 0000000..bc819bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsItem.m @@ -0,0 +1,104 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +#import "FIRInstallationsStoredAuthToken.h" +#import "FIRInstallationsStoredItem.h" + +@implementation FIRInstallationsItem + +- (instancetype)initWithAppID:(NSString *)appID firebaseAppName:(NSString *)firebaseAppName { + self = [super init]; + if (self) { + _appID = [appID copy]; + _firebaseAppName = [firebaseAppName copy]; + } + return self; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsItem *clone = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.firebaseAppName]; + clone.firebaseInstallationID = [self.firebaseInstallationID copy]; + clone.refreshToken = [self.refreshToken copy]; + clone.authToken = [self.authToken copy]; + clone.registrationStatus = self.registrationStatus; + + return clone; +} + +- (void)updateWithStoredItem:(FIRInstallationsStoredItem *)item { + self.firebaseInstallationID = item.firebaseInstallationID; + self.refreshToken = item.refreshToken; + self.authToken = item.authToken; + self.registrationStatus = item.registrationStatus; + self.IIDDefaultToken = item.IIDDefaultToken; +} + +- (FIRInstallationsStoredItem *)storedItem { + FIRInstallationsStoredItem *storedItem = [[FIRInstallationsStoredItem alloc] init]; + storedItem.firebaseInstallationID = self.firebaseInstallationID; + storedItem.refreshToken = self.refreshToken; + storedItem.authToken = self.authToken; + storedItem.registrationStatus = self.registrationStatus; + storedItem.IIDDefaultToken = self.IIDDefaultToken; + return storedItem; +} + +- (nonnull NSString *)identifier { + return [[self class] identifierWithAppID:self.appID appName:self.firebaseAppName]; +} + ++ (NSString *)identifierWithAppID:(NSString *)appID appName:(NSString *)appName { + return [appID stringByAppendingString:appName]; +} + ++ (NSString *)generateFID { + NSUUID *UUID = [NSUUID UUID]; + uuid_t UUIDBytes; + [UUID getUUIDBytes:UUIDBytes]; + + NSUInteger UUIDLength = sizeof(uuid_t); + NSData *UUIDData = [NSData dataWithBytes:UUIDBytes length:UUIDLength]; + + uint8_t UUIDLast4Bits = UUIDBytes[UUIDLength - 1] & 0b00001111; + + // FID first 4 bits must be `0111`. The last 4 UUID bits will be cut later to form a proper FID. + // To keep 16 random bytes we copy these last 4 UUID to the FID 1st byte after `0111` prefix. + uint8_t FIDPrefix = 0b01110000 | UUIDLast4Bits; + NSMutableData *FIDData = [NSMutableData dataWithBytes:&FIDPrefix length:1]; + + [FIDData appendData:UUIDData]; + NSString *FIDString = [self base64URLEncodedStringWithData:FIDData]; + + // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5 bytes. + // Our generated ID has 16 bytes UUID + 1 byte prefix which after encoding with base64 will become + // 23 characters plus 1 character for "=" padding. + + // Remove the 23rd character that was added because of the extra 4 bits at the + // end of our 17 byte data and the '=' padding. + return [FIDString substringWithRange:NSMakeRange(0, 22)]; +} + ++ (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + return string; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h new file mode 100644 index 0000000..baeadb2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +extern FIRLoggerService kFIRLoggerInstallations; + +// FIRInstallationsAPIService.m +extern NSString *const kFIRInstallationsMessageCodeSendAPIRequest; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError; +extern NSString *const kFIRInstallationsMessageCodeAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse; +extern NSString *const kFIRInstallationsMessageCodeParsingAPIResponse; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed; +extern NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed; + +// FIRInstallationsIDController.m +extern NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated; +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration; + +// FIRInstallationsStoredItem.m +extern NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch; + +// FIRInstallationsStoredAuthToken.m +extern NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch; + +// FIRInstallationsStoredIIDCheckin.m +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch; +extern NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode; + +// FIRInstallations.m +extern NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m new file mode 100644 index 0000000..c2bdf37 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsLogger.m @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsLogger.h" + +FIRLoggerService kFIRLoggerInstallations = @"[Firebase/Installations]"; + +// FIRInstallationsAPIService.m +NSString *const kFIRInstallationsMessageCodeSendAPIRequest = @"I-FIS001001"; +NSString *const kFIRInstallationsMessageCodeAPIRequestNetworkError = @"I-FIS001002"; +NSString *const kFIRInstallationsMessageCodeAPIRequestResponse = @"I-FIS001003"; +NSString *const kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse = @"I-FIS001004"; +NSString *const kFIRInstallationsMessageCodeParsingAPIResponse = @"I-FIS001005"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed = @"I-FIS001006"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed = @"I-FIS001007"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed = @"I-FIS001008"; +NSString *const kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed = @"I-FIS001009"; + +// FIRInstallationsIDController.m +NSString *const kFIRInstallationsMessageCodeNewGetInstallationOperationCreated = @"I-FIS002000"; +NSString *const kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated = @"I-FIS002001"; +NSString *const kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated = @"I-FIS002002"; +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseConfiguration = @"I-FIS002003"; + +// FIRInstallationsStoredItem.m +NSString *const kFIRInstallationsMessageCodeInstallationCoderVersionMismatch = @"I-FIS003000"; + +// FIRInstallationsStoredAuthToken.m +NSString *const kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch = @"I-FIS004000"; + +// FIRInstallationsStoredIIDCheckin.m +NSString *const kFIRInstallationsMessageCodeIIDCheckinCoderVersionMismatch = @"I-FIS007000"; +NSString *const kFIRInstallationsMessageCodeIIDCheckinFailedToDecode = @"I-FIS007001"; + +// FIRInstallations.m +NSString *const kFIRInstallationsMessageCodeInvalidFirebaseAppOptions = @"I-FIS008000"; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m new file mode 100644 index 0000000..a75e3f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/FIRInstallationsVersion.m @@ -0,0 +1,23 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsVersion.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +const char *const FIRInstallationsVersionStr = (const char *const)STR(FIRInstallations_LIB_VERSION); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h new file mode 100644 index 0000000..e2408ca --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** The class encapsulates a port of a piece FirebaseInstanceID logic required to migrate IID. */ +@interface FIRInstallationsIIDStore : NSObject + +/** + * Retrieves existing IID if present. + * @return Returns a promise that is resolved with IID string if IID has been found or rejected with + * an error otherwise. + */ +- (FBLPromise *)existingIID; + +/** + * Deletes existing IID if present. + * @return Returns a promise that is resolved with `[NSNull null]` if the IID was successfully. + * deleted or was not found. The promise is rejected otherwise. + */ +- (FBLPromise *)deleteExistingIID; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m new file mode 100644 index 0000000..1f3a82a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m @@ -0,0 +1,236 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import "FIRInstallationsErrorUtil.h" + +static NSString *const kFIRInstallationsIIDKeyPairPublicTagPrefix = + @"com.google.iid.keypair.public-"; +static NSString *const kFIRInstallationsIIDKeyPairPrivateTagPrefix = + @"com.google.iid.keypair.private-"; +static NSString *const kFIRInstallationsIIDCreationTimePlistKey = @"|S|cre"; + +@implementation FIRInstallationsIIDStore + +- (FBLPromise *)existingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + if (![self hasPlistIIDFlag]) { + return nil; + } + + NSData *IIDPublicKeyData = [self IIDPublicKeyData]; + return [self IIDWithPublicKeyData:IIDPublicKeyData]; + }] + .validate(^BOOL(NSString *_Nullable IID) { + return IID.length > 0; + }); +} + +- (FBLPromise *)deleteExistingIID { + return [FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + NSError *error; + if (![self deleteIIDFlagFromPlist:&error]) { + return error; + } + + if (![self deleteIID:&error]) { + return error; + } + + return [NSNull null]; + }]; +} + +#pragma mark - IID decoding + +- (NSString *)IIDWithPublicKeyData:(NSData *)publicKeyData { + NSData *publicKeySHA1 = [self sha1WithData:publicKeyData]; + + const uint8_t *bytes = publicKeySHA1.bytes; + NSMutableData *identityData = [NSMutableData dataWithData:publicKeySHA1]; + + uint8_t b0 = bytes[0]; + // Take the first byte and make the initial four 7 by initially making the initial 4 bits 0 + // and then adding 0x70 to it. + b0 = 0x70 + (0xF & b0); + // failsafe should give you back b0 itself + b0 = (b0 & 0xFF); + [identityData replaceBytesInRange:NSMakeRange(0, 1) withBytes:&b0]; + NSData *data = [identityData subdataWithRange:NSMakeRange(0, 8 * sizeof(Byte))]; + return [self base64URLEncodedStringWithData:data]; +} + +- (NSData *)sha1WithData:(NSData *)data { + unsigned char output[CC_SHA1_DIGEST_LENGTH]; + unsigned int length = (unsigned int)[data length]; + + CC_SHA1(data.bytes, length, output); + return [NSData dataWithBytes:output length:CC_SHA1_DIGEST_LENGTH]; +} + +- (NSString *)base64URLEncodedStringWithData:(NSData *)data { + NSString *string = [data base64EncodedStringWithOptions:0]; + string = [string stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + string = [string stringByReplacingOccurrencesOfString:@"+" withString:@"-"]; + string = [string stringByReplacingOccurrencesOfString:@"=" withString:@""]; + return string; +} + +#pragma mark - Keychain + +- (NSData *)IIDPublicKeyData { + NSString *tag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *query = [self keyPairQueryWithTag:tag returnData:YES]; + + CFTypeRef keyRef = NULL; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + return nil; + } + + return (__bridge NSData *)keyRef; +} + +- (BOOL)deleteIID:(NSError **)outError { + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix + error:outError]) { + return NO; + } + + if (![self deleteKeychainKeyWithTagPrefix:kFIRInstallationsIIDKeyPairPrivateTagPrefix + error:outError]) { + return NO; + } + + return YES; +} + +- (BOOL)deleteKeychainKeyWithTagPrefix:(NSString *)tagPrefix error:(NSError **)outError { + NSString *keyTag = [self keychainKeyTagWithPrefix:kFIRInstallationsIIDKeyPairPublicTagPrefix]; + NSDictionary *keyQuery = [self keyPairQueryWithTag:keyTag returnData:NO]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keyQuery); + + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete" status:status], + outError); + return NO; + } + + return YES; +} + +- (NSDictionary *)keyPairQueryWithTag:(NSString *)tag returnData:(BOOL)shouldReturnData { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + NSData *tagData = [tag dataUsingEncoding:NSUTF8StringEncoding]; + + query[(__bridge id)kSecClass] = (__bridge id)kSecClassKey; + query[(__bridge id)kSecAttrApplicationTag] = tagData; + query[(__bridge id)kSecAttrKeyType] = (__bridge id)kSecAttrKeyTypeRSA; + if (shouldReturnData) { + query[(__bridge id)kSecReturnData] = @(YES); + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +- (NSString *)keychainKeyTagWithPrefix:(NSString *)prefix { + NSString *mainAppBundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (mainAppBundleID.length == 0) { + return nil; + } + return [NSString stringWithFormat:@"%@%@", prefix, mainAppBundleID]; +} + +- (NSString *)mainbundleIdentifier { + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleIdentifier.length) { + return nil; + } + return bundleIdentifier; +} + +#pragma mark - Plist + +- (BOOL)deleteIIDFlagFromPlist:(NSError **)outError { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return YES; + } + + NSMutableDictionary *plistContent = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; + plistContent[kFIRInstallationsIIDCreationTimePlistKey] = nil; + + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + return [plistContent writeToURL:[NSURL fileURLWithPath:path] error:outError]; + } + + return [plistContent writeToFile:path atomically:YES]; +} + +- (BOOL)hasPlistIIDFlag { + NSString *path = [self plistPath]; + if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { + return NO; + } + + NSDictionary *plistContent = [[NSDictionary alloc] initWithContentsOfFile:path]; + return plistContent[kFIRInstallationsIIDCreationTimePlistKey] != nil; +} + +- (NSString *)plistPath { + NSString *plistNameWithExtension = @"com.google.iid-keypair.plist"; + NSString *_subDirectoryName = @"Google/FirebaseInstanceID"; + + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h new file mode 100644 index 0000000..ed98e3d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class reads a default IID token from IID store if available. + */ +@interface FIRInstallationsIIDTokenStore : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID; + +- (FBLPromise *)existingIIDDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m new file mode 100644 index 0000000..1c9dbab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m @@ -0,0 +1,157 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIIDTokenStore.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsKeychainUtils.h" + +static NSString *const kFIRInstallationsIIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstallationsIIDTokenInfo : NSObject +@property(nonatomic, nullable, copy) NSString *token; +@end + +@implementation FIRInstallationsIIDTokenInfo + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)coder { +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { + self = [super init]; + if (self) { + _token = [coder decodeObjectOfClass:[NSString class] forKey:@"token"]; + } + return self; +} + +@end + +@interface FIRInstallationsIIDTokenStore () +@property(nonatomic, readonly) NSString *GCMSenderID; +@end + +@implementation FIRInstallationsIIDTokenStore + +- (instancetype)initWithGCMSenderID:(NSString *)GCMSenderID { + self = [super init]; + if (self) { + _GCMSenderID = GCMSenderID; + } + return self; +} + +- (FBLPromise *)existingIIDDefaultToken { + return [[FBLPromise onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + do:^id _Nullable { + return [self IIDDefaultTokenData]; + }] onQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0) + then:^id _Nullable(NSData *_Nullable keychainData) { + return [self IIDCheckinWithData:keychainData]; + }]; +} + +- (FBLPromise *)IIDCheckinWithData:(NSData *)data { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSError *archiverError; + NSKeyedUnarchiver *unarchiver; + if (@available(iOS 11.0, tvOS 11.0, macOS 10.13, *)) { + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:&archiverError]; + } else { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + archiverError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + + if (!unarchiver) { + NSError *error = archiverError ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:error]; + return resultPromise; + } + + [unarchiver setClass:[FIRInstallationsIIDTokenInfo class] forClassName:@"FIRInstanceIDTokenInfo"]; + FIRInstallationsIIDTokenInfo *IIDTokenInfo = + [unarchiver decodeObjectOfClass:[FIRInstallationsIIDTokenInfo class] + forKey:NSKeyedArchiveRootObjectKey]; + + if (IIDTokenInfo.token.length < 1) { + [resultPromise reject:[FIRInstallationsErrorUtil corruptedIIDTokenData]]; + return resultPromise; + } + + [resultPromise fulfill:IIDTokenInfo.token]; + + return resultPromise; +} + +- (FBLPromise *)IIDDefaultTokenData { + FBLPromise *resultPromise = [FBLPromise pendingPromise]; + + NSMutableDictionary *keychainQuery = [self IIDDefaultTokenDataKeychainQuery]; + NSError *error; + NSData *data = [FIRInstallationsKeychainUtils getItemWithQuery:keychainQuery error:&error]; + + if (data) { + [resultPromise fulfill:data]; + return resultPromise; + } else { + NSError *outError = error ?: [FIRInstallationsErrorUtil corruptedIIDTokenData]; + [resultPromise reject:outError]; + return resultPromise; + } +} + +- (NSMutableDictionary *)IIDDefaultTokenDataKeychainQuery { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + finalQuery[(__bridge NSString *)kSecAttrGeneric] = kFIRInstallationsIIDTokenKeychainId; + + NSString *account = [self IIDAppIdentifier]; + if ([account length]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + + finalQuery[(__bridge NSString *)kSecAttrService] = + [self serviceKeyForAuthorizedEntity:self.GCMSenderID scope:@"*"]; + return finalQuery; +} + +- (NSString *)IIDAppIdentifier { + return [[NSBundle mainBundle] bundleIdentifier] ?: @""; +} + +- (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h new file mode 100644 index 0000000..b45475d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstallationsUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstallationsHeartbeatKey; + +/** + * The class is responsible for interacting with HTTP REST API for Installations. + */ +@interface FIRInstallationsAPIService : NSObject + +/** + * The default initializer. + * @param APIKey The Firebase project API key (see `FIROptions.APIKey`). + * @param projectID The Firebase project ID (see `FIROptions.projectID`). + */ +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID; + +/** + * Sends a request to register a new FID to get auth and refresh tokens. + * @param installation The `FIRInstallationsItem` instance with the FID to register. + * @return A promise that is resolved with a new `FIRInstallationsItem` instance with valid tokens. + * It is rejected with an error in case of a failure. + */ +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation; + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation; + +/** + * Sends a request to delete the installation, related auth tokens and all related data from the + * server. + * @param installation The installation to delete. + * @return Returns a promise that is resolved with the passed installation on successful deletion or + * is rejected with an error otherwise. + */ +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m new file mode 100644 index 0000000..5bd7e3b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m @@ -0,0 +1,346 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsAPIService.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import +#import +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem+RegisterInstallationAPI.h" +#import "FIRInstallationsLogger.h" + +NSString *const kFIRInstallationsAPIBaseURL = @"https://firebaseinstallations.googleapis.com"; +NSString *const kFIRInstallationsAPIKey = @"X-Goog-Api-Key"; +NSString *const kFIRInstallationsBundleId = @"X-Ios-Bundle-Identifier"; +NSString *const kFIRInstallationsIIDMigrationAuthHeader = @"x-goog-fis-ios-iid-migration-auth"; +NSString *const kFIRInstallationsHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstallationsHeartbeatTag = @"fire-installations"; +NSString *const kFIRInstallationsUserAgentKey = @"X-firebase-client"; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsURLSessionResponse : NSObject +@property(nonatomic) NSHTTPURLResponse *HTTPResponse; +@property(nonatomic) NSData *data; + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data; +@end + +@implementation FIRInstallationsURLSessionResponse + +- (instancetype)initWithResponse:(NSHTTPURLResponse *)response data:(nullable NSData *)data { + self = [super init]; + if (self) { + _HTTPResponse = response; + _data = data ?: [NSData data]; + } + return self; +} + +@end + +@interface FIRInstallationsAPIService () +@property(nonatomic, readonly) NSURLSession *URLSession; +@property(nonatomic, readonly) NSString *APIKey; +@property(nonatomic, readonly) NSString *projectID; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstallationsAPIService + +- (instancetype)initWithAPIKey:(NSString *)APIKey projectID:(NSString *)projectID { + NSURLSession *URLSession = [NSURLSession + sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + return [self initWithURLSession:URLSession APIKey:APIKey projectID:projectID]; +} + +/// The initializer for tests. +- (instancetype)initWithURLSession:(NSURLSession *)URLSession + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID { + self = [super init]; + if (self) { + _URLSession = URLSession; + _APIKey = [APIKey copy]; + _projectID = [projectID copy]; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise *)registerInstallation:(FIRInstallationsItem *)installation { + NSURLRequest *request = [self registerRequestWithInstallation:installation]; + return [self sendURLRequest:request].then( + ^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self registeredInstallationWithInstallation:installation serverResponse:response]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + NSURLRequest *request = [self authTokenRequestWithInstallation:installation]; + return [self sendURLRequest:request] + .then(^FBLPromise *( + FIRInstallationsURLSessionResponse *response) { + return [self authTokenWithServerResponse:response]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsStoredAuthToken *authToken) { + FIRInstallationsItem *updatedInstallation = [installation copy]; + updatedInstallation.authToken = authToken; + return updatedInstallation; + }); +} + +- (FBLPromise *)deleteInstallation:(FIRInstallationsItem *)installation { + NSURLRequest *request = [self deleteInstallationRequestWithInstallation:installation]; + return [[self sendURLRequest:request] + then:^id _Nullable(FIRInstallationsURLSessionResponse *_Nullable value) { + // Return the original installation on success. + return installation; + }]; +} + +#pragma mark - Register Installation + +- (NSURLRequest *)registerRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/", + kFIRInstallationsAPIBaseURL, self.projectID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{ + @"fid" : installation.firebaseInstallationID, + @"authVersion" : @"FIS_v2", + @"appId" : installation.appID, + @"sdkVersion" : [self SDKVersion] + }; + + NSDictionary *headers; + if (installation.IIDDefaultToken) { + headers = @{kFIRInstallationsIIDMigrationAuthHeader : installation.IIDDefaultToken}; + } + + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:nil + additionalHeaders:headers]; +} + +- (FBLPromise *) + registeredInstallationWithInstallation:(FIRInstallationsItem *)installation + serverResponse:(FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsItem *registeredInstallation = + [installation registeredInstallationWithJSONData:response.data + date:[NSDate date] + error:&error]; + if (registeredInstallation == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationFailed, + @"Failed to parse FIRInstallationsItem: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingInstallationSucceed, + @"FIRInstallationsItem parsed successfully."); + return registeredInstallation; + }]; +} + +#pragma mark - Auth token + +- (NSURLRequest *)authTokenRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = + [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/authTokens:generate", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + NSDictionary *bodyDict = @{@"installation" : @{@"sdkVersion" : [self SDKVersion]}}; + return [self requestWithURL:URL + HTTPMethod:@"POST" + bodyDict:bodyDict + refreshToken:installation.refreshToken]; +} + +- (FBLPromise *)authTokenWithServerResponse: + (FIRInstallationsURLSessionResponse *)response { + return [FBLPromise do:^id { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeParsingAPIResponse, + @"Parsing server response for %@.", response.HTTPResponse.URL); + NSError *error; + FIRInstallationsStoredAuthToken *token = + [FIRInstallationsItem authTokenWithGenerateTokenAPIJSONData:response.data + date:[NSDate date] + error:&error]; + if (token == nil) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenFailed, + @"Failed to parse FIRInstallationsStoredAuthToken: %@.", error); + return error; + } + + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIResponseParsingAuthTokenSucceed, + @"FIRInstallationsStoredAuthToken parsed successfully."); + return token; + }]; +} + +#pragma mark - Delete Installation + +- (NSURLRequest *)deleteInstallationRequestWithInstallation:(FIRInstallationsItem *)installation { + NSString *URLString = [NSString stringWithFormat:@"%@/v1/projects/%@/installations/%@/", + kFIRInstallationsAPIBaseURL, self.projectID, + installation.firebaseInstallationID]; + NSURL *URL = [NSURL URLWithString:URLString]; + + return [self requestWithURL:URL + HTTPMethod:@"DELETE" + bodyDict:@{} + refreshToken:installation.refreshToken]; +} + +#pragma mark - URL Request +- (NSURLRequest *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken { + return [self requestWithURL:requestURL + HTTPMethod:HTTPMethod + bodyDict:bodyDict + refreshToken:refreshToken + additionalHeaders:nil]; +} + +- (NSURLRequest *)requestWithURL:(NSURL *)requestURL + HTTPMethod:(NSString *)HTTPMethod + bodyDict:(NSDictionary *)bodyDict + refreshToken:(nullable NSString *)refreshToken + additionalHeaders: + (nullable NSDictionary *)additionalHeaders { + __block NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL]; + request.HTTPMethod = HTTPMethod; + NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; + [request addValue:self.APIKey forHTTPHeaderField:kFIRInstallationsAPIKey]; + [request addValue:bundleIdentifier forHTTPHeaderField:kFIRInstallationsBundleId]; + [self setJSONHTTPBody:bodyDict forRequest:request]; + if (refreshToken) { + NSString *authHeader = [NSString stringWithFormat:@"FIS_v2 %@", refreshToken]; + [request setValue:authHeader forHTTPHeaderField:@"Authorization"]; + } + // User agent Header. + [request setValue:[FIRApp firebaseUserAgent] forHTTPHeaderField:kFIRInstallationsUserAgentKey]; + // Heartbeat Header. + [request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstallationsHeartbeatTag]) + .stringValue + forHTTPHeaderField:kFIRInstallationsHeartbeatKey]; + [additionalHeaders enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull key, NSString *_Nonnull obj, BOOL *_Nonnull stop) { + [request setValue:obj forHTTPHeaderField:key]; + }]; + + return [request copy]; +} + +- (FBLPromise *)URLRequestPromise:(NSURLRequest *)request { + return [[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeSendAPIRequest, + @"Sending request: %@, body:%@, headers: %@.", request, + [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding], + request.allHTTPHeaderFields); + [[self.URLSession + dataTaskWithRequest:request + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + if (error) { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAPIRequestNetworkError, + @"Request failed: %@, error: %@.", request, error); + reject(error); + } else { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeAPIRequestResponse, + @"Request response received: %@, error: %@, body: %@.", request, error, + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); + fulfill([[FIRInstallationsURLSessionResponse alloc] + initWithResponse:(NSHTTPURLResponse *)response + data:data]); + } + }] resume]; + }] then:^id _Nullable(FIRInstallationsURLSessionResponse *response) { + return [self validateHTTPResponseStatusCode:response]; + }]; +} + +- (FBLPromise *)validateHTTPResponseStatusCode: + (FIRInstallationsURLSessionResponse *)response { + NSInteger statusCode = response.HTTPResponse.statusCode; + return [FBLPromise do:^id _Nullable { + if (statusCode < 200 || statusCode >= 300) { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeUnexpectedAPIRequestResponse, + @"Unexpected API response: %@, body: %@.", response.HTTPResponse, + [[NSString alloc] initWithData:response.data encoding:NSUTF8StringEncoding]); + return [FIRInstallationsErrorUtil APIErrorWithHTTPResponse:response.HTTPResponse + data:response.data]; + } + return response; + }]; +} + +- (FBLPromise *)sendURLRequest:(NSURLRequest *)request { + return [FBLPromise attempts:1 + delay:1 + condition:^BOOL(NSInteger remainingAttempts, NSError *_Nonnull error) { + return [FIRInstallationsErrorUtil isAPIError:error withHTTPCode:500]; + } + retry:^id _Nullable { + return [self URLRequestPromise:request]; + }]; +} + +- (NSString *)SDKVersion { + return [NSString stringWithFormat:@"i:%s", FIRInstallationsVersionStr]; +} + +#pragma mark - JSON + +- (void)setJSONHTTPBody:(NSDictionary *)body + forRequest:(NSMutableURLRequest *)request { + [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + + NSError *error; + NSData *JSONData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error]; + if (JSONData == nil) { + // TODO: Log or return an error. + } + request.HTTPBody = JSONData; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h new file mode 100644 index 0000000..cc6b543 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem.h" + +@class FIRInstallationsStoredAuthToken; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstallationsItem (RegisterInstallationAPI) + +/** + * Parses and validates the Register Installation API response and returns a corresponding + * `FIRInstallationsItem` instance on success. + * @param JSONData The data with JSON encoded API response. + * @param date The Auth Token expiration date will be calculated as `date` + + * `response.authToken.expiresIn`. For most of the cases `[NSDate date]` should be passed there. A + * different value may be passed e.g. for unit tests. + * @param outError A pointer to assign a specific `NSError` instance in case of failure. No error is + * assigned in case of success. + * @return Returns a new `FIRInstallationsItem` instance in the success case or `nil` otherwise. + */ +- (nullable FIRInstallationsItem *)registeredInstallationWithJSONData:(NSData *)JSONData + date:(NSDate *)date + error: + (NSError *_Nullable *)outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError; + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m new file mode 100644 index 0000000..569e35b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m @@ -0,0 +1,142 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsItem+RegisterInstallationAPI.h" + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsStoredAuthToken.h" + +@implementation FIRInstallationsItem (RegisterInstallationAPI) + +- (nullable FIRInstallationsItem *) + registeredInstallationWithJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError *__autoreleasing _Nullable *_Nullable)outError { + NSDictionary *responseJSON = [FIRInstallationsItem dictionaryFromJSONData:data error:outError]; + if (!responseJSON) { + return nil; + } + + NSString *refreshToken = [FIRInstallationsItem validStringOrNilForKey:@"refreshToken" + fromDict:responseJSON]; + if (refreshToken == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"refreshToken"], + outError); + return nil; + } + + NSDictionary *authTokenDict = responseJSON[@"authToken"]; + if (![authTokenDict isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken"], + outError); + return nil; + } + + FIRInstallationsStoredAuthToken *authToken = + [FIRInstallationsItem authTokenWithJSONDict:authTokenDict date:date error:outError]; + if (authToken == nil) { + return nil; + } + + FIRInstallationsItem *installation = + [[FIRInstallationsItem alloc] initWithAppID:self.appID firebaseAppName:self.firebaseAppName]; + NSString *installationID = [FIRInstallationsItem validStringOrNilForKey:@"fid" + fromDict:responseJSON]; + installation.firebaseInstallationID = installationID ?: self.firebaseInstallationID; + installation.refreshToken = refreshToken; + installation.authToken = authToken; + installation.registrationStatus = FIRInstallationStatusRegistered; + + return installation; +} + +#pragma mark - Auth token + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithGenerateTokenAPIJSONData:(NSData *)data + date:(NSDate *)date + error:(NSError **) + outError { + NSDictionary *dict = [self dictionaryFromJSONData:data error:outError]; + if (!dict) { + return nil; + } + + return [self authTokenWithJSONDict:dict date:date error:outError]; +} + ++ (nullable FIRInstallationsStoredAuthToken *)authTokenWithJSONDict: + (NSDictionary *)dict + date:(NSDate *)date + error:(NSError **)outError { + NSString *token = [self validStringOrNilForKey:@"token" fromDict:dict]; + if (token == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil FIDRegistrationErrorWithResponseMissingField:@"authToken.token"], + outError); + return nil; + } + + NSString *expiresInString = [self validStringOrNilForKey:@"expiresIn" fromDict:dict]; + if (expiresInString == nil) { + FIRInstallationsItemSetErrorToPointer( + [FIRInstallationsErrorUtil + FIDRegistrationErrorWithResponseMissingField:@"authToken.expiresIn"], + outError); + return nil; + } + + // The response should contain the string in format like "604800s". + // The server should never response with anything else except seconds. + // Just drop the last character and parse a number from string. + NSString *expiresInSeconds = [expiresInString substringToIndex:expiresInString.length - 1]; + NSTimeInterval expiresIn = [expiresInSeconds doubleValue]; + NSDate *expirationDate = [date dateByAddingTimeInterval:expiresIn]; + + FIRInstallationsStoredAuthToken *authToken = [[FIRInstallationsStoredAuthToken alloc] init]; + authToken.status = FIRInstallationsAuthTokenStatusTokenReceived; + authToken.token = token; + authToken.expirationDate = expirationDate; + + return authToken; +} + +#pragma mark - JSON + ++ (nullable NSDictionary *)dictionaryFromJSONData:(NSData *)data + error:(NSError **)outError { + NSError *error; + NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + + if (![responseJSON isKindOfClass:[NSDictionary class]]) { + FIRInstallationsItemSetErrorToPointer([FIRInstallationsErrorUtil JSONSerializationError:error], + outError); + return nil; + } + + return responseJSON; +} + ++ (NSString *)validStringOrNilForKey:(NSString *)key fromDict:(NSDictionary *)dict { + NSString *string = dict[key]; + if ([string isKindOfClass:[NSString class]] && string.length > 0) { + return string; + } + return nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h new file mode 100644 index 0000000..ab2092d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBLPromise; +@class FIRInstallationsItem; + +/** + * The class is responsible for managing FID for a given `FIRApp`. + */ +@interface FIRInstallationsIDController : NSObject + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(nullable NSString *)accessGroup; + +- (FBLPromise *)getInstallationItem; + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh; + +- (FBLPromise *)deleteInstallation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m new file mode 100644 index 0000000..1982a57 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m @@ -0,0 +1,458 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsIDController.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import + +#import "FIRInstallationsAPIService.h" +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsIIDStore.h" +#import "FIRInstallationsIIDTokenStore.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsSingleOperationPromiseCache.h" +#import "FIRInstallationsStore.h" +#import "FIRSecureStorage.h" + +#import "FIRInstallationsHTTPError.h" +#import "FIRInstallationsStoredAuthToken.h" + +const NSNotificationName FIRInstallationIDDidChangeNotification = + @"FIRInstallationIDDidChangeNotification"; +NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey = + @"FIRInstallationIDDidChangeNotification"; + +NSTimeInterval const kFIRInstallationsTokenExpirationThreshold = 60 * 60; // 1 hour. + +@interface FIRInstallationsIDController () +@property(nonatomic, readonly) NSString *appID; +@property(nonatomic, readonly) NSString *appName; + +@property(nonatomic, readonly) FIRInstallationsStore *installationsStore; +@property(nonatomic, readonly) FIRInstallationsIIDStore *IIDStore; +@property(nonatomic, readonly) FIRInstallationsIIDTokenStore *IIDTokenStore; + +@property(nonatomic, readonly) FIRInstallationsAPIService *APIService; + +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *getInstallationPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *authTokenPromiseCache; +@property(nonatomic, readonly) FIRInstallationsSingleOperationPromiseCache + *authTokenForcingRefreshPromiseCache; +@property(nonatomic, readonly) + FIRInstallationsSingleOperationPromiseCache *deleteInstallationPromiseCache; +@end + +@implementation FIRInstallationsIDController + +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + APIKey:(NSString *)APIKey + projectID:(NSString *)projectID + GCMSenderID:(NSString *)GCMSenderID + accessGroup:(NSString *)accessGroup { + FIRSecureStorage *secureStorage = [[FIRSecureStorage alloc] init]; + FIRInstallationsStore *installationsStore = + [[FIRInstallationsStore alloc] initWithSecureStorage:secureStorage accessGroup:accessGroup]; + + // Use `GCMSenderID` as project identifier when `projectID` is not available. + NSString *APIServiceProjectID = (projectID.length > 0) ? projectID : GCMSenderID; + FIRInstallationsAPIService *apiService = + [[FIRInstallationsAPIService alloc] initWithAPIKey:APIKey projectID:APIServiceProjectID]; + + FIRInstallationsIIDStore *IIDStore = [[FIRInstallationsIIDStore alloc] init]; + FIRInstallationsIIDTokenStore *IIDCheckingStore = + [[FIRInstallationsIIDTokenStore alloc] initWithGCMSenderID:GCMSenderID]; + + return [self initWithGoogleAppID:appID + appName:appName + installationsStore:installationsStore + APIService:apiService + IIDStore:IIDStore + IIDTokenStore:IIDCheckingStore]; +} + +/// The initializer is supposed to be used by tests to inject `installationsStore`. +- (instancetype)initWithGoogleAppID:(NSString *)appID + appName:(NSString *)appName + installationsStore:(FIRInstallationsStore *)installationsStore + APIService:(FIRInstallationsAPIService *)APIService + IIDStore:(FIRInstallationsIIDStore *)IIDStore + IIDTokenStore:(FIRInstallationsIIDTokenStore *)IIDTokenStore { + self = [super init]; + if (self) { + _appID = appID; + _appName = appName; + _installationsStore = installationsStore; + _APIService = APIService; + _IIDStore = IIDStore; + _IIDTokenStore = IIDTokenStore; + + __weak FIRInstallationsIDController *weakSelf = self; + + _getInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createGetInstallationItemPromise]; + }]; + + _authTokenPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:NO]; + }]; + + _authTokenForcingRefreshPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf installationWithValidAuthTokenForcingRefresh:YES]; + }]; + + _deleteInstallationPromiseCache = [[FIRInstallationsSingleOperationPromiseCache alloc] + initWithNewOperationHandler:^FBLPromise *_Nonnull { + FIRInstallationsIDController *strongSelf = weakSelf; + return [strongSelf createDeleteInstallationPromise]; + }]; + } + return self; +} + +#pragma mark - Get Installation. + +- (FBLPromise *)getInstallationItem { + return [self.getInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createGetInstallationItemPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewGetInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + FBLPromise *installationItemPromise = + [self getStoredInstallation].recover(^id(NSError *error) { + return [self createAndSaveFID]; + }); + + // Initiate registration process on success if needed, but return the installation without waiting + // for it. + installationItemPromise.then(^id(FIRInstallationsItem *installation) { + [self getAuthTokenForcingRefresh:NO]; + return nil; + }); + + return installationItemPromise; +} + +- (FBLPromise *)getStoredInstallation { + return [self.installationsStore installationForAppID:self.appID appName:self.appName].validate( + ^BOOL(FIRInstallationsItem *installation) { + BOOL isValid = NO; + switch (installation.registrationStatus) { + case FIRInstallationStatusUnregistered: + case FIRInstallationStatusRegistered: + isValid = YES; + break; + + case FIRInstallationStatusUnknown: + isValid = NO; + break; + } + + return isValid; + }); +} + +- (FBLPromise *)createAndSaveFID { + return [self migrateOrGenerateInstallation] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self saveInstallation:installation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *installation) { + [self postFIDDidChangeNotification]; + return installation; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installation { + return [self.installationsStore saveInstallation:installation].then( + ^FIRInstallationsItem *(NSNull *result) { + return installation; + }); +} + +/** + * Tries to migrate IID data stored by FirebaseInstanceID SDK or generates a new Installation ID if + * not found. + */ +- (FBLPromise *)migrateOrGenerateInstallation { + if (![self isDefaultApp]) { + // Existing IID should be used only for default FirebaseApp. + FIRInstallationsItem *installation = + [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + return [FBLPromise resolvedWith:installation]; + } + + return [[[FBLPromise + all:@[ [self.IIDStore existingIID], [self.IIDTokenStore existingIIDDefaultToken] ]] + then:^id _Nullable(NSArray *_Nullable results) { + NSString *existingIID = results[0]; + NSString *IIDDefaultToken = results[1]; + + return [self createInstallationWithFID:existingIID IIDDefaultToken:IIDDefaultToken]; + }] recover:^id _Nullable(NSError *_Nonnull error) { + return [self createInstallationWithFID:[FIRInstallationsItem generateFID] IIDDefaultToken:nil]; + }]; +} + +- (FIRInstallationsItem *)createInstallationWithFID:(NSString *)FID + IIDDefaultToken:(nullable NSString *)IIDDefaultToken { + FIRInstallationsItem *installation = [[FIRInstallationsItem alloc] initWithAppID:self.appID + firebaseAppName:self.appName]; + installation.firebaseInstallationID = FID; + installation.IIDDefaultToken = IIDDefaultToken; + installation.registrationStatus = FIRInstallationStatusUnregistered; + return installation; +} + +#pragma mark - FID registration + +- (FBLPromise *)registerInstallationIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusRegistered: + // Already registered. Do nothing. + return [FBLPromise resolvedWith:installation]; + + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // Registration required. Proceed. + break; + } + + return [self.APIService registerInstallation:installation] + .catch(^(NSError *_Nonnull error) { + if ([self doesRegistrationErrorRequireConfigChange:error]) { + FIRLogError(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInvalidFirebaseConfiguration, + @"Firebase Installation registration failed for app with name: %@, error: " + @"%@\nPlease make sure you use valid GoogleService-Info.plist", + self.appName, error); + } + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + return [self saveInstallation:registeredInstallation]; + }) + .then(^FIRInstallationsItem *(FIRInstallationsItem *registeredInstallation) { + // Server may respond with a different FID if the sent one cannot be accepted. + if (![registeredInstallation.firebaseInstallationID + isEqualToString:installation.firebaseInstallationID]) { + [self postFIDDidChangeNotification]; + } + return registeredInstallation; + }); +} + +- (BOOL)doesRegistrationErrorRequireConfigChange:(NSError *)error { + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + if (![HTTPError isKindOfClass:[FIRInstallationsHTTPError class]]) { + return NO; + } + + switch (HTTPError.HTTPResponse.statusCode) { + // These are the errors that require Firebase configuration change. + case FIRInstallationsRegistrationHTTPCodeInvalidArgument: + case FIRInstallationsRegistrationHTTPCodeInvalidAPIKey: + case FIRInstallationsRegistrationHTTPCodeAPIKeyToProjectIDMismatch: + case FIRInstallationsRegistrationHTTPCodeProjectNotFound: + return YES; + + default: + return NO; + } +} + +#pragma mark - Auth Token + +- (FBLPromise *)getAuthTokenForcingRefresh:(BOOL)forceRefresh { + if (forceRefresh || [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] != nil) { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingOrCreateNewPromise]; + } else { + return [self.authTokenPromiseCache getExistingPendingOrCreateNewPromise]; + } +} + +- (FBLPromise *)installationWithValidAuthTokenForcingRefresh: + (BOOL)forceRefresh { + FIRLogDebug(kFIRLoggerInstallations, kFIRInstallationsMessageCodeNewGetAuthTokenOperationCreated, + @"-[FIRInstallationsIDController installationWithValidAuthTokenForcingRefresh:%@], " + @"appName: %@", + @(forceRefresh), self.appName); + + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self registerInstallationIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *registeredInstallation) { + BOOL isTokenExpiredOrExpiresSoon = + [registeredInstallation.authToken.expirationDate timeIntervalSinceDate:[NSDate date]] < + kFIRInstallationsTokenExpirationThreshold; + if (forceRefresh || isTokenExpiredOrExpiresSoon) { + return [self refreshAuthTokenForInstallation:registeredInstallation]; + } else { + return registeredInstallation; + } + }) + .recover(^id(NSError *error) { + return [self regenerateFIDOnRefreshTokenErrorIfNeeded:error]; + }); +} + +- (FBLPromise *)refreshAuthTokenForInstallation: + (FIRInstallationsItem *)installation { + return [[self.APIService refreshAuthTokenForInstallation:installation] + then:^id _Nullable(FIRInstallationsItem *_Nullable refreshedInstallation) { + return [self saveInstallation:refreshedInstallation]; + }]; +} + +- (id)regenerateFIDOnRefreshTokenErrorIfNeeded:(NSError *)error { + if (![error isKindOfClass:[FIRInstallationsHTTPError class]]) { + // No recovery possible. Return the same error. + return error; + } + + FIRInstallationsHTTPError *HTTPError = (FIRInstallationsHTTPError *)error; + switch (HTTPError.HTTPResponse.statusCode) { + case FIRInstallationsAuthTokenHTTPCodeInvalidAuthentication: + case FIRInstallationsAuthTokenHTTPCodeFIDNotFound: + // The stored installation was damaged or blocked by the server. + // Delete the stored installation then generate and register a new one. + return [self getInstallationItem] + .then(^FBLPromise *(FIRInstallationsItem *installation) { + return [self deleteInstallationLocally:installation]; + }) + .then(^FBLPromise *(id result) { + return [self installationWithValidAuthTokenForcingRefresh:NO]; + }); + + default: + // No recovery possible. Return the same error. + return error; + } +} + +#pragma mark - Delete FID + +- (FBLPromise *)deleteInstallation { + return [self.deleteInstallationPromiseCache getExistingPendingOrCreateNewPromise]; +} + +- (FBLPromise *)createDeleteInstallationPromise { + FIRLogDebug(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeNewDeleteInstallationOperationCreated, @"%s, appName: %@", + __PRETTY_FUNCTION__, self.appName); + + // Check for ongoing requests first, if there is no a request, then check local storage for + // existing installation. + FBLPromise *currentInstallationPromise = + [self mostRecentInstallationOperation] ?: [self getStoredInstallation]; + + return currentInstallationPromise + .then(^id(FIRInstallationsItem *installation) { + return [self sendDeleteInstallationRequestIfNeeded:installation]; + }) + .then(^id(FIRInstallationsItem *installation) { + // Remove the installation from the local storage. + return [self deleteInstallationLocally:installation]; + }); +} + +- (FBLPromise *)deleteInstallationLocally:(FIRInstallationsItem *)installation { + return [self.installationsStore removeInstallationForAppID:installation.appID + appName:installation.firebaseAppName] + .then(^FBLPromise *(NSNull *result) { + return [self deleteExistingIIDIfNeeded]; + }) + .then(^NSNull *(NSNull *result) { + [self postFIDDidChangeNotification]; + return result; + }); +} + +- (FBLPromise *)sendDeleteInstallationRequestIfNeeded: + (FIRInstallationsItem *)installation { + switch (installation.registrationStatus) { + case FIRInstallationStatusUnknown: + case FIRInstallationStatusUnregistered: + // The installation is not registered, so it is safe to be deleted as is, so return early. + return [FBLPromise resolvedWith:installation]; + break; + + case FIRInstallationStatusRegistered: + // Proceed to de-register the installation on the server. + break; + } + + return [self.APIService deleteInstallation:installation].recover(^id(NSError *APIError) { + if ([FIRInstallationsErrorUtil isAPIError:APIError withHTTPCode:404]) { + // The installation was not found on the server. + // Return success. + return installation; + } else { + // Re-throw the error otherwise. + return APIError; + } + }); +} + +- (FBLPromise *)deleteExistingIIDIfNeeded { + if ([self isDefaultApp]) { + return [self.IIDStore deleteExistingIID]; + } else { + return [FBLPromise resolvedWith:[NSNull null]]; + } +} + +- (nullable FBLPromise *)mostRecentInstallationOperation { + return [self.authTokenForcingRefreshPromiseCache getExistingPendingPromise] + ?: [self.authTokenPromiseCache getExistingPendingPromise] + ?: [self.getInstallationPromiseCache getExistingPendingPromise]; +} + +#pragma mark - Notifications + +- (void)postFIDDidChangeNotification { + [[NSNotificationCenter defaultCenter] + postNotificationName:FIRInstallationIDDidChangeNotification + object:nil + userInfo:@{kFIRInstallationIDDidChangeNotificationAppNameKey : self.appName}]; +} + +#pragma mark - Default App + +- (BOOL)isDefaultApp { + return [self.appName isEqualToString:kFIRDefaultAppName]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h new file mode 100644 index 0000000..aeb54e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class makes sure the a single operation (represented by a promise) is performed at a time. If + * there is an ongoing operation, then its existing corresponding promise will be returned instead + * of starting a new operation. + */ +@interface FIRInstallationsSingleOperationPromiseCache<__covariant ResultType> : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The designated initializer. + * @param newOperationHandler The block that must return a new promise representing the + * single-at-a-time operation. The promise should be fulfilled when the operation is completed. The + * factory block will be used to create a new promise when needed. + */ +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler NS_DESIGNATED_INITIALIZER; + +/** + * Creates a new promise or returns an existing pending one. + * @return Returns and existing pending promise if exists. If the pending promise does not exist + * then a new one will be created using the `factory` block passed in the initializer. Once the + * pending promise gets resolved, it is removed, so calling the method again will lead to creating + * and caching another promise. + */ +- (FBLPromise *)getExistingPendingOrCreateNewPromise; + +/** + * Returns an existing pending promise or `nil`. + * @return Returns an existing pending promise if there is one or `nil` otherwise. + */ +- (nullable FBLPromise *)getExistingPendingPromise; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m new file mode 100644 index 0000000..dfccfe3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsSingleOperationPromiseCache.h" + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +@interface FIRInstallationsSingleOperationPromiseCache () +@property(nonatomic, readonly) FBLPromise *_Nonnull (^newOperationHandler)(void); +@property(nonatomic, nullable) FBLPromise *pendingPromise; +@end + +@implementation FIRInstallationsSingleOperationPromiseCache + +- (instancetype)initWithNewOperationHandler: + (FBLPromise *_Nonnull (^)(void))newOperationHandler { + if (newOperationHandler == nil) { + [NSException raise:NSInvalidArgumentException + format:@"`newOperationHandler` must not be `nil`."]; + } + + self = [super init]; + if (self) { + _newOperationHandler = [newOperationHandler copy]; + } + return self; +} + +- (FBLPromise *)getExistingPendingOrCreateNewPromise { + @synchronized(self) { + if (!self.pendingPromise) { + self.pendingPromise = self.newOperationHandler(); + + self.pendingPromise + .then(^id(id result) { + @synchronized(self) { + self.pendingPromise = nil; + return nil; + } + }) + .catch(^void(NSError *error) { + @synchronized(self) { + self.pendingPromise = nil; + } + }); + } + + return self.pendingPromise; + } +} + +- (nullable FBLPromise *)getExistingPendingPromise { + @synchronized(self) { + return self.pendingPromise; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h new file mode 100644 index 0000000..3edc692 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The enum represent possible states of the installation ID. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredItem`. Modification + * of it can lead to incompatibility with previous version. Any modification must be evaluated and, + * if it is really needed, the `storageVersion` must be bumped and proper migration code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsStatus) { + /** Represents either an initial status when a FIRInstallationsItem instance was created but not + * stored to Keychain or an undefined status (e.g. when the status failed to deserialize). + */ + FIRInstallationStatusUnknown, + /// The Firebase Installation has not yet been registered with FIS. + FIRInstallationStatusUnregistered, + /// The Firebase Installation has successfully been registered with FIS. + FIRInstallationStatusRegistered, +}; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h new file mode 100644 index 0000000..5334cc9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; +@class FIRInstallationsItem; +@class FIRSecureStorage; + +NS_ASSUME_NONNULL_BEGIN + +/// The user defaults suite name used to store data. +extern NSString *const kFIRInstallationsStoreUserDefaultsID; + +/// The class is responsible for storing and accessing the installations data. +@interface FIRInstallationsStore : NSObject + +/** + * The default initializer. + * @param storage The secure storage to save installations data. + * @param accessGroup The Keychain Access Group to store and request the installations data. + */ +- (instancetype)initWithSecureStorage:(FIRSecureStorage *)storage + accessGroup:(nullable NSString *)accessGroup; + +/** + * Retrieves existing installation ID if there is. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a `FBLPromise` instance. The promise is resolved with a FIRInstallationsItem + * instance if there is a valid installation stored for `appID` and `appName`. The promise is + * rejected with a specific error when the installation has not been found or with another possible + * error. + */ +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName; + +/** + * Saves the given installation. + * + * @param installationItem The installation data. + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem; + +/** + * Removes installation data for the given app parameters. + * @param appID The Firebase(Google) Application ID. + * @param appName The Firebase Application Name. + * + * @return Returns a promise that is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m new file mode 100644 index 0000000..9fcfd74 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m @@ -0,0 +1,125 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStore.h" + +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsItem.h" +#import "FIRInstallationsStoredItem.h" +#import "FIRSecureStorage.h" + +NSString *const kFIRInstallationsStoreUserDefaultsID = @"com.firebase.FIRInstallations"; + +@interface FIRInstallationsStore () +@property(nonatomic, readonly) FIRSecureStorage *secureStorage; +@property(nonatomic, readonly, nullable) NSString *accessGroup; +@property(nonatomic, readonly) dispatch_queue_t queue; +@property(nonatomic, readonly) GULUserDefaults *userDefaults; +@end + +@implementation FIRInstallationsStore + +- (instancetype)initWithSecureStorage:(FIRSecureStorage *)storage + accessGroup:(NSString *)accessGroup { + self = [super init]; + if (self) { + _secureStorage = storage; + _accessGroup = [accessGroup copy]; + _queue = dispatch_queue_create("com.firebase.FIRInstallationsStore", DISPATCH_QUEUE_SERIAL); + + NSString *userDefaultsSuiteName = _accessGroup ?: kFIRInstallationsStoreUserDefaultsID; + _userDefaults = [[GULUserDefaults alloc] initWithSuiteName:userDefaultsSuiteName]; + } + return self; +} + +- (FBLPromise *)installationForAppID:(NSString *)appID + appName:(NSString *)appName { + NSString *itemID = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self installationExistsForAppID:appID appName:appName] + .then(^id(id result) { + return [self.secureStorage getObjectForKey:itemID + objectClass:[FIRInstallationsStoredItem class] + accessGroup:self.accessGroup]; + }) + .then(^id(FIRInstallationsStoredItem *_Nullable storedItem) { + if (storedItem == nil) { + return [FIRInstallationsErrorUtil installationItemNotFoundForAppID:appID appName:appName]; + } + + FIRInstallationsItem *item = [[FIRInstallationsItem alloc] initWithAppID:appID + firebaseAppName:appName]; + [item updateWithStoredItem:storedItem]; + return item; + }); +} + +- (FBLPromise *)saveInstallation:(FIRInstallationsItem *)installationItem { + FIRInstallationsStoredItem *storedItem = [installationItem storedItem]; + NSString *identifier = [installationItem identifier]; + + return + [self.secureStorage setObject:storedItem forKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:YES forItemWithIdentifier:identifier]; + }); +} + +- (FBLPromise *)removeInstallationForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [self.secureStorage removeObjectForKey:identifier accessGroup:self.accessGroup].then( + ^id(id result) { + return [self setInstallationExists:NO forItemWithIdentifier:identifier]; + }); +} + +#pragma mark - User defaults + +- (FBLPromise *)installationExistsForAppID:(NSString *)appID appName:(NSString *)appName { + NSString *identifier = [FIRInstallationsItem identifierWithAppID:appID appName:appName]; + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + return [[self userDefaults] objectForKey:identifier] != nil + ? [NSNull null] + : [FIRInstallationsErrorUtil + installationItemNotFoundForAppID:appID + appName:appName]; + }]; +} + +- (FBLPromise *)setInstallationExists:(BOOL)exists + forItemWithIdentifier:(NSString *)identifier { + return [FBLPromise onQueue:self.queue + do:^id _Nullable { + if (exists) { + [[self userDefaults] setBool:YES forKey:identifier]; + } else { + [[self userDefaults] removeObjectForKey:identifier]; + } + + return [NSNull null]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h new file mode 100644 index 0000000..f6e4282 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The enum represent possible states of the installation auth token. + * + * WARNING: The enum is stored to Keychain as a part of `FIRInstallationsStoredAuthToken`. + * Modification of it can lead to incompatibility with previous version. Any modification must be + * evaluated and, if it is really needed, the `storageVersion` must be bumped and proper migration + * code added. + */ +typedef NS_ENUM(NSInteger, FIRInstallationsAuthTokenStatus) { + /// An initial status or an undefined value. + FIRInstallationsAuthTokenStatusUnknown, + /// The auth token has been received from the server. + FIRInstallationsAuthTokenStatusTokenReceived +}; + +/** + * This class serializes and deserializes the installation data into/from `NSData` to be stored in + * Keychain. This class is primarily used by `FIRInstallationsStore`. It is also used on the logic + * level as a data object (see `FIRInstallationsItem.authToken`). + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredAuthToken : NSObject +@property FIRInstallationsAuthTokenStatus status; + +/// The token that can be used to authorize requests to Firebase backend. +@property(nullable, copy) NSString *token; +/// The date when the auth token expires. +@property(nullable, copy) NSDate *expirationDate; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m new file mode 100644 index 0000000..b21f6dd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredAuthToken.h" + +#import "FIRInstallationsLogger.h" + +NSString *const kFIRInstallationsStoredAuthTokenStatusKey = @"status"; +NSString *const kFIRInstallationsStoredAuthTokenTokenKey = @"token"; +NSString *const kFIRInstallationsStoredAuthTokenExpirationDateKey = @"expirationDate"; +NSString *const kFIRInstallationsStoredAuthTokenStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredAuthTokenStorageVersion = 1; + +@implementation FIRInstallationsStoredAuthToken + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredAuthTokenStorageVersion; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + FIRInstallationsStoredAuthToken *clone = [[FIRInstallationsStoredAuthToken alloc] init]; + clone.status = self.status; + clone.token = [self.token copy]; + clone.expirationDate = self.expirationDate; + return clone; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeInteger:self.status forKey:kFIRInstallationsStoredAuthTokenStatusKey]; + [aCoder encodeObject:self.token forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + [aCoder encodeObject:self.expirationDate + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + [aCoder encodeInteger:self.storageVersion + forKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStorageVersionKey]; + if (storageVersion > kFIRInstallationsStoredAuthTokenStorageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeAuthTokenCoderVersionMismatch, + @"FIRInstallationsStoredAuthToken was encoded by a newer coder version %ld. " + @"Current coder version is %ld. Some auth token data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredAuthTokenStorageVersion); + } + + FIRInstallationsStoredAuthToken *object = [[FIRInstallationsStoredAuthToken alloc] init]; + object.status = [aDecoder decodeIntegerForKey:kFIRInstallationsStoredAuthTokenStatusKey]; + object.token = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredAuthTokenTokenKey]; + object.expirationDate = + [aDecoder decodeObjectOfClass:[NSDate class] + forKey:kFIRInstallationsStoredAuthTokenExpirationDateKey]; + + return object; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h new file mode 100644 index 0000000..4926588 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h @@ -0,0 +1,51 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstallationsStatus.h" + +@class FIRInstallationsStoredAuthToken; +@class FIRInstallationsStoredIIDCheckin; + +NS_ASSUME_NONNULL_BEGIN + +/** + * The class is supposed to be used by `FIRInstallationsStore` only. It is required to + * serialize/deserialize the installation data into/from `NSData` to be stored in Keychain. + * + * WARNING: Modification of the class properties can lead to incompatibility with the stored data + * encoded by the previous class versions. Any modification must be evaluated and, if it is really + * needed, the `storageVersion` must be bumped and proper migration code added. + */ +@interface FIRInstallationsStoredItem : NSObject + +/// A stable identifier that uniquely identifies the app instance. +@property(nonatomic, copy, nullable) NSString *firebaseInstallationID; +/// The `refreshToken` is used to authorize the auth token requests. +@property(nonatomic, copy, nullable) NSString *refreshToken; + +@property(nonatomic, nullable) FIRInstallationsStoredAuthToken *authToken; +@property(nonatomic) FIRInstallationsStatus registrationStatus; + +/// Instance ID default auth token imported from IID store as a part of IID migration. +@property(nonatomic, nullable) NSString *IIDDefaultToken; + +/// The version of local storage. +@property(nonatomic, readonly) NSInteger storageVersion; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m new file mode 100644 index 0000000..0c7655c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsStoredItem.h" + +#import "FIRInstallationsLogger.h" +#import "FIRInstallationsStoredAuthToken.h" + +NSString *const kFIRInstallationsStoredItemFirebaseInstallationIDKey = @"firebaseInstallationID"; +NSString *const kFIRInstallationsStoredItemRefreshTokenKey = @"refreshToken"; +NSString *const kFIRInstallationsStoredItemAuthTokenKey = @"authToken"; +NSString *const kFIRInstallationsStoredItemRegistrationStatusKey = @"registrationStatus"; +NSString *const kFIRInstallationsStoredItemIIDDefaultTokenKey = @"IIDDefaultToken"; +NSString *const kFIRInstallationsStoredItemStorageVersionKey = @"storageVersion"; + +NSInteger const kFIRInstallationsStoredItemStorageVersion = 1; + +@implementation FIRInstallationsStoredItem + +- (NSInteger)storageVersion { + return kFIRInstallationsStoredItemStorageVersion; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:self.firebaseInstallationID + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + [aCoder encodeObject:self.refreshToken forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + [aCoder encodeObject:self.authToken forKey:kFIRInstallationsStoredItemAuthTokenKey]; + [aCoder encodeInteger:self.registrationStatus + forKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + [aCoder encodeObject:self.IIDDefaultToken forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + [aCoder encodeInteger:self.storageVersion forKey:kFIRInstallationsStoredItemStorageVersionKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + NSInteger storageVersion = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemStorageVersionKey]; + if (storageVersion > self.storageVersion) { + FIRLogWarning(kFIRLoggerInstallations, + kFIRInstallationsMessageCodeInstallationCoderVersionMismatch, + @"FIRInstallationsStoredItem was encoded by a newer coder version %ld. Current " + @"coder version is %ld. Some installation data may be lost.", + (long)storageVersion, (long)kFIRInstallationsStoredItemStorageVersion); + } + + FIRInstallationsStoredItem *item = [[FIRInstallationsStoredItem alloc] init]; + item.firebaseInstallationID = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemFirebaseInstallationIDKey]; + item.refreshToken = [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemRefreshTokenKey]; + item.authToken = [aDecoder decodeObjectOfClass:[FIRInstallationsStoredAuthToken class] + forKey:kFIRInstallationsStoredItemAuthTokenKey]; + item.registrationStatus = + [aDecoder decodeIntegerForKey:kFIRInstallationsStoredItemRegistrationStatusKey]; + item.IIDDefaultToken = + [aDecoder decodeObjectOfClass:[NSString class] + forKey:kFIRInstallationsStoredItemIIDDefaultTokenKey]; + + return item; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h new file mode 100644 index 0000000..4839b4e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallations.h @@ -0,0 +1,120 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRApp; +@class FIRInstallationsAuthTokenResult; + +NS_ASSUME_NONNULL_BEGIN + +/** A notification with this name is sent each time an installation is created or deleted. */ +FOUNDATION_EXPORT const NSNotificationName FIRInstallationIDDidChangeNotification; +/** `userInfo` key for the `FirebaseApp.name` in `FIRInstallationIDDidChangeNotification`. */ +FOUNDATION_EXPORT NSString *const kFIRInstallationIDDidChangeNotificationAppNameKey; + +/** + * An installation ID handler block. + * @param identifier The installation ID string if exists or `nil` otherwise. + * @param error The error when `identifier == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsIDHandler)(NSString *__nullable identifier, + NSError *__nullable error) + NS_SWIFT_NAME(InstallationsIDHandler); + +/** + * An authorization token handler block. + * @param tokenResult An instance of `InstallationsAuthTokenResult` in case of success or `nil` + * otherwise. + * @param error The error when `tokenResult == nil` or `nil` otherwise. + */ +typedef void (^FIRInstallationsTokenHandler)( + FIRInstallationsAuthTokenResult *__nullable tokenResult, NSError *__nullable error) + NS_SWIFT_NAME(InstallationsTokenHandler); + +/** + * The class provides API for Firebase Installations. + * Each configured `FirebaseApp` has a corresponding single instance of `Installations`. + * An instance of the class provides access to the installation info for the `FirebaseApp` as well + * as the ability to delete it. A Firebase Installation is unique by `FirebaseApp.name` and + * `FirebaseApp.options.googleAppID` . + */ +NS_SWIFT_NAME(Installations) +@interface FIRInstallations : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Returns a default instance of `Installations`. + * @returns An instance of `Installations` for `FirebaseApp.defaultApp(). + * @throw Throws an exception if the default app is not configured yet or required `FirebaseApp` + * options are missing. + */ ++ (FIRInstallations *)installations NS_SWIFT_NAME(installations()); + +/** + * Returns an instance of `Installations` for an application. + * @param application A configured `FirebaseApp` instance. + * @returns An instance of `Installations` corresponding to the passed application. + * @throw Throws an exception if required `FirebaseApp` options are missing. + */ ++ (FIRInstallations *)installationsWithApp:(FIRApp *)application NS_SWIFT_NAME(installations(app:)); + +/** + * The method creates or retrieves an installation ID. The installation ID is a stable identifier + * that uniquely identifies the app instance. NOTE: If the application already has an existing + * FirebaseInstanceID then the InstanceID identifier will be used. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsIDHandler` for additional details. + */ +- (void)installationIDWithCompletion:(FIRInstallationsIDHandler)completion; + +/** + * Retrieves (locally if it exists or from the server) a valid authorization token. An existing + * token may be invalidated or expired, so it is recommended to fetch the auth token before each + * server request. The method does the same as `Installations.authTokenForcingRefresh(:, + * completion:)` with forcing refresh `NO`. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenWithCompletion:(FIRInstallationsTokenHandler)completion; + +/** + * Retrieves (locally or from the server depending on `forceRefresh` value) a valid authorization + * token. An existing token may be invalidated or expire, so it is recommended to fetch the auth + * token before each server request. This method should be used with `forceRefresh == YES` when e.g. + * a request with the previously fetched auth token failed with "Not Authorized" error. + * @param forceRefresh If `YES` then the locally cached auth token will be ignored and a new one + * will be requested from the server. If `NO`, then the locally cached auth token will be returned + * if exists and has not expired yet. + * @param completion A completion handler which is invoked when the operation completes. See + * `InstallationsTokenHandler` for additional details. + */ +- (void)authTokenForcingRefresh:(BOOL)forceRefresh + completion:(FIRInstallationsTokenHandler)completion; + +/** + * Deletes all the installation data including the unique identifier, auth tokens and + * all related data on the server side. A network connection is required for the method to + * succeed. If fails, the existing installation data remains untouched. + * @param completion A completion handler which is invoked when the operation completes. `error == + * nil` indicates success. + */ +- (void)deleteWithCompletion:(void (^)(NSError *__nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h new file mode 100644 index 0000000..7753132 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class represents a result of the auth token request. */ +NS_SWIFT_NAME(InstallationsAuthTokenResult) +@interface FIRInstallationsAuthTokenResult : NSObject + +/** The authorization token string. */ +@property(nonatomic, readonly) NSString *authToken; + +/** The auth token expiration date. */ +@property(nonatomic, readonly) NSDate *expirationDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h new file mode 100644 index 0000000..d0c3b99 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *const kFirebaseInstallationsErrorDomain; + +typedef NS_ENUM(NSUInteger, FIRInstallationsErrorCode) { + /** Unknown error. See `userInfo` for details. */ + FIRInstallationsErrorCodeUnknown = 0, + + /** Keychain error. See `userInfo` for details. */ + FIRInstallationsErrorCodeKeychain = 1, + + /** Server unreachable. A network error or server is unavailable. See `userInfo` for details. */ + FIRInstallationsErrorCodeServerUnreachable = 2, + + /** FirebaseApp configuration issues e.g. invalid GMP-App-ID, etc. See `userInfo` for details. */ + FIRInstallationsErrorCodeInvalidConfiguration = 3, + +} NS_SWIFT_NAME(InstallationsErrorCode); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h new file mode 100644 index 0000000..8cdf677 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h @@ -0,0 +1,19 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT const char *const FIRInstallationsVersionStr; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h new file mode 100644 index 0000000..accc9ac --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h @@ -0,0 +1,20 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h new file mode 100644 index 0000000..4d73ec0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Helper functions to access Keychain. +@interface FIRInstallationsKeychainUtils : NSObject + ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError; + ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m new file mode 100644 index 0000000..51da86a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m @@ -0,0 +1,107 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstallationsKeychainUtils.h" + +#import "FIRInstallationsErrorUtil.h" + +@implementation FIRInstallationsKeychainUtils + ++ (nullable NSData *)getItemWithQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSMutableDictionary *mutableQuery = [query mutableCopy]; + + mutableQuery[(__bridge id)kSecReturnData] = @YES; + mutableQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFDataRef result = NULL; + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)mutableQuery, (CFTypeRef *)&result); + + if (status == errSecSuccess && result != NULL) { + if (outError) { + *outError = nil; + } + + return (__bridge_transfer NSData *)result; + } + + if (status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + } else { + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemCopyMatching" + status:status]; + } + } + return nil; +} + ++ (BOOL)setItem:(NSData *)item + withQuery:(NSDictionary *)query + error:(NSError *_Nullable *_Nullable)outError { + NSData *existingItem = [self getItemWithQuery:query error:outError]; + if (outError && *outError) { + return NO; + } + + NSMutableDictionary *mutableQuery = [query mutableCopy]; + mutableQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + + OSStatus status; + if (!existingItem) { + mutableQuery[(__bridge id)kSecValueData] = item; + status = SecItemAdd((__bridge CFDictionaryRef)mutableQuery, NULL); + } else { + NSDictionary *attributes = @{(__bridge id)kSecValueData : item}; + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes); + } + + if (status == noErr) { + if (outError) { + *outError = nil; + } + return YES; + } + + NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd"; + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:function status:status]; + } + return NO; +} + ++ (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + + if (status == noErr || status == errSecItemNotFound) { + if (outError) { + *outError = nil; + } + return YES; + } + + if (outError) { + *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete" + status:status]; + } + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h new file mode 100644 index 0000000..5548e3e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h @@ -0,0 +1,71 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FBLPromise; + +NS_ASSUME_NONNULL_BEGIN + +/// The class provides a convenient abstraction on top of the iOS Keychain API to save data. +@interface FIRSecureStorage : NSObject + +/** + * Get an object by key. + * @param key The key. + * @param objectClass The expected object class required by `NSSecureCoding`. + * @param accessGroup The Keychain Access Group. + * + * @return Returns a promise. It is resolved with an object stored by key if exists. It is resolved + * with `nil` when the object not found. It fails on a Keychain error. + */ +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup; + +/** + * Saves the given object by the given key. + * @param object The object to store. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +/** + * Removes the object by the given key. + * @param key The key to store the object. If there is an existing object by the key, it will be + * overridden. + * @param accessGroup The Keychain Access Group. + * + * @return Returns which is resolved with `[NSNull null]` on success. + */ +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup; + +#if TARGET_OS_OSX +/// If not `nil`, then only this keychain will be used to save and read data (see +/// `kSecMatchSearchList` and `kSecUseKeychain`. It is mostly intended to be used by unit tests. +@property(nonatomic, nullable) SecKeychainRef keychainRef; +#endif // TARGET_OSX + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m new file mode 100644 index 0000000..543e848 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m @@ -0,0 +1,255 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRSecureStorage.h" +#import + +#if __has_include() +#import +#else +#import "FBLPromises.h" +#endif + +#import "FIRInstallationsErrorUtil.h" +#import "FIRInstallationsKeychainUtils.h" + +@interface FIRSecureStorage () +@property(nonatomic, readonly) dispatch_queue_t keychainQueue; +@property(nonatomic, readonly) dispatch_queue_t inMemoryCacheQueue; +@property(nonatomic, readonly) NSString *service; +@property(nonatomic, readonly) NSCache> *inMemoryCache; +@end + +@implementation FIRSecureStorage + +- (instancetype)init { + NSCache *cache = [[NSCache alloc] init]; + // Cache up to 5 installations. + cache.countLimit = 5; + return [self initWithService:@"com.firebase.FIRInstallations.installations" cache:cache]; +} + +- (instancetype)initWithService:(NSString *)service cache:(NSCache *)cache { + self = [super init]; + if (self) { + _keychainQueue = dispatch_queue_create( + "com.firebase.FIRInstallations.FIRSecureStorage.Keychain", DISPATCH_QUEUE_SERIAL); + _inMemoryCacheQueue = dispatch_queue_create( + "com.firebase.FIRInstallations.FIRSecureStorage.InMemoryCache", DISPATCH_QUEUE_SERIAL); + _service = [service copy]; + _inMemoryCache = cache; + } + return self; +} + +#pragma mark - Public + +- (FBLPromise> *)getObjectForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Return cached object or fail otherwise. + id object = [self.inMemoryCache objectForKey:key]; + return object + ?: [[NSError alloc] + initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }] + .recover(^id _Nullable(NSError *error) { + // Look for the object in the keychain. + return [self getObjectFromKeychainForKey:key + objectClass:objectClass + accessGroup:accessGroup]; + }); +} + +- (FBLPromise *)setObject:(id)object + forKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + // Save to the in-memory cache first. + [self.inMemoryCache setObject:object forKey:[key copy]]; + return [NSNull null]; + }] + .thenOn(self.keychainQueue, ^id(id result) { + // Then store the object to the keychain. + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = [self archiveDataForObject:object error:&error]; + if (!encodedObject) { + return error; + } + + if (![FIRInstallationsKeychainUtils setItem:encodedObject withQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +- (FBLPromise *)removeObjectForKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + return [FBLPromise onQueue:self.inMemoryCacheQueue + do:^id _Nullable { + [self.inMemoryCache removeObjectForKey:key]; + return nil; + }] + .thenOn(self.keychainQueue, ^id(id result) { + NSDictionary *query = [self keychainQueryWithKey:key accessGroup:accessGroup]; + + NSError *error; + if (![FIRInstallationsKeychainUtils removeItemWithQuery:query error:&error]) { + return error; + } + + return [NSNull null]; + }); +} + +#pragma mark - Private + +- (FBLPromise> *)getObjectFromKeychainForKey:(NSString *)key + objectClass:(Class)objectClass + accessGroup:(nullable NSString *)accessGroup { + // Look for the object in the keychain. + return [FBLPromise onQueue:self.keychainQueue + do:^id { + NSDictionary *query = [self keychainQueryWithKey:key + accessGroup:accessGroup]; + NSError *error; + NSData *encodedObject = + [FIRInstallationsKeychainUtils getItemWithQuery:query error:&error]; + + if (error) { + return error; + } + if (!encodedObject) { + return nil; + } + id object = [self unarchivedObjectOfClass:objectClass + fromData:encodedObject + error:&error]; + if (error) { + return error; + } + + return object; + }] + .thenOn(self.inMemoryCacheQueue, + ^id _Nullable(id _Nullable object) { + // Save object to the in-memory cache if exists and return the object. + if (object) { + [self.inMemoryCache setObject:object forKey:[key copy]]; + } + return object; + }); +} + +- (void)resetInMemoryCache { + [self.inMemoryCache removeAllObjects]; +} + +#pragma mark - Keychain + +- (NSMutableDictionary *)keychainQueryWithKey:(NSString *)key + accessGroup:(nullable NSString *)accessGroup { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + + query[(__bridge NSString *)kSecClass] = (__bridge NSString *)kSecClassGenericPassword; + query[(__bridge NSString *)kSecAttrService] = self.service; + query[(__bridge NSString *)kSecAttrAccount] = key; + + if (accessGroup) { + query[(__bridge NSString *)kSecAttrAccessGroup] = accessGroup; + } + +#if TARGET_OS_OSX + if (self.keychainRef) { + query[(__bridge NSString *)kSecUseKeychain] = (__bridge id)(self.keychainRef); + query[(__bridge NSString *)kSecMatchSearchList] = @[ (__bridge id)(self.keychainRef) ]; + } +#endif // TARGET_OSX + + return query; +} + +- (nullable NSData *)archiveDataForObject:(id)object error:(NSError **)outError { + NSData *archiveData; + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + archiveData = [NSKeyedArchiver archivedDataWithRootObject:object + requiringSecureCoding:YES + error:&error]; + if (error && outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithError:error]; + } + } else { + @try { + NSMutableData *data = [NSMutableData data]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + archiver.requiresSecureCoding = YES; + + [archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey]; + [archiver finishEncoding]; + + archiveData = [data copy]; + } @catch (NSException *exception) { + if (outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + } + + return archiveData; +} + +- (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError { + id object; + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + object = [NSKeyedUnarchiver unarchivedObjectOfClass:class fromData:data error:&error]; + if (error && outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithError:error]; + } + } else { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + unarchiver.requiresSecureCoding = YES; + + object = [unarchiver decodeObjectOfClass:class forKey:NSKeyedArchiveRootObjectKey]; + } @catch (NSException *exception) { + if (outError) { + *outError = [FIRInstallationsErrorUtil keyedArchiverErrorWithException:exception]; + } + } + } + + return object; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstallations/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h new file mode 100644 index 0000000..e3e36e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRIMessageCode.h @@ -0,0 +1,150 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// The format of the debug code will show in the log as: e.g. +// for code 1000, it will show as I-IID001000. +typedef NS_ENUM(NSInteger, FIRInstanceIDMessageCode) { + // DO NOT USE 2000, 2002. + kFIRInstanceIDMessageCodeFIRApp000 = 1000, // I-IID001000 + kFIRInstanceIDMessageCodeFIRApp001 = 1001, + kFIRInstanceIDMessageCodeFIRApp002 = 1002, + kFIRInstanceIDMessageCodeInternal001 = 2001, + kFIRInstanceIDMessageCodeInternal002 = 2002, + // FIRInstanceID.m + // DO NOT USE 4000. + kFIRInstanceIDMessageCodeInstanceID000 = 3000, + kFIRInstanceIDMessageCodeInstanceID001 = 3001, + kFIRInstanceIDMessageCodeInstanceID002 = 3002, + kFIRInstanceIDMessageCodeInstanceID003 = 3003, + kFIRInstanceIDMessageCodeInstanceID004 = 3004, + kFIRInstanceIDMessageCodeInstanceID005 = 3005, + kFIRInstanceIDMessageCodeInstanceID006 = 3006, + kFIRInstanceIDMessageCodeInstanceID007 = 3007, + kFIRInstanceIDMessageCodeInstanceID008 = 3008, + kFIRInstanceIDMessageCodeInstanceID009 = 3009, + kFIRInstanceIDMessageCodeInstanceID010 = 3010, + kFIRInstanceIDMessageCodeInstanceID011 = 3011, + kFIRInstanceIDMessageCodeInstanceID012 = 3012, + kFIRInstanceIDMessageCodeInstanceID013 = 3013, + kFIRInstanceIDMessageCodeInstanceID014 = 3014, + kFIRInstanceIDMessageCodeInstanceID015 = 3015, + kFIRInstanceIDMessageCodeRefetchingTokenForAPNS = 3016, + kFIRInstanceIDMessageCodeInstanceID017 = 3017, + kFIRInstanceIDMessageCodeInstanceID018 = 3018, + // FIRInstanceIDAuthService.m + kFIRInstanceIDMessageCodeAuthService000 = 5000, + kFIRInstanceIDMessageCodeAuthService001 = 5001, + kFIRInstanceIDMessageCodeAuthService002 = 5002, + kFIRInstanceIDMessageCodeAuthService003 = 5003, + kFIRInstanceIDMessageCodeAuthService004 = 5004, + kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress = 5004, + + // FIRInstanceIDBackupExcludedPlist.m + // Do NOT USE 6003 + kFIRInstanceIDMessageCodeBackupExcludedPlist000 = 6000, + kFIRInstanceIDMessageCodeBackupExcludedPlist001 = 6001, + kFIRInstanceIDMessageCodeBackupExcludedPlist002 = 6002, + // FIRInstanceIDCheckinService.m + kFIRInstanceIDMessageCodeService000 = 7000, + kFIRInstanceIDMessageCodeService001 = 7001, + kFIRInstanceIDMessageCodeService002 = 7002, + kFIRInstanceIDMessageCodeService003 = 7003, + kFIRInstanceIDMessageCodeService004 = 7004, + kFIRInstanceIDMessageCodeService005 = 7005, + kFIRInstanceIDMessageCodeService006 = 7006, + kFIRInstanceIDInvalidNetworkSession = 7007, + kFIRInstanceIDInvalidSettingResponse = 7008, + // FIRInstanceIDCheckinStore.m + // DO NOT USE 8002, 8004 - 8008 + kFIRInstanceIDMessageCodeCheckinStore000 = 8000, + kFIRInstanceIDMessageCodeCheckinStore001 = 8001, + kFIRInstanceIDMessageCodeCheckinStore003 = 8003, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted = 8009, + kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved = 8010, + + // DO NOT USE 9000 - 9006 + + // DO NOT USE 10000 - 10009 + + // DO NOT USE 11000 - 11002 + + // DO NOT USE 12000 - 12014 + + // FIRInstanceIDStore.m + // DO NOT USE 13004, 13005, 13007, 13008, 13010, 13011, 13013, 13014 + kFIRInstanceIDMessageCodeStore000 = 13000, + kFIRInstanceIDMessageCodeStore001 = 13001, + kFIRInstanceIDMessageCodeStore002 = 13002, + kFIRInstanceIDMessageCodeStore003 = 13003, + kFIRInstanceIDMessageCodeStore006 = 13006, + kFIRInstanceIDMessageCodeStore009 = 13009, + kFIRInstanceIDMessageCodeStore012 = 13012, + // FIRInstanceIDTokenManager.m + // DO NOT USE 14002, 14005 + kFIRInstanceIDMessageCodeTokenManager000 = 14000, + kFIRInstanceIDMessageCodeTokenManager001 = 14001, + kFIRInstanceIDMessageCodeTokenManager003 = 14003, + kFIRInstanceIDMessageCodeTokenManager004 = 14004, + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset = 14006, + kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset = 14007, + kFIRInstanceIDMessageCodeTokenManagerSavedAppVersion = 14008, + kFIRInstanceIDMessageCodeTokenManagerErrorInvalidatingAllTokens = 14009, + kFIRInstanceIDMessageCodeTokenManagerAPNSChanged = 14010, + kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated = 14011, + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken = 14012, + // FIRInstanceIDTokenStore.m + // DO NOT USE 15002 - 15013 + kFIRInstanceIDMessageCodeTokenStore000 = 15000, + kFIRInstanceIDMessageCodeTokenStore001 = 15001, + kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo = 15015, + + // DO NOT USE 16000, 18004 + + // FIRInstanceIDUtilities.m + kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier = 18000, + kFIRInstanceIDMessageCodeUtilitiesAppEnvironmentUtilNotAvailable = 18001, + kFIRInstanceIDMessageCodeUtilitiesCannotGetHardwareModel = 18002, + kFIRInstanceIDMessageCodeUtilitiesCannotGetSystemVersion = 18003, + // FIRInstanceIDTokenOperation.m + kFIRInstanceIDMessageCodeTokenOperationFailedToSignParams = 19000, + // FIRInstanceIDTokenFetchOperation.m + // DO NOT USE 20004, 20005 + kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest = 20000, + kFIRInstanceIDMessageCodeTokenFetchOperationRequestError = 20001, + kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse = 20002, + kFIRInstanceIDMessageCodeTokenFetchOperationBadTokenStructure = 20003, + // FIRInstanceIDTokenDeleteOperation.m + kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest = 21000, + kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError = 21001, + kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse = 21002, + // FIRInstanceIDTokenInfo.m + kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo = 22000, + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged = 22001, + kFIRInstanceIDMessageCodeTokenInfoLocaleChanged = 22002, + // FIRInstanceIDKeychain.m + kFIRInstanceIDKeychainReadItemError = 23000, + kFIRInstanceIDKeychainAddItemError = 23001, + kFIRInstanceIDKeychainDeleteItemError = 23002, + kFIRInstanceIDKeychainCreateKeyPairError = 23003, + kFIRInstanceIDKeychainUpdateItemError = 23004, + + // FIRInstanceIDStringEncoding.m + kFIRInstanceIDStringEncodingBufferUnderflow = 24000, + kFIRInstanceIDStringEncodingBufferOverflow = 24001, + +}; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m new file mode 100644 index 0000000..c5ffe7a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID+Private.m @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID+Private.h" + +#import + +#import +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDTokenManager.h" + +@class FIRInstallations; + +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) FIRInstanceIDTokenManager *tokenManager; + +@end + +@implementation FIRInstanceID (Private) + +// This method just wraps our pre-configured auth service to make the request. +// This method is only needed by first-party users, like Remote Config. +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler { + [self.tokenManager.authService fetchCheckinInfoWithHandler:handler]; +} + +// TODO(#4486): Delete the method, `self.firebaseInstallationsID` and related +// code for Firebase 7 release. +- (NSString *)appInstanceID:(NSError **)outError { + return self.firebaseInstallationsID; +} + +#pragma mark - Firebase Installations Compatibility + +/// Presence of this method indicates that this version of IID uses FirebaseInstallations under the +/// hood. It is checked by FirebaseInstallations SDK. ++ (BOOL)usesFIS { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m new file mode 100644 index 0000000..f9cba4f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceID.m @@ -0,0 +1,1130 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +#import + +#import +#import +#import +#import +#import +#import +#import +#import "FIRInstanceID+Private.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCombinedHandler.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenManager.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +// Public constants +NSString *const kFIRInstanceIDScopeFirebaseMessaging = @"fcm"; + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +const NSNotificationName kFIRInstanceIDTokenRefreshNotification = + @"com.firebase.iid.notif.refresh-token"; +#else +NSString *const kFIRInstanceIDTokenRefreshNotification = @"com.firebase.iid.notif.refresh-token"; +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +NSString *const kFIRInstanceIDInvalidNilHandlerError = @"Invalid nil handler."; + +// Private constants +int64_t const kMaxRetryIntervalForDefaultTokenInSeconds = 20 * 60; // 20 minutes +int64_t const kMinRetryIntervalForDefaultTokenInSeconds = 10; // 10 seconds +// we retry only a max 5 times. +// TODO(chliangGoogle): If we still fail we should listen for the network change notification +// since GCM would have started Reachability. We only start retrying after we see a configuration +// change. +NSInteger const kMaxRetryCountForDefaultToken = 5; + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH +static NSString *const kEntitlementsAPSEnvironmentKey = @"Entitlements.aps-environment"; +#else +static NSString *const kEntitlementsAPSEnvironmentKey = + @"Entitlements.com.apple.developer.aps-environment"; +#endif +static NSString *const kAPSEnvironmentDevelopmentValue = @"development"; +/// FIRMessaging selector that returns the current FIRMessaging auto init +/// enabled flag. +static NSString *const kFIRInstanceIDFCMSelectorAutoInitEnabled = + @"isAutoInitEnabledWithUserDefaults:"; + +static NSString *const kFIRInstanceIDAPNSTokenType = @"APNSTokenType"; +static NSString *const kFIRIIDAppReadyToConfigureSDKNotification = + @"FIRAppReadyToConfigureSDKNotification"; +static NSString *const kFIRIIDAppNameKey = @"FIRAppNameKey"; +static NSString *const kFIRIIDErrorDomain = @"com.firebase.instanceid"; +static NSString *const kFIRIIDServiceInstanceID = @"InstanceID"; + +/** + * The APNS token type for the app. If the token type is set to `UNKNOWN` + * InstanceID will implicitly try to figure out what the actual token type + * is from the provisioning profile. + * This must match FIRMessagingAPNSTokenType in FIRMessaging.h + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDAPNSTokenType) { + /// Unknown token type. + FIRInstanceIDAPNSTokenTypeUnknown, + /// Sandbox token type. + FIRInstanceIDAPNSTokenTypeSandbox, + /// Production token type. + FIRInstanceIDAPNSTokenTypeProd, +} NS_SWIFT_NAME(InstanceIDAPNSTokenType); + +@interface FIRInstanceIDResult () +@property(nonatomic, readwrite, copy) NSString *instanceID; +@property(nonatomic, readwrite, copy) NSString *token; +@end + +@interface FIRInstanceID () + +// FIRApp configuration objects. +@property(nonatomic, readwrite, copy) NSString *fcmSenderID; +@property(nonatomic, readwrite, copy) NSString *firebaseAppID; + +// Raw APNS token data +@property(nonatomic, readwrite, strong) NSData *apnsTokenData; + +@property(nonatomic, readwrite) FIRInstanceIDAPNSTokenType apnsTokenType; +// String-based, internal representation of APNS token +@property(nonatomic, readwrite, copy) NSString *APNSTupleString; +// Token fetched from the server automatically for the default app. +@property(nonatomic, readwrite, copy) NSString *defaultFCMToken; + +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenManager *tokenManager; +@property(nonatomic, readwrite, strong) FIRInstallations *installations; + +// backoff and retry for default token +@property(nonatomic, readwrite, assign) NSInteger retryCountForDefaultToken; +@property(atomic, strong, nullable) + FIRInstanceIDCombinedHandler *defaultTokenFetchHandler; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, copy, nullable) NSString *firebaseInstallationsID; + +@end + +// InstanceID doesn't provide any functionality to other components, +// so it provides a private, empty protocol that it conforms to and use it for registration. + +@protocol FIRInstanceIDInstanceProvider +@end + +@interface FIRInstanceID () +@end + +@implementation FIRInstanceIDResult +- (id)copyWithZone:(NSZone *)zone { + FIRInstanceIDResult *result = [[[self class] allocWithZone:zone] init]; + result.instanceID = self.instanceID; + result.token = self.token; + return result; +} +@end + +@implementation FIRInstanceID + +// File static to support InstanceID tests that call [FIRInstanceID instanceID] after +// [FIRInstanceID instanceIDForTests]. +static FIRInstanceID *gInstanceID; + ++ (instancetype)instanceID { + // If the static instance was created, return it. This should only be set in tests and we should + // eventually use proper dependency injection for a better test structure. + if (gInstanceID != nil) { + return gInstanceID; + } + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + FIRInstanceID *instanceID = + (FIRInstanceID *)FIR_COMPONENT(FIRInstanceIDInstanceProvider, defaultApp.container); + return instanceID; +} + +- (instancetype)initPrivately { + self = [super init]; + if (self != nil) { + // Use automatic detection of sandbox, unless otherwise set by developer + _apnsTokenType = FIRInstanceIDAPNSTokenTypeUnknown; + } + return self; +} + ++ (FIRInstanceID *)instanceIDForTests { + gInstanceID = [[FIRInstanceID alloc] initPrivately]; + [gInstanceID start]; + return gInstanceID; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark - Tokens + +- (NSString *)token { + if (!self.fcmSenderID.length) { + return nil; + } + + NSString *cachedToken = [self cachedTokenIfAvailable]; + + if (cachedToken) { + return cachedToken; + } else { + // If we've never had a cached default token, we should fetch one because unrelatedly, + // this request will help us determine whether the locally-generated Instance ID keypair is not + // unique, and therefore generate a new one. + [self defaultTokenWithHandler:nil]; + return nil; + } +} + +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler { + FIRInstanceID_WEAKIFY(self); + [self getIDWithHandler:^(NSString *identity, NSError *error) { + FIRInstanceID_STRONGIFY(self); + // This is in main queue already + if (error) { + if (handler) { + handler(nil, error); + } + return; + } + FIRInstanceIDResult *result = [[FIRInstanceIDResult alloc] init]; + result.instanceID = identity; + NSString *cachedToken = [self cachedTokenIfAvailable]; + if (cachedToken) { + if (handler) { + result.token = cachedToken; + handler(result, nil); + } + // If no handler, simply return since client has generated iid and token. + return; + } + [self defaultTokenWithHandler:^(NSString *_Nullable token, NSError *_Nullable error) { + if (handler) { + if (error) { + handler(nil, error); + return; + } + result.token = token; + handler(result, nil); + } + }]; + }]; +} + +- (NSString *)cachedTokenIfAvailable { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope]; + return cachedTokenInfo.token; +} + +- (void)setDefaultFCMToken:(NSString *)defaultFCMToken { + if (_defaultFCMToken && defaultFCMToken && [defaultFCMToken isEqualToString:_defaultFCMToken]) { + return; + } + + _defaultFCMToken = defaultFCMToken; + + // Sending this notification out will ensure that FIRMessaging has the updated + // default FCM token. + NSNotification *internalDefaultTokenNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenNotification + object:_defaultFCMToken]; + [[NSNotificationQueue defaultQueue] enqueueNotification:internalDefaultTokenNotification + postingStyle:NSPostASAP]; +} + +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID000, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + // Add internal options + NSMutableDictionary *tokenOptions = [NSMutableDictionary dictionary]; + if (options.count) { + [tokenOptions addEntriesFromDictionary:options]; + } + + NSString *APNSKey = kFIRInstanceIDTokenOptionsAPNSKey; + NSString *serverTypeKey = kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + if (tokenOptions[APNSKey] != nil && tokenOptions[serverTypeKey] == nil) { + // APNS key was given, but server type is missing. Supply the server type with automatic + // checking. This can happen when the token is requested from FCM, which does not include a + // server type during its request. + tokenOptions[serverTypeKey] = @([self isSandboxApp]); + } + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + if (FIRInstanceIDIsValidGCMScope(scope) && !tokenOptions[APNSKey]) { + errorCode = kFIRInstanceIDErrorCodeMissingAPNSToken; + } else if (FIRInstanceIDIsValidGCMScope(scope) && + ![tokenOptions[APNSKey] isKindOfClass:[NSData class]]) { + errorCode = kFIRInstanceIDErrorCodeInvalidRequest; + } else if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDTokenHandler newHandler = ^(NSString *token, NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(token, error); + }); + }; + + if (errorCode != noError) { + newHandler(nil, [NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, + NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(nil, error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(nil, newError); + + } else { + FIRInstanceIDTokenInfo *cachedTokenInfo = + [self.tokenManager cachedTokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; + if (cachedTokenInfo) { + FIRInstanceIDAPNSInfo *optionsAPNSInfo = + [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:tokenOptions]; + // Check if APNS Info is changed + if ((!cachedTokenInfo.APNSInfo && !optionsAPNSInfo) || + [cachedTokenInfo.APNSInfo isEqualToAPNSInfo:optionsAPNSInfo]) { + // check if token is fresh + if ([cachedTokenInfo isFreshWithIID:identifier]) { + newHandler(cachedTokenInfo.token, nil); + return; + } + } + } + [self.tokenManager fetchNewTokenWithAuthorizedEntity:[authorizedEntity copy] + scope:[scope copy] + instanceID:identifier + options:tokenOptions + handler:newHandler]; + } + }]; + }]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID001, + kFIRInstanceIDInvalidNilHandlerError); + } + + // comparing enums to ints directly throws a warning + FIRInstanceIDErrorCode noError = INT_MAX; + FIRInstanceIDErrorCode errorCode = noError; + + if (![authorizedEntity length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidAuthorizedEntity; + } else if (![scope length]) { + errorCode = kFIRInstanceIDErrorCodeInvalidScope; + } else if (!self.installations) { + errorCode = kFIRInstanceIDErrorCodeInvalidStart; + } + + FIRInstanceIDDeleteTokenHandler newHandler = ^(NSError *error) { + // If a default token is deleted successfully, reset the defaultFCMToken too. + if (!error && [authorizedEntity isEqualToString:self.fcmSenderID] && + [scope isEqualToString:kFIRInstanceIDDefaultTokenScope]) { + self.defaultFCMToken = nil; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (errorCode != noError) { + newHandler([NSError errorWithFIRInstanceIDErrorCode:errorCode]); + return; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDAuthService *authService = self.tokenManager.authService; + [authService + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + newHandler(error); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations installationIDWithCompletion:^(NSString *_Nullable identifier, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + newHandler(newError); + + } else { + [self.tokenManager deleteTokenWithAuthorizedEntity:authorizedEntity + scope:scope + instanceID:identifier + handler:newHandler]; + } + }]; + }]; +} + +#pragma mark - Identity + +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID003, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + // When getID is explicitly called, trigger getToken to make sure token always exists. + // This is to avoid ID conflict (ID is not checked for conflict until we generate a token) + if (identifier) { + [self token]; + } + handler(identifier, error); + }]; +} + +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler { + if (!handler) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID004, + kFIRInstanceIDInvalidNilHandlerError); + return; + } + + void (^callHandlerOnMainThread)(NSError *) = ^(NSError *error) { + if ([NSThread isMainThread]) { + handler(error); + return; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }; + + if (!self.installations) { + FIRInstanceIDErrorCode error = kFIRInstanceIDErrorCodeInvalidStart; + callHandlerOnMainThread([NSError errorWithFIRInstanceIDErrorCode:error]); + return; + } + + FIRInstanceID_WEAKIFY(self); + void (^deleteTokensHandler)(NSError *) = ^void(NSError *error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + callHandlerOnMainThread(error); + return; + } + [self deleteIdentityWithHandler:^(NSError *error) { + callHandlerOnMainThread(error); + }]; + }; + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + NSError *newError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPair]; + callHandlerOnMainThread(newError); + } else { + [self.tokenManager deleteAllTokensWithInstanceID:identifier handler:deleteTokensHandler]; + } + }]; +} + +- (void)notifyIdentityReset { + [self deleteIdentityWithHandler:nil]; +} + +// Delete all the local cache checkin, IID and token. +- (void)deleteIdentityWithHandler:(FIRInstanceIDDeleteHandler)handler { + // Delete tokens. + [self.tokenManager deleteAllTokensLocallyWithHandler:^(NSError *deleteTokenError) { + // Reset FCM token. + self.defaultFCMToken = nil; + if (deleteTokenError) { + if (handler) { + handler(deleteTokenError); + } + return; + } + + // Delete Instance ID. + [self.installations deleteWithCompletion:^(NSError *_Nullable error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + + [self.tokenManager.authService resetCheckinWithHandler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + // Only request new token if FCM auto initialization is + // enabled. + if ([self isFCMAutoInitEnabled]) { + // Deletion succeeds! Requesting new checkin, IID and token. + // TODO(chliangGoogle) see if dispatch_after is necessary + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self defaultTokenWithHandler:nil]; + }); + } + if (handler) { + handler(nil); + } + }]; + }]; + }]; +} + +#pragma mark - Checkin + +- (BOOL)tryToLoadValidCheckinInfo { + FIRInstanceIDCheckinPreferences *checkinPreferences = + [self.tokenManager.authService checkinPreferences]; + return [checkinPreferences hasValidCheckinInfo]; +} + +- (NSString *)deviceAuthID { + return [self.tokenManager.authService checkinPreferences].deviceID; +} + +- (NSString *)secretToken { + return [self.tokenManager.authService checkinPreferences].secretToken; +} + +- (NSString *)versionInfo { + return [self.tokenManager.authService checkinPreferences].versionInfo; +} + +#pragma mark - Config + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-iid" + withVersion:FIRInstanceIDCurrentLibraryVersion()]; +} + ++ (nonnull NSArray *)componentsToRegister { + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + // InstanceID only works with the default app. + if (!container.app.isDefaultApp) { + // Only configure for the default FIRApp. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeFIRApp002, + @"Firebase Instance ID only works with the default app."); + return nil; + } + + // Ensure it's cached so it returns the same instance every time instanceID is called. + *isCacheable = YES; + FIRInstanceID *instanceID = [[FIRInstanceID alloc] initPrivately]; + [instanceID start]; + [instanceID configureInstanceIDWithOptions:container.app.options]; + return instanceID; + }; + FIRComponent *instanceIDProvider = + [FIRComponent componentWithProtocol:@protocol(FIRInstanceIDInstanceProvider) + instantiationTiming:FIRInstantiationTimingEagerInDefaultApp + dependencies:@[] + creationBlock:creationBlock]; + return @[ instanceIDProvider ]; +} + +- (void)configureInstanceIDWithOptions:(FIROptions *)options { + NSString *GCMSenderID = options.GCMSenderID; + if (!GCMSenderID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeFIRApp000, + @"Firebase not set up correctly, nil or empty senderID."); + [NSException raise:kFIRIIDErrorDomain + format:@"Could not configure Firebase InstanceID. GCMSenderID must not be nil or " + @"empty."]; + } + + self.fcmSenderID = GCMSenderID; + self.firebaseAppID = options.googleAppID; + + [self updateFirebaseInstallationID]; + + // FCM generates a FCM token during app start for sending push notification to device. + // This is not needed for app extension except for watch. +#if TARGET_OS_WATCH + [self didCompleteConfigure]; +#else + if (![GULAppEnvironmentUtil isAppExtension]) { + [self didCompleteConfigure]; + } +#endif +} + +// This is used to start any operations when we receive FirebaseSDK setup notification +// from FIRCore. +- (void)didCompleteConfigure { + NSString *cachedToken = [self cachedTokenIfAvailable]; + // When there is a cached token, do the token refresh. + if (cachedToken) { + // Clean up expired tokens by checking the token refresh policy. + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + if ([self.tokenManager checkTokenRefreshPolicyWithIID:identifier]) { + // Default token is expired, fetch default token from server. + [self defaultTokenWithHandler:nil]; + } + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + }]; + } else if ([self isFCMAutoInitEnabled]) { + // When there is no cached token, must check auto init is enabled. + // If it's disabled, don't initiate token generation/refresh. + // If no cache token and auto init is enabled, fetch a token from server. + [self defaultTokenWithHandler:nil]; + // Notify FCM with the default token. + self.defaultFCMToken = [self token]; + } + // ONLY checkin when auto data collection is turned on. + if ([self isFCMAutoInitEnabled]) { + [self.tokenManager.authService scheduleCheckin:YES]; + } +} + +- (BOOL)isFCMAutoInitEnabled { + Class messagingClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + // Firebase Messaging is not installed, auto init should be disabled since it's for FCM. + if (!messagingClass) { + return NO; + } + + // Messaging doesn't have the class method, auto init should be enabled since FCM exists. + SEL autoInitSelector = NSSelectorFromString(kFIRInstanceIDFCMSelectorAutoInitEnabled); + if (![messagingClass respondsToSelector:autoInitSelector]) { + return YES; + } + + // Get the autoInitEnabled class method. + IMP isAutoInitEnabledIMP = [messagingClass methodForSelector:autoInitSelector]; + BOOL(*isAutoInitEnabled) + (Class, SEL, GULUserDefaults *) = (BOOL(*)(id, SEL, GULUserDefaults *))isAutoInitEnabledIMP; + + // Check FCM's isAutoInitEnabled property. + return isAutoInitEnabled(messagingClass, autoInitSelector, + [GULUserDefaults standardUserDefaults]); +} + +// Actually makes InstanceID instantiate both the IID and Token-related subsystems. +- (void)start { + if (![FIRInstanceIDStore hasSubDirectory:kFIRInstanceIDSubDirectoryName]) { + [FIRInstanceIDStore createSubDirectory:kFIRInstanceIDSubDirectoryName]; + } + + [self setupTokenManager]; + self.installations = [FIRInstallations installations]; + [self setupNotificationListeners]; +} + +// Creates the token manager, which is used for fetching, caching, and retrieving tokens. +- (void)setupTokenManager { + self.tokenManager = [[FIRInstanceIDTokenManager alloc] init]; +} + +- (void)setupNotificationListeners { + // To prevent double notifications remove observer from all events during setup. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self]; + [center addObserver:self + selector:@selector(notifyIdentityReset) + name:kFIRInstanceIDIdentityInvalidatedNotification + object:nil]; + [center addObserver:self + selector:@selector(notifyAPNSTokenIsSet:) + name:kFIRInstanceIDAPNSTokenNotification + object:nil]; + [self observeFirebaseInstallationIDChanges]; +} + +#pragma mark - Private Helpers +/// Maximum retry count to fetch the default token. ++ (int64_t)maxRetryCountForDefaultToken { + return kMaxRetryCountForDefaultToken; +} + +/// Minimum interval in seconds between retries to fetch the default token. ++ (int64_t)minIntervalForDefaultTokenRetry { + return kMinRetryIntervalForDefaultTokenInSeconds; +} + +/// Maximum retry interval between retries to fetch default token. ++ (int64_t)maxRetryIntervalForDefaultTokenInSeconds { + return kMaxRetryIntervalForDefaultTokenInSeconds; +} + +- (NSInteger)retryIntervalToFetchDefaultToken { + if (self.retryCountForDefaultToken >= [[self class] maxRetryCountForDefaultToken]) { + return (NSInteger)[[self class] maxRetryIntervalForDefaultTokenInSeconds]; + } + // exponential backoff with a fixed initial retry time + // 11s, 22s, 44s, 88s ... + int64_t minInterval = [[self class] minIntervalForDefaultTokenRetry]; + return (NSInteger)MIN( + (1 << self.retryCountForDefaultToken) + minInterval * self.retryCountForDefaultToken, + kMaxRetryIntervalForDefaultTokenInSeconds); +} + +- (void)defaultTokenWithHandler:(nullable FIRInstanceIDTokenHandler)aHandler { + [self defaultTokenWithRetry:NO handler:aHandler]; +} + +/** + * @param retry Indicates if the method is called to perform a retry after a failed attempt. + * If `YES`, then actual token request will be performed even if `self.defaultTokenFetchHandler != + * nil` + */ +- (void)defaultTokenWithRetry:(BOOL)retry handler:(nullable FIRInstanceIDTokenHandler)aHandler { + BOOL shouldPerformRequest = retry || self.defaultTokenFetchHandler == nil; + + if (!self.defaultTokenFetchHandler) { + self.defaultTokenFetchHandler = [[FIRInstanceIDCombinedHandler alloc] init]; + } + + if (aHandler) { + [self.defaultTokenFetchHandler addHandler:aHandler]; + } + + if (!shouldPerformRequest) { + return; + } + + NSDictionary *instanceIDOptions = @{}; + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging && self.apnsTokenData) { + BOOL isSandboxApp = (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + instanceIDOptions = @{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp), + }; + } + + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenHandler newHandler = ^void(NSString *token, NSError *error) { + FIRInstanceID_STRONGIFY(self); + + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID009, + @"Failed to fetch default token %@", error); + + // This notification can be sent multiple times since we can't guarantee success at any point + // of time. + NSNotification *tokenFetchFailNotification = + [NSNotification notificationWithName:kFIRInstanceIDDefaultGCMTokenFailNotification + object:[error copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenFetchFailNotification + postingStyle:NSPostASAP]; + + self.retryCountForDefaultToken = (NSInteger)MIN(self.retryCountForDefaultToken + 1, + [[self class] maxRetryCountForDefaultToken]); + + // Do not retry beyond the maximum limit. + if (self.retryCountForDefaultToken < [[self class] maxRetryCountForDefaultToken]) { + NSInteger retryInterval = [self retryIntervalToFetchDefaultToken]; + [self retryGetDefaultTokenAfter:retryInterval]; + } else { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID007, + @"Failed to retrieve the default FCM token after %ld retries", + (long)self.retryCountForDefaultToken); + [self performDefaultTokenHandlerWithToken:nil error:error]; + } + } else { + // If somebody updated IID with APNS token while our initial request did not have it + // set we need to update it on the server. + NSData *deviceTokenInRequest = instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSKey]; + BOOL isSandboxInRequest = + [instanceIDOptions[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey] boolValue]; + // Note that APNSTupleStringInRequest will be nil if deviceTokenInRequest is nil + NSString *APNSTupleStringInRequest = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + deviceTokenInRequest, isSandboxInRequest); + // If the APNs value either remained nil, or was the same non-nil value, the APNs value + // did not change. + BOOL APNSRemainedSameDuringFetch = + (self.APNSTupleString == nil && APNSTupleStringInRequest == nil) || + ([self.APNSTupleString isEqualToString:APNSTupleStringInRequest]); + if (!APNSRemainedSameDuringFetch && hasFirebaseMessaging) { + // APNs value did change mid-fetch, so the token should be re-fetched with the current APNs + // value. + [self retryGetDefaultTokenAfter:0]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeRefetchingTokenForAPNS, + @"Received APNS token while fetching default token. " + @"Refetching default token."); + // Do not notify and handle completion handler since this is a retry. + // Simply return. + return; + } else { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeInstanceID010, + @"Successfully fetched default token."); + } + // Post the required notifications if somebody is waiting. + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID008, @"Got default token %@", + token); + NSString *previousFCMToken = self.defaultFCMToken; + self.defaultFCMToken = token; + + // Only notify of token refresh if we have a new valid token that's different than before + if (self.defaultFCMToken.length && ![self.defaultFCMToken isEqualToString:previousFCMToken]) { + NSNotification *tokenRefreshNotification = + [NSNotification notificationWithName:kFIRInstanceIDTokenRefreshNotification + object:[self.defaultFCMToken copy]]; + [[NSNotificationQueue defaultQueue] enqueueNotification:tokenRefreshNotification + postingStyle:NSPostASAP]; + } + + [self performDefaultTokenHandlerWithToken:token error:nil]; + } + }; + + [self tokenWithAuthorizedEntity:self.fcmSenderID + scope:kFIRInstanceIDDefaultTokenScope + options:instanceIDOptions + handler:newHandler]; +} + +/** + * + */ +- (void)performDefaultTokenHandlerWithToken:(NSString *)token error:(NSError *)error { + if (!self.defaultTokenFetchHandler) { + return; + } + + [self.defaultTokenFetchHandler combinedHandler](token, error); + self.defaultTokenFetchHandler = nil; +} + +- (void)retryGetDefaultTokenAfter:(NSTimeInterval)retryInterval { + FIRInstanceID_WEAKIFY(self); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(retryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + // Pass nil: no new handlers to be added, currently existing handlers + // will be called + [self defaultTokenWithRetry:YES handler:nil]; + }); +} + +#pragma mark - APNS Token +// This should only be triggered from FCM. +- (void)notifyAPNSTokenIsSet:(NSNotification *)notification { + NSData *token = notification.object; + if (!token || ![token isKindOfClass:[NSData class]]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal002, @"Invalid APNS token type %@", + NSStringFromClass([notification.object class])); + return; + } + NSInteger type = [notification.userInfo[kFIRInstanceIDAPNSTokenType] integerValue]; + + // The APNS token is being added, or has changed (rare) + if ([self.apnsTokenData isEqualToData:token]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID011, + @"Trying to reset APNS token to the same value. Will return"); + return; + } + // Use this token type for when we have to automatically fetch tokens in the future + self.apnsTokenType = type; + BOOL isSandboxApp = (type == FIRInstanceIDAPNSTokenTypeSandbox); + if (self.apnsTokenType == FIRInstanceIDAPNSTokenTypeUnknown) { + isSandboxApp = [self isSandboxApp]; + } + self.apnsTokenData = [token copy]; + self.APNSTupleString = FIRInstanceIDAPNSTupleStringForTokenAndServerType(token, isSandboxApp); + + // Pro-actively invalidate the default token, if the APNs change makes it + // invalid. Previously, we invalidated just before fetching the token. + NSArray *invalidatedTokens = + [self.tokenManager updateTokensToAPNSDeviceToken:self.apnsTokenData isSandbox:isSandboxApp]; + + // Re-fetch any invalidated tokens automatically, this time with the current APNs token, so that + // they are up-to-date. + if (invalidatedTokens.count > 0) { + FIRInstanceID_WEAKIFY(self); + + [self.installations + installationIDWithCompletion:^(NSString *_Nullable identifier, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (self == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID017, + @"Instance ID shut down during token reset. Aborting"); + return; + } + if (self.apnsTokenData == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID018, + @"apnsTokenData was set to nil during token reset. Aborting"); + return; + } + + NSMutableDictionary *tokenOptions = [@{ + kFIRInstanceIDTokenOptionsAPNSKey : self.apnsTokenData, + kFIRInstanceIDTokenOptionsAPNSIsSandboxKey : @(isSandboxApp) + } mutableCopy]; + if (self.firebaseAppID) { + tokenOptions[kFIRInstanceIDTokenOptionsFirebaseAppIDKey] = self.firebaseAppID; + } + + for (FIRInstanceIDTokenInfo *tokenInfo in invalidatedTokens) { + if ([tokenInfo.token isEqualToString:self.defaultFCMToken]) { + // We will perform a special fetch for the default FCM token, so that the delegate + // methods are called. For all others, we will do an internal re-fetch. + [self defaultTokenWithHandler:nil]; + } else { + [self.tokenManager fetchNewTokenWithAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope + instanceID:identifier + options:tokenOptions + handler:^(NSString *_Nullable token, + NSError *_Nullable error){ + + }]; + } + } + }]; + } +} + +- (BOOL)isSandboxApp { + static BOOL isSandboxApp = YES; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + isSandboxApp = ![self isProductionApp]; + }); + return isSandboxApp; +} + +- (BOOL)isProductionApp { + const BOOL defaultAppTypeProd = YES; + + NSError *error = nil; + if ([GULAppEnvironmentUtil isSimulator]) { + [self logAPNSConfigurationError:@"Running InstanceID on a simulator doesn't have APNS. " + @"Use prod profile by default."]; + return defaultAppTypeProd; + } + + if ([GULAppEnvironmentUtil isFromAppStore]) { + // Apps distributed via AppStore or TestFlight use the Production APNS certificates. + return defaultAppTypeProd; + } +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *path = [[[NSBundle mainBundle] bundlePath] + stringByAppendingPathComponent:@"embedded.mobileprovision"]; +#elif TARGET_OS_OSX + NSString *path = [[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent] + stringByAppendingPathComponent:@"embedded.provisionprofile"]; +#endif + + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox] && !path.length) { + // Distributed via TestFlight + return defaultAppTypeProd; + } + + NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error]; + + if (!profileData.length || error) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + // The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the + // end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit + // ASCII. Replace any 0s or invalid characters in the input. + uint8_t *profileBytes = (uint8_t *)profileData.bytes; + for (int i = 0; i < profileData.length; i++) { + uint8_t currentByte = profileBytes[i]; + if (!currentByte || currentByte > 127) { + profileBytes[i] = '.'; + } + } + + NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes + length:profileData.length + encoding:NSASCIIStringEncoding + freeWhenDone:NO]; + + if (error || !embeddedProfile.length) { + NSString *errorString = + [NSString stringWithFormat:@"Error while reading embedded mobileprovision %@", error]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + + NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile]; + NSString *plistContents; + if ([scanner scanUpToString:@"" intoString:&plistContents]) { + plistContents = [plistContents stringByAppendingString:@""]; + } + } + + if (!plistContents.length) { + return defaultAppTypeProd; + } + + NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding]; + if (!data.length) { + [self logAPNSConfigurationError:@"Couldn't read plist fetched from embedded mobileprovision"]; + return defaultAppTypeProd; + } + + NSError *plistMapError; + id plistData = [NSPropertyListSerialization propertyListWithData:data + options:NSPropertyListImmutable + format:nil + error:&plistMapError]; + if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) { + NSString *errorString = + [NSString stringWithFormat:@"Error while converting assumed plist to dict %@", + plistMapError.localizedDescription]; + [self logAPNSConfigurationError:errorString]; + return defaultAppTypeProd; + } + NSDictionary *plistMap = (NSDictionary *)plistData; + + if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID012, + @"Provisioning profile has specifically provisioned devices, " + @"most likely a Dev profile."); + } + + NSString *apsEnvironment = [plistMap valueForKeyPath:kEntitlementsAPSEnvironmentKey]; + NSString *debugString __unused = + [NSString stringWithFormat:@"APNS Environment in profile: %@", apsEnvironment]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID013, @"%@", debugString); + + // No aps-environment in the profile. + if (!apsEnvironment.length) { + [self logAPNSConfigurationError:@"No aps-environment set. If testing on a device APNS is not " + @"correctly configured. Please recheck your provisioning " + @"profiles. If testing on a simulator this is fine since APNS " + @"doesn't work on the simulator."]; + return defaultAppTypeProd; + } + + if ([apsEnvironment isEqualToString:kAPSEnvironmentDevelopmentValue]) { + return NO; + } + + return defaultAppTypeProd; +} + +/// Log error messages only when Messaging exists in the pod. +- (void)logAPNSConfigurationError:(NSString *)errorString { + BOOL hasFirebaseMessaging = NSClassFromString(kFIRInstanceIDFCMSDKClassString) != nil; + if (hasFirebaseMessaging) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeInstanceID014, @"%@", errorString); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInstanceID015, @"%@", errorString); + } +} + +#pragma mark - Sync InstanceID + +- (void)updateFirebaseInstallationID { + FIRInstanceID_WEAKIFY(self); + [self.installations + installationIDWithCompletion:^(NSString *_Nullable installationID, NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + self.firebaseInstallationsID = installationID; + }]; +} + +- (void)installationIDDidChangeNotificationReceived:(NSNotification *)notification { + NSString *installationAppID = + notification.userInfo[kFIRInstallationIDDidChangeNotificationAppNameKey]; + if ([installationAppID isKindOfClass:[NSString class]] && + [installationAppID isEqual:self.firebaseAppID]) { + [self updateFirebaseInstallationID]; + } +} + +- (void)observeFirebaseInstallationIDChanges { + [[NSNotificationCenter defaultCenter] removeObserver:self + name:FIRInstallationIDDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(installationIDDidChangeNotificationReceived:) + name:FIRInstallationIDDidChangeNotification + object:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h new file mode 100644 index 0000000..92b2469 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an APNS device token and whether its environment is for sandbox. + * It can read from and write to an NSDictionary for simple serialization. + */ +@interface FIRInstanceIDAPNSInfo : NSObject + +/// The APNs device token, provided by the OS to the application delegate +@property(nonatomic, readonly, strong) NSData *deviceToken; +/// Represents whether or not this is deviceToken is for the sandbox +/// environment, or production. +@property(nonatomic, readonly, getter=isSandbox) BOOL sandbox; + +/** + * Initializes the receiver with an APNs device token, and boolean + * representing whether that token is for the sandbox environment. + * + * @param deviceToken The APNs device token typically provided by the + * operating system. + * @param isSandbox YES if the APNs device token is for the sandbox + * environment, or NO if it is for production. + * @return An instance of FIRInstanceIDAPNSInfo. + */ +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox; + +/** + * Initializes the receiver from a token options dictionary containing data + * within the `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey` keys. The token should be an + * NSData blob, and the sandbox value should be an NSNumber + * representing a boolean value. + * + * @param dictionary A dictionary containing values under the keys + * `kFIRInstanceIDTokenOptionsAPNSKey` and + * `kFIRInstanceIDTokenOptionsAPNSIsSandboxKey`. + * @return An instance of FIRInstanceIDAPNSInfo, or nil if the + * dictionary data was invalid or missing. + */ +- (nullable instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary; + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m new file mode 100644 index 0000000..d1f9d08 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAPNSInfo.m @@ -0,0 +1,79 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAPNSInfo.h" + +#import "FIRInstanceIDConstants.h" + +/// The key used to find the APNs device token in an archive. +NSString *const kFIRInstanceIDAPNSInfoTokenKey = @"device_token"; +/// The key used to find the sandbox value in an archive. +NSString *const kFIRInstanceIDAPNSInfoSandboxKey = @"sandbox"; + +@implementation FIRInstanceIDAPNSInfo + +- (instancetype)initWithDeviceToken:(NSData *)deviceToken isSandbox:(BOOL)isSandbox { + self = [super init]; + if (self) { + _deviceToken = [deviceToken copy]; + _sandbox = isSandbox; + } + return self; +} + +- (instancetype)initWithTokenOptionsDictionary:(NSDictionary *)dictionary { + id deviceToken = dictionary[kFIRInstanceIDTokenOptionsAPNSKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + + id isSandbox = dictionary[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if (![isSandbox isKindOfClass:[NSNumber class]]) { + return nil; + } + self = [super init]; + if (self) { + _deviceToken = (NSData *)deviceToken; + _sandbox = ((NSNumber *)isSandbox).boolValue; + } + return self; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + id deviceToken = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoTokenKey]; + if (![deviceToken isKindOfClass:[NSData class]]) { + return nil; + } + BOOL isSandbox = [aDecoder decodeBoolForKey:kFIRInstanceIDAPNSInfoSandboxKey]; + return [self initWithDeviceToken:(NSData *)deviceToken isSandbox:isSandbox]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.deviceToken forKey:kFIRInstanceIDAPNSInfoTokenKey]; + [aCoder encodeBool:self.sandbox forKey:kFIRInstanceIDAPNSInfoSandboxKey]; +} + +- (BOOL)isEqualToAPNSInfo:(FIRInstanceIDAPNSInfo *)otherInfo { + if ([super isEqual:otherInfo]) { + return YES; + } + return ([self.deviceToken isEqualToData:otherInfo.deviceToken] && + self.isSandbox == otherInfo.isSandbox); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h new file mode 100644 index 0000000..8d453b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +extern NSString *__nonnull const kFIRInstanceIDKeychainWildcardIdentifier; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper around storing FCM auth data in iOS keychain. + */ +@interface FIRInstanceIDAuthKeychain : NSObject + +/** + * Designated Initializer. Init a generic `SecClassGenericPassword` keychain with `identifier` + * as the `kSecAttrGeneric`. + * + * @param identifier The generic attribute to be used by the keychain. + * + * @return A Keychain object with `kSecAttrGeneric` attribute set to identifier. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + * Get keychain items matching the given service and account. The service and/or account + * can be a wildcard (`kFIRInstanceIDKeychainWildcardIdentifier`), which case the query + * will include all items matching any services and/or accounts. + * + * @param service The kSecAttrService used to save the password. Can be wildcard. + * @param account The kSecAttrAccount used to save the password. Can be wildcard. + * + * @return An array of |NSData|s matching the provided inputs. + */ +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account; + +/** + * Get keychain item for a given service and account. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * + * @return A cached keychain item for a given account and service, or nil if it was not + * found or could not be retrieved. + */ +- (NSData *)dataForService:(NSString *)service account:(NSString *)account; + +/** + * Remove the cached items from the keychain matching the service, account and access group. + * In case the items do not exist, YES is returned but with a valid error object with code + * `errSecItemNotFound`. + * + * @param service The kSecAttrService used to save the password. + * @param account The kSecAttrAccount used to save the password. + * @param handler The callback handler which is invoked when the remove operation is complete, with + * an error if there is any. + */ +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *error))handler; + +/** + * Set the data for a given service and account. + * We use `kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly` which + * prevents backup and restore to iCloud, and works for app extension that can + * execute right after a device is restarted (and not unlocked). + * + * @param data The data to save. + * @param service The `kSecAttrService` used to save the password. + * @param account The `kSecAttrAccount` used to save the password. + * @param handler The callback handler which is invoked when the add operation is complete, + * with an error if there is any. + * + */ +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(nullable void (^)(NSError *))handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m new file mode 100644 index 0000000..dfce2f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m @@ -0,0 +1,216 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDKeychain.h" +#import "FIRInstanceIDLogger.h" + +/** + * The error type representing why we couldn't read data from the keychain. + */ +typedef NS_ENUM(int, FIRInstanceIDKeychainErrorType) { + kFIRInstanceIDKeychainErrorBadArguments = -1301, +}; + +NSString *const kFIRInstanceIDKeychainWildcardIdentifier = @"*"; + +@interface FIRInstanceIDAuthKeychain () + +@property(nonatomic, copy) NSString *generic; +// cachedKeychainData is keyed by service and account, the value is an array of NSData. +// It is used to cache the tokens per service, per account, as well as checkin data per service, +// per account inside the keychain. +@property(nonatomic) + NSMutableDictionary *> *> + *cachedKeychainData; + +@end + +@implementation FIRInstanceIDAuthKeychain + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _generic = [identifier copy]; + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } + return self; +} + ++ (NSMutableDictionary *)keychainQueryForService:(NSString *)service + account:(NSString *)account + generic:(NSString *)generic { + NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword}; + + NSMutableDictionary *finalQuery = [NSMutableDictionary dictionaryWithDictionary:query]; + if ([generic length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:generic]) { + finalQuery[(__bridge NSString *)kSecAttrGeneric] = generic; + } + if ([account length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:account]) { + finalQuery[(__bridge NSString *)kSecAttrAccount] = account; + } + if ([service length] && ![kFIRInstanceIDKeychainWildcardIdentifier isEqualToString:service]) { + finalQuery[(__bridge NSString *)kSecAttrService] = service; + } + return finalQuery; +} + +- (NSMutableDictionary *)keychainQueryForService:(NSString *)service account:(NSString *)account { + return [[self class] keychainQueryForService:service account:account generic:self.generic]; +} + +- (NSArray *)itemsMatchingService:(NSString *)service account:(NSString *)account { + // If query wildcard service, it asks for all the results, which always query from keychain. + if (![service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + ![account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] && + _cachedKeychainData[service][account]) { + // As long as service, account array exist, even it's empty, it means we've queried it before, + // returns the cache value. + return _cachedKeychainData[service][account]; + } + + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + NSMutableArray *results; + keychainQuery[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; +#if TARGET_OS_IOS || TARGET_OS_TV + keychainQuery[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitAll; + // FIRInstanceIDKeychain should only take a query and return a result, will handle the query here. + NSArray *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#elif TARGET_OS_OSX || TARGET_OS_WATCH + keychainQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + NSData *passwordInfos = + CFBridgingRelease([[FIRInstanceIDKeychain sharedInstance] itemWithQuery:keychainQuery]); +#endif + + if (!passwordInfos) { + // Nothing was found, simply return from this sync block. + // Make sure to label the cache entry empty, signaling that we've queried this entry. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return @[]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + return @[]; + } + results = [[NSMutableArray alloc] init]; +#if TARGET_OS_IOS || TARGET_OS_TV + NSInteger numPasswords = passwordInfos.count; + for (NSUInteger i = 0; i < numPasswords; i++) { + NSDictionary *passwordInfo = [passwordInfos objectAtIndex:i]; + if (passwordInfo[(__bridge id)kSecValueData]) { + [results addObject:passwordInfo[(__bridge id)kSecValueData]]; + } + } +#elif TARGET_OS_OSX || TARGET_OS_WATCH + [results addObject:passwordInfos]; +#endif + // We query the keychain because it didn't exist in cache, now query is done, update the result in + // the cache. + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Do not update cache if it's wildcard query. + return [results copy]; + } else if (_cachedKeychainData[service]) { + [_cachedKeychainData[service] setObject:[results copy] forKey:account]; + } else { + NSMutableDictionary *entry = [@{account : [results copy]} mutableCopy]; + [_cachedKeychainData setObject:entry forKey:service]; + } + return [results copy]; +} + +- (NSData *)dataForService:(NSString *)service account:(NSString *)account { + NSArray *items = [self itemsMatchingService:service account:account]; + // If items is nil or empty, nil will be returned. + return items.firstObject; +} + +- (void)removeItemsMatchingService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *error))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all keychain items. + _cachedKeychainData = [[NSMutableDictionary alloc] init]; + } else if ([account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + // Delete all entries under service, + if (_cachedKeychainData[service]) { + _cachedKeychainData[service] = [[NSMutableDictionary alloc] init]; + } + } else if (_cachedKeychainData[service]) { + // We should keep the service/account entry instead of nil so we know + // it's "empty entry" instead of "not query from keychain yet". + [_cachedKeychainData[service] setObject:@[] forKey:account]; + } else { + [_cachedKeychainData setObject:[@{account : @[]} mutableCopy] forKey:service]; + } + NSMutableDictionary *keychainQuery = [self keychainQueryForService:service account:account]; + [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:keychainQuery handler:handler]; +} + +- (void)setData:(NSData *)data + forService:(NSString *)service + account:(NSString *)account + handler:(void (^)(NSError *))handler { + if ([service isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier] || + [account isEqualToString:kFIRInstanceIDKeychainWildcardIdentifier]) { + if (handler) { + handler([NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:kFIRInstanceIDKeychainErrorBadArguments + userInfo:nil]); + } + return; + } + [self removeItemsMatchingService:service + account:account + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (data.length > 0) { + NSMutableDictionary *keychainQuery = + [self keychainQueryForService:service account:account]; + keychainQuery[(__bridge id)kSecValueData] = data; + + keychainQuery[(__bridge id)kSecAttrAccessible] = + (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; + [[FIRInstanceIDKeychain sharedInstance] + addItemWithQuery:keychainQuery + handler:handler]; + } + }]; + // Set the cache value. This must happen after removeItemsMatchingService:account:handler was + // called, so the cache value was reset before setting a new value. + if (_cachedKeychainData[service]) { + if (_cachedKeychainData[service][account]) { + _cachedKeychainData[service][account] = @[ data ]; + } else { + [_cachedKeychainData[service] setObject:@[ data ] forKey:account]; + } + } else { + [_cachedKeychainData setObject:[@{account : @[ data ]} mutableCopy] forKey:service]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h new file mode 100644 index 0000000..1fb715e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FIRInstanceIDCheckinService.h" + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDStore; + +/** + * FIRInstanceIDAuthService is responsible for retrieving, caching, and supplying checkin info + * for the rest of Instance ID. A checkin can be scheduled, meaning that it will keep retrying the + * checkin request until it is successful. A checkin can also be requested directly, with a + * completion handler. + */ +@interface FIRInstanceIDAuthService : NSObject + +/** + * Used only for testing. In addition to taking a store (for locally caching the checkin info), it + * also takes a checkinService. + */ +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store; + +/** + * Initializes the auth service given a store (which provides the local caching of checkin info). + * This initializer will create its own instance of FIRInstanceIDCheckinService. + */ +- (instancetype)initWithStore:(FIRInstanceIDStore *)store; + +#pragma mark - Checkin Service + +/** + * Checks if the current deviceID and secret are valid or not. + * + * @return YES if the checkin credentials are valid else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Fetch checkin info from the server. This would usually refresh the existing + * checkin credentials for the current app. + * + * @param handler The completion handler to invoke once the checkin info has been + * refreshed. + */ +- (void)fetchCheckinInfoWithHandler:(FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Schedule checkin. Will hit the network only if the currently loaded checkin + * preferences are stale. + * + * @param immediately YES if we want it to be scheduled immediately else NO. + */ +- (void)scheduleCheckin:(BOOL)immediately; + +/** + * Returns the checkin preferences currently loaded in memory. The Checkin preferences + * can be either valid or invalid. + * + * @return The checkin preferences loaded in memory. + */ +- (FIRInstanceIDCheckinPreferences *)checkinPreferences; + +/** + * Cancels any ongoing checkin fetch, if any. + */ +- (void)stopCheckinRequest; + +/** + * Resets the checkin information. + * + * @param handler The callback handler which is invoked when checkin reset is complete, + * with an error if there is any. + */ +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m new file mode 100644 index 0000000..8c33c44 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDAuthService.m @@ -0,0 +1,302 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDAuthService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "NSError+FIRInstanceID.h" + +// Max time interval between checkin retry in seconds. +static const int64_t kMaxCheckinRetryIntervalInSeconds = 1 << 5; + +@interface FIRInstanceIDAuthService () + +// Used to retrieve and cache the checkin info to disk and Keychain. +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *store; +// Used to perform single checkin fetches. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinService *checkinService; +// The current checkin info. It will be compared to what is retrieved to determine whether it is +// different than what is in the cache. +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; + +// This array will track multiple handlers waiting for checkin to be performed. When a checkin +// request completes, all the handlers will be notified. +// Changes to the checkinHandlers array should happen in a thread-safe manner. +@property(nonatomic, readonly, strong) + NSMutableArray *checkinHandlers; + +// This is set to true if there is a checkin request in-flight. +@property(atomic, readwrite, assign) BOOL isCheckinInProgress; +// This timer is used a perform checkin retries. It is cancellable. +@property(atomic, readwrite, strong) NSTimer *scheduledCheckinTimer; +// The number of times checkin has been retried during a scheduled checkin. +@property(atomic, readwrite, assign) int checkinRetryCount; + +@end + +@implementation FIRInstanceIDAuthService + +- (instancetype)initWithCheckinService:(FIRInstanceIDCheckinService *)checkinService + store:(FIRInstanceIDStore *)store { + self = [super init]; + if (self) { + _store = store; + _checkinPreferences = [_store cachedCheckinPreferences]; + _checkinService = checkinService; + _checkinHandlers = [NSMutableArray array]; + } + return self; +} + +- (void)dealloc { + [_scheduledCheckinTimer invalidate]; +} + +- (instancetype)initWithStore:(FIRInstanceIDStore *)store { + FIRInstanceIDCheckinService *checkinService = [[FIRInstanceIDCheckinService alloc] init]; + return [self initWithCheckinService:checkinService store:store]; +} + +#pragma mark - Schedule Checkin + +- (void)scheduleCheckin:(BOOL)immediately { + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + // Checkin is already scheduled, so this (non-immediate) request can be ignored. + if (!immediately && [self.scheduledCheckinTimer isValid]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService000, + @"Checkin sync already scheduled. Will not schedule."); + return; + } + + if (immediately) { + [self performScheduledCheckin]; + } else { + int64_t checkinRetryDuration = [self calculateNextCheckinRetryIntervalInSeconds]; + [self startCheckinTimerWithDuration:(NSTimeInterval)checkinRetryDuration]; + } +} + +- (void)startCheckinTimerWithDuration:(NSTimeInterval)timerDuration { + self.scheduledCheckinTimer = + [NSTimer scheduledTimerWithTimeInterval:timerDuration + target:self + selector:@selector(onScheduledCheckinTimerFired:) + userInfo:nil + repeats:NO]; + // Add some tolerance to the timer, to allow iOS to be more flexible with this timer + self.scheduledCheckinTimer.tolerance = 0.5; +} + +- (void)clearScheduledCheckinTimer { + [self.scheduledCheckinTimer invalidate]; + self.scheduledCheckinTimer = nil; +} + +- (void)onScheduledCheckinTimerFired:(NSTimer *)timer { + [self performScheduledCheckin]; +} + +- (void)performScheduledCheckin { + // No checkin scheduled as of now. + [self clearScheduledCheckinTimer]; + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + return; + } + + FIRInstanceID_WEAKIFY(self); + [self + fetchCheckinInfoWithHandler:^(FIRInstanceIDCheckinPreferences *preferences, NSError *error) { + FIRInstanceID_STRONGIFY(self); + self.checkinRetryCount++; + + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService001, @"Checkin error %@.", + error); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Schedule another checkin + [self scheduleCheckin:NO]; + }); + + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService002, @"Checkin success."); + } + }]; +} + +- (int64_t)calculateNextCheckinRetryIntervalInSeconds { + // persistent failures can lead to overflow prevent that. + if (self.checkinRetryCount >= 10) { + return kMaxCheckinRetryIntervalInSeconds; + } + return MIN(1 << self.checkinRetryCount, kMaxCheckinRetryIntervalInSeconds); +} + +#pragma mark - Checkin Service + +- (BOOL)hasValidCheckinInfo { + return [self.checkinPreferences hasValidCheckinInfo]; +} + +- (void)fetchCheckinInfoWithHandler:(nonnull FIRInstanceIDDeviceCheckinCompletion)handler { + // Perform any changes to self.checkinHandlers and _isCheckinInProgress in a thread-safe way. + @synchronized(self) { + [self.checkinHandlers addObject:handler]; + + if (_isCheckinInProgress) { + // Nothing more to do until our checkin request is done + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthServiceCheckinInProgress, + @"Checkin is in progress\n"); + return; + } + } + + // Checkin is still valid, so a remote checkin is not required. + if ([self.checkinPreferences hasValidCheckinInfo]) { + [self notifyCheckinHandlersWithCheckin:self.checkinPreferences error:nil]; + return; + } + + @synchronized(self) { + _isCheckinInProgress = YES; + } + [self.checkinService + checkinWithExistingCheckin:self.checkinPreferences + completion:^(FIRInstanceIDCheckinPreferences *checkinPreferences, + NSError *error) { + @synchronized(self) { + self->_isCheckinInProgress = NO; + } + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService003, + @"Failed to checkin device %@", error); + [self notifyCheckinHandlersWithCheckin:nil error:error]; + return; + } + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeAuthService004, + @"Successfully got checkin credentials"); + BOOL hasSameCachedPreferences = + [self cachedCheckinMatchesCheckin:checkinPreferences]; + checkinPreferences.hasPreCachedAuthCredentials = hasSameCachedPreferences; + + // Update to the most recent checkin preferences + self.checkinPreferences = checkinPreferences; + + // Save the checkin info to disk + // Keychain might not be accessible, so confirm that checkin preferences can + // be saved + [self.store + saveCheckinPreferences:checkinPreferences + handler:^(NSError *checkinSaveError) { + if (checkinSaveError && !hasSameCachedPreferences) { + // The checkin info was new, but it couldn't be + // written to the Keychain. Delete any stuff that was + // cached in memory. This doesn't delete any + // previously persisted preferences. + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeService004, + @"Unable to save checkin info, resetting " + @"checkin preferences " + "in memory."); + [checkinPreferences reset]; + [self + notifyCheckinHandlersWithCheckin:nil + error: + checkinSaveError]; + } else { + // The checkin is either new, or it was the same (and + // it couldn't be saved). Either way, report that the + // checkin preferences were received successfully. + [self notifyCheckinHandlersWithCheckin: + checkinPreferences + error:nil]; + if (!hasSameCachedPreferences) { + // Checkin is new. + // Notify any listeners that might be waiting for + // checkin to be fetched, such as Firebase + // Messaging (for its MCS connection). + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] + postNotificationName: + kFIRInstanceIDCheckinFetchedNotification + object:nil]; + }); + } + } + }]; + }]; +} + +- (FIRInstanceIDCheckinPreferences *)checkinPreferences { + return _checkinPreferences; +} + +- (void)stopCheckinRequest { + [self.checkinService stopFetching]; +} + +- (void)resetCheckinWithHandler:(void (^)(NSError *error))handler { + [self.store removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + self.checkinPreferences = nil; + } + if (handler) { + handler(error); + } + }]; +} + +#pragma mark - Private + +/** + * Goes through the current list of checkin handlers and fires them with the same checkin and/or + * error info. The checkin handlers will get cleared after. + */ +- (void)notifyCheckinHandlersWithCheckin:(nullable FIRInstanceIDCheckinPreferences *)checkin + error:(nullable NSError *)error { + @synchronized(self) { + for (FIRInstanceIDDeviceCheckinCompletion handler in self.checkinHandlers) { + handler(checkin, error); + } + [self.checkinHandlers removeAllObjects]; + } +} + +/** + * Given a |checkin|, it will compare it to the current checkinPreferences to see if the + * deviceID and secretToken are the same. + */ +- (BOOL)cachedCheckinMatchesCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + if (self.checkinPreferences && checkin) { + return ([self.checkinPreferences.deviceID isEqualToString:checkin.deviceID] && + [self.checkinPreferences.secretToken isEqualToString:checkin.secretToken]); + } + return NO; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h new file mode 100644 index 0000000..bccaced --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDBackupExcludedPlist : NSObject + +/** + * Caches the plist contents in memory so we don't hit the disk each time we want + * to query something in the plist. This is loaded lazily i.e. if you write to the + * plist the contents you want to write will be stored here if the write was + * successful. The other case where it is loaded is if you read the plist contents + * by calling `contentAsDictionary`. + * + * In case you write to the plist and then try to read the file using + * `contentAsDictionary` we would just return the cachedPlistContents since it would + * represent the disk contents. + */ +@property(nonatomic, readonly, strong) NSDictionary *cachedPlistContents; + +/** + * Init a backup excluded plist file. + * + * @param fileName The filename for the plist file. + * @param subDirectory The subdirectory in Application Support to save the plist. + * + * @return Helper which allows to read write data to a backup excluded plist. + */ +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory; + +/** + * Write dictionary data to the backup excluded plist file. If the file does not exist + * it would be created before writing to it. + * + * @param dict The data to be written to the plist. + * @param error The error object if any while writing the data. + * + * @return YES if the write was successful else NO. + */ +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error; + +/** + * Delete the backup excluded plist created with the above filename. + * + * @param error The error object if any while deleting the file. + * + * @return YES If the delete was successful else NO. + */ +- (BOOL)deleteFile:(NSError **)error; + +/** + * The contents of the plist file. We also store the contents of the file in-memory. + * If the in-memory contents are valid we return the in-memory contents else we read + * the file from disk. + * + * @return A dictionary object that contains the contents of the plist file if the file + * exists else nil. + */ +- (NSDictionary *)contentAsDictionary; + +/** + * Check if the plist exists on the disk or not. + * + * @return YES if the file exists on the disk else NO. + */ +- (BOOL)doesFileExist; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m new file mode 100644 index 0000000..c1085ca --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDBackupExcludedPlist.h" + +#import "FIRInstanceIDLogger.h" + +@interface FIRInstanceIDBackupExcludedPlist () + +@property(nonatomic, readwrite, copy) NSString *fileName; +@property(nonatomic, readwrite, copy) NSString *subDirectoryName; +@property(nonatomic, readwrite, strong) NSDictionary *cachedPlistContents; + +@end + +@implementation FIRInstanceIDBackupExcludedPlist + +- (instancetype)initWithFileName:(NSString *)fileName subDirectory:(NSString *)subDirectory { + self = [super init]; + if (self) { + _fileName = [fileName copy]; + _subDirectoryName = [subDirectory copy]; + } + return self; +} + +- (BOOL)writeDictionary:(NSDictionary *)dict error:(NSError **)error { + NSString *path = [self plistPathInDirectory]; + if (![dict writeToFile:path atomically:YES]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist000, + @"Failed to write to %@.plist", self.fileName); + return NO; + } + + // Successfully wrote contents -- change the in-memory contents + self.cachedPlistContents = [dict copy]; + + NSURL *URL = [NSURL fileURLWithPath:path]; + if (error) { + *error = nil; + } + + NSDictionary *preferences = [URL resourceValuesForKeys:@[ NSURLIsExcludedFromBackupKey ] + error:error]; + if ([preferences[NSURLIsExcludedFromBackupKey] boolValue]) { + return YES; + } + + BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:error]; + if (!success) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeBackupExcludedPlist001, + @"Error excluding %@ from backup, %@", [URL lastPathComponent], + error ? *error : @""); + } + return success; +} + +- (BOOL)deleteFile:(NSError **)error { + BOOL success = YES; + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + success = [[NSFileManager defaultManager] removeItemAtPath:path error:error]; + } + // remove the in-memory contents + self.cachedPlistContents = nil; + return success; +} + +- (NSDictionary *)contentAsDictionary { + if (!self.cachedPlistContents) { + NSString *path = [self plistPathInDirectory]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + self.cachedPlistContents = [[NSDictionary alloc] initWithContentsOfFile:path]; + } + } + return self.cachedPlistContents; +} + +- (BOOL)doesFileExist { + NSString *path = [self plistPathInDirectory]; + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +#pragma mark - Private + +- (NSString *)plistPathInDirectory { + NSArray *directoryPaths; + NSString *plistNameWithExtension = [NSString stringWithFormat:@"%@.plist", self.fileName]; + directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSArray *components = @[ directoryPaths.lastObject, _subDirectoryName, plistNameWithExtension ]; + + return [NSString pathWithComponents:components]; +} + +- (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h new file mode 100644 index 0000000..d2f286d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface FIRInstanceIDCheckinPreferences (Internal) + +/** + * Parse the checkin auth credentials saved in the Keychain to initialize checkin + * preferences. + * + * @param keychainContent The checkin auth credentials saved in the Keychain. + * + * @return A valid checkin preferences object if the checkin auth credentials in the + * keychain can be parsed successfully else nil. + */ ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent; + +/** + * Default initializer for InstanceID checkin preferences. + * + * @param deviceID The deviceID for the app. + * @param secretToken The secret token the app uses to authenticate with the server. + * + * @return A checkin preferences object with given deviceID and secretToken. + */ +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken; + +/** + * Update checkin preferences from the preferences dict persisted as a plist. The dict contains + * all the checkin preferences retrieved from the server except the deviceID and secret which + * are stored in the Keychain. + * + * @param checkinPlistContent The checkin preferences saved in a plist on the disk. + */ +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent; + +/** + * Reset the current checkin preferences object. + */ +- (void)reset; + +/** + * The string that contains the checkin auth credentials i.e. deviceID and secret. This + * needs to be stored in the Keychain. + * + * @return The checkin auth credential string containing the deviceID and secret. + */ +- (NSString *)checkinKeychainContent; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m new file mode 100644 index 0000000..88cc40a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences+Internal.h" + +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kCheckinKeychainContentSeparatorString = @"|"; + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +@end + +@implementation FIRInstanceIDCheckinPreferences (Internal) + ++ (FIRInstanceIDCheckinPreferences *)preferencesFromKeychainContents:(NSString *)keychainContent { + NSString *deviceID = [self checkinDeviceIDFromKeychainContent:keychainContent]; + NSString *secret = [self checkinSecretFromKeychainContent:keychainContent]; + if ([deviceID length] && [secret length]) { + return [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceID secretToken:secret]; + } else { + return nil; + } +} + +- (instancetype)initWithDeviceID:(NSString *)deviceID secretToken:(NSString *)secretToken { + self = [super init]; + if (self) { + self.deviceID = [deviceID copy]; + self.secretToken = [secretToken copy]; + } + return self; +} + +- (void)reset { + self.deviceID = nil; + self.secretToken = nil; + self.digest = nil; + self.versionInfo = nil; + self.gServicesData = nil; + self.deviceDataVersion = nil; + self.lastCheckinTimestampMillis = 0; +} + +- (void)updateWithCheckinPlistContents:(NSDictionary *)checkinPlistContent { + for (NSString *key in checkinPlistContent) { + if ([kFIRInstanceIDDigestStringKey isEqualToString:key]) { + self.digest = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDVersionInfoStringKey isEqualToString:key]) { + self.versionInfo = [checkinPlistContent[key] copy]; + } else if ([kFIRInstanceIDLastCheckinTimeKey isEqualToString:key]) { + self.lastCheckinTimestampMillis = [checkinPlistContent[key] longLongValue]; + } else if ([kFIRInstanceIDGServicesDictionaryKey isEqualToString:key]) { + self.gServicesData = [checkinPlistContent[key] mutableCopy]; + } else if ([kFIRInstanceIDDeviceDataVersionKey isEqualToString:key]) { + self.deviceDataVersion = [checkinPlistContent[key] copy]; + } + // Otherwise we have some keys we don't care about + } +} + +- (NSString *)checkinKeychainContent { + if ([self.deviceID length] && [self.secretToken length]) { + return [NSString stringWithFormat:@"%@%@%@", self.deviceID, + kCheckinKeychainContentSeparatorString, self.secretToken]; + } else { + return nil; + } +} + ++ (NSString *)checkinDeviceIDFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:0]; +} + ++ (NSString *)checkinSecretFromKeychainContent:(NSString *)keychainContent { + return [self checkinKeychainContent:keychainContent forIndex:1]; +} + ++ (NSString *)checkinKeychainContent:(NSString *)keychainContent forIndex:(int)index { + NSArray *keychainComponents = + [keychainContent componentsSeparatedByString:kCheckinKeychainContentSeparatorString]; + if (index >= 0 && index < 2 && [keychainComponents count] == 2) { + return keychainComponents[index]; + } else { + return nil; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m new file mode 100644 index 0000000..2f3c55e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinPreferences.h" + +#import +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDUtilities.h" + +const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval = 7 * 24 * 60 * 60; // 7 days. + +@interface FIRInstanceIDCheckinPreferences () + +@property(nonatomic, readwrite, copy) NSString *deviceID; +@property(nonatomic, readwrite, copy) NSString *secretToken; +@property(nonatomic, readwrite, copy) NSString *digest; +@property(nonatomic, readwrite, copy) NSString *versionInfo; +@property(nonatomic, readwrite, copy) NSString *deviceDataVersion; + +@property(nonatomic, readwrite, strong) NSMutableDictionary *gServicesData; +@property(nonatomic, readwrite, assign) int64_t lastCheckinTimestampMillis; + +// This flag indicates that we have already saved the above deviceID and secret +// to our keychain and hence we don't need to save again. This is helpful since +// on checkin refresh we can avoid writing to the Keychain which can sometimes +// be very buggy. For info check this https://forums.developer.apple.com/thread/4743 +@property(nonatomic, readwrite, assign) BOOL hasPreCachedAuthCredentials; + +@end + +@implementation FIRInstanceIDCheckinPreferences + +- (NSDictionary *)checkinPlistContents { + NSMutableDictionary *checkinPlistContents = [NSMutableDictionary dictionary]; + checkinPlistContents[kFIRInstanceIDDigestStringKey] = self.digest ?: @""; + checkinPlistContents[kFIRInstanceIDVersionInfoStringKey] = self.versionInfo ?: @""; + checkinPlistContents[kFIRInstanceIDDeviceDataVersionKey] = self.deviceDataVersion ?: @""; + checkinPlistContents[kFIRInstanceIDLastCheckinTimeKey] = @(self.lastCheckinTimestampMillis); + checkinPlistContents[kFIRInstanceIDGServicesDictionaryKey] = + [self.gServicesData count] ? self.gServicesData : @{}; + return checkinPlistContents; +} + +- (BOOL)hasCheckinInfo { + return (self.deviceID.length && self.secretToken.length); +} + +- (BOOL)hasValidCheckinInfo { + int64_t currentTimestampInMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + int64_t timeSinceLastCheckinInMillis = currentTimestampInMillis - self.lastCheckinTimestampMillis; + + BOOL hasCheckinInfo = [self hasCheckinInfo]; + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + // If it's app's first time open and checkin is already fetched and no locale information is + // stored, then checkin info is valid. We should not checkin again because locale is considered + // "changed". + if (hasCheckinInfo && !lastLocale) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return YES; + } + + // If locale has changed, checkin info is no longer valid. + // Also update locale information if changed. (Only do it here not in token refresh) + if (FIRInstanceIDHasLocaleChanged()) { + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + [[GULUserDefaults standardUserDefaults] setObject:currentLocale + forKey:kFIRInstanceIDUserDefaultsKeyLocale]; + return NO; + } + + return (hasCheckinInfo && + (timeSinceLastCheckinInMillis / 1000.0 < kFIRInstanceIDDefaultCheckinInterval)); +} + +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials { + _hasPreCachedAuthCredentials = hasPreCachedAuthCredentials; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h new file mode 100644 index 0000000..9c5850b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** Checkin refresh interval. **/ +FOUNDATION_EXPORT const NSTimeInterval kFIRInstanceIDDefaultCheckinInterval; + +@interface FIRInstanceIDCheckinPreferences () + +- (BOOL)hasPreCachedAuthCredentials; +- (void)setHasPreCachedAuthCredentials:(BOOL)hasPreCachedAuthCredentials; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h new file mode 100644 index 0000000..e14b51c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.h @@ -0,0 +1,68 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import "FIRInstanceIDUtilities.h" + +NS_ASSUME_NONNULL_BEGIN + +// keys in Checkin preferences +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceAuthIdKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSecretTokenKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDigestStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDLastCheckinTimeKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDVersionInfoStringKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDGServicesDictionaryKey; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDeviceDataVersionKey; + +@class FIRInstanceIDCheckinPreferences; + +/** + * Register the device with Checkin Service and get back the `authID`, `secret + * token` etc. for the client. Checkin results are cached in the + * `FIRInstanceIDCache` and periodically refreshed to prevent them from being stale. + * Each client needs to register with checkin before registering with InstanceID. + */ +@interface FIRInstanceIDCheckinService : NSObject + +/** + * Execute a device checkin request to obtain an deviceID, secret token, + * gService data. + * + * @param existingCheckin An existing checkin preference object, if available. + * @param completion Completion hander called on success or failure of device checkin. + */ +- (void)checkinWithExistingCheckin:(nullable FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion; + +/** + * This would stop any request that the service made to the checkin backend and also + * release any callback handlers that it holds. + */ +- (void)stopFetching; + +/** + * Set test block for mock testing network requests. + * + * @param block The block to invoke as a mock response from the network. + */ ++ (void)setCheckinTestBlock:(nullable FIRInstanceIDURLRequestTestBlock)block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m new file mode 100644 index 0000000..d3ace54 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinService.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinService.h" + +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kDeviceCheckinURL = @"https://device-provisioning.googleapis.com/checkin"; + +// keys in Checkin preferences +NSString *const kFIRInstanceIDDeviceAuthIdKey = @"GMSInstanceIDDeviceAuthIdKey"; +NSString *const kFIRInstanceIDSecretTokenKey = @"GMSInstanceIDSecretTokenKey"; +NSString *const kFIRInstanceIDDigestStringKey = @"GMSInstanceIDDigestKey"; +NSString *const kFIRInstanceIDLastCheckinTimeKey = @"GMSInstanceIDLastCheckinTimestampKey"; +NSString *const kFIRInstanceIDVersionInfoStringKey = @"GMSInstanceIDVersionInfo"; +NSString *const kFIRInstanceIDGServicesDictionaryKey = @"GMSInstanceIDGServicesData"; +NSString *const kFIRInstanceIDDeviceDataVersionKey = @"GMSInstanceIDDeviceDataVersion"; + +static NSUInteger const kCheckinType = 2; // DeviceType IOS in l/w/a/_checkin.proto +static NSUInteger const kCheckinVersion = 2; +static NSUInteger const kFragment = 0; + +static FIRInstanceIDURLRequestTestBlock testBlock; + +@interface FIRInstanceIDCheckinService () + +@property(nonatomic, readwrite, strong) NSURLSession *session; + +@end + +@implementation FIRInstanceIDCheckinService +; + +- (instancetype)init { + self = [super init]; + if (self) { + // Create an URLSession once, even though checkin should happen about once a day + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + config.allowsCellularAccess = YES; + _session = [NSURLSession sessionWithConfiguration:config]; + _session.sessionDescription = @"com.google.iid-checkin"; + } + return self; +} + +- (void)dealloc { + testBlock = nil; + [self.session invalidateAndCancel]; +} + +- (void)checkinWithExistingCheckin:(FIRInstanceIDCheckinPreferences *)existingCheckin + completion:(FIRInstanceIDDeviceCheckinCompletion)completion { + if (self.session == nil) { + FIRInstanceIDLoggerError(kFIRInstanceIDInvalidNetworkSession, + @"Inconsistent state: NSURLSession has been invalidated"); + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]; + if (completion) { + completion(nil, error); + } + return; + } + + NSURL *url = [NSURL URLWithString:kDeviceCheckinURL]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setValue:@"application/json" forHTTPHeaderField:@"content-type"]; + NSDictionary *checkinParameters = [self checkinParametersWithExistingCheckin:existingCheckin]; + NSData *checkinData = [NSJSONSerialization dataWithJSONObject:checkinParameters + options:0 + error:nil]; + request.HTTPMethod = @"POST"; + request.HTTPBody = checkinData; + + void (^handler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService000, + @"Device checkin HTTP fetch error. Error Code: %ld", + (long)error.code); + if (completion) { + completion(nil, error); + } + return; + } + + NSError *serializationError; + NSDictionary *dataResponse = [NSJSONSerialization JSONObjectWithData:data + options:0 + error:&serializationError]; + if (serializationError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService001, + @"Error serializing json object. Error Code: %ld", + _FIRInstanceID_L(serializationError.code)); + if (completion) { + completion(nil, serializationError); + } + return; + } + + NSString *deviceAuthID = [dataResponse[@"android_id"] stringValue]; + NSString *secretToken = [dataResponse[@"security_token"] stringValue]; + if ([deviceAuthID length] == 0) { + NSError *error = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidRequest]; + if (completion) { + completion(nil, error); + } + return; + } + + int64_t lastCheckinTimestampMillis = [dataResponse[@"time_msec"] longLongValue]; + int64_t currentTimestampMillis = FIRInstanceIDCurrentTimestampInMilliseconds(); + // Somehow the server clock gets out of sync with the device clock. + // Reset the last checkin timestamp in case this happens. + if (lastCheckinTimestampMillis > currentTimestampMillis) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeService002, @"Invalid last checkin timestamp %@ in future.", + [NSDate dateWithTimeIntervalSince1970:lastCheckinTimestampMillis / 1000.0]); + lastCheckinTimestampMillis = currentTimestampMillis; + } + + NSString *deviceDataVersionInfo = dataResponse[@"device_data_version_info"] ?: @""; + NSString *digest = dataResponse[@"digest"] ?: @""; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService003, + @"Checkin successful with authId: %@, " + @"digest: %@, " + @"lastCheckinTimestamp: %lld", + deviceAuthID, digest, lastCheckinTimestampMillis); + + NSString *versionInfo = dataResponse[@"version_info"] ?: @""; + NSMutableDictionary *gservicesData = [NSMutableDictionary dictionary]; + + // Read gServices data. + NSArray *flatSettings = dataResponse[@"setting"]; + for (NSDictionary *dict in flatSettings) { + if (dict[@"name"] && dict[@"value"]) { + gservicesData[dict[@"name"]] = dict[@"value"]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDInvalidSettingResponse, + @"Invalid setting in checkin response: (%@: %@)", + dict[@"name"], dict[@"value"]); + } + } + + FIRInstanceIDCheckinPreferences *checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:deviceAuthID + secretToken:secretToken]; + NSDictionary *preferences = @{ + kFIRInstanceIDDigestStringKey : digest, + kFIRInstanceIDVersionInfoStringKey : versionInfo, + kFIRInstanceIDLastCheckinTimeKey : @(lastCheckinTimestampMillis), + kFIRInstanceIDGServicesDictionaryKey : gservicesData, + kFIRInstanceIDDeviceDataVersionKey : deviceDataVersionInfo, + }; + [checkinPreferences updateWithCheckinPlistContents:preferences]; + if (completion) { + completion(checkinPreferences, nil); + } + }; + // Test block + if (testBlock) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService005, + @"Test block set, will not hit the server"); + testBlock(request, handler); + return; + } + + NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:handler]; + [task resume]; +} + +- (void)stopFetching { + [self.session invalidateAndCancel]; + // The session cannot be reused after invalidation. Dispose it to prevent accident reusing. + self.session = nil; +} + +#pragma mark - Private + +- (NSDictionary *)checkinParametersWithExistingCheckin: + (nullable FIRInstanceIDCheckinPreferences *)checkinPreferences { + NSString *deviceModel = FIRInstanceIDDeviceModel(); + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + NSString *osVersion = [NSString stringWithFormat:@"IOS_%@", systemVersion]; + + // Get locale from GCM if GCM exists else use system API. + NSString *locale = FIRInstanceIDCurrentLocale(); + + NSInteger userNumber = 0; // Multi Profile may change this. + NSInteger userSerialNumber = 0; // Multi Profile may change this + + NSString *timeZone = [NSTimeZone localTimeZone].name; + int64_t lastCheckingTimestampMillis = checkinPreferences.lastCheckinTimestampMillis; + + NSDictionary *checkinParameters = @{ + @"checkin" : @{ + @"iosbuild" : @{@"model" : deviceModel, @"os_version" : osVersion}, + @"type" : @(kCheckinType), + @"user_number" : @(userNumber), + @"last_checkin_msec" : @(lastCheckingTimestampMillis), + }, + @"fragment" : @(kFragment), + @"locale" : locale, + @"version" : @(kCheckinVersion), + @"digest" : checkinPreferences.digest ?: @"", + @"time_zone" : timeZone, + @"user_serial_number" : @(userSerialNumber), + @"id" : @([checkinPreferences.deviceID longLongValue]), + @"security_token" : @([checkinPreferences.secretToken longLongValue]), + }; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeService006, @"Checkin parameters: %@", + checkinParameters); + return checkinParameters; +} + ++ (void)setCheckinTestBlock:(FIRInstanceIDURLRequestTestBlock)block { + testBlock = [block copy]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h new file mode 100644 index 0000000..5e1b119 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.h @@ -0,0 +1,108 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; + +// These values exposed for testing +extern NSString *const kFIRInstanceIDCheckinKeychainService; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount; +extern NSString *const kFIRInstanceIDLegacyCheckinKeychainService; + +/** + * Checkin preferences backing store. + */ +@interface FIRInstanceIDCheckinStore : NSObject + +/** + * Designated Initializer. Initialize a checkin store with the given backup excluded + * plist filename. + * + * @param checkinFilename The backup excluded plist filename to persist checkin + * preferences. + * + * @param subDirectoryName Sub-directory in standard directory where we write + * InstanceID plist. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName; + +/** + * Initialize a checkin store with the given backup excluded plist and keychain. + * + * @param plist The backup excluded plist to persist checkin preferences. + * @param keychain The keychain used to persist checkin auth preferences. + * + * @return Store to persist checkin preferences. + */ +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain; + +/** + * Checks whether the backup excluded checkin preferences are present on the disk or not. + * + * @return YES if the backup excluded checkin plist exists on the disks else NO. + */ +- (BOOL)hasCheckinPlist; + +#pragma mark - Save + +/** + * Save the checkin preferences to backing store. + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler; + +#pragma mark - Delete + +/** + * Remove the cached checkin preferences. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler; + +#pragma mark - Get + +/** + * Get the cached device secret. If we cannot access it for some reason we + * return the appropriate error object. + * + * @return The cached checkin preferences if present else nil. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Migrate the checkin item from old service/account to the new one. + * The new account is dynamic as it uses bundle ID. + * This is to ensure checkin is not shared across apps, but still the same + * if app has used GCM before. + * This call should only happen once. + * + */ +- (void)migrateCheckinItemIfNeeded; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m new file mode 100644 index 0000000..1142778 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCheckinStore.m @@ -0,0 +1,236 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCheckinStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDBackupExcludedPlist.h" +#import "FIRInstanceIDCheckinPreferences+Internal.h" +#import "FIRInstanceIDCheckinPreferences_Private.h" +#import "FIRInstanceIDCheckinService.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" +#import "FIRInstanceIDVersionUtilities.h" +#import "NSError+FIRInstanceID.h" + +static NSString *const kFIRInstanceIDCheckinKeychainGeneric = @"com.google.iid"; + +NSString *const kFIRInstanceIDCheckinKeychainService = @"com.google.iid.checkin"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainAccount = @"com.google.iid.checkin-account"; +NSString *const kFIRInstanceIDLegacyCheckinKeychainService = @"com.google.iid.checkin-service"; + +// Checkin plist used to have the deviceID and secret stored in them and that's why they +// had 6 items in it. Since the deviceID and secret have been moved to the keychain +// there would only be 4 items. +static const NSInteger kOldCheckinPlistCount = 6; + +@interface FIRInstanceIDCheckinStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; +// Checkin will store items under +// Keychain account: , +// Keychain service: |kFIRInstanceIDCheckinKeychainService| +@property(nonatomic, readonly) NSString *bundleIdentifierForKeychainAccount; + +@end + +@implementation FIRInstanceIDCheckinStore + +- (instancetype)initWithCheckinPlistFileName:(NSString *)checkinFilename + subDirectoryName:(NSString *)subDirectoryName { + FIRInstanceIDBackupExcludedPlist *plist = + [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:checkinFilename + subDirectory:subDirectoryName]; + + FIRInstanceIDAuthKeychain *keychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDCheckinKeychainGeneric]; + return [self initWithCheckinPlist:plist keychain:keychain]; +} + +- (instancetype)initWithCheckinPlist:(FIRInstanceIDBackupExcludedPlist *)plist + keychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _plist = plist; + _keychain = keychain; + } + return self; +} + +- (BOOL)hasCheckinPlist { + return [self.plist doesFileExist]; +} + +- (NSString *)bundleIdentifierForKeychainAccount { + static NSString *bundleIdentifier; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundleIdentifier = FIRInstanceIDAppIdentifier(); + }); + return bundleIdentifier; +} + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + NSDictionary *checkinPlistContents = [preferences checkinPlistContents]; + NSString *checkinKeychainContent = [preferences checkinKeychainContent]; + + if (![checkinKeychainContent length]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore000, + @"Failed to get checkin keychain content from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + if (![checkinPlistContents count]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore001, + @"Failed to get checkin plist contents from memory."); + if (handler) { + handler([NSError + errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn]); + } + return; + } + + // Save all other checkin preferences in a plist + NSError *error; + if (![self.plist writeDictionary:checkinPlistContents error:&error]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStore003, + @"Failed to save checkin plist contents." + @"Will delete auth credentials"); + [self.keychain removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + if (handler) { + handler(error); + } + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistSaved, + @"Checkin plist file is saved"); + + // Save the deviceID and secret in the Keychain + if (!preferences.hasPreCachedAuthCredentials) { + NSData *data = [checkinKeychainContent dataUsingEncoding:NSUTF8StringEncoding]; + [self.keychain setData:data + forService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + if (error) { + if (handler) { + handler(error); + } + return; + } + if (handler) { + handler(nil); + } + }]; + } else { + handler(nil); + } +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *error))handler { + // Delete the checkin preferences plist first to avoid delay. + NSError *deletePlistError; + if (![self.plist deleteFile:&deletePlistError]) { + handler(deletePlistError); + return; + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeCheckinStoreCheckinPlistDeleted, + @"Deleted checkin plist file."); + // Remove deviceID and secret from Keychain + [self.keychain + removeItemsMatchingService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:^(NSError *error) { + // Try to remove from old location as well because migration + // is no longer needed. Consider this is either a fresh install + // or an identity wipe. + [self.keychain + removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + handler(error); + }]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + // Query the keychain for deviceID and secret + NSData *item = [self.keychain dataForService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount]; + + // Check info found in keychain + NSString *checkinKeychainContent = [[NSString alloc] initWithData:item + encoding:NSUTF8StringEncoding]; + FIRInstanceIDCheckinPreferences *checkinPreferences = + [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:checkinKeychainContent]; + + NSDictionary *checkinPlistContents = [self.plist contentAsDictionary]; + + NSString *plistDeviceAuthID = checkinPlistContents[kFIRInstanceIDDeviceAuthIdKey]; + NSString *plistSecretToken = checkinPlistContents[kFIRInstanceIDSecretTokenKey]; + + // If deviceID and secret not found in the keychain verify that we don't have them in the + // checkin preferences plist. + if (![checkinPreferences.deviceID length] && ![checkinPreferences.secretToken length]) { + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + // Couldn't find checkin credentials in keychain but found them in the plist. + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } else { + // Couldn't find checkin credentials in keychain nor plist + return nil; + } + } else if (kOldCheckinPlistCount == checkinPlistContents.count) { + // same check as above but just to be extra sure that we cover all upgrade cases properly. + // TODO(chliangGoogle): Remove this case, after verifying it's not needed + if ([plistDeviceAuthID length] && [plistSecretToken length]) { + checkinPreferences = + [[FIRInstanceIDCheckinPreferences alloc] initWithDeviceID:plistDeviceAuthID + secretToken:plistSecretToken]; + } + } + + [checkinPreferences updateWithCheckinPlistContents:checkinPlistContents]; + return checkinPreferences; +} + +- (void)migrateCheckinItemIfNeeded { + // Check for checkin in the old location, using the legacy keys + // Query the keychain for deviceID and secret + NSData *dataInOldLocation = + [self.keychain dataForService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount]; + if (dataInOldLocation) { + // Save to new location + [self.keychain setData:dataInOldLocation + forService:kFIRInstanceIDCheckinKeychainService + account:self.bundleIdentifierForKeychainAccount + handler:nil]; + // Remove from old location + [self.keychain removeItemsMatchingService:kFIRInstanceIDLegacyCheckinKeychainService + account:kFIRInstanceIDLegacyCheckinKeychainAccount + handler:nil]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h new file mode 100644 index 0000000..dcb5429 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A generic class to combine several handler blocks into a single block in a thread-safe manner + */ +@interface FIRInstanceIDCombinedHandler : NSObject + +- (void)addHandler:(void (^)(ResultType _Nullable result, NSError* _Nullable error))handler; +- (void (^)(ResultType _Nullable result, NSError* _Nullable error))combinedHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m new file mode 100644 index 0000000..bc6be6c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDCombinedHandler.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDCombinedHandler.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRInstanseIDHandler)(id _Nullable result, NSError *_Nullable error); + +@interface FIRInstanceIDCombinedHandler () +@property(atomic, readonly, strong) NSMutableArray *handlers; +@end + +NS_ASSUME_NONNULL_END + +@implementation FIRInstanceIDCombinedHandler + +- (instancetype)init { + self = [super init]; + if (self) { + _handlers = [NSMutableArray array]; + } + return self; +} + +- (void)addHandler:(FIRInstanseIDHandler)handler { + if (!handler) { + return; + } + + @synchronized(self) { + [self.handlers addObject:handler]; + } +} + +- (FIRInstanseIDHandler)combinedHandler { + FIRInstanseIDHandler combinedHandler = nil; + + @synchronized(self) { + NSArray *handlers = [self.handlers copy]; + combinedHandler = ^(id result, NSError *error) { + for (FIRInstanseIDHandler handler in handlers) { + handler(result, error); + } + }; + } + + return combinedHandler; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h new file mode 100644 index 0000000..cd2e131 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#pragma mark - Commands + +/** + * Value included in a structured response or GCM message from IID, indicating + * an identity reset. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceID_CMD_RST; + +#pragma mark - Notifications + +/// Notification used to deliver GCM messages for InstanceID. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDCheckinFetchedNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAPNSTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenNotification; +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDIdentityInvalidatedNotification; + +#pragma mark - Miscellaneous + +/// The scope used to save the IID "*" scope token. This is used for saving the +/// IID auth token that we receive from the server. This feature was never +/// implemented on the server side. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAllScopeIdentifier; +/// The scope used to save the IID "*" scope token. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDefaultTokenScope; + +/// Subdirectory in search path directory to store InstanceID preferences. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDSubDirectoryName; + +/// The key for APNS token in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSKey; + +/// The key for APNS token environment type in options dictionary. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey; + +/// The key for GMP AppID sent in registration requests. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey; + +/// The key to enable auto-register by swizzling AppDelegate's methods. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey; + +/// Error code for missing entitlements in Keychain. iOS Keychain error +/// https://forums.developer.apple.com/thread/4743 +FOUNDATION_EXPORT const int kFIRInstanceIDSecMissingEntitlementErrorCode; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m new file mode 100644 index 0000000..81f4620 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDConstants.m @@ -0,0 +1,46 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDConstants.h" + +// Commands +NSString *const kFIRInstanceID_CMD_RST = @"RST"; + +// NOTIFICATIONS +NSString *const kFIRInstanceIDCheckinFetchedNotification = @"com.google.gcm.notif-checkin-fetched"; +NSString *const kFIRInstanceIDAPNSTokenNotification = @"com.firebase.iid.notif.apns-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenNotification = @"com.firebase.iid.notif.fcm-token"; +NSString *const kFIRInstanceIDDefaultGCMTokenFailNotification = + @"com.firebase.iid.notif.fcm-token-fail"; + +NSString *const kFIRInstanceIDIdentityInvalidatedNotification = @"com.google.iid.identity-invalid"; + +// Miscellaneous +NSString *const kFIRInstanceIDAllScopeIdentifier = @"iid-all"; +NSString *const kFIRInstanceIDDefaultTokenScope = @"*"; +NSString *const kFIRInstanceIDSubDirectoryName = @"Google/FirebaseInstanceID"; + +// Registration Options +NSString *const kFIRInstanceIDTokenOptionsAPNSKey = @"apns_token"; +NSString *const kFIRInstanceIDTokenOptionsAPNSIsSandboxKey = @"apns_sandbox"; +NSString *const kFIRInstanceIDTokenOptionsFirebaseAppIDKey = @"gmp_app_id"; + +NSString *const kFIRInstanceIDAppDelegateProxyEnabledInfoPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +// iOS Keychain error https://forums.developer.apple.com/thread/4743 +// An undocumented error code hence need to be redeclared. +const int kFIRInstanceIDSecMissingEntitlementErrorCode = -34018; diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h new file mode 100644 index 0000000..ccc25b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDDefines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIRInstanceIDLib_FIRInstanceIDDefines_h +#define FIRInstanceIDLib_FIRInstanceIDDefines_h + +#define _FIRInstanceID_VERBOSE_LOGGING 1 + +// Verbose Logging +#if (_FIRInstanceID_VERBOSE_LOGGING) +#define FIRInstanceID_DEV_VERBOSE_LOG(...) NSLog(__VA_ARGS__) +#else +#define FIRInstanceID_DEV_VERBOSE_LOG(...) \ + do { \ + } while (0) +#endif // VERBOSE_LOGGING + +// WEAKIFY & STRONGIFY +// Helper macro. +#define _FIRInstanceID_WEAKNAME(VAR) VAR##_weak_ + +#define FIRInstanceID_WEAKIFY(VAR) __weak __typeof__(VAR) _FIRInstanceID_WEAKNAME(VAR) = (VAR); + +#define FIRInstanceID_STRONGIFY(VAR) \ + _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wshadow\"") \ + __strong __typeof__(VAR) VAR = _FIRInstanceID_WEAKNAME(VAR); \ + _Pragma("clang diagnostic pop") + +// Type Conversions (used for NSInteger etc) +#ifndef _FIRInstanceID_L +#define _FIRInstanceID_L(v) (long)(v) +#endif + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h new file mode 100644 index 0000000..1c80d8e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/* The Keychain error domain */ +extern NSString *const kFIRInstanceIDKeychainErrorDomain; + +/* + * Wrapping the keychain operations in a serialize queue. This is to avoid keychain operation + * blocking main queue. + */ +@interface FIRInstanceIDKeychain : NSObject + +/** + * FIRInstanceIDKeychain. + * + * @return A shared instance of FIRInstanceIDKeychain. + */ ++ (instancetype)sharedInstance; + +/** + * Get keychain items matching the given a query. + * + * @param keychainQuery The keychain query. + * + * @return An CFTypeRef result matching the provided inputs. + */ +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery; + +/** + * Remove the cached items from the keychain matching the query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the remove operation is + * complete, with an error if there is any. + */ +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *error))handler; + +/** + * Add the item with a given query. + * + * @param keychainQuery The keychain query. + * @param handler The callback handler which is invoked when the add operation is + * complete, with an error if there is any. + */ +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m new file mode 100644 index 0000000..df1b4f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDKeychain.m @@ -0,0 +1,114 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDKeychain.h" + +#import "FIRInstanceIDLogger.h" + +NSString *const kFIRInstanceIDKeychainErrorDomain = @"com.google.iid"; + +@interface FIRInstanceIDKeychain () { + dispatch_queue_t _keychainOperationQueue; +} + +@end + +@implementation FIRInstanceIDKeychain + ++ (instancetype)sharedInstance { + static FIRInstanceIDKeychain *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[FIRInstanceIDKeychain alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _keychainOperationQueue = + dispatch_queue_create("com.google.FirebaseInstanceID.Keychain", DISPATCH_QUEUE_SERIAL); + } + return self; +} + +- (CFTypeRef)itemWithQuery:(NSDictionary *)keychainQuery { + __block SecKeyRef keyRef = NULL; + dispatch_sync(_keychainOperationQueue, ^{ + OSStatus status = + SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyRef); + + if (status != noErr) { + if (keyRef) { + CFRelease(keyRef); + } + FIRInstanceIDLoggerDebug(kFIRInstanceIDKeychainReadItemError, + @"Info is not found in Keychain. OSStatus: %d. Keychain query: %@", + (int)status, keychainQuery); + } + }); + return keyRef; +} + +- (void)removeItemWithQuery:(NSDictionary *)keychainQuery + handler:(void (^)(NSError *error))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery); + if (status != noErr) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDKeychainDeleteItemError, + @"Couldn't delete item from Keychain OSStatus: %d with the keychain query %@", + (int)status, keychainQuery); + } + + if (handler) { + NSError *error; + // When item is not found, it should NOT be considered as an error. The operation should + // continue. + if (status != noErr && status != errSecItemNotFound) { + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +- (void)addItemWithQuery:(NSDictionary *)keychainQuery handler:(void (^)(NSError *))handler { + dispatch_async(_keychainOperationQueue, ^{ + OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL); + + if (handler) { + NSError *error; + if (status != noErr) { + FIRInstanceIDLoggerWarning(kFIRInstanceIDKeychainAddItemError, + @"Couldn't add item to Keychain OSStatus: %d", (int)status); + error = [NSError errorWithDomain:kFIRInstanceIDKeychainErrorDomain + code:status + userInfo:nil]; + } + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + } + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h new file mode 100644 index 0000000..ab93976 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.h @@ -0,0 +1,66 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRIMessageCode.h" + +// The convenience macros are only defined if they haven't already been defined. +#ifndef FIRInstanceIDLoggerInfo + +// Convenience macros that log to the shared GTMLogger instance. These macros +// are how users should typically log to FIRInstanceIDLogger. +#define FIRInstanceIDLoggerDebug(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncDebug:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerInfo(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncInfo:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerNotice(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncNotice:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerWarning(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncWarning:__func__ messageCode:code msg:__VA_ARGS__] +#define FIRInstanceIDLoggerError(code, ...) \ + [FIRInstanceIDSharedLogger() logFuncError:__func__ messageCode:code msg:__VA_ARGS__] + +#endif // !defined(FIRInstanceIDLoggerInfo) + +@interface FIRInstanceIDLogger : NSObject + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... NS_FORMAT_FUNCTION(3, 4); + +@end + +/** + * Instantiates and/or returns a shared GTMLogger used exclusively + * for InstanceID log messages. + * @return the shared GTMLogger instance + */ +FIRInstanceIDLogger *FIRInstanceIDSharedLogger(void); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m new file mode 100644 index 0000000..2600d3b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDLogger.m @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDLogger.h" + +#import + +// Re-definition of FIRLogger service, as it is not included in :FIRAppHeaders target +NSString *const kFIRInstanceIDLoggerService = @"[Firebase/InstanceID]"; + +@implementation FIRInstanceIDLogger + +#pragma mark - Log Helpers + ++ (NSString *)formatMessageCode:(FIRInstanceIDMessageCode)messageCode { + return [NSString stringWithFormat:@"I-IID%06ld", (long)messageCode]; +} + +- (void)logFuncDebug:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelDebug, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncInfo:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelInfo, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncNotice:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelNotice, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncWarning:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelWarning, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +- (void)logFuncError:(const char *)func + messageCode:(FIRInstanceIDMessageCode)messageCode + msg:(NSString *)fmt, ... { + va_list args; + va_start(args, fmt); + FIRLogBasic(FIRLoggerLevelError, kFIRInstanceIDLoggerService, + [FIRInstanceIDLogger formatMessageCode:messageCode], fmt, args); + va_end(args); +} + +@end + +FIRInstanceIDLogger *FIRInstanceIDSharedLogger() { + static dispatch_once_t onceToken; + static FIRInstanceIDLogger *logger; + dispatch_once(&onceToken, ^{ + logger = [[FIRInstanceIDLogger alloc] init]; + }); + + return logger; +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h new file mode 100644 index 0000000..d1f2634 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.h @@ -0,0 +1,183 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDBackupExcludedPlist; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDCheckinStore; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDTokenStore; + +@class FIRInstanceIDStore; +@protocol FIRInstanceIDStoreDelegate + +/** + * This is called when the store has decided to invalide its tokens associated with the + * previous checkin credentials. After deleting the tokens locally, it calls this method + * to notify the delegate of the change. If possible, the delegate should use this time + * to request the invalidation of the tokens on the server as well. + */ +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +@end + +/** + * Used to persist the InstanceID tokens. This is also used to cache the Checkin + * credentials. The store also checks for stale entries in the store and + * let's us know if things in the store are stale or not. It does not however + * acts on stale entries in anyway. + */ +@interface FIRInstanceIDStore : NSObject + +/** + * The delegate set in the initializer which is notified of changes in the store. + */ +@property(nonatomic, readonly, weak) NSObject *delegate; + +- (instancetype)init __attribute__((unavailable("Use initWithDelegate: instead."))); + +/** + * Initialize a default store to persist InstanceID tokens and options. + * + * @param delegate The delegate with which to be notified of changes in the store. + * @return Store to persist InstanceID tokens. + */ +- (instancetype)initWithDelegate:(NSObject *)delegate; + +/** + * Initialize a store with the token store used to persist tokens, and a checkin store. + * Used for testing. + * + * @param checkinStore Persistent store that persists checkin preferences. + * @param tokenStore Persistent store that persists tokens. + * + * @return Store to persist InstanceID tokens and options. + */ +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate + NS_DESIGNATED_INITIALIZER; + +#pragma mark - Save +/** + * Save the instanceID token info to the store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo handler:(void (^)(NSError *))handler; + +#pragma mark - Get + +/** + * Get the cached token info. + * + * @param authorizedEntity The authorized entity for which we want the token. + * @param scope The scope for which we want the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * returns nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Delete + +/** + * Remove the cached token for a given authorizedEntity and scope. If the token was never + * cached or deleted from the cache before this is a no-op. + * + * @param authorizedEntity The authorizedEntity for the cached token. + * @param scope The scope for the cached token + */ +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Removes all cached tokens from the persistent store. In case deleting the cached tokens + * fails we try to delete the backup excluded plist that stores the tokens. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + * + */ +- (void)removeAllCachedTokensWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Persisting Checkin Preferences + +/** + * Save the checkin preferences + * + * @param preferences Checkin preferences to save. + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(nullable void (^)(NSError *error))handler; + +/** + * Return the cached checkin preferences. + * + * @return Checkin preferences. + */ +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences; + +/** + * Remove the cached checkin preferences from the store. + * + * @param handler The callback handler which is invoked when the operation is complete, + * with an error if there is any. + */ +- (void)removeCheckinPreferencesWithHandler:(nullable void (^)(NSError *error))handler; + +#pragma mark - Standard Directory sub-directory + +/** + * Check if supported directory has InstanceID subdirectory + * + * @return YES if the Application Support directory has InstanceID subdirectory else NO. + */ ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName; + +/** + * Create InstanceID subdirectory in Application support directory. + * + * @return YES if the subdirectory was created successfully else NO. + */ ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName; + +/** + * Removes Application Support subdirectory for InstanceID. + * + * @param error The error object if any while trying to delete the sub-directory. + * + * @return YES if the deletion was successful else NO. + */ ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m new file mode 100644 index 0000000..1c7a0d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStore.m @@ -0,0 +1,242 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDStore.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDCheckinStore.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenStore.h" +#import "FIRInstanceIDVersionUtilities.h" + +// NOTE: These values should be in sync with what InstanceID saves in as. +static NSString *const kCheckinFileName = @"g-checkin"; + +// APNS token (use the old key value i.e. with prefix GMS) +static NSString *const kFIRInstanceIDLibraryVersion = @"GMSInstanceID-version"; + +@interface FIRInstanceIDStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinStore *checkinStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDTokenStore *tokenStore; + +@end + +@implementation FIRInstanceIDStore + +- (instancetype)initWithDelegate:(NSObject *)delegate { + FIRInstanceIDCheckinStore *checkinStore = [[FIRInstanceIDCheckinStore alloc] + initWithCheckinPlistFileName:kCheckinFileName + subDirectoryName:kFIRInstanceIDSubDirectoryName]; + + FIRInstanceIDTokenStore *tokenStore = [FIRInstanceIDTokenStore defaultStore]; + + return [self initWithCheckinStore:checkinStore tokenStore:tokenStore delegate:delegate]; +} + +- (instancetype)initWithCheckinStore:(FIRInstanceIDCheckinStore *)checkinStore + tokenStore:(FIRInstanceIDTokenStore *)tokenStore + delegate:(NSObject *)delegate { + self = [super init]; + if (self) { + _checkinStore = checkinStore; + _tokenStore = tokenStore; + _delegate = delegate; + [self resetCredentialsIfNeeded]; + } + return self; +} + +#pragma mark - Upgrades + ++ (BOOL)hasSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return NO; + } else if (!isDirectory) { + return NO; + } + return YES; +} + ++ (NSSearchPathDirectory)supportedDirectory { +#if TARGET_OS_TV + return NSCachesDirectory; +#else + return NSApplicationSupportDirectory; +#endif +} + ++ (NSString *)pathForSupportSubDirectory:(NSString *)subDirectoryName { + NSArray *directoryPaths = + NSSearchPathForDirectoriesInDomains([self supportedDirectory], NSUserDomainMask, YES); + NSString *dirPath = directoryPaths.lastObject; + NSArray *components = @[ dirPath, subDirectoryName ]; + return [NSString pathWithComponents:components]; +} + ++ (BOOL)createSubDirectory:(NSString *)subDirectoryName { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL hasSubDirectory; + + if (![[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&hasSubDirectory]) { + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:subDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:&error]; + if (error) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore000, + @"Cannot create directory %@, error: %@", subDirectoryPath, error); + return NO; + } + } else { + if (!hasSubDirectory) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore001, + @"Found file instead of directory at %@", subDirectoryPath); + return NO; + } + } + return YES; +} + ++ (BOOL)removeSubDirectory:(NSString *)subDirectoryName error:(NSError **)error { + if ([self hasSubDirectory:subDirectoryName]) { + NSString *subDirectoryPath = [self pathForSupportSubDirectory:subDirectoryName]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:subDirectoryPath + isDirectory:&isDirectory]) { + return [[NSFileManager defaultManager] removeItemAtPath:subDirectoryPath error:error]; + } + } + return YES; +} + +/** + * Reset the keychain preferences if the app had been deleted earlier and then reinstalled. + * Keychain preferences are not cleared in the above scenario so explicitly clear them. + * + * In case of an iCloud backup and restore the Keychain preferences should already be empty + * since the Keychain items are marked with `*BackupThisDeviceOnly`. + */ +- (void)resetCredentialsIfNeeded { + BOOL checkinPlistExists = [self.checkinStore hasCheckinPlist]; + // Checkin info existed in backup excluded plist. Should not be a fresh install. + if (checkinPlistExists) { + // FCM user can still have the old version of checkin, migration should only happen once. + [self.checkinStore migrateCheckinItemIfNeeded]; + return; + } + + // reset checkin in keychain if a fresh install. + // set the old checkin preferences to unregister pre-registered tokens + FIRInstanceIDCheckinPreferences *oldCheckinPreferences = + [self.checkinStore cachedCheckinPreferences]; + + if (oldCheckinPreferences) { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (!error) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeStore002, + @"Removed cached checkin preferences from Keychain because this is a fresh install."); + } else { + FIRInstanceIDLoggerError( + kFIRInstanceIDMessageCodeStore003, + @"Couldn't remove cached checkin preferences for a fresh install. Error: %@", error); + } + if (oldCheckinPreferences.deviceID.length && oldCheckinPreferences.secretToken.length) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore006, + @"App reset detected. Will delete server registrations."); + // We don't really need to delete old FCM tokens created via IID auth tokens since + // those tokens are already hashed by APNS token as the has so creating a new + // token should automatically delete the old-token. + [self.delegate store:self didDeleteFCMScopedTokensForCheckin:oldCheckinPreferences]; + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeStore009, + @"App reset detected but no valid checkin auth preferences found." + @" Will not delete server registrations."); + } + }]; + } +} + +#pragma mark - Get + +- (FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + // TODO(chliangGoogle): If we don't have the token plist we should delete all the tokens from + // the keychain. This is because not having the plist signifies a backup and restore operation. + // In case the keychain has any tokens these would now be stale and therefore should be + // deleted. + if (![authorizedEntity length] || ![scope length]) { + return nil; + } + FIRInstanceIDTokenInfo *info = [self.tokenStore tokenInfoWithAuthorizedEntity:authorizedEntity + scope:scope]; + return info; +} + +- (NSArray *)cachedTokenInfos { + return [self.tokenStore cachedTokenInfos]; +} + +#pragma mark - Save + +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *error))handler { + [self.tokenStore saveTokenInfo:tokenInfo handler:handler]; +} + +#pragma mark - Delete + +- (void)removeCachedTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + if (![authorizedEntity length] || ![scope length]) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeStore012, + @"Will not delete token with invalid entity: %@, scope: %@", + authorizedEntity, scope); + return; + } + [self.tokenStore removeTokenWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)removeAllCachedTokensWithHandler:(void (^)(NSError *error))handler { + [self.tokenStore removeAllTokensWithHandler:handler]; +} + +#pragma mark - FIRInstanceIDCheckinCache protocol + +- (void)saveCheckinPreferences:(FIRInstanceIDCheckinPreferences *)preferences + handler:(void (^)(NSError *error))handler { + [self.checkinStore saveCheckinPreferences:preferences handler:handler]; +} + +- (FIRInstanceIDCheckinPreferences *)cachedCheckinPreferences { + return [self.checkinStore cachedCheckinPreferences]; +} + +- (void)removeCheckinPreferencesWithHandler:(void (^)(NSError *))handler { + [self.checkinStore removeCheckinPreferencesWithHandler:^(NSError *error) { + if (handler) { + handler(error); + } + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h new file mode 100644 index 0000000..8f2f369 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.h @@ -0,0 +1,66 @@ +// +// GTMStringEncoding.h +// +// Copyright 2010 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import + +// A generic class for arbitrary base-2 to 128 string encoding and decoding. +@interface FIRInstanceIDStringEncoding : NSObject { + @private + NSData *charMapData_; + char *charMap_; + int reverseCharMap_[128]; + int shift_; + unsigned int mask_; + BOOL doPad_; + char paddingChar_; + int padLen_; +} + ++ (id)rfc4648Base64WebsafeStringEncoding; + +// Create a new, autoreleased GTMStringEncoding object with the given string, +// as described below. ++ (id)stringEncodingWithString:(NSString *)string; + +// Initialize a new GTMStringEncoding object with the string. +// +// The length of the string must be a power of 2, at least 2 and at most 128. +// Only 7-bit ASCII characters are permitted in the string. +// +// These characters are the canonical set emitted during encoding. +// If the characters have alternatives (e.g. case, easily transposed) then use +// addDecodeSynonyms: to configure them. +- (id)initWithString:(NSString *)string; + +// Indicates whether padding is performed during encoding. +- (BOOL)doPad; +- (void)setDoPad:(BOOL)doPad; + +// Sets the padding character to use during encoding. +- (void)setPaddingChar:(char)c; + +// Encode a raw binary buffer to a 7-bit ASCII string. +- (NSString *)encode:(NSData *)data; + +// Decode a 7-bit ASCII string to a raw binary buffer. +- (NSData *)decode:(NSString *)string; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m new file mode 100644 index 0000000..e1ab269 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDStringEncoding.m @@ -0,0 +1,208 @@ +// +// FIRInstanceIDStringEncoding.m +// +// Copyright 2009 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy +// of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. +// + +// This is a copy of GTMStringEncoding. FIRInstanceID wants to avoid +// a CocoaPods GTM dependency. Hence we use our own version of StringEncoding. + +#import "FIRInstanceIDStringEncoding.h" + +#import "FIRInstanceIDLogger.h" + +enum { kUnknownChar = -1, kPaddingChar = -2, kIgnoreChar = -3 }; + +@implementation FIRInstanceIDStringEncoding + ++ (id)rfc4648Base64WebsafeStringEncoding { + FIRInstanceIDStringEncoding *ret = [self + stringEncodingWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]; + + [ret setPaddingChar:'=']; + [ret setDoPad:YES]; + return ret; +} + +static inline int lcm(int a, int b) { + for (int aa = a, bb = b;;) { + if (aa == bb) + return aa; + else if (aa < bb) + aa += a; + else + bb += b; + } +} + ++ (id)stringEncodingWithString:(NSString *)string { + return [[FIRInstanceIDStringEncoding alloc] initWithString:string]; +} + +- (id)initWithString:(NSString *)string { + if ((self = [super init])) { + charMapData_ = [string dataUsingEncoding:NSASCIIStringEncoding]; + if (!charMapData_) { + // Unable to convert string to ASCII + return nil; + } + charMap_ = (char *)[charMapData_ bytes]; + NSUInteger length = [charMapData_ length]; + if (length < 2 || length > 128 || length & (length - 1)) { + // Length not a power of 2 between 2 and 128 + return nil; + } + + memset(reverseCharMap_, kUnknownChar, sizeof(reverseCharMap_)); + for (unsigned int i = 0; i < length; i++) { + if (reverseCharMap_[(int)charMap_[i]] != kUnknownChar) { + // Duplicate character at |i| + return nil; + } + reverseCharMap_[(int)charMap_[i]] = i; + } + + for (NSUInteger i = 1; i < length; i <<= 1) shift_++; + mask_ = (1 << shift_) - 1; + padLen_ = lcm(8, shift_) / shift_; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"", 1 << shift_, charMapData_]; +} + +- (BOOL)doPad { + return doPad_; +} + +- (void)setDoPad:(BOOL)doPad { + doPad_ = doPad; +} + +- (void)setPaddingChar:(char)c { + paddingChar_ = c; + reverseCharMap_[(int)c] = kPaddingChar; +} + +- (NSString *)encode:(NSData *)inData { + NSUInteger inLen = [inData length]; + if (inLen <= 0) { + // Empty input + return @""; + } + unsigned char *inBuf = (unsigned char *)[inData bytes]; + NSUInteger inPos = 0; + + NSUInteger outLen = (inLen * 8 + shift_ - 1) / shift_; + if (doPad_) { + outLen = ((outLen + padLen_ - 1) / padLen_) * padLen_; + } + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + unsigned int buffer = inBuf[inPos++]; + int bitsLeft = 8; + while (bitsLeft > 0 || inPos < inLen) { + if (bitsLeft < shift_) { + if (inPos < inLen) { + buffer <<= 8; + buffer |= (inBuf[inPos++] & 0xff); + bitsLeft += 8; + } else { + int pad = shift_ - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + unsigned int idx = (buffer >> (bitsLeft - shift_)) & mask_; + bitsLeft -= shift_; + outBuf[outPos++] = charMap_[idx]; + } + + if (doPad_) { + while (outPos < outLen) outBuf[outPos++] = paddingChar_; + } + + if (outPos != outLen) { + FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferUnderflow, + @"Underflowed output buffer"); + return nil; + } + [outData setLength:outPos]; + + return [[NSString alloc] initWithData:outData encoding:NSASCIIStringEncoding]; +} + +- (NSData *)decode:(NSString *)inString { + char *inBuf = (char *)[inString cStringUsingEncoding:NSASCIIStringEncoding]; + if (!inBuf) { + // Unable to convert buffer to ASCII + return nil; + } + NSUInteger inLen = strlen(inBuf); + + NSUInteger outLen = inLen * shift_ / 8; + NSMutableData *outData = [NSMutableData dataWithLength:outLen]; + unsigned char *outBuf = (unsigned char *)[outData mutableBytes]; + NSUInteger outPos = 0; + + int buffer = 0; + int bitsLeft = 0; + BOOL expectPad = NO; + for (NSUInteger i = 0; i < inLen; i++) { + int val = reverseCharMap_[(int)inBuf[i]]; + switch (val) { + case kIgnoreChar: + break; + case kPaddingChar: + expectPad = YES; + break; + case kUnknownChar: + // Unexpected data at input pos |i| + return nil; + default: + if (expectPad) { + // Expected further padding characters + return nil; + } + buffer <<= shift_; + buffer |= val & mask_; + bitsLeft += shift_; + if (bitsLeft >= 8) { + outBuf[outPos++] = (unsigned char)(buffer >> (bitsLeft - 8)); + bitsLeft -= 8; + } + break; + } + } + + if (bitsLeft && buffer & ((1 << bitsLeft) - 1)) { + // Incomplete trailing data + return nil; + } + + // Shorten buffer if needed due to padding chars + if (outPos > outLen) { + FIRInstanceIDLoggerError(kFIRInstanceIDStringEncodingBufferOverflow, @"Overflowed buffer"); + } + [outData setLength:outPos]; + + return outData; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h new file mode 100644 index 0000000..b6723fd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h @@ -0,0 +1,31 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenDeleteOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(nullable NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(nullable NSString *)instanceID + action:(FIRInstanceIDTokenAction)action; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m new file mode 100644 index 0000000..34511c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m @@ -0,0 +1,118 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenDeleteOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +@implementation FIRInstanceIDTokenDeleteOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + self = [super initWithAction:action + forAuthorizedEntity:authorizedEntity + scope:scope + options:nil + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [FIRInstanceIDTokenOperation standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"delete" value:@"true"]]; + if (self.action == FIRInstanceIDTokenActionDeleteTokenAndIID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"iid-operation" + value:@"delete"]]; + } + if (self.authorizedEntity) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + } + // Typically we include our public key-signed url items, but in some cases (like deleting all FCM + // tokens), we don't. + if (self.instanceID.length > 0) { + [queryItems addObjectsFromArray:[self queryItemsWithInstanceID:self.instanceID]]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationFetchRequest, + @"Unregister request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationRequestError, + @"Device unregister HTTP fetch error. Error code: %ld", + _FIRInstanceID_L(error.code)); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + + if (![dataResponse hasPrefix:@"deleted="] && ![dataResponse hasPrefix:@"token="]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenDeleteOperationBadResponse, + @"Invalid unregister response %@", response); + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded token:nil error:nil]; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h new file mode 100644 index 0000000..6fa800e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseUserAgentKey; + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFirebaseHeartbeatKey; + +@interface FIRInstanceIDTokenFetchOperation : FIRInstanceIDTokenOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +@end +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m new file mode 100644 index 0000000..bdc8701 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m @@ -0,0 +1,207 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenFetchOperation.h" + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenOperation+Private.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +#import +#import + +// We can have a static int since this error should theoretically only +// happen once (for the first time). If it repeats there is something +// else that is wrong. +static int phoneRegistrationErrorRetryCount = 0; +static const int kMaxPhoneRegistrationErrorRetryCount = 10; +NSString *const kFIRInstanceIDFirebaseUserAgentKey = @"X-firebase-client"; +NSString *const kFIRInstanceIDFirebaseHeartbeatKey = @"X-firebase-client-log-type"; +NSString *const kFIRInstanceIDHeartbeatTag = @"fire-iid"; + +@implementation FIRInstanceIDTokenFetchOperation + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super initWithAction:FIRInstanceIDTokenActionFetch + forAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + if (self) { + } + return self; +} + +- (void)performTokenOperation { + NSMutableURLRequest *request = [self tokenRequest]; + NSString *checkinVersionInfo = self.checkinPreferences.versionInfo; + [request setValue:checkinVersionInfo forHTTPHeaderField:@"info"]; + [request setValue:[FIRApp firebaseUserAgent] + forHTTPHeaderField:kFIRInstanceIDFirebaseUserAgentKey]; + [request setValue:@([FIRHeartbeatInfo heartbeatCodeForTag:kFIRInstanceIDHeartbeatTag]).stringValue + forHTTPHeaderField:kFIRInstanceIDFirebaseHeartbeatKey]; + + // Build form-encoded body + NSString *deviceAuthID = self.checkinPreferences.deviceID; + NSMutableArray *queryItems = + [[self class] standardQueryItemsWithDeviceID:deviceAuthID scope:self.scope]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"sender" + value:self.authorizedEntity]]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-subtype" + value:self.authorizedEntity]]; + + [queryItems addObjectsFromArray:[self queryItemsWithInstanceID:self.instanceID]]; + + // Create query items from passed-in options + id apnsTokenData = self.options[kFIRInstanceIDTokenOptionsAPNSKey]; + id apnsSandboxValue = self.options[kFIRInstanceIDTokenOptionsAPNSIsSandboxKey]; + if ([apnsTokenData isKindOfClass:[NSData class]] && + [apnsSandboxValue isKindOfClass:[NSNumber class]]) { + NSString *APNSString = FIRInstanceIDAPNSTupleStringForTokenAndServerType( + apnsTokenData, ((NSNumber *)apnsSandboxValue).boolValue); + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsAPNSKey + value:APNSString]; + [queryItems addObject:item]; + } + id firebaseAppID = self.options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + if ([firebaseAppID isKindOfClass:[NSString class]]) { + // The name of the query item happens to be the same as the dictionary key + FIRInstanceIDURLQueryItem *item = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDTokenOptionsFirebaseAppIDKey + value:(NSString *)firebaseAppID]; + [queryItems addObject:item]; + } + + NSString *content = FIRInstanceIDQueryFromQueryItems(queryItems); + request.HTTPBody = [content dataUsingEncoding:NSUTF8StringEncoding]; + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationFetchRequest, + @"Register request to %@ content: %@", FIRInstanceIDRegisterServer(), + content); + + FIRInstanceID_WEAKIFY(self); + void (^requestHandler)(NSData *, NSURLResponse *, NSError *) = + ^(NSData *data, NSURLResponse *response, NSError *error) { + FIRInstanceID_STRONGIFY(self); + [self handleResponseWithData:data response:response error:error]; + }; + + // Test block + if (self.testBlock) { + self.testBlock(request, requestHandler); + return; + } + + NSURLSession *session = [FIRInstanceIDTokenOperation sharedURLSession]; + self.dataTask = [session dataTaskWithRequest:request completionHandler:requestHandler]; + [self.dataTask resume]; +} + +#pragma mark - Request Handling + +- (void)handleResponseWithData:(NSData *)data + response:(NSURLResponse *)response + error:(NSError *)error { + if (error) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationRequestError, + @"Token fetch HTTP error. Error Code: %ld", (long)error.code); + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSString *dataResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + + if (dataResponse.length == 0) { + NSError *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + return; + } + NSDictionary *parsedResponse = [self parseFetchTokenResponse:dataResponse]; + + if ([parsedResponse[@"token"] length]) { + [self finishWithResult:FIRInstanceIDTokenOperationSucceeded + token:parsedResponse[@"token"] + error:nil]; + return; + } + + NSString *errorValue = parsedResponse[@"Error"]; + NSError *responseError; + if (errorValue.length) { + NSArray *errorComponents = [errorValue componentsSeparatedByString:@":"]; + // HACK (Kansas replication delay), PHONE_REGISTRATION_ERROR on App + // uninstall and reinstall. + if ([errorComponents containsObject:@"PHONE_REGISTRATION_ERROR"]) { + // Encountered issue http://b/27043795 + // Retry register until successful or another error encountered or a + // certain number of tries are over. + + if (phoneRegistrationErrorRetryCount < kMaxPhoneRegistrationErrorRetryCount) { + const int nextRetryInterval = 1 << phoneRegistrationErrorRetryCount; + FIRInstanceID_WEAKIFY(self); + + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(nextRetryInterval * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + FIRInstanceID_STRONGIFY(self); + phoneRegistrationErrorRetryCount++; + [self performTokenOperation]; + }); + return; + } + } else if ([errorComponents containsObject:kFIRInstanceID_CMD_RST]) { + // Server detected the identity we use is no longer valid. + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center postNotificationName:kFIRInstanceIDIdentityInvalidatedNotification object:nil]; + + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeInternal001, + @"Identity is invalid. Server request identity reset."); + responseError = + [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidIdentity]; + } + } + if (!responseError) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenFetchOperationBadResponse, + @"Invalid fetch response, expected 'token' or 'Error' key"); + responseError = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown]; + } + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:responseError]; +} + +// expect a response e.g. "token=\nGOOG.ttl=123" +- (NSDictionary *)parseFetchTokenResponse:(NSString *)response { + NSArray *lines = [response componentsSeparatedByString:@"\n"]; + NSMutableDictionary *parsedResponse = [NSMutableDictionary dictionary]; + for (NSString *line in lines) { + NSArray *keyAndValue = [line componentsSeparatedByString:@"="]; + if ([keyAndValue count] > 1) { + parsedResponse[keyAndValue[0]] = keyAndValue[1]; + } + } + return parsedResponse; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h new file mode 100644 index 0000000..3b752a3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.h @@ -0,0 +1,92 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRInstanceIDAPNSInfo.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents an Instance ID token, and all of the relevant information + * associated with it. It can read from and write to an NSDictionary object, for + * simple serialization. + */ +@interface FIRInstanceIDTokenInfo : NSObject + +/// The authorized entity (also known as Sender ID), associated with the token. +@property(nonatomic, readonly, copy) NSString *authorizedEntity; +/// The scope associated with the token. This is an arbitrary string, typically "*". +@property(nonatomic, readonly, copy) NSString *scope; +/// The token value itself, with which all other properties are associated. +@property(nonatomic, readonly, copy) NSString *token; + +// These properties are nullable because they might not exist for tokens fetched from +// legacy storage formats. + +/// The app version that this token represents. +@property(nonatomic, readonly, copy, nullable) NSString *appVersion; +/// The Firebase app ID (also known as GMP App ID), that this token is associated with. +@property(nonatomic, readonly, copy, nullable) NSString *firebaseAppID; + +/// Tokens may not always be associated with an APNs token, and may be associated after +/// being created. +@property(nonatomic, strong, nullable) FIRInstanceIDAPNSInfo *APNSInfo; +/// The time that this token info was updated. The cache time is writeable, since in +/// some cases the token info may be refreshed from the server. In those situations, +/// the cacheTime would be updated. +@property(nonatomic, copy, nullable) NSDate *cacheTime; + +/** + * Initializes a FIRInstanceIDTokenInfo object with the required parameters. These + * parameters represent all the relevant associated data with a token. + * + * @param authorizedEntity The authorized entity (also known as Sender ID). + * @param scope The scope of the token, typically "*" meaning + * it's a "default scope". + * @param token The token value itself. + * @param appVersion The application version that this token is associated with. + * @param firebaseAppID The Firebase app ID which this token is associated with. + * @return An instance of FIRInstanceIDTokenInfo. + */ +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(nullable NSString *)appVersion + firebaseAppID:(nullable NSString *)firebaseAppID; + +/** + * Check whether the token is still fresh based on: + * 1. Last fetch token is within the 7 days. + * 2. Language setting is not changed. + * 3. App version is current. + * 4. GMP App ID is current. + * 5. token is consistent with the current IID. + * 6. APNS info has changed. + * @param IID The app identifiier that is used to check if token is prefixed with. + * @return If token is fresh. + * + */ +- (BOOL)isFreshWithIID:(NSString *)IID; + +/* + * Check whether the token is default token. + */ +- (BOOL)isDefaultToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m new file mode 100644 index 0000000..59b0e92 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenInfo.m @@ -0,0 +1,212 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenInfo.h" + +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDUtilities.h" + +/** + * @enum Token Info Dictionary Key Constants + * @discussion The keys that are checked when a token info is + * created from a dictionary. The same keys are used + * when decoding/encoding an archive. + */ +/// Specifies a dictonary key whose value represents the authorized entity, or +/// Sender ID for the token. +static NSString *const kFIRInstanceIDAuthorizedEntityKey = @"authorized_entity"; +/// Specifies a dictionary key whose value represents the scope of the token, +/// typically "*". +static NSString *const kFIRInstanceIDScopeKey = @"scope"; +/// Specifies a dictionary key which represents the token value itself. +static NSString *const kFIRInstanceIDTokenKey = @"token"; +/// Specifies a dictionary key which represents the app version associated +/// with the token. +static NSString *const kFIRInstanceIDAppVersionKey = @"app_version"; +/// Specifies a dictionary key which represents the GMP App ID associated with +/// the token. +static NSString *const kFIRInstanceIDFirebaseAppIDKey = @"firebase_app_id"; +/// Specifies a dictionary key representing an archive for a +/// `FIRInstanceIDAPNSInfo` object. +static NSString *const kFIRInstanceIDAPNSInfoKey = @"apns_info"; +/// Specifies a dictionary key representing the "last cached" time for the token. +static NSString *const kFIRInstanceIDCacheTimeKey = @"cache_time"; +/// Default interval that token stays fresh. +const NSTimeInterval kDefaultFetchTokenInterval = 7 * 24 * 60 * 60; // 7 days. + +@implementation FIRInstanceIDTokenInfo + +- (instancetype)initWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + token:(NSString *)token + appVersion:(NSString *)appVersion + firebaseAppID:(NSString *)firebaseAppID { + self = [super init]; + if (self) { + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _token = [token copy]; + _appVersion = [appVersion copy]; + _firebaseAppID = [firebaseAppID copy]; + } + return self; +} + +- (BOOL)isFreshWithIID:(NSString *)IID { + // Last fetch token cache time could be null if token is from legacy storage format. Then token is + // considered not fresh and should be refreshed and overwrite with the latest storage format. + if (!IID) { + return NO; + } + if (!_cacheTime) { + return NO; + } + + // Check if it's consistent with IID + if (![self.token hasPrefix:IID]) { + return NO; + } + + // Check if app has just been updated to a new version. + NSString *currentAppVersion = FIRInstanceIDCurrentAppVersion(); + if (!_appVersion || ![_appVersion isEqualToString:currentAppVersion]) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager004, + @"Invalidating cached token for %@ (%@) due to app version change.", + _authorizedEntity, _scope); + return NO; + } + + // Check if GMP App ID has changed + NSString *currentFirebaseAppID = FIRInstanceIDFirebaseAppID(); + if (!_firebaseAppID || ![_firebaseAppID isEqualToString:currentFirebaseAppID]) { + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenInfoFirebaseAppIDChanged, + @"Invalidating cached token due to Firebase App IID change from %@ to %@", _firebaseAppID, + currentFirebaseAppID); + return NO; + } + + // Check whether locale has changed, if yes, token needs to be updated with server for locale + // information. + if (FIRInstanceIDHasLocaleChanged()) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenInfoLocaleChanged, + @"Invalidating cached token due to locale change"); + return NO; + } + + // Locale is not changed, check whether token has been fetched within 7 days. + NSTimeInterval lastFetchTokenTimestamp = [_cacheTime timeIntervalSince1970]; + NSTimeInterval currentTimestamp = FIRInstanceIDCurrentTimestampInSeconds(); + NSTimeInterval timeSinceLastFetchToken = currentTimestamp - lastFetchTokenTimestamp; + return (timeSinceLastFetchToken < kDefaultFetchTokenInterval); +} + +- (BOOL)isDefaultToken { + return [self.scope isEqualToString:kFIRInstanceIDDefaultTokenScope]; +} + +#pragma mark - NSCoding + +- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder { + // These value cannot be nil + + id authorizedEntity = [aDecoder decodeObjectForKey:kFIRInstanceIDAuthorizedEntityKey]; + if (![authorizedEntity isKindOfClass:[NSString class]]) { + return nil; + } + + id scope = [aDecoder decodeObjectForKey:kFIRInstanceIDScopeKey]; + if (![scope isKindOfClass:[NSString class]]) { + return nil; + } + + id token = [aDecoder decodeObjectForKey:kFIRInstanceIDTokenKey]; + if (![token isKindOfClass:[NSString class]]) { + return nil; + } + + // These values are nullable, so only fail the decode if the type does not match + + id appVersion = [aDecoder decodeObjectForKey:kFIRInstanceIDAppVersionKey]; + if (appVersion && ![appVersion isKindOfClass:[NSString class]]) { + return nil; + } + + id firebaseAppID = [aDecoder decodeObjectForKey:kFIRInstanceIDFirebaseAppIDKey]; + if (firebaseAppID && ![firebaseAppID isKindOfClass:[NSString class]]) { + return nil; + } + + id rawAPNSInfo = [aDecoder decodeObjectForKey:kFIRInstanceIDAPNSInfoKey]; + if (rawAPNSInfo && ![rawAPNSInfo isKindOfClass:[NSData class]]) { + return nil; + } + + FIRInstanceIDAPNSInfo *APNSInfo = nil; + if (rawAPNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + APNSInfo = [NSKeyedUnarchiver unarchiveObjectWithData:rawAPNSInfo]; +#pragma clang diagnostic pop + } @catch (NSException *exception) { + FIRInstanceIDLoggerInfo(kFIRInstanceIDMessageCodeTokenInfoBadAPNSInfo, + @"Could not parse raw APNS Info while parsing archived token info."); + APNSInfo = nil; + } @finally { + } + } + + id cacheTime = [aDecoder decodeObjectForKey:kFIRInstanceIDCacheTimeKey]; + if (cacheTime && ![cacheTime isKindOfClass:[NSDate class]]) { + return nil; + } + + self = [super init]; + if (self) { + _authorizedEntity = authorizedEntity; + _scope = scope; + _token = token; + _appVersion = appVersion; + _firebaseAppID = firebaseAppID; + _APNSInfo = APNSInfo; + _cacheTime = cacheTime; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:self.authorizedEntity forKey:kFIRInstanceIDAuthorizedEntityKey]; + [aCoder encodeObject:self.scope forKey:kFIRInstanceIDScopeKey]; + [aCoder encodeObject:self.token forKey:kFIRInstanceIDTokenKey]; + [aCoder encodeObject:self.appVersion forKey:kFIRInstanceIDAppVersionKey]; + [aCoder encodeObject:self.firebaseAppID forKey:kFIRInstanceIDFirebaseAppIDKey]; + NSData *rawAPNSInfo; + if (self.APNSInfo) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + rawAPNSInfo = [NSKeyedArchiver archivedDataWithRootObject:self.APNSInfo]; +#pragma clang diagnostic pop + + [aCoder encodeObject:rawAPNSInfo forKey:kFIRInstanceIDAPNSInfoKey]; + } + [aCoder encodeObject:self.cacheTime forKey:kFIRInstanceIDCacheTimeKey]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h new file mode 100644 index 0000000..46e1ac8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.h @@ -0,0 +1,149 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" + +@class FIRInstanceIDAuthService; +@class FIRInstanceIDCheckinPreferences; +@class FIRInstanceIDTokenInfo; +@class FIRInstanceIDStore; + +typedef NS_OPTIONS(NSUInteger, FIRInstanceIDInvalidTokenReason) { + FIRInstanceIDInvalidTokenReasonNone = 0, // 0 + FIRInstanceIDInvalidTokenReasonAppVersion = (1 << 0), // 0...00001 + FIRInstanceIDInvalidTokenReasonAPNSToken = (1 << 1), // 0...00010 +}; + +/** + * Manager for the InstanceID token requests i.e `newToken` and `deleteToken`. This + * manages the overall interaction of the `InstanceIDStore`, the token register + * service and the callbacks associated with `GCMInstanceID`. + */ +@interface FIRInstanceIDTokenManager : NSObject + +/// Expose the auth service, so it can be used by others +@property(nonatomic, readonly, strong) FIRInstanceIDAuthService *authService; + +/** + * Fetch new token for the given authorizedEntity and scope. This makes an + * asynchronous request to the InstanceID backend to create a new token for + * the service and returns it. This will replace any old token for the given + * authorizedEntity and scope that has been cached before. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param options The options to be added to the fetch request. + * @param handler The handler to be invoked once we have the token or the + * fetch request to InstanceID backend results in an error. Also + * since it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Return the cached token info, if one exists, for the given authorizedEntity and scope. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info, if available, matching the parameters. + */ +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Delete the token for the given authorizedEntity and scope. If the token has + * been cached, it will be deleted from the store. It will also make an + * asynchronous request to the InstanceID backend to invalidate the token. + * + * @param authorizedEntity The authorized entity for the token, should not be nil. + * @param scope The scope for the token, should not be nil. + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to + * InstanceID backend has returned. If the request was + * successful we invoke the handler with a nil error; + * otherwise we call it with an appropriate error. Also since + * it's a public handler it should always be called + * asynchronously. This should be non-nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. This method should only be triggered + * when InstanceID is deleted + * + * @param instanceID The unique string identifying the app instance. + * @param handler The handler to be invoked once the delete request to InstanceID backend + * has returned. If the request was successful we invoke the handler with + * a nil error; else we pass in an appropriate error. This should be non-nil + * and be called asynchronously. + */ +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler; + +/** + * Deletes all cached tokens from the persistent store. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler; + +/** + * Stop any ongoing token operations. + */ +- (void)stopAllTokenOperations; + +#pragma mark - Invalidating Cached Tokens + +/** + * Invalidate any cached tokens, if the app version has changed since last launch or if the token + * is cached for more than 7 days. + * @param IID The cached instanceID, check if token is prefixed by such IID. + * + * @return Whether we should fetch default token from server. + * + * @discussion This should safely be called prior to any tokens being retrieved from + * the cache or being fetched from the network. + */ +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID; + +/** + * Upon being provided with different APNs or sandbox, any locally cached tokens + * should be deleted, and the new APNs token should be cached. + * + * @discussion It is possible for this method to be called while token operations are + * in-progress or queued. In this case, the in-flight token operations will have stale + * APNs information. The default token is checked for being out-of-date by Instance ID, + * and re-fetched. Custom tokens are not currently checked. + * + * @param deviceToken The APNS device token, provided by the operating system. + * @param isSandbox YES if the device token is for the sandbox environment, NO otherwise. + * + * @return The array of FIRInstanceIDTokenInfo objects which were invalidated. + */ +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m new file mode 100644 index 0000000..0ebcfc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenManager.m @@ -0,0 +1,340 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenManager.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDAuthService.h" +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDDefines.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDStore.h" +#import "FIRInstanceIDTokenDeleteOperation.h" +#import "FIRInstanceIDTokenFetchOperation.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDTokenOperation.h" +#import "NSError+FIRInstanceID.h" + +@interface FIRInstanceIDTokenManager () + +@property(nonatomic, readwrite, strong) FIRInstanceIDStore *instanceIDStore; +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthService *authService; +@property(nonatomic, readonly, strong) NSOperationQueue *tokenOperations; + +@property(nonatomic, readwrite, strong) FIRInstanceIDAPNSInfo *currentAPNSInfo; + +@end + +@implementation FIRInstanceIDTokenManager + +- (instancetype)init { + self = [super init]; + if (self) { + _instanceIDStore = [[FIRInstanceIDStore alloc] initWithDelegate:self]; + _authService = [[FIRInstanceIDAuthService alloc] initWithStore:_instanceIDStore]; + [self configureTokenOperations]; + } + return self; +} + +- (void)dealloc { + [self stopAllTokenOperations]; +} + +- (void)configureTokenOperations { + _tokenOperations = [[NSOperationQueue alloc] init]; + _tokenOperations.name = @"com.google.iid-token-operations"; + // For now, restrict the operations to be serial, because in some cases (like if the + // authorized entity and scope are the same), order matters. + // If we have to deal with several different token requests simultaneously, it would be a good + // idea to add some better intelligence around this (performing unrelated token operations + // simultaneously, etc.). + _tokenOperations.maxConcurrentOperationCount = 1; + if ([_tokenOperations respondsToSelector:@selector(qualityOfService)]) { + _tokenOperations.qualityOfService = NSOperationQualityOfServiceUtility; + } +} + +- (void)fetchNewTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + options:(NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManager000, + @"Fetch new token for authorizedEntity: %@, scope: %@", authorizedEntity, + scope); + FIRInstanceIDTokenFetchOperation *operation = + [self createFetchOperationWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + instanceID:instanceID]; + FIRInstanceID_WEAKIFY(self); + FIRInstanceIDTokenOperationCompletion completion = + ^(FIRInstanceIDTokenOperationResult result, NSString *_Nullable token, + NSError *_Nullable error) { + FIRInstanceID_STRONGIFY(self); + if (error) { + handler(nil, error); + return; + } + NSString *firebaseAppID = options[kFIRInstanceIDTokenOptionsFirebaseAppIDKey]; + FIRInstanceIDTokenInfo *tokenInfo = [[FIRInstanceIDTokenInfo alloc] + initWithAuthorizedEntity:authorizedEntity + scope:scope + token:token + appVersion:FIRInstanceIDCurrentAppVersion() + firebaseAppID:firebaseAppID]; + tokenInfo.APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithTokenOptionsDictionary:options]; + + [self.instanceIDStore + saveTokenInfo:tokenInfo + handler:^(NSError *error) { + if (!error) { + // Do not send the token back in case the save was unsuccessful. Since with + // the new asychronous fetch mechanism this can lead to infinite loops, for + // example, we will return a valid token even though we weren't able to store + // it in our cache. The first token will lead to a onTokenRefresh callback + // wherein the user again calls `getToken` but since we weren't able to save + // it we won't hit the cache but hit the server again leading to an infinite + // loop. + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManager001, + @"Token fetch successful, token: %@, authorizedEntity: %@, scope:%@", + token, authorizedEntity, scope); + + if (handler) { + handler(token, nil); + } + } else { + if (handler) { + handler(nil, error); + } + } + }]; + }; + // Add completion handler, and ensure it's called on the main queue + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + completion(result, token, error); + }); + }]; + [self.tokenOperations addOperation:operation]; +} + +- (FIRInstanceIDTokenInfo *)cachedTokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + return [self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]; +} + +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + instanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteTokenHandler)handler { + if ([self.instanceIDStore tokenInfoWithAuthorizedEntity:authorizedEntity scope:scope]) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:authorizedEntity scope:scope]; + } + // Does not matter if we cannot find it in the cache. Still make an effort to unregister + // from the server. + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteToken]; + + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensWithInstanceID:(NSString *)instanceID + handler:(FIRInstanceIDDeleteHandler)handler { + // delete all tokens + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + if (!checkinPreferences) { + // The checkin is already deleted. No need to trigger the token delete operation as client no + // longer has the checkin information for server to delete. + dispatch_async(dispatch_get_main_queue(), ^{ + handler(nil); + }); + return; + } + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:kFIRInstanceIDKeychainWildcardIdentifier + scope:kFIRInstanceIDKeychainWildcardIdentifier + checkinPreferences:checkinPreferences + instanceID:instanceID + action:FIRInstanceIDTokenActionDeleteTokenAndIID]; + if (handler) { + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(error); + }); + }]; + } + [self.tokenOperations addOperation:operation]; +} + +- (void)deleteAllTokensLocallyWithHandler:(void (^)(NSError *error))handler { + [self.instanceIDStore removeAllCachedTokensWithHandler:handler]; +} + +- (void)stopAllTokenOperations { + [self.authService stopCheckinRequest]; + [self.tokenOperations cancelAllOperations]; +} + +#pragma mark - FIRInstanceIDStoreDelegate + +- (void)store:(FIRInstanceIDStore *)store + didDeleteFCMScopedTokensForCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + // Make a best effort try to delete the old client related state on the FCM server. This is + // required to delete old pubusb registrations which weren't cleared when the app was deleted. + // + // This is only a one time effort. If this call fails the client would still receive duplicate + // pubsub notifications if he is again subscribed to the same topic. + // + // The client state should be cleared on the server for the provided checkin preferences. + FIRInstanceIDTokenDeleteOperation *operation = + [self createDeleteOperationWithAuthorizedEntity:nil + scope:nil + checkinPreferences:checkin + instanceID:nil + action:FIRInstanceIDTokenActionDeleteToken]; + [operation addCompletionHandler:^(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + FIRInstanceIDMessageCode code = + kFIRInstanceIDMessageCodeTokenManagerErrorDeletingFCMTokensOnAppReset; + FIRInstanceIDLoggerDebug(code, @"Failed to delete GCM server registrations on app reset."); + } else { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerDeletedFCMTokensOnAppReset, + @"Successfully deleted GCM server registrations on app reset"); + } + }]; + + [self.tokenOperations addOperation:operation]; +} + +#pragma mark - Unit Testing Stub Helpers +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenFetchOperation *) + createFetchOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + instanceID:(NSString *)instanceID { + FIRInstanceIDCheckinPreferences *checkinPreferences = self.authService.checkinPreferences; + FIRInstanceIDTokenFetchOperation *operation = + [[FIRInstanceIDTokenFetchOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + options:options + checkinPreferences:checkinPreferences + instanceID:instanceID]; + return operation; +} + +// We really have this method so that we can more easily stub it out for unit testing +- (FIRInstanceIDTokenDeleteOperation *) + createDeleteOperationWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID + action:(FIRInstanceIDTokenAction)action { + FIRInstanceIDTokenDeleteOperation *operation = + [[FIRInstanceIDTokenDeleteOperation alloc] initWithAuthorizedEntity:authorizedEntity + scope:scope + checkinPreferences:checkinPreferences + instanceID:instanceID + action:action]; + return operation; +} + +#pragma mark - Invalidating Cached Tokens +- (BOOL)checkTokenRefreshPolicyWithIID:(NSString *)IID { + // We know at least one cached token exists. + BOOL shouldFetchDefaultToken = NO; + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *tokenInfo in tokenInfos) { + if ([tokenInfo isFreshWithIID:IID]) { + // Token is fresh and in right format, do nothing + continue; + } + if ([tokenInfo isDefaultToken]) { + // Default token is expired, do not mark for deletion. Fetch directly from server to + // replace the current one. + shouldFetchDefaultToken = YES; + } else { + // Non-default token is expired, mark for deletion. + [tokenInfosToDelete addObject:tokenInfo]; + } + FIRInstanceIDLoggerDebug( + kFIRInstanceIDMessageCodeTokenManagerInvalidateStaleToken, + @"Invalidating cached token for %@ (%@) due to token is no longer fresh.", + tokenInfo.authorizedEntity, tokenInfo.scope); + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return shouldFetchDefaultToken; +} + +- (NSArray *)updateTokensToAPNSDeviceToken:(NSData *)deviceToken + isSandbox:(BOOL)isSandbox { + // Each cached IID token that is missing an APNSInfo, or has an APNSInfo associated should be + // checked and invalidated if needed. + FIRInstanceIDAPNSInfo *APNSInfo = [[FIRInstanceIDAPNSInfo alloc] initWithDeviceToken:deviceToken + isSandbox:isSandbox]; + if ([self.currentAPNSInfo isEqualToAPNSInfo:APNSInfo]) { + return @[]; + } + self.currentAPNSInfo = APNSInfo; + + NSArray *tokenInfos = [self.instanceIDStore cachedTokenInfos]; + NSMutableArray *tokenInfosToDelete = + [NSMutableArray arrayWithCapacity:tokenInfos.count]; + for (FIRInstanceIDTokenInfo *cachedTokenInfo in tokenInfos) { + // Check if the cached APNSInfo is nil, or if it is an old APNSInfo. + if (!cachedTokenInfo.APNSInfo || + ![cachedTokenInfo.APNSInfo isEqualToAPNSInfo:self.currentAPNSInfo]) { + // Mark for invalidation. + [tokenInfosToDelete addObject:cachedTokenInfo]; + } + } + for (FIRInstanceIDTokenInfo *tokenInfoToDelete in tokenInfosToDelete) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenManagerAPNSChangedTokenInvalidated, + @"Invalidating cached token for %@ (%@) due to APNs token change.", + tokenInfoToDelete.authorizedEntity, tokenInfoToDelete.scope); + [self.instanceIDStore removeCachedTokenWithAuthorizedEntity:tokenInfoToDelete.authorizedEntity + scope:tokenInfoToDelete.scope]; + } + return tokenInfosToDelete; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h new file mode 100644 index 0000000..3383875 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h @@ -0,0 +1,69 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import "FIRInstanceIDUtilities.h" + +@class FIRInstanceIDURLQueryItem; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRInstanceIDTokenOperation (Private) + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + ++ (NSURLSession *)sharedURLSession; + +#pragma mark - Initialization +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(nullable NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID; + +#pragma mark - Request Construction ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope; +- (NSMutableURLRequest *)tokenRequest; +- (NSArray *)queryItemsWithInstanceID:(NSString *)instanceID; + +#pragma mark - HTTP Headers +/** + * Given a valid checkin preferences object, it will return a string that can be used + * in the "Authorization" HTTP header to authenticate this request. + * + * @param checkin The valid checkin preferences object, with a deviceID and secretToken. + */ ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin; + +#pragma mark - Result +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error; + +#pragma mark - Methods to override +- (void)performTokenOperation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h new file mode 100644 index 0000000..fa8ad08 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.h @@ -0,0 +1,72 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDCheckinPreferences; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents the action taken on an FCM token. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenAction) { + FIRInstanceIDTokenActionFetch, + FIRInstanceIDTokenActionDeleteToken, + FIRInstanceIDTokenActionDeleteTokenAndIID, +}; + +/** + * Represents the possible results of a token operation. + */ +typedef NS_ENUM(NSInteger, FIRInstanceIDTokenOperationResult) { + FIRInstanceIDTokenOperationSucceeded, + FIRInstanceIDTokenOperationError, + FIRInstanceIDTokenOperationCancelled, +}; + +/** + * Callback to invoke once the HTTP call to FIRMessaging backend for updating + * subscription finishes. + * + * @param result The result of the operation. + * @param token If the action for fetching a token and the request was successful, this will hold + * the value of the token. Otherwise nil. + * @param error The error which occurred while performing the token operation. This will be nil + * in case the operation was successful, or if the operation was cancelled. + */ +typedef void (^FIRInstanceIDTokenOperationCompletion)(FIRInstanceIDTokenOperationResult result, + NSString *_Nullable token, + NSError *_Nullable error); + +@interface FIRInstanceIDTokenOperation : NSOperation + +@property(nonatomic, readonly) FIRInstanceIDTokenAction action; +@property(nonatomic, readonly, nullable) NSString *authorizedEntity; +@property(nonatomic, readonly, nullable) NSString *scope; +@property(nonatomic, readonly, nullable) NSDictionary *options; +@property(nonatomic, readonly, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readonly, strong) NSString *instanceID; + +@property(nonatomic, readonly) FIRInstanceIDTokenOperationResult result; + +- (instancetype)init NS_UNAVAILABLE; + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m new file mode 100644 index 0000000..aa0f75e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenOperation.m @@ -0,0 +1,258 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenOperation.h" + +#import + +#import "FIRInstanceIDCheckinPreferences.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDURLQueryItem.h" +#import "FIRInstanceIDUtilities.h" +#import "NSError+FIRInstanceID.h" + +static const NSInteger kFIRInstanceIDPlatformVersionIOS = 2; + +static NSString *const kFIRInstanceIDParamInstanceID = @"appid"; +// Scope parameter that defines the service using the token +static NSString *const kFIRInstanceIDParamScope = @"X-scope"; +// Defines the SDK version +static NSString *const kFIRInstanceIDParamFCMLibVersion = @"X-cliv"; + +@interface FIRInstanceIDTokenOperation () { + BOOL _isFinished; + BOOL _isExecuting; +} + +@property(nonatomic, readwrite, strong) FIRInstanceIDCheckinPreferences *checkinPreferences; +@property(nonatomic, readwrite, strong) NSString *instanceID; + +@property(atomic, strong) NSURLSessionDataTask *dataTask; +@property(readonly, strong) + NSMutableArray *completionHandlers; + +@property(atomic, strong, nullable) NSString *FISAuthToken; + +// For testing only +@property(nonatomic, readwrite, copy) FIRInstanceIDURLRequestTestBlock testBlock; + +@end + +@implementation FIRInstanceIDTokenOperation + ++ (NSURLSession *)sharedURLSession { + static NSURLSession *tokenOperationSharedSession; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + config.timeoutIntervalForResource = 60.0f; // 1 minute + tokenOperationSharedSession = [NSURLSession sessionWithConfiguration:config]; + tokenOperationSharedSession.sessionDescription = @"com.google.iid.tokens.session"; + }); + return tokenOperationSharedSession; +} + +- (instancetype)initWithAction:(FIRInstanceIDTokenAction)action + forAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(NSDictionary *)options + checkinPreferences:(FIRInstanceIDCheckinPreferences *)checkinPreferences + instanceID:(NSString *)instanceID { + self = [super init]; + if (self) { + _action = action; + _authorizedEntity = [authorizedEntity copy]; + _scope = [scope copy]; + _options = [options copy]; + _checkinPreferences = checkinPreferences; + _instanceID = instanceID; + _completionHandlers = [NSMutableArray array]; + + _isExecuting = NO; + _isFinished = NO; + } + return self; +} + +- (void)dealloc { + _testBlock = nil; + _authorizedEntity = nil; + _scope = nil; + _options = nil; + _checkinPreferences = nil; + _instanceID = nil; + [_completionHandlers removeAllObjects]; + _completionHandlers = nil; +} + +- (void)addCompletionHandler:(FIRInstanceIDTokenOperationCompletion)handler { + [self.completionHandlers addObject:handler]; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + return _isExecuting; +} + +- (void)setExecuting:(BOOL)executing { + [self willChangeValueForKey:@"isExecuting"]; + _isExecuting = executing; + [self didChangeValueForKey:@"isExecuting"]; +} + +- (BOOL)isFinished { + return _isFinished; +} + +- (void)setFinished:(BOOL)finished { + [self willChangeValueForKey:@"isFinished"]; + _isFinished = finished; + [self didChangeValueForKey:@"isFinished"]; +} + +- (void)start { + if (self.isCancelled) { + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; + return; + } + + // Quickly validate whether or not the operation has all it needs to begin + BOOL checkinfoAvailable = [self.checkinPreferences hasCheckinInfo]; + if (!checkinfoAvailable) { + FIRInstanceIDErrorCode errorCode = kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn; + [self finishWithResult:FIRInstanceIDTokenOperationError + token:nil + error:[NSError errorWithFIRInstanceIDErrorCode:errorCode]]; + return; + } + + [self setExecuting:YES]; + + [[FIRInstallations installations] + authTokenWithCompletion:^(FIRInstallationsAuthTokenResult *_Nullable tokenResult, + NSError *_Nullable error) { + if (tokenResult.authToken.length > 0) { + self.FISAuthToken = tokenResult.authToken; + [self performTokenOperation]; + } else { + [self finishWithResult:FIRInstanceIDTokenOperationError token:nil error:error]; + } + }]; +} + +- (void)finishWithResult:(FIRInstanceIDTokenOperationResult)result + token:(nullable NSString *)token + error:(nullable NSError *)error { + // Add a check to prevent this finish from being called more than once. + if (self.isFinished) { + return; + } + self.dataTask = nil; + _result = result; + // TODO(chliangGoogle): Call these in the main thread? + for (FIRInstanceIDTokenOperationCompletion completionHandler in self.completionHandlers) { + completionHandler(result, token, error); + } + + [self setExecuting:NO]; + [self setFinished:YES]; +} + +- (void)cancel { + [super cancel]; + [self.dataTask cancel]; + [self finishWithResult:FIRInstanceIDTokenOperationCancelled token:nil error:nil]; +} + +- (void)performTokenOperation { +} + +- (NSMutableURLRequest *)tokenRequest { + NSString *authHeader = + [FIRInstanceIDTokenOperation HTTPAuthHeaderFromCheckin:self.checkinPreferences]; + return [[self class] requestWithAuthHeader:authHeader FISAuthToken:self.FISAuthToken]; +} + +#pragma mark - Request Construction ++ (NSMutableURLRequest *)requestWithAuthHeader:(NSString *)authHeaderString + FISAuthToken:(NSString *)FISAuthToken { + NSURL *url = [NSURL URLWithString:FIRInstanceIDRegisterServer()]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + + // Add HTTP headers + [request setValue:authHeaderString forHTTPHeaderField:@"Authorization"]; + [request setValue:FIRInstanceIDAppIdentifier() forHTTPHeaderField:@"app"]; + if (FISAuthToken) { + [request setValue:FISAuthToken forHTTPHeaderField:@"x-goog-firebase-installations-auth"]; + } + request.HTTPMethod = @"POST"; + return request; +} + ++ (NSMutableArray *)standardQueryItemsWithDeviceID:(NSString *)deviceID + scope:(NSString *)scope { + NSMutableArray *queryItems = [NSMutableArray arrayWithCapacity:8]; + + // E.g. X-osv=10.2.1 + NSString *systemVersion = FIRInstanceIDOperatingSystemVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"X-osv" value:systemVersion]]; + // E.g. device= + if (deviceID) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"device" value:deviceID]]; + } + // E.g. X-scope=fcm + if (scope) { + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamScope + value:scope]]; + } + // E.g. plat=2 + NSString *platform = [NSString stringWithFormat:@"%ld", (long)kFIRInstanceIDPlatformVersionIOS]; + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"plat" value:platform]]; + // E.g. app=com.myapp.foo + NSString *appIdentifier = FIRInstanceIDAppIdentifier(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app" value:appIdentifier]]; + // E.g. app_ver=1.5 + NSString *appVersion = FIRInstanceIDCurrentAppVersion(); + [queryItems addObject:[FIRInstanceIDURLQueryItem queryItemWithName:@"app_ver" value:appVersion]]; + // E.g. X-cliv=fiid-1.2.3 + NSString *fcmLibraryVersion = + [NSString stringWithFormat:@"fiid-%@", FIRInstanceIDCurrentGCMVersion()]; + if (fcmLibraryVersion.length) { + FIRInstanceIDURLQueryItem *gcmLibVersion = + [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamFCMLibVersion + value:fcmLibraryVersion]; + [queryItems addObject:gcmLibVersion]; + } + + return queryItems; +} + +- (NSArray *)queryItemsWithInstanceID:(NSString *)instanceID { + return @[ [FIRInstanceIDURLQueryItem queryItemWithName:kFIRInstanceIDParamInstanceID + value:instanceID] ]; +} + +#pragma mark - HTTP Header + ++ (NSString *)HTTPAuthHeaderFromCheckin:(FIRInstanceIDCheckinPreferences *)checkin { + NSString *deviceID = checkin.deviceID; + NSString *secret = checkin.secretToken; + return [NSString stringWithFormat:@"AidLogin %@:%@", deviceID, secret]; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h new file mode 100644 index 0000000..861c87b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.h @@ -0,0 +1,106 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRInstanceIDAPNSInfo; +@class FIRInstanceIDAuthKeychain; +@class FIRInstanceIDTokenInfo; + +/** + * This class is responsible for retrieving and saving `FIRInstanceIDTokenInfo` objects from the + * keychain. The keychain keys that are used are: + * Account:
(e.g. com.mycompany.myapp) + * Service: : (e.g. 1234567890:*) + */ +@interface FIRInstanceIDTokenStore : NSObject + +NS_ASSUME_NONNULL_BEGIN + +/** + * Create a default InstanceID token store. Uses a valid Keychain object as it's + * persistent backing store. + * + * @return A valid token store object. + */ ++ (instancetype)defaultStore; + +- (instancetype)init __attribute__((unavailable("Use -initWithKeychain: instead."))); + +/** + * Initialize a token store object with a Keychain object. Used for testing. + * + * @param keychain The Keychain object to use as the backing store for tokens. + * + * @return A valid token store object with the given Keychain as backing store. + */ +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain; + +#pragma mark - Get + +/** + * Get the cached token from the Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + * @return The cached token info if any for the given authorizedEntity and scope else + * nil. + */ +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope; + +/** + * Return all cached token infos from the Keychain. + * + * @return The cached token infos, if any, that are stored in the Keychain. + */ +- (NSArray *)cachedTokenInfos; + +#pragma mark - Save + +/** + * Save the instanceID token info to the persistent store. + * + * @param tokenInfo The token info to store. + * @param handler The callback handler which is invoked when token saving is complete, + * with an error if there is any. + */ +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(nullable void (^)(NSError *))handler; + +#pragma mark - Delete + +/** + * Remove the cached token from Keychain. + * + * @param authorizedEntity The authorized entity for the token. + * @param scope The scope for the token. + * + */ +- (void)removeTokenWithAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope; + +/** + * Remove all the cached tokens from the Keychain. + * @param handler The callback handler which is invoked when tokens deletion is complete, + * with an error if there is any. + * + */ +- (void)removeAllTokensWithHandler:(nullable void (^)(NSError *))handler; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m new file mode 100644 index 0000000..f97f932 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDTokenStore.m @@ -0,0 +1,143 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDTokenStore.h" + +#import "FIRInstanceIDAuthKeyChain.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" +#import "FIRInstanceIDTokenInfo.h" +#import "FIRInstanceIDUtilities.h" + +static NSString *const kFIRInstanceIDTokenKeychainId = @"com.google.iid-tokens"; + +@interface FIRInstanceIDTokenStore () + +@property(nonatomic, readwrite, strong) FIRInstanceIDAuthKeychain *keychain; + +@end + +@implementation FIRInstanceIDTokenStore + ++ (instancetype)defaultStore { + FIRInstanceIDAuthKeychain *tokenKeychain = + [[FIRInstanceIDAuthKeychain alloc] initWithIdentifier:kFIRInstanceIDTokenKeychainId]; + return [[FIRInstanceIDTokenStore alloc] initWithKeychain:tokenKeychain]; +} + +- (instancetype)initWithKeychain:(FIRInstanceIDAuthKeychain *)keychain { + self = [super init]; + if (self) { + _keychain = keychain; + } + return self; +} + +#pragma mark - Get + ++ (NSString *)serviceKeyForAuthorizedEntity:(NSString *)authorizedEntity scope:(NSString *)scope { + return [NSString stringWithFormat:@"%@:%@", authorizedEntity, scope]; +} + +- (nullable FIRInstanceIDTokenInfo *)tokenInfoWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + NSData *item = [self.keychain dataForService:service account:account]; + if (!item) { + return nil; + } + // Token infos created from legacy storage don't have appVersion, firebaseAppID, or APNSInfo. + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + return tokenInfo; +} + +- (NSArray *)cachedTokenInfos { + NSString *account = FIRInstanceIDAppIdentifier(); + NSArray *items = + [self.keychain itemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier account:account]; + NSMutableArray *tokenInfos = + [NSMutableArray arrayWithCapacity:items.count]; + for (NSData *item in items) { + FIRInstanceIDTokenInfo *tokenInfo = [[self class] tokenInfoFromKeychainItem:item]; + if (tokenInfo) { + [tokenInfos addObject:tokenInfo]; + } + } + return tokenInfos; +} + ++ (nullable FIRInstanceIDTokenInfo *)tokenInfoFromKeychainItem:(NSData *)item { + // Check if it is saved as an archived FIRInstanceIDTokenInfo, otherwise return nil. + FIRInstanceIDTokenInfo *tokenInfo = nil; + // NOTE: Passing in nil to unarchiveObjectWithData will result in an iOS error logged + // in the console on iOS 10 and below. Avoid by checking item.data's existence. + if (item) { + // TODO(chliangGoogle: Use the new API and secureCoding protocol. + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfo = [NSKeyedUnarchiver unarchiveObjectWithData:item]; +#pragma clang diagnostic pop + + } @catch (NSException *exception) { + FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeTokenStoreExceptionUnarchivingTokenInfo, + @"Unable to parse token info from Keychain item; item was in an " + @"invalid format"); + tokenInfo = nil; + } @finally { + } + } + return tokenInfo; +} + +#pragma mark - Save +// Token Infos will be saved under these Keychain keys: +// Account:
(e.g. com.mycompany.myapp) +// Service: : (e.g. 1234567890:*) +- (void)saveTokenInfo:(FIRInstanceIDTokenInfo *)tokenInfo + handler:(void (^)(NSError *))handler { // Keep the cachetime up-to-date. + tokenInfo.cacheTime = [NSDate date]; + // Always write to the Keychain, so that the cacheTime is up-to-date. + NSData *tokenInfoData; + // TODO(chliangGoogle: Use the new API and secureCoding protocol. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + tokenInfoData = [NSKeyedArchiver archivedDataWithRootObject:tokenInfo]; +#pragma clang diagnostic pop + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:tokenInfo.authorizedEntity + scope:tokenInfo.scope]; + [self.keychain setData:tokenInfoData forService:service account:account handler:handler]; +} + +#pragma mark - Delete + +- (void)removeTokenWithAuthorizedEntity:(nonnull NSString *)authorizedEntity + scope:(nonnull NSString *)scope { + NSString *account = FIRInstanceIDAppIdentifier(); + NSString *service = [[self class] serviceKeyForAuthorizedEntity:authorizedEntity scope:scope]; + [self.keychain removeItemsMatchingService:service account:account handler:nil]; +} + +- (void)removeAllTokensWithHandler:(void (^)(NSError *error))handler { + NSString *account = FIRInstanceIDAppIdentifier(); + [self.keychain removeItemsMatchingService:kFIRInstanceIDKeychainWildcardIdentifier + account:account + handler:handler]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h new file mode 100644 index 0000000..3a3a1d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +// Stand-in for NSURLQueryItem, which is only available on iOS 8.0 and up. +@interface FIRInstanceIDURLQueryItem : NSObject + +@property(nonatomic, readonly) NSString *name; +@property(nonatomic, readonly) NSString *value; + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value; +- (instancetype)initWithName:(NSString *)name value:(NSString *)value; + +@end + +/** + * Given an array of query items, construct a URL query. On iOS 8.0 and above, this will use + * NSURLQueryItems internally to perform the string creation, and will be done manually in iOS + * 7 and below. + */ +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m new file mode 100644 index 0000000..59b4865 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDURLQueryItem.m @@ -0,0 +1,55 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDURLQueryItem.h" + +@implementation FIRInstanceIDURLQueryItem + ++ (instancetype)queryItemWithName:(NSString *)name value:(NSString *)value { + return [[[self class] alloc] initWithName:name value:value]; +} + +- (instancetype)initWithName:(NSString *)name value:(NSString *)value { + self = [super init]; + if (self) { + _name = [name copy]; + _value = [value copy]; + } + return self; +} +@end + +NSString *FIRInstanceIDQueryFromQueryItems(NSArray *queryItems) { + if ([NSURLQueryItem class]) { + // We are iOS 8.0 and above. Convert to NSURLQueryItems and get query that way + // to take advantage of any automatic encoding + NSMutableArray *urlItems = + [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [urlItems addObject:[NSURLQueryItem queryItemWithName:queryItem.name value:queryItem.value]]; + } + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.queryItems = urlItems; + return components.query; + } else { + // We are on iOS 7.0. Manually create the query string + NSMutableArray *pairs = [NSMutableArray arrayWithCapacity:queryItems.count]; + for (FIRInstanceIDURLQueryItem *queryItem in queryItems) { + [pairs addObject:[NSString stringWithFormat:@"%@=%@", queryItem.name, queryItem.value]]; + } + return [pairs componentsJoinedByString:@"&"]; + } +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h new file mode 100644 index 0000000..da6ebad --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.h @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +FOUNDATION_EXPORT NSString *const kFIRInstanceIDFCMSDKClassString; + +/// locale key stored in GULUserDefaults +FOUNDATION_EXPORT NSString *const kFIRInstanceIDUserDefaultsKeyLocale; + +#pragma mark - Test Blocks + +/** + * Response block for mock registration requests made during tests. + * + * @param data The data as returned by the mock request. + * @param response The response as returned by the mock request. + * @param error The error if any as returned by the mock request. + */ +typedef void (^FIRInstanceIDURLRequestTestResponseBlock)(NSData *data, + NSURLResponse *response, + NSError *error); + +/** + * Test block to mock registration requests response. + * + * @param request The request to mock response for. + * @param response The response block for the mocked request. + */ +typedef void (^FIRInstanceIDURLRequestTestBlock)(NSURLRequest *request, + FIRInstanceIDURLRequestTestResponseBlock response); + +#pragma mark - URL Helpers + +FOUNDATION_EXPORT NSString *FIRInstanceIDRegisterServer(void); + +#pragma mark - Time + +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInSeconds(void); +FOUNDATION_EXPORT int64_t FIRInstanceIDCurrentTimestampInMilliseconds(void); + +#pragma mark - App Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentAppVersion(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDAppIdentifier(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDFirebaseAppID(void); + +#pragma mark - Device Info + +FOUNDATION_EXPORT NSString *FIRInstanceIDDeviceModel(void); +FOUNDATION_EXPORT NSString *FIRInstanceIDOperatingSystemVersion(void); +FOUNDATION_EXPORT BOOL FIRInstanceIDHasLocaleChanged(void); + +#pragma mark - Helpers + +FOUNDATION_EXPORT BOOL FIRInstanceIDIsValidGCMScope(NSString *scope); +FOUNDATION_EXPORT NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken); +FOUNDATION_EXPORT NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, + BOOL isSandbox); + +#pragma mark - GCM Helpers +/// Returns the current GCM version if GCM library is found else returns nil. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentGCMVersion(void); + +/// Returns the current locale. If GCM is present it queries GCM for a +/// Context Manager specific locale. Otherwise, it returns the system's first +/// preferred language (which may be set independently from locale). If the +/// system returns no preferred languages, this method returns the most common +/// language for the user's given locale. Guaranteed to return a nonnull value. +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLocale(void); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m new file mode 100644 index 0000000..9eaafa7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDUtilities.m @@ -0,0 +1,208 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDUtilities.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#endif +#import + +#import +#import +#import "FIRInstanceID.h" +#import "FIRInstanceIDConstants.h" +#import "FIRInstanceIDLogger.h" + +// Convert the macro to a string +#define STR_EXPAND(x) #x +#define STR(x) STR_EXPAND(x) + +static NSString *const kFIRInstanceIDAPNSSandboxPrefix = @"s_"; +static NSString *const kFIRInstanceIDAPNSProdPrefix = @"p_"; + +/// FIRMessaging Class that responds to the FIRMessaging SDK version selector. +/// Verify at runtime if the class exists and implements the required method. +NSString *const kFIRInstanceIDFCMSDKClassString = @"FIRMessaging"; + +/// FIRMessaging selector that returns the current FIRMessaging library version. +static NSString *const kFIRInstanceIDFCMSDKVersionSelectorString = @"FIRMessagingSDKVersion"; + +/// FIRMessaging selector that returns the current device locale. +static NSString *const kFIRInstanceIDFCMSDKLocaleSelectorString = @"FIRMessagingSDKCurrentLocale"; + +NSString *const kFIRInstanceIDUserDefaultsKeyLocale = + @"com.firebase.instanceid.user_defaults.locale"; // locale key stored in GULUserDefaults + +/// Static values which will be populated once retrieved using +/// |FIRInstanceIDRetrieveEnvironmentInfoFromFirebaseCore|. +static NSString *operatingSystemVersion; +static NSString *hardwareDeviceModel; + +#pragma mark - URL Helpers + +NSString *FIRInstanceIDRegisterServer() { + return @"https://fcmtoken.googleapis.com/register"; +} + +#pragma mark - Time + +int64_t FIRInstanceIDCurrentTimestampInSeconds() { + return (int64_t)[[NSDate date] timeIntervalSince1970]; +} + +int64_t FIRInstanceIDCurrentTimestampInMilliseconds() { + return (int64_t)(FIRInstanceIDCurrentTimestampInSeconds() * 1000.0); +} + +#pragma mark - App Info + +NSString *FIRInstanceIDCurrentAppVersion() { + NSString *version = [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; + if (![version length]) { + return @""; + } + return version; +} + +NSString *FIRInstanceIDBundleIDByRemovingLastPartFrom(NSString *bundleID) { + NSString *bundleIDComponentsSeparator = @"."; + + NSMutableArray *bundleIDComponents = + [[bundleID componentsSeparatedByString:bundleIDComponentsSeparator] mutableCopy]; + [bundleIDComponents removeLastObject]; + + return [bundleIDComponents componentsJoinedByString:bundleIDComponentsSeparator]; +} + +NSString *FIRInstanceIDAppIdentifier() { + NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier]; + if (!bundleID.length) { + FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeUtilitiesMissingBundleIdentifier, + @"The mainBundle's bundleIdentifier returned '%@'. Bundle identifier " + @"expected to be non-empty.", + bundleID); + return @""; + } +#if TARGET_OS_WATCH + return FIRInstanceIDBundleIDByRemovingLastPartFrom(bundleID); +#endif + return bundleID; +} + +NSString *FIRInstanceIDFirebaseAppID() { + return [FIROptions defaultOptions].googleAppID; +} + +#pragma mark - Device Info +// Get the device model from Firebase Core's App Environment Util +NSString *FIRInstanceIDDeviceModel() { + static dispatch_once_t once; + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + hardwareDeviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return hardwareDeviceModel; +} + +// Get the system version from Firebase Core's App Environment Util +NSString *FIRInstanceIDOperatingSystemVersion() { +#if TARGET_OS_IOS || TARGET_OS_TV + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_WATCH + return [NSProcessInfo processInfo].operatingSystemVersionString; +#endif +} + +BOOL FIRInstanceIDHasLocaleChanged() { + NSString *lastLocale = + [[GULUserDefaults standardUserDefaults] stringForKey:kFIRInstanceIDUserDefaultsKeyLocale]; + NSString *currentLocale = FIRInstanceIDCurrentLocale(); + if (lastLocale) { + if ([currentLocale isEqualToString:lastLocale]) { + return NO; + } + } + return YES; +} + +#pragma mark - Helpers + +BOOL FIRInstanceIDIsValidGCMScope(NSString *scope) { + return [scope compare:kFIRInstanceIDScopeFirebaseMessaging + options:NSCaseInsensitiveSearch] == NSOrderedSame; +} + +NSString *FIRInstanceIDStringForAPNSDeviceToken(NSData *deviceToken) { + NSMutableString *APNSToken = [NSMutableString string]; + unsigned char *bytes = (unsigned char *)[deviceToken bytes]; + for (int i = 0; i < (int)deviceToken.length; i++) { + [APNSToken appendFormat:@"%02x", bytes[i]]; + } + return APNSToken; +} + +NSString *FIRInstanceIDAPNSTupleStringForTokenAndServerType(NSData *deviceToken, BOOL isSandbox) { + if (deviceToken == nil) { + // A nil deviceToken leads to an invalid tuple string, so return nil. + return nil; + } + NSString *prefix = isSandbox ? kFIRInstanceIDAPNSSandboxPrefix : kFIRInstanceIDAPNSProdPrefix; + NSString *APNSString = FIRInstanceIDStringForAPNSDeviceToken(deviceToken); + NSString *APNSTupleString = [NSString stringWithFormat:@"%@%@", prefix, APNSString]; + + return APNSTupleString; +} + +#pragma mark - GCM Helpers + +NSString *FIRInstanceIDCurrentGCMVersion() { + Class versionClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL versionSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKVersionSelectorString); + if ([versionClass respondsToSelector:versionSelector]) { + IMP getVersionIMP = [versionClass methodForSelector:versionSelector]; + NSString *(*getVersion)(id, SEL) = (void *)getVersionIMP; + return getVersion(versionClass, versionSelector); + } + return nil; +} + +NSString *FIRInstanceIDCurrentLocale() { + Class localeClass = NSClassFromString(kFIRInstanceIDFCMSDKClassString); + SEL localeSelector = NSSelectorFromString(kFIRInstanceIDFCMSDKLocaleSelectorString); + + if ([localeClass respondsToSelector:localeSelector]) { + IMP getLocaleIMP = [localeClass methodForSelector:localeSelector]; + NSString *(*getLocale)(id, SEL) = (void *)getLocaleIMP; + NSString *fcmLocale = getLocale(localeClass, localeSelector); + if (fcmLocale != nil) { + return fcmLocale; + } + } + + NSString *systemLanguage = [[NSLocale preferredLanguages] firstObject]; + if (systemLanguage != nil) { + return systemLanguage; + } + + if (@available(macOS 10.12, iOS 10.0, *)) { + return [NSLocale currentLocale].languageCode; + } else { + return nil; + } +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h new file mode 100644 index 0000000..ec5a76c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * Parsing utility for InstanceID Library versions. InstanceID lib follows semantic versioning. + * This provides utilities to parse the library versions to enable features and do + * updates based on appropriate library versions. + * + * Some example semantic versions are 1.0.1, 2.1.0, 2.1.1, 2.2.0-alpha1, 2.2.1-beta1 + */ + +FOUNDATION_EXPORT NSString *FIRInstanceIDCurrentLibraryVersion(void); +/// Returns the current Major version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMajor(void); +/// Returns the current Minor version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionMinor(void); +/// Returns the current Patch version of GCM library. +FOUNDATION_EXPORT int FIRInstanceIDCurrentLibraryVersionPatch(void); +/// Returns YES if current library version is `beta` else NO. +FOUNDATION_EXPORT BOOL FIRInstanceIDCurrentLibraryVersionIsBeta(void); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m new file mode 100644 index 0000000..c2e532a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/FIRInstanceIDVersionUtilities.m @@ -0,0 +1,85 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceIDVersionUtilities.h" + +// Convert the macro to a string +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x + +static NSString *const kSemanticVersioningSeparator = @"."; +static NSString *const kBetaVersionPrefix = @"-beta"; + +static NSString *libraryVersion; + +static int majorVersion; +static int minorVersion; +static int patchVersion; +static int betaVersion; + +void FIRInstanceIDParseCurrentLibraryVersion() { + static NSArray *allVersions; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableString *daylightVersion = + [NSMutableString stringWithUTF8String:STR(FIRInstanceID_LIB_VERSION)]; + // Parse versions + // major, minor, patch[-beta#] + allVersions = [daylightVersion componentsSeparatedByString:kSemanticVersioningSeparator]; + if (allVersions.count == 3) { + majorVersion = [allVersions[0] intValue]; + minorVersion = [allVersions[1] intValue]; + + // Parse patch and beta versions + NSArray *patchAndBetaVersion = + [allVersions[2] componentsSeparatedByString:kBetaVersionPrefix]; + if (patchAndBetaVersion.count == 2) { + patchVersion = [patchAndBetaVersion[0] intValue]; + betaVersion = [patchAndBetaVersion[1] intValue]; + } else if (patchAndBetaVersion.count == 1) { + patchVersion = [patchAndBetaVersion[0] intValue]; + } + } + + // Copy library version + libraryVersion = [daylightVersion copy]; + }); +} + +NSString *FIRInstanceIDCurrentLibraryVersion() { + FIRInstanceIDParseCurrentLibraryVersion(); + return libraryVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMajor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return majorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionMinor() { + FIRInstanceIDParseCurrentLibraryVersion(); + return minorVersion; +} + +int FIRInstanceIDCurrentLibraryVersionPatch() { + FIRInstanceIDParseCurrentLibraryVersion(); + return patchVersion; +} + +BOOL FIRInstanceIDCurrentLibraryVersionIsBeta() { + FIRInstanceIDParseCurrentLibraryVersion(); + return betaVersion > 0; +} diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h new file mode 100644 index 0000000..b533dc4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.h @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +FOUNDATION_EXPORT NSString *const kFIRInstanceIDDomain; + +typedef NS_ENUM(NSUInteger, FIRInstanceIDErrorCode) { + // Unknown error. + kFIRInstanceIDErrorCodeUnknown = 0, + + // Http related errors. + kFIRInstanceIDErrorCodeAuthentication = 1, + kFIRInstanceIDErrorCodeNoAccess = 2, + kFIRInstanceIDErrorCodeTimeout = 3, + kFIRInstanceIDErrorCodeNetwork = 4, + + // Another operation is in progress. + kFIRInstanceIDErrorCodeOperationInProgress = 5, + + // Failed to perform device check in. + kFIRInstanceIDErrorCodeRegistrarFailedToCheckIn = 6, + + kFIRInstanceIDErrorCodeInvalidRequest = 7, + + // InstanceID generic errors + kFIRInstanceIDErrorCodeMissingDeviceID = 501, + + // InstanceID Token specific errors + kFIRInstanceIDErrorCodeMissingAPNSToken = 1001, + kFIRInstanceIDErrorCodeMissingAPNSServerType = 1002, + kFIRInstanceIDErrorCodeInvalidAuthorizedEntity = 1003, + kFIRInstanceIDErrorCodeInvalidScope = 1004, + kFIRInstanceIDErrorCodeInvalidStart = 1005, + kFIRInstanceIDErrorCodeInvalidKeyPair = 1006, + + // InstanceID Identity specific errors + // Generic InstanceID keypair error + kFIRInstanceIDErrorCodeMissingKeyPair = 2001, + kFIRInstanceIDErrorCodeInvalidKeyPairTags = 2002, + kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime = 2005, + kFIRInstanceIDErrorCodeInvalidIdentity = 2006, + +}; + +@interface NSError (FIRInstanceID) + +@property(nonatomic, readonly) FIRInstanceIDErrorCode instanceIDErrorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode; + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo; + ++ (NSError *)FIRInstanceIDErrorMissingCheckin; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m new file mode 100644 index 0000000..560a5df --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/NSError+FIRInstanceID.m @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "NSError+FIRInstanceID.h" + +NSString *const kFIRInstanceIDDomain = @"com.firebase.iid"; + +@implementation NSError (FIRInstanceID) + +- (FIRInstanceIDErrorCode)instanceIDErrorCode { + return (FIRInstanceIDErrorCode)self.code; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode { + return [NSError errorWithFIRInstanceIDErrorCode:errorCode userInfo:nil]; +} + ++ (NSError *)errorWithFIRInstanceIDErrorCode:(FIRInstanceIDErrorCode)errorCode + userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:kFIRInstanceIDDomain code:errorCode userInfo:userInfo]; +} + ++ (NSError *)FIRInstanceIDErrorMissingCheckin { + NSDictionary *userInfo = @{@"msg" : @"Missing device credentials. Retry later."}; + + return [NSError errorWithDomain:kFIRInstanceIDDomain + code:kFIRInstanceIDErrorCodeMissingDeviceID + userInfo:userInfo]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h new file mode 100644 index 0000000..632e21b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID+Private.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/** + * @related FIRInstanceIDCheckinService + * + * The completion handler invoked once the fetch from Checkin server finishes. + * For successful fetches we returned checkin information by the checkin service + * and `nil` error, else we return the appropriate error object as reported by the + * Checkin Service. + * + * @param checkinPreferences The checkin preferences as fetched from the server. + * @param error The error object which fetching GServices data. + */ +typedef void (^FIRInstanceIDDeviceCheckinCompletion)( + FIRInstanceIDCheckinPreferences *_Nullable checkinPreferences, NSError *_Nullable error); + +/** + * Private API used by Firebase SDK teams by calling in reflection or internal teams. + */ +@interface FIRInstanceID (Private) + +/** + * Fetches checkin info for the app. If the app has valid cached checkin preferences + * they are returned instead of making a network request. + * + * @param handler The completion handler to invoke once the request has completed. + */ +- (void)fetchCheckinInfoWithHandler:(nullable FIRInstanceIDDeviceCheckinCompletion)handler; + +/** + * Get the InstanceID for the app. If an ID was created before and cached + * successfully we will return that ID. If no cached ID exists we create + * a new ID, cache it and return that. + * + * This is a blocking call and should not really be called on the main thread. + * + * @param error The error object that represents the error while trying to + * retrieve the instance id. + * + * @return The InstanceID for the app. + */ +- (nullable NSString *)appInstanceID:(NSError *_Nullable *_Nullable)error + DEPRECATED_MSG_ATTRIBUTE("Please use getID(handler:) for Swift or " + "getIDWithHandler: for Objective-C instead."); + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h new file mode 100644 index 0000000..be3ec57 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h @@ -0,0 +1,62 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The preferences InstanceID loads from checkin server. The deviceID and secret that checkin + * provides is used to authenticate all future requests to the server. Besides the deviceID + * and secret the other information that checkin provides is stored in a plist on the device. + * The deviceID and secret are persisted in the device keychain. + */ +@interface FIRInstanceIDCheckinPreferences : NSObject + +/** + * DeviceID and secretToken are the checkin auth credentials and are stored in the Keychain. + */ +@property(nonatomic, readonly, copy) NSString *deviceID; +@property(nonatomic, readonly, copy) NSString *secretToken; + +/** + * All the other checkin preferences other than deviceID and secret are stored in a plist. + */ +@property(nonatomic, readonly, copy) NSString *deviceDataVersion; +@property(nonatomic, readonly, copy) NSString *digest; +@property(nonatomic, readonly, copy) NSString *versionInfo; +@property(nonatomic, readonly, assign) int64_t lastCheckinTimestampMillis; + +/** + * The content retrieved from checkin server that should be persisted in a plist. This + * doesn't contain the deviceID and secret which are stored in the Keychain since they + * should be more private. + * + * @return The checkin preferences that should be persisted in a plist. + */ +- (NSDictionary *)checkinPlistContents; + +/** + * Return whether checkin info exists, valid or not. + */ +- (BOOL)hasCheckinInfo; + +/** + * Verify if checkin preferences are valid or not. + * + * @return YES if valid checkin preferences else NO. + */ +- (BOOL)hasValidCheckinInfo; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h new file mode 100644 index 0000000..c343f88 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Private/FIRInstanceID_Private.h @@ -0,0 +1,74 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDCheckinPreferences; +@class FIRInstallations; + +/** + * Private API used by other Firebase SDKs. + */ +@interface FIRInstanceID () + +@property(nonatomic, readonly, strong) NSString *deviceAuthID; +@property(nonatomic, readonly, strong) NSString *secretToken; +@property(nonatomic, readonly, strong) NSString *versionInfo; + +@property(nonatomic, readonly, strong) FIRInstallations *installations; + +/// A cached value of FID. Should be used only for `-[FIRInstanceID appInstanceID:]`. +@property(atomic, readonly, copy, nullable) NSString *firebaseInstallationsID; + +/** + * Private initializer. + */ +- (instancetype)initPrivately; + +/** + * Returns a Firebase Messaging scoped token for the firebase app. + * + * @return Returns the stored token if the device has registered with Firebase Messaging, otherwise + * returns nil. + */ +- (nullable NSString *)token; + +/** + * Verify if valid checkin preferences have been loaded in memory. + * + * @return YES if valid checkin preferences exist in memory else NO. + */ +- (BOOL)hasValidCheckinInfo; + +/** + * Try to load prefetched checkin preferences from the cache. This supports the use case where + * InstanceID library has already obtained a valid checkin and we should be using that. + * + * This should be used as a last gasp effort to retreive any cached checkin preferences before + * hitting the FIRMessaging backend to retrieve new preferences. + * + * Note this is only required because InstanceID and FIRMessaging both require checkin preferences + * which need to be synced with each other. + * + * @return YES if successfully loaded cached checkin preferences into memory else NO. + */ +- (BOOL)tryToLoadValidCheckinInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h new file mode 100644 index 0000000..0f96d91 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FIRInstanceID.h @@ -0,0 +1,312 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRInstanceIDResult; +/** + * @memberof FIRInstanceID + * + * The scope to be used when fetching/deleting a token for Firebase Messaging. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDScopeFirebaseMessaging + NS_SWIFT_NAME(InstanceIDScopeFirebaseMessaging); + +#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT const NSNotificationName kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefresh); +#else +/** + * Called when the system determines that tokens need to be refreshed. + * This method is also called if Instance ID has been reset in which + * case, tokens and FCM topic subscriptions also need to be refreshed. + * + * Instance ID service will throttle the refresh event across all devices + * to control the rate of token updates on application servers. + */ +FOUNDATION_EXPORT NSString *const kFIRInstanceIDTokenRefreshNotification + NS_SWIFT_NAME(InstanceIDTokenRefreshNotification); +#endif // defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID token returns. If + * the call fails we return the appropriate `error code` as described below. + * + * @param token The valid token as returned by InstanceID backend. + * + * @param error The error describing why generating a new token + * failed. See the error codes below for a more detailed + * description. + */ +typedef void (^FIRInstanceIDTokenHandler)(NSString *__nullable token, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the InstanceID `deleteToken` returns. If + * the call fails we return the appropriate `error code` as described below + * + * @param error The error describing why deleting the token failed. + * See the error codes below for a more detailed description. + */ +typedef void (^FIRInstanceIDDeleteTokenHandler)(NSError *error) + NS_SWIFT_NAME(InstanceIDDeleteTokenHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity is created. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param identity A valid identity for the app instance, nil if there was an error + * while creating an identity. + * @param error The error if fetching the identity fails else nil. + */ +typedef void (^FIRInstanceIDHandler)(NSString *__nullable identity, NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and all the tokens associated + * with it are deleted. Returns a valid error object in case of failure else nil. + * + * @param error The error if deleting the identity and all the tokens associated with + * it fails else nil. + */ +typedef void (^FIRInstanceIDDeleteHandler)(NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDDeleteHandler); + +/** + * @related FIRInstanceID + * + * The completion handler invoked when the app identity and token are fetched. If the + * identity wasn't created for some reason we return the appropriate error code. + * + * @param result The result containing an identity for the app instance and a valid token, + * nil if there was an error while creating the result. + * @param error The error if fetching the identity or token fails else nil. + */ +typedef void (^FIRInstanceIDResultHandler)(FIRInstanceIDResult *__nullable result, + NSError *__nullable error) + NS_SWIFT_NAME(InstanceIDResultHandler); + +/** + * Public errors produced by InstanceID. + */ +typedef NS_ENUM(NSUInteger, FIRInstanceIDError) { + // Http related errors. + + /// Unknown error. + FIRInstanceIDErrorUnknown = 0, + + /// Auth Error -- GCM couldn't validate request from this client. + FIRInstanceIDErrorAuthentication = 1, + + /// NoAccess -- InstanceID service cannot be accessed. + FIRInstanceIDErrorNoAccess = 2, + + /// Timeout -- Request to InstanceID backend timed out. + FIRInstanceIDErrorTimeout = 3, + + /// Network -- No network available to reach the servers. + FIRInstanceIDErrorNetwork = 4, + + /// OperationInProgress -- Another similar operation in progress, + /// bailing this one. + FIRInstanceIDErrorOperationInProgress = 5, + + /// InvalidRequest -- Some parameters of the request were invalid. + FIRInstanceIDErrorInvalidRequest = 7, +} NS_SWIFT_NAME(InstanceIDError); + +/** + * A class contains the results of InstanceID and token query. + */ +NS_SWIFT_NAME(InstanceIDResult) +@interface FIRInstanceIDResult : NSObject + +/** + * An instanceID uniquely identifies the app instance. + */ +@property(nonatomic, readonly, copy) NSString *instanceID; + +/* + * Returns a Firebase Messaging scoped token for the firebase app. + */ +@property(nonatomic, readonly, copy) NSString *token; + +@end + +/** + * Instance ID provides a unique identifier for each app instance and a mechanism + * to authenticate and authorize actions (for example, sending an FCM message). + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * Instance ID is long lived but, may be reset if the device is not used for + * a long time or the Instance ID service detects a problem. + * If Instance ID is reset, the app will be notified via + * `kFIRInstanceIDTokenRefreshNotification`. + * + * If the Instance ID has become invalid, the app can request a new one and + * send it to the app server. + * To prove ownership of Instance ID and to allow servers to access data or + * services associated with the app, call + * `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + */ +NS_SWIFT_NAME(InstanceID) +@interface FIRInstanceID : NSObject + +/** + * FIRInstanceID. + * + * @return A shared instance of FIRInstanceID. + */ ++ (instancetype)instanceID NS_SWIFT_NAME(instanceID()); + +/** + * Unavailable. Use +instanceID instead. + */ +- (instancetype)init __attribute__((unavailable("Use +instanceID instead."))); + +#pragma mark - Tokens + +/** + * Returns a result of app instance identifier InstanceID and a Firebase Messaging scoped token. + * param handler The callback handler invoked when an app instanceID and a default token + * are generated and returned. If instanceID and token fetching fail for some + * reason the callback is invoked with nil `result` and the appropriate error. + */ +- (void)instanceIDWithHandler:(FIRInstanceIDResultHandler)handler; + +/** + * Returns a token that authorizes an Entity (example: cloud service) to perform + * an action on behalf of the application identified by Instance ID. + * + * This is similar to an OAuth2 token except, it applies to the + * application instance instead of a user. + * + * This is an asynchronous call. If the token fetching fails for some reason + * we invoke the completion callback with nil `token` and the appropriate + * error. + * + * This generates an Instance ID if it does not exist yet, which starts periodically sending + * information to the Firebase backend (see `[FIRInstanceID getIDWithHandler:]`). + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at any point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an + * error with code `OperationInProgress`. + * + * @see FIRInstanceID deleteTokenWithAuthorizedEntity:scope:handler: + * + * @param authorizedEntity Entity authorized by the token. + * @param scope Action authorized for authorizedEntity. + * @param options The extra options to be sent with your token request. The + * value for the `apns_token` should be the NSData object + * passed to the UIApplicationDelegate's + * `didRegisterForRemoteNotificationsWithDeviceToken` method. + * The value for `apns_sandbox` should be a boolean (or an + * NSNumber representing a BOOL in Objective-C) set to true if + * your app is a debug build, which means that the APNs + * device token is for the sandbox environment. It should be + * set to false otherwise. If the `apns_sandbox` key is not + * provided, an automatically-detected value shall be used. + * @param handler The callback handler which is invoked when the token is + * successfully fetched. In case of success a valid `token` and + * `nil` error are returned. In case of any error the `token` + * is nil and a valid `error` is returned. The valid error + * codes have been documented above. + */ +- (void)tokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + options:(nullable NSDictionary *)options + handler:(FIRInstanceIDTokenHandler)handler; + +/** + * Revokes access to a scope (action) for an entity previously + * authorized by `[FIRInstanceID tokenWithAuthorizedEntity:scope:options:handler]`. + * + * This is an asynchronous call. Call this on the main thread since InstanceID lib + * is not thread safe. In case token deletion fails for some reason we invoke the + * `handler` callback passed in with the appropriate error code. + * + * Note, you can only have one `token` or `deleteToken` call for a given + * authorizedEntity and scope at a point of time. Making another such call with the + * same authorizedEntity and scope before the last one finishes will result in an error + * with code `OperationInProgress`. + * + * @param authorizedEntity Entity that must no longer have access. + * @param scope Action that entity is no longer authorized to perform. + * @param handler The handler that is invoked once the unsubscribe call ends. + * In case of error an appropriate error object is returned + * else error is nil. + */ +- (void)deleteTokenWithAuthorizedEntity:(NSString *)authorizedEntity + scope:(NSString *)scope + handler:(FIRInstanceIDDeleteTokenHandler)handler; + +#pragma mark - Identity + +/** + * Asynchronously fetch a stable identifier that uniquely identifies the app + * instance. If the identifier has been revoked or has expired, this method will + * return a new identifier. + * + * Once an InstanceID is generated, the library periodically sends information about the + * application and the device where it's running to the Firebase backend. To stop this. see + * `[FIRInstanceID deleteIDWithHandler:]`. + * + * @param handler The handler to invoke once the identifier has been fetched. + * In case of error an appropriate error object is returned else + * a valid identifier is returned and a valid identifier for the + * application instance. + */ +- (void)getIDWithHandler:(FIRInstanceIDHandler)handler NS_SWIFT_NAME(getID(handler:)); + +/** + * Resets Instance ID and revokes all tokens. + * + * This method also triggers a request to fetch a new Instance ID and Firebase Messaging scope + * token. Please listen to kFIRInstanceIDTokenRefreshNotification when the new ID and token are + * ready. + * + * This stops the periodic sending of data to the Firebase backend that began when the Instance ID + * was generated. No more data is sent until another library calls Instance ID internally again + * (like FCM, RemoteConfig or Analytics) or user explicitly calls Instance ID APIs to get an + * Instance ID and token again. + */ +- (void)deleteIDWithHandler:(FIRInstanceIDDeleteHandler)handler NS_SWIFT_NAME(deleteID(handler:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h new file mode 100644 index 0000000..78c9ef1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/Firebase/InstanceID/Public/FirebaseInstanceID.h @@ -0,0 +1,17 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRInstanceID.h" diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseInstanceID/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m new file mode 100644 index 0000000..ea5f02e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage.m @@ -0,0 +1,262 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import + +#import "FirebaseStorage/Sources/FIRStorageComponent.h" +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStoragePath.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import +#import +#import +#import + +#import +#import + +static NSMutableDictionary< + NSString * /* app name */, + NSMutableDictionary *> *_fetcherServiceMap; +static GTMSessionFetcherRetryBlock _retryWhenOffline; + +@interface FIRStorage () { + /// Stored Auth reference, if it exists. This needs to be stored for `copyWithZone:`. + id _Nullable _auth; +} +@end + +@implementation FIRStorage + ++ (void)initialize { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _retryWhenOffline = ^(BOOL suggestedWillRetry, NSError *GTM_NULLABLE_TYPE error, + GTMSessionFetcherRetryResponse response) { + bool shouldRetry = suggestedWillRetry; + // GTMSessionFetcher does not consider being offline a retryable error, but we do, so we + // special-case it here. + if (!shouldRetry && error) { + shouldRetry = error.code == NSURLErrorNotConnectedToInternet; + } + response(shouldRetry); + }; + _fetcherServiceMap = [[NSMutableDictionary alloc] init]; + }); +} + ++ (GTMSessionFetcherService *)fetcherServiceForApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth { + @synchronized(_fetcherServiceMap) { + NSMutableDictionary *bucketMap = _fetcherServiceMap[app.name]; + if (!bucketMap) { + bucketMap = [[NSMutableDictionary alloc] init]; + _fetcherServiceMap[app.name] = bucketMap; + } + + GTMSessionFetcherService *fetcherService = bucketMap[bucket]; + if (!fetcherService) { + fetcherService = [[GTMSessionFetcherService alloc] init]; + [fetcherService setRetryEnabled:YES]; + [fetcherService setRetryBlock:_retryWhenOffline]; + FIRStorageTokenAuthorizer *authorizer = + [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:app.options.googleAppID + fetcherService:fetcherService + authProvider:auth]; + [fetcherService setAuthorizer:authorizer]; + bucketMap[bucket] = fetcherService; + } + return fetcherService; + } +} + ++ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled { + [GTMSessionFetcher setLoggingEnabled:isLoggingEnabled]; +} + ++ (instancetype)storage { + return [self storageForApp:[FIRApp defaultApp]]; +} + ++ (instancetype)storageForApp:(FIRApp *)app { + if (app.options.storageBucket) { + NSString *url = [app.options.storageBucket isEqualToString:@""] + ? @"" + : [@"gs://" stringByAppendingString:app.options.storageBucket]; + return [self storageForApp:app URL:url]; + } else { + NSString *const kAppNotConfiguredMessage = + @"No default Storage bucket found. Did you configure Firebase Storage properly?"; + [NSException raise:NSInvalidArgumentException format:kAppNotConfiguredMessage]; + return nil; + } +} + ++ (instancetype)storageWithURL:(NSString *)url { + return [self storageForApp:[FIRApp defaultApp] URL:url]; +} + ++ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url { + NSString *bucket; + if ([url isEqualToString:@""]) { + bucket = @""; + } else { + FIRStoragePath *path; + + @try { + path = [FIRStoragePath pathFromGSURI:url]; + } @catch (NSException *e) { + [NSException raise:NSInternalInconsistencyException + format:@"URI must be in the form of gs:///"]; + } + + if (path.object != nil && ![path.object isEqualToString:@""]) { + [NSException raise:NSInternalInconsistencyException + format:@"Storage bucket cannot be initialized with a path"]; + } + + bucket = path.bucket; + } + + // Retrieve the instance provider from the app's container to inject dependencies as needed. + id provider = + FIR_COMPONENT(FIRStorageMultiBucketProvider, app.container); + return [provider storageForBucket:bucket]; +} + +- (instancetype)initWithApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth { + self = [super init]; + if (self) { + _app = app; + _auth = auth; + _storageBucket = bucket; + _dispatchQueue = dispatch_queue_create("com.google.firebase.storage", DISPATCH_QUEUE_SERIAL); + _fetcherServiceForApp = [FIRStorage fetcherServiceForApp:_app bucket:bucket auth:auth]; + _maxDownloadRetryTime = 600.0; + _maxOperationRetryTime = 120.0; + _maxUploadRetryTime = 600.0; + } + return self; +} + +- (instancetype)init { + NSAssert(false, @"Storage cannot be directly instantiated, use " + "Storage.storage() or Storage.storage(app:) instead"); + return nil; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorage *storage = [[[self class] allocWithZone:zone] initWithApp:_app + bucket:_storageBucket + auth:_auth]; + storage.callbackQueue = self.callbackQueue; + return storage; +} + +// Two FIRStorage objects are equal if they use the same app +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorage class]]) { + return NO; + } + + BOOL isEqualObject = [self isEqualToFIRStorage:(FIRStorage *)object]; + return isEqualObject; +} + +- (BOOL)isEqualToFIRStorage:(FIRStorage *)storage { + BOOL isEqual = + [_app isEqual:storage.app] && [_storageBucket isEqualToString:storage.storageBucket]; + return isEqual; +} + +- (NSUInteger)hash { + NSUInteger hash = [_app hash] ^ [self.callbackQueue hash]; + return hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, _app]; +} + +#pragma mark - Public methods + +- (FIRStorageReference *)reference { + FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:_storageBucket object:nil]; + return [[FIRStorageReference alloc] initWithStorage:self path:path]; +} + +- (FIRStorageReference *)referenceForURL:(NSString *)string { + FIRStoragePath *path = [FIRStoragePath pathFromString:string]; + + // If no default bucket exists (empty string), accept anything. + if ([_storageBucket isEqual:@""]) { + FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path]; + return reference; + } + + // If there exists a default bucket, throw if provided a different bucket. + if (![path.bucket isEqual:_storageBucket]) { + NSString *const kInvalidBucketFormat = + @"Provided bucket: %@ does not match the Storage bucket of the current instance: %@"; + [NSException raise:NSInvalidArgumentException + format:kInvalidBucketFormat, path.bucket, _storageBucket]; + } + + FIRStorageReference *reference = [[FIRStorageReference alloc] initWithStorage:self path:path]; + return reference; +} + +- (FIRStorageReference *)referenceWithPath:(NSString *)string { + FIRStorageReference *reference = [[self reference] child:string]; + return reference; +} + +- (dispatch_queue_t)callbackQueue { + return _fetcherServiceForApp.callbackQueue; +} + +- (void)setCallbackQueue:(dispatch_queue_t)callbackQueue { + _fetcherServiceForApp.callbackQueue = callbackQueue; +} + +#pragma mark - Background tasks + ++ (void)enableBackgroundTasks:(BOOL)isEnabled { + [NSException raise:NSGenericException format:@"enableBackgroundTasks not implemented"]; +} + +- (NSArray *)uploadTasks { + [NSException raise:NSGenericException format:@"getUploadTasks not implemented"]; + return nil; +} + +- (NSArray *)downloadTasks { + [NSException raise:NSGenericException format:@"getDownloadTasks not implemented"]; + return nil; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h new file mode 100644 index 0000000..ac3637b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.h @@ -0,0 +1,45 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +@class FIRApp; +@class FIRStorage; + +NS_ASSUME_NONNULL_BEGIN + +/// This protocol is used in the interop registration process to register an instance provider for +/// individual FIRApps. +@protocol FIRStorageMultiBucketProvider + +/// Default method for creating a Storage instance. +- (FIRStorage *)storageForBucket:(NSString *)bucket; + +@end + +/// A concrete implementation for FIRStorageMultiBucketProvider to create Storage instances. +@interface FIRStorageComponent : NSObject + +/// The FIRApp that instances will be set up with. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Default method for creating a Storage instance. +- (FIRStorage *)storageForBucket:(NSString *)bucket; + +/// Unavailable, use `storageForApp:storageURL:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m new file mode 100644 index 0000000..55cfcc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageComponent.m @@ -0,0 +1,88 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageComponent.h" + +#import + +#import +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorage () +// Surface the internal initializer to create instances of FIRStorage. +- (instancetype)initWithApp:(FIRApp *)app + bucket:(NSString *)bucket + auth:(nullable id)auth; +@end + +@interface FIRStorageComponent () +/// Internal initializer. +- (instancetype)initWithApp:(FIRApp *)app; +@end + +@implementation FIRStorageComponent + +#pragma mark - Initialization + +- (instancetype)initWithApp:(FIRApp *)app { + self = [super init]; + if (self) { + _app = app; + } + return self; +} + +#pragma mark - Lifecycle + ++ (void)load { + [FIRApp registerInternalLibrary:(Class)self + withName:@"fire-str" + withVersion:[NSString stringWithUTF8String:FIRStorageVersionString]]; +} + +#pragma mark - FIRComponentRegistrant + ++ (nonnull NSArray *)componentsToRegister { + FIRDependency *authDep = [FIRDependency dependencyWithProtocol:@protocol(FIRAuthInterop) + isRequired:NO]; + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + return [[FIRStorageComponent alloc] initWithApp:container.app]; + }; + FIRComponent *storageProvider = + [FIRComponent componentWithProtocol:@protocol(FIRStorageMultiBucketProvider) + instantiationTiming:FIRInstantiationTimingLazy + dependencies:@[ authDep ] + creationBlock:creationBlock]; + + return @[ storageProvider ]; +} + +#pragma mark - FIRStorageInstanceProvider Conformance + +- (FIRStorage *)storageForBucket:(NSString *)bucket { + // Create an instance of FIRStorage and return it. + id auth = FIR_COMPONENT(FIRAuthInterop, self.app.container); + return [[FIRStorage alloc] initWithApp:self.app bucket:bucket auth:auth]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m new file mode 100644 index 0000000..11dbfa0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants.m @@ -0,0 +1,92 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +NSString *const kGCSScheme = @"https"; +NSString *const kGCSHost = @"www.googleapis.com"; +NSString *const kGCSUploadPath = @"upload"; +NSString *const kGCSStorageVersionPath = @"storage/v1"; +NSString *const kGCSBucketPathFormat = @"b/%@"; +NSString *const kGCSObjectPathFormat = @"o/%@"; + +NSString *const kFIRStorageScheme = @"https"; +NSString *const kFIRStorageHost = @"firebasestorage.googleapis.com"; +NSString *const kFIRStorageVersionPath = @"v0"; +NSString *const kFIRStorageBucketPathFormat = @"b/%@"; +NSString *const kFIRStorageObjectPathFormat = @"o/%@"; +NSString *const kFIRStorageFullPathFormat = @"/v0/b/%@/o/%@"; + +NSString *const kFIRStorageAuthTokenFormat = @"Firebase %@"; +NSString *const kFIRStorageDefaultBucketFormat = @"gs://%@"; + +NSString *const kFIRStorageResponseErrorDomain = @"ResponseErrorDomain"; +NSString *const kFIRStorageResponseErrorCode = @"ResponseErrorCode"; +NSString *const kFIRStorageResponseBody = @"ResponseBody"; + +NSString *const FIRStorageErrorDomain = @"FIRStorageErrorDomain"; + +NSString *const kFIRStorageInvalidDataFormat = @"Invalid data returned from the server: %@"; +NSString *const kFIRStorageInvalidObserverStatus = + @"Invalid observer status requested, use one " + @"of: FIRStorageTaskStatusPause, Resume, Progress, " + @"Complete, or Failure"; + +/** + * String constants mapping GCS Object#list results to ListResult fields. + */ +NSString *const kFIRStorageListPrefixes = @"prefixes"; +NSString *const kFIRStorageListItems = @"items"; +NSString *const kFIRStorageListItemName = @"name"; +NSString *const kFIRStorageListPageToken = @"nextPageToken"; + +/** + * String constants mapping GCS Object#resource mappings to metadata fields. + */ +NSString *const kFIRStorageMetadataBucket = @"bucket"; +NSString *const kFIRStorageMetadataCacheControl = @"cacheControl"; +NSString *const kFIRStorageMetadataContentDisposition = @"contentDisposition"; +NSString *const kFIRStorageMetadataContentEncoding = @"contentEncoding"; +NSString *const kFIRStorageMetadataContentLanguage = @"contentLanguage"; +NSString *const kFIRStorageMetadataContentType = @"contentType"; +NSString *const kFIRStorageMetadataCustomMetadata = @"metadata"; +NSString *const kFIRStorageMetadataSize = @"size"; +NSString *const kFIRStorageMetadataGeneration = @"generation"; +NSString *const kFIRStorageMetadataMetageneration = @"metageneration"; +NSString *const kFIRStorageMetadataTimeCreated = @"timeCreated"; +NSString *const kFIRStorageMetadataUpdated = @"updated"; +NSString *const kFIRStorageMetadataName = @"name"; +NSString *const kFIRStorageMetadataDownloadTokens = @"downloadTokens"; +NSString *const kFIRStorageMetadataMd5Hash = @"md5Hash"; + +// TODO: add notification support +NSString *const kFIRStorageTaskStatusResumeNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusPauseNotification = @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusProgressNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusCompleteNotification = + @"kFIRStorageTaskStatusResumeNotification"; +NSString *const kFIRStorageTaskStatusFailureNotification = + @"kFIRStorageTaskStatusResumeNotification"; + +NSString *const kFIRStorageBundleIdentifier = @"com.google.firebase.storage"; + +// The STR and STR_EXPAND macro allow a numeric version passed to he compiler driver +// with a -D to be treated as a string instead of an invalid floating point value. +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +const char *const FIRStorageVersionString = (const char *const)STR(FIRStorage_VERSION); diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h new file mode 100644 index 0000000..76c382d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageConstants_Private.h @@ -0,0 +1,150 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageMetadata; + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXPORT NSString *const kGCSScheme; +FOUNDATION_EXPORT NSString *const kGCSHost; +FOUNDATION_EXPORT NSString *const kGCSUploadPath; +FOUNDATION_EXPORT NSString *const kGCSStorageVersionPath; +FOUNDATION_EXPORT NSString *const kGCSBucketPathFormat; +FOUNDATION_EXPORT NSString *const kGCSObjectPathFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageScheme; +FOUNDATION_EXPORT NSString *const kFIRStorageHost; +FOUNDATION_EXPORT NSString *const kFIRStorageVersionPath; +FOUNDATION_EXPORT NSString *const kFIRStorageBucketPathFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageObjectPathFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageFullPathFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageAuthTokenFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageDefaultBucketFormat; + +FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorDomain; +FOUNDATION_EXPORT NSString *const kFIRStorageResponseErrorCode; +FOUNDATION_EXPORT NSString *const kFIRStorageResponseBody; + +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusResumeNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusPauseNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusProgressNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusCompleteNotification; +FOUNDATION_EXPORT NSString *const kFIRStorageTaskStatusFailureNotification; + +FOUNDATION_EXPORT NSString *const kFIRStorageListPrefixes; +FOUNDATION_EXPORT NSString *const kFIRStorageListItems; +FOUNDATION_EXPORT NSString *const kFIRStorageListItemName; +FOUNDATION_EXPORT NSString *const kFIRStorageListPageToken; + +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataBucket; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCacheControl; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentDisposition; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentEncoding; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentLanguage; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataContentType; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataCustomMetadata; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataSize; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataGeneration; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMetageneration; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataTimeCreated; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataUpdated; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataName; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataDownloadTokens; +FOUNDATION_EXPORT NSString *const kFIRStorageMetadataMd5Hash; + +FOUNDATION_EXPORT NSString *const kFIRStorageInvalidDataFormat; +FOUNDATION_EXPORT NSString *const kFIRStorageInvalidObserverStatus; + +FOUNDATION_EXPORT NSString *const kFIRStorageBundleIdentifier; + +/** + * Enum representing the internal state of an upload or download task. + */ +typedef NS_ENUM(NSInteger, FIRStorageTaskState) { + /** + * Unknown task state + */ + FIRStorageTaskStateUnknown, + + /** + * Task is being queued is ready to run + */ + FIRStorageTaskStateQueueing, + + /** + * Task is resuming from a paused state + */ + FIRStorageTaskStateResuming, + + /** + * Task is currently running + */ + FIRStorageTaskStateRunning, + + /** + * Task reporting a progress event + */ + FIRStorageTaskStateProgress, + + /** + * Task is pausing + */ + FIRStorageTaskStatePausing, + + /** + * Task is completing successfully + */ + FIRStorageTaskStateCompleting, + + /** + * Task is failing unrecoverably + */ + FIRStorageTaskStateFailing, + + /** + * Task paused successfully + */ + FIRStorageTaskStatePaused, + + /** + * Task cancelled successfully + */ + FIRStorageTaskStateCancelled, + + /** + * Task completed successfully + */ + FIRStorageTaskStateSuccess, + + /** + * Task failed unrecoverably + */ + FIRStorageTaskStateFailed +}; + +/** + * Represents the various types of metadata: Files or Folders. + */ +typedef NS_ENUM(NSUInteger, FIRStorageMetadataType) { + FIRStorageMetadataTypeUnknown, + FIRStorageMetadataTypeFile, + FIRStorageMetadataTypeFolder, +}; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h new file mode 100644 index 0000000..02fcf62 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to delete an object in Firebase Storage. + */ +@interface FIRStorageDeleteTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m new file mode 100644 index 0000000..1bb443e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDeleteTask.m @@ -0,0 +1,83 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageDeleteTask.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageDeleteTask { + @private + FIRStorageVoidError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)enqueue { + __weak FIRStorageDeleteTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageDeleteTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"DELETE"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + + fetcher.comment = @"DeleteTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + if (callback) { + callback(self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diangostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m new file mode 100644 index 0000000..c551c3c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask.m @@ -0,0 +1,189 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageDownloadTask + +@synthesize progress = _progress; +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(nullable NSURL *)fileURL { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _fileURL = [fileURL copy]; + _progress = [NSProgress progressWithTotalUnitCount:0]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + [self enqueueWithData:nil]; +} + +- (void)enqueueWithData:(nullable NSData *)resumeData { + __weak FIRStorageDownloadTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageDownloadTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + strongSelf.state = FIRStorageTaskStateQueueing; + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxDownloadRetryTime; + NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL + resolvingAgainstBaseURL:NO]; + [components setQuery:@"alt=media"]; + request.URL = components.URL; + + GTMSessionFetcher *fetcher; + if (resumeData) { + fetcher = [GTMSessionFetcher fetcherWithDownloadResumeData:resumeData]; + fetcher.comment = @"Resuming DownloadTask"; + } else { + fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + fetcher.comment = @"Starting DownloadTask"; + } + + [fetcher setResumeDataBlock:^(NSData *data) { + FIRStorageDownloadTask *strong = weakSelf; + if (strong && data) { + strong->_downloadData = data; + } + }]; + + fetcher.maxRetryInterval = strongSelf.reference.storage.maxDownloadRetryTime; + + if (strongSelf->_fileURL) { + // Handle file downloads + [fetcher setDestinationFileURL:strongSelf->_fileURL]; + [fetcher setDownloadProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesWritten; + weakSelf.progress.totalUnitCount = totalBytesExpectedToWrite; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + } else { + // Handle data downloads + [fetcher setReceivedProgressBlock:^(int64_t bytesWritten, int64_t totalBytesWritten) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesWritten; + int64_t totalLength = [[weakSelf.fetcher response] expectedContentLength]; + weakSelf.progress.totalUnitCount = totalLength; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + } + + strongSelf->_fetcher = fetcher; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + // Fire last progress updates + [self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot]; + + // Handle potential issues with download + if (error) { + self.state = FIRStorageTaskStateFailed; + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + [self fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; + return; + } + + // Download completed successfully, fire completion callbacks + self.state = FIRStorageTaskStateSuccess; + + if (data) { + self->_downloadData = data; + } + + [self fireHandlersForStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + strongSelf.state = FIRStorageTaskStateRunning; + [strongSelf.fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +#pragma mark - Download Management + +- (void)cancel { + NSError *error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled]; + [self cancelWithError:error]; +} + +- (void)cancelWithError:(NSError *)error { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateCancelled; + [weakSelf.fetcher stopFetching]; + weakSelf.error = error; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot]; + }]; +} + +- (void)pause { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStatePausing; + [weakSelf.fetcher stopFetching]; + // Give the resume callback a chance to run (if scheduled) + [weakSelf.fetcher waitForCompletionWithTimeout:0.001]; + weakSelf.state = FIRStorageTaskStatePaused; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:snapshot]; + }]; +} + +- (void)resume { + __weak FIRStorageDownloadTask *weakSelf = self; + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateResuming; + FIRStorageTaskSnapshot *snapshot = weakSelf.snapshot; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + [weakSelf enqueueWithData:weakSelf.downloadData]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h new file mode 100644 index 0000000..1b68205 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h @@ -0,0 +1,59 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class FIRStorageReference; +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageDownloadTask () + +/** + * Bytes which have been downloaded so far. + */ +@property(readonly, nonatomic) NSData *downloadData; + +/** + * The file on disk to write to. + */ +@property(copy, nonatomic) NSURL *fileURL; + +/** + * Initializes a download task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param fileURL The system URL to download to. If nil, download in memory as bytes. + * @return Returns an instance of FIRStorageDownloadTask + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(nullable NSURL *)fileURL; + +/** + * Cancels the download task and passes an appropriate error to the developer. + * @param error NSError to propegate to the developer. + */ +- (void)cancelWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h new file mode 100644 index 0000000..99648c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.h @@ -0,0 +1,70 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; + +/** + * Adds wrappers for common Firebase Storage errors (including creating errors from GCS errors). + * For more information on unwrapping GCS errors, see the GCS errors docs: + * https://cloud.google.com/storage/docs/json_api/v1/status-codes + * This is never publicly exposed to end developers (as they will simply see an NSError). + */ +@interface FIRStorageErrors : NSObject + +/** + * Creates a Firebase Storage error from a specific FIRStorageErrorCode. + */ ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code; + +/** + * Creates a Firebase Storage error from a specific FIRStorageErrorCode while adding + * custom info from an optionally provided info dictionary. + */ ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code + infoDictionary:(nullable NSDictionary *)dictionary; + +/** + * Creates a Firebase Storage error from a specific GCS error and FIRStorageReference. + * @param error Server error to wrap and return as a Firebase Storage error. + * @param reference FIRStorageReference which provides context about the request being made. + * @return Returns a Firebase Storage error, or nil if no error is provided. + */ ++ (nullable NSError *)errorWithServerError:(nullable NSError *)error + reference:(nullable FIRStorageReference *)reference; + +/** + * Creates a Firebase Storage error from an invalid request. + * + * @param request The NSData representation of the invalid user request. + * @return Returns the corresponding Firebase Storage error. + */ ++ (NSError *)errorWithInvalidRequest:(NSData *)request; + +/** + * Creates a Firebase Storage error with a custom error message. + * + * @param errorMessage A custom error message. + * @return Returns the corresponding Firebase Storage error. + */ ++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m new file mode 100644 index 0000000..1301d06 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageErrors.m @@ -0,0 +1,189 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageErrors.h" + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" + +@implementation FIRStorageErrors + ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code { + return [FIRStorageErrors errorWithCode:code infoDictionary:nil]; +} + ++ (NSError *)errorWithCode:(FIRStorageErrorCode)code + infoDictionary:(nullable NSDictionary *)dictionary { + NSMutableDictionary *errorDictionary; + if (dictionary) { + errorDictionary = [dictionary mutableCopy]; + } else { + errorDictionary = [[NSMutableDictionary alloc] init]; + } + + NSString *errorMessage; + switch (code) { + case FIRStorageErrorCodeObjectNotFound: + errorMessage = + [NSString stringWithFormat:@"Object %@ does not exist.", errorDictionary[@"object"]]; + break; + + case FIRStorageErrorCodeBucketNotFound: + errorMessage = + [NSString stringWithFormat:@"Bucket %@ does not exist.", errorDictionary[@"bucket"]]; + break; + + case FIRStorageErrorCodeProjectNotFound: + errorMessage = + [NSString stringWithFormat:@"Project %@ does not exist.", errorDictionary[@"project"]]; + break; + + case FIRStorageErrorCodeQuotaExceeded: { + NSString *const kQuotaExceededFormat = + @"Quota for bucket %@ exceeded, please view quota on firebase.google.com."; + errorMessage = [NSString stringWithFormat:kQuotaExceededFormat, errorDictionary[@"bucket"]]; + break; + } + + case FIRStorageErrorCodeDownloadSizeExceeded: { + int64_t total = [errorDictionary[@"totalSize"] longLongValue]; + int64_t size = [errorDictionary[@"maxAllowedSize"] longLongValue]; + NSString *totalString = total ? @(total).stringValue : @"unknown"; + NSString *sizeString = total ? @(size).stringValue : @"unknown"; + NSString *const kSizeExceededErrorFormat = + @"Attempted to download object with size of %@ bytes, " + @"which exceeds the maximum size of %@ bytes. " + @"Consider raising the maximum download size, or using " + @"[FIRStorageReference writeToFile:]"; + errorMessage = [NSString stringWithFormat:kSizeExceededErrorFormat, totalString, sizeString]; + break; + } + + case FIRStorageErrorCodeUnauthenticated: + errorMessage = @"User is not authenticated, please authenticate using Firebase " + @"Authentication and try again."; + break; + + case FIRStorageErrorCodeUnauthorized: { + NSString *bucket = errorDictionary[@"bucket"]; + NSString *object = errorDictionary[@"object"]; + NSString *const kUnauthorizedFormat = @"User does not have permission to access gs://%@/%@."; + errorMessage = [NSString stringWithFormat:kUnauthorizedFormat, bucket, object]; + break; + } + + case FIRStorageErrorCodeRetryLimitExceeded: + errorMessage = @"Max retry time for operation exceeded, please try again."; + break; + + case FIRStorageErrorCodeNonMatchingChecksum: { + // TODO: replace with actual checksum strings when we choose to implement. + NSString *const kChecksumFailedErrorFormat = + @"Uploaded/downloaded object %@ has checksum: %@ " + @"which does not match server checksum: %@. Please retry the upload/download."; + errorMessage = [NSString stringWithFormat:kChecksumFailedErrorFormat, @"object", + @"client checksum", @"server checksum"]; + break; + } + + case FIRStorageErrorCodeCancelled: + errorMessage = @"User cancelled the upload/download."; + break; + + case FIRStorageErrorCodeUnknown: + /* Fall through to default case for unknown errors */ + + default: + errorMessage = @"An unknown error occurred, please check the server response."; + break; + } + + errorDictionary[NSLocalizedDescriptionKey] = errorMessage; + + NSError *err = [NSError errorWithDomain:FIRStorageErrorDomain code:code userInfo:errorDictionary]; + return err; +} + ++ (nullable NSError *)errorWithServerError:(nullable NSError *)error + reference:(nullable FIRStorageReference *)reference { + if (error == nil) { + return nil; + } + + FIRStorageErrorCode errorCode; + switch (error.code) { + case 400: + errorCode = FIRStorageErrorCodeUnknown; + break; + + case 401: + errorCode = FIRStorageErrorCodeUnauthenticated; + break; + + case 402: + errorCode = FIRStorageErrorCodeQuotaExceeded; + break; + + case 403: + errorCode = FIRStorageErrorCodeUnauthorized; + break; + + case 404: + errorCode = FIRStorageErrorCodeObjectNotFound; + break; + + default: + errorCode = FIRStorageErrorCodeUnknown; + break; + } + + NSMutableDictionary *errorDictionary = + [[[NSDictionary alloc] initWithDictionary:error.userInfo] mutableCopy]; + errorDictionary[kFIRStorageResponseErrorDomain] = error.domain; + errorDictionary[kFIRStorageResponseErrorCode] = @(error.code); + + // Turn raw response into a string + NSData *responseData = errorDictionary[@"data"]; + if (responseData) { + NSString *errorString = [[NSString alloc] initWithData:responseData + encoding:NSUTF8StringEncoding]; + errorDictionary[kFIRStorageResponseBody] = errorString ?: @"No Response from Server."; + } + + errorDictionary[@"bucket"] = reference.path.bucket; + errorDictionary[@"object"] = reference.path.object; + + NSError *clientError = [FIRStorageErrors errorWithCode:errorCode infoDictionary:errorDictionary]; + return clientError; +} + ++ (NSError *)errorWithInvalidRequest:(NSData *)request { + NSString *requestString = [[NSString alloc] initWithData:request encoding:NSUTF8StringEncoding]; + NSString *invalidDataString = + [NSString stringWithFormat:kFIRStorageInvalidDataFormat, requestString]; + NSDictionary *dict; + if (invalidDataString.length > 0) { + dict = @{NSLocalizedFailureReasonErrorKey : invalidDataString}; + } + return [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnknown infoDictionary:dict]; +} + ++ (NSError *)errorWithCustomMessage:(NSString *)errorMessage { + return [NSError errorWithDomain:FIRStorageErrorDomain + code:FIRStorageErrorCodeUnknown + userInfo:@{NSLocalizedDescriptionKey : errorMessage}]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h new file mode 100644 index 0000000..0611695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get a download URL for an object in Firebase Storage. + */ +@interface FIRStorageGetDownloadURLTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidURLError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m new file mode 100644 index 0000000..f7422b2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m @@ -0,0 +1,126 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageGetDownloadURLTask { + @private + FIRStorageVoidURLError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidURLError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + ++ (NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary { + NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens]; + + if (downloadTokens && downloadTokens.length > 0) { + NSArray *downloadTokenArray = [downloadTokens componentsSeparatedByString:@","]; + NSString *bucket = dictionary[kFIRStorageMetadataBucket]; + NSString *path = dictionary[kFIRStorageMetadataName]; + NSString *fullPath = [NSString stringWithFormat:kFIRStorageFullPathFormat, bucket, + [FIRStorageUtils GCSEscapedString:path]]; + + NSURLComponents *components = [[NSURLComponents alloc] init]; + components.scheme = kFIRStorageScheme; + components.host = kFIRStorageHost; + components.percentEncodedPath = fullPath; + + // The backend can return an arbitrary number of download tokens, but we only expose the first + // token via the download URL. + NSURLQueryItem *altItem = [[NSURLQueryItem alloc] initWithName:@"alt" value:@"media"]; + NSURLQueryItem *tokenItem = [[NSURLQueryItem alloc] initWithName:@"token" + value:downloadTokenArray[0]]; + components.queryItems = @[ altItem, tokenItem ]; + + return [components URL]; + } + + return nil; +} + +- (void)enqueue { + __weak FIRStorageGetDownloadURLTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageGetDownloadURLTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidURLError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"GetDownloadURLTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + NSURL *downloadURL; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + downloadURL = + [FIRStorageGetDownloadURLTask downloadURLFromMetadataDictionary:responseDictionary]; + if (!downloadURL) { + self.error = + [FIRStorageErrors errorWithCustomMessage:@"Failed to retrieve a download URL."]; + } + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(downloadURL, self.error); + } + + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +}; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h new file mode 100644 index 0000000..a4b5ff8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get a download URL for an object in Firebase Storage. + */ +@interface FIRStorageGetDownloadURLTask () + +/** Extracts a download URL from the StorageMetadata dictonary representation. */ ++ (nullable NSURL *)downloadURLFromMetadataDictionary:(NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h new file mode 100644 index 0000000..a14c44f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.h @@ -0,0 +1,35 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability to get metadata on an object in Firebase Storage. + */ +@interface FIRStorageGetMetadataTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidMetadataError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m new file mode 100644 index 0000000..3a947e7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageGetMetadataTask.m @@ -0,0 +1,97 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h" + +#import +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +@implementation FIRStorageGetMetadataTask { + @private + FIRStorageVoidMetadataError _completion; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + completion:(FIRStorageVoidMetadataError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageGetMetadataTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageGetMetadataTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidMetadataError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"GetMetadataTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(metadata, self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m new file mode 100644 index 0000000..7a02651 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult.m @@ -0,0 +1,73 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@implementation FIRStorageListResult + ++ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary *)dictionary + atReference:(FIRStorageReference *)reference { + NSMutableArray *prefixes = [NSMutableArray new]; + NSMutableArray *items = [NSMutableArray new]; + + FIRStorageReference *rootReference = reference.root; + + NSArray *prefixEntries = dictionary[kFIRStorageListPrefixes]; + for (NSString *prefixEntry in prefixEntries) { + NSString *pathWithoutTrailingSlash = prefixEntry; + if ([prefixEntry hasSuffix:@"/"]) { + pathWithoutTrailingSlash = [pathWithoutTrailingSlash substringToIndex:prefixEntry.length - 1]; + } + + FIRStorageReference *prefixReference = [rootReference child:pathWithoutTrailingSlash]; + NSAssert([prefixReference.fullPath hasPrefix:reference.fullPath], + @"Expected %@ to be a child element of %@", reference, prefixReference); + [prefixes addObject:prefixReference]; + } + + NSArray *> *itemEntries = dictionary[kFIRStorageListItems]; + for (NSDictionary *itemEntry in itemEntries) { + FIRStorageReference *itemReference = [rootReference child:itemEntry[kFIRStorageListItemName]]; + NSAssert([itemReference.fullPath hasPrefix:reference.fullPath], + @"Expected %@ to be a child element of %@", reference, itemReference); + [items addObject:itemReference]; + } + + NSString *pageToken = dictionary[kFIRStorageListPageToken]; + return [[FIRStorageListResult alloc] initWithPrefixes:prefixes items:items pageToken:pageToken]; +} + +- (nullable instancetype)initWithPrefixes:(NSArray *)prefixes + items:(NSArray *)items + pageToken:(nullable NSString *)pageToken { + self = [super init]; + if (self) { + _prefixes = [prefixes copy]; + _items = [items copy]; + _pageToken = [pageToken copy]; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageListResult *clone = [[[self class] allocWithZone:zone] initWithPrefixes:_prefixes + items:_items + pageToken:_pageToken]; + + return clone; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h new file mode 100644 index 0000000..f4a2f54 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListResult_Private.h @@ -0,0 +1,40 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageListResult (Private) + +/** + * Creates an instance of FIRStorageListResult with the contents of a dictionary. + * + * @param dictionary A dictionary containing the parsed JSON response from the backend. + * @param reference The FIRStorageReference that `list()` was called on. + * @return An instance of FIRStorageListResult that represents the contents of the dictionary. + */ ++ (nullable FIRStorageListResult *)fromDictionary:(NSDictionary *)dictionary + atReference:(FIRStorageReference *)reference; + +/** Initializes a new FIRStorageListResult with the given data. */ +- (nullable instancetype)initWithPrefixes:(NSArray *)prefixes + items:(NSArray *)items + pageToken:(nullable NSString *)pageToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h new file mode 100644 index 0000000..ea3fc48 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.h @@ -0,0 +1,57 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Block typedef typically used in `list()` and `listAll()`. + * @param listResult The FIRStorageListResult returned by the operation, if it exists. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidListError)(FIRStorageListResult *_Nullable listResult, + NSError *_Nullable error); + +/** A Task that lists the entries under a {@link StorageReference} */ +@interface FIRStorageListTask : FIRStorageTask + +/** + * Initializes a new List Task. + * + * To schedule the task, invoke `[FIRStorageListTask enqueue]`. + * + * @param reference The location to invoke List on. + * @param service GTMSessionFetcherService to use for the RPC. + * @param queue The queue to schedule the List operation on. + * @param pageSize An optional pageSize, denoting the maximum size of the result set. If + * set to `nil`, the backend will use the default page size. + * @param previousPageToken An optional pageToken, used to resume a previous invocation. + * @param completion The completion handler to be called with the FIRStorageListResult. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + pageSize:(nullable NSNumber *)pageSize + previousPageToken:(nullable NSString *)previousPageToken + completion:(FIRStorageVoidListError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m new file mode 100644 index 0000000..c30bbdc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageListTask.m @@ -0,0 +1,127 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageListTask.h" +#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageListTask { + @private + FIRStorageVoidListError _completion; + NSNumber *_pageSize; + NSString *_previousPageToken; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + pageSize:(nullable NSNumber *)pageSize + previousPageToken:(nullable NSString *)previousPageToken + completion:(FIRStorageVoidListError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _completion = [completion copy]; + _pageSize = pageSize; + _previousPageToken = [previousPageToken copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageListTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageListTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableDictionary *queryParams = [NSMutableDictionary new]; + + NSString *prefix = [self reference].fullPath; + if (prefix.length != 0) { + queryParams[@"prefix"] = [prefix stringByAppendingString:@"/"]; + } + + // Firebase Storage uses file system semantics and treats slashes as separators. GCS's List API + // does not prescribe a separator, and hence we need to provide a slash as the delimiter. + queryParams[@"delimiter"] = @"/"; + + // listAll() doesn't set a pageSize as this allows Firebase Storage to determine how many items + // to return per page. This removes the need to backfill results if Firebase Storage filters + // objects that are considered invalid (such as items with two consecutive slashes). + if (strongSelf->_pageSize != nil) { + queryParams[@"maxResults"] = [strongSelf->_pageSize stringValue]; + } + + if (strongSelf->_previousPageToken) { + queryParams[@"pageToken"] = strongSelf->_previousPageToken; + } + + FIRStoragePath *basePath = [[FIRStoragePath alloc] initWithBucket:self.reference.bucket + object:nil]; + NSMutableURLRequest *request = + [[FIRStorageUtils defaultRequestForPath:basePath queryParams:queryParams] mutableCopy]; + + request.HTTPMethod = @"GET"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + + FIRStorageVoidListError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + fetcher.comment = @"ListTask"; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageListResult *listResult; + if (error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary != nil) { + listResult = [FIRStorageListResult fromDictionary:responseDictionary + atReference:self.reference]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(listResult, self.error); + } + + // Remove retain cycle set up by `strongSelf->_fetcherCompletion` + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m new file mode 100644 index 0000000..c692129 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata.m @@ -0,0 +1,224 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +// TODO: consider rewriting this using GTLR (GTLRStorageObjects.h) +@implementation FIRStorageMetadata + +#pragma mark - Initializers + +- (instancetype)init { + return [self initWithDictionary:[NSDictionary dictionary]]; +} + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + if (self) { + _initialMetadata = [dictionary copy]; + + _bucket = dictionary[kFIRStorageMetadataBucket]; + _cacheControl = dictionary[kFIRStorageMetadataCacheControl]; + _contentDisposition = dictionary[kFIRStorageMetadataContentDisposition]; + _contentEncoding = dictionary[kFIRStorageMetadataContentEncoding]; + _contentLanguage = dictionary[kFIRStorageMetadataContentLanguage]; + _contentType = dictionary[kFIRStorageMetadataContentType]; + _customMetadata = dictionary[kFIRStorageMetadataCustomMetadata]; + _size = [dictionary[kFIRStorageMetadataSize] longLongValue]; + _generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue]; + _metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue]; + _timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]]; + _updated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataUpdated]]; + _md5Hash = dictionary[kFIRStorageMetadataMd5Hash]; + // GCS "name" is our path, our "name" is just the last path component of the path + _path = dictionary[kFIRStorageMetadataName]; + _name = [_path lastPathComponent]; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageMetadata *clone = + [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]]; + clone.initialMetadata = [self.initialMetadata copy]; + return clone; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorageMetadata class]]) { + return NO; + } + + BOOL isEqualObject = [self isEqualToFIRStorageMetadata:(FIRStorageMetadata *)object]; + return isEqualObject; +} + +- (BOOL)isEqualToFIRStorageMetadata:(FIRStorageMetadata *)metadata { + return [[self dictionaryRepresentation] isEqualToDictionary:[metadata dictionaryRepresentation]]; +} + +- (NSUInteger)hash { + NSUInteger hash = [[self dictionaryRepresentation] hash]; + return hash; +} + +- (NSString *)description { + NSDictionary *metadataDictionary = [self dictionaryRepresentation]; + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, metadataDictionary]; +} + +#pragma mark - Public methods + +- (NSDictionary *)dictionaryRepresentation { + NSMutableDictionary *metadataDictionary = [[NSMutableDictionary alloc] initWithCapacity:13]; + + if (_bucket) { + metadataDictionary[kFIRStorageMetadataBucket] = _bucket; + } + + if (_cacheControl) { + metadataDictionary[kFIRStorageMetadataCacheControl] = _cacheControl; + } + + if (_contentDisposition) { + metadataDictionary[kFIRStorageMetadataContentDisposition] = _contentDisposition; + } + + if (_contentEncoding) { + metadataDictionary[kFIRStorageMetadataContentEncoding] = _contentEncoding; + } + + if (_contentLanguage) { + metadataDictionary[kFIRStorageMetadataContentLanguage] = _contentLanguage; + } + + if (_contentType) { + metadataDictionary[kFIRStorageMetadataContentType] = _contentType; + } + + if (_md5Hash) { + metadataDictionary[kFIRStorageMetadataMd5Hash] = _md5Hash; + } + + if (_customMetadata) { + metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata; + } + + if (_generation) { + NSString *generationString = [NSString stringWithFormat:@"%lld", _generation]; + metadataDictionary[kFIRStorageMetadataGeneration] = generationString; + } + + if (_metageneration) { + NSString *metagenerationString = [NSString stringWithFormat:@"%lld", _metageneration]; + metadataDictionary[kFIRStorageMetadataMetageneration] = metagenerationString; + } + + if (_timeCreated) { + metadataDictionary[kFIRStorageMetadataTimeCreated] = [self RFC3339StringFromDate:_timeCreated]; + } + + if (_updated) { + metadataDictionary[kFIRStorageMetadataUpdated] = [self RFC3339StringFromDate:_updated]; + } + + if (_path) { + metadataDictionary[kFIRStorageMetadataName] = _path; + } + + if (_size) { + metadataDictionary[kFIRStorageMetadataSize] = [NSNumber numberWithLongLong:_size]; + } + + return [metadataDictionary copy]; +} + +- (BOOL)isFile { + return _type == FIRStorageMetadataTypeFile; +} + +- (BOOL)isFolder { + return _type == FIRStorageMetadataTypeFolder; +} + +#pragma mark - Private methods + ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata { + for (NSString *metadataKey in [oldMetadata allKeys]) { + id oldValue = [oldMetadata objectForKey:metadataKey]; + id newValue = [metadata objectForKey:metadataKey]; + + if (oldValue && !newValue) { + [metadata setObject:[NSNull null] forKey:metadataKey]; + } else if ([oldValue isKindOfClass:[NSString class]] && + [newValue isKindOfClass:[NSString class]]) { + if ([oldValue isEqualToString:newValue]) { + [metadata removeObjectForKey:metadataKey]; + } + } else if ([oldValue isKindOfClass:[NSDictionary class]] && + [newValue isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *nestedMetadata = [newValue mutableCopy]; + [self removeMatchingMetadata:nestedMetadata oldMetadata:oldValue]; + [metadata setObject:[nestedMetadata copy] forKey:metadataKey]; + } + } +} + +- (NSDictionary *)updatedMetadata { + NSMutableDictionary *metadataUpdate = [[self dictionaryRepresentation] mutableCopy]; + [FIRStorageMetadata removeMatchingMetadata:metadataUpdate oldMetadata:_initialMetadata]; + return [metadataUpdate copy]; +} + +#pragma mark - RFC 3339 conversions + +static NSDateFormatter *sRFC3339DateFormatter; + +static void setupDateFormatterOnce(void) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sRFC3339DateFormatter = [[NSDateFormatter alloc] init]; + NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; + + [sRFC3339DateFormatter setLocale:enUSPOSIXLocale]; + [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZZZ"]; + [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]]; + }); +} + +- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString { + setupDateFormatterOnce(); + NSDate *rfc3339Date = [sRFC3339DateFormatter dateFromString:dateString]; + return rfc3339Date; +} + +- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date { + setupDateFormatterOnce(); + NSString *rfc3339String = [sRFC3339DateFormatter stringFromDate:date]; + return rfc3339String; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h new file mode 100644 index 0000000..30faa26 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageMetadata_Private.h @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageMetadata () + +@property(readwrite, nonatomic) NSString *name; + +@property(readwrite, nonatomic) NSString *path; + +@property(readwrite, nonatomic) FIRStorageReference *reference; + +/** + * The type of the object, either a "File" or a "Folder". + */ +@property(readwrite) FIRStorageMetadataType type; + +/** + * The original metadata representation received from the server or an empty dictionary + * if the metadata object was initialized by the user. + */ +@property(copy, nonatomic) NSDictionary *initialMetadata; + +/** + * Recursively removes entries in 'metadata' that are unmodified from 'oldMetadata'. + * Adds 'NSNull' for entries that only exist in oldMetadata. + */ ++ (void)removeMatchingMetadata:(NSMutableDictionary *)metadata + oldMetadata:(NSDictionary *)oldMetadata; + +/** + * Computes the updates between the state at initialization and the current state. + * Returns a dictionary with only the updated data. Removed keys are set to NSNull. + */ +- (NSDictionary *)updatedMetadata; + +/** + * Returns an RFC3339 formatted date from a string. + * @param dateString An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ. + * @return An NSDate populated from the string or nil if conversion isn't possible. + */ +- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString; + +/** + * Returns an RFC3339 formatted string from an NSDate object. + * @param date The NSDate object to be converted to a string. + * @return An NSString of the form: yyyy-MM-ddTHH:mm:ss.SSSZ or nil if conversion isn't possible. + */ +- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m new file mode 100644 index 0000000..858138e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask.m @@ -0,0 +1,215 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageObservableTask { + @private + // Handlers for pause, resume, progress, success, and failure callbacks + NSMutableDictionary *_resumeHandlers; + NSMutableDictionary *_pauseHandlers; + NSMutableDictionary *_progressHandlers; + NSMutableDictionary *_successHandlers; + NSMutableDictionary *_failureHandlers; + // Reverse map of fetcher handles to status types + NSMutableDictionary *_handleToStatusMap; +} + +@synthesize state = _state; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _pauseHandlers = [[NSMutableDictionary alloc] init]; + _resumeHandlers = [[NSMutableDictionary alloc] init]; + _progressHandlers = [[NSMutableDictionary alloc] init]; + _successHandlers = [[NSMutableDictionary alloc] init]; + _failureHandlers = [[NSMutableDictionary alloc] init]; + _handleToStatusMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +#pragma mark - Observers + +- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status + handler:(FIRStorageVoidSnapshot)handler { + FIRStorageVoidSnapshot callback = handler; + + // Note: self.snapshot is synchronized + FIRStorageTaskSnapshot *snapshot = self.snapshot; + // TODO: use an increasing counter instead of a random UUID + NSString *UUIDString = [[NSUUID UUID] UUIDString]; + switch (status) { + case FIRStorageTaskStatusPause: + @synchronized(self) { + [_pauseHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStatePausing || _state == FIRStorageTaskStatePaused) { + [self fireHandlers:_pauseHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusResume: + @synchronized(self) { + [_resumeHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateResuming || _state == FIRStorageTaskStateRunning) { + [self fireHandlers:_resumeHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusProgress: + @synchronized(self) { + [_progressHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateRunning || _state == FIRStorageTaskStateProgress) { + [self fireHandlers:_progressHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusSuccess: + @synchronized(self) { + [_successHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateSuccess) { + [self fireHandlers:_successHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusFailure: + @synchronized(self) { + [_failureHandlers setValue:callback forKey:UUIDString]; + } // @synchronized(self) + if (_state == FIRStorageTaskStateFailing || _state == FIRStorageTaskStateFailed) { + [self fireHandlers:_failureHandlers snapshot:snapshot]; + } + break; + + case FIRStorageTaskStatusUnknown: + // Fall through to exception case if an unknown status is passed + + default: + [NSException raise:NSInternalInconsistencyException + format:kFIRStorageInvalidObserverStatus, nil]; + break; + } + + @synchronized(self) { + _handleToStatusMap[UUIDString] = @(status); + } // @synchronized(self) + + return UUIDString; +} + +- (void)removeObserverWithHandle:(FIRStorageHandle)handle { + FIRStorageTaskStatus status = [_handleToStatusMap[handle] intValue]; + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + + @synchronized(self) { + [observerDictionary removeObjectForKey:handle]; + [_handleToStatusMap removeObjectForKey:handle]; + } // @synchronized(self) +} + +- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status { + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + [self removeHandlersFromStatusMapForDictionary:observerDictionary]; + + @synchronized(self) { + [observerDictionary removeAllObjects]; + } // @synchronized(self) +} + +- (void)removeAllObservers { + @synchronized(self) { + [_pauseHandlers removeAllObjects]; + [_resumeHandlers removeAllObjects]; + [_progressHandlers removeAllObjects]; + [_successHandlers removeAllObjects]; + [_failureHandlers removeAllObjects]; + [_handleToStatusMap removeAllObjects]; + } // @synchronized(self) +} + +- (NSMutableDictionary *)handlerDictionaryForStatus: + (FIRStorageTaskStatus)status { + switch (status) { + case FIRStorageTaskStatusPause: + return _pauseHandlers; + + case FIRStorageTaskStatusResume: + return _resumeHandlers; + + case FIRStorageTaskStatusProgress: + return _progressHandlers; + + case FIRStorageTaskStatusSuccess: + return _successHandlers; + + case FIRStorageTaskStatusFailure: + return _failureHandlers; + + case FIRStorageTaskStatusUnknown: + return [NSMutableDictionary dictionary]; + + default: + [NSException raise:NSInternalInconsistencyException + format:kFIRStorageInvalidObserverStatus, nil]; + return nil; + } +} + +- (void)removeHandlersFromStatusMapForDictionary: + (NSMutableDictionary *)dict { + @synchronized(self) { + [_handleToStatusMap removeObjectsForKeys:dict.allKeys]; + } // @synchronized(self) +} + +- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot { + NSMutableDictionary *observerDictionary = + [self handlerDictionaryForStatus:status]; + [self fireHandlers:observerDictionary snapshot:snapshot]; +} + +- (void)fireHandlers:(NSMutableDictionary *)handlers + snapshot:(FIRStorageTaskSnapshot *)snapshot { + dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + // TODO: iterate over this list in a consistent order + NSMutableDictionary *handlersCopy; + @synchronized(self) { + handlersCopy = [handlers copy]; + } // @synchronized(self) + [handlersCopy + enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull key, FIRStorageVoidSnapshot _Nonnull handler, BOOL *_Nonnull stop) { + dispatch_async(callbackQueue, ^{ + handler(snapshot); + }); + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h new file mode 100644 index 0000000..fb8081d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageObservableTask_Private.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; +@class FIRStorageTaskSnapshot; +@class GTMSessionFetcherService; + +@interface FIRStorageObservableTask () + +/** + * Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService. + * @param reference A FIRStorageReference the task will be performed on. + * @param service A GTMSessionFetcherService which provides the fetchers and configuration for + * requests. + * @param queue The shared queue to use for all Storage operations. + * @return A new FIRStorageTask representing the current task. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue; + +/** + * Raise events for a given task status by passing along a snapshot of existing task state. + * @param status A FIRStorageTaskStatus to raise events for. + * @param snapshot A FIRStorageTaskSnapshot snapshot of task state to pass through the handler. + */ +- (void)fireHandlersForStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h new file mode 100644 index 0000000..53ff7ef --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.h @@ -0,0 +1,106 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Represents a path in GCS, which can be represented as: gs://bucket/path/to/object + * or http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object?token=<12345> + * This class also includes helper methods to parse those URI/Ls, as well as to + * add and remove path segments. + */ +@interface FIRStoragePath : NSObject + +/** + * The GCS bucket in the path. + */ +@property(copy, nonatomic) NSString *bucket; + +/** + * The GCS object in the path. + */ +@property(copy, nonatomic, nullable) NSString *object; + +/** + * Parses a generic string (representing some URI or URL) and returns the appropriate path. + * @param string String which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid gs:// URI or http[s]:// URL. + */ ++ (nullable FIRStoragePath *)pathFromString:(NSString *)string; + +/** + * Parses a gs://bucket/path/to/object URI into a GCS path. + * @param aURIString gs:// URI which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid gs:// URI. + */ ++ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString; + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Constructs an FIRStoragePath object that represents the given bucket and object. + * @param bucket The name of the bucket. + * @param object The name of the object. + * @return An instance of FIRStoragePath representing the @a bucket and @a object. + */ +- (instancetype)initWithBucket:(NSString *)bucket + object:(nullable NSString *)object NS_DESIGNATED_INITIALIZER; + +/** + * Parses a http[s]://firebasestorage.googleapis.com/v0/b/bucket/o/path/to/object...?token=<12345> + * URL into a GCS path. + * @param aURLString http[s]:// URL which is parsed into a path. + * string which is parsed into a path. + * @return Returns an instance of FIRStoragePath or nil if one can't be created. + * @throws Throws an exception if the string is not a valid http[s]:// URL. + */ ++ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString; + +/** + * Creates a new path based off of the current path and a string appended to it. + * Note that all slashes are compressed to a single slash, and leading and trailing slashes + * are removed. + * @param path String to append to the current path. + * @return Returns a new instance of FIRStoragePath with the new path appended. + */ +- (FIRStoragePath *)child:(NSString *)path; + +/** + * Creates a new path based off of the current path with the last path segment removed. + * @return Returns a new instance of FIRStoragePath pointing to the parent path, + * or nil if the current path points to the root. + */ +- (nullable FIRStoragePath *)parent; + +/** + * Creates a new path based off of the root of the bucket. + * @return Returns a new instance of FIRStoragePath pointing to the root of the bucket. + */ +- (FIRStoragePath *)root; + +/** + * Returns a GS URI representing the current path. + * @return Returns a gs://bucket/path/to/object URI representing the current path. + */ +- (NSString *)stringValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m new file mode 100644 index 0000000..ef897d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStoragePath.m @@ -0,0 +1,199 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +@implementation FIRStoragePath + +#pragma mark - Class methods + ++ (nullable FIRStoragePath *)pathFromString:(NSString *)string { + if ([string hasPrefix:@"gs://"]) { + // "gs://bucket/path/to/object" + return [FIRStoragePath pathFromGSURI:string]; + } else if ([string hasPrefix:@"http://"] || [string hasPrefix:@"https://"]) { + // "http[s]://firebasestorage.googleapis.com/bucket/path/to/object?signed_url_params" + return [FIRStoragePath pathFromHTTPURL:string]; + } else { + // Invalid scheme, raise an exception! + [NSException raise:NSInternalInconsistencyException + format:@"URL scheme must be one of gs://, http://, or https:// "]; + return nil; + } +} + ++ (nullable FIRStoragePath *)pathFromGSURI:(NSString *)aURIString { + NSString *bucketName; + NSString *objectName; + NSScanner *scanner = [NSScanner scannerWithString:aURIString]; + BOOL isGSURI = [scanner scanString:@"gs://" intoString:NULL]; + BOOL hasBucket = [scanner scanUpToString:@"/" intoString:&bucketName]; + [scanner scanString:@"/" intoString:NULL]; + [scanner scanUpToString:@"\n" intoString:&objectName]; + + if (!isGSURI || !hasBucket) { + [NSException raise:NSInternalInconsistencyException + format:@"URI must be in the form of gs:///"]; + return nil; + } + + return [[self alloc] initWithBucket:bucketName object:objectName]; +} + ++ (nullable FIRStoragePath *)pathFromHTTPURL:(NSString *)aURLString { + NSString *bucketName; + NSString *objectName; + NSURL *httpsURL = [NSURL URLWithString:aURLString]; + NSArray *pathComponents = httpsURL.pathComponents; // [/, v0, b, , o, ] + + if ([httpsURL.host isEqual:kFIRStorageHost]) { + // Have a bucket name + if ([pathComponents count] > 3) { + bucketName = pathComponents[3]; + } + + // Have an object name + if ([pathComponents count] > 5) { + NSRange objectRange = NSMakeRange(5, [pathComponents count] - 5); + objectName = [[pathComponents subarrayWithRange:objectRange] componentsJoinedByString:@"/"]; + } + } + + if (bucketName.length == 0) { + [NSException raise:NSInternalInconsistencyException + format:@"URL must be in the form of " + @"http[s]://firebasestorage.googleapis.com/v0/b//o/[?token=signed_url_params]"]; + return nil; + } + + if (objectName.length == 0) { + objectName = nil; + } + + return [[self alloc] initWithBucket:bucketName object:objectName]; +} + +#pragma mark - Initializers + +- (instancetype)initWithBucket:(NSString *)bucket object:(nullable NSString *)object { + self = [super init]; + if (self) { + _bucket = [bucket copy]; + _object = [self standardizedPathForString:[object copy]]; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithBucket:_bucket object:_object]; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStoragePath class]]) { + return NO; + } + + BOOL isObjectEqual = [self isEqualToFIRStoragePath:(FIRStoragePath *)object]; + return isObjectEqual; +} + +- (BOOL)isEqualToFIRStoragePath:(FIRStoragePath *)path { + BOOL isBucketEqual = _bucket == nil && path->_bucket == nil; + BOOL isObjectEqual = _object == nil && path->_object == nil; + + if (_bucket && path->_bucket) { + isBucketEqual = [_bucket isEqual:path->_bucket]; + } + + if (_object && path.object) { + isObjectEqual = [_object isEqual:path->_object]; + } + + BOOL isEqual = isBucketEqual && isObjectEqual; + return isEqual; +} + +- (NSUInteger)hash { + // "...because in those days, you could XOR anything with anything and get something useful..." + // https://www.usenix.org/system/files/1309_14-17_mickens.pdf + NSUInteger hash = [_bucket hash] ^ [_object hash]; + return hash; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, [self stringValue]]; +} + +- (NSString *)stringValue { + return [NSString stringWithFormat:@"gs://%@/%@", _bucket, _object ?: @""]; +} + +#pragma mark - Public methods + +- (FIRStoragePath *)child:(NSString *)path { + if (path.length == 0) { + return [self copy]; // Return a copy of the same path, nothing happened + } + + NSString *childObject; + if (_object == nil) { + childObject = path; + } else { + childObject = [_object stringByAppendingPathComponent:path]; + } + + FIRStoragePath *childPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:childObject]; + return childPath; +} + +- (nullable FIRStoragePath *)parent { + if (_object.length == 0) { + return nil; + } + + NSString *parentObject = [_object stringByDeletingLastPathComponent]; + FIRStoragePath *parentPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:parentObject]; + return parentPath; +} + +- (FIRStoragePath *)root { + FIRStoragePath *rootPath = [[FIRStoragePath alloc] initWithBucket:_bucket object:nil]; + return rootPath; +} + +#pragma mark - Private methods + +// Removes leading and trailing slashes, and compresses multiple slashes +// to create a canonical representation. +// Example: /foo//bar///baz//// -> foo/bar/baz +- (NSString *)standardizedPathForString:(NSString *)string { + NSMutableArray *components = [[string componentsSeparatedByString:@"/"] mutableCopy]; + NSIndexSet *removedPaths = + [components indexesOfObjectsPassingTest:^BOOL(NSString *string, NSUInteger idx, BOOL *stop) { + return (string.length == 0); + }]; + [components removeObjectsAtIndexes:removedPaths]; + return [components componentsJoinedByString:@"/"]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m new file mode 100644 index 0000000..16bcf7c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference.m @@ -0,0 +1,459 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageDeleteTask.h" +#import "FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h" +#import "FirebaseStorage/Sources/FIRStorageGetMetadataTask.h" +#import "FirebaseStorage/Sources/FIRStorageListResult_Private.h" +#import "FirebaseStorage/Sources/FIRStorageListTask.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h" +#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import +#import + +#import +#import + +@implementation FIRStorageReference + +- (instancetype)init { + FIRStorage *storage = [FIRStorage storage]; + NSString *storageBucket = storage.app.options.storageBucket; + FIRStoragePath *path = [[FIRStoragePath alloc] initWithBucket:storageBucket object:nil]; + FIRStorageReference *reference = [self initWithStorage:storage path:path]; + return reference; +} + +- (instancetype)initWithStorage:(FIRStorage *)storage path:(FIRStoragePath *)path { + self = [super init]; + if (self) { + _storage = storage; + _path = path; + } + return self; +} + +#pragma mark - NSObject overrides + +- (instancetype)copyWithZone:(NSZone *)zone { + FIRStorageReference *copiedReference = [[[self class] allocWithZone:zone] initWithStorage:_storage + path:_path]; + return copiedReference; +} + +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + + if (![object isKindOfClass:[FIRStorageReference class]]) { + return NO; + } + + BOOL isObjectEqual = [self isEqualToFIRStorageReference:(FIRStorageReference *)object]; + return isObjectEqual; +} + +- (BOOL)isEqualToFIRStorageReference:(FIRStorageReference *)reference { + BOOL isEqual = [_storage isEqual:reference.storage] && [_path isEqual:reference.path]; + return isEqual; +} + +- (NSUInteger)hash { + NSUInteger hash = [_storage hash] ^ [_path hash]; + return hash; +} + +- (NSString *)description { + return [self stringValue]; +} + +- (NSString *)stringValue { + NSString *value = [NSString stringWithFormat:@"gs://%@/%@", _path.bucket, _path.object ?: @""]; + return value; +} + +#pragma mark - Property Getters + +- (NSString *)bucket { + NSString *bucket = _path.bucket; + return bucket; +} + +- (NSString *)fullPath { + NSString *path = _path.object; + if (!path) { + path = @""; + } + return path; +} + +- (NSString *)name { + NSString *name = [_path.object lastPathComponent]; + if (!name) { + name = @""; + } + return name; +} + +#pragma mark - Path Operations + +- (FIRStorageReference *)root { + FIRStoragePath *rootPath = [_path root]; + FIRStorageReference *rootReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:rootPath]; + return rootReference; +} + +- (nullable FIRStorageReference *)parent { + FIRStoragePath *parentPath = [_path parent]; + if (!parentPath) { + return nil; + } + + FIRStorageReference *parentReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:parentPath]; + return parentReference; +} + +- (FIRStorageReference *)child:(NSString *)path { + FIRStoragePath *childPath = [_path child:path]; + FIRStorageReference *childReference = [[FIRStorageReference alloc] initWithStorage:_storage + path:childPath]; + return childReference; +} + +#pragma mark - Uploads + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData { + return [self putData:uploadData metadata:nil completion:nil]; +} + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata { + return [self putData:uploadData metadata:metadata completion:nil]; +} + +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + if (!metadata) { + metadata = [[FIRStorageMetadata alloc] init]; + } + + metadata.path = _path.object; + metadata.name = [_path.object lastPathComponent]; + FIRStorageUploadTask *task = + [[FIRStorageUploadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + data:uploadData + metadata:metadata]; + + if (completion) { + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(snapshot.metadata, nil); + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(nil, snapshot.error); + }); + }]; + } + [task enqueue]; + return task; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL { + return [self putFile:fileURL metadata:nil completion:nil]; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata { + return [self putFile:fileURL metadata:metadata completion:nil]; +} + +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + if (!metadata) { + metadata = [[FIRStorageMetadata alloc] init]; + } + + metadata.path = _path.object; + metadata.name = [_path.object lastPathComponent]; + FIRStorageUploadTask *task = + [[FIRStorageUploadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:fileURL + metadata:metadata]; + + if (completion) { + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(snapshot.metadata, nil); + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(nil, snapshot.error); + }); + }]; + } + [task enqueue]; + return task; +} + +#pragma mark - Downloads + +- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size + completion:(FIRStorageVoidDataError)completion { + FIRStorageDownloadTask *task = + [[FIRStorageDownloadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:nil]; + + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + FIRStorageDownloadTask *task = snapshot.task; + dispatch_async(callbackQueue, ^{ + completion(task.downloadData, nil); + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(nil, snapshot.error); + }); + }]; + [task + observeStatus:FIRStorageTaskStatusProgress + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + FIRStorageDownloadTask *task = snapshot.task; + if (task.progress.totalUnitCount > size || task.progress.completedUnitCount > size) { + NSDictionary *infoDictionary = + @{@"totalSize" : @(task.progress.totalUnitCount), + @"maxAllowedSize" : @(size)}; + NSError *error = + [FIRStorageErrors errorWithCode:FIRStorageErrorCodeDownloadSizeExceeded + infoDictionary:infoDictionary]; + [task cancelWithError:error]; + } + }]; + [task enqueue]; + return task; +} + +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL { + return [self writeToFile:fileURL completion:nil]; +} + +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL + completion:(FIRStorageVoidURLError)completion { + FIRStorageDownloadTask *task = + [[FIRStorageDownloadTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + file:fileURL]; + if (completion) { + dispatch_queue_t callbackQueue = _storage.fetcherServiceForApp.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [task observeStatus:FIRStorageTaskStatusSuccess + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(fileURL, nil); + }); + }]; + [task observeStatus:FIRStorageTaskStatusFailure + handler:^(FIRStorageTaskSnapshot *_Nonnull snapshot) { + dispatch_async(callbackQueue, ^{ + completion(nil, snapshot.error); + }); + }]; + } + [task enqueue]; + return task; +} + +- (void)downloadURLWithCompletion:(FIRStorageVoidURLError)completion { + FIRStorageGetDownloadURLTask *task = + [[FIRStorageGetDownloadURLTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +#pragma mark - List + +- (void)listWithMaxResults:(int64_t)maxResults completion:(FIRStorageVoidListError)completion { + if (maxResults <= 0 || maxResults > 1000) { + completion(nil, + [FIRStorageUtils storageErrorWithDescription: + @"Argument 'maxResults' must be between 1 and 1000 inclusive." + code:FIRStorageErrorCodeInvalidArgument]); + } else { + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:@(maxResults) + previousPageToken:nil + completion:completion]; + [task enqueue]; + } +} + +- (void)listWithMaxResults:(int64_t)maxResults + pageToken:(NSString *)pageToken + completion:(FIRStorageVoidListError)completion { + if (maxResults <= 0 || maxResults > 1000) { + completion(nil, + [FIRStorageUtils storageErrorWithDescription: + @"Argument 'maxResults' must be between 1 and 1000 inclusive." + code:FIRStorageErrorCodeInvalidArgument]); + } else { + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:@(maxResults) + previousPageToken:pageToken + completion:completion]; + [task enqueue]; + } +} + +- (void)listAllWithCompletion:(FIRStorageVoidListError)completion { + NSMutableArray *prefixes = [NSMutableArray new]; + NSMutableArray *items = [NSMutableArray new]; + + __weak FIRStorageReference *weakSelf = self; + + __block FIRStorageVoidListError paginatedCompletion = + ^(FIRStorageListResult *listResult, NSError *error) { + if (error) { + completion(nil, error); + } + + FIRStorageReference *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + + [prefixes addObjectsFromArray:listResult.prefixes]; + [items addObjectsFromArray:listResult.items]; + + if (listResult.pageToken) { + FIRStorageListTask *nextPage = [[FIRStorageListTask alloc] + initWithReference:self + fetcherService:strongSelf->_storage.fetcherServiceForApp + dispatchQueue:strongSelf->_storage.dispatchQueue + pageSize:nil + previousPageToken:listResult.pageToken + completion:paginatedCompletion]; + [nextPage enqueue]; + } else { + FIRStorageListResult *result = [[FIRStorageListResult alloc] initWithPrefixes:prefixes + items:items + pageToken:nil]; + // Break the retain cycle we set up indirectly by passing the callback to `nextPage`. + paginatedCompletion = nil; + completion(result, nil); + } + }; + + FIRStorageListTask *task = + [[FIRStorageListTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + pageSize:nil + previousPageToken:nil + completion:paginatedCompletion]; + + [task enqueue]; +} + +#pragma mark - Metadata Operations + +- (void)metadataWithCompletion:(FIRStorageVoidMetadataError)completion { + FIRStorageGetMetadataTask *task = + [[FIRStorageGetMetadataTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +- (void)updateMetadata:(FIRStorageMetadata *)metadata + completion:(nullable FIRStorageVoidMetadataError)completion { + FIRStorageUpdateMetadataTask *task = + [[FIRStorageUpdateMetadataTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + metadata:metadata + completion:completion]; + [task enqueue]; +} + +#pragma mark - Delete + +- (void)deleteWithCompletion:(nullable FIRStorageVoidError)completion { + FIRStorageDeleteTask *task = + [[FIRStorageDeleteTask alloc] initWithReference:self + fetcherService:_storage.fetcherServiceForApp + dispatchQueue:_storage.dispatchQueue + completion:completion]; + [task enqueue]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h new file mode 100644 index 0000000..84a36b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageReference_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageReference () + +@property(nonatomic, readwrite) FIRStorage *storage; + +/** + * The current path which points to an object in the Google Cloud Storage bucket. + */ +@property(strong, nonatomic) FIRStoragePath *path; + +- (instancetype)initWithStorage:(FIRStorage *)storage + path:(FIRStoragePath *)path NS_DESIGNATED_INITIALIZER; + +- (NSString *)stringValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m new file mode 100644 index 0000000..49bc109 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask.m @@ -0,0 +1,68 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import +#import +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorage_Private.h" + +#import + +@implementation FIRStorageTask + +- (instancetype)init { + @throw [NSException exceptionWithName:@"Attempt to call unavailable initializer." + reason:@"init unavailable, use designated initializer" + userInfo:nil]; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue { + self = [super init]; + if (self) { + _reference = reference; + _baseRequest = [FIRStorageUtils defaultRequestForPath:reference.path]; + _fetcherService = service; + _fetcherService.maxRetryInterval = _reference.storage.maxOperationRetryTime; + _dispatchQueue = queue; + } + return self; +} + +- (FIRStorageTaskSnapshot *)snapshot { + @synchronized(self) { + NSProgress *progress = [NSProgress progressWithTotalUnitCount:self.progress.totalUnitCount]; + progress.completedUnitCount = self.progress.completedUnitCount; + FIRStorageTaskSnapshot *snapshot = + [[FIRStorageTaskSnapshot alloc] initWithTask:self + state:self.state + metadata:self.metadata + reference:self.reference + progress:progress + error:[self.error copy]]; + return snapshot; + } +} + +- (void)dispatchAsync:(void (^)(void))block { + dispatch_async(self.dispatchQueue, block); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m new file mode 100644 index 0000000..c5f7c2b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot.m @@ -0,0 +1,87 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" + +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageTaskSnapshot + +- (instancetype)initWithTask:(__kindof FIRStorageTask *)task + state:(FIRStorageTaskState)state + metadata:(nullable FIRStorageMetadata *)metadata + reference:(FIRStorageReference *)reference + progress:(nullable NSProgress *)progress + error:(nullable NSError *)error { + self = [super init]; + if (self) { + _task = task; + _metadata = metadata; + _reference = reference; + _progress = progress; + _error = error; + + switch (state) { + case FIRStorageTaskStateQueueing: + case FIRStorageTaskStateRunning: + case FIRStorageTaskStateResuming: + _status = FIRStorageTaskStatusResume; + break; + + case FIRStorageTaskStateProgress: + _status = FIRStorageTaskStatusProgress; + break; + + case FIRStorageTaskStatePaused: + case FIRStorageTaskStatePausing: + _status = FIRStorageTaskStatusPause; + break; + + case FIRStorageTaskStateSuccess: + case FIRStorageTaskStateCompleting: + _status = FIRStorageTaskStatusSuccess; + break; + + case FIRStorageTaskStateCancelled: + case FIRStorageTaskStateFailing: + case FIRStorageTaskStateFailed: + _status = FIRStorageTaskStatusFailure; + break; + + default: + _status = FIRStorageTaskStatusUnknown; + } + } + return self; +} + +- (NSString *)description { + switch (_status) { + case FIRStorageTaskStatusResume: + return @""; + case FIRStorageTaskStatusProgress: + return [NSString stringWithFormat:@"", _progress]; + case FIRStorageTaskStatusPause: + return @""; + case FIRStorageTaskStatusSuccess: + return @""; + case FIRStorageTaskStatusFailure: + return [NSString stringWithFormat:@"", _error]; + default: + return @""; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h new file mode 100644 index 0000000..4ffc971 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageMetadata; +@class FIRStorageReference; +@class FIRStorageTask; + +@interface FIRStorageTaskSnapshot () + +@property(readwrite, copy, nonatomic) FIRStorageTask *task; +@property(readwrite, copy, nonatomic) FIRStorageMetadata *metadata; +@property(readwrite, copy, nonatomic) FIRStorageReference *reference; +@property(readwrite, strong, nonatomic) NSProgress *progress; +@property(readwrite, copy, nonatomic) NSError *error; + +/** + * Creates a new task snapshot from the given properties. + * @param task The task being represented in this snapshot. + * @param state The current state of the parent task. + * @param metadata The FIRStorageMetadata of a task. Before upload/update, contains the metadata + * to be updated; after, contains the returned metadata. May be nil if no metadata is provided + * or returned. + * @param reference The FIRStorageReference that spawned the task this snapshot is based on. + * @param progress An NSProgress object containing progress of the task this snapshot is based on, + * or nil if the task doesn't report progress. + * @param error An NSError object containing an error that occurred during the task, + * if one occurred. + * @return Returns the constructed snapshot. + */ +- (instancetype)initWithTask:(__kindof FIRStorageTask *)task + state:(FIRStorageTaskState)state + metadata:(nullable FIRStorageMetadata *)metadata + reference:(FIRStorageReference *)reference + progress:(nullable NSProgress *)progress + error:(nullable NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h new file mode 100644 index 0000000..6d441e7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTask_Private.h @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" +#import "FirebaseStorage/Sources/FIRStorageReference_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageTask () + +/** + * State for the current task in progress. + */ +@property(atomic) FIRStorageTaskState state; + +/** + * FIRStorageMetadata for the task in progress, or nil if none present. + */ +@property(strong, nonatomic, nullable) FIRStorageMetadata *metadata; + +/** + * Error which occurred during task execution, or nil if no error occurred. + */ +@property(strong, nonatomic, nullable) NSError *error; + +/** + * NSProgress object which tracks the progess of an observable task. + */ +@property(strong, nonatomic) NSProgress *progress; + +/** + * Reference pointing to the location the task is being performed against. + */ +@property(strong, nonatomic) FIRStorageReference *reference; + +/** + * A serial queue for all storage operations. + */ +@property(nonatomic, readonly) dispatch_queue_t dispatchQueue; + +@property(strong, readwrite, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot; + +@property(readonly, copy, nonatomic) NSURLRequest *baseRequest; + +@property(strong, atomic) GTMSessionFetcher *fetcher; + +@property(readonly, nonatomic) GTMSessionFetcherService *fetcherService; + +@property(readonly, copy) GTMSessionFetcherCompletionHandler fetcherCompletion; + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Creates a new FIRStorageTask initialized with a FIRStorageReference and GTMSessionFetcherService. + * @param reference A FIRStorageReference the task will be performed on. + * @param service A GTMSessionFetcherService which provides the fetchers and configuration for + * requests. + * @param queue The shared queue to use for all Storage operations. + * @return A new FIRStorageTask representing the current task. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER; + +/** Dispatches a block on the shared Storage queue. */ +- (void)dispatchAsync:(void (^)(void))block; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h new file mode 100644 index 0000000..75893dd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@protocol FIRAuthInterop; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Wrapper class for FIRAuthInterop that implements the GTMFetcherAuthorizationProtocol, + * so as to easily provide GTMSessionFetcher fetches a Firebase Authentication JWT + * for the current logged in user. Handles token expiration and other failure cases. + * If no authentication provider exists or no token is found, no token is added + * and the request is passed. + */ +@interface FIRStorageTokenAuthorizer : NSObject + +/** + * Initializes the token authorizer with an instance of FIRApp. + * @param googleAppID The Google AppID of the app to send with the request. + * @param auth An instance that provides access to Auth functionality, if it exists. + * @return Returns an instance of FIRStorageTokenAuthorizer which adds the appropriate + * "Authorization" header to all outbound requests. Note that a token may not be added + * if the Auth instance is nil. This allows for unauthenticated access, if Firebase + * Storage rules allow for it. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + fetcherService:(GTMSessionFetcherService *)service + authProvider:(nullable id)auth; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m new file mode 100644 index 0000000..2374145 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m @@ -0,0 +1,132 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h" + +#import +#import +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" + +#import + +@implementation FIRStorageTokenAuthorizer { + @private + /// Google App ID to pass along with each request. + NSString *_googleAppID; + + /// Auth provider. + id _auth; +} + +@synthesize fetcherService = _fetcherService; + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + fetcherService:(GTMSessionFetcherService *)service + authProvider:(nullable id)auth { + self = [super init]; + if (self) { + _googleAppID = googleAppID; + _fetcherService = service; + _auth = auth; + } + return self; +} + +#pragma mark - GTMFetcherAuthorizationProtocol methods + +- (void)authorizeRequest:(NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel { + // Set version header on each request + NSString *versionString = [NSString stringWithFormat:@"ios/%s", FIRStorageVersionString]; + [request setValue:versionString forHTTPHeaderField:@"x-firebase-storage-version"]; + + // Set GMP ID on each request + [request setValue:_googleAppID forHTTPHeaderField:@"x-firebase-gmpid"]; + + if (delegate && sel) { + id selfParam = self; + NSMethodSignature *sig = [delegate methodSignatureForSelector:sel]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:sel]; + [invocation setTarget:delegate]; + [invocation setArgument:&selfParam atIndex:2]; + [invocation setArgument:&request atIndex:3]; + + dispatch_queue_t callbackQueue = self.fetcherService.callbackQueue; + if (!callbackQueue) { + callbackQueue = dispatch_get_main_queue(); + } + + [invocation retainArguments]; + if (_auth) { + [_auth getTokenForcingRefresh:NO + withCallback:^(NSString *_Nullable token, NSError *_Nullable error) { + if (error) { + NSMutableDictionary *errorDictionary = + [NSMutableDictionary dictionaryWithDictionary:error.userInfo]; + errorDictionary[kFIRStorageResponseErrorDomain] = error.domain; + errorDictionary[kFIRStorageResponseErrorCode] = @(error.code); + + NSError *tokenError = + [FIRStorageErrors errorWithCode:FIRStorageErrorCodeUnauthenticated + infoDictionary:errorDictionary]; + [invocation setArgument:&tokenError atIndex:4]; + } else if (token) { + NSString *firebaseToken = + [NSString stringWithFormat:kFIRStorageAuthTokenFormat, token]; + [request setValue:firebaseToken forHTTPHeaderField:@"Authorization"]; + } + dispatch_async(callbackQueue, ^{ + [invocation invoke]; + }); + }]; + } else { + dispatch_async(callbackQueue, ^{ + [invocation invoke]; + }); + } + } +} + +// Note that stopAuthorization, isAuthorizingRequest, and userEmail +// aren't relevant with the Firebase App/Auth implementation of tokens, +// and thus aren't implemented. Token refresh is handled transparently +// for us, and we don't allow the auth request to be stopped. +// Auth is also not required so the world doesn't stop. +- (void)stopAuthorization { + // Noop +} + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request { + // Noop +} + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request { + return NO; +} + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request { + NSString *authHeader = request.allHTTPHeaderFields[@"Authorization"]; + BOOL isFirebaseToken = [authHeader hasPrefix:@"Firebase"]; + return isFirebaseToken; +} + +- (NSString *)userEmail { + // Noop + return nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h new file mode 100644 index 0000000..fb60fc5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Task which provides the ability update the metadata on an object in Firebase Storage. + */ +@interface FIRStorageUpdateMetadataTask : FIRStorageTask + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + metadata:(FIRStorageMetadata *)metadata + completion:(FIRStorageVoidMetadataError)completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m new file mode 100644 index 0000000..d091b7c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m @@ -0,0 +1,107 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h" + +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" + +@implementation FIRStorageUpdateMetadataTask { + @private + FIRStorageVoidMetadataError _completion; + // Metadata used in the update request + FIRStorageMetadata *_updateMetadata; +} + +@synthesize fetcher = _fetcher; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + metadata:(FIRStorageMetadata *)metadata + completion:(FIRStorageVoidMetadataError)completion { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _updateMetadata = [metadata copy]; + _completion = [completion copy]; + } + return self; +} + +- (void)dealloc { + [_fetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageUpdateMetadataTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageUpdateMetadataTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + NSDictionary *updateDictionary = [strongSelf->_updateMetadata updatedMetadata]; + NSData *updateData = [NSData frs_dataFromJSONDictionary:updateDictionary]; + request.HTTPMethod = @"PATCH"; + request.timeoutInterval = strongSelf.reference.storage.maxOperationRetryTime; + request.HTTPBody = updateData; + NSString *typeString = @"application/json; charset=UTF-8"; + [request setValue:typeString forHTTPHeaderField:@"Content-Type"]; + NSString *lengthString = [NSString stringWithFormat:@"%zu", (unsigned long)[updateData length]]; + [request setValue:lengthString forHTTPHeaderField:@"Content-Length"]; + + FIRStorageVoidMetadataError callback = strongSelf->_completion; + strongSelf->_completion = nil; + + GTMSessionFetcher *fetcher = [strongSelf.fetcherService fetcherWithRequest:request]; + strongSelf->_fetcher = fetcher; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-retain-cycles" + strongSelf->_fetcherCompletion = ^(NSData *data, NSError *error) { + FIRStorageMetadata *metadata; + if (error) { + if (!self.error) { + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + } + } else { + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary) { + metadata = [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + } + + if (callback) { + callback(metadata, self.error); + } + self->_fetcherCompletion = nil; + }; +#pragma clang diagnostic pop + + fetcher.comment = @"UpdateMetadataTask"; + + [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + weakSelf.fetcherCompletion(data, error); + }]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m new file mode 100644 index 0000000..730218d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask.m @@ -0,0 +1,260 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageMetadata_Private.h" +#import "FirebaseStorage/Sources/FIRStorageObservableTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageTask_Private.h" +#import "FirebaseStorage/Sources/FIRStorageUploadTask_Private.h" + +#import + +@implementation FIRStorageUploadTask + +@synthesize progress = _progress; +@synthesize fetcherCompletion = _fetcherCompletion; + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + data:(NSData *)uploadData + metadata:(FIRStorageMetadata *)metadata { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _uploadMetadata = [metadata copy]; + _uploadData = [uploadData copy]; + _progress = [NSProgress progressWithTotalUnitCount:[_uploadData length]]; + + if (!_uploadMetadata.contentType) { + _uploadMetadata.contentType = @"application/octet-stream"; + } + } + return self; +} + +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(NSURL *)fileURL + metadata:(FIRStorageMetadata *)metadata { + self = [super initWithReference:reference fetcherService:service dispatchQueue:queue]; + if (self) { + _uploadMetadata = [metadata copy]; + _fileURL = [fileURL copy]; + _progress = [NSProgress progressWithTotalUnitCount:0]; + + NSString *mimeType = [FIRStorageUtils MIMETypeForExtension:[_fileURL pathExtension]]; + + if (!_uploadMetadata.contentType) { + _uploadMetadata.contentType = mimeType ?: @"application/octet-stream"; + } + } + return self; +} + +- (void)dealloc { + [_uploadFetcher stopFetching]; +} + +- (void)enqueue { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + FIRStorageUploadTask *strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + NSError *contentValidationError; + if (![strongSelf isContentToUploadValid:&contentValidationError]) { + strongSelf.error = contentValidationError; + [strongSelf finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:strongSelf.snapshot]; + return; + } + + strongSelf.state = FIRStorageTaskStateQueueing; + + NSMutableURLRequest *request = [strongSelf.baseRequest mutableCopy]; + request.HTTPMethod = @"POST"; + request.timeoutInterval = strongSelf.reference.storage.maxUploadRetryTime; + NSData *bodyData = + [NSData frs_dataFromJSONDictionary:[strongSelf->_uploadMetadata dictionaryRepresentation]]; + request.HTTPBody = bodyData; + [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; + NSString *contentLengthString = + [NSString stringWithFormat:@"%zu", (unsigned long)[bodyData length]]; + [request setValue:contentLengthString forHTTPHeaderField:@"Content-Length"]; + + NSURLComponents *components = [NSURLComponents componentsWithURL:request.URL + resolvingAgainstBaseURL:NO]; + + if ([components.host isEqual:kGCSHost]) { + [components setPercentEncodedPath:[@"/upload" stringByAppendingString:components.path]]; + } + + NSDictionary *queryParams = @{@"uploadType" : @"resumable", @"name" : self.uploadMetadata.path}; + [components setPercentEncodedQuery:[FIRStorageUtils queryStringForDictionary:queryParams]]; + request.URL = components.URL; + + GTMSessionUploadFetcher *uploadFetcher = + [GTMSessionUploadFetcher uploadFetcherWithRequest:request + uploadMIMEType:strongSelf->_uploadMetadata.contentType + chunkSize:kGTMSessionUploadFetcherStandardChunkSize + fetcherService:self.fetcherService]; + + if (strongSelf->_uploadData) { + [uploadFetcher setUploadData:strongSelf->_uploadData]; + uploadFetcher.comment = @"Data UploadTask"; + } else if (strongSelf->_fileURL) { + [uploadFetcher setUploadFileURL:strongSelf->_fileURL]; + uploadFetcher.comment = @"File UploadTask"; + } + + uploadFetcher.maxRetryInterval = self.reference.storage.maxUploadRetryTime; + + [uploadFetcher setSendProgressBlock:^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + weakSelf.state = FIRStorageTaskStateProgress; + weakSelf.progress.completedUnitCount = totalBytesSent; + weakSelf.progress.totalUnitCount = totalBytesExpectedToSend; + weakSelf.metadata = self->_uploadMetadata; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:weakSelf.snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; + + strongSelf->_uploadFetcher = uploadFetcher; + + // Process fetches + strongSelf.state = FIRStorageTaskStateRunning; + + strongSelf->_fetcherCompletion = ^(NSData *_Nullable data, NSError *_Nullable error) { + // Fire last progress updates + [self fireHandlersForStatus:FIRStorageTaskStatusProgress snapshot:self.snapshot]; + + // Handle potential issues with upload + if (error) { + self.state = FIRStorageTaskStateFailed; + self.error = [FIRStorageErrors errorWithServerError:error reference:self.reference]; + self.metadata = self->_uploadMetadata; + + [self finishTaskWithStatus:FIRStorageTaskStatusFailure snapshot:self.snapshot]; + return; + } + + // Upload completed successfully, fire completion callbacks + self.state = FIRStorageTaskStateSuccess; + + NSDictionary *responseDictionary = [NSDictionary frs_dictionaryFromJSONData:data]; + if (responseDictionary) { + FIRStorageMetadata *metadata = + [[FIRStorageMetadata alloc] initWithDictionary:responseDictionary]; + [metadata setType:FIRStorageMetadataTypeFile]; + self.metadata = metadata; + } else { + self.error = [FIRStorageErrors errorWithInvalidRequest:data]; + } + + [self finishTaskWithStatus:FIRStorageTaskStatusSuccess snapshot:self.snapshot]; + }; + + [strongSelf->_uploadFetcher + beginFetchWithCompletionHandler:^(NSData *_Nullable data, NSError *_Nullable error) { + if (weakSelf.fetcherCompletion != nil) { + weakSelf.fetcherCompletion(data, error); + } + }]; + }]; +} + +- (void)finishTaskWithStatus:(FIRStorageTaskStatus)status + snapshot:(FIRStorageTaskSnapshot *)snapshot { + [self fireHandlersForStatus:status snapshot:self.snapshot]; + [self removeAllObservers]; + self->_fetcherCompletion = nil; +} + +- (BOOL)isContentToUploadValid:(NSError **)outError { + if (_uploadData != nil) { + return YES; + } + + NSError *fileReachabilityError; + if (![_fileURL checkResourceIsReachableAndReturnError:&fileReachabilityError]) { + if (outError != NULL) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:2]; + userInfo[NSLocalizedDescriptionKey] = + [NSString stringWithFormat:@"File at URL: %@ is not reachable.", _fileURL.absoluteString]; + + if (fileReachabilityError) { + userInfo[NSUnderlyingErrorKey] = fileReachabilityError; + } + + *outError = [NSError errorWithDomain:FIRStorageErrorDomain + code:FIRStorageErrorCodeUnknown + userInfo:userInfo]; + } + + return NO; + } + + return YES; +} + +#pragma mark - Upload Management + +- (void)cancel { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateCancelled; + [weakSelf.uploadFetcher stopFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + weakSelf.error = [FIRStorageErrors errorWithCode:FIRStorageErrorCodeCancelled]; + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusFailure snapshot:weakSelf.snapshot]; + }]; +} + +- (void)pause { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStatePaused; + [weakSelf.uploadFetcher pauseFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusPause snapshot:weakSelf.snapshot]; + }]; +} + +- (void)resume { + __weak FIRStorageUploadTask *weakSelf = self; + + [self dispatchAsync:^() { + weakSelf.state = FIRStorageTaskStateResuming; + [weakSelf.uploadFetcher resumeFetching]; + if (weakSelf.state != FIRStorageTaskStateSuccess) { + weakSelf.metadata = weakSelf.uploadMetadata; + } + [weakSelf fireHandlersForStatus:FIRStorageTaskStatusResume snapshot:weakSelf.snapshot]; + weakSelf.state = FIRStorageTaskStateRunning; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h new file mode 100644 index 0000000..8d37a8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUploadTask_Private.h @@ -0,0 +1,73 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@class GTMSessionUploadFetcher; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorageUploadTask () + +/** + * The data to be uploaded (if uploading bytes). + */ +@property(readonly, copy, nonatomic, nullable) NSData *uploadData; + +/** + * The name of a file on disk to be uploaded (if uploading from a file). + */ +@property(readonly, copy, nonatomic, nullable) NSURL *fileURL; + +/** + * The FIRStorageMetadata about the object being uploaded. + */ +@property(readonly, copy, nonatomic) FIRStorageMetadata *uploadMetadata; + +/** + * GTMSessionUploadFetcher used by all uploads. + */ +@property(strong, atomic) GTMSessionUploadFetcher *uploadFetcher; + +/** + * Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param uploadData The NSData object to be uploaded. + * @return Returns an instance of FIRStorageUploadTask. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + data:(NSData *)uploadData + metadata:(FIRStorageMetadata *)metadata; + +/** + * Initializes an upload task with a base FIRStorageReference and GTMSessionFetcherService. + * @param reference The base FIRStorageReference which fetchers use for configuration. + * @param service The GTMSessionFetcherService which will create fetchers. + * @param queue The shared queue to use for all Storage operations. + * @param fileURL The system file URL to upload from. + * @return Returns an instance of FIRStorageUploadTask. + */ +- (instancetype)initWithReference:(FIRStorageReference *)reference + fetcherService:(GTMSessionFetcherService *)service + dispatchQueue:(dispatch_queue_t)queue + file:(NSURL *)fileURL + metadata:(FIRStorageMetadata *)metadata; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h new file mode 100644 index 0000000..55dfab0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.h @@ -0,0 +1,111 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStoragePath; + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageUtils provides a number of helper methods for commonly used operations + * in Firebase Storage, such as JSON parsing, escaping, and file extensions. + */ +@interface FIRStorageUtils : NSObject + +/** + * Returns a percent encoded string appropriate for GCS. + * See https://cloud.google.com/storage/docs/naming for more details. + * @param string A path to escape characters according to the GCS + * @return A percent encoded string appropriate for GCS operations or nil if string is nil + * or can't be escaped. + */ ++ (nullable NSString *)GCSEscapedString:(NSString *)string; + +/** + * Returns the MIME type for a file extension. + * Example of how to get MIME type here: http://ddeville.me/2011/12/mime-to-UTI-cocoa/ + * @param extension A file extension such as "txt", "png", etc. + * @return The MIME type for the input extension such as "text/plain", "image/png", etc. + * or nil if no type is found. + */ ++ (nullable NSString *)MIMETypeForExtension:(NSString *)extension; + +/** + * Returns a properly escaped query string from a given dictionary of query items to values. + * @param dictionary A dictionary containing query items and associated values. + * @return A properly escaped query string or the empty string for a nil or empty dictionary. + */ ++ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary; + +/** + * Returns a base NSURLRequest used by all tasks. + * @param path The FIRStoragePath to create a request for. + * @return Returns a properly formatted NSURLRequest of the form: + * scheme://host/version/b//o[/path/to/object] + */ ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path; + +/** + * Returns a base NSURLRequest with custom query parameters. + * @param path The FIRStoragePath to create a request for. + * @param queryParams A key/value dictionary with query parameters. + * @return Returns a formatted NSURLRequest + */ ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path + queryParams:(NSDictionary *)queryParams; + +/** + * Creates the appropriate GCS percent escaped path for a given FIRStoragePath. + * @param path The FIRStoragePath to encode. + * @return Returns the GCS encoded URL for a given FIRStoragePath. + */ ++ (NSString *)encodedURLForPath:(FIRStoragePath *)path; + +/** + * Creates a NSError in the Firebase Storage domain with given code and description. + * Useful for argument validation. + * @param description The error description to surface to the user. + * @param code The error code. + * @return An NSError in the Firebase Storage error domain. + */ ++ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code; + +@end + +@interface NSDictionary (FIRStorageNSDictionaryJSONHelpers) + +/** + * Returns a dictionary representation of the data in @a data. + * @param data NSData containing JSON data. + * @return An NSDictionary representation of the JSON, or nil if serialization failed. + */ ++ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data; + +@end + +@interface NSData (FIRStorageNSDataJSONHelpers) + +/** + * Returns an NSData instance containing JSON serialized from @a dictionary. + * @param dictionary An NSDictionary containing only types serializable to JSON. + * @return An NSData object representing the binary JSON, or nil if serialization failed. + */ ++ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m new file mode 100644 index 0000000..32afa9a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorageUtils.m @@ -0,0 +1,151 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif + +#import "FirebaseStorage/Sources/FIRStorageUtils.h" + +#import "FirebaseStorage/Sources/FIRStorageConstants_Private.h" +#import "FirebaseStorage/Sources/FIRStorageErrors.h" +#import "FirebaseStorage/Sources/FIRStoragePath.h" + +#import + +// This is the list at https://cloud.google.com/storage/docs/json_api/ without &, ; and +. +NSString *const kGCSObjectAllowedCharacterSet = + @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*,=:@"; + +@implementation FIRStorageUtils + ++ (nullable NSString *)GCSEscapedString:(NSString *)string { + NSCharacterSet *allowedCharacters = + [NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet]; + + return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters]; +} + ++ (nullable NSString *)MIMETypeForExtension:(NSString *)extension { + if (extension == nil) { + return nil; + } + + CFStringRef pathExtension = (__bridge_retained CFStringRef)extension; + CFStringRef type = + UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL); + NSString *mimeType = + (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType); + CFRelease(pathExtension); + if (type != NULL) { + CFRelease(type); + } + + return mimeType; +} + ++ (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary { + if (!dictionary) { + return @""; + } + + __block NSMutableArray *queryItems = [[NSMutableArray alloc] initWithCapacity:[dictionary count]]; + [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value, + BOOL *_Nonnull stop) { + NSString *item = + [FIRStorageUtils GCSEscapedString:[NSString stringWithFormat:@"%@=%@", name, value]]; + [queryItems addObject:item]; + }]; + return [queryItems componentsJoinedByString:@"&"]; +} + ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path { + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSURLComponents *components = [[NSURLComponents alloc] init]; + [components setScheme:kFIRStorageScheme]; + [components setHost:kFIRStorageHost]; + NSString *encodedPath = [self encodedURLForPath:path]; + [components setPercentEncodedPath:encodedPath]; + [request setURL:components.URL]; + return request; +} + ++ (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path + queryParams:(NSDictionary *)queryParams { + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSURLComponents *components = [[NSURLComponents alloc] init]; + [components setScheme:kFIRStorageScheme]; + [components setHost:kFIRStorageHost]; + + NSMutableArray *queryItems = [NSMutableArray new]; + for (NSString *key in queryParams) { + [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryParams[key]]]; + } + [components setQueryItems:queryItems]; + + NSString *encodedPath = [self encodedURLForPath:path]; + [components setPercentEncodedPath:encodedPath]; + [request setURL:components.URL]; + return request; +} + ++ (NSString *)encodedURLForPath:(FIRStoragePath *)path { + NSString *bucketName = [FIRStorageUtils GCSEscapedString:path.bucket]; + NSString *objectName = [FIRStorageUtils GCSEscapedString:path.object]; + NSString *bucketFormat = [NSString stringWithFormat:kFIRStorageBucketPathFormat, bucketName]; + NSString *urlPath = [@"/" stringByAppendingPathComponent:bucketFormat]; + if (objectName) { + NSString *objectFormat = [NSString stringWithFormat:kFIRStorageObjectPathFormat, objectName]; + urlPath = [urlPath stringByAppendingFormat:@"/%@", objectFormat]; + } else { + urlPath = [urlPath stringByAppendingString:@"/o"]; + } + return [@"/" stringByAppendingString:[kFIRStorageVersionPath stringByAppendingString:urlPath]]; +} + ++ (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code { + return [NSError errorWithDomain:FIRStorageErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : description}]; +} + +@end + +@implementation NSDictionary (FIRStorageNSDictionaryJSONHelpers) + ++ (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data { + if (!data) { + return nil; + } + return [NSJSONSerialization JSONObjectWithData:data + options:NSJSONReadingMutableContainers + error:nil]; +} + +@end + +@implementation NSData (FIRStorageNSDataJSONHelpers) + ++ (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary { + if (!dictionary) { + return nil; + } + return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h new file mode 100644 index 0000000..04cecc1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/FIRStorage_Private.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@class FIRApp; +@class GTMSessionFetcherService; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRStorage () + +@property(strong, nonatomic, readwrite) FIRApp *app; + +@property(strong, nonatomic) GTMSessionFetcherService *fetcherServiceForApp; + +@property(nonatomic, readonly) dispatch_queue_t dispatchQueue; + +@property(strong, nonatomic) NSString *storageBucket; + +/** + * Enables/disables GTMSessionFetcher HTTP logging + * @param isLoggingEnabled Boolean passed through to enable/disable GTMSessionFetcher logging + */ ++ (void)setGTMSessionFetcherLoggingEnabled:(BOOL)isLoggingEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h new file mode 100644 index 0000000..85eb25d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorage.h @@ -0,0 +1,130 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" + +@class FIRApp; +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** Project version string for FirebaseStorage. */ +FOUNDATION_EXPORT const char *const FIRStorageVersionString NS_SWIFT_NAME(StorageVersionString); + +/** + * FirebaseStorage is a service that supports uploading and downloading binary objects, + * such as images, videos, and other files to Google Cloud Storage. + * + * If you call [FIRStorage storage], the instance will initialize with the default FIRApp, + * [FIRApp defaultApp], and the storage location will come from the provided + * GoogleService-Info.plist. + * + * If you call [FIRStorage storageForApp:] and provide a custom instance of FIRApp, + * the storage location will be specified via the FIROptions#storageBucket property. + */ +NS_SWIFT_NAME(Storage) +@interface FIRStorage : NSObject + +/** + * Creates an instance of FIRStorage, configured with the default FIRApp. + * @return the FIRStorage instance, initialized with the default FIRApp. + */ ++ (instancetype)storage NS_SWIFT_NAME(storage()); + +/** + * Creates an instance of FIRStorage, configured with the custom FIRApp @a app. + * @param app The custom FIRApp used for initialization. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageForApp:(FIRApp *)app NS_SWIFT_NAME(storage(app:)); + +/** + * Creates an instance of FIRStorage, configured with a custom storage bucket @a url. + * @param url The gs:// url to your Firebase Storage Bucket. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageWithURL:(NSString *)url NS_SWIFT_NAME(storage(url:)); + +/** + * Creates an instance of FIRStorage, configured with a custom FIRApp @a app and a custom storage + * bucket @a url. + * @param app The custom FIRApp used for initialization. + * @param url The gs:// url to your Firebase Storage Bucket. + * @return the FIRStorage instance, initialized with the custom FIRApp. + */ ++ (instancetype)storageForApp:(FIRApp *)app URL:(NSString *)url NS_SWIFT_NAME(storage(app:url:)); + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The Firebase App associated with this Firebase Storage instance. + */ +@property(strong, nonatomic, readonly) FIRApp *app; + +/** + * Maximum time in seconds to retry an upload if a failure occurs. + * Defaults to 10 minutes (600 seconds). + */ +@property NSTimeInterval maxUploadRetryTime; + +/** + * Maximum time in seconds to retry a download if a failure occurs. + * Defaults to 10 minutes (600 seconds). + */ +@property NSTimeInterval maxDownloadRetryTime; + +/** + * Maximum time in seconds to retry operations other than upload and download if a failure occurs. + * Defaults to 2 minutes (120 seconds). + */ +@property NSTimeInterval maxOperationRetryTime; + +/** + * Queue that all developer callbacks are fired on. Defaults to the main queue. + */ +@property(strong, nonatomic) dispatch_queue_t callbackQueue; + +/** + * Creates a FIRStorageReference initialized at the root Firebase Storage location. + * @return An instance of FIRStorageReference initialized at the root. + */ +- (FIRStorageReference *)reference; + +/** + * Creates a FIRStorageReference given a gs:// or https:// URL pointing to a Firebase Storage + * location. For example, you can pass in an https:// download URL retrieved from + * [FIRStorageReference downloadURLWithCompletion] or the gs:// URI from + * [FIRStorageReference description]. + * @param string A gs:// or https:// URL to initialize the reference with. + * @return An instance of FIRStorageReference at the given child path. + * @throws Throws an exception if passed in URL is not associated with the FIRApp used to initialize + * this FIRStorage. + */ +- (FIRStorageReference *)referenceForURL:(NSString *)string; + +/** + * Creates a FIRStorageReference initialized at a child Firebase Storage location. + * @param string A relative path from the root to initialize the reference with, + * for instance @"path/to/object". + * @return An instance of FIRStorageReference at the given child path. + */ +- (FIRStorageReference *)referenceWithPath:(NSString *)string; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h new file mode 100644 index 0000000..52c7382 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageConstants.h @@ -0,0 +1,174 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageDownloadTask; +@class FIRStorageMetadata; +@class FIRStorageTaskSnapshot; +@class FIRStorageUploadTask; + +NS_ASSUME_NONNULL_BEGIN + +/** + * NSString typedef representing a task listener handle. + */ +typedef NSString *FIRStorageHandle NS_SWIFT_NAME(StorageHandle); + +/** + * Block typedef typically used when downloading data. + * @param data The data returned by the download, or nil if no data available or download failed. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidDataError)(NSData *_Nullable data, NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidDataError); + +/** + * Block typedef typically used when performing "binary" async operations such as delete, + * where the operation either succeeds without an error or fails with an error. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidError)(NSError *_Nullable error) NS_SWIFT_NAME(StorageVoidError); + +/** + * Block typedef typically used when retrieving metadata. + * @param metadata The metadata returned by the operation, if metadata exists. + */ +typedef void (^FIRStorageVoidMetadata)(FIRStorageMetadata *_Nullable metadata) + NS_SWIFT_NAME(StorageVoidMetadata); + +/** + * Block typedef typically used when retrieving metadata with the possibility of an error. + * @param metadata The metadata returned by the operation, if metadata exists. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidMetadataError)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidMetadataError); + +/** + * Block typedef typically used to asynchronously return a storage task snapshot. + * @param snapshot The returned task snapshot. + */ +typedef void (^FIRStorageVoidSnapshot)(FIRStorageTaskSnapshot *snapshot) + NS_SWIFT_NAME(StorageVoidSnapshot); + +/** + * Block typedef typically used when retrieving a download URL. + * @param URL The download URL associated with the operation. + * @param error The error describing failure, if one occurred. + */ +typedef void (^FIRStorageVoidURLError)(NSURL *_Nullable URL, NSError *_Nullable error) + NS_SWIFT_NAME(StorageVoidURLError); + +/** + * Enum representing the upload and download task status. + */ +typedef NS_ENUM(NSInteger, FIRStorageTaskStatus) { + /** + * Unknown task status. + */ + FIRStorageTaskStatusUnknown, + + /** + * Task is being resumed. + */ + FIRStorageTaskStatusResume, + + /** + * Task reported a progress event. + */ + FIRStorageTaskStatusProgress, + + /** + * Task is paused. + */ + FIRStorageTaskStatusPause, + + /** + * Task has completed successfully. + */ + FIRStorageTaskStatusSuccess, + + /** + * Task has failed and is unrecoverable. + */ + FIRStorageTaskStatusFailure +} NS_SWIFT_NAME(StorageTaskStatus); + +/** + * Firebase Storage error domain. + */ +FOUNDATION_EXPORT NSString *const FIRStorageErrorDomain NS_SWIFT_NAME(StorageErrorDomain); + +/** + * Enum representing the errors raised by Firebase Storage. + */ +typedef NS_ENUM(NSInteger, FIRStorageErrorCode) { + /** An unknown error occurred. */ + FIRStorageErrorCodeUnknown = -13000, + + /** No object exists at the desired reference. */ + FIRStorageErrorCodeObjectNotFound = -13010, + + /** No bucket is configured for Firebase Storage. */ + FIRStorageErrorCodeBucketNotFound = -13011, + + /** No project is configured for Firebase Storage. */ + FIRStorageErrorCodeProjectNotFound = -13012, + + /** + * Quota on your Firebase Storage bucket has been exceeded. + * If you're on the free tier, upgrade to a paid plan. + * If you're on a paid plan, reach out to Firebase support. + */ + FIRStorageErrorCodeQuotaExceeded = -13013, + + /** User is unauthenticated. Authenticate and try again. */ + FIRStorageErrorCodeUnauthenticated = -13020, + + /** + * User is not authorized to perform the desired action. + * Check your rules to ensure they are correct. + */ + FIRStorageErrorCodeUnauthorized = -13021, + + /** + * The maximum time limit on an operation (upload, download, delete, etc.) has been exceeded. + * Try uploading again. + */ + FIRStorageErrorCodeRetryLimitExceeded = -13030, + + /** + * File on the client does not match the checksum of the file received by the server. + * Try uploading again. + */ + FIRStorageErrorCodeNonMatchingChecksum = -13031, + + /** + * Size of the downloaded file exceeds the amount of memory allocated for the download. + * Increase memory cap and try downloading again. + */ + FIRStorageErrorCodeDownloadSizeExceeded = -13032, + + /** User cancelled the operation. */ + FIRStorageErrorCodeCancelled = -13040, + + /** An invalid argument was provided. */ + FIRStorageErrorCodeInvalidArgument = -13050 +} NS_SWIFT_NAME(StorageErrorCode); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h new file mode 100644 index 0000000..c11373f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageObservableTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageDownloadTask implements resumable downloads from an object in Firebase Storage. + * Downloads can be returned on completion with a completion handler, and can be monitored + * by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume, + * or FIRStorageTask#cancel. + * Downloads can currently be returned as NSData in memory, or as an NSURL to a file on disk. + * Downloads are performed on a background queue, and callbacks are raised on the developer + * specified callbackQueue in FIRStorage, or the main queue if left unspecified. + * Currently all uploads must be initiated and managed on the main queue. + */ +NS_SWIFT_NAME(StorageDownloadTask) +@interface FIRStorageDownloadTask : FIRStorageObservableTask + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h new file mode 100644 index 0000000..0207c51 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageListResult.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** Contains the prefixes and items returned by a `StorageReference.list()` call. */ +NS_SWIFT_NAME(StorageListResult) +@interface FIRStorageListResult : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * The prefixes (folders) returned by the `list()` operation. + * + * @return A list of prefixes (folders). + */ +@property(nonatomic, readonly) NSArray *prefixes; + +/** + * The items (files) returned by the `list()` operation. + * + * @return A list of items (files). + */ +@property(nonatomic, readonly) NSArray *items; + +/** + * Returns a token that can be used to resume a previous `list()` operation. `nil` + * indicates that there are no more results. + * + * @return A page token if more results are available. + */ +@property(nonatomic, readonly, nullable) NSString *pageToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h new file mode 100644 index 0000000..3749504 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageMetadata.h @@ -0,0 +1,140 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class FIRStorageReference; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Class which represents the metadata on an object in Firebase Storage. This metadata is + * returned on successful operations, and can be used to retrieve download URLs, content types, + * and a FIRStorage reference to the object in question. Full documentation can be found at the GCS + * Objects#resource docs. + * @see https://cloud.google.com/storage/docs/json_api/v1/objects#resource + */ +NS_SWIFT_NAME(StorageMetadata) +@interface FIRStorageMetadata : NSObject + +/** + * The name of the bucket containing this object. + */ +@property(copy, nonatomic, readonly) NSString *bucket; + +/** + * Cache-Control directive for the object data. + */ +@property(copy, nonatomic, nullable) NSString *cacheControl; + +/** + * Content-Disposition of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentDisposition; + +/** + * Content-Encoding of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentEncoding; + +/** + * Content-Language of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentLanguage; + +/** + * Content-Type of the object data. + */ +@property(copy, nonatomic, nullable) NSString *contentType; + +/** + * MD5 hash of the data; encoded using base64. + */ +@property(copy, nonatomic, nullable, readonly) NSString *md5Hash; + +/** + * The content generation of this object. Used for object versioning. + */ +@property(readonly) int64_t generation; + +/** + * User-provided metadata, in key/value pairs. + */ +@property(copy, nonatomic, nullable) NSDictionary *customMetadata; + +/** + * The version of the metadata for this object at this generation. Used + * for preconditions and for detecting changes in metadata. A metageneration number is only + * meaningful in the context of a particular generation of a particular object. + */ +@property(readonly) int64_t metageneration; + +/** + * The name of this object, in gs://bucket/path/to/object.txt, this is object.txt. + */ +@property(copy, nonatomic, readonly, nullable) NSString *name; + +/** + * The full path of this object, in gs://bucket/path/to/object.txt, this is path/to/object.txt. + */ +@property(copy, nonatomic, readonly, nullable) NSString *path; + +/** + * Content-Length of the data in bytes. + */ +@property(readonly) int64_t size; + +/** + * The creation time of the object in RFC 3339 format. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *timeCreated; + +/** + * The modification time of the object metadata in RFC 3339 format. + */ +@property(copy, nonatomic, readonly, nullable) NSDate *updated; + +/** + * A reference to the object in Firebase Storage. + */ +@property(strong, nonatomic, readonly, nullable) FIRStorageReference *storageReference; + +/** + * Creates an instance of FIRStorageMetadata from the contents of a dictionary. + * @return An instance of FIRStorageMetadata that represents the contents of a dictionary. + */ +- (nullable instancetype)initWithDictionary:(NSDictionary *)dictionary + NS_DESIGNATED_INITIALIZER; + +/** + * Creates an NSDictionary from the contents of the metadata. + * @return An NSDictionary that represents the contents of the metadata. + */ +- (NSDictionary *)dictionaryRepresentation; + +/** + * Determines if the current metadata represents a "file". + */ +@property(readonly, getter=isFile) BOOL file; + +/** + * Determines if the current metadata represents a "folder". + */ +@property(readonly, getter=isFolder) BOOL folder; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h new file mode 100644 index 0000000..d8ad401 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageObservableTask.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRStorageTask.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageReference; +@class FIRStorageTaskSnapshot; + +/** + * Extends FIRStorageTask to provide observable semantics such as adding and removing observers. + * Observers produce a FIRStorageHandle, which is used to keep track of and remove specific + * observers at a later date. + * This class is currently not thread safe and can only be called on the main thread. + */ +NS_SWIFT_NAME(StorageObservableTask) +@interface FIRStorageObservableTask : FIRStorageTask + +/** + * Observes changes in the upload status: Resume, Pause, Progress, Success, and Failure. + * @param status The FIRStorageTaskStatus change to observe. + * @param handler A callback that fires every time the status event occurs, + * returns a FIRStorageTaskSnapshot containing the state of the task. + * @return A task handle that can be used to remove the observer at a later date. + */ +- (FIRStorageHandle)observeStatus:(FIRStorageTaskStatus)status + handler:(void (^)(FIRStorageTaskSnapshot *snapshot))handler; + +/** + * Removes the single observer with the provided handle. + * @param handle The handle of the task to remove. + */ +- (void)removeObserverWithHandle:(FIRStorageHandle)handle; + +/** + * Removes all observers for a single status. + * @param status A FIRStorageTaskStatus to remove listeners for. + */ +- (void)removeAllObserversForStatus:(FIRStorageTaskStatus)status; + +/** + * Removes all observers. + */ +- (void)removeAllObservers; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h new file mode 100644 index 0000000..94b1c89 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageReference.h @@ -0,0 +1,313 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageTask.h" +#import "FIRStorageUploadTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageReference represents a reference to a Google Cloud Storage object. Developers can + * upload and download objects, as well as get/set object metadata, and delete an object at the + * path. + * @see https://cloud.google.com/storage/ + */ +NS_SWIFT_NAME(StorageReference) +@interface FIRStorageReference : NSObject + +/** + * The FIRStorage service object which created this reference. + */ +@property(nonatomic, readonly) FIRStorage *storage; + +/** + * The name of the Google Cloud Storage bucket associated with this reference, + * in gs://bucket/path/to/object.txt, the bucket would be: 'bucket' + */ +@property(nonatomic, readonly) NSString *bucket; + +/** + * The full path to this object, not including the Google Cloud Storage bucket. + * In gs://bucket/path/to/object.txt, the full path would be: 'path/to/object.txt' + */ +@property(nonatomic, readonly) NSString *fullPath; + +/** + * The short name of the object associated with this reference, + * in gs://bucket/path/to/object.txt, the name of the object would be: 'object.txt' + */ +@property(nonatomic, readonly) NSString *name; + +#pragma mark - Path Operations + +/** + * Creates a new FIRStorageReference pointing to the root object. + * @return A new FIRStorageReference pointing to the root object. + */ +- (FIRStorageReference *)root; + +/** + * Creates a new FIRStorageReference pointing to the parent of the current reference + * or nil if this instance references the root location. + * For example: + * path = foo/bar/baz parent = foo/bar + * path = foo parent = (root) + * path = (root) parent = nil + * @return A new FIRStorageReference pointing to the parent of the current reference. + */ +- (nullable FIRStorageReference *)parent; + +/** + * Creates a new FIRStorageReference pointing to a child object of the current reference. + * path = foo child = bar newPath = foo/bar + * path = foo/bar child = baz newPath = foo/bar/baz + * All leading and trailing slashes will be removed, and consecutive slashes will be + * compressed to single slashes. For example: + * child = /foo/bar newPath = foo/bar + * child = foo/bar/ newPath = foo/bar + * child = foo///bar newPath = foo/bar + * @param path Path to append to the current path. + * @return A new FIRStorageReference pointing to a child location of the current reference. + */ +- (FIRStorageReference *)child:(NSString *)path; + +#pragma mark - Uploads + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference, + * without additional metadata. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +- (FIRStorageUploadTask *)putData:(NSData *)uploadData NS_SWIFT_NAME(putData(_:)); + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata +NS_SWIFT_NAME(putData(_:metadata:)); +// clang-format on + +/** + * Asynchronously uploads data to the currently specified FIRStorageReference. + * This is not recommended for large files, and one should instead upload a file from disk. + * @param uploadData The NSData to upload. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @param completion A completion block that either returns the object metadata on success, + * or an error on failure. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putData:(NSData *)uploadData + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion + NS_SWIFT_NAME(putData(_:metadata:completion:)); +// clang-format on + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference, + * without additional metadata. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL NS_SWIFT_NAME(putFile(from:)); + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + NS_SWIFT_NAME(putFile(from:metadata:)); +// clang-format on + +/** + * Asynchronously uploads a file to the currently specified FIRStorageReference. + * @param fileURL A URL representing the system file path of the object to be uploaded. + * @param metadata FIRStorageMetadata containing additional information (MIME type, etc.) + * about the object being uploaded. + * @param completion A completion block that either returns the object metadata on success, + * or an error on failure. + * @return An instance of FIRStorageUploadTask, which can be used to monitor or manage the upload. + */ +// clang-format off +- (FIRStorageUploadTask *)putFile:(NSURL *)fileURL + metadata:(nullable FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion + NS_SWIFT_NAME(putFile(from:metadata:completion:)); +// clang-format on + +#pragma mark - Downloads + +/** + * Asynchronously downloads the object at the FIRStorageReference to an NSData object in memory. + * An NSData of the provided max size will be allocated, so ensure that the device has enough free + * memory to complete the download. For downloading large files, writeToFile may be a better option. + * @param size The maximum size in bytes to download. If the download exceeds this size + * the task will be cancelled and an error will be returned. + * @param completion A completion block that either returns the object data on success, + * or an error on failure. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +// clang-format off +- (FIRStorageDownloadTask *)dataWithMaxSize:(int64_t)size + completion:(void (^)(NSData *_Nullable data, + NSError *_Nullable error))completion + NS_SWIFT_NAME(getData(maxSize:completion:)); +// clang-format on + +/** + * Asynchronously retrieves a long lived download URL with a revokable token. + * This can be used to share the file with others, but can be revoked by a developer + * in the Firebase Console if desired. + * @param completion A completion block that either returns the URL on success, + * or an error on failure. + */ +- (void)downloadURLWithCompletion:(void (^)(NSURL *_Nullable URL, + NSError *_Nullable error))completion; + +/** + * Asynchronously downloads the object at the current path to a specified system filepath. + * @param fileURL A file system URL representing the path the object should be downloaded to. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL; + +/** + * Asynchronously downloads the object at the current path to a specified system filepath. + * @param fileURL A file system URL representing the path the object should be downloaded to. + * @param completion A completion block that fires when the file download completes. + * Returns an NSURL pointing to the file path of the downloaded file on success, + * or an error on failure. + * @return An FIRStorageDownloadTask that can be used to monitor or manage the download. + */ +- (FIRStorageDownloadTask *)writeToFile:(NSURL *)fileURL + completion:(nullable void (^)(NSURL *_Nullable URL, + NSError *_Nullable error))completion; +#pragma mark - List Support + +/** + * List all items (files) and prefixes (folders) under this StorageReference. + * + * This is a helper method for calling list() repeatedly until there are no more results. + * Consistency of the result is not guaranteed if objects are inserted or removed while this + * operation is executing. All results are buffered in memory. + * + * `listAll(completion:)` is only available for projects using Firebase Rules Version 2. + * + * @param completion A completion handler that will be invoked with all items and prefixes under + * the current StorageReference. + */ +- (void)listAllWithCompletion:(void (^)(FIRStorageListResult *result, + NSError *_Nullable error))completion; + +/** + * List up to `maxResults` items (files) and prefixes (folders) under this StorageReference. + * + * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object + * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be + * filtered. + * + * `list(maxResults:completion:)` is only available for projects using Firebase Rules Version 2. + * + * @param maxResults The maximum number of results to return in a single page. Must be greater + * than 0 and at most 1000. + * @param completion A completion handler that will be invoked with up to maxResults items and + * prefixes under the current StorageReference. + */ +- (void)listWithMaxResults:(int64_t)maxResults + completion: + (void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion; + +/** + * Resumes a previous call to list(maxResults:completion:)`, starting after a pagination token. + * Returns the next set of items (files) and prefixes (folders) under this StorageReference. + * + * "/" is treated as a path delimiter. Firebase Storage does not support unsupported object + * paths that end with "/" or contain two consecutive "/"s. All invalid objects in GCS will be + * filtered. + * + * `list(maxResults:pageToken:completion:)`is only available for projects using Firebase Rules + * Version 2. + * + * @param maxResults The maximum number of results to return in a single page. Must be greater + * than 0 and at most 1000. + * @param pageToken A page token from a previous call to list. + * @param completion A completion handler that will be invoked with the next items and prefixes + * under the current StorageReference. + */ +- (void)listWithMaxResults:(int64_t)maxResults + pageToken:(NSString *)pageToken + completion: + (void (^)(FIRStorageListResult *result, NSError *_Nullable error))completion; + +#pragma mark - Metadata Operations + +/** + * Retrieves metadata associated with an object at the current path. + * @param completion A completion block which returns the object metadata on success, + * or an error on failure. + */ +- (void)metadataWithCompletion: + (void (^)(FIRStorageMetadata *_Nullable metadata, NSError *_Nullable error))completion + NS_SWIFT_NAME(getMetadata(completion:)); + +/** + * Updates the metadata associated with an object at the current path. + * @param metadata An FIRStorageMetadata object with the metadata to update. + * @param completion A completion block which returns the FIRStorageMetadata on success, + * or an error on failure. + */ +// clang-format off +- (void)updateMetadata:(FIRStorageMetadata *)metadata + completion:(nullable void (^)(FIRStorageMetadata *_Nullable metadata, + NSError *_Nullable error))completion +NS_SWIFT_NAME(updateMetadata(_:completion:)); +// clang-format on + +#pragma mark - Delete + +/** + * Deletes the object at the current path. + * @param completion A completion block which returns nil on success, or an error on failure. + */ +- (void)deleteWithCompletion:(nullable void (^)(NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h new file mode 100644 index 0000000..e889d5e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTask.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" +#import "FIRStorageMetadata.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * A superclass to all FIRStorage*Tasks, including FIRStorageUploadTask + * and FIRStorageDownloadTask, to provide state transitions, event raising, and common storage + * or metadata and errors. + * Callbacks are always fired on the developer specified callback queue. + * If no queue is specified by the developer, it defaults to the main queue. + * Currently not thread safe, so only call methods on the main thread. + */ +NS_SWIFT_NAME(StorageTask) +@interface FIRStorageTask : NSObject + +/** + * An immutable view of the task and associated metadata, progress, error, etc. + */ +@property(strong, readonly, nonatomic, nonnull) FIRStorageTaskSnapshot *snapshot; + +@end + +/** + * Defines task operations such as pause, resume, cancel, and enqueue for all tasks. + * All tasks are required to implement enqueue, which begins the task, and may optionally + * implement pause, resume, and cancel, which operate on the task to pause, resume, and cancel + * operations. + */ +NS_SWIFT_NAME(StorageTaskManagement) +@protocol FIRStorageTaskManagement + +@required +/** + * Prepares a task and begins execution. + */ +- (void)enqueue; + +@optional +/** + * Pauses a task currently in progress. + */ +- (void)pause; + +/** + * Cancels a task currently in progress. + */ +- (void)cancel; + +/** + * Resumes a task that is paused. + */ +- (void)resume; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h new file mode 100644 index 0000000..7d14202 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageConstants.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRStorageMetadata; +@class FIRStorageReference; +@class FIRStorageTask; + +/** + * FIRStorageTaskSnapshot represents an immutable view of a task. + * A Snapshot contains a task, storage reference, metadata (if it exists), + * progress, and an error (if one occurred). + */ +NS_SWIFT_NAME(StorageTaskSnapshot) +@interface FIRStorageTaskSnapshot : NSObject + +/** + * Subclass of FIRStorageTask this snapshot represents. + */ +@property(readonly, copy, nonatomic) __kindof FIRStorageTask *task; + +/** + * Metadata returned by the task, or nil if no metadata returned. + */ +@property(readonly, copy, nonatomic, nullable) FIRStorageMetadata *metadata; + +/** + * FIRStorageReference this task is operates on. + */ +@property(readonly, copy, nonatomic) FIRStorageReference *reference; + +/** + * NSProgress object which tracks the progess of an upload or download. + */ +@property(readonly, strong, nonatomic, nullable) NSProgress *progress; + +/** + * Error during task execution, or nil if no error occurred. + */ +@property(readonly, copy, nonatomic, nullable) NSError *error; + +/** + * Status of the task. + */ +@property(readonly, nonatomic) FIRStorageTaskStatus status; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h new file mode 100644 index 0000000..c753500 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FIRStorageUploadTask.h @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "FIRStorageObservableTask.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * FIRStorageUploadTask implements resumable uploads to a file in Firebase Storage. + * Uploads can be returned on completion with a completion callback, and can be monitored + * by attaching observers, or controlled by calling FIRStorageTask#pause, FIRStorageTask#resume, + * or FIRStorageTask#cancel. + * Uploads can take NSData in memory, or an NSURL to a file on disk. + * Uploads are performed on a background queue, and callbacks are raised on the developer + * specified callbackQueue in FIRStorage, or the main queue if left unspecified. + * Currently all uploads must be initiated and managed on the main queue. + */ +NS_SWIFT_NAME(StorageUploadTask) +@interface FIRStorageUploadTask : FIRStorageObservableTask + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h new file mode 100644 index 0000000..be9ee24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/FirebaseStorage/Sources/Public/FirebaseStorage.h @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageObservableTask.h" +#import "FIRStorageReference.h" +#import "FIRStorageTask.h" +#import "FIRStorageTaskSnapshot.h" +#import "FIRStorageUploadTask.h" diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/LICENSE b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/FirebaseStorage/README.md b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/README.md new file mode 100644 index 0000000..3ddc8fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/FirebaseStorage/README.md @@ -0,0 +1,251 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, FirebaseABTesting, FirebaseAuth, FirebaseCore, +FirebaseDatabase, FirebaseMessaging, FirebaseFirestore, +FirebaseFunctions, FirebaseRemoteConfig, and FirebaseStorage now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/LICENSE b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/README.md b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/README.md new file mode 100644 index 0000000..478efde --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/README.md @@ -0,0 +1,23 @@ +# Google Toolbox for Mac - Session Fetcher # + +**Project site**
+**Discussion group** + +[![Build Status](https://travis-ci.org/google/gtm-session-fetcher.svg?branch=master)](https://travis-ci.org/google/gtm-session-fetcher) + +`GTMSessionFetcher` makes it easy for Cocoa applications to perform http +operations. The fetcher is implemented as a wrapper on `NSURLSession`, so its +behavior is asynchronous and uses operating-system settings on iOS and Mac OS X. + +Features include: +- Simple to build; only one source/header file pair is required +- Simple to use: takes just two lines of code to fetch a request +- Supports upload and download sessions +- Flexible cookie storage +- Automatic retry on errors, with exponential backoff +- Support for generating multipart MIME upload streams +- Easy, convenient logging of http requests and responses +- Supports plug-in authentication such as with GTMAppAuth +- Easily testable; self-mocking +- Automatic rate limiting when created by the `GTMSessionFetcherService` factory class +- Fully independent of other projects diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h new file mode 100644 index 0000000..1937a32 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.h @@ -0,0 +1,1322 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// GTMSessionFetcher is a wrapper around NSURLSession for http operations. +// +// What does this offer on top of of NSURLSession? +// +// - Block-style callbacks for useful functionality like progress rather +// than delegate methods. +// - Out-of-process uploads and downloads using NSURLSession, including +// management of fetches after relaunch. +// - Integration with GTMAppAuth for invisible management and refresh of +// authorization tokens. +// - Pretty-printed http logging. +// - Cookies handling that does not interfere with or get interfered with +// by WebKit cookies or on Mac by Safari and other apps. +// - Credentials handling for the http operation. +// - Rate-limiting and cookie grouping when fetchers are created with +// GTMSessionFetcherService. +// +// If the bodyData or bodyFileURL property is set, then a POST request is assumed. +// +// Each fetcher is assumed to be for a one-shot fetch request; don't reuse the object +// for a second fetch. +// +// The fetcher will be self-retained as long as a connection is pending. +// +// To keep user activity private, URLs must have an https scheme (unless the property +// allowedInsecureSchemes is set to permit the scheme.) +// +// Callbacks will be released when the fetch completes or is stopped, so there is no need +// to use weak self references in the callback blocks. +// +// Sample usage: +// +// _fetcherService = [[GTMSessionFetcherService alloc] init]; +// +// GTMSessionFetcher *myFetcher = [_fetcherService fetcherWithURLString:myURLString]; +// myFetcher.retryEnabled = YES; +// myFetcher.comment = @"First profile image"; +// +// // Optionally specify a file URL or NSData for the request body to upload. +// myFetcher.bodyData = [postString dataUsingEncoding:NSUTF8StringEncoding]; +// +// [myFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { +// if (error != nil) { +// // Server status code or network error. +// // +// // If the domain is kGTMSessionFetcherStatusDomain then the error code +// // is a failure status from the server. +// } else { +// // Fetch succeeded. +// } +// }]; +// +// There is also a beginFetch call that takes a pointer and selector for the completion handler; +// a pointer and selector is a better style when the callback is a substantial, separate method. +// +// NOTE: Fetches may retrieve data from the server even though the server +// returned an error, so the criteria for success is a non-nil error. +// The completion handler is called when the server status is >= 300 with an NSError +// having domain kGTMSessionFetcherStatusDomain and code set to the server status. +// +// Status codes are at +// +// +// Background session support: +// +// Out-of-process uploads and downloads may be created by setting the fetcher's +// useBackgroundSession property. Data to be uploaded should be provided via +// the uploadFileURL property; the download destination should be specified with +// the destinationFileURL. NOTE: Background upload files should be in a location +// that will be valid even after the device is restarted, so the file should not +// be uploaded from a system temporary or cache directory. +// +// Background session transfers are slower, and should typically be used only +// for very large downloads or uploads (hundreds of megabytes). +// +// When background sessions are used in iOS apps, the application delegate must +// pass through the parameters from UIApplicationDelegate's +// application:handleEventsForBackgroundURLSession:completionHandler: to the +// fetcher class. +// +// When the application has been relaunched, it may also create a new fetcher +// instance to handle completion of the transfers. +// +// - (void)application:(UIApplication *)application +// handleEventsForBackgroundURLSession:(NSString *)identifier +// completionHandler:(void (^)())completionHandler { +// // Application was re-launched on completing an out-of-process download. +// +// // Pass the URLSession info related to this re-launch to the fetcher class. +// [GTMSessionFetcher application:application +// handleEventsForBackgroundURLSession:identifier +// completionHandler:completionHandler]; +// +// // Get a fetcher related to this re-launch and re-hook up a completionHandler to it. +// GTMSessionFetcher *fetcher = [GTMSessionFetcher fetcherWithSessionIdentifier:identifier]; +// NSURL *destinationFileURL = fetcher.destinationFileURL; +// fetcher.completionHandler = ^(NSData *data, NSError *error) { +// [self downloadCompletedToFile:destinationFileURL error:error]; +// }; +// } +// +// +// Threading and queue support: +// +// Networking always happens on a background thread; there is no advantage to +// changing thread or queue to create or start a fetcher. +// +// Callbacks are run on the main thread; alternatively, the app may set the +// fetcher's callbackQueue to a dispatch queue. +// +// Once the fetcher's beginFetch method has been called, the fetcher's methods and +// properties may be accessed from any thread. +// +// Downloading to disk: +// +// To have downloaded data saved directly to disk, specify a file URL for the +// destinationFileURL property. +// +// HTTP methods and headers: +// +// Alternative HTTP methods, like PUT, and custom headers can be specified by +// creating the fetcher with an appropriate NSMutableURLRequest. +// +// +// Caching: +// +// The fetcher avoids caching. That is best for API requests, but may hurt +// repeat fetches of static data. Apps may enable a persistent disk cache by +// customizing the config: +// +// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher, +// NSURLSessionConfiguration *config) { +// config.URLCache = [NSURLCache sharedURLCache]; +// }; +// +// Or use the standard system config to share cookie storage with web views +// and to enable disk caching: +// +// fetcher.configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; +// +// +// Cookies: +// +// There are three supported mechanisms for remembering cookies between fetches. +// +// By default, a standalone GTMSessionFetcher uses a mutable array held +// statically to track cookies for all instantiated fetchers. This avoids +// cookies being set by servers for the application from interfering with +// Safari and WebKit cookie settings, and vice versa. +// The fetcher cookies are lost when the application quits. +// +// To rely instead on WebKit's global NSHTTPCookieStorage, set the fetcher's +// cookieStorage property: +// myFetcher.cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; +// +// To share cookies with other apps, use the method introduced in iOS 9/OS X 10.11: +// myFetcher.cookieStorage = +// [NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:kMyCompanyContainedID]; +// +// To ignore existing cookies and only have cookies related to the single fetch +// be applied, make a temporary cookie storage object: +// myFetcher.cookieStorage = [[GTMSessionCookieStorage alloc] init]; +// +// Note: cookies set while following redirects will be sent to the server, as +// the redirects are followed by the fetcher. +// +// To completely disable cookies, similar to setting cookieStorageMethod to +// kGTMHTTPFetcherCookieStorageMethodNone, adjust the session configuration +// appropriately in the fetcher or fetcher service: +// fetcher.configurationBlock = ^(GTMSessionFetcher *configFetcher, +// NSURLSessionConfiguration *config) { +// config.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever; +// config.HTTPShouldSetCookies = NO; +// }; +// +// If the fetcher is created from a GTMSessionFetcherService object +// then the cookie storage mechanism is set to use the cookie storage in the +// service object rather than the static storage. Disabling cookies in the +// session configuration set on a service object will disable cookies for all +// fetchers created from that GTMSessionFetcherService object, since the session +// configuration is propagated to the fetcher. +// +// +// Monitoring data transfers. +// +// The fetcher supports a variety of properties for progress monitoring +// progress with callback blocks. +// GTMSessionFetcherSendProgressBlock sendProgressBlock +// GTMSessionFetcherReceivedProgressBlock receivedProgressBlock +// GTMSessionFetcherDownloadProgressBlock downloadProgressBlock +// +// If supplied by the server, the anticipated total download size is available +// as [[myFetcher response] expectedContentLength] (and may be -1 for unknown +// download sizes.) +// +// +// Automatic retrying of fetches +// +// The fetcher can optionally create a timer and reattempt certain kinds of +// fetch failures (status codes 408, request timeout; 502, gateway failure; +// 503, service unavailable; 504, gateway timeout; networking errors +// NSURLErrorTimedOut and NSURLErrorNetworkConnectionLost.) The user may +// set a retry selector to customize the type of errors which will be retried. +// +// Retries are done in an exponential-backoff fashion (that is, after 1 second, +// 2, 4, 8, and so on.) +// +// Enabling automatic retries looks like this: +// myFetcher.retryEnabled = YES; +// +// With retries enabled, the completion callbacks are called only +// when no more retries will be attempted. Calling the fetcher's stopFetching +// method will terminate the retry timer, without the finished or failure +// selectors being invoked. +// +// Optionally, the client may set the maximum retry interval: +// myFetcher.maxRetryInterval = 60.0; // in seconds; default is 60 seconds +// // for downloads, 600 for uploads +// +// Servers should never send a 400 or 500 status for errors that are retryable +// by clients, as those values indicate permanent failures. In nearly all +// cases, the default standard retry behavior is correct for clients, and no +// custom client retry behavior is needed or appropriate. Servers that send +// non-retryable status codes and expect the client to retry the request are +// faulty. +// +// Still, the client may provide a block to determine if a status code or other +// error should be retried. The block returns YES to set the retry timer or NO +// to fail without additional fetch attempts. +// +// The retry method may return the |suggestedWillRetry| argument to get the +// default retry behavior. Server status codes are present in the +// error argument, and have the domain kGTMSessionFetcherStatusDomain. The +// user's method may look something like this: +// +// myFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *error, +// GTMSessionFetcherRetryResponse response) { +// // Perhaps examine error.domain and error.code, or fetcher.retryCount +// // +// // Respond with YES to start the retry timer, NO to proceed to the failure +// // callback, or suggestedWillRetry to get default behavior for the +// // current error domain and code values. +// response(suggestedWillRetry); +// }; + + +#import + +#if TARGET_OS_IPHONE +#import +#endif +#if TARGET_OS_WATCH +#import +#endif + +// By default it is stripped from non DEBUG builds. Developers can override +// this in their project settings. +#ifndef STRIP_GTM_FETCH_LOGGING + #if !DEBUG + #define STRIP_GTM_FETCH_LOGGING 1 + #else + #define STRIP_GTM_FETCH_LOGGING 0 + #endif +#endif + +// Logs in debug builds. +#ifndef GTMSESSION_LOG_DEBUG + #if DEBUG + #define GTMSESSION_LOG_DEBUG(...) NSLog(__VA_ARGS__) + #else + #define GTMSESSION_LOG_DEBUG(...) do { } while (0) + #endif +#endif + +// Asserts in debug builds (or logs in debug builds if GTMSESSION_ASSERT_AS_LOG +// or NS_BLOCK_ASSERTIONS are defined.) +#ifndef GTMSESSION_ASSERT_DEBUG + #if DEBUG && !defined(NS_BLOCK_ASSERTIONS) && !GTMSESSION_ASSERT_AS_LOG + #undef GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_AS_LOG 1 + #endif + + #if DEBUG && !GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_DEBUG(...) NSAssert(__VA_ARGS__) + #elif DEBUG + #define GTMSESSION_ASSERT_DEBUG(pred, ...) if (!(pred)) { NSLog(__VA_ARGS__); } + #else + #define GTMSESSION_ASSERT_DEBUG(pred, ...) do { } while (0) + #endif +#endif + +// Asserts in debug builds, logs in release builds (or logs in debug builds if +// GTMSESSION_ASSERT_AS_LOG is defined.) +#ifndef GTMSESSION_ASSERT_DEBUG_OR_LOG + #if DEBUG && !GTMSESSION_ASSERT_AS_LOG + #define GTMSESSION_ASSERT_DEBUG_OR_LOG(...) NSAssert(__VA_ARGS__) + #else + #define GTMSESSION_ASSERT_DEBUG_OR_LOG(pred, ...) if (!(pred)) { NSLog(__VA_ARGS__); } + #endif +#endif + +// Macro useful for examining messages from NSURLSession during debugging. +#if 0 +#define GTM_LOG_SESSION_DELEGATE(...) GTMSESSION_LOG_DEBUG(__VA_ARGS__) +#else +#define GTM_LOG_SESSION_DELEGATE(...) +#endif + +#ifndef GTM_NULLABLE + #if __has_feature(nullability) // Available starting in Xcode 6.3 + #define GTM_NULLABLE_TYPE __nullable + #define GTM_NONNULL_TYPE __nonnull + #define GTM_NULLABLE nullable + #define GTM_NONNULL_DECL nonnull // GTM_NONNULL is used by GTMDefines.h + #define GTM_NULL_RESETTABLE null_resettable + + #define GTM_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN + #define GTM_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END + #else + #define GTM_NULLABLE_TYPE + #define GTM_NONNULL_TYPE + #define GTM_NULLABLE + #define GTM_NONNULL_DECL + #define GTM_NULL_RESETTABLE + #define GTM_ASSUME_NONNULL_BEGIN + #define GTM_ASSUME_NONNULL_END + #endif // __has_feature(nullability) +#endif // GTM_NULLABLE + +#ifndef GTM_DECLARE_GENERICS + #if __has_feature(objc_generics) + #define GTM_DECLARE_GENERICS 1 + #else + #define GTM_DECLARE_GENERICS 0 + #endif +#endif + +#ifndef GTM_NSArrayOf + #if GTM_DECLARE_GENERICS + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #else + #define GTM_NSArrayOf(value) NSArray + #define GTM_NSDictionaryOf(key, value) NSDictionary + #endif // __has_feature(objc_generics) +#endif // GTM_NSArrayOf + +// For iOS, the fetcher can declare itself a background task to allow fetches +// to finish when the app leaves the foreground. +// +// (This is unrelated to providing a background configuration, which allows +// out-of-process uploads and downloads.) +// +// To disallow use of background tasks during fetches, the target should define +// GTM_BACKGROUND_TASK_FETCHING to 0, or alternatively may set the +// skipBackgroundTask property to YES. +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH && !defined(GTM_BACKGROUND_TASK_FETCHING) + #define GTM_BACKGROUND_TASK_FETCHING 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if (TARGET_OS_TV \ + || TARGET_OS_WATCH \ + || (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0)) + #ifndef GTM_USE_SESSION_FETCHER + #define GTM_USE_SESSION_FETCHER 1 + #endif +#endif + +#if !defined(GTMBridgeFetcher) + // These bridge macros should be identical in GTMHTTPFetcher.h and GTMSessionFetcher.h + #if GTM_USE_SESSION_FETCHER + // Macros to new fetcher class. + #define GTMBridgeFetcher GTMSessionFetcher + #define GTMBridgeFetcherService GTMSessionFetcherService + #define GTMBridgeFetcherServiceProtocol GTMSessionFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMSessionFetcherAssertValidSelector + #define GTMBridgeCookieStorage GTMSessionCookieStorage + #define GTMBridgeCleanedUserAgentString GTMFetcherCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMFetcherSystemVersionString + #define GTMBridgeApplicationIdentifier GTMFetcherApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMSessionFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest GTMSessionFetcherStatusBadRequest + #else + // Macros to old fetcher class. + #define GTMBridgeFetcher GTMHTTPFetcher + #define GTMBridgeFetcherService GTMHTTPFetcherService + #define GTMBridgeFetcherServiceProtocol GTMHTTPFetcherServiceProtocol + #define GTMBridgeAssertValidSelector GTMAssertSelectorNilOrImplementedWithArgs + #define GTMBridgeCookieStorage GTMCookieStorage + #define GTMBridgeCleanedUserAgentString GTMCleanedUserAgentString + #define GTMBridgeSystemVersionString GTMSystemVersionString + #define GTMBridgeApplicationIdentifier GTMApplicationIdentifier + #define kGTMBridgeFetcherStatusDomain kGTMHTTPFetcherStatusDomain + #define kGTMBridgeFetcherStatusBadRequest kGTMHTTPFetcherStatusBadRequest + #endif // GTM_USE_SESSION_FETCHER +#endif + +// When creating background sessions to perform out-of-process uploads and +// downloads, on app launch any background sessions must be reconnected in +// order to receive events that occurred while the app was not running. +// +// The fetcher will automatically attempt to recreate the sessions on app +// start, but doing so reads from NSUserDefaults. This may have launch-time +// performance impacts. +// +// To avoid launch performance impacts, on iPhone/iPad with iOS 13+ the +// GTMSessionFetcher class will register for the app launch notification and +// perform the reconnect then. +// +// Apps targeting Mac or older iOS SDKs can opt into the new behavior by defining +// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH=1. +// +// Apps targeting new SDKs can force the old behavior by defining +// GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH = 0. +#ifndef GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH + // Default to the on-launch behavior for iOS 13+. + #if TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0 + #define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 1 + #else + #define GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH 0 + #endif +#endif + +GTM_ASSUME_NONNULL_BEGIN + +// Notifications +// +// Fetch started and stopped, and fetch retry delay started and stopped. +extern NSString *const kGTMSessionFetcherStartedNotification; +extern NSString *const kGTMSessionFetcherStoppedNotification; +extern NSString *const kGTMSessionFetcherRetryDelayStartedNotification; +extern NSString *const kGTMSessionFetcherRetryDelayStoppedNotification; + +// Completion handler notification. This is intended for use by code capturing +// and replaying fetch requests and results for testing. For fetches where +// destinationFileURL or accumulateDataBlock is set for the fetcher, the data +// will be nil for successful fetches. +// +// This notification is posted on the main thread. +extern NSString *const kGTMSessionFetcherCompletionInvokedNotification; +extern NSString *const kGTMSessionFetcherCompletionDataKey; +extern NSString *const kGTMSessionFetcherCompletionErrorKey; + +// Constants for NSErrors created by the fetcher (excluding server status errors, +// and error objects originating in the OS.) +extern NSString *const kGTMSessionFetcherErrorDomain; + +// The fetcher turns server error status values (3XX, 4XX, 5XX) into NSErrors +// with domain kGTMSessionFetcherStatusDomain. +// +// Any server response body data accompanying the status error is added to the +// userInfo dictionary with key kGTMSessionFetcherStatusDataKey. +extern NSString *const kGTMSessionFetcherStatusDomain; +extern NSString *const kGTMSessionFetcherStatusDataKey; +extern NSString *const kGTMSessionFetcherStatusDataContentTypeKey; + +// When a fetch fails with an error, these keys are included in the error userInfo +// dictionary if retries were attempted. +extern NSString *const kGTMSessionFetcherNumberOfRetriesDoneKey; +extern NSString *const kGTMSessionFetcherElapsedIntervalWithRetriesKey; + +// Background session support requires access to NSUserDefaults. +// If [NSUserDefaults standardUserDefaults] doesn't yield the correct NSUserDefaults for your usage, +// ie for an App Extension, then implement this class/method to return the correct NSUserDefaults. +// https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW6 +@interface GTMSessionFetcherUserDefaultsFactory : NSObject + ++ (NSUserDefaults *)fetcherUserDefaults; + +@end + +#ifdef __cplusplus +} +#endif + +typedef NS_ENUM(NSInteger, GTMSessionFetcherError) { + GTMSessionFetcherErrorDownloadFailed = -1, + GTMSessionFetcherErrorUploadChunkUnavailable = -2, + GTMSessionFetcherErrorBackgroundExpiration = -3, + GTMSessionFetcherErrorBackgroundFetchFailed = -4, + GTMSessionFetcherErrorInsecureRequest = -5, + GTMSessionFetcherErrorTaskCreationFailed = -6, +}; + +typedef NS_ENUM(NSInteger, GTMSessionFetcherStatus) { + // Standard http status codes. + GTMSessionFetcherStatusNotModified = 304, + GTMSessionFetcherStatusBadRequest = 400, + GTMSessionFetcherStatusUnauthorized = 401, + GTMSessionFetcherStatusForbidden = 403, + GTMSessionFetcherStatusPreconditionFailed = 412 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +@class GTMSessionCookieStorage; +@class GTMSessionFetcher; + +// The configuration block is for modifying the NSURLSessionConfiguration only. +// DO NOT change any fetcher properties in the configuration block. +typedef void (^GTMSessionFetcherConfigurationBlock)(GTMSessionFetcher *fetcher, + NSURLSessionConfiguration *configuration); +typedef void (^GTMSessionFetcherSystemCompletionHandler)(void); +typedef void (^GTMSessionFetcherCompletionHandler)(NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); +typedef void (^GTMSessionFetcherBodyStreamProviderResponse)(NSInputStream *bodyStream); +typedef void (^GTMSessionFetcherBodyStreamProvider)(GTMSessionFetcherBodyStreamProviderResponse response); +typedef void (^GTMSessionFetcherDidReceiveResponseDispositionBlock)(NSURLSessionResponseDisposition disposition); +typedef void (^GTMSessionFetcherDidReceiveResponseBlock)(NSURLResponse *response, + GTMSessionFetcherDidReceiveResponseDispositionBlock dispositionBlock); +typedef void (^GTMSessionFetcherChallengeDispositionBlock)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential); +typedef void (^GTMSessionFetcherChallengeBlock)(GTMSessionFetcher *fetcher, + NSURLAuthenticationChallenge *challenge, + GTMSessionFetcherChallengeDispositionBlock dispositionBlock); +typedef void (^GTMSessionFetcherWillRedirectResponse)(NSURLRequest * GTM_NULLABLE_TYPE redirectedRequest); +typedef void (^GTMSessionFetcherWillRedirectBlock)(NSHTTPURLResponse *redirectResponse, + NSURLRequest *redirectRequest, + GTMSessionFetcherWillRedirectResponse response); +typedef void (^GTMSessionFetcherAccumulateDataBlock)(NSData * GTM_NULLABLE_TYPE buffer); +typedef void (^GTMSessionFetcherSimulateByteTransferBlock)(NSData * GTM_NULLABLE_TYPE buffer, + int64_t bytesWritten, + int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite); +typedef void (^GTMSessionFetcherReceivedProgressBlock)(int64_t bytesWritten, + int64_t totalBytesWritten); +typedef void (^GTMSessionFetcherDownloadProgressBlock)(int64_t bytesWritten, + int64_t totalBytesWritten, + int64_t totalBytesExpectedToWrite); +typedef void (^GTMSessionFetcherSendProgressBlock)(int64_t bytesSent, + int64_t totalBytesSent, + int64_t totalBytesExpectedToSend); +typedef void (^GTMSessionFetcherWillCacheURLResponseResponse)(NSCachedURLResponse * GTM_NULLABLE_TYPE cachedResponse); +typedef void (^GTMSessionFetcherWillCacheURLResponseBlock)(NSCachedURLResponse *proposedResponse, + GTMSessionFetcherWillCacheURLResponseResponse responseBlock); +typedef void (^GTMSessionFetcherRetryResponse)(BOOL shouldRetry); +typedef void (^GTMSessionFetcherRetryBlock)(BOOL suggestedWillRetry, + NSError * GTM_NULLABLE_TYPE error, + GTMSessionFetcherRetryResponse response); + +typedef void (^GTMSessionFetcherTestResponse)(NSHTTPURLResponse * GTM_NULLABLE_TYPE response, + NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); +typedef void (^GTMSessionFetcherTestBlock)(GTMSessionFetcher *fetcherToTest, + GTMSessionFetcherTestResponse testResponse); + +void GTMSessionFetcherAssertValidSelector(id GTM_NULLABLE_TYPE obj, SEL GTM_NULLABLE_TYPE sel, ...); + +// Utility functions for applications self-identifying to servers via a +// user-agent header + +// The "standard" user agent includes the application identifier, taken from the bundle, +// followed by a space and the system version string. Pass nil to use +mainBundle as the source +// of the bundle identifier. +// +// Applications may use this as a starting point for their own user agent strings, perhaps +// with additional sections appended. Use GTMFetcherCleanedUserAgentString() below to +// clean up any string being added to the user agent. +NSString *GTMFetcherStandardUserAgentString(NSBundle * GTM_NULLABLE_TYPE bundle); + +// Make a generic name and version for the current application, like +// com.example.MyApp/1.2.3 relying on the bundle identifier and the +// CFBundleShortVersionString or CFBundleVersion. +// +// The bundle ID may be overridden as the base identifier string by +// adding to the bundle's Info.plist a "GTMUserAgentID" key. +// +// If no bundle ID or override is available, the process name preceded +// by "proc_" is used. +NSString *GTMFetcherApplicationIdentifier(NSBundle * GTM_NULLABLE_TYPE bundle); + +// Make an identifier like "MacOSX/10.7.1" or "iPod_Touch/4.1 hw/iPod1_1" +NSString *GTMFetcherSystemVersionString(void); + +// Make a parseable user-agent identifier from the given string, replacing whitespace +// and commas with underscores, and removing other characters that may interfere +// with parsing of the full user-agent string. +// +// For example, @"[My App]" would become @"My_App" +NSString *GTMFetcherCleanedUserAgentString(NSString *str); + +// Grab the data from an input stream. Since streams cannot be assumed to be rewindable, +// this may be destructive; the caller can try to rewind the stream (by setting the +// NSStreamFileCurrentOffsetKey property) or can just use the NSData to make a new +// NSInputStream. This function is intended to facilitate testing rather than be used in +// production. +// +// This function operates synchronously on the current thread. Depending on how the +// input stream is implemented, it may be appropriate to dispatch to a different +// queue before calling this function. +// +// Failure is indicated by a returned data value of nil. +NSData * GTM_NULLABLE_TYPE GTMDataFromInputStream(NSInputStream *inputStream, NSError **outError); + +#ifdef __cplusplus +} // extern "C" +#endif + + +#if !GTM_USE_SESSION_FETCHER +@protocol GTMHTTPFetcherServiceProtocol; +#endif + +// This protocol allows abstract references to the fetcher service, primarily for +// fetchers (which may be compiled without the fetcher service class present.) +// +// Apps should not need to use this protocol. +@protocol GTMSessionFetcherServiceProtocol +// This protocol allows us to call into the service without requiring +// GTMSessionFetcherService sources in this project + +@property(atomic, strong) dispatch_queue_t callbackQueue; + +- (BOOL)fetcherShouldBeginFetching:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidCreateSession:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidBeginFetching:(GTMSessionFetcher *)fetcher; +- (void)fetcherDidStop:(GTMSessionFetcher *)fetcher; + +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher; + +@property(atomic, assign) BOOL reuseSession; +- (GTM_NULLABLE NSURLSession *)session; +- (GTM_NULLABLE NSURLSession *)sessionForFetcherCreation; +- (GTM_NULLABLE id)sessionDelegate; +- (GTM_NULLABLE NSDate *)stoppedAllFetchersDate; + +// Methods for compatibility with the old GTMHTTPFetcher. +@property(atomic, readonly, strong, GTM_NULLABLE) NSOperationQueue *delegateQueue; + +@end // @protocol GTMSessionFetcherServiceProtocol + +#ifndef GTM_FETCHER_AUTHORIZATION_PROTOCOL +#define GTM_FETCHER_AUTHORIZATION_PROTOCOL 1 +@protocol GTMFetcherAuthorizationProtocol +@required +// This protocol allows us to call the authorizer without requiring its sources +// in this project. +- (void)authorizeRequest:(GTM_NULLABLE NSMutableURLRequest *)request + delegate:(id)delegate + didFinishSelector:(SEL)sel; + +- (void)stopAuthorization; + +- (void)stopAuthorizationForRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizingRequest:(NSURLRequest *)request; + +- (BOOL)isAuthorizedRequest:(NSURLRequest *)request; + +@property(atomic, strong, readonly, GTM_NULLABLE) NSString *userEmail; + +@optional + +// Indicate if authorization may be attempted. Even if this succeeds, +// authorization may fail if the user's permissions have been revoked. +@property(atomic, readonly) BOOL canAuthorize; + +// For development only, allow authorization of non-SSL requests, allowing +// transmission of the bearer token unencrypted. +@property(atomic, assign) BOOL shouldAuthorizeAllRequests; + +- (void)authorizeRequest:(GTM_NULLABLE NSMutableURLRequest *)request + completionHandler:(void (^)(NSError * GTM_NULLABLE_TYPE error))handler; + +#if GTM_USE_SESSION_FETCHER +@property(atomic, weak, GTM_NULLABLE) id fetcherService; +#else +@property(atomic, weak, GTM_NULLABLE) id fetcherService; +#endif + +- (BOOL)primeForRefresh; + +@end +#endif // GTM_FETCHER_AUTHORIZATION_PROTOCOL + +#if GTM_BACKGROUND_TASK_FETCHING +// A protocol for an alternative target for messages from GTMSessionFetcher to UIApplication. +// Set the target using +[GTMSessionFetcher setSubstituteUIApplication:] +@protocol GTMUIApplicationProtocol +- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName + expirationHandler:(void(^ __nullable)(void))handler; +- (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier; +@end +#endif + +#pragma mark - + +// GTMSessionFetcher objects are used for async retrieval of an http get or post +// +// See additional comments at the beginning of this file +@interface GTMSessionFetcher : NSObject + +// Create a fetcher +// +// fetcherWithRequest will return an autoreleased fetcher, but if +// the connection is successfully created, the connection should retain the +// fetcher for the life of the connection as well. So the caller doesn't have +// to retain the fetcher explicitly unless they want to be able to cancel it. ++ (instancetype)fetcherWithRequest:(GTM_NULLABLE NSURLRequest *)request; + +// Convenience methods that make a request, like +fetcherWithRequest ++ (instancetype)fetcherWithURL:(NSURL *)requestURL; ++ (instancetype)fetcherWithURLString:(NSString *)requestURLString; + +// Methods for creating fetchers to continue previous fetches. ++ (instancetype)fetcherWithDownloadResumeData:(NSData *)resumeData; ++ (GTM_NULLABLE instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier; + +// Returns an array of currently active fetchers for background sessions, +// both restarted and newly created ones. ++ (GTM_NSArrayOf(GTMSessionFetcher *) *)fetchersForBackgroundSessions; + +// Designated initializer. +// +// Applications should create fetchers with a "fetcherWith..." method on a fetcher +// service or a class method, not with this initializer. +// +// The configuration should typically be nil. Applications needing to customize +// the configuration may do so by setting the configurationBlock property. +- (instancetype)initWithRequest:(GTM_NULLABLE NSURLRequest *)request + configuration:(GTM_NULLABLE NSURLSessionConfiguration *)configuration; + +// The fetcher's request. This may not be set after beginFetch has been invoked. The request +// may change due to redirects. +@property(atomic, strong, GTM_NULLABLE) NSURLRequest *request; + +// Set a header field value on the request. Header field value changes will not +// affect a fetch after the fetch has begun. +- (void)setRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field; + +// Data used for resuming a download task. +@property(atomic, readonly, GTM_NULLABLE) NSData *downloadResumeData; + +// The configuration; this must be set before the fetch begins. If no configuration is +// set or inherited from the fetcher service, then the fetcher uses an ephemeral config. +// +// NOTE: This property should typically be nil. Applications needing to customize +// the configuration should do so by setting the configurationBlock property. +// That allows the fetcher to pick an appropriate base configuration, with the +// application setting only the configuration properties it needs to customize. +@property(atomic, strong, GTM_NULLABLE) NSURLSessionConfiguration *configuration; + +// A block the client may use to customize the configuration used to create the session. +// +// This is called synchronously, either on the thread that begins the fetch or, during a retry, +// on the main thread. The configuration block may be called repeatedly if multiple fetchers are +// created. +// +// The configuration block is for modifying the NSURLSessionConfiguration only. +// DO NOT change any fetcher properties in the configuration block. Fetcher properties +// may be set in the fetcher service prior to fetcher creation, or on the fetcher prior +// to invoking beginFetch. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherConfigurationBlock configurationBlock; + +// A session is created as needed by the fetcher. A fetcher service object +// may maintain sessions for multiple fetches to the same host. +@property(atomic, strong, GTM_NULLABLE) NSURLSession *session; + +// The task in flight. +@property(atomic, readonly, GTM_NULLABLE) NSURLSessionTask *sessionTask; + +// The background session identifier. +@property(atomic, readonly, GTM_NULLABLE) NSString *sessionIdentifier; + +// Indicates a fetcher created to finish a background session task. +@property(atomic, readonly) BOOL wasCreatedFromBackgroundSession; + +// Additional user-supplied data to encode into the session identifier. Since session identifier +// length limits are unspecified, this should be kept small. Key names beginning with an underscore +// are reserved for use by the fetcher. +@property(atomic, strong, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSString *) *sessionUserInfo; + +// The human-readable description to be assigned to the task. +@property(atomic, copy, GTM_NULLABLE) NSString *taskDescription; + +// The priority assigned to the task, if any. Use NSURLSessionTaskPriorityLow, +// NSURLSessionTaskPriorityDefault, or NSURLSessionTaskPriorityHigh. +@property(atomic, assign) float taskPriority; + +// The fetcher encodes information used to resume a session in the session identifier. +// This method, intended for internal use returns the encoded information. The sessionUserInfo +// dictionary is stored as identifier metadata. +- (GTM_NULLABLE GTM_NSDictionaryOf(NSString *, NSString *) *)sessionIdentifierMetadata; + +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH +// The app should pass to this method the completion handler passed in the app delegate method +// application:handleEventsForBackgroundURLSession:completionHandler: ++ (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(GTMSessionFetcherSystemCompletionHandler)completionHandler; +#endif + +// Indicate that a newly created session should be a background session. +// A new session identifier will be created by the fetcher. +// +// Warning: The only thing background sessions are for is rare download +// of huge, batched files of data. And even just for those, there's a lot +// of pain and hackery needed to get transfers to actually happen reliably +// with background sessions. +// +// Don't try to upload or download in many background sessions, since the system +// will impose an exponentially increasing time penalty to prevent the app from +// getting too much background execution time. +// +// References: +// +// "Moving to Fewer, Larger Transfers" +// https://forums.developer.apple.com/thread/14853 +// +// "NSURLSession’s Resume Rate Limiter" +// https://forums.developer.apple.com/thread/14854 +// +// "Background Session Task state persistence" +// https://forums.developer.apple.com/thread/11554 +// +@property(atomic, assign) BOOL useBackgroundSession; + +// Indicates if the fetcher was started using a background session. +@property(atomic, readonly, getter=isUsingBackgroundSession) BOOL usingBackgroundSession; + +// Indicates if uploads should use an upload task. This is always set for file or stream-provider +// bodies, but may be set explicitly for NSData bodies. +@property(atomic, assign) BOOL useUploadTask; + +// Indicates that the fetcher is using a session that may be shared with other fetchers. +@property(atomic, readonly) BOOL canShareSession; + +// By default, the fetcher allows only secure (https) schemes unless this +// property is set, or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For example, during debugging when fetching from a development server that lacks SSL support, +// this may be set to @[ @"http" ], or when the fetcher is used to retrieve local files, +// this may be set to @[ @"file" ]. +// +// This should be left as nil for release builds to avoid creating the opportunity for +// leaking private user behavior and data. If a server is providing insecure URLs +// for fetching by the client app, report the problem as server security & privacy bug. +// +// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when +// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist. +@property(atomic, copy, GTM_NULLABLE) GTM_NSArrayOf(NSString *) *allowedInsecureSchemes; + +// By default, the fetcher prohibits localhost requests unless this property is set, +// or the GTM_ALLOW_INSECURE_REQUESTS build flag is set. +// +// For localhost requests, the URL scheme is not checked when this property is set. +// +// For builds with the iOS 9/OS X 10.11 and later SDKs, this property is required only when +// the app specifies NSAppTransportSecurity/NSAllowsArbitraryLoads in the main bundle's Info.plist. +@property(atomic, assign) BOOL allowLocalhostRequest; + +// By default, the fetcher requires valid server certs. This may be bypassed +// temporarily for development against a test server with an invalid cert. +@property(atomic, assign) BOOL allowInvalidServerCertificates; + +// Cookie storage object for this fetcher. If nil, the fetcher will use a static cookie +// storage instance shared among fetchers. If this fetcher was created by a fetcher service +// object, it will be set to use the service object's cookie storage. See Cookies section above for +// the full discussion. +// +// Because as of Jan 2014 standalone instances of NSHTTPCookieStorage do not actually +// store any cookies (Radar 15735276) we use our own subclass, GTMSessionCookieStorage, +// to hold cookies in memory. +@property(atomic, strong, GTM_NULLABLE) NSHTTPCookieStorage *cookieStorage; + +// Setting the credential is optional; it is used if the connection receives +// an authentication challenge. +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *credential; + +// Setting the proxy credential is optional; it is used if the connection +// receives an authentication challenge from a proxy. +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *proxyCredential; + +// If body data, body file URL, or body stream provider is not set, then a GET request +// method is assumed. +@property(atomic, strong, GTM_NULLABLE) NSData *bodyData; + +// File to use as the request body. This forces use of an upload task. +@property(atomic, strong, GTM_NULLABLE) NSURL *bodyFileURL; + +// Length of body to send, expected or actual. +@property(atomic, readonly) int64_t bodyLength; + +// The body stream provider may be called repeatedly to provide a body. +// Setting a body stream provider forces use of an upload task. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherBodyStreamProvider bodyStreamProvider; + +// Object to add authorization to the request, if needed. +// +// This may not be changed once beginFetch has been invoked. +@property(atomic, strong, GTM_NULLABLE) id authorizer; + +// The service object that created and monitors this fetcher, if any. +@property(atomic, strong) id service; + +// The host, if any, used to classify this fetcher in the fetcher service. +@property(atomic, copy, GTM_NULLABLE) NSString *serviceHost; + +// The priority, if any, used for starting fetchers in the fetcher service. +// +// Lower values are higher priority; the default is 0, and values may +// be negative or positive. This priority affects only the start order of +// fetchers that are being delayed by a fetcher service when the running fetchers +// exceeds the service's maxRunningFetchersPerHost. A priority of NSIntegerMin will +// exempt this fetcher from delay. +@property(atomic, assign) NSInteger servicePriority; + +// The delegate's optional didReceiveResponse block may be used to inspect or alter +// the session task response. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherDidReceiveResponseBlock didReceiveResponseBlock; + +// The delegate's optional challenge block may be used to inspect or alter +// the session task challenge. +// +// If this block is not set, the fetcher's default behavior for the NSURLSessionTask +// didReceiveChallenge: delegate method is to use the fetcher's respondToChallenge: method +// which relies on the fetcher's credential and proxyCredential properties. +// +// Warning: This may be called repeatedly if the challenge fails. Check +// challenge.previousFailureCount to identify repeated invocations. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherChallengeBlock challengeBlock; + +// The delegate's optional willRedirect block may be used to inspect or alter +// the redirection. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherWillRedirectBlock willRedirectBlock; + +// The optional send progress block reports body bytes uploaded. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherSendProgressBlock sendProgressBlock; + +// The optional accumulate block may be set by clients wishing to accumulate data +// themselves rather than let the fetcher append each buffer to an NSData. +// +// When this is called with nil data (such as on redirect) the client +// should empty its accumulation buffer. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherAccumulateDataBlock accumulateDataBlock; + +// The optional received progress block may be used to monitor data +// received from a data task. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherReceivedProgressBlock receivedProgressBlock; + +// The delegate's optional downloadProgress block may be used to monitor download +// progress in writing to disk. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherDownloadProgressBlock downloadProgressBlock; + +// The delegate's optional willCacheURLResponse block may be used to alter the cached +// NSURLResponse. The user may prevent caching by passing nil to the block's response. +// +// This is called on the callback queue. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherWillCacheURLResponseBlock willCacheURLResponseBlock; + +// Enable retrying; see comments at the top of this file. Setting +// retryEnabled=YES resets the min and max retry intervals. +@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled; + +// Retry block is optional for retries. +// +// If present, this block should call the response block with YES to cause a retry or NO to end the +// fetch. +// See comments at the top of this file. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherRetryBlock retryBlock; + +// Retry intervals must be strictly less than maxRetryInterval, else +// they will be limited to maxRetryInterval and no further retries will +// be attempted. Setting maxRetryInterval to 0.0 will reset it to the +// default value, 60 seconds for downloads and 600 seconds for uploads. +@property(atomic, assign) NSTimeInterval maxRetryInterval; + +// Starting retry interval. Setting minRetryInterval to 0.0 will reset it +// to a random value between 1.0 and 2.0 seconds. Clients should normally not +// set this except for unit testing. +@property(atomic, assign) NSTimeInterval minRetryInterval; + +// Multiplier used to increase the interval between retries, typically 2.0. +// Clients should not need to set this. +@property(atomic, assign) double retryFactor; + +// Number of retries attempted. +@property(atomic, readonly) NSUInteger retryCount; + +// Interval delay to precede next retry. +@property(atomic, readonly) NSTimeInterval nextRetryInterval; + +#if GTM_BACKGROUND_TASK_FETCHING +// Skip use of a UIBackgroundTask, thus requiring fetches to complete when the app is in the +// foreground. +// +// Targets should define GTM_BACKGROUND_TASK_FETCHING to 0 to avoid use of a UIBackgroundTask +// on iOS to allow fetches to complete in the background. This property is available when +// it's not practical to set the preprocessor define. +@property(atomic, assign) BOOL skipBackgroundTask; +#endif // GTM_BACKGROUND_TASK_FETCHING + +// Begin fetching the request +// +// The delegate may optionally implement the callback or pass nil for the selector or handler. +// +// The delegate and all callback blocks are retained between the beginFetch call until after the +// finish callback, or until the fetch is stopped. +// +// An error is passed to the callback for server statuses 300 or +// higher, with the status stored as the error object's code. +// +// finishedSEL has a signature like: +// - (void)fetcher:(GTMSessionFetcher *)fetcher +// finishedWithData:(NSData *)data +// error:(NSError *)error; +// +// If the application has specified a destinationFileURL or an accumulateDataBlock +// for the fetcher, the data parameter passed to the callback will be nil. + +- (void)beginFetchWithDelegate:(GTM_NULLABLE id)delegate + didFinishSelector:(GTM_NULLABLE SEL)finishedSEL; + +- (void)beginFetchWithCompletionHandler:(GTM_NULLABLE GTMSessionFetcherCompletionHandler)handler; + +// Returns YES if this fetcher is in the process of fetching a URL. +@property(atomic, readonly, getter=isFetching) BOOL fetching; + +// Cancel the fetch of the request that's currently in progress. The completion handler +// will not be called. +- (void)stopFetching; + +// A block to be called when the fetch completes. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherCompletionHandler completionHandler; + +// A block to be called if download resume data becomes available. +@property(atomic, strong, GTM_NULLABLE) void (^resumeDataBlock)(NSData *); + +// Return the status code from the server response. +@property(atomic, readonly) NSInteger statusCode; + +// Return the http headers from the response. +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSString *) *responseHeaders; + +// The response, once it's been received. +@property(atomic, strong, readonly, GTM_NULLABLE) NSURLResponse *response; + +// Bytes downloaded so far. +@property(atomic, readonly) int64_t downloadedLength; + +// Buffer of currently-downloaded data, if available. +@property(atomic, readonly, strong, GTM_NULLABLE) NSData *downloadedData; + +// Local path to which the downloaded file will be moved. +// +// If a file already exists at the path, it will be overwritten. +// Will create the enclosing folders if they are not present. +@property(atomic, strong, GTM_NULLABLE) NSURL *destinationFileURL; + +// The time this fetcher originally began fetching. This is useful as a time +// barrier for ignoring irrelevant fetch notifications or callbacks. +@property(atomic, strong, readonly, GTM_NULLABLE) NSDate *initialBeginFetchDate; + +// userData is retained solely for the convenience of the client. +@property(atomic, strong, GTM_NULLABLE) id userData; + +// Stored property values are retained solely for the convenience of the client. +@property(atomic, copy, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, id) *properties; + +- (void)setProperty:(GTM_NULLABLE id)obj forKey:(NSString *)key; // Pass nil for obj to remove the property. +- (GTM_NULLABLE id)propertyForKey:(NSString *)key; + +- (void)addPropertiesFromDictionary:(GTM_NSDictionaryOf(NSString *, id) *)dict; + +// Comments are useful for logging, so are strongly recommended for each fetcher. +@property(atomic, copy, GTM_NULLABLE) NSString *comment; + +- (void)setCommentWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +// Log of request and response, if logging is enabled +@property(atomic, copy, GTM_NULLABLE) NSString *log; + +// Callbacks are run on this queue. If none is supplied, the main queue is used. +@property(atomic, strong, GTM_NULL_RESETTABLE) dispatch_queue_t callbackQueue; + +// The queue used internally by the session to invoke its delegate methods in the fetcher. +// +// Application callbacks are always called by the fetcher on the callbackQueue above, +// not on this queue. Apps should generally not change this queue. +// +// The default delegate queue is the main queue. +// +// This value is ignored after the session has been created, so this +// property should be set in the fetcher service rather in the fetcher as it applies +// to a shared session. +@property(atomic, strong, GTM_NULL_RESETTABLE) NSOperationQueue *sessionDelegateQueue; + +// Spin the run loop or sleep the thread, discarding events, until the fetch has completed. +// +// This is only for use in testing or in tools without a user interface. +// +// Note: Synchronous fetches should never be used by shipping apps; they are +// sufficient reason for rejection from the app store. +// +// Returns NO if timed out. +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds; + +// Test block is optional for testing. +// +// If present, this block will cause the fetcher to skip starting the session, and instead +// use the test block response values when calling the completion handler and delegate code. +// +// Test code can set this on the fetcher or on the fetcher service. For testing libraries +// that use a fetcher without exposing either the fetcher or the fetcher service, the global +// method setGlobalTestBlock: will set the block for all fetchers that do not have a test +// block set. +// +// The test code can pass nil for all response parameters to indicate that the fetch +// should proceed. +// +// Applications can exclude test block support by setting GTM_DISABLE_FETCHER_TEST_BLOCK. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherTestBlock testBlock; + ++ (void)setGlobalTestBlock:(GTM_NULLABLE GTMSessionFetcherTestBlock)block; + +// When using the testBlock, |testBlockAccumulateDataChunkCount| is the desired number of chunks to +// divide the response data into if the client has streaming enabled. The data will be divided up to +// |testBlockAccumulateDataChunkCount| chunks; however, the exact amount may vary depending on the +// size of the response data (e.g. a 1-byte response can only be divided into one chunk). +@property(atomic, readwrite) NSUInteger testBlockAccumulateDataChunkCount; + +#if GTM_BACKGROUND_TASK_FETCHING +// For testing or to override UIApplication invocations, apps may specify an alternative +// target for messages to UIApplication. ++ (void)setSubstituteUIApplication:(nullable id)substituteUIApplication; ++ (nullable id)substituteUIApplication; +#endif // GTM_BACKGROUND_TASK_FETCHING + +// Exposed for testing. ++ (GTMSessionCookieStorage *)staticCookieStorage; ++ (BOOL)appAllowsInsecureRequests; + +#if STRIP_GTM_FETCH_LOGGING +// If logging is stripped, provide a stub for the main method +// for controlling logging. ++ (void)setLoggingEnabled:(BOOL)flag; ++ (BOOL)isLoggingEnabled; + +#else + +// These methods let an application log specific body text, such as the text description of a binary +// request or response. The application should set the fetcher to defer response body logging until +// the response has been received and the log response body has been set by the app. For example: +// +// fetcher.logRequestBody = [binaryObject stringDescription]; +// fetcher.deferResponseBodyLogging = YES; +// [fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { +// if (error == nil) { +// fetcher.logResponseBody = [[[MyThing alloc] initWithData:data] stringDescription]; +// } +// fetcher.deferResponseBodyLogging = NO; +// }]; + +@property(atomic, copy, GTM_NULLABLE) NSString *logRequestBody; +@property(atomic, assign) BOOL deferResponseBodyLogging; +@property(atomic, copy, GTM_NULLABLE) NSString *logResponseBody; + +// Internal logging support. +@property(atomic, readonly) NSData *loggedStreamData; +@property(atomic, assign) BOOL hasLoggedError; +@property(atomic, strong, GTM_NULLABLE) NSURL *redirectedFromURL; +- (void)appendLoggedStreamData:(NSData *)dataToAdd; +- (void)clearLoggedStreamData; + +#endif // STRIP_GTM_FETCH_LOGGING + +@end + +@interface GTMSessionFetcher (BackwardsCompatibilityOnly) +// Clients using GTMSessionFetcher should set the cookie storage explicitly themselves. +// This method is just for compatibility with the old GTMHTTPFetcher class. +- (void)setCookieStorageMethod:(NSInteger)method; +@end + +// Until we can just instantiate NSHTTPCookieStorage for local use, we'll +// implement all the public methods ourselves. This stores cookies only in +// memory. Additional methods are provided for testing. +// +// iOS 9/OS X 10.11 added +[NSHTTPCookieStorage sharedCookieStorageForGroupContainerIdentifier:] +// which may also be used to create cookie storage. +@interface GTMSessionCookieStorage : NSHTTPCookieStorage + +// Add the array off cookies to the storage, replacing duplicates. +// Also removes expired cookies from the storage. +- (void)setCookies:(GTM_NULLABLE GTM_NSArrayOf(NSHTTPCookie *) *)cookies; + +- (void)removeAllCookies; + +@end + +// Macros to monitor synchronization blocks in debug builds. +// These report problems using GTMSessionCheckDebug. +// +// GTMSessionMonitorSynchronized Start monitoring a top-level-only +// @sync scope. +// GTMSessionMonitorRecursiveSynchronized Start monitoring a top-level or +// recursive @sync scope. +// GTMSessionCheckSynchronized Verify that the current execution +// is inside a @sync scope. +// GTMSessionCheckNotSynchronized Verify that the current execution +// is not inside a @sync scope. +// +// Example usage: +// +// - (void)myExternalMethod { +// @synchronized(self) { +// GTMSessionMonitorSynchronized(self) +// +// - (void)myInternalMethod { +// GTMSessionCheckSynchronized(self); +// +// - (void)callMyCallbacks { +// GTMSessionCheckNotSynchronized(self); +// +// GTMSessionCheckNotSynchronized is available for verifying the code isn't +// in a deadlockable @sync state when posting notifications and invoking +// callbacks. Don't use GTMSessionCheckNotSynchronized immediately before a +// @sync scope; the normal recursiveness check of GTMSessionMonitorSynchronized +// can catch those. + +#ifdef __OBJC__ +// If asserts are entirely no-ops, the synchronization monitor is just a bunch +// of counting code that doesn't report exceptional circumstances in any way. +// Only build the synchronization monitor code if NS_BLOCK_ASSERTIONS is not +// defined or asserts are being logged instead. +#if DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) + #define __GTMSessionMonitorSynchronizedVariableInner(varname, counter) \ + varname ## counter + #define __GTMSessionMonitorSynchronizedVariable(varname, counter) \ + __GTMSessionMonitorSynchronizedVariableInner(varname, counter) + + #define GTMSessionMonitorSynchronized(obj) \ + NS_VALID_UNTIL_END_OF_SCOPE id \ + __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \ + [[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \ + allowRecursive:NO \ + functionName:__func__] + + #define GTMSessionMonitorRecursiveSynchronized(obj) \ + NS_VALID_UNTIL_END_OF_SCOPE id \ + __GTMSessionMonitorSynchronizedVariable(__monitor, __COUNTER__) = \ + [[GTMSessionSyncMonitorInternal alloc] initWithSynchronizationObject:obj \ + allowRecursive:YES \ + functionName:__func__] + + #define GTMSessionCheckSynchronized(obj) { \ + GTMSESSION_ASSERT_DEBUG( \ + [GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + @"GTMSessionCheckSynchronized(" #obj ") failed: not sync'd" \ + @" on " #obj " in %s. Call stack:\n%@", \ + __func__, [NSThread callStackSymbols]); \ + } + + #define GTMSessionCheckNotSynchronized(obj) { \ + GTMSESSION_ASSERT_DEBUG( \ + ![GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + @"GTMSessionCheckNotSynchronized(" #obj ") failed: was sync'd" \ + @" on " #obj " in %s by %@. Call stack:\n%@", __func__, \ + [GTMSessionSyncMonitorInternal functionsHoldingSynchronizationOnObject:obj], \ + [NSThread callStackSymbols]); \ + } + +// GTMSessionSyncMonitorInternal is a private class that keeps track of the +// beginning and end of synchronized scopes. +// +// This class should not be used directly, but only via the +// GTMSessionMonitorSynchronized macro. +@interface GTMSessionSyncMonitorInternal : NSObject +- (instancetype)initWithSynchronizationObject:(id)object + allowRecursive:(BOOL)allowRecursive + functionName:(const char *)functionName; +// Return the names of the functions that hold sync on the object, or nil if none. ++ (NSArray *)functionsHoldingSynchronizationOnObject:(id)object; +@end + +#else + #define GTMSessionMonitorSynchronized(obj) do { } while (0) + #define GTMSessionMonitorRecursiveSynchronized(obj) do { } while (0) + #define GTMSessionCheckSynchronized(obj) do { } while (0) + #define GTMSessionCheckNotSynchronized(obj) do { } while (0) +#endif // !DEBUG +#endif // __OBJC__ + + +GTM_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m new file mode 100644 index 0000000..c248847 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcher.m @@ -0,0 +1,4648 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionFetcher.h" +#if TARGET_OS_OSX && GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH +// To reconnect background sessions on Mac outside +load requires importing and linking +// AppKit to access the NSApplicationDidFinishLaunching symbol. +#import +#endif + +#import + +#ifndef STRIP_GTM_FETCH_LOGGING + #error GTMSessionFetcher headers should have defaulted this if it wasn't already defined. +#endif + +GTM_ASSUME_NONNULL_BEGIN + +NSString *const kGTMSessionFetcherStartedNotification = @"kGTMSessionFetcherStartedNotification"; +NSString *const kGTMSessionFetcherStoppedNotification = @"kGTMSessionFetcherStoppedNotification"; +NSString *const kGTMSessionFetcherRetryDelayStartedNotification = @"kGTMSessionFetcherRetryDelayStartedNotification"; +NSString *const kGTMSessionFetcherRetryDelayStoppedNotification = @"kGTMSessionFetcherRetryDelayStoppedNotification"; + +NSString *const kGTMSessionFetcherCompletionInvokedNotification = @"kGTMSessionFetcherCompletionInvokedNotification"; +NSString *const kGTMSessionFetcherCompletionDataKey = @"data"; +NSString *const kGTMSessionFetcherCompletionErrorKey = @"error"; + +NSString *const kGTMSessionFetcherErrorDomain = @"com.google.GTMSessionFetcher"; +NSString *const kGTMSessionFetcherStatusDomain = @"com.google.HTTPStatus"; +NSString *const kGTMSessionFetcherStatusDataKey = @"data"; // data returned with a kGTMSessionFetcherStatusDomain error +NSString *const kGTMSessionFetcherStatusDataContentTypeKey = @"data_content_type"; + +NSString *const kGTMSessionFetcherNumberOfRetriesDoneKey = @"kGTMSessionFetcherNumberOfRetriesDoneKey"; +NSString *const kGTMSessionFetcherElapsedIntervalWithRetriesKey = @"kGTMSessionFetcherElapsedIntervalWithRetriesKey"; + +static NSString *const kGTMSessionIdentifierPrefix = @"com.google.GTMSessionFetcher"; +static NSString *const kGTMSessionIdentifierDestinationFileURLMetadataKey = @"_destURL"; +static NSString *const kGTMSessionIdentifierBodyFileURLMetadataKey = @"_bodyURL"; + +// The default max retry interview is 10 minutes for uploads (POST/PUT/PATCH), +// 1 minute for downloads. +static const NSTimeInterval kUnsetMaxRetryInterval = -1.0; +static const NSTimeInterval kDefaultMaxDownloadRetryInterval = 60.0; +static const NSTimeInterval kDefaultMaxUploadRetryInterval = 60.0 * 10.; + +// The maximum data length that can be loaded to the error userInfo +static const int64_t kMaximumDownloadErrorDataLength = 20000; + +#ifdef GTMSESSION_PERSISTED_DESTINATION_KEY +// Projects using unique class names should also define a unique persisted destination key. +static NSString * const kGTMSessionFetcherPersistedDestinationKey = + GTMSESSION_PERSISTED_DESTINATION_KEY; +#else +static NSString * const kGTMSessionFetcherPersistedDestinationKey = + @"com.google.GTMSessionFetcher.downloads"; +#endif + +GTM_ASSUME_NONNULL_END + +// +// GTMSessionFetcher +// + +#if 0 +#define GTM_LOG_BACKGROUND_SESSION(...) GTMSESSION_LOG_DEBUG(__VA_ARGS__) +#else +#define GTM_LOG_BACKGROUND_SESSION(...) +#endif + +#ifndef GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY + #if (TARGET_OS_TV \ + || TARGET_OS_WATCH \ + || (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0)) + #define GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY 1 + #endif +#endif + +#if ((defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) || \ + (TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MIN_REQUIRED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MIN_REQUIRED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#elif ((TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MAX_ALLOWED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MAX_ALLOWED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 1 +#else +#define GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#define GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION 0 +#endif + +#if ((defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST) || \ + (TARGET_OS_OSX && defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15) || \ + (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_13_0) || \ + (TARGET_OS_WATCH && defined(__WATCHOS_6_0) && __WATCHOS_VERSION_MIN_REQUIRED >= __WATCHOS_6_0) || \ + (TARGET_OS_TV && defined(__TVOS_13_0) && __TVOS_VERSION_MIN_REQUIRED >= __TVOS_13_0)) +#define GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR 1 +#else +#define GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR 0 +#endif + +@interface GTMSessionFetcher () + +@property(atomic, strong, readwrite, GTM_NULLABLE) NSData *downloadedData; +@property(atomic, strong, readwrite, GTM_NULLABLE) NSData *downloadResumeData; + +#if GTM_BACKGROUND_TASK_FETCHING +// Should always be accessed within an @synchronized(self). +@property(assign, nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier; +#endif + +@property(atomic, readwrite, getter=isUsingBackgroundSession) BOOL usingBackgroundSession; + +@end + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (GTMSessionFetcherLoggingInternal) +- (void)logFetchWithError:(NSError *)error; +- (void)logNowWithError:(GTM_NULLABLE NSError *)error; +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream; +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider; +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +GTM_ASSUME_NONNULL_BEGIN + +static NSTimeInterval InitialMinRetryInterval(void) { + return 1.0 + ((double)(arc4random_uniform(0x0FFFF)) / (double) 0x0FFFF); +} + +static BOOL IsLocalhost(NSString * GTM_NULLABLE_TYPE host) { + // We check if there's host, and then make the comparisons. + if (host == nil) return NO; + return ([host caseInsensitiveCompare:@"localhost"] == NSOrderedSame + || [host isEqual:@"::1"] + || [host isEqual:@"127.0.0.1"]); +} + +static NSDictionary *GTM_NULLABLE_TYPE GTMErrorUserInfoForData( + NSData *GTM_NULLABLE_TYPE data, NSDictionary *GTM_NULLABLE_TYPE responseHeaders) { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + + if (data.length > 0) { + userInfo[kGTMSessionFetcherStatusDataKey] = data; + + NSString *contentType = responseHeaders[@"Content-Type"]; + if (contentType) { + userInfo[kGTMSessionFetcherStatusDataContentTypeKey] = contentType; + } + } + + return userInfo.count > 0 ? userInfo : nil; +} + +static GTMSessionFetcherTestBlock GTM_NULLABLE_TYPE gGlobalTestBlock; + +@implementation GTMSessionFetcher { + NSMutableURLRequest *_request; // after beginFetch, changed only in delegate callbacks + BOOL _useUploadTask; // immutable after beginFetch + NSURL *_bodyFileURL; // immutable after beginFetch + GTMSessionFetcherBodyStreamProvider _bodyStreamProvider; // immutable after beginFetch + NSURLSession *_session; + BOOL _shouldInvalidateSession; // immutable after beginFetch + NSURLSession *_sessionNeedingInvalidation; + NSURLSessionConfiguration *_configuration; + NSURLSessionTask *_sessionTask; + NSString *_taskDescription; + float _taskPriority; + NSURLResponse *_response; + NSString *_sessionIdentifier; + BOOL _wasCreatedFromBackgroundSession; + BOOL _didCreateSessionIdentifier; + NSString *_sessionIdentifierUUID; + BOOL _userRequestedBackgroundSession; + BOOL _usingBackgroundSession; + NSMutableData * GTM_NULLABLE_TYPE _downloadedData; + NSError *_downloadFinishedError; + NSData *_downloadResumeData; // immutable after construction + NSData * GTM_NULLABLE_TYPE _downloadTaskErrorData; // Data for when download task fails + NSURL *_destinationFileURL; + int64_t _downloadedLength; + NSURLCredential *_credential; // username & password + NSURLCredential *_proxyCredential; // credential supplied to proxy servers + BOOL _isStopNotificationNeeded; // set when start notification has been sent + BOOL _isUsingTestBlock; // set when a test block was provided (remains set when the block is released) + id _userData; // retained, if set by caller + NSMutableDictionary *_properties; // more data retained for caller + dispatch_queue_t _callbackQueue; + dispatch_group_t _callbackGroup; // read-only after creation + NSOperationQueue *_delegateQueue; // immutable after beginFetch + + id _authorizer; // immutable after beginFetch + + // The service object that created and monitors this fetcher, if any. + id _service; // immutable; set by the fetcher service upon creation + NSString *_serviceHost; + NSInteger _servicePriority; // immutable after beginFetch + BOOL _hasStoppedFetching; // counterpart to _initialBeginFetchDate + BOOL _userStoppedFetching; + + BOOL _isRetryEnabled; // user wants auto-retry + NSTimer *_retryTimer; + NSUInteger _retryCount; + NSTimeInterval _maxRetryInterval; // default 60 (download) or 600 (upload) seconds + NSTimeInterval _minRetryInterval; // random between 1 and 2 seconds + NSTimeInterval _retryFactor; // default interval multiplier is 2 + NSTimeInterval _lastRetryInterval; + NSDate *_initialBeginFetchDate; // date that beginFetch was first invoked; immutable after initial beginFetch + NSDate *_initialRequestDate; // date of first request to the target server (ignoring auth) + BOOL _hasAttemptedAuthRefresh; // accessed only in shouldRetryNowForStatus: + + NSString *_comment; // comment for log + NSString *_log; +#if !STRIP_GTM_FETCH_LOGGING + NSMutableData *_loggedStreamData; + NSURL *_redirectedFromURL; + NSString *_logRequestBody; + NSString *_logResponseBody; + BOOL _hasLoggedError; + BOOL _deferResponseBodyLogging; +#endif +} + +#if !GTMSESSION_UNIT_TESTING ++ (void)load { +#if GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH && TARGET_OS_IPHONE + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(reconnectFetchersForBackgroundSessionsOnAppLaunch:) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; +#elif GTMSESSION_RECONNECT_BACKGROUND_SESSIONS_ON_LAUNCH && TARGET_OS_OSX + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(reconnectFetchersForBackgroundSessionsOnAppLaunch:) + name:NSApplicationDidFinishLaunchingNotification + object:nil]; +#else + [self fetchersForBackgroundSessions]; +#endif +} + ++ (void)reconnectFetchersForBackgroundSessionsOnAppLaunch:(NSNotification *)notification { + // Give all other app-did-launch handlers a chance to complete before + // reconnecting the fetchers. Not doing this may lead to reconnecting + // before the app delegate has a chance to run. + dispatch_async(dispatch_get_main_queue(), ^{ + [self fetchersForBackgroundSessions]; + }); +} +#endif // !GTMSESSION_UNIT_TESTING + ++ (instancetype)fetcherWithRequest:(GTM_NULLABLE NSURLRequest *)request { + return [[self alloc] initWithRequest:request configuration:nil]; +} + ++ (instancetype)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + ++ (instancetype)fetcherWithURLString:(NSString *)requestURLString { + return [self fetcherWithURL:(NSURL *)[NSURL URLWithString:requestURLString]]; +} + ++ (instancetype)fetcherWithDownloadResumeData:(NSData *)resumeData { + GTMSessionFetcher *fetcher = [self fetcherWithRequest:nil]; + fetcher.comment = @"Resuming download"; + fetcher.downloadResumeData = resumeData; + return fetcher; +} + ++ (GTM_NULLABLE instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (!fetcher && [sessionIdentifier hasPrefix:kGTMSessionIdentifierPrefix]) { + fetcher = [self fetcherWithRequest:nil]; + [fetcher setSessionIdentifier:sessionIdentifier]; + [sessionIdentifierToFetcherMap setObject:fetcher forKey:sessionIdentifier]; + fetcher->_wasCreatedFromBackgroundSession = YES; + [fetcher setCommentWithFormat:@"Resuming %@", + fetcher && fetcher->_sessionIdentifierUUID ? fetcher->_sessionIdentifierUUID : @"?"]; + } + return fetcher; +} + ++ (NSMapTable *)sessionIdentifierToFetcherMap { + // TODO: What if a service is involved in creating the fetcher? Currently, when re-creating + // fetchers, if a service was involved, it is not re-created. Should the service maintain a map? + static NSMapTable *gSessionIdentifierToFetcherMap = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSessionIdentifierToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return gSessionIdentifierToFetcherMap; +} + +#if !GTM_ALLOW_INSECURE_REQUESTS ++ (BOOL)appAllowsInsecureRequests { + // If the main bundle Info.plist key NSAppTransportSecurity is present, and it specifies + // NSAllowsArbitraryLoads, then we need to explicitly enforce secure schemes. +#if GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY + static BOOL allowsInsecureRequests; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSBundle *mainBundle = [NSBundle mainBundle]; + NSDictionary *appTransportSecurity = + [mainBundle objectForInfoDictionaryKey:@"NSAppTransportSecurity"]; + allowsInsecureRequests = + [[appTransportSecurity objectForKey:@"NSAllowsArbitraryLoads"] boolValue]; + }); + return allowsInsecureRequests; +#else + // For builds targeting iOS 8 or 10.10 and earlier, we want to require fetcher + // security checks. + return YES; +#endif // GTM_TARGET_SUPPORTS_APP_TRANSPORT_SECURITY +} +#else // GTM_ALLOW_INSECURE_REQUESTS ++ (BOOL)appAllowsInsecureRequests { + return YES; +} +#endif // !GTM_ALLOW_INSECURE_REQUESTS + + +- (instancetype)init { + return [self initWithRequest:nil configuration:nil]; +} + +- (instancetype)initWithRequest:(NSURLRequest *)request { + return [self initWithRequest:request configuration:nil]; +} + +- (instancetype)initWithRequest:(GTM_NULLABLE NSURLRequest *)request + configuration:(GTM_NULLABLE NSURLSessionConfiguration *)configuration { + self = [super init]; + if (self) { +#if GTM_BACKGROUND_TASK_FETCHING + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; +#endif + _request = [request mutableCopy]; + _configuration = configuration; + + NSData *bodyData = request.HTTPBody; + if (bodyData) { + _bodyLength = (int64_t)bodyData.length; + } else { + _bodyLength = NSURLSessionTransferSizeUnknown; + } + + _callbackQueue = dispatch_get_main_queue(); + _callbackGroup = dispatch_group_create(); + _delegateQueue = [NSOperationQueue mainQueue]; + + _minRetryInterval = InitialMinRetryInterval(); + _maxRetryInterval = kUnsetMaxRetryInterval; + + _taskPriority = -1.0f; // Valid values if set are 0.0...1.0. + + _testBlockAccumulateDataChunkCount = 1; + +#if !STRIP_GTM_FETCH_LOGGING + // Encourage developers to set the comment property or use + // setCommentWithFormat: by providing a default string. + _comment = @"(No fetcher comment set)"; +#endif + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + // disallow use of fetchers in a copy property + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (NSString *)description { + NSString *requestStr = self.request.URL.description; + if (requestStr.length == 0) { + if (self.downloadResumeData.length > 0) { + requestStr = @""; + } else if (_wasCreatedFromBackgroundSession) { + requestStr = @""; + } else { + requestStr = @""; + } + } + return [NSString stringWithFormat:@"%@ %p (%@)", [self class], self, requestStr]; +} + +- (void)dealloc { + GTMSESSION_ASSERT_DEBUG(!_isStopNotificationNeeded, + @"unbalanced fetcher notification for %@", _request.URL); + [self forgetSessionIdentifierForFetcherWithoutSyncCheck]; + + // Note: if a session task or a retry timer was pending, then this instance + // would be retained by those so it wouldn't be getting dealloc'd, + // hence we don't need to stopFetch here +} + +#pragma mark - + +// Begin fetching the URL (or begin a retry fetch). The delegate is retained +// for the duration of the fetch connection. + +- (void)beginFetchWithCompletionHandler:(GTM_NULLABLE GTMSessionFetcherCompletionHandler)handler { + GTMSessionCheckNotSynchronized(self); + + _completionHandler = [handler copy]; + + // The user may have called setDelegate: earlier if they want to use other + // delegate-style callbacks during the fetch; otherwise, the delegate is nil, + // which is fine. + [self beginFetchMayDelay:YES mayAuthorize:YES]; +} + +// Begin fetching the URL for a retry fetch. The delegate and completion handler +// are already provided, and do not need to be copied. +- (void)beginFetchForRetry { + GTMSessionCheckNotSynchronized(self); + + [self beginFetchMayDelay:YES mayAuthorize:YES]; +} + +- (GTMSessionFetcherCompletionHandler)completionHandlerWithTarget:(GTM_NULLABLE_TYPE id)target + didFinishSelector:(GTM_NULLABLE_TYPE SEL)finishedSelector { + GTMSessionFetcherAssertValidSelector(target, finishedSelector, @encode(GTMSessionFetcher *), + @encode(NSData *), @encode(NSError *), 0); + GTMSessionFetcherCompletionHandler completionHandler = ^(NSData *data, NSError *error) { + if (target && finishedSelector) { + id selfArg = self; // Placate ARC. + NSMethodSignature *sig = [target methodSignatureForSelector:finishedSelector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig]; + [invocation setSelector:(SEL)finishedSelector]; + [invocation setTarget:target]; + [invocation setArgument:&selfArg atIndex:2]; + [invocation setArgument:&data atIndex:3]; + [invocation setArgument:&error atIndex:4]; + [invocation invoke]; + } + }; + return completionHandler; +} + +- (void)beginFetchWithDelegate:(GTM_NULLABLE_TYPE id)target + didFinishSelector:(GTM_NULLABLE_TYPE SEL)finishedSelector { + GTMSessionCheckNotSynchronized(self); + + GTMSessionFetcherCompletionHandler handler = [self completionHandlerWithTarget:target + didFinishSelector:finishedSelector]; + [self beginFetchWithCompletionHandler:handler]; +} + +- (void)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize { + // This is the internal entry point for re-starting fetches. + GTMSessionCheckNotSynchronized(self); + + NSMutableURLRequest *fetchRequest = _request; // The request property is now externally immutable. + NSURL *fetchRequestURL = fetchRequest.URL; + NSString *priorSessionIdentifier = self.sessionIdentifier; + + // A utility block for creating error objects when we fail to start the fetch. + NSError *(^beginFailureError)(NSInteger) = ^(NSInteger code){ + NSString *urlString = fetchRequestURL.absoluteString; + NSDictionary *userInfo = @{ + NSURLErrorFailingURLStringErrorKey : (urlString ? urlString : @"(missing URL)") + }; + return [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:code + userInfo:userInfo]; + }; + + // Catch delegate queue maxConcurrentOperationCount values other than 1, particularly + // NSOperationQueueDefaultMaxConcurrentOperationCount (-1), to avoid the additional complexity + // of simultaneous or out-of-order delegate callbacks. + GTMSESSION_ASSERT_DEBUG(_delegateQueue.maxConcurrentOperationCount == 1, + @"delegate queue %@ should support one concurrent operation, not %ld", + _delegateQueue.name, + (long)_delegateQueue.maxConcurrentOperationCount); + + if (!_initialBeginFetchDate) { + // This ivar is set only here on the initial beginFetch so need not be synchronized. + _initialBeginFetchDate = [[NSDate alloc] init]; + } + + if (self.sessionTask != nil) { + // If cached fetcher returned through fetcherWithSessionIdentifier:, then it's + // already begun, but don't consider this a failure, since the user need not know this. + if (self.sessionIdentifier != nil) { + return; + } + GTMSESSION_ASSERT_DEBUG(NO, @"Fetch object %@ being reused; this should never happen", self); + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorDownloadFailed)]; + return; + } + + if (fetchRequestURL == nil && !_downloadResumeData && !priorSessionIdentifier) { + GTMSESSION_ASSERT_DEBUG(NO, @"Beginning a fetch requires a request with a URL"); + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorDownloadFailed)]; + return; + } + + // We'll respect the user's request for a background session (unless this is + // an upload fetcher, which does its initial request foreground.) + self.usingBackgroundSession = self.useBackgroundSession && [self canFetchWithBackgroundSession]; + + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSError *fileCheckError; + if (![bodyFileURL checkResourceIsReachableAndReturnError:&fileCheckError]) { + // This assert fires when the file being uploaded no longer exists once + // the fetcher is ready to start the upload. + GTMSESSION_ASSERT_DEBUG_OR_LOG(0, @"Body file is unreachable: %@\n %@", + bodyFileURL.path, fileCheckError); + [self failToBeginFetchWithError:fileCheckError]; + return; + } + } + + NSString *requestScheme = fetchRequestURL.scheme; + BOOL isDataRequest = [requestScheme isEqual:@"data"]; + if (isDataRequest) { + // NSURLSession does not support data URLs in background sessions. +#if DEBUG + if (priorSessionIdentifier || self.sessionIdentifier) { + GTMSESSION_LOG_DEBUG(@"Converting background to foreground session for %@", + fetchRequest); + } +#endif + [self setSessionIdentifierInternal:nil]; + self.useBackgroundSession = NO; + } + +#if GTM_ALLOW_INSECURE_REQUESTS + BOOL shouldCheckSecurity = NO; +#else + BOOL shouldCheckSecurity = (fetchRequestURL != nil + && !isDataRequest + && [[self class] appAllowsInsecureRequests]); +#endif + + if (shouldCheckSecurity) { + // Allow https only for requests, unless overridden by the client. + // + // Non-https requests may too easily be snooped, so we disallow them by default. + // + // file: and data: schemes are usually safe if they are hardcoded in the client or provided + // by a trusted source, but since it's fairly rare to need them, it's safest to make clients + // explicitly whitelist them. + BOOL isSecure = + requestScheme != nil && [requestScheme caseInsensitiveCompare:@"https"] == NSOrderedSame; + if (!isSecure) { + BOOL allowRequest = NO; + NSString *host = fetchRequestURL.host; + + // Check schemes first. A file scheme request may be allowed here, or as a localhost request. + for (NSString *allowedScheme in _allowedInsecureSchemes) { + if (requestScheme != nil && + [requestScheme caseInsensitiveCompare:allowedScheme] == NSOrderedSame) { + allowRequest = YES; + break; + } + } + if (!allowRequest) { + // Check for localhost requests. Security checks only occur for non-https requests, so + // this check won't happen for an https request to localhost. + BOOL isLocalhostRequest = (host.length == 0 && [fetchRequestURL isFileURL]) || IsLocalhost(host); + if (isLocalhostRequest) { + if (self.allowLocalhostRequest) { + allowRequest = YES; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Fetch request for localhost but fetcher" + @" allowLocalhostRequest is not set: %@", fetchRequestURL); + } + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Insecure fetch request has a scheme (%@)" + @" not found in fetcher allowedInsecureSchemes (%@): %@", + requestScheme, _allowedInsecureSchemes ?: @" @[] ", fetchRequestURL); + } + } + + if (!allowRequest) { +#if !DEBUG + NSLog(@"Insecure fetch disallowed for %@", fetchRequestURL.description ?: @"nil request URL"); +#endif + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorInsecureRequest)]; + return; + } + } // !isSecure + } // (requestURL != nil) && !isDataRequest + + if (self.cookieStorage == nil) { + self.cookieStorage = [[self class] staticCookieStorage]; + } + + BOOL isRecreatingSession = (self.sessionIdentifier != nil) && (fetchRequest == nil); + + self.canShareSession = !isRecreatingSession && !self.usingBackgroundSession; + + if (!self.session && self.canShareSession) { + self.session = [_service sessionForFetcherCreation]; + // If _session is nil, then the service's session creation semaphore will block + // until this fetcher invokes fetcherDidCreateSession: below, so this *must* invoke + // that method, even if the session fails to be created. + } + + if (!self.session) { + // Create a session. + if (!_configuration) { + if (priorSessionIdentifier || self.usingBackgroundSession) { + NSString *sessionIdentifier = priorSessionIdentifier; + if (!sessionIdentifier) { + sessionIdentifier = [self createSessionIdentifierWithMetadata:nil]; + } + NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIdentifierToFetcherMap]; + [sessionIdentifierToFetcherMap setObject:self forKey:self.sessionIdentifier]; + + if (@available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.10, *)) { + _configuration = + [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionIdentifier]; + } else { +#if ((!TARGET_OS_IPHONE && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) \ + || (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)) + // If building with support for iOS 7 or < macOS 10.10, allow using the older + // -backgroundSessionConfiguration: method, otherwise leave it out to avoid deprecated + // API warnings/errors. + _configuration = + [NSURLSessionConfiguration backgroundSessionConfiguration:sessionIdentifier]; +#endif + } + self.usingBackgroundSession = YES; + self.canShareSession = NO; + } else { + _configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + } +#if !GTM_ALLOW_INSECURE_REQUESTS +#if GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; +#elif GTM_SDK_SUPPORTS_TLSMINIMUMSUPPORTEDPROTOCOLVERSION + if (@available(iOS 13, tvOS 13, watchOS 6, macOS 10.15, *)) { +#if TARGET_OS_IOS + // Early seeds of iOS 13 don't actually support the selector and several + // months later, those seeds are still in use, so validate if the selector + // is supported. + if ([_configuration respondsToSelector:@selector(setTLSMinimumSupportedProtocolVersion:)]) { + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; + } else { + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; + } +#else + _configuration.TLSMinimumSupportedProtocolVersion = tls_protocol_version_TLSv12; +#endif // TARGET_OS_IOS + } else { + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; + } +#else + _configuration.TLSMinimumSupportedProtocol = kTLSProtocol12; +#endif // GTM_SDK_REQUIRES_TLSMINIMUMSUPPORTEDPROTOCOLVERSION +#endif + } // !_configuration + _configuration.HTTPCookieStorage = self.cookieStorage; + + if (_configurationBlock) { + _configurationBlock(self, _configuration); + } + + id delegate = [_service sessionDelegate]; + if (!delegate || !self.canShareSession) { + delegate = self; + } + self.session = [NSURLSession sessionWithConfiguration:_configuration + delegate:delegate + delegateQueue:self.sessionDelegateQueue]; + GTMSESSION_ASSERT_DEBUG(self.session, @"Couldn't create session"); + + // Tell the service about the session created by this fetcher. This also signals the + // service's semaphore to allow other fetchers to request this session. + [_service fetcherDidCreateSession:self]; + + // If this assertion fires, the client probably tried to use a session identifier that was + // already used. The solution is to make the client use a unique identifier (or better yet let + // the session fetcher assign the identifier). + GTMSESSION_ASSERT_DEBUG(self.session.delegate == delegate, @"Couldn't assign delegate."); + + if (self.session) { + BOOL isUsingSharedDelegate = (delegate != self); + if (!isUsingSharedDelegate) { + _shouldInvalidateSession = YES; + } + } + } + + if (isRecreatingSession) { + _shouldInvalidateSession = YES; + + // Let's make sure there are tasks still running or if not that we get a callback from a + // completed one; otherwise, we assume the tasks failed. + // This is the observed behavior perhaps 25% of the time within the Simulator running 7.0.3 on + // exiting the app after starting an upload and relaunching the app if we manage to relaunch + // after the task has completed, but before the system relaunches us in the background. + [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, + NSArray *downloadTasks) { + if (dataTasks.count == 0 && uploadTasks.count == 0 && downloadTasks.count == 0) { + double const kDelayInSeconds = 1.0; // We should get progress indication or completion soon + dispatch_time_t checkForFeedbackDelay = + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDelayInSeconds * NSEC_PER_SEC)); + dispatch_after(checkForFeedbackDelay, dispatch_get_main_queue(), ^{ + if (!self.sessionTask && !fetchRequest) { + // If our task and/or request haven't been restored, then we assume task feedback lost. + [self removePersistedBackgroundSessionFromDefaults]; + NSError *sessionError = + [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorBackgroundFetchFailed + userInfo:nil]; + [self failToBeginFetchWithError:sessionError]; + } + }); + } + }]; + return; + } + + self.downloadedData = nil; + self.downloadedLength = 0; + + if (_servicePriority == NSIntegerMin) { + mayDelay = NO; + } + if (mayDelay && _service) { + BOOL shouldFetchNow = [_service fetcherShouldBeginFetching:self]; + if (!shouldFetchNow) { + // The fetch is deferred, but will happen later. + // + // If this session is held by the fetcher service, clear the session now so that we don't + // assume it's still valid after the fetcher is restarted. + if (self.canShareSession) { + self.session = nil; + } + return; + } + } + + NSString *effectiveHTTPMethod = [fetchRequest valueForHTTPHeaderField:@"X-HTTP-Method-Override"]; + if (effectiveHTTPMethod == nil) { + effectiveHTTPMethod = fetchRequest.HTTPMethod; + } + BOOL isEffectiveHTTPGet = (effectiveHTTPMethod == nil + || [effectiveHTTPMethod isEqual:@"GET"]); + + BOOL needsUploadTask = (self.useUploadTask || self.bodyFileURL || self.bodyStreamProvider); + if (_bodyData || self.bodyStreamProvider || fetchRequest.HTTPBodyStream) { + if (isEffectiveHTTPGet) { + fetchRequest.HTTPMethod = @"POST"; + isEffectiveHTTPGet = NO; + } + + if (_bodyData) { + if (!needsUploadTask) { + fetchRequest.HTTPBody = _bodyData; + } +#if !STRIP_GTM_FETCH_LOGGING + } else if (fetchRequest.HTTPBodyStream) { + if ([self respondsToSelector:@selector(loggedInputStreamForInputStream:)]) { + fetchRequest.HTTPBodyStream = + [self performSelector:@selector(loggedInputStreamForInputStream:) + withObject:fetchRequest.HTTPBodyStream]; + } +#endif + } + } + + // We authorize after setting up the http method and body in the request + // because OAuth 1 may need to sign the request body + if (mayAuthorize && _authorizer && !isDataRequest) { + BOOL isAuthorized = [_authorizer isAuthorizedRequest:fetchRequest]; + if (!isAuthorized) { + // Authorization needed. + // + // If this session is held by the fetcher service, clear the session now so that we don't + // assume it's still valid after authorization completes. + if (self.canShareSession) { + self.session = nil; + } + + // Authorizing the request will recursively call this beginFetch:mayDelay: + // or failToBeginFetchWithError:. + [self authorizeRequest]; + return; + } + } + + // set the default upload or download retry interval, if necessary + if ([self isRetryEnabled] && self.maxRetryInterval <= 0) { + if (isEffectiveHTTPGet || [effectiveHTTPMethod isEqual:@"HEAD"]) { + [self setMaxRetryInterval:kDefaultMaxDownloadRetryInterval]; + } else { + [self setMaxRetryInterval:kDefaultMaxUploadRetryInterval]; + } + } + + // finally, start the connection + NSURLSessionTask *newSessionTask; + BOOL needsDataAccumulator = NO; + if (_downloadResumeData) { + newSessionTask = [_session downloadTaskWithResumeData:_downloadResumeData]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed downloadTaskWithResumeData for %@, resume data %lu bytes", + _session, (unsigned long)_downloadResumeData.length); + } else if (_destinationFileURL && !isDataRequest) { + newSessionTask = [_session downloadTaskWithRequest:fetchRequest]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, @"Failed downloadTaskWithRequest for %@, %@", + _session, fetchRequest); + } else if (needsUploadTask) { + if (bodyFileURL) { + newSessionTask = [_session uploadTaskWithRequest:fetchRequest + fromFile:bodyFileURL]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithRequest for %@, %@, file %@", + _session, fetchRequest, bodyFileURL.path); + } else if (self.bodyStreamProvider) { + newSessionTask = [_session uploadTaskWithStreamedRequest:fetchRequest]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithStreamedRequest for %@, %@", + _session, fetchRequest); + } else { + GTMSESSION_ASSERT_DEBUG_OR_LOG(_bodyData != nil, + @"Upload task needs body data, %@", fetchRequest); + newSessionTask = [_session uploadTaskWithRequest:fetchRequest + fromData:(NSData * GTM_NONNULL_TYPE)_bodyData]; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, + @"Failed uploadTaskWithRequest for %@, %@, body data %lu bytes", + _session, fetchRequest, (unsigned long)_bodyData.length); + } + needsDataAccumulator = YES; + } else { + newSessionTask = [_session dataTaskWithRequest:fetchRequest]; + needsDataAccumulator = YES; + GTMSESSION_ASSERT_DEBUG_OR_LOG(newSessionTask, @"Failed dataTaskWithRequest for %@, %@", + _session, fetchRequest); + } + self.sessionTask = newSessionTask; + + if (!newSessionTask) { + // We shouldn't get here; if we're here, an earlier assertion should have fired to explain + // which session task creation failed. + [self failToBeginFetchWithError:beginFailureError(GTMSessionFetcherErrorTaskCreationFailed)]; + return; + } + + if (needsDataAccumulator && _accumulateDataBlock == nil) { + self.downloadedData = [NSMutableData data]; + } + if (_taskDescription) { + newSessionTask.taskDescription = _taskDescription; + } + if (_taskPriority >= 0) { + if (@available(iOS 8.0, macOS 10.10, *)) { + newSessionTask.priority = _taskPriority; + } + } + +#if GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSESSION_ASSERT_DEBUG(_testBlock == nil && gGlobalTestBlock == nil, @"test blocks disabled"); + _testBlock = nil; +#else + if (!_testBlock) { + if (gGlobalTestBlock) { + // Note that the test block may pass nil for all of its response parameters, + // indicating that the fetch should actually proceed. This is useful when the + // global test block has been set, and the app is only testing a specific + // fetcher. The block simulation code will then resume the task. + _testBlock = gGlobalTestBlock; + } + } + _isUsingTestBlock = (_testBlock != nil); +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK + +#if GTM_BACKGROUND_TASK_FETCHING + id app = [[self class] fetcherUIApplication]; + // Background tasks seem to interfere with out-of-process uploads and downloads. + if (app && !self.skipBackgroundTask && !self.useBackgroundSession) { + // Tell UIApplication that we want to continue even when the app is in the + // background. +#if DEBUG + NSString *bgTaskName = [NSString stringWithFormat:@"%@-%@", + [self class], fetchRequest.URL.host]; +#else + NSString *bgTaskName = @"GTMSessionFetcher"; +#endif + __block UIBackgroundTaskIdentifier bgTaskID = [app beginBackgroundTaskWithName:bgTaskName + expirationHandler:^{ + // Background task expiration callback - this block is always invoked by + // UIApplication on the main thread. + if (bgTaskID != UIBackgroundTaskInvalid) { + @synchronized(self) { + if (bgTaskID == self.backgroundTaskIdentifier) { + self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + } + [app endBackgroundTask:bgTaskID]; + } + }]; + @synchronized(self) { + self.backgroundTaskIdentifier = bgTaskID; + } + } +#endif + + if (!_initialRequestDate) { + _initialRequestDate = [[NSDate alloc] init]; + } + + // We don't expect to reach here even on retry or auth until a stop notification has been sent + // for the previous task, but we should ensure that we don't unbalance that. + GTMSESSION_ASSERT_DEBUG(!_isStopNotificationNeeded, @"Start notification without a prior stop"); + [self sendStopNotificationIfNeeded]; + + [self addPersistedBackgroundSessionToDefaults]; + + [self setStopNotificationNeeded:YES]; + + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherStartedNotification + userInfo:nil + requireAsync:NO]; + + // The service needs to know our task if it is serving as NSURLSession delegate. + [_service fetcherDidBeginFetching:self]; + + if (_testBlock) { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + [self simulateFetchForTestBlock]; +#endif + } else { + // We resume the session task after posting the notification since the + // delegate callbacks may happen immediately if the fetch is started off + // the main thread or the session delegate queue is on a background thread, + // and we don't want to post a start notification after a premature finish + // of the session task. + [newSessionTask resume]; + } +} + +NSData * GTM_NULLABLE_TYPE GTMDataFromInputStream(NSInputStream *inputStream, NSError **outError) { + NSMutableData *data = [NSMutableData data]; + + [inputStream open]; + NSInteger numberOfBytesRead = 0; + while ([inputStream hasBytesAvailable]) { + uint8_t buffer[512]; + numberOfBytesRead = [inputStream read:buffer maxLength:sizeof(buffer)]; + if (numberOfBytesRead > 0) { + [data appendBytes:buffer length:(NSUInteger)numberOfBytesRead]; + } else { + break; + } + } + [inputStream close]; + NSError *streamError = inputStream.streamError; + + if (streamError) { + data = nil; + } + if (outError) { + *outError = streamError; + } + return data; +} + +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + +- (void)simulateFetchForTestBlock { + // This is invoked on the same thread as the beginFetch method was. + // + // Callbacks will all occur on the callback queue. + _testBlock(self, ^(NSURLResponse *response, NSData *responseData, NSError *error) { + // Callback from test block. + if (response == nil && responseData == nil && error == nil) { + // Assume the fetcher should execute rather than be tested. + self->_testBlock = nil; + self->_isUsingTestBlock = NO; + [self->_sessionTask resume]; + return; + } + + GTMSessionFetcherBodyStreamProvider bodyStreamProvider = self.bodyStreamProvider; + if (bodyStreamProvider) { + bodyStreamProvider(^(NSInputStream *bodyStream){ + // Read from the input stream into an NSData buffer. We'll drain the stream + // explicitly on a background queue. + [self invokeOnCallbackQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0) + afterUserStopped:NO + block:^{ + NSError *streamError; + NSData *streamedData = GTMDataFromInputStream(bodyStream, &streamError); + + dispatch_async(dispatch_get_main_queue(), ^{ + // Continue callbacks on the main thread, since serial behavior + // is more reliable for tests. + [self simulateDataCallbacksForTestBlockWithBodyData:streamedData + response:response + responseData:responseData + error:(error ?: streamError)]; + }); + }]; + }); + } else { + // No input stream; use the supplied data or file URL. + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSError *readError; + self->_bodyData = [NSData dataWithContentsOfURL:bodyFileURL + options:NSDataReadingMappedIfSafe + error:&readError]; + error = readError; + } + + // No stream provider. + + // In real fetches, nothing happens until the run loop spins, so apps have leeway to + // set callbacks after they call beginFetch. We'll mirror that fetcher behavior by + // delaying callbacks here at least to the next spin of the run loop. That keeps + // immediate, synchronous setting of callback blocks after beginFetch working in tests. + dispatch_async(dispatch_get_main_queue(), ^{ + [self simulateDataCallbacksForTestBlockWithBodyData:self->_bodyData + response:response + responseData:responseData + error:error]; + }); + } + }); +} + +- (void)simulateByteTransferReportWithDataLength:(int64_t)totalDataLength + block:(GTMSessionFetcherSendProgressBlock)block { + // This utility method simulates transfer progress with up to three callbacks. + // It is used to call back to any of the progress blocks. + int64_t sendReportSize = totalDataLength / 3 + 1; + int64_t totalSent = 0; + while (totalSent < totalDataLength) { + int64_t bytesRemaining = totalDataLength - totalSent; + sendReportSize = MIN(sendReportSize, bytesRemaining); + totalSent += sendReportSize; + [self invokeOnCallbackQueueUnlessStopped:^{ + block(sendReportSize, totalSent, totalDataLength); + }]; + } +} + +- (void)simulateDataCallbacksForTestBlockWithBodyData:(NSData * GTM_NULLABLE_TYPE)bodyData + response:(NSURLResponse *)response + responseData:(NSData *)suppliedData + error:(NSError *)suppliedError { + __block NSData *responseData = suppliedData; + __block NSError *responseError = suppliedError; + + // This method does the test simulation of callbacks once the upload + // and download data are known. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Get copies of ivars we'll access in async invocations. This simulation assumes + // they won't change during fetcher execution. + NSURL *destinationFileURL = _destinationFileURL; + GTMSessionFetcherWillRedirectBlock willRedirectBlock = _willRedirectBlock; + GTMSessionFetcherDidReceiveResponseBlock didReceiveResponseBlock = _didReceiveResponseBlock; + GTMSessionFetcherSendProgressBlock sendProgressBlock = _sendProgressBlock; + GTMSessionFetcherDownloadProgressBlock downloadProgressBlock = _downloadProgressBlock; + GTMSessionFetcherAccumulateDataBlock accumulateDataBlock = _accumulateDataBlock; + GTMSessionFetcherReceivedProgressBlock receivedProgressBlock = _receivedProgressBlock; + GTMSessionFetcherWillCacheURLResponseBlock willCacheURLResponseBlock = + _willCacheURLResponseBlock; + GTMSessionFetcherChallengeBlock challengeBlock = _challengeBlock; + + // Simulate receipt of redirection. + if (willRedirectBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + willRedirectBlock((NSHTTPURLResponse *)response, self->_request, + ^(NSURLRequest *redirectRequest) { + // For simulation, we'll assume the app will just continue. + }); + }]; + } + + // If the fetcher has a challenge block, simulate a challenge. + // + // It might be nice to eventually let the user determine which testBlock + // fetches get challenged rather than always executing the supplied + // challenge block. + if (challengeBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + NSURL *requestURL = self->_request.URL; + NSString *host = requestURL.host; + NSURLProtectionSpace *pspace = + [[NSURLProtectionSpace alloc] initWithHost:host + port:requestURL.port.integerValue + protocol:requestURL.scheme + realm:nil + authenticationMethod:NSURLAuthenticationMethodHTTPBasic]; + id unusedSender = + (id)[NSNull null]; + NSURLAuthenticationChallenge *challenge = + [[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:pspace + proposedCredential:nil + previousFailureCount:0 + failureResponse:nil + error:nil + sender:unusedSender]; + challengeBlock(self, challenge, ^(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential){ + // We could change the responseData and responseError based on the disposition, + // but it's easier for apps to just supply the expected data and error + // directly to the test block. So this simulation ignores the disposition. + }); + }]; + } + + // Simulate receipt of an initial response. + if (response && didReceiveResponseBlock) { + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + didReceiveResponseBlock(response, ^(NSURLSessionResponseDisposition desiredDisposition) { + // For simulation, we'll assume the disposition is to continue. + }); + }]; + } + + // Simulate reporting send progress. + if (sendProgressBlock) { + [self simulateByteTransferReportWithDataLength:(int64_t)bodyData.length + block:^(int64_t bytesSent, + int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + // This is invoked on the callback queue unless stopped. + sendProgressBlock(bytesSent, totalBytesSent, totalBytesExpectedToSend); + }]; + } + + if (destinationFileURL) { + // Simulate download to file progress. + if (downloadProgressBlock) { + [self simulateByteTransferReportWithDataLength:(int64_t)responseData.length + block:^(int64_t bytesDownloaded, + int64_t totalBytesDownloaded, + int64_t totalBytesExpectedToDownload) { + // This is invoked on the callback queue unless stopped. + downloadProgressBlock(bytesDownloaded, totalBytesDownloaded, + totalBytesExpectedToDownload); + }]; + } + + NSError *writeError; + [responseData writeToURL:destinationFileURL + options:NSDataWritingAtomic + error:&writeError]; + if (writeError) { + // Tell the test code that writing failed. + responseError = writeError; + } + } else { + // Simulate download to NSData progress. + if ((accumulateDataBlock || receivedProgressBlock) && responseData) { + [self simulateByteTransferWithData:responseData + block:^(NSData *data, + int64_t bytesReceived, + int64_t totalBytesReceived, + int64_t totalBytesExpectedToReceive) { + // This is invoked on the callback queue unless stopped. + if (accumulateDataBlock) { + accumulateDataBlock(data); + } + + if (receivedProgressBlock) { + receivedProgressBlock(bytesReceived, totalBytesReceived); + } + }]; + } + + if (!accumulateDataBlock) { + _downloadedData = [responseData mutableCopy]; + } + + if (willCacheURLResponseBlock) { + // Simulate letting the client inspect and alter the cached response. + NSData *cachedData = responseData ?: [[NSData alloc] init]; // Always have non-nil data. + NSCachedURLResponse *cachedResponse = + [[NSCachedURLResponse alloc] initWithResponse:response + data:cachedData]; + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:YES + block:^{ + willCacheURLResponseBlock(cachedResponse, ^(NSCachedURLResponse *responseToCache){ + // The app may provide an alternative response, or nil to defeat caching. + }); + }]; + } + } + _response = response; + } // @synchronized(self) + + NSOperationQueue *queue = self.sessionDelegateQueue; + [queue addOperationWithBlock:^{ + // Rather than invoke failToBeginFetchWithError: we want to simulate completion of + // a connection that started and ended, so we'll call down to finishWithError: + NSInteger status = responseError ? responseError.code : 200; + if (status >= 200 && status <= 399) { + [self finishWithError:nil shouldRetry:NO]; + } else { + [self shouldRetryNowForStatus:status + error:responseError + forceAssumeRetry:NO + response:^(BOOL shouldRetry) { + [self finishWithError:responseError shouldRetry:shouldRetry]; + }]; + } + }]; +} + +- (void)simulateByteTransferWithData:(NSData *)responseData + block:(GTMSessionFetcherSimulateByteTransferBlock)transferBlock { + // This utility method simulates transfering data to the client. It divides the data into at most + // "chunkCount" chunks and then passes each chunk along with a progress update to transferBlock. + // This function can be used with accumulateDataBlock or receivedProgressBlock. + + NSUInteger chunkCount = MAX(self.testBlockAccumulateDataChunkCount, (NSUInteger) 1); + NSUInteger totalDataLength = responseData.length; + NSUInteger sendDataSize = totalDataLength / chunkCount + 1; + NSUInteger totalSent = 0; + while (totalSent < totalDataLength) { + NSUInteger bytesRemaining = totalDataLength - totalSent; + sendDataSize = MIN(sendDataSize, bytesRemaining); + NSData *chunkData = [responseData subdataWithRange:NSMakeRange(totalSent, sendDataSize)]; + totalSent += sendDataSize; + [self invokeOnCallbackQueueUnlessStopped:^{ + transferBlock(chunkData, + (int64_t)sendDataSize, + (int64_t)totalSent, + (int64_t)totalDataLength); + }]; + } +} + +#endif // !GTM_DISABLE_FETCHER_TEST_BLOCK + +- (void)setSessionTask:(NSURLSessionTask *)sessionTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionTask != sessionTask) { + _sessionTask = sessionTask; + if (_sessionTask) { + // Request could be nil on restoring this fetcher from a background session. + if (!_request) { + _request = [_sessionTask.originalRequest mutableCopy]; + } + } + } + } // @synchronized(self) +} + +- (NSURLSessionTask * GTM_NULLABLE_TYPE)sessionTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionTask; + } // @synchronized(self) +} + ++ (NSUserDefaults *)fetcherUserDefaults { + static NSUserDefaults *gFetcherUserDefaults = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class fetcherUserDefaultsClass = NSClassFromString(@"GTMSessionFetcherUserDefaultsFactory"); + if (fetcherUserDefaultsClass) { + gFetcherUserDefaults = [fetcherUserDefaultsClass fetcherUserDefaults]; + } else { + gFetcherUserDefaults = [NSUserDefaults standardUserDefaults]; + } + }); + return gFetcherUserDefaults; +} + +- (void)addPersistedBackgroundSessionToDefaults { + NSString *sessionIdentifier = self.sessionIdentifier; + if (!sessionIdentifier) { + return; + } + NSArray *oldBackgroundSessions = [[self class] activePersistedBackgroundSessions]; + if ([oldBackgroundSessions containsObject:_sessionIdentifier]) { + return; + } + NSMutableArray *newBackgroundSessions = + [NSMutableArray arrayWithArray:oldBackgroundSessions]; + [newBackgroundSessions addObject:sessionIdentifier]; + GTM_LOG_BACKGROUND_SESSION(@"Add to background sessions: %@", newBackgroundSessions); + + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + [userDefaults setObject:newBackgroundSessions + forKey:kGTMSessionFetcherPersistedDestinationKey]; + [userDefaults synchronize]; +} + +- (void)removePersistedBackgroundSessionFromDefaults { + NSString *sessionIdentifier = self.sessionIdentifier; + if (!sessionIdentifier) return; + + NSArray *oldBackgroundSessions = [[self class] activePersistedBackgroundSessions]; + if (!oldBackgroundSessions) { + return; + } + NSMutableArray *newBackgroundSessions = + [NSMutableArray arrayWithArray:oldBackgroundSessions]; + NSUInteger sessionIndex = [newBackgroundSessions indexOfObject:sessionIdentifier]; + if (sessionIndex == NSNotFound) { + return; + } + [newBackgroundSessions removeObjectAtIndex:sessionIndex]; + GTM_LOG_BACKGROUND_SESSION(@"Remove from background sessions: %@", newBackgroundSessions); + + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + if (newBackgroundSessions.count == 0) { + [userDefaults removeObjectForKey:kGTMSessionFetcherPersistedDestinationKey]; + } else { + [userDefaults setObject:newBackgroundSessions + forKey:kGTMSessionFetcherPersistedDestinationKey]; + } + [userDefaults synchronize]; +} + ++ (GTM_NULLABLE NSArray *)activePersistedBackgroundSessions { + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + NSArray *oldBackgroundSessions = + [userDefaults arrayForKey:kGTMSessionFetcherPersistedDestinationKey]; + if (oldBackgroundSessions.count == 0) { + return nil; + } + NSMutableArray *activeBackgroundSessions = nil; + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + for (NSString *sessionIdentifier in oldBackgroundSessions) { + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (fetcher) { + if (!activeBackgroundSessions) { + activeBackgroundSessions = [[NSMutableArray alloc] init]; + } + [activeBackgroundSessions addObject:sessionIdentifier]; + } + } + return activeBackgroundSessions; +} + ++ (NSArray *)fetchersForBackgroundSessions { + NSUserDefaults *userDefaults = [[self class] fetcherUserDefaults]; + NSArray *backgroundSessions = + [userDefaults arrayForKey:kGTMSessionFetcherPersistedDestinationKey]; + NSMapTable *sessionIdentifierToFetcherMap = [self sessionIdentifierToFetcherMap]; + NSMutableArray *fetchers = [NSMutableArray array]; + for (NSString *sessionIdentifier in backgroundSessions) { + GTMSessionFetcher *fetcher = [sessionIdentifierToFetcherMap objectForKey:sessionIdentifier]; + if (!fetcher) { + fetcher = [self fetcherWithSessionIdentifier:sessionIdentifier]; + GTMSESSION_ASSERT_DEBUG(fetcher != nil, + @"Unexpected invalid session identifier: %@", sessionIdentifier); + [fetcher beginFetchWithCompletionHandler:nil]; + } + GTM_LOG_BACKGROUND_SESSION(@"%@ restoring session %@ by creating fetcher %@ %p", + [self class], sessionIdentifier, fetcher, fetcher); + if (fetcher != nil) { + [fetchers addObject:fetcher]; + } + } + return fetchers; +} + +#if TARGET_OS_IPHONE && !TARGET_OS_WATCH ++ (void)application:(UIApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(GTMSessionFetcherSystemCompletionHandler)completionHandler { + GTMSessionFetcher *fetcher = [self fetcherWithSessionIdentifier:identifier]; + if (fetcher != nil) { + fetcher.systemCompletionHandler = completionHandler; + } else { + GTM_LOG_BACKGROUND_SESSION(@"%@ did not create background session identifier: %@", + [self class], identifier); + } +} +#endif + +- (NSString * GTM_NULLABLE_TYPE)sessionIdentifier { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionIdentifier; + } // @synchronized(self) +} + +- (void)setSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(!_session, @"Unable to set session identifier after session created"); + _sessionIdentifier = [sessionIdentifier copy]; + _usingBackgroundSession = YES; + _canShareSession = NO; + [self restoreDefaultStateForSessionIdentifierMetadata]; + } // @synchronized(self) +} + +- (void)setSessionIdentifierInternal:(GTM_NULLABLE NSString *)sessionIdentifier { + // This internal method only does a synchronized set of the session identifier. + // It does not have side effects on the background session, shared session, or + // session identifier metadata. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _sessionIdentifier = [sessionIdentifier copy]; + } // @synchronized(self) +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionUserInfo { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionUserInfo == nil) { + // We'll return the metadata dictionary with internal keys removed. This avoids the user + // re-using the userInfo dictionary later and accidentally including the internal keys. + NSMutableDictionary *metadata = [[self sessionIdentifierMetadataUnsynchronized] mutableCopy]; + NSSet *keysToRemove = [metadata keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) { + return [key hasPrefix:@"_"]; + }]; + [metadata removeObjectsForKeys:[keysToRemove allObjects]]; + if (metadata.count > 0) { + _sessionUserInfo = metadata; + } + } + return _sessionUserInfo; + } // @synchronized(self) +} + +- (void)setSessionUserInfo:(NSDictionary * GTM_NULLABLE_TYPE)dictionary { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(_sessionIdentifier == nil, @"Too late to assign userInfo"); + _sessionUserInfo = dictionary; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSDictionary *)sessionIdentifierDefaultMetadata { + GTMSessionCheckSynchronized(self); + + NSMutableDictionary *defaultUserInfo = [[NSMutableDictionary alloc] init]; + if (_destinationFileURL) { + defaultUserInfo[kGTMSessionIdentifierDestinationFileURLMetadataKey] = + [_destinationFileURL absoluteString]; + } + if (_bodyFileURL) { + defaultUserInfo[kGTMSessionIdentifierBodyFileURLMetadataKey] = [_bodyFileURL absoluteString]; + } + return (defaultUserInfo.count > 0) ? defaultUserInfo : nil; +} + +- (void)restoreDefaultStateForSessionIdentifierMetadata { + GTMSessionCheckSynchronized(self); + + NSDictionary *metadata = [self sessionIdentifierMetadataUnsynchronized]; + NSString *destinationFileURLString = metadata[kGTMSessionIdentifierDestinationFileURLMetadataKey]; + if (destinationFileURLString) { + _destinationFileURL = [NSURL URLWithString:destinationFileURLString]; + GTM_LOG_BACKGROUND_SESSION(@"Restoring destination file URL: %@", _destinationFileURL); + } + NSString *bodyFileURLString = metadata[kGTMSessionIdentifierBodyFileURLMetadataKey]; + if (bodyFileURLString) { + _bodyFileURL = [NSURL URLWithString:bodyFileURLString]; + GTM_LOG_BACKGROUND_SESSION(@"Restoring body file URL: %@", _bodyFileURL); + } +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionIdentifierMetadata { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [self sessionIdentifierMetadataUnsynchronized]; + } +} + +- (NSDictionary * GTM_NULLABLE_TYPE)sessionIdentifierMetadataUnsynchronized { + GTMSessionCheckSynchronized(self); + + // Session Identifier format: "com.google.__ + if (!_sessionIdentifier) { + return nil; + } + NSScanner *metadataScanner = [NSScanner scannerWithString:_sessionIdentifier]; + [metadataScanner setCharactersToBeSkipped:nil]; + NSString *metadataString; + NSString *uuid; + if ([metadataScanner scanUpToString:@"_" intoString:NULL] && + [metadataScanner scanString:@"_" intoString:NULL] && + [metadataScanner scanUpToString:@"_" intoString:&uuid] && + [metadataScanner scanString:@"_" intoString:NULL] && + [metadataScanner scanUpToString:@"\n" intoString:&metadataString]) { + _sessionIdentifierUUID = uuid; + NSData *metadataData = [metadataString dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error; + NSDictionary *metadataDict = + [NSJSONSerialization JSONObjectWithData:metadataData + options:0 + error:&error]; + GTM_LOG_BACKGROUND_SESSION(@"User Info from session identifier: %@ %@", + metadataDict, error ? error : @""); + return metadataDict; + } + return nil; +} + +- (NSString *)createSessionIdentifierWithMetadata:(NSDictionary * GTM_NULLABLE_TYPE)metadataToInclude { + NSString *result; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Session Identifier format: "com.google.__ + GTMSESSION_ASSERT_DEBUG(!_sessionIdentifier, @"Session identifier already created"); + _sessionIdentifierUUID = [[NSUUID UUID] UUIDString]; + _sessionIdentifier = + [NSString stringWithFormat:@"%@_%@", kGTMSessionIdentifierPrefix, _sessionIdentifierUUID]; + // Start with user-supplied keys so they cannot accidentally override the fetcher's keys. + NSMutableDictionary *metadataDict = + [NSMutableDictionary dictionaryWithDictionary:(NSDictionary * GTM_NONNULL_TYPE)_sessionUserInfo]; + + if (metadataToInclude) { + [metadataDict addEntriesFromDictionary:(NSDictionary *)metadataToInclude]; + } + NSDictionary *defaultMetadataDict = [self sessionIdentifierDefaultMetadata]; + if (defaultMetadataDict) { + [metadataDict addEntriesFromDictionary:defaultMetadataDict]; + } + if (metadataDict.count > 0) { + NSData *metadataData = [NSJSONSerialization dataWithJSONObject:metadataDict + options:0 + error:NULL]; + GTMSESSION_ASSERT_DEBUG(metadataData != nil, + @"Session identifier user info failed to convert to JSON"); + if (metadataData.length > 0) { + NSString *metadataString = [[NSString alloc] initWithData:metadataData + encoding:NSUTF8StringEncoding]; + _sessionIdentifier = + [_sessionIdentifier stringByAppendingFormat:@"_%@", metadataString]; + } + } + _didCreateSessionIdentifier = YES; + result = _sessionIdentifier; + } // @synchronized(self) + return result; +} + +- (void)failToBeginFetchWithError:(NSError *)error { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _hasStoppedFetching = YES; + } + + if (error == nil) { + error = [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorDownloadFailed + userInfo:nil]; + } + + [self invokeFetchCallbacksOnCallbackQueueWithData:nil + error:error]; + [self releaseCallbacks]; + + [_service fetcherDidStop:self]; + + self.authorizer = nil; +} + ++ (GTMSessionCookieStorage *)staticCookieStorage { + static GTMSessionCookieStorage *gCookieStorage = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gCookieStorage = [[GTMSessionCookieStorage alloc] init]; + }); + return gCookieStorage; +} + +#if GTM_BACKGROUND_TASK_FETCHING + +- (void)endBackgroundTask { + // Whenever the connection stops or background execution expires, + // we need to tell UIApplication we're done. + UIBackgroundTaskIdentifier bgTaskID; + @synchronized(self) { + bgTaskID = self.backgroundTaskIdentifier; + if (bgTaskID != UIBackgroundTaskInvalid) { + self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + } + + if (bgTaskID != UIBackgroundTaskInvalid) { + id app = [[self class] fetcherUIApplication]; + [app endBackgroundTask:bgTaskID]; + } +} + +#endif // GTM_BACKGROUND_TASK_FETCHING + +- (void)authorizeRequest { + GTMSessionCheckNotSynchronized(self); + + id authorizer = self.authorizer; + SEL asyncAuthSel = @selector(authorizeRequest:delegate:didFinishSelector:); + if ([authorizer respondsToSelector:asyncAuthSel]) { + SEL callbackSel = @selector(authorizer:request:finishedWithError:); + NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; + [authorizer authorizeRequest:mutableRequest + delegate:self + didFinishSelector:callbackSel]; + } else { + GTMSESSION_ASSERT_DEBUG(authorizer == nil, @"invalid authorizer for fetch"); + + // No authorizing possible, and authorizing happens only after any delay; + // just begin fetching + [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + +- (void)authorizer:(id)auth + request:(NSMutableURLRequest *)authorizedRequest + finishedWithError:(NSError *)error { + GTMSessionCheckNotSynchronized(self); + + if (error != nil) { + // We can't fetch without authorization + [self failToBeginFetchWithError:error]; + } else { + @synchronized(self) { + _request = authorizedRequest; + } + [self beginFetchMayDelay:NO + mayAuthorize:NO]; + } +} + + +- (BOOL)canFetchWithBackgroundSession { + // Subclasses may override. + return YES; +} + +// Returns YES if the fetcher has been started and has not yet stopped. +// +// Fetching includes waiting for authorization or for retry, waiting to be allowed by the +// service object to start the request, and actually fetching the request. +- (BOOL)isFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [self isFetchingUnsynchronized]; + } +} + +- (BOOL)isFetchingUnsynchronized { + GTMSessionCheckSynchronized(self); + + BOOL hasBegun = (_initialBeginFetchDate != nil); + return hasBegun && !_hasStoppedFetching; +} + +- (NSURLResponse * GTM_NULLABLE_TYPE)response { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + return response; + } // @synchronized(self) +} + +- (NSURLResponse * GTM_NULLABLE_TYPE)responseUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = _sessionTask.response; + if (!response) response = _response; + return response; +} + +- (NSInteger)statusCode { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSInteger statusCode = [self statusCodeUnsynchronized]; + return statusCode; + } // @synchronized(self) +} + +- (NSInteger)statusCodeUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + NSInteger statusCode; + + if ([response respondsToSelector:@selector(statusCode)]) { + statusCode = [(NSHTTPURLResponse *)response statusCode]; + } else { + // Default to zero, in hopes of hinting "Unknown" (we can't be + // sure that things are OK enough to use 200). + statusCode = 0; + } + return statusCode; +} + +- (NSDictionary * GTM_NULLABLE_TYPE)responseHeaders { + GTMSessionCheckNotSynchronized(self); + + NSURLResponse *response = self.response; + if ([response respondsToSelector:@selector(allHeaderFields)]) { + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + return headers; + } + return nil; +} + +- (NSDictionary * GTM_NULLABLE_TYPE)responseHeadersUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSURLResponse *response = [self responseUnsynchronized]; + if ([response respondsToSelector:@selector(allHeaderFields)]) { + NSDictionary *headers = [(NSHTTPURLResponse *)response allHeaderFields]; + return headers; + } + return nil; +} + +- (void)releaseCallbacks { + // Avoid releasing blocks in the sync section since objects dealloc'd by + // the blocks being released may call back into the fetcher or fetcher + // service. + dispatch_queue_t NS_VALID_UNTIL_END_OF_SCOPE holdCallbackQueue; + GTMSessionFetcherCompletionHandler NS_VALID_UNTIL_END_OF_SCOPE holdCompletionHandler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + holdCallbackQueue = _callbackQueue; + holdCompletionHandler = _completionHandler; + + _callbackQueue = nil; + _completionHandler = nil; // Setter overridden in upload. Setter assumed to be used externally. + } + + // Set local callback pointers to nil here rather than let them release at the end of the scope + // to make any problems due to the blocks being released be a bit more obvious in a stack trace. + holdCallbackQueue = nil; + holdCompletionHandler = nil; + + self.configurationBlock = nil; + self.didReceiveResponseBlock = nil; + self.challengeBlock = nil; + self.willRedirectBlock = nil; + self.sendProgressBlock = nil; + self.receivedProgressBlock = nil; + self.downloadProgressBlock = nil; + self.accumulateDataBlock = nil; + self.willCacheURLResponseBlock = nil; + self.retryBlock = nil; + self.testBlock = nil; + self.resumeDataBlock = nil; +} + +- (void)forgetSessionIdentifierForFetcher { + GTMSessionCheckSynchronized(self); + [self forgetSessionIdentifierForFetcherWithoutSyncCheck]; +} + +- (void)forgetSessionIdentifierForFetcherWithoutSyncCheck { + // This should be called inside a @synchronized block (except during dealloc.) + if (_sessionIdentifier) { + NSMapTable *sessionIdentifierToFetcherMap = [[self class] sessionIdentifierToFetcherMap]; + [sessionIdentifierToFetcherMap removeObjectForKey:_sessionIdentifier]; + _sessionIdentifier = nil; + _didCreateSessionIdentifier = NO; + } +} + +// External stop method +- (void)stopFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Prevent enqueued callbacks from executing. + _userStoppedFetching = YES; + } // @synchronized(self) + [self stopFetchReleasingCallbacks:YES]; +} + +// Cancel the fetch of the URL that's currently in progress. +// +// If shouldReleaseCallbacks is NO then the fetch will be retried so the callbacks +// need to still be retained. +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks { + [self removePersistedBackgroundSessionFromDefaults]; + + id service; + NSMutableURLRequest *request; + + // If the task or the retry timer is all that's retaining the fetcher, + // we want to be sure this instance survives stopping at least long enough for + // the stack to unwind. + __autoreleasing GTMSessionFetcher *holdSelf = self; + + BOOL hasCanceledTask = NO; + + [holdSelf destroyRetryTimer]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _hasStoppedFetching = YES; + + service = _service; + request = _request; + + if (_sessionTask) { + // In case cancelling the task or session calls this recursively, we want + // to ensure that we'll only release the task and delegate once, + // so first set _sessionTask to nil + // + // This may be called in a callback from the task, so use autorelease to avoid + // releasing the task in its own callback. + __autoreleasing NSURLSessionTask *oldTask = _sessionTask; + if (!_isUsingTestBlock) { + _response = _sessionTask.response; + } + _sessionTask = nil; + + if ([oldTask state] != NSURLSessionTaskStateCompleted) { + // For download tasks, when the fetch is stopped, we may provide resume data that can + // be used to create a new session. + BOOL mayResume = (_resumeDataBlock + && [oldTask respondsToSelector:@selector(cancelByProducingResumeData:)]); + if (!mayResume) { + [oldTask cancel]; + // A side effect of stopping the task is that URLSession:task:didCompleteWithError: + // will be invoked asynchronously on the delegate queue. + } else { + void (^resumeBlock)(NSData *) = _resumeDataBlock; + _resumeDataBlock = nil; + + // Save callbackQueue since releaseCallbacks clears it. + dispatch_queue_t callbackQueue = _callbackQueue; + dispatch_group_enter(_callbackGroup); + [(NSURLSessionDownloadTask *)oldTask cancelByProducingResumeData:^(NSData *resumeData) { + [self invokeOnCallbackQueue:callbackQueue + afterUserStopped:YES + block:^{ + resumeBlock(resumeData); + dispatch_group_leave(self->_callbackGroup); + }]; + }]; + } + hasCanceledTask = YES; + } + } + + // If the task was canceled, wait until the URLSession:task:didCompleteWithError: to call + // finishTasksAndInvalidate, since calling it immediately tends to crash, see radar 18471901. + if (_session) { + BOOL shouldInvalidate = _shouldInvalidateSession; +#if TARGET_OS_IPHONE + // Don't invalidate if we've got a systemCompletionHandler, since + // URLSessionDidFinishEventsForBackgroundURLSession: won't be called if invalidated. + shouldInvalidate = shouldInvalidate && !self.systemCompletionHandler; +#endif + if (shouldInvalidate) { + __autoreleasing NSURLSession *oldSession = _session; + _session = nil; + + if (!hasCanceledTask) { + [oldSession finishTasksAndInvalidate]; + } else { + _sessionNeedingInvalidation = oldSession; + } + } + } + } // @synchronized(self) + + // send the stopped notification + [self sendStopNotificationIfNeeded]; + + [_authorizer stopAuthorizationForRequest:request]; + + if (shouldReleaseCallbacks) { + [self releaseCallbacks]; + + self.authorizer = nil; + } + + [service fetcherDidStop:self]; + +#if GTM_BACKGROUND_TASK_FETCHING + [self endBackgroundTask]; +#endif +} + +- (void)setStopNotificationNeeded:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _isStopNotificationNeeded = flag; + } // @synchronized(self) +} + +- (void)sendStopNotificationIfNeeded { + BOOL sendNow = NO; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_isStopNotificationNeeded) { + _isStopNotificationNeeded = NO; + sendNow = YES; + } + } // @synchronized(self) + + if (sendNow) { + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherStoppedNotification + userInfo:nil + requireAsync:NO]; + } +} + +- (void)retryFetch { + [self stopFetchReleasingCallbacks:NO]; + + // A retry will need a configuration with a fresh session identifier. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_sessionIdentifier && _didCreateSessionIdentifier) { + [self forgetSessionIdentifierForFetcher]; + _configuration = nil; + } + + if (_canShareSession) { + // Force a grab of the current session from the fetcher service in case + // the service's old one has become invalid. + _session = nil; + } + } // @synchronized(self) + + [self beginFetchForRetry]; +} + +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + // Uncovered in upload fetcher testing, because the chunk fetcher is being waited on, and gets + // released by the upload code. The uploader just holds onto it with an ivar, and that gets + // nilled in the chunk fetcher callback. + // Used once in while loop just to avoid unused variable compiler warning. + __autoreleasing GTMSessionFetcher *holdSelf = self; + + NSDate *giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + BOOL shouldSpinRunLoop = ([NSThread isMainThread] && + (!self.callbackQueue + || self.callbackQueue == dispatch_get_main_queue())); + BOOL expired = NO; + + // Loop until the callbacks have been called and released, and until + // the connection is no longer pending, until there are no callback dispatches + // in flight, or until the timeout has expired. + int64_t delta = (int64_t)(100 * NSEC_PER_MSEC); // 100 ms + while (1) { + BOOL isTaskInProgress = (holdSelf->_sessionTask + && [_sessionTask state] != NSURLSessionTaskStateCompleted); + BOOL needsToCallCompletion = (_completionHandler != nil); + BOOL isCallbackInProgress = (_callbackGroup + && dispatch_group_wait(_callbackGroup, dispatch_time(DISPATCH_TIME_NOW, delta))); + + if (!isTaskInProgress && !needsToCallCompletion && !isCallbackInProgress) break; + + expired = ([giveUpDate timeIntervalSinceNow] < 0); + if (expired) { + GTMSESSION_LOG_DEBUG(@"GTMSessionFetcher waitForCompletionWithTimeout:%0.1f expired -- " + @"%@%@%@", timeoutInSeconds, + isTaskInProgress ? @"taskInProgress " : @"", + needsToCallCompletion ? @"needsToCallCompletion " : @"", + isCallbackInProgress ? @"isCallbackInProgress" : @""); + break; + } + + // Run the current run loop 1/1000 of a second to give the networking + // code a chance to work + const NSTimeInterval kSpinInterval = 0.001; + if (shouldSpinRunLoop) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:kSpinInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + [NSThread sleepForTimeInterval:kSpinInterval]; + } + } + return !expired; +} + ++ (void)setGlobalTestBlock:(GTMSessionFetcherTestBlock GTM_NULLABLE_TYPE)block { +#if GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSESSION_ASSERT_DEBUG(block == nil, @"test blocks disabled"); +#endif + gGlobalTestBlock = [block copy]; +} + +#if GTM_BACKGROUND_TASK_FETCHING + +static GTM_NULLABLE_TYPE id gSubstituteUIApp; + ++ (void)setSubstituteUIApplication:(nullable id)app { + gSubstituteUIApp = app; +} + ++ (nullable id)substituteUIApplication { + return gSubstituteUIApp; +} + ++ (nullable id)fetcherUIApplication { + id app = gSubstituteUIApp; + if (app) return app; + + // iOS App extensions should not call [UIApplication sharedApplication], even + // if UIApplication responds to it. + + static Class applicationClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + BOOL isAppExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + if (!isAppExtension) { + Class cls = NSClassFromString(@"UIApplication"); + if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) { + applicationClass = cls; + } + } + }); + + if (applicationClass) { + app = (id)[applicationClass sharedApplication]; + } + return app; +} +#endif // GTM_BACKGROUND_TASK_FETCHING + +#pragma mark NSURLSession Delegate Methods + +// NSURLSession documentation indicates that redirectRequest can be passed to the handler +// but empirically redirectRequest lacks the HTTP body, so passing it will break POSTs. +// Instead, we construct a new request, a copy of the original, with overrides from the +// redirect. + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)redirectResponse + newRequest:(NSURLRequest *)redirectRequest + completionHandler:(void (^)(NSURLRequest * GTM_NULLABLE_TYPE))handler { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ willPerformHTTPRedirection:%@ newRequest:%@", + [self class], self, session, task, redirectResponse, redirectRequest); + + if ([self userStoppedFetching]) { + handler(nil); + return; + } + if (redirectRequest && redirectResponse) { + // Copy the original request, including the body. + NSURLRequest *originalRequest = self.request; + NSMutableURLRequest *newRequest = [originalRequest mutableCopy]; + + // The new requests's URL overrides the original's URL. + [newRequest setURL:[GTMSessionFetcher redirectURLWithOriginalRequestURL:originalRequest.URL + redirectRequestURL:redirectRequest.URL]]; + + // Any headers in the redirect override headers in the original. + NSDictionary *redirectHeaders = redirectRequest.allHTTPHeaderFields; + for (NSString *key in redirectHeaders) { + NSString *value = [redirectHeaders objectForKey:key]; + [newRequest setValue:value forHTTPHeaderField:key]; + } + + redirectRequest = newRequest; + + // Log the response we just received + [self setResponse:redirectResponse]; + [self logNowWithError:nil]; + + GTMSessionFetcherWillRedirectBlock willRedirectBlock = self.willRedirectBlock; + if (willRedirectBlock) { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + willRedirectBlock(redirectResponse, redirectRequest, ^(NSURLRequest *clientRequest) { + + // Update the request for future logging. + [self updateMutableRequest:[clientRequest mutableCopy]]; + + handler(clientRequest); + }); + }]; + } // @synchronized(self) + return; + } + // Continues here if the client did not provide a redirect block. + + // Update the request for future logging. + [self updateMutableRequest:[redirectRequest mutableCopy]]; + } + handler(redirectRequest); +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))handler { + [self setSessionTask:dataTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didReceiveResponse:%@", + [self class], self, session, dataTask, response); + void (^accumulateAndFinish)(NSURLSessionResponseDisposition) = + ^(NSURLSessionResponseDisposition dispositionValue) { + // This method is called when the server has determined that it + // has enough information to create the NSURLResponse + // it can be called multiple times, for example in the case of a + // redirect, so each time we reset the data. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL hadPreviousData = self->_downloadedLength > 0; + + [self->_downloadedData setLength:0]; + self->_downloadedLength = 0; + + if (hadPreviousData && (dispositionValue != NSURLSessionResponseCancel)) { + // Tell the accumulate block to discard prior data. + GTMSessionFetcherAccumulateDataBlock accumulateBlock = self->_accumulateDataBlock; + if (accumulateBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + accumulateBlock(nil); + }]; + } + } + } // @synchronized(self) + handler(dispositionValue); + }; + + GTMSessionFetcherDidReceiveResponseBlock receivedResponseBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + receivedResponseBlock = _didReceiveResponseBlock; + if (receivedResponseBlock) { + // We will ultimately need to call back to NSURLSession's handler with the disposition value + // for this delegate method even if the user has stopped the fetcher. + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + receivedResponseBlock(response, ^(NSURLSessionResponseDisposition desiredDisposition) { + accumulateAndFinish(desiredDisposition); + }); + }]; + } + } // @synchronized(self) + + if (receivedResponseBlock == nil) { + accumulateAndFinish(NSURLSessionResponseAllow); + } +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didBecomeDownloadTask:%@", + [self class], self, session, dataTask, downloadTask); + [self setSessionTask:downloadTask]; +} + + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential))handler { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didReceiveChallenge:%@", + [self class], self, session, task, challenge); + + GTMSessionFetcherChallengeBlock challengeBlock = self.challengeBlock; + if (challengeBlock) { + // The fetcher user has provided custom challenge handling. + // + // We will ultimately need to call back to NSURLSession's handler with the disposition value + // for this delegate method even if the user has stopped the fetcher. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + challengeBlock(self, challenge, handler); + }]; + } + } else { + // No challenge block was provided by the client. + [self respondToChallenge:challenge + completionHandler:handler]; + } +} + +- (void)respondToChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential * GTM_NULLABLE_TYPE credential))handler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSInteger previousFailureCount = [challenge previousFailureCount]; + if (previousFailureCount <= 2) { + NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; + NSString *authenticationMethod = [protectionSpace authenticationMethod]; + if ([authenticationMethod isEqual:NSURLAuthenticationMethodServerTrust]) { + // SSL. + // + // Background sessions seem to require an explicit check of the server trust object + // rather than default handling. + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + // No server trust information is available. + handler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } else { + // Server trust information is available. + void (^callback)(SecTrustRef, BOOL) = ^(SecTrustRef trustRef, BOOL allow){ + if (allow) { + NSURLCredential *trustCredential = [NSURLCredential credentialForTrust:trustRef]; + handler(NSURLSessionAuthChallengeUseCredential, trustCredential); + } else { + GTMSESSION_LOG_DEBUG(@"Cancelling authentication challenge for %@", self->_request.URL); + handler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + if (_allowInvalidServerCertificates) { + callback(serverTrust, YES); + } else { + [[self class] evaluateServerTrust:serverTrust + forRequest:_request + completionHandler:callback]; + } + } + return; + } + + NSURLCredential *credential = _credential; + + if ([[challenge protectionSpace] isProxy] && _proxyCredential != nil) { + credential = _proxyCredential; + } + + if (credential) { + handler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + // The credential is still nil; tell the OS to use the default handling. This is needed + // for things that can come out of the keychain (proxies, client certificates, etc.). + // + // Note: Looking up a credential with NSURLCredentialStorage's + // defaultCredentialForProtectionSpace: is *not* the same invoking the handler with + // NSURLSessionAuthChallengePerformDefaultHandling. In the case of + // NSURLAuthenticationMethodClientCertificate, you can get nil back from + // NSURLCredentialStorage, while using this code path instead works. + handler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + } + + } else { + // We've failed auth 3 times. The completion handler will be called with code + // NSURLErrorCancelled. + handler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + } // @synchronized(self) +} + +// Return redirect URL based on the original request URL and redirect request URL. +// +// Method disallows any scheme changes between the original request URL and redirect request URL +// aside from "http" to "https". If a change in scheme is detected the redirect URL inherits the +// scheme from the original request URL. ++ (GTM_NULLABLE NSURL *)redirectURLWithOriginalRequestURL:(GTM_NULLABLE NSURL *)originalRequestURL + redirectRequestURL:(GTM_NULLABLE NSURL *)redirectRequestURL { + // In the case of an NSURLSession redirect, neither URL should ever be nil; as a sanity check + // if either is nil return the other URL. + if (!redirectRequestURL) return originalRequestURL; + if (!originalRequestURL) return redirectRequestURL; + + NSString *originalScheme = originalRequestURL.scheme; + NSString *redirectScheme = redirectRequestURL.scheme; + BOOL insecureToSecureRedirect = + (originalScheme != nil && [originalScheme caseInsensitiveCompare:@"http"] == NSOrderedSame && + redirectScheme != nil && [redirectScheme caseInsensitiveCompare:@"https"] == NSOrderedSame); + + // This can't really be nil for the inputs, but to keep the analyzer happy + // for the -caseInsensitiveCompare: call below, give it a value if it were. + if (!originalScheme) originalScheme = @"https"; + + // Check for changes to the scheme and disallow any changes except for http to https. + if (!insecureToSecureRedirect && + (redirectScheme.length != originalScheme.length || + [redirectScheme caseInsensitiveCompare:originalScheme] != NSOrderedSame)) { + NSURLComponents *components = + [NSURLComponents componentsWithURL:(NSURL * _Nonnull)redirectRequestURL + resolvingAgainstBaseURL:NO]; + components.scheme = originalScheme; + return components.URL; + } + + return redirectRequestURL; +} + +// Validate the certificate chain. +// +// This may become a public method if it appears to be useful to users. ++ (void)evaluateServerTrust:(SecTrustRef)serverTrust + forRequest:(NSURLRequest *)request + completionHandler:(void (^)(SecTrustRef trustRef, BOOL allow))handler { + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + // + // We must also avoid multiple uses of the trust object, per docs: + // "It is not safe to call this function concurrently with any other function that uses + // the same trust management object, or to re-enter this function for the same trust + // management object." + // + // SecTrustEvaluateAsync both does sync execution of Evaluate and calls back on the + // queue passed to it, according to at sources in + // http://www.opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55050.9/lib/SecTrust.cpp + // It would require a global serial queue to ensure the evaluate happens only on a + // single thread at a time, so we'll stick with using SecTrustEvaluate on a background + // thread. + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + dispatch_async(evaluateBackgroundQueue, ^{ + // It looks like the implementation of SecTrustEvaluate() on Mac grabs a global lock, + // so it may be redundant for us to also lock, but it's easy to synchronize here + // anyway. + BOOL shouldAllow; +#if GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR + CFErrorRef errorRef = NULL; + @synchronized ([GTMSessionFetcher class]) { + GTMSessionMonitorSynchronized([GTMSessionFetcher class]); + + // SecTrustEvaluateWithError handles both the "proceed" and "unspecified" cases, + // so it is not necessary to check the trust result the evaluation returns true. + shouldAllow = SecTrustEvaluateWithError(serverTrust, &errorRef); + } + + if (errorRef) { + GTMSESSION_LOG_DEBUG(@"Error %d evaluating trust for %@", + (int)CFErrorGetCode(errorRef), request); + CFRelease(errorRef); + } +#else + SecTrustResultType trustEval = kSecTrustResultInvalid; + OSStatus trustError; + @synchronized([GTMSessionFetcher class]) { + GTMSessionMonitorSynchronized([GTMSessionFetcher class]); + + trustError = SecTrustEvaluate(serverTrust, &trustEval); + } + if (trustError != errSecSuccess) { + GTMSESSION_LOG_DEBUG(@"Error %d evaluating trust for %@", + (int)trustError, request); + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + if (trustEval == kSecTrustResultUnspecified + || trustEval == kSecTrustResultProceed) { + shouldAllow = YES; + } else { + shouldAllow = NO; + GTMSESSION_LOG_DEBUG(@"Challenge SecTrustResultType %u for %@, properties: %@", + trustEval, request.URL.host, + CFBridgingRelease(SecTrustCopyProperties(serverTrust))); + } + } +#endif // GTM_SDK_REQUIRES_SECTRUSTEVALUATEWITHERROR + handler(serverTrust, shouldAllow); + + CFRelease(serverTrust); + }); +} + +- (void)invokeOnCallbackQueueUnlessStopped:(void (^)(void))block { + [self invokeOnCallbackQueueAfterUserStopped:NO + block:block]; +} + +- (void)invokeOnCallbackQueueAfterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + GTMSessionCheckSynchronized(self); + + [self invokeOnCallbackUnsynchronizedQueueAfterUserStopped:afterStopped + block:block]; +} + +- (void)invokeOnCallbackUnsynchronizedQueueAfterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + // testBlock simulation code may not be synchronizing when this is invoked. + [self invokeOnCallbackQueue:_callbackQueue + afterUserStopped:afterStopped + block:block]; +} + +- (void)invokeOnCallbackQueue:(dispatch_queue_t)callbackQueue + afterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block { + if (callbackQueue) { + dispatch_group_async(_callbackGroup, callbackQueue, ^{ + if (!afterStopped) { + NSDate *serviceStoppedAllDate = [self->_service stoppedAllFetchersDate]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Avoid a race between stopFetching and the callback. + if (self->_userStoppedFetching) { + return; + } + + // Also avoid calling back if the service has stopped all fetchers + // since this one was created. The fetcher may have stopped before + // stopAllFetchers was invoked, so _userStoppedFetching wasn't set, + // but the app still won't expect the callback to fire after + // the service's stopAllFetchers was invoked. + if (serviceStoppedAllDate + && [self->_initialBeginFetchDate compare:serviceStoppedAllDate] != NSOrderedDescending) { + // stopAllFetchers was called after this fetcher began. + return; + } + } // @synchronized(self) + } + block(); + }); + } +} + +- (void)invokeFetchCallbacksOnCallbackQueueWithData:(GTM_NULLABLE NSData *)data + error:(GTM_NULLABLE NSError *)error { + // Callbacks will be released in the method stopFetchReleasingCallbacks: + GTMSessionFetcherCompletionHandler handler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + handler = _completionHandler; + + if (handler) { + [self invokeOnCallbackQueueUnlessStopped:^{ + handler(data, error); + + // Post a notification, primarily to allow code to collect responses for + // testing. + // + // The observing code is not likely on the fetcher's callback + // queue, so this posts explicitly to the main queue. + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (data) { + userInfo[kGTMSessionFetcherCompletionDataKey] = data; + } + if (error) { + userInfo[kGTMSessionFetcherCompletionErrorKey] = error; + } + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherCompletionInvokedNotification + userInfo:userInfo + requireAsync:NO]; + }]; + } + } // @synchronized(self) +} + +- (void)postNotificationOnMainThreadWithName:(NSString *)noteName + userInfo:(GTM_NULLABLE NSDictionary *)userInfo + requireAsync:(BOOL)requireAsync { + dispatch_block_t postBlock = ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:noteName + object:self + userInfo:userInfo]; + }; + + if ([NSThread isMainThread] && !requireAsync) { + // Post synchronously for compatibility with older code using the fetcher. + + // Avoid calling out to other code from inside a sync block to avoid risk + // of a deadlock or of recursive sync. + GTMSessionCheckNotSynchronized(self); + + postBlock(); + } else { + dispatch_async(dispatch_get_main_queue(), postBlock); + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)uploadTask + needNewBodyStream:(void (^)(NSInputStream * GTM_NULLABLE_TYPE bodyStream))completionHandler { + [self setSessionTask:uploadTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ needNewBodyStream:", + [self class], self, session, uploadTask); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSessionFetcherBodyStreamProvider provider = _bodyStreamProvider; +#if !STRIP_GTM_FETCH_LOGGING + if ([self respondsToSelector:@selector(loggedStreamProviderForStreamProvider:)]) { + provider = [self performSelector:@selector(loggedStreamProviderForStreamProvider:) + withObject:provider]; + } +#endif + if (provider) { + [self invokeOnCallbackQueueUnlessStopped:^{ + provider(completionHandler); + }]; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"NSURLSession expects a stream provider"); + + completionHandler(nil); + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didSendBodyData:%lld" + @" totalBytesSent:%lld totalBytesExpectedToSend:%lld", + [self class], self, session, task, bytesSent, totalBytesSent, + totalBytesExpectedToSend); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (!_sendProgressBlock) { + return; + } + // We won't hold on to send progress block; it's ok to not send it if the upload finishes. + [self invokeOnCallbackQueueUnlessStopped:^{ + GTMSessionFetcherSendProgressBlock progressBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + progressBlock = self->_sendProgressBlock; + } + if (progressBlock) { + progressBlock(bytesSent, totalBytesSent, totalBytesExpectedToSend); + } + }]; + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + [self setSessionTask:dataTask]; + NSUInteger bufferLength = data.length; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ didReceiveData:%p (%llu bytes)", + [self class], self, session, dataTask, data, + (unsigned long long)bufferLength); + if (bufferLength == 0) { + // Observed on completing an out-of-process upload. + return; + } + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSessionFetcherAccumulateDataBlock accumulateBlock = _accumulateDataBlock; + if (accumulateBlock) { + // Let the client accumulate the data. + _downloadedLength += bufferLength; + [self invokeOnCallbackQueueUnlessStopped:^{ + accumulateBlock(data); + }]; + } else if (!_userStoppedFetching) { + // Append to the mutable data buffer unless the fetch has been cancelled. + + // Resumed upload tasks may not yet have a data buffer. + if (_downloadedData == nil) { + // Using NSClassFromString for iOS 6 compatibility. + GTMSESSION_ASSERT_DEBUG( + ![dataTask isKindOfClass:NSClassFromString(@"NSURLSessionDownloadTask")], + @"Resumed download tasks should not receive data bytes"); + _downloadedData = [[NSMutableData alloc] init]; + } + + [_downloadedData appendData:data]; + _downloadedLength = (int64_t)_downloadedData.length; + + // We won't hold on to receivedProgressBlock here; it's ok to not send + // it if the transfer finishes. + if (_receivedProgressBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + GTMSessionFetcherReceivedProgressBlock progressBlock; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + progressBlock = self->_receivedProgressBlock; + } + if (progressBlock) { + progressBlock((int64_t)bufferLength, self->_downloadedLength); + } + }]; + } + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ dataTask:%@ willCacheResponse:%@ %@", + [self class], self, session, dataTask, + proposedResponse, proposedResponse.response); + GTMSessionFetcherWillCacheURLResponseBlock callback; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + callback = _willCacheURLResponseBlock; + + if (callback) { + [self invokeOnCallbackQueueAfterUserStopped:YES + block:^{ + callback(proposedResponse, completionHandler); + }]; + } + } // @synchronized(self) + if (!callback) { + completionHandler(proposedResponse); + } +} + + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didWriteData:(int64_t)bytesWritten + totalBytesWritten:(int64_t)totalBytesWritten +totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didWriteData:%lld" + @" bytesWritten:%lld totalBytesExpectedToWrite:%lld", + [self class], self, session, downloadTask, bytesWritten, + totalBytesWritten, totalBytesExpectedToWrite); + [self setSessionTask:downloadTask]; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if ((totalBytesExpectedToWrite != NSURLSessionTransferSizeUnknown) && + (totalBytesExpectedToWrite < totalBytesWritten)) { + // Have observed cases were bytesWritten == totalBytesExpectedToWrite, + // but totalBytesWritten > totalBytesExpectedToWrite, so setting to unkown in these cases. + totalBytesExpectedToWrite = NSURLSessionTransferSizeUnknown; + } + + GTMSessionFetcherDownloadProgressBlock progressBlock; + progressBlock = self->_downloadProgressBlock; + if (progressBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + progressBlock(bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); + }]; + } + } // @synchronized(self) +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didResumeAtOffset:(int64_t)fileOffset +expectedTotalBytes:(int64_t)expectedTotalBytes { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didResumeAtOffset:%lld" + @" expectedTotalBytes:%lld", + [self class], self, session, downloadTask, fileOffset, + expectedTotalBytes); + [self setSessionTask:downloadTask]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask +didFinishDownloadingToURL:(NSURL *)downloadLocationURL { + // Download may have relaunched app, so update _sessionTask. + [self setSessionTask:downloadTask]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ downloadTask:%@ didFinishDownloadingToURL:%@", + [self class], self, session, downloadTask, downloadLocationURL); + NSNumber *fileSizeNum; + [downloadLocationURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:NULL]; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURL *destinationURL = _destinationFileURL; + + _downloadedLength = fileSizeNum.longLongValue; + + // Overwrite any previous file at the destination URL. + NSFileManager *fileMgr = [NSFileManager defaultManager]; + NSError *removeError; + if (![fileMgr removeItemAtURL:destinationURL error:&removeError] + && removeError.code != NSFileNoSuchFileError) { + GTMSESSION_LOG_DEBUG(@"Could not remove previous file at %@ due to %@", + downloadLocationURL.path, removeError); + } + + NSInteger statusCode = [self statusCodeUnsynchronized]; + if (statusCode < 200 || statusCode > 399) { + // In OS X 10.11, the response body is written to a file even on a server + // status error. For convenience of the fetcher client, we'll skip saving the + // downloaded body to the destination URL so that clients do not need to know + // to delete the file following fetch errors. + GTMSESSION_LOG_DEBUG(@"Abandoning download due to status %ld, file %@", + (long)statusCode, downloadLocationURL.path); + + // On error code, add the contents of the temporary file to _downloadTaskErrorData + // This way fetcher clients have access to error details possibly passed by the server. + if (_downloadedLength > 0 && _downloadedLength <= kMaximumDownloadErrorDataLength) { + _downloadTaskErrorData = [NSData dataWithContentsOfURL:downloadLocationURL]; + } else if (_downloadedLength > kMaximumDownloadErrorDataLength) { + GTMSESSION_LOG_DEBUG(@"Download error data for file %@ not passed to userInfo due to size " + @"%lld", downloadLocationURL.path, _downloadedLength); + } + } else { + NSError *moveError; + NSURL *destinationFolderURL = [destinationURL URLByDeletingLastPathComponent]; + BOOL didMoveDownload = NO; + if ([fileMgr createDirectoryAtURL:destinationFolderURL + withIntermediateDirectories:YES + attributes:nil + error:&moveError]) { + didMoveDownload = [fileMgr moveItemAtURL:downloadLocationURL + toURL:destinationURL + error:&moveError]; + } + if (!didMoveDownload) { + _downloadFinishedError = moveError; + } + GTM_LOG_BACKGROUND_SESSION(@"%@ %p Moved download from \"%@\" to \"%@\" %@", + [self class], self, + downloadLocationURL.path, destinationURL.path, + error ? error : @""); + } + } // @synchronized(self) +} + +/* Sent as the last message related to a specific task. Error may be + * nil, which implies that no error occurred and this task is complete. + */ +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(NSError *)error { + [self setSessionTask:task]; + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ task:%@ didCompleteWithError:%@", + [self class], self, session, task, error); + + NSInteger status = self.statusCode; + BOOL forceAssumeRetry = NO; + BOOL succeeded = NO; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + // The task is never resumed when a testBlock is used. When the session is destroyed, + // we should ignore the callback, since the testBlock support code itself invokes + // shouldRetryNowForStatus: and finishWithError:shouldRetry: + if (_isUsingTestBlock) return; +#endif + + if (error == nil) { + error = _downloadFinishedError; + } + succeeded = (error == nil && status >= 0 && status < 300); + if (succeeded) { + // Succeeded. + _bodyLength = task.countOfBytesSent; + } + } // @synchronized(self) + + if (succeeded) { + [self finishWithError:nil shouldRetry:NO]; + return; + } + // For background redirects, no delegate method is called, so we cannot restore a stripped + // Authorization header, so if a 403 ("Forbidden") was generated due to a missing OAuth 2 header, + // set the current request's URL to the redirected URL, so we in effect restore the Authorization + // header. + if ((status == 403) && self.usingBackgroundSession) { + NSURL *redirectURL = self.response.URL; + NSURLRequest *request = self.request; + if (![request.URL isEqual:redirectURL]) { + NSString *authorizationHeader = [request.allHTTPHeaderFields objectForKey:@"Authorization"]; + if (authorizationHeader != nil) { + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + mutableRequest.URL = redirectURL; + [self updateMutableRequest:mutableRequest]; + // Avoid assuming the session is still valid. + self.session = nil; + forceAssumeRetry = YES; + } + } + } + + // If invalidating the session was deferred in stopFetchReleasingCallbacks: then do it now. + NSURLSession *oldSession = self.sessionNeedingInvalidation; + if (oldSession) { + [self setSessionNeedingInvalidation:NULL]; + [oldSession finishTasksAndInvalidate]; + } + + // Failed. + [self shouldRetryNowForStatus:status + error:error + forceAssumeRetry:forceAssumeRetry + response:^(BOOL shouldRetry) { + [self finishWithError:error shouldRetry:shouldRetry]; + }]; +} + +#if TARGET_OS_IPHONE +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSessionDidFinishEventsForBackgroundURLSession:%@", + [self class], self, session); + [self removePersistedBackgroundSessionFromDefaults]; + + GTMSessionFetcherSystemCompletionHandler handler; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + handler = self.systemCompletionHandler; + self.systemCompletionHandler = nil; + } // @synchronized(self) + if (handler) { + GTM_LOG_BACKGROUND_SESSION(@"%@ %p Calling system completionHandler", [self class], self); + handler(); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLSession *oldSession = _session; + _session = nil; + if (_shouldInvalidateSession) { + [oldSession finishTasksAndInvalidate]; + } + } // @synchronized(self) + } +} +#endif + +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(GTM_NULLABLE NSError *)error { + // This may happen repeatedly for retries. On authentication callbacks, the retry + // may begin before the prior session sends the didBecomeInvalid delegate message. + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ didBecomeInvalidWithError:%@", + [self class], self, session, error); + if (session == (NSURLSession *)self.session) { + GTM_LOG_SESSION_DELEGATE(@" Unexpected retained invalid session: %@", session); + self.session = nil; + } +} + +- (void)finishWithError:(GTM_NULLABLE NSError *)error shouldRetry:(BOOL)shouldRetry { + [self removePersistedBackgroundSessionFromDefaults]; + + BOOL shouldStopFetching = YES; + NSData *downloadedData = nil; +#if !STRIP_GTM_FETCH_LOGGING + BOOL shouldDeferLogging = NO; +#endif + BOOL shouldBeginRetryTimer = NO; + NSInteger status = [self statusCode]; + NSURL *destinationURL = self.destinationFileURL; + + BOOL fetchSucceeded = (error == nil && status >= 0 && status < 300); + +#if !STRIP_GTM_FETCH_LOGGING + if (!fetchSucceeded) { + if (!shouldDeferLogging && !self.hasLoggedError) { + [self logNowWithError:error]; + self.hasLoggedError = YES; + } + } +#endif // !STRIP_GTM_FETCH_LOGGING + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + +#if !STRIP_GTM_FETCH_LOGGING + shouldDeferLogging = _deferResponseBodyLogging; +#endif + if (fetchSucceeded) { + // Success + if ((_downloadedData.length > 0) && (destinationURL != nil)) { + // Overwrite any previous file at the destination URL. + NSFileManager *fileMgr = [NSFileManager defaultManager]; + [fileMgr removeItemAtURL:destinationURL + error:NULL]; + NSURL *destinationFolderURL = [destinationURL URLByDeletingLastPathComponent]; + BOOL didMoveDownload = NO; + if ([fileMgr createDirectoryAtURL:destinationFolderURL + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + didMoveDownload = [_downloadedData writeToURL:destinationURL + options:NSDataWritingAtomic + error:&error]; + } + if (didMoveDownload) { + _downloadedData = nil; + } else { + _downloadFinishedError = error; + } + } + downloadedData = _downloadedData; + } else { + // Unsuccessful with error or status over 300. Retry or notify the delegate of failure + if (shouldRetry) { + // Retrying. + shouldBeginRetryTimer = YES; + shouldStopFetching = NO; + } else { + if (error == nil) { + // Create an error. + NSDictionary *userInfo = GTMErrorUserInfoForData( + _downloadedData.length > 0 ? _downloadedData : _downloadTaskErrorData, + [self responseHeadersUnsynchronized]); + + error = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:status + userInfo:userInfo]; + } else { + // If the error had resume data, and the client supplied a resume block, pass the + // data to the client. + void (^resumeBlock)(NSData *) = _resumeDataBlock; + _resumeDataBlock = nil; + if (resumeBlock) { + NSData *resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]; + if (resumeData) { + [self invokeOnCallbackQueueAfterUserStopped:YES block:^{ + resumeBlock(resumeData); + }]; + } + } + } + if (_downloadedData.length > 0) { + downloadedData = _downloadedData; + } + // If the error occurred after retries, report the number and duration of the + // retries. This provides a clue to a developer looking at the error description + // that the fetcher did retry before failing with this error. + if (_retryCount > 0) { + NSMutableDictionary *userInfoWithRetries = + [NSMutableDictionary dictionaryWithDictionary:(NSDictionary *)error.userInfo]; + NSTimeInterval timeSinceInitialRequest = -[_initialRequestDate timeIntervalSinceNow]; + [userInfoWithRetries setObject:@(timeSinceInitialRequest) + forKey:kGTMSessionFetcherElapsedIntervalWithRetriesKey]; + [userInfoWithRetries setObject:@(_retryCount) + forKey:kGTMSessionFetcherNumberOfRetriesDoneKey]; + error = [NSError errorWithDomain:(NSString *)error.domain + code:error.code + userInfo:userInfoWithRetries]; + } + } + } + } // @synchronized(self) + + if (shouldBeginRetryTimer) { + [self beginRetryTimer]; + } + + // We want to send the stop notification before calling the delegate's + // callback selector, since the callback selector may release all of + // the fetcher properties that the client is using to track the fetches. + // + // We'll also stop now so that, to any observers watching the notifications, + // it doesn't look like our wait for a retry (which may be long, + // 30 seconds or more) is part of the network activity. + [self sendStopNotificationIfNeeded]; + + if (shouldStopFetching) { + [self invokeFetchCallbacksOnCallbackQueueWithData:downloadedData + error:error]; + // The upload subclass doesn't want to release callbacks until upload chunks have completed. + BOOL shouldRelease = [self shouldReleaseCallbacksUponCompletion]; + [self stopFetchReleasingCallbacks:shouldRelease]; + } + +#if !STRIP_GTM_FETCH_LOGGING + // _hasLoggedError is only set by this method + if (!shouldDeferLogging && !_hasLoggedError) { + [self logNowWithError:error]; + } +#endif +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // A subclass can override this to keep callbacks around after the + // connection has finished successfully + return YES; +} + +- (void)logNowWithError:(GTM_NULLABLE NSError *)error { + GTMSessionCheckNotSynchronized(self); + + // If the logging category is available, then log the current request, + // response, data, and error + if ([self respondsToSelector:@selector(logFetchWithError:)]) { + [self performSelector:@selector(logFetchWithError:) withObject:error]; + } +} + +#pragma mark Retries + +- (BOOL)isRetryError:(NSError *)error { + struct RetryRecord { + __unsafe_unretained NSString *const domain; + NSInteger code; + }; + + struct RetryRecord retries[] = { + { kGTMSessionFetcherStatusDomain, 408 }, // request timeout + { kGTMSessionFetcherStatusDomain, 502 }, // failure gatewaying to another server + { kGTMSessionFetcherStatusDomain, 503 }, // service unavailable + { kGTMSessionFetcherStatusDomain, 504 }, // request timeout + { NSURLErrorDomain, NSURLErrorTimedOut }, + { NSURLErrorDomain, NSURLErrorNetworkConnectionLost }, + { nil, 0 } + }; + + // NSError's isEqual always returns false for equal but distinct instances + // of NSError, so we have to compare the domain and code values explicitly + NSString *domain = error.domain; + NSInteger code = error.code; + for (int idx = 0; retries[idx].domain != nil; idx++) { + if (code == retries[idx].code && [domain isEqual:retries[idx].domain]) { + return YES; + } + } + return NO; +} + +// shouldRetryNowForStatus:error: responds with YES if the user has enabled retries +// and the status or error is one that is suitable for retrying. "Suitable" +// means either the isRetryError:'s list contains the status or error, or the +// user's retry block is present and returns YES when called, or the +// authorizer may be able to fix. +- (void)shouldRetryNowForStatus:(NSInteger)status + error:(NSError *)error + forceAssumeRetry:(BOOL)forceAssumeRetry + response:(GTMSessionFetcherRetryResponse)response { + // Determine if a refreshed authorizer may avoid an authorization error + BOOL willRetry = NO; + + // We assume _authorizer is immutable after beginFetch, and _hasAttemptedAuthRefresh is modified + // only in this method, and this method is invoked on the serial delegate queue. + // + // We want to avoid calling the authorizer from inside a sync block. + BOOL isFirstAuthError = (_authorizer != nil + && !_hasAttemptedAuthRefresh + && status == GTMSessionFetcherStatusUnauthorized); // 401 + + BOOL hasPrimed = NO; + if (isFirstAuthError) { + if ([_authorizer respondsToSelector:@selector(primeForRefresh)]) { + hasPrimed = [_authorizer primeForRefresh]; + } + } + + BOOL shouldRetryForAuthRefresh = NO; + if (hasPrimed) { + shouldRetryForAuthRefresh = YES; + _hasAttemptedAuthRefresh = YES; + [self updateRequestValue:nil forHTTPHeaderField:@"Authorization"]; + } + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL shouldDoRetry = [self isRetryEnabledUnsynchronized]; + if (shouldDoRetry && ![self hasRetryAfterInterval]) { + + // Determine if we're doing exponential backoff retries + shouldDoRetry = [self nextRetryIntervalUnsynchronized] < _maxRetryInterval; + + if (shouldDoRetry) { + // If an explicit max retry interval was set, we expect repeated backoffs to take + // up to roughly twice that for repeated fast failures. If the initial attempt is + // already more than 3 times the max retry interval, then failures have taken a long time + // (such as from network timeouts) so don't retry again to avoid the app becoming + // unexpectedly unresponsive. + if (_maxRetryInterval > 0) { + NSTimeInterval maxAllowedIntervalBeforeRetry = _maxRetryInterval * 3; + NSTimeInterval timeSinceInitialRequest = -[_initialRequestDate timeIntervalSinceNow]; + if (timeSinceInitialRequest > maxAllowedIntervalBeforeRetry) { + shouldDoRetry = NO; + } + } + } + } + BOOL canRetry = shouldRetryForAuthRefresh || forceAssumeRetry || shouldDoRetry; + if (canRetry) { + NSDictionary *userInfo = + GTMErrorUserInfoForData(_downloadedData, [self responseHeadersUnsynchronized]); + NSError *statusError = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:status + userInfo:userInfo]; + if (error == nil) { + error = statusError; + } + willRetry = shouldRetryForAuthRefresh || + forceAssumeRetry || + [self isRetryError:error] || + ((error != statusError) && [self isRetryError:statusError]); + + // If the user has installed a retry callback, consult that. + GTMSessionFetcherRetryBlock retryBlock = _retryBlock; + if (retryBlock) { + [self invokeOnCallbackQueueUnlessStopped:^{ + retryBlock(willRetry, error, response); + }]; + return; + } + } + } // @synchronized(self) + response(willRetry); +} + +- (BOOL)hasRetryAfterInterval { + GTMSessionCheckSynchronized(self); + + NSDictionary *responseHeaders = [self responseHeadersUnsynchronized]; + NSString *retryAfterValue = [responseHeaders valueForKey:@"Retry-After"]; + return (retryAfterValue != nil); +} + +- (NSTimeInterval)retryAfterInterval { + GTMSessionCheckSynchronized(self); + + NSDictionary *responseHeaders = [self responseHeadersUnsynchronized]; + NSString *retryAfterValue = [responseHeaders valueForKey:@"Retry-After"]; + if (retryAfterValue == nil) { + return 0; + } + // Retry-After formatted as HTTP-date | delta-seconds + // Reference: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html + NSDateFormatter *rfc1123DateFormatter = [[NSDateFormatter alloc] init]; + rfc1123DateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + rfc1123DateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"]; + rfc1123DateFormatter.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss z"; + NSDate *retryAfterDate = [rfc1123DateFormatter dateFromString:retryAfterValue]; + NSTimeInterval retryAfterInterval = (retryAfterDate != nil) ? + retryAfterDate.timeIntervalSinceNow : retryAfterValue.intValue; + retryAfterInterval = MAX(0, retryAfterInterval); + return retryAfterInterval; +} + +- (void)beginRetryTimer { + if (![NSThread isMainThread]) { + // Defer creating and starting the timer until we're on the main thread to ensure it has + // a run loop. + dispatch_group_async(_callbackGroup, dispatch_get_main_queue(), ^{ + [self beginRetryTimer]; + }); + return; + } + + [self destroyRetryTimer]; + +#if GTM_BACKGROUND_TASK_FETCHING + // Don't keep a background task active while awaiting retry, which can lead to the + // app exceeding the allotted time for keeping the background task open, causing the + // system to terminate the app. When the retry starts, a new background task will + // be created. + [self endBackgroundTask]; +#endif // GTM_BACKGROUND_TASK_FETCHING + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSTimeInterval nextInterval = [self nextRetryIntervalUnsynchronized]; + NSTimeInterval maxInterval = _maxRetryInterval; + NSTimeInterval newInterval = MIN(nextInterval, (maxInterval > 0 ? maxInterval : DBL_MAX)); + NSTimeInterval newIntervalTolerance = (newInterval / 10) > 1.0 ?: 1.0; + + _lastRetryInterval = newInterval; + + _retryTimer = [NSTimer timerWithTimeInterval:newInterval + target:self + selector:@selector(retryTimerFired:) + userInfo:nil + repeats:NO]; + _retryTimer.tolerance = newIntervalTolerance; + [[NSRunLoop mainRunLoop] addTimer:_retryTimer + forMode:NSDefaultRunLoopMode]; + } // @synchronized(self) + + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherRetryDelayStartedNotification + userInfo:nil + requireAsync:NO]; +} + +- (void)retryTimerFired:(NSTimer *)timer { + [self destroyRetryTimer]; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _retryCount++; + } // @synchronized(self) + + NSOperationQueue *queue = self.sessionDelegateQueue; + [queue addOperationWithBlock:^{ + [self retryFetch]; + }]; +} + +- (void)destroyRetryTimer { + BOOL shouldNotify = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_retryTimer) { + [_retryTimer invalidate]; + _retryTimer = nil; + shouldNotify = YES; + } + } + + if (shouldNotify) { + [self postNotificationOnMainThreadWithName:kGTMSessionFetcherRetryDelayStoppedNotification + userInfo:nil + requireAsync:NO]; + } +} + +- (NSUInteger)retryCount { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _retryCount; + } // @synchronized(self) +} + +- (NSTimeInterval)nextRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSTimeInterval interval = [self nextRetryIntervalUnsynchronized]; + return interval; + } // @synchronized(self) +} + +- (NSTimeInterval)nextRetryIntervalUnsynchronized { + GTMSessionCheckSynchronized(self); + + NSInteger statusCode = [self statusCodeUnsynchronized]; + if ((statusCode == 503) && [self hasRetryAfterInterval]) { + NSTimeInterval secs = [self retryAfterInterval]; + return secs; + } + // The next wait interval is the factor (2.0) times the last interval, + // but never less than the minimum interval. + NSTimeInterval secs = _lastRetryInterval * _retryFactor; + if (_maxRetryInterval > 0) { + secs = MIN(secs, _maxRetryInterval); + } + secs = MAX(secs, _minRetryInterval); + + return secs; +} + +- (NSTimer *)retryTimer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _retryTimer; + } // @synchronized(self) +} + +- (BOOL)isRetryEnabled { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isRetryEnabled; + } // @synchronized(self) +} + +- (BOOL)isRetryEnabledUnsynchronized { + GTMSessionCheckSynchronized(self); + + return _isRetryEnabled; +} + +- (void)setRetryEnabled:(BOOL)flag { + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag && !_isRetryEnabled) { + // We defer initializing these until the user calls setRetryEnabled + // to avoid using the random number generator if it's not needed. + // However, this means min and max intervals for this fetcher are reset + // as a side effect of calling setRetryEnabled. + // + // Make an initial retry interval random between 1.0 and 2.0 seconds + _minRetryInterval = InitialMinRetryInterval(); + _maxRetryInterval = kUnsetMaxRetryInterval; + _retryFactor = 2.0; + _lastRetryInterval = 0.0; + } + _isRetryEnabled = flag; + } // @synchronized(self) +}; + +- (NSTimeInterval)maxRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _maxRetryInterval; + } // @synchronized(self) +} + +- (void)setMaxRetryInterval:(NSTimeInterval)secs { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (secs > 0) { + _maxRetryInterval = secs; + } else { + _maxRetryInterval = kUnsetMaxRetryInterval; + } + } // @synchronized(self) +} + +- (double)minRetryInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _minRetryInterval; + } // @synchronized(self) +} + +- (void)setMinRetryInterval:(NSTimeInterval)secs { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (secs > 0) { + _minRetryInterval = secs; + } else { + // Set min interval to a random value between 1.0 and 2.0 seconds + // so that if multiple clients start retrying at the same time, they'll + // repeat at different times and avoid overloading the server + _minRetryInterval = InitialMinRetryInterval(); + } + } // @synchronized(self) + +} + +#pragma mark iOS System Completion Handlers + +#if TARGET_OS_IPHONE +static NSMutableDictionary *gSystemCompletionHandlers = nil; + +- (GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler { + return [[self class] systemCompletionHandlerForSessionIdentifier:_sessionIdentifier]; +} + +- (void)setSystemCompletionHandler:(GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler { + [[self class] setSystemCompletionHandler:systemCompletionHandler + forSessionIdentifier:_sessionIdentifier]; +} + ++ (void)setSystemCompletionHandler:(GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandler + forSessionIdentifier:(NSString *)sessionIdentifier { + if (!sessionIdentifier) { + NSLog(@"%s with nil identifier", __PRETTY_FUNCTION__); + return; + } + + @synchronized([GTMSessionFetcher class]) { + if (gSystemCompletionHandlers == nil && systemCompletionHandler != nil) { + gSystemCompletionHandlers = [[NSMutableDictionary alloc] init]; + } + // Use setValue: to remove the object if completionHandler is nil. + [gSystemCompletionHandlers setValue:systemCompletionHandler + forKey:sessionIdentifier]; + } +} + ++ (GTM_NULLABLE GTMSessionFetcherSystemCompletionHandler)systemCompletionHandlerForSessionIdentifier:(NSString *)sessionIdentifier { + if (!sessionIdentifier) { + return nil; + } + @synchronized([GTMSessionFetcher class]) { + return [gSystemCompletionHandlers objectForKey:sessionIdentifier]; + } +} +#endif // TARGET_OS_IPHONE + +#pragma mark Getters and Setters + +@synthesize downloadResumeData = _downloadResumeData, + configuration = _configuration, + configurationBlock = _configurationBlock, + sessionTask = _sessionTask, + wasCreatedFromBackgroundSession = _wasCreatedFromBackgroundSession, + sessionUserInfo = _sessionUserInfo, + taskDescription = _taskDescription, + taskPriority = _taskPriority, + usingBackgroundSession = _usingBackgroundSession, + canShareSession = _canShareSession, + completionHandler = _completionHandler, + credential = _credential, + proxyCredential = _proxyCredential, + bodyData = _bodyData, + bodyLength = _bodyLength, + service = _service, + serviceHost = _serviceHost, + accumulateDataBlock = _accumulateDataBlock, + receivedProgressBlock = _receivedProgressBlock, + downloadProgressBlock = _downloadProgressBlock, + resumeDataBlock = _resumeDataBlock, + didReceiveResponseBlock = _didReceiveResponseBlock, + challengeBlock = _challengeBlock, + willRedirectBlock = _willRedirectBlock, + sendProgressBlock = _sendProgressBlock, + willCacheURLResponseBlock = _willCacheURLResponseBlock, + retryBlock = _retryBlock, + retryFactor = _retryFactor, + allowedInsecureSchemes = _allowedInsecureSchemes, + allowLocalhostRequest = _allowLocalhostRequest, + allowInvalidServerCertificates = _allowInvalidServerCertificates, + cookieStorage = _cookieStorage, + callbackQueue = _callbackQueue, + initialBeginFetchDate = _initialBeginFetchDate, + testBlock = _testBlock, + testBlockAccumulateDataChunkCount = _testBlockAccumulateDataChunkCount, + comment = _comment, + log = _log; + +#if !STRIP_GTM_FETCH_LOGGING +@synthesize redirectedFromURL = _redirectedFromURL, + logRequestBody = _logRequestBody, + logResponseBody = _logResponseBody, + hasLoggedError = _hasLoggedError; +#endif + +#if GTM_BACKGROUND_TASK_FETCHING +@synthesize backgroundTaskIdentifier = _backgroundTaskIdentifier, + skipBackgroundTask = _skipBackgroundTask; +#endif + +- (GTM_NULLABLE NSURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_request copy]; + } // @synchronized(self) +} + +- (void)setRequest:(GTM_NULLABLE NSURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (![self isFetchingUnsynchronized]) { + _request = [request mutableCopy]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"request may not be set after beginFetch has been invoked"); + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSMutableURLRequest *)mutableRequestForTesting { + // Allow tests only to modify the request, useful during retries. + return _request; +} + +// Internal method for updating the request property such as on redirects. +- (void)updateMutableRequest:(GTM_NULLABLE NSMutableURLRequest *)request { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _request = request; + } // @synchronized(self) +} + +// Set a header field value on the request. Header field value changes will not +// affect a fetch after the fetch has begun. +- (void)setRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field { + if (![self isFetching]) { + [self updateRequestValue:value forHTTPHeaderField:field]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"request may not be set after beginFetch has been invoked"); + } +} + +// Internal method for updating request headers. +- (void)updateRequestValue:(GTM_NULLABLE NSString *)value forHTTPHeaderField:(NSString *)field { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_request setValue:value forHTTPHeaderField:field]; + } // @synchronized(self) +} + +- (void)setResponse:(GTM_NULLABLE NSURLResponse *)response { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _response = response; + } // @synchronized(self) +} + +- (int64_t)bodyLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_bodyLength == NSURLSessionTransferSizeUnknown) { + if (_bodyData) { + _bodyLength = (int64_t)_bodyData.length; + } else if (_bodyFileURL) { + NSNumber *fileSizeNum = nil; + NSError *fileSizeError = nil; + if ([_bodyFileURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:&fileSizeError]) { + _bodyLength = [fileSizeNum longLongValue]; + } + } + } + return _bodyLength; + } // @synchronized(self) +} + +- (BOOL)useUploadTask { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _useUploadTask; + } // @synchronized(self) +} + +- (void)setUseUploadTask:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag != _useUploadTask) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"useUploadTask should not change after beginFetch has been invoked"); + _useUploadTask = flag; + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURL *)bodyFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _bodyFileURL; + } // @synchronized(self) +} + +- (void)setBodyFileURL:(GTM_NULLABLE NSURL *)fileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // The comparison here is a trivial optimization and forgiveness for any client that + // repeatedly sets the property, so it just uses pointer comparison rather than isEqual:. + if (fileURL != _bodyFileURL) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"fileURL should not change after beginFetch has been invoked"); + + _bodyFileURL = fileURL; + } + } // @synchronized(self) +} + +- (GTM_NULLABLE GTMSessionFetcherBodyStreamProvider)bodyStreamProvider { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _bodyStreamProvider; + } // @synchronized(self) +} + +- (void)setBodyStreamProvider:(GTM_NULLABLE GTMSessionFetcherBodyStreamProvider)block { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"stream provider should not change after beginFetch has been invoked"); + + _bodyStreamProvider = [block copy]; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _authorizer; + } // @synchronized(self) +} + +- (void)setAuthorizer:(GTM_NULLABLE id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (authorizer != _authorizer) { + if ([self isFetchingUnsynchronized]) { + GTMSESSION_ASSERT_DEBUG(0, @"authorizer should not change after beginFetch has been invoked"); + } else { + _authorizer = authorizer; + } + } + } // @synchronized(self) +} + +- (GTM_NULLABLE NSData *)downloadedData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _downloadedData; + } // @synchronized(self) +} + +- (void)setDownloadedData:(GTM_NULLABLE NSData *)data { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _downloadedData = [data mutableCopy]; + } // @synchronized(self) +} + +- (int64_t)downloadedLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _downloadedLength; + } // @synchronized(self) +} + +- (void)setDownloadedLength:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _downloadedLength = length; + } // @synchronized(self) +} + +- (dispatch_queue_t GTM_NONNULL_TYPE)callbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _callbackQueue; + } // @synchronized(self) +} + +- (void)setCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _callbackQueue = queue ?: dispatch_get_main_queue(); + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _session; + } // @synchronized(self) +} + +- (NSInteger)servicePriority { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _servicePriority; + } // @synchronized(self) +} + +- (void)setServicePriority:(NSInteger)value { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (value != _servicePriority) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"servicePriority should not change after beginFetch has been invoked"); + + _servicePriority = value; + } + } // @synchronized(self) +} + + +- (void)setSession:(GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = session; + } // @synchronized(self) +} + +- (BOOL)canShareSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _canShareSession; + } // @synchronized(self) +} + +- (void)setCanShareSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _canShareSession = flag; + } // @synchronized(self) +} + +- (BOOL)useBackgroundSession { + // This reflects if the user requested a background session, not necessarily + // if one was created. That is tracked with _usingBackgroundSession. + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userRequestedBackgroundSession; + } // @synchronized(self) +} + +- (void)setUseBackgroundSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (flag != _userRequestedBackgroundSession) { + GTMSESSION_ASSERT_DEBUG(![self isFetchingUnsynchronized], + @"useBackgroundSession should not change after beginFetch has been invoked"); + + _userRequestedBackgroundSession = flag; + } + } // @synchronized(self) +} + +- (BOOL)isUsingBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _usingBackgroundSession; + } // @synchronized(self) +} + +- (void)setUsingBackgroundSession:(BOOL)flag { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _usingBackgroundSession = flag; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURLSession *)sessionNeedingInvalidation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _sessionNeedingInvalidation; + } // @synchronized(self) +} + +- (void)setSessionNeedingInvalidation:(GTM_NULLABLE NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _sessionNeedingInvalidation = session; + } // @synchronized(self) +} + +- (NSOperationQueue * GTM_NONNULL_TYPE)sessionDelegateQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateQueue; + } // @synchronized(self) +} + +- (void)setSessionDelegateQueue:(NSOperationQueue * GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (queue != _delegateQueue) { + if ([self isFetchingUnsynchronized]) { + GTMSESSION_ASSERT_DEBUG(0, @"sessionDelegateQueue should not change after fetch begins"); + } else { + _delegateQueue = queue ?: [NSOperationQueue mainQueue]; + } + } + } // @synchronized(self) +} + +- (BOOL)userStoppedFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userStoppedFetching; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)userData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _userData; + } // @synchronized(self) +} + +- (void)setUserData:(GTM_NULLABLE id)theObj { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _userData = theObj; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSURL *)destinationFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _destinationFileURL; + } // @synchronized(self) +} + +- (void)setDestinationFileURL:(GTM_NULLABLE NSURL *)destinationFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (((_destinationFileURL == nil) && (destinationFileURL == nil)) || + [_destinationFileURL isEqual:destinationFileURL]) { + return; + } + if (_sessionIdentifier) { + // This is something we don't expect to happen in production. + // However if it ever happen, leave a system log. + NSLog(@"%@: Destination File URL changed from (%@) to (%@) after session identifier has " + @"been created.", + [self class], _destinationFileURL, destinationFileURL); +#if DEBUG + // On both the simulator and devices, the path can change to the download file, but the name + // shouldn't change. Technically, this isn't supported in the fetcher, but the change of + // URL is expected to happen only across development runs through Xcode. + NSString *oldFilename = [_destinationFileURL lastPathComponent]; + NSString *newFilename = [destinationFileURL lastPathComponent]; + #pragma unused(oldFilename) + #pragma unused(newFilename) + GTMSESSION_ASSERT_DEBUG([oldFilename isEqualToString:newFilename], + @"Destination File URL cannot be changed after session identifier has been created"); +#endif + } + _destinationFileURL = destinationFileURL; + } // @synchronized(self) +} + +- (void)setProperties:(GTM_NULLABLE NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _properties = [dict mutableCopy]; + } // @synchronized(self) +} + +- (GTM_NULLABLE NSDictionary *)properties { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _properties; + } // @synchronized(self) +} + +- (void)setProperty:(GTM_NULLABLE id)obj forKey:(NSString *)key { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_properties == nil && obj != nil) { + _properties = [[NSMutableDictionary alloc] init]; + } + [_properties setValue:obj forKey:key]; + } // @synchronized(self) +} + +- (GTM_NULLABLE id)propertyForKey:(NSString *)key { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_properties objectForKey:key]; + } // @synchronized(self) +} + +- (void)addPropertiesFromDictionary:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_properties == nil && dict != nil) { + [self setProperties:[dict mutableCopy]]; + } else { + [_properties addEntriesFromDictionary:dict]; + } + } // @synchronized(self) +} + +- (void)setCommentWithFormat:(id)format, ... { +#if !STRIP_GTM_FETCH_LOGGING + NSString *result = format; + if (format) { + va_list argList; + va_start(argList, format); + + result = [[NSString alloc] initWithFormat:format + arguments:argList]; + va_end(argList); + } + [self setComment:result]; +#endif +} + +#if !STRIP_GTM_FETCH_LOGGING +- (NSData *)loggedStreamData { + return _loggedStreamData; +} + +- (void)appendLoggedStreamData:dataToAdd { + if (!_loggedStreamData) { + _loggedStreamData = [NSMutableData data]; + } + [_loggedStreamData appendData:dataToAdd]; +} + +- (void)clearLoggedStreamData { + _loggedStreamData = nil; +} + +- (void)setDeferResponseBodyLogging:(BOOL)deferResponseBodyLogging { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (deferResponseBodyLogging != _deferResponseBodyLogging) { + _deferResponseBodyLogging = deferResponseBodyLogging; + if (!deferResponseBodyLogging && !self.hasLoggedError) { + [_delegateQueue addOperationWithBlock:^{ + [self logNowWithError:nil]; + }]; + } + } + } // @synchronized(self) +} + +- (BOOL)deferResponseBodyLogging { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _deferResponseBodyLogging; + } // @synchronized(self) +} + +#else ++ (void)setLoggingEnabled:(BOOL)flag { +} + ++ (BOOL)isLoggingEnabled { + return NO; +} +#endif // STRIP_GTM_FETCH_LOGGING + +@end + +@implementation GTMSessionFetcher (BackwardsCompatibilityOnly) + +- (void)setCookieStorageMethod:(NSInteger)method { + // For backwards compatibility with the old fetcher, we'll support the old constants. + // + // Clients using the GTMSessionFetcher class should set the cookie storage explicitly + // themselves. + NSHTTPCookieStorage *storage = nil; + switch(method) { + case 0: // kGTMHTTPFetcherCookieStorageMethodStatic + // nil storage will use [[self class] staticCookieStorage] when the fetch begins. + break; + case 1: // kGTMHTTPFetcherCookieStorageMethodFetchHistory + // Do nothing; use whatever was set by the fetcher service. + return; + case 2: // kGTMHTTPFetcherCookieStorageMethodSystemDefault + storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + break; + case 3: // kGTMHTTPFetcherCookieStorageMethodNone + // Create temporary storage for this fetcher only. + storage = [[GTMSessionCookieStorage alloc] init]; + break; + default: + GTMSESSION_ASSERT_DEBUG(0, @"Invalid cookie storage method: %d", (int)method); + } + self.cookieStorage = storage; +} + +@end + +@implementation GTMSessionCookieStorage { + NSMutableArray *_cookies; + NSHTTPCookieAcceptPolicy _policy; +} + +- (id)init { + self = [super init]; + if (self != nil) { + _cookies = [[NSMutableArray alloc] init]; + } + return self; +} + +- (GTM_NULLABLE NSArray *)cookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_cookies copy]; + } // @synchronized(self) +} + +- (void)setCookie:(NSHTTPCookie *)cookie { + if (!cookie) return; + if (_policy == NSHTTPCookieAcceptPolicyNever) return; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self internalSetCookie:cookie]; + } // @synchronized(self) +} + +// Note: this should only be called from inside a @synchronized(self) block. +- (void)internalSetCookie:(NSHTTPCookie *)newCookie { + GTMSessionCheckSynchronized(self); + + if (_policy == NSHTTPCookieAcceptPolicyNever) return; + + BOOL isValidCookie = (newCookie.name.length > 0 + && newCookie.domain.length > 0 + && newCookie.path.length > 0); + GTMSESSION_ASSERT_DEBUG(isValidCookie, @"invalid cookie: %@", newCookie); + + if (isValidCookie) { + // Remove the cookie if it's currently in the array. + NSHTTPCookie *oldCookie = [self cookieMatchingCookie:newCookie]; + if (oldCookie) { + [_cookies removeObjectIdenticalTo:oldCookie]; + } + + if (![[self class] hasCookieExpired:newCookie]) { + [_cookies addObject:newCookie]; + } + } +} + +// Add all cookies in the new cookie array to the storage, +// replacing stored cookies as appropriate. +// +// Side effect: removes expired cookies from the storage array. +- (void)setCookies:(GTM_NULLABLE NSArray *)newCookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self removeExpiredCookies]; + + for (NSHTTPCookie *newCookie in newCookies) { + [self internalSetCookie:newCookie]; + } + } // @synchronized(self) +} + +- (void)setCookies:(NSArray *)cookies forURL:(GTM_NULLABLE NSURL *)URL mainDocumentURL:(GTM_NULLABLE NSURL *)mainDocumentURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_policy == NSHTTPCookieAcceptPolicyNever) { + return; + } + + if (_policy == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain) { + NSString *mainHost = mainDocumentURL.host; + NSString *associatedHost = URL.host; + if (!mainHost || ![associatedHost hasSuffix:mainHost]) { + return; + } + } + } // @synchronized(self) + [self setCookies:cookies]; +} + +- (void)deleteCookie:(NSHTTPCookie *)cookie { + if (!cookie) return; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSHTTPCookie *foundCookie = [self cookieMatchingCookie:cookie]; + if (foundCookie) { + [_cookies removeObjectIdenticalTo:foundCookie]; + } + } // @synchronized(self) +} + +// Retrieve all cookies appropriate for the given URL, considering +// domain, path, cookie name, expiration, security setting. +// Side effect: removed expired cookies from the storage array. +- (GTM_NULLABLE NSArray *)cookiesForURL:(NSURL *)theURL { + NSMutableArray *foundCookies = nil; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self removeExpiredCookies]; + + // We'll prepend "." to the desired domain, since we want the + // actual domain "nytimes.com" to still match the cookie domain + // ".nytimes.com" when we check it below with hasSuffix. + NSString *host = theURL.host.lowercaseString; + NSString *path = theURL.path; + NSString *scheme = [theURL scheme]; + + NSString *requestingDomain = nil; + BOOL isLocalhostRetrieval = NO; + + if (IsLocalhost(host)) { + isLocalhostRetrieval = YES; + } else { + if (host.length > 0) { + requestingDomain = [@"." stringByAppendingString:host]; + } + } + + for (NSHTTPCookie *storedCookie in _cookies) { + NSString *cookieDomain = storedCookie.domain.lowercaseString; + NSString *cookiePath = storedCookie.path; + BOOL cookieIsSecure = [storedCookie isSecure]; + + BOOL isDomainOK; + + if (isLocalhostRetrieval) { + // Prior to 10.5.6, the domain stored into NSHTTPCookies for localhost + // is "localhost.local" + isDomainOK = (IsLocalhost(cookieDomain) + || [cookieDomain isEqual:@"localhost.local"]); + } else { + // Ensure we're matching exact domain names. We prepended a dot to the + // requesting domain, so we can also prepend one here if needed before + // checking if the request contains the cookie domain. + if (![cookieDomain hasPrefix:@"."]) { + cookieDomain = [@"." stringByAppendingString:cookieDomain]; + } + isDomainOK = [requestingDomain hasSuffix:cookieDomain]; + } + + BOOL isPathOK = [cookiePath isEqual:@"/"] || [path hasPrefix:cookiePath]; + BOOL isSecureOK = (!cookieIsSecure + || [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame); + + if (isDomainOK && isPathOK && isSecureOK) { + if (foundCookies == nil) { + foundCookies = [NSMutableArray array]; + } + [foundCookies addObject:storedCookie]; + } + } + } // @synchronized(self) + return foundCookies; +} + +// Override methods from the NSHTTPCookieStorage (NSURLSessionTaskAdditions) category. +- (void)storeCookies:(NSArray *)cookies forTask:(NSURLSessionTask *)task { + NSURLRequest *currentRequest = task.currentRequest; + [self setCookies:cookies forURL:currentRequest.URL mainDocumentURL:nil]; +} + +- (void)getCookiesForTask:(NSURLSessionTask *)task + completionHandler:(void (^)(GTM_NSArrayOf(NSHTTPCookie *) *))completionHandler { + if (completionHandler) { + NSURLRequest *currentRequest = task.currentRequest; + NSURL *currentRequestURL = currentRequest.URL; + NSArray *cookies = [self cookiesForURL:currentRequestURL]; + completionHandler(cookies); + } +} + +// Return a cookie from the array with the same name, domain, and path as the +// given cookie, or else return nil if none found. +// +// Both the cookie being tested and all cookies in the storage array should +// be valid (non-nil name, domains, paths). +// +// Note: this should only be called from inside a @synchronized(self) block +- (GTM_NULLABLE NSHTTPCookie *)cookieMatchingCookie:(NSHTTPCookie *)cookie { + GTMSessionCheckSynchronized(self); + + NSString *name = cookie.name; + NSString *domain = cookie.domain; + NSString *path = cookie.path; + + GTMSESSION_ASSERT_DEBUG(name && domain && path, + @"Invalid stored cookie (name:%@ domain:%@ path:%@)", name, domain, path); + + for (NSHTTPCookie *storedCookie in _cookies) { + if ([storedCookie.name isEqual:name] + && [storedCookie.domain isEqual:domain] + && [storedCookie.path isEqual:path]) { + return storedCookie; + } + } + return nil; +} + +// Internal routine to remove any expired cookies from the array, excluding +// cookies with nil expirations. +// +// Note: this should only be called from inside a @synchronized(self) block +- (void)removeExpiredCookies { + GTMSessionCheckSynchronized(self); + + // Count backwards since we're deleting items from the array + for (NSInteger idx = (NSInteger)_cookies.count - 1; idx >= 0; idx--) { + NSHTTPCookie *storedCookie = [_cookies objectAtIndex:(NSUInteger)idx]; + if ([[self class] hasCookieExpired:storedCookie]) { + [_cookies removeObjectAtIndex:(NSUInteger)idx]; + } + } +} + ++ (BOOL)hasCookieExpired:(NSHTTPCookie *)cookie { + NSDate *expiresDate = [cookie expiresDate]; + if (expiresDate == nil) { + // Cookies seem to have a Expires property even when the expiresDate method returns nil. + id expiresVal = [[cookie properties] objectForKey:NSHTTPCookieExpires]; + if ([expiresVal isKindOfClass:[NSDate class]]) { + expiresDate = expiresVal; + } + } + BOOL hasExpired = (expiresDate != nil && [expiresDate timeIntervalSinceNow] < 0); + return hasExpired; +} + +- (void)removeAllCookies { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_cookies removeAllObjects]; + } // @synchronized(self) +} + +- (NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _policy; + } // @synchronized(self) +} + +- (void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)cookieAcceptPolicy { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _policy = cookieAcceptPolicy; + } // @synchronized(self) +} + +@end + +void GTMSessionFetcherAssertValidSelector(id GTM_NULLABLE_TYPE obj, SEL GTM_NULLABLE_TYPE sel, ...) { + // Verify that the object's selector is implemented with the proper + // number and type of arguments +#if DEBUG + va_list argList; + va_start(argList, sel); + + if (obj && sel) { + // Check that the selector is implemented + if (![obj respondsToSelector:sel]) { + NSLog(@"\"%@\" selector \"%@\" is unimplemented or misnamed", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel)); + NSCAssert(0, @"callback selector unimplemented or misnamed"); + } else { + const char *expectedArgType; + unsigned int argCount = 2; // skip self and _cmd + NSMethodSignature *sig = [obj methodSignatureForSelector:sel]; + + // Check that each expected argument is present and of the correct type + while ((expectedArgType = va_arg(argList, const char*)) != 0) { + + if ([sig numberOfArguments] > argCount) { + const char *foundArgType = [sig getArgumentTypeAtIndex:argCount]; + + if (0 != strncmp(foundArgType, expectedArgType, strlen(expectedArgType))) { + NSLog(@"\"%@\" selector \"%@\" argument %d should be type %s", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel), (argCount - 2), expectedArgType); + NSCAssert(0, @"callback selector argument type mistake"); + } + } + argCount++; + } + + // Check that the proper number of arguments are present in the selector + if (argCount != [sig numberOfArguments]) { + NSLog(@"\"%@\" selector \"%@\" should have %d arguments", + NSStringFromClass([(id)obj class]), + NSStringFromSelector((SEL)sel), (argCount - 2)); + NSCAssert(0, @"callback selector arguments incorrect"); + } + } + } + + va_end(argList); +#endif +} + +NSString *GTMFetcherCleanedUserAgentString(NSString *str) { + // Reference http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html + // and http://www-archive.mozilla.org/build/user-agent-strings.html + + if (str == nil) return @""; + + NSMutableString *result = [NSMutableString stringWithString:str]; + + // Replace spaces and commas with underscores + [result replaceOccurrencesOfString:@" " + withString:@"_" + options:0 + range:NSMakeRange(0, result.length)]; + [result replaceOccurrencesOfString:@"," + withString:@"_" + options:0 + range:NSMakeRange(0, result.length)]; + + // Delete http token separators and remaining whitespace + static NSCharacterSet *charsToDelete = nil; + if (charsToDelete == nil) { + // Make a set of unwanted characters + NSString *const kSeparators = @"()<>@;:\\\"/[]?={}"; + + NSMutableCharacterSet *mutableChars = + [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy]; + [mutableChars addCharactersInString:kSeparators]; + charsToDelete = [mutableChars copy]; // hang on to an immutable copy + } + + while (1) { + NSRange separatorRange = [result rangeOfCharacterFromSet:charsToDelete]; + if (separatorRange.location == NSNotFound) break; + + [result deleteCharactersInRange:separatorRange]; + }; + + return result; +} + +NSString *GTMFetcherSystemVersionString(void) { + static NSString *sSavedSystemString; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // The Xcode 8 SDKs finally cleaned up this mess by providing TARGET_OS_OSX + // and TARGET_OS_IOS, but to build with older SDKs, those don't exist and + // instead one has to rely on TARGET_OS_MAC (which is true for iOS, watchOS, + // and tvOS) and TARGET_OS_IPHONE (which is true for iOS, watchOS, tvOS). So + // one has to order these carefully so you pick off the specific things + // first. + // If the code can ever assume Xcode 8 or higher (even when building for + // older OSes), then + // TARGET_OS_MAC -> TARGET_OS_OSX + // TARGET_OS_IPHONE -> TARGET_OS_IOS + // TARGET_IPHONE_SIMULATOR -> TARGET_OS_SIMULATOR +#if TARGET_OS_WATCH + // watchOS - WKInterfaceDevice + + WKInterfaceDevice *currentDevice = [WKInterfaceDevice currentDevice]; + + NSString *rawModel = [currentDevice model]; + NSString *model = GTMFetcherCleanedUserAgentString(rawModel); + + NSString *systemVersion = [currentDevice systemVersion]; + +#if TARGET_OS_SIMULATOR + NSString *hardwareModel = @"sim"; +#else + NSString *hardwareModel; + struct utsname unameRecord; + if (uname(&unameRecord) == 0) { + NSString *machineName = @(unameRecord.machine); + hardwareModel = GTMFetcherCleanedUserAgentString(machineName); + } + if (hardwareModel.length == 0) { + hardwareModel = @"unk"; + } +#endif + + sSavedSystemString = [[NSString alloc] initWithFormat:@"%@/%@ hw/%@", + model, systemVersion, hardwareModel]; + // Example: Apple_Watch/3.0 hw/Watch1_2 +#elif TARGET_OS_TV || TARGET_OS_IPHONE + // iOS and tvOS have UIDevice, use that. + UIDevice *currentDevice = [UIDevice currentDevice]; + + NSString *rawModel = [currentDevice model]; + NSString *model = GTMFetcherCleanedUserAgentString(rawModel); + + NSString *systemVersion = [currentDevice systemVersion]; + +#if TARGET_IPHONE_SIMULATOR || TARGET_OS_SIMULATOR + NSString *hardwareModel = @"sim"; +#else + NSString *hardwareModel; + struct utsname unameRecord; + if (uname(&unameRecord) == 0) { + NSString *machineName = @(unameRecord.machine); + hardwareModel = GTMFetcherCleanedUserAgentString(machineName); + } + if (hardwareModel.length == 0) { + hardwareModel = @"unk"; + } +#endif + + sSavedSystemString = [[NSString alloc] initWithFormat:@"%@/%@ hw/%@", + model, systemVersion, hardwareModel]; + // Example: iPod_Touch/2.2 hw/iPod1_1 + // Example: Apple_TV/9.2 hw/AppleTV5,3 +#elif TARGET_OS_MAC + // Mac build + NSProcessInfo *procInfo = [NSProcessInfo processInfo]; +#if !defined(MAC_OS_X_VERSION_10_10) + BOOL hasOperatingSystemVersion = NO; +#elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 + BOOL hasOperatingSystemVersion = + [procInfo respondsToSelector:@selector(operatingSystemVersion)]; +#else + BOOL hasOperatingSystemVersion = YES; +#endif + NSString *versString; + if (hasOperatingSystemVersion) { +#if defined(MAC_OS_X_VERSION_10_10) + // A reference to NSOperatingSystemVersion requires the 10.10 SDK. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +// Disable unguarded availability warning as we can't use the @availability macro until we require +// all clients to build with Xcode 9 or above. + NSOperatingSystemVersion version = procInfo.operatingSystemVersion; +#pragma clang diagnostic pop + versString = [NSString stringWithFormat:@"%ld.%ld.%ld", + (long)version.majorVersion, (long)version.minorVersion, + (long)version.patchVersion]; +#else +#pragma unused(procInfo) +#endif + } else { + // With Gestalt inexplicably deprecated in 10.8, we're reduced to reading + // the system plist file. + NSString *const kPath = @"/System/Library/CoreServices/SystemVersion.plist"; + NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:kPath]; + versString = [plist objectForKey:@"ProductVersion"]; + if (versString.length == 0) { + versString = @"10.?.?"; + } + } + + sSavedSystemString = [[NSString alloc] initWithFormat:@"MacOSX/%@", versString]; +#elif defined(_SYS_UTSNAME_H) + // Foundation-only build + struct utsname unameRecord; + uname(&unameRecord); + + sSavedSystemString = [NSString stringWithFormat:@"%s/%s", + unameRecord.sysname, unameRecord.release]; // "Darwin/8.11.1" +#else +#error No branch taken for a default user agent +#endif + }); + return sSavedSystemString; +} + +NSString *GTMFetcherStandardUserAgentString(NSBundle * GTM_NULLABLE_TYPE bundle) { + NSString *result = [NSString stringWithFormat:@"%@ %@", + GTMFetcherApplicationIdentifier(bundle), + GTMFetcherSystemVersionString()]; + return result; +} + +NSString *GTMFetcherApplicationIdentifier(NSBundle * GTM_NULLABLE_TYPE bundle) { + @synchronized([GTMSessionFetcher class]) { + static NSMutableDictionary *sAppIDMap = nil; + + // If there's a bundle ID, use that; otherwise, use the process name + if (bundle == nil) { + bundle = [NSBundle mainBundle]; + } + NSString *bundleID = [bundle bundleIdentifier]; + if (bundleID == nil) { + bundleID = @""; + } + + NSString *identifier = [sAppIDMap objectForKey:bundleID]; + if (identifier) return identifier; + + // Apps may add a string to the info.plist to uniquely identify different builds. + identifier = [bundle objectForInfoDictionaryKey:@"GTMUserAgentID"]; + if (identifier.length == 0) { + if (bundleID.length > 0) { + identifier = bundleID; + } else { + // Fall back on the procname, prefixed by "proc" to flag that it's + // autogenerated and perhaps unreliable + NSString *procName = [[NSProcessInfo processInfo] processName]; + identifier = [NSString stringWithFormat:@"proc_%@", procName]; + } + } + + // Clean up whitespace and special characters + identifier = GTMFetcherCleanedUserAgentString(identifier); + + // If there's a version number, append that + NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + if (version.length == 0) { + version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; + } + + // Clean up whitespace and special characters + version = GTMFetcherCleanedUserAgentString(version); + + // Glue the two together (cleanup done above or else cleanup would strip the + // slash) + if (version.length > 0) { + identifier = [identifier stringByAppendingFormat:@"/%@", version]; + } + + if (sAppIDMap == nil) { + sAppIDMap = [[NSMutableDictionary alloc] init]; + } + [sAppIDMap setObject:identifier forKey:bundleID]; + return identifier; + } +} + +#if DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) +@implementation GTMSessionSyncMonitorInternal { + NSValue *_objectKey; // The synchronize target object. + const char *_functionName; // The function containing the monitored sync block. +} + +- (instancetype)initWithSynchronizationObject:(id)object + allowRecursive:(BOOL)allowRecursive + functionName:(const char *)functionName { + self = [super init]; + if (self) { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + _objectKey = [NSValue valueWithNonretainedObject:object]; + _functionName = functionName; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + if (counters == nil) { + counters = [NSMutableDictionary dictionary]; + threadDict[(id)threadKey] = counters; + } + NSCountedSet *functionNamesCounter = counters[_objectKey]; + NSUInteger numberOfSyncingFunctions = functionNamesCounter.count; + + if (!allowRecursive) { + BOOL isTopLevelSyncScope = (numberOfSyncingFunctions == 0); + NSArray *stack = [NSThread callStackSymbols]; + GTMSESSION_ASSERT_DEBUG(isTopLevelSyncScope, + @"*** Recursive sync on %@ at %s; previous sync at %@\n%@", + [object class], functionName, functionNamesCounter.allObjects, + [stack subarrayWithRange:NSMakeRange(1, stack.count - 1)]); + } + + if (!functionNamesCounter) { + functionNamesCounter = [NSCountedSet set]; + counters[_objectKey] = functionNamesCounter; + } + [functionNamesCounter addObject:(id _Nonnull)@(functionName)]; + } + return self; +} + +- (void)dealloc { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + NSCountedSet *functionNamesCounter = counters[_objectKey]; + NSString *functionNameStr = @(_functionName); + NSUInteger numberOfSyncsByThisFunction = [functionNamesCounter countForObject:functionNameStr]; + NSArray *stack = [NSThread callStackSymbols]; + GTMSESSION_ASSERT_DEBUG(numberOfSyncsByThisFunction > 0, @"Sync not found on %@ at %s\n%@", + [_objectKey.nonretainedObjectValue class], _functionName, + [stack subarrayWithRange:NSMakeRange(1, stack.count - 1)]); + [functionNamesCounter removeObject:functionNameStr]; + if (functionNamesCounter.count == 0) { + [counters removeObjectForKey:_objectKey]; + } +} + ++ (NSArray *)functionsHoldingSynchronizationOnObject:(id)object { + Class threadKey = [GTMSessionSyncMonitorInternal class]; + NSValue *localObjectKey = [NSValue valueWithNonretainedObject:object]; + + NSMutableDictionary *threadDict = [NSThread currentThread].threadDictionary; + NSMutableDictionary *counters = threadDict[threadKey]; + NSCountedSet *functionNamesCounter = counters[localObjectKey]; + return functionNamesCounter.count > 0 ? functionNamesCounter.allObjects : nil; +} +@end +#endif // DEBUG && (!defined(NS_BLOCK_ASSERTIONS) || GTMSESSION_ASSERT_AS_LOG) +GTM_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h new file mode 100644 index 0000000..5ccea78 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.h @@ -0,0 +1,112 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GTMSessionFetcher.h" + +// GTM HTTP Logging +// +// All traffic using GTMSessionFetcher can be easily logged. Call +// +// [GTMSessionFetcher setLoggingEnabled:YES]; +// +// to begin generating log files. +// +// Unless explicitly set by the application using +setLoggingDirectory:, +// logs are put into a default directory, located at: +// * macOS: ~/Desktop/GTMHTTPDebugLogs +// * iOS simulator: ~/GTMHTTPDebugLogs (in application sandbox) +// * iOS device: ~/Documents/GTMHTTPDebugLogs (in application sandbox) +// +// Tip: use the Finder's "Sort By Date" to find the most recent logs. +// +// Each run of an application gets a separate set of log files. An html +// file is generated to simplify browsing the run's http transactions. +// The html file includes javascript links for inline viewing of uploaded +// and downloaded data. +// +// A symlink is created in the logs folder to simplify finding the html file +// for the latest run of the application; the symlink is called +// +// AppName_http_log_newest.html +// +// For better viewing of XML logs, use Camino or Firefox rather than Safari. +// +// Each fetcher may be given a comment to be inserted as a label in the logs, +// such as +// [fetcher setCommentWithFormat:@"retrieve item %@", itemName]; +// +// Projects may define STRIP_GTM_FETCH_LOGGING to remove logging code. + +#if !STRIP_GTM_FETCH_LOGGING + +@interface GTMSessionFetcher (GTMSessionFetcherLogging) + +// Note: on macOS the default logs directory is ~/Desktop/GTMHTTPDebugLogs; on +// iOS simulators it will be the ~/GTMHTTPDebugLogs (in the app sandbox); on +// iOS devices it will be in ~/Documents/GTMHTTPDebugLogs (in the app sandbox). +// These directories will be created as needed, and are excluded from backups +// to iCloud and iTunes. +// +// If a custom directory is set, the directory should already exist. It is +// the application's responsibility to exclude any custom directory from +// backups, if desired. ++ (void)setLoggingDirectory:(NSString *)path; ++ (NSString *)loggingDirectory; + +// client apps can turn logging on and off ++ (void)setLoggingEnabled:(BOOL)isLoggingEnabled; ++ (BOOL)isLoggingEnabled; + +// client apps can turn off logging to a file if they want to only check +// the fetcher's log property ++ (void)setLoggingToFileEnabled:(BOOL)isLoggingToFileEnabled; ++ (BOOL)isLoggingToFileEnabled; + +// client apps can optionally specify process name and date string used in +// log file names ++ (void)setLoggingProcessName:(NSString *)processName; ++ (NSString *)loggingProcessName; + ++ (void)setLoggingDateStamp:(NSString *)dateStamp; ++ (NSString *)loggingDateStamp; + +// client apps can specify the directory for the log for this specific run, +// typically to match the directory used by another fetcher class, like: +// +// [GTMSessionFetcher setLogDirectoryForCurrentRun:[GTMHTTPFetcher logDirectoryForCurrentRun]]; +// +// Setting this overrides the logging directory, process name, and date stamp when writing +// the log file. ++ (void)setLogDirectoryForCurrentRun:(NSString *)logDirectoryForCurrentRun; ++ (NSString *)logDirectoryForCurrentRun; + +// Prunes old log directories that have not been modified since the provided date. +// This will not delete the current run's log directory. ++ (void)deleteLogDirectoriesOlderThanDate:(NSDate *)date; + +// internal; called by fetcher +- (void)logFetchWithError:(NSError *)error; +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream; +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider; + +// internal; accessors useful for viewing logs ++ (NSString *)processNameLogPrefix; ++ (NSString *)symlinkNameSuffix; ++ (NSString *)htmlFileName; + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m new file mode 100644 index 0000000..cdf5c17 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherLogging.m @@ -0,0 +1,982 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#include +#include + +#import "GTMSessionFetcherLogging.h" + +#ifndef STRIP_GTM_FETCH_LOGGING + #error GTMSessionFetcher headers should have defaulted this if it wasn't already defined. +#endif + +#if !STRIP_GTM_FETCH_LOGGING + +// Sensitive credential strings are replaced in logs with _snip_ +// +// Apps that must see the contents of sensitive tokens can set this to 1 +#ifndef SKIP_GTM_FETCH_LOGGING_SNIPPING +#define SKIP_GTM_FETCH_LOGGING_SNIPPING 0 +#endif + +// If GTMReadMonitorInputStream is available, it can be used for +// capturing uploaded streams of data +// +// We locally declare methods of GTMReadMonitorInputStream so we +// do not need to import the header, as some projects may not have it available +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMReadMonitorInputStream : NSInputStream + ++ (instancetype)inputStreamWithStream:(NSInputStream *)input; + +@property (assign) id readDelegate; +@property (assign) SEL readSelector; + +@end +#else +@class GTMReadMonitorInputStream; +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionFetcher (GTMHTTPFetcherLoggingUtilities) + ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict; ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr; +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(int64_t)length; + +@end + +@implementation GTMSessionFetcher (GTMSessionFetcherLogging) + +// fetchers come and fetchers go, but statics are forever +static BOOL gIsLoggingEnabled = NO; +static BOOL gIsLoggingToFile = YES; +static NSString *gLoggingDirectoryPath = nil; +static NSString *gLogDirectoryForCurrentRun = nil; +static NSString *gLoggingDateStamp = nil; +static NSString *gLoggingProcessName = nil; + ++ (void)setLoggingDirectory:(NSString *)path { + gLoggingDirectoryPath = [path copy]; +} + ++ (NSString *)loggingDirectory { + if (!gLoggingDirectoryPath) { + NSArray *paths = nil; +#if TARGET_IPHONE_SIMULATOR + // default to a directory called GTMHTTPDebugLogs into a sandbox-safe + // directory that a developer can find easily, the application home + paths = @[ NSHomeDirectory() ]; +#elif TARGET_OS_IPHONE + // Neither ~/Desktop nor ~/Home is writable on an actual iOS, watchOS, or tvOS device. + // Put it in ~/Documents. + paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); +#else + // default to a directory called GTMHTTPDebugLogs in the desktop folder + paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES); +#endif + + NSString *desktopPath = paths.firstObject; + if (desktopPath) { + NSString *const kGTMLogFolderName = @"GTMHTTPDebugLogs"; + NSString *logsFolderPath = [desktopPath stringByAppendingPathComponent:kGTMLogFolderName]; + + NSFileManager *fileMgr = [NSFileManager defaultManager]; + BOOL isDir; + BOOL doesFolderExist = [fileMgr fileExistsAtPath:logsFolderPath isDirectory:&isDir]; + if (!doesFolderExist) { + // make the directory + doesFolderExist = [fileMgr createDirectoryAtPath:logsFolderPath + withIntermediateDirectories:YES + attributes:nil + error:NULL]; + if (doesFolderExist) { + // The directory has been created. Exclude it from backups. + NSURL *pathURL = [NSURL fileURLWithPath:logsFolderPath isDirectory:YES]; + [pathURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:NULL]; + } + } + + if (doesFolderExist) { + // it's there; store it in the global + gLoggingDirectoryPath = [logsFolderPath copy]; + } + } + } + return gLoggingDirectoryPath; +} + ++ (void)setLogDirectoryForCurrentRun:(NSString *)logDirectoryForCurrentRun { + // Set the path for this run's logs. + gLogDirectoryForCurrentRun = [logDirectoryForCurrentRun copy]; +} + ++ (NSString *)logDirectoryForCurrentRun { + // make a directory for this run's logs, like SyncProto_logs_10-16_01-56-58PM + if (gLogDirectoryForCurrentRun) return gLogDirectoryForCurrentRun; + + NSString *parentDir = [self loggingDirectory]; + NSString *logNamePrefix = [self processNameLogPrefix]; + NSString *dateStamp = [self loggingDateStamp]; + NSString *dirName = [NSString stringWithFormat:@"%@%@", logNamePrefix, dateStamp]; + NSString *logDirectory = [parentDir stringByAppendingPathComponent:dirName]; + + if (gIsLoggingToFile) { + NSFileManager *fileMgr = [NSFileManager defaultManager]; + // Be sure that the first time this app runs, it's not writing to a preexisting folder + static BOOL gShouldReuseFolder = NO; + if (!gShouldReuseFolder) { + gShouldReuseFolder = YES; + NSString *origLogDir = logDirectory; + for (int ctr = 2; ctr < 20; ++ctr) { + if (![fileMgr fileExistsAtPath:logDirectory]) break; + + // append a digit + logDirectory = [origLogDir stringByAppendingFormat:@"_%d", ctr]; + } + } + if (![fileMgr createDirectoryAtPath:logDirectory + withIntermediateDirectories:YES + attributes:nil + error:NULL]) return nil; + } + gLogDirectoryForCurrentRun = logDirectory; + + return gLogDirectoryForCurrentRun; +} + ++ (void)setLoggingEnabled:(BOOL)isLoggingEnabled { + gIsLoggingEnabled = isLoggingEnabled; +} + ++ (BOOL)isLoggingEnabled { + return gIsLoggingEnabled; +} + ++ (void)setLoggingToFileEnabled:(BOOL)isLoggingToFileEnabled { + gIsLoggingToFile = isLoggingToFileEnabled; +} + ++ (BOOL)isLoggingToFileEnabled { + return gIsLoggingToFile; +} + ++ (void)setLoggingProcessName:(NSString *)processName { + gLoggingProcessName = [processName copy]; +} + ++ (NSString *)loggingProcessName { + // get the process name (once per run) replacing spaces with underscores + if (!gLoggingProcessName) { + NSString *procName = [[NSProcessInfo processInfo] processName]; + gLoggingProcessName = [procName stringByReplacingOccurrencesOfString:@" " withString:@"_"]; + } + return gLoggingProcessName; +} + ++ (void)setLoggingDateStamp:(NSString *)dateStamp { + gLoggingDateStamp = [dateStamp copy]; +} + ++ (NSString *)loggingDateStamp { + // We'll pick one date stamp per run, so a run that starts at a later second + // will get a unique results html file + if (!gLoggingDateStamp) { + // produce a string like 08-21_01-41-23PM + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setFormatterBehavior:NSDateFormatterBehavior10_4]; + [formatter setDateFormat:@"M-dd_hh-mm-ssa"]; + + gLoggingDateStamp = [formatter stringFromDate:[NSDate date]]; + } + return gLoggingDateStamp; +} + ++ (NSString *)processNameLogPrefix { + static NSString *gPrefix = nil; + if (!gPrefix) { + NSString *processName = [self loggingProcessName]; + gPrefix = [[NSString alloc] initWithFormat:@"%@_log_", processName]; + } + return gPrefix; +} + ++ (NSString *)symlinkNameSuffix { + return @"_log_newest.html"; +} + ++ (NSString *)htmlFileName { + return @"aperçu_http_log.html"; +} + ++ (void)deleteLogDirectoriesOlderThanDate:(NSDate *)cutoffDate { + NSFileManager *fileMgr = [NSFileManager defaultManager]; + NSURL *parentDir = [NSURL fileURLWithPath:[[self class] loggingDirectory]]; + NSURL *logDirectoryForCurrentRun = + [NSURL fileURLWithPath:[[self class] logDirectoryForCurrentRun]]; + NSError *error; + NSArray *contents = [fileMgr contentsOfDirectoryAtURL:parentDir + includingPropertiesForKeys:@[ NSURLContentModificationDateKey ] + options:0 + error:&error]; + for (NSURL *itemURL in contents) { + if ([itemURL isEqual:logDirectoryForCurrentRun]) continue; + + NSDate *modDate; + if ([itemURL getResourceValue:&modDate + forKey:NSURLContentModificationDateKey + error:&error]) { + if ([modDate compare:cutoffDate] == NSOrderedAscending) { + if (![fileMgr removeItemAtURL:itemURL error:&error]) { + NSLog(@"deleteLogDirectoriesOlderThanDate failed to delete %@: %@", + itemURL.path, error); + } + } + } else { + NSLog(@"deleteLogDirectoriesOlderThanDate failed to get mod date of %@: %@", + itemURL.path, error); + } + } +} + +// formattedStringFromData returns a prettyprinted string for XML or JSON input, +// and a plain string for other input data +- (NSString *)formattedStringFromData:(NSData *)inputData + contentType:(NSString *)contentType + JSON:(NSDictionary **)outJSON { + if (!inputData) return nil; + + // if the content type is JSON and we have the parsing class available, use that + if ([contentType hasPrefix:@"application/json"] && inputData.length > 5) { + // convert from JSON string to NSObjects and back to a formatted string + NSMutableDictionary *obj = [NSJSONSerialization JSONObjectWithData:inputData + options:NSJSONReadingMutableContainers + error:NULL]; + if (obj) { + if (outJSON) *outJSON = obj; + if ([obj isKindOfClass:[NSMutableDictionary class]]) { + // for security and privacy, omit OAuth 2 response access and refresh tokens + if ([obj valueForKey:@"refresh_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"refresh_token"]; + } + if ([obj valueForKey:@"access_token"] != nil) { + [obj setObject:@"_snip_" forKey:@"access_token"]; + } + } + NSData *data = [NSJSONSerialization dataWithJSONObject:obj + options:NSJSONWritingPrettyPrinted + error:NULL]; + if (data) { + NSString *jsonStr = [[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding]; + return jsonStr; + } + } + } + +#if !TARGET_OS_IPHONE && !GTM_SKIP_LOG_XMLFORMAT + // verify that this data starts with the bytes indicating XML + + NSString *const kXMLLintPath = @"/usr/bin/xmllint"; + static BOOL gHasCheckedAvailability = NO; + static BOOL gIsXMLLintAvailable = NO; + + if (!gHasCheckedAvailability) { + gIsXMLLintAvailable = [[NSFileManager defaultManager] fileExistsAtPath:kXMLLintPath]; + gHasCheckedAvailability = YES; + } + if (gIsXMLLintAvailable + && inputData.length > 5 + && strncmp(inputData.bytes, " 0) { + // success + inputData = formattedData; + } + } +#else + // we can't call external tasks on the iPhone; leave the XML unformatted +#endif + + NSString *dataStr = [[NSString alloc] initWithData:inputData + encoding:NSUTF8StringEncoding]; + return dataStr; +} + +// stringFromStreamData creates a string given the supplied data +// +// If NSString can create a UTF-8 string from the data, then that is returned. +// +// Otherwise, this routine tries to find a MIME boundary at the beginning of the data block, and +// uses that to break up the data into parts. Each part will be used to try to make a UTF-8 string. +// For parts that fail, a replacement string showing the part header and <> is supplied +// in place of the binary data. + +- (NSString *)stringFromStreamData:(NSData *)data + contentType:(NSString *)contentType { + + if (!data) return nil; + + // optimistically, see if the whole data block is UTF-8 + NSString *streamDataStr = [self formattedStringFromData:data + contentType:contentType + JSON:NULL]; + if (streamDataStr) return streamDataStr; + + // Munge a buffer by replacing non-ASCII bytes with underscores, and turn that munged buffer an + // NSString. That gives us a string we can use with NSScanner. + NSMutableData *mutableData = [NSMutableData dataWithData:data]; + unsigned char *bytes = (unsigned char *)mutableData.mutableBytes; + + for (unsigned int idx = 0; idx < mutableData.length; ++idx) { + if (bytes[idx] > 0x7F || bytes[idx] == 0) { + bytes[idx] = '_'; + } + } + + NSString *mungedStr = [[NSString alloc] initWithData:mutableData + encoding:NSUTF8StringEncoding]; + if (mungedStr) { + + // scan for the boundary string + NSString *boundary = nil; + NSScanner *scanner = [NSScanner scannerWithString:mungedStr]; + + if ([scanner scanUpToString:@"\r\n" intoString:&boundary] + && [boundary hasPrefix:@"--"]) { + + // we found a boundary string; use it to divide the string into parts + NSArray *mungedParts = [mungedStr componentsSeparatedByString:boundary]; + + // look at each munged part in the original string, and try to convert those into UTF-8 + NSMutableArray *origParts = [NSMutableArray array]; + NSUInteger offset = 0; + for (NSString *mungedPart in mungedParts) { + NSUInteger partSize = mungedPart.length; + NSData *origPartData = [data subdataWithRange:NSMakeRange(offset, partSize)]; + NSString *origPartStr = [[NSString alloc] initWithData:origPartData + encoding:NSUTF8StringEncoding]; + if (origPartStr) { + // we could make this original part into UTF-8; use the string + [origParts addObject:origPartStr]; + } else { + // this part can't be made into UTF-8; scan the header, if we can + NSString *header = nil; + NSScanner *headerScanner = [NSScanner scannerWithString:mungedPart]; + if (![headerScanner scanUpToString:@"\r\n\r\n" intoString:&header]) { + // we couldn't find a header + header = @""; + } + // make a part string with the header and <> + NSString *binStr = [NSString stringWithFormat:@"\r%@\r<<%lu bytes>>\r", + header, (long)(partSize - header.length)]; + [origParts addObject:binStr]; + } + offset += partSize + boundary.length; + } + // rejoin the original parts + streamDataStr = [origParts componentsJoinedByString:boundary]; + } + } + if (!streamDataStr) { + // give up; just make a string showing the uploaded bytes + streamDataStr = [NSString stringWithFormat:@"<<%u bytes>>", (unsigned int)data.length]; + } + return streamDataStr; +} + +// logFetchWithError is called following a successful or failed fetch attempt +// +// This method does all the work for appending to and creating log files + +- (void)logFetchWithError:(NSError *)error { + if (![[self class] isLoggingEnabled]) return; + NSString *logDirectory = [[self class] logDirectoryForCurrentRun]; + if (!logDirectory) return; + NSString *processName = [[self class] loggingProcessName]; + + // TODO: add Javascript to display response data formatted in hex + + // each response's NSData goes into its own xml or txt file, though all responses for this run of + // the app share a main html file. This counter tracks all fetch responses for this app run. + // + // we'll use a local variable since this routine may be reentered while waiting for XML formatting + // to be completed by an external task + static int gResponseCounter = 0; + int responseCounter = ++gResponseCounter; + + NSURLResponse *response = [self response]; + NSDictionary *responseHeaders = [self responseHeaders]; + NSString *responseDataStr = nil; + NSDictionary *responseJSON = nil; + + // if there's response data, decide what kind of file to put it in based on the first bytes of the + // file or on the mime type supplied by the server + NSString *responseMIMEType = [response MIMEType]; + BOOL isResponseImage = NO; + + // file name for an image data file + NSString *responseDataFileName = nil; + + int64_t responseDataLength = self.downloadedLength; + if (responseDataLength > 0) { + NSData *downloadedData = self.downloadedData; + if (downloadedData == nil + && responseDataLength > 0 + && responseDataLength < 20000 + && self.destinationFileURL) { + // There's a download file that's not too big, so get the data to display from the downloaded + // file. + NSURL *destinationURL = self.destinationFileURL; + downloadedData = [NSData dataWithContentsOfURL:destinationURL]; + } + NSString *responseType = [responseHeaders valueForKey:@"Content-Type"]; + responseDataStr = [self formattedStringFromData:downloadedData + contentType:responseType + JSON:&responseJSON]; + NSString *responseDataExtn = nil; + NSData *dataToWrite = nil; + if (responseDataStr) { + // we were able to make a UTF-8 string from the response data + if ([responseMIMEType isEqual:@"application/atom+xml"] + || [responseMIMEType hasSuffix:@"/xml"]) { + responseDataExtn = @"xml"; + dataToWrite = [responseDataStr dataUsingEncoding:NSUTF8StringEncoding]; + } + } else if ([responseMIMEType isEqual:@"image/jpeg"]) { + responseDataExtn = @"jpg"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/gif"]) { + responseDataExtn = @"gif"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else if ([responseMIMEType isEqual:@"image/png"]) { + responseDataExtn = @"png"; + dataToWrite = downloadedData; + isResponseImage = YES; + } else { + // add more non-text types here + } + // if we have an extension, save the raw data in a file with that extension + if (responseDataExtn && dataToWrite) { + // generate a response file base name like + NSString *responseBaseName = [NSString stringWithFormat:@"fetch_%d_response", responseCounter]; + responseDataFileName = [responseBaseName stringByAppendingPathExtension:responseDataExtn]; + NSString *responseDataFilePath = [logDirectory stringByAppendingPathComponent:responseDataFileName]; + + NSError *downloadedError = nil; + if (gIsLoggingToFile && ![dataToWrite writeToFile:responseDataFilePath + options:0 + error:&downloadedError]) { + NSLog(@"%@ logging write error:%@ (%@)", [self class], downloadedError, responseDataFileName); + } + } + } + // we'll have one main html file per run of the app + NSString *htmlName = [[self class] htmlFileName]; + NSString *htmlPath =[logDirectory stringByAppendingPathComponent:htmlName]; + + // if the html file exists (from logging previous fetches) we don't need + // to re-write the header or the scripts + NSFileManager *fileMgr = [NSFileManager defaultManager]; + BOOL didFileExist = [fileMgr fileExistsAtPath:htmlPath]; + + NSMutableString* outputHTML = [NSMutableString string]; + + // we need a header to say we'll have UTF-8 text + if (!didFileExist) { + [outputHTML appendFormat:@"%@ HTTP fetch log %@", + processName, [[self class] loggingDateStamp]]; + } + // now write the visible html elements + NSString *copyableFileName = [NSString stringWithFormat:@"fetch_%d.txt", responseCounter]; + + NSDate *now = [NSDate date]; + // write the date & time, the comment, and the link to the plain-text (copyable) log + [outputHTML appendFormat:@"%@      ", now]; + + NSString *comment = [self comment]; + if (comment.length > 0) { + [outputHTML appendFormat:@"%@      ", comment]; + } + [outputHTML appendFormat:@"request/response log
", copyableFileName]; + NSTimeInterval elapsed = -self.initialBeginFetchDate.timeIntervalSinceNow; + [outputHTML appendFormat:@"elapsed: %5.3fsec
", elapsed]; + + // write the request URL + NSURLRequest *request = self.request; + NSString *requestMethod = request.HTTPMethod; + NSURL *requestURL = request.URL; + + // Save the request URL for next time in case this redirects. + NSString *redirectedFromURLString = [self.redirectedFromURL absoluteString]; + self.redirectedFromURL = [requestURL copy]; + if (redirectedFromURLString) { + [outputHTML appendFormat:@"redirected from %@
", + redirectedFromURLString]; + } + [outputHTML appendFormat:@"request: %@ %@
\n", requestMethod, requestURL]; + + // write the request headers + NSDictionary *requestHeaders = request.allHTTPHeaderFields; + NSUInteger numberOfRequestHeaders = requestHeaders.count; + if (numberOfRequestHeaders > 0) { + // Indicate if the request is authorized; warn if the request is authorized but non-SSL + NSString *auth = [requestHeaders objectForKey:@"Authorization"]; + NSString *headerDetails = @""; + if (auth) { + BOOL isInsecure = [[requestURL scheme] isEqual:@"http"]; + if (isInsecure) { + // 26A0 = ⚠ + headerDetails = + @"   authorized, non-SSL "; + } else { + headerDetails = @"   authorized"; + } + } + NSString *cookiesHdr = [requestHeaders objectForKey:@"Cookie"]; + if (cookiesHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   cookies"]; + } + NSString *matchHdr = [requestHeaders objectForKey:@"If-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   if-match"]; + } + matchHdr = [requestHeaders objectForKey:@"If-None-Match"]; + if (matchHdr) { + headerDetails = [headerDetails stringByAppendingString:@"   if-none-match"]; + } + [outputHTML appendFormat:@"   headers: %d %@
", + (int)numberOfRequestHeaders, headerDetails]; + } else { + [outputHTML appendFormat:@"   headers: none
"]; + } + // write the request post data + NSData *bodyData = nil; + NSData *loggedStreamData = self.loggedStreamData; + if (loggedStreamData) { + bodyData = loggedStreamData; + } else { + bodyData = self.bodyData; + if (bodyData == nil) { + bodyData = self.request.HTTPBody; + } + } + uint64_t bodyDataLength = bodyData.length; + + if (bodyData.length == 0) { + // If the data is in a body upload file URL, read that in if it's not huge. + NSURL *bodyFileURL = self.bodyFileURL; + if (bodyFileURL) { + NSNumber *fileSizeNum = nil; + NSError *fileSizeError = nil; + if ([bodyFileURL getResourceValue:&fileSizeNum + forKey:NSURLFileSizeKey + error:&fileSizeError]) { + bodyDataLength = [fileSizeNum unsignedLongLongValue]; + if (bodyDataLength > 0 && bodyDataLength < 50000) { + bodyData = [NSData dataWithContentsOfURL:bodyFileURL + options:NSDataReadingUncached + error:&fileSizeError]; + } + } + } + } + NSString *bodyDataStr = nil; + NSString *postType = [requestHeaders valueForKey:@"Content-Type"]; + + if (bodyDataLength > 0) { + [outputHTML appendFormat:@"   data: %llu bytes, %@
\n", + bodyDataLength, postType ? postType : @"(no type)"]; + NSString *logRequestBody = self.logRequestBody; + if (logRequestBody) { + bodyDataStr = [logRequestBody copy]; + self.logRequestBody = nil; + } else { + bodyDataStr = [self stringFromStreamData:bodyData + contentType:postType]; + if (bodyDataStr) { + // remove OAuth 2 client secret and refresh token + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"client_secret=" + endString:@"&"]; + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"refresh_token=" + endString:@"&"]; + // remove ClientLogin password + bodyDataStr = [[self class] snipSubstringOfString:bodyDataStr + betweenStartString:@"&Passwd=" + endString:@"&"]; + } + } + } else { + // no post data + } + // write the response status, MIME type, URL + NSInteger status = [self statusCode]; + if (response) { + NSString *statusString = @""; + if (status != 0) { + if (status == 200 || status == 201) { + statusString = [NSString stringWithFormat:@"%ld", (long)status]; + + // report any JSON-RPC error + if ([responseJSON isKindOfClass:[NSDictionary class]]) { + NSDictionary *jsonError = [responseJSON objectForKey:@"error"]; + if ([jsonError isKindOfClass:[NSDictionary class]]) { + NSString *jsonCode = [[jsonError valueForKey:@"code"] description]; + NSString *jsonMessage = [jsonError valueForKey:@"message"]; + if (jsonCode || jsonMessage) { + // 2691 = ⚑ + NSString *const jsonErrFmt = + @"   JSON error: %@ %@  ⚑"; + statusString = [statusString stringByAppendingFormat:jsonErrFmt, + jsonCode ? jsonCode : @"", + jsonMessage ? jsonMessage : @""]; + } + } + } + } else { + // purple for anything other than 200 or 201 + NSString *flag = status >= 400 ? @" ⚑" : @""; // 2691 = ⚑ + NSString *explanation = [NSHTTPURLResponse localizedStringForStatusCode:status]; + NSString *const statusFormat = @"%ld %@ %@"; + statusString = [NSString stringWithFormat:statusFormat, (long)status, explanation, flag]; + } + } + // show the response URL only if it's different from the request URL + NSString *responseURLStr = @""; + NSURL *responseURL = response.URL; + + if (responseURL && ![responseURL isEqual:request.URL]) { + NSString *const responseURLFormat = + @"response URL: %@
\n"; + responseURLStr = [NSString stringWithFormat:responseURLFormat, [responseURL absoluteString]]; + } + [outputHTML appendFormat:@"response:  status %@
\n%@", + statusString, responseURLStr]; + // Write the response headers + NSUInteger numberOfResponseHeaders = responseHeaders.count; + if (numberOfResponseHeaders > 0) { + // Indicate if the server is setting cookies + NSString *cookiesSet = [responseHeaders valueForKey:@"Set-Cookie"]; + NSString *cookiesStr = + cookiesSet ? @"  sets cookies" : @""; + // Indicate if the server is redirecting + NSString *location = [responseHeaders valueForKey:@"Location"]; + BOOL isRedirect = status >= 300 && status <= 399 && location != nil; + NSString *redirectsStr = + isRedirect ? @"  redirects" : @""; + [outputHTML appendFormat:@"   headers: %d %@ %@
\n", + (int)numberOfResponseHeaders, cookiesStr, redirectsStr]; + } else { + [outputHTML appendString:@"   headers: none
\n"]; + } + } + // error + if (error) { + [outputHTML appendFormat:@"Error: %@
\n", error.description]; + } + // Write the response data + if (responseDataFileName) { + if (isResponseImage) { + // Make a small inline image that links to the full image file + [outputHTML appendFormat:@"   data: %lld bytes, %@
", + responseDataLength, responseMIMEType]; + NSString *const fmt = + @"image\n"; + [outputHTML appendFormat:fmt, responseDataFileName, responseDataFileName]; + } else { + // The response data was XML; link to the xml file + NSString *const fmt = + @"   data: %lld bytes, %@   %@\n"; + [outputHTML appendFormat:fmt, responseDataLength, responseMIMEType, + responseDataFileName, [responseDataFileName pathExtension]]; + } + } else { + // The response data was not an image; just show the length and MIME type + [outputHTML appendFormat:@"   data: %lld bytes, %@\n", + responseDataLength, responseMIMEType ? responseMIMEType : @"(no response type)"]; + } + // Make a single string of the request and response, suitable for copying + // to the clipboard and pasting into a bug report + NSMutableString *copyable = [NSMutableString string]; + if (comment) { + [copyable appendFormat:@"%@\n\n", comment]; + } + [copyable appendFormat:@"%@ elapsed: %5.3fsec\n", now, elapsed]; + if (redirectedFromURLString) { + [copyable appendFormat:@"Redirected from %@\n", redirectedFromURLString]; + } + [copyable appendFormat:@"Request: %@ %@\n", requestMethod, requestURL]; + if (requestHeaders.count > 0) { + [copyable appendFormat:@"Request headers:\n%@\n", + [[self class] headersStringForDictionary:requestHeaders]]; + } + if (bodyDataLength > 0) { + [copyable appendFormat:@"Request body: (%llu bytes)\n", bodyDataLength]; + if (bodyDataStr) { + [copyable appendFormat:@"%@\n", bodyDataStr]; + } + [copyable appendString:@"\n"]; + } + if (response) { + [copyable appendFormat:@"Response: status %d\n", (int) status]; + [copyable appendFormat:@"Response headers:\n%@\n", + [[self class] headersStringForDictionary:responseHeaders]]; + [copyable appendFormat:@"Response body: (%lld bytes)\n", responseDataLength]; + if (responseDataLength > 0) { + NSString *logResponseBody = self.logResponseBody; + if (logResponseBody) { + // The user has provided the response body text. + responseDataStr = [logResponseBody copy]; + self.logResponseBody = nil; + } + if (responseDataStr != nil) { + [copyable appendFormat:@"%@\n", responseDataStr]; + } else { + // Even though it's redundant, we'll put in text to indicate that all the bytes are binary. + if (self.destinationFileURL) { + [copyable appendFormat:@"<<%lld bytes>> to file %@\n", + responseDataLength, self.destinationFileURL.path]; + } else { + [copyable appendFormat:@"<<%lld bytes>>\n", responseDataLength]; + } + } + } + } + if (error) { + [copyable appendFormat:@"Error: %@\n", error]; + } + // Save to log property before adding the separator + self.log = copyable; + + [copyable appendString:@"-----------------------------------------------------------\n"]; + + // Write the copyable version to another file (linked to at the top of the html file, above) + // + // Ideally, something to just copy this to the clipboard like + // Copy here." + // would work everywhere, but it only works in Safari as of 8/2010 + if (gIsLoggingToFile) { + NSString *parentDir = [[self class] loggingDirectory]; + NSString *copyablePath = [logDirectory stringByAppendingPathComponent:copyableFileName]; + NSError *copyableError = nil; + if (![copyable writeToFile:copyablePath + atomically:NO + encoding:NSUTF8StringEncoding + error:©ableError]) { + // Error writing to file + NSLog(@"%@ logging write error:%@ (%@)", [self class], copyableError, copyablePath); + } + [outputHTML appendString:@"

"]; + + // Append the HTML to the main output file + const char* htmlBytes = outputHTML.UTF8String; + NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:htmlPath + append:YES]; + [stream open]; + [stream write:(const uint8_t *) htmlBytes maxLength:strlen(htmlBytes)]; + [stream close]; + + // Make a symlink to the latest html + NSString *const symlinkNameSuffix = [[self class] symlinkNameSuffix]; + NSString *symlinkName = [processName stringByAppendingString:symlinkNameSuffix]; + NSString *symlinkPath = [parentDir stringByAppendingPathComponent:symlinkName]; + + [fileMgr removeItemAtPath:symlinkPath error:NULL]; + [fileMgr createSymbolicLinkAtPath:symlinkPath + withDestinationPath:htmlPath + error:NULL]; +#if TARGET_OS_IPHONE + static BOOL gReportedLoggingPath = NO; + if (!gReportedLoggingPath) { + gReportedLoggingPath = YES; + NSLog(@"GTMSessionFetcher logging to \"%@\"", parentDir); + } +#endif + } +} + +- (NSInputStream *)loggedInputStreamForInputStream:(NSInputStream *)inputStream { + if (!inputStream) return nil; + if (![GTMSessionFetcher isLoggingEnabled]) return inputStream; + + [self clearLoggedStreamData]; // Clear any previous data. + Class monitorClass = NSClassFromString(@"GTMReadMonitorInputStream"); + if (!monitorClass) { + NSString const *str = @"<>"; + NSData *stringData = [str dataUsingEncoding:NSUTF8StringEncoding]; + [self appendLoggedStreamData:stringData]; + return inputStream; + } + inputStream = [monitorClass inputStreamWithStream:inputStream]; + + GTMReadMonitorInputStream *readMonitorInputStream = (GTMReadMonitorInputStream *)inputStream; + [readMonitorInputStream setReadDelegate:self]; + SEL readSel = @selector(inputStream:readIntoBuffer:length:); + [readMonitorInputStream setReadSelector:readSel]; + + return inputStream; +} + +- (GTMSessionFetcherBodyStreamProvider)loggedStreamProviderForStreamProvider: + (GTMSessionFetcherBodyStreamProvider)streamProvider { + if (!streamProvider) return nil; + if (![GTMSessionFetcher isLoggingEnabled]) return streamProvider; + + [self clearLoggedStreamData]; // Clear any previous data. + Class monitorClass = NSClassFromString(@"GTMReadMonitorInputStream"); + if (!monitorClass) { + NSString const *str = @"<>"; + NSData *stringData = [str dataUsingEncoding:NSUTF8StringEncoding]; + [self appendLoggedStreamData:stringData]; + return streamProvider; + } + GTMSessionFetcherBodyStreamProvider loggedStreamProvider = + ^(GTMSessionFetcherBodyStreamProviderResponse response) { + streamProvider(^(NSInputStream *bodyStream) { + bodyStream = [self loggedInputStreamForInputStream:bodyStream]; + response(bodyStream); + }); + }; + return loggedStreamProvider; +} + +@end + +@implementation GTMSessionFetcher (GTMSessionFetcherLoggingUtilities) + +- (void)inputStream:(GTMReadMonitorInputStream *)stream + readIntoBuffer:(void *)buffer + length:(int64_t)length { + // append the captured data + NSData *data = [NSData dataWithBytesNoCopy:buffer + length:(NSUInteger)length + freeWhenDone:NO]; + [self appendLoggedStreamData:data]; +} + +#pragma mark Fomatting Utilities + ++ (NSString *)snipSubstringOfString:(NSString *)originalStr + betweenStartString:(NSString *)startStr + endString:(NSString *)endStr { +#if SKIP_GTM_FETCH_LOGGING_SNIPPING + return originalStr; +#else + if (!originalStr) return nil; + + // Find the start string, and replace everything between it + // and the end string (or the end of the original string) with "_snip_" + NSRange startRange = [originalStr rangeOfString:startStr]; + if (startRange.location == NSNotFound) return originalStr; + + // We found the start string + NSUInteger originalLength = originalStr.length; + NSUInteger startOfTarget = NSMaxRange(startRange); + NSRange targetAndRest = NSMakeRange(startOfTarget, originalLength - startOfTarget); + NSRange endRange = [originalStr rangeOfString:endStr + options:0 + range:targetAndRest]; + NSRange replaceRange; + if (endRange.location == NSNotFound) { + // Found no end marker so replace to end of string + replaceRange = targetAndRest; + } else { + // Replace up to the endStr + replaceRange = NSMakeRange(startOfTarget, endRange.location - startOfTarget); + } + NSString *result = [originalStr stringByReplacingCharactersInRange:replaceRange + withString:@"_snip_"]; + return result; +#endif // SKIP_GTM_FETCH_LOGGING_SNIPPING +} + ++ (NSString *)headersStringForDictionary:(NSDictionary *)dict { + // Format the dictionary in http header style, like + // Accept: application/json + // Cache-Control: no-cache + // Content-Type: application/json; charset=utf-8 + // + // Pad the key names, but not beyond 16 chars, since long custom header + // keys just create too much whitespace + NSArray *keys = [dict.allKeys sortedArrayUsingSelector:@selector(compare:)]; + + NSMutableString *str = [NSMutableString string]; + for (NSString *key in keys) { + NSString *value = [dict valueForKey:key]; + if ([key isEqual:@"Authorization"]) { + // Remove OAuth 1 token + value = [[self class] snipSubstringOfString:value + betweenStartString:@"oauth_token=\"" + endString:@"\""]; + + // Remove OAuth 2 bearer token (draft 16, and older form) + value = [[self class] snipSubstringOfString:value + betweenStartString:@"Bearer " + endString:@"\n"]; + value = [[self class] snipSubstringOfString:value + betweenStartString:@"OAuth " + endString:@"\n"]; + + // Remove Google ClientLogin + value = [[self class] snipSubstringOfString:value + betweenStartString:@"GoogleLogin auth=" + endString:@"\n"]; + } + [str appendFormat:@" %@: %@\n", key, value]; + } + return str; +} + +@end + +#endif // !STRIP_GTM_FETCH_LOGGING diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h new file mode 100644 index 0000000..fb743ca --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.h @@ -0,0 +1,193 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// For best performance and convenient usage, fetchers should be generated by a common +// GTMSessionFetcherService instance, like +// +// _fetcherService = [[GTMSessionFetcherService alloc] init]; +// GTMSessionFetcher* myFirstFetcher = [_fetcherService fetcherWithRequest:request1]; +// GTMSessionFetcher* mySecondFetcher = [_fetcherService fetcherWithRequest:request2]; + +#import "GTMSessionFetcher.h" + +GTM_ASSUME_NONNULL_BEGIN + +// Notifications. + +// This notification indicates a reusable session has become invalid. It is intended mainly for the +// service's unit tests. +// +// The notification object is the fetcher service. +// The invalid session is provided via the userInfo kGTMSessionFetcherServiceSessionKey key. +extern NSString *const kGTMSessionFetcherServiceSessionBecameInvalidNotification; +extern NSString *const kGTMSessionFetcherServiceSessionKey; + +@interface GTMSessionFetcherService : NSObject + +// Queues of delayed and running fetchers. Each dictionary contains arrays +// of GTMSessionFetcher *fetchers, keyed by NSString *host +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSArray *) *delayedFetchersByHost; +@property(atomic, strong, readonly, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, NSArray *) *runningFetchersByHost; + +// A max value of 0 means no fetchers should be delayed. +// The default limit is 10 simultaneous fetchers targeting each host. +// This does not apply to fetchers whose useBackgroundSession property is YES. Since services are +// not resurrected on an app relaunch, delayed fetchers would effectively be abandoned. +@property(atomic, assign) NSUInteger maxRunningFetchersPerHost; + +// Properties to be applied to each fetcher; see GTMSessionFetcher.h for descriptions +@property(atomic, strong, GTM_NULLABLE) NSURLSessionConfiguration *configuration; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherConfigurationBlock configurationBlock; +@property(atomic, strong, GTM_NULLABLE) NSHTTPCookieStorage *cookieStorage; +@property(atomic, strong, GTM_NULL_RESETTABLE) dispatch_queue_t callbackQueue; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherChallengeBlock challengeBlock; +@property(atomic, strong, GTM_NULLABLE) NSURLCredential *credential; +@property(atomic, strong) NSURLCredential *proxyCredential; +@property(atomic, copy, GTM_NULLABLE) GTM_NSArrayOf(NSString *) *allowedInsecureSchemes; +@property(atomic, assign) BOOL allowLocalhostRequest; +@property(atomic, assign) BOOL allowInvalidServerCertificates; +@property(atomic, assign, getter=isRetryEnabled) BOOL retryEnabled; +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherRetryBlock retryBlock; +@property(atomic, assign) NSTimeInterval maxRetryInterval; +@property(atomic, assign) NSTimeInterval minRetryInterval; +@property(atomic, copy, GTM_NULLABLE) GTM_NSDictionaryOf(NSString *, id) *properties; + +#if GTM_BACKGROUND_TASK_FETCHING +@property(atomic, assign) BOOL skipBackgroundTask; +#endif + +// A default useragent of GTMFetcherStandardUserAgentString(nil) will be given to each fetcher +// created by this service unless the request already has a user-agent header set. +// This default will be added starting with builds with the SDKs for OS X 10.11 and iOS 9. +// +// To use the configuration's default user agent, set this property to nil. +@property(atomic, copy, GTM_NULLABLE) NSString *userAgent; + +// The authorizer to attach to the created fetchers. If a specific fetcher should +// not authorize its requests, the fetcher's authorizer property may be set to nil +// before the fetch begins. +@property(atomic, strong, GTM_NULLABLE) id authorizer; + +// Delegate queue used by the session when calling back to the fetcher. The default +// is the main queue. Changing this does not affect the queue used to call back to the +// application; that is specified by the callbackQueue property above. +@property(atomic, strong, GTM_NULL_RESETTABLE) NSOperationQueue *sessionDelegateQueue; + +// When enabled, indicates the same session should be used by subsequent fetchers. +// +// This is enabled by default. +@property(atomic, assign) BOOL reuseSession; + +// Sets the delay until an unused session is invalidated. +// The default interval is 60 seconds. +// +// If the interval is set to 0, then any reused session is not invalidated except by +// explicitly invoking -resetSession. Be aware that setting the interval to 0 thus +// causes the session's delegate to be retained until the session is explicitly reset. +@property(atomic, assign) NSTimeInterval unusedSessionTimeout; + +// If shouldReuseSession is enabled, this will force creation of a new session when future +// fetchers begin. +- (void)resetSession; + +// Create a fetcher +// +// These methods will return a fetcher. If successfully created, the connection +// will hold a strong reference to it for the life of the connection as well. +// So the caller doesn't have to hold onto the fetcher explicitly unless they +// want to be able to monitor or cancel it. +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request; +- (GTMSessionFetcher *)fetcherWithURL:(NSURL *)requestURL; +- (GTMSessionFetcher *)fetcherWithURLString:(NSString *)requestURLString; + +// Common method for fetcher creation. +// +// -fetcherWithRequest:fetcherClass: may be overridden to customize creation of +// fetchers. This is the ONLY method in the GTMSessionFetcher library intended to +// be overridden. +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass; + +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher; + +- (NSUInteger)numberOfFetchers; // running + delayed fetchers +- (NSUInteger)numberOfRunningFetchers; +- (NSUInteger)numberOfDelayedFetchers; + +// Return a list of all running or delayed fetchers. This includes fetchers created +// by the service which have been started and have not yet stopped. +// +// Returns an array of fetcher objects, or nil if none. +- (GTM_NULLABLE GTM_NSArrayOf(GTMSessionFetcher *) *)issuedFetchers; + +// Search for running or delayed fetchers with the specified URL. +// +// Returns an array of fetcher objects found, or nil if none found. +- (GTM_NULLABLE GTM_NSArrayOf(GTMSessionFetcher *) *)issuedFetchersWithRequestURL:(NSURL *)requestURL; + +- (void)stopAllFetchers; + +// Methods for use by the fetcher class only. +- (GTM_NULLABLE NSURLSession *)session; +- (GTM_NULLABLE NSURLSession *)sessionForFetcherCreation; +- (GTM_NULLABLE id)sessionDelegate; +- (GTM_NULLABLE NSDate *)stoppedAllFetchersDate; + +// The testBlock can inspect its fetcher parameter's request property to +// determine which fetcher is being faked. +@property(atomic, copy, GTM_NULLABLE) GTMSessionFetcherTestBlock testBlock; + +@end + +@interface GTMSessionFetcherService (TestingSupport) + +// Convenience methods to create a fetcher service for testing. +// +// Fetchers generated by this mock fetcher service will not perform any +// network operation, but will invoke callbacks and provide the supplied data +// or error to the completion handler. +// +// You can make more customized mocks by setting the test block property of the service +// or fetcher; the test block can inspect the fetcher's request or other properties. +// +// See the description of the testBlock property below. ++ (instancetype)mockFetcherServiceWithFakedData:(GTM_NULLABLE NSData *)fakedDataOrNil + fakedError:(GTM_NULLABLE NSError *)fakedErrorOrNil; ++ (instancetype)mockFetcherServiceWithFakedData:(GTM_NULLABLE NSData *)fakedDataOrNil + fakedResponse:(NSHTTPURLResponse *)fakedResponse + fakedError:(GTM_NULLABLE NSError *)fakedErrorOrNil; + +// Spin the run loop and discard events (or, if not on the main thread, just sleep the thread) +// until all running and delayed fetchers have completed. +// +// This is only for use in testing or in tools without a user interface. +// +// Synchronous fetches should never be done by shipping apps; they are +// sufficient reason for rejection from the app store. +// +// Returns NO if timed out. +- (BOOL)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds; + +@end + +@interface GTMSessionFetcherService (BackwardsCompatibilityOnly) + +// Clients using GTMSessionFetcher should set the cookie storage explicitly themselves. +// This method is just for compatibility with the old fetcher. +@property(atomic, assign) NSInteger cookieStorageMethod; + +@end + +GTM_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m new file mode 100644 index 0000000..bd44787 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionFetcherService.m @@ -0,0 +1,1369 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionFetcherService.h" + +NSString *const kGTMSessionFetcherServiceSessionBecameInvalidNotification + = @"kGTMSessionFetcherServiceSessionBecameInvalidNotification"; +NSString *const kGTMSessionFetcherServiceSessionKey + = @"kGTMSessionFetcherServiceSessionKey"; + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (ServiceMethods) +- (BOOL)beginFetchMayDelay:(BOOL)mayDelay + mayAuthorize:(BOOL)mayAuthorize; +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionFetcherService () + +@property(atomic, strong, readwrite) NSDictionary *delayedFetchersByHost; +@property(atomic, strong, readwrite) NSDictionary *runningFetchersByHost; + +@end + +// Since NSURLSession doesn't support a separate delegate per task (!), instances of this +// class serve as a session delegate trampoline. +// +// This class maps a session's tasks to fetchers, and resends delegate messages to the task's +// fetcher. +@interface GTMSessionFetcherSessionDelegateDispatcher : NSObject + +// The session for the tasks in this dispatcher's task-to-fetcher map. +@property(atomic) NSURLSession *session; + +// The timer interval for invalidating a session that has no active tasks. +@property(atomic) NSTimeInterval discardInterval; + +// The current discard timer. +@property(atomic, readonly) NSTimer *discardTimer; + + +- (instancetype)initWithParentService:(GTMSessionFetcherService *)parentService + sessionDiscardInterval:(NSTimeInterval)discardInterval; + +- (void)setFetcher:(GTMSessionFetcher *)fetcher + forTask:(NSURLSessionTask *)task; +- (void)removeFetcher:(GTMSessionFetcher *)fetcher; + +// Before using a session, tells the delegate dispatcher to stop the discard timer. +- (void)startSessionUsage; + +// When abandoning a delegate dispatcher, we want to avoid the session retaining +// the delegate after tasks complete. +- (void)abandon; + +@end + + +@implementation GTMSessionFetcherService { + NSMutableDictionary *_delayedFetchersByHost; + NSMutableDictionary *_runningFetchersByHost; + NSUInteger _maxRunningFetchersPerHost; + + // When this ivar is nil, the service will not reuse sessions. + GTMSessionFetcherSessionDelegateDispatcher *_delegateDispatcher; + + // Fetchers will wait on this if another fetcher is creating the shared NSURLSession. + dispatch_semaphore_t _sessionCreationSemaphore; + + dispatch_queue_t _callbackQueue; + NSOperationQueue *_delegateQueue; + NSHTTPCookieStorage *_cookieStorage; + NSString *_userAgent; + NSTimeInterval _timeout; + + NSURLCredential *_credential; // Username & password. + NSURLCredential *_proxyCredential; // Credential supplied to proxy servers. + + NSInteger _cookieStorageMethod; + + id _authorizer; + + // For waitForCompletionOfAllFetchersWithTimeout: we need to wait on stopped fetchers since + // they've not yet finished invoking their queued callbacks. This array is nil except when + // waiting on fetchers. + NSMutableArray *_stoppedFetchersToWaitFor; + + // For fetchers that enqueued their callbacks before stopAllFetchers was called on the service, + // set a barrier so the callbacks know to bail out. + NSDate *_stoppedAllFetchersDate; +} + +@synthesize maxRunningFetchersPerHost = _maxRunningFetchersPerHost, + configuration = _configuration, + configurationBlock = _configurationBlock, + cookieStorage = _cookieStorage, + userAgent = _userAgent, + challengeBlock = _challengeBlock, + credential = _credential, + proxyCredential = _proxyCredential, + allowedInsecureSchemes = _allowedInsecureSchemes, + allowLocalhostRequest = _allowLocalhostRequest, + allowInvalidServerCertificates = _allowInvalidServerCertificates, + retryEnabled = _retryEnabled, + retryBlock = _retryBlock, + maxRetryInterval = _maxRetryInterval, + minRetryInterval = _minRetryInterval, + properties = _properties, + unusedSessionTimeout = _unusedSessionTimeout, + testBlock = _testBlock; + +#if GTM_BACKGROUND_TASK_FETCHING +@synthesize skipBackgroundTask = _skipBackgroundTask; +#endif + +- (instancetype)init { + self = [super init]; + if (self) { + _delayedFetchersByHost = [[NSMutableDictionary alloc] init]; + _runningFetchersByHost = [[NSMutableDictionary alloc] init]; + _maxRunningFetchersPerHost = 10; + _cookieStorageMethod = -1; + _unusedSessionTimeout = 60.0; + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + _callbackQueue = dispatch_get_main_queue(); + + _delegateQueue = [[NSOperationQueue alloc] init]; + _delegateQueue.maxConcurrentOperationCount = 1; + _delegateQueue.name = @"com.google.GTMSessionFetcher.NSURLSessionDelegateQueue"; + + _sessionCreationSemaphore = dispatch_semaphore_create(1); + + // Starting with the SDKs for OS X 10.11/iOS 9, the service has a default useragent. + // Apps can remove this and get the default system "CFNetwork" useragent by setting the + // fetcher service's userAgent property to nil. +#if (!TARGET_OS_IPHONE && defined(MAC_OS_X_VERSION_10_11) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_11) \ + || (TARGET_OS_IPHONE && defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0) + _userAgent = GTMFetcherStandardUserAgentString(nil); +#endif + } + return self; +} + +- (void)dealloc { + [self detachAuthorizer]; + [_delegateDispatcher abandon]; +} + +#pragma mark Generate a new fetcher + +// Clients may override this method. Clients should not override any other library methods. +- (id)fetcherWithRequest:(NSURLRequest *)request + fetcherClass:(Class)fetcherClass { + GTMSessionFetcher *fetcher = [[fetcherClass alloc] initWithRequest:request + configuration:self.configuration]; + fetcher.callbackQueue = self.callbackQueue; + fetcher.sessionDelegateQueue = self.sessionDelegateQueue; + fetcher.challengeBlock = self.challengeBlock; + fetcher.credential = self.credential; + fetcher.proxyCredential = self.proxyCredential; + fetcher.authorizer = self.authorizer; + fetcher.cookieStorage = self.cookieStorage; + fetcher.allowedInsecureSchemes = self.allowedInsecureSchemes; + fetcher.allowLocalhostRequest = self.allowLocalhostRequest; + fetcher.allowInvalidServerCertificates = self.allowInvalidServerCertificates; + fetcher.configurationBlock = self.configurationBlock; + fetcher.retryEnabled = self.retryEnabled; + fetcher.retryBlock = self.retryBlock; + fetcher.maxRetryInterval = self.maxRetryInterval; + fetcher.minRetryInterval = self.minRetryInterval; + fetcher.properties = self.properties; + fetcher.service = self; + if (self.cookieStorageMethod >= 0) { + [fetcher setCookieStorageMethod:self.cookieStorageMethod]; + } + +#if GTM_BACKGROUND_TASK_FETCHING + fetcher.skipBackgroundTask = self.skipBackgroundTask; +#endif + + NSString *userAgent = self.userAgent; + if (userAgent.length > 0 + && [request valueForHTTPHeaderField:@"User-Agent"] == nil) { + [fetcher setRequestValue:userAgent + forHTTPHeaderField:@"User-Agent"]; + } + fetcher.testBlock = self.testBlock; + + return fetcher; +} + +- (GTMSessionFetcher *)fetcherWithRequest:(NSURLRequest *)request { + return [self fetcherWithRequest:request + fetcherClass:[GTMSessionFetcher class]]; +} + +- (GTMSessionFetcher *)fetcherWithURL:(NSURL *)requestURL { + return [self fetcherWithRequest:[NSURLRequest requestWithURL:requestURL]]; +} + +- (GTMSessionFetcher *)fetcherWithURLString:(NSString *)requestURLString { + NSURL *url = [NSURL URLWithString:requestURLString]; + return [self fetcherWithURL:url]; +} + +// Returns a session for the fetcher's host, or nil. +- (NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSURLSession *session = _delegateDispatcher.session; + return session; + } +} + +// Returns a session for the fetcher's host, or nil. For shared sessions, this +// waits on a semaphore, blocking other fetchers while the caller creates the +// session if needed. +- (NSURLSession *)sessionForFetcherCreation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + if (!_delegateDispatcher) { + // This fetcher is creating a non-shared session, so skip the semaphore usage. + return nil; + } + } + + // Wait if another fetcher is currently creating a session; avoid waiting + // inside the @synchronized block, as that can deadlock. + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Before getting the NSURLSession for task creation, it is + // important to invalidate and nil out the session discard timer; otherwise + // the session can be invalidated between when it is returned to the + // fetcher, and when the fetcher attempts to create its NSURLSessionTask. + [_delegateDispatcher startSessionUsage]; + + NSURLSession *session = _delegateDispatcher.session; + if (session) { + // The calling fetcher will receive a preexisting session, so + // we can allow other fetchers to create a session. + dispatch_semaphore_signal(_sessionCreationSemaphore); + } else { + // No existing session was obtained, so the calling fetcher will create the session; + // it *must* invoke fetcherDidCreateSession: to signal the dispatcher's semaphore after + // the session has been created (or fails to be created) to avoid a hang. + } + return session; + } +} + +- (id)sessionDelegate { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateDispatcher; + } +} + +#pragma mark Queue Management + +- (void)addRunningFetcher:(GTMSessionFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of running fetchers for this host, creating the array if needed. + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + if (runningForHost == nil) { + runningForHost = [NSMutableArray arrayWithObject:fetcher]; + [_runningFetchersByHost setObject:runningForHost forKey:host]; + } else { + [runningForHost addObject:fetcher]; + } +} + +- (void)addDelayedFetcher:(GTMSessionFetcher *)fetcher + forHost:(NSString *)host { + // Add to the array of delayed fetchers for this host, creating the array if needed. + NSMutableArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + if (delayedForHost == nil) { + delayedForHost = [NSMutableArray arrayWithObject:fetcher]; + [_delayedFetchersByHost setObject:delayedForHost forKey:host]; + } else { + [delayedForHost addObject:fetcher]; + } +} + +- (BOOL)isDelayingFetcher:(GTMSessionFetcher *)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSString *host = fetcher.request.URL.host; + if (host == nil) { + return NO; + } + NSArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + NSUInteger idx = [delayedForHost indexOfObjectIdenticalTo:fetcher]; + BOOL isDelayed = (delayedForHost != nil) && (idx != NSNotFound); + return isDelayed; + } +} + +- (BOOL)fetcherShouldBeginFetching:(GTMSessionFetcher *)fetcher { + // Entry point from the fetcher + NSURL *requestURL = fetcher.request.URL; + NSString *host = requestURL.host; + + // Addresses "file:///path" case where localhost is the implicit host. + if (host.length == 0 && [requestURL isFileURL]) { + host = @"localhost"; + } + + if (host.length == 0) { + // Data URIs legitimately have no host, reject other hostless URLs. + GTMSESSION_ASSERT_DEBUG([[requestURL scheme] isEqual:@"data"], @"%@ lacks host", fetcher); + return YES; + } + + BOOL shouldBeginResult; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + if (runningForHost != nil + && [runningForHost indexOfObjectIdenticalTo:fetcher] != NSNotFound) { + GTMSESSION_ASSERT_DEBUG(NO, @"%@ was already running", fetcher); + return YES; + } + + BOOL shouldRunNow = (fetcher.usingBackgroundSession + || _maxRunningFetchersPerHost == 0 + || _maxRunningFetchersPerHost > + [[self class] numberOfNonBackgroundSessionFetchers:runningForHost]); + if (shouldRunNow) { + [self addRunningFetcher:fetcher forHost:host]; + shouldBeginResult = YES; + } else { + [self addDelayedFetcher:fetcher forHost:host]; + shouldBeginResult = NO; + } + } // @synchronized(self) + + // We'll save the host that serves as the key for this fetcher's array + // to avoid any chance of the underlying request changing, stranding + // the fetcher in the wrong array + fetcher.serviceHost = host; + + return shouldBeginResult; +} + +- (void)startFetcher:(GTMSessionFetcher *)fetcher { + [fetcher beginFetchMayDelay:NO + mayAuthorize:YES]; +} + +// Internal utility. Returns a fetcher's delegate if it's a dispatcher, or nil if the fetcher +// is its own delegate (possibly via proxy) and has no dispatcher. +- (GTMSessionFetcherSessionDelegateDispatcher *)delegateDispatcherForFetcher:(GTMSessionFetcher *)fetcher { + GTMSessionCheckNotSynchronized(self); + + NSURLSession *fetcherSession = fetcher.session; + if (fetcherSession) { + id fetcherDelegate = fetcherSession.delegate; + // If the delegate is non-nil and claims to be a GTMSessionFetcher, there is no dispatcher; + // assume the fetcher is the delegate or has been proxied (some third-party frameworks + // are known to swizzle NSURLSession to proxy its delegate). + BOOL hasDispatcher = (fetcherDelegate != nil && + ![fetcherDelegate isKindOfClass:[GTMSessionFetcher class]]); + if (hasDispatcher) { + GTMSESSION_ASSERT_DEBUG([fetcherDelegate isKindOfClass:[GTMSessionFetcherSessionDelegateDispatcher class]], + @"Fetcher delegate class: %@", [fetcherDelegate class]); + return (GTMSessionFetcherSessionDelegateDispatcher *)fetcherDelegate; + } + } + return nil; +} + +- (void)fetcherDidCreateSession:(GTMSessionFetcher *)fetcher { + if (fetcher.canShareSession) { + NSURLSession *fetcherSession = fetcher.session; + GTMSESSION_ASSERT_DEBUG(fetcherSession != nil, @"Fetcher missing its session: %@", fetcher); + + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + if (delegateDispatcher) { + GTMSESSION_ASSERT_DEBUG(delegateDispatcher.session == nil, + @"Fetcher made an extra session: %@", fetcher); + + // Save this fetcher's session. + delegateDispatcher.session = fetcherSession; + + // Allow other fetchers to request this session now. + dispatch_semaphore_signal(_sessionCreationSemaphore); + } + } +} + +- (void)fetcherDidBeginFetching:(GTMSessionFetcher *)fetcher { + // If this fetcher has a separate delegate with a shared session, then + // this fetcher should be added to the delegate's map of tasks to fetchers. + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + if (delegateDispatcher) { + GTMSESSION_ASSERT_DEBUG(fetcher.canShareSession, + @"Inappropriate shared session: %@", fetcher); + + // There should already be a session, from this or a previous fetcher. + // + // Sanity check that the fetcher's session is the delegate's shared session. + NSURLSession *sharedSession = delegateDispatcher.session; + NSURLSession *fetcherSession = fetcher.session; + GTMSESSION_ASSERT_DEBUG(sharedSession != nil, @"Missing delegate session: %@", fetcher); + GTMSESSION_ASSERT_DEBUG(fetcherSession == sharedSession, + @"Inconsistent session: %@ %@ (shared: %@)", + fetcher, fetcherSession, sharedSession); + + if (sharedSession != nil && fetcherSession == sharedSession) { + NSURLSessionTask *task = fetcher.sessionTask; + GTMSESSION_ASSERT_DEBUG(task != nil, @"Missing session task: %@", fetcher); + + if (task) { + [delegateDispatcher setFetcher:fetcher + forTask:task]; + } + } + } +} + +- (void)stopFetcher:(GTMSessionFetcher *)fetcher { + [fetcher stopFetching]; +} + +- (void)fetcherDidStop:(GTMSessionFetcher *)fetcher { + // Entry point from the fetcher + NSString *host = fetcher.serviceHost; + if (!host) { + // fetcher has been stopped previously + return; + } + + // This removeFetcher: invocation is a fallback; typically, fetchers are removed from the task + // map when the task completes. + GTMSessionFetcherSessionDelegateDispatcher *delegateDispatcher = + [self delegateDispatcherForFetcher:fetcher]; + [delegateDispatcher removeFetcher:fetcher]; + + NSMutableArray *fetchersToStart; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // If a test is waiting for all fetchers to stop, it needs to wait for this one + // to invoke its callbacks on the callback queue. + [_stoppedFetchersToWaitFor addObject:fetcher]; + + NSMutableArray *runningForHost = [_runningFetchersByHost objectForKey:host]; + [runningForHost removeObject:fetcher]; + + NSMutableArray *delayedForHost = [_delayedFetchersByHost objectForKey:host]; + [delayedForHost removeObject:fetcher]; + + while (delayedForHost.count > 0 + && [[self class] numberOfNonBackgroundSessionFetchers:runningForHost] + < _maxRunningFetchersPerHost) { + // Start another delayed fetcher running, scanning for the minimum + // priority value, defaulting to FIFO for equal priorities + GTMSessionFetcher *nextFetcher = nil; + for (GTMSessionFetcher *delayedFetcher in delayedForHost) { + if (nextFetcher == nil + || delayedFetcher.servicePriority < nextFetcher.servicePriority) { + nextFetcher = delayedFetcher; + } + } + + if (nextFetcher) { + [self addRunningFetcher:nextFetcher forHost:host]; + runningForHost = [_runningFetchersByHost objectForKey:host]; + + [delayedForHost removeObjectIdenticalTo:nextFetcher]; + + if (!fetchersToStart) { + fetchersToStart = [NSMutableArray array]; + } + [fetchersToStart addObject:nextFetcher]; + } + } + + if (runningForHost.count == 0) { + // None left; remove the empty array + [_runningFetchersByHost removeObjectForKey:host]; + } + + if (delayedForHost.count == 0) { + [_delayedFetchersByHost removeObjectForKey:host]; + } + } // @synchronized(self) + + // Start fetchers outside of the synchronized block to avoid a deadlock. + for (GTMSessionFetcher *nextFetcher in fetchersToStart) { + [self startFetcher:nextFetcher]; + } + + // The fetcher is no longer in the running or the delayed array, + // so remove its host and thread properties + fetcher.serviceHost = nil; +} + +- (NSUInteger)numberOfFetchers { + NSUInteger running = [self numberOfRunningFetchers]; + NSUInteger delayed = [self numberOfDelayedFetchers]; + return running + delayed; +} + +- (NSUInteger)numberOfRunningFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger sum = 0; + for (NSString *host in _runningFetchersByHost) { + NSArray *fetchers = [_runningFetchersByHost objectForKey:host]; + sum += fetchers.count; + } + return sum; + } +} + +- (NSUInteger)numberOfDelayedFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger sum = 0; + for (NSString *host in _delayedFetchersByHost) { + NSArray *fetchers = [_delayedFetchersByHost objectForKey:host]; + sum += fetchers.count; + } + return sum; + } +} + +- (NSArray *)issuedFetchers { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSMutableArray *allFetchers = [NSMutableArray array]; + void (^accumulateFetchers)(id, id, BOOL *) = ^(NSString *host, + NSArray *fetchersForHost, + BOOL *stop) { + [allFetchers addObjectsFromArray:fetchersForHost]; + }; + [_runningFetchersByHost enumerateKeysAndObjectsUsingBlock:accumulateFetchers]; + [_delayedFetchersByHost enumerateKeysAndObjectsUsingBlock:accumulateFetchers]; + + GTMSESSION_ASSERT_DEBUG(allFetchers.count == [NSSet setWithArray:allFetchers].count, + @"Fetcher appears multiple times\n running: %@\n delayed: %@", + _runningFetchersByHost, _delayedFetchersByHost); + + return allFetchers.count > 0 ? allFetchers : nil; + } +} + +- (NSArray *)issuedFetchersWithRequestURL:(NSURL *)requestURL { + NSString *host = requestURL.host; + if (host.length == 0) return nil; + + NSURL *targetURL = [requestURL absoluteURL]; + + NSArray *allFetchers = [self issuedFetchers]; + NSIndexSet *indexes = [allFetchers indexesOfObjectsPassingTest:^BOOL(GTMSessionFetcher *fetcher, + NSUInteger idx, + BOOL *stop) { + NSURL *fetcherURL = [fetcher.request.URL absoluteURL]; + return [fetcherURL isEqual:targetURL]; + }]; + + NSArray *result = nil; + if (indexes.count > 0) { + result = [allFetchers objectsAtIndexes:indexes]; + } + return result; +} + +- (void)stopAllFetchers { + NSArray *delayedFetchersByHost; + NSArray *runningFetchersByHost; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Set the time barrier so fetchers know not to call back even if + // the stop calls below occur after the fetchers naturally + // stopped and so were removed from _runningFetchersByHost, + // but while the callbacks were already enqueued before stopAllFetchers + // was invoked. + _stoppedAllFetchersDate = [[NSDate alloc] init]; + + // Remove fetchers from the delayed list to avoid fetcherDidStop: from + // starting more fetchers running as a side effect of stopping one + delayedFetchersByHost = _delayedFetchersByHost.allValues; + [_delayedFetchersByHost removeAllObjects]; + + runningFetchersByHost = _runningFetchersByHost.allValues; + [_runningFetchersByHost removeAllObjects]; + } + + for (NSArray *delayedForHost in delayedFetchersByHost) { + for (GTMSessionFetcher *fetcher in delayedForHost) { + [self stopFetcher:fetcher]; + } + } + + for (NSArray *runningForHost in runningFetchersByHost) { + for (GTMSessionFetcher *fetcher in runningForHost) { + [self stopFetcher:fetcher]; + } + } +} + +- (NSDate *)stoppedAllFetchersDate { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _stoppedAllFetchersDate; + } +} + +#pragma mark Accessors + +- (BOOL)reuseSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateDispatcher != nil; + } +} + +- (void)setReuseSession:(BOOL)shouldReuse { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + BOOL wasReusing = (_delegateDispatcher != nil); + if (shouldReuse != wasReusing) { + [self abandonDispatcher]; + if (shouldReuse) { + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + } else { + _delegateDispatcher = nil; + } + } + } +} + +- (void)resetSession { + GTMSessionCheckNotSynchronized(self); + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + [self resetSessionInternal]; + } + + dispatch_semaphore_signal(_sessionCreationSemaphore); +} + +- (void)resetSessionInternal { + GTMSessionCheckSynchronized(self); + + // The old dispatchers may be retained as delegates of any ongoing sessions by those sessions. + if (_delegateDispatcher) { + [self abandonDispatcher]; + _delegateDispatcher = + [[GTMSessionFetcherSessionDelegateDispatcher alloc] initWithParentService:self + sessionDiscardInterval:_unusedSessionTimeout]; + } +} + +- (void)resetSessionForDispatcherDiscardTimer:(NSTimer *)timer { + GTMSessionCheckNotSynchronized(self); + + dispatch_semaphore_wait(_sessionCreationSemaphore, DISPATCH_TIME_FOREVER); + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_delegateDispatcher.discardTimer == timer) { + // If the delegate dispatcher's current discardTimer is the same object as the timer + // that fired, no fetcher has recently attempted to start using the session by calling + // startSessionUsage, which invalidates and nils out the timer. + [self resetSessionInternal]; + } else { + // A fetcher has invalidated the timer between its triggering and now, potentially + // meaning a fetcher has requested access to the NSURLSession, and may be in the process + // of starting a new task. The dispatcher should not be abandoned, as this can lead + // to a race condition between calling -finishTasksAndInvalidate on the NSURLSession + // and the fetcher attempting to create a new task. + } + } + + dispatch_semaphore_signal(_sessionCreationSemaphore); +} + +- (NSTimeInterval)unusedSessionTimeout { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _unusedSessionTimeout; + } +} + +- (void)setUnusedSessionTimeout:(NSTimeInterval)timeout { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _unusedSessionTimeout = timeout; + _delegateDispatcher.discardInterval = timeout; + } +} + +// This method should be called inside of @synchronized(self) +- (void)abandonDispatcher { + GTMSessionCheckSynchronized(self); + [_delegateDispatcher abandon]; +} + +- (NSDictionary *)runningFetchersByHost { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_runningFetchersByHost copy]; + } +} + +- (void)setRunningFetchersByHost:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _runningFetchersByHost = [dict mutableCopy]; + } +} + +- (NSDictionary *)delayedFetchersByHost { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_delayedFetchersByHost copy]; + } +} + +- (void)setDelayedFetchersByHost:(NSDictionary *)dict { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delayedFetchersByHost = [dict mutableCopy]; + } +} + +- (id)authorizer { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _authorizer; + } +} + +- (void)setAuthorizer:(id)obj { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (obj != _authorizer) { + [self detachAuthorizer]; + } + + _authorizer = obj; + } + + // Use the fetcher service for the authorization fetches if the auth + // object supports fetcher services + if ([obj respondsToSelector:@selector(setFetcherService:)]) { +#if GTM_USE_SESSION_FETCHER + [obj setFetcherService:self]; +#else + [obj setFetcherService:(id)self]; +#endif + } +} + +// This should be called inside a @synchronized(self) block except during dealloc. +- (void)detachAuthorizer { + // This method is called by the fetcher service's dealloc and setAuthorizer: + // methods; do not override. + // + // The fetcher service retains the authorizer, and the authorizer has a + // weak pointer to the fetcher service (a non-zeroing pointer for + // compatibility with iOS 4 and Mac OS X 10.5/10.6.) + // + // When this fetcher service no longer uses the authorizer, we want to remove + // the authorizer's dependence on the fetcher service. Authorizers can still + // function without a fetcher service. + if ([_authorizer respondsToSelector:@selector(fetcherService)]) { + id authFetcherService = [_authorizer fetcherService]; + if (authFetcherService == self) { + [_authorizer setFetcherService:nil]; + } + } +} + +- (dispatch_queue_t GTM_NONNULL_TYPE)callbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _callbackQueue; + } // @synchronized(self) +} + +- (void)setCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _callbackQueue = queue ?: dispatch_get_main_queue(); + } // @synchronized(self) +} + +- (NSOperationQueue * GTM_NONNULL_TYPE)sessionDelegateQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateQueue; + } // @synchronized(self) +} + +- (void)setSessionDelegateQueue:(NSOperationQueue * GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateQueue = queue ?: [NSOperationQueue mainQueue]; + } // @synchronized(self) +} + +- (NSOperationQueue *)delegateQueue { + // Provided for compatibility with the old fetcher service. The gtm-oauth2 code respects + // any custom delegate queue for calling the app. + return nil; +} + ++ (NSUInteger)numberOfNonBackgroundSessionFetchers:(NSArray *)fetchers { + NSUInteger sum = 0; + for (GTMSessionFetcher *fetcher in fetchers) { + if (!fetcher.usingBackgroundSession) { + ++sum; + } + } + return sum; +} + +@end + +@implementation GTMSessionFetcherService (TestingSupport) + ++ (instancetype)mockFetcherServiceWithFakedData:(NSData *)fakedDataOrNil + fakedError:(NSError *)fakedErrorOrNil { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + NSURL *url = [NSURL URLWithString:@"http://example.invalid"]; + NSHTTPURLResponse *fakedResponse = + [[NSHTTPURLResponse alloc] initWithURL:url + statusCode:(fakedErrorOrNil ? 500 : 200) + HTTPVersion:@"HTTP/1.1" + headerFields:nil]; + return [self mockFetcherServiceWithFakedData:fakedDataOrNil + fakedResponse:fakedResponse + fakedError:fakedErrorOrNil]; +#else + GTMSESSION_ASSERT_DEBUG(0, @"Test blocks disabled"); + return nil; +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK +} + ++ (instancetype)mockFetcherServiceWithFakedData:(NSData *)fakedDataOrNil + fakedResponse:(NSHTTPURLResponse *)fakedResponse + fakedError:(NSError *)fakedErrorOrNil { +#if !GTM_DISABLE_FETCHER_TEST_BLOCK + GTMSessionFetcherService *service = [[self alloc] init]; + service.allowedInsecureSchemes = @[ @"http" ]; + service.testBlock = ^(GTMSessionFetcher *fetcherToTest, + GTMSessionFetcherTestResponse testResponse) { + testResponse(fakedResponse, fakedDataOrNil, fakedErrorOrNil); + }; + return service; +#else + GTMSESSION_ASSERT_DEBUG(0, @"Test blocks disabled"); + return nil; +#endif // GTM_DISABLE_FETCHER_TEST_BLOCK +} + +#pragma mark Synchronous Wait for Unit Testing + +- (BOOL)waitForCompletionOfAllFetchersWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate *giveUpDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + _stoppedFetchersToWaitFor = [NSMutableArray array]; + + BOOL shouldSpinRunLoop = [NSThread isMainThread]; + const NSTimeInterval kSpinInterval = 0.001; + BOOL didTimeOut = NO; + while (([self numberOfFetchers] > 0 || _stoppedFetchersToWaitFor.count > 0)) { + didTimeOut = [giveUpDate timeIntervalSinceNow] < 0; + if (didTimeOut) break; + + GTMSessionFetcher *stoppedFetcher = _stoppedFetchersToWaitFor.firstObject; + if (stoppedFetcher) { + [_stoppedFetchersToWaitFor removeObject:stoppedFetcher]; + [stoppedFetcher waitForCompletionWithTimeout:10.0 * kSpinInterval]; + } + + if (shouldSpinRunLoop) { + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:kSpinInterval]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + [NSThread sleepForTimeInterval:kSpinInterval]; + } + } + _stoppedFetchersToWaitFor = nil; + + return !didTimeOut; +} + +@end + +@implementation GTMSessionFetcherService (BackwardsCompatibilityOnly) + +- (NSInteger)cookieStorageMethod { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _cookieStorageMethod; + } +} + +- (void)setCookieStorageMethod:(NSInteger)cookieStorageMethod { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _cookieStorageMethod = cookieStorageMethod; + } +} + +@end + +@implementation GTMSessionFetcherSessionDelegateDispatcher { + __weak GTMSessionFetcherService *_parentService; + NSURLSession *_session; + + // The task map maps NSURLSessionTasks to GTMSessionFetchers + NSMutableDictionary *_taskToFetcherMap; + // The discard timer will invalidate sessions after the session's last task completes. + NSTimer *_discardTimer; + NSTimeInterval _discardInterval; +} + +@synthesize discardInterval = _discardInterval, + session = _session; + +- (instancetype)init { + [self doesNotRecognizeSelector:_cmd]; + return nil; +} + +- (instancetype)initWithParentService:(GTMSessionFetcherService *)parentService + sessionDiscardInterval:(NSTimeInterval)discardInterval { + self = [super init]; + if (self) { + _discardInterval = discardInterval; + _parentService = parentService; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ %p %@ %@", + [self class], self, + _session ?: @"", + _taskToFetcherMap.count > 0 ? _taskToFetcherMap : @""]; +} + +- (NSTimer *)discardTimer { + GTMSessionCheckNotSynchronized(self); + @synchronized(self) { + return _discardTimer; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)startDiscardTimer { + GTMSessionCheckSynchronized(self); + [_discardTimer invalidate]; + _discardTimer = nil; + if (_discardInterval > 0) { + _discardTimer = [NSTimer timerWithTimeInterval:_discardInterval + target:self + selector:@selector(discardTimerFired:) + userInfo:nil + repeats:NO]; + [_discardTimer setTolerance:(_discardInterval / 10)]; + [[NSRunLoop mainRunLoop] addTimer:_discardTimer forMode:NSRunLoopCommonModes]; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)destroyDiscardTimer { + GTMSessionCheckSynchronized(self); + [_discardTimer invalidate]; + _discardTimer = nil; +} + +- (void)discardTimerFired:(NSTimer *)timer { + GTMSessionFetcherService *service; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + NSUInteger numberOfTasks = _taskToFetcherMap.count; + if (numberOfTasks == 0) { + service = _parentService; + } + } + + // Inform the service that the discard timer has fired, and should check whether the + // service can abandon us. -resetSession cannot be called directly, as there is a + // race condition that must be guarded against with the NSURLSession being returned + // from sessionForFetcherCreation outside other locks. The service can take steps + // to prevent resetting the session if that has occurred. + // + // The service must be called from outside the @synchronized block. + [service resetSessionForDispatcherDiscardTimer:timer]; +} + +- (void)abandon { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self destroySessionAndTimer]; + } +} + +- (void)startSessionUsage { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [self destroyDiscardTimer]; + } +} + +// This method should be called inside of a @synchronized(self) block. +- (void)destroySessionAndTimer { + GTMSessionCheckSynchronized(self); + [self destroyDiscardTimer]; + + // Break any retain cycle from the session holding the delegate. + [_session finishTasksAndInvalidate]; + + // Immediately clear the session so no new task may be issued with it. + // + // The _taskToFetcherMap needs to stay valid until the outstanding tasks finish. + _session = nil; +} + +- (void)setFetcher:(GTMSessionFetcher *)fetcher forTask:(NSURLSessionTask *)task { + GTMSESSION_ASSERT_DEBUG(fetcher != nil, @"missing fetcher"); + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_taskToFetcherMap == nil) { + _taskToFetcherMap = [[NSMutableDictionary alloc] init]; + } + + if (fetcher) { + [_taskToFetcherMap setObject:fetcher forKey:task]; + [self destroyDiscardTimer]; + } + } +} + +- (void)removeFetcher:(GTMSessionFetcher *)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + // Typically, a fetcher should be removed when its task invokes + // URLSession:task:didCompleteWithError:. + // + // When fetching with a testBlock, though, the task completed delegate + // method may not be invoked, requiring cleanup here. + NSArray *tasks = [_taskToFetcherMap allKeysForObject:fetcher]; + GTMSESSION_ASSERT_DEBUG(tasks.count <= 1, @"fetcher task not unmapped: %@", tasks); + [_taskToFetcherMap removeObjectsForKeys:tasks]; + + if (_taskToFetcherMap.count == 0) { + [self startDiscardTimer]; + } + } +} + +// This helper method provides synchronized access to the task map for the delegate +// methods below. +- (id)fetcherForTask:(NSURLSessionTask *)task { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return [_taskToFetcherMap objectForKey:task]; + } +} + +- (void)removeTaskFromMap:(NSURLSessionTask *)task { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + [_taskToFetcherMap removeObjectForKey:task]; + } +} + +- (void)setSession:(NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = session; + } +} + +- (NSURLSession *)session { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _session; + } +} + +- (NSTimeInterval)discardInterval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _discardInterval; + } +} + +- (void)setDiscardInterval:(NSTimeInterval)interval { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _discardInterval = interval; + } +} + +// NSURLSessionDelegate protocol methods. + +// - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session; +// +// TODO(seh): How do we route this to an appropriate fetcher? + + +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { + GTM_LOG_SESSION_DELEGATE(@"%@ %p URLSession:%@ didBecomeInvalidWithError:%@", + [self class], self, session, error); + NSDictionary *localTaskToFetcherMap; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _session = nil; + + localTaskToFetcherMap = [_taskToFetcherMap copy]; + } + + // Any "suspended" tasks may not have received callbacks from NSURLSession when the session + // completes; we'll call them now. + [localTaskToFetcherMap enumerateKeysAndObjectsUsingBlock:^(NSURLSessionTask *task, + GTMSessionFetcher *fetcher, + BOOL *stop) { + if (fetcher.session == session) { + // Our delegate method URLSession:task:didCompleteWithError: will rely on + // _taskToFetcherMap so that should still contain this fetcher. + NSError *canceledError = [NSError errorWithDomain:NSURLErrorDomain + code:NSURLErrorCancelled + userInfo:nil]; + [self URLSession:session task:task didCompleteWithError:canceledError]; + } else { + GTMSESSION_ASSERT_DEBUG(0, @"Unexpected session in fetcher: %@ has %@ (expected %@)", + fetcher, fetcher.session, session); + } + }]; + + // Our tests rely on this notification to know the session discard timer fired. + NSDictionary *userInfo = @{ kGTMSessionFetcherServiceSessionKey : session }; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMSessionFetcherServiceSessionBecameInvalidNotification + object:_parentService + userInfo:userInfo]; +} + + +#pragma mark - NSURLSessionTaskDelegate + +// NSURLSessionTaskDelegate protocol methods. +// +// We won't test here if the fetcher responds to these since we only want this +// class to implement the same delegate methods the fetcher does (so NSURLSession's +// tests for respondsToSelector: will have the same result whether the session +// delegate is the fetcher or this dispatcher.) + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task +willPerformHTTPRedirection:response + newRequest:request + completionHandler:completionHandler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))handler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + didReceiveChallenge:challenge + completionHandler:handler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + needNewBodyStream:(void (^)(NSInputStream *bodyStream))handler { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + needNewBodyStream:handler]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent +totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + id fetcher = [self fetcherForTask:task]; + [fetcher URLSession:session + task:task + didSendBodyData:bytesSent + totalBytesSent:totalBytesSent +totalBytesExpectedToSend:totalBytesExpectedToSend]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(NSError *)error { + id fetcher = [self fetcherForTask:task]; + + // This is the usual way tasks are removed from the task map. + [self removeTaskFromMap:task]; + + [fetcher URLSession:session + task:task + didCompleteWithError:error]; +} + +// NSURLSessionDataDelegate protocol methods. + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition))handler { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + didReceiveResponse:response + completionHandler:handler]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask { + id fetcher = [self fetcherForTask:dataTask]; + GTMSESSION_ASSERT_DEBUG(fetcher != nil, @"Missing fetcher for %@", dataTask); + [self removeTaskFromMap:dataTask]; + if (fetcher) { + GTMSESSION_ASSERT_DEBUG([fetcher isKindOfClass:[GTMSessionFetcher class]], + @"Expecting GTMSessionFetcher"); + [self setFetcher:(GTMSessionFetcher *)fetcher forTask:downloadTask]; + } + + [fetcher URLSession:session + dataTask:dataTask +didBecomeDownloadTask:downloadTask]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + didReceiveData:data]; +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + willCacheResponse:(NSCachedURLResponse *)proposedResponse + completionHandler:(void (^)(NSCachedURLResponse *))handler { + id fetcher = [self fetcherForTask:dataTask]; + [fetcher URLSession:session + dataTask:dataTask + willCacheResponse:proposedResponse + completionHandler:handler]; +} + +// NSURLSessionDownloadDelegate protocol methods. + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask +didFinishDownloadingToURL:(NSURL *)location { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask +didFinishDownloadingToURL:location]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didWriteData:(int64_t)bytesWritten + totalBytesWritten:(int64_t)totalWritten +totalBytesExpectedToWrite:(int64_t)totalExpected { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask + didWriteData:bytesWritten + totalBytesWritten:totalWritten +totalBytesExpectedToWrite:totalExpected]; +} + +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)downloadTask + didResumeAtOffset:(int64_t)fileOffset +expectedTotalBytes:(int64_t)expectedTotalBytes { + id fetcher = [self fetcherForTask:downloadTask]; + [fetcher URLSession:session + downloadTask:downloadTask + didResumeAtOffset:fileOffset + expectedTotalBytes:expectedTotalBytes]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h new file mode 100644 index 0000000..2f9023a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.h @@ -0,0 +1,175 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// GTMSessionUploadFetcher implements Google's resumable upload protocol. + +// +// This subclass of GTMSessionFetcher simulates the series of fetches +// needed for chunked upload as a single fetch operation. +// +// Protocol document: TBD +// +// To the client, the only fetcher that exists is this class; the subsidiary +// fetchers needed for uploading chunks are not visible (though the most recent +// chunk fetcher may be accessed via the -activeFetcher or -chunkFetcher methods, and +// -responseHeaders and -statusCode reflect results from the most recent chunk +// fetcher.) +// +// Chunk fetchers are discarded as soon as they have completed. +// +// The protocol also allows for a cancellation notification request to be sent to the +// server to allow discarding of the currently uploaded data and this will be sent +// automatically upon calling stopFetching if the upload has already started. +// +// Note: Unlike the fetcher superclass, the methods of GTMSessionUploadFetcher should +// only be used from the main thread until further work is done to make this subclass +// thread-safe. + +#import "GTMSessionFetcher.h" +#import "GTMSessionFetcherService.h" + +GTM_ASSUME_NONNULL_BEGIN + +// The value to use for file size parameters when the file size is not yet known. +extern int64_t const kGTMSessionUploadFetcherUnknownFileSize; + +// Unless an application knows it needs a smaller chunk size, it should use the standard +// chunk size, which sends the entire file as a single chunk to minimize upload overhead. +// Setting an explicit chunk size that comfortably fits in memory is advisable for large +// uploads. +extern int64_t const kGTMSessionUploadFetcherStandardChunkSize; + +// When uploading requires data buffer allocations (such as uploading from an NSData or +// an NSFileHandle) this is the maximum buffer size that will be created by the fetcher. +extern int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize; + +// Notification that the upload location URL was provided by the server. +extern NSString *const kGTMSessionFetcherUploadLocationObtainedNotification; + +// Block to provide data during uploads. +// +// Response data may be allocated with dataWithBytesNoCopy:length:freeWhenDone: for efficiency, +// and released after the response block returns. +// +// If the length of the file being uploaded is unknown or already set, send +// kGTMSessionUploadFetcherUnknownFileSize for |fullUploadLength|. Otherwise, set |fullUploadLength| +// to its proper value. +// +// Pass nil as the data (and optionally an NSError) for a failure. +typedef void (^GTMSessionUploadFetcherDataProviderResponse)(NSData * GTM_NULLABLE_TYPE data, + int64_t fullUploadLength, + NSError * GTM_NULLABLE_TYPE error); +// Do not call the response with an NSData object with less data than the requested length unless +// you are passing the fullUploadLength to the fetcher for the first time and it is the last chunk +// of data in the file being uploaded. +typedef void (^GTMSessionUploadFetcherDataProvider)(int64_t offset, int64_t length, + GTMSessionUploadFetcherDataProviderResponse response); + +// Block to be notified about the final status of the cancellation request started in stopFetching. +// +// |fetcher| will be the cancel request that was sent to the server, or nil if stopFetching is not +// going to send a cancel request. If |fetcher| is provided, the other parameters correspond to the +// completion handler of the cancellation request fetcher. +typedef void (^GTMSessionUploadFetcherCancellationHandler)( + GTMSessionFetcher * GTM_NULLABLE_TYPE fetcher, + NSData * GTM_NULLABLE_TYPE data, + NSError * GTM_NULLABLE_TYPE error); + +@interface GTMSessionUploadFetcher : GTMSessionFetcher + +// Create an upload fetcher specifying either the request or the resume location URL, +// then set an upload data source using one of these: +// +// setUploadFileURL: +// setUploadDataLength:provider: +// setUploadFileHandle: +// setUploadData: + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + +// Allows cellular access. ++ (instancetype)uploadFetcherWithLocation:(NSURL * GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil; + +// Allows dataProviders for files of unknown length. Pass kGTMSessionUploadFetcherUnknownFileSize as +// |fullLength| if the length is unknown. +- (void)setUploadDataLength:(int64_t)fullLength + provider:(GTM_NULLABLE GTMSessionUploadFetcherDataProvider)block; + ++ (NSArray *)uploadFetchersForBackgroundSessions; ++ (GTM_NULLABLE instancetype)uploadFetcherForSessionIdentifier:(NSString *)sessionIdentifier; + +- (void)pauseFetching; +- (void)resumeFetching; +- (BOOL)isPaused; + +@property(atomic, strong, GTM_NULLABLE) NSURL *uploadLocationURL; +@property(atomic, strong, GTM_NULLABLE) NSData *uploadData; +@property(atomic, strong, GTM_NULLABLE) NSURL *uploadFileURL; +@property(atomic, strong, GTM_NULLABLE) NSFileHandle *uploadFileHandle; +@property(atomic, copy, readonly, GTM_NULLABLE) GTMSessionUploadFetcherDataProvider uploadDataProvider; +@property(atomic, copy) NSString *uploadMIMEType; +@property(atomic, readonly, assign) int64_t chunkSize; +@property(atomic, readonly, assign) int64_t currentOffset; +// Reflects the original NSURLRequest's @c allowCellularAccess property. +@property(atomic, readonly, assign) BOOL allowsCellularAccess; + +// The fetcher for the current data chunk, if any +@property(atomic, strong, GTM_NULLABLE) GTMSessionFetcher *chunkFetcher; + +// The active fetcher is the current chunk fetcher, or the upload fetcher itself +// if no chunk fetcher has yet been created. +@property(atomic, readonly) GTMSessionFetcher *activeFetcher; + +// The last request made by an active fetcher. Useful for testing. +@property(atomic, readonly, GTM_NULLABLE) NSURLRequest *lastChunkRequest; + +// The status code from the most recently-completed fetch. +@property(atomic, assign) NSInteger statusCode; + +// Invoked as part of the stop fetching process. Invoked immediately if there is no upload in +// progress, otherwise invoked with the results of the attempt to notify the server that the +// upload will not continue. +// +// Unlike other callbacks, since this is related specifically to the stopFetching flow it is not +// cleared by stopFetching. It will instead clear itself after it is invoked or if the completion +// has occured before stopFetching is called. +@property(atomic, copy, GTM_NULLABLE) GTMSessionUploadFetcherCancellationHandler + cancellationHandler; + +// Exposed for testing only. +@property(atomic, readonly, GTM_NULLABLE) dispatch_queue_t delegateCallbackQueue; +@property(atomic, readonly, GTM_NULLABLE) GTMSessionFetcherCompletionHandler delegateCompletionHandler; + +@end + +@interface GTMSessionFetcher (GTMSessionUploadFetcherMethods) + +@property(readonly, GTM_NULLABLE) GTMSessionUploadFetcher *parentUploadFetcher; + +@end + +GTM_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m new file mode 100644 index 0000000..4ea43f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GTMSessionFetcher/Source/GTMSessionUploadFetcher.m @@ -0,0 +1,1985 @@ +/* Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#import "GTMSessionUploadFetcher.h" + +static NSString *const kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey = @"_upChunk"; +static NSString *const kGTMSessionIdentifierUploadFileURLMetadataKey = @"_upFileURL"; +static NSString *const kGTMSessionIdentifierUploadFileLengthMetadataKey = @"_upFileLen"; +static NSString *const kGTMSessionIdentifierUploadLocationURLMetadataKey = @"_upLocURL"; +static NSString *const kGTMSessionIdentifierUploadMIMETypeMetadataKey = @"_uploadMIME"; +static NSString *const kGTMSessionIdentifierUploadChunkSizeMetadataKey = @"_upChSize"; +static NSString *const kGTMSessionIdentifierUploadCurrentOffsetMetadataKey = @"_upOffset"; +static NSString *const kGTMSessionIdentifierUploadAllowsCellularAccess = @"_upAllowsCellularAccess"; + +static NSString *const kGTMSessionHeaderXGoogUploadChunkGranularity = @"X-Goog-Upload-Chunk-Granularity"; +static NSString *const kGTMSessionHeaderXGoogUploadCommand = @"X-Goog-Upload-Command"; +static NSString *const kGTMSessionHeaderXGoogUploadContentLength = @"X-Goog-Upload-Content-Length"; +static NSString *const kGTMSessionHeaderXGoogUploadContentType = @"X-Goog-Upload-Content-Type"; +static NSString *const kGTMSessionHeaderXGoogUploadOffset = @"X-Goog-Upload-Offset"; +static NSString *const kGTMSessionHeaderXGoogUploadProtocol = @"X-Goog-Upload-Protocol"; +static NSString *const kGTMSessionXGoogUploadProtocolResumable = @"resumable"; +static NSString *const kGTMSessionHeaderXGoogUploadSizeReceived = @"X-Goog-Upload-Size-Received"; +static NSString *const kGTMSessionHeaderXGoogUploadStatus = @"X-Goog-Upload-Status"; +static NSString *const kGTMSessionHeaderXGoogUploadURL = @"X-Goog-Upload-URL"; + +// Property of chunk fetchers identifying the parent upload fetcher. Non-retained NSValue. +static NSString *const kGTMSessionUploadFetcherChunkParentKey = @"_uploadFetcherChunkParent"; + +int64_t const kGTMSessionUploadFetcherUnknownFileSize = -1; + +int64_t const kGTMSessionUploadFetcherStandardChunkSize = (int64_t)LLONG_MAX; + +#if TARGET_OS_IPHONE +int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize = 10 * 1024 * 1024; // 10 MB for iOS, watchOS, tvOS +#else +int64_t const kGTMSessionUploadFetcherMaximumDemandBufferSize = 100 * 1024 * 1024; // 100 MB for macOS +#endif + +typedef NS_ENUM(NSUInteger, GTMSessionUploadFetcherStatus) { + kStatusUnknown, + kStatusActive, + kStatusFinal, + kStatusCancelled, +}; + +NSString *const kGTMSessionFetcherUploadLocationObtainedNotification = + @"kGTMSessionFetcherUploadLocationObtainedNotification"; + +#if !GTMSESSION_BUILD_COMBINED_SOURCES +@interface GTMSessionFetcher (ProtectedMethods) + +// Access to non-public method on the parent fetcher class. +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks; +- (void)createSessionIdentifierWithMetadata:(NSDictionary *)metadata; +- (GTMSessionFetcherCompletionHandler)completionHandlerWithTarget:(id)target + didFinishSelector:(SEL)finishedSelector; +- (void)invokeOnCallbackQueue:(dispatch_queue_t)callbackQueue + afterUserStopped:(BOOL)afterStopped + block:(void (^)(void))block; +- (NSTimer *)retryTimer; +- (void)beginFetchForRetry; + +@property(readwrite, strong) NSData *downloadedData; +- (void)releaseCallbacks; + +- (NSInteger)statusCodeUnsynchronized; + +- (BOOL)userStoppedFetching; + +@end +#endif // !GTMSESSION_BUILD_COMBINED_SOURCES + +@interface GTMSessionUploadFetcher () + +// Changing readonly to readwrite. +@property(atomic, strong, readwrite) NSURLRequest *lastChunkRequest; +@property(atomic, readwrite, assign) int64_t currentOffset; + +// Internal properties. +@property(strong, atomic, GTM_NULLABLE) GTMSessionFetcher *fetcherInFlight; // Synchronized on self. + +@property(assign, atomic, getter=isSubdataGenerating) BOOL subdataGenerating; +@property(assign, atomic) BOOL shouldInitiateOffsetQuery; +@property(assign, atomic) int64_t uploadGranularity; +@property(assign, atomic) BOOL allowsCellularAccess; + +@end + +@implementation GTMSessionUploadFetcher { + GTMSessionFetcher *_chunkFetcher; + + // We'll call through to the delegate's completion handler. + GTMSessionFetcherCompletionHandler _delegateCompletionHandler; + dispatch_queue_t _delegateCallbackQueue; + + // The initial fetch's body length and bytes actually sent are + // needed for calculating progress during subsequent chunk uploads + int64_t _initialBodyLength; + int64_t _initialBodySent; + + // The upload server address for the chunks of this upload session. + NSURL *_uploadLocationURL; + + // _uploadData, _uploadDataProvider, or _uploadFileHandle may be set, but only one. + NSData *_uploadData; + NSFileHandle *_uploadFileHandle; + GTMSessionUploadFetcherDataProvider _uploadDataProvider; + NSURL *_uploadFileURL; + int64_t _uploadFileLength; + NSString *_uploadMIMEType; + int64_t _chunkSize; + int64_t _uploadGranularity; + BOOL _isPaused; + BOOL _isRestartedUpload; + BOOL _shouldInitiateOffsetQuery; + + // Tied to useBackgroundSession property, since this property is applicable to chunk fetchers. + BOOL _useBackgroundSessionOnChunkFetchers; + + // We keep the latest offset into the upload data just for progress reporting. + int64_t _currentOffset; + + NSDictionary *_recentChunkReponseHeaders; + NSInteger _recentChunkStatusCode; + + // For waiting, we need to know the fetcher in flight, if any, and if subdata generation + // is in progress. + GTMSessionFetcher *_fetcherInFlight; + BOOL _isSubdataGenerating; + BOOL _isCancelInFlight; + + GTMSessionUploadFetcherCancellationHandler _cancellationHandler; +} + ++ (void)load { + [self uploadFetchersForBackgroundSessions]; +} + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTMSessionFetcherService *)fetcherService { + GTMSessionUploadFetcher *fetcher = [self uploadFetcherWithRequest:request + fetcherService:fetcherService]; + [fetcher setLocationURL:nil + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:request.allowsCellularAccess]; + return fetcher; +} + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + fetcherService:(GTM_NULLABLE GTMSessionFetcherService *)fetcherServiceOrNil { + return [self uploadFetcherWithLocation:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:YES + fetcherService:fetcherServiceOrNil]; +} + ++ (instancetype)uploadFetcherWithLocation:(NSURL *GTM_NULLABLE_TYPE)uploadLocationURL + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess + fetcherService:(GTMSessionFetcherService *)fetcherService { + GTMSessionUploadFetcher *fetcher = [self uploadFetcherWithRequest:nil + fetcherService:fetcherService]; + [fetcher setLocationURL:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:chunkSize + allowsCellularAccess:allowsCellularAccess]; + return fetcher; +} + ++ (instancetype)uploadFetcherForSessionIdentifierMetadata:(NSDictionary *)metadata { + GTMSESSION_ASSERT_DEBUG( + [metadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] boolValue], + @"Session identifier metadata is not for an upload fetcher: %@", metadata); + + NSNumber *uploadFileLengthNum = metadata[kGTMSessionIdentifierUploadFileLengthMetadataKey]; + GTMSESSION_ASSERT_DEBUG(uploadFileLengthNum != nil, + @"Session metadata missing an UploadFileSize"); + if (uploadFileLengthNum == nil) return nil; + + int64_t uploadFileLength = [uploadFileLengthNum longLongValue]; + GTMSESSION_ASSERT_DEBUG(uploadFileLength >= 0, @"Session metadata UploadFileSize is unknown"); + + NSString *uploadFileURLString = metadata[kGTMSessionIdentifierUploadFileURLMetadataKey]; + GTMSESSION_ASSERT_DEBUG(uploadFileURLString, @"Session metadata missing an UploadFileURL"); + if (uploadFileURLString == nil) return nil; + + NSURL *uploadFileURL = [NSURL URLWithString:uploadFileURLString]; + // There used to be a call here to NSURL checkResourceIsReachableAndReturnError: to check for the + // existence of the file (also tried NSFileManager fileExistsAtPath:). We've determined + // empirically that the check can fail at startup even when the upload file does in fact exist. + // For now, we'll go ahead and restore the background upload fetcher. If the file doesn't exist, + // it will fail later. + + NSString *uploadLocationURLString = metadata[kGTMSessionIdentifierUploadLocationURLMetadataKey]; + NSURL *uploadLocationURL = + uploadLocationURLString ? [NSURL URLWithString:uploadLocationURLString] : nil; + + NSString *uploadMIMEType = + metadata[kGTMSessionIdentifierUploadMIMETypeMetadataKey]; + int64_t uploadChunkSize = + [metadata[kGTMSessionIdentifierUploadChunkSizeMetadataKey] longLongValue]; + if (uploadChunkSize <= 0) { + uploadChunkSize = kGTMSessionUploadFetcherStandardChunkSize; + } + int64_t currentOffset = + [metadata[kGTMSessionIdentifierUploadCurrentOffsetMetadataKey] longLongValue]; + + BOOL allowsCellularAccess = YES; + if (metadata[kGTMSessionIdentifierUploadAllowsCellularAccess]) { + allowsCellularAccess = [metadata[kGTMSessionIdentifierUploadAllowsCellularAccess] boolValue]; + } + + GTMSESSION_ASSERT_DEBUG(currentOffset <= uploadFileLength, + @"CurrentOffset (%lld) exceeds UploadFileSize (%lld)", + currentOffset, uploadFileLength); + if (currentOffset > uploadFileLength) return nil; + + GTMSessionUploadFetcher *uploadFetcher = [self uploadFetcherWithLocation:uploadLocationURL + uploadMIMEType:uploadMIMEType + chunkSize:uploadChunkSize + allowsCellularAccess:allowsCellularAccess + fetcherService:nil]; + // Set the upload file length before setting the upload file URL tries to determine the length. + [uploadFetcher setUploadFileLength:uploadFileLength]; + + uploadFetcher.uploadFileURL = uploadFileURL; + uploadFetcher.sessionUserInfo = metadata; + uploadFetcher.useBackgroundSession = YES; + uploadFetcher.currentOffset = currentOffset; + uploadFetcher.delegateCallbackQueue = uploadFetcher.callbackQueue; + uploadFetcher.allowedInsecureSchemes = @[ @"http" ]; // Allowed on restored upload fetcher. + return uploadFetcher; +} + ++ (instancetype)uploadFetcherWithRequest:(NSURLRequest *)request + fetcherService:(GTMSessionFetcherService *)fetcherService { + // Internal utility method for instantiating fetchers + GTMSessionUploadFetcher *fetcher; + if ([fetcherService isKindOfClass:[GTMSessionFetcherService class]]) { + fetcher = [fetcherService fetcherWithRequest:request + fetcherClass:self]; + } else { + fetcher = [self fetcherWithRequest:request]; + } + fetcher.useBackgroundSession = YES; + return fetcher; +} + ++ (NSPointerArray *)uploadFetcherPointerArrayForBackgroundSessions { + static NSPointerArray *gUploadFetcherPointerArrayForBackgroundSessions = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gUploadFetcherPointerArrayForBackgroundSessions = [NSPointerArray weakObjectsPointerArray]; + }); + return gUploadFetcherPointerArrayForBackgroundSessions; +} + ++ (instancetype)uploadFetcherForSessionIdentifier:(NSString *)sessionIdentifier { + GTMSESSION_ASSERT_DEBUG(sessionIdentifier != nil, @"Invalid session identifier"); + NSArray *uploadFetchersForBackgroundSessions = [self uploadFetchersForBackgroundSessions]; + for (GTMSessionUploadFetcher *uploadFetcher in uploadFetchersForBackgroundSessions) { + if ([uploadFetcher.chunkFetcher.sessionIdentifier isEqual:sessionIdentifier]) { + return uploadFetcher; + } + } + return nil; +} + ++ (NSArray *)uploadFetchersForBackgroundSessions { + NSMutableSet *restoredSessionIdentifiers = [[NSMutableSet alloc] init]; + NSMutableArray *uploadFetchers = [[NSMutableArray alloc] init]; + NSPointerArray *uploadFetcherPointerArray = [self uploadFetcherPointerArrayForBackgroundSessions]; + + // Collect the background session upload fetchers that are still in memory. + @synchronized(uploadFetcherPointerArray) { + [uploadFetcherPointerArray compact]; + for (GTMSessionUploadFetcher *uploadFetcher in uploadFetcherPointerArray) { + NSString *sessionIdentifier = uploadFetcher.chunkFetcher.sessionIdentifier; + if (sessionIdentifier) { + [restoredSessionIdentifiers addObject:sessionIdentifier]; + [uploadFetchers addObject:uploadFetcher]; + } + } + } // @synchronized(uploadFetcherPointerArray) + + // The system may have other ongoing background upload sessions. Restore upload fetchers for those + // too. + NSArray *fetchers = [GTMSessionFetcher fetchersForBackgroundSessions]; + for (GTMSessionFetcher *fetcher in fetchers) { + NSString *sessionIdentifier = fetcher.sessionIdentifier; + if (!sessionIdentifier || [restoredSessionIdentifiers containsObject:sessionIdentifier]) { + continue; + } + NSDictionary *sessionIdentifierMetadata = [fetcher sessionIdentifierMetadata]; + if (sessionIdentifierMetadata == nil) { + continue; + } + if (![sessionIdentifierMetadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] boolValue]) { + continue; + } + GTMSessionUploadFetcher *uploadFetcher = + [self uploadFetcherForSessionIdentifierMetadata:sessionIdentifierMetadata]; + if (uploadFetcher == nil) { + // Something went wrong with this upload fetcher, so kill the restored chunk fetcher. + [fetcher stopFetching]; + continue; + } + [uploadFetchers addObject:uploadFetcher]; + uploadFetcher->_chunkFetcher = fetcher; + uploadFetcher->_fetcherInFlight = fetcher; + [uploadFetcher attachSendProgressBlockToChunkFetcher:fetcher]; + fetcher.completionHandler = + [fetcher completionHandlerWithTarget:uploadFetcher + didFinishSelector:@selector(chunkFetcher:finishedWithData:error:)]; + + GTMSESSION_LOG_DEBUG(@"%@ restoring upload fetcher %@ for chunk fetcher %@", + [self class], uploadFetcher, fetcher); + } + return uploadFetchers; +} + +- (void)setUploadData:(NSData *)data { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadData != data) { + _uploadData = data; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSData *)uploadData { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadData; + } +} + +- (void)setUploadFileHandle:(NSFileHandle *)fh { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileHandle != fh) { + _uploadFileHandle = fh; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSFileHandle *)uploadFileHandle { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadFileHandle; + } +} + +- (void)setUploadFileURL:(NSURL *)uploadURL { + BOOL changed = NO; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileURL != uploadURL) { + _uploadFileURL = uploadURL; + changed = YES; + } + } + if (changed) { + [self setupRequestHeaders]; + } +} + +- (NSURL *)uploadFileURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadFileURL; + } +} + +- (void)setUploadFileLength:(int64_t)fullLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadFileLength == kGTMSessionUploadFetcherUnknownFileSize && + fullLength != kGTMSessionUploadFetcherUnknownFileSize) { + _uploadFileLength = fullLength; + } + } +} + +- (void)setUploadDataLength:(int64_t)fullLength + provider:(GTMSessionUploadFetcherDataProvider)block { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadDataProvider = [block copy]; + _uploadFileLength = fullLength; + } + [self setupRequestHeaders]; +} + +- (GTMSessionUploadFetcherDataProvider)uploadDataProvider { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadDataProvider; + } +} + + +- (void)setUploadMIMEType:(NSString *)uploadMIMEType { + GTMSESSION_ASSERT_DEBUG(0, @"TODO: disallow setUploadMIMEType by making declaration readonly"); + // (and uploadMIMEType, chunksize, currentOffset) + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadMIMEType = uploadMIMEType; + } +} + +- (NSString *)uploadMIMEType { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadMIMEType; + } +} + +- (int64_t)chunkSize { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _chunkSize; + } +} + +- (void)setupRequestHeaders { + GTMSessionCheckNotSynchronized(self); + +#if DEBUG + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + int hasData = (_uploadData != nil) ? 1 : 0; + int hasFileHandle = (_uploadFileHandle != nil) ? 1 : 0; + int hasFileURL = (_uploadFileURL != nil) ? 1 : 0; + int hasUploadDataProvider = (_uploadDataProvider != nil) ? 1 : 0; + int numberOfSources = hasData + hasFileHandle + hasFileURL + hasUploadDataProvider; + #pragma unused(numberOfSources) + GTMSESSION_ASSERT_DEBUG(numberOfSources == 1, + @"Need just one upload source (%d)", numberOfSources); + } // @synchronized(self) +#endif + + // Add our custom headers to the initial request indicating the data + // type and total size to be delivered later in the chunk requests. + NSMutableURLRequest *mutableRequest = [self.request mutableCopy]; + + GTMSESSION_ASSERT_DEBUG((mutableRequest == nil) != (_uploadLocationURL == nil), + @"Request and location are mutually exclusive"); + if (!mutableRequest) return; + + [mutableRequest setValue:kGTMSessionXGoogUploadProtocolResumable + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadProtocol]; + [mutableRequest setValue:@"start" + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + [mutableRequest setValue:_uploadMIMEType + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentType]; + [mutableRequest setValue:@([self fullUploadLength]).stringValue + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentLength]; + + NSString *method = mutableRequest.HTTPMethod; + if (method == nil || [method caseInsensitiveCompare:@"GET"] == NSOrderedSame) { + [mutableRequest setHTTPMethod:@"POST"]; + } + + // Ensure the user agent header identifies this to the upload server as a + // GTMSessionUploadFetcher client. The /1 can be incremented in the unlikely circumstance + // we need to make a bug fix in the client that the server can recognize. + NSString *const kUserAgentStub = @"(GTMSUF/1)"; + NSString *userAgent = [mutableRequest valueForHTTPHeaderField:@"User-Agent"]; + if (userAgent == nil + || [userAgent rangeOfString:kUserAgentStub].location == NSNotFound) { + if (userAgent.length == 0) { + userAgent = GTMFetcherStandardUserAgentString(nil); + } + userAgent = [userAgent stringByAppendingFormat:@" %@", kUserAgentStub]; + [mutableRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + [self setRequest:mutableRequest]; +} + +- (void)setLocationURL:(NSURL *GTM_NULLABLE_TYPE)location + uploadMIMEType:(NSString *)uploadMIMEType + chunkSize:(int64_t)chunkSize + allowsCellularAccess:(BOOL)allowsCellularAccess { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + GTMSESSION_ASSERT_DEBUG(chunkSize > 0, @"chunk size is zero"); + + _allowsCellularAccess = allowsCellularAccess; + + // When resuming an upload, set the known upload target URL. + _uploadLocationURL = location; + + _uploadMIMEType = uploadMIMEType; + _chunkSize = chunkSize; + + // Indicate that we've not yet determined the file handle's length + _uploadFileLength = kGTMSessionUploadFetcherUnknownFileSize; + + // Indicate that we've not yet determined the upload fetcher status + _recentChunkStatusCode = -1; + + // If this is restarting an upload begun by another fetcher, + // the location is specified but the request is nil + _isRestartedUpload = (location != nil); + } // @synchronized(self) +} + +- (int64_t)fullUploadLength { + int64_t result; + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_uploadData) { + result = (int64_t)_uploadData.length; + } else { + if (_uploadFileLength == kGTMSessionUploadFetcherUnknownFileSize) { + if (_uploadFileHandle) { + // First time through, seek to end to determine file length + _uploadFileLength = (int64_t)[_uploadFileHandle seekToEndOfFile]; + } else if (_uploadDataProvider) { + // _uploadFileLength is set when the _uploadDataProvider is set. + GTMSESSION_ASSERT_DEBUG(_uploadFileLength >= 0, @"No uploadDataProvider length set"); + } else { + NSNumber *filesizeNum; + NSError *valueError; + if ([_uploadFileURL getResourceValue:&filesizeNum + forKey:NSURLFileSizeKey + error:&valueError]) { + _uploadFileLength = filesizeNum.longLongValue; + } else { + GTMSESSION_ASSERT_DEBUG(NO, @"Cannot get file size: %@\n %@", + valueError, _uploadFileURL.path); + _uploadFileLength = 0; + } + } + } + result = _uploadFileLength; + } + } // @synchronized(self) + return result; +} + +// Make a subdata of the upload data. +- (void)generateChunkSubdataWithOffset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + GTMSessionUploadFetcherDataProvider uploadDataProvider = self.uploadDataProvider; + if (uploadDataProvider) { + uploadDataProvider(offset, length, response); + return; + } + + NSData *uploadData = self.uploadData; + if (uploadData) { + // NSData provided. + NSData *resultData; + if (offset == 0 && length == (int64_t)uploadData.length) { + resultData = uploadData; + } else { + int64_t dataLength = (int64_t)uploadData.length; + // Ensure our range is valid. b/18007814 + if (offset + length > dataLength) { + NSString *errorMessage = [NSString stringWithFormat: + @"Range invalid for upload data. offset: %lld\tlength: %lld\tdataLength: %lld", + offset, length, dataLength]; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + NSRange range = NSMakeRange((NSUInteger)offset, (NSUInteger)length); + + @try { + resultData = [uploadData subdataWithRange:range]; + } + @catch (NSException *exception) { + NSString *errorMessage = exception.description; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + } + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, nil); + return; + } + NSURL *uploadFileURL = self.uploadFileURL; + if (uploadFileURL) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self generateChunkSubdataFromFileURL:uploadFileURL + offset:offset + length:length + response:response]; + }); + return; + } + GTMSESSION_ASSERT_DEBUG(_uploadFileHandle, @"Unexpectedly missing upload data package"); + NSFileHandle *uploadFileHandle = self.uploadFileHandle; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self generateChunkSubdataFromFileHandle:uploadFileHandle + offset:offset + length:length + response:response]; + }); +} + +- (void)generateChunkSubdataFromFileHandle:(NSFileHandle *)fileHandle + offset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + NSData *resultData; + NSError *error; + @try { + [fileHandle seekToFileOffset:(unsigned long long)offset]; + resultData = [fileHandle readDataOfLength:(NSUInteger)length]; + } + @catch (NSException *exception) { + GTMSESSION_ASSERT_DEBUG(NO, @"uploadFileHandle failed to read, %@", exception); + error = [self uploadChunkUnavailableErrorWithDescription:exception.description]; + } + // The response always re-dispatches to the main thread, so we skip doing that here. + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, error); +} + +- (void)generateChunkSubdataFromFileURL:(NSURL *)fileURL + offset:(int64_t)offset + length:(int64_t)length + response:(GTMSessionUploadFetcherDataProviderResponse)response { + GTMSessionCheckNotSynchronized(self); + + NSData *resultData; + NSError *error; + int64_t fullUploadLength = [self fullUploadLength]; + NSData *mappedData = + [NSData dataWithContentsOfURL:fileURL + options:NSDataReadingMappedAlways + NSDataReadingUncached + error:&error]; + if (!mappedData) { + // We could not create an NSData by memory-mapping the file. +#if TARGET_IPHONE_SIMULATOR + // NSTemporaryDirectory() can differ in the simulator between app restarts, + // yet the contents for the new path remains unchanged, so try the latest temp path. + if ([error.domain isEqual:NSCocoaErrorDomain] && (error.code == NSFileReadNoSuchFileError)) { + NSString *filename = [fileURL lastPathComponent]; + NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:filename]; + NSURL *newFileURL = [NSURL fileURLWithPath:filePath]; + if (![newFileURL isEqual:fileURL]) { + [self generateChunkSubdataFromFileURL:newFileURL + offset:offset + length:length + response:response]; + return; + } + } +#endif + + // If the file is just too large to create an NSData for, or if for some other reason we can't + // map it, create an NSFileHandle instead to read a subset into an NSData. +#if DEBUG + NSNumber *fileSizeNum; + BOOL hasFileSize = [fileURL getResourceValue:&fileSizeNum forKey:NSURLFileSizeKey error:NULL]; + GTMSESSION_LOG_DEBUG(@"Note: uploadFileURL is falling back to creating upload chunks by reading" + @" an NSFileHandle since uploadFileURL failed to map the upload file," + @" file size %@, %@", + hasFileSize ? fileSizeNum : @"unknown", error); +#endif + + NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingFromURL:fileURL + error:&error]; + if (fileHandle != nil) { + [self generateChunkSubdataFromFileHandle:fileHandle + offset:offset + length:length + response:response]; + return; + } + GTMSESSION_ASSERT_DEBUG(NO, @"uploadFileURL failed to read, %@", error); + // Fall through with the error. + } else { + // Successfully created an NSData by memory-mapping the file. + if ((NSUInteger)(offset + length) > mappedData.length) { + NSString *errorMessage = [NSString stringWithFormat: + @"Range invalid for upload data. offset: %lld\tlength: %lld\tdataLength: %lld\texpected UploadLength: %lld", + offset, length, (long long)mappedData.length, fullUploadLength]; + GTMSESSION_ASSERT_DEBUG(NO, @"%@", errorMessage); + response(nil, + kGTMSessionUploadFetcherUnknownFileSize, + [self uploadChunkUnavailableErrorWithDescription:errorMessage]); + return; + } + if (offset > 0 || length < fullUploadLength) { + NSRange range = NSMakeRange((NSUInteger)offset, (NSUInteger)length); + resultData = [mappedData subdataWithRange:range]; + } else { + resultData = mappedData; + } + } + // The response always re-dispatches to the main thread, so we skip re-dispatching here. + response(resultData, kGTMSessionUploadFetcherUnknownFileSize, error); +} + +- (NSError *)uploadChunkUnavailableErrorWithDescription:(NSString *)description { + // The description in the userInfo is intended as a clue to programmers, not + // for client code to examine or rely on. + NSDictionary *userInfo = @{ @"description" : description }; + return [NSError errorWithDomain:kGTMSessionFetcherErrorDomain + code:GTMSessionFetcherErrorUploadChunkUnavailable + userInfo:userInfo]; +} + +- (NSError *)prematureFailureErrorWithUserInfo:(NSDictionary *)userInfo { + // An error for if we get an unexpected status from the upload server or + // otherwise cannot continue. This is an issue beyond the upload protocol; + // there's no way the client can do anything useful except give up. + NSError *error = [NSError errorWithDomain:kGTMSessionFetcherStatusDomain + code:501 // Not implemented + userInfo:userInfo]; + return error; +} + ++ (GTMSessionUploadFetcherStatus)uploadStatusFromResponseHeaders:(NSDictionary *)responseHeaders { + NSString *statusString = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus]; + if ([statusString isEqual:@"active"]) { + return kStatusActive; + } + if ([statusString isEqual:@"final"]) { + return kStatusFinal; + } + if ([statusString isEqual:@"cancelled"]) { + return kStatusCancelled; + } + return kStatusUnknown; +} + +#pragma mark Method overrides affecting the initial fetch only + +- (void)setCompletionHandler:(GTMSessionFetcherCompletionHandler)handler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCompletionHandler = handler; + } +} + +- (void)setDelegateCallbackQueue:(dispatch_queue_t GTM_NULLABLE_TYPE)queue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCallbackQueue = queue; + } +} + +- (dispatch_queue_t GTM_NULLABLE_TYPE)delegateCallbackQueue { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _delegateCallbackQueue; + } +} + +- (BOOL)isRestartedUpload { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isRestartedUpload; + } +} + +- (GTMSessionFetcher * GTM_NULLABLE_TYPE)chunkFetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _chunkFetcher; + } +} + +- (void)setChunkFetcher:(GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _chunkFetcher = fetcher; + } +} + +- (void)setFetcherInFlight:(GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _fetcherInFlight = fetcher; + } +} + +- (GTMSessionFetcher * GTM_NULLABLE_TYPE)fetcherInFlight { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _fetcherInFlight; + } +} + +- (void)setCancellationHandler:(GTMSessionUploadFetcherCancellationHandler GTM_NULLABLE_TYPE) + cancellationHandler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _cancellationHandler = cancellationHandler; + } +} + +- (GTMSessionUploadFetcherCancellationHandler GTM_NULLABLE_TYPE)cancellationHandler { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _cancellationHandler; + } +} + +- (void)beginFetchForRetry { + GTMSessionCheckNotSynchronized(self); + + // Override the superclass to reset the initial body length and fetcher-in-flight, + // then call the superclass implementation. + [self setInitialBodyLength:[self bodyLength]]; + + GTMSESSION_ASSERT_DEBUG(self.fetcherInFlight == nil, @"unexpected fetcher in flight: %@", + self.fetcherInFlight); + self.fetcherInFlight = self; + [super beginFetchForRetry]; +} + +- (void)beginFetchWithCompletionHandler:(GTMSessionFetcherCompletionHandler)handler { + GTMSessionCheckNotSynchronized(self); + + [self setInitialBodyLength:[self bodyLength]]; + + // We'll hold onto the superclass's callback queue so we can invoke the handler + // even after the superclass has released the queue and its callback handler, as + // happens during auth failure. + [self setDelegateCallbackQueue:self.callbackQueue]; + self.completionHandler = handler; + + if ([self isRestartedUpload]) { + // When restarting an upload, we know the destination location for chunk fetches, + // but we need to query to find the initial offset. + if (![self isPaused]) { + [self sendQueryForUploadOffsetWithFetcherProperties:self.properties]; + } + return; + } + // We don't want to call into the client's completion block immediately + // after the finish of the initial connection (the delegate is called only + // when uploading finishes), so we substitute our own completion block to be + // called when the initial connection finishes + GTMSESSION_ASSERT_DEBUG(self.fetcherInFlight == nil, @"unexpected fetcher in flight: %@", + self.fetcherInFlight); + + self.fetcherInFlight = self; + [super beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + self.fetcherInFlight = nil; + // callback + + BOOL hasTestBlock = (self.testBlock != nil); + if (![self isRestartedUpload] && !hasTestBlock) { + if (error == nil) { + [self beginChunkFetches]; + } else { + if ([self retryTimer] == nil) { + [self invokeFinalCallbackWithData:nil + error:error + shouldInvalidateLocation:YES]; + } + } + } else { + // If there was no initial request, then this fetch is resuming some + // other uploadFetcher's initial request, and the superclass's connection + // is never used, so at this point we call the user's actual completion + // block. + if (!hasTestBlock) { + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + } else { + // There was a test block, so we won't do chunk fetches, but we simulate obtaining + // the data to be uploaded from the upload data provider block or the file handle, + // and then call back. + [self generateChunkSubdataWithOffset:0 + length:[self fullUploadLength] + response:^(NSData *generateData, int64_t fullUploadLength, NSError *generateError) { + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + }]; + } + } + }]; +} + +- (void)beginChunkFetches { + GTMSessionCheckNotSynchronized(self); + +#if DEBUG + // The initial response of the resumable upload protocol should have an + // empty body + // + // This assert typically happens because the upload create/edit link URL was + // not supplied with the request, and the server is thus expecting a non- + // resumable request/response. + if (self.downloadedData.length > 0) { + NSData *downloadedData = self.downloadedData; + NSString *str = [[NSString alloc] initWithData:downloadedData + encoding:NSUTF8StringEncoding]; + #pragma unused(str) + GTMSESSION_ASSERT_DEBUG(NO, @"unexpected response data (uploading to the wrong URL?)\n%@", str); + } +#endif + + // We need to get the upload URL from the location header to continue. + NSDictionary *responseHeaders = [self responseHeaders]; + + [self retrieveUploadChunkGranularityFromResponseHeaders:responseHeaders]; + + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown, + @"beginChunkFetches has unexpected upload status for headers %@", responseHeaders); + + BOOL isPrematureStop = (uploadStatus == kStatusFinal) || (uploadStatus == kStatusCancelled); + + NSString *uploadLocationURLStr = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadURL]; + BOOL hasUploadLocation = (uploadLocationURLStr.length > 0); + + if (isPrematureStop || !hasUploadLocation) { + GTMSESSION_ASSERT_DEBUG(NO, @"Premature failure: upload-status:\"%@\" location:%@", + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus], uploadLocationURLStr); + // We cannot continue since we do not know the location to use + // as our upload destination. + NSDictionary *userInfo = nil; + NSData *downloadedData = self.downloadedData; + if (downloadedData.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : downloadedData }; + } + NSError *failureError = [self prematureFailureErrorWithUserInfo:userInfo]; + [self invokeFinalCallbackWithData:nil + error:failureError + shouldInvalidateLocation:YES]; + return; + } + + self.uploadLocationURL = [NSURL URLWithString:uploadLocationURLStr]; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc postNotificationName:kGTMSessionFetcherUploadLocationObtainedNotification + object:self]; + + // we've now sent all of the initial post body data, so we need to include + // its size in future progress indicator callbacks + [self setInitialBodySent:[self initialBodyLength]]; + + // just in case the user paused us during the initial fetch... + if (![self isPaused]) { + [self uploadNextChunkWithOffset:0]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didSendBodyData:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent + totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { + // Overrides the superclass. + [self invokeDelegateWithDidSendBytes:bytesSent + totalBytesSent:totalBytesSent + totalBytesExpectedToSend:totalBytesExpectedToSend + [self fullUploadLength]]; +} + +- (BOOL)shouldReleaseCallbacksUponCompletion { + // Overrides the superclass. + + // We don't want the superclass to release the delegate and callback + // blocks once the initial fetch has finished + // + // This is invoked for only successful completion of the connection; + // an error always will invoke and release the callbacks + return NO; +} + +- (void)invokeFinalCallbackWithData:(NSData *)data + error:(NSError *)error + shouldInvalidateLocation:(BOOL)shouldInvalidateLocation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (shouldInvalidateLocation) { + _uploadLocationURL = nil; + } + + dispatch_queue_t queue = _delegateCallbackQueue; + GTMSessionFetcherCompletionHandler handler = _delegateCompletionHandler; + if (queue && handler) { + [self invokeOnCallbackQueue:queue + afterUserStopped:NO + block:^{ + handler(data, error); + }]; + } + } // @synchronized(self) + + [self releaseUploadAndBaseCallbacks:!self.userStoppedFetching]; +} + +- (void)releaseUploadAndBaseCallbacks:(BOOL)shouldReleaseCancellation { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _delegateCallbackQueue = nil; + _delegateCompletionHandler = nil; + _uploadDataProvider = nil; + if (shouldReleaseCancellation) { + _cancellationHandler = nil; + } + } + + // Release the base class's callbacks, too, if needed. + [self releaseCallbacks]; +} + +- (void)stopFetchReleasingCallbacks:(BOOL)shouldReleaseCallbacks { + GTMSessionCheckNotSynchronized(self); + + // Clear _fetcherInFlight when stopped. Moved from stopFetching, since that's a public method, + // where this method does the work. Fixes issue clearing value when retryBlock included. + GTMSessionFetcher *fetcherInFlight = self.fetcherInFlight; + if (fetcherInFlight == self) { + self.fetcherInFlight = nil; + } + + [super stopFetchReleasingCallbacks:shouldReleaseCallbacks]; + + if (shouldReleaseCallbacks) { + [self releaseUploadAndBaseCallbacks:NO]; + } +} + +#pragma mark Chunk fetching methods + +- (void)uploadNextChunkWithOffset:(int64_t)offset { + // use the properties in each chunk fetcher + NSDictionary *props = [self properties]; + + [self uploadNextChunkWithOffset:offset + fetcherProperties:props]; +} + +- (void)sendQueryForUploadOffsetWithFetcherProperties:(NSDictionary *)props { + GTMSessionFetcher *queryFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:YES]; + queryFetcher.bodyData = [NSData data]; + + NSString *originalComment = self.comment; + [queryFetcher setCommentWithFormat:@"%@ (query offset)", + originalComment ? originalComment : @"upload"]; + + [queryFetcher setRequestValue:@"query" forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + + self.fetcherInFlight = queryFetcher; + [queryFetcher beginFetchWithDelegate:self + didFinishSelector:@selector(queryFetcher:finishedWithData:error:)]; +} + +- (void)queryFetcher:(GTMSessionFetcher *)queryFetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + self.fetcherInFlight = nil; + + NSDictionary *responseHeaders = [queryFetcher responseHeaders]; + NSString *sizeReceivedHeader; + + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown || error != nil, + @"query fetcher completion has unexpected upload status for headers %@", responseHeaders); + + if (error == nil) { + sizeReceivedHeader = [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadSizeReceived]; + + if (uploadStatus == kStatusCancelled || + (uploadStatus == kStatusActive && sizeReceivedHeader == nil)) { + NSDictionary *userInfo = nil; + if (data.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : data }; + } + error = [self prematureFailureErrorWithUserInfo:userInfo]; + } + } + + if (error == nil) { + int64_t offset = [sizeReceivedHeader longLongValue]; + int64_t fullUploadLength = [self fullUploadLength]; + if (uploadStatus == kStatusFinal || + (offset >= fullUploadLength && + fullUploadLength != kGTMSessionUploadFetcherUnknownFileSize)) { + // Handle we're done + [self chunkFetcher:queryFetcher finishedWithData:data error:nil]; + } else { + [self retrieveUploadChunkGranularityFromResponseHeaders:responseHeaders]; + [self uploadNextChunkWithOffset:offset]; + } + } else { + // Handle query error + [self chunkFetcher:queryFetcher finishedWithData:data error:error]; + } +} + +- (void)sendCancelUploadWithFetcherProperties:(NSDictionary *)props { + @synchronized(self) { + _isCancelInFlight = YES; + } + GTMSessionFetcher *cancelFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:YES]; + cancelFetcher.bodyData = [NSData data]; + + NSString *originalComment = self.comment; + [cancelFetcher setCommentWithFormat:@"%@ (cancel)", + originalComment ? originalComment : @"upload"]; + + [cancelFetcher setRequestValue:@"cancel" forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + + self.fetcherInFlight = cancelFetcher; + [cancelFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) { + self.fetcherInFlight = nil; + if (![self triggerCancellationHandlerForFetch:cancelFetcher data:data error:error]) { + if (error) { + GTMSESSION_LOG_DEBUG(@"cancelFetcher %@", error); + } + } + @synchronized(self) { + self->_isCancelInFlight = NO; + } + }]; +} + +- (void)uploadNextChunkWithOffset:(int64_t)offset + fetcherProperties:(NSDictionary *)props { + GTMSessionCheckNotSynchronized(self); + + // Example chunk headers: + // X-Goog-Upload-Command: upload, finalize + // X-Goog-Upload-Offset: 0 + // Content-Length: 2000000 + // Content-Type: image/jpeg + // + // {bytes 0-1999999} + + // The chunk upload URL requires no authentication header. + GTMSessionFetcher *chunkFetcher = [self uploadFetcherWithProperties:props + isQueryFetch:NO]; + [self attachSendProgressBlockToChunkFetcher:chunkFetcher]; + int64_t chunkSize = [self updateChunkFetcher:chunkFetcher + forChunkAtOffset:offset]; + BOOL isUploadingFileURL = (self.uploadFileURL != nil); + int64_t fullUploadLength = [self fullUploadLength]; + + // The chunk size may have changed, so determine again if we're uploading the full file. + BOOL isUploadingFullFile = (offset == 0 && + fullUploadLength != kGTMSessionUploadFetcherUnknownFileSize && + chunkSize >= fullUploadLength); + if (isUploadingFullFile && isUploadingFileURL) { + // The data is the full upload file URL. + chunkFetcher.bodyFileURL = self.uploadFileURL; + [self beginChunkFetcher:chunkFetcher + offset:offset]; + } else { + // Make an NSData for the subset for this upload chunk. + self.subdataGenerating = YES; + [self generateChunkSubdataWithOffset:offset + length:chunkSize + response:^(NSData *chunkData, int64_t uploadFileLength, NSError *chunkError) { + // The subdata methods may leave us on a background thread. + dispatch_async(dispatch_get_main_queue(), ^{ + self.subdataGenerating = NO; + + // dont allow the updating of fileLength for uploads not using a data provider as they + // should know the file length before the upload starts. + if (self->_uploadDataProvider != nil && uploadFileLength > 0) { + [self setUploadFileLength:uploadFileLength]; + // Update the command and content-length headers if this is the last chunk to be sent. + if (offset + chunkSize >= uploadFileLength) { + int64_t updatedChunkSize = [self updateChunkFetcher:chunkFetcher + forChunkAtOffset:offset]; + if (updatedChunkSize == 0) { + // Calling beginChunkFetcher early when there is no more data to send allows us to + // properly handle nil chunkData below without having to account for the case where + // we are just finalizing the file. + chunkFetcher.bodyData = [[NSData alloc] init]; + [self beginChunkFetcher:chunkFetcher + offset:offset]; + return; + } + } + } + + if (chunkData == nil) { + NSError *responseError = chunkError; + if (!responseError) { + responseError = [self uploadChunkUnavailableErrorWithDescription:@"chunkData is nil"]; + } + [self invokeFinalCallbackWithData:nil + error:responseError + shouldInvalidateLocation:YES]; + return; + } + + BOOL didWriteFile = NO; + if (isUploadingFileURL) { + // Make a temporary file with the data subset. + NSString *tempName = + [NSString stringWithFormat:@"GTMUpload_temp_%@", [[NSUUID UUID] UUIDString]]; + NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:tempName]; + NSError *writeError; + didWriteFile = [chunkData writeToFile:tempPath + options:NSDataWritingAtomic + error:&writeError]; + if (didWriteFile) { + chunkFetcher.bodyFileURL = [NSURL fileURLWithPath:tempPath]; + } else { + GTMSESSION_LOG_DEBUG(@"writeToFile failed: %@\n%@", writeError, tempPath); + } + } + if (!didWriteFile) { + chunkFetcher.bodyData = [chunkData copy]; + } + [self beginChunkFetcher:chunkFetcher + offset:offset]; + }); + }]; + } +} + +- (void)beginChunkFetcher:(GTMSessionFetcher *)chunkFetcher + offset:(int64_t)offset { + + // Track the current offset for progress reporting + self.currentOffset = offset; + + // Hang on to the fetcher in case we need to cancel it. We set these before beginning the + // chunk fetch so the observers notified of chunk fetches can inspect the upload fetcher to + // match to the chunk. + self.chunkFetcher = chunkFetcher; + self.fetcherInFlight = chunkFetcher; + + // Update the last chunk request, including any request headers. + self.lastChunkRequest = chunkFetcher.request; + + [chunkFetcher beginFetchWithDelegate:self + didFinishSelector:@selector(chunkFetcher:finishedWithData:error:)]; +} + +- (void)attachSendProgressBlockToChunkFetcher:(GTMSessionFetcher *)chunkFetcher { + chunkFetcher.sendProgressBlock = ^(int64_t bytesSent, int64_t totalBytesSent, + int64_t totalBytesExpectedToSend) { + // The total bytes expected include the initial body and the full chunked + // data, independent of how big this fetcher's chunk is. + int64_t initialBodySent = [self bodyLength]; // TODO(grobbins) use [self initialBodySent] + int64_t totalSent = initialBodySent + self.currentOffset + totalBytesSent; + int64_t totalExpected = initialBodySent + [self fullUploadLength]; + + [self invokeDelegateWithDidSendBytes:bytesSent + totalBytesSent:totalSent + totalBytesExpectedToSend:totalExpected]; + }; +} + +- (NSDictionary *)uploadSessionIdentifierMetadata { + NSMutableDictionary *metadata = [NSMutableDictionary dictionary]; + metadata[kGTMSessionIdentifierIsUploadChunkFetcherMetadataKey] = @YES; + GTMSESSION_ASSERT_DEBUG(self.uploadFileURL, + @"Invalid upload fetcher to create session identifier for metadata"); + metadata[kGTMSessionIdentifierUploadFileURLMetadataKey] = [self.uploadFileURL absoluteString]; + metadata[kGTMSessionIdentifierUploadFileLengthMetadataKey] = @([self fullUploadLength]); + + if (self.uploadLocationURL) { + metadata[kGTMSessionIdentifierUploadLocationURLMetadataKey] = + [self.uploadLocationURL absoluteString]; + } + if (self.uploadMIMEType) { + metadata[kGTMSessionIdentifierUploadMIMETypeMetadataKey] = self.uploadMIMEType; + } + metadata[kGTMSessionIdentifierUploadChunkSizeMetadataKey] = @(self.chunkSize); + metadata[kGTMSessionIdentifierUploadCurrentOffsetMetadataKey] = @(self.currentOffset); + metadata[kGTMSessionIdentifierUploadAllowsCellularAccess] = @(self.request.allowsCellularAccess); + + return metadata; +} + +- (GTMSessionFetcher *)uploadFetcherWithProperties:(NSDictionary *)properties + isQueryFetch:(BOOL)isQueryFetch { + GTMSessionCheckNotSynchronized(self); + + // Common code to make a request for a query command or for a chunk upload. + NSURL *uploadLocationURL = self.uploadLocationURL; + NSMutableURLRequest *chunkRequest = [NSMutableURLRequest requestWithURL:uploadLocationURL]; + [chunkRequest setHTTPMethod:@"PUT"]; + + // copy the user-agent from the original connection + // n.b. that self.request is nil for upload fetchers created with an existing upload location + // URL. + NSURLRequest *origRequest = self.request; + + chunkRequest.allowsCellularAccess = origRequest.allowsCellularAccess; + if (!origRequest) { + chunkRequest.allowsCellularAccess = _allowsCellularAccess; + } + NSString *userAgent = [origRequest valueForHTTPHeaderField:@"User-Agent"]; + if (userAgent.length > 0) { + [chunkRequest setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + } + + [chunkRequest setValue:kGTMSessionXGoogUploadProtocolResumable + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadProtocol]; + + // To avoid timeouts when debugging, copy the timeout of the initial fetcher. + NSTimeInterval origTimeout = [origRequest timeoutInterval]; + [chunkRequest setTimeoutInterval:origTimeout]; + + // + // Make a new chunk fetcher. + // + GTMSessionFetcher *chunkFetcher = [GTMSessionFetcher fetcherWithRequest:chunkRequest]; + chunkFetcher.callbackQueue = self.callbackQueue; + chunkFetcher.sessionUserInfo = self.sessionUserInfo; + chunkFetcher.configurationBlock = self.configurationBlock; + chunkFetcher.allowedInsecureSchemes = self.allowedInsecureSchemes; + chunkFetcher.allowLocalhostRequest = self.allowLocalhostRequest; + chunkFetcher.allowInvalidServerCertificates = self.allowInvalidServerCertificates; + chunkFetcher.useUploadTask = !isQueryFetch; + + if (self.uploadFileURL && !isQueryFetch && self.useBackgroundSession) { + [chunkFetcher createSessionIdentifierWithMetadata:[self uploadSessionIdentifierMetadata]]; + } + + // Give the chunk fetcher the same properties as the previous chunk fetcher + chunkFetcher.properties = [properties mutableCopy]; + [chunkFetcher setProperty:[NSValue valueWithNonretainedObject:self] + forKey:kGTMSessionUploadFetcherChunkParentKey]; + + // copy other fetcher settings to the new fetcher + chunkFetcher.retryEnabled = self.retryEnabled; + chunkFetcher.maxRetryInterval = self.maxRetryInterval; + + if ([self isRetryEnabled]) { + // We interpose our own retry method both so we can change the request to ask the server to + // tell us where to resume the chunk. + chunkFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *chunkError, + GTMSessionFetcherRetryResponse response) { + void (^finish)(BOOL) = ^(BOOL shouldRetry){ + // We'll retry by sending an offset query. + if (shouldRetry) { + self.shouldInitiateOffsetQuery = !isQueryFetch; + + // We don't know what our actual offset is anymore, but the server will tell us. + self.currentOffset = 0; + } + // We don't actually want to retry this specific fetcher. + response(NO); + }; + + GTMSessionFetcherRetryBlock retryBlock = self.retryBlock; + if (retryBlock) { + // Ask the client, then call the finish block above. + retryBlock(suggestedWillRetry, chunkError, finish); + } else { + finish(suggestedWillRetry); + } + }; + } + + return chunkFetcher; +} + +- (void)chunkFetcher:(GTMSessionFetcher *)chunkFetcher + finishedWithData:(NSData *)data + error:(NSError *)error { + BOOL hasDestroyedOldChunkFetcher = NO; + self.fetcherInFlight = nil; + + NSDictionary *responseHeaders = [chunkFetcher responseHeaders]; + GTMSessionUploadFetcherStatus uploadStatus = + [[self class] uploadStatusFromResponseHeaders:responseHeaders]; + GTMSESSION_ASSERT_DEBUG(uploadStatus != kStatusUnknown + || error != nil + || self.wasCreatedFromBackgroundSession, + @"chunk fetcher completion has kStatusUnknown upload status for headers %@ fetcher %@", + responseHeaders, self); + BOOL isUploadStatusStopped = (uploadStatus == kStatusFinal || uploadStatus == kStatusCancelled); + + // Check if the fetcher was actually querying. If it failed, do not retry, + // as it would enter an infinite retry loop. + NSString *uploadCommand = + chunkFetcher.request.allHTTPHeaderFields[kGTMSessionHeaderXGoogUploadCommand]; + BOOL isQueryFetch = [uploadCommand isEqual:@"query"]; + + // TODO + // Maybe here we can check to see if the request had x goog content length set. (the file length one). + int64_t previousContentLength = + [[chunkFetcher.request valueForHTTPHeaderField:@"Content-Length"] longLongValue]; + // The Content-Length header may not be present if the chunk fetcher was recreated from + // a background session. + BOOL hasKnownChunkSize = (previousContentLength > 0); + BOOL needsQuery = (!hasKnownChunkSize && !isUploadStatusStopped); + + if (error || (needsQuery && !isQueryFetch)) { + NSInteger status = error.code; + + // Status 4xx indicates a bad offset in the Google upload protocol. However, do not retry status + // 404 per spec, nor if the upload size appears to have been zero (since the server will just + // keep asking us to retry.) + if (self.shouldInitiateOffsetQuery || + (needsQuery && !isQueryFetch) || + ([error.domain isEqual:kGTMSessionFetcherStatusDomain] && + status >= 400 && status <= 499 && + status != 404 && + uploadStatus == kStatusActive && + previousContentLength > 0)) { + self.shouldInitiateOffsetQuery = NO; + [self destroyChunkFetcher]; + hasDestroyedOldChunkFetcher = YES; + [self sendQueryForUploadOffsetWithFetcherProperties:chunkFetcher.properties]; + } else { + // Some unexpected status has occurred; handle it as we would a regular + // object fetcher failure. + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:NO]; + } + } else { + // The chunk has uploaded successfully. + int64_t newOffset = self.currentOffset + previousContentLength; +#if DEBUG + // Verify that if we think all of the uploading data has been sent, the server responded with + // the "final" upload status. + BOOL hasUploadAllData = (newOffset == [self fullUploadLength]); + BOOL isFinalStatus = (uploadStatus == kStatusFinal); + #pragma unused(hasUploadAllData,isFinalStatus) + GTMSESSION_ASSERT_DEBUG(hasUploadAllData == isFinalStatus || !hasKnownChunkSize, + @"uploadStatus:%@ newOffset:%lld (%lld + %lld) fullUploadLength:%lld" + @" chunkFetcher:%@ requestHeaders:%@ responseHeaders:%@", + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadStatus], + newOffset, self.currentOffset, previousContentLength, + [self fullUploadLength], + chunkFetcher, chunkFetcher.request.allHTTPHeaderFields, + responseHeaders); +#endif + if (isUploadStatusStopped || (_currentOffset > _uploadFileLength && _uploadFileLength > 0)) { + // This was the last chunk. + if (error == nil && uploadStatus == kStatusCancelled) { + // Report cancelled status as an error. + NSDictionary *userInfo = nil; + if (data.length > 0) { + userInfo = @{ kGTMSessionFetcherStatusDataKey : data }; + } + data = nil; + error = [self prematureFailureErrorWithUserInfo:userInfo]; + } else { + // The upload is in final status. + // + // Take the chunk fetcher's data as the superclass data. + self.downloadedData = data; + self.statusCode = chunkFetcher.statusCode; + } + + // we're done + [self invokeFinalCallbackWithData:data + error:error + shouldInvalidateLocation:YES]; + } else { + // Start the next chunk. + self.currentOffset = newOffset; + + // We want to destroy this chunk fetcher before creating the next one, but + // we want to pass on its properties + NSDictionary *props = [chunkFetcher properties]; + + // We no longer need to be able to cancel this chunkFetcher. Destroy it + // before we create a new chunk fetcher. + [self destroyChunkFetcher]; + hasDestroyedOldChunkFetcher = YES; + + [self uploadNextChunkWithOffset:newOffset + fetcherProperties:props]; + } + } + if (!hasDestroyedOldChunkFetcher) { + [self destroyChunkFetcher]; + } +} + +- (void)destroyChunkFetcher { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_fetcherInFlight == _chunkFetcher) { + _fetcherInFlight = nil; + } + + [_chunkFetcher stopFetching]; + + NSURL *chunkFileURL = _chunkFetcher.bodyFileURL; + BOOL wasTemporaryUploadFile = ![chunkFileURL isEqual:_uploadFileURL]; + if (wasTemporaryUploadFile) { + NSError *error; + [[NSFileManager defaultManager] removeItemAtURL:chunkFileURL + error:&error]; + if (error) { + GTMSESSION_LOG_DEBUG(@"removingItemAtURL failed: %@\n%@", error, chunkFileURL); + } + } + + _recentChunkReponseHeaders = _chunkFetcher.responseHeaders; + + // To avoid retain cycles, remove all properties except the parent identifier. + _chunkFetcher.properties = + @{ kGTMSessionUploadFetcherChunkParentKey : [NSValue valueWithNonretainedObject:self] }; + + _chunkFetcher.retryBlock = nil; + _chunkFetcher.sendProgressBlock = nil; + _chunkFetcher = nil; + } // @synchronized(self) +} + +// This method calculates the proper values to pass to the client's send progress block. +// +// The actual total bytes sent include the initial body sent, plus the +// offset into the batched data prior to the current chunk fetcher + +- (void)invokeDelegateWithDidSendBytes:(int64_t)bytesSent + totalBytesSent:(int64_t)totalBytesSent + totalBytesExpectedToSend:(int64_t)totalBytesExpected { + GTMSessionCheckNotSynchronized(self); + + // Ensure the chunk fetcher survives the callback in case the user pauses the upload process. + __block GTMSessionFetcher *holdFetcher = self.chunkFetcher; + + [self invokeOnCallbackQueue:self.delegateCallbackQueue + afterUserStopped:NO + block:^{ + GTMSessionFetcherSendProgressBlock sendProgressBlock = self.sendProgressBlock; + if (sendProgressBlock) { + sendProgressBlock(bytesSent, totalBytesSent, totalBytesExpected); + } + holdFetcher = nil; + }]; +} + +- (void)retrieveUploadChunkGranularityFromResponseHeaders:(NSDictionary *)responseHeaders { + GTMSessionCheckNotSynchronized(self); + + // Standard granularity for Google uploads is 256K. + NSString *chunkGranularityHeader = + [responseHeaders objectForKey:kGTMSessionHeaderXGoogUploadChunkGranularity]; + self.uploadGranularity = chunkGranularityHeader.longLongValue; +} + +#pragma mark - + +- (BOOL)isPaused { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _isPaused; + } // @synchronized(self) +} + +- (void)pauseFetching { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _isPaused = YES; + } // @synchronized(self) + + // Pausing just means stopping the current chunk from uploading; + // when we resume, we will send a query request to the server to + // figure out what bytes to resume sending. + // + // We won't try to cancel the initial data upload, but rather will check + // for being paused in beginChunkFetches. + [self destroyChunkFetcher]; +} + +- (void)resumeFetching { + BOOL wasPaused; + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + wasPaused = _isPaused; + _isPaused = NO; + } // @synchronized(self) + + if (wasPaused) { + [self sendQueryForUploadOffsetWithFetcherProperties:self.properties]; + } +} + +- (void)stopFetching { + // Overrides the superclass + [self destroyChunkFetcher]; + + // If we think the server is waiting for more data, then tell it there won't be more. + if (self.uploadLocationURL) { + [self sendCancelUploadWithFetcherProperties:[self properties]]; + self.uploadLocationURL = nil; + } else { + [self invokeOnCallbackQueue:self.callbackQueue + afterUserStopped:YES + block:^{ + // Repeated calls to stopFetching may cause this path to be reached despite having sent a real + // cancel request, check here to ensure that the cancellation handler invocation which fires + // will definitely be for the real request sent previously. + @synchronized(self) { + if (self->_isCancelInFlight) { + return; + } + } + [self triggerCancellationHandlerForFetch:nil data:nil error:nil]; + }]; + } + + [super stopFetching]; +} + +// Fires the cancellation handler, returning whether there was a handler to be fired. +- (BOOL)triggerCancellationHandlerForFetch:(GTMSessionFetcher *)fetcher + data:(NSData *)data + error:(NSError *)error { + GTMSessionUploadFetcherCancellationHandler handler = self.cancellationHandler; + if (handler) { + handler(fetcher, data, error); + self.cancellationHandler = nil; + return YES; + } + return NO; +} + +#pragma mark - + +- (int64_t)updateChunkFetcher:(GTMSessionFetcher *)chunkFetcher + forChunkAtOffset:(int64_t)offset { + BOOL isUploadingFileURL = (self.uploadFileURL != nil); + + // Upload another chunk, meeting server-required granularity. + int64_t chunkSize = self.chunkSize; + + int64_t fullUploadLength = [self fullUploadLength]; + BOOL isFileLengthKnown = fullUploadLength >= 0; + + BOOL isUploadingFullFile = (offset == 0 && isFileLengthKnown && chunkSize >= fullUploadLength); + if (!isUploadingFileURL || !isUploadingFullFile) { + // We're not uploading the entire file and given the file URL. Since we'll be + // allocating a subdata block for a chunk, we need to bound it to something that + // won't blow the process's memory. + if (chunkSize > kGTMSessionUploadFetcherMaximumDemandBufferSize) { + chunkSize = kGTMSessionUploadFetcherMaximumDemandBufferSize; + } + } + + int64_t granularity = self.uploadGranularity; + if (granularity > 0) { + if (chunkSize < granularity) { + chunkSize = granularity; + } else { + chunkSize = chunkSize - (chunkSize % granularity); + } + } + + GTMSESSION_ASSERT_DEBUG(offset < fullUploadLength || fullUploadLength == 0, + @"offset %lld exceeds data length %lld", offset, fullUploadLength); + + if (granularity > 0) { + offset = offset - (offset % granularity); + } + + // If the chunk size is bigger than the remaining data, or else + // it's close enough in size to the remaining data that we'd rather + // avoid having a whole extra http fetch for the leftover bit, then make + // this chunk size exactly match the remaining data size + NSString *command; + int64_t thisChunkSize = chunkSize; + + BOOL isChunkTooBig = (thisChunkSize >= (fullUploadLength - offset)); + BOOL isChunkAlmostBigEnough = (fullUploadLength - offset - 2500 < thisChunkSize); + BOOL isFinalChunk = (isChunkTooBig || isChunkAlmostBigEnough) && isFileLengthKnown; + if (isFinalChunk) { + thisChunkSize = fullUploadLength - offset; + if (thisChunkSize > 0) { + command = @"upload, finalize"; + } else { + command = @"finalize"; + } + } else { + command = @"upload"; + } + NSString *lengthStr = @(thisChunkSize).stringValue; + NSString *offsetStr = @(offset).stringValue; + + [chunkFetcher setRequestValue:command forHTTPHeaderField:kGTMSessionHeaderXGoogUploadCommand]; + [chunkFetcher setRequestValue:lengthStr forHTTPHeaderField:@"Content-Length"]; + [chunkFetcher setRequestValue:offsetStr forHTTPHeaderField:kGTMSessionHeaderXGoogUploadOffset]; + if (_uploadFileLength != kGTMSessionUploadFetcherUnknownFileSize) { + [chunkFetcher setRequestValue:@([self fullUploadLength]).stringValue + forHTTPHeaderField:kGTMSessionHeaderXGoogUploadContentLength]; + } + + // Append the range of bytes in this chunk to the fetcher comment. + NSString *baseComment = self.comment; + [chunkFetcher setCommentWithFormat:@"%@ (%lld-%lld)", + baseComment ? baseComment : @"upload", offset, MAX(0, offset + thisChunkSize - 1)]; + + return thisChunkSize; +} + +// Public properties. +@synthesize currentOffset = _currentOffset, + allowsCellularAccess = _allowsCellularAccess, + delegateCompletionHandler = _delegateCompletionHandler, + chunkFetcher = _chunkFetcher, + lastChunkRequest = _lastChunkRequest, + subdataGenerating = _subdataGenerating, + shouldInitiateOffsetQuery = _shouldInitiateOffsetQuery, + uploadGranularity = _uploadGranularity; + +// Internal properties. +@dynamic fetcherInFlight; +@dynamic activeFetcher; +@dynamic statusCode; +@dynamic delegateCallbackQueue; + ++ (void)removePointer:(void *)pointer fromPointerArray:(NSPointerArray *)pointerArray { + for (NSUInteger index = 0, count = pointerArray.count; index < count; ++index) { + void *pointerAtIndex = [pointerArray pointerAtIndex:index]; + if (pointerAtIndex == pointer) { + [pointerArray removePointerAtIndex:index]; + return; + } + } +} + +- (BOOL)useBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _useBackgroundSessionOnChunkFetchers; + } // @synchronized(self +} + +- (void)setUseBackgroundSession:(BOOL)useBackgroundSession { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_useBackgroundSessionOnChunkFetchers != useBackgroundSession) { + _useBackgroundSessionOnChunkFetchers = useBackgroundSession; + NSPointerArray *uploadFetcherPointerArrayForBackgroundSessions = + [[self class] uploadFetcherPointerArrayForBackgroundSessions]; + @synchronized(uploadFetcherPointerArrayForBackgroundSessions) { + if (_useBackgroundSessionOnChunkFetchers) { + [uploadFetcherPointerArrayForBackgroundSessions addPointer:(__bridge void *)self]; + } else { + [[self class] removePointer:(__bridge void *)self + fromPointerArray:uploadFetcherPointerArrayForBackgroundSessions]; + } + } // @synchronized(uploadFetcherPointerArrayForBackgroundSessions) + } + } // @synchronized(self) +} + +- (BOOL)canFetchWithBackgroundSession { + // The initial upload fetcher is always a foreground session; the + // useBackgroundSession property will apply only to chunk fetchers, + // not to queries. + return NO; +} + +- (NSDictionary *)responseHeaders { + GTMSessionCheckNotSynchronized(self); + // Overrides the superclass + + // If asked for the fetcher's response, use the most recent chunk fetcher's response, + // since the original request's response lacks useful information like the actual + // Content-Type. + NSDictionary *dict = self.chunkFetcher.responseHeaders; + if (dict) { + return dict; + } + + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + if (_recentChunkReponseHeaders) { + return _recentChunkReponseHeaders; + } + } // @synchronized(self + + // No chunk fetcher yet completed, so return whatever we have from the initial fetch. + return [super responseHeaders]; +} + +- (NSInteger)statusCodeUnsynchronized { + GTMSessionCheckSynchronized(self); + + if (_recentChunkStatusCode != -1) { + // Overrides the superclass to indicate status appropriate to the initial + // or latest chunk fetch + return _recentChunkStatusCode; + } else { + return [super statusCodeUnsynchronized]; + } +} + + +- (void)setStatusCode:(NSInteger)val { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _recentChunkStatusCode = val; + } +} + +- (int64_t)initialBodyLength { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _initialBodyLength; + } +} + +- (void)setInitialBodyLength:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _initialBodyLength = length; + } +} + +- (int64_t)initialBodySent { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _initialBodySent; + } +} + +- (void)setInitialBodySent:(int64_t)length { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _initialBodySent = length; + } +} + +- (NSURL *)uploadLocationURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + return _uploadLocationURL; + } +} + +- (void)setUploadLocationURL:(NSURL *)locationURL { + @synchronized(self) { + GTMSessionMonitorSynchronized(self); + + _uploadLocationURL = locationURL; + } +} + +- (GTMSessionFetcher *)activeFetcher { + GTMSessionFetcher *result = self.fetcherInFlight; + if (result) return result; + + return self; +} + +- (BOOL)isFetching { + // If there is an active chunk fetcher, then the upload fetcher is considered + // to still be fetching. + if (self.fetcherInFlight != nil) return YES; + + return [super isFetching]; +} + +- (BOOL)waitForCompletionWithTimeout:(NSTimeInterval)timeoutInSeconds { + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutInSeconds]; + + while (self.fetcherInFlight || self.subdataGenerating) { + if ([timeoutDate timeIntervalSinceNow] < 0) return NO; + + if (self.subdataGenerating) { + // Allow time for subdata generation. + NSDate *stopDate = [NSDate dateWithTimeIntervalSinceNow:0.001]; + [[NSRunLoop currentRunLoop] runUntilDate:stopDate]; + } else { + // Wait for any chunk or query fetchers that still have pending callbacks or + // notifications. + BOOL timedOut; + + if (self.fetcherInFlight == self) { + timedOut = ![super waitForCompletionWithTimeout:timeoutInSeconds]; + } else { + timedOut = ![self.fetcherInFlight waitForCompletionWithTimeout:timeoutInSeconds]; + } + if (timedOut) return NO; + } + } + return YES; +} + +@end + +@implementation GTMSessionFetcher (GTMSessionUploadFetcherMethods) + +- (GTMSessionUploadFetcher *)parentUploadFetcher { + NSValue *property = [self propertyForKey:kGTMSessionUploadFetcherChunkParentKey]; + if (!property) return nil; + + GTMSessionUploadFetcher *uploadFetcher = property.nonretainedObjectValue; + + GTMSESSION_ASSERT_DEBUG([uploadFetcher isKindOfClass:[GTMSessionUploadFetcher class]], + @"Unexpected parent upload fetcher class: %@", [uploadFetcher class]); + return uploadFetcher; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement b/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement new file mode 100755 index 0000000..de27b25 Binary files /dev/null and b/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/GoogleAppMeasurement differ diff --git a/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap b/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap new file mode 100755 index 0000000..de80e9e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleAppMeasurement/Frameworks/GoogleAppMeasurement.framework/Modules/module.modulemap @@ -0,0 +1,11 @@ +framework module GoogleAppMeasurement { + export * + module * { export * } + link "sqlite3" + link "z" + link framework "CoreData" + link framework "Security" + link framework "StoreKit" + link framework "SystemConfiguration" + link framework "UIKit" +} diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m new file mode 100644 index 0000000..3e5f57b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m @@ -0,0 +1,36 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORAssert.h" + +GDTCORAssertionBlock GDTCORAssertionBlockToRunInstead(void) { + // This class is only compiled in by unit tests, and this should fail quickly in optimized builds. + Class GDTCORAssertClass = NSClassFromString(@"GDTCORAssertHelper"); + if (__builtin_expect(!!GDTCORAssertClass, 0)) { + SEL assertionBlockSEL = NSSelectorFromString(@"assertionBlock"); + if (assertionBlockSEL) { + IMP assertionBlockIMP = [GDTCORAssertClass methodForSelector:assertionBlockSEL]; + if (assertionBlockIMP) { + GDTCORAssertionBlock assertionBlock = ((GDTCORAssertionBlock(*)(id, SEL))assertionBlockIMP)( + GDTCORAssertClass, assertionBlockSEL); + if (assertionBlock) { + return assertionBlock; + } + } + } + } + return NULL; +} diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m new file mode 100644 index 0000000..f0ea8ab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORClock.m @@ -0,0 +1,164 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORClock.h" + +#import + +// Using a monotonic clock is necessary because CFAbsoluteTimeGetCurrent(), NSDate, and related all +// are subject to drift. That it to say, multiple consecutive calls do not always result in a +// time that is in the future. Clocks may be adjusted by the user, NTP, or any number of external +// factors. This class attempts to determine the wall-clock time at the time of the event by +// capturing the kernel start and time since boot to determine a wallclock time in UTC. +// +// Timezone offsets at the time of a snapshot are also captured in order to provide local-time +// details. Other classes in this library depend on comparing times at some time in the future to +// a time captured in the past, and this class needs to provide a mechanism to do that. +// +// TL;DR: This class attempts to accomplish two things: 1. Provide accurate event times. 2. Provide +// a monotonic clock mechanism to accurately check if some clock snapshot was before or after +// by using a shared reference point (kernel boot time). +// +// Note: Much of the mach time stuff doesn't work properly in the simulator. So this class can be +// difficult to unit test. + +/** Returns the kernel boottime property from sysctl. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The KERN_BOOTTIME property from sysctl, in nanoseconds. + */ +static int64_t KernelBootTimeInNanoseconds() { + // Caching the result is not possible because clock drift would not be accounted for. + struct timeval boottime; + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + size_t size = sizeof(boottime); + int rc = sysctl(mib, 2, &boottime, &size, NULL, 0); + if (rc != 0) { + return 0; + } + return (int64_t)boottime.tv_sec * NSEC_PER_MSEC + (int64_t)boottime.tv_usec; +} + +/** Returns value of gettimeofday, in nanoseconds. + * + * Inspired by https://stackoverflow.com/a/40497811 + * + * @return The value of gettimeofday, in nanoseconds. + */ +static int64_t UptimeInNanoseconds() { + int64_t before_now; + int64_t after_now; + struct timeval now; + + before_now = KernelBootTimeInNanoseconds(); + // Addresses a race condition in which the system time has updated, but the boottime has not. + do { + gettimeofday(&now, NULL); + after_now = KernelBootTimeInNanoseconds(); + } while (after_now != before_now); + return (int64_t)now.tv_sec * NSEC_PER_MSEC + (int64_t)now.tv_usec - before_now; +} + +// TODO: Consider adding a 'trustedTime' property that can be populated by the response from a BE. +@implementation GDTCORClock + +- (instancetype)init { + self = [super init]; + if (self) { + _kernelBootTime = KernelBootTimeInNanoseconds(); + _uptime = UptimeInNanoseconds(); + _timeMillis = + (int64_t)((CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) * NSEC_PER_USEC); + CFTimeZoneRef timeZoneRef = CFTimeZoneCopySystem(); + _timezoneOffsetSeconds = CFTimeZoneGetSecondsFromGMT(timeZoneRef, 0); + CFRelease(timeZoneRef); + } + return self; +} + ++ (GDTCORClock *)snapshot { + return [[GDTCORClock alloc] init]; +} + ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture { + GDTCORClock *snapshot = [self snapshot]; + snapshot->_timeMillis += millisInTheFuture; + return snapshot; +} + +- (BOOL)isAfter:(GDTCORClock *)otherClock { + // These clocks are trivially comparable when they share a kernel boot time. + if (_kernelBootTime == otherClock->_kernelBootTime) { + int64_t timeDiff = (_timeMillis + _timezoneOffsetSeconds) - + (otherClock->_timeMillis + otherClock->_timezoneOffsetSeconds); + return timeDiff > 0; + } else { + int64_t kernelBootTimeDiff = otherClock->_kernelBootTime - _kernelBootTime; + // This isn't a great solution, but essentially, if the other clock's boot time is 'later', NO + // is returned. This can be altered by changing the system time and rebooting. + return kernelBootTimeDiff < 0 ? YES : NO; + } +} + +- (NSUInteger)hash { + return [@(_kernelBootTime) hash] ^ [@(_uptime) hash] ^ [@(_timeMillis) hash] ^ + [@(_timezoneOffsetSeconds) hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +#pragma mark - NSSecureCoding + +/** NSKeyedCoder key for timeMillis property. */ +static NSString *const kGDTCORClockTimeMillisKey = @"GDTCORClockTimeMillis"; + +/** NSKeyedCoder key for timezoneOffsetMillis property. */ +static NSString *const kGDTCORClockTimezoneOffsetSeconds = @"GDTCORClockTimezoneOffsetSeconds"; + +/** NSKeyedCoder key for _kernelBootTime ivar. */ +static NSString *const kGDTCORClockKernelBootTime = @"GDTCORClockKernelBootTime"; + +/** NSKeyedCoder key for _uptime ivar. */ +static NSString *const kGDTCORClockUptime = @"GDTCORClockUptime"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + // TODO: If the kernelBootTime is more recent, we need to change the kernel boot time and + // uptimeMillis ivars + _timeMillis = [aDecoder decodeInt64ForKey:kGDTCORClockTimeMillisKey]; + _timezoneOffsetSeconds = [aDecoder decodeInt64ForKey:kGDTCORClockTimezoneOffsetSeconds]; + _kernelBootTime = [aDecoder decodeInt64ForKey:kGDTCORClockKernelBootTime]; + _uptime = [aDecoder decodeInt64ForKey:kGDTCORClockUptime]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeInt64:_timeMillis forKey:kGDTCORClockTimeMillisKey]; + [aCoder encodeInt64:_timezoneOffsetSeconds forKey:kGDTCORClockTimezoneOffsetSeconds]; + [aCoder encodeInt64:_kernelBootTime forKey:kGDTCORClockKernelBootTime]; + [aCoder encodeInt64:_uptime forKey:kGDTCORClockUptime]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m new file mode 100644 index 0000000..6df92a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORConsoleLogger.h" + +/** The console logger prefix. */ +static NSString *kGDTCORConsoleLogger = @"[GoogleDataTransport]"; + +NSString *GDTCORMessageCodeEnumToString(GDTCORMessageCode code) { + return [[NSString alloc] initWithFormat:@"I-GDTCOR%06ld", (long)code]; +} + +void GDTCORLog(GDTCORMessageCode code, NSString *format, ...) { +// Don't log anything in not debug builds. +#if !NDEBUG + NSString *logFormat = [NSString stringWithFormat:@"%@[%@] %@", kGDTCORConsoleLogger, + GDTCORMessageCodeEnumToString(code), format]; + va_list args; + va_start(args, format); + NSLogv(logFormat, args); + va_end(args); +#endif // !NDEBUG +} diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m new file mode 100644 index 0000000..33c3f15 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m @@ -0,0 +1,64 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@implementation GDTCORDataFuture + +- (instancetype)initWithFileURL:(NSURL *)fileURL { + self = [super init]; + if (self) { + _fileURL = fileURL; + } + return self; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (NSUInteger)hash { + // In reality, only one of these should be populated. + return [_fileURL hash] ^ [_originalData hash]; +} + +#pragma mark - NSSecureCoding + +/** Coding key for _fileURL ivar. */ +static NSString *kGDTCORDataFutureFileURLKey = @"GDTCORDataFutureFileURLKey"; + +/** Coding key for _data ivar. */ +static NSString *kGDTCORDataFutureDataKey = @"GDTCORDataFutureDataKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_fileURL forKey:kGDTCORDataFutureFileURLKey]; + [aCoder encodeObject:_originalData forKey:kGDTCORDataFutureDataKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [self init]; + if (self) { + _fileURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kGDTCORDataFutureFileURLKey]; + _originalData = [aDecoder decodeObjectOfClass:[NSData class] forKey:kGDTCORDataFutureDataKey]; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m new file mode 100644 index 0000000..ed0c8e8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m @@ -0,0 +1,123 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" + +@implementation GDTCOREvent + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"Please give a valid mapping ID"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _target = target; + _qosTier = GDTCOREventQosDefault; + } + GDTCORLogDebug("Event %@ created. mappingID: %@ target:%ld qos:%ld", self, _mappingID, + (long)_target, (long)_qosTier); + return self; +} + +- (instancetype)copy { + GDTCOREvent *copy = [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; + copy.dataObject = _dataObject; + copy.dataObjectTransportBytes = _dataObjectTransportBytes; + copy.qosTier = _qosTier; + copy.clockSnapshot = _clockSnapshot; + copy.customPrioritizationParams = _customPrioritizationParams; + GDTCORLogDebug("Copying event %@ to event %@", self, copy); + return copy; +} + +- (NSUInteger)hash { + // This loses some precision, but it's probably fine. + NSUInteger mappingIDHash = [_mappingID hash]; + NSUInteger timeHash = [_clockSnapshot hash]; + NSUInteger dataObjectTransportBytesHash = [_dataObjectTransportBytes hash]; + return mappingIDHash ^ _target ^ dataObjectTransportBytesHash ^ _qosTier ^ timeHash; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (void)setDataObject:(id)dataObject { + // If you're looking here because of a performance issue in -transportBytes slowing the assignment + // of -dataObject, one way to address this is to add a queue to this class, + // dispatch_(barrier_ if concurrent)async here, and implement the getter with a dispatch_sync. + if (dataObject != _dataObject) { + _dataObject = dataObject; + _dataObjectTransportBytes = [dataObject transportBytes]; + } +} + +- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture { + return [[GDTCORStoredEvent alloc] initWithEvent:self dataFuture:dataFuture]; +} + +#pragma mark - NSSecureCoding and NSCoding Protocols + +/** NSCoding key for mappingID property. */ +static NSString *mappingIDKey = @"_mappingID"; + +/** NSCoding key for target property. */ +static NSString *targetKey = @"_target"; + +/** NSCoding key for dataObjectTransportBytes property. */ +static NSString *dataObjectTransportBytesKey = @"_dataObjectTransportBytesKey"; + +/** NSCoding key for qosTier property. */ +static NSString *qosTierKey = @"_qosTier"; + +/** NSCoding key for clockSnapshot property. */ +static NSString *clockSnapshotKey = @"_clockSnapshot"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + NSString *mappingID = [aDecoder decodeObjectOfClass:[NSObject class] forKey:mappingIDKey]; + NSInteger target = [aDecoder decodeIntegerForKey:targetKey]; + self = [self initWithMappingID:mappingID target:target]; + if (self) { + _dataObjectTransportBytes = [aDecoder decodeObjectOfClass:[NSData class] + forKey:dataObjectTransportBytesKey]; + _qosTier = [aDecoder decodeIntegerForKey:qosTierKey]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:clockSnapshotKey]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [aCoder encodeObject:_mappingID forKey:mappingIDKey]; + [aCoder encodeInteger:_target forKey:targetKey]; + [aCoder encodeObject:_dataObjectTransportBytes forKey:dataObjectTransportBytesKey]; + [aCoder encodeInteger:_qosTier forKey:qosTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:clockSnapshotKey]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m new file mode 100644 index 0000000..cd554ad --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m @@ -0,0 +1,132 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORLifecycle.h" + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +@implementation GDTCORLifecycle + ++ (void)load { + [self sharedInstance]; +} + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance { + static GDTCORLifecycle *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORLifecycle alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:kGDTCORApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(applicationWillEnterForeground:) + name:kGDTCORApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = kGDTCORApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(applicationWillTerminate:) + name:name + object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)applicationDidEnterBackground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is backgrounding."); + [[GDTCORTransformer sharedInstance] appWillBackground:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is backgrounding."); + [[GDTCORStorage sharedInstance] appWillBackground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is backgrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillBackground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillBackground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is backgrounding."); + [[GDTCORRegistrar sharedInstance] appWillBackground:application]; + } +} + +- (void)applicationWillEnterForeground:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is foregrounding."); + [[GDTCORTransformer sharedInstance] appWillForeground:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is foregrounding."); + [[GDTCORStorage sharedInstance] appWillForeground:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is foregrounding."); + [[GDTCORUploadCoordinator sharedInstance] appWillForeground:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillForeground:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is foregrounding."); + [[GDTCORRegistrar sharedInstance] appWillForeground:application]; + } +} + +- (void)applicationWillTerminate:(NSNotification *)notification { + GDTCORApplication *application = [GDTCORApplication sharedApplication]; + if ([[GDTCORTransformer sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORTransformer that the app is terminating."); + [[GDTCORTransformer sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORStorage sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORStorage that the app is terminating."); + [[GDTCORStorage sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORUploadCoordinator sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORUploadCoordinator that the app is terminating."); + [[GDTCORUploadCoordinator sharedInstance] appWillTerminate:application]; + } + if ([[GDTCORRegistrar sharedInstance] respondsToSelector:@selector(appWillTerminate:)]) { + GDTCORLogDebug("%@", @"Signaling GDTCORRegistrar that the app is terminating."); + [[GDTCORRegistrar sharedInstance] appWillTerminate:application]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m new file mode 100644 index 0000000..778ced9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m @@ -0,0 +1,222 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#ifdef GDTCOR_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +NSString *const kGDTCORVersion = @STR(GDTCOR_VERSION); +#else +NSString *const kGDTCORVersion = @"Unknown"; +#endif // GDTCOR_VERSION + +const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid = 0; + +NSString *const kGDTCORApplicationDidEnterBackgroundNotification = + @"GDTCORApplicationDidEnterBackgroundNotification"; + +NSString *const kGDTCORApplicationWillEnterForegroundNotification = + @"GDTCORApplicationWillEnterForegroundNotification"; + +NSString *const kGDTCORApplicationWillTerminateNotification = + @"GDTCORApplicationWillTerminateNotification"; +#if !TARGET_OS_WATCH +BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags) { +#if TARGET_OS_IOS + return (flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN; +#else + return NO; +#endif // TARGET_OS_IOS +} +#endif // !TARGET_OS_WATCH + +@interface GDTCORApplication () +/** + Private flag to match the existing `readonly` public flag. This will be accurate for all platforms, + since we handle each platform's lifecycle notifications separately. + */ +@property(atomic, readwrite) BOOL isRunningInBackground; + +@end + +@implementation GDTCORApplication + ++ (void)load { + GDTCORLogDebug( + "%@", @"GDT is initializing. Please note that if you quit the app via the " + "debugger and not through a lifecycle event, event data will remain on disk but " + "storage won't have a reference to them since the singleton wasn't saved to disk."); +#if TARGET_OS_IOS || TARGET_OS_TV + // If this asserts, please file a bug at https://github.com/firebase/firebase-ios-sdk/issues. + GDTCORFatalAssert( + GDTCORBackgroundIdentifierInvalid == UIBackgroundTaskInvalid, + @"GDTCORBackgroundIdentifierInvalid and UIBackgroundTaskInvalid should be the same."); +#endif + [self sharedApplication]; +} + ++ (nullable GDTCORApplication *)sharedApplication { + static GDTCORApplication *application; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + application = [[GDTCORApplication alloc] init]; + }); + return application; +} + +- (instancetype)init { + self = [super init]; + if (self) { + // This class will be instantiated in the foreground. + _isRunningInBackground = NO; + +#if TARGET_OS_IOS || TARGET_OS_TV + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + NSString *name = UIApplicationWillTerminateNotification; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillTerminate:) + name:name + object:nil]; + +#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + if (@available(iOS 13, tvOS 13.0, *)) { + [notificationCenter addObserver:self + selector:@selector(iOSApplicationWillEnterForeground:) + name:UISceneWillEnterForegroundNotification + object:nil]; + [notificationCenter addObserver:self + selector:@selector(iOSApplicationDidEnterBackground:) + name:UISceneWillDeactivateNotification + object:nil]; + } +#endif // defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 + +#elif TARGET_OS_OSX + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + [notificationCenter addObserver:self + selector:@selector(macOSApplicationWillTerminate:) + name:NSApplicationWillTerminateNotification + object:nil]; +#endif // TARGET_OS_IOS || TARGET_OS_TV + } + return self; +} + +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^)(void))handler { + GDTCORBackgroundIdentifier bgID = + [[self sharedApplicationForBackgroundTask] beginBackgroundTaskWithName:name + expirationHandler:handler]; +#if !NDEBUG + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug("Creating background task with name:%@ bgID:%ld", name, (long)bgID); + } +#endif // !NDEBUG + return bgID; +} + +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID { + if (bgID != GDTCORBackgroundIdentifierInvalid) { + GDTCORLogDebug("Ending background task with ID:%ld was successful", (long)bgID); + [[self sharedApplicationForBackgroundTask] endBackgroundTask:bgID]; + return; + } +} + +#pragma mark - App environment helpers + +- (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + +/** Returns a UIApplication instance if on the appropriate platform. + * + * @return The shared UIApplication if on the appropriate platform. + */ +#if TARGET_OS_IOS || TARGET_OS_TV +- (nullable UIApplication *)sharedApplicationForBackgroundTask { +#else +- (nullable id)sharedApplicationForBackgroundTask { +#endif + if ([self isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(@"UIApplication"); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - UIApplicationDelegate + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)iOSApplicationDidEnterBackground:(NSNotification *)notif { + _isRunningInBackground = YES; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is backgrounding."); + [notifCenter postNotificationName:kGDTCORApplicationDidEnterBackgroundNotification object:nil]; +} + +- (void)iOSApplicationWillEnterForeground:(NSNotification *)notif { + _isRunningInBackground = NO; + + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is foregrounding."); + [notifCenter postNotificationName:kGDTCORApplicationWillEnterForegroundNotification object:nil]; +} + +- (void)iOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - NSApplicationDelegate + +#if TARGET_OS_OSX +- (void)macOSApplicationWillTerminate:(NSNotification *)notif { + NSNotificationCenter *notifCenter = [NSNotificationCenter defaultCenter]; + GDTCORLogDebug("%@", @"GDTCORPlatform is sending a notif that the app is terminating."); + [notifCenter postNotificationName:kGDTCORApplicationWillTerminateNotification object:nil]; +} +#endif // TARGET_OS_OSX + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m new file mode 100644 index 0000000..1c6555a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m @@ -0,0 +1,118 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORReachability.h" +#import "GDTCORLibrary/Private/GDTCORReachability_Private.h" +#if !TARGET_OS_WATCH + +#import + +#import + +/** Sets the _callbackFlag ivar whenever the network changes. + * + * @param reachability The reachability object calling back. + * @param flags The new flag values. + * @param info Any data that might be passed in by the callback. + */ +static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +@implementation GDTCORReachability { + /** The reachability object. */ + SCNetworkReachabilityRef _reachabilityRef; + + /** The queue on which callbacks and all work will occur. */ + dispatch_queue_t _reachabilityQueue; + + /** Flags specified by reachability callbacks. */ + SCNetworkConnectionFlags _callbackFlags; +} + ++ (void)load { + [self sharedInstance]; +} + ++ (instancetype)sharedInstance { + static GDTCORReachability *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORReachability alloc] init]; + }); + return sharedInstance; +} + ++ (SCNetworkReachabilityFlags)currentFlags { + __block SCNetworkReachabilityFlags currentFlags; + dispatch_sync([GDTCORReachability sharedInstance] -> _reachabilityQueue, ^{ + GDTCORReachability *reachability = [GDTCORReachability sharedInstance]; + currentFlags = reachability->_flags ? reachability->_flags : reachability->_callbackFlags; + GDTCORLogDebug("Initial reachability flags determined: %d", currentFlags); + }); + return currentFlags; +} + +- (instancetype)init { + self = [super init]; + if (self) { + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + _reachabilityQueue = + dispatch_queue_create("com.google.GDTCORReachability", DISPATCH_QUEUE_SERIAL); + _reachabilityRef = SCNetworkReachabilityCreateWithAddress( + kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress); + Boolean success = SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, _reachabilityQueue); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", @"The reachability queue wasn't set."); + } + success = SCNetworkReachabilitySetCallback(_reachabilityRef, GDTCORReachabilityCallback, NULL); + if (!success) { + GDTCORLogWarning(GDTCORMCWReachabilityFailed, @"%@", + @"The reachability callback wasn't set."); + } + + // Get the initial set of flags. + dispatch_async(_reachabilityQueue, ^{ + Boolean valid = SCNetworkReachabilityGetFlags(self->_reachabilityRef, &self->_flags); + if (!valid) { + GDTCORLogDebug("%@", @"Determining reachability failed."); + self->_flags = 0; + } + }); + } + return self; +} + +- (void)setCallbackFlags:(SCNetworkReachabilityFlags)flags { + if (_callbackFlags != flags) { + self->_callbackFlags = flags; + } +} + +@end + +static void GDTCORReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GDTCORLogDebug("Reachability changed, new flags: %d", flags); + [[GDTCORReachability sharedInstance] setCallbackFlags:flags]; +} + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m new file mode 100644 index 0000000..1440376 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m @@ -0,0 +1,142 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Public/GDTCORRegistrar.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" + +#import + +@implementation GDTCORRegistrar { + /** Backing ivar for targetToUploader property. */ + NSMutableDictionary> *_targetToUploader; + + /** Backing ivar for targetToPrioritizer property. */ + NSMutableDictionary> *_targetToPrioritizer; +} + ++ (instancetype)sharedInstance { + static GDTCORRegistrar *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCORRegistrar alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _registrarQueue = dispatch_queue_create("com.google.GDTCORRegistrar", DISPATCH_QUEUE_SERIAL); + _targetToPrioritizer = [[NSMutableDictionary alloc] init]; + _targetToUploader = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)registerUploader:(id)backend target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug("Registered an uploader: %@ for target:%ld", backend, (long)target); + strongSelf->_targetToUploader[@(target)] = backend; + } + }); +} + +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target { + __weak GDTCORRegistrar *weakSelf = self; + dispatch_async(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + GDTCORLogDebug("Registered a prioritizer: %@ for target:%ld", prioritizer, (long)target); + strongSelf->_targetToPrioritizer[@(target)] = prioritizer; + } + }); +} + +- (NSMutableDictionary> *)targetToUploader { + __block NSMutableDictionary> *targetToUploader; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToUploader = strongSelf->_targetToUploader; + } + }); + return targetToUploader; +} + +- (NSMutableDictionary> *)targetToPrioritizer { + __block NSMutableDictionary> *targetToPrioritizer; + __weak GDTCORRegistrar *weakSelf = self; + dispatch_sync(_registrarQueue, ^{ + GDTCORRegistrar *strongSelf = weakSelf; + if (strongSelf) { + targetToPrioritizer = strongSelf->_targetToPrioritizer; + } + }); + return targetToPrioritizer; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillBackground:(nonnull GDTCORApplication *)app { + dispatch_async(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillBackground:)]) { + [uploader appWillBackground:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillBackground:)]) { + [prioritizer appWillBackground:app]; + } + } + }); +} + +- (void)appWillForeground:(nonnull GDTCORApplication *)app { + dispatch_async(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillForeground:)]) { + [uploader appWillForeground:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillForeground:)]) { + [prioritizer appWillForeground:app]; + } + } + }); +} + +- (void)appWillTerminate:(nonnull GDTCORApplication *)app { + dispatch_sync(_registrarQueue, ^{ + for (id uploader in [self->_targetToUploader allValues]) { + if ([uploader respondsToSelector:@selector(appWillTerminate:)]) { + [uploader appWillTerminate:app]; + } + } + for (id prioritizer in [self->_targetToPrioritizer allValues]) { + if ([prioritizer respondsToSelector:@selector(appWillTerminate:)]) { + [prioritizer appWillTerminate:app]; + } + } + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m new file mode 100644 index 0000000..a694471 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m @@ -0,0 +1,345 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORStorage.h" +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" + +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCOREvent_Private.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +/** Creates and/or returns a singleton NSString that is the shared storage path. + * + * @return The SDK event storage path. + */ +static NSString *GDTCORStoragePath() { + static NSString *storagePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *cachePath = + NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0]; + storagePath = [NSString stringWithFormat:@"%@/google-sdks-events", cachePath]; + GDTCORLogDebug("Events will be saved to %@", storagePath); + }); + return storagePath; +} + +@implementation GDTCORStorage + ++ (NSString *)archivePath { + static NSString *archivePath; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + archivePath = [GDTCORStoragePath() stringByAppendingPathComponent:@"GDTCORStorageArchive"]; + }); + return archivePath; +} + ++ (instancetype)sharedInstance { + static GDTCORStorage *sharedStorage; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedStorage = [[GDTCORStorage alloc] init]; + }); + return sharedStorage; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _storageQueue = dispatch_queue_create("com.google.GDTCORStorage", DISPATCH_QUEUE_SERIAL); + _targetToEventSet = [[NSMutableDictionary alloc] init]; + _storedEvents = [[NSMutableOrderedSet alloc] init]; + _uploadCoordinator = [GDTCORUploadCoordinator sharedInstance]; + } + return self; +} + +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion { + GDTCORLogDebug("Saving event: %@", event); + if (event == nil) { + GDTCORLogDebug("%@", @"The event was nil, so it was not saved."); + return; + } + if (!completion) { + completion = ^(BOOL wasWritten, NSError *error) { + }; + } + + [self createEventDirectoryIfNotExists]; + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + // End the background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + dispatch_async(_storageQueue, ^{ + // Check that a backend implementation is available for this target. + NSInteger target = event.target; + + // Check that a prioritizer is available for this target. + id prioritizer = + [GDTCORRegistrar sharedInstance].targetToPrioritizer[@(target)]; + GDTCORAssert(prioritizer, @"There's no prioritizer registered for the given target. Are you " + @"sure you've added the support library for the backend you need?"); + + // Write the transport bytes to disk, get a filename. + GDTCORAssert(event.dataObjectTransportBytes, @"The event should have been serialized to bytes"); + NSError *error = nil; + NSURL *eventFile = [self saveEventBytesToDisk:event.dataObjectTransportBytes + eventHash:event.hash + error:&error]; + GDTCORLogDebug("Event saved to disk: %@", eventFile); + GDTCORDataFuture *dataFuture = [[GDTCORDataFuture alloc] initWithFileURL:eventFile]; + GDTCORStoredEvent *storedEvent = [event storedEventWithDataFuture:dataFuture]; + completion(eventFile != nil, error); + + // Add event to tracking collections. + [self addEventToTrackingCollections:storedEvent]; + + // Have the prioritizer prioritize the event. + [prioritizer prioritizeEvent:storedEvent]; + + // Check the QoS, if it's high priority, notify the target that it has a high priority event. + if (event.qosTier == GDTCOREventQoSFast) { + [self.uploadCoordinator forceUploadForTarget:target]; + } + + // Write state to disk if we're in the background. + if ([[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORLogDebug("%@", @"Saving storage state because the app is running in the background"); + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } + } + + // Cancel or end the associated background task if it's still valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + GDTCORLogDebug("Event %@ is stored. There are %ld events stored on disk", event, + (unsigned long)self->_storedEvents.count); + }); +} + +- (void)removeEvents:(NSSet *)events { + NSSet *eventsToRemove = [events copy]; + dispatch_async(_storageQueue, ^{ + for (GDTCORStoredEvent *event in eventsToRemove) { + // Remove from disk, first and foremost. + NSError *error; + if (event.dataFuture.fileURL) { + NSURL *fileURL = event.dataFuture.fileURL; + [[NSFileManager defaultManager] removeItemAtURL:fileURL error:&error]; + GDTCORAssert(error == nil, @"There was an error removing an event file: %@", error); + GDTCORLogDebug("Removed event from disk: %@", fileURL); + } + + // Remove from the tracking collections. + [self.storedEvents removeObject:event]; + [self.targetToEventSet[event.target] removeObject:event]; + } + }); +} + +#pragma mark - Private helper methods + +/** Creates the storage directory if it does not exist. */ +- (void)createEventDirectoryIfNotExists { + NSError *error; + BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:GDTCORStoragePath() + withIntermediateDirectories:YES + attributes:0 + error:&error]; + if (!result || error) { + GDTCORLogError(GDTCORMCEDirectoryCreationError, @"Error creating the directory: %@", error); + } +} + +/** Saves the event's dataObjectTransportBytes to a file using NSData mechanisms. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param transportBytes The transport bytes of the event. + * @param eventHash The hash value of the event. + * @return The filename + */ +- (NSURL *)saveEventBytesToDisk:(NSData *)transportBytes + eventHash:(NSUInteger)eventHash + error:(NSError **)error { + NSString *storagePath = GDTCORStoragePath(); + NSString *event = [NSString stringWithFormat:@"event-%lu", (unsigned long)eventHash]; + NSURL *eventFilePath = [NSURL fileURLWithPath:[storagePath stringByAppendingPathComponent:event]]; + + GDTCORAssert(![[NSFileManager defaultManager] fileExistsAtPath:eventFilePath.path], + @"An event shouldn't already exist at this path: %@", eventFilePath.path); + + BOOL writingSuccess = [transportBytes writeToURL:eventFilePath + options:NSDataWritingAtomic + error:error]; + if (!writingSuccess) { + GDTCORLogError(GDTCORMCEFileWriteError, @"An event file could not be written: %@", + eventFilePath); + } + + return eventFilePath; +} + +/** Adds the event to internal tracking collections. + * + * @note This method should only be called from a method within a block on _storageQueue to maintain + * thread safety. + * + * @param event The event to track. + */ +- (void)addEventToTrackingCollections:(GDTCORStoredEvent *)event { + [_storedEvents addObject:event]; + NSMutableSet *events = self.targetToEventSet[event.target]; + events = events ? events : [[NSMutableSet alloc] init]; + [events addObject:event]; + _targetToEventSet[event.target] = events; +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSData dataWithContentsOfFile:[GDTCORStorage archivePath]]; + if (data) { + [NSKeyedUnarchiver unarchivedObjectOfClass:[GDTCORStorage class] fromData:data error:&error]; + } + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedUnarchiver unarchiveObjectWithFile:[GDTCORStorage archivePath]]; +#endif + } +} + +- (void)appWillBackground:(GDTCORApplication *)app { + dispatch_async(_storageQueue, ^{ + // Immediately request a background task to run until the end of the current queue of work, and + // cancel it once the work is done. + __block GDTCORBackgroundIdentifier bgID = + [app beginBackgroundTaskWithName:@"GDTStorage" + expirationHandler:^{ + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } + + // End the background task if it's still valid. + [app endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + NSError *error; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self + requiringSecureCoding:YES + error:&error]; + [data writeToFile:[GDTCORStorage archivePath] atomically:YES]; + } else { +#if !TARGET_OS_MACCATALYST && !TARGET_OS_WATCH + [NSKeyedArchiver archiveRootObject:self toFile:[GDTCORStorage archivePath]]; +#endif + } +} + +#pragma mark - NSSecureCoding + +/** The NSKeyedCoder key for the storedEvents property. */ +static NSString *const kGDTCORStorageStoredEventsKey = @"GDTCORStorageStoredEventsKey"; + +/** The NSKeyedCoder key for the targetToEventSet property. */ +static NSString *const kGDTCORStorageTargetToEventSetKey = @"GDTCORStorageTargetToEventSetKey"; + +/** The NSKeyedCoder key for the uploadCoordinator property. */ +static NSString *const kGDTCORStorageUploadCoordinatorKey = @"GDTCORStorageUploadCoordinatorKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + // Create the singleton and populate its ivars. + GDTCORStorage *sharedInstance = [self.class sharedInstance]; + dispatch_sync(sharedInstance.storageQueue, ^{ + NSSet *classes = + [NSSet setWithObjects:[NSMutableOrderedSet class], [GDTCORStoredEvent class], nil]; + sharedInstance->_storedEvents = [aDecoder decodeObjectOfClasses:classes + forKey:kGDTCORStorageStoredEventsKey]; + classes = [NSSet setWithObjects:[NSMutableDictionary class], [NSMutableSet class], + [GDTCORStoredEvent class], nil]; + sharedInstance->_targetToEventSet = + [aDecoder decodeObjectOfClasses:classes forKey:kGDTCORStorageTargetToEventSetKey]; + sharedInstance->_uploadCoordinator = + [aDecoder decodeObjectOfClass:[GDTCORUploadCoordinator class] + forKey:kGDTCORStorageUploadCoordinatorKey]; + }); + return sharedInstance; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + GDTCORStorage *sharedInstance = [self.class sharedInstance]; + NSMutableOrderedSet *storedEvents = sharedInstance->_storedEvents; + if (storedEvents) { + [aCoder encodeObject:storedEvents forKey:kGDTCORStorageStoredEventsKey]; + } + NSMutableDictionary *> *targetToEventSet = + sharedInstance->_targetToEventSet; + if (targetToEventSet) { + [aCoder encodeObject:targetToEventSet forKey:kGDTCORStorageTargetToEventSetKey]; + } + GDTCORUploadCoordinator *uploadCoordinator = sharedInstance->_uploadCoordinator; + if (uploadCoordinator) { + [aCoder encodeObject:uploadCoordinator forKey:kGDTCORStorageUploadCoordinatorKey]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m new file mode 100644 index 0000000..a243394 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m @@ -0,0 +1,95 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" + +@implementation GDTCORStoredEvent + +- (instancetype)initWithEvent:(GDTCOREvent *)event + dataFuture:(nonnull GDTCORDataFuture *)dataFuture { + self = [super init]; + if (self) { + _dataFuture = dataFuture; + _mappingID = event.mappingID; + _target = @(event.target); + _qosTier = event.qosTier; + _clockSnapshot = event.clockSnapshot; + _customPrioritizationParams = event.customPrioritizationParams; + } + return self; +} + +#pragma mark - NSSecureCoding + +/** Coding key for the dataFuture ivar. */ +static NSString *kDataFutureKey = @"GDTCORStoredEventDataFutureKey"; + +/** Coding key for mappingID ivar. */ +static NSString *kMappingIDKey = @"GDTCORStoredEventMappingIDKey"; + +/** Coding key for target ivar. */ +static NSString *kTargetKey = @"GDTCORStoredEventTargetKey"; + +/** Coding key for qosTier ivar. */ +static NSString *kQosTierKey = @"GDTCORStoredEventQosTierKey"; + +/** Coding key for clockSnapshot ivar. */ +static NSString *kClockSnapshotKey = @"GDTCORStoredEventClockSnapshotKey"; + +/** Coding key for customPrioritizationParams ivar. */ +static NSString *kCustomPrioritizationParamsKey = @"GDTCORStoredEventcustomPrioritizationParamsKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_dataFuture forKey:kDataFutureKey]; + [aCoder encodeObject:_mappingID forKey:kMappingIDKey]; + [aCoder encodeObject:_target forKey:kTargetKey]; + [aCoder encodeObject:@(_qosTier) forKey:kQosTierKey]; + [aCoder encodeObject:_clockSnapshot forKey:kClockSnapshotKey]; + [aCoder encodeObject:_customPrioritizationParams forKey:kCustomPrioritizationParamsKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [self init]; + if (self) { + _dataFuture = [aDecoder decodeObjectOfClass:[GDTCORDataFuture class] forKey:kDataFutureKey]; + _mappingID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kMappingIDKey]; + _target = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kTargetKey]; + NSNumber *qosTier = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kQosTierKey]; + _qosTier = [qosTier intValue]; + _clockSnapshot = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kClockSnapshotKey]; + _customPrioritizationParams = [aDecoder decodeObjectOfClass:[NSDictionary class] + forKey:kCustomPrioritizationParamsKey]; + } + return self; +} + +- (BOOL)isEqual:(GDTCORStoredEvent *)other { + return [self hash] == [other hash]; +} + +- (NSUInteger)hash { + return [_dataFuture hash] ^ [_mappingID hash] ^ [_target hash] ^ [_clockSnapshot hash] ^ _qosTier; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m new file mode 100644 index 0000000..a794cf3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m @@ -0,0 +1,98 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" +#import "GDTCORLibrary/Private/GDTCORTransformer_Private.h" + +#import +#import +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@implementation GDTCORTransformer + ++ (instancetype)sharedInstance { + static GDTCORTransformer *eventTransformer; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + eventTransformer = [[self alloc] init]; + }); + return eventTransformer; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _eventWritingQueue = + dispatch_queue_create("com.google.GDTCORTransformer", DISPATCH_QUEUE_SERIAL); + _storageInstance = [GDTCORStorage sharedInstance]; + } + return self; +} + +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(NSArray> *)transformers + onComplete:(nonnull void (^)(BOOL wasWritten, NSError *error))completion { + GDTCORAssert(event, @"You can't write a nil event"); + if (!completion) { + completion = ^(BOOL wasWritten, NSError *_Nullable error) { + }; + } + + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTTransformer" + expirationHandler:^{ + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }]; + dispatch_async(_eventWritingQueue, ^{ + GDTCOREvent *transformedEvent = event; + for (id transformer in transformers) { + if ([transformer respondsToSelector:@selector(transform:)]) { + GDTCORLogDebug("Applying a transformer to event %@", event); + transformedEvent = [transformer transform:transformedEvent]; + if (!transformedEvent) { + completion(NO, nil); + return; + } + } else { + GDTCORLogError(GDTCORMCETransformerDoesntImplementTransform, + @"Transformer doesn't implement transform: %@", transformer); + completion(NO, nil); + return; + } + } + [self.storageInstance storeEvent:transformedEvent onComplete:completion]; + + // The work is done, cancel the background task if it's valid. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + // Flush the queue immediately. + dispatch_sync(_eventWritingQueue, ^{ + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m new file mode 100644 index 0000000..c63c262 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import "GDTCORLibrary/Private/GDTCORTransport_Private.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +@implementation GDTCORTransport + +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target { + GDTCORAssert(mappingID.length > 0, @"A mapping ID cannot be nil or empty"); + GDTCORAssert(target > 0, @"A target cannot be negative or 0"); + if (mappingID == nil || mappingID.length == 0 || target <= 0) { + return nil; + } + self = [super init]; + if (self) { + _mappingID = mappingID; + _transformers = transformers; + _target = target; + _transformerInstance = [GDTCORTransformer sharedInstance]; + } + GDTCORLogDebug("Transport object created. mappingID:%@ transformers:%@ target:%ld", _mappingID, + _transformers, (long)_target); + return self; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion { + event.qosTier = GDTCOREventQoSTelemetry; + [self sendEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + GDTCORLogDebug("Telemetry event sent: %@", event); + if (completion) { + completion(wasWritten, nil); + } + }]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion { + GDTCORAssert(event.qosTier != GDTCOREventQoSTelemetry, @"Use -sendTelemetryEvent, please."); + [self sendEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + GDTCORLogDebug("Data event sent: %@", event); + if (completion) { + completion(wasWritten, nil); + } + }]; +} + +- (void)sendTelemetryEvent:(GDTCOREvent *)event { + [self sendTelemetryEvent:event + onComplete:^(BOOL wasWritten, NSError *_Nullable error){ + }]; +} + +- (void)sendDataEvent:(GDTCOREvent *)event { + [self sendDataEvent:event + onComplete:^(BOOL wasWritten, NSError *_Nullable error){ + }]; +} + +- (GDTCOREvent *)eventForTransport { + return [[GDTCOREvent alloc] initWithMappingID:_mappingID target:_target]; +} + +#pragma mark - Private helper methods + +/** Sends the given event through the transport pipeline. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion { + // TODO: Determine if sending an event before registration is allowed. + GDTCORAssert(event, @"You can't send a nil event"); + GDTCOREvent *copiedEvent = [event copy]; + copiedEvent.clockSnapshot = [GDTCORClock snapshot]; + [self.transformerInstance transformEvent:copiedEvent + withTransformers:_transformers + onComplete:completion]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m new file mode 100644 index 0000000..7ebef6b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m @@ -0,0 +1,274 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORReachability.h" +#import "GDTCORLibrary/Private/GDTCORRegistrar_Private.h" +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@implementation GDTCORUploadCoordinator + ++ (instancetype)sharedInstance { + static GDTCORUploadCoordinator *sharedUploader; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedUploader = [[GDTCORUploadCoordinator alloc] init]; + [sharedUploader startTimer]; + }); + return sharedUploader; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _coordinationQueue = + dispatch_queue_create("com.google.GDTCORUploadCoordinator", DISPATCH_QUEUE_SERIAL); + _registrar = [GDTCORRegistrar sharedInstance]; + _timerInterval = 30 * NSEC_PER_SEC; + _timerLeeway = 5 * NSEC_PER_SEC; + _targetToInFlightPackages = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void)forceUploadForTarget:(GDTCORTarget)target { + dispatch_async(_coordinationQueue, ^{ + GDTCORLogDebug("Forcing an upload of target %ld", (long)target); + GDTCORUploadConditions conditions = [self uploadConditions]; + conditions |= GDTCORUploadConditionHighPriority; + [self uploadTargets:@[ @(target) ] conditions:conditions]; + }); +} + +#pragma mark - Property overrides + +// GDTCORStorage and GDTCORUploadCoordinator +sharedInstance methods call each other, so this breaks +// the loop. +- (GDTCORStorage *)storage { + if (!_storage) { + _storage = [GDTCORStorage sharedInstance]; + } + return _storage; +} + +#pragma mark - Private helper methods + +/** Starts a timer that checks whether or not events can be uploaded at regular intervals. It will + * check the next-upload clocks of all targets to determine if an upload attempt can be made. + */ +- (void)startTimer { + dispatch_sync(_coordinationQueue, ^{ + self->_timer = + dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self->_coordinationQueue); + dispatch_source_set_timer(self->_timer, DISPATCH_TIME_NOW, self->_timerInterval, + self->_timerLeeway); + dispatch_source_set_event_handler(self->_timer, ^{ + if (![[GDTCORApplication sharedApplication] isRunningInBackground]) { + GDTCORUploadConditions conditions = [self uploadConditions]; + GDTCORLogDebug("%@", @"Upload timer fired"); + [self uploadTargets:[self.registrar.targetToUploader allKeys] conditions:conditions]; + } + }); + GDTCORLogDebug("%@", @"Upload timer started"); + dispatch_resume(self->_timer); + }); +} + +/** Stops the currently running timer. */ +- (void)stopTimer { + if (_timer) { + dispatch_source_cancel(_timer); + } +} + +/** Triggers the uploader implementations for the given targets to upload. + * + * @param targets An array of targets to trigger. + * @param conditions The set of upload conditions. + */ +- (void)uploadTargets:(NSArray *)targets conditions:(GDTCORUploadConditions)conditions { + dispatch_async(_coordinationQueue, ^{ + if ((conditions & GDTCORUploadConditionNoNetwork) == GDTCORUploadConditionNoNetwork) { + return; + } + for (NSNumber *target in targets) { + // Don't trigger uploads for targets that have an in-flight package already. + if (self->_targetToInFlightPackages[target]) { + GDTCORLogDebug("Target %@ will not upload, there's an upload in flight", target); + continue; + } + // Ask the uploader if they can upload and do so, if it can. + id uploader = self.registrar.targetToUploader[target]; + if ([uploader readyToUploadTarget:target.intValue conditions:conditions]) { + id prioritizer = self.registrar.targetToPrioritizer[target]; + GDTCORUploadPackage *package = [prioritizer uploadPackageWithTarget:target.intValue + conditions:conditions]; + if (package.events.count) { + self->_targetToInFlightPackages[target] = package; + GDTCORLogDebug("Package of %ld events is being handed over to an uploader", + (long)package.events.count); + [uploader uploadPackage:package]; + } else { + [package completeDelivery]; + } + } + GDTCORLogDebug("Target %@ is not ready to upload", target); + } + }); +} + +/** Returns the current upload conditions after making determinations about the network connection. + * + * @return The current upload conditions. + */ +- (GDTCORUploadConditions)uploadConditions { +#if TARGET_OS_WATCH + return GDTCORUploadConditionNoNetwork; +#else + SCNetworkReachabilityFlags currentFlags = [GDTCORReachability currentFlags]; + BOOL reachable = + (currentFlags & kSCNetworkReachabilityFlagsReachable) == kSCNetworkReachabilityFlagsReachable; + BOOL connectionRequired = (currentFlags & kSCNetworkReachabilityFlagsConnectionRequired) == + kSCNetworkReachabilityFlagsConnectionRequired; + BOOL networkConnected = reachable && !connectionRequired; + + if (!networkConnected) { + return GDTCORUploadConditionNoNetwork; + } + + BOOL isWWAN = GDTCORReachabilityFlagsContainWWAN(currentFlags); + if (isWWAN) { + return GDTCORUploadConditionMobileData; + } else { + return GDTCORUploadConditionWifiData; + } +#endif +} + +#pragma mark - NSSecureCoding support + +/** The NSKeyedCoder key for the targetToInFlightPackages property. */ +static NSString *const ktargetToInFlightPackagesKey = + @"GDTCORUploadCoordinatortargetToInFlightPackages"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + GDTCORUploadCoordinator *sharedCoordinator = [GDTCORUploadCoordinator sharedInstance]; + dispatch_sync(sharedCoordinator->_coordinationQueue, ^{ + @try { + sharedCoordinator->_targetToInFlightPackages = + [aDecoder decodeObjectOfClass:[NSMutableDictionary class] + forKey:ktargetToInFlightPackagesKey]; + + } @catch (NSException *exception) { + sharedCoordinator->_targetToInFlightPackages = [NSMutableDictionary dictionary]; + } + }); + return sharedCoordinator; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + dispatch_sync(_coordinationQueue, ^{ + // All packages that have been given to uploaders need to be tracked so that their expiration + // timers can be called. + if (self->_targetToInFlightPackages.count > 0) { + [aCoder encodeObject:self->_targetToInFlightPackages forKey:ktargetToInFlightPackagesKey]; + } + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillForeground:(GDTCORApplication *)app { + // Not entirely thread-safe, but it should be fine. + [self startTimer]; +} + +- (void)appWillBackground:(GDTCORApplication *)app { + // Should be thread-safe. If it ends up not being, put this in a dispatch_sync. + [self stopTimer]; +} + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_coordinationQueue, ^{ + [self stopTimer]; + }); +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + if (!prioritizer) { + GDTCORLogError(GDTCORMCEPrioritizerError, + @"A prioritizer should be registered for this target: %@", targetNumber); + } + if ([prioritizer respondsToSelector:@selector(packageDelivered:successful:)]) { + [prioritizer packageDelivered:package successful:successful]; + } + } + if (package.events != nil) { + [self.storage removeEvents:package.events]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + if (!_coordinationQueue) { + return; + } + dispatch_async(_coordinationQueue, ^{ + NSNumber *targetNumber = @(package.target); + NSMutableDictionary *targetToInFlightPackages = + self->_targetToInFlightPackages; + GDTCORRegistrar *registrar = self->_registrar; + if (targetToInFlightPackages) { + [targetToInFlightPackages removeObjectForKey:targetNumber]; + } + if (registrar) { + id prioritizer = registrar.targetToPrioritizer[targetNumber]; + id uploader = registrar.targetToUploader[targetNumber]; + if ([prioritizer respondsToSelector:@selector(packageExpired:)]) { + [prioritizer packageExpired:package]; + } + if ([uploader respondsToSelector:@selector(packageExpired:)]) { + [uploader packageExpired:package]; + } + } + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m new file mode 100644 index 0000000..6ac5f4f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m @@ -0,0 +1,159 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +#import "GDTCORLibrary/Private/GDTCORStorage_Private.h" +#import "GDTCORLibrary/Private/GDTCORUploadCoordinator.h" +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +@implementation GDTCORUploadPackage { + /** If YES, the package's -completeDelivery method has been called. */ + BOOL _isDelivered; + + /** If YES, is being handled by the handler. */ + BOOL _isHandled; + + /** A timer that will regularly check to see whether this package has expired or not. */ + NSTimer *_expirationTimer; +} + +- (instancetype)initWithTarget:(GDTCORTarget)target { + self = [super init]; + if (self) { + _target = target; + _storage = [GDTCORStorage sharedInstance]; + _deliverByTime = [GDTCORClock clockSnapshotInTheFuture:180000]; + _handler = [GDTCORUploadCoordinator sharedInstance]; + _expirationTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 + target:self + selector:@selector(checkIfPackageIsExpired:) + userInfo:nil + repeats:YES]; + } + GDTCORLogDebug("Upload package created %@", self); + return self; +} + +- (instancetype)copy { + GDTCORUploadPackage *newPackage = [[GDTCORUploadPackage alloc] initWithTarget:_target]; + newPackage->_events = [_events copy]; + GDTCORLogDebug("Copying UploadPackage %@ to %@", self, newPackage); + return newPackage; +} + +- (NSUInteger)hash { + return [_events hash]; +} + +- (BOOL)isEqual:(id)object { + return [self hash] == [object hash]; +} + +- (void)dealloc { + [_expirationTimer invalidate]; +} + +- (void)setStorage:(GDTCORStorage *)storage { + if (storage != _storage) { + _storage = storage; + } +} + +- (void)completeDelivery { + if (_isDelivered) { + GDTCORLogError(GDTCORMCEDeliverTwice, @"%@", + @"It's an API violation to call -completeDelivery twice."); + } + _isDelivered = YES; + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + [_expirationTimer invalidate]; + _isHandled = YES; + [_handler packageDelivered:self successful:YES]; + } + GDTCORLogDebug("Upload package delivered: %@", self); +} + +- (void)retryDeliveryInTheFuture { + if (!_isHandled && _handler && + [_handler respondsToSelector:@selector(packageDelivered:successful:)]) { + [_expirationTimer invalidate]; + _isHandled = YES; + [_handler packageDelivered:self successful:NO]; + } + GDTCORLogDebug("Upload package will retry in the future: %@", self); +} + +- (void)checkIfPackageIsExpired:(NSTimer *)timer { + if ([[GDTCORClock snapshot] isAfter:_deliverByTime]) { + if (_handler && [_handler respondsToSelector:@selector(packageExpired:)]) { + _isHandled = YES; + [_expirationTimer invalidate]; + GDTCORLogDebug("Upload package expired: %@", self); + [_handler packageExpired:self]; + } + } +} + +#pragma mark - NSSecureCoding + +/** The keyed archiver key for the events property. */ +static NSString *const kEventsKey = @"GDTCORUploadPackageEventsKey"; + +/** The keyed archiver key for the _isHandled property. */ +static NSString *const kDeliverByTimeKey = @"GDTCORUploadPackageDeliveryByTimeKey"; + +/** The keyed archiver key for the _isHandled ivar. */ +static NSString *const kIsHandledKey = @"GDTCORUploadPackageIsHandledKey"; + +/** The keyed archiver key for the handler property. */ +static NSString *const kHandlerKey = @"GDTCORUploadPackageHandlerKey"; + +/** The keyed archiver key for the target property. */ +static NSString *const kTargetKey = @"GDTCORUploadPackageTargetKey"; + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + [aCoder encodeObject:_events forKey:kEventsKey]; + [aCoder encodeObject:_deliverByTime forKey:kDeliverByTimeKey]; + [aCoder encodeBool:_isHandled forKey:kIsHandledKey]; + [aCoder encodeObject:_handler forKey:kHandlerKey]; + [aCoder encodeInteger:_target forKey:kTargetKey]; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + GDTCORTarget target = [aDecoder decodeIntegerForKey:kTargetKey]; + self = [self initWithTarget:target]; + if (self) { + NSSet *classes = [NSSet setWithObjects:[NSSet class], [GDTCORStoredEvent class], nil]; + _events = [aDecoder decodeObjectOfClasses:classes forKey:kEventsKey]; + _deliverByTime = [aDecoder decodeObjectOfClass:[GDTCORClock class] forKey:kDeliverByTimeKey]; + _isHandled = [aDecoder decodeBoolForKey:kIsHandledKey]; + // _handler isn't technically NSSecureCoding, because we don't know the class of this object. + // but it gets decoded anyway. + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h new file mode 100644 index 0000000..f7f8a28 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCOREvent () + +/** The serialized bytes of the event data object. */ +@property(nonatomic) NSData *dataObjectTransportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h new file mode 100644 index 0000000..7879b59 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if !TARGET_OS_WATCH +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** This class helps determine upload conditions by determining connectivity. */ +@interface GDTCORReachability : NSObject +#if !TARGET_OS_WATCH +/** The current set flags indicating network conditions */ ++ (SCNetworkReachabilityFlags)currentFlags; +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h new file mode 100644 index 0000000..5d3ddaf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORReachability.h" + +@interface GDTCORReachability () + +#if !TARGET_OS_WATCH +/** Allows manually setting the flags for testing purposes. */ +@property(nonatomic, readwrite) SCNetworkReachabilityFlags flags; +#endif + +/** Creates/returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h new file mode 100644 index 0000000..074fc11 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GDTCORRegistrar () + +NS_ASSUME_NONNULL_BEGIN + +/** The concurrent queue on which all registration occurs. */ +@property(nonatomic, readonly) dispatch_queue_t registrarQueue; + +/** A map of targets to backend implementations. */ +@property(atomic, readonly) NSMutableDictionary> *targetToUploader; + +/** A map of targets to prioritizer implementations. */ +@property(atomic, readonly) + NSMutableDictionary> *targetToPrioritizer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h new file mode 100644 index 0000000..bbb3778 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h @@ -0,0 +1,52 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the storage of events. This class is thread-safe. */ +@interface GDTCORStorage : NSObject + +/** Creates and/or returns the storage singleton. + * + * @return The storage singleton. + */ ++ (instancetype)sharedInstance; + +/** Stores event.dataObjectTransportBytes into a shared on-device folder and tracks the event via + * a GDTCORStoredEvent instance. + * + * @param event The event to store. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)storeEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *error))completion; + +/** Removes a set of events from storage specified by their hash. + * + * @param events The set of stored events to remove. + */ +- (void)removeEvents:(NSSet *)events; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h new file mode 100644 index 0000000..24569fd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h @@ -0,0 +1,47 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORStorage.h" + +@class GDTCORUploadCoordinator; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORStorage () + +/** The queue on which all storage work will occur. */ +@property(nonatomic) dispatch_queue_t storageQueue; + +/** A map of targets to a set of stored events. */ +@property(nonatomic) + NSMutableDictionary *> *targetToEventSet; + +/** All the events that have been stored. */ +@property(readonly, nonatomic) NSMutableOrderedSet *storedEvents; + +/** The upload coordinator instance used by this storage instance. */ +@property(nonatomic) GDTCORUploadCoordinator *uploadCoordinator; + +/** Returns the path to the keyed archive of the singleton. This is where the singleton is saved + * to disk during certain app lifecycle events. + * + * @return File path to serialized singleton. + */ ++ (NSString *)archivePath; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h new file mode 100644 index 0000000..9da9fc3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +@protocol GDTCOREventTransformer; + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the transforming of events. It's desirable for this to be its own class + * because running all events through a single instance ensures that transformers are thread-safe. + * Having a per-transport queue to run on isn't sufficient because transformer objects could + * maintain state (or at least, there's nothing to stop them from doing that) and the same instances + * may be used across multiple instances. + */ +@interface GDTCORTransformer : NSObject + +/** Instantiates or returns the event transformer singleton. + * + * @return The singleton instance of the event transformer. + */ ++ (instancetype)sharedInstance; + +/** Writes the result of applying the given transformers' -transform method on the given event. + * + * @note If the app is suspended, a background task will be created to complete work in-progress, + * but this method will not send any further events until the app is resumed. + * + * @param event The event to apply transformers on. + * @param transformers The list of transformers to apply. + * @param completion A block to run when an event was written to disk or dropped. + */ +- (void)transformEvent:(GDTCOREvent *)event + withTransformers:(nullable NSArray> *)transformers + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h new file mode 100644 index 0000000..fcdae34 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h @@ -0,0 +1,33 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORLibrary/Private/GDTCORTransformer.h" + +@class GDTCORStorage; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransformer () + +/** The queue on which all work will occur. */ +@property(nonatomic) dispatch_queue_t eventWritingQueue; + +/** The storage instance used to store events. Should only be used to inject a testing fake. */ +@property(nonatomic) GDTCORStorage *storageInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h new file mode 100644 index 0000000..71f73a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCORTransformer; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport () + +/** The mapping identifier that the target backend will use to map the transport bytes to proto. */ +@property(nonatomic) NSString *mappingID; + +/** The transformers that will operate on events sent by this transport. */ +@property(nonatomic) NSArray> *transformers; + +/** The target backend of this transport. */ +@property(nonatomic) NSInteger target; + +/** The transformer instance to used to transform events. Allows injecting a fake during testing. */ +@property(nonatomic) GDTCORTransformer *transformerInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h new file mode 100644 index 0000000..b1d708c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h @@ -0,0 +1,77 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +#import "GDTCORLibrary/Private/GDTCORUploadPackage_Private.h" + +@class GDTCORClock; +@class GDTCORStorage; + +NS_ASSUME_NONNULL_BEGIN + +/** This class connects storage and uploader implementations, providing events to an uploader + * and informing the storage what events were successfully uploaded or not. + */ +@interface GDTCORUploadCoordinator + : NSObject + +/** The queue on which all upload coordination will occur. Also used by a dispatch timer. */ +/** Creates and/or returrns the singleton. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; +@property(nonatomic, readonly) dispatch_queue_t coordinationQueue; + +/** A timer that will causes regular checks for events to upload. */ +@property(nonatomic, readonly) dispatch_source_t timer; + +/** The interval the timer will fire. */ +@property(nonatomic, readonly) uint64_t timerInterval; + +/** Some leeway given to libdispatch for the timer interval event. */ +@property(nonatomic, readonly) uint64_t timerLeeway; + +/** The map of targets to in-flight packages. */ +@property(nonatomic, readonly) + NSMutableDictionary *targetToInFlightPackages; + +/** The storage object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORStorage *storage; + +/** The registrar object the coordinator will use. Generally used for testing. */ +@property(nonatomic) GDTCORRegistrar *registrar; + +/** Forces the backend specified by the target to upload the provided set of events. This should + * only ever happen when the QoS tier of an event requires it. + * + * @param target The target that should force an upload. + */ +- (void)forceUploadForTarget:(GDTCORTarget)target; + +/** Starts the upload timer. */ +- (void)startTimer; + +/** Stops the upload timer from running. */ +- (void)stopTimer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h new file mode 100644 index 0000000..1eb58d4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCORStorage; + +@interface GDTCORUploadPackage () + +/** The storage object this upload package will use to resolve event hashes to files. */ +@property(nonatomic) GDTCORStorage *storage; + +/** A handler that will receive callbacks for certain events. */ +@property(nonatomic) id handler; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h new file mode 100644 index 0000000..5dfe192 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +/** A block type that could be run instead of normal assertion logging. No return type, no params. + */ +typedef void (^GDTCORAssertionBlock)(void); + +/** Returns the result of executing a soft-linked method present in unit tests that allows a block + * to be run instead of normal assertion logging. This helps ameliorate issues with catching + * exceptions that occur on a dispatch_queue. + * + * @return A block that can be run instead of normal assert printing. + */ +FOUNDATION_EXPORT GDTCORAssertionBlock _Nullable GDTCORAssertionBlockToRunInstead(void); + +#if defined(NS_BLOCK_ASSERTIONS) + +#define GDTCORAssert(condition, ...) \ + do { \ + } while (0); + +#define GDTCORFatalAssert(condition, ...) \ + do { \ + } while (0); + +#else // defined(NS_BLOCK_ASSERTIONS) + +/** Asserts using a console log, unless a block was specified to be run instead. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORAssert(condition, ...) \ + do { \ + if (__builtin_expect(!(condition), 0)) { \ + GDTCORAssertionBlock assertionBlock = GDTCORAssertionBlockToRunInstead(); \ + if (assertionBlock) { \ + assertionBlock(); \ + } else { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogError(GDTCORMCEGeneralError, @"Assertion failed (%@:%d): %@,", __assert_file__, \ + __LINE__, ##__VA_ARGS__); \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } \ + } \ + } while (0); + +/** Asserts by logging to the console and throwing an exception if NS_BLOCK_ASSERTIONS is not + * defined. + * + * @param condition The condition you'd expect to be YES. + */ +#define GDTCORFatalAssert(condition, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (__builtin_expect(!(condition), 0)) { \ + NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ + __assert_file__ = __assert_file__ ? __assert_file__ : @""; \ + GDTCORLogError(GDTCORMCEFatalAssertion, \ + @"Fatal assertion encountered, please open an issue at " \ + "https://github.com/firebase/firebase-ios-sdk/issues " \ + "(%@:%d): %@,", \ + __assert_file__, __LINE__, ##__VA_ARGS__); \ + [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ + object:self \ + file:__assert_file__ \ + lineNumber:__LINE__ \ + description:@"%@", ##__VA_ARGS__]; \ + } \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } while (0); + +#endif // defined(NS_BLOCK_ASSERTIONS) diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h new file mode 100644 index 0000000..01de21a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class manages the device clock and produces snapshots of the current time. */ +@interface GDTCORClock : NSObject + +/** The wallclock time, UTC, in milliseconds. */ +@property(nonatomic, readonly) int64_t timeMillis; + +/** The offset from UTC in seconds. */ +@property(nonatomic, readonly) int64_t timezoneOffsetSeconds; + +/** The kernel boot time when this clock was created. */ +@property(nonatomic, readonly) int64_t kernelBootTime; + +/** The device uptime when this clock was created. */ +@property(nonatomic, readonly) int64_t uptime; + +/** Creates a GDTCORClock object using the current time and offsets. + * + * @return A new GDTCORClock object representing the current time state. + */ ++ (instancetype)snapshot; + +/** Creates a GDTCORClock object representing a time in the future, relative to now. + * + * @param millisInTheFuture The millis in the future from now this clock should represent. + * @return An instance representing a future time. + */ ++ (instancetype)clockSnapshotInTheFuture:(uint64_t)millisInTheFuture; + +/** Compares one clock with another, returns YES if the caller is after the parameter. + * + * @return YES if the calling clock's time is after the given clock's time. + */ +- (BOOL)isAfter:(GDTCORClock *)otherClock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h new file mode 100644 index 0000000..c70706b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Set this to 1 to have the library print out as much as possible about what GDT is doing. +#define GDT_VERBOSE_LOGGING 0 + +/** A list of message codes to print in the logger that help to correspond printed messages with + * code locations. + * + * Prefixes: + * - MCW => MessageCodeWarning + * - MCE => MessageCodeError + */ +typedef NS_ENUM(NSInteger, GDTCORMessageCode) { + + /** For warning messages concerning transportBytes: not being implemented by a data object. */ + GDTCORMCWDataObjectMissingBytesImpl = 1, + + /** For warning messages concerning a failed event upload. */ + GDTCORMCWUploadFailed = 2, + + /** For warning messages concerning a forced event upload. */ + GDTCORMCWForcedUpload = 3, + + /** For warning messages concerning a failed reachability call. */ + GDTCORMCWReachabilityFailed = 4, + + /** For error messages concerning transform: not being implemented by an event transformer. */ + GDTCORMCETransformerDoesntImplementTransform = 1000, + + /** For error messages concerning the creation of a directory failing. */ + GDTCORMCEDirectoryCreationError = 1001, + + /** For error messages concerning the writing of a event file. */ + GDTCORMCEFileWriteError = 1002, + + /** For error messages concerning the lack of a prioritizer for a given backend. */ + GDTCORMCEPrioritizerError = 1003, + + /** For error messages concerning a package delivery API violation. */ + GDTCORMCEDeliverTwice = 1004, + + /** For error messages concerning an error in an implementation of -transportBytes. */ + GDTCORMCETransportBytesError = 1005, + + /** For general purpose error messages in a dependency. */ + GDTCORMCEGeneralError = 1006, + + /** For fatal errors. Please go to https://github.com/firebase/firebase-ios-sdk/issues and open + * an issue if you encounter an error with this code. + */ + GDTCORMCEFatalAssertion = 1007 +}; + +/** */ +FOUNDATION_EXPORT +void GDTCORLog(GDTCORMessageCode code, NSString *_Nonnull format, ...); + +/** Returns the string that represents some message code. + * + * @param code The code to convert to a string. + * @return The string representing the message code. + */ +FOUNDATION_EXPORT NSString *_Nonnull GDTCORMessageCodeEnumToString(GDTCORMessageCode code); + +// A define to wrap GULLogWarning with slightly more convenient usage. +#define GDTCORLogWarning(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap GULLogError with slightly more convenient usage and a failing assert. +#define GDTCORLogError(MESSAGE_CODE, MESSAGE_FORMAT, ...) \ + GDTCORLog(MESSAGE_CODE, MESSAGE_FORMAT, __VA_ARGS__); + +// A define to wrap NSLog for verbose console logs only useful for local debugging. +#if GDT_VERBOSE_LOGGING == 1 +#define GDTCORLogDebug(FORMAT, ...) NSLog(@"GDT: " FORMAT, __VA_ARGS__); +#else +#define GDTCORLogDebug(...) +#endif // GDT_VERBOSE_LOGGING == 1 diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h new file mode 100644 index 0000000..07f428f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h @@ -0,0 +1,42 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class represents a future data object, determined at instantiation time. */ +@interface GDTCORDataFuture : NSObject + +/** The data, computed on-demand, depending on the initializer. */ +@property(nullable, readonly, nonatomic) NSData *data; + +/** If not nil, this data future was instantiated with this file URL. */ +@property(nullable, readonly, nonatomic) NSURL *fileURL; + +/** If not nil, this data future was instantiated with this NSData instance. */ +@property(nullable, readonly, nonatomic) NSData *originalData; + +/** Initializes an instance with the given the fileURL. + * + * @param fileURL The fileURL containing the data to return in -data. + * @return An instance of this class. + */ +- (instancetype)initWithFileURL:(NSURL *)fileURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h new file mode 100644 index 0000000..1ab55de --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h @@ -0,0 +1,94 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCORClock; +@class GDTCORDataFuture; +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCOREventQoS) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCOREventQoSUnknown = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCOREventQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCOREventQoSDaily = 2, + + /** This event should be sent when requested by the uploader. */ + GDTCOREventQosDefault = 3, + + /** This event should be sent immediately along with any other data that can be batched. */ + GDTCOREventQoSFast = 4, + + /** This event should only be uploaded on wifi. */ + GDTCOREventQoSWifiOnly = 5, +}; + +@interface GDTCOREvent : NSObject + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) NSInteger target; + +/** The data object encapsulated in the transport of your choice, as long as it implements + * the GDTCOREventDataObject protocol. */ +@property(nullable, nonatomic) id dataObject; + +/** The quality of service tier this event belongs to. */ +@property(nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(nonatomic) GDTCORClock *clockSnapshot; + +/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. It will be + * retained by a copy in -copy, but not used for -hash. + * + * @note Ensure that classes contained therein implement NSSecureCoding to prevent loss of data. + */ +@property(nullable, nonatomic) NSDictionary *customPrioritizationParams; + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes an instance using the given mappingID. + * + * @param mappingID The mapping identifier. + * @param target The event's target identifier. + * @return An instance of this class. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +/** Returns the GDTCORStoredEvent equivalent of self. + * + * @param dataFuture The data future representing the transport bytes of the original event. + * @return An equivalent GDTCORStoredEvent. + */ +- (GDTCORStoredEvent *)storedEventWithDataFuture:(GDTCORDataFuture *)dataFuture; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h new file mode 100644 index 0000000..34ef624 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface that event protos should implement regardless of the + * underlying transport technology (protobuf, nanopb, etc). + */ +@protocol GDTCOREventDataObject + +@required + +/** Returns the serialized proto bytes of the implementing event proto. + * + * @return the serialized proto bytes of the implementing event proto. + */ +- (NSData *)transportBytes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h new file mode 100644 index 0000000..29f9592 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Defines the API that event transformers must adopt. */ +@protocol GDTCOREventTransformer + +@required + +/** Transforms an event by applying some logic to it. Events returned can be nil, for example, in + * instances where the event should be sampled. + * + * @param event The event to transform. + * @return A transformed event, or nil if the transformation dropped the event. + */ +- (nullable GDTCOREvent *)transform:(GDTCOREvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h new file mode 100644 index 0000000..4d61a21 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +/** A protocol defining the lifecycle events objects in the library must respond to immediately. */ +@protocol GDTCORLifecycleProtocol + +@optional + +/** Indicates an imminent app termination in the rare occurrence when -applicationWillTerminate: has + * been called. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillTerminate:(GDTCORApplication *)app; + +/** Indicates that the app is moving to background and eventual suspension or the current UIScene is + * deactivating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillBackground:(GDTCORApplication *)app; + +/** Indicates that the app is resuming operation or a UIScene is activating. + * + * @param app The GDTCORApplication instance. + */ +- (void)appWillForeground:(GDTCORApplication *)app; + +@end + +/** This class manages the library's response to app lifecycle events. + * + * When backgrounding, the library doesn't stop processing events, it's just that several background + * tasks will end up being created for every event that's sent, and the stateful objects of the + * library (GDTCORStorage and GDTCORUploadCoordinator singletons) will deserialize themselves from + * and to disk before and after every operation, respectively. + */ +@interface GDTCORLifecycle : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h new file mode 100644 index 0000000..d72c2c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h @@ -0,0 +1,98 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if !TARGET_OS_WATCH +#import +#endif +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +NS_ASSUME_NONNULL_BEGIN + +/** The GoogleDataTransport library version. */ +FOUNDATION_EXPORT NSString *const kGDTCORVersion; + +/** A notification sent out if the app is backgrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationDidEnterBackgroundNotification; + +/** A notification sent out if the app is foregrounding. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillEnterForegroundNotification; + +/** A notification sent out if the app is terminating. */ +FOUNDATION_EXPORT NSString *const kGDTCORApplicationWillTerminateNotification; + +#if !TARGET_OS_WATCH +/** Compares flags with the WWAN reachability flag, if available, and returns YES if present. + * + * @param flags The set of reachability flags. + * @return YES if the WWAN flag is set, NO otherwise. + */ +BOOL GDTCORReachabilityFlagsContainWWAN(SCNetworkReachabilityFlags flags); +#endif + +/** A typedef identify background identifiers. */ +typedef volatile NSUInteger GDTCORBackgroundIdentifier; + +/** A background task's invalid sentinel value. */ +FOUNDATION_EXPORT const GDTCORBackgroundIdentifier GDTCORBackgroundIdentifierInvalid; + +#if TARGET_OS_IOS || TARGET_OS_TV +/** A protocol that wraps UIApplicationDelegate or NSObject protocol, depending on the platform. */ +@protocol GDTCORApplicationDelegate +#elif TARGET_OS_OSX +@protocol GDTCORApplicationDelegate +#else +@protocol GDTCORApplicationDelegate +#endif // TARGET_OS_IOS || TARGET_OS_TV + +@end + +/** A cross-platform application class. */ +@interface GDTCORApplication : NSObject + +/** Flag to determine if the application is running in the background. */ +@property(atomic, readonly) BOOL isRunningInBackground; + +/** Creates and/or returns the shared application instance. + * + * @return The shared application instance. + */ ++ (nullable GDTCORApplication *)sharedApplication; + +/** Creates a background task with the returned identifier if on a suitable platform. + * + * @name name The name of the task, useful for debugging which background tasks are running. + * @param handler The handler block that is called if the background task expires. + * @return An identifier for the background task, or GDTCORBackgroundIdentifierInvalid if one + * couldn't be created. + */ +- (GDTCORBackgroundIdentifier)beginBackgroundTaskWithName:(NSString *)name + expirationHandler:(void (^__nullable)(void))handler; + +/** Ends the background task if the identifier is valid. + * + * @param bgID The background task to end. + */ +- (void)endBackgroundTask:(GDTCORBackgroundIdentifier)bgID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h new file mode 100644 index 0000000..583e84d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h @@ -0,0 +1,75 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +@class GDTCORStoredEvent; + +NS_ASSUME_NONNULL_BEGIN + +/** Options that define a set of upload conditions. This is used to help minimize end user data + * consumption impact. + */ +typedef NS_OPTIONS(NSInteger, GDTCORUploadConditions) { + + /** An upload shouldn't be attempted, because there's no network. */ + GDTCORUploadConditionNoNetwork = 1 << 0, + + /** An upload would likely use mobile data. */ + GDTCORUploadConditionMobileData = 1 << 1, + + /** An upload would likely use wifi data. */ + GDTCORUploadConditionWifiData = 1 << 2, + + /** An upload uses some sort of network connection, but it's unclear which. */ + GDTCORUploadConditionUnclearConnection = 1 << 3, + + /** A high priority event has occurred. */ + GDTCORUploadConditionHighPriority = 1 << 4, +}; + +/** This protocol defines the common interface of event prioritization. Prioritizers are + * stateful objects that prioritize events upon insertion into storage and remain prepared to return + * a set of filenames to the storage system. + */ +@protocol GDTCORPrioritizer + +@required + +/** Accepts an event and uses the event metadata to make choices on how to prioritize the event. + * This method exists as a way to help prioritize which events should be sent, which is dependent on + * the request proto structure of your backend. + * + * @param event The event to prioritize. + */ +- (void)prioritizeEvent:(GDTCORStoredEvent *)event; + +/** Returns a set of events to upload given a set of conditions. + * + * @param target The target to create an upload package for. + * @param conditions A bit mask specifying the current upload conditions. + * @return An object to be used by the uploader to determine file URLs to upload with respect to the + * current conditions. + */ +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h new file mode 100644 index 0000000..0a8fbb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the registration of targets with the transport SDK. */ +@interface GDTCORRegistrar : NSObject + +/** Creates and/or returns the singleton instance. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +/** Registers a backend implementation with the GoogleDataTransport infrastructure. + * + * @param backend The backend object to register. + * @param target The target this backend object will be responsible for. + */ +- (void)registerUploader:(id)backend target:(GDTCORTarget)target; + +/** Registers a event prioritizer implementation with the GoogleDataTransport infrastructure. + * + * @param prioritizer The prioritizer object to register. + * @param target The target this prioritizer object will be responsible for. + */ +- (void)registerPrioritizer:(id)prioritizer target:(GDTCORTarget)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h new file mode 100644 index 0000000..647b220 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#import + +#import +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORStoredEvent : NSObject + +/** The data future representing the original event's transport bytes. */ +@property(readonly, nonatomic) GDTCORDataFuture *dataFuture; + +/** The mapping identifier, to allow backends to map the transport bytes to a proto. */ +@property(readonly, nonatomic) NSString *mappingID; + +/** The identifier for the backend this event will eventually be sent to. */ +@property(readonly, nonatomic) NSNumber *target; + +/** The quality of service tier this event belongs to. */ +@property(readonly, nonatomic) GDTCOREventQoS qosTier; + +/** The clock snapshot at the time of the event. */ +@property(readonly, nonatomic) GDTCORClock *clockSnapshot; + +/** A dictionary provided to aid prioritizers by allowing the passing of arbitrary data. + * + * @note Ensure that custom classes in this dict implement NSSecureCoding to prevent loss of data. + */ +@property(readonly, nullable, nonatomic) NSDictionary *customPrioritizationParams; + +/** Initializes a stored event with the given URL and event. + * + * @param event The event this stored event represents. + * @param dataFuture The dataFuture this event represents. + * @return An instance of this class. + */ +- (instancetype)initWithEvent:(GDTCOREvent *)event dataFuture:(GDTCORDataFuture *)dataFuture; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h new file mode 100644 index 0000000..5db8852 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** The list of targets supported by the shared transport infrastructure. If adding a new target, + * please use the previous value +1. + */ +typedef NS_ENUM(NSInteger, GDTCORTarget) { + + /** A target only used in testing. */ + kGDTCORTargetTest = 999, + + /** The CCT target. */ + kGDTCORTargetCCT = 1000, + + /** The FLL target. */ + kGDTCORTargetFLL = 1001, + + /** The CSH target. The CSH target is a special-purpose backend. Please do not use it without + * permission. + */ + kGDTCORTargetCSH = 1002 +}; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h new file mode 100644 index 0000000..9c72115 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCOREvent; + +NS_ASSUME_NONNULL_BEGIN + +@interface GDTCORTransport : NSObject + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Initializes a new transport that will send events to the given target backend. + * + * @param mappingID The mapping identifier used by the backend to map the data object transport + * bytes to a proto. + * @param transformers A list of transformers to be applied to events that are sent. + * @param target The target backend of this transport. + * @return A transport that will send events. + */ +- (nullable instancetype)initWithMappingID:(NSString *)mappingID + transformers: + (nullable NSArray> *)transformers + target:(NSInteger)target NS_DESIGNATED_INITIALIZER; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an internal telemetry event. Events sent using this API are lower in priority, + * and sometimes won't be sent on their own. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendTelemetryEvent:(GDTCOREvent *)event; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + * @param completion A block that will be called when the event has been written or dropped. + */ +- (void)sendDataEvent:(GDTCOREvent *)event + onComplete:(void (^)(BOOL wasWritten, NSError *_Nullable error))completion; + +/** Copies and sends an SDK service data event. Events send using this API are higher in priority, + * and will cause a network request at some point in the relative near future. + * + * @note This will convert the event's data object to data and release the original event. + * + * @param event The event to send. + */ +- (void)sendDataEvent:(GDTCOREvent *)event; + +/** Creates an event for use by this transport. + * + * @return An event that is suited for use by this transport. + */ +- (GDTCOREvent *)eventForTransport; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h new file mode 100644 index 0000000..46a676b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h @@ -0,0 +1,80 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +@class GDTCORClock; +@class GDTCORStoredEvent; +@class GDTCORUploadPackage; + +/** A protocol that allows a handler to respond to package lifecycle events. */ +@protocol GDTCORUploadPackageProtocol + +@optional + +/** Indicates that the package has expired. + * + * @note Package expiration will only be checked every 5 seconds. + * + * @param package The package that has expired. + */ +- (void)packageExpired:(GDTCORUploadPackage *)package; + +/** Indicates that the package was successfully delivered. + * + * @param package The package that was delivered. + */ +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful; + +@end + +/** This class is a container that's handed off to uploaders. */ +@interface GDTCORUploadPackage : NSObject + +/** The set of stored events in this upload package. */ +@property(nonatomic) NSSet *events; + +/** The expiration time. If [[GDTCORClock snapshot] isAfter:deliverByTime] this package has expired. + * + * @note By default, the expiration time will be 3 minutes from creation. + */ +@property(nonatomic) GDTCORClock *deliverByTime; + +/** The target of this package. */ +@property(nonatomic, readonly) GDTCORTarget target; + +/** Initializes a package instance. + * + * @param target The target/destination of this package. + * @return An instance of this class. + */ +- (instancetype)initWithTarget:(GDTCORTarget)target NS_DESIGNATED_INITIALIZER; + +// Please use the designated initializer. +- (instancetype)init NS_UNAVAILABLE; + +/** Completes delivery of the package. + * + * @note This *needs* to be called by an uploader for the package to not expire. + */ +- (void)completeDelivery; + +/** Sends the package back, indicating that delivery should be attempted again in the future. */ +- (void)retryDeliveryInTheFuture; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h new file mode 100644 index 0000000..cadee47 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This protocol defines the common interface for uploader implementations. */ +@protocol GDTCORUploader + +@required + +/** Returns YES if the uploader can make an upload attempt, NO otherwise. + * + * @param target The target being checked. + * @param conditions The conditions that the upload attempt is likely to occur under. + * @return YES if the uploader can make an upload attempt, NO otherwise. + */ +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions; + +/** Uploads events to the backend using this specific backend's chosen format. + * + * @param package The event package to upload. Make sure to call -completeDelivery. + */ +- (void)uploadPackage:(GDTCORUploadPackage *)package; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h new file mode 100644 index 0000000..e46a385 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCORDataFuture.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORRegistrar.h" +#import "GDTCORStoredEvent.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploadPackage.h" +#import "GDTCORUploader.h" diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/LICENSE b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/README.md b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransport/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m new file mode 100644 index 0000000..6ae115d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m @@ -0,0 +1,96 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" + +#import + +@implementation GDTCCTCompressionHelper + ++ (nullable NSData *)gzippedData:(NSData *)data { +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (data.length > UINT_MAX) { + return nil; + } +#endif + + const uint kChunkSize = 1024; + + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + ++ (BOOL)isGzipped:(NSData *)data { + const UInt8 *bytes = (const UInt8 *)data.bytes; + return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m new file mode 100644 index 0000000..2afb823 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m @@ -0,0 +1,198 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" + +#if TARGET_OS_IOS || TARGET_OS_TV +#import +#elif TARGET_OS_OSX +#import +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#pragma mark - General purpose encoders + +pb_bytes_array_t *GDTCCTEncodeString(NSString *string) { + NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding]; + return GDTCCTEncodeData(stringBytes); +} + +pb_bytes_array_t *GDTCCTEncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +#pragma mark - CCT object constructors + +NSData *_Nullable GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest) { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for size: %s", + PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, gdt_cct_BatchedLogRequest_fields, batchedLogRequest)) { + GDTCORLogError(GDTCORMCEGeneralError, @"Error in nanopb encoding for bytes: %s", + PB_GET_ERROR(&ostream)); + } + CFDataSetLength(dataRef, ostream.bytes_written); + + return CFBridgingRelease(dataRef); +} + +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet) { + gdt_cct_BatchedLogRequest batchedLogRequest = gdt_cct_BatchedLogRequest_init_default; + NSUInteger numberOfLogRequests = logMappingIDToLogSet.count; + gdt_cct_LogRequest *logRequests = malloc(sizeof(gdt_cct_LogRequest) * numberOfLogRequests); + + __block int i = 0; + [logMappingIDToLogSet enumerateKeysAndObjectsUsingBlock:^( + NSString *_Nonnull logMappingID, + NSSet *_Nonnull logSet, BOOL *_Nonnull stop) { + int32_t logSource = [logMappingID intValue]; + gdt_cct_LogRequest logRequest = GDTCCTConstructLogRequest(logSource, logSet); + logRequests[i] = logRequest; + i++; + }]; + + batchedLogRequest.log_request = logRequests; + batchedLogRequest.log_request_count = (pb_size_t)numberOfLogRequests; + return batchedLogRequest; +} + +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, + NSSet *_Nonnull logSet) { + if (logSet.count == 0) { + GDTCORLogError(GDTCORMCEGeneralError, @"%@", + @"An empty event set can't be serialized to proto."); + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + return logRequest; + } + gdt_cct_LogRequest logRequest = gdt_cct_LogRequest_init_default; + logRequest.log_source = logSource; + logRequest.has_log_source = 1; + logRequest.client_info = GDTCCTConstructClientInfo(); + logRequest.has_client_info = 1; + logRequest.log_event = malloc(sizeof(gdt_cct_LogEvent) * logSet.count); + int i = 0; + for (GDTCORStoredEvent *log in logSet) { + gdt_cct_LogEvent logEvent = GDTCCTConstructLogEvent(log); + logRequest.log_event[i] = logEvent; + i++; + } + logRequest.log_event_count = (pb_size_t)logSet.count; + + GDTCORClock *currentTime = [GDTCORClock snapshot]; + logRequest.request_time_ms = currentTime.timeMillis; + logRequest.has_request_time_ms = 1; + logRequest.request_uptime_ms = currentTime.uptime; + logRequest.has_request_uptime_ms = 1; + + return logRequest; +} + +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCORStoredEvent *event) { + gdt_cct_LogEvent logEvent = gdt_cct_LogEvent_init_default; + logEvent.event_time_ms = event.clockSnapshot.timeMillis; + logEvent.has_event_time_ms = 1; + logEvent.event_uptime_ms = event.clockSnapshot.uptime; + logEvent.has_event_uptime_ms = 1; + logEvent.timezone_offset_seconds = event.clockSnapshot.timezoneOffsetSeconds; + logEvent.has_timezone_offset_seconds = 1; + // TODO: Read network_connection_info from the custom params dict. + + NSError *error; + NSData *extensionBytes = [NSData dataWithContentsOfURL:event.dataFuture.fileURL + options:0 + error:&error]; + if (error) { + GDTCORLogError(GDTCORMCEGeneralError, + @"There was an error reading extension bytes from disk: %@", error); + return logEvent; + } + logEvent.source_extension = GDTCCTEncodeData(extensionBytes); // read bytes from the file. + return logEvent; +} + +gdt_cct_ClientInfo GDTCCTConstructClientInfo() { + gdt_cct_ClientInfo clientInfo = gdt_cct_ClientInfo_init_default; + clientInfo.client_type = gdt_cct_ClientInfo_ClientType_IOS_FIREBASE; + clientInfo.has_client_type = 1; +#if TARGET_OS_IOS || TARGET_OS_TV + clientInfo.ios_client_info = GDTCCTConstructiOSClientInfo(); + clientInfo.has_ios_client_info = 1; +#elif TARGET_OS_OSX + // TODO(mikehaney24): Expand the proto to include macOS client info. +#endif + return clientInfo; +} + +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo() { + gdt_cct_IosClientInfo iOSClientInfo = gdt_cct_IosClientInfo_init_default; +#if TARGET_OS_IOS || TARGET_OS_TV + UIDevice *device = [UIDevice currentDevice]; + NSBundle *bundle = [NSBundle mainBundle]; + NSLocale *locale = [NSLocale currentLocale]; + iOSClientInfo.os_full_version = GDTCCTEncodeString(device.systemVersion); + NSArray *versionComponents = [device.systemVersion componentsSeparatedByString:@"."]; + iOSClientInfo.os_major_version = GDTCCTEncodeString(versionComponents[0]); + NSString *version = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; + if (version) { + iOSClientInfo.application_build = GDTCCTEncodeString(version); + } + NSString *countryCode = [locale objectForKey:NSLocaleCountryCode]; + if (countryCode) { + iOSClientInfo.country = GDTCCTEncodeString([locale objectForKey:NSLocaleCountryCode]); + } + iOSClientInfo.model = GDTCCTEncodeString(device.model); + NSString *languageCode = bundle.preferredLocalizations.firstObject; + iOSClientInfo.language_code = + languageCode ? GDTCCTEncodeString(languageCode) : GDTCCTEncodeString(@"en"); + iOSClientInfo.application_bundle_id = GDTCCTEncodeString(bundle.bundleIdentifier); +#endif + return iOSClientInfo; +} + +#pragma mark - CCT Object decoders + +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error) { + gdt_cct_LogResponse response = gdt_cct_LogResponse_init_default; + pb_istream_t istream = pb_istream_from_buffer([data bytes], [data length]); + if (!pb_decode(&istream, gdt_cct_LogResponse_fields, &response)) { + NSString *nanopb_error = [NSString stringWithFormat:@"%s", PB_GET_ERROR(&istream)]; + NSDictionary *userInfo = @{@"nanopb error:" : nanopb_error}; + if (error != NULL) { + *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:userInfo]; + } + response = (gdt_cct_LogResponse)gdt_cct_LogResponse_init_default; + } + return response; +} diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m new file mode 100644 index 0000000..3e2906c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m @@ -0,0 +1,252 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import +#import +#import +#import +#import + +const static int64_t kMillisPerDay = 8.64e+7; + +@implementation GDTCCTPrioritizer + ++ (void)load { + GDTCCTPrioritizer *prioritizer = [GDTCCTPrioritizer sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerPrioritizer:prioritizer target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTPrioritizer *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTPrioritizer alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _queue = dispatch_queue_create("com.google.GDTCCTPrioritizer", DISPATCH_QUEUE_SERIAL); + _CCTEvents = [[NSMutableSet alloc] init]; + _FLLEvents = [[NSMutableSet alloc] init]; + _CSHEvents = [[NSMutableSet alloc] init]; + } + return self; +} + +#pragma mark - GDTCORPrioritizer Protocol + +- (void)prioritizeEvent:(GDTCORStoredEvent *)event { + dispatch_async(_queue, ^{ + switch (event.target.intValue) { + case kGDTCORTargetCCT: + [self.CCTEvents addObject:event]; + break; + + case kGDTCORTargetFLL: + [self.FLLEvents addObject:event]; + break; + + case kGDTCORTargetCSH: + [self.CSHEvents addObject:event]; + break; + + default: + GDTCORLogDebug("GDTCCTPrioritizer doesn't support target %d", event.target.intValue); + break; + } + }); +} + +- (GDTCORUploadPackage *)uploadPackageWithTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORUploadPackage *package = [[GDTCORUploadPackage alloc] initWithTarget:target]; + dispatch_sync(_queue, ^{ + NSSet *eventsThatWillBeSent = [self eventsForTarget:target + conditions:conditions]; + package.events = eventsThatWillBeSent; + }); + GDTCORLogDebug("CCT: %lu events are in the upload package", (unsigned long)package.events.count); + return package; +} + +#pragma mark - Private helper methods + +/** The different possible quality of service specifiers. High values indicate high priority. */ +typedef NS_ENUM(NSInteger, GDTCCTQoSTier) { + /** The QoS tier wasn't set, and won't ever be sent. */ + GDTCCTQoSDefault = 0, + + /** This event is internal telemetry data that should not be sent on its own if possible. */ + GDTCCTQoSTelemetry = 1, + + /** This event should be sent, but in a batch only roughly once per day. */ + GDTCCTQoSDaily = 2, + + /** This event should only be uploaded on wifi. */ + GDTCCTQoSWifiOnly = 5, +}; + +/** Converts a GDTCOREventQoS to a GDTCCTQoS tier. + * + * @param qosTier The GDTCOREventQoS value. + * @return A static NSNumber that represents the CCT QoS tier. + */ +FOUNDATION_STATIC_INLINE +NSNumber *GDTCCTQosTierFromGDTCOREventQosTier(GDTCOREventQoS qosTier) { + switch (qosTier) { + case GDTCOREventQoSWifiOnly: + return @(GDTCCTQoSWifiOnly); + break; + + case GDTCOREventQoSTelemetry: + // falls through. + case GDTCOREventQoSDaily: + return @(GDTCCTQoSDaily); + break; + + default: + return @(GDTCCTQoSDefault); + break; + } +} + +/** Constructs a set of events for upload to CCT, FLL, or CSH backends. These backends are + * request-proto and batching compatible, so they construct event batches the same way. + * + * @param conditions The set of conditions the upload package should be made under. + * @param target The target backend. + * @return A set of events for the target. + */ +- (NSSet *)eventsForTarget:(GDTCORTarget)target + conditions:(GDTCORUploadConditions)conditions { + GDTCORClock __strong **timeOfLastDailyUpload = NULL; + NSSet *eventsToFilter; + switch (target) { + case kGDTCORTargetCCT: + eventsToFilter = self.CCTEvents; + timeOfLastDailyUpload = &self->_CCTTimeOfLastDailyUpload; + break; + + case kGDTCORTargetFLL: + eventsToFilter = self.FLLEvents; + timeOfLastDailyUpload = &self->_FLLOfLastDailyUpload; + break; + + case kGDTCORTargetCSH: + // This backend doesn't batch and uploads all events as soon as possible without respect to + // any upload condition. + return self.CSHEvents; + break; + + default: + // Return an empty set. + return [[NSSet alloc] init]; + break; + } + + NSMutableSet *eventsThatWillBeSent = [[NSMutableSet alloc] init]; + // A high priority event effectively flushes all events to be sent. + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + GDTCORLogDebug("%@", @"CCT: A high priority event is flushing all events."); + return eventsToFilter; + } + + // If on wifi, upload logs that are ok to send on wifi. + if ((conditions & GDTCORUploadConditionWifiData) == GDTCORUploadConditionWifiData) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnWifi:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send on wifi are being added to the upload package"); + } else { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendOnMobileData:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send on mobile are being added to the upload package"); + } + + // If it's been > 24h since the last daily upload, upload logs with the daily QoS. + if (*timeOfLastDailyUpload) { + int64_t millisSinceLastUpload = + [GDTCORClock snapshot].timeMillis - (*timeOfLastDailyUpload).timeMillis; + if (millisSinceLastUpload > kMillisPerDay) { + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send daily are being added to the upload package"); + } + } else { + *timeOfLastDailyUpload = [GDTCORClock snapshot]; + [eventsThatWillBeSent unionSet:[self logEventsOkToSendDaily:eventsToFilter]]; + GDTCORLogDebug("%@", @"CCT: events ok to send daily are being added to the upload package"); + } + return eventsThatWillBeSent; +} + +/** Returns a set of logs that are ok to upload whilst on mobile data. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on mobile data. + */ +- (NSSet *)logEventsOkToSendOnMobileData:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDefault)]; + }]; +} + +/** Returns a set of logs that are ok to upload whilst on wifi. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload whilst on wifi. + */ +- (NSSet *)logEventsOkToSendOnWifi:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + NSNumber *qosTier = GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier); + return [qosTier isEqual:@(GDTCCTQoSDefault)] || [qosTier isEqual:@(GDTCCTQoSWifiOnly)] || + [qosTier isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +/** Returns a set of logs that only should have a single upload attempt per day. + * + * @note This should be called from a thread safe method. + * @return A set of logs that are ok to upload only once per day. + */ +- (NSSet *)logEventsOkToSendDaily:(NSSet *)events { + return [events objectsPassingTest:^BOOL(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + return [GDTCCTQosTierFromGDTCOREventQosTier(event.qosTier) isEqual:@(GDTCCTQoSDaily)]; + }]; +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageDelivered:(GDTCORUploadPackage *)package successful:(BOOL)successful { + dispatch_async(_queue, ^{ + NSSet *events = [package.events copy]; + for (GDTCORStoredEvent *event in events) { + // We don't know what collection the event was contained in, so attempt removal from all. + [self.CCTEvents removeObject:event]; + [self.FLLEvents removeObject:event]; + [self.CSHEvents removeObject:event]; + } + }); +} + +- (void)packageExpired:(GDTCORUploadPackage *)package { + [self packageDelivered:package successful:YES]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m new file mode 100644 index 0000000..7c6d4f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m @@ -0,0 +1,450 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "GDTCCTLibrary/Private/GDTCCTUploader.h" + +#import +#import +#import + +#import +#import +#import + +#import "GDTCCTLibrary/Private/GDTCCTCompressionHelper.h" +#import "GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h" +#import "GDTCCTLibrary/Private/GDTCCTPrioritizer.h" + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +#ifdef GDTCCTSUPPORT_VERSION +#define STR(x) STR_EXPAND(x) +#define STR_EXPAND(x) #x +static NSString *const kGDTCCTSupportSDKVersion = @STR(GDTCCTSUPPORT_VERSION); +#else +static NSString *const kGDTCCTSupportSDKVersion = @"UNKNOWN"; +#endif // GDTCCTSUPPORT_VERSION + +#if !NDEBUG +NSNotificationName const GDTCCTUploadCompleteNotification = @"com.GDTCCTUploader.UploadComplete"; +#endif // #if !NDEBUG + +@interface GDTCCTUploader () + +// Redeclared as readwrite. +@property(nullable, nonatomic, readwrite) NSURLSessionUploadTask *currentTask; + +@end + +@implementation GDTCCTUploader + ++ (void)load { + GDTCCTUploader *uploader = [GDTCCTUploader sharedInstance]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCCT]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetFLL]; + [[GDTCORRegistrar sharedInstance] registerUploader:uploader target:kGDTCORTargetCSH]; +} + ++ (instancetype)sharedInstance { + static GDTCCTUploader *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[GDTCCTUploader alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _uploaderQueue = dispatch_queue_create("com.google.GDTCCTUploader", DISPATCH_QUEUE_SERIAL); + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + _uploaderSession = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + } + return self; +} + +/** + * + */ +- (nullable NSURL *)serverURLForTarget:(GDTCORTarget)target { + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + static NSURL *CCTServerURL; + static dispatch_once_t CCTOnceToken; + dispatch_once(&CCTOnceToken, ^{ + const char *p1 = "hts/frbslgiggolai.o/0clgbth"; + const char *p2 = "tp:/ieaeogn.ogepscmvc/o/ac"; + const char URL[54] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], '\0'}; + CCTServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *FLLServerURL; + static dispatch_once_t FLLOnceToken; + dispatch_once(&FLLOnceToken, ^{ + const char *p1 = "hts/frbslgigp.ogepscmv/ieo/eaybtho"; + const char *p2 = "tp:/ieaeogn-agolai.o/1frlglgc/aclg"; + const char URL[69] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], '\0'}; + FLLServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + + static NSURL *CSHServerURL; + static dispatch_once_t CSHOnceToken; + dispatch_once(&CSHOnceToken, ^{ + // These strings should be interleaved to construct the real URL. This is just to (hopefully) + // fool github URL scanning bots. + const char *p1 = "hts/cahyiseot-agolai.o/1frlglgc/aclg"; + const char *p2 = "tp:/rsltcrprsp.ogepscmv/ieo/eaybtho"; + const char URL[72] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], p1[4], + p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], p1[8], p2[8], + p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], p1[12], p2[12], p1[13], + p2[13], p1[14], p2[14], p1[15], p2[15], p1[16], p2[16], p1[17], p2[17], + p1[18], p2[18], p1[19], p2[19], p1[20], p2[20], p1[21], p2[21], p1[22], + p2[22], p1[23], p2[23], p1[24], p2[24], p1[25], p2[25], p1[26], p2[26], + p1[27], p2[27], p1[28], p2[28], p1[29], p2[29], p1[30], p2[30], p1[31], + p2[31], p1[32], p2[32], p1[33], p2[33], p1[34], p2[34], p1[35], '\0'}; + CSHServerURL = [NSURL URLWithString:[NSString stringWithUTF8String:URL]]; + }); + +#if !NDEBUG + if (_testServerURL) { + return _testServerURL; + } +#endif // !NDEBUG + + switch (target) { + case kGDTCORTargetCCT: + return CCTServerURL; + + case kGDTCORTargetFLL: + return FLLServerURL; + + case kGDTCORTargetCSH: + return CSHServerURL; + + default: + GDTCORLogDebug("GDTCCTUploader doesn't support target %ld", (long)target); + return nil; + break; + } +} + +- (NSString *)FLLAndCSHAPIKey { + static NSString *defaultServerKey; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // These strings should be interleaved to construct the real key. + const char *p1 = "AzSBG0honD6A-PxV5nBc"; + const char *p2 = "Iay44Iwtu2vV0AOrz1C"; + const char defaultKey[40] = {p1[0], p2[0], p1[1], p2[1], p1[2], p2[2], p1[3], p2[3], + p1[4], p2[4], p1[5], p2[5], p1[6], p2[6], p1[7], p2[7], + p1[8], p2[8], p1[9], p2[9], p1[10], p2[10], p1[11], p2[11], + p1[12], p2[12], p1[13], p2[13], p1[14], p2[14], p1[15], p2[15], + p1[16], p2[16], p1[17], p2[17], p1[18], p2[18], p1[19], '\0'}; + defaultServerKey = [NSString stringWithUTF8String:defaultKey]; + }); + return defaultServerKey; +} + +- (void)uploadPackage:(GDTCORUploadPackage *)package { + __block GDTCORBackgroundIdentifier bgID = GDTCORBackgroundIdentifierInvalid; + bgID = [[GDTCORApplication sharedApplication] + beginBackgroundTaskWithName:@"GDTCCTUploader-upload" + expirationHandler:^{ + if (bgID != GDTCORBackgroundIdentifierInvalid) { + // Cancel the upload and complete delivery. + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + + // End the background task. + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + } + }]; + + dispatch_async(_uploaderQueue, ^{ + if (self->_currentTask || self->_currentUploadPackage) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"%@", + @"An upload shouldn't be initiated with another in progress."); + return; + } + GDTCORTarget target = package.target; + id completionHandler = ^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + GDTCORLogDebug("%@", @"CCT: request completed"); + if (error) { + GDTCORLogWarning(GDTCORMCWUploadFailed, @"There was an error uploading events: %@", error); + } + NSError *decodingError; + if (data) { + gdt_cct_LogResponse logResponse = GDTCCTDecodeLogResponse(data, &decodingError); + if (!decodingError && logResponse.has_next_request_wait_millis) { + GDTCORLogDebug( + "CCT: The backend responded asking to not upload for %lld millis from now.", + logResponse.next_request_wait_millis); + GDTCORClock *futureUploadTime = + [GDTCORClock clockSnapshotInTheFuture:logResponse.next_request_wait_millis]; + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + default: + break; + } + } else { + GDTCORLogDebug("%@", @"CCT: The backend response failed to parse, so the next request " + @"won't occur until 15 minutes from now"); + // 15 minutes from now. + GDTCORClock *futureUploadTime = [GDTCORClock clockSnapshotInTheFuture:15 * 60 * 1000]; + switch (target) { + case kGDTCORTargetCCT: + self->_CCTNextUploadTime = futureUploadTime; + break; + + case kGDTCORTargetFLL: + // Falls through. + case kGDTCORTargetCSH: + self->_FLLNextUploadTime = futureUploadTime; + break; + + default: + break; + } + } + pb_release(gdt_cct_LogResponse_fields, &logResponse); + } + + // Only retry if one of these codes is returned. + if (((NSHTTPURLResponse *)response).statusCode == 429 || + ((NSHTTPURLResponse *)response).statusCode == 503) { + [package retryDeliveryInTheFuture]; + } else { +#if !NDEBUG + // Post a notification when in DEBUG mode to state how many packages were uploaded. Useful + // for validation during tests. + [[NSNotificationCenter defaultCenter] postNotificationName:GDTCCTUploadCompleteNotification + object:@(package.events.count)]; +#endif // #if !NDEBUG + GDTCORLogDebug("%@", @"CCT: package delivered"); + [package completeDelivery]; + } + + // End the background task if there was one. + if (bgID != GDTCORBackgroundIdentifierInvalid) { + [[GDTCORApplication sharedApplication] endBackgroundTask:bgID]; + bgID = GDTCORBackgroundIdentifierInvalid; + } + self.currentTask = nil; + self.currentUploadPackage = nil; + }; + self->_currentUploadPackage = package; + NSData *requestProtoData = + [self constructRequestProtoFromPackage:(GDTCORUploadPackage *)package]; + NSData *gzippedData = [GDTCCTCompressionHelper gzippedData:requestProtoData]; + BOOL usingGzipData = gzippedData != nil && gzippedData.length < requestProtoData.length; + NSData *dataToSend = usingGzipData ? gzippedData : requestProtoData; + NSURLRequest *request = [self constructRequestForTarget:target data:dataToSend]; + GDTCORLogDebug("CTT: request created: %@", request); + self.currentTask = [self.uploaderSession uploadTaskWithRequest:request + fromData:dataToSend + completionHandler:completionHandler]; + GDTCORLogDebug("%@", @"CCT: The upload task is about to begin."); + [self.currentTask resume]; + }); +} + +- (BOOL)readyToUploadTarget:(GDTCORTarget)target conditions:(GDTCORUploadConditions)conditions { + __block BOOL result = NO; + dispatch_sync(_uploaderQueue, ^{ + if (target == kGDTCORTargetCSH && [GDTCCTPrioritizer sharedInstance].CSHEvents.count > 0) { + result = YES; + return; + } + if (self->_currentUploadPackage) { + result = NO; + GDTCORLogDebug("%@", @"CCT: can't upload because a package is in flight"); + return; + } + if (self->_currentTask) { + result = NO; + GDTCORLogDebug("%@", @"CCT: can't upload because a task is in progress"); + return; + } + if ((conditions & GDTCORUploadConditionHighPriority) == GDTCORUploadConditionHighPriority) { + result = YES; + GDTCORLogDebug("%@", @"CCT: a high priority event is allowing an upload"); + return; + } + switch (target) { + case kGDTCORTargetCCT: + if (self->_CCTNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_CCTNextUploadTime]; + } + break; + + case kGDTCORTargetFLL: + if (self->_FLLNextUploadTime) { + result = [[GDTCORClock snapshot] isAfter:self->_FLLNextUploadTime]; + } + break; + + default: + // The CSH backend should be handled above. + break; + } + if (result) { + GDTCORLogDebug("CCT: can upload to target %ld because the request wait time has transpired", + (long)target); + } else { + GDTCORLogDebug("CCT: can't upload to target %ld because the backend asked to wait", + (long)target); + } + result = YES; + GDTCORLogDebug("CCT: can upload to target %ld because nothing is preventing it", (long)target); + }); + return result; +} + +#pragma mark - Private helper methods + +/** Constructs data given an upload package. + * + * @param package The upload package used to construct the request proto bytes. + * @return Proto bytes representing a gdt_cct_LogRequest object. + */ +- (nonnull NSData *)constructRequestProtoFromPackage:(GDTCORUploadPackage *)package { + // Segment the log events by log type. + NSMutableDictionary *> *logMappingIDToLogSet = + [[NSMutableDictionary alloc] init]; + [package.events + enumerateObjectsUsingBlock:^(GDTCORStoredEvent *_Nonnull event, BOOL *_Nonnull stop) { + NSMutableSet *logSet = logMappingIDToLogSet[event.mappingID]; + logSet = logSet ? logSet : [[NSMutableSet alloc] init]; + [logSet addObject:event]; + logMappingIDToLogSet[event.mappingID] = logSet; + }]; + + gdt_cct_BatchedLogRequest batchedLogRequest = + GDTCCTConstructBatchedLogRequest(logMappingIDToLogSet); + + NSData *data = GDTCCTEncodeBatchedLogRequest(&batchedLogRequest); + pb_release(gdt_cct_BatchedLogRequest_fields, &batchedLogRequest); + return data ? data : [[NSData alloc] init]; +} + +/** Constructs a request to FLL given a URL and request body data. + * + * @param target The target backend to send the request to. + * @param data The request body data. + * @return A new NSURLRequest ready to be sent to FLL. + */ +- (NSURLRequest *)constructRequestForTarget:(GDTCORTarget)target data:(NSData *)data { + NSURL *URL = [self serverURLForTarget:target]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; + NSString *targetString; + switch (target) { + case kGDTCORTargetCCT: + targetString = @"cct"; + break; + + case kGDTCORTargetFLL: + targetString = @"fll"; + break; + + case kGDTCORTargetCSH: + targetString = @"csh"; + break; + + default: + targetString = @"unknown"; + break; + } + NSString *userAgent = + [NSString stringWithFormat:@"datatransport/%@ %@support/%@ apple/", kGDTCORVersion, + targetString, kGDTCCTSupportSDKVersion]; + if (target == kGDTCORTargetFLL || target == kGDTCORTargetCSH) { + [request setValue:[self FLLAndCSHAPIKey] forHTTPHeaderField:@"X-Goog-Api-Key"]; + } + if ([GDTCCTCompressionHelper isGzipped:data]) { + [request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + } + [request setValue:@"application/x-protobuf" forHTTPHeaderField:@"Content-Type"]; + [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; + [request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; + request.HTTPMethod = @"POST"; + [request setHTTPBody:data]; + return request; +} + +#pragma mark - GDTCORUploadPackageProtocol + +- (void)packageExpired:(GDTCORUploadPackage *)package { + dispatch_async(_uploaderQueue, ^{ + [self.currentTask cancel]; + self.currentTask = nil; + self.currentUploadPackage = nil; + }); +} + +#pragma mark - GDTCORLifecycleProtocol + +- (void)appWillTerminate:(GDTCORApplication *)application { + dispatch_sync(_uploaderQueue, ^{ + [self.currentTask cancel]; + [self.currentUploadPackage completeDelivery]; + }); +} + +#pragma mark - NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { + if (!completionHandler) { + return; + } + if (response.statusCode == 302 || response.statusCode == 301) { + if ([request.URL isEqual:[self serverURLForTarget:kGDTCORTargetFLL]]) { + NSURLRequest *newRequest = [self constructRequestForTarget:kGDTCORTargetCCT + data:task.originalRequest.HTTPBody]; + completionHandler(newRequest); + } + } else { + completionHandler(request); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h new file mode 100644 index 0000000..08d0a4b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** A class with methods to help with gzipped data. */ +@interface GDTCCTCompressionHelper : NSObject + +/** Compresses the given data and returns a new data object. + * + * @note Reduced version from GULNSData+zlib.m of GoogleUtilities. + * @return Compressed data, or nil if there was an error. + */ ++ (nullable NSData *)gzippedData:(NSData *)data; + +/** Returns YES if the data looks like it was gzip compressed by checking for the gzip magic number. + * + * @note: From https://en.wikipedia.org/wiki/Gzip, gzip's magic number is 1f 8b. + * @return YES if the data appears gzipped, NO otherwise. + */ ++ (BOOL)isGzipped:(NSData *)data; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h new file mode 100644 index 0000000..08081cc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h @@ -0,0 +1,112 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h" + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - General purpose encoders + +/** Converts an NSString* to a pb_bytes_array_t*. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param string The string to convert. + * @return A newly allocated array of bytes representing the UTF8 encoding of the string. + */ +pb_bytes_array_t *GDTCCTEncodeString(NSString *string); + +/** Converts an NSData to a pb_bytes_array_t*. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param data The data to convert. + * @return A newly allocated array of bytes with [data bytes] copied into it. + */ +pb_bytes_array_t *GDTCCTEncodeData(NSData *data); + +#pragma mark - CCT object constructors + +/** Encodes a batched log request. + * + * @note Ensure that pb_release is called on the batchedLogRequest param. + * + * @param batchedLogRequest A pointer to the log batch to encode to bytes. + * @return An NSData object representing the bytes of the log request batch. + */ +FOUNDATION_EXPORT +NSData *GDTCCTEncodeBatchedLogRequest(gdt_cct_BatchedLogRequest *batchedLogRequest); + +/** Constructs a gdt_cct_BatchedLogRequest given sets of events segemented by mapping ID. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * + * @param logMappingIDToLogSet A map of mapping IDs to sets of events to convert into a batch. + * @return A newly created gdt_cct_BatchedLogRequest. + */ +FOUNDATION_EXPORT +gdt_cct_BatchedLogRequest GDTCCTConstructBatchedLogRequest( + NSDictionary *> *logMappingIDToLogSet); + +/** Constructs a log request given a log source and a set of events. + * + * @note malloc is called in this method. Ensure that pb_release is called on this or the parent. + * @param logSource The CCT log source to put into the log request. + * @param logSet The set of events to send in this log request. + */ +FOUNDATION_EXPORT +gdt_cct_LogRequest GDTCCTConstructLogRequest(int32_t logSource, NSSet *logSet); + +/** Constructs a gdt_cct_LogEvent given a GDTCORStoredEvent*. + * + * @param event The GDTCORStoredEvent to convert. + * @return The new gdt_cct_LogEvent object. + */ +FOUNDATION_EXPORT +gdt_cct_LogEvent GDTCCTConstructLogEvent(GDTCORStoredEvent *event); + +/** Constructs a gdt_cct_ClientInfo representing the client device. + * + * @return The new gdt_cct_ClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_ClientInfo GDTCCTConstructClientInfo(void); + +/** Constructs a gdt_cct_IosClientInfo representing the client device. + * + * @return The new gdt_cct_IosClientInfo object. + */ +FOUNDATION_EXPORT +gdt_cct_IosClientInfo GDTCCTConstructiOSClientInfo(void); + +#pragma mark - CCT object decoders + +/** Decodes a gdt_cct_LogResponse given proto bytes. + * + * @note malloc is called in this method. Ensure that pb_release is called on the return value. + * + * @param data The proto bytes of the gdt_cct_LogResponse. + * @param error An error that will be populated if something went wrong during decoding. + * @return A newly allocated gdt_cct_LogResponse from the data, if the bytes decoded properly. + */ +FOUNDATION_EXPORT +gdt_cct_LogResponse GDTCCTDecodeLogResponse(NSData *data, NSError **error); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h new file mode 100644 index 0000000..22414e2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** Manages the prioritization of events from GoogleDataTransport. */ +@interface GDTCCTPrioritizer : NSObject + +/** The queue on which this prioritizer operates. */ +@property(nonatomic) dispatch_queue_t queue; + +/** All CCT events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CCTEvents; + +/** All FLL events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *FLLEvents; + +/** All CSH events that have been processed by this prioritizer. */ +@property(nonatomic) NSMutableSet *CSHEvents; + +/** The most recent attempted upload of CCT daily uploaded logs. */ +@property(nonatomic) GDTCORClock *CCTTimeOfLastDailyUpload; + +/** The most recent attempted upload of FLL daily uploaded logs*/ +@property(nonatomic) GDTCORClock *FLLOfLastDailyUpload; + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h new file mode 100644 index 0000000..cdc322d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h @@ -0,0 +1,63 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +#if !NDEBUG +/** A notification fired when uploading is complete, detailing the number of events uploaded. */ +extern NSNotificationName const GDTCCTUploadCompleteNotification; +#endif // #if !NDEBUG + +/** Class capable of uploading events to the CCT backend. */ +@interface GDTCCTUploader : NSObject + +/** The queue on which all CCT uploading will occur. */ +@property(nonatomic, readonly) dispatch_queue_t uploaderQueue; + +/** The URL session that will attempt upload. */ +@property(nonatomic, readonly) NSURLSession *uploaderSession; + +/** The current upload task. */ +@property(nullable, nonatomic, readonly) NSURLSessionUploadTask *currentTask; + +/** Current upload package. */ +@property(nullable, nonatomic) GDTCORUploadPackage *currentUploadPackage; + +/** The next upload time for the CCT target. */ +@property(nullable, nonatomic) GDTCORClock *CCTNextUploadTime; + +/** The next upload time for the FLL target. */ +@property(nullable, nonatomic) GDTCORClock *FLLNextUploadTime; + +#if !NDEBUG +/** An upload URL used across all targets. For testing only. */ +@property(nullable, nonatomic) NSURL *testServerURL; + +#endif // !NDEBUG + +/** Creates and/or returns the singleton instance of this class. + * + * @return The singleton instance of this class. + */ ++ (instancetype)sharedInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c new file mode 100644 index 0000000..95846e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c @@ -0,0 +1,128 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 */ + +#include "cct.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default = gdt_cct_NetworkConnectionInfo_NetworkType_NONE; +const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default = gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE; +const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default = gdt_cct_QosTierConfiguration_QosTier_DEFAULT; +const int32_t gdt_cct_QosTierConfiguration_log_source_default = 0; + + +const pb_field_t gdt_cct_LogEvent_fields[7] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogEvent, event_time_ms, event_time_ms, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_LogEvent, source_extension, event_time_ms, 0), + PB_FIELD( 11, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_code, source_extension, 0), + PB_FIELD( 15, SINT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, timezone_offset_seconds, event_code, 0), + PB_FIELD( 17, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, event_uptime_ms, timezone_offset_seconds, 0), + PB_FIELD( 23, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogEvent, network_connection_info, event_uptime_ms, &gdt_cct_NetworkConnectionInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3] = { + PB_FIELD( 1, ENUM , OPTIONAL, STATIC , FIRST, gdt_cct_NetworkConnectionInfo, network_type, network_type, &gdt_cct_NetworkConnectionInfo_network_type_default), + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_NetworkConnectionInfo, mobile_subtype, network_type, &gdt_cct_NetworkConnectionInfo_mobile_subtype_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_IosClientInfo_fields[8] = { + PB_FIELD( 3, BYTES , OPTIONAL, POINTER , FIRST, gdt_cct_IosClientInfo, os_major_version, os_major_version, 0), + PB_FIELD( 4, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, os_full_version, os_major_version, 0), + PB_FIELD( 5, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_build, os_full_version, 0), + PB_FIELD( 6, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, country, application_build, 0), + PB_FIELD( 7, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, model, country, 0), + PB_FIELD( 8, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, language_code, model, 0), + PB_FIELD( 11, BYTES , OPTIONAL, POINTER , OTHER, gdt_cct_IosClientInfo, application_bundle_id, language_code, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_ClientInfo_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_ClientInfo, client_type, client_type, 0), + PB_FIELD( 4, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_ClientInfo, ios_client_info, client_type, &gdt_cct_IosClientInfo_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_BatchedLogRequest_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_BatchedLogRequest, log_request, log_request, &gdt_cct_LogRequest_fields), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogRequest_fields[7] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, gdt_cct_LogRequest, client_info, client_info, &gdt_cct_ClientInfo_fields), + PB_FIELD( 2, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, log_source, client_info, 0), + PB_FIELD( 3, MESSAGE , REPEATED, POINTER , OTHER, gdt_cct_LogRequest, log_event, log_source, &gdt_cct_LogEvent_fields), + PB_FIELD( 4, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_time_ms, log_event, 0), + PB_FIELD( 8, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, request_uptime_ms, request_time_ms, 0), + PB_FIELD( 9, UENUM , OPTIONAL, STATIC , OTHER, gdt_cct_LogRequest, qos_tier, request_uptime_ms, &gdt_cct_LogRequest_qos_tier_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTierConfiguration_fields[3] = { + PB_FIELD( 2, UENUM , OPTIONAL, STATIC , FIRST, gdt_cct_QosTierConfiguration, qos_tier, qos_tier, 0), + PB_FIELD( 3, INT32 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTierConfiguration, log_source, qos_tier, &gdt_cct_QosTierConfiguration_log_source_default), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_QosTiersOverride_fields[3] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, gdt_cct_QosTiersOverride, qos_tier_configuration, qos_tier_configuration, &gdt_cct_QosTierConfiguration_fields), + PB_FIELD( 2, INT64 , OPTIONAL, STATIC , OTHER, gdt_cct_QosTiersOverride, qos_tier_fingerprint, qos_tier_configuration, 0), + PB_LAST_FIELD +}; + +const pb_field_t gdt_cct_LogResponse_fields[3] = { + PB_FIELD( 1, INT64 , OPTIONAL, STATIC , FIRST, gdt_cct_LogResponse, next_request_wait_millis, next_request_wait_millis, 0), + PB_FIELD( 3, MESSAGE , OPTIONAL, STATIC , OTHER, gdt_cct_LogResponse, qos_tier, next_request_wait_millis, &gdt_cct_QosTiersOverride_fields), + PB_LAST_FIELD +}; + + + + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 65536 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 65536 && pb_membersize(gdt_cct_LogRequest, client_info) < 65536 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(gdt_cct_LogEvent, network_connection_info) < 256 && pb_membersize(gdt_cct_ClientInfo, ios_client_info) < 256 && pb_membersize(gdt_cct_LogRequest, client_info) < 256 && pb_membersize(gdt_cct_LogResponse, qos_tier) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_gdt_cct_LogEvent_gdt_cct_NetworkConnectionInfo_gdt_cct_IosClientInfo_gdt_cct_ClientInfo_gdt_cct_BatchedLogRequest_gdt_cct_LogRequest_gdt_cct_QosTierConfiguration_gdt_cct_QosTiersOverride_gdt_cct_LogResponse) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h new file mode 100644 index 0000000..a6d4cfb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h @@ -0,0 +1,281 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 */ + +#ifndef PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#define PB_GDT_CCT_CCT_NANOPB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _gdt_cct_NetworkConnectionInfo_NetworkType { + gdt_cct_NetworkConnectionInfo_NetworkType_NONE = -1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE = 0, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI = 1, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_MMS = 2, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_SUPL = 3, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_DUN = 4, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_HIPRI = 5, + gdt_cct_NetworkConnectionInfo_NetworkType_WIMAX = 6, + gdt_cct_NetworkConnectionInfo_NetworkType_BLUETOOTH = 7, + gdt_cct_NetworkConnectionInfo_NetworkType_DUMMY = 8, + gdt_cct_NetworkConnectionInfo_NetworkType_ETHERNET = 9, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_FOTA = 10, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IMS = 11, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_CBS = 12, + gdt_cct_NetworkConnectionInfo_NetworkType_WIFI_P2P = 13, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_IA = 14, + gdt_cct_NetworkConnectionInfo_NetworkType_MOBILE_EMERGENCY = 15, + gdt_cct_NetworkConnectionInfo_NetworkType_PROXY = 16, + gdt_cct_NetworkConnectionInfo_NetworkType_VPN = 17 +} gdt_cct_NetworkConnectionInfo_NetworkType; +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MIN gdt_cct_NetworkConnectionInfo_NetworkType_NONE +#define _gdt_cct_NetworkConnectionInfo_NetworkType_MAX gdt_cct_NetworkConnectionInfo_NetworkType_VPN +#define _gdt_cct_NetworkConnectionInfo_NetworkType_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_NetworkType)(gdt_cct_NetworkConnectionInfo_NetworkType_VPN+1)) + +typedef enum _gdt_cct_NetworkConnectionInfo_MobileSubtype { + gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE = 0, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GPRS = 1, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EDGE = 2, + gdt_cct_NetworkConnectionInfo_MobileSubtype_UMTS = 3, + gdt_cct_NetworkConnectionInfo_MobileSubtype_CDMA = 4, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_0 = 5, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_A = 6, + gdt_cct_NetworkConnectionInfo_MobileSubtype_RTT = 7, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSDPA = 8, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSUPA = 9, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPA = 10, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IDEN = 11, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EVDO_B = 12, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE = 13, + gdt_cct_NetworkConnectionInfo_MobileSubtype_EHRPD = 14, + gdt_cct_NetworkConnectionInfo_MobileSubtype_HSPAP = 15, + gdt_cct_NetworkConnectionInfo_MobileSubtype_GSM = 16, + gdt_cct_NetworkConnectionInfo_MobileSubtype_TD_SCDMA = 17, + gdt_cct_NetworkConnectionInfo_MobileSubtype_IWLAN = 18, + gdt_cct_NetworkConnectionInfo_MobileSubtype_LTE_CA = 19, + gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED = 100 +} gdt_cct_NetworkConnectionInfo_MobileSubtype; +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_MAX gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED +#define _gdt_cct_NetworkConnectionInfo_MobileSubtype_ARRAYSIZE ((gdt_cct_NetworkConnectionInfo_MobileSubtype)(gdt_cct_NetworkConnectionInfo_MobileSubtype_COMBINED+1)) + +typedef enum _gdt_cct_ClientInfo_ClientType { + gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN = 0, + gdt_cct_ClientInfo_ClientType_IOS_FIREBASE = 15 +} gdt_cct_ClientInfo_ClientType; +#define _gdt_cct_ClientInfo_ClientType_MIN gdt_cct_ClientInfo_ClientType_CLIENT_UNKNOWN +#define _gdt_cct_ClientInfo_ClientType_MAX gdt_cct_ClientInfo_ClientType_IOS_FIREBASE +#define _gdt_cct_ClientInfo_ClientType_ARRAYSIZE ((gdt_cct_ClientInfo_ClientType)(gdt_cct_ClientInfo_ClientType_IOS_FIREBASE+1)) + +typedef enum _gdt_cct_QosTierConfiguration_QosTier { + gdt_cct_QosTierConfiguration_QosTier_DEFAULT = 0, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_ONLY = 1, + gdt_cct_QosTierConfiguration_QosTier_UNMETERED_OR_DAILY = 2, + gdt_cct_QosTierConfiguration_QosTier_FAST_IF_RADIO_AWAKE = 3, + gdt_cct_QosTierConfiguration_QosTier_NEVER = 4 +} gdt_cct_QosTierConfiguration_QosTier; +#define _gdt_cct_QosTierConfiguration_QosTier_MIN gdt_cct_QosTierConfiguration_QosTier_DEFAULT +#define _gdt_cct_QosTierConfiguration_QosTier_MAX gdt_cct_QosTierConfiguration_QosTier_NEVER +#define _gdt_cct_QosTierConfiguration_QosTier_ARRAYSIZE ((gdt_cct_QosTierConfiguration_QosTier)(gdt_cct_QosTierConfiguration_QosTier_NEVER+1)) + +/* Struct definitions */ +typedef struct _gdt_cct_BatchedLogRequest { + pb_size_t log_request_count; + struct _gdt_cct_LogRequest *log_request; +/* @@protoc_insertion_point(struct:gdt_cct_BatchedLogRequest) */ +} gdt_cct_BatchedLogRequest; + +typedef struct _gdt_cct_IosClientInfo { + pb_bytes_array_t *os_major_version; + pb_bytes_array_t *os_full_version; + pb_bytes_array_t *application_build; + pb_bytes_array_t *country; + pb_bytes_array_t *model; + pb_bytes_array_t *language_code; + pb_bytes_array_t *application_bundle_id; +/* @@protoc_insertion_point(struct:gdt_cct_IosClientInfo) */ +} gdt_cct_IosClientInfo; + +typedef struct _gdt_cct_ClientInfo { + bool has_client_type; + gdt_cct_ClientInfo_ClientType client_type; + bool has_ios_client_info; + gdt_cct_IosClientInfo ios_client_info; +/* @@protoc_insertion_point(struct:gdt_cct_ClientInfo) */ +} gdt_cct_ClientInfo; + +typedef struct _gdt_cct_NetworkConnectionInfo { + bool has_network_type; + gdt_cct_NetworkConnectionInfo_NetworkType network_type; + bool has_mobile_subtype; + gdt_cct_NetworkConnectionInfo_MobileSubtype mobile_subtype; +/* @@protoc_insertion_point(struct:gdt_cct_NetworkConnectionInfo) */ +} gdt_cct_NetworkConnectionInfo; + +typedef struct _gdt_cct_QosTierConfiguration { + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; + bool has_log_source; + int32_t log_source; +/* @@protoc_insertion_point(struct:gdt_cct_QosTierConfiguration) */ +} gdt_cct_QosTierConfiguration; + +typedef struct _gdt_cct_QosTiersOverride { + pb_size_t qos_tier_configuration_count; + struct _gdt_cct_QosTierConfiguration *qos_tier_configuration; + bool has_qos_tier_fingerprint; + int64_t qos_tier_fingerprint; +/* @@protoc_insertion_point(struct:gdt_cct_QosTiersOverride) */ +} gdt_cct_QosTiersOverride; + +typedef struct _gdt_cct_LogEvent { + bool has_event_time_ms; + int64_t event_time_ms; + pb_bytes_array_t *source_extension; + bool has_event_code; + int32_t event_code; + bool has_timezone_offset_seconds; + int64_t timezone_offset_seconds; + bool has_event_uptime_ms; + int64_t event_uptime_ms; + bool has_network_connection_info; + gdt_cct_NetworkConnectionInfo network_connection_info; +/* @@protoc_insertion_point(struct:gdt_cct_LogEvent) */ +} gdt_cct_LogEvent; + +typedef struct _gdt_cct_LogRequest { + bool has_client_info; + gdt_cct_ClientInfo client_info; + bool has_log_source; + int32_t log_source; + pb_size_t log_event_count; + struct _gdt_cct_LogEvent *log_event; + bool has_request_time_ms; + int64_t request_time_ms; + bool has_request_uptime_ms; + int64_t request_uptime_ms; + bool has_qos_tier; + gdt_cct_QosTierConfiguration_QosTier qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogRequest) */ +} gdt_cct_LogRequest; + +typedef struct _gdt_cct_LogResponse { + bool has_next_request_wait_millis; + int64_t next_request_wait_millis; + bool has_qos_tier; + gdt_cct_QosTiersOverride qos_tier; +/* @@protoc_insertion_point(struct:gdt_cct_LogResponse) */ +} gdt_cct_LogResponse; + +/* Default values for struct fields */ +extern const gdt_cct_NetworkConnectionInfo_NetworkType gdt_cct_NetworkConnectionInfo_network_type_default; +extern const gdt_cct_NetworkConnectionInfo_MobileSubtype gdt_cct_NetworkConnectionInfo_mobile_subtype_default; +extern const gdt_cct_QosTierConfiguration_QosTier gdt_cct_LogRequest_qos_tier_default; +extern const int32_t gdt_cct_QosTierConfiguration_log_source_default; + +/* Initializer values for message structs */ +#define gdt_cct_LogEvent_init_default {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_default} +#define gdt_cct_NetworkConnectionInfo_init_default {false, gdt_cct_NetworkConnectionInfo_NetworkType_NONE, false, gdt_cct_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE} +#define gdt_cct_IosClientInfo_init_default {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_default {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_default} +#define gdt_cct_BatchedLogRequest_init_default {0, NULL} +#define gdt_cct_LogRequest_init_default {false, gdt_cct_ClientInfo_init_default, false, 0, 0, NULL, false, 0, false, 0, false, gdt_cct_QosTierConfiguration_QosTier_DEFAULT} +#define gdt_cct_QosTierConfiguration_init_default {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_default {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_default {false, 0, false, gdt_cct_QosTiersOverride_init_default} +#define gdt_cct_LogEvent_init_zero {false, 0, NULL, false, 0, false, 0, false, 0, false, gdt_cct_NetworkConnectionInfo_init_zero} +#define gdt_cct_NetworkConnectionInfo_init_zero {false, _gdt_cct_NetworkConnectionInfo_NetworkType_MIN, false, _gdt_cct_NetworkConnectionInfo_MobileSubtype_MIN} +#define gdt_cct_IosClientInfo_init_zero {NULL, NULL, NULL, NULL, NULL, NULL, NULL} +#define gdt_cct_ClientInfo_init_zero {false, _gdt_cct_ClientInfo_ClientType_MIN, false, gdt_cct_IosClientInfo_init_zero} +#define gdt_cct_BatchedLogRequest_init_zero {0, NULL} +#define gdt_cct_LogRequest_init_zero {false, gdt_cct_ClientInfo_init_zero, false, 0, 0, NULL, false, 0, false, 0, false, _gdt_cct_QosTierConfiguration_QosTier_MIN} +#define gdt_cct_QosTierConfiguration_init_zero {false, _gdt_cct_QosTierConfiguration_QosTier_MIN, false, 0} +#define gdt_cct_QosTiersOverride_init_zero {0, NULL, false, 0} +#define gdt_cct_LogResponse_init_zero {false, 0, false, gdt_cct_QosTiersOverride_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define gdt_cct_BatchedLogRequest_log_request_tag 1 +#define gdt_cct_IosClientInfo_os_major_version_tag 3 +#define gdt_cct_IosClientInfo_os_full_version_tag 4 +#define gdt_cct_IosClientInfo_application_build_tag 5 +#define gdt_cct_IosClientInfo_country_tag 6 +#define gdt_cct_IosClientInfo_model_tag 7 +#define gdt_cct_IosClientInfo_language_code_tag 8 +#define gdt_cct_IosClientInfo_application_bundle_id_tag 11 +#define gdt_cct_ClientInfo_client_type_tag 1 +#define gdt_cct_ClientInfo_ios_client_info_tag 4 +#define gdt_cct_NetworkConnectionInfo_network_type_tag 1 +#define gdt_cct_NetworkConnectionInfo_mobile_subtype_tag 2 +#define gdt_cct_QosTierConfiguration_qos_tier_tag 2 +#define gdt_cct_QosTierConfiguration_log_source_tag 3 +#define gdt_cct_QosTiersOverride_qos_tier_configuration_tag 1 +#define gdt_cct_QosTiersOverride_qos_tier_fingerprint_tag 2 +#define gdt_cct_LogEvent_event_time_ms_tag 1 +#define gdt_cct_LogEvent_event_code_tag 11 +#define gdt_cct_LogEvent_event_uptime_ms_tag 17 +#define gdt_cct_LogEvent_source_extension_tag 6 +#define gdt_cct_LogEvent_timezone_offset_seconds_tag 15 +#define gdt_cct_LogEvent_network_connection_info_tag 23 +#define gdt_cct_LogRequest_request_time_ms_tag 4 +#define gdt_cct_LogRequest_request_uptime_ms_tag 8 +#define gdt_cct_LogRequest_client_info_tag 1 +#define gdt_cct_LogRequest_log_source_tag 2 +#define gdt_cct_LogRequest_log_event_tag 3 +#define gdt_cct_LogRequest_qos_tier_tag 9 +#define gdt_cct_LogResponse_next_request_wait_millis_tag 1 +#define gdt_cct_LogResponse_qos_tier_tag 3 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t gdt_cct_LogEvent_fields[7]; +extern const pb_field_t gdt_cct_NetworkConnectionInfo_fields[3]; +extern const pb_field_t gdt_cct_IosClientInfo_fields[8]; +extern const pb_field_t gdt_cct_ClientInfo_fields[3]; +extern const pb_field_t gdt_cct_BatchedLogRequest_fields[2]; +extern const pb_field_t gdt_cct_LogRequest_fields[7]; +extern const pb_field_t gdt_cct_QosTierConfiguration_fields[3]; +extern const pb_field_t gdt_cct_QosTiersOverride_fields[3]; +extern const pb_field_t gdt_cct_LogResponse_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* gdt_cct_LogEvent_size depends on runtime parameters */ +#define gdt_cct_NetworkConnectionInfo_size 13 +/* gdt_cct_IosClientInfo_size depends on runtime parameters */ +/* gdt_cct_ClientInfo_size depends on runtime parameters */ +/* gdt_cct_BatchedLogRequest_size depends on runtime parameters */ +/* gdt_cct_LogRequest_size depends on runtime parameters */ +#define gdt_cct_QosTierConfiguration_size 13 +/* gdt_cct_QosTiersOverride_size depends on runtime parameters */ +/* gdt_cct_LogResponse_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CCT_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/LICENSE b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/README.md b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/README.md new file mode 100644 index 0000000..8c6e952 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleDataTransportCCTSupport/README.md @@ -0,0 +1,267 @@ +# Firebase iOS Open Source Development + [![Actions Status][gh-core-badge]][gh-actions] + [![Actions Status][gh-dynamiclinks-badge]][gh-actions] + [![Actions Status][gh-datatransport-badge]][gh-actions] + [![Actions Status][gh-storage-badge]][gh-actions] + [![Actions Status][gh-zip-badge]][gh-actions] + [![Travis](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m new file mode 100644 index 0000000..173a776 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m @@ -0,0 +1,1038 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import +#import +#import +#import +#import "GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h" +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +#import + +// Implementations need to be typed before calling the implementation directly to cast the +// arguments and the return types correctly. Otherwise, it will crash the app. +typedef BOOL (*GULRealOpenURLSourceApplicationAnnotationIMP)( + id, SEL, GULApplication *, NSURL *, NSString *, id); + +typedef BOOL (*GULRealOpenURLOptionsIMP)( + id, SEL, GULApplication *, NSURL *, NSDictionary *); + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (*GULRealHandleEventsForBackgroundURLSessionIMP)( + id, SEL, GULApplication *, NSString *, void (^)()); +#pragma clang diagnostic pop + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef BOOL (*GULRealContinueUserActivityIMP)( + id, SEL, GULApplication *, NSUserActivity *, void (^)(NSArray *restorableObjects)); +#pragma clang diagnostic pop + +typedef void (*GULRealDidRegisterForRemoteNotificationsIMP)(id, SEL, GULApplication *, NSData *); + +typedef void (*GULRealDidFailToRegisterForRemoteNotificationsIMP)(id, + SEL, + GULApplication *, + NSError *); + +typedef void (*GULRealDidReceiveRemoteNotificationIMP)(id, SEL, GULApplication *, NSDictionary *); + +// TODO: Since we don't support iOS 7 anymore, see if we can remove the check below. +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +typedef void (*GULRealDidReceiveRemoteNotificationWithCompletionIMP)( + id, SEL, GULApplication *, NSDictionary *, void (^)(UIBackgroundFetchResult)); +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +typedef void (^GULAppDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; + +static NSString *const kGULAppDelegateKeyPath = @"delegate"; + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/AppDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseAppDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the App Delegate. */ +static NSString *const kGULAppDelegatePrefix = @"GUL_"; + +/** The original instance of App Delegate. */ +static id gOriginalAppDelegate; + +/** The original App Delegate class */ +static Class gOriginalAppDelegateClass; + +/** The subclass of the original App Delegate. */ +static Class gAppDelegateSubclass; + +/** Remote notification methods selectors + * + * We have to opt out of referencing APNS related App Delegate methods directly to prevent + * an Apple review warning email about missing Push Notification Entitlement + * (like here: https://github.com/firebase/firebase-ios-sdk/issues/2807). From our experience, the + * warning is triggered when any of the symbols is present in the application sent to review, even + * if the code is never executed. Because GULAppDelegateSwizzler may be used by applications that + * are not using APNS we have to refer to the methods indirectly using selector constructed from + * string. + * + * NOTE: None of the methods is proxied unless it is explicitly requested by calling the method + * +[GULAppDelegateSwizzler proxyOriginalDelegateIncludingAPNSMethods] + */ +static NSString *const kGULDidRegisterForRemoteNotificationsSEL = + @"application:didRegisterForRemoteNotificationsWithDeviceToken:"; +static NSString *const kGULDidFailToRegisterForRemoteNotificationsSEL = + @"application:didFailToRegisterForRemoteNotificationsWithError:"; +static NSString *const kGULDidReceiveRemoteNotificationSEL = + @"application:didReceiveRemoteNotification:"; +static NSString *const kGULDidReceiveRemoteNotificationWithCompletionSEL = + @"application:didReceiveRemoteNotification:fetchCompletionHandler:"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULZeroingWeakContainer +@end + +@interface GULAppDelegateObserver : NSObject +@end + +@implementation GULAppDelegateObserver { + BOOL _isObserving; +} + ++ (GULAppDelegateObserver *)sharedInstance { + static GULAppDelegateObserver *instance; + static dispatch_once_t once; + dispatch_once(&once, ^{ + instance = [[GULAppDelegateObserver alloc] init]; + }); + return instance; +} + +- (void)observeUIApplication { + if (_isObserving) { + return; + } + [[GULAppDelegateSwizzler sharedApplication] + addObserver:self + forKeyPath:kGULAppDelegateKeyPath + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld + context:nil]; + _isObserving = YES; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + if ([keyPath isEqual:kGULAppDelegateKeyPath]) { + id newValue = change[NSKeyValueChangeNewKey]; + id oldValue = change[NSKeyValueChangeOldKey]; + if ([newValue isEqual:oldValue]) { + return; + } + // Free the stored app delegate instance because it has been changed to a different instance to + // avoid keeping it alive forever. + if ([oldValue isEqual:gOriginalAppDelegate]) { + gOriginalAppDelegate = nil; + // Remove the observer. Parse it to NSObject to avoid warning. + [[GULAppDelegateSwizzler sharedApplication] removeObserver:self + forKeyPath:kGULAppDelegateKeyPath]; + _isObserving = NO; + } + } +} + +@end + +@implementation GULAppDelegateSwizzler + +static dispatch_once_t sProxyAppDelegateOnceToken; +static dispatch_once_t sProxyAppDelegateRemoteNotificationOnceToken; + +#pragma mark - Public methods + ++ (BOOL)isAppDelegateProxyEnabled { + NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; + + id isFirebaseProxyEnabledPlistValue = infoDictionary[kGULFirebaseAppDelegateProxyEnabledPlistKey]; + id isGoogleProxyEnabledPlistValue = + infoDictionary[kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey]; + + // Enabled by default. + BOOL isFirebaseAppDelegateProxyEnabled = YES; + BOOL isGoogleUtilitiesAppDelegateProxyEnabled = YES; + + if ([isFirebaseProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isFirebaseAppDelegateProxyEnabled = [isFirebaseProxyEnabledPlistValue boolValue]; + } + + if ([isGoogleProxyEnabledPlistValue isKindOfClass:[NSNumber class]]) { + isGoogleUtilitiesAppDelegateProxyEnabled = [isGoogleProxyEnabledPlistValue boolValue]; + } + + // Only deactivate the proxy if it is explicitly disabled by app developers using either one of + // the plist flags. + return isFirebaseAppDelegateProxyEnabled && isGoogleUtilitiesAppDelegateProxyEnabled; +} + ++ (GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor { + NSAssert(interceptor, @"AppDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(GULApplicationDelegate)], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling000], + @"AppDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling001], + @"AppDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = [NSString stringWithFormat:@"%@%p", kGULAppDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling002], + @"AppDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULZeroingWeakContainer *weakObject = [[GULZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULAppDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"AppDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"AppDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling003], + @"AppDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULZeroingWeakContainer *weakContainer = [GULAppDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling004], + @"AppDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + ++ (void)proxyOriginalDelegate { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + dispatch_once(&sProxyAppDelegateOnceToken, ^{ + id originalDelegate = + [GULAppDelegateSwizzler sharedApplication].delegate; + [GULAppDelegateSwizzler proxyAppDelegate:originalDelegate]; + }); +} + ++ (void)proxyOriginalDelegateIncludingAPNSMethods { + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + [self proxyOriginalDelegate]; + + dispatch_once(&sProxyAppDelegateRemoteNotificationOnceToken, ^{ + id appDelegate = [GULAppDelegateSwizzler sharedApplication].delegate; + + NSMutableDictionary *realImplementationsBySelector = + [objc_getAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey) mutableCopy]; + + [self proxyRemoteNotificationsMethodsWithAppDelegateSubClass:gAppDelegateSubclass + realClass:gOriginalAppDelegateClass + appDelegate:appDelegate + realImplementationsBySelector:realImplementationsBySelector]; + + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN); + [self reassignAppDelegate]; + }); +} + +#pragma mark - Create proxy + ++ (GULApplication *)sharedApplication { + if ([GULAppEnvironmentUtil isAppExtension]) { + return nil; + } + id sharedApplication = nil; + Class uiApplicationClass = NSClassFromString(kGULApplicationClassName); + if (uiApplicationClass && + [uiApplicationClass respondsToSelector:(NSSelectorFromString(@"sharedApplication"))]) { + sharedApplication = [uiApplicationClass sharedApplication]; + } + return sharedApplication; +} + +#pragma mark - Override default methods + +/** Creates a new subclass of the class of the given object and sets the isa value of the given + * object to the new subclass. Additionally this copies methods to that new subclass that allow us + * to intercept UIApplicationDelegate methods. This is better known as isa swizzling. + * + * @param appDelegate The object to which you want to isa swizzle. This has to conform to the + * UIApplicationDelegate subclass. + * @return Returns the new subclass. + */ ++ (nullable Class)createSubclassWithObject:(id)appDelegate { + Class realClass = [appDelegate class]; + + // Create GUL__ + NSString *classNameWithPrefix = + [kGULAppDelegatePrefix stringByAppendingString:NSStringFromClass(realClass)]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling005], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: %@", + NSStringFromClass(realClass), newClassName); + return nil; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class appDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (appDelegateSubClass == Nil) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling006], + @"Cannot create a proxy for App Delegate. Subclass already exists. Original Class: " + @"%@, subclass: Nil", + NSStringFromClass(realClass)); + return nil; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For application:continueUserActivity:restorationHandler: + SEL continueUserActivitySEL = @selector(application:continueUserActivity:restorationHandler:); + [self proxyDestinationSelector:continueUserActivitySEL + implementationsFromSourceSelector:continueUserActivitySEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + +#if TARGET_OS_IOS || TARGET_OS_TV + // Add the following methods from GULAppDelegate class, and store the real implementation so it + // can forward to the real one. + // For application:openURL:options: + SEL applicationOpenURLOptionsSEL = @selector(application:openURL:options:); + if ([appDelegate respondsToSelector:applicationOpenURLOptionsSEL]) { + // Only add the application:openURL:options: method if the original AppDelegate implements it. + // This fixes a bug if an app only implements application:openURL:sourceApplication:annotation: + // (if we add the `options` method, iOS sees that one exists and does not call the + // `sourceApplication` method, which in this case is the only one the app implements). + + [self proxyDestinationSelector:applicationOpenURLOptionsSEL + implementationsFromSourceSelector:applicationOpenURLOptionsSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + + // For application:handleEventsForBackgroundURLSession:completionHandler: + SEL handleEventsForBackgroundURLSessionSEL = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + [self proxyDestinationSelector:handleEventsForBackgroundURLSessionSEL + implementationsFromSourceSelector:handleEventsForBackgroundURLSessionSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + // For application:openURL:sourceApplication:annotation: + SEL openURLSourceApplicationAnnotationSEL = @selector(application: + openURL:sourceApplication:annotation:); + + [self proxyDestinationSelector:openURLSourceApplicationAnnotationSEL + implementationsFromSourceSelector:openURLSourceApplicationAnnotationSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; +#endif // TARGET_OS_IOS + + // Override the description too so the custom class name will not show up. + [GULAppDelegateSwizzler addInstanceMethodWithDestinationSelector:@selector(description) + withImplementationFromSourceSelector:@selector(fakeDescription) + fromClass:[self class] + toClass:appDelegateSubClass]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(appDelegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(appDelegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(appDelegateSubClass)) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling007], + @"Cannot create subclass of App Delegate, because the created subclass is not the " + @"same size. %@", + NSStringFromClass(realClass)); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return nil; + } + + // Make the newly created class to be the subclass of the real App Delegate class. + objc_registerClassPair(appDelegateSubClass); + if (object_setClass(appDelegate, appDelegateSubClass)) { + GULLogDebug(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling008], + @"Successfully created App Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULAppDelegateSwizzler correctAppDelegateProxyKey]); + } + + return appDelegateSubClass; +} + ++ (void)proxyRemoteNotificationsMethodsWithAppDelegateSubClass:(Class)appDelegateSubClass + realClass:(Class)realClass + appDelegate:(id)appDelegate + realImplementationsBySelector: + (NSMutableDictionary *)realImplementationsBySelector { + if (realClass == nil || appDelegateSubClass == nil || appDelegate == nil || + realImplementationsBySelector == nil) { + // The App Delegate has not been swizzled. + return; + } + + // For application:didRegisterForRemoteNotificationsWithDeviceToken: + SEL didRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + SEL didRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didRegisterForRemoteNotificationsWithDeviceToken:); + + [self proxyDestinationSelector:didRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didFailToRegisterForRemoteNotificationsWithError: + SEL didFailToRegisterForRemoteNotificationsSEL = + NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + SEL didFailToRegisterForRemoteNotificationsDonorSEL = @selector(application: + donor_didFailToRegisterForRemoteNotificationsWithError:); + + [self proxyDestinationSelector:didFailToRegisterForRemoteNotificationsSEL + implementationsFromSourceSelector:didFailToRegisterForRemoteNotificationsDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification: + SEL didReceiveRemoteNotificationSEL = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + SEL didReceiveRemoteNotificationDonotSEL = @selector(application: + donor_didReceiveRemoteNotification:); + + [self proxyDestinationSelector:didReceiveRemoteNotificationSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationDonotSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // For application:didReceiveRemoteNotification:fetchCompletionHandler: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + if ([GULAppEnvironmentUtil isIOS7OrHigher]) { + SEL didReceiveRemoteNotificationWithCompletionSEL = + NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + SEL didReceiveRemoteNotificationWithCompletionDonorSEL = + @selector(application:donor_didReceiveRemoteNotification:fetchCompletionHandler:); + if ([appDelegate respondsToSelector:didReceiveRemoteNotificationWithCompletionSEL]) { + // Only add the application:didReceiveRemoteNotification:fetchCompletionHandler: method if + // the original AppDelegate implements it. + // This fixes a bug if an app only implements application:didReceiveRemoteNotification: + // (if we add the method with completion, iOS sees that one exists and does not call + // the method without the completion, which in this case is the only one the app implements). + + [self proxyDestinationSelector:didReceiveRemoteNotificationWithCompletionSEL + implementationsFromSourceSelector:didReceiveRemoteNotificationWithCompletionDonorSEL + fromClass:[GULAppDelegateSwizzler class] + toClass:appDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + } + } +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +} + +/// We have to do this to invalidate the cache that caches the original respondsToSelector of +/// openURL handlers. Without this, it won't call the default implementations because the system +/// checks and caches them. +/// Register KVO only once. Otherwise, the observing method will be called as many times as +/// being registered. ++ (void)reassignAppDelegate { +#if !TARGET_OS_WATCH + id delegate = [self sharedApplication].delegate; + [self sharedApplication].delegate = nil; + [self sharedApplication].delegate = delegate; + gOriginalAppDelegate = delegate; + [[GULAppDelegateObserver sharedInstance] observeUIApplication]; +#endif +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULAppDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULAppDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULAppDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULAppDelegateInterceptorCallback)callback { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULAppDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeAppDelegateSwizzling010], + @"AppDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULAppDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + +// The methods below are donor methods which are added to the dynamic subclass of the App Delegate. +// They are called within the scope of the real App Delegate so |self| does not refer to the +// GULAppDelegateSwizzler instance but the real App Delegate instance. + +#pragma mark - [Donor Methods] Overridden instance description method + +- (NSString *)fakeDescription { + Class realClass = objc_getAssociatedObject(self, &kGULRealClassKey); + return [NSString stringWithFormat:@"<%@: %p>", realClass, self]; +} + +#pragma mark - [Donor Methods] URL overridden handler methods +#if TARGET_OS_IOS || TARGET_OS_TV + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options { + SEL methodSelector = @selector(application:openURL:options:); + // Call the real implementation if the real App Delegate has any. + NSValue *openURLIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLOptionsIMP openURLOptionsIMP = [openURLIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + +// This is needed to for the library to be warning free on iOS versions < 9. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + openURL:url + options:options]; + }]; +#pragma clang diagnostic pop + if (openURLOptionsIMP) { + returnedValue |= openURLOptionsIMP(self, methodSelector, application, url, options); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#if TARGET_OS_IOS + +- (BOOL)application:(GULApplication *)application + openURL:(NSURL *)url + sourceApplication:(NSString *)sourceApplication + annotation:(id)annotation { + SEL methodSelector = @selector(application:openURL:sourceApplication:annotation:); + + // Call the real implementation if the real App Delegate has any. + NSValue *openURLSourceAppAnnotationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealOpenURLSourceApplicationAnnotationIMP openURLSourceApplicationAnnotationIMP = + [openURLSourceAppAnnotationIMPPointer pointerValue]; + + __block BOOL returnedValue = NO; + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + returnedValue |= [interceptor application:application + openURL:url + sourceApplication:sourceApplication + annotation:annotation]; +#pragma clang diagnostic pop + }]; + if (openURLSourceApplicationAnnotationIMP) { + returnedValue |= openURLSourceApplicationAnnotationIMP(self, methodSelector, application, url, + sourceApplication, annotation); + } + return returnedValue; +} + +#endif // TARGET_OS_IOS + +#pragma mark - [Donor Methods] Network overridden handler methods + +#if TARGET_OS_IOS || TARGET_OS_TV + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +- (void)application:(GULApplication *)application + handleEventsForBackgroundURLSession:(NSString *)identifier + completionHandler:(void (^)())completionHandler API_AVAILABLE(ios(7.0)) { +#pragma clang diagnostic pop + SEL methodSelector = @selector(application: + handleEventsForBackgroundURLSession:completionHandler:); + NSValue *handleBackgroundSessionPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealHandleEventsForBackgroundURLSessionIMP handleBackgroundSessionIMP = + [handleBackgroundSessionPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + [interceptor application:application + handleEventsForBackgroundURLSession:identifier + completionHandler:completionHandler]; + }]; + // Call the real implementation if the real App Delegate has any. + if (handleBackgroundSessionIMP) { + handleBackgroundSessionIMP(self, methodSelector, application, identifier, completionHandler); + } +} + +#endif // TARGET_OS_IOS || TARGET_OS_TV + +#pragma mark - [Donor Methods] User Activities overridden handler methods + +// This is needed to for the library to be warning free on iOS versions < 8. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (BOOL)application:(GULApplication *)application + continueUserActivity:(NSUserActivity *)userActivity + restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { + SEL methodSelector = @selector(application:continueUserActivity:restorationHandler:); + NSValue *continueUserActivityIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealContinueUserActivityIMP continueUserActivityIMP = + continueUserActivityIMPPointer.pointerValue; + + __block BOOL returnedValue = NO; +#if !TARGET_OS_WATCH + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + returnedValue |= [interceptor application:application + continueUserActivity:userActivity + restorationHandler:restorationHandler]; + }]; +#endif + // Call the real implementation if the real App Delegate has any. + if (continueUserActivityIMP) { + returnedValue |= continueUserActivityIMP(self, methodSelector, application, userActivity, + restorationHandler); + } + return returnedValue; +} +#pragma clang diagnostic pop + +#pragma mark - [Donor Methods] Remote Notifications + +- (void)application:(GULApplication *)application + donor_didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + SEL methodSelector = NSSelectorFromString(kGULDidRegisterForRemoteNotificationsSEL); + + NSValue *didRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidRegisterForRemoteNotificationsIMP didRegisterForRemoteNotificationsIMP = + [didRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&deviceToken) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didRegisterForRemoteNotificationsIMP) { + didRegisterForRemoteNotificationsIMP(self, methodSelector, application, deviceToken); + } +} + +- (void)application:(GULApplication *)application + donor_didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { + SEL methodSelector = NSSelectorFromString(kGULDidFailToRegisterForRemoteNotificationsSEL); + NSValue *didFailToRegisterForRemoteNotificationsIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidFailToRegisterForRemoteNotificationsIMP didFailToRegisterForRemoteNotificationsIMP = + [didFailToRegisterForRemoteNotificationsIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&error) atIndex:3]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didFailToRegisterForRemoteNotificationsIMP) { + didFailToRegisterForRemoteNotificationsIMP(self, methodSelector, application, error); + } +} + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo + fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationWithCompletionSEL); + NSValue *didReceiveRemoteNotificationWithCompletionIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationWithCompletionIMP + didReceiveRemoteNotificationWithCompletionIMP = + [didReceiveRemoteNotificationWithCompletionIMPPointer pointerValue]; + + // Notify interceptors. + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation setArgument:(void *)(&completionHandler) atIndex:4]; + [invocation invoke]; + }]; + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationWithCompletionIMP) { + didReceiveRemoteNotificationWithCompletionIMP(self, methodSelector, application, userInfo, + completionHandler); + } +} +#pragma clang diagnostic pop +#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 && !TARGET_OS_WATCH + +- (void)application:(GULApplication *)application + donor_didReceiveRemoteNotification:(NSDictionary *)userInfo { + SEL methodSelector = NSSelectorFromString(kGULDidReceiveRemoteNotificationSEL); + NSValue *didReceiveRemoteNotificationIMPPointer = + [GULAppDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULRealDidReceiveRemoteNotificationIMP didReceiveRemoteNotificationIMP = + [didReceiveRemoteNotificationIMPPointer pointerValue]; + + // Notify interceptors. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [GULAppDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + NSInvocation *invocation = [GULAppDelegateSwizzler + appDelegateInvocationForSelector:methodSelector]; + [invocation setTarget:interceptor]; + [invocation setSelector:methodSelector]; + [invocation setArgument:(void *)(&application) atIndex:2]; + [invocation setArgument:(void *)(&userInfo) atIndex:3]; + [invocation invoke]; + }]; +#pragma clang diagnostic pop + // Call the real implementation if the real App Delegate has any. + if (didReceiveRemoteNotificationIMP) { + didReceiveRemoteNotificationIMP(self, methodSelector, application, userInfo); + } +} + ++ (nullable NSInvocation *)appDelegateInvocationForSelector:(SEL)selector { + struct objc_method_description methodDescription = + protocol_getMethodDescription(@protocol(GULApplicationDelegate), selector, NO, YES); + if (methodDescription.types == NULL) { + return nil; + } + + NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSInvocation invocationWithMethodSignature:signature]; +} + ++ (void)proxyAppDelegate:(id)appDelegate { + if (![appDelegate conformsToProtocol:@protocol(GULApplicationDelegate)]) { + GULLogNotice( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate], + @"App Delegate does not conform to UIApplicationDelegate protocol. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + id originalDelegate = appDelegate; + // Do not create a subclass if it is not enabled. + if (![GULAppDelegateSwizzler isAppDelegateProxyEnabled]) { + GULLogNotice(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling011], + @"App Delegate Proxy is disabled. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + // Do not accept nil delegate. + if (!originalDelegate) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling012], + @"Cannot create App Delegate Proxy because App Delegate instance is nil. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } + + @try { + gOriginalAppDelegateClass = [originalDelegate class]; + gAppDelegateSubclass = [self createSubclassWithObject:originalDelegate]; + [self reassignAppDelegate]; + } @catch (NSException *exception) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeAppDelegateSwizzling013], + @"Cannot create App Delegate Proxy. %@", + [GULAppDelegateSwizzler correctAlternativeWhenAppDelegateProxyNotCreated]); + return; + } +} + +#pragma mark - Methods to print correct debug logs + ++ (NSString *)correctAppDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseAppDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesAppDelegateProxyEnabledPlistKey; +} + ++ (NSString *)correctAlternativeWhenAppDelegateProxyNotCreated { + return NSClassFromString(@"FIRCore") + ? @"To log deep link campaigns manually, call the methods in " + @"FIRAnalytics+AppDelegate.h." + : @""; +} + +#pragma mark - Private Methods for Testing + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (void)resetProxyOriginalDelegateOnceToken { + sProxyAppDelegateOnceToken = 0; + sProxyAppDelegateRemoteNotificationOnceToken = 0; +} + ++ (id)originalDelegate { + return gOriginalAppDelegate; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h new file mode 100644 index 0000000..d7ebd86 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h @@ -0,0 +1,55 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +@class GULApplication; + +NS_ASSUME_NONNULL_BEGIN + +@interface GULAppDelegateSwizzler () + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param appDelegate The object that needs to be isa swizzled. This should conform to the + * application delegate protocol. + */ ++ (void)proxyAppDelegate:(id)appDelegate; + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** Resets the token that prevents the app delegate proxy from being isa swizzled multiple times. */ ++ (void)resetProxyOriginalDelegateOnceToken; + +/** Returns the original app delegate that was proxied. + * + * @return The original app delegate instance that was proxied. + */ ++ (id)originalDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h new file mode 100644 index 0000000..c1b2d6e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULAppDelegateInterceptorID; + +/** This class contains methods that isa swizzle the app delegate. */ +@interface GULAppDelegateSwizzler : NSProxy + +/** Registers an app delegate interceptor whose methods will be invoked as they're invoked on the + * original app delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULAppDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULAppDelegateInterceptorID)registerAppDelegateInterceptor: + (id)interceptor; + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterAppDelegateInterceptorWithID:(GULAppDelegateInterceptorID)interceptorID; + +/** This method ensures that the original app delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the app delegate once). + * + * This method doesn't proxy APNS related methods: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * To proxy these methods use +[GULAppDelegateSwizzler + * proxyOriginalDelegateIncludingAPNSMethods]. The methods have to be proxied separately to + * avoid potential warnings from Apple review about missing Push Notification Entitlement (e.g. + * https://github.com/firebase/firebase-ios-sdk/issues/2807) + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegateIncludingAPNSMethods + */ ++ (void)proxyOriginalDelegate; + +/** This method ensures that the original app delegate has been proxied including APNS related + * methods. Call this before registering your interceptor. This method is safe to call multiple + * times (but it only proxies the app delegate once) or + * after +[GULAppDelegateSwizzler proxyOriginalDelegate] + * + * This method calls +[GULAppDelegateSwizzler proxyOriginalDelegate] under the hood. + * After calling this method the following App Delegate methods will be proxied in addition to + * the methods proxied by proxyOriginalDelegate: + * @code + * - application:didRegisterForRemoteNotificationsWithDeviceToken: + * - application:didFailToRegisterForRemoteNotificationsWithError: + * - application:didReceiveRemoteNotification:fetchCompletionHandler: + * - application:didReceiveRemoteNotification: + * @endcode + * + * The method has no effect for extensions. + * + * @see proxyOriginalDelegate + */ ++ (void)proxyOriginalDelegateIncludingAPNSMethods; + +/** Indicates whether app delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if AppDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isAppDelegateProxyEnabled; + +/** Returns the current sharedApplication. + * + * @return the current application instance if in an app, or nil if in extension or if it doesn't + * exist. + */ ++ (nullable GULApplication *)sharedApplication; + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +NS_ASSUME_NONNULL_END + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h new file mode 100644 index 0000000..8067212 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#if TARGET_OS_IOS || TARGET_OS_TV + +#import + +#define GULApplication UIApplication +#define GULApplicationDelegate UIApplicationDelegate +#define GULUserActivityRestoring UIUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"UIApplication"; + +#elif TARGET_OS_OSX + +#import + +#define GULApplication NSApplication +#define GULApplicationDelegate NSApplicationDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"NSApplication"; + +#elif TARGET_OS_WATCH + +#import + +// We match the according watchOS API but swizzling should not work in watch +#define GULApplication WKExtension +#define GULApplicationDelegate WKExtensionDelegate +#define GULUserActivityRestoring NSUserActivityRestoring + +static NSString *const kGULApplicationClassName = @"WKExtension"; + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h new file mode 100644 index 0000000..053ce84 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Common/GULLoggerCodes.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +typedef NS_ENUM(NSInteger, GULSwizzlerMessageCode) { + // App Delegate Swizzling. + kGULSwizzlerMessageCodeAppDelegateSwizzling000 = 1000, // I-SWZ001000 + kGULSwizzlerMessageCodeAppDelegateSwizzling001 = 1001, // I-SWZ001001 + kGULSwizzlerMessageCodeAppDelegateSwizzling002 = 1002, // I-SWZ001002 + kGULSwizzlerMessageCodeAppDelegateSwizzling003 = 1003, // I-SWZ001003 + kGULSwizzlerMessageCodeAppDelegateSwizzling004 = 1004, // I-SWZ001004 + kGULSwizzlerMessageCodeAppDelegateSwizzling005 = 1005, // I-SWZ001005 + kGULSwizzlerMessageCodeAppDelegateSwizzling006 = 1006, // I-SWZ001006 + kGULSwizzlerMessageCodeAppDelegateSwizzling007 = 1007, // I-SWZ001007 + kGULSwizzlerMessageCodeAppDelegateSwizzling008 = 1008, // I-SWZ001008 + kGULSwizzlerMessageCodeAppDelegateSwizzling009 = 1009, // I-SWZ001009 + kGULSwizzlerMessageCodeAppDelegateSwizzling010 = 1010, // I-SWZ001010 + kGULSwizzlerMessageCodeAppDelegateSwizzling011 = 1011, // I-SWZ001011 + kGULSwizzlerMessageCodeAppDelegateSwizzling012 = 1012, // I-SWZ001012 + kGULSwizzlerMessageCodeAppDelegateSwizzling013 = 1013, // I-SWZ001013 + kGULSwizzlerMessageCodeAppDelegateSwizzlingInvalidAppDelegate = 1014, // I-SWZ001014 + + // Scene Delegate Swizzling. + kGULSwizzlerMessageCodeSceneDelegateSwizzling000 = 1100, // I-SWZ001100 + kGULSwizzlerMessageCodeSceneDelegateSwizzling001 = 1101, // I-SWZ001101 + kGULSwizzlerMessageCodeSceneDelegateSwizzling002 = 1102, // I-SWZ001102 + kGULSwizzlerMessageCodeSceneDelegateSwizzling003 = 1103, // I-SWZ001103 + kGULSwizzlerMessageCodeSceneDelegateSwizzling004 = 1104, // I-SWZ001104 + kGULSwizzlerMessageCodeSceneDelegateSwizzling005 = 1105, // I-SWZ001105 + kGULSwizzlerMessageCodeSceneDelegateSwizzling006 = 1106, // I-SWZ001106 + kGULSwizzlerMessageCodeSceneDelegateSwizzling007 = 1107, // I-SWZ001107 + kGULSwizzlerMessageCodeSceneDelegateSwizzling008 = 1108, // I-SWZ001108 + kGULSwizzlerMessageCodeSceneDelegateSwizzling009 = 1109, // I-SWZ001109 + kGULSwizzlerMessageCodeSceneDelegateSwizzling010 = 1110, // I-SWZ001110 + kGULSwizzlerMessageCodeSceneDelegateSwizzling011 = 1111, // I-SWZ001111 + kGULSwizzlerMessageCodeSceneDelegateSwizzling012 = 1112, // I-SWZ001112 + kGULSwizzlerMessageCodeSceneDelegateSwizzling013 = 1113, // I-SWZ001113 + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate = 1114, // I-SWZ001114 + + // Method Swizzling. + kGULSwizzlerMessageCodeMethodSwizzling000 = 2000, // I-SWZ002000 +}; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m new file mode 100644 index 0000000..483c859 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULHeartbeatDateStorage.m @@ -0,0 +1,140 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +@interface GULHeartbeatDateStorage () +/** The storage to store the date of the last sent heartbeat. */ +@property(nonatomic, readonly) NSFileCoordinator *fileCoordinator; +@end + +@implementation GULHeartbeatDateStorage + +- (instancetype)initWithFileName:(NSString *)fileName { + if (fileName == nil) { + return nil; + } + + self = [super init]; + if (self) { + _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil]; + NSURL *directoryURL = [[self class] directoryPathURL]; + [[self class] checkAndCreateDirectory:directoryURL fileCoordinator:_fileCoordinator]; + _fileURL = [directoryURL URLByAppendingPathComponent:fileName]; + } + return self; +} + +/** Returns the URL path of the Application Support folder. + * @return the URL path of Application Support. + */ ++ (NSURL *)directoryPathURL { + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSArray *components = @[ paths.lastObject, @"Google/FIRApp" ]; + NSString *directoryString = [NSString pathWithComponents:components]; + NSURL *directoryURL = [NSURL fileURLWithPath:directoryString]; + return directoryURL; +} + +/** Checks and creates a directory for the directory specified by the + * directory url + * @param directoryPathURL The path to the directory which needs to be created. + * @param fileCoordinator The fileCoordinator object to coordinate writes to the directory. + */ ++ (void)checkAndCreateDirectory:(NSURL *)directoryPathURL + fileCoordinator:(NSFileCoordinator *)fileCoordinator { + NSError *fileCoordinatorError = nil; + [fileCoordinator + coordinateWritingItemAtURL:directoryPathURL + options:0 + error:&fileCoordinatorError + byAccessor:^(NSURL *writingDirectoryURL) { + NSError *error; + if (![writingDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + // If fail creating the Application Support directory, log warning. + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtURL:writingDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&error]; + } + }]; +} + +- (nullable NSMutableDictionary *)heartbeatDictionaryWithFileURL:(NSURL *)readingFileURL { + NSError *error; + NSMutableDictionary *dict; + NSData *objectData = [NSData dataWithContentsOfURL:readingFileURL options:0 error:&error]; + if (objectData == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } else { + dict = [GULSecureCoding + unarchivedObjectOfClasses:[NSSet setWithArray:@[ NSDictionary.class, NSDate.class ]] + fromData:objectData + error:&error]; + if (dict == nil || error != nil) { + dict = [NSMutableDictionary dictionary]; + } + } + return dict; +} + +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag { + __block NSMutableDictionary *dict; + NSError *error; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL) { + dict = [self heartbeatDictionaryWithFileURL:readingURL]; + }]; + return dict[tag]; +} + +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag { + NSError *error; + __block BOOL isSuccess = false; + [self.fileCoordinator coordinateReadingItemAtURL:self.fileURL + options:0 + writingItemAtURL:self.fileURL + options:0 + error:&error + byAccessor:^(NSURL *readingURL, NSURL *writingURL) { + NSMutableDictionary *dictionary = + [self heartbeatDictionaryWithFileURL:readingURL]; + dictionary[tag] = date; + NSError *error; + isSuccess = [self writeDictionary:dictionary + forWritingURL:writingURL + error:&error]; + }]; + return isSuccess; +} + +- (BOOL)writeDictionary:(NSMutableDictionary *)dictionary + forWritingURL:(NSURL *)writingFileURL + error:(NSError **)outError { + NSData *data = [GULSecureCoding archivedDataWithRootObject:dictionary error:outError]; + if (*outError != nil) { + return false; + } else { + return [data writeToURL:writingFileURL atomically:YES]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m new file mode 100644 index 0000000..ebfb808 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/GULSecureCoding.m @@ -0,0 +1,103 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/Public/GULSecureCoding.h" + +NSString *const kGULSecureCodingError = @"GULSecureCodingError"; + +@implementation GULSecureCoding + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError { + id object; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + object = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:data error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; +#pragma clang diagnostic pop + unarchiver.requiresSecureCoding = YES; + + object = [unarchiver decodeObjectOfClasses:classes forKey:NSKeyedArchiveRootObjectKey]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + + if (object == nil && outError && *outError == nil) { + NSString *failureReason = @"NSKeyedUnarchiver failed to unarchive data."; + *outError = [NSError errorWithDomain:kGULSecureCodingError + code:-1 + userInfo:@{NSLocalizedFailureReasonErrorKey : failureReason}]; + } + } + + return object; +} + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError { + return [self unarchivedObjectOfClasses:[NSSet setWithObject:class] fromData:data error:outError]; +} + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError { + NSData *archiveData; +#if __has_builtin(__builtin_available) + if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) { + archiveData = [NSKeyedArchiver archivedDataWithRootObject:object + requiringSecureCoding:YES + error:outError]; + } else +#endif // __has_builtin(__builtin_available) + { + @try { + NSMutableData *data = [NSMutableData data]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; +#pragma clang diagnostic pop + archiver.requiresSecureCoding = YES; + + [archiver encodeObject:object forKey:NSKeyedArchiveRootObjectKey]; + [archiver finishEncoding]; + + archiveData = [data copy]; + } @catch (NSException *exception) { + if (outError) { + *outError = [self archivingErrorWithException:exception]; + } + } + } + + return archiveData; +} + ++ (NSError *)archivingErrorWithException:(NSException *)exception { + NSString *failureReason = [NSString + stringWithFormat:@"NSKeyedArchiver exception with name: %@, reason: %@, userInfo: %@", + exception.name, exception.reason, exception.userInfo]; + NSDictionary *errorUserInfo = @{NSLocalizedFailureReasonErrorKey : failureReason}; + + return [NSError errorWithDomain:kGULSecureCodingError code:-1 userInfo:errorUserInfo]; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h new file mode 100644 index 0000000..9432dfc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// Stores either a date or a dictionary to a specified file. +@interface GULHeartbeatDateStorage : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, readonly) NSURL *fileURL; + +/** + * Default initializer. + * @param fileName The name of the file to store the date information. + * exist, it will be created if needed. + */ +- (instancetype)initWithFileName:(NSString *)fileName; + +/** + * Reads the date from the specified file for the given tag. + * @return Returns date if exists, otherwise `nil`. + */ +- (nullable NSDate *)heartbeatDateForTag:(NSString *)tag; + +/** + * Saves the date for the specified tag in the specified file. + * @return YES on success, NO otherwise. + */ +- (BOOL)setHearbeatDate:(NSDate *)date forTag:(NSString *)tag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h new file mode 100644 index 0000000..8484b39 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/Public/GULSecureCoding.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** The class wraps `NSKeyedArchiver` and `NSKeyedUnarchiver` API to provide a unified secure coding + * methods for iOS versions before and after 11. + */ +@interface GULSecureCoding : NSObject + ++ (nullable id)unarchivedObjectOfClasses:(NSSet *)classes + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable id)unarchivedObjectOfClass:(Class)class + fromData:(NSData *)data + error:(NSError **)outError; + ++ (nullable NSData *)archivedDataWithRootObject:(id)object error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h new file mode 100644 index 0000000..d550264 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +@interface GULAppEnvironmentUtil : NSObject + +/// Indicates whether the app is from Apple Store or not. Returns NO if the app is on simulator, +/// development environment or sideloaded. ++ (BOOL)isFromAppStore; + +/// Indicates whether the app is a Testflight app. Returns YES if the app has sandbox receipt. +/// Returns NO otherwise. ++ (BOOL)isAppStoreReceiptSandbox; + +/// Indicates whether the app is on simulator or not at runtime depending on the device +/// architecture. ++ (BOOL)isSimulator; + +/// The current device model. Returns an empty string if device model cannot be retrieved. ++ (NSString *)deviceModel; + +/// The current operating system version. Returns an empty string if the system version cannot be +/// retrieved. ++ (NSString *)systemVersion; + +/// Indicates whether it is running inside an extension or an app. ++ (BOOL)isAppExtension; + +/// @return Returns @YES when is run on iOS version greater or equal to 7.0 ++ (BOOL)isIOS7OrHigher; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m new file mode 100644 index 0000000..6442941 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m @@ -0,0 +1,263 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h" + +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import +#endif + +/// The encryption info struct and constants are missing from the iPhoneSimulator SDK, but not from +/// the iPhoneOS or Mac OS X SDKs. Since one doesn't ever ship a Simulator binary, we'll just +/// provide the definitions here. +#if TARGET_OS_SIMULATOR && !defined(LC_ENCRYPTION_INFO) +#define LC_ENCRYPTION_INFO 0x21 +struct encryption_info_command { + uint32_t cmd; + uint32_t cmdsize; + uint32_t cryptoff; + uint32_t cryptsize; + uint32_t cryptid; +}; +#endif + +@implementation GULAppEnvironmentUtil + +/// A key for the Info.plist to enable or disable checking if the App Store is running in a sandbox. +/// This will affect your data integrity when using Firebase Analytics, as it will disable some +/// necessary checks. +static NSString *const kFIRAppStoreReceiptURLCheckEnabledKey = + @"FirebaseAppStoreReceiptURLCheckEnabled"; + +/// The file name of the sandbox receipt. This is available on iOS >= 8.0 +static NSString *const kFIRAIdentitySandboxReceiptFileName = @"sandboxReceipt"; + +/// The following copyright from Landon J. Fuller applies to the isAppEncrypted function. +/// +/// Copyright (c) 2017 Landon J. Fuller +/// All rights reserved. +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software +/// and associated documentation files (the "Software"), to deal in the Software without +/// restriction, including without limitation the rights to use, copy, modify, merge, publish, +/// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +/// Software is furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in all copies or +/// substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +/// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +/// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +/// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +/// +/// Comment from iPhone Dev Wiki +/// Crack Prevention: +/// App Store binaries are signed by both their developer and Apple. This encrypts the binary so +/// that decryption keys are needed in order to make the binary readable. When iOS executes the +/// binary, the decryption keys are used to decrypt the binary into a readable state where it is +/// then loaded into memory and executed. iOS can tell the encryption status of a binary via the +/// cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is a non-zero +/// value then the binary is encrypted. +/// +/// 'Cracking' works by letting the kernel decrypt the binary then siphoning the decrypted data into +/// a new binary file, resigning, and repackaging. This will only work on jailbroken devices as +/// codesignature validation has been removed. Resigning takes place because while the codesignature +/// doesn't have to be valid thanks to the jailbreak, it does have to be in place unless you have +/// AppSync or similar to disable codesignature checks. +/// +/// More information at Landon Fuller's blog +static BOOL IsAppEncrypted() { + const struct mach_header *executableHeader = NULL; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + const struct mach_header *header = _dyld_get_image_header(i); + if (header && header->filetype == MH_EXECUTE) { + executableHeader = header; + break; + } + } + + if (!executableHeader) { + return NO; + } + + BOOL is64bit = (executableHeader->magic == MH_MAGIC_64); + uintptr_t cursor = (uintptr_t)executableHeader + + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header)); + const struct segment_command *segmentCommand = NULL; + uint32_t i = 0; + + while (i++ < executableHeader->ncmds) { + segmentCommand = (struct segment_command *)cursor; + + if (!segmentCommand) { + continue; + } + + if ((!is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO) || + (is64bit && segmentCommand->cmd == LC_ENCRYPTION_INFO_64)) { + if (is64bit) { + struct encryption_info_command_64 *cryptCmd = + (struct encryption_info_command_64 *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } else { + struct encryption_info_command *cryptCmd = (struct encryption_info_command *)segmentCommand; + return cryptCmd && cryptCmd->cryptid != 0; + } + } + cursor += segmentCommand->cmdsize; + } + + return NO; +} + +static BOOL HasSCInfoFolder() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + NSString *bundlePath = [NSBundle mainBundle].bundlePath; + NSString *scInfoPath = [bundlePath stringByAppendingPathComponent:@"SC_Info"]; + return [[NSFileManager defaultManager] fileExistsAtPath:scInfoPath]; +#elif TARGET_OS_OSX + return NO; +#endif +} + +static BOOL HasEmbeddedMobileProvision() { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"].length > 0; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isFromAppStore { + static dispatch_once_t isEncryptedOnce; + static BOOL isEncrypted = NO; + + dispatch_once(&isEncryptedOnce, ^{ + isEncrypted = IsAppEncrypted(); + }); + + if ([GULAppEnvironmentUtil isSimulator]) { + return NO; + } + + // If an app contain the sandboxReceipt file, it means its coming from TestFlight + // This must be checked before the SCInfo Folder check below since TestFlight apps may + // also have an SCInfo folder. + if ([GULAppEnvironmentUtil isAppStoreReceiptSandbox]) { + return NO; + } + + if (HasSCInfoFolder()) { + // When iTunes downloads a .ipa, it also gets a customized .sinf file which is added to the + // main SC_Info directory. + return YES; + } + + // For iOS >= 8.0, iTunesMetadata.plist is moved outside of the sandbox. Any attempt to read + // the iTunesMetadata.plist outside of the sandbox will be rejected by Apple. + // If the app does not contain the embedded.mobileprovision which is stripped out by Apple when + // the app is submitted to store, then it is highly likely that it is from Apple Store. + return isEncrypted && !HasEmbeddedMobileProvision(); +} + ++ (BOOL)isAppStoreReceiptSandbox { + // Since checking the App Store's receipt URL can be memory intensive, check the option in the + // Info.plist if developers opted out of this check. + id enableSandboxCheck = + [[NSBundle mainBundle] objectForInfoDictionaryKey:kFIRAppStoreReceiptURLCheckEnabledKey]; + if (enableSandboxCheck && [enableSandboxCheck isKindOfClass:[NSNumber class]] && + ![enableSandboxCheck boolValue]) { + return NO; + } +// The #else is for pre Xcode 9 where @available is not yet implemented. +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + NSURL *appStoreReceiptURL = [NSBundle mainBundle].appStoreReceiptURL; + NSString *appStoreReceiptFileName = appStoreReceiptURL.lastPathComponent; + return [appStoreReceiptFileName isEqualToString:kFIRAIdentitySandboxReceiptFileName]; + } + return NO; +} + ++ (BOOL)isSimulator { +#if TARGET_OS_IOS || TARGET_OS_TV + NSString *platform = [GULAppEnvironmentUtil deviceModel]; + return [platform isEqual:@"x86_64"] || [platform isEqual:@"i386"]; +#elif TARGET_OS_OSX + return NO; +#endif + return NO; +} + ++ (NSString *)deviceModel { + static dispatch_once_t once; + static NSString *deviceModel; + + dispatch_once(&once, ^{ + struct utsname systemInfo; + if (uname(&systemInfo) == 0) { + deviceModel = [NSString stringWithUTF8String:systemInfo.machine]; + } + }); + return deviceModel; +} + ++ (NSString *)systemVersion { +#if TARGET_OS_IOS + return [UIDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX || TARGET_OS_TV || TARGET_OS_WATCH + // Assemble the systemVersion, excluding the patch version if it's 0. + NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; + NSMutableString *versionString = [[NSMutableString alloc] + initWithFormat:@"%ld.%ld", (long)osVersion.majorVersion, (long)osVersion.minorVersion]; + if (osVersion.patchVersion != 0) { + [versionString appendFormat:@".%ld", (long)osVersion.patchVersion]; + } + return versionString; +#endif +} + ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH + // Documented by Apple + BOOL appExtension = [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]; + return appExtension; +#elif TARGET_OS_OSX + return NO; +#endif +} + ++ (BOOL)isIOS7OrHigher { +#if __has_builtin(__builtin_available) + if (@available(iOS 7.0, *)) { +#else + if ([[UIDevice currentDevice].systemVersion integerValue] >= 7) { +#endif + return YES; + } + + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/LICENSE b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/LICENSE new file mode 100644 index 0000000..30a8f72 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/LICENSE @@ -0,0 +1,247 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m new file mode 100644 index 0000000..0a512da --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/GULLogger.m @@ -0,0 +1,214 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Logger/Private/GULLogger.h" + +#include + +#import +#import + +/// ASL client facility name used by GULLogger. +const char *kGULLoggerASLClientFacilityName = "com.google.utilities.logger"; + +static dispatch_once_t sGULLoggerOnceToken; + +static aslclient sGULLoggerClient; + +static dispatch_queue_t sGULClientQueue; + +static BOOL sGULLoggerDebugMode; + +static GULLoggerLevel sGULLoggerMaximumLevel; + +// Allow clients to register a version to include in the log. +static const char *sVersion = ""; + +static GULLoggerService kGULLoggerLogger = @"[GULLogger]"; + +#ifdef DEBUG +/// The regex pattern for the message code. +static NSString *const kMessageCodePattern = @"^I-[A-Z]{3}[0-9]{6}$"; +static NSRegularExpression *sMessageCodeRegex; +#endif + +void GULLoggerInitializeASL(void) { + dispatch_once(&sGULLoggerOnceToken, ^{ + NSInteger majorOSVersion = [[GULAppEnvironmentUtil systemVersion] integerValue]; + uint32_t aslOptions = ASL_OPT_STDERR; +#if TARGET_OS_SIMULATOR + // The iOS 11 simulator doesn't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 11) { + aslOptions = 0; + } +#else + // Devices running iOS 10 or higher don't need the ASL_OPT_STDERR flag. + if (majorOSVersion >= 10) { + aslOptions = 0; + } +#endif // TARGET_OS_SIMULATOR + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" // asl is deprecated + // Initialize the ASL client handle. + sGULLoggerClient = asl_open(NULL, kGULLoggerASLClientFacilityName, aslOptions); + sGULLoggerMaximumLevel = GULLoggerLevelNotice; + + // Set the filter used by system/device log. Initialize in default mode. + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(ASL_LEVEL_NOTICE)); + + sGULClientQueue = dispatch_queue_create("GULLoggingClientQueue", DISPATCH_QUEUE_SERIAL); + dispatch_set_target_queue(sGULClientQueue, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)); +#ifdef DEBUG + sMessageCodeRegex = [NSRegularExpression regularExpressionWithPattern:kMessageCodePattern + options:0 + error:NULL]; +#endif + }); +} + +void GULLoggerEnableSTDERR(void) { + asl_add_log_file(sGULLoggerClient, STDERR_FILENO); +} + +void GULLoggerForceDebug(void) { + // We should enable debug mode if we're not running from App Store. + if (![GULAppEnvironmentUtil isFromAppStore]) { + sGULLoggerDebugMode = YES; + GULSetLoggerLevel(GULLoggerLevelDebug); + } +} + +__attribute__((no_sanitize("thread"))) void GULSetLoggerLevel(GULLoggerLevel loggerLevel) { + if (loggerLevel < GULLoggerLevelMin || loggerLevel > GULLoggerLevelMax) { + GULLogError(kGULLoggerLogger, NO, @"I-COR000023", @"Invalid logger level, %ld", + (long)loggerLevel); + return; + } + GULLoggerInitializeASL(); + // We should not raise the logger level if we are running from App Store. + if (loggerLevel >= GULLoggerLevelNotice && [GULAppEnvironmentUtil isFromAppStore]) { + return; + } + + sGULLoggerMaximumLevel = loggerLevel; + dispatch_async(sGULClientQueue, ^{ + asl_set_filter(sGULLoggerClient, ASL_FILTER_MASK_UPTO(loggerLevel)); + }); +} + +/** + * Check if the level is high enough to be loggable. + */ +__attribute__((no_sanitize("thread"))) BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel) { + GULLoggerInitializeASL(); + if (sGULLoggerDebugMode) { + return YES; + } + return (BOOL)(loggerLevel <= sGULLoggerMaximumLevel); +} + +#ifdef DEBUG +void GULResetLogger() { + sGULLoggerOnceToken = 0; +} + +aslclient getGULLoggerClient() { + return sGULLoggerClient; +} + +dispatch_queue_t getGULClientQueue() { + return sGULClientQueue; +} + +BOOL getGULLoggerDebugMode() { + return sGULLoggerDebugMode; +} +#endif + +void GULLoggerRegisterVersion(const char *version) { + sVersion = version; +} + +void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, + va_list args_ptr) { + GULLoggerInitializeASL(); + if (!(level <= sGULLoggerMaximumLevel || sGULLoggerDebugMode || forceLog)) { + return; + } + +#ifdef DEBUG + NSCAssert(messageCode.length == 11, @"Incorrect message code length."); + NSRange messageCodeRange = NSMakeRange(0, messageCode.length); + NSUInteger numberOfMatches = [sMessageCodeRegex numberOfMatchesInString:messageCode + options:0 + range:messageCodeRange]; + NSCAssert(numberOfMatches == 1, @"Incorrect message code format."); +#endif + NSString *logMsg; + if (args_ptr == NULL) { + logMsg = message; + } else { + logMsg = [[NSString alloc] initWithFormat:message arguments:args_ptr]; + } + logMsg = [NSString stringWithFormat:@"%s - %@[%@] %@", sVersion, service, messageCode, logMsg]; + dispatch_async(sGULClientQueue, ^{ + asl_log(sGULLoggerClient, NULL, (int)level, "%s", logMsg.UTF8String); + }); +} +#pragma clang diagnostic pop + +/** + * Generates the logging functions using macros. + * + * Calling GULLogError({service}, @"I-XYZ000001", @"Configure %@ failed.", @"blah") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure blah failed. + * Calling GULLogDebug({service}, @"I-XYZ000001", @"Configure succeed.") shows: + * yyyy-mm-dd hh:mm:ss.SSS sender[PID] [{service}][I-XYZ000001] Configure succeed. + */ +#define GUL_LOGGING_FUNCTION(level) \ + void GULLog##level(GULLoggerService service, BOOL force, NSString *messageCode, \ + NSString *message, ...) { \ + va_list args_ptr; \ + va_start(args_ptr, message); \ + GULLogBasic(GULLoggerLevel##level, service, force, messageCode, message, args_ptr); \ + va_end(args_ptr); \ + } + +GUL_LOGGING_FUNCTION(Error) +GUL_LOGGING_FUNCTION(Warning) +GUL_LOGGING_FUNCTION(Notice) +GUL_LOGGING_FUNCTION(Info) +GUL_LOGGING_FUNCTION(Debug) + +#undef GUL_MAKE_LOGGER + +#pragma mark - GULLoggerWrapper + +@implementation GULLoggerWrapper + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args { + GULLogBasic(level, service, NO, messageCode, message, args); +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h new file mode 100644 index 0000000..ff42576 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Private/GULLogger.h @@ -0,0 +1,159 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * The services used in the logger. + */ +typedef NSString *const GULLoggerService; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initialize GULLogger. + */ +extern void GULLoggerInitializeASL(void); + +/** + * Override log level to Debug. + */ +void GULLoggerForceDebug(void); + +/** + * Turn on logging to STDERR. + */ +extern void GULLoggerEnableSTDERR(void); + +/** + * Changes the default logging level of GULLoggerLevelNotice to a user-specified level. + * The default level cannot be set above GULLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern void GULSetLoggerLevel(GULLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the GULLoggerLevel enum values). + */ +extern BOOL GULIsLoggableLevel(GULLoggerLevel loggerLevel); + +/** + * Register version to include in logs. + * (required) version + */ +extern void GULLoggerRegisterVersion(const char *version); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than GULLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void GULLogBasic(GULLoggerLevel level, + GULLoggerService service, + BOOL forceLog, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type GULLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * GULLogError(kGULLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void GULLogError(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogWarning(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogNotice(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogInfo(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); +extern void GULLogDebug(GULLoggerService service, + BOOL force, + NSString *messageCode, + NSString *message, + ...) NS_FORMAT_FUNCTION(4, 5); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface GULLoggerWrapper : NSObject + +/** + * Objective-C wrapper for GULLogBasic to allow weak linking to GULLogger + * (required) log level (one of the GULLoggerLevel enum values). + * (required) service name of type GULLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(GULLoggerLevel)level + withService:(GULLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h new file mode 100644 index 0000000..f0ee435 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Logger/Public/GULLoggerLevel.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/** + * The log levels used by internal logging. + */ +typedef NS_ENUM(NSInteger, GULLoggerLevel) { + /** Error level, matches ASL_LEVEL_ERR. */ + GULLoggerLevelError = 3, + /** Warning level, matches ASL_LEVEL_WARNING. */ + GULLoggerLevelWarning = 4, + /** Notice level, matches ASL_LEVEL_NOTICE. */ + GULLoggerLevelNotice = 5, + /** Info level, matches ASL_LEVEL_INFO. */ + GULLoggerLevelInfo = 6, + /** Debug level, matches ASL_LEVEL_DEBUG. */ + GULLoggerLevelDebug = 7, + /** Minimum log level. */ + GULLoggerLevelMin = GULLoggerLevelError, + /** Maximum log level. */ + GULLoggerLevelMax = GULLoggerLevelDebug +} NS_SWIFT_NAME(GoogleLoggerLevel); diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m new file mode 100644 index 0000000..27d48bb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/GULSwizzler.m @@ -0,0 +1,153 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h" + +#import + +#ifdef DEBUG +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/MethodSwizzler]"; +#endif + +dispatch_queue_t GetGULSwizzlingQueue(void) { + static dispatch_queue_t queue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.GULSwizzler", DISPATCH_QUEUE_SERIAL); + }); + return queue; +} + +@implementation GULSwizzler + ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block { + dispatch_sync(GetGULSwizzlingQueue(), ^{ + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + Class resolvedClass = aClass; + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + resolvedClass = object_getClass(aClass); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"You're attempting to swizzle a method that doesn't exist. (%@, %@)", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + IMP newImp = imp_implementationWithBlock(block); +#ifdef DEBUG + IMP currentImp = class_getMethodImplementation(resolvedClass, selector); + Class class = NSClassFromString(@"GULSwizzlingCache"); + if (class) { + SEL cacheSelector = NSSelectorFromString(@"cacheCurrentIMP:forNewIMP:forClass:withSelector:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:cacheSelector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:cacheSelector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv setArgument:&(newImp) atIndex:3]; + [inv setArgument:&(resolvedClass) atIndex:4]; + [inv setArgument:(void *_Nonnull) & (selector) atIndex:5]; + [inv invoke]; + } + } +#endif + + const char *typeEncoding = method_getTypeEncoding(method); + __unused IMP originalImpOfClass = + class_replaceMethod(resolvedClass, selector, newImp, typeEncoding); + +#ifdef DEBUG + // If !originalImpOfClass, then the IMP came from a superclass. + if (originalImpOfClass) { + SEL selector = NSSelectorFromString(@"originalIMPOfCurrentIMP:"); + NSMethodSignature *methodSignature = [class methodSignatureForSelector:selector]; + if (methodSignature != nil) { + NSInvocation *inv = [NSInvocation invocationWithMethodSignature:methodSignature]; + [inv setSelector:selector]; + [inv setTarget:class]; + [inv setArgument:&(currentImp) atIndex:2]; + [inv invoke]; + IMP testOriginal; + [inv getReturnValue:&testOriginal]; + if (originalImpOfClass != testOriginal) { + GULLogWarning(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeMethodSwizzling000], + @"Swizzling class: %@ SEL:%@ after it has been previously been swizzled.", + NSStringFromClass(resolvedClass), NSStringFromSelector(selector)); + } + } + } +#endif + }); +} + ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector { + NSAssert(selector, @"The selector cannot be NULL"); + NSAssert(aClass, @"The class cannot be Nil"); + if (selector == NULL || aClass == nil) { + return nil; + } + __block IMP currentIMP = nil; + dispatch_sync(GetGULSwizzlingQueue(), ^{ + Method method = nil; + if (isClassSelector) { + method = class_getClassMethod(aClass, selector); + } else { + method = class_getInstanceMethod(aClass, selector); + } + NSAssert(method, @"The Method for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + if (method == nil) { + return; + } + currentIMP = method_getImplementation(method); + NSAssert(currentIMP, @"The IMP for this class/selector combo doesn't exist (%@, %@).", + NSStringFromClass(aClass), NSStringFromSelector(selector)); + }); + return currentIMP; +} + ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector { + Method method = isClassSelector ? class_getClassMethod(aClass, selector) + : class_getInstanceMethod(aClass, selector); + return method != nil; +} + ++ (NSArray *)ivarObjectsForObject:(id)object { + NSMutableArray *array = [NSMutableArray array]; + unsigned int count; + Ivar *vars = class_copyIvarList([object class], &count); + for (NSUInteger i = 0; i < count; i++) { + const char *typeEncoding = ivar_getTypeEncoding(vars[i]); + // Check to see if the ivar is an object. + if (strncmp(typeEncoding, "@", 1) == 0) { + id ivarObject = object_getIvar(object, vars[i]); + [array addObject:ivarObject]; + } + } + free(vars); + return array; +} +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h new file mode 100644 index 0000000..a33262a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h @@ -0,0 +1,207 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * GULOriginalIMPConvenienceMacros.h + * + * This header contains convenience macros for invoking the original IMP of a swizzled method. + */ + +/** + * Invokes original IMP when the original selector takes no arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + */ +#define GUL_INVOKE_ORIGINAL_IMP0(__receivingObject, __swizzledSEL, __returnType, __originalIMP) \ + ((__returnType(*)(id, SEL))__originalIMP)(__receivingObject, __swizzledSEL) + +/** + * Invokes original IMP when the original selector takes 1 argument. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP1(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1)))__originalIMP)(__receivingObject, __swizzledSEL, \ + __arg1) + +/** + * Invokes original IMP when the original selector takes 2 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP2(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2) + +/** + * Invokes original IMP when the original selector takes 3 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP3(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), \ + __typeof__(__arg3)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3) + +/** + * Invokes original IMP when the original selector takes 4 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP4(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4)))__originalIMP)(__receivingObject, __swizzledSEL, __arg1, \ + __arg2, __arg3, __arg4) + +/** + * Invokes original IMP when the original selector takes 5 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP5(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5) + +/** + * Invokes original IMP when the original selector takes 6 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP6(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) + +/** + * Invokes original IMP when the original selector takes 7 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP7(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7) + +/** + * Invokes original IMP when the original selector takes 8 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP8(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8) + +/** + * Invokes original IMP when the original selector takes 9 arguments. + * + * @param __receivingObject The object on which the IMP is invoked. + * @param __swizzledSEL The selector used for swizzling. + * @param __returnType The return type of the original implementation. + * @param __originalIMP The original IMP. + * @param __arg1 The first argument. + * @param __arg2 The second argument. + * @param __arg3 The third argument. + * @param __arg4 The fourth argument. + * @param __arg5 The fifth argument. + * @param __arg6 The sixth argument. + * @param __arg7 The seventh argument. + * @param __arg8 The eighth argument. + * @param __arg9 The ninth argument. + */ +#define GUL_INVOKE_ORIGINAL_IMP9(__receivingObject, __swizzledSEL, __returnType, __originalIMP, \ + __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, \ + __arg9) \ + ((__returnType(*)(id, SEL, __typeof__(__arg1), __typeof__(__arg2), __typeof__(__arg3), \ + __typeof__(__arg4), __typeof__(__arg5), __typeof__(__arg6), \ + __typeof__(__arg7), __typeof__(__arg8), __typeof__(__arg9)))__originalIMP)( \ + __receivingObject, __swizzledSEL, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, \ + __arg8, __arg9) diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h new file mode 100644 index 0000000..26949c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** This class handles the runtime manipulation necessary to instrument selectors. It stores the + * classes and selectors that have been swizzled, and runs all operations on its own queue. + */ +@interface GULSwizzler : NSObject + +/** Manipulates the Objective-C runtime to replace the original IMP with the supplied block. + * + * @param aClass The class to swizzle. + * @param selector The selector of the class to swizzle. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @param block The block that replaces the original IMP. + */ ++ (void)swizzleClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector + withBlock:(nullable id)block; + +/** Returns the current IMP for the given class and selector. + * + * @param aClass The class to use. + * @param selector The selector to find the implementation of. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return The implementation of the selector in the runtime. + */ ++ (nullable IMP)currentImplementationForClass:(Class)aClass + selector:(SEL)selector + isClassSelector:(BOOL)isClassSelector; + +/** Checks the runtime to see if a selector exists on a class. If a property is declared as + * @dynamic, we have a reverse swizzling situation, where the implementation of a method exists + * only in concrete subclasses, and NOT in the superclass. We can detect that situation using + * this helper method. Similarly, we can detect situations where a class doesn't implement a + * protocol method. + * + * @param selector The selector to check for. + * @param aClass The class to check. + * @param isClassSelector A BOOL specifying whether the selector is a class or instance selector. + * @return YES if the method was found in this selector/class combination, NO otherwise. + */ ++ (BOOL)selector:(SEL)selector existsInClass:(Class)aClass isClassSelector:(BOOL)isClassSelector; + +/** Returns a list of all Objective-C (and not primitive) ivars contained by the given object. + * + * @param object The object whose ivars will be iterated. + * @return The list of ivar objects. + */ ++ (NSArray *)ivarObjectsForObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h new file mode 100644 index 0000000..36f94a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.h @@ -0,0 +1,49 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +/// This is a copy of Google Toolbox for Mac library to avoid creating an extra framework. + +// NOTE: For 64bit, none of these apis handle input sizes >32bits, they will return nil when given +// such data. To handle data of that size you really should be streaming it rather then doing it all +// in memory. + +@interface NSData (GULGzip) + +/// Returns an data as the result of decompressing the payload of |data|.The data to decompress must +/// be a gzipped payloads. ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error; + +/// Returns an compressed data with the result of gzipping the payload of |data|. Uses the default +/// compression level. ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error; + +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorDomain; +FOUNDATION_EXPORT NSString *const GULNSDataZlibErrorKey; // NSNumber +FOUNDATION_EXPORT NSString *const GULNSDataZlibRemainingBytesKey; // NSNumber + +typedef NS_ENUM(NSInteger, GULNSDataZlibError) { + GULNSDataZlibErrorGreaterThan32BitsToCompress = 1024, + // An internal zlib error. + // GULNSDataZlibErrorKey will contain the error value. + // NSLocalizedDescriptionKey may contain an error string from zlib. + // Look in zlib.h for list of errors. + GULNSDataZlibErrorInternal, + // There was left over data in the buffer that was not used. + // GULNSDataZlibRemainingBytesKey will contain number of remaining bytes. + GULNSDataZlibErrorDataRemaining +}; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m new file mode 100644 index 0000000..5a77bb8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/NSData+zlib/GULNSData+zlib.m @@ -0,0 +1,207 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/NSData+zlib/GULNSData+zlib.h" + +#import + +#define kChunkSize 1024 +#define Z_DEFAULT_COMPRESSION (-1) + +NSString *const GULNSDataZlibErrorDomain = @"com.google.GULNSDataZlibErrorDomain"; +NSString *const GULNSDataZlibErrorKey = @"GULNSDataZlibErrorKey"; +NSString *const GULNSDataZlibRemainingBytesKey = @"GULNSDataZlibRemainingBytesKey"; + +@implementation NSData (GULGzip) + ++ (NSData *)gul_dataByInflatingGzippedData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + int windowBits = 15; // 15 to enable any window size + windowBits += 32; // and +32 to enable zlib or gzip header detection. + + int retCode; + if ((retCode = inflateInit2(&strm, windowBits)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 4x the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length * 4)]; + unsigned char output[kChunkSize]; + + // Loop to collect the data. + do { + // Update what we're passing in. + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = inflate(&strm, Z_NO_FLUSH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSMutableDictionary *userInfo = + [NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + if (strm.msg) { + NSString *message = [NSString stringWithUTF8String:strm.msg]; + if (message) { + [userInfo setObject:message forKey:NSLocalizedDescriptionKey]; + } + } + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + inflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // Make sure there wasn't more data tacked onto the end of a valid compressed stream. + if (strm.avail_in != 0) { + if (error) { + NSDictionary *userInfo = + [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedInt:strm.avail_in] + forKey:GULNSDataZlibRemainingBytesKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorDataRemaining + userInfo:userInfo]; + } + result = nil; + } + // The only way out of the loop was by hitting the end of the stream. + NSAssert(retCode == Z_STREAM_END, + @"Thought we finished inflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + inflateEnd(&strm); + + return result; +} + ++ (NSData *)gul_dataByGzippingData:(NSData *)data error:(NSError **)error { + const void *bytes = [data bytes]; + NSUInteger length = [data length]; + + int level = Z_DEFAULT_COMPRESSION; + if (!bytes || !length) { + return nil; + } + +#if defined(__LP64__) && __LP64__ + // Don't support > 32bit length for 64 bit, see note in header. + if (length > UINT_MAX) { + if (error) { + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorGreaterThan32BitsToCompress + userInfo:nil]; + } + return nil; + } +#endif + + z_stream strm; + bzero(&strm, sizeof(z_stream)); + + int memLevel = 8; // Default. + int windowBits = 15 + 16; // Enable gzip header instead of zlib header. + + int retCode; + if ((retCode = deflateInit2(&strm, level, Z_DEFLATED, windowBits, memLevel, + Z_DEFAULT_STRATEGY)) != Z_OK) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + return nil; + } + + // Hint the size at 1/4 the input size. + NSMutableData *result = [NSMutableData dataWithCapacity:(length / 4)]; + unsigned char output[kChunkSize]; + + // Setup the input. + strm.avail_in = (unsigned int)length; + strm.next_in = (unsigned char *)bytes; + + // Collect the data. + do { + // update what we're passing in + strm.avail_out = kChunkSize; + strm.next_out = output; + retCode = deflate(&strm, Z_FINISH); + if ((retCode != Z_OK) && (retCode != Z_STREAM_END)) { + if (error) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:retCode] + forKey:GULNSDataZlibErrorKey]; + *error = [NSError errorWithDomain:GULNSDataZlibErrorDomain + code:GULNSDataZlibErrorInternal + userInfo:userInfo]; + } + deflateEnd(&strm); + return nil; + } + // Collect what we got. + unsigned gotBack = kChunkSize - strm.avail_out; + if (gotBack > 0) { + [result appendBytes:output length:gotBack]; + } + + } while (retCode == Z_OK); + + // If the loop exits, it used all input and the stream ended. + NSAssert(strm.avail_in == 0, + @"Should have finished deflating without using all input, %u bytes left", strm.avail_in); + NSAssert(retCode == Z_STREAM_END, + @"thought we finished deflate w/o getting a result of stream end, code %d", retCode); + + // Clean up. + deflateEnd(&strm); + + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m new file mode 100644 index 0000000..4389660 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULMutableDictionary.m @@ -0,0 +1,101 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" + +@implementation GULMutableDictionary { + /// The mutable dictionary. + NSMutableDictionary *_objects; + + /// Serial synchronization queue. All reads should use dispatch_sync, while writes use + /// dispatch_async. + dispatch_queue_t _queue; +} + +- (instancetype)init { + self = [super init]; + + if (self) { + _objects = [[NSMutableDictionary alloc] init]; + _queue = dispatch_queue_create("GULMutableDictionary", DISPATCH_QUEUE_SERIAL); + } + + return self; +} + +- (NSString *)description { + __block NSString *description; + dispatch_sync(_queue, ^{ + description = self->_objects.description; + }); + return description; +} + +- (id)objectForKey:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = [self->_objects objectForKey:key]; + }); + return object; +} + +- (void)setObject:(id)object forKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects setObject:object forKey:key]; + }); +} + +- (void)removeObjectForKey:(id)key { + dispatch_async(_queue, ^{ + [self->_objects removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_async(_queue, ^{ + [self->_objects removeAllObjects]; + }); +} + +- (NSUInteger)count { + __block NSUInteger count; + dispatch_sync(_queue, ^{ + count = self->_objects.count; + }); + return count; +} + +- (id)objectForKeyedSubscript:(id)key { + __block id object; + dispatch_sync(_queue, ^{ + object = self->_objects[key]; + }); + return object; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + dispatch_async(_queue, ^{ + self->_objects[key] = obj; + }); +} + +- (NSDictionary *)dictionary { + __block NSDictionary *dictionary; + dispatch_sync(_queue, ^{ + dictionary = [self->_objects copy]; + }); + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m new file mode 100644 index 0000000..9d78e0e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetwork.m @@ -0,0 +1,389 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetwork.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +#import +#import +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +/// Constant string for request header Content-Encoding. +static NSString *const kGULNetworkContentCompressionKey = @"Content-Encoding"; + +/// Constant string for request header Content-Encoding value. +static NSString *const kGULNetworkContentCompressionValue = @"gzip"; + +/// Constant string for request header Content-Length. +static NSString *const kGULNetworkContentLengthKey = @"Content-Length"; + +/// Constant string for request header Content-Type. +static NSString *const kGULNetworkContentTypeKey = @"Content-Type"; + +/// Constant string for request header Content-Type value. +static NSString *const kGULNetworkContentTypeValue = @"application/x-www-form-urlencoded"; + +/// Constant string for GET request method. +static NSString *const kGULNetworkGETRequestMethod = @"GET"; + +/// Constant string for POST request method. +static NSString *const kGULNetworkPOSTRequestMethod = @"POST"; + +/// Default constant string as a prefix for network logger. +static NSString *const kGULNetworkLogTag = @"Google/Utilities/Network"; + +@interface GULNetwork () +@end + +@implementation GULNetwork { + /// Network reachability. + GULReachabilityChecker *_reachability; + + /// The dictionary of requests by session IDs { NSString : id }. + GULMutableDictionary *_requests; +} + +- (instancetype)init { + return [self initWithReachabilityHost:kGULNetworkReachabilityHost]; +} + +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost { + self = [super init]; + if (self) { + // Setup reachability. + _reachability = [[GULReachabilityChecker alloc] initWithReachabilityDelegate:self + withHost:reachabilityHost]; + if (![_reachability start]) { + return nil; + } + + _requests = [[GULMutableDictionary alloc] init]; + _timeoutInterval = kGULNetworkTimeOutInterval; + } + return self; +} + +- (void)dealloc { + _reachability.reachabilityDelegate = nil; + [_reachability stop]; +} + +#pragma mark - External Methods + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler { + [GULNetworkURLSession handleEventsForBackgroundURLSessionID:sessionID + completionHandler:completionHandler]; +} + +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + NSError *compressError = nil; + NSData *compressedData = [NSData gul_dataByGzippingData:payload error:&compressError]; + if (!compressedData || compressError) { + if (compressError || payload.length > 0) { + // If the payload is not empty but it fails to compress the payload, something has been wrong. + [self handleErrorWithCode:GULErrorCodeNetworkPayloadCompression + queue:queue + withHandler:handler]; + return nil; + } + compressedData = [[NSData alloc] init]; + } + + NSString *postLength = @(compressedData.length).stringValue; + + // Set up the request with the compressed data. + [request setValue:postLength forHTTPHeaderField:kGULNetworkContentLengthKey]; + request.HTTPBody = compressedData; + request.HTTPMethod = kGULNetworkPOSTRequestMethod; + [request setValue:kGULNetworkContentTypeValue forHTTPHeaderField:kGULNetworkContentTypeKey]; + [request setValue:kGULNetworkContentCompressionValue + forHTTPHeaderField:kGULNetworkContentCompressionKey]; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncPOSTRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, + NSString *sessionID, NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork000 + message:@"Uploading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler { + if (!url.absoluteString.length) { + [self handleErrorWithCode:GULErrorCodeNetworkInvalidURL queue:queue withHandler:handler]; + return nil; + } + + NSTimeInterval timeOutInterval = _timeoutInterval ?: kGULNetworkTimeOutInterval; + NSMutableURLRequest *request = + [[NSMutableURLRequest alloc] initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeOutInterval]; + + if (!request) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + request.HTTPMethod = kGULNetworkGETRequestMethod; + request.allHTTPHeaderFields = headers; + + GULNetworkURLSession *fetcher = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:self]; + fetcher.backgroundNetworkEnabled = usingBackgroundSession; + + __weak GULNetwork *weakSelf = self; + NSString *requestID = [fetcher + sessionIDFromAsyncGETRequest:request + completionHandler:^(NSHTTPURLResponse *response, NSData *data, NSString *sessionID, + NSError *error) { + GULNetwork *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + if (sessionID.length) { + [strongSelf->_requests removeObjectForKey:sessionID]; + } + if (handler) { + handler(response, data, error); + } + }); + }]; + + if (!requestID) { + [self handleErrorWithCode:GULErrorCodeNetworkSessionTaskCreation + queue:queue + withHandler:handler]; + return nil; + } + + [self GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeNetwork001 + message:@"Downloading data. Host" + context:url]; + _requests[requestID] = fetcher; + return requestID; +} + +- (BOOL)hasUploadInProgress { + return _requests.count > 0; +} + +#pragma mark - Network Reachability + +/// Tells reachability delegate to call reachabilityDidChangeToStatus: to notify the network +/// reachability has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status { + _networkConnected = (status == kGULReachabilityViaCellular || status == kGULReachabilityViaWifi); + [_reachabilityDelegate reachabilityDidChange]; +} + +#pragma mark - Network logger delegate + +- (void)setLoggerDelegate:(id)loggerDelegate { + // Explicitly check whether the delegate responds to the methods because conformsToProtocol does + // not work correctly even though the delegate does respond to the methods. + if (!loggerDelegate || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:contexts:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:context:)] || + ![loggerDelegate respondsToSelector:@selector(GULNetwork_logWithLevel: + messageCode:message:)]) { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork002], + @"Cannot set the network logger delegate: delegate does not conform to the network " + "logger protocol."); + return; + } + _loggerDelegate = loggerDelegate; +} + +#pragma mark - Private methods + +/// Handles network error and calls completion handler with the error. +- (void)handleErrorWithCode:(NSInteger)code + queue:(dispatch_queue_t)queue + withHandler:(GULNetworkCompletionHandler)handler { + NSDictionary *userInfo = @{kGULNetworkErrorContext : @"Failed to create network request"}; + NSError *error = [[NSError alloc] initWithDomain:kGULNetworkErrorDomain + code:code + userInfo:userInfo]; + [self GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeNetwork002 + message:@"Failed to create network request. Code, error" + contexts:@[ @(code), error ]]; + if (handler) { + dispatch_queue_t queueToDispatch = queue ? queue : dispatch_get_main_queue(); + dispatch_async(queueToDispatch, ^{ + handler(nil, nil, error); + }); + } +} + +#pragma mark - Network logger + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts { + // Let the delegate log the message if there is a valid logger delegate. Otherwise, just log + // errors/warnings/info messages to the console log. + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + contexts:contexts]; + return; + } + if (_isDebugModeEnabled || logLevel == kGULNetworkLogLevelError || + logLevel == kGULNetworkLogLevelWarning || logLevel == kGULNetworkLogLevelInfo) { + NSString *formattedMessage = GULStringWithLogMessage(message, logLevel, contexts); + NSLog(@"%@", formattedMessage); + GULLogBasic((GULLoggerLevel)logLevel, kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)messageCode], formattedMessage, + NULL); + } +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel + messageCode:messageCode + message:message + context:context]; + return; + } + NSArray *contexts = context ? @[ context ] : @[]; + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:contexts]; +} + +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message { + if (_loggerDelegate) { + [_loggerDelegate GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message]; + return; + } + [self GULNetwork_logWithLevel:logLevel messageCode:messageCode message:message contexts:@[]]; +} + +/// Returns a string for the given log level (e.g. kGULNetworkLogLevelError -> @"ERROR"). +static NSString *GULLogLevelDescriptionFromLogLevel(GULNetworkLogLevel logLevel) { + static NSDictionary *levelNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + levelNames = @{ + @(kGULNetworkLogLevelError) : @"ERROR", + @(kGULNetworkLogLevelWarning) : @"WARNING", + @(kGULNetworkLogLevelInfo) : @"INFO", + @(kGULNetworkLogLevelDebug) : @"DEBUG" + }; + }); + return levelNames[@(logLevel)]; +} + +/// Returns a formatted string to be used for console logging. +static NSString *GULStringWithLogMessage(NSString *message, + GULNetworkLogLevel logLevel, + NSArray *contexts) { + if (!message) { + message = @"(Message was nil)"; + } else if (!message.length) { + message = @"(Message was empty)"; + } + NSMutableString *result = [[NSMutableString alloc] + initWithFormat:@"<%@/%@> %@", kGULNetworkLogTag, GULLogLevelDescriptionFromLogLevel(logLevel), + message]; + + if (!contexts.count) { + return result; + } + + NSMutableArray *formattedContexts = [[NSMutableArray alloc] init]; + for (id item in contexts) { + [formattedContexts addObject:(item != [NSNull null] ? item : @"(nil)")]; + } + + [result appendString:@": "]; + [result appendString:[formattedContexts componentsJoinedByString:@", "]]; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m new file mode 100644 index 0000000..dea8dbd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkConstants.m @@ -0,0 +1,40 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" + +#import + +NSString *const kGULNetworkBackgroundSessionConfigIDPrefix = @"com.gul.network.background-upload"; +NSString *const kGULNetworkApplicationSupportSubdirectory = @"GUL/Network"; +NSString *const kGULNetworkTempDirectoryName = @"GULNetworkTemporaryDirectory"; +const NSTimeInterval kGULNetworkTempFolderExpireTime = 60 * 60; // 1 hour +const NSTimeInterval kGULNetworkTimeOutInterval = 60; // 1 minute. +NSString *const kGULNetworkReachabilityHost = @"app-measurement.com"; +NSString *const kGULNetworkErrorContext = @"Context"; + +const int kGULNetworkHTTPStatusOK = 200; +const int kGULNetworkHTTPStatusNoContent = 204; +const int kGULNetworkHTTPStatusCodeMultipleChoices = 300; +const int kGULNetworkHTTPStatusCodeMovedPermanently = 301; +const int kGULNetworkHTTPStatusCodeFound = 302; +const int kGULNetworkHTTPStatusCodeNotModified = 304; +const int kGULNetworkHTTPStatusCodeMovedTemporarily = 307; +const int kGULNetworkHTTPStatusCodeNotFound = 404; +const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic = 429; +const int kGULNetworkHTTPStatusCodeUnavailable = 503; + +NSString *const kGULNetworkErrorDomain = @"com.gul.network.ErrorDomain"; + +GULLoggerService kGULLoggerNetwork = @"[GULNetwork]"; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m new file mode 100644 index 0000000..df8bf46 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/GULNetworkURLSession.m @@ -0,0 +1,762 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Network/Private/GULNetworkURLSession.h" + +#import +#import "GoogleUtilities/Network/Private/GULMutableDictionary.h" +#import "GoogleUtilities/Network/Private/GULNetworkConstants.h" +#import "GoogleUtilities/Network/Private/GULNetworkMessageCode.h" + +@interface GULNetworkURLSession () +@end + +@implementation GULNetworkURLSession { + /// The handler to be called when the request completes or error has occurs. + GULNetworkURLSessionCompletionHandler _completionHandler; + + /// Session ID generated randomly with a fixed prefix. + NSString *_sessionID; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + /// The session configuration. NSURLSessionConfiguration' is only available on iOS 7.0 or newer. + NSURLSessionConfiguration *_sessionConfig; + + /// The current NSURLSession. + NSURLSession *__weak _Nullable _URLSession; +#pragma clang diagnostic pop + + /// The path to the directory where all temporary files are stored before uploading. + NSURL *_networkDirectoryURL; + + /// The downloaded data from fetching. + NSData *_downloadedData; + + /// The path to the temporary file which stores the uploading data. + NSURL *_uploadingFileURL; + + /// The current request. + NSURLRequest *_request; +} + +#pragma mark - Init + +- (instancetype)initWithNetworkLoggerDelegate:(id)networkLoggerDelegate { + self = [super init]; + if (self) { + // Create URL to the directory where all temporary files to upload have to be stored. + NSArray *paths = + NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *applicationSupportDirectory = paths.firstObject; + NSArray *tempPathComponents = @[ + applicationSupportDirectory, kGULNetworkApplicationSupportSubdirectory, + kGULNetworkTempDirectoryName + ]; + _networkDirectoryURL = [NSURL fileURLWithPathComponents:tempPathComponents]; + _sessionID = [NSString stringWithFormat:@"%@-%@", kGULNetworkBackgroundSessionConfigIDPrefix, + [[NSUUID UUID] UUIDString]]; + _loggerDelegate = networkLoggerDelegate; + } + return self; +} + +#pragma mark - External Methods + +#pragma mark - To be called from AppDelegate + ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler: + (GULNetworkSystemCompletionHandler)systemCompletionHandler { + // The session may not be Analytics background. Ignore those that do not have the prefix. + if (![sessionID hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + return; + } + GULNetworkURLSession *fetcher = [self fetcherWithSessionIdentifier:sessionID]; + if (fetcher != nil) { + [fetcher addSystemCompletionHandler:systemCompletionHandler forSession:sessionID]; + } else { + GULLogError(kGULLoggerNetwork, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULNetworkMessageCodeNetwork003], + @"Failed to retrieve background session with ID %@ after app is relaunched.", + sessionID); + } +} + +#pragma mark - External Methods + +/// Sends an async POST request using NSURLSession for iOS >= 7.0, and returns an ID of the +/// connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + // NSURLSessionUploadTask does not work with NSData in the background. + // To avoid this issue, write the data to a temporary file to upload it. + // Make a temporary file with the data subset. + _uploadingFileURL = [self temporaryFilePathWithSessionID:_sessionID]; + NSError *writeError; + NSURLSessionUploadTask *postRequestTask; + NSURLSession *session; + BOOL didWriteFile = NO; + + // Clean up the entire temp folder to avoid temp files that remain in case the previous session + // crashed and did not clean up. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // If there is no background network enabled, no need to write to file. This will allow default + // network session which runs on the foreground. + if (_backgroundNetworkEnabled && [self ensureTemporaryDirectoryExists]) { + didWriteFile = [request.HTTPBody writeToFile:_uploadingFileURL.path + options:NSDataWritingAtomic + error:&writeError]; + + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession000 + message:@"Failed to write request data to file" + context:writeError]; + } + } + + if (didWriteFile) { + // Exclude this file from backing up to iTunes. There are conflicting reports that excluding + // directory from backing up does not exclude files of that directory from backing up. + [self excludeFromBackupForURL:_uploadingFileURL]; + + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromFile:_uploadingFileURL]; + } else { + // If we cannot write to file, just send it in the foreground. + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + [self populateSessionConfig:_sessionConfig withRequest:request]; + session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + postRequestTask = [session uploadTaskWithRequest:request fromData:request.HTTPBody]; + } + + if (!session || !postRequestTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + // Store completion handler because background session does not accept handler block but custom + // delegate. + _completionHandler = [handler copy]; + [postRequestTask resume]; + + return _sessionID; +} + +/// Sends an async GET request using NSURLSession for iOS >= 7.0, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler + API_AVAILABLE(ios(7.0)) { + if (_backgroundNetworkEnabled) { + _sessionConfig = [self backgroundSessionConfigWithSessionID:_sessionID]; + } else { + _sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + } + + [self populateSessionConfig:_sessionConfig withRequest:request]; + + // Do not cache the GET request. + _sessionConfig.URLCache = nil; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:_sessionConfig + delegate:self + delegateQueue:[NSOperationQueue mainQueue]]; + NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; + + if (!session || !downloadTask) { + NSError *error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkRequestCreation + userInfo:@{kGULNetworkErrorContext : @"Cannot create network session"}]; + [self callCompletionHandler:handler withResponse:nil data:nil error:error]; + return nil; + } + + _URLSession = session; + + // Save the session into memory. + [[self class] setSessionInFetcherMap:self forSessionID:_sessionID]; + + _request = [request copy]; + + _completionHandler = [handler copy]; + [downloadTask resume]; + + return _sessionID; +} + +#pragma mark - NSURLSessionDataDelegate + +/// Called by the NSURLSession when the data task has received some of the expected data. +/// Once the session is completed, URLSession:task:didCompleteWithError will be called and the +/// completion handler will be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + @synchronized(self) { + NSMutableData *mutableData = [[NSMutableData alloc] init]; + if (_downloadedData) { + mutableData = _downloadedData.mutableCopy; + } + [mutableData appendData:data]; + _downloadedData = mutableData; + } +} + +#pragma mark - NSURLSessionTaskDelegate + +/// Called by the NSURLSession once the download task is completed. The file is saved in the +/// provided URL so we need to read the data and store into _downloadedData. Once the session is +/// completed, URLSession:task:didCompleteWithError will be called and the completion handler will +/// be called with the downloaded data. +- (void)URLSession:(NSURLSession *)session + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:(NSURL *)url API_AVAILABLE(ios(7.0)) { + if (!url.path) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession001 + message:@"Unable to read downloaded data from empty temp path"]; + _downloadedData = nil; + return; + } + + NSError *error; + _downloadedData = [NSData dataWithContentsOfFile:url.path options:0 error:&error]; + + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession002 + message:@"Cannot read the content of downloaded data" + context:error]; + _downloadedData = nil; + } +} + +#if TARGET_OS_IOS || TARGET_OS_TV +- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session + API_AVAILABLE(ios(7.0)) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession003 + message:@"Background session finished" + context:session.configuration.identifier]; + [self callSystemCompletionHandler:session.configuration.identifier]; +} +#endif + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error API_AVAILABLE(ios(7.0)) { + // Avoid any chance of recursive behavior leading to it being used repeatedly. + GULNetworkURLSessionCompletionHandler handler = _completionHandler; + _completionHandler = nil; + + if (task.response) { + // The following assertion should always be true for HTTP requests, see https://goo.gl/gVLxT7. + NSAssert([task.response isKindOfClass:[NSHTTPURLResponse class]], @"URL response must be HTTP"); + + // The server responded so ignore the error created by the system. + error = nil; + } else if (!error) { + error = [[NSError alloc] + initWithDomain:kGULNetworkErrorDomain + code:GULErrorCodeNetworkInvalidResponse + userInfo:@{kGULNetworkErrorContext : @"Network Error: Empty network response"}]; + } + + [self callCompletionHandler:handler + withResponse:(NSHTTPURLResponse *)task.response + data:_downloadedData + error:error]; + + // Remove the temp file to avoid trashing devices with lots of temp files. + [self removeTempItemAtURL:_uploadingFileURL]; + + // Try to clean up stale files again. + [self maybeRemoveTempFilesAtURL:_networkDirectoryURL + expiringTime:kGULNetworkTempFolderExpireTime]; + + // This is called without checking the sessionID here since non-background sessions + // won't have an ID. + [session finishTasksAndInvalidate]; + + // Explicitly remove the session so it won't be reused. The weak map table should + // remove the session on deallocation, but dealloc may not happen immediately after + // calling `finishTasksAndInvalidate`. + NSString *sessionID = session.configuration.identifier; + [[self class] setSessionInFetcherMap:nil forSessionID:sessionID]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge + completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, + NSURLCredential *credential))completionHandler + API_AVAILABLE(ios(7.0)) { + // The handling is modeled after GTMSessionFetcher. + if ([challenge.protectionSpace.authenticationMethod + isEqualToString:NSURLAuthenticationMethodServerTrust]) { + SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; + if (serverTrust == NULL) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession004 + message:@"Received empty server trust for host. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); + return; + } + NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; + if (!credential) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession005 + message:@"Unable to verify server identity. Host" + context:_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession006 + message:@"Received SSL challenge for host. Host" + context:_request.URL]; + + void (^callback)(BOOL) = ^(BOOL allow) { + if (allow) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + } else { + [self->_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession007 + message:@"Cancelling authentication challenge for host. Host" + context:self->_request.URL]; + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + } + }; + + // Retain the trust object to avoid a SecTrustEvaluate() crash on iOS 7. + CFRetain(serverTrust); + + // Evaluate the certificate chain. + // + // The delegate queue may be the main thread. Trust evaluation could cause some + // blocking network activity, so we must evaluate async, as documented at + // https://developer.apple.com/library/ios/technotes/tn2232/ + dispatch_queue_t evaluateBackgroundQueue = + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_async(evaluateBackgroundQueue, ^{ + SecTrustResultType trustEval = kSecTrustResultInvalid; + BOOL shouldAllow; + OSStatus trustError; + + @synchronized([GULNetworkURLSession class]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + trustError = SecTrustEvaluate(serverTrust, &trustEval); +#pragma clang dianostic pop + } + + if (trustError != errSecSuccess) { + [self->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession008 + message:@"Cannot evaluate server trust. Error, host" + contexts:@[ @(trustError), self->_request.URL ]]; + shouldAllow = NO; + } else { + // Having a trust level "unspecified" by the user is the usual result, described at + // https://developer.apple.com/library/mac/qa/qa1360 + shouldAllow = + (trustEval == kSecTrustResultUnspecified || trustEval == kSecTrustResultProceed); + } + + // Call the call back with the permission. + callback(shouldAllow); + + CFRelease(serverTrust); + }); + return; + } + + // Default handling for other Auth Challenges. + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + +#pragma mark - Internal Methods + +/// Stores system completion handler with session ID as key. +- (void)addSystemCompletionHandler:(GULNetworkSystemCompletionHandler)handler + forSession:(NSString *)identifier { + if (!handler) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession009 + message:@"Cannot store nil system completion handler in network"]; + return; + } + + if (!identifier.length) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession010 + message:@"Cannot store system completion handler with empty network " + "session identifier"]; + return; + } + + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + if (systemCompletionHandlers[identifier]) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession011 + message:@"Got multiple system handlers for a single session ID" + context:identifier]; + } + + systemCompletionHandlers[identifier] = handler; +} + +/// Calls the system provided completion handler with the session ID stored in the dictionary. +/// The handler will be removed from the dictionary after being called. +- (void)callSystemCompletionHandler:(NSString *)identifier { + GULMutableDictionary *systemCompletionHandlers = + [[self class] sessionIDToSystemCompletionHandlerDictionary]; + GULNetworkSystemCompletionHandler handler = [systemCompletionHandlers objectForKey:identifier]; + + if (handler) { + [systemCompletionHandlers removeObjectForKey:identifier]; + + dispatch_async(dispatch_get_main_queue(), ^{ + handler(); + }); + } +} + +/// Sets or updates the session ID of this session. +- (void)setSessionID:(NSString *)sessionID { + _sessionID = [sessionID copy]; +} + +/// Creates a background session configuration with the session ID using the supported method. +- (NSURLSessionConfiguration *)backgroundSessionConfigWithSessionID:(NSString *)sessionID + API_AVAILABLE(ios(7.0)) { +#if (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_10) || \ + TARGET_OS_TV || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0) + + // iOS 8/10.10 builds require the new backgroundSessionConfiguration method name. + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; + +#elif (TARGET_OS_OSX && defined(MAC_OS_X_VERSION_10_10) && \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10) || \ + (TARGET_OS_IOS && defined(__IPHONE_8_0) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0) + + // Do a runtime check to avoid a deprecation warning about using + // +backgroundSessionConfiguration: on iOS 8. + if ([NSURLSessionConfiguration + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + // Running on iOS 8+/OS X 10.10+. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:sessionID]; +#pragma clang diagnostic pop + } else { + // Running on iOS 7/OS X 10.9. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; + } + +#else + // Building with an SDK earlier than iOS 8/OS X 10.10. + return [NSURLSessionConfiguration backgroundSessionConfiguration:sessionID]; +#endif +} + +- (void)maybeRemoveTempFilesAtURL:(NSURL *)folderURL expiringTime:(NSTimeInterval)staleTime { + if (!folderURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + NSArray *properties = @[ NSURLCreationDateKey ]; + NSArray *directoryContent = + [fileManager contentsOfDirectoryAtURL:folderURL + includingPropertiesForKeys:properties + options:NSDirectoryEnumerationSkipsSubdirectoryDescendants + error:&error]; + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelDebug + messageCode:kGULNetworkMessageCodeURLSession012 + message:@"Cannot get files from the temporary network folder. Error" + context:error]; + return; + } + + if (!directoryContent.count) { + return; + } + + NSTimeInterval now = [NSDate date].timeIntervalSince1970; + for (NSURL *tempFile in directoryContent) { + NSDate *creationDate; + BOOL getCreationDate = [tempFile getResourceValue:&creationDate + forKey:NSURLCreationDateKey + error:NULL]; + if (!getCreationDate) { + continue; + } + NSTimeInterval creationTimeInterval = creationDate.timeIntervalSince1970; + if (fabs(now - creationTimeInterval) > staleTime) { + [self removeTempItemAtURL:tempFile]; + } + } +} + +/// Removes the temporary file written to disk for sending the request. It has to be cleaned up +/// after the session is done. +- (void)removeTempItemAtURL:(NSURL *)fileURL { + if (!fileURL.absoluteString.length) { + return; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + if (![fileManager removeItemAtURL:fileURL error:&error] && error.code != NSFileNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession013 + message:@"Failed to remove temporary uploading data file. Error" + context:error.localizedDescription]; + } +} + +/// Gets the fetcher with the session ID. ++ (instancetype)fetcherWithSessionIdentifier:(NSString *)sessionIdentifier { + GULNetworkURLSession *session = [self sessionFromFetcherMapForSessionID:sessionIdentifier]; + if (!session && [sessionIdentifier hasPrefix:kGULNetworkBackgroundSessionConfigIDPrefix]) { + session = [[GULNetworkURLSession alloc] initWithNetworkLoggerDelegate:nil]; + [session setSessionID:sessionIdentifier]; + [self setSessionInFetcherMap:session forSessionID:sessionIdentifier]; + } + return session; +} + +/// Returns a map of the fetcher by session ID. Creates a map if it is not created. +/// When reading and writing from/to the session map, don't use this method directly. +/// To avoid thread safety issues, use one of the helper methods at the bottom of the +/// file: setSessionInFetcherMap:forSessionID:, sessionFromFetcherMapForSessionID: ++ (NSMapTable *)sessionIDToFetcherMap { + static NSMapTable *sessionIDToFetcherMap; + + static dispatch_once_t sessionMapOnceToken; + dispatch_once(&sessionMapOnceToken, ^{ + sessionIDToFetcherMap = [NSMapTable strongToWeakObjectsMapTable]; + }); + return sessionIDToFetcherMap; +} + ++ (NSLock *)sessionIDToFetcherMapReadWriteLock { + static NSLock *lock; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + lock = [[NSLock alloc] init]; + }); + return lock; +} + +/// Returns a map of system provided completion handler by session ID. Creates a map if it is not +/// created. ++ (GULMutableDictionary *)sessionIDToSystemCompletionHandlerDictionary { + static GULMutableDictionary *systemCompletionHandlers; + + static dispatch_once_t systemCompletionHandlerOnceToken; + dispatch_once(&systemCompletionHandlerOnceToken, ^{ + systemCompletionHandlers = [[GULMutableDictionary alloc] init]; + }); + return systemCompletionHandlers; +} + +- (NSURL *)temporaryFilePathWithSessionID:(NSString *)sessionID { + NSString *tempName = [NSString stringWithFormat:@"GULUpload_temp_%@", sessionID]; + return [_networkDirectoryURL URLByAppendingPathComponent:tempName]; +} + +/// Makes sure that the directory to store temp files exists. If not, tries to create it and returns +/// YES. If there is anything wrong, returns NO. +- (BOOL)ensureTemporaryDirectoryExists { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + + // Create a temporary directory if it does not exist or was deleted. + if ([_networkDirectoryURL checkResourceIsReachableAndReturnError:&error]) { + return YES; + } + + if (error && error.code != NSFileReadNoSuchFileError) { + [_loggerDelegate + GULNetwork_logWithLevel:kGULNetworkLogLevelWarning + messageCode:kGULNetworkMessageCodeURLSession014 + message:@"Error while trying to access Network temp folder. Error" + context:error]; + } + + NSError *writeError = nil; + + [fileManager createDirectoryAtURL:_networkDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:&writeError]; + if (writeError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession015 + message:@"Cannot create temporary directory. Error" + context:writeError]; + return NO; + } + + // Set the iCloud exclusion attribute on the Documents URL. + [self excludeFromBackupForURL:_networkDirectoryURL]; + + return YES; +} + +- (void)excludeFromBackupForURL:(NSURL *)url { + if (!url.path) { + return; + } + + // Set the iCloud exclusion attribute on the Documents URL. + NSError *preventBackupError = nil; + [url setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:&preventBackupError]; + if (preventBackupError) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession016 + message:@"Cannot exclude temporary folder from iTunes backup"]; + } +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request + completionHandler:(void (^)(NSURLRequest *))completionHandler API_AVAILABLE(ios(7.0)) { + NSArray *nonAllowedRedirectionCodes = @[ + @(kGULNetworkHTTPStatusCodeFound), @(kGULNetworkHTTPStatusCodeMovedPermanently), + @(kGULNetworkHTTPStatusCodeMovedTemporarily), @(kGULNetworkHTTPStatusCodeMultipleChoices) + ]; + + // Allow those not in the non allowed list to be followed. + if (![nonAllowedRedirectionCodes containsObject:@(response.statusCode)]) { + completionHandler(request); + return; + } + + // Do not allow redirection if the response code is in the non-allowed list. + NSURLRequest *newRequest = request; + + if (response) { + newRequest = nil; + } + + completionHandler(newRequest); +} + +#pragma mark - Helper Methods + ++ (void)setSessionInFetcherMap:(GULNetworkURLSession *)session forSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *existingSession = + [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + if (existingSession) { + if (session) { + NSString *message = [NSString stringWithFormat:@"Discarding session: %@", existingSession]; + [existingSession->_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelInfo + messageCode:kGULNetworkMessageCodeURLSession019 + message:message]; + } + [existingSession->_URLSession finishTasksAndInvalidate]; + } + if (session) { + [[[self class] sessionIDToFetcherMap] setObject:session forKey:sessionID]; + } else { + [[[self class] sessionIDToFetcherMap] removeObjectForKey:sessionID]; + } + [[self sessionIDToFetcherMapReadWriteLock] unlock]; +} + ++ (nullable GULNetworkURLSession *)sessionFromFetcherMapForSessionID:(NSString *)sessionID { + [[self sessionIDToFetcherMapReadWriteLock] lock]; + GULNetworkURLSession *session = [[[self class] sessionIDToFetcherMap] objectForKey:sessionID]; + [[self sessionIDToFetcherMapReadWriteLock] unlock]; + return session; +} + +- (void)callCompletionHandler:(GULNetworkURLSessionCompletionHandler)handler + withResponse:(NSHTTPURLResponse *)response + data:(NSData *)data + error:(NSError *)error { + if (error) { + [_loggerDelegate GULNetwork_logWithLevel:kGULNetworkLogLevelError + messageCode:kGULNetworkMessageCodeURLSession017 + message:@"Encounter network error. Code, error" + contexts:@[ @(error.code), error ]]; + } + + if (handler) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(response, data, self->_sessionID, error); + }); + } +} + +// Always use the request parameters even if the default session configuration is more restrictive. +- (void)populateSessionConfig:(NSURLSessionConfiguration *)sessionConfig + withRequest:(NSURLRequest *)request API_AVAILABLE(ios(7.0)) { + sessionConfig.HTTPAdditionalHeaders = request.allHTTPHeaderFields; + sessionConfig.timeoutIntervalForRequest = request.timeoutInterval; + sessionConfig.timeoutIntervalForResource = request.timeoutInterval; + sessionConfig.requestCachePolicy = request.cachePolicy; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h new file mode 100644 index 0000000..a8cc45b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULMutableDictionary.h @@ -0,0 +1,46 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +/// A mutable dictionary that provides atomic accessor and mutators. +@interface GULMutableDictionary : NSObject + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKey:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)object forKey:(id)key; + +/// Removes the object given its session ID from the dictionary. +- (void)removeObjectForKey:(id)key; + +/// Removes all objects. +- (void)removeAllObjects; + +/// Returns the number of current objects in the dictionary. +- (NSUInteger)count; + +/// Returns an object given a key in the dictionary or nil if not found. +- (id)objectForKeyedSubscript:(id)key; + +/// Updates the object given its key or adds it to the dictionary if it is not in the dictionary. +- (void)setObject:(id)obj forKeyedSubscript:(id)key; + +/// Returns the immutable dictionary. +- (NSDictionary *)dictionary; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h new file mode 100644 index 0000000..0e75ae5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetwork.h @@ -0,0 +1,87 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkConstants.h" +#import "GULNetworkLoggerProtocol.h" +#import "GULNetworkURLSession.h" + +/// Delegate protocol for GULNetwork events. +@protocol GULNetworkReachabilityDelegate + +/// Tells the delegate to handle events when the network reachability changes to connected or not +/// connected. +- (void)reachabilityDidChange; + +@end + +/// The Network component that provides network status and handles network requests and responses. +/// This is not thread safe. +/// +/// NOTE: +/// User must add FIRAnalytics handleEventsForBackgroundURLSessionID:completionHandler to the +/// AppDelegate application:handleEventsForBackgroundURLSession:completionHandler: +@interface GULNetwork : NSObject + +/// Indicates if network connectivity is available. +@property(nonatomic, readonly, getter=isNetworkConnected) BOOL networkConnected; + +/// Indicates if there are any uploads in progress. +@property(nonatomic, readonly, getter=hasUploadInProgress) BOOL uploadInProgress; + +/// An optional delegate that can be used in the event when network reachability changes. +@property(nonatomic, weak) id reachabilityDelegate; + +/// An optional delegate that can be used to log messages, warnings or errors that occur in the +/// network operations. +@property(nonatomic, weak) id loggerDelegate; + +/// Indicates whether the logger should display debug messages. +@property(nonatomic, assign) BOOL isDebugModeEnabled; + +/// The time interval in seconds for the network request to timeout. +@property(nonatomic, assign) NSTimeInterval timeoutInterval; + +/// Initializes with the default reachability host. +- (instancetype)init; + +/// Initializes with a custom reachability host. +- (instancetype)initWithReachabilityHost:(NSString *)reachabilityHost; + +/// Handles events when background session with the given ID has finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Compresses and sends a POST request with the provided data to the URL. The session will be +/// background session if usingBackgroundSession is YES. Otherwise, the POST session is default +/// session. Returns a session ID or nil if an error occurs. +- (NSString *)postURL:(NSURL *)url + payload:(NSData *)payload + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +/// Sends a GET request with the provided data to the URL. The session will be background session +/// if usingBackgroundSession is YES. Otherwise, the GET session is default session. Returns a +/// session ID or nil if an error occurs. +- (NSString *)getURL:(NSURL *)url + headers:(NSDictionary *)headers + queue:(dispatch_queue_t)queue + usingBackgroundSession:(BOOL)usingBackgroundSession + completionHandler:(GULNetworkCompletionHandler)handler; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h new file mode 100644 index 0000000..44d440b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkConstants.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import + +/// Error codes in Firebase Network error domain. +/// Note: these error codes should never change. It would make it harder to decode the errors if +/// we inadvertently altered any of these codes in a future SDK version. +typedef NS_ENUM(NSInteger, GULNetworkErrorCode) { + /// Unknown error. + GULNetworkErrorCodeUnknown = 0, + /// Error occurs when the request URL is invalid. + GULErrorCodeNetworkInvalidURL = 1, + /// Error occurs when request cannot be constructed. + GULErrorCodeNetworkRequestCreation = 2, + /// Error occurs when payload cannot be compressed. + GULErrorCodeNetworkPayloadCompression = 3, + /// Error occurs when session task cannot be created. + GULErrorCodeNetworkSessionTaskCreation = 4, + /// Error occurs when there is no response. + GULErrorCodeNetworkInvalidResponse = 5 +}; + +#pragma mark - Network constants + +/// The prefix of the ID of the background session. +extern NSString *const kGULNetworkBackgroundSessionConfigIDPrefix; + +/// The sub directory to store the files of data that is being uploaded in the background. +extern NSString *const kGULNetworkApplicationSupportSubdirectory; + +/// Name of the temporary directory that stores files for background uploading. +extern NSString *const kGULNetworkTempDirectoryName; + +/// The period when the temporary uploading file can stay. +extern const NSTimeInterval kGULNetworkTempFolderExpireTime; + +/// The default network request timeout interval. +extern const NSTimeInterval kGULNetworkTimeOutInterval; + +/// The host to check the reachability of the network. +extern NSString *const kGULNetworkReachabilityHost; + +/// The key to get the error context of the UserInfo. +extern NSString *const kGULNetworkErrorContext; + +#pragma mark - Network Status Code + +extern const int kGULNetworkHTTPStatusOK; +extern const int kGULNetworkHTTPStatusNoContent; +extern const int kGULNetworkHTTPStatusCodeMultipleChoices; +extern const int kGULNetworkHTTPStatusCodeMovedPermanently; +extern const int kGULNetworkHTTPStatusCodeFound; +extern const int kGULNetworkHTTPStatusCodeNotModified; +extern const int kGULNetworkHTTPStatusCodeMovedTemporarily; +extern const int kGULNetworkHTTPStatusCodeNotFound; +extern const int kGULNetworkHTTPStatusCodeCannotAcceptTraffic; +extern const int kGULNetworkHTTPStatusCodeUnavailable; + +#pragma mark - Error Domain + +extern NSString *const kGULNetworkErrorDomain; + +/// The logger service for GULNetwork. +extern GULLoggerService kGULLoggerNetwork; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h new file mode 100644 index 0000000..f1be590 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import + +#import "GULNetworkMessageCode.h" + +/// The log levels used by GULNetworkLogger. +typedef NS_ENUM(NSInteger, GULNetworkLogLevel) { + kGULNetworkLogLevelError = GULLoggerLevelError, + kGULNetworkLogLevelWarning = GULLoggerLevelWarning, + kGULNetworkLogLevelInfo = GULLoggerLevelInfo, + kGULNetworkLogLevelDebug = GULLoggerLevelDebug, +}; + +@protocol GULNetworkLoggerDelegate + +@required +/// Tells the delegate to log a message with an array of contexts and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + contexts:(NSArray *)contexts; + +/// Tells the delegate to log a message with a context and the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message + context:(id)context; + +/// Tells the delegate to log a message with the log level. +- (void)GULNetwork_logWithLevel:(GULNetworkLogLevel)logLevel + messageCode:(GULNetworkMessageCode)messageCode + message:(NSString *)message; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h new file mode 100644 index 0000000..507bc5a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkMessageCode.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULNetworkMessageCode) { + // GULNetwork.m + kGULNetworkMessageCodeNetwork000 = 900000, // I-NET900000 + kGULNetworkMessageCodeNetwork001 = 900001, // I-NET900001 + kGULNetworkMessageCodeNetwork002 = 900002, // I-NET900002 + kGULNetworkMessageCodeNetwork003 = 900003, // I-NET900003 + // GULNetworkURLSession.m + kGULNetworkMessageCodeURLSession000 = 901000, // I-NET901000 + kGULNetworkMessageCodeURLSession001 = 901001, // I-NET901001 + kGULNetworkMessageCodeURLSession002 = 901002, // I-NET901002 + kGULNetworkMessageCodeURLSession003 = 901003, // I-NET901003 + kGULNetworkMessageCodeURLSession004 = 901004, // I-NET901004 + kGULNetworkMessageCodeURLSession005 = 901005, // I-NET901005 + kGULNetworkMessageCodeURLSession006 = 901006, // I-NET901006 + kGULNetworkMessageCodeURLSession007 = 901007, // I-NET901007 + kGULNetworkMessageCodeURLSession008 = 901008, // I-NET901008 + kGULNetworkMessageCodeURLSession009 = 901009, // I-NET901009 + kGULNetworkMessageCodeURLSession010 = 901010, // I-NET901010 + kGULNetworkMessageCodeURLSession011 = 901011, // I-NET901011 + kGULNetworkMessageCodeURLSession012 = 901012, // I-NET901012 + kGULNetworkMessageCodeURLSession013 = 901013, // I-NET901013 + kGULNetworkMessageCodeURLSession014 = 901014, // I-NET901014 + kGULNetworkMessageCodeURLSession015 = 901015, // I-NET901015 + kGULNetworkMessageCodeURLSession016 = 901016, // I-NET901016 + kGULNetworkMessageCodeURLSession017 = 901017, // I-NET901017 + kGULNetworkMessageCodeURLSession018 = 901018, // I-NET901018 + kGULNetworkMessageCodeURLSession019 = 901019, // I-NET901019 +}; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h new file mode 100644 index 0000000..3f9f7f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Network/Private/GULNetworkURLSession.h @@ -0,0 +1,62 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +#import "GULNetworkLoggerProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^GULNetworkCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSError *_Nullable error); +typedef void (^GULNetworkURLSessionCompletionHandler)(NSHTTPURLResponse *_Nullable response, + NSData *_Nullable data, + NSString *sessionID, + NSError *_Nullable error); +typedef void (^GULNetworkSystemCompletionHandler)(void); + +/// The protocol that uses NSURLSession for iOS >= 7.0 to handle requests and responses. +@interface GULNetworkURLSession : NSObject + +/// Indicates whether the background network is enabled. Default value is NO. +@property(nonatomic, getter=isBackgroundNetworkEnabled) BOOL backgroundNetworkEnabled; + +/// The logger delegate to log message, errors or warnings that occur during the network operations. +@property(nonatomic, weak, nullable) id loggerDelegate; + +/// Calls the system provided completion handler after the background session is finished. ++ (void)handleEventsForBackgroundURLSessionID:(NSString *)sessionID + completionHandler:(GULNetworkSystemCompletionHandler)completionHandler; + +/// Initializes with logger delegate. +- (instancetype)initWithNetworkLoggerDelegate: + (nullable id)networkLoggerDelegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Sends an asynchronous POST request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session/connection. +- (nullable NSString *)sessionIDFromAsyncPOSTRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +/// Sends an asynchronous GET request and calls the provided completion handler when the request +/// completes or when errors occur, and returns an ID of the session. +- (nullable NSString *)sessionIDFromAsyncGETRequest:(NSURLRequest *)request + completionHandler:(GULNetworkURLSessionCompletionHandler)handler; + +NS_ASSUME_NONNULL_END +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h new file mode 100644 index 0000000..8aabc8a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h @@ -0,0 +1,47 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +typedef SCNetworkReachabilityRef (*GULReachabilityCreateWithNameFn)(CFAllocatorRef allocator, + const char *host); + +typedef Boolean (*GULReachabilitySetCallbackFn)(SCNetworkReachabilityRef target, + SCNetworkReachabilityCallBack callback, + SCNetworkReachabilityContext *context); +typedef Boolean (*GULReachabilityScheduleWithRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); +typedef Boolean (*GULReachabilityUnscheduleFromRunLoopFn)(SCNetworkReachabilityRef target, + CFRunLoopRef runLoop, + CFStringRef runLoopMode); + +typedef void (*GULReachabilityReleaseFn)(CFTypeRef cf); + +struct GULReachabilityApi { + GULReachabilityCreateWithNameFn createWithNameFn; + GULReachabilitySetCallbackFn setCallbackFn; + GULReachabilityScheduleWithRunLoopFn scheduleWithRunLoopFn; + GULReachabilityUnscheduleFromRunLoopFn unscheduleFromRunLoopFn; + GULReachabilityReleaseFn releaseFn; +}; +#endif +@interface GULReachabilityChecker (Internal) + +- (const struct GULReachabilityApi *)reachabilityApi; +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m new file mode 100644 index 0000000..a334c1a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/GULReachabilityChecker.m @@ -0,0 +1,263 @@ +// Copyright 2017 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +#import "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityChecker.h" +#import "GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h" + +#import +#import + +static GULLoggerService kGULLoggerReachability = @"[GULReachability]"; +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info); + +static const struct GULReachabilityApi kGULDefaultReachabilityApi = { + SCNetworkReachabilityCreateWithName, + SCNetworkReachabilitySetCallback, + SCNetworkReachabilityScheduleWithRunLoop, + SCNetworkReachabilityUnscheduleFromRunLoop, + CFRelease, +}; + +static NSString *const kGULReachabilityUnknownStatus = @"Unknown"; +static NSString *const kGULReachabilityConnectedStatus = @"Connected"; +static NSString *const kGULReachabilityDisconnectedStatus = @"Disconnected"; +#endif +@interface GULReachabilityChecker () + +@property(nonatomic, assign) const struct GULReachabilityApi *reachabilityApi; +@property(nonatomic, assign) GULReachabilityStatus reachabilityStatus; +@property(nonatomic, copy) NSString *host; +#if !TARGET_OS_WATCH +@property(nonatomic, assign) SCNetworkReachabilityRef reachability; +#endif + +@end + +@implementation GULReachabilityChecker + +@synthesize reachabilityApi = reachabilityApi_; +#if !TARGET_OS_WATCH +@synthesize reachability = reachability_; +#endif + +- (const struct GULReachabilityApi *)reachabilityApi { + return reachabilityApi_; +} + +- (void)setReachabilityApi:(const struct GULReachabilityApi *)reachabilityApi { +#if !TARGET_OS_WATCH + if (reachability_) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode000], + @"Cannot change reachability API while reachability is running. " + @"Call stop first."); + return; + } + reachabilityApi_ = reachabilityApi; +#endif +} + +@synthesize reachabilityStatus = reachabilityStatus_; +@synthesize host = host_; +@synthesize reachabilityDelegate = reachabilityDelegate_; + +- (BOOL)isActive { +#if !TARGET_OS_WATCH + return reachability_ != nil; +#else + return NO; +#endif +} + +- (void)setReachabilityDelegate:(id)reachabilityDelegate { + if (reachabilityDelegate && + (![(NSObject *)reachabilityDelegate conformsToProtocol:@protocol(GULReachabilityDelegate)])) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-NET%06ld", (long)kGULReachabilityMessageCode005], + @"Reachability delegate doesn't conform to Reachability protocol."); + return; + } + reachabilityDelegate_ = reachabilityDelegate; +} + +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host { + self = [super init]; + + if (!host || !host.length) { + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode001], + @"Invalid host specified"); + return nil; + } + if (self) { +#if !TARGET_OS_WATCH + [self setReachabilityDelegate:reachabilityDelegate]; + reachabilityApi_ = &kGULDefaultReachabilityApi; + reachabilityStatus_ = kGULReachabilityUnknown; + host_ = [host copy]; + reachability_ = nil; +#endif + } + return self; +} + +- (void)dealloc { + reachabilityDelegate_ = nil; + [self stop]; +} + +- (BOOL)start { +#if TARGET_OS_WATCH + return NO; +#else + + if (!reachability_) { + reachability_ = reachabilityApi_->createWithNameFn(kCFAllocatorDefault, [host_ UTF8String]); + if (!reachability_) { + return NO; + } + SCNetworkReachabilityContext context = { + 0, /* version */ + (__bridge void *)(self), /* info (passed as last parameter to reachability callback) */ + NULL, /* retain */ + NULL, /* release */ + NULL /* copyDescription */ + }; + if (!reachabilityApi_->setCallbackFn(reachability_, ReachabilityCallback, &context) || + !reachabilityApi_->scheduleWithRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes)) { + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + + GULLogError(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode002], + @"Failed to start reachability handle"); + return NO; + } + } + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode003], + @"Monitoring the network status"); + return YES; +#endif +} + +- (void)stop { +#if !TARGET_OS_WATCH + if (reachability_) { + reachabilityStatus_ = kGULReachabilityUnknown; + reachabilityApi_->unscheduleFromRunLoopFn(reachability_, CFRunLoopGetMain(), + kCFRunLoopCommonModes); + reachabilityApi_->releaseFn(reachability_); + reachability_ = nil; + } +#endif +} + +#if !TARGET_OS_WATCH +- (GULReachabilityStatus)statusForFlags:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = kGULReachabilityNotReachable; + // If the Reachable flag is not set, we definitely don't have connectivity. + if (flags & kSCNetworkReachabilityFlagsReachable) { + // Reachable flag is set. Check further flags. + if (!(flags & kSCNetworkReachabilityFlagsConnectionRequired)) { +// Connection required flag is not set, so we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } else if ((flags & (kSCNetworkReachabilityFlagsConnectionOnDemand | + kSCNetworkReachabilityFlagsConnectionOnTraffic)) && + !(flags & kSCNetworkReachabilityFlagsInterventionRequired)) { +// If the connection on demand or connection on traffic flag is set, and user intervention +// is not required, we have connectivity. +#if TARGET_OS_IOS || TARGET_OS_TV + status = (flags & kSCNetworkReachabilityFlagsIsWWAN) ? kGULReachabilityViaCellular + : kGULReachabilityViaWifi; +#elif TARGET_OS_OSX + status = kGULReachabilityViaWifi; +#endif + } + } + return status; +} + +- (void)reachabilityFlagsChanged:(SCNetworkReachabilityFlags)flags { + GULReachabilityStatus status = [self statusForFlags:flags]; + if (reachabilityStatus_ != status) { + NSString *reachabilityStatusString; + if (status == kGULReachabilityUnknown) { + reachabilityStatusString = kGULReachabilityUnknownStatus; + } else { + reachabilityStatusString = (status == kGULReachabilityNotReachable) + ? kGULReachabilityDisconnectedStatus + : kGULReachabilityConnectedStatus; + } + + GULLogDebug(kGULLoggerReachability, NO, + [NSString stringWithFormat:@"I-REA%06ld", (long)kGULReachabilityMessageCode004], + @"Network status has changed. Code:%@, status:%@", @(status), + reachabilityStatusString); + reachabilityStatus_ = status; + [reachabilityDelegate_ reachability:self statusChanged:reachabilityStatus_]; + } +} + +#endif +@end + +#if !TARGET_OS_WATCH +static void ReachabilityCallback(SCNetworkReachabilityRef reachability, + SCNetworkReachabilityFlags flags, + void *info) { + GULReachabilityChecker *checker = (__bridge GULReachabilityChecker *)info; + [checker reachabilityFlagsChanged:flags]; +} +#endif + +// This function used to be at the top of the file, but it was moved here +// as a workaround for a suspected compiler bug. When compiled in Release mode +// and run on an iOS device with WiFi disabled, the reachability code crashed +// when calling SCNetworkReachabilityScheduleWithRunLoop, or shortly thereafter. +// After unsuccessfully trying to diagnose the cause of the crash, it was +// discovered that moving this function to the end of the file magically fixed +// the crash. If you are going to edit this file, exercise caution and make sure +// to test thoroughly with an iOS device under various network conditions. +const NSString *GULReachabilityStatusString(GULReachabilityStatus status) { + switch (status) { + case kGULReachabilityUnknown: + return @"Reachability Unknown"; + + case kGULReachabilityNotReachable: + return @"Not reachable"; + + case kGULReachabilityViaWifi: + return @"Reachable via Wifi"; + + case kGULReachabilityViaCellular: + return @"Reachable via Cellular Data"; + + default: + return [NSString stringWithFormat:@"Invalid reachability status %d", (int)status]; + } +} diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h new file mode 100644 index 0000000..0c70c05 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityChecker.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#if !TARGET_OS_WATCH +#import +#endif + +/// Reachability Status +typedef enum { + kGULReachabilityUnknown, ///< Have not yet checked or been notified whether host is reachable. + kGULReachabilityNotReachable, ///< Host is not reachable. + kGULReachabilityViaWifi, ///< Host is reachable via Wifi. + kGULReachabilityViaCellular, ///< Host is reachable via cellular. +} GULReachabilityStatus; + +const NSString *GULReachabilityStatusString(GULReachabilityStatus status); + +@class GULReachabilityChecker; + +/// Google Analytics iOS Reachability Checker. +@protocol GULReachabilityDelegate +@required +/// Called when network status has changed. +- (void)reachability:(GULReachabilityChecker *)reachability + statusChanged:(GULReachabilityStatus)status; +@end + +/// Google Analytics iOS Network Status Checker. +@interface GULReachabilityChecker : NSObject + +/// The last known reachability status, or GULReachabilityStatusUnknown if the +/// checker is not active. +@property(nonatomic, readonly) GULReachabilityStatus reachabilityStatus; +/// The host to which reachability status is to be checked. +@property(nonatomic, copy, readonly) NSString *host; +/// The delegate to be notified of reachability status changes. +@property(nonatomic, weak) id reachabilityDelegate; +/// `YES` if the reachability checker is active, `NO` otherwise. +@property(nonatomic, readonly) BOOL isActive; + +/// Initialize the reachability checker. Note that you must call start to begin checking for and +/// receiving notifications about network status changes. +/// +/// @param reachabilityDelegate The delegate to be notified when reachability status to host +/// changes. +/// +/// @param host The name of the host. +/// +- (instancetype)initWithReachabilityDelegate:(id)reachabilityDelegate + withHost:(NSString *)host; + +- (instancetype)init NS_UNAVAILABLE; + +/// Start checking for reachability to the specified host. This has no effect if the status +/// checker is already checking for connectivity. +/// +/// @return `YES` if initiating status checking was successful or the status checking has already +/// been initiated, `NO` otherwise. +- (BOOL)start; + +/// Stop checking for reachability to the specified host. This has no effect if the status +/// checker is not checking for connectivity. +- (void)stop; + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h new file mode 100644 index 0000000..373e0af --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Google + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +// Make sure these codes do not overlap with any contained in the FIRAMessageCode enum. +typedef NS_ENUM(NSInteger, GULReachabilityMessageCode) { + // GULReachabilityChecker.m + kGULReachabilityMessageCode000 = 902000, // I-NET902000 + kGULReachabilityMessageCode001 = 902001, // I-NET902001 + kGULReachabilityMessageCode002 = 902002, // I-NET902002 + kGULReachabilityMessageCode003 = 902003, // I-NET902003 + kGULReachabilityMessageCode004 = 902004, // I-NET902004 + kGULReachabilityMessageCode005 = 902005, // I-NET902005 + kGULReachabilityMessageCode006 = 902006, // I-NET902006 +}; diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m new file mode 100644 index 0000000..b80e2af --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m @@ -0,0 +1,438 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "TargetConditionals.h" + +#import +#import +#import +#import +#import +#import "GoogleUtilities/Common/GULLoggerCodes.h" +#import "GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h" + +#import + +#if UISCENE_SUPPORTED +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (*GULOpenURLContextsIMP)(id, SEL, UIScene *, NSSet *); + +API_AVAILABLE(ios(13.0), tvos(13.0)) +typedef void (^GULSceneDelegateInterceptorCallback)(id); + +// The strings below are the keys for associated objects. +static char const *const kGULRealIMPBySelectorKey = "GUL_realIMPBySelector"; +static char const *const kGULRealClassKey = "GUL_realClass"; +#endif // UISCENE_SUPPORTED + +static GULLoggerService kGULLoggerSwizzler = @"[GoogleUtilities/SceneDelegateSwizzler]"; + +// Since Firebase SDKs also use this for app delegate proxying, in order to not be a breaking change +// we disable App Delegate proxying when either of these two flags are set to NO. + +/** Plist key that allows Firebase developers to disable App and Scene Delegate Proxying. */ +static NSString *const kGULFirebaseSceneDelegateProxyEnabledPlistKey = + @"FirebaseAppDelegateProxyEnabled"; + +/** Plist key that allows developers not using Firebase to disable App and Scene Delegate Proxying. + */ +static NSString *const kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey = + @"GoogleUtilitiesAppDelegateProxyEnabled"; + +/** The prefix of the Scene Delegate. */ +static NSString *const kGULSceneDelegatePrefix = @"GUL_"; + +/** + * This class is necessary to store the delegates in an NSArray without retaining them. + * [NSValue valueWithNonRetainedObject] also provides this functionality, but does not provide a + * zeroing pointer. This will cause EXC_BAD_ACCESS when trying to access the object after it is + * dealloced. Instead, this container stores a weak, zeroing reference to the object, which + * automatically is set to nil by the runtime when the object is dealloced. + */ +@interface GULSceneZeroingWeakContainer : NSObject + +/** Stores a weak object. */ +@property(nonatomic, weak) id object; + +@end + +@implementation GULSceneZeroingWeakContainer +@end + +@implementation GULSceneDelegateSwizzler + +#pragma mark - Public methods + ++ (BOOL)isSceneDelegateProxyEnabled { + return [GULAppDelegateSwizzler isAppDelegateProxyEnabled]; +} + ++ (void)proxyOriginalSceneDelegate { +#if UISCENE_SUPPORTED + if ([GULAppEnvironmentUtil isAppExtension]) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (@available(iOS 13.0, tvOS 13.0, *)) { + if (![GULSceneDelegateSwizzler isSceneDelegateProxyEnabled]) { + return; + } + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleSceneWillConnectToNotification:) + name:UISceneWillConnectNotification + object:nil]; + } + }); +#endif // UISCENE_SUPPORTED +} + +#if UISCENE_SUPPORTED ++ (GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor:(id)interceptor { + NSAssert(interceptor, @"SceneDelegateProxy cannot add nil interceptor"); + NSAssert([interceptor conformsToProtocol:@protocol(UISceneDelegate)], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + + if (!interceptor) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling000], + @"SceneDelegateProxy cannot add nil interceptor."); + return nil; + } + if (![interceptor conformsToProtocol:@protocol(UISceneDelegate)]) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling001], + @"SceneDelegateProxy interceptor does not conform to UIApplicationDelegate"); + return nil; + } + + // The ID should be the same given the same interceptor object. + NSString *interceptorID = + [NSString stringWithFormat:@"%@%p", kGULSceneDelegatePrefix, interceptor]; + if (!interceptorID.length) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling002], + @"SceneDelegateProxy cannot create Interceptor ID."); + return nil; + } + GULSceneZeroingWeakContainer *weakObject = [[GULSceneZeroingWeakContainer alloc] init]; + weakObject.object = interceptor; + [GULSceneDelegateSwizzler interceptors][interceptorID] = weakObject; + return interceptorID; +} + ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID { + NSAssert(interceptorID, @"SceneDelegateProxy cannot unregister nil interceptor ID."); + NSAssert(((NSString *)interceptorID).length != 0, + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + + if (!interceptorID) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling003], + @"SceneDelegateProxy cannot unregister empty interceptor ID."); + return; + } + + GULSceneZeroingWeakContainer *weakContainer = + [GULSceneDelegateSwizzler interceptors][interceptorID]; + if (!weakContainer.object) { + GULLogError(kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling004], + @"SceneDelegateProxy cannot unregister interceptor that was not registered. " + "Interceptor ID %@", + interceptorID); + return; + } + + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:interceptorID]; +} + +#pragma mark - Helper methods + ++ (GULMutableDictionary *)interceptors { + static dispatch_once_t onceToken; + static GULMutableDictionary *sInterceptors; + dispatch_once(&onceToken, ^{ + sInterceptors = [[GULMutableDictionary alloc] init]; + }); + return sInterceptors; +} + ++ (void)clearInterceptors { + [[self interceptors] removeAllObjects]; +} + ++ (nullable NSValue *)originalImplementationForSelector:(SEL)selector object:(id)object { + NSDictionary *realImplementationBySelector = + objc_getAssociatedObject(object, &kGULRealIMPBySelectorKey); + return realImplementationBySelector[NSStringFromSelector(selector)]; +} + ++ (void)proxyDestinationSelector:(SEL)destinationSelector + implementationsFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)sourceClass + toClass:(Class)destinationClass + realClass:(Class)realClass + storeDestinationImplementationTo: + (NSMutableDictionary *)destinationImplementationsBySelector { + [self addInstanceMethodWithDestinationSelector:destinationSelector + withImplementationFromSourceSelector:sourceSelector + fromClass:sourceClass + toClass:destinationClass]; + IMP sourceImplementation = + [GULSceneDelegateSwizzler implementationOfMethodSelector:destinationSelector + fromClass:realClass]; + NSValue *sourceImplementationPointer = [NSValue valueWithPointer:sourceImplementation]; + + NSString *destinationSelectorString = NSStringFromSelector(destinationSelector); + destinationImplementationsBySelector[destinationSelectorString] = sourceImplementationPointer; +} + +/** Copies a method identified by the methodSelector from one class to the other. After this method + * is called, performing [toClassInstance methodSelector] will be similar to calling + * [fromClassInstance methodSelector]. This method does nothing if toClass already has a method + * identified by methodSelector. + * + * @param methodSelector The SEL that identifies both the method on the fromClass as well as the + * one on the toClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector + withImplementationFromSourceSelector:methodSelector + fromClass:fromClass + toClass:toClass]; +} + +/** Copies a method identified by the sourceSelector from the fromClass as a method for the + * destinationSelector on the toClass. After this method is called, performing + * [toClassInstance destinationSelector] will be similar to calling + * [fromClassInstance sourceSelector]. This method does nothing if toClass already has a method + * identified by destinationSelector. + * + * @param destinationSelector The SEL that identifies the method on the toClass. + * @param sourceSelector The SEL that identifies the method on the fromClass. + * @param fromClass The class from which a method is sourced. + * @param toClass The class to which the method is added. If the class already has a method with + * the same selector, this has no effect. + */ ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector + withImplementationFromSourceSelector:(SEL)sourceSelector + fromClass:(Class)fromClass + toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling009], + @"Cannot copy method to destination selector %@ as it already exists", + NSStringFromSelector(destinationSelector)); + } +} + +/** Gets the IMP of the instance method on the class identified by the selector. + * + * @param selector The selector of which the IMP is to be fetched. + * @param aClass The class from which the IMP is to be fetched. + * @return The IMP of the instance method identified by selector and aClass. + */ ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + +/** Enumerates through all the interceptors and if they respond to a given selector, executes a + * GULSceneDelegateInterceptorCallback with the interceptor. + * + * @param methodSelector The SEL to check if an interceptor responds to. + * @param callback the GULSceneDelegateInterceptorCallback. + */ ++ (void)notifyInterceptorsWithMethodSelector:(SEL)methodSelector + callback:(GULSceneDelegateInterceptorCallback)callback + API_AVAILABLE(ios(13.0)) { + if (!callback) { + return; + } + + NSDictionary *interceptors = [GULSceneDelegateSwizzler interceptors].dictionary; + [interceptors enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + GULSceneZeroingWeakContainer *interceptorContainer = obj; + id interceptor = interceptorContainer.object; + if (!interceptor) { + GULLogWarning( + kGULLoggerSwizzler, NO, + [NSString stringWithFormat:@"I-SWZ%06ld", + (long)kGULSwizzlerMessageCodeSceneDelegateSwizzling010], + @"SceneDelegateProxy cannot find interceptor with ID %@. Removing the interceptor.", key); + [[GULSceneDelegateSwizzler interceptors] removeObjectForKey:key]; + return; + } + if ([interceptor respondsToSelector:methodSelector]) { + callback(interceptor); + } + }]; +} + ++ (void)handleSceneWillConnectToNotification:(NSNotification *)notification { + if (@available(iOS 13.0, tvOS 13.0, *)) { + if ([notification.object isKindOfClass:[UIScene class]]) { + UIScene *scene = (UIScene *)notification.object; + [GULSceneDelegateSwizzler proxySceneDelegateIfNeeded:scene]; + } + } +} + +#pragma mark - [Donor Methods] UISceneDelegate URL handler + +- (void)scene:(UIScene *)scene + openURLContexts:(NSSet *)URLContexts API_AVAILABLE(ios(13.0), tvos(13.0)) { + if (@available(iOS 13.0, tvOS 13.0, *)) { + SEL methodSelector = @selector(scene:openURLContexts:); + // Call the real implementation if the real Scene Delegate has any. + NSValue *openURLContextsIMPPointer = + [GULSceneDelegateSwizzler originalImplementationForSelector:methodSelector object:self]; + GULOpenURLContextsIMP openURLContextsIMP = [openURLContextsIMPPointer pointerValue]; + + [GULSceneDelegateSwizzler + notifyInterceptorsWithMethodSelector:methodSelector + callback:^(id interceptor) { + if ([interceptor + conformsToProtocol:@protocol(UISceneDelegate)]) { + id sceneInterceptor = + (id)interceptor; + [sceneInterceptor scene:scene openURLContexts:URLContexts]; + } + }]; + + if (openURLContextsIMP) { + openURLContextsIMP(self, methodSelector, scene, URLContexts); + } + } +} + ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene { + Class realClass = [scene.delegate class]; + NSString *className = NSStringFromClass(realClass); + + // Skip proxying if failed to get the delegate class name for some reason (e.g. `delegate == nil`) + // or the class has a prefix of kGULAppDelegatePrefix, which means it has been proxied before. + if (className == nil || [className hasPrefix:kGULSceneDelegatePrefix]) { + return; + } + + NSString *classNameWithPrefix = [kGULSceneDelegatePrefix stringByAppendingString:className]; + NSString *newClassName = + [NSString stringWithFormat:@"%@-%@", classNameWithPrefix, [NSUUID UUID].UUIDString]; + + if (NSClassFromString(newClassName)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: %@", + className, newClassName); + return; + } + + // Register the new class as subclass of the real one. Do not allocate more than the real class + // size. + Class sceneDelegateSubClass = objc_allocateClassPair(realClass, newClassName.UTF8String, 0); + if (sceneDelegateSubClass == Nil) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create a proxy for Scene Delegate. Subclass already exists. Original Class" + @": %@, subclass: Nil", + className); + return; + } + + NSMutableDictionary *realImplementationsBySelector = + [[NSMutableDictionary alloc] init]; + + // For scene:openURLContexts: + SEL openURLContextsSEL = @selector(scene:openURLContexts:); + [self proxyDestinationSelector:openURLContextsSEL + implementationsFromSourceSelector:openURLContextsSEL + fromClass:[GULSceneDelegateSwizzler class] + toClass:sceneDelegateSubClass + realClass:realClass + storeDestinationImplementationTo:realImplementationsBySelector]; + + // Store original implementations to a fake property of the original delegate. + objc_setAssociatedObject(scene.delegate, &kGULRealIMPBySelectorKey, + [realImplementationsBySelector copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(scene.delegate, &kGULRealClassKey, realClass, + OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // The subclass size has to be exactly the same size with the original class size. The subclass + // cannot have more ivars/properties than its superclass since it will cause an offset in memory + // that can lead to overwriting the isa of an object in the next frame. + if (class_getInstanceSize(realClass) != class_getInstanceSize(sceneDelegateSubClass)) { + GULLogError( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Cannot create subclass of Scene Delegate, because the created subclass is not the " + @"same size. %@", + className); + NSAssert(NO, @"Classes must be the same size to swizzle isa"); + return; + } + + // Make the newly created class to be the subclass of the real Scene Delegate class. + objc_registerClassPair(sceneDelegateSubClass); + if (object_setClass(scene.delegate, sceneDelegateSubClass)) { + GULLogDebug( + kGULLoggerSwizzler, NO, + [NSString + stringWithFormat:@"I-SWZ%06ld", + (long) + kGULSwizzlerMessageCodeSceneDelegateSwizzlingInvalidSceneDelegate], + @"Successfully created Scene Delegate Proxy automatically. To disable the " + @"proxy, set the flag %@ to NO (Boolean) in the Info.plist", + [GULSceneDelegateSwizzler correctSceneDelegateProxyKey]); + } +} + ++ (NSString *)correctSceneDelegateProxyKey { + return NSClassFromString(@"FIRCore") ? kGULFirebaseSceneDelegateProxyEnabledPlistKey + : kGULGoogleUtilitiesSceneDelegateProxyEnabledPlistKey; +} + +#endif // UISCENE_SUPPORTED + +@end diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h new file mode 100644 index 0000000..a2439eb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface GULSceneDelegateSwizzler () + +#if UISCENE_SUPPORTED + +/** Returns a dictionary containing interceptor IDs mapped to a GULZeroingWeakContainer. + * + * @return A dictionary of the form {NSString : GULZeroingWeakContainer}, where the NSString is + * the interceptorID. + */ ++ (GULMutableDictionary *)interceptors; + +/** Deletes all the registered interceptors. */ ++ (void)clearInterceptors; + +/** ISA Swizzles the given appDelegate as the original app delegate would be. + * + * @param scene The scene whose delegate needs to be isa swizzled. This should conform to the + * scene delegate protocol. + */ ++ (void)proxySceneDelegateIfNeeded:(UIScene *)scene API_AVAILABLE(ios(13.0), tvos(13.0)); + +#endif // UISCENE_SUPPORTED + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h new file mode 100644 index 0000000..420b3e7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h @@ -0,0 +1,73 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !TARGET_OS_OSX +#import +#endif // !TARGET_OS_OSX + +#if ((TARGET_OS_IOS || TARGET_OS_TV) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 130000)) +#define UISCENE_SUPPORTED 1 +#endif + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *const GULSceneDelegateInterceptorID; + +/** This class contains methods that isa swizzle the scene delegate. */ +@interface GULSceneDelegateSwizzler : NSProxy + +#if UISCENE_SUPPORTED + +/** Registers a scene delegate interceptor whose methods will be invoked as they're invoked on the + * original scene delegate. + * + * @param interceptor An instance of a class that conforms to the application delegate protocol. + * The interceptor is NOT retained. + * @return A unique GULSceneDelegateInterceptorID if interceptor was successfully registered; nil + * if it fails. + */ ++ (nullable GULSceneDelegateInterceptorID)registerSceneDelegateInterceptor: + (id)interceptor API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Unregisters an interceptor with the given ID if it exists. + * + * @param interceptorID The object that was generated when the interceptor was registered. + */ ++ (void)unregisterSceneDelegateInterceptorWithID:(GULSceneDelegateInterceptorID)interceptorID + API_AVAILABLE(ios(13.0), tvos(13.0)); + +/** Do not initialize this class. */ +- (instancetype)init NS_UNAVAILABLE; + +#endif // UISCENE_SUPPORTED + +/** This method ensures that the original scene delegate has been proxied. Call this before + * registering your interceptor. This method is safe to call multiple times (but it only proxies + * the scene delegate once). + * + * The method has no effect for extensions. + */ ++ (void)proxyOriginalSceneDelegate; + +/** Indicates whether scene delegate proxy is explicitly disabled or enabled. Enabled by default. + * + * @return YES if SceneDelegateProxy is Enabled, NO otherwise. + */ ++ (BOOL)isSceneDelegateProxyEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m new file mode 100644 index 0000000..47ac35d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/GULUserDefaults.m @@ -0,0 +1,213 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Private/GULUserDefaults.h" + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSTimeInterval const kGULSynchronizeInterval = 1.0; + +static NSString *const kGULLogFormat = @"I-GUL%06ld"; + +static GULLoggerService kGULLogUserDefaultsService = @"[GoogleUtilities/UserDefaults]"; + +typedef NS_ENUM(NSInteger, GULUDMessageCode) { + GULUDMessageCodeInvalidKeyGet = 1, + GULUDMessageCodeInvalidKeySet = 2, + GULUDMessageCodeInvalidObjectSet = 3, + GULUDMessageCodeSynchronizeFailed = 4, +}; + +@interface GULUserDefaults () + +/// Equivalent to the suite name for NSUserDefaults. +@property(readonly) CFStringRef appNameRef; + +@property(atomic) BOOL isPreferenceFileExcluded; + +@end + +@implementation GULUserDefaults { + // The application name is the same with the suite name of the NSUserDefaults, and it is used for + // preferences. + CFStringRef _appNameRef; +} + ++ (GULUserDefaults *)standardUserDefaults { + static GULUserDefaults *standardUserDefaults; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[GULUserDefaults alloc] init]; + }); + return standardUserDefaults; +} + +- (instancetype)init { + return [self initWithSuiteName:nil]; +} + +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName { + self = [super init]; + + NSString *name = [suiteName copy]; + + if (self) { + // `kCFPreferencesCurrentApplication` maps to the same defaults database as + // `[NSUserDefaults standardUserDefaults]`. + _appNameRef = + name.length ? (__bridge_retained CFStringRef)name : kCFPreferencesCurrentApplication; + } + + return self; +} + +- (void)dealloc { + // If we're using a custom `_appNameRef` it needs to be released. If it's a constant, it shouldn't + // need to be released since we don't own it. + if (CFStringCompare(_appNameRef, kCFPreferencesCurrentApplication, 0) != kCFCompareEqualTo) { + CFRelease(_appNameRef); + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; +} + +- (nullable id)objectForKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(@"", NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeyGet], + @"Cannot get object for invalid user default key."); + return nil; + } + return (__bridge_transfer id)CFPreferencesCopyAppValue((__bridge CFStringRef)key, _appNameRef); +} + +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName { + NSString *key = [defaultName copy]; + if (![key isKindOfClass:[NSString class]] || !key.length) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidKeySet], + @"Cannot set object for invalid user default key."); + return; + } + if (!value) { + CFPreferencesSetAppValue((__bridge CFStringRef)key, NULL, _appNameRef); + [self scheduleSynchronize]; + return; + } + BOOL isAcceptableValue = + [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || + [value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]] || + [value isKindOfClass:[NSDate class]] || [value isKindOfClass:[NSData class]]; + if (!isAcceptableValue) { + GULLogWarning(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeInvalidObjectSet], + @"Cannot set invalid object to user defaults. Must be a string, number, array, " + @"dictionary, date, or data. Value: %@", + value); + return; + } + + CFPreferencesSetAppValue((__bridge CFStringRef)key, (__bridge CFStringRef)value, _appNameRef); + [self scheduleSynchronize]; +} + +- (void)removeObjectForKey:(NSString *)key { + [self setObject:nil forKey:key]; +} + +#pragma mark - Getters + +- (NSInteger)integerForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.integerValue; +} + +- (float)floatForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.floatValue; +} + +- (double)doubleForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.doubleValue; +} + +- (BOOL)boolForKey:(NSString *)defaultName { + NSNumber *object = [self objectForKey:defaultName]; + return object.boolValue; +} + +- (nullable NSString *)stringForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSArray *)arrayForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName { + return [self objectForKey:defaultName]; +} + +#pragma mark - Setters + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)defaultName { + [self setObject:@(integer) forKey:defaultName]; +} + +- (void)setFloat:(float)value forKey:(NSString *)defaultName { + [self setObject:@(value) forKey:defaultName]; +} + +- (void)setDouble:(double)doubleNumber forKey:(NSString *)defaultName { + [self setObject:@(doubleNumber) forKey:defaultName]; +} + +- (void)setBool:(BOOL)boolValue forKey:(NSString *)defaultName { + [self setObject:@(boolValue) forKey:defaultName]; +} + +#pragma mark - Save data + +- (void)synchronize { + if (!CFPreferencesAppSynchronize(_appNameRef)) { + GULLogError(kGULLogUserDefaultsService, NO, + [NSString stringWithFormat:kGULLogFormat, (long)GULUDMessageCodeSynchronizeFailed], + @"Cannot synchronize user defaults to disk"); + } +} + +#pragma mark - Private methods + +- (void)scheduleSynchronize { + // Synchronize data using a timer so that multiple set... calls can be coalesced under one + // synchronize. + [NSObject cancelPreviousPerformRequestsWithTarget:self + selector:@selector(synchronize) + object:nil]; + // This method may be called on multiple queues (due to set... methods can be called on any queue) + // synchronize can be scheduled on different queues, so make sure that it does not crash. If this + // instance goes away, self will be released also, no one will retain it and the schedule won't be + // called. + [self performSelector:@selector(synchronize) withObject:nil afterDelay:kGULSynchronizeInterval]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h new file mode 100644 index 0000000..0d04781 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/GoogleUtilities/UserDefaults/Private/GULUserDefaults.h @@ -0,0 +1,110 @@ +// Copyright 2018 Google +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A thread-safe user defaults that uses C functions from CFPreferences.h instead of +/// `NSUserDefaults`. This is to avoid sending an `NSNotification` when it's changed from a +/// background thread to avoid crashing. // TODO: Insert radar number here. +@interface GULUserDefaults : NSObject + +/// A shared user defaults similar to +[NSUserDefaults standardUserDefaults] and accesses the same +/// data of the standardUserDefaults. ++ (GULUserDefaults *)standardUserDefaults; + +/// Initializes preferences with a suite name that is the same with the NSUserDefaults' suite name. +/// Both of CFPreferences and NSUserDefaults share the same plist file so their data will exactly +/// the same. +/// +/// @param suiteName The name of the suite of the user defaults. +- (instancetype)initWithSuiteName:(nullable NSString *)suiteName; + +#pragma mark - Getters + +/// Searches the receiver's search list for a default with the key 'defaultName' and return it. If +/// another process has changed defaults in the search list, NSUserDefaults will automatically +/// update to the latest values. If the key in question has been marked as ubiquitous via a Defaults +/// Configuration File, the latest value may not be immediately available, and the registered value +/// will be returned instead. +- (nullable id)objectForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value is not an NSArray. +- (nullable NSArray *)arrayForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will return nil if the value +/// is not an NSDictionary. +- (nullable NSDictionary *)dictionaryForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it will convert NSNumber values to their NSString +/// representation. If a non-string non-number value is found, nil will be returned. +- (nullable NSString *)stringForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the +/// value is an NSNumber, the result of -integerValue will be returned. If the value is an NSString, +/// it will be converted to NSInteger if possible. If the value is a boolean, it will be converted +/// to either 1 for YES or 0 for NO. If the value is absent or can't be converted to an integer, 0 +/// will be returned. +- (NSInteger)integerForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a float, and boolean values will not be +/// converted. +- (float)floatForKey:(NSString *)defaultName; + +/// Similar to -integerForKey:, except that it returns a double, and boolean values will not be +/// converted. +- (double)doubleForKey:(NSString *)defaultName; + +/// Equivalent to -objectForKey:, except that it converts the returned value to a BOOL. If the value +/// is an NSNumber, NO will be returned if the value is 0, YES otherwise. If the value is an +/// NSString, values of "YES" or "1" will return YES, and values of "NO", "0", or any other string +/// will return NO. If the value is absent or can't be converted to a BOOL, NO will be returned. +- (BOOL)boolForKey:(NSString *)defaultName; + +#pragma mark - Setters + +/// Immediately stores a value (or removes the value if `nil` is passed as the value) for the +/// provided key in the search list entry for the receiver's suite name in the current user and any +/// host, then asynchronously stores the value persistently, where it is made available to other +/// processes. +- (void)setObject:(nullable id)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a float to an NSNumber. +- (void)setFloat:(float)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a double to an +/// NSNumber. +- (void)setDouble:(double)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from an NSInteger to an +/// NSNumber. +- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName; + +/// Equivalent to -setObject:forKey: except that the value is converted from a BOOL to an NSNumber. +- (void)setBool:(BOOL)value forKey:(NSString *)defaultName; + +#pragma mark - Removing Defaults + +/// Equivalent to -[... setObject:nil forKey:defaultName] +- (void)removeObjectForKey:(NSString *)defaultName; + +#pragma mark - Save data + +/// Blocks the calling thread until all in-progress set operations have completed. +- (void)synchronize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/GoogleUtilities/README.md b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/README.md new file mode 100644 index 0000000..5097a89 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/GoogleUtilities/README.md @@ -0,0 +1,254 @@ +# Firebase iOS Open Source Development [![Build Status](https://travis-ci.org/firebase/firebase-ios-sdk.svg?branch=master)](https://travis-ci.org/firebase/firebase-ios-sdk) + +This repository contains a subset of the Firebase iOS SDK source. It currently +includes FirebaseCore, FirebaseABTesting, FirebaseAuth, FirebaseDatabase, +FirebaseFirestore, FirebaseFunctions, FirebaseInstanceID, FirebaseInAppMessaging, +FirebaseInAppMessagingDisplay, FirebaseMessaging, FirebaseRemoteConfig, and +FirebaseStorage. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.1 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`. +These commands will get the right versions: + +``` +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/e3496d9/Formula/clang-format.rb +brew upgrade https://raw.githubusercontent.com/Homebrew/homebrew-core/7963c3d/Formula/swiftformat.rb +``` + +Note: if you already have a newer version of these installed you may need to +`brew switch` to this version. + +To update this section, find the versions of clang-format and swiftformat.rb to +match the versions in the CI failure logs +[here](https://github.com/Homebrew/homebrew-core/tree/master/Formula). + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and replace the appropriate dummy plist file +(e.g. in [Example/Database/App/](Example/Database/App/)); + +Some sample apps like Firebase Messaging ([Example/Messaging/App](Example/Messaging/App)) require +special Apple capabilities, and you will have to change the sample app to use a unique bundle +identifier that you can control in your own Apple Developer account. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](Example/Auth/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +To run the Database Integration tests, make your database authentication rules +[public](https://firebase.google.com/docs/database/security/quickstart). + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](Example/Storage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). + +Keep in mind that macOS, Catalyst and tvOS are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS or tvOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' +pod 'Firebase/Auth' +pod 'Firebase/Crashlytics' +pod 'Firebase/Database' +pod 'Firebase/Firestore' +pod 'Firebase/Functions' +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Private/Firebase/Firebase.h b/PediatricPancreas_Storyboard/Pods/Headers/Private/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Private/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h new file mode 120000 index 0000000..0253e25 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseAuthInterop/FIRAuthInterop.h @@ -0,0 +1 @@ +../../../FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h new file mode 120000 index 0000000..ce646ec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h new file mode 120000 index 0000000..07d83d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Private/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Public/Firebase/Firebase.h b/PediatricPancreas_Storyboard/Pods/Headers/Public/Firebase/Firebase.h new file mode 120000 index 0000000..07ac6eb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Public/Firebase/Firebase.h @@ -0,0 +1 @@ +../../../Firebase/CoreOnly/Sources/Firebase.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h new file mode 120000 index 0000000..0253e25 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseAuthInterop/FIRAuthInterop.h @@ -0,0 +1 @@ +../../../FirebaseAuthInterop/Interop/Auth/Public/FIRAuthInterop.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h new file mode 120000 index 0000000..ce646ec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsData.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h new file mode 120000 index 0000000..07d83d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Headers/Public/FirebaseCoreDiagnosticsInterop/FIRCoreDiagnosticsInterop.h @@ -0,0 +1 @@ +../../../FirebaseCoreDiagnosticsInterop/Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Manifest.lock b/PediatricPancreas_Storyboard/Pods/Manifest.lock new file mode 100644 index 0000000..3f3f2f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Manifest.lock @@ -0,0 +1,137 @@ +PODS: + - Firebase/Core (6.17.0): + - Firebase/CoreOnly + - FirebaseAnalytics (= 6.2.2) + - Firebase/CoreOnly (6.17.0): + - FirebaseCore (= 6.6.2) + - Firebase/Database (6.17.0): + - Firebase/CoreOnly + - FirebaseDatabase (~> 6.1.4) + - Firebase/Storage (6.17.0): + - Firebase/CoreOnly + - FirebaseStorage (~> 3.5.0) + - FirebaseAnalytics (6.2.2): + - FirebaseCore (~> 6.6) + - FirebaseInstanceID (~> 4.3) + - GoogleAppMeasurement (= 6.2.2) + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - FirebaseAuthInterop (1.0.0) + - FirebaseCore (6.6.2): + - FirebaseCoreDiagnostics (~> 1.2) + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - FirebaseCoreDiagnostics (1.2.0): + - FirebaseCoreDiagnosticsInterop (~> 1.2) + - GoogleDataTransportCCTSupport (~> 1.3) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/Logger (~> 6.5) + - nanopb (~> 0.3.901) + - FirebaseCoreDiagnosticsInterop (1.2.0) + - FirebaseDatabase (6.1.4): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - leveldb-library (~> 1.22) + - FirebaseInstallations (1.1.0): + - FirebaseCore (~> 6.6) + - GoogleUtilities/UserDefaults (~> 6.5) + - PromisesObjC (~> 1.2) + - FirebaseInstanceID (4.3.1): + - FirebaseCore (~> 6.6) + - FirebaseInstallations (~> 1.0) + - GoogleUtilities/Environment (~> 6.5) + - GoogleUtilities/UserDefaults (~> 6.5) + - FirebaseStorage (3.5.0): + - FirebaseAuthInterop (~> 1.0) + - FirebaseCore (~> 6.0) + - GTMSessionFetcher/Core (~> 1.1) + - GoogleAppMeasurement (6.2.2): + - GoogleUtilities/AppDelegateSwizzler (~> 6.0) + - GoogleUtilities/MethodSwizzler (~> 6.0) + - GoogleUtilities/Network (~> 6.0) + - "GoogleUtilities/NSData+zlib (~> 6.0)" + - nanopb (= 0.3.9011) + - GoogleDataTransport (4.0.0) + - GoogleDataTransportCCTSupport (1.4.0): + - GoogleDataTransport (~> 4.0) + - nanopb (~> 0.3.901) + - GoogleUtilities/AppDelegateSwizzler (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (6.5.1) + - GoogleUtilities/Logger (6.5.1): + - GoogleUtilities/Environment + - GoogleUtilities/MethodSwizzler (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/Network (6.5.1): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (6.5.1)" + - GoogleUtilities/Reachability (6.5.1): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (6.5.1): + - GoogleUtilities/Logger + - GTMSessionFetcher/Core (1.3.1) + - leveldb-library (1.22) + - nanopb (0.3.9011): + - nanopb/decode (= 0.3.9011) + - nanopb/encode (= 0.3.9011) + - nanopb/decode (0.3.9011) + - nanopb/encode (0.3.9011) + - PromisesObjC (1.2.8) + +DEPENDENCIES: + - Firebase/Core + - Firebase/Database + - Firebase/Storage + +SPEC REPOS: + trunk: + - Firebase + - FirebaseAnalytics + - FirebaseAuthInterop + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseCoreDiagnosticsInterop + - FirebaseDatabase + - FirebaseInstallations + - FirebaseInstanceID + - FirebaseStorage + - GoogleAppMeasurement + - GoogleDataTransport + - GoogleDataTransportCCTSupport + - GoogleUtilities + - GTMSessionFetcher + - leveldb-library + - nanopb + - PromisesObjC + +SPEC CHECKSUMS: + Firebase: 2672e5636b42f977177716317e68346ae5e9de25 + FirebaseAnalytics: cf95d3aab897612783020fbd98401d5366f135ee + FirebaseAuthInterop: 0ffa57668be100582bb7643d4fcb7615496c41fc + FirebaseCore: a1dd9dd6355a8356dd30a8f076839e242285a81c + FirebaseCoreDiagnostics: 5e78803ab276bc5b50340e3c539c06c3de35c649 + FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850 + FirebaseDatabase: 0144e0706a4761f1b0e8679572eba8095ddb59be + FirebaseInstallations: 575cd32f2aec0feeb0e44f5d0110a09e5e60b47b + FirebaseInstanceID: 031d7d0c8e7b5c030bbeb4d2a690550375e83fec + FirebaseStorage: 6c5263796af3b1be82ed173598aade47535fe125 + GoogleAppMeasurement: d0560d915abf15e692e8538ba1d58442217b6aff + GoogleDataTransport: 47fe3b8e1673e5187dfd615656a3c5034f150d69 + GoogleDataTransportCCTSupport: 36f69887fd212db6d7ef4dd45ba44523717a434e + GoogleUtilities: 06eb53bb579efe7099152735900dd04bf09e7275 + GTMSessionFetcher: cea130bbfe5a7edc8d06d3f0d17288c32ffe9925 + leveldb-library: 55d93ee664b4007aac644a782d11da33fba316f7 + nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd + PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6 + +PODFILE CHECKSUM: 2b8aab10dc2ed1c09c0e116f72abd31d827654b1 + +COCOAPODS: 1.8.4 diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..8f4de2d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,6524 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXAggregateTarget section */ + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */ = { + isa = PBXAggregateTarget; + buildConfigurationList = C2B17CA0717D72AEA47AB8C4E1652030 /* Build configuration list for PBXAggregateTarget "Firebase" */; + buildPhases = ( + ); + dependencies = ( + A86B54826E2EA357A9E4EF0CA7C8D25E /* PBXTargetDependency */, + 9089FF135822BEE9E10F39594E1EC487 /* PBXTargetDependency */, + D1B2D249EBE644FE4A399FAD17173251 /* PBXTargetDependency */, + 87BEF7CCA2828E143F52F4667E385CEE /* PBXTargetDependency */, + ); + name = Firebase; + }; + 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = CD64B52618F3D742F1527AB1C42ECB95 /* Build configuration list for PBXAggregateTarget "FirebaseCoreDiagnosticsInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseCoreDiagnosticsInterop; + }; + 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */ = { + isa = PBXAggregateTarget; + buildConfigurationList = BD280CAFB18CC9A1F33CAACBAA7DDE72 /* Build configuration list for PBXAggregateTarget "FirebaseAuthInterop" */; + buildPhases = ( + ); + dependencies = ( + ); + name = FirebaseAuthInterop; + }; + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 5DB189BCCF5A8C3F2A19B6D93AD65ACE /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */; + buildPhases = ( + ); + dependencies = ( + F90FAE92CE4739886F82CECA40921D87 /* PBXTargetDependency */, + 75AD11D1386149B1465CBE28285DD48B /* PBXTargetDependency */, + ); + name = GoogleAppMeasurement; + }; + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 0DEB38A977DAF9AC9FE5DADE8049F71E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */; + buildPhases = ( + ); + dependencies = ( + 72D57259FC0744307EA81E16CAC5A881 /* PBXTargetDependency */, + 00EC45E47078FCC77557A8B4EE533F87 /* PBXTargetDependency */, + F7D3045BF1FAB138CB45DA3751ECDE8B /* PBXTargetDependency */, + 0C87077F1AAEC62E4534092C7FEFF80A /* PBXTargetDependency */, + 2357AC32539315EA9D953E73978A8695 /* PBXTargetDependency */, + ); + name = FirebaseAnalytics; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 0060000465B9E17FBC63E9A209A0D812 /* GDTCOREvent_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 986E76CDB36A58245C5FFB25DF53A794 /* GDTCOREvent_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 00D778F7464CD6C207C38F5E3F0775C5 /* FTupleTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E2B112675E7D67B7AF74F65E5478631 /* FTupleTransaction.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 00DCAA7573F2E72B6199CBA90FB95947 /* hash.cc in Sources */ = {isa = PBXBuildFile; fileRef = 75488CF61E51A631F39BCAB3BD1723B4 /* hash.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0104C71870B54BA06B7A694204C163A9 /* FIRErrorCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 856069552761D6C6E970C60B6DFB24FC /* FIRErrorCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 010792DD347E0305A235B9C4E6FEA68C /* FIRStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A13CB75BF68742AE7610270D81FCE09 /* FIRStorage.m */; }; + 01F8CA6FC1B684592EB39FF66F7E413F /* filter_block.h in Headers */ = {isa = PBXBuildFile; fileRef = DD1AC890E27B00503F3CF6EE90A68C0E /* filter_block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 025D8975E3F1E0454C78740B08AD63C6 /* status.cc in Sources */ = {isa = PBXBuildFile; fileRef = 74CAEF8480566F2AC62C5C743E46760D /* status.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0297E70E68D821A53F9F751CC0D6C0FF /* FIRInstallationsStore.h in Headers */ = {isa = PBXBuildFile; fileRef = E2D22F3C8DC79314E4327FF9F03407E5 /* FIRInstallationsStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 02DB6C108D93B1A28894EE7DB7E7EBC0 /* GULReachabilityChecker+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 11A186726CCB0F63136A8019DBBD7BAD /* GULReachabilityChecker+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 02E579CAD373BBD07CA64034DF8027D3 /* FIRStorageConstants_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AC60B43FA6D28BB9A4A8E7ED8F591134 /* FIRStorageConstants_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 03AA8E00CA6CF9C1D534409AAEA8248A /* FIRStorageListTask.m in Sources */ = {isa = PBXBuildFile; fileRef = A2A97AE7647179E52903F372F44D6340 /* FIRStorageListTask.m */; }; + 0485D0FEC1E223F80D6BD9D354594836 /* firebasecore.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = EC150F4FD984963E187F5A3AA42C98C9 /* firebasecore.nanopb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 04888C1575F74E2D46652037037EA1CB /* FBLPromise+Timeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 8151357CD1DF92DA0968F4263590737C /* FBLPromise+Timeout.h */; }; + 0618A0B20B54F52088A0AB9C34D7DC99 /* FSyncPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 84DF235307E2195AC3E126915E5737F5 /* FSyncPoint.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 070E3339AECA7C5674B8B54564DD73ED /* dumpfile.h in Headers */ = {isa = PBXBuildFile; fileRef = B2D4F7FF0ED7AEDB99891B0C005224EB /* dumpfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 072110AA280A13A773C874AA79460241 /* thread_annotations.h in Headers */ = {isa = PBXBuildFile; fileRef = 24E7AED0E578075903339C2F3EFEEDCE /* thread_annotations.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0732D22C3FDE4D4294A9CAEA66F17E75 /* FBLPromise+Any.m in Sources */ = {isa = PBXBuildFile; fileRef = DFF58064766E5A66920C1C0D4C244C58 /* FBLPromise+Any.m */; }; + 07578FB392C497B667C42371F502D4BB /* FCachePolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A18CD9744D0EA0AD2406244414CF334 /* FCachePolicy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 07D22076FA861D0AA49401ED247A611B /* FListenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A6652E2684D336D22085F48B522BF60 /* FListenProvider.m */; }; + 082631C7BB8433F196DAE1B3B9ED2051 /* env_windows_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = CF1CF114DF0F9CB07BF12F9C39F293E8 /* env_windows_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 083769BEEFB26C5A674C30D07FF86B1D /* FChildrenNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 61F577D9F788CAFE7BAA2EA673AC2037 /* FChildrenNode.m */; }; + 0881B956B8D20DD2A321A5CC092BE414 /* FIRBundleUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 120A6866016396AA3B307F0F69751349 /* FIRBundleUtil.m */; }; + 08BD0585E5A36731DE2DF3AF02C1F1BC /* GULNetwork.h in Headers */ = {isa = PBXBuildFile; fileRef = E147ED0EDA24CB6101C7523658C4287B /* GULNetwork.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 08CDB376EECD2693BEE23F7CE0D80151 /* FTupleStringNode.h in Headers */ = {isa = PBXBuildFile; fileRef = FFBEFCD078D6A76273D277223110B3D5 /* FTupleStringNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 08E13FE7C0331833F8C5BD5B8A07E338 /* FIRTransactionResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D7DB9E6A2C35C869B3D55E0C1488F2D /* FIRTransactionResult.m */; }; + 093D16634CD5F0D9BC5DFDA279B7BA51 /* FIRInstallationsStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 923F5208B9B8E8112E5376E4979EEA33 /* FIRInstallationsStore.m */; }; + 0A0051BFB3DDD86CB50D8111BF720E92 /* testutil.h in Headers */ = {isa = PBXBuildFile; fileRef = E04256A559431B024EAFE17349932DB7 /* testutil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0AB7B1835610DA780A74F7498821442A /* version_set.h in Headers */ = {isa = PBXBuildFile; fileRef = 505C1A8D2A956C3FF8FA6D699EB4A581 /* version_set.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0AE086F148587D4383DC19E9E74F0903 /* GDTCCTNanopbHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 0489E9C92A381651A399F3201AA11690 /* GDTCCTNanopbHelpers.m */; }; + 0AEBFA834735E8579CAC2EB3ACF6D99C /* GULReachabilityMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 357BB6787D118D45F0E266C2F542034B /* GULReachabilityMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0B73D00819088DBCA387F8746897CEAA /* FIRStorageGetDownloadURLTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A462BED47E045F027B03735EEBDFFF1 /* FIRStorageGetDownloadURLTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0BCD424C49808AB562C7829839B02CEB /* FIRStorageMetadata_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 27F5B2B2A72A0F52C3D43E4B64D2AFE9 /* FIRStorageMetadata_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0C2659EFC2C3CA756799555B3328CEAD /* FIRStorageUploadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 28CE8ECC4C7F8A3887EBB85CD1B873A8 /* FIRStorageUploadTask.m */; }; + 0C63314596A323C37290FF4DB6A013ED /* FTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5F1AAD2D2CFDCF6A5B824D5A886C1CD2 /* FTreeNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0CFD4F9A80FE920A92C46ED090AF8ECA /* FTupleCallbackStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = B8E8E3D1874DBA689E9ABB2098726F79 /* FTupleCallbackStatus.m */; }; + 0D35668137C9AA24B5FA0D7704E66D5A /* FAtomicNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = C809DE63B19C8CBD6601AD4374B3033F /* FAtomicNumber.m */; }; + 0D634D41D845B84BA0F917AC310AA0A1 /* FTupleCallbackStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = A3E75433084553833D078D8157B97071 /* FTupleCallbackStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0DC20D18348E15F68BA7C9DDEF0688E2 /* FCompleteChildSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 26AF78DA83D9E020289D43F83EFF9A8E /* FCompleteChildSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E1E3057EF6B378D07627A39E872528A /* FIRInstanceIDTokenOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 19EDA0A14684A68E5E6E03FE91AEEAF6 /* FIRInstanceIDTokenOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0E2CAB550C7C03046C52A839DF6EC0CE /* FIRInstanceIDKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = 93588089D0F50EF58C900EDDED947082 /* FIRInstanceIDKeychain.m */; }; + 0E98FAFC4AEF3E2FB107970B36F82F6D /* log_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3BA3B39AD51B46E55E3A6A609CBC8E7B /* log_writer.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 0F8C7E276F025666C37CA0CECAC3F000 /* pb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BA5379813ED95F892512A874565DB18 /* pb_common.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0FC9CB243D972863E886EA91F49D3671 /* FTupleObjectNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 02B9220BF322F27318370B8242BCAFFD /* FTupleObjectNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0FCD61B46D9E94F0A608F553C4B40C73 /* FUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 9304301663FF641F230B41BD66C1231F /* FUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 0FE7F31E7E8B2FAE647345833AEFD58B /* FViewCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF1ADD915E44D639B021AE569D35711 /* FViewCache.m */; }; + 0FFDA2E9E380E2D537CAB57AB1D73833 /* FIRLibrary.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BBE4090EA3B9932677701AF91974C67 /* FIRLibrary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 102E4DC6BEF70142E938F9FFDB50C4B3 /* GDTCORTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 97E3FCCAF2E02AF6ECBD79CFF27F1C32 /* GDTCORTransport.m */; }; + 103B71ABACD6856EA53DA7B7D89E0186 /* FArraySortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = AC59DA87CAFC56215715B1ED2B850470 /* FArraySortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 104B54D07959A075405C7A9184CD2A08 /* FIRComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = D1EC4B9C46DFC905A56E0EB7306005D6 /* FIRComponent.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 10DDD967508DB60F26789B27F9FE68C6 /* FIRStorageDownloadTask.m in Sources */ = {isa = PBXBuildFile; fileRef = B9B32050A70491C586A91F247F294DB7 /* FIRStorageDownloadTask.m */; }; + 10E54E6E5596E34B158C9BAEF9553614 /* FChildEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 805E27E72E56B05291C95F20340F6635 /* FChildEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 10F4529D16EC386BC7B854710B376B8D /* GULHeartbeatDateStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E03362CBA1953F1EE9640B25411BED8 /* GULHeartbeatDateStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 111AFF732CA09A146E987DFA8A37D8E6 /* FRepoManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D38174AAFD5096B52D9FFE2771D0112 /* FRepoManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 11E8D925C1958F799B64BF74CD1E4FC3 /* FIRTransactionResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 4507041848E941A730652DCB9C6775E4 /* FIRTransactionResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1234B5B2DE0C98E5482BCF2B10FC2C52 /* GULSceneDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = A5F49AB94F002497A53AFCEAFB1FD6C7 /* GULSceneDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 130A90BC2E5A25B77F82E084845F6A37 /* GDTCORConsoleLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = F9555000E6E1599039D9EBA4786F57AE /* GDTCORConsoleLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1330FEAA85B79B7328C5EBC2B984A0BE /* FIRAnalyticsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = AC876BD753D740DFC24D59EE46909C72 /* FIRAnalyticsConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 1359391BAB507E711118506EEA347792 /* GDTCORAssert.m in Sources */ = {isa = PBXBuildFile; fileRef = 8357EDEAA0A8963A7A21EBFAC6DA743E /* GDTCORAssert.m */; }; + 135EF8179570BC83487189BC312B1CBD /* FEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = D0F4533B0FF71752214FFD4B62FF2878 /* FEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 139C36EBECD414E6E83E09A7CA235723 /* GDTCORPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = C7E966DF9D6827BA4FDAC1BF918F69E2 /* GDTCORPrioritizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 13BB66DF5376B6E63B7E853B990A138E /* GoogleDataTransportCCTSupport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A5BF35B8BA91663594BBF5352762EB54 /* GoogleDataTransportCCTSupport-dummy.m */; }; + 13C7B63FBBEE3E94D53258ED8F64F1F2 /* FKeepSyncedEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CBA2F623E71DEDC84E9B69EE321EAF7 /* FKeepSyncedEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 142699BB466888EC9B27EFB78553EE7D /* FIRAnalyticsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 13695C66BA611111420DD884C0C70123 /* FIRAnalyticsConfiguration.m */; }; + 14421D05135873CE794E99DF30AF1720 /* FImmutableSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = DCE0EA688C9DF641CB79FF48F8739F46 /* FImmutableSortedDictionary.m */; }; + 1467E275A257119254198B74EC96371C /* GDTCCTPrioritizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D0233BAEAA67BC6CA1D33848C2D0B0E /* GDTCCTPrioritizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14858254AE33D7911341C466A1F39CB5 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = DD0768EA430D4B40783B1367C205D0E6 /* FIRInstanceIDCheckinPreferences+Internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 14DAC046DD9EAC4548374C3EA28B3C47 /* FPathIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = EB66CFB1B78584AFE3578475D2046904 /* FPathIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 15A989DB253C7765136C1BF9645EB553 /* GDTCCTUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EDD66CDFCF74C4E949499D9C55DC80B /* GDTCCTUploader.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 166567686120393ADD2E2058177C7900 /* FIRStorageDownloadTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 53BE173D71059143D61695D5A4F056C0 /* FIRStorageDownloadTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 171830EFC97DEC7EE70B0C57EC31F4C5 /* FIRStorageListResult.m in Sources */ = {isa = PBXBuildFile; fileRef = C23D9EF2FABCE6C06BB74403C7E0FF09 /* FIRStorageListResult.m */; }; + 17B3E5E8B357C3D8170E11F8661EE6D2 /* FWriteTree.h in Headers */ = {isa = PBXBuildFile; fileRef = E11E2FAA9EC9301A1722BBBF7781DBE9 /* FWriteTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 17ED47B565E13B2E74FD5B9EFC551648 /* FValueEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D03DB7135783EFF5869EED8E463C2F3 /* FValueEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 189886B026180FF0F90DA01FF72F844A /* FIRInstallationsIDController.h in Headers */ = {isa = PBXBuildFile; fileRef = F75F9105694B168C0EFBBA4713124CC5 /* FIRInstallationsIDController.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1900A31A09DBAD658619229902EA43AB /* FTupleUserCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = BDF0C9F93532C7101C7CB69E2867EC6B /* FTupleUserCallback.m */; }; + 1937D86D43A9560AD0794EC916807251 /* FIRInstanceIDTokenDeleteOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C4ADE903728E190BA0EE2D6BF297FB07 /* FIRInstanceIDTokenDeleteOperation.m */; }; + 196A5C196E931158F2688B37E9DF1636 /* FBLPromise+Async.m in Sources */ = {isa = PBXBuildFile; fileRef = D760272F98CD0831968339D53400681F /* FBLPromise+Async.m */; }; + 1980307895FA65A21D31BC6389B3BEC3 /* FIRComponentContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = A92253B0A83EB13072622A5C886F1162 /* FIRComponentContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 19D72AF22467A9FBD6E3FB59ADA49C22 /* FIRInstallationsHTTPError.h in Headers */ = {isa = PBXBuildFile; fileRef = B62D960DC80DC12623B220EA85CD926B /* FIRInstallationsHTTPError.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1A0DCB6073A15A19D74843765F0E7DEA /* FEventEmitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 004545246F93039319DCDA7ABAA016A1 /* FEventEmitter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1AB9186FB7FDEC77E769537F55D0AD15 /* FIRInstallationsAuthTokenResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7661DE9A527D6B176752AAFDF7C1E0A4 /* FIRInstallationsAuthTokenResultInternal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1B03F07008EE89B438D451D5B714A322 /* FIRConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 9226C7EFCB8792B87686A9B3CCF32F26 /* FIRConfiguration.m */; }; + 1B0D9DCD481F94F72089297BA93C6B67 /* FIRInstanceIDBackupExcludedPlist.m in Sources */ = {isa = PBXBuildFile; fileRef = 72AD7602E5FEDA3830584CA043EB7F4C /* FIRInstanceIDBackupExcludedPlist.m */; }; + 1B5A6CABFFE529DCE886DC13EFAC75C8 /* pb.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C2DF7D088303A95D61EE4E40773F52 /* pb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1B818DAFB27BFE8532E60E85BEC640EE /* filter_policy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 114EC166893B4C60D76A1917530AF647 /* filter_policy.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1C8F050A8A53777613A0A58D5C229155 /* GULSceneDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = A9E80D2D264051242FAAC6384CA1ED2D /* GULSceneDelegateSwizzler.m */; }; + 1CE1F53F5FF5F137ADAC6B7B923FAC6F /* GULAppDelegateSwizzler_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 596E00795348CC02B5DA56B1BCC7C88E /* GULAppDelegateSwizzler_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1D311F38B7A23ED9154B53473F1F649D /* FIndexedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = EDE4E8B5C0D67DC87A1CD2751C80E135 /* FIndexedFilter.m */; }; + 1DD28C450CEEB1E0BD4BF464397FB8F5 /* FImmutableSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 782084FA99F3F0AA7F176FA5363CDCC7 /* FImmutableSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1E508D43C3526EDD5157BE901D816438 /* FIRInstanceIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = CB9C8BA79F404A632E12BFD15164FFE0 /* FIRInstanceIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1E6D3B25EB193CACD277F7F545DD37C1 /* FirebaseInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 248334110F3275218F717022DE49A024 /* FirebaseInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1E7F94DC9E3ACF6E735E9A4F1A8DB008 /* bloom.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7FA6113A1FB0835D3542880DB4C2C78B /* bloom.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1F0D0D927D9E205B8A23118A5600D6E3 /* fbase64.h in Headers */ = {isa = PBXBuildFile; fileRef = E9A6FBFCCF1F2E924CB0619DD122C7C4 /* fbase64.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1F2B25E18DC5A01F6CA6BF22117177D7 /* FBLPromisePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = ECACF7849D7CAC8D64FB070D76863651 /* FBLPromisePrivate.h */; }; + 1F3AD4EC227982AC02B7974EAAAFAC02 /* FMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB170657617FFA0F073315570B8F945 /* FMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 1F509E54D03B15D90FD2699E7B69F858 /* FIRInstanceIDTokenOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5EDB4E35C2E12DAC6223E2BCD17CFD54 /* FIRInstanceIDTokenOperation.m */; }; + 1F586133C4EB98DE288A2A66763DC9D9 /* FTupleObjectNode.m in Sources */ = {isa = PBXBuildFile; fileRef = C0E2C72E350099611A032C30D9E97D46 /* FTupleObjectNode.m */; }; + 1F8513A8A40A6C81E0158C6F1C9C2A7A /* export.h in Headers */ = {isa = PBXBuildFile; fileRef = B0CC945D6C82F1429CCFA0460131A4E3 /* export.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F9AAE2958DC0F59836F2FCA9EB170BF /* FIRInstallationsItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AE4E4E587A9E312162D01C3498442C1 /* FIRInstallationsItem.m */; }; + 1FE6D486D2DA7BDDF9D44F4F747CE838 /* FBLPromise+Always.h in Headers */ = {isa = PBXBuildFile; fileRef = C883E313B32C196FA849B2E308CF1812 /* FBLPromise+Always.h */; }; + 209C6C81908CB62A4AED0C06E234C0C7 /* FIRDatabaseQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DF96CD59FB20F67464B5372DD87EB2D /* FIRDatabaseQuery.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 20AC7BF2996FC3FB7EAFA0AE6F439DF2 /* GDTCORStorage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAED39340F04B8544FC496CFCF1EADCC /* GDTCORStorage_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 20C917F80DD977810A0B54FD24EC50B2 /* FLLRBValueNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BD1B051942ADDA047D2B87D13FBA2954 /* FLLRBValueNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 21138158A15A5007967102D506444F67 /* FIRInstallationsErrorUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = F49FDE10DC964A182BD8D6BF72E56F64 /* FIRInstallationsErrorUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 21A0EA0EB2E7348BA2EAD78CCDE9577D /* FirebaseCore-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 08F10222301531C836C3CE7358FAF158 /* FirebaseCore-dummy.m */; }; + 21A4C63ABD0FA527DA121AC249C5A7AC /* table.h in Headers */ = {isa = PBXBuildFile; fileRef = CE14B460E98E60C8B07474C59D604D04 /* table.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 21E747E5978CE879441249FE60948F03 /* FIRInstanceIDConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = F8EBCF41CD843B76AEFF4A01DF812CF8 /* FIRInstanceIDConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 224E1BC8E9A46104F316606FD03055F6 /* FIRErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 8D79F1C1C537FF4B030110EC6A6A0E3D /* FIRErrors.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 22DF9946B451F1077BCACEEEF6876E75 /* GDTCCTPrioritizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 79F3DEB203D9A6D3538745CB46A6B6BE /* GDTCCTPrioritizer.m */; }; + 23623AC88B05692373ABCAFC5D55D595 /* FBLPromise+Wrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 8931E783ED057317826553414CE66BF4 /* FBLPromise+Wrap.h */; }; + 23C2F747D08DC06216A44A74566B03E5 /* GULLoggerCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A8E64F1793145DD60F66ECDFBFB4458 /* GULLoggerCodes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 23E6C4D752655CD446CC374BCCBD4339 /* GDTCORTargets.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E37890FCB2C3ABF59FA19621429FEC8 /* GDTCORTargets.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2450E43216ABE26BB815CEBAC3EDE2C0 /* FirebaseInstallations-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E5B60F06DA7799B681DAF0B1D2005CE /* FirebaseInstallations-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 24FA01B81F00742983794A0AC9163FA9 /* FStringUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 887E36B3DBCD3FE4AC51137704580907 /* FStringUtilities.m */; }; + 253A920BEB214305408903AB0189C6BB /* FIRStorageTokenAuthorizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 88629EDEAC20BEE6D9706C0D1683C65A /* FIRStorageTokenAuthorizer.m */; }; + 2558F4F5D4FECE3F6558FFA5DC2F89CD /* GULSceneDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 75967CE2C51C3463D72B9F051DAE5A38 /* GULSceneDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 257A76BC89A5C8BA63DE013722BEA0EA /* FCachePolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AEA2494228A798570ADA4BA569AAD3D /* FCachePolicy.m */; }; + 25B7246C2ECD86917341CCDA10E7FD2B /* no_destructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 8853FCD9B54090977DA47CDC4CE1BE96 /* no_destructor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 26A44D084033DEE3774091F0FDB79F92 /* FIRInstanceIDAuthService.h in Headers */ = {isa = PBXBuildFile; fileRef = 33BEA7F632D48EFB31127984359A7D0D /* FIRInstanceIDAuthService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 26A62904906424401425EBA3464DB4FB /* FIRInstanceIDTokenFetchOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 642DB2182537105AE858C3B8BD03C98A /* FIRInstanceIDTokenFetchOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 26C6CC2CC4472E8A89EC34D66DB59404 /* GoogleDataTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A99DFD371A5473D820867DF4D748DEF /* GoogleDataTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2736216E519666F7310B417759A98AC8 /* FirebaseInstallations-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 933460CA2E165B422AB65FD22F461DC0 /* FirebaseInstallations-dummy.m */; }; + 27655880FB0469AAEF29271BE07CCE25 /* GTMSessionFetcher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F54CE05621F4425787E29C0CEBF58EC3 /* GTMSessionFetcher-dummy.m */; }; + 27BF2DD3CD0D923211654994F172B6C4 /* FIRDatabaseConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = B1EBAFAAEA3B7B4B663AE6FF460AA209 /* FIRDatabaseConfig.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 280200E7B69674B99F7932BDFD44EF34 /* FCompoundWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 58CC0D44AC060ACEC0D534668FA1A8E7 /* FCompoundWrite.m */; }; + 28B5DC913E77AB95727AAC7901F85043 /* FIRDatabaseQuery_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A78F28BB6A74CF05958DCF007498954 /* FIRDatabaseQuery_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 292269F67F53E8DE948D5F59623A2547 /* FMaxNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D7B8E85F15B91F2BE7228170D267A72 /* FMaxNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2927A43C382BB970274A35157220EF55 /* PromisesObjC-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 288371F32354A7A2D02E6D211872D6C0 /* PromisesObjC-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 29B6B6CF40BBB25B0125619030D686A5 /* FIRInstanceIDTokenManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F1E35600A76731626B0A9B4A65F4FECD /* FIRInstanceIDTokenManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2A0D2FAC556850D1B71AE2236FBA3DF9 /* FBLPromise+Reduce.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B79E46D2F75EC32EFDC026DBC054C0B /* FBLPromise+Reduce.m */; }; + 2A25C6113AF53711F1BCAEEA92ED51A6 /* log_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9078AF964D68A97418B2A5520D4F95F3 /* log_writer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2B26CAD0907DB48C814785DC142CB23F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 2B8D8668C774CF9751826B5E5DAAF449 /* FIRStorageObservableTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6C6B82976BE98D85A276818786669979 /* FIRStorageObservableTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C2C69EBEBBEFDFC9AA4E8162CAF8837 /* format.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1FB1649F83A4B89E0BAFC3DF429C1CDD /* format.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 2C403D26D56AB4E4F3ADF6F5B34B3B93 /* FIRInstanceIDDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = D90E6343DA880305944FEEC32E0536F5 /* FIRInstanceIDDefines.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2C4910AD5EBA5BBFD3E42C2B2EB8C377 /* FIRInstanceIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FBF2FCB4B59F5862D91B4604A5180ED /* FIRInstanceIDTokenStore.m */; }; + 2CDE72E87C681B0410BE868E185CAC7E /* cct.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = 92E0699CC8C007B776F78978059335C0 /* cct.nanopb.c */; }; + 2D06159D0C5265DD9B03C4581E775EA1 /* FTupleObjects.h in Headers */ = {isa = PBXBuildFile; fileRef = B712425379B4E7BFDB5FAB86EABCBEEA /* FTupleObjects.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2DD892913137E6A24A430719D3DE4858 /* FirebaseStorage-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CC0DCC8D797EF0765CF6FB77E762DA91 /* FirebaseStorage-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2DDFE0D16169C642D9133AFEDE7C69A9 /* FTupleTSN.h in Headers */ = {isa = PBXBuildFile; fileRef = D3540C0CCBE5B51413625FE4BE262F06 /* FTupleTSN.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2DF33B70B48CB3417592B1DF55646C03 /* FBLPromise+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = 709376BC4C402E261D56E950EEF1F71B /* FBLPromise+Testing.m */; }; + 2E331C59A64D9A95EE752F403C6DDC90 /* FIRStorageTaskSnapshot_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B5993ED6459C75C852370192D89E609A /* FIRStorageTaskSnapshot_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2E588B234A541C10B722D4B202171008 /* FIRAppAssociationRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F72A7C87673FA30B1B60FBE587CE6F7 /* FIRAppAssociationRegistration.m */; }; + 2F2F02E72BBE8400C31CA1DFF6E1009B /* FLLRBEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 12F5D011A000BAC69522947792FBF47F /* FLLRBEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 30880DC7962C6AA2C76F741A56A08BC5 /* FRangedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C53D964DD593409B7EDF149D2D09939 /* FRangedFilter.m */; }; + 30D072B1E1EA4B0C52DBEC86815C4546 /* status.h in Headers */ = {isa = PBXBuildFile; fileRef = 6944123B6B8C495EEB39ED65A920FF22 /* status.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 30DB119E7230E8DBC74B69ADB8A15238 /* FAtomicNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = BA66AD23BE6F4FA5FB56166743AF197B /* FAtomicNumber.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 312389C2BA9484DD3CA5FB97B5CF125A /* GDTCORDataFuture.h in Headers */ = {isa = PBXBuildFile; fileRef = EF6B5B884808EE33F3AE364E1A8D7058 /* GDTCORDataFuture.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 315136729DD55A92945D3852BDFFD1A6 /* GDTCORStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B1E2BCB035B1D3DC3D62CBD00650324 /* GDTCORStorage.m */; }; + 3216257623D8E40F5E98540AB3C6B09E /* FIRInstanceIDCheckinService.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F3FF41C7805A4DA98244AEF7CC226C3 /* FIRInstanceIDCheckinService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3297CD4971460E07997D3868D23B484E /* GULApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 057F8B6F54F1827EA608534EE8AE4208 /* GULApplication.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 32AAD116A411C310EA4C466B1034441C /* FBLPromise+Async.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = D4F7B7D12CD2AB5F4DA44ADE285B89A3 /* FBLPromise+Async.h */; }; + 32C50B96E226768D3B378336BAEFBB22 /* write_batch.cc in Sources */ = {isa = PBXBuildFile; fileRef = D02507890F4001343580522441E85F51 /* write_batch.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 32C529A1A254C52805E2BE8817065A28 /* FIRDatabaseReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B934CF29FE5CD666ED5FEB4184D4D0E /* FIRDatabaseReference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 332EA8B301C28DD67ACCCCFE9C301BCD /* GDTCORAssert.h in Headers */ = {isa = PBXBuildFile; fileRef = D15D6F80E8028925AB24321AFD3ADB9D /* GDTCORAssert.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 33535514510048650EFFF474494C9CBB /* GTMSessionFetcherLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 429F8F88B08A830D3F8C419F57124FC0 /* GTMSessionFetcherLogging.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 33587E54E4FFBF9937C9514CBD2C2ADB /* FIRHeartbeatInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 6721CA9F38C56DD1FED43D3ADA7A6D2B /* FIRHeartbeatInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3362488F496054F89AA6F18A09C54436 /* FIRDependency.m in Sources */ = {isa = PBXBuildFile; fileRef = D30A603A1AF1B8113D6B28B35BB1685C /* FIRDependency.m */; }; + 3383C8F20A10A76713EF355800DF4ACA /* FPriorityIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = A9EC9ED037C6087A02E7502A11DB4B44 /* FPriorityIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 345084C0B8D05AC602644235063E246A /* GDTCORTransport_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C15F1AE465F68C48C5F2AC5D6A1AD58B /* GDTCORTransport_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 346676A559DE3D4AA6505253006AF77B /* FIRDatabaseConfig_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7F502C86D58BBC8320F07C65EFEB0D65 /* FIRDatabaseConfig_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 358009462CC96D360C81CDAA2A19551E /* c.cc in Sources */ = {isa = PBXBuildFile; fileRef = EE8661EE9163CB9D35ADAEA97516FE8B /* c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 3580F08EEC9D7B182B8D3C2C7AEB5F53 /* FIRDataSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 7C5330642B43535CB64DF4DEB6A008A7 /* FIRDataSnapshot.m */; }; + 3581AD2D8C42D39B9E8B27FA7E09FDA5 /* FIRStoragePath.m in Sources */ = {isa = PBXBuildFile; fileRef = EF027EB6EC10790B2A23AC612C1FB6DA /* FIRStoragePath.m */; }; + 3696262C419108CACCDD9678138D4E2C /* FNextPushId.m in Sources */ = {isa = PBXBuildFile; fileRef = FC70AFB7FD9A61A5D9A481E9F24F1AD3 /* FNextPushId.m */; }; + 373188ECD2445ECE3D2E5A0758A0C6FA /* FIRStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A1564C52DDFB1957E792196332B66A9 /* FIRStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 37529E7A194E25957F44BAFB08422BF9 /* FTypedefs_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4F315F3C9A54FD6665C263FE3FE692 /* FTypedefs_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 37768774C8955B8BCB1239F4B8207779 /* FEventRaiser.h in Headers */ = {isa = PBXBuildFile; fileRef = F2F1F22644685D1B297E9BC3110FF0A3 /* FEventRaiser.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 37CFB19C20CA92E610E2A648E8E0A554 /* FIRComponentType.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B4900A12B99435B7C2DBC1A20FA5194 /* FIRComponentType.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 37D9C520623CF08EB5C51D9F4EC644C9 /* GDTCORPlatform.h in Headers */ = {isa = PBXBuildFile; fileRef = EF8F20248E90A517FA3C288D99992F53 /* GDTCORPlatform.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 38BB0158ED998278F61583309B1512A4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */; }; + 38C7DD9B9C431DFE0F2B0A5D77EF7CEA /* FIRInstanceIDAPNSInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = A3E39E8101A41A91A2C935F98E570B0D /* FIRInstanceIDAPNSInfo.m */; }; + 38E416BDCA44F349F2293244CBB090C3 /* GULNetworkURLSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 13D8301FC7F37CB3A191D1FCF00126C2 /* GULNetworkURLSession.m */; }; + 398105E314BE7A83BC79BA999C80DF87 /* FBLPromise+Recover.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FAF5018229925BF08F2CB786CCE90A5 /* FBLPromise+Recover.m */; }; + 3A1A8267A6DF125D7BCE2D342F1D1571 /* FirebaseCore-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 81B7215BC7FAD9F6EA89A037D4450CE0 /* FirebaseCore-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3A2588C2516C334C381160C8F7CF6C02 /* GDTCORLifecycle.m in Sources */ = {isa = PBXBuildFile; fileRef = 844DBAFA06AA17E01947CC83D557C229 /* GDTCORLifecycle.m */; }; + 3A39684C35F7AAA1639553E02FAE319C /* GULNetworkURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = C91AB5BA273E41BEE728337BDEABA5C7 /* GULNetworkURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3A4609CC6E45B5244A0745948E944C6D /* GULSecureCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 16D2CB4D08C7DF2EE66A293C0D99EFD0 /* GULSecureCoding.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3A464EE1239B1FABEE1C1C95D22D602C /* FIRComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 713848D338963B5826A36B0526691EE8 /* FIRComponent.m */; }; + 3A863D0820C600D6EDB165471E932A61 /* APLevelDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D8978C2B9BC0CE887AF50290BB35F7F /* APLevelDB.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3AA904AC1AC07C74C35566D77E88B8C1 /* builder.h in Headers */ = {isa = PBXBuildFile; fileRef = F955BEF204ED310BC614813D9D710DC3 /* builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3AE1866EB63A6C5123188B3247410DB1 /* block_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = D8061BD1CFDE7004EC0A4E0E19DCF6DC /* block_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 3AF083A6E1147C2A01BFD01146472601 /* GULNetworkMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C4835B62590F9B75776B27FA8D95579 /* GULNetworkMessageCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3BA56169E7AB7512E4C89D0B47834A57 /* FTupleRemovedQueriesEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D74B536712C66F3158E15B064EE90C1 /* FTupleRemovedQueriesEvents.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C0EA007E5F899CAE00A0EF83B9CAA39 /* FOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A46F2DCE1834AD1C9950A85E7A8A6CE /* FOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3C3ED24D6617734394DC42AFDD9416B0 /* FSRWebSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = F80CF052FA0620A9B8D80C1A367E7F5E /* FSRWebSocket.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3CA6B5EF1BAB325870F6A25AEB4F900D /* FPruneForest.m in Sources */ = {isa = PBXBuildFile; fileRef = 54BBDDB60CC332B9CB959B5E4B403CCF /* FPruneForest.m */; }; + 3D277E51CC2EC71690121326D17C4A2A /* FIRInstanceIDCheckinService.m in Sources */ = {isa = PBXBuildFile; fileRef = ED7E3BD4AABE613AC52785257A0E89E6 /* FIRInstanceIDCheckinService.m */; }; + 3D7CEDF8484D204F3F1CF919657AB034 /* env.h in Headers */ = {isa = PBXBuildFile; fileRef = 0902E4607D9246B44AFA3EDCD2FDCE51 /* env.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3D94213C2542294E0672EF0F2F0A4B35 /* FIRStorageMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 3345F327E7A52648AAE06E3C6F9D1929 /* FIRStorageMetadata.m */; }; + 3E16306F9748D0D18B338CC4734EB2D7 /* cct.nanopb.h in Headers */ = {isa = PBXBuildFile; fileRef = 1096D1DBCB98AE4385176B1D98D0D4D1 /* cct.nanopb.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3ECF1A24ADBC31B4997C5636A5AAF429 /* PromisesObjC-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = BE42B997AA83C8CA9F70E16204BDC654 /* PromisesObjC-dummy.m */; }; + 3F7F40A4E72679DFFADB6A15450889BB /* GDTCCTUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C77A25EF19821D402BAE78598EA5361 /* GDTCCTUploader.m */; }; + 4033DFF8E46CBFFA88DBF899FB5E492B /* FIRStorageConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 610BC07F3FD1BBBB5175FAD2234EEF62 /* FIRStorageConstants.m */; }; + 4076E700A4E56EA44F916A6EB5B38A84 /* two_level_iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3FAFB71A7764BCD006424B153CB958B6 /* two_level_iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 408E7890B97BFBE9E46C9442755E4F64 /* firebasecore.nanopb.c in Sources */ = {isa = PBXBuildFile; fileRef = 6FA32E4E626458BC0248B40BCAED895C /* firebasecore.nanopb.c */; }; + 40E86DB8ADFE08A02B465C68DC01480C /* FIRDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 865B4435A179E8D322EEB8594A18DFAD /* FIRDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4155F20106954F206FDF73C397087801 /* FIRErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 77BC895560CE00DAEB6A086A1CDEAEDA /* FIRErrors.m */; }; + 419D3C01D1B29563FFBA8B2314634835 /* FBLPromise+All.h in Headers */ = {isa = PBXBuildFile; fileRef = 0B0E05A5A7593B41D7DA14F11FF6330C /* FBLPromise+All.h */; }; + 41AAAF78EC837E65D5B3C48EEFB67C31 /* FKeepSyncedEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = B978BE12FBC5DB5499497CF643032AE7 /* FKeepSyncedEventRegistration.m */; }; + 4295EE4125B59C180ABF75BB9612E88B /* GULLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = 3455F9C221E70B76D67B1E8DAA70A45A /* GULLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 437562A81373610965061FB53F6EACEB /* FBLPromise.m in Sources */ = {isa = PBXBuildFile; fileRef = E27C8AA3E91D56F81055B51152E93C5C /* FBLPromise.m */; }; + 43C6AB676FED45667A7CE48AEAD59348 /* FIRInstanceIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B76679FD290C6916E68E4A74C44F5BB /* FIRInstanceIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 44EFB4D00D62857239E5571903BD9164 /* FirebaseInstanceID-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 850CBF344E1BD1CF84B5206F0E4F3AA6 /* FirebaseInstanceID-dummy.m */; }; + 44FA484BDB5493766E852DD68943A34A /* FIRInstanceIDCombinedHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E238A56E9E62DC870959BDB148BFCE6C /* FIRInstanceIDCombinedHandler.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 44FEB57BB9E17E89A76B8D124C9E1745 /* NSError+FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = 19C33078E1D0C7BF23A35F6D11FACB9C /* NSError+FIRInstanceID.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 45A6DAD4056F205353651CF50A58587D /* FIRInstanceIDAuthService.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AD2E9ECB85005226A653B4C97E2D639 /* FIRInstanceIDAuthService.m */; }; + 462B3DE471312B134D72A97157DBEA5A /* FIRStoragePath.h in Headers */ = {isa = PBXBuildFile; fileRef = 09BCB0749FF5FD9B5F63C2DDB97398DF /* FIRStoragePath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 464D0D77EE026481403D5C592D0396B1 /* fbase64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6A9D4B61A684DA305FA8367430CC9501 /* fbase64.c */; }; + 4666B09703FACB6EE3CA19D02AA31B04 /* FIRStorageGetMetadataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = E67C1D1A48982697C198AB692680D803 /* FIRStorageGetMetadataTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 46CEAFF362A5F1B66B456B9C235AD7F6 /* FIRInstallationsVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = A27D336247C06AEE085EF43CF6156864 /* FIRInstallationsVersion.m */; }; + 46FA556CA70DE477C3CE680860AF1D14 /* FBLPromise+Recover.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A776495F0C11B2D6E910717050FE201 /* FBLPromise+Recover.h */; }; + 47BA6C0FE17DF42A04CFF844FA404F4B /* FPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 8D58C1777E830172B31A330830F0C9F4 /* FPath.m */; }; + 47C8A20C53128BE5AED6082FA0A35709 /* FIRInstanceIDStringEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 0072A3F0BA7D1F7A27B20C82BFB6DFB3 /* FIRInstanceIDStringEncoding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 47F6067CC44AE06245E1882980711492 /* FBLPromise+Async.h in Headers */ = {isa = PBXBuildFile; fileRef = D4F7B7D12CD2AB5F4DA44ADE285B89A3 /* FBLPromise+Async.h */; }; + 47F67D7B3CF893A35D08A2B4A475D44C /* FIRInstanceIDTokenInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = C7D94DF9C10300D6FB71C8D9A931EB78 /* FIRInstanceIDTokenInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 48BD5B3CCD4213D84EC61120F70FFBC8 /* FIRInstallationsAuthTokenResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B2BC02CB066E06F4B11FD2D5F9B8573 /* FIRInstallationsAuthTokenResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4A1F808C2B87E169F70699304F10C40B /* FBLPromise+Await.h in Headers */ = {isa = PBXBuildFile; fileRef = 10CF2C664D0E815ED48EC7BAEB31578D /* FBLPromise+Await.h */; }; + 4A6047BD4714AA06F5964A0C2F904F08 /* FWebSocketConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 76F6CAA85B9481E77015FE98685F15E3 /* FWebSocketConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4AD4E46142AA949BE9AE25B792D61732 /* GULMutableDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = DE429484969950B4A6B5CE157A9B0853 /* GULMutableDictionary.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4AE57F500B1BBE13D09C4542EC268354 /* FBLPromise+Delay.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 2DD4AD8A942A3CD434EDBDFC70B5CAE8 /* FBLPromise+Delay.h */; }; + 4B744F7ECEDDE138738E97A0BF826C72 /* FIndexedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 96449186D538D5BB130663F9FE2A1F30 /* FIndexedNode.m */; }; + 4BFB521CC159F5F69B8261795EEAAB61 /* FBLPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = EABF0AF368631BBA0EBC6315F6B4144E /* FBLPromise.h */; }; + 4C21648C88ADCB2009437EB6C11D8121 /* FBLPromise+Await.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 10CF2C664D0E815ED48EC7BAEB31578D /* FBLPromise+Await.h */; }; + 4CA25B9F5EFA8065AC1646679E2B8E95 /* filename.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4F37B777FF7AF7050F952C1F7EDBEC58 /* filename.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 4CEC7F97E23B73C3EB8467874BDFA4D4 /* FBLPromise+Validate.m in Sources */ = {isa = PBXBuildFile; fileRef = ECE11C4938A2B72ABEBFEE62ED66BF8F /* FBLPromise+Validate.m */; }; + 4D1FEFA9C0A520FBE0C555B0CC66F51C /* windows_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 42BD5D5243A04F06CDD2CA2E9C329BC1 /* windows_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4D349EC94D9E84F85D21A857E3AABFE3 /* FTupleSetIdPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C411E83FCE8D78F920AF6FBCD474ACB /* FTupleSetIdPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4D4A8EBFB5A1691749D24D300F61A3FF /* GDTCORUploadCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = FDE03C5490F34BDF665841D50ADB48A5 /* GDTCORUploadCoordinator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4E70FCDE9B19C1D1B77CC230F816881C /* GULSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 99BE1790BA27F64B840314B5027E34B2 /* GULSwizzler.m */; }; + 4E967714328F78862492EEC7BA0FB0A1 /* GoogleDataTransport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = B36EC66A74944CD3B2D95D93B739EF06 /* GoogleDataTransport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4E9D1A1586ABD90707E0120057572B81 /* FIROptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 830B396C70A3D0C1AD07F7F579343658 /* FIROptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 4ED882A9E6B2980972E792D0CB139DBA /* FCompoundWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = E4828C39CC6E1566EEC841FEA1495EB9 /* FCompoundWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4EED550851389F3E8126BDE91CDE723C /* FIRNoopAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E4564C0D672A2920A1F8E2AD2506168 /* FIRNoopAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4F029724AC4AD29BFD402662CD6223EC /* FBLPromise+Validate.h in Headers */ = {isa = PBXBuildFile; fileRef = 54384F820C1941AB60BF900E4154CA50 /* FBLPromise+Validate.h */; }; + 4F5C04D804BE187A0EBCB200253AFFE0 /* FQueryParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FA6F619BDF7B5CDBF4A4639BA797B13 /* FQueryParams.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4F5F19C3307CBF09DE07A99B240FC8E8 /* FIRInstanceID.h in Headers */ = {isa = PBXBuildFile; fileRef = A9303EA8089F8772A23463AAFBEB9A1D /* FIRInstanceID.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4F63EAB5E4D8EB05103553ADFDBD156B /* FOperationSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 80CA19561A2817A212C0488DEA559C8B /* FOperationSource.m */; }; + 4FB6E5688CE1DEF10E5EF46A40D02D64 /* FBLPromise+All.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 0B0E05A5A7593B41D7DA14F11FF6330C /* FBLPromise+All.h */; }; + 4FCFEE1C2ADABAC43C06952EB87CBE6F /* FIRStorageReference_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E8FA1A885EFD41939BDF374FBA3EEDD /* FIRStorageReference_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4FE44DDB908484BEB2F890A5F1D0D8BC /* FRepo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CD81AAA2CDF7215DED4146B535ADC11 /* FRepo_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4FEA2D42A189500203A2670FD24927C7 /* FPathIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = CDAF96ED50A683983650B65E4986A78E /* FPathIndex.m */; }; + 501BE573E169967A986DDF9D4DD4ABBD /* FNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A301F01504541019F6CCFE316CB38D1 /* FNodeFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 51D81B007B74DF31D5A1A9C4173A539A /* FBLPromise+Always.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = C883E313B32C196FA849B2E308CF1812 /* FBLPromise+Always.h */; }; + 51D9D07F47519F2EBCD03E728DF5D90D /* slice.h in Headers */ = {isa = PBXBuildFile; fileRef = A3B4AC5B091751C2FEFA28BD2F610472 /* slice.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 51F66A667C160C6F4067FAB0C2475C74 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 52AB5FE12A66D9E4A69B672A70AA9B7B /* FViewProcessorResult.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA172D5E1D03619ED29BD779DB0ABCB /* FViewProcessorResult.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 53713E44B39E56DC4F2D913240EFA4BE /* FIRInstanceID_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 96EA9A40414062574AB929B056EEEEC8 /* FIRInstanceID_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5396B23C3E969FCB53609C6D08E46F57 /* FIRInstanceIDCheckinStore.m in Sources */ = {isa = PBXBuildFile; fileRef = C6F4380E9D8DEA36E07AF6214D0E0B97 /* FIRInstanceIDCheckinStore.m */; }; + 5400377357C674D5FBD88C009884C2E6 /* GDTCOREventTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B5C7C088DAC8E08B4C0ABE1D9D7F187 /* GDTCOREventTransformer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5426CFC847A5503F3DAD8883148156CC /* GDTCORReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = F3E0784D73B1A725557C578A0E0DE9F1 /* GDTCORReachability.m */; }; + 54BD58C6F92DE47237137A8131805FFE /* FIRStorageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D5513A2CF10850CFC7325CC68B0B83E /* FIRStorageUtils.m */; }; + 54BFFCB3A078A2B6CC5C701419EE2181 /* FClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 36266F0A667DE528AC3A3717E8619598 /* FClock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5523D52C1C9FF280A9221352558C19C9 /* FLimitedFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 72AD2864FE4085C639DB8DCEBC3129B0 /* FLimitedFilter.m */; }; + 55931DE141753FDAA067598C0048E5C0 /* nanopb-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A5D4B358001D3F084CB3C4CAE20B7C92 /* nanopb-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 55F0FB83F68D1E59A1050B6FC9CAAB19 /* FBLPromise+Delay.m in Sources */ = {isa = PBXBuildFile; fileRef = F77D63E559DFC813F4B3AAD2075AB8B0 /* FBLPromise+Delay.m */; }; + 572DE75BD68F3CC17AF5AD9FB0E93846 /* FIRInstallationsIDController.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DB1D9E61CF269224355B759C08644D /* FIRInstallationsIDController.m */; }; + 57A3883510AD776AC295A5DA2EDFD46F /* FIRInstallationsStoredItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 3045F5E31607213D2722DE71D476C435 /* FIRInstallationsStoredItem.m */; }; + 58213DBE6ECFAD53E9CEF8F02624B898 /* FBLPromise+Reduce.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = D628266F3DD667493EE2D5198C86BD0A /* FBLPromise+Reduce.h */; }; + 582EBE61A305FB0F81BC4840A62F9F51 /* FIRStorageDownloadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = C1225D1251AB40E186EA9E17BBEAAEAE /* FIRStorageDownloadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5866936362B3EE71506D896DE44AB839 /* GULMutableDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 22626DBD000812B98478D77E874B3DB6 /* GULMutableDictionary.m */; }; + 5896965A186A9A0D56E5A3985D44B3A1 /* FPendingPut.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D4F44ED2E2432E9E466D9C93573B02F /* FPendingPut.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 58F95D088D6DBB1ED47F5153F5FCE603 /* GDTCORReachability_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 66C7999CC47AE67D949C1766C0BF2CAA /* GDTCORReachability_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5973EF25A8342251F93D0386AFDA860C /* FDataEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D445E473C41D23773680E8C73E7723 /* FDataEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 59BE46AE30D313C3ADBAEE3D1F590AC7 /* FBLPromise+Reduce.h in Headers */ = {isa = PBXBuildFile; fileRef = D628266F3DD667493EE2D5198C86BD0A /* FBLPromise+Reduce.h */; }; + 5D44A6B990D07F835AD99E8A3E688B41 /* FTransformedEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = D1341BB202306F13B00265AF86B8F877 /* FTransformedEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5DA34F6E8304809F1A45C0807260E91E /* FAuthTokenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = CDEDD664B4945B5C3FFCC439EF5E91F7 /* FAuthTokenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5DB57E86935F4F06F66CD844CEDEED4D /* FBLPromise+Then.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9C60FD75C09F75F9F289419CC6EC3DBC /* FBLPromise+Then.h */; }; + 5DCD70562BD075983509DDA8DB876DF6 /* GDTCCTCompressionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1800C48AE5BA951A1284B03F4CE961EC /* GDTCCTCompressionHelper.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5E3A76525152956B8F0923A9A49AEC18 /* GULNSData+zlib.m in Sources */ = {isa = PBXBuildFile; fileRef = AB743D0C97C93EEEAB0DB0FE278337E2 /* GULNSData+zlib.m */; }; + 5E63FCAFBC2EDC9E57641148C54B1D38 /* FIRStorageGetMetadataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C346213450344E3B75189159433894A /* FIRStorageGetMetadataTask.m */; }; + 5EF8E17B00EEE8FBC71720B439F6F11C /* FRepoInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D331B9DF3258EB11BC34C9C24AD173 /* FRepoInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5F20EB1FE7759423C4F9F6E62F17957D /* FIRInstallationsItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 50EEA6FAE9C760AB7F5E302B5284F1CF /* FIRInstallationsItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5F4B5AFB5A71275C5A6D53829D36C6C0 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */; }; + 5F74BA54BC98A870C3D578726F47CEFA /* FIRInstanceIDTokenOperation+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = B0FFB14C614912059B869AA124CE1548 /* FIRInstanceIDTokenOperation+Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5F7F3C7F972AA9890E45308685FAC3DF /* FIRTransactionResult_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 82298B35EE4C04E3F2E48ADB974F83FC /* FIRTransactionResult_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 5F8AB02CF7EB58E470C8D0EAA6BAE948 /* FIRConfigurationInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = C5A1079708AAFDAB8F4F53D6660A3B1E /* FIRConfigurationInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 5FB7F6B417571F24C0A9137648949A3A /* histogram.cc in Sources */ = {isa = PBXBuildFile; fileRef = C2B014A14B7708A1DFC2279C43A94DF2 /* histogram.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6048CA58D8139DDD0235A6684C4AEDD5 /* FSyncPoint.m in Sources */ = {isa = PBXBuildFile; fileRef = 975C05758199E92BCDF7B8AEFA8DC5BC /* FSyncPoint.m */; }; + 6098BBAFCF135CA53AB68384EE9A0341 /* filename.h in Headers */ = {isa = PBXBuildFile; fileRef = AD62319FBDEE7FD684B7E6C057EA8BD0 /* filename.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 611280146682FF4A88AC71242A8D847B /* FBLPromise+Timeout.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D72AE006E38F62BE505E7BBF0C7EB9 /* FBLPromise+Timeout.m */; }; + 617C26FE86E7F5425C186DDC8DA00B15 /* cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = A0FBCE4F7720531AA7D93AE2CF179D0F /* cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6264181DB03AD90251373D451D9C4A9E /* dbformat.cc in Sources */ = {isa = PBXBuildFile; fileRef = 748D3B36EBC228F82613077FDE13692C /* dbformat.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 62CE493C8B6E576B498D90F1D68508AC /* FIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BEAA6AF83FDDCDCFCF2A22F215C51BC /* FIndex.m */; }; + 638E30974DFA78B0931036B0F02D633B /* FIRInstanceIDLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 29B7D1344D0B83EDA9B3133EB6C60D9D /* FIRInstanceIDLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 63AA601F2B6A0FD6D0D55CB4E5E5DC95 /* FCompoundHash.m in Sources */ = {isa = PBXBuildFile; fileRef = 3FE5BCB2204D5F18D2166F9985632680 /* FCompoundHash.m */; }; + 63AB79587BC1351662D4CB4E12D415A6 /* FTupleRemovedQueriesEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C8F76E68FA2494D6AF6EF791A7C30A9 /* FTupleRemovedQueriesEvents.m */; }; + 63AC718F66B67F519CECD7642CDA616B /* leveldb-library-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F3D3E03AB5F3B1F5C79EBFDB2B3E5B0D /* leveldb-library-dummy.m */; }; + 63F1625DCA8A82EDA22881FC7374292C /* write_batch_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = A727AE1575353CFF867D48C1919605D6 /* write_batch_internal.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 63FE55F9EA99D118FFA3AF34724D1424 /* FTreeSortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = C89732C5EDCECB77A12B87C1018E8B99 /* FTreeSortedDictionary.m */; }; + 643C288DFB3AF7857EDF2E20778C3A3F /* FAckUserWrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 201C752BCD7C078C782D815894466726 /* FAckUserWrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6444DB1EDAC39731543FE5D552ED4515 /* FImmutableTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 84672658BD8FE38B6372AFB154D09F65 /* FImmutableTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 64BF7813913EC822B81A1D601FE9B6A9 /* FEventGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = E49EBE95EE5226D43810CC59CC54EB44 /* FEventGenerator.m */; }; + 64E4B118012477620D4021CB9F889100 /* FIRInstanceIDURLQueryItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 607C922BE31F4818FD0C53BF79A4EC1A /* FIRInstanceIDURLQueryItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 651FC1165EF2D33C3AB5A81D21975147 /* FirebaseDatabase-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CDB4A8DA2BE9BFC90E5444E2A185301F /* FirebaseDatabase-dummy.m */; }; + 65DB3742B1FB346721CD46295FB4AF00 /* FConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 2FE5FEF4C93674EEFE8E07E813B00232 /* FConnection.m */; }; + 65EE2706CAA882AFD22DA82ADA09F30B /* GULNetwork.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A43440C82173CB5E42191974CF04F1D /* GULNetwork.m */; }; + 66277C11101A700E913517D61D856BFD /* FIRDataSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A7C86481B1F7532480087F344D12CC5 /* FIRDataSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 664EFFE98B1B9DA2164C46CE2BA05EA1 /* write_batch.h in Headers */ = {isa = PBXBuildFile; fileRef = 9379B377EEB58D4388B5DC1218A2CCC8 /* write_batch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 677657C55AEF922D9264DC8A794AC66E /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = CFE16650F6104B6F46B1EF91CE0FE364 /* FIRInstallationsItem+RegisterInstallationAPI.m */; }; + 69162A12A8CBB4BE21827065EBE80841 /* GTMSessionFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = AD95BC524E418C110A31AA6B77EE4664 /* GTMSessionFetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 691E504A56F2581637FD4C6CC10CC1E5 /* FIRDataEventType.h in Headers */ = {isa = PBXBuildFile; fileRef = 093D5D062733F074DD56AA1955F96DBA /* FIRDataEventType.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6A9BA323932E718D585D3EAD9AEC7E39 /* skiplist.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDB4CAA763E5FF7337EDEB141AFD95A /* skiplist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6AA694D35FA277681777FE88109FDC9F /* FIRStorage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 33E94FF93F0D0F4C36D3C35D97BD8DCB /* FIRStorage_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B139E50666884DDA98F39506C31F6B8 /* FIRInstallationsStoredAuthToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 879E2DE3ADE8E82073D5CED0089B357B /* FIRInstallationsStoredAuthToken.m */; }; + 6B44AB74D808DA88A581A5AC33E8F816 /* GDTCORPlatform.m in Sources */ = {isa = PBXBuildFile; fileRef = 6ACE358791743E000CFCB19614F5CE16 /* GDTCORPlatform.m */; }; + 6B492D24D60FA03960B5209F57D8E51C /* FBLPromise+Wrap.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 8931E783ED057317826553414CE66BF4 /* FBLPromise+Wrap.h */; }; + 6B4E54F20B4197926667E618A146429A /* FIRInstanceIDUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B5D47BE607CECCD8CFC8645008D99C7 /* FIRInstanceIDUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6B5D9858B70EF1362BD676748C27733F /* FWriteTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 690B9A3F161D19CD0FA5B461D0B67875 /* FWriteTree.m */; }; + 6B66E97D28746CC9C28D2F06251E5E89 /* cache.h in Headers */ = {isa = PBXBuildFile; fileRef = C3313BC5CDF1D9223D5FBA0F11BA5EBD /* cache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6B99CF35203D52B6710F0E4F2760F5F4 /* GULAppDelegateSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = A474C4C0651A543458D27D8A61CCF815 /* GULAppDelegateSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6BDD887158AE7BF5C19A11D3A676B54C /* options.cc in Sources */ = {isa = PBXBuildFile; fileRef = F7C0D5DD8E1D50B533B78792246BB6BC /* options.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6BF7ECEF7DD61561B78479955CA2D7C4 /* FIRInstanceIDTokenManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 483A5ADBF76AC92AA5C6D5507BB4E23E /* FIRInstanceIDTokenManager.m */; }; + 6C4C736295AD5F12B4D491DD2C46B194 /* FIRStorageObservableTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F532EB505ACAFC5EC6CFDDC747C753D /* FIRStorageObservableTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6C87D5D170CCC6CE2FF3D7AA3FB41001 /* GTMSessionFetcher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CAC2D41AC8570E0DFC63ADB7AC6A34C4 /* GTMSessionFetcher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6D1DC4625B27B6BFE18191C504247BF4 /* FIRStorageComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = A98D534267BBF249F20C291BCAD5DA55 /* FIRStorageComponent.m */; }; + 6D39CB536BCCFACE41951751224E0689 /* filter_block.cc in Sources */ = {isa = PBXBuildFile; fileRef = B9B6D75A17283D9FBCD34327DD2E6D55 /* filter_block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6D66F6C94E918A2AD882B2BD89AB90DB /* FSnapshotUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 6E1E4893A247B3564298AD37244E5E4A /* FSnapshotUtilities.m */; }; + 6D8FB3307C967E413C09377B65D95CC0 /* iterator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 68835ABB7B485036D75560A394D52DF5 /* iterator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 6E2BFCCC98EDAB76197000C0B80C29E6 /* FBLPromiseError.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 788528DEECC60A3130BFE6A2DD831079 /* FBLPromiseError.h */; }; + 6E636ED7B4C86C1B187091AB9E2C8A6C /* FValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = BDC5BA23017FC776000E41644015C34C /* FValidation.m */; }; + 6E8564186C4DC48202BDF3472AD3FE9E /* FTrackedQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 72597659B9DB60714BB5B7577D28FEDD /* FTrackedQuery.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6ECC2775AAB5390B970C817987859232 /* FIRStorageObservableTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E79602773F8F3F189744F56604A4AD /* FIRStorageObservableTask.m */; }; + 6F04DC3872A339A319A349E083F9165A /* FIRStorageDeleteTask.m in Sources */ = {isa = PBXBuildFile; fileRef = DD27A6E60F01AA15B88C57ADEE40B496 /* FIRStorageDeleteTask.m */; }; + 6F0890444301E337A069103808084FEF /* comparator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E05A614C11C6F07FF6BD355BEBDF07D /* comparator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6F1FB5DC371A0D21F7C10CEDC7B2FBB7 /* FView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5300BFD42D87DACC4E4A4C4495F15CB6 /* FView.m */; }; + 6F68B4D340A54874296A0B9717366D33 /* FIRInstallationsIIDTokenStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 03937960479CC5DA69B2F6CE80C880A3 /* FIRInstallationsIIDTokenStore.m */; }; + 6FE410A6F9FFBC77EF8FD39F34C8EDD3 /* FIRInstanceIDAuthKeyChain.m in Sources */ = {isa = PBXBuildFile; fileRef = 91BC6FFC5BA4E9232D75C5DA2913F91A /* FIRInstanceIDAuthKeyChain.m */; }; + 70EC18ABF46391ECCE28724F51F764C7 /* FTrackedQueryManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FE8DA5D3C54741AF02DCB290B8D866B /* FTrackedQueryManager.m */; }; + 7120A37D497F8C2742AF0050C46A1811 /* FIRInstallationsIIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA6CE7B8DD64D3E66580F5383EA2133 /* FIRInstallationsIIDStore.m */; }; + 716DCD5041771292E3BA4E2CD8BD9920 /* FPersistenceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F2AC7B9BC9D8655DE104DF06635B6F26 /* FPersistenceManager.m */; }; + 71C817080F4DDD76B43661DC2B645735 /* FTuplePathValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB7097098D26ECEDB878F37E1F8EA41 /* FTuplePathValue.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 720875322DC993F5489A8C287D88B360 /* FQuerySpec.h in Headers */ = {isa = PBXBuildFile; fileRef = D68CD9DCDB8B776D07D3EE629559983C /* FQuerySpec.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7239A5C21F6059BF4A0A776DCA9F4D26 /* FIRNoopAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = C261FFBF13CE61BB390215E9CA9C5FD5 /* FIRNoopAuthTokenProvider.m */; }; + 729CF00271D19B1F36AD1C9C8DDF3E17 /* FPersistentConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = D35AA5CCE687873A9CF17FDAF81BCC49 /* FPersistentConnection.m */; }; + 736EAE56500A6A2B91EF75CF2E9ABA5D /* FIRStorageListTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F69FC4745356C9F9EFA3FC172441B8D1 /* FIRStorageListTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 73A314709FAC4C46D13508F8E34EFC23 /* FIRStorageMetadata.h in Headers */ = {isa = PBXBuildFile; fileRef = A0575E69E82A456143066F611BF304E9 /* FIRStorageMetadata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 73E59601E5BFA2443AB2B8879D3DBCEB /* FTupleBoolBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 1483A141DA43BEE0914320FCA91B9E6C /* FTupleBoolBlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 754346F9FC4F9B00E27C59AAF4F25CD0 /* testharness.h in Headers */ = {isa = PBXBuildFile; fileRef = B4B90F0206371335E59420084F0FFAB3 /* testharness.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7581977D9500AE8FF79CEDD4CC0C8EEC /* FIRInstanceIDAuthKeyChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 75CBA7F15D495B26751E54BF4A558FA1 /* FIRInstanceIDAuthKeyChain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7595B8AF683D138FF6D5D7706B67971C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 7598D63A78F5DFC0709164C7CD572F78 /* GULNetworkLoggerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 87ED48D67D39DE00A35A205D0B1B05B6 /* GULNetworkLoggerProtocol.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 75CC6F9BE2575EFC85A4C1993BF5CF3E /* FTrackedQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 192069076F1645702572E4BB839A1FBD /* FTrackedQuery.m */; }; + 761650FDEBEBFEE584AE819A5E22B707 /* FListenProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = E193069FA536F860D51FA8C5BE5EC30B /* FListenProvider.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7660FE06276819EAB7420D5B67AA9045 /* FSyncTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F057C30095A02BF5F796E7CA9E1C295 /* FSyncTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7691C3FFA1093E1F9E79603A447BBC68 /* FMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EBA5F26A7ACDF18FC265E9A4E42DFA7 /* FMerge.m */; }; + 76B36E894C14C5C660C25E14AE5C7DD5 /* FNamedNode.m in Sources */ = {isa = PBXBuildFile; fileRef = AEBBB845997D63AABC3D3BF792E2AF04 /* FNamedNode.m */; }; + 76E075F0176E4F265A079A009D059A04 /* FViewProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = D6F6607EDEEF1D6596A32CF0CBD0511A /* FViewProcessor.m */; }; + 771FBA17F31F0043FEED1CB08D033837 /* FRepo.m in Sources */ = {isa = PBXBuildFile; fileRef = 5178BD41D5098BE8385637308F58C5FA /* FRepo.m */; }; + 77743CC07125058575369EF4E87D7DB4 /* FLimitedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 818EA601A22844DE95498B87F08F4CE8 /* FLimitedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 77BB721CAEE12F5B4CCFBB723F3F8D3E /* FIRApp.m in Sources */ = {isa = PBXBuildFile; fileRef = E27C12152E295AE51F1462B3956ADF9A /* FIRApp.m */; }; + 77C86F8FC541A60AE065CDB0CD90DAB6 /* FAuthTokenProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EAA193AE29B62BC092AD06205FD31C8 /* FAuthTokenProvider.m */; }; + 788511937056976C5DA219C6D9EB7399 /* FKeyIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 68CEF19BF3A286DFCD34482F7F8EBDA1 /* FKeyIndex.m */; }; + 78FABE98809E7FB98D45AC121BD4A5FD /* FSyncTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 20966C015039AA38819B63EFA48DDCD6 /* FSyncTree.m */; }; + 7916CFEE9143C1C3D7296DFF66AE5469 /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = C38C2F78048851357831E011AF92F876 /* FIRInstallationsItem+RegisterInstallationAPI.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 79F4BBA63390241FCF5FFBDB16619173 /* FEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D2D95038A32C6F364131AE25DA18D37 /* FEmptyNode.m */; }; + 7A32E72F51ABC1E99CA736FB19DEED4F /* GDTCORClock.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D5813664B48EEEECBD73FE4B6AF656E /* GDTCORClock.m */; }; + 7A38D80E7C30B77BA99C30CD3B35D9FC /* table_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = D0CFD980F55BDA288F9F5F389065BCEB /* table_builder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7A53D8D03C4684575862EDB86C2AB168 /* FBLPromise+Race.h in Headers */ = {isa = PBXBuildFile; fileRef = FBFD83C5D86D93B245CD240C86246263 /* FBLPromise+Race.h */; }; + 7B127A8E52CC4BF993993F92D54891EC /* FLeafNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 19458D70173FD697C88000691293B4C8 /* FLeafNode.m */; }; + 7B6D2BB37EE995E561AA9B370AEF8E6B /* FPriorityIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = DD161D56636E063DF147582966B2705A /* FPriorityIndex.m */; }; + 7BAC15E35BC888DFC0317FCC5526FDB8 /* GULLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = CF854CBC1924CB4762773A59FA06AAD6 /* GULLogger.m */; }; + 7C26BC19A31C575E1EAC07AFC2185CE0 /* FBLPromise+Then.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF1E1AB955E1D60F59D3B21F43389D6 /* FBLPromise+Then.m */; }; + 7CA6185CE3610CFAF706ABDA56173C07 /* FBLPromise+Retry.h in Headers */ = {isa = PBXBuildFile; fileRef = F74357951D0E0FCFAB5F7DE7D9B10AB9 /* FBLPromise+Retry.h */; }; + 7D1159E615ECDA356A0C3DE46514241B /* GDTCORTransformer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C11004830397FE020F6EDE9413D3CFC /* GDTCORTransformer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7D42612361DCD88702ADC3EE552D33BC /* FViewProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = C34CFA0CD6D054D8ECCB50347442C309 /* FViewProcessor.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7DA5DAC7FA9A603B93F0F35B5128DE2E /* FIRDiagnosticsData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A84CC0D422B1D53DB21636894EE1EFC /* FIRDiagnosticsData.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7DBDD67838022F8D94F82BC4C39DC75B /* FIRInstallationsKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 9ACA1297A58C6DEEE74A97F1D898F72B /* FIRInstallationsKeychainUtils.m */; }; + 7DCE2CA7560BA7C7BB1463FD60E2E8BD /* FCompoundHash.h in Headers */ = {isa = PBXBuildFile; fileRef = DB7C2097612DD516A996C265A7EBDBA4 /* FCompoundHash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7DF0739B4722AE07617F65C0BF27D06D /* FIRStorageTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 92B13DDB5CB3F9B1C18773D451D044FC /* FIRStorageTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7E008C50A7A20243444C7B15BA138089 /* coding.cc in Sources */ = {isa = PBXBuildFile; fileRef = E26FDD1CFCD18864203B9242BEB1EBF1 /* coding.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7F316A45604FD022592B46CBEC961866 /* block.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9C3E5A6D44DDBAA12BB947034F1DDA85 /* block.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7F9E1883331F823C5EB51E87851E3E51 /* FCacheNode.h in Headers */ = {isa = PBXBuildFile; fileRef = A0B697892DA8B676D87651CB9C438A1D /* FCacheNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 7FD12F99349D882E8A5C0553F5B42C30 /* table_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1D84106EEDBEB4ABE5F79A6CF40A6C46 /* table_builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 8086747B000673FE85AE2CDC9BCF9F97 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 80E96D8E39F3CEC4ECB25553B90726E1 /* GULNSData+zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = D1067267D7E7186772FB61C1FD41B054 /* GULNSData+zlib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 81BAAF16E2B0900842FDAD09B244AA53 /* FRepoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A25305788598EBB7D81781D92991341A /* FRepoManager.m */; }; + 820E1890ABE1688D89211D1BCAFDC337 /* FSRWebSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = A54C9AF9132A993BDCA8FA4CDB334692 /* FSRWebSocket.m */; }; + 828DAE36E61058CA12A5A48B18407164 /* FIROptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 411DF6A51F39A73FC87869A8A5AF5170 /* FIROptions.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 828E420D4531AA888F5A39A2F2772157 /* FTupleSetIdPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 312064CA84E0B1CCE2BFF80E4A923AC7 /* FTupleSetIdPath.m */; }; + 8359351040DF8FE835DF10BD2C6AE9E1 /* FTupleOnDisconnect.h in Headers */ = {isa = PBXBuildFile; fileRef = EFDAB92669C9F072D980DC72D47ADE41 /* FTupleOnDisconnect.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 835B3D8377DA5D3D63555ACFF87668B1 /* FImmutableTree.m in Sources */ = {isa = PBXBuildFile; fileRef = D75E77BA956ACEBBA0AF6BE30433A511 /* FImmutableTree.m */; }; + 8362EC8832941BC529EA0C9E9B9905FA /* coding.h in Headers */ = {isa = PBXBuildFile; fileRef = 58289B6076C1CF90C0AEA2F1BA7CF68B /* coding.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 836C8C9A7F2C37E14C32D26657A691E4 /* FChange.m in Sources */ = {isa = PBXBuildFile; fileRef = C3601A2F20B68571CFD4D5585BA05C52 /* FChange.m */; }; + 83AE066A91D8C56272DF82389C5C6E09 /* FIRInstanceIDKeychain.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B2DC3F3158AC569D8BB4D9159B92FDD /* FIRInstanceIDKeychain.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 83E06D7DF383E38338D42D28FC3BEBBB /* FLLRBNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 45C0503452AD338BDBAA92921C9DE194 /* FLLRBNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8423C55527E64F1812D09786125FA512 /* FBLPromise+Race.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C452676C3EB75F3891DBC914F75291A /* FBLPromise+Race.m */; }; + 844E341DC43007F8D350C5871AF899BE /* FPruneForest.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC08069DA325ABB6838B87AC6835656 /* FPruneForest.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 847EBAF530456EA7D8E8D15C25C06E32 /* FTree.m in Sources */ = {isa = PBXBuildFile; fileRef = A248E1E0FA382168B833426DDECDB4FB /* FTree.m */; }; + 84DF0D7211BCE3745D019AAFE8C35A1B /* FBLPromises.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 5B7B5A1E8610253395EBC43E530959CA /* FBLPromises.h */; }; + 8536B41B796BE0AAB0DF4BF6EA085E33 /* FConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = D752406CBEEC7D0ADECA246969C4CF9D /* FConstants.m */; }; + 86A9E5C99527684827C235224559D4DE /* iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E826F61C6B288FEEEBA15A3388C37EBE /* iterator.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 86E5BCF0724E538365D344454A3F3278 /* port_example.h in Headers */ = {isa = PBXBuildFile; fileRef = FE6CE57F830C31B2D2A7D544113C28CC /* port_example.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 87290DB3F2EDD697F4E6432838194C95 /* FBLPromise.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = EABF0AF368631BBA0EBC6315F6B4144E /* FBLPromise.h */; }; + 87A01DBF2A88ED8B674303FD80F91425 /* FRepo.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D6ADFA238D1EE026EEA9BAC14D8F931 /* FRepo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 87B0FB4038E754FD7352BFECFB158C57 /* FIRStorageUploadTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D6FC6558E8C6C30A444F001D3A20CD2 /* FIRStorageUploadTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 883F2A60B72F776412EED0A7A31D90C1 /* FOverwrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A1C718556F05CC83E3A0A98FC95B6F5 /* FOverwrite.m */; }; + 88FE26A1F111DA8ADFACFB2C21FC8560 /* FIRStorageTaskSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F0BFC9D0F80D4FBE73F0652CB04E596 /* FIRStorageTaskSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 890E7AD9723DD1354170A4CB31C0E7A7 /* FIRStorageTask.h in Headers */ = {isa = PBXBuildFile; fileRef = EACB33C10F6F9E2BFAD2353C454F9AE7 /* FIRStorageTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8958E775CB1D33AE4F5BDF52724797A1 /* FTupleNodePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9FD3430FC65B7BAB65043C8C66278E /* FTupleNodePath.m */; }; + 89957B71EAB83CFA8235A37A01DFD36B /* FIRStorageUpdateMetadataTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 38C523982ECA211A1C922FEE51D4428F /* FIRStorageUpdateMetadataTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 89A2C51FCAE3567F5894E25E0ABD3C05 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 89BB95047C61758DBCCA8439385D59DF /* FAckUserWrite.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EFC7BAC9CEA86180EE50C52ADF90B7E /* FAckUserWrite.m */; }; + 89D7BC2FAF21481AFF8D790C0C7E865E /* FIRInstallationsErrorUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AAAC42AF05E13F7344E5CF861CA1945 /* FIRInstallationsErrorUtil.m */; }; + 89E522F7F84341756DEBB135DC9BEEC3 /* FClock.m in Sources */ = {isa = PBXBuildFile; fileRef = E99B3791B40D702BA7499A2791FF41FB /* FClock.m */; }; + 8A1B6697EA2803700F481934EE104EC3 /* FTupleObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = E2E98869B1CB0FA25A72A5EFF1D02816 /* FTupleObjects.m */; }; + 8B03BA58C638AE48CA4E8B2C4C5A2792 /* FTuplePathValue.m in Sources */ = {isa = PBXBuildFile; fileRef = FA66E374375C4A12B0A38918F5DB9B4B /* FTuplePathValue.m */; }; + 8B60886BE7DA0D5C0E675B3D0C44D388 /* filter_policy.h in Headers */ = {isa = PBXBuildFile; fileRef = BD19B03DA6680BFB310D0060308CCD22 /* filter_policy.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8B7713351FD4F1EEDDB3F67E18D7B032 /* FBLPromise+Catch.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = A02930679CA97D007C20B3DF2C78DA38 /* FBLPromise+Catch.h */; }; + 8B97CFB39083F9769E2F676DAA5EBA0B /* FIRRetryHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = A6560A52892AAE5757A5CEE963E13593 /* FIRRetryHelper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8C48DE58B885ACC442E2445ED473136E /* FBLPromise+Catch.m in Sources */ = {isa = PBXBuildFile; fileRef = 3602C9CF1460A33C123A3A12FD8C307E /* FBLPromise+Catch.m */; }; + 8C5E5F02844ABAAC171F730D03F792D1 /* FEventRaiser.m in Sources */ = {isa = PBXBuildFile; fileRef = 0072E27C9E6009B48B7F04E59F4F71C1 /* FEventRaiser.m */; }; + 8C9BA1E165EE7575E621F061D269EB18 /* FIRInstallationsLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = DBC613BFA3150CBAC4A2F3088A3496AB /* FIRInstallationsLogger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D1EABDFB067573AD6D3EFB6DB7E0D71 /* FTrackedQueryManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A86A8FD734185489EECEE9ABE1B8639 /* FTrackedQueryManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D32B9E96C8D7AAB2D4C874A0031E08E /* FStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = EC38A8C53E78ED42481B50F3D1DA08BB /* FStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8D65B36E1B3E5C2A54C55E6E061F795D /* FBLPromise+Validate.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 54384F820C1941AB60BF900E4154CA50 /* FBLPromise+Validate.h */; }; + 8DAFEABBEABD44FB7ADEE290940C1B4A /* FIRVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 2467A834C566F16403C6F4E386D5943D /* FIRVersion.m */; }; + 8DC45ACAC7CA43FCF89837E18D0373D9 /* FIRLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 1ACD081B6F3DD381BC03AF0B1D4EA03C /* FIRLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8DD54A0A7E8E133E8156363E96698995 /* GDTCORDataFuture.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE3EAA708149B8146C731A7AC4FB682 /* GDTCORDataFuture.m */; }; + 8E22BF1FFFB98647ECA203A8E7AF37DD /* GULUserDefaults.h in Headers */ = {isa = PBXBuildFile; fileRef = 55061862C4109FA0B57C202449412BF6 /* GULUserDefaults.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 8E60130359B0DAD32D6767B2527446ED /* GDTCORUploadPackage.m in Sources */ = {isa = PBXBuildFile; fileRef = 875FED658B925BC28611FDB1B8858369 /* GDTCORUploadPackage.m */; }; + 8EB89BB70E30C5A3FAF63B1326E5472C /* pb_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = FBCE9ABE7022B4327517A73BE43D2C25 /* pb_decode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + 8EBE9FAEA74066BBF5AE478B7FD93FC0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 8EE9A761D6B7B901935116CC1790ED46 /* GoogleDataTransportCCTSupport-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 27E7DBAA6418AC1DF35DF54CF5996CEE /* GoogleDataTransportCCTSupport-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8F08089419E600DA51BDADF36DB792AF /* FIRInstallationsSingleOperationPromiseCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E0A31444EC9783637FF1BF0E9FAAF92B /* FIRInstallationsSingleOperationPromiseCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 8F4A47BFC891AD3DDC3E4DFFB0F25046 /* version_set.cc in Sources */ = {isa = PBXBuildFile; fileRef = 35025384884E48B66920A6D01BE8A148 /* version_set.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 90001814C0232EA9ED085F1CE470B8B4 /* FIRStorageErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 12F18220753EC36AA3774DEDD6478578 /* FIRStorageErrors.m */; }; + 903338B5CBC6007A0BA72F31B656B955 /* FLevelDBStorageEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 19A1C443965CAAF1705E6A645B84E2C2 /* FLevelDBStorageEngine.m */; }; + 91F97F8FF5C8BA9F55621F0161A4DEB5 /* memtable.h in Headers */ = {isa = PBXBuildFile; fileRef = F45D4E33349EF35597144185678B05C5 /* memtable.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9206BDCA1DD50E2745D33A92D4E40078 /* GDTCOREvent.m in Sources */ = {isa = PBXBuildFile; fileRef = DF087165A75F7E60174E3AAB4D5101F7 /* GDTCOREvent.m */; }; + 921B68DD7F7EF6BF3D2415A2B4B5998D /* FIRDatabaseComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = A3C2723DD4EBBF36E3422C8F261BC567 /* FIRDatabaseComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9244F29221DB1B85A5642637DD3AB19A /* FIRInstallationsSingleOperationPromiseCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 6250B9B9864608A84ACE5C17FCFD6C40 /* FIRInstallationsSingleOperationPromiseCache.m */; }; + 925FD7C33A68A155B3223E833822C99D /* random.h in Headers */ = {isa = PBXBuildFile; fileRef = 646E3EB1AF891BC9543C99781D5C61CC /* random.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 928310BC62D2BEC2CADAB2AA934EE5A2 /* FIRInstallationsAuthTokenResult.m in Sources */ = {isa = PBXBuildFile; fileRef = A6B7B883FE64676C0CD7B665C2CAB402 /* FIRInstallationsAuthTokenResult.m */; }; + 929A05CBBFE0CDB1A9D04FE9471A8B7D /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = F318D95F186F44696E86DD96E1D6625A /* port.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9309FAF9DD702689F43B7191CEE212DD /* GULReachabilityChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = D0899F5BE9309740C647BE99B3BD7C59 /* GULReachabilityChecker.m */; }; + 93B51015B2568DF742D1ACF5C00D18AC /* arena.cc in Sources */ = {isa = PBXBuildFile; fileRef = BCCD4D307EC99FAF7669F3B43419DAEF /* arena.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 94FC8A0E6D527D341B830E9639205039 /* FWriteTreeRef.m in Sources */ = {isa = PBXBuildFile; fileRef = BB9276EF011DDA9D5DCE46C59B323984 /* FWriteTreeRef.m */; }; + 9503B342F7CFC98B702861D793378AD9 /* FWriteTreeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 44C3D7F04D9498A963E4218040395239 /* FWriteTreeRef.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9535F67513B537D39075DCC8B40769FB /* FIRInstanceIDTokenFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 83601D3D66D4C646F41A88B146365C27 /* FIRInstanceIDTokenFetchOperation.m */; }; + 95E1FE5CD5A52C608E8935917ACDA696 /* dbformat.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4576E396AB8F6390C668D1DFF46CDE /* dbformat.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 974010B0CB603F4B3082B6B5A73BE9BD /* FMaxNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 74AEFB17E19376B554C4B5CBE9839CFC /* FMaxNode.m */; }; + 97AC8D62B5D6DBB36B67FF181AED0A8E /* GDTCOREventDataObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C0AB9D4108F4576B594A1159BD62850 /* GDTCOREventDataObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 97FCAB23B3B3295D4AB6C670767E7595 /* FIRConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = F03192D6CD3300140B77BF7EA1CCA565 /* FIRConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 98DA22ECB841196BE5E2314435244D65 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + 99A636D3D11B5CA5908D9E7DBA1BA0E3 /* FIRVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 593F643A1D127168A8A468748C572D8B /* FIRVersion.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9A76B979483CDCC7889F7439157B1865 /* FIRIMessageCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 396B90CA36D20A652948E5CDA84CDC5E /* FIRIMessageCode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9A861EE27F9EE8D8F08D283949432631 /* FCacheNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BC2C6B675EB725F0D223EC27209FD39 /* FCacheNode.m */; }; + 9AAF3D66FF52AABDD06019F200A2D6A9 /* FirebaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = BBD01369BBFDE33B2EA046878BD3C0B9 /* FirebaseCore.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9BF8F2C1071091020A1723B7D830B352 /* FIRInstallationsStoredItem.h in Headers */ = {isa = PBXBuildFile; fileRef = B05A5F93428885B5A938FC466B2A15FD /* FIRInstallationsStoredItem.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9BFAFB9A249CD946F01A580004125ADF /* FIRLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = BD0F6EDF8E4EF83990ED65297E06B81B /* FIRLogger.m */; }; + 9C48553D8F15E59701336C838B13432C /* FIRDatabaseComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B70C438948477944CD43C50B8C26AB7 /* FIRDatabaseComponent.m */; }; + 9CE2E00FE4F6A58989CCA338DF3BA161 /* FEmptyNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C4A7F66B2805F2635EB770E33626B88 /* FEmptyNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9D2487DE9D41A0BE0F8ACAB14237F697 /* FIRInstanceIDLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 41401874FA638C00FF727FA7A46C972F /* FIRInstanceIDLogger.m */; }; + 9D25E6F740FFB7E2E1C51DF595D30C98 /* FIRInstallationsVersion.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B28B1D9152BF89EA21A1F696D785A12 /* FIRInstallationsVersion.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9D884E628C4EC58605210B17D77C29EA /* FirebaseCoreDiagnostics-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C6603077B3BAE9B69D097E3D89FE4D7 /* FirebaseCoreDiagnostics-dummy.m */; }; + 9D9E041AF29679CF41A433513A059BBA /* FIRInstanceID+Private.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C206964574410436FED4D6E158610F0 /* FIRInstanceID+Private.m */; }; + 9E2135C68E192F65B64295066DD70718 /* db_iter.cc in Sources */ = {isa = PBXBuildFile; fileRef = FB842126904767A67B91205B38C304F5 /* db_iter.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 9E6932F0856AB44456533DCF80A711CC /* block_builder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A706EAFB3D2A122ECD92DD5799E98BE /* block_builder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9E8737109FCEF2E5CC22B402CA17C9E8 /* FIRInstanceIDURLQueryItem.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2CDC345A549E5ED13CB3912D118A47 /* FIRInstanceIDURLQueryItem.m */; }; + 9F02242AEA02A2E8BEEEE56896022A8E /* FKeyIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 945DAB6906A81D5EC5D0F1F2DA26500C /* FKeyIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9F1497DD933D42DEDBE7DB1FC7E2251E /* GDTCORTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 95AE095CF820AEDCF24899B9BF862975 /* GDTCORTransport.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9F3032C9BB51D69539BDB7F4AD859ACA /* FEventGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 071ED579E4A1C9D1C68506228B44FC8E /* FEventGenerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9F480EDE16EBA9D07BD5CCF66B3CC57A /* FIRInstanceID+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CF567AE7E57310AE4A3C5DEA9C1FA082 /* FIRInstanceID+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9F86991A723581E08AE8E6EE79466BC6 /* FIRStorageDeleteTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C7BFD32D5BBC98FC727B87823E3F0C /* FIRStorageDeleteTask.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9FCA6A53EB43D6322A186258C68EDCB9 /* FTreeSortedDictionaryEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 051ECA26E694DE464F0B2262039F89BD /* FTreeSortedDictionaryEnumerator.m */; }; + 9FE2088DC595663A06EC17EF66921A26 /* db_impl.cc in Sources */ = {isa = PBXBuildFile; fileRef = C584B9B3948F8F67F6591EE319DACC20 /* db_impl.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + A06DFFAB0A1C8E35A6C18FF78EA37507 /* FIRMutableData.m in Sources */ = {isa = PBXBuildFile; fileRef = 34D58F578A6B32ACB43E4F081310AF3A /* FIRMutableData.m */; }; + A08B7932A2AEA599496A3763C951AE6B /* FIRInstallationsAPIService.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7326DD6B394923A78CA1BBC5D827E2 /* FIRInstallationsAPIService.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A0ACAB10D0A53EF6EB4873D611C6A42F /* FirebaseInstanceID-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9ADC2802276930B11A1968FD14EB6362 /* FirebaseInstanceID-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A16D303C0AC6A7D42E0F8A0AA94B613B /* version_edit.h in Headers */ = {isa = PBXBuildFile; fileRef = 585302D48E99F87797E63B309BF8AA44 /* version_edit.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A1B2114FED012572E978166C217EC8E8 /* GULAppEnvironmentUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B0DA53538D50A020387AB115C11CE206 /* GULAppEnvironmentUtil.m */; }; + A1F8A330C664BB690B2F07BA7D42C17E /* FLevelDBStorageEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 5E02672207635E1E0F3FFDADFFFD3946 /* FLevelDBStorageEngine.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A204AC2A99A5F0775FEE42474CA87A65 /* pb_encode.h in Headers */ = {isa = PBXBuildFile; fileRef = 689A74FA4AD346552142D35E8DBF8BE5 /* pb_encode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A2307117BA50B6FBEBDCC55F89D227A4 /* APLevelDB.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5C235D00DEB88A19CFC0216A0D1148C /* APLevelDB.mm */; }; + A27AA2264237C9872164D6F1BB7C92DA /* FIRStorageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = FF0A44A5C1649AF3610C4A16F8CEAA7B /* FIRStorageUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A2D1C41371A0266897AF7AF98812091B /* GoogleDataTransport-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F20EACCD4C59A1512EEA6F07603AC103 /* GoogleDataTransport-dummy.m */; }; + A2D249927139D3D5A465236958CE9942 /* GULNetworkConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 4225CA428474D85D68CB643FE8588165 /* GULNetworkConstants.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A446CF2879E16656DEABDC8EEF930F9B /* FBLPromise+Then.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C60FD75C09F75F9F289419CC6EC3DBC /* FBLPromise+Then.h */; }; + A49C47375A61C2F57352B691384C14B6 /* FBLPromise+Recover.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 9A776495F0C11B2D6E910717050FE201 /* FBLPromise+Recover.h */; }; + A4DB9C6D43242A307C3213CC1A78B690 /* FListenComplete.h in Headers */ = {isa = PBXBuildFile; fileRef = D03D9478B9C4950F5892831FA40A6F85 /* FListenComplete.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A54B91653824B62CC3957DC96367BEC0 /* env_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = DD9AD7328301C7C2428C3398259925F8 /* env_posix.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + A6DA65E484EF41CA534C9708A78B99F2 /* FIRInstanceIDTokenInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 184D0B16C9E04FF26374C15D181A7F5B /* FIRInstanceIDTokenInfo.m */; }; + A6F78146F5D097FAAD4B832C4D495AB0 /* FTypedefs.h in Headers */ = {isa = PBXBuildFile; fileRef = AC0DBEBA832AEB2C6C3CCBC1E2DCF07D /* FTypedefs.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A708AAE603B2A6D119284985B4B0A633 /* FIRApp.h in Headers */ = {isa = PBXBuildFile; fileRef = 615CCFC202BFA16A80BC04AC96FCF487 /* FIRApp.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A74F10527A78F572439633D8D6F162C2 /* FIRCoreDiagnosticsConnector.h in Headers */ = {isa = PBXBuildFile; fileRef = A7265876B72206667C402E8DA2657541 /* FIRCoreDiagnosticsConnector.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A757314004034116D9AB766F51CF4348 /* FTreeNode.m in Sources */ = {isa = PBXBuildFile; fileRef = C81FBDB69D3D7E4329AD1A0FD479E6D7 /* FTreeNode.m */; }; + A77CF7F275FD69E4BB4E021F418D74B5 /* FChildEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = CB211419F418229FA95278C411875D55 /* FChildEventRegistration.m */; }; + A7D220511D6C7F7540F0C91FC006034C /* FIRStorageUpdateMetadataTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B6FD5CF4CFDF8CF03B9B7B49DBEF46A /* FIRStorageUpdateMetadataTask.m */; }; + A7F60C5B2674E51F045AD6FE27970891 /* GoogleUtilities-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7D89A6CB046C6FA85A49FCC0B99090 /* GoogleUtilities-dummy.m */; }; + A84D6BEF12D2AE019F4E77A0C527E906 /* c.h in Headers */ = {isa = PBXBuildFile; fileRef = C12710FB7206C72F3780C9F49C020BA1 /* c.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A87F1BB8D6C296793793F7BCFE722B30 /* FQuerySpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 0031AF1FB02DAD5BF0064720F7C7EBA1 /* FQuerySpec.m */; }; + A89C04521E00485D808FA28609FFCBFB /* GTMSessionUploadFetcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 4110031FA1CB0283269D477218EDFA3D /* GTMSessionUploadFetcher.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A8D0E460F9516ECD96C2EE6C62E639D8 /* FPendingPut.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F173297AC99D08D91EA05F159592E18 /* FPendingPut.m */; }; + A8FEF73E60F905C4CFEF7963E5444AF4 /* pb_common.c in Sources */ = {isa = PBXBuildFile; fileRef = B346E012CA98A38C8509220492705220 /* pb_common.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc -fno-objc-arc"; }; }; + A99706F65C909FC6718BEFA0CC372FEA /* FIRSecureStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E0287E8C63893D4474D3CD7F879AD0D /* FIRSecureStorage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + A9E07F9288E24EC1952D77C18F3928F0 /* FLeafNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D7DBE42AC5973FED94FD2BFAD8DB4DF /* FLeafNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AA22B314F3365FA8BEAD68BEEFA0D6D7 /* FIROptions.m in Sources */ = {isa = PBXBuildFile; fileRef = BE201BF532103F0EFC7059AD2232DEC1 /* FIROptions.m */; }; + AA2D99531924F8709CC5C6DA5A84A1D2 /* FirebaseStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 128CF27E454BFEA60A3C9AA8900394BB /* FirebaseStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA7C495E4999B5D171B45257EB2B6F67 /* FIRStorageTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 78362BB93558FF4EAAEB1E8B43AF9174 /* FIRStorageTask.m */; }; + AB69509E8F7A9D7413D1CCA245838A8A /* GULHeartbeatDateStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 102030AB0E29D8723B187640A14759D9 /* GULHeartbeatDateStorage.m */; }; + AB7C479F3F90C663B612A3B28927DFC9 /* Pods-PediatricPancreas_Storyboard-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FA2D57AC7503BB3ECD9DDD080FF3536 /* Pods-PediatricPancreas_Storyboard-dummy.m */; }; + ABAD09E66DF0EBBFEAEEA73AF38EA7F2 /* repair.cc in Sources */ = {isa = PBXBuildFile; fileRef = 44866FAB99B09DB36E26EE4B4E7EE3BF /* repair.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + ABD146608271EEF848812A0D554572D5 /* FServerValues.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DC869DC361D2BDADAFAE9ECAF9D61C8 /* FServerValues.h */; settings = {ATTRIBUTES = (Project, ); }; }; + AC115DD8776F1A81B040F1084312D550 /* FValueIndex.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B5009794F8E9B14AFDCCCC35B349A3D /* FValueIndex.m */; }; + AC4C9808D241DB5569DCA5E06F982427 /* table.cc in Sources */ = {isa = PBXBuildFile; fileRef = EA7BFFCAAF832433E1DCCF3E39E54D6E /* table.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + ACBDD6FAC6B0779840C1A49EF7DF9786 /* FServerValues.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CB62E487FA29460E6F077133621B7BD /* FServerValues.m */; }; + AD40A049FBE7ECCA46352FD95416072E /* FIRComponentType.m in Sources */ = {isa = PBXBuildFile; fileRef = 970D1EE49B5B4AE3A1C04FE453E26463 /* FIRComponentType.m */; }; + AD643FC92A4606AF667A4B5161F44C1E /* FIRDatabaseReference_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 916F2253BB01607784C0DB1216E2E9CE /* FIRDatabaseReference_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ADDCBE632C2C646643F3F862EBF6835B /* env_posix_test_helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 029E54A0C7F78D5174C1DE28C541531E /* env_posix_test_helper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ADF87CA273D444759D20EA51731A1B90 /* FIRSecureStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 134AEB3F267142E63330B1EE8557A729 /* FIRSecureStorage.m */; }; + AE9269076F92047F499E33896427FA3D /* FLLRBEmptyNode.m in Sources */ = {isa = PBXBuildFile; fileRef = DB395C56E1B48FBF6BDD2F3219DB0F5F /* FLLRBEmptyNode.m */; }; + AF1273B969A636DB365E700548D5928B /* FIRAppInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = D3C3D69913967F6EE53380D4DF1BAAC3 /* FIRAppInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + AFAAF7F17169821F3881DBC0250EB51C /* FDataEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FCE5C0E1371E8E6FCAC3358D8DF24E6 /* FDataEvent.m */; }; + B04699CACB7CC3F9C1F3B1AEDC5D0A84 /* FIRBundleUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = FDACA0EDDA8DC12E586A89B7A92044CB /* FIRBundleUtil.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B098D41B81126938688435CFF517F0CC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + B1061C7C80A0F6DF24EC31E6FE73AA0B /* FChildrenNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 44222B32871DED425CC6FD62785342C5 /* FChildrenNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B16532AB9D0FB86BE4CF3D9E86209D51 /* GTMSessionFetcherService.m in Sources */ = {isa = PBXBuildFile; fileRef = 38D86F977EC22FCEFF56212D1B48EB8B /* GTMSessionFetcherService.m */; }; + B1B47680FDB11C2E597CECBAAA6D3A32 /* options.h in Headers */ = {isa = PBXBuildFile; fileRef = 9724FC0DB2B700C5916C4B225396830E /* options.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B1EBC26487152BC48AA9A05C66576947 /* FIRDiagnosticsData.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FFBC2FEA5B7B0021EC1D822FDCF4EBB /* FIRDiagnosticsData.m */; }; + B259A3DCF44B88A9BCA0300A484EAD8E /* FIRComponentContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4FC8B84916B3508094591E16F5044642 /* FIRComponentContainer.m */; }; + B2F841F93A8850DF98625D0BF618D259 /* FIRInstallations.m in Sources */ = {isa = PBXBuildFile; fileRef = 788D52215E806B9AAF19263432A92BBD /* FIRInstallations.m */; }; + B34E2EBAFB177A7519DA402AE480AEEF /* FirebaseCoreDiagnostics-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 722C71C6D27A3037C21FC011B803AA74 /* FirebaseCoreDiagnostics-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B36F0725AD821954CFBB57931006CAB4 /* GULSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 16CE5915391DA812240B7E3D3EA23BB6 /* GULSwizzler.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B373E85687ACBCE3AAB896CD3554E510 /* FBLPromisePrivate.h in Copy . Private Headers */ = {isa = PBXBuildFile; fileRef = ECACF7849D7CAC8D64FB070D76863651 /* FBLPromisePrivate.h */; }; + B3BB577D4211D3023294E7F18B90FCA5 /* FSnapshotUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = A3D6CD0CB3F7889EF66E4B88ACE8EE4F /* FSnapshotUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B3D0940AEEB725E34BF0AE38A2E34AD8 /* FIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E6033BCAD8C3551417FE27E1BD0BC0D /* FIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B3D655C3B250B2B216B666B36D99E445 /* FIRMutableData_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 453024A9DD7B840DCB627C15A631AA6E /* FIRMutableData_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B3E0AFA032C3F21E2588F3A0EA12140E /* FBLPromise+Any.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = B6664E7165D5105EE3355D7B7FD1AEAC /* FBLPromise+Any.h */; }; + B4986614E4F4D8F4FFE503AFFAF3D58D /* arena.h in Headers */ = {isa = PBXBuildFile; fileRef = 9DDB6715072A57A18500B34BA425AEBD /* arena.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B4B0C9ABA908C556FE701D3A72D68EA6 /* FTupleOnDisconnect.m in Sources */ = {isa = PBXBuildFile; fileRef = 46A9327BAF9A628A9002286422BF7F83 /* FTupleOnDisconnect.m */; }; + B5145DE6102507FAD19274D1271E2C99 /* FIRStorageConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 81CD2FBB0D1DF2DE80B0A92A432198D5 /* FIRStorageConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B552E8D129507C97200F2AC1B2121BF5 /* GDTCORRegistrar_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FDD7328DA6F01C55D0E675A37C0976EC /* GDTCORRegistrar_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B56960273A4E32A0FA480C50AD403309 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + B620561754FCF5F73A5B8BBE59AE6F87 /* FTupleFirebase.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B041AE2CD41F4960AA09352D90DA5F7 /* FTupleFirebase.m */; }; + B67210B747B2F553A333E5D8909340EC /* FBLPromises.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B7B5A1E8610253395EBC43E530959CA /* FBLPromises.h */; }; + B68E07FCDC1873E5B1EB886F680E7450 /* GoogleUtilities-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 47A60F3366969F399160D8AE328D1F1B /* GoogleUtilities-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B696C2574730621A7A06CBDC788AD8BA /* FTreeSortedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 24B3EA8490EADB3F93B91A42EF325BEE /* FTreeSortedDictionary.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B69E623E913DC7FC77990E74DDCF127B /* FIRServerValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C5E93C787026AE510C04647460CDC1E /* FIRServerValue.m */; }; + B6D8A7CDFB1EC2596BF2FB68460D9DFC /* GDTCORClock.h in Headers */ = {isa = PBXBuildFile; fileRef = 85BDAD751CA36AAB6F83EFD5C027EA91 /* GDTCORClock.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B7A60B75838E75A34495A209BC8B5BB5 /* memtable.cc in Sources */ = {isa = PBXBuildFile; fileRef = DF082C74F4DA2DEAC965BC29903B79AC /* memtable.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B7DA98B94071F1BBE02BF22D7313B848 /* GDTCORUploadPackage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 0634A83F899FE66CAACB549A4DE98343 /* GDTCORUploadPackage_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + B7EFCCE0D8338C14B9D98A430F183A0D /* FIRInstallationsHTTPError.m in Sources */ = {isa = PBXBuildFile; fileRef = E936E8C2B50044D3205DF51E9E9007DD /* FIRInstallationsHTTPError.m */; }; + B8521AD66344AF93B35758605EC7FADE /* FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B51851E07A886CF2821B854EA81E101 /* FIRInstanceID.m */; }; + B85351E2EA1547BECBAA42B92CCE35E4 /* FParsedUrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DEECD90DC659AAA5A515F133BA3D8A4 /* FParsedUrl.m */; }; + B8A89FC9B89E6A1A2AC7FE5646986CED /* builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 61C03183DE684C75C09F7D131C6D8E6F /* builder.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B8B7C8401035F8F75B8E0812F77B1352 /* FIRStorageReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 15C33E1A98FACB2E96B1D9BE014EFA20 /* FIRStorageReference.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B8F1F4020E930C0DE5C12D6A043B1C0A /* FRangeMerge.h in Headers */ = {isa = PBXBuildFile; fileRef = 07ED1B1B3F489527C7662FED486F7315 /* FRangeMerge.h */; settings = {ATTRIBUTES = (Project, ); }; }; + B8F556A9D5941E43CBF644F49E241585 /* testharness.cc in Sources */ = {isa = PBXBuildFile; fileRef = 10F2138F2FBC045AC402BDA69D3CD680 /* testharness.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + B9CFB547B444FDF1B9F719AE1F95F6BD /* FIRInstanceIDCheckinPreferences_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B42259F661E6F3C660CF1AE5031683E /* FIRInstanceIDCheckinPreferences_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BA027134643F044506DE83C5A75EB3C3 /* FTupleBoolBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 71DA7C5A98E56EFF594760AD94F1C73C /* FTupleBoolBlock.m */; }; + BA3974AE08AEF5E6AF9E375ED03C8FD7 /* mutexlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DA3D7D0CCBF53EA683D879E7BD0E744 /* mutexlock.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BA506F5F3A63E7A3AFDF669F5F28DD13 /* table_cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A59D3DCFF16FA7B1C33B039ECCC3B79 /* table_cache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BA559B250E2210B4EF12513109B50C2E /* FImmutableSortedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B98410F83421303C9BE8074E1C0E4AC /* FImmutableSortedSet.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BB706CE15895A0E5263D2EC37F7B4964 /* GDTCORUploadCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 83CD465F0A45201ABBAE6485F83F43E8 /* GDTCORUploadCoordinator.m */; }; + BBB5066022594C5799922EA073C8DFFC /* FBLPromise+Retry.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F123D96464AE6E248DA68965E4D63EC /* FBLPromise+Retry.m */; }; + BBD58D26EF7464B105F93DFEF27598E2 /* GDTCOREvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CECE9D2BE91CA5F856D1C62E06F7E40 /* GDTCOREvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BBEB53A54F4B17418511C2B7A93EA5CB /* FCancelEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = C34D9E474712175C6FD3E2563CE00F17 /* FCancelEvent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BC4C1C862D2EF427A6162317ED9E91A7 /* FIRInstanceIDStringEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B73657F1BCBACE23835E1CFAE2DFD69 /* FIRInstanceIDStringEncoding.m */; }; + BCC2A87AD0F14860F6B19ADA649102EC /* FirebaseInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = FC18ABE2366295F29168F13229AD4B6F /* FirebaseInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BD75C0A4D524F1F55EABC2310709B308 /* FIRAppAssociationRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E05B4C70129B7EFF74EFA170692157 /* FIRAppAssociationRegistration.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BD8B9318417E3C24B6E108A1245D1FCC /* FChildChangeAccumulator.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D04C17438C9FE6F61E8B3DC057EF647 /* FChildChangeAccumulator.m */; }; + BDAAF880CC0610608FB5C85CC2D2DE19 /* FBLPromise+Any.h in Headers */ = {isa = PBXBuildFile; fileRef = B6664E7165D5105EE3355D7B7FD1AEAC /* FBLPromise+Any.h */; }; + BDB1BFEF26F5E8828BB9AA94F29F854E /* NSData+SRB64Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 707D8125F2FAB7F6422BB626C37044D0 /* NSData+SRB64Additions.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BEB60C0A059ED0DDACE9B3E66B355AC7 /* FBLPromise+All.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C269625485B6A7289C6746D99E1EFF /* FBLPromise+All.m */; }; + BEC63CA25DAB47C32BD3889AD9D2DB59 /* pb_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 05873CB9F2FD43CA2C12872CBAF74522 /* pb_encode.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc -fno-objc-arc"; }; }; + BEE35C518925421AA701E260DC70824D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */; }; + BF1B710E5D6EF9B26D5AF0E33D6A6D35 /* GULUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A12816661B22D94EE76C808C4D2C /* GULUserDefaults.m */; }; + BF58D2D9988D1AC7206E61E20842F1D5 /* FBLPromise+Testing.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 4C5151EB7A134D6CB59D6FD68C17EB14 /* FBLPromise+Testing.h */; }; + BF62F42B4AB545D89B1E5F573481EAA6 /* FIRInstallationsStoredAuthToken.h in Headers */ = {isa = PBXBuildFile; fileRef = F9896C33DDA84C01B16BAFBA8D05642A /* FIRInstallationsStoredAuthToken.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BFC4F89E3D91D2265FFC4D1E0BAEE473 /* FIRInstallationsStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AB26A53B7AF9F47ABC78485EF2137FB /* FIRInstallationsStatus.h */; settings = {ATTRIBUTES = (Project, ); }; }; + BFE36AC51520DA7A0D3DCD7C82E6ACED /* FNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 9B00ED90C4A7935626C4626A06EF9B8C /* FNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C047E8F3590D88BEA7EE7169952A8667 /* version_edit.cc in Sources */ = {isa = PBXBuildFile; fileRef = 94541BC6EE0BD2BEFDF6CD8A2EE668BA /* version_edit.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + C0E9002DF488FE3C7EB377DCB60489E5 /* FBLPromise+Do.h in Headers */ = {isa = PBXBuildFile; fileRef = 224AFDDED1449BD5811E120270B60A6B /* FBLPromise+Do.h */; }; + C119D47F74B1B6FCDFF11594BB63AC42 /* GULSecureCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A7E1843FD613F018523298FB0DF7927 /* GULSecureCoding.m */; }; + C1E4769235EFCB2083CEEF1FB91FF90C /* FIRStorageTokenAuthorizer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3246B27D9A917C54052A78F54307238 /* FIRStorageTokenAuthorizer.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C34D0883D644A8776DC5B9FFADBD1BD3 /* GULLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = E1D04018157FF78C2C0FE18C2BBFF9F9 /* GULLogger.h */; settings = {ATTRIBUTES = (Private, ); }; }; + C3E2919B411BA3CF158348803AF1E82F /* FQueryParams.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CE95ABB415602B3D411D9B619A4E1A9 /* FQueryParams.m */; }; + C3EBD3D0966FE8874E7F89CDD15A3B86 /* GDTCORLifecycle.h in Headers */ = {isa = PBXBuildFile; fileRef = F41ABEC6B1F1039CE216732C698269B2 /* GDTCORLifecycle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C435E0AAAADD2B845ED62B61CA942AAB /* FValueEventRegistration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0014856EC9AAD4D35366C287A7B9B14A /* FValueEventRegistration.m */; }; + C45F8382F9374D3B1FA2FA441A672268 /* GDTCORTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 68B8803604DCC5D6E7CD419A7B2933F5 /* GDTCORTransformer.m */; }; + C48DC50EC6F56D8DCF49AD3A41FEEF06 /* FIRServerValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 194C2F1E5104D28EFFB7D4AA2CD4BC46 /* FIRServerValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C4980A12D0365C6B5A7FB9BE99591F51 /* FSnapshotHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = B55FE2E8404E0FF6108ED090BF7F4B51 /* FSnapshotHolder.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C4BBEEA190A095C9901FCDDB1E68F409 /* format.h in Headers */ = {isa = PBXBuildFile; fileRef = E05235154C224436E6591861CD028C05 /* format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C4C43A44D26E7EFA74170AB5656AF8B3 /* GDTCORRegistrar.h in Headers */ = {isa = PBXBuildFile; fileRef = AE506B6FA93C8C128423247BFB7439C0 /* GDTCORRegistrar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + C5615055335733CDDA1F38C5F1FF18F8 /* crc32c.cc in Sources */ = {isa = PBXBuildFile; fileRef = 390419A5519751A14BED14EC54F229AF /* crc32c.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + C5C1AA2278E0981C27C7FC6B830E78D9 /* FIRInstanceIDVersionUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C4608282EA2EF296797D3E04024663A6 /* FIRInstanceIDVersionUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C5D55C124298CF890A5B11A04B7DA7A6 /* GTMSessionFetcherLogging.m in Sources */ = {isa = PBXBuildFile; fileRef = F5D1434B5914AC5EC2EFAC3B3AFA8B3A /* GTMSessionFetcherLogging.m */; }; + C669DCFA7234B9F5B49D19B003F14F57 /* FIRCoreDiagnosticsConnector.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F890C9E8FFF45508AAFF1DF9F44F1C /* FIRCoreDiagnosticsConnector.m */; }; + C7A0CB2A71F338ACD6FB638CA44FD03C /* GDTCORRegistrar.m in Sources */ = {isa = PBXBuildFile; fileRef = D448C9B8697D1412FE36F767443E3199 /* GDTCORRegistrar.m */; }; + C7B7396F092BAEC6F052E521D27F8B28 /* FBLPromise+Retry.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = F74357951D0E0FCFAB5F7DE7D9B10AB9 /* FBLPromise+Retry.h */; }; + C7B88A7AF4DC14A4D9E0394E4E60CEC5 /* FIRStorageComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 88F58F93946BE6895E8BBF7AF2D2D164 /* FIRStorageComponent.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C7C7C8A4A99E2C549BC4E20490093F89 /* FEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AB25ED792C29BE405E3B3CD3A8F2EF0 /* FEventEmitter.m */; }; + C9A8B33C6517A73354D4488B13E64B57 /* FBLPromise+Await.m in Sources */ = {isa = PBXBuildFile; fileRef = 2BD2F054BA7A505A5CF0CF32893BF976 /* FBLPromise+Await.m */; }; + C9C0A1BDF76F95B0012D094BBABCDC89 /* crc32c.h in Headers */ = {isa = PBXBuildFile; fileRef = 31B1AE108730E173979B504D5E7431DC /* crc32c.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C9CA958CEA35B968BECF9CD99C750F0F /* log_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 330BA0E97DE040797CA80B20D2DBFD22 /* log_reader.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + CA31E125CB6F5EEB01582E3F9FA45900 /* FSparseSnapshotTree.h in Headers */ = {isa = PBXBuildFile; fileRef = D5E4EF988C712EDDFC300B001F7A0C7E /* FSparseSnapshotTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CAC96738E23FBDAE61A6D00359F9DF67 /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = 53B1117013327054ED85001947D836A4 /* logging.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + CB48A1F715EB71F01CA213657B87F4B5 /* two_level_iterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E807E38FDEA4D03D392C95EC28E738C /* two_level_iterator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CC08E6C4FFD5413612BE1D7ED3CE22EF /* FRangeMerge.m in Sources */ = {isa = PBXBuildFile; fileRef = 489F989E3EF4CC170458E2F7BACF34A5 /* FRangeMerge.m */; }; + CC1A1197F3C84723E2D823E87DFA2F1B /* Pods-PediatricPancreas_Storyboard-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CB49879889C49984CF1E9264CD820068 /* Pods-PediatricPancreas_Storyboard-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CC2C0BE45973FC0CAAB0EA0DD82C68E1 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */ = {isa = PBXBuildFile; fileRef = 74CDCD1E534C5FA7C7571D7246388818 /* FIRInstanceIDCheckinPreferences+Internal.m */; }; + CC3676812D759C6FD587820C0DBC0C6B /* FIRRetryHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 67AB9E7A57BC5C8FD59ABE9097063C35 /* FIRRetryHelper.m */; }; + CC58E23726F7AE4F75A3C61B793A2831 /* FTupleTSN.m in Sources */ = {isa = PBXBuildFile; fileRef = 37B02A7BCA4D800A027495A301A5E818 /* FTupleTSN.m */; }; + CCB6D21D1AFCAD82AF282CA2D1EBF49A /* leveldb-library-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6FBACF296A5333288E22B9978DF7798E /* leveldb-library-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CCE70E7976B3859DDC23F2F06C5B54F3 /* FSnapshotHolder.m in Sources */ = {isa = PBXBuildFile; fileRef = 90EFE7C5E29A5A1DC18F8FFE9C38ED1F /* FSnapshotHolder.m */; }; + CD9A6E834DBDCB1929D472C0C5079A08 /* NSData+SRB64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F41AD0ACE33C987BAC1374E6B1320A3 /* NSData+SRB64Additions.m */; }; + CDE60789D578C150075686DA4858E058 /* FBLPromiseError.h in Headers */ = {isa = PBXBuildFile; fileRef = 788528DEECC60A3130BFE6A2DD831079 /* FBLPromiseError.h */; }; + CF5FD6EFE83C8F4C8B2A868E7393CAEA /* FIRCoreDiagnostics.m in Sources */ = {isa = PBXBuildFile; fileRef = 9384A9222E3CA4ED907B7F7FD64AFABA /* FIRCoreDiagnostics.m */; }; + CFED822B928298F5A0E727674813A92D /* FWebSocketConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 96AD2BF11C0A8B331AAF6F623FF7762A /* FWebSocketConnection.m */; }; + D13AE8C940F401A4565B7ACFA42AED8E /* FIRInstanceIDCheckinPreferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 21C9F5A07D09B15611C75D123DD8396B /* FIRInstanceIDCheckinPreferences.m */; }; + D1622A62EE504256DBE10CF51F67975B /* FTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 244B4E0C8D9ED4451E9A26BF10BB836E /* FTree.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D1844E585A85E6C0B99654FBA152382E /* FIRInstanceIDStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 906F798474B836189059B9A51D6BBFBB /* FIRInstanceIDStore.m */; }; + D1FFA9ECFE6F7758D887320EF104DE5E /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E27E74E05C98E0B5F68063DCB85240 /* snapshot.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D241681D6846AAAA94E6E1C3D3EBD9E6 /* FTupleTransaction.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A2482A6E24283C2687635398220B20B /* FTupleTransaction.m */; }; + D29A6B422C3BBB02E8C924045E2FACF5 /* FLLRBValueNode.m in Sources */ = {isa = PBXBuildFile; fileRef = F27AD869EA4F65CDB13697DDE36D24E0 /* FLLRBValueNode.m */; }; + D29D79614CE914BDEFD03A6367D9030C /* FIRInstanceIDTokenDeleteOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB94A073C78837518C58FDBB49EE385 /* FIRInstanceIDTokenDeleteOperation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D3103BDBD1CC376D54BFC859EBFD233D /* FChildChangeAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 93C88B8F3BAB0E426BD1EFF9B685F904 /* FChildChangeAccumulator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D3CDC4D016687D9ABCF4A86EE5A2C994 /* FPersistentConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BB4BB40C8BAC7ADD48C45341955554A /* FPersistentConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D4533645AECEFBAEF365BD3D371C11FB /* pb_decode.h in Headers */ = {isa = PBXBuildFile; fileRef = 15853D21D1AFFB8499F10A9CB08B835C /* pb_decode.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D47D7135085458EC266BD4C8682F06E6 /* GULOriginalIMPConvenienceMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7F761B656167D3B87EF50DE069B696 /* GULOriginalIMPConvenienceMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; + D49BB466034BB998F9D122F9B5743E36 /* FTupleUserCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 6F17AA9202487602D6AB7C3285CD4697 /* FTupleUserCallback.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D4F6BA0702DA90CC376ADAD732BA71EC /* env.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9295AFCFC39BB1FDBB0EC3D9ECCF37CE /* env.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + D67D3C6167A627C95BF7B1BAF6193B0B /* FSparseSnapshotTree.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B5054CF11B84CB3FA9A573C0176038A /* FSparseSnapshotTree.m */; }; + D69FAAC0FB29982BACC356F973EC8C33 /* FIndexedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = C849D3E9FF9EB2A0EE26851441710E41 /* FIndexedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D7262E5CF3EE19D4075C38EA4613E224 /* db_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A4EAEA519CDE2E290007A2243F72CBC /* db_impl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D753FA9673411EDDE9CBC1B1D6B4BE46 /* FIRInstallations.h in Headers */ = {isa = PBXBuildFile; fileRef = 59F63533E39055260C58815ACE106993 /* FIRInstallations.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D75F1B505F85888AF493B7FF7333F596 /* FIRInstallationsLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 99445128B63465CAA78511775C044826 /* FIRInstallationsLogger.m */; }; + D7B2568B93A8855C75A2D9893CEEE396 /* FirebaseStorage-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E569D8C956BCCC66778E7660040E4E /* FirebaseStorage-dummy.m */; }; + D81BD423C792CF4930C1137F1C1FD41D /* FIRInstallationsIIDTokenStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E65C6252D7B9C6219B60EF273C7BD3F /* FIRInstallationsIIDTokenStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D86E16705CEB928565E15EF6603CC284 /* FNextPushId.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4A4BAB38692F24392EAFB5C9645180 /* FNextPushId.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D89DDCAD361741ECA2CA115601BA5663 /* FIRInstanceIDBackupExcludedPlist.h in Headers */ = {isa = PBXBuildFile; fileRef = A841629ECEDFBFB7FF0841EF6C8E1E28 /* FIRInstanceIDBackupExcludedPlist.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D931B8E1268C9CF58432AF78C5FC798A /* FIRMutableData.h in Headers */ = {isa = PBXBuildFile; fileRef = 17527F81C485EAD0DA6BDDB41CE38598 /* FIRMutableData.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D9BFE6EE614608A3B9CA2C16403EDDA3 /* FIRInstanceIDCombinedHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 64409ABC3DCB79196DA6ED00E0308A43 /* FIRInstanceIDCombinedHandler.m */; }; + DA2F583B9ECE9612978CB7347B1372C8 /* GTMSessionFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = EDB960BBC8F94DEF008EF48F34DC8AE6 /* GTMSessionFetcher.m */; }; + DAA1263EE3BA44CA628D70158C0EFBAE /* GDTCORTransformer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 52395DE321F4785481C559231D4936A9 /* GDTCORTransformer_Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DAB3FB4565600539E11B01572756D2E2 /* FTupleStringNode.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8D40B6AFCF5F6C29F50AB149BF8282 /* FTupleStringNode.m */; }; + DAE6C5E0795DABC15B3B87B089F22F58 /* FBLPromise+Delay.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD4AD8A942A3CD434EDBDFC70B5CAE8 /* FBLPromise+Delay.h */; }; + DB53EAAD6F40751E21FFF59D4B388515 /* FIRDependency.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DED8B128D826A18F00619CCFDF72995 /* FIRDependency.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DB957918731AA083B784B9C7FC626F6E /* FIRInstallationsAPIService.m in Sources */ = {isa = PBXBuildFile; fileRef = 05E19944C7BC20A465DA3DE28DB49B0E /* FIRInstallationsAPIService.m */; }; + DC241C4495CC6CD95E50D4AD19556260 /* FIRInstallationsErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 5327239BCECD082DD39C0F036B522DF7 /* FIRInstallationsErrors.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DC369AB43B3D1FB1CEEE74B1D64420C1 /* FView.h in Headers */ = {isa = PBXBuildFile; fileRef = C0EB6D5853B9601249F3331602421954 /* FView.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DC3B0995BB8B588FAC007CAA357D50D5 /* FTupleNodePath.h in Headers */ = {isa = PBXBuildFile; fileRef = FD8E96626EC223FFE031515C273E16FA /* FTupleNodePath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DC66204BDCAEAABE6F58AD23B812E21B /* FImmutableSortedSet.m in Sources */ = {isa = PBXBuildFile; fileRef = BF8836BA9AAA1475DEDA54342B0F927B /* FImmutableSortedSet.m */; }; + DC813E9A9C54EE937F0EBB7894ACD47F /* FBLPromise+Always.m in Sources */ = {isa = PBXBuildFile; fileRef = 46109B02A1531B0A8FF22CA39EF12E40 /* FBLPromise+Always.m */; }; + DCD1917F472DCA0394AC42C653F985E0 /* GULAppEnvironmentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 107EEF2DDC74972CC27D7B59D733DE16 /* GULAppEnvironmentUtil.h */; settings = {ATTRIBUTES = (Private, ); }; }; + DD18C482342841FE2C0F62FBD342AAE3 /* FIRDatabaseConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = A5B6CB88832D4E926A10C1260DDD5B26 /* FIRDatabaseConfig.m */; }; + DD1A73622491FB1154B58CF81AC7635E /* GULAppDelegateSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 8796EE5E561EE5AC1133A1E430CD4EE0 /* GULAppDelegateSwizzler.m */; }; + DD28FF1388C380AB61723D5A866DAF45 /* FValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B544FA9B3431D609145527D612E6563 /* FValidation.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DDF4E3845A849A316A90A82FBFCBF6B6 /* FIRStorageListResult_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = C7B2ECE638DABE730837F22C5CC35FB2 /* FIRStorageListResult_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DE5127503E0B3121728A9C378CB6F646 /* log_format.h in Headers */ = {isa = PBXBuildFile; fileRef = 141087222BACACD95D911E82A46EE9A1 /* log_format.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DE76C40DF0294BB958BB87675C02DDF9 /* FIRInstanceIDUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = E403FD09A6EDAA770ACD23EB7E750605 /* FIRInstanceIDUtilities.m */; }; + DEE47D10701E5457D744D9911388A67C /* posix_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 5139CF30473560788ABDCB14D62A88F7 /* posix_logger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E018635E49B5FD51E549A42412B1007B /* FIRStorageGetDownloadURLTask.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CE038EBFA6A42EE048F83E4B840E76F /* FIRStorageGetDownloadURLTask.m */; }; + E01CA51DA38E4CE6C592826095290FE0 /* FRangedFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = EC472A7E11E0AF865D19CFCAF9A72A0E /* FRangedFilter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E025D3364F92AE27EEAA46349A9A1FD6 /* FIRDatabase_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 87F6444DE4F1D787D0B1FB58BD680119 /* FIRDatabase_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E0454F4406F2F6D99F67B5BB7714F6A7 /* comparator.cc in Sources */ = {isa = PBXBuildFile; fileRef = A29247354C87D56646F76034F1DDDCFB /* comparator.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E0BAF15488BBDC150E9189768245B0FD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + E0EE15E9D3F86F49D116A9FCC5806C80 /* FOperationSource.h in Headers */ = {isa = PBXBuildFile; fileRef = D1784750A2945CB885B1E0E6B9FD4D8E /* FOperationSource.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E1019446F7D2644FFCBD73C31DBB0847 /* FIRStorageListResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 400B4EF49B532BEB9532849F5FD07F5A /* FIRStorageListResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E1955EC9F66FC352251073FFC1E01376 /* FBLPromise+Race.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = FBFD83C5D86D93B245CD240C86246263 /* FBLPromise+Race.h */; }; + E1EEFF5D8FBFE19F70F73FA7AB89256F /* FTransformedEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 95E6DE4A2B320864D331EB38E2425AD8 /* FTransformedEnumerator.m */; }; + E2795A9FB59C5E9E8ACE0A0274C7FBEE /* merger.cc in Sources */ = {isa = PBXBuildFile; fileRef = 155EA6AF78AAC81C5A5EA1DE64050B53 /* merger.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + E2A4DEC1BF2DCBE4C91B541A481DFEEC /* log_reader.h in Headers */ = {isa = PBXBuildFile; fileRef = F2CC73872DB886E14A2366F2B113982A /* log_reader.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E38885D124D3963B62B19DA1ECBD50E7 /* GULReachabilityChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 5201DB2D923D20FB1DB7E6BF7295229D /* GULReachabilityChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E3CD894872245BDD43B912BBC60BCEC1 /* GDTCORConsoleLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = F22F1DCA0BFD189772156B0071867DE9 /* GDTCORConsoleLogger.m */; }; + E3FCCAA4EDFB0A3CFB02048CD44A6DDA /* FPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 250AA97D89AEB8E9740DE1F693CD6303 /* FPath.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E42A0E8B4190A2236B8FBCAE5213E56B /* GDTCORStoredEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = C9D62FF736B44971DF9091825EA70670 /* GDTCORStoredEvent.m */; }; + E442CE0E937527C6C747AB5E4C78C9A4 /* FListenComplete.m in Sources */ = {isa = PBXBuildFile; fileRef = B1A12E1B5F9F863A9AFEF72FD5DC75BC /* FListenComplete.m */; }; + E469A3376472C43FFF2A26B7E68A4A32 /* GDTCORStoredEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F04DA8747EA8BE73026D773DF27B3AD /* GDTCORStoredEvent.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E4AF342C6E516D164AE805048E0A1779 /* FIRStorageErrors.h in Headers */ = {isa = PBXBuildFile; fileRef = 2048A7357F01687FD8F3665E48D84747 /* FIRStorageErrors.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E51F20C7985E6AB9FAAB08BACEFFED9A /* FCancelEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D9FA396FC4735E76B98DBFA4F74A73EF /* FCancelEvent.m */; }; + E5A77EE1434FF9ABCE6726072B416E7D /* FArraySortedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 334A858E767B7ABD572D6D2F1F9EECAF /* FArraySortedDictionary.m */; }; + E5E504F03A20C48C531D96698E8D921D /* FViewCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 792AFB5085BC525196F9BA0AE3A01326 /* FViewCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E624E062F40F024B87C07635FD7F8337 /* FIRInstanceIDConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = CD0EFB5FD41F0F3B6F7CA637FEE7CD77 /* FIRInstanceIDConstants.m */; }; + E66E899B714EC0D889376587705AA280 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + E67063C0F04726CC695F621A05097687 /* GDTCCTCompressionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = E14A19143EB768AC61D16C115E81F4D0 /* GDTCCTCompressionHelper.m */; }; + E811EF77152AE3518910050E8A79838E /* FChange.h in Headers */ = {isa = PBXBuildFile; fileRef = 41813E5BC58F89CA3B1728140B44B6A3 /* FChange.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E818EDB2D704D61FE5704437DEDADB2C /* FIRHeartbeatInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 297EA095162F086760B8783BF73A1D20 /* FIRHeartbeatInfo.m */; }; + E836BAF8C30B308B105A4396A775B39F /* FIRInstanceIDVersionUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CDEF6C17D03168126524359F161CB71 /* FIRInstanceIDVersionUtilities.m */; }; + E85B408CB57586431D8F0C365268D4C9 /* GDTCCTNanopbHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 059FD50937C2B1086A8FCF3ADC371B8B /* GDTCCTNanopbHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; + E87A2038DC2E45F0D997FBBA114E751F /* FOverwrite.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A98BA1F60CC9765DC24CD540AF2E6A3 /* FOverwrite.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E88676E726AD5E95AEF7070FFAD60660 /* NSError+FIRInstanceID.m in Sources */ = {isa = PBXBuildFile; fileRef = D17245470BF0B46FF5A077C52AFD2803 /* NSError+FIRInstanceID.m */; }; + E90A85D8E0E4F114DDED6C5FAE9E9B29 /* db_iter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B30443859D305A810204C8278AEB271 /* db_iter.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E96E4B5E3B8024E8BC9C40948616F733 /* FBLPromise+Do.m in Sources */ = {isa = PBXBuildFile; fileRef = 5CDC4558A7037B459CADC5E3F8DB0B33 /* FBLPromise+Do.m */; }; + E9B0DC6D113276BAAA73E21CCBB62405 /* FIRStorageUploadTask.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F1CC7A848EE5F4DD8AFD48F48C16C6 /* FIRStorageUploadTask.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E9BC50FC3603B8FF93D78C2A62983D54 /* nanopb-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B6E9B7C31546F012D471390B2E511490 /* nanopb-dummy.m */; }; + E9BF1A5ADF89EBD75DDF91246D02809B /* FIRInstanceIDCheckinStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 370216E4EF7609FBEC6F9EABA8562C55 /* FIRInstanceIDCheckinStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E9E8CA0DDC6041BBF6A68B8E52090900 /* FStringUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = FFC87D297C3C3484EBF939B420C4EBAD /* FStringUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EA56A5F2CCC146B819B9B021B73B664C /* FIRStorageReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 50950C3AE1D36D0DFFC58C5E1C571B02 /* FIRStorageReference.m */; }; + EA936B59DC28C23ACF1CBE125E7718C1 /* FBLPromiseError.m in Sources */ = {isa = PBXBuildFile; fileRef = 774ACC4D4332DC492738A1293DCAE200 /* FBLPromiseError.m */; }; + EAFAD4163B7DB72562603E8371DEFA68 /* GDTCORReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DD98E9DFFAF9630E85D5AA939CC6FE2 /* GDTCORReachability.h */; settings = {ATTRIBUTES = (Private, ); }; }; + EB096D368174CCECCF0D2BA36D208B37 /* FIRStorageTaskSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 022E69B7A3365C89979582D7FBF6F5CC /* FIRStorageTaskSnapshot.m */; }; + EB5A30ADDD05C512297605FE48C39CB6 /* GDTCORUploadPackage.h in Headers */ = {isa = PBXBuildFile; fileRef = A4E1EB8597FF3EC84853B45630CA42ED /* GDTCORUploadPackage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EB89130CF60E605E86BA02872F7ED0BA /* FBLPromise+Timeout.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 8151357CD1DF92DA0968F4263590737C /* FBLPromise+Timeout.h */; }; + EC2EECECD2279FC03827652CD100C789 /* GTMSessionFetcherService.h in Headers */ = {isa = PBXBuildFile; fileRef = EE496FABD67CAAF80A37A368BA2DFF3D /* GTMSessionFetcherService.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ECD2747D43E1AD3C38C38E0D34BED9EE /* FIRStorageGetDownloadURLTask_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BAEE7AB26C4A136E7E3F4B44E7BEA97 /* FIRStorageGetDownloadURLTask_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + ED104CA7FAB817196409F4628EC34B78 /* FIRLoggerLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = A1E7B8A283EC1446D5E09B2F3647012E /* FIRLoggerLevel.h */; settings = {ATTRIBUTES = (Public, ); }; }; + ED1B544A0F6CF645915DC76DD34FF679 /* FirebaseDatabase-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E9BBCC3054D48A4CD2B5D5D10A50E38C /* FirebaseDatabase-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + EE265235E6C44A2B23C94F458ECCC8FB /* FUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 69AF1F488EDABE86507D79D8AFF1E55E /* FUtilities.m */; }; + EE7BB1E13A26E35B39ADFC7D4B56D80D /* FWriteRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = 3975CADB3F0440D001CE42671FD82B69 /* FWriteRecord.m */; }; + EED214C55E222403C1D5EB753D863DCA /* FValueIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A96090A085525143C604ABE9DD7A8C2 /* FValueIndex.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EF345A619B91C20B6B8BE46FDEDBCC77 /* iterator_wrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F5B4E47D4F948AB4781BE06654B0B1A0 /* iterator_wrapper.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EFA1831C9A10F6FA481B87383F1E41D5 /* FPersistenceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AC599B33E662AE5F07C790B72D2C0BA3 /* FPersistenceManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EFB6F1B26ED2B0373F0D731255F5773F /* FIRDataSnapshot_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 76076FE9A810D6F3BB2702942C80DAE1 /* FIRDataSnapshot_Private.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F0C386075EA179A50E66B642F0F9F0F1 /* merger.h in Headers */ = {isa = PBXBuildFile; fileRef = D0DFD8426C0E3D2B694A39A96102CAE8 /* merger.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F15A28D41D32CBFBB684103037D42EDF /* FTupleFirebase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2339CB4AB1EFFABA9FE159FDF9CABBDD /* FTupleFirebase.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F1AE420BF3679263627A8331203D0328 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + F21A40D690B2C7A2DEC81F926C36BC73 /* FBLPromise+Catch.h in Headers */ = {isa = PBXBuildFile; fileRef = A02930679CA97D007C20B3DF2C78DA38 /* FBLPromise+Catch.h */; }; + F33783FAA7F1D799CE7EF388FD407556 /* db.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E1A7752DD11EF21A11603EF886B6447 /* db.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3F6C01A5AF8569D54E59FAD714EF276 /* FIRComponentContainerInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 68E9186DC5A562BB4509641DC981B866 /* FIRComponentContainerInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + F43B7DCFE0826550D972986707BDDCC4 /* table_cache.cc in Sources */ = {isa = PBXBuildFile; fileRef = 61853C19FB27025E1FDBA8BAB314FCCC /* table_cache.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + F49CFC15763573F573C74BFBC260FDD8 /* FParsedUrl.h in Headers */ = {isa = PBXBuildFile; fileRef = AD92B971F394927786C8101BFD4C07E0 /* FParsedUrl.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F51A4C01270848A6F2583BB316AA6B43 /* histogram.h in Headers */ = {isa = PBXBuildFile; fileRef = BA2003C66B9E13070828B7FF4822C7EB /* histogram.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F556C8734F8F8AB26A777068AFFC8817 /* port_stdcxx.h in Headers */ = {isa = PBXBuildFile; fileRef = BC53E9479AFE30937D40541E9A3C3A67 /* port_stdcxx.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F568FC176BB78F4A7F9C3DB2A823246B /* FWriteRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 033D1DE42F6AEAA2F2FE9CF6AE4B70BD /* FWriteRecord.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F597291457E81538D19FEC0CAFCF6517 /* FIRDatabaseQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C899CCE4B5ADC63B99D167B4F6C09D9 /* FIRDatabaseQuery.m */; }; + F5E900C53C41B147E4F72C06F1C310FB /* FNamedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F83CEF39EB3C9712DC040CEA8502D78 /* FNamedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F6237E72428D8021D2B69E8E71A9EC8F /* FIRDatabase.m in Sources */ = {isa = PBXBuildFile; fileRef = 632E5D0FA81F7B8874C7A3343EB12F62 /* FIRDatabase.m */; }; + F68BCE89AE6C3311B11C34A92D43D21C /* FBLPromise+Wrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 66009FB9A96C02DE9E78F386B5D6E14A /* FBLPromise+Wrap.m */; }; + F78D02843626AC2ABA1D794557608E99 /* FTreeSortedDictionaryEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = ABC50885F71A3B759ABD6A64762A0E6D /* FTreeSortedDictionaryEnumerator.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F83AB8BEBC3EE24CDFD6054A32777D31 /* FBLPromise+Do.h in Copy . Public Headers */ = {isa = PBXBuildFile; fileRef = 224AFDDED1449BD5811E120270B60A6B /* FBLPromise+Do.h */; }; + F855AEF04B44D6F5B299DE45F255EABF /* FIRInstallationsKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = A24FE0E7A20BBABF063F9974EE71BD68 /* FIRInstallationsKeychainUtils.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F860CF248BB1315D65608641EA6E457A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + F8DDD059A033A7ED85707270A939E394 /* FIRInstallationsIIDStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FC2872D62DB58E74049962B6F9FC53 /* FIRInstallationsIIDStore.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F957C58A6C1486518C11B1673D527696 /* FConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 47F6BCA1337943A0F0648467B2AAD1D7 /* FConnection.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F9C8C5887422C8EED02F764349DF5F6D /* dumpfile.cc in Sources */ = {isa = PBXBuildFile; fileRef = 50EE24DC0A427CD4D94FAC3BB1119197 /* dumpfile.cc */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + F9D0A266CB35C375FFFF03428B064677 /* FIRInstanceIDAPNSInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65A05577DB4A1FC0196B42515C4A5936 /* FIRInstanceIDAPNSInfo.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F9FC09F7E6F71FE9C3562FD0E5ED9B02 /* FIRDatabaseReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 6AF4EFB562C4F2ACC556C482569CDAC7 /* FIRDatabaseReference.m */; }; + FA2671747739AA8D4B2A91A6E8B98ABC /* FViewProcessorResult.m in Sources */ = {isa = PBXBuildFile; fileRef = EF4C1A8DA8015C4C9565AA9AF3BBF375 /* FViewProcessorResult.m */; }; + FA9EFF6D5A591DC2149A1F8965BB4E09 /* GDTCORUploader.h in Headers */ = {isa = PBXBuildFile; fileRef = 304BB26FD24F626815E78336619266C5 /* GDTCORUploader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FAD80A624EBAB6374BA83F2CF0097F8B /* FIRInstanceIDCheckinPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 764C432940EFD97B8CE3336C8257B57E /* FIRInstanceIDCheckinPreferences.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FB93839AE195233F516E25E855763E06 /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = C9A065473A00B170B362BDB7ECF1B77C /* hash.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FBC70BD28D97C01F322043960996DA80 /* logging.h in Headers */ = {isa = PBXBuildFile; fileRef = C7CE15484C79764DF2F6200480570299 /* logging.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FBCFD169B08BBF258597A1026AADFCE1 /* FirebaseDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = F5E0E11BE35D93380875787C9803A6CC /* FirebaseDatabase.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FC894422B5D2B621D5A8D940CCBC1D14 /* GDTCORStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 90D43FD412508EEDA57DF27A754BBC88 /* GDTCORStorage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + FC95DD1B5A91CBA5DD357F64654159EC /* GULNetworkConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B90CFA09998FA5040F032B04C452424 /* GULNetworkConstants.m */; }; + FD00057352D62F190E3FF7E0C2B7CB9F /* GTMSessionUploadFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F04B2F4684D4B3EA35FD95BF17E07F1 /* GTMSessionUploadFetcher.m */; }; + FD5CDA516E0C702C5630EC560E660F4A /* FRepoInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DADF937F52289F4BDB16AE7DB822B058 /* FRepoInfo.m */; }; + FDECC79C340C9366B4458A31A783E7CD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */; }; + FE88BBBBF16F3F855EA9FCE6AF54FF34 /* FBLPromise+Testing.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C5151EB7A134D6CB59D6FD68C17EB14 /* FBLPromise+Testing.h */; }; + FE9E1C9273191A1109C91760B86A5372 /* FIndexedNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 265E98998557D90106A27053DB002C6A /* FIndexedNode.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FEC5E3D048685E51D290B22735BCF647 /* FEventRegistration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7C15052C0D43C705657358284FDD5A /* FEventRegistration.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FF2335F3442E339F9251BB26CEA3AC66 /* block.h in Headers */ = {isa = PBXBuildFile; fileRef = FD8DD3CBCFCD6D546467D83131DB9AAF /* block.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FFAB3C9E798AD12B4F1274FC275D1491 /* FConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 42F9237E26387A51DA413989DA2C49FD /* FConstants.h */; settings = {ATTRIBUTES = (Project, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0519A6B5FE41B00CC60376A6AA85F241 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 0E235A75C7262F1B8D7A216138B30175 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + 115550D29A90177B2A9E25D611F0AE12 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 118F38B29BC1C109A477C92A35BFAD9D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 1963FEB2F2F3883CEAF178DEC2E4ADD4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + 239095B7E773EFC58377C4DECC74846F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 239A22790B2934FA257A90BEAA0DC845 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + 30BE08EA5B5CC1196FD7D75E6989C3A9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 32B9D3BE4A4FD98D1A5A9E67B7A878AE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 32D6A3B0BFB1FD13F7CB6C0D22A1EEB7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + 35F9ECDBCD941C37EE58DD1C3022230F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + 3AA9A0191F50B4235987601396354AF9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 3B2519791314D28CBDD44813F64C14C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 072CEA044D2EF26F03496D5996BBF59F; + remoteInfo = Firebase; + }; + 3C5ED0ACF5CB34BC99CDEC9681102C9A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + 3F371FFFA962F3D07B2A1C57995FF34C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 23E7C4A52360C026F97E4A96D91B03CE; + remoteInfo = FirebaseStorage; + }; + 4886473D196C96F8F1B7553251A3326A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 4EEA44DD7E76B742438269A75A5E8C30 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 57262A096B9144EADF9AC78310B9B344 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + 596EB1EB99F8552A8774B47E5E4871EA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + 62DBC3ED071795C969F8C6006A0EA4D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 620E05868772C10B4920DC7E324F2C87; + remoteInfo = FirebaseCoreDiagnostics; + }; + 67D8E91B757D81888ADED8270649CA0F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 742D6BE3D55B692C13E4BD4360EC7AE7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + 750DCA08ECA626D07B691DB359E31682 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9E25537BF40D1A3B30CF43FD3E6ACD94; + remoteInfo = FirebaseInstanceID; + }; + 7B02A7C3C437936B9A2619F121D4D8BA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5EB4B0B6DA6D5C0C3365733BEAA1C485; + remoteInfo = FirebaseCoreDiagnosticsInterop; + }; + 7B9EECB0CE62C0C4FB325BB4FA4BD090 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 8ECBD339FFD46206CA2A38035E5D816E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + 8FF2A32E1C7581EAEFEA63B453BD4FAA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + 96A9760A4B0DEEA3CB72F01707497E91 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 736AF68F6527ACF6B4A4C54728824A1C; + remoteInfo = FirebaseDatabase; + }; + 9770B6A8B0453660EA5B9F94F9CA39A9 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D676E21115185671D7258A56944ABE98; + remoteInfo = GTMSessionFetcher; + }; + 9861A9465DB23D225E71FC48960CF619 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + A451A85BCCE1A5286398D6E7AD5856DE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + A71270B0D0EF2F59141A961F77CE4FA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + B591ED0C9CF201C628766AFE46C6A8F4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + B67FB31C218CEFFCA7F96092FC79C92E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F4F25FCAC51B51FD5F986EB939BF1F87; + remoteInfo = GoogleDataTransportCCTSupport; + }; + B93D8094B4A53F8AF336876932BD3111 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + C043B4C9C448C167FDA0A5D51485905C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + C1186E8393E89C3BF0EFBE8FCF69E168 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5C0371EE948D0357B8EE0E34ABB44BF0; + remoteInfo = GoogleDataTransport; + }; + C246C5A6CA5187AC9928E031C596A66C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B53D977A951AFC38B21751B706C1DF83; + remoteInfo = GoogleAppMeasurement; + }; + C7C50420664F1376B8397A84A1DA539F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = C49E7A4D59E5C8BE8DE9FB1EFB150185; + remoteInfo = FirebaseAnalytics; + }; + D577790062B5559EF005039852A97DF2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + D7BE435F0D850CBDFE0E7773319DAB21 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D7F5D5DD528D21A72DC87ADA5B12E2D; + remoteInfo = GoogleUtilities; + }; + DBDEA060322D6A39A0BA11D8CF8E3535 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + DD135F6A3D57CEDFAFD9519B666ACB61 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D2B5E7DCCBBFB32341D857D01211A1A3; + remoteInfo = nanopb; + }; + E230E7D796C9CA44B91416DE1C7D9A92 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9307B7A119490930CF70393AB529AAC1; + remoteInfo = "leveldb-library"; + }; + E6F12775249208F0E5031C4DBD7CBA3E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; + EAABF2C2B122D2438A851071140173D6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8EC0F2618965C875A96BFDBEE5D9734C; + remoteInfo = FirebaseAuthInterop; + }; + EE6CB9A1D7EF80B05B1AE87404E229CA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 23E7C4A52360C026F97E4A96D91B03CE; + remoteInfo = FirebaseStorage; + }; + F09B23A3B28C2C7F222D0313D2E9ACA8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2BBF7206D7FAC92C82A042A99C4A98F8; + remoteInfo = PromisesObjC; + }; + F254D49AE2D7E4B01F61AE638C0AB1F6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 87803597EB3F20FC46472B85392EC4FD; + remoteInfo = FirebaseInstallations; + }; + FF454CE06C88D8A46F7DC4DA89084D05 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4402AFF83DBDC4DD07E198685FDC2DF2; + remoteInfo = FirebaseCore; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 269B4DC8DE63FB8AE06511FBB8B22F16 /* Copy . Public Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + 4FB6E5688CE1DEF10E5EF46A40D02D64 /* FBLPromise+All.h in Copy . Public Headers */, + 51D81B007B74DF31D5A1A9C4173A539A /* FBLPromise+Always.h in Copy . Public Headers */, + B3E0AFA032C3F21E2588F3A0EA12140E /* FBLPromise+Any.h in Copy . Public Headers */, + 32AAD116A411C310EA4C466B1034441C /* FBLPromise+Async.h in Copy . Public Headers */, + 4C21648C88ADCB2009437EB6C11D8121 /* FBLPromise+Await.h in Copy . Public Headers */, + 8B7713351FD4F1EEDDB3F67E18D7B032 /* FBLPromise+Catch.h in Copy . Public Headers */, + 4AE57F500B1BBE13D09C4542EC268354 /* FBLPromise+Delay.h in Copy . Public Headers */, + F83AB8BEBC3EE24CDFD6054A32777D31 /* FBLPromise+Do.h in Copy . Public Headers */, + E1955EC9F66FC352251073FFC1E01376 /* FBLPromise+Race.h in Copy . Public Headers */, + A49C47375A61C2F57352B691384C14B6 /* FBLPromise+Recover.h in Copy . Public Headers */, + 58213DBE6ECFAD53E9CEF8F02624B898 /* FBLPromise+Reduce.h in Copy . Public Headers */, + C7B7396F092BAEC6F052E521D27F8B28 /* FBLPromise+Retry.h in Copy . Public Headers */, + BF58D2D9988D1AC7206E61E20842F1D5 /* FBLPromise+Testing.h in Copy . Public Headers */, + 5DB57E86935F4F06F66CD844CEDEED4D /* FBLPromise+Then.h in Copy . Public Headers */, + EB89130CF60E605E86BA02872F7ED0BA /* FBLPromise+Timeout.h in Copy . Public Headers */, + 8D65B36E1B3E5C2A54C55E6E061F795D /* FBLPromise+Validate.h in Copy . Public Headers */, + 6B492D24D60FA03960B5209F57D8E51C /* FBLPromise+Wrap.h in Copy . Public Headers */, + 87290DB3F2EDD697F4E6432838194C95 /* FBLPromise.h in Copy . Public Headers */, + 6E2BFCCC98EDAB76197000C0B80C29E6 /* FBLPromiseError.h in Copy . Public Headers */, + 84DF0D7211BCE3745D019AAFE8C35A1B /* FBLPromises.h in Copy . Public Headers */, + ); + name = "Copy . Public Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; + A00A245420F328FAEDAAC8E7516FBF09 /* Copy . Private Headers */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(PRIVATE_HEADERS_FOLDER_PATH)/."; + dstSubfolderSpec = 16; + files = ( + B373E85687ACBCE3AAB896CD3554E510 /* FBLPromisePrivate.h in Copy . Private Headers */, + ); + name = "Copy . Private Headers"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0014856EC9AAD4D35366C287A7B9B14A /* FValueEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueEventRegistration.m; path = Firebase/Database/Core/View/FValueEventRegistration.m; sourceTree = ""; }; + 0031AF1FB02DAD5BF0064720F7C7EBA1 /* FQuerySpec.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQuerySpec.m; path = Firebase/Database/Core/FQuerySpec.m; sourceTree = ""; }; + 004545246F93039319DCDA7ABAA016A1 /* FEventEmitter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventEmitter.h; path = Firebase/Database/Utilities/FEventEmitter.h; sourceTree = ""; }; + 0072A3F0BA7D1F7A27B20C82BFB6DFB3 /* FIRInstanceIDStringEncoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStringEncoding.h; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.h; sourceTree = ""; }; + 0072E27C9E6009B48B7F04E59F4F71C1 /* FEventRaiser.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventRaiser.m; path = Firebase/Database/Core/View/FEventRaiser.m; sourceTree = ""; }; + 022E69B7A3365C89979582D7FBF6F5CC /* FIRStorageTaskSnapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTaskSnapshot.m; path = FirebaseStorage/Sources/FIRStorageTaskSnapshot.m; sourceTree = ""; }; + 029E54A0C7F78D5174C1DE28C541531E /* env_posix_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_posix_test_helper.h; path = util/env_posix_test_helper.h; sourceTree = ""; }; + 02B9220BF322F27318370B8242BCAFFD /* FTupleObjectNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjectNode.h; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.h; sourceTree = ""; }; + 033D1DE42F6AEAA2F2FE9CF6AE4B70BD /* FWriteRecord.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteRecord.h; path = Firebase/Database/Core/FWriteRecord.h; sourceTree = ""; }; + 03937960479CC5DA69B2F6CE80C880A3 /* FIRInstallationsIIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDTokenStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.m; sourceTree = ""; }; + 0489E9C92A381651A399F3201AA11690 /* GDTCCTNanopbHelpers.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTNanopbHelpers.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTNanopbHelpers.m; sourceTree = ""; }; + 051ECA26E694DE464F0B2262039F89BD /* FTreeSortedDictionaryEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionaryEnumerator.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.m; sourceTree = ""; }; + 057F8B6F54F1827EA608534EE8AE4208 /* GULApplication.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULApplication.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULApplication.h; sourceTree = ""; }; + 05873CB9F2FD43CA2C12872CBAF74522 /* pb_encode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_encode.c; sourceTree = ""; }; + 059FD50937C2B1086A8FCF3ADC371B8B /* GDTCCTNanopbHelpers.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTNanopbHelpers.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTNanopbHelpers.h; sourceTree = ""; }; + 05E19944C7BC20A465DA3DE28DB49B0E /* FIRInstallationsAPIService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAPIService.m; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.m; sourceTree = ""; }; + 0634A83F899FE66CAACB549A4DE98343 /* GDTCORUploadPackage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadPackage_Private.h; sourceTree = ""; }; + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = nanopb.framework; path = nanopb.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 071ED579E4A1C9D1C68506228B44FC8E /* FEventGenerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventGenerator.h; path = Firebase/Database/FEventGenerator.h; sourceTree = ""; }; + 07ED1B1B3F489527C7662FED486F7315 /* FRangeMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangeMerge.h; path = Firebase/Database/Core/FRangeMerge.h; sourceTree = ""; }; + 08F10222301531C836C3CE7358FAF158 /* FirebaseCore-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCore-dummy.m"; sourceTree = ""; }; + 0902E4607D9246B44AFA3EDCD2FDCE51 /* env.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env.h; path = include/leveldb/env.h; sourceTree = ""; }; + 093D5D062733F074DD56AA1955F96DBA /* FIRDataEventType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataEventType.h; path = Firebase/Database/Public/FIRDataEventType.h; sourceTree = ""; }; + 09BCB0749FF5FD9B5F63C2DDB97398DF /* FIRStoragePath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStoragePath.h; path = FirebaseStorage/Sources/FIRStoragePath.h; sourceTree = ""; }; + 09C3130C882910E48C5E81FFB4E257F1 /* Pods-PediatricPancreas_Storyboard-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PediatricPancreas_Storyboard-frameworks.sh"; sourceTree = ""; }; + 0A301F01504541019F6CCFE316CB38D1 /* FNodeFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNodeFilter.h; path = Firebase/Database/Core/View/Filter/FNodeFilter.h; sourceTree = ""; }; + 0A6652E2684D336D22085F48B522BF60 /* FListenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenProvider.m; path = Firebase/Database/Core/FListenProvider.m; sourceTree = ""; }; + 0A99DFD371A5473D820867DF4D748DEF /* GoogleDataTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GoogleDataTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GoogleDataTransport.h; sourceTree = ""; }; + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = leveldb.framework; path = "leveldb-library.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AB25ED792C29BE405E3B3CD3A8F2EF0 /* FEventEmitter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventEmitter.m; path = Firebase/Database/Utilities/FEventEmitter.m; sourceTree = ""; }; + 0AEA2494228A798570ADA4BA569AAD3D /* FCachePolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCachePolicy.m; path = Firebase/Database/Persistence/FCachePolicy.m; sourceTree = ""; }; + 0B0E05A5A7593B41D7DA14F11FF6330C /* FBLPromise+All.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+All.h"; path = "Sources/FBLPromises/include/FBLPromise+All.h"; sourceTree = ""; }; + 0B70C438948477944CD43C50B8C26AB7 /* FIRDatabaseComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseComponent.m; path = Firebase/Database/Api/FIRDatabaseComponent.m; sourceTree = ""; }; + 0B79E46D2F75EC32EFDC026DBC054C0B /* FBLPromise+Reduce.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Reduce.m"; path = "Sources/FBLPromises/FBLPromise+Reduce.m"; sourceTree = ""; }; + 0C206964574410436FED4D6E158610F0 /* FIRInstanceID+Private.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceID+Private.m"; path = "Firebase/InstanceID/FIRInstanceID+Private.m"; sourceTree = ""; }; + 0C452676C3EB75F3891DBC914F75291A /* FBLPromise+Race.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Race.m"; path = "Sources/FBLPromises/FBLPromise+Race.m"; sourceTree = ""; }; + 0C5C92E86E83A2EAD99482570335606B /* nanopb.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = nanopb.xcconfig; sourceTree = ""; }; + 0D38174AAFD5096B52D9FFE2771D0112 /* FRepoManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoManager.h; path = Firebase/Database/Core/FRepoManager.h; sourceTree = ""; }; + 0D7B8E85F15B91F2BE7228170D267A72 /* FMaxNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMaxNode.h; path = Firebase/Database/FMaxNode.h; sourceTree = ""; }; + 0DA7971DA1658D238157296A691E6CAD /* FirebaseCore-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCore-Info.plist"; sourceTree = ""; }; + 0DD98E9DFFAF9630E85D5AA939CC6FE2 /* GDTCORReachability.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability.h; sourceTree = ""; }; + 0E037F738D549FCCFD726636BF810C7D /* leveldb-library-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-prefix.pch"; sourceTree = ""; }; + 0E1A7752DD11EF21A11603EF886B6447 /* db.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db.h; path = include/leveldb/db.h; sourceTree = ""; }; + 0EDD66CDFCF74C4E949499D9C55DC80B /* GDTCCTUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTUploader.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTUploader.h; sourceTree = ""; }; + 0EFC7BAC9CEA86180EE50C52ADF90B7E /* FAckUserWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAckUserWrite.m; path = Firebase/Database/Core/Operation/FAckUserWrite.m; sourceTree = ""; }; + 0F123D96464AE6E248DA68965E4D63EC /* FBLPromise+Retry.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Retry.m"; path = "Sources/FBLPromises/FBLPromise+Retry.m"; sourceTree = ""; }; + 0F3CC58D9AE381DA2AD37457F99B2D02 /* GoogleDataTransport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransport-Info.plist"; sourceTree = ""; }; + 0F83CEF39EB3C9712DC040CEA8502D78 /* FNamedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNamedNode.h; path = Firebase/Database/FNamedNode.h; sourceTree = ""; }; + 102030AB0E29D8723B187640A14759D9 /* GULHeartbeatDateStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULHeartbeatDateStorage.m; path = GoogleUtilities/Environment/GULHeartbeatDateStorage.m; sourceTree = ""; }; + 107EEF2DDC74972CC27D7B59D733DE16 /* GULAppEnvironmentUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppEnvironmentUtil.h; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.h; sourceTree = ""; }; + 1096D1DBCB98AE4385176B1D98D0D4D1 /* cct.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cct.nanopb.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.h; sourceTree = ""; }; + 10CF2C664D0E815ED48EC7BAEB31578D /* FBLPromise+Await.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Await.h"; path = "Sources/FBLPromises/include/FBLPromise+Await.h"; sourceTree = ""; }; + 10F2138F2FBC045AC402BDA69D3CD680 /* testharness.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = testharness.cc; path = util/testharness.cc; sourceTree = ""; }; + 114EC166893B4C60D76A1917530AF647 /* filter_policy.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_policy.cc; path = util/filter_policy.cc; sourceTree = ""; }; + 11A186726CCB0F63136A8019DBBD7BAD /* GULReachabilityChecker+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULReachabilityChecker+Internal.h"; path = "GoogleUtilities/Reachability/GULReachabilityChecker+Internal.h"; sourceTree = ""; }; + 120A6866016396AA3B307F0F69751349 /* FIRBundleUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRBundleUtil.m; path = FirebaseCore/Sources/FIRBundleUtil.m; sourceTree = ""; }; + 128CF27E454BFEA60A3C9AA8900394BB /* FirebaseStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseStorage.h; path = FirebaseStorage/Sources/Public/FirebaseStorage.h; sourceTree = ""; }; + 12F18220753EC36AA3774DEDD6478578 /* FIRStorageErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageErrors.m; path = FirebaseStorage/Sources/FIRStorageErrors.m; sourceTree = ""; }; + 12F5D011A000BAC69522947792FBF47F /* FLLRBEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBEmptyNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.h; sourceTree = ""; }; + 134AEB3F267142E63330B1EE8557A729 /* FIRSecureStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRSecureStorage.m; path = FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.m; sourceTree = ""; }; + 13695C66BA611111420DD884C0C70123 /* FIRAnalyticsConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAnalyticsConfiguration.m; path = FirebaseCore/Sources/FIRAnalyticsConfiguration.m; sourceTree = ""; }; + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstallations.framework; path = FirebaseInstallations.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 13D8301FC7F37CB3A191D1FCF00126C2 /* GULNetworkURLSession.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkURLSession.m; path = GoogleUtilities/Network/GULNetworkURLSession.m; sourceTree = ""; }; + 141087222BACACD95D911E82A46EE9A1 /* log_format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_format.h; path = db/log_format.h; sourceTree = ""; }; + 1483A141DA43BEE0914320FCA91B9E6C /* FTupleBoolBlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleBoolBlock.h; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.h; sourceTree = ""; }; + 155EA6AF78AAC81C5A5EA1DE64050B53 /* merger.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = merger.cc; path = table/merger.cc; sourceTree = ""; }; + 15853D21D1AFFB8499F10A9CB08B835C /* pb_decode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_decode.h; sourceTree = ""; }; + 15C33E1A98FACB2E96B1D9BE014EFA20 /* FIRStorageReference.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageReference.h; path = FirebaseStorage/Sources/Public/FIRStorageReference.h; sourceTree = ""; }; + 15E0BCDFB63DB8313F394A34962DE91A /* GoogleAppMeasurement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GoogleAppMeasurement.framework; path = Frameworks/GoogleAppMeasurement.framework; sourceTree = ""; }; + 16CE5915391DA812240B7E3D3EA23BB6 /* GULSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSwizzler.h; path = GoogleUtilities/MethodSwizzler/Private/GULSwizzler.h; sourceTree = ""; }; + 16D2CB4D08C7DF2EE66A293C0D99EFD0 /* GULSecureCoding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSecureCoding.h; path = GoogleUtilities/Environment/Public/GULSecureCoding.h; sourceTree = ""; }; + 1740112BBEA67D8392EF5D3C50104C7F /* GoogleUtilities-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-prefix.pch"; sourceTree = ""; }; + 17527F81C485EAD0DA6BDDB41CE38598 /* FIRMutableData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData.h; path = Firebase/Database/Public/FIRMutableData.h; sourceTree = ""; }; + 1800C48AE5BA951A1284B03F4CE961EC /* GDTCCTCompressionHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTCompressionHelper.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTCompressionHelper.h; sourceTree = ""; }; + 184D0B16C9E04FF26374C15D181A7F5B /* FIRInstanceIDTokenInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenInfo.m; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.m; sourceTree = ""; }; + 192069076F1645702572E4BB839A1FBD /* FTrackedQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQuery.m; path = Firebase/Database/Persistence/FTrackedQuery.m; sourceTree = ""; }; + 19458D70173FD697C88000691293B4C8 /* FLeafNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLeafNode.m; path = Firebase/Database/Snapshot/FLeafNode.m; sourceTree = ""; }; + 194C2F1E5104D28EFFB7D4AA2CD4BC46 /* FIRServerValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRServerValue.h; path = Firebase/Database/Public/FIRServerValue.h; sourceTree = ""; }; + 19A1C443965CAAF1705E6A645B84E2C2 /* FLevelDBStorageEngine.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLevelDBStorageEngine.m; path = Firebase/Database/Persistence/FLevelDBStorageEngine.m; sourceTree = ""; }; + 19C33078E1D0C7BF23A35F6D11FACB9C /* NSError+FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSError+FIRInstanceID.h"; path = "Firebase/InstanceID/NSError+FIRInstanceID.h"; sourceTree = ""; }; + 19EDA0A14684A68E5E6E03FE91AEEAF6 /* FIRInstanceIDTokenOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.h; sourceTree = ""; }; + 1AB26A53B7AF9F47ABC78485EF2137FB /* FIRInstallationsStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStatus.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsStatus.h; sourceTree = ""; }; + 1ACD081B6F3DD381BC03AF0B1D4EA03C /* FIRLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLogger.h; path = FirebaseCore/Sources/Private/FIRLogger.h; sourceTree = ""; }; + 1B4900A12B99435B7C2DBC1A20FA5194 /* FIRComponentType.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentType.h; path = FirebaseCore/Sources/Private/FIRComponentType.h; sourceTree = ""; }; + 1B544FA9B3431D609145527D612E6563 /* FValidation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValidation.h; path = Firebase/Database/Utilities/FValidation.h; sourceTree = ""; }; + 1B76679FD290C6916E68E4A74C44F5BB /* FIRInstanceIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDStore.h; path = Firebase/InstanceID/FIRInstanceIDStore.h; sourceTree = ""; }; + 1B934CF29FE5CD666ED5FEB4184D4D0E /* FIRDatabaseReference.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference.h; path = Firebase/Database/Public/FIRDatabaseReference.h; sourceTree = ""; }; + 1C4835B62590F9B75776B27FA8D95579 /* GULNetworkMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkMessageCode.h; path = GoogleUtilities/Network/Private/GULNetworkMessageCode.h; sourceTree = ""; }; + 1C77A25EF19821D402BAE78598EA5361 /* GDTCCTUploader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTUploader.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTUploader.m; sourceTree = ""; }; + 1C899CCE4B5ADC63B99D167B4F6C09D9 /* FIRDatabaseQuery.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseQuery.m; path = Firebase/Database/Api/FIRDatabaseQuery.m; sourceTree = ""; }; + 1CB62E487FA29460E6F077133621B7BD /* FServerValues.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FServerValues.m; path = Firebase/Database/Core/FServerValues.m; sourceTree = ""; }; + 1CECE9D2BE91CA5F856D1C62E06F7E40 /* GDTCOREvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREvent.h; sourceTree = ""; }; + 1D5513A2CF10850CFC7325CC68B0B83E /* FIRStorageUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUtils.m; path = FirebaseStorage/Sources/FIRStorageUtils.m; sourceTree = ""; }; + 1D6ADFA238D1EE026EEA9BAC14D8F931 /* FRepo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo.h; path = Firebase/Database/Core/FRepo.h; sourceTree = ""; }; + 1D84106EEDBEB4ABE5F79A6CF40A6C46 /* table_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_builder.cc; path = table/table_builder.cc; sourceTree = ""; }; + 1E0287E8C63893D4474D3CD7F879AD0D /* FIRSecureStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRSecureStorage.h; path = FirebaseInstallations/Source/Library/SecureStorage/FIRSecureStorage.h; sourceTree = ""; }; + 1E05A614C11C6F07FF6BD355BEBDF07D /* comparator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = comparator.h; path = include/leveldb/comparator.h; sourceTree = ""; }; + 1E2B112675E7D67B7AF74F65E5478631 /* FTupleTransaction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTransaction.h; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.h; sourceTree = ""; }; + 1E4564C0D672A2920A1F8E2AD2506168 /* FIRNoopAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRNoopAuthTokenProvider.h; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.h; sourceTree = ""; }; + 1E6033BCAD8C3551417FE27E1BD0BC0D /* FIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndex.h; path = Firebase/Database/FIndex.h; sourceTree = ""; }; + 1E7D89A6CB046C6FA85A49FCC0B99090 /* GoogleUtilities-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleUtilities-dummy.m"; sourceTree = ""; }; + 1F3FF41C7805A4DA98244AEF7CC226C3 /* FIRInstanceIDCheckinService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinService.h; path = Firebase/InstanceID/FIRInstanceIDCheckinService.h; sourceTree = ""; }; + 1FAF5018229925BF08F2CB786CCE90A5 /* FBLPromise+Recover.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Recover.m"; path = "Sources/FBLPromises/FBLPromise+Recover.m"; sourceTree = ""; }; + 1FB1649F83A4B89E0BAFC3DF429C1CDD /* format.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = format.cc; path = table/format.cc; sourceTree = ""; }; + 201C752BCD7C078C782D815894466726 /* FAckUserWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAckUserWrite.h; path = Firebase/Database/Core/Operation/FAckUserWrite.h; sourceTree = ""; }; + 2048A7357F01687FD8F3665E48D84747 /* FIRStorageErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageErrors.h; path = FirebaseStorage/Sources/FIRStorageErrors.h; sourceTree = ""; }; + 20966C015039AA38819B63EFA48DDCD6 /* FSyncTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncTree.m; path = Firebase/Database/Core/FSyncTree.m; sourceTree = ""; }; + 21C9F5A07D09B15611C75D123DD8396B /* FIRInstanceIDCheckinPreferences.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinPreferences.m; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences.m; sourceTree = ""; }; + 21FFE28A3BB0A1F707CF7F6BCE2EA3F9 /* FirebaseInstanceID.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstanceID.modulemap; sourceTree = ""; }; + 224AFDDED1449BD5811E120270B60A6B /* FBLPromise+Do.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Do.h"; path = "Sources/FBLPromises/include/FBLPromise+Do.h"; sourceTree = ""; }; + 22626DBD000812B98478D77E874B3DB6 /* GULMutableDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULMutableDictionary.m; path = GoogleUtilities/Network/GULMutableDictionary.m; sourceTree = ""; }; + 2339CB4AB1EFFABA9FE159FDF9CABBDD /* FTupleFirebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleFirebase.h; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.h; sourceTree = ""; }; + 234930C333672879FDFADB107116635A /* Pods-PediatricPancreas_Storyboard-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PediatricPancreas_Storyboard-acknowledgements.markdown"; sourceTree = ""; }; + 23AA2ACA14FF7EEF14BCE4BA3C1FA75D /* GoogleDataTransport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransport.modulemap; sourceTree = ""; }; + 244B4E0C8D9ED4451E9A26BF10BB836E /* FTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTree.h; path = Firebase/Database/Core/Utilities/FTree.h; sourceTree = ""; }; + 2467A834C566F16403C6F4E386D5943D /* FIRVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRVersion.m; path = FirebaseCore/Sources/FIRVersion.m; sourceTree = ""; }; + 248334110F3275218F717022DE49A024 /* FirebaseInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstanceID.h; path = Firebase/InstanceID/Public/FirebaseInstanceID.h; sourceTree = ""; }; + 24B3EA8490EADB3F93B91A42EF325BEE /* FTreeSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.h; sourceTree = ""; }; + 24E7AED0E578075903339C2F3EFEEDCE /* thread_annotations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = thread_annotations.h; path = port/thread_annotations.h; sourceTree = ""; }; + 250AA97D89AEB8E9740DE1F693CD6303 /* FPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPath.h; path = Firebase/Database/Core/Utilities/FPath.h; sourceTree = ""; }; + 254E203E550C89C08D3928C8E43B25F7 /* FIRCoreDiagnosticsInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsInterop.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsInterop.h; sourceTree = ""; }; + 265E98998557D90106A27053DB002C6A /* FIndexedNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedNode.h; path = Firebase/Database/Snapshot/FIndexedNode.h; sourceTree = ""; }; + 26AF78DA83D9E020289D43F83EFF9A8E /* FCompleteChildSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompleteChildSource.h; path = Firebase/Database/Core/View/Filter/FCompleteChildSource.h; sourceTree = ""; }; + 26E05B4C70129B7EFF74EFA170692157 /* FIRAppAssociationRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppAssociationRegistration.h; path = FirebaseCore/Sources/Private/FIRAppAssociationRegistration.h; sourceTree = ""; }; + 27E7DBAA6418AC1DF35DF54CF5996CEE /* GoogleDataTransportCCTSupport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransportCCTSupport-umbrella.h"; sourceTree = ""; }; + 27F5B2B2A72A0F52C3D43E4B64D2AFE9 /* FIRStorageMetadata_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageMetadata_Private.h; path = FirebaseStorage/Sources/FIRStorageMetadata_Private.h; sourceTree = ""; }; + 288371F32354A7A2D02E6D211872D6C0 /* PromisesObjC-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PromisesObjC-umbrella.h"; sourceTree = ""; }; + 28C189D7C4A9807852DFBCFFFCBC5211 /* FirebaseCoreDiagnostics.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCoreDiagnostics.modulemap; sourceTree = ""; }; + 28CE8ECC4C7F8A3887EBB85CD1B873A8 /* FIRStorageUploadTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUploadTask.m; path = FirebaseStorage/Sources/FIRStorageUploadTask.m; sourceTree = ""; }; + 297EA095162F086760B8783BF73A1D20 /* FIRHeartbeatInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRHeartbeatInfo.m; path = FirebaseCore/Sources/FIRHeartbeatInfo.m; sourceTree = ""; }; + 29ABCFF3146693410EBE4650CB1C2E37 /* FirebaseAnalytics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAnalytics.xcconfig; sourceTree = ""; }; + 29B7D1344D0B83EDA9B3133EB6C60D9D /* FIRInstanceIDLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDLogger.h; path = Firebase/InstanceID/FIRInstanceIDLogger.h; sourceTree = ""; }; + 2A706EAFB3D2A122ECD92DD5799E98BE /* block_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block_builder.h; path = table/block_builder.h; sourceTree = ""; }; + 2A8E64F1793145DD60F66ECDFBFB4458 /* GULLoggerCodes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerCodes.h; path = GoogleUtilities/Common/GULLoggerCodes.h; sourceTree = ""; }; + 2B28B1D9152BF89EA21A1F696D785A12 /* FIRInstallationsVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsVersion.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsVersion.h; sourceTree = ""; }; + 2B6FD5CF4CFDF8CF03B9B7B49DBEF46A /* FIRStorageUpdateMetadataTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageUpdateMetadataTask.m; path = FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.m; sourceTree = ""; }; + 2BD2F054BA7A505A5CF0CF32893BF976 /* FBLPromise+Await.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Await.m"; path = "Sources/FBLPromises/FBLPromise+Await.m"; sourceTree = ""; }; + 2C346213450344E3B75189159433894A /* FIRStorageGetMetadataTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageGetMetadataTask.m; path = FirebaseStorage/Sources/FIRStorageGetMetadataTask.m; sourceTree = ""; }; + 2C7BD76C6C962EDF1D8EE513F83F9CE1 /* GTMSessionFetcher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GTMSessionFetcher.modulemap; sourceTree = ""; }; + 2C8F76E68FA2494D6AF6EF791A7C30A9 /* FTupleRemovedQueriesEvents.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleRemovedQueriesEvents.m; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.m; sourceTree = ""; }; + 2CD81AAA2CDF7215DED4146B535ADC11 /* FRepo_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepo_Private.h; path = Firebase/Database/Core/FRepo_Private.h; sourceTree = ""; }; + 2D7DB9E6A2C35C869B3D55E0C1488F2D /* FIRTransactionResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRTransactionResult.m; path = Firebase/Database/Api/FIRTransactionResult.m; sourceTree = ""; }; + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseInstanceID.framework; path = FirebaseInstanceID.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DA3D7D0CCBF53EA683D879E7BD0E744 /* mutexlock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = mutexlock.h; path = util/mutexlock.h; sourceTree = ""; }; + 2DD4AD8A942A3CD434EDBDFC70B5CAE8 /* FBLPromise+Delay.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Delay.h"; path = "Sources/FBLPromises/include/FBLPromise+Delay.h"; sourceTree = ""; }; + 2E03362CBA1953F1EE9640B25411BED8 /* GULHeartbeatDateStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULHeartbeatDateStorage.h; path = GoogleUtilities/Environment/Public/GULHeartbeatDateStorage.h; sourceTree = ""; }; + 2EB170657617FFA0F073315570B8F945 /* FMerge.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FMerge.h; path = Firebase/Database/Core/Operation/FMerge.h; sourceTree = ""; }; + 2F04DA8747EA8BE73026D773DF27B3AD /* GDTCORStoredEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStoredEvent.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORStoredEvent.h; sourceTree = ""; }; + 2F0BFC9D0F80D4FBE73F0652CB04E596 /* FIRStorageTaskSnapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTaskSnapshot.h; path = FirebaseStorage/Sources/Public/FIRStorageTaskSnapshot.h; sourceTree = ""; }; + 2FBF2FCB4B59F5862D91B4604A5180ED /* FIRInstanceIDTokenStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenStore.m; path = Firebase/InstanceID/FIRInstanceIDTokenStore.m; sourceTree = ""; }; + 2FE5FEF4C93674EEFE8E07E813B00232 /* FConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConnection.m; path = Firebase/Database/Realtime/FConnection.m; sourceTree = ""; }; + 3045F5E31607213D2722DE71D476C435 /* FIRInstallationsStoredItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredItem.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.m; sourceTree = ""; }; + 304BB26FD24F626815E78336619266C5 /* GDTCORUploader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploader.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploader.h; sourceTree = ""; }; + 30E79602773F8F3F189744F56604A4AD /* FIRStorageObservableTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageObservableTask.m; path = FirebaseStorage/Sources/FIRStorageObservableTask.m; sourceTree = ""; }; + 312064CA84E0B1CCE2BFF80E4A923AC7 /* FTupleSetIdPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleSetIdPath.m; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.m; sourceTree = ""; }; + 31B1AE108730E173979B504D5E7431DC /* crc32c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = crc32c.h; path = util/crc32c.h; sourceTree = ""; }; + 32C7BFD32D5BBC98FC727B87823E3F0C /* FIRStorageDeleteTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDeleteTask.h; path = FirebaseStorage/Sources/FIRStorageDeleteTask.h; sourceTree = ""; }; + 330BA0E97DE040797CA80B20D2DBFD22 /* log_reader.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_reader.cc; path = db/log_reader.cc; sourceTree = ""; }; + 3345F327E7A52648AAE06E3C6F9D1929 /* FIRStorageMetadata.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageMetadata.m; path = FirebaseStorage/Sources/FIRStorageMetadata.m; sourceTree = ""; }; + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FBLPromises.framework; path = PromisesObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 334A858E767B7ABD572D6D2F1F9EECAF /* FArraySortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FArraySortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.m; sourceTree = ""; }; + 33BEA7F632D48EFB31127984359A7D0D /* FIRInstanceIDAuthService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthService.h; path = Firebase/InstanceID/FIRInstanceIDAuthService.h; sourceTree = ""; }; + 33E94FF93F0D0F4C36D3C35D97BD8DCB /* FIRStorage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorage_Private.h; path = FirebaseStorage/Sources/FIRStorage_Private.h; sourceTree = ""; }; + 3439DCCC83A1FA43A42F2B632AD4CAFE /* PromisesObjC-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "PromisesObjC-Info.plist"; sourceTree = ""; }; + 3455F9C221E70B76D67B1E8DAA70A45A /* GULLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLoggerLevel.h; path = GoogleUtilities/Logger/Public/GULLoggerLevel.h; sourceTree = ""; }; + 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + 34D58F578A6B32ACB43E4F081310AF3A /* FIRMutableData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRMutableData.m; path = Firebase/Database/Api/FIRMutableData.m; sourceTree = ""; }; + 35025384884E48B66920A6D01BE8A148 /* version_set.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_set.cc; path = db/version_set.cc; sourceTree = ""; }; + 357BB6787D118D45F0E266C2F542034B /* GULReachabilityMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityMessageCode.h; path = GoogleUtilities/Reachability/Private/GULReachabilityMessageCode.h; sourceTree = ""; }; + 35857822AD1FB3F14370669224C71326 /* Pods_PediatricPancreas_Storyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PediatricPancreas_Storyboard.framework; path = "Pods-PediatricPancreas_Storyboard.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3602C9CF1460A33C123A3A12FD8C307E /* FBLPromise+Catch.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Catch.m"; path = "Sources/FBLPromises/FBLPromise+Catch.m"; sourceTree = ""; }; + 36266F0A667DE528AC3A3717E8619598 /* FClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FClock.h; path = Firebase/Database/FClock.h; sourceTree = ""; }; + 370216E4EF7609FBEC6F9EABA8562C55 /* FIRInstanceIDCheckinStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinStore.h; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.h; sourceTree = ""; }; + 37B02A7BCA4D800A027495A301A5E818 /* FTupleTSN.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTSN.m; path = Firebase/Database/Utilities/Tuples/FTupleTSN.m; sourceTree = ""; }; + 38C523982ECA211A1C922FEE51D4428F /* FIRStorageUpdateMetadataTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUpdateMetadataTask.h; path = FirebaseStorage/Sources/FIRStorageUpdateMetadataTask.h; sourceTree = ""; }; + 38D86F977EC22FCEFF56212D1B48EB8B /* GTMSessionFetcherService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcherService.m; path = Source/GTMSessionFetcherService.m; sourceTree = ""; }; + 390419A5519751A14BED14EC54F229AF /* crc32c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = crc32c.cc; path = util/crc32c.cc; sourceTree = ""; }; + 396B90CA36D20A652948E5CDA84CDC5E /* FIRIMessageCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRIMessageCode.h; path = Firebase/InstanceID/FIRIMessageCode.h; sourceTree = ""; }; + 3975CADB3F0440D001CE42671FD82B69 /* FWriteRecord.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteRecord.m; path = Firebase/Database/Core/FWriteRecord.m; sourceTree = ""; }; + 3A13CB75BF68742AE7610270D81FCE09 /* FIRStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorage.m; path = FirebaseStorage/Sources/FIRStorage.m; sourceTree = ""; }; + 3AE4E4E587A9E312162D01C3498442C1 /* FIRInstallationsItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsItem.m; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.m; sourceTree = ""; }; + 3B5C7C088DAC8E08B4C0ABE1D9D7F187 /* GDTCOREventTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventTransformer.h; sourceTree = ""; }; + 3BA3B39AD51B46E55E3A6A609CBC8E7B /* log_writer.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = log_writer.cc; path = db/log_writer.cc; sourceTree = ""; }; + 3BAEE7AB26C4A136E7E3F4B44E7BEA97 /* FIRStorageGetDownloadURLTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetDownloadURLTask_Private.h; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask_Private.h; sourceTree = ""; }; + 3C0AB9D4108F4576B594A1159BD62850 /* GDTCOREventDataObject.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREventDataObject.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCOREventDataObject.h; sourceTree = ""; }; + 3CE038EBFA6A42EE048F83E4B840E76F /* FIRStorageGetDownloadURLTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageGetDownloadURLTask.m; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.m; sourceTree = ""; }; + 3D03DB7135783EFF5869EED8E463C2F3 /* FValueEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueEventRegistration.h; path = Firebase/Database/Core/View/FValueEventRegistration.h; sourceTree = ""; }; + 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + 3D74B536712C66F3158E15B064EE90C1 /* FTupleRemovedQueriesEvents.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleRemovedQueriesEvents.h; path = Firebase/Database/Utilities/Tuples/FTupleRemovedQueriesEvents.h; sourceTree = ""; }; + 3E141DEE77985B8019CF800305A79116 /* FirebaseInstanceID.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstanceID.xcconfig; sourceTree = ""; }; + 3F532EB505ACAFC5EC6CFDDC747C753D /* FIRStorageObservableTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageObservableTask.h; path = FirebaseStorage/Sources/Public/FIRStorageObservableTask.h; sourceTree = ""; }; + 3F72A7C87673FA30B1B60FBE587CE6F7 /* FIRAppAssociationRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRAppAssociationRegistration.m; path = FirebaseCore/Sources/FIRAppAssociationRegistration.m; sourceTree = ""; }; + 3FAFB71A7764BCD006424B153CB958B6 /* two_level_iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = two_level_iterator.cc; path = table/two_level_iterator.cc; sourceTree = ""; }; + 3FE5BCB2204D5F18D2166F9985632680 /* FCompoundHash.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundHash.m; path = Firebase/Database/Core/FCompoundHash.m; sourceTree = ""; }; + 400B4EF49B532BEB9532849F5FD07F5A /* FIRStorageListResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListResult.h; path = FirebaseStorage/Sources/Public/FIRStorageListResult.h; sourceTree = ""; }; + 4110031FA1CB0283269D477218EDFA3D /* GTMSessionUploadFetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionUploadFetcher.h; path = Source/GTMSessionUploadFetcher.h; sourceTree = ""; }; + 411DF6A51F39A73FC87869A8A5AF5170 /* FIROptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptions.h; path = FirebaseCore/Sources/Public/FIROptions.h; sourceTree = ""; }; + 41401874FA638C00FF727FA7A46C972F /* FIRInstanceIDLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDLogger.m; path = Firebase/InstanceID/FIRInstanceIDLogger.m; sourceTree = ""; }; + 41813E5BC58F89CA3B1728140B44B6A3 /* FChange.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChange.h; path = Firebase/Database/Core/View/FChange.h; sourceTree = ""; }; + 4225CA428474D85D68CB643FE8588165 /* GULNetworkConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkConstants.h; path = GoogleUtilities/Network/Private/GULNetworkConstants.h; sourceTree = ""; }; + 42526DD42D37ABD04FBD8D85D95F52F5 /* GoogleDataTransportCCTSupport.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleDataTransportCCTSupport.modulemap; sourceTree = ""; }; + 429F8F88B08A830D3F8C419F57124FC0 /* GTMSessionFetcherLogging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcherLogging.h; path = Source/GTMSessionFetcherLogging.h; sourceTree = ""; }; + 42BD5D5243A04F06CDD2CA2E9C329BC1 /* windows_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = windows_logger.h; path = util/windows_logger.h; sourceTree = ""; }; + 42F9237E26387A51DA413989DA2C49FD /* FConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConstants.h; path = Firebase/Database/Constants/FConstants.h; sourceTree = ""; }; + 43C2DF7D088303A95D61EE4E40773F52 /* pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb.h; sourceTree = ""; }; + 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 44222B32871DED425CC6FD62785342C5 /* FChildrenNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildrenNode.h; path = Firebase/Database/Snapshot/FChildrenNode.h; sourceTree = ""; }; + 44866FAB99B09DB36E26EE4B4E7EE3BF /* repair.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = repair.cc; path = db/repair.cc; sourceTree = ""; }; + 44C3D7F04D9498A963E4218040395239 /* FWriteTreeRef.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTreeRef.h; path = Firebase/Database/Core/FWriteTreeRef.h; sourceTree = ""; }; + 4507041848E941A730652DCB9C6775E4 /* FIRTransactionResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult.h; path = Firebase/Database/Public/FIRTransactionResult.h; sourceTree = ""; }; + 453024A9DD7B840DCB627C15A631AA6E /* FIRMutableData_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRMutableData_Private.h; path = Firebase/Database/Api/Private/FIRMutableData_Private.h; sourceTree = ""; }; + 45C0503452AD338BDBAA92921C9DE194 /* FLLRBNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBNode.h; sourceTree = ""; }; + 46109B02A1531B0A8FF22CA39EF12E40 /* FBLPromise+Always.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Always.m"; path = "Sources/FBLPromises/FBLPromise+Always.m"; sourceTree = ""; }; + 46A9327BAF9A628A9002286422BF7F83 /* FTupleOnDisconnect.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleOnDisconnect.m; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.m; sourceTree = ""; }; + 47A60F3366969F399160D8AE328D1F1B /* GoogleUtilities-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleUtilities-umbrella.h"; sourceTree = ""; }; + 47F6BCA1337943A0F0648467B2AAD1D7 /* FConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FConnection.h; path = Firebase/Database/Realtime/FConnection.h; sourceTree = ""; }; + 483A5ADBF76AC92AA5C6D5507BB4E23E /* FIRInstanceIDTokenManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenManager.m; path = Firebase/InstanceID/FIRInstanceIDTokenManager.m; sourceTree = ""; }; + 489F989E3EF4CC170458E2F7BACF34A5 /* FRangeMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangeMerge.m; path = Firebase/Database/Core/FRangeMerge.m; sourceTree = ""; }; + 4A59D3DCFF16FA7B1C33B039ECCC3B79 /* table_cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_cache.h; path = db/table_cache.h; sourceTree = ""; }; + 4A7C86481B1F7532480087F344D12CC5 /* FIRDataSnapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot.h; path = Firebase/Database/Public/FIRDataSnapshot.h; sourceTree = ""; }; + 4A86A8FD734185489EECEE9ABE1B8639 /* FTrackedQueryManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQueryManager.h; path = Firebase/Database/Persistence/FTrackedQueryManager.h; sourceTree = ""; }; + 4B041AE2CD41F4960AA09352D90DA5F7 /* FTupleFirebase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleFirebase.m; path = Firebase/Database/Utilities/Tuples/FTupleFirebase.m; sourceTree = ""; }; + 4BD3A12816661B22D94EE76C808C4D2C /* GULUserDefaults.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULUserDefaults.m; path = GoogleUtilities/UserDefaults/GULUserDefaults.m; sourceTree = ""; }; + 4C11004830397FE020F6EDE9413D3CFC /* GDTCORTransformer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer.h; sourceTree = ""; }; + 4C5151EB7A134D6CB59D6FD68C17EB14 /* FBLPromise+Testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Testing.h"; path = "Sources/FBLPromises/include/FBLPromise+Testing.h"; sourceTree = ""; }; + 4C6BD82E581F5CC725968B1D68A00C19 /* GTMSessionFetcher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMSessionFetcher-prefix.pch"; sourceTree = ""; }; + 4DED8B128D826A18F00619CCFDF72995 /* FIRDependency.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDependency.h; path = FirebaseCore/Sources/Private/FIRDependency.h; sourceTree = ""; }; + 4DEECD90DC659AAA5A515F133BA3D8A4 /* FParsedUrl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FParsedUrl.m; path = Firebase/Database/Utilities/FParsedUrl.m; sourceTree = ""; }; + 4E0CDAA6233B7D55E0DF49497C0476EF /* GoogleAppMeasurement.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleAppMeasurement.xcconfig; sourceTree = ""; }; + 4E37890FCB2C3ABF59FA19621429FEC8 /* GDTCORTargets.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTargets.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTargets.h; sourceTree = ""; }; + 4F057C30095A02BF5F796E7CA9E1C295 /* FSyncTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncTree.h; path = Firebase/Database/Core/FSyncTree.h; sourceTree = ""; }; + 4F173297AC99D08D91EA05F159592E18 /* FPendingPut.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPendingPut.m; path = Firebase/Database/Persistence/FPendingPut.m; sourceTree = ""; }; + 4F37B777FF7AF7050F952C1F7EDBEC58 /* filename.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filename.cc; path = db/filename.cc; sourceTree = ""; }; + 4FA6F619BDF7B5CDBF4A4639BA797B13 /* FQueryParams.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQueryParams.h; path = Firebase/Database/Core/FQueryParams.h; sourceTree = ""; }; + 4FC8B84916B3508094591E16F5044642 /* FIRComponentContainer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentContainer.m; path = FirebaseCore/Sources/FIRComponentContainer.m; sourceTree = ""; }; + 505C1A8D2A956C3FF8FA6D699EB4A581 /* version_set.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_set.h; path = db/version_set.h; sourceTree = ""; }; + 50950C3AE1D36D0DFFC58C5E1C571B02 /* FIRStorageReference.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageReference.m; path = FirebaseStorage/Sources/FIRStorageReference.m; sourceTree = ""; }; + 50EE24DC0A427CD4D94FAC3BB1119197 /* dumpfile.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dumpfile.cc; path = db/dumpfile.cc; sourceTree = ""; }; + 50EEA6FAE9C760AB7F5E302B5284F1CF /* FIRInstallationsItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsItem.h; path = FirebaseInstallations/Source/Library/FIRInstallationsItem.h; sourceTree = ""; }; + 5139CF30473560788ABDCB14D62A88F7 /* posix_logger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = posix_logger.h; path = util/posix_logger.h; sourceTree = ""; }; + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseDatabase.framework; path = FirebaseDatabase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5178BD41D5098BE8385637308F58C5FA /* FRepo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepo.m; path = Firebase/Database/Core/FRepo.m; sourceTree = ""; }; + 51D445E473C41D23773680E8C73E7723 /* FDataEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FDataEvent.h; path = Firebase/Database/Core/View/FDataEvent.h; sourceTree = ""; }; + 5201DB2D923D20FB1DB7E6BF7295229D /* GULReachabilityChecker.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULReachabilityChecker.h; path = GoogleUtilities/Reachability/Private/GULReachabilityChecker.h; sourceTree = ""; }; + 52395DE321F4785481C559231D4936A9 /* GDTCORTransformer_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransformer_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransformer_Private.h; sourceTree = ""; }; + 5300BFD42D87DACC4E4A4C4495F15CB6 /* FView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FView.m; path = Firebase/Database/Core/View/FView.m; sourceTree = ""; }; + 5327239BCECD082DD39C0F036B522DF7 /* FIRInstallationsErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrors.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsErrors.h; sourceTree = ""; }; + 53B1117013327054ED85001947D836A4 /* logging.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = logging.cc; path = util/logging.cc; sourceTree = ""; }; + 53BE173D71059143D61695D5A4F056C0 /* FIRStorageDownloadTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDownloadTask_Private.h; path = FirebaseStorage/Sources/FIRStorageDownloadTask_Private.h; sourceTree = ""; }; + 54384F820C1941AB60BF900E4154CA50 /* FBLPromise+Validate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Validate.h"; path = "Sources/FBLPromises/include/FBLPromise+Validate.h"; sourceTree = ""; }; + 543DC2781DDBFCFA5F37C29E898584EA /* leveldb-library.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "leveldb-library.modulemap"; sourceTree = ""; }; + 54B7003E10AD368606F445FE6596D080 /* Firebase.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Firebase.xcconfig; sourceTree = ""; }; + 54BBDDB60CC332B9CB959B5E4B403CCF /* FPruneForest.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPruneForest.m; path = Firebase/Database/Persistence/FPruneForest.m; sourceTree = ""; }; + 55061862C4109FA0B57C202449412BF6 /* GULUserDefaults.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULUserDefaults.h; path = GoogleUtilities/UserDefaults/Private/GULUserDefaults.h; sourceTree = ""; }; + 58289B6076C1CF90C0AEA2F1BA7CF68B /* coding.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = coding.h; path = util/coding.h; sourceTree = ""; }; + 585302D48E99F87797E63B309BF8AA44 /* version_edit.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = version_edit.h; path = db/version_edit.h; sourceTree = ""; }; + 5895FD073A61E38C37025CFF0C5467AD /* FirebaseInstanceID-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstanceID-Info.plist"; sourceTree = ""; }; + 58CC0D44AC060ACEC0D534668FA1A8E7 /* FCompoundWrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCompoundWrite.m; path = Firebase/Database/Snapshot/FCompoundWrite.m; sourceTree = ""; }; + 58D72AE006E38F62BE505E7BBF0C7EB9 /* FBLPromise+Timeout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Timeout.m"; path = "Sources/FBLPromises/FBLPromise+Timeout.m"; sourceTree = ""; }; + 593F643A1D127168A8A468748C572D8B /* FIRVersion.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRVersion.h; path = FirebaseCore/Sources/FIRVersion.h; sourceTree = ""; }; + 596E00795348CC02B5DA56B1BCC7C88E /* GULAppDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler_Private.h; path = GoogleUtilities/AppDelegateSwizzler/Internal/GULAppDelegateSwizzler_Private.h; sourceTree = ""; }; + 59F63533E39055260C58815ACE106993 /* FIRInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallations.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallations.h; sourceTree = ""; }; + 5A7E1843FD613F018523298FB0DF7927 /* GULSecureCoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSecureCoding.m; path = GoogleUtilities/Environment/GULSecureCoding.m; sourceTree = ""; }; + 5A7F99E2491289AB40887AE66C1C6DAF /* FirebaseDatabase-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseDatabase-Info.plist"; sourceTree = ""; }; + 5A96090A085525143C604ABE9DD7A8C2 /* FValueIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FValueIndex.h; path = Firebase/Database/FValueIndex.h; sourceTree = ""; }; + 5AAAC42AF05E13F7344E5CF861CA1945 /* FIRInstallationsErrorUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsErrorUtil.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.m; sourceTree = ""; }; + 5B30443859D305A810204C8278AEB271 /* db_iter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_iter.h; path = db/db_iter.h; sourceTree = ""; }; + 5B5D47BE607CECCD8CFC8645008D99C7 /* FIRInstanceIDUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDUtilities.h; path = Firebase/InstanceID/FIRInstanceIDUtilities.h; sourceTree = ""; }; + 5B7B5A1E8610253395EBC43E530959CA /* FBLPromises.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromises.h; path = Sources/FBLPromises/include/FBLPromises.h; sourceTree = ""; }; + 5B98410F83421303C9BE8074E1C0E4AC /* FImmutableSortedSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedSet.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.h; sourceTree = ""; }; + 5BC2C6B675EB725F0D223EC27209FD39 /* FCacheNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCacheNode.m; path = Firebase/Database/Core/View/FCacheNode.m; sourceTree = ""; }; + 5C4576E396AB8F6390C668D1DFF46CDE /* dbformat.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dbformat.h; path = db/dbformat.h; sourceTree = ""; }; + 5C5E93C787026AE510C04647460CDC1E /* FIRServerValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRServerValue.m; path = Firebase/Database/Api/FIRServerValue.m; sourceTree = ""; }; + 5C9FD3430FC65B7BAB65043C8C66278E /* FTupleNodePath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleNodePath.m; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.m; sourceTree = ""; }; + 5CBA2F623E71DEDC84E9B69EE321EAF7 /* FKeepSyncedEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeepSyncedEventRegistration.h; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.h; sourceTree = ""; }; + 5CDC4558A7037B459CADC5E3F8DB0B33 /* FBLPromise+Do.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Do.m"; path = "Sources/FBLPromises/FBLPromise+Do.m"; sourceTree = ""; }; + 5D4F44ED2E2432E9E466D9C93573B02F /* FPendingPut.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPendingPut.h; path = Firebase/Database/Persistence/FPendingPut.h; sourceTree = ""; }; + 5D6FC6558E8C6C30A444F001D3A20CD2 /* FIRStorageUploadTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUploadTask_Private.h; path = FirebaseStorage/Sources/FIRStorageUploadTask_Private.h; sourceTree = ""; }; + 5D7DBE42AC5973FED94FD2BFAD8DB4DF /* FLeafNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLeafNode.h; path = Firebase/Database/Snapshot/FLeafNode.h; sourceTree = ""; }; + 5DF1ADD915E44D639B021AE569D35711 /* FViewCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewCache.m; path = Firebase/Database/Core/View/FViewCache.m; sourceTree = ""; }; + 5E02672207635E1E0F3FFDADFFFD3946 /* FLevelDBStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLevelDBStorageEngine.h; path = Firebase/Database/Persistence/FLevelDBStorageEngine.h; sourceTree = ""; }; + 5EDB4E35C2E12DAC6223E2BCD17CFD54 /* FIRInstanceIDTokenOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenOperation.m; sourceTree = ""; }; + 5F1AAD2D2CFDCF6A5B824D5A886C1CD2 /* FTreeNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeNode.h; path = Firebase/Database/Core/Utilities/FTreeNode.h; sourceTree = ""; }; + 5FA2D57AC7503BB3ECD9DDD080FF3536 /* Pods-PediatricPancreas_Storyboard-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PediatricPancreas_Storyboard-dummy.m"; sourceTree = ""; }; + 5FB7097098D26ECEDB878F37E1F8EA41 /* FTuplePathValue.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTuplePathValue.h; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.h; sourceTree = ""; }; + 5FCE5C0E1371E8E6FCAC3358D8DF24E6 /* FDataEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FDataEvent.m; path = Firebase/Database/Core/View/FDataEvent.m; sourceTree = ""; }; + 5FE8DA5D3C54741AF02DCB290B8D866B /* FTrackedQueryManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTrackedQueryManager.m; path = Firebase/Database/Persistence/FTrackedQueryManager.m; sourceTree = ""; }; + 5FFBC2FEA5B7B0021EC1D822FDCF4EBB /* FIRDiagnosticsData.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDiagnosticsData.m; path = FirebaseCore/Sources/FIRDiagnosticsData.m; sourceTree = ""; }; + 607C922BE31F4818FD0C53BF79A4EC1A /* FIRInstanceIDURLQueryItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDURLQueryItem.h; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.h; sourceTree = ""; }; + 610BC07F3FD1BBBB5175FAD2234EEF62 /* FIRStorageConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageConstants.m; path = FirebaseStorage/Sources/FIRStorageConstants.m; sourceTree = ""; }; + 615CCFC202BFA16A80BC04AC96FCF487 /* FIRApp.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRApp.h; path = FirebaseCore/Sources/Public/FIRApp.h; sourceTree = ""; }; + 61853C19FB27025E1FDBA8BAB314FCCC /* table_cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table_cache.cc; path = db/table_cache.cc; sourceTree = ""; }; + 61C03183DE684C75C09F7D131C6D8E6F /* builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = builder.cc; path = db/builder.cc; sourceTree = ""; }; + 61F577D9F788CAFE7BAA2EA673AC2037 /* FChildrenNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildrenNode.m; path = Firebase/Database/Snapshot/FChildrenNode.m; sourceTree = ""; }; + 6250B9B9864608A84ACE5C17FCFD6C40 /* FIRInstallationsSingleOperationPromiseCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsSingleOperationPromiseCache.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.m; sourceTree = ""; }; + 632E5D0FA81F7B8874C7A3343EB12F62 /* FIRDatabase.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabase.m; path = Firebase/Database/Api/FIRDatabase.m; sourceTree = ""; }; + 642DB2182537105AE858C3B8BD03C98A /* FIRInstanceIDTokenFetchOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenFetchOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.h; sourceTree = ""; }; + 64409ABC3DCB79196DA6ED00E0308A43 /* FIRInstanceIDCombinedHandler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCombinedHandler.m; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.m; sourceTree = ""; }; + 646E3EB1AF891BC9543C99781D5C61CC /* random.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = random.h; path = util/random.h; sourceTree = ""; }; + 651D975CFB0F58EC635DB69073FC0D6B /* FirebaseStorage.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseStorage.xcconfig; sourceTree = ""; }; + 65A05577DB4A1FC0196B42515C4A5936 /* FIRInstanceIDAPNSInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAPNSInfo.h; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.h; sourceTree = ""; }; + 65B8BFDE850B199A7E5D618376A6C00F /* Pods-PediatricPancreas_Storyboard-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas_Storyboard-acknowledgements.plist"; sourceTree = ""; }; + 66009FB9A96C02DE9E78F386B5D6E14A /* FBLPromise+Wrap.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Wrap.m"; path = "Sources/FBLPromises/FBLPromise+Wrap.m"; sourceTree = ""; }; + 66C7999CC47AE67D949C1766C0BF2CAA /* GDTCORReachability_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORReachability_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORReachability_Private.h; sourceTree = ""; }; + 6721CA9F38C56DD1FED43D3ADA7A6D2B /* FIRHeartbeatInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRHeartbeatInfo.h; path = FirebaseCore/Sources/Private/FIRHeartbeatInfo.h; sourceTree = ""; }; + 67AB9E7A57BC5C8FD59ABE9097063C35 /* FIRRetryHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRRetryHelper.m; path = Firebase/Database/Core/Utilities/FIRRetryHelper.m; sourceTree = ""; }; + 68835ABB7B485036D75560A394D52DF5 /* iterator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = iterator.cc; path = table/iterator.cc; sourceTree = ""; }; + 689A74FA4AD346552142D35E8DBF8BE5 /* pb_encode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_encode.h; sourceTree = ""; }; + 68B8803604DCC5D6E7CD419A7B2933F5 /* GDTCORTransformer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransformer.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransformer.m; sourceTree = ""; }; + 68CEF19BF3A286DFCD34482F7F8EBDA1 /* FKeyIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeyIndex.m; path = Firebase/Database/FKeyIndex.m; sourceTree = ""; }; + 68E9186DC5A562BB4509641DC981B866 /* FIRComponentContainerInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainerInternal.h; path = FirebaseCore/Sources/Private/FIRComponentContainerInternal.h; sourceTree = ""; }; + 690B9A3F161D19CD0FA5B461D0B67875 /* FWriteTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTree.m; path = Firebase/Database/Core/FWriteTree.m; sourceTree = ""; }; + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransportCCTSupport.framework; path = GoogleDataTransportCCTSupport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6944123B6B8C495EEB39ED65A920FF22 /* status.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = status.h; path = include/leveldb/status.h; sourceTree = ""; }; + 69AF1F488EDABE86507D79D8AFF1E55E /* FUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FUtilities.m; path = Firebase/Database/Utilities/FUtilities.m; sourceTree = ""; }; + 6A18CD9744D0EA0AD2406244414CF334 /* FCachePolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCachePolicy.h; path = Firebase/Database/Persistence/FCachePolicy.h; sourceTree = ""; }; + 6A1C718556F05CC83E3A0A98FC95B6F5 /* FOverwrite.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOverwrite.m; path = Firebase/Database/Core/Operation/FOverwrite.m; sourceTree = ""; }; + 6A2482A6E24283C2687635398220B20B /* FTupleTransaction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleTransaction.m; path = Firebase/Database/Utilities/Tuples/FTupleTransaction.m; sourceTree = ""; }; + 6A46F2DCE1834AD1C9950A85E7A8A6CE /* FOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperation.h; path = Firebase/Database/Core/Operation/FOperation.h; sourceTree = ""; }; + 6A98BA1F60CC9765DC24CD540AF2E6A3 /* FOverwrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOverwrite.h; path = Firebase/Database/Core/Operation/FOverwrite.h; sourceTree = ""; }; + 6A9D4B61A684DA305FA8367430CC9501 /* fbase64.c */ = {isa = PBXFileReference; includeInIndex = 1; name = fbase64.c; path = Firebase/Database/third_party/SocketRocket/fbase64.c; sourceTree = ""; }; + 6ACE358791743E000CFCB19614F5CE16 /* GDTCORPlatform.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORPlatform.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORPlatform.m; sourceTree = ""; }; + 6AEFD138EE7C9728145FFC7C5D91EB61 /* Pods-PediatricPancreas_Storyboard-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PediatricPancreas_Storyboard-Info.plist"; sourceTree = ""; }; + 6AF4EFB562C4F2ACC556C482569CDAC7 /* FIRDatabaseReference.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseReference.m; path = Firebase/Database/FIRDatabaseReference.m; sourceTree = ""; }; + 6B42259F661E6F3C660CF1AE5031683E /* FIRInstanceIDCheckinPreferences_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences_Private.h; path = Firebase/InstanceID/FIRInstanceIDCheckinPreferences_Private.h; sourceTree = ""; }; + 6B5054CF11B84CB3FA9A573C0176038A /* FSparseSnapshotTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSparseSnapshotTree.m; path = Firebase/Database/Core/FSparseSnapshotTree.m; sourceTree = ""; }; + 6B51851E07A886CF2821B854EA81E101 /* FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceID.m; path = Firebase/InstanceID/FIRInstanceID.m; sourceTree = ""; }; + 6BBE4090EA3B9932677701AF91974C67 /* FIRLibrary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLibrary.h; path = FirebaseCore/Sources/Private/FIRLibrary.h; sourceTree = ""; }; + 6BDB4CAA763E5FF7337EDEB141AFD95A /* skiplist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = skiplist.h; path = db/skiplist.h; sourceTree = ""; }; + 6BEAA6AF83FDDCDCFCF2A22F215C51BC /* FIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndex.m; path = Firebase/Database/FIndex.m; sourceTree = ""; }; + 6C6B82976BE98D85A276818786669979 /* FIRStorageObservableTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageObservableTask_Private.h; path = FirebaseStorage/Sources/FIRStorageObservableTask_Private.h; sourceTree = ""; }; + 6CE95ABB415602B3D411D9B619A4E1A9 /* FQueryParams.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FQueryParams.m; path = Firebase/Database/Core/FQueryParams.m; sourceTree = ""; }; + 6D00CFE10ED50E217A18222CFB918840 /* FirebaseCore.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseCore.modulemap; sourceTree = ""; }; + 6E1E4893A247B3564298AD37244E5E4A /* FSnapshotUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotUtilities.m; path = Firebase/Database/Snapshot/FSnapshotUtilities.m; sourceTree = ""; }; + 6E5B60F06DA7799B681DAF0B1D2005CE /* FirebaseInstallations-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstallations-umbrella.h"; sourceTree = ""; }; + 6F17AA9202487602D6AB7C3285CD4697 /* FTupleUserCallback.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleUserCallback.h; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.h; sourceTree = ""; }; + 6FA32E4E626458BC0248B40BCAED895C /* firebasecore.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = firebasecore.nanopb.c; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.c; sourceTree = ""; }; + 6FBACF296A5333288E22B9978DF7798E /* leveldb-library-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "leveldb-library-umbrella.h"; sourceTree = ""; }; + 6FD6C19FE120D8553793CC6271F99B2D /* GoogleDataTransportCCTSupport.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransportCCTSupport.xcconfig; sourceTree = ""; }; + 707D8125F2FAB7F6422BB626C37044D0 /* NSData+SRB64Additions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSData+SRB64Additions.h"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.h"; sourceTree = ""; }; + 709376BC4C402E261D56E950EEF1F71B /* FBLPromise+Testing.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Testing.m"; path = "Sources/FBLPromises/FBLPromise+Testing.m"; sourceTree = ""; }; + 713848D338963B5826A36B0526691EE8 /* FIRComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponent.m; path = FirebaseCore/Sources/FIRComponent.m; sourceTree = ""; }; + 71DA7C5A98E56EFF594760AD94F1C73C /* FTupleBoolBlock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleBoolBlock.m; path = Firebase/Database/Utilities/Tuples/FTupleBoolBlock.m; sourceTree = ""; }; + 720B7D4BFAC22CBEB1F9CE8E9D9823FE /* FirebaseAuthInterop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseAuthInterop.xcconfig; sourceTree = ""; }; + 722C71C6D27A3037C21FC011B803AA74 /* FirebaseCoreDiagnostics-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCoreDiagnostics-umbrella.h"; sourceTree = ""; }; + 72597659B9DB60714BB5B7577D28FEDD /* FTrackedQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTrackedQuery.h; path = Firebase/Database/Persistence/FTrackedQuery.h; sourceTree = ""; }; + 72AD2864FE4085C639DB8DCEBC3129B0 /* FLimitedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLimitedFilter.m; path = Firebase/Database/Core/View/Filter/FLimitedFilter.m; sourceTree = ""; }; + 72AD7602E5FEDA3830584CA043EB7F4C /* FIRInstanceIDBackupExcludedPlist.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDBackupExcludedPlist.m; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.m; sourceTree = ""; }; + 748D3B36EBC228F82613077FDE13692C /* dbformat.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = dbformat.cc; path = db/dbformat.cc; sourceTree = ""; }; + 74AEFB17E19376B554C4B5CBE9839CFC /* FMaxNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMaxNode.m; path = Firebase/Database/FMaxNode.m; sourceTree = ""; }; + 74CAEF8480566F2AC62C5C743E46760D /* status.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = status.cc; path = util/status.cc; sourceTree = ""; }; + 74CDCD1E534C5FA7C7571D7246388818 /* FIRInstanceIDCheckinPreferences+Internal.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstanceIDCheckinPreferences+Internal.m"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.m"; sourceTree = ""; }; + 75488CF61E51A631F39BCAB3BD1723B4 /* hash.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = hash.cc; path = util/hash.cc; sourceTree = ""; }; + 75967CE2C51C3463D72B9F051DAE5A38 /* GULSceneDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler.h; path = GoogleUtilities/SceneDelegateSwizzler/Private/GULSceneDelegateSwizzler.h; sourceTree = ""; }; + 75CBA7F15D495B26751E54BF4A558FA1 /* FIRInstanceIDAuthKeyChain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDAuthKeyChain.h; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.h; sourceTree = ""; }; + 76076FE9A810D6F3BB2702942C80DAE1 /* FIRDataSnapshot_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDataSnapshot_Private.h; path = Firebase/Database/Api/Private/FIRDataSnapshot_Private.h; sourceTree = ""; }; + 764C432940EFD97B8CE3336C8257B57E /* FIRInstanceIDCheckinPreferences.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCheckinPreferences.h; path = Firebase/InstanceID/Private/FIRInstanceIDCheckinPreferences.h; sourceTree = ""; }; + 7661DE9A527D6B176752AAFDF7C1E0A4 /* FIRInstallationsAuthTokenResultInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResultInternal.h; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResultInternal.h; sourceTree = ""; }; + 76C1FFB27224C9E18EA9AA2E0B897BC7 /* FirebaseInstallations.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseInstallations.xcconfig; sourceTree = ""; }; + 76F6CAA85B9481E77015FE98685F15E3 /* FWebSocketConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWebSocketConnection.h; path = Firebase/Database/Realtime/FWebSocketConnection.h; sourceTree = ""; }; + 774ACC4D4332DC492738A1293DCAE200 /* FBLPromiseError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromiseError.m; path = Sources/FBLPromises/FBLPromiseError.m; sourceTree = ""; }; + 77BC895560CE00DAEB6A086A1CDEAEDA /* FIRErrors.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRErrors.m; path = FirebaseCore/Sources/FIRErrors.m; sourceTree = ""; }; + 782084FA99F3F0AA7F176FA5363CDCC7 /* FImmutableSortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableSortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.h; sourceTree = ""; }; + 78362BB93558FF4EAAEB1E8B43AF9174 /* FIRStorageTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTask.m; path = FirebaseStorage/Sources/FIRStorageTask.m; sourceTree = ""; }; + 788528DEECC60A3130BFE6A2DD831079 /* FBLPromiseError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromiseError.h; path = Sources/FBLPromises/include/FBLPromiseError.h; sourceTree = ""; }; + 788D52215E806B9AAF19263432A92BBD /* FIRInstallations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallations.m; path = FirebaseInstallations/Source/Library/FIRInstallations.m; sourceTree = ""; }; + 792AFB5085BC525196F9BA0AE3A01326 /* FViewCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewCache.h; path = Firebase/Database/Core/View/FViewCache.h; sourceTree = ""; }; + 79975F9B23E6D90138DD71D7F47EFDB4 /* FirebaseAnalytics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FirebaseAnalytics.framework; path = Frameworks/FirebaseAnalytics.framework; sourceTree = ""; }; + 79F3DEB203D9A6D3538745CB46A6B6BE /* GDTCCTPrioritizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTPrioritizer.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTPrioritizer.m; sourceTree = ""; }; + 7B4F315F3C9A54FD6665C263FE3FE692 /* FTypedefs_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs_Private.h; path = Firebase/Database/Api/Private/FTypedefs_Private.h; sourceTree = ""; }; + 7C5330642B43535CB64DF4DEB6A008A7 /* FIRDataSnapshot.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDataSnapshot.m; path = Firebase/Database/Api/FIRDataSnapshot.m; sourceTree = ""; }; + 7CA76B59C217CF7E6BB876EF16BA6E76 /* GoogleDataTransport.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleDataTransport.xcconfig; sourceTree = ""; }; + 7D0233BAEAA67BC6CA1D33848C2D0B0E /* GDTCCTPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCCTPrioritizer.h; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Private/GDTCCTPrioritizer.h; sourceTree = ""; }; + 7D2D95038A32C6F364131AE25DA18D37 /* FEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEmptyNode.m; path = Firebase/Database/Snapshot/FEmptyNode.m; sourceTree = ""; }; + 7DC869DC361D2BDADAFAE9ECAF9D61C8 /* FServerValues.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FServerValues.h; path = Firebase/Database/Core/FServerValues.h; sourceTree = ""; }; + 7E65C6252D7B9C6219B60EF273C7BD3F /* FIRInstallationsIIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDTokenStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDTokenStore.h; sourceTree = ""; }; + 7E7C15052C0D43C705657358284FDD5A /* FEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRegistration.h; path = Firebase/Database/Core/View/FEventRegistration.h; sourceTree = ""; }; + 7EAA193AE29B62BC092AD06205FD31C8 /* FAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAuthTokenProvider.m; path = Firebase/Database/Login/FAuthTokenProvider.m; sourceTree = ""; }; + 7EBA5F26A7ACDF18FC265E9A4E42DFA7 /* FMerge.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FMerge.m; path = Firebase/Database/Core/Operation/FMerge.m; sourceTree = ""; }; + 7F04B2F4684D4B3EA35FD95BF17E07F1 /* GTMSessionUploadFetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionUploadFetcher.m; path = Source/GTMSessionUploadFetcher.m; sourceTree = ""; }; + 7F502C86D58BBC8320F07C65EFEB0D65 /* FIRDatabaseConfig_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig_Private.h; path = Firebase/Database/FIRDatabaseConfig_Private.h; sourceTree = ""; }; + 7FA6113A1FB0835D3542880DB4C2C78B /* bloom.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = bloom.cc; path = util/bloom.cc; sourceTree = ""; }; + 7FA6CE7B8DD64D3E66580F5383EA2133 /* FIRInstallationsIIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIIDStore.m; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.m; sourceTree = ""; }; + 805E27E72E56B05291C95F20340F6635 /* FChildEventRegistration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildEventRegistration.h; path = Firebase/Database/Core/View/FChildEventRegistration.h; sourceTree = ""; }; + 808CF5532538521A7A0CBECF62C43FED /* FirebaseInstallations-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseInstallations-Info.plist"; sourceTree = ""; }; + 80CA19561A2817A212C0488DEA559C8B /* FOperationSource.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FOperationSource.m; path = Firebase/Database/Core/Operation/FOperationSource.m; sourceTree = ""; }; + 8151357CD1DF92DA0968F4263590737C /* FBLPromise+Timeout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Timeout.h"; path = "Sources/FBLPromises/include/FBLPromise+Timeout.h"; sourceTree = ""; }; + 818EA601A22844DE95498B87F08F4CE8 /* FLimitedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLimitedFilter.h; path = Firebase/Database/Core/View/Filter/FLimitedFilter.h; sourceTree = ""; }; + 81B7215BC7FAD9F6EA89A037D4450CE0 /* FirebaseCore-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseCore-umbrella.h"; sourceTree = ""; }; + 81BB2A12A57AC10B0729222BF61A4E46 /* FirebaseCoreDiagnosticsInterop.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnosticsInterop.xcconfig; sourceTree = ""; }; + 81CD2FBB0D1DF2DE80B0A92A432198D5 /* FIRStorageConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageConstants.h; path = FirebaseStorage/Sources/Public/FIRStorageConstants.h; sourceTree = ""; }; + 82298B35EE4C04E3F2E48ADB974F83FC /* FIRTransactionResult_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRTransactionResult_Private.h; path = Firebase/Database/Api/Private/FIRTransactionResult_Private.h; sourceTree = ""; }; + 830B396C70A3D0C1AD07F7F579343658 /* FIROptionsInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIROptionsInternal.h; path = FirebaseCore/Sources/Private/FIROptionsInternal.h; sourceTree = ""; }; + 8357EDEAA0A8963A7A21EBFAC6DA743E /* GDTCORAssert.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORAssert.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORAssert.m; sourceTree = ""; }; + 83601D3D66D4C646F41A88B146365C27 /* FIRInstanceIDTokenFetchOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenFetchOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenFetchOperation.m; sourceTree = ""; }; + 83CD465F0A45201ABBAE6485F83F43E8 /* GDTCORUploadCoordinator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadCoordinator.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadCoordinator.m; sourceTree = ""; }; + 844DBAFA06AA17E01947CC83D557C229 /* GDTCORLifecycle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORLifecycle.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORLifecycle.m; sourceTree = ""; }; + 84672658BD8FE38B6372AFB154D09F65 /* FImmutableTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FImmutableTree.h; path = Firebase/Database/Core/Utilities/FImmutableTree.h; sourceTree = ""; }; + 84DF235307E2195AC3E126915E5737F5 /* FSyncPoint.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSyncPoint.h; path = Firebase/Database/Core/FSyncPoint.h; sourceTree = ""; }; + 850CBF344E1BD1CF84B5206F0E4F3AA6 /* FirebaseInstanceID-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstanceID-dummy.m"; sourceTree = ""; }; + 856069552761D6C6E970C60B6DFB24FC /* FIRErrorCode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrorCode.h; path = FirebaseCore/Sources/Private/FIRErrorCode.h; sourceTree = ""; }; + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleDataTransport.framework; path = GoogleDataTransport.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 85BDAD751CA36AAB6F83EFD5C027EA91 /* GDTCORClock.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORClock.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORClock.h; sourceTree = ""; }; + 865B4435A179E8D322EEB8594A18DFAD /* FIRDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase.h; path = Firebase/Database/Public/FIRDatabase.h; sourceTree = ""; }; + 875FED658B925BC28611FDB1B8858369 /* GDTCORUploadPackage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORUploadPackage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORUploadPackage.m; sourceTree = ""; }; + 8796EE5E561EE5AC1133A1E430CD4EE0 /* GULAppDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppDelegateSwizzler.m; path = GoogleUtilities/AppDelegateSwizzler/GULAppDelegateSwizzler.m; sourceTree = ""; }; + 879E2DE3ADE8E82073D5CED0089B357B /* FIRInstallationsStoredAuthToken.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStoredAuthToken.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.m; sourceTree = ""; }; + 87ED48D67D39DE00A35A205D0B1B05B6 /* GULNetworkLoggerProtocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkLoggerProtocol.h; path = GoogleUtilities/Network/Private/GULNetworkLoggerProtocol.h; sourceTree = ""; }; + 87F6444DE4F1D787D0B1FB58BD680119 /* FIRDatabase_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabase_Private.h; path = Firebase/Database/Api/Private/FIRDatabase_Private.h; sourceTree = ""; }; + 8853FCD9B54090977DA47CDC4CE1BE96 /* no_destructor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = no_destructor.h; path = util/no_destructor.h; sourceTree = ""; }; + 88629EDEAC20BEE6D9706C0D1683C65A /* FIRStorageTokenAuthorizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageTokenAuthorizer.m; path = FirebaseStorage/Sources/FIRStorageTokenAuthorizer.m; sourceTree = ""; }; + 887E36B3DBCD3FE4AC51137704580907 /* FStringUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FStringUtilities.m; path = Firebase/Database/Utilities/FStringUtilities.m; sourceTree = ""; }; + 88F58F93946BE6895E8BBF7AF2D2D164 /* FIRStorageComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageComponent.h; path = FirebaseStorage/Sources/FIRStorageComponent.h; sourceTree = ""; }; + 89308F35D1DD5AFD0EFE15D0E4153250 /* nanopb-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "nanopb-Info.plist"; sourceTree = ""; }; + 8931E783ED057317826553414CE66BF4 /* FBLPromise+Wrap.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Wrap.h"; path = "Sources/FBLPromises/include/FBLPromise+Wrap.h"; sourceTree = ""; }; + 8A57155E388077CC8F4BCBF83A0702DE /* leveldb-library-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "leveldb-library-Info.plist"; sourceTree = ""; }; + 8A78F28BB6A74CF05958DCF007498954 /* FIRDatabaseQuery_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseQuery_Private.h; sourceTree = ""; }; + 8B1E2BCB035B1D3DC3D62CBD00650324 /* GDTCORStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORStorage.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORStorage.m; sourceTree = ""; }; + 8B2BC02CB066E06F4B11FD2D5F9B8573 /* FIRInstallationsAuthTokenResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAuthTokenResult.h; path = FirebaseInstallations/Source/Library/Public/FIRInstallationsAuthTokenResult.h; sourceTree = ""; }; + 8B90CFA09998FA5040F032B04C452424 /* GULNetworkConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetworkConstants.m; path = GoogleUtilities/Network/GULNetworkConstants.m; sourceTree = ""; }; + 8BB4BB40C8BAC7ADD48C45341955554A /* FPersistentConnection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistentConnection.h; path = Firebase/Database/Core/FPersistentConnection.h; sourceTree = ""; }; + 8C4A7F66B2805F2635EB770E33626B88 /* FEmptyNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEmptyNode.h; path = Firebase/Database/Snapshot/FEmptyNode.h; sourceTree = ""; }; + 8C53D964DD593409B7EDF149D2D09939 /* FRangedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRangedFilter.m; path = Firebase/Database/FRangedFilter.m; sourceTree = ""; }; + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCoreDiagnostics.framework; path = FirebaseCoreDiagnostics.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8CDEF6C17D03168126524359F161CB71 /* FIRInstanceIDVersionUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDVersionUtilities.m; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.m; sourceTree = ""; }; + 8D2DFCE2D56BFB801722402559090803 /* GoogleUtilities.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GoogleUtilities.xcconfig; sourceTree = ""; }; + 8D58C1777E830172B31A330830F0C9F4 /* FPath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPath.m; path = Firebase/Database/Core/Utilities/FPath.m; sourceTree = ""; }; + 8D79F1C1C537FF4B030110EC6A6A0E3D /* FIRErrors.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRErrors.h; path = FirebaseCore/Sources/Private/FIRErrors.h; sourceTree = ""; }; + 906F798474B836189059B9A51D6BBFBB /* FIRInstanceIDStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStore.m; path = Firebase/InstanceID/FIRInstanceIDStore.m; sourceTree = ""; }; + 9078AF964D68A97418B2A5520D4F95F3 /* log_writer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_writer.h; path = db/log_writer.h; sourceTree = ""; }; + 90D43FD412508EEDA57DF27A754BBC88 /* GDTCORStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStorage.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage.h; sourceTree = ""; }; + 90EFE7C5E29A5A1DC18F8FFE9C38ED1F /* FSnapshotHolder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSnapshotHolder.m; path = Firebase/Database/Core/FSnapshotHolder.m; sourceTree = ""; }; + 915F579A059A8F18FF02F62D36B4F1BC /* PromisesObjC.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PromisesObjC.xcconfig; sourceTree = ""; }; + 916F2253BB01607784C0DB1216E2E9CE /* FIRDatabaseReference_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseReference_Private.h; path = Firebase/Database/Api/Private/FIRDatabaseReference_Private.h; sourceTree = ""; }; + 91BC6FFC5BA4E9232D75C5DA2913F91A /* FIRInstanceIDAuthKeyChain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthKeyChain.m; path = Firebase/InstanceID/FIRInstanceIDAuthKeyChain.m; sourceTree = ""; }; + 921DB4627BC7133390AD63BC6F55EB53 /* FirebaseStorage.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseStorage.modulemap; sourceTree = ""; }; + 9226C7EFCB8792B87686A9B3CCF32F26 /* FIRConfiguration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRConfiguration.m; path = FirebaseCore/Sources/FIRConfiguration.m; sourceTree = ""; }; + 923F5208B9B8E8112E5376E4979EEA33 /* FIRInstallationsStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsStore.m; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.m; sourceTree = ""; }; + 9295AFCFC39BB1FDBB0EC3D9ECCF37CE /* env.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env.cc; path = util/env.cc; sourceTree = ""; }; + 92B13DDB5CB3F9B1C18773D451D044FC /* FIRStorageTask_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTask_Private.h; path = FirebaseStorage/Sources/FIRStorageTask_Private.h; sourceTree = ""; }; + 92E0699CC8C007B776F78978059335C0 /* cct.nanopb.c */ = {isa = PBXFileReference; includeInIndex = 1; name = cct.nanopb.c; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/Protogen/nanopb/cct.nanopb.c; sourceTree = ""; }; + 9304301663FF641F230B41BD66C1231F /* FUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FUtilities.h; path = Firebase/Database/Utilities/FUtilities.h; sourceTree = ""; }; + 933460CA2E165B422AB65FD22F461DC0 /* FirebaseInstallations-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseInstallations-dummy.m"; sourceTree = ""; }; + 93588089D0F50EF58C900EDDED947082 /* FIRInstanceIDKeychain.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDKeychain.m; path = Firebase/InstanceID/FIRInstanceIDKeychain.m; sourceTree = ""; }; + 9379B377EEB58D4388B5DC1218A2CCC8 /* write_batch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch.h; path = include/leveldb/write_batch.h; sourceTree = ""; }; + 9384A9222E3CA4ED907B7F7FD64AFABA /* FIRCoreDiagnostics.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnostics.m; path = Firebase/CoreDiagnostics/FIRCDLibrary/FIRCoreDiagnostics.m; sourceTree = ""; }; + 93C88B8F3BAB0E426BD1EFF9B685F904 /* FChildChangeAccumulator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FChildChangeAccumulator.h; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.h; sourceTree = ""; }; + 93D331B9DF3258EB11BC34C9C24AD173 /* FRepoInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRepoInfo.h; path = Firebase/Database/Core/FRepoInfo.h; sourceTree = ""; }; + 93FC2872D62DB58E74049962B6F9FC53 /* FIRInstallationsIIDStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIIDStore.h; path = FirebaseInstallations/Source/Library/IIDMigration/FIRInstallationsIIDStore.h; sourceTree = ""; }; + 94541BC6EE0BD2BEFDF6CD8A2EE668BA /* version_edit.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = version_edit.cc; path = db/version_edit.cc; sourceTree = ""; }; + 945DAB6906A81D5EC5D0F1F2DA26500C /* FKeyIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FKeyIndex.h; path = Firebase/Database/FKeyIndex.h; sourceTree = ""; }; + 95AE095CF820AEDCF24899B9BF862975 /* GDTCORTransport.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORTransport.h; sourceTree = ""; }; + 95E6DE4A2B320864D331EB38E2425AD8 /* FTransformedEnumerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTransformedEnumerator.m; path = Firebase/Database/FTransformedEnumerator.m; sourceTree = ""; }; + 96449186D538D5BB130663F9FE2A1F30 /* FIndexedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedNode.m; path = Firebase/Database/Snapshot/FIndexedNode.m; sourceTree = ""; }; + 96AD2BF11C0A8B331AAF6F623FF7762A /* FWebSocketConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWebSocketConnection.m; path = Firebase/Database/Realtime/FWebSocketConnection.m; sourceTree = ""; }; + 96EA9A40414062574AB929B056EEEEC8 /* FIRInstanceID_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID_Private.h; path = Firebase/InstanceID/Private/FIRInstanceID_Private.h; sourceTree = ""; }; + 970D1EE49B5B4AE3A1C04FE453E26463 /* FIRComponentType.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRComponentType.m; path = FirebaseCore/Sources/FIRComponentType.m; sourceTree = ""; }; + 9724FC0DB2B700C5916C4B225396830E /* options.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = options.h; path = include/leveldb/options.h; sourceTree = ""; }; + 975C05758199E92BCDF7B8AEFA8DC5BC /* FSyncPoint.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSyncPoint.m; path = Firebase/Database/Core/FSyncPoint.m; sourceTree = ""; }; + 97C269625485B6A7289C6746D99E1EFF /* FBLPromise+All.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+All.m"; path = "Sources/FBLPromises/FBLPromise+All.m"; sourceTree = ""; }; + 97E3FCCAF2E02AF6ECBD79CFF27F1C32 /* GDTCORTransport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORTransport.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORTransport.m; sourceTree = ""; }; + 986E76CDB36A58245C5FFB25DF53A794 /* GDTCOREvent_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCOREvent_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCOREvent_Private.h; sourceTree = ""; }; + 99445128B63465CAA78511775C044826 /* FIRInstallationsLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsLogger.m; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.m; sourceTree = ""; }; + 99BE1790BA27F64B840314B5027E34B2 /* GULSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSwizzler.m; path = GoogleUtilities/MethodSwizzler/GULSwizzler.m; sourceTree = ""; }; + 9A1564C52DDFB1957E792196332B66A9 /* FIRStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorage.h; path = FirebaseStorage/Sources/Public/FIRStorage.h; sourceTree = ""; }; + 9A43440C82173CB5E42191974CF04F1D /* GULNetwork.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULNetwork.m; path = GoogleUtilities/Network/GULNetwork.m; sourceTree = ""; }; + 9A462BED47E045F027B03735EEBDFFF1 /* FIRStorageGetDownloadURLTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetDownloadURLTask.h; path = FirebaseStorage/Sources/FIRStorageGetDownloadURLTask.h; sourceTree = ""; }; + 9A4EAEA519CDE2E290007A2243F72CBC /* db_impl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = db_impl.h; path = db/db_impl.h; sourceTree = ""; }; + 9A776495F0C11B2D6E910717050FE201 /* FBLPromise+Recover.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Recover.h"; path = "Sources/FBLPromises/include/FBLPromise+Recover.h"; sourceTree = ""; }; + 9A84CC0D422B1D53DB21636894EE1EFC /* FIRDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDiagnosticsData.h; path = FirebaseCore/Sources/Private/FIRDiagnosticsData.h; sourceTree = ""; }; + 9ACA1297A58C6DEEE74A97F1D898F72B /* FIRInstallationsKeychainUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsKeychainUtils.m; path = FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.m; sourceTree = ""; }; + 9AD2E9ECB85005226A653B4C97E2D639 /* FIRInstanceIDAuthService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAuthService.m; path = Firebase/InstanceID/FIRInstanceIDAuthService.m; sourceTree = ""; }; + 9ADC2802276930B11A1968FD14EB6362 /* FirebaseInstanceID-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseInstanceID-umbrella.h"; sourceTree = ""; }; + 9B00ED90C4A7935626C4626A06EF9B8C /* FNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNode.h; path = Firebase/Database/Snapshot/FNode.h; sourceTree = ""; }; + 9B2DC3F3158AC569D8BB4D9159B92FDD /* FIRInstanceIDKeychain.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDKeychain.h; path = Firebase/InstanceID/FIRInstanceIDKeychain.h; sourceTree = ""; }; + 9B5009794F8E9B14AFDCCCC35B349A3D /* FValueIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValueIndex.m; path = Firebase/Database/FValueIndex.m; sourceTree = ""; }; + 9B73657F1BCBACE23835E1CFAE2DFD69 /* FIRInstanceIDStringEncoding.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDStringEncoding.m; path = Firebase/InstanceID/FIRInstanceIDStringEncoding.m; sourceTree = ""; }; + 9BA5379813ED95F892512A874565DB18 /* pb_common.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = pb_common.h; sourceTree = ""; }; + 9C3E5A6D44DDBAA12BB947034F1DDA85 /* block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block.cc; path = table/block.cc; sourceTree = ""; }; + 9C411E83FCE8D78F920AF6FBCD474ACB /* FTupleSetIdPath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleSetIdPath.h; path = Firebase/Database/Utilities/Tuples/FTupleSetIdPath.h; sourceTree = ""; }; + 9C60FD75C09F75F9F289419CC6EC3DBC /* FBLPromise+Then.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Then.h"; path = "Sources/FBLPromises/include/FBLPromise+Then.h"; sourceTree = ""; }; + 9C6603077B3BAE9B69D097E3D89FE4D7 /* FirebaseCoreDiagnostics-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseCoreDiagnostics-dummy.m"; sourceTree = ""; }; + 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseStorage.framework; path = FirebaseStorage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9D04C17438C9FE6F61E8B3DC057EF647 /* FChildChangeAccumulator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildChangeAccumulator.m; path = Firebase/Database/Core/View/Filter/FChildChangeAccumulator.m; sourceTree = ""; }; + 9D5813664B48EEEECBD73FE4B6AF656E /* GDTCORClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORClock.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORClock.m; sourceTree = ""; }; + 9D8978C2B9BC0CE887AF50290BB35F7F /* APLevelDB.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = APLevelDB.h; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.h"; sourceTree = ""; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9DDB6715072A57A18500B34BA425AEBD /* arena.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = arena.h; path = util/arena.h; sourceTree = ""; }; + 9DF96CD59FB20F67464B5372DD87EB2D /* FIRDatabaseQuery.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseQuery.h; path = Firebase/Database/Public/FIRDatabaseQuery.h; sourceTree = ""; }; + 9E57284E338D6F0BA60A7F2435A31E90 /* FIRAuthInterop.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAuthInterop.h; path = Interop/Auth/Public/FIRAuthInterop.h; sourceTree = ""; }; + 9E807E38FDEA4D03D392C95EC28E738C /* two_level_iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = two_level_iterator.h; path = table/two_level_iterator.h; sourceTree = ""; }; + 9E8FA1A885EFD41939BDF374FBA3EEDD /* FIRStorageReference_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageReference_Private.h; path = FirebaseStorage/Sources/FIRStorageReference_Private.h; sourceTree = ""; }; + 9F41AD0ACE33C987BAC1374E6B1320A3 /* NSData+SRB64Additions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSData+SRB64Additions.m"; path = "Firebase/Database/third_party/SocketRocket/NSData+SRB64Additions.m"; sourceTree = ""; }; + A02930679CA97D007C20B3DF2C78DA38 /* FBLPromise+Catch.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Catch.h"; path = "Sources/FBLPromises/include/FBLPromise+Catch.h"; sourceTree = ""; }; + A0575E69E82A456143066F611BF304E9 /* FIRStorageMetadata.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageMetadata.h; path = FirebaseStorage/Sources/Public/FIRStorageMetadata.h; sourceTree = ""; }; + A0B697892DA8B676D87651CB9C438A1D /* FCacheNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCacheNode.h; path = Firebase/Database/Core/View/FCacheNode.h; sourceTree = ""; }; + A0FBCE4F7720531AA7D93AE2CF179D0F /* cache.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = cache.cc; path = util/cache.cc; sourceTree = ""; }; + A1468D1E82115BE338C7006EDB09A252 /* GTMSessionFetcher-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GTMSessionFetcher-Info.plist"; sourceTree = ""; }; + A1E7B8A283EC1446D5E09B2F3647012E /* FIRLoggerLevel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRLoggerLevel.h; path = FirebaseCore/Sources/Public/FIRLoggerLevel.h; sourceTree = ""; }; + A248E1E0FA382168B833426DDECDB4FB /* FTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTree.m; path = Firebase/Database/Core/Utilities/FTree.m; sourceTree = ""; }; + A24FE0E7A20BBABF063F9974EE71BD68 /* FIRInstallationsKeychainUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsKeychainUtils.h; path = FirebaseInstallations/Source/Library/SecureStorage/FIRInstallationsKeychainUtils.h; sourceTree = ""; }; + A25305788598EBB7D81781D92991341A /* FRepoManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoManager.m; path = Firebase/Database/Core/FRepoManager.m; sourceTree = ""; }; + A27D336247C06AEE085EF43CF6156864 /* FIRInstallationsVersion.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsVersion.m; path = FirebaseInstallations/Source/Library/FIRInstallationsVersion.m; sourceTree = ""; }; + A29247354C87D56646F76034F1DDDCFB /* comparator.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = comparator.cc; path = util/comparator.cc; sourceTree = ""; }; + A2A97AE7647179E52903F372F44D6340 /* FIRStorageListTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageListTask.m; path = FirebaseStorage/Sources/FIRStorageListTask.m; sourceTree = ""; }; + A39BBE27DEE67B7711E6288FA3EAAE95 /* FirebaseCoreDiagnostics-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseCoreDiagnostics-Info.plist"; sourceTree = ""; }; + A3B4AC5B091751C2FEFA28BD2F610472 /* slice.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = slice.h; path = include/leveldb/slice.h; sourceTree = ""; }; + A3C2723DD4EBBF36E3422C8F261BC567 /* FIRDatabaseComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseComponent.h; path = Firebase/Database/Api/FIRDatabaseComponent.h; sourceTree = ""; }; + A3D6CD0CB3F7889EF66E4B88ACE8EE4F /* FSnapshotUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotUtilities.h; path = Firebase/Database/Snapshot/FSnapshotUtilities.h; sourceTree = ""; }; + A3E39E8101A41A91A2C935F98E570B0D /* FIRInstanceIDAPNSInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDAPNSInfo.m; path = Firebase/InstanceID/FIRInstanceIDAPNSInfo.m; sourceTree = ""; }; + A3E75433084553833D078D8157B97071 /* FTupleCallbackStatus.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleCallbackStatus.h; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.h; sourceTree = ""; }; + A3F890C9E8FFF45508AAFF1DF9F44F1C /* FIRCoreDiagnosticsConnector.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRCoreDiagnosticsConnector.m; path = FirebaseCore/Sources/FIRCoreDiagnosticsConnector.m; sourceTree = ""; }; + A474C4C0651A543458D27D8A61CCF815 /* GULAppDelegateSwizzler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULAppDelegateSwizzler.h; path = GoogleUtilities/AppDelegateSwizzler/Private/GULAppDelegateSwizzler.h; sourceTree = ""; }; + A4E1EB8597FF3EC84853B45630CA42ED /* GDTCORUploadPackage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadPackage.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORUploadPackage.h; sourceTree = ""; }; + A54C9AF9132A993BDCA8FA4CDB334692 /* FSRWebSocket.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FSRWebSocket.m; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.m; sourceTree = ""; }; + A5B6CB88832D4E926A10C1260DDD5B26 /* FIRDatabaseConfig.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDatabaseConfig.m; path = Firebase/Database/Api/FIRDatabaseConfig.m; sourceTree = ""; }; + A5BF35B8BA91663594BBF5352762EB54 /* GoogleDataTransportCCTSupport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransportCCTSupport-dummy.m"; sourceTree = ""; }; + A5D4B358001D3F084CB3C4CAE20B7C92 /* nanopb-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-umbrella.h"; sourceTree = ""; }; + A5F49AB94F002497A53AFCEAFB1FD6C7 /* GULSceneDelegateSwizzler_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULSceneDelegateSwizzler_Private.h; path = GoogleUtilities/SceneDelegateSwizzler/Internal/GULSceneDelegateSwizzler_Private.h; sourceTree = ""; }; + A6560A52892AAE5757A5CEE963E13593 /* FIRRetryHelper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRRetryHelper.h; path = Firebase/Database/Core/Utilities/FIRRetryHelper.h; sourceTree = ""; }; + A677A20A2384930F4EDAC77AD596B992 /* FirebaseStorage-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "FirebaseStorage-Info.plist"; sourceTree = ""; }; + A6B7B883FE64676C0CD7B665C2CAB402 /* FIRInstallationsAuthTokenResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsAuthTokenResult.m; path = FirebaseInstallations/Source/Library/FIRInstallationsAuthTokenResult.m; sourceTree = ""; }; + A709E7DFAFADE38DEEC73BDCD1D24C7B /* GoogleUtilities.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = GoogleUtilities.modulemap; sourceTree = ""; }; + A7265876B72206667C402E8DA2657541 /* FIRCoreDiagnosticsConnector.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsConnector.h; path = FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h; sourceTree = ""; }; + A727AE1575353CFF867D48C1919605D6 /* write_batch_internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = write_batch_internal.h; path = db/write_batch_internal.h; sourceTree = ""; }; + A841629ECEDFBFB7FF0841EF6C8E1E28 /* FIRInstanceIDBackupExcludedPlist.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDBackupExcludedPlist.h; path = Firebase/InstanceID/FIRInstanceIDBackupExcludedPlist.h; sourceTree = ""; }; + A86D7D56CD84812BBC2847B8B41BB88D /* Pods-PediatricPancreas_Storyboard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas_Storyboard.release.xcconfig"; sourceTree = ""; }; + A92253B0A83EB13072622A5C886F1162 /* FIRComponentContainer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponentContainer.h; path = FirebaseCore/Sources/Private/FIRComponentContainer.h; sourceTree = ""; }; + A9303EA8089F8772A23463AAFBEB9A1D /* FIRInstanceID.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceID.h; path = Firebase/InstanceID/Public/FIRInstanceID.h; sourceTree = ""; }; + A98D534267BBF249F20C291BCAD5DA55 /* FIRStorageComponent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageComponent.m; path = FirebaseStorage/Sources/FIRStorageComponent.m; sourceTree = ""; }; + A9E80D2D264051242FAAC6384CA1ED2D /* GULSceneDelegateSwizzler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULSceneDelegateSwizzler.m; path = GoogleUtilities/SceneDelegateSwizzler/GULSceneDelegateSwizzler.m; sourceTree = ""; }; + A9EC9ED037C6087A02E7502A11DB4B44 /* FPriorityIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPriorityIndex.h; path = Firebase/Database/FPriorityIndex.h; sourceTree = ""; }; + AA0D45E1C53E134EDD9ED58E44506FDB /* FIRCoreDiagnosticsData.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRCoreDiagnosticsData.h; path = Interop/CoreDiagnostics/Public/FIRCoreDiagnosticsData.h; sourceTree = ""; }; + AA2CDC345A549E5ED13CB3912D118A47 /* FIRInstanceIDURLQueryItem.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDURLQueryItem.m; path = Firebase/InstanceID/FIRInstanceIDURLQueryItem.m; sourceTree = ""; }; + AA7F761B656167D3B87EF50DE069B696 /* GULOriginalIMPConvenienceMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULOriginalIMPConvenienceMacros.h; path = GoogleUtilities/MethodSwizzler/Private/GULOriginalIMPConvenienceMacros.h; sourceTree = ""; }; + AB6496D33D3F05745C5AA89A1BCBF238 /* GTMSessionFetcher.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = GTMSessionFetcher.xcconfig; sourceTree = ""; }; + AB743D0C97C93EEEAB0DB0FE278337E2 /* GULNSData+zlib.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "GULNSData+zlib.m"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.m"; sourceTree = ""; }; + ABC50885F71A3B759ABD6A64762A0E6D /* FTreeSortedDictionaryEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTreeSortedDictionaryEnumerator.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionaryEnumerator.h; sourceTree = ""; }; + AC0DBEBA832AEB2C6C3CCBC1E2DCF07D /* FTypedefs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTypedefs.h; path = Firebase/Database/Utilities/FTypedefs.h; sourceTree = ""; }; + AC599B33E662AE5F07C790B72D2C0BA3 /* FPersistenceManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPersistenceManager.h; path = Firebase/Database/Persistence/FPersistenceManager.h; sourceTree = ""; }; + AC59DA87CAFC56215715B1ED2B850470 /* FArraySortedDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FArraySortedDictionary.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FArraySortedDictionary.h; sourceTree = ""; }; + AC60B43FA6D28BB9A4A8E7ED8F591134 /* FIRStorageConstants_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageConstants_Private.h; path = FirebaseStorage/Sources/FIRStorageConstants_Private.h; sourceTree = ""; }; + AC876BD753D740DFC24D59EE46909C72 /* FIRAnalyticsConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAnalyticsConfiguration.h; path = FirebaseCore/Sources/Private/FIRAnalyticsConfiguration.h; sourceTree = ""; }; + ACC08069DA325ABB6838B87AC6835656 /* FPruneForest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPruneForest.h; path = Firebase/Database/Persistence/FPruneForest.h; sourceTree = ""; }; + AD62319FBDEE7FD684B7E6C057EA8BD0 /* filename.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filename.h; path = db/filename.h; sourceTree = ""; }; + AD92B971F394927786C8101BFD4C07E0 /* FParsedUrl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FParsedUrl.h; path = Firebase/Database/Utilities/FParsedUrl.h; sourceTree = ""; }; + AD95BC524E418C110A31AA6B77EE4664 /* GTMSessionFetcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcher.h; path = Source/GTMSessionFetcher.h; sourceTree = ""; }; + ADA04271750C05862833E153F889470C /* FIRAnalyticsConnector.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FIRAnalyticsConnector.framework; path = Frameworks/FIRAnalyticsConnector.framework; sourceTree = ""; }; + AE506B6FA93C8C128423247BFB7439C0 /* GDTCORRegistrar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORRegistrar.h; sourceTree = ""; }; + AE725393C345416026E97A02D28712D4 /* FirebaseCore.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCore.xcconfig; sourceTree = ""; }; + AEAA491E682EA0923D5EE202E2D60D08 /* Firebase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Firebase.h; path = CoreOnly/Sources/Firebase.h; sourceTree = ""; }; + AEBBB845997D63AABC3D3BF792E2AF04 /* FNamedNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNamedNode.m; path = Firebase/Database/FNamedNode.m; sourceTree = ""; }; + B05A5F93428885B5A938FC466B2A15FD /* FIRInstallationsStoredItem.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredItem.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredItem.h; sourceTree = ""; }; + B0CC945D6C82F1429CCFA0460131A4E3 /* export.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = export.h; path = include/leveldb/export.h; sourceTree = ""; }; + B0DA53538D50A020387AB115C11CE206 /* GULAppEnvironmentUtil.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULAppEnvironmentUtil.m; path = GoogleUtilities/Environment/third_party/GULAppEnvironmentUtil.m; sourceTree = ""; }; + B0DB1D9E61CF269224355B759C08644D /* FIRInstallationsIDController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsIDController.m; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.m; sourceTree = ""; }; + B0FFB14C614912059B869AA124CE1548 /* FIRInstanceIDTokenOperation+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDTokenOperation+Private.h"; path = "Firebase/InstanceID/FIRInstanceIDTokenOperation+Private.h"; sourceTree = ""; }; + B1A12E1B5F9F863A9AFEF72FD5DC75BC /* FListenComplete.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FListenComplete.m; path = Firebase/Database/FListenComplete.m; sourceTree = ""; }; + B1EBAFAAEA3B7B4B663AE6FF460AA209 /* FIRDatabaseConfig.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRDatabaseConfig.h; path = Firebase/Database/Api/FIRDatabaseConfig.h; sourceTree = ""; }; + B2D4F7FF0ED7AEDB99891B0C005224EB /* dumpfile.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = dumpfile.h; path = include/leveldb/dumpfile.h; sourceTree = ""; }; + B346E012CA98A38C8509220492705220 /* pb_common.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_common.c; sourceTree = ""; }; + B36EC66A74944CD3B2D95D93B739EF06 /* GoogleDataTransport-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GoogleDataTransport-umbrella.h"; sourceTree = ""; }; + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GoogleUtilities.framework; path = GoogleUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B4B90F0206371335E59420084F0FFAB3 /* testharness.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testharness.h; path = util/testharness.h; sourceTree = ""; }; + B55FE2E8404E0FF6108ED090BF7F4B51 /* FSnapshotHolder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSnapshotHolder.h; path = Firebase/Database/Core/FSnapshotHolder.h; sourceTree = ""; }; + B5993ED6459C75C852370192D89E609A /* FIRStorageTaskSnapshot_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTaskSnapshot_Private.h; path = FirebaseStorage/Sources/FIRStorageTaskSnapshot_Private.h; sourceTree = ""; }; + B62D960DC80DC12623B220EA85CD926B /* FIRInstallationsHTTPError.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsHTTPError.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.h; sourceTree = ""; }; + B6664E7165D5105EE3355D7B7FD1AEAC /* FBLPromise+Any.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Any.h"; path = "Sources/FBLPromises/include/FBLPromise+Any.h"; sourceTree = ""; }; + B6E9B7C31546F012D471390B2E511490 /* nanopb-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "nanopb-dummy.m"; sourceTree = ""; }; + B712425379B4E7BFDB5FAB86EABCBEEA /* FTupleObjects.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleObjects.h; path = Firebase/Database/Utilities/Tuples/FTupleObjects.h; sourceTree = ""; }; + B82F58D4E27A17968CE2E5A6F072524E /* leveldb-library.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "leveldb-library.xcconfig"; sourceTree = ""; }; + B8316BB66D3F5111376080F16B6BA96B /* FirebaseDatabase.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseDatabase.modulemap; sourceTree = ""; }; + B8E8E3D1874DBA689E9ABB2098726F79 /* FTupleCallbackStatus.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleCallbackStatus.m; path = Firebase/Database/Utilities/Tuples/FTupleCallbackStatus.m; sourceTree = ""; }; + B978BE12FBC5DB5499497CF643032AE7 /* FKeepSyncedEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FKeepSyncedEventRegistration.m; path = Firebase/Database/Core/View/FKeepSyncedEventRegistration.m; sourceTree = ""; }; + B9B32050A70491C586A91F247F294DB7 /* FIRStorageDownloadTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageDownloadTask.m; path = FirebaseStorage/Sources/FIRStorageDownloadTask.m; sourceTree = ""; }; + B9B6D75A17283D9FBCD34327DD2E6D55 /* filter_block.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = filter_block.cc; path = table/filter_block.cc; sourceTree = ""; }; + BA2003C66B9E13070828B7FF4822C7EB /* histogram.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = histogram.h; path = util/histogram.h; sourceTree = ""; }; + BA66AD23BE6F4FA5FB56166743AF197B /* FAtomicNumber.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAtomicNumber.h; path = Firebase/Database/Utilities/FAtomicNumber.h; sourceTree = ""; }; + BB9276EF011DDA9D5DCE46C59B323984 /* FWriteTreeRef.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FWriteTreeRef.m; path = Firebase/Database/Core/FWriteTreeRef.m; sourceTree = ""; }; + BBD01369BBFDE33B2EA046878BD3C0B9 /* FirebaseCore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseCore.h; path = FirebaseCore/Sources/Public/FirebaseCore.h; sourceTree = ""; }; + BC4B5FAFD6E4A5815AD9618CF1F3B07D /* nanopb-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "nanopb-prefix.pch"; sourceTree = ""; }; + BC53E9479AFE30937D40541E9A3C3A67 /* port_stdcxx.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_stdcxx.h; path = port/port_stdcxx.h; sourceTree = ""; }; + BCCD4D307EC99FAF7669F3B43419DAEF /* arena.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = arena.cc; path = util/arena.cc; sourceTree = ""; }; + BD0F6EDF8E4EF83990ED65297E06B81B /* FIRLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRLogger.m; path = FirebaseCore/Sources/FIRLogger.m; sourceTree = ""; }; + BD19B03DA6680BFB310D0060308CCD22 /* filter_policy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_policy.h; path = include/leveldb/filter_policy.h; sourceTree = ""; }; + BD1B051942ADDA047D2B87D13FBA2954 /* FLLRBValueNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FLLRBValueNode.h; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.h; sourceTree = ""; }; + BDC5BA23017FC776000E41644015C34C /* FValidation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FValidation.m; path = Firebase/Database/Utilities/FValidation.m; sourceTree = ""; }; + BDF0C9F93532C7101C7CB69E2867EC6B /* FTupleUserCallback.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleUserCallback.m; path = Firebase/Database/Utilities/Tuples/FTupleUserCallback.m; sourceTree = ""; }; + BE201BF532103F0EFC7059AD2232DEC1 /* FIROptions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIROptions.m; path = FirebaseCore/Sources/FIROptions.m; sourceTree = ""; }; + BE42B997AA83C8CA9F70E16204BDC654 /* PromisesObjC-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PromisesObjC-dummy.m"; sourceTree = ""; }; + BF8836BA9AAA1475DEDA54342B0F927B /* FImmutableSortedSet.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedSet.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedSet.m; sourceTree = ""; }; + BFE3EAA708149B8146C731A7AC4FB682 /* GDTCORDataFuture.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORDataFuture.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORDataFuture.m; sourceTree = ""; }; + C0E2C72E350099611A032C30D9E97D46 /* FTupleObjectNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjectNode.m; path = Firebase/Database/Utilities/Tuples/FTupleObjectNode.m; sourceTree = ""; }; + C0EB6D5853B9601249F3331602421954 /* FView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FView.h; path = Firebase/Database/Core/View/FView.h; sourceTree = ""; }; + C1225D1251AB40E186EA9E17BBEAAEAE /* FIRStorageDownloadTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageDownloadTask.h; path = FirebaseStorage/Sources/Public/FIRStorageDownloadTask.h; sourceTree = ""; }; + C12710FB7206C72F3780C9F49C020BA1 /* c.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = c.h; path = include/leveldb/c.h; sourceTree = ""; }; + C15F1AE465F68C48C5F2AC5D6A1AD58B /* GDTCORTransport_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORTransport_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORTransport_Private.h; sourceTree = ""; }; + C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = GTMSessionFetcher.framework; path = GTMSessionFetcher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C23D9EF2FABCE6C06BB74403C7E0FF09 /* FIRStorageListResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageListResult.m; path = FirebaseStorage/Sources/FIRStorageListResult.m; sourceTree = ""; }; + C261FFBF13CE61BB390215E9CA9C5FD5 /* FIRNoopAuthTokenProvider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRNoopAuthTokenProvider.m; path = Firebase/Database/Login/FIRNoopAuthTokenProvider.m; sourceTree = ""; }; + C2B014A14B7708A1DFC2279C43A94DF2 /* histogram.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = histogram.cc; path = util/histogram.cc; sourceTree = ""; }; + C3313BC5CDF1D9223D5FBA0F11BA5EBD /* cache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = cache.h; path = include/leveldb/cache.h; sourceTree = ""; }; + C34CFA0CD6D054D8ECCB50347442C309 /* FViewProcessor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessor.h; path = Firebase/Database/FViewProcessor.h; sourceTree = ""; }; + C34D9E474712175C6FD3E2563CE00F17 /* FCancelEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCancelEvent.h; path = Firebase/Database/Core/View/FCancelEvent.h; sourceTree = ""; }; + C3601A2F20B68571CFD4D5585BA05C52 /* FChange.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChange.m; path = Firebase/Database/Core/View/FChange.m; sourceTree = ""; }; + C37EA4AD27A51901CB827A1DEC06AC6D /* FirebaseInstallations.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FirebaseInstallations.modulemap; sourceTree = ""; }; + C38C2F78048851357831E011AF92F876 /* FIRInstallationsItem+RegisterInstallationAPI.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstallationsItem+RegisterInstallationAPI.h"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.h"; sourceTree = ""; }; + C4608282EA2EF296797D3E04024663A6 /* FIRInstanceIDVersionUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDVersionUtilities.h; path = Firebase/InstanceID/FIRInstanceIDVersionUtilities.h; sourceTree = ""; }; + C4ADE903728E190BA0EE2D6BF297FB07 /* FIRInstanceIDTokenDeleteOperation.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDTokenDeleteOperation.m; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.m; sourceTree = ""; }; + C584B9B3948F8F67F6591EE319DACC20 /* db_impl.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_impl.cc; path = db/db_impl.cc; sourceTree = ""; }; + C5A1079708AAFDAB8F4F53D6660A3B1E /* FIRConfigurationInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfigurationInternal.h; path = FirebaseCore/Sources/Private/FIRConfigurationInternal.h; sourceTree = ""; }; + C6F4380E9D8DEA36E07AF6214D0E0B97 /* FIRInstanceIDCheckinStore.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinStore.m; path = Firebase/InstanceID/FIRInstanceIDCheckinStore.m; sourceTree = ""; }; + C7B2ECE638DABE730837F22C5CC35FB2 /* FIRStorageListResult_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListResult_Private.h; path = FirebaseStorage/Sources/FIRStorageListResult_Private.h; sourceTree = ""; }; + C7CE15484C79764DF2F6200480570299 /* logging.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = logging.h; path = util/logging.h; sourceTree = ""; }; + C7D94DF9C10300D6FB71C8D9A931EB78 /* FIRInstanceIDTokenInfo.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenInfo.h; path = Firebase/InstanceID/FIRInstanceIDTokenInfo.h; sourceTree = ""; }; + C7E966DF9D6827BA4FDAC1BF918F69E2 /* GDTCORPrioritizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPrioritizer.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPrioritizer.h; sourceTree = ""; }; + C809DE63B19C8CBD6601AD4374B3033F /* FAtomicNumber.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FAtomicNumber.m; path = Firebase/Database/Utilities/FAtomicNumber.m; sourceTree = ""; }; + C81FBDB69D3D7E4329AD1A0FD479E6D7 /* FTreeNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeNode.m; path = Firebase/Database/Core/Utilities/FTreeNode.m; sourceTree = ""; }; + C849D3E9FF9EB2A0EE26851441710E41 /* FIndexedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIndexedFilter.h; path = Firebase/Database/Core/View/Filter/FIndexedFilter.h; sourceTree = ""; }; + C883E313B32C196FA849B2E308CF1812 /* FBLPromise+Always.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Always.h"; path = "Sources/FBLPromises/include/FBLPromise+Always.h"; sourceTree = ""; }; + C89732C5EDCECB77A12B87C1018E8B99 /* FTreeSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTreeSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FTreeSortedDictionary.m; sourceTree = ""; }; + C91AB5BA273E41BEE728337BDEABA5C7 /* GULNetworkURLSession.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetworkURLSession.h; path = GoogleUtilities/Network/Private/GULNetworkURLSession.h; sourceTree = ""; }; + C9A065473A00B170B362BDB7ECF1B77C /* hash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = hash.h; path = util/hash.h; sourceTree = ""; }; + C9ABC90AE3F25AE15E777A3E6803A97F /* Pods-PediatricPancreas_Storyboard.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PediatricPancreas_Storyboard.modulemap"; sourceTree = ""; }; + C9D62FF736B44971DF9091825EA70670 /* GDTCORStoredEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORStoredEvent.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORStoredEvent.m; sourceTree = ""; }; + CAC2D41AC8570E0DFC63ADB7AC6A34C4 /* GTMSessionFetcher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "GTMSessionFetcher-umbrella.h"; sourceTree = ""; }; + CAED39340F04B8544FC496CFCF1EADCC /* GDTCORStorage_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORStorage_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORStorage_Private.h; sourceTree = ""; }; + CB211419F418229FA95278C411875D55 /* FChildEventRegistration.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FChildEventRegistration.m; path = Firebase/Database/Core/View/FChildEventRegistration.m; sourceTree = ""; }; + CB49879889C49984CF1E9264CD820068 /* Pods-PediatricPancreas_Storyboard-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PediatricPancreas_Storyboard-umbrella.h"; sourceTree = ""; }; + CB9C8BA79F404A632E12BFD15164FFE0 /* FIRInstanceIDTokenStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenStore.h; path = Firebase/InstanceID/FIRInstanceIDTokenStore.h; sourceTree = ""; }; + CC0DCC8D797EF0765CF6FB77E762DA91 /* FirebaseStorage-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseStorage-umbrella.h"; sourceTree = ""; }; + CC4A4BAB38692F24392EAFB5C9645180 /* FNextPushId.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FNextPushId.h; path = Firebase/Database/Utilities/FNextPushId.h; sourceTree = ""; }; + CD0EFB5FD41F0F3B6F7CA637FEE7CD77 /* FIRInstanceIDConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDConstants.m; path = Firebase/InstanceID/FIRInstanceIDConstants.m; sourceTree = ""; }; + CD8D40B6AFCF5F6C29F50AB149BF8282 /* FTupleStringNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleStringNode.m; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.m; sourceTree = ""; }; + CDA172D5E1D03619ED29BD779DB0ABCB /* FViewProcessorResult.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FViewProcessorResult.h; path = Firebase/Database/FViewProcessorResult.h; sourceTree = ""; }; + CDAF96ED50A683983650B65E4986A78E /* FPathIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPathIndex.m; path = Firebase/Database/FPathIndex.m; sourceTree = ""; }; + CDB4A8DA2BE9BFC90E5444E2A185301F /* FirebaseDatabase-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseDatabase-dummy.m"; sourceTree = ""; }; + CDEDD664B4945B5C3FFCC439EF5E91F7 /* FAuthTokenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FAuthTokenProvider.h; path = Firebase/Database/Login/FAuthTokenProvider.h; sourceTree = ""; }; + CDF1E1AB955E1D60F59D3B21F43389D6 /* FBLPromise+Then.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Then.m"; path = "Sources/FBLPromises/FBLPromise+Then.m"; sourceTree = ""; }; + CE14B460E98E60C8B07474C59D604D04 /* table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table.h; path = include/leveldb/table.h; sourceTree = ""; }; + CED26793E5FAE2551262829D529B1C2C /* GoogleUtilities-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleUtilities-Info.plist"; sourceTree = ""; }; + CF1CF114DF0F9CB07BF12F9C39F293E8 /* env_windows_test_helper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = env_windows_test_helper.h; path = util/env_windows_test_helper.h; sourceTree = ""; }; + CF567AE7E57310AE4A3C5DEA9C1FA082 /* FIRInstanceID+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceID+Private.h"; path = "Firebase/InstanceID/Private/FIRInstanceID+Private.h"; sourceTree = ""; }; + CF854CBC1924CB4762773A59FA06AAD6 /* GULLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULLogger.m; path = GoogleUtilities/Logger/GULLogger.m; sourceTree = ""; }; + CFE16650F6104B6F46B1EF91CE0FE364 /* FIRInstallationsItem+RegisterInstallationAPI.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FIRInstallationsItem+RegisterInstallationAPI.m"; path = "FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsItem+RegisterInstallationAPI.m"; sourceTree = ""; }; + D02507890F4001343580522441E85F51 /* write_batch.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = write_batch.cc; path = db/write_batch.cc; sourceTree = ""; }; + D03D9478B9C4950F5892831FA40A6F85 /* FListenComplete.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenComplete.h; path = Firebase/Database/FListenComplete.h; sourceTree = ""; }; + D0899F5BE9309740C647BE99B3BD7C59 /* GULReachabilityChecker.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GULReachabilityChecker.m; path = GoogleUtilities/Reachability/GULReachabilityChecker.m; sourceTree = ""; }; + D0CFD980F55BDA288F9F5F389065BCEB /* table_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = table_builder.h; path = include/leveldb/table_builder.h; sourceTree = ""; }; + D0DFD8426C0E3D2B694A39A96102CAE8 /* merger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = merger.h; path = table/merger.h; sourceTree = ""; }; + D0F4533B0FF71752214FFD4B62FF2878 /* FEvent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEvent.h; path = Firebase/Database/Core/View/FEvent.h; sourceTree = ""; }; + D1067267D7E7186772FB61C1FD41B054 /* GULNSData+zlib.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "GULNSData+zlib.h"; path = "GoogleUtilities/NSData+zlib/GULNSData+zlib.h"; sourceTree = ""; }; + D1341BB202306F13B00265AF86B8F877 /* FTransformedEnumerator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTransformedEnumerator.h; path = Firebase/Database/FTransformedEnumerator.h; sourceTree = ""; }; + D15D6F80E8028925AB24321AFD3ADB9D /* GDTCORAssert.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORAssert.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORAssert.h; sourceTree = ""; }; + D17245470BF0B46FF5A077C52AFD2803 /* NSError+FIRInstanceID.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSError+FIRInstanceID.m"; path = "Firebase/InstanceID/NSError+FIRInstanceID.m"; sourceTree = ""; }; + D1784750A2945CB885B1E0E6B9FD4D8E /* FOperationSource.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FOperationSource.h; path = Firebase/Database/Core/Operation/FOperationSource.h; sourceTree = ""; }; + D1EC4B9C46DFC905A56E0EB7306005D6 /* FIRComponent.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRComponent.h; path = FirebaseCore/Sources/Private/FIRComponent.h; sourceTree = ""; }; + D30A603A1AF1B8113D6B28B35BB1685C /* FIRDependency.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRDependency.m; path = FirebaseCore/Sources/FIRDependency.m; sourceTree = ""; }; + D3540C0CCBE5B51413625FE4BE262F06 /* FTupleTSN.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleTSN.h; path = Firebase/Database/Utilities/Tuples/FTupleTSN.h; sourceTree = ""; }; + D35AA5CCE687873A9CF17FDAF81BCC49 /* FPersistentConnection.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistentConnection.m; path = Firebase/Database/Core/FPersistentConnection.m; sourceTree = ""; }; + D3C3D69913967F6EE53380D4DF1BAAC3 /* FIRAppInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRAppInternal.h; path = FirebaseCore/Sources/Private/FIRAppInternal.h; sourceTree = ""; }; + D448C9B8697D1412FE36F767443E3199 /* GDTCORRegistrar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORRegistrar.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORRegistrar.m; sourceTree = ""; }; + D4F7B7D12CD2AB5F4DA44ADE285B89A3 /* FBLPromise+Async.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Async.h"; path = "Sources/FBLPromises/include/FBLPromise+Async.h"; sourceTree = ""; }; + D5E4EF988C712EDDFC300B001F7A0C7E /* FSparseSnapshotTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSparseSnapshotTree.h; path = Firebase/Database/Core/FSparseSnapshotTree.h; sourceTree = ""; }; + D628266F3DD667493EE2D5198C86BD0A /* FBLPromise+Reduce.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Reduce.h"; path = "Sources/FBLPromises/include/FBLPromise+Reduce.h"; sourceTree = ""; }; + D68CD9DCDB8B776D07D3EE629559983C /* FQuerySpec.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FQuerySpec.h; path = Firebase/Database/Core/FQuerySpec.h; sourceTree = ""; }; + D6F6607EDEEF1D6596A32CF0CBD0511A /* FViewProcessor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessor.m; path = Firebase/Database/FViewProcessor.m; sourceTree = ""; }; + D752406CBEEC7D0ADECA246969C4CF9D /* FConstants.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FConstants.m; path = Firebase/Database/Constants/FConstants.m; sourceTree = ""; }; + D75E77BA956ACEBBA0AF6BE30433A511 /* FImmutableTree.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableTree.m; path = Firebase/Database/Core/Utilities/FImmutableTree.m; sourceTree = ""; }; + D760272F98CD0831968339D53400681F /* FBLPromise+Async.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Async.m"; path = "Sources/FBLPromises/FBLPromise+Async.m"; sourceTree = ""; }; + D8061BD1CFDE7004EC0A4E0E19DCF6DC /* block_builder.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = block_builder.cc; path = table/block_builder.cc; sourceTree = ""; }; + D8E569D8C956BCCC66778E7660040E4E /* FirebaseStorage-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FirebaseStorage-dummy.m"; sourceTree = ""; }; + D90E6343DA880305944FEEC32E0536F5 /* FIRInstanceIDDefines.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDDefines.h; path = Firebase/InstanceID/FIRInstanceIDDefines.h; sourceTree = ""; }; + D9FA396FC4735E76B98DBFA4F74A73EF /* FCancelEvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FCancelEvent.m; path = Firebase/Database/Core/View/FCancelEvent.m; sourceTree = ""; }; + DAD004FBD9D742F267D2146C5F8D4D6A /* FirebaseDatabase.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseDatabase.xcconfig; sourceTree = ""; }; + DADF937F52289F4BDB16AE7DB822B058 /* FRepoInfo.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FRepoInfo.m; path = Firebase/Database/Core/FRepoInfo.m; sourceTree = ""; }; + DB395C56E1B48FBF6BDD2F3219DB0F5F /* FLLRBEmptyNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBEmptyNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBEmptyNode.m; sourceTree = ""; }; + DB7C2097612DD516A996C265A7EBDBA4 /* FCompoundHash.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundHash.h; path = Firebase/Database/Core/FCompoundHash.h; sourceTree = ""; }; + DBC613BFA3150CBAC4A2F3088A3496AB /* FIRInstallationsLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsLogger.h; path = FirebaseInstallations/Source/Library/FIRInstallationsLogger.h; sourceTree = ""; }; + DCE0EA688C9DF641CB79FF48F8739F46 /* FImmutableSortedDictionary.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FImmutableSortedDictionary.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FImmutableSortedDictionary.m; sourceTree = ""; }; + DD0768EA430D4B40783B1367C205D0E6 /* FIRInstanceIDCheckinPreferences+Internal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FIRInstanceIDCheckinPreferences+Internal.h"; path = "Firebase/InstanceID/FIRInstanceIDCheckinPreferences+Internal.h"; sourceTree = ""; }; + DD161D56636E063DF147582966B2705A /* FPriorityIndex.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPriorityIndex.m; path = Firebase/Database/FPriorityIndex.m; sourceTree = ""; }; + DD1AC890E27B00503F3CF6EE90A68C0E /* filter_block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = filter_block.h; path = table/filter_block.h; sourceTree = ""; }; + DD27A6E60F01AA15B88C57ADEE40B496 /* FIRStorageDeleteTask.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStorageDeleteTask.m; path = FirebaseStorage/Sources/FIRStorageDeleteTask.m; sourceTree = ""; }; + DD9AD7328301C7C2428C3398259925F8 /* env_posix.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = env_posix.cc; path = util/env_posix.cc; sourceTree = ""; }; + DE429484969950B4A6B5CE157A9B0853 /* GULMutableDictionary.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULMutableDictionary.h; path = GoogleUtilities/Network/Private/GULMutableDictionary.h; sourceTree = ""; }; + DF082C74F4DA2DEAC965BC29903B79AC /* memtable.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = memtable.cc; path = db/memtable.cc; sourceTree = ""; }; + DF087165A75F7E60174E3AAB4D5101F7 /* GDTCOREvent.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCOREvent.m; path = GoogleDataTransport/GDTCORLibrary/GDTCOREvent.m; sourceTree = ""; }; + DFF58064766E5A66920C1C0D4C244C58 /* FBLPromise+Any.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Any.m"; path = "Sources/FBLPromises/FBLPromise+Any.m"; sourceTree = ""; }; + E04256A559431B024EAFE17349932DB7 /* testutil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = testutil.h; path = util/testutil.h; sourceTree = ""; }; + E05235154C224436E6591861CD028C05 /* format.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = format.h; path = table/format.h; sourceTree = ""; }; + E0A31444EC9783637FF1BF0E9FAAF92B /* FIRInstallationsSingleOperationPromiseCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsSingleOperationPromiseCache.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsSingleOperationPromiseCache.h; sourceTree = ""; }; + E11E2FAA9EC9301A1722BBBF7781DBE9 /* FWriteTree.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FWriteTree.h; path = Firebase/Database/Core/FWriteTree.h; sourceTree = ""; }; + E147ED0EDA24CB6101C7523658C4287B /* GULNetwork.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULNetwork.h; path = GoogleUtilities/Network/Private/GULNetwork.h; sourceTree = ""; }; + E14A19143EB768AC61D16C115E81F4D0 /* GDTCCTCompressionHelper.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCCTCompressionHelper.m; path = GoogleDataTransportCCTSupport/GDTCCTLibrary/GDTCCTCompressionHelper.m; sourceTree = ""; }; + E193069FA536F860D51FA8C5BE5EC30B /* FListenProvider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FListenProvider.h; path = Firebase/Database/Core/FListenProvider.h; sourceTree = ""; }; + E1D04018157FF78C2C0FE18C2BBFF9F9 /* GULLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GULLogger.h; path = GoogleUtilities/Logger/Private/GULLogger.h; sourceTree = ""; }; + E238A56E9E62DC870959BDB148BFCE6C /* FIRInstanceIDCombinedHandler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDCombinedHandler.h; path = Firebase/InstanceID/FIRInstanceIDCombinedHandler.h; sourceTree = ""; }; + E26FDD1CFCD18864203B9242BEB1EBF1 /* coding.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = coding.cc; path = util/coding.cc; sourceTree = ""; }; + E27C12152E295AE51F1462B3956ADF9A /* FIRApp.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRApp.m; path = FirebaseCore/Sources/FIRApp.m; sourceTree = ""; }; + E27C8AA3E91D56F81055B51152E93C5C /* FBLPromise.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FBLPromise.m; path = Sources/FBLPromises/FBLPromise.m; sourceTree = ""; }; + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FirebaseCore.framework; path = FirebaseCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2D22F3C8DC79314E4327FF9F03407E5 /* FIRInstallationsStore.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStore.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStore.h; sourceTree = ""; }; + E2E98869B1CB0FA25A72A5EFF1D02816 /* FTupleObjects.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTupleObjects.m; path = Firebase/Database/Utilities/Tuples/FTupleObjects.m; sourceTree = ""; }; + E3246B27D9A917C54052A78F54307238 /* FIRStorageTokenAuthorizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTokenAuthorizer.h; path = FirebaseStorage/Sources/FIRStorageTokenAuthorizer.h; sourceTree = ""; }; + E3D2F5A5F496F3111AF778C077AEB889 /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PediatricPancreas_Storyboard.debug.xcconfig"; sourceTree = ""; }; + E403FD09A6EDAA770ACD23EB7E750605 /* FIRInstanceIDUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDUtilities.m; path = Firebase/InstanceID/FIRInstanceIDUtilities.m; sourceTree = ""; }; + E4828C39CC6E1566EEC841FEA1495EB9 /* FCompoundWrite.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FCompoundWrite.h; path = Firebase/Database/Snapshot/FCompoundWrite.h; sourceTree = ""; }; + E49EBE95EE5226D43810CC59CC54EB44 /* FEventGenerator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FEventGenerator.m; path = Firebase/Database/FEventGenerator.m; sourceTree = ""; }; + E5559932E650E15482A1C77AF1D52CE5 /* nanopb.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = nanopb.modulemap; sourceTree = ""; }; + E67C1D1A48982697C198AB692680D803 /* FIRStorageGetMetadataTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageGetMetadataTask.h; path = FirebaseStorage/Sources/FIRStorageGetMetadataTask.h; sourceTree = ""; }; + E80ADBF36FB8C56A60C984778F7D9720 /* GoogleDataTransportCCTSupport-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "GoogleDataTransportCCTSupport-Info.plist"; sourceTree = ""; }; + E826F61C6B288FEEEBA15A3388C37EBE /* iterator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator.h; path = include/leveldb/iterator.h; sourceTree = ""; }; + E936E8C2B50044D3205DF51E9E9007DD /* FIRInstallationsHTTPError.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstallationsHTTPError.m; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsHTTPError.m; sourceTree = ""; }; + E99B3791B40D702BA7499A2791FF41FB /* FClock.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FClock.m; path = Firebase/Database/FClock.m; sourceTree = ""; }; + E9A6FBFCCF1F2E924CB0619DD122C7C4 /* fbase64.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = fbase64.h; path = Firebase/Database/third_party/SocketRocket/fbase64.h; sourceTree = ""; }; + E9BBCC3054D48A4CD2B5D5D10A50E38C /* FirebaseDatabase-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FirebaseDatabase-umbrella.h"; sourceTree = ""; }; + EA7BFFCAAF832433E1DCCF3E39E54D6E /* table.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = table.cc; path = table/table.cc; sourceTree = ""; }; + EABF0AF368631BBA0EBC6315F6B4144E /* FBLPromise.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromise.h; path = Sources/FBLPromises/include/FBLPromise.h; sourceTree = ""; }; + EACB33C10F6F9E2BFAD2353C454F9AE7 /* FIRStorageTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageTask.h; path = FirebaseStorage/Sources/Public/FIRStorageTask.h; sourceTree = ""; }; + EB66CFB1B78584AFE3578475D2046904 /* FPathIndex.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FPathIndex.h; path = Firebase/Database/FPathIndex.h; sourceTree = ""; }; + EC150F4FD984963E187F5A3AA42C98C9 /* firebasecore.nanopb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = firebasecore.nanopb.h; path = Firebase/CoreDiagnostics/FIRCDLibrary/Protogen/nanopb/firebasecore.nanopb.h; sourceTree = ""; }; + EC38A8C53E78ED42481B50F3D1DA08BB /* FStorageEngine.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStorageEngine.h; path = Firebase/Database/Persistence/FStorageEngine.h; sourceTree = ""; }; + EC472A7E11E0AF865D19CFCAF9A72A0E /* FRangedFilter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FRangedFilter.h; path = Firebase/Database/FRangedFilter.h; sourceTree = ""; }; + ECACF7849D7CAC8D64FB070D76863651 /* FBLPromisePrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FBLPromisePrivate.h; path = Sources/FBLPromises/include/FBLPromisePrivate.h; sourceTree = ""; }; + ECE11C4938A2B72ABEBFEE62ED66BF8F /* FBLPromise+Validate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Validate.m"; path = "Sources/FBLPromises/FBLPromise+Validate.m"; sourceTree = ""; }; + ED48C66680CD29C4D2F5DE39F29CAFFB /* FirebaseCoreDiagnostics.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FirebaseCoreDiagnostics.xcconfig; sourceTree = ""; }; + ED7E3BD4AABE613AC52785257A0E89E6 /* FIRInstanceIDCheckinService.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRInstanceIDCheckinService.m; path = Firebase/InstanceID/FIRInstanceIDCheckinService.m; sourceTree = ""; }; + EDB960BBC8F94DEF008EF48F34DC8AE6 /* GTMSessionFetcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcher.m; path = Source/GTMSessionFetcher.m; sourceTree = ""; }; + EDE4E8B5C0D67DC87A1CD2751C80E135 /* FIndexedFilter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIndexedFilter.m; path = Firebase/Database/Core/View/Filter/FIndexedFilter.m; sourceTree = ""; }; + EE496FABD67CAAF80A37A368BA2DFF3D /* GTMSessionFetcherService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GTMSessionFetcherService.h; path = Source/GTMSessionFetcherService.h; sourceTree = ""; }; + EE8661EE9163CB9D35ADAEA97516FE8B /* c.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = c.cc; path = db/c.cc; sourceTree = ""; }; + EEB94A073C78837518C58FDBB49EE385 /* FIRInstanceIDTokenDeleteOperation.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenDeleteOperation.h; path = Firebase/InstanceID/FIRInstanceIDTokenDeleteOperation.h; sourceTree = ""; }; + EF027EB6EC10790B2A23AC612C1FB6DA /* FIRStoragePath.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FIRStoragePath.m; path = FirebaseStorage/Sources/FIRStoragePath.m; sourceTree = ""; }; + EF4C1A8DA8015C4C9565AA9AF3BBF375 /* FViewProcessorResult.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FViewProcessorResult.m; path = Firebase/Database/FViewProcessorResult.m; sourceTree = ""; }; + EF6B5B884808EE33F3AE364E1A8D7058 /* GDTCORDataFuture.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORDataFuture.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORDataFuture.h; sourceTree = ""; }; + EF8F20248E90A517FA3C288D99992F53 /* GDTCORPlatform.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORPlatform.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORPlatform.h; sourceTree = ""; }; + EFDAB92669C9F072D980DC72D47ADE41 /* FTupleOnDisconnect.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleOnDisconnect.h; path = Firebase/Database/Utilities/Tuples/FTupleOnDisconnect.h; sourceTree = ""; }; + F03192D6CD3300140B77BF7EA1CCA565 /* FIRConfiguration.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRConfiguration.h; path = FirebaseCore/Sources/Public/FIRConfiguration.h; sourceTree = ""; }; + F1E35600A76731626B0A9B4A65F4FECD /* FIRInstanceIDTokenManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDTokenManager.h; path = Firebase/InstanceID/FIRInstanceIDTokenManager.h; sourceTree = ""; }; + F20EACCD4C59A1512EEA6F07603AC103 /* GoogleDataTransport-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GoogleDataTransport-dummy.m"; sourceTree = ""; }; + F22F1DCA0BFD189772156B0071867DE9 /* GDTCORConsoleLogger.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORConsoleLogger.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORConsoleLogger.m; sourceTree = ""; }; + F27AD869EA4F65CDB13697DDE36D24E0 /* FLLRBValueNode.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FLLRBValueNode.m; path = Firebase/Database/third_party/FImmutableSortedDictionary/FImmutableSortedDictionary/FLLRBValueNode.m; sourceTree = ""; }; + F2AC7B9BC9D8655DE104DF06635B6F26 /* FPersistenceManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FPersistenceManager.m; path = Firebase/Database/Persistence/FPersistenceManager.m; sourceTree = ""; }; + F2CC73872DB886E14A2366F2B113982A /* log_reader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = log_reader.h; path = db/log_reader.h; sourceTree = ""; }; + F2F1F22644685D1B297E9BC3110FF0A3 /* FEventRaiser.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FEventRaiser.h; path = Firebase/Database/Core/View/FEventRaiser.h; sourceTree = ""; }; + F318D95F186F44696E86DD96E1D6625A /* port.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port.h; path = port/port.h; sourceTree = ""; }; + F3D3E03AB5F3B1F5C79EBFDB2B3E5B0D /* leveldb-library-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "leveldb-library-dummy.m"; sourceTree = ""; }; + F3DA6D82523EE796EDDBDF7266EBEF6D /* PromisesObjC.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PromisesObjC.modulemap; sourceTree = ""; }; + F3E0784D73B1A725557C578A0E0DE9F1 /* GDTCORReachability.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GDTCORReachability.m; path = GoogleDataTransport/GDTCORLibrary/GDTCORReachability.m; sourceTree = ""; }; + F3E27E74E05C98E0B5F68063DCB85240 /* snapshot.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = snapshot.h; path = db/snapshot.h; sourceTree = ""; }; + F3F1CC7A848EE5F4DD8AFD48F48C16C6 /* FIRStorageUploadTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUploadTask.h; path = FirebaseStorage/Sources/Public/FIRStorageUploadTask.h; sourceTree = ""; }; + F41ABEC6B1F1039CE216732C698269B2 /* GDTCORLifecycle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORLifecycle.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORLifecycle.h; sourceTree = ""; }; + F45D4E33349EF35597144185678B05C5 /* memtable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = memtable.h; path = db/memtable.h; sourceTree = ""; }; + F49FDE10DC964A182BD8D6BF72E56F64 /* FIRInstallationsErrorUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsErrorUtil.h; path = FirebaseInstallations/Source/Library/Errors/FIRInstallationsErrorUtil.h; sourceTree = ""; }; + F54CE05621F4425787E29C0CEBF58EC3 /* GTMSessionFetcher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "GTMSessionFetcher-dummy.m"; sourceTree = ""; }; + F5B4E47D4F948AB4781BE06654B0B1A0 /* iterator_wrapper.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = iterator_wrapper.h; path = table/iterator_wrapper.h; sourceTree = ""; }; + F5C235D00DEB88A19CFC0216A0D1148C /* APLevelDB.mm */ = {isa = PBXFileReference; includeInIndex = 1; name = APLevelDB.mm; path = "Firebase/Database/third_party/Wrap-leveldb/APLevelDB.mm"; sourceTree = ""; }; + F5D1434B5914AC5EC2EFAC3B3AFA8B3A /* GTMSessionFetcherLogging.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = GTMSessionFetcherLogging.m; path = Source/GTMSessionFetcherLogging.m; sourceTree = ""; }; + F5E0E11BE35D93380875787C9803A6CC /* FirebaseDatabase.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseDatabase.h; path = Firebase/Database/Public/FirebaseDatabase.h; sourceTree = ""; }; + F69FC4745356C9F9EFA3FC172441B8D1 /* FIRStorageListTask.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageListTask.h; path = FirebaseStorage/Sources/FIRStorageListTask.h; sourceTree = ""; }; + F74357951D0E0FCFAB5F7DE7D9B10AB9 /* FBLPromise+Retry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Retry.h"; path = "Sources/FBLPromises/include/FBLPromise+Retry.h"; sourceTree = ""; }; + F75F9105694B168C0EFBBA4713124CC5 /* FIRInstallationsIDController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsIDController.h; path = FirebaseInstallations/Source/Library/InstallationsIDController/FIRInstallationsIDController.h; sourceTree = ""; }; + F77D63E559DFC813F4B3AAD2075AB8B0 /* FBLPromise+Delay.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "FBLPromise+Delay.m"; path = "Sources/FBLPromises/FBLPromise+Delay.m"; sourceTree = ""; }; + F7C0D5DD8E1D50B533B78792246BB6BC /* options.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = options.cc; path = util/options.cc; sourceTree = ""; }; + F80CF052FA0620A9B8D80C1A367E7F5E /* FSRWebSocket.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FSRWebSocket.h; path = Firebase/Database/third_party/SocketRocket/FSRWebSocket.h; sourceTree = ""; }; + F8EBCF41CD843B76AEFF4A01DF812CF8 /* FIRInstanceIDConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstanceIDConstants.h; path = Firebase/InstanceID/FIRInstanceIDConstants.h; sourceTree = ""; }; + F9555000E6E1599039D9EBA4786F57AE /* GDTCORConsoleLogger.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORConsoleLogger.h; path = GoogleDataTransport/GDTCORLibrary/Public/GDTCORConsoleLogger.h; sourceTree = ""; }; + F955BEF204ED310BC614813D9D710DC3 /* builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = builder.h; path = db/builder.h; sourceTree = ""; }; + F9896C33DDA84C01B16BAFBA8D05642A /* FIRInstallationsStoredAuthToken.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsStoredAuthToken.h; path = FirebaseInstallations/Source/Library/InstallationsStore/FIRInstallationsStoredAuthToken.h; sourceTree = ""; }; + FA66E374375C4A12B0A38918F5DB9B4B /* FTuplePathValue.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FTuplePathValue.m; path = Firebase/Database/Utilities/Tuples/FTuplePathValue.m; sourceTree = ""; }; + FA7326DD6B394923A78CA1BBC5D827E2 /* FIRInstallationsAPIService.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRInstallationsAPIService.h; path = FirebaseInstallations/Source/Library/InstallationsAPI/FIRInstallationsAPIService.h; sourceTree = ""; }; + FB842126904767A67B91205B38C304F5 /* db_iter.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = db_iter.cc; path = db/db_iter.cc; sourceTree = ""; }; + FBCE9ABE7022B4327517A73BE43D2C25 /* pb_decode.c */ = {isa = PBXFileReference; includeInIndex = 1; path = pb_decode.c; sourceTree = ""; }; + FBFD83C5D86D93B245CD240C86246263 /* FBLPromise+Race.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "FBLPromise+Race.h"; path = "Sources/FBLPromises/include/FBLPromise+Race.h"; sourceTree = ""; }; + FC18ABE2366295F29168F13229AD4B6F /* FirebaseInstallations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FirebaseInstallations.h; path = FirebaseInstallations/Source/Library/Public/FirebaseInstallations.h; sourceTree = ""; }; + FC70AFB7FD9A61A5D9A481E9F24F1AD3 /* FNextPushId.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = FNextPushId.m; path = Firebase/Database/Utilities/FNextPushId.m; sourceTree = ""; }; + FD8DD3CBCFCD6D546467D83131DB9AAF /* block.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = block.h; path = table/block.h; sourceTree = ""; }; + FD8E96626EC223FFE031515C273E16FA /* FTupleNodePath.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleNodePath.h; path = Firebase/Database/Utilities/Tuples/FTupleNodePath.h; sourceTree = ""; }; + FDACA0EDDA8DC12E586A89B7A92044CB /* FIRBundleUtil.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRBundleUtil.h; path = FirebaseCore/Sources/FIRBundleUtil.h; sourceTree = ""; }; + FDD7328DA6F01C55D0E675A37C0976EC /* GDTCORRegistrar_Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORRegistrar_Private.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORRegistrar_Private.h; sourceTree = ""; }; + FDE03C5490F34BDF665841D50ADB48A5 /* GDTCORUploadCoordinator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = GDTCORUploadCoordinator.h; path = GoogleDataTransport/GDTCORLibrary/Private/GDTCORUploadCoordinator.h; sourceTree = ""; }; + FE6CE57F830C31B2D2A7D544113C28CC /* port_example.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = port_example.h; path = port/port_example.h; sourceTree = ""; }; + FF0A44A5C1649AF3610C4A16F8CEAA7B /* FIRStorageUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FIRStorageUtils.h; path = FirebaseStorage/Sources/FIRStorageUtils.h; sourceTree = ""; }; + FFBEFCD078D6A76273D277223110B3D5 /* FTupleStringNode.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FTupleStringNode.h; path = Firebase/Database/Utilities/Tuples/FTupleStringNode.h; sourceTree = ""; }; + FFC87D297C3C3484EBF939B420C4EBAD /* FStringUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = FStringUtilities.h; path = Firebase/Database/Utilities/FStringUtilities.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2D8606A32A41CB40AAFFBCBCD1696310 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 98DA22ECB841196BE5E2314435244D65 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 38940F714A6BBC8ADACEC78C9E0F6C08 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FDECC79C340C9366B4458A31A783E7CD /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5DF37E3EF94989DF8CAE4076F21381EE /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8086747B000673FE85AE2CDC9BCF9F97 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6DFC5CD58BD6F472325388D88D9BEC06 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E0BAF15488BBDC150E9189768245B0FD /* Foundation.framework in Frameworks */, + 5F4B5AFB5A71275C5A6D53829D36C6C0 /* Security.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7C13B57579C7CE08BA7978B2260D8727 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7595B8AF683D138FF6D5D7706B67971C /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 802E7B243B377BCEF43384753EF1BD6F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E66E899B714EC0D889376587705AA280 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 912C1C624B98DDAC060EB8D5447D68DA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 89A2C51FCAE3567F5894E25E0ABD3C05 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9BED85A766DD5DD199782CDD1CB12F2D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2B26CAD0907DB48C814785DC142CB23F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C6A766CB759F8982F53D2B59F8BFF07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B56960273A4E32A0FA480C50AD403309 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AAA4C7647506233567DF9FF0A75968D0 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 51F66A667C160C6F4067FAB0C2475C74 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B90C2DC39BCD6CF494C7B57BF01D5501 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8EBE9FAEA74066BBF5AE478B7FD93FC0 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CBFE6A050EBB5B87E7ED88AD95397203 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F1AE420BF3679263627A8331203D0328 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB74152AABA217349F58AFA22CF0A690 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B098D41B81126938688435CFF517F0CC /* Foundation.framework in Frameworks */, + 38BB0158ED998278F61583309B1512A4 /* Security.framework in Frameworks */, + BEE35C518925421AA701E260DC70824D /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ECA9D30190CFBAD261C97DB31D37A303 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F860CF248BB1315D65608641EA6E457A /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 017AE26135AE1DDB6F97614CBAFF8735 /* decode */ = { + isa = PBXGroup; + children = ( + ); + name = decode; + sourceTree = ""; + }; + 02B093BADFB5EC801C0A441E2CA6A0E7 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 116C8F94BB7CAD502B144C358A356C28 /* Pods-PediatricPancreas_Storyboard */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0D606D6935B2A17CA59AEFF7E234E6FD /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + 0D606D6935B2A17CA59AEFF7E234E6FD /* iOS */ = { + isa = PBXGroup; + children = ( + 43CCB64591E5193571220AB99A29E8AD /* Foundation.framework */, + 3D345AA1CA7BA285C593B4CB9AF8A501 /* Security.framework */, + 3477DD5B6202AED934620CCA7D1D6879 /* SystemConfiguration.framework */, + ); + name = iOS; + sourceTree = ""; + }; + 0DFB3F04D7C7710F6DF6EDB73BCA9BD3 /* Support Files */ = { + isa = PBXGroup; + children = ( + 921DB4627BC7133390AD63BC6F55EB53 /* FirebaseStorage.modulemap */, + 651D975CFB0F58EC635DB69073FC0D6B /* FirebaseStorage.xcconfig */, + D8E569D8C956BCCC66778E7660040E4E /* FirebaseStorage-dummy.m */, + A677A20A2384930F4EDAC77AD596B992 /* FirebaseStorage-Info.plist */, + CC0DCC8D797EF0765CF6FB77E762DA91 /* FirebaseStorage-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseStorage"; + sourceTree = ""; + }; + 10FF548947B9B86C759B2EBF67BB7354 /* Support Files */ = { + isa = PBXGroup; + children = ( + 21FFE28A3BB0A1F707CF7F6BCE2EA3F9 /* FirebaseInstanceID.modulemap */, + 3E141DEE77985B8019CF800305A79116 /* FirebaseInstanceID.xcconfig */, + 850CBF344E1BD1CF84B5206F0E4F3AA6 /* FirebaseInstanceID-dummy.m */, + 5895FD073A61E38C37025CFF0C5467AD /* FirebaseInstanceID-Info.plist */, + 9ADC2802276930B11A1968FD14EB6362 /* FirebaseInstanceID-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstanceID"; + sourceTree = ""; + }; + 116C8F94BB7CAD502B144C358A356C28 /* Pods-PediatricPancreas_Storyboard */ = { + isa = PBXGroup; + children = ( + C9ABC90AE3F25AE15E777A3E6803A97F /* Pods-PediatricPancreas_Storyboard.modulemap */, + 234930C333672879FDFADB107116635A /* Pods-PediatricPancreas_Storyboard-acknowledgements.markdown */, + 65B8BFDE850B199A7E5D618376A6C00F /* Pods-PediatricPancreas_Storyboard-acknowledgements.plist */, + 5FA2D57AC7503BB3ECD9DDD080FF3536 /* Pods-PediatricPancreas_Storyboard-dummy.m */, + 09C3130C882910E48C5E81FFB4E257F1 /* Pods-PediatricPancreas_Storyboard-frameworks.sh */, + 6AEFD138EE7C9728145FFC7C5D91EB61 /* Pods-PediatricPancreas_Storyboard-Info.plist */, + CB49879889C49984CF1E9264CD820068 /* Pods-PediatricPancreas_Storyboard-umbrella.h */, + E3D2F5A5F496F3111AF778C077AEB889 /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */, + A86D7D56CD84812BBC2847B8B41BB88D /* Pods-PediatricPancreas_Storyboard.release.xcconfig */, + ); + name = "Pods-PediatricPancreas_Storyboard"; + path = "Target Support Files/Pods-PediatricPancreas_Storyboard"; + sourceTree = ""; + }; + 1CE9D0DD732124887B3B770DCCB8EAE0 /* Support Files */ = { + isa = PBXGroup; + children = ( + F3DA6D82523EE796EDDBDF7266EBEF6D /* PromisesObjC.modulemap */, + 915F579A059A8F18FF02F62D36B4F1BC /* PromisesObjC.xcconfig */, + BE42B997AA83C8CA9F70E16204BDC654 /* PromisesObjC-dummy.m */, + 3439DCCC83A1FA43A42F2B632AD4CAFE /* PromisesObjC-Info.plist */, + 288371F32354A7A2D02E6D211872D6C0 /* PromisesObjC-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/PromisesObjC"; + sourceTree = ""; + }; + 1E42463EC212B6057A6107A5A9542F70 /* Support Files */ = { + isa = PBXGroup; + children = ( + C37EA4AD27A51901CB827A1DEC06AC6D /* FirebaseInstallations.modulemap */, + 76C1FFB27224C9E18EA9AA2E0B897BC7 /* FirebaseInstallations.xcconfig */, + 933460CA2E165B422AB65FD22F461DC0 /* FirebaseInstallations-dummy.m */, + 808CF5532538521A7A0CBECF62C43FED /* FirebaseInstallations-Info.plist */, + 6E5B60F06DA7799B681DAF0B1D2005CE /* FirebaseInstallations-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseInstallations"; + sourceTree = ""; + }; + 222F606FF31B0F68939C4E7DF028D4FA /* Firebase */ = { + isa = PBXGroup; + children = ( + 41BF25D8A5BC107EFA362653260B45F8 /* CoreOnly */, + 8C8E0F7AD7C250B736114E2A77402F28 /* Support Files */, + ); + name = Firebase; + path = Firebase; + sourceTree = ""; + }; + 2B4BF5617AA5DB3FEF1605B7246DACA7 /* MethodSwizzler */ = { + isa = PBXGroup; + children = ( + AA7F761B656167D3B87EF50DE069B696 /* GULOriginalIMPConvenienceMacros.h */, + 16CE5915391DA812240B7E3D3EA23BB6 /* GULSwizzler.h */, + 99BE1790BA27F64B840314B5027E34B2 /* GULSwizzler.m */, + ); + name = MethodSwizzler; + sourceTree = ""; + }; + 367FEC5D6891FF7DE81223F96433AF5B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 15E0BCDFB63DB8313F394A34962DE91A /* GoogleAppMeasurement.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 409CD672C7AC9DCC91718049D2EF7D23 /* Environment */ = { + isa = PBXGroup; + children = ( + 107EEF2DDC74972CC27D7B59D733DE16 /* GULAppEnvironmentUtil.h */, + B0DA53538D50A020387AB115C11CE206 /* GULAppEnvironmentUtil.m */, + 2E03362CBA1953F1EE9640B25411BED8 /* GULHeartbeatDateStorage.h */, + 102030AB0E29D8723B187640A14759D9 /* GULHeartbeatDateStorage.m */, + 16D2CB4D08C7DF2EE66A293C0D99EFD0 /* GULSecureCoding.h */, + 5A7E1843FD613F018523298FB0DF7927 /* GULSecureCoding.m */, + ); + name = Environment; + sourceTree = ""; + }; + 41BF25D8A5BC107EFA362653260B45F8 /* CoreOnly */ = { + isa = PBXGroup; + children = ( + AEAA491E682EA0923D5EE202E2D60D08 /* Firebase.h */, + ); + name = CoreOnly; + sourceTree = ""; + }; + 424052ED612234D6E832E95175E11138 /* FirebaseCoreDiagnosticsInterop */ = { + isa = PBXGroup; + children = ( + AA0D45E1C53E134EDD9ED58E44506FDB /* FIRCoreDiagnosticsData.h */, + 254E203E550C89C08D3928C8E43B25F7 /* FIRCoreDiagnosticsInterop.h */, + 824ECEE0F4CF59E8F50699F163A86AFE /* Support Files */, + ); + name = FirebaseCoreDiagnosticsInterop; + path = FirebaseCoreDiagnosticsInterop; + sourceTree = ""; + }; + 430476B606F9BE625C3CE0AD0C38A83E /* GoogleDataTransport */ = { + isa = PBXGroup; + children = ( + D15D6F80E8028925AB24321AFD3ADB9D /* GDTCORAssert.h */, + 8357EDEAA0A8963A7A21EBFAC6DA743E /* GDTCORAssert.m */, + 85BDAD751CA36AAB6F83EFD5C027EA91 /* GDTCORClock.h */, + 9D5813664B48EEEECBD73FE4B6AF656E /* GDTCORClock.m */, + F9555000E6E1599039D9EBA4786F57AE /* GDTCORConsoleLogger.h */, + F22F1DCA0BFD189772156B0071867DE9 /* GDTCORConsoleLogger.m */, + EF6B5B884808EE33F3AE364E1A8D7058 /* GDTCORDataFuture.h */, + BFE3EAA708149B8146C731A7AC4FB682 /* GDTCORDataFuture.m */, + 1CECE9D2BE91CA5F856D1C62E06F7E40 /* GDTCOREvent.h */, + DF087165A75F7E60174E3AAB4D5101F7 /* GDTCOREvent.m */, + 986E76CDB36A58245C5FFB25DF53A794 /* GDTCOREvent_Private.h */, + 3C0AB9D4108F4576B594A1159BD62850 /* GDTCOREventDataObject.h */, + 3B5C7C088DAC8E08B4C0ABE1D9D7F187 /* GDTCOREventTransformer.h */, + F41ABEC6B1F1039CE216732C698269B2 /* GDTCORLifecycle.h */, + 844DBAFA06AA17E01947CC83D557C229 /* GDTCORLifecycle.m */, + EF8F20248E90A517FA3C288D99992F53 /* GDTCORPlatform.h */, + 6ACE358791743E000CFCB19614F5CE16 /* GDTCORPlatform.m */, + C7E966DF9D6827BA4FDAC1BF918F69E2 /* GDTCORPrioritizer.h */, + 0DD98E9DFFAF9630E85D5AA939CC6FE2 /* GDTCORReachability.h */, + F3E0784D73B1A725557C578A0E0DE9F1 /* GDTCORReachability.m */, + 66C7999CC47AE67D949C1766C0BF2CAA /* GDTCORReachability_Private.h */, + AE506B6FA93C8C128423247BFB7439C0 /* GDTCORRegistrar.h */, + D448C9B8697D1412FE36F767443E3199 /* GDTCORRegistrar.m */, + FDD7328DA6F01C55D0E675A37C0976EC /* GDTCORRegistrar_Private.h */, + 90D43FD412508EEDA57DF27A754BBC88 /* GDTCORStorage.h */, + 8B1E2BCB035B1D3DC3D62CBD00650324 /* GDTCORStorage.m */, + CAED39340F04B8544FC496CFCF1EADCC /* GDTCORStorage_Private.h */, + 2F04DA8747EA8BE73026D773DF27B3AD /* GDTCORStoredEvent.h */, + C9D62FF736B44971DF9091825EA70670 /* GDTCORStoredEvent.m */, + 4E37890FCB2C3ABF59FA19621429FEC8 /* GDTCORTargets.h */, + 4C11004830397FE020F6EDE9413D3CFC /* GDTCORTransformer.h */, + 68B8803604DCC5D6E7CD419A7B2933F5 /* GDTCORTransformer.m */, + 52395DE321F4785481C559231D4936A9 /* GDTCORTransformer_Private.h */, + 95AE095CF820AEDCF24899B9BF862975 /* GDTCORTransport.h */, + 97E3FCCAF2E02AF6ECBD79CFF27F1C32 /* GDTCORTransport.m */, + C15F1AE465F68C48C5F2AC5D6A1AD58B /* GDTCORTransport_Private.h */, + FDE03C5490F34BDF665841D50ADB48A5 /* GDTCORUploadCoordinator.h */, + 83CD465F0A45201ABBAE6485F83F43E8 /* GDTCORUploadCoordinator.m */, + 304BB26FD24F626815E78336619266C5 /* GDTCORUploader.h */, + A4E1EB8597FF3EC84853B45630CA42ED /* GDTCORUploadPackage.h */, + 875FED658B925BC28611FDB1B8858369 /* GDTCORUploadPackage.m */, + 0634A83F899FE66CAACB549A4DE98343 /* GDTCORUploadPackage_Private.h */, + 0A99DFD371A5473D820867DF4D748DEF /* GoogleDataTransport.h */, + CDB583DD5DD7478730DFA75754339E14 /* Support Files */, + ); + name = GoogleDataTransport; + path = GoogleDataTransport; + sourceTree = ""; + }; + 434A5C78A5FFF8AFE7AD2798CFE9ED8C /* Support Files */ = { + isa = PBXGroup; + children = ( + 6D00CFE10ED50E217A18222CFB918840 /* FirebaseCore.modulemap */, + AE725393C345416026E97A02D28712D4 /* FirebaseCore.xcconfig */, + 08F10222301531C836C3CE7358FAF158 /* FirebaseCore-dummy.m */, + 0DA7971DA1658D238157296A691E6CAD /* FirebaseCore-Info.plist */, + 81B7215BC7FAD9F6EA89A037D4450CE0 /* FirebaseCore-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCore"; + sourceTree = ""; + }; + 4A654C88D0B538BAEC30C66DB98A8BCC /* Support Files */ = { + isa = PBXGroup; + children = ( + 28C189D7C4A9807852DFBCFFFCBC5211 /* FirebaseCoreDiagnostics.modulemap */, + ED48C66680CD29C4D2F5DE39F29CAFFB /* FirebaseCoreDiagnostics.xcconfig */, + 9C6603077B3BAE9B69D097E3D89FE4D7 /* FirebaseCoreDiagnostics-dummy.m */, + A39BBE27DEE67B7711E6288FA3EAAE95 /* FirebaseCoreDiagnostics-Info.plist */, + 722C71C6D27A3037C21FC011B803AA74 /* FirebaseCoreDiagnostics-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCoreDiagnostics"; + sourceTree = ""; + }; + 4F671C0BAE75DCDB711D299CA7F6748E /* nanopb */ = { + isa = PBXGroup; + children = ( + 43C2DF7D088303A95D61EE4E40773F52 /* pb.h */, + B346E012CA98A38C8509220492705220 /* pb_common.c */, + 9BA5379813ED95F892512A874565DB18 /* pb_common.h */, + FBCE9ABE7022B4327517A73BE43D2C25 /* pb_decode.c */, + 15853D21D1AFFB8499F10A9CB08B835C /* pb_decode.h */, + 05873CB9F2FD43CA2C12872CBAF74522 /* pb_encode.c */, + 689A74FA4AD346552142D35E8DBF8BE5 /* pb_encode.h */, + 017AE26135AE1DDB6F97614CBAFF8735 /* decode */, + E9733B5E515550799F902178F9770353 /* encode */, + D4BF2EFA85A55C8C9F88177558486D49 /* Support Files */, + ); + name = nanopb; + path = nanopb; + sourceTree = ""; + }; + 606361156995095FE2DDD38255392E48 /* NSData+zlib */ = { + isa = PBXGroup; + children = ( + D1067267D7E7186772FB61C1FD41B054 /* GULNSData+zlib.h */, + AB743D0C97C93EEEAB0DB0FE278337E2 /* GULNSData+zlib.m */, + ); + name = "NSData+zlib"; + sourceTree = ""; + }; + 6374768777A7FB5EC6EEBC3FA7AF17EF /* FirebaseInstallations */ = { + isa = PBXGroup; + children = ( + FC18ABE2366295F29168F13229AD4B6F /* FirebaseInstallations.h */, + 59F63533E39055260C58815ACE106993 /* FIRInstallations.h */, + 788D52215E806B9AAF19263432A92BBD /* FIRInstallations.m */, + FA7326DD6B394923A78CA1BBC5D827E2 /* FIRInstallationsAPIService.h */, + 05E19944C7BC20A465DA3DE28DB49B0E /* FIRInstallationsAPIService.m */, + 8B2BC02CB066E06F4B11FD2D5F9B8573 /* FIRInstallationsAuthTokenResult.h */, + A6B7B883FE64676C0CD7B665C2CAB402 /* FIRInstallationsAuthTokenResult.m */, + 7661DE9A527D6B176752AAFDF7C1E0A4 /* FIRInstallationsAuthTokenResultInternal.h */, + 5327239BCECD082DD39C0F036B522DF7 /* FIRInstallationsErrors.h */, + F49FDE10DC964A182BD8D6BF72E56F64 /* FIRInstallationsErrorUtil.h */, + 5AAAC42AF05E13F7344E5CF861CA1945 /* FIRInstallationsErrorUtil.m */, + B62D960DC80DC12623B220EA85CD926B /* FIRInstallationsHTTPError.h */, + E936E8C2B50044D3205DF51E9E9007DD /* FIRInstallationsHTTPError.m */, + F75F9105694B168C0EFBBA4713124CC5 /* FIRInstallationsIDController.h */, + B0DB1D9E61CF269224355B759C08644D /* FIRInstallationsIDController.m */, + 93FC2872D62DB58E74049962B6F9FC53 /* FIRInstallationsIIDStore.h */, + 7FA6CE7B8DD64D3E66580F5383EA2133 /* FIRInstallationsIIDStore.m */, + 7E65C6252D7B9C6219B60EF273C7BD3F /* FIRInstallationsIIDTokenStore.h */, + 03937960479CC5DA69B2F6CE80C880A3 /* FIRInstallationsIIDTokenStore.m */, + 50EEA6FAE9C760AB7F5E302B5284F1CF /* FIRInstallationsItem.h */, + 3AE4E4E587A9E312162D01C3498442C1 /* FIRInstallationsItem.m */, + C38C2F78048851357831E011AF92F876 /* FIRInstallationsItem+RegisterInstallationAPI.h */, + CFE16650F6104B6F46B1EF91CE0FE364 /* FIRInstallationsItem+RegisterInstallationAPI.m */, + A24FE0E7A20BBABF063F9974EE71BD68 /* FIRInstallationsKeychainUtils.h */, + 9ACA1297A58C6DEEE74A97F1D898F72B /* FIRInstallationsKeychainUtils.m */, + DBC613BFA3150CBAC4A2F3088A3496AB /* FIRInstallationsLogger.h */, + 99445128B63465CAA78511775C044826 /* FIRInstallationsLogger.m */, + E0A31444EC9783637FF1BF0E9FAAF92B /* FIRInstallationsSingleOperationPromiseCache.h */, + 6250B9B9864608A84ACE5C17FCFD6C40 /* FIRInstallationsSingleOperationPromiseCache.m */, + 1AB26A53B7AF9F47ABC78485EF2137FB /* FIRInstallationsStatus.h */, + E2D22F3C8DC79314E4327FF9F03407E5 /* FIRInstallationsStore.h */, + 923F5208B9B8E8112E5376E4979EEA33 /* FIRInstallationsStore.m */, + F9896C33DDA84C01B16BAFBA8D05642A /* FIRInstallationsStoredAuthToken.h */, + 879E2DE3ADE8E82073D5CED0089B357B /* FIRInstallationsStoredAuthToken.m */, + B05A5F93428885B5A938FC466B2A15FD /* FIRInstallationsStoredItem.h */, + 3045F5E31607213D2722DE71D476C435 /* FIRInstallationsStoredItem.m */, + 2B28B1D9152BF89EA21A1F696D785A12 /* FIRInstallationsVersion.h */, + A27D336247C06AEE085EF43CF6156864 /* FIRInstallationsVersion.m */, + 1E0287E8C63893D4474D3CD7F879AD0D /* FIRSecureStorage.h */, + 134AEB3F267142E63330B1EE8557A729 /* FIRSecureStorage.m */, + 1E42463EC212B6057A6107A5A9542F70 /* Support Files */, + ); + name = FirebaseInstallations; + path = FirebaseInstallations; + sourceTree = ""; + }; + 69BC57C6667BE14E9592102D39A3362B /* FirebaseAuthInterop */ = { + isa = PBXGroup; + children = ( + 9E57284E338D6F0BA60A7F2435A31E90 /* FIRAuthInterop.h */, + 6DA86ED5507C2F0A3155658C8D562DAE /* Support Files */, + ); + name = FirebaseAuthInterop; + path = FirebaseAuthInterop; + sourceTree = ""; + }; + 6DA86ED5507C2F0A3155658C8D562DAE /* Support Files */ = { + isa = PBXGroup; + children = ( + 720B7D4BFAC22CBEB1F9CE8E9D9823FE /* FirebaseAuthInterop.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAuthInterop"; + sourceTree = ""; + }; + 6DC191E3328BB6B6C7F5E2F6918711BA /* Core */ = { + isa = PBXGroup; + children = ( + AD95BC524E418C110A31AA6B77EE4664 /* GTMSessionFetcher.h */, + EDB960BBC8F94DEF008EF48F34DC8AE6 /* GTMSessionFetcher.m */, + 429F8F88B08A830D3F8C419F57124FC0 /* GTMSessionFetcherLogging.h */, + F5D1434B5914AC5EC2EFAC3B3AFA8B3A /* GTMSessionFetcherLogging.m */, + EE496FABD67CAAF80A37A368BA2DFF3D /* GTMSessionFetcherService.h */, + 38D86F977EC22FCEFF56212D1B48EB8B /* GTMSessionFetcherService.m */, + 4110031FA1CB0283269D477218EDFA3D /* GTMSessionUploadFetcher.h */, + 7F04B2F4684D4B3EA35FD95BF17E07F1 /* GTMSessionUploadFetcher.m */, + ); + name = Core; + sourceTree = ""; + }; + 824ECEE0F4CF59E8F50699F163A86AFE /* Support Files */ = { + isa = PBXGroup; + children = ( + 81BB2A12A57AC10B0729222BF61A4E46 /* FirebaseCoreDiagnosticsInterop.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseCoreDiagnosticsInterop"; + sourceTree = ""; + }; + 8BBEA259A1144D9665C8540BD6877235 /* Support Files */ = { + isa = PBXGroup; + children = ( + 4E0CDAA6233B7D55E0DF49497C0476EF /* GoogleAppMeasurement.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleAppMeasurement"; + sourceTree = ""; + }; + 8C8E0F7AD7C250B736114E2A77402F28 /* Support Files */ = { + isa = PBXGroup; + children = ( + 54B7003E10AD368606F445FE6596D080 /* Firebase.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/Firebase"; + sourceTree = ""; + }; + 90FBF734D07B41FF7DE2F1D943AA8949 /* FirebaseCoreDiagnostics */ = { + isa = PBXGroup; + children = ( + 9384A9222E3CA4ED907B7F7FD64AFABA /* FIRCoreDiagnostics.m */, + 6FA32E4E626458BC0248B40BCAED895C /* firebasecore.nanopb.c */, + EC150F4FD984963E187F5A3AA42C98C9 /* firebasecore.nanopb.h */, + 4A654C88D0B538BAEC30C66DB98A8BCC /* Support Files */, + ); + name = FirebaseCoreDiagnostics; + path = FirebaseCoreDiagnostics; + sourceTree = ""; + }; + 9909CF8E87BCC2E4463BEDB8AE68E30A /* Support Files */ = { + isa = PBXGroup; + children = ( + B8316BB66D3F5111376080F16B6BA96B /* FirebaseDatabase.modulemap */, + DAD004FBD9D742F267D2146C5F8D4D6A /* FirebaseDatabase.xcconfig */, + CDB4A8DA2BE9BFC90E5444E2A185301F /* FirebaseDatabase-dummy.m */, + 5A7F99E2491289AB40887AE66C1C6DAF /* FirebaseDatabase-Info.plist */, + E9BBCC3054D48A4CD2B5D5D10A50E38C /* FirebaseDatabase-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseDatabase"; + sourceTree = ""; + }; + 9B68BBEE02B34415ED2CA1082A9CE6A5 /* GoogleUtilities */ = { + isa = PBXGroup; + children = ( + C6F89E4635363F0294548E6029BCEE8C /* AppDelegateSwizzler */, + 409CD672C7AC9DCC91718049D2EF7D23 /* Environment */, + CBBB602E04C44EE535B6C11D6634A191 /* Logger */, + 2B4BF5617AA5DB3FEF1605B7246DACA7 /* MethodSwizzler */, + ECE79AF0D374F02B1F4EC10BA93C4E75 /* Network */, + 606361156995095FE2DDD38255392E48 /* NSData+zlib */, + FD2E8B6DD73A91FA8E1B7DF38644DE8E /* Reachability */, + D158B4FC5B210EE32C095D1B27C70CB3 /* Support Files */, + ED393E1B63AC500FB28910D7290AB4B2 /* UserDefaults */, + ); + name = GoogleUtilities; + path = GoogleUtilities; + sourceTree = ""; + }; + 9BD542E3C0F206FB753961AAB4D631FF /* PromisesObjC */ = { + isa = PBXGroup; + children = ( + EABF0AF368631BBA0EBC6315F6B4144E /* FBLPromise.h */, + E27C8AA3E91D56F81055B51152E93C5C /* FBLPromise.m */, + 0B0E05A5A7593B41D7DA14F11FF6330C /* FBLPromise+All.h */, + 97C269625485B6A7289C6746D99E1EFF /* FBLPromise+All.m */, + C883E313B32C196FA849B2E308CF1812 /* FBLPromise+Always.h */, + 46109B02A1531B0A8FF22CA39EF12E40 /* FBLPromise+Always.m */, + B6664E7165D5105EE3355D7B7FD1AEAC /* FBLPromise+Any.h */, + DFF58064766E5A66920C1C0D4C244C58 /* FBLPromise+Any.m */, + D4F7B7D12CD2AB5F4DA44ADE285B89A3 /* FBLPromise+Async.h */, + D760272F98CD0831968339D53400681F /* FBLPromise+Async.m */, + 10CF2C664D0E815ED48EC7BAEB31578D /* FBLPromise+Await.h */, + 2BD2F054BA7A505A5CF0CF32893BF976 /* FBLPromise+Await.m */, + A02930679CA97D007C20B3DF2C78DA38 /* FBLPromise+Catch.h */, + 3602C9CF1460A33C123A3A12FD8C307E /* FBLPromise+Catch.m */, + 2DD4AD8A942A3CD434EDBDFC70B5CAE8 /* FBLPromise+Delay.h */, + F77D63E559DFC813F4B3AAD2075AB8B0 /* FBLPromise+Delay.m */, + 224AFDDED1449BD5811E120270B60A6B /* FBLPromise+Do.h */, + 5CDC4558A7037B459CADC5E3F8DB0B33 /* FBLPromise+Do.m */, + FBFD83C5D86D93B245CD240C86246263 /* FBLPromise+Race.h */, + 0C452676C3EB75F3891DBC914F75291A /* FBLPromise+Race.m */, + 9A776495F0C11B2D6E910717050FE201 /* FBLPromise+Recover.h */, + 1FAF5018229925BF08F2CB786CCE90A5 /* FBLPromise+Recover.m */, + D628266F3DD667493EE2D5198C86BD0A /* FBLPromise+Reduce.h */, + 0B79E46D2F75EC32EFDC026DBC054C0B /* FBLPromise+Reduce.m */, + F74357951D0E0FCFAB5F7DE7D9B10AB9 /* FBLPromise+Retry.h */, + 0F123D96464AE6E248DA68965E4D63EC /* FBLPromise+Retry.m */, + 4C5151EB7A134D6CB59D6FD68C17EB14 /* FBLPromise+Testing.h */, + 709376BC4C402E261D56E950EEF1F71B /* FBLPromise+Testing.m */, + 9C60FD75C09F75F9F289419CC6EC3DBC /* FBLPromise+Then.h */, + CDF1E1AB955E1D60F59D3B21F43389D6 /* FBLPromise+Then.m */, + 8151357CD1DF92DA0968F4263590737C /* FBLPromise+Timeout.h */, + 58D72AE006E38F62BE505E7BBF0C7EB9 /* FBLPromise+Timeout.m */, + 54384F820C1941AB60BF900E4154CA50 /* FBLPromise+Validate.h */, + ECE11C4938A2B72ABEBFEE62ED66BF8F /* FBLPromise+Validate.m */, + 8931E783ED057317826553414CE66BF4 /* FBLPromise+Wrap.h */, + 66009FB9A96C02DE9E78F386B5D6E14A /* FBLPromise+Wrap.m */, + 788528DEECC60A3130BFE6A2DD831079 /* FBLPromiseError.h */, + 774ACC4D4332DC492738A1293DCAE200 /* FBLPromiseError.m */, + ECACF7849D7CAC8D64FB070D76863651 /* FBLPromisePrivate.h */, + 5B7B5A1E8610253395EBC43E530959CA /* FBLPromises.h */, + 1CE9D0DD732124887B3B770DCCB8EAE0 /* Support Files */, + ); + name = PromisesObjC; + path = PromisesObjC; + sourceTree = ""; + }; + 9C3088195642FD02BD4245FDBF2DC6F9 /* Support Files */ = { + isa = PBXGroup; + children = ( + 29ABCFF3146693410EBE4650CB1C2E37 /* FirebaseAnalytics.xcconfig */, + ); + name = "Support Files"; + path = "../Target Support Files/FirebaseAnalytics"; + sourceTree = ""; + }; + 9D227DC3D4C6AFDF9594160D4875F541 /* FirebaseAnalytics */ = { + isa = PBXGroup; + children = ( + DBBBABB4577B68A58E41A895914B8B5B /* Frameworks */, + 9C3088195642FD02BD4245FDBF2DC6F9 /* Support Files */, + ); + name = FirebaseAnalytics; + path = FirebaseAnalytics; + sourceTree = ""; + }; + A39846E85AAB76336CD74335C4FEF845 /* Support Files */ = { + isa = PBXGroup; + children = ( + 2C7BD76C6C962EDF1D8EE513F83F9CE1 /* GTMSessionFetcher.modulemap */, + AB6496D33D3F05745C5AA89A1BCBF238 /* GTMSessionFetcher.xcconfig */, + F54CE05621F4425787E29C0CEBF58EC3 /* GTMSessionFetcher-dummy.m */, + A1468D1E82115BE338C7006EDB09A252 /* GTMSessionFetcher-Info.plist */, + 4C6BD82E581F5CC725968B1D68A00C19 /* GTMSessionFetcher-prefix.pch */, + CAC2D41AC8570E0DFC63ADB7AC6A34C4 /* GTMSessionFetcher-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/GTMSessionFetcher"; + sourceTree = ""; + }; + A4B3170DC9B145BAF1FCE8A08B93044A /* FirebaseDatabase */ = { + isa = PBXGroup; + children = ( + 9D8978C2B9BC0CE887AF50290BB35F7F /* APLevelDB.h */, + F5C235D00DEB88A19CFC0216A0D1148C /* APLevelDB.mm */, + 201C752BCD7C078C782D815894466726 /* FAckUserWrite.h */, + 0EFC7BAC9CEA86180EE50C52ADF90B7E /* FAckUserWrite.m */, + AC59DA87CAFC56215715B1ED2B850470 /* FArraySortedDictionary.h */, + 334A858E767B7ABD572D6D2F1F9EECAF /* FArraySortedDictionary.m */, + BA66AD23BE6F4FA5FB56166743AF197B /* FAtomicNumber.h */, + C809DE63B19C8CBD6601AD4374B3033F /* FAtomicNumber.m */, + CDEDD664B4945B5C3FFCC439EF5E91F7 /* FAuthTokenProvider.h */, + 7EAA193AE29B62BC092AD06205FD31C8 /* FAuthTokenProvider.m */, + 6A9D4B61A684DA305FA8367430CC9501 /* fbase64.c */, + E9A6FBFCCF1F2E924CB0619DD122C7C4 /* fbase64.h */, + A0B697892DA8B676D87651CB9C438A1D /* FCacheNode.h */, + 5BC2C6B675EB725F0D223EC27209FD39 /* FCacheNode.m */, + 6A18CD9744D0EA0AD2406244414CF334 /* FCachePolicy.h */, + 0AEA2494228A798570ADA4BA569AAD3D /* FCachePolicy.m */, + C34D9E474712175C6FD3E2563CE00F17 /* FCancelEvent.h */, + D9FA396FC4735E76B98DBFA4F74A73EF /* FCancelEvent.m */, + 41813E5BC58F89CA3B1728140B44B6A3 /* FChange.h */, + C3601A2F20B68571CFD4D5585BA05C52 /* FChange.m */, + 93C88B8F3BAB0E426BD1EFF9B685F904 /* FChildChangeAccumulator.h */, + 9D04C17438C9FE6F61E8B3DC057EF647 /* FChildChangeAccumulator.m */, + 805E27E72E56B05291C95F20340F6635 /* FChildEventRegistration.h */, + CB211419F418229FA95278C411875D55 /* FChildEventRegistration.m */, + 44222B32871DED425CC6FD62785342C5 /* FChildrenNode.h */, + 61F577D9F788CAFE7BAA2EA673AC2037 /* FChildrenNode.m */, + 36266F0A667DE528AC3A3717E8619598 /* FClock.h */, + E99B3791B40D702BA7499A2791FF41FB /* FClock.m */, + 26AF78DA83D9E020289D43F83EFF9A8E /* FCompleteChildSource.h */, + DB7C2097612DD516A996C265A7EBDBA4 /* FCompoundHash.h */, + 3FE5BCB2204D5F18D2166F9985632680 /* FCompoundHash.m */, + E4828C39CC6E1566EEC841FEA1495EB9 /* FCompoundWrite.h */, + 58CC0D44AC060ACEC0D534668FA1A8E7 /* FCompoundWrite.m */, + 47F6BCA1337943A0F0648467B2AAD1D7 /* FConnection.h */, + 2FE5FEF4C93674EEFE8E07E813B00232 /* FConnection.m */, + 42F9237E26387A51DA413989DA2C49FD /* FConstants.h */, + D752406CBEEC7D0ADECA246969C4CF9D /* FConstants.m */, + 51D445E473C41D23773680E8C73E7723 /* FDataEvent.h */, + 5FCE5C0E1371E8E6FCAC3358D8DF24E6 /* FDataEvent.m */, + 8C4A7F66B2805F2635EB770E33626B88 /* FEmptyNode.h */, + 7D2D95038A32C6F364131AE25DA18D37 /* FEmptyNode.m */, + D0F4533B0FF71752214FFD4B62FF2878 /* FEvent.h */, + 004545246F93039319DCDA7ABAA016A1 /* FEventEmitter.h */, + 0AB25ED792C29BE405E3B3CD3A8F2EF0 /* FEventEmitter.m */, + 071ED579E4A1C9D1C68506228B44FC8E /* FEventGenerator.h */, + E49EBE95EE5226D43810CC59CC54EB44 /* FEventGenerator.m */, + F2F1F22644685D1B297E9BC3110FF0A3 /* FEventRaiser.h */, + 0072E27C9E6009B48B7F04E59F4F71C1 /* FEventRaiser.m */, + 7E7C15052C0D43C705657358284FDD5A /* FEventRegistration.h */, + 782084FA99F3F0AA7F176FA5363CDCC7 /* FImmutableSortedDictionary.h */, + DCE0EA688C9DF641CB79FF48F8739F46 /* FImmutableSortedDictionary.m */, + 5B98410F83421303C9BE8074E1C0E4AC /* FImmutableSortedSet.h */, + BF8836BA9AAA1475DEDA54342B0F927B /* FImmutableSortedSet.m */, + 84672658BD8FE38B6372AFB154D09F65 /* FImmutableTree.h */, + D75E77BA956ACEBBA0AF6BE30433A511 /* FImmutableTree.m */, + 1E6033BCAD8C3551417FE27E1BD0BC0D /* FIndex.h */, + 6BEAA6AF83FDDCDCFCF2A22F215C51BC /* FIndex.m */, + C849D3E9FF9EB2A0EE26851441710E41 /* FIndexedFilter.h */, + EDE4E8B5C0D67DC87A1CD2751C80E135 /* FIndexedFilter.m */, + 265E98998557D90106A27053DB002C6A /* FIndexedNode.h */, + 96449186D538D5BB130663F9FE2A1F30 /* FIndexedNode.m */, + 865B4435A179E8D322EEB8594A18DFAD /* FIRDatabase.h */, + 632E5D0FA81F7B8874C7A3343EB12F62 /* FIRDatabase.m */, + 87F6444DE4F1D787D0B1FB58BD680119 /* FIRDatabase_Private.h */, + A3C2723DD4EBBF36E3422C8F261BC567 /* FIRDatabaseComponent.h */, + 0B70C438948477944CD43C50B8C26AB7 /* FIRDatabaseComponent.m */, + B1EBAFAAEA3B7B4B663AE6FF460AA209 /* FIRDatabaseConfig.h */, + A5B6CB88832D4E926A10C1260DDD5B26 /* FIRDatabaseConfig.m */, + 7F502C86D58BBC8320F07C65EFEB0D65 /* FIRDatabaseConfig_Private.h */, + 9DF96CD59FB20F67464B5372DD87EB2D /* FIRDatabaseQuery.h */, + 1C899CCE4B5ADC63B99D167B4F6C09D9 /* FIRDatabaseQuery.m */, + 8A78F28BB6A74CF05958DCF007498954 /* FIRDatabaseQuery_Private.h */, + 1B934CF29FE5CD666ED5FEB4184D4D0E /* FIRDatabaseReference.h */, + 6AF4EFB562C4F2ACC556C482569CDAC7 /* FIRDatabaseReference.m */, + 916F2253BB01607784C0DB1216E2E9CE /* FIRDatabaseReference_Private.h */, + 093D5D062733F074DD56AA1955F96DBA /* FIRDataEventType.h */, + 4A7C86481B1F7532480087F344D12CC5 /* FIRDataSnapshot.h */, + 7C5330642B43535CB64DF4DEB6A008A7 /* FIRDataSnapshot.m */, + 76076FE9A810D6F3BB2702942C80DAE1 /* FIRDataSnapshot_Private.h */, + F5E0E11BE35D93380875787C9803A6CC /* FirebaseDatabase.h */, + 17527F81C485EAD0DA6BDDB41CE38598 /* FIRMutableData.h */, + 34D58F578A6B32ACB43E4F081310AF3A /* FIRMutableData.m */, + 453024A9DD7B840DCB627C15A631AA6E /* FIRMutableData_Private.h */, + 1E4564C0D672A2920A1F8E2AD2506168 /* FIRNoopAuthTokenProvider.h */, + C261FFBF13CE61BB390215E9CA9C5FD5 /* FIRNoopAuthTokenProvider.m */, + A6560A52892AAE5757A5CEE963E13593 /* FIRRetryHelper.h */, + 67AB9E7A57BC5C8FD59ABE9097063C35 /* FIRRetryHelper.m */, + 194C2F1E5104D28EFFB7D4AA2CD4BC46 /* FIRServerValue.h */, + 5C5E93C787026AE510C04647460CDC1E /* FIRServerValue.m */, + 4507041848E941A730652DCB9C6775E4 /* FIRTransactionResult.h */, + 2D7DB9E6A2C35C869B3D55E0C1488F2D /* FIRTransactionResult.m */, + 82298B35EE4C04E3F2E48ADB974F83FC /* FIRTransactionResult_Private.h */, + 5CBA2F623E71DEDC84E9B69EE321EAF7 /* FKeepSyncedEventRegistration.h */, + B978BE12FBC5DB5499497CF643032AE7 /* FKeepSyncedEventRegistration.m */, + 945DAB6906A81D5EC5D0F1F2DA26500C /* FKeyIndex.h */, + 68CEF19BF3A286DFCD34482F7F8EBDA1 /* FKeyIndex.m */, + 5D7DBE42AC5973FED94FD2BFAD8DB4DF /* FLeafNode.h */, + 19458D70173FD697C88000691293B4C8 /* FLeafNode.m */, + 5E02672207635E1E0F3FFDADFFFD3946 /* FLevelDBStorageEngine.h */, + 19A1C443965CAAF1705E6A645B84E2C2 /* FLevelDBStorageEngine.m */, + 818EA601A22844DE95498B87F08F4CE8 /* FLimitedFilter.h */, + 72AD2864FE4085C639DB8DCEBC3129B0 /* FLimitedFilter.m */, + D03D9478B9C4950F5892831FA40A6F85 /* FListenComplete.h */, + B1A12E1B5F9F863A9AFEF72FD5DC75BC /* FListenComplete.m */, + E193069FA536F860D51FA8C5BE5EC30B /* FListenProvider.h */, + 0A6652E2684D336D22085F48B522BF60 /* FListenProvider.m */, + 12F5D011A000BAC69522947792FBF47F /* FLLRBEmptyNode.h */, + DB395C56E1B48FBF6BDD2F3219DB0F5F /* FLLRBEmptyNode.m */, + 45C0503452AD338BDBAA92921C9DE194 /* FLLRBNode.h */, + BD1B051942ADDA047D2B87D13FBA2954 /* FLLRBValueNode.h */, + F27AD869EA4F65CDB13697DDE36D24E0 /* FLLRBValueNode.m */, + 0D7B8E85F15B91F2BE7228170D267A72 /* FMaxNode.h */, + 74AEFB17E19376B554C4B5CBE9839CFC /* FMaxNode.m */, + 2EB170657617FFA0F073315570B8F945 /* FMerge.h */, + 7EBA5F26A7ACDF18FC265E9A4E42DFA7 /* FMerge.m */, + 0F83CEF39EB3C9712DC040CEA8502D78 /* FNamedNode.h */, + AEBBB845997D63AABC3D3BF792E2AF04 /* FNamedNode.m */, + CC4A4BAB38692F24392EAFB5C9645180 /* FNextPushId.h */, + FC70AFB7FD9A61A5D9A481E9F24F1AD3 /* FNextPushId.m */, + 9B00ED90C4A7935626C4626A06EF9B8C /* FNode.h */, + 0A301F01504541019F6CCFE316CB38D1 /* FNodeFilter.h */, + 6A46F2DCE1834AD1C9950A85E7A8A6CE /* FOperation.h */, + D1784750A2945CB885B1E0E6B9FD4D8E /* FOperationSource.h */, + 80CA19561A2817A212C0488DEA559C8B /* FOperationSource.m */, + 6A98BA1F60CC9765DC24CD540AF2E6A3 /* FOverwrite.h */, + 6A1C718556F05CC83E3A0A98FC95B6F5 /* FOverwrite.m */, + AD92B971F394927786C8101BFD4C07E0 /* FParsedUrl.h */, + 4DEECD90DC659AAA5A515F133BA3D8A4 /* FParsedUrl.m */, + 250AA97D89AEB8E9740DE1F693CD6303 /* FPath.h */, + 8D58C1777E830172B31A330830F0C9F4 /* FPath.m */, + EB66CFB1B78584AFE3578475D2046904 /* FPathIndex.h */, + CDAF96ED50A683983650B65E4986A78E /* FPathIndex.m */, + 5D4F44ED2E2432E9E466D9C93573B02F /* FPendingPut.h */, + 4F173297AC99D08D91EA05F159592E18 /* FPendingPut.m */, + AC599B33E662AE5F07C790B72D2C0BA3 /* FPersistenceManager.h */, + F2AC7B9BC9D8655DE104DF06635B6F26 /* FPersistenceManager.m */, + 8BB4BB40C8BAC7ADD48C45341955554A /* FPersistentConnection.h */, + D35AA5CCE687873A9CF17FDAF81BCC49 /* FPersistentConnection.m */, + A9EC9ED037C6087A02E7502A11DB4B44 /* FPriorityIndex.h */, + DD161D56636E063DF147582966B2705A /* FPriorityIndex.m */, + ACC08069DA325ABB6838B87AC6835656 /* FPruneForest.h */, + 54BBDDB60CC332B9CB959B5E4B403CCF /* FPruneForest.m */, + 4FA6F619BDF7B5CDBF4A4639BA797B13 /* FQueryParams.h */, + 6CE95ABB415602B3D411D9B619A4E1A9 /* FQueryParams.m */, + D68CD9DCDB8B776D07D3EE629559983C /* FQuerySpec.h */, + 0031AF1FB02DAD5BF0064720F7C7EBA1 /* FQuerySpec.m */, + EC472A7E11E0AF865D19CFCAF9A72A0E /* FRangedFilter.h */, + 8C53D964DD593409B7EDF149D2D09939 /* FRangedFilter.m */, + 07ED1B1B3F489527C7662FED486F7315 /* FRangeMerge.h */, + 489F989E3EF4CC170458E2F7BACF34A5 /* FRangeMerge.m */, + 1D6ADFA238D1EE026EEA9BAC14D8F931 /* FRepo.h */, + 5178BD41D5098BE8385637308F58C5FA /* FRepo.m */, + 2CD81AAA2CDF7215DED4146B535ADC11 /* FRepo_Private.h */, + 93D331B9DF3258EB11BC34C9C24AD173 /* FRepoInfo.h */, + DADF937F52289F4BDB16AE7DB822B058 /* FRepoInfo.m */, + 0D38174AAFD5096B52D9FFE2771D0112 /* FRepoManager.h */, + A25305788598EBB7D81781D92991341A /* FRepoManager.m */, + 7DC869DC361D2BDADAFAE9ECAF9D61C8 /* FServerValues.h */, + 1CB62E487FA29460E6F077133621B7BD /* FServerValues.m */, + B55FE2E8404E0FF6108ED090BF7F4B51 /* FSnapshotHolder.h */, + 90EFE7C5E29A5A1DC18F8FFE9C38ED1F /* FSnapshotHolder.m */, + A3D6CD0CB3F7889EF66E4B88ACE8EE4F /* FSnapshotUtilities.h */, + 6E1E4893A247B3564298AD37244E5E4A /* FSnapshotUtilities.m */, + D5E4EF988C712EDDFC300B001F7A0C7E /* FSparseSnapshotTree.h */, + 6B5054CF11B84CB3FA9A573C0176038A /* FSparseSnapshotTree.m */, + F80CF052FA0620A9B8D80C1A367E7F5E /* FSRWebSocket.h */, + A54C9AF9132A993BDCA8FA4CDB334692 /* FSRWebSocket.m */, + EC38A8C53E78ED42481B50F3D1DA08BB /* FStorageEngine.h */, + FFC87D297C3C3484EBF939B420C4EBAD /* FStringUtilities.h */, + 887E36B3DBCD3FE4AC51137704580907 /* FStringUtilities.m */, + 84DF235307E2195AC3E126915E5737F5 /* FSyncPoint.h */, + 975C05758199E92BCDF7B8AEFA8DC5BC /* FSyncPoint.m */, + 4F057C30095A02BF5F796E7CA9E1C295 /* FSyncTree.h */, + 20966C015039AA38819B63EFA48DDCD6 /* FSyncTree.m */, + 72597659B9DB60714BB5B7577D28FEDD /* FTrackedQuery.h */, + 192069076F1645702572E4BB839A1FBD /* FTrackedQuery.m */, + 4A86A8FD734185489EECEE9ABE1B8639 /* FTrackedQueryManager.h */, + 5FE8DA5D3C54741AF02DCB290B8D866B /* FTrackedQueryManager.m */, + D1341BB202306F13B00265AF86B8F877 /* FTransformedEnumerator.h */, + 95E6DE4A2B320864D331EB38E2425AD8 /* FTransformedEnumerator.m */, + 244B4E0C8D9ED4451E9A26BF10BB836E /* FTree.h */, + A248E1E0FA382168B833426DDECDB4FB /* FTree.m */, + 5F1AAD2D2CFDCF6A5B824D5A886C1CD2 /* FTreeNode.h */, + C81FBDB69D3D7E4329AD1A0FD479E6D7 /* FTreeNode.m */, + 24B3EA8490EADB3F93B91A42EF325BEE /* FTreeSortedDictionary.h */, + C89732C5EDCECB77A12B87C1018E8B99 /* FTreeSortedDictionary.m */, + ABC50885F71A3B759ABD6A64762A0E6D /* FTreeSortedDictionaryEnumerator.h */, + 051ECA26E694DE464F0B2262039F89BD /* FTreeSortedDictionaryEnumerator.m */, + 1483A141DA43BEE0914320FCA91B9E6C /* FTupleBoolBlock.h */, + 71DA7C5A98E56EFF594760AD94F1C73C /* FTupleBoolBlock.m */, + A3E75433084553833D078D8157B97071 /* FTupleCallbackStatus.h */, + B8E8E3D1874DBA689E9ABB2098726F79 /* FTupleCallbackStatus.m */, + 2339CB4AB1EFFABA9FE159FDF9CABBDD /* FTupleFirebase.h */, + 4B041AE2CD41F4960AA09352D90DA5F7 /* FTupleFirebase.m */, + FD8E96626EC223FFE031515C273E16FA /* FTupleNodePath.h */, + 5C9FD3430FC65B7BAB65043C8C66278E /* FTupleNodePath.m */, + 02B9220BF322F27318370B8242BCAFFD /* FTupleObjectNode.h */, + C0E2C72E350099611A032C30D9E97D46 /* FTupleObjectNode.m */, + B712425379B4E7BFDB5FAB86EABCBEEA /* FTupleObjects.h */, + E2E98869B1CB0FA25A72A5EFF1D02816 /* FTupleObjects.m */, + EFDAB92669C9F072D980DC72D47ADE41 /* FTupleOnDisconnect.h */, + 46A9327BAF9A628A9002286422BF7F83 /* FTupleOnDisconnect.m */, + 5FB7097098D26ECEDB878F37E1F8EA41 /* FTuplePathValue.h */, + FA66E374375C4A12B0A38918F5DB9B4B /* FTuplePathValue.m */, + 3D74B536712C66F3158E15B064EE90C1 /* FTupleRemovedQueriesEvents.h */, + 2C8F76E68FA2494D6AF6EF791A7C30A9 /* FTupleRemovedQueriesEvents.m */, + 9C411E83FCE8D78F920AF6FBCD474ACB /* FTupleSetIdPath.h */, + 312064CA84E0B1CCE2BFF80E4A923AC7 /* FTupleSetIdPath.m */, + FFBEFCD078D6A76273D277223110B3D5 /* FTupleStringNode.h */, + CD8D40B6AFCF5F6C29F50AB149BF8282 /* FTupleStringNode.m */, + 1E2B112675E7D67B7AF74F65E5478631 /* FTupleTransaction.h */, + 6A2482A6E24283C2687635398220B20B /* FTupleTransaction.m */, + D3540C0CCBE5B51413625FE4BE262F06 /* FTupleTSN.h */, + 37B02A7BCA4D800A027495A301A5E818 /* FTupleTSN.m */, + 6F17AA9202487602D6AB7C3285CD4697 /* FTupleUserCallback.h */, + BDF0C9F93532C7101C7CB69E2867EC6B /* FTupleUserCallback.m */, + AC0DBEBA832AEB2C6C3CCBC1E2DCF07D /* FTypedefs.h */, + 7B4F315F3C9A54FD6665C263FE3FE692 /* FTypedefs_Private.h */, + 9304301663FF641F230B41BD66C1231F /* FUtilities.h */, + 69AF1F488EDABE86507D79D8AFF1E55E /* FUtilities.m */, + 1B544FA9B3431D609145527D612E6563 /* FValidation.h */, + BDC5BA23017FC776000E41644015C34C /* FValidation.m */, + 3D03DB7135783EFF5869EED8E463C2F3 /* FValueEventRegistration.h */, + 0014856EC9AAD4D35366C287A7B9B14A /* FValueEventRegistration.m */, + 5A96090A085525143C604ABE9DD7A8C2 /* FValueIndex.h */, + 9B5009794F8E9B14AFDCCCC35B349A3D /* FValueIndex.m */, + C0EB6D5853B9601249F3331602421954 /* FView.h */, + 5300BFD42D87DACC4E4A4C4495F15CB6 /* FView.m */, + 792AFB5085BC525196F9BA0AE3A01326 /* FViewCache.h */, + 5DF1ADD915E44D639B021AE569D35711 /* FViewCache.m */, + C34CFA0CD6D054D8ECCB50347442C309 /* FViewProcessor.h */, + D6F6607EDEEF1D6596A32CF0CBD0511A /* FViewProcessor.m */, + CDA172D5E1D03619ED29BD779DB0ABCB /* FViewProcessorResult.h */, + EF4C1A8DA8015C4C9565AA9AF3BBF375 /* FViewProcessorResult.m */, + 76F6CAA85B9481E77015FE98685F15E3 /* FWebSocketConnection.h */, + 96AD2BF11C0A8B331AAF6F623FF7762A /* FWebSocketConnection.m */, + 033D1DE42F6AEAA2F2FE9CF6AE4B70BD /* FWriteRecord.h */, + 3975CADB3F0440D001CE42671FD82B69 /* FWriteRecord.m */, + E11E2FAA9EC9301A1722BBBF7781DBE9 /* FWriteTree.h */, + 690B9A3F161D19CD0FA5B461D0B67875 /* FWriteTree.m */, + 44C3D7F04D9498A963E4218040395239 /* FWriteTreeRef.h */, + BB9276EF011DDA9D5DCE46C59B323984 /* FWriteTreeRef.m */, + 707D8125F2FAB7F6422BB626C37044D0 /* NSData+SRB64Additions.h */, + 9F41AD0ACE33C987BAC1374E6B1320A3 /* NSData+SRB64Additions.m */, + 9909CF8E87BCC2E4463BEDB8AE68E30A /* Support Files */, + ); + name = FirebaseDatabase; + path = FirebaseDatabase; + sourceTree = ""; + }; + A511C9BEBA5B3ED1AD1A74BB6BBCEE4F /* FirebaseInstanceID */ = { + isa = PBXGroup; + children = ( + 248334110F3275218F717022DE49A024 /* FirebaseInstanceID.h */, + 396B90CA36D20A652948E5CDA84CDC5E /* FIRIMessageCode.h */, + A9303EA8089F8772A23463AAFBEB9A1D /* FIRInstanceID.h */, + 6B51851E07A886CF2821B854EA81E101 /* FIRInstanceID.m */, + CF567AE7E57310AE4A3C5DEA9C1FA082 /* FIRInstanceID+Private.h */, + 0C206964574410436FED4D6E158610F0 /* FIRInstanceID+Private.m */, + 96EA9A40414062574AB929B056EEEEC8 /* FIRInstanceID_Private.h */, + 65A05577DB4A1FC0196B42515C4A5936 /* FIRInstanceIDAPNSInfo.h */, + A3E39E8101A41A91A2C935F98E570B0D /* FIRInstanceIDAPNSInfo.m */, + 75CBA7F15D495B26751E54BF4A558FA1 /* FIRInstanceIDAuthKeyChain.h */, + 91BC6FFC5BA4E9232D75C5DA2913F91A /* FIRInstanceIDAuthKeyChain.m */, + 33BEA7F632D48EFB31127984359A7D0D /* FIRInstanceIDAuthService.h */, + 9AD2E9ECB85005226A653B4C97E2D639 /* FIRInstanceIDAuthService.m */, + A841629ECEDFBFB7FF0841EF6C8E1E28 /* FIRInstanceIDBackupExcludedPlist.h */, + 72AD7602E5FEDA3830584CA043EB7F4C /* FIRInstanceIDBackupExcludedPlist.m */, + 764C432940EFD97B8CE3336C8257B57E /* FIRInstanceIDCheckinPreferences.h */, + 21C9F5A07D09B15611C75D123DD8396B /* FIRInstanceIDCheckinPreferences.m */, + DD0768EA430D4B40783B1367C205D0E6 /* FIRInstanceIDCheckinPreferences+Internal.h */, + 74CDCD1E534C5FA7C7571D7246388818 /* FIRInstanceIDCheckinPreferences+Internal.m */, + 6B42259F661E6F3C660CF1AE5031683E /* FIRInstanceIDCheckinPreferences_Private.h */, + 1F3FF41C7805A4DA98244AEF7CC226C3 /* FIRInstanceIDCheckinService.h */, + ED7E3BD4AABE613AC52785257A0E89E6 /* FIRInstanceIDCheckinService.m */, + 370216E4EF7609FBEC6F9EABA8562C55 /* FIRInstanceIDCheckinStore.h */, + C6F4380E9D8DEA36E07AF6214D0E0B97 /* FIRInstanceIDCheckinStore.m */, + E238A56E9E62DC870959BDB148BFCE6C /* FIRInstanceIDCombinedHandler.h */, + 64409ABC3DCB79196DA6ED00E0308A43 /* FIRInstanceIDCombinedHandler.m */, + F8EBCF41CD843B76AEFF4A01DF812CF8 /* FIRInstanceIDConstants.h */, + CD0EFB5FD41F0F3B6F7CA637FEE7CD77 /* FIRInstanceIDConstants.m */, + D90E6343DA880305944FEEC32E0536F5 /* FIRInstanceIDDefines.h */, + 9B2DC3F3158AC569D8BB4D9159B92FDD /* FIRInstanceIDKeychain.h */, + 93588089D0F50EF58C900EDDED947082 /* FIRInstanceIDKeychain.m */, + 29B7D1344D0B83EDA9B3133EB6C60D9D /* FIRInstanceIDLogger.h */, + 41401874FA638C00FF727FA7A46C972F /* FIRInstanceIDLogger.m */, + 1B76679FD290C6916E68E4A74C44F5BB /* FIRInstanceIDStore.h */, + 906F798474B836189059B9A51D6BBFBB /* FIRInstanceIDStore.m */, + 0072A3F0BA7D1F7A27B20C82BFB6DFB3 /* FIRInstanceIDStringEncoding.h */, + 9B73657F1BCBACE23835E1CFAE2DFD69 /* FIRInstanceIDStringEncoding.m */, + EEB94A073C78837518C58FDBB49EE385 /* FIRInstanceIDTokenDeleteOperation.h */, + C4ADE903728E190BA0EE2D6BF297FB07 /* FIRInstanceIDTokenDeleteOperation.m */, + 642DB2182537105AE858C3B8BD03C98A /* FIRInstanceIDTokenFetchOperation.h */, + 83601D3D66D4C646F41A88B146365C27 /* FIRInstanceIDTokenFetchOperation.m */, + C7D94DF9C10300D6FB71C8D9A931EB78 /* FIRInstanceIDTokenInfo.h */, + 184D0B16C9E04FF26374C15D181A7F5B /* FIRInstanceIDTokenInfo.m */, + F1E35600A76731626B0A9B4A65F4FECD /* FIRInstanceIDTokenManager.h */, + 483A5ADBF76AC92AA5C6D5507BB4E23E /* FIRInstanceIDTokenManager.m */, + 19EDA0A14684A68E5E6E03FE91AEEAF6 /* FIRInstanceIDTokenOperation.h */, + 5EDB4E35C2E12DAC6223E2BCD17CFD54 /* FIRInstanceIDTokenOperation.m */, + B0FFB14C614912059B869AA124CE1548 /* FIRInstanceIDTokenOperation+Private.h */, + CB9C8BA79F404A632E12BFD15164FFE0 /* FIRInstanceIDTokenStore.h */, + 2FBF2FCB4B59F5862D91B4604A5180ED /* FIRInstanceIDTokenStore.m */, + 607C922BE31F4818FD0C53BF79A4EC1A /* FIRInstanceIDURLQueryItem.h */, + AA2CDC345A549E5ED13CB3912D118A47 /* FIRInstanceIDURLQueryItem.m */, + 5B5D47BE607CECCD8CFC8645008D99C7 /* FIRInstanceIDUtilities.h */, + E403FD09A6EDAA770ACD23EB7E750605 /* FIRInstanceIDUtilities.m */, + C4608282EA2EF296797D3E04024663A6 /* FIRInstanceIDVersionUtilities.h */, + 8CDEF6C17D03168126524359F161CB71 /* FIRInstanceIDVersionUtilities.m */, + 19C33078E1D0C7BF23A35F6D11FACB9C /* NSError+FIRInstanceID.h */, + D17245470BF0B46FF5A077C52AFD2803 /* NSError+FIRInstanceID.m */, + 10FF548947B9B86C759B2EBF67BB7354 /* Support Files */, + ); + name = FirebaseInstanceID; + path = FirebaseInstanceID; + sourceTree = ""; + }; + A63B6F4D202E2962600F4BC79F84F99C /* Pods */ = { + isa = PBXGroup; + children = ( + 222F606FF31B0F68939C4E7DF028D4FA /* Firebase */, + 9D227DC3D4C6AFDF9594160D4875F541 /* FirebaseAnalytics */, + 69BC57C6667BE14E9592102D39A3362B /* FirebaseAuthInterop */, + A7AF9E038CE9F0D6009EBE65A977FAF3 /* FirebaseCore */, + 90FBF734D07B41FF7DE2F1D943AA8949 /* FirebaseCoreDiagnostics */, + 424052ED612234D6E832E95175E11138 /* FirebaseCoreDiagnosticsInterop */, + A4B3170DC9B145BAF1FCE8A08B93044A /* FirebaseDatabase */, + 6374768777A7FB5EC6EEBC3FA7AF17EF /* FirebaseInstallations */, + A511C9BEBA5B3ED1AD1A74BB6BBCEE4F /* FirebaseInstanceID */, + EF1CBE41C2A65C229F315CB51127929A /* FirebaseStorage */, + B69D47AF218359824DF5B66324FAF797 /* GoogleAppMeasurement */, + 430476B606F9BE625C3CE0AD0C38A83E /* GoogleDataTransport */, + E9521787DDE2B64186772868D59D0A55 /* GoogleDataTransportCCTSupport */, + 9B68BBEE02B34415ED2CA1082A9CE6A5 /* GoogleUtilities */, + E89CAAD1419AED0BFBF7D20967A424F7 /* GTMSessionFetcher */, + B35BB1F6DCDEC58AF5E173CEE708E9CD /* leveldb-library */, + 4F671C0BAE75DCDB711D299CA7F6748E /* nanopb */, + 9BD542E3C0F206FB753961AAB4D631FF /* PromisesObjC */, + ); + name = Pods; + sourceTree = ""; + }; + A7AF9E038CE9F0D6009EBE65A977FAF3 /* FirebaseCore */ = { + isa = PBXGroup; + children = ( + AC876BD753D740DFC24D59EE46909C72 /* FIRAnalyticsConfiguration.h */, + 13695C66BA611111420DD884C0C70123 /* FIRAnalyticsConfiguration.m */, + 615CCFC202BFA16A80BC04AC96FCF487 /* FIRApp.h */, + E27C12152E295AE51F1462B3956ADF9A /* FIRApp.m */, + 26E05B4C70129B7EFF74EFA170692157 /* FIRAppAssociationRegistration.h */, + 3F72A7C87673FA30B1B60FBE587CE6F7 /* FIRAppAssociationRegistration.m */, + D3C3D69913967F6EE53380D4DF1BAAC3 /* FIRAppInternal.h */, + FDACA0EDDA8DC12E586A89B7A92044CB /* FIRBundleUtil.h */, + 120A6866016396AA3B307F0F69751349 /* FIRBundleUtil.m */, + D1EC4B9C46DFC905A56E0EB7306005D6 /* FIRComponent.h */, + 713848D338963B5826A36B0526691EE8 /* FIRComponent.m */, + A92253B0A83EB13072622A5C886F1162 /* FIRComponentContainer.h */, + 4FC8B84916B3508094591E16F5044642 /* FIRComponentContainer.m */, + 68E9186DC5A562BB4509641DC981B866 /* FIRComponentContainerInternal.h */, + 1B4900A12B99435B7C2DBC1A20FA5194 /* FIRComponentType.h */, + 970D1EE49B5B4AE3A1C04FE453E26463 /* FIRComponentType.m */, + F03192D6CD3300140B77BF7EA1CCA565 /* FIRConfiguration.h */, + 9226C7EFCB8792B87686A9B3CCF32F26 /* FIRConfiguration.m */, + C5A1079708AAFDAB8F4F53D6660A3B1E /* FIRConfigurationInternal.h */, + A7265876B72206667C402E8DA2657541 /* FIRCoreDiagnosticsConnector.h */, + A3F890C9E8FFF45508AAFF1DF9F44F1C /* FIRCoreDiagnosticsConnector.m */, + 4DED8B128D826A18F00619CCFDF72995 /* FIRDependency.h */, + D30A603A1AF1B8113D6B28B35BB1685C /* FIRDependency.m */, + 9A84CC0D422B1D53DB21636894EE1EFC /* FIRDiagnosticsData.h */, + 5FFBC2FEA5B7B0021EC1D822FDCF4EBB /* FIRDiagnosticsData.m */, + BBD01369BBFDE33B2EA046878BD3C0B9 /* FirebaseCore.h */, + 856069552761D6C6E970C60B6DFB24FC /* FIRErrorCode.h */, + 8D79F1C1C537FF4B030110EC6A6A0E3D /* FIRErrors.h */, + 77BC895560CE00DAEB6A086A1CDEAEDA /* FIRErrors.m */, + 6721CA9F38C56DD1FED43D3ADA7A6D2B /* FIRHeartbeatInfo.h */, + 297EA095162F086760B8783BF73A1D20 /* FIRHeartbeatInfo.m */, + 6BBE4090EA3B9932677701AF91974C67 /* FIRLibrary.h */, + 1ACD081B6F3DD381BC03AF0B1D4EA03C /* FIRLogger.h */, + BD0F6EDF8E4EF83990ED65297E06B81B /* FIRLogger.m */, + A1E7B8A283EC1446D5E09B2F3647012E /* FIRLoggerLevel.h */, + 411DF6A51F39A73FC87869A8A5AF5170 /* FIROptions.h */, + BE201BF532103F0EFC7059AD2232DEC1 /* FIROptions.m */, + 830B396C70A3D0C1AD07F7F579343658 /* FIROptionsInternal.h */, + 593F643A1D127168A8A468748C572D8B /* FIRVersion.h */, + 2467A834C566F16403C6F4E386D5943D /* FIRVersion.m */, + 434A5C78A5FFF8AFE7AD2798CFE9ED8C /* Support Files */, + ); + name = FirebaseCore; + path = FirebaseCore; + sourceTree = ""; + }; + B35BB1F6DCDEC58AF5E173CEE708E9CD /* leveldb-library */ = { + isa = PBXGroup; + children = ( + BCCD4D307EC99FAF7669F3B43419DAEF /* arena.cc */, + 9DDB6715072A57A18500B34BA425AEBD /* arena.h */, + 9C3E5A6D44DDBAA12BB947034F1DDA85 /* block.cc */, + FD8DD3CBCFCD6D546467D83131DB9AAF /* block.h */, + D8061BD1CFDE7004EC0A4E0E19DCF6DC /* block_builder.cc */, + 2A706EAFB3D2A122ECD92DD5799E98BE /* block_builder.h */, + 7FA6113A1FB0835D3542880DB4C2C78B /* bloom.cc */, + 61C03183DE684C75C09F7D131C6D8E6F /* builder.cc */, + F955BEF204ED310BC614813D9D710DC3 /* builder.h */, + EE8661EE9163CB9D35ADAEA97516FE8B /* c.cc */, + C12710FB7206C72F3780C9F49C020BA1 /* c.h */, + A0FBCE4F7720531AA7D93AE2CF179D0F /* cache.cc */, + C3313BC5CDF1D9223D5FBA0F11BA5EBD /* cache.h */, + E26FDD1CFCD18864203B9242BEB1EBF1 /* coding.cc */, + 58289B6076C1CF90C0AEA2F1BA7CF68B /* coding.h */, + A29247354C87D56646F76034F1DDDCFB /* comparator.cc */, + 1E05A614C11C6F07FF6BD355BEBDF07D /* comparator.h */, + 390419A5519751A14BED14EC54F229AF /* crc32c.cc */, + 31B1AE108730E173979B504D5E7431DC /* crc32c.h */, + 0E1A7752DD11EF21A11603EF886B6447 /* db.h */, + C584B9B3948F8F67F6591EE319DACC20 /* db_impl.cc */, + 9A4EAEA519CDE2E290007A2243F72CBC /* db_impl.h */, + FB842126904767A67B91205B38C304F5 /* db_iter.cc */, + 5B30443859D305A810204C8278AEB271 /* db_iter.h */, + 748D3B36EBC228F82613077FDE13692C /* dbformat.cc */, + 5C4576E396AB8F6390C668D1DFF46CDE /* dbformat.h */, + 50EE24DC0A427CD4D94FAC3BB1119197 /* dumpfile.cc */, + B2D4F7FF0ED7AEDB99891B0C005224EB /* dumpfile.h */, + 9295AFCFC39BB1FDBB0EC3D9ECCF37CE /* env.cc */, + 0902E4607D9246B44AFA3EDCD2FDCE51 /* env.h */, + DD9AD7328301C7C2428C3398259925F8 /* env_posix.cc */, + 029E54A0C7F78D5174C1DE28C541531E /* env_posix_test_helper.h */, + CF1CF114DF0F9CB07BF12F9C39F293E8 /* env_windows_test_helper.h */, + B0CC945D6C82F1429CCFA0460131A4E3 /* export.h */, + 4F37B777FF7AF7050F952C1F7EDBEC58 /* filename.cc */, + AD62319FBDEE7FD684B7E6C057EA8BD0 /* filename.h */, + B9B6D75A17283D9FBCD34327DD2E6D55 /* filter_block.cc */, + DD1AC890E27B00503F3CF6EE90A68C0E /* filter_block.h */, + 114EC166893B4C60D76A1917530AF647 /* filter_policy.cc */, + BD19B03DA6680BFB310D0060308CCD22 /* filter_policy.h */, + 1FB1649F83A4B89E0BAFC3DF429C1CDD /* format.cc */, + E05235154C224436E6591861CD028C05 /* format.h */, + 75488CF61E51A631F39BCAB3BD1723B4 /* hash.cc */, + C9A065473A00B170B362BDB7ECF1B77C /* hash.h */, + C2B014A14B7708A1DFC2279C43A94DF2 /* histogram.cc */, + BA2003C66B9E13070828B7FF4822C7EB /* histogram.h */, + 68835ABB7B485036D75560A394D52DF5 /* iterator.cc */, + E826F61C6B288FEEEBA15A3388C37EBE /* iterator.h */, + F5B4E47D4F948AB4781BE06654B0B1A0 /* iterator_wrapper.h */, + 141087222BACACD95D911E82A46EE9A1 /* log_format.h */, + 330BA0E97DE040797CA80B20D2DBFD22 /* log_reader.cc */, + F2CC73872DB886E14A2366F2B113982A /* log_reader.h */, + 3BA3B39AD51B46E55E3A6A609CBC8E7B /* log_writer.cc */, + 9078AF964D68A97418B2A5520D4F95F3 /* log_writer.h */, + 53B1117013327054ED85001947D836A4 /* logging.cc */, + C7CE15484C79764DF2F6200480570299 /* logging.h */, + DF082C74F4DA2DEAC965BC29903B79AC /* memtable.cc */, + F45D4E33349EF35597144185678B05C5 /* memtable.h */, + 155EA6AF78AAC81C5A5EA1DE64050B53 /* merger.cc */, + D0DFD8426C0E3D2B694A39A96102CAE8 /* merger.h */, + 2DA3D7D0CCBF53EA683D879E7BD0E744 /* mutexlock.h */, + 8853FCD9B54090977DA47CDC4CE1BE96 /* no_destructor.h */, + F7C0D5DD8E1D50B533B78792246BB6BC /* options.cc */, + 9724FC0DB2B700C5916C4B225396830E /* options.h */, + F318D95F186F44696E86DD96E1D6625A /* port.h */, + FE6CE57F830C31B2D2A7D544113C28CC /* port_example.h */, + BC53E9479AFE30937D40541E9A3C3A67 /* port_stdcxx.h */, + 5139CF30473560788ABDCB14D62A88F7 /* posix_logger.h */, + 646E3EB1AF891BC9543C99781D5C61CC /* random.h */, + 44866FAB99B09DB36E26EE4B4E7EE3BF /* repair.cc */, + 6BDB4CAA763E5FF7337EDEB141AFD95A /* skiplist.h */, + A3B4AC5B091751C2FEFA28BD2F610472 /* slice.h */, + F3E27E74E05C98E0B5F68063DCB85240 /* snapshot.h */, + 74CAEF8480566F2AC62C5C743E46760D /* status.cc */, + 6944123B6B8C495EEB39ED65A920FF22 /* status.h */, + EA7BFFCAAF832433E1DCCF3E39E54D6E /* table.cc */, + CE14B460E98E60C8B07474C59D604D04 /* table.h */, + 1D84106EEDBEB4ABE5F79A6CF40A6C46 /* table_builder.cc */, + D0CFD980F55BDA288F9F5F389065BCEB /* table_builder.h */, + 61853C19FB27025E1FDBA8BAB314FCCC /* table_cache.cc */, + 4A59D3DCFF16FA7B1C33B039ECCC3B79 /* table_cache.h */, + 10F2138F2FBC045AC402BDA69D3CD680 /* testharness.cc */, + B4B90F0206371335E59420084F0FFAB3 /* testharness.h */, + E04256A559431B024EAFE17349932DB7 /* testutil.h */, + 24E7AED0E578075903339C2F3EFEEDCE /* thread_annotations.h */, + 3FAFB71A7764BCD006424B153CB958B6 /* two_level_iterator.cc */, + 9E807E38FDEA4D03D392C95EC28E738C /* two_level_iterator.h */, + 94541BC6EE0BD2BEFDF6CD8A2EE668BA /* version_edit.cc */, + 585302D48E99F87797E63B309BF8AA44 /* version_edit.h */, + 35025384884E48B66920A6D01BE8A148 /* version_set.cc */, + 505C1A8D2A956C3FF8FA6D699EB4A581 /* version_set.h */, + 42BD5D5243A04F06CDD2CA2E9C329BC1 /* windows_logger.h */, + D02507890F4001343580522441E85F51 /* write_batch.cc */, + 9379B377EEB58D4388B5DC1218A2CCC8 /* write_batch.h */, + A727AE1575353CFF867D48C1919605D6 /* write_batch_internal.h */, + E772F1E0CBB4C8C4FA6E2E37F0B2F4F8 /* Support Files */, + ); + name = "leveldb-library"; + path = "leveldb-library"; + sourceTree = ""; + }; + B69D47AF218359824DF5B66324FAF797 /* GoogleAppMeasurement */ = { + isa = PBXGroup; + children = ( + 367FEC5D6891FF7DE81223F96433AF5B /* Frameworks */, + 8BBEA259A1144D9665C8540BD6877235 /* Support Files */, + ); + name = GoogleAppMeasurement; + path = GoogleAppMeasurement; + sourceTree = ""; + }; + C6F89E4635363F0294548E6029BCEE8C /* AppDelegateSwizzler */ = { + isa = PBXGroup; + children = ( + A474C4C0651A543458D27D8A61CCF815 /* GULAppDelegateSwizzler.h */, + 8796EE5E561EE5AC1133A1E430CD4EE0 /* GULAppDelegateSwizzler.m */, + 596E00795348CC02B5DA56B1BCC7C88E /* GULAppDelegateSwizzler_Private.h */, + 057F8B6F54F1827EA608534EE8AE4208 /* GULApplication.h */, + 2A8E64F1793145DD60F66ECDFBFB4458 /* GULLoggerCodes.h */, + 75967CE2C51C3463D72B9F051DAE5A38 /* GULSceneDelegateSwizzler.h */, + A9E80D2D264051242FAAC6384CA1ED2D /* GULSceneDelegateSwizzler.m */, + A5F49AB94F002497A53AFCEAFB1FD6C7 /* GULSceneDelegateSwizzler_Private.h */, + ); + name = AppDelegateSwizzler; + sourceTree = ""; + }; + CBBB602E04C44EE535B6C11D6634A191 /* Logger */ = { + isa = PBXGroup; + children = ( + E1D04018157FF78C2C0FE18C2BBFF9F9 /* GULLogger.h */, + CF854CBC1924CB4762773A59FA06AAD6 /* GULLogger.m */, + 3455F9C221E70B76D67B1E8DAA70A45A /* GULLoggerLevel.h */, + ); + name = Logger; + sourceTree = ""; + }; + CDB583DD5DD7478730DFA75754339E14 /* Support Files */ = { + isa = PBXGroup; + children = ( + 23AA2ACA14FF7EEF14BCE4BA3C1FA75D /* GoogleDataTransport.modulemap */, + 7CA76B59C217CF7E6BB876EF16BA6E76 /* GoogleDataTransport.xcconfig */, + F20EACCD4C59A1512EEA6F07603AC103 /* GoogleDataTransport-dummy.m */, + 0F3CC58D9AE381DA2AD37457F99B2D02 /* GoogleDataTransport-Info.plist */, + B36EC66A74944CD3B2D95D93B739EF06 /* GoogleDataTransport-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransport"; + sourceTree = ""; + }; + CF1408CF629C7361332E53B88F7BD30C = { + isa = PBXGroup; + children = ( + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, + 03C5C200A0787E300053CFA8F53CA094 /* Frameworks */, + A63B6F4D202E2962600F4BC79F84F99C /* Pods */, + E20D525EB57DB63AB9F154BE4F6DCB9F /* Products */, + 02B093BADFB5EC801C0A441E2CA6A0E7 /* Targets Support Files */, + ); + sourceTree = ""; + }; + D158B4FC5B210EE32C095D1B27C70CB3 /* Support Files */ = { + isa = PBXGroup; + children = ( + A709E7DFAFADE38DEEC73BDCD1D24C7B /* GoogleUtilities.modulemap */, + 8D2DFCE2D56BFB801722402559090803 /* GoogleUtilities.xcconfig */, + 1E7D89A6CB046C6FA85A49FCC0B99090 /* GoogleUtilities-dummy.m */, + CED26793E5FAE2551262829D529B1C2C /* GoogleUtilities-Info.plist */, + 1740112BBEA67D8392EF5D3C50104C7F /* GoogleUtilities-prefix.pch */, + 47A60F3366969F399160D8AE328D1F1B /* GoogleUtilities-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleUtilities"; + sourceTree = ""; + }; + D4BF2EFA85A55C8C9F88177558486D49 /* Support Files */ = { + isa = PBXGroup; + children = ( + E5559932E650E15482A1C77AF1D52CE5 /* nanopb.modulemap */, + 0C5C92E86E83A2EAD99482570335606B /* nanopb.xcconfig */, + B6E9B7C31546F012D471390B2E511490 /* nanopb-dummy.m */, + 89308F35D1DD5AFD0EFE15D0E4153250 /* nanopb-Info.plist */, + BC4B5FAFD6E4A5815AD9618CF1F3B07D /* nanopb-prefix.pch */, + A5D4B358001D3F084CB3C4CAE20B7C92 /* nanopb-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/nanopb"; + sourceTree = ""; + }; + DBBBABB4577B68A58E41A895914B8B5B /* Frameworks */ = { + isa = PBXGroup; + children = ( + ADA04271750C05862833E153F889470C /* FIRAnalyticsConnector.framework */, + 79975F9B23E6D90138DD71D7F47EFDB4 /* FirebaseAnalytics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + E1C6B9011DC12754522D7F7B1B954996 /* Support Files */ = { + isa = PBXGroup; + children = ( + 42526DD42D37ABD04FBD8D85D95F52F5 /* GoogleDataTransportCCTSupport.modulemap */, + 6FD6C19FE120D8553793CC6271F99B2D /* GoogleDataTransportCCTSupport.xcconfig */, + A5BF35B8BA91663594BBF5352762EB54 /* GoogleDataTransportCCTSupport-dummy.m */, + E80ADBF36FB8C56A60C984778F7D9720 /* GoogleDataTransportCCTSupport-Info.plist */, + 27E7DBAA6418AC1DF35DF54CF5996CEE /* GoogleDataTransportCCTSupport-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/GoogleDataTransportCCTSupport"; + sourceTree = ""; + }; + E20D525EB57DB63AB9F154BE4F6DCB9F /* Products */ = { + isa = PBXGroup; + children = ( + 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */, + E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */, + 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */, + 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */, + 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */, + 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */, + 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */, + 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */, + 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */, + B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */, + C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */, + 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */, + 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */, + 35857822AD1FB3F14370669224C71326 /* Pods_PediatricPancreas_Storyboard.framework */, + ); + name = Products; + sourceTree = ""; + }; + E772F1E0CBB4C8C4FA6E2E37F0B2F4F8 /* Support Files */ = { + isa = PBXGroup; + children = ( + 543DC2781DDBFCFA5F37C29E898584EA /* leveldb-library.modulemap */, + B82F58D4E27A17968CE2E5A6F072524E /* leveldb-library.xcconfig */, + F3D3E03AB5F3B1F5C79EBFDB2B3E5B0D /* leveldb-library-dummy.m */, + 8A57155E388077CC8F4BCBF83A0702DE /* leveldb-library-Info.plist */, + 0E037F738D549FCCFD726636BF810C7D /* leveldb-library-prefix.pch */, + 6FBACF296A5333288E22B9978DF7798E /* leveldb-library-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/leveldb-library"; + sourceTree = ""; + }; + E89CAAD1419AED0BFBF7D20967A424F7 /* GTMSessionFetcher */ = { + isa = PBXGroup; + children = ( + 6DC191E3328BB6B6C7F5E2F6918711BA /* Core */, + A39846E85AAB76336CD74335C4FEF845 /* Support Files */, + ); + name = GTMSessionFetcher; + path = GTMSessionFetcher; + sourceTree = ""; + }; + E9521787DDE2B64186772868D59D0A55 /* GoogleDataTransportCCTSupport */ = { + isa = PBXGroup; + children = ( + 92E0699CC8C007B776F78978059335C0 /* cct.nanopb.c */, + 1096D1DBCB98AE4385176B1D98D0D4D1 /* cct.nanopb.h */, + 1800C48AE5BA951A1284B03F4CE961EC /* GDTCCTCompressionHelper.h */, + E14A19143EB768AC61D16C115E81F4D0 /* GDTCCTCompressionHelper.m */, + 059FD50937C2B1086A8FCF3ADC371B8B /* GDTCCTNanopbHelpers.h */, + 0489E9C92A381651A399F3201AA11690 /* GDTCCTNanopbHelpers.m */, + 7D0233BAEAA67BC6CA1D33848C2D0B0E /* GDTCCTPrioritizer.h */, + 79F3DEB203D9A6D3538745CB46A6B6BE /* GDTCCTPrioritizer.m */, + 0EDD66CDFCF74C4E949499D9C55DC80B /* GDTCCTUploader.h */, + 1C77A25EF19821D402BAE78598EA5361 /* GDTCCTUploader.m */, + E1C6B9011DC12754522D7F7B1B954996 /* Support Files */, + ); + name = GoogleDataTransportCCTSupport; + path = GoogleDataTransportCCTSupport; + sourceTree = ""; + }; + E9733B5E515550799F902178F9770353 /* encode */ = { + isa = PBXGroup; + children = ( + ); + name = encode; + sourceTree = ""; + }; + ECE79AF0D374F02B1F4EC10BA93C4E75 /* Network */ = { + isa = PBXGroup; + children = ( + DE429484969950B4A6B5CE157A9B0853 /* GULMutableDictionary.h */, + 22626DBD000812B98478D77E874B3DB6 /* GULMutableDictionary.m */, + E147ED0EDA24CB6101C7523658C4287B /* GULNetwork.h */, + 9A43440C82173CB5E42191974CF04F1D /* GULNetwork.m */, + 4225CA428474D85D68CB643FE8588165 /* GULNetworkConstants.h */, + 8B90CFA09998FA5040F032B04C452424 /* GULNetworkConstants.m */, + 87ED48D67D39DE00A35A205D0B1B05B6 /* GULNetworkLoggerProtocol.h */, + 1C4835B62590F9B75776B27FA8D95579 /* GULNetworkMessageCode.h */, + C91AB5BA273E41BEE728337BDEABA5C7 /* GULNetworkURLSession.h */, + 13D8301FC7F37CB3A191D1FCF00126C2 /* GULNetworkURLSession.m */, + ); + name = Network; + sourceTree = ""; + }; + ED393E1B63AC500FB28910D7290AB4B2 /* UserDefaults */ = { + isa = PBXGroup; + children = ( + 55061862C4109FA0B57C202449412BF6 /* GULUserDefaults.h */, + 4BD3A12816661B22D94EE76C808C4D2C /* GULUserDefaults.m */, + ); + name = UserDefaults; + sourceTree = ""; + }; + EF1CBE41C2A65C229F315CB51127929A /* FirebaseStorage */ = { + isa = PBXGroup; + children = ( + 128CF27E454BFEA60A3C9AA8900394BB /* FirebaseStorage.h */, + 9A1564C52DDFB1957E792196332B66A9 /* FIRStorage.h */, + 3A13CB75BF68742AE7610270D81FCE09 /* FIRStorage.m */, + 33E94FF93F0D0F4C36D3C35D97BD8DCB /* FIRStorage_Private.h */, + 88F58F93946BE6895E8BBF7AF2D2D164 /* FIRStorageComponent.h */, + A98D534267BBF249F20C291BCAD5DA55 /* FIRStorageComponent.m */, + 81CD2FBB0D1DF2DE80B0A92A432198D5 /* FIRStorageConstants.h */, + 610BC07F3FD1BBBB5175FAD2234EEF62 /* FIRStorageConstants.m */, + AC60B43FA6D28BB9A4A8E7ED8F591134 /* FIRStorageConstants_Private.h */, + 32C7BFD32D5BBC98FC727B87823E3F0C /* FIRStorageDeleteTask.h */, + DD27A6E60F01AA15B88C57ADEE40B496 /* FIRStorageDeleteTask.m */, + C1225D1251AB40E186EA9E17BBEAAEAE /* FIRStorageDownloadTask.h */, + B9B32050A70491C586A91F247F294DB7 /* FIRStorageDownloadTask.m */, + 53BE173D71059143D61695D5A4F056C0 /* FIRStorageDownloadTask_Private.h */, + 2048A7357F01687FD8F3665E48D84747 /* FIRStorageErrors.h */, + 12F18220753EC36AA3774DEDD6478578 /* FIRStorageErrors.m */, + 9A462BED47E045F027B03735EEBDFFF1 /* FIRStorageGetDownloadURLTask.h */, + 3CE038EBFA6A42EE048F83E4B840E76F /* FIRStorageGetDownloadURLTask.m */, + 3BAEE7AB26C4A136E7E3F4B44E7BEA97 /* FIRStorageGetDownloadURLTask_Private.h */, + E67C1D1A48982697C198AB692680D803 /* FIRStorageGetMetadataTask.h */, + 2C346213450344E3B75189159433894A /* FIRStorageGetMetadataTask.m */, + 400B4EF49B532BEB9532849F5FD07F5A /* FIRStorageListResult.h */, + C23D9EF2FABCE6C06BB74403C7E0FF09 /* FIRStorageListResult.m */, + C7B2ECE638DABE730837F22C5CC35FB2 /* FIRStorageListResult_Private.h */, + F69FC4745356C9F9EFA3FC172441B8D1 /* FIRStorageListTask.h */, + A2A97AE7647179E52903F372F44D6340 /* FIRStorageListTask.m */, + A0575E69E82A456143066F611BF304E9 /* FIRStorageMetadata.h */, + 3345F327E7A52648AAE06E3C6F9D1929 /* FIRStorageMetadata.m */, + 27F5B2B2A72A0F52C3D43E4B64D2AFE9 /* FIRStorageMetadata_Private.h */, + 3F532EB505ACAFC5EC6CFDDC747C753D /* FIRStorageObservableTask.h */, + 30E79602773F8F3F189744F56604A4AD /* FIRStorageObservableTask.m */, + 6C6B82976BE98D85A276818786669979 /* FIRStorageObservableTask_Private.h */, + 09BCB0749FF5FD9B5F63C2DDB97398DF /* FIRStoragePath.h */, + EF027EB6EC10790B2A23AC612C1FB6DA /* FIRStoragePath.m */, + 15C33E1A98FACB2E96B1D9BE014EFA20 /* FIRStorageReference.h */, + 50950C3AE1D36D0DFFC58C5E1C571B02 /* FIRStorageReference.m */, + 9E8FA1A885EFD41939BDF374FBA3EEDD /* FIRStorageReference_Private.h */, + EACB33C10F6F9E2BFAD2353C454F9AE7 /* FIRStorageTask.h */, + 78362BB93558FF4EAAEB1E8B43AF9174 /* FIRStorageTask.m */, + 92B13DDB5CB3F9B1C18773D451D044FC /* FIRStorageTask_Private.h */, + 2F0BFC9D0F80D4FBE73F0652CB04E596 /* FIRStorageTaskSnapshot.h */, + 022E69B7A3365C89979582D7FBF6F5CC /* FIRStorageTaskSnapshot.m */, + B5993ED6459C75C852370192D89E609A /* FIRStorageTaskSnapshot_Private.h */, + E3246B27D9A917C54052A78F54307238 /* FIRStorageTokenAuthorizer.h */, + 88629EDEAC20BEE6D9706C0D1683C65A /* FIRStorageTokenAuthorizer.m */, + 38C523982ECA211A1C922FEE51D4428F /* FIRStorageUpdateMetadataTask.h */, + 2B6FD5CF4CFDF8CF03B9B7B49DBEF46A /* FIRStorageUpdateMetadataTask.m */, + F3F1CC7A848EE5F4DD8AFD48F48C16C6 /* FIRStorageUploadTask.h */, + 28CE8ECC4C7F8A3887EBB85CD1B873A8 /* FIRStorageUploadTask.m */, + 5D6FC6558E8C6C30A444F001D3A20CD2 /* FIRStorageUploadTask_Private.h */, + FF0A44A5C1649AF3610C4A16F8CEAA7B /* FIRStorageUtils.h */, + 1D5513A2CF10850CFC7325CC68B0B83E /* FIRStorageUtils.m */, + 0DFB3F04D7C7710F6DF6EDB73BCA9BD3 /* Support Files */, + ); + name = FirebaseStorage; + path = FirebaseStorage; + sourceTree = ""; + }; + FD2E8B6DD73A91FA8E1B7DF38644DE8E /* Reachability */ = { + isa = PBXGroup; + children = ( + 5201DB2D923D20FB1DB7E6BF7295229D /* GULReachabilityChecker.h */, + D0899F5BE9309740C647BE99B3BD7C59 /* GULReachabilityChecker.m */, + 11A186726CCB0F63136A8019DBBD7BAD /* GULReachabilityChecker+Internal.h */, + 357BB6787D118D45F0E266C2F542034B /* GULReachabilityMessageCode.h */, + ); + name = Reachability; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 130846F9CCCA95C355AC070B736B2277 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 332EA8B301C28DD67ACCCCFE9C301BCD /* GDTCORAssert.h in Headers */, + B6D8A7CDFB1EC2596BF2FB68460D9DFC /* GDTCORClock.h in Headers */, + 130A90BC2E5A25B77F82E084845F6A37 /* GDTCORConsoleLogger.h in Headers */, + 312389C2BA9484DD3CA5FB97B5CF125A /* GDTCORDataFuture.h in Headers */, + BBD58D26EF7464B105F93DFEF27598E2 /* GDTCOREvent.h in Headers */, + 0060000465B9E17FBC63E9A209A0D812 /* GDTCOREvent_Private.h in Headers */, + 97AC8D62B5D6DBB36B67FF181AED0A8E /* GDTCOREventDataObject.h in Headers */, + 5400377357C674D5FBD88C009884C2E6 /* GDTCOREventTransformer.h in Headers */, + C3EBD3D0966FE8874E7F89CDD15A3B86 /* GDTCORLifecycle.h in Headers */, + 37D9C520623CF08EB5C51D9F4EC644C9 /* GDTCORPlatform.h in Headers */, + 139C36EBECD414E6E83E09A7CA235723 /* GDTCORPrioritizer.h in Headers */, + EAFAD4163B7DB72562603E8371DEFA68 /* GDTCORReachability.h in Headers */, + 58F95D088D6DBB1ED47F5153F5FCE603 /* GDTCORReachability_Private.h in Headers */, + C4C43A44D26E7EFA74170AB5656AF8B3 /* GDTCORRegistrar.h in Headers */, + B552E8D129507C97200F2AC1B2121BF5 /* GDTCORRegistrar_Private.h in Headers */, + FC894422B5D2B621D5A8D940CCBC1D14 /* GDTCORStorage.h in Headers */, + 20AC7BF2996FC3FB7EAFA0AE6F439DF2 /* GDTCORStorage_Private.h in Headers */, + E469A3376472C43FFF2A26B7E68A4A32 /* GDTCORStoredEvent.h in Headers */, + 23E6C4D752655CD446CC374BCCBD4339 /* GDTCORTargets.h in Headers */, + 7D1159E615ECDA356A0C3DE46514241B /* GDTCORTransformer.h in Headers */, + DAA1263EE3BA44CA628D70158C0EFBAE /* GDTCORTransformer_Private.h in Headers */, + 9F1497DD933D42DEDBE7DB1FC7E2251E /* GDTCORTransport.h in Headers */, + 345084C0B8D05AC602644235063E246A /* GDTCORTransport_Private.h in Headers */, + 4D4A8EBFB5A1691749D24D300F61A3FF /* GDTCORUploadCoordinator.h in Headers */, + FA9EFF6D5A591DC2149A1F8965BB4E09 /* GDTCORUploader.h in Headers */, + EB5A30ADDD05C512297605FE48C39CB6 /* GDTCORUploadPackage.h in Headers */, + B7DA98B94071F1BBE02BF22D7313B848 /* GDTCORUploadPackage_Private.h in Headers */, + 4E967714328F78862492EEC7BA0FB0A1 /* GoogleDataTransport-umbrella.h in Headers */, + 26C6CC2CC4472E8A89EC34D66DB59404 /* GoogleDataTransport.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 192B0C5C073EC9A6765B19688E2E54E1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3A863D0820C600D6EDB165471E932A61 /* APLevelDB.h in Headers */, + 643C288DFB3AF7857EDF2E20778C3A3F /* FAckUserWrite.h in Headers */, + 103B71ABACD6856EA53DA7B7D89E0186 /* FArraySortedDictionary.h in Headers */, + 30DB119E7230E8DBC74B69ADB8A15238 /* FAtomicNumber.h in Headers */, + 5DA34F6E8304809F1A45C0807260E91E /* FAuthTokenProvider.h in Headers */, + 1F0D0D927D9E205B8A23118A5600D6E3 /* fbase64.h in Headers */, + 7F9E1883331F823C5EB51E87851E3E51 /* FCacheNode.h in Headers */, + 07578FB392C497B667C42371F502D4BB /* FCachePolicy.h in Headers */, + BBEB53A54F4B17418511C2B7A93EA5CB /* FCancelEvent.h in Headers */, + E811EF77152AE3518910050E8A79838E /* FChange.h in Headers */, + D3103BDBD1CC376D54BFC859EBFD233D /* FChildChangeAccumulator.h in Headers */, + 10E54E6E5596E34B158C9BAEF9553614 /* FChildEventRegistration.h in Headers */, + B1061C7C80A0F6DF24EC31E6FE73AA0B /* FChildrenNode.h in Headers */, + 54BFFCB3A078A2B6CC5C701419EE2181 /* FClock.h in Headers */, + 0DC20D18348E15F68BA7C9DDEF0688E2 /* FCompleteChildSource.h in Headers */, + 7DCE2CA7560BA7C7BB1463FD60E2E8BD /* FCompoundHash.h in Headers */, + 4ED882A9E6B2980972E792D0CB139DBA /* FCompoundWrite.h in Headers */, + F957C58A6C1486518C11B1673D527696 /* FConnection.h in Headers */, + FFAB3C9E798AD12B4F1274FC275D1491 /* FConstants.h in Headers */, + 5973EF25A8342251F93D0386AFDA860C /* FDataEvent.h in Headers */, + 9CE2E00FE4F6A58989CCA338DF3BA161 /* FEmptyNode.h in Headers */, + 135EF8179570BC83487189BC312B1CBD /* FEvent.h in Headers */, + 1A0DCB6073A15A19D74843765F0E7DEA /* FEventEmitter.h in Headers */, + 9F3032C9BB51D69539BDB7F4AD859ACA /* FEventGenerator.h in Headers */, + 37768774C8955B8BCB1239F4B8207779 /* FEventRaiser.h in Headers */, + FEC5E3D048685E51D290B22735BCF647 /* FEventRegistration.h in Headers */, + 1DD28C450CEEB1E0BD4BF464397FB8F5 /* FImmutableSortedDictionary.h in Headers */, + BA559B250E2210B4EF12513109B50C2E /* FImmutableSortedSet.h in Headers */, + 6444DB1EDAC39731543FE5D552ED4515 /* FImmutableTree.h in Headers */, + B3D0940AEEB725E34BF0AE38A2E34AD8 /* FIndex.h in Headers */, + D69FAAC0FB29982BACC356F973EC8C33 /* FIndexedFilter.h in Headers */, + FE9E1C9273191A1109C91760B86A5372 /* FIndexedNode.h in Headers */, + 40E86DB8ADFE08A02B465C68DC01480C /* FIRDatabase.h in Headers */, + E025D3364F92AE27EEAA46349A9A1FD6 /* FIRDatabase_Private.h in Headers */, + 921B68DD7F7EF6BF3D2415A2B4B5998D /* FIRDatabaseComponent.h in Headers */, + 27BF2DD3CD0D923211654994F172B6C4 /* FIRDatabaseConfig.h in Headers */, + 346676A559DE3D4AA6505253006AF77B /* FIRDatabaseConfig_Private.h in Headers */, + 209C6C81908CB62A4AED0C06E234C0C7 /* FIRDatabaseQuery.h in Headers */, + 28B5DC913E77AB95727AAC7901F85043 /* FIRDatabaseQuery_Private.h in Headers */, + 32C529A1A254C52805E2BE8817065A28 /* FIRDatabaseReference.h in Headers */, + AD643FC92A4606AF667A4B5161F44C1E /* FIRDatabaseReference_Private.h in Headers */, + 691E504A56F2581637FD4C6CC10CC1E5 /* FIRDataEventType.h in Headers */, + 66277C11101A700E913517D61D856BFD /* FIRDataSnapshot.h in Headers */, + EFB6F1B26ED2B0373F0D731255F5773F /* FIRDataSnapshot_Private.h in Headers */, + ED1B544A0F6CF645915DC76DD34FF679 /* FirebaseDatabase-umbrella.h in Headers */, + FBCFD169B08BBF258597A1026AADFCE1 /* FirebaseDatabase.h in Headers */, + D931B8E1268C9CF58432AF78C5FC798A /* FIRMutableData.h in Headers */, + B3D655C3B250B2B216B666B36D99E445 /* FIRMutableData_Private.h in Headers */, + 4EED550851389F3E8126BDE91CDE723C /* FIRNoopAuthTokenProvider.h in Headers */, + 8B97CFB39083F9769E2F676DAA5EBA0B /* FIRRetryHelper.h in Headers */, + C48DC50EC6F56D8DCF49AD3A41FEEF06 /* FIRServerValue.h in Headers */, + 11E8D925C1958F799B64BF74CD1E4FC3 /* FIRTransactionResult.h in Headers */, + 5F7F3C7F972AA9890E45308685FAC3DF /* FIRTransactionResult_Private.h in Headers */, + 13C7B63FBBEE3E94D53258ED8F64F1F2 /* FKeepSyncedEventRegistration.h in Headers */, + 9F02242AEA02A2E8BEEEE56896022A8E /* FKeyIndex.h in Headers */, + A9E07F9288E24EC1952D77C18F3928F0 /* FLeafNode.h in Headers */, + A1F8A330C664BB690B2F07BA7D42C17E /* FLevelDBStorageEngine.h in Headers */, + 77743CC07125058575369EF4E87D7DB4 /* FLimitedFilter.h in Headers */, + A4DB9C6D43242A307C3213CC1A78B690 /* FListenComplete.h in Headers */, + 761650FDEBEBFEE584AE819A5E22B707 /* FListenProvider.h in Headers */, + 2F2F02E72BBE8400C31CA1DFF6E1009B /* FLLRBEmptyNode.h in Headers */, + 83E06D7DF383E38338D42D28FC3BEBBB /* FLLRBNode.h in Headers */, + 20C917F80DD977810A0B54FD24EC50B2 /* FLLRBValueNode.h in Headers */, + 292269F67F53E8DE948D5F59623A2547 /* FMaxNode.h in Headers */, + 1F3AD4EC227982AC02B7974EAAAFAC02 /* FMerge.h in Headers */, + F5E900C53C41B147E4F72C06F1C310FB /* FNamedNode.h in Headers */, + D86E16705CEB928565E15EF6603CC284 /* FNextPushId.h in Headers */, + BFE36AC51520DA7A0D3DCD7C82E6ACED /* FNode.h in Headers */, + 501BE573E169967A986DDF9D4DD4ABBD /* FNodeFilter.h in Headers */, + 3C0EA007E5F899CAE00A0EF83B9CAA39 /* FOperation.h in Headers */, + E0EE15E9D3F86F49D116A9FCC5806C80 /* FOperationSource.h in Headers */, + E87A2038DC2E45F0D997FBBA114E751F /* FOverwrite.h in Headers */, + F49CFC15763573F573C74BFBC260FDD8 /* FParsedUrl.h in Headers */, + E3FCCAA4EDFB0A3CFB02048CD44A6DDA /* FPath.h in Headers */, + 14DAC046DD9EAC4548374C3EA28B3C47 /* FPathIndex.h in Headers */, + 5896965A186A9A0D56E5A3985D44B3A1 /* FPendingPut.h in Headers */, + EFA1831C9A10F6FA481B87383F1E41D5 /* FPersistenceManager.h in Headers */, + D3CDC4D016687D9ABCF4A86EE5A2C994 /* FPersistentConnection.h in Headers */, + 3383C8F20A10A76713EF355800DF4ACA /* FPriorityIndex.h in Headers */, + 844E341DC43007F8D350C5871AF899BE /* FPruneForest.h in Headers */, + 4F5C04D804BE187A0EBCB200253AFFE0 /* FQueryParams.h in Headers */, + 720875322DC993F5489A8C287D88B360 /* FQuerySpec.h in Headers */, + E01CA51DA38E4CE6C592826095290FE0 /* FRangedFilter.h in Headers */, + B8F1F4020E930C0DE5C12D6A043B1C0A /* FRangeMerge.h in Headers */, + 87A01DBF2A88ED8B674303FD80F91425 /* FRepo.h in Headers */, + 4FE44DDB908484BEB2F890A5F1D0D8BC /* FRepo_Private.h in Headers */, + 5EF8E17B00EEE8FBC71720B439F6F11C /* FRepoInfo.h in Headers */, + 111AFF732CA09A146E987DFA8A37D8E6 /* FRepoManager.h in Headers */, + ABD146608271EEF848812A0D554572D5 /* FServerValues.h in Headers */, + C4980A12D0365C6B5A7FB9BE99591F51 /* FSnapshotHolder.h in Headers */, + B3BB577D4211D3023294E7F18B90FCA5 /* FSnapshotUtilities.h in Headers */, + CA31E125CB6F5EEB01582E3F9FA45900 /* FSparseSnapshotTree.h in Headers */, + 3C3ED24D6617734394DC42AFDD9416B0 /* FSRWebSocket.h in Headers */, + 8D32B9E96C8D7AAB2D4C874A0031E08E /* FStorageEngine.h in Headers */, + E9E8CA0DDC6041BBF6A68B8E52090900 /* FStringUtilities.h in Headers */, + 0618A0B20B54F52088A0AB9C34D7DC99 /* FSyncPoint.h in Headers */, + 7660FE06276819EAB7420D5B67AA9045 /* FSyncTree.h in Headers */, + 6E8564186C4DC48202BDF3472AD3FE9E /* FTrackedQuery.h in Headers */, + 8D1EABDFB067573AD6D3EFB6DB7E0D71 /* FTrackedQueryManager.h in Headers */, + 5D44A6B990D07F835AD99E8A3E688B41 /* FTransformedEnumerator.h in Headers */, + D1622A62EE504256DBE10CF51F67975B /* FTree.h in Headers */, + 0C63314596A323C37290FF4DB6A013ED /* FTreeNode.h in Headers */, + B696C2574730621A7A06CBDC788AD8BA /* FTreeSortedDictionary.h in Headers */, + F78D02843626AC2ABA1D794557608E99 /* FTreeSortedDictionaryEnumerator.h in Headers */, + 73E59601E5BFA2443AB2B8879D3DBCEB /* FTupleBoolBlock.h in Headers */, + 0D634D41D845B84BA0F917AC310AA0A1 /* FTupleCallbackStatus.h in Headers */, + F15A28D41D32CBFBB684103037D42EDF /* FTupleFirebase.h in Headers */, + DC3B0995BB8B588FAC007CAA357D50D5 /* FTupleNodePath.h in Headers */, + 0FC9CB243D972863E886EA91F49D3671 /* FTupleObjectNode.h in Headers */, + 2D06159D0C5265DD9B03C4581E775EA1 /* FTupleObjects.h in Headers */, + 8359351040DF8FE835DF10BD2C6AE9E1 /* FTupleOnDisconnect.h in Headers */, + 71C817080F4DDD76B43661DC2B645735 /* FTuplePathValue.h in Headers */, + 3BA56169E7AB7512E4C89D0B47834A57 /* FTupleRemovedQueriesEvents.h in Headers */, + 4D349EC94D9E84F85D21A857E3AABFE3 /* FTupleSetIdPath.h in Headers */, + 08CDB376EECD2693BEE23F7CE0D80151 /* FTupleStringNode.h in Headers */, + 00D778F7464CD6C207C38F5E3F0775C5 /* FTupleTransaction.h in Headers */, + 2DDFE0D16169C642D9133AFEDE7C69A9 /* FTupleTSN.h in Headers */, + D49BB466034BB998F9D122F9B5743E36 /* FTupleUserCallback.h in Headers */, + A6F78146F5D097FAAD4B832C4D495AB0 /* FTypedefs.h in Headers */, + 37529E7A194E25957F44BAFB08422BF9 /* FTypedefs_Private.h in Headers */, + 0FCD61B46D9E94F0A608F553C4B40C73 /* FUtilities.h in Headers */, + DD28FF1388C380AB61723D5A866DAF45 /* FValidation.h in Headers */, + 17ED47B565E13B2E74FD5B9EFC551648 /* FValueEventRegistration.h in Headers */, + EED214C55E222403C1D5EB753D863DCA /* FValueIndex.h in Headers */, + DC369AB43B3D1FB1CEEE74B1D64420C1 /* FView.h in Headers */, + E5E504F03A20C48C531D96698E8D921D /* FViewCache.h in Headers */, + 7D42612361DCD88702ADC3EE552D33BC /* FViewProcessor.h in Headers */, + 52AB5FE12A66D9E4A69B672A70AA9B7B /* FViewProcessorResult.h in Headers */, + 4A6047BD4714AA06F5964A0C2F904F08 /* FWebSocketConnection.h in Headers */, + F568FC176BB78F4A7F9C3DB2A823246B /* FWriteRecord.h in Headers */, + 17B3E5E8B357C3D8170E11F8661EE6D2 /* FWriteTree.h in Headers */, + 9503B342F7CFC98B702861D793378AD9 /* FWriteTreeRef.h in Headers */, + BDB1BFEF26F5E8828BB9AA94F29F854E /* NSData+SRB64Additions.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1CDA080D670C55743CD2C23B65E28C0D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2DD892913137E6A24A430719D3DE4858 /* FirebaseStorage-umbrella.h in Headers */, + AA2D99531924F8709CC5C6DA5A84A1D2 /* FirebaseStorage.h in Headers */, + 373188ECD2445ECE3D2E5A0758A0C6FA /* FIRStorage.h in Headers */, + 6AA694D35FA277681777FE88109FDC9F /* FIRStorage_Private.h in Headers */, + C7B88A7AF4DC14A4D9E0394E4E60CEC5 /* FIRStorageComponent.h in Headers */, + B5145DE6102507FAD19274D1271E2C99 /* FIRStorageConstants.h in Headers */, + 02E579CAD373BBD07CA64034DF8027D3 /* FIRStorageConstants_Private.h in Headers */, + 9F86991A723581E08AE8E6EE79466BC6 /* FIRStorageDeleteTask.h in Headers */, + 582EBE61A305FB0F81BC4840A62F9F51 /* FIRStorageDownloadTask.h in Headers */, + 166567686120393ADD2E2058177C7900 /* FIRStorageDownloadTask_Private.h in Headers */, + E4AF342C6E516D164AE805048E0A1779 /* FIRStorageErrors.h in Headers */, + 0B73D00819088DBCA387F8746897CEAA /* FIRStorageGetDownloadURLTask.h in Headers */, + ECD2747D43E1AD3C38C38E0D34BED9EE /* FIRStorageGetDownloadURLTask_Private.h in Headers */, + 4666B09703FACB6EE3CA19D02AA31B04 /* FIRStorageGetMetadataTask.h in Headers */, + E1019446F7D2644FFCBD73C31DBB0847 /* FIRStorageListResult.h in Headers */, + DDF4E3845A849A316A90A82FBFCBF6B6 /* FIRStorageListResult_Private.h in Headers */, + 736EAE56500A6A2B91EF75CF2E9ABA5D /* FIRStorageListTask.h in Headers */, + 73A314709FAC4C46D13508F8E34EFC23 /* FIRStorageMetadata.h in Headers */, + 0BCD424C49808AB562C7829839B02CEB /* FIRStorageMetadata_Private.h in Headers */, + 6C4C736295AD5F12B4D491DD2C46B194 /* FIRStorageObservableTask.h in Headers */, + 2B8D8668C774CF9751826B5E5DAAF449 /* FIRStorageObservableTask_Private.h in Headers */, + 462B3DE471312B134D72A97157DBEA5A /* FIRStoragePath.h in Headers */, + B8B7C8401035F8F75B8E0812F77B1352 /* FIRStorageReference.h in Headers */, + 4FCFEE1C2ADABAC43C06952EB87CBE6F /* FIRStorageReference_Private.h in Headers */, + 890E7AD9723DD1354170A4CB31C0E7A7 /* FIRStorageTask.h in Headers */, + 7DF0739B4722AE07617F65C0BF27D06D /* FIRStorageTask_Private.h in Headers */, + 88FE26A1F111DA8ADFACFB2C21FC8560 /* FIRStorageTaskSnapshot.h in Headers */, + 2E331C59A64D9A95EE752F403C6DDC90 /* FIRStorageTaskSnapshot_Private.h in Headers */, + C1E4769235EFCB2083CEEF1FB91FF90C /* FIRStorageTokenAuthorizer.h in Headers */, + 89957B71EAB83CFA8235A37A01DFD36B /* FIRStorageUpdateMetadataTask.h in Headers */, + E9B0DC6D113276BAAA73E21CCBB62405 /* FIRStorageUploadTask.h in Headers */, + 87B0FB4038E754FD7352BFECFB158C57 /* FIRStorageUploadTask_Private.h in Headers */, + A27AA2264237C9872164D6F1BB7C92DA /* FIRStorageUtils.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1D02BC54197F0FFCF23C7FB11B54C97D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 55931DE141753FDAA067598C0048E5C0 /* nanopb-umbrella.h in Headers */, + 1B5A6CABFFE529DCE886DC13EFAC75C8 /* pb.h in Headers */, + 0F8C7E276F025666C37CA0CECAC3F000 /* pb_common.h in Headers */, + D4533645AECEFBAEF365BD3D371C11FB /* pb_decode.h in Headers */, + A204AC2A99A5F0775FEE42474CA87A65 /* pb_encode.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2187ED229A481071D8BF304BF9D1D668 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1330FEAA85B79B7328C5EBC2B984A0BE /* FIRAnalyticsConfiguration.h in Headers */, + A708AAE603B2A6D119284985B4B0A633 /* FIRApp.h in Headers */, + BD75C0A4D524F1F55EABC2310709B308 /* FIRAppAssociationRegistration.h in Headers */, + AF1273B969A636DB365E700548D5928B /* FIRAppInternal.h in Headers */, + B04699CACB7CC3F9C1F3B1AEDC5D0A84 /* FIRBundleUtil.h in Headers */, + 104B54D07959A075405C7A9184CD2A08 /* FIRComponent.h in Headers */, + 1980307895FA65A21D31BC6389B3BEC3 /* FIRComponentContainer.h in Headers */, + F3F6C01A5AF8569D54E59FAD714EF276 /* FIRComponentContainerInternal.h in Headers */, + 37CFB19C20CA92E610E2A648E8E0A554 /* FIRComponentType.h in Headers */, + 97FCAB23B3B3295D4AB6C670767E7595 /* FIRConfiguration.h in Headers */, + 5F8AB02CF7EB58E470C8D0EAA6BAE948 /* FIRConfigurationInternal.h in Headers */, + A74F10527A78F572439633D8D6F162C2 /* FIRCoreDiagnosticsConnector.h in Headers */, + DB53EAAD6F40751E21FFF59D4B388515 /* FIRDependency.h in Headers */, + 7DA5DAC7FA9A603B93F0F35B5128DE2E /* FIRDiagnosticsData.h in Headers */, + 3A1A8267A6DF125D7BCE2D342F1D1571 /* FirebaseCore-umbrella.h in Headers */, + 9AAF3D66FF52AABDD06019F200A2D6A9 /* FirebaseCore.h in Headers */, + 0104C71870B54BA06B7A694204C163A9 /* FIRErrorCode.h in Headers */, + 224E1BC8E9A46104F316606FD03055F6 /* FIRErrors.h in Headers */, + 33587E54E4FFBF9937C9514CBD2C2ADB /* FIRHeartbeatInfo.h in Headers */, + 0FFDA2E9E380E2D537CAB57AB1D73833 /* FIRLibrary.h in Headers */, + 8DC45ACAC7CA43FCF89837E18D0373D9 /* FIRLogger.h in Headers */, + ED104CA7FAB817196409F4628EC34B78 /* FIRLoggerLevel.h in Headers */, + 828DAE36E61058CA12A5A48B18407164 /* FIROptions.h in Headers */, + 4E9D1A1586ABD90707E0120057572B81 /* FIROptionsInternal.h in Headers */, + 99A636D3D11B5CA5908D9E7DBA1BA0E3 /* FIRVersion.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 39F8F432763BFB98AA46683A2BBAE9E4 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CC1A1197F3C84723E2D823E87DFA2F1B /* Pods-PediatricPancreas_Storyboard-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 419D40800BCCDC88B4D30635D2CFB068 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B4986614E4F4D8F4FFE503AFFAF3D58D /* arena.h in Headers */, + FF2335F3442E339F9251BB26CEA3AC66 /* block.h in Headers */, + 9E6932F0856AB44456533DCF80A711CC /* block_builder.h in Headers */, + 3AA904AC1AC07C74C35566D77E88B8C1 /* builder.h in Headers */, + A84D6BEF12D2AE019F4E77A0C527E906 /* c.h in Headers */, + 6B66E97D28746CC9C28D2F06251E5E89 /* cache.h in Headers */, + 8362EC8832941BC529EA0C9E9B9905FA /* coding.h in Headers */, + 6F0890444301E337A069103808084FEF /* comparator.h in Headers */, + C9C0A1BDF76F95B0012D094BBABCDC89 /* crc32c.h in Headers */, + F33783FAA7F1D799CE7EF388FD407556 /* db.h in Headers */, + D7262E5CF3EE19D4075C38EA4613E224 /* db_impl.h in Headers */, + E90A85D8E0E4F114DDED6C5FAE9E9B29 /* db_iter.h in Headers */, + 95E1FE5CD5A52C608E8935917ACDA696 /* dbformat.h in Headers */, + 070E3339AECA7C5674B8B54564DD73ED /* dumpfile.h in Headers */, + 3D7CEDF8484D204F3F1CF919657AB034 /* env.h in Headers */, + ADDCBE632C2C646643F3F862EBF6835B /* env_posix_test_helper.h in Headers */, + 082631C7BB8433F196DAE1B3B9ED2051 /* env_windows_test_helper.h in Headers */, + 1F8513A8A40A6C81E0158C6F1C9C2A7A /* export.h in Headers */, + 6098BBAFCF135CA53AB68384EE9A0341 /* filename.h in Headers */, + 01F8CA6FC1B684592EB39FF66F7E413F /* filter_block.h in Headers */, + 8B60886BE7DA0D5C0E675B3D0C44D388 /* filter_policy.h in Headers */, + C4BBEEA190A095C9901FCDDB1E68F409 /* format.h in Headers */, + FB93839AE195233F516E25E855763E06 /* hash.h in Headers */, + F51A4C01270848A6F2583BB316AA6B43 /* histogram.h in Headers */, + 86A9E5C99527684827C235224559D4DE /* iterator.h in Headers */, + EF345A619B91C20B6B8BE46FDEDBCC77 /* iterator_wrapper.h in Headers */, + CCB6D21D1AFCAD82AF282CA2D1EBF49A /* leveldb-library-umbrella.h in Headers */, + DE5127503E0B3121728A9C378CB6F646 /* log_format.h in Headers */, + E2A4DEC1BF2DCBE4C91B541A481DFEEC /* log_reader.h in Headers */, + 2A25C6113AF53711F1BCAEEA92ED51A6 /* log_writer.h in Headers */, + FBC70BD28D97C01F322043960996DA80 /* logging.h in Headers */, + 91F97F8FF5C8BA9F55621F0161A4DEB5 /* memtable.h in Headers */, + F0C386075EA179A50E66B642F0F9F0F1 /* merger.h in Headers */, + BA3974AE08AEF5E6AF9E375ED03C8FD7 /* mutexlock.h in Headers */, + 25B7246C2ECD86917341CCDA10E7FD2B /* no_destructor.h in Headers */, + B1B47680FDB11C2E597CECBAAA6D3A32 /* options.h in Headers */, + 929A05CBBFE0CDB1A9D04FE9471A8B7D /* port.h in Headers */, + 86E5BCF0724E538365D344454A3F3278 /* port_example.h in Headers */, + F556C8734F8F8AB26A777068AFFC8817 /* port_stdcxx.h in Headers */, + DEE47D10701E5457D744D9911388A67C /* posix_logger.h in Headers */, + 925FD7C33A68A155B3223E833822C99D /* random.h in Headers */, + 6A9BA323932E718D585D3EAD9AEC7E39 /* skiplist.h in Headers */, + 51D9D07F47519F2EBCD03E728DF5D90D /* slice.h in Headers */, + D1FFA9ECFE6F7758D887320EF104DE5E /* snapshot.h in Headers */, + 30D072B1E1EA4B0C52DBEC86815C4546 /* status.h in Headers */, + 21A4C63ABD0FA527DA121AC249C5A7AC /* table.h in Headers */, + 7A38D80E7C30B77BA99C30CD3B35D9FC /* table_builder.h in Headers */, + BA506F5F3A63E7A3AFDF669F5F28DD13 /* table_cache.h in Headers */, + 754346F9FC4F9B00E27C59AAF4F25CD0 /* testharness.h in Headers */, + 0A0051BFB3DDD86CB50D8111BF720E92 /* testutil.h in Headers */, + 072110AA280A13A773C874AA79460241 /* thread_annotations.h in Headers */, + CB48A1F715EB71F01CA213657B87F4B5 /* two_level_iterator.h in Headers */, + A16D303C0AC6A7D42E0F8A0AA94B613B /* version_edit.h in Headers */, + 0AB7B1835610DA780A74F7498821442A /* version_set.h in Headers */, + 4D1FEFA9C0A520FBE0C555B0CC66F51C /* windows_logger.h in Headers */, + 664EFFE98B1B9DA2164C46CE2BA05EA1 /* write_batch.h in Headers */, + 63F1625DCA8A82EDA22881FC7374292C /* write_batch_internal.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4603A9F90624815C0C762F6AFA0EE844 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2450E43216ABE26BB815CEBAC3EDE2C0 /* FirebaseInstallations-umbrella.h in Headers */, + BCC2A87AD0F14860F6B19ADA649102EC /* FirebaseInstallations.h in Headers */, + D753FA9673411EDDE9CBC1B1D6B4BE46 /* FIRInstallations.h in Headers */, + A08B7932A2AEA599496A3763C951AE6B /* FIRInstallationsAPIService.h in Headers */, + 48BD5B3CCD4213D84EC61120F70FFBC8 /* FIRInstallationsAuthTokenResult.h in Headers */, + 1AB9186FB7FDEC77E769537F55D0AD15 /* FIRInstallationsAuthTokenResultInternal.h in Headers */, + DC241C4495CC6CD95E50D4AD19556260 /* FIRInstallationsErrors.h in Headers */, + 21138158A15A5007967102D506444F67 /* FIRInstallationsErrorUtil.h in Headers */, + 19D72AF22467A9FBD6E3FB59ADA49C22 /* FIRInstallationsHTTPError.h in Headers */, + 189886B026180FF0F90DA01FF72F844A /* FIRInstallationsIDController.h in Headers */, + F8DDD059A033A7ED85707270A939E394 /* FIRInstallationsIIDStore.h in Headers */, + D81BD423C792CF4930C1137F1C1FD41D /* FIRInstallationsIIDTokenStore.h in Headers */, + 7916CFEE9143C1C3D7296DFF66AE5469 /* FIRInstallationsItem+RegisterInstallationAPI.h in Headers */, + 5F20EB1FE7759423C4F9F6E62F17957D /* FIRInstallationsItem.h in Headers */, + F855AEF04B44D6F5B299DE45F255EABF /* FIRInstallationsKeychainUtils.h in Headers */, + 8C9BA1E165EE7575E621F061D269EB18 /* FIRInstallationsLogger.h in Headers */, + 8F08089419E600DA51BDADF36DB792AF /* FIRInstallationsSingleOperationPromiseCache.h in Headers */, + BFC4F89E3D91D2265FFC4D1E0BAEE473 /* FIRInstallationsStatus.h in Headers */, + 0297E70E68D821A53F9F751CC0D6C0FF /* FIRInstallationsStore.h in Headers */, + BF62F42B4AB545D89B1E5F573481EAA6 /* FIRInstallationsStoredAuthToken.h in Headers */, + 9BF8F2C1071091020A1723B7D830B352 /* FIRInstallationsStoredItem.h in Headers */, + 9D25E6F740FFB7E2E1C51DF595D30C98 /* FIRInstallationsVersion.h in Headers */, + A99706F65C909FC6718BEFA0CC372FEA /* FIRSecureStorage.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4CEDE0D4AA0F276FC82619A45BE5DB28 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + B68E07FCDC1873E5B1EB886F680E7450 /* GoogleUtilities-umbrella.h in Headers */, + 6B99CF35203D52B6710F0E4F2760F5F4 /* GULAppDelegateSwizzler.h in Headers */, + 1CE1F53F5FF5F137ADAC6B7B923FAC6F /* GULAppDelegateSwizzler_Private.h in Headers */, + DCD1917F472DCA0394AC42C653F985E0 /* GULAppEnvironmentUtil.h in Headers */, + 3297CD4971460E07997D3868D23B484E /* GULApplication.h in Headers */, + 10F4529D16EC386BC7B854710B376B8D /* GULHeartbeatDateStorage.h in Headers */, + C34D0883D644A8776DC5B9FFADBD1BD3 /* GULLogger.h in Headers */, + 23C2F747D08DC06216A44A74566B03E5 /* GULLoggerCodes.h in Headers */, + 4295EE4125B59C180ABF75BB9612E88B /* GULLoggerLevel.h in Headers */, + 4AD4E46142AA949BE9AE25B792D61732 /* GULMutableDictionary.h in Headers */, + 08BD0585E5A36731DE2DF3AF02C1F1BC /* GULNetwork.h in Headers */, + A2D249927139D3D5A465236958CE9942 /* GULNetworkConstants.h in Headers */, + 7598D63A78F5DFC0709164C7CD572F78 /* GULNetworkLoggerProtocol.h in Headers */, + 3AF083A6E1147C2A01BFD01146472601 /* GULNetworkMessageCode.h in Headers */, + 3A39684C35F7AAA1639553E02FAE319C /* GULNetworkURLSession.h in Headers */, + 80E96D8E39F3CEC4ECB25553B90726E1 /* GULNSData+zlib.h in Headers */, + D47D7135085458EC266BD4C8682F06E6 /* GULOriginalIMPConvenienceMacros.h in Headers */, + 02DB6C108D93B1A28894EE7DB7E7EBC0 /* GULReachabilityChecker+Internal.h in Headers */, + E38885D124D3963B62B19DA1ECBD50E7 /* GULReachabilityChecker.h in Headers */, + 0AEBFA834735E8579CAC2EB3ACF6D99C /* GULReachabilityMessageCode.h in Headers */, + 2558F4F5D4FECE3F6558FFA5DC2F89CD /* GULSceneDelegateSwizzler.h in Headers */, + 1234B5B2DE0C98E5482BCF2B10FC2C52 /* GULSceneDelegateSwizzler_Private.h in Headers */, + 3A4609CC6E45B5244A0745948E944C6D /* GULSecureCoding.h in Headers */, + B36F0725AD821954CFBB57931006CAB4 /* GULSwizzler.h in Headers */, + 8E22BF1FFFB98647ECA203A8E7AF37DD /* GULUserDefaults.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 64FB4A070FE69092F995B324535EE1CD /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 6C87D5D170CCC6CE2FF3D7AA3FB41001 /* GTMSessionFetcher-umbrella.h in Headers */, + 69162A12A8CBB4BE21827065EBE80841 /* GTMSessionFetcher.h in Headers */, + 33535514510048650EFFF474494C9CBB /* GTMSessionFetcherLogging.h in Headers */, + EC2EECECD2279FC03827652CD100C789 /* GTMSessionFetcherService.h in Headers */, + A89C04521E00485D808FA28609FFCBFB /* GTMSessionUploadFetcher.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8AE47766464C0F45BC7D3ED9AAE038DE /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E16306F9748D0D18B338CC4734EB2D7 /* cct.nanopb.h in Headers */, + 5DCD70562BD075983509DDA8DB876DF6 /* GDTCCTCompressionHelper.h in Headers */, + E85B408CB57586431D8F0C365268D4C9 /* GDTCCTNanopbHelpers.h in Headers */, + 1467E275A257119254198B74EC96371C /* GDTCCTPrioritizer.h in Headers */, + 15A989DB253C7765136C1BF9645EB553 /* GDTCCTUploader.h in Headers */, + 8EE9A761D6B7B901935116CC1790ED46 /* GoogleDataTransportCCTSupport-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AD017839C06BD010952930E0C4A095EC /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A0ACAB10D0A53EF6EB4873D611C6A42F /* FirebaseInstanceID-umbrella.h in Headers */, + 1E6D3B25EB193CACD277F7F545DD37C1 /* FirebaseInstanceID.h in Headers */, + 9A76B979483CDCC7889F7439157B1865 /* FIRIMessageCode.h in Headers */, + 9F480EDE16EBA9D07BD5CCF66B3CC57A /* FIRInstanceID+Private.h in Headers */, + 4F5F19C3307CBF09DE07A99B240FC8E8 /* FIRInstanceID.h in Headers */, + 53713E44B39E56DC4F2D913240EFA4BE /* FIRInstanceID_Private.h in Headers */, + F9D0A266CB35C375FFFF03428B064677 /* FIRInstanceIDAPNSInfo.h in Headers */, + 7581977D9500AE8FF79CEDD4CC0C8EEC /* FIRInstanceIDAuthKeyChain.h in Headers */, + 26A44D084033DEE3774091F0FDB79F92 /* FIRInstanceIDAuthService.h in Headers */, + D89DDCAD361741ECA2CA115601BA5663 /* FIRInstanceIDBackupExcludedPlist.h in Headers */, + 14858254AE33D7911341C466A1F39CB5 /* FIRInstanceIDCheckinPreferences+Internal.h in Headers */, + FAD80A624EBAB6374BA83F2CF0097F8B /* FIRInstanceIDCheckinPreferences.h in Headers */, + B9CFB547B444FDF1B9F719AE1F95F6BD /* FIRInstanceIDCheckinPreferences_Private.h in Headers */, + 3216257623D8E40F5E98540AB3C6B09E /* FIRInstanceIDCheckinService.h in Headers */, + E9BF1A5ADF89EBD75DDF91246D02809B /* FIRInstanceIDCheckinStore.h in Headers */, + 44FA484BDB5493766E852DD68943A34A /* FIRInstanceIDCombinedHandler.h in Headers */, + 21E747E5978CE879441249FE60948F03 /* FIRInstanceIDConstants.h in Headers */, + 2C403D26D56AB4E4F3ADF6F5B34B3B93 /* FIRInstanceIDDefines.h in Headers */, + 83AE066A91D8C56272DF82389C5C6E09 /* FIRInstanceIDKeychain.h in Headers */, + 638E30974DFA78B0931036B0F02D633B /* FIRInstanceIDLogger.h in Headers */, + 43C6AB676FED45667A7CE48AEAD59348 /* FIRInstanceIDStore.h in Headers */, + 47C8A20C53128BE5AED6082FA0A35709 /* FIRInstanceIDStringEncoding.h in Headers */, + D29D79614CE914BDEFD03A6367D9030C /* FIRInstanceIDTokenDeleteOperation.h in Headers */, + 26A62904906424401425EBA3464DB4FB /* FIRInstanceIDTokenFetchOperation.h in Headers */, + 47F67D7B3CF893A35D08A2B4A475D44C /* FIRInstanceIDTokenInfo.h in Headers */, + 29B6B6CF40BBB25B0125619030D686A5 /* FIRInstanceIDTokenManager.h in Headers */, + 5F74BA54BC98A870C3D578726F47CEFA /* FIRInstanceIDTokenOperation+Private.h in Headers */, + 0E1E3057EF6B378D07627A39E872528A /* FIRInstanceIDTokenOperation.h in Headers */, + 1E508D43C3526EDD5157BE901D816438 /* FIRInstanceIDTokenStore.h in Headers */, + 64E4B118012477620D4021CB9F889100 /* FIRInstanceIDURLQueryItem.h in Headers */, + 6B4E54F20B4197926667E618A146429A /* FIRInstanceIDUtilities.h in Headers */, + C5C1AA2278E0981C27C7FC6B830E78D9 /* FIRInstanceIDVersionUtilities.h in Headers */, + 44FEB57BB9E17E89A76B8D124C9E1745 /* NSError+FIRInstanceID.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BEBE541599E5FD44BD4EC6C00EFAB614 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 0485D0FEC1E223F80D6BD9D354594836 /* firebasecore.nanopb.h in Headers */, + B34E2EBAFB177A7519DA402AE480AEEF /* FirebaseCoreDiagnostics-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB4036BA6E2269D78D1E773C15E5ED09 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 419D3C01D1B29563FFBA8B2314634835 /* FBLPromise+All.h in Headers */, + 1FE6D486D2DA7BDDF9D44F4F747CE838 /* FBLPromise+Always.h in Headers */, + BDAAF880CC0610608FB5C85CC2D2DE19 /* FBLPromise+Any.h in Headers */, + 47F6067CC44AE06245E1882980711492 /* FBLPromise+Async.h in Headers */, + 4A1F808C2B87E169F70699304F10C40B /* FBLPromise+Await.h in Headers */, + F21A40D690B2C7A2DEC81F926C36BC73 /* FBLPromise+Catch.h in Headers */, + DAE6C5E0795DABC15B3B87B089F22F58 /* FBLPromise+Delay.h in Headers */, + C0E9002DF488FE3C7EB377DCB60489E5 /* FBLPromise+Do.h in Headers */, + 7A53D8D03C4684575862EDB86C2AB168 /* FBLPromise+Race.h in Headers */, + 46FA556CA70DE477C3CE680860AF1D14 /* FBLPromise+Recover.h in Headers */, + 59BE46AE30D313C3ADBAEE3D1F590AC7 /* FBLPromise+Reduce.h in Headers */, + 7CA6185CE3610CFAF706ABDA56173C07 /* FBLPromise+Retry.h in Headers */, + FE88BBBBF16F3F855EA9FCE6AF54FF34 /* FBLPromise+Testing.h in Headers */, + A446CF2879E16656DEABDC8EEF930F9B /* FBLPromise+Then.h in Headers */, + 04888C1575F74E2D46652037037EA1CB /* FBLPromise+Timeout.h in Headers */, + 4F029724AC4AD29BFD402662CD6223EC /* FBLPromise+Validate.h in Headers */, + 23623AC88B05692373ABCAFC5D55D595 /* FBLPromise+Wrap.h in Headers */, + 4BFB521CC159F5F69B8261795EEAAB61 /* FBLPromise.h in Headers */, + CDE60789D578C150075686DA4858E058 /* FBLPromiseError.h in Headers */, + 1F2B25E18DC5A01F6CA6BF22117177D7 /* FBLPromisePrivate.h in Headers */, + B67210B747B2F553A333E5D8909340EC /* FBLPromises.h in Headers */, + 2927A43C382BB970274A35157220EF55 /* PromisesObjC-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */ = { + isa = PBXNativeTarget; + buildConfigurationList = F3FE35D32589E8D9D20757244DA48B09 /* Build configuration list for PBXNativeTarget "FirebaseStorage" */; + buildPhases = ( + 1CDA080D670C55743CD2C23B65E28C0D /* Headers */, + 973567BB59AABEA876FA3149B844D671 /* Sources */, + 802E7B243B377BCEF43384753EF1BD6F /* Frameworks */, + 5C58FA40F48BC4E272331FED72E25C1E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 38DDBCD37A18047DCDF6E7F9BFF6D076 /* PBXTargetDependency */, + 313210733AE3BC49AEB2F6DD8D94D41C /* PBXTargetDependency */, + C6C3A7AF88127E286F184DC8C1B126FE /* PBXTargetDependency */, + ); + name = FirebaseStorage; + productName = FirebaseStorage; + productReference = 9CF8FA5F01F446F01AAC7331075452AD /* FirebaseStorage.framework */; + productType = "com.apple.product-type.framework"; + }; + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */ = { + isa = PBXNativeTarget; + buildConfigurationList = FC959BA6A8F4810F766F9AAF74853C1C /* Build configuration list for PBXNativeTarget "PromisesObjC" */; + buildPhases = ( + CB4036BA6E2269D78D1E773C15E5ED09 /* Headers */, + 517C22992560BEC4B4AD39CA654B663B /* Sources */, + 2D8606A32A41CB40AAFFBCBCD1696310 /* Frameworks */, + 2979593BBAB5AE2DB9B63147A0F0EA68 /* Resources */, + 269B4DC8DE63FB8AE06511FBB8B22F16 /* Copy . Public Headers */, + A00A245420F328FAEDAAC8E7516FBF09 /* Copy . Private Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PromisesObjC; + productName = PromisesObjC; + productReference = 3347A1AB6546F0A3977529B8F199DC41 /* FBLPromises.framework */; + productType = "com.apple.product-type.framework"; + }; + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */ = { + isa = PBXNativeTarget; + buildConfigurationList = E0051EA384E24FC75A3A80B8E1E63F4C /* Build configuration list for PBXNativeTarget "FirebaseCore" */; + buildPhases = ( + 2187ED229A481071D8BF304BF9D1D668 /* Headers */, + AE07BD1A6297D05645694748BDFC6C5E /* Sources */, + 9BED85A766DD5DD199782CDD1CB12F2D /* Frameworks */, + 193870DE0E39C0BA224177A2778E38F9 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 26E98BDE443ADA9B9FFB8CA62E2AFC26 /* PBXTargetDependency */, + 5E6C69390453D0B9C226012D5C370A4A /* PBXTargetDependency */, + DC2D61D7B5AAC85EE2082976F195646B /* PBXTargetDependency */, + ); + name = FirebaseCore; + productName = FirebaseCore; + productReference = E2B63D462DB7F827C4B11FD51E4F8E2D /* FirebaseCore.framework */; + productType = "com.apple.product-type.framework"; + }; + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */ = { + isa = PBXNativeTarget; + buildConfigurationList = 03C69977197FB210700683A693848CD8 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */; + buildPhases = ( + 130846F9CCCA95C355AC070B736B2277 /* Headers */, + 37E5D09D029789FBBBC4B82A68C66D23 /* Sources */, + AAA4C7647506233567DF9FF0A75968D0 /* Frameworks */, + A61A5770BCADF1284C16BE3B3F15C01F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleDataTransport; + productName = GoogleDataTransport; + productReference = 856B5CD56F194FAD26EA91620B66D614 /* GoogleDataTransport.framework */; + productType = "com.apple.product-type.framework"; + }; + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */ = { + isa = PBXNativeTarget; + buildConfigurationList = DC665A976EE39388357D491AB7A632EF /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */; + buildPhases = ( + BEBE541599E5FD44BD4EC6C00EFAB614 /* Headers */, + 9C8FFCCE80B105DD7D4E009AB663C334 /* Sources */, + 7C13B57579C7CE08BA7978B2260D8727 /* Frameworks */, + 7A57BEC9019F065C6C145B716B3D4BDC /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D584E2A3DB684D97155ACA3F82E1CFD4 /* PBXTargetDependency */, + 4B77086EEA306513BFC51FCAD91063D7 /* PBXTargetDependency */, + 1C64A6756AFDC641F1613C7DC82CB477 /* PBXTargetDependency */, + 0591622CEB0B7BACBE520F0AF1B238D3 /* PBXTargetDependency */, + ); + name = FirebaseCoreDiagnostics; + productName = FirebaseCoreDiagnostics; + productReference = 8CC9178C366942FD6FF6A115604EAD58 /* FirebaseCoreDiagnostics.framework */; + productType = "com.apple.product-type.framework"; + }; + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2C9D1AE1143F17DCFD8D4E85059CF7DC /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */; + buildPhases = ( + 192B0C5C073EC9A6765B19688E2E54E1 /* Headers */, + C2F556D948FAFF27B997C28AA938FFCA /* Sources */, + CBFE6A050EBB5B87E7ED88AD95397203 /* Frameworks */, + DBAD5C2862084247C35AB177D3CA1011 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 64B32BD3F1919B8F0009EC0B5702B96C /* PBXTargetDependency */, + 97C3541CC26483F1C17D172C1E8B02BC /* PBXTargetDependency */, + E35F8B53FC2222F3A0EF53AA256BAB6C /* PBXTargetDependency */, + ); + name = FirebaseDatabase; + productName = FirebaseDatabase; + productReference = 51671C73F008B5C0C3751B3855999213 /* FirebaseDatabase.framework */; + productType = "com.apple.product-type.framework"; + }; + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */ = { + isa = PBXNativeTarget; + buildConfigurationList = 91A23903EB5CBC5A5B669707FBC53853 /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */; + buildPhases = ( + 4603A9F90624815C0C762F6AFA0EE844 /* Headers */, + EA1850AF31138B7ED7EA7DC10B7AD94C /* Sources */, + ECA9D30190CFBAD261C97DB31D37A303 /* Frameworks */, + D6125F35E0F31207374E266D39708782 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 006C0599B322B2A071A0E6BE46C1C90B /* PBXTargetDependency */, + 60536324D1192BCC2E9F578208E5E286 /* PBXTargetDependency */, + BD039C8ABA7EAABF9AB927634EBC0763 /* PBXTargetDependency */, + ); + name = FirebaseInstallations; + productName = FirebaseInstallations; + productReference = 13C8C8B254851998F9289F71229B28A2 /* FirebaseInstallations.framework */; + productType = "com.apple.product-type.framework"; + }; + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1C889A0661C0A7C8673998DD5001B2B9 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */; + buildPhases = ( + 4CEDE0D4AA0F276FC82619A45BE5DB28 /* Headers */, + BFF9856820EEA5FC6B863518ED9B1135 /* Sources */, + DB74152AABA217349F58AFA22CF0A690 /* Frameworks */, + E2A7C24E8F497788AA5FBF7B75914EB1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GoogleUtilities; + productName = GoogleUtilities; + productReference = B43874C6CBB50E7134FBEC24BABFE14F /* GoogleUtilities.framework */; + productType = "com.apple.product-type.framework"; + }; + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */ = { + isa = PBXNativeTarget; + buildConfigurationList = 611DD575F9DF5427C804BEFA22DF22DE /* Build configuration list for PBXNativeTarget "leveldb-library" */; + buildPhases = ( + 419D40800BCCDC88B4D30635D2CFB068 /* Headers */, + 6970BD69C589CD3E4F9A67139ED66C18 /* Sources */, + B90C2DC39BCD6CF494C7B57BF01D5501 /* Frameworks */, + 0DD38B51F69D00C3A017FA32BD65AAE0 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "leveldb-library"; + productName = "leveldb-library"; + productReference = 0A9F46A999C47653013D3AD854352507 /* leveldb.framework */; + productType = "com.apple.product-type.framework"; + }; + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */ = { + isa = PBXNativeTarget; + buildConfigurationList = 05A917D87C53A0E9BD3114B20337A4B9 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */; + buildPhases = ( + AD017839C06BD010952930E0C4A095EC /* Headers */, + 8DA11696A35204F4C333FF5955724597 /* Sources */, + 5DF37E3EF94989DF8CAE4076F21381EE /* Frameworks */, + 4A49114767A76EAB587D177AFAD26BB8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 1F1284703AEDC0768BEB2CEB7044CA53 /* PBXTargetDependency */, + F5BF6546E393C3EE9D02D965B7083878 /* PBXTargetDependency */, + CD72E5EBAD6C41F99E812273DA0391B6 /* PBXTargetDependency */, + ); + name = FirebaseInstanceID; + productName = FirebaseInstanceID; + productReference = 2DA0D814DFCB860D31D7BCD63D795858 /* FirebaseInstanceID.framework */; + productType = "com.apple.product-type.framework"; + }; + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6B1DE05CE45EFD6CA239C3759FC27C2E /* Build configuration list for PBXNativeTarget "nanopb" */; + buildPhases = ( + 1D02BC54197F0FFCF23C7FB11B54C97D /* Headers */, + 1394197F4BCDF01B34242E82093E6F59 /* Sources */, + 9C6A766CB759F8982F53D2B59F8BFF07 /* Frameworks */, + 3980B9177A1276BF9B0931F27A18966F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = nanopb; + productName = nanopb; + productReference = 06FC5C9CF96D60C50FCD47D339C91951 /* nanopb.framework */; + productType = "com.apple.product-type.framework"; + }; + D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */ = { + isa = PBXNativeTarget; + buildConfigurationList = 24D2795D8F0CD51BF55E56300305D520 /* Build configuration list for PBXNativeTarget "GTMSessionFetcher" */; + buildPhases = ( + 64FB4A070FE69092F995B324535EE1CD /* Headers */, + BA3F18D8054F9424D16EBE9F754B1D33 /* Sources */, + 6DFC5CD58BD6F472325388D88D9BEC06 /* Frameworks */, + 8EE268F1AE808B2FDE18620B512331E8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = GTMSessionFetcher; + productName = GTMSessionFetcher; + productReference = C1998E0D8085221AD87F89B614C10E52 /* GTMSessionFetcher.framework */; + productType = "com.apple.product-type.framework"; + }; + D85855245F43DA2357E1ACB718D90A83 /* Pods-PediatricPancreas_Storyboard */ = { + isa = PBXNativeTarget; + buildConfigurationList = BAFA5C83AB0CDCC9BA34BC51A139E08A /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas_Storyboard" */; + buildPhases = ( + 39F8F432763BFB98AA46683A2BBAE9E4 /* Headers */, + ACBC784717BBCFB7D766166842014178 /* Sources */, + 38940F714A6BBC8ADACEC78C9E0F6C08 /* Frameworks */, + FCA3CEE9E03C1A5A4BE856C74EC723B8 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CA5E0339DA3600E7FB763F21E4E73FEC /* PBXTargetDependency */, + 6BA2A77691CB0EEA88ED8BE8959A9DDD /* PBXTargetDependency */, + 4B0280ED443E4105B0F74A01307B6D77 /* PBXTargetDependency */, + D609E0FC3D6721F31074E7F96C0AE5AB /* PBXTargetDependency */, + 0D29A89C5DAC454618B12E00BDBD2632 /* PBXTargetDependency */, + D16E7F58277EAC7CA5A95C501A241C61 /* PBXTargetDependency */, + 9C82163FC3CE0DEE1BE0442F316B33BD /* PBXTargetDependency */, + 97F03936455A9DF9B4EB04AA12D8694E /* PBXTargetDependency */, + 82DFBB6FEF2022C3BE7AFC2B610D9A12 /* PBXTargetDependency */, + 2A3BDD43D5A45C1A60ADB5375C11778E /* PBXTargetDependency */, + 322DBC40CA7E8C7D2E5E0A4796B2931A /* PBXTargetDependency */, + CCBDE497A6FDAF6354877D3AAB567D13 /* PBXTargetDependency */, + B3DB3D3F27A267C9C875FD116794DDE3 /* PBXTargetDependency */, + 8F09C9C3DCF2A725DAA3AC31B490D59D /* PBXTargetDependency */, + DB3CCB71E60713D4C3EB2E8FFF66CB43 /* PBXTargetDependency */, + 7F6533FBEFAB1FD4B4F8F6129EBA9AB9 /* PBXTargetDependency */, + 05AE9896B6FA444CBD262AF59758CFA0 /* PBXTargetDependency */, + 3C266BA114E5AFBB9BEB3508D6850C0E /* PBXTargetDependency */, + ); + name = "Pods-PediatricPancreas_Storyboard"; + productName = "Pods-PediatricPancreas_Storyboard"; + productReference = 35857822AD1FB3F14370669224C71326 /* Pods_PediatricPancreas_Storyboard.framework */; + productType = "com.apple.product-type.framework"; + }; + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */ = { + isa = PBXNativeTarget; + buildConfigurationList = C850296960BD9D89C4BE51F8477758E0 /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */; + buildPhases = ( + 8AE47766464C0F45BC7D3ED9AAE038DE /* Headers */, + 6ECE5BD9BE75988C2A8DFC3467195514 /* Sources */, + 912C1C624B98DDAC060EB8D5447D68DA /* Frameworks */, + 9D69D0FC15600D07950F48AEBFAA14C4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + C4EC67DE16EA797742AE1FE64F5CF5A5 /* PBXTargetDependency */, + B530F916027C62FD2202E49BD69F33FC /* PBXTargetDependency */, + ); + name = GoogleDataTransportCCTSupport; + productName = GoogleDataTransportCCTSupport; + productReference = 6942351307BC1F54575D9853307EAE0E /* GoogleDataTransportCCTSupport.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BFDFE7DC352907FC980B868725387E98 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1100; + }; + buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CF1408CF629C7361332E53B88F7BD30C; + productRefGroup = E20D525EB57DB63AB9F154BE4F6DCB9F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 072CEA044D2EF26F03496D5996BBF59F /* Firebase */, + C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */, + 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */, + 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */, + 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */, + 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */, + 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */, + 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */, + 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */, + 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */, + B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */, + 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */, + F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */, + 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */, + D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */, + 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */, + D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */, + D85855245F43DA2357E1ACB718D90A83 /* Pods-PediatricPancreas_Storyboard */, + 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0DD38B51F69D00C3A017FA32BD65AAE0 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 193870DE0E39C0BA224177A2778E38F9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2979593BBAB5AE2DB9B63147A0F0EA68 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 3980B9177A1276BF9B0931F27A18966F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4A49114767A76EAB587D177AFAD26BB8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5C58FA40F48BC4E272331FED72E25C1E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7A57BEC9019F065C6C145B716B3D4BDC /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8EE268F1AE808B2FDE18620B512331E8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9D69D0FC15600D07950F48AEBFAA14C4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A61A5770BCADF1284C16BE3B3F15C01F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D6125F35E0F31207374E266D39708782 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBAD5C2862084247C35AB177D3CA1011 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E2A7C24E8F497788AA5FBF7B75914EB1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FCA3CEE9E03C1A5A4BE856C74EC723B8 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1394197F4BCDF01B34242E82093E6F59 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E9BC50FC3603B8FF93D78C2A62983D54 /* nanopb-dummy.m in Sources */, + A8FEF73E60F905C4CFEF7963E5444AF4 /* pb_common.c in Sources */, + 8EB89BB70E30C5A3FAF63B1326E5472C /* pb_decode.c in Sources */, + BEC63CA25DAB47C32BD3889AD9D2DB59 /* pb_encode.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 37E5D09D029789FBBBC4B82A68C66D23 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1359391BAB507E711118506EEA347792 /* GDTCORAssert.m in Sources */, + 7A32E72F51ABC1E99CA736FB19DEED4F /* GDTCORClock.m in Sources */, + E3CD894872245BDD43B912BBC60BCEC1 /* GDTCORConsoleLogger.m in Sources */, + 8DD54A0A7E8E133E8156363E96698995 /* GDTCORDataFuture.m in Sources */, + 9206BDCA1DD50E2745D33A92D4E40078 /* GDTCOREvent.m in Sources */, + 3A2588C2516C334C381160C8F7CF6C02 /* GDTCORLifecycle.m in Sources */, + 6B44AB74D808DA88A581A5AC33E8F816 /* GDTCORPlatform.m in Sources */, + 5426CFC847A5503F3DAD8883148156CC /* GDTCORReachability.m in Sources */, + C7A0CB2A71F338ACD6FB638CA44FD03C /* GDTCORRegistrar.m in Sources */, + 315136729DD55A92945D3852BDFFD1A6 /* GDTCORStorage.m in Sources */, + E42A0E8B4190A2236B8FBCAE5213E56B /* GDTCORStoredEvent.m in Sources */, + C45F8382F9374D3B1FA2FA441A672268 /* GDTCORTransformer.m in Sources */, + 102E4DC6BEF70142E938F9FFDB50C4B3 /* GDTCORTransport.m in Sources */, + BB706CE15895A0E5263D2EC37F7B4964 /* GDTCORUploadCoordinator.m in Sources */, + 8E60130359B0DAD32D6767B2527446ED /* GDTCORUploadPackage.m in Sources */, + A2D1C41371A0266897AF7AF98812091B /* GoogleDataTransport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 517C22992560BEC4B4AD39CA654B663B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BEB60C0A059ED0DDACE9B3E66B355AC7 /* FBLPromise+All.m in Sources */, + DC813E9A9C54EE937F0EBB7894ACD47F /* FBLPromise+Always.m in Sources */, + 0732D22C3FDE4D4294A9CAEA66F17E75 /* FBLPromise+Any.m in Sources */, + 196A5C196E931158F2688B37E9DF1636 /* FBLPromise+Async.m in Sources */, + C9A8B33C6517A73354D4488B13E64B57 /* FBLPromise+Await.m in Sources */, + 8C48DE58B885ACC442E2445ED473136E /* FBLPromise+Catch.m in Sources */, + 55F0FB83F68D1E59A1050B6FC9CAAB19 /* FBLPromise+Delay.m in Sources */, + E96E4B5E3B8024E8BC9C40948616F733 /* FBLPromise+Do.m in Sources */, + 8423C55527E64F1812D09786125FA512 /* FBLPromise+Race.m in Sources */, + 398105E314BE7A83BC79BA999C80DF87 /* FBLPromise+Recover.m in Sources */, + 2A0D2FAC556850D1B71AE2236FBA3DF9 /* FBLPromise+Reduce.m in Sources */, + BBB5066022594C5799922EA073C8DFFC /* FBLPromise+Retry.m in Sources */, + 2DF33B70B48CB3417592B1DF55646C03 /* FBLPromise+Testing.m in Sources */, + 7C26BC19A31C575E1EAC07AFC2185CE0 /* FBLPromise+Then.m in Sources */, + 611280146682FF4A88AC71242A8D847B /* FBLPromise+Timeout.m in Sources */, + 4CEC7F97E23B73C3EB8467874BDFA4D4 /* FBLPromise+Validate.m in Sources */, + F68BCE89AE6C3311B11C34A92D43D21C /* FBLPromise+Wrap.m in Sources */, + 437562A81373610965061FB53F6EACEB /* FBLPromise.m in Sources */, + EA936B59DC28C23ACF1CBE125E7718C1 /* FBLPromiseError.m in Sources */, + 3ECF1A24ADBC31B4997C5636A5AAF429 /* PromisesObjC-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6970BD69C589CD3E4F9A67139ED66C18 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 93B51015B2568DF742D1ACF5C00D18AC /* arena.cc in Sources */, + 7F316A45604FD022592B46CBEC961866 /* block.cc in Sources */, + 3AE1866EB63A6C5123188B3247410DB1 /* block_builder.cc in Sources */, + 1E7F94DC9E3ACF6E735E9A4F1A8DB008 /* bloom.cc in Sources */, + B8A89FC9B89E6A1A2AC7FE5646986CED /* builder.cc in Sources */, + 358009462CC96D360C81CDAA2A19551E /* c.cc in Sources */, + 617C26FE86E7F5425C186DDC8DA00B15 /* cache.cc in Sources */, + 7E008C50A7A20243444C7B15BA138089 /* coding.cc in Sources */, + E0454F4406F2F6D99F67B5BB7714F6A7 /* comparator.cc in Sources */, + C5615055335733CDDA1F38C5F1FF18F8 /* crc32c.cc in Sources */, + 9FE2088DC595663A06EC17EF66921A26 /* db_impl.cc in Sources */, + 9E2135C68E192F65B64295066DD70718 /* db_iter.cc in Sources */, + 6264181DB03AD90251373D451D9C4A9E /* dbformat.cc in Sources */, + F9C8C5887422C8EED02F764349DF5F6D /* dumpfile.cc in Sources */, + D4F6BA0702DA90CC376ADAD732BA71EC /* env.cc in Sources */, + A54B91653824B62CC3957DC96367BEC0 /* env_posix.cc in Sources */, + 4CA25B9F5EFA8065AC1646679E2B8E95 /* filename.cc in Sources */, + 6D39CB536BCCFACE41951751224E0689 /* filter_block.cc in Sources */, + 1B818DAFB27BFE8532E60E85BEC640EE /* filter_policy.cc in Sources */, + 2C2C69EBEBBEFDFC9AA4E8162CAF8837 /* format.cc in Sources */, + 00DCAA7573F2E72B6199CBA90FB95947 /* hash.cc in Sources */, + 5FB7F6B417571F24C0A9137648949A3A /* histogram.cc in Sources */, + 6D8FB3307C967E413C09377B65D95CC0 /* iterator.cc in Sources */, + 63AC718F66B67F519CECD7642CDA616B /* leveldb-library-dummy.m in Sources */, + C9CA958CEA35B968BECF9CD99C750F0F /* log_reader.cc in Sources */, + 0E98FAFC4AEF3E2FB107970B36F82F6D /* log_writer.cc in Sources */, + CAC96738E23FBDAE61A6D00359F9DF67 /* logging.cc in Sources */, + B7A60B75838E75A34495A209BC8B5BB5 /* memtable.cc in Sources */, + E2795A9FB59C5E9E8ACE0A0274C7FBEE /* merger.cc in Sources */, + 6BDD887158AE7BF5C19A11D3A676B54C /* options.cc in Sources */, + ABAD09E66DF0EBBFEAEEA73AF38EA7F2 /* repair.cc in Sources */, + 025D8975E3F1E0454C78740B08AD63C6 /* status.cc in Sources */, + AC4C9808D241DB5569DCA5E06F982427 /* table.cc in Sources */, + 7FD12F99349D882E8A5C0553F5B42C30 /* table_builder.cc in Sources */, + F43B7DCFE0826550D972986707BDDCC4 /* table_cache.cc in Sources */, + B8F556A9D5941E43CBF644F49E241585 /* testharness.cc in Sources */, + 4076E700A4E56EA44F916A6EB5B38A84 /* two_level_iterator.cc in Sources */, + C047E8F3590D88BEA7EE7169952A8667 /* version_edit.cc in Sources */, + 8F4A47BFC891AD3DDC3E4DFFB0F25046 /* version_set.cc in Sources */, + 32C50B96E226768D3B378336BAEFBB22 /* write_batch.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6ECE5BD9BE75988C2A8DFC3467195514 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2CDE72E87C681B0410BE868E185CAC7E /* cct.nanopb.c in Sources */, + E67063C0F04726CC695F621A05097687 /* GDTCCTCompressionHelper.m in Sources */, + 0AE086F148587D4383DC19E9E74F0903 /* GDTCCTNanopbHelpers.m in Sources */, + 22DF9946B451F1077BCACEEEF6876E75 /* GDTCCTPrioritizer.m in Sources */, + 3F7F40A4E72679DFFADB6A15450889BB /* GDTCCTUploader.m in Sources */, + 13BB66DF5376B6E63B7E853B990A138E /* GoogleDataTransportCCTSupport-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8DA11696A35204F4C333FF5955724597 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 44EFB4D00D62857239E5571903BD9164 /* FirebaseInstanceID-dummy.m in Sources */, + 9D9E041AF29679CF41A433513A059BBA /* FIRInstanceID+Private.m in Sources */, + B8521AD66344AF93B35758605EC7FADE /* FIRInstanceID.m in Sources */, + 38C7DD9B9C431DFE0F2B0A5D77EF7CEA /* FIRInstanceIDAPNSInfo.m in Sources */, + 6FE410A6F9FFBC77EF8FD39F34C8EDD3 /* FIRInstanceIDAuthKeyChain.m in Sources */, + 45A6DAD4056F205353651CF50A58587D /* FIRInstanceIDAuthService.m in Sources */, + 1B0D9DCD481F94F72089297BA93C6B67 /* FIRInstanceIDBackupExcludedPlist.m in Sources */, + CC2C0BE45973FC0CAAB0EA0DD82C68E1 /* FIRInstanceIDCheckinPreferences+Internal.m in Sources */, + D13AE8C940F401A4565B7ACFA42AED8E /* FIRInstanceIDCheckinPreferences.m in Sources */, + 3D277E51CC2EC71690121326D17C4A2A /* FIRInstanceIDCheckinService.m in Sources */, + 5396B23C3E969FCB53609C6D08E46F57 /* FIRInstanceIDCheckinStore.m in Sources */, + D9BFE6EE614608A3B9CA2C16403EDDA3 /* FIRInstanceIDCombinedHandler.m in Sources */, + E624E062F40F024B87C07635FD7F8337 /* FIRInstanceIDConstants.m in Sources */, + 0E2CAB550C7C03046C52A839DF6EC0CE /* FIRInstanceIDKeychain.m in Sources */, + 9D2487DE9D41A0BE0F8ACAB14237F697 /* FIRInstanceIDLogger.m in Sources */, + D1844E585A85E6C0B99654FBA152382E /* FIRInstanceIDStore.m in Sources */, + BC4C1C862D2EF427A6162317ED9E91A7 /* FIRInstanceIDStringEncoding.m in Sources */, + 1937D86D43A9560AD0794EC916807251 /* FIRInstanceIDTokenDeleteOperation.m in Sources */, + 9535F67513B537D39075DCC8B40769FB /* FIRInstanceIDTokenFetchOperation.m in Sources */, + A6DA65E484EF41CA534C9708A78B99F2 /* FIRInstanceIDTokenInfo.m in Sources */, + 6BF7ECEF7DD61561B78479955CA2D7C4 /* FIRInstanceIDTokenManager.m in Sources */, + 1F509E54D03B15D90FD2699E7B69F858 /* FIRInstanceIDTokenOperation.m in Sources */, + 2C4910AD5EBA5BBFD3E42C2B2EB8C377 /* FIRInstanceIDTokenStore.m in Sources */, + 9E8737109FCEF2E5CC22B402CA17C9E8 /* FIRInstanceIDURLQueryItem.m in Sources */, + DE76C40DF0294BB958BB87675C02DDF9 /* FIRInstanceIDUtilities.m in Sources */, + E836BAF8C30B308B105A4396A775B39F /* FIRInstanceIDVersionUtilities.m in Sources */, + E88676E726AD5E95AEF7070FFAD60660 /* NSError+FIRInstanceID.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 973567BB59AABEA876FA3149B844D671 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D7B2568B93A8855C75A2D9893CEEE396 /* FirebaseStorage-dummy.m in Sources */, + 010792DD347E0305A235B9C4E6FEA68C /* FIRStorage.m in Sources */, + 6D1DC4625B27B6BFE18191C504247BF4 /* FIRStorageComponent.m in Sources */, + 4033DFF8E46CBFFA88DBF899FB5E492B /* FIRStorageConstants.m in Sources */, + 6F04DC3872A339A319A349E083F9165A /* FIRStorageDeleteTask.m in Sources */, + 10DDD967508DB60F26789B27F9FE68C6 /* FIRStorageDownloadTask.m in Sources */, + 90001814C0232EA9ED085F1CE470B8B4 /* FIRStorageErrors.m in Sources */, + E018635E49B5FD51E549A42412B1007B /* FIRStorageGetDownloadURLTask.m in Sources */, + 5E63FCAFBC2EDC9E57641148C54B1D38 /* FIRStorageGetMetadataTask.m in Sources */, + 171830EFC97DEC7EE70B0C57EC31F4C5 /* FIRStorageListResult.m in Sources */, + 03AA8E00CA6CF9C1D534409AAEA8248A /* FIRStorageListTask.m in Sources */, + 3D94213C2542294E0672EF0F2F0A4B35 /* FIRStorageMetadata.m in Sources */, + 6ECC2775AAB5390B970C817987859232 /* FIRStorageObservableTask.m in Sources */, + 3581AD2D8C42D39B9E8B27FA7E09FDA5 /* FIRStoragePath.m in Sources */, + EA56A5F2CCC146B819B9B021B73B664C /* FIRStorageReference.m in Sources */, + AA7C495E4999B5D171B45257EB2B6F67 /* FIRStorageTask.m in Sources */, + EB096D368174CCECCF0D2BA36D208B37 /* FIRStorageTaskSnapshot.m in Sources */, + 253A920BEB214305408903AB0189C6BB /* FIRStorageTokenAuthorizer.m in Sources */, + A7D220511D6C7F7540F0C91FC006034C /* FIRStorageUpdateMetadataTask.m in Sources */, + 0C2659EFC2C3CA756799555B3328CEAD /* FIRStorageUploadTask.m in Sources */, + 54BD58C6F92DE47237137A8131805FFE /* FIRStorageUtils.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 9C8FFCCE80B105DD7D4E009AB663C334 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF5FD6EFE83C8F4C8B2A868E7393CAEA /* FIRCoreDiagnostics.m in Sources */, + 408E7890B97BFBE9E46C9442755E4F64 /* firebasecore.nanopb.c in Sources */, + 9D884E628C4EC58605210B17D77C29EA /* FirebaseCoreDiagnostics-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + ACBC784717BBCFB7D766166842014178 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB7C479F3F90C663B612A3B28927DFC9 /* Pods-PediatricPancreas_Storyboard-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AE07BD1A6297D05645694748BDFC6C5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 142699BB466888EC9B27EFB78553EE7D /* FIRAnalyticsConfiguration.m in Sources */, + 77BB721CAEE12F5B4CCFBB723F3F8D3E /* FIRApp.m in Sources */, + 2E588B234A541C10B722D4B202171008 /* FIRAppAssociationRegistration.m in Sources */, + 0881B956B8D20DD2A321A5CC092BE414 /* FIRBundleUtil.m in Sources */, + 3A464EE1239B1FABEE1C1C95D22D602C /* FIRComponent.m in Sources */, + B259A3DCF44B88A9BCA0300A484EAD8E /* FIRComponentContainer.m in Sources */, + AD40A049FBE7ECCA46352FD95416072E /* FIRComponentType.m in Sources */, + 1B03F07008EE89B438D451D5B714A322 /* FIRConfiguration.m in Sources */, + C669DCFA7234B9F5B49D19B003F14F57 /* FIRCoreDiagnosticsConnector.m in Sources */, + 3362488F496054F89AA6F18A09C54436 /* FIRDependency.m in Sources */, + B1EBC26487152BC48AA9A05C66576947 /* FIRDiagnosticsData.m in Sources */, + 21A0EA0EB2E7348BA2EAD78CCDE9577D /* FirebaseCore-dummy.m in Sources */, + 4155F20106954F206FDF73C397087801 /* FIRErrors.m in Sources */, + E818EDB2D704D61FE5704437DEDADB2C /* FIRHeartbeatInfo.m in Sources */, + 9BFAFB9A249CD946F01A580004125ADF /* FIRLogger.m in Sources */, + AA22B314F3365FA8BEAD68BEEFA0D6D7 /* FIROptions.m in Sources */, + 8DAFEABBEABD44FB7ADEE290940C1B4A /* FIRVersion.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BA3F18D8054F9424D16EBE9F754B1D33 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 27655880FB0469AAEF29271BE07CCE25 /* GTMSessionFetcher-dummy.m in Sources */, + DA2F583B9ECE9612978CB7347B1372C8 /* GTMSessionFetcher.m in Sources */, + C5D55C124298CF890A5B11A04B7DA7A6 /* GTMSessionFetcherLogging.m in Sources */, + B16532AB9D0FB86BE4CF3D9E86209D51 /* GTMSessionFetcherService.m in Sources */, + FD00057352D62F190E3FF7E0C2B7CB9F /* GTMSessionUploadFetcher.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BFF9856820EEA5FC6B863518ED9B1135 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A7F60C5B2674E51F045AD6FE27970891 /* GoogleUtilities-dummy.m in Sources */, + DD1A73622491FB1154B58CF81AC7635E /* GULAppDelegateSwizzler.m in Sources */, + A1B2114FED012572E978166C217EC8E8 /* GULAppEnvironmentUtil.m in Sources */, + AB69509E8F7A9D7413D1CCA245838A8A /* GULHeartbeatDateStorage.m in Sources */, + 7BAC15E35BC888DFC0317FCC5526FDB8 /* GULLogger.m in Sources */, + 5866936362B3EE71506D896DE44AB839 /* GULMutableDictionary.m in Sources */, + 65EE2706CAA882AFD22DA82ADA09F30B /* GULNetwork.m in Sources */, + FC95DD1B5A91CBA5DD357F64654159EC /* GULNetworkConstants.m in Sources */, + 38E416BDCA44F349F2293244CBB090C3 /* GULNetworkURLSession.m in Sources */, + 5E3A76525152956B8F0923A9A49AEC18 /* GULNSData+zlib.m in Sources */, + 9309FAF9DD702689F43B7191CEE212DD /* GULReachabilityChecker.m in Sources */, + 1C8F050A8A53777613A0A58D5C229155 /* GULSceneDelegateSwizzler.m in Sources */, + C119D47F74B1B6FCDFF11594BB63AC42 /* GULSecureCoding.m in Sources */, + 4E70FCDE9B19C1D1B77CC230F816881C /* GULSwizzler.m in Sources */, + BF1B710E5D6EF9B26D5AF0E33D6A6D35 /* GULUserDefaults.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + C2F556D948FAFF27B997C28AA938FFCA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A2307117BA50B6FBEBDCC55F89D227A4 /* APLevelDB.mm in Sources */, + 89BB95047C61758DBCCA8439385D59DF /* FAckUserWrite.m in Sources */, + E5A77EE1434FF9ABCE6726072B416E7D /* FArraySortedDictionary.m in Sources */, + 0D35668137C9AA24B5FA0D7704E66D5A /* FAtomicNumber.m in Sources */, + 77C86F8FC541A60AE065CDB0CD90DAB6 /* FAuthTokenProvider.m in Sources */, + 464D0D77EE026481403D5C592D0396B1 /* fbase64.c in Sources */, + 9A861EE27F9EE8D8F08D283949432631 /* FCacheNode.m in Sources */, + 257A76BC89A5C8BA63DE013722BEA0EA /* FCachePolicy.m in Sources */, + E51F20C7985E6AB9FAAB08BACEFFED9A /* FCancelEvent.m in Sources */, + 836C8C9A7F2C37E14C32D26657A691E4 /* FChange.m in Sources */, + BD8B9318417E3C24B6E108A1245D1FCC /* FChildChangeAccumulator.m in Sources */, + A77CF7F275FD69E4BB4E021F418D74B5 /* FChildEventRegistration.m in Sources */, + 083769BEEFB26C5A674C30D07FF86B1D /* FChildrenNode.m in Sources */, + 89E522F7F84341756DEBB135DC9BEEC3 /* FClock.m in Sources */, + 63AA601F2B6A0FD6D0D55CB4E5E5DC95 /* FCompoundHash.m in Sources */, + 280200E7B69674B99F7932BDFD44EF34 /* FCompoundWrite.m in Sources */, + 65DB3742B1FB346721CD46295FB4AF00 /* FConnection.m in Sources */, + 8536B41B796BE0AAB0DF4BF6EA085E33 /* FConstants.m in Sources */, + AFAAF7F17169821F3881DBC0250EB51C /* FDataEvent.m in Sources */, + 79F4BBA63390241FCF5FFBDB16619173 /* FEmptyNode.m in Sources */, + C7C7C8A4A99E2C549BC4E20490093F89 /* FEventEmitter.m in Sources */, + 64BF7813913EC822B81A1D601FE9B6A9 /* FEventGenerator.m in Sources */, + 8C5E5F02844ABAAC171F730D03F792D1 /* FEventRaiser.m in Sources */, + 14421D05135873CE794E99DF30AF1720 /* FImmutableSortedDictionary.m in Sources */, + DC66204BDCAEAABE6F58AD23B812E21B /* FImmutableSortedSet.m in Sources */, + 835B3D8377DA5D3D63555ACFF87668B1 /* FImmutableTree.m in Sources */, + 62CE493C8B6E576B498D90F1D68508AC /* FIndex.m in Sources */, + 1D311F38B7A23ED9154B53473F1F649D /* FIndexedFilter.m in Sources */, + 4B744F7ECEDDE138738E97A0BF826C72 /* FIndexedNode.m in Sources */, + F6237E72428D8021D2B69E8E71A9EC8F /* FIRDatabase.m in Sources */, + 9C48553D8F15E59701336C838B13432C /* FIRDatabaseComponent.m in Sources */, + DD18C482342841FE2C0F62FBD342AAE3 /* FIRDatabaseConfig.m in Sources */, + F597291457E81538D19FEC0CAFCF6517 /* FIRDatabaseQuery.m in Sources */, + F9FC09F7E6F71FE9C3562FD0E5ED9B02 /* FIRDatabaseReference.m in Sources */, + 3580F08EEC9D7B182B8D3C2C7AEB5F53 /* FIRDataSnapshot.m in Sources */, + 651FC1165EF2D33C3AB5A81D21975147 /* FirebaseDatabase-dummy.m in Sources */, + A06DFFAB0A1C8E35A6C18FF78EA37507 /* FIRMutableData.m in Sources */, + 7239A5C21F6059BF4A0A776DCA9F4D26 /* FIRNoopAuthTokenProvider.m in Sources */, + CC3676812D759C6FD587820C0DBC0C6B /* FIRRetryHelper.m in Sources */, + B69E623E913DC7FC77990E74DDCF127B /* FIRServerValue.m in Sources */, + 08E13FE7C0331833F8C5BD5B8A07E338 /* FIRTransactionResult.m in Sources */, + 41AAAF78EC837E65D5B3C48EEFB67C31 /* FKeepSyncedEventRegistration.m in Sources */, + 788511937056976C5DA219C6D9EB7399 /* FKeyIndex.m in Sources */, + 7B127A8E52CC4BF993993F92D54891EC /* FLeafNode.m in Sources */, + 903338B5CBC6007A0BA72F31B656B955 /* FLevelDBStorageEngine.m in Sources */, + 5523D52C1C9FF280A9221352558C19C9 /* FLimitedFilter.m in Sources */, + E442CE0E937527C6C747AB5E4C78C9A4 /* FListenComplete.m in Sources */, + 07D22076FA861D0AA49401ED247A611B /* FListenProvider.m in Sources */, + AE9269076F92047F499E33896427FA3D /* FLLRBEmptyNode.m in Sources */, + D29A6B422C3BBB02E8C924045E2FACF5 /* FLLRBValueNode.m in Sources */, + 974010B0CB603F4B3082B6B5A73BE9BD /* FMaxNode.m in Sources */, + 7691C3FFA1093E1F9E79603A447BBC68 /* FMerge.m in Sources */, + 76B36E894C14C5C660C25E14AE5C7DD5 /* FNamedNode.m in Sources */, + 3696262C419108CACCDD9678138D4E2C /* FNextPushId.m in Sources */, + 4F63EAB5E4D8EB05103553ADFDBD156B /* FOperationSource.m in Sources */, + 883F2A60B72F776412EED0A7A31D90C1 /* FOverwrite.m in Sources */, + B85351E2EA1547BECBAA42B92CCE35E4 /* FParsedUrl.m in Sources */, + 47BA6C0FE17DF42A04CFF844FA404F4B /* FPath.m in Sources */, + 4FEA2D42A189500203A2670FD24927C7 /* FPathIndex.m in Sources */, + A8D0E460F9516ECD96C2EE6C62E639D8 /* FPendingPut.m in Sources */, + 716DCD5041771292E3BA4E2CD8BD9920 /* FPersistenceManager.m in Sources */, + 729CF00271D19B1F36AD1C9C8DDF3E17 /* FPersistentConnection.m in Sources */, + 7B6D2BB37EE995E561AA9B370AEF8E6B /* FPriorityIndex.m in Sources */, + 3CA6B5EF1BAB325870F6A25AEB4F900D /* FPruneForest.m in Sources */, + C3E2919B411BA3CF158348803AF1E82F /* FQueryParams.m in Sources */, + A87F1BB8D6C296793793F7BCFE722B30 /* FQuerySpec.m in Sources */, + 30880DC7962C6AA2C76F741A56A08BC5 /* FRangedFilter.m in Sources */, + CC08E6C4FFD5413612BE1D7ED3CE22EF /* FRangeMerge.m in Sources */, + 771FBA17F31F0043FEED1CB08D033837 /* FRepo.m in Sources */, + FD5CDA516E0C702C5630EC560E660F4A /* FRepoInfo.m in Sources */, + 81BAAF16E2B0900842FDAD09B244AA53 /* FRepoManager.m in Sources */, + ACBDD6FAC6B0779840C1A49EF7DF9786 /* FServerValues.m in Sources */, + CCE70E7976B3859DDC23F2F06C5B54F3 /* FSnapshotHolder.m in Sources */, + 6D66F6C94E918A2AD882B2BD89AB90DB /* FSnapshotUtilities.m in Sources */, + D67D3C6167A627C95BF7B1BAF6193B0B /* FSparseSnapshotTree.m in Sources */, + 820E1890ABE1688D89211D1BCAFDC337 /* FSRWebSocket.m in Sources */, + 24FA01B81F00742983794A0AC9163FA9 /* FStringUtilities.m in Sources */, + 6048CA58D8139DDD0235A6684C4AEDD5 /* FSyncPoint.m in Sources */, + 78FABE98809E7FB98D45AC121BD4A5FD /* FSyncTree.m in Sources */, + 75CC6F9BE2575EFC85A4C1993BF5CF3E /* FTrackedQuery.m in Sources */, + 70EC18ABF46391ECCE28724F51F764C7 /* FTrackedQueryManager.m in Sources */, + E1EEFF5D8FBFE19F70F73FA7AB89256F /* FTransformedEnumerator.m in Sources */, + 847EBAF530456EA7D8E8D15C25C06E32 /* FTree.m in Sources */, + A757314004034116D9AB766F51CF4348 /* FTreeNode.m in Sources */, + 63FE55F9EA99D118FFA3AF34724D1424 /* FTreeSortedDictionary.m in Sources */, + 9FCA6A53EB43D6322A186258C68EDCB9 /* FTreeSortedDictionaryEnumerator.m in Sources */, + BA027134643F044506DE83C5A75EB3C3 /* FTupleBoolBlock.m in Sources */, + 0CFD4F9A80FE920A92C46ED090AF8ECA /* FTupleCallbackStatus.m in Sources */, + B620561754FCF5F73A5B8BBE59AE6F87 /* FTupleFirebase.m in Sources */, + 8958E775CB1D33AE4F5BDF52724797A1 /* FTupleNodePath.m in Sources */, + 1F586133C4EB98DE288A2A66763DC9D9 /* FTupleObjectNode.m in Sources */, + 8A1B6697EA2803700F481934EE104EC3 /* FTupleObjects.m in Sources */, + B4B0C9ABA908C556FE701D3A72D68EA6 /* FTupleOnDisconnect.m in Sources */, + 8B03BA58C638AE48CA4E8B2C4C5A2792 /* FTuplePathValue.m in Sources */, + 63AB79587BC1351662D4CB4E12D415A6 /* FTupleRemovedQueriesEvents.m in Sources */, + 828E420D4531AA888F5A39A2F2772157 /* FTupleSetIdPath.m in Sources */, + DAB3FB4565600539E11B01572756D2E2 /* FTupleStringNode.m in Sources */, + D241681D6846AAAA94E6E1C3D3EBD9E6 /* FTupleTransaction.m in Sources */, + CC58E23726F7AE4F75A3C61B793A2831 /* FTupleTSN.m in Sources */, + 1900A31A09DBAD658619229902EA43AB /* FTupleUserCallback.m in Sources */, + EE265235E6C44A2B23C94F458ECCC8FB /* FUtilities.m in Sources */, + 6E636ED7B4C86C1B187091AB9E2C8A6C /* FValidation.m in Sources */, + C435E0AAAADD2B845ED62B61CA942AAB /* FValueEventRegistration.m in Sources */, + AC115DD8776F1A81B040F1084312D550 /* FValueIndex.m in Sources */, + 6F1FB5DC371A0D21F7C10CEDC7B2FBB7 /* FView.m in Sources */, + 0FE7F31E7E8B2FAE647345833AEFD58B /* FViewCache.m in Sources */, + 76E075F0176E4F265A079A009D059A04 /* FViewProcessor.m in Sources */, + FA2671747739AA8D4B2A91A6E8B98ABC /* FViewProcessorResult.m in Sources */, + CFED822B928298F5A0E727674813A92D /* FWebSocketConnection.m in Sources */, + EE7BB1E13A26E35B39ADFC7D4B56D80D /* FWriteRecord.m in Sources */, + 6B5D9858B70EF1362BD676748C27733F /* FWriteTree.m in Sources */, + 94FC8A0E6D527D341B830E9639205039 /* FWriteTreeRef.m in Sources */, + CD9A6E834DBDCB1929D472C0C5079A08 /* NSData+SRB64Additions.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + EA1850AF31138B7ED7EA7DC10B7AD94C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2736216E519666F7310B417759A98AC8 /* FirebaseInstallations-dummy.m in Sources */, + B2F841F93A8850DF98625D0BF618D259 /* FIRInstallations.m in Sources */, + DB957918731AA083B784B9C7FC626F6E /* FIRInstallationsAPIService.m in Sources */, + 928310BC62D2BEC2CADAB2AA934EE5A2 /* FIRInstallationsAuthTokenResult.m in Sources */, + 89D7BC2FAF21481AFF8D790C0C7E865E /* FIRInstallationsErrorUtil.m in Sources */, + B7EFCCE0D8338C14B9D98A430F183A0D /* FIRInstallationsHTTPError.m in Sources */, + 572DE75BD68F3CC17AF5AD9FB0E93846 /* FIRInstallationsIDController.m in Sources */, + 7120A37D497F8C2742AF0050C46A1811 /* FIRInstallationsIIDStore.m in Sources */, + 6F68B4D340A54874296A0B9717366D33 /* FIRInstallationsIIDTokenStore.m in Sources */, + 677657C55AEF922D9264DC8A794AC66E /* FIRInstallationsItem+RegisterInstallationAPI.m in Sources */, + 1F9AAE2958DC0F59836F2FCA9EB170BF /* FIRInstallationsItem.m in Sources */, + 7DBDD67838022F8D94F82BC4C39DC75B /* FIRInstallationsKeychainUtils.m in Sources */, + D75F1B505F85888AF493B7FF7333F596 /* FIRInstallationsLogger.m in Sources */, + 9244F29221DB1B85A5642637DD3AB19A /* FIRInstallationsSingleOperationPromiseCache.m in Sources */, + 093D16634CD5F0D9BC5DFDA279B7BA51 /* FIRInstallationsStore.m in Sources */, + 6B139E50666884DDA98F39506C31F6B8 /* FIRInstallationsStoredAuthToken.m in Sources */, + 57A3883510AD776AC295A5DA2EDFD46F /* FIRInstallationsStoredItem.m in Sources */, + 46CEAFF362A5F1B66B456B9C235AD7F6 /* FIRInstallationsVersion.m in Sources */, + ADF87CA273D444759D20EA51731A1B90 /* FIRSecureStorage.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 006C0599B322B2A071A0E6BE46C1C90B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = D577790062B5559EF005039852A97DF2 /* PBXContainerItemProxy */; + }; + 00EC45E47078FCC77557A8B4EE533F87 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 750DCA08ECA626D07B691DB359E31682 /* PBXContainerItemProxy */; + }; + 0591622CEB0B7BACBE520F0AF1B238D3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 1963FEB2F2F3883CEAF178DEC2E4ADD4 /* PBXContainerItemProxy */; + }; + 05AE9896B6FA444CBD262AF59758CFA0 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = E230E7D796C9CA44B91416DE1C7D9A92 /* PBXContainerItemProxy */; + }; + 0C87077F1AAEC62E4534092C7FEFF80A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 4886473D196C96F8F1B7553251A3326A /* PBXContainerItemProxy */; + }; + 0D29A89C5DAC454618B12E00BDBD2632 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 62DBC3ED071795C969F8C6006A0EA4D4 /* PBXContainerItemProxy */; + }; + 1C64A6756AFDC641F1613C7DC82CB477 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 0519A6B5FE41B00CC60376A6AA85F241 /* PBXContainerItemProxy */; + }; + 1F1284703AEDC0768BEB2CEB7044CA53 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = E6F12775249208F0E5031C4DBD7CBA3E /* PBXContainerItemProxy */; + }; + 2357AC32539315EA9D953E73978A8695 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = B591ED0C9CF201C628766AFE46C6A8F4 /* PBXContainerItemProxy */; + }; + 26E98BDE443ADA9B9FFB8CA62E2AFC26 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnostics; + target = 620E05868772C10B4920DC7E324F2C87 /* FirebaseCoreDiagnostics */; + targetProxy = 239095B7E773EFC58377C4DECC74846F /* PBXContainerItemProxy */; + }; + 2A3BDD43D5A45C1A60ADB5375C11778E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseStorage; + target = 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */; + targetProxy = 3F371FFFA962F3D07B2A1C57995FF34C /* PBXContainerItemProxy */; + }; + 313210733AE3BC49AEB2F6DD8D94D41C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 30BE08EA5B5CC1196FD7D75E6989C3A9 /* PBXContainerItemProxy */; + }; + 322DBC40CA7E8C7D2E5E0A4796B2931A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = 9770B6A8B0453660EA5B9F94F9CA39A9 /* PBXContainerItemProxy */; + }; + 38DDBCD37A18047DCDF6E7F9BFF6D076 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = 3C5ED0ACF5CB34BC99CDEC9681102C9A /* PBXContainerItemProxy */; + }; + 3C266BA114E5AFBB9BEB3508D6850C0E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = DD135F6A3D57CEDFAFD9519B666ACB61 /* PBXContainerItemProxy */; + }; + 4B0280ED443E4105B0F74A01307B6D77 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = EAABF2C2B122D2438A851071140173D6 /* PBXContainerItemProxy */; + }; + 4B77086EEA306513BFC51FCAD91063D7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = 9861A9465DB23D225E71FC48960CF619 /* PBXContainerItemProxy */; + }; + 5E6C69390453D0B9C226012D5C370A4A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 67D8E91B757D81888ADED8270649CA0F /* PBXContainerItemProxy */; + }; + 60536324D1192BCC2E9F578208E5E286 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 7B9EECB0CE62C0C4FB325BB4FA4BD090 /* PBXContainerItemProxy */; + }; + 64B32BD3F1919B8F0009EC0B5702B96C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAuthInterop; + target = 8EC0F2618965C875A96BFDBEE5D9734C /* FirebaseAuthInterop */; + targetProxy = 0E235A75C7262F1B8D7A216138B30175 /* PBXContainerItemProxy */; + }; + 6BA2A77691CB0EEA88ED8BE8959A9DDD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = A71270B0D0EF2F59141A961F77CE4FA4 /* PBXContainerItemProxy */; + }; + 72D57259FC0744307EA81E16CAC5A881 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = FF454CE06C88D8A46F7DC4DA89084D05 /* PBXContainerItemProxy */; + }; + 75AD11D1386149B1465CBE28285DD48B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = B93D8094B4A53F8AF336876932BD3111 /* PBXContainerItemProxy */; + }; + 7F6533FBEFAB1FD4B4F8F6129EBA9AB9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = 596EB1EB99F8552A8774B47E5E4871EA /* PBXContainerItemProxy */; + }; + 82DFBB6FEF2022C3BE7AFC2B610D9A12 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstanceID; + target = 9E25537BF40D1A3B30CF43FD3E6ACD94 /* FirebaseInstanceID */; + targetProxy = 35F9ECDBCD941C37EE58DD1C3022230F /* PBXContainerItemProxy */; + }; + 87BEF7CCA2828E143F52F4667E385CEE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseStorage; + target = 23E7C4A52360C026F97E4A96D91B03CE /* FirebaseStorage */; + targetProxy = EE6CB9A1D7EF80B05B1AE87404E229CA /* PBXContainerItemProxy */; + }; + 8F09C9C3DCF2A725DAA3AC31B490D59D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransportCCTSupport; + target = F4F25FCAC51B51FD5F986EB939BF1F87 /* GoogleDataTransportCCTSupport */; + targetProxy = B67FB31C218CEFFCA7F96092FC79C92E /* PBXContainerItemProxy */; + }; + 9089FF135822BEE9E10F39594E1EC487 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 4EEA44DD7E76B742438269A75A5E8C30 /* PBXContainerItemProxy */; + }; + 97C3541CC26483F1C17D172C1E8B02BC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 742D6BE3D55B692C13E4BD4360EC7AE7 /* PBXContainerItemProxy */; + }; + 97F03936455A9DF9B4EB04AA12D8694E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = DBDEA060322D6A39A0BA11D8CF8E3535 /* PBXContainerItemProxy */; + }; + 9C82163FC3CE0DEE1BE0442F316B33BD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = 32D6A3B0BFB1FD13F7CB6C0D22A1EEB7 /* PBXContainerItemProxy */; + }; + A86B54826E2EA357A9E4EF0CA7C8D25E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseAnalytics; + target = C49E7A4D59E5C8BE8DE9FB1EFB150185 /* FirebaseAnalytics */; + targetProxy = C7C50420664F1376B8397A84A1DA539F /* PBXContainerItemProxy */; + }; + B3DB3D3F27A267C9C875FD116794DDE3 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = C1186E8393E89C3BF0EFBE8FCF69E168 /* PBXContainerItemProxy */; + }; + B530F916027C62FD2202E49BD69F33FC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = nanopb; + target = D2B5E7DCCBBFB32341D857D01211A1A3 /* nanopb */; + targetProxy = 115550D29A90177B2A9E25D611F0AE12 /* PBXContainerItemProxy */; + }; + BD039C8ABA7EAABF9AB927634EBC0763 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PromisesObjC; + target = 2BBF7206D7FAC92C82A042A99C4A98F8 /* PromisesObjC */; + targetProxy = F09B23A3B28C2C7F222D0313D2E9ACA8 /* PBXContainerItemProxy */; + }; + C4EC67DE16EA797742AE1FE64F5CF5A5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleDataTransport; + target = 5C0371EE948D0357B8EE0E34ABB44BF0 /* GoogleDataTransport */; + targetProxy = A451A85BCCE1A5286398D6E7AD5856DE /* PBXContainerItemProxy */; + }; + C6C3A7AF88127E286F184DC8C1B126FE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GTMSessionFetcher; + target = D676E21115185671D7258A56944ABE98 /* GTMSessionFetcher */; + targetProxy = 57262A096B9144EADF9AC78310B9B344 /* PBXContainerItemProxy */; + }; + CA5E0339DA3600E7FB763F21E4E73FEC /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Firebase; + target = 072CEA044D2EF26F03496D5996BBF59F /* Firebase */; + targetProxy = 3B2519791314D28CBDD44813F64C14C3 /* PBXContainerItemProxy */; + }; + CCBDE497A6FDAF6354877D3AAB567D13 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = C246C5A6CA5187AC9928E031C596A66C /* PBXContainerItemProxy */; + }; + CD72E5EBAD6C41F99E812273DA0391B6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = C043B4C9C448C167FDA0A5D51485905C /* PBXContainerItemProxy */; + }; + D16E7F58277EAC7CA5A95C501A241C61 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 7B02A7C3C437936B9A2619F121D4D8BA /* PBXContainerItemProxy */; + }; + D1B2D249EBE644FE4A399FAD17173251 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseDatabase; + target = 736AF68F6527ACF6B4A4C54728824A1C /* FirebaseDatabase */; + targetProxy = 96A9760A4B0DEEA3CB72F01707497E91 /* PBXContainerItemProxy */; + }; + D584E2A3DB684D97155ACA3F82E1CFD4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCoreDiagnosticsInterop; + target = 5EB4B0B6DA6D5C0C3365733BEAA1C485 /* FirebaseCoreDiagnosticsInterop */; + targetProxy = 32B9D3BE4A4FD98D1A5A9E67B7A878AE /* PBXContainerItemProxy */; + }; + D609E0FC3D6721F31074E7F96C0AE5AB /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseCore; + target = 4402AFF83DBDC4DD07E198685FDC2DF2 /* FirebaseCore */; + targetProxy = 3AA9A0191F50B4235987601396354AF9 /* PBXContainerItemProxy */; + }; + DB3CCB71E60713D4C3EB2E8FFF66CB43 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 118F38B29BC1C109A477C92A35BFAD9D /* PBXContainerItemProxy */; + }; + DC2D61D7B5AAC85EE2082976F195646B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = D7BE435F0D850CBDFE0E7773319DAB21 /* PBXContainerItemProxy */; + }; + E35F8B53FC2222F3A0EF53AA256BAB6C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "leveldb-library"; + target = 9307B7A119490930CF70393AB529AAC1 /* leveldb-library */; + targetProxy = 8ECBD339FFD46206CA2A38035E5D816E /* PBXContainerItemProxy */; + }; + F5BF6546E393C3EE9D02D965B7083878 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FirebaseInstallations; + target = 87803597EB3F20FC46472B85392EC4FD /* FirebaseInstallations */; + targetProxy = F254D49AE2D7E4B01F61AE638C0AB1F6 /* PBXContainerItemProxy */; + }; + F7D3045BF1FAB138CB45DA3751ECDE8B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleAppMeasurement; + target = B53D977A951AFC38B21751B706C1DF83 /* GoogleAppMeasurement */; + targetProxy = 239A22790B2934FA257A90BEAA0DC845 /* PBXContainerItemProxy */; + }; + F90FAE92CE4739886F82CECA40921D87 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = GoogleUtilities; + target = 8D7F5D5DD528D21A72DC87ADA5B12E2D /* GoogleUtilities */; + targetProxy = 8FF2A32E1C7581EAEFEA63B453BD4FAA /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0147BBC64F932E9CCAC117BA5DE96531 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7CA76B59C217CF7E6BB876EF16BA6E76 /* GoogleDataTransport.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 03ECB27795F61AA6A21BFB96301BEDDC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A86D7D56CD84812BBC2847B8B41BB88D /* Pods-PediatricPancreas_Storyboard.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 04E39391EA8B290AD36C550BC8A672F8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4E0CDAA6233B7D55E0DF49497C0476EF /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 07DC5610335182989C3D3607C2F37730 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 29ABCFF3146693410EBE4650CB1C2E37 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0DC744A0E4DA0BBFE51D18B1769FFFCA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 651D975CFB0F58EC635DB69073FC0D6B /* FirebaseStorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage.modulemap"; + PRODUCT_MODULE_NAME = FirebaseStorage; + PRODUCT_NAME = FirebaseStorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0E3E4F868235F19E192F72809F7073F9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ED48C66680CD29C4D2F5DE39F29CAFFB /* FirebaseCoreDiagnostics.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 0F1D0E8B92D4D4B0D9E3724B7A8EFDD2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = ED48C66680CD29C4D2F5DE39F29CAFFB /* FirebaseCoreDiagnostics.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCoreDiagnostics; + PRODUCT_NAME = FirebaseCoreDiagnostics; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 10A7C1338F055874E0A9F8BEC9D995D5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 29ABCFF3146693410EBE4650CB1C2E37 /* FirebaseAnalytics.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 19116AD6B498E9B61C96788E7C65F983 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DAD004FBD9D742F267D2146C5F8D4D6A /* FirebaseDatabase.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1B07F9DB8169FD8F22EF454523CC01BC /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DAD004FBD9D742F267D2146C5F8D4D6A /* FirebaseDatabase.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap"; + PRODUCT_MODULE_NAME = FirebaseDatabase; + PRODUCT_NAME = FirebaseDatabase; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 22C51AAC420439FDA54015FEC3ADD0C7 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 81BB2A12A57AC10B0729222BF61A4E46 /* FirebaseCoreDiagnosticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 29F939C1A1D49DB92860C01B2530A785 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 54B7003E10AD368606F445FE6596D080 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 31880F37E5D3FE2CA6553F3578510668 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 651D975CFB0F58EC635DB69073FC0D6B /* FirebaseStorage.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseStorage/FirebaseStorage.modulemap"; + PRODUCT_MODULE_NAME = FirebaseStorage; + PRODUCT_NAME = FirebaseStorage; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 3A1EC008EBC04E9427469048330E3D9B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 76C1FFB27224C9E18EA9AA2E0B897BC7 /* FirebaseInstallations.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 3E64B50C69B8278283FDA2844560BDD9 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8D2DFCE2D56BFB801722402559090803 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 40CB16FC79D22E785E5DAC4B7C7858CC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 915F579A059A8F18FF02F62D36B4F1BC /* PromisesObjC.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 44D44E934C89E872B4D9A36A225BDD79 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB6496D33D3F05745C5AA89A1BCBF238 /* GTMSessionFetcher.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap"; + PRODUCT_MODULE_NAME = GTMSessionFetcher; + PRODUCT_NAME = GTMSessionFetcher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 496674F8AC9F01A63A2B899851625DE8 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E3D2F5A5F496F3111AF778C077AEB889 /* Pods-PediatricPancreas_Storyboard.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_OBJC_WEAK = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 58CE6E5911C164EADC34EA80E43E252E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE725393C345416026E97A02D28712D4 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 6CEBDF5BD9AD626C5041E10BE87B9FFF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6FD6C19FE120D8553793CC6271F99B2D /* GoogleDataTransportCCTSupport.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 7318FA67CE0085A3852B177D3E9A3D13 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AB6496D33D3F05745C5AA89A1BCBF238 /* GTMSessionFetcher.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap"; + PRODUCT_MODULE_NAME = GTMSessionFetcher; + PRODUCT_NAME = GTMSessionFetcher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 79563F5A26C8052285837F3FC7E380A1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 915F579A059A8F18FF02F62D36B4F1BC /* PromisesObjC.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/PromisesObjC/PromisesObjC-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/PromisesObjC/PromisesObjC.modulemap"; + PRODUCT_MODULE_NAME = FBLPromises; + PRODUCT_NAME = FBLPromises; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 810A03F2A9763A9B8B07C771E4A611A2 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 720B7D4BFAC22CBEB1F9CE8E9D9823FE /* FirebaseAuthInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 8C0AF339BF967DCA8B3E83441B334BE1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3E141DEE77985B8019CF800305A79116 /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 91B83F88F24582D7A8F6B9B89BC2814E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8D2DFCE2D56BFB801722402559090803 /* GoogleUtilities.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/GoogleUtilities/GoogleUtilities.modulemap"; + PRODUCT_MODULE_NAME = GoogleUtilities; + PRODUCT_NAME = GoogleUtilities; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 93653F8EDFA9D0F4935F6E014A3CACD2 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7CA76B59C217CF7E6BB876EF16BA6E76 /* GoogleDataTransport.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransport; + PRODUCT_NAME = GoogleDataTransport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 939F1A8F6BCEB7F9F64D9EEE50CAE014 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 9CD2D5C8734529A37EB394A9B113710E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE725393C345416026E97A02D28712D4 /* FirebaseCore.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseCore/FirebaseCore-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseCore/FirebaseCore.modulemap"; + PRODUCT_MODULE_NAME = FirebaseCore; + PRODUCT_NAME = FirebaseCore; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 9D0CD5DA6C1048B9058AACEAB1670C64 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B82F58D4E27A17968CE2E5A6F072524E /* leveldb-library.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + AEE97645A5F66ED076C63903EE9BDC7A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 54B7003E10AD368606F445FE6596D080 /* Firebase.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B6CBC5FFF92B3CB7920BE04E2B12E694 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C5C92E86E83A2EAD99482570335606B /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + B7B16BCDDA3FC8CE3A1C7625C7482EC8 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3E141DEE77985B8019CF800305A79116 /* FirebaseInstanceID.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstanceID; + PRODUCT_NAME = FirebaseInstanceID; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + BC0BD232913FC861CC1F39D5D2C216BB /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4E0CDAA6233B7D55E0DF49497C0476EF /* GoogleAppMeasurement.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C61FCE3AD7191BBAF217B9D5E3AA8552 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 720B7D4BFAC22CBEB1F9CE8E9D9823FE /* FirebaseAuthInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + CA6178295D258FAB07CACC8B2A69E2AB /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 76C1FFB27224C9E18EA9AA2E0B897BC7 /* FirebaseInstallations.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap"; + PRODUCT_MODULE_NAME = FirebaseInstallations; + PRODUCT_NAME = FirebaseInstallations; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + CAD9769CFFE5F61AE4EEBB12C6591665 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B82F58D4E27A17968CE2E5A6F072524E /* leveldb-library.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/leveldb-library/leveldb-library-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/leveldb-library/leveldb-library-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/leveldb-library/leveldb-library.modulemap"; + PRODUCT_MODULE_NAME = leveldb; + PRODUCT_NAME = leveldb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D2E16E560DD0BD8CBED42592ACE36C7D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0C5C92E86E83A2EAD99482570335606B /* nanopb.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/nanopb/nanopb-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/nanopb/nanopb-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = "Target Support Files/nanopb/nanopb.modulemap"; + PRODUCT_MODULE_NAME = nanopb; + PRODUCT_NAME = nanopb; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + E54127B175FFF628AB892715D927B083 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 81BB2A12A57AC10B0729222BF61A4E46 /* FirebaseCoreDiagnosticsInterop.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + ECB437504DF805BD96CAABF97400B526 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + FD4DEA7CA79F324F19AA2F27C3850EAC /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6FD6C19FE120D8553793CC6271F99B2D /* GoogleDataTransportCCTSupport.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap"; + PRODUCT_MODULE_NAME = GoogleDataTransportCCTSupport; + PRODUCT_NAME = GoogleDataTransportCCTSupport; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 03C69977197FB210700683A693848CD8 /* Build configuration list for PBXNativeTarget "GoogleDataTransport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0147BBC64F932E9CCAC117BA5DE96531 /* Debug */, + 93653F8EDFA9D0F4935F6E014A3CACD2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 05A917D87C53A0E9BD3114B20337A4B9 /* Build configuration list for PBXNativeTarget "FirebaseInstanceID" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C0AF339BF967DCA8B3E83441B334BE1 /* Debug */, + B7B16BCDDA3FC8CE3A1C7625C7482EC8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0DEB38A977DAF9AC9FE5DADE8049F71E /* Build configuration list for PBXAggregateTarget "FirebaseAnalytics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 07DC5610335182989C3D3607C2F37730 /* Debug */, + 10A7C1338F055874E0A9F8BEC9D995D5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1C889A0661C0A7C8673998DD5001B2B9 /* Build configuration list for PBXNativeTarget "GoogleUtilities" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 91B83F88F24582D7A8F6B9B89BC2814E /* Debug */, + 3E64B50C69B8278283FDA2844560BDD9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 24D2795D8F0CD51BF55E56300305D520 /* Build configuration list for PBXNativeTarget "GTMSessionFetcher" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 44D44E934C89E872B4D9A36A225BDD79 /* Debug */, + 7318FA67CE0085A3852B177D3E9A3D13 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2C9D1AE1143F17DCFD8D4E85059CF7DC /* Build configuration list for PBXNativeTarget "FirebaseDatabase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 19116AD6B498E9B61C96788E7C65F983 /* Debug */, + 1B07F9DB8169FD8F22EF454523CC01BC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 939F1A8F6BCEB7F9F64D9EEE50CAE014 /* Debug */, + ECB437504DF805BD96CAABF97400B526 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 5DB189BCCF5A8C3F2A19B6D93AD65ACE /* Build configuration list for PBXAggregateTarget "GoogleAppMeasurement" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 04E39391EA8B290AD36C550BC8A672F8 /* Debug */, + BC0BD232913FC861CC1F39D5D2C216BB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 611DD575F9DF5427C804BEFA22DF22DE /* Build configuration list for PBXNativeTarget "leveldb-library" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9D0CD5DA6C1048B9058AACEAB1670C64 /* Debug */, + CAD9769CFFE5F61AE4EEBB12C6591665 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6B1DE05CE45EFD6CA239C3759FC27C2E /* Build configuration list for PBXNativeTarget "nanopb" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D2E16E560DD0BD8CBED42592ACE36C7D /* Debug */, + B6CBC5FFF92B3CB7920BE04E2B12E694 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 91A23903EB5CBC5A5B669707FBC53853 /* Build configuration list for PBXNativeTarget "FirebaseInstallations" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CA6178295D258FAB07CACC8B2A69E2AB /* Debug */, + 3A1EC008EBC04E9427469048330E3D9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BAFA5C83AB0CDCC9BA34BC51A139E08A /* Build configuration list for PBXNativeTarget "Pods-PediatricPancreas_Storyboard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 496674F8AC9F01A63A2B899851625DE8 /* Debug */, + 03ECB27795F61AA6A21BFB96301BEDDC /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BD280CAFB18CC9A1F33CAACBAA7DDE72 /* Build configuration list for PBXAggregateTarget "FirebaseAuthInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 810A03F2A9763A9B8B07C771E4A611A2 /* Debug */, + C61FCE3AD7191BBAF217B9D5E3AA8552 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C2B17CA0717D72AEA47AB8C4E1652030 /* Build configuration list for PBXAggregateTarget "Firebase" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AEE97645A5F66ED076C63903EE9BDC7A /* Debug */, + 29F939C1A1D49DB92860C01B2530A785 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C850296960BD9D89C4BE51F8477758E0 /* Build configuration list for PBXNativeTarget "GoogleDataTransportCCTSupport" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FD4DEA7CA79F324F19AA2F27C3850EAC /* Debug */, + 6CEBDF5BD9AD626C5041E10BE87B9FFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CD64B52618F3D742F1527AB1C42ECB95 /* Build configuration list for PBXAggregateTarget "FirebaseCoreDiagnosticsInterop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E54127B175FFF628AB892715D927B083 /* Debug */, + 22C51AAC420439FDA54015FEC3ADD0C7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DC665A976EE39388357D491AB7A632EF /* Build configuration list for PBXNativeTarget "FirebaseCoreDiagnostics" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0F1D0E8B92D4D4B0D9E3724B7A8EFDD2 /* Debug */, + 0E3E4F868235F19E192F72809F7073F9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E0051EA384E24FC75A3A80B8E1E63F4C /* Build configuration list for PBXNativeTarget "FirebaseCore" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 58CE6E5911C164EADC34EA80E43E252E /* Debug */, + 9CD2D5C8734529A37EB394A9B113710E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + F3FE35D32589E8D9D20757244DA48B09 /* Build configuration list for PBXNativeTarget "FirebaseStorage" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 31880F37E5D3FE2CA6553F3578510668 /* Debug */, + 0DC744A0E4DA0BBFE51D18B1769FFFCA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FC959BA6A8F4810F766F9AAF74853C1C /* Build configuration list for PBXNativeTarget "PromisesObjC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 40CB16FC79D22E785E5DAC4B7C7858CC /* Debug */, + 79563F5A26C8052285837F3FC7E380A1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme new file mode 100644 index 0000000..ab9e834 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Firebase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme new file mode 100644 index 0000000..3eba3b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAnalytics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme new file mode 100644 index 0000000..7202e6b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseAuthInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme new file mode 100644 index 0000000..a4c140c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCore.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme new file mode 100644 index 0000000..21f827d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnostics.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme new file mode 100644 index 0000000..7a77896 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseCoreDiagnosticsInterop.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme new file mode 100644 index 0000000..0756d3d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseDatabase.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme new file mode 100644 index 0000000..68d579e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstallations.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme new file mode 100644 index 0000000..35d5ec7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseInstanceID.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseStorage.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseStorage.xcscheme new file mode 100644 index 0000000..2f89b49 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/FirebaseStorage.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GTMSessionFetcher.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GTMSessionFetcher.xcscheme new file mode 100644 index 0000000..4e23ec8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GTMSessionFetcher.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme new file mode 100644 index 0000000..3b0614e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleAppMeasurement.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme new file mode 100644 index 0000000..6208c32 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme new file mode 100644 index 0000000..968a5eb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleDataTransportCCTSupport.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme new file mode 100644 index 0000000..3915f21 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/GoogleUtilities.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas_Storyboard.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas_Storyboard.xcscheme new file mode 100644 index 0000000..506f3e0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/Pods-PediatricPancreas_Storyboard.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme new file mode 100644 index 0000000..d1487d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/PromisesObjC.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme new file mode 100644 index 0000000..b199804 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/leveldb-library.xcscheme @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme new file mode 100644 index 0000000..2183889 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/nanopb.xcscheme @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..648ce5d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Pods.xcodeproj/xcuserdata/jeffery.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,144 @@ + + + + + SchemeUserState + + Firebase.xcscheme + + isShown + + orderHint + 0 + + FirebaseAnalytics.xcscheme + + isShown + + orderHint + 1 + + FirebaseAuthInterop.xcscheme + + isShown + + orderHint + 2 + + FirebaseCore.xcscheme + + isShown + + orderHint + 3 + + FirebaseCoreDiagnostics.xcscheme + + isShown + + orderHint + 4 + + FirebaseCoreDiagnosticsInterop.xcscheme + + isShown + + orderHint + 5 + + FirebaseDatabase.xcscheme + + isShown + + orderHint + 6 + + FirebaseInstallations.xcscheme + + isShown + + orderHint + 7 + + FirebaseInstanceID.xcscheme + + isShown + + orderHint + 8 + + FirebaseStorage.xcscheme + + isShown + + orderHint + 9 + + GTMSessionFetcher.xcscheme + + isShown + + orderHint + 14 + + GoogleAppMeasurement.xcscheme + + isShown + + orderHint + 10 + + GoogleDataTransport.xcscheme + + isShown + + orderHint + 11 + + GoogleDataTransportCCTSupport.xcscheme + + isShown + + orderHint + 12 + + GoogleUtilities.xcscheme + + isShown + + orderHint + 13 + + Pods-PediatricPancreas_Storyboard.xcscheme + + isShown + + orderHint + 17 + + PromisesObjC.xcscheme + + isShown + + orderHint + 18 + + leveldb-library.xcscheme + + isShown + + orderHint + 15 + + nanopb.xcscheme + + isShown + + orderHint + 16 + + + SuppressBuildableAutocreation + + + diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/LICENSE b/PediatricPancreas_Storyboard/Pods/PromisesObjC/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/README.md b/PediatricPancreas_Storyboard/Pods/PromisesObjC/README.md new file mode 100644 index 0000000..0eecbb1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/README.md @@ -0,0 +1,60 @@ +[![Apache +License](https://img.shields.io/github/license/google/promises.svg)](LICENSE) +[![Travis](https://api.travis-ci.org/google/promises.svg?branch=master)](https://travis-ci.org/google/promises) +[![Gitter Chat](https://badges.gitter.im/google/promises.svg)](https://gitter.im/google/promises) + +![Platforms](https://img.shields.io/badge/platforms-macOS%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-blue.svg?longCache=true&style=flat) +![Languages](https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg?longCache=true&style=flat) +![Package Managers](https://img.shields.io/badge/supports-Bazel%20%7C%20SwiftPM%20%7C%20CocoaPods%20%7C%20Carthage-yellow.svg?longCache=true&style=flat) + +# Promises + +Promises is a modern framework that provides a synchronization construct for +Objective-C and Swift to facilitate writing asynchronous code. + +* [Introduction](g3doc/index.md) + * [The problem with async + code](g3doc/index.md#the-problem-with-async-code) + * [Promises to the rescue](g3doc/index.md#promises-to-the-rescue) + * [What is a promise?](g3doc/index.md#what-is-a-promise) +* [Framework](g3doc/index.md#framework) + * [Features](g3doc/index.md#features) + * [Benchmark](g3doc/index.md#benchmark) +* [Getting started](g3doc/index.md#getting-started) + * [Add dependency](g3doc/index.md#add-dependency) + * [Import](g3doc/index.md#import) + * [Adopt](g3doc/index.md#adopt) +* [Basics](g3doc/index.md#basics) + * [Creating promises](g3doc/index.md#creating-promises) + * [Async](g3doc/index.md#async) + * [Do](g3doc/index.md#do) + * [Pending](g3doc/index.md#pending) + * [Resolved](g3doc/index.md#create-a-resolved-promise) + * [Observing fulfillment](g3doc/index.md#observing-fulfillment) + * [Then](g3doc/index.md#then) + * [Observing rejection](g3doc/index.md#observing-rejection) + * [Catch](g3doc/index.md#catch) +* [Extensions](g3doc/index.md#extensions) + * [All](g3doc/index.md#all) + * [Always](g3doc/index.md#always) + * [Any](g3doc/index.md#any) + * [Await](g3doc/index.md#await) + * [Delay](g3doc/index.md#delay) + * [Race](g3doc/index.md#race) + * [Recover](g3doc/index.md#recover) + * [Reduce](g3doc/index.md#reduce) + * [Retry](g3doc/index.md#retry) + * [Timeout](g3doc/index.md#timeout) + * [Validate](g3doc/index.md#validate) + * [Wrap](g3doc/index.md#wrap) +* [Advanced topics](g3doc/index.md#advanced-topics) + * [Default dispatch queue](g3doc/index.md#default-dispatch-queue) + * [Ownership and retain + cycles](g3doc/index.md#ownership-and-retain-cycles) + * [Testing](g3doc/index.md#testing) + * [Objective-C <-> Swift + interoperability](g3doc/index.md#objective-c---swift-interoperability) + * [Dot-syntax in Objective-C](g3doc/index.md#dot-syntax-in-objective-c) +* [Anti-patterns](g3doc/index.md#anti-patterns) + * [Broken chain](g3doc/index.md#broken-chain) + * [Nested promises](g3doc/index.md#nested-promises) diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m new file mode 100644 index 0000000..c21f30e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+All.m @@ -0,0 +1,86 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AllAdditions) + ++ (FBLPromise *)all:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue all:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue all:(NSArray *)allPromises { + NSParameterAssert(queue); + NSParameterAssert(allPromises); + + if (allPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [allPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else if ([promise isKindOfClass:[NSError class]]) { + reject(promise); + return; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are fulfilled. + for (FBLPromise *promise in promises) { + if (!promise.isFulfilled) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill([promises valueForKey:NSStringFromSelector(@selector(value))]); + } + reject:^(NSError *error) { + reject(error); + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all { + return ^(NSArray *promises) { + return [self all:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue all:promises]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m new file mode 100644 index 0000000..6927442 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Always.m @@ -0,0 +1,58 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Always.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AlwaysAdditions) + +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue always:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue always:(FBLPromiseAlwaysWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue + chainedFulfill:^id(id value) { + work(); + return value; + } + chainedReject:^id(NSError *error) { + work(); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AlwaysAdditions) + +- (FBLPromise * (^)(FBLPromiseAlwaysWorkBlock))always { + return ^(FBLPromiseAlwaysWorkBlock work) { + return [self always:work]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn { + return ^(dispatch_queue_t queue, FBLPromiseAlwaysWorkBlock work) { + return [self onQueue:queue always:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m new file mode 100644 index 0000000..e101c98 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Any.m @@ -0,0 +1,112 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Any.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +static NSArray *FBLPromiseCombineValuesAndErrors(NSArray *promises) { + NSMutableArray *combinedValuesAndErrors = [[NSMutableArray alloc] init]; + for (FBLPromise *promise in promises) { + if (promise.isFulfilled) { + [combinedValuesAndErrors addObject:promise.value ?: [NSNull null]]; + continue; + } + if (promise.isRejected) { + [combinedValuesAndErrors addObject:promise.error]; + continue; + } + assert(!promise.isPending); + }; + return combinedValuesAndErrors; +} + +@implementation FBLPromise (AnyAdditions) + ++ (FBLPromise *)any:(NSArray *)promises { + return [self onQueue:FBLPromise.defaultDispatchQueue any:promises]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue any:(NSArray *)anyPromises { + NSParameterAssert(queue); + NSParameterAssert(anyPromises); + + if (anyPromises.count == 0) { + return [[FBLPromise alloc] initWithResolution:@[]]; + } + NSMutableArray *promises = [anyPromises mutableCopy]; + return [FBLPromise + onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (NSUInteger i = 0; i < promises.count; ++i) { + id promise = promises[i]; + if ([promise isKindOfClass:self]) { + continue; + } else { + [promises replaceObjectAtIndex:i + withObject:[[FBLPromise alloc] initWithResolution:promise]]; + } + } + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue + fulfill:^(id __unused _) { + // Wait until all are resolved. + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + } + // If called multiple times, only the first one affects the result. + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } + reject:^(NSError *error) { + BOOL atLeastOneIsFulfilled = NO; + for (FBLPromise *promise in promises) { + if (promise.isPending) { + return; + } + if (promise.isFulfilled) { + atLeastOneIsFulfilled = YES; + } + } + if (atLeastOneIsFulfilled) { + fulfill(FBLPromiseCombineValuesAndErrors(promises)); + } else { + reject(error); + } + }]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any { + return ^(NSArray *promises) { + return [self any:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue any:promises]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m new file mode 100644 index 0000000..249158c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Async.m @@ -0,0 +1,70 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Async.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (AsyncAdditions) + ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue async:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue async:(FBLPromiseAsyncWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + work( + ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }, + ^(NSError *error) { + [promise reject:error]; + }); + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async { + return ^(FBLPromiseAsyncWorkBlock work) { + return [self async:work]; + }; +} + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn { + return ^(dispatch_queue_t queue, FBLPromiseAsyncWorkBlock work) { + return [self onQueue:queue async:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m new file mode 100644 index 0000000..ea3b87a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Await.m @@ -0,0 +1,48 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Await.h" + +#import "FBLPromisePrivate.h" + +id __nullable FBLPromiseAwait(FBLPromise *promise, NSError **outError) { + assert(promise); + + static dispatch_once_t onceToken; + static dispatch_queue_t queue; + dispatch_once(&onceToken, ^{ + queue = dispatch_queue_create("com.google.FBLPromises.Await", DISPATCH_QUEUE_CONCURRENT); + }); + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + id __block resolution; + NSError __block *blockError; + [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + resolution = value; + dispatch_semaphore_signal(semaphore); + return value; + } + chainedReject:^id(NSError *error) { + blockError = error; + dispatch_semaphore_signal(semaphore); + return error; + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if (outError) { + *outError = blockError; + } + return resolution; +} diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m new file mode 100644 index 0000000..25e8ce6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Catch.m @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Catch.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (CatchAdditions) + +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject { + return [self onQueue:FBLPromise.defaultDispatchQueue catch:reject]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue catch:(FBLPromiseCatchWorkBlock)reject { + NSParameterAssert(queue); + NSParameterAssert(reject); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + reject(error); + return error; + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch { + return ^(FBLPromiseCatchWorkBlock catch) { + return [self catch:catch]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn { + return ^(dispatch_queue_t queue, FBLPromiseCatchWorkBlock catch) { + return [self onQueue:queue catch:catch]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m new file mode 100644 index 0000000..ce94c33 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Delay.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Delay.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DelayAdditions) + +- (FBLPromise *)delay:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue delay:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue delay:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + [promise fulfill:value]; + }); + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay { + return ^(NSTimeInterval interval) { + return [self delay:interval]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue delay:interval]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m new file mode 100644 index 0000000..eb7e10d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Do.m @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Do.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (DoAdditions) + ++ (instancetype)do:(FBLPromiseDoWorkBlock)work { + return [self onQueue:self.defaultDispatchQueue do:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_DoAdditions) + ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn { + return ^(dispatch_queue_t queue, FBLPromiseDoWorkBlock work) { + return [self onQueue:queue do:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m new file mode 100644 index 0000000..b5bd9f1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Race.m @@ -0,0 +1,65 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Race.h" + +#import "FBLPromise+Async.h" +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RaceAdditions) + ++ (instancetype)race:(NSArray *)promises { + return [self onQueue:self.defaultDispatchQueue race:promises]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)racePromises { + NSParameterAssert(queue); + NSAssert(racePromises.count > 0, @"No promises to observe"); + + NSArray *promises = [racePromises copy]; + return [FBLPromise onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + for (id promise in promises) { + if (![promise isKindOfClass:self]) { + fulfill(promise); + return; + } + } + // Subscribe all, but only the first one to resolve will change + // the resulting promise's state. + for (FBLPromise *promise in promises) { + [promise observeOnQueue:queue fulfill:fulfill reject:reject]; + } + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race { + return ^(NSArray *promises) { + return [self race:promises]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn { + return ^(dispatch_queue_t queue, NSArray *promises) { + return [self onQueue:queue race:promises]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m new file mode 100644 index 0000000..0c9326a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Recover.m @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Recover.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (RecoverAdditions) + +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery { + return [self onQueue:FBLPromise.defaultDispatchQueue recover:recovery]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue recover:(FBLPromiseRecoverWorkBlock)recovery { + NSParameterAssert(queue); + NSParameterAssert(recovery); + + return [self chainOnQueue:queue + chainedFulfill:nil + chainedReject:^id(NSError *error) { + return recovery(error); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover { + return ^(FBLPromiseRecoverWorkBlock recovery) { + return [self recover:recovery]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn { + return ^(dispatch_queue_t queue, FBLPromiseRecoverWorkBlock recovery) { + return [self onQueue:queue recover:recovery]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m new file mode 100644 index 0000000..1f3fc50 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Reduce.m @@ -0,0 +1,61 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Reduce.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ReduceAdditions) + +- (FBLPromise *)reduce:(NSArray *)items combine:(FBLPromiseReducerBlock)reducer { + return [self onQueue:FBLPromise.defaultDispatchQueue reduce:items combine:reducer]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer { + NSParameterAssert(queue); + NSParameterAssert(items); + NSParameterAssert(reducer); + + FBLPromise *promise = self; + for (id item in items) { + promise = [promise chainOnQueue:queue + chainedFulfill:^id(id value) { + return reducer(value, item); + } + chainedReject:nil]; + } + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce { + return ^(NSArray *items, FBLPromiseReducerBlock reducer) { + return [self reduce:items combine:reducer]; + }; +} + +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn { + return ^(dispatch_queue_t queue, NSArray *items, FBLPromiseReducerBlock reducer) { + return [self onQueue:queue reduce:items combine:reducer]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m new file mode 100644 index 0000000..37c5576 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Retry.m @@ -0,0 +1,128 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Retry.h" + +#import "FBLPromisePrivate.h" + +NSInteger const FBLPromiseRetryDefaultAttemptsCount = 1; +NSTimeInterval const FBLPromiseRetryDefaultDelayInterval = 1.0; + +static void FBLPromiseRetryAttempt(FBLPromise *promise, dispatch_queue_t queue, NSInteger count, + NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + __auto_type retrier = ^(id __nullable value) { + if ([value isKindOfClass:[NSError class]]) { + if (count <= 0 || (predicate && !predicate(count, value))) { + [promise reject:value]; + } else { + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + FBLPromiseRetryAttempt(promise, queue, count - 1, interval, predicate, work); + }); + } + } else { + [promise fulfill:value]; + } + }; + id value = work(); + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue fulfill:retrier reject:retrier]; + } else { + retrier(value); + } +} + +@implementation FBLPromise (RetryAdditions) + ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue attempts:FBLPromiseRetryDefaultAttemptsCount retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue attempts:count retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:queue + attempts:count + delay:FBLPromiseRetryDefaultDelayInterval + condition:nil + retry:work]; +} + ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue + attempts:count + delay:interval + condition:predicate + retry:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + FBLPromiseRetryAttempt(promise, queue, count, interval, predicate, work); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry { + return ^id(FBLPromiseRetryWorkBlock work) { + return [self retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn { + return ^id(dispatch_queue_t queue, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue retry:work]; + }; +} + ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgain { + return ^id(NSInteger count, NSTimeInterval interval, FBLPromiseRetryPredicateBlock predicate, + FBLPromiseRetryWorkBlock work) { + return [self attempts:count delay:interval condition:predicate retry:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock, + FBLPromiseRetryWorkBlock))retryAgainOn { + return ^id(dispatch_queue_t queue, NSInteger count, NSTimeInterval interval, + FBLPromiseRetryPredicateBlock predicate, FBLPromiseRetryWorkBlock work) { + return [self onQueue:queue attempts:count delay:interval condition:predicate retry:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m new file mode 100644 index 0000000..27e8e6c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Testing.m @@ -0,0 +1,56 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) { + BOOL isTimedOut = NO; + NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout]; + static NSTimeInterval const minimalTimeout = 0.01; + static int64_t const minimalTimeToWait = (int64_t)(minimalTimeout * NSEC_PER_SEC); + dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, minimalTimeToWait); + dispatch_group_t dispatchGroup = FBLPromise.dispatchGroup; + NSRunLoop *runLoop = NSRunLoop.currentRunLoop; + while (dispatch_group_wait(dispatchGroup, waitTime)) { + isTimedOut = timeoutDate.timeIntervalSinceNow < 0.0; + if (isTimedOut) { + break; + } + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:minimalTimeout]]; + } + return !isTimedOut; +} + +@implementation FBLPromise (TestingAdditions) + +// These properties are implemented in the FBLPromise class itself. +@dynamic isPending; +@dynamic isFulfilled; +@dynamic isRejected; +@dynamic pendingObjects; +@dynamic value; +@dynamic error; + ++ (dispatch_group_t)dispatchGroup { + static dispatch_group_t gDispatchGroup; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gDispatchGroup = dispatch_group_create(); + }); + return gDispatchGroup; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m new file mode 100644 index 0000000..ab03bd1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Then.m @@ -0,0 +1,50 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Then.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ThenAdditions) + +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work { + return [self onQueue:FBLPromise.defaultDispatchQueue then:work]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue then:(FBLPromiseThenWorkBlock)work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self chainOnQueue:queue chainedFulfill:work chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then { + return ^(FBLPromiseThenWorkBlock work) { + return [self then:work]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn { + return ^(dispatch_queue_t queue, FBLPromiseThenWorkBlock work) { + return [self onQueue:queue then:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m new file mode 100644 index 0000000..a2252e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Timeout.m @@ -0,0 +1,64 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Timeout.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (TimeoutAdditions) + +- (FBLPromise *)timeout:(NSTimeInterval)interval { + return [self onQueue:FBLPromise.defaultDispatchQueue timeout:interval]; +} + +- (FBLPromise *)onQueue:(dispatch_queue_t)queue timeout:(NSTimeInterval)interval { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + typeof(self) __weak weakPromise = promise; + dispatch_after(dispatch_time(0, (int64_t)(interval * NSEC_PER_SEC)), queue, ^{ + NSError *timedOutError = [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeTimedOut + userInfo:nil]; + [weakPromise reject:timedOutError]; + }); + return promise; +} + +@end + +@implementation FBLPromise (DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout { + return ^(NSTimeInterval interval) { + return [self timeout:interval]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn { + return ^(dispatch_queue_t queue, NSTimeInterval interval) { + return [self onQueue:queue timeout:interval]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m new file mode 100644 index 0000000..1e21e81 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Validate.m @@ -0,0 +1,56 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Validate.h" + +#import "FBLPromisePrivate.h" + +@implementation FBLPromise (ValidateAdditions) + +- (FBLPromise*)validate:(FBLPromiseValidateWorkBlock)predicate { + return [self onQueue:FBLPromise.defaultDispatchQueue validate:predicate]; +} + +- (FBLPromise*)onQueue:(dispatch_queue_t)queue validate:(FBLPromiseValidateWorkBlock)predicate { + NSParameterAssert(queue); + NSParameterAssert(predicate); + + FBLPromiseChainedFulfillBlock chainedFulfill = ^id(id value) { + return predicate(value) ? value : + [[NSError alloc] initWithDomain:FBLPromiseErrorDomain + code:FBLPromiseErrorCodeValidationFailure + userInfo:nil]; + }; + return [self chainOnQueue:queue chainedFulfill:chainedFulfill chainedReject:nil]; +} + +@end + +@implementation FBLPromise (DotSyntax_ValidateAdditions) + +- (FBLPromise* (^)(FBLPromiseValidateWorkBlock))validate { + return ^(FBLPromiseValidateWorkBlock predicate) { + return [self validate:predicate]; + }; +} + +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn { + return ^(dispatch_queue_t queue, FBLPromiseValidateWorkBlock predicate) { + return [self onQueue:queue validate:predicate]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m new file mode 100644 index 0000000..3d3341e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise+Wrap.m @@ -0,0 +1,420 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Wrap.h" + +#import "FBLPromise+Async.h" + +@implementation FBLPromise (WrapAdditions) + ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^{ + fulfill(nil); + }); + }]; +} + ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(id __nullable value) { + fulfill(value); + }); + }]; +} + ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(nil); + } + }); + }]; +} + ++ (instancetype)wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapObjectOrErrorCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (instancetype)wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapErrorOrObjectCompletion:work]; +} + ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSError *__nullable error, id __nullable value) { + if (error) { + reject(error); + } else { + fulfill(value); + } + }); + }]; +} + ++ (FBLPromise *)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrap2ObjectsOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(id __nullable value1, id __nullable value2, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@[ value1, value2 ]); + } + }); + }]; +} + ++ (FBLPromise *)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(BOOL value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapBoolOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(BOOL value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(NSInteger value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapIntegerOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(NSInteger value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + ++ (FBLPromise *)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:(dispatch_queue_t)queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) { + work(^(double value) { + fulfill(@(value)); + }); + }]; +} + ++ (FBLPromise *)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion))work { + return [self onQueue:self.defaultDispatchQueue wrapDoubleOrErrorCompletion:work]; +} + ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion))work { + NSParameterAssert(queue); + NSParameterAssert(work); + + return [self onQueue:queue + async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { + work(^(double value, NSError *__nullable error) { + if (error) { + reject(error); + } else { + fulfill(@(value)); + } + }); + }]; +} + +@end + +@implementation FBLPromise (DotSyntax_WrapAdditions) + ++ (FBLPromise * (^)(void (^)(FBLPromiseCompletion)))wrapCompletion { + return ^(void (^work)(FBLPromiseCompletion)) { + return [self wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseCompletion)) { + return [self onQueue:queue wrapCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion { + return ^(void (^work)(FBLPromiseObjectCompletion)) { + return [self wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectCompletion)) { + return [self onQueue:queue wrapObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion { + return ^(void (^work)(FBLPromiseErrorCompletion)) { + return [self wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorCompletion)) { + return [self onQueue:queue wrapErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion { + return ^(void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseObjectOrErrorCompletion)) { + return [self onQueue:queue wrapObjectOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion { + return ^(void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseErrorOrObjectCompletion)) { + return [self onQueue:queue wrapErrorOrObjectCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion { + return ^(void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromise2ObjectsOrErrorCompletion)) { + return [self onQueue:queue wrap2ObjectsOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion { + return ^(void (^work)(FBLPromiseBoolCompletion)) { + return [self wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolCompletion)) { + return [self onQueue:queue wrapBoolCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletion { + return ^(void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseBoolOrErrorCompletion))) + wrapBoolOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseBoolOrErrorCompletion)) { + return [self onQueue:queue wrapBoolOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion { + return ^(void (^work)(FBLPromiseIntegerCompletion)) { + return [self wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerCompletion)) { + return [self onQueue:queue wrapIntegerCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion { + return ^(void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseIntegerOrErrorCompletion)) { + return [self onQueue:queue wrapIntegerOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion { + return ^(void (^work)(FBLPromiseDoubleCompletion)) { + return [self wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleCompletion)) { + return [self onQueue:queue wrapDoubleCompletion:work]; + }; +} + ++ (FBLPromise * (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion { + return ^(void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self wrapDoubleOrErrorCompletion:work]; + }; +} + ++ (FBLPromise * (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn { + return ^(dispatch_queue_t queue, void (^work)(FBLPromiseDoubleOrErrorCompletion)) { + return [self onQueue:queue wrapDoubleOrErrorCompletion:work]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m new file mode 100644 index 0000000..0837b04 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromise.m @@ -0,0 +1,297 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromisePrivate.h" + +/** All states a promise can be in. */ +typedef NS_ENUM(NSInteger, FBLPromiseState) { + FBLPromiseStatePending = 0, + FBLPromiseStateFulfilled, + FBLPromiseStateRejected, +}; + +typedef void (^FBLPromiseObserver)(FBLPromiseState state, id __nullable resolution); + +static dispatch_queue_t gFBLPromiseDefaultDispatchQueue; + +@implementation FBLPromise { + /** Current state of the promise. */ + FBLPromiseState _state; + /** + Set of arbitrary objects to keep strongly while the promise is pending. + Becomes nil after the promise has been resolved. + */ + NSMutableSet *__nullable _pendingObjects; + /** + Value to fulfill the promise with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ + id __nullable _value; + /** + Error to reject the promise with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ + NSError *__nullable _error; + /** List of observers to notify when the promise gets resolved. */ + NSMutableArray *_observers; +} + ++ (void)initialize { + if (self == [FBLPromise class]) { + gFBLPromiseDefaultDispatchQueue = dispatch_get_main_queue(); + } +} + ++ (dispatch_queue_t)defaultDispatchQueue { + @synchronized(self) { + return gFBLPromiseDefaultDispatchQueue; + } +} + ++ (void)setDefaultDispatchQueue:(dispatch_queue_t)queue { + NSParameterAssert(queue); + + @synchronized(self) { + gFBLPromiseDefaultDispatchQueue = queue; + } +} + ++ (instancetype)pendingPromise { + return [[self alloc] initPending]; +} + ++ (instancetype)resolvedWith:(nullable id)resolution { + return [[self alloc] initWithResolution:resolution]; +} + +- (void)fulfill:(nullable id)value { + if ([value isKindOfClass:[NSError class]]) { + [self reject:(NSError *)value]; + } else { + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateFulfilled; + _value = value; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _value); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } + } +} + +- (void)reject:(NSError *)error { + NSAssert([error isKindOfClass:[NSError class]], @"Invalid error type."); + + if (![error isKindOfClass:[NSError class]]) { + // Give up on invalid error type in Release mode. + @throw error; // NOLINT + } + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + _state = FBLPromiseStateRejected; + _error = error; + _pendingObjects = nil; + for (FBLPromiseObserver observer in _observers) { + observer(_state, _error); + } + _observers = nil; + dispatch_group_leave(FBLPromise.dispatchGroup); + } + } +} + +#pragma mark - NSObject + +- (NSString *)description { + if (self.isFulfilled) { + return [NSString stringWithFormat:@"<%@ %p> Fulfilled: %@", NSStringFromClass([self class]), + self, self.value]; + } + if (self.isRejected) { + return [NSString stringWithFormat:@"<%@ %p> Rejected: %@", NSStringFromClass([self class]), + self, self.error]; + } + return [NSString stringWithFormat:@"<%@ %p> Pending", NSStringFromClass([self class]), self]; +} + +#pragma mark - Private + +- (instancetype)initPending { + self = [super init]; + if (self) { + dispatch_group_enter(FBLPromise.dispatchGroup); + } + return self; +} + +- (instancetype)initWithResolution:(nullable id)resolution { + self = [super init]; + if (self) { + if ([resolution isKindOfClass:[NSError class]]) { + _state = FBLPromiseStateRejected; + _error = (NSError *)resolution; + } else { + _state = FBLPromiseStateFulfilled; + _value = resolution; + } + } + return self; +} + +- (void)dealloc { + if (_state == FBLPromiseStatePending) { + dispatch_group_leave(FBLPromise.dispatchGroup); + } +} + +- (BOOL)isPending { + @synchronized(self) { + return _state == FBLPromiseStatePending; + } +} + +- (BOOL)isFulfilled { + @synchronized(self) { + return _state == FBLPromiseStateFulfilled; + } +} + +- (BOOL)isRejected { + @synchronized(self) { + return _state == FBLPromiseStateRejected; + } +} + +- (nullable id)value { + @synchronized(self) { + return _value; + } +} + +- (NSError *__nullable)error { + @synchronized(self) { + return _error; + } +} + +- (NSMutableSet *__nullable)pendingObjects { + @synchronized(self) { + if (_state == FBLPromiseStatePending) { + if (!_pendingObjects) { + _pendingObjects = [[NSMutableSet alloc] init]; + } + } + return _pendingObjects; + } +} + +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject { + NSParameterAssert(queue); + NSParameterAssert(onFulfill); + NSParameterAssert(onReject); + + @synchronized(self) { + switch (_state) { + case FBLPromiseStatePending: { + if (!_observers) { + _observers = [[NSMutableArray alloc] init]; + } + [_observers addObject:^(FBLPromiseState state, id __nullable resolution) { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + switch (state) { + case FBLPromiseStatePending: + break; + case FBLPromiseStateFulfilled: + onFulfill(resolution); + break; + case FBLPromiseStateRejected: + onReject(resolution); + break; + } + }); + }]; + break; + } + case FBLPromiseStateFulfilled: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onFulfill(self->_value); + }); + break; + } + case FBLPromiseStateRejected: { + dispatch_group_async(FBLPromise.dispatchGroup, queue, ^{ + onReject(self->_error); + }); + break; + } + } + } +} + +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject { + NSParameterAssert(queue); + + FBLPromise *promise = [[FBLPromise alloc] initPending]; + __auto_type resolver = ^(id __nullable value) { + if ([value isKindOfClass:[FBLPromise class]]) { + [(FBLPromise *)value observeOnQueue:queue + fulfill:^(id __nullable value) { + [promise fulfill:value]; + } + reject:^(NSError *error) { + [promise reject:error]; + }]; + } else { + [promise fulfill:value]; + } + }; + [self observeOnQueue:queue + fulfill:^(id __nullable value) { + value = chainedFulfill ? chainedFulfill(value) : value; + resolver(value); + } + reject:^(NSError *error) { + id value = chainedReject ? chainedReject(error) : error; + resolver(value); + }]; + return promise; +} + +@end + +@implementation FBLPromise (DotSyntaxAdditions) + ++ (instancetype (^)(void))pending { + return ^(void) { + return [self pendingPromise]; + }; +} + ++ (instancetype (^)(id __nullable))resolved { + return ^(id resolution) { + return [self resolvedWith:resolution]; + }; +} + +@end diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m new file mode 100644 index 0000000..1cc181a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/FBLPromiseError.m @@ -0,0 +1,19 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NSErrorDomain const FBLPromiseErrorDomain = @"com.google.FBLPromises.Error"; diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h new file mode 100644 index 0000000..9c0090e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+All.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AllAdditions) + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)all:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until all of the given promises are fulfilled. + If one of the given promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected FBLPromise correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of an array containing the values of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + all:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `all` operators. + Usage: FBLPromise.all(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AllAdditions) + ++ (FBLPromise * (^)(NSArray *))all FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))allOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h new file mode 100644 index 0000000..13000f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Always.h @@ -0,0 +1,54 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AlwaysAdditions) + +typedef void (^FBLPromiseAlwaysWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)always:(FBLPromiseAlwaysWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to dispatch on. + @param work A block that always executes, no matter if the receiver is rejected or fulfilled. + @return A new pending promise to be resolved with same resolution as the receiver. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + always:(FBLPromiseAlwaysWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `always` operators. + Usage: promise.always(^{...}) + */ +@interface FBLPromise(DotSyntax_AlwaysAdditions) + +- (FBLPromise* (^)(FBLPromiseAlwaysWorkBlock))always FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAlwaysWorkBlock))alwaysOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h new file mode 100644 index 0000000..82875bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Any.h @@ -0,0 +1,69 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AnyAdditions) + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSErrors`, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)any:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Waits until all of the given promises are either fulfilled or rejected. + If all promises are rejected, then the returned promise is rejected with same error + as the last one rejected. + If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of + values or `NSError`s, matching the original order of fulfilled or rejected promises respectively. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + Promises resolved with `nil` become `NSNull` instances in the resulting array. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return Promise of array containing the values or `NSError`s of input promises in the same order. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + any:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `any` operators. + Usage: FBLPromise.any(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_AnyAdditions) + ++ (FBLPromise * (^)(NSArray *))any FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h new file mode 100644 index 0000000..0588a9e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Async.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(AsyncAdditions) + +typedef void (^FBLPromiseFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseAsyncWorkBlock)(FBLPromiseFulfillBlock fulfill, + FBLPromiseRejectBlock reject) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)async:(FBLPromiseAsyncWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + async:(FBLPromiseAsyncWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `async` operators. + Usage: FBLPromise.async(^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { ... }) + */ +@interface FBLPromise(DotSyntax_AsyncAdditions) + ++ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h new file mode 100644 index 0000000..c97a1ba --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Await.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for promise resolution. The current thread blocks until the promise is resolved. + + @param promise Promise to wait for. + @param error Error the promise was rejected with, or `nil` if the promise was fulfilled. + @return Value the promise was fulfilled with. If the promise was rejected, the return value + is always `nil`, but the error out arg is not. + */ +FOUNDATION_EXTERN id __nullable FBLPromiseAwait(FBLPromise *promise, + NSError **error) NS_REFINED_FOR_SWIFT; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h new file mode 100644 index 0000000..a9ff170 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Catch.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(CatchAdditions) + +typedef void (^FBLPromiseCatchWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously. + + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)catch:(FBLPromiseCatchWorkBlock)reject NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with same resolution as the receiver. + If receiver is rejected, then `reject` block is executed asynchronously on the given queue. + + @param queue A queue to invoke the `reject` block on. + @param reject A block to handle the error that receiver was rejected with. + @return A new pending promise. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + catch:(FBLPromiseCatchWorkBlock)reject NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `catch` operators. + Usage: promise.catch(^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_CatchAdditions) + +- (FBLPromise* (^)(FBLPromiseCatchWorkBlock))catch FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchWorkBlock))catchOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h new file mode 100644 index 0000000..557df48 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Delay.h @@ -0,0 +1,59 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DelayAdditions) + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)delay:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a new pending promise that fulfills with the same value as `self` after the `delay`, or + rejects with the same error immediately. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that fulfills at least `delay` seconds later than `self`, or rejects + with the same error immediately. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + delay:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `delay` operators. + Usage: promise.delay(...) + */ +@interface FBLPromise(DotSyntax_DelayAdditions) + +- (FBLPromise * (^)(NSTimeInterval))delay FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSTimeInterval))delayOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h new file mode 100644 index 0000000..6838e0a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Do.h @@ -0,0 +1,55 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(DoAdditions) + +typedef id __nullable (^FBLPromiseDoWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously. + + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)do:(FBLPromiseDoWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise and executes `work` block asynchronously on the given queue. + + @param queue A queue to invoke the `work` block on. + @param work A block that returns a value or an error used to resolve the promise. + @return A new pending promise. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `do` operators. + Usage: FBLPromise.doOn(queue, ^(NSError *error) { ... }) + */ +@interface FBLPromise(DotSyntax_DoAdditions) + ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h new file mode 100644 index 0000000..2f67258 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Race.h @@ -0,0 +1,62 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RaceAdditions) + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)race:(NSArray *)promises NS_SWIFT_UNAVAILABLE(""); + +/** + Wait until any of the given promises are fulfilled. + If one of the promises is rejected, then the returned promise is rejected with same error. + If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`, + it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly. + + @param queue A queue to dispatch on. + @param promises Promises to wait for. + @return A new pending promise to be resolved with the same resolution as the first promise, among + the given ones, which was resolved. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue race:(NSArray *)promises NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `race` operators. + Usage: FBLPromise.race(@[ ... ]) + */ +@interface FBLPromise(DotSyntax_RaceAdditions) + ++ (FBLPromise * (^)(NSArray *))race FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSArray *))raceOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h new file mode 100644 index 0000000..bb7df7e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Recover.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(RecoverAdditions) + +typedef id __nullable (^FBLPromiseRecoverWorkBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)recover:(FBLPromiseRecoverWorkBlock)recovery NS_SWIFT_UNAVAILABLE(""); + +/** + Provides a new promise to recover in case the receiver gets rejected. + + @param queue A queue to dispatch on. + @param recovery A block to handle the error that the receiver was rejected with. + @return A new pending promise to use instead of the rejected one that gets resolved with resolution + returned from `recovery` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + recover:(FBLPromiseRecoverWorkBlock)recovery NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `recover` operators. + Usage: promise.recover(^id(NSError *error) {...}) + */ +@interface FBLPromise(DotSyntax_RecoverAdditions) + +- (FBLPromise * (^)(FBLPromiseRecoverWorkBlock))recover FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRecoverWorkBlock))recoverOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h new file mode 100644 index 0000000..5bb1eee --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Reduce.h @@ -0,0 +1,71 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ReduceAdditions) + +typedef id __nullable (^FBLPromiseReducerBlock)(Value __nullable partial, id next) + NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +/** + Sequentially reduces a collection of values to a single promise using a given combining block + and the value `self` resolves with as initial value. + + @param queue A queue to dispatch on. + @param items An array of values to process in order. + @param reducer A block to combine an accumulating value and an element of the sequence into + the new accumulating value or a promise resolved with it, to be used in the next + call of the `reducer` or returned to the caller. + @return A new pending promise returned from the last `reducer` invocation. + Or `self` if `items` is empty. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + reduce:(NSArray *)items + combine:(FBLPromiseReducerBlock)reducer NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `reduce` operators. + Usage: promise.reduce(values, ^id(id partial, id next) { ... }) + */ +@interface FBLPromise(DotSyntax_ReduceAdditions) + +- (FBLPromise * (^)(NSArray *, FBLPromiseReducerBlock))reduce FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, NSArray *, FBLPromiseReducerBlock))reduceOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h new file mode 100644 index 0000000..98ef558 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Retry.h @@ -0,0 +1,165 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** The default number of retry attempts is 1. */ +FOUNDATION_EXTERN NSInteger const FBLPromiseRetryDefaultAttemptsCount NS_REFINED_FOR_SWIFT; + +/** The default delay interval before making a retry attempt is 1.0 second. */ +FOUNDATION_EXTERN NSTimeInterval const FBLPromiseRetryDefaultDelayInterval NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(RetryAdditions) + +typedef id __nullable (^FBLPromiseRetryWorkBlock)(void) NS_SWIFT_UNAVAILABLE(""); +typedef BOOL (^FBLPromiseRetryPredicateBlock)(NSInteger, NSError *) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on rejection where the + `work` block is retried after a delay of `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. Defaults to `FBLPromiseRetryDefaultAttemptsCount` attempt(s) on + rejection where the `work` block is retried on the given `queue` after a delay of + `FBLPromiseRetryDefaultDelayInterval` second(s). + + @param queue A queue to invoke the `work` block on. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously, or rejects with the same error after all retry attempts have + been exhausted. On rejection, the `work` block is retried after the given delay `interval` and will + continue to retry until the number of specified attempts have been exhausted or will bail early if + the given condition is not met. + + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the default queue and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise that fulfills with the same value as the promise returned from `work` + block, which executes asynchronously on the given `queue`, or rejects with the same error after all + retry attempts have been exhausted. On rejection, the `work` block is retried after the given + delay `interval` and will continue to retry until the number of specified attempts have been + exhausted or will bail early if the given condition is not met. + + @param queue A queue to invoke the `work` block on. + @param count Max number of retry attempts. The `work` block will be executed once if the specified + count is less than or equal to zero. + @param interval Time to wait before the next retry attempt. + @param predicate Condition to check before the next retry attempt. The predicate block provides the + the number of remaining retry attempts and the error that the promise was rejected + with. + @param work A block that executes asynchronously on the given `queue` and returns a value or an + error used to resolve the promise. + @return A new pending promise that fulfills with the same value as the promise returned from `work` + block, or rejects with the same error after all retry attempts have been exhausted or if + the given condition is not met. + */ ++ (FBLPromise *)onQueue:(dispatch_queue_t)queue + attempts:(NSInteger)count + delay:(NSTimeInterval)interval + condition:(nullable FBLPromiseRetryPredicateBlock)predicate + retry:(FBLPromiseRetryWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise+Retry` operators. + Usage: FBLPromise.retry(^id { ... }) + */ +@interface FBLPromise(DotSyntax_RetryAdditions) + ++ (FBLPromise * (^)(FBLPromiseRetryWorkBlock))retry FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseRetryWorkBlock))retryOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(NSInteger, NSTimeInterval, FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgain FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise * (^)(dispatch_queue_t, NSInteger, NSTimeInterval, + FBLPromiseRetryPredicateBlock __nullable, + FBLPromiseRetryWorkBlock))retryAgainOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h new file mode 100644 index 0000000..07a65ec --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Testing.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Waits for all scheduled promises blocks. + + @param timeout Maximum time to wait. + @return YES if all promises blocks have completed before the timeout and NO otherwise. + */ +FOUNDATION_EXTERN BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) NS_REFINED_FOR_SWIFT; + +@interface FBLPromise(TestingAdditions) + +/** + Dispatch group for promises that is typically used to wait for all scheduled blocks. + */ +@property(class, nonatomic, readonly) dispatch_group_t dispatchGroup NS_REFINED_FOR_SWIFT; + +/** + Properties to get the current state of the promise. + */ +@property(nonatomic, readonly) BOOL isPending NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isFulfilled NS_REFINED_FOR_SWIFT; +@property(nonatomic, readonly) BOOL isRejected NS_REFINED_FOR_SWIFT; + +/** + Set of arbitrary objects to keep strongly while the promise is pending. + Becomes nil after the promise has been resolved. + */ +@property(nonatomic, readonly, nullable) NSMutableSet *pendingObjects NS_REFINED_FOR_SWIFT; + +/** + Value the promise was fulfilled with. + Can be nil if the promise is still pending, was resolved with nil or after it has been rejected. + */ +@property(nonatomic, readonly, nullable) Value value NS_REFINED_FOR_SWIFT; + +/** + Error the promise was rejected with. + Can be nil if the promise is still pending or after it has been fulfilled. + */ +@property(nonatomic, readonly, nullable) NSError *error NS_REFINED_FOR_SWIFT; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h new file mode 100644 index 0000000..32027e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Then.h @@ -0,0 +1,63 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ThenAdditions) + +typedef id __nullable (^FBLPromiseThenWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously only + when the receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with + the same error. + + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise which eventually gets resolved with resolution returned from `work` + block: either value, error or another promise. The `work` block is executed asynchronously when the + receiver is fulfilled. If receiver is rejected, the returned promise is also rejected with the same + error. + + @param queue A queue to invoke the `work` block on. + @param work A block to handle the value that receiver was fulfilled with. + @return A new pending promise to be resolved with resolution returned from the `work` block. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + then:(FBLPromiseThenWorkBlock)work NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `then` operators. + Usage: promise.then(^id(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ThenAdditions) + +- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h new file mode 100644 index 0000000..184ba16 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Timeout.h @@ -0,0 +1,57 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(TimeoutAdditions) + +/** + Waits for a promise with the specified `timeout`. + + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)timeout:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE(""); + +/** + Waits for a promise with the specified `timeout`. + + @param queue A queue to dispatch on. + @param interval Time to wait in seconds. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + timeout:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `timeout` operators. + Usage: promise.timeout(...) + */ +@interface FBLPromise(DotSyntax_TimeoutAdditions) + +- (FBLPromise* (^)(NSTimeInterval))timeout FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h new file mode 100644 index 0000000..9dfa2f1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Validate.h @@ -0,0 +1,60 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FBLPromise(ValidateAdditions) + +typedef BOOL (^FBLPromiseValidateWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)validate:(FBLPromiseValidateWorkBlock)predicate NS_SWIFT_UNAVAILABLE(""); + +/** + Validates a fulfilled value or rejects the value if it can not be validated. + + @param queue A queue to dispatch on. + @param predicate An expression to validate. + @return A new pending promise that gets either resolved with same resolution as the receiver or + rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`. + */ +- (FBLPromise *)onQueue:(dispatch_queue_t)queue + validate:(FBLPromiseValidateWorkBlock)predicate NS_REFINED_FOR_SWIFT; + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `validate` operators. + Usage: promise.validate(^BOOL(id value) { ... }) + */ +@interface FBLPromise(DotSyntax_ValidateAdditions) + +- (FBLPromise * (^)(FBLPromiseValidateWorkBlock))validate FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); +- (FBLPromise * (^)(dispatch_queue_t, FBLPromiseValidateWorkBlock))validateOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h new file mode 100644 index 0000000..664e1bb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise+Wrap.h @@ -0,0 +1,316 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Different types of completion handlers available to be wrapped with promise. + */ +typedef void (^FBLPromiseCompletion)(void) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectCompletion)(id __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorCompletion)(NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseObjectOrErrorCompletion)(id __nullable, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseErrorOrObjectCompletion)(NSError* __nullable, id __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromise2ObjectsOrErrorCompletion)(id __nullable, id __nullable, + NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolCompletion)(BOOL) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseBoolOrErrorCompletion)(BOOL, NSError* __nullable) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerCompletion)(NSInteger) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseIntegerOrErrorCompletion)(NSInteger, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleCompletion)(double) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseDoubleOrErrorCompletion)(double, NSError* __nullable) + NS_SWIFT_UNAVAILABLE(""); + +/** + Provides an easy way to convert methods that use common callback patterns into promises. + */ +@interface FBLPromise(WrapAdditions) + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)wrapCompletion:(void (^)(FBLPromiseCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with `nil` when completion handler is invoked. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapCompletion:(void (^)(FBLPromiseCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectCompletion:(void (^)(FBLPromiseObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error provided by completion handler. + If error is `nil`, fulfills with `nil`, otherwise rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorCompletion:(void (^)(FBLPromiseErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)wrapObjectOrErrorCompletion: + (void (^)(FBLPromiseObjectOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an object provided by completion handler if error is `nil`. + Otherwise, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapObjectOrErrorCompletion:(void (^)(FBLPromiseObjectOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)wrapErrorOrObjectCompletion: + (void (^)(FBLPromiseErrorOrObjectCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an error or object provided by completion handler. If error + is not `nil`, rejects with the error. + */ ++ (instancetype)onQueue:(dispatch_queue_t)queue + wrapErrorOrObjectCompletion:(void (^)(FBLPromiseErrorOrObjectCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)wrap2ObjectsOrErrorCompletion: + (void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an array of objects provided by completion handler in order + if error is `nil`. Otherwise, rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrap2ObjectsOrErrorCompletion:(void (^)(FBLPromise2ObjectsOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolCompletion:(void (^)(FBLPromiseBoolCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapBoolOrErrorCompletion: + (void (^)(FBLPromiseBoolOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapBoolOrErrorCompletion:(void (^)(FBLPromiseBoolOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerCompletion:(void (^)(FBLPromiseIntegerCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapIntegerOrErrorCompletion: + (void (^)(FBLPromiseIntegerOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapIntegerOrErrorCompletion:(void (^)(FBLPromiseIntegerOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleCompletion:(void (^)(FBLPromiseDoubleCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +/** + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)wrapDoubleOrErrorCompletion: + (void (^)(FBLPromiseDoubleOrErrorCompletion handler))work NS_SWIFT_UNAVAILABLE(""); + +/** + @param queue A queue to invoke the `work` block on. + @param work A block to perform any operations needed to resolve the promise. + @returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`. + Otherwise rejects with the error. + */ ++ (FBLPromise*)onQueue:(dispatch_queue_t)queue + wrapDoubleOrErrorCompletion:(void (^)(FBLPromiseDoubleOrErrorCompletion handler))work + NS_SWIFT_UNAVAILABLE(""); + +@end + +/** + Convenience dot-syntax wrappers for `FBLPromise` `wrap` operators. + Usage: FBLPromise.wrapCompletion(^(FBLPromiseCompletion handler) {...}) + */ +@interface FBLPromise(DotSyntax_WrapAdditions) + ++ (FBLPromise* (^)(void (^)(FBLPromiseCompletion)))wrapCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseCompletion)))wrapCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseObjectCompletion)))wrapObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletion FBL_PROMISES_DOT_SYNTAX + NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseErrorCompletion)))wrapErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseObjectOrErrorCompletion)))wrapObjectOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseErrorOrObjectCompletion)))wrapErrorOrObjectCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromise2ObjectsOrErrorCompletion))) + wrap2ObjectsOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolCompletion)))wrapBoolCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseBoolOrErrorCompletion)))wrapBoolOrErrorCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseIntegerCompletion)))wrapIntegerCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseIntegerOrErrorCompletion))) + wrapIntegerOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletion + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, + void (^)(FBLPromiseDoubleCompletion)))wrapDoubleCompletionOn + FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletion FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (FBLPromise* (^)(dispatch_queue_t, void (^)(FBLPromiseDoubleOrErrorCompletion))) + wrapDoubleOrErrorCompletionOn FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h new file mode 100644 index 0000000..cec6336 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromise.h @@ -0,0 +1,82 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromiseError.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Promises synchronization construct in Objective-C. + */ +@interface FBLPromise<__covariant Value> : NSObject + +/** + Default dispatch queue used for `FBLPromise`, which is `main` if a queue is not specified. + */ +@property(class) dispatch_queue_t defaultDispatchQueue NS_REFINED_FOR_SWIFT; + +/** + Creates a pending promise. + */ ++ (instancetype)pendingPromise NS_REFINED_FOR_SWIFT; + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ ++ (instancetype)resolvedWith:(nullable id)resolution NS_REFINED_FOR_SWIFT; + +/** + Synchronously fulfills the promise with a value. + + @param value An arbitrary value to fulfill the promise with, including `nil`. + */ +- (void)fulfill:(nullable Value)value NS_REFINED_FOR_SWIFT; + +/** + Synchronously rejects the promise with an error. + + @param error An error to reject the promise with. + */ +- (void)reject:(NSError *)error NS_REFINED_FOR_SWIFT; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@end + +#ifdef FBL_PROMISES_DOT_SYNTAX_IS_DEPRECATED +#define FBL_PROMISES_DOT_SYNTAX __attribute__((deprecated)) +#else +#define FBL_PROMISES_DOT_SYNTAX +#endif + +@interface FBLPromise(DotSyntaxAdditions) + +/** + Convenience dot-syntax wrappers for FBLPromise. + Usage: FBLPromise.pending() + FBLPromise.resolved(value) + + */ ++ (instancetype (^)(void))pending FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); ++ (instancetype (^)(id __nullable))resolved FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h new file mode 100644 index 0000000..d37af53 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromiseError.h @@ -0,0 +1,43 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXTERN NSErrorDomain const FBLPromiseErrorDomain NS_REFINED_FOR_SWIFT; + +/** + Possible error codes in `FBLPromiseErrorDomain`. + */ +typedef NS_ENUM(NSInteger, FBLPromiseErrorCode) { + /** Promise failed to resolve in time. */ + FBLPromiseErrorCodeTimedOut = 1, + /** Validation predicate returned false. */ + FBLPromiseErrorCodeValidationFailure = 2, +} NS_REFINED_FOR_SWIFT; + +NS_INLINE BOOL FBLPromiseErrorIsTimedOut(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeTimedOut; +} + +NS_INLINE BOOL FBLPromiseErrorIsValidationFailure(NSError *error) NS_SWIFT_UNAVAILABLE("") { + return error.domain == FBLPromiseErrorDomain && + error.code == FBLPromiseErrorCodeValidationFailure; +} + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h new file mode 100644 index 0000000..7a132f2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromisePrivate.h @@ -0,0 +1,66 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+Testing.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Miscellaneous low-level private interfaces available to extend standard FBLPromise functionality. + */ +@interface FBLPromise() + +typedef void (^FBLPromiseOnFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE(""); +typedef void (^FBLPromiseOnRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedFulfillBlock)(Value __nullable value) + NS_SWIFT_UNAVAILABLE(""); +typedef id __nullable (^__nullable FBLPromiseChainedRejectBlock)(NSError *error) + NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a pending promise. + */ +- (instancetype)initPending NS_SWIFT_UNAVAILABLE(""); + +/** + Creates a resolved promise. + + @param resolution An object to resolve the promise with: either a value or an error. + @return A new resolved promise. + */ +- (instancetype)initWithResolution:(nullable id)resolution NS_SWIFT_UNAVAILABLE(""); + +/** + Invokes `fulfill` and `reject` blocks on `queue` when the receiver gets either fulfilled or + rejected respectively. + */ +- (void)observeOnQueue:(dispatch_queue_t)queue + fulfill:(FBLPromiseOnFulfillBlock)onFulfill + reject:(FBLPromiseOnRejectBlock)onReject NS_SWIFT_UNAVAILABLE(""); + +/** + Returns a new promise which gets resolved with the return value of `chainedFulfill` or + `chainedReject` blocks respectively. The blocks are invoked when the receiver gets either + fulfilled or rejected. If `nil` is passed to either block arg, the returned promise is resolved + with the same resolution as the receiver. + */ +- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue + chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill + chainedReject:(FBLPromiseChainedRejectBlock)chainedReject NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h new file mode 100644 index 0000000..2d90bad --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/PromisesObjC/Sources/FBLPromises/include/FBLPromises.h @@ -0,0 +1,32 @@ +/** + Copyright 2018 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Firebase/Firebase.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/Firebase/Firebase.xcconfig new file mode 100644 index 0000000..c7f15b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Firebase/Firebase.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Firebase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Firebase" "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/Firebase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig new file mode 100644 index 0000000..c9dc3f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAnalytics/FirebaseAnalytics.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAnalytics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAnalytics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig new file mode 100644 index 0000000..316604a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseAuthInterop/FirebaseAuthInterop.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseAuthInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseAuthInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist new file mode 100644 index 0000000..43ee74c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.6.2 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m new file mode 100644 index 0000000..4f1eb27 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCore : NSObject +@end +@implementation PodsDummy_FirebaseCore +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h new file mode 100644 index 0000000..102aecb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRApp.h" +#import "FIRConfiguration.h" +#import "FirebaseCore.h" +#import "FIRLoggerLevel.h" +#import "FIROptions.h" + +FOUNDATION_EXPORT double FirebaseCoreVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap new file mode 100644 index 0000000..4c38b87 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCore { + umbrella header "FirebaseCore-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig new file mode 100644 index 0000000..861154b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCore/FirebaseCore.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRCore_VERSION=6.6.2 Firebase_VERSION=6.17.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}" +OTHER_CFLAGS = $(inherited) -fno-autolink +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCore +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist new file mode 100644 index 0000000..2a9158a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m new file mode 100644 index 0000000..224d263 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseCoreDiagnostics : NSObject +@end +@implementation PodsDummy_FirebaseCoreDiagnostics +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h new file mode 100644 index 0000000..d6c0706 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "firebasecore.nanopb.h" + +FOUNDATION_EXPORT double FirebaseCoreDiagnosticsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseCoreDiagnosticsVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap new file mode 100644 index 0000000..d9cad8b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseCoreDiagnostics { + umbrella header "FirebaseCoreDiagnostics-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig new file mode 100644 index 0000000..08d790f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}/Firebase/CoreDiagnostics/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnostics +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig new file mode 100644 index 0000000..66fd960 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseCoreDiagnosticsInterop/FirebaseCoreDiagnosticsInterop.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnosticsInterop +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/FirebaseCoreDiagnosticsInterop" "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseCoreDiagnosticsInterop +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist new file mode 100644 index 0000000..059bf7b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.1.4 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m new file mode 100644 index 0000000..40813e7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseDatabase : NSObject +@end +@implementation PodsDummy_FirebaseDatabase +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h new file mode 100644 index 0000000..b9b40ff --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase-umbrella.h @@ -0,0 +1,25 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FIRDatabase.h" +#import "FIRDatabaseQuery.h" +#import "FIRDatabaseReference.h" +#import "FIRDataEventType.h" +#import "FIRDataSnapshot.h" +#import "FirebaseDatabase.h" +#import "FIRMutableData.h" +#import "FIRServerValue.h" +#import "FIRTransactionResult.h" + +FOUNDATION_EXPORT double FirebaseDatabaseVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseDatabaseVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap new file mode 100644 index 0000000..7424a95 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseDatabase { + umbrella header "FirebaseDatabase-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig new file mode 100644 index 0000000..293f459 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseDatabase/FirebaseDatabase.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRDatabase_VERSION=6.1.4 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseDatabase +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist new file mode 100644 index 0000000..21a30b4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m new file mode 100644 index 0000000..ae19551 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstallations : NSObject +@end +@implementation PodsDummy_FirebaseInstallations +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h new file mode 100644 index 0000000..78e5979 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations-umbrella.h @@ -0,0 +1,21 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstallations.h" +#import "FIRInstallations.h" +#import "FIRInstallationsAuthTokenResult.h" +#import "FIRInstallationsErrors.h" +#import "FIRInstallationsVersion.h" + +FOUNDATION_EXPORT double FirebaseInstallationsVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstallationsVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap new file mode 100644 index 0000000..f6e2a29 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstallations { + umbrella header "FirebaseInstallations-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig new file mode 100644 index 0000000..bf477db --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstallations/FirebaseInstallations.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstallations_LIB_VERSION=1.1.0 FIR_INSTALLATIONS_ALLOWS_INCOMPATIBLE_IID_VERSION=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstallations +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist new file mode 100644 index 0000000..33563de --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.3.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m new file mode 100644 index 0000000..937a03d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseInstanceID : NSObject +@end +@implementation PodsDummy_FirebaseInstanceID +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h new file mode 100644 index 0000000..90ba5de --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID-umbrella.h @@ -0,0 +1,18 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseInstanceID.h" +#import "FIRInstanceID.h" + +FOUNDATION_EXPORT double FirebaseInstanceIDVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseInstanceIDVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap new file mode 100644 index 0000000..ff5248f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseInstanceID { + umbrella header "FirebaseInstanceID-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig new file mode 100644 index 0000000..f24d49f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseInstanceID/FirebaseInstanceID.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRInstanceID_LIB_VERSION=4.3.1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseInstanceID +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist new file mode 100644 index 0000000..078bbf3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.5.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m new file mode 100644 index 0000000..15945ee --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_FirebaseStorage : NSObject +@end +@implementation PodsDummy_FirebaseStorage +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h new file mode 100644 index 0000000..40d6144 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage-umbrella.h @@ -0,0 +1,27 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FirebaseStorage.h" +#import "FIRStorage.h" +#import "FIRStorageConstants.h" +#import "FIRStorageDownloadTask.h" +#import "FIRStorageListResult.h" +#import "FIRStorageMetadata.h" +#import "FIRStorageObservableTask.h" +#import "FIRStorageReference.h" +#import "FIRStorageTask.h" +#import "FIRStorageTaskSnapshot.h" +#import "FIRStorageUploadTask.h" + +FOUNDATION_EXPORT double FirebaseStorageVersionNumber; +FOUNDATION_EXPORT const unsigned char FirebaseStorageVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap new file mode 100644 index 0000000..627ff18 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.modulemap @@ -0,0 +1,6 @@ +framework module FirebaseStorage { + umbrella header "FirebaseStorage-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.xcconfig new file mode 100644 index 0000000..a45c21d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/FirebaseStorage/FirebaseStorage.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 FIRStorage_VERSION=3.5.0 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_TARGET_SRCROOT}" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/FirebaseStorage +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist new file mode 100644 index 0000000..10f280e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.3.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m new file mode 100644 index 0000000..13d68b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GTMSessionFetcher : NSObject +@end +@implementation PodsDummy_GTMSessionFetcher +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h new file mode 100644 index 0000000..1c0b7b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher-umbrella.h @@ -0,0 +1,20 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GTMSessionFetcher.h" +#import "GTMSessionFetcherLogging.h" +#import "GTMSessionFetcherService.h" +#import "GTMSessionUploadFetcher.h" + +FOUNDATION_EXPORT double GTMSessionFetcherVersionNumber; +FOUNDATION_EXPORT const unsigned char GTMSessionFetcherVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap new file mode 100644 index 0000000..5121a4d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.modulemap @@ -0,0 +1,6 @@ +framework module GTMSessionFetcher { + umbrella header "GTMSessionFetcher-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.xcconfig new file mode 100644 index 0000000..af4ab71 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GTMSessionFetcher/GTMSessionFetcher.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -framework "Security" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GTMSessionFetcher +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig new file mode 100644 index 0000000..b2e9274 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement.xcconfig @@ -0,0 +1,11 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleAppMeasurement +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "StoreKit" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleAppMeasurement +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist new file mode 100644 index 0000000..3424ca6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 4.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m new file mode 100644 index 0000000..9a08ec3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransport : NSObject +@end +@implementation PodsDummy_GoogleDataTransport +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h new file mode 100644 index 0000000..6b79543 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport-umbrella.h @@ -0,0 +1,33 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GDTCORAssert.h" +#import "GDTCORClock.h" +#import "GDTCORConsoleLogger.h" +#import "GDTCORDataFuture.h" +#import "GDTCOREvent.h" +#import "GDTCOREventDataObject.h" +#import "GDTCOREventTransformer.h" +#import "GDTCORLifecycle.h" +#import "GDTCORPlatform.h" +#import "GDTCORPrioritizer.h" +#import "GDTCORRegistrar.h" +#import "GDTCORStoredEvent.h" +#import "GDTCORTargets.h" +#import "GDTCORTransport.h" +#import "GDTCORUploader.h" +#import "GDTCORUploadPackage.h" +#import "GoogleDataTransport.h" + +FOUNDATION_EXPORT double GoogleDataTransportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap new file mode 100644 index 0000000..8a67414 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransport { + umbrella header "GoogleDataTransport-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig new file mode 100644 index 0000000..67373ab --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransport/GoogleDataTransport.xcconfig @@ -0,0 +1,13 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GDTCOR_VERSION=4.0.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist new file mode 100644 index 0000000..7b6b52a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.4.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m new file mode 100644 index 0000000..3c7f556 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleDataTransportCCTSupport : NSObject +@end +@implementation PodsDummy_GoogleDataTransportCCTSupport +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h new file mode 100644 index 0000000..7f5ac1c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport-umbrella.h @@ -0,0 +1,17 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "cct.nanopb.h" + +FOUNDATION_EXPORT double GoogleDataTransportCCTSupportVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleDataTransportCCTSupportVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap new file mode 100644 index 0000000..7cec8f0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.modulemap @@ -0,0 +1,6 @@ +framework module GoogleDataTransportCCTSupport { + umbrella header "GoogleDataTransportCCTSupport-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig new file mode 100644 index 0000000..d54ea79 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.xcconfig @@ -0,0 +1,14 @@ +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 GDTCCTSUPPORT_VERSION=1.4.0 +GCC_TREAT_WARNINGS_AS_ERRORS = YES +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/GoogleDataTransportCCTSupport/" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleDataTransportCCTSupport +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist new file mode 100644 index 0000000..07e37a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 6.5.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m new file mode 100644 index 0000000..98ac4e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_GoogleUtilities : NSObject +@end +@implementation PodsDummy_GoogleUtilities +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h new file mode 100644 index 0000000..508e631 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities-umbrella.h @@ -0,0 +1,19 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "GULLoggerLevel.h" +#import "GULLoggerCodes.h" +#import "GULNSData+zlib.h" + +FOUNDATION_EXPORT double GoogleUtilitiesVersionNumber; +FOUNDATION_EXPORT const unsigned char GoogleUtilitiesVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap new file mode 100644 index 0000000..491dd0a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.modulemap @@ -0,0 +1,6 @@ +framework module GoogleUtilities { + umbrella header "GoogleUtilities-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig new file mode 100644 index 0000000..4604138 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/GoogleUtilities/GoogleUtilities.xcconfig @@ -0,0 +1,12 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities +GCC_C_LANGUAGE_STANDARD = c99 +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}" +OTHER_LDFLAGS = $(inherited) -l"z" -framework "Security" -framework "SystemConfiguration" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/GoogleUtilities +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.markdown b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.markdown new file mode 100644 index 0000000..4ee54fd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.markdown @@ -0,0 +1,2995 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## Firebase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseAnalytics + +Copyright 2020 Google + +## FirebaseAuthInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCore + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnostics + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseCoreDiagnosticsInterop + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseDatabase + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstallations + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseInstanceID + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## FirebaseStorage + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GTMSessionFetcher + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleAppMeasurement + +Copyright 2020 Google + +## GoogleDataTransport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleDataTransportCCTSupport + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## GoogleUtilities + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +iPhone Dev Wiki +Crack Prevention: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at Landon +Fuller's blog + + +## PromisesObjC + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +## leveldb-library + +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +## nanopb + +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + +Generated by CocoaPods - https://cocoapods.org diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.plist new file mode 100644 index 0000000..25e7bfd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-acknowledgements.plist @@ -0,0 +1,3129 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + Firebase + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + FirebaseAnalytics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseAuthInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCore + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnostics + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseCoreDiagnosticsInterop + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseDatabase + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstallations + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseInstanceID + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + FirebaseStorage + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GTMSessionFetcher + Type + PSGroupSpecifier + + + FooterText + Copyright 2020 Google + License + Copyright + Title + GoogleAppMeasurement + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + GoogleDataTransportCCTSupport + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +================================================================================ + +The following copyright from Landon J. Fuller applies to the isAppEncrypted +function in Environment/third_party/GULAppEnvironmentUtil.m. + +Copyright (c) 2017 Landon J. Fuller <landon@landonf.org> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Comment from +<a href="http://iphonedevwiki.net/index.php/Crack_prevention">iPhone Dev Wiki +Crack Prevention</a>: App Store binaries are signed by both their developer +and Apple. This encrypts the binary so that decryption keys are needed in order +to make the binary readable. When iOS executes the binary, the decryption keys +are used to decrypt the binary into a readable state where it is then loaded +into memory and executed. iOS can tell the encryption status of a binary via the +cryptid structure member of LC_ENCRYPTION_INFO MachO load command. If cryptid is +a non-zero value then the binary is encrypted. + +'Cracking' works by letting the kernel decrypt the binary then siphoning the +decrypted data into a new binary file, resigning, and repackaging. This will +only work on jailbroken devices as codesignature validation has been removed. +Resigning takes place because while the codesignature doesn't have to be valid +thanks to the jailbreak, it does have to be in place unless you have AppSync or +similar to disable codesignature checks. + +More information at <a href="http://landonf.org/2009/02/index.html">Landon +Fuller's blog</a> + + License + Apache + Title + GoogleUtilities + Type + PSGroupSpecifier + + + FooterText + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + License + Apache + Title + PromisesObjC + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + License + New BSD + Title + leveldb-library + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2011 Petteri Aimonen <jpa at nanopb.mail.kapsi.fi> + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + + License + zlib + Title + nanopb + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-dummy.m new file mode 100644 index 0000000..ddd148d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PediatricPancreas_Storyboard : NSObject +@end +@implementation PodsDummy_Pods_PediatricPancreas_Storyboard +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-input-files.xcfilelist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-input-files.xcfilelist new file mode 100644 index 0000000..270cfc9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-input-files.xcfilelist @@ -0,0 +1,6 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh +${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-output-files.xcfilelist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-output-files.xcfilelist new file mode 100644 index 0000000..232ef83 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Debug-output-files.xcfilelist @@ -0,0 +1,5 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-input-files.xcfilelist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-input-files.xcfilelist new file mode 100644 index 0000000..270cfc9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-input-files.xcfilelist @@ -0,0 +1,6 @@ +${PODS_ROOT}/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh +${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework +${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework +${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework +${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework +${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-output-files.xcfilelist b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-output-files.xcfilelist new file mode 100644 index 0000000..232ef83 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks-Release-output-files.xcfilelist @@ -0,0 +1,5 @@ +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/leveldb.framework +${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh new file mode 100755 index 0000000..2200ff2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-frameworks.sh @@ -0,0 +1,179 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +function on_error { + echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" +} +trap 'on_error $LINENO' ERR + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + elif [ -L "${binary}" ]; then + echo "Destination binary is symlinked..." + dirname="$(dirname "${binary}")" + binary="${dirname}/$(readlink "${binary}")" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identity + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework" + install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework" + install_framework "${BUILT_PRODUCTS_DIR}/leveldb-library/leveldb.framework" + install_framework "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-umbrella.h new file mode 100644 index 0000000..26026fe --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PediatricPancreas_StoryboardVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PediatricPancreas_StoryboardVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.debug.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.debug.xcconfig new file mode 100644 index 0000000..9ed1a64 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.debug.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage/FirebaseStorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "FirebaseStorage" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "MobileCoreServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.modulemap new file mode 100644 index 0000000..8a6ef0b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PediatricPancreas_Storyboard { + umbrella header "Pods-PediatricPancreas_Storyboard-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.release.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.release.xcconfig new file mode 100644 index 0000000..9ed1a64 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/Pods-PediatricPancreas_Storyboard/Pods-PediatricPancreas_Storyboard.release.xcconfig @@ -0,0 +1,10 @@ +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb" "${PODS_ROOT}/FirebaseAnalytics/Frameworks" "${PODS_ROOT}/GoogleAppMeasurement/Frameworks" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseDatabase/FirebaseDatabase.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstanceID/FirebaseInstanceID.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FirebaseStorage/FirebaseStorage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransport/GoogleDataTransport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleDataTransportCCTSupport/GoogleDataTransportCCTSupport.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library/leveldb.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/nanopb/nanopb.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/Firebase" "${PODS_ROOT}/Headers/Public/FirebaseAuthInterop" "${PODS_ROOT}/Headers/Public/FirebaseCoreDiagnosticsInterop" $(inherited) ${PODS_ROOT}/Firebase/CoreOnly/Sources "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"icucore" -l"sqlite3" -l"z" -framework "CFNetwork" -framework "FBLPromises" -framework "FIRAnalyticsConnector" -framework "FirebaseAnalytics" -framework "FirebaseCore" -framework "FirebaseCoreDiagnostics" -framework "FirebaseDatabase" -framework "FirebaseInstallations" -framework "FirebaseInstanceID" -framework "FirebaseStorage" -framework "Foundation" -framework "GTMSessionFetcher" -framework "GoogleAppMeasurement" -framework "GoogleDataTransport" -framework "GoogleDataTransportCCTSupport" -framework "GoogleUtilities" -framework "MobileCoreServices" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "leveldb" -framework "nanopb" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist new file mode 100644 index 0000000..f5f78f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.2.8 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m new file mode 100644 index 0000000..ab1f210 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PromisesObjC : NSObject +@end +@implementation PodsDummy_PromisesObjC +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h new file mode 100644 index 0000000..5b014a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC-umbrella.h @@ -0,0 +1,36 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "FBLPromise+All.h" +#import "FBLPromise+Always.h" +#import "FBLPromise+Any.h" +#import "FBLPromise+Async.h" +#import "FBLPromise+Await.h" +#import "FBLPromise+Catch.h" +#import "FBLPromise+Delay.h" +#import "FBLPromise+Do.h" +#import "FBLPromise+Race.h" +#import "FBLPromise+Recover.h" +#import "FBLPromise+Reduce.h" +#import "FBLPromise+Retry.h" +#import "FBLPromise+Testing.h" +#import "FBLPromise+Then.h" +#import "FBLPromise+Timeout.h" +#import "FBLPromise+Validate.h" +#import "FBLPromise+Wrap.h" +#import "FBLPromise.h" +#import "FBLPromiseError.h" +#import "FBLPromises.h" + +FOUNDATION_EXPORT double FBLPromisesVersionNumber; +FOUNDATION_EXPORT const unsigned char FBLPromisesVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap new file mode 100644 index 0000000..7d485cd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.modulemap @@ -0,0 +1,6 @@ +framework module FBLPromises { + umbrella header "PromisesObjC-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig new file mode 100644 index 0000000..dac127e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/PromisesObjC/PromisesObjC.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_TARGET_SRCROOT}/Sources/FBLPromises/include" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/PromisesObjC +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist new file mode 100644 index 0000000..da1bc00 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.22.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m new file mode 100644 index 0000000..dba1492 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_leveldb_library : NSObject +@end +@implementation PodsDummy_leveldb_library +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h new file mode 100644 index 0000000..6a45902 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library-umbrella.h @@ -0,0 +1,31 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "c.h" +#import "cache.h" +#import "comparator.h" +#import "db.h" +#import "dumpfile.h" +#import "env.h" +#import "export.h" +#import "filter_policy.h" +#import "iterator.h" +#import "options.h" +#import "slice.h" +#import "status.h" +#import "table.h" +#import "table_builder.h" +#import "write_batch.h" + +FOUNDATION_EXPORT double leveldbVersionNumber; +FOUNDATION_EXPORT const unsigned char leveldbVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap new file mode 100644 index 0000000..fd77435 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.modulemap @@ -0,0 +1,6 @@ +framework module leveldb { + umbrella header "leveldb-library-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig new file mode 100644 index 0000000..d1992a1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/leveldb-library/leveldb-library.xcconfig @@ -0,0 +1,13 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/leveldb-library +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 LEVELDB_IS_BIG_ENDIAN=0 LEVELDB_PLATFORM_POSIX HAVE_FULLFSYNC=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/leveldb-library" "${PODS_ROOT}/leveldb-library/include" +OTHER_LDFLAGS = $(inherited) -l"c++" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/leveldb-library +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_HEADERMAP = No +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES +WARNING_CFLAGS = -Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-Info.plist b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-Info.plist new file mode 100644 index 0000000..bcc2778 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.3.9011 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-dummy.m b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-dummy.m new file mode 100644 index 0000000..b3fa595 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_nanopb : NSObject +@end +@implementation PodsDummy_nanopb +@end diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-prefix.pch b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-umbrella.h b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-umbrella.h new file mode 100644 index 0000000..07e77b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb-umbrella.h @@ -0,0 +1,26 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + +#import "pb.h" +#import "pb_common.h" +#import "pb_decode.h" +#import "pb_encode.h" +#import "pb.h" +#import "pb_decode.h" +#import "pb_common.h" +#import "pb.h" +#import "pb_encode.h" +#import "pb_common.h" + +FOUNDATION_EXPORT double nanopbVersionNumber; +FOUNDATION_EXPORT const unsigned char nanopbVersionString[]; + diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.modulemap b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.modulemap new file mode 100644 index 0000000..e8d4b53 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.modulemap @@ -0,0 +1,6 @@ +framework module nanopb { + umbrella header "nanopb-umbrella.h" + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.xcconfig b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.xcconfig new file mode 100644 index 0000000..8e7193b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/Target Support Files/nanopb/nanopb.xcconfig @@ -0,0 +1,9 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/nanopb +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 $(inherited) PB_FIELD_32BIT=1 PB_NO_PACKED_STRUCTS=1 PB_ENABLE_MALLOC=1 +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/nanopb +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/LICENSE b/PediatricPancreas_Storyboard/Pods/leveldb-library/LICENSE new file mode 100644 index 0000000..8e80208 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/README.md b/PediatricPancreas_Storyboard/Pods/leveldb-library/README.md new file mode 100644 index 0000000..0b660ae --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/README.md @@ -0,0 +1,225 @@ +**LevelDB is a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values.** + +[![Build Status](https://travis-ci.org/google/leveldb.svg?branch=master)](https://travis-ci.org/google/leveldb) +[![Build status](https://ci.appveyor.com/api/projects/status/g2j5j4rfkda6eyw5/branch/master?svg=true)](https://ci.appveyor.com/project/pwnall/leveldb) + +Authors: Sanjay Ghemawat (sanjay@google.com) and Jeff Dean (jeff@google.com) + +# Features + + * Keys and values are arbitrary byte arrays. + * Data is stored sorted by key. + * Callers can provide a custom comparison function to override the sort order. + * The basic operations are `Put(key,value)`, `Get(key)`, `Delete(key)`. + * Multiple changes can be made in one atomic batch. + * Users can create a transient snapshot to get a consistent view of data. + * Forward and backward iteration is supported over the data. + * Data is automatically compressed using the [Snappy compression library](http://google.github.io/snappy/). + * External activity (file system operations etc.) is relayed through a virtual interface so users can customize the operating system interactions. + +# Documentation + + [LevelDB library documentation](https://github.com/google/leveldb/blob/master/doc/index.md) is online and bundled with the source code. + +# Limitations + + * This is not a SQL database. It does not have a relational data model, it does not support SQL queries, and it has no support for indexes. + * Only a single process (possibly multi-threaded) can access a particular database at a time. + * There is no client-server support builtin to the library. An application that needs such support will have to wrap their own server around the library. + +# Building + +This project supports [CMake](https://cmake.org/) out of the box. + +### Build for POSIX + +Quick start: + +```bash +mkdir -p build && cd build +cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build . +``` + +### Building for Windows + +First generate the Visual Studio 2017 project/solution files: + +```cmd +mkdir build +cd build +cmake -G "Visual Studio 15" .. +``` +The default default will build for x86. For 64-bit run: + +```cmd +cmake -G "Visual Studio 15 Win64" .. +``` + +To compile the Windows solution from the command-line: + +```cmd +devenv /build Debug leveldb.sln +``` + +or open leveldb.sln in Visual Studio and build from within. + +Please see the CMake documentation and `CMakeLists.txt` for more advanced usage. + +# Contributing to the leveldb Project + +The leveldb project welcomes contributions. leveldb's primary goal is to be +a reliable and fast key/value store. Changes that are in line with the +features/limitations outlined above, and meet the requirements below, +will be considered. + +Contribution requirements: + +1. **Tested platforms only**. We _generally_ will only accept changes for + platforms that are compiled and tested. This means POSIX (for Linux and + macOS) or Windows. Very small changes will sometimes be accepted, but + consider that more of an exception than the rule. + +2. **Stable API**. We strive very hard to maintain a stable API. Changes that + require changes for projects using leveldb _might_ be rejected without + sufficient benefit to the project. + +3. **Tests**: All changes must be accompanied by a new (or changed) test, or + a sufficient explanation as to why a new (or changed) test is not required. + +4. **Consistent Style**: This project conforms to the + [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html). + To ensure your changes are properly formatted please run: + + ``` + clang-format -i --style=file + ``` + +## Submitting a Pull Request + +Before any pull request will be accepted the author must first sign a +Contributor License Agreement (CLA) at https://cla.developers.google.com/. + +In order to keep the commit timeline linear +[squash](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Squashing-Commits) +your changes down to a single commit and [rebase](https://git-scm.com/docs/git-rebase) +on google/leveldb/master. This keeps the commit timeline linear and more easily sync'ed +with the internal repository at Google. More information at GitHub's +[About Git rebase](https://help.github.com/articles/about-git-rebase/) page. + +# Performance + +Here is a performance report (with explanations) from the run of the +included db_bench program. The results are somewhat noisy, but should +be enough to get a ballpark performance estimate. + +## Setup + +We use a database with a million entries. Each entry has a 16 byte +key, and a 100 byte value. Values used by the benchmark compress to +about half their original size. + + LevelDB: version 1.1 + Date: Sun May 1 12:11:26 2011 + CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz + CPUCache: 4096 KB + Keys: 16 bytes each + Values: 100 bytes each (50 bytes after compression) + Entries: 1000000 + Raw Size: 110.6 MB (estimated) + File Size: 62.9 MB (estimated) + +## Write performance + +The "fill" benchmarks create a brand new database, in either +sequential, or random order. The "fillsync" benchmark flushes data +from the operating system to the disk after every operation; the other +write operations leave the data sitting in the operating system buffer +cache for a while. The "overwrite" benchmark does random writes that +update existing keys in the database. + + fillseq : 1.765 micros/op; 62.7 MB/s + fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops) + fillrandom : 2.460 micros/op; 45.0 MB/s + overwrite : 2.380 micros/op; 46.5 MB/s + +Each "op" above corresponds to a write of a single key/value pair. +I.e., a random write benchmark goes at approximately 400,000 writes per second. + +Each "fillsync" operation costs much less (0.3 millisecond) +than a disk seek (typically 10 milliseconds). We suspect that this is +because the hard disk itself is buffering the update in its memory and +responding before the data has been written to the platter. This may +or may not be safe based on whether or not the hard disk has enough +power to save its memory in the event of a power failure. + +## Read performance + +We list the performance of reading sequentially in both the forward +and reverse direction, and also the performance of a random lookup. +Note that the database created by the benchmark is quite small. +Therefore the report characterizes the performance of leveldb when the +working set fits in memory. The cost of reading a piece of data that +is not present in the operating system buffer cache will be dominated +by the one or two disk seeks needed to fetch the data from disk. +Write performance will be mostly unaffected by whether or not the +working set fits in memory. + + readrandom : 16.677 micros/op; (approximately 60,000 reads per second) + readseq : 0.476 micros/op; 232.3 MB/s + readreverse : 0.724 micros/op; 152.9 MB/s + +LevelDB compacts its underlying storage data in the background to +improve read performance. The results listed above were done +immediately after a lot of random writes. The results after +compactions (which are usually triggered automatically) are better. + + readrandom : 11.602 micros/op; (approximately 85,000 reads per second) + readseq : 0.423 micros/op; 261.8 MB/s + readreverse : 0.663 micros/op; 166.9 MB/s + +Some of the high cost of reads comes from repeated decompression of blocks +read from disk. If we supply enough cache to the leveldb so it can hold the +uncompressed blocks in memory, the read performance improves again: + + readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction) + readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction) + +## Repository contents + +See [doc/index.md](doc/index.md) for more explanation. See +[doc/impl.md](doc/impl.md) for a brief overview of the implementation. + +The public interface is in include/*.h. Callers should not include or +rely on the details of any other header files in this package. Those +internal APIs may be changed without warning. + +Guide to header files: + +* **include/db.h**: Main interface to the DB: Start here + +* **include/options.h**: Control over the behavior of an entire database, +and also control over the behavior of individual reads and writes. + +* **include/comparator.h**: Abstraction for user-specified comparison function. +If you want just bytewise comparison of keys, you can use the default +comparator, but clients can write their own comparator implementations if they +want custom ordering (e.g. to handle different character encodings, etc.) + +* **include/iterator.h**: Interface for iterating over data. You can get +an iterator from a DB object. + +* **include/write_batch.h**: Interface for atomically applying multiple +updates to a database. + +* **include/slice.h**: A simple module for maintaining a pointer and a +length into some other byte array. + +* **include/status.h**: Status is returned from many of the public interfaces +and is used to report success and various kinds of errors. + +* **include/env.h**: +Abstraction of the OS environment. A posix implementation of this interface is +in util/env_posix.cc + +* **include/table.h, include/table_builder.h**: Lower-level modules that most +clients probably won't use directly diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.cc new file mode 100644 index 0000000..9520ee4 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/builder.h" + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta) { + Status s; + meta->file_size = 0; + iter->SeekToFirst(); + + std::string fname = TableFileName(dbname, meta->number); + if (iter->Valid()) { + WritableFile* file; + s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + + TableBuilder* builder = new TableBuilder(options, file); + meta->smallest.DecodeFrom(iter->key()); + for (; iter->Valid(); iter->Next()) { + Slice key = iter->key(); + meta->largest.DecodeFrom(key); + builder->Add(key, iter->value()); + } + + // Finish and check for builder errors + s = builder->Finish(); + if (s.ok()) { + meta->file_size = builder->FileSize(); + assert(meta->file_size > 0); + } + delete builder; + + // Finish and check for file errors + if (s.ok()) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (s.ok()) { + // Verify that the table is usable + Iterator* it = table_cache->NewIterator(ReadOptions(), meta->number, + meta->file_size); + s = it->status(); + delete it; + } + } + + // Check for input iterator errors + if (!iter->status().ok()) { + s = iter->status(); + } + + if (s.ok() && meta->file_size > 0) { + // Keep it + } else { + env->DeleteFile(fname); + } + return s; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.h new file mode 100644 index 0000000..7bd0b80 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/builder.h @@ -0,0 +1,30 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_BUILDER_H_ +#define STORAGE_LEVELDB_DB_BUILDER_H_ + +#include "leveldb/status.h" + +namespace leveldb { + +struct Options; +struct FileMetaData; + +class Env; +class Iterator; +class TableCache; +class VersionEdit; + +// Build a Table file from the contents of *iter. The generated file +// will be named according to meta->number. On success, the rest of +// *meta will be filled with metadata about the generated table. +// If no data is present in *iter, meta->file_size will be set to +// zero, and no Table file will be produced. +Status BuildTable(const std::string& dbname, Env* env, const Options& options, + TableCache* table_cache, Iterator* iter, FileMetaData* meta); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_BUILDER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/c.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/c.cc new file mode 100644 index 0000000..e0f3367 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/c.cc @@ -0,0 +1,566 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/c.h" + +#include + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/write_batch.h" + +using leveldb::Cache; +using leveldb::Comparator; +using leveldb::CompressionType; +using leveldb::DB; +using leveldb::Env; +using leveldb::FileLock; +using leveldb::FilterPolicy; +using leveldb::Iterator; +using leveldb::kMajorVersion; +using leveldb::kMinorVersion; +using leveldb::Logger; +using leveldb::NewBloomFilterPolicy; +using leveldb::NewLRUCache; +using leveldb::Options; +using leveldb::RandomAccessFile; +using leveldb::Range; +using leveldb::ReadOptions; +using leveldb::SequentialFile; +using leveldb::Slice; +using leveldb::Snapshot; +using leveldb::Status; +using leveldb::WritableFile; +using leveldb::WriteBatch; +using leveldb::WriteOptions; + +extern "C" { + +struct leveldb_t { + DB* rep; +}; +struct leveldb_iterator_t { + Iterator* rep; +}; +struct leveldb_writebatch_t { + WriteBatch rep; +}; +struct leveldb_snapshot_t { + const Snapshot* rep; +}; +struct leveldb_readoptions_t { + ReadOptions rep; +}; +struct leveldb_writeoptions_t { + WriteOptions rep; +}; +struct leveldb_options_t { + Options rep; +}; +struct leveldb_cache_t { + Cache* rep; +}; +struct leveldb_seqfile_t { + SequentialFile* rep; +}; +struct leveldb_randomfile_t { + RandomAccessFile* rep; +}; +struct leveldb_writablefile_t { + WritableFile* rep; +}; +struct leveldb_logger_t { + Logger* rep; +}; +struct leveldb_filelock_t { + FileLock* rep; +}; + +struct leveldb_comparator_t : public Comparator { + virtual ~leveldb_comparator_t() { (*destructor_)(state_); } + + virtual int Compare(const Slice& a, const Slice& b) const { + return (*compare_)(state_, a.data(), a.size(), b.data(), b.size()); + } + + virtual const char* Name() const { return (*name_)(state_); } + + // No-ops since the C binding does not support key shortening methods. + virtual void FindShortestSeparator(std::string*, const Slice&) const {} + virtual void FindShortSuccessor(std::string* key) const {} + + void* state_; + void (*destructor_)(void*); + int (*compare_)(void*, const char* a, size_t alen, const char* b, + size_t blen); + const char* (*name_)(void*); +}; + +struct leveldb_filterpolicy_t : public FilterPolicy { + virtual ~leveldb_filterpolicy_t() { (*destructor_)(state_); } + + virtual const char* Name() const { return (*name_)(state_); } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + std::vector key_pointers(n); + std::vector key_sizes(n); + for (int i = 0; i < n; i++) { + key_pointers[i] = keys[i].data(); + key_sizes[i] = keys[i].size(); + } + size_t len; + char* filter = (*create_)(state_, &key_pointers[0], &key_sizes[0], n, &len); + dst->append(filter, len); + free(filter); + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return (*key_match_)(state_, key.data(), key.size(), filter.data(), + filter.size()); + } + + void* state_; + void (*destructor_)(void*); + const char* (*name_)(void*); + char* (*create_)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length); + unsigned char (*key_match_)(void*, const char* key, size_t length, + const char* filter, size_t filter_length); +}; + +struct leveldb_env_t { + Env* rep; + bool is_default; +}; + +static bool SaveError(char** errptr, const Status& s) { + assert(errptr != nullptr); + if (s.ok()) { + return false; + } else if (*errptr == nullptr) { + *errptr = strdup(s.ToString().c_str()); + } else { + // TODO(sanjay): Merge with existing error? + free(*errptr); + *errptr = strdup(s.ToString().c_str()); + } + return true; +} + +static char* CopyString(const std::string& str) { + char* result = reinterpret_cast(malloc(sizeof(char) * str.size())); + memcpy(result, str.data(), sizeof(char) * str.size()); + return result; +} + +leveldb_t* leveldb_open(const leveldb_options_t* options, const char* name, + char** errptr) { + DB* db; + if (SaveError(errptr, DB::Open(options->rep, std::string(name), &db))) { + return nullptr; + } + leveldb_t* result = new leveldb_t; + result->rep = db; + return result; +} + +void leveldb_close(leveldb_t* db) { + delete db->rep; + delete db; +} + +void leveldb_put(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, size_t vallen, + char** errptr) { + SaveError(errptr, + db->rep->Put(options->rep, Slice(key, keylen), Slice(val, vallen))); +} + +void leveldb_delete(leveldb_t* db, const leveldb_writeoptions_t* options, + const char* key, size_t keylen, char** errptr) { + SaveError(errptr, db->rep->Delete(options->rep, Slice(key, keylen))); +} + +void leveldb_write(leveldb_t* db, const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr) { + SaveError(errptr, db->rep->Write(options->rep, &batch->rep)); +} + +char* leveldb_get(leveldb_t* db, const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr) { + char* result = nullptr; + std::string tmp; + Status s = db->rep->Get(options->rep, Slice(key, keylen), &tmp); + if (s.ok()) { + *vallen = tmp.size(); + result = CopyString(tmp); + } else { + *vallen = 0; + if (!s.IsNotFound()) { + SaveError(errptr, s); + } + } + return result; +} + +leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options) { + leveldb_iterator_t* result = new leveldb_iterator_t; + result->rep = db->rep->NewIterator(options->rep); + return result; +} + +const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db) { + leveldb_snapshot_t* result = new leveldb_snapshot_t; + result->rep = db->rep->GetSnapshot(); + return result; +} + +void leveldb_release_snapshot(leveldb_t* db, + const leveldb_snapshot_t* snapshot) { + db->rep->ReleaseSnapshot(snapshot->rep); + delete snapshot; +} + +char* leveldb_property_value(leveldb_t* db, const char* propname) { + std::string tmp; + if (db->rep->GetProperty(Slice(propname), &tmp)) { + // We use strdup() since we expect human readable output. + return strdup(tmp.c_str()); + } else { + return nullptr; + } +} + +void leveldb_approximate_sizes(leveldb_t* db, int num_ranges, + const char* const* range_start_key, + const size_t* range_start_key_len, + const char* const* range_limit_key, + const size_t* range_limit_key_len, + uint64_t* sizes) { + Range* ranges = new Range[num_ranges]; + for (int i = 0; i < num_ranges; i++) { + ranges[i].start = Slice(range_start_key[i], range_start_key_len[i]); + ranges[i].limit = Slice(range_limit_key[i], range_limit_key_len[i]); + } + db->rep->GetApproximateSizes(ranges, num_ranges, sizes); + delete[] ranges; +} + +void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, const char* limit_key, + size_t limit_key_len) { + Slice a, b; + db->rep->CompactRange( + // Pass null Slice if corresponding "const char*" is null + (start_key ? (a = Slice(start_key, start_key_len), &a) : nullptr), + (limit_key ? (b = Slice(limit_key, limit_key_len), &b) : nullptr)); +} + +void leveldb_destroy_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, DestroyDB(name, options->rep)); +} + +void leveldb_repair_db(const leveldb_options_t* options, const char* name, + char** errptr) { + SaveError(errptr, RepairDB(name, options->rep)); +} + +void leveldb_iter_destroy(leveldb_iterator_t* iter) { + delete iter->rep; + delete iter; +} + +unsigned char leveldb_iter_valid(const leveldb_iterator_t* iter) { + return iter->rep->Valid(); +} + +void leveldb_iter_seek_to_first(leveldb_iterator_t* iter) { + iter->rep->SeekToFirst(); +} + +void leveldb_iter_seek_to_last(leveldb_iterator_t* iter) { + iter->rep->SeekToLast(); +} + +void leveldb_iter_seek(leveldb_iterator_t* iter, const char* k, size_t klen) { + iter->rep->Seek(Slice(k, klen)); +} + +void leveldb_iter_next(leveldb_iterator_t* iter) { iter->rep->Next(); } + +void leveldb_iter_prev(leveldb_iterator_t* iter) { iter->rep->Prev(); } + +const char* leveldb_iter_key(const leveldb_iterator_t* iter, size_t* klen) { + Slice s = iter->rep->key(); + *klen = s.size(); + return s.data(); +} + +const char* leveldb_iter_value(const leveldb_iterator_t* iter, size_t* vlen) { + Slice s = iter->rep->value(); + *vlen = s.size(); + return s.data(); +} + +void leveldb_iter_get_error(const leveldb_iterator_t* iter, char** errptr) { + SaveError(errptr, iter->rep->status()); +} + +leveldb_writebatch_t* leveldb_writebatch_create() { + return new leveldb_writebatch_t; +} + +void leveldb_writebatch_destroy(leveldb_writebatch_t* b) { delete b; } + +void leveldb_writebatch_clear(leveldb_writebatch_t* b) { b->rep.Clear(); } + +void leveldb_writebatch_put(leveldb_writebatch_t* b, const char* key, + size_t klen, const char* val, size_t vlen) { + b->rep.Put(Slice(key, klen), Slice(val, vlen)); +} + +void leveldb_writebatch_delete(leveldb_writebatch_t* b, const char* key, + size_t klen) { + b->rep.Delete(Slice(key, klen)); +} + +void leveldb_writebatch_iterate(const leveldb_writebatch_t* b, void* state, + void (*put)(void*, const char* k, size_t klen, + const char* v, size_t vlen), + void (*deleted)(void*, const char* k, + size_t klen)) { + class H : public WriteBatch::Handler { + public: + void* state_; + void (*put_)(void*, const char* k, size_t klen, const char* v, size_t vlen); + void (*deleted_)(void*, const char* k, size_t klen); + virtual void Put(const Slice& key, const Slice& value) { + (*put_)(state_, key.data(), key.size(), value.data(), value.size()); + } + virtual void Delete(const Slice& key) { + (*deleted_)(state_, key.data(), key.size()); + } + }; + H handler; + handler.state_ = state; + handler.put_ = put; + handler.deleted_ = deleted; + b->rep.Iterate(&handler); +} + +void leveldb_writebatch_append(leveldb_writebatch_t* destination, + const leveldb_writebatch_t* source) { + destination->rep.Append(source->rep); +} + +leveldb_options_t* leveldb_options_create() { return new leveldb_options_t; } + +void leveldb_options_destroy(leveldb_options_t* options) { delete options; } + +void leveldb_options_set_comparator(leveldb_options_t* opt, + leveldb_comparator_t* cmp) { + opt->rep.comparator = cmp; +} + +void leveldb_options_set_filter_policy(leveldb_options_t* opt, + leveldb_filterpolicy_t* policy) { + opt->rep.filter_policy = policy; +} + +void leveldb_options_set_create_if_missing(leveldb_options_t* opt, + unsigned char v) { + opt->rep.create_if_missing = v; +} + +void leveldb_options_set_error_if_exists(leveldb_options_t* opt, + unsigned char v) { + opt->rep.error_if_exists = v; +} + +void leveldb_options_set_paranoid_checks(leveldb_options_t* opt, + unsigned char v) { + opt->rep.paranoid_checks = v; +} + +void leveldb_options_set_env(leveldb_options_t* opt, leveldb_env_t* env) { + opt->rep.env = (env ? env->rep : nullptr); +} + +void leveldb_options_set_info_log(leveldb_options_t* opt, leveldb_logger_t* l) { + opt->rep.info_log = (l ? l->rep : nullptr); +} + +void leveldb_options_set_write_buffer_size(leveldb_options_t* opt, size_t s) { + opt->rep.write_buffer_size = s; +} + +void leveldb_options_set_max_open_files(leveldb_options_t* opt, int n) { + opt->rep.max_open_files = n; +} + +void leveldb_options_set_cache(leveldb_options_t* opt, leveldb_cache_t* c) { + opt->rep.block_cache = c->rep; +} + +void leveldb_options_set_block_size(leveldb_options_t* opt, size_t s) { + opt->rep.block_size = s; +} + +void leveldb_options_set_block_restart_interval(leveldb_options_t* opt, int n) { + opt->rep.block_restart_interval = n; +} + +void leveldb_options_set_max_file_size(leveldb_options_t* opt, size_t s) { + opt->rep.max_file_size = s; +} + +void leveldb_options_set_compression(leveldb_options_t* opt, int t) { + opt->rep.compression = static_cast(t); +} + +leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)) { + leveldb_comparator_t* result = new leveldb_comparator_t; + result->state_ = state; + result->destructor_ = destructor; + result->compare_ = compare; + result->name_ = name; + return result; +} + +void leveldb_comparator_destroy(leveldb_comparator_t* cmp) { delete cmp; } + +leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)) { + leveldb_filterpolicy_t* result = new leveldb_filterpolicy_t; + result->state_ = state; + result->destructor_ = destructor; + result->create_ = create_filter; + result->key_match_ = key_may_match; + result->name_ = name; + return result; +} + +void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t* filter) { + delete filter; +} + +leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom(int bits_per_key) { + // Make a leveldb_filterpolicy_t, but override all of its methods so + // they delegate to a NewBloomFilterPolicy() instead of user + // supplied C functions. + struct Wrapper : public leveldb_filterpolicy_t { + static void DoNothing(void*) {} + + ~Wrapper() { delete rep_; } + const char* Name() const { return rep_->Name(); } + void CreateFilter(const Slice* keys, int n, std::string* dst) const { + return rep_->CreateFilter(keys, n, dst); + } + bool KeyMayMatch(const Slice& key, const Slice& filter) const { + return rep_->KeyMayMatch(key, filter); + } + + const FilterPolicy* rep_; + }; + Wrapper* wrapper = new Wrapper; + wrapper->rep_ = NewBloomFilterPolicy(bits_per_key); + wrapper->state_ = nullptr; + wrapper->destructor_ = &Wrapper::DoNothing; + return wrapper; +} + +leveldb_readoptions_t* leveldb_readoptions_create() { + return new leveldb_readoptions_t; +} + +void leveldb_readoptions_destroy(leveldb_readoptions_t* opt) { delete opt; } + +void leveldb_readoptions_set_verify_checksums(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.verify_checksums = v; +} + +void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t* opt, + unsigned char v) { + opt->rep.fill_cache = v; +} + +void leveldb_readoptions_set_snapshot(leveldb_readoptions_t* opt, + const leveldb_snapshot_t* snap) { + opt->rep.snapshot = (snap ? snap->rep : nullptr); +} + +leveldb_writeoptions_t* leveldb_writeoptions_create() { + return new leveldb_writeoptions_t; +} + +void leveldb_writeoptions_destroy(leveldb_writeoptions_t* opt) { delete opt; } + +void leveldb_writeoptions_set_sync(leveldb_writeoptions_t* opt, + unsigned char v) { + opt->rep.sync = v; +} + +leveldb_cache_t* leveldb_cache_create_lru(size_t capacity) { + leveldb_cache_t* c = new leveldb_cache_t; + c->rep = NewLRUCache(capacity); + return c; +} + +void leveldb_cache_destroy(leveldb_cache_t* cache) { + delete cache->rep; + delete cache; +} + +leveldb_env_t* leveldb_create_default_env() { + leveldb_env_t* result = new leveldb_env_t; + result->rep = Env::Default(); + result->is_default = true; + return result; +} + +void leveldb_env_destroy(leveldb_env_t* env) { + if (!env->is_default) delete env->rep; + delete env; +} + +char* leveldb_env_get_test_directory(leveldb_env_t* env) { + std::string result; + if (!env->rep->GetTestDirectory(&result).ok()) { + return nullptr; + } + + char* buffer = static_cast(malloc(result.size() + 1)); + memcpy(buffer, result.data(), result.size()); + buffer[result.size()] = '\0'; + return buffer; +} + +void leveldb_free(void* ptr) { free(ptr); } + +int leveldb_major_version() { return kMajorVersion; } + +int leveldb_minor_version() { return kMinorVersion; } + +} // end extern "C" diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.cc new file mode 100644 index 0000000..761ebf6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.cc @@ -0,0 +1,1550 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_impl.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include "db/builder.h" +#include "db/db_iter.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_set.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/table_builder.h" +#include "port/port.h" +#include "table/block.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" +#include "util/mutexlock.h" + +namespace leveldb { + +const int kNumNonTableCacheFiles = 10; + +// Information kept for every waiting writer +struct DBImpl::Writer { + explicit Writer(port::Mutex* mu) + : batch(nullptr), sync(false), done(false), cv(mu) {} + + Status status; + WriteBatch* batch; + bool sync; + bool done; + port::CondVar cv; +}; + +struct DBImpl::CompactionState { + // Files produced by compaction + struct Output { + uint64_t number; + uint64_t file_size; + InternalKey smallest, largest; + }; + + Output* current_output() { return &outputs[outputs.size() - 1]; } + + explicit CompactionState(Compaction* c) + : compaction(c), + smallest_snapshot(0), + outfile(nullptr), + builder(nullptr), + total_bytes(0) {} + + Compaction* const compaction; + + // Sequence numbers < smallest_snapshot are not significant since we + // will never have to service a snapshot below smallest_snapshot. + // Therefore if we have seen a sequence number S <= smallest_snapshot, + // we can drop all entries for the same key with sequence numbers < S. + SequenceNumber smallest_snapshot; + + std::vector outputs; + + // State kept for output being generated + WritableFile* outfile; + TableBuilder* builder; + + uint64_t total_bytes; +}; + +// Fix user-supplied options to be reasonable +template +static void ClipToRange(T* ptr, V minvalue, V maxvalue) { + if (static_cast(*ptr) > maxvalue) *ptr = maxvalue; + if (static_cast(*ptr) < minvalue) *ptr = minvalue; +} +Options SanitizeOptions(const std::string& dbname, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src) { + Options result = src; + result.comparator = icmp; + result.filter_policy = (src.filter_policy != nullptr) ? ipolicy : nullptr; + ClipToRange(&result.max_open_files, 64 + kNumNonTableCacheFiles, 50000); + ClipToRange(&result.write_buffer_size, 64 << 10, 1 << 30); + ClipToRange(&result.max_file_size, 1 << 20, 1 << 30); + ClipToRange(&result.block_size, 1 << 10, 4 << 20); + if (result.info_log == nullptr) { + // Open a log file in the same directory as the db + src.env->CreateDir(dbname); // In case it does not exist + src.env->RenameFile(InfoLogFileName(dbname), OldInfoLogFileName(dbname)); + Status s = src.env->NewLogger(InfoLogFileName(dbname), &result.info_log); + if (!s.ok()) { + // No place suitable for logging + result.info_log = nullptr; + } + } + if (result.block_cache == nullptr) { + result.block_cache = NewLRUCache(8 << 20); + } + return result; +} + +static int TableCacheSize(const Options& sanitized_options) { + // Reserve ten files or so for other uses and give the rest to TableCache. + return sanitized_options.max_open_files - kNumNonTableCacheFiles; +} + +DBImpl::DBImpl(const Options& raw_options, const std::string& dbname) + : env_(raw_options.env), + internal_comparator_(raw_options.comparator), + internal_filter_policy_(raw_options.filter_policy), + options_(SanitizeOptions(dbname, &internal_comparator_, + &internal_filter_policy_, raw_options)), + owns_info_log_(options_.info_log != raw_options.info_log), + owns_cache_(options_.block_cache != raw_options.block_cache), + dbname_(dbname), + table_cache_(new TableCache(dbname_, options_, TableCacheSize(options_))), + db_lock_(nullptr), + shutting_down_(false), + background_work_finished_signal_(&mutex_), + mem_(nullptr), + imm_(nullptr), + has_imm_(false), + logfile_(nullptr), + logfile_number_(0), + log_(nullptr), + seed_(0), + tmp_batch_(new WriteBatch), + background_compaction_scheduled_(false), + manual_compaction_(nullptr), + versions_(new VersionSet(dbname_, &options_, table_cache_, + &internal_comparator_)) {} + +DBImpl::~DBImpl() { + // Wait for background work to finish. + mutex_.Lock(); + shutting_down_.store(true, std::memory_order_release); + while (background_compaction_scheduled_) { + background_work_finished_signal_.Wait(); + } + mutex_.Unlock(); + + if (db_lock_ != nullptr) { + env_->UnlockFile(db_lock_); + } + + delete versions_; + if (mem_ != nullptr) mem_->Unref(); + if (imm_ != nullptr) imm_->Unref(); + delete tmp_batch_; + delete log_; + delete logfile_; + delete table_cache_; + + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } +} + +Status DBImpl::NewDB() { + VersionEdit new_db; + new_db.SetComparatorName(user_comparator()->Name()); + new_db.SetLogNumber(0); + new_db.SetNextFile(2); + new_db.SetLastSequence(0); + + const std::string manifest = DescriptorFileName(dbname_, 1); + WritableFile* file; + Status s = env_->NewWritableFile(manifest, &file); + if (!s.ok()) { + return s; + } + { + log::Writer log(file); + std::string record; + new_db.EncodeTo(&record); + s = log.AddRecord(record); + if (s.ok()) { + s = file->Close(); + } + } + delete file; + if (s.ok()) { + // Make "CURRENT" file that points to the new manifest file. + s = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(manifest); + } + return s; +} + +void DBImpl::MaybeIgnoreError(Status* s) const { + if (s->ok() || options_.paranoid_checks) { + // No change needed + } else { + Log(options_.info_log, "Ignoring error %s", s->ToString().c_str()); + *s = Status::OK(); + } +} + +void DBImpl::DeleteObsoleteFiles() { + mutex_.AssertHeld(); + + if (!bg_error_.ok()) { + // After a background error, we don't know whether a new version may + // or may not have been committed, so we cannot safely garbage collect. + return; + } + + // Make a set of all of the live files + std::set live = pending_outputs_; + versions_->AddLiveFiles(&live); + + std::vector filenames; + env_->GetChildren(dbname_, &filenames); // Ignoring errors on purpose + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + bool keep = true; + switch (type) { + case kLogFile: + keep = ((number >= versions_->LogNumber()) || + (number == versions_->PrevLogNumber())); + break; + case kDescriptorFile: + // Keep my manifest file, and any newer incarnations' + // (in case there is a race that allows other incarnations) + keep = (number >= versions_->ManifestFileNumber()); + break; + case kTableFile: + keep = (live.find(number) != live.end()); + break; + case kTempFile: + // Any temp files that are currently being written to must + // be recorded in pending_outputs_, which is inserted into "live" + keep = (live.find(number) != live.end()); + break; + case kCurrentFile: + case kDBLockFile: + case kInfoLogFile: + keep = true; + break; + } + + if (!keep) { + if (type == kTableFile) { + table_cache_->Evict(number); + } + Log(options_.info_log, "Delete type=%d #%lld\n", static_cast(type), + static_cast(number)); + env_->DeleteFile(dbname_ + "/" + filenames[i]); + } + } + } +} + +Status DBImpl::Recover(VersionEdit* edit, bool* save_manifest) { + mutex_.AssertHeld(); + + // Ignore error from CreateDir since the creation of the DB is + // committed only when the descriptor is created, and this directory + // may already exist from a previous failed creation attempt. + env_->CreateDir(dbname_); + assert(db_lock_ == nullptr); + Status s = env_->LockFile(LockFileName(dbname_), &db_lock_); + if (!s.ok()) { + return s; + } + + if (!env_->FileExists(CurrentFileName(dbname_))) { + if (options_.create_if_missing) { + s = NewDB(); + if (!s.ok()) { + return s; + } + } else { + return Status::InvalidArgument( + dbname_, "does not exist (create_if_missing is false)"); + } + } else { + if (options_.error_if_exists) { + return Status::InvalidArgument(dbname_, + "exists (error_if_exists is true)"); + } + } + + s = versions_->Recover(save_manifest); + if (!s.ok()) { + return s; + } + SequenceNumber max_sequence(0); + + // Recover from all newer log files than the ones named in the + // descriptor (new log files may have been added by the previous + // incarnation without registering them in the descriptor). + // + // Note that PrevLogNumber() is no longer used, but we pay + // attention to it in case we are recovering a database + // produced by an older version of leveldb. + const uint64_t min_log = versions_->LogNumber(); + const uint64_t prev_log = versions_->PrevLogNumber(); + std::vector filenames; + s = env_->GetChildren(dbname_, &filenames); + if (!s.ok()) { + return s; + } + std::set expected; + versions_->AddLiveFiles(&expected); + uint64_t number; + FileType type; + std::vector logs; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + expected.erase(number); + if (type == kLogFile && ((number >= min_log) || (number == prev_log))) + logs.push_back(number); + } + } + if (!expected.empty()) { + char buf[50]; + snprintf(buf, sizeof(buf), "%d missing files; e.g.", + static_cast(expected.size())); + return Status::Corruption(buf, TableFileName(dbname_, *(expected.begin()))); + } + + // Recover in the order in which the logs were generated + std::sort(logs.begin(), logs.end()); + for (size_t i = 0; i < logs.size(); i++) { + s = RecoverLogFile(logs[i], (i == logs.size() - 1), save_manifest, edit, + &max_sequence); + if (!s.ok()) { + return s; + } + + // The previous incarnation may not have written any MANIFEST + // records after allocating this log number. So we manually + // update the file number allocation counter in VersionSet. + versions_->MarkFileNumberUsed(logs[i]); + } + + if (versions_->LastSequence() < max_sequence) { + versions_->SetLastSequence(max_sequence); + } + + return Status::OK(); +} + +Status DBImpl::RecoverLogFile(uint64_t log_number, bool last_log, + bool* save_manifest, VersionEdit* edit, + SequenceNumber* max_sequence) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + const char* fname; + Status* status; // null if options_.paranoid_checks==false + virtual void Corruption(size_t bytes, const Status& s) { + Log(info_log, "%s%s: dropping %d bytes; %s", + (this->status == nullptr ? "(ignoring error) " : ""), fname, + static_cast(bytes), s.ToString().c_str()); + if (this->status != nullptr && this->status->ok()) *this->status = s; + } + }; + + mutex_.AssertHeld(); + + // Open the log file + std::string fname = LogFileName(dbname_, log_number); + SequentialFile* file; + Status status = env_->NewSequentialFile(fname, &file); + if (!status.ok()) { + MaybeIgnoreError(&status); + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.fname = fname.c_str(); + reporter.status = (options_.paranoid_checks ? &status : nullptr); + // We intentionally make log::Reader do checksumming even if + // paranoid_checks==false so that corruptions cause entire commits + // to be skipped instead of propagating bad information (like overly + // large sequence numbers). + log::Reader reader(file, &reporter, true /*checksum*/, 0 /*initial_offset*/); + Log(options_.info_log, "Recovering log #%llu", + (unsigned long long)log_number); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + int compactions = 0; + MemTable* mem = nullptr; + while (reader.ReadRecord(&record, &scratch) && status.ok()) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + + if (mem == nullptr) { + mem = new MemTable(internal_comparator_); + mem->Ref(); + } + status = WriteBatchInternal::InsertInto(&batch, mem); + MaybeIgnoreError(&status); + if (!status.ok()) { + break; + } + const SequenceNumber last_seq = WriteBatchInternal::Sequence(&batch) + + WriteBatchInternal::Count(&batch) - 1; + if (last_seq > *max_sequence) { + *max_sequence = last_seq; + } + + if (mem->ApproximateMemoryUsage() > options_.write_buffer_size) { + compactions++; + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + mem->Unref(); + mem = nullptr; + if (!status.ok()) { + // Reflect errors immediately so that conditions like full + // file-systems cause the DB::Open() to fail. + break; + } + } + } + + delete file; + + // See if we should keep reusing the last log file. + if (status.ok() && options_.reuse_logs && last_log && compactions == 0) { + assert(logfile_ == nullptr); + assert(log_ == nullptr); + assert(mem_ == nullptr); + uint64_t lfile_size; + if (env_->GetFileSize(fname, &lfile_size).ok() && + env_->NewAppendableFile(fname, &logfile_).ok()) { + Log(options_.info_log, "Reusing old log %s \n", fname.c_str()); + log_ = new log::Writer(logfile_, lfile_size); + logfile_number_ = log_number; + if (mem != nullptr) { + mem_ = mem; + mem = nullptr; + } else { + // mem can be nullptr if lognum exists but was empty. + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + } + } + } + + if (mem != nullptr) { + // mem did not get reused; compact it. + if (status.ok()) { + *save_manifest = true; + status = WriteLevel0Table(mem, edit, nullptr); + } + mem->Unref(); + } + + return status; +} + +Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, + Version* base) { + mutex_.AssertHeld(); + const uint64_t start_micros = env_->NowMicros(); + FileMetaData meta; + meta.number = versions_->NewFileNumber(); + pending_outputs_.insert(meta.number); + Iterator* iter = mem->NewIterator(); + Log(options_.info_log, "Level-0 table #%llu: started", + (unsigned long long)meta.number); + + Status s; + { + mutex_.Unlock(); + s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + mutex_.Lock(); + } + + Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s", + (unsigned long long)meta.number, (unsigned long long)meta.file_size, + s.ToString().c_str()); + delete iter; + pending_outputs_.erase(meta.number); + + // Note that if file_size is zero, the file has been deleted and + // should not be added to the manifest. + int level = 0; + if (s.ok() && meta.file_size > 0) { + const Slice min_user_key = meta.smallest.user_key(); + const Slice max_user_key = meta.largest.user_key(); + if (base != nullptr) { + level = base->PickLevelForMemTableOutput(min_user_key, max_user_key); + } + edit->AddFile(level, meta.number, meta.file_size, meta.smallest, + meta.largest); + } + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros; + stats.bytes_written = meta.file_size; + stats_[level].Add(stats); + return s; +} + +void DBImpl::CompactMemTable() { + mutex_.AssertHeld(); + assert(imm_ != nullptr); + + // Save the contents of the memtable as a new Table + VersionEdit edit; + Version* base = versions_->current(); + base->Ref(); + Status s = WriteLevel0Table(imm_, &edit, base); + base->Unref(); + + if (s.ok() && shutting_down_.load(std::memory_order_acquire)) { + s = Status::IOError("Deleting DB during memtable compaction"); + } + + // Replace immutable memtable with the generated Table + if (s.ok()) { + edit.SetPrevLogNumber(0); + edit.SetLogNumber(logfile_number_); // Earlier logs no longer needed + s = versions_->LogAndApply(&edit, &mutex_); + } + + if (s.ok()) { + // Commit to the new state + imm_->Unref(); + imm_ = nullptr; + has_imm_.store(false, std::memory_order_release); + DeleteObsoleteFiles(); + } else { + RecordBackgroundError(s); + } +} + +void DBImpl::CompactRange(const Slice* begin, const Slice* end) { + int max_level_with_files = 1; + { + MutexLock l(&mutex_); + Version* base = versions_->current(); + for (int level = 1; level < config::kNumLevels; level++) { + if (base->OverlapInLevel(level, begin, end)) { + max_level_with_files = level; + } + } + } + TEST_CompactMemTable(); // TODO(sanjay): Skip if memtable does not overlap + for (int level = 0; level < max_level_with_files; level++) { + TEST_CompactRange(level, begin, end); + } +} + +void DBImpl::TEST_CompactRange(int level, const Slice* begin, + const Slice* end) { + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + + InternalKey begin_storage, end_storage; + + ManualCompaction manual; + manual.level = level; + manual.done = false; + if (begin == nullptr) { + manual.begin = nullptr; + } else { + begin_storage = InternalKey(*begin, kMaxSequenceNumber, kValueTypeForSeek); + manual.begin = &begin_storage; + } + if (end == nullptr) { + manual.end = nullptr; + } else { + end_storage = InternalKey(*end, 0, static_cast(0)); + manual.end = &end_storage; + } + + MutexLock l(&mutex_); + while (!manual.done && !shutting_down_.load(std::memory_order_acquire) && + bg_error_.ok()) { + if (manual_compaction_ == nullptr) { // Idle + manual_compaction_ = &manual; + MaybeScheduleCompaction(); + } else { // Running either my compaction or another compaction. + background_work_finished_signal_.Wait(); + } + } + if (manual_compaction_ == &manual) { + // Cancel my manual compaction since we aborted early for some reason. + manual_compaction_ = nullptr; + } +} + +Status DBImpl::TEST_CompactMemTable() { + // nullptr batch means just wait for earlier writes to be done + Status s = Write(WriteOptions(), nullptr); + if (s.ok()) { + // Wait until the compaction completes + MutexLock l(&mutex_); + while (imm_ != nullptr && bg_error_.ok()) { + background_work_finished_signal_.Wait(); + } + if (imm_ != nullptr) { + s = bg_error_; + } + } + return s; +} + +void DBImpl::RecordBackgroundError(const Status& s) { + mutex_.AssertHeld(); + if (bg_error_.ok()) { + bg_error_ = s; + background_work_finished_signal_.SignalAll(); + } +} + +void DBImpl::MaybeScheduleCompaction() { + mutex_.AssertHeld(); + if (background_compaction_scheduled_) { + // Already scheduled + } else if (shutting_down_.load(std::memory_order_acquire)) { + // DB is being deleted; no more background compactions + } else if (!bg_error_.ok()) { + // Already got an error; no more changes + } else if (imm_ == nullptr && manual_compaction_ == nullptr && + !versions_->NeedsCompaction()) { + // No work to be done + } else { + background_compaction_scheduled_ = true; + env_->Schedule(&DBImpl::BGWork, this); + } +} + +void DBImpl::BGWork(void* db) { + reinterpret_cast(db)->BackgroundCall(); +} + +void DBImpl::BackgroundCall() { + MutexLock l(&mutex_); + assert(background_compaction_scheduled_); + if (shutting_down_.load(std::memory_order_acquire)) { + // No more background work when shutting down. + } else if (!bg_error_.ok()) { + // No more background work after a background error. + } else { + BackgroundCompaction(); + } + + background_compaction_scheduled_ = false; + + // Previous compaction may have produced too many files in a level, + // so reschedule another compaction if needed. + MaybeScheduleCompaction(); + background_work_finished_signal_.SignalAll(); +} + +void DBImpl::BackgroundCompaction() { + mutex_.AssertHeld(); + + if (imm_ != nullptr) { + CompactMemTable(); + return; + } + + Compaction* c; + bool is_manual = (manual_compaction_ != nullptr); + InternalKey manual_end; + if (is_manual) { + ManualCompaction* m = manual_compaction_; + c = versions_->CompactRange(m->level, m->begin, m->end); + m->done = (c == nullptr); + if (c != nullptr) { + manual_end = c->input(0, c->num_input_files(0) - 1)->largest; + } + Log(options_.info_log, + "Manual compaction at level-%d from %s .. %s; will stop at %s\n", + m->level, (m->begin ? m->begin->DebugString().c_str() : "(begin)"), + (m->end ? m->end->DebugString().c_str() : "(end)"), + (m->done ? "(end)" : manual_end.DebugString().c_str())); + } else { + c = versions_->PickCompaction(); + } + + Status status; + if (c == nullptr) { + // Nothing to do + } else if (!is_manual && c->IsTrivialMove()) { + // Move file to next level + assert(c->num_input_files(0) == 1); + FileMetaData* f = c->input(0, 0); + c->edit()->DeleteFile(c->level(), f->number); + c->edit()->AddFile(c->level() + 1, f->number, f->file_size, f->smallest, + f->largest); + status = versions_->LogAndApply(c->edit(), &mutex_); + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n", + static_cast(f->number), c->level() + 1, + static_cast(f->file_size), + status.ToString().c_str(), versions_->LevelSummary(&tmp)); + } else { + CompactionState* compact = new CompactionState(c); + status = DoCompactionWork(compact); + if (!status.ok()) { + RecordBackgroundError(status); + } + CleanupCompaction(compact); + c->ReleaseInputs(); + DeleteObsoleteFiles(); + } + delete c; + + if (status.ok()) { + // Done + } else if (shutting_down_.load(std::memory_order_acquire)) { + // Ignore compaction errors found during shutting down + } else { + Log(options_.info_log, "Compaction error: %s", status.ToString().c_str()); + } + + if (is_manual) { + ManualCompaction* m = manual_compaction_; + if (!status.ok()) { + m->done = true; + } + if (!m->done) { + // We only compacted part of the requested range. Update *m + // to the range that is left to be compacted. + m->tmp_storage = manual_end; + m->begin = &m->tmp_storage; + } + manual_compaction_ = nullptr; + } +} + +void DBImpl::CleanupCompaction(CompactionState* compact) { + mutex_.AssertHeld(); + if (compact->builder != nullptr) { + // May happen if we get a shutdown call in the middle of compaction + compact->builder->Abandon(); + delete compact->builder; + } else { + assert(compact->outfile == nullptr); + } + delete compact->outfile; + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + pending_outputs_.erase(out.number); + } + delete compact; +} + +Status DBImpl::OpenCompactionOutputFile(CompactionState* compact) { + assert(compact != nullptr); + assert(compact->builder == nullptr); + uint64_t file_number; + { + mutex_.Lock(); + file_number = versions_->NewFileNumber(); + pending_outputs_.insert(file_number); + CompactionState::Output out; + out.number = file_number; + out.smallest.Clear(); + out.largest.Clear(); + compact->outputs.push_back(out); + mutex_.Unlock(); + } + + // Make the output file + std::string fname = TableFileName(dbname_, file_number); + Status s = env_->NewWritableFile(fname, &compact->outfile); + if (s.ok()) { + compact->builder = new TableBuilder(options_, compact->outfile); + } + return s; +} + +Status DBImpl::FinishCompactionOutputFile(CompactionState* compact, + Iterator* input) { + assert(compact != nullptr); + assert(compact->outfile != nullptr); + assert(compact->builder != nullptr); + + const uint64_t output_number = compact->current_output()->number; + assert(output_number != 0); + + // Check for iterator errors + Status s = input->status(); + const uint64_t current_entries = compact->builder->NumEntries(); + if (s.ok()) { + s = compact->builder->Finish(); + } else { + compact->builder->Abandon(); + } + const uint64_t current_bytes = compact->builder->FileSize(); + compact->current_output()->file_size = current_bytes; + compact->total_bytes += current_bytes; + delete compact->builder; + compact->builder = nullptr; + + // Finish and check for file errors + if (s.ok()) { + s = compact->outfile->Sync(); + } + if (s.ok()) { + s = compact->outfile->Close(); + } + delete compact->outfile; + compact->outfile = nullptr; + + if (s.ok() && current_entries > 0) { + // Verify that the table is usable + Iterator* iter = + table_cache_->NewIterator(ReadOptions(), output_number, current_bytes); + s = iter->status(); + delete iter; + if (s.ok()) { + Log(options_.info_log, "Generated table #%llu@%d: %lld keys, %lld bytes", + (unsigned long long)output_number, compact->compaction->level(), + (unsigned long long)current_entries, + (unsigned long long)current_bytes); + } + } + return s; +} + +Status DBImpl::InstallCompactionResults(CompactionState* compact) { + mutex_.AssertHeld(); + Log(options_.info_log, "Compacted %d@%d + %d@%d files => %lld bytes", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), compact->compaction->level() + 1, + static_cast(compact->total_bytes)); + + // Add compaction outputs + compact->compaction->AddInputDeletions(compact->compaction->edit()); + const int level = compact->compaction->level(); + for (size_t i = 0; i < compact->outputs.size(); i++) { + const CompactionState::Output& out = compact->outputs[i]; + compact->compaction->edit()->AddFile(level + 1, out.number, out.file_size, + out.smallest, out.largest); + } + return versions_->LogAndApply(compact->compaction->edit(), &mutex_); +} + +Status DBImpl::DoCompactionWork(CompactionState* compact) { + const uint64_t start_micros = env_->NowMicros(); + int64_t imm_micros = 0; // Micros spent doing imm_ compactions + + Log(options_.info_log, "Compacting %d@%d + %d@%d files", + compact->compaction->num_input_files(0), compact->compaction->level(), + compact->compaction->num_input_files(1), + compact->compaction->level() + 1); + + assert(versions_->NumLevelFiles(compact->compaction->level()) > 0); + assert(compact->builder == nullptr); + assert(compact->outfile == nullptr); + if (snapshots_.empty()) { + compact->smallest_snapshot = versions_->LastSequence(); + } else { + compact->smallest_snapshot = snapshots_.oldest()->sequence_number(); + } + + // Release mutex while we're actually doing the compaction work + mutex_.Unlock(); + + Iterator* input = versions_->MakeInputIterator(compact->compaction); + input->SeekToFirst(); + Status status; + ParsedInternalKey ikey; + std::string current_user_key; + bool has_current_user_key = false; + SequenceNumber last_sequence_for_key = kMaxSequenceNumber; + for (; input->Valid() && !shutting_down_.load(std::memory_order_acquire);) { + // Prioritize immutable compaction work + if (has_imm_.load(std::memory_order_relaxed)) { + const uint64_t imm_start = env_->NowMicros(); + mutex_.Lock(); + if (imm_ != nullptr) { + CompactMemTable(); + // Wake up MakeRoomForWrite() if necessary. + background_work_finished_signal_.SignalAll(); + } + mutex_.Unlock(); + imm_micros += (env_->NowMicros() - imm_start); + } + + Slice key = input->key(); + if (compact->compaction->ShouldStopBefore(key) && + compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + + // Handle key/value, add to state, etc. + bool drop = false; + if (!ParseInternalKey(key, &ikey)) { + // Do not hide error keys + current_user_key.clear(); + has_current_user_key = false; + last_sequence_for_key = kMaxSequenceNumber; + } else { + if (!has_current_user_key || + user_comparator()->Compare(ikey.user_key, Slice(current_user_key)) != + 0) { + // First occurrence of this user key + current_user_key.assign(ikey.user_key.data(), ikey.user_key.size()); + has_current_user_key = true; + last_sequence_for_key = kMaxSequenceNumber; + } + + if (last_sequence_for_key <= compact->smallest_snapshot) { + // Hidden by an newer entry for same user key + drop = true; // (A) + } else if (ikey.type == kTypeDeletion && + ikey.sequence <= compact->smallest_snapshot && + compact->compaction->IsBaseLevelForKey(ikey.user_key)) { + // For this user key: + // (1) there is no data in higher levels + // (2) data in lower levels will have larger sequence numbers + // (3) data in layers that are being compacted here and have + // smaller sequence numbers will be dropped in the next + // few iterations of this loop (by rule (A) above). + // Therefore this deletion marker is obsolete and can be dropped. + drop = true; + } + + last_sequence_for_key = ikey.sequence; + } +#if 0 + Log(options_.info_log, + " Compact: %s, seq %d, type: %d %d, drop: %d, is_base: %d, " + "%d smallest_snapshot: %d", + ikey.user_key.ToString().c_str(), + (int)ikey.sequence, ikey.type, kTypeValue, drop, + compact->compaction->IsBaseLevelForKey(ikey.user_key), + (int)last_sequence_for_key, (int)compact->smallest_snapshot); +#endif + + if (!drop) { + // Open output file if necessary + if (compact->builder == nullptr) { + status = OpenCompactionOutputFile(compact); + if (!status.ok()) { + break; + } + } + if (compact->builder->NumEntries() == 0) { + compact->current_output()->smallest.DecodeFrom(key); + } + compact->current_output()->largest.DecodeFrom(key); + compact->builder->Add(key, input->value()); + + // Close output file if it is big enough + if (compact->builder->FileSize() >= + compact->compaction->MaxOutputFileSize()) { + status = FinishCompactionOutputFile(compact, input); + if (!status.ok()) { + break; + } + } + } + + input->Next(); + } + + if (status.ok() && shutting_down_.load(std::memory_order_acquire)) { + status = Status::IOError("Deleting DB during compaction"); + } + if (status.ok() && compact->builder != nullptr) { + status = FinishCompactionOutputFile(compact, input); + } + if (status.ok()) { + status = input->status(); + } + delete input; + input = nullptr; + + CompactionStats stats; + stats.micros = env_->NowMicros() - start_micros - imm_micros; + for (int which = 0; which < 2; which++) { + for (int i = 0; i < compact->compaction->num_input_files(which); i++) { + stats.bytes_read += compact->compaction->input(which, i)->file_size; + } + } + for (size_t i = 0; i < compact->outputs.size(); i++) { + stats.bytes_written += compact->outputs[i].file_size; + } + + mutex_.Lock(); + stats_[compact->compaction->level() + 1].Add(stats); + + if (status.ok()) { + status = InstallCompactionResults(compact); + } + if (!status.ok()) { + RecordBackgroundError(status); + } + VersionSet::LevelSummaryStorage tmp; + Log(options_.info_log, "compacted to: %s", versions_->LevelSummary(&tmp)); + return status; +} + +namespace { + +struct IterState { + port::Mutex* const mu; + Version* const version GUARDED_BY(mu); + MemTable* const mem GUARDED_BY(mu); + MemTable* const imm GUARDED_BY(mu); + + IterState(port::Mutex* mutex, MemTable* mem, MemTable* imm, Version* version) + : mu(mutex), version(version), mem(mem), imm(imm) {} +}; + +static void CleanupIteratorState(void* arg1, void* arg2) { + IterState* state = reinterpret_cast(arg1); + state->mu->Lock(); + state->mem->Unref(); + if (state->imm != nullptr) state->imm->Unref(); + state->version->Unref(); + state->mu->Unlock(); + delete state; +} + +} // anonymous namespace + +Iterator* DBImpl::NewInternalIterator(const ReadOptions& options, + SequenceNumber* latest_snapshot, + uint32_t* seed) { + mutex_.Lock(); + *latest_snapshot = versions_->LastSequence(); + + // Collect together all needed child iterators + std::vector list; + list.push_back(mem_->NewIterator()); + mem_->Ref(); + if (imm_ != nullptr) { + list.push_back(imm_->NewIterator()); + imm_->Ref(); + } + versions_->current()->AddIterators(options, &list); + Iterator* internal_iter = + NewMergingIterator(&internal_comparator_, &list[0], list.size()); + versions_->current()->Ref(); + + IterState* cleanup = new IterState(&mutex_, mem_, imm_, versions_->current()); + internal_iter->RegisterCleanup(CleanupIteratorState, cleanup, nullptr); + + *seed = ++seed_; + mutex_.Unlock(); + return internal_iter; +} + +Iterator* DBImpl::TEST_NewInternalIterator() { + SequenceNumber ignored; + uint32_t ignored_seed; + return NewInternalIterator(ReadOptions(), &ignored, &ignored_seed); +} + +int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes() { + MutexLock l(&mutex_); + return versions_->MaxNextLevelOverlappingBytes(); +} + +Status DBImpl::Get(const ReadOptions& options, const Slice& key, + std::string* value) { + Status s; + MutexLock l(&mutex_); + SequenceNumber snapshot; + if (options.snapshot != nullptr) { + snapshot = + static_cast(options.snapshot)->sequence_number(); + } else { + snapshot = versions_->LastSequence(); + } + + MemTable* mem = mem_; + MemTable* imm = imm_; + Version* current = versions_->current(); + mem->Ref(); + if (imm != nullptr) imm->Ref(); + current->Ref(); + + bool have_stat_update = false; + Version::GetStats stats; + + // Unlock while reading from files and memtables + { + mutex_.Unlock(); + // First look in the memtable, then in the immutable memtable (if any). + LookupKey lkey(key, snapshot); + if (mem->Get(lkey, value, &s)) { + // Done + } else if (imm != nullptr && imm->Get(lkey, value, &s)) { + // Done + } else { + s = current->Get(options, lkey, value, &stats); + have_stat_update = true; + } + mutex_.Lock(); + } + + if (have_stat_update && current->UpdateStats(stats)) { + MaybeScheduleCompaction(); + } + mem->Unref(); + if (imm != nullptr) imm->Unref(); + current->Unref(); + return s; +} + +Iterator* DBImpl::NewIterator(const ReadOptions& options) { + SequenceNumber latest_snapshot; + uint32_t seed; + Iterator* iter = NewInternalIterator(options, &latest_snapshot, &seed); + return NewDBIterator(this, user_comparator(), iter, + (options.snapshot != nullptr + ? static_cast(options.snapshot) + ->sequence_number() + : latest_snapshot), + seed); +} + +void DBImpl::RecordReadSample(Slice key) { + MutexLock l(&mutex_); + if (versions_->current()->RecordReadSample(key)) { + MaybeScheduleCompaction(); + } +} + +const Snapshot* DBImpl::GetSnapshot() { + MutexLock l(&mutex_); + return snapshots_.New(versions_->LastSequence()); +} + +void DBImpl::ReleaseSnapshot(const Snapshot* snapshot) { + MutexLock l(&mutex_); + snapshots_.Delete(static_cast(snapshot)); +} + +// Convenience methods +Status DBImpl::Put(const WriteOptions& o, const Slice& key, const Slice& val) { + return DB::Put(o, key, val); +} + +Status DBImpl::Delete(const WriteOptions& options, const Slice& key) { + return DB::Delete(options, key); +} + +Status DBImpl::Write(const WriteOptions& options, WriteBatch* updates) { + Writer w(&mutex_); + w.batch = updates; + w.sync = options.sync; + w.done = false; + + MutexLock l(&mutex_); + writers_.push_back(&w); + while (!w.done && &w != writers_.front()) { + w.cv.Wait(); + } + if (w.done) { + return w.status; + } + + // May temporarily unlock and wait. + Status status = MakeRoomForWrite(updates == nullptr); + uint64_t last_sequence = versions_->LastSequence(); + Writer* last_writer = &w; + if (status.ok() && updates != nullptr) { // nullptr batch is for compactions + WriteBatch* updates = BuildBatchGroup(&last_writer); + WriteBatchInternal::SetSequence(updates, last_sequence + 1); + last_sequence += WriteBatchInternal::Count(updates); + + // Add to log and apply to memtable. We can release the lock + // during this phase since &w is currently responsible for logging + // and protects against concurrent loggers and concurrent writes + // into mem_. + { + mutex_.Unlock(); + status = log_->AddRecord(WriteBatchInternal::Contents(updates)); + bool sync_error = false; + if (status.ok() && options.sync) { + status = logfile_->Sync(); + if (!status.ok()) { + sync_error = true; + } + } + if (status.ok()) { + status = WriteBatchInternal::InsertInto(updates, mem_); + } + mutex_.Lock(); + if (sync_error) { + // The state of the log file is indeterminate: the log record we + // just added may or may not show up when the DB is re-opened. + // So we force the DB into a mode where all future writes fail. + RecordBackgroundError(status); + } + } + if (updates == tmp_batch_) tmp_batch_->Clear(); + + versions_->SetLastSequence(last_sequence); + } + + while (true) { + Writer* ready = writers_.front(); + writers_.pop_front(); + if (ready != &w) { + ready->status = status; + ready->done = true; + ready->cv.Signal(); + } + if (ready == last_writer) break; + } + + // Notify new head of write queue + if (!writers_.empty()) { + writers_.front()->cv.Signal(); + } + + return status; +} + +// REQUIRES: Writer list must be non-empty +// REQUIRES: First writer must have a non-null batch +WriteBatch* DBImpl::BuildBatchGroup(Writer** last_writer) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + Writer* first = writers_.front(); + WriteBatch* result = first->batch; + assert(result != nullptr); + + size_t size = WriteBatchInternal::ByteSize(first->batch); + + // Allow the group to grow up to a maximum size, but if the + // original write is small, limit the growth so we do not slow + // down the small write too much. + size_t max_size = 1 << 20; + if (size <= (128 << 10)) { + max_size = size + (128 << 10); + } + + *last_writer = first; + std::deque::iterator iter = writers_.begin(); + ++iter; // Advance past "first" + for (; iter != writers_.end(); ++iter) { + Writer* w = *iter; + if (w->sync && !first->sync) { + // Do not include a sync write into a batch handled by a non-sync write. + break; + } + + if (w->batch != nullptr) { + size += WriteBatchInternal::ByteSize(w->batch); + if (size > max_size) { + // Do not make batch too big + break; + } + + // Append to *result + if (result == first->batch) { + // Switch to temporary batch instead of disturbing caller's batch + result = tmp_batch_; + assert(WriteBatchInternal::Count(result) == 0); + WriteBatchInternal::Append(result, first->batch); + } + WriteBatchInternal::Append(result, w->batch); + } + *last_writer = w; + } + return result; +} + +// REQUIRES: mutex_ is held +// REQUIRES: this thread is currently at the front of the writer queue +Status DBImpl::MakeRoomForWrite(bool force) { + mutex_.AssertHeld(); + assert(!writers_.empty()); + bool allow_delay = !force; + Status s; + while (true) { + if (!bg_error_.ok()) { + // Yield previous error + s = bg_error_; + break; + } else if (allow_delay && versions_->NumLevelFiles(0) >= + config::kL0_SlowdownWritesTrigger) { + // We are getting close to hitting a hard limit on the number of + // L0 files. Rather than delaying a single write by several + // seconds when we hit the hard limit, start delaying each + // individual write by 1ms to reduce latency variance. Also, + // this delay hands over some CPU to the compaction thread in + // case it is sharing the same core as the writer. + mutex_.Unlock(); + env_->SleepForMicroseconds(1000); + allow_delay = false; // Do not delay a single write more than once + mutex_.Lock(); + } else if (!force && + (mem_->ApproximateMemoryUsage() <= options_.write_buffer_size)) { + // There is room in current memtable + break; + } else if (imm_ != nullptr) { + // We have filled up the current memtable, but the previous + // one is still being compacted, so we wait. + Log(options_.info_log, "Current memtable full; waiting...\n"); + background_work_finished_signal_.Wait(); + } else if (versions_->NumLevelFiles(0) >= config::kL0_StopWritesTrigger) { + // There are too many level-0 files. + Log(options_.info_log, "Too many L0 files; waiting...\n"); + background_work_finished_signal_.Wait(); + } else { + // Attempt to switch to a new memtable and trigger compaction of old + assert(versions_->PrevLogNumber() == 0); + uint64_t new_log_number = versions_->NewFileNumber(); + WritableFile* lfile = nullptr; + s = env_->NewWritableFile(LogFileName(dbname_, new_log_number), &lfile); + if (!s.ok()) { + // Avoid chewing through file number space in a tight loop. + versions_->ReuseFileNumber(new_log_number); + break; + } + delete log_; + delete logfile_; + logfile_ = lfile; + logfile_number_ = new_log_number; + log_ = new log::Writer(lfile); + imm_ = mem_; + has_imm_.store(true, std::memory_order_release); + mem_ = new MemTable(internal_comparator_); + mem_->Ref(); + force = false; // Do not force another compaction if have room + MaybeScheduleCompaction(); + } + } + return s; +} + +bool DBImpl::GetProperty(const Slice& property, std::string* value) { + value->clear(); + + MutexLock l(&mutex_); + Slice in = property; + Slice prefix("leveldb."); + if (!in.starts_with(prefix)) return false; + in.remove_prefix(prefix.size()); + + if (in.starts_with("num-files-at-level")) { + in.remove_prefix(strlen("num-files-at-level")); + uint64_t level; + bool ok = ConsumeDecimalNumber(&in, &level) && in.empty(); + if (!ok || level >= config::kNumLevels) { + return false; + } else { + char buf[100]; + snprintf(buf, sizeof(buf), "%d", + versions_->NumLevelFiles(static_cast(level))); + *value = buf; + return true; + } + } else if (in == "stats") { + char buf[200]; + snprintf(buf, sizeof(buf), + " Compactions\n" + "Level Files Size(MB) Time(sec) Read(MB) Write(MB)\n" + "--------------------------------------------------\n"); + value->append(buf); + for (int level = 0; level < config::kNumLevels; level++) { + int files = versions_->NumLevelFiles(level); + if (stats_[level].micros > 0 || files > 0) { + snprintf(buf, sizeof(buf), "%3d %8d %8.0f %9.0f %8.0f %9.0f\n", level, + files, versions_->NumLevelBytes(level) / 1048576.0, + stats_[level].micros / 1e6, + stats_[level].bytes_read / 1048576.0, + stats_[level].bytes_written / 1048576.0); + value->append(buf); + } + } + return true; + } else if (in == "sstables") { + *value = versions_->current()->DebugString(); + return true; + } else if (in == "approximate-memory-usage") { + size_t total_usage = options_.block_cache->TotalCharge(); + if (mem_) { + total_usage += mem_->ApproximateMemoryUsage(); + } + if (imm_) { + total_usage += imm_->ApproximateMemoryUsage(); + } + char buf[50]; + snprintf(buf, sizeof(buf), "%llu", + static_cast(total_usage)); + value->append(buf); + return true; + } + + return false; +} + +void DBImpl::GetApproximateSizes(const Range* range, int n, uint64_t* sizes) { + // TODO(opt): better implementation + Version* v; + { + MutexLock l(&mutex_); + versions_->current()->Ref(); + v = versions_->current(); + } + + for (int i = 0; i < n; i++) { + // Convert user_key into a corresponding internal key. + InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek); + uint64_t start = versions_->ApproximateOffsetOf(v, k1); + uint64_t limit = versions_->ApproximateOffsetOf(v, k2); + sizes[i] = (limit >= start ? limit - start : 0); + } + + { + MutexLock l(&mutex_); + v->Unref(); + } +} + +// Default implementations of convenience methods that subclasses of DB +// can call if they wish +Status DB::Put(const WriteOptions& opt, const Slice& key, const Slice& value) { + WriteBatch batch; + batch.Put(key, value); + return Write(opt, &batch); +} + +Status DB::Delete(const WriteOptions& opt, const Slice& key) { + WriteBatch batch; + batch.Delete(key); + return Write(opt, &batch); +} + +DB::~DB() {} + +Status DB::Open(const Options& options, const std::string& dbname, DB** dbptr) { + *dbptr = nullptr; + + DBImpl* impl = new DBImpl(options, dbname); + impl->mutex_.Lock(); + VersionEdit edit; + // Recover handles create_if_missing, error_if_exists + bool save_manifest = false; + Status s = impl->Recover(&edit, &save_manifest); + if (s.ok() && impl->mem_ == nullptr) { + // Create new log and a corresponding memtable. + uint64_t new_log_number = impl->versions_->NewFileNumber(); + WritableFile* lfile; + s = options.env->NewWritableFile(LogFileName(dbname, new_log_number), + &lfile); + if (s.ok()) { + edit.SetLogNumber(new_log_number); + impl->logfile_ = lfile; + impl->logfile_number_ = new_log_number; + impl->log_ = new log::Writer(lfile); + impl->mem_ = new MemTable(impl->internal_comparator_); + impl->mem_->Ref(); + } + } + if (s.ok() && save_manifest) { + edit.SetPrevLogNumber(0); // No older logs needed after recovery. + edit.SetLogNumber(impl->logfile_number_); + s = impl->versions_->LogAndApply(&edit, &impl->mutex_); + } + if (s.ok()) { + impl->DeleteObsoleteFiles(); + impl->MaybeScheduleCompaction(); + } + impl->mutex_.Unlock(); + if (s.ok()) { + assert(impl->mem_ != nullptr); + *dbptr = impl; + } else { + delete impl; + } + return s; +} + +Snapshot::~Snapshot() {} + +Status DestroyDB(const std::string& dbname, const Options& options) { + Env* env = options.env; + std::vector filenames; + Status result = env->GetChildren(dbname, &filenames); + if (!result.ok()) { + // Ignore error in case directory does not exist + return Status::OK(); + } + + FileLock* lock; + const std::string lockname = LockFileName(dbname); + result = env->LockFile(lockname, &lock); + if (result.ok()) { + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type) && + type != kDBLockFile) { // Lock file will be deleted at end + Status del = env->DeleteFile(dbname + "/" + filenames[i]); + if (result.ok() && !del.ok()) { + result = del; + } + } + } + env->UnlockFile(lock); // Ignore error since state is already gone + env->DeleteFile(lockname); + env->DeleteDir(dbname); // Ignore error in case dir contains other files + } + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.h new file mode 100644 index 0000000..ae87d6e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_impl.h @@ -0,0 +1,216 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_IMPL_H_ +#define STORAGE_LEVELDB_DB_DB_IMPL_H_ + +#include +#include +#include +#include + +#include "db/dbformat.h" +#include "db/log_writer.h" +#include "db/snapshot.h" +#include "leveldb/db.h" +#include "leveldb/env.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +class MemTable; +class TableCache; +class Version; +class VersionEdit; +class VersionSet; + +class DBImpl : public DB { + public: + DBImpl(const Options& options, const std::string& dbname); + + DBImpl(const DBImpl&) = delete; + DBImpl& operator=(const DBImpl&) = delete; + + virtual ~DBImpl(); + + // Implementations of the DB interface + virtual Status Put(const WriteOptions&, const Slice& key, const Slice& value); + virtual Status Delete(const WriteOptions&, const Slice& key); + virtual Status Write(const WriteOptions& options, WriteBatch* updates); + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value); + virtual Iterator* NewIterator(const ReadOptions&); + virtual const Snapshot* GetSnapshot(); + virtual void ReleaseSnapshot(const Snapshot* snapshot); + virtual bool GetProperty(const Slice& property, std::string* value); + virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes); + virtual void CompactRange(const Slice* begin, const Slice* end); + + // Extra methods (for testing) that are not in the public DB interface + + // Compact any files in the named level that overlap [*begin,*end] + void TEST_CompactRange(int level, const Slice* begin, const Slice* end); + + // Force current memtable contents to be compacted. + Status TEST_CompactMemTable(); + + // Return an internal iterator over the current state of the database. + // The keys of this iterator are internal keys (see format.h). + // The returned iterator should be deleted when no longer needed. + Iterator* TEST_NewInternalIterator(); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t TEST_MaxNextLevelOverlappingBytes(); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. + void RecordReadSample(Slice key); + + private: + friend class DB; + struct CompactionState; + struct Writer; + + // Information for a manual compaction + struct ManualCompaction { + int level; + bool done; + const InternalKey* begin; // null means beginning of key range + const InternalKey* end; // null means end of key range + InternalKey tmp_storage; // Used to keep track of compaction progress + }; + + // Per level compaction stats. stats_[level] stores the stats for + // compactions that produced data for the specified "level". + struct CompactionStats { + CompactionStats() : micros(0), bytes_read(0), bytes_written(0) {} + + void Add(const CompactionStats& c) { + this->micros += c.micros; + this->bytes_read += c.bytes_read; + this->bytes_written += c.bytes_written; + } + + int64_t micros; + int64_t bytes_read; + int64_t bytes_written; + }; + + Iterator* NewInternalIterator(const ReadOptions&, + SequenceNumber* latest_snapshot, + uint32_t* seed); + + Status NewDB(); + + // Recover the descriptor from persistent storage. May do a significant + // amount of work to recover recently logged updates. Any changes to + // be made to the descriptor are added to *edit. + Status Recover(VersionEdit* edit, bool* save_manifest) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void MaybeIgnoreError(Status* s) const; + + // Delete any unneeded files and stale in-memory entries. + void DeleteObsoleteFiles() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Compact the in-memory write buffer to disk. Switches to a new + // log-file/memtable and writes a new descriptor iff successful. + // Errors are recorded in bg_error_. + void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status RecoverLogFile(uint64_t log_number, bool last_log, bool* save_manifest, + VersionEdit* edit, SequenceNumber* max_sequence) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status MakeRoomForWrite(bool force /* compact even if there is room? */) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + WriteBatch* BuildBatchGroup(Writer** last_writer) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + void RecordBackgroundError(const Status& s); + + void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + static void BGWork(void* db); + void BackgroundCall(); + void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_); + void CleanupCompaction(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + Status DoCompactionWork(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + Status OpenCompactionOutputFile(CompactionState* compact); + Status FinishCompactionOutputFile(CompactionState* compact, Iterator* input); + Status InstallCompactionResults(CompactionState* compact) + EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + const Comparator* user_comparator() const { + return internal_comparator_.user_comparator(); + } + + // Constant after construction + Env* const env_; + const InternalKeyComparator internal_comparator_; + const InternalFilterPolicy internal_filter_policy_; + const Options options_; // options_.comparator == &internal_comparator_ + const bool owns_info_log_; + const bool owns_cache_; + const std::string dbname_; + + // table_cache_ provides its own synchronization + TableCache* const table_cache_; + + // Lock over the persistent DB state. Non-null iff successfully acquired. + FileLock* db_lock_; + + // State below is protected by mutex_ + port::Mutex mutex_; + std::atomic shutting_down_; + port::CondVar background_work_finished_signal_ GUARDED_BY(mutex_); + MemTable* mem_; + MemTable* imm_ GUARDED_BY(mutex_); // Memtable being compacted + std::atomic has_imm_; // So bg thread can detect non-null imm_ + WritableFile* logfile_; + uint64_t logfile_number_ GUARDED_BY(mutex_); + log::Writer* log_; + uint32_t seed_ GUARDED_BY(mutex_); // For sampling. + + // Queue of writers. + std::deque writers_ GUARDED_BY(mutex_); + WriteBatch* tmp_batch_ GUARDED_BY(mutex_); + + SnapshotList snapshots_ GUARDED_BY(mutex_); + + // Set of table files to protect from deletion because they are + // part of ongoing compactions. + std::set pending_outputs_ GUARDED_BY(mutex_); + + // Has a background compaction been scheduled or is running? + bool background_compaction_scheduled_ GUARDED_BY(mutex_); + + ManualCompaction* manual_compaction_ GUARDED_BY(mutex_); + + VersionSet* const versions_; + + // Have we encountered a background error in paranoid mode? + Status bg_error_ GUARDED_BY(mutex_); + + CompactionStats stats_[config::kNumLevels] GUARDED_BY(mutex_); +}; + +// Sanitize db options. The caller should delete result.info_log if +// it is not equal to src.info_log. +Options SanitizeOptions(const std::string& db, + const InternalKeyComparator* icmp, + const InternalFilterPolicy* ipolicy, + const Options& src); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_IMPL_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.cc new file mode 100644 index 0000000..8ff288e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.cc @@ -0,0 +1,309 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/db_iter.h" + +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "port/port.h" +#include "util/logging.h" +#include "util/mutexlock.h" +#include "util/random.h" + +namespace leveldb { + +#if 0 +static void DumpInternalIter(Iterator* iter) { + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + ParsedInternalKey k; + if (!ParseInternalKey(iter->key(), &k)) { + fprintf(stderr, "Corrupt '%s'\n", EscapeString(iter->key()).c_str()); + } else { + fprintf(stderr, "@ '%s'\n", k.DebugString().c_str()); + } + } +} +#endif + +namespace { + +// Memtables and sstables that make the DB representation contain +// (userkey,seq,type) => uservalue entries. DBIter +// combines multiple entries for the same userkey found in the DB +// representation into a single entry while accounting for sequence +// numbers, deletion markers, overwrites, etc. +class DBIter : public Iterator { + public: + // Which direction is the iterator currently moving? + // (1) When moving forward, the internal iterator is positioned at + // the exact entry that yields this->key(), this->value() + // (2) When moving backwards, the internal iterator is positioned + // just before all entries whose user key == this->key(). + enum Direction { kForward, kReverse }; + + DBIter(DBImpl* db, const Comparator* cmp, Iterator* iter, SequenceNumber s, + uint32_t seed) + : db_(db), + user_comparator_(cmp), + iter_(iter), + sequence_(s), + direction_(kForward), + valid_(false), + rnd_(seed), + bytes_until_read_sampling_(RandomCompactionPeriod()) {} + + DBIter(const DBIter&) = delete; + DBIter& operator=(const DBIter&) = delete; + + virtual ~DBIter() { delete iter_; } + virtual bool Valid() const { return valid_; } + virtual Slice key() const { + assert(valid_); + return (direction_ == kForward) ? ExtractUserKey(iter_->key()) : saved_key_; + } + virtual Slice value() const { + assert(valid_); + return (direction_ == kForward) ? iter_->value() : saved_value_; + } + virtual Status status() const { + if (status_.ok()) { + return iter_->status(); + } else { + return status_; + } + } + + virtual void Next(); + virtual void Prev(); + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + + private: + void FindNextUserEntry(bool skipping, std::string* skip); + void FindPrevUserEntry(); + bool ParseKey(ParsedInternalKey* key); + + inline void SaveKey(const Slice& k, std::string* dst) { + dst->assign(k.data(), k.size()); + } + + inline void ClearSavedValue() { + if (saved_value_.capacity() > 1048576) { + std::string empty; + swap(empty, saved_value_); + } else { + saved_value_.clear(); + } + } + + // Picks the number of bytes that can be read until a compaction is scheduled. + size_t RandomCompactionPeriod() { + return rnd_.Uniform(2 * config::kReadBytesPeriod); + } + + DBImpl* db_; + const Comparator* const user_comparator_; + Iterator* const iter_; + SequenceNumber const sequence_; + Status status_; + std::string saved_key_; // == current key when direction_==kReverse + std::string saved_value_; // == current raw value when direction_==kReverse + Direction direction_; + bool valid_; + Random rnd_; + size_t bytes_until_read_sampling_; +}; + +inline bool DBIter::ParseKey(ParsedInternalKey* ikey) { + Slice k = iter_->key(); + + size_t bytes_read = k.size() + iter_->value().size(); + while (bytes_until_read_sampling_ < bytes_read) { + bytes_until_read_sampling_ += RandomCompactionPeriod(); + db_->RecordReadSample(k); + } + assert(bytes_until_read_sampling_ >= bytes_read); + bytes_until_read_sampling_ -= bytes_read; + + if (!ParseInternalKey(k, ikey)) { + status_ = Status::Corruption("corrupted internal key in DBIter"); + return false; + } else { + return true; + } +} + +void DBIter::Next() { + assert(valid_); + + if (direction_ == kReverse) { // Switch directions? + direction_ = kForward; + // iter_ is pointing just before the entries for this->key(), + // so advance into the range of entries for this->key() and then + // use the normal skipping code below. + if (!iter_->Valid()) { + iter_->SeekToFirst(); + } else { + iter_->Next(); + } + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + return; + } + // saved_key_ already contains the key to skip past. + } else { + // Store in saved_key_ the current key so we skip it below. + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + } + + FindNextUserEntry(true, &saved_key_); +} + +void DBIter::FindNextUserEntry(bool skipping, std::string* skip) { + // Loop until we hit an acceptable entry to yield + assert(iter_->Valid()); + assert(direction_ == kForward); + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + switch (ikey.type) { + case kTypeDeletion: + // Arrange to skip all upcoming entries for this key since + // they are hidden by this deletion. + SaveKey(ikey.user_key, skip); + skipping = true; + break; + case kTypeValue: + if (skipping && + user_comparator_->Compare(ikey.user_key, *skip) <= 0) { + // Entry hidden + } else { + valid_ = true; + saved_key_.clear(); + return; + } + break; + } + } + iter_->Next(); + } while (iter_->Valid()); + saved_key_.clear(); + valid_ = false; +} + +void DBIter::Prev() { + assert(valid_); + + if (direction_ == kForward) { // Switch directions? + // iter_ is pointing at the current entry. Scan backwards until + // the key changes so we can use the normal reverse scanning code. + assert(iter_->Valid()); // Otherwise valid_ would have been false + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + while (true) { + iter_->Prev(); + if (!iter_->Valid()) { + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + return; + } + if (user_comparator_->Compare(ExtractUserKey(iter_->key()), saved_key_) < + 0) { + break; + } + } + direction_ = kReverse; + } + + FindPrevUserEntry(); +} + +void DBIter::FindPrevUserEntry() { + assert(direction_ == kReverse); + + ValueType value_type = kTypeDeletion; + if (iter_->Valid()) { + do { + ParsedInternalKey ikey; + if (ParseKey(&ikey) && ikey.sequence <= sequence_) { + if ((value_type != kTypeDeletion) && + user_comparator_->Compare(ikey.user_key, saved_key_) < 0) { + // We encountered a non-deleted value in entries for previous keys, + break; + } + value_type = ikey.type; + if (value_type == kTypeDeletion) { + saved_key_.clear(); + ClearSavedValue(); + } else { + Slice raw_value = iter_->value(); + if (saved_value_.capacity() > raw_value.size() + 1048576) { + std::string empty; + swap(empty, saved_value_); + } + SaveKey(ExtractUserKey(iter_->key()), &saved_key_); + saved_value_.assign(raw_value.data(), raw_value.size()); + } + } + iter_->Prev(); + } while (iter_->Valid()); + } + + if (value_type == kTypeDeletion) { + // End + valid_ = false; + saved_key_.clear(); + ClearSavedValue(); + direction_ = kForward; + } else { + valid_ = true; + } +} + +void DBIter::Seek(const Slice& target) { + direction_ = kForward; + ClearSavedValue(); + saved_key_.clear(); + AppendInternalKey(&saved_key_, + ParsedInternalKey(target, sequence_, kValueTypeForSeek)); + iter_->Seek(saved_key_); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToFirst() { + direction_ = kForward; + ClearSavedValue(); + iter_->SeekToFirst(); + if (iter_->Valid()) { + FindNextUserEntry(false, &saved_key_ /* temporary storage */); + } else { + valid_ = false; + } +} + +void DBIter::SeekToLast() { + direction_ = kReverse; + ClearSavedValue(); + iter_->SeekToLast(); + FindPrevUserEntry(); +} + +} // anonymous namespace + +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed) { + return new DBIter(db, user_key_comparator, internal_iter, sequence, seed); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.h new file mode 100644 index 0000000..fd93e91 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/db_iter.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DB_ITER_H_ +#define STORAGE_LEVELDB_DB_DB_ITER_H_ + +#include + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class DBImpl; + +// Return a new iterator that converts internal keys (yielded by +// "*internal_iter") that were live at the specified "sequence" number +// into appropriate user keys. +Iterator* NewDBIterator(DBImpl* db, const Comparator* user_key_comparator, + Iterator* internal_iter, SequenceNumber sequence, + uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DB_ITER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.cc new file mode 100644 index 0000000..69e8dc6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/dbformat.h" + +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { + +static uint64_t PackSequenceAndType(uint64_t seq, ValueType t) { + assert(seq <= kMaxSequenceNumber); + assert(t <= kValueTypeForSeek); + return (seq << 8) | t; +} + +void AppendInternalKey(std::string* result, const ParsedInternalKey& key) { + result->append(key.user_key.data(), key.user_key.size()); + PutFixed64(result, PackSequenceAndType(key.sequence, key.type)); +} + +std::string ParsedInternalKey::DebugString() const { + char buf[50]; + snprintf(buf, sizeof(buf), "' @ %llu : %d", (unsigned long long)sequence, + int(type)); + std::string result = "'"; + result += EscapeString(user_key.ToString()); + result += buf; + return result; +} + +std::string InternalKey::DebugString() const { + std::string result; + ParsedInternalKey parsed; + if (ParseInternalKey(rep_, &parsed)) { + result = parsed.DebugString(); + } else { + result = "(bad)"; + result.append(EscapeString(rep_)); + } + return result; +} + +const char* InternalKeyComparator::Name() const { + return "leveldb.InternalKeyComparator"; +} + +int InternalKeyComparator::Compare(const Slice& akey, const Slice& bkey) const { + // Order by: + // increasing user key (according to user-supplied comparator) + // decreasing sequence number + // decreasing type (though sequence# should be enough to disambiguate) + int r = user_comparator_->Compare(ExtractUserKey(akey), ExtractUserKey(bkey)); + if (r == 0) { + const uint64_t anum = DecodeFixed64(akey.data() + akey.size() - 8); + const uint64_t bnum = DecodeFixed64(bkey.data() + bkey.size() - 8); + if (anum > bnum) { + r = -1; + } else if (anum < bnum) { + r = +1; + } + } + return r; +} + +void InternalKeyComparator::FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Attempt to shorten the user portion of the key + Slice user_start = ExtractUserKey(*start); + Slice user_limit = ExtractUserKey(limit); + std::string tmp(user_start.data(), user_start.size()); + user_comparator_->FindShortestSeparator(&tmp, user_limit); + if (tmp.size() < user_start.size() && + user_comparator_->Compare(user_start, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*start, tmp) < 0); + assert(this->Compare(tmp, limit) < 0); + start->swap(tmp); + } +} + +void InternalKeyComparator::FindShortSuccessor(std::string* key) const { + Slice user_key = ExtractUserKey(*key); + std::string tmp(user_key.data(), user_key.size()); + user_comparator_->FindShortSuccessor(&tmp); + if (tmp.size() < user_key.size() && + user_comparator_->Compare(user_key, tmp) < 0) { + // User key has become shorter physically, but larger logically. + // Tack on the earliest possible number to the shortened user key. + PutFixed64(&tmp, + PackSequenceAndType(kMaxSequenceNumber, kValueTypeForSeek)); + assert(this->Compare(*key, tmp) < 0); + key->swap(tmp); + } +} + +const char* InternalFilterPolicy::Name() const { return user_policy_->Name(); } + +void InternalFilterPolicy::CreateFilter(const Slice* keys, int n, + std::string* dst) const { + // We rely on the fact that the code in table.cc does not mind us + // adjusting keys[]. + Slice* mkey = const_cast(keys); + for (int i = 0; i < n; i++) { + mkey[i] = ExtractUserKey(keys[i]); + // TODO(sanjay): Suppress dups? + } + user_policy_->CreateFilter(keys, n, dst); +} + +bool InternalFilterPolicy::KeyMayMatch(const Slice& key, const Slice& f) const { + return user_policy_->KeyMayMatch(ExtractUserKey(key), f); +} + +LookupKey::LookupKey(const Slice& user_key, SequenceNumber s) { + size_t usize = user_key.size(); + size_t needed = usize + 13; // A conservative estimate + char* dst; + if (needed <= sizeof(space_)) { + dst = space_; + } else { + dst = new char[needed]; + } + start_ = dst; + dst = EncodeVarint32(dst, usize + 8); + kstart_ = dst; + memcpy(dst, user_key.data(), usize); + dst += usize; + EncodeFixed64(dst, PackSequenceAndType(s, kValueTypeForSeek)); + dst += 8; + end_ = dst; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.h new file mode 100644 index 0000000..013028a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dbformat.h @@ -0,0 +1,218 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_DBFORMAT_H_ +#define STORAGE_LEVELDB_DB_DBFORMAT_H_ + +#include + +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/filter_policy.h" +#include "leveldb/slice.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +// Grouping of constants. We may want to make some of these +// parameters set via options. +namespace config { +static const int kNumLevels = 7; + +// Level-0 compaction is started when we hit this many files. +static const int kL0_CompactionTrigger = 4; + +// Soft limit on number of level-0 files. We slow down writes at this point. +static const int kL0_SlowdownWritesTrigger = 8; + +// Maximum number of level-0 files. We stop writes at this point. +static const int kL0_StopWritesTrigger = 12; + +// Maximum level to which a new compacted memtable is pushed if it +// does not create overlap. We try to push to level 2 to avoid the +// relatively expensive level 0=>1 compactions and to avoid some +// expensive manifest file operations. We do not push all the way to +// the largest level since that can generate a lot of wasted disk +// space if the same key space is being repeatedly overwritten. +static const int kMaxMemCompactLevel = 2; + +// Approximate gap in bytes between samples of data read during iteration. +static const int kReadBytesPeriod = 1048576; + +} // namespace config + +class InternalKey; + +// Value types encoded as the last component of internal keys. +// DO NOT CHANGE THESE ENUM VALUES: they are embedded in the on-disk +// data structures. +enum ValueType { kTypeDeletion = 0x0, kTypeValue = 0x1 }; +// kValueTypeForSeek defines the ValueType that should be passed when +// constructing a ParsedInternalKey object for seeking to a particular +// sequence number (since we sort sequence numbers in decreasing order +// and the value type is embedded as the low 8 bits in the sequence +// number in internal keys, we need to use the highest-numbered +// ValueType, not the lowest). +static const ValueType kValueTypeForSeek = kTypeValue; + +typedef uint64_t SequenceNumber; + +// We leave eight bits empty at the bottom so a type and sequence# +// can be packed together into 64-bits. +static const SequenceNumber kMaxSequenceNumber = ((0x1ull << 56) - 1); + +struct ParsedInternalKey { + Slice user_key; + SequenceNumber sequence; + ValueType type; + + ParsedInternalKey() {} // Intentionally left uninitialized (for speed) + ParsedInternalKey(const Slice& u, const SequenceNumber& seq, ValueType t) + : user_key(u), sequence(seq), type(t) {} + std::string DebugString() const; +}; + +// Return the length of the encoding of "key". +inline size_t InternalKeyEncodingLength(const ParsedInternalKey& key) { + return key.user_key.size() + 8; +} + +// Append the serialization of "key" to *result. +void AppendInternalKey(std::string* result, const ParsedInternalKey& key); + +// Attempt to parse an internal key from "internal_key". On success, +// stores the parsed data in "*result", and returns true. +// +// On error, returns false, leaves "*result" in an undefined state. +bool ParseInternalKey(const Slice& internal_key, ParsedInternalKey* result); + +// Returns the user key portion of an internal key. +inline Slice ExtractUserKey(const Slice& internal_key) { + assert(internal_key.size() >= 8); + return Slice(internal_key.data(), internal_key.size() - 8); +} + +// A comparator for internal keys that uses a specified comparator for +// the user key portion and breaks ties by decreasing sequence number. +class InternalKeyComparator : public Comparator { + private: + const Comparator* user_comparator_; + + public: + explicit InternalKeyComparator(const Comparator* c) : user_comparator_(c) {} + virtual const char* Name() const; + virtual int Compare(const Slice& a, const Slice& b) const; + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const; + virtual void FindShortSuccessor(std::string* key) const; + + const Comparator* user_comparator() const { return user_comparator_; } + + int Compare(const InternalKey& a, const InternalKey& b) const; +}; + +// Filter policy wrapper that converts from internal keys to user keys +class InternalFilterPolicy : public FilterPolicy { + private: + const FilterPolicy* const user_policy_; + + public: + explicit InternalFilterPolicy(const FilterPolicy* p) : user_policy_(p) {} + virtual const char* Name() const; + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const; + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const; +}; + +// Modules in this directory should keep internal keys wrapped inside +// the following class instead of plain strings so that we do not +// incorrectly use string comparisons instead of an InternalKeyComparator. +class InternalKey { + private: + std::string rep_; + + public: + InternalKey() {} // Leave rep_ as empty to indicate it is invalid + InternalKey(const Slice& user_key, SequenceNumber s, ValueType t) { + AppendInternalKey(&rep_, ParsedInternalKey(user_key, s, t)); + } + + void DecodeFrom(const Slice& s) { rep_.assign(s.data(), s.size()); } + Slice Encode() const { + assert(!rep_.empty()); + return rep_; + } + + Slice user_key() const { return ExtractUserKey(rep_); } + + void SetFrom(const ParsedInternalKey& p) { + rep_.clear(); + AppendInternalKey(&rep_, p); + } + + void Clear() { rep_.clear(); } + + std::string DebugString() const; +}; + +inline int InternalKeyComparator::Compare(const InternalKey& a, + const InternalKey& b) const { + return Compare(a.Encode(), b.Encode()); +} + +inline bool ParseInternalKey(const Slice& internal_key, + ParsedInternalKey* result) { + const size_t n = internal_key.size(); + if (n < 8) return false; + uint64_t num = DecodeFixed64(internal_key.data() + n - 8); + unsigned char c = num & 0xff; + result->sequence = num >> 8; + result->type = static_cast(c); + result->user_key = Slice(internal_key.data(), n - 8); + return (c <= static_cast(kTypeValue)); +} + +// A helper class useful for DBImpl::Get() +class LookupKey { + public: + // Initialize *this for looking up user_key at a snapshot with + // the specified sequence number. + LookupKey(const Slice& user_key, SequenceNumber sequence); + + LookupKey(const LookupKey&) = delete; + LookupKey& operator=(const LookupKey&) = delete; + + ~LookupKey(); + + // Return a key suitable for lookup in a MemTable. + Slice memtable_key() const { return Slice(start_, end_ - start_); } + + // Return an internal key (suitable for passing to an internal iterator) + Slice internal_key() const { return Slice(kstart_, end_ - kstart_); } + + // Return the user key + Slice user_key() const { return Slice(kstart_, end_ - kstart_ - 8); } + + private: + // We construct a char array of the form: + // klength varint32 <-- start_ + // userkey char[klength] <-- kstart_ + // tag uint64 + // <-- end_ + // The array is a suitable MemTable key. + // The suffix starting with "userkey" can be used as an InternalKey. + const char* start_; + const char* kstart_; + const char* end_; + char space_[200]; // Avoid allocation for short keys +}; + +inline LookupKey::~LookupKey() { + if (start_ != space_) delete[] start_; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_DBFORMAT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dumpfile.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dumpfile.cc new file mode 100644 index 0000000..9d22d58 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/dumpfile.cc @@ -0,0 +1,232 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/dumpfile.h" + +#include + +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" +#include "leveldb/status.h" +#include "leveldb/table.h" +#include "leveldb/write_batch.h" +#include "util/logging.h" + +namespace leveldb { + +namespace { + +bool GuessType(const std::string& fname, FileType* type) { + size_t pos = fname.rfind('/'); + std::string basename; + if (pos == std::string::npos) { + basename = fname; + } else { + basename = std::string(fname.data() + pos + 1, fname.size() - pos - 1); + } + uint64_t ignored; + return ParseFileName(basename, &ignored, type); +} + +// Notified when log reader encounters corruption. +class CorruptionReporter : public log::Reader::Reporter { + public: + virtual void Corruption(size_t bytes, const Status& status) { + std::string r = "corruption: "; + AppendNumberTo(&r, bytes); + r += " bytes; "; + r += status.ToString(); + r.push_back('\n'); + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Print contents of a log file. (*func)() is called on every record. +Status PrintLogContents(Env* env, const std::string& fname, + void (*func)(uint64_t, Slice, WritableFile*), + WritableFile* dst) { + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + CorruptionReporter reporter; + reporter.dst_ = dst; + log::Reader reader(file, &reporter, true, 0); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch)) { + (*func)(reader.LastRecordOffset(), record, dst); + } + delete file; + return Status::OK(); +} + +// Called on every item found in a WriteBatch. +class WriteBatchItemPrinter : public WriteBatch::Handler { + public: + virtual void Put(const Slice& key, const Slice& value) { + std::string r = " put '"; + AppendEscapedStringTo(&r, key); + r += "' '"; + AppendEscapedStringTo(&r, value); + r += "'\n"; + dst_->Append(r); + } + virtual void Delete(const Slice& key) { + std::string r = " del '"; + AppendEscapedStringTo(&r, key); + r += "'\n"; + dst_->Append(r); + } + + WritableFile* dst_; +}; + +// Called on every log record (each one of which is a WriteBatch) +// found in a kLogFile. +static void WriteBatchPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + if (record.size() < 12) { + r += "log record length "; + AppendNumberTo(&r, record.size()); + r += " is too small\n"; + dst->Append(r); + return; + } + WriteBatch batch; + WriteBatchInternal::SetContents(&batch, record); + r += "sequence "; + AppendNumberTo(&r, WriteBatchInternal::Sequence(&batch)); + r.push_back('\n'); + dst->Append(r); + WriteBatchItemPrinter batch_item_printer; + batch_item_printer.dst_ = dst; + Status s = batch.Iterate(&batch_item_printer); + if (!s.ok()) { + dst->Append(" error: " + s.ToString() + "\n"); + } +} + +Status DumpLog(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, WriteBatchPrinter, dst); +} + +// Called on every log record (each one of which is a WriteBatch) +// found in a kDescriptorFile. +static void VersionEditPrinter(uint64_t pos, Slice record, WritableFile* dst) { + std::string r = "--- offset "; + AppendNumberTo(&r, pos); + r += "; "; + VersionEdit edit; + Status s = edit.DecodeFrom(record); + if (!s.ok()) { + r += s.ToString(); + r.push_back('\n'); + } else { + r += edit.DebugString(); + } + dst->Append(r); +} + +Status DumpDescriptor(Env* env, const std::string& fname, WritableFile* dst) { + return PrintLogContents(env, fname, VersionEditPrinter, dst); +} + +Status DumpTable(Env* env, const std::string& fname, WritableFile* dst) { + uint64_t file_size; + RandomAccessFile* file = nullptr; + Table* table = nullptr; + Status s = env->GetFileSize(fname, &file_size); + if (s.ok()) { + s = env->NewRandomAccessFile(fname, &file); + } + if (s.ok()) { + // We use the default comparator, which may or may not match the + // comparator used in this database. However this should not cause + // problems since we only use Table operations that do not require + // any comparisons. In particular, we do not call Seek or Prev. + s = Table::Open(Options(), file, file_size, &table); + } + if (!s.ok()) { + delete table; + delete file; + return s; + } + + ReadOptions ro; + ro.fill_cache = false; + Iterator* iter = table->NewIterator(ro); + std::string r; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + r.clear(); + ParsedInternalKey key; + if (!ParseInternalKey(iter->key(), &key)) { + r = "badkey '"; + AppendEscapedStringTo(&r, iter->key()); + r += "' => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } else { + r = "'"; + AppendEscapedStringTo(&r, key.user_key); + r += "' @ "; + AppendNumberTo(&r, key.sequence); + r += " : "; + if (key.type == kTypeDeletion) { + r += "del"; + } else if (key.type == kTypeValue) { + r += "val"; + } else { + AppendNumberTo(&r, key.type); + } + r += " => '"; + AppendEscapedStringTo(&r, iter->value()); + r += "'\n"; + dst->Append(r); + } + } + s = iter->status(); + if (!s.ok()) { + dst->Append("iterator error: " + s.ToString() + "\n"); + } + + delete iter; + delete table; + delete file; + return Status::OK(); +} + +} // namespace + +Status DumpFile(Env* env, const std::string& fname, WritableFile* dst) { + FileType ftype; + if (!GuessType(fname, &ftype)) { + return Status::InvalidArgument(fname + ": unknown file type"); + } + switch (ftype) { + case kLogFile: + return DumpLog(env, fname, dst); + case kDescriptorFile: + return DumpDescriptor(env, fname, dst); + case kTableFile: + return DumpTable(env, fname, dst); + default: + break; + } + return Status::InvalidArgument(fname + ": not a dump-able file type"); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.cc new file mode 100644 index 0000000..85de45c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/filename.h" + +#include +#include + +#include "db/dbformat.h" +#include "leveldb/env.h" +#include "util/logging.h" + +namespace leveldb { + +// A utility routine: write "data" to the named file and Sync() it. +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname); + +static std::string MakeFileName(const std::string& dbname, uint64_t number, + const char* suffix) { + char buf[100]; + snprintf(buf, sizeof(buf), "/%06llu.%s", + static_cast(number), suffix); + return dbname + buf; +} + +std::string LogFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "log"); +} + +std::string TableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "ldb"); +} + +std::string SSTTableFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "sst"); +} + +std::string DescriptorFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + char buf[100]; + snprintf(buf, sizeof(buf), "/MANIFEST-%06llu", + static_cast(number)); + return dbname + buf; +} + +std::string CurrentFileName(const std::string& dbname) { + return dbname + "/CURRENT"; +} + +std::string LockFileName(const std::string& dbname) { return dbname + "/LOCK"; } + +std::string TempFileName(const std::string& dbname, uint64_t number) { + assert(number > 0); + return MakeFileName(dbname, number, "dbtmp"); +} + +std::string InfoLogFileName(const std::string& dbname) { + return dbname + "/LOG"; +} + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname) { + return dbname + "/LOG.old"; +} + +// Owned filenames have the form: +// dbname/CURRENT +// dbname/LOCK +// dbname/LOG +// dbname/LOG.old +// dbname/MANIFEST-[0-9]+ +// dbname/[0-9]+.(log|sst|ldb) +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type) { + Slice rest(filename); + if (rest == "CURRENT") { + *number = 0; + *type = kCurrentFile; + } else if (rest == "LOCK") { + *number = 0; + *type = kDBLockFile; + } else if (rest == "LOG" || rest == "LOG.old") { + *number = 0; + *type = kInfoLogFile; + } else if (rest.starts_with("MANIFEST-")) { + rest.remove_prefix(strlen("MANIFEST-")); + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + if (!rest.empty()) { + return false; + } + *type = kDescriptorFile; + *number = num; + } else { + // Avoid strtoull() to keep filename format independent of the + // current locale + uint64_t num; + if (!ConsumeDecimalNumber(&rest, &num)) { + return false; + } + Slice suffix = rest; + if (suffix == Slice(".log")) { + *type = kLogFile; + } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) { + *type = kTableFile; + } else if (suffix == Slice(".dbtmp")) { + *type = kTempFile; + } else { + return false; + } + *number = num; + } + return true; +} + +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number) { + // Remove leading "dbname/" and add newline to manifest file name + std::string manifest = DescriptorFileName(dbname, descriptor_number); + Slice contents = manifest; + assert(contents.starts_with(dbname + "/")); + contents.remove_prefix(dbname.size() + 1); + std::string tmp = TempFileName(dbname, descriptor_number); + Status s = WriteStringToFileSync(env, contents.ToString() + "\n", tmp); + if (s.ok()) { + s = env->RenameFile(tmp, CurrentFileName(dbname)); + } + if (!s.ok()) { + env->DeleteFile(tmp); + } + return s; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.h new file mode 100644 index 0000000..524e813 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/filename.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// File names used by DB code + +#ifndef STORAGE_LEVELDB_DB_FILENAME_H_ +#define STORAGE_LEVELDB_DB_FILENAME_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +enum FileType { + kLogFile, + kDBLockFile, + kTableFile, + kDescriptorFile, + kCurrentFile, + kTempFile, + kInfoLogFile // Either the current one, or an old one +}; + +// Return the name of the log file with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string LogFileName(const std::string& dbname, uint64_t number); + +// Return the name of the sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string TableFileName(const std::string& dbname, uint64_t number); + +// Return the legacy file name for an sstable with the specified number +// in the db named by "dbname". The result will be prefixed with +// "dbname". +std::string SSTTableFileName(const std::string& dbname, uint64_t number); + +// Return the name of the descriptor file for the db named by +// "dbname" and the specified incarnation number. The result will be +// prefixed with "dbname". +std::string DescriptorFileName(const std::string& dbname, uint64_t number); + +// Return the name of the current file. This file contains the name +// of the current manifest file. The result will be prefixed with +// "dbname". +std::string CurrentFileName(const std::string& dbname); + +// Return the name of the lock file for the db named by +// "dbname". The result will be prefixed with "dbname". +std::string LockFileName(const std::string& dbname); + +// Return the name of a temporary file owned by the db named "dbname". +// The result will be prefixed with "dbname". +std::string TempFileName(const std::string& dbname, uint64_t number); + +// Return the name of the info log file for "dbname". +std::string InfoLogFileName(const std::string& dbname); + +// Return the name of the old info log file for "dbname". +std::string OldInfoLogFileName(const std::string& dbname); + +// If filename is a leveldb file, store the type of the file in *type. +// The number encoded in the filename is stored in *number. If the +// filename was successfully parsed, returns true. Else return false. +bool ParseFileName(const std::string& filename, uint64_t* number, + FileType* type); + +// Make the CURRENT file point to the descriptor file with the +// specified number. +Status SetCurrentFile(Env* env, const std::string& dbname, + uint64_t descriptor_number); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_FILENAME_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_format.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_format.h new file mode 100644 index 0000000..356e69f --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_format.h @@ -0,0 +1,35 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Log format information shared by reader and writer. +// See ../doc/log_format.md for more detail. + +#ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_ +#define STORAGE_LEVELDB_DB_LOG_FORMAT_H_ + +namespace leveldb { +namespace log { + +enum RecordType { + // Zero is reserved for preallocated files + kZeroType = 0, + + kFullType = 1, + + // For fragments + kFirstType = 2, + kMiddleType = 3, + kLastType = 4 +}; +static const int kMaxRecordType = kLastType; + +static const int kBlockSize = 32768; + +// Header is checksum (4 bytes), length (2 bytes), type (1 byte). +static const int kHeaderSize = 4 + 2 + 1; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.cc new file mode 100644 index 0000000..f472723 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.cc @@ -0,0 +1,274 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_reader.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +Reader::Reporter::~Reporter() {} + +Reader::Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset) + : file_(file), + reporter_(reporter), + checksum_(checksum), + backing_store_(new char[kBlockSize]), + buffer_(), + eof_(false), + last_record_offset_(0), + end_of_buffer_offset_(0), + initial_offset_(initial_offset), + resyncing_(initial_offset > 0) {} + +Reader::~Reader() { delete[] backing_store_; } + +bool Reader::SkipToInitialBlock() { + const size_t offset_in_block = initial_offset_ % kBlockSize; + uint64_t block_start_location = initial_offset_ - offset_in_block; + + // Don't search a block if we'd be in the trailer + if (offset_in_block > kBlockSize - 6) { + block_start_location += kBlockSize; + } + + end_of_buffer_offset_ = block_start_location; + + // Skip to start of first block that can contain the initial record + if (block_start_location > 0) { + Status skip_status = file_->Skip(block_start_location); + if (!skip_status.ok()) { + ReportDrop(block_start_location, skip_status); + return false; + } + } + + return true; +} + +bool Reader::ReadRecord(Slice* record, std::string* scratch) { + if (last_record_offset_ < initial_offset_) { + if (!SkipToInitialBlock()) { + return false; + } + } + + scratch->clear(); + record->clear(); + bool in_fragmented_record = false; + // Record offset of the logical record that we're reading + // 0 is a dummy value to make compilers happy + uint64_t prospective_record_offset = 0; + + Slice fragment; + while (true) { + const unsigned int record_type = ReadPhysicalRecord(&fragment); + + // ReadPhysicalRecord may have only had an empty trailer remaining in its + // internal buffer. Calculate the offset of the next physical record now + // that it has returned, properly accounting for its header size. + uint64_t physical_record_offset = + end_of_buffer_offset_ - buffer_.size() - kHeaderSize - fragment.size(); + + if (resyncing_) { + if (record_type == kMiddleType) { + continue; + } else if (record_type == kLastType) { + resyncing_ = false; + continue; + } else { + resyncing_ = false; + } + } + + switch (record_type) { + case kFullType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(1)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->clear(); + *record = fragment; + last_record_offset_ = prospective_record_offset; + return true; + + case kFirstType: + if (in_fragmented_record) { + // Handle bug in earlier versions of log::Writer where + // it could emit an empty kFirstType record at the tail end + // of a block followed by a kFullType or kFirstType record + // at the beginning of the next block. + if (!scratch->empty()) { + ReportCorruption(scratch->size(), "partial record without end(2)"); + } + } + prospective_record_offset = physical_record_offset; + scratch->assign(fragment.data(), fragment.size()); + in_fragmented_record = true; + break; + + case kMiddleType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(1)"); + } else { + scratch->append(fragment.data(), fragment.size()); + } + break; + + case kLastType: + if (!in_fragmented_record) { + ReportCorruption(fragment.size(), + "missing start of fragmented record(2)"); + } else { + scratch->append(fragment.data(), fragment.size()); + *record = Slice(*scratch); + last_record_offset_ = prospective_record_offset; + return true; + } + break; + + case kEof: + if (in_fragmented_record) { + // This can be caused by the writer dying immediately after + // writing a physical record but before completing the next; don't + // treat it as a corruption, just ignore the entire logical record. + scratch->clear(); + } + return false; + + case kBadRecord: + if (in_fragmented_record) { + ReportCorruption(scratch->size(), "error in middle of record"); + in_fragmented_record = false; + scratch->clear(); + } + break; + + default: { + char buf[40]; + snprintf(buf, sizeof(buf), "unknown record type %u", record_type); + ReportCorruption( + (fragment.size() + (in_fragmented_record ? scratch->size() : 0)), + buf); + in_fragmented_record = false; + scratch->clear(); + break; + } + } + } + return false; +} + +uint64_t Reader::LastRecordOffset() { return last_record_offset_; } + +void Reader::ReportCorruption(uint64_t bytes, const char* reason) { + ReportDrop(bytes, Status::Corruption(reason)); +} + +void Reader::ReportDrop(uint64_t bytes, const Status& reason) { + if (reporter_ != nullptr && + end_of_buffer_offset_ - buffer_.size() - bytes >= initial_offset_) { + reporter_->Corruption(static_cast(bytes), reason); + } +} + +unsigned int Reader::ReadPhysicalRecord(Slice* result) { + while (true) { + if (buffer_.size() < kHeaderSize) { + if (!eof_) { + // Last read was a full read, so this is a trailer to skip + buffer_.clear(); + Status status = file_->Read(kBlockSize, &buffer_, backing_store_); + end_of_buffer_offset_ += buffer_.size(); + if (!status.ok()) { + buffer_.clear(); + ReportDrop(kBlockSize, status); + eof_ = true; + return kEof; + } else if (buffer_.size() < kBlockSize) { + eof_ = true; + } + continue; + } else { + // Note that if buffer_ is non-empty, we have a truncated header at the + // end of the file, which can be caused by the writer crashing in the + // middle of writing the header. Instead of considering this an error, + // just report EOF. + buffer_.clear(); + return kEof; + } + } + + // Parse the header + const char* header = buffer_.data(); + const uint32_t a = static_cast(header[4]) & 0xff; + const uint32_t b = static_cast(header[5]) & 0xff; + const unsigned int type = header[6]; + const uint32_t length = a | (b << 8); + if (kHeaderSize + length > buffer_.size()) { + size_t drop_size = buffer_.size(); + buffer_.clear(); + if (!eof_) { + ReportCorruption(drop_size, "bad record length"); + return kBadRecord; + } + // If the end of the file has been reached without reading |length| bytes + // of payload, assume the writer died in the middle of writing the record. + // Don't report a corruption. + return kEof; + } + + if (type == kZeroType && length == 0) { + // Skip zero length record without reporting any drops since + // such records are produced by the mmap based writing code in + // env_posix.cc that preallocates file regions. + buffer_.clear(); + return kBadRecord; + } + + // Check crc + if (checksum_) { + uint32_t expected_crc = crc32c::Unmask(DecodeFixed32(header)); + uint32_t actual_crc = crc32c::Value(header + 6, 1 + length); + if (actual_crc != expected_crc) { + // Drop the rest of the buffer since "length" itself may have + // been corrupted and if we trust it, we could find some + // fragment of a real log record that just happens to look + // like a valid log record. + size_t drop_size = buffer_.size(); + buffer_.clear(); + ReportCorruption(drop_size, "checksum mismatch"); + return kBadRecord; + } + } + + buffer_.remove_prefix(kHeaderSize + length); + + // Skip physical record that started before initial_offset_ + if (end_of_buffer_offset_ - buffer_.size() - kHeaderSize - length < + initial_offset_) { + result->clear(); + return kBadRecord; + } + + *result = Slice(header + kHeaderSize, length); + return type; + } +} + +} // namespace log +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.h new file mode 100644 index 0000000..001da89 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_reader.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_READER_H_ +#define STORAGE_LEVELDB_DB_LOG_READER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class SequentialFile; + +namespace log { + +class Reader { + public: + // Interface for reporting errors. + class Reporter { + public: + virtual ~Reporter(); + + // Some corruption was detected. "size" is the approximate number + // of bytes dropped due to the corruption. + virtual void Corruption(size_t bytes, const Status& status) = 0; + }; + + // Create a reader that will return log records from "*file". + // "*file" must remain live while this Reader is in use. + // + // If "reporter" is non-null, it is notified whenever some data is + // dropped due to a detected corruption. "*reporter" must remain + // live while this Reader is in use. + // + // If "checksum" is true, verify checksums if available. + // + // The Reader will start reading at the first record located at physical + // position >= initial_offset within the file. + Reader(SequentialFile* file, Reporter* reporter, bool checksum, + uint64_t initial_offset); + + Reader(const Reader&) = delete; + Reader& operator=(const Reader&) = delete; + + ~Reader(); + + // Read the next record into *record. Returns true if read + // successfully, false if we hit end of the input. May use + // "*scratch" as temporary storage. The contents filled in *record + // will only be valid until the next mutating operation on this + // reader or the next mutation to *scratch. + bool ReadRecord(Slice* record, std::string* scratch); + + // Returns the physical offset of the last record returned by ReadRecord. + // + // Undefined before the first call to ReadRecord. + uint64_t LastRecordOffset(); + + private: + // Extend record types with the following special values + enum { + kEof = kMaxRecordType + 1, + // Returned whenever we find an invalid physical record. + // Currently there are three situations in which this happens: + // * The record has an invalid CRC (ReadPhysicalRecord reports a drop) + // * The record is a 0-length record (No drop is reported) + // * The record is below constructor's initial_offset (No drop is reported) + kBadRecord = kMaxRecordType + 2 + }; + + // Skips all blocks that are completely before "initial_offset_". + // + // Returns true on success. Handles reporting. + bool SkipToInitialBlock(); + + // Return type, or one of the preceding special values + unsigned int ReadPhysicalRecord(Slice* result); + + // Reports dropped bytes to the reporter. + // buffer_ must be updated to remove the dropped bytes prior to invocation. + void ReportCorruption(uint64_t bytes, const char* reason); + void ReportDrop(uint64_t bytes, const Status& reason); + + SequentialFile* const file_; + Reporter* const reporter_; + bool const checksum_; + char* const backing_store_; + Slice buffer_; + bool eof_; // Last Read() indicated EOF by returning < kBlockSize + + // Offset of the last record returned by ReadRecord. + uint64_t last_record_offset_; + // Offset of the first location past the end of buffer_. + uint64_t end_of_buffer_offset_; + + // Offset at which to start looking for the first record to return + uint64_t const initial_offset_; + + // True if we are resynchronizing after a seek (initial_offset_ > 0). In + // particular, a run of kMiddleType and kLastType records can be silently + // skipped in this mode + bool resyncing_; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_READER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.cc new file mode 100644 index 0000000..5e83f6a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.cc @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/log_writer.h" + +#include + +#include "leveldb/env.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { +namespace log { + +static void InitTypeCrc(uint32_t* type_crc) { + for (int i = 0; i <= kMaxRecordType; i++) { + char t = static_cast(i); + type_crc[i] = crc32c::Value(&t, 1); + } +} + +Writer::Writer(WritableFile* dest) : dest_(dest), block_offset_(0) { + InitTypeCrc(type_crc_); +} + +Writer::Writer(WritableFile* dest, uint64_t dest_length) + : dest_(dest), block_offset_(dest_length % kBlockSize) { + InitTypeCrc(type_crc_); +} + +Writer::~Writer() {} + +Status Writer::AddRecord(const Slice& slice) { + const char* ptr = slice.data(); + size_t left = slice.size(); + + // Fragment the record if necessary and emit it. Note that if slice + // is empty, we still want to iterate once to emit a single + // zero-length record + Status s; + bool begin = true; + do { + const int leftover = kBlockSize - block_offset_; + assert(leftover >= 0); + if (leftover < kHeaderSize) { + // Switch to a new block + if (leftover > 0) { + // Fill the trailer (literal below relies on kHeaderSize being 7) + static_assert(kHeaderSize == 7, ""); + dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover)); + } + block_offset_ = 0; + } + + // Invariant: we never leave < kHeaderSize bytes in a block. + assert(kBlockSize - block_offset_ - kHeaderSize >= 0); + + const size_t avail = kBlockSize - block_offset_ - kHeaderSize; + const size_t fragment_length = (left < avail) ? left : avail; + + RecordType type; + const bool end = (left == fragment_length); + if (begin && end) { + type = kFullType; + } else if (begin) { + type = kFirstType; + } else if (end) { + type = kLastType; + } else { + type = kMiddleType; + } + + s = EmitPhysicalRecord(type, ptr, fragment_length); + ptr += fragment_length; + left -= fragment_length; + begin = false; + } while (s.ok() && left > 0); + return s; +} + +Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, + size_t length) { + assert(length <= 0xffff); // Must fit in two bytes + assert(block_offset_ + kHeaderSize + length <= kBlockSize); + + // Format the header + char buf[kHeaderSize]; + buf[4] = static_cast(length & 0xff); + buf[5] = static_cast(length >> 8); + buf[6] = static_cast(t); + + // Compute the crc of the record type and the payload. + uint32_t crc = crc32c::Extend(type_crc_[t], ptr, length); + crc = crc32c::Mask(crc); // Adjust for storage + EncodeFixed32(buf, crc); + + // Write the header and the payload + Status s = dest_->Append(Slice(buf, kHeaderSize)); + if (s.ok()) { + s = dest_->Append(Slice(ptr, length)); + if (s.ok()) { + s = dest_->Flush(); + } + } + block_offset_ += kHeaderSize + length; + return s; +} + +} // namespace log +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.h new file mode 100644 index 0000000..c0a2114 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/log_writer.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_LOG_WRITER_H_ +#define STORAGE_LEVELDB_DB_LOG_WRITER_H_ + +#include + +#include "db/log_format.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class WritableFile; + +namespace log { + +class Writer { + public: + // Create a writer that will append data to "*dest". + // "*dest" must be initially empty. + // "*dest" must remain live while this Writer is in use. + explicit Writer(WritableFile* dest); + + // Create a writer that will append data to "*dest". + // "*dest" must have initial length "dest_length". + // "*dest" must remain live while this Writer is in use. + Writer(WritableFile* dest, uint64_t dest_length); + + Writer(const Writer&) = delete; + Writer& operator=(const Writer&) = delete; + + ~Writer(); + + Status AddRecord(const Slice& slice); + + private: + Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); + + WritableFile* dest_; + int block_offset_; // Current offset in block + + // crc32c values for all supported record types. These are + // pre-computed to reduce the overhead of computing the crc of the + // record type stored in the header. + uint32_t type_crc_[kMaxRecordType + 1]; +}; + +} // namespace log +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.cc new file mode 100644 index 0000000..c91405c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.cc @@ -0,0 +1,136 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/memtable.h" +#include "db/dbformat.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/iterator.h" +#include "util/coding.h" + +namespace leveldb { + +static Slice GetLengthPrefixedSlice(const char* data) { + uint32_t len; + const char* p = data; + p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted + return Slice(p, len); +} + +MemTable::MemTable(const InternalKeyComparator& comparator) + : comparator_(comparator), refs_(0), table_(comparator_, &arena_) {} + +MemTable::~MemTable() { assert(refs_ == 0); } + +size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); } + +int MemTable::KeyComparator::operator()(const char* aptr, + const char* bptr) const { + // Internal keys are encoded as length-prefixed strings. + Slice a = GetLengthPrefixedSlice(aptr); + Slice b = GetLengthPrefixedSlice(bptr); + return comparator.Compare(a, b); +} + +// Encode a suitable internal key target for "target" and return it. +// Uses *scratch as scratch space, and the returned pointer will point +// into this scratch space. +static const char* EncodeKey(std::string* scratch, const Slice& target) { + scratch->clear(); + PutVarint32(scratch, target.size()); + scratch->append(target.data(), target.size()); + return scratch->data(); +} + +class MemTableIterator : public Iterator { + public: + explicit MemTableIterator(MemTable::Table* table) : iter_(table) {} + + virtual bool Valid() const { return iter_.Valid(); } + virtual void Seek(const Slice& k) { iter_.Seek(EncodeKey(&tmp_, k)); } + virtual void SeekToFirst() { iter_.SeekToFirst(); } + virtual void SeekToLast() { iter_.SeekToLast(); } + virtual void Next() { iter_.Next(); } + virtual void Prev() { iter_.Prev(); } + virtual Slice key() const { return GetLengthPrefixedSlice(iter_.key()); } + virtual Slice value() const { + Slice key_slice = GetLengthPrefixedSlice(iter_.key()); + return GetLengthPrefixedSlice(key_slice.data() + key_slice.size()); + } + + virtual Status status() const { return Status::OK(); } + + private: + MemTable::Table::Iterator iter_; + std::string tmp_; // For passing to EncodeKey + + // No copying allowed + MemTableIterator(const MemTableIterator&); + void operator=(const MemTableIterator&); +}; + +Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); } + +void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key, + const Slice& value) { + // Format of an entry is concatenation of: + // key_size : varint32 of internal_key.size() + // key bytes : char[internal_key.size()] + // value_size : varint32 of value.size() + // value bytes : char[value.size()] + size_t key_size = key.size(); + size_t val_size = value.size(); + size_t internal_key_size = key_size + 8; + const size_t encoded_len = VarintLength(internal_key_size) + + internal_key_size + VarintLength(val_size) + + val_size; + char* buf = arena_.Allocate(encoded_len); + char* p = EncodeVarint32(buf, internal_key_size); + memcpy(p, key.data(), key_size); + p += key_size; + EncodeFixed64(p, (s << 8) | type); + p += 8; + p = EncodeVarint32(p, val_size); + memcpy(p, value.data(), val_size); + assert(p + val_size == buf + encoded_len); + table_.Insert(buf); +} + +bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) { + Slice memkey = key.memtable_key(); + Table::Iterator iter(&table_); + iter.Seek(memkey.data()); + if (iter.Valid()) { + // entry format is: + // klength varint32 + // userkey char[klength] + // tag uint64 + // vlength varint32 + // value char[vlength] + // Check that it belongs to same user key. We do not check the + // sequence number since the Seek() call above should have skipped + // all entries with overly large sequence numbers. + const char* entry = iter.key(); + uint32_t key_length; + const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length); + if (comparator_.comparator.user_comparator()->Compare( + Slice(key_ptr, key_length - 8), key.user_key()) == 0) { + // Correct user key + const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8); + switch (static_cast(tag & 0xff)) { + case kTypeValue: { + Slice v = GetLengthPrefixedSlice(key_ptr + key_length); + value->assign(v.data(), v.size()); + return true; + } + case kTypeDeletion: + *s = Status::NotFound(Slice()); + return true; + } + } + } + return false; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.h new file mode 100644 index 0000000..9d986b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/memtable.h @@ -0,0 +1,87 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_MEMTABLE_H_ +#define STORAGE_LEVELDB_DB_MEMTABLE_H_ + +#include + +#include "db/dbformat.h" +#include "db/skiplist.h" +#include "leveldb/db.h" +#include "util/arena.h" + +namespace leveldb { + +class InternalKeyComparator; +class MemTableIterator; + +class MemTable { + public: + // MemTables are reference counted. The initial reference count + // is zero and the caller must call Ref() at least once. + explicit MemTable(const InternalKeyComparator& comparator); + + MemTable(const MemTable&) = delete; + MemTable& operator=(const MemTable&) = delete; + + // Increase reference count. + void Ref() { ++refs_; } + + // Drop reference count. Delete if no more references exist. + void Unref() { + --refs_; + assert(refs_ >= 0); + if (refs_ <= 0) { + delete this; + } + } + + // Returns an estimate of the number of bytes of data in use by this + // data structure. It is safe to call when MemTable is being modified. + size_t ApproximateMemoryUsage(); + + // Return an iterator that yields the contents of the memtable. + // + // The caller must ensure that the underlying MemTable remains live + // while the returned iterator is live. The keys returned by this + // iterator are internal keys encoded by AppendInternalKey in the + // db/format.{h,cc} module. + Iterator* NewIterator(); + + // Add an entry into memtable that maps key to value at the + // specified sequence number and with the specified type. + // Typically value will be empty if type==kTypeDeletion. + void Add(SequenceNumber seq, ValueType type, const Slice& key, + const Slice& value); + + // If memtable contains a value for key, store it in *value and return true. + // If memtable contains a deletion for key, store a NotFound() error + // in *status and return true. + // Else, return false. + bool Get(const LookupKey& key, std::string* value, Status* s); + + private: + friend class MemTableIterator; + friend class MemTableBackwardIterator; + + struct KeyComparator { + const InternalKeyComparator comparator; + explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {} + int operator()(const char* a, const char* b) const; + }; + + typedef SkipList Table; + + ~MemTable(); // Private since only Unref() should be used to delete it + + KeyComparator comparator_; + int refs_; + Arena arena_; + Table table_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_MEMTABLE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/repair.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/repair.cc new file mode 100644 index 0000000..3c676ca --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/repair.cc @@ -0,0 +1,450 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// We recover the contents of the descriptor from the other files we find. +// (1) Any log files are first converted to tables +// (2) We scan every table to compute +// (a) smallest/largest for the table +// (b) largest sequence number in the table +// (3) We generate descriptor contents: +// - log number is set to zero +// - next-file-number is set to 1 + largest file number we found +// - last-sequence-number is set to largest sequence# found across +// all tables (see 2c) +// - compaction pointers are cleared +// - every table file is added at level 0 +// +// Possible optimization 1: +// (a) Compute total size and use to pick appropriate max-level M +// (b) Sort tables by largest sequence# in the table +// (c) For each table: if it overlaps earlier table, place in level-0, +// else place in level-M. +// Possible optimization 2: +// Store per-table metadata (smallest, largest, largest-seq#, ...) +// in the table's meta section to speed up ScanTable. + +#include "db/builder.h" +#include "db/db_impl.h" +#include "db/dbformat.h" +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "db/version_edit.h" +#include "db/write_batch_internal.h" +#include "leveldb/comparator.h" +#include "leveldb/db.h" +#include "leveldb/env.h" + +namespace leveldb { + +namespace { + +class Repairer { + public: + Repairer(const std::string& dbname, const Options& options) + : dbname_(dbname), + env_(options.env), + icmp_(options.comparator), + ipolicy_(options.filter_policy), + options_(SanitizeOptions(dbname, &icmp_, &ipolicy_, options)), + owns_info_log_(options_.info_log != options.info_log), + owns_cache_(options_.block_cache != options.block_cache), + next_file_number_(1) { + // TableCache can be small since we expect each table to be opened once. + table_cache_ = new TableCache(dbname_, options_, 10); + } + + ~Repairer() { + delete table_cache_; + if (owns_info_log_) { + delete options_.info_log; + } + if (owns_cache_) { + delete options_.block_cache; + } + } + + Status Run() { + Status status = FindFiles(); + if (status.ok()) { + ConvertLogFilesToTables(); + ExtractMetaData(); + status = WriteDescriptor(); + } + if (status.ok()) { + unsigned long long bytes = 0; + for (size_t i = 0; i < tables_.size(); i++) { + bytes += tables_[i].meta.file_size; + } + Log(options_.info_log, + "**** Repaired leveldb %s; " + "recovered %d files; %llu bytes. " + "Some data may have been lost. " + "****", + dbname_.c_str(), static_cast(tables_.size()), bytes); + } + return status; + } + + private: + struct TableInfo { + FileMetaData meta; + SequenceNumber max_sequence; + }; + + Status FindFiles() { + std::vector filenames; + Status status = env_->GetChildren(dbname_, &filenames); + if (!status.ok()) { + return status; + } + if (filenames.empty()) { + return Status::IOError(dbname_, "repair found no files"); + } + + uint64_t number; + FileType type; + for (size_t i = 0; i < filenames.size(); i++) { + if (ParseFileName(filenames[i], &number, &type)) { + if (type == kDescriptorFile) { + manifests_.push_back(filenames[i]); + } else { + if (number + 1 > next_file_number_) { + next_file_number_ = number + 1; + } + if (type == kLogFile) { + logs_.push_back(number); + } else if (type == kTableFile) { + table_numbers_.push_back(number); + } else { + // Ignore other files + } + } + } + } + return status; + } + + void ConvertLogFilesToTables() { + for (size_t i = 0; i < logs_.size(); i++) { + std::string logname = LogFileName(dbname_, logs_[i]); + Status status = ConvertLogToTable(logs_[i]); + if (!status.ok()) { + Log(options_.info_log, "Log #%llu: ignoring conversion error: %s", + (unsigned long long)logs_[i], status.ToString().c_str()); + } + ArchiveFile(logname); + } + } + + Status ConvertLogToTable(uint64_t log) { + struct LogReporter : public log::Reader::Reporter { + Env* env; + Logger* info_log; + uint64_t lognum; + virtual void Corruption(size_t bytes, const Status& s) { + // We print error messages for corruption, but continue repairing. + Log(info_log, "Log #%llu: dropping %d bytes; %s", + (unsigned long long)lognum, static_cast(bytes), + s.ToString().c_str()); + } + }; + + // Open the log file + std::string logname = LogFileName(dbname_, log); + SequentialFile* lfile; + Status status = env_->NewSequentialFile(logname, &lfile); + if (!status.ok()) { + return status; + } + + // Create the log reader. + LogReporter reporter; + reporter.env = env_; + reporter.info_log = options_.info_log; + reporter.lognum = log; + // We intentionally make log::Reader do checksumming so that + // corruptions cause entire commits to be skipped instead of + // propagating bad information (like overly large sequence + // numbers). + log::Reader reader(lfile, &reporter, false /*do not checksum*/, + 0 /*initial_offset*/); + + // Read all the records and add to a memtable + std::string scratch; + Slice record; + WriteBatch batch; + MemTable* mem = new MemTable(icmp_); + mem->Ref(); + int counter = 0; + while (reader.ReadRecord(&record, &scratch)) { + if (record.size() < 12) { + reporter.Corruption(record.size(), + Status::Corruption("log record too small")); + continue; + } + WriteBatchInternal::SetContents(&batch, record); + status = WriteBatchInternal::InsertInto(&batch, mem); + if (status.ok()) { + counter += WriteBatchInternal::Count(&batch); + } else { + Log(options_.info_log, "Log #%llu: ignoring %s", + (unsigned long long)log, status.ToString().c_str()); + status = Status::OK(); // Keep going with rest of file + } + } + delete lfile; + + // Do not record a version edit for this conversion to a Table + // since ExtractMetaData() will also generate edits. + FileMetaData meta; + meta.number = next_file_number_++; + Iterator* iter = mem->NewIterator(); + status = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta); + delete iter; + mem->Unref(); + mem = nullptr; + if (status.ok()) { + if (meta.file_size > 0) { + table_numbers_.push_back(meta.number); + } + } + Log(options_.info_log, "Log #%llu: %d ops saved to Table #%llu %s", + (unsigned long long)log, counter, (unsigned long long)meta.number, + status.ToString().c_str()); + return status; + } + + void ExtractMetaData() { + for (size_t i = 0; i < table_numbers_.size(); i++) { + ScanTable(table_numbers_[i]); + } + } + + Iterator* NewTableIterator(const FileMetaData& meta) { + // Same as compaction iterators: if paranoid_checks are on, turn + // on checksum verification. + ReadOptions r; + r.verify_checksums = options_.paranoid_checks; + return table_cache_->NewIterator(r, meta.number, meta.file_size); + } + + void ScanTable(uint64_t number) { + TableInfo t; + t.meta.number = number; + std::string fname = TableFileName(dbname_, number); + Status status = env_->GetFileSize(fname, &t.meta.file_size); + if (!status.ok()) { + // Try alternate file name. + fname = SSTTableFileName(dbname_, number); + Status s2 = env_->GetFileSize(fname, &t.meta.file_size); + if (s2.ok()) { + status = Status::OK(); + } + } + if (!status.ok()) { + ArchiveFile(TableFileName(dbname_, number)); + ArchiveFile(SSTTableFileName(dbname_, number)); + Log(options_.info_log, "Table #%llu: dropped: %s", + (unsigned long long)t.meta.number, status.ToString().c_str()); + return; + } + + // Extract metadata by scanning through table. + int counter = 0; + Iterator* iter = NewTableIterator(t.meta); + bool empty = true; + ParsedInternalKey parsed; + t.max_sequence = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + Slice key = iter->key(); + if (!ParseInternalKey(key, &parsed)) { + Log(options_.info_log, "Table #%llu: unparsable key %s", + (unsigned long long)t.meta.number, EscapeString(key).c_str()); + continue; + } + + counter++; + if (empty) { + empty = false; + t.meta.smallest.DecodeFrom(key); + } + t.meta.largest.DecodeFrom(key); + if (parsed.sequence > t.max_sequence) { + t.max_sequence = parsed.sequence; + } + } + if (!iter->status().ok()) { + status = iter->status(); + } + delete iter; + Log(options_.info_log, "Table #%llu: %d entries %s", + (unsigned long long)t.meta.number, counter, status.ToString().c_str()); + + if (status.ok()) { + tables_.push_back(t); + } else { + RepairTable(fname, t); // RepairTable archives input file. + } + } + + void RepairTable(const std::string& src, TableInfo t) { + // We will copy src contents to a new table and then rename the + // new table over the source. + + // Create builder. + std::string copy = TableFileName(dbname_, next_file_number_++); + WritableFile* file; + Status s = env_->NewWritableFile(copy, &file); + if (!s.ok()) { + return; + } + TableBuilder* builder = new TableBuilder(options_, file); + + // Copy data. + Iterator* iter = NewTableIterator(t.meta); + int counter = 0; + for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { + builder->Add(iter->key(), iter->value()); + counter++; + } + delete iter; + + ArchiveFile(src); + if (counter == 0) { + builder->Abandon(); // Nothing to save + } else { + s = builder->Finish(); + if (s.ok()) { + t.meta.file_size = builder->FileSize(); + } + } + delete builder; + builder = nullptr; + + if (s.ok()) { + s = file->Close(); + } + delete file; + file = nullptr; + + if (counter > 0 && s.ok()) { + std::string orig = TableFileName(dbname_, t.meta.number); + s = env_->RenameFile(copy, orig); + if (s.ok()) { + Log(options_.info_log, "Table #%llu: %d entries repaired", + (unsigned long long)t.meta.number, counter); + tables_.push_back(t); + } + } + if (!s.ok()) { + env_->DeleteFile(copy); + } + } + + Status WriteDescriptor() { + std::string tmp = TempFileName(dbname_, 1); + WritableFile* file; + Status status = env_->NewWritableFile(tmp, &file); + if (!status.ok()) { + return status; + } + + SequenceNumber max_sequence = 0; + for (size_t i = 0; i < tables_.size(); i++) { + if (max_sequence < tables_[i].max_sequence) { + max_sequence = tables_[i].max_sequence; + } + } + + edit_.SetComparatorName(icmp_.user_comparator()->Name()); + edit_.SetLogNumber(0); + edit_.SetNextFile(next_file_number_); + edit_.SetLastSequence(max_sequence); + + for (size_t i = 0; i < tables_.size(); i++) { + // TODO(opt): separate out into multiple levels + const TableInfo& t = tables_[i]; + edit_.AddFile(0, t.meta.number, t.meta.file_size, t.meta.smallest, + t.meta.largest); + } + + // fprintf(stderr, "NewDescriptor:\n%s\n", edit_.DebugString().c_str()); + { + log::Writer log(file); + std::string record; + edit_.EncodeTo(&record); + status = log.AddRecord(record); + } + if (status.ok()) { + status = file->Close(); + } + delete file; + file = nullptr; + + if (!status.ok()) { + env_->DeleteFile(tmp); + } else { + // Discard older manifests + for (size_t i = 0; i < manifests_.size(); i++) { + ArchiveFile(dbname_ + "/" + manifests_[i]); + } + + // Install new manifest + status = env_->RenameFile(tmp, DescriptorFileName(dbname_, 1)); + if (status.ok()) { + status = SetCurrentFile(env_, dbname_, 1); + } else { + env_->DeleteFile(tmp); + } + } + return status; + } + + void ArchiveFile(const std::string& fname) { + // Move into another directory. E.g., for + // dir/foo + // rename to + // dir/lost/foo + const char* slash = strrchr(fname.c_str(), '/'); + std::string new_dir; + if (slash != nullptr) { + new_dir.assign(fname.data(), slash - fname.data()); + } + new_dir.append("/lost"); + env_->CreateDir(new_dir); // Ignore error + std::string new_file = new_dir; + new_file.append("/"); + new_file.append((slash == nullptr) ? fname.c_str() : slash + 1); + Status s = env_->RenameFile(fname, new_file); + Log(options_.info_log, "Archiving %s: %s\n", fname.c_str(), + s.ToString().c_str()); + } + + const std::string dbname_; + Env* const env_; + InternalKeyComparator const icmp_; + InternalFilterPolicy const ipolicy_; + const Options options_; + bool owns_info_log_; + bool owns_cache_; + TableCache* table_cache_; + VersionEdit edit_; + + std::vector manifests_; + std::vector table_numbers_; + std::vector logs_; + std::vector tables_; + uint64_t next_file_number_; +}; +} // namespace + +Status RepairDB(const std::string& dbname, const Options& options) { + Repairer repairer(dbname, options); + return repairer.Run(); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/skiplist.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/skiplist.h new file mode 100644 index 0000000..a59b45b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/skiplist.h @@ -0,0 +1,382 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SKIPLIST_H_ +#define STORAGE_LEVELDB_DB_SKIPLIST_H_ + +// Thread safety +// ------------- +// +// Writes require external synchronization, most likely a mutex. +// Reads require a guarantee that the SkipList will not be destroyed +// while the read is in progress. Apart from that, reads progress +// without any internal locking or synchronization. +// +// Invariants: +// +// (1) Allocated nodes are never deleted until the SkipList is +// destroyed. This is trivially guaranteed by the code since we +// never delete any skip list nodes. +// +// (2) The contents of a Node except for the next/prev pointers are +// immutable after the Node has been linked into the SkipList. +// Only Insert() modifies the list, and it is careful to initialize +// a node and use release-stores to publish the nodes in one or +// more lists. +// +// ... prev vs. next pointer ordering ... + +#include +#include +#include + +#include "util/arena.h" +#include "util/random.h" + +namespace leveldb { + +class Arena; + +template +class SkipList { + private: + struct Node; + + public: + // Create a new SkipList object that will use "cmp" for comparing keys, + // and will allocate memory using "*arena". Objects allocated in the arena + // must remain allocated for the lifetime of the skiplist object. + explicit SkipList(Comparator cmp, Arena* arena); + + SkipList(const SkipList&) = delete; + SkipList& operator=(const SkipList&) = delete; + + // Insert key into the list. + // REQUIRES: nothing that compares equal to key is currently in the list. + void Insert(const Key& key); + + // Returns true iff an entry that compares equal to key is in the list. + bool Contains(const Key& key) const; + + // Iteration over the contents of a skip list + class Iterator { + public: + // Initialize an iterator over the specified list. + // The returned iterator is not valid. + explicit Iterator(const SkipList* list); + + // Returns true iff the iterator is positioned at a valid node. + bool Valid() const; + + // Returns the key at the current position. + // REQUIRES: Valid() + const Key& key() const; + + // Advances to the next position. + // REQUIRES: Valid() + void Next(); + + // Advances to the previous position. + // REQUIRES: Valid() + void Prev(); + + // Advance to the first entry with a key >= target + void Seek(const Key& target); + + // Position at the first entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToFirst(); + + // Position at the last entry in list. + // Final state of iterator is Valid() iff list is not empty. + void SeekToLast(); + + private: + const SkipList* list_; + Node* node_; + // Intentionally copyable + }; + + private: + enum { kMaxHeight = 12 }; + + inline int GetMaxHeight() const { + return max_height_.load(std::memory_order_relaxed); + } + + Node* NewNode(const Key& key, int height); + int RandomHeight(); + bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); } + + // Return true if key is greater than the data stored in "n" + bool KeyIsAfterNode(const Key& key, Node* n) const; + + // Return the earliest node that comes at or after key. + // Return nullptr if there is no such node. + // + // If prev is non-null, fills prev[level] with pointer to previous + // node at "level" for every level in [0..max_height_-1]. + Node* FindGreaterOrEqual(const Key& key, Node** prev) const; + + // Return the latest node with a key < key. + // Return head_ if there is no such node. + Node* FindLessThan(const Key& key) const; + + // Return the last node in the list. + // Return head_ if list is empty. + Node* FindLast() const; + + // Immutable after construction + Comparator const compare_; + Arena* const arena_; // Arena used for allocations of nodes + + Node* const head_; + + // Modified only by Insert(). Read racily by readers, but stale + // values are ok. + std::atomic max_height_; // Height of the entire list + + // Read/written only by Insert(). + Random rnd_; +}; + +// Implementation details follow +template +struct SkipList::Node { + explicit Node(const Key& k) : key(k) {} + + Key const key; + + // Accessors/mutators for links. Wrapped in methods so we can + // add the appropriate barriers as necessary. + Node* Next(int n) { + assert(n >= 0); + // Use an 'acquire load' so that we observe a fully initialized + // version of the returned Node. + return next_[n].load(std::memory_order_acquire); + } + void SetNext(int n, Node* x) { + assert(n >= 0); + // Use a 'release store' so that anybody who reads through this + // pointer observes a fully initialized version of the inserted node. + next_[n].store(x, std::memory_order_release); + } + + // No-barrier variants that can be safely used in a few locations. + Node* NoBarrier_Next(int n) { + assert(n >= 0); + return next_[n].load(std::memory_order_relaxed); + } + void NoBarrier_SetNext(int n, Node* x) { + assert(n >= 0); + next_[n].store(x, std::memory_order_relaxed); + } + + private: + // Array of length equal to the node height. next_[0] is lowest level link. + std::atomic next_[1]; +}; + +template +typename SkipList::Node* SkipList::NewNode( + const Key& key, int height) { + char* const node_memory = arena_->AllocateAligned( + sizeof(Node) + sizeof(std::atomic) * (height - 1)); + return new (node_memory) Node(key); +} + +template +inline SkipList::Iterator::Iterator(const SkipList* list) { + list_ = list; + node_ = nullptr; +} + +template +inline bool SkipList::Iterator::Valid() const { + return node_ != nullptr; +} + +template +inline const Key& SkipList::Iterator::key() const { + assert(Valid()); + return node_->key; +} + +template +inline void SkipList::Iterator::Next() { + assert(Valid()); + node_ = node_->Next(0); +} + +template +inline void SkipList::Iterator::Prev() { + // Instead of using explicit "prev" links, we just search for the + // last node that falls before key. + assert(Valid()); + node_ = list_->FindLessThan(node_->key); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +inline void SkipList::Iterator::Seek(const Key& target) { + node_ = list_->FindGreaterOrEqual(target, nullptr); +} + +template +inline void SkipList::Iterator::SeekToFirst() { + node_ = list_->head_->Next(0); +} + +template +inline void SkipList::Iterator::SeekToLast() { + node_ = list_->FindLast(); + if (node_ == list_->head_) { + node_ = nullptr; + } +} + +template +int SkipList::RandomHeight() { + // Increase height with probability 1 in kBranching + static const unsigned int kBranching = 4; + int height = 1; + while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) { + height++; + } + assert(height > 0); + assert(height <= kMaxHeight); + return height; +} + +template +bool SkipList::KeyIsAfterNode(const Key& key, Node* n) const { + // null n is considered infinite + return (n != nullptr) && (compare_(n->key, key) < 0); +} + +template +typename SkipList::Node* +SkipList::FindGreaterOrEqual(const Key& key, + Node** prev) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (KeyIsAfterNode(key, next)) { + // Keep searching in this list + x = next; + } else { + if (prev != nullptr) prev[level] = x; + if (level == 0) { + return next; + } else { + // Switch to next list + level--; + } + } + } +} + +template +typename SkipList::Node* +SkipList::FindLessThan(const Key& key) const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + assert(x == head_ || compare_(x->key, key) < 0); + Node* next = x->Next(level); + if (next == nullptr || compare_(next->key, key) >= 0) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +typename SkipList::Node* SkipList::FindLast() + const { + Node* x = head_; + int level = GetMaxHeight() - 1; + while (true) { + Node* next = x->Next(level); + if (next == nullptr) { + if (level == 0) { + return x; + } else { + // Switch to next list + level--; + } + } else { + x = next; + } + } +} + +template +SkipList::SkipList(Comparator cmp, Arena* arena) + : compare_(cmp), + arena_(arena), + head_(NewNode(0 /* any key will do */, kMaxHeight)), + max_height_(1), + rnd_(0xdeadbeef) { + for (int i = 0; i < kMaxHeight; i++) { + head_->SetNext(i, nullptr); + } +} + +template +void SkipList::Insert(const Key& key) { + // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() + // here since Insert() is externally synchronized. + Node* prev[kMaxHeight]; + Node* x = FindGreaterOrEqual(key, prev); + + // Our data structure does not allow duplicate insertion + assert(x == nullptr || !Equal(key, x->key)); + + int height = RandomHeight(); + if (height > GetMaxHeight()) { + for (int i = GetMaxHeight(); i < height; i++) { + prev[i] = head_; + } + // It is ok to mutate max_height_ without any synchronization + // with concurrent readers. A concurrent reader that observes + // the new value of max_height_ will see either the old value of + // new level pointers from head_ (nullptr), or a new value set in + // the loop below. In the former case the reader will + // immediately drop to the next level since nullptr sorts after all + // keys. In the latter case the reader will use the new node. + max_height_.store(height, std::memory_order_relaxed); + } + + x = NewNode(key, height); + for (int i = 0; i < height; i++) { + // NoBarrier_SetNext() suffices since we will add a barrier when + // we publish a pointer to "x" in prev[i]. + x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); + prev[i]->SetNext(i, x); + } +} + +template +bool SkipList::Contains(const Key& key) const { + Node* x = FindGreaterOrEqual(key, nullptr); + if (x != nullptr && Equal(key, x->key)) { + return true; + } else { + return false; + } +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SKIPLIST_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/snapshot.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/snapshot.h new file mode 100644 index 0000000..9f1d664 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/snapshot.h @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_SNAPSHOT_H_ +#define STORAGE_LEVELDB_DB_SNAPSHOT_H_ + +#include "db/dbformat.h" +#include "leveldb/db.h" + +namespace leveldb { + +class SnapshotList; + +// Snapshots are kept in a doubly-linked list in the DB. +// Each SnapshotImpl corresponds to a particular sequence number. +class SnapshotImpl : public Snapshot { + public: + SnapshotImpl(SequenceNumber sequence_number) + : sequence_number_(sequence_number) {} + + SequenceNumber sequence_number() const { return sequence_number_; } + + private: + friend class SnapshotList; + + // SnapshotImpl is kept in a doubly-linked circular list. The SnapshotList + // implementation operates on the next/previous fields direcly. + SnapshotImpl* prev_; + SnapshotImpl* next_; + + const SequenceNumber sequence_number_; + +#if !defined(NDEBUG) + SnapshotList* list_ = nullptr; +#endif // !defined(NDEBUG) +}; + +class SnapshotList { + public: + SnapshotList() : head_(0) { + head_.prev_ = &head_; + head_.next_ = &head_; + } + + bool empty() const { return head_.next_ == &head_; } + SnapshotImpl* oldest() const { + assert(!empty()); + return head_.next_; + } + SnapshotImpl* newest() const { + assert(!empty()); + return head_.prev_; + } + + // Creates a SnapshotImpl and appends it to the end of the list. + SnapshotImpl* New(SequenceNumber sequence_number) { + assert(empty() || newest()->sequence_number_ <= sequence_number); + + SnapshotImpl* snapshot = new SnapshotImpl(sequence_number); + +#if !defined(NDEBUG) + snapshot->list_ = this; +#endif // !defined(NDEBUG) + snapshot->next_ = &head_; + snapshot->prev_ = head_.prev_; + snapshot->prev_->next_ = snapshot; + snapshot->next_->prev_ = snapshot; + return snapshot; + } + + // Removes a SnapshotImpl from this list. + // + // The snapshot must have been created by calling New() on this list. + // + // The snapshot pointer should not be const, because its memory is + // deallocated. However, that would force us to change DB::ReleaseSnapshot(), + // which is in the API, and currently takes a const Snapshot. + void Delete(const SnapshotImpl* snapshot) { +#if !defined(NDEBUG) + assert(snapshot->list_ == this); +#endif // !defined(NDEBUG) + snapshot->prev_->next_ = snapshot->next_; + snapshot->next_->prev_ = snapshot->prev_; + delete snapshot; + } + + private: + // Dummy head of doubly-linked list of snapshots + SnapshotImpl head_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.cc new file mode 100644 index 0000000..73f05fd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.cc @@ -0,0 +1,120 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/table_cache.h" + +#include "db/filename.h" +#include "leveldb/env.h" +#include "leveldb/table.h" +#include "util/coding.h" + +namespace leveldb { + +struct TableAndFile { + RandomAccessFile* file; + Table* table; +}; + +static void DeleteEntry(const Slice& key, void* value) { + TableAndFile* tf = reinterpret_cast(value); + delete tf->table; + delete tf->file; + delete tf; +} + +static void UnrefEntry(void* arg1, void* arg2) { + Cache* cache = reinterpret_cast(arg1); + Cache::Handle* h = reinterpret_cast(arg2); + cache->Release(h); +} + +TableCache::TableCache(const std::string& dbname, const Options& options, + int entries) + : env_(options.env), + dbname_(dbname), + options_(options), + cache_(NewLRUCache(entries)) {} + +TableCache::~TableCache() { delete cache_; } + +Status TableCache::FindTable(uint64_t file_number, uint64_t file_size, + Cache::Handle** handle) { + Status s; + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + Slice key(buf, sizeof(buf)); + *handle = cache_->Lookup(key); + if (*handle == nullptr) { + std::string fname = TableFileName(dbname_, file_number); + RandomAccessFile* file = nullptr; + Table* table = nullptr; + s = env_->NewRandomAccessFile(fname, &file); + if (!s.ok()) { + std::string old_fname = SSTTableFileName(dbname_, file_number); + if (env_->NewRandomAccessFile(old_fname, &file).ok()) { + s = Status::OK(); + } + } + if (s.ok()) { + s = Table::Open(options_, file, file_size, &table); + } + + if (!s.ok()) { + assert(table == nullptr); + delete file; + // We do not cache error results so that if the error is transient, + // or somebody repairs the file, we recover automatically. + } else { + TableAndFile* tf = new TableAndFile; + tf->file = file; + tf->table = table; + *handle = cache_->Insert(key, tf, 1, &DeleteEntry); + } + } + return s; +} + +Iterator* TableCache::NewIterator(const ReadOptions& options, + uint64_t file_number, uint64_t file_size, + Table** tableptr) { + if (tableptr != nullptr) { + *tableptr = nullptr; + } + + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (!s.ok()) { + return NewErrorIterator(s); + } + + Table* table = reinterpret_cast(cache_->Value(handle))->table; + Iterator* result = table->NewIterator(options); + result->RegisterCleanup(&UnrefEntry, cache_, handle); + if (tableptr != nullptr) { + *tableptr = table; + } + return result; +} + +Status TableCache::Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Cache::Handle* handle = nullptr; + Status s = FindTable(file_number, file_size, &handle); + if (s.ok()) { + Table* t = reinterpret_cast(cache_->Value(handle))->table; + s = t->InternalGet(options, k, arg, handle_result); + cache_->Release(handle); + } + return s; +} + +void TableCache::Evict(uint64_t file_number) { + char buf[sizeof(file_number)]; + EncodeFixed64(buf, file_number); + cache_->Erase(Slice(buf, sizeof(buf))); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.h new file mode 100644 index 0000000..93069c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/table_cache.h @@ -0,0 +1,58 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Thread-safe (provides internal synchronization) + +#ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_ +#define STORAGE_LEVELDB_DB_TABLE_CACHE_H_ + +#include + +#include + +#include "db/dbformat.h" +#include "leveldb/cache.h" +#include "leveldb/table.h" +#include "port/port.h" + +namespace leveldb { + +class Env; + +class TableCache { + public: + TableCache(const std::string& dbname, const Options& options, int entries); + ~TableCache(); + + // Return an iterator for the specified file number (the corresponding + // file length must be exactly "file_size" bytes). If "tableptr" is + // non-null, also sets "*tableptr" to point to the Table object + // underlying the returned iterator, or to nullptr if no Table object + // underlies the returned iterator. The returned "*tableptr" object is owned + // by the cache and should not be deleted, and is valid for as long as the + // returned iterator is live. + Iterator* NewIterator(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, Table** tableptr = nullptr); + + // If a seek to internal key "k" in specified file finds an entry, + // call (*handle_result)(arg, found_key, found_value). + Status Get(const ReadOptions& options, uint64_t file_number, + uint64_t file_size, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, const Slice&)); + + // Evict any entry for the specified file number + void Evict(uint64_t file_number); + + private: + Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); + + Env* const env_; + const std::string dbname_; + const Options& options_; + Cache* cache_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.cc new file mode 100644 index 0000000..44a4d02 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.cc @@ -0,0 +1,260 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_edit.h" + +#include "db/version_set.h" +#include "util/coding.h" + +namespace leveldb { + +// Tag numbers for serialized VersionEdit. These numbers are written to +// disk and should not be changed. +enum Tag { + kComparator = 1, + kLogNumber = 2, + kNextFileNumber = 3, + kLastSequence = 4, + kCompactPointer = 5, + kDeletedFile = 6, + kNewFile = 7, + // 8 was used for large value refs + kPrevLogNumber = 9 +}; + +void VersionEdit::Clear() { + comparator_.clear(); + log_number_ = 0; + prev_log_number_ = 0; + last_sequence_ = 0; + next_file_number_ = 0; + has_comparator_ = false; + has_log_number_ = false; + has_prev_log_number_ = false; + has_next_file_number_ = false; + has_last_sequence_ = false; + deleted_files_.clear(); + new_files_.clear(); +} + +void VersionEdit::EncodeTo(std::string* dst) const { + if (has_comparator_) { + PutVarint32(dst, kComparator); + PutLengthPrefixedSlice(dst, comparator_); + } + if (has_log_number_) { + PutVarint32(dst, kLogNumber); + PutVarint64(dst, log_number_); + } + if (has_prev_log_number_) { + PutVarint32(dst, kPrevLogNumber); + PutVarint64(dst, prev_log_number_); + } + if (has_next_file_number_) { + PutVarint32(dst, kNextFileNumber); + PutVarint64(dst, next_file_number_); + } + if (has_last_sequence_) { + PutVarint32(dst, kLastSequence); + PutVarint64(dst, last_sequence_); + } + + for (size_t i = 0; i < compact_pointers_.size(); i++) { + PutVarint32(dst, kCompactPointer); + PutVarint32(dst, compact_pointers_[i].first); // level + PutLengthPrefixedSlice(dst, compact_pointers_[i].second.Encode()); + } + + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + PutVarint32(dst, kDeletedFile); + PutVarint32(dst, iter->first); // level + PutVarint64(dst, iter->second); // file number + } + + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + PutVarint32(dst, kNewFile); + PutVarint32(dst, new_files_[i].first); // level + PutVarint64(dst, f.number); + PutVarint64(dst, f.file_size); + PutLengthPrefixedSlice(dst, f.smallest.Encode()); + PutLengthPrefixedSlice(dst, f.largest.Encode()); + } +} + +static bool GetInternalKey(Slice* input, InternalKey* dst) { + Slice str; + if (GetLengthPrefixedSlice(input, &str)) { + dst->DecodeFrom(str); + return true; + } else { + return false; + } +} + +static bool GetLevel(Slice* input, int* level) { + uint32_t v; + if (GetVarint32(input, &v) && v < config::kNumLevels) { + *level = v; + return true; + } else { + return false; + } +} + +Status VersionEdit::DecodeFrom(const Slice& src) { + Clear(); + Slice input = src; + const char* msg = nullptr; + uint32_t tag; + + // Temporary storage for parsing + int level; + uint64_t number; + FileMetaData f; + Slice str; + InternalKey key; + + while (msg == nullptr && GetVarint32(&input, &tag)) { + switch (tag) { + case kComparator: + if (GetLengthPrefixedSlice(&input, &str)) { + comparator_ = str.ToString(); + has_comparator_ = true; + } else { + msg = "comparator name"; + } + break; + + case kLogNumber: + if (GetVarint64(&input, &log_number_)) { + has_log_number_ = true; + } else { + msg = "log number"; + } + break; + + case kPrevLogNumber: + if (GetVarint64(&input, &prev_log_number_)) { + has_prev_log_number_ = true; + } else { + msg = "previous log number"; + } + break; + + case kNextFileNumber: + if (GetVarint64(&input, &next_file_number_)) { + has_next_file_number_ = true; + } else { + msg = "next file number"; + } + break; + + case kLastSequence: + if (GetVarint64(&input, &last_sequence_)) { + has_last_sequence_ = true; + } else { + msg = "last sequence number"; + } + break; + + case kCompactPointer: + if (GetLevel(&input, &level) && GetInternalKey(&input, &key)) { + compact_pointers_.push_back(std::make_pair(level, key)); + } else { + msg = "compaction pointer"; + } + break; + + case kDeletedFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &number)) { + deleted_files_.insert(std::make_pair(level, number)); + } else { + msg = "deleted file"; + } + break; + + case kNewFile: + if (GetLevel(&input, &level) && GetVarint64(&input, &f.number) && + GetVarint64(&input, &f.file_size) && + GetInternalKey(&input, &f.smallest) && + GetInternalKey(&input, &f.largest)) { + new_files_.push_back(std::make_pair(level, f)); + } else { + msg = "new-file entry"; + } + break; + + default: + msg = "unknown tag"; + break; + } + } + + if (msg == nullptr && !input.empty()) { + msg = "invalid tag"; + } + + Status result; + if (msg != nullptr) { + result = Status::Corruption("VersionEdit", msg); + } + return result; +} + +std::string VersionEdit::DebugString() const { + std::string r; + r.append("VersionEdit {"); + if (has_comparator_) { + r.append("\n Comparator: "); + r.append(comparator_); + } + if (has_log_number_) { + r.append("\n LogNumber: "); + AppendNumberTo(&r, log_number_); + } + if (has_prev_log_number_) { + r.append("\n PrevLogNumber: "); + AppendNumberTo(&r, prev_log_number_); + } + if (has_next_file_number_) { + r.append("\n NextFile: "); + AppendNumberTo(&r, next_file_number_); + } + if (has_last_sequence_) { + r.append("\n LastSeq: "); + AppendNumberTo(&r, last_sequence_); + } + for (size_t i = 0; i < compact_pointers_.size(); i++) { + r.append("\n CompactPointer: "); + AppendNumberTo(&r, compact_pointers_[i].first); + r.append(" "); + r.append(compact_pointers_[i].second.DebugString()); + } + for (DeletedFileSet::const_iterator iter = deleted_files_.begin(); + iter != deleted_files_.end(); ++iter) { + r.append("\n DeleteFile: "); + AppendNumberTo(&r, iter->first); + r.append(" "); + AppendNumberTo(&r, iter->second); + } + for (size_t i = 0; i < new_files_.size(); i++) { + const FileMetaData& f = new_files_[i].second; + r.append("\n AddFile: "); + AppendNumberTo(&r, new_files_[i].first); + r.append(" "); + AppendNumberTo(&r, f.number); + r.append(" "); + AppendNumberTo(&r, f.file_size); + r.append(" "); + r.append(f.smallest.DebugString()); + r.append(" .. "); + r.append(f.largest.DebugString()); + } + r.append("\n}\n"); + return r; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.h new file mode 100644 index 0000000..2dadda7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_edit.h @@ -0,0 +1,106 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_VERSION_EDIT_H_ +#define STORAGE_LEVELDB_DB_VERSION_EDIT_H_ + +#include +#include +#include + +#include "db/dbformat.h" + +namespace leveldb { + +class VersionSet; + +struct FileMetaData { + FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) {} + + int refs; + int allowed_seeks; // Seeks allowed until compaction + uint64_t number; + uint64_t file_size; // File size in bytes + InternalKey smallest; // Smallest internal key served by table + InternalKey largest; // Largest internal key served by table +}; + +class VersionEdit { + public: + VersionEdit() { Clear(); } + ~VersionEdit() {} + + void Clear(); + + void SetComparatorName(const Slice& name) { + has_comparator_ = true; + comparator_ = name.ToString(); + } + void SetLogNumber(uint64_t num) { + has_log_number_ = true; + log_number_ = num; + } + void SetPrevLogNumber(uint64_t num) { + has_prev_log_number_ = true; + prev_log_number_ = num; + } + void SetNextFile(uint64_t num) { + has_next_file_number_ = true; + next_file_number_ = num; + } + void SetLastSequence(SequenceNumber seq) { + has_last_sequence_ = true; + last_sequence_ = seq; + } + void SetCompactPointer(int level, const InternalKey& key) { + compact_pointers_.push_back(std::make_pair(level, key)); + } + + // Add the specified file at the specified number. + // REQUIRES: This version has not been saved (see VersionSet::SaveTo) + // REQUIRES: "smallest" and "largest" are smallest and largest keys in file + void AddFile(int level, uint64_t file, uint64_t file_size, + const InternalKey& smallest, const InternalKey& largest) { + FileMetaData f; + f.number = file; + f.file_size = file_size; + f.smallest = smallest; + f.largest = largest; + new_files_.push_back(std::make_pair(level, f)); + } + + // Delete the specified "file" from the specified "level". + void DeleteFile(int level, uint64_t file) { + deleted_files_.insert(std::make_pair(level, file)); + } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(const Slice& src); + + std::string DebugString() const; + + private: + friend class VersionSet; + + typedef std::set > DeletedFileSet; + + std::string comparator_; + uint64_t log_number_; + uint64_t prev_log_number_; + uint64_t next_file_number_; + SequenceNumber last_sequence_; + bool has_comparator_; + bool has_log_number_; + bool has_prev_log_number_; + bool has_next_file_number_; + bool has_last_sequence_; + + std::vector > compact_pointers_; + DeletedFileSet deleted_files_; + std::vector > new_files_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.cc new file mode 100644 index 0000000..96a92cc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.cc @@ -0,0 +1,1585 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "db/version_set.h" + +#include + +#include + +#include "db/filename.h" +#include "db/log_reader.h" +#include "db/log_writer.h" +#include "db/memtable.h" +#include "db/table_cache.h" +#include "leveldb/env.h" +#include "leveldb/table_builder.h" +#include "table/merger.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +static size_t TargetFileSize(const Options* options) { + return options->max_file_size; +} + +// Maximum bytes of overlaps in grandparent (i.e., level+2) before we +// stop building a single file in a level->level+1 compaction. +static int64_t MaxGrandParentOverlapBytes(const Options* options) { + return 10 * TargetFileSize(options); +} + +// Maximum number of bytes in all compacted files. We avoid expanding +// the lower level file set of a compaction if it would make the +// total compaction cover more than this many bytes. +static int64_t ExpandedCompactionByteSizeLimit(const Options* options) { + return 25 * TargetFileSize(options); +} + +static double MaxBytesForLevel(const Options* options, int level) { + // Note: the result for level zero is not really used since we set + // the level-0 compaction threshold based on number of files. + + // Result for both level-0 and level-1 + double result = 10. * 1048576.0; + while (level > 1) { + result *= 10; + level--; + } + return result; +} + +static uint64_t MaxFileSizeForLevel(const Options* options, int level) { + // We could vary per level to reduce number of files? + return TargetFileSize(options); +} + +static int64_t TotalFileSize(const std::vector& files) { + int64_t sum = 0; + for (size_t i = 0; i < files.size(); i++) { + sum += files[i]->file_size; + } + return sum; +} + +Version::~Version() { + assert(refs_ == 0); + + // Remove from linked list + prev_->next_ = next_; + next_->prev_ = prev_; + + // Drop references to files + for (int level = 0; level < config::kNumLevels; level++) { + for (size_t i = 0; i < files_[level].size(); i++) { + FileMetaData* f = files_[level][i]; + assert(f->refs > 0); + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } +} + +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key) { + uint32_t left = 0; + uint32_t right = files.size(); + while (left < right) { + uint32_t mid = (left + right) / 2; + const FileMetaData* f = files[mid]; + if (icmp.InternalKeyComparator::Compare(f->largest.Encode(), key) < 0) { + // Key at "mid.largest" is < "target". Therefore all + // files at or before "mid" are uninteresting. + left = mid + 1; + } else { + // Key at "mid.largest" is >= "target". Therefore all files + // after "mid" are uninteresting. + right = mid; + } + } + return right; +} + +static bool AfterFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs before all keys and is therefore never after *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->largest.user_key()) > 0); +} + +static bool BeforeFile(const Comparator* ucmp, const Slice* user_key, + const FileMetaData* f) { + // null user_key occurs after all keys and is therefore never before *f + return (user_key != nullptr && + ucmp->Compare(*user_key, f->smallest.user_key()) < 0); +} + +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key) { + const Comparator* ucmp = icmp.user_comparator(); + if (!disjoint_sorted_files) { + // Need to check against all files + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + if (AfterFile(ucmp, smallest_user_key, f) || + BeforeFile(ucmp, largest_user_key, f)) { + // No overlap + } else { + return true; // Overlap + } + } + return false; + } + + // Binary search over file list + uint32_t index = 0; + if (smallest_user_key != nullptr) { + // Find the earliest possible internal key for smallest_user_key + InternalKey small_key(*smallest_user_key, kMaxSequenceNumber, + kValueTypeForSeek); + index = FindFile(icmp, files, small_key.Encode()); + } + + if (index >= files.size()) { + // beginning of range is after all files, so no overlap. + return false; + } + + return !BeforeFile(ucmp, largest_user_key, files[index]); +} + +// An internal iterator. For a given version/level pair, yields +// information about the files in the level. For a given entry, key() +// is the largest key that occurs in the file, and value() is an +// 16-byte value containing the file number and file size, both +// encoded using EncodeFixed64. +class Version::LevelFileNumIterator : public Iterator { + public: + LevelFileNumIterator(const InternalKeyComparator& icmp, + const std::vector* flist) + : icmp_(icmp), flist_(flist), index_(flist->size()) { // Marks as invalid + } + virtual bool Valid() const { return index_ < flist_->size(); } + virtual void Seek(const Slice& target) { + index_ = FindFile(icmp_, *flist_, target); + } + virtual void SeekToFirst() { index_ = 0; } + virtual void SeekToLast() { + index_ = flist_->empty() ? 0 : flist_->size() - 1; + } + virtual void Next() { + assert(Valid()); + index_++; + } + virtual void Prev() { + assert(Valid()); + if (index_ == 0) { + index_ = flist_->size(); // Marks as invalid + } else { + index_--; + } + } + Slice key() const { + assert(Valid()); + return (*flist_)[index_]->largest.Encode(); + } + Slice value() const { + assert(Valid()); + EncodeFixed64(value_buf_, (*flist_)[index_]->number); + EncodeFixed64(value_buf_ + 8, (*flist_)[index_]->file_size); + return Slice(value_buf_, sizeof(value_buf_)); + } + virtual Status status() const { return Status::OK(); } + + private: + const InternalKeyComparator icmp_; + const std::vector* const flist_; + uint32_t index_; + + // Backing store for value(). Holds the file number and size. + mutable char value_buf_[16]; +}; + +static Iterator* GetFileIterator(void* arg, const ReadOptions& options, + const Slice& file_value) { + TableCache* cache = reinterpret_cast(arg); + if (file_value.size() != 16) { + return NewErrorIterator( + Status::Corruption("FileReader invoked with unexpected value")); + } else { + return cache->NewIterator(options, DecodeFixed64(file_value.data()), + DecodeFixed64(file_value.data() + 8)); + } +} + +Iterator* Version::NewConcatenatingIterator(const ReadOptions& options, + int level) const { + return NewTwoLevelIterator( + new LevelFileNumIterator(vset_->icmp_, &files_[level]), &GetFileIterator, + vset_->table_cache_, options); +} + +void Version::AddIterators(const ReadOptions& options, + std::vector* iters) { + // Merge all level zero files together since they may overlap + for (size_t i = 0; i < files_[0].size(); i++) { + iters->push_back(vset_->table_cache_->NewIterator( + options, files_[0][i]->number, files_[0][i]->file_size)); + } + + // For levels > 0, we can use a concatenating iterator that sequentially + // walks through the non-overlapping files in the level, opening them + // lazily. + for (int level = 1; level < config::kNumLevels; level++) { + if (!files_[level].empty()) { + iters->push_back(NewConcatenatingIterator(options, level)); + } + } +} + +// Callback from TableCache::Get() +namespace { +enum SaverState { + kNotFound, + kFound, + kDeleted, + kCorrupt, +}; +struct Saver { + SaverState state; + const Comparator* ucmp; + Slice user_key; + std::string* value; +}; +} // namespace +static void SaveValue(void* arg, const Slice& ikey, const Slice& v) { + Saver* s = reinterpret_cast(arg); + ParsedInternalKey parsed_key; + if (!ParseInternalKey(ikey, &parsed_key)) { + s->state = kCorrupt; + } else { + if (s->ucmp->Compare(parsed_key.user_key, s->user_key) == 0) { + s->state = (parsed_key.type == kTypeValue) ? kFound : kDeleted; + if (s->state == kFound) { + s->value->assign(v.data(), v.size()); + } + } + } +} + +static bool NewestFirst(FileMetaData* a, FileMetaData* b) { + return a->number > b->number; +} + +void Version::ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)) { + // TODO(sanjay): Change Version::Get() to use this function. + const Comparator* ucmp = vset_->icmp_.user_comparator(); + + // Search level-0 in order from newest to oldest. + std::vector tmp; + tmp.reserve(files_[0].size()); + for (uint32_t i = 0; i < files_[0].size(); i++) { + FileMetaData* f = files_[0][i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (!tmp.empty()) { + std::sort(tmp.begin(), tmp.end(), NewestFirst); + for (uint32_t i = 0; i < tmp.size(); i++) { + if (!(*func)(arg, 0, tmp[i])) { + return; + } + } + } + + // Search other levels. + for (int level = 1; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Binary search to find earliest index whose largest key >= internal_key. + uint32_t index = FindFile(vset_->icmp_, files_[level], internal_key); + if (index < num_files) { + FileMetaData* f = files_[level][index]; + if (ucmp->Compare(user_key, f->smallest.user_key()) < 0) { + // All of "f" is past any data for user_key + } else { + if (!(*func)(arg, level, f)) { + return; + } + } + } + } +} + +Status Version::Get(const ReadOptions& options, const LookupKey& k, + std::string* value, GetStats* stats) { + Slice ikey = k.internal_key(); + Slice user_key = k.user_key(); + const Comparator* ucmp = vset_->icmp_.user_comparator(); + Status s; + + stats->seek_file = nullptr; + stats->seek_file_level = -1; + FileMetaData* last_file_read = nullptr; + int last_file_read_level = -1; + + // We can search level-by-level since entries never hop across + // levels. Therefore we are guaranteed that if we find data + // in a smaller level, later levels are irrelevant. + std::vector tmp; + FileMetaData* tmp2; + for (int level = 0; level < config::kNumLevels; level++) { + size_t num_files = files_[level].size(); + if (num_files == 0) continue; + + // Get the list of files to search in this level + FileMetaData* const* files = &files_[level][0]; + if (level == 0) { + // Level-0 files may overlap each other. Find all files that + // overlap user_key and process them in order from newest to oldest. + tmp.reserve(num_files); + for (uint32_t i = 0; i < num_files; i++) { + FileMetaData* f = files[i]; + if (ucmp->Compare(user_key, f->smallest.user_key()) >= 0 && + ucmp->Compare(user_key, f->largest.user_key()) <= 0) { + tmp.push_back(f); + } + } + if (tmp.empty()) continue; + + std::sort(tmp.begin(), tmp.end(), NewestFirst); + files = &tmp[0]; + num_files = tmp.size(); + } else { + // Binary search to find earliest index whose largest key >= ikey. + uint32_t index = FindFile(vset_->icmp_, files_[level], ikey); + if (index >= num_files) { + files = nullptr; + num_files = 0; + } else { + tmp2 = files[index]; + if (ucmp->Compare(user_key, tmp2->smallest.user_key()) < 0) { + // All of "tmp2" is past any data for user_key + files = nullptr; + num_files = 0; + } else { + files = &tmp2; + num_files = 1; + } + } + } + + for (uint32_t i = 0; i < num_files; ++i) { + if (last_file_read != nullptr && stats->seek_file == nullptr) { + // We have had more than one seek for this read. Charge the 1st file. + stats->seek_file = last_file_read; + stats->seek_file_level = last_file_read_level; + } + + FileMetaData* f = files[i]; + last_file_read = f; + last_file_read_level = level; + + Saver saver; + saver.state = kNotFound; + saver.ucmp = ucmp; + saver.user_key = user_key; + saver.value = value; + s = vset_->table_cache_->Get(options, f->number, f->file_size, ikey, + &saver, SaveValue); + if (!s.ok()) { + return s; + } + switch (saver.state) { + case kNotFound: + break; // Keep searching in other files + case kFound: + return s; + case kDeleted: + s = Status::NotFound(Slice()); // Use empty error message for speed + return s; + case kCorrupt: + s = Status::Corruption("corrupted key for ", user_key); + return s; + } + } + } + + return Status::NotFound(Slice()); // Use an empty error message for speed +} + +bool Version::UpdateStats(const GetStats& stats) { + FileMetaData* f = stats.seek_file; + if (f != nullptr) { + f->allowed_seeks--; + if (f->allowed_seeks <= 0 && file_to_compact_ == nullptr) { + file_to_compact_ = f; + file_to_compact_level_ = stats.seek_file_level; + return true; + } + } + return false; +} + +bool Version::RecordReadSample(Slice internal_key) { + ParsedInternalKey ikey; + if (!ParseInternalKey(internal_key, &ikey)) { + return false; + } + + struct State { + GetStats stats; // Holds first matching file + int matches; + + static bool Match(void* arg, int level, FileMetaData* f) { + State* state = reinterpret_cast(arg); + state->matches++; + if (state->matches == 1) { + // Remember first match. + state->stats.seek_file = f; + state->stats.seek_file_level = level; + } + // We can stop iterating once we have a second match. + return state->matches < 2; + } + }; + + State state; + state.matches = 0; + ForEachOverlapping(ikey.user_key, internal_key, &state, &State::Match); + + // Must have at least two matches since we want to merge across + // files. But what if we have a single file that contains many + // overwrites and deletions? Should we have another mechanism for + // finding such files? + if (state.matches >= 2) { + // 1MB cost is about 1 seek (see comment in Builder::Apply). + return UpdateStats(state.stats); + } + return false; +} + +void Version::Ref() { ++refs_; } + +void Version::Unref() { + assert(this != &vset_->dummy_versions_); + assert(refs_ >= 1); + --refs_; + if (refs_ == 0) { + delete this; + } +} + +bool Version::OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key) { + return SomeFileOverlapsRange(vset_->icmp_, (level > 0), files_[level], + smallest_user_key, largest_user_key); +} + +int Version::PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key) { + int level = 0; + if (!OverlapInLevel(0, &smallest_user_key, &largest_user_key)) { + // Push to next level if there is no overlap in next level, + // and the #bytes overlapping in the level after that are limited. + InternalKey start(smallest_user_key, kMaxSequenceNumber, kValueTypeForSeek); + InternalKey limit(largest_user_key, 0, static_cast(0)); + std::vector overlaps; + while (level < config::kMaxMemCompactLevel) { + if (OverlapInLevel(level + 1, &smallest_user_key, &largest_user_key)) { + break; + } + if (level + 2 < config::kNumLevels) { + // Check that file does not overlap too many grandparent bytes. + GetOverlappingInputs(level + 2, &start, &limit, &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > MaxGrandParentOverlapBytes(vset_->options_)) { + break; + } + } + level++; + } + } + return level; +} + +// Store in "*inputs" all files in "level" that overlap [begin,end] +void Version::GetOverlappingInputs(int level, const InternalKey* begin, + const InternalKey* end, + std::vector* inputs) { + assert(level >= 0); + assert(level < config::kNumLevels); + inputs->clear(); + Slice user_begin, user_end; + if (begin != nullptr) { + user_begin = begin->user_key(); + } + if (end != nullptr) { + user_end = end->user_key(); + } + const Comparator* user_cmp = vset_->icmp_.user_comparator(); + for (size_t i = 0; i < files_[level].size();) { + FileMetaData* f = files_[level][i++]; + const Slice file_start = f->smallest.user_key(); + const Slice file_limit = f->largest.user_key(); + if (begin != nullptr && user_cmp->Compare(file_limit, user_begin) < 0) { + // "f" is completely before specified range; skip it + } else if (end != nullptr && user_cmp->Compare(file_start, user_end) > 0) { + // "f" is completely after specified range; skip it + } else { + inputs->push_back(f); + if (level == 0) { + // Level-0 files may overlap each other. So check if the newly + // added file has expanded the range. If so, restart search. + if (begin != nullptr && user_cmp->Compare(file_start, user_begin) < 0) { + user_begin = file_start; + inputs->clear(); + i = 0; + } else if (end != nullptr && + user_cmp->Compare(file_limit, user_end) > 0) { + user_end = file_limit; + inputs->clear(); + i = 0; + } + } + } + } +} + +std::string Version::DebugString() const { + std::string r; + for (int level = 0; level < config::kNumLevels; level++) { + // E.g., + // --- level 1 --- + // 17:123['a' .. 'd'] + // 20:43['e' .. 'g'] + r.append("--- level "); + AppendNumberTo(&r, level); + r.append(" ---\n"); + const std::vector& files = files_[level]; + for (size_t i = 0; i < files.size(); i++) { + r.push_back(' '); + AppendNumberTo(&r, files[i]->number); + r.push_back(':'); + AppendNumberTo(&r, files[i]->file_size); + r.append("["); + r.append(files[i]->smallest.DebugString()); + r.append(" .. "); + r.append(files[i]->largest.DebugString()); + r.append("]\n"); + } + } + return r; +} + +// A helper class so we can efficiently apply a whole sequence +// of edits to a particular state without creating intermediate +// Versions that contain full copies of the intermediate state. +class VersionSet::Builder { + private: + // Helper to sort by v->files_[file_number].smallest + struct BySmallestKey { + const InternalKeyComparator* internal_comparator; + + bool operator()(FileMetaData* f1, FileMetaData* f2) const { + int r = internal_comparator->Compare(f1->smallest, f2->smallest); + if (r != 0) { + return (r < 0); + } else { + // Break ties by file number + return (f1->number < f2->number); + } + } + }; + + typedef std::set FileSet; + struct LevelState { + std::set deleted_files; + FileSet* added_files; + }; + + VersionSet* vset_; + Version* base_; + LevelState levels_[config::kNumLevels]; + + public: + // Initialize a builder with the files from *base and other info from *vset + Builder(VersionSet* vset, Version* base) : vset_(vset), base_(base) { + base_->Ref(); + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + levels_[level].added_files = new FileSet(cmp); + } + } + + ~Builder() { + for (int level = 0; level < config::kNumLevels; level++) { + const FileSet* added = levels_[level].added_files; + std::vector to_unref; + to_unref.reserve(added->size()); + for (FileSet::const_iterator it = added->begin(); it != added->end(); + ++it) { + to_unref.push_back(*it); + } + delete added; + for (uint32_t i = 0; i < to_unref.size(); i++) { + FileMetaData* f = to_unref[i]; + f->refs--; + if (f->refs <= 0) { + delete f; + } + } + } + base_->Unref(); + } + + // Apply all of the edits in *edit to the current state. + void Apply(VersionEdit* edit) { + // Update compaction pointers + for (size_t i = 0; i < edit->compact_pointers_.size(); i++) { + const int level = edit->compact_pointers_[i].first; + vset_->compact_pointer_[level] = + edit->compact_pointers_[i].second.Encode().ToString(); + } + + // Delete files + const VersionEdit::DeletedFileSet& del = edit->deleted_files_; + for (VersionEdit::DeletedFileSet::const_iterator iter = del.begin(); + iter != del.end(); ++iter) { + const int level = iter->first; + const uint64_t number = iter->second; + levels_[level].deleted_files.insert(number); + } + + // Add new files + for (size_t i = 0; i < edit->new_files_.size(); i++) { + const int level = edit->new_files_[i].first; + FileMetaData* f = new FileMetaData(edit->new_files_[i].second); + f->refs = 1; + + // We arrange to automatically compact this file after + // a certain number of seeks. Let's assume: + // (1) One seek costs 10ms + // (2) Writing or reading 1MB costs 10ms (100MB/s) + // (3) A compaction of 1MB does 25MB of IO: + // 1MB read from this level + // 10-12MB read from next level (boundaries may be misaligned) + // 10-12MB written to next level + // This implies that 25 seeks cost the same as the compaction + // of 1MB of data. I.e., one seek costs approximately the + // same as the compaction of 40KB of data. We are a little + // conservative and allow approximately one seek for every 16KB + // of data before triggering a compaction. + f->allowed_seeks = static_cast((f->file_size / 16384U)); + if (f->allowed_seeks < 100) f->allowed_seeks = 100; + + levels_[level].deleted_files.erase(f->number); + levels_[level].added_files->insert(f); + } + } + + // Save the current state in *v. + void SaveTo(Version* v) { + BySmallestKey cmp; + cmp.internal_comparator = &vset_->icmp_; + for (int level = 0; level < config::kNumLevels; level++) { + // Merge the set of added files with the set of pre-existing files. + // Drop any deleted files. Store the result in *v. + const std::vector& base_files = base_->files_[level]; + std::vector::const_iterator base_iter = base_files.begin(); + std::vector::const_iterator base_end = base_files.end(); + const FileSet* added = levels_[level].added_files; + v->files_[level].reserve(base_files.size() + added->size()); + for (FileSet::const_iterator added_iter = added->begin(); + added_iter != added->end(); ++added_iter) { + // Add all smaller files listed in base_ + for (std::vector::const_iterator bpos = + std::upper_bound(base_iter, base_end, *added_iter, cmp); + base_iter != bpos; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + + MaybeAddFile(v, level, *added_iter); + } + + // Add remaining base files + for (; base_iter != base_end; ++base_iter) { + MaybeAddFile(v, level, *base_iter); + } + +#ifndef NDEBUG + // Make sure there is no overlap in levels > 0 + if (level > 0) { + for (uint32_t i = 1; i < v->files_[level].size(); i++) { + const InternalKey& prev_end = v->files_[level][i - 1]->largest; + const InternalKey& this_begin = v->files_[level][i]->smallest; + if (vset_->icmp_.Compare(prev_end, this_begin) >= 0) { + fprintf(stderr, "overlapping ranges in same level %s vs. %s\n", + prev_end.DebugString().c_str(), + this_begin.DebugString().c_str()); + abort(); + } + } + } +#endif + } + } + + void MaybeAddFile(Version* v, int level, FileMetaData* f) { + if (levels_[level].deleted_files.count(f->number) > 0) { + // File is deleted: do nothing + } else { + std::vector* files = &v->files_[level]; + if (level > 0 && !files->empty()) { + // Must not overlap + assert(vset_->icmp_.Compare((*files)[files->size() - 1]->largest, + f->smallest) < 0); + } + f->refs++; + files->push_back(f); + } + } +}; + +VersionSet::VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, + const InternalKeyComparator* cmp) + : env_(options->env), + dbname_(dbname), + options_(options), + table_cache_(table_cache), + icmp_(*cmp), + next_file_number_(2), + manifest_file_number_(0), // Filled by Recover() + last_sequence_(0), + log_number_(0), + prev_log_number_(0), + descriptor_file_(nullptr), + descriptor_log_(nullptr), + dummy_versions_(this), + current_(nullptr) { + AppendVersion(new Version(this)); +} + +VersionSet::~VersionSet() { + current_->Unref(); + assert(dummy_versions_.next_ == &dummy_versions_); // List must be empty + delete descriptor_log_; + delete descriptor_file_; +} + +void VersionSet::AppendVersion(Version* v) { + // Make "v" current + assert(v->refs_ == 0); + assert(v != current_); + if (current_ != nullptr) { + current_->Unref(); + } + current_ = v; + v->Ref(); + + // Append to linked list + v->prev_ = dummy_versions_.prev_; + v->next_ = &dummy_versions_; + v->prev_->next_ = v; + v->next_->prev_ = v; +} + +Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) { + if (edit->has_log_number_) { + assert(edit->log_number_ >= log_number_); + assert(edit->log_number_ < next_file_number_); + } else { + edit->SetLogNumber(log_number_); + } + + if (!edit->has_prev_log_number_) { + edit->SetPrevLogNumber(prev_log_number_); + } + + edit->SetNextFile(next_file_number_); + edit->SetLastSequence(last_sequence_); + + Version* v = new Version(this); + { + Builder builder(this, current_); + builder.Apply(edit); + builder.SaveTo(v); + } + Finalize(v); + + // Initialize new descriptor log file if necessary by creating + // a temporary file that contains a snapshot of the current version. + std::string new_manifest_file; + Status s; + if (descriptor_log_ == nullptr) { + // No reason to unlock *mu here since we only hit this path in the + // first call to LogAndApply (when opening the database). + assert(descriptor_file_ == nullptr); + new_manifest_file = DescriptorFileName(dbname_, manifest_file_number_); + edit->SetNextFile(next_file_number_); + s = env_->NewWritableFile(new_manifest_file, &descriptor_file_); + if (s.ok()) { + descriptor_log_ = new log::Writer(descriptor_file_); + s = WriteSnapshot(descriptor_log_); + } + } + + // Unlock during expensive MANIFEST log write + { + mu->Unlock(); + + // Write new record to MANIFEST log + if (s.ok()) { + std::string record; + edit->EncodeTo(&record); + s = descriptor_log_->AddRecord(record); + if (s.ok()) { + s = descriptor_file_->Sync(); + } + if (!s.ok()) { + Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str()); + } + } + + // If we just created a new descriptor file, install it by writing a + // new CURRENT file that points to it. + if (s.ok() && !new_manifest_file.empty()) { + s = SetCurrentFile(env_, dbname_, manifest_file_number_); + } + + mu->Lock(); + } + + // Install the new version + if (s.ok()) { + AppendVersion(v); + log_number_ = edit->log_number_; + prev_log_number_ = edit->prev_log_number_; + } else { + delete v; + if (!new_manifest_file.empty()) { + delete descriptor_log_; + delete descriptor_file_; + descriptor_log_ = nullptr; + descriptor_file_ = nullptr; + env_->DeleteFile(new_manifest_file); + } + } + + return s; +} + +Status VersionSet::Recover(bool* save_manifest) { + struct LogReporter : public log::Reader::Reporter { + Status* status; + virtual void Corruption(size_t bytes, const Status& s) { + if (this->status->ok()) *this->status = s; + } + }; + + // Read "CURRENT" file, which contains a pointer to the current manifest file + std::string current; + Status s = ReadFileToString(env_, CurrentFileName(dbname_), ¤t); + if (!s.ok()) { + return s; + } + if (current.empty() || current[current.size() - 1] != '\n') { + return Status::Corruption("CURRENT file does not end with newline"); + } + current.resize(current.size() - 1); + + std::string dscname = dbname_ + "/" + current; + SequentialFile* file; + s = env_->NewSequentialFile(dscname, &file); + if (!s.ok()) { + if (s.IsNotFound()) { + return Status::Corruption("CURRENT points to a non-existent file", + s.ToString()); + } + return s; + } + + bool have_log_number = false; + bool have_prev_log_number = false; + bool have_next_file = false; + bool have_last_sequence = false; + uint64_t next_file = 0; + uint64_t last_sequence = 0; + uint64_t log_number = 0; + uint64_t prev_log_number = 0; + Builder builder(this, current_); + + { + LogReporter reporter; + reporter.status = &s; + log::Reader reader(file, &reporter, true /*checksum*/, + 0 /*initial_offset*/); + Slice record; + std::string scratch; + while (reader.ReadRecord(&record, &scratch) && s.ok()) { + VersionEdit edit; + s = edit.DecodeFrom(record); + if (s.ok()) { + if (edit.has_comparator_ && + edit.comparator_ != icmp_.user_comparator()->Name()) { + s = Status::InvalidArgument( + edit.comparator_ + " does not match existing comparator ", + icmp_.user_comparator()->Name()); + } + } + + if (s.ok()) { + builder.Apply(&edit); + } + + if (edit.has_log_number_) { + log_number = edit.log_number_; + have_log_number = true; + } + + if (edit.has_prev_log_number_) { + prev_log_number = edit.prev_log_number_; + have_prev_log_number = true; + } + + if (edit.has_next_file_number_) { + next_file = edit.next_file_number_; + have_next_file = true; + } + + if (edit.has_last_sequence_) { + last_sequence = edit.last_sequence_; + have_last_sequence = true; + } + } + } + delete file; + file = nullptr; + + if (s.ok()) { + if (!have_next_file) { + s = Status::Corruption("no meta-nextfile entry in descriptor"); + } else if (!have_log_number) { + s = Status::Corruption("no meta-lognumber entry in descriptor"); + } else if (!have_last_sequence) { + s = Status::Corruption("no last-sequence-number entry in descriptor"); + } + + if (!have_prev_log_number) { + prev_log_number = 0; + } + + MarkFileNumberUsed(prev_log_number); + MarkFileNumberUsed(log_number); + } + + if (s.ok()) { + Version* v = new Version(this); + builder.SaveTo(v); + // Install recovered version + Finalize(v); + AppendVersion(v); + manifest_file_number_ = next_file; + next_file_number_ = next_file + 1; + last_sequence_ = last_sequence; + log_number_ = log_number; + prev_log_number_ = prev_log_number; + + // See if we can reuse the existing MANIFEST file. + if (ReuseManifest(dscname, current)) { + // No need to save new manifest + } else { + *save_manifest = true; + } + } + + return s; +} + +bool VersionSet::ReuseManifest(const std::string& dscname, + const std::string& dscbase) { + if (!options_->reuse_logs) { + return false; + } + FileType manifest_type; + uint64_t manifest_number; + uint64_t manifest_size; + if (!ParseFileName(dscbase, &manifest_number, &manifest_type) || + manifest_type != kDescriptorFile || + !env_->GetFileSize(dscname, &manifest_size).ok() || + // Make new compacted MANIFEST if old one is too big + manifest_size >= TargetFileSize(options_)) { + return false; + } + + assert(descriptor_file_ == nullptr); + assert(descriptor_log_ == nullptr); + Status r = env_->NewAppendableFile(dscname, &descriptor_file_); + if (!r.ok()) { + Log(options_->info_log, "Reuse MANIFEST: %s\n", r.ToString().c_str()); + assert(descriptor_file_ == nullptr); + return false; + } + + Log(options_->info_log, "Reusing MANIFEST %s\n", dscname.c_str()); + descriptor_log_ = new log::Writer(descriptor_file_, manifest_size); + manifest_file_number_ = manifest_number; + return true; +} + +void VersionSet::MarkFileNumberUsed(uint64_t number) { + if (next_file_number_ <= number) { + next_file_number_ = number + 1; + } +} + +void VersionSet::Finalize(Version* v) { + // Precomputed best level for next compaction + int best_level = -1; + double best_score = -1; + + for (int level = 0; level < config::kNumLevels - 1; level++) { + double score; + if (level == 0) { + // We treat level-0 specially by bounding the number of files + // instead of number of bytes for two reasons: + // + // (1) With larger write-buffer sizes, it is nice not to do too + // many level-0 compactions. + // + // (2) The files in level-0 are merged on every read and + // therefore we wish to avoid too many files when the individual + // file size is small (perhaps because of a small write-buffer + // setting, or very high compression ratios, or lots of + // overwrites/deletions). + score = v->files_[level].size() / + static_cast(config::kL0_CompactionTrigger); + } else { + // Compute the ratio of current size to size limit. + const uint64_t level_bytes = TotalFileSize(v->files_[level]); + score = + static_cast(level_bytes) / MaxBytesForLevel(options_, level); + } + + if (score > best_score) { + best_level = level; + best_score = score; + } + } + + v->compaction_level_ = best_level; + v->compaction_score_ = best_score; +} + +Status VersionSet::WriteSnapshot(log::Writer* log) { + // TODO: Break up into multiple records to reduce memory usage on recovery? + + // Save metadata + VersionEdit edit; + edit.SetComparatorName(icmp_.user_comparator()->Name()); + + // Save compaction pointers + for (int level = 0; level < config::kNumLevels; level++) { + if (!compact_pointer_[level].empty()) { + InternalKey key; + key.DecodeFrom(compact_pointer_[level]); + edit.SetCompactPointer(level, key); + } + } + + // Save files + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = current_->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + const FileMetaData* f = files[i]; + edit.AddFile(level, f->number, f->file_size, f->smallest, f->largest); + } + } + + std::string record; + edit.EncodeTo(&record); + return log->AddRecord(record); +} + +int VersionSet::NumLevelFiles(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return current_->files_[level].size(); +} + +const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const { + // Update code if kNumLevels changes + static_assert(config::kNumLevels == 7, ""); + snprintf(scratch->buffer, sizeof(scratch->buffer), + "files[ %d %d %d %d %d %d %d ]", int(current_->files_[0].size()), + int(current_->files_[1].size()), int(current_->files_[2].size()), + int(current_->files_[3].size()), int(current_->files_[4].size()), + int(current_->files_[5].size()), int(current_->files_[6].size())); + return scratch->buffer; +} + +uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) { + uint64_t result = 0; + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + if (icmp_.Compare(files[i]->largest, ikey) <= 0) { + // Entire file is before "ikey", so just add the file size + result += files[i]->file_size; + } else if (icmp_.Compare(files[i]->smallest, ikey) > 0) { + // Entire file is after "ikey", so ignore + if (level > 0) { + // Files other than level 0 are sorted by meta->smallest, so + // no further files in this level will contain data for + // "ikey". + break; + } + } else { + // "ikey" falls in the range for this table. Add the + // approximate offset of "ikey" within the table. + Table* tableptr; + Iterator* iter = table_cache_->NewIterator( + ReadOptions(), files[i]->number, files[i]->file_size, &tableptr); + if (tableptr != nullptr) { + result += tableptr->ApproximateOffsetOf(ikey.Encode()); + } + delete iter; + } + } + } + return result; +} + +void VersionSet::AddLiveFiles(std::set* live) { + for (Version* v = dummy_versions_.next_; v != &dummy_versions_; + v = v->next_) { + for (int level = 0; level < config::kNumLevels; level++) { + const std::vector& files = v->files_[level]; + for (size_t i = 0; i < files.size(); i++) { + live->insert(files[i]->number); + } + } + } +} + +int64_t VersionSet::NumLevelBytes(int level) const { + assert(level >= 0); + assert(level < config::kNumLevels); + return TotalFileSize(current_->files_[level]); +} + +int64_t VersionSet::MaxNextLevelOverlappingBytes() { + int64_t result = 0; + std::vector overlaps; + for (int level = 1; level < config::kNumLevels - 1; level++) { + for (size_t i = 0; i < current_->files_[level].size(); i++) { + const FileMetaData* f = current_->files_[level][i]; + current_->GetOverlappingInputs(level + 1, &f->smallest, &f->largest, + &overlaps); + const int64_t sum = TotalFileSize(overlaps); + if (sum > result) { + result = sum; + } + } + } + return result; +} + +// Stores the minimal range that covers all entries in inputs in +// *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange(const std::vector& inputs, + InternalKey* smallest, InternalKey* largest) { + assert(!inputs.empty()); + smallest->Clear(); + largest->Clear(); + for (size_t i = 0; i < inputs.size(); i++) { + FileMetaData* f = inputs[i]; + if (i == 0) { + *smallest = f->smallest; + *largest = f->largest; + } else { + if (icmp_.Compare(f->smallest, *smallest) < 0) { + *smallest = f->smallest; + } + if (icmp_.Compare(f->largest, *largest) > 0) { + *largest = f->largest; + } + } + } +} + +// Stores the minimal range that covers all entries in inputs1 and inputs2 +// in *smallest, *largest. +// REQUIRES: inputs is not empty +void VersionSet::GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest) { + std::vector all = inputs1; + all.insert(all.end(), inputs2.begin(), inputs2.end()); + GetRange(all, smallest, largest); +} + +Iterator* VersionSet::MakeInputIterator(Compaction* c) { + ReadOptions options; + options.verify_checksums = options_->paranoid_checks; + options.fill_cache = false; + + // Level-0 files have to be merged together. For other levels, + // we will make a concatenating iterator per level. + // TODO(opt): use concatenating iterator for level-0 if there is no overlap + const int space = (c->level() == 0 ? c->inputs_[0].size() + 1 : 2); + Iterator** list = new Iterator*[space]; + int num = 0; + for (int which = 0; which < 2; which++) { + if (!c->inputs_[which].empty()) { + if (c->level() + which == 0) { + const std::vector& files = c->inputs_[which]; + for (size_t i = 0; i < files.size(); i++) { + list[num++] = table_cache_->NewIterator(options, files[i]->number, + files[i]->file_size); + } + } else { + // Create concatenating iterator for the files from this level + list[num++] = NewTwoLevelIterator( + new Version::LevelFileNumIterator(icmp_, &c->inputs_[which]), + &GetFileIterator, table_cache_, options); + } + } + } + assert(num <= space); + Iterator* result = NewMergingIterator(&icmp_, list, num); + delete[] list; + return result; +} + +Compaction* VersionSet::PickCompaction() { + Compaction* c; + int level; + + // We prefer compactions triggered by too much data in a level over + // the compactions triggered by seeks. + const bool size_compaction = (current_->compaction_score_ >= 1); + const bool seek_compaction = (current_->file_to_compact_ != nullptr); + if (size_compaction) { + level = current_->compaction_level_; + assert(level >= 0); + assert(level + 1 < config::kNumLevels); + c = new Compaction(options_, level); + + // Pick the first file that comes after compact_pointer_[level] + for (size_t i = 0; i < current_->files_[level].size(); i++) { + FileMetaData* f = current_->files_[level][i]; + if (compact_pointer_[level].empty() || + icmp_.Compare(f->largest.Encode(), compact_pointer_[level]) > 0) { + c->inputs_[0].push_back(f); + break; + } + } + if (c->inputs_[0].empty()) { + // Wrap-around to the beginning of the key space + c->inputs_[0].push_back(current_->files_[level][0]); + } + } else if (seek_compaction) { + level = current_->file_to_compact_level_; + c = new Compaction(options_, level); + c->inputs_[0].push_back(current_->file_to_compact_); + } else { + return nullptr; + } + + c->input_version_ = current_; + c->input_version_->Ref(); + + // Files in level 0 may overlap each other, so pick up all overlapping ones + if (level == 0) { + InternalKey smallest, largest; + GetRange(c->inputs_[0], &smallest, &largest); + // Note that the next call will discard the file we placed in + // c->inputs_[0] earlier and replace it with an overlapping set + // which will include the picked file. + current_->GetOverlappingInputs(0, &smallest, &largest, &c->inputs_[0]); + assert(!c->inputs_[0].empty()); + } + + SetupOtherInputs(c); + + return c; +} + +// Finds the largest key in a vector of files. Returns true if files it not +// empty. +bool FindLargestKey(const InternalKeyComparator& icmp, + const std::vector& files, + InternalKey* largest_key) { + if (files.empty()) { + return false; + } + *largest_key = files[0]->largest; + for (size_t i = 1; i < files.size(); ++i) { + FileMetaData* f = files[i]; + if (icmp.Compare(f->largest, *largest_key) > 0) { + *largest_key = f->largest; + } + } + return true; +} + +// Finds minimum file b2=(l2, u2) in level file for which l2 > u1 and +// user_key(l2) = user_key(u1) +FileMetaData* FindSmallestBoundaryFile( + const InternalKeyComparator& icmp, + const std::vector& level_files, + const InternalKey& largest_key) { + const Comparator* user_cmp = icmp.user_comparator(); + FileMetaData* smallest_boundary_file = nullptr; + for (size_t i = 0; i < level_files.size(); ++i) { + FileMetaData* f = level_files[i]; + if (icmp.Compare(f->smallest, largest_key) > 0 && + user_cmp->Compare(f->smallest.user_key(), largest_key.user_key()) == + 0) { + if (smallest_boundary_file == nullptr || + icmp.Compare(f->smallest, smallest_boundary_file->smallest) < 0) { + smallest_boundary_file = f; + } + } + } + return smallest_boundary_file; +} + +// Extracts the largest file b1 from |compaction_files| and then searches for a +// b2 in |level_files| for which user_key(u1) = user_key(l2). If it finds such a +// file b2 (known as a boundary file) it adds it to |compaction_files| and then +// searches again using this new upper bound. +// +// If there are two blocks, b1=(l1, u1) and b2=(l2, u2) and +// user_key(u1) = user_key(l2), and if we compact b1 but not b2 then a +// subsequent get operation will yield an incorrect result because it will +// return the record from b2 in level i rather than from b1 because it searches +// level by level for records matching the supplied user key. +// +// parameters: +// in level_files: List of files to search for boundary files. +// in/out compaction_files: List of files to extend by adding boundary files. +void AddBoundaryInputs(const InternalKeyComparator& icmp, + const std::vector& level_files, + std::vector* compaction_files) { + InternalKey largest_key; + + // Quick return if compaction_files is empty. + if (!FindLargestKey(icmp, *compaction_files, &largest_key)) { + return; + } + + bool continue_searching = true; + while (continue_searching) { + FileMetaData* smallest_boundary_file = + FindSmallestBoundaryFile(icmp, level_files, largest_key); + + // If a boundary file was found advance largest_key, otherwise we're done. + if (smallest_boundary_file != NULL) { + compaction_files->push_back(smallest_boundary_file); + largest_key = smallest_boundary_file->largest; + } else { + continue_searching = false; + } + } +} + +void VersionSet::SetupOtherInputs(Compaction* c) { + const int level = c->level(); + InternalKey smallest, largest; + + AddBoundaryInputs(icmp_, current_->files_[level], &c->inputs_[0]); + GetRange(c->inputs_[0], &smallest, &largest); + + current_->GetOverlappingInputs(level + 1, &smallest, &largest, + &c->inputs_[1]); + + // Get entire range covered by compaction + InternalKey all_start, all_limit; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + + // See if we can grow the number of inputs in "level" without + // changing the number of "level+1" files we pick up. + if (!c->inputs_[1].empty()) { + std::vector expanded0; + current_->GetOverlappingInputs(level, &all_start, &all_limit, &expanded0); + AddBoundaryInputs(icmp_, current_->files_[level], &expanded0); + const int64_t inputs0_size = TotalFileSize(c->inputs_[0]); + const int64_t inputs1_size = TotalFileSize(c->inputs_[1]); + const int64_t expanded0_size = TotalFileSize(expanded0); + if (expanded0.size() > c->inputs_[0].size() && + inputs1_size + expanded0_size < + ExpandedCompactionByteSizeLimit(options_)) { + InternalKey new_start, new_limit; + GetRange(expanded0, &new_start, &new_limit); + std::vector expanded1; + current_->GetOverlappingInputs(level + 1, &new_start, &new_limit, + &expanded1); + if (expanded1.size() == c->inputs_[1].size()) { + Log(options_->info_log, + "Expanding@%d %d+%d (%ld+%ld bytes) to %d+%d (%ld+%ld bytes)\n", + level, int(c->inputs_[0].size()), int(c->inputs_[1].size()), + long(inputs0_size), long(inputs1_size), int(expanded0.size()), + int(expanded1.size()), long(expanded0_size), long(inputs1_size)); + smallest = new_start; + largest = new_limit; + c->inputs_[0] = expanded0; + c->inputs_[1] = expanded1; + GetRange2(c->inputs_[0], c->inputs_[1], &all_start, &all_limit); + } + } + } + + // Compute the set of grandparent files that overlap this compaction + // (parent == level+1; grandparent == level+2) + if (level + 2 < config::kNumLevels) { + current_->GetOverlappingInputs(level + 2, &all_start, &all_limit, + &c->grandparents_); + } + + // Update the place where we will do the next compaction for this level. + // We update this immediately instead of waiting for the VersionEdit + // to be applied so that if the compaction fails, we will try a different + // key range next time. + compact_pointer_[level] = largest.Encode().ToString(); + c->edit_.SetCompactPointer(level, largest); +} + +Compaction* VersionSet::CompactRange(int level, const InternalKey* begin, + const InternalKey* end) { + std::vector inputs; + current_->GetOverlappingInputs(level, begin, end, &inputs); + if (inputs.empty()) { + return nullptr; + } + + // Avoid compacting too much in one shot in case the range is large. + // But we cannot do this for level-0 since level-0 files can overlap + // and we must not pick one file and drop another older file if the + // two files overlap. + if (level > 0) { + const uint64_t limit = MaxFileSizeForLevel(options_, level); + uint64_t total = 0; + for (size_t i = 0; i < inputs.size(); i++) { + uint64_t s = inputs[i]->file_size; + total += s; + if (total >= limit) { + inputs.resize(i + 1); + break; + } + } + } + + Compaction* c = new Compaction(options_, level); + c->input_version_ = current_; + c->input_version_->Ref(); + c->inputs_[0] = inputs; + SetupOtherInputs(c); + return c; +} + +Compaction::Compaction(const Options* options, int level) + : level_(level), + max_output_file_size_(MaxFileSizeForLevel(options, level)), + input_version_(nullptr), + grandparent_index_(0), + seen_key_(false), + overlapped_bytes_(0) { + for (int i = 0; i < config::kNumLevels; i++) { + level_ptrs_[i] = 0; + } +} + +Compaction::~Compaction() { + if (input_version_ != nullptr) { + input_version_->Unref(); + } +} + +bool Compaction::IsTrivialMove() const { + const VersionSet* vset = input_version_->vset_; + // Avoid a move if there is lots of overlapping grandparent data. + // Otherwise, the move could create a parent file that will require + // a very expensive merge later on. + return (num_input_files(0) == 1 && num_input_files(1) == 0 && + TotalFileSize(grandparents_) <= + MaxGrandParentOverlapBytes(vset->options_)); +} + +void Compaction::AddInputDeletions(VersionEdit* edit) { + for (int which = 0; which < 2; which++) { + for (size_t i = 0; i < inputs_[which].size(); i++) { + edit->DeleteFile(level_ + which, inputs_[which][i]->number); + } + } +} + +bool Compaction::IsBaseLevelForKey(const Slice& user_key) { + // Maybe use binary search to find right entry instead of linear search? + const Comparator* user_cmp = input_version_->vset_->icmp_.user_comparator(); + for (int lvl = level_ + 2; lvl < config::kNumLevels; lvl++) { + const std::vector& files = input_version_->files_[lvl]; + for (; level_ptrs_[lvl] < files.size();) { + FileMetaData* f = files[level_ptrs_[lvl]]; + if (user_cmp->Compare(user_key, f->largest.user_key()) <= 0) { + // We've advanced far enough + if (user_cmp->Compare(user_key, f->smallest.user_key()) >= 0) { + // Key falls in this file's range, so definitely not base level + return false; + } + break; + } + level_ptrs_[lvl]++; + } + } + return true; +} + +bool Compaction::ShouldStopBefore(const Slice& internal_key) { + const VersionSet* vset = input_version_->vset_; + // Scan to find earliest grandparent file that contains key. + const InternalKeyComparator* icmp = &vset->icmp_; + while (grandparent_index_ < grandparents_.size() && + icmp->Compare(internal_key, + grandparents_[grandparent_index_]->largest.Encode()) > + 0) { + if (seen_key_) { + overlapped_bytes_ += grandparents_[grandparent_index_]->file_size; + } + grandparent_index_++; + } + seen_key_ = true; + + if (overlapped_bytes_ > MaxGrandParentOverlapBytes(vset->options_)) { + // Too much overlap for current output; start new output + overlapped_bytes_ = 0; + return true; + } else { + return false; + } +} + +void Compaction::ReleaseInputs() { + if (input_version_ != nullptr) { + input_version_->Unref(); + input_version_ = nullptr; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.h new file mode 100644 index 0000000..69f3d70 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/version_set.h @@ -0,0 +1,393 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// The representation of a DBImpl consists of a set of Versions. The +// newest version is called "current". Older versions may be kept +// around to provide a consistent view to live iterators. +// +// Each Version keeps track of a set of Table files per level. The +// entire set of versions is maintained in a VersionSet. +// +// Version,VersionSet are thread-compatible, but require external +// synchronization on all accesses. + +#ifndef STORAGE_LEVELDB_DB_VERSION_SET_H_ +#define STORAGE_LEVELDB_DB_VERSION_SET_H_ + +#include +#include +#include + +#include "db/dbformat.h" +#include "db/version_edit.h" +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +namespace log { +class Writer; +} + +class Compaction; +class Iterator; +class MemTable; +class TableBuilder; +class TableCache; +class Version; +class VersionSet; +class WritableFile; + +// Return the smallest index i such that files[i]->largest >= key. +// Return files.size() if there is no such file. +// REQUIRES: "files" contains a sorted list of non-overlapping files. +int FindFile(const InternalKeyComparator& icmp, + const std::vector& files, const Slice& key); + +// Returns true iff some file in "files" overlaps the user key range +// [*smallest,*largest]. +// smallest==nullptr represents a key smaller than all keys in the DB. +// largest==nullptr represents a key largest than all keys in the DB. +// REQUIRES: If disjoint_sorted_files, files[] contains disjoint ranges +// in sorted order. +bool SomeFileOverlapsRange(const InternalKeyComparator& icmp, + bool disjoint_sorted_files, + const std::vector& files, + const Slice* smallest_user_key, + const Slice* largest_user_key); + +class Version { + public: + // Lookup the value for key. If found, store it in *val and + // return OK. Else return a non-OK status. Fills *stats. + // REQUIRES: lock is not held + struct GetStats { + FileMetaData* seek_file; + int seek_file_level; + }; + + // Append to *iters a sequence of iterators that will + // yield the contents of this Version when merged together. + // REQUIRES: This version has been saved (see VersionSet::SaveTo) + void AddIterators(const ReadOptions&, std::vector* iters); + + Status Get(const ReadOptions&, const LookupKey& key, std::string* val, + GetStats* stats); + + // Adds "stats" into the current state. Returns true if a new + // compaction may need to be triggered, false otherwise. + // REQUIRES: lock is held + bool UpdateStats(const GetStats& stats); + + // Record a sample of bytes read at the specified internal key. + // Samples are taken approximately once every config::kReadBytesPeriod + // bytes. Returns true if a new compaction may need to be triggered. + // REQUIRES: lock is held + bool RecordReadSample(Slice key); + + // Reference count management (so Versions do not disappear out from + // under live iterators) + void Ref(); + void Unref(); + + void GetOverlappingInputs( + int level, + const InternalKey* begin, // nullptr means before all keys + const InternalKey* end, // nullptr means after all keys + std::vector* inputs); + + // Returns true iff some file in the specified level overlaps + // some part of [*smallest_user_key,*largest_user_key]. + // smallest_user_key==nullptr represents a key smaller than all the DB's keys. + // largest_user_key==nullptr represents a key largest than all the DB's keys. + bool OverlapInLevel(int level, const Slice* smallest_user_key, + const Slice* largest_user_key); + + // Return the level at which we should place a new memtable compaction + // result that covers the range [smallest_user_key,largest_user_key]. + int PickLevelForMemTableOutput(const Slice& smallest_user_key, + const Slice& largest_user_key); + + int NumFiles(int level) const { return files_[level].size(); } + + // Return a human readable string that describes this version's contents. + std::string DebugString() const; + + private: + friend class Compaction; + friend class VersionSet; + + class LevelFileNumIterator; + + explicit Version(VersionSet* vset) + : vset_(vset), + next_(this), + prev_(this), + refs_(0), + file_to_compact_(nullptr), + file_to_compact_level_(-1), + compaction_score_(-1), + compaction_level_(-1) {} + + Version(const Version&) = delete; + Version& operator=(const Version&) = delete; + + ~Version(); + + Iterator* NewConcatenatingIterator(const ReadOptions&, int level) const; + + // Call func(arg, level, f) for every file that overlaps user_key in + // order from newest to oldest. If an invocation of func returns + // false, makes no more calls. + // + // REQUIRES: user portion of internal_key == user_key. + void ForEachOverlapping(Slice user_key, Slice internal_key, void* arg, + bool (*func)(void*, int, FileMetaData*)); + + VersionSet* vset_; // VersionSet to which this Version belongs + Version* next_; // Next version in linked list + Version* prev_; // Previous version in linked list + int refs_; // Number of live refs to this version + + // List of files per level + std::vector files_[config::kNumLevels]; + + // Next file to compact based on seek stats. + FileMetaData* file_to_compact_; + int file_to_compact_level_; + + // Level that should be compacted next and its compaction score. + // Score < 1 means compaction is not strictly needed. These fields + // are initialized by Finalize(). + double compaction_score_; + int compaction_level_; +}; + +class VersionSet { + public: + VersionSet(const std::string& dbname, const Options* options, + TableCache* table_cache, const InternalKeyComparator*); + VersionSet(const VersionSet&) = delete; + VersionSet& operator=(const VersionSet&) = delete; + + ~VersionSet(); + + // Apply *edit to the current version to form a new descriptor that + // is both saved to persistent state and installed as the new + // current version. Will release *mu while actually writing to the file. + // REQUIRES: *mu is held on entry. + // REQUIRES: no other thread concurrently calls LogAndApply() + Status LogAndApply(VersionEdit* edit, port::Mutex* mu) + EXCLUSIVE_LOCKS_REQUIRED(mu); + + // Recover the last saved descriptor from persistent storage. + Status Recover(bool* save_manifest); + + // Return the current version. + Version* current() const { return current_; } + + // Return the current manifest file number + uint64_t ManifestFileNumber() const { return manifest_file_number_; } + + // Allocate and return a new file number + uint64_t NewFileNumber() { return next_file_number_++; } + + // Arrange to reuse "file_number" unless a newer file number has + // already been allocated. + // REQUIRES: "file_number" was returned by a call to NewFileNumber(). + void ReuseFileNumber(uint64_t file_number) { + if (next_file_number_ == file_number + 1) { + next_file_number_ = file_number; + } + } + + // Return the number of Table files at the specified level. + int NumLevelFiles(int level) const; + + // Return the combined file size of all files at the specified level. + int64_t NumLevelBytes(int level) const; + + // Return the last sequence number. + uint64_t LastSequence() const { return last_sequence_; } + + // Set the last sequence number to s. + void SetLastSequence(uint64_t s) { + assert(s >= last_sequence_); + last_sequence_ = s; + } + + // Mark the specified file number as used. + void MarkFileNumberUsed(uint64_t number); + + // Return the current log file number. + uint64_t LogNumber() const { return log_number_; } + + // Return the log file number for the log file that is currently + // being compacted, or zero if there is no such log file. + uint64_t PrevLogNumber() const { return prev_log_number_; } + + // Pick level and inputs for a new compaction. + // Returns nullptr if there is no compaction to be done. + // Otherwise returns a pointer to a heap-allocated object that + // describes the compaction. Caller should delete the result. + Compaction* PickCompaction(); + + // Return a compaction object for compacting the range [begin,end] in + // the specified level. Returns nullptr if there is nothing in that + // level that overlaps the specified range. Caller should delete + // the result. + Compaction* CompactRange(int level, const InternalKey* begin, + const InternalKey* end); + + // Return the maximum overlapping data (in bytes) at next level for any + // file at a level >= 1. + int64_t MaxNextLevelOverlappingBytes(); + + // Create an iterator that reads over the compaction inputs for "*c". + // The caller should delete the iterator when no longer needed. + Iterator* MakeInputIterator(Compaction* c); + + // Returns true iff some level needs a compaction. + bool NeedsCompaction() const { + Version* v = current_; + return (v->compaction_score_ >= 1) || (v->file_to_compact_ != nullptr); + } + + // Add all files listed in any live version to *live. + // May also mutate some internal state. + void AddLiveFiles(std::set* live); + + // Return the approximate offset in the database of the data for + // "key" as of version "v". + uint64_t ApproximateOffsetOf(Version* v, const InternalKey& key); + + // Return a human-readable short (single-line) summary of the number + // of files per level. Uses *scratch as backing store. + struct LevelSummaryStorage { + char buffer[100]; + }; + const char* LevelSummary(LevelSummaryStorage* scratch) const; + + private: + class Builder; + + friend class Compaction; + friend class Version; + + bool ReuseManifest(const std::string& dscname, const std::string& dscbase); + + void Finalize(Version* v); + + void GetRange(const std::vector& inputs, InternalKey* smallest, + InternalKey* largest); + + void GetRange2(const std::vector& inputs1, + const std::vector& inputs2, + InternalKey* smallest, InternalKey* largest); + + void SetupOtherInputs(Compaction* c); + + // Save current contents to *log + Status WriteSnapshot(log::Writer* log); + + void AppendVersion(Version* v); + + Env* const env_; + const std::string dbname_; + const Options* const options_; + TableCache* const table_cache_; + const InternalKeyComparator icmp_; + uint64_t next_file_number_; + uint64_t manifest_file_number_; + uint64_t last_sequence_; + uint64_t log_number_; + uint64_t prev_log_number_; // 0 or backing store for memtable being compacted + + // Opened lazily + WritableFile* descriptor_file_; + log::Writer* descriptor_log_; + Version dummy_versions_; // Head of circular doubly-linked list of versions. + Version* current_; // == dummy_versions_.prev_ + + // Per-level key at which the next compaction at that level should start. + // Either an empty string, or a valid InternalKey. + std::string compact_pointer_[config::kNumLevels]; +}; + +// A Compaction encapsulates information about a compaction. +class Compaction { + public: + ~Compaction(); + + // Return the level that is being compacted. Inputs from "level" + // and "level+1" will be merged to produce a set of "level+1" files. + int level() const { return level_; } + + // Return the object that holds the edits to the descriptor done + // by this compaction. + VersionEdit* edit() { return &edit_; } + + // "which" must be either 0 or 1 + int num_input_files(int which) const { return inputs_[which].size(); } + + // Return the ith input file at "level()+which" ("which" must be 0 or 1). + FileMetaData* input(int which, int i) const { return inputs_[which][i]; } + + // Maximum size of files to build during this compaction. + uint64_t MaxOutputFileSize() const { return max_output_file_size_; } + + // Is this a trivial compaction that can be implemented by just + // moving a single input file to the next level (no merging or splitting) + bool IsTrivialMove() const; + + // Add all inputs to this compaction as delete operations to *edit. + void AddInputDeletions(VersionEdit* edit); + + // Returns true if the information we have available guarantees that + // the compaction is producing data in "level+1" for which no data exists + // in levels greater than "level+1". + bool IsBaseLevelForKey(const Slice& user_key); + + // Returns true iff we should stop building the current output + // before processing "internal_key". + bool ShouldStopBefore(const Slice& internal_key); + + // Release the input version for the compaction, once the compaction + // is successful. + void ReleaseInputs(); + + private: + friend class Version; + friend class VersionSet; + + Compaction(const Options* options, int level); + + int level_; + uint64_t max_output_file_size_; + Version* input_version_; + VersionEdit edit_; + + // Each compaction reads inputs from "level_" and "level_+1" + std::vector inputs_[2]; // The two sets of inputs + + // State used to check for number of overlapping grandparent files + // (parent == level_ + 1, grandparent == level_ + 2) + std::vector grandparents_; + size_t grandparent_index_; // Index in grandparent_starts_ + bool seen_key_; // Some output key has been seen + int64_t overlapped_bytes_; // Bytes of overlap between current output + // and grandparent files + + // State for implementing IsBaseLevelForKey + + // level_ptrs_ holds indices into input_version_->levels_: our state + // is that we are positioned at one of the file ranges for each + // higher level than the ones involved in this compaction (i.e. for + // all L >= level_ + 2). + size_t level_ptrs_[config::kNumLevels]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_VERSION_SET_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch.cc new file mode 100644 index 0000000..2dec642 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch.cc @@ -0,0 +1,150 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch::rep_ := +// sequence: fixed64 +// count: fixed32 +// data: record[count] +// record := +// kTypeValue varstring varstring | +// kTypeDeletion varstring +// varstring := +// len: varint32 +// data: uint8[len] + +#include "leveldb/write_batch.h" + +#include "db/dbformat.h" +#include "db/memtable.h" +#include "db/write_batch_internal.h" +#include "leveldb/db.h" +#include "util/coding.h" + +namespace leveldb { + +// WriteBatch header has an 8-byte sequence number followed by a 4-byte count. +static const size_t kHeader = 12; + +WriteBatch::WriteBatch() { Clear(); } + +WriteBatch::~WriteBatch() {} + +WriteBatch::Handler::~Handler() {} + +void WriteBatch::Clear() { + rep_.clear(); + rep_.resize(kHeader); +} + +size_t WriteBatch::ApproximateSize() const { return rep_.size(); } + +Status WriteBatch::Iterate(Handler* handler) const { + Slice input(rep_); + if (input.size() < kHeader) { + return Status::Corruption("malformed WriteBatch (too small)"); + } + + input.remove_prefix(kHeader); + Slice key, value; + int found = 0; + while (!input.empty()) { + found++; + char tag = input[0]; + input.remove_prefix(1); + switch (tag) { + case kTypeValue: + if (GetLengthPrefixedSlice(&input, &key) && + GetLengthPrefixedSlice(&input, &value)) { + handler->Put(key, value); + } else { + return Status::Corruption("bad WriteBatch Put"); + } + break; + case kTypeDeletion: + if (GetLengthPrefixedSlice(&input, &key)) { + handler->Delete(key); + } else { + return Status::Corruption("bad WriteBatch Delete"); + } + break; + default: + return Status::Corruption("unknown WriteBatch tag"); + } + } + if (found != WriteBatchInternal::Count(this)) { + return Status::Corruption("WriteBatch has wrong count"); + } else { + return Status::OK(); + } +} + +int WriteBatchInternal::Count(const WriteBatch* b) { + return DecodeFixed32(b->rep_.data() + 8); +} + +void WriteBatchInternal::SetCount(WriteBatch* b, int n) { + EncodeFixed32(&b->rep_[8], n); +} + +SequenceNumber WriteBatchInternal::Sequence(const WriteBatch* b) { + return SequenceNumber(DecodeFixed64(b->rep_.data())); +} + +void WriteBatchInternal::SetSequence(WriteBatch* b, SequenceNumber seq) { + EncodeFixed64(&b->rep_[0], seq); +} + +void WriteBatch::Put(const Slice& key, const Slice& value) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeValue)); + PutLengthPrefixedSlice(&rep_, key); + PutLengthPrefixedSlice(&rep_, value); +} + +void WriteBatch::Delete(const Slice& key) { + WriteBatchInternal::SetCount(this, WriteBatchInternal::Count(this) + 1); + rep_.push_back(static_cast(kTypeDeletion)); + PutLengthPrefixedSlice(&rep_, key); +} + +void WriteBatch::Append(const WriteBatch& source) { + WriteBatchInternal::Append(this, &source); +} + +namespace { +class MemTableInserter : public WriteBatch::Handler { + public: + SequenceNumber sequence_; + MemTable* mem_; + + virtual void Put(const Slice& key, const Slice& value) { + mem_->Add(sequence_, kTypeValue, key, value); + sequence_++; + } + virtual void Delete(const Slice& key) { + mem_->Add(sequence_, kTypeDeletion, key, Slice()); + sequence_++; + } +}; +} // namespace + +Status WriteBatchInternal::InsertInto(const WriteBatch* b, MemTable* memtable) { + MemTableInserter inserter; + inserter.sequence_ = WriteBatchInternal::Sequence(b); + inserter.mem_ = memtable; + return b->Iterate(&inserter); +} + +void WriteBatchInternal::SetContents(WriteBatch* b, const Slice& contents) { + assert(contents.size() >= kHeader); + b->rep_.assign(contents.data(), contents.size()); +} + +void WriteBatchInternal::Append(WriteBatch* dst, const WriteBatch* src) { + SetCount(dst, Count(dst) + Count(src)); + assert(src->rep_.size() >= kHeader); + dst->rep_.append(src->rep_.data() + kHeader, src->rep_.size() - kHeader); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch_internal.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch_internal.h new file mode 100644 index 0000000..fce86e3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/db/write_batch_internal.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ +#define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ + +#include "db/dbformat.h" +#include "leveldb/write_batch.h" + +namespace leveldb { + +class MemTable; + +// WriteBatchInternal provides static methods for manipulating a +// WriteBatch that we don't want in the public WriteBatch interface. +class WriteBatchInternal { + public: + // Return the number of entries in the batch. + static int Count(const WriteBatch* batch); + + // Set the count for the number of entries in the batch. + static void SetCount(WriteBatch* batch, int n); + + // Return the sequence number for the start of this batch. + static SequenceNumber Sequence(const WriteBatch* batch); + + // Store the specified number as the sequence number for the start of + // this batch. + static void SetSequence(WriteBatch* batch, SequenceNumber seq); + + static Slice Contents(const WriteBatch* batch) { return Slice(batch->rep_); } + + static size_t ByteSize(const WriteBatch* batch) { return batch->rep_.size(); } + + static void SetContents(WriteBatch* batch, const Slice& contents); + + static Status InsertInto(const WriteBatch* batch, MemTable* memtable); + + static void Append(WriteBatch* dst, const WriteBatch* src); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/c.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/c.h new file mode 100644 index 0000000..8e0d592 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/c.h @@ -0,0 +1,270 @@ +/* Copyright (c) 2011 The LevelDB Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. See the AUTHORS file for names of contributors. + + C bindings for leveldb. May be useful as a stable ABI that can be + used by programs that keep leveldb in a shared library, or for + a JNI api. + + Does not support: + . getters for the option types + . custom comparators that implement key shortening + . custom iter, db, env, cache implementations using just the C bindings + + Some conventions: + + (1) We expose just opaque struct pointers and functions to clients. + This allows us to change internal representations without having to + recompile clients. + + (2) For simplicity, there is no equivalent to the Slice type. Instead, + the caller has to pass the pointer and length as separate + arguments. + + (3) Errors are represented by a null-terminated c string. NULL + means no error. All operations that can raise an error are passed + a "char** errptr" as the last argument. One of the following must + be true on entry: + *errptr == NULL + *errptr points to a malloc()ed null-terminated error message + (On Windows, *errptr must have been malloc()-ed by this library.) + On success, a leveldb routine leaves *errptr unchanged. + On failure, leveldb frees the old value of *errptr and + set *errptr to a malloc()ed error message. + + (4) Bools have the type unsigned char (0 == false; rest == true) + + (5) All of the pointer arguments must be non-NULL. +*/ + +#ifndef STORAGE_LEVELDB_INCLUDE_C_H_ +#define STORAGE_LEVELDB_INCLUDE_C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include "leveldb/export.h" + +/* Exported types */ + +typedef struct leveldb_t leveldb_t; +typedef struct leveldb_cache_t leveldb_cache_t; +typedef struct leveldb_comparator_t leveldb_comparator_t; +typedef struct leveldb_env_t leveldb_env_t; +typedef struct leveldb_filelock_t leveldb_filelock_t; +typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; +typedef struct leveldb_iterator_t leveldb_iterator_t; +typedef struct leveldb_logger_t leveldb_logger_t; +typedef struct leveldb_options_t leveldb_options_t; +typedef struct leveldb_randomfile_t leveldb_randomfile_t; +typedef struct leveldb_readoptions_t leveldb_readoptions_t; +typedef struct leveldb_seqfile_t leveldb_seqfile_t; +typedef struct leveldb_snapshot_t leveldb_snapshot_t; +typedef struct leveldb_writablefile_t leveldb_writablefile_t; +typedef struct leveldb_writebatch_t leveldb_writebatch_t; +typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; + +/* DB operations */ + +LEVELDB_EXPORT leveldb_t* leveldb_open(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_close(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_put(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, const char* val, + size_t vallen, char** errptr); + +LEVELDB_EXPORT void leveldb_delete(leveldb_t* db, + const leveldb_writeoptions_t* options, + const char* key, size_t keylen, + char** errptr); + +LEVELDB_EXPORT void leveldb_write(leveldb_t* db, + const leveldb_writeoptions_t* options, + leveldb_writebatch_t* batch, char** errptr); + +/* Returns NULL if not found. A malloc()ed array otherwise. + Stores the length of the array in *vallen. */ +LEVELDB_EXPORT char* leveldb_get(leveldb_t* db, + const leveldb_readoptions_t* options, + const char* key, size_t keylen, size_t* vallen, + char** errptr); + +LEVELDB_EXPORT leveldb_iterator_t* leveldb_create_iterator( + leveldb_t* db, const leveldb_readoptions_t* options); + +LEVELDB_EXPORT const leveldb_snapshot_t* leveldb_create_snapshot(leveldb_t* db); + +LEVELDB_EXPORT void leveldb_release_snapshot( + leveldb_t* db, const leveldb_snapshot_t* snapshot); + +/* Returns NULL if property name is unknown. + Else returns a pointer to a malloc()-ed null-terminated value. */ +LEVELDB_EXPORT char* leveldb_property_value(leveldb_t* db, + const char* propname); + +LEVELDB_EXPORT void leveldb_approximate_sizes( + leveldb_t* db, int num_ranges, const char* const* range_start_key, + const size_t* range_start_key_len, const char* const* range_limit_key, + const size_t* range_limit_key_len, uint64_t* sizes); + +LEVELDB_EXPORT void leveldb_compact_range(leveldb_t* db, const char* start_key, + size_t start_key_len, + const char* limit_key, + size_t limit_key_len); + +/* Management operations */ + +LEVELDB_EXPORT void leveldb_destroy_db(const leveldb_options_t* options, + const char* name, char** errptr); + +LEVELDB_EXPORT void leveldb_repair_db(const leveldb_options_t* options, + const char* name, char** errptr); + +/* Iterator */ + +LEVELDB_EXPORT void leveldb_iter_destroy(leveldb_iterator_t*); +LEVELDB_EXPORT unsigned char leveldb_iter_valid(const leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_first(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek_to_last(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_seek(leveldb_iterator_t*, const char* k, + size_t klen); +LEVELDB_EXPORT void leveldb_iter_next(leveldb_iterator_t*); +LEVELDB_EXPORT void leveldb_iter_prev(leveldb_iterator_t*); +LEVELDB_EXPORT const char* leveldb_iter_key(const leveldb_iterator_t*, + size_t* klen); +LEVELDB_EXPORT const char* leveldb_iter_value(const leveldb_iterator_t*, + size_t* vlen); +LEVELDB_EXPORT void leveldb_iter_get_error(const leveldb_iterator_t*, + char** errptr); + +/* Write batch */ + +LEVELDB_EXPORT leveldb_writebatch_t* leveldb_writebatch_create(); +LEVELDB_EXPORT void leveldb_writebatch_destroy(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_clear(leveldb_writebatch_t*); +LEVELDB_EXPORT void leveldb_writebatch_put(leveldb_writebatch_t*, + const char* key, size_t klen, + const char* val, size_t vlen); +LEVELDB_EXPORT void leveldb_writebatch_delete(leveldb_writebatch_t*, + const char* key, size_t klen); +LEVELDB_EXPORT void leveldb_writebatch_iterate( + const leveldb_writebatch_t*, void* state, + void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), + void (*deleted)(void*, const char* k, size_t klen)); +LEVELDB_EXPORT void leveldb_writebatch_append( + leveldb_writebatch_t* destination, const leveldb_writebatch_t* source); + +/* Options */ + +LEVELDB_EXPORT leveldb_options_t* leveldb_options_create(); +LEVELDB_EXPORT void leveldb_options_destroy(leveldb_options_t*); +LEVELDB_EXPORT void leveldb_options_set_comparator(leveldb_options_t*, + leveldb_comparator_t*); +LEVELDB_EXPORT void leveldb_options_set_filter_policy(leveldb_options_t*, + leveldb_filterpolicy_t*); +LEVELDB_EXPORT void leveldb_options_set_create_if_missing(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_error_if_exists(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_paranoid_checks(leveldb_options_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); +LEVELDB_EXPORT void leveldb_options_set_info_log(leveldb_options_t*, + leveldb_logger_t*); +LEVELDB_EXPORT void leveldb_options_set_write_buffer_size(leveldb_options_t*, + size_t); +LEVELDB_EXPORT void leveldb_options_set_max_open_files(leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_cache(leveldb_options_t*, + leveldb_cache_t*); +LEVELDB_EXPORT void leveldb_options_set_block_size(leveldb_options_t*, size_t); +LEVELDB_EXPORT void leveldb_options_set_block_restart_interval( + leveldb_options_t*, int); +LEVELDB_EXPORT void leveldb_options_set_max_file_size(leveldb_options_t*, + size_t); + +enum { leveldb_no_compression = 0, leveldb_snappy_compression = 1 }; +LEVELDB_EXPORT void leveldb_options_set_compression(leveldb_options_t*, int); + +/* Comparator */ + +LEVELDB_EXPORT leveldb_comparator_t* leveldb_comparator_create( + void* state, void (*destructor)(void*), + int (*compare)(void*, const char* a, size_t alen, const char* b, + size_t blen), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_comparator_destroy(leveldb_comparator_t*); + +/* Filter policy */ + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create( + void* state, void (*destructor)(void*), + char* (*create_filter)(void*, const char* const* key_array, + const size_t* key_length_array, int num_keys, + size_t* filter_length), + unsigned char (*key_may_match)(void*, const char* key, size_t length, + const char* filter, size_t filter_length), + const char* (*name)(void*)); +LEVELDB_EXPORT void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); + +LEVELDB_EXPORT leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( + int bits_per_key); + +/* Read options */ + +LEVELDB_EXPORT leveldb_readoptions_t* leveldb_readoptions_create(); +LEVELDB_EXPORT void leveldb_readoptions_destroy(leveldb_readoptions_t*); +LEVELDB_EXPORT void leveldb_readoptions_set_verify_checksums( + leveldb_readoptions_t*, unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_fill_cache(leveldb_readoptions_t*, + unsigned char); +LEVELDB_EXPORT void leveldb_readoptions_set_snapshot(leveldb_readoptions_t*, + const leveldb_snapshot_t*); + +/* Write options */ + +LEVELDB_EXPORT leveldb_writeoptions_t* leveldb_writeoptions_create(); +LEVELDB_EXPORT void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); +LEVELDB_EXPORT void leveldb_writeoptions_set_sync(leveldb_writeoptions_t*, + unsigned char); + +/* Cache */ + +LEVELDB_EXPORT leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); +LEVELDB_EXPORT void leveldb_cache_destroy(leveldb_cache_t* cache); + +/* Env */ + +LEVELDB_EXPORT leveldb_env_t* leveldb_create_default_env(); +LEVELDB_EXPORT void leveldb_env_destroy(leveldb_env_t*); + +/* If not NULL, the returned buffer must be released using leveldb_free(). */ +LEVELDB_EXPORT char* leveldb_env_get_test_directory(leveldb_env_t*); + +/* Utility */ + +/* Calls free(ptr). + REQUIRES: ptr was malloc()-ed and returned by one of the routines + in this file. Note that in certain cases (typically on Windows), you + may need to call this routine instead of free(ptr) to dispose of + malloc()-ed memory returned by this library. */ +LEVELDB_EXPORT void leveldb_free(void* ptr); + +/* Return the major version number for this release. */ +LEVELDB_EXPORT int leveldb_major_version(); + +/* Return the minor version number for this release. */ +LEVELDB_EXPORT int leveldb_minor_version(); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* STORAGE_LEVELDB_INCLUDE_C_H_ */ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/cache.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/cache.h new file mode 100644 index 0000000..7d1a221 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/cache.h @@ -0,0 +1,111 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Cache is an interface that maps keys to values. It has internal +// synchronization and may be safely accessed concurrently from +// multiple threads. It may automatically evict entries to make room +// for new entries. Values have a specified charge against the cache +// capacity. For example, a cache where the values are variable +// length strings, may use the length of the string as the charge for +// the string. +// +// A builtin cache implementation with a least-recently-used eviction +// policy is provided. Clients may use their own implementations if +// they want something more sophisticated (like scan-resistance, a +// custom eviction policy, variable cache sizing, etc.) + +#ifndef STORAGE_LEVELDB_INCLUDE_CACHE_H_ +#define STORAGE_LEVELDB_INCLUDE_CACHE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Cache; + +// Create a new cache with a fixed size capacity. This implementation +// of Cache uses a least-recently-used eviction policy. +LEVELDB_EXPORT Cache* NewLRUCache(size_t capacity); + +class LEVELDB_EXPORT Cache { + public: + Cache() = default; + + Cache(const Cache&) = delete; + Cache& operator=(const Cache&) = delete; + + // Destroys all existing entries by calling the "deleter" + // function that was passed to the constructor. + virtual ~Cache(); + + // Opaque handle to an entry stored in the cache. + struct Handle {}; + + // Insert a mapping from key->value into the cache and assign it + // the specified charge against the total cache capacity. + // + // Returns a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + // + // When the inserted entry is no longer needed, the key and + // value will be passed to "deleter". + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) = 0; + + // If the cache has no mapping for "key", returns nullptr. + // + // Else return a handle that corresponds to the mapping. The caller + // must call this->Release(handle) when the returned mapping is no + // longer needed. + virtual Handle* Lookup(const Slice& key) = 0; + + // Release a mapping returned by a previous Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void Release(Handle* handle) = 0; + + // Return the value encapsulated in a handle returned by a + // successful Lookup(). + // REQUIRES: handle must not have been released yet. + // REQUIRES: handle must have been returned by a method on *this. + virtual void* Value(Handle* handle) = 0; + + // If the cache contains entry for key, erase it. Note that the + // underlying entry will be kept around until all existing handles + // to it have been released. + virtual void Erase(const Slice& key) = 0; + + // Return a new numeric id. May be used by multiple clients who are + // sharing the same cache to partition the key space. Typically the + // client will allocate a new id at startup and prepend the id to + // its cache keys. + virtual uint64_t NewId() = 0; + + // Remove all cache entries that are not actively in use. Memory-constrained + // applications may wish to call this method to reduce memory usage. + // Default implementation of Prune() does nothing. Subclasses are strongly + // encouraged to override the default implementation. A future release of + // leveldb may change Prune() to a pure abstract method. + virtual void Prune() {} + + // Return an estimate of the combined charges of all elements stored in the + // cache. + virtual size_t TotalCharge() const = 0; + + private: + void LRU_Remove(Handle* e); + void LRU_Append(Handle* e); + void Unref(Handle* e); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_CACHE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/comparator.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/comparator.h new file mode 100644 index 0000000..a85b51e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/comparator.h @@ -0,0 +1,64 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +// A Comparator object provides a total order across slices that are +// used as keys in an sstable or a database. A Comparator implementation +// must be thread-safe since leveldb may invoke its methods concurrently +// from multiple threads. +class LEVELDB_EXPORT Comparator { + public: + virtual ~Comparator(); + + // Three-way comparison. Returns value: + // < 0 iff "a" < "b", + // == 0 iff "a" == "b", + // > 0 iff "a" > "b" + virtual int Compare(const Slice& a, const Slice& b) const = 0; + + // The name of the comparator. Used to check for comparator + // mismatches (i.e., a DB created with one comparator is + // accessed using a different comparator. + // + // The client of this package should switch to a new name whenever + // the comparator implementation changes in a way that will cause + // the relative ordering of any two keys to change. + // + // Names starting with "leveldb." are reserved and should not be used + // by any clients of this package. + virtual const char* Name() const = 0; + + // Advanced functions: these are used to reduce the space requirements + // for internal data structures like index blocks. + + // If *start < limit, changes *start to a short string in [start,limit). + // Simple comparator implementations may return with *start unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const = 0; + + // Changes *key to a short string >= *key. + // Simple comparator implementations may return with *key unchanged, + // i.e., an implementation of this method that does nothing is correct. + virtual void FindShortSuccessor(std::string* key) const = 0; +}; + +// Return a builtin comparator that uses lexicographic byte-wise +// ordering. The result remains the property of this module and +// must not be deleted. +LEVELDB_EXPORT const Comparator* BytewiseComparator(); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/db.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/db.h new file mode 100644 index 0000000..ea3d9e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/db.h @@ -0,0 +1,167 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DB_H_ +#define STORAGE_LEVELDB_INCLUDE_DB_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" +#include "leveldb/options.h" + +namespace leveldb { + +// Update CMakeLists.txt if you change these +static const int kMajorVersion = 1; +static const int kMinorVersion = 22; + +struct Options; +struct ReadOptions; +struct WriteOptions; +class WriteBatch; + +// Abstract handle to particular state of a DB. +// A Snapshot is an immutable object and can therefore be safely +// accessed from multiple threads without any external synchronization. +class LEVELDB_EXPORT Snapshot { + protected: + virtual ~Snapshot(); +}; + +// A range of keys +struct LEVELDB_EXPORT Range { + Range() {} + Range(const Slice& s, const Slice& l) : start(s), limit(l) {} + + Slice start; // Included in the range + Slice limit; // Not included in the range +}; + +// A DB is a persistent ordered map from keys to values. +// A DB is safe for concurrent access from multiple threads without +// any external synchronization. +class LEVELDB_EXPORT DB { + public: + // Open the database with the specified "name". + // Stores a pointer to a heap-allocated database in *dbptr and returns + // OK on success. + // Stores nullptr in *dbptr and returns a non-OK status on error. + // Caller should delete *dbptr when it is no longer needed. + static Status Open(const Options& options, const std::string& name, + DB** dbptr); + + DB() = default; + + DB(const DB&) = delete; + DB& operator=(const DB&) = delete; + + virtual ~DB(); + + // Set the database entry for "key" to "value". Returns OK on success, + // and a non-OK status on error. + // Note: consider setting options.sync = true. + virtual Status Put(const WriteOptions& options, const Slice& key, + const Slice& value) = 0; + + // Remove the database entry (if any) for "key". Returns OK on + // success, and a non-OK status on error. It is not an error if "key" + // did not exist in the database. + // Note: consider setting options.sync = true. + virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; + + // Apply the specified updates to the database. + // Returns OK on success, non-OK on failure. + // Note: consider setting options.sync = true. + virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; + + // If the database contains an entry for "key" store the + // corresponding value in *value and return OK. + // + // If there is no entry for "key" leave *value unchanged and return + // a status for which Status::IsNotFound() returns true. + // + // May return some other Status on an error. + virtual Status Get(const ReadOptions& options, const Slice& key, + std::string* value) = 0; + + // Return a heap-allocated iterator over the contents of the database. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + // + // Caller should delete the iterator when it is no longer needed. + // The returned iterator should be deleted before this db is deleted. + virtual Iterator* NewIterator(const ReadOptions& options) = 0; + + // Return a handle to the current DB state. Iterators created with + // this handle will all observe a stable snapshot of the current DB + // state. The caller must call ReleaseSnapshot(result) when the + // snapshot is no longer needed. + virtual const Snapshot* GetSnapshot() = 0; + + // Release a previously acquired snapshot. The caller must not + // use "snapshot" after this call. + virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; + + // DB implementations can export properties about their state + // via this method. If "property" is a valid property understood by this + // DB implementation, fills "*value" with its current value and returns + // true. Otherwise returns false. + // + // + // Valid property names include: + // + // "leveldb.num-files-at-level" - return the number of files at level , + // where is an ASCII representation of a level number (e.g. "0"). + // "leveldb.stats" - returns a multi-line string that describes statistics + // about the internal operation of the DB. + // "leveldb.sstables" - returns a multi-line string that describes all + // of the sstables that make up the db contents. + // "leveldb.approximate-memory-usage" - returns the approximate number of + // bytes of memory in use by the DB. + virtual bool GetProperty(const Slice& property, std::string* value) = 0; + + // For each i in [0,n-1], store in "sizes[i]", the approximate + // file system space used by keys in "[range[i].start .. range[i].limit)". + // + // Note that the returned sizes measure file system space usage, so + // if the user data compresses by a factor of ten, the returned + // sizes will be one-tenth the size of the corresponding user data size. + // + // The results may not include the sizes of recently written data. + virtual void GetApproximateSizes(const Range* range, int n, + uint64_t* sizes) = 0; + + // Compact the underlying storage for the key range [*begin,*end]. + // In particular, deleted and overwritten versions are discarded, + // and the data is rearranged to reduce the cost of operations + // needed to access the data. This operation should typically only + // be invoked by users who understand the underlying implementation. + // + // begin==nullptr is treated as a key before all keys in the database. + // end==nullptr is treated as a key after all keys in the database. + // Therefore the following call will compact the entire database: + // db->CompactRange(nullptr, nullptr); + virtual void CompactRange(const Slice* begin, const Slice* end) = 0; +}; + +// Destroy the contents of the specified database. +// Be very careful using this method. +// +// Note: For backwards compatibility, if DestroyDB is unable to list the +// database files, Status::OK() will still be returned masking this failure. +LEVELDB_EXPORT Status DestroyDB(const std::string& name, + const Options& options); + +// If a DB cannot be opened, you may attempt to call this method to +// resurrect as much of the contents of the database as possible. +// Some data may be lost, so be careful when calling this function +// on a database that contains important information. +LEVELDB_EXPORT Status RepairDB(const std::string& dbname, + const Options& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DB_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/dumpfile.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/dumpfile.h new file mode 100644 index 0000000..a58bc6b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/dumpfile.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ +#define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ + +#include + +#include "leveldb/env.h" +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +// Dump the contents of the file named by fname in text format to +// *dst. Makes a sequence of dst->Append() calls; each call is passed +// the newline-terminated text corresponding to a single item found +// in the file. +// +// Returns a non-OK result if fname does not name a leveldb storage +// file, or if the file cannot be read. +LEVELDB_EXPORT Status DumpFile(Env* env, const std::string& fname, + WritableFile* dst); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/env.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/env.h new file mode 100644 index 0000000..112fe96 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/env.h @@ -0,0 +1,387 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An Env is an interface used by the leveldb implementation to access +// operating system functionality like the filesystem etc. Callers +// may wish to provide a custom Env object when opening a database to +// get fine gain control; e.g., to rate limit file system operations. +// +// All Env implementations are safe for concurrent access from +// multiple threads without any external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_ +#define STORAGE_LEVELDB_INCLUDE_ENV_H_ + +#include +#include + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +#if defined(_WIN32) +// The leveldb::Env class below contains a DeleteFile method. +// At the same time, , a fairly popular header +// file for Windows applications, defines a DeleteFile macro. +// +// Without any intervention on our part, the result of this +// unfortunate coincidence is that the name of the +// leveldb::Env::DeleteFile method seen by the compiler depends on +// whether was included before or after the LevelDB +// headers. +// +// To avoid headaches, we undefined DeleteFile (if defined) and +// redefine it at the bottom of this file. This way +// can be included before this file (or not at all) and the +// exported method will always be leveldb::Env::DeleteFile. +#if defined(DeleteFile) +#undef DeleteFile +#define LEVELDB_DELETEFILE_UNDEFINED +#endif // defined(DeleteFile) +#endif // defined(_WIN32) + +namespace leveldb { + +class FileLock; +class Logger; +class RandomAccessFile; +class SequentialFile; +class Slice; +class WritableFile; + +class LEVELDB_EXPORT Env { + public: + Env() = default; + + Env(const Env&) = delete; + Env& operator=(const Env&) = delete; + + virtual ~Env(); + + // Return a default environment suitable for the current operating + // system. Sophisticated users may wish to provide their own Env + // implementation instead of relying on this default environment. + // + // The result of Default() belongs to leveldb and must never be deleted. + static Env* Default(); + + // Create an object that sequentially reads the file with the specified name. + // On success, stores a pointer to the new file in *result and returns OK. + // On failure stores nullptr in *result and returns non-OK. If the file does + // not exist, returns a non-OK status. Implementations should return a + // NotFound status when the file does not exist. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewSequentialFile(const std::string& fname, + SequentialFile** result) = 0; + + // Create an object supporting random-access reads from the file with the + // specified name. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. If the file does not exist, returns a non-OK + // status. Implementations should return a NotFound status when the file does + // not exist. + // + // The returned file may be concurrently accessed by multiple threads. + virtual Status NewRandomAccessFile(const std::string& fname, + RandomAccessFile** result) = 0; + + // Create an object that writes to a new file with the specified + // name. Deletes any existing file with the same name and creates a + // new file. On success, stores a pointer to the new file in + // *result and returns OK. On failure stores nullptr in *result and + // returns non-OK. + // + // The returned file will only be accessed by one thread at a time. + virtual Status NewWritableFile(const std::string& fname, + WritableFile** result) = 0; + + // Create an object that either appends to an existing file, or + // writes to a new file (if the file does not exist to begin with). + // On success, stores a pointer to the new file in *result and + // returns OK. On failure stores nullptr in *result and returns + // non-OK. + // + // The returned file will only be accessed by one thread at a time. + // + // May return an IsNotSupportedError error if this Env does + // not allow appending to an existing file. Users of Env (including + // the leveldb implementation) must be prepared to deal with + // an Env that does not support appending. + virtual Status NewAppendableFile(const std::string& fname, + WritableFile** result); + + // Returns true iff the named file exists. + virtual bool FileExists(const std::string& fname) = 0; + + // Store in *result the names of the children of the specified directory. + // The names are relative to "dir". + // Original contents of *results are dropped. + virtual Status GetChildren(const std::string& dir, + std::vector* result) = 0; + + // Delete the named file. + virtual Status DeleteFile(const std::string& fname) = 0; + + // Create the specified directory. + virtual Status CreateDir(const std::string& dirname) = 0; + + // Delete the specified directory. + virtual Status DeleteDir(const std::string& dirname) = 0; + + // Store the size of fname in *file_size. + virtual Status GetFileSize(const std::string& fname, uint64_t* file_size) = 0; + + // Rename file src to target. + virtual Status RenameFile(const std::string& src, + const std::string& target) = 0; + + // Lock the specified file. Used to prevent concurrent access to + // the same db by multiple processes. On failure, stores nullptr in + // *lock and returns non-OK. + // + // On success, stores a pointer to the object that represents the + // acquired lock in *lock and returns OK. The caller should call + // UnlockFile(*lock) to release the lock. If the process exits, + // the lock will be automatically released. + // + // If somebody else already holds the lock, finishes immediately + // with a failure. I.e., this call does not wait for existing locks + // to go away. + // + // May create the named file if it does not already exist. + virtual Status LockFile(const std::string& fname, FileLock** lock) = 0; + + // Release the lock acquired by a previous successful call to LockFile. + // REQUIRES: lock was returned by a successful LockFile() call + // REQUIRES: lock has not already been unlocked. + virtual Status UnlockFile(FileLock* lock) = 0; + + // Arrange to run "(*function)(arg)" once in a background thread. + // + // "function" may run in an unspecified thread. Multiple functions + // added to the same Env may run concurrently in different threads. + // I.e., the caller may not assume that background work items are + // serialized. + virtual void Schedule(void (*function)(void* arg), void* arg) = 0; + + // Start a new thread, invoking "function(arg)" within the new thread. + // When "function(arg)" returns, the thread will be destroyed. + virtual void StartThread(void (*function)(void* arg), void* arg) = 0; + + // *path is set to a temporary directory that can be used for testing. It may + // or may not have just been created. The directory may or may not differ + // between runs of the same process, but subsequent calls will return the + // same directory. + virtual Status GetTestDirectory(std::string* path) = 0; + + // Create and return a log file for storing informational messages. + virtual Status NewLogger(const std::string& fname, Logger** result) = 0; + + // Returns the number of micro-seconds since some fixed point in time. Only + // useful for computing deltas of time. + virtual uint64_t NowMicros() = 0; + + // Sleep/delay the thread for the prescribed number of micro-seconds. + virtual void SleepForMicroseconds(int micros) = 0; +}; + +// A file abstraction for reading sequentially through a file +class LEVELDB_EXPORT SequentialFile { + public: + SequentialFile() = default; + + SequentialFile(const SequentialFile&) = delete; + SequentialFile& operator=(const SequentialFile&) = delete; + + virtual ~SequentialFile(); + + // Read up to "n" bytes from the file. "scratch[0..n-1]" may be + // written by this routine. Sets "*result" to the data that was + // read (including if fewer than "n" bytes were successfully read). + // May set "*result" to point at data in "scratch[0..n-1]", so + // "scratch[0..n-1]" must be live when "*result" is used. + // If an error was encountered, returns a non-OK status. + // + // REQUIRES: External synchronization + virtual Status Read(size_t n, Slice* result, char* scratch) = 0; + + // Skip "n" bytes from the file. This is guaranteed to be no + // slower that reading the same data, but may be faster. + // + // If end of file is reached, skipping will stop at the end of the + // file, and Skip will return OK. + // + // REQUIRES: External synchronization + virtual Status Skip(uint64_t n) = 0; +}; + +// A file abstraction for randomly reading the contents of a file. +class LEVELDB_EXPORT RandomAccessFile { + public: + RandomAccessFile() = default; + + RandomAccessFile(const RandomAccessFile&) = delete; + RandomAccessFile& operator=(const RandomAccessFile&) = delete; + + virtual ~RandomAccessFile(); + + // Read up to "n" bytes from the file starting at "offset". + // "scratch[0..n-1]" may be written by this routine. Sets "*result" + // to the data that was read (including if fewer than "n" bytes were + // successfully read). May set "*result" to point at data in + // "scratch[0..n-1]", so "scratch[0..n-1]" must be live when + // "*result" is used. If an error was encountered, returns a non-OK + // status. + // + // Safe for concurrent use by multiple threads. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const = 0; +}; + +// A file abstraction for sequential writing. The implementation +// must provide buffering since callers may append small fragments +// at a time to the file. +class LEVELDB_EXPORT WritableFile { + public: + WritableFile() = default; + + WritableFile(const WritableFile&) = delete; + WritableFile& operator=(const WritableFile&) = delete; + + virtual ~WritableFile(); + + virtual Status Append(const Slice& data) = 0; + virtual Status Close() = 0; + virtual Status Flush() = 0; + virtual Status Sync() = 0; +}; + +// An interface for writing log messages. +class LEVELDB_EXPORT Logger { + public: + Logger() = default; + + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; + + virtual ~Logger(); + + // Write an entry to the log file with the specified format. + virtual void Logv(const char* format, va_list ap) = 0; +}; + +// Identifies a locked file. +class LEVELDB_EXPORT FileLock { + public: + FileLock() = default; + + FileLock(const FileLock&) = delete; + FileLock& operator=(const FileLock&) = delete; + + virtual ~FileLock(); +}; + +// Log the specified data to *info_log if info_log is non-null. +void Log(Logger* info_log, const char* format, ...) +#if defined(__GNUC__) || defined(__clang__) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +// A utility routine: write "data" to the named file. +LEVELDB_EXPORT Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname); + +// A utility routine: read contents of named file into *data +LEVELDB_EXPORT Status ReadFileToString(Env* env, const std::string& fname, + std::string* data); + +// An implementation of Env that forwards all calls to another Env. +// May be useful to clients who wish to override just part of the +// functionality of another Env. +class LEVELDB_EXPORT EnvWrapper : public Env { + public: + // Initialize an EnvWrapper that delegates all calls to *t. + explicit EnvWrapper(Env* t) : target_(t) {} + virtual ~EnvWrapper(); + + // Return the target to which this Env forwards all calls. + Env* target() const { return target_; } + + // The following text is boilerplate that forwards all methods to target(). + Status NewSequentialFile(const std::string& f, SequentialFile** r) override { + return target_->NewSequentialFile(f, r); + } + Status NewRandomAccessFile(const std::string& f, + RandomAccessFile** r) override { + return target_->NewRandomAccessFile(f, r); + } + Status NewWritableFile(const std::string& f, WritableFile** r) override { + return target_->NewWritableFile(f, r); + } + Status NewAppendableFile(const std::string& f, WritableFile** r) override { + return target_->NewAppendableFile(f, r); + } + bool FileExists(const std::string& f) override { + return target_->FileExists(f); + } + Status GetChildren(const std::string& dir, + std::vector* r) override { + return target_->GetChildren(dir, r); + } + Status DeleteFile(const std::string& f) override { + return target_->DeleteFile(f); + } + Status CreateDir(const std::string& d) override { + return target_->CreateDir(d); + } + Status DeleteDir(const std::string& d) override { + return target_->DeleteDir(d); + } + Status GetFileSize(const std::string& f, uint64_t* s) override { + return target_->GetFileSize(f, s); + } + Status RenameFile(const std::string& s, const std::string& t) override { + return target_->RenameFile(s, t); + } + Status LockFile(const std::string& f, FileLock** l) override { + return target_->LockFile(f, l); + } + Status UnlockFile(FileLock* l) override { return target_->UnlockFile(l); } + void Schedule(void (*f)(void*), void* a) override { + return target_->Schedule(f, a); + } + void StartThread(void (*f)(void*), void* a) override { + return target_->StartThread(f, a); + } + Status GetTestDirectory(std::string* path) override { + return target_->GetTestDirectory(path); + } + Status NewLogger(const std::string& fname, Logger** result) override { + return target_->NewLogger(fname, result); + } + uint64_t NowMicros() override { return target_->NowMicros(); } + void SleepForMicroseconds(int micros) override { + target_->SleepForMicroseconds(micros); + } + + private: + Env* target_; +}; + +} // namespace leveldb + +// Redefine DeleteFile if necessary. +#if defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) +#if defined(UNICODE) +#define DeleteFile DeleteFileW +#else +#define DeleteFile DeleteFileA +#endif // defined(UNICODE) +#endif // defined(_WIN32) && defined(LEVELDB_DELETEFILE_UNDEFINED) + +#endif // STORAGE_LEVELDB_INCLUDE_ENV_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/export.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/export.h new file mode 100644 index 0000000..6ba9b18 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/export.h @@ -0,0 +1,33 @@ +// Copyright (c) 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_EXPORT_H_ +#define STORAGE_LEVELDB_INCLUDE_EXPORT_H_ + +#if !defined(LEVELDB_EXPORT) + +#if defined(LEVELDB_SHARED_LIBRARY) +#if defined(_WIN32) + +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __declspec(dllexport) +#else +#define LEVELDB_EXPORT __declspec(dllimport) +#endif // defined(LEVELDB_COMPILE_LIBRARY) + +#else // defined(_WIN32) +#if defined(LEVELDB_COMPILE_LIBRARY) +#define LEVELDB_EXPORT __attribute__((visibility("default"))) +#else +#define LEVELDB_EXPORT +#endif +#endif // defined(_WIN32) + +#else // defined(LEVELDB_SHARED_LIBRARY) +#define LEVELDB_EXPORT +#endif + +#endif // !defined(LEVELDB_EXPORT) + +#endif // STORAGE_LEVELDB_INCLUDE_EXPORT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/filter_policy.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/filter_policy.h new file mode 100644 index 0000000..49c8eda --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/filter_policy.h @@ -0,0 +1,72 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A database can be configured with a custom FilterPolicy object. +// This object is responsible for creating a small filter from a set +// of keys. These filters are stored in leveldb and are consulted +// automatically by leveldb to decide whether or not to read some +// information from disk. In many cases, a filter can cut down the +// number of disk seeks form a handful to a single disk seek per +// DB::Get() call. +// +// Most people will want to use the builtin bloom filter support (see +// NewBloomFilterPolicy() below). + +#ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ +#define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT FilterPolicy { + public: + virtual ~FilterPolicy(); + + // Return the name of this policy. Note that if the filter encoding + // changes in an incompatible way, the name returned by this method + // must be changed. Otherwise, old incompatible filters may be + // passed to methods of this type. + virtual const char* Name() const = 0; + + // keys[0,n-1] contains a list of keys (potentially with duplicates) + // that are ordered according to the user supplied comparator. + // Append a filter that summarizes keys[0,n-1] to *dst. + // + // Warning: do not change the initial contents of *dst. Instead, + // append the newly constructed filter to *dst. + virtual void CreateFilter(const Slice* keys, int n, + std::string* dst) const = 0; + + // "filter" contains the data appended by a preceding call to + // CreateFilter() on this class. This method must return true if + // the key was in the list of keys passed to CreateFilter(). + // This method may return true or false if the key was not on the + // list, but it should aim to return false with a high probability. + virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; +}; + +// Return a new filter policy that uses a bloom filter with approximately +// the specified number of bits per key. A good value for bits_per_key +// is 10, which yields a filter with ~ 1% false positive rate. +// +// Callers must delete the result after any database that is using the +// result has been closed. +// +// Note: if you are using a custom comparator that ignores some parts +// of the keys being compared, you must not use NewBloomFilterPolicy() +// and must provide your own FilterPolicy that also ignores the +// corresponding parts of the keys. For example, if the comparator +// ignores trailing spaces, it would be incorrect to use a +// FilterPolicy (like NewBloomFilterPolicy) that does not ignore +// trailing spaces in keys. +LEVELDB_EXPORT const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/iterator.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/iterator.h new file mode 100644 index 0000000..bb9a5df --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/iterator.h @@ -0,0 +1,112 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// An iterator yields a sequence of key/value pairs from a source. +// The following class defines the interface. Multiple implementations +// are provided by this library. In particular, iterators are provided +// to access the contents of a Table or a DB. +// +// Multiple threads can invoke const methods on an Iterator without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Iterator must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ +#define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ + +#include "leveldb/export.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" + +namespace leveldb { + +class LEVELDB_EXPORT Iterator { + public: + Iterator(); + + Iterator(const Iterator&) = delete; + Iterator& operator=(const Iterator&) = delete; + + virtual ~Iterator(); + + // An iterator is either positioned at a key/value pair, or + // not valid. This method returns true iff the iterator is valid. + virtual bool Valid() const = 0; + + // Position at the first key in the source. The iterator is Valid() + // after this call iff the source is not empty. + virtual void SeekToFirst() = 0; + + // Position at the last key in the source. The iterator is + // Valid() after this call iff the source is not empty. + virtual void SeekToLast() = 0; + + // Position at the first key in the source that is at or past target. + // The iterator is Valid() after this call iff the source contains + // an entry that comes at or past target. + virtual void Seek(const Slice& target) = 0; + + // Moves to the next entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the last entry in the source. + // REQUIRES: Valid() + virtual void Next() = 0; + + // Moves to the previous entry in the source. After this call, Valid() is + // true iff the iterator was not positioned at the first entry in source. + // REQUIRES: Valid() + virtual void Prev() = 0; + + // Return the key for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice key() const = 0; + + // Return the value for the current entry. The underlying storage for + // the returned slice is valid only until the next modification of + // the iterator. + // REQUIRES: Valid() + virtual Slice value() const = 0; + + // If an error has occurred, return it. Else return an ok status. + virtual Status status() const = 0; + + // Clients are allowed to register function/arg1/arg2 triples that + // will be invoked when this iterator is destroyed. + // + // Note that unlike all of the preceding methods, this method is + // not abstract and therefore clients should not override it. + using CleanupFunction = void (*)(void* arg1, void* arg2); + void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); + + private: + // Cleanup functions are stored in a single-linked list. + // The list's head node is inlined in the iterator. + struct CleanupNode { + // True if the node is not used. Only head nodes might be unused. + bool IsEmpty() const { return function == nullptr; } + // Invokes the cleanup function. + void Run() { + assert(function != nullptr); + (*function)(arg1, arg2); + } + + // The head node is used if the function pointer is not null. + CleanupFunction function; + void* arg1; + void* arg2; + CleanupNode* next; + }; + CleanupNode cleanup_head_; +}; + +// Return an empty iterator (yields nothing). +LEVELDB_EXPORT Iterator* NewEmptyIterator(); + +// Return an empty iterator with the specified status. +LEVELDB_EXPORT Iterator* NewErrorIterator(const Status& status); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/options.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/options.h new file mode 100644 index 0000000..b748772 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/options.h @@ -0,0 +1,187 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ +#define STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class Cache; +class Comparator; +class Env; +class FilterPolicy; +class Logger; +class Snapshot; + +// DB contents are stored in a set of blocks, each of which holds a +// sequence of key,value pairs. Each block may be compressed before +// being stored in a file. The following enum describes which +// compression method (if any) is used to compress a block. +enum CompressionType { + // NOTE: do not change the values of existing entries, as these are + // part of the persistent format on disk. + kNoCompression = 0x0, + kSnappyCompression = 0x1 +}; + +// Options to control the behavior of a database (passed to DB::Open) +struct LEVELDB_EXPORT Options { + // Create an Options object with default values for all fields. + Options(); + + // ------------------- + // Parameters that affect behavior + + // Comparator used to define the order of keys in the table. + // Default: a comparator that uses lexicographic byte-wise ordering + // + // REQUIRES: The client must ensure that the comparator supplied + // here has the same name and orders keys *exactly* the same as the + // comparator provided to previous open calls on the same DB. + const Comparator* comparator; + + // If true, the database will be created if it is missing. + bool create_if_missing = false; + + // If true, an error is raised if the database already exists. + bool error_if_exists = false; + + // If true, the implementation will do aggressive checking of the + // data it is processing and will stop early if it detects any + // errors. This may have unforeseen ramifications: for example, a + // corruption of one DB entry may cause a large number of entries to + // become unreadable or for the entire DB to become unopenable. + bool paranoid_checks = false; + + // Use the specified object to interact with the environment, + // e.g. to read/write files, schedule background work, etc. + // Default: Env::Default() + Env* env; + + // Any internal progress/error information generated by the db will + // be written to info_log if it is non-null, or to a file stored + // in the same directory as the DB contents if info_log is null. + Logger* info_log = nullptr; + + // ------------------- + // Parameters that affect performance + + // Amount of data to build up in memory (backed by an unsorted log + // on disk) before converting to a sorted on-disk file. + // + // Larger values increase performance, especially during bulk loads. + // Up to two write buffers may be held in memory at the same time, + // so you may wish to adjust this parameter to control memory usage. + // Also, a larger write buffer will result in a longer recovery time + // the next time the database is opened. + size_t write_buffer_size = 4 * 1024 * 1024; + + // Number of open files that can be used by the DB. You may need to + // increase this if your database has a large working set (budget + // one open file per 2MB of working set). + int max_open_files = 1000; + + // Control over blocks (user data is stored in a set of blocks, and + // a block is the unit of reading from disk). + + // If non-null, use the specified cache for blocks. + // If null, leveldb will automatically create and use an 8MB internal cache. + Cache* block_cache = nullptr; + + // Approximate size of user data packed per block. Note that the + // block size specified here corresponds to uncompressed data. The + // actual size of the unit read from disk may be smaller if + // compression is enabled. This parameter can be changed dynamically. + size_t block_size = 4 * 1024; + + // Number of keys between restart points for delta encoding of keys. + // This parameter can be changed dynamically. Most clients should + // leave this parameter alone. + int block_restart_interval = 16; + + // Leveldb will write up to this amount of bytes to a file before + // switching to a new one. + // Most clients should leave this parameter alone. However if your + // filesystem is more efficient with larger files, you could + // consider increasing the value. The downside will be longer + // compactions and hence longer latency/performance hiccups. + // Another reason to increase this parameter might be when you are + // initially populating a large database. + size_t max_file_size = 2 * 1024 * 1024; + + // Compress blocks using the specified compression algorithm. This + // parameter can be changed dynamically. + // + // Default: kSnappyCompression, which gives lightweight but fast + // compression. + // + // Typical speeds of kSnappyCompression on an Intel(R) Core(TM)2 2.4GHz: + // ~200-500MB/s compression + // ~400-800MB/s decompression + // Note that these speeds are significantly faster than most + // persistent storage speeds, and therefore it is typically never + // worth switching to kNoCompression. Even if the input data is + // incompressible, the kSnappyCompression implementation will + // efficiently detect that and will switch to uncompressed mode. + CompressionType compression = kSnappyCompression; + + // EXPERIMENTAL: If true, append to existing MANIFEST and log files + // when a database is opened. This can significantly speed up open. + // + // Default: currently false, but may become true later. + bool reuse_logs = false; + + // If non-null, use the specified filter policy to reduce disk reads. + // Many applications will benefit from passing the result of + // NewBloomFilterPolicy() here. + const FilterPolicy* filter_policy = nullptr; +}; + +// Options that control read operations +struct LEVELDB_EXPORT ReadOptions { + ReadOptions() = default; + + // If true, all data read from underlying storage will be + // verified against corresponding checksums. + bool verify_checksums = false; + + // Should the data read for this iteration be cached in memory? + // Callers may wish to set this field to false for bulk scans. + bool fill_cache = true; + + // If "snapshot" is non-null, read as of the supplied snapshot + // (which must belong to the DB that is being read and which must + // not have been released). If "snapshot" is null, use an implicit + // snapshot of the state at the beginning of this read operation. + const Snapshot* snapshot = nullptr; +}; + +// Options that control write operations +struct LEVELDB_EXPORT WriteOptions { + WriteOptions() = default; + + // If true, the write will be flushed from the operating system + // buffer cache (by calling WritableFile::Sync()) before the write + // is considered complete. If this flag is true, writes will be + // slower. + // + // If this flag is false, and the machine crashes, some recent + // writes may be lost. Note that if it is just the process that + // crashes (i.e., the machine does not reboot), no writes will be + // lost even if sync==false. + // + // In other words, a DB write with sync==false has similar + // crash semantics as the "write()" system call. A DB write + // with sync==true has similar crash semantics to a "write()" + // system call followed by "fsync()". + bool sync = false; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_OPTIONS_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/slice.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/slice.h new file mode 100644 index 0000000..2df417d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/slice.h @@ -0,0 +1,115 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_ +#define STORAGE_LEVELDB_INCLUDE_SLICE_H_ + +#include +#include +#include + +#include + +#include "leveldb/export.h" + +namespace leveldb { + +class LEVELDB_EXPORT Slice { + public: + // Create an empty slice. + Slice() : data_(""), size_(0) {} + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) {} + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) {} + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) {} + + // Intentionally copyable. + Slice(const Slice&) = default; + Slice& operator=(const Slice&) = default; + + // Return a pointer to the beginning of the referenced data + const char* data() const { return data_; } + + // Return the length (in bytes) of the referenced data + size_t size() const { return size_; } + + // Return true iff the length of the referenced data is zero + bool empty() const { return size_ == 0; } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { + data_ = ""; + size_ = 0; + } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString() const { return std::string(data_, size_); } + + // Three-way comparison. Returns value: + // < 0 iff "*this" < "b", + // == 0 iff "*this" == "b", + // > 0 iff "*this" > "b" + int compare(const Slice& b) const; + + // Return true iff "x" is a prefix of "*this" + bool starts_with(const Slice& x) const { + return ((size_ >= x.size_) && (memcmp(data_, x.data_, x.size_) == 0)); + } + + private: + const char* data_; + size_t size_; +}; + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { return !(x == y); } + +inline int Slice::compare(const Slice& b) const { + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + if (r == 0) { + if (size_ < b.size_) + r = -1; + else if (size_ > b.size_) + r = +1; + } + return r; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/status.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/status.h new file mode 100644 index 0000000..e327314 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/status.h @@ -0,0 +1,122 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A Status encapsulates the result of an operation. It may indicate success, +// or it may indicate an error with an associated error message. +// +// Multiple threads can invoke const methods on a Status without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Status must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_ +#define STORAGE_LEVELDB_INCLUDE_STATUS_H_ + +#include +#include + +#include "leveldb/export.h" +#include "leveldb/slice.h" + +namespace leveldb { + +class LEVELDB_EXPORT Status { + public: + // Create a success status. + Status() noexcept : state_(nullptr) {} + ~Status() { delete[] state_; } + + Status(const Status& rhs); + Status& operator=(const Status& rhs); + + Status(Status&& rhs) noexcept : state_(rhs.state_) { rhs.state_ = nullptr; } + Status& operator=(Status&& rhs) noexcept; + + // Return a success status. + static Status OK() { return Status(); } + + // Return error status of an appropriate type. + static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotFound, msg, msg2); + } + static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kCorruption, msg, msg2); + } + static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kNotSupported, msg, msg2); + } + static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kInvalidArgument, msg, msg2); + } + static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { + return Status(kIOError, msg, msg2); + } + + // Returns true iff the status indicates success. + bool ok() const { return (state_ == nullptr); } + + // Returns true iff the status indicates a NotFound error. + bool IsNotFound() const { return code() == kNotFound; } + + // Returns true iff the status indicates a Corruption error. + bool IsCorruption() const { return code() == kCorruption; } + + // Returns true iff the status indicates an IOError. + bool IsIOError() const { return code() == kIOError; } + + // Returns true iff the status indicates a NotSupportedError. + bool IsNotSupportedError() const { return code() == kNotSupported; } + + // Returns true iff the status indicates an InvalidArgument. + bool IsInvalidArgument() const { return code() == kInvalidArgument; } + + // Return a string representation of this status suitable for printing. + // Returns the string "OK" for success. + std::string ToString() const; + + private: + enum Code { + kOk = 0, + kNotFound = 1, + kCorruption = 2, + kNotSupported = 3, + kInvalidArgument = 4, + kIOError = 5 + }; + + Code code() const { + return (state_ == nullptr) ? kOk : static_cast(state_[4]); + } + + Status(Code code, const Slice& msg, const Slice& msg2); + static const char* CopyState(const char* s); + + // OK status has a null state_. Otherwise, state_ is a new[] array + // of the following form: + // state_[0..3] == length of message + // state_[4] == code + // state_[5..] == message + const char* state_; +}; + +inline Status::Status(const Status& rhs) { + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); +} +inline Status& Status::operator=(const Status& rhs) { + // The following condition catches both aliasing (when this == &rhs), + // and the common case where both rhs and *this are ok. + if (state_ != rhs.state_) { + delete[] state_; + state_ = (rhs.state_ == nullptr) ? nullptr : CopyState(rhs.state_); + } + return *this; +} +inline Status& Status::operator=(Status&& rhs) noexcept { + std::swap(state_, rhs.state_); + return *this; +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table.h new file mode 100644 index 0000000..25c6013 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table.h @@ -0,0 +1,84 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/iterator.h" + +namespace leveldb { + +class Block; +class BlockHandle; +class Footer; +struct Options; +class RandomAccessFile; +struct ReadOptions; +class TableCache; + +// A Table is a sorted map from strings to strings. Tables are +// immutable and persistent. A Table may be safely accessed from +// multiple threads without external synchronization. +class LEVELDB_EXPORT Table { + public: + // Attempt to open the table that is stored in bytes [0..file_size) + // of "file", and read the metadata entries necessary to allow + // retrieving data from the table. + // + // If successful, returns ok and sets "*table" to the newly opened + // table. The client should delete "*table" when no longer needed. + // If there was an error while initializing the table, sets "*table" + // to nullptr and returns a non-ok status. Does not take ownership of + // "*source", but the client must ensure that "source" remains live + // for the duration of the returned table's lifetime. + // + // *file must remain live while this Table is in use. + static Status Open(const Options& options, RandomAccessFile* file, + uint64_t file_size, Table** table); + + Table(const Table&) = delete; + Table& operator=(const Table&) = delete; + + ~Table(); + + // Returns a new iterator over the table contents. + // The result of NewIterator() is initially invalid (caller must + // call one of the Seek methods on the iterator before using it). + Iterator* NewIterator(const ReadOptions&) const; + + // Given a key, return an approximate byte offset in the file where + // the data for that key begins (or would begin if the key were + // present in the file). The returned value is in terms of file + // bytes, and so includes effects like compression of the underlying data. + // E.g., the approximate offset of the last key in the table will + // be close to the file length. + uint64_t ApproximateOffsetOf(const Slice& key) const; + + private: + friend class TableCache; + struct Rep; + + static Iterator* BlockReader(void*, const ReadOptions&, const Slice&); + + explicit Table(Rep* rep) : rep_(rep) {} + + // Calls (*handle_result)(arg, ...) with the entry found after a call + // to Seek(key). May not make such a call if filter policy says + // that key is not present. + Status InternalGet(const ReadOptions&, const Slice& key, void* arg, + void (*handle_result)(void* arg, const Slice& k, + const Slice& v)); + + void ReadMeta(const Footer& footer); + void ReadFilter(const Slice& filter_handle_value); + + Rep* const rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table_builder.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table_builder.h new file mode 100644 index 0000000..7d8896b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/table_builder.h @@ -0,0 +1,93 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// TableBuilder provides the interface used to build a Table +// (an immutable and sorted map from keys to values). +// +// Multiple threads can invoke const methods on a TableBuilder without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same TableBuilder must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ +#define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/options.h" +#include "leveldb/status.h" + +namespace leveldb { + +class BlockBuilder; +class BlockHandle; +class WritableFile; + +class LEVELDB_EXPORT TableBuilder { + public: + // Create a builder that will store the contents of the table it is + // building in *file. Does not close the file. It is up to the + // caller to close the file after calling Finish(). + TableBuilder(const Options& options, WritableFile* file); + + TableBuilder(const TableBuilder&) = delete; + TableBuilder& operator=(const TableBuilder&) = delete; + + // REQUIRES: Either Finish() or Abandon() has been called. + ~TableBuilder(); + + // Change the options used by this builder. Note: only some of the + // option fields can be changed after construction. If a field is + // not allowed to change dynamically and its value in the structure + // passed to the constructor is different from its value in the + // structure passed to this method, this method will return an error + // without changing any fields. + Status ChangeOptions(const Options& options); + + // Add key,value to the table being constructed. + // REQUIRES: key is after any previously added key according to comparator. + // REQUIRES: Finish(), Abandon() have not been called + void Add(const Slice& key, const Slice& value); + + // Advanced operation: flush any buffered key/value pairs to file. + // Can be used to ensure that two adjacent entries never live in + // the same data block. Most clients should not need to use this method. + // REQUIRES: Finish(), Abandon() have not been called + void Flush(); + + // Return non-ok iff some error has been detected. + Status status() const; + + // Finish building the table. Stops using the file passed to the + // constructor after this function returns. + // REQUIRES: Finish(), Abandon() have not been called + Status Finish(); + + // Indicate that the contents of this builder should be abandoned. Stops + // using the file passed to the constructor after this function returns. + // If the caller is not going to call Finish(), it must call Abandon() + // before destroying this builder. + // REQUIRES: Finish(), Abandon() have not been called + void Abandon(); + + // Number of calls to Add() so far. + uint64_t NumEntries() const; + + // Size of the file generated so far. If invoked after a successful + // Finish() call, returns the size of the final generated file. + uint64_t FileSize() const; + + private: + bool ok() const { return status().ok(); } + void WriteBlock(BlockBuilder* block, BlockHandle* handle); + void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle); + + struct Rep; + Rep* rep_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/write_batch.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/write_batch.h new file mode 100644 index 0000000..94d4115 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/include/leveldb/write_batch.h @@ -0,0 +1,83 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// WriteBatch holds a collection of updates to apply atomically to a DB. +// +// The updates are applied in the order in which they are added +// to the WriteBatch. For example, the value of "key" will be "v3" +// after the following batch is written: +// +// batch.Put("key", "v1"); +// batch.Delete("key"); +// batch.Put("key", "v2"); +// batch.Put("key", "v3"); +// +// Multiple threads can invoke const methods on a WriteBatch without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same WriteBatch must use +// external synchronization. + +#ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ +#define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ + +#include + +#include "leveldb/export.h" +#include "leveldb/status.h" + +namespace leveldb { + +class Slice; + +class LEVELDB_EXPORT WriteBatch { + public: + class LEVELDB_EXPORT Handler { + public: + virtual ~Handler(); + virtual void Put(const Slice& key, const Slice& value) = 0; + virtual void Delete(const Slice& key) = 0; + }; + + WriteBatch(); + + // Intentionally copyable. + WriteBatch(const WriteBatch&) = default; + WriteBatch& operator=(const WriteBatch&) = default; + + ~WriteBatch(); + + // Store the mapping "key->value" in the database. + void Put(const Slice& key, const Slice& value); + + // If the database contains a mapping for "key", erase it. Else do nothing. + void Delete(const Slice& key); + + // Clear all updates buffered in this batch. + void Clear(); + + // The size of the database changes caused by this batch. + // + // This number is tied to implementation details, and may change across + // releases. It is intended for LevelDB usage metrics. + size_t ApproximateSize() const; + + // Copies the operations in "source" to this batch. + // + // This runs in O(source size) time. However, the constant factor is better + // than calling Iterate() over the source batch with a Handler that replicates + // the operations into this batch. + void Append(const WriteBatch& source); + + // Support for iterating over the contents of a batch. + Status Iterate(Handler* handler) const; + + private: + friend class WriteBatchInternal; + + std::string rep_; // See comment in write_batch.cc for the format of rep_ +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port.h new file mode 100644 index 0000000..4b247f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_H_ +#define STORAGE_LEVELDB_PORT_PORT_H_ + +#include + +// Include the appropriate platform specific file below. If you are +// porting to a new platform, see "port_example.h" for documentation +// of what the new port_.h file must provide. +#if defined(LEVELDB_PLATFORM_POSIX) || defined(LEVELDB_PLATFORM_WINDOWS) +#include "port/port_stdcxx.h" +#elif defined(LEVELDB_PLATFORM_CHROMIUM) +#include "port/port_chromium.h" +#endif + +#endif // STORAGE_LEVELDB_PORT_PORT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_example.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_example.h new file mode 100644 index 0000000..1a8fca2 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_example.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// This file contains the specification, but not the implementations, +// of the types/operations/etc. that should be defined by a platform +// specific port_.h file. Use this file as a reference for +// how to port this package to a new platform. + +#ifndef STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ +#define STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +// TODO(jorlow): Many of these belong more in the environment class rather than +// here. We should try moving them and see if it affects perf. + +// The following boolean constant must be true on a little-endian machine +// and false otherwise. +static const bool kLittleEndian = true /* or some other expression */; + +// ------------------ Threading ------------------- + +// A Mutex represents an exclusive lock. +class LOCKABLE Mutex { + public: + Mutex(); + ~Mutex(); + + // Lock the mutex. Waits until other lockers have exited. + // Will deadlock if the mutex is already locked by this thread. + void Lock() EXCLUSIVE_LOCK_FUNCTION(); + + // Unlock the mutex. + // REQUIRES: This mutex was locked by this thread. + void Unlock() UNLOCK_FUNCTION(); + + // Optionally crash if this thread does not hold this mutex. + // The implementation must be fast, especially if NDEBUG is + // defined. The implementation is allowed to skip all checks. + void AssertHeld() ASSERT_EXCLUSIVE_LOCK(); +}; + +class CondVar { + public: + explicit CondVar(Mutex* mu); + ~CondVar(); + + // Atomically release *mu and block on this condition variable until + // either a call to SignalAll(), or a call to Signal() that picks + // this thread to wakeup. + // REQUIRES: this thread holds *mu + void Wait(); + + // If there are some threads waiting, wake up at least one of them. + void Signal(); + + // Wake up all waiting threads. + void SignallAll(); +}; + +// ------------------ Compression ------------------- + +// Store the snappy compression of "input[0,input_length-1]" in *output. +// Returns false if snappy is not supported by this port. +bool Snappy_Compress(const char* input, size_t input_length, + std::string* output); + +// If input[0,input_length-1] looks like a valid snappy compressed +// buffer, store the size of the uncompressed data in *result and +// return true. Else return false. +bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result); + +// Attempt to snappy uncompress input[0,input_length-1] into *output. +// Returns true if successful, false if the input is invalid lightweight +// compressed data. +// +// REQUIRES: at least the first "n" bytes of output[] must be writable +// where "n" is the result of a successful call to +// Snappy_GetUncompressedLength. +bool Snappy_Uncompress(const char* input_data, size_t input_length, + char* output); + +// ------------------ Miscellaneous ------------------- + +// If heap profiling is not supported, returns false. +// Else repeatedly calls (*func)(arg, data, n) and then returns true. +// The concatenation of all "data[0,n-1]" fragments is the heap profile. +bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg); + +// Extend the CRC to include the first n bytes of buf. +// +// Returns zero if the CRC cannot be extended using acceleration, else returns +// the newly extended CRC value (which may also be zero). +uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size); + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_EXAMPLE_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_stdcxx.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_stdcxx.h new file mode 100644 index 0000000..e9cb0e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/port_stdcxx.h @@ -0,0 +1,153 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ +#define STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ + +// port/port_config.h availability is automatically detected via __has_include +// in newer compilers. If LEVELDB_HAS_PORT_CONFIG_H is defined, it overrides the +// configuration detection. +#if defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if LEVELDB_HAS_PORT_CONFIG_H +#include "port/port_config.h" +#endif // LEVELDB_HAS_PORT_CONFIG_H + +#elif defined(__has_include) + +#if __has_include("port/port_config.h") +#include "port/port_config.h" +#endif // __has_include("port/port_config.h") + +#endif // defined(LEVELDB_HAS_PORT_CONFIG_H) + +#if HAVE_CRC32C +#include +#endif // HAVE_CRC32C +#if HAVE_SNAPPY +#include +#endif // HAVE_SNAPPY + +#include +#include // NOLINT +#include +#include +#include // NOLINT +#include + +#include "port/thread_annotations.h" + +namespace leveldb { +namespace port { + +static const bool kLittleEndian = !LEVELDB_IS_BIG_ENDIAN; + +class CondVar; + +// Thinly wraps std::mutex. +class LOCKABLE Mutex { + public: + Mutex() = default; + ~Mutex() = default; + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu_.lock(); } + void Unlock() UNLOCK_FUNCTION() { mu_.unlock(); } + void AssertHeld() ASSERT_EXCLUSIVE_LOCK() {} + + private: + friend class CondVar; + std::mutex mu_; +}; + +// Thinly wraps std::condition_variable. +class CondVar { + public: + explicit CondVar(Mutex* mu) : mu_(mu) { assert(mu != nullptr); } + ~CondVar() = default; + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Wait() { + std::unique_lock lock(mu_->mu_, std::adopt_lock); + cv_.wait(lock); + lock.release(); + } + void Signal() { cv_.notify_one(); } + void SignalAll() { cv_.notify_all(); } + + private: + std::condition_variable cv_; + Mutex* const mu_; +}; + +inline bool Snappy_Compress(const char* input, size_t length, + std::string* output) { +#if HAVE_SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; +#endif // HAVE_SNAPPY + + return false; +} + +inline bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#if HAVE_SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)result; + return false; +#endif // HAVE_SNAPPY +} + +inline bool Snappy_Uncompress(const char* input, size_t length, char* output) { +#if HAVE_SNAPPY + return snappy::RawUncompress(input, length, output); +#else + // Silence compiler warnings about unused arguments. + (void)input; + (void)length; + (void)output; + return false; +#endif // HAVE_SNAPPY +} + +inline bool GetHeapProfile(void (*func)(void*, const char*, int), void* arg) { + // Silence compiler warnings about unused arguments. + (void)func; + (void)arg; + return false; +} + +inline uint32_t AcceleratedCRC32C(uint32_t crc, const char* buf, size_t size) { +#if HAVE_CRC32C + return ::crc32c::Extend(crc, reinterpret_cast(buf), size); +#else + // Silence compiler warnings about unused arguments. + (void)crc; + (void)buf; + (void)size; + return 0; +#endif // HAVE_CRC32C +} + +} // namespace port +} // namespace leveldb + +#endif // STORAGE_LEVELDB_PORT_PORT_STDCXX_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/port/thread_annotations.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/thread_annotations.h new file mode 100644 index 0000000..1547df9 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/port/thread_annotations.h @@ -0,0 +1,108 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ +#define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ + +// Use Clang's thread safety analysis annotations when available. In other +// environments, the macros receive empty definitions. +// Usage documentation: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html + +#if !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#if defined(__clang__) + +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#endif // !defined(THREAD_ANNOTATION_ATTRIBUTE__) + +#ifndef GUARDED_BY +#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) +#endif + +#ifndef PT_GUARDED_BY +#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) +#endif + +#ifndef ACQUIRED_AFTER +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) +#endif + +#ifndef ACQUIRED_BEFORE +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_LOCKS_REQUIRED +#define EXCLUSIVE_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCKS_REQUIRED +#define SHARED_LOCKS_REQUIRED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__)) +#endif + +#ifndef LOCKS_EXCLUDED +#define LOCKS_EXCLUDED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) +#endif + +#ifndef LOCK_RETURNED +#define LOCK_RETURNED(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) +#endif + +#ifndef LOCKABLE +#define LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(lockable) +#endif + +#ifndef SCOPED_LOCKABLE +#define SCOPED_LOCKABLE THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) +#endif + +#ifndef EXCLUSIVE_LOCK_FUNCTION +#define EXCLUSIVE_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_LOCK_FUNCTION +#define SHARED_LOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__)) +#endif + +#ifndef EXCLUSIVE_TRYLOCK_FUNCTION +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__)) +#endif + +#ifndef SHARED_TRYLOCK_FUNCTION +#define SHARED_TRYLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__)) +#endif + +#ifndef UNLOCK_FUNCTION +#define UNLOCK_FUNCTION(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__)) +#endif + +#ifndef NO_THREAD_SAFETY_ANALYSIS +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) +#endif + +#ifndef ASSERT_EXCLUSIVE_LOCK +#define ASSERT_EXCLUSIVE_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__)) +#endif + +#ifndef ASSERT_SHARED_LOCK +#define ASSERT_SHARED_LOCK(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__)) +#endif + +#endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.cc new file mode 100644 index 0000000..ad0ee98 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.cc @@ -0,0 +1,266 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Decodes the blocks generated by block_builder.cc. + +#include "table/block.h" + +#include +#include + +#include "leveldb/comparator.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/logging.h" + +namespace leveldb { + +inline uint32_t Block::NumRestarts() const { + assert(size_ >= sizeof(uint32_t)); + return DecodeFixed32(data_ + size_ - sizeof(uint32_t)); +} + +Block::Block(const BlockContents& contents) + : data_(contents.data.data()), + size_(contents.data.size()), + owned_(contents.heap_allocated) { + if (size_ < sizeof(uint32_t)) { + size_ = 0; // Error marker + } else { + size_t max_restarts_allowed = (size_ - sizeof(uint32_t)) / sizeof(uint32_t); + if (NumRestarts() > max_restarts_allowed) { + // The size is too small for NumRestarts() + size_ = 0; + } else { + restart_offset_ = size_ - (1 + NumRestarts()) * sizeof(uint32_t); + } + } +} + +Block::~Block() { + if (owned_) { + delete[] data_; + } +} + +// Helper routine: decode the next block entry starting at "p", +// storing the number of shared key bytes, non_shared key bytes, +// and the length of the value in "*shared", "*non_shared", and +// "*value_length", respectively. Will not dereference past "limit". +// +// If any errors are detected, returns nullptr. Otherwise, returns a +// pointer to the key delta (just past the three decoded values). +static inline const char* DecodeEntry(const char* p, const char* limit, + uint32_t* shared, uint32_t* non_shared, + uint32_t* value_length) { + if (limit - p < 3) return nullptr; + *shared = reinterpret_cast(p)[0]; + *non_shared = reinterpret_cast(p)[1]; + *value_length = reinterpret_cast(p)[2]; + if ((*shared | *non_shared | *value_length) < 128) { + // Fast path: all three values are encoded in one byte each + p += 3; + } else { + if ((p = GetVarint32Ptr(p, limit, shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, non_shared)) == nullptr) return nullptr; + if ((p = GetVarint32Ptr(p, limit, value_length)) == nullptr) return nullptr; + } + + if (static_cast(limit - p) < (*non_shared + *value_length)) { + return nullptr; + } + return p; +} + +class Block::Iter : public Iterator { + private: + const Comparator* const comparator_; + const char* const data_; // underlying block contents + uint32_t const restarts_; // Offset of restart array (list of fixed32) + uint32_t const num_restarts_; // Number of uint32_t entries in restart array + + // current_ is offset in data_ of current entry. >= restarts_ if !Valid + uint32_t current_; + uint32_t restart_index_; // Index of restart block in which current_ falls + std::string key_; + Slice value_; + Status status_; + + inline int Compare(const Slice& a, const Slice& b) const { + return comparator_->Compare(a, b); + } + + // Return the offset in data_ just past the end of the current entry. + inline uint32_t NextEntryOffset() const { + return (value_.data() + value_.size()) - data_; + } + + uint32_t GetRestartPoint(uint32_t index) { + assert(index < num_restarts_); + return DecodeFixed32(data_ + restarts_ + index * sizeof(uint32_t)); + } + + void SeekToRestartPoint(uint32_t index) { + key_.clear(); + restart_index_ = index; + // current_ will be fixed by ParseNextKey(); + + // ParseNextKey() starts at the end of value_, so set value_ accordingly + uint32_t offset = GetRestartPoint(index); + value_ = Slice(data_ + offset, 0); + } + + public: + Iter(const Comparator* comparator, const char* data, uint32_t restarts, + uint32_t num_restarts) + : comparator_(comparator), + data_(data), + restarts_(restarts), + num_restarts_(num_restarts), + current_(restarts_), + restart_index_(num_restarts_) { + assert(num_restarts_ > 0); + } + + virtual bool Valid() const { return current_ < restarts_; } + virtual Status status() const { return status_; } + virtual Slice key() const { + assert(Valid()); + return key_; + } + virtual Slice value() const { + assert(Valid()); + return value_; + } + + virtual void Next() { + assert(Valid()); + ParseNextKey(); + } + + virtual void Prev() { + assert(Valid()); + + // Scan backwards to a restart point before current_ + const uint32_t original = current_; + while (GetRestartPoint(restart_index_) >= original) { + if (restart_index_ == 0) { + // No more entries + current_ = restarts_; + restart_index_ = num_restarts_; + return; + } + restart_index_--; + } + + SeekToRestartPoint(restart_index_); + do { + // Loop until end of current entry hits the start of original entry + } while (ParseNextKey() && NextEntryOffset() < original); + } + + virtual void Seek(const Slice& target) { + // Binary search in restart array to find the last restart point + // with a key < target + uint32_t left = 0; + uint32_t right = num_restarts_ - 1; + while (left < right) { + uint32_t mid = (left + right + 1) / 2; + uint32_t region_offset = GetRestartPoint(mid); + uint32_t shared, non_shared, value_length; + const char* key_ptr = + DecodeEntry(data_ + region_offset, data_ + restarts_, &shared, + &non_shared, &value_length); + if (key_ptr == nullptr || (shared != 0)) { + CorruptionError(); + return; + } + Slice mid_key(key_ptr, non_shared); + if (Compare(mid_key, target) < 0) { + // Key at "mid" is smaller than "target". Therefore all + // blocks before "mid" are uninteresting. + left = mid; + } else { + // Key at "mid" is >= "target". Therefore all blocks at or + // after "mid" are uninteresting. + right = mid - 1; + } + } + + // Linear search (within restart block) for first key >= target + SeekToRestartPoint(left); + while (true) { + if (!ParseNextKey()) { + return; + } + if (Compare(key_, target) >= 0) { + return; + } + } + } + + virtual void SeekToFirst() { + SeekToRestartPoint(0); + ParseNextKey(); + } + + virtual void SeekToLast() { + SeekToRestartPoint(num_restarts_ - 1); + while (ParseNextKey() && NextEntryOffset() < restarts_) { + // Keep skipping + } + } + + private: + void CorruptionError() { + current_ = restarts_; + restart_index_ = num_restarts_; + status_ = Status::Corruption("bad entry in block"); + key_.clear(); + value_.clear(); + } + + bool ParseNextKey() { + current_ = NextEntryOffset(); + const char* p = data_ + current_; + const char* limit = data_ + restarts_; // Restarts come right after data + if (p >= limit) { + // No more entries to return. Mark as invalid. + current_ = restarts_; + restart_index_ = num_restarts_; + return false; + } + + // Decode next entry + uint32_t shared, non_shared, value_length; + p = DecodeEntry(p, limit, &shared, &non_shared, &value_length); + if (p == nullptr || key_.size() < shared) { + CorruptionError(); + return false; + } else { + key_.resize(shared); + key_.append(p, non_shared); + value_ = Slice(p + non_shared, value_length); + while (restart_index_ + 1 < num_restarts_ && + GetRestartPoint(restart_index_ + 1) < current_) { + ++restart_index_; + } + return true; + } + } +}; + +Iterator* Block::NewIterator(const Comparator* comparator) { + if (size_ < sizeof(uint32_t)) { + return NewErrorIterator(Status::Corruption("bad block contents")); + } + const uint32_t num_restarts = NumRestarts(); + if (num_restarts == 0) { + return NewEmptyIterator(); + } else { + return new Iter(comparator, data_, restart_offset_, num_restarts); + } +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.h new file mode 100644 index 0000000..c8f1f7b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_H_ + +#include +#include + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct BlockContents; +class Comparator; + +class Block { + public: + // Initialize the block with the specified contents. + explicit Block(const BlockContents& contents); + + Block(const Block&) = delete; + Block& operator=(const Block&) = delete; + + ~Block(); + + size_t size() const { return size_; } + Iterator* NewIterator(const Comparator* comparator); + + private: + class Iter; + + uint32_t NumRestarts() const; + + const char* data_; + size_t size_; + uint32_t restart_offset_; // Offset in data_ of restart array + bool owned_; // Block owns data_[] +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.cc new file mode 100644 index 0000000..f7cb1b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.cc @@ -0,0 +1,108 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// BlockBuilder generates blocks where keys are prefix-compressed: +// +// When we store a key, we drop the prefix shared with the previous +// string. This helps reduce the space requirement significantly. +// Furthermore, once every K keys, we do not apply the prefix +// compression and store the entire key. We call this a "restart +// point". The tail end of the block stores the offsets of all of the +// restart points, and can be used to do a binary search when looking +// for a particular key. Values are stored as-is (without compression) +// immediately following the corresponding key. +// +// An entry for a particular key-value pair has the form: +// shared_bytes: varint32 +// unshared_bytes: varint32 +// value_length: varint32 +// key_delta: char[unshared_bytes] +// value: char[value_length] +// shared_bytes == 0 for restart points. +// +// The trailer of the block has the form: +// restarts: uint32[num_restarts] +// num_restarts: uint32 +// restarts[i] contains the offset within the block of the ith restart point. + +#include "table/block_builder.h" + +#include + +#include + +#include "leveldb/comparator.h" +#include "leveldb/table_builder.h" +#include "util/coding.h" + +namespace leveldb { + +BlockBuilder::BlockBuilder(const Options* options) + : options_(options), restarts_(), counter_(0), finished_(false) { + assert(options->block_restart_interval >= 1); + restarts_.push_back(0); // First restart point is at offset 0 +} + +void BlockBuilder::Reset() { + buffer_.clear(); + restarts_.clear(); + restarts_.push_back(0); // First restart point is at offset 0 + counter_ = 0; + finished_ = false; + last_key_.clear(); +} + +size_t BlockBuilder::CurrentSizeEstimate() const { + return (buffer_.size() + // Raw data buffer + restarts_.size() * sizeof(uint32_t) + // Restart array + sizeof(uint32_t)); // Restart array length +} + +Slice BlockBuilder::Finish() { + // Append restart array + for (size_t i = 0; i < restarts_.size(); i++) { + PutFixed32(&buffer_, restarts_[i]); + } + PutFixed32(&buffer_, restarts_.size()); + finished_ = true; + return Slice(buffer_); +} + +void BlockBuilder::Add(const Slice& key, const Slice& value) { + Slice last_key_piece(last_key_); + assert(!finished_); + assert(counter_ <= options_->block_restart_interval); + assert(buffer_.empty() // No values yet? + || options_->comparator->Compare(key, last_key_piece) > 0); + size_t shared = 0; + if (counter_ < options_->block_restart_interval) { + // See how much sharing to do with previous string + const size_t min_length = std::min(last_key_piece.size(), key.size()); + while ((shared < min_length) && (last_key_piece[shared] == key[shared])) { + shared++; + } + } else { + // Restart compression + restarts_.push_back(buffer_.size()); + counter_ = 0; + } + const size_t non_shared = key.size() - shared; + + // Add "" to buffer_ + PutVarint32(&buffer_, shared); + PutVarint32(&buffer_, non_shared); + PutVarint32(&buffer_, value.size()); + + // Add string delta to buffer_ followed by value + buffer_.append(key.data() + shared, non_shared); + buffer_.append(value.data(), value.size()); + + // Update state + last_key_.resize(shared); + last_key_.append(key.data() + shared, non_shared); + assert(Slice(last_key_) == key); + counter_++; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.h new file mode 100644 index 0000000..f91f5e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/block_builder.h @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ +#define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ + +#include + +#include + +#include "leveldb/slice.h" + +namespace leveldb { + +struct Options; + +class BlockBuilder { + public: + explicit BlockBuilder(const Options* options); + + BlockBuilder(const BlockBuilder&) = delete; + BlockBuilder& operator=(const BlockBuilder&) = delete; + + // Reset the contents as if the BlockBuilder was just constructed. + void Reset(); + + // REQUIRES: Finish() has not been called since the last call to Reset(). + // REQUIRES: key is larger than any previously added key + void Add(const Slice& key, const Slice& value); + + // Finish building the block and return a slice that refers to the + // block contents. The returned slice will remain valid for the + // lifetime of this builder or until Reset() is called. + Slice Finish(); + + // Returns an estimate of the current (uncompressed) size of the block + // we are building. + size_t CurrentSizeEstimate() const; + + // Return true iff no entries have been added since the last Reset() + bool empty() const { return buffer_.empty(); } + + private: + const Options* options_; + std::string buffer_; // Destination buffer + std::vector restarts_; // Restart points + int counter_; // Number of entries emitted since restart + bool finished_; // Has Finish() been called? + std::string last_key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.cc new file mode 100644 index 0000000..09ec009 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.cc @@ -0,0 +1,106 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/filter_block.h" + +#include "leveldb/filter_policy.h" +#include "util/coding.h" + +namespace leveldb { + +// See doc/table_format.md for an explanation of the filter block format. + +// Generate new filter every 2KB of data +static const size_t kFilterBaseLg = 11; +static const size_t kFilterBase = 1 << kFilterBaseLg; + +FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy) + : policy_(policy) {} + +void FilterBlockBuilder::StartBlock(uint64_t block_offset) { + uint64_t filter_index = (block_offset / kFilterBase); + assert(filter_index >= filter_offsets_.size()); + while (filter_index > filter_offsets_.size()) { + GenerateFilter(); + } +} + +void FilterBlockBuilder::AddKey(const Slice& key) { + Slice k = key; + start_.push_back(keys_.size()); + keys_.append(k.data(), k.size()); +} + +Slice FilterBlockBuilder::Finish() { + if (!start_.empty()) { + GenerateFilter(); + } + + // Append array of per-filter offsets + const uint32_t array_offset = result_.size(); + for (size_t i = 0; i < filter_offsets_.size(); i++) { + PutFixed32(&result_, filter_offsets_[i]); + } + + PutFixed32(&result_, array_offset); + result_.push_back(kFilterBaseLg); // Save encoding parameter in result + return Slice(result_); +} + +void FilterBlockBuilder::GenerateFilter() { + const size_t num_keys = start_.size(); + if (num_keys == 0) { + // Fast path if there are no keys for this filter + filter_offsets_.push_back(result_.size()); + return; + } + + // Make list of keys from flattened key structure + start_.push_back(keys_.size()); // Simplify length computation + tmp_keys_.resize(num_keys); + for (size_t i = 0; i < num_keys; i++) { + const char* base = keys_.data() + start_[i]; + size_t length = start_[i + 1] - start_[i]; + tmp_keys_[i] = Slice(base, length); + } + + // Generate filter for current set of keys and append to result_. + filter_offsets_.push_back(result_.size()); + policy_->CreateFilter(&tmp_keys_[0], static_cast(num_keys), &result_); + + tmp_keys_.clear(); + keys_.clear(); + start_.clear(); +} + +FilterBlockReader::FilterBlockReader(const FilterPolicy* policy, + const Slice& contents) + : policy_(policy), data_(nullptr), offset_(nullptr), num_(0), base_lg_(0) { + size_t n = contents.size(); + if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array + base_lg_ = contents[n - 1]; + uint32_t last_word = DecodeFixed32(contents.data() + n - 5); + if (last_word > n - 5) return; + data_ = contents.data(); + offset_ = data_ + last_word; + num_ = (n - 5 - last_word) / 4; +} + +bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) { + uint64_t index = block_offset >> base_lg_; + if (index < num_) { + uint32_t start = DecodeFixed32(offset_ + index * 4); + uint32_t limit = DecodeFixed32(offset_ + index * 4 + 4); + if (start <= limit && limit <= static_cast(offset_ - data_)) { + Slice filter = Slice(data_ + start, limit - start); + return policy_->KeyMayMatch(key, filter); + } else if (start == limit) { + // Empty filters do not match any keys + return false; + } + } + return true; // Errors are treated as potential matches +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.h new file mode 100644 index 0000000..73b5399 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/filter_block.h @@ -0,0 +1,69 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A filter block is stored near the end of a Table file. It contains +// filters (e.g., bloom filters) for all data blocks in the table combined +// into a single filter block. + +#ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ +#define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ + +#include +#include + +#include +#include + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +class FilterPolicy; + +// A FilterBlockBuilder is used to construct all of the filters for a +// particular Table. It generates a single string which is stored as +// a special block in the Table. +// +// The sequence of calls to FilterBlockBuilder must match the regexp: +// (StartBlock AddKey*)* Finish +class FilterBlockBuilder { + public: + explicit FilterBlockBuilder(const FilterPolicy*); + + FilterBlockBuilder(const FilterBlockBuilder&) = delete; + FilterBlockBuilder& operator=(const FilterBlockBuilder&) = delete; + + void StartBlock(uint64_t block_offset); + void AddKey(const Slice& key); + Slice Finish(); + + private: + void GenerateFilter(); + + const FilterPolicy* policy_; + std::string keys_; // Flattened key contents + std::vector start_; // Starting index in keys_ of each key + std::string result_; // Filter data computed so far + std::vector tmp_keys_; // policy_->CreateFilter() argument + std::vector filter_offsets_; +}; + +class FilterBlockReader { + public: + // REQUIRES: "contents" and *policy must stay live while *this is live. + FilterBlockReader(const FilterPolicy* policy, const Slice& contents); + bool KeyMayMatch(uint64_t block_offset, const Slice& key); + + private: + const FilterPolicy* policy_; + const char* data_; // Pointer to filter data (at block-start) + const char* offset_; // Pointer to beginning of offset array (at block-end) + size_t num_; // Number of entries in offset array + size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file) +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.cc new file mode 100644 index 0000000..e183977 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/format.h" + +#include "leveldb/env.h" +#include "port/port.h" +#include "table/block.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +void BlockHandle::EncodeTo(std::string* dst) const { + // Sanity check that all fields have been set + assert(offset_ != ~static_cast(0)); + assert(size_ != ~static_cast(0)); + PutVarint64(dst, offset_); + PutVarint64(dst, size_); +} + +Status BlockHandle::DecodeFrom(Slice* input) { + if (GetVarint64(input, &offset_) && GetVarint64(input, &size_)) { + return Status::OK(); + } else { + return Status::Corruption("bad block handle"); + } +} + +void Footer::EncodeTo(std::string* dst) const { + const size_t original_size = dst->size(); + metaindex_handle_.EncodeTo(dst); + index_handle_.EncodeTo(dst); + dst->resize(2 * BlockHandle::kMaxEncodedLength); // Padding + PutFixed32(dst, static_cast(kTableMagicNumber & 0xffffffffu)); + PutFixed32(dst, static_cast(kTableMagicNumber >> 32)); + assert(dst->size() == original_size + kEncodedLength); + (void)original_size; // Disable unused variable warning. +} + +Status Footer::DecodeFrom(Slice* input) { + const char* magic_ptr = input->data() + kEncodedLength - 8; + const uint32_t magic_lo = DecodeFixed32(magic_ptr); + const uint32_t magic_hi = DecodeFixed32(magic_ptr + 4); + const uint64_t magic = ((static_cast(magic_hi) << 32) | + (static_cast(magic_lo))); + if (magic != kTableMagicNumber) { + return Status::Corruption("not an sstable (bad magic number)"); + } + + Status result = metaindex_handle_.DecodeFrom(input); + if (result.ok()) { + result = index_handle_.DecodeFrom(input); + } + if (result.ok()) { + // We skip over any leftover data (just padding for now) in "input" + const char* end = magic_ptr + 8; + *input = Slice(end, input->data() + input->size() - end); + } + return result; +} + +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result) { + result->data = Slice(); + result->cachable = false; + result->heap_allocated = false; + + // Read the block contents as well as the type/crc footer. + // See table_builder.cc for the code that built this structure. + size_t n = static_cast(handle.size()); + char* buf = new char[n + kBlockTrailerSize]; + Slice contents; + Status s = file->Read(handle.offset(), n + kBlockTrailerSize, &contents, buf); + if (!s.ok()) { + delete[] buf; + return s; + } + if (contents.size() != n + kBlockTrailerSize) { + delete[] buf; + return Status::Corruption("truncated block read"); + } + + // Check the crc of the type and the block contents + const char* data = contents.data(); // Pointer to where Read put the data + if (options.verify_checksums) { + const uint32_t crc = crc32c::Unmask(DecodeFixed32(data + n + 1)); + const uint32_t actual = crc32c::Value(data, n + 1); + if (actual != crc) { + delete[] buf; + s = Status::Corruption("block checksum mismatch"); + return s; + } + } + + switch (data[n]) { + case kNoCompression: + if (data != buf) { + // File implementation gave us pointer to some other data. + // Use it directly under the assumption that it will be live + // while the file is open. + delete[] buf; + result->data = Slice(data, n); + result->heap_allocated = false; + result->cachable = false; // Do not double-cache + } else { + result->data = Slice(buf, n); + result->heap_allocated = true; + result->cachable = true; + } + + // Ok + break; + case kSnappyCompression: { + size_t ulength = 0; + if (!port::Snappy_GetUncompressedLength(data, n, &ulength)) { + delete[] buf; + return Status::Corruption("corrupted compressed block contents"); + } + char* ubuf = new char[ulength]; + if (!port::Snappy_Uncompress(data, n, ubuf)) { + delete[] buf; + delete[] ubuf; + return Status::Corruption("corrupted compressed block contents"); + } + delete[] buf; + result->data = Slice(ubuf, ulength); + result->heap_allocated = true; + result->cachable = true; + break; + } + default: + delete[] buf; + return Status::Corruption("bad block type"); + } + + return Status::OK(); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.h new file mode 100644 index 0000000..2ad145c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/format.h @@ -0,0 +1,100 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_FORMAT_H_ +#define STORAGE_LEVELDB_TABLE_FORMAT_H_ + +#include + +#include + +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "leveldb/table_builder.h" + +namespace leveldb { + +class Block; +class RandomAccessFile; +struct ReadOptions; + +// BlockHandle is a pointer to the extent of a file that stores a data +// block or a meta block. +class BlockHandle { + public: + // Maximum encoding length of a BlockHandle + enum { kMaxEncodedLength = 10 + 10 }; + + BlockHandle(); + + // The offset of the block in the file. + uint64_t offset() const { return offset_; } + void set_offset(uint64_t offset) { offset_ = offset; } + + // The size of the stored block + uint64_t size() const { return size_; } + void set_size(uint64_t size) { size_ = size; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + uint64_t offset_; + uint64_t size_; +}; + +// Footer encapsulates the fixed information stored at the tail +// end of every table file. +class Footer { + public: + // Encoded length of a Footer. Note that the serialization of a + // Footer will always occupy exactly this many bytes. It consists + // of two block handles and a magic number. + enum { kEncodedLength = 2 * BlockHandle::kMaxEncodedLength + 8 }; + + Footer() {} + + // The block handle for the metaindex block of the table + const BlockHandle& metaindex_handle() const { return metaindex_handle_; } + void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; } + + // The block handle for the index block of the table + const BlockHandle& index_handle() const { return index_handle_; } + void set_index_handle(const BlockHandle& h) { index_handle_ = h; } + + void EncodeTo(std::string* dst) const; + Status DecodeFrom(Slice* input); + + private: + BlockHandle metaindex_handle_; + BlockHandle index_handle_; +}; + +// kTableMagicNumber was picked by running +// echo http://code.google.com/p/leveldb/ | sha1sum +// and taking the leading 64 bits. +static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull; + +// 1-byte type + 32-bit crc +static const size_t kBlockTrailerSize = 5; + +struct BlockContents { + Slice data; // Actual contents of data + bool cachable; // True iff data can be cached + bool heap_allocated; // True iff caller should delete[] data.data() +}; + +// Read the block identified by "handle" from "file". On failure +// return non-OK. On success fill *result and return OK. +Status ReadBlock(RandomAccessFile* file, const ReadOptions& options, + const BlockHandle& handle, BlockContents* result); + +// Implementation details follow. Clients should ignore, + +inline BlockHandle::BlockHandle() + : offset_(~static_cast(0)), size_(~static_cast(0)) {} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_FORMAT_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator.cc new file mode 100644 index 0000000..dfef083 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator.cc @@ -0,0 +1,76 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/iterator.h" + +namespace leveldb { + +Iterator::Iterator() { + cleanup_head_.function = nullptr; + cleanup_head_.next = nullptr; +} + +Iterator::~Iterator() { + if (!cleanup_head_.IsEmpty()) { + cleanup_head_.Run(); + for (CleanupNode* node = cleanup_head_.next; node != nullptr;) { + node->Run(); + CleanupNode* next_node = node->next; + delete node; + node = next_node; + } + } +} + +void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) { + assert(func != nullptr); + CleanupNode* node; + if (cleanup_head_.IsEmpty()) { + node = &cleanup_head_; + } else { + node = new CleanupNode(); + node->next = cleanup_head_.next; + cleanup_head_.next = node; + } + node->function = func; + node->arg1 = arg1; + node->arg2 = arg2; +} + +namespace { + +class EmptyIterator : public Iterator { + public: + EmptyIterator(const Status& s) : status_(s) {} + ~EmptyIterator() override = default; + + bool Valid() const override { return false; } + void Seek(const Slice& target) override {} + void SeekToFirst() override {} + void SeekToLast() override {} + void Next() override { assert(false); } + void Prev() override { assert(false); } + Slice key() const override { + assert(false); + return Slice(); + } + Slice value() const override { + assert(false); + return Slice(); + } + Status status() const override { return status_; } + + private: + Status status_; +}; + +} // anonymous namespace + +Iterator* NewEmptyIterator() { return new EmptyIterator(Status::OK()); } + +Iterator* NewErrorIterator(const Status& status) { + return new EmptyIterator(status); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator_wrapper.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator_wrapper.h new file mode 100644 index 0000000..c230572 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/iterator_wrapper.h @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ +#define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ + +#include "leveldb/iterator.h" +#include "leveldb/slice.h" + +namespace leveldb { + +// A internal wrapper class with an interface similar to Iterator that +// caches the valid() and key() results for an underlying iterator. +// This can help avoid virtual function calls and also gives better +// cache locality. +class IteratorWrapper { + public: + IteratorWrapper() : iter_(nullptr), valid_(false) {} + explicit IteratorWrapper(Iterator* iter) : iter_(nullptr) { Set(iter); } + ~IteratorWrapper() { delete iter_; } + Iterator* iter() const { return iter_; } + + // Takes ownership of "iter" and will delete it when destroyed, or + // when Set() is invoked again. + void Set(Iterator* iter) { + delete iter_; + iter_ = iter; + if (iter_ == nullptr) { + valid_ = false; + } else { + Update(); + } + } + + // Iterator interface methods + bool Valid() const { return valid_; } + Slice key() const { + assert(Valid()); + return key_; + } + Slice value() const { + assert(Valid()); + return iter_->value(); + } + // Methods below require iter() != nullptr + Status status() const { + assert(iter_); + return iter_->status(); + } + void Next() { + assert(iter_); + iter_->Next(); + Update(); + } + void Prev() { + assert(iter_); + iter_->Prev(); + Update(); + } + void Seek(const Slice& k) { + assert(iter_); + iter_->Seek(k); + Update(); + } + void SeekToFirst() { + assert(iter_); + iter_->SeekToFirst(); + Update(); + } + void SeekToLast() { + assert(iter_); + iter_->SeekToLast(); + Update(); + } + + private: + void Update() { + valid_ = iter_->Valid(); + if (valid_) { + key_ = iter_->key(); + } + } + + Iterator* iter_; + bool valid_; + Slice key_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.cc new file mode 100644 index 0000000..1bbc6cf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.cc @@ -0,0 +1,191 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/merger.h" + +#include "leveldb/comparator.h" +#include "leveldb/iterator.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { +class MergingIterator : public Iterator { + public: + MergingIterator(const Comparator* comparator, Iterator** children, int n) + : comparator_(comparator), + children_(new IteratorWrapper[n]), + n_(n), + current_(nullptr), + direction_(kForward) { + for (int i = 0; i < n; i++) { + children_[i].Set(children[i]); + } + } + + virtual ~MergingIterator() { delete[] children_; } + + virtual bool Valid() const { return (current_ != nullptr); } + + virtual void SeekToFirst() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToFirst(); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void SeekToLast() { + for (int i = 0; i < n_; i++) { + children_[i].SeekToLast(); + } + FindLargest(); + direction_ = kReverse; + } + + virtual void Seek(const Slice& target) { + for (int i = 0; i < n_; i++) { + children_[i].Seek(target); + } + FindSmallest(); + direction_ = kForward; + } + + virtual void Next() { + assert(Valid()); + + // Ensure that all children are positioned after key(). + // If we are moving in the forward direction, it is already + // true for all of the non-current_ children since current_ is + // the smallest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kForward) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid() && + comparator_->Compare(key(), child->key()) == 0) { + child->Next(); + } + } + } + direction_ = kForward; + } + + current_->Next(); + FindSmallest(); + } + + virtual void Prev() { + assert(Valid()); + + // Ensure that all children are positioned before key(). + // If we are moving in the reverse direction, it is already + // true for all of the non-current_ children since current_ is + // the largest child and key() == current_->key(). Otherwise, + // we explicitly position the non-current_ children. + if (direction_ != kReverse) { + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child != current_) { + child->Seek(key()); + if (child->Valid()) { + // Child is at first entry >= key(). Step back one to be < key() + child->Prev(); + } else { + // Child has no entries >= key(). Position at last entry. + child->SeekToLast(); + } + } + } + direction_ = kReverse; + } + + current_->Prev(); + FindLargest(); + } + + virtual Slice key() const { + assert(Valid()); + return current_->key(); + } + + virtual Slice value() const { + assert(Valid()); + return current_->value(); + } + + virtual Status status() const { + Status status; + for (int i = 0; i < n_; i++) { + status = children_[i].status(); + if (!status.ok()) { + break; + } + } + return status; + } + + private: + // Which direction is the iterator moving? + enum Direction { kForward, kReverse }; + + void FindSmallest(); + void FindLargest(); + + // We might want to use a heap in case there are lots of children. + // For now we use a simple array since we expect a very small number + // of children in leveldb. + const Comparator* comparator_; + IteratorWrapper* children_; + int n_; + IteratorWrapper* current_; + Direction direction_; +}; + +void MergingIterator::FindSmallest() { + IteratorWrapper* smallest = nullptr; + for (int i = 0; i < n_; i++) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (smallest == nullptr) { + smallest = child; + } else if (comparator_->Compare(child->key(), smallest->key()) < 0) { + smallest = child; + } + } + } + current_ = smallest; +} + +void MergingIterator::FindLargest() { + IteratorWrapper* largest = nullptr; + for (int i = n_ - 1; i >= 0; i--) { + IteratorWrapper* child = &children_[i]; + if (child->Valid()) { + if (largest == nullptr) { + largest = child; + } else if (comparator_->Compare(child->key(), largest->key()) > 0) { + largest = child; + } + } + } + current_ = largest; +} +} // namespace + +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n) { + assert(n >= 0); + if (n == 0) { + return NewEmptyIterator(); + } else if (n == 1) { + return children[0]; + } else { + return new MergingIterator(comparator, children, n); + } +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.h new file mode 100644 index 0000000..41cedc5 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/merger.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_MERGER_H_ +#define STORAGE_LEVELDB_TABLE_MERGER_H_ + +namespace leveldb { + +class Comparator; +class Iterator; + +// Return an iterator that provided the union of the data in +// children[0,n-1]. Takes ownership of the child iterators and +// will delete them when the result iterator is deleted. +// +// The result does no duplicate suppression. I.e., if a particular +// key is present in K child iterators, it will be yielded K times. +// +// REQUIRES: n >= 0 +Iterator* NewMergingIterator(const Comparator* comparator, Iterator** children, + int n); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_MERGER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table.cc new file mode 100644 index 0000000..b07bc88 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table.cc @@ -0,0 +1,273 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table.h" + +#include "leveldb/cache.h" +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "table/two_level_iterator.h" +#include "util/coding.h" + +namespace leveldb { + +struct Table::Rep { + ~Rep() { + delete filter; + delete[] filter_data; + delete index_block; + } + + Options options; + Status status; + RandomAccessFile* file; + uint64_t cache_id; + FilterBlockReader* filter; + const char* filter_data; + + BlockHandle metaindex_handle; // Handle to metaindex_block: saved from footer + Block* index_block; +}; + +Status Table::Open(const Options& options, RandomAccessFile* file, + uint64_t size, Table** table) { + *table = nullptr; + if (size < Footer::kEncodedLength) { + return Status::Corruption("file is too short to be an sstable"); + } + + char footer_space[Footer::kEncodedLength]; + Slice footer_input; + Status s = file->Read(size - Footer::kEncodedLength, Footer::kEncodedLength, + &footer_input, footer_space); + if (!s.ok()) return s; + + Footer footer; + s = footer.DecodeFrom(&footer_input); + if (!s.ok()) return s; + + // Read the index block + BlockContents index_block_contents; + if (s.ok()) { + ReadOptions opt; + if (options.paranoid_checks) { + opt.verify_checksums = true; + } + s = ReadBlock(file, opt, footer.index_handle(), &index_block_contents); + } + + if (s.ok()) { + // We've successfully read the footer and the index block: we're + // ready to serve requests. + Block* index_block = new Block(index_block_contents); + Rep* rep = new Table::Rep; + rep->options = options; + rep->file = file; + rep->metaindex_handle = footer.metaindex_handle(); + rep->index_block = index_block; + rep->cache_id = (options.block_cache ? options.block_cache->NewId() : 0); + rep->filter_data = nullptr; + rep->filter = nullptr; + *table = new Table(rep); + (*table)->ReadMeta(footer); + } + + return s; +} + +void Table::ReadMeta(const Footer& footer) { + if (rep_->options.filter_policy == nullptr) { + return; // Do not need any metadata + } + + // TODO(sanjay): Skip this if footer.metaindex_handle() size indicates + // it is an empty block. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents contents; + if (!ReadBlock(rep_->file, opt, footer.metaindex_handle(), &contents).ok()) { + // Do not propagate errors since meta info is not needed for operation + return; + } + Block* meta = new Block(contents); + + Iterator* iter = meta->NewIterator(BytewiseComparator()); + std::string key = "filter."; + key.append(rep_->options.filter_policy->Name()); + iter->Seek(key); + if (iter->Valid() && iter->key() == Slice(key)) { + ReadFilter(iter->value()); + } + delete iter; + delete meta; +} + +void Table::ReadFilter(const Slice& filter_handle_value) { + Slice v = filter_handle_value; + BlockHandle filter_handle; + if (!filter_handle.DecodeFrom(&v).ok()) { + return; + } + + // We might want to unify with ReadBlock() if we start + // requiring checksum verification in Table::Open. + ReadOptions opt; + if (rep_->options.paranoid_checks) { + opt.verify_checksums = true; + } + BlockContents block; + if (!ReadBlock(rep_->file, opt, filter_handle, &block).ok()) { + return; + } + if (block.heap_allocated) { + rep_->filter_data = block.data.data(); // Will need to delete later + } + rep_->filter = new FilterBlockReader(rep_->options.filter_policy, block.data); +} + +Table::~Table() { delete rep_; } + +static void DeleteBlock(void* arg, void* ignored) { + delete reinterpret_cast(arg); +} + +static void DeleteCachedBlock(const Slice& key, void* value) { + Block* block = reinterpret_cast(value); + delete block; +} + +static void ReleaseBlock(void* arg, void* h) { + Cache* cache = reinterpret_cast(arg); + Cache::Handle* handle = reinterpret_cast(h); + cache->Release(handle); +} + +// Convert an index iterator value (i.e., an encoded BlockHandle) +// into an iterator over the contents of the corresponding block. +Iterator* Table::BlockReader(void* arg, const ReadOptions& options, + const Slice& index_value) { + Table* table = reinterpret_cast(arg); + Cache* block_cache = table->rep_->options.block_cache; + Block* block = nullptr; + Cache::Handle* cache_handle = nullptr; + + BlockHandle handle; + Slice input = index_value; + Status s = handle.DecodeFrom(&input); + // We intentionally allow extra stuff in index_value so that we + // can add more features in the future. + + if (s.ok()) { + BlockContents contents; + if (block_cache != nullptr) { + char cache_key_buffer[16]; + EncodeFixed64(cache_key_buffer, table->rep_->cache_id); + EncodeFixed64(cache_key_buffer + 8, handle.offset()); + Slice key(cache_key_buffer, sizeof(cache_key_buffer)); + cache_handle = block_cache->Lookup(key); + if (cache_handle != nullptr) { + block = reinterpret_cast(block_cache->Value(cache_handle)); + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + if (contents.cachable && options.fill_cache) { + cache_handle = block_cache->Insert(key, block, block->size(), + &DeleteCachedBlock); + } + } + } + } else { + s = ReadBlock(table->rep_->file, options, handle, &contents); + if (s.ok()) { + block = new Block(contents); + } + } + } + + Iterator* iter; + if (block != nullptr) { + iter = block->NewIterator(table->rep_->options.comparator); + if (cache_handle == nullptr) { + iter->RegisterCleanup(&DeleteBlock, block, nullptr); + } else { + iter->RegisterCleanup(&ReleaseBlock, block_cache, cache_handle); + } + } else { + iter = NewErrorIterator(s); + } + return iter; +} + +Iterator* Table::NewIterator(const ReadOptions& options) const { + return NewTwoLevelIterator( + rep_->index_block->NewIterator(rep_->options.comparator), + &Table::BlockReader, const_cast(this), options); +} + +Status Table::InternalGet(const ReadOptions& options, const Slice& k, void* arg, + void (*handle_result)(void*, const Slice&, + const Slice&)) { + Status s; + Iterator* iiter = rep_->index_block->NewIterator(rep_->options.comparator); + iiter->Seek(k); + if (iiter->Valid()) { + Slice handle_value = iiter->value(); + FilterBlockReader* filter = rep_->filter; + BlockHandle handle; + if (filter != nullptr && handle.DecodeFrom(&handle_value).ok() && + !filter->KeyMayMatch(handle.offset(), k)) { + // Not found + } else { + Iterator* block_iter = BlockReader(this, options, iiter->value()); + block_iter->Seek(k); + if (block_iter->Valid()) { + (*handle_result)(arg, block_iter->key(), block_iter->value()); + } + s = block_iter->status(); + delete block_iter; + } + } + if (s.ok()) { + s = iiter->status(); + } + delete iiter; + return s; +} + +uint64_t Table::ApproximateOffsetOf(const Slice& key) const { + Iterator* index_iter = + rep_->index_block->NewIterator(rep_->options.comparator); + index_iter->Seek(key); + uint64_t result; + if (index_iter->Valid()) { + BlockHandle handle; + Slice input = index_iter->value(); + Status s = handle.DecodeFrom(&input); + if (s.ok()) { + result = handle.offset(); + } else { + // Strange: we can't decode the block handle in the index block. + // We'll just return the offset of the metaindex block, which is + // close to the whole file size for this case. + result = rep_->metaindex_handle.offset(); + } + } else { + // key is past the last key in the file. Approximate the offset + // by returning the offset of the metaindex block (which is + // right near the end of the file). + result = rep_->metaindex_handle.offset(); + } + delete index_iter; + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table_builder.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table_builder.cc new file mode 100644 index 0000000..278febf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/table_builder.cc @@ -0,0 +1,265 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/table_builder.h" + +#include + +#include "leveldb/comparator.h" +#include "leveldb/env.h" +#include "leveldb/filter_policy.h" +#include "leveldb/options.h" +#include "table/block_builder.h" +#include "table/filter_block.h" +#include "table/format.h" +#include "util/coding.h" +#include "util/crc32c.h" + +namespace leveldb { + +struct TableBuilder::Rep { + Rep(const Options& opt, WritableFile* f) + : options(opt), + index_block_options(opt), + file(f), + offset(0), + data_block(&options), + index_block(&index_block_options), + num_entries(0), + closed(false), + filter_block(opt.filter_policy == nullptr + ? nullptr + : new FilterBlockBuilder(opt.filter_policy)), + pending_index_entry(false) { + index_block_options.block_restart_interval = 1; + } + + Options options; + Options index_block_options; + WritableFile* file; + uint64_t offset; + Status status; + BlockBuilder data_block; + BlockBuilder index_block; + std::string last_key; + int64_t num_entries; + bool closed; // Either Finish() or Abandon() has been called. + FilterBlockBuilder* filter_block; + + // We do not emit the index entry for a block until we have seen the + // first key for the next data block. This allows us to use shorter + // keys in the index block. For example, consider a block boundary + // between the keys "the quick brown fox" and "the who". We can use + // "the r" as the key for the index block entry since it is >= all + // entries in the first block and < all entries in subsequent + // blocks. + // + // Invariant: r->pending_index_entry is true only if data_block is empty. + bool pending_index_entry; + BlockHandle pending_handle; // Handle to add to index block + + std::string compressed_output; +}; + +TableBuilder::TableBuilder(const Options& options, WritableFile* file) + : rep_(new Rep(options, file)) { + if (rep_->filter_block != nullptr) { + rep_->filter_block->StartBlock(0); + } +} + +TableBuilder::~TableBuilder() { + assert(rep_->closed); // Catch errors where caller forgot to call Finish() + delete rep_->filter_block; + delete rep_; +} + +Status TableBuilder::ChangeOptions(const Options& options) { + // Note: if more fields are added to Options, update + // this function to catch changes that should not be allowed to + // change in the middle of building a Table. + if (options.comparator != rep_->options.comparator) { + return Status::InvalidArgument("changing comparator while building table"); + } + + // Note that any live BlockBuilders point to rep_->options and therefore + // will automatically pick up the updated options. + rep_->options = options; + rep_->index_block_options = options; + rep_->index_block_options.block_restart_interval = 1; + return Status::OK(); +} + +void TableBuilder::Add(const Slice& key, const Slice& value) { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->num_entries > 0) { + assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); + } + + if (r->pending_index_entry) { + assert(r->data_block.empty()); + r->options.comparator->FindShortestSeparator(&r->last_key, key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + + if (r->filter_block != nullptr) { + r->filter_block->AddKey(key); + } + + r->last_key.assign(key.data(), key.size()); + r->num_entries++; + r->data_block.Add(key, value); + + const size_t estimated_block_size = r->data_block.CurrentSizeEstimate(); + if (estimated_block_size >= r->options.block_size) { + Flush(); + } +} + +void TableBuilder::Flush() { + Rep* r = rep_; + assert(!r->closed); + if (!ok()) return; + if (r->data_block.empty()) return; + assert(!r->pending_index_entry); + WriteBlock(&r->data_block, &r->pending_handle); + if (ok()) { + r->pending_index_entry = true; + r->status = r->file->Flush(); + } + if (r->filter_block != nullptr) { + r->filter_block->StartBlock(r->offset); + } +} + +void TableBuilder::WriteBlock(BlockBuilder* block, BlockHandle* handle) { + // File format contains a sequence of blocks where each block has: + // block_data: uint8[n] + // type: uint8 + // crc: uint32 + assert(ok()); + Rep* r = rep_; + Slice raw = block->Finish(); + + Slice block_contents; + CompressionType type = r->options.compression; + // TODO(postrelease): Support more compression options: zlib? + switch (type) { + case kNoCompression: + block_contents = raw; + break; + + case kSnappyCompression: { + std::string* compressed = &r->compressed_output; + if (port::Snappy_Compress(raw.data(), raw.size(), compressed) && + compressed->size() < raw.size() - (raw.size() / 8u)) { + block_contents = *compressed; + } else { + // Snappy not supported, or compressed less than 12.5%, so just + // store uncompressed form + block_contents = raw; + type = kNoCompression; + } + break; + } + } + WriteRawBlock(block_contents, type, handle); + r->compressed_output.clear(); + block->Reset(); +} + +void TableBuilder::WriteRawBlock(const Slice& block_contents, + CompressionType type, BlockHandle* handle) { + Rep* r = rep_; + handle->set_offset(r->offset); + handle->set_size(block_contents.size()); + r->status = r->file->Append(block_contents); + if (r->status.ok()) { + char trailer[kBlockTrailerSize]; + trailer[0] = type; + uint32_t crc = crc32c::Value(block_contents.data(), block_contents.size()); + crc = crc32c::Extend(crc, trailer, 1); // Extend crc to cover block type + EncodeFixed32(trailer + 1, crc32c::Mask(crc)); + r->status = r->file->Append(Slice(trailer, kBlockTrailerSize)); + if (r->status.ok()) { + r->offset += block_contents.size() + kBlockTrailerSize; + } + } +} + +Status TableBuilder::status() const { return rep_->status; } + +Status TableBuilder::Finish() { + Rep* r = rep_; + Flush(); + assert(!r->closed); + r->closed = true; + + BlockHandle filter_block_handle, metaindex_block_handle, index_block_handle; + + // Write filter block + if (ok() && r->filter_block != nullptr) { + WriteRawBlock(r->filter_block->Finish(), kNoCompression, + &filter_block_handle); + } + + // Write metaindex block + if (ok()) { + BlockBuilder meta_index_block(&r->options); + if (r->filter_block != nullptr) { + // Add mapping from "filter.Name" to location of filter data + std::string key = "filter."; + key.append(r->options.filter_policy->Name()); + std::string handle_encoding; + filter_block_handle.EncodeTo(&handle_encoding); + meta_index_block.Add(key, handle_encoding); + } + + // TODO(postrelease): Add stats and other meta blocks + WriteBlock(&meta_index_block, &metaindex_block_handle); + } + + // Write index block + if (ok()) { + if (r->pending_index_entry) { + r->options.comparator->FindShortSuccessor(&r->last_key); + std::string handle_encoding; + r->pending_handle.EncodeTo(&handle_encoding); + r->index_block.Add(r->last_key, Slice(handle_encoding)); + r->pending_index_entry = false; + } + WriteBlock(&r->index_block, &index_block_handle); + } + + // Write footer + if (ok()) { + Footer footer; + footer.set_metaindex_handle(metaindex_block_handle); + footer.set_index_handle(index_block_handle); + std::string footer_encoding; + footer.EncodeTo(&footer_encoding); + r->status = r->file->Append(footer_encoding); + if (r->status.ok()) { + r->offset += footer_encoding.size(); + } + } + return r->status; +} + +void TableBuilder::Abandon() { + Rep* r = rep_; + assert(!r->closed); + r->closed = true; +} + +uint64_t TableBuilder::NumEntries() const { return rep_->num_entries; } + +uint64_t TableBuilder::FileSize() const { return rep_->offset; } + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.cc new file mode 100644 index 0000000..5340a4d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.cc @@ -0,0 +1,171 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "table/two_level_iterator.h" + +#include "leveldb/table.h" +#include "table/block.h" +#include "table/format.h" +#include "table/iterator_wrapper.h" + +namespace leveldb { + +namespace { + +typedef Iterator* (*BlockFunction)(void*, const ReadOptions&, const Slice&); + +class TwoLevelIterator : public Iterator { + public: + TwoLevelIterator(Iterator* index_iter, BlockFunction block_function, + void* arg, const ReadOptions& options); + + virtual ~TwoLevelIterator(); + + virtual void Seek(const Slice& target); + virtual void SeekToFirst(); + virtual void SeekToLast(); + virtual void Next(); + virtual void Prev(); + + virtual bool Valid() const { return data_iter_.Valid(); } + virtual Slice key() const { + assert(Valid()); + return data_iter_.key(); + } + virtual Slice value() const { + assert(Valid()); + return data_iter_.value(); + } + virtual Status status() const { + // It'd be nice if status() returned a const Status& instead of a Status + if (!index_iter_.status().ok()) { + return index_iter_.status(); + } else if (data_iter_.iter() != nullptr && !data_iter_.status().ok()) { + return data_iter_.status(); + } else { + return status_; + } + } + + private: + void SaveError(const Status& s) { + if (status_.ok() && !s.ok()) status_ = s; + } + void SkipEmptyDataBlocksForward(); + void SkipEmptyDataBlocksBackward(); + void SetDataIterator(Iterator* data_iter); + void InitDataBlock(); + + BlockFunction block_function_; + void* arg_; + const ReadOptions options_; + Status status_; + IteratorWrapper index_iter_; + IteratorWrapper data_iter_; // May be nullptr + // If data_iter_ is non-null, then "data_block_handle_" holds the + // "index_value" passed to block_function_ to create the data_iter_. + std::string data_block_handle_; +}; + +TwoLevelIterator::TwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) + : block_function_(block_function), + arg_(arg), + options_(options), + index_iter_(index_iter), + data_iter_(nullptr) {} + +TwoLevelIterator::~TwoLevelIterator() {} + +void TwoLevelIterator::Seek(const Slice& target) { + index_iter_.Seek(target); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.Seek(target); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToFirst() { + index_iter_.SeekToFirst(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::SeekToLast() { + index_iter_.SeekToLast(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::Next() { + assert(Valid()); + data_iter_.Next(); + SkipEmptyDataBlocksForward(); +} + +void TwoLevelIterator::Prev() { + assert(Valid()); + data_iter_.Prev(); + SkipEmptyDataBlocksBackward(); +} + +void TwoLevelIterator::SkipEmptyDataBlocksForward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Next(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToFirst(); + } +} + +void TwoLevelIterator::SkipEmptyDataBlocksBackward() { + while (data_iter_.iter() == nullptr || !data_iter_.Valid()) { + // Move to next block + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + return; + } + index_iter_.Prev(); + InitDataBlock(); + if (data_iter_.iter() != nullptr) data_iter_.SeekToLast(); + } +} + +void TwoLevelIterator::SetDataIterator(Iterator* data_iter) { + if (data_iter_.iter() != nullptr) SaveError(data_iter_.status()); + data_iter_.Set(data_iter); +} + +void TwoLevelIterator::InitDataBlock() { + if (!index_iter_.Valid()) { + SetDataIterator(nullptr); + } else { + Slice handle = index_iter_.value(); + if (data_iter_.iter() != nullptr && + handle.compare(data_block_handle_) == 0) { + // data_iter_ is already constructed with this iterator, so + // no need to change anything + } else { + Iterator* iter = (*block_function_)(arg_, options_, handle); + data_block_handle_.assign(handle.data(), handle.size()); + SetDataIterator(iter); + } + } +} + +} // namespace + +Iterator* NewTwoLevelIterator(Iterator* index_iter, + BlockFunction block_function, void* arg, + const ReadOptions& options) { + return new TwoLevelIterator(index_iter, block_function, arg, options); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.h new file mode 100644 index 0000000..81ffe80 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/table/two_level_iterator.h @@ -0,0 +1,31 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ +#define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ + +#include "leveldb/iterator.h" + +namespace leveldb { + +struct ReadOptions; + +// Return a new two level iterator. A two-level iterator contains an +// index iterator whose values point to a sequence of blocks where +// each block is itself a sequence of key,value pairs. The returned +// two-level iterator yields the concatenation of all key/value pairs +// in the sequence of blocks. Takes ownership of "index_iter" and +// will delete it when no longer needed. +// +// Uses a supplied function to convert an index_iter value into +// an iterator over the contents of the corresponding block. +Iterator* NewTwoLevelIterator( + Iterator* index_iter, + Iterator* (*block_function)(void* arg, const ReadOptions& options, + const Slice& index_value), + void* arg, const ReadOptions& options); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.cc new file mode 100644 index 0000000..46e3b2e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/arena.h" + +namespace leveldb { + +static const int kBlockSize = 4096; + +Arena::Arena() + : alloc_ptr_(nullptr), alloc_bytes_remaining_(0), memory_usage_(0) {} + +Arena::~Arena() { + for (size_t i = 0; i < blocks_.size(); i++) { + delete[] blocks_[i]; + } +} + +char* Arena::AllocateFallback(size_t bytes) { + if (bytes > kBlockSize / 4) { + // Object is more than a quarter of our block size. Allocate it separately + // to avoid wasting too much space in leftover bytes. + char* result = AllocateNewBlock(bytes); + return result; + } + + // We waste the remaining space in the current block. + alloc_ptr_ = AllocateNewBlock(kBlockSize); + alloc_bytes_remaining_ = kBlockSize; + + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; +} + +char* Arena::AllocateAligned(size_t bytes) { + const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8; + static_assert((align & (align - 1)) == 0, + "Pointer size should be a power of 2"); + size_t current_mod = reinterpret_cast(alloc_ptr_) & (align - 1); + size_t slop = (current_mod == 0 ? 0 : align - current_mod); + size_t needed = bytes + slop; + char* result; + if (needed <= alloc_bytes_remaining_) { + result = alloc_ptr_ + slop; + alloc_ptr_ += needed; + alloc_bytes_remaining_ -= needed; + } else { + // AllocateFallback always returned aligned memory + result = AllocateFallback(bytes); + } + assert((reinterpret_cast(result) & (align - 1)) == 0); + return result; +} + +char* Arena::AllocateNewBlock(size_t block_bytes) { + char* result = new char[block_bytes]; + blocks_.push_back(result); + memory_usage_.fetch_add(block_bytes + sizeof(char*), + std::memory_order_relaxed); + return result; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.h new file mode 100644 index 0000000..68fc55d --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/arena.h @@ -0,0 +1,71 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_ +#define STORAGE_LEVELDB_UTIL_ARENA_H_ + +#include +#include +#include +#include +#include + +namespace leveldb { + +class Arena { + public: + Arena(); + + Arena(const Arena&) = delete; + Arena& operator=(const Arena&) = delete; + + ~Arena(); + + // Return a pointer to a newly allocated memory block of "bytes" bytes. + char* Allocate(size_t bytes); + + // Allocate memory with the normal alignment guarantees provided by malloc. + char* AllocateAligned(size_t bytes); + + // Returns an estimate of the total memory usage of data allocated + // by the arena. + size_t MemoryUsage() const { + return memory_usage_.load(std::memory_order_relaxed); + } + + private: + char* AllocateFallback(size_t bytes); + char* AllocateNewBlock(size_t block_bytes); + + // Allocation state + char* alloc_ptr_; + size_t alloc_bytes_remaining_; + + // Array of new[] allocated memory blocks + std::vector blocks_; + + // Total memory usage of the arena. + // + // TODO(costan): This member is accessed via atomics, but the others are + // accessed without any locking. Is this OK? + std::atomic memory_usage_; +}; + +inline char* Arena::Allocate(size_t bytes) { + // The semantics of what to return are a bit messy if we allow + // 0-byte allocations, so we disallow them here (we don't need + // them for our internal use). + assert(bytes > 0); + if (bytes <= alloc_bytes_remaining_) { + char* result = alloc_ptr_; + alloc_ptr_ += bytes; + alloc_bytes_remaining_ -= bytes; + return result; + } + return AllocateFallback(bytes); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ARENA_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/bloom.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/bloom.cc new file mode 100644 index 0000000..7f97464 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/bloom.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +#include "leveldb/slice.h" +#include "util/hash.h" + +namespace leveldb { + +namespace { +static uint32_t BloomHash(const Slice& key) { + return Hash(key.data(), key.size(), 0xbc9f1d34); +} + +class BloomFilterPolicy : public FilterPolicy { + public: + explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) { + // We intentionally round down to reduce probing cost a little bit + k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2) + if (k_ < 1) k_ = 1; + if (k_ > 30) k_ = 30; + } + + virtual const char* Name() const { return "leveldb.BuiltinBloomFilter2"; } + + virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const { + // Compute bloom filter size (in both bits and bytes) + size_t bits = n * bits_per_key_; + + // For small n, we can see a very high false positive rate. Fix it + // by enforcing a minimum bloom filter length. + if (bits < 64) bits = 64; + + size_t bytes = (bits + 7) / 8; + bits = bytes * 8; + + const size_t init_size = dst->size(); + dst->resize(init_size + bytes, 0); + dst->push_back(static_cast(k_)); // Remember # of probes in filter + char* array = &(*dst)[init_size]; + for (int i = 0; i < n; i++) { + // Use double-hashing to generate a sequence of hash values. + // See analysis in [Kirsch,Mitzenmacher 2006]. + uint32_t h = BloomHash(keys[i]); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k_; j++) { + const uint32_t bitpos = h % bits; + array[bitpos / 8] |= (1 << (bitpos % 8)); + h += delta; + } + } + } + + virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const { + const size_t len = bloom_filter.size(); + if (len < 2) return false; + + const char* array = bloom_filter.data(); + const size_t bits = (len - 1) * 8; + + // Use the encoded k so that we can read filters generated by + // bloom filters created using different parameters. + const size_t k = array[len - 1]; + if (k > 30) { + // Reserved for potentially new encodings for short bloom filters. + // Consider it a match. + return true; + } + + uint32_t h = BloomHash(key); + const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits + for (size_t j = 0; j < k; j++) { + const uint32_t bitpos = h % bits; + if ((array[bitpos / 8] & (1 << (bitpos % 8))) == 0) return false; + h += delta; + } + return true; + } + + private: + size_t bits_per_key_; + size_t k_; +}; +} // namespace + +const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) { + return new BloomFilterPolicy(bits_per_key); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/cache.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/cache.cc new file mode 100644 index 0000000..0f801cc --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/cache.cc @@ -0,0 +1,400 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/cache.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/hash.h" +#include "util/mutexlock.h" + +namespace leveldb { + +Cache::~Cache() {} + +namespace { + +// LRU cache implementation +// +// Cache entries have an "in_cache" boolean indicating whether the cache has a +// reference on the entry. The only ways that this can become false without the +// entry being passed to its "deleter" are via Erase(), via Insert() when +// an element with a duplicate key is inserted, or on destruction of the cache. +// +// The cache keeps two linked lists of items in the cache. All items in the +// cache are in one list or the other, and never both. Items still referenced +// by clients but erased from the cache are in neither list. The lists are: +// - in-use: contains the items currently referenced by clients, in no +// particular order. (This list is used for invariant checking. If we +// removed the check, elements that would otherwise be on this list could be +// left as disconnected singleton lists.) +// - LRU: contains the items not currently referenced by clients, in LRU order +// Elements are moved between these lists by the Ref() and Unref() methods, +// when they detect an element in the cache acquiring or losing its only +// external reference. + +// An entry is a variable length heap-allocated structure. Entries +// are kept in a circular doubly linked list ordered by access time. +struct LRUHandle { + void* value; + void (*deleter)(const Slice&, void* value); + LRUHandle* next_hash; + LRUHandle* next; + LRUHandle* prev; + size_t charge; // TODO(opt): Only allow uint32_t? + size_t key_length; + bool in_cache; // Whether entry is in the cache. + uint32_t refs; // References, including cache reference, if present. + uint32_t hash; // Hash of key(); used for fast sharding and comparisons + char key_data[1]; // Beginning of key + + Slice key() const { + // next_ is only equal to this if the LRU handle is the list head of an + // empty list. List heads never have meaningful keys. + assert(next != this); + + return Slice(key_data, key_length); + } +}; + +// We provide our own simple hash table since it removes a whole bunch +// of porting hacks and is also faster than some of the built-in hash +// table implementations in some of the compiler/runtime combinations +// we have tested. E.g., readrandom speeds up by ~5% over the g++ +// 4.4.3's builtin hashtable. +class HandleTable { + public: + HandleTable() : length_(0), elems_(0), list_(nullptr) { Resize(); } + ~HandleTable() { delete[] list_; } + + LRUHandle* Lookup(const Slice& key, uint32_t hash) { + return *FindPointer(key, hash); + } + + LRUHandle* Insert(LRUHandle* h) { + LRUHandle** ptr = FindPointer(h->key(), h->hash); + LRUHandle* old = *ptr; + h->next_hash = (old == nullptr ? nullptr : old->next_hash); + *ptr = h; + if (old == nullptr) { + ++elems_; + if (elems_ > length_) { + // Since each cache entry is fairly large, we aim for a small + // average linked list length (<= 1). + Resize(); + } + } + return old; + } + + LRUHandle* Remove(const Slice& key, uint32_t hash) { + LRUHandle** ptr = FindPointer(key, hash); + LRUHandle* result = *ptr; + if (result != nullptr) { + *ptr = result->next_hash; + --elems_; + } + return result; + } + + private: + // The table consists of an array of buckets where each bucket is + // a linked list of cache entries that hash into the bucket. + uint32_t length_; + uint32_t elems_; + LRUHandle** list_; + + // Return a pointer to slot that points to a cache entry that + // matches key/hash. If there is no such cache entry, return a + // pointer to the trailing slot in the corresponding linked list. + LRUHandle** FindPointer(const Slice& key, uint32_t hash) { + LRUHandle** ptr = &list_[hash & (length_ - 1)]; + while (*ptr != nullptr && ((*ptr)->hash != hash || key != (*ptr)->key())) { + ptr = &(*ptr)->next_hash; + } + return ptr; + } + + void Resize() { + uint32_t new_length = 4; + while (new_length < elems_) { + new_length *= 2; + } + LRUHandle** new_list = new LRUHandle*[new_length]; + memset(new_list, 0, sizeof(new_list[0]) * new_length); + uint32_t count = 0; + for (uint32_t i = 0; i < length_; i++) { + LRUHandle* h = list_[i]; + while (h != nullptr) { + LRUHandle* next = h->next_hash; + uint32_t hash = h->hash; + LRUHandle** ptr = &new_list[hash & (new_length - 1)]; + h->next_hash = *ptr; + *ptr = h; + h = next; + count++; + } + } + assert(elems_ == count); + delete[] list_; + list_ = new_list; + length_ = new_length; + } +}; + +// A single shard of sharded cache. +class LRUCache { + public: + LRUCache(); + ~LRUCache(); + + // Separate from constructor so caller can easily make an array of LRUCache + void SetCapacity(size_t capacity) { capacity_ = capacity; } + + // Like Cache methods, but with an extra "hash" parameter. + Cache::Handle* Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, void* value)); + Cache::Handle* Lookup(const Slice& key, uint32_t hash); + void Release(Cache::Handle* handle); + void Erase(const Slice& key, uint32_t hash); + void Prune(); + size_t TotalCharge() const { + MutexLock l(&mutex_); + return usage_; + } + + private: + void LRU_Remove(LRUHandle* e); + void LRU_Append(LRUHandle* list, LRUHandle* e); + void Ref(LRUHandle* e); + void Unref(LRUHandle* e); + bool FinishErase(LRUHandle* e) EXCLUSIVE_LOCKS_REQUIRED(mutex_); + + // Initialized before use. + size_t capacity_; + + // mutex_ protects the following state. + mutable port::Mutex mutex_; + size_t usage_ GUARDED_BY(mutex_); + + // Dummy head of LRU list. + // lru.prev is newest entry, lru.next is oldest entry. + // Entries have refs==1 and in_cache==true. + LRUHandle lru_ GUARDED_BY(mutex_); + + // Dummy head of in-use list. + // Entries are in use by clients, and have refs >= 2 and in_cache==true. + LRUHandle in_use_ GUARDED_BY(mutex_); + + HandleTable table_ GUARDED_BY(mutex_); +}; + +LRUCache::LRUCache() : capacity_(0), usage_(0) { + // Make empty circular linked lists. + lru_.next = &lru_; + lru_.prev = &lru_; + in_use_.next = &in_use_; + in_use_.prev = &in_use_; +} + +LRUCache::~LRUCache() { + assert(in_use_.next == &in_use_); // Error if caller has an unreleased handle + for (LRUHandle* e = lru_.next; e != &lru_;) { + LRUHandle* next = e->next; + assert(e->in_cache); + e->in_cache = false; + assert(e->refs == 1); // Invariant of lru_ list. + Unref(e); + e = next; + } +} + +void LRUCache::Ref(LRUHandle* e) { + if (e->refs == 1 && e->in_cache) { // If on lru_ list, move to in_use_ list. + LRU_Remove(e); + LRU_Append(&in_use_, e); + } + e->refs++; +} + +void LRUCache::Unref(LRUHandle* e) { + assert(e->refs > 0); + e->refs--; + if (e->refs == 0) { // Deallocate. + assert(!e->in_cache); + (*e->deleter)(e->key(), e->value); + free(e); + } else if (e->in_cache && e->refs == 1) { + // No longer in use; move to lru_ list. + LRU_Remove(e); + LRU_Append(&lru_, e); + } +} + +void LRUCache::LRU_Remove(LRUHandle* e) { + e->next->prev = e->prev; + e->prev->next = e->next; +} + +void LRUCache::LRU_Append(LRUHandle* list, LRUHandle* e) { + // Make "e" newest entry by inserting just before *list + e->next = list; + e->prev = list->prev; + e->prev->next = e; + e->next->prev = e; +} + +Cache::Handle* LRUCache::Lookup(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + LRUHandle* e = table_.Lookup(key, hash); + if (e != nullptr) { + Ref(e); + } + return reinterpret_cast(e); +} + +void LRUCache::Release(Cache::Handle* handle) { + MutexLock l(&mutex_); + Unref(reinterpret_cast(handle)); +} + +Cache::Handle* LRUCache::Insert(const Slice& key, uint32_t hash, void* value, + size_t charge, + void (*deleter)(const Slice& key, + void* value)) { + MutexLock l(&mutex_); + + LRUHandle* e = + reinterpret_cast(malloc(sizeof(LRUHandle) - 1 + key.size())); + e->value = value; + e->deleter = deleter; + e->charge = charge; + e->key_length = key.size(); + e->hash = hash; + e->in_cache = false; + e->refs = 1; // for the returned handle. + memcpy(e->key_data, key.data(), key.size()); + + if (capacity_ > 0) { + e->refs++; // for the cache's reference. + e->in_cache = true; + LRU_Append(&in_use_, e); + usage_ += charge; + FinishErase(table_.Insert(e)); + } else { // don't cache. (capacity_==0 is supported and turns off caching.) + // next is read by key() in an assert, so it must be initialized + e->next = nullptr; + } + while (usage_ > capacity_ && lru_.next != &lru_) { + LRUHandle* old = lru_.next; + assert(old->refs == 1); + bool erased = FinishErase(table_.Remove(old->key(), old->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } + + return reinterpret_cast(e); +} + +// If e != nullptr, finish removing *e from the cache; it has already been +// removed from the hash table. Return whether e != nullptr. +bool LRUCache::FinishErase(LRUHandle* e) { + if (e != nullptr) { + assert(e->in_cache); + LRU_Remove(e); + e->in_cache = false; + usage_ -= e->charge; + Unref(e); + } + return e != nullptr; +} + +void LRUCache::Erase(const Slice& key, uint32_t hash) { + MutexLock l(&mutex_); + FinishErase(table_.Remove(key, hash)); +} + +void LRUCache::Prune() { + MutexLock l(&mutex_); + while (lru_.next != &lru_) { + LRUHandle* e = lru_.next; + assert(e->refs == 1); + bool erased = FinishErase(table_.Remove(e->key(), e->hash)); + if (!erased) { // to avoid unused variable when compiled NDEBUG + assert(erased); + } + } +} + +static const int kNumShardBits = 4; +static const int kNumShards = 1 << kNumShardBits; + +class ShardedLRUCache : public Cache { + private: + LRUCache shard_[kNumShards]; + port::Mutex id_mutex_; + uint64_t last_id_; + + static inline uint32_t HashSlice(const Slice& s) { + return Hash(s.data(), s.size(), 0); + } + + static uint32_t Shard(uint32_t hash) { return hash >> (32 - kNumShardBits); } + + public: + explicit ShardedLRUCache(size_t capacity) : last_id_(0) { + const size_t per_shard = (capacity + (kNumShards - 1)) / kNumShards; + for (int s = 0; s < kNumShards; s++) { + shard_[s].SetCapacity(per_shard); + } + } + virtual ~ShardedLRUCache() {} + virtual Handle* Insert(const Slice& key, void* value, size_t charge, + void (*deleter)(const Slice& key, void* value)) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Insert(key, hash, value, charge, deleter); + } + virtual Handle* Lookup(const Slice& key) { + const uint32_t hash = HashSlice(key); + return shard_[Shard(hash)].Lookup(key, hash); + } + virtual void Release(Handle* handle) { + LRUHandle* h = reinterpret_cast(handle); + shard_[Shard(h->hash)].Release(handle); + } + virtual void Erase(const Slice& key) { + const uint32_t hash = HashSlice(key); + shard_[Shard(hash)].Erase(key, hash); + } + virtual void* Value(Handle* handle) { + return reinterpret_cast(handle)->value; + } + virtual uint64_t NewId() { + MutexLock l(&id_mutex_); + return ++(last_id_); + } + virtual void Prune() { + for (int s = 0; s < kNumShards; s++) { + shard_[s].Prune(); + } + } + virtual size_t TotalCharge() const { + size_t total = 0; + for (int s = 0; s < kNumShards; s++) { + total += shard_[s].TotalCharge(); + } + return total; + } +}; + +} // end anonymous namespace + +Cache* NewLRUCache(size_t capacity) { return new ShardedLRUCache(capacity); } + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.cc new file mode 100644 index 0000000..e2089df --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.cc @@ -0,0 +1,192 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/coding.h" + +namespace leveldb { + +void EncodeFixed32(char* dst, uint32_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + } +} + +void EncodeFixed64(char* dst, uint64_t value) { + if (port::kLittleEndian) { + memcpy(dst, &value, sizeof(value)); + } else { + dst[0] = value & 0xff; + dst[1] = (value >> 8) & 0xff; + dst[2] = (value >> 16) & 0xff; + dst[3] = (value >> 24) & 0xff; + dst[4] = (value >> 32) & 0xff; + dst[5] = (value >> 40) & 0xff; + dst[6] = (value >> 48) & 0xff; + dst[7] = (value >> 56) & 0xff; + } +} + +void PutFixed32(std::string* dst, uint32_t value) { + char buf[sizeof(value)]; + EncodeFixed32(buf, value); + dst->append(buf, sizeof(buf)); +} + +void PutFixed64(std::string* dst, uint64_t value) { + char buf[sizeof(value)]; + EncodeFixed64(buf, value); + dst->append(buf, sizeof(buf)); +} + +char* EncodeVarint32(char* dst, uint32_t v) { + // Operate on characters as unsigneds + unsigned char* ptr = reinterpret_cast(dst); + static const int B = 128; + if (v < (1 << 7)) { + *(ptr++) = v; + } else if (v < (1 << 14)) { + *(ptr++) = v | B; + *(ptr++) = v >> 7; + } else if (v < (1 << 21)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = v >> 14; + } else if (v < (1 << 28)) { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = v >> 21; + } else { + *(ptr++) = v | B; + *(ptr++) = (v >> 7) | B; + *(ptr++) = (v >> 14) | B; + *(ptr++) = (v >> 21) | B; + *(ptr++) = v >> 28; + } + return reinterpret_cast(ptr); +} + +void PutVarint32(std::string* dst, uint32_t v) { + char buf[5]; + char* ptr = EncodeVarint32(buf, v); + dst->append(buf, ptr - buf); +} + +char* EncodeVarint64(char* dst, uint64_t v) { + static const int B = 128; + unsigned char* ptr = reinterpret_cast(dst); + while (v >= B) { + *(ptr++) = v | B; + v >>= 7; + } + *(ptr++) = static_cast(v); + return reinterpret_cast(ptr); +} + +void PutVarint64(std::string* dst, uint64_t v) { + char buf[10]; + char* ptr = EncodeVarint64(buf, v); + dst->append(buf, ptr - buf); +} + +void PutLengthPrefixedSlice(std::string* dst, const Slice& value) { + PutVarint32(dst, value.size()); + dst->append(value.data(), value.size()); +} + +int VarintLength(uint64_t v) { + int len = 1; + while (v >= 128) { + v >>= 7; + len++; + } + return len; +} + +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value) { + uint32_t result = 0; + for (uint32_t shift = 0; shift <= 28 && p < limit; shift += 7) { + uint32_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint32(Slice* input, uint32_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint32Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* value) { + uint64_t result = 0; + for (uint32_t shift = 0; shift <= 63 && p < limit; shift += 7) { + uint64_t byte = *(reinterpret_cast(p)); + p++; + if (byte & 128) { + // More bytes are present + result |= ((byte & 127) << shift); + } else { + result |= (byte << shift); + *value = result; + return reinterpret_cast(p); + } + } + return nullptr; +} + +bool GetVarint64(Slice* input, uint64_t* value) { + const char* p = input->data(); + const char* limit = p + input->size(); + const char* q = GetVarint64Ptr(p, limit, value); + if (q == nullptr) { + return false; + } else { + *input = Slice(q, limit - q); + return true; + } +} + +const char* GetLengthPrefixedSlice(const char* p, const char* limit, + Slice* result) { + uint32_t len; + p = GetVarint32Ptr(p, limit, &len); + if (p == nullptr) return nullptr; + if (p + len > limit) return nullptr; + *result = Slice(p, len); + return p + len; +} + +bool GetLengthPrefixedSlice(Slice* input, Slice* result) { + uint32_t len; + if (GetVarint32(input, &len) && input->size() >= len) { + *result = Slice(input->data(), len); + input->remove_prefix(len); + return true; + } else { + return false; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.h new file mode 100644 index 0000000..d9eeaa3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/coding.h @@ -0,0 +1,104 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Endian-neutral encoding: +// * Fixed-length numbers are encoded with least-significant byte first +// * In addition we support variable length "varint" encoding +// * Strings are encoded prefixed by their length in varint format + +#ifndef STORAGE_LEVELDB_UTIL_CODING_H_ +#define STORAGE_LEVELDB_UTIL_CODING_H_ + +#include +#include + +#include + +#include "leveldb/slice.h" +#include "port/port.h" + +namespace leveldb { + +// Standard Put... routines append to a string +void PutFixed32(std::string* dst, uint32_t value); +void PutFixed64(std::string* dst, uint64_t value); +void PutVarint32(std::string* dst, uint32_t value); +void PutVarint64(std::string* dst, uint64_t value); +void PutLengthPrefixedSlice(std::string* dst, const Slice& value); + +// Standard Get... routines parse a value from the beginning of a Slice +// and advance the slice past the parsed value. +bool GetVarint32(Slice* input, uint32_t* value); +bool GetVarint64(Slice* input, uint64_t* value); +bool GetLengthPrefixedSlice(Slice* input, Slice* result); + +// Pointer-based variants of GetVarint... These either store a value +// in *v and return a pointer just past the parsed value, or return +// nullptr on error. These routines only look at bytes in the range +// [p..limit-1] +const char* GetVarint32Ptr(const char* p, const char* limit, uint32_t* v); +const char* GetVarint64Ptr(const char* p, const char* limit, uint64_t* v); + +// Returns the length of the varint32 or varint64 encoding of "v" +int VarintLength(uint64_t v); + +// Lower-level versions of Put... that write directly into a character buffer +// REQUIRES: dst has enough space for the value being written +void EncodeFixed32(char* dst, uint32_t value); +void EncodeFixed64(char* dst, uint64_t value); + +// Lower-level versions of Put... that write directly into a character buffer +// and return a pointer just past the last byte written. +// REQUIRES: dst has enough space for the value being written +char* EncodeVarint32(char* dst, uint32_t value); +char* EncodeVarint64(char* dst, uint64_t value); + +// Lower-level versions of Get... that read directly from a character buffer +// without any bounds checking. + +inline uint32_t DecodeFixed32(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint32_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + return ((static_cast(static_cast(ptr[0]))) | + (static_cast(static_cast(ptr[1])) << 8) | + (static_cast(static_cast(ptr[2])) << 16) | + (static_cast(static_cast(ptr[3])) << 24)); + } +} + +inline uint64_t DecodeFixed64(const char* ptr) { + if (port::kLittleEndian) { + // Load the raw bytes + uint64_t result; + memcpy(&result, ptr, sizeof(result)); // gcc optimizes this to a plain load + return result; + } else { + uint64_t lo = DecodeFixed32(ptr); + uint64_t hi = DecodeFixed32(ptr + 4); + return (hi << 32) | lo; + } +} + +// Internal routine for use by fallback path of GetVarint32Ptr +const char* GetVarint32PtrFallback(const char* p, const char* limit, + uint32_t* value); +inline const char* GetVarint32Ptr(const char* p, const char* limit, + uint32_t* value) { + if (p < limit) { + uint32_t result = *(reinterpret_cast(p)); + if ((result & 128) == 0) { + *value = result; + return p + 1; + } + } + return GetVarint32PtrFallback(p, limit, value); +} + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CODING_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/comparator.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/comparator.cc new file mode 100644 index 0000000..26d1eb3 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/comparator.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include + +#include "leveldb/comparator.h" +#include "leveldb/slice.h" +#include "util/logging.h" +#include "util/no_destructor.h" + +namespace leveldb { + +Comparator::~Comparator() {} + +namespace { +class BytewiseComparatorImpl : public Comparator { + public: + BytewiseComparatorImpl() {} + + virtual const char* Name() const { return "leveldb.BytewiseComparator"; } + + virtual int Compare(const Slice& a, const Slice& b) const { + return a.compare(b); + } + + virtual void FindShortestSeparator(std::string* start, + const Slice& limit) const { + // Find length of common prefix + size_t min_length = std::min(start->size(), limit.size()); + size_t diff_index = 0; + while ((diff_index < min_length) && + ((*start)[diff_index] == limit[diff_index])) { + diff_index++; + } + + if (diff_index >= min_length) { + // Do not shorten if one string is a prefix of the other + } else { + uint8_t diff_byte = static_cast((*start)[diff_index]); + if (diff_byte < static_cast(0xff) && + diff_byte + 1 < static_cast(limit[diff_index])) { + (*start)[diff_index]++; + start->resize(diff_index + 1); + assert(Compare(*start, limit) < 0); + } + } + } + + virtual void FindShortSuccessor(std::string* key) const { + // Find first character that can be incremented + size_t n = key->size(); + for (size_t i = 0; i < n; i++) { + const uint8_t byte = (*key)[i]; + if (byte != static_cast(0xff)) { + (*key)[i] = byte + 1; + key->resize(i + 1); + return; + } + } + // *key is a run of 0xffs. Leave it alone. + } +}; +} // namespace + +const Comparator* BytewiseComparator() { + static NoDestructor singleton; + return singleton.get(); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.cc new file mode 100644 index 0000000..c2e61f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.cc @@ -0,0 +1,380 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// A portable implementation of crc32c. + +#include "util/crc32c.h" + +#include +#include + +#include "port/port.h" +#include "util/coding.h" + +namespace leveldb { +namespace crc32c { + +namespace { + +const uint32_t kByteExtensionTable[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, + 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, + 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, + 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, + 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, + 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, + 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, + 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, + 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, + 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, + 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, + 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, + 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, + 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, + 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, + 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, + 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, + 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, + 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, + 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, + 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, + 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351}; + +const uint32_t kStrideExtensionTable0[256] = { + 0x00000000, 0x30d23865, 0x61a470ca, 0x517648af, 0xc348e194, 0xf39ad9f1, + 0xa2ec915e, 0x923ea93b, 0x837db5d9, 0xb3af8dbc, 0xe2d9c513, 0xd20bfd76, + 0x4035544d, 0x70e76c28, 0x21912487, 0x11431ce2, 0x03171d43, 0x33c52526, + 0x62b36d89, 0x526155ec, 0xc05ffcd7, 0xf08dc4b2, 0xa1fb8c1d, 0x9129b478, + 0x806aa89a, 0xb0b890ff, 0xe1ced850, 0xd11ce035, 0x4322490e, 0x73f0716b, + 0x228639c4, 0x125401a1, 0x062e3a86, 0x36fc02e3, 0x678a4a4c, 0x57587229, + 0xc566db12, 0xf5b4e377, 0xa4c2abd8, 0x941093bd, 0x85538f5f, 0xb581b73a, + 0xe4f7ff95, 0xd425c7f0, 0x461b6ecb, 0x76c956ae, 0x27bf1e01, 0x176d2664, + 0x053927c5, 0x35eb1fa0, 0x649d570f, 0x544f6f6a, 0xc671c651, 0xf6a3fe34, + 0xa7d5b69b, 0x97078efe, 0x8644921c, 0xb696aa79, 0xe7e0e2d6, 0xd732dab3, + 0x450c7388, 0x75de4bed, 0x24a80342, 0x147a3b27, 0x0c5c750c, 0x3c8e4d69, + 0x6df805c6, 0x5d2a3da3, 0xcf149498, 0xffc6acfd, 0xaeb0e452, 0x9e62dc37, + 0x8f21c0d5, 0xbff3f8b0, 0xee85b01f, 0xde57887a, 0x4c692141, 0x7cbb1924, + 0x2dcd518b, 0x1d1f69ee, 0x0f4b684f, 0x3f99502a, 0x6eef1885, 0x5e3d20e0, + 0xcc0389db, 0xfcd1b1be, 0xada7f911, 0x9d75c174, 0x8c36dd96, 0xbce4e5f3, + 0xed92ad5c, 0xdd409539, 0x4f7e3c02, 0x7fac0467, 0x2eda4cc8, 0x1e0874ad, + 0x0a724f8a, 0x3aa077ef, 0x6bd63f40, 0x5b040725, 0xc93aae1e, 0xf9e8967b, + 0xa89eded4, 0x984ce6b1, 0x890ffa53, 0xb9ddc236, 0xe8ab8a99, 0xd879b2fc, + 0x4a471bc7, 0x7a9523a2, 0x2be36b0d, 0x1b315368, 0x096552c9, 0x39b76aac, + 0x68c12203, 0x58131a66, 0xca2db35d, 0xfaff8b38, 0xab89c397, 0x9b5bfbf2, + 0x8a18e710, 0xbacadf75, 0xebbc97da, 0xdb6eafbf, 0x49500684, 0x79823ee1, + 0x28f4764e, 0x18264e2b, 0x18b8ea18, 0x286ad27d, 0x791c9ad2, 0x49cea2b7, + 0xdbf00b8c, 0xeb2233e9, 0xba547b46, 0x8a864323, 0x9bc55fc1, 0xab1767a4, + 0xfa612f0b, 0xcab3176e, 0x588dbe55, 0x685f8630, 0x3929ce9f, 0x09fbf6fa, + 0x1baff75b, 0x2b7dcf3e, 0x7a0b8791, 0x4ad9bff4, 0xd8e716cf, 0xe8352eaa, + 0xb9436605, 0x89915e60, 0x98d24282, 0xa8007ae7, 0xf9763248, 0xc9a40a2d, + 0x5b9aa316, 0x6b489b73, 0x3a3ed3dc, 0x0aecebb9, 0x1e96d09e, 0x2e44e8fb, + 0x7f32a054, 0x4fe09831, 0xddde310a, 0xed0c096f, 0xbc7a41c0, 0x8ca879a5, + 0x9deb6547, 0xad395d22, 0xfc4f158d, 0xcc9d2de8, 0x5ea384d3, 0x6e71bcb6, + 0x3f07f419, 0x0fd5cc7c, 0x1d81cddd, 0x2d53f5b8, 0x7c25bd17, 0x4cf78572, + 0xdec92c49, 0xee1b142c, 0xbf6d5c83, 0x8fbf64e6, 0x9efc7804, 0xae2e4061, + 0xff5808ce, 0xcf8a30ab, 0x5db49990, 0x6d66a1f5, 0x3c10e95a, 0x0cc2d13f, + 0x14e49f14, 0x2436a771, 0x7540efde, 0x4592d7bb, 0xd7ac7e80, 0xe77e46e5, + 0xb6080e4a, 0x86da362f, 0x97992acd, 0xa74b12a8, 0xf63d5a07, 0xc6ef6262, + 0x54d1cb59, 0x6403f33c, 0x3575bb93, 0x05a783f6, 0x17f38257, 0x2721ba32, + 0x7657f29d, 0x4685caf8, 0xd4bb63c3, 0xe4695ba6, 0xb51f1309, 0x85cd2b6c, + 0x948e378e, 0xa45c0feb, 0xf52a4744, 0xc5f87f21, 0x57c6d61a, 0x6714ee7f, + 0x3662a6d0, 0x06b09eb5, 0x12caa592, 0x22189df7, 0x736ed558, 0x43bced3d, + 0xd1824406, 0xe1507c63, 0xb02634cc, 0x80f40ca9, 0x91b7104b, 0xa165282e, + 0xf0136081, 0xc0c158e4, 0x52fff1df, 0x622dc9ba, 0x335b8115, 0x0389b970, + 0x11ddb8d1, 0x210f80b4, 0x7079c81b, 0x40abf07e, 0xd2955945, 0xe2476120, + 0xb331298f, 0x83e311ea, 0x92a00d08, 0xa272356d, 0xf3047dc2, 0xc3d645a7, + 0x51e8ec9c, 0x613ad4f9, 0x304c9c56, 0x009ea433}; + +const uint32_t kStrideExtensionTable1[256] = { + 0x00000000, 0x54075546, 0xa80eaa8c, 0xfc09ffca, 0x55f123e9, 0x01f676af, + 0xfdff8965, 0xa9f8dc23, 0xabe247d2, 0xffe51294, 0x03eced5e, 0x57ebb818, + 0xfe13643b, 0xaa14317d, 0x561dceb7, 0x021a9bf1, 0x5228f955, 0x062fac13, + 0xfa2653d9, 0xae21069f, 0x07d9dabc, 0x53de8ffa, 0xafd77030, 0xfbd02576, + 0xf9cabe87, 0xadcdebc1, 0x51c4140b, 0x05c3414d, 0xac3b9d6e, 0xf83cc828, + 0x043537e2, 0x503262a4, 0xa451f2aa, 0xf056a7ec, 0x0c5f5826, 0x58580d60, + 0xf1a0d143, 0xa5a78405, 0x59ae7bcf, 0x0da92e89, 0x0fb3b578, 0x5bb4e03e, + 0xa7bd1ff4, 0xf3ba4ab2, 0x5a429691, 0x0e45c3d7, 0xf24c3c1d, 0xa64b695b, + 0xf6790bff, 0xa27e5eb9, 0x5e77a173, 0x0a70f435, 0xa3882816, 0xf78f7d50, + 0x0b86829a, 0x5f81d7dc, 0x5d9b4c2d, 0x099c196b, 0xf595e6a1, 0xa192b3e7, + 0x086a6fc4, 0x5c6d3a82, 0xa064c548, 0xf463900e, 0x4d4f93a5, 0x1948c6e3, + 0xe5413929, 0xb1466c6f, 0x18beb04c, 0x4cb9e50a, 0xb0b01ac0, 0xe4b74f86, + 0xe6add477, 0xb2aa8131, 0x4ea37efb, 0x1aa42bbd, 0xb35cf79e, 0xe75ba2d8, + 0x1b525d12, 0x4f550854, 0x1f676af0, 0x4b603fb6, 0xb769c07c, 0xe36e953a, + 0x4a964919, 0x1e911c5f, 0xe298e395, 0xb69fb6d3, 0xb4852d22, 0xe0827864, + 0x1c8b87ae, 0x488cd2e8, 0xe1740ecb, 0xb5735b8d, 0x497aa447, 0x1d7df101, + 0xe91e610f, 0xbd193449, 0x4110cb83, 0x15179ec5, 0xbcef42e6, 0xe8e817a0, + 0x14e1e86a, 0x40e6bd2c, 0x42fc26dd, 0x16fb739b, 0xeaf28c51, 0xbef5d917, + 0x170d0534, 0x430a5072, 0xbf03afb8, 0xeb04fafe, 0xbb36985a, 0xef31cd1c, + 0x133832d6, 0x473f6790, 0xeec7bbb3, 0xbac0eef5, 0x46c9113f, 0x12ce4479, + 0x10d4df88, 0x44d38ace, 0xb8da7504, 0xecdd2042, 0x4525fc61, 0x1122a927, + 0xed2b56ed, 0xb92c03ab, 0x9a9f274a, 0xce98720c, 0x32918dc6, 0x6696d880, + 0xcf6e04a3, 0x9b6951e5, 0x6760ae2f, 0x3367fb69, 0x317d6098, 0x657a35de, + 0x9973ca14, 0xcd749f52, 0x648c4371, 0x308b1637, 0xcc82e9fd, 0x9885bcbb, + 0xc8b7de1f, 0x9cb08b59, 0x60b97493, 0x34be21d5, 0x9d46fdf6, 0xc941a8b0, + 0x3548577a, 0x614f023c, 0x635599cd, 0x3752cc8b, 0xcb5b3341, 0x9f5c6607, + 0x36a4ba24, 0x62a3ef62, 0x9eaa10a8, 0xcaad45ee, 0x3eced5e0, 0x6ac980a6, + 0x96c07f6c, 0xc2c72a2a, 0x6b3ff609, 0x3f38a34f, 0xc3315c85, 0x973609c3, + 0x952c9232, 0xc12bc774, 0x3d2238be, 0x69256df8, 0xc0ddb1db, 0x94dae49d, + 0x68d31b57, 0x3cd44e11, 0x6ce62cb5, 0x38e179f3, 0xc4e88639, 0x90efd37f, + 0x39170f5c, 0x6d105a1a, 0x9119a5d0, 0xc51ef096, 0xc7046b67, 0x93033e21, + 0x6f0ac1eb, 0x3b0d94ad, 0x92f5488e, 0xc6f21dc8, 0x3afbe202, 0x6efcb744, + 0xd7d0b4ef, 0x83d7e1a9, 0x7fde1e63, 0x2bd94b25, 0x82219706, 0xd626c240, + 0x2a2f3d8a, 0x7e2868cc, 0x7c32f33d, 0x2835a67b, 0xd43c59b1, 0x803b0cf7, + 0x29c3d0d4, 0x7dc48592, 0x81cd7a58, 0xd5ca2f1e, 0x85f84dba, 0xd1ff18fc, + 0x2df6e736, 0x79f1b270, 0xd0096e53, 0x840e3b15, 0x7807c4df, 0x2c009199, + 0x2e1a0a68, 0x7a1d5f2e, 0x8614a0e4, 0xd213f5a2, 0x7beb2981, 0x2fec7cc7, + 0xd3e5830d, 0x87e2d64b, 0x73814645, 0x27861303, 0xdb8fecc9, 0x8f88b98f, + 0x267065ac, 0x727730ea, 0x8e7ecf20, 0xda799a66, 0xd8630197, 0x8c6454d1, + 0x706dab1b, 0x246afe5d, 0x8d92227e, 0xd9957738, 0x259c88f2, 0x719bddb4, + 0x21a9bf10, 0x75aeea56, 0x89a7159c, 0xdda040da, 0x74589cf9, 0x205fc9bf, + 0xdc563675, 0x88516333, 0x8a4bf8c2, 0xde4cad84, 0x2245524e, 0x76420708, + 0xdfbadb2b, 0x8bbd8e6d, 0x77b471a7, 0x23b324e1}; + +const uint32_t kStrideExtensionTable2[256] = { + 0x00000000, 0x678efd01, 0xcf1dfa02, 0xa8930703, 0x9bd782f5, 0xfc597ff4, + 0x54ca78f7, 0x334485f6, 0x3243731b, 0x55cd8e1a, 0xfd5e8919, 0x9ad07418, + 0xa994f1ee, 0xce1a0cef, 0x66890bec, 0x0107f6ed, 0x6486e636, 0x03081b37, + 0xab9b1c34, 0xcc15e135, 0xff5164c3, 0x98df99c2, 0x304c9ec1, 0x57c263c0, + 0x56c5952d, 0x314b682c, 0x99d86f2f, 0xfe56922e, 0xcd1217d8, 0xaa9cead9, + 0x020fedda, 0x658110db, 0xc90dcc6c, 0xae83316d, 0x0610366e, 0x619ecb6f, + 0x52da4e99, 0x3554b398, 0x9dc7b49b, 0xfa49499a, 0xfb4ebf77, 0x9cc04276, + 0x34534575, 0x53ddb874, 0x60993d82, 0x0717c083, 0xaf84c780, 0xc80a3a81, + 0xad8b2a5a, 0xca05d75b, 0x6296d058, 0x05182d59, 0x365ca8af, 0x51d255ae, + 0xf94152ad, 0x9ecfafac, 0x9fc85941, 0xf846a440, 0x50d5a343, 0x375b5e42, + 0x041fdbb4, 0x639126b5, 0xcb0221b6, 0xac8cdcb7, 0x97f7ee29, 0xf0791328, + 0x58ea142b, 0x3f64e92a, 0x0c206cdc, 0x6bae91dd, 0xc33d96de, 0xa4b36bdf, + 0xa5b49d32, 0xc23a6033, 0x6aa96730, 0x0d279a31, 0x3e631fc7, 0x59ede2c6, + 0xf17ee5c5, 0x96f018c4, 0xf371081f, 0x94fff51e, 0x3c6cf21d, 0x5be20f1c, + 0x68a68aea, 0x0f2877eb, 0xa7bb70e8, 0xc0358de9, 0xc1327b04, 0xa6bc8605, + 0x0e2f8106, 0x69a17c07, 0x5ae5f9f1, 0x3d6b04f0, 0x95f803f3, 0xf276fef2, + 0x5efa2245, 0x3974df44, 0x91e7d847, 0xf6692546, 0xc52da0b0, 0xa2a35db1, + 0x0a305ab2, 0x6dbea7b3, 0x6cb9515e, 0x0b37ac5f, 0xa3a4ab5c, 0xc42a565d, + 0xf76ed3ab, 0x90e02eaa, 0x387329a9, 0x5ffdd4a8, 0x3a7cc473, 0x5df23972, + 0xf5613e71, 0x92efc370, 0xa1ab4686, 0xc625bb87, 0x6eb6bc84, 0x09384185, + 0x083fb768, 0x6fb14a69, 0xc7224d6a, 0xa0acb06b, 0x93e8359d, 0xf466c89c, + 0x5cf5cf9f, 0x3b7b329e, 0x2a03aaa3, 0x4d8d57a2, 0xe51e50a1, 0x8290ada0, + 0xb1d42856, 0xd65ad557, 0x7ec9d254, 0x19472f55, 0x1840d9b8, 0x7fce24b9, + 0xd75d23ba, 0xb0d3debb, 0x83975b4d, 0xe419a64c, 0x4c8aa14f, 0x2b045c4e, + 0x4e854c95, 0x290bb194, 0x8198b697, 0xe6164b96, 0xd552ce60, 0xb2dc3361, + 0x1a4f3462, 0x7dc1c963, 0x7cc63f8e, 0x1b48c28f, 0xb3dbc58c, 0xd455388d, + 0xe711bd7b, 0x809f407a, 0x280c4779, 0x4f82ba78, 0xe30e66cf, 0x84809bce, + 0x2c139ccd, 0x4b9d61cc, 0x78d9e43a, 0x1f57193b, 0xb7c41e38, 0xd04ae339, + 0xd14d15d4, 0xb6c3e8d5, 0x1e50efd6, 0x79de12d7, 0x4a9a9721, 0x2d146a20, + 0x85876d23, 0xe2099022, 0x878880f9, 0xe0067df8, 0x48957afb, 0x2f1b87fa, + 0x1c5f020c, 0x7bd1ff0d, 0xd342f80e, 0xb4cc050f, 0xb5cbf3e2, 0xd2450ee3, + 0x7ad609e0, 0x1d58f4e1, 0x2e1c7117, 0x49928c16, 0xe1018b15, 0x868f7614, + 0xbdf4448a, 0xda7ab98b, 0x72e9be88, 0x15674389, 0x2623c67f, 0x41ad3b7e, + 0xe93e3c7d, 0x8eb0c17c, 0x8fb73791, 0xe839ca90, 0x40aacd93, 0x27243092, + 0x1460b564, 0x73ee4865, 0xdb7d4f66, 0xbcf3b267, 0xd972a2bc, 0xbefc5fbd, + 0x166f58be, 0x71e1a5bf, 0x42a52049, 0x252bdd48, 0x8db8da4b, 0xea36274a, + 0xeb31d1a7, 0x8cbf2ca6, 0x242c2ba5, 0x43a2d6a4, 0x70e65352, 0x1768ae53, + 0xbffba950, 0xd8755451, 0x74f988e6, 0x137775e7, 0xbbe472e4, 0xdc6a8fe5, + 0xef2e0a13, 0x88a0f712, 0x2033f011, 0x47bd0d10, 0x46bafbfd, 0x213406fc, + 0x89a701ff, 0xee29fcfe, 0xdd6d7908, 0xbae38409, 0x1270830a, 0x75fe7e0b, + 0x107f6ed0, 0x77f193d1, 0xdf6294d2, 0xb8ec69d3, 0x8ba8ec25, 0xec261124, + 0x44b51627, 0x233beb26, 0x223c1dcb, 0x45b2e0ca, 0xed21e7c9, 0x8aaf1ac8, + 0xb9eb9f3e, 0xde65623f, 0x76f6653c, 0x1178983d}; + +const uint32_t kStrideExtensionTable3[256] = { + 0x00000000, 0xf20c0dfe, 0xe1f46d0d, 0x13f860f3, 0xc604aceb, 0x3408a115, + 0x27f0c1e6, 0xd5fccc18, 0x89e52f27, 0x7be922d9, 0x6811422a, 0x9a1d4fd4, + 0x4fe183cc, 0xbded8e32, 0xae15eec1, 0x5c19e33f, 0x162628bf, 0xe42a2541, + 0xf7d245b2, 0x05de484c, 0xd0228454, 0x222e89aa, 0x31d6e959, 0xc3dae4a7, + 0x9fc30798, 0x6dcf0a66, 0x7e376a95, 0x8c3b676b, 0x59c7ab73, 0xabcba68d, + 0xb833c67e, 0x4a3fcb80, 0x2c4c517e, 0xde405c80, 0xcdb83c73, 0x3fb4318d, + 0xea48fd95, 0x1844f06b, 0x0bbc9098, 0xf9b09d66, 0xa5a97e59, 0x57a573a7, + 0x445d1354, 0xb6511eaa, 0x63add2b2, 0x91a1df4c, 0x8259bfbf, 0x7055b241, + 0x3a6a79c1, 0xc866743f, 0xdb9e14cc, 0x29921932, 0xfc6ed52a, 0x0e62d8d4, + 0x1d9ab827, 0xef96b5d9, 0xb38f56e6, 0x41835b18, 0x527b3beb, 0xa0773615, + 0x758bfa0d, 0x8787f7f3, 0x947f9700, 0x66739afe, 0x5898a2fc, 0xaa94af02, + 0xb96ccff1, 0x4b60c20f, 0x9e9c0e17, 0x6c9003e9, 0x7f68631a, 0x8d646ee4, + 0xd17d8ddb, 0x23718025, 0x3089e0d6, 0xc285ed28, 0x17792130, 0xe5752cce, + 0xf68d4c3d, 0x048141c3, 0x4ebe8a43, 0xbcb287bd, 0xaf4ae74e, 0x5d46eab0, + 0x88ba26a8, 0x7ab62b56, 0x694e4ba5, 0x9b42465b, 0xc75ba564, 0x3557a89a, + 0x26afc869, 0xd4a3c597, 0x015f098f, 0xf3530471, 0xe0ab6482, 0x12a7697c, + 0x74d4f382, 0x86d8fe7c, 0x95209e8f, 0x672c9371, 0xb2d05f69, 0x40dc5297, + 0x53243264, 0xa1283f9a, 0xfd31dca5, 0x0f3dd15b, 0x1cc5b1a8, 0xeec9bc56, + 0x3b35704e, 0xc9397db0, 0xdac11d43, 0x28cd10bd, 0x62f2db3d, 0x90fed6c3, + 0x8306b630, 0x710abbce, 0xa4f677d6, 0x56fa7a28, 0x45021adb, 0xb70e1725, + 0xeb17f41a, 0x191bf9e4, 0x0ae39917, 0xf8ef94e9, 0x2d1358f1, 0xdf1f550f, + 0xcce735fc, 0x3eeb3802, 0xb13145f8, 0x433d4806, 0x50c528f5, 0xa2c9250b, + 0x7735e913, 0x8539e4ed, 0x96c1841e, 0x64cd89e0, 0x38d46adf, 0xcad86721, + 0xd92007d2, 0x2b2c0a2c, 0xfed0c634, 0x0cdccbca, 0x1f24ab39, 0xed28a6c7, + 0xa7176d47, 0x551b60b9, 0x46e3004a, 0xb4ef0db4, 0x6113c1ac, 0x931fcc52, + 0x80e7aca1, 0x72eba15f, 0x2ef24260, 0xdcfe4f9e, 0xcf062f6d, 0x3d0a2293, + 0xe8f6ee8b, 0x1afae375, 0x09028386, 0xfb0e8e78, 0x9d7d1486, 0x6f711978, + 0x7c89798b, 0x8e857475, 0x5b79b86d, 0xa975b593, 0xba8dd560, 0x4881d89e, + 0x14983ba1, 0xe694365f, 0xf56c56ac, 0x07605b52, 0xd29c974a, 0x20909ab4, + 0x3368fa47, 0xc164f7b9, 0x8b5b3c39, 0x795731c7, 0x6aaf5134, 0x98a35cca, + 0x4d5f90d2, 0xbf539d2c, 0xacabfddf, 0x5ea7f021, 0x02be131e, 0xf0b21ee0, + 0xe34a7e13, 0x114673ed, 0xc4babff5, 0x36b6b20b, 0x254ed2f8, 0xd742df06, + 0xe9a9e704, 0x1ba5eafa, 0x085d8a09, 0xfa5187f7, 0x2fad4bef, 0xdda14611, + 0xce5926e2, 0x3c552b1c, 0x604cc823, 0x9240c5dd, 0x81b8a52e, 0x73b4a8d0, + 0xa64864c8, 0x54446936, 0x47bc09c5, 0xb5b0043b, 0xff8fcfbb, 0x0d83c245, + 0x1e7ba2b6, 0xec77af48, 0x398b6350, 0xcb876eae, 0xd87f0e5d, 0x2a7303a3, + 0x766ae09c, 0x8466ed62, 0x979e8d91, 0x6592806f, 0xb06e4c77, 0x42624189, + 0x519a217a, 0xa3962c84, 0xc5e5b67a, 0x37e9bb84, 0x2411db77, 0xd61dd689, + 0x03e11a91, 0xf1ed176f, 0xe215779c, 0x10197a62, 0x4c00995d, 0xbe0c94a3, + 0xadf4f450, 0x5ff8f9ae, 0x8a0435b6, 0x78083848, 0x6bf058bb, 0x99fc5545, + 0xd3c39ec5, 0x21cf933b, 0x3237f3c8, 0xc03bfe36, 0x15c7322e, 0xe7cb3fd0, + 0xf4335f23, 0x063f52dd, 0x5a26b1e2, 0xa82abc1c, 0xbbd2dcef, 0x49ded111, + 0x9c221d09, 0x6e2e10f7, 0x7dd67004, 0x8fda7dfa}; + +// CRCs are pre- and post- conditioned by xoring with all ones. +static constexpr const uint32_t kCRC32Xor = static_cast(0xffffffffU); + +// Reads a little-endian 32-bit integer from a 32-bit-aligned buffer. +inline uint32_t ReadUint32LE(const uint8_t* buffer) { + return DecodeFixed32(reinterpret_cast(buffer)); +} + +// Returns the smallest address >= the given address that is aligned to N bytes. +// +// N must be a power of two. +template +constexpr inline const uint8_t* RoundUp(const uint8_t* pointer) { + return reinterpret_cast( + (reinterpret_cast(pointer) + (N - 1)) & + ~static_cast(N - 1)); +} + +} // namespace + +// Determine if the CPU running this program can accelerate the CRC32C +// calculation. +static bool CanAccelerateCRC32C() { + // port::AcceleretedCRC32C returns zero when unable to accelerate. + static const char kTestCRCBuffer[] = "TestCRCBuffer"; + static const char kBufSize = sizeof(kTestCRCBuffer) - 1; + static const uint32_t kTestCRCValue = 0xdcbc59fa; + + return port::AcceleratedCRC32C(0, kTestCRCBuffer, kBufSize) == kTestCRCValue; +} + +uint32_t Extend(uint32_t crc, const char* data, size_t n) { + static bool accelerate = CanAccelerateCRC32C(); + if (accelerate) { + return port::AcceleratedCRC32C(crc, data, n); + } + + const uint8_t* p = reinterpret_cast(data); + const uint8_t* e = p + n; + uint32_t l = crc ^ kCRC32Xor; + +// Process one byte at a time. +#define STEP1 \ + do { \ + int c = (l & 0xff) ^ *p++; \ + l = kByteExtensionTable[c] ^ (l >> 8); \ + } while (0) + +// Process one of the 4 strides of 4-byte data. +#define STEP4(s) \ + do { \ + crc##s = ReadUint32LE(p + s * 4) ^ kStrideExtensionTable3[crc##s & 0xff] ^ \ + kStrideExtensionTable2[(crc##s >> 8) & 0xff] ^ \ + kStrideExtensionTable1[(crc##s >> 16) & 0xff] ^ \ + kStrideExtensionTable0[crc##s >> 24]; \ + } while (0) + +// Process a 16-byte swath of 4 strides, each of which has 4 bytes of data. +#define STEP16 \ + do { \ + STEP4(0); \ + STEP4(1); \ + STEP4(2); \ + STEP4(3); \ + p += 16; \ + } while (0) + +// Process 4 bytes that were already loaded into a word. +#define STEP4W(w) \ + do { \ + w ^= l; \ + for (size_t i = 0; i < 4; ++i) { \ + w = (w >> 8) ^ kByteExtensionTable[w & 0xff]; \ + } \ + l = w; \ + } while (0) + + // Point x at first 4-byte aligned byte in the buffer. This might be past the + // end of the buffer. + const uint8_t* x = RoundUp<4>(p); + if (x <= e) { + // Process bytes p is 4-byte aligned. + while (p != x) { + STEP1; + } + } + + if ((e - p) >= 16) { + // Load a 16-byte swath into the stride partial results. + uint32_t crc0 = ReadUint32LE(p + 0 * 4) ^ l; + uint32_t crc1 = ReadUint32LE(p + 1 * 4); + uint32_t crc2 = ReadUint32LE(p + 2 * 4); + uint32_t crc3 = ReadUint32LE(p + 3 * 4); + p += 16; + + // It is possible to get better speeds (at least on x86) by interleaving + // prefetching 256 bytes ahead with processing 64 bytes at a time. See the + // portable implementation in https://github.com/google/crc32c/. + + // Process one 16-byte swath at a time. + while ((e - p) >= 16) { + STEP16; + } + + // Advance one word at a time as far as possible. + while ((e - p) >= 4) { + STEP4(0); + uint32_t tmp = crc0; + crc0 = crc1; + crc1 = crc2; + crc2 = crc3; + crc3 = tmp; + p += 4; + } + + // Combine the 4 partial stride results. + l = 0; + STEP4W(crc0); + STEP4W(crc1); + STEP4W(crc2); + STEP4W(crc3); + } + + // Process the last few bytes. + while (p != e) { + STEP1; + } +#undef STEP4W +#undef STEP16 +#undef STEP4 +#undef STEP1 + return l ^ kCRC32Xor; +} + +} // namespace crc32c +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.h new file mode 100644 index 0000000..98fabb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/crc32c.h @@ -0,0 +1,43 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_CRC32C_H_ +#define STORAGE_LEVELDB_UTIL_CRC32C_H_ + +#include +#include + +namespace leveldb { +namespace crc32c { + +// Return the crc32c of concat(A, data[0,n-1]) where init_crc is the +// crc32c of some string A. Extend() is often used to maintain the +// crc32c of a stream of data. +uint32_t Extend(uint32_t init_crc, const char* data, size_t n); + +// Return the crc32c of data[0,n-1] +inline uint32_t Value(const char* data, size_t n) { return Extend(0, data, n); } + +static const uint32_t kMaskDelta = 0xa282ead8ul; + +// Return a masked representation of crc. +// +// Motivation: it is problematic to compute the CRC of a string that +// contains embedded CRCs. Therefore we recommend that CRCs stored +// somewhere (e.g., in files) should be masked before being stored. +inline uint32_t Mask(uint32_t crc) { + // Rotate right by 15 bits and add a constant. + return ((crc >> 15) | (crc << 17)) + kMaskDelta; +} + +// Return the crc whose masked representation is masked_crc. +inline uint32_t Unmask(uint32_t masked_crc) { + uint32_t rot = masked_crc - kMaskDelta; + return ((rot >> 17) | (rot << 15)); +} + +} // namespace crc32c +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_CRC32C_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env.cc new file mode 100644 index 0000000..6cd5f2e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/env.h" + +namespace leveldb { + +Env::~Env() {} + +Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) { + return Status::NotSupported("NewAppendableFile", fname); +} + +SequentialFile::~SequentialFile() {} + +RandomAccessFile::~RandomAccessFile() {} + +WritableFile::~WritableFile() {} + +Logger::~Logger() {} + +FileLock::~FileLock() {} + +void Log(Logger* info_log, const char* format, ...) { + if (info_log != nullptr) { + va_list ap; + va_start(ap, format); + info_log->Logv(format, ap); + va_end(ap); + } +} + +static Status DoWriteStringToFile(Env* env, const Slice& data, + const std::string& fname, bool should_sync) { + WritableFile* file; + Status s = env->NewWritableFile(fname, &file); + if (!s.ok()) { + return s; + } + s = file->Append(data); + if (s.ok() && should_sync) { + s = file->Sync(); + } + if (s.ok()) { + s = file->Close(); + } + delete file; // Will auto-close if we did not close above + if (!s.ok()) { + env->DeleteFile(fname); + } + return s; +} + +Status WriteStringToFile(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, false); +} + +Status WriteStringToFileSync(Env* env, const Slice& data, + const std::string& fname) { + return DoWriteStringToFile(env, data, fname, true); +} + +Status ReadFileToString(Env* env, const std::string& fname, std::string* data) { + data->clear(); + SequentialFile* file; + Status s = env->NewSequentialFile(fname, &file); + if (!s.ok()) { + return s; + } + static const int kBufferSize = 8192; + char* space = new char[kBufferSize]; + while (true) { + Slice fragment; + s = file->Read(kBufferSize, &fragment, space); + if (!s.ok()) { + break; + } + data->append(fragment.data(), fragment.size()); + if (fragment.empty()) { + break; + } + } + delete[] space; + delete file; + return s; +} + +EnvWrapper::~EnvWrapper() {} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix.cc new file mode 100644 index 0000000..8c74f5a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix.cc @@ -0,0 +1,876 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "leveldb/status.h" +#include "port/port.h" +#include "port/thread_annotations.h" +#include "util/env_posix_test_helper.h" +#include "util/posix_logger.h" + +namespace leveldb { + +namespace { + +// Set by EnvPosixTestHelper::SetReadOnlyMMapLimit() and MaxOpenFiles(). +int g_open_read_only_file_limit = -1; + +// Up to 1000 mmap regions for 64-bit binaries; none for 32-bit. +constexpr const int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0; + +// Can be set using EnvPosixTestHelper::SetReadOnlyMMapLimit. +int g_mmap_limit = kDefaultMmapLimit; + +constexpr const size_t kWritableFileBufferSize = 65536; + +Status PosixError(const std::string& context, int error_number) { + if (error_number == ENOENT) { + return Status::NotFound(context, std::strerror(error_number)); + } else { + return Status::IOError(context, std::strerror(error_number)); + } +} + +// Helper class to limit resource usage to avoid exhaustion. +// Currently used to limit read-only file descriptors and mmap file usage +// so that we do not run out of file descriptors or virtual memory, or run into +// kernel performance problems for very large databases. +class Limiter { + public: + // Limit maximum number of resources to |max_acquires|. + Limiter(int max_acquires) : acquires_allowed_(max_acquires) {} + + Limiter(const Limiter&) = delete; + Limiter operator=(const Limiter&) = delete; + + // If another resource is available, acquire it and return true. + // Else return false. + bool Acquire() { + int old_acquires_allowed = + acquires_allowed_.fetch_sub(1, std::memory_order_relaxed); + + if (old_acquires_allowed > 0) return true; + + acquires_allowed_.fetch_add(1, std::memory_order_relaxed); + return false; + } + + // Release a resource acquired by a previous call to Acquire() that returned + // true. + void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); } + + private: + // The number of available resources. + // + // This is a counter and is not tied to the invariants of any other class, so + // it can be operated on safely using std::memory_order_relaxed. + std::atomic acquires_allowed_; +}; + +// Implements sequential read access in a file using read(). +// +// Instances of this class are thread-friendly but not thread-safe, as required +// by the SequentialFile API. +class PosixSequentialFile final : public SequentialFile { + public: + PosixSequentialFile(std::string filename, int fd) + : fd_(fd), filename_(filename) {} + ~PosixSequentialFile() override { close(fd_); } + + Status Read(size_t n, Slice* result, char* scratch) override { + Status status; + while (true) { + ::ssize_t read_size = ::read(fd_, scratch, n); + if (read_size < 0) { // Read error. + if (errno == EINTR) { + continue; // Retry + } + status = PosixError(filename_, errno); + break; + } + *result = Slice(scratch, read_size); + break; + } + return status; + } + + Status Skip(uint64_t n) override { + if (::lseek(fd_, n, SEEK_CUR) == static_cast(-1)) { + return PosixError(filename_, errno); + } + return Status::OK(); + } + + private: + const int fd_; + const std::string filename_; +}; + +// Implements random read access in a file using pread(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixRandomAccessFile final : public RandomAccessFile { + public: + // The new instance takes ownership of |fd|. |fd_limiter| must outlive this + // instance, and will be used to determine if . + PosixRandomAccessFile(std::string filename, int fd, Limiter* fd_limiter) + : has_permanent_fd_(fd_limiter->Acquire()), + fd_(has_permanent_fd_ ? fd : -1), + fd_limiter_(fd_limiter), + filename_(std::move(filename)) { + if (!has_permanent_fd_) { + assert(fd_ == -1); + ::close(fd); // The file will be opened on every read. + } + } + + ~PosixRandomAccessFile() override { + if (has_permanent_fd_) { + assert(fd_ != -1); + ::close(fd_); + fd_limiter_->Release(); + } + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + int fd = fd_; + if (!has_permanent_fd_) { + fd = ::open(filename_.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename_, errno); + } + } + + assert(fd != -1); + + Status status; + ssize_t read_size = ::pread(fd, scratch, n, static_cast(offset)); + *result = Slice(scratch, (read_size < 0) ? 0 : read_size); + if (read_size < 0) { + // An error: return a non-ok status. + status = PosixError(filename_, errno); + } + if (!has_permanent_fd_) { + // Close the temporary file descriptor opened earlier. + assert(fd != fd_); + ::close(fd); + } + return status; + } + + private: + const bool has_permanent_fd_; // If false, the file is opened on every read. + const int fd_; // -1 if has_permanent_fd_ is false. + Limiter* const fd_limiter_; + const std::string filename_; +}; + +// Implements random read access in a file using mmap(). +// +// Instances of this class are thread-safe, as required by the RandomAccessFile +// API. Instances are immutable and Read() only calls thread-safe library +// functions. +class PosixMmapReadableFile final : public RandomAccessFile { + public: + // mmap_base[0, length-1] points to the memory-mapped contents of the file. It + // must be the result of a successful call to mmap(). This instances takes + // over the ownership of the region. + // + // |mmap_limiter| must outlive this instance. The caller must have already + // aquired the right to use one mmap region, which will be released when this + // instance is destroyed. + PosixMmapReadableFile(std::string filename, char* mmap_base, size_t length, + Limiter* mmap_limiter) + : mmap_base_(mmap_base), + length_(length), + mmap_limiter_(mmap_limiter), + filename_(std::move(filename)) {} + + ~PosixMmapReadableFile() override { + ::munmap(static_cast(mmap_base_), length_); + mmap_limiter_->Release(); + } + + Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override { + if (offset + n > length_) { + *result = Slice(); + return PosixError(filename_, EINVAL); + } + + *result = Slice(mmap_base_ + offset, n); + return Status::OK(); + } + + private: + char* const mmap_base_; + const size_t length_; + Limiter* const mmap_limiter_; + const std::string filename_; +}; + +class PosixWritableFile final : public WritableFile { + public: + PosixWritableFile(std::string filename, int fd) + : pos_(0), + fd_(fd), + is_manifest_(IsManifest(filename)), + filename_(std::move(filename)), + dirname_(Dirname(filename_)) {} + + ~PosixWritableFile() override { + if (fd_ >= 0) { + // Ignoring any potential errors + Close(); + } + } + + Status Append(const Slice& data) override { + size_t write_size = data.size(); + const char* write_data = data.data(); + + // Fit as much as possible into buffer. + size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_); + std::memcpy(buf_ + pos_, write_data, copy_size); + write_data += copy_size; + write_size -= copy_size; + pos_ += copy_size; + if (write_size == 0) { + return Status::OK(); + } + + // Can't fit in buffer, so need to do at least one write. + Status status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + // Small writes go to buffer, large writes are written directly. + if (write_size < kWritableFileBufferSize) { + std::memcpy(buf_, write_data, write_size); + pos_ = write_size; + return Status::OK(); + } + return WriteUnbuffered(write_data, write_size); + } + + Status Close() override { + Status status = FlushBuffer(); + const int close_result = ::close(fd_); + if (close_result < 0 && status.ok()) { + status = PosixError(filename_, errno); + } + fd_ = -1; + return status; + } + + Status Flush() override { return FlushBuffer(); } + + Status Sync() override { + // Ensure new files referred to by the manifest are in the filesystem. + // + // This needs to happen before the manifest file is flushed to disk, to + // avoid crashing in a state where the manifest refers to files that are not + // yet on disk. + Status status = SyncDirIfManifest(); + if (!status.ok()) { + return status; + } + + status = FlushBuffer(); + if (!status.ok()) { + return status; + } + + return SyncFd(fd_, filename_); + } + + private: + Status FlushBuffer() { + Status status = WriteUnbuffered(buf_, pos_); + pos_ = 0; + return status; + } + + Status WriteUnbuffered(const char* data, size_t size) { + while (size > 0) { + ssize_t write_result = ::write(fd_, data, size); + if (write_result < 0) { + if (errno == EINTR) { + continue; // Retry + } + return PosixError(filename_, errno); + } + data += write_result; + size -= write_result; + } + return Status::OK(); + } + + Status SyncDirIfManifest() { + Status status; + if (!is_manifest_) { + return status; + } + + int fd = ::open(dirname_.c_str(), O_RDONLY); + if (fd < 0) { + status = PosixError(dirname_, errno); + } else { + status = SyncFd(fd, dirname_); + ::close(fd); + } + return status; + } + + // Ensures that all the caches associated with the given file descriptor's + // data are flushed all the way to durable media, and can withstand power + // failures. + // + // The path argument is only used to populate the description string in the + // returned Status if an error occurs. + static Status SyncFd(int fd, const std::string& fd_path) { +#if HAVE_FULLFSYNC + // On macOS and iOS, fsync() doesn't guarantee durability past power + // failures. fcntl(F_FULLFSYNC) is required for that purpose. Some + // filesystems don't support fcntl(F_FULLFSYNC), and require a fallback to + // fsync(). + if (::fcntl(fd, F_FULLFSYNC) == 0) { + return Status::OK(); + } +#endif // HAVE_FULLFSYNC + +#if HAVE_FDATASYNC + bool sync_success = ::fdatasync(fd) == 0; +#else + bool sync_success = ::fsync(fd) == 0; +#endif // HAVE_FDATASYNC + + if (sync_success) { + return Status::OK(); + } + return PosixError(fd_path, errno); + } + + // Returns the directory name in a path pointing to a file. + // + // Returns "." if the path does not contain any directory separator. + static std::string Dirname(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return std::string("."); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return filename.substr(0, separator_pos); + } + + // Extracts the file name from a path pointing to a file. + // + // The returned Slice points to |filename|'s data buffer, so it is only valid + // while |filename| is alive and unchanged. + static Slice Basename(const std::string& filename) { + std::string::size_type separator_pos = filename.rfind('/'); + if (separator_pos == std::string::npos) { + return Slice(filename); + } + // The filename component should not contain a path separator. If it does, + // the splitting was done incorrectly. + assert(filename.find('/', separator_pos + 1) == std::string::npos); + + return Slice(filename.data() + separator_pos + 1, + filename.length() - separator_pos - 1); + } + + // True if the given file is a manifest file. + static bool IsManifest(const std::string& filename) { + return Basename(filename).starts_with("MANIFEST"); + } + + // buf_[0, pos_ - 1] contains data to be written to fd_. + char buf_[kWritableFileBufferSize]; + size_t pos_; + int fd_; + + const bool is_manifest_; // True if the file's name starts with MANIFEST. + const std::string filename_; + const std::string dirname_; // The directory of filename_. +}; + +int LockOrUnlock(int fd, bool lock) { + errno = 0; + struct ::flock file_lock_info; + std::memset(&file_lock_info, 0, sizeof(file_lock_info)); + file_lock_info.l_type = (lock ? F_WRLCK : F_UNLCK); + file_lock_info.l_whence = SEEK_SET; + file_lock_info.l_start = 0; + file_lock_info.l_len = 0; // Lock/unlock entire file. + return ::fcntl(fd, F_SETLK, &file_lock_info); +} + +// Instances are thread-safe because they are immutable. +class PosixFileLock : public FileLock { + public: + PosixFileLock(int fd, std::string filename) + : fd_(fd), filename_(std::move(filename)) {} + + int fd() const { return fd_; } + const std::string& filename() const { return filename_; } + + private: + const int fd_; + const std::string filename_; +}; + +// Tracks the files locked by PosixEnv::LockFile(). +// +// We maintain a separate set instead of relying on fcntrl(F_SETLK) because +// fcntl(F_SETLK) does not provide any protection against multiple uses from the +// same process. +// +// Instances are thread-safe because all member data is guarded by a mutex. +class PosixLockTable { + public: + bool Insert(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + bool succeeded = locked_files_.insert(fname).second; + mu_.Unlock(); + return succeeded; + } + void Remove(const std::string& fname) LOCKS_EXCLUDED(mu_) { + mu_.Lock(); + locked_files_.erase(fname); + mu_.Unlock(); + } + + private: + port::Mutex mu_; + std::set locked_files_ GUARDED_BY(mu_); +}; + +class PosixEnv : public Env { + public: + PosixEnv(); + ~PosixEnv() override { + static char msg[] = "PosixEnv singleton destroyed. Unsupported behavior!\n"; + std::fwrite(msg, 1, sizeof(msg), stderr); + std::abort(); + } + + Status NewSequentialFile(const std::string& filename, + SequentialFile** result) override { + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixSequentialFile(filename, fd); + return Status::OK(); + } + + Status NewRandomAccessFile(const std::string& filename, + RandomAccessFile** result) override { + *result = nullptr; + int fd = ::open(filename.c_str(), O_RDONLY); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!mmap_limiter_.Acquire()) { + *result = new PosixRandomAccessFile(filename, fd, &fd_limiter_); + return Status::OK(); + } + + uint64_t file_size; + Status status = GetFileSize(filename, &file_size); + if (status.ok()) { + void* mmap_base = + ::mmap(/*addr=*/nullptr, file_size, PROT_READ, MAP_SHARED, fd, 0); + if (mmap_base != MAP_FAILED) { + *result = new PosixMmapReadableFile(filename, + reinterpret_cast(mmap_base), + file_size, &mmap_limiter_); + } else { + status = PosixError(filename, errno); + } + } + ::close(fd); + if (!status.ok()) { + mmap_limiter_.Release(); + } + return status; + } + + Status NewWritableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_TRUNC | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + Status NewAppendableFile(const std::string& filename, + WritableFile** result) override { + int fd = ::open(filename.c_str(), O_APPEND | O_WRONLY | O_CREAT, 0644); + if (fd < 0) { + *result = nullptr; + return PosixError(filename, errno); + } + + *result = new PosixWritableFile(filename, fd); + return Status::OK(); + } + + bool FileExists(const std::string& filename) override { + return ::access(filename.c_str(), F_OK) == 0; + } + + Status GetChildren(const std::string& directory_path, + std::vector* result) override { + result->clear(); + ::DIR* dir = ::opendir(directory_path.c_str()); + if (dir == nullptr) { + return PosixError(directory_path, errno); + } + struct ::dirent* entry; + while ((entry = ::readdir(dir)) != nullptr) { + result->emplace_back(entry->d_name); + } + ::closedir(dir); + return Status::OK(); + } + + Status DeleteFile(const std::string& filename) override { + if (::unlink(filename.c_str()) != 0) { + return PosixError(filename, errno); + } + return Status::OK(); + } + + Status CreateDir(const std::string& dirname) override { + if (::mkdir(dirname.c_str(), 0755) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status DeleteDir(const std::string& dirname) override { + if (::rmdir(dirname.c_str()) != 0) { + return PosixError(dirname, errno); + } + return Status::OK(); + } + + Status GetFileSize(const std::string& filename, uint64_t* size) override { + struct ::stat file_stat; + if (::stat(filename.c_str(), &file_stat) != 0) { + *size = 0; + return PosixError(filename, errno); + } + *size = file_stat.st_size; + return Status::OK(); + } + + Status RenameFile(const std::string& from, const std::string& to) override { + if (std::rename(from.c_str(), to.c_str()) != 0) { + return PosixError(from, errno); + } + return Status::OK(); + } + + Status LockFile(const std::string& filename, FileLock** lock) override { + *lock = nullptr; + + int fd = ::open(filename.c_str(), O_RDWR | O_CREAT, 0644); + if (fd < 0) { + return PosixError(filename, errno); + } + + if (!locks_.Insert(filename)) { + ::close(fd); + return Status::IOError("lock " + filename, "already held by process"); + } + + if (LockOrUnlock(fd, true) == -1) { + int lock_errno = errno; + ::close(fd); + locks_.Remove(filename); + return PosixError("lock " + filename, lock_errno); + } + + *lock = new PosixFileLock(fd, filename); + return Status::OK(); + } + + Status UnlockFile(FileLock* lock) override { + PosixFileLock* posix_file_lock = static_cast(lock); + if (LockOrUnlock(posix_file_lock->fd(), false) == -1) { + return PosixError("unlock " + posix_file_lock->filename(), errno); + } + locks_.Remove(posix_file_lock->filename()); + ::close(posix_file_lock->fd()); + delete posix_file_lock; + return Status::OK(); + } + + void Schedule(void (*background_work_function)(void* background_work_arg), + void* background_work_arg) override; + + void StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) override; + + Status GetTestDirectory(std::string* result) override { + const char* env = std::getenv("TEST_TMPDIR"); + if (env && env[0] != '\0') { + *result = env; + } else { + char buf[100]; + std::snprintf(buf, sizeof(buf), "/tmp/leveldbtest-%d", + static_cast(::geteuid())); + *result = buf; + } + + // The CreateDir status is ignored because the directory may already exist. + CreateDir(*result); + + return Status::OK(); + } + + Status NewLogger(const std::string& filename, Logger** result) override { + std::FILE* fp = std::fopen(filename.c_str(), "w"); + if (fp == nullptr) { + *result = nullptr; + return PosixError(filename, errno); + } else { + *result = new PosixLogger(fp); + return Status::OK(); + } + } + + uint64_t NowMicros() override { + static constexpr uint64_t kUsecondsPerSecond = 1000000; + struct ::timeval tv; + ::gettimeofday(&tv, nullptr); + return static_cast(tv.tv_sec) * kUsecondsPerSecond + tv.tv_usec; + } + + void SleepForMicroseconds(int micros) override { ::usleep(micros); } + + private: + void BackgroundThreadMain(); + + static void BackgroundThreadEntryPoint(PosixEnv* env) { + env->BackgroundThreadMain(); + } + + // Stores the work item data in a Schedule() call. + // + // Instances are constructed on the thread calling Schedule() and used on the + // background thread. + // + // This structure is thread-safe beacuse it is immutable. + struct BackgroundWorkItem { + explicit BackgroundWorkItem(void (*function)(void* arg), void* arg) + : function(function), arg(arg) {} + + void (*const function)(void*); + void* const arg; + }; + + port::Mutex background_work_mutex_; + port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_); + bool started_background_thread_ GUARDED_BY(background_work_mutex_); + + std::queue background_work_queue_ + GUARDED_BY(background_work_mutex_); + + PosixLockTable locks_; // Thread-safe. + Limiter mmap_limiter_; // Thread-safe. + Limiter fd_limiter_; // Thread-safe. +}; + +// Return the maximum number of concurrent mmaps. +int MaxMmaps() { return g_mmap_limit; } + +// Return the maximum number of read-only files to keep open. +int MaxOpenFiles() { + if (g_open_read_only_file_limit >= 0) { + return g_open_read_only_file_limit; + } + struct ::rlimit rlim; + if (::getrlimit(RLIMIT_NOFILE, &rlim)) { + // getrlimit failed, fallback to hard-coded default. + g_open_read_only_file_limit = 50; + } else if (rlim.rlim_cur == RLIM_INFINITY) { + g_open_read_only_file_limit = std::numeric_limits::max(); + } else { + // Allow use of 20% of available file descriptors for read-only files. + g_open_read_only_file_limit = rlim.rlim_cur / 5; + } + return g_open_read_only_file_limit; +} + +} // namespace + +PosixEnv::PosixEnv() + : background_work_cv_(&background_work_mutex_), + started_background_thread_(false), + mmap_limiter_(MaxMmaps()), + fd_limiter_(MaxOpenFiles()) {} + +void PosixEnv::Schedule( + void (*background_work_function)(void* background_work_arg), + void* background_work_arg) { + background_work_mutex_.Lock(); + + // Start the background thread, if we haven't done so already. + if (!started_background_thread_) { + started_background_thread_ = true; + std::thread background_thread(PosixEnv::BackgroundThreadEntryPoint, this); + background_thread.detach(); + } + + // If the queue is empty, the background thread may be waiting for work. + if (background_work_queue_.empty()) { + background_work_cv_.Signal(); + } + + background_work_queue_.emplace(background_work_function, background_work_arg); + background_work_mutex_.Unlock(); +} + +void PosixEnv::BackgroundThreadMain() { + while (true) { + background_work_mutex_.Lock(); + + // Wait until there is work to be done. + while (background_work_queue_.empty()) { + background_work_cv_.Wait(); + } + + assert(!background_work_queue_.empty()); + auto background_work_function = background_work_queue_.front().function; + void* background_work_arg = background_work_queue_.front().arg; + background_work_queue_.pop(); + + background_work_mutex_.Unlock(); + background_work_function(background_work_arg); + } +} + +namespace { + +// Wraps an Env instance whose destructor is never created. +// +// Intended usage: +// using PlatformSingletonEnv = SingletonEnv; +// void ConfigurePosixEnv(int param) { +// PlatformSingletonEnv::AssertEnvNotInitialized(); +// // set global configuration flags. +// } +// Env* Env::Default() { +// static PlatformSingletonEnv default_env; +// return default_env.env(); +// } +template +class SingletonEnv { + public: + SingletonEnv() { +#if !defined(NDEBUG) + env_initialized_.store(true, std::memory_order::memory_order_relaxed); +#endif // !defined(NDEBUG) + static_assert(sizeof(env_storage_) >= sizeof(EnvType), + "env_storage_ will not fit the Env"); + static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType), + "env_storage_ does not meet the Env's alignment needs"); + new (&env_storage_) EnvType(); + } + ~SingletonEnv() = default; + + SingletonEnv(const SingletonEnv&) = delete; + SingletonEnv& operator=(const SingletonEnv&) = delete; + + Env* env() { return reinterpret_cast(&env_storage_); } + + static void AssertEnvNotInitialized() { +#if !defined(NDEBUG) + assert(!env_initialized_.load(std::memory_order::memory_order_relaxed)); +#endif // !defined(NDEBUG) + } + + private: + typename std::aligned_storage::type + env_storage_; +#if !defined(NDEBUG) + static std::atomic env_initialized_; +#endif // !defined(NDEBUG) +}; + +#if !defined(NDEBUG) +template +std::atomic SingletonEnv::env_initialized_; +#endif // !defined(NDEBUG) + +using PosixDefaultEnv = SingletonEnv; + +} // namespace + +void PosixEnv::StartThread(void (*thread_main)(void* thread_main_arg), + void* thread_main_arg) { + std::thread new_thread(thread_main, thread_main_arg); + new_thread.detach(); +} + +void EnvPosixTestHelper::SetReadOnlyFDLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_open_read_only_file_limit = limit; +} + +void EnvPosixTestHelper::SetReadOnlyMMapLimit(int limit) { + PosixDefaultEnv::AssertEnvNotInitialized(); + g_mmap_limit = limit; +} + +Env* Env::Default() { + static PosixDefaultEnv env_container; + return env_container.env(); +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix_test_helper.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix_test_helper.h new file mode 100644 index 0000000..0386960 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_posix_test_helper.h @@ -0,0 +1,28 @@ +// Copyright 2017 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ + +namespace leveldb { + +class EnvPosixTest; + +// A helper for the POSIX Env to facilitate testing. +class EnvPosixTestHelper { + private: + friend class EnvPosixTest; + + // Set the maximum number of read-only files that will be opened. + // Must be called before creating an Env. + static void SetReadOnlyFDLimit(int limit); + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_POSIX_TEST_HELPER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_windows_test_helper.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_windows_test_helper.h new file mode 100644 index 0000000..e6f6020 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/env_windows_test_helper.h @@ -0,0 +1,25 @@ +// Copyright 2018 (c) The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ +#define STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ + +namespace leveldb { + +class EnvWindowsTest; + +// A helper for the Windows Env to facilitate testing. +class EnvWindowsTestHelper { + private: + friend class CorruptionTest; + friend class EnvWindowsTest; + + // Set the maximum number of read-only files that will be mapped via mmap. + // Must be called before creating an Env. + static void SetReadOnlyMMapLimit(int limit); +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_ENV_WINDOWS_TEST_HELPER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/filter_policy.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/filter_policy.cc new file mode 100644 index 0000000..90fd754 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/filter_policy.cc @@ -0,0 +1,11 @@ +// Copyright (c) 2012 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/filter_policy.h" + +namespace leveldb { + +FilterPolicy::~FilterPolicy() {} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.cc new file mode 100644 index 0000000..67dc134 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/hash.h" + +#include + +#include "util/coding.h" + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels. The real definition should be provided externally. +// This one is a fallback version for unsupported compilers. +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed) { + // Similar to murmur hash + const uint32_t m = 0xc6a4a793; + const uint32_t r = 24; + const char* limit = data + n; + uint32_t h = seed ^ (n * m); + + // Pick up four bytes at a time + while (data + 4 <= limit) { + uint32_t w = DecodeFixed32(data); + data += 4; + h += w; + h *= m; + h ^= (h >> 16); + } + + // Pick up remaining bytes + switch (limit - data) { + case 3: + h += static_cast(data[2]) << 16; + FALLTHROUGH_INTENDED; + case 2: + h += static_cast(data[1]) << 8; + FALLTHROUGH_INTENDED; + case 1: + h += static_cast(data[0]); + h *= m; + h ^= (h >> r); + break; + } + return h; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.h new file mode 100644 index 0000000..74bdb6e --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/hash.h @@ -0,0 +1,19 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Simple hash function used for internal data structures + +#ifndef STORAGE_LEVELDB_UTIL_HASH_H_ +#define STORAGE_LEVELDB_UTIL_HASH_H_ + +#include +#include + +namespace leveldb { + +uint32_t Hash(const char* data, size_t n, uint32_t seed); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HASH_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.cc new file mode 100644 index 0000000..65092c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.cc @@ -0,0 +1,272 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/histogram.h" + +#include +#include + +#include "port/port.h" + +namespace leveldb { + +const double Histogram::kBucketLimit[kNumBuckets] = { + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 12, + 14, + 16, + 18, + 20, + 25, + 30, + 35, + 40, + 45, + 50, + 60, + 70, + 80, + 90, + 100, + 120, + 140, + 160, + 180, + 200, + 250, + 300, + 350, + 400, + 450, + 500, + 600, + 700, + 800, + 900, + 1000, + 1200, + 1400, + 1600, + 1800, + 2000, + 2500, + 3000, + 3500, + 4000, + 4500, + 5000, + 6000, + 7000, + 8000, + 9000, + 10000, + 12000, + 14000, + 16000, + 18000, + 20000, + 25000, + 30000, + 35000, + 40000, + 45000, + 50000, + 60000, + 70000, + 80000, + 90000, + 100000, + 120000, + 140000, + 160000, + 180000, + 200000, + 250000, + 300000, + 350000, + 400000, + 450000, + 500000, + 600000, + 700000, + 800000, + 900000, + 1000000, + 1200000, + 1400000, + 1600000, + 1800000, + 2000000, + 2500000, + 3000000, + 3500000, + 4000000, + 4500000, + 5000000, + 6000000, + 7000000, + 8000000, + 9000000, + 10000000, + 12000000, + 14000000, + 16000000, + 18000000, + 20000000, + 25000000, + 30000000, + 35000000, + 40000000, + 45000000, + 50000000, + 60000000, + 70000000, + 80000000, + 90000000, + 100000000, + 120000000, + 140000000, + 160000000, + 180000000, + 200000000, + 250000000, + 300000000, + 350000000, + 400000000, + 450000000, + 500000000, + 600000000, + 700000000, + 800000000, + 900000000, + 1000000000, + 1200000000, + 1400000000, + 1600000000, + 1800000000, + 2000000000, + 2500000000.0, + 3000000000.0, + 3500000000.0, + 4000000000.0, + 4500000000.0, + 5000000000.0, + 6000000000.0, + 7000000000.0, + 8000000000.0, + 9000000000.0, + 1e200, +}; + +void Histogram::Clear() { + min_ = kBucketLimit[kNumBuckets - 1]; + max_ = 0; + num_ = 0; + sum_ = 0; + sum_squares_ = 0; + for (int i = 0; i < kNumBuckets; i++) { + buckets_[i] = 0; + } +} + +void Histogram::Add(double value) { + // Linear search is fast enough for our usage in db_bench + int b = 0; + while (b < kNumBuckets - 1 && kBucketLimit[b] <= value) { + b++; + } + buckets_[b] += 1.0; + if (min_ > value) min_ = value; + if (max_ < value) max_ = value; + num_++; + sum_ += value; + sum_squares_ += (value * value); +} + +void Histogram::Merge(const Histogram& other) { + if (other.min_ < min_) min_ = other.min_; + if (other.max_ > max_) max_ = other.max_; + num_ += other.num_; + sum_ += other.sum_; + sum_squares_ += other.sum_squares_; + for (int b = 0; b < kNumBuckets; b++) { + buckets_[b] += other.buckets_[b]; + } +} + +double Histogram::Median() const { return Percentile(50.0); } + +double Histogram::Percentile(double p) const { + double threshold = num_ * (p / 100.0); + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + sum += buckets_[b]; + if (sum >= threshold) { + // Scale linearly within this bucket + double left_point = (b == 0) ? 0 : kBucketLimit[b - 1]; + double right_point = kBucketLimit[b]; + double left_sum = sum - buckets_[b]; + double right_sum = sum; + double pos = (threshold - left_sum) / (right_sum - left_sum); + double r = left_point + (right_point - left_point) * pos; + if (r < min_) r = min_; + if (r > max_) r = max_; + return r; + } + } + return max_; +} + +double Histogram::Average() const { + if (num_ == 0.0) return 0; + return sum_ / num_; +} + +double Histogram::StandardDeviation() const { + if (num_ == 0.0) return 0; + double variance = (sum_squares_ * num_ - sum_ * sum_) / (num_ * num_); + return sqrt(variance); +} + +std::string Histogram::ToString() const { + std::string r; + char buf[200]; + snprintf(buf, sizeof(buf), "Count: %.0f Average: %.4f StdDev: %.2f\n", num_, + Average(), StandardDeviation()); + r.append(buf); + snprintf(buf, sizeof(buf), "Min: %.4f Median: %.4f Max: %.4f\n", + (num_ == 0.0 ? 0.0 : min_), Median(), max_); + r.append(buf); + r.append("------------------------------------------------------\n"); + const double mult = 100.0 / num_; + double sum = 0; + for (int b = 0; b < kNumBuckets; b++) { + if (buckets_[b] <= 0.0) continue; + sum += buckets_[b]; + snprintf(buf, sizeof(buf), "[ %7.0f, %7.0f ) %7.0f %7.3f%% %7.3f%% ", + ((b == 0) ? 0.0 : kBucketLimit[b - 1]), // left + kBucketLimit[b], // right + buckets_[b], // count + mult * buckets_[b], // percentage + mult * sum); // cumulative percentage + r.append(buf); + + // Add hash marks based on percentage; 20 marks for 100%. + int marks = static_cast(20 * (buckets_[b] / num_) + 0.5); + r.append(marks, '#'); + r.push_back('\n'); + } + return r; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.h new file mode 100644 index 0000000..4da60fb --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/histogram.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ +#define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ + +#include + +namespace leveldb { + +class Histogram { + public: + Histogram() {} + ~Histogram() {} + + void Clear(); + void Add(double value); + void Merge(const Histogram& other); + + std::string ToString() const; + + private: + enum { kNumBuckets = 154 }; + + double Median() const; + double Percentile(double p) const; + double Average() const; + double StandardDeviation() const; + + static const double kBucketLimit[kNumBuckets]; + + double min_; + double max_; + double num_; + double sum_; + double sum_squares_; + + double buckets_[kNumBuckets]; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.cc new file mode 100644 index 0000000..1ad8f1c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/logging.h" + +#include +#include +#include +#include + +#include + +#include "leveldb/env.h" +#include "leveldb/slice.h" + +namespace leveldb { + +void AppendNumberTo(std::string* str, uint64_t num) { + char buf[30]; + snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); + str->append(buf); +} + +void AppendEscapedStringTo(std::string* str, const Slice& value) { + for (size_t i = 0; i < value.size(); i++) { + char c = value[i]; + if (c >= ' ' && c <= '~') { + str->push_back(c); + } else { + char buf[10]; + snprintf(buf, sizeof(buf), "\\x%02x", + static_cast(c) & 0xff); + str->append(buf); + } + } +} + +std::string NumberToString(uint64_t num) { + std::string r; + AppendNumberTo(&r, num); + return r; +} + +std::string EscapeString(const Slice& value) { + std::string r; + AppendEscapedStringTo(&r, value); + return r; +} + +bool ConsumeDecimalNumber(Slice* in, uint64_t* val) { + // Constants that will be optimized away. + constexpr const uint64_t kMaxUint64 = std::numeric_limits::max(); + constexpr const char kLastDigitOfMaxUint64 = + '0' + static_cast(kMaxUint64 % 10); + + uint64_t value = 0; + + // reinterpret_cast-ing from char* to unsigned char* to avoid signedness. + const unsigned char* start = + reinterpret_cast(in->data()); + + const unsigned char* end = start + in->size(); + const unsigned char* current = start; + for (; current != end; ++current) { + const unsigned char ch = *current; + if (ch < '0' || ch > '9') break; + + // Overflow check. + // kMaxUint64 / 10 is also constant and will be optimized away. + if (value > kMaxUint64 / 10 || + (value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) { + return false; + } + + value = (value * 10) + (ch - '0'); + } + + *val = value; + const size_t digits_consumed = current - start; + in->remove_prefix(digits_consumed); + return digits_consumed != 0; +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.h new file mode 100644 index 0000000..8ff2da8 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/logging.h @@ -0,0 +1,45 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Must not be included from any .h files to avoid polluting the namespace +// with macros. + +#ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_ +#define STORAGE_LEVELDB_UTIL_LOGGING_H_ + +#include +#include + +#include + +#include "port/port.h" + +namespace leveldb { + +class Slice; +class WritableFile; + +// Append a human-readable printout of "num" to *str +void AppendNumberTo(std::string* str, uint64_t num); + +// Append a human-readable printout of "value" to *str. +// Escapes any non-printable characters found in "value". +void AppendEscapedStringTo(std::string* str, const Slice& value); + +// Return a human-readable printout of "num" +std::string NumberToString(uint64_t num); + +// Return a human-readable version of "value". +// Escapes any non-printable characters found in "value". +std::string EscapeString(const Slice& value); + +// Parse a human-readable number from "*in" into *value. On success, +// advances "*in" past the consumed number and sets "*val" to the +// numeric value. Otherwise, returns false and leaves *in in an +// unspecified state. +bool ConsumeDecimalNumber(Slice* in, uint64_t* val); + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_LOGGING_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/mutexlock.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/mutexlock.h new file mode 100644 index 0000000..0cb2e25 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/mutexlock.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ +#define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ + +#include "port/port.h" +#include "port/thread_annotations.h" + +namespace leveldb { + +// Helper class that locks a mutex on construction and unlocks the mutex when +// the destructor of the MutexLock object is invoked. +// +// Typical usage: +// +// void MyClass::MyMethod() { +// MutexLock l(&mu_); // mu_ is an instance variable +// ... some complex code, possibly with multiple return paths ... +// } + +class SCOPED_LOCKABLE MutexLock { + public: + explicit MutexLock(port::Mutex* mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) { + this->mu_->Lock(); + } + ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + port::Mutex* const mu_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/no_destructor.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/no_destructor.h new file mode 100644 index 0000000..a0d3b87 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/no_destructor.h @@ -0,0 +1,46 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ +#define STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ + +#include +#include + +namespace leveldb { + +// Wraps an instance whose destructor is never called. +// +// This is intended for use with function-level static variables. +template +class NoDestructor { + public: + template + explicit NoDestructor(ConstructorArgTypes&&... constructor_args) { + static_assert(sizeof(instance_storage_) >= sizeof(InstanceType), + "instance_storage_ is not large enough to hold the instance"); + static_assert( + alignof(decltype(instance_storage_)) >= alignof(InstanceType), + "instance_storage_ does not meet the instance's alignment requirement"); + new (&instance_storage_) + InstanceType(std::forward(constructor_args)...); + } + + ~NoDestructor() = default; + + NoDestructor(const NoDestructor&) = delete; + NoDestructor& operator=(const NoDestructor&) = delete; + + InstanceType* get() { + return reinterpret_cast(&instance_storage_); + } + + private: + typename std::aligned_storage::type instance_storage_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_NO_DESTRUCTOR_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/options.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/options.cc new file mode 100644 index 0000000..62de5bf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/options.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/options.h" + +#include "leveldb/comparator.h" +#include "leveldb/env.h" + +namespace leveldb { + +Options::Options() : comparator(BytewiseComparator()), env(Env::Default()) {} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/posix_logger.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/posix_logger.h new file mode 100644 index 0000000..28e15d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/posix_logger.h @@ -0,0 +1,130 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation that can be shared by all environments +// where enough posix functionality is available. + +#ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class PosixLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit PosixLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~PosixLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + struct ::timeval now_timeval; + ::gettimeofday(&now_timeval, nullptr); + const std::time_t now_seconds = now_timeval.tv_sec; + struct std::tm now_components; + ::localtime_r(&now_seconds, &now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.tm_year + 1900, now_components.tm_mon + 1, + now_components.tm_mday, now_components.tm_hour, now_components.tm_min, + now_components.tm_sec, static_cast(now_timeval.tv_usec), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/random.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/random.h new file mode 100644 index 0000000..76f7daf --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/random.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_RANDOM_H_ +#define STORAGE_LEVELDB_UTIL_RANDOM_H_ + +#include + +namespace leveldb { + +// A very simple random number generator. Not especially good at +// generating truly random bits, but good enough for our needs in this +// package. +class Random { + private: + uint32_t seed_; + + public: + explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) { + // Avoid bad seeds. + if (seed_ == 0 || seed_ == 2147483647L) { + seed_ = 1; + } + } + uint32_t Next() { + static const uint32_t M = 2147483647L; // 2^31-1 + static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0 + // We are computing + // seed_ = (seed_ * A) % M, where M = 2^31-1 + // + // seed_ must not be zero or M, or else all subsequent computed values + // will be zero or M respectively. For all other values, seed_ will end + // up cycling through every number in [1,M-1] + uint64_t product = seed_ * A; + + // Compute (product % M) using the fact that ((x << 31) % M) == x. + seed_ = static_cast((product >> 31) + (product & M)); + // The first reduction may overflow by 1 bit, so we may need to + // repeat. mod == M is not possible; using > allows the faster + // sign-bit-based test. + if (seed_ > M) { + seed_ -= M; + } + return seed_; + } + // Returns a uniformly distributed value in the range [0..n-1] + // REQUIRES: n > 0 + uint32_t Uniform(int n) { return Next() % n; } + + // Randomly returns true ~"1/n" of the time, and false otherwise. + // REQUIRES: n > 0 + bool OneIn(int n) { return (Next() % n) == 0; } + + // Skewed: pick "base" uniformly from range [0,max_log] and then + // return "base" random bits. The effect is to pick a number in the + // range [0,2^max_log-1] with exponential bias towards smaller numbers. + uint32_t Skewed(int max_log) { return Uniform(1 << Uniform(max_log + 1)); } +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_RANDOM_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/status.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/status.cc new file mode 100644 index 0000000..6ca8da6 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/status.cc @@ -0,0 +1,77 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "leveldb/status.h" + +#include + +#include "port/port.h" + +namespace leveldb { + +const char* Status::CopyState(const char* state) { + uint32_t size; + memcpy(&size, state, sizeof(size)); + char* result = new char[size + 5]; + memcpy(result, state, size + 5); + return result; +} + +Status::Status(Code code, const Slice& msg, const Slice& msg2) { + assert(code != kOk); + const uint32_t len1 = msg.size(); + const uint32_t len2 = msg2.size(); + const uint32_t size = len1 + (len2 ? (2 + len2) : 0); + char* result = new char[size + 5]; + memcpy(result, &size, sizeof(size)); + result[4] = static_cast(code); + memcpy(result + 5, msg.data(), len1); + if (len2) { + result[5 + len1] = ':'; + result[6 + len1] = ' '; + memcpy(result + 7 + len1, msg2.data(), len2); + } + state_ = result; +} + +std::string Status::ToString() const { + if (state_ == nullptr) { + return "OK"; + } else { + char tmp[30]; + const char* type; + switch (code()) { + case kOk: + type = "OK"; + break; + case kNotFound: + type = "NotFound: "; + break; + case kCorruption: + type = "Corruption: "; + break; + case kNotSupported: + type = "Not implemented: "; + break; + case kInvalidArgument: + type = "Invalid argument: "; + break; + case kIOError: + type = "IO error: "; + break; + default: + snprintf(tmp, sizeof(tmp), + "Unknown code(%d): ", static_cast(code())); + type = tmp; + break; + } + std::string result(type); + uint32_t length; + memcpy(&length, state_, sizeof(length)); + result.append(state_ + 5, length); + return result; + } +} + +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.cc b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.cc new file mode 100644 index 0000000..318ecfa --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#include "util/testharness.h" + +#include +#include +#include + +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { +namespace test { + +namespace { +struct Test { + const char* base; + const char* name; + void (*func)(); +}; +std::vector* tests; +} // namespace + +bool RegisterTest(const char* base, const char* name, void (*func)()) { + if (tests == nullptr) { + tests = new std::vector; + } + Test t; + t.base = base; + t.name = name; + t.func = func; + tests->push_back(t); + return true; +} + +int RunAllTests() { + const char* matcher = getenv("LEVELDB_TESTS"); + + int num = 0; + if (tests != nullptr) { + for (size_t i = 0; i < tests->size(); i++) { + const Test& t = (*tests)[i]; + if (matcher != nullptr) { + std::string name = t.base; + name.push_back('.'); + name.append(t.name); + if (strstr(name.c_str(), matcher) == nullptr) { + continue; + } + } + fprintf(stderr, "==== Test %s.%s\n", t.base, t.name); + (*t.func)(); + ++num; + } + } + fprintf(stderr, "==== PASSED %d tests\n", num); + return 0; +} + +std::string TmpDir() { + std::string dir; + Status s = Env::Default()->GetTestDirectory(&dir); + ASSERT_TRUE(s.ok()) << s.ToString(); + return dir; +} + +int RandomSeed() { + const char* env = getenv("TEST_RANDOM_SEED"); + int result = (env != nullptr ? atoi(env) : 301); + if (result <= 0) { + result = 301; + } + return result; +} + +} // namespace test +} // namespace leveldb diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.h new file mode 100644 index 0000000..72cd162 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testharness.h @@ -0,0 +1,141 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ +#define STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ + +#include +#include + +#include + +#include "leveldb/status.h" + +namespace leveldb { +namespace test { + +// Run some of the tests registered by the TEST() macro. If the +// environment variable "LEVELDB_TESTS" is not set, runs all tests. +// Otherwise, runs only the tests whose name contains the value of +// "LEVELDB_TESTS" as a substring. E.g., suppose the tests are: +// TEST(Foo, Hello) { ... } +// TEST(Foo, World) { ... } +// LEVELDB_TESTS=Hello will run the first test +// LEVELDB_TESTS=o will run both tests +// LEVELDB_TESTS=Junk will run no tests +// +// Returns 0 if all tests pass. +// Dies or returns a non-zero value if some test fails. +int RunAllTests(); + +// Return the directory to use for temporary storage. +std::string TmpDir(); + +// Return a randomization seed for this run. Typically returns the +// same number on repeated invocations of this binary, but automated +// runs may be able to vary the seed. +int RandomSeed(); + +// An instance of Tester is allocated to hold temporary state during +// the execution of an assertion. +class Tester { + private: + bool ok_; + const char* fname_; + int line_; + std::stringstream ss_; + + public: + Tester(const char* f, int l) : ok_(true), fname_(f), line_(l) {} + + ~Tester() { + if (!ok_) { + fprintf(stderr, "%s:%d:%s\n", fname_, line_, ss_.str().c_str()); + exit(1); + } + } + + Tester& Is(bool b, const char* msg) { + if (!b) { + ss_ << " Assertion failure " << msg; + ok_ = false; + } + return *this; + } + + Tester& IsOk(const Status& s) { + if (!s.ok()) { + ss_ << " " << s.ToString(); + ok_ = false; + } + return *this; + } + +#define BINARY_OP(name, op) \ + template \ + Tester& name(const X& x, const Y& y) { \ + if (!(x op y)) { \ + ss_ << " failed: " << x << (" " #op " ") << y; \ + ok_ = false; \ + } \ + return *this; \ + } + + BINARY_OP(IsEq, ==) + BINARY_OP(IsNe, !=) + BINARY_OP(IsGe, >=) + BINARY_OP(IsGt, >) + BINARY_OP(IsLe, <=) + BINARY_OP(IsLt, <) +#undef BINARY_OP + + // Attach the specified value to the error message if an error has occurred + template + Tester& operator<<(const V& value) { + if (!ok_) { + ss_ << " " << value; + } + return *this; + } +}; + +#define ASSERT_TRUE(c) ::leveldb::test::Tester(__FILE__, __LINE__).Is((c), #c) +#define ASSERT_OK(s) ::leveldb::test::Tester(__FILE__, __LINE__).IsOk((s)) +#define ASSERT_EQ(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsEq((a), (b)) +#define ASSERT_NE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsNe((a), (b)) +#define ASSERT_GE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGe((a), (b)) +#define ASSERT_GT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsGt((a), (b)) +#define ASSERT_LE(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLe((a), (b)) +#define ASSERT_LT(a, b) \ + ::leveldb::test::Tester(__FILE__, __LINE__).IsLt((a), (b)) + +#define TCONCAT(a, b) TCONCAT1(a, b) +#define TCONCAT1(a, b) a##b + +#define TEST(base, name) \ + class TCONCAT(_Test_, name) : public base { \ + public: \ + void _Run(); \ + static void _RunIt() { \ + TCONCAT(_Test_, name) t; \ + t._Run(); \ + } \ + }; \ + bool TCONCAT(_Test_ignored_, name) = ::leveldb::test::RegisterTest( \ + #base, #name, &TCONCAT(_Test_, name)::_RunIt); \ + void TCONCAT(_Test_, name)::_Run() + +// Register the specified test. Typically not used directly, but +// invoked via the macro expansion of TEST. +bool RegisterTest(const char* base, const char* name, void (*func)()); + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTHARNESS_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testutil.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testutil.h new file mode 100644 index 0000000..bb4051b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/testutil.h @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. + +#ifndef STORAGE_LEVELDB_UTIL_TESTUTIL_H_ +#define STORAGE_LEVELDB_UTIL_TESTUTIL_H_ + +#include "helpers/memenv/memenv.h" +#include "leveldb/env.h" +#include "leveldb/slice.h" +#include "util/random.h" + +namespace leveldb { +namespace test { + +// Store in *dst a random string of length "len" and return a Slice that +// references the generated data. +Slice RandomString(Random* rnd, int len, std::string* dst); + +// Return a random key with the specified length that may contain interesting +// characters (e.g. \x00, \xff, etc.). +std::string RandomKey(Random* rnd, int len); + +// Store in *dst a string of length "len" that will compress to +// "N*compressed_fraction" bytes and return a Slice that references +// the generated data. +Slice CompressibleString(Random* rnd, double compressed_fraction, size_t len, + std::string* dst); + +// A wrapper that allows injection of errors. +class ErrorEnv : public EnvWrapper { + public: + bool writable_file_error_; + int num_writable_file_errors_; + + ErrorEnv() + : EnvWrapper(NewMemEnv(Env::Default())), + writable_file_error_(false), + num_writable_file_errors_(0) {} + ~ErrorEnv() override { delete target(); } + + Status NewWritableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewWritableFile(fname, result); + } + + Status NewAppendableFile(const std::string& fname, + WritableFile** result) override { + if (writable_file_error_) { + ++num_writable_file_errors_; + *result = nullptr; + return Status::IOError(fname, "fake error"); + } + return target()->NewAppendableFile(fname, result); + } +}; + +} // namespace test +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_ diff --git a/PediatricPancreas_Storyboard/Pods/leveldb-library/util/windows_logger.h b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/windows_logger.h new file mode 100644 index 0000000..9296063 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/leveldb-library/util/windows_logger.h @@ -0,0 +1,124 @@ +// Copyright (c) 2018 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Logger implementation for the Windows platform. + +#ifndef STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ +#define STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ + +#include +#include +#include +#include +#include +#include + +#include "leveldb/env.h" + +namespace leveldb { + +class WindowsLogger final : public Logger { + public: + // Creates a logger that writes to the given file. + // + // The PosixLogger instance takes ownership of the file handle. + explicit WindowsLogger(std::FILE* fp) : fp_(fp) { assert(fp != nullptr); } + + ~WindowsLogger() override { std::fclose(fp_); } + + void Logv(const char* format, va_list arguments) override { + // Record the time as close to the Logv() call as possible. + SYSTEMTIME now_components; + ::GetLocalTime(&now_components); + + // Record the thread ID. + constexpr const int kMaxThreadIdSize = 32; + std::ostringstream thread_stream; + thread_stream << std::this_thread::get_id(); + std::string thread_id = thread_stream.str(); + if (thread_id.size() > kMaxThreadIdSize) { + thread_id.resize(kMaxThreadIdSize); + } + + // We first attempt to print into a stack-allocated buffer. If this attempt + // fails, we make a second attempt with a dynamically allocated buffer. + constexpr const int kStackBufferSize = 512; + char stack_buffer[kStackBufferSize]; + static_assert(sizeof(stack_buffer) == static_cast(kStackBufferSize), + "sizeof(char) is expected to be 1 in C++"); + + int dynamic_buffer_size = 0; // Computed in the first iteration. + for (int iteration = 0; iteration < 2; ++iteration) { + const int buffer_size = + (iteration == 0) ? kStackBufferSize : dynamic_buffer_size; + char* const buffer = + (iteration == 0) ? stack_buffer : new char[dynamic_buffer_size]; + + // Print the header into the buffer. + int buffer_offset = snprintf( + buffer, buffer_size, "%04d/%02d/%02d-%02d:%02d:%02d.%06d %s ", + now_components.wYear, now_components.wMonth, now_components.wDay, + now_components.wHour, now_components.wMinute, now_components.wSecond, + static_cast(now_components.wMilliseconds * 1000), + thread_id.c_str()); + + // The header can be at most 28 characters (10 date + 15 time + + // 3 delimiters) plus the thread ID, which should fit comfortably into the + // static buffer. + assert(buffer_offset <= 28 + kMaxThreadIdSize); + static_assert(28 + kMaxThreadIdSize < kStackBufferSize, + "stack-allocated buffer may not fit the message header"); + assert(buffer_offset < buffer_size); + + // Print the message into the buffer. + std::va_list arguments_copy; + va_copy(arguments_copy, arguments); + buffer_offset += + std::vsnprintf(buffer + buffer_offset, buffer_size - buffer_offset, + format, arguments_copy); + va_end(arguments_copy); + + // The code below may append a newline at the end of the buffer, which + // requires an extra character. + if (buffer_offset >= buffer_size - 1) { + // The message did not fit into the buffer. + if (iteration == 0) { + // Re-run the loop and use a dynamically-allocated buffer. The buffer + // will be large enough for the log message, an extra newline and a + // null terminator. + dynamic_buffer_size = buffer_offset + 2; + continue; + } + + // The dynamically-allocated buffer was incorrectly sized. This should + // not happen, assuming a correct implementation of (v)snprintf. Fail + // in tests, recover by truncating the log message in production. + assert(false); + buffer_offset = buffer_size - 1; + } + + // Add a newline if necessary. + if (buffer[buffer_offset - 1] != '\n') { + buffer[buffer_offset] = '\n'; + ++buffer_offset; + } + + assert(buffer_offset <= buffer_size); + std::fwrite(buffer, 1, buffer_offset, fp_); + std::fflush(fp_); + + if (iteration != 0) { + delete[] buffer; + } + break; + } + } + + private: + std::FILE* const fp_; +}; + +} // namespace leveldb + +#endif // STORAGE_LEVELDB_UTIL_WINDOWS_LOGGER_H_ diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/LICENSE.txt b/PediatricPancreas_Storyboard/Pods/nanopb/LICENSE.txt new file mode 100644 index 0000000..d11c9af --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/README.md b/PediatricPancreas_Storyboard/Pods/nanopb/README.md new file mode 100644 index 0000000..07860f0 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/README.md @@ -0,0 +1,71 @@ +Nanopb - Protocol Buffers for Embedded Systems +============================================== + +[![Build Status](https://travis-ci.org/nanopb/nanopb.svg?branch=master)](https://travis-ci.org/nanopb/nanopb) + +Nanopb is a small code-size Protocol Buffers implementation in ansi C. It is +especially suitable for use in microcontrollers, but fits any memory +restricted system. + +* **Homepage:** https://jpa.kapsi.fi/nanopb/ +* **Documentation:** https://jpa.kapsi.fi/nanopb/docs/ +* **Downloads:** https://jpa.kapsi.fi/nanopb/download/ +* **Forum:** https://groups.google.com/forum/#!forum/nanopb + + + +Using the nanopb library +------------------------ +To use the nanopb library, you need to do two things: + +1. Compile your .proto files for nanopb, using protoc. +2. Include pb_encode.c, pb_decode.c and pb_common.c in your project. + +The easiest way to get started is to study the project in "examples/simple". +It contains a Makefile, which should work directly under most Linux systems. +However, for any other kind of build system, see the manual steps in +README.txt in that folder. + + + +Using the Protocol Buffers compiler (protoc) +-------------------------------------------- +The nanopb generator is implemented as a plugin for the Google's own protoc +compiler. This has the advantage that there is no need to reimplement the +basic parsing of .proto files. However, it does mean that you need the +Google's protobuf library in order to run the generator. + +If you have downloaded a binary package for nanopb (either Windows, Linux or +Mac OS X version), the 'protoc' binary is included in the 'generator-bin' +folder. In this case, you are ready to go. Simply run this command: + + generator-bin/protoc --nanopb_out=. myprotocol.proto + +However, if you are using a git checkout or a plain source distribution, you +need to provide your own version of protoc and the Google's protobuf library. +On Linux, the necessary packages are protobuf-compiler and python-protobuf. +On Windows, you can either build Google's protobuf library from source or use +one of the binary distributions of it. In either case, if you use a separate +protoc, you need to manually give the path to nanopb generator: + + protoc --plugin=protoc-gen-nanopb=nanopb/generator/protoc-gen-nanopb ... + + + +Running the tests +----------------- +If you want to perform further development of the nanopb core, or to verify +its functionality using your compiler and platform, you'll want to run the +test suite. The build rules for the test suite are implemented using Scons, +so you need to have that installed. To run the tests: + + cd tests + scons + +This will show the progress of various test cases. If the output does not +end in an error, the test cases were successful. + +Note: Mac OS X by default aliases 'clang' as 'gcc', while not actually +supporting the same command line options as gcc does. To run tests on +Mac OS X, use: "scons CC=clang CXX=clang". Same way can be used to run +tests with different compilers on any platform. diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb.h b/PediatricPancreas_Storyboard/Pods/nanopb/pb.h new file mode 100644 index 0000000..174a84b --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb.h @@ -0,0 +1,593 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ + + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.3.9.1 + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif +#else +#define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x04 + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x05 + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x06 + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x07 + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x08 + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0A +#define PB_LTYPE_MASK 0x0F + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#elif defined(PB_FIELD_16BIT) + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. + */ +PB_PACKED_STRUCT_START +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; +} pb_packed; +PB_PACKED_STRUCT_END + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; +#endif + + /* Free arg for use by callback */ + void *arg; +}; + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 30 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside an union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. + */ +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. + */ +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} + +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) + +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for repeated static fixed count fields.*/ +#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + 0, \ + pb_membersize(message, field[0]), \ + pb_arraysize(message, field), ptr} + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.c b/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.c new file mode 100644 index 0000000..4fb7186 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.c @@ -0,0 +1,97 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = fields; + iter->pos = fields; + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + + return (iter->pos->tag != 0); +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + const pb_field_t *prev_field = iter->pos; + + if (prev_field->tag == 0) + { + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos++; + + if (iter->pos->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, iter->start, iter->dest_struct); + return false; + } + else + { + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF && + iter->pos->data_offset == PB_SIZE_MAX) + { + /* Don't advance pointers inside unions */ + return true; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) + { + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; + } + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) + { + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return true; + } +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + const pb_field_t *start = iter->pos; + + do { + if (iter->pos->tag == tag && + PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION) + { + /* Found the wanted field */ + return true; + } + + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + /* Searched all the way back to start, and found nothing. */ + return false; +} + + diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.h b/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.h new file mode 100644 index 0000000..60b3d37 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_common.h @@ -0,0 +1,42 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.c b/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.c new file mode 100644 index 0000000..4b80e81 --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.c @@ -0,0 +1,1508 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + return pb_read(stream, NULL, length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = size; + stream->bytes_left -= size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_OPTIONAL: + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; + return func(stream, iter->pos, iter->pData); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < iter->pos->array_size) + { + void *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + (*size)++; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)iter->pSize; + char *pItem = (char*)iter->pData + iter->pos->data_size * (*size); + + if ((*size)++ >= iter->pos->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return func(stream, iter->pos, pItem); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)iter->pSize = iter->pos->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(iter->pData, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t*)iter->pos->ptr, iter->pData); + } + return func(stream, iter->pos, iter->pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) +{ + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_STRING || + PB_LTYPE(iter->pos->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + memset(pItem, 0, iter->pos->data_size); + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, pItem); + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(iter); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + pb_type_t type; + pb_decoder_t func; + + type = iter->pos->type; + func = PB_DECODERS[PB_LTYPE(type)]; + + switch (PB_HTYPE(type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + pb_release_single_field(iter); + } + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = iter->pos->tag; + } + + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) + { + return func(stream, iter->pos, iter->pData); + } + else + { + if (!allocate_field(stream, iter->pData, iter->pos->data_size, 1)) + return false; + + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, iter->pos, *(void**)iter->pData); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; + size_t allocated_size = *size; + void *pItem; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + allocated_size += (substream.bytes_left - 1) / iter->pos->data_size + 1; + + if (!allocate_field(&substream, iter->pData, iter->pos->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + pItem = *(char**)iter->pData + iter->pos->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, iter->pos, pItem)) + { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, iter->pData, iter->pos->data_size, *size)) + return false; + + pItem = *(char**)iter->pData + iter->pos->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, iter->pos, pItem); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + if (!pCallback->funcs.decode(&substream, iter->pos, arg)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return pCallback->funcs.decode(&substream, iter->pos, arg); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, iter)) + return false; + } +#endif + + switch (PB_ATYPE(iter->pos->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, iter); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, iter); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, iter); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + pb_field_iter_t iter; + + if (field->tag != tag) + return true; + + iter_from_extension(&iter, extension); + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + const pb_field_t *start = iter->pos; + + do { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->pos != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static void pb_field_set_to_default(pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)iter->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)iter->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE(iter->pos->type) == PB_LTYPE_SUBMESSAGE) + { + /* Initialize submessage to defaults */ + pb_message_set_to_defaults((const pb_field_t *) iter->pos->ptr, iter->pData); + } + else if (iter->pos->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, iter->pos->ptr, iter->pos->data_size); + } + else + { + /* Initialize to zeros */ + memset(iter->pData, 0, iter->pos->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)iter->pData = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)iter->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } +} + +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); +} + +/********************* + * Decode all fields * + *********************/ + +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + const uint32_t allbits = ~(uint32_t)0; + uint32_t extension_range_start = 0; + pb_field_iter_t iter; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + const pb_field_t *fixed_count_field = NULL; + pb_size_t fixed_count_size = 0; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (!pb_field_iter_find(&iter, tag)) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.pos->tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED + && iter.pSize == iter.pData) + { + if (fixed_count_field != iter.pos) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.pos; + fixed_count_size = 0; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != NULL && + fixed_count_size != fixed_count_field->array_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + unsigned req_field_count; + pb_type_t last_type; + unsigned i; + do { + req_field_count = iter.required_field_index; + last_type = iter.pos->type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.pos->tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + bool status; + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_noinit(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) +{ + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = iter->pos->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(iter, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(iter); + + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + + return true; +} + +static void pb_release_single_field(const pb_field_iter_t *iter) +{ + pb_type_t type; + type = iter->pos->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)iter->pSize != iter->pos->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)iter->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); + ext = ext->next; + } + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + pItem = *(void**)iter->pData; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + if (PB_ATYPE(type) == PB_ATYPE_STATIC && iter->pSize == iter->pData) { + /* No _count field so use size of the array */ + count = iter->pos->array_size; + } else { + count = *(pb_size_t*)iter->pSize; + } + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > iter->pos->array_size) + { + /* Protect against corrupted _count fields */ + count = iter->pos->array_size; + } + } + + if (pItem) + { + while (count--) + { + pb_release((const pb_field_t*)iter->pos->ptr, pItem); + pItem = (char*)pItem + iter->pos->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)iter->pSize = 0; + } + + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; + } +} + +void pb_release(const pb_field_t fields[], void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[4]; + + if (!pb_read(stream, bytes, 4)) + return false; + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + pb_byte_t bytes[8]; + + if (!pb_read(stream, bytes, 8)) + return false; + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + + return true; +} +#endif + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; +} + +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} + +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *bdest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + bdest = *(pb_bytes_array_t**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + bdest = (pb_bytes_array_t*)dest; + } + + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + size_t alloc_size; + bool status; + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = size + 1; + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (!allocate_field(stream, dest, alloc_size, 1)) + return false; + dest = *(void**)dest; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + bool status; + pb_istream_t substream; + const pb_field_t* submsg_fields = (const pb_field_t*)field->ptr; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + status = pb_decode(&substream, submsg_fields, dest); + else + status = pb_decode_noinit(&substream, submsg_fields, dest); + + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(dest, 0, field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)dest, field->data_size); +} diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.h b/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.h new file mode 100644 index 0000000..398b24a --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_decode.h @@ -0,0 +1,175 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. + * + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. + * + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + */ +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_field_t fields[], void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for bool, enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.c b/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.c new file mode 100644 index 0000000..089172c --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.c @@ -0,0 +1,869 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t + +static bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value); +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) +{ + size_t i; + const void *p; + size_t size; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + p = pData; + for (i = 0; i < count; i++) + { + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + p = pData; + for (i = 0; i < count; i++) + { + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; + } + } + else + { + p = pData; + for (i = 0; i < count; i++) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + if (!func(stream, field, *(const void* const*)p)) + return false; + } + else + { + if (!func(stream, field, p)) + return false; + } + p = (const char*)p + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) +{ + pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; + + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) + { + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool*)pSize == false; + } + + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) + { + do + { + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) + { + /* Static optional, repeated or oneof field */ + pSize = (const char*)pData + field->size_offset; + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + } + else + { + /* Required field, always present */ + implicit_has = true; + } + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } + + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!func(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool*)pSize) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: { + pb_size_t count; + if (field->size_offset != 0) { + count = *(const pb_size_t*)pSize; + } else { + count = field->array_size; + } + if (!encode_array(stream, field, pData, count, func)) + return false; + break; + } + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + + if (!func(stream, field, pData)) + return false; + } + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return true; +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) + { + if (!callback->funcs.encode(stream, field, arg)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); + } + else + { + return encode_field(stream, field, extension->dest); + } +} + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, iter.pos, iter.pData)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, iter.pos, iter.pData)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + return pb_encode_submessage(stream, fields, src_struct); +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); +} + +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +#ifdef PB_WITHOUT_64BIT +bool checkreturn pb_encode_negative_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + size_t compensation = 32;/* we need to compensate 32 bits all set to 1 */ + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + if (compensation) + { + /* re-set all the compensation bits we can or need */ + size_t bits = compensation > 7 ? 7 : compensation; + value ^= (pb_uint64_t)((0xFFu >> (8 - bits)) << 25); /* set the number of bits needed on the lowest of the most significant 7 bits */ + compensation -= bits; + } + i++; + } + buffer[i - 1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} +#endif + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + pb_byte_t buffer[10]; + size_t i = 0; + + if (value <= 0x7F) + { + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); + } + + while (value) + { + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; + } + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + +#ifdef PB_WITHOUT_64BIT + if (value < 0) + return pb_encode_negative_varint(stream, (pb_uint64_t)value); + else +#endif + return pb_encode_varint(stream, (pb_uint64_t)value); +} + +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} + +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); +#ifndef PB_WITHOUT_64BIT + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); +#endif +} + +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)src; + + if (src == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + size_t size = 0; + size_t max_size = field->data_size; + const char *p = (const char*)src; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + max_size = (size_t)-1; + + if (src == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + } + + return pb_encode_string(stream, (const pb_byte_t*)src, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + if (field->ptr == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); +} + diff --git a/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.h b/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.h new file mode 100644 index 0000000..8bf78dd --- /dev/null +++ b/PediatricPancreas_Storyboard/Pods/nanopb/pb_encode.h @@ -0,0 +1,170 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. + */ +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/.gitattributes b/PediatricPancreas_Storyboard/ResearchKit-master/.gitattributes new file mode 100755 index 0000000..ebd151c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/.gitattributes @@ -0,0 +1 @@ +LFS-Files/** filter=lfs diff=lfs merge=lfs -text diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/.gitignore b/PediatricPancreas_Storyboard/ResearchKit-master/.gitignore new file mode 100755 index 0000000..5d16a9e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/.gitignore @@ -0,0 +1,21 @@ +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +.DS_Store +*.pyc diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/.lfsconfig b/PediatricPancreas_Storyboard/ResearchKit-master/.lfsconfig new file mode 100755 index 0000000..2cf1bce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/.lfsconfig @@ -0,0 +1,2 @@ +[lfs] + fetchexclude = * diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/.travis.yml b/PediatricPancreas_Storyboard/ResearchKit-master/.travis.yml new file mode 100755 index 0000000..b452e30 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/.travis.yml @@ -0,0 +1,5 @@ +language: objective-c +osx_image: xcode11 +xcode_project: ResearchKit.xcodeproj +xcode_scheme: ResearchKit +xcode_destination: platform=iOS Simulator,OS=13.0,name=iPhone 11 Pro Max diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/CONTRIBUTING.md b/PediatricPancreas_Storyboard/ResearchKit-master/CONTRIBUTING.md new file mode 100755 index 0000000..95e6cf9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/CONTRIBUTING.md @@ -0,0 +1,187 @@ +Contributing to the ResearchKit Framework +=========================== + +This page focuses on code contributions to the existing +codebase. However, other types of contributions are welcome too, in +keeping with the ResearchKit™ framework [best practices](../../wiki/best-practices). For example, +contributions of original free-to-use survey content, back-end integrations, +validation data, and analysis or processing tools are all welcome. Ask +on the [*ResearchKit* Forum](https://forums.developer.apple.com/community/researchkit) or [contact us](https://developer.apple.com/contact/researchkit/) for guidance. + + +Contributing software +--------------------- + +This page assumes you already know how to check out and build the +code. Contributions to the ResearchKit framework are expected to comply with the +[ResearchKit Contribution Terms and License Policy](#contribution); please familiarize yourself +with this policy prior to submitting a pull request. For any contribution, ensure that you own +the rights or have permission from the copyright holder. (e.g. code, images, surveys, videos +and other content you may include) + +To contribute to ResearchKit: + +1. [Choose or create an issue to work on.](#create) +2. [Create a personal fork of the ResearchKit framework.](#fork) +3. [Develop your changes in your fork.](#develop) +4. [Run the tests.](#test) +5. [Submit a pull request.](#request) +6. Make any changes requested by the reviewer, and update your pull request as needed. +7. Once accepted, your pull request will be merged into master. + +Choosing an issue to work on +---------------------------- + +To find an issue to work on, either pick something that you need for +your app, or select one of the issues from our [issue list](../../issues). Or, +consider one of the areas where we'd like to extend ResearchKit: + +* Faster 'get started' to a useful app +* More active tasks +* Data analysis for active tasks +* More consent sections +* Back end integrations + +If in doubt, bring your idea up on the [*ResearchKit* Forum](https://forums.developer.apple.com/community/researchkit). + + +Creating a personal fork +------------------------ + +On GitHub, it's easy to create a personal fork. Just tap the "Fork" +button on the top right, and clone your new repository. + + +Develop your changes in your fork +--------------------------------- + +Develop your changes using your normal development process. If you +already have code from an existing project, you may need to adjust its +style to more closely match the [ResearchKit framework coding style](./docs-standalone/coding-style-guide.md). + +New components may need to expose new Public or Private +headers. Public headers are for APIs that are likely to be a stable +part of the interface of the ResearchKit framework. Private headers are for APIs that +may need to be accessed from app-side unit tests, or that are more +subject to change than the public interface. All other headers should +be internal, "Project" headers. + +Please review and ensure that any contributions you make comply with +the [ResearchKit Contribution Terms and License Policy](#contribution). + +Add automated tests for your feature, where it is possible to do +so. For UI driven components where it is harder to write automated +tests, add UI to at least one test application so that the new +features can be reviewed and tested. Consider also whether to add new +code to other existing demo apps to exercise your feature. + +When adding UI driven components, make sure that they are accessible. +Follow the steps outlined in the [Best Practices](../../wiki/best-practices) +section under Accessibility. Before submitting the pull request, you should +audit your components with Voice Over (or other relevant assistive technologies) +enabled. + +Keep changes that fix different issues separate. For bug fixes, +separate bugs should be submitted as separate pull requests. A good +way to do this is to create a new branch in your fork for each new +bug work on. + +Any new user-visible strings should be included in the English +`ResearchKit.strings` table so that they can be picked up and +localized in the next release cycle. + + +Run the tests +------------- + +All unit tests should pass, and there should be no warnings. Also +verify that test apps run on both device and simulator. + +Where your code affects UI presentation, also test: + +* Multiple device form factors (for instance, iPhone 4S, iPhone 5, iPhone 6, iPhone 6 Plus). +* Dynamic text, especially at the "Large" setting. +* Rotation between portrait and landscape, where appropriate. + +You can use the apps in the `Testing` and `samples` directories to +test your changes. + +Submit a pull request +--------------------- + +The reviewers may request changes. Make the changes, and update your +pull request as needed. Reviews will focus on coding style, +correctness, and design consistency. + +This process does not take the place of an ethical review, for example +by an institutional review board (IRB) or ethics committee. + +After acceptance +---------------- + +Once your pull request has been accepted, your changes will be merged +to master. You are still responsible for your change after it is +accepted. Stay in contact, in case bugs are detected that may require +your attention. + +When the project is next branched for release, your changes will be +incorporated. Queries may come back to you regarding localization, +documentation, or other issues during this process. + + + + +Release process +----------------- + +The `master` branch is used for work in progress. On `master`: + +* All test apps should build and run error free. +* Unit tests should all pass. +* Everything should be continuously in working order in English (the + base language). + + The project will make periodic releases. When preparing a stable release, we + will branch from `master` to a convergence branch. During this process, + changes will be made first to the convergence branch, and then merged into + `master`. On the convergence branch, changes will be made only to: + + * Fix high priority issues. + * Update documentation. + * Bring localization up to date. + * Ensure good behavior across all supported devices. + + After the converging process is completed, we will merge everything to the + `stable` branch and tag with a new release number. The most recent release + will be highlighted in the [README](../..). + + + ResearchKit Contribution Terms and License Policy + ======================================= + + Thank you for your interest in contributing to the ResearchKit + community. In order to maintain consistency and license compatibility + throughout the project, all contributions must comply with our + licensing policy and terms for contributing code to the ResearchKit + project: + + 1. If you are submitting a patch to the existing codebase, you + represent that you have the right to license the patch, including + all code and content, to Apple and the community, and agree by + submitting the patch that your changes are + licensed under the existing license terms of the file you are + modifying (i.e., [ResearchKit BSD license](LICENSE)). + You confirm that you have added your copyright (name and year) to + the relevant files for changes that are more than 10 lines of code. + 2. If you are submitting a new file for inclusion in the ResearchKit + framework (no code or other content is copied from another source), you + have included your copyright (name and year) and a copy of the ResearchKit + BSD license. By submitting your new file you represent that you have the + right to license your file to Apple and the community, and agree that your + file submission is licensed under the ResearchKit BSD license. + 3. If you aren't the author of the patch, you agree that you have + the right to submit the patch, and have included the original copyright + notices and licensing terms with it, to the extent that they exist. + If there wasn't a copyright notice or license, please make a note of it + in your response. Generally we can only take in patches that are + BSD-licensed in order to maintain license compatibility within the project. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/LICENSE b/PediatricPancreas_Storyboard/ResearchKit-master/LICENSE new file mode 100755 index 0000000..78ff542 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/LICENSE @@ -0,0 +1,28 @@ +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/README.md b/PediatricPancreas_Storyboard/ResearchKit-master/README.md new file mode 100755 index 0000000..f6d396b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/README.md @@ -0,0 +1,286 @@ +ResearchKit Framework +=========== + +![VCS](https://img.shields.io/badge/dvcs-Git%20%2B%20LFS-tomato.svg) ![Platform](https://img.shields.io/cocoapods/p/ResearchKit.svg) ![CocoaPods](https://img.shields.io/cocoapods/v/ResearchKit.svg) ![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-yellow.svg?style=flat) [![License](https://img.shields.io/badge/license-BSD-green.svg?style=flat)](https://github.com/ResearchKit/ResearchKit#license) ![](https://travis-ci.com/ResearchKit/ResearchKit.svg?branch=master) + +The *ResearchKit™ framework* is an open source software framework that makes it easy to create apps +for medical research or for other research projects. + +* [Getting Started](#gettingstarted) +* Documentation: + * [Programming Guide](http://researchkit.org/docs/docs/Overview/GuideOverview.html) + * [Framework Reference](http://researchkit.org/docs/index.html) +* [Best Practices](../../wiki/best-practices) +* [Contributing to ResearchKit](CONTRIBUTING.md) +* [Website](http://researchkit.org) and [Blog](http://researchkit.org/blog.html) +* [ResearchKit BSD License](#license) + +Getting More Information +======================== + +* Join the [*ResearchKit* Forum](https://forums.developer.apple.com/community/researchkit) for discussing uses of the *ResearchKit framework and* related projects. + +Use Cases +=========== + +A task in the *ResearchKit framework* contains a set of steps to present to a user. Everything, +whether it’s a *survey*, the *consent process*, or *active tasks*, is represented as a task that can +be presented with a task view controller. + +Surveys +------- + +The *ResearchKit framework* provides a pre-built user interface for surveys, which can be presented +modally on an *iPhone*, *iPod Touch*, or *iPad*. See + *[Creating Surveys](http://researchkit.org/docs/docs/Survey/CreatingSurveys.html)* for more + information. + + +Consent +---------------- + +The *ResearchKit framework* provides visual consent templates that you can customize to explain the +details of your research study and obtain a signature if needed. +See *[Obtaining Consent](http://researchkit.org/docs/docs/InformedConsent/InformedConsent.html)* for +more information. + + +Active Tasks +------------ + +Some studies may need data beyond survey questions or the passive data collection capabilities +available through use of the *HealthKit* and *CoreMotion* APIs if you are programming for *iOS*. +*ResearchKit*'s active tasks invite users to perform activities under semi-controlled conditions, +while *iPhone* sensors actively collect data. See +*[Active Tasks](http://researchkit.org/docs/docs/ActiveTasks/ActiveTasks.html)* for more +information. +ResearchKit active tasks are not diagnostic tools nor medical devices of any kind and output from those active tasks may not be used for diagnosis. Developers and researchers are responsible for complying with all applicable laws and regulations with respect to further development and use of the active tasks. + +Charts +------------ +*ResearchKit* includes a *Charts module*. It features three chart types: a *pie chart* (`ORKPieChartView`), a *line graph chart* (`ORKLineGraphChartView`), and a *discrete graph chart* (`ORKDiscreteGraphChartView`). + +The views in the *Charts module* can be used independently of the rest of *ResearchKit*. They don't automatically connect with any other part of *ResearchKit*: the developer has to supply the data to be displayed through the views' `dataSources`, which allows for maximum flexibility. + + +Getting Started +=============== + + +Requirements +------------ + +The primary *ResearchKit framework* codebase supports *iOS* and requires *Xcode 8.0* or newer. The +*ResearchKit framework* has a *Base SDK* version of *8.0*, meaning that apps using the *ResearchKit +framework* can run on devices with *iOS 8.0* or newer. + + +Installation +------------ + +The latest stable version of *ResearchKit framework* can be cloned with + +``` +git clone -b stable https://github.com/ResearchKit/ResearchKit.git +``` + +Or, for the latest changes, use the `master` branch: + +``` +git clone https://github.com/ResearchKit/ResearchKit.git +``` + +Building +-------- + +Build the *ResearchKit framework* by opening `ResearchKit.xcodeproj` and running the `ResearchKit` +framework target. Optionally, run the unit tests too. + + +Adding the ResearchKit framework to your App +------------------------------ + +This walk-through shows how to embed the *ResearchKit framework* in your app as a dynamic framework, +and present a simple task view controller. + +### 1. Add the ResearchKit framework to Your Project + +To get started, drag `ResearchKit.xcodeproj` from your checkout into your *iOS* app project +in *Xcode*: + +

+
+ Adding the ResearchKit framework to your
+   project +
+
+ +Then, embed the *ResearchKit framework* as a dynamic framework in your app, by adding it to the +*Embedded Binaries* section of the *General* pane for your target as shown in the figure below. + +
+
+ Adding the ResearchKit framework to
+   Embedded Binaries +
Adding the ResearchKit framework to Embedded Binaries
+
+
+ +Note: You can also import *ResearchKit* into your project using a + [dependency manager](./docs-standalone/dependency-management.md) such as *CocoaPods* or *Carthage*. + +### 2. Create a Step + +In this walk-through, we will use the *ResearchKit framework* to modally present a simple + single-step task showing a single instruction. + +Create a step for your task by adding some code, perhaps in `viewDidAppear:` of an existing view +controller. To keep things simple, we'll use an instruction step (`ORKInstructionStep`) and name +the step `myStep`. + +*Objective-C* + +```objc +ORKInstructionStep *myStep = + [[ORKInstructionStep alloc] initWithIdentifier:@"intro"]; +myStep.title = @"Welcome to ResearchKit"; +``` + +*Swift* + +```swift +let myStep = ORKInstructionStep(identifier: "intro") +myStep.title = "Welcome to ResearchKit" +``` + +### 3. Create a Task + +Use the ordered task class (`ORKOrderedTask`) to create a task that contains `myStep`. An ordered +task is just a task where the order and selection of later steps does not depend on the results of +earlier ones. Name your task `task` and initialize it with `myStep`. + +*Objective-C* + +```objc +ORKOrderedTask *task = + [[ORKOrderedTask alloc] initWithIdentifier:@"task" steps:@[myStep]]; +``` + +*Swift* + +```swift +let task = ORKOrderedTask(identifier: "task", steps: [myStep]) +``` + +### 4. Present the Task + +Create a task view controller (`ORKTaskViewController`) and initialize it with your `task`. A task +view controller manages a task and collects the results of each step. In this case, your task view +controller simply displays your instruction step. + +*Objective-C* + +```objc +ORKTaskViewController *taskViewController = + [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; +taskViewController.delegate = self; +[self presentViewController:taskViewController animated:YES completion:nil]; +``` + +*Swift* + +```swift +let taskViewController = ORKTaskViewController(task: task, taskRun: nil) +taskViewController.delegate = self +present(taskViewController, animated: true, completion: nil) +``` + +The above snippet assumes that your class implements the `ORKTaskViewControllerDelegate` protocol. +This has just one required method, which you must implement in order to handle the completion of + the task: + +*Objective-C* + +```objc +- (void)taskViewController:(ORKTaskViewController *)taskViewController + didFinishWithReason:(ORKTaskViewControllerFinishReason)reason + error:(NSError *)error { + + ORKTaskResult *taskResult = [taskViewController result]; + // You could do something with the result here. + + // Then, dismiss the task view controller. + [self dismissViewControllerAnimated:YES completion:nil]; +} +``` + +*Swift* + +```swift +func taskViewController(_ taskViewController: ORKTaskViewController, + didFinishWith reason: ORKTaskViewControllerFinishReason, + error: Error?) { + let taskResult = taskViewController.result + // You could do something with the result here. + + // Then, dismiss the task view controller. + dismiss(animated: true, completion: nil) +} +``` + + +If you now run your app, you should see your first *ResearchKit framework* instruction step: + +
+
+ HelloWorld example screenshot +
+
+ + + +What else can the ResearchKit framework do? +----------------------------- + +The *ResearchKit* [`ORKCatalog`](samples/ORKCatalog) sample app is a good place to start. Find the +project in ResearchKit's [`samples`](samples) directory. This project includes a list of all the +types of steps supported by the *ResearchKit framework* in the first tab, and displays a browser for the +results of the last completed task in the second tab. The third tab shows some examples from the *Charts module*. + + + +License +======= + +The source in the *ResearchKit* repository is made available under the following license unless +another license is explicitly identified: + +``` +Copyright (c) 2015 - 2018, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +``` diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/RELEASE-NOTES.md b/PediatricPancreas_Storyboard/ResearchKit-master/RELEASE-NOTES.md new file mode 100755 index 0000000..c8474e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/RELEASE-NOTES.md @@ -0,0 +1,405 @@ +# ResearchKit Release Notes + +## ResearchKit 2.0 Release Notes + +*ResearchKit 2.0* supports *iOS* and requires *Xcode 9.0* or newer. +The minimum supported *Base SDK* is *11.0*. + +*ResearchKit 2.0* is a beta release with updates and support for documentation, localization, accessibility and QA coming over the next few months ahead of our stable release. + +In addition to general stability and performance improvements, *ResearchKit 2.0* includes the following new features and enhancements. + +### Community Updates + +- **Repo Privileges** +We have opened up our access rights and have expanded our GitHub privileges to some of the external members of our community. This gives these community members direct write access to the ResearchKit repository and merge pull requests. + +- **Schedule Changes** +Previously the ResearchKit framework pushed to our master and stable branches simultaneously. With this release we want to allow for more participation from the community so to accomplish this, we will push to the stable branch some time after our initial push to master. This will enable the community to check out the new features, provide suggestions and submit pull requests. During this time between master and stable, we will complete accessibility, localization and QA sweeps of the code so if you make contributions during this time, they will be reflected in the official stable release branch to follow. + +### UI Updates + +- **iOS Look and Feel** +We have updated ResearchKit to support the look and feel of *iOS 11*. Updates across all of our modules include bold titles and fonts as well as left alignment for all text. + +- **Footers and Buttons** +The step footers and buttons have been updated across all our modules to enable a better and more intuitive user experience as participants navigate through your apps. Footers are now sticky to the bottom of all views and support new filled button styles. The cancel button has also been relocated to the under the continue button and these updates are able to handle ‘cancel’ and ‘skip’ buttons simultaneously. Progress indicators have also been aligned to the top right to allow for the new scrolling title implementation. + +- **Card View** +This new view enhances the look and feel of surveys and forms. These updates improve the user experience for participants completing forms and surveys by more clearly segmenting the various steps and questions a user is asked to complete. + +- **PDF Viewer** +This steps allows users to easily navigate, annotate, search and share any PDF. + +### Active Tasks + +- **Speech Recognition** +The speech recognition task lets developers present participants with either an image for users to describe or a block of text for users to repeat. The participant will press record while they follow the prompt and when they have completed recording, a transcription will appear for them to edit if they feel anything was transcribed incorrectly. The task will generate results that include an audio recording of what the participant said, a transcription of the output from the speech to text engine and the transcription which is editable by the participant if they made any changes to the output. + +- **Environment SPL Meter** +This task measures the current noise in the participant’s environment. The task can be incorporated as a step into any hearing test or module and used as a gating step to ensure that the participant is in a suitable environment to complete their assessments. + +- **Tone Audiometry** +The tone audiometry task has been enhanced to include an updated algorithm and implementation to better evaluate a user’s hearing. Tones will decrease in dBHL until a user’s failed attempt and then again increasing until a successful attempt. This tasks also utilizes a variety of different calibrations, metrics and tables which are calibrated for AirPods only. This allows developers to now collect the hearing threshold level of participants who complete this test. + +- **Speech in Noise** +The Speech in Noise test is another task that can be used to measure the hearing health of users. During this test, users will listen to a recording which includes ambient noises in the background as well as a phrase. The participant will be asked to repeat back the phrase using the Speech Recognition task. Throughout the task, the ambient background noise will increase or decrease in levels, allowing developers to measure the Speech Reception Threshold (SRT) of a user. Stay tuned as more audio files will be added to the repository over the coming months! + +- **Amsler Grid** +The Amsler Grid test is a task that can be used to collect data about a users vision. During this task participants will hold the phone at a certain distance from their face and close one eye or the other as instructed. A grid is displayed for users to view and if they see any distortions such as wavy or blurred lines, they can mark those areas on the grid using their finger or a stylus to annotate. + +### New Sample App + +- **Parkinson's Research Sample App** +This sample app demonstrates how to leverage the new Movement Disorder API which is available within the CoreMotion framework. + + +### Please Note + +*ResearchKit 2.0* is a beta release. We will be updating our master branch at regular intervals in the coming months to address various issues and expand support for localization and accessibility. + + +## ResearchKit 1.5 Release Notes + +*ResearchKit 1.5* supports *iOS* and requires *Xcode 8.0* or newer. The minimum supported *Base SDK* is *8.0*. + +In addition to general stabiltiy and performance improvements, *ResearchKit 1.5* includes the following new features and enhancements. + +- **New Active Tasks** + + - **Stroop Test** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Stroop Test* shows the participant different combinations of text and tint colors on the screen. + + Users must ignore the text and instead select the button that reflects the first letter of the tint color. + + - **Trail Making Test** + + *Contributed by Faraz Hussain.* + + The *Trail Making Test* instructs participants to connect a series of labelled circles and the time to complete the test is recorded. + + - **Range of Motion Test** + + *Contributed by Daren Levy, Dr. Raj Karia, John Guydo.* + + Participants are instructed to follow a series of steps while accelerometer and gyroscope data is captured to measure flexed and extended positions for both the shoulder and knee. + + - **Touch Anywhere Active Task** + + *Contributed by Daren Levy, Dr. Raj Karia, John Guydo* + + Allows the user to get their device in the proper position and then tap the screen to indicate they are ready to begin the next step. + +- **New Steps** + + - **Video Instruction Step** + + *Contributed by [Oliver Schäfer](https://github.com/oliverschaefer).* + + The *Video Instruction Step* provides a step to be used to display a video. + + This step can be used to display videos to users from either a local or remote source. + +- **Other Improvements** + + - **Tone Audiometry Test** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + Updated to include both a left and right button. + + - **Digital Object Identifier** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + Assigns a Digital Object Identifier to the ResearchKit repository on GitHub to use when referencing the framework. + + +## ResearchKit 1.4 Release Notes + +*ResearchKit 1.4* supports *iOS* and requires *Xcode 8.0* or newer. The minimum supported *Base SDK* is *8.0*. + +In addition to general stabiltiy and performance improvements, *ResearchKit 1.4* includes the following new features and enhancements. + +- **New Active Task** + + - **Hand Tremor Task** + + *Contributed by [Shannon Young](https://github.com/syoung-smallwisdom).* + + The *Hand Tremor Task* asks the participant to hold the device with their most affected hand in various positions while accelerometer and motion data is captured. + + - **Walk Back and Forth Task** + + *Contributed by [Shannon Young](https://github.com/syoung-smallwisdom).* + + The *Walk Back and Forth Task* addresses the concern of researchers/participants who have difficulty locating an unobstructed path for 20 steps. + + Instructs users to walk and turn in a full circle, allowing the tests to be conducted in a smaller space. + +- **New Steps** + + - **Video Capture Step** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Video Capture Step* provides a step to be used to record video. + + The step can be used as part of a survey to capture video respones as well. + + - **Review Step** + + *Contributed by [Oliver Schäfer](https://github.com/oliverschaefer).* + + The *Review Step* allows a participant to review and modify their answers to a survey. + + The step can be used in the middle of a survey, at the end of a survey, or a standalone module. + + - **Signature Step** + + *Contributed by [Oliver Schäfer](https://github.com/oliverschaefer).* + + The *Signature Step* provides an interface for a participant to sign their name. + + The step can be used for handwriting detection or simply to sign a document. + + - **Table Step** + + *Contributed by [Shannon Young](https://github.com/syoung-smallwisdom).* + + The *Table Step* provides a way to neatly display data in a table. + +- **Other Improvements** + + - **Data Collection Module** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Data Collection Module* makes it even easier to aggregate data from HealthKit and device sensors. + + - **Tapping Test** + + *Contributed by [Michał Zaborowski](https://github.com/m1entus).* + + The *Tapping Test* is updated to include tap duration as part of the result. + + +## ResearchKit 1.3 Release Notes + +*ResearchKit 1.3* supports *iOS* and requires *Xcode 7.2* or newer. The minimum supported *Base SDK* is *8.0*. + +In addition to general stability and performance improvements, *ResearchKit 1.3* includes the following new features and enhancements. + +- **New Active Task** + + - **9-Hole Peg Test** + + *Contributed by [Julien Therier](https://github.com/julientherier).* + + The *9-Hole Peg Test task* is used to test upper extremity functionality. + + The test involves putting a variable number of pegs in a hole and subsequently removing them. + + The test is documented in the scientific literature to measure the *[MSFC score in Multiple Sclerosis](http://www.nationalmssociety.org/For-Professionals/Researchers/Resources-for-Researchers/Clinical-Study-Measures/9-Hole-Peg-Test-(9-HPT))* or *[Parkinson's Disease](http://www.ncbi.nlm.nih.gov/pubmed/22020457)*. + +- **Sample App** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Sample App* (`ORKSample` project on *ResearchKit*'s workspace) serves as a template application that combines different modules from the *ResearchKit framework*. + +- **Account Module** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Account Module* provides steps to facilitate account creation and login. + + The module includes the following steps: + + 1. *Registration*, used to allow the participant to create a new account. + 2. *Verification*, used to confirm if the participant has verified the provided email address. + 3. *Login*, used to allow registered users to login. + +- **Passcode with Touch ID** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + The *Passcode with Touch ID module* provides the ability to secure any *ResearchKit* application with a numeric passcode. + + This module includes a *Keychain Wrapper* that stores the passcode on the device, as well as the option to use *Touch ID* on compatible devices. The passcode module supports 4-digit and 6-digit numeric codes. + + The passcode module provides the following components: + + 1. *Passcode creation step*, which can be used as part of onboarding to create a passcode and store it in the keychain. + 2. *Passcode authentication view controller*, which can be modally presented when appropriate. + 3. *Passcode modification view controller*, which allows the participant to change their passcode. + +- **Other Improvements** + + - **Optional Form Items** + + *Contributed by [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez).* + + Adds the `optional` property to `ORKFormItem`. + + The *Continue/Done* button of form steps is enabled when all of the following conditions are met: + + - At least one form item has an answer. + - All the non-optional form items have answers. + - All answered form items have valid answers. + + - **Location Question** + + *Contributed by [Quintiles](https://github.com/QuintilesRK).* + + A *Location Question* can be used to request details about the participant's current location or about a specific address. + + The question uses *MapKit* to provide a visual representation for the specified address. + + - **Wait Step** + + *Contributed by [Quintiles](https://github.com/QuintilesRK).* + + The *Wait Step* provides a step to be used in-between steps when additional data processing is required. + + The step supports both indeterminate and determinate progress views, as well as the ability to show text status updates. + + - **Validated Text Answer Format** + + *Contributed by [Quintiles](https://github.com/QuintilesRK).* + + The *Validated Text Answer Format* enhances the existing *Text Answer Format* by providing input validation using a regular expression. + + A valid *NSRegularExpression* object and an *error message* string are required to properly use this answer format. + + +## ResearchKit 1.2 Release Notes + +*ResearchKit 1.2* supports *iOS* and requires *Xcode 7.0* or newer. The minimum supported *Base SDK* is *8.0*. + +In addition to general stability and performance improvements, *ResearchKit 1.2* includes the following new features and enhancements. + +- **New Active Tasks** + + - **Tower of Hanoi Task** + + *Contributed by [coxy1989](https://github.com/coxy1989).* + + The *[Tower of Hanoi](https://en.wikipedia.org/wiki/Tower_of_Hanoi#Applications) task* is frequently used in psychological research on problem solving. + + It is a mathematical puzzle consisting of three rods and a number of disks of different sizes which can slide onto any rod. The puzzle starts with the disks in a stack in ascending order of size on one rod (the smallest at the top). + + The objective of the puzzle is to move the entire stack to another rod, obeying the following rules: + + 1. Only one disk can be moved at a time. + 2. Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack. + 3. No disk may be placed on top of a smaller disk. + + - **Paced Serial Addition Test Task** + + *Contributed by [Julien Therier](https://github.com/julientherier).* + + The *Paced Serial Addition Test task* provides adaptations of both the *Paced Auditory Serial Addition Test (PASAT)* and the *Paced Visual Serial Addition Test (PVSAT)*. + + The *[PASAT](https://en.wikipedia.org/wiki/Paced_Auditory_Serial_Addition_Test)* is a neuropsychological test used to assess capacity and rate of information processing and sustained and divided attention. + + Both tests are documented in the scientific literature ([Fos et al., 2000](http://www.ncbi.nlm.nih.gov/pubmed/11125707); [Nagels et al., 2005](http://www.ncbi.nlm.nih.gov/pubmed/15823678)) as a measure of the [*Multiple Sclerosis Functional Score*](http://www.nationalmssociety.org/For-Professionals/Researchers/Resources-for-Researchers/Clinical-Study-Measures/Multiple-Sclerosis-Functional-Composite-%28MSFC%29). + + This task generates a series of single digits (for example, 60 of them), at the specific frequency (for example, one new digit every 2 or 3 seconds). The user must add the newly presented digit to the one prior to it. + + - **Timed Walk Task** + + *Contributed by [Julien Therier](https://github.com/julientherier).* + + The *Timed Walk task* measures gait speed and is an adaptation of the [*Timed 25-Foot Walk*](http://www.nationalmssociety.org/For-Professionals/Researchers/Resources-for-Researchers/Clinical-Study-Measures/Timed-25-Foot-Walk-%28T25-FW%29) in the context of *multiple sclerosis*. + + Gait speed has been demonstrated to be a useful and reliable functional measure of walking ability. When administering the *Timed Walk Task*, patients are allowed to use assistive devices (canes, crutches, walkers). + +- **Charts Module** + + *Contributed by [coxy1989](https://github.com/coxy1989) and [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez).* + + A *Charts module* has been implemented. It features three chart types: a *pie chart* (`ORKPieChartView`), a *line graph chart* (`ORKLineGraphChartView`), and a *discrete graph chart* (`ORKDiscreteGraphChartView`). + + The views in the *Charts module* can be used independently of the rest of *ResearchKit*. It doesn't automatically connect with any other *ResearchKit* module: the developer has to supply the data to be displayed through the views' `dataSources`, which allows for maximum flexibility. + +- **Other Improvements** + + - **Scale Answer Format** + + *Contributed by [Apple Inc](https://github.com/researchkit).* + + *Discrete scales* now support *text choice* labels, and all *scales* support images in place of the minimum and maximum range labels. + + - **Result Predicates** + + *Contributed by [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez).* + + The predicate-building methods in `ORKResultPredicate` now use the new `ORKResultSelector` class for unequivocally identifying a *question step result* or a *form item result*. + + This eliminates ambiguity when matching results with the same inner scope identifier. For example, a *form item result* can have the same identifier as a *question step result* or as another *form item result* in a different *form step*, and you can now match them separately. + + +## ResearchKit 1.1 Release Notes + +*ResearchKit 1.1* supports *iOS* and requires *Xcode 6.3* or newer. The minimum supported *Base SDK* is *8.0*. + +In addition to general stability and performance improvements, *ResearchKit 1.1* includes the following new features and enhancements. + +- **Navigable Ordered Task** + + *Contributed by [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez).* + + A new type of *conditional ordered task* (`ORKNavigableOrderedTask`) has been implemented. + + The developer can use the `ORKStepNavigationRule` subclasses to dynamically navigate between the task steps: + - `ORKPredicateStepNavigationRule` allows to make conditional jumps by matching previous results (either those of the ongoing task, or those of any previously stored task result tree). You typically use the class methods in the `ORKResultPredicate` class to match answers in the most commonly used result types. + - `ORKDirectStepNavigationRule` provides support for unconditional jumps. + +- **New Active Tasks** + - **Reaction Time Task** + + *Contributed by [coxy1989](https://github.com/coxy1989).* + + The *Reaction Time Task* is an adaptation of the [*Simple Reaction Time test (SRT)*](http://www.cambridgecognition.com/tests/simple-reaction-time-srt). *SRT* measures reaction time through delivery of a known stimulus to a known location to elicit a known response. + + This test is deployed in a range of research questions across fields including medicine, sports science and psychology. + + Although it classically involves pressing the space bar or clicking a mouse in response to an event on screen, the *ResearchKit* implementation relies on the study participant shaking the device when she sees a blue circle on the screen, which we think is more correlatable to a true stimulus reaction test. + + - **Tone Audiometry Task** + + *Contributed by [Vincent Tourraine](https://github.com/vtourraine).* + + The *Tone Audiometry Task* is an adaptation of the [*Pure Tone Audiometry test (PTA)*](https://en.wikipedia.org/wiki/Pure_tone_audiometry). *PTA* is a key hearing test used to identify hearing threshold levels of an individual, enabling determination of the degree, type and configuration of a hearing loss. + + The *ResearchKit* implementation generates a series of pure sinusoid sounds, with different frequencies and on different channels (left or right). The test starts at the minimum volume and is gradually increased until the participant perceives it and taps a button. At that time, the current sound amplitude, frequency and channel are recorded. + +- **Scale Answer Format Enhancements** + + *Contributed by [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez) and [Bruce Duncan](https://github.com/brucehappy).* + + Support for discrete and continuous *vertical scales* has been added. Some questions, like mood measurement or symptom severity measurement queries may be more naturally presented using a *vertical scale*. + + The *Scale Answer Format* has also been improved by making it usable within forms. + +- **Image Capture Step** + + *Contributed by [Bruce Duncan](https://github.com/brucehappy).* + + An *Image Capture Step* has been added. The researcher can ask the participant to take pictures of relevant body parts. The researcher can provide a body part image template to facilitate the scale and orientation of the taken pictures. + +- **iPad Support** + + *Contributed by [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez) and [Apple Inc](https://github.com/researchkit).* + + *iPad support* for all orientations has been implemented. + +- **iPhone Landscape Support** + + *Contributed by [Apple Inc.](https://github.com/researchkit) and [Ricardo Sánchez-Sáez](https://github.com/rsanchezsaez).* + + *iPhone landscape orientation support* has been implemented. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..bb1462a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 0000000..18d9810 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/RKWorkspace.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit.podspec b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit.podspec new file mode 100755 index 0000000..e2343fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit.podspec @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = 'ResearchKit' + s.version = '2.1.0-beta' + s.summary = 'ResearchKit is an open source software framework that makes it easy to create apps for medical research or for other research projects.' + s.homepage = 'https://www.github.com/ResearchKit/ResearchKit' + s.documentation_url = 'http://researchkit.github.io/docs/' + s.license = { :type => 'BSD', :file => 'LICENSE' } + s.author = { 'researchkit.org' => 'http://researchkit.org' } + s.source = { :git => 'https://github.com/ResearchKit/ResearchKit.git', :tag => s.version.to_s } + s.public_header_files = `./scripts/find_headers.rb --public`.split("\n") + s.private_header_files = `./scripts/find_headers.rb --private`.split("\n") + s.source_files = 'ResearchKit/**/*.{h,m,swift}' + s.resources = 'ResearchKit/**/*.{fsh,vsh}', 'ResearchKit/Animations/**/*.m4v', 'ResearchKit/Artwork.xcassets', 'ResearchKit/Localized/*.lproj' + s.platform = :ios, '11.0' + s.requires_arc = true + s.swift_version = '5' + s.module_map = "ResearchKit/ResearchKit.modulemap" +end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibility.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibility.h new file mode 100755 index 0000000..87b7b51 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibility.h @@ -0,0 +1,35 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +// Shared header for accessibility functionality. +#import "ORKAccessibilityFunctions.h" +#import "ORKGraphChartAccessibilityElement.h" +#import "UIView+ORKAccessibility.h" diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.h new file mode 100755 index 0000000..1437d4b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKHelpers_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKScaleSlider; + +// Used to properly format values from the ORKScaleSlider. +ORK_EXTERN NSString * _Nullable ORKAccessibilityFormatScaleSliderValue(CGFloat value, ORKScaleSlider *slider); +ORK_EXTERN NSString * _Nullable ORKAccessibilityFormatContinuousScaleSliderValue(CGFloat value, ORKScaleSlider *slider); + +// Performs a block on the main thread after a delay. If Voice Over is not running, the block is performed immediately. +ORK_EXTERN void ORKAccessibilityPerformBlockAfterDelay(NSTimeInterval delay, void(^block)(void)); + +// Convenience for posting an accessibility notification after a delay. +ORK_INLINE void ORKAccessibilityPostNotificationAfterDelay(UIAccessibilityNotifications notification, _Nullable id argument, NSTimeInterval delay) { + ORKAccessibilityPerformBlockAfterDelay(delay, ^{ + UIAccessibilityPostNotification(notification, argument); + }); +} + +// Creates a string suitable for Voice Over by joining the variables with ", " and avoiding nil and empty strings. +#define ORKAccessibilityStringForVariables(...) _ORKAccessibilityStringForVariables(ORK_NARG(__VA_ARGS__), ##__VA_ARGS__) +ORK_EXTERN NSString *_ORKAccessibilityStringForVariables(NSInteger numParameters, NSString *baseString, ...); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.m new file mode 100755 index 0000000..15d2ec6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKAccessibilityFunctions.m @@ -0,0 +1,93 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + +#import "ORKScaleSlider.h" +#import "ORKScaleSliderView.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKAccessibilityFunctions.h" +#import "UIView+ORKAccessibility.h" + + +NSString *ORKAccessibilityFormatScaleSliderValue(CGFloat value, ORKScaleSlider *slider) { + ORKScaleSliderView *sliderView = (ORKScaleSliderView *)[slider ork_superviewOfType:[ORKScaleSliderView class]]; + if (!slider || !sliderView) { + return nil; + } + + NSNumber *normalizedValue = [sliderView.formatProvider normalizedValueForNumber:@(value)]; + return [sliderView.formatProvider localizedStringForNumber:normalizedValue]; +} + +NSString *ORKAccessibilityFormatContinuousScaleSliderValue(CGFloat value, ORKScaleSlider *slider) { + ORKScaleSliderView *sliderView = (ORKScaleSliderView *)[slider ork_superviewOfType:[ORKScaleSliderView class]]; + if (!slider || !sliderView) { + return nil; + } + + return [sliderView.formatProvider localizedStringForNumber:@(value)]; +} + +void ORKAccessibilityPerformBlockAfterDelay(NSTimeInterval delay, void(^block)(void)) { + if (block == nil) { + return; + } + if (!UIAccessibilityIsVoiceOverRunning()) { + delay = 0; + } + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + block(); + }); +} + +NSString *_ORKAccessibilityStringForVariables(NSInteger numParameters, NSString *baseString, ...) { + NSMutableArray *variables = [[NSMutableArray alloc] init]; + + NSInteger paramIndex = 0; + + va_list args; + va_start(args, baseString); + for (__unsafe_unretained NSString *variable = baseString; + paramIndex < numParameters; + variable = va_arg(args, __unsafe_unretained NSString *), paramIndex++) { + + if ([variable isKindOfClass:[NSString class]] && variable.length > 0) { + [variables addObject:variable]; + } + + } + va_end(args); + + return [variables componentsJoinedByString:@", "]; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.h new file mode 100755 index 0000000..a59c0ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKGraphChartAccessibilityElement : UIAccessibilityElement + +- (nonnull instancetype)initWithAccessibilityContainer:(nonnull UIView *)container index:(NSInteger)index maxIndex:(NSInteger)maxIndex; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.m new file mode 100755 index 0000000..db8fba2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/ORKGraphChartAccessibilityElement.m @@ -0,0 +1,66 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKGraphChartAccessibilityElement.h" + + +@interface ORKGraphChartAccessibilityElement() + +@property (assign, nonatomic) NSInteger index; +@property (assign, nonatomic) NSInteger maxIndex; + +@end + + +@implementation ORKGraphChartAccessibilityElement + +- (nonnull instancetype)initWithAccessibilityContainer:(nonnull UIView *)container index:(NSInteger)index maxIndex:(NSInteger)maxIndex { + self = [super initWithAccessibilityContainer:container]; + if (self) { + self.index = index; + self.maxIndex = maxIndex; + } + return self; +} + +- (CGRect)accessibilityFrame { + if (self.maxIndex == 0) { + return [super accessibilityFrame]; + } + + CGRect containerFrame = [self.accessibilityContainer frame]; + CGFloat height = CGRectGetHeight(containerFrame); + CGFloat width = CGRectGetWidth(containerFrame) / self.maxIndex; + CGFloat x = self.index * width; + + return UIAccessibilityConvertFrameToScreenCoordinates(CGRectMake(x, 0, width, height), self.accessibilityContainer); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.h new file mode 100755 index 0000000..843fbdf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (ORKAccessibility) + +- (nullable UIView *)ork_superviewOfType:(nullable Class)aClass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.m new file mode 100755 index 0000000..0957a23 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Accessibility/UIView+ORKAccessibility.m @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "UIView+ORKAccessibility.h" + + +@implementation UIView (ORKAccessibility) + +- (UIView *)ork_superviewOfType:(Class)aClass { + if (aClass == nil) { + return nil; + } + + id superview = [self superview]; + if (superview == nil) { + return nil; + } else if ([superview isKindOfClass:aClass]) { + return superview; + } + + return [superview ork_superviewOfType:aClass]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.h new file mode 100755 index 0000000..9dead51 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import CoreLocation; + + +NS_ASSUME_NONNULL_BEGIN + +@interface CLLocation (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.m new file mode 100755 index 0000000..d0a4af2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CLLocation+ORKJSONDictionary.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "CLLocation+ORKJSONDictionary.h" + +#import "ORKHelpers_Internal.h" + + +@implementation CLLocation (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary { + CLLocationCoordinate2D coord = self.coordinate; + CLLocationDistance altitude = self.altitude; + CLLocationAccuracy horizAccuracy = self.horizontalAccuracy; + CLLocationAccuracy vertAccuracy = self.verticalAccuracy; + CLLocationDirection course = self.course; + CLLocationSpeed speed = self.speed; + NSDate *timestamp = self.timestamp; + CLFloor *floor = self.floor; + + NSMutableDictionary *dictionary = [@{ @"timestamp": ORKStringFromDateISO8601(timestamp) } mutableCopy]; + + if (horizAccuracy >= 0) { + dictionary[@"coordinate"] = @{ @"latitude": [NSDecimalNumber numberWithDouble:coord.latitude], + @"longitude": [NSDecimalNumber numberWithDouble:coord.longitude]}; + dictionary[@"horizontalAccuracy"] = [NSDecimalNumber numberWithDouble:horizAccuracy]; + } + if (vertAccuracy >= 0) { + dictionary[@"altitude"] = [NSDecimalNumber numberWithDouble:altitude]; + dictionary[@"verticalAccuracy"] = [NSDecimalNumber numberWithDouble:vertAccuracy]; + } + if (course >= 0) { + dictionary[@"course"] = [NSDecimalNumber numberWithDouble:course]; + } + if (speed >= 0) { + dictionary[@"speed"] = [NSDecimalNumber numberWithDouble:speed]; + } + if (floor) { + dictionary[@"floor"] = @(floor.level); + } + + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.h new file mode 100755 index 0000000..f8432dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import CoreMotion; + + +NS_ASSUME_NONNULL_BEGIN + +@interface CMAccelerometerData (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.m new file mode 100755 index 0000000..210dee2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMAccelerometerData+ORKJSONDictionary.m @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "CMAccelerometerData+ORKJSONDictionary.h" + + +@implementation CMAccelerometerData (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary { + NSDictionary *dictionary = @{ @"timestamp": [NSDecimalNumber numberWithDouble:self.timestamp], + @"x": [NSDecimalNumber numberWithDouble:self.acceleration.x], + @"y": [NSDecimalNumber numberWithDouble:self.acceleration.y], + @"z": [NSDecimalNumber numberWithDouble:self.acceleration.z] + }; + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.h new file mode 100755 index 0000000..bb621b4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import CoreMotion; + + +NS_ASSUME_NONNULL_BEGIN + +@interface CMDeviceMotion (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.m new file mode 100755 index 0000000..b4300d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMDeviceMotion+ORKJSONDictionary.m @@ -0,0 +1,76 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "CMDeviceMotion+ORKJSONDictionary.h" + + +@implementation CMDeviceMotion (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary { + CMQuaternion attitude = self.attitude.quaternion; + CMRotationRate rotationRate = self.rotationRate; + CMAcceleration gravity = self.gravity; + CMAcceleration userAccel = self.userAcceleration; + CMCalibratedMagneticField field = self.magneticField; + + NSDictionary *dictionary = @{@"timestamp": [NSDecimalNumber numberWithDouble:self.timestamp], + @"attitude": @{ + @"x": [NSDecimalNumber numberWithDouble:attitude.x], + @"y": [NSDecimalNumber numberWithDouble:attitude.y], + @"z": [NSDecimalNumber numberWithDouble:attitude.z], + @"w": [NSDecimalNumber numberWithDouble:attitude.w] + }, + @"rotationRate": @{ + @"x": [NSDecimalNumber numberWithDouble:rotationRate.x], + @"y": [NSDecimalNumber numberWithDouble:rotationRate.y], + @"z": [NSDecimalNumber numberWithDouble:rotationRate.z] + }, + @"gravity": @{ + @"x": [NSDecimalNumber numberWithDouble:gravity.x], + @"y": [NSDecimalNumber numberWithDouble:gravity.y], + @"z": [NSDecimalNumber numberWithDouble:gravity.z] + }, + @"userAcceleration": @{ + @"x": [NSDecimalNumber numberWithDouble:userAccel.x], + @"y": [NSDecimalNumber numberWithDouble:userAccel.y], + @"z": [NSDecimalNumber numberWithDouble:userAccel.z] + }, + @"magneticField": @{ + @"x": [NSDecimalNumber numberWithDouble:field.field.x], + @"y": [NSDecimalNumber numberWithDouble:field.field.y], + @"z": [NSDecimalNumber numberWithDouble:field.field.z], + @"accuracy": [NSDecimalNumber numberWithDouble:field.accuracy] + } + }; + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.h new file mode 100755 index 0000000..8c599f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import CoreMotion; + + +NS_ASSUME_NONNULL_BEGIN + +@interface CMMotionActivity (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.m new file mode 100755 index 0000000..4561450 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMMotionActivity+ORKJSONDictionary.m @@ -0,0 +1,84 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "CMMotionActivity+ORKJSONDictionary.h" + +#import "ORKHelpers_Internal.h" + + +static NSString *const ActivityUnknown = @"unknown"; +static NSString *const ActivityStationary = @"stationary"; +static NSString *const ActivityWalking = @"walking"; +static NSString *const ActivityRunning = @"running"; +static NSString *const ActivityAutomotive = @"automotive"; +static NSString *const StartDateKey = @"startDate"; +static NSString *const EndDateKey = @"endDate"; + +static NSString *stringFromActivityConfidence(CMMotionActivityConfidence confidence) { + NSDictionary *confidences = @{@(CMMotionActivityConfidenceHigh): @"high", + @(CMMotionActivityConfidenceMedium): @"medium", + @(CMMotionActivityConfidenceLow): @"low"}; + return confidences[@(confidence)]; +} + +static NSArray *activityArray(CMMotionActivity *activity) { + NSMutableArray *array = [NSMutableArray array]; + if (activity.unknown) { + [array addObject:ActivityUnknown]; + } + if (activity.stationary) { + [array addObject:ActivityStationary]; + } + if (activity.walking) { + [array addObject:ActivityWalking]; + } + if (activity.running) { + [array addObject:ActivityRunning]; + } + if (activity.automotive) { + [array addObject:ActivityAutomotive]; + } + return array; +} + +static NSString *const ActivityKey = @"activity"; +static NSString *const ConfidenceKey = @"confidence"; + + +@implementation CMMotionActivity (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary { + return @{ConfidenceKey: stringFromActivityConfidence(self.confidence), + ActivityKey: activityArray(self), + StartDateKey: ORKStringFromDateISO8601(self.startDate)}; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.h new file mode 100755 index 0000000..12ef42c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import CoreMotion; + + +NS_ASSUME_NONNULL_BEGIN + +@interface CMPedometerData (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.m new file mode 100755 index 0000000..e7f8d04 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CMPedometerData+ORKJSONDictionary.m @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "CMPedometerData+ORKJSONDictionary.h" + +#import "ORKHelpers_Internal.h" + +@import CoreMotion; + + +@implementation CMPedometerData (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionary { + NSMutableDictionary *dictionary = [@{ @"startDate": ORKStringFromDateISO8601(self.startDate), @"endDate": ORKStringFromDateISO8601(self.endDate) } mutableCopy]; + for (NSString *key in @[ @"numberOfSteps", @"distance", @"floorsAscended", @"floorsDescended" ]) { + [dictionary setValue:[self valueForKey:key] forKey:key]; + } + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CircleSlider.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CircleSlider.swift new file mode 100755 index 0000000..0f75ee6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/CircleSlider.swift @@ -0,0 +1,283 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +public enum CircleSliderOption { + case startAngle(Double) + case barColor(UIColor) + case trackingColor(UIColor) + case thumbColor(UIColor) + case thumbImage(UIImage) + case barWidth(CGFloat) + case thumbWidth(CGFloat) + case maxValue(Float) + case minValue(Float) + case sliderEnabled(Bool) + case viewInset(CGFloat) + case minMaxSwitchTreshold(Float) +} + +open class CircleSlider: UISlider { + + private let minThumbTouchAreaWidth: CGFloat = 44 + private var latestDegree: Double = 0 + private var startValue: Float = 0 + open var sliderValue: Float { + get { + return startValue + } + set { + var value = newValue + let significantChange = (maxValue - minValue) * (1.0 - minMaxSwitchTreshold) + let isSignificantChangeOccured = abs(newValue - startValue) > significantChange + + if isSignificantChangeOccured { + if startValue < newValue { + value = minValue + } else { + value = maxValue + } + } else { + value = newValue + } + + startValue = value + sendActions(for: .valueChanged) + var degree = Math.degreeFromValue(startAngle, value: sliderValue, maxValue: maxValue, minValue: minValue) + + if startValue == maxValue { + degree -= degree / (360 * 100) + } + + layout(degree) + } + } + private var trackLayer: TrackLayer! { + didSet { + layer.addSublayer(trackLayer) + } + } + private var thumbView: UIView! { + didSet { + if sliderEnabled { + thumbView.backgroundColor = thumbColor + thumbView.center = thumbCenter(startAngle) + thumbView.layer.cornerRadius = thumbView!.bounds.size.width * 0.5 + addSubview(thumbView) + if let thumbImage = thumbImage { + let thumbImageView = UIImageView(frame: thumbView.bounds) + thumbImageView.image = thumbImage + thumbView.addSubview(thumbImageView) + thumbView.backgroundColor = UIColor.clear + } + } else { + thumbView.isHidden = true + } + } + } + + private var startAngle: Double = -90 + private var barColor = UIColor.lightGray + private var trackingColor = UIColor.blue + private var thumbColor = UIColor.black + private var barWidth: CGFloat = 20 + private var maxValue: Float = 101 + private var minValue: Float = 0 + private var sliderEnabled = true + private var viewInset: CGFloat = 20 + private var minMaxSwitchTreshold: Float = 0.0 + private var thumbImage: UIImage? + private var _thumbWidth: CGFloat? + private var thumbWidth: CGFloat { + get { + if let retValue = _thumbWidth { + return retValue + } + + return (thumbImage?.size.height)! + } + set { + _thumbWidth = newValue + } + } + + override open func awakeFromNib() { + super.awakeFromNib() + backgroundColor = UIColor.clear + } + + public init(frame: CGRect, options: [CircleSliderOption]?) { + super.init(frame: frame) + if let options = options { + build(options) + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapHandle(sender:))) + tapGesture.numberOfTouchesRequired = 1 + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(tapHandle(sender:))) + addGestureRecognizer(tapGesture) + addGestureRecognizer(panGesture) + } + } + + required public init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override open func layoutSublayers(of layer: CALayer) { + if trackLayer == nil { + trackLayer = TrackLayer(bounds: bounds.insetBy(dx: viewInset, dy: viewInset), setting: createLayerSetting()) + } + if thumbView == nil { + if let image = thumbImage { + thumbView = UIView(frame: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) + } else { + thumbView = UIView(frame: CGRect(x: 0, y: 0, width: thumbWidth, height: thumbWidth)) + } + } + } + + override open func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if !sliderEnabled { + return nil + } + + return self + } + + open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + var bounds = self.bounds + bounds = bounds.insetBy(dx: 100.0, dy: 100.0) + return bounds.contains(point) + } + + override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { + let degree = Math.pointPairToBearingDegrees(center, endPoint: touch.location(in: self)) + latestDegree = degree + layout(degree) + let value = Float(Math.adjustValue(startAngle, degree: degree, maxValue: maxValue, minValue: minValue)) + thumbView.transform = CGAffineTransform(rotationAngle: CGFloat(Math.degreesToRadians(degree))) + sliderValue = value + return true + } + + @objc + func tapHandle(sender: UIGestureRecognizer) { + if isUserInteractionEnabled { + let degree = Math.pointPairToBearingDegrees(center, endPoint: sender.location(in: self)) + latestDegree = degree + layout(degree) + let value = Float(Math.adjustValue(startAngle, degree: degree, maxValue: maxValue, minValue: minValue)) + thumbView.transform = CGAffineTransform(rotationAngle: CGFloat(Math.degreesToRadians(degree))) + sliderValue = value + } + } + + open func changeOptions(_ options: [CircleSliderOption]) { + build(options) + redraw() + } + + private func redraw() { + + if trackLayer != nil { + trackLayer.removeFromSuperlayer() + } + trackLayer = TrackLayer(bounds: bounds.insetBy(dx: viewInset, dy: viewInset), setting: createLayerSetting()) + if thumbView != nil { + thumbView.removeFromSuperview() + } + + if let image = thumbImage { + thumbView = UIView(frame: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) + } else { + thumbView = UIView(frame: CGRect(x: 0, y: 0, width: thumbWidth, height: thumbWidth)) + } + + self.layout(self.latestDegree) + } + + func build(_ options: [CircleSliderOption]) { + for option in options { + switch option { + case let .startAngle(value): + startAngle = value + latestDegree = startAngle + case let .barColor(value): + barColor = value + case let .trackingColor(value): + trackingColor = value + case let .thumbColor(value): + thumbColor = value + case let .barWidth(value): + barWidth = value + case let .thumbWidth(value): + thumbWidth = value + case let .maxValue(value): + maxValue = value + maxValue += 1 + case let .minValue(value): + minValue = value + startValue = minValue + case let .sliderEnabled(value): + sliderEnabled = value + case let .viewInset(value): + viewInset = value + case let .minMaxSwitchTreshold(value): + minMaxSwitchTreshold = value + case let .thumbImage(value): + thumbImage = value + } + } + } + + private func layout(_ degree: Double) { + if let trackLayer = trackLayer, let thumbView = self.thumbView { + trackLayer.degree = degree + thumbView.center = thumbCenter(degree) + thumbView.transform = CGAffineTransform(rotationAngle: CGFloat(Math.degreesToRadians(degree))) + trackLayer.setNeedsDisplay() + } + } + + private func createLayerSetting() -> TrackLayer.Setting { + var setting = TrackLayer.Setting() + setting.startAngle = startAngle + setting.barColor = barColor + setting.trackingColor = trackingColor + setting.barWidth = barWidth + return setting + } + + private func thumbCenter(_ degree: Double) -> CGPoint { + let radius = (bounds.insetBy(dx: viewInset, dy: viewInset).width * 0.5) - (barWidth * 0.5) + 5 + return Math.pointFromAngle(frame, angle: degree, radius: Double(radius)) + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ExtensionModel.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ExtensionModel.swift new file mode 100755 index 0000000..bd2655a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ExtensionModel.swift @@ -0,0 +1,126 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +public enum DeviceType: String { + + case iPhone5 = "iPhone5" + case iPhone5C = "iPhone5C" + case iPhone5S = "iPhone5S" + case iPhone6Plus = "iPhone6Plus" + case iPhone6 = "iPhone6" + case iPhone6S = "iPhone6S" + case iPhone6SPlus = "iPhone6SPlus" + case iPhone7 = "iPhone7" + case iPhone7Plus = "iPhone7Plus" + case iPhoneSE = "iPhoneSE" + + case IPodTouch5 = "iPod5,1" + case IPodTouch6 = "iPod7,1" +} + +func parseDeviceType(_ identifier: String) -> DeviceType { + + switch identifier { + case "iPhone5,1", "iPhone5,2": return .iPhone5 + case "iPhone5,3", "iPhone5,4": return .iPhone5C + case "iPhone6,1", "iPhone6,2": return .iPhone5S + case "iPhone7,1": return .iPhone6Plus + case "iPhone7,2": return .iPhone6 + case "iPhone8,2": return .iPhone6SPlus + case "iPhone8,1": return .iPhone6S + case "iPhone9,1", "iPhone9,3": return .iPhone7 + case "iPhone9,2", "iPhone9,4": return .iPhone7Plus + case "iPhone8,4": return .iPhoneSE + + case "iPod5,1": return .IPodTouch5 + case "iPod7,1": return .IPodTouch6 + + default: + if UIDevice.iPhonePlus { + return .iPhone7Plus + } else { + return .iPhone7 + } + } +} + +var pixelPerInchIphonePlus: CGFloat = 401 + +var pixelPerInchIphone: CGFloat = 326 + +var inchPerMm: CGFloat = 25.4 + +var renderedPixels: CGFloat = 1.15 + +func parsePixelPerInch(deviceType: DeviceType) -> CGFloat { + + switch deviceType { + case .iPhone5, .iPhone5C, .iPhone5S, .iPhoneSE, .iPhone6, .iPhone6S, .iPhone7, .IPodTouch5, .IPodTouch6: return pixelPerInchIphone + case .iPhone6Plus, .iPhone6SPlus, .iPhone7Plus: return pixelPerInchIphonePlus + } +} + +public extension UIDevice { + + class var deviceType: DeviceType { + var systemInfo = utsname() + uname(&systemInfo) + + let machine = systemInfo.machine + let mirror = Mirror(reflecting: machine) + var identifier = "" + + for child in mirror.children { + if let value = child.value as? Int8, value != 0 { + identifier.append(String(UnicodeScalar(UInt8(value)))) + } + } + + return parseDeviceType(identifier) + } + + class var pixelsPerMm: CGFloat { + return parsePixelPerInch(deviceType: UIDevice.deviceType) / inchPerMm + } + + class var iPhonePlus: Bool { + if UIDevice.current.userInterfaceIdiom != .phone { + return false + } + + if UIScreen.main.scale > 2.9 { + return true + } + + return false + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/EyeActivitySlider.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/EyeActivitySlider.swift new file mode 100755 index 0000000..37877e7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/EyeActivitySlider.swift @@ -0,0 +1,181 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +internal class EyeActivitySlider: UIView { + + private var testType: VisionStepType? + + private var incorrectAnswers = 0 + private let contentGap: CGFloat = 20.0 + private let toleranceAngle = 22.5 + private let letterAngles = [0, 45, 90, 135, 180, 225, 270, 315] + private var letterSize: CGFloat { + var letterSize: CGFloat! + + if self.testType == .visualAcuity { + letterSize = letterMmSizes[currentStep] * UIDevice.pixelsPerMm / UIScreen.main.nativeScale + } else { + letterSize = 20 * UIDevice.pixelsPerMm / UIScreen.main.nativeScale + } + + return letterSize + } + + private var currentStep = 0 + private var letterMmSizes: [CGFloat] = [5.82, 4.65, 3.72, 2.91, 2.33, 1.86, 1.45, 1.16, 0.93, 0.73, 0.58, 0.47, 0.37] + private var contrastLevels: [CGFloat] = [0.9, 0.92, 0.937, 0.95, 0.96, 0.968, 0.975, 0.98, 0.984, 0.9875, 0.99] + private var stepScores: [Int] = [50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110] + private var letterAngle = 0.0 + + private lazy var letterImageView: UIImageView = { + let letterImage = UIImage(named: "iCNLandoltC", + in: Bundle(for: type(of: self)), + compatibleWith: nil) + let imageView = UIImageView(image: letterImage!) + return imageView + }() + + private lazy var circleImageView: UIImageView = { + let circleImage = UIImage(named: "orangeGrayCircle", + in: Bundle(for: type(of: self)), + compatibleWith: nil) + return UIImageView(image: circleImage!) + }() + + private var slider: CircleSlider? + + internal init(testType: VisionStepType) { + super.init(frame: CGRect()) + + self.testType = testType + commonInit() + } + + required internal init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + commonInit() + } + + private func commonInit() { + addSubview(letterImageView) + + circleImageView.contentMode = .scaleAspectFit + addSubview(circleImageView) + + let thumbImage = UIImage(named: "iCNDialPointerWithShadow", + in: Bundle(for: type(of: self)), + compatibleWith: nil) + + slider = CircleSlider(frame: bounds, options: [ + CircleSliderOption.barColor(UIColor.clear), + CircleSliderOption.trackingColor(UIColor.clear), + CircleSliderOption.startAngle(0), + CircleSliderOption.maxValue(360), + CircleSliderOption.minValue(0), + CircleSliderOption.thumbImage(thumbImage!) + ]) + + addSubview(slider!) + updateSliderAndLetter() + } + + override public func layoutSubviews() { + super.layoutSubviews() + + letterAngle = Double(letterAngles[Int(arc4random_uniform(7))]) + letterImageView.transform = CGAffineTransform.identity + letterImageView.frame = CGRect(origin: CGPoint(), size: CGSize(width: letterSize, height: letterSize)) + letterImageView.center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2) + letterImageView.transform = CGAffineTransform(rotationAngle: CGFloat(Math.degreesToRadians(letterAngle))) + letterImageView.alpha = getAlpha() + slider?.frame = bounds + + var frame = contentFrame() + circleImageView.frame = frame + + let labelMargin: CGFloat = 30.0 + frame.origin.x += labelMargin + frame.origin.y += labelMargin + frame.size.width -= labelMargin * 2 + frame.size.height -= labelMargin * 2 + } + + private func updateSliderAndLetter() { + guard incorrectAnswers < 2 else { return } + + letterImageView.isHidden = false + slider?.sliderValue = 0 + slider?.isUserInteractionEnabled = true + slider?.isHidden = false + setNeedsLayout() + } + + private func contentFrame() -> CGRect { + let sideLength = min(bounds.size.width, bounds.size.height) - contentGap + let contentFrame = CGRect(x: (bounds.size.width - sideLength) / 2, y: (bounds.size.height - sideLength) / 2, width: sideLength, height: sideLength) + return contentFrame + } + + private func getAlpha() -> CGFloat { + return testType == .visualAcuity ? 1.0 : (1 - contrastLevels[currentStep]) + } + + private func getResult() -> Bool { + let sliderValue = Double((slider?.sliderValue)!) + let leftMargin = letterAngle - toleranceAngle + let rightMargin = letterAngle + toleranceAngle + let result = sliderValue > leftMargin && sliderValue < rightMargin + + if result == false { + incorrectAnswers += 1 + } else { + currentStep += 1 + } + + return result + } + + internal func hideLetter() { + letterImageView.isHidden = true + } + + internal func fetchResultDataAndUpdateSlider() -> (outcome: Bool, letterAngle: Double, sliderAngle: Double, score: Int, incorrectAnswers: Int, maxScore: Int) { + let outcome = getResult() + let score = stepScores[currentStep] + let currentSliderValue = Double((slider?.sliderValue)!) + let currentLetterAngle = letterAngle + let maxScore = testType == .visualAcuity ? stepScores.last! : stepScores[contrastLevels.count - 1] + updateSliderAndLetter() + + return (outcome, currentLetterAngle, currentSliderValue, score, incorrectAnswers, maxScore) + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.h new file mode 100755 index 0000000..3cb4f06 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import HealthKit; + + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_OPTIONS(NSInteger, ORKSampleJSONOptions) { + ORKSampleIncludeMetadata = 0x1, + ORKSampleIncludeSource = 0x2, + ORKSampleIncludeUUID = 0x4 +}; + +/** + JSON serialization aid for HKSample. + */ +@interface HKSample (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(nullable HKUnit *)unit; + +@end + + +/** + JSON serialization aid for HKCorrelation. + */ +@interface HKCorrelation (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options sampleTypes:(NSArray *)sampleTypes units:(NSArray *)units; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.m new file mode 100755 index 0000000..0edddba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/HKSample+ORKJSONDictionary.m @@ -0,0 +1,169 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "HKSample+ORKJSONDictionary.h" + +#import "ORKHelpers_Internal.h" + + +static NSString *const HKSampleIdentifierKey = @"type"; // For compatibility with Health XML export +static NSString *const HKUUIDKey = @"uuid"; +static NSString *const HKSampleStartDateKey = @"startDate"; +static NSString *const HKSampleEndDateKey = @"endDate"; +static NSString *const HKSampleValue = @"value"; +static NSString *const HKMetadataKey = @"metadata"; +static NSString *const HKSourceKey = @"source"; +static NSString *const HKUnitKey = @"unit"; +static NSString *const HKCorrelatedObjectsKey = @"objects"; +// static NSString *const HKSourceIdentifierKey = @"sourceBundleIdentifier"; + + +@implementation HKSample (ORKJSONDictionary) + +- (NSMutableDictionary *)ork_JSONMutableDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(HKUnit *)unit { + NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:12]; + + // Type identification + HKSampleType *sampleType = [self sampleType]; + mutableDictionary[HKSampleIdentifierKey] = [sampleType identifier]; + + // consider adding @"class" : NSStringFromClass(sampleType) ? + + // Start and end dates + NSDate *startDate = [self startDate]; + if (startDate) { + mutableDictionary[HKSampleStartDateKey] = ORKStringFromDateISO8601(startDate); + } + + NSDate *endDate = [self endDate]; + if (endDate) { + mutableDictionary[HKSampleEndDateKey] = ORKStringFromDateISO8601(endDate); + } + if (unit) { + mutableDictionary[HKUnitKey] = [unit unitString]; + } + if ((options & ORKSampleIncludeUUID)) { + NSUUID *uuid = [self UUID]; + if (uuid) { + mutableDictionary[HKUUIDKey] = uuid.UUIDString; + } + } + + if ( (options & ORKSampleIncludeMetadata) && self.metadata.count > 0) { + NSMutableDictionary *metadata = [self.metadata mutableCopy]; + for (NSString *k in metadata) { + id obj = metadata[k]; + if ([obj isKindOfClass:[NSDate class]]) { + metadata[k] = ORKStringFromDateISO8601(obj); + } + } + + mutableDictionary[HKMetadataKey] = metadata; + } + + if (options & ORKSampleIncludeSource) { + HKSource *source = [[self sourceRevision] source]; + if (source.name) { + mutableDictionary[HKSourceKey] = source.name; + } + } + + return mutableDictionary; +} + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(HKUnit *)unit { + return [self ork_JSONMutableDictionaryWithOptions:options unit:unit]; +} + +@end + + +@interface HKCategorySample (ORKJSONDictionary) + +@end + + +@implementation HKCategorySample (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(HKUnit *)unit { + NSMutableDictionary *dictionary = [self ork_JSONMutableDictionaryWithOptions:options unit:unit]; + + NSInteger value = self.value; + dictionary[HKSampleValue] = @(value); + + return dictionary; +} + +@end + + +@interface HKQuantitySample (ORKJSONDictionary) + +@end + + +@implementation HKQuantitySample (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options unit:(HKUnit *)unit { + NSMutableDictionary *dictionary = [self ork_JSONMutableDictionaryWithOptions:options unit:unit]; + + HKQuantity *quantity = [self quantity]; + double value = [quantity doubleValueForUnit:unit]; + dictionary[HKSampleValue] = @(value); + + + return dictionary; +} + +@end + + +@implementation HKCorrelation (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)options sampleTypes:(NSArray *)sampleTypes units:(NSArray *)units { + NSMutableDictionary *mutableDictionary = [self ork_JSONMutableDictionaryWithOptions:options unit:nil]; + + // The correlated objects + NSMutableArray *correlatedObjects = [NSMutableArray arrayWithCapacity:sampleTypes.count]; + for (HKSample *sample in self.objects) { + NSUInteger idx = [sampleTypes indexOfObject:sample.sampleType]; + if (idx == NSNotFound) { + continue; + } + + [correlatedObjects addObject:[sample ork_JSONDictionaryWithOptions:options unit:units[idx]]]; + } + mutableDictionary[HKCorrelatedObjectsKey] = correlatedObjects; + + return mutableDictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Math.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Math.swift new file mode 100755 index 0000000..68b6df8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Math.swift @@ -0,0 +1,76 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +internal class Math { + + internal class func degreesToRadians(_ angle: Double) -> Double { + return angle / 180 * .pi + } + + internal class func pointFromAngle(_ frame: CGRect, angle: Double, radius: Double) -> CGPoint { + let radian = degreesToRadians(angle) + let xPoint = Double(frame.midX) + cos(radian) * radius + let yPoint = Double(frame.midY) + sin(radian) * radius + return CGPoint(x: xPoint, y: yPoint) + } + + internal class func pointPairToBearingDegrees(_ startPoint: CGPoint, endPoint: CGPoint) -> Double { + let originPoint = CGPoint(x: endPoint.x - startPoint.x, y: endPoint.y - startPoint.y) + let bearingRadians = atan2(Double(originPoint.y), Double(originPoint.x)) + var bearingDegrees = bearingRadians * (180.0 / .pi) + bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)) + return bearingDegrees + } + + internal class func adjustValue(_ startAngle: Double, degree: Double, maxValue: Float, minValue: Float) -> Double { + let ratio = Double((maxValue - minValue) / 360) + let ratioStart = ratio * startAngle + let ratioDegree = ratio * degree + let adjustValue: Double + if startAngle < 0 { + adjustValue = (360 + startAngle) > degree ? (ratioDegree - ratioStart) : (ratioDegree - ratioStart) - (360 * ratio) + } else { + adjustValue = (360 - (360 - startAngle)) < degree ? (ratioDegree - ratioStart) : (ratioDegree - ratioStart) + (360 * ratio) + } + return adjustValue + (Double(minValue)) + } + + internal class func adjustDegree(_ startAngle: Double, degree: Double) -> Double { + return (360 + startAngle) > degree ? degree : -(360 - degree) + } + + internal class func degreeFromValue(_ startAngle: Double, value: Float, maxValue: Float, minValue: Float) -> Double { + let ratio = Double((maxValue - minValue) / 360) + let angle = Double(value) / ratio + return angle + startAngle - (Double(minValue) / ratio) + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Noise.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Noise.wav new file mode 100755 index 0000000..dd47878 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Noise.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.h new file mode 100755 index 0000000..72b4dab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKAccelerometerRecorder` class represents a recorder that requests and collects raw accelerometer data from CoreMotion at a fixed frequency. + + The accelerometer recorder continues to record when the application enters the + background by using the background task support provided by UIApplication. + */ +ORK_CLASS_AVAILABLE +@interface ORKAccelerometerRecorder : ORKRecorder + +/** + The frequency of accelerometer data collected from CoreMotion, in hertz (Hz). + */ +@property (nonatomic, readonly) double frequency; + +/** + Returns an initialized accelerometer recorder using the specified frequency. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param frequency The frequency of accelerometer data collected from CoreMotion, in hertz (Hz). + @param step The step that requested this recorder. + @param outputDirectory The directory in which the accelerometer data should be stored. + + @return An initialized accelerometer recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + frequency:(double)frequency + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.m new file mode 100755 index 0000000..288ebc5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAccelerometerRecorder.m @@ -0,0 +1,231 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAccelerometerRecorder.h" + +#import "ORKDataLogger.h" + +#import "ORKRecorder_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "CMAccelerometerData+ORKJSONDictionary.h" + +@import CoreMotion; + + +@interface ORKAccelerometerRecorder () { + ORKDataLogger *_logger; + NSError *_recordingError; +} + +@property (nonatomic, strong) CMMotionManager *motionManager; + +@property (nonatomic) NSTimeInterval uptime; + +@end + + +@implementation ORKAccelerometerRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier step:step outputDirectory:outputDirectory]; + if (self) { + self.frequency = frequency; + self.continuesInBackground = YES; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (NSString *)recorderType { + return @"accel"; +} + +- (void)setFrequency:(double)frequency { + if (frequency <= 0) { + _frequency = 1; + } else { + _frequency = frequency; + } +} + +- (CMMotionManager *)createMotionManager { + return [[CMMotionManager alloc] init]; +} + +- (void)start { + [super start]; + + self.motionManager = [self createMotionManager]; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + if (!self.motionManager || !self.motionManager.accelerometerAvailable) { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:NSFeatureUnsupportedError + userInfo:@{@"recorder": self}]; + [self finishRecordingWithError:error]; + return; + } + + self.motionManager.accelerometerUpdateInterval = 1.0 / _frequency; + + self.uptime = [NSProcessInfo processInfo].systemUptime; + + [self.motionManager stopAccelerometerUpdates]; + + [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *data, NSError *error) { + BOOL success = NO; + if (data) { + success = [_logger append:[data ork_JSONDictionary] error:&error]; + } + if (!success) { + dispatch_async(dispatch_get_main_queue(), ^{ + _recordingError = error; + [self stop]; + }); + } + }]; +} + +- (NSDictionary *)userInfo { + return @{ @"frequency": @(self.frequency) }; +} + +- (void)stop { + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = _recordingError; + _recordingError = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (self.isRecording) { + [self.motionManager stopAccelerometerUpdates]; + self.motionManager = nil; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:nil]; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +- (BOOL)isRecording { + return self.motionManager.accelerometerActive; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +@end + + +@implementation ORKAccelerometerRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithIdentifier:(NSString *)identifier { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use subclass designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency { + self = [super initWithIdentifier:identifier]; + if (self) { + _frequency = frequency; + } + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return [[ORKAccelerometerRecorder alloc] initWithIdentifier:self.identifier + frequency:self.frequency + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, frequency); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, frequency); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.frequency == castObject.frequency)); +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionCoreMotionAccelerometer; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.h new file mode 100755 index 0000000..8ea323b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.h @@ -0,0 +1,211 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import HealthKit; +#import + + +@class ORKRecorderConfiguration; + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKActiveStep` class is the base class for steps in active tasks, which + are steps that collect sensor data in a semi-controlled environment, as opposed + to the purely passive data collection enabled by HealthKit, or the more subjective data + collected when users fill in surveys. + + In addition to the behaviors of `ORKStep`, active steps have the concept of + life cycle, which includes a defined start and finish. + + The ResearchKit framework provides built-in behaviors that allow active steps to play voice prompts, speak a count down, and have a + defined duration. + + To present an active step in your app, it's likely that you will subclass `ORKActiveStep` and + `ORKActiveStepViewController` to present custom UI and custom + prompts. For example subclasses, see `ORKSpatialSpanMemoryStep` or `ORKFitnessStep`. + Active steps may also need `ORKResult` subclasses to record their results + if these don't come purely from recorders. + + If you develop a new active step subclass, consider contributing your + code to the ResearchKit project so that it's available for others to use in + their studies. + + See also: `ORKActiveStepViewController` + */ +ORK_CLASS_AVAILABLE +@interface ORKActiveStep : ORKStep + +/** + The duration of the step in seconds. + + If the step duration is greater than zero, a built-in timer starts when the + step starts. If `shouldStartTimerAutomatically` is set, the timer + starts when the step's view appears. When the timer expires, a sound or + vibration may be played. If `shouldContinueOnFinish` is set, the step +automatically navigates forward when the timer expires. + + The default value of this property is `0`, which disables the built-in timer. + + See also: `ORKActiveStepViewController` + */ +@property (nonatomic) NSTimeInterval stepDuration; + +/** + A Boolean value indicating whether to show a view with a default timer. + + The default timer UI is not used in any of the current predefined tasks, + but it can be displayed in a simple active task that does not require custom + UI and needs only a count down timer on screen during data collection. + + Note that this property is ignored if `stepDuration` is `0`. + + The default value of this property is `YES`. + */ +@property (nonatomic) BOOL shouldShowDefaultTimer; + +/** + A Boolean value indicating whether to speak the last few seconds in the count down of the + duration of a timed step. + + When the value of this property is `YES`, `AVSpeechSynthesizer` is used to synthesize the countdown. Note that this property is ignored if VoiceOver is enabled. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldSpeakCountDown; + +/** + A Boolean value indicating whether to speak the halfway point in the count down of the + duration of a timed step. + + When the value of this property is `YES`, `AVSpeechSynthesizer` is used to synthesize the countdown. Note that this property is ignored if VoiceOver is enabled. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldSpeakRemainingTimeAtHalfway; + + +/** + A Boolean value indicating whether to start the count down timer automatically when the step starts, or + require the user to take some explicit action to start the step, such as tapping a button. + + Usually the explicit action needs to come from custom UI in an + `ORKActiveStepViewController` subclass. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldStartTimerAutomatically; + +/** + A Boolean value indicating whether to play a default sound when the step starts. + +The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldPlaySoundOnStart; + +/** + A Boolean value indicating whether to play a default sound when the step finishes. + +The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldPlaySoundOnFinish; + +/** + A Boolean value indicating whether to vibrate when the step starts. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldVibrateOnStart; + +/** + A Boolean value indicating whether to vibrate when the step finishes. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldVibrateOnFinish; + +/** + A Boolean value indicating whether the Next button should double as a skip action before + the step finishes. + + When the value of this property is `YES`, the ResearchKit framework hides the skip button and makes the Next button function as a skip button when the step has not yet finished. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldUseNextAsSkipButton; + +/** + A Boolean value indicating whether to transition automatically when the step finishes. + + When the value of this property is `YES`, the active step view controller automatically performs the + continue action when the `[ORKActiveStepViewController finish]` method + is called. + + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldContinueOnFinish; + +/** + Localized text that represents an instructional voice prompt. + + Instructional speech begins when the step starts. If VoiceOver is active, + the instruction is spoken by VoiceOver. + */ +@property (nonatomic, copy, nullable) NSString *spokenInstruction; + +/** + Localized text that represents an instructional voice prompt for when the step finishes. + + Instructional speech begins when the step finishes. If VoiceOver is active, + the instruction is spoken by VoiceOver. + */ +@property (nonatomic, copy, nullable) NSString *finishedSpokenInstruction; + +/** + An array of recorder configurations that define the parameters for recorders to be + run during a step to collect sensor or other data. + + If you want to collect data from sensors while the step is in progress, + add one or more recorder configurations to the array. The active step view + controller instantiates recorders and collates their results as children + of the step result. + + The set of recorder configurations is scanned when populating the + `requestedHealthKitTypesForReading` and `requestedPermissions` properties. + + See also: `ORKRecorderConfiguration` and `ORKRecorder`. + */ +@property (nonatomic, copy, nullable) NSArray *recorderConfigurations; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.m new file mode 100755 index 0000000..485c9b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep.m @@ -0,0 +1,187 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStep.h" +#import "ORKActiveStep_Internal.h" + +#import "ORKActiveStepViewController.h" +#import "ORKRecorder_Private.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKActiveStep + ++ (Class)stepViewControllerClass { + return [ORKActiveStepViewController class]; +} + +- (BOOL)startsFinished { + return (_stepDuration == 0); +} + +- (BOOL)hasCountDown { + return (_stepDuration > 0) && _shouldShowDefaultTimer; +} + +- (BOOL)hasTitle { + NSString *title = self.title; + return (title != nil && title.length > 0); +} + +- (BOOL)hasText { + NSString *text = self.text; + return (text != nil && text.length > 0); +} + +- (BOOL)hasVoice { + BOOL hasSpokenInstruction = (_spokenInstruction != nil && _spokenInstruction.length > 0); + BOOL hasFinishedSpokenInstruction = (_finishedSpokenInstruction != nil && _finishedSpokenInstruction.length > 0); + return (hasSpokenInstruction || hasFinishedSpokenInstruction); +} + +- (BOOL)isRestorable { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = YES; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKActiveStep *step = [super copyWithZone:zone]; + step.stepDuration = self.stepDuration; + step.shouldStartTimerAutomatically = self.shouldStartTimerAutomatically; + step.shouldSpeakCountDown = self.shouldSpeakCountDown; + step.shouldSpeakRemainingTimeAtHalfway = self.shouldSpeakRemainingTimeAtHalfway; + step.shouldShowDefaultTimer = self.shouldShowDefaultTimer; + step.shouldPlaySoundOnStart = self.shouldPlaySoundOnStart; + step.shouldPlaySoundOnFinish = self.shouldPlaySoundOnFinish; + step.shouldVibrateOnStart = self.shouldVibrateOnStart; + step.shouldVibrateOnFinish = self.shouldVibrateOnFinish; + step.shouldUseNextAsSkipButton = self.shouldUseNextAsSkipButton; + step.shouldContinueOnFinish = self.shouldContinueOnFinish; + step.spokenInstruction = self.spokenInstruction; + step.finishedSpokenInstruction = self.finishedSpokenInstruction; + step.recorderConfigurations = [self.recorderConfigurations copy]; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self ) { + ORK_DECODE_DOUBLE(aDecoder, stepDuration); + ORK_DECODE_BOOL(aDecoder, shouldStartTimerAutomatically); + ORK_DECODE_BOOL(aDecoder, shouldSpeakCountDown); + ORK_DECODE_BOOL(aDecoder, shouldSpeakRemainingTimeAtHalfway); + ORK_DECODE_BOOL(aDecoder, shouldShowDefaultTimer); + ORK_DECODE_BOOL(aDecoder, shouldPlaySoundOnStart); + ORK_DECODE_BOOL(aDecoder, shouldPlaySoundOnFinish); + ORK_DECODE_BOOL(aDecoder, shouldVibrateOnStart); + ORK_DECODE_BOOL(aDecoder, shouldVibrateOnFinish); + ORK_DECODE_BOOL(aDecoder, shouldUseNextAsSkipButton); + ORK_DECODE_BOOL(aDecoder, shouldContinueOnFinish); + ORK_DECODE_OBJ_CLASS(aDecoder, spokenInstruction, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, finishedSpokenInstruction, NSString); + ORK_DECODE_OBJ_ARRAY(aDecoder, recorderConfigurations, ORKRecorderConfiguration); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, stepDuration); + ORK_ENCODE_BOOL(aCoder, shouldStartTimerAutomatically); + ORK_ENCODE_BOOL(aCoder, shouldSpeakCountDown); + ORK_ENCODE_BOOL(aCoder, shouldSpeakRemainingTimeAtHalfway); + ORK_ENCODE_BOOL(aCoder, shouldShowDefaultTimer); + ORK_ENCODE_BOOL(aCoder, shouldPlaySoundOnStart); + ORK_ENCODE_BOOL(aCoder, shouldPlaySoundOnFinish); + ORK_ENCODE_BOOL(aCoder, shouldVibrateOnStart); + ORK_ENCODE_BOOL(aCoder, shouldVibrateOnFinish); + ORK_ENCODE_BOOL(aCoder, shouldUseNextAsSkipButton); + ORK_ENCODE_BOOL(aCoder, shouldContinueOnFinish); + ORK_ENCODE_OBJ(aCoder, spokenInstruction); + ORK_ENCODE_OBJ(aCoder, finishedSpokenInstruction); + ORK_ENCODE_OBJ(aCoder, recorderConfigurations); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.spokenInstruction, castObject.spokenInstruction) && + ORKEqualObjects(self.finishedSpokenInstruction, castObject.finishedSpokenInstruction) && + ORKEqualObjects(self.recorderConfigurations, castObject.recorderConfigurations) && + (self.stepDuration == castObject.stepDuration) && + (self.shouldShowDefaultTimer == castObject.shouldShowDefaultTimer) && + (self.shouldStartTimerAutomatically == castObject.shouldStartTimerAutomatically) && + (self.shouldSpeakCountDown == castObject.shouldSpeakCountDown) && + (self.shouldSpeakRemainingTimeAtHalfway == castObject.shouldSpeakRemainingTimeAtHalfway) && + (self.shouldPlaySoundOnStart == castObject.shouldPlaySoundOnStart) && + (self.shouldPlaySoundOnFinish == castObject.shouldPlaySoundOnFinish) && + (self.shouldVibrateOnStart == castObject.shouldVibrateOnStart) && + (self.shouldVibrateOnFinish == castObject.shouldVibrateOnFinish) && + (self.shouldContinueOnFinish == castObject.shouldContinueOnFinish) && + (self.shouldUseNextAsSkipButton == castObject.shouldUseNextAsSkipButton)); +} + +- (NSSet *)requestedHealthKitTypesForReading { + NSMutableSet *set = [NSMutableSet set]; + for (ORKRecorderConfiguration *config in self.recorderConfigurations) { + NSSet *subset = [config requestedHealthKitTypesForReading]; + if (subset) { + [set unionSet:subset]; + } + } + return set; +} + +- (ORKPermissionMask)requestedPermissions { + ORKPermissionMask mask = [super requestedPermissions]; + for (ORKRecorderConfiguration *config in self.recorderConfigurations) { + mask |= [config requestedPermissionMask]; + } + return mask; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.h new file mode 100755 index 0000000..3b94c4e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKQuantityLabel : ORKLabel + +@end + + +@interface ORKActiveStepQuantityView : UIView + +@property (nonatomic, strong, nullable) NSString *title; +@property (nonatomic, strong, nullable) NSString *value; +@property (nonatomic, strong, nullable) UIImage *image; +@property (nonatomic) BOOL enabled; + +@property (nonatomic, strong, readonly, nullable) UILabel *titleLabel; +@property (nonatomic, strong, readonly, nullable) UILabel *valueLabel; + +@end + + +@interface ORKQuantityPairView : UIView + +@property (nonatomic, strong, nullable) ORKActiveStepQuantityView *leftView; +@property (nonatomic, strong, nullable) ORKActiveStepQuantityView *rightView; + +@property (nonatomic, assign) BOOL keylineHidden; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.m new file mode 100755 index 0000000..c588f56 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepQuantityView.m @@ -0,0 +1,333 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStepQuantityView.h" + +#import "ORKSubheadlineLabel.h" +#import "ORKTintedImageView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKQuantityLabel + ++ (UIFont *)defaultFont { + return ORKTimeFontForSize(35); +} + +@end + + +@implementation ORKActiveStepQuantityView { + ORKSubheadlineLabel *_titleLabel; + ORKQuantityLabel *_valueLabel; + ORKTintedImageView *_imageView; + UIView *_valueHolder; + + NSLayoutConstraint *_zeroWidthConstraint; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _titleLabel = [ORKSubheadlineLabel new]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + _valueLabel = [ORKQuantityLabel new]; + _valueLabel.textAlignment = NSTextAlignmentCenter; + _imageView = [ORKTintedImageView new]; + _imageView.shouldApplyTint = YES; + _valueHolder = [UIView new]; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + _valueLabel.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + _valueHolder.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_titleLabel]; + [_valueHolder addSubview:_valueLabel]; + [_valueHolder addSubview:_imageView]; + [self addSubview:_valueHolder]; + +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.2]; + _titleLabel.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.2]; + _valueLabel.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.2]; +#endif + + for (UIView *view in @[_titleLabel, _valueLabel, _imageView]) { + view.isAccessibilityElement = NO; + } + + [self setUpConstraints]; + } + return self; +} + +- (void)setEnabled:(BOOL)enabled { + _enabled = enabled; + self.hidden = !enabled; + [self setNeedsUpdateConstraints]; +} + +- (void)setTitle:(NSString *)title { + _title = title; + _titleLabel.text = title; +} + +- (void)setValue:(NSString *)value { + _value = value; + _valueLabel.text = value; +} + +- (void)setImage:(UIImage *)image { + _image = nil; + _imageView.image = image; +} + +- (void)setUpConstraints { + + const CGFloat TitleBaselineToValueBaseline = 40; + const CGFloat ValueBaselineToBottom = 36; + + NSMutableArray *constraints = [NSMutableArray array]; + NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _valueLabel, _imageView); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_titleLabel]" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_titleLabel]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_imageView]-10-[_valueLabel]|" + options:NSLayoutFormatAlignAllCenterY + metrics:nil + views:views]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueLabel + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:_titleLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:TitleBaselineToValueBaseline]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_valueLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:ValueBaselineToBottom]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueHolder + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_valueHolder + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueLabel + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_valueHolder + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueHolder + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_valueHolder + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + for (NSLayoutConstraint *constraint in constraints) { + constraint.priority = UILayoutPriorityRequired - 2; + } + + [NSLayoutConstraint activateConstraints:constraints]; + + _zeroWidthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; + _zeroWidthConstraint.priority = UILayoutPriorityRequired - 1; + [self setNeedsUpdateConstraints]; +} + +- (void)updateConstraints { + _zeroWidthConstraint.active = !_enabled; + [super updateConstraints]; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + return _titleLabel.accessibilityLabel; +} + +- (NSString *)accessibilityValue { + return _valueLabel.accessibilityLabel; +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitUpdatesFrequently; +} + +@end + + +@implementation ORKQuantityPairView { + UIView *_metricKeyline; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _leftView = [ORKActiveStepQuantityView new]; + _rightView = [ORKActiveStepQuantityView new]; + + _leftView.translatesAutoresizingMaskIntoConstraints = NO; + _rightView.translatesAutoresizingMaskIntoConstraints = NO; + _metricKeyline = [UIView new]; + _metricKeyline.translatesAutoresizingMaskIntoConstraints = NO; + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setKeylineHidden:NO]; + _metricKeyline.backgroundColor = [UIColor ork_midGrayTintColor]; + + [self addSubview:_leftView]; + [self addSubview:_rightView]; + [self addSubview:_metricKeyline]; + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + + NSMutableArray *constraints = [NSMutableArray array]; + NSDictionary *views = NSDictionaryOfVariableBindings(_leftView, _rightView, _metricKeyline); + + // Leave space for the keyline between these views, and then constrain it to be 1px wide and go from top to bottom baseline of metric views. + CGFloat scale = [UIScreen mainScreen].scale; + NSArray *vertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_leftView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]; + [constraints addObjectsFromArray:vertConstraints]; + + NSArray *horizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_leftView]-s-[_rightView]-|" + options:NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom|NSLayoutFormatDirectionLeftToRight + metrics:@{ @"s": @(1.0 / scale) } + views:views]; + for (NSLayoutConstraint *constraint in horizConstraints) { + constraint.priority = UILayoutPriorityDefaultHigh + 1; + } + [constraints addObjectsFromArray:horizConstraints]; + + // Ensure baseline alignment of title and value + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftView.titleLabel + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:_rightView.titleLabel + attribute:NSLayoutAttributeFirstBaseline + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftView.valueLabel + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:_rightView.valueLabel + attribute:NSLayoutAttributeFirstBaseline + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_leftView][_metricKeyline(==s)]" + options:NSLayoutFormatAlignAllTop|NSLayoutFormatDirectionLeftToRight + metrics:@{ @"s": @(1.0 / scale) } + views:views]]; + NSLayoutConstraint *keylineBottom = [NSLayoutConstraint constraintWithItem:_metricKeyline + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_leftView.valueLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:0.0]; + [constraints addObject:keylineBottom]; + + NSLayoutConstraint *maxWidthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + maxWidthConstraint.priority = UILayoutPriorityRequired - 2; + [constraints addObject:maxWidthConstraint]; + + + // This constraint should be beaten out by the full-width-coverage and zero-width constraints if only one of the views is enabled. + NSLayoutConstraint *equalWidthConstraint = [NSLayoutConstraint constraintWithItem:_leftView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_rightView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]; + equalWidthConstraint.priority = UILayoutPriorityDefaultLow; + [constraints addObject:equalWidthConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setKeylineHidden:(BOOL)keylineHidden { + _keylineHidden = keylineHidden; + _metricKeyline.hidden = keylineHidden; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.h new file mode 100755 index 0000000..d095484 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKActiveStepTimer; + +typedef void (^ORKActiveStepTimerHandler)(ORKActiveStepTimer *timer, BOOL finished); + +@interface ORKActiveStepTimer : NSObject + +- (instancetype)initWithDuration:(NSTimeInterval)duration interval:(NSTimeInterval)interval runtime:(NSTimeInterval)runtime handler:(ORKActiveStepTimerHandler)handler; + +@property (nonatomic, assign) NSTimeInterval duration; + +@property (nonatomic, readonly) NSTimeInterval interval; + +@property (nonatomic, readonly) NSTimeInterval runtime; + +/* + Handler callbacks are returned on interval boundaries. The timer automatically + pauses itself when finished=YES. + + This handler is retained. Be careful not to create a retain cycle. + */ +@property (nonatomic, copy, readonly) ORKActiveStepTimerHandler handler; + +// Pauses the timer. +- (void)pause; + +// Resumes the timer where it left off. +- (void)resume; + +// Sets runtime to 0. Stops the timer if it is running. +- (void)reset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.m new file mode 100755 index 0000000..16849d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimer.m @@ -0,0 +1,243 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStepTimer.h" + +#import "ORKHelpers_Internal.h" + +@import UIKit; +#include +#include + + +static NSTimeInterval timeIntervalFromMachTime(uint64_t delta) { + static mach_timebase_info_data_t sTimebaseInfo; + if ( sTimebaseInfo.denom == 0 ) { + (void) mach_timebase_info(&sTimebaseInfo); + } + uint64_t elapsedNano = delta * sTimebaseInfo.numer / sTimebaseInfo.denom; + return elapsedNano * 1.0 / NSEC_PER_SEC; +} + + +@implementation ORKActiveStepTimer { + uint64_t _startTime; + NSTimeInterval _preExistingRuntime; + dispatch_queue_t _queue; + dispatch_source_t _timer; + UIBackgroundTaskIdentifier _backgroundTaskIdentifier; + uint32_t _isRunning; +} + +- (instancetype)initWithDuration:(NSTimeInterval)duration interval:(NSTimeInterval)interval runtime:(NSTimeInterval)runtime handler:(ORKActiveStepTimerHandler)handler { + self = [super init]; + if (self) { + if (!handler) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Handler is required" userInfo:nil]; + } + + _duration = duration; + _interval = interval; + _handler = [handler copy]; + _preExistingRuntime = runtime; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + + _queue = dispatch_queue_create("active_step", DISPATCH_QUEUE_SERIAL); + + } + return self; +} + +- (void)dealloc { + [self queue_pauseAtFinish:NO]; +} + +- (NSTimeInterval)runtime { + __block NSTimeInterval runtime = 0; + dispatch_sync(_queue, ^{ + runtime = [self queue_runtime]; + }); + return MIN(runtime,_duration); +} + +- (void)pause { + dispatch_sync(_queue, ^{ + [self queue_pauseAtFinish:NO]; + }); +} + +- (void)resume { + dispatch_sync(_queue, ^{ + [self queue_resume]; + }); +} + +- (void)reset { + dispatch_sync(_queue, ^{ + [self queue_reset]; + }); +} + +- (NSTimeInterval)queue_runtime { + NSTimeInterval runtime = _preExistingRuntime; + if (_timer != NULL) { + uint64_t now = mach_absolute_time(); + runtime += timeIntervalFromMachTime(now - _startTime); + } + return runtime; +} + +- (void)setDuration:(NSTimeInterval)duration { + dispatch_sync(_queue, ^{ + _duration = duration; + }); +} + +- (void)hiqueue_event { + dispatch_sync(_queue, ^{ + [self queue_event]; + }); +} + +- (void)queue_event { + [self queue_assertBackgroundTask]; + + NSTimeInterval runtime = [self queue_runtime]; + BOOL finished = (runtime >= _duration); + if (finished) { + [self queue_pauseAtFinish:YES]; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + _handler(self, finished); + dispatch_sync(_queue, ^{ + + // If the timer is still NULL here, we can safely release the background task. + if (_timer == NULL) { + [self queue_releaseBackgroundTask]; + } + }); + }); +} + +- (void)queue_clearTimer { + if (_timer != NULL) { + + dispatch_source_cancel(_timer); + _timer = NULL; + } +} + +- (void)queue_releaseBackgroundTask { + if (_backgroundTaskIdentifier == UIBackgroundTaskInvalid) { + return; + } + UIBackgroundTaskIdentifier identifier = _backgroundTaskIdentifier; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] endBackgroundTask:identifier]; + }); +} + +- (void)queue_assertBackgroundTask { + if (_backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + return; + } + _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + // This is guaranteed to be called synchronously on the main queue, switch to our queue to invalidate the identifier + dispatch_sync(_queue, ^{ + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + }); + }]; +} + +- (void)queue_resume { + if (_timer != NULL) { + // Already resumed + return; + } + if ([self queue_runtime] >= _duration) { + // Already finished. Fire one event to indicate. + [self queue_event]; + return; + } + + // We want to run in the background if we can, so voice can be played, etc. + assert(_backgroundTaskIdentifier == UIBackgroundTaskInvalid); + + [self queue_assertBackgroundTask]; + + _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, + 0, 0, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)); + if (_timer == NULL) { + assert(0); + return; + } + ORKWeakTypeOf(self) weakSelf = self; + dispatch_source_set_event_handler(_timer, ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf hiqueue_event]; + }); + + NSTimeInterval timeUntilNextFire = (floor(_preExistingRuntime / _interval) + 1)*_interval - _preExistingRuntime; + + _startTime = mach_absolute_time(); + dispatch_source_set_timer(_timer, + dispatch_time(DISPATCH_TIME_NOW, timeUntilNextFire * NSEC_PER_SEC), + _interval * NSEC_PER_SEC, + 0.05 * NSEC_PER_SEC); + dispatch_resume(_timer); +} + +- (void)queue_pauseAtFinish:(BOOL)atFinish { + if (_timer == NULL) { + // Not running + return; + } + + uint64_t now = mach_absolute_time(); + [self queue_clearTimer]; + _preExistingRuntime += timeIntervalFromMachTime(now - _startTime); + _startTime = 0; + + if (!atFinish) { + // If we are atFinish, the task will be released after the handler completes + [self queue_releaseBackgroundTask]; + } +} + +- (void)queue_reset { + [self queue_clearTimer]; + _preExistingRuntime = 0; + [self queue_releaseBackgroundTask]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.h new file mode 100755 index 0000000..51eae5c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKActiveStep; +@class ORKCountdownLabel; +@class ORKTextButton; + +@interface ORKActiveStepTimerView : ORKActiveStepCustomView + +@property (nonatomic, strong, nullable) ORKCountdownLabel *countDownLabel; + +@property (nonatomic, strong, nullable) ORKTextButton *startTimerButton; + +@property (nonatomic, strong, nullable) ORKActiveStep *step; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.m new file mode 100755 index 0000000..a56984d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepTimerView.m @@ -0,0 +1,234 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStepTimerView.h" + +#import "ORKActiveStepTimer.h" +#import "ORKCountdownLabel.h" +#import "ORKSurveyAnswerCellForText.h" +#import "ORKSurveyAnswerCellForNumber.h" +#import "ORKTextButton.h" +#import "ORKVoiceEngine.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKActiveStep_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKActiveStepTimerView { + BOOL _started; + BOOL _registeredForNotifications; + + NSLayoutConstraint *_countDownLabelBottomToStartTimerButtonTopConstraint; + NSLayoutConstraint *_countDownLabelZeroHeightConstraint; + NSLayoutConstraint *_startTimerButtonZeroHeightConstraint; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + // Count Down + { + _countDownLabel = [ORKCountdownLabel new]; + _countDownLabel.textAlignment = NSTextAlignmentCenter; + _countDownLabel.text = @" "; + + [self addSubview:_countDownLabel]; + } + // Count down start button + { + _startTimerButton = [ORKTextButton new]; + [_startTimerButton setTitle:ORKLocalizedString(@"BUTTON_START_TIMER", nil) forState:UIControlStateNormal]; + [_startTimerButton addTarget:self action:@selector(startTimerButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; + _startTimerButton.exclusiveTouch = YES; + + [self addSubview:_startTimerButton]; + } + + _countDownLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently; + + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + } + return self; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + ORKActiveStepViewController *viewController = self.activeStepViewController; + if (viewController) { + [self updateDisplay:viewController]; + } +} + +- (void)setRegisteredForNotifications:(BOOL)registered { + if (registered == _registeredForNotifications) { + return; + } + + registered = _registeredForNotifications; + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + if (registered) { + [notificationCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; + } else { + [notificationCenter removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; + } +} + +- (void)didMoveToWindow { + [self setRegisteredForNotifications:(self.window != nil)]; +} + +- (void)setStep:(ORKActiveStep *)step { + _step = step; + _countDownLabel.hidden = !(_step.hasCountDown); + BOOL hasTimerButton = (_step.hasCountDown && _step.shouldStartTimerAutomatically == NO); + _startTimerButton.hidden = !hasTimerButton; + _startTimerButton.alpha = 1; + + [_countDownLabel setCountDownValue:(NSInteger)[_step stepDuration]]; + + [self setNeedsUpdateConstraints]; +} + +- (void)startTimerButtonTapped:(id)sender { + [self.activeStepViewController start]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _countDownLabel); +} + +- (void)updateDisplay:(ORKActiveStepViewController *)viewController { + NSInteger countDownValue = (NSInteger)round(viewController.timeRemaining); + [_countDownLabel setCountDownValue:countDownValue]; +} + +- (void)resetStep:(ORKActiveStepViewController *)viewController { + self.step = (ORKActiveStep *)viewController.step; +} + +- (void)startStep:(ORKActiveStepViewController *)viewController { + _startTimerButton.alpha = 0; +} + +- (void)suspendStep:(ORKActiveStepViewController *)viewController { +} + +- (void)resumeStep:(ORKActiveStepViewController *)viewController { + self.step = (ORKActiveStep *)viewController.step; + if ([viewController timerActive]) { + _startTimerButton.alpha = 0; + [self updateDisplay:viewController]; + } +} + +- (void)finishStep:(ORKActiveStepViewController *)viewController { +} + +static const CGFloat CountDownLabelToButtonMargin = 2.0; + +- (void)setUpConstraints { + NSDictionary *views = NSDictionaryOfVariableBindings(_countDownLabel, _startTimerButton); + ORKEnableAutoLayoutForViews(views.allValues); + + NSMutableArray *constraints = [NSMutableArray new]; + + for (UIView *view in views.allValues) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + } + + [constraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_countDownLabel + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + _countDownLabelBottomToStartTimerButtonTopConstraint = [NSLayoutConstraint constraintWithItem:_startTimerButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_countDownLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:CountDownLabelToButtonMargin]; + [constraints addObject:_countDownLabelBottomToStartTimerButtonTopConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_startTimerButton + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; + + _countDownLabelZeroHeightConstraint = [NSLayoutConstraint constraintWithItem:_countDownLabel + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; + _startTimerButtonZeroHeightConstraint = [NSLayoutConstraint constraintWithItem:_startTimerButton + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; + [self setNeedsUpdateConstraints]; +} + +- (void)updateConstraints { + _countDownLabelZeroHeightConstraint.active = _countDownLabel.hidden; + _startTimerButtonZeroHeightConstraint.active = (_countDownLabel.hidden || _startTimerButton.hidden); + _countDownLabelBottomToStartTimerButtonTopConstraint.constant = + (_countDownLabel.hidden || _startTimerButton.hidden) ? 0.0 : CountDownLabelToButtonMargin; + [super updateConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.h new file mode 100755 index 0000000..dee18bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.h @@ -0,0 +1,259 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKActiveStepViewController` class is the base class for displaying `ORKActiveStep` + subclasses. The predefined active tasks defined in `ORKOrderedTask` all make use + of subclasses of `ORKActiveStep`, paired with `ORKActiveStepViewController` + subclasses. + + An active step view controller is typically instantiated by a task view controller + when it encounters an active step in a task. Active steps generally include some form of sensor-driven data collection, or involve some highly interactive content, such as a cognitive task or game. + + Examples of active step view controller subclasses include `ORKWalkingTaskStepViewController`, + `ORKCountdownStepViewController`, `ORKSpatialSpanMemoryStepViewController`, + `ORKFitnessStepViewController`, and `ORKAudioStepViewController`. + + The primary feature that active step view controllers enable is life cycle. After an active step is presented, it can be started to start a timer. When the timer expires, the + step is considered finished. Some steps may have the concept of suspend and resume, such as when + the app is put in the background, and during which data recording is temporarily paused. + These life cycle methods generally apply to any recorders being used to record + data from the device's sensors, but they should also be applied to any UI + being displayed to clearly indicate when data is being collected + for the task. + + When you develop a new active step, you should subclass `ORKActiveStepViewController` + and define your specific UI. When subclassing, pay special attention to the life cycle + methods, `start`, `finish`, `suspend`, and `resume`. Also, be sure to test for + the expected behavior when the user suspends and resumes the app, during task + save and restore, and during UIKit's UI state restoration. + + See also: `ORKActiveStep`. + */ +ORK_CLASS_AVAILABLE +@interface ORKActiveStepViewController : ORKStepViewController + +/// @name UI Customization + +/** + The custom view for the active step. + + Attach a custom view here, and implement `sizeThatFits:` or + use `intrinsicContentSize` or provide constraints that request the size needed for + the custom view within the active step's layout. + + Custom views can be used for visual instructions with animation, + or for getting interactive input. + */ +@property (nonatomic, strong, nullable) UIView *customView; + +/** + The image view for the active step. (read-only) + + The image view is created on demand when this property is accessed, and is a + shortcut to display an image in the custom area of an active task (that is, instead of + using `customView`). + */ +@property (nonatomic, strong, readonly, nullable) UIImageView *imageView; + +/// @name Data collection + +/** + The array of recorders currently in use by the active step. (read-only) + + Recorders are generated when the step starts, based on the recorder + configurations of the step. Each recorder is an instance of `ORKRecorder`, and + is created by the active step view controller using the array of recorder + configurations in the step. + + See also: `ORKRecorderConfiguration` and `ORKActiveStep`. + */ +@property (nonatomic, strong, readonly, nullable) NSArray *recorders; + +/// @name Active step life cycle + +/** + A Boolean value that indicates whether the step has finished. (read-only) + + If the step is considered finished, the Continue button is enabled and the Skip + button is hidden. When the step is not finished, the Continue button is disabled and the Skip + button is visible. + + In addition, when a step is finished, all recorders are stopped. + */ +@property (nonatomic, assign, readonly, getter=isFinished) BOOL finished; + +/** + A Boolean value that indicates whether the step has started. (read-only) + + If the step has not yet started, recorders are not yet running, and time + is not counted against the `duration` of the step. + */ +@property (nonatomic, assign, readonly, getter=isStarted) BOOL started; + +/** + Tells the view controller that the active step has finished. + + This method is an override point for subclasses, called by the base class when + the step has just finished. + + The default implementation does nothing except in the case of steps that have countdown + enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured. + */ +- (void)stepDidFinish; + +/** + A Boolean value that indicates whether to suspend the step if the app is not + active or the screen is off. + + Active steps that require the screen in order to work should suspend + recording when the app goes into the background. Other active steps require + the step to continue while the app is in the background. For example, the fitness check + active step continues to collect data while the screen is off, and continues + to give voice prompts. + */ +@property (nonatomic, assign) BOOL suspendIfInactive; + +/** + Starts the active step. + + Call this method to start the timer on the active step, if there is one, and + to start any data recording. + + When you start the step, recorders are instantiated based on their configurations and then started. All + timers should start, and the UI should show users that the step is in progress. + + This method does nothing if the step has already started. + + Subclasses should super when overriding this method. + */ +- (void)start; + +/** + Suspends the active step. + + Call this method to suspend data recording and the step's timer. + + This method may called automatically when the app is suspended. + The view controller can be configured not to suspend even if the app + goes into the background (for more information, see `suspendIfInactive`). + + Subclasses should call super when overriding this method. + */ +- (void)suspend; + +/** + Resumes the active step. + + Call this method when the step should be resumed. Calls to this method should + be paired with previous calls to `suspend`. + + This method may be called automatically when the app is resumed. The view + controller can be configured not to suspend even if the app + goes into the background (for more information, see `suspendIfInactive`). + + When the step is resumed, the UI should resume at the point where the user left off, + or, if that does not make sense for the particular step, to the most recent + suitable point. + + Subclasses should call super when overriding this method. + */ +- (void)resume; + +/** + Finishes the active step. + + Call this method to finish the active step. If the active step is configured with + a timer, this method is called automatically when the timer expires. + + Finishing the active step stops all data recording and stops any timers. In steps that have the + `shouldContinueOnFinish` property set, forward navigation to the next step + may ensue. + + This method does nothing if the step has already finished. + + Subclasses should call super when overriding this method. + */ +- (void)finish; + +/// @name Recorder life cycle + +/** + Tells the view controller that the set of recorders changed. + + This method is usually called by the active step view controller in response + to `start` or `resume`. + + Subclasses may override this method. + */ +- (void)recordersDidChange; + +/** + Tells the view controller that the recorders are about to start. + + This method is called by the active step view controller after instantiating + the recorders, but before starting them. + + Subclasses may override this method. + */ +- (void)recordersWillStart; + +/** + Tells the view controller that the recorders are about to stop. + + This method is called by the active step view controller before + stopping the recorders. + + Subclasses may override this method. + */ +- (void)recordersWillStop; + +/** + Tells the view controller that the step has been loaded and is about to start. + + This method is called by the active step view controller just after the step + has been set. The base implementation instantiates the recorders and timer but + does not start them. + + Subclasses may override this method, but must also call super. + */ +- (void)prepareStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.m new file mode 100755 index 0000000..08c5e98 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController.m @@ -0,0 +1,572 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepTimerView.h" +#import "ORKActiveStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKVerticalContainerView.h" +#import "ORKVoiceEngine.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKRecorder_Internal.h" + +#import "ORKActiveStep_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKResult.h" +#import "ORKTask.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKActiveStepViewController () { + ORKActiveStepView *_activeStepView; + ORKActiveStepTimer *_activeStepTimer; + + NSArray *_recorderResults; + + SystemSoundID _alertSound; + NSURL *_alertSoundURL; + BOOL _hasSpokenHalfwayCountdown; + NSArray *_constraints; +} + +@property (nonatomic, strong) NSArray *recorders; + +@end + + +@implementation ORKActiveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + + self = [super initWithStep:step]; + if (self) { + _recorderResults = [NSArray new]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; + _timerUpdateInterval = 1; + } + return self; +} + +- (void)applicationWillResignActive:(NSNotification *)notification { + if (self.suspendIfInactive) { + [self suspend]; + } +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + if (self.suspendIfInactive) { + [self resume]; + } +} + +- (ORKActiveStep *)activeStep { + NSAssert(self.step == nil || [self.step isKindOfClass:[ORKActiveStep class]], @"Step should be a subclass of an ORKActiveStep"); + return (ORKActiveStep *)self.step; +} + +- (ORKActiveStepView *)activeStepView { + return _activeStepView; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setActiveStepView]; + [self setNavigationFooterView]; + [self updateContinueButtonItem]; + [self setupConstraints]; + [self prepareStep]; +} + +- (void)setActiveStepView { + if (!_activeStepView) { + _activeStepView = [ORKActiveStepView new]; + [_activeStepView placeNavigationContainerInsideScrollView]; + } + if (_customView) { + _activeStepView.customContentView = _customView; + } + [self.view addSubview:_activeStepView]; +} + +- (void)setNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = _activeStepView.navigationFooterView; + } + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueEnabled = _finished; + + ORKActiveStep *step = [self activeStep]; + _navigationFooterView.useNextForSkip = step.shouldUseNextAsSkipButton; + _navigationFooterView.optional = step.optional; + BOOL neverHasContinueButton = (step.shouldContinueOnFinish && !step.startsFinished); + [_navigationFooterView setNeverHasContinueButton:neverHasContinueButton]; + [_navigationFooterView updateContinueAndSkipEnabled]; + + [self updateContinueButtonItem]; +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _constraints = nil; + + + _activeStepView.translatesAutoresizingMaskIntoConstraints = NO; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_activeStepView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_activeStepView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_activeStepView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_activeStepView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)stepDidChange { + [super stepDidChange]; + ORKActiveStep *step = [self activeStep]; + _activeStepView.activeStep = step; + [self prepareStep]; +} + +- (void)setCustomView:(UIView *)customView { + _customView = customView; + if (_customView) { + [_activeStepView setCustomContentView:_customView]; + } +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + if (_activeStepView.navigationFooterView) { + [_activeStepView.navigationFooterView flattenIfNeeded]; + } + ORK_Log_Debug("%@",self); +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + ORK_Log_Debug("%@",self); + + // Wait for animation complete + dispatch_async(dispatch_get_main_queue(), ^{ + if(self.started){ + // Should call resume instead of start when the task has been started. + [self resume]; + } else if ([[self activeStep] shouldStartTimerAutomatically]) { + [self start]; + } + }); +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + ORK_Log_Debug("%@",self); + + [self suspend]; +} + +- (void)updateContinueButtonItem { + _navigationFooterView.continueButtonItem = self.continueButtonItem; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + [self updateContinueButtonItem]; +} + +- (void)setLearnMoreButtonItem:(UIBarButtonItem *)learnMoreButtonItem { + [super setLearnMoreButtonItem:learnMoreButtonItem]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _navigationFooterView.skipButtonItem = skipButtonItem; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + [super setCancelButtonItem:cancelButtonItem]; +} + +- (void)setFinished:(BOOL)finished { + _finished = finished; + _navigationFooterView.continueEnabled = finished; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + if (_recorderResults) { + sResult.results = [sResult.results arrayByAddingObjectsFromArray:_recorderResults] ? : _recorderResults; + } + return sResult; +} + +#pragma mark - transition + +- (void)recordersDidChange { +} + +- (void)recordersWillStart { +} + +- (void)recordersWillStop { +} + +- (void)prepareRecorders { + // Stop any existing recorders + [self recordersWillStop]; + for (ORKRecorder *recorder in self.recorders) { + recorder.delegate = nil; + [recorder stop]; + } + NSMutableArray *recorders = [NSMutableArray array]; + + for (ORKRecorderConfiguration * provider in self.activeStep.recorderConfigurations) { + // If the outputDirectory is nil, recorders which require one will generate an error. + // We start them anyway, because we don't know which recorders will require an outputDirectory. + ORKRecorder *recorder = [provider recorderForStep:self.step + outputDirectory:self.outputDirectory]; + recorder.configuration = provider; + recorder.delegate = self; + + [recorders addObject:recorder]; + } + self.recorders = recorders; + + [self recordersDidChange]; +} + +- (void)setOutputDirectory:(NSURL *)outputDirectory { + [super setOutputDirectory:outputDirectory]; + [self prepareStep]; +} + +- (void)prepareStep { + if (self.activeStep == nil) { + return; + } + + self.finished = [[self activeStep] startsFinished]; + + ORK_Log_Debug("%@", self); + _activeStepView.activeStep = self.activeStep; + + if ([self.activeStep hasCountDown]) { + ORKActiveStepTimerView *timerView = [ORKActiveStepTimerView new]; + _activeStepView.activeCustomView = timerView; + } else { + _activeStepView.activeCustomView = nil; + } + _activeStepView.activeCustomView.activeStepViewController = self; + [_activeStepView.activeCustomView resetStep:self]; + [self resetTimer]; + + [self prepareRecorders]; +} + +- (void)startRecorders { + [self recordersWillStart]; + // Start recorders + for (ORKRecorder *recorder in self.recorders) { + [recorder viewController:self willStartStepWithView:self.customViewContainer]; + [recorder start]; + } +} + +- (void)stopRecorders { + [self recordersWillStop]; + for (ORKRecorder *recorder in self.recorders) { + [recorder stop]; + } +} + +- (void)playSound { + if (_alertSoundURL == nil) { + _alertSoundURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/short_low_high.caf"]; + AudioServicesCreateSystemSoundID((__bridge CFURLRef)(_alertSoundURL), &_alertSound); + } + AudioServicesPlaySystemSound(_alertSound); +} + +- (void)start { + ORK_Log_Debug("%@",self); + self.started = YES; + [self startTimer]; + [_activeStepView.activeCustomView startStep:self]; + + [self startRecorders]; + + if (self.activeStep.shouldVibrateOnStart) { + AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); + } + + if (self.activeStep.shouldPlaySoundOnStart) { + [self playSound]; + } + + // Start speech + if (self.activeStep.hasVoice && self.activeStep.spokenInstruction) { + // Let VO speak "Step x of y" before the instruction. + // If VO is not running, the text is spoken immediately. + ORKAccessibilityPerformBlockAfterDelay(1.5, ^{ + [[ORKVoiceEngine sharedVoiceEngine] speakText:self.activeStep.spokenInstruction]; + }); + } +} + +- (void)suspend { + ORK_Log_Debug("%@",self); + if (self.finished || !self.started) { + return; + } + + [_activeStepTimer pause]; + [_activeStepView.activeCustomView suspendStep:self]; + + [self stopRecorders]; +} + +- (void)resume { + ORK_Log_Debug("%@",self); + if (self.finished || !self.started) { + return; + } + + [_activeStepTimer resume]; + [self prepareRecorders]; + [self startRecorders]; + [_activeStepView.activeCustomView resumeStep:self]; +} + +- (void)finish { + ORK_Log_Debug("%@",self); + if (self.finished) { + return; + } + + self.finished = YES; + [_activeStepTimer pause]; + [_activeStepView.activeCustomView finishStep:self]; + [self stopRecorders]; + if (self.activeStep.shouldPlaySoundOnFinish) { + [self playSound]; + } + if (self.activeStep.shouldVibrateOnFinish) { + AudioServicesPlayAlertSound(kSystemSoundID_Vibrate); + } + if (self.activeStep.hasVoice && self.activeStep.finishedSpokenInstruction) { + [[ORKVoiceEngine sharedVoiceEngine] speakText:self.activeStep.finishedSpokenInstruction]; + } + if (!self.activeStep.startsFinished) { + if (self.activeStep.shouldContinueOnFinish) { + [self goForward]; + } + } + [self stepDidFinish]; +} + +- (void)dealloc { + AudioServicesDisposeSystemSoundID(_alertSound); + NSNotificationCenter *nfc = [NSNotificationCenter defaultCenter]; + [nfc removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + [nfc removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; +} + +#pragma mark - timers + +- (void)resetTimer { + [_activeStepTimer reset]; + _activeStepTimer = nil; +} + +- (void)startTimer { + [self resetTimer]; + + NSTimeInterval stepDuration = self.activeStep.stepDuration; + + if (stepDuration > 0) { + ORKWeakTypeOf(self) weakSelf = self; + _activeStepTimer = [[ORKActiveStepTimer alloc] initWithDuration:stepDuration + interval:_timerUpdateInterval + runtime:0 + handler:^(ORKActiveStepTimer *timer, BOOL finished) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf countDownTimerFired:timer finished:finished]; + }]; + [_activeStepTimer resume]; + } +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + if (finished) { + [self finish]; + } + NSInteger countDownValue = (NSInteger)round(timer.duration - timer.runtime); + ORKActiveStepCustomView *customView = _activeStepView.activeCustomView; + [customView updateDisplay:self]; + + + ORKVoiceEngine *voice = [ORKVoiceEngine sharedVoiceEngine]; + + if (!finished && self.activeStep.shouldSpeakCountDown) { + // Speak entire countdown if VO is running. + if (UIAccessibilityIsVoiceOverRunning()) { + [voice speakInt:countDownValue]; + return; + } + + if (0 < countDownValue && countDownValue <= 3) { + [voice speakInt:countDownValue]; + } + } + + BOOL isHalfway = !_hasSpokenHalfwayCountdown && timer.runtime > timer.duration / 2.0; + if (!finished && self.activeStep.shouldSpeakRemainingTimeAtHalfway && !UIAccessibilityIsVoiceOverRunning() && isHalfway) { + _hasSpokenHalfwayCountdown = YES; + + NSDateComponentsFormatter *secondsFormatter = [NSDateComponentsFormatter new]; + secondsFormatter.unitsStyle = NSDateFormatterFullStyle; + secondsFormatter.allowedUnits = NSCalendarUnitSecond; + secondsFormatter.formattingContext = NSFormattingContextDynamic; + secondsFormatter.maximumUnitCount = 1; + NSString *seconds = [secondsFormatter stringFromTimeInterval:countDownValue]; + NSString *text = [NSString localizedStringWithFormat:ORKLocalizedString(@"COUNTDOWN_SPOKEN_REMAINING_%@", nil), seconds]; + + [voice speakText:text]; + } +} + +- (BOOL)timerActive { + return (_activeStepTimer != nil); +} + +- (NSTimeInterval)timeRemaining { + if (_activeStepTimer == nil) { + return self.activeStep.stepDuration; + } + return _activeStepTimer.duration - _activeStepTimer.runtime; +} + +- (NSTimeInterval)runtime { + if (_activeStepTimer == nil) { + return 0; + } + return _activeStepTimer.runtime; +} + + +#pragma mark - action handlers + +- (void)stepDidFinish { +} + +#pragma mark - ORKRecorderDelegate + +- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(ORKResult *)result { + _recorderResults = [_recorderResults arrayByAddingObject:result]; + [self notifyDelegateOnResultChange]; +} + +- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + if (error) { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(stepViewController:recorder:didFailWithError:)]) { + [strongDelegate stepViewController:self recorder:recorder didFailWithError:error]; + } + + // If the recorder returns an error indicating that file write failed, and the output directory was nil, + // we consider it a fatal error and fail the step. Otherwise, developers might be confused to get + // no output, just because they did not set an output directory. + if ([error.domain isEqualToString:NSCocoaErrorDomain] && + error.code == NSFileWriteInvalidFileNameError && + self.outputDirectory == nil) { + [strongDelegate stepViewControllerDidFail:self withError:error]; + } + } +} + +static NSString *const _ORKFinishedRestoreKey = @"finished"; +static NSString *const _ORKRecorderResultsRestoreKey = @"recorderResults"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeBool:_finished forKey:_ORKFinishedRestoreKey]; + [coder encodeObject:_recorderResults forKey:_ORKRecorderResultsRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + self.finished = [coder decodeBoolForKey:_ORKFinishedRestoreKey]; + _recorderResults = [coder decodeObjectOfClass:[NSArray class] forKey:_ORKRecorderResultsRestoreKey]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController_Internal.h new file mode 100755 index 0000000..ec75f5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStepViewController_Internal.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKActiveStepTimer; +@class ORKActiveStepView; +@class ORKNavigationContainerView; + +@interface ORKActiveStepViewController () + +/** + The customViewContainer allows custom view to be its subview. + + @note When ORKTouchRecorder is present, its gesture recognizer attaches to customViewContainer. + */ +@property (nonatomic, strong, readonly, nullable) UIView *customViewContainer; + +@property (nonatomic, strong, readonly, nullable) ORKActiveStepView *activeStepView; + +@property (nonatomic, readonly) NSTimeInterval timeRemaining; +@property (nonatomic, readonly) NSTimeInterval runtime; +@property (nonatomic, readonly) BOOL timerActive; +@property (nonatomic, assign) NSTimeInterval timerUpdateInterval; + +@property (nonatomic, assign, getter=isStarted) BOOL started; + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished; // Let subclass receive timer fires + +- (void)applicationWillResignActive:(NSNotification *)notification; +- (void)applicationDidBecomeActive:(NSNotification *)notification; + +- (void)stopRecorders; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep_Internal.h new file mode 100755 index 0000000..51a039d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKActiveStep_Internal.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKActiveStep () + + // Convenience methods. +- (BOOL)startsFinished; +- (BOOL)hasCountDown; +- (BOOL)hasTitle; +- (BOOL)hasText; +- (BOOL)hasVoice; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.h new file mode 100755 index 0000000..73ac9aa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "ORKCustomStepView_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKAmslerGridContentView : ORKActiveStepCustomView + +@property (nonatomic, assign) int numberOfCellsPerSide; +@property (nonatomic, assign) float lineWidth; +@property (nonatomic, strong, nullable) UIColor *lineColor; +@property (nonatomic, strong, nullable) UIColor *backgroundColor; +@property (nonatomic, assign) float ratioOfWidthToRadius; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.m new file mode 100755 index 0000000..db869ab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridContentView.m @@ -0,0 +1,102 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKAmslerGridContentView.h" + +@interface ORKAmslerGridContentView() { + UIBezierPath *path; + CGFloat dimension; +} +@end + +@implementation ORKAmslerGridContentView + +- (void)plotAmslerGrid { + dimension = MIN(self.bounds.size.width, self.bounds.size.height); + + path = [[UIBezierPath alloc] init]; + path.lineWidth = _lineWidth; + + CGFloat cellSize = dimension/_numberOfCellsPerSide; + + for (int index = 0; index < _numberOfCellsPerSide; index ++) { + CGPoint startVertical = CGPointMake((CGFloat)index * cellSize, 0); + CGPoint endVertical = CGPointMake((CGFloat)index * cellSize, dimension); + [path moveToPoint:startVertical]; + [path addLineToPoint:endVertical]; + + CGPoint startHorizontal = CGPointMake(0, (CGFloat)index * cellSize); + CGPoint endHorizontal = CGPointMake(dimension, (CGFloat)index * cellSize); + [path moveToPoint:startHorizontal]; + [path addLineToPoint:endHorizontal]; + } + [path closePath]; +} + +- (void)drawRect:(CGRect)rect { + [super drawRect:rect]; + [_backgroundColor setFill]; + CGContextFillRect(UIGraphicsGetCurrentContext(), rect); + + [self plotAmslerGrid]; + [_lineColor setStroke]; + [path stroke]; + UIBezierPath *circleInTheCenter = [UIBezierPath bezierPathWithArcCenter:CGPointMake(dimension/2, dimension/2) radius:dimension/_ratioOfWidthToRadius startAngle:0 endAngle:360 clockwise:YES]; + [_lineColor setFill]; + [circleInTheCenter fill]; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _numberOfCellsPerSide = 10; + _lineWidth = 1.0; + _ratioOfWidthToRadius = 75; + _lineColor = [UIColor blackColor]; + _backgroundColor = [UIColor whiteColor]; + [self setDimensionConstraint]; + } + return self; +} + +- (void)setDimensionConstraint { + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0] + ]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.h new file mode 100755 index 0000000..9428d56 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.h @@ -0,0 +1,67 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + + +/** + The `ORKAmslerGridResult` class represents the result of a successful attempt of `ORKAmslerGridStep`. + + An amsler grid result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKAmslerGridResult : ORKResult + + +- (instancetype)initWithIdentifier:(NSString *)identifier + image:(UIImage *)image + path:(NSArray *)path + eyeSide:(ORKAmslerGridEyeSide)eyeSide; + +/** + Eye side closed. + */ +@property (nonatomic) ORKAmslerGridEyeSide eyeSide; +/** + The image for the step. + */ +@property (nonatomic, nullable) UIImage *image; + +/** + The path used to mark the area in the image. + */ +@property (nonatomic, copy, nullable) NSArray *path; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.m new file mode 100755 index 0000000..bcde804 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridResult.m @@ -0,0 +1,95 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAmslerGridResult.h" +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKAmslerGridResult + + +- (instancetype)initWithIdentifier:(NSString *)identifier + image:(UIImage *)image + path:(NSArray *)path + eyeSide:(ORKAmslerGridEyeSide)eyeSide{ + self = [super initWithIdentifier:identifier]; + if (self) { + _image = [image copy]; + _path = ORKArrayCopyObjects(path); + _eyeSide = eyeSide; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_IMAGE(aCoder, image); + ORK_ENCODE_OBJ(aCoder, path); + ORK_ENCODE_ENUM(aCoder, eyeSide); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_IMAGE(aDecoder, image); + ORK_DECODE_OBJ_ARRAY(aDecoder, path, UIBezierPath); + ORK_DECODE_ENUM(aDecoder, eyeSide); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return super.hash ^ self.image.hash ^ self.path.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.image, castObject.image) && + ORKEqualObjects(self.path, castObject.path) && + (self.eyeSide == castObject.eyeSide)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKAmslerGridResult *result = [super copyWithZone:zone]; + result->_image = [_image copy]; + result->_path = ORKArrayCopyObjects(_path); + result->_eyeSide = _eyeSide; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.h new file mode 100755 index 0000000..6c1691a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKAmslerGridStep : ORKActiveStep + +@property (nonatomic) ORKAmslerGridEyeSide eyeSide; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.m new file mode 100755 index 0000000..33f3e77 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStep.m @@ -0,0 +1,91 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAmslerGridStep.h" +#import "ORKHelpers_Internal.h" +#import "ORKAmslerGridStepViewController.h" + +@implementation ORKAmslerGridStep + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldVibrateOnStart = YES; + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + self.stepDuration = NSIntegerMax; + self.eyeSide = ORKAmslerGridEyeSideNotSpecified; + } + return self; +} + ++ (Class)stepViewControllerClass { + return [ORKAmslerGridStepViewController class]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, eyeSide); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, eyeSide); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame && (self.eyeSide == castObject.eyeSide)); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)startsFinished { + return NO; +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKAmslerGridStep *step = [super copyWithZone:zone]; + step->_eyeSide = _eyeSide; + return step; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.h new file mode 100755 index 0000000..80f2a92 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKAmslerGridStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.m new file mode 100755 index 0000000..be57ad3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAmslerGridStepViewController.m @@ -0,0 +1,182 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAmslerGridStepViewController.h" +#import "ORKAmslerGridContentView.h" +#import "ORKAmslerGridStep.h" +#import "ORKFreehandDrawingView.h" +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKStepViewController_Internal.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKNavigationContainerView.h" +#import "ORKStep_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKAmslerGridResult.h" +#import "ORKResult_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKBorderedButton.h" + + +@interface ORKAmslerGridStepViewController () { + ORKFreehandDrawingView *_freehandDrawingView; + ORKAmslerGridContentView *_amslerGridView; +} + +@end + +@implementation ORKAmslerGridStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + self.shouldIgnoreiPadDesign = YES; + return self; +} + +- (ORKAmslerGridStep *)amslerGridStep { + return (ORKAmslerGridStep *)self.step; +} + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.view.backgroundColor = [UIColor blackColor]; + _amslerGridView = [ORKAmslerGridContentView new]; + _amslerGridView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _amslerGridView; + [self.activeStepView removeCustomContentPadding]; + + _freehandDrawingView = [ORKFreehandDrawingView new]; + + _freehandDrawingView.translatesAutoresizingMaskIntoConstraints = NO; + _freehandDrawingView.backgroundColor = [UIColor clearColor]; + _freehandDrawingView.opaque = NO; + + [_amslerGridView addSubview:_freehandDrawingView]; + + UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; + [panGestureRecognizer setMinimumNumberOfTouches:2]; + [self.activeStepView addGestureRecognizer:panGestureRecognizer]; + + self.activeStepView.isAccessibilityElement = YES; + self.activeStepView.accessibilityLabel = ORKLocalizedString(@"AX_AMSLER_GRID_LABEL", nil); + self.activeStepView.accessibilityHint = ORKLocalizedString(@"AX_AMSLER_GRID_HINT", nil); + self.activeStepView.accessibilityTraits = UIAccessibilityTraitImage | UIAccessibilityTraitAllowsDirectInteraction; + [self setupContraints]; +} + +- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer { + if (recognizer.state == UIGestureRecognizerStateChanged) { + [self finish]; + } +} + +- (void)setupContraints { + CGFloat width = MIN(self.view.bounds.size.width, self.view.bounds.size.height); + NSArray *constraints = @[ + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:width], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:width], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_amslerGridView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_amslerGridView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return UIInterfaceOrientationMaskPortrait + UIInterfaceOrientationMaskPortraitUpsideDown; +} + +- (void)stepDidFinish { + [super stepDidFinish]; + [self.navigationController setNavigationBarHidden:NO animated:NO]; +} + +- (ORKStepResult *)result { + + ORKStepResult *parentResult = [super result]; + + if (_freehandDrawingView.freehandDrawingExists) { + UIImage *image = [self getImage]; + ORKAmslerGridResult *amslerGridResult = [[ORKAmslerGridResult alloc] initWithIdentifier:self.step.identifier image:image path:_freehandDrawingView.freehandDrawingPath eyeSide: [self amslerGridStep].eyeSide]; + parentResult.results = @[amslerGridResult]; + } + + return parentResult; +} + +- (UIImage *)getImage { + CGSize imageContextSize; + imageContextSize = _amslerGridView.bounds.size; + UIGraphicsBeginImageContext(imageContextSize); + + UIGraphicsBeginImageContextWithOptions(imageContextSize, _amslerGridView.isOpaque, 0.0f); + + CGRect rec = CGRectMake(0, 0, _amslerGridView.bounds.size.width, _amslerGridView.bounds.size.height); + [_amslerGridView drawViewHierarchyInRect:rec afterScreenUpdates:NO]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.h new file mode 100755 index 0000000..a3595ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKAudioContentView : ORKActiveStepCustomView + +@property (nonatomic, copy, nullable) UIColor *keyColor; +@property (nonatomic, copy, nullable) UIColor *alertColor; + +@property (nonatomic, assign) BOOL failed; +@property (nonatomic, assign, getter=isFinished) BOOL finished; +@property (nonatomic, assign) NSTimeInterval timeLeft; + +@property (nonatomic, assign) CGFloat alertThreshold; + +@property (nonatomic, copy, nullable) NSArray *samples; + +// Samples should be in the range of (0, 1). +- (void)addSample:(NSNumber *)sample; +- (void)removeAllSamples; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.m new file mode 100755 index 0000000..3c2d1b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioContentView.m @@ -0,0 +1,262 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioContentView.h" +#import "ORKAudioGraphView.h" + +#import "ORKHeadlineLabel.h" +#import "ORKLabel.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +// The central blue region. +static const CGFloat GraphViewBlueZoneHeight = 170; + +// The two bands at top and bottom which are "loud" each have this height. +static const CGFloat GraphViewRedZoneHeight = 25; + +@interface ORKAudioTimerLabel : ORKLabel + +@end + + +@implementation ORKAudioTimerLabel + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + UIFontDescriptor *alternativeDescriptor = ORKFontDescriptorForLightStylisticAlternative(descriptor); + return [UIFont fontWithDescriptor:alternativeDescriptor size:[alternativeDescriptor pointSize] + 4]; +} + +@end + +@interface ORKAudioContentView () + +@property (nonatomic, strong) ORKHeadlineLabel *alertLabel; +@property (nonatomic, strong) UILabel *timerLabel; +@property (nonatomic, strong) ORKAudioGraphView *graphView; + +@end + + +@implementation ORKAudioContentView { + NSMutableArray *_samples; + UIColor *_keyColor; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); + + self.alertLabel = [ORKHeadlineLabel new]; + _alertLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.timerLabel = [ORKAudioTimerLabel new]; + _timerLabel.translatesAutoresizingMaskIntoConstraints = NO; + _timerLabel.textAlignment = NSTextAlignmentRight; + self.graphView = [ORKAudioGraphView new]; + _graphView.translatesAutoresizingMaskIntoConstraints = NO; + self.translatesAutoresizingMaskIntoConstraints = NO; + + self.alertColor = [UIColor ork_redColor]; + + [self addSubview:_alertLabel]; + [self addSubview:_timerLabel]; + [self addSubview:_graphView]; + + _alertLabel.text = ORKLocalizedString(@"AUDIO_TOO_LOUD_LABEL", nil); + // _timerLabel.text set in -updateTimerLabel: + + self.alertThreshold = GraphViewBlueZoneHeight / ((GraphViewRedZoneHeight * 2) + GraphViewBlueZoneHeight); + + [self updateGraphSamples]; + [self applyKeyColor]; + [self setUpConstraints]; + } + return self; +} + +- (void)tintColorDidChange { + [self applyKeyColor]; +} + +- (void)setFailed:(BOOL)failed { + _failed = failed; + _alertLabel.text = failed ? ORKLocalizedString(@"AUDIO_GENERIC_ERROR_LABEL", nil) : ORKLocalizedString(@"AUDIO_TOO_LOUD_LABEL", nil); + [self updateAlertLabelHidden]; +} + +- (void)setFinished:(BOOL)finished { + _finished = finished; + [self updateAlertLabelHidden]; +} + +- (void)applyKeyColor { + UIColor *keyColor = [self keyColor]; + _timerLabel.textColor = keyColor; + _graphView.keyColor = keyColor; +} + +- (UIColor *)keyColor { + return _keyColor ? : [self tintColor]; +} + +- (void)setKeyColor:(UIColor *)keyColor { + _keyColor = keyColor; + [self applyKeyColor]; +} + +- (void)setAlertColor:(UIColor *)alertColor { + _alertColor = alertColor; + _alertLabel.textColor = alertColor; + _graphView.alertColor = alertColor; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_timerLabel, _alertLabel, _graphView); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_graphView]-[_alertLabel]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_alertLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + const CGFloat sideMargin = self.layoutMargins.left + (2 * ORKStandardLeftMarginForTableViewCell(self)); + const CGFloat innerMargin = 2; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-sideMargin-[_graphView]-innerMargin-[_timerLabel]-sideMargin-|" + options:NSLayoutFormatAlignAllCenterY + metrics:@{@"sideMargin": @(sideMargin), @"innerMargin": @(innerMargin)} + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_graphView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:(GraphViewBlueZoneHeight + GraphViewRedZoneHeight * 2)]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setAlertThreshold:(CGFloat)alertThreshold { + _alertThreshold = alertThreshold; + _graphView.alertThreshold = alertThreshold; + [self updateGraphSamples]; +} + +- (void)setTimeLeft:(NSTimeInterval)timeLeft { + _timeLeft = timeLeft; + [self updateTimerLabel]; +} + +- (void)updateTimerLabel { + static NSDateComponentsFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [NSDateComponentsFormatter new]; + formatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; + formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad; + formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond; + }); + + NSString *string = [formatter stringFromTimeInterval:MAX(round(_timeLeft),0)]; + _timerLabel.text = string; + _timerLabel.hidden = (string == nil); +} + +- (void)updateGraphSamples { + _graphView.values = _samples; + [self updateAlertLabelHidden]; +} + +- (void)updateAlertLabelHidden { + NSNumber *sample = _samples.lastObject; + BOOL show = (!_finished && (sample.doubleValue > _alertThreshold)) || _failed; + + if (_alertLabel.hidden && show) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, _alertLabel.text); + } + _alertLabel.hidden = !show; +} + +- (void)setSamples:(NSArray *)samples { + _samples = [samples mutableCopy]; + [self updateGraphSamples]; +} + +- (void)addSample:(NSNumber *)sample { + NSAssert(sample != nil, @"Sample should be non-nil"); + if (!_samples) { + _samples = [NSMutableArray array]; + } + [_samples addObject:sample]; + // Try to keep around 250 samples + if (_samples.count > 500) { + _samples = [[_samples subarrayWithRange:(NSRange){250, _samples.count - 250}] mutableCopy]; + } + [self updateGraphSamples]; +} + +- (void)removeAllSamples { + _samples = nil; + [self updateGraphSamples]; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + NSString *timerAxString = _timerLabel.isHidden ? nil : _timerLabel.accessibilityLabel; + NSString *alertAxString = _alertLabel.isHidden ? nil : _alertLabel.accessibilityLabel; + return ORKAccessibilityStringForVariables(ORKLocalizedString(@"AX_AUDIO_BAR_GRAPH", nil), timerAxString, alertAxString); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitUpdatesFrequently; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.h new file mode 100755 index 0000000..40ee02a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.h @@ -0,0 +1,110 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + --- + + This software is based on the original source by Matt Gallagher. + http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html + + Copyright (c) 2009-2011 Matt Gallagher. All rights reserved. + + This software is provided 'as-is', without any express or implied warranty. In + no event will the authors be held liable for any damages arising from the use + of this software. Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + + +@import UIKit; +@import AVFoundation; +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKAudioGenerator` class represents an audio tone generator. + */ +ORK_CLASS_AVAILABLE +@interface ORKAudioGenerator : NSObject + +/** + Plays a tone at a specific frequency in stereo. + + The sound is a "pure" sinusoid tone. + + @param frequency The audio frequency in hertz. + */ +- (void)playSoundAtFrequency:(double)frequency; + +/** + Plays a tone at a specific frequency on a specific channel, with a fade-in effect. + + The sound is a "pure" sinusoid tone. + The fade-in effect is applied linearly for the peak amplitude, from a 0 to 1 factor. + + @param frequency The audio frequency in hertz. + @param channel The audio channel (left or right). + @param duration The fade-in duration. + */ +- (void)playSoundAtFrequency:(double)frequency + onChannel:(ORKAudioChannel)channel + fadeInDuration:(NSTimeInterval)duration; + +/** + Stops the audio being played. + */ +- (void)stop; + +/** + Returns the peak audio volume being currently played, in decibels (dB). + + @return The current audio volume in decibels. + */ +- (double)volumeInDecibels; + +/** + Returns the peak audio volume amplitude being currently played (from 0 to 1). + + @return The current audio volume amplitude. + */ +- (double)volumeAmplitude; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.m new file mode 100755 index 0000000..adb0c4f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGenerator.m @@ -0,0 +1,283 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + --- + + This software is based on the original source by Matt Gallagher. + http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html + + Copyright (c) 2009-2011 Matt Gallagher. All rights reserved. + + This software is provided 'as-is', without any express or implied warranty. In + no event will the authors be held liable for any damages arising from the use + of this software. Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + + +#import "ORKAudioGenerator.h" + +@import AudioToolbox; + + +@interface ORKAudioGenerator () { + @public + AudioComponentInstance _toneUnit; + double _frequency; + double _theta; + ORKAudioChannel _activeChannel; + BOOL _playsStereo; + double _fadeInFactor; + NSTimeInterval _fadeInDuration; +} + +- (void)setupAudioSession; +- (void)createToneUnit; +- (void)play; +- (void)handleInterruption:(id)sender; + +@end + + +const double ORKSineWaveToneGeneratorAmplitudeDefault = 0.03f; +const double ORKSineWaveToneGeneratorSampleRateDefault = 44100.0f; + +static OSStatus ORKAudioGeneratorRenderTone(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { + // Fixed amplitude is good enough for our purposes + const double amplitude = ORKSineWaveToneGeneratorAmplitudeDefault; + + // Get the tone parameters out of the view controller + ORKAudioGenerator *audioGenerator = (__bridge ORKAudioGenerator *)inRefCon; + double theta = audioGenerator->_theta; + double theta_increment = 2.0 * M_PI * audioGenerator->_frequency / ORKSineWaveToneGeneratorSampleRateDefault; + + double fadeInFactor = audioGenerator->_fadeInFactor; + + // This is a mono tone generator so we only need the first buffer + Float32 *bufferActive = (Float32 *)ioData->mBuffers[audioGenerator->_activeChannel].mData; + Float32 *bufferNonActive = (Float32 *)ioData->mBuffers[1 - audioGenerator->_activeChannel].mData; + + // Generate the samples + for (UInt32 frame = 0; frame < inNumberFrames; frame++) { + double bufferValue = sin(theta) * amplitude * pow(10, 2 * fadeInFactor - 2); + bufferActive[frame] = bufferValue; + if (audioGenerator->_playsStereo) { + bufferNonActive[frame] = bufferValue; + } else { + bufferNonActive[frame] = 0; + } + + theta += theta_increment; + if (theta > 2.0 * M_PI) { + theta -= 2.0 * M_PI; + } + + fadeInFactor += 1.0 / (ORKSineWaveToneGeneratorSampleRateDefault * audioGenerator->_fadeInDuration); + if (fadeInFactor >= 1) { + fadeInFactor = 1; + } + } + + // Store the theta back in the view controller + audioGenerator->_theta = theta; + audioGenerator->_fadeInFactor = fadeInFactor; + + return noErr; +} + + +@implementation ORKAudioGenerator + +- (instancetype)init { + self = [super init]; + if (self) { + [self setupAudioSession]; + + // Automatically stop and then restart audio playback when the app resigns active. + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; + } + return self; +} + +- (void)dealloc { + [self stop]; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + if (_toneUnit) { + __unused OSErr error = AudioOutputUnitStart(_toneUnit); + NSAssert1(error == noErr, @"Error starting unit: %hd", error); + } +} + +- (void)applicationWillResignActive:(NSNotification *)notification { + if (_toneUnit) { + __unused OSErr error = AudioOutputUnitStop(_toneUnit); + NSAssert1(error == noErr, @"Error stopping unit: %hd", error); + } +} + +- (double)volumeInDecibels { + return 20 * log(self.volumeAmplitude); +} + +- (double)volumeAmplitude { + return ORKSineWaveToneGeneratorAmplitudeDefault * pow(10, 2 * _fadeInFactor - 2); +} + +- (void)playSoundAtFrequency:(double)playFrequency { + _frequency = playFrequency; + _fadeInFactor = 0; + _fadeInDuration = 0.5; + _playsStereo = YES; + + [self play]; +} + +- (void)playSoundAtFrequency:(double)playFrequency + onChannel:(ORKAudioChannel)playChannel + fadeInDuration:(NSTimeInterval)duration { + _frequency = playFrequency; + _activeChannel = playChannel; + _fadeInFactor = 0; + _fadeInDuration = duration; + _playsStereo = NO; + + [self play]; +} + +- (void)play { + if (!_toneUnit) { + [self createToneUnit]; + + // Stop changing parameters on the unit + OSErr error = AudioUnitInitialize(_toneUnit); + NSAssert1(error == noErr, @"Error initializing unit: %hd", error); + + // Start playback + error = AudioOutputUnitStart(_toneUnit); + NSAssert1(error == noErr, @"Error starting unit: %hd", error); + } +} + +- (void)stop { + if (_toneUnit) { + AudioOutputUnitStop(_toneUnit); + AudioUnitUninitialize(_toneUnit); + AudioComponentInstanceDispose(_toneUnit); + _toneUnit = nil; + } +} + +- (void)setupAudioSession { + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + BOOL ok; + NSError *setCategoryError = nil; + ok = [audioSession setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError]; + NSAssert1(ok, @"Audio error %@", setCategoryError); + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleInterruption:) + name:AVAudioSessionInterruptionNotification + object:audioSession]; +} + +- (void)createToneUnit { + // Configure the search parameters to find the default playback output unit + // (called the kAudioUnitSubType_RemoteIO on iOS but + // kAudioUnitSubType_DefaultOutput on Mac OS X) + AudioComponentDescription defaultOutputDescription; + defaultOutputDescription.componentType = kAudioUnitType_Output; + defaultOutputDescription.componentSubType = kAudioUnitSubType_RemoteIO; + defaultOutputDescription.componentManufacturer = kAudioUnitManufacturer_Apple; + defaultOutputDescription.componentFlags = 0; + defaultOutputDescription.componentFlagsMask = 0; + + // Get the default playback output unit + AudioComponent defaultOutput = AudioComponentFindNext(NULL, &defaultOutputDescription); + NSAssert(defaultOutput, @"Can't find default output"); + + // Create a new unit based on this that we'll use for output + OSErr error = AudioComponentInstanceNew(defaultOutput, &_toneUnit); + NSAssert1(_toneUnit, @"Error creating unit: %hd", error); + + // Set our tone rendering function on the unit + AURenderCallbackStruct input; + input.inputProc = ORKAudioGeneratorRenderTone; + input.inputProcRefCon = (__bridge void *)(self); + error = AudioUnitSetProperty(_toneUnit, + kAudioUnitProperty_SetRenderCallback, + kAudioUnitScope_Input, + 0, + &input, + sizeof(input)); + NSAssert1(error == noErr, @"Error setting callback: %hd", error); + + // Set the format to 32 bit, single channel, floating point, linear PCM + const int four_bytes_per_float = 4; + const int eight_bits_per_byte = 8; + AudioStreamBasicDescription streamFormat; + streamFormat.mSampleRate = ORKSineWaveToneGeneratorSampleRateDefault; + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; + streamFormat.mBytesPerPacket = four_bytes_per_float; + streamFormat.mFramesPerPacket = 1; + streamFormat.mBytesPerFrame = four_bytes_per_float; + streamFormat.mChannelsPerFrame = 2; + streamFormat.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte; + error = AudioUnitSetProperty (_toneUnit, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + 0, + &streamFormat, + sizeof(AudioStreamBasicDescription)); + NSAssert1(error == noErr, @"Error setting stream format: %hd", error); +} + +- (void)handleInterruption:(id)sender { + [self stop]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.h new file mode 100755 index 0000000..fe0de38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKAudioGraphView : UIView + +@property (nonatomic, strong) UIColor *keyColor; +@property (nonatomic, strong) UIColor *alertColor; + +@property (nonatomic, copy) NSArray *values; + +@property (nonatomic) CGFloat alertThreshold; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.m new file mode 100755 index 0000000..232b367 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioGraphView.m @@ -0,0 +1,160 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioGraphView.h" +#import "ORKSkin.h" + + +static const CGFloat ValueLineWidth = 4.5; +static const CGFloat ValueLineMargin = 1.5; +static const CGFloat GraphHeight = 150.0; + + +@implementation ORKAudioGraphView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setUpConstraints]; + +#if TARGET_IPHONE_SIMULATOR + _values = @[ @(0.2), @(0.6), @(0.55), @(0.1), @(0.75), @(0.7) ]; +#endif + } + return self; +} + +- (void)setUpConstraints { + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:GraphHeight]; + heightConstraint.priority = UILayoutPriorityFittingSizeLevel; + + [NSLayoutConstraint activateConstraints:@[heightConstraint]]; +} + +- (void)setValues:(NSArray *)values { + _values = [values copy]; + [self setNeedsDisplay]; +} + +- (void)setKeyColor:(UIColor *)keyColor { + _keyColor = [keyColor copy]; + [self setNeedsDisplay]; +} + +- (void)setAlertColor:(UIColor *)alertColor { + _alertColor = [alertColor copy]; + [self setNeedsDisplay]; +} + +- (void)setAlertThreshold:(CGFloat)alertThreshold { + _alertThreshold = alertThreshold; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGRect bounds = self.bounds; + + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetFillColorWithColor(context, ORKNeedWideScreenDesign(self) ? ORKColor(ORKiPadBackgroundViewColorKey).CGColor : ORKColor(ORKBackgroundColorKey).CGColor); + CGContextFillRect(context, bounds); + + CGFloat scale = self.window.screen.scale; + + CGFloat midY = CGRectGetMidY(bounds); + CGFloat maxX = CGRectGetMaxX(bounds); + CGFloat halfHeight = bounds.size.height / 2; + CGContextSaveGState(context); + { + UIBezierPath *centerLine = [UIBezierPath new]; + [centerLine moveToPoint:(CGPoint){.x = 0, .y = midY}]; + [centerLine addLineToPoint:(CGPoint){.x = maxX, .y = midY}]; + + CGContextSetLineWidth(context, 1.0 / scale); + [_keyColor setStroke]; + CGFloat lengths[2] = {3, 3}; + CGContextSetLineDash(context, 0, lengths, 2); + + [centerLine stroke]; + } + CGContextRestoreGState(context); + + CGFloat lineStep = ValueLineMargin + ValueLineWidth; + + CGContextSaveGState(context); + { + CGFloat x = maxX - lineStep / 2; + CGContextSetLineWidth(context, ValueLineWidth); + CGContextSetLineCap(context, kCGLineCapRound); + + UIBezierPath *path1 = [UIBezierPath new]; + path1.lineCapStyle = kCGLineCapRound; + path1.lineWidth = ValueLineWidth; + UIBezierPath *path2 = [path1 copy]; + + for (NSNumber *value in [_values reverseObjectEnumerator]) { + CGFloat floatValue = value.doubleValue; + + UIBezierPath *path = nil; + if (floatValue > _alertThreshold) { + path = path1; + [_alertColor setStroke]; + } else { + path = path2; + [_keyColor setStroke]; + } + [path moveToPoint:(CGPoint){.x = x, .y = midY - floatValue*halfHeight}]; + [path addLineToPoint:(CGPoint){.x = x, .y = midY + floatValue*halfHeight}]; + + x -= lineStep; + + if (x < 0) { + break; + } + + } + + [_alertColor setStroke]; + [path1 stroke]; + + [_keyColor setStroke]; + [path2 stroke]; + + } + CGContextRestoreGState(context); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.h new file mode 100755 index 0000000..0ec65ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.h @@ -0,0 +1,77 @@ +/* + Copyright (c) 2016, Sage Bionetworks + Copyright (c) 2016, Apple Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKAudioLevelNavigationRule : ORKStepNavigationRule + +/* + The `init` and `new` methods are unavailable. + + `ORKStepNavigationRule` classes should be initialized with custom designated initializers on each + subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized direct-step navigation rule using the specified destination step identifier. + + @param audioLevelStepIdentifier The identifier of the step with the audio file to check. + @param destinationStepIdentifier The identifier of the destination step if audio test passes. + @param recordingSettings Use key AVNumberOfChannelsKey to sepcify the number of recording channels. + @return A audio level step navigation rule. + */ +- (instancetype)initWithAudioLevelStepIdentifier:(NSString *)audioLevelStepIdentifier + destinationStepIdentifier:(NSString *)destinationStepIdentifier + recordingSettings:(NSDictionary *)recordingSettings NS_DESIGNATED_INITIALIZER; + +/** + Returns a new direct-step navigation rule initialized from data in a given unarchiver. + + @param aDecoder The coder from which to initialize the step navigation rule. + + @return A new direct-step navigation rule. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, copy, readonly) NSString *audioLevelStepIdentifier; +@property (nonatomic, copy, readonly) NSString *destinationStepIdentifier; +@property (nonatomic, copy, readonly) NSDictionary *recordingSettings; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.m new file mode 100755 index 0000000..5b169fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioLevelNavigationRule.m @@ -0,0 +1,218 @@ +/* + Copyright (c) 2016, Sage Bionetworks + Copyright (c) 2016, Apple Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioLevelNavigationRule.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKFileResult.h" +#import "ORKResultPredicate.h" +#import "ORKStepNavigationRule_Internal.h" + +#import "ORKHelpers_Internal.h" + +#import + + +Float32 const VolumeThreshold = 0.45; +UInt16 const LinearPCMBitDepth = 16; +Float32 const MaxAmplitude = 32767.0; +Float32 const VolumeClamp = 60.0; + + +@interface ORKAudioLevelNavigationRule () + +@property (nonatomic, copy, readwrite) NSString *audioLevelStepIdentifier; +@property (nonatomic, copy, readwrite) NSString *destinationStepIdentifier; +@property (nonatomic, copy, readwrite) NSDictionary *recordingSettings; + +@end + + +@implementation ORKAudioLevelNavigationRule + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithAudioLevelStepIdentifier:(NSString *)audioLevelStepIdentifier + destinationStepIdentifier:(NSString *)destinationStepIdentifier + recordingSettings:(NSDictionary *)recordingSettings +{ + ORKThrowInvalidArgumentExceptionIfNil(audioLevelStepIdentifier); + ORKThrowInvalidArgumentExceptionIfNil(destinationStepIdentifier); + ORKThrowInvalidArgumentExceptionIfNil(recordingSettings); + self = [super init]; + if (self) { + _audioLevelStepIdentifier = [audioLevelStepIdentifier copy]; + _destinationStepIdentifier = [destinationStepIdentifier copy]; + _recordingSettings = [recordingSettings copy]; + } + return self; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, audioLevelStepIdentifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, destinationStepIdentifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, recordingSettings, NSDictionary); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, audioLevelStepIdentifier); + ORK_ENCODE_OBJ(aCoder, destinationStepIdentifier); + ORK_ENCODE_OBJ(aCoder, recordingSettings); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + typeof(self) rule = [[[self class] allocWithZone:zone] initWithAudioLevelStepIdentifier:self.audioLevelStepIdentifier destinationStepIdentifier:self.destinationStepIdentifier recordingSettings:self.recordingSettings]; + return rule; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.audioLevelStepIdentifier, castObject.audioLevelStepIdentifier) + && ORKEqualObjects(self.destinationStepIdentifier, castObject.destinationStepIdentifier) + && ORKEqualObjects(self.recordingSettings, castObject.recordingSettings)); +} + +- (NSUInteger)hash { + return _audioLevelStepIdentifier.hash ^ _destinationStepIdentifier.hash ^ _recordingSettings.hash; +} + +#pragma mark - Required overrides + +- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult { + + // Get the result file + ORKStepResult *stepResult = (ORKStepResult *)[taskResult resultForIdentifier:self.audioLevelStepIdentifier]; + ORKFileResult *audioLevelResult = (ORKFileResult *)[stepResult.results firstObject]; + + // Check the volume + if ((audioLevelResult.fileURL != nil) && [self checkAudioLevelFromSoundFile:audioLevelResult.fileURL]) { + // Returning nil will drop through to the next step (which should be the the step that has the instructions + // for moving to a quieter room). + return nil; + } + + return self.destinationStepIdentifier; +} + +- (BOOL)checkAudioLevelFromSoundFile:(NSURL *)fileURL { + // Setup reader + AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; + if (urlAsset.tracks.count == 0) { + ORK_Log_Info("No tracks found for urlAsset: %@", fileURL); + return NO; + } + + NSError *error = nil; + AVAssetReader *reader = [[AVAssetReader alloc] initWithAsset:urlAsset error:&error]; + AVAssetTrack *track = [urlAsset.tracks objectAtIndex:0]; + NSDictionary *outputSettings = @{AVFormatIDKey: @(kAudioFormatLinearPCM), + AVLinearPCMBitDepthKey: @(LinearPCMBitDepth), + AVLinearPCMIsBigEndianKey: @(NO), + AVLinearPCMIsFloatKey: @(NO), + AVLinearPCMIsNonInterleaved: @(NO)}; + AVAssetReaderTrackOutput *output = [[AVAssetReaderTrackOutput alloc] initWithTrack:track outputSettings:outputSettings]; + [reader addOutput:output]; + + // Setup initial values - Assume 2 channels if not in recording settings + const UInt32 channelCount = (UInt32)[self.recordingSettings[AVNumberOfChannelsKey] unsignedIntegerValue] ? : 2; + const UInt32 bytesPerSample = 2 * channelCount; + + // setup criteria block - Use a high-pass filter and a rolling average of the amplitude + // normalized to be < 1 + __block Float32 rollingAvg = 0; + __block UInt64 totalCount = 0; + void (^processVolume)(Float32) = ^(Float32 amplitude) { + if (amplitude != 0) { + Float32 dB = 20 * log10(ABS(amplitude) / MaxAmplitude); + float clampedValue = MAX(dB / VolumeClamp, -1) + 1; + totalCount++; + rollingAvg = (rollingAvg * (totalCount - 1) + clampedValue) / totalCount; + } + }; + + // While there are samples to read and the number of samples above the decibel threshold + // is less than the total number of allowed samples over the limit, keep going + [reader startReading]; + while (reader.status == AVAssetReaderStatusReading) { + + AVAssetReaderTrackOutput *trackOutput = (AVAssetReaderTrackOutput *)[reader.outputs objectAtIndex:0]; + CMSampleBufferRef sampleBufferRef = [trackOutput copyNextSampleBuffer]; + + if (sampleBufferRef) { + CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBufferRef); + size_t length = CMBlockBufferGetDataLength(blockBufferRef); + + NSMutableData *data = [NSMutableData dataWithLength:length]; + CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, data.mutableBytes); + + SInt16 *samples = (SInt16 *) data.mutableBytes; + UInt64 sampleCount = length / bytesPerSample; + for (UInt32 i = 0; i < sampleCount ; i++) { + Float32 left = (Float32) *samples++; + processVolume(left); + if (channelCount == 2) { + Float32 right = (Float32) *samples++; + processVolume(right); + } + } + + CMSampleBufferInvalidate(sampleBufferRef); + CFRelease(sampleBufferRef); + } + } + + return rollingAvg > VolumeThreshold; +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.h new file mode 100755 index 0000000..90e6239 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.h @@ -0,0 +1,90 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import AVFoundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The ORKAudioRecorder class represents a recorder that uses the app's + `AVAudioSession` object to record audio. + + To ensure audio recording continues when a task enters the background, + add the `audio` tag to `UIBackgroundModes` in your app's `Info.plist` file. + */ +ORK_CLASS_AVAILABLE +@interface ORKAudioRecorder : ORKRecorder + +/** + The default audio format settings. + + If no settings are specified, the audio configuration is + MPEG4 AAC, 2 channels, 16 bit, 44.1 kHz, AVAudioQualityMin. + */ ++ (NSDictionary *)defaultRecorderSettings; + +/** + Audio format settings + + Settings for the recording session. + Passed to AVAudioRecorder`'s `-initWithURL:settings:error:` + For information on the settings available for an audio recorder, see "AV Foundation Audio Settings Constants". + */ +@property (nonatomic, copy, readonly) NSDictionary *recorderSettings; + +/** + Returns an initialized audio recorder using the specified settings, step, and output directory. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param recorderSettings The settings for the recording session. + @param step The step that requested this recorder. + @param outputDirectory The directory in which the audio output should be stored. + + @return An initialized audio recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + recorderSettings:(nullable NSDictionary *)recorderSettings + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + +/** + Reference to the audio recorder being used. + + The value of this property is used in the audio task in order to display recorded volume in real time during the task. + */ +@property (nonatomic, strong, readonly, nullable) AVAudioRecorder *audioRecorder; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.m new file mode 100755 index 0000000..c13c631 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioRecorder.m @@ -0,0 +1,341 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioRecorder.h" + +#import "ORKRecorder_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKAudioRecorder () + +@property (nonatomic, strong) AVAudioRecorder *audioRecorder; + +@property (nonatomic, copy) NSDictionary *recorderSettings; + +@property (nonatomic, copy) NSString *savedSessionCategory; + +@end + + +@implementation ORKAudioRecorder + +- (void)dealloc { + ORK_Log_Debug("Remove audiorecorder %p", self); + [_audioRecorder stop]; + _audioRecorder = nil; +} + ++ (NSDictionary *)defaultRecorderSettings { + return @{AVFormatIDKey : @(kAudioFormatMPEG4AAC), + AVEncoderAudioQualityKey : @(AVAudioQualityMin), + AVNumberOfChannelsKey : @(2), + AVSampleRateKey : @(44100.0)}; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + recorderSettings:(NSDictionary *)recorderSettings + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier step:step outputDirectory:outputDirectory]; + if (self) { + + self.continuesInBackground = YES; + if (!recorderSettings) { + recorderSettings = [[self class] defaultRecorderSettings]; + } + if (![recorderSettings isKindOfClass:[NSDictionary class]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"recorderSettings should be a dictionary" userInfo:recorderSettings]; + } + self.recorderSettings = recorderSettings; + } + return self; +} + +- (void)restoreSavedAudioSessionCategory { + if (_savedSessionCategory) { + NSError *error; + if (![[AVAudioSession sharedInstance] setCategory:_savedSessionCategory error:&error]) { + ORK_Log_Error("Failed to restore the audio session category: %@", [error localizedDescription]); + } + _savedSessionCategory = nil; + } +} + +- (void)start { + if (self.outputDirectory == nil) { + @throw [NSException exceptionWithName:NSDestinationInvalidException reason:@"audioRecorder requires an output directory" userInfo:nil]; + } + // Only create the file when we should actually start recording. + if (!_audioRecorder) { + + NSError *error = nil; + NSURL *soundFileURL = [self recordingFileURL]; + if (![self recreateFileWithError:&error]) { + [self finishRecordingWithError:error]; + return; + } + + + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + _savedSessionCategory = audioSession.category; + if (![audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]) { + [self finishRecordingWithError:error]; + return; + } + + ORK_Log_Debug("Create audioRecorder %p", self); + _audioRecorder = [[AVAudioRecorder alloc] + initWithURL:soundFileURL + settings:self.recorderSettings + error:&error]; + if (!_audioRecorder) { + [self finishRecordingWithError:error]; + return; + } + +#if !TARGET_IPHONE_SIMULATOR + if (!_audioRecorder.recording) { + [_audioRecorder prepareToRecord]; + } +#endif + } + +#if !TARGET_IPHONE_SIMULATOR + if (!_audioRecorder.recording) { + [_audioRecorder prepareToRecord]; + [_audioRecorder record]; + } +#endif + [super start]; + +} + +- (void)stop { + if (!_audioRecorder) { + // Error has already been returned. + return; + } + + [self doStopRecording]; + + NSURL *fileUrl = [self recordingFileURL]; + if (![[NSFileManager defaultManager] fileExistsAtPath:[[self recordingFileURL] path]]) { + fileUrl = nil; + } + + [self reportFileResultWithFile:fileUrl error:nil]; + + [super stop]; +} + +- (BOOL)isRecording { + return _audioRecorder.recording; +} + +- (NSString *)mimeType { + NSDictionary *recorderSettings = [self recorderSettings]; + unsigned int recorderFormat = ((NSNumber *)recorderSettings[AVFormatIDKey]).unsignedIntValue; + + NSString *contentType = @"audio"; + switch (recorderFormat) { + case kAudioFormatLinearPCM: { + int numBits = ((NSNumber *)recorderSettings[AVLinearPCMBitDepthKey]).intValue ? : 16; + contentType = [NSString stringWithFormat:@"audio/L%d", numBits]; + break; + } + case kAudioFormatAC3: { + contentType = @"audio/ac3"; + break; + } + case kAudioFormatMPEG4AAC: + case kAudioFormatMPEG4CELP: + case kAudioFormatMPEG4HVXC: + case kAudioFormatMPEG4TwinVQ: + case kAudioFormatAppleLossless: { + contentType = @"audio/m4a"; + break; + } + case kAudioFormatULaw: { + contentType = @"audio/basic"; + break; + } + } + return contentType; +} + +- (NSString *)recorderType { + return @"audio"; +} + +- (void)doStopRecording { + if (self.isRecording) { +#if !TARGET_IPHONE_SIMULATOR + [_audioRecorder stop]; + + [self applyFileProtection:ORKFileProtectionComplete toFileAtURL:[self recordingFileURL]]; +#endif + [self restoreSavedAudioSessionCategory]; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + + [super finishRecordingWithError:error]; +} + +- (NSString *)extension { + NSDictionary *recorderSettings = [self recorderSettings]; + unsigned int recorderFormat = ((NSNumber *)recorderSettings[AVFormatIDKey]).unsignedIntValue; + + NSString *extension = @"au"; + switch (recorderFormat) { + case kAudioFormatLinearPCM: + { + extension = @"pcm"; + break; + } + case kAudioFormatAC3: { + extension = @"ac3"; + break; + } + case kAudioFormatMPEG4AAC: + case kAudioFormatMPEG4CELP: + case kAudioFormatMPEG4HVXC: + case kAudioFormatMPEG4TwinVQ: + case kAudioFormatAppleLossless: { + extension = @"m4a"; + break; + } + } + return extension; +} + +- (NSURL *)recordingFileURL { + return [[self recordingDirectoryURL] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self logName], [self extension]]]; +} + +- (BOOL)recreateFileWithError:(NSError **)errorOut { + NSURL *url = [self recordingFileURL]; + if (!url) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteInvalidFileNameError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"ERROR_RECORDER_NO_OUTPUT_DIRECTORY", nil)}]; + } + return NO; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (![fileManager createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:errorOut]) { + return NO; + } + + if ([fileManager fileExistsAtPath:[url path]]) { + if (![fileManager removeItemAtPath:[url path] error:errorOut]) { + return NO; + } + } + + [fileManager createFileAtPath:[url path] contents:nil attributes:nil]; + [fileManager setAttributes:@{NSFileProtectionKey: ORKFileProtectionFromMode(ORKFileProtectionCompleteUnlessOpen)} ofItemAtPath:[url path] error:errorOut]; + return YES; +} + +- (void)reset { + [_audioRecorder stop]; + _audioRecorder = nil; + [super reset]; +} + +@end + + +@implementation ORKAudioRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithIdentifier:(NSString *)identifier { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use subclass designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + recorderSettings:(NSDictionary *)recorderSettings { + self = [super initWithIdentifier:identifier]; + if (self) { + if (recorderSettings && ![recorderSettings isKindOfClass:[NSDictionary class]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"recorderSettings should be a dictionary" userInfo:recorderSettings]; + } + _recorderSettings = recorderSettings; + } + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + return [[ORKAudioRecorder alloc] initWithIdentifier:self.identifier + recorderSettings:self.recorderSettings + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, recorderSettings, NSDictionary); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, recorderSettings); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.recorderSettings, castObject.recorderSettings)); +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionAudioRecording; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.h new file mode 100755 index 0000000..5d3f98f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKAudioStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.m new file mode 100755 index 0000000..6d81e79 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStep.m @@ -0,0 +1,70 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioStep.h" + +#import "ORKAudioStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKAudioStep + ++ (Class)stepViewControllerClass { + return [ORKAudioStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldStartTimerAutomatically = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSTimeInterval const ORKAudioTaskMinimumDuration = 5.0; + + if ( self.stepDuration < ORKAudioTaskMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKAudioTaskMinimumDuration)] userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.h new file mode 100755 index 0000000..30eff12 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKAudioStepViewController : ORKActiveStepViewController + +@property (nonatomic, assign) CGFloat alertThreshold; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.m new file mode 100755 index 0000000..6aeb8a3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKAudioStepViewController.m @@ -0,0 +1,191 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAudioStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKAudioContentView.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKVerticalContainerView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKAudioRecorder.h" + +#import "ORKAudioStep.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + +@import AVFoundation; + + +@interface ORKAudioStepViewController () + +@property (nonatomic, strong) AVAudioRecorder *avAudioRecorder; + +@end + + +@implementation ORKAudioStepViewController { + ORKAudioContentView *_audioContentView; + ORKAudioRecorder *_audioRecorder; + ORKActiveStepTimer *_timer; + NSError *_audioRecorderError; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + // Continue audio recording in the background + self.suspendIfInactive = NO; + } + return self; +} + +- (void)setAlertThreshold:(CGFloat)alertThreshold { + _alertThreshold = alertThreshold; + if (self.isViewLoaded && alertThreshold > 0) { + _audioContentView.alertThreshold = alertThreshold; + } +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + _audioContentView = [ORKAudioContentView new]; + _audioContentView.timeLeft = self.audioStep.stepDuration; + + if (self.alertThreshold > 0) { + _audioContentView.alertThreshold = self.alertThreshold; + } + + self.activeStepView.activeCustomView = _audioContentView; +} + +- (void)audioRecorderDidChange { + _audioRecorder.audioRecorder.meteringEnabled = YES; + [self setAvAudioRecorder:_audioRecorder.audioRecorder]; +} + +- (void)recordersDidChange { + ORKAudioRecorder *audioRecorder = nil; + for (ORKRecorder *recorder in self.recorders) { + if ([recorder isKindOfClass:[ORKAudioRecorder class]]) { + audioRecorder = (ORKAudioRecorder *)recorder; + break; + } + } + _audioRecorder = audioRecorder; + [self audioRecorderDidChange]; +} + +- (ORKAudioStep *)audioStep { + return (ORKAudioStep *)self.step; +} + +- (void)doSample { + if (_audioRecorderError) { + return; + } + [_avAudioRecorder updateMeters]; + float value = [_avAudioRecorder averagePowerForChannel:0]; + // Assume value is in range roughly -60dB to 0dB + float clampedValue = MAX(value / 60.0, -1) + 1; + [_audioContentView addSample:@(clampedValue)]; + _audioContentView.timeLeft = [_timer duration] - [_timer runtime]; +} + +- (void)startNewTimerIfNeeded { + if (!_timer) { + NSTimeInterval duration = self.audioStep.stepDuration; + ORKWeakTypeOf(self) weakSelf = self; + _timer = [[ORKActiveStepTimer alloc] initWithDuration:duration interval:duration / 100 runtime:0 handler:^(ORKActiveStepTimer *timer, BOOL finished) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf doSample]; + if (finished) { + [strongSelf finish]; + } + }]; + [_timer resume]; + } + _audioContentView.finished = NO; +} + +- (void)start { + [super start]; + [self audioRecorderDidChange]; + [_timer reset]; + _timer = nil; + [self startNewTimerIfNeeded]; + +} + +- (void)suspend { + [super suspend]; + [_timer pause]; + if (_avAudioRecorder) { + [_audioContentView addSample:@(0)]; + } +} + +- (void)resume { + [super resume]; + [self audioRecorderDidChange]; + [self startNewTimerIfNeeded]; + [_timer resume]; +} + +- (void)finish { + if (_audioRecorderError) { + return; + } + [super finish]; + [_timer reset]; + _timer = nil; +} + +- (void)stepDidFinish { + _audioContentView.finished = YES; +} + +- (void)setAvAudioRecorder:(AVAudioRecorder *)recorder { + _avAudioRecorder = nil; + _avAudioRecorder = recorder; +} + +- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + [super recorder:recorder didFailWithError:error]; + _audioRecorderError = error; + _audioContentView.failed = YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.h new file mode 100755 index 0000000..1410a44 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKCountdownStep` class represents a step that displays a label and a + countdown for a time equal to its duration. + + To use the countdown step, set the `duration` property, incorporate it into a + task, and present the task with a task view controller. + + The countdown step is used in most of ResearchKit's predefined active tasks. + */ +ORK_CLASS_AVAILABLE +@interface ORKCountdownStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.m new file mode 100755 index 0000000..f47046e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStep.m @@ -0,0 +1,66 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCountdownStep.h" + +#import "ORKCountdownStepViewController.h" + + +@implementation ORKCountdownStep + ++ (Class)stepViewControllerClass { + return [ORKCountdownStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldStartTimerAutomatically = YES; + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + self.stepDuration = 5.0; + } + return self; +} + +- (void)validateParameters { + + [super validateParameters]; + + NSTimeInterval const ORKCountdownStepMinimumDuration = 3.0; + + if ( self.stepDuration < ORKCountdownStepMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKCountdownStepMinimumDuration)] userInfo:nil]; + } + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.h new file mode 100755 index 0000000..0cc20ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKCountdownStepViewController` class represents the step view controller that corresponds to an `ORKCountdownStep`. + + It is not usually necessary to instantiate this view controller directly. + Instead, add a countdown step to a task, and present the task in a task + view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKCountdownStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.m new file mode 100755 index 0000000..331bfe7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKCountdownStepViewController.m @@ -0,0 +1,274 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCountdownStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKLabel.h" +#import "ORKSubheadlineLabel.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKActiveStep.h" +#import "ORKResult.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" + + +@interface ORKCountDownViewLabel : ORKLabel + +@end + + +@implementation ORKCountDownViewLabel ++ (UIFont *)defaultFont { + return ORKThinFontWithSize(56); +} +@end + + +@interface ORKCountdownView : ORKActiveStepCustomView + +@property (nonatomic, strong) ORKSubheadlineLabel *textLabel; +@property (nonatomic, strong) ORKCountDownViewLabel *timeLabel; +@property (nonatomic, strong) UIView *progressView; + +- (void)startAnimateWithDuration:(NSTimeInterval)duration; + +@end + + +@implementation ORKCountdownView { + CAShapeLayer *_circleLayer; +} + +static const CGFloat ProgressIndicatorDiameter = 104.0; +static const CGFloat ProgressIndicatorOuterMargin = 1.0; + +- (instancetype)init { + self = [super init]; + if (self) { + _textLabel = [ORKSubheadlineLabel new]; + _textLabel.textAlignment = NSTextAlignmentCenter; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.text = ORKLocalizedString(@"COUNTDOWN_LABEL", nil); + _textLabel.adjustsFontSizeToFitWidth = YES; + [self addSubview:_textLabel]; + + _timeLabel = [ORKCountDownViewLabel new]; + _timeLabel.translatesAutoresizingMaskIntoConstraints = NO; + _timeLabel.textAlignment = NSTextAlignmentCenter; + [self addSubview:_timeLabel]; + + _progressView = [UIView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_progressView]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + + _circleLayer = [CAShapeLayer layer]; + static const CGFloat ProgressIndicatorRadius = ProgressIndicatorDiameter / 2; + _circleLayer.path = [[UIBezierPath bezierPathWithArcCenter:CGPointMake(ProgressIndicatorRadius + ProgressIndicatorOuterMargin, ProgressIndicatorRadius + ProgressIndicatorOuterMargin) + radius:ProgressIndicatorRadius + startAngle:M_PI + M_PI_2 + endAngle:-M_PI_2 + clockwise:NO] CGPath]; + _circleLayer.fillColor = [UIColor clearColor].CGColor; + _circleLayer.strokeColor = self.tintColor.CGColor; + _circleLayer.lineWidth = 1; + + [_progressView.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + [_progressView.layer addSublayer:_circleLayer]; + + _textLabel.isAccessibilityElement = NO; + _timeLabel.isAccessibilityElement = NO; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *metrics = @{@"d": @(ProgressIndicatorDiameter + 2 * ProgressIndicatorOuterMargin)}; + NSDictionary *views = NSDictionaryOfVariableBindings(_textLabel, _timeLabel, _progressView); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_textLabel]-(>=0)-[_progressView(==d)]|" + options:NSLayoutFormatDirectionLeadingToTrailing | NSLayoutFormatAlignAllCenterX + metrics:metrics + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[_textLabel]-(>=0)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:metrics + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[_progressView(==d)]-(>=0)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:metrics + views:views]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_timeLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_progressView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + // Constant required in order to give appearance of vertical centering (compensating for leading on font) + [constraints addObject:[NSLayoutConstraint constraintWithItem:_timeLabel + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_progressView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:-3.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_textLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:16.0 - ProgressIndicatorOuterMargin]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)tintColorDidChange { + _circleLayer.strokeColor = self.tintColor.CGColor; +} + +- (void)startAnimateWithDuration:(NSTimeInterval)duration { + CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"]; + animation.duration = duration * 2; + animation.removedOnCompletion = YES; + animation.values = @[ @(1.0), @(0.0), @(0.0) ]; + animation.keyTimes = @[ @(0.0), @(0.5), @(1.0) ]; + animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; + [_circleLayer addAnimation:animation forKey:@"drawCircleAnimation"]; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + return ORKAccessibilityStringForVariables(_textLabel.accessibilityLabel, _timeLabel.accessibilityLabel); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitUpdatesFrequently; +} + +@end + + +@interface ORKCountdownStepViewController () + +@property (nonatomic, strong) ORKCountdownView *countdownView; + +@end + + +@implementation ORKCountdownStepViewController { + NSInteger _countDown; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = NO; + } + return self; +} + +- (void)setStep:(ORKStep *)step { + [super setStep:step]; + _countDown = round([(ORKActiveStep *)step stepDuration]); +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.learnMoreButtonItem = nil; + + _countdownView = [[ORKCountdownView alloc] init]; + _countdownView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _countdownView; + [self updateCountdownLabel]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @(_countDown).stringValue); + [_countdownView startAnimateWithDuration:[(ORKActiveStep *)self.step stepDuration]]; +} + +- (void)updateCountdownLabel { + _countdownView.timeLabel.text = ORKLocalizedStringFromNumber(@(_countDown)); +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + _countDown = MAX((_countDown - 1), 0); + [self updateCountdownLabel]; + + if (UIAccessibilityIsVoiceOverRunning()) { + if (finished) { + [[NSNotificationCenter defaultCenter] addObserverForName:UIAccessibilityAnnouncementDidFinishNotification + object:nil + queue:nil + usingBlock:^(NSNotification *note) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityAnnouncementDidFinishNotification object:nil]; + [super countDownTimerFired:timer finished:finished]; + }]; + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, ORKLocalizedString(@"AX_ANNOUNCE_BEGIN_TASK", nil)); + } else { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, @(_countDown).stringValue); + [super countDownTimerFired:timer finished:finished]; + } + } else { + [super countDownTimerFired:timer finished:finished]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.h new file mode 100755 index 0000000..09d4992 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.h @@ -0,0 +1,582 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKDataLogger; +@class HKUnit; + +/** + The `ORKDataLoggerDelegate` protocol defines methods that the delegate of an `ORKDataLogger` object uses to handle data being logged to disk. + */ +@protocol ORKDataLoggerDelegate + +/** + Tells the delegate when a log file rollover occurs. + + @param dataLogger The data logger providing the notification. + @param fileUrl The URL of the newly renamed log file. + */ +- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl; + +@optional +/** + Tells the delegate if the number of bytes in completed logs changes. + + When files are removed or added, or marked as uploaded or unmarked, this delegate method is called a short time later. Multiple directory changes + are rolled up into a single delegate callback. + + @param dataLogger The data logger providing the notification. + */ +- (void)dataLoggerByteCountsDidChange:(ORKDataLogger *)dataLogger; + +@end + + +@protocol ORKDataLoggerExtendedDelegate + +@optional +/** + Tells the delegate that the maximum current log file lifetime changed. + @param dataLogger Source of this event. + */ +- (void)dataLoggerThresholdsDidChange:(ORKDataLogger *)dataLogger; + +@end + + +@class ORKLogFormatter; + +/** + The `ORKDataLogger` class is an internal component used by some `ORKRecorder` + subclasses for writing data to disk during tasks. An `ORKDataLogger` object manages one log as a set of files in a directory. + + The current log file is at `directory/logName`. + Historic log files are at `directory/logName-(timestamp)-(count)` + where timestamp is of the form `YYYYMMddHHmmss` (Zulu) and indicates the time + the log finished (that is, was rolled over). If more than one rollover occurs within + one second, additional log files may be created with increasing `count`. + + The user is responsible for managing the historic log files, but the `ORKDataLogger` class + provides tools for enumerating them (in sorted order). + + The data logger contains a concept of whether a file has been uploaded, which + is tracked using file attributes. This feature can facilitate a workflow in which + log files are archived and queued for upload before actually sending them to + a server. When archived and ready for upload, the files could be marked uploaded + by the `ORKDataLogger`. When the upload is complete and the data has been handed + off downstream, the files can then be deleted. If the upload fails, the uploaded + files can have that flag cleared, to indicate that they should be included + in the next archiving attempt. + */ +ORK_CLASS_AVAILABLE +@interface ORKDataLogger : NSObject + +/** + Returns a data logger with an `ORKJSONLogFormatter`. + + @param url The URL of the directory in which to place log files. + @param logName The prefix on the log file name in an ASCII string. Note that the string must not contain the hyphen character ("-"), because a hyphen is used as a separator in the log naming scheme. + @param delegate The initial delegate. May be `nil`. + */ ++ (ORKDataLogger *)JSONDataLoggerWithDirectory:(NSURL *)url logName:(NSString *)logName delegate:(nullable id)delegate; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized data logger using the specified URL, log name, formatter, and delegate. + + @param url The URL of the directory in which to place log files + @param logName The prefix on the log file name in an ASCII string. Note that + the string must not contain the hyphen character ("-"), because a hyphen is used as a separator in the log naming scheme. + @param formatter The type of formatter to use for the log, such as `ORKJSONLogFormatter`. + @param delegate The initial delegate. May be `nil`. + + @return An initialized data logger. + */ +- (instancetype)initWithDirectory:(NSURL *)url logName:(NSString *)logName formatter:(ORKLogFormatter *)formatter delegate:(nullable id)delegate NS_DESIGNATED_INITIALIZER; + +/// The delegate to be notified when file sizes change or the log rolls over. +@property (weak, nullable) id delegate; + +/// The log formatter being used. +@property (strong, readonly) ORKLogFormatter *logFormatter; + +/** + The maximum current log file size. + + When the current log reaches this size, it is automatically rolled over. + */ +@property size_t maximumCurrentLogFileSize; + +/** + The maximum current log file lifetime. + + When the current log file has been active this long, it is rolled over. + */ +@property NSTimeInterval maximumCurrentLogFileLifetime; + +/// The number of bytes of log data that are not marked uploaded, excluding the current file. This value is lazily updated. +@property unsigned long long pendingBytes; + +/// The number of bytes of log data that are marked uploaded. This value is lazily updated. +@property unsigned long long uploadedBytes; + +/// The file protection mode to use for newly created files. +@property (assign) ORKFileProtectionMode fileProtectionMode; + +/// The prefix on the log file names. +@property (copy, readonly) NSString *logName; + +/// Forces a roll-over now. +- (void)finishCurrentLog; + +/// The current log file's location. +- (NSURL *)currentLogFileURL; + +/** + Enumerates the URLs of completed log files, sorted to put the oldest first. + + Takes a snapshot of the current directory's relevant files, sorts them, + and enumerates them. Errors can occur if changes are being made to the filesystem other + than through this object. + + @param block The block to call during enumeration. + @param error Any error detected during the enumeration. + + @return `YES` if the enumeration was successful; otherwise, `NO`. + */ +- (BOOL)enumerateLogs:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError * _Nullable *)error; + +/** + Enumerates the URLs of completed log files not yet marked uploaded, + sorted to put the oldest first. + + This method takes a snapshot of the current directory's completed nonuploaded log files, sorts them, + and then enumerates them. Errors can occur if changes are being made to the filesystem other + than through this object. + + @param block The block to call during enumeration. + @param error Any error detected during the enumeration. + + @return `YES` if the enumeration was successful; otherwise, `NO`. + */ +- (BOOL)enumerateLogsNeedingUpload:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError * _Nullable *)error; + +/** + Enumerates the URLs of completed log files not already marked uploaded, + sorted to put the oldest first. + + Takes a snapshot of the current directory's completed uploaded log files, sorts them, + and then enumerates them. Errors can occur if changes are being made to the filesystem other + than through this object. + + @param block The block to call during enumeration. + @param error Any error detected during the enumeration. + + @return `YES` if the enumeration was successful; otherwise, `NO`. + */ +- (BOOL)enumerateLogsAlreadyUploaded:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError * _Nullable *)error; + +/** + Appends an object to the log file, which is formatted with `logFormatter`. + + The default log formatter expects NSData; call canAcceptLogObjectOfClass: on `logFormatter` to determine if it will accept this object. + + Note that the current log file is created and opened lazily when a request to + log data is made. If an attempt is made to log data and there is no access due + to file protection, the log is immediately rolled over and a new file created. + + @param object Should be an object of a class that is accepted by the logFormatter. + @param error Error output, if the append fails. + + @return `YES` if appending succeeds; otherwise, `NO`. + */ +- (BOOL)append:(id)object error:(NSError * _Nullable *)error; + +/** + Appends multiple objects to the log file. + + This method formats and appends all the objects at once. Using this method may have efficiency + and atomicity gains for error handling, compared to making multiple calls to `append:error`. + + @param objects An array of objects of a class that is accepted by the logFormatter. + @param error Error output, if the append fails. + + @return `YES` if appending succeeds; otherwise, `NO`. + */ +- (BOOL)appendObjects:(NSArray *)objects error:(NSError * _Nullable *)error; + +/** + Checks whether a file has been marked as uploaded. + + @param url The URL to check. + + @return `YES` if the uploaded attribute has been set on the file and the file exists; otherwise, + `NO`. + */ +- (BOOL)isFileUploadedAtURL:(NSURL *)url; + +/** + Marks or unmarks a file as uploaded. + + This method uses an extended attribute on the filesystem to mark a file as uploaded. + This is intended for book-keeping use only and to track which files have already + been attached to a pending upload. When the upload is sufficiently complete, + the file should be removed. + + @param uploaded A Boolean value that indicates whether to mark the file uploaded or not uploaded. + @param url The URL to mark. + @param error The error that occurred, if the operation fails. + + @return `YES` if adding or removing the attribute succeeded; otherwise, `NO`. + */ +- (BOOL)markFileUploaded:(BOOL)uploaded atURL:(NSURL *)url error:(NSError * _Nullable *)error; + +/** + Removes files if they are marked uploaded. + + If a file is in the list, but is no longer marked uploaded, this method does not remove the file. This workflow lets you unmark files selectively if they could not be added + to the archive, and later call `removeUploadedFiles:withError:` to remove only + the files that are still marked uploaded. + + @param fileURLs The array of files that should be removed. + @param error The error that occurred, if the operation fails. + + @return `YES` if removing the files succeeded; otherwise, `NO`. + */ +- (BOOL)removeUploadedFiles:(NSArray *)fileURLs withError:(NSError * _Nullable *)error; + +/** + Removes all files managed by this logger (files that have the `logName` prefix). + + @param error The error that occurred, if operation fails. + + @return `YES` if removing the files succeeded.; otherwise, `NO`. + */ +- (BOOL)removeAllFilesWithError:(NSError * _Nullable *)error; + +@end + + +/** + The `ORKLogFormatter` class represents the base (default) log formatter, which appends data + blindly to a log file. + + A log formatter is used by a data logger to format objects + for output to the log, and to begin a new log file and end an existing log file. + `ORKLogFormatter` accepts NSData and has neither a header nor a footer. + + A log formatter should ensure that the log is always in a valid state, so that + even if the app is killed, the log is still readable. + */ +@interface ORKLogFormatter : NSObject + +/** + Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object. + + @param c The class of object to serialize. + + @return `YES` if the log formatter can serialize this object class; otherwise, `NO`. + */ +- (BOOL)canAcceptLogObjectOfClass:(Class)c; + +/** + Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object. + + @param object The object to serialize. + + @return `YES` if the log formatter can serialize `object`; otherwise, `NO` + */ +- (BOOL)canAcceptLogObject:(id)object; + +/** + Begins a new log file on the specified file handle. + + For example, may write a header or opening stanza of a new log file. + + @param fileHandle The file handle to which to write. + @param error The error output, on failure. + + @return `YES` if the write succeeds; otherwise, `NO`. + */ +- (BOOL)beginLogWithFileHandle:(NSFileHandle *)fileHandle error:(NSError * _Nullable *)error; + +/** + Appends the specified object to the log file. + + @param object The object to write. + @param fileHandle The file handle to which to write. + @param error The error output, on failure. + + @return `YES` if the write succeeds; otherwise, `NO`. + */ +- (BOOL)appendObject:(id)object fileHandle:(NSFileHandle *)fileHandle error:(NSError * _Nullable *)error; + +/** + Appends the specified objects to the log file. + + @param objects The objects to write. + @param fileHandle The file handle to which to write. + @param error The error output, on failure. + + @return `YES` if the write succeeds; otherwise, `NO`. + */ +- (BOOL)appendObjects:(NSArray *)objects fileHandle:(NSFileHandle *)fileHandle error:(NSError * _Nullable *)error; + +@end + + +/** + The `ORKJSONLogFormatter` class represents a log formatter for producing JSON output. + + The JSON log formatter accepts `NSDictionary` objects for serialization. + The JSON output is a dictionary that contains one key, `items`, + which contains the array of logged items. The log itself does not contain + any timestamp information, so the items should include such fields, + if desired. + */ +ORK_CLASS_AVAILABLE +@interface ORKJSONLogFormatter : ORKLogFormatter + +@end + + +@class ORKJSONDataLogger; +@class ORKDataLoggerManager; + +/** + The `ORKDataLoggerManagerDelegate` protocol defines methods a delegate can implement to receive notifications + when the data loggers managed by a `ORKDataLoggerManager` reach a certain file size threshold. + */ +ORK_CLASS_AVAILABLE +@protocol ORKDataLoggerManagerDelegate + +/** + Called by the data logger manager when the total size of files + that are not marked uploaded has reached a threshold. + + @param dataLoggerManager The manager that produced the notification. + @param pendingUploadBytes The number of bytes managed by all the loggers, which + have not yet been marked uploaded. + */ +- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLoggerManager pendingUploadBytesReachedThreshold:(unsigned long long)pendingUploadBytes; + +/** + Called by the data logger manager when the total size of files + managed by any of the loggers has reached a threshold. + + @param dataLoggerManager The manager that produced the notification. + @param totalBytes The total number of bytes of all files managed. + */ +- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLoggerManager totalBytesReachedThreshold:(unsigned long long)totalBytes; + +@end + + +/** + The `ORKDataLoggerManager` class represents a manager for multiple `ORKDataLogger` instances, + which tracks the total size of log files produced and can notify its delegate + when file sizes reach configurable thresholds. + + The `ORKDataLoggerManager` class is an internal component used by some `ORKRecorder` + subclasses for writing data to disk during tasks. + + This manager can be used to organize the `ORKDataLogger` logs in a directory, + and keep track of the total number of bytes stored on disk by each logger. The + delegate can be informed if either the number of bytes pending upload, or the total + number of bytes, exceeds configurable thresholds. + + The configuration of the loggers and their thresholds is persisted in a + configuration file in the log directory. + + If the number of bytes pending upload exceeds the threshold, the natural action is to + upload them. A block-based enumeration is provided for enumerating all the logs + pending upload. Use `enumerateLogsNeedingUpload:error:`, and when a log has been + processed for upload, use the logger to mark it uploaded. + + When the upload succeeds (or at least is successfully queued), the uploaded files + can be removed across all the loggers by calling `removeUploadedFiles:error:` + + If the total number of bytes exceeds the threshold, the natural action is to remove log + files that have been marked uploaded, and then remove old log files until the + threshold is no longer exceeded. You can do this by calling `removeOldAndUploadedLogsToThreshold:error:` + */ +ORK_CLASS_AVAILABLE +@interface ORKDataLoggerManager : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized data logger manager using the specified directory and delegate. + + Designated initializer. + + @param directory The file URL of the directory where the data loggers should coexist. + @param delegate The delegate to receive notifications. + + @return An initialized data logger manager. + */ +- (instancetype)initWithDirectory:(NSURL *)directory delegate:(nullable id)delegate NS_DESIGNATED_INITIALIZER; + +/// The delegate of the data logger manager. +@property (weak, nullable) id delegate; + +/// The threshold for delegate callback for total bytes not marked uploaded. +@property unsigned long long pendingUploadBytesThreshold; + +/// The threshold for delegate callback for total bytes of completed logs. +@property unsigned long long totalBytesThreshold; + +/// The total number of bytes of files not marked as pending upload. +@property unsigned long long pendingUploadBytes; + +/// The total number of bytes for all the loggers. +@property unsigned long long totalBytes; + +/** + Adds a data logger with a JSON log format to the directory. + + This method throws an exception if a logger already exists with the specified log name. + + @param logName The log name prefix for the data logger. + + @return The `ORKDataLogger` object that was added. + */ +- (ORKDataLogger *)addJSONDataLoggerForLogName:(NSString *)logName; + +/** + Adds a data logger with a particular formatter to the directory. + + @param logName The log name prefix for the data logger. + @param formatter The log formatter instance to use for this logger. + + @return The `ORKDataLogger` object that was added, or the existing one if one already existed for + that log name. + */ +- (ORKDataLogger *)addDataLoggerForLogName:(NSString *)logName formatter:(ORKLogFormatter *)formatter; + +/** + Retrieves the already existing data logger for a log name. + + @param logName The log name prefix for the data logger. + + @return The `ORKDataLogger` object that was retrieved, or `nil` if one already existed for that log name. + */ +- (nullable ORKDataLogger *)dataLoggerForLogName:(NSString *)logName; + +/** + Removes a data logger. + + @param logger The logger to remove. + */ +- (void)removeDataLogger:(ORKDataLogger *)logger; + +/// Returns the set of log names of the data loggers managed by this object. +- (NSArray *)logNames; + +/** + Enumerates all the logs that need upload across all data loggers, sorted from oldest to first. + + Before sorting the logs, this method fetches all the data loggers' logs that need upload. + + @param block The block to call during enumeration. + @param error The error, on failure. + + @return `YES` if the enumeration succeeds; otherwise, `NO`. + */ +- (BOOL)enumerateLogsNeedingUpload:(void (^)(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop))block error:(NSError * _Nullable *)error; + +/** + Unmarks the set of uploaded files. + + Use this method to indicate that the specified files should no longer be marked uploaded (for example, because + the upload did not succeed). + + @param fileURLs The array of file URLs that should no longer be marked uploaded. + @param error The error, on failure. + + @return `YES` if the operation succeeds; otherwise, `NO`. + */ +- (BOOL)unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError * _Nullable *)error; + +/** + Removes a set of uploaded files. + + This method is analogous to a similar method in `ORKDataLogger`, but it accepts an array of files + that may relate to any of the data loggers. It is an error to pass a URL which would not + belong to one of the loggers managed by this manager. + + @param fileURLs The array of file URLs that should be removed. + @param error The error, on failure. + + @return `YES` if the operation succeeds; otherwise, `NO`. + */ +- (BOOL)removeUploadedFiles:(NSArray *)fileURLs error:(NSError * _Nullable *)error; + +/** + Removes old and uploaded logs to bring total bytes down to a threshold. + + This method removes uploaded logs first, followed by the oldest log files across + all of the data loggers, until the total usage falls below a threshold. + + @param bytes The threshold down to which to remove old log files. File removal stops when the total bytes managed by all the data loggers reaches this threshold. + @param error The error, on failure. + + @return `YES` if the operation succeeds; otherwise, `NO`. + */ +- (BOOL)removeOldAndUploadedLogsToThreshold:(unsigned long long)bytes error:(NSError * _Nullable *)error; + +@end + + +@interface ORKDataLogger (Tests) + +/// The file handle to which to write +- (nullable NSFileHandle *)fileHandle; + +@end + + +@interface NSURL (ORKDataLogger) + +- (BOOL)ork_isUploaded; +- (BOOL)ork_setUploaded:(BOOL)uploaded error:(NSError * _Nullable *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.m new file mode 100755 index 0000000..3b02c5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDataLogger.m @@ -0,0 +1,1440 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDataLogger.h" + +#import "ORKHelpers_Internal.h" +#import "CMMotionActivity+ORKJSONDictionary.h" +#import "HKSample+ORKJSONDictionary.h" + +#include + + +static const char *ORKDataLoggerUploadedAttr = "com.apple.ResearchKit.uploaded"; + +// Default per-logfile settings when a data logger is used in an ORKDataLoggerManager +static const NSTimeInterval ORKDataLoggerManagerDefaultLogFileLifetime = 60 * 60 * 24 * 3; // 3 days +static const unsigned long long ORKDataLoggerManagerDefaultLogFileSize = 1024 * 1024; // 1 MB + +static NSString *const ORKDataLoggerManagerConfigurationFilename = @".ORKDataLoggerManagerConfiguration"; + + +@interface ORKDataLogger () + +@property (copy, setter=_setLogName:) NSString *logName; + +@property (strong, setter=_setLogFormatter:) ORKLogFormatter *logFormatter; + +- (void)fileSizeLimitsDidChange; + +- (instancetype)initWithDirectory:(NSURL *)url configuration:(NSDictionary *)configuration delegate:(id)delegate; + +- (NSDictionary *)configuration; + +@end + + +@interface ORKObjectObserver : NSObject + +- (instancetype)initWithObject:(id)object keys:(NSArray *)keys selector:(SEL)selector; + +@property (unsafe_unretained) id object; + +- (void)pause; +- (void)resume; + +@end + + +@implementation NSURL (ORKDataLogger) + +- (NSString *)ork_logName { + NSString *lastComponent = [self lastPathComponent]; + NSRange idx = [lastComponent rangeOfString:@"-"]; + if (!idx.length) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not a completed log file" userInfo:@{@"url":self}]; + } + + NSString *logName = [lastComponent substringToIndex:idx.location]; + return logName; +} + +- (NSString *)ork_logDateComponent { + NSString *lastComponent = [self lastPathComponent]; + NSRange idx = [lastComponent rangeOfString:@"-"]; + if (!idx.length) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not a completed log file" userInfo:@{@"url":self}]; + } + + NSString *logDateComponent = [lastComponent substringFromIndex:idx.location + 1]; + return logDateComponent; +} + +- (BOOL)ork_isUploaded { + NSData *data = [self ork_dataForAttr:ORKDataLoggerUploadedAttr]; + if (!data) { + return NO; + } + + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return (string.integerValue != 0); +} + +- (BOOL)ork_setUploaded:(BOOL)uploaded error:(NSError **)errorOut { + NSString *value = (uploaded ? @"1" : @"0"); + NSData *encodedString = [value dataUsingEncoding:NSUTF8StringEncoding]; + return [self ork_setData:encodedString forAttr:ORKDataLoggerUploadedAttr error:errorOut]; +} + +- (NSData *)ork_dataForAttr:(const char *)attr { + const char *path = [self fileSystemRepresentation]; + + ssize_t length = getxattr(path, attr, NULL, 0, 0, 0); + + if (length < 0) { + return nil; + } + + NSMutableData *data = [NSMutableData dataWithLength:length]; + length = getxattr(path, attr, data.mutableBytes, length, 0, 0); + if (length <= 0) { + return nil; + } + + return data; +} + +- (BOOL)ork_setData:(NSData *)data forAttr:(const char *)attr error:(NSError **)errorOut { + const char *path = [self fileSystemRepresentation]; + int rc = setxattr(path, attr, data.bytes, data.length, 0, 0); + if (rc != 0) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:rc userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"ERROR_DATALOGGER_SET_ATTRIBUTE", nil)}]; + } + } + return (rc == 0); +} + +- (NSString *)ork_logNameInDirectory:(NSURL *)directory { + if (![self isFileURL]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not a fileURL" userInfo:@{@"url":self}]; + } + + NSString *lastComponent = [self lastPathComponent]; + NSRange idx = [lastComponent rangeOfString:@"-"]; + if (!idx.length) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not a completed log file" userInfo:@{@"url":self}]; + } + + if (![[self URLByDeletingLastPathComponent] isEqual:directory]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not in expected directory" userInfo:@{@"url":self}]; + } + + NSString *logName = [lastComponent substringToIndex:idx.location]; + return logName; +} + +@end + + +@implementation ORKObjectObserver { + NSArray *_keys; + BOOL _observing; + SEL _selector; +} + +static void *ORKObjectObserverContext = &ORKObjectObserverContext; + +- (instancetype)initWithObject:(id)object keys:(NSArray *)keys selector:(SEL)selector { + self = [super init]; + if (self) { + self.object = object; + _keys = [keys copy]; + _selector = selector; + [self resume]; + } + return self; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if (context == ORKObjectObserverContext) { + NSObject *obj = self.object; + // Avoid -performSelector: warning by explicitly indicating we have a void return + ((void (*)(id, SEL))[obj methodForSelector:_selector])(obj, _selector); + } +} + +- (void)stopObserving { + [self pause]; +} + +- (void)pause { + if (_observing) { + _observing = NO; + for (NSString *key in _keys) { + [_object removeObserver:self forKeyPath:key]; + } + } +} + +- (void)resume { + if (!_observing) { + for (NSString *key in _keys) { + [_object addObserver:self forKeyPath:key options:(NSKeyValueObservingOptions)0 context:ORKObjectObserverContext]; + } + _observing = YES; + } +} + +- (void)dealloc { + [self stopObserving]; +} + +@end + + +@interface ORKLogFormatter () { + unsigned long long _checkpoint; +} + +@end + + +@implementation ORKLogFormatter + +- (BOOL)canAcceptLogObjectOfClass:(Class)c { + return [c isSubclassOfClass:[NSData class]]; +} + +- (BOOL)canAcceptLogObject:(id)object { + return [object isKindOfClass:[NSData class]]; +} + +- (BOOL)beginLogWithFileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + return YES; +} + +- (BOOL)writeData:(NSData *)data fileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + BOOL result = YES; + @try { + [fileHandle writeData:data]; + } + @catch (NSException *exception) { + result = NO; + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{@"exception": exception}]; + } + } + return result; +} + +- (unsigned long long)checkpointWithFileHandle:(NSFileHandle *)fileHandle { + return [fileHandle offsetInFile]; +} + +- (void)rollbackToCheckpoint:(unsigned long long)offset fileHandle:(NSFileHandle *)fileHandle { + [fileHandle seekToFileOffset:offset]; + [fileHandle truncateFileAtOffset:offset]; +} + +- (BOOL)appendObject:(id)object fileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + if (![self canAcceptLogObject:object]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"ORKLogFormatter accepts NSData only" userInfo:nil]; + } + return [self writeData:(NSData *)object fileHandle:fileHandle error:errorOut]; +} + +- (BOOL)appendObjects:(NSArray *)objects fileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + unsigned long long checkpoint = [self checkpointWithFileHandle:fileHandle]; + + NSError *error = nil; + BOOL success = YES; + for (NSObject *obj in objects) { + success = [self appendObject:obj fileHandle:fileHandle error:&error]; + if (!success) { + break; + } + } + + if (!success) { + [self rollbackToCheckpoint:checkpoint fileHandle:fileHandle]; + if (errorOut != NULL) { + *errorOut = error; + } + } + + return success; +} + +@end + + +static NSString *const kJSONLogEmptyLogString = @"{\"items\":[]}"; +static NSString *const kJSONLogFooterString = @"]}"; // The part of the log string that comes after the logged objects +static NSString *const kJSONObjectSeparatorString = @","; + +static NSInteger _ORKJSON_emptyLogLength = 0; +static NSInteger _ORKJSON_terminatorLength = 0; + +@implementation ORKJSONLogFormatter + +- (instancetype)init { + self = [super init]; + if (self) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _ORKJSON_emptyLogLength = [kJSONLogEmptyLogString dataUsingEncoding:NSUTF8StringEncoding].length; + _ORKJSON_terminatorLength = [kJSONLogFooterString dataUsingEncoding:NSUTF8StringEncoding].length; + }); + } + return self; +} + +- (BOOL)canAcceptLogObjectOfClass:(Class)c { + return [c isSubclassOfClass:[NSDictionary class]]; +} + +- (BOOL)canAcceptLogObject:(id)object { + if ([object isKindOfClass:[NSDictionary class]] && [NSJSONSerialization isValidJSONObject:object]) { + return true; + } else if ([object isKindOfClass:[NSData class]]) { + if ([NSJSONSerialization JSONObjectWithData:object + options:kNilOptions + error:nil]) { + return true; + } + } + return false; +} + +- (BOOL)beginLogWithFileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + // Write valid JSON containing no objects + NSData *data = [kJSONLogEmptyLogString dataUsingEncoding:NSUTF8StringEncoding]; + return [self writeData:data fileHandle:fileHandle error:errorOut]; +} + +- (unsigned long long)checkpointWithFileHandle:(NSFileHandle *)fileHandle { + unsigned long long offset = [fileHandle seekToEndOfFile]; + return offset; +} + +- (void)rollbackToCheckpoint:(unsigned long long)offset fileHandle:(NSFileHandle *)fileHandle { + [fileHandle seekToFileOffset:offset]; + if (offset > 0) { + assert(offset >= _ORKJSON_terminatorLength); + [fileHandle seekToFileOffset:(offset - _ORKJSON_terminatorLength)]; + [self writeData:[kJSONLogFooterString dataUsingEncoding:NSUTF8StringEncoding] fileHandle:fileHandle error:nil]; + [fileHandle truncateFileAtOffset:offset]; + } +} + +- (BOOL)appendObject:(id)object fileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + return [self appendObjects:@[object] fileHandle:fileHandle error:errorOut]; +} + +/* + * Because the log could be written with file protection on, we ensure the log + * is always valid JSON so we can roll over at any time. + * + * When writing, we seek to the end, then seek back past the footer bytes, + * before writing. When writing, we write a separator (if needed), the JSON + * object being appended, and the footer bytes. + */ +- (BOOL)appendObjects:(NSArray *)objects fileHandle:(NSFileHandle *)fileHandle error:(NSError **)errorOut { + if (!fileHandle) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Filehandle is nil" userInfo:nil]; + } + NSInteger numObjects = objects.count; + if (numObjects == 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"No objects" userInfo:nil]; + } + for (NSObject *object in objects) { + if (![self canAcceptLogObject:object]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"ORKLogFormatter accepts JSON serializable objects only" userInfo:nil]; + } + } + + // Seek to the end of the file; we'll later backtrack + unsigned long long offset = [fileHandle seekToEndOfFile]; + if (offset == 0) { + if (![self beginLogWithFileHandle:fileHandle error:errorOut]) { + return NO; + } + offset = [fileHandle offsetInFile]; + } + + unsigned long long checkpoint = [self checkpointWithFileHandle:fileHandle]; + + NSMutableData *outputData = [NSMutableData data]; + NSData *separatorData = [kJSONObjectSeparatorString dataUsingEncoding:NSUTF8StringEncoding]; + if (offset > _ORKJSON_emptyLogLength) { + [outputData appendData:separatorData]; + } + + // Serialize each object separately to the buffer, pending a single write, so the + // objects form part of a single array. + __block BOOL success = YES; + __block NSError *localError; + [objects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSData *data; + if ([obj isKindOfClass:[NSData class]]) { + data = obj; + } else { + data = [NSJSONSerialization dataWithJSONObject:obj options:(NSJSONWritingOptions)0 error:&localError]; + } + if (!data) { + success = NO; + *stop = YES; + } else { + [outputData appendData:data]; + if (idx + 1 < numObjects) { + [outputData appendData:separatorData]; + } + } + }]; + if (errorOut != NULL) { + *errorOut = localError; + } + if (!success) { + return success; + } + + [outputData appendData:[kJSONLogFooterString dataUsingEncoding:NSUTF8StringEncoding]]; + + assert(_ORKJSON_terminatorLength < offset); + [fileHandle seekToFileOffset:(offset - _ORKJSON_terminatorLength)]; + + success = [self writeData:outputData fileHandle:fileHandle error:errorOut]; + + if (!success) { + [self rollbackToCheckpoint:checkpoint fileHandle:fileHandle]; + } + + return success; +} + +@end + + +@implementation ORKDataLogger { + NSURL *_url; + ORKObjectObserver *_observer; + + NSString *_oldLogsPrefix; + + NSFileHandle *_currentFileHandle; + + dispatch_queue_t _queue; + dispatch_source_t _directorySource; + dispatch_group_t _directoryUpdateGroup; + + BOOL _directoryDirty; +} + ++ (ORKDataLogger *)JSONDataLoggerWithDirectory:(NSURL *)url logName:(NSString *)logName delegate:(id)delegate { + return [[ORKDataLogger alloc] initWithDirectory:url logName:logName formatter:[ORKJSONLogFormatter new] delegate:delegate]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithDirectory:(NSURL *)url logName:(NSString *)logName formatter:(ORKLogFormatter *)formatter delegate:(id)delegate { + self = [super init]; + if (self) { + _url = [url copy]; + if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"directory does not exist" userInfo:nil]; + } + if ([logName hasSuffix:@"-"]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"logName should not terminate with '-'" userInfo:nil]; + } + if (!logName.length) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"logName must be non-empty" userInfo:nil]; + } + + NSString *queueId = [@"ResearchKit.log." stringByAppendingString:logName]; + _queue = dispatch_queue_create([queueId cStringUsingEncoding:NSUTF8StringEncoding], DISPATCH_QUEUE_SERIAL); + + _directoryUpdateGroup = dispatch_group_create(); + + self.logName = logName; + self.logFormatter = formatter; + self.delegate = delegate; + self.fileProtectionMode = ORKFileProtectionNone; + _oldLogsPrefix = [_logName stringByAppendingString:@"-"]; + + _observer = [[ORKObjectObserver alloc] initWithObject:self keys:@[@"maximumCurrentLogFileLifetime", @"maximumCurrentLogFileSize"] selector:@selector(fileSizeLimitsDidChange)]; + + [self setupDirectorySource]; + } + return self; +} + +- (instancetype)initWithDirectory:(NSURL *)url configuration:(NSDictionary *)configuration delegate:(id)delegate { + Class formatterClass = NSClassFromString(configuration[@"formatterClass"]); + if (!formatterClass) { + @throw [NSException exceptionWithName:NSGenericException reason:[NSString stringWithFormat:@"%@ is not a class", configuration[@"formatterClass"]] userInfo:nil]; + } + + self = [self initWithDirectory:url logName:configuration[@"logName"] formatter:[[formatterClass alloc] init] delegate:delegate]; + if (self) { + // Don't notify about initial setup + [_observer pause]; + self.maximumCurrentLogFileSize = ((NSNumber *)configuration[@"maximumCurrentLogFileSize"]).unsignedLongValue; + self.maximumCurrentLogFileLifetime = ((NSNumber *)configuration[@"maximumCurrentLogFileLifetime"]).doubleValue; + [_observer resume]; + } + return self; +} + +- (NSDictionary *)configuration { + return @{@"logName": self.logName, + @"formatterClass": NSStringFromClass([self.logFormatter class]), + @"fileProtectionMode": @(self.fileProtectionMode), + @"maximumCurrentLogFileSize": @(self.maximumCurrentLogFileSize), + @"maximumCurrentLogFileLifetime": @(self.maximumCurrentLogFileLifetime) + }; +} + +// The directory source watches for added and removed files in our directory. +// If files are added or removed, we can automatically recalculate our byte counts. +- (void)setupDirectorySource { + int dirFD = open([_url fileSystemRepresentation], O_EVTONLY); + if (dirFD < 0) { + ORK_Log_Info("Could not track directory %s (%d)", [_url fileSystemRepresentation], [[NSFileManager defaultManager] fileExistsAtPath:[_url path]]); + } else { + // Dispatch to a concurrent queue, so we don't store up blocks while our + // queue is working. + _directorySource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, dirFD, DISPATCH_VNODE_WRITE, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + if (!_directorySource) { + close(dirFD); + } + } + + if (_directorySource) { + dispatch_source_set_cancel_handler(_directorySource, ^{ close(dirFD); }); + ORKWeakTypeOf(self) weakSelf = self; + dispatch_source_set_event_handler(_directorySource, ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf directoryUpdated]; + }); + dispatch_resume(_directorySource); + } +} + +#pragma mark Primary interface + +- (void)fileSizeLimitsDidChange { + dispatch_async(dispatch_get_main_queue(), ^{ + id delegate = (id)self.delegate; + if ([delegate respondsToSelector:@selector(dataLoggerThresholdsDidChange:)]) { + [delegate dataLoggerThresholdsDidChange:self]; + } + }); + dispatch_async(_queue, ^{ + [self queue_rolloverIfNeeded]; + + }); +} + +- (void)finishCurrentLog { + dispatch_sync(_queue, ^{ + [self queue_rollover]; + }); +} + +- (NSURL *)currentLogFileURL { + return [_url URLByAppendingPathComponent:_logName]; +} + +- (BOOL)urlMatchesLogName:(NSURL *)url { + NSString *lastComponent = [url lastPathComponent]; + return ([lastComponent isEqualToString:_logName] || [lastComponent hasPrefix:_oldLogsPrefix]); +} + +- (NSFileHandle *)fileHandle { + return _currentFileHandle; +} + +- (BOOL)enumerateLogs:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError * __autoreleasing *)error { + if (!block) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Block parameter is required" userInfo:nil]; + } + + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_enumerateLogs:block error:error]; + }); + return success; +} + +- (BOOL)enumerateLogsUploaded:(BOOL)uploaded block:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + if (!block) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Block parameter is required" userInfo:nil]; + } + + __block BOOL success = NO; + __block NSError *localError; + dispatch_sync(_queue, ^{ + success = [self queue_enumerateLogsUploaded:uploaded block:block error:&localError]; + }); + if (errorOut != NULL) { + *errorOut = localError; + } + return success; +} + +- (BOOL)enumerateLogsNeedingUpload:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + return [self enumerateLogsUploaded:NO block:block error:errorOut]; +} + +- (BOOL)enumerateLogsAlreadyUploaded:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + return [self enumerateLogsUploaded:YES block:block error:errorOut]; +} + +- (BOOL)append:(id)object error:(NSError * __autoreleasing *)error { + if (!object) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Nil object" userInfo:nil]; + } + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_append:object error:error]; + }); + return success; +} + +- (BOOL)appendObjects:(NSArray *)objects error:(NSError * __autoreleasing *)error { + if (!objects.count) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Empty array" userInfo:nil]; + } + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_appendObjects:objects error:error]; + }); + return success; +} + +- (BOOL)markFileUploaded:(BOOL)uploaded atURL:(NSURL *)url error:(NSError * __autoreleasing *)error { + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_markFileUploaded:uploaded atURL:url error:error]; + }); + return success; +} + +- (BOOL)removeUploadedFiles:(NSArray *)fileURLs withError:(NSError * __autoreleasing *)error { + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_removeUploadedFiles:fileURLs withError:error]; + }); + return success; +} + +- (BOOL)removeAllFilesWithError:(NSError * __autoreleasing *)error { + __block BOOL success = NO; + dispatch_sync(_queue, ^{ + success = [self queue_removeAllFilesWithError:error]; + }); + return success; +} + +- (BOOL)isFileUploadedAtURL:(NSURL *)url { + if (![url isFileURL]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"URL must be a file URL" userInfo:nil]; + } + + return [url ork_isUploaded]; +} + +#pragma mark queue methods + +- (void)dealloc { + dispatch_source_cancel(_directorySource); + _directorySource = nil; +} + +- (void)queue_setNeedsUpdateBytes { + if (!_directoryDirty) { + _directoryDirty = YES; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), _queue, ^{ + if (!_directoryDirty) { + return; + } + [self queue_updateBytes]; + }); + } +} + +- (void)directoryUpdated { + if (dispatch_group_wait(_directoryUpdateGroup, DISPATCH_TIME_NOW) != 0) { + // This op is already running or queued; can skip + return; + } + dispatch_group_async(_directoryUpdateGroup, _queue, ^{ + [self queue_setNeedsUpdateBytes]; + }); +} + +- (BOOL)queue_enumerateLogs:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + static NSArray *keys = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + keys = @[NSURLFileSizeKey, NSURLPathKey, NSURLIsRegularFileKey]; + }); + + NSFileManager *manager = [NSFileManager defaultManager]; + NSEnumerator *enumerator = [manager enumeratorAtURL:_url + includingPropertiesForKeys:@[] + options:(NSDirectoryEnumerationOptions)( NSDirectoryEnumerationSkipsSubdirectoryDescendants| + NSDirectoryEnumerationSkipsHiddenFiles| + NSDirectoryEnumerationSkipsPackageDescendants) + errorHandler:nil]; + + NSError *error = nil; + NSMutableArray *urls = [NSMutableArray array]; + for (NSURL *url in enumerator) { + if (![self urlMatchesLogName:url]) { + continue; + } + if ( [[url lastPathComponent] isEqualToString:_logName]) { + // Don't include the "current" log file + continue; + } + NSDictionary *resources = [url resourceValuesForKeys:keys error:&error]; + if (error) { + // If there's been an error getting the resource values, give up + break; + } + if (!((NSNumber *)resources[NSURLIsRegularFileKey]).boolValue) { + continue; + } + [urls addObject:url]; + } + + if (!error) { + // Sort the URLs before beginning enumeration for the caller + [urls sortUsingComparator:^NSComparisonResult(NSURL *obj1, NSURL *obj2) { + // We can assume all relate to files in the same directory + return [[obj1 lastPathComponent] compare:[obj2 lastPathComponent]]; + }]; + + for (NSURL *url in urls) { + BOOL stop = NO; + block(url, &stop); + if (stop) { + break; + } + } + } + + if (errorOut != NULL) { + *errorOut = error; + } + return (error ? NO : YES); +} + +- (BOOL)queue_enumerateLogsUploaded:(BOOL)uploaded block:(void (^)(NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + return [self queue_enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + BOOL wantUploaded = [logFileUrl ork_isUploaded]; + BOOL isWanted = (wantUploaded && uploaded) || (!wantUploaded && !uploaded); + if (isWanted) { + block(logFileUrl, stop); + } + } error:errorOut]; +} + +- (NSFileHandle *)queue_makeFileHandleWithError:(NSError **)errorOut { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *url = [self currentLogFileURL]; + + // If this fails, it's probably because the file doesn't exist + NSNumber *fileExists = nil; + [url getResourceValue:&fileExists forKey:NSURLIsRegularFileKey error:nil]; + + BOOL createNewFile = !fileExists.boolValue; + + NSFileHandle *fileHandle = nil; + if (!createNewFile) { + fileHandle = [NSFileHandle fileHandleForWritingToURL:url error:errorOut]; + if (!fileHandle) { + // Assume it's because we can't open the file, perhaps for security reasons. + // Close and rename the log. + [self queue_closeAndRenameLog]; + createNewFile = YES; + } + } + + if (createNewFile) { + NSString *filePath = [url path]; + BOOL success = [fileManager createFileAtPath:filePath contents:nil attributes:nil]; + if (!success) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileNoSuchFileError userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"ERROR_DATALOGGER_CREATE_FILE", nil)}]; + } + return nil; + } + fileHandle = [NSFileHandle fileHandleForWritingToURL:[self currentLogFileURL] error:errorOut]; + if (!fileHandle) { + [fileManager removeItemAtURL:url error:nil]; + return nil; + } + } + + if (createNewFile) { + assert(fileHandle); + + // Set file protection after opening the file, so that class B works as expected. + BOOL success = [fileManager setAttributes:@{NSFileProtectionKey: ORKFileProtectionFromMode(self.fileProtectionMode)} ofItemAtPath:[url path] error:errorOut]; + + // Allow formatter to initialize the log file with header content + success = success && [self.logFormatter beginLogWithFileHandle:fileHandle error:errorOut]; + + if (!success) { + [fileHandle closeFile]; + [fileManager removeItemAtURL:url error:nil]; + return nil; + } + } + _currentFileHandle = fileHandle; + return _currentFileHandle; +} + +- (NSFileHandle *)queue_fileHandleWithError:(NSError **)errorOut { + if (!_currentFileHandle) { + _currentFileHandle = [self queue_makeFileHandleWithError:errorOut]; + + [_currentFileHandle seekToEndOfFile]; + } + return _currentFileHandle; +} + ++ (NSURL *)nextUrlForDirectoryUrl:(NSURL *)directory logName:(NSString *)logName { + static NSDateFormatter *dateFromatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dateFromatter = [NSDateFormatter new]; + [dateFromatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + dateFromatter.dateFormat = @"yyyyMMddHHmmss"; + }); + + NSString *datedLog = [NSString stringWithFormat:@"%@-%@",logName, [dateFromatter stringFromDate:[NSDate date]]]; + NSURL *destinationUrl = [directory URLByAppendingPathComponent:datedLog]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + int digit = 0; + while ([fileManager fileExistsAtPath:[destinationUrl path] isDirectory:NULL]) { + digit ++; + NSString *lastComponent = [datedLog stringByAppendingFormat:@"-%02d",digit]; + destinationUrl = [directory URLByAppendingPathComponent:lastComponent]; + } + + return destinationUrl; +} + +- (void)queue_closeAndRenameLog { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *url = [self currentLogFileURL]; + + // Close any existing file handle + if (_currentFileHandle) { + [_currentFileHandle synchronizeFile]; + [_currentFileHandle closeFile]; + _currentFileHandle = nil; + } + + // Check if a non-empty file exists, and create the file handle if so + NSDictionary *parameters = [url resourceValuesForKeys:@[NSURLIsRegularFileKey,NSURLFileSizeKey] error:nil]; + + if (((NSNumber *)parameters[NSURLIsRegularFileKey]).boolValue) { + if (((NSNumber *)parameters[NSURLFileSizeKey]).intValue > 0) { + NSURL *destinationUrl = [ORKDataLogger nextUrlForDirectoryUrl:_url logName:_logName]; + ORK_Log_Debug("Rollover: %@ to %@", [url lastPathComponent], [destinationUrl lastPathComponent]); + [fileManager moveItemAtURL:url toURL:destinationUrl error:nil]; + if (self.fileProtectionMode == ORKFileProtectionCompleteUnlessOpen) { + // Upgrade to complete file protection after roll-over + NSError *error = nil; + if (![fileManager setAttributes:@{NSFileProtectionKey: NSFileProtectionComplete} + ofItemAtPath:[destinationUrl path] error:&error]) { + ORK_Log_Error("Error setting NSFileProtectionComplete on %@: %@", destinationUrl, error); + } + } + + dispatch_async(dispatch_get_main_queue(), ^{ + id delegate = self.delegate; + [delegate dataLogger:self finishedLogFile:destinationUrl]; + }); + } else { + // Size zero file is present. Get rid of it. + [fileManager removeItemAtURL:url error:nil]; + } + } +} + +- (void)queue_rolloverIfNeeded { + NSURL *url = [self currentLogFileURL]; + NSDictionary *parameters = [url resourceValuesForKeys:@[NSURLIsRegularFileKey, NSURLFileSizeKey, NSURLCreationDateKey] error:nil]; + + NSInteger fileSize = ((NSNumber *)parameters[NSURLFileSizeKey]).integerValue; + NSDate *creationDate = parameters[NSURLCreationDateKey]; + + BOOL exceededSizeThreshold = ( (self.maximumCurrentLogFileSize > 0) && (fileSize >= self.maximumCurrentLogFileSize)); + + NSDate *earliestAcceptableCreationDate = [NSDate dateWithTimeIntervalSinceNow:-self.maximumCurrentLogFileLifetime]; + + BOOL exceededAgeThreshold = (self.maximumCurrentLogFileLifetime > 0) && creationDate && ( [earliestAcceptableCreationDate earlierDate:creationDate] == creationDate ); + + if (exceededAgeThreshold || exceededSizeThreshold) { + [self queue_rollover]; + } +} + +- (void)queue_rollover { + [self queue_closeAndRenameLog]; +} + +- (BOOL)queue_append:(id)object error:(NSError **)errorOut { + [self queue_rolloverIfNeeded]; + + NSFileHandle *fileHandle = [self queue_fileHandleWithError:errorOut]; + if (!fileHandle) { + return NO; + } + + BOOL result = [self.logFormatter appendObject:object fileHandle:_currentFileHandle error:errorOut]; + + // Quick check to see if we've run over the maximum log file size + if ((self.maximumCurrentLogFileSize > 0) && ([_currentFileHandle offsetInFile] >= self.maximumCurrentLogFileSize)) { + [self queue_rollover]; + } + + return result; +} + +- (BOOL)queue_appendObjects:(NSArray *)objects error:(NSError **)errorOut { + [self queue_rolloverIfNeeded]; + + NSFileHandle *fileHandle = [self queue_fileHandleWithError:errorOut]; + if (!fileHandle) { + return NO; + } + + BOOL result = [self.logFormatter appendObjects:objects fileHandle:_currentFileHandle error:errorOut]; + + // Quick check to see if we've run over the maximum log file size + if ((self.maximumCurrentLogFileSize > 0) && ([_currentFileHandle offsetInFile] >= self.maximumCurrentLogFileSize)) { + [self queue_rollover]; + } + return result; +} + +- (BOOL)queue_markFileUploaded:(BOOL)uploaded atURL:(NSURL *)url error:(NSError **)errorOut { + BOOL success = [url ork_setUploaded:uploaded error:errorOut]; + [self queue_setNeedsUpdateBytes]; + return success; +} + +- (BOOL)queue_removeUploadedFiles:(NSArray *)fileURLs withError:(NSError **)errorOut { + NSFileManager *fileManager = [NSFileManager defaultManager]; + __block NSMutableArray *errors = [NSMutableArray array]; + __block NSError *error = nil; + BOOL success = [self queue_enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + if ([fileURLs containsObject:logFileUrl]) { + BOOL uploaded = [logFileUrl ork_isUploaded]; + + if (uploaded) { + if (![fileManager removeItemAtURL:logFileUrl error:&error]) { + [errors addObject:error]; + error = nil; + } + } else { + // File was requested to be removed, but was not marked uploaded + [errors addObject:[NSError errorWithDomain:ORKErrorDomain + code:ORKErrorInvalidObject + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"ERROR_DATALOGGER_COULD_NOT_MAORK", nil), @"url": logFileUrl}]]; + } + } + } error:&error]; + if (!success && error) { + [errors addObject:error]; + error = nil; + } + + // Reporting multiple errors + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain + code:ORKErrorMultipleErrors + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"ERROR_DATALOGGER_MULTIPLE", nil), @"errors": errors}]; + success = NO; + } + return success; +} + +- (BOOL)queue_removeAllFilesWithError:(NSError * __autoreleasing *)error { + [_currentFileHandle closeFile]; + _currentFileHandle = nil; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + [fileManager removeItemAtURL:[self currentLogFileURL] error:NULL]; + + return [self queue_enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + [fileManager removeItemAtURL:logFileUrl error:error]; + } error:error]; +} + +- (void)queue_updateBytes { + _directoryDirty = NO; + + __block ssize_t pending = 0; + __block ssize_t uploaded = 0; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + [self queue_enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + BOOL logWasUploaded = [logFileUrl ork_isUploaded]; + + NSDictionary *attribs = [fileManager attributesOfItemAtPath:[logFileUrl path] error:nil]; + unsigned long long size = [attribs fileSize]; + + if (logWasUploaded) { + uploaded += size; + } else { + pending += size; + } + } error:nil]; + + self.pendingBytes = pending; + self.uploadedBytes = uploaded; + + if ([self.delegate respondsToSelector:@selector(dataLoggerByteCountsDidChange:)]) { + [self.delegate dataLoggerByteCountsDidChange:self]; + } +} + +@end + + +@interface ORKDataLoggerManager () { + NSURL *_directory; + NSMutableDictionary *_records; + NSMutableDictionary *_observers; + + BOOL _pendingUploadDelegateSent; + BOOL _totalBytesDelegateSent; + + dispatch_queue_t _queue; + + BOOL _updateBytesPending; + dispatch_group_t _updateBytesGroup; + + ORKObjectObserver *_observer; +} + +@end + + +@implementation ORKDataLoggerManager + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithDirectory:(NSURL *)directory delegate:(id)delegate { + self = [super init]; + if (self) { + _directory = directory; + if (![[NSFileManager defaultManager] fileExistsAtPath:[_directory path]]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"directory does not exist" userInfo:nil]; + } + _delegate = delegate; + + _updateBytesGroup = dispatch_group_create(); + + NSString *queueId = [@"ResearchKit.loggerman." stringByAppendingString:[directory lastPathComponent]]; + _queue = dispatch_queue_create([queueId cStringUsingEncoding:NSUTF8StringEncoding], DISPATCH_QUEUE_SERIAL); + if (!_queue) { + return nil; + } + + NSDictionary *configuration = [NSDictionary dictionaryWithContentsOfURL:[_directory URLByAppendingPathComponent:ORKDataLoggerManagerConfigurationFilename]]; + [self loadConfiguration:configuration]; + + _observer = [[ORKObjectObserver alloc] initWithObject:self keys:@[@"pendingUploadBytesThreshold", @"totalBytesThreshold"] selector:@selector(configurationDidChange)]; + + [self setNeedsUpdateBytes]; + } + return self; +} + +static NSString *const PendingUploadBytesThresholdKey = @"pendingUploadBytesThreshold"; +static NSString *const TotalBytesThresholdKey = @"totalBytesThreshold"; +static NSString *const LoggerConfigurationsKey = @"loggers"; + +- (void)loadConfiguration:(NSDictionary *)configuration { + self.pendingUploadBytesThreshold = ((NSNumber *)configuration[PendingUploadBytesThresholdKey]).unsignedLongLongValue; + self.totalBytesThreshold = ((NSNumber *)configuration[TotalBytesThresholdKey]).unsignedLongLongValue; + + NSMutableDictionary *records = [NSMutableDictionary dictionary]; + for (NSDictionary *loggerConfiguration in configuration[LoggerConfigurationsKey]) { + ORKDataLogger *logger = [[ORKDataLogger alloc] initWithDirectory:_directory configuration:loggerConfiguration delegate:self]; + records[logger.logName] = logger; + } + _records = records; +} + +- (NSDictionary *)queue_configuration { + NSMutableArray *loggerConfigurations = [_records.allValues valueForKey:@"configuration"]; + + return @{PendingUploadBytesThresholdKey: @(self.pendingUploadBytesThreshold), + TotalBytesThresholdKey: @(self.totalBytesThreshold), + LoggerConfigurationsKey: loggerConfigurations }; +} + +- (void)queue_synchronizeConfiguration { + NSDictionary *configuration = [self queue_configuration]; + [configuration writeToURL:[_directory URLByAppendingPathComponent:ORKDataLoggerManagerConfigurationFilename] atomically:YES]; +} + +- (void)configurationDidChange { + dispatch_sync(_queue, ^{ + [self queue_synchronizeConfiguration]; + }); +} + +- (ORKDataLogger *)addJSONDataLoggerForLogName:(NSString *)logName { + return [self addDataLoggerForLogName:logName formatter:[ORKJSONLogFormatter new]]; +} + +- (ORKDataLogger *)queue_addDataLoggerForLogName:(NSString *)logName formatter:(ORKLogFormatter *)formatter { + ORKDataLogger *dataLogger = [[ORKDataLogger alloc] initWithDirectory:_directory logName:logName formatter:formatter delegate:self]; + dataLogger.delegate = nil; + // Pick suitable defaults for a typical use pattern + dataLogger.maximumCurrentLogFileLifetime = ORKDataLoggerManagerDefaultLogFileLifetime; + dataLogger.maximumCurrentLogFileSize = ORKDataLoggerManagerDefaultLogFileSize; + dataLogger.delegate = self; + + _records[logName] = dataLogger; + [self queue_synchronizeConfiguration]; + + [self setNeedsUpdateBytes]; + + return dataLogger; +} + +- (ORKDataLogger *)addDataLoggerForLogName:(NSString *)logName formatter:(ORKLogFormatter *)formatter { + if (_records[logName]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Duplicate logger with log name '%@'",logName] userInfo:nil]; + } + + __block ORKDataLogger *dataLogger = nil; + dispatch_sync(_queue, ^{ + dataLogger = [self queue_addDataLoggerForLogName:logName formatter:formatter]; + }); + return dataLogger; +} + +- (void)queue_removeDataLogger:(ORKDataLogger *)logger { + NSString *logName = logger.logName; + ORKDataLogger *thisLogger = _records[logName]; + if (thisLogger && (thisLogger != logger)) { + @throw [NSException exceptionWithName:NSGenericException reason:[NSString stringWithFormat:@"Logger provided for %@ is not the managed one",logName] userInfo:nil]; + } + [logger removeAllFilesWithError:nil]; + [_records removeObjectForKey:logName]; + [self queue_synchronizeConfiguration]; +} + +- (void)removeDataLogger:(ORKDataLogger *)logger { + dispatch_sync(_queue, ^{ + [self queue_removeDataLogger:logger]; + }); +} + +- (ORKDataLogger *)dataLoggerForLogName:(NSString *)logName { + __block ORKDataLogger *dataLogger = nil; + dispatch_sync(_queue, ^{ + dataLogger = _records[logName]; + }); + return dataLogger; +} + +- (NSArray *)logNames { + __block NSArray *logNames = nil; + dispatch_sync(_queue, ^{ + logNames = _records.allKeys; + }); + return logNames; +} + +- (BOOL)queue_enumerateLogsNeedingUpload:(void (^)(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop))block error:(NSError **)errorOut { + BOOL success = YES; + NSMutableArray *allFiles = [NSMutableArray array]; + // Collect all the log file URLs so we can sort them by date rather than enumerating by logger. + for (ORKDataLogger *logger in _records.allValues) { + success = [logger enumerateLogsNeedingUpload:^(NSURL *logFileUrl, BOOL *stop) { + [allFiles addObject:logFileUrl]; + } error:errorOut]; + + if (!success) { + break; + } + } + if (!success) { + return NO; + } + + // Sort by ascending log file date, as recorded in the timestamp in the filename + [allFiles sortUsingComparator:^NSComparisonResult(NSURL *obj1, NSURL *obj2) { + NSComparisonResult result = [[obj1 ork_logDateComponent] compare:[obj2 ork_logDateComponent]]; + if (result == NSOrderedSame) { + result = [[obj1 path] compare:[obj2 path]]; + } + return result; + }]; + + // Enumerate them to the block based API. + for (NSURL *url in allFiles) { + __block BOOL shouldStop = NO; + ORKDataLogger *logger = _records[[url ork_logName]]; + block(logger, url, &shouldStop); + if (shouldStop) { + break; + } + } + + return success; +} + +- (BOOL)enumerateLogsNeedingUpload:(void (^)(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop))block error:(NSError * __autoreleasing *)error { + if (!block) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Block argument required" userInfo:nil]; + } + + __block BOOL success = YES; + dispatch_sync(_queue, ^{ + success = [self queue_enumerateLogsNeedingUpload:block error:error]; + }); + return success; +} + +- (BOOL)queue_removeUploadedFiles:(NSArray *)fileURLs error:(NSError **)errorOut { + BOOL success = YES; + NSMutableArray *notRemoved = [NSMutableArray array]; + for (NSURL *url in fileURLs) { + NSString *logName = [url ork_logNameInDirectory:_directory]; + + if (!_records[logName]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not from a known logger" userInfo:@{@"url":url}]; + } + + NSError *error = nil; + BOOL itemSuccess = [[NSFileManager defaultManager] removeItemAtURL:url error:&error]; + if (!itemSuccess) { + [notRemoved addObject:url]; + success = NO; + } + } + if (errorOut != NULL && notRemoved.count) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorMultipleErrors userInfo:@{@"notRemoved":notRemoved}]; + } + return success; +} + +- (BOOL)removeUploadedFiles:(NSArray *)fileURLs error:(NSError * __autoreleasing *)error { + + __block BOOL success = YES; + dispatch_sync(_queue, ^{ + success = [self queue_removeUploadedFiles:fileURLs error:error]; + }); + return success; +} + +- (BOOL)queue_unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError **)errorOut { + BOOL success = YES; + NSMutableArray *notRemoved = [NSMutableArray array]; + for (NSURL *url in fileURLs) { + NSString *logName = [url ork_logNameInDirectory:_directory]; + ORKDataLogger *logger = _records[logName]; + if (!logger) { + @throw [NSException exceptionWithName:NSGenericException reason:@"URL is not from a known logger" userInfo:@{@"url":url}]; + } + + NSError *error = nil; + BOOL itemSuccess = [logger markFileUploaded:NO atURL:url error:&error]; + if (!itemSuccess) { + [notRemoved addObject:url]; + success = NO; + } + } + if (errorOut != NULL && notRemoved.count) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorMultipleErrors userInfo:@{@"notRemoved":notRemoved}]; + } + return success; +} + +- (BOOL)unmarkUploadedFiles:(NSArray *)fileURLs error:(NSError * __autoreleasing *)error { + __block BOOL success = YES; + dispatch_sync(_queue, ^{ + success = [self queue_unmarkUploadedFiles:fileURLs error:error]; + }); + return success; +} + +- (BOOL)queue_removeOldAndUploadedLogsToThreshold:(unsigned long long)bytes error:(NSError **)errorOut { + if (bytes == 0) { + for (ORKDataLogger *logger in _records) { + [logger removeAllFilesWithError:nil]; + } + + + return (self.totalBytes == 0); + } + + __block unsigned long long totalBytes = self.totalBytes; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (totalBytes > bytes) { + for (ORKDataLogger *logger in _records.allValues) { + [logger enumerateLogsAlreadyUploaded:^(NSURL *logFileUrl, BOOL *stop) { + unsigned long long fileSize = [[fileManager attributesOfItemAtPath:[logFileUrl path] error:nil] fileSize]; + if (fileSize > 0) { + if ([fileManager removeItemAtURL:logFileUrl error:nil]) { + totalBytes -= fileSize; + } + } + if (totalBytes <= bytes) { + *stop = YES; + } + } error:nil]; + + if (totalBytes <= bytes) { + break; + } + } + } + + if (totalBytes > bytes) { + [self queue_enumerateLogsNeedingUpload:^(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop) { + unsigned long long fileSize = [[fileManager attributesOfItemAtPath:[logFileUrl path] error:nil] fileSize]; + if (fileSize > 0) { + if ([fileManager removeItemAtURL:logFileUrl error:nil]) { + totalBytes -= fileSize; + } + } + + if (totalBytes <= bytes) { + *stop = YES; + } + + } error:nil]; + } + + if (errorOut != NULL && (totalBytes > bytes)) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorObjectNotFound userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE", nil)}]; + } + + return (totalBytes <= bytes); +} + +- (BOOL)removeOldAndUploadedLogsToThreshold:(unsigned long long)bytes error:(NSError * __autoreleasing *)error { + __block BOOL success = YES; + dispatch_sync(_queue, ^{ + success = [self queue_removeOldAndUploadedLogsToThreshold:bytes error:error]; + }); + return success; +} + +- (void)queue_updateBytes { + unsigned long long pending = 0; + unsigned long long uploaded = 0; + for (ORKDataLogger *logger in _records.allValues) { + pending += logger.pendingBytes; + uploaded += logger.uploadedBytes; + } + + BOOL exceededPendingThreshold = (self.pendingUploadBytesThreshold > 0) && (pending > self.pendingUploadBytesThreshold); + BOOL exceededTotalThreshold = (self.totalBytesThreshold > 0) && ( (pending + uploaded) > self.totalBytesThreshold); + + self.pendingUploadBytes = pending; + self.totalBytes = (pending + uploaded); + + if (exceededPendingThreshold && !_pendingUploadDelegateSent) { + [self.delegate dataLoggerManager:self pendingUploadBytesReachedThreshold:pending]; + _pendingUploadDelegateSent = YES; + } else if (!exceededPendingThreshold) { + _pendingUploadDelegateSent = NO; + } + + if (exceededTotalThreshold && !_totalBytesDelegateSent) { + [self.delegate dataLoggerManager:self totalBytesReachedThreshold:(pending + uploaded)]; + _totalBytesDelegateSent = YES; + } else if (!exceededTotalThreshold) { + _totalBytesDelegateSent = NO; + } +} + +- (void)setNeedsUpdateBytes { + // If a request is already pending, ignore this one + if (dispatch_group_wait(_updateBytesGroup, DISPATCH_TIME_NOW) != 0) { + return; + } + + dispatch_group_async(_updateBytesGroup, _queue, ^{ + [self queue_updateBytes]; + }); +} + +#pragma mark ORKDataLoggerDelegate + +- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl { + // Do nothing; we'll notice what happened when byte counts change +} + +- (void)dataLoggerByteCountsDidChange:(ORKDataLogger *)dataLogger { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self setNeedsUpdateBytes]; + }); +} + +- (void)dataLoggerThresholdsDidChange:(ORKDataLogger *)dataLogger { + [self configurationDidChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.h new file mode 100755 index 0000000..fcd91eb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class CMDeviceMotion; + +@protocol ORKDeviceMotionRecorderDelegate + +@optional + +- (void)deviceMotionRecorderDidUpdateWithMotion:(CMDeviceMotion *)motion; + +@end + +/** + The `ORKDeviceMotionRecorder` class represents a recorder that requests and collects device motion data from CoreMotion at a fixed frequency. + + To ensure that the motion recorder continues to record when the app enters the + background, use the background task support provided by `UIApplication`. + */ +ORK_CLASS_AVAILABLE +@interface ORKDeviceMotionRecorder : ORKRecorder + +/** + The frequency of motion data collection from CoreMotion in hertz (Hz). + */ +@property (nonatomic, readonly) double frequency; + +/** + Returns an initialized device motion recorder using the specified frequency. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param frequency The frequency of motion data collection from CoreMotion in hertz (Hz). + @param step The step that requested this recorder. + @param outputDirectory The directory in which the device motion data should be stored. + + @return An initialized motion data recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + frequency:(double)frequency + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.m new file mode 100755 index 0000000..7e2b4e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKDeviceMotionRecorder.m @@ -0,0 +1,224 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDeviceMotionRecorder.h" + +#import "ORKDataLogger.h" + +#import "ORKRecorder_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "CMDeviceMotion+ORKJSONDictionary.h" + +@import CoreMotion; + + +@interface ORKDeviceMotionRecorder () { + ORKDataLogger *_logger; +} + +@property (nonatomic, strong) CMMotionManager *motionManager; + +@property (nonatomic) NSTimeInterval uptime; + +@end + + +@implementation ORKDeviceMotionRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier + frequency:(double)frequency + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier + step:step + outputDirectory:outputDirectory]; + if (self) { + self.frequency = frequency; + self.continuesInBackground = YES; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (void)setFrequency:(double)frequency { + if (frequency <= 0) { + _frequency = 1; + } else { + _frequency = frequency; + } +} + +- (CMMotionManager *)createMotionManager { + return [[CMMotionManager alloc] init]; +} + +- (void)start { + [super start]; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + self.motionManager = [self createMotionManager]; + self.motionManager.deviceMotionUpdateInterval = 1.0 / _frequency; + + self.uptime = [NSProcessInfo processInfo].systemUptime; + + [self.motionManager stopDeviceMotionUpdates]; + + [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion *data, NSError *error) { + BOOL success = NO; + if (data) { + success = [_logger append:[data ork_JSONDictionary] error:&error]; + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(deviceMotionRecorderDidUpdateWithMotion:)]) { + [delegate deviceMotionRecorderDidUpdateWithMotion:data]; + } + } + if (!success) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self finishRecordingWithError:error]; + }); + } + }]; +} + +- (NSString *)recorderType { + return @"deviceMotion"; +} + +- (void)stop { + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (self.isRecording) { + [self.motionManager stopDeviceMotionUpdates]; + self.motionManager = nil; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:error]; +} + +- (BOOL)isRecording { + return self.motionManager.deviceMotionActive; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +@end + + +@implementation ORKDeviceMotionRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithIdentifier:(NSString *)identifier { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use subclass designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)freq { + self = [super initWithIdentifier:identifier]; + if (self) { + _frequency = freq; + } + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return [[ORKDeviceMotionRecorder alloc] initWithIdentifier:self.identifier + frequency:self.frequency + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, frequency); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, frequency); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.frequency == castObject.frequency)); +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionCoreMotionAccelerometer; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.h new file mode 100755 index 0000000..f3a05dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" +#import "ORKUnitLabel.h" +#import "ORKRingView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKRoundTappingButton; + +@interface ORKEnvironmentSPLMeterContentView : ORKActiveStepCustomView + +- (void)setProgress:(CGFloat)progress; + +- (void)setProgressCircle:(CGFloat)progress; + +@property(nonatomic, strong) ORKRingView *ringView; + +- (void)reachedOptimumNoiseLevel; + +@end + +NS_ASSUME_NONNULL_END + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.m new file mode 100755 index 0000000..558bbc7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterContentView.m @@ -0,0 +1,168 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKEnvironmentSPLMeterContentView.h" + +#import "ORKRoundTappingButton.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKRingView.h" +#import "ORKProgressView.h" +#import "ORKCompletionCheckmarkView.h" + +static const CGFloat CircleIndicatorMaxDiameter = 150.0; +static const CGFloat RingViewTopPadding = 24.0; +static const CGFloat InstructionLabelTopPadding = 50.0; + +@implementation ORKEnvironmentSPLMeterContentView { + UIView *_circleIndicatorView; + UILabel *_DBInstructionLabel; + CGFloat preValue; + CGFloat currentValue; + UIColor *_circleIndicatorNoiseColor; +} + +- (instancetype)init { + self = [super init]; + if (self) { + preValue = -M_PI_2; + currentValue = 0.0; + _circleIndicatorNoiseColor = UIColor.systemOrangeColor; + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setupRingView]; + [self setupCircleIndicatorView]; + [self setProgressCircle:0.0]; + [self setupDBInstructionLabel]; + } + + return self; +} + +- (void)setupRingView { + if (!_ringView) { + _ringView = [ORKRingView new]; + } + _ringView.animationDuration = 0.0; + _ringView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_ringView]; + + [[_ringView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + [[_ringView.topAnchor constraintEqualToAnchor:self.topAnchor constant:RingViewTopPadding] setActive:YES]; + [_ringView setColor:UIColor.grayColor]; +} + +- (void)setupCircleIndicatorView { + if (!_circleIndicatorView) { + _circleIndicatorView = [UIView new]; + } + _circleIndicatorView.translatesAutoresizingMaskIntoConstraints = NO; + [self insertSubview:_circleIndicatorView belowSubview:_ringView]; + + [[_circleIndicatorView.centerXAnchor constraintEqualToAnchor:_ringView.centerXAnchor] setActive:YES]; + [[_circleIndicatorView.centerYAnchor constraintEqualToAnchor:_ringView.centerYAnchor] setActive:YES]; + [[_circleIndicatorView.heightAnchor constraintEqualToConstant:CircleIndicatorMaxDiameter] setActive:YES]; + [[_circleIndicatorView.widthAnchor constraintEqualToConstant:CircleIndicatorMaxDiameter] setActive:YES]; + _circleIndicatorView.layer.cornerRadius = CircleIndicatorMaxDiameter * 0.5; +} + +- (void)setupDBInstructionLabel { + if (!_DBInstructionLabel) { + _DBInstructionLabel = [ORKLabel new]; + _DBInstructionLabel.numberOfLines = 0; + _DBInstructionLabel.textColor = UIColor.systemGrayColor; + _DBInstructionLabel.text = ORKLocalizedString(@"ENVIRONMENTSPL_OK", nil); + } + _DBInstructionLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_DBInstructionLabel]; + + [[_DBInstructionLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + [[_DBInstructionLabel.topAnchor constraintEqualToAnchor:_circleIndicatorView.bottomAnchor constant:InstructionLabelTopPadding] setActive:YES]; +} + +- (void)setProgressCircle:(CGFloat)progress { + CGFloat circleDiameter; + CGFloat y1 = 0.5, x1 = 0.8, y2 = 1.4, x2 = 1.2; + + if (progress < x1) { + // lower limit for diameter + circleDiameter = y1; + } else if (progress > x2) { + // upper limit for diameter + circleDiameter = y2; + } else { + // linear interpolation + circleDiameter = y1 + (y2 - y1)/(x2 - x1) * (progress - x1); + } + if (progress > 1.0) { + [_ringView setBackgroundLayerStrokeColor:[UIColor.whiteColor colorWithAlphaComponent:0.3] circleStrokeColor:UIColor.whiteColor]; + } + else { + [_ringView resetLayerColors]; + } + [UIView animateWithDuration:0.8 + delay:0 + options:UIViewAnimationOptionCurveLinear + animations:^{ + _circleIndicatorView.transform = CGAffineTransformMakeScale(circleDiameter, circleDiameter); + _circleIndicatorView.backgroundColor = progress > 1.0 ? _circleIndicatorNoiseColor : self.tintColor; + } + completion:nil]; + [self updateInstructionForValue:progress]; +} + +- (void)setProgress:(CGFloat)progress { + CGFloat value = progress < 0.001 ? 0.001 : progress; + [_ringView setValue:value]; +} + +- (void)updateInstructionForValue:(CGFloat)progress { + dispatch_async(dispatch_get_main_queue(), ^{ + _DBInstructionLabel.text = progress >= 1.0 ? ORKLocalizedString(@"ENVIRONMENTSPL_NOISE", nil) : ORKLocalizedString(@"ENVIRONMENTSPL_OK", nil); + }); +} + +- (void)finishStep:(ORKActiveStepViewController *)viewController { + [super finishStep:viewController]; +} + +- (void)reachedOptimumNoiseLevel { + _ringView.hidden = YES; + _circleIndicatorView.hidden = YES; + ORKCompletionCheckmarkView *checkmarkView = [[ORKCompletionCheckmarkView alloc] initWithDimension:_ringView.bounds.size.width]; + checkmarkView.translatesAutoresizingMaskIntoConstraints = NO; + [self insertSubview:checkmarkView aboveSubview:_ringView]; + [[checkmarkView.centerXAnchor constraintEqualToAnchor:_ringView.centerXAnchor] setActive:YES]; + [[checkmarkView.centerYAnchor constraintEqualToAnchor:_ringView.centerYAnchor] setActive:YES]; + [checkmarkView setAnimationPoint:1 animated:YES]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.h new file mode 100755 index 0000000..6ba4748 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +ORK_CLASS_AVAILABLE +@interface ORKEnvironmentSPLMeterResult : ORKResult + +@property (nonatomic, assign) double sensitivityOffset; + +@property (nonatomic, copy, nullable) NSArray *recordedSPLMeterSamples; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.m new file mode 100755 index 0000000..aaab011 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterResult.m @@ -0,0 +1,83 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKEnvironmentSPLMeterResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKEnvironmentSPLMeterResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, sensitivityOffset); + ORK_ENCODE_OBJ(aCoder, recordedSPLMeterSamples); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, sensitivityOffset); + ORK_DECODE_OBJ_ARRAY(aDecoder, recordedSPLMeterSamples, NSNumber); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.sensitivityOffset == castObject.sensitivityOffset && + ORKEqualObjects(self.recordedSPLMeterSamples, castObject.recordedSPLMeterSamples)) ; +} + +- (NSUInteger)hash { + return super.hash ^ self.recordedSPLMeterSamples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKEnvironmentSPLMeterResult *result = [super copyWithZone:zone]; + result.sensitivityOffset = self.sensitivityOffset; + result.recordedSPLMeterSamples = [self.recordedSPLMeterSamples copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; sensitivityOffset: %.1lf; recordedSPLMeterSamples: %@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.sensitivityOffset, self.recordedSPLMeterSamples]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.h new file mode 100755 index 0000000..1581b95 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKEnvironmentSPLMeterStep : ORKActiveStep + +/** + The maximum permissible value for the environment sound pressure level in dBA. + */ +@property (nonatomic, assign) double thresholdValue; + +/** + The rate at which the `AVAudioPCMBuffer` is queried and A-weighted filter is applied. + */ +@property (nonatomic, assign) NSTimeInterval samplingInterval; + +/** + The number of consecutive samples less than threshold value required for the step to proceed. + */ +@property (nonatomic, assign) NSInteger requiredContiguousSamples; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.m new file mode 100755 index 0000000..907986f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStep.m @@ -0,0 +1,122 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKEnvironmentSPLMeterStep.h" +#import "ORKEnvironmentSPLMeterStepViewController.h" + +#import "ORKHelpers_Internal.h" + +#define ORKEnvironmentSPLMeterTaskDefaultThresholdValue 35.0 +#define ORKEnvironmentSPLMeterTaskMinimumSamplingInterval 1.0 +#define ORKEnvironmentSPLMeterTaskDefaultRequiredContiguousSamples 5 + +@implementation ORKEnvironmentSPLMeterStep + ++ (Class)stepViewControllerClass { + return [ORKEnvironmentSPLMeterStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + self.thresholdValue = ORKEnvironmentSPLMeterTaskDefaultThresholdValue; + self.samplingInterval = ORKEnvironmentSPLMeterTaskMinimumSamplingInterval; + self.requiredContiguousSamples = ORKEnvironmentSPLMeterTaskDefaultRequiredContiguousSamples; + self.stepDuration = CGFLOAT_MAX; + self.shouldShowDefaultTimer = NO; +} + +- (void)validateParameters { + [super validateParameters]; + + if (self.thresholdValue < 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"threshold cannot be lesser than 0"] userInfo:nil]; + } + if (self.samplingInterval < ORKEnvironmentSPLMeterTaskMinimumSamplingInterval) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"sampling interval cannot be lesser than %@", @(ORKEnvironmentSPLMeterTaskMinimumSamplingInterval)] userInfo:nil]; + } + if (self.requiredContiguousSamples <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"required contiguous samples cannot be less than or equal to 0"] userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKEnvironmentSPLMeterStep *step = [super copyWithZone:zone]; + step.thresholdValue = self.thresholdValue; + step.samplingInterval = self.samplingInterval; + step.requiredContiguousSamples = self.requiredContiguousSamples; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, thresholdValue); + ORK_DECODE_DOUBLE(aDecoder, samplingInterval); + ORK_DECODE_INTEGER(aDecoder, requiredContiguousSamples); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, thresholdValue); + ORK_ENCODE_DOUBLE(aCoder, samplingInterval); + ORK_ENCODE_INTEGER(aCoder, requiredContiguousSamples); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && (self.thresholdValue == castObject.thresholdValue) + && (self.samplingInterval == castObject.samplingInterval) + && (self.requiredContiguousSamples == castObject.requiredContiguousSamples)); +} + +@end + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.h new file mode 100755 index 0000000..14856ba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKEnvironmentSPLMeterStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.m new file mode 100755 index 0000000..9bab011 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKEnvironmentSPLMeterStepViewController.m @@ -0,0 +1,381 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKEnvironmentSPLMeterStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKRoundTappingButton.h" +#import "ORKEnvironmentSPLMeterContentView.h" +#import "ORKRingView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKEnvironmentSPLMeterResult.h" +#import "ORKEnvironmentSPLMeterStep.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKSkin.h" + +#import "ORKHelpers_Internal.h" +#import +#include + +@interface ORKEnvironmentSPLMeterStepViewController () { + AVAudioEngine *_audioEngine; + AVAudioInputNode *_inputNode; + AVAudioUnitEQ *_eqUnit; + AVAudioFrameCount _bufferSize; + uint32_t _sampleRate; + AVAudioFormat *_inputNodeOutputFormat; + int _countToFetch; + NSMutableArray *_rmsBuffer; + dispatch_semaphore_t _semaphoreRms; + float _rmsData; + float _spl; + double _samplingInterval; + double _thresholdValue; + double _sensitivityOffset; + NSInteger _requiredContiguousSamples; + int _counter; + NSMutableArray *_recordedSamples; + AVAudioSessionCategory _savedSessionCategory; + AVAudioSessionMode _savedSessionMode; + AVAudioSessionCategoryOptions _savedSessionCategoryOptions; +} + +@property (nonatomic, strong) ORKEnvironmentSPLMeterContentView *environmentSPLMeterContentView; + +@end + +@implementation ORKEnvironmentSPLMeterStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + _rmsBuffer = [NSMutableArray new]; + _semaphoreRms = dispatch_semaphore_create(1); + _rmsData = 0.0; + _spl = 0.0; + _counter = 0; + _samplingInterval = 1.0; + _requiredContiguousSamples = 1; + _sensitivityOffset = -23.3; + _recordedSamples = [NSMutableArray new]; + } + + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self saveAudioSession]; + _sensitivityOffset = [self sensitivityOffsetForDevice]; + _environmentSPLMeterContentView = [ORKEnvironmentSPLMeterContentView new]; + [self setNavigationFooterView]; + _environmentSPLMeterContentView.ringView.delegate = self; + self.activeStepView.activeCustomView = _environmentSPLMeterContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + [self requestMicrophoneAuthorization]; + [self configureAudioSession]; + _audioEngine = [[AVAudioEngine alloc] init]; + _eqUnit = [[AVAudioUnitEQ alloc] initWithNumberOfBands:6]; + _inputNode = [_audioEngine inputNode]; + _inputNodeOutputFormat = [_inputNode inputFormatForBus:0]; + _sampleRate = (uint32_t)_inputNodeOutputFormat.sampleRate; + _bufferSize = _sampleRate/10; + _countToFetch = _sampleRate/(int)_bufferSize; + [self configureEQ]; + [_audioEngine attachNode:_eqUnit]; + [_audioEngine connect:_inputNode to:_eqUnit format:_inputNodeOutputFormat]; +} + +- (void)saveAudioSession { + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + _savedSessionCategory = audioSession.category; + _savedSessionMode = audioSession.mode; + _savedSessionCategoryOptions = audioSession.categoryOptions; +} + +- (void)setNavigationFooterView { + self.activeStepView.navigationFooterView.continueButtonItem = self.continueButtonItem; + self.activeStepView.navigationFooterView.continueEnabled = NO; + [self.activeStepView.navigationFooterView updateContinueAndSkipEnabled]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + [self start]; + + _samplingInterval = [self environmentSPLMeterStep].samplingInterval; + _requiredContiguousSamples = [self environmentSPLMeterStep].requiredContiguousSamples; + _thresholdValue = [self environmentSPLMeterStep].thresholdValue; + [self splWorkBlock]; + +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [self resetAudioSession]; + [_eqUnit removeTapOnBus:0]; + [_audioEngine stop]; + [_rmsBuffer removeAllObjects]; +} + +- (NSString *)deviceType { + return [[UIDevice currentDevice] model]; +} + +- (double)sensitivityOffsetForDevice { + NSDictionary *lookupTable = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:@"splMeter_sensitivity_offset" ofType:@"plist"]]; + NSString *deviceTypeString = [self deviceType]; + double sensitivity = [[lookupTable valueForKey:deviceTypeString] doubleValue]; + return ( sensitivity ? : _sensitivityOffset); +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = sResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKEnvironmentSPLMeterResult *splResult = [[ORKEnvironmentSPLMeterResult alloc] initWithIdentifier:self.step.identifier]; + splResult.startDate = sResult.startDate; + splResult.endDate = now; + splResult.sensitivityOffset = _sensitivityOffset; + splResult.recordedSPLMeterSamples = [_recordedSamples copy]; + + [results addObject:splResult]; + + sResult.results = [results copy]; + + return sResult; +} + +- (void)requestMicrophoneAuthorization { + [[AVAudioSession sharedInstance] recordPermission]; +} + +- (void)configureAudioSession { + NSError *error = nil; + + // Stop any existing audio + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:&error]; + if (error) { + ORK_Log_Error("Setting AVAudioSessionCategory failed with error message: \"%@\"", error.localizedDescription); + } + [[AVAudioSession sharedInstance] setActive:YES error:&error]; + if (error) { + ORK_Log_Error("Activating AVAudioSession failed with error message: \"%@\"", error.localizedDescription); + } + + // Force input/output from iOS device + [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeMeasurement options:AVAudioSessionCategoryOptionMixWithOthers error:&error]; + [[AVAudioSession sharedInstance] overrideOutputAudioPort: AVAudioSessionPortOverrideSpeaker error:&error]; + if (error) { + ORK_Log_Error("Setting AVAudioSessionCategory failed with error message: \"%@\"", error.localizedDescription); + } + [[AVAudioSession sharedInstance] setActive:YES error:&error]; + if (error) { + ORK_Log_Error("Activating AVAudioSession failed with error message: \"%@\"", error.localizedDescription); + } +} + +- (void)configureEQ { + _eqUnit.globalGain = 0; + + // A-weighting EQ + AVAudioUnitEQFilterParameters *eqCoefficient = _eqUnit.bands[0]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeHighPass; + eqCoefficient.frequency = 290; + eqCoefficient.bypass = NO; + + eqCoefficient = _eqUnit.bands[1]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeParametric; + eqCoefficient.frequency = 243; + eqCoefficient.bandwidth = 1.3882; + eqCoefficient.gain = -4.5; + eqCoefficient.bypass = NO; + + eqCoefficient = _eqUnit.bands[2]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeParametric; + eqCoefficient.frequency = 450; + eqCoefficient.bandwidth = 0.94428; + eqCoefficient.gain = -1.5; + eqCoefficient.bypass = NO; + + eqCoefficient = _eqUnit.bands[3]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeParametric; + eqCoefficient.frequency = 2650; + eqCoefficient.bandwidth = 2.4924; + eqCoefficient.gain = 1.25; + eqCoefficient.bypass = NO; + + eqCoefficient = _eqUnit.bands[4]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeParametric; + eqCoefficient.frequency = 10000; + eqCoefficient.bandwidth = 1.0246; + eqCoefficient.gain = -1.5; + eqCoefficient.bypass = NO; + + eqCoefficient = _eqUnit.bands[5]; + eqCoefficient.filterType = AVAudioUnitEQFilterTypeLowPass; + eqCoefficient.frequency = 11800; + eqCoefficient.bypass = NO; +} + +- (void)splWorkBlock { + if (!_audioEngine.isRunning && ![[AVAudioSession sharedInstance] isOtherAudioPlaying]) { + [_eqUnit installTapOnBus:0 + bufferSize:_bufferSize + format:_inputNodeOutputFormat + block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) { + if ([AVAudioSession sharedInstance].recordPermission == AVAudioSessionRecordPermissionGranted) { + if (buffer.frameLength != _bufferSize) { + _bufferSize = buffer.frameLength; + } + int sampleCount = _samplingInterval * _countToFetch; + float rms = 0.0; + for (int i = 0; i < buffer.frameLength; i++) { + float value = [@(buffer.floatChannelData[0][i]) floatValue]; + rms += value * value; + } + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [_rmsBuffer addObject:@(rms)]; + + // perform averaging based on capture interval + if (_rmsBuffer.count >= sampleCount + 1) { + float rmsSum = 0.0; + int i = sampleCount; + NSUInteger j = _rmsBuffer.count - 1; + while (i>0) { + rmsSum += [_rmsBuffer[j] floatValue]; + i --; + j --; + } + _rmsData = rmsSum/_samplingInterval; + float calValue = _sensitivityOffset; + _spl = (20 * log10f(sqrtf(_rmsData/(float)_sampleRate))) - calValue + 94; + [_recordedSamples addObject:[NSNumber numberWithFloat:_spl]]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.environmentSPLMeterContentView setProgressCircle:(_spl/_thresholdValue)]; + }); + [self evaluateThreshold:_spl]; + [_rmsBuffer removeAllObjects]; + } + dispatch_semaphore_signal(_semaphoreRms); + }); + dispatch_semaphore_wait(_semaphoreRms, DISPATCH_TIME_FOREVER); + } else if ([AVAudioSession sharedInstance].recordPermission == AVAudioSessionRecordPermissionDenied) { + dispatch_async(dispatch_get_main_queue(), ^{ + [_eqUnit removeTapOnBus:0]; + [_audioEngine stop]; + [_rmsBuffer removeAllObjects]; + }); + } + }]; + if (!_audioEngine.isRunning && ![[AVAudioSession sharedInstance] isOtherAudioPlaying]) { + NSError *error = nil; + [_audioEngine startAndReturnError:&error]; + } else { + [_eqUnit removeTapOnBus:0]; + [_audioEngine stop]; + [_rmsBuffer removeAllObjects]; + } + } +} + +- (void) evaluateThreshold: (float)spl { + if (spl < _thresholdValue) { + _counter += 1; + [self.environmentSPLMeterContentView.ringView fillRingWithDuration:(double)_requiredContiguousSamples*_samplingInterval]; + if (_counter >= _requiredContiguousSamples) { + [self reachedOptimumNoiseLevel]; + } + } else { + _counter = 0; + self.environmentSPLMeterContentView.ringView.animationDuration = 0.5; + [self.environmentSPLMeterContentView setProgress:0.0]; + } +} + +- (void) resetAudioSession { + NSError *error = nil; + [[AVAudioSession sharedInstance] setCategory:_savedSessionCategory mode:_savedSessionMode options:_savedSessionCategoryOptions error:&error]; + [[AVAudioSession sharedInstance] overrideOutputAudioPort: AVAudioSessionPortOverrideNone error:&error]; + if (error) { + ORK_Log_Error("Setting AVAudioSessionCategory failed with error message: \"%@\"", error.localizedDescription); + } + [[AVAudioSession sharedInstance] setActive:YES error:&error]; + if (error) { + ORK_Log_Error("Activating AVAudioSession failed with error message: \"%@\"", error.localizedDescription); + } +} + +- (void)reachedOptimumNoiseLevel { + [self resetAudioSession]; + [_audioEngine stop]; +} + +- (void)stepDidFinish { + [super stepDidFinish]; + [self.environmentSPLMeterContentView finishStep:self]; + [self goForward]; +} + +- (void)start { + [super start]; +} + +- (ORKEnvironmentSPLMeterStep *)environmentSPLMeterStep { + return (ORKEnvironmentSPLMeterStep *)self.step; +} + +#pragma mark - ORKRingViewDelegate + +- (void)ringViewDidFinishFillAnimation { + [self.environmentSPLMeterContentView reachedOptimumNoiseLevel]; + self.activeStepView.navigationFooterView.continueEnabled = YES; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.h new file mode 100755 index 0000000..bd1e034 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.h @@ -0,0 +1,81 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKFileResult` class is a result that references the location of a file produced + during a task. + + A file result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize the linked file for transmission + to the server. + + Active steps typically produce file results when CoreMotion or HealthKit are + serialized to disk using a data logger (`ORKDataLogger`). Audio recording also produces a file + result. + + When you write a custom step, use files to report results only when the data + is likely to be too big to hold in memory for the duration of the task. For + example, fitness tasks that use sensors can be quite long and can generate + a large number of samples. To compensate for the length of the task, you can stream the samples to disk during + the task, and return an `ORKFileResult` object in the result hierarchy, usually as a + child of an `ORKStepResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKFileResult : ORKResult + +/** + The MIME content type of the result. + + For example, `@"application/json"`. + */ +@property (nonatomic, copy, nullable) NSString *contentType; + +/** + The URL of the file produced. + + It is the responsibility of the receiver of the result object to delete + the file when it is no longer needed. + + The file is typically written to the output directory of the + task view controller, so it is common to manage the archiving or cleanup + of these files by archiving or deleting the entire output directory. + */ +@property (nonatomic, copy, nullable) NSURL *fileURL; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.m new file mode 100755 index 0000000..c0361d4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFileResult.m @@ -0,0 +1,87 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFileResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKFileResult + +- (BOOL)isSaveable { + return (_fileURL != nil); +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_URL(aCoder, fileURL); + ORK_ENCODE_OBJ(aCoder, contentType); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_URL(aDecoder, fileURL); + ORK_DECODE_OBJ_CLASS(aDecoder, contentType, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualFileURLs(self.fileURL, castObject.fileURL) && + ORKEqualObjects(self.contentType, castObject.contentType)); +} + +- (NSUInteger)hash { + return super.hash ^ self.fileURL.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKFileResult *result = [super copyWithZone:zone]; + result.fileURL = [self.fileURL copy]; + result.contentType = [self.contentType copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; fileURL: %@ (%lld bytes)%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.fileURL, [[NSFileManager defaultManager] attributesOfItemAtPath:self.fileURL.path error:nil].fileSize, self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.h new file mode 100755 index 0000000..350fbec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKFitnessContentView : ORKActiveStepCustomView + +@property (nonatomic, assign, getter=isFinished) BOOL finished; + +@property (nonatomic) BOOL hasHeartRate; +@property (nonatomic) BOOL hasDistance; + +@property (nonatomic, copy, nullable) NSString *heartRate; +@property (nonatomic) double distanceInMeters; + +@property (nonatomic, strong, nullable) UIImage *image; + +@property (nonatomic, assign) NSTimeInterval timeLeft; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.m new file mode 100755 index 0000000..a4f95be --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessContentView.m @@ -0,0 +1,346 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFitnessContentView.h" + +#import "ORKActiveStepQuantityView.h" +#import "ORKTintedImageView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@import CoreMotion; +@import HealthKit; + + +// #define LAYOUT_TEST 1 +// #define LAYOUT_DEBUG 1 + +@interface ORKFitnessContentView () { + ORKQuantityLabel *_timerLabel; + ORKQuantityPairView *_quantityPairView; + UIView *_imageSpacer1; + UIView *_imageSpacer2; + ORKTintedImageView *_imageView; + NSLengthFormatter *_lengthFormatter; + NSLayoutConstraint *_imageRatioConstraint; + NSLayoutConstraint *_topConstraint; +} + +@end + + +@implementation ORKFitnessContentView + +- (ORKActiveStepQuantityView *)distanceView { + return _quantityPairView.leftView; +} + +- (ORKActiveStepQuantityView *)heartRateView { + return _quantityPairView.rightView; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _timerLabel = [ORKQuantityLabel new]; + _quantityPairView = [ORKQuantityPairView new]; + _imageSpacer1 = [UIView new]; + _imageSpacer1.translatesAutoresizingMaskIntoConstraints = NO; + _imageSpacer2 = [UIView new]; + _imageSpacer2.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_imageSpacer1]; + [self addSubview:_imageSpacer2]; + [self heartRateView].image = [UIImage imageNamed:@"heart-fitness" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + [self updateLengthFormatter]; + _imageView = [ORKTintedImageView new]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.shouldApplyTint = YES; + _timerLabel.translatesAutoresizingMaskIntoConstraints = NO; + _quantityPairView.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + self.translatesAutoresizingMaskIntoConstraints = NO; + [self updateKeylineVisible]; + + _timerLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently; + _imageView.isAccessibilityElement = NO; + + self.hasHeartRate = _hasHeartRate; + self.hasDistance = _hasDistance; + +#if LAYOUT_TEST + self.timeLeft = 60 * 5; + self.hasHeartRate = YES; + self.hasDistance = YES; + self.distanceInMeters = 100; + self.heartRate = @"22"; +#endif +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.2]; + _quantityPairView.backgroundColor = [[UIColor orangeColor] colorWithAlphaComponent:0.2]; +#endif + + [self setDistanceInMeters:0]; + [self heartRateView].title = ORKLocalizedString(@"FITNESS_HEARTRATE_TITLE", nil); + + [self addSubview:_quantityPairView]; + [self addSubview:_imageView]; + [self addSubview:_timerLabel]; + [self setUpConstraints]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil]; + + [self tintColorDidChange]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)updateLengthFormatter { + _lengthFormatter = [NSLengthFormatter new]; + _lengthFormatter.numberFormatter.maximumFractionDigits = 1; + _lengthFormatter.numberFormatter.maximumSignificantDigits = 3; +} + +- (void)localeDidChange:(NSNotification *)notification { + [self updateLengthFormatter]; + [self setDistanceInMeters:_distanceInMeters]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + const CGFloat CaptionBaselineToTimerTop = ORKGetMetricForWindow(ORKScreenMetricCaptionBaselineToFitnessTimerTop, window); + const CGFloat CaptionBaselineToStepViewTop = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTop, window); + _topConstraint.constant = (CaptionBaselineToTimerTop - CaptionBaselineToStepViewTop); +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + NSDictionary *views = NSDictionaryOfVariableBindings(_timerLabel, _imageView, _quantityPairView, _imageSpacer1, _imageSpacer2); + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_timerLabel][_imageSpacer1(>=0)][_imageView]" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + + _topConstraint = [NSLayoutConstraint constraintWithItem:_timerLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [constraints addObject:_topConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_timerLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_timerLabel + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_imageView][_imageSpacer2(>=0)][_quantityPairView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_imageSpacer1 + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_imageSpacer2 + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_imageSpacer1 + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_imageSpacer2 + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + + NSLayoutConstraint *imageSpacerHeightConstraint = [NSLayoutConstraint constraintWithItem:_imageSpacer1 + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:CGFLOAT_MIN]; + imageSpacerHeightConstraint.priority = UILayoutPriorityDefaultLow - 1; + [constraints addObject:imageSpacerHeightConstraint]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_quantityPairView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + NSLayoutConstraint *maxWidthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + maxWidthConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:maxWidthConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; + [self updateConstraintConstantsForWindow:self.window]; +} + +- (void)setImage:(UIImage *)image { + _image = image; + _imageView.image = image; + + _imageRatioConstraint.active = NO; + + CGSize size = image.size; + if (size.width > 0 && size.height > 0) { + _imageRatioConstraint = [NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_imageView + attribute:NSLayoutAttributeWidth + multiplier:size.height / size.width + constant:0.0]; + _imageRatioConstraint.active = YES; + } +} + +- (void)setHasDistance:(BOOL)hasDistance { + _hasDistance = hasDistance; + [self distanceView].enabled = _hasDistance; + [self updateKeylineVisible]; +} + +- (void)setHasHeartRate:(BOOL)hasHeartRate { + _hasHeartRate = hasHeartRate; + [self heartRateView].enabled = _hasHeartRate; + [self updateKeylineVisible]; +} + +- (void)setHeartRate:(NSString *)heartRate { + _heartRate = heartRate; + [self heartRateView].value = heartRate; +} + +- (void)updateKeylineVisible { + [_quantityPairView setKeylineHidden:!(_hasDistance && _hasHeartRate)]; +} + +- (void)setDistanceInMeters:(double)distanceInMeters { + _distanceInMeters = distanceInMeters; + double displayDistance = _distanceInMeters; + NSString *distanceString = nil; + NSLengthFormatterUnit unit; + NSString *unitString = [_lengthFormatter unitStringFromMeters:displayDistance usedUnit:&unit]; + + switch (unit) { + case NSLengthFormatterUnitCentimeter: + case NSLengthFormatterUnitMillimeter: + unit = NSLengthFormatterUnitMeter; + // Force showing 0 meters if the distance is sufficiently short to be displayed in cm or mm + unitString = [_lengthFormatter unitStringFromValue:0 unit:NSLengthFormatterUnitMeter]; + displayDistance = 0; + break; + default: + break; + } + + // Use HealthKit to convert the unit, so we can use the number formatter directly. + HKUnit *hkUnit = [HKUnit unitFromLengthFormatterUnit:unit]; + double conversionFactor = 1.0; + if ([hkUnit isNull] && (unit == NSLengthFormatterUnitYard)) { + hkUnit = [HKUnit footUnit]; + conversionFactor = 1.0 / 3.0; + } + HKQuantity *quantity = [HKQuantity quantityWithUnit:[HKUnit meterUnit] doubleValue:displayDistance]; + distanceString = [_lengthFormatter.numberFormatter stringFromNumber:@([quantity doubleValueForUnit:hkUnit]*conversionFactor)]; + + [self distanceView].title = [NSString localizedStringWithFormat:ORKLocalizedString(@"FITNESS_DISTANCE_TITLE_FORMAT", nil), unitString]; + [self distanceView].value = distanceString; +} + +- (void)setTimeLeft:(NSTimeInterval)timeLeft { + _timeLeft = timeLeft; + [self updateTimerLabel]; +} + +- (void)updateTimerLabel { + static NSDateComponentsFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [NSDateComponentsFormatter new]; + formatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; + formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad; + formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond; + }); + + NSString *labelString = [formatter stringFromTimeInterval:MAX(round(_timeLeft),0)]; + _timerLabel.text = labelString; + _timerLabel.hidden = (labelString == nil); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.h new file mode 100755 index 0000000..260e02b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Fitness step. + + Displays usual header, a counting-up timer, read outs for distance and/or + heart rate if corresponding recorders are attached. + + Also displays an image during the task. + */ +ORK_CLASS_AVAILABLE +@interface ORKFitnessStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.m new file mode 100755 index 0000000..7a168f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStep.m @@ -0,0 +1,70 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFitnessStep.h" + +#import "ORKFitnessStepViewController.h" + + +@implementation ORKFitnessStep + ++ (Class)stepViewControllerClass { + return [ORKFitnessStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSTimeInterval const ORKFitnessStepMinimumDuration = 5.0; + + if (self.stepDuration < ORKFitnessStepMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"rest duration cannot be shorter than %@ seconds.", @(ORKFitnessStepMinimumDuration)] userInfo:nil]; + } +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKFitnessStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)startsFinished { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.h new file mode 100755 index 0000000..60fe201 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Step view controller corresponding to `ORKFitnessStep`. + + Observes countdown timer, heart rate, and distance, and relays these to the + screen during the task. + */ +ORK_CLASS_AVAILABLE +@interface ORKFitnessStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.m new file mode 100755 index 0000000..4470da2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKFitnessStepViewController.m @@ -0,0 +1,151 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFitnessStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKFitnessContentView.h" +#import "ORKVerticalContainerView.h" + +#import "ORKStepViewController_Internal.h" +#import "ORKHealthQuantityTypeRecorder.h" +#import "ORKPedometerRecorder.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKFitnessStep.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKFitnessStepViewController () { + NSInteger _intendedSteps; + ORKFitnessContentView *_contentView; + NSNumberFormatter *_hrFormatter; +} + +@end + + +@implementation ORKFitnessStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = NO; + } + return self; +} + +- (ORKFitnessStep *)fitnessStep { + return (ORKFitnessStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + _hrFormatter = [[NSNumberFormatter alloc] init]; + _hrFormatter.numberStyle = kCFNumberFormatterNoStyle; + _contentView.timeLeft = self.fitnessStep.stepDuration; + +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + _contentView = [ORKFitnessContentView new]; + _contentView.timeLeft = self.fitnessStep.stepDuration; + self.activeStepView.activeCustomView = _contentView; +} + +- (void)updateHeartRateWithQuantity:(HKQuantitySample *)quantity unit:(HKUnit *)unit { + if (quantity != nil) { + _contentView.hasHeartRate = YES; + } + if (quantity) { + _contentView.heartRate = [_hrFormatter stringFromNumber:@([quantity.quantity doubleValueForUnit:unit])]; + } else { + _contentView.heartRate = @"--"; + } +} + +- (void)updateDistance:(double)distanceInMeters { + _contentView.hasDistance = YES; + _contentView.distanceInMeters = distanceInMeters; + +} + +- (void)recordersDidChange { + [super recordersDidChange]; + + ORKPedometerRecorder *pedometerRecorder = nil; + ORKHealthQuantityTypeRecorder *heartRateRecorder = nil; + for (ORKRecorder *recorder in self.recorders) { + if ([recorder isKindOfClass:[ORKPedometerRecorder class]]) { + pedometerRecorder = (ORKPedometerRecorder *)recorder; + } else if ([recorder isKindOfClass:[ORKHealthQuantityTypeRecorder class]]) { + ORKHealthQuantityTypeRecorder *rec1 = (ORKHealthQuantityTypeRecorder *)recorder; + if ([[[rec1 quantityType] identifier] isEqualToString:HKQuantityTypeIdentifierHeartRate]) { + heartRateRecorder = (ORKHealthQuantityTypeRecorder *)recorder; + } + } + } + + if (heartRateRecorder == nil) { + _contentView.hasHeartRate = NO; + } + _contentView.heartRate = @"--"; + _contentView.hasDistance = (pedometerRecorder != nil); + _contentView.distanceInMeters = 0; + +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + _contentView.timeLeft = finished ? 0 : (timer.duration - timer.runtime); + [super countDownTimerFired:timer finished:finished]; +} + +#pragma mark - ORKHealthQuantityTypeRecorderDelegate + +- (void)healthQuantityTypeRecorderDidUpdate:(ORKHealthQuantityTypeRecorder *)healthQuantityTypeRecorder { + if ([[healthQuantityTypeRecorder.quantityType identifier] isEqualToString:HKQuantityTypeIdentifierHeartRate]) { + [self updateHeartRateWithQuantity:healthQuantityTypeRecorder.lastSample unit:healthQuantityTypeRecorder.unit]; + } +} + +#pragma mark - ORKPedometerRecorderDelegate + +- (void)pedometerRecorderDidUpdate:(ORKPedometerRecorder *)pedometerRecorder { + double distanceInMeters = pedometerRecorder.totalDistance; + [self updateDistance:distanceInMeters]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.h new file mode 100755 index 0000000..d75b8c7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKHealthClinicalTypeRecorder` class represents a recorder for collecting health records data from HealthKit during + an active task. + */ +#if defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0 +ORK_CLASS_AVAILABLE +API_AVAILABLE(ios(12.0)) +@interface ORKHealthClinicalTypeRecorder : ORKRecorder + +@property (nonatomic, copy, readonly) HKClinicalType *healthClinicalType; + +@property (nonatomic, copy, readonly) HKFHIRResourceType healthFHIRResourceType; + +/** + Returns an initialized health clinical type recorder using the specified HKClinicalType and HKFHIRResourceType. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param healthClinicalType The HKClinicalType data that should be collected during the active task. + @param healthFHIRResourceType The HKFHIRResourceType for the predicate used to query the HKClinicalType. + @param step The step that requested this recorder. + @param outputDirectory The directory in which the health records data queried from HealthKit should be stored. + + @return An initialized health quantity type recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + healthClinicalType:(HKClinicalType *)healthClinicalType + healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER API_AVAILABLE(ios(12.0)); + +@end +#endif + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.m new file mode 100755 index 0000000..363d912 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthClinicalTypeRecorder.m @@ -0,0 +1,236 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +#if defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0 + +#import "ORKHealthClinicalTypeRecorder.h" +#import "ORKHelpers_Internal.h" +#import "ORKDataLogger.h" +#import "ORKRecorder_Private.h" +#import "ORKRecorder_Internal.h" +#import "HKSample+ORKJSONDictionary.h" + + +@interface ORKHealthClinicalTypeRecorder () { + ORKDataLogger *_logger; + BOOL _isRecording; + HKHealthStore *_healthStore; + ORKStep *_step; +} + +@end + +@implementation ORKHealthClinicalTypeRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier + healthClinicalType:(HKClinicalType *)healthClinicalType + healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier + step:step + outputDirectory:outputDirectory]; + if (self) { + NSParameterAssert(healthClinicalType != nil); + _healthClinicalType = healthClinicalType; + _healthFHIRResourceType = healthFHIRResourceType; + self.continuesInBackground = YES; + _step = step; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (void)start { + [super start]; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + if (![HKHealthStore isHealthDataAvailable]) { + [self finishRecordingWithError:[NSError errorWithDomain:NSCocoaErrorDomain + code:NSFeatureUnsupportedError + userInfo:@{@"recorder" : self}]]; + return; + } + + if (!_healthStore) { + _healthStore = [HKHealthStore new]; + } + + HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:_healthClinicalType + predicate:_healthFHIRResourceType ? [HKQuery predicateForClinicalRecordsWithFHIRResourceType:_healthFHIRResourceType] : nil limit:HKObjectQueryNoLimit + sortDescriptors:nil + resultsHandler:^(HKSampleQuery * _Nonnull sampleQuery, NSArray<__kindof HKSample *> * _Nullable sampleResults, NSError * _Nullable error) { + NSUInteger resultCount = sampleResults.count; + if (resultCount == 0) { + return; + } + + [sampleResults enumerateObjectsUsingBlock:^(HKClinicalRecord *clinicalRecord, NSUInteger idx, BOOL *stop) { + + NSError *logError = nil; + [_logger append:clinicalRecord.FHIRResource.data error:&logError]; + if (logError) { + ORK_Log_Error("Failed to add health records object to the logger with error: %@", logError); + return; + } + }]; + }]; + + _isRecording = YES; + [_healthStore executeQuery:query]; +} + +- (NSString *)recorderType { + return _healthClinicalType.identifier; +} + +- (void)stop { + if (!_isRecording) { + return; + } + + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (_isRecording) { + _isRecording = NO; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:error]; +} + +- (BOOL)isRecording { + return _isRecording; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +@end + + +@implementation ORKHealthClinicalTypeRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithIdentifier:(NSString *)identifier { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use subclass designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + healthClinicalType:(HKClinicalType *)healthClinicalType + healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType { + self = [super initWithIdentifier:identifier]; + if (self) { + NSParameterAssert(healthClinicalType != nil); + _healthClinicalType = healthClinicalType; + _healthFHIRResourceType = healthFHIRResourceType; + } + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + return [[ORKHealthClinicalTypeRecorder alloc] initWithIdentifier:self.identifier + healthClinicalType:_healthClinicalType + healthFHIRResourceType:_healthFHIRResourceType + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, healthClinicalType, HKClinicalType); + ORK_DECODE_OBJ(aDecoder, healthFHIRResourceType); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, healthClinicalType); + ORK_ENCODE_OBJ(aCoder, healthFHIRResourceType); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.healthClinicalType, castObject.healthClinicalType)&& + ORKEqualObjects(self.healthFHIRResourceType, castObject.healthFHIRResourceType)); +} + +- (NSSet *)requestedHealthKitTypesForReading { + return [NSSet setWithObject:_healthClinicalType]; +} + +@end +#endif diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.h new file mode 100755 index 0000000..8f4b76f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.h @@ -0,0 +1,80 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKHealthQuantityTypeRecorder; + +@protocol ORKHealthQuantityTypeRecorderDelegate + +@optional +- (void)healthQuantityTypeRecorderDidUpdate:(ORKHealthQuantityTypeRecorder *)healthQuantityTypeRecorder; + +@end + + +/** + The `ORKHealthQuantityTypeRecorder` class represents a recorder for collecting real time sample data from HealthKit, such as heart rate, during + an active task. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthQuantityTypeRecorder : ORKRecorder + +@property (nonatomic, copy, readonly) HKQuantityType *quantityType; + +@property (nonatomic, copy, readonly) HKUnit *unit; + +@property (nonatomic, copy, readonly, nullable) HKQuantitySample *lastSample; + +/** + Returns an initialized health quantity type recorder using the specified quantity type and unit. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param quantityType The quantity type that should be collected during the active task. + @param unit The unit for the data that should be collected and serialized. + @param step The step that requested this recorder. + @param outputDirectory The directory in which the HealthKit data should be stored. + + @return An initialized health quantity type recorder. +*/ +- (instancetype)initWithIdentifier:(NSString *)identifier + healthQuantityType:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.m new file mode 100755 index 0000000..d005048 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHealthQuantityTypeRecorder.m @@ -0,0 +1,370 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHealthQuantityTypeRecorder.h" +#import "ORKHelpers_Internal.h" +#import "ORKDataLogger.h" +#import "ORKRecorder_Private.h" +#import "ORKRecorder_Internal.h" +#import "HKSample+ORKJSONDictionary.h" + + +@interface ORKHealthQuantityTypeRecorder () { + ORKDataLogger *_logger; + BOOL _isRecording; + HKHealthStore *_healthStore; + NSPredicate *_samplePredicate; + HKObserverQuery *_observerQuery; + /// Either the HKQueryAnchor object *or* NSUInteger value are tracked since the initializer for + /// iOS 8 and iOS 9 use different objects. Only one will actually be referenced in the initalizer. + HKQueryAnchor *_anchor; + NSUInteger _anchorValue; + HKQuantitySample *_lastSample; +} + +@end + +#ifdef __IPHONE_10_0 +/// Add a protocol defining the initializer for iOS 8 apps. This signature was deprecated in iOS 9 +/// and deleted in iOS 10. +@interface HKAnchoredObjectQuery (iOS8) +- (instancetype)initWithType:(HKSampleType *)type + predicate:(NSPredicate *)predicate + anchor:(NSUInteger)anchor + limit:(NSUInteger)limit + completionHandler:(void (^)(HKAnchoredObjectQuery *query, + NSArray<__kindof HKSample *> *results, + NSUInteger newAnchor, + NSError *error))handler NS_DEPRECATED_IOS(8_0, 9_0); +@end +#endif + +@implementation ORKHealthQuantityTypeRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier + healthQuantityType:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier + step:step + outputDirectory:outputDirectory]; + if (self) { + NSParameterAssert(quantityType != nil); + NSParameterAssert(unit != nil); + // Quantity type and unit are immutable, so should be equivalent to -copy + _quantityType = quantityType; + _unit = unit; + self.continuesInBackground = YES; + _anchorValue = HKAnchoredObjectQueryNoAnchor; + _anchor = [HKQueryAnchor anchorFromValue:_anchorValue]; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (void)updateMostRecentSample:(HKQuantitySample *)sample { + [self willChangeValueForKey:@"lastSample"]; + _lastSample = sample; + [self didChangeValueForKey:@"lastSample"]; + + id delegate = (id)self.delegate; + if (delegate && [delegate respondsToSelector:@selector(healthQuantityTypeRecorderDidUpdate:)]) { + [delegate healthQuantityTypeRecorderDidUpdate:self]; + } +} + +static const NSInteger _HealthAnchoredQueryLimit = 100; + +- (void)query_logResults:(NSArray *)results withAnchor:(HKQueryAnchor*)newAnchor anchorValue:(NSUInteger)anchorValue { + + NSUInteger resultCount = results.count; + if (resultCount == 0) { + return; + } + + // Do conversion to dictionary on whatever queue we happen to be on. + NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:resultCount]; + [results enumerateObjectsUsingBlock:^(HKQuantitySample *sample, NSUInteger idx, BOOL *stop) { + [dictionaries addObject:[sample ork_JSONDictionaryWithOptions:ORKSampleIncludeSource|ORKSampleIncludeMetadata unit:_unit]]; + }]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateMostRecentSample:results.lastObject]; + + NSError *error = nil; + if (![_logger appendObjects:dictionaries error:&error]) { + // Logger writes are unrecoverable + [self finishRecordingWithError:error]; + return; + } + + _anchor = newAnchor; + _anchorValue = anchorValue; + + if (resultCount == _HealthAnchoredQueryLimit) { + // Do another fetch immediately rather than wait for an observation + [self doFetchNewData]; + } + }); +} + +- (void)doFetchNewData { + if (!_healthStore || !_isRecording) { + return; + } + NSAssert(_samplePredicate != nil, @"Sample predicate should be non-nil if recording"); + + __weak typeof(self) weakSelf = self; + void (^handleResults)(NSArray <__kindof HKSample *> *, HKQueryAnchor *, NSUInteger, NSError *) = ^ (NSArray *results, HKQueryAnchor *newAnchor, NSUInteger newAnchorValue, NSError *error) { + if (error) { + // An error in the query's not the end of the world: we'll probably get another chance. Just log it. + ORK_Log_Error("Anchored query error: %@", error); + return; + } + + __typeof(self) strongSelf = weakSelf; + [strongSelf query_logResults:results withAnchor:newAnchor anchorValue:newAnchorValue]; + }; + + + HKAnchoredObjectQuery *anchoredQuery; + if ([HKAnchoredObjectQuery instancesRespondToSelector:@selector(initWithType:predicate:anchor:limit:resultsHandler:)]) { + + anchoredQuery = [[HKAnchoredObjectQuery alloc] initWithType:_quantityType + predicate:_samplePredicate + anchor:_anchor + limit:_HealthAnchoredQueryLimit + resultsHandler: + ^(HKAnchoredObjectQuery *query, NSArray *sampleObjects, NSArray *deletedObjects, HKQueryAnchor *newAnchor, NSError *error) { + handleResults(sampleObjects, newAnchor, 0, error); + }]; + } else if ([HKAnchoredObjectQuery instancesRespondToSelector:@selector(initWithType:predicate:anchor:limit:completionHandler:)]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + anchoredQuery = [[HKAnchoredObjectQuery alloc] initWithType:_quantityType + predicate:_samplePredicate + anchor:_anchorValue + limit:_HealthAnchoredQueryLimit + completionHandler: + ^(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> *results, NSUInteger newAnchor, NSError *error) { + handleResults(results, nil, newAnchor, error); + }]; +#pragma clang diagnostic pop + } + else { + NSAssert(NO, @"Could not instantiate an HKAnchoredObjectQuery."); + } + + [_healthStore executeQuery:anchoredQuery]; +} + +- (void)start { + [super start]; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + if (![HKHealthStore isHealthDataAvailable]) { + [self finishRecordingWithError:[NSError errorWithDomain:NSCocoaErrorDomain + code:NSFeatureUnsupportedError + userInfo:@{@"recorder" : self}]]; + return; + } + + if (!_healthStore) { + // Get a new obsever query + _healthStore = [HKHealthStore new]; + } else { + // Reset + if (_observerQuery) { + [_healthStore stopQuery:_observerQuery]; + _observerQuery = nil; + } + } + + _lastSample = nil; + _samplePredicate = [HKQuery predicateForSamplesWithStartDate:[NSDate date] endDate:nil options:HKQueryOptionStrictStartDate]; + + NSAssert(!_observerQuery, @"observer query should not exist if not recording"); + + __weak __typeof(self) weakSelf = self; + _observerQuery = [[HKObserverQuery alloc] + initWithSampleType:_quantityType + predicate:_samplePredicate + updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error) { + __typeof(self) strongSelf = weakSelf; + + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + [strongSelf finishRecordingWithError:error]; + } else { + [strongSelf doFetchNewData]; + } + }); + + // Immediately signal receipt. We've fired off to either finish or do a new fetch. + completionHandler(); + + }]; + + _isRecording = YES; + [_healthStore executeQuery:_observerQuery]; +} + +- (NSString *)recorderType { + return _quantityType.identifier; +} + +- (void)stop { + if (!_isRecording) { + return; + } + + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (_isRecording) { + NSAssert(_observerQuery != nil, @"Observer query should be non-nil when recording"); + [_healthStore stopQuery:_observerQuery]; + _observerQuery = nil; + + _samplePredicate = nil; + _isRecording = NO; + + [self updateMostRecentSample:nil]; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:error]; +} + +- (BOOL)isRecording { + return _isRecording; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +@end + + +@implementation ORKHealthQuantityTypeRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithIdentifier:(NSString *)identifier { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use subclass designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier healthQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit { + self = [super initWithIdentifier:identifier]; + if (self) { + NSParameterAssert(quantityType != nil); + NSParameterAssert(unit != nil); + // Quantity type and unit are immutable, so should be equivalent to -copy + _quantityType = quantityType; + _unit = unit; + } + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return [[ORKHealthQuantityTypeRecorder alloc] initWithIdentifier:self.identifier + healthQuantityType:_quantityType + unit:_unit + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, quantityType, HKQuantityType); + ORK_DECODE_OBJ_CLASS(aDecoder, unit, HKUnit); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, quantityType); + ORK_ENCODE_OBJ(aCoder, unit); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.quantityType, castObject.quantityType)&& + ORKEqualObjects(self.unit, castObject.unit)); +} + +- (NSSet *)requestedHealthKitTypesForReading { + return [NSSet setWithObject:_quantityType]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.h new file mode 100755 index 0000000..cc025ca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKHolePegTestPlaceContentViewDelegate; + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestPlaceContentView : ORKActiveStepCustomView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithMovingDirection:(ORKBodySagittal)movingDirection rotated:(BOOL)rotated NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, assign) ORKBodySagittal movingDirection; +@property (nonatomic, assign) double threshold; +@property (nonatomic, assign, getter = isRotated) BOOL rotated; +@property (nonatomic, weak) id delegate; + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; + +@end + + +@protocol ORKHolePegTestPlaceContentViewDelegate + +- (void)holePegTestPlaceDidProgress:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView; +- (void)holePegTestPlaceDidSucceed:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView withDistance:(CGFloat)distance; +- (void)holePegTestPlaceDidFail:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.m new file mode 100755 index 0000000..d003882 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceContentView.m @@ -0,0 +1,373 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestPlaceContentView.h" + +#import "ORKDirectionView.h" +#import "ORKHolePegTestPlaceHoleView.h" +#import "ORKHolePegTestPlacePegView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const CGFloat ORKOrientationThreshold = 12.0f; +static const CGFloat ORKHolePegViewDiameter = 88.0f; +#define degreesToRadians(degrees) ((degrees) / 180.0 * M_PI) + + +@interface ORKHolePegTestPlaceContentView () + +@property (nonatomic, strong) UIProgressView *progressView; +@property (nonatomic, strong) ORKHolePegTestPlacePegView *pegView; +@property (nonatomic, strong) ORKHolePegTestPlaceHoleView *holeView; +@property (nonatomic, strong) ORKDirectionView *directionView; +@property (nonatomic, copy) NSArray *constraints; + +@property (nonatomic, strong) UIPinchGestureRecognizer *pinchRecognizer; +@property (nonatomic, strong) UIPanGestureRecognizer *panRecognizer; +@property (nonatomic, strong) UIRotationGestureRecognizer *rotationRecognizer; +@property (nonatomic, assign, getter = isMovable) BOOL movable; +@property (nonatomic, assign, getter = hasMoveEnded) BOOL moveEnded; +@property (nonatomic, assign) CGFloat rotation; +@property (nonatomic, assign) CGFloat rotationOffset; +@property (nonatomic, assign) CGPoint translation; +@property (nonatomic, assign) CGPoint translationOffset; +@property (nonatomic, assign) CGPoint startPoint; + +@end + + +@implementation ORKHolePegTestPlaceContentView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithMovingDirection:(ORKBodySagittal)movingDirection rotated:(BOOL)rotated { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.movingDirection = movingDirection; + self.rotated = rotated; + + self.progressView = [UIProgressView new]; + self.progressView.progressTintColor = self.tintColor; + [self.progressView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.progressView setAlpha:0]; + [self addSubview:self.progressView]; + + self.holeView = [[ORKHolePegTestPlaceHoleView alloc] initWithFrame:CGRectMake(0, 0, ORKHolePegViewDiameter, ORKHolePegViewDiameter)]; + self.holeView.rotated = self.isRotated; + [self.holeView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:self.holeView]; + + self.pegView = [[ORKHolePegTestPlacePegView alloc] initWithFrame:CGRectMake(0, 0, ORKHolePegViewDiameter, ORKHolePegViewDiameter)]; + self.pegView.rotated = self.isRotated; + [self.pegView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:self.pegView]; + + self.directionView = [[ORKDirectionView alloc] initWithOrientation:(self.movingDirection == ORKBodySagittalLeft) ? ORKBodySagittalRight : ORKBodySagittalLeft]; + [self.directionView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:self.directionView]; + + [self setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self setNeedsUpdateConstraints]; + + self.movable = NO; + self.moveEnded = NO; + self.startPoint = CGPointZero; + + self.pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self + action:@selector(handlePinch:)]; + self.pinchRecognizer.delegate = self; + [self addGestureRecognizer:self.pinchRecognizer]; + + self.panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self + action:@selector(handlePan:)]; + self.panRecognizer.delegate = self; + [self addGestureRecognizer:self.panRecognizer]; + + if (rotated) { + self.rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self + action:@selector(handleRotate:)]; + self.rotationRecognizer.delegate = self; + [self addGestureRecognizer:self.rotationRecognizer]; + } + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.progressView.progressTintColor = self.tintColor; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; +} + +- (void)updateConstraints { + if ([self.constraints count]) { + [NSLayoutConstraint deactivateConstraints:self.constraints]; + self.constraints = nil; + } + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _pegView, _holeView, _directionView); + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:(self.movingDirection == ORKBodySagittalLeft) ? @"H:|-[_pegView]->=0-[_holeView]-|" : @"H:|-[_holeView]->=0-[_pegView]-|" + options:NSLayoutFormatAlignAllCenterY + metrics:nil views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_progressView]" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.pegView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.directionView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.directionView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + self.constraints = constraintsArray; + [self addConstraints:self.constraints]; + + [NSLayoutConstraint activateConstraints:self.constraints]; + [super updateConstraints]; +} + +#pragma mark - gesture recognizer methods + +- (void)pickupPegWithGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { + CGPoint touch = [gestureRecognizer locationInView:self]; + CGPoint touch1 = [gestureRecognizer locationOfTouch:0 inView:self]; + CGPoint touch2 = [gestureRecognizer locationOfTouch:1 inView:self]; + double distance = hypot(touch1.x - touch2.x, touch1.y - touch2.y); + + if (distance < 3 * CGRectGetWidth(self.pegView.frame) && + CGRectContainsPoint(self.pegView.frame, touch)) { + self.movable = YES; + } else { + self.movable = NO; + } +} + +- (void)handlePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer { + if ([pinchGestureRecognizer numberOfTouches] == 2) { + [self pickupPegWithGestureRecognizer:pinchGestureRecognizer]; + } +} + +- (void)handlePan:(UIPanGestureRecognizer *)panGestureRecognizer { + if ([panGestureRecognizer numberOfTouches] != 2 || + panGestureRecognizer.state == UIGestureRecognizerStateEnded || + panGestureRecognizer.state == UIGestureRecognizerStateCancelled || + panGestureRecognizer.state == UIGestureRecognizerStateFailed) { + [self resetTransformAtPoint:[panGestureRecognizer locationInView:self]]; + } else { + if (self.isMovable) { + self.translation = CGPointMake([panGestureRecognizer translationInView:self].x - self.translationOffset.x, + [panGestureRecognizer translationInView:self].y - self.translationOffset.y); + [self updateTransformAtPoint:[panGestureRecognizer locationInView:self]]; + } else { + self.translationOffset = CGPointMake([panGestureRecognizer translationInView:self].x - self.translation.x, + [panGestureRecognizer translationInView:self].y - self.translation.y); + if (CGPointEqualToPoint(self.startPoint, CGPointZero)) { + [self pickupPegWithGestureRecognizer:panGestureRecognizer]; + } + } + } +} + +- (void)handleRotate:(UIRotationGestureRecognizer *)rotationGestureRecognizer { + if ([rotationGestureRecognizer numberOfTouches] != 2 || + rotationGestureRecognizer.state == UIGestureRecognizerStateEnded || + rotationGestureRecognizer.state == UIGestureRecognizerStateCancelled || + rotationGestureRecognizer.state == UIGestureRecognizerStateFailed) { + [self resetTransformAtPoint:[rotationGestureRecognizer locationInView:self]]; + } else { + if (self.isMovable) { + self.rotation = rotationGestureRecognizer.rotation - self.rotationOffset; + [self updateTransformAtPoint:[rotationGestureRecognizer locationInView:self]]; + } else { + self.rotationOffset = rotationGestureRecognizer.rotation - self.rotation; + } + } +} + +- (void)updateTransformAtPoint:(CGPoint)point { + self.pegView.transform = CGAffineTransformMakeTranslation(self.translation.x, self.translation.y); + self.pegView.transform = CGAffineTransformRotate(self.pegView.transform, self.rotation); + [self pegViewDidMoveAtPoint:point]; +} + +- (void)resetTransformAtPoint:(CGPoint)point { + if (!self.hasMoveEnded) { + self.movable = NO; + self.moveEnded = YES; + + self.pinchRecognizer.enabled = NO; + self.panRecognizer.enabled = NO; + self.rotationRecognizer.enabled = NO; + + BOOL animated = ![self pegViewMoveDidEndAtPoint:point]; + self.pegView.hidden = !animated; + + [UIView animateWithDuration:animated ? 0.15f : 0.0f + delay:0.0f + options:UIViewAnimationOptionCurveEaseOut + animations:^(){ + self.pegView.transform = CGAffineTransformIdentity; + self.pegView.alpha = 1.0f; + } + completion:^(BOOL finished){ + self.rotation = 0.0f; + self.rotationOffset = 0.0f; + self.translation = CGPointZero; + self.translationOffset = CGPointZero; + self.pinchRecognizer.enabled = YES; + self.panRecognizer.enabled = YES; + self.rotationRecognizer.enabled = YES; + self.moveEnded = NO; + self.pegView.hidden = NO; + }]; + } +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer +shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return YES; +} + +#pragma mark - peg view delegate + +- (void)pegViewDidMoveAtPoint:(CGPoint)point { + self.directionView.hidden = YES; + + if (CGPointEqualToPoint(self.startPoint, CGPointZero)) { + self.startPoint = point; + } + + if ([self.delegate respondsToSelector:@selector(holePegTestPlaceDidProgress:)]) { + [self.delegate holePegTestPlaceDidProgress:self]; + } + + if (self.holeView.isSuccess) { + self.holeView.success = NO; + } + + if ([self holeViewContainsPegView]) { + self.pegView.alpha = 1.0f; + } else { + self.pegView.alpha = 0.2f; + } +} + +- (BOOL)pegViewMoveDidEndAtPoint:(CGPoint)point { + self.directionView.hidden = NO; + + BOOL succeeded = NO; + if ([self holeViewContainsPegView]) { + if ([self.delegate respondsToSelector:@selector(holePegTestPlaceDidSucceed:withDistance:)]) { + CGFloat distance = hypotf(point.x - self.startPoint.x, point.y - self.startPoint.y); + [self.delegate holePegTestPlaceDidSucceed:self withDistance:distance]; + } + self.holeView.success = YES; + succeeded = YES; + } else { + if ([self.delegate respondsToSelector:@selector(holePegTestPlaceDidFail:)]) { + [self.delegate holePegTestPlaceDidFail:self]; + } + self.holeView.success = NO; + } + self.startPoint = CGPointZero; + return succeeded; +} + +- (BOOL)holeViewContainsPegView { + CGRect detectionFrame = CGRectMake(CGRectGetMidX(self.holeView.frame) - (self.threshold * CGRectGetWidth(self.holeView.frame) / 2), + CGRectGetMidY(self.holeView.frame) - (self.threshold * CGRectGetHeight(self.holeView.frame) / 2), + self.threshold * CGRectGetWidth(self.holeView.frame), + self.threshold * CGRectGetHeight(self.holeView.frame)); + + CGPoint pegCenter = CGPointMake(CGRectGetMaxX(self.pegView.frame) - CGRectGetWidth(self.pegView.frame) / 2, + CGRectGetMaxY(self.pegView.frame) - CGRectGetHeight(self.pegView.frame) / 2); + + if (CGRectContainsPoint(detectionFrame, pegCenter)) { + if (self.isRotated) { + double rotation = atan2(self.pegView.transform.b, self.pegView.transform.a); + double angle = fmod(fabs(rotation), M_PI_2); + if (angle > M_PI_4 - degreesToRadians(ORKOrientationThreshold) && + angle < M_PI_4 + degreesToRadians(ORKOrientationThreshold)) { + return YES; + } + } else { + return YES; + } + } + + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.h new file mode 100755 index 0000000..8b26dff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestPlaceHoleView : UIView + +@property (nonatomic, assign, getter = isRotated) BOOL rotated; +@property (nonatomic, assign, getter = isSuccess) BOOL success; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.m new file mode 100755 index 0000000..59a186d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceHoleView.m @@ -0,0 +1,173 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestPlaceHoleView.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat ORKPlaceHoleViewRotation = 45.0f; + + +@interface ORKHolePegTestPlaceHoleView () + +@property (nonatomic, strong) CAShapeLayer *checkLayer; +@property (nonatomic, strong) CAShapeLayer *crossLayer; + +@end + + +@implementation ORKHolePegTestPlaceHoleView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + UIBezierPath *path = [[UIBezierPath alloc] init]; + [path moveToPoint:CGPointMake(27.7f, 46.9f)]; + [path addLineToPoint:CGPointMake(36.1f, 56.3f)]; + [path addLineToPoint:CGPointMake(62.8f, 30.3f)]; + path.lineCapStyle = kCGLineCapRound; + path.lineWidth = 3.6f; + + CAShapeLayer *checkLayer = [CAShapeLayer new]; + checkLayer.path = path.CGPath; + checkLayer.lineWidth = 3.6f; + checkLayer.lineCap = kCALineCapRound; + checkLayer.lineJoin = kCALineJoinRound; + checkLayer.frame = self.layer.bounds; + checkLayer.strokeColor = self.tintColor.CGColor; + checkLayer.backgroundColor = [UIColor clearColor].CGColor; + checkLayer.fillColor = nil; + self.checkLayer = checkLayer; + + self.opaque = NO; + self.success = NO; + } + + return self; +} + +- (CGSize)intrinsicContentSize { + return CGSizeMake(self.frame.size.width, self.frame.size.height); +} + +#pragma mark - drawing method + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.checkLayer.strokeColor = self.tintColor.CGColor; + [self setNeedsDisplay]; +} + +- (void)setSuccess:(BOOL)success +{ + _success = success; + [self.checkLayer removeFromSuperlayer]; + [self.crossLayer removeFromSuperlayer]; + [self setNeedsDisplay]; +} + +- (void)setRotated:(BOOL)rotated +{ + _rotated = rotated; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + CGRect bounds = self.bounds; + UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectInset(bounds, 1.0f, 1.0f)]; + path.lineWidth = 2.0f; + [self.tintColor setStroke]; + [path stroke]; + + if (self.isSuccess) { + [self.layer addSublayer:self.checkLayer]; + + CAMediaTimingFunction *timing = [[CAMediaTimingFunction alloc] initWithControlPoints:0.180739998817444 + :0 + :0.577960014343262 + :0.918200016021729]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + [animation setTimingFunction:timing]; + [animation setFillMode:kCAFillModeBoth]; + animation.fromValue = @(0); + animation.toValue = @(1); + animation.duration = 0.3f; + animation.delegate = self; + [self.checkLayer addAnimation:animation forKey:@"strokeEnd"]; + } else if (self.isRotated) { + UIBezierPath *crossPath = [[UIBezierPath alloc] init]; + [crossPath moveToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 1/4)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 7/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 1/4, CGRectGetHeight(bounds) * 7/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 1/4, CGRectGetHeight(bounds) * 9/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 9/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 3/4)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 3/4)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 9/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 3/4, CGRectGetHeight(bounds) * 9/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 3/4, CGRectGetHeight(bounds) * 7/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 7/16)]; + [crossPath addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 1/4)]; + [crossPath closePath]; + + CAShapeLayer *crossLayer = [[CAShapeLayer alloc] init]; + crossLayer.path = crossPath.CGPath; + crossLayer.bounds = CGPathGetBoundingBox(crossLayer.path); + crossLayer.anchorPoint = CGPointMake(0.5, 0.5); + crossLayer.fillColor = self.tintColor.CGColor; + + CATransform3D transform = CATransform3DMakeTranslation(CGRectGetMidX(bounds), CGRectGetMidY(bounds), 1); + transform = CATransform3DRotate(transform, ORKPlaceHoleViewRotation * (M_PI / 180), 0, 0, 1); + crossLayer.transform = transform; + + self.crossLayer = crossLayer; + + [self.layer addSublayer:self.crossLayer]; + } + + CGContextRestoreGState(context); +} + +- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag { + ORKWeakTypeOf(self) weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.7f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + strongSelf.success = NO; + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.h new file mode 100755 index 0000000..bc8ea9d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestPlacePegView : UIView + +@property (nonatomic, assign, getter = isRotated) BOOL rotated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.m new file mode 100755 index 0000000..b6d8cb9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlacePegView.m @@ -0,0 +1,93 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestPlacePegView.h" + + +@implementation ORKHolePegTestPlacePegView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + self.opaque = NO; + } + + return self; +} + +- (CGSize)intrinsicContentSize { + return CGSizeMake(self.frame.size.width, self.frame.size.height); +} + +#pragma mark - drawing method + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self setNeedsDisplay]; +} + +- (void)setRotated:(BOOL)rotated +{ + _rotated = rotated; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + CGRect bounds = self.bounds; + UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:bounds]; + + if (self.isRotated) { + [path moveToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 1/4)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 7/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 1/4, CGRectGetHeight(bounds) * 7/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 1/4, CGRectGetHeight(bounds) * 9/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 9/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 7/16, CGRectGetHeight(bounds) * 3/4)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 3/4)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 9/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 3/4, CGRectGetHeight(bounds) * 9/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 3/4, CGRectGetHeight(bounds) * 7/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 7/16)]; + [path addLineToPoint:CGPointMake(CGRectGetWidth(bounds) * 9/16, CGRectGetHeight(bounds) * 1/4)]; + [path closePath]; + } + + [self.tintColor setFill]; + [path fill]; + + CGContextRestoreGState(context); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.h new file mode 100755 index 0000000..5c34a10 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestPlaceStep : ORKActiveStep + +@property (nonatomic, assign) ORKBodySagittal movingDirection; +@property (nonatomic, assign, getter = isDominantHandTested) BOOL dominantHandTested; +@property (nonatomic, assign) NSInteger numberOfPegs; +@property (nonatomic, assign) double threshold; +@property (nonatomic, assign, getter = isRotated) BOOL rotated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.m new file mode 100755 index 0000000..e17654f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStep.m @@ -0,0 +1,136 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestPlaceStep.h" +#import "ORKHolePegTestPlaceStepViewController.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKHolePegTestPlaceStep + ++ (Class)stepViewControllerClass { + return [ORKHolePegTestPlaceStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + int const ORKHolePegTestMinimumNumberOfPegs = 1; + + double const ORKHolePegTestMinimumThreshold = 0.0f; + double const ORKHolePegTestMaximumThreshold = 1.0f; + + NSTimeInterval const ORKHolePegTestMinimumDuration = 1.0f; + + if (self.movingDirection != ORKBodySagittalLeft && + self.movingDirection != ORKBodySagittalRight) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"moving direction should be left or right."] userInfo:nil]; + } + + if (self.numberOfPegs < ORKHolePegTestMinimumNumberOfPegs) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"number of pegs must be greater than or equal to %@.", @(ORKHolePegTestMinimumNumberOfPegs)] userInfo:nil]; + } + + if (self.threshold < ORKHolePegTestMinimumThreshold || + self.threshold > ORKHolePegTestMaximumThreshold) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"threshold must be greater than or equal to %@ and lower or equal to %@.", @(ORKHolePegTestMinimumThreshold), @(ORKHolePegTestMaximumThreshold)] userInfo:nil]; + } + + if (self.stepDuration < ORKHolePegTestMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKHolePegTestMinimumDuration)] userInfo:nil]; + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, movingDirection); + ORK_DECODE_BOOL(aDecoder, dominantHandTested); + ORK_DECODE_INTEGER(aDecoder, numberOfPegs); + ORK_DECODE_DOUBLE(aDecoder, threshold); + ORK_DECODE_BOOL(aDecoder, rotated); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, movingDirection); + ORK_ENCODE_BOOL(aCoder, dominantHandTested); + ORK_ENCODE_INTEGER(aCoder, numberOfPegs); + ORK_ENCODE_DOUBLE(aCoder, threshold); + ORK_ENCODE_BOOL(aCoder, rotated); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) step = [super copyWithZone:zone]; + step.movingDirection = self.movingDirection; + step.dominantHandTested = self.dominantHandTested; + step.numberOfPegs = self.numberOfPegs; + step.threshold = self.threshold; + step.rotated = self.rotated; + return step; +} + +- (NSUInteger)hash { + return [super hash] ^ self.movingDirection ^ self.dominantHandTested ^ self.numberOfPegs ^ (NSInteger)(self.threshold * 100) ^ self.rotated; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.movingDirection == castObject.movingDirection) && + (self.dominantHandTested == castObject.dominantHandTested) && + (self.numberOfPegs == castObject.numberOfPegs) && + (self.threshold == castObject.threshold) && + (self.rotated == castObject.rotated)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.h new file mode 100755 index 0000000..978640f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestPlaceStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.m new file mode 100755 index 0000000..b66ba10 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestPlaceStepViewController.m @@ -0,0 +1,179 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestPlaceStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKHolePegTestPlaceContentView.h" +#import "ORKStepContainerView_Private.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKHolePegTestPlaceStep.h" +#import "ORKHolePegTestResult.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + + +@interface ORKHolePegTestPlaceStepViewController () + +@property (nonatomic, strong) NSMutableArray *samples; +@property (nonatomic, strong) ORKHolePegTestPlaceContentView *holePegTestPlaceContentView; +@property (nonatomic, assign) NSTimeInterval sampleStart; +@property (nonatomic, assign) NSUInteger successes; +@property (nonatomic, assign) NSUInteger failures; + +@end + + +@implementation ORKHolePegTestPlaceStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (ORKHolePegTestPlaceStep *)holePegTestPlaceStep { + return (ORKHolePegTestPlaceStep *)self.step; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.holePegTestPlaceContentView = [[ORKHolePegTestPlaceContentView alloc] initWithMovingDirection:[self holePegTestPlaceStep].movingDirection + rotated:[self holePegTestPlaceStep].rotated]; + self.holePegTestPlaceContentView.threshold = [self holePegTestPlaceStep].threshold; + self.holePegTestPlaceContentView.delegate = self; + self.activeStepView.activeCustomView = self.holePegTestPlaceContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; +} + +#pragma mark - step life cycle methods + +- (void)start { + self.successes = 0; + self.failures = 0; + self.samples = [NSMutableArray array]; + [self.holePegTestPlaceContentView setProgress:0.001f animated:NO]; + + [super start]; +} + +#pragma mark - result methods + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKHolePegTestResult *holePegTestResult = [[ORKHolePegTestResult alloc] initWithIdentifier:self.step.identifier]; + holePegTestResult.movingDirection = [self holePegTestPlaceStep].movingDirection; + holePegTestResult.dominantHandTested = [self holePegTestPlaceStep].isDominantHandTested; + holePegTestResult.numberOfPegs = [self holePegTestPlaceStep].numberOfPegs; + holePegTestResult.threshold = [self holePegTestPlaceStep].threshold; + holePegTestResult.rotated = [self holePegTestPlaceStep].isRotated; + holePegTestResult.totalSuccesses = self.successes; + holePegTestResult.totalFailures = self.failures; + holePegTestResult.totalTime = [self holePegTestPlaceStep].stepDuration - self.timeRemaining; + double totalDistance = 0.0; + for (ORKHolePegTestSample *sample in self.samples) { + totalDistance += sample.distance; + } + holePegTestResult.totalDistance = totalDistance; + holePegTestResult.samples = self.samples; + + [results addObject:holePegTestResult]; + + sResult.results = [results copy]; + + return sResult; +} + +- (void)saveSampleWithDistance:(CGFloat)distance { + ORKHolePegTestSample *sample = [[ORKHolePegTestSample alloc] init]; + sample.time = CACurrentMediaTime() - self.sampleStart; + sample.distance = distance; + self.sampleStart = CACurrentMediaTime(); + + [self.samples addObject:sample]; +} + +#pragma mark - hole peg test content view delegate + +- (void)holePegTestPlaceDidProgress:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView { + if (!self.isStarted) { + self.sampleStart = CACurrentMediaTime(); + [self start]; + } + + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestPlaceStep].movingDirection == ORKBodySagittalRight ? ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT_2", nil)]]]; +} + +- (void)holePegTestPlaceDidSucceed:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView withDistance:(CGFloat)distance { + self.successes++; + + [self saveSampleWithDistance:distance]; + + [holePegTestPlaceContentView setProgress:((CGFloat)self.successes / [self holePegTestPlaceStep].numberOfPegs) animated:YES]; + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestPlaceStep].movingDirection == ORKBodySagittalRight ? ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]]; + + if (self.successes >= [self holePegTestPlaceStep].numberOfPegs) { + [((ORKNavigableOrderedTask *)self.taskViewController.task) removeNavigationRuleForTriggerStepIdentifier:[self holePegTestPlaceStep].identifier]; + [self finish]; + } +} + +- (void)holePegTestPlaceDidFail:(ORKHolePegTestPlaceContentView *)holePegTestPlaceContentView { + self.failures++; + + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestPlaceStep].movingDirection == ORKBodySagittalRight ? ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.h new file mode 100755 index 0000000..71bb94c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.h @@ -0,0 +1,65 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKHolePegTestRemoveContentViewDelegate; + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestRemoveContentView : ORKActiveStepCustomView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithMovingDirection:(ORKBodySagittal)movingDirection NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, assign) ORKBodySagittal movingDirection; +@property (nonatomic, assign) double threshold; +@property (nonatomic, weak) id delegate; + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; + +@end + + +@protocol ORKHolePegTestRemoveContentViewDelegate + +- (void)holePegTestRemoveDidProgress:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView; +- (void)holePegTestRemoveDidSucceed:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView withDistance:(CGFloat)distance; +- (void)holePegTestRemoveDidFail:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.m new file mode 100755 index 0000000..a5404b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveContentView.m @@ -0,0 +1,343 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestRemoveContentView.h" + +#import "ORKDirectionView.h" +#import "ORKHolePegTestRemovePegView.h" +#import "ORKSeparatorView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const CGFloat PegViewDiameter = 88.0f; +static const CGFloat PegViewSeparatorWidth = 2.0f; + + +@interface ORKHolePegTestRemoveContentView () + +@property (nonatomic, strong) UIProgressView *progressView; +@property (nonatomic, strong) ORKHolePegTestRemovePegView *pegView; +@property (nonatomic, strong) ORKSeparatorView *separatorView; +@property (nonatomic, strong) ORKDirectionView *directionView; +@property (nonatomic, strong) UIView *container; +@property (nonatomic, copy) NSArray *constraints; + +@property (nonatomic, strong) UIPinchGestureRecognizer *pinchRecognizer; +@property (nonatomic, strong) UIPanGestureRecognizer *panRecognizer; +@property (nonatomic, assign, getter = isMovable) BOOL movable; +@property (nonatomic, assign, getter = hasMoveEnded) BOOL moveEnded; +@property (nonatomic, assign) CGPoint translation; +@property (nonatomic, assign) CGPoint translationOffset; +@property (nonatomic, assign) CGPoint startPoint; + +@end + + +@implementation ORKHolePegTestRemoveContentView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithMovingDirection:(ORKBodySagittal)movingDirection { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.movingDirection = movingDirection; + self.opaque = NO; + + self.container = [UIView new]; + self.container.translatesAutoresizingMaskIntoConstraints = NO; + + self.progressView = [UIProgressView new]; + self.progressView.progressTintColor = self.tintColor; + [self.progressView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.progressView setAlpha:0]; + [self addSubview:self.progressView]; + + self.pegView = [[ORKHolePegTestRemovePegView alloc] initWithFrame:CGRectMake(0, 0, PegViewDiameter, PegViewDiameter)]; + [self.pegView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.container addSubview:self.pegView]; + + self.separatorView = [[ORKSeparatorView alloc] init]; + [self.separatorView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.container addSubview:self.separatorView]; + + self.directionView = [[ORKDirectionView alloc] initWithOrientation:(self.movingDirection == ORKBodySagittalLeft) ? ORKBodySagittalRight : ORKBodySagittalLeft]; + [self.directionView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:self.directionView]; + + [self addSubview:self.container]; + + [self setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self setNeedsUpdateConstraints]; + + self.movable = NO; + self.moveEnded = NO; + self.startPoint = CGPointZero; + + self.pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self + action:@selector(handlePinch:)]; + self.pinchRecognizer.delegate = self; + [self addGestureRecognizer:self.pinchRecognizer]; + + self.panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self + action:@selector(handlePan:)]; + self.panRecognizer.delegate = self; + [self addGestureRecognizer:self.panRecognizer]; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.progressView.progressTintColor = self.tintColor; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; +} + +- (void)updateConstraints { + if ([self.constraints count]) { + [NSLayoutConstraint deactivateConstraints:self.constraints]; + self.constraints = nil; + } + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _container, _pegView, _separatorView, _directionView); + NSDictionary *metrics = @{@"diameter": @(PegViewDiameter), @"separator": @(PegViewSeparatorWidth), @"margin": @((1 + self.threshold) * PegViewDiameter)}; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:(self.movingDirection == ORKBodySagittalLeft) ? @"H:|-[_pegView(diameter)]->=0-[_separatorView(separator)]-(margin)-|" : @"H:|-(margin)-[_separatorView(separator)]->=0-[_pegView(diameter)]-|" + options:NSLayoutFormatAlignAllCenterY + metrics:metrics views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_container]|" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_pegView(diameter)]-(>=0)-|" + options:(NSLayoutFormatOptions)0 + metrics:metrics views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_separatorView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_progressView][_container]|" + options:(NSLayoutFormatOptions)0 + metrics:metrics views:views]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.directionView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.directionView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + self.constraints = constraintsArray; + [self addConstraints:self.constraints]; + + [NSLayoutConstraint activateConstraints:self.constraints]; + [super updateConstraints]; +} + +#pragma mark - gesture recognizer methods + +- (void)pickupPegWithGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { + CGPoint touch = [gestureRecognizer locationInView:self]; + CGPoint touch1 = [gestureRecognizer locationOfTouch:0 inView:self]; + CGPoint touch2 = [gestureRecognizer locationOfTouch:1 inView:self]; + double distance = hypot(touch1.x - touch2.x, touch1.y - touch2.y); + + if (distance < 3 * CGRectGetWidth(self.pegView.frame) && + CGRectContainsPoint(self.pegView.frame, touch)) { + self.movable = YES; + } else { + self.movable = NO; + } +} + +- (void)handlePinch:(UIPinchGestureRecognizer *)pinchGestureRecognizer { + if ([pinchGestureRecognizer numberOfTouches] == 2) { + [self pickupPegWithGestureRecognizer:pinchGestureRecognizer]; + } +} + +- (void)handlePan:(UIPanGestureRecognizer *)panGestureRecognizer { + if ([panGestureRecognizer numberOfTouches] != 2 || + panGestureRecognizer.state == UIGestureRecognizerStateEnded || + panGestureRecognizer.state == UIGestureRecognizerStateCancelled || + panGestureRecognizer.state == UIGestureRecognizerStateFailed) { + [self resetTransformAtPoint:[panGestureRecognizer locationInView:self]]; + } else { + if (self.isMovable) { + self.translation = CGPointMake([panGestureRecognizer translationInView:self].x - self.translationOffset.x, + [panGestureRecognizer translationInView:self].y - self.translationOffset.y); + [self updateTransformAtPoint:[panGestureRecognizer locationInView:self]]; + } else { + self.translationOffset = CGPointMake([panGestureRecognizer translationInView:self].x - self.translation.x, + [panGestureRecognizer translationInView:self].y - self.translation.y); + if (CGPointEqualToPoint(self.startPoint, CGPointZero)) { + [self pickupPegWithGestureRecognizer:panGestureRecognizer]; + } + } + } +} + +- (void)updateTransformAtPoint:(CGPoint)point { + self.pegView.transform = CGAffineTransformMakeTranslation(self.translation.x, self.translation.y); + [self pegViewDidMoveAtPoint:point]; +} + +- (void)resetTransformAtPoint:(CGPoint)point { + if (!self.hasMoveEnded) { + self.movable = NO; + self.moveEnded = YES; + + self.pinchRecognizer.enabled = NO; + self.panRecognizer.enabled = NO; + + BOOL animated = ![self pegViewMoveDidEndAtPoint:point]; + + [UIView animateWithDuration:animated ? 0.15f : 0.0f + delay:animated ? 0.0f : 0.30f + options:UIViewAnimationOptionCurveEaseOut + animations:^(){ + self.pegView.transform = CGAffineTransformIdentity; + self.pegView.alpha = 1.0f; + } + completion:^(BOOL finished){ + self.translation = CGPointZero; + self.translationOffset = CGPointZero; + self.pinchRecognizer.enabled = YES; + self.panRecognizer.enabled = YES; + self.moveEnded = NO; + self.pegView.hidden = NO; + }]; + } +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer +shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return YES; +} + +#pragma mark - peg view delegate + +- (void)pegViewDidMoveAtPoint:(CGPoint)point { + self.directionView.hidden = YES; + + if (CGPointEqualToPoint(self.startPoint, CGPointZero)) { + self.startPoint = point; + } + + if ([self.delegate respondsToSelector:@selector(holePegTestRemoveDidProgress:)]) { + [self.delegate holePegTestRemoveDidProgress:self]; + } + + if (self.pegView.isSuccess) { + self.pegView.success = NO; + } + + if ([self pegViewBehindLine]) { + self.pegView.alpha = 1.0f; + } else { + self.pegView.alpha = 0.2f; + } +} + +- (BOOL)pegViewMoveDidEndAtPoint:(CGPoint)point { + self.directionView.hidden = NO; + + BOOL succeeded = NO; + if ([self pegViewBehindLine]) { + if ([self.delegate respondsToSelector:@selector(holePegTestRemoveDidSucceed:withDistance:)]) { + CGFloat distance = hypotf(point.x - self.startPoint.x, point.y - self.startPoint.y); + [self.delegate holePegTestRemoveDidSucceed:self withDistance:distance]; + } + self.pegView.success = YES; + succeeded = YES; + } else { + if ([self.delegate respondsToSelector:@selector(holePegTestRemoveDidFail:)]) { + [self.delegate holePegTestRemoveDidFail:self]; + } + self.pegView.success = NO; + } + self.startPoint = CGPointZero; + return succeeded; +} + +- (BOOL)pegViewBehindLine { + if (self.movingDirection == ORKBodySagittalLeft) { + if (CGRectGetMinX(self.pegView.frame) > CGRectGetMaxX(self.separatorView.frame)) { + return YES; + } else { + return NO; + } + } else { + if (CGRectGetMaxX(self.pegView.frame) < CGRectGetMinX(self.separatorView.frame)) { + return YES; + } else { + return NO; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.h new file mode 100755 index 0000000..c444c38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestRemovePegView : UIView + +@property (nonatomic, assign, getter = isSuccess) BOOL success; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.m new file mode 100755 index 0000000..d2dbcce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemovePegView.m @@ -0,0 +1,122 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestRemovePegView.h" + + +@interface ORKHolePegTestRemovePegView () + +@property (nonatomic, strong) CAShapeLayer *checkLayer; + +@end + + +@implementation ORKHolePegTestRemovePegView + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + UIBezierPath *path = [[UIBezierPath alloc] init]; + [path moveToPoint:CGPointMake(27.7f, 46.9f)]; + [path addLineToPoint:CGPointMake(36.1f, 56.3f)]; + [path addLineToPoint:CGPointMake(62.8f, 30.3f)]; + path.lineCapStyle = kCGLineCapRound; + path.lineWidth = 3.6f; + + CAShapeLayer *checkLayer = [CAShapeLayer new]; + checkLayer.path = path.CGPath; + checkLayer.lineWidth = 3.6f; + checkLayer.lineCap = kCALineCapRound; + checkLayer.lineJoin = kCALineJoinRound; + checkLayer.frame = self.layer.bounds; + checkLayer.strokeColor = [UIColor whiteColor].CGColor; + checkLayer.backgroundColor = [UIColor clearColor].CGColor; + checkLayer.fillColor = nil; + self.checkLayer = checkLayer; + + self.opaque = NO; + self.success = NO; + } + + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self setNeedsDisplay]; +} + +#pragma mark - drawing method + +- (void)setSuccess:(BOOL)success +{ + _success = success; + [self.checkLayer removeFromSuperlayer]; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + CGRect bounds = self.bounds; + UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:bounds]; + path.lineWidth = 2.0f; + [self.tintColor setFill]; + [path fill]; + + if (self.isSuccess) { + [self.layer addSublayer:self.checkLayer]; + + CAMediaTimingFunction *timing = [[CAMediaTimingFunction alloc] initWithControlPoints:0.180739998817444 + :0 + :0.577960014343262 + :0.918200016021729]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + [animation setTimingFunction:timing]; + [animation setFillMode:kCAFillModeBoth]; + animation.fromValue = @(0); + animation.toValue = @(1); + animation.duration = 0.25f; + animation.delegate = self; + [self.checkLayer addAnimation:animation forKey:@"strokeEnd"]; + } + + CGContextRestoreGState(context); +} + +- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag { + self.success = NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.h new file mode 100755 index 0000000..e6a8fd1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestRemoveStep : ORKActiveStep + +@property (nonatomic, assign) ORKBodySagittal movingDirection; +@property (nonatomic, assign, getter = isDominantHandTested) BOOL dominantHandTested; +@property (nonatomic, assign) NSInteger numberOfPegs; +@property (nonatomic, assign) double threshold; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.m new file mode 100755 index 0000000..e1b29c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStep.m @@ -0,0 +1,134 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestRemoveStep.h" + +#import "ORKHolePegTestRemoveStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKHolePegTestRemoveStep + ++ (Class)stepViewControllerClass { + return [ORKHolePegTestRemoveStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + int const ORKHolePegTestMinimumNumberOfPegs = 1; + + double const ORKHolePegTestMinimumThreshold = 0.0f; + double const ORKHolePegTestMaximumThreshold = 1.0f; + + NSTimeInterval const ORKHolePegTestMinimumDuration = 1.0f; + + if (self.movingDirection != ORKBodySagittalLeft && + self.movingDirection != ORKBodySagittalRight) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"moving direction should be left or right."] userInfo:nil]; + } + + if (self.numberOfPegs < ORKHolePegTestMinimumNumberOfPegs) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"number of pegs must be greater than or equal to %@.", @(ORKHolePegTestMinimumNumberOfPegs)] userInfo:nil]; + } + + if (self.threshold < ORKHolePegTestMinimumThreshold || + self.threshold > ORKHolePegTestMaximumThreshold) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"threshold must be greater than or equal to %@ and lower or equal to %@.", @(ORKHolePegTestMinimumThreshold), @(ORKHolePegTestMaximumThreshold)] userInfo:nil]; + } + + if (self.stepDuration < ORKHolePegTestMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKHolePegTestMinimumDuration)] userInfo:nil]; + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, movingDirection); + ORK_DECODE_BOOL(aDecoder, dominantHandTested); + ORK_DECODE_INTEGER(aDecoder, numberOfPegs); + ORK_DECODE_DOUBLE(aDecoder, threshold); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, movingDirection); + ORK_ENCODE_BOOL(aCoder, dominantHandTested); + ORK_ENCODE_INTEGER(aCoder, numberOfPegs); + ORK_ENCODE_DOUBLE(aCoder, threshold); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) step = [super copyWithZone:zone]; + step.movingDirection = self.movingDirection; + step.dominantHandTested = self.dominantHandTested; + step.numberOfPegs = self.numberOfPegs; + step.threshold = self.threshold; + return step; +} + +- (NSUInteger)hash { + return [super hash] ^ self.movingDirection ^ self.dominantHandTested ^ self.numberOfPegs ^ (NSInteger)(self.threshold * 100); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.movingDirection == castObject.movingDirection) && + (self.dominantHandTested == castObject.dominantHandTested) && + (self.numberOfPegs == castObject.numberOfPegs) && + (self.threshold == castObject.threshold)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.h new file mode 100755 index 0000000..32bfdc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestRemoveStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.m new file mode 100755 index 0000000..6e215fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestRemoveStepViewController.m @@ -0,0 +1,178 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestRemoveStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKHolePegTestRemoveContentView.h" +#import "ORKStepContainerView_Private.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController.h" + +#import "ORKHolePegTestRemoveStep.h" +#import "ORKHolePegTestResult.h" + +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" +#import "ORKCollectionResult_Private.h" + + +@interface ORKHolePegTestRemoveStepViewController () + +@property (nonatomic, strong) NSMutableArray *samples; +@property (nonatomic, strong) ORKHolePegTestRemoveContentView *holePegTestRemoveContentView; +@property (nonatomic, assign) NSTimeInterval sampleStart; +@property (nonatomic, assign) NSUInteger successes; +@property (nonatomic, assign) NSUInteger failures; + +@end + + +@implementation ORKHolePegTestRemoveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (ORKHolePegTestRemoveStep *)holePegTestRemoveStep { + return (ORKHolePegTestRemoveStep *)self.step; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.holePegTestRemoveContentView = [[ORKHolePegTestRemoveContentView alloc] initWithMovingDirection:[self holePegTestRemoveStep].movingDirection]; + self.holePegTestRemoveContentView.threshold = [self holePegTestRemoveStep].threshold; + self.holePegTestRemoveContentView.delegate = self; + self.activeStepView.activeCustomView = self.holePegTestRemoveContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + + NSString *identifier = [[self holePegTestRemoveStep].identifier stringByReplacingOccurrencesOfString:@"remove" withString:@"place"]; + NSTimeInterval placeStepDuration = ((ORKHolePegTestResult *)[[self.taskViewController.result stepResultForStepIdentifier:identifier].results firstObject]).totalTime; + [self holePegTestRemoveStep].stepDuration -= placeStepDuration; + + [self start]; +} + +#pragma mark - step life cycle methods + +- (void)start { + self.sampleStart = CACurrentMediaTime(); + self.successes = 0; + self.failures = 0; + self.samples = [NSMutableArray array]; + [self.holePegTestRemoveContentView setProgress:0.001f animated:NO]; + + [super start]; +} + +#pragma mark - result methods + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKHolePegTestResult *holePegTestResult = [[ORKHolePegTestResult alloc] initWithIdentifier:self.step.identifier]; + holePegTestResult.movingDirection = [self holePegTestRemoveStep].movingDirection; + holePegTestResult.dominantHandTested = [self holePegTestRemoveStep].isDominantHandTested; + holePegTestResult.numberOfPegs = [self holePegTestRemoveStep].numberOfPegs; + holePegTestResult.threshold = [self holePegTestRemoveStep].threshold; + holePegTestResult.rotated = NO; + holePegTestResult.totalSuccesses = self.successes; + holePegTestResult.totalFailures = self.failures; + holePegTestResult.totalTime = [self holePegTestRemoveStep].stepDuration - self.timeRemaining; + double totalDistance = 0.0; + for (ORKHolePegTestSample *sample in self.samples) { + totalDistance += sample.distance; + } + holePegTestResult.totalDistance = totalDistance; + holePegTestResult.samples = self.samples; + + [results addObject:holePegTestResult]; + + sResult.results = [results copy]; + + return sResult; +} + +- (void)saveSampleWithDistance:(CGFloat)distance { + ORKHolePegTestSample *sample = [[ORKHolePegTestSample alloc] init]; + sample.time = CACurrentMediaTime() - self.sampleStart; + sample.distance = distance; + self.sampleStart = CACurrentMediaTime(); + + [self.samples addObject:sample]; +} + +#pragma mark - hole peg test content view delegate + +- (void)holePegTestRemoveDidProgress:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView { + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestRemoveStep].movingDirection == ORKBodySagittalLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT_2", nil)]]]; +} + +- (void)holePegTestRemoveDidSucceed:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView withDistance:(CGFloat)distance { + self.successes++; + + [self saveSampleWithDistance:distance]; + + [holePegTestRemoveContentView setProgress:((CGFloat)self.successes / [self holePegTestRemoveStep].numberOfPegs) animated:YES]; + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestRemoveStep].movingDirection == ORKBodySagittalLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]]; + + if (self.successes >= [self holePegTestRemoveStep].numberOfPegs) { + [self finish]; + } +} + +- (void)holePegTestRemoveDidFail:(ORKHolePegTestRemoveContentView *)holePegTestRemoveContentView { + self.failures++; + + [self.activeStepView updateTitle:self.step.title + text:[[self holePegTestRemoveStep].movingDirection == ORKBodySagittalLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.h new file mode 100755 index 0000000..e316ff2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.h @@ -0,0 +1,132 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKHolePegTestSample; + +/** + The `ORKHolePegTestResult` class records the results of a hole peg test. + + The hole peg test result object records the number of pegs, an array of move samples, the total duration + and also various attributes of the hole peg test. + + The hole peg test samples are generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize them for transmission to a server, + or to immediately perform analysis on them. + */ +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestResult : ORKResult + +/** + The hole peg test moving direction. + */ +@property (nonatomic, assign) ORKBodySagittal movingDirection; + +/** + The step is for the dominant hand. + */ +@property (nonatomic, assign, getter = isDominantHandTested) BOOL dominantHandTested; + +/** + The number of pegs to test. + */ +@property (nonatomic, assign) NSInteger numberOfPegs; + +/** + The detection area sensitivity. + */ +@property (nonatomic, assign) double threshold; + +/** + The hole peg test also assesses the rotation capabilities. + */ +@property (nonatomic, assign, getter = isRotated) BOOL rotated; + +/** + The number of succeeded moves (out of `numberOfPegs` possible). + */ +@property (nonatomic, assign) NSInteger totalSuccesses; + +/** + The number of failed moves. + */ +@property (nonatomic, assign) NSInteger totalFailures; + +/** + The total time needed to perform the test step (ie. the sum of all samples time). + */ +@property (nonatomic, assign) NSTimeInterval totalTime; + +/** + The total distance needed to perform the test step (ie. the sum of all samples distance). + */ +@property (nonatomic, assign) double totalDistance; + +/** + An array of collected samples, in which each item is an `ORKHolePegTestSample` + object that represents a peg move. + */ +@property (nonatomic, copy, nullable) NSArray *samples; + +@end + + +/** + The `ORKHolePegTestSample` class represents a peg move. + + The sample object records the duration, and the move distance. + An hole peg test is included in an `ORKHolePegTestResult` object, and is recorded + by the step view controller for the corresponding task. + + An hole peg test sample is typically generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize the sample for + transmission to a server, or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKHolePegTestSample : NSObject + +/** + The time interval for the peg move. + */ +@property (nonatomic, assign) NSTimeInterval time; + +/** + The peg move distance. + */ +@property (nonatomic, assign) double distance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.m new file mode 100755 index 0000000..2f81dd6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKHolePegTestResult.m @@ -0,0 +1,160 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHolePegTestResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKHolePegTestResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, movingDirection); + ORK_ENCODE_BOOL(aCoder, dominantHandTested); + ORK_ENCODE_INTEGER(aCoder, numberOfPegs); + ORK_ENCODE_INTEGER(aCoder, threshold); + ORK_ENCODE_BOOL(aCoder, rotated); + ORK_ENCODE_INTEGER(aCoder, totalSuccesses); + ORK_ENCODE_INTEGER(aCoder, totalFailures); + ORK_ENCODE_DOUBLE(aCoder, totalTime); + ORK_ENCODE_DOUBLE(aCoder, totalDistance); + ORK_ENCODE_OBJ(aCoder, samples); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, movingDirection); + ORK_DECODE_BOOL(aDecoder, dominantHandTested); + ORK_DECODE_INTEGER(aDecoder, numberOfPegs); + ORK_DECODE_INTEGER(aDecoder, threshold); + ORK_DECODE_BOOL(aDecoder, rotated); + ORK_DECODE_INTEGER(aDecoder, totalSuccesses); + ORK_DECODE_INTEGER(aDecoder, totalFailures); + ORK_DECODE_DOUBLE(aDecoder, totalTime); + ORK_DECODE_DOUBLE(aDecoder, totalDistance); + ORK_DECODE_OBJ_ARRAY(aDecoder, samples, ORKHolePegTestSample); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.movingDirection == castObject.movingDirection) && + (self.isDominantHandTested == castObject.isDominantHandTested) && + (self.numberOfPegs == castObject.numberOfPegs) && + (self.threshold == castObject.threshold) && + (self.isRotated == castObject.isRotated) && + (self.totalSuccesses == castObject.totalSuccesses) && + (self.totalFailures == castObject.totalFailures) && + (self.totalTime == castObject.totalTime) && + (self.totalDistance == castObject.totalDistance) && + ORKEqualObjects(self.samples, castObject.samples)) ; +} + +- (NSUInteger)hash { + return super.hash ^ self.samples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKHolePegTestResult *result = [super copyWithZone:zone]; + result.movingDirection = self.movingDirection; + result.dominantHandTested = self.isDominantHandTested; + result.numberOfPegs = self.numberOfPegs; + result.threshold = self.threshold; + result.rotated = self.isRotated; + result.totalSuccesses = self.totalSuccesses; + result.totalFailures = self.totalFailures; + result.totalTime = self.totalTime; + result.totalDistance = self.totalDistance; + result.samples = [self.samples copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; successes: %@; time: %@; samples: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], @(self.totalSuccesses), @(self.totalTime), self.samples, self.descriptionSuffix]; +} + +@end + + +@implementation ORKHolePegTestSample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, time); + ORK_ENCODE_DOUBLE(aCoder, distance); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, time); + ORK_DECODE_DOUBLE(aDecoder, distance); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.time == castObject.time) && + (self.distance == castObject.distance)) ; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKHolePegTestSample *sample = [[[self class] allocWithZone:zone] init]; + sample.time = self.time; + sample.distance = self.distance; + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; time: %@; distance: %@>", self.class.description, self, @(self.time), @(self.distance)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCResult.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCResult.swift new file mode 100755 index 0000000..3967dbf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCResult.swift @@ -0,0 +1,106 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ResearchKit.Private + +public class ORKLandoltCResult: ORKResult { + + public var outcome: Bool? + public var letterAngle: Double? + public var sliderAngle: Double? + public var score: Int? + + enum Keys: String { + case outcome + case letterAngle + case sliderAngle + case score + } + + public init(identifier: String, outcome: Bool, letterAngle: Double, sliderAngle: Double, score: Int) { + super.init(identifier: identifier) + + self.outcome = outcome + self.letterAngle = letterAngle + self.sliderAngle = sliderAngle + self.score = score + } + + override public func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + + aCoder.encode(outcome, forKey: Keys.outcome.rawValue) + aCoder.encode(letterAngle, forKey: Keys.letterAngle.rawValue) + aCoder.encode(sliderAngle, forKey: Keys.sliderAngle.rawValue) + aCoder.encode(score, forKey: Keys.score.rawValue) + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + outcome = aDecoder.decodeObject(forKey: Keys.outcome.rawValue) as? Bool ?? false + letterAngle = aDecoder.decodeObject(forKey: Keys.letterAngle.rawValue) as? Double ?? 0.0 + sliderAngle = aDecoder.decodeObject(forKey: Keys.sliderAngle.rawValue) as? Double ?? 0.0 + score = aDecoder.decodeObject(forKey: Keys.score.rawValue) as? Int ?? 0 + } + + override public func copy(with zone: NSZone? = nil) -> Any { + let result = super.copy(with: zone) as! ORKLandoltCResult + + result.outcome = outcome + result.letterAngle = letterAngle + result.sliderAngle = sliderAngle + result.score = score + + return result + } + + override public func isEqual(_ object: Any?) -> Bool { + let isParentSame = super.isEqual(object) + + if let castObject = object as? ORKLandoltCResult { + + return (isParentSame && + ORKEqualObjects(outcome as Any, castObject.outcome as Any) && + ORKEqualObjects(letterAngle as Any, castObject.letterAngle as Any) && + ORKEqualObjects(sliderAngle as Any, castObject.sliderAngle as Any) && + ORKEqualObjects(score as Any, castObject.score as Any)) + } + + return true + } + + override public func description(withNumberOfPaddingSpaces numberOfPaddingSpaces: UInt) -> String { + let descriptionString = " \(descriptionPrefix(withNumberOfPaddingSpaces: numberOfPaddingSpaces)); Outcome: \(String(describing: outcome)); LetterAngle: \(String(describing: letterAngle)); SliderAngle: \(String(describing: sliderAngle)); Score: \(String(describing: score))" + return descriptionString + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStep.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStep.swift new file mode 100755 index 0000000..503b1cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStep.swift @@ -0,0 +1,105 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@objc +public enum VisionStepLeftOrRightEye: Int { + case left + case right +} + +@objc +public enum VisionStepType: Int { + case visualAcuity + case contrastSensitivity +} + +@objc +public class ORKLandoltCStep: ORKActiveStep { + + public var testType: VisionStepType? + public var eyeToTest: VisionStepLeftOrRightEye? + + enum Key: String { + case testType + case eyeToTest + } + + public override class func stepViewControllerClass() -> AnyClass { + return ORKLandoltCStepViewController.self + } + + public class func supportsSecureCoding() -> Bool { + return true + } + + @objc + public init(identifier: String, testType: VisionStepType, eyeToTest: VisionStepLeftOrRightEye) { + super.init(identifier: identifier) + self.testType = testType + self.eyeToTest = eyeToTest + } + + public override var allowsBackNavigation: Bool { + return false + } + + public override func copy(with zone: NSZone? = nil) -> Any { + let visionStep: ORKLandoltCStep = super.copy(with: zone) as! ORKLandoltCStep + return visionStep + } + + public required init(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + + if let typeValue = aDecoder.decodeObject(forKey: "stepType") as? Int { + testType = VisionStepType(rawValue: typeValue) + } + + if let eyeValue = aDecoder.decodeObject(forKey: "eyeToTest") as? Int { + eyeToTest = VisionStepLeftOrRightEye(rawValue: eyeValue) + } + } + + public override func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(testType, forKey: Key.testType.rawValue) + aCoder.encode(eyeToTest, forKey: Key.eyeToTest.rawValue) + } + + public override func isEqual(_ object: Any?) -> Bool { + if let object = object as? ORKLandoltCStep { + return testType == object.testType && eyeToTest == object.eyeToTest + } + return false + } + +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepContentView.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepContentView.swift new file mode 100755 index 0000000..aaeba30 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepContentView.swift @@ -0,0 +1,81 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ResearchKit.Private + +internal class ORKLandoltCStepContentView: UIView { + + var eyeActivitySlider: EyeActivitySlider? + private var testType: VisionStepType? + + internal init(testType: VisionStepType) { + super.init(frame: CGRect()) + translatesAutoresizingMaskIntoConstraints = false + + self.testType = testType + setupSubviews() + setupConstraints() + } + + internal required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + internal func setupSubviews() { + guard let typeValue = testType else { + return + } + + eyeActivitySlider = EyeActivitySlider(testType: typeValue) + addSubview(eyeActivitySlider!) + } + + internal func setupConstraints() { + eyeActivitySlider?.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + NSLayoutConstraint(item: eyeActivitySlider!, + attribute: .width, + relatedBy: .equal, + toItem: self, + attribute: .width, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: eyeActivitySlider!, + attribute: .height, + relatedBy: .equal, + toItem: self, + attribute: .width, + multiplier: 1.0, + constant: 0.0) + ]) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepViewController.swift new file mode 100755 index 0000000..129517b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLandoltCStepViewController.swift @@ -0,0 +1,268 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import ResearchKit.Private + +public class ORKLandoltCStepViewController: ORKActiveStepViewController { + + private var activityTimer = Timer() + private var results = NSMutableArray() + private var visionStepView: ORKLandoltCStepView + private var eyeToTest: VisionStepLeftOrRightEye? + private var testType: VisionStepType? + + public override init(step: ORKStep?) { + if let visionStep = step as? ORKLandoltCStep { + eyeToTest = visionStep.eyeToTest + testType = visionStep.testType + } + visionStepView = ORKLandoltCStepView(testType: testType) + super.init(step: step) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override var result: ORKStepResult? { + let stepResult = super.result + stepResult?.results = results.copy() as? [ORKResult] + + return stepResult! + } + + + public override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = UIColor.white + activeStepView?.customContentView = visionStepView + activeStepView?.removeCustomContentPadding() + activeStepView?.customContentFillsAvailableSpace = true + + // TODO: Localize + visionStepView.currentEyeLabel.text = eyeToTest == .left ? "Left Eye" : "Right Eye" + visionStepView.continueButton.addTarget(self, action: #selector(continueButtonWasPressed), for: .touchUpInside) + startTimer() + } + + override public func stepDidFinish() { + super.stepDidFinish() + goForward() + } + + private func startTimer() { + activityTimer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(hideCircle), userInfo: nil, repeats: false) + } + + @objc + private func hideCircle() { + activityTimer.invalidate() + visionStepView.visionContentView?.eyeActivitySlider?.hideLetter() + visionStepView.topInstructionLabel.isHidden = false + } + + @objc + private func continueButtonWasPressed() { + activityTimer.invalidate() + visionStepView.topInstructionLabel.isHidden = true + visionStepView.continueButton.isEnabled = false + + if let resultData = visionStepView.visionContentView?.eyeActivitySlider?.fetchResultDataAndUpdateSlider() { + let stepResult: ORKLandoltCResult = ORKLandoltCResult(identifier: step!.identifier, + outcome: resultData.outcome, + letterAngle: resultData.letterAngle, + sliderAngle: resultData.sliderAngle, + score: resultData.score) + results.add(stepResult) + + if resultData.incorrectAnswers == 2 || resultData.score == resultData.maxScore { + stepDidFinish() + } else { + visionStepView.continueButton.isEnabled = true + startTimer() + } + } + } +} + +public class ORKLandoltCStepView: UIView { + + var visionContentView: ORKLandoltCStepContentView? + + let continueButtonCornerRadius: CGFloat = 12.0 + let eyeLabelTopPadding: CGFloat = 20.0 + let instructionLabelTopPadding: CGFloat = 15.0 + let visionContentTopPadding: CGFloat = 10.0 + + let continueButton = ORKRoundTappingButton() + let currentEyeLabel = UILabel() + let topInstructionLabel = UILabel() + + init(testType: VisionStepType!) { + super.init(frame: .zero) + setupCurrentEyeLabel() + setupTopInstructionLabel() + setupVisionContentView(testType: testType) + setupContinueButton() + setupConstraints() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupVisionContentView(testType: VisionStepType!) { + if visionContentView == nil { + visionContentView = ORKLandoltCStepContentView(testType: testType) + } + addSubview(visionContentView!) + } + + func setupCurrentEyeLabel() { + currentEyeLabel.isHidden = true + currentEyeLabel.textAlignment = .center + currentEyeLabel.textColor = UIColor.black + currentEyeLabel.numberOfLines = 0 + // TODO: set FontDescriptor + currentEyeLabel.font = UIFont(name: "", size: 20.0) + addSubview(currentEyeLabel) + } + + func setupTopInstructionLabel() { + topInstructionLabel.textAlignment = .center + topInstructionLabel.numberOfLines = 0 + topInstructionLabel.textColor = UIColor.black + // TODO: Localize + topInstructionLabel.text = "Move the dial to where you think the opening in the letter was." + // TODO: set FontDescriptor + topInstructionLabel.font = UIFont(name: "", size: 20.0) + topInstructionLabel.isHidden = true + addSubview(topInstructionLabel) + } + + func setupContinueButton() { + // TODO: Localize + continueButton.diameter = 60.0 + continueButton.setTitle("Next", for: UIControl.State.normal) + continueButton.backgroundColor = tintColor + continueButton.layer.cornerRadius = continueButtonCornerRadius + addSubview(continueButton) + } + + private func setupConstraints() { + currentEyeLabel.translatesAutoresizingMaskIntoConstraints = false + topInstructionLabel.translatesAutoresizingMaskIntoConstraints = false + visionContentView?.translatesAutoresizingMaskIntoConstraints = false + continueButton.translatesAutoresizingMaskIntoConstraints = false + + let constraints = [ + NSLayoutConstraint(item: currentEyeLabel, + attribute: .top, + relatedBy: .equal, + toItem: self, + attribute: .top, + multiplier: 1.0, + constant: eyeLabelTopPadding), + NSLayoutConstraint(item: currentEyeLabel, + attribute: .centerX, + relatedBy: .equal, + toItem: self, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: topInstructionLabel, + attribute: .top, + relatedBy: .equal, + toItem: currentEyeLabel, + attribute: .bottom, + multiplier: 1.0, + constant: instructionLabelTopPadding), + NSLayoutConstraint(item: topInstructionLabel, + attribute: .centerX, + relatedBy: .equal, + toItem: self, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: topInstructionLabel, + attribute: .width, + relatedBy: .equal, + toItem: self, + attribute: .width, + multiplier: 0.8, + constant: 0.0), + NSLayoutConstraint(item: visionContentView!, + attribute: .top, + relatedBy: .equal, + toItem: topInstructionLabel, + attribute: .bottom, + multiplier: 1.0, + constant: visionContentTopPadding), + NSLayoutConstraint(item: visionContentView!, + attribute: .centerX, + relatedBy: .equal, + toItem: self, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: visionContentView!, + attribute: .width, + relatedBy: .equal, + toItem: self, + attribute: .width, + multiplier: 0.8, + constant: 0.0), + NSLayoutConstraint(item: visionContentView!, + attribute: .height, + relatedBy: .equal, + toItem: self, + attribute: .height, + multiplier: 0.8, + constant: 0.0), + NSLayoutConstraint(item: continueButton, + attribute: .centerX, + relatedBy: .equal, + toItem: self, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: continueButton, + attribute: .bottom, + relatedBy: .equal, + toItem: self, + attribute: .bottom, + multiplier: 1.0, + constant: -20.0) + ] + + NSLayoutConstraint.activate(constraints) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.h new file mode 100755 index 0000000..7f8e8e0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import CoreLocation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKLocationRecorder` class represents a recorder for collecting location data from CoreLocation. + + Because location data is sensitive information, you need to take special care in handling it, including removoing or otherwise preparing it for a + anonymous data set. + + The accuracy of location data may be limited indoors. + */ +ORK_CLASS_AVAILABLE +@interface ORKLocationRecorder : ORKRecorder + +/** + Returns an initialized location recorder. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param step The step that requested this recorder. + @param outputDirectory The directory in which the location data should be stored. + + @return An initialized location recorder. +*/ +- (instancetype)initWithIdentifier:(NSString *)identifier + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + + +/** + The location manager, if any, being used by this recorder. + */ +@property (nonatomic, strong, nullable, readonly) CLLocationManager *locationManager; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.m new file mode 100755 index 0000000..6e64d9b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKLocationRecorder.m @@ -0,0 +1,204 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLocationRecorder.h" + +#import "ORKDataLogger.h" + +#import "ORKRecorder_Internal.h" + +#import "CLLocation+ORKJSONDictionary.h" + +#import + + +@interface ORKLocationRecorder () { + ORKDataLogger *_logger; + NSError *_recordingError; + BOOL _started; +} + +@property (nonatomic, strong, nullable) CLLocationManager *locationManager; + +@property (nonatomic) NSTimeInterval uptime; + +@end + + +@implementation ORKLocationRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier step:step outputDirectory:outputDirectory]; + if (self) { + self.continuesInBackground = YES; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (NSString *)recorderType { + return @"location"; +} + +- (CLLocationManager *)createLocationManager { + return [[CLLocationManager alloc] init]; +} + +- (void)start { + [super start]; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + self.locationManager = [self createLocationManager]; + if ([CLLocationManager authorizationStatus] <= kCLAuthorizationStatusDenied) { + [self.locationManager requestWhenInUseAuthorization]; + } + self.locationManager.pausesLocationUpdatesAutomatically = NO; + self.locationManager.delegate = self; + + if (!self.locationManager) { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:NSFeatureUnsupportedError + userInfo:@{@"recorder": self}]; + [self finishRecordingWithError:error]; + return; + } + + self.uptime = [NSProcessInfo processInfo].systemUptime; + [self.locationManager startUpdatingLocation]; +} + +- (void)doStopRecording { + [self.locationManager stopUpdatingLocation]; + self.locationManager.delegate = nil; + self.locationManager = nil; +} + +- (void)stop { + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = _recordingError; + _recordingError = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)locationManager:(CLLocationManager *)manager + didUpdateLocations:(NSArray *)locations { + BOOL success = YES; + NSParameterAssert(locations.count >= 0); + NSError *error = nil; + if (locations) { + NSMutableArray *dictionaries = [NSMutableArray arrayWithCapacity:locations.count]; + [locations enumerateObjectsUsingBlock:^(CLLocation *obj, NSUInteger idx, BOOL *stop) { + NSDictionary *d = [obj ork_JSONDictionary]; + [dictionaries addObject:d]; + }]; + + success = [_logger appendObjects:dictionaries error:&error]; + } + if (!success) { + dispatch_async(dispatch_get_main_queue(), ^{ + _recordingError = error; + [self stop]; + }); + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:nil]; +} + +- (BOOL)isRecording { + return [CLLocationManager locationServicesEnabled] && (self.locationManager != nil) && ([CLLocationManager authorizationStatus] > kCLAuthorizationStatusDenied); +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +@end + + +@implementation ORKLocationRecorderConfiguration + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [super initWithIdentifier:identifier]; +} + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return [[ORKLocationRecorder alloc] initWithIdentifier:self.identifier step:step outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + return isParentSame; +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionCoreLocation; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.h new file mode 100755 index 0000000..a25e427 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTypes.h" +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPSATKeyboardView; + +@interface ORKPSATContentView : ORKActiveStepCustomView + +@property (nonatomic, strong) ORKPSATKeyboardView *keyboardView; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithPresentationMode:(ORKPSATPresentationMode)presentationMode NS_DESIGNATED_INITIALIZER; +- (void)setEnabled:(BOOL)enabled; +- (void)setAddition:(NSUInteger)additionIndex forTotal:(NSUInteger)totalAddition withDigit:(NSNumber *)digit; +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.m new file mode 100755 index 0000000..0a4b57e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATContentView.m @@ -0,0 +1,173 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPSATContentView.h" + +#import "ORKBorderedButton.h" +#import "ORKPSATKeyboardView.h" +#import "ORKTapCountLabel.h" +#import "ORKVoiceEngine.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKPSATContentView () + +@property (nonatomic, assign, getter = isAuditory) BOOL auditory; +@property (nonatomic, strong) UIProgressView *progressView; +@property (nonatomic, strong) ORKTapCountLabel *digitLabel; + +@end + + +@implementation ORKPSATContentView + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [self initWithPresentationMode:ORKPSATPresentationModeAuditory]; + return self; +} + +- (instancetype)initWithPresentationMode:(ORKPSATPresentationMode)presentationMode { + self = [super initWithFrame:CGRectZero]; + + if (self) { + + _digitLabel = [ORKTapCountLabel new]; + _digitLabel.textAlignment = NSTextAlignmentCenter; + _digitLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_digitLabel]; + _auditory = (presentationMode & ORKPSATPresentationModeAuditory) ? YES : NO; + if (!(presentationMode & ORKPSATPresentationModeVisual)) { + _digitLabel.hidden = YES; + } + + _progressView = [UIProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + _progressView.progressTintColor = [self tintColor]; + [_progressView setAlpha:0]; + [self addSubview:_progressView]; + + _keyboardView = [ORKPSATKeyboardView new]; + _keyboardView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_keyboardView]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setNeedsUpdateConstraints]; + } + + return self; +} + +- (void)setEnabled:(BOOL)enabled { + self.keyboardView.enabled = enabled; +} + +- (void)setAddition:(NSUInteger)additionIndex forTotal:(NSUInteger)totalAddition withDigit:(NSNumber *)digit { + if (digit.integerValue == -1) { + self.digitLabel.textColor = [[UIColor blackColor] colorWithAlphaComponent:0.3f]; + self.digitLabel.text = ORKLocalizedString(@"PSAT_NO_DIGIT", nil); + } else { + [self.keyboardView.selectedAnswerButton setSelected:NO]; + self.digitLabel.textColor = nil; + self.digitLabel.text = [NSNumberFormatter localizedStringFromNumber:digit + numberStyle:NSNumberFormatterNoStyle]; + if (self.isAuditory) { + [[ORKVoiceEngine sharedVoiceEngine] speakInt:digit.integerValue]; + } + } +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.progressView.progressTintColor = self.tintColor; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:self.constraints]; + + const CGFloat ORKPSATKeyboardWidth = ORKGetMetricForWindow(ORKScreenMetricPSATKeyboardViewWidth, self.window); + const CGFloat ORKPSATKeyboardHeight = ORKGetMetricForWindow(ORKScreenMetricPSATKeyboardViewHeight, self.window); + + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _digitLabel, _keyboardView); + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_keyboardView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKPSATKeyboardWidth]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_keyboardView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_keyboardView(==keyboardHeight)]" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"keyboardHeight": @(ORKPSATKeyboardHeight) } + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_progressView]-[_digitLabel]-(>=10)-[_keyboardView]-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; + [super updateConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.h new file mode 100755 index 0000000..ad508db --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKBorderedButton; +@protocol ORKPSATKeyboardViewDelegate; + +@interface ORKPSATKeyboardView : UIView + +@property (nonatomic, weak) id delegate; +@property (nonatomic, weak) ORKBorderedButton *selectedAnswerButton; + +- (void)setEnabled:(BOOL)enabled; + +@end + +@protocol ORKPSATKeyboardViewDelegate + +- (void)keyboardView:(ORKPSATKeyboardView *)keyboardView didSelectAnswer:(NSInteger)answer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.m new file mode 100755 index 0000000..bcac700 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATKeyboardView.m @@ -0,0 +1,153 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPSATKeyboardView.h" + +#import "ORKBorderedButton.h" + + +NSUInteger const ORKPSATMinimumAnswer = 3; +NSUInteger const ORKPSATMaximumAnswer = 17; + +@interface ORKPSATKeyboardView () + +@property (nonatomic, strong, readonly) NSArray *answerButtons; +@property (nonatomic, strong) NSArray *constraints; + +@end + + +@implementation ORKPSATKeyboardView + +- (instancetype)init { + self = [super init]; + if (self) { + NSMutableArray *buttonsArray = [[NSMutableArray alloc] initWithCapacity:(ORKPSATMaximumAnswer - ORKPSATMinimumAnswer) + 1]; + ORKBorderedButton *answerButton = nil; + for (int i = ORKPSATMinimumAnswer; i <= ORKPSATMaximumAnswer; i++) { + answerButton = [self answerButtonWithTitle:[NSNumberFormatter localizedStringFromNumber:@(i) + numberStyle:NSNumberFormatterNoStyle]]; + [buttonsArray addObject:answerButton]; + [self addSubview:answerButton]; + } + _answerButtons = [NSArray arrayWithArray:buttonsArray]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setNeedsUpdateConstraints]; + } + + return self; +} + +- (ORKBorderedButton *)answerButtonWithTitle:(NSString *)title { + ORKBorderedButton *answerButton = [ORKBorderedButton new]; + answerButton.translatesAutoresizingMaskIntoConstraints = NO; + [answerButton setTitle:title forState:UIControlStateNormal]; + [answerButton addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchUpInside]; + answerButton.accessibilityTraits |= UIAccessibilityTraitKeyboardKey; + return answerButton; +} + +- (void)setEnabled:(BOOL)enabled { + for (ORKBorderedButton *answerButton in self.answerButtons) { + [answerButton setEnabled:enabled]; + } +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:self.constraints]; + + NSMutableArray *constraints = [NSMutableArray array]; + + ORKBorderedButton *answer3Button = self.answerButtons[0]; + ORKBorderedButton *answer4Button = self.answerButtons[1]; + ORKBorderedButton *answer5Button = self.answerButtons[2]; + ORKBorderedButton *answer6Button = self.answerButtons[3]; + ORKBorderedButton *answer7Button = self.answerButtons[4]; + ORKBorderedButton *answer8Button = self.answerButtons[5]; + ORKBorderedButton *answer9Button = self.answerButtons[6]; + ORKBorderedButton *answer10Button = self.answerButtons[7]; + ORKBorderedButton *answer11Button = self.answerButtons[8]; + ORKBorderedButton *answer12Button = self.answerButtons[9]; + ORKBorderedButton *answer13Button = self.answerButtons[10]; + ORKBorderedButton *answer14Button = self.answerButtons[11]; + ORKBorderedButton *answer15Button = self.answerButtons[12]; + ORKBorderedButton *answer16Button = self.answerButtons[13]; + ORKBorderedButton *answer17Button = self.answerButtons[14]; + + + NSDictionary *views = NSDictionaryOfVariableBindings(answer3Button, answer4Button, answer5Button, answer6Button, answer7Button, answer8Button, answer9Button, answer10Button, answer11Button, answer12Button, answer13Button, answer14Button, answer15Button, answer16Button, answer17Button); + + // First line of answer buttons + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer3Button]-[answer4Button(==answer3Button)]-[answer5Button(==answer3Button)]-[answer6Button(==answer3Button)]-[answer7Button(==answer3Button)]-|" + options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom + metrics:nil views:views]]; + + // Second line of answer buttons + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer8Button]-[answer9Button(==answer8Button)]-[answer10Button(==answer8Button)]-[answer11Button(==answer8Button)]-[answer12Button(==answer8Button)]-|" + options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom + metrics:nil views:views]]; + + // Third line of answer buttons + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[answer13Button]-[answer14Button(==answer13Button)]-[answer15Button(==answer13Button)]-[answer16Button(==answer13Button)]-[answer17Button(==answer13Button)]-|" + options:NSLayoutFormatAlignAllCenterY|NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom + metrics:nil views:views]]; + + // Align vertically + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[answer3Button]-[answer8Button(==answer3Button)]-[answer13Button(==answer3Button)]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; + [super updateConstraints]; +} + +#pragma mark buttonAction + +- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event { + ORKBorderedButton *tappedAnswerButton = (ORKBorderedButton *)button; + + [self.selectedAnswerButton setSelected:NO]; + self.selectedAnswerButton = tappedAnswerButton; + [self.selectedAnswerButton setSelected:YES]; + + if ([self.delegate respondsToSelector:@selector(keyboardView:didSelectAnswer:)]) { + NSInteger answerValue = [self.answerButtons indexOfObject:tappedAnswerButton] + ORKPSATMinimumAnswer; + [self.delegate keyboardView:self didSelectAnswer:answerValue]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.h new file mode 100755 index 0000000..9ff64af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.h @@ -0,0 +1,142 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPSATSample; + +/** + The `ORKPSATResult` class records the results of a PSAT test. + + The PSAT result object records the initial digit, an array of addition samples, the total of correct answers + and also various attributes of the PSAT test. + + The PSAT samples are generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize them for transmission to a server, + or to immediately perform analysis on them. + */ +ORK_CLASS_AVAILABLE +@interface ORKPSATResult : ORKResult + +/** + The PSAT presentation mode. + */ +@property (nonatomic, assign) ORKPSATPresentationMode presentationMode; + +/** + The time interval between two digits presented. + PSAT-2" is 2 seconds; PSAT-3" is 3 seconds. + */ +@property (nonatomic, assign) NSTimeInterval interStimulusInterval; + +/** + The amount of time a digit is shown on the screen (0 second for PASAT). + */ +@property (nonatomic, assign) NSTimeInterval stimulusDuration; + +/** + The length of the series, that is, the number of additions. + */ +@property (nonatomic, assign) NSInteger length; + +/** + The number of correct sums given (out of 'length' possible ones). + */ +@property (nonatomic, assign) NSInteger totalCorrect; + +/** + The number of consecutive correct answers (out of 'length - 1' possible ones). + Used to overcome the alternate answer strategy. + */ +@property (nonatomic, assign) NSInteger totalDyad; + +/** + The total time needed to answer all additions (that is, the sum of all the samples times). + */ +@property (nonatomic, assign) NSTimeInterval totalTime; + +/** + The initial digit. + */ +@property (nonatomic, assign) NSInteger initialDigit; + +/** + An array of collected samples, in which each item is an `ORKPSATSample` + object that represents an addition sample. + */ +@property (nonatomic, copy, nullable) NSArray *samples; + +@end + + +/** + The `ORKPSATSample` class represents a numeric answer to an addition question. + If the answer is correct, the sample object records the presented digit and the numeric answer. + A PSAT sample is included in an `ORKPSATResult` object and is recorded + by the step view controller for the corresponding task. + + A PSAT sample is typically generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize the sample for + transmission to a server, or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKPSATSample : NSObject + +/** + A Boolean value indicating whether the addition answer was the correct one. + + The value of this property is `YES` when the addition result is the correct + one, and `NO` otherwise. + */ +@property (nonatomic, assign, getter=isCorrect) BOOL correct; + +/** + The presented digit. + */ +@property (nonatomic, assign) NSInteger digit; + +/** + The numeric answer; + `-1` if no answer is provided. + */ +@property (nonatomic, assign) NSInteger answer; + +/** + The time interval between the new digit and the answer, or test duration if no answer is provided. + */ +@property (nonatomic, assign) NSTimeInterval time; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.m new file mode 100755 index 0000000..2ef4f5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATResult.m @@ -0,0 +1,165 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPSATResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKPSATSample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_BOOL(aCoder, correct); + ORK_ENCODE_INTEGER(aCoder, digit); + ORK_ENCODE_INTEGER(aCoder, answer); + ORK_ENCODE_DOUBLE(aCoder, time); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_BOOL(aDecoder, correct); + ORK_DECODE_INTEGER(aDecoder, digit); + ORK_DECODE_INTEGER(aDecoder, answer); + ORK_DECODE_DOUBLE(aDecoder, time); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.isCorrect == castObject.isCorrect) && + (self.digit == castObject.digit) && + (self.answer == castObject.answer) && + (self.time == castObject.time)) ; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPSATSample *sample = [[[self class] allocWithZone:zone] init]; + sample.correct = self.isCorrect; + sample.digit = self.digit; + sample.answer = self.answer; + sample.time = self.time; + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; correct: %@; digit: %@; answer: %@; time: %@>", self.class.description, self, @(self.isCorrect), @(self.digit), @(self.answer), @(self.time)]; +} + +@end + + +@implementation ORKPSATResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, presentationMode); + ORK_ENCODE_DOUBLE(aCoder, interStimulusInterval); + ORK_ENCODE_DOUBLE(aCoder, stimulusDuration); + ORK_ENCODE_INTEGER(aCoder, length); + ORK_ENCODE_INTEGER(aCoder, totalCorrect); + ORK_ENCODE_INTEGER(aCoder, totalDyad); + ORK_ENCODE_DOUBLE(aCoder, totalTime); + ORK_ENCODE_INTEGER(aCoder, initialDigit); + ORK_ENCODE_OBJ(aCoder, samples); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, presentationMode); + ORK_DECODE_DOUBLE(aDecoder, interStimulusInterval); + ORK_DECODE_DOUBLE(aDecoder, stimulusDuration); + ORK_DECODE_INTEGER(aDecoder, length); + ORK_DECODE_INTEGER(aDecoder, totalCorrect); + ORK_DECODE_INTEGER(aDecoder, totalDyad); + ORK_DECODE_DOUBLE(aDecoder, totalTime); + ORK_DECODE_INTEGER(aDecoder, initialDigit); + ORK_DECODE_OBJ_ARRAY(aDecoder, samples, ORKPSATSample); + } + return self; + +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.presentationMode == castObject.presentationMode) && + (self.interStimulusInterval == castObject.interStimulusInterval) && + (self.stimulusDuration == castObject.stimulusDuration) && + (self.length == castObject.length) && + (self.totalCorrect == castObject.totalCorrect) && + (self.totalDyad == castObject.totalDyad) && + (self.totalTime == castObject.totalTime) && + (self.initialDigit == castObject.initialDigit) && + ORKEqualObjects(self.samples, castObject.samples)) ; +} + +- (NSUInteger)hash { + return super.hash ^ self.samples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPSATResult *result = [super copyWithZone:zone]; + result.presentationMode = self.presentationMode; + result.interStimulusInterval = self.interStimulusInterval; + result.stimulusDuration = self.stimulusDuration; + result.length = self.length; + result.totalCorrect = self.totalCorrect; + result.totalDyad = self.totalDyad; + result.totalTime = self.totalTime; + result.initialDigit = self.initialDigit; + result.samples = [self.samples copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; correct: %@/%@; samples: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], @(self.totalCorrect), @(self.length), self.samples, self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.h new file mode 100755 index 0000000..04c7150 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKPSATStep : ORKActiveStep + +@property (nonatomic, assign) ORKPSATPresentationMode presentationMode; +@property (nonatomic, assign) NSTimeInterval interStimulusInterval; +@property (nonatomic, assign) NSTimeInterval stimulusDuration; +@property (nonatomic, assign) NSInteger seriesLength; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.m new file mode 100755 index 0000000..355267b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStep.m @@ -0,0 +1,143 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPSATStep.h" + +#import "ORKPSATStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKPSATStep + ++ (Class)stepViewControllerClass { + return [ORKPSATStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldStartTimerAutomatically = YES; + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSTimeInterval const ORKPSATInterStimulusMinimumInterval = 1.0; + NSTimeInterval const ORKPSATInterStimulusMaximumInterval = 5.0; + + NSTimeInterval const ORKPSATStimulusMinimumDuration = 0.2; + + NSInteger const ORKPSATSerieMinimumLength = 10; + NSInteger const ORKPSATSerieMaximumLength = 120; + + NSTimeInterval totalDuration = (self.seriesLength + 1) * self.interStimulusInterval; + if (self.stepDuration != totalDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"step duration must be equal to %@ seconds.", @(totalDuration)] userInfo:nil]; + } + + if (!(self.presentationMode & ORKPSATPresentationModeAuditory) && + !(self.presentationMode & ORKPSATPresentationModeVisual)) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"step presentation mode must be auditory and/or visual." userInfo:nil]; + } + + if (self.interStimulusInterval < ORKPSATInterStimulusMinimumInterval || + self.interStimulusInterval > ORKPSATInterStimulusMaximumInterval) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"inter stimulus interval must be greater than or equal to %@ seconds and less than or equal to %@ seconds.", @(ORKPSATInterStimulusMinimumInterval), @(ORKPSATInterStimulusMaximumInterval)] userInfo:nil]; + } + + if ((self.presentationMode & ORKPSATPresentationModeVisual) && + (self.stimulusDuration < ORKPSATStimulusMinimumDuration || self.stimulusDuration > self.interStimulusInterval)) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"stimulus duration must be greater than or equal to %@ seconds and less than or equal to %@ seconds.", @(ORKPSATStimulusMinimumDuration), @(self.interStimulusInterval)] userInfo:nil]; + } + + if (self.seriesLength < ORKPSATSerieMinimumLength || + self.seriesLength > ORKPSATSerieMaximumLength) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"serie length must be greater than or equal to %@ additions and less than or equal to %@ additions.", @(ORKPSATSerieMinimumLength), @(ORKPSATSerieMaximumLength)] userInfo:nil]; + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, presentationMode); + ORK_DECODE_DOUBLE(aDecoder, interStimulusInterval); + ORK_DECODE_DOUBLE(aDecoder, stimulusDuration); + ORK_DECODE_INTEGER(aDecoder, seriesLength); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, presentationMode); + ORK_ENCODE_DOUBLE(aCoder, interStimulusInterval); + ORK_ENCODE_DOUBLE(aCoder, stimulusDuration); + ORK_ENCODE_INTEGER(aCoder, seriesLength); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPSATStep *step = [super copyWithZone:zone]; + step.presentationMode = self.presentationMode; + step.interStimulusInterval = self.interStimulusInterval; + step.stimulusDuration = self.stimulusDuration; + step.seriesLength = self.seriesLength; + return step; +} + +- (NSUInteger)hash { + return [super hash] ^ self.presentationMode ^ (NSInteger)(self.interStimulusInterval*100) ^ (NSInteger)(self.stimulusDuration*100) ^ self.seriesLength; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.presentationMode == castObject.presentationMode) && + (self.interStimulusInterval == castObject.interStimulusInterval) && + (self.stimulusDuration == castObject.stimulusDuration) && + (self.seriesLength == castObject.seriesLength)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.h new file mode 100755 index 0000000..23917bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKPSATStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.m new file mode 100755 index 0000000..c09dbe8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPSATStepViewController.m @@ -0,0 +1,247 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPSATStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKPSATContentView.h" +#import "ORKPSATKeyboardView.h" +#import "ORKVerticalContainerView.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKPSATResult.h" +#import "ORKPSATStep.h" +#import "ORKResult.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKPSATStepViewController () + +@property (nonatomic, strong) NSMutableArray *samples; +@property (nonatomic, strong) ORKPSATContentView *psatContentView; +@property (nonatomic, strong) NSArray *digits; +@property (nonatomic, assign) NSUInteger currentDigitIndex; +@property (nonatomic, assign) NSInteger currentAnswer; +@property (nonatomic, strong) ORKActiveStepTimer *clearDigitsTimer; +@property (nonatomic, assign) NSTimeInterval answerStart; +@property (nonatomic, assign) NSTimeInterval answerEnd; + +@end + + +@implementation ORKPSATStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + self.suspendIfInactive = YES; + } + + return self; +} + +- (ORKPSATStep *)psatStep { + NSAssert(self.step == nil || [self.step isKindOfClass:[ORKPSATStep class]], @"Step class must be subclass of ORKPSATStep."); + return (ORKPSATStep *)self.step; +} + +- (NSArray *)arrayWithPSATDigits { + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[self psatStep].seriesLength + 1]; + NSUInteger digit = 0; + for (NSUInteger i = 0; i < [self psatStep].seriesLength + 1; i++) { + do + { + digit = (arc4random() % (9)) + 1; + } while (digit == ((NSNumber *)[array lastObject]).integerValue); + [array addObject:@(digit)]; + } + return array; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show buttons + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.psatContentView = [[ORKPSATContentView alloc] initWithPresentationMode:[self psatStep].presentationMode]; + self.psatContentView.keyboardView.delegate = self; + [self.psatContentView setEnabled:NO]; + self.activeStepView.activeCustomView = self.psatContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + + self.timerUpdateInterval = [self psatStep].interStimulusInterval; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKPSATResult *PSATResult = [[ORKPSATResult alloc] initWithIdentifier:self.step.identifier]; + PSATResult.presentationMode = [self psatStep].presentationMode; + PSATResult.interStimulusInterval = [self psatStep].interStimulusInterval; + if ([self psatStep].presentationMode & ORKPSATPresentationModeVisual) { + PSATResult.stimulusDuration = [self psatStep].stimulusDuration; + } else { + PSATResult.stimulusDuration = 0.0; + } + PSATResult.length = [self psatStep].seriesLength; + PSATResult.initialDigit = self.digits[0].integerValue; + NSInteger totalCorrect = 0; + BOOL previousAnswerCorrect = NO; + NSInteger totalDyad = 0; + CGFloat totalTime = 0.0; + for (ORKPSATSample *sample in self.samples) { + totalTime += sample.time; + if (sample.isCorrect) { + totalCorrect++; + if (previousAnswerCorrect) { + totalDyad++; + } + } + previousAnswerCorrect = sample.isCorrect; + } + PSATResult.totalCorrect = totalCorrect; + PSATResult.totalTime = totalTime; + PSATResult.totalDyad = totalDyad; + PSATResult.samples = self.samples; + + [results addObject:PSATResult]; + + sResult.results = [results copy]; + + return sResult; +} + +- (void)start { + self.digits = [self arrayWithPSATDigits]; + self.currentDigitIndex = 0; + [self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:self.digits[self.currentDigitIndex]]; + [self.psatContentView setProgress:0.001 animated:NO]; + self.currentAnswer = -1; + self.samples = [NSMutableArray array]; + + if ([self psatStep].presentationMode & ORKPSATPresentationModeVisual && + ([self psatStep].interStimulusInterval - [self psatStep].stimulusDuration) > 0.05 ) { + + // Don't show `-` if the difference between stimulusDuration and interStimulusInterval is less than timer's resolution. + ORKWeakTypeOf(self) weakSelf = self; + self.clearDigitsTimer = [[ORKActiveStepTimer alloc] initWithDuration:[self psatStep].stepDuration + interval:[self psatStep].interStimulusInterval + runtime:-[self psatStep].stimulusDuration + handler:^(ORKActiveStepTimer *timer, BOOL finished) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf clearDigitsTimerFired]; + }]; + [self.clearDigitsTimer resume]; + } + + [super start]; +} + +- (void)suspend { + [self.clearDigitsTimer pause]; + [super suspend]; +} + +- (void)resume { + [self.clearDigitsTimer resume]; + [super resume]; +} + +- (void)finish { + [self.clearDigitsTimer reset]; + self.clearDigitsTimer = nil; + [super finish]; +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + if (self.currentDigitIndex == 0) { + [self.psatContentView setEnabled:YES]; + [self.activeStepView updateTitle:self.step.title text:ORKLocalizedString(@"PSAT_INSTRUCTION", nil)]; + } else { + [self saveSample]; + } + + self.currentDigitIndex++; + self.answerStart = CACurrentMediaTime(); + self.answerEnd = 0; + + if (self.currentDigitIndex <= [self psatStep].seriesLength) { + [self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:self.digits[self.currentDigitIndex]]; + } + + self.currentAnswer = -1; + + CGFloat progress = finished ? 1 : (timer.runtime / timer.duration); + [self.psatContentView setProgress:progress animated:YES]; + + [super countDownTimerFired:timer finished:finished]; +} + +- (void)clearDigitsTimerFired { + [self.psatContentView setAddition:self.currentDigitIndex forTotal:[self psatStep].seriesLength withDigit:@(-1)]; +} + +- (void)saveSample { + ORKPSATSample *sample = [[ORKPSATSample alloc] init]; + NSInteger previousDigit = self.digits[self.currentDigitIndex - 1].integerValue; + NSInteger currentDigit = self.digits[self.currentDigitIndex].integerValue;; + sample.correct = previousDigit + currentDigit == self.currentAnswer ? YES : NO; + sample.digit = currentDigit; + sample.answer = self.currentAnswer; + sample.time = self.answerEnd == 0 ? [self psatStep].interStimulusInterval : self.answerEnd - self.answerStart; + + [self.samples addObject:sample]; +} + +#pragma mark - keyboard view delegate + +- (void)keyboardView:(ORKPSATKeyboardView *)keyboardView didSelectAnswer:(NSInteger)answer { + self.currentAnswer = answer; + self.answerEnd = CACurrentMediaTime(); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.h new file mode 100755 index 0000000..1ff3334 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPedometerRecorder; + +@protocol ORKPedometerRecorderDelegate + +@optional +- (void)pedometerRecorderDidUpdate:(ORKPedometerRecorder *)pedometerRecorder; + +@end + + +/** + A recorder that requests and collects device motion data from CoreMotion at a fixed frequency. + + The accelerometer recorder continues to record if the application enters the + background using UIApplication's background task support. + */ +ORK_CLASS_AVAILABLE +@interface ORKPedometerRecorder : ORKRecorder + +@property (nonatomic, readonly, nullable) NSDate *lastUpdateDate; + +@property (nonatomic, readonly) NSInteger totalNumberOfSteps; + +// Negative if an invalid value. +@property (nonatomic, readonly) NSInteger totalDistance; + +/** + Returns an initialized pedometer recorder. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param step The step that requested this recorder. + @param outputDirectory The directory in which the pedometer data should be stored. + + @return An initialized pedometer recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.m new file mode 100755 index 0000000..82579a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKPedometerRecorder.m @@ -0,0 +1,216 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPedometerRecorder.h" + +#import "ORKDataLogger.h" + +#import "ORKRecorder_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "CMPedometerData+ORKJSONDictionary.h" + + +@interface ORKPedometerRecorder () { + ORKDataLogger *_logger; + BOOL _isRecording; +} + +@property (nonatomic, strong) CMPedometer *pedometer; + +@end + + +@implementation ORKPedometerRecorder + +- (instancetype)initWithIdentifier:(NSString *)identifier + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier + step:step + outputDirectory:outputDirectory]; + if (self) { + self.continuesInBackground = YES; + } + return self; +} + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (void)updateStatisticsWithData:(CMPedometerData *)pedometerData { + _lastUpdateDate = pedometerData.endDate; + _totalNumberOfSteps = pedometerData.numberOfSteps.integerValue; + if (pedometerData.distance) { + _totalDistance = pedometerData.distance.doubleValue; + } else { + _totalDistance = -1; + } + + id delegate = self.delegate; + if ([delegate respondsToSelector:@selector(pedometerRecorderDidUpdate:)]) { + [delegate pedometerRecorderDidUpdate:self]; + } +} + +- (CMPedometer *)createPedometer { + return [[CMPedometer alloc] init]; +} + +- (void)start { + [super start]; + + _lastUpdateDate = nil; + _totalNumberOfSteps = 0; + _totalDistance = -1; + + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + self.pedometer = [self createPedometer]; + + if (![[self.pedometer class] isStepCountingAvailable]) { + [self finishRecordingWithError:[NSError errorWithDomain:NSCocoaErrorDomain + code:NSFeatureUnsupportedError + userInfo:@{@"recorder": self}]]; + return; + } + + _isRecording = YES; + ORKWeakTypeOf(self) weakSelf = self; + [self.pedometer startPedometerUpdatesFromDate:[NSDate date] withHandler:^(CMPedometerData *pedometerData, NSError *error) { + + BOOL success = NO; + if (pedometerData) { + success = [_logger append:[pedometerData ork_JSONDictionary] error:&error]; + dispatch_async(dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf updateStatisticsWithData:pedometerData]; + }); + } + if (!success || error) { + dispatch_async(dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf finishRecordingWithError:error]; + }); + } + }]; +} + +- (NSString *)recorderType { + return @"pedometer"; +} + +- (void)stop { + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } + error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (_isRecording) { + [self.pedometer stopPedometerUpdates]; + _isRecording = NO; + self.pedometer = nil; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:error]; +} + +- (BOOL)isRecording { + return _isRecording; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +@end + + +@implementation ORKPedometerRecorderConfiguration + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [super initWithIdentifier:identifier]; +} + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return [[ORKPedometerRecorder alloc] initWithIdentifier:self.identifier + step:step + outputDirectory:outputDirectory]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + return (isParentSame); +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionCoreMotionActivity; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.h new file mode 100755 index 0000000..e40d025 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKRangeOfMotionResult` class records the results of a range of motion active task. + + An `ORKRangeOfMotionResult` object records the angle values in degrees. + */ +ORK_CLASS_AVAILABLE +@interface ORKRangeOfMotionResult : ORKResult + +/** + The angle (degrees) from the device reference position at the start position. + */ +@property (nonatomic, assign) double start; + +/** + The angle (degrees) from the device reference position when the task finishes recording. + */ +@property (nonatomic, assign) double finish; + +/** + The angle (degrees) from the device reference position at the minimum angle (e.g. when the knee is most bent, such as at the end of the task). + */ +@property (nonatomic, assign) double minimum; + +/** + The angle (degrees) from the device reference position at the maximum angle (e.g. when the knee is extended). + */ +@property (nonatomic, assign) double maximum; + +/** + The angle (degrees) passed through from the start position to the maximum angle (e.g. from when the knee is flexed to when it is extended). + */ +@property (nonatomic, assign) double range; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.m new file mode 100755 index 0000000..5a4322a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionResult.m @@ -0,0 +1,94 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRangeOfMotionResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKRangeOfMotionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, start); + ORK_ENCODE_DOUBLE(aCoder, finish); + ORK_ENCODE_DOUBLE(aCoder, minimum); + ORK_ENCODE_DOUBLE(aCoder, maximum); + ORK_ENCODE_DOUBLE(aCoder, range); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, start); + ORK_DECODE_DOUBLE(aDecoder, finish); + ORK_DECODE_DOUBLE(aDecoder, minimum); + ORK_DECODE_DOUBLE(aDecoder, maximum); + ORK_DECODE_DOUBLE(aDecoder, range); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return isParentSame && + self.start == castObject.start && + self.finish == castObject.finish && + self.minimum == castObject.minimum && + self.maximum == castObject.maximum && + self.range == castObject.range; +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKRangeOfMotionResult *result = [super copyWithZone:zone]; + result.start = self.start; + result.finish = self.finish; + result.minimum = self.minimum; + result.maximum = self.maximum; + result.range = self.range; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"<%@: start: %f; finish: %f; minimum: %f; maximum: %f; range: %f>", self.class.description, self.start, self.finish, self.minimum, self.maximum, self.range]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.h new file mode 100755 index 0000000..4e247cd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKRangeOfMotionStep` class represents a step that takes a range of motion measurement. + */ +ORK_CLASS_AVAILABLE +@interface ORKRangeOfMotionStep : ORKActiveStep + +@property (nonatomic, assign) ORKPredefinedTaskLimbOption limbOption; //The left and/or right limb to be tested during the task + +- (instancetype)initWithIdentifier:(NSString *)identifier limbOption:(ORKPredefinedTaskLimbOption)limbOption; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.m new file mode 100755 index 0000000..feeb418 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStep.m @@ -0,0 +1,101 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRangeOfMotionStep.h" +#import "ORKRangeOfMotionStepViewController.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKRangeOfMotionStep + ++ (Class)stepViewControllerClass { + return [ORKRangeOfMotionStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier limbOption:(ORKPredefinedTaskLimbOption)limbOption { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldVibrateOnStart = YES; + self.shouldPlaySoundOnStart = YES; + self.shouldVibrateOnFinish = YES; + self.shouldPlaySoundOnFinish = YES; + self.shouldContinueOnFinish = YES; + self.shouldStartTimerAutomatically = YES; + self.limbOption = limbOption; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + if (self.limbOption != ORKPredefinedTaskLimbOptionLeft && self.limbOption != ORKPredefinedTaskLimbOptionRight) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:ORKLocalizedString(@"LIMB_OPTION_LEFT_OR_RIGHT_ERROR", nil) + userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKRangeOfMotionStep *step = [super copyWithZone:zone]; + step.limbOption = self.limbOption; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, limbOption); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, limbOption); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && (self.limbOption == castObject.limbOption)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.h new file mode 100755 index 0000000..d21b299 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + This class is used by the `ORKRangeOfMotionStep.` Its result corresponds to the device's orientation + as recorded by CoreMotion. + */ +ORK_CLASS_AVAILABLE +@interface ORKRangeOfMotionStepViewController : ORKActiveStepViewController { + double _startAngle; + double _newAngle; + double _minAngle; + double _maxAngle; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.m new file mode 100755 index 0000000..2cedaa2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRangeOfMotionStepViewController.m @@ -0,0 +1,231 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRangeOfMotionStepViewController.h" + +#import "ORKCustomStepView_Internal.h" +#import "ORKHelpers_Internal.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKDeviceMotionRecorder.h" +#import "ORKActiveStepView.h" +#import "ORKProgressView.h" +#import "ORKRangeOfMotionResult.h" +#import "ORKSkin.h" + + +#define radiansToDegrees(radians) ((radians) * 180.0 / M_PI) +#define allOrientationsForPitch(x, w, y, z) (atan2(2.0 * (x*w + y*z), 1.0 - 2.0 * (x*x + z*z))) +#define allOrientationsForRoll(x, w, y, z) (atan2(2.0 * (y*w - x*z), 1.0 - 2.0 * (y*y + z*z))) +#define allOrientationsForYaw(x, w, y, z) (asin(2.0 * (x*y - w*z))) + + +@interface ORKRangeOfMotionContentView : ORKActiveStepCustomView { + NSLayoutConstraint *_topConstraint; +} + +@property (nonatomic, strong, readonly) ORKProgressView *progressView; + +@end + + +@implementation ORKRangeOfMotionContentView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _progressView = [ORKProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_progressView]; + [self setUpConstraints]; + [self updateConstraintConstantsForWindow:self.window]; + } + return self; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView); + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_progressView]-(>=0)-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + _topConstraint = [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; // constant will be set in updateConstraintConstantsForWindow: + [constraints addObject:_topConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + const CGFloat CaptionBaselineToProgressTop = 100; + const CGFloat CaptionBaselineToStepViewTop = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTop, window); + _topConstraint.constant = CaptionBaselineToProgressTop - CaptionBaselineToStepViewTop; +} + +- (void)updateConstraints { + [self updateConstraintConstantsForWindow:self.window]; + [super updateConstraints]; +} + +@end + + +@interface ORKRangeOfMotionStepViewController () { + ORKRangeOfMotionContentView *_contentView; + UITapGestureRecognizer *_gestureRecognizer; + CMAttitude *_referenceAttitude; + UIInterfaceOrientation _orientation; +} + +@end + + +@implementation ORKRangeOfMotionStepViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + _contentView = [ORKRangeOfMotionContentView new]; + _contentView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _contentView; + _gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; + [self.activeStepView addGestureRecognizer:_gestureRecognizer]; +} + //This function records the angle of the device when the screen is tapped +- (void)handleTap:(UIGestureRecognizer *)sender { + [self calculateAndSetAngles]; + [self finish]; +} + +- (void)calculateAndSetAngles { + _startAngle = ([self getDeviceAngleInDegreesFromAttitude:_referenceAttitude]); + + //This function calculates maximum and minimum angles recorded by the device + if (_newAngle > _maxAngle) { + _maxAngle = _newAngle; + } + if (_minAngle == 0.0 || _newAngle < _minAngle) { + _minAngle = _newAngle; + } +} + +#pragma mark - ORKDeviceMotionRecorderDelegate + +- (void)deviceMotionRecorderDidUpdateWithMotion:(CMDeviceMotion *)motion { + if (!_referenceAttitude) { + _referenceAttitude = motion.attitude; + } + CMAttitude *currentAttitude = [motion.attitude copy]; + + [currentAttitude multiplyByInverseOfAttitude:_referenceAttitude]; + + double angle = [self getDeviceAngleInDegreesFromAttitude:currentAttitude]; + + //This function shifts the range of angles reported by the device from +/-180 degrees to -90 to +270 degrees, which should be sufficient to cover all ahievable knee and shoulder ranges of motion + BOOL shiftAngleRange = angle > 90 && angle <= 180; + if (shiftAngleRange) { + _newAngle = fabs(angle) - 360; + } else { + _newAngle = angle; + } + + [self calculateAndSetAngles]; +} + +/* + When the device is in Portrait mode, we need to get the attitude's pitch + to determine the device's angle. attitude.pitch doesn't return all + orientations, so we use the attitude's quaternion to calculate the + angle. + */ +- (double)getDeviceAngleInDegreesFromAttitude:(CMAttitude *)attitude { + if (!_orientation) { + _orientation = [UIApplication sharedApplication].statusBarOrientation; + } + double angle; + if (UIInterfaceOrientationIsLandscape(_orientation)) { + double x = attitude.quaternion.x; + double w = attitude.quaternion.w; + double y = attitude.quaternion.y; + double z = attitude.quaternion.z; + angle = radiansToDegrees(allOrientationsForRoll(x, w, y, z)); + } else { + double x = attitude.quaternion.x; + double w = attitude.quaternion.w; + double y = attitude.quaternion.y; + double z = attitude.quaternion.z; + angle = radiansToDegrees(allOrientationsForPitch(x, w, y, z)); + } + return angle; +} + + +#pragma mark - ORKActiveTaskViewController + +- (ORKResult *)result { + ORKStepResult *stepResult = [super result]; + + ORKRangeOfMotionResult *result = [[ORKRangeOfMotionResult alloc] initWithIdentifier:self.step.identifier]; + + result.start = 90.0 - _startAngle; + result.finish = result.start - _newAngle; + //Because the task uses pitch in the direction opposite to the original CoreMotion device axes (i.e. right hand rule), maximum and minimum angles are reported the 'wrong' way around for the knee and shoulder tasks + result.minimum = result.start - _maxAngle; + result.maximum = result.start - _minAngle; + result.range = fabs(result.maximum - result.minimum); + + stepResult.results = [self.addedResults arrayByAddingObject:result] ? : @[result]; + + return stepResult; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.h new file mode 100755 index 0000000..64bf1ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKReactionTimeContentView : ORKActiveStepCustomView + +- (void)setStimulusHidden:(BOOL)hidden; + +- (void)startSuccessAnimationWithDuration:(NSTimeInterval)duration completion:(nullable void (^)(void))completion; + +- (void)startFailureAnimationWithDuration:(NSTimeInterval)duration completion:(nullable void (^)(void))completion; + +- (void)resetAfterDelay:(NSTimeInterval)delay completion:(nullable void (^)(void))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.m new file mode 100755 index 0000000..c9c2758 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeContentView.m @@ -0,0 +1,109 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReactionTimeContentView.h" + +#import "ORKNavigationContainerView.h" +#import "ORKReactionTimeStimulusView.h" + + +@implementation ORKReactionTimeContentView { + ORKReactionTimeStimulusView *_stimulusView; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.translatesAutoresizingMaskIntoConstraints = NO; + [self addStimulusView]; + } + return self; +} + +- (void)startSuccessAnimationWithDuration:(NSTimeInterval)duration completion:(void (^)(void))completion { + [_stimulusView startSuccessAnimationWithDuration:duration completion:completion]; +} + +- (void)startFailureAnimationWithDuration:(NSTimeInterval)duration completion:(void (^)(void))completion { + [_stimulusView startFailureAnimationWithDuration:duration completion:completion]; +} + +- (void)resetAfterDelay:(NSTimeInterval)delay completion:(nullable void (^)(void))completion { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + _stimulusView.hidden = YES; + if (completion) { + completion(); + } + }); +} + +- (void)addStimulusView { + if (!_stimulusView) { + _stimulusView = [ORKReactionTimeStimulusView new]; + _stimulusView.translatesAutoresizingMaskIntoConstraints = NO; + _stimulusView.backgroundColor = self.tintColor; + [self addSubview:_stimulusView]; + [self setUpStimulusViewConstraints]; + } +} + +- (void)setStimulusHidden:(BOOL)hidden { + _stimulusView.hidden = hidden; +} + +- (void)setUpStimulusViewConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_stimulusView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_stimulusView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:8.0]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_stimulusView]-(>=0)-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:NSDictionaryOfVariableBindings(_stimulusView)]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.h new file mode 100755 index 0000000..ba87b02 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKFileResult; + +/** + The `ORKReactionTimeResult` class represents the result of a single successful attempt within an ORKReactionTimeStep. + + The `timestamp` property is equal to the value of systemUptime (in NSProcessInfo) when the stimulus occurred. + Each entry of motion data in this file contains a time interval which may be directly compared to timestamp in order to determine the elapsed time since the stimulus. + + The fileResult property references the motion data recorded from the beginning of the attempt until the threshold acceleration was reached. + Using the time taken to reach the threshold acceleration as the reaction time of a participant will yield a rather crude measurement. Rather, you should devise your own method using the data recorded to obtain an accurate approximation of the true reaction time. + + A reaction time result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize the sample for transmission to a server + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKReactionTimeResult: ORKResult + +@property (nonatomic, assign) NSTimeInterval timestamp; + +@property (nonatomic, strong) ORKFileResult *fileResult; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.m new file mode 100755 index 0000000..96a9f1d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeResult.m @@ -0,0 +1,85 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReactionTimeResult.h" + +#import "ORKFileResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKReactionTimeResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_OBJ(aCoder, fileResult); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_OBJ_CLASS(aDecoder, fileResult, ORKFileResult); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.timestamp == castObject.timestamp) && + ORKEqualObjects(self.fileResult, castObject.fileResult)) ; +} + +- (NSUInteger)hash { + return super.hash ^ [NSNumber numberWithDouble:self.timestamp].hash ^ self.fileResult.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKReactionTimeResult *result = [super copyWithZone:zone]; + result.fileResult = [self.fileResult copy]; + result.timestamp = self.timestamp; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; timestamp: %f; fileResult: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.timestamp, self.fileResult.description, self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.h new file mode 100755 index 0000000..891d439 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import AudioToolbox; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKReactionTimeStep : ORKActiveStep + +@property (nonatomic, assign) NSTimeInterval maximumStimulusInterval; + +@property (nonatomic, assign) NSTimeInterval minimumStimulusInterval; + +@property (nonatomic, assign) NSTimeInterval timeout; + +@property (nonatomic, assign) NSInteger numberOfAttempts; + +@property (nonatomic, assign) double thresholdAcceleration; + +@property (nonatomic, assign) SystemSoundID successSound; + +@property (nonatomic, assign) SystemSoundID timeoutSound; + +@property (nonatomic, assign) SystemSoundID failureSound; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.m new file mode 100755 index 0000000..ca15c1c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStep.m @@ -0,0 +1,148 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#import "ORKReactionTimeStep.h" + +#import "ORKReactionTimeViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKReactionTimeStep + ++ (Class)stepViewControllerClass { + return [ORKReactionTimeViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + self.shouldContinueOnFinish = YES; + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKReactionTimeStep *step = [super copyWithZone:zone]; + step.maximumStimulusInterval = self.maximumStimulusInterval; + step.minimumStimulusInterval = self.minimumStimulusInterval; + step.thresholdAcceleration = self.thresholdAcceleration; + step.timeout = self.timeout; + step.numberOfAttempts = self.numberOfAttempts; + step.successSound = self.successSound; + step.timeoutSound = self.timeoutSound; + step.failureSound = self.failureSound; + return step; +} + +- (void)validateParameters { + [super validateParameters]; + + if (self.minimumStimulusInterval <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"minimumStimulusInterval must be greater than zero" + userInfo:nil]; + } + if (self.maximumStimulusInterval < self.minimumStimulusInterval) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"maximumStimulusInterval cannot be less than minimumStimulusInterval" + userInfo:nil]; + } + if (self.thresholdAcceleration <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"thresholdAcceleration must be greater than zero" + userInfo:nil]; + } + if (self.timeout <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"timeout must be greater than zero" + userInfo:nil]; + } + if (self.numberOfAttempts <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"numberOfAttempts must be greater than zero" + userInfo:nil]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, maximumStimulusInterval); + ORK_DECODE_DOUBLE(aDecoder, minimumStimulusInterval); + ORK_DECODE_DOUBLE(aDecoder, thresholdAcceleration); + ORK_DECODE_DOUBLE(aDecoder, timeout); + ORK_DECODE_UINT32(aDecoder, successSound); + ORK_DECODE_UINT32(aDecoder, timeoutSound); + ORK_DECODE_UINT32(aDecoder, failureSound); + ORK_DECODE_INTEGER(aDecoder, numberOfAttempts); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, maximumStimulusInterval); + ORK_ENCODE_DOUBLE(aCoder, minimumStimulusInterval); + ORK_ENCODE_DOUBLE(aCoder, thresholdAcceleration); + ORK_ENCODE_DOUBLE(aCoder, timeout); + ORK_ENCODE_UINT32(aCoder, successSound); + ORK_ENCODE_UINT32(aCoder, timeoutSound); + ORK_ENCODE_UINT32(aCoder, failureSound); + ORK_ENCODE_INTEGER(aCoder, numberOfAttempts); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.maximumStimulusInterval == castObject.maximumStimulusInterval) && + (self.minimumStimulusInterval == castObject.minimumStimulusInterval) && + (self.thresholdAcceleration == castObject.thresholdAcceleration) && + (self.timeout == castObject.timeout) && + (self.successSound == castObject.successSound) && + (self.timeoutSound == castObject.timeoutSound) && + (self.failureSound == castObject.failureSound) && + (self.numberOfAttempts == castObject.numberOfAttempts)); +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (BOOL)startsFinished { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.h new file mode 100755 index 0000000..ac3b926 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKReactionTimeStimulusView : UIView + +- (void)reset; + +- (void)startSuccessAnimationWithDuration:(NSTimeInterval)duration completion:(nullable void(^)(void))completion; + +- (void)startFailureAnimationWithDuration:(NSTimeInterval)duration completion:(nullable void(^)(void))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.m new file mode 100755 index 0000000..c61f926 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeStimulusView.m @@ -0,0 +1,165 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReactionTimeStimulusView.h" + + +@implementation ORKReactionTimeStimulusView { + CAShapeLayer *_tickLayer; + CAShapeLayer *_crossLayer; +} + +static const CGFloat RoundReactionTimeViewDiameter = 122; + +- (instancetype)init { + self = [super init]; + if (self) { + self.layer.cornerRadius = RoundReactionTimeViewDiameter * 0.5; + } + return self; +} + +- (CGSize)intrinsicContentSize { + return CGSizeMake(RoundReactionTimeViewDiameter, RoundReactionTimeViewDiameter); +} + +- (void)reset { + [_tickLayer removeFromSuperlayer]; + [_crossLayer removeFromSuperlayer]; + _tickLayer = nil; + _crossLayer = nil; + self.layer.backgroundColor = self.tintColor.CGColor; +} + +- (void)startSuccessAnimationWithDuration:(NSTimeInterval)duration completion:(void(^)(void))completion { + if (self.hidden) { + if (completion) { + completion(); + } + return; + } + + [self addTickLayer]; + [CATransaction begin]; + [CATransaction setCompletionBlock:completion]; + CAMediaTimingFunction *timing = [[CAMediaTimingFunction alloc] initWithControlPoints:0.180739998817444 :0 :0.577960014343262 :0.918200016021729]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + [animation setTimingFunction:timing]; + animation.removedOnCompletion = NO; + [animation setFillMode:kCAFillModeForwards]; + animation.fromValue = @(0); + animation.toValue = @(1); + animation.duration = duration; + [_tickLayer addAnimation:animation forKey:@"strokeEnd"]; + [CATransaction commit]; +} + +- (void)startFailureAnimationWithDuration:(NSTimeInterval)duration completion:(void(^)(void))completion { + self.hidden = NO; + + self.layer.backgroundColor = [UIColor clearColor].CGColor; + [self addCrossLayer]; + [CATransaction begin]; + [CATransaction setCompletionBlock:completion]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + [animation setFillMode:kCAFillModeForwards]; + animation.fromValue = @([(CAShapeLayer *)[_crossLayer presentationLayer] strokeEnd]); + animation.toValue = @(1); + animation.duration = duration; + _crossLayer.strokeEnd = 1; + [_crossLayer addAnimation:animation forKey:@"strokeEnd"]; + [CATransaction commit]; +} + +- (void)setHidden:(BOOL)hidden { + [self reset]; + [super setHidden:hidden]; +} + +- (void)addCrossLayer { + _crossLayer = [self lineDrawingLayer]; + _crossLayer.strokeColor = [UIColor redColor].CGColor; + _crossLayer.path = [self crossPath]; + [self.layer addSublayer:_crossLayer]; +} + +- (void)addTickLayer { + _tickLayer = [self lineDrawingLayer]; + _tickLayer.strokeColor = [UIColor whiteColor].CGColor; + _tickLayer.path = [self tickPath]; + [self.layer addSublayer:_tickLayer]; +} + +- (CGPathRef)concealPath:(CGFloat)radius { + return [[UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) + radius:radius / 2 + startAngle:M_PI + M_PI_2 + endAngle:-M_PI_2 + clockwise:NO] CGPath]; +} + +- (CGPathRef)tickPath { + UIBezierPath *path = [self linePath]; + [path moveToPoint:(CGPoint){37,65}]; + [path addLineToPoint:(CGPoint){50,78}]; + [path addLineToPoint:(CGPoint){87,42}]; + return path.CGPath; +} + +- (CGPathRef)crossPath { + UIBezierPath *path = [self linePath]; + [path moveToPoint:(CGPoint){45,78}]; + [path addLineToPoint:(CGPoint){82,42}]; + [path moveToPoint:(CGPoint){45,42}]; + [path addLineToPoint:(CGPoint){82,78}]; + return path.CGPath; +} + +- (UIBezierPath *)linePath { + UIBezierPath *path = [UIBezierPath new]; + path.lineCapStyle = kCGLineCapRound; + path.lineWidth = 5; + return path; +} + +- (CAShapeLayer *)lineDrawingLayer { + CAShapeLayer *shapeLayer = [CAShapeLayer new]; + shapeLayer.strokeEnd = 0; + shapeLayer.lineWidth = 5; + shapeLayer.lineCap = kCALineCapRound; + shapeLayer.lineJoin = kCALineJoinRound; + shapeLayer.frame = self.layer.bounds; + shapeLayer.backgroundColor = [UIColor clearColor].CGColor; + shapeLayer.fillColor = nil; + return shapeLayer; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.h new file mode 100755 index 0000000..c60be91 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" +#import "ORKActiveStepViewController.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKReactionTimeViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.m new file mode 100755 index 0000000..7e1bfbd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKReactionTimeViewController.m @@ -0,0 +1,238 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReactionTimeViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKReactionTimeContentView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKReactionTimeResult.h" +#import "ORKReactionTimeStep.h" +#import "ORKResult.h" + +#import "ORKHelpers_Internal.h" + +#import +#import + + +@implementation ORKReactionTimeViewController { + ORKReactionTimeContentView *_reactionTimeContentView; + NSMutableArray *_results; + NSTimer *_stimulusTimer; + NSTimer *_timeoutTimer; + NSTimeInterval _stimulusTimestamp; + BOOL _validResult; + BOOL _timedOut; + BOOL _shouldIndicateFailure; +} + +static const NSTimeInterval OutcomeAnimationDuration = 0.3; + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + [self configureTitle]; + _results = [NSMutableArray new]; + _reactionTimeContentView = [ORKReactionTimeContentView new]; + self.activeStepView.activeCustomView = _reactionTimeContentView; + [_reactionTimeContentView setStimulusHidden:YES]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + _shouldIndicateFailure = YES; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + _shouldIndicateFailure = NO; +} + +#pragma mark - ORKActiveStepViewController + +- (void)start { + [super start]; + [self startStimulusTimer]; + +} + +#if TARGET_IPHONE_SIMULATOR +- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event { + if (event.type == UIEventSubtypeMotionShake) { + if (_validResult) { + ORKReactionTimeResult *reactionTimeResult = [[ORKReactionTimeResult alloc] initWithIdentifier:self.step.identifier]; + reactionTimeResult.timestamp = _stimulusTimestamp; + [_results addObject:reactionTimeResult]; + } + [self attemptDidFinish]; + } +} +#endif + + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + stepResult.results = [self.addedResults arrayByAddingObjectsFromArray:_results] ? : _results; + return stepResult; +} + +- (void)applicationWillResignActive:(NSNotification *)notification { + [super applicationWillResignActive:notification]; + _validResult = NO; + [_stimulusTimer invalidate]; + [_timeoutTimer invalidate]; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + [super applicationDidBecomeActive:notification]; + [self resetAfterDelay:0]; +} + +#pragma mark - ORKRecorderDelegate + +- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(ORKResult *)result { + if (_validResult) { + ORKReactionTimeResult *reactionTimeResult = [[ORKReactionTimeResult alloc] initWithIdentifier:self.step.identifier]; + reactionTimeResult.timestamp = _stimulusTimestamp; + reactionTimeResult.fileResult = (ORKFileResult *)result; + [_results addObject:reactionTimeResult]; + } + [self attemptDidFinish]; +} + +#pragma mark - ORKDeviceMotionRecorderDelegate + +- (void)deviceMotionRecorderDidUpdateWithMotion:(CMDeviceMotion *)motion { + CMAcceleration v = motion.userAcceleration; + double vectorMagnitude = sqrt(((v.x * v.x) + (v.y * v.y) + (v.z * v.z))); + if (vectorMagnitude > [self reactionTimeStep].thresholdAcceleration) { + [self stopRecorders]; + } +} + +#pragma mark - ORKReactionTimeStepViewController + +- (ORKReactionTimeStep *)reactionTimeStep { + return (ORKReactionTimeStep *)self.step; +} + +- (void)configureTitle { + NSString *format = ORKLocalizedString(@"REACTION_TIME_TASK_ATTEMPTS_FORMAT", nil); + NSString *text = [NSString stringWithFormat:format, ORKLocalizedStringFromNumber(@(_results.count + 1)), ORKLocalizedStringFromNumber(@([self reactionTimeStep].numberOfAttempts))]; + [self.activeStepView updateTitle:ORKLocalizedString(@"REACTION_TIME_TASK_ACTIVE_STEP_TITLE", nil) text:text]; +} + +- (void)attemptDidFinish { + void (^completion)(void) = ^{ + if (_results.count == [self reactionTimeStep].numberOfAttempts) { + [self finish]; + } else { + [self resetAfterDelay:2]; + } + }; + if (_validResult) { + [self indicateSuccess:completion]; + } else { + [self indicateFailure:completion]; + } + _validResult = NO; + _timedOut = NO; + [_stimulusTimer invalidate]; + [_timeoutTimer invalidate]; +} + +- (void)indicateSuccess:(void(^)(void))completion { + [_reactionTimeContentView startSuccessAnimationWithDuration:OutcomeAnimationDuration completion:completion]; + AudioServicesPlaySystemSound([self reactionTimeStep].successSound); +} + +- (void)indicateFailure:(void(^)(void))completion { + if (!_shouldIndicateFailure) { + return; + } + [_reactionTimeContentView startFailureAnimationWithDuration:OutcomeAnimationDuration completion:completion]; + SystemSoundID sound = _timedOut ? [self reactionTimeStep].timeoutSound : [self reactionTimeStep].failureSound; + AudioServicesPlayAlertSound(sound); +} + +- (void)resetAfterDelay:(NSTimeInterval)delay { + ORKWeakTypeOf(self) weakSelf = self; + [_reactionTimeContentView resetAfterDelay:delay completion:^{ + [weakSelf configureTitle]; + [weakSelf start]; + }]; +} + +- (void)startStimulusTimer { + _stimulusTimer = [NSTimer scheduledTimerWithTimeInterval:[self stimulusInterval] target:self selector:@selector(stimulusTimerDidFire) userInfo:nil repeats:NO]; +} + +- (void)stimulusTimerDidFire { + _stimulusTimestamp = [NSProcessInfo processInfo].systemUptime; + [_reactionTimeContentView setStimulusHidden:NO]; + _validResult = YES; + [self startTimeoutTimer]; +} + +- (void)startTimeoutTimer { + NSTimeInterval timeout = [self reactionTimeStep].timeout; + if (timeout > 0) { + _timeoutTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:@selector(timeoutTimerDidFire) userInfo:nil repeats:NO]; + } +} + +- (void)timeoutTimerDidFire { + _validResult = NO; + _timedOut = YES; + [self stopRecorders]; + +#if TARGET_IPHONE_SIMULATOR + // Device motion recorder won't work, so manually trigger didfinish + [self attemptDidFinish]; +#endif +} + +- (NSTimeInterval)stimulusInterval { + ORKReactionTimeStep *step = [self reactionTimeStep]; + NSTimeInterval range = step.maximumStimulusInterval - step.minimumStimulusInterval; + NSTimeInterval randomFactor = ((NSTimeInterval)arc4random() / RAND_MAX) * range; + return randomFactor + step.minimumStimulusInterval; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.h new file mode 100755 index 0000000..74b6ec0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.h @@ -0,0 +1,597 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import HealthKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKRecorder; +@class ORKResult; +@class ORKStep; + +/** + The `ORKRecorderConfiguration` class is the abstract base class for recorder configurations + that can be attached to an active step (`ORKActiveStep`). + + Recorder configurations provide an easy way to collect CoreMotion + or other sensor data into a serialized format during the duration of an active step. + If you want to filter or process the data in real time, it is better to + use the existing APIs directly. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + + To add a new recorder, subclass both `ORKRecorderConfiguration` and `ORKRecorder`, + and add the new `ORKRecorderConfiguration` subclass to an `ORKActiveStep` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKRecorderConfiguration : NSObject + +/* + The `init` and `new` methods are unavailable outside the framework on `ORKRecorderConfiguration`, + because it is an abstract class. + + `ORKRecorderConfiguration` classes should be initialized with custom designated + initializers on each subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + A short string that uniquely identifies the recorder configuration within the step. + + The identifier is reproduced in the results of a recorder created from this configuration. In fact, the only way to link a result + (an `ORKFileResult` object) to the recorder that generated it is to look at the value of + `identifier`. To accurately identify recorder results, you need to ensure that recorder identifiers + are unique within each step. + + In some cases, it can be useful to link the recorder identifier to a unique identifier in a + database; in other cases, it can make sense to make the identifier human + readable. + */ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + Returns a recorder instance using this configuration. + + @param step The step for which this recorder is being created. + @param outputDirectory The directory in which all output file data should be written (if producing `ORKFileResult` instances). + + @return A configured recorder instance. + */ +- (nullable ORKRecorder *)recorderForStep:(nullable ORKStep *)step outputDirectory:(nullable NSURL *)outputDirectory; + +/** + Returns the HealthKit types for which this recorder requires read access in a set of `HKSampleType` objects. + + Typically, the task view controller automatically collects + and collates the types of HealthKit data requested by each of the active steps in a task, + and requests access to them at the end of the initial instruction + steps in the task. + + If your recorder requires or would benefit from read access to HealthKit at + runtime during the task, return the appropriate set of `HKSampleType` objects. + */ +- (nullable NSSet *)requestedHealthKitTypesForReading; + +@end + + +/** + The `ORKAccelerometerRecorderConfiguration` subclass configures + the collection of accelerometer data during an active step. + + Accelerometer data is serialized to JSON and returned as an `ORKFileResult` object. + For details on the format, see `CMAccelerometerData+ORKJSONDictionary`. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKAccelerometerRecorderConfiguration : ORKRecorderConfiguration + +/** + The frequency of accelerometer data collection in samples per second (Hz). + */ +@property (nonatomic, readonly) double frequency; + +/** + Returns an initialized accelerometer recorder configuration using the specified frequency. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + @param frequency The frequency of accelerometer data collection in samples per second (Hz). + + @return An initialized accelerometer recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency NS_DESIGNATED_INITIALIZER; + +/** + Returns a new accelerometer recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the accelerometer recorder configuration. + + @return A new accelerometer recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +/** + The `ORKAudioRecorderConfiguration` class represents a configuration that records + audio data during an active step. + + An `ORKAudioRecorderConfiguration` generates an `ORKAudioRecorder` object. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKAudioRecorderConfiguration : ORKRecorderConfiguration + +/** + The audio format settings for the recorder. + + Pass the settings for the recording session to the `AVAudioRecorder` method `initWithURL:settings:error:`. + For information on the settings available for an audio recorder, see "AV Foundation Audio Settings Constants" in + the AVFoundation documentation. + + The results are returned as an `ORKFileResult` object, which points to an audio file. + */ +@property (nonatomic, readonly, nullable) NSDictionary *recorderSettings; + +/** + Returns an initialized audio recorder configuration using the specified settings. + + This method is the designated initializer. + + For information on the settings available for an audio recorder, see "AV Foundation Audio Settings Constants". + + @param identifier The unique identifier of the recorder configuration. + @param recorderSettings The settings for the recording session. + + @return An initialized audio recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier recorderSettings:(NSDictionary *)recorderSettings NS_DESIGNATED_INITIALIZER; + +/** + Returns a new audio recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the audio recorder configuration. + + @return A new audio recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +/** + The `ORKDeviceMotionRecorderConfiguration` class represents a configuration + that records device motion data during an active step. + + Device motion data is the processed motion data provided by CoreMotion and obtained + from a `CMMotionManager` object. The data can include measures of the overall device orientation + obtained from combining accelerometer, magnetometer, and gyroscope data. + + Device motion data is serialized to JSON and returned as an `ORKFileResult` object. + For details on the format, see `CMDeviceMotion+ORKJSONDictionary`. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKDeviceMotionRecorderConfiguration : ORKRecorderConfiguration + +/** + The frequency of motion data collection in samples per second (Hz). + */ +@property (nonatomic, readonly) double frequency; + +/** + Returns an initialized device motion recorder configuration using the specified frequency. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + @param frequency Motion data collection frequency in samples per second (Hz). + + @return An initialized device motion recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency NS_DESIGNATED_INITIALIZER; + +/** + Returns a new device motion recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the device motion recorder configuration. + + @return A new device motion recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +/** + The `ORKPedometerRecorderConfiguration` class represents a configuration + that records pedometer data during an active step. + + Pedometer data consists of information about the processed steps provided by CoreMotion, obtained + from a `CMPedometer` object. The pedometer object essentially reports the total number of steps taken since the + start of recording, updating the value every time a significant number of steps have + been detected. + + Pedometer data is serialized to JSON and returned as an `ORKFileResult` object. + For details on the format, see `CMPedometerData+ORKJSONDictionary`. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKPedometerRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized pedometer recorder configuration. + + The recorder instantiates a `CMPedometer` object, so no additional parameters besides + the identifier are required. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + + @return An initialized pedometer recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new pedometer recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the pedometer recorder configuration. + + @return A new pedometer recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +/** + The `ORKLocationRecorderConfiguration` class represents a configuration + that records location data during an active step. + + The location data reported is the location provided by CoreLocation. + + If this configuration is included in an active step in a task, the task + view controller requests access to location data at the end of the + initial instruction steps in the task. + + Location data is serialized to JSON and returned as an `ORKFileResult` object. + For details on the format, see `CLLocation+ORKJSONDictionary`. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + + No additional parameters besides the identifier are required. + */ +ORK_CLASS_AVAILABLE +@interface ORKLocationRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized location recorder configuration. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + + @return An initialized location recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new location recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the location recorder configuration. + + @return A new location recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +/** + The `ORKHealthQuantityTypeRecorderConfiguration` class represents a configuration + that records data from a HealthKit quantity type during an active step. + + Before you can use this configuration, you must use Xcode to enable the appropriate HealthKit entitlement + for your app. + + HealthKit quantity type data is serialized to JSON and returned as an `ORKFileResult` object. + For details on the format, see `HKSample+ORKJSONDictionary`. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthQuantityTypeRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized health quantity type recorder configuration using the specified quantity type and unit designation. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + @param quantityType The quantity type that should be collected during the active task. + @param unit The unit for the data that should be collected and serialized. + + @return An initialized health quantity type recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier healthQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit NS_DESIGNATED_INITIALIZER; + +/** + Returns a new health quantity type recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the health quantity type recorder configuration. + + @return A new health quantity type recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + The quantity type to be collected from HealthKit. (read-only) + */ +@property (nonatomic, readonly, copy) HKQuantityType *quantityType; + +/** + The unit in which to serialize the data from HealthKit. (read-only) + */ +@property (nonatomic, readonly, copy) HKUnit *unit; + +@end + +ORK_CLASS_AVAILABLE +#if defined(__IPHONE_12_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_12_0 +API_AVAILABLE(ios(12.0)) +@interface ORKHealthClinicalTypeRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized health clinical type recorder configuration using the specified clinical type. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + @param healthClinicalType The HKClinicalType that should be collected during the active task. + @param healthFHIRResourceType The HKFHIRResourceType that should be used as predicate while querying for the healthClinicalType. Providing a HKFHIRResourceType that does not correspond to a HKClinicalType will NOT generate any result. + + @return An initialized health clinical type recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + healthClinicalType:(HKClinicalType *)healthClinicalType + healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType NS_DESIGNATED_INITIALIZER API_AVAILABLE(ios(12.0)); + +/** + Returns a new health clinical type recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the health clinical type recorder configuration. + + @return A new health clinical type recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + The HKClinicalType to be collected from HealthKit. (read-only) + */ +@property (nonatomic, readonly, copy) HKClinicalType *healthClinicalType; + +/** + The HKFHIRResourceType to used as predicate for HKQuery. (read-only) + */ +@property (nonatomic, readonly, copy) HKFHIRResourceType healthFHIRResourceType; + +@end +#endif + +/** + The `ORKStreamingAudioRecorderConfiguration` class represents a configuration that records streaming + audio data during an active step. + + An `ORKStreamingAudioRecorderConfiguration` generates an `ORKStreamingAudioRecorder` object. + + To use a recorder, include its configuration in the `recorderConfigurations` property + of an `ORKActiveStep` object, include that step in a task, and present it with + a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKStreamingAudioRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized audio recorder configuration. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + + @return An initialized audio recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new audio recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the audio recorder configuration. + + @return A new audio recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + +/** + The `ORKRecorderDelegate` protocol defines methods that the delegate of an `ORKRecorder` object should use to handle errors and log the + completed results. + + This protocol is implemented by `ORKActiveStepViewController`; your app should not +need to implement it. + */ +@protocol ORKRecorderDelegate + +/** + Tells the delegate that the recorder has completed with the specified result. + + Typically, this method is called once when recording is stopped. + + @param recorder The generating recorder object. + @param result The generated result. + */ +- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(nullable ORKResult *)result; + +/** + Tells the delegate that recording failed. + + Typically, this method is called once when the error occurred. + + @param recorder The generating recorder object. + @param error The error that occurred. + */ +- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error; + +@end + + +/** + A recorder is the runtime companion to an `ORKRecorderConfiguration` object, and is + usually generated by one. + + During active tasks, it is often useful to collect one or more pieces of data + from sensors on the device. In research tasks, it's not always + necessary to display that data, but it's important to record it in a controlled manner. + + An active step (`ORKActiveStep`) has an array of recorder configurations + (`ORKRecorderConfiguration`) that identify the types of data it needs to record + for the duration of the step. When a step starts, the active step view controller + instantiates a recorder for each of the step's recorder configurations. + The step view controller starts the recorder when the active step is started, and stops the + recorder when the active step is finished. + + The results of recording are typically written to a file specified by the value of the `outputDirectory` property. + + Usually, the `ORKActiveStepViewController` object is the recorder's delegate, and it + receives callbacks when errors occur or when recording is complete. + */ +ORK_CLASS_AVAILABLE +@interface ORKRecorder : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/// @name Configuration + +@property (nonatomic, weak, nullable) id delegate; + +/** + A short string that uniquely identifies the recorder (usually assigned by the recorder configuration). + + The identifier is reproduced in the results of a recorder created from this configuration. In fact, the only way to link a result + (an `ORKFileResult` object) to the recorder that generated it is to look at the value of + `identifier`. To accurately identify recorder results, you need to ensure that recorder identifiers + are unique within each step. + + In some cases, it can be useful to link the recorder identifier to a unique identifier in a + database; in other cases, it can make sense to make the identifier human + readable. + */ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + The step that produced this recorder, configured during initialization. + */ +@property (nonatomic, strong, readonly, nullable) ORKStep *step; + +/** + The configuration that produced this recorder. + */ +@property (nonatomic, strong, readonly, nullable) ORKRecorderConfiguration *configuration; + +/** + The file URL of the output directory configured during initialization. + + Typically, you set the `outputDirectory` property for the `ORKTaskViewController` object + before presenting the task. + */ +@property (nonatomic, copy, readonly, nullable) NSURL *outputDirectory; + +/** + Returns the log prefix for the log file. + */ +- (nullable NSString *)logName; + +/// @name Runtime Life Cycle + +/** + Starts data recording. + + If an error occurs when recording starts, it is returned through the delegate. + */ +- (void)start NS_REQUIRES_SUPER; + +/** + Stops data recording, which generally triggers the return of results. + + If an error occurs when stopping the recorder, it is returned through the delegate. + Subclasses should call `finishRecordingWithError:` rather than calling super. + */ +- (void)stop NS_REQUIRES_SUPER; + +/** + A Boolean value indicating whether the recorder is currently recording. + + @return `YES` if the recorder is recording; otherwise, `NO`. + */ +@property (nonatomic, readonly, getter=isRecording) BOOL recording; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.m new file mode 100755 index 0000000..677a63d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder.m @@ -0,0 +1,263 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRecorder.h" +#import "ORKRecorder_Internal.h" + +#import "ORKDataLogger.h" +#import "ORKFileResult.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKRecorderConfiguration + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + ORKThrowInvalidArgumentExceptionIfNil(identifier); + _identifier = [identifier copy]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + return 0; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + return nil; +} + +- (NSSet *)requestedHealthKitTypesForReading { + return nil; +} +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionNone; +} + +@end + + +@implementation ORKRecorder { + UIBackgroundTaskIdentifier _backgroundTask; + NSUUID *_recorderUUID; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + @throw [NSException exceptionWithName:NSGenericException reason:@"Use designated initializer" userInfo:nil]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + self = [super init]; + if (self) { + if (nil == identifier) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"identifier cannot be nil." userInfo:nil]; + } + + _identifier = [identifier copy]; + _outputDirectory = outputDirectory; + self.step = step; + _backgroundTask = NSNotFound; + _recorderUUID = [NSUUID UUID]; + } + return self; +} + +- (void)viewController:(UIViewController *)viewController willStartStepWithView:(UIView *)view { +} + +- (void)start { + if (self.continuesInBackground) { + UIApplication *app = [UIApplication sharedApplication]; + UIBackgroundTaskIdentifier oldTask = _backgroundTask; + _backgroundTask = [app beginBackgroundTaskWithName:[NSString stringWithFormat:@"%@.%p",NSStringFromClass([self class]),self] + expirationHandler:^{ + [self stop]; + }]; + if (oldTask != NSNotFound) { + [app endBackgroundTask:oldTask]; + } + } + self.startDate = [NSDate date]; +} + +- (void)stop { + [self finishRecordingWithError:nil]; + [self reset]; +} + +- (void)finishRecordingWithError:(NSError *)error { + // NOTE. This method may be called multiple times (once when someone tries + // to finish, and another time with -stop is actually called. + + if (error) { + // ALWAYS report errors to the delegate, even if we think we're finished already + id localDelegate = self.delegate; + if (localDelegate && [localDelegate respondsToSelector:@selector(recorder:didFailWithError:)]) { + [localDelegate recorder:self didFailWithError:error]; + } + [self reset]; + } + + if (_backgroundTask != NSNotFound) { + // End the background task asynchronously, so whatever we're doing cleaning up the recorder has a chance to complete. + UIBackgroundTaskIdentifier identifier = _backgroundTask; + _backgroundTask = NSNotFound; + + // Hold the background task for a little extra to give time for the next step to kick in, + // if it is an automatic transition. + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] endBackgroundTask:identifier]; + }); + } +} + +- (NSURL *)recordingDirectoryURL { + if (!_outputDirectory) { + return nil; + } + return [NSURL fileURLWithPath:[_outputDirectory.path stringByAppendingPathComponent:[NSString stringWithFormat:@"recorder-%@", _recorderUUID.UUIDString]]]; +} + +- (NSString *)recorderType { + return @"recorder"; +} + +- (NSString *)logName { + return [NSString stringWithFormat:@"%@_%@", [self recorderType], _recorderUUID.UUIDString]; +} + +- (ORKDataLogger *)makeJSONDataLoggerWithError:(NSError **)errorOut { + NSURL *workingDir = [self recordingDirectoryURL]; + if (!workingDir) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteInvalidFileNameError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"ERROR_RECORDER_NO_OUTPUT_DIRECTORY", nil)}]; + } + return nil; + } + if (![[NSFileManager defaultManager] createDirectoryAtURL:workingDir withIntermediateDirectories:YES attributes:nil error:errorOut]) { + return nil; + } + + NSString *identifier = [self logName]; + NSString *logName = [identifier stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; + + // Class B data protection for temporary file during active task logging. + ORKDataLogger *logger = [[ORKDataLogger alloc] initWithDirectory:workingDir logName:logName formatter:[ORKJSONLogFormatter new] delegate:nil]; + + logger.fileProtectionMode = ORKFileProtectionCompleteUnlessOpen; + return logger; +} + +- (void)reset { + _recorderUUID = [NSUUID UUID]; +} + +- (NSString *)mimeType { + return nil; +} + +- (NSDictionary *)userInfo { + return nil; +} + +- (void)applyFileProtection:(ORKFileProtectionMode)fileProtection toFileAtURL:(NSURL *)url { + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error = nil; + if (! [fileManager setAttributes:@{NSFileProtectionKey: ORKFileProtectionFromMode(fileProtection)} ofItemAtPath:[url path] error:&error]) { + ORK_Log_Error("Error setting %@ on %@: %@", ORKFileProtectionFromMode(fileProtection), url, error); + } +} + +- (void)reportFileResultWithFile:(NSURL *)fileUrl error:(NSError *)error { + + id localDelegate = self.delegate; + if (fileUrl && !error) { + if (localDelegate && [localDelegate respondsToSelector:@selector(recorder:didCompleteWithResult:)]) { + ORKFileResult *result = [[ORKFileResult alloc] initWithIdentifier:self.identifier]; + result.contentType = [self mimeType]; + result.fileURL = fileUrl; + result.userInfo = self.userInfo; + result.startDate = self.startDate; + + [localDelegate recorder:self didCompleteWithResult:result]; + + // Point future recording at a new directory + [self reset]; + } + } else { + if (!error) { + error = [NSError errorWithDomain:NSCocoaErrorDomain + code:NSFileReadNoSuchFileError + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"ERROR_RECORDER_NO_DATA", nil)}]; + } + [self finishRecordingWithError:error]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Internal.h new file mode 100755 index 0000000..72c4b8f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Internal.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRecorder_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKDataLogger; + +@interface ORKRecorder () + +@property (nonatomic, strong, nullable) ORKStep *step; + +@property (nonatomic, strong, nullable) ORKRecorderConfiguration *configuration; + +@property (nonatomic) BOOL continuesInBackground; + +@property (nonatomic, copy, nullable) NSDate *startDate; + +- (NSString *)recorderType; + +- (nullable ORKDataLogger *)makeJSONDataLoggerWithError:(NSError * _Nullable *)error NS_REQUIRES_SUPER; + +- (void)reset NS_REQUIRES_SUPER; + +- (void)reportFileResultWithFile:(nullable NSURL *)fileUrl error:(nullable NSError *)error; + +- (nullable NSURL *)recordingDirectoryURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Private.h new file mode 100755 index 0000000..8dda163 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKRecorder_Private.h @@ -0,0 +1,151 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStep; + +/** + The `ORKTouchRecorderConfiguration` is a recorder configuration class for + generating an `ORKTouchRecorder`. + + It is currently considered private, and is not used in any of the active tasks. + */ +ORK_CLASS_AVAILABLE +@interface ORKTouchRecorderConfiguration : ORKRecorderConfiguration + +/** + Returns an initialized touch recorder configuration. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + + @return An initialized touch recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new touch recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the touch recorder configuration. + + @return A new touch recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +@interface ORKRecorder () + +/** + Returns an initialized recorder. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder. + @param step The step for which this recorder is being created. + @param outputDirectory The directory in which all output file data should be written (if producing `ORKFileResult` instances). + + @return An initialized recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier step:(nullable ORKStep *)step outputDirectory:(nullable NSURL *)outputDirectory; + +/** + A preparation step to provide viewController and view before record starting. + + The step view controller should call this method before starting the recorder, + so that recorders that need a view or gesture recognizer in order to function + can attach themselves. + + @param viewController The view controller that is about to 'start' + @param view Primary active view for the step. + */ +- (void)viewController:(UIViewController *)viewController willStartStepWithView:(nullable UIView *)view; + +/** + Indicates that recording has failed; stop recording and report the error to the + delegate + + @param error Error that occurred. + */ +- (void)finishRecordingWithError:(nullable NSError *)error; + +/** + Helper for subclasses to request that file protection be applied to a file on disk. + + This method is exposed to facilitate unit testing. + + @param fileProtection Level of file protection desired + @param url URL of file to protect. + */ +- (void)applyFileProtection:(ORKFileProtectionMode)fileProtection toFileAtURL:(NSURL *)url; + +@end + + +@interface ORKRecorderConfiguration () + +/** + Returns an initialized recorder configuration. + + This method is the designated initializer. + + @param identifier The unique identifier of the recorder configuration. + + @return An initialized recorder configuration. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new recorder configuration initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the recorder configuration. + + @return A new recorder configuration. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Returns the permission mask indicating the permissions required for this configuration. + + This method is typically overridden in new recorder configuration subclasses. + */ +- (ORKPermissionMask)requestedPermissionMask; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.h new file mode 100755 index 0000000..4a7c0c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKSecondaryTaskStep : ORKInstructionStep + +@property (nonatomic) ORKOrderedTask *secondaryTask; +@property (nonatomic) NSString *secondaryTaskButtonTitle; +@property (nonatomic) NSString *nextButtonTitle; +@property (nonatomic) NSUInteger requiredAttempts; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.m new file mode 100755 index 0000000..72b2db3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStep.m @@ -0,0 +1,99 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKSecondaryTaskStep.h" +#import "ORKSecondaryTaskStepViewController.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKSecondaryTaskStep + + ++ (Class)stepViewControllerClass { + return [ORKSecondaryTaskStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + + self = [super initWithIdentifier:identifier]; + if (self) { + self.requiredAttempts = 1; + self.optional = YES; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, secondaryTask, ORKOrderedTask); + ORK_DECODE_OBJ_CLASS(aDecoder, secondaryTaskButtonTitle, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, nextButtonTitle, NSString); + ORK_DECODE_INTEGER(aDecoder, requiredAttempts); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, secondaryTask); + ORK_ENCODE_OBJ(aCoder, secondaryTaskButtonTitle); + ORK_ENCODE_OBJ(aCoder, nextButtonTitle); + ORK_ENCODE_INTEGER(aCoder, requiredAttempts); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSecondaryTaskStep *step = [super copyWithZone:zone]; + step->_secondaryTask = [_secondaryTask copy]; + step->_secondaryTaskButtonTitle = [_secondaryTaskButtonTitle copy]; + step->_nextButtonTitle = [_nextButtonTitle copy]; + step->_requiredAttempts = _requiredAttempts; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.secondaryTask, castObject.secondaryTask) + && ORKEqualObjects(self.secondaryTaskButtonTitle, castObject.secondaryTaskButtonTitle) + && ORKEqualObjects(self.nextButtonTitle, castObject.nextButtonTitle) + && self.requiredAttempts == castObject.requiredAttempts); +} + +- (NSUInteger)hash { + return super.hash ^ self.secondaryTask.hash ^ self.secondaryTaskButtonTitle.hash ^ self.nextButtonTitle.hash ^ self.requiredAttempts; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.h new file mode 100755 index 0000000..c387e60 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKSecondaryTaskStepViewController : ORKInstructionStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.m new file mode 100755 index 0000000..c3aae96 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSecondaryTaskStepViewController.m @@ -0,0 +1,124 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKSecondaryTaskStepViewController.h" +#import "ORKSecondaryTaskStep.h" +#import "ORKStepViewController_Internal.h" +#import "ORKHelpers_Internal.h" +#import "ORKTaskViewController.h" +#import "ORKInstructionStepContainerView.h" +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKStepView.h" +#import "ORKNavigationContainerView.h" + +@interface ORKSecondaryTaskStepViewController () + +@end + +@implementation ORKSecondaryTaskStepViewController { + ORKTaskViewController *secondaryTaskViewController; + NSUInteger requiredAttempts; + NSUInteger numberOfTimesTaskCompleted; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + numberOfTimesTaskCompleted = 0; +} + +- (ORKSecondaryTaskStep *)secondaryTaskStep { + return (ORKSecondaryTaskStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + [self resetSecondaryTaskViewController]; + requiredAttempts = [self secondaryTaskStep].requiredAttempts; + [self updateButtonState]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + if ([self secondaryTaskStep].nextButtonTitle) { + [continueButtonItem setTitle:[self secondaryTaskStep].nextButtonTitle]; + } + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + + [skipButtonItem setTitle:[self secondaryTaskStep].secondaryTaskButtonTitle ? : ORKLocalizedString(@"SECONDARY_TASK_START_BUTTON", nil)]; + [skipButtonItem setTarget:self]; + [skipButtonItem setAction:@selector(startSecondaryTaskHandler:)]; +} + +- (void)startSecondaryTaskHandler:(id)sender{ + [self startSecondaryTaskButtonTapped]; +} + +- (void)startSecondaryTaskButtonTapped { + if (secondaryTaskViewController) { + [self presentViewController:secondaryTaskViewController animated:YES completion:NULL]; + } +} + +- (void)resetSecondaryTaskViewController { + secondaryTaskViewController.delegate = nil; + secondaryTaskViewController = nil; + secondaryTaskViewController = [[ORKTaskViewController alloc] initWithTask:[self secondaryTaskStep].secondaryTask taskRunUUID:[NSUUID UUID]]; + secondaryTaskViewController.delegate = self; + secondaryTaskViewController.outputDirectory = self.taskViewController.outputDirectory; +} + +- (void)taskCompleted { + numberOfTimesTaskCompleted = numberOfTimesTaskCompleted + 1; + [self updateButtonState]; +} + +- (void)updateButtonState { + + [self.stepView.navigationFooterView setContinueEnabled:(requiredAttempts == 0) || (numberOfTimesTaskCompleted >= requiredAttempts)]; + + [self.stepView.navigationFooterView setSkipEnabled:(numberOfTimesTaskCompleted > requiredAttempts)]; +} + +#pragma mark ORKTaskViewControllerDelegate + +- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error { + if (reason == ORKTaskViewControllerFinishReasonCompleted) { + + [self taskCompleted]; + [self resetSecondaryTaskViewController]; + } + [taskViewController dismissViewControllerAnimated:YES completion:NULL]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.h new file mode 100755 index 0000000..121f26c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRangeOfMotionStep.h" + + +/** + The `ORKShoulderRangeOfMotionStep` class represents a step that takes a range of motion measurement + for either a left or right shoulder. + */ +ORK_CLASS_AVAILABLE +@interface ORKShoulderRangeOfMotionStep : ORKRangeOfMotionStep + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.m new file mode 100755 index 0000000..567e492 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStep.m @@ -0,0 +1,43 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKShoulderRangeOfMotionStep.h" +#import "ORKShoulderRangeOfMotionStepViewController.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKShoulderRangeOfMotionStep + ++ (Class)stepViewControllerClass { + return [ORKShoulderRangeOfMotionStepViewController class]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.h new file mode 100755 index 0000000..1f6598f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRangeOfMotionStepViewController.h" + + +/** + This class override its parent's result because here + a flex result of 0 degrees would mean the device is at a 90 degree angle. + */ +ORK_CLASS_AVAILABLE +@interface ORKShoulderRangeOfMotionStepViewController : ORKRangeOfMotionStepViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.m new file mode 100755 index 0000000..9f8742b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKShoulderRangeOfMotionStepViewController.m @@ -0,0 +1,58 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKShoulderRangeOfMotionStepViewController.h" + +#import "ORKRangeOfMotionResult.h" +#import "ORKStepViewController_Internal.h" + + +@implementation ORKShoulderRangeOfMotionStepViewController + +#pragma mark - ORKActiveTaskViewController + +- (ORKResult *)result { + ORKStepResult *stepResult = [super result]; + + ORKRangeOfMotionResult *result = [[ORKRangeOfMotionResult alloc] initWithIdentifier:self.step.identifier]; + result.start = 90.0 - _startAngle; + result.finish = result.start - _newAngle; + //Because the task uses pitch in the direction opposite to the original CoreMotion device axes (i.e. right hand rule), maximum and minimum angles are reported the 'wrong' way around for the knee and shoulder tasks + result.minimum = result.start - _maxAngle; + result.maximum = result.start - _minAngle; + result.range = fabs(result.maximum - result.minimum); + + stepResult.results = [self.addedResults arrayByAddingObject:result] ? : @[result]; + + return stepResult; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.h new file mode 100755 index 0000000..b78c60f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.h @@ -0,0 +1,87 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKSpatialSpanGame` class represents a model object that represents one game-like experience in a spatial span memory task. + + A game consists of a subset of a permutation of the integers [0 .. gameSize - 1], + which represent the sequence of targets that should be tapped. + */ +@interface ORKSpatialSpanGame : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized spatial span game using the specified game size, sequence length, and seed. + + This method is the designated initializer. + @param gameSize The number of tiles in the game. + @param sequenceLength The number of elements in the sequence that the user has to remember. + @param seed The generator that should be used for generating the sequence. A value of 0 means that a random seed is used. + */ +- (instancetype)initWithGameSize:(NSInteger)gameSize + sequenceLength:(NSInteger)sequenceLength + seed:(uint32_t)seed NS_DESIGNATED_INITIALIZER; + +/// The number of tiles in the game. +@property (nonatomic, readonly) NSInteger gameSize; + +/// The length of the sequence. A sequence is a sub-array of a random permutation of integers (0..gameSize-1) that has a length of `sequenceLength`. +@property (nonatomic, readonly) NSInteger sequenceLength; + +/// The seed to use to generate the sequence. Note that if you pass `seed` to another game, you get the same game. +@property (nonatomic, readonly) uint32_t seed; + +/** + Enumerates the sequence, calling the block once for each element. + + @param handler The block to be called for each element in the sequence. The `handler` block takes the following parameters: + + `step` The step in the sequence. The step starts at 0 and increments by one on each call. + `tileIndex` The index in [ 0 .. gameSize ] that corresponds to the step's element of the sequence. + `isLastStep` A Boolean value that indicates if this is the last step in the sequence. + `stop` A Boolean value that indicates if the enumeration should be terminated (pass `NO` to terminate the enumeration). + */ + +- (void)enumerateSequenceWithHandler:(void(^)(NSInteger step, NSInteger tileIndex, BOOL isLastStep, BOOL *stop))handler; + +/// Returns the value of the specified step in the sequence. +- (NSInteger)tileIndexForStep:(NSInteger)step; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.m new file mode 100755 index 0000000..c965058 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGame.m @@ -0,0 +1,112 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanGame.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSpatialSpanGame { + NSInteger *_sequence; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (void)generateSequence { + _sequence = calloc(_gameSize, sizeof(NSInteger)); + if (_sequence == NULL) { + return; + } + for (NSInteger i = 0; i < _gameSize; i++) { + _sequence[i] = i; + } + + // Knuth algorithm: swap each with a random element elsewhere in the array. + // Note: we will only use the first _sequenceLength elements of this array + srandom(_seed); + for (NSInteger i = 0; i < _gameSize; i++) { + NSInteger rand_i = arc4random() % _gameSize; + NSInteger tmp = _sequence[i]; + _sequence[i] = _sequence[rand_i]; + _sequence[rand_i] = tmp; + } +} + +- (void)dealloc { + if (_sequence != NULL) { + free(_sequence); + _sequence = NULL; + } +} + +- (instancetype)initWithGameSize:(NSInteger)gameSize + sequenceLength:(NSInteger)sequenceLength + seed:(uint32_t)seed { + self = [super init]; + if (self) { + _gameSize = gameSize; + _sequenceLength = sequenceLength; + NSParameterAssert(_gameSize > 0); + NSParameterAssert(_sequenceLength > 0); + NSParameterAssert(_sequenceLength < _gameSize); + _seed = seed; + if (_seed == 0) { + _seed = arc4random(); + } + [self generateSequence]; + + if (_sequence == NULL) { + self = nil; + } + } + return self; +} + +/// Step parameter is the step in the sequence; tileIndex is the value of that step of the sequence. +- (void)enumerateSequenceWithHandler:(void(^)(NSInteger step, NSInteger tileIndex, BOOL isLastStep, BOOL *stop))handler { + BOOL stop = NO; + for (NSInteger i = 0; i < _sequenceLength; i++) { + handler(i, _sequence[i], (i == _sequenceLength), &stop); + if (stop) break; + } +} + +- (NSInteger)tileIndexForStep:(NSInteger)step { + return _sequence[step]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.h new file mode 100755 index 0000000..26e6bac --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKSpatialSpanGame; + +typedef NS_ENUM(NSInteger, ORKSpatialSpanResult) { + ORKSpatialSpanResultIgnore, + ORKSpatialSpanResultCorrect, + ORKSpatialSpanResultIncorrect +}; + +typedef NS_ENUM(NSInteger, ORKSpatialSpanTargetState) { + ORKSpatialSpanTargetStateQuiescent, + ORKSpatialSpanTargetStateActive, + ORKSpatialSpanTargetStateCorrect, + ORKSpatialSpanTargetStateIncorrect +}; + +@interface ORKSpatialSpanGameState : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithGame:(ORKSpatialSpanGame *)game NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, strong, readonly, nullable) ORKSpatialSpanGame *game; + +@property (nonatomic, readonly, getter=isComplete) BOOL complete; + +/// Enumerates all tiles, indicating the state of each tile at the specified state of the game. +- (void)enumerateTilesWithHandler:(void (^)(NSInteger tileIndex, ORKSpatialSpanTargetState state, BOOL *stop))handler; + +/// Returns a result indicating whether the user's tap was correct, incorrect, or ignorable. +- (ORKSpatialSpanResult)playTileIndex:(NSInteger)tileIndex; + +- (void)reset; + +// Returns `NSNotFound` if there have been no plays +- (NSInteger)lastSuccessfulTileIndex; + +// Number of tiles that have been successfully tapped +- (NSInteger)currentStepIndex; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.m new file mode 100755 index 0000000..04659c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanGameState.m @@ -0,0 +1,122 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanGameState.h" + +#import "ORKSpatialSpanGame.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSpatialSpanGameState { + NSMutableArray *_plays; + ORKSpatialSpanTargetState *_states; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithGame:(ORKSpatialSpanGame *)game { + self = [super init]; + if (self) { + _game = game; + _plays = [NSMutableArray array]; + + _states = calloc([_game gameSize], sizeof(ORKSpatialSpanTargetState)); + if (_states == NULL) { + self = nil; + } + } + return self; +} + +- (void)dealloc { + if (_states != NULL) { + free(_states); + _states = NULL; + } +} + +- (void)reset { + const NSInteger gameSize = [_game gameSize]; + for (NSInteger tileIndex = 0; tileIndex < gameSize; tileIndex++) { + _states[tileIndex] = ORKSpatialSpanTargetStateQuiescent; + } + [_plays removeAllObjects]; + _complete = NO; +} + +/// Enumerate all tiles, indicating the state of each tile at this point in the game. +- (void)enumerateTilesWithHandler:(void (^)(NSInteger tileIndex, ORKSpatialSpanTargetState state, BOOL *stop))handler { + const NSInteger gameSize = [_game gameSize]; + BOOL stop = NO; + for (NSInteger tileIndex = 0; tileIndex < gameSize; tileIndex++) { + handler(tileIndex, _states[tileIndex], &stop); + if (stop) break; + } +} + +/// User tapped a tile. Returns YES if it was the correct next tile. +- (ORKSpatialSpanResult)playTileIndex:(NSInteger)tileIndex { + if (_states[tileIndex] != ORKSpatialSpanTargetStateQuiescent) { + return ORKSpatialSpanResultIgnore; + } + + NSInteger sequencePosition = _plays.count; + BOOL correct = ([_game tileIndexForStep:sequencePosition] == tileIndex); + _states[tileIndex] = correct ? ORKSpatialSpanTargetStateCorrect : ORKSpatialSpanTargetStateIncorrect; + if (correct) { + [_plays addObject:@(tileIndex)]; + } + if (_plays.count >= [_game sequenceLength]) { + _complete = YES; + } + + return correct ? ORKSpatialSpanResultCorrect : ORKSpatialSpanResultIncorrect; +} + +- (NSInteger)currentStepIndex { + return _plays.count; +} + +- (NSInteger)lastSuccessfulTileIndex { + if (!_plays.count) { + return NSNotFound; + } + return ((NSNumber *)_plays.lastObject).integerValue; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.h new file mode 100755 index 0000000..0a0a2b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCustomStepView_Internal.h" +#import "ORKSpatialSpanTargetView.h" +#import "ORKBorderedButton.h" + + +NS_ASSUME_NONNULL_BEGIN + +typedef struct { + NSInteger width; + NSInteger height; +} ORKGridSize; + +@class ORKSpatialSpanMemoryGameView; + +@protocol ORKSpatialSpanMemoryGameViewDelegate + +- (void)gameView:(ORKSpatialSpanMemoryGameView *)gameView didTapTileWithIndex:(NSInteger)tileIndex recognizer:(UITapGestureRecognizer *)recognizer; + +@end + + +@interface ORKSpatialSpanMemoryGameView : UIView + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, assign) ORKGridSize gridSize; + +@property (nonatomic, readonly) NSInteger numberOfTiles; + +@property (nonatomic, readonly, nullable) NSArray *tileViews; + +@property (nonatomic, strong, nullable) UIImage *customTargetImage; + +- (void)resetTilesAnimated:(BOOL)animated; + +- (void)setState:(ORKSpatialSpanTargetState)state forTileIndex:(NSInteger)tileIndex animated:(BOOL)animated; +- (ORKSpatialSpanTargetState)stateForTileIndex:(NSInteger)tileIndex; + +@end + + +@interface ORKSpatialSpanMemoryContentView : ORKActiveStepCustomView + +@property (nonatomic, strong, readonly) ORKSpatialSpanMemoryGameView *gameView; + +@property (nonatomic, assign, getter=isFooterHidden) BOOL footerHidden; + +@property (nonatomic, strong, nullable) NSString *capitalizedPluralItemDescription; + +// Things that can be shown in the footer. +@property (nonatomic, assign) NSInteger numberOfItems; +@property (nonatomic, assign) NSInteger score; +@property (nonatomic, strong, nullable) ORKBorderedButton *buttonItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.m new file mode 100755 index 0000000..7734fa3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryContentView.m @@ -0,0 +1,366 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanMemoryContentView.h" + +#import "ORKActiveStepQuantityView.h" +#import "ORKNavigationContainerView.h" +#import "ORKSpatialSpanTargetView.h" +#import "ORKVerticalContainerView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +// #define LAYOUT_DEBUG 1 + +@implementation ORKSpatialSpanMemoryGameView + +#pragma mark Primary interface + +- (void)setGridSize:(ORKGridSize)gridSize { + _gridSize = gridSize; +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.2]; +#endif + [self resetTilesAnimated:NO]; +} + +- (NSInteger)numberOfTiles { + return _gridSize.width * _gridSize.height; +} + +- (ORKSpatialSpanTargetView *)makeTargetView { + ORKSpatialSpanTargetView *targetView = [[ORKSpatialSpanTargetView alloc] init]; + targetView.customTargetImage = _customTargetImage; + return targetView; +} + +- (void)resetTilesAnimated:(BOOL)animated { + NSArray *currentViews = _tileViews; + NSInteger numberOfTilesOld = _tileViews.count; + NSInteger numberOfTilesNew = _gridSize.width * _gridSize.height; + NSMutableArray *newViews = [NSMutableArray arrayWithCapacity:numberOfTilesNew]; + NSArray *viewsToRemove = nil; + if (numberOfTilesOld <= numberOfTilesNew) { + [newViews addObjectsFromArray:currentViews]; + NSInteger tilesToAdd = numberOfTilesNew - numberOfTilesOld; + for (NSInteger idx = 0; idx < tilesToAdd; idx++) { + [newViews addObject:[self makeTargetView]]; + } + } else { + [newViews addObjectsFromArray:[currentViews subarrayWithRange:(NSRange){0,numberOfTilesNew}]]; + viewsToRemove = [currentViews subarrayWithRange:(NSRange){numberOfTilesNew, numberOfTilesOld-numberOfTilesNew}]; + } + + void(^resetBlock)(void) = ^(void) { + for (ORKSpatialSpanTargetView *view in viewsToRemove) { + view.delegate = nil; + [view removeFromSuperview]; + } + if (numberOfTilesNew > numberOfTilesOld) { + NSArray *addedViews = [newViews subarrayWithRange:(NSRange){numberOfTilesOld,numberOfTilesNew-numberOfTilesOld}]; + for (ORKSpatialSpanTargetView *view in addedViews) { + view.delegate = self; + [self addSubview:view]; + } + } + + _tileViews = newViews; + for (ORKSpatialSpanTargetView *view in _tileViews) { + [view setState:ORKSpatialSpanTargetStateQuiescent]; + } + + [self layoutSubviews]; + }; + + if (animated) { + [UIView transitionWithView:self duration:0.3 options:UIViewAnimationOptionCurveEaseInOut animations:resetBlock completion:NULL]; + } else { + resetBlock(); + } + +} + +- (void)setCustomTargetImage:(UIImage *)customTargetImage { + _customTargetImage = customTargetImage; + for (ORKSpatialSpanTargetView *view in _tileViews) { + view.customTargetImage = _customTargetImage; + } +} + +- (void)targetView:(ORKSpatialSpanTargetView *)targetView recognizer:(UITapGestureRecognizer *)recognizer { + [_delegate gameView:self + didTapTileWithIndex:[_tileViews indexOfObject:targetView] + recognizer:recognizer]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect bounds = self.bounds; + CGFloat gridItemEdgeLength = ORKFloorToViewScale(MIN(bounds.size.width / _gridSize.width, bounds.size.height / _gridSize.height), self); + + gridItemEdgeLength = MIN(gridItemEdgeLength, 114); + CGSize gridItemSize = (CGSize){gridItemEdgeLength, gridItemEdgeLength}; + + CGPoint centeringOffset = CGPointZero; + centeringOffset.x = 0.5 * (bounds.size.width - (gridItemSize.width * _gridSize.width)); + centeringOffset.y = 0.5 * (bounds.size.height - (gridItemSize.height * _gridSize.height)); + + NSInteger tileIndex = 0; + for (NSInteger x = 0; x < _gridSize.width; x++) { + for (NSInteger y = 0; y < _gridSize.height; y++) { + ORKSpatialSpanTargetView *targetView = _tileViews[tileIndex]; + + CGPoint origin = (CGPoint){.x = ORKFloorToViewScale(centeringOffset.x + x * gridItemSize.width, self), + .y = ORKFloorToViewScale(centeringOffset.y + y * gridItemSize.height, self)}; + targetView.frame = (CGRect){.origin=origin, .size=gridItemSize}; + + tileIndex ++; + } + } +} + +- (void)setState:(ORKSpatialSpanTargetState)state forTileIndex:(NSInteger)tileIndex animated:(BOOL)animated { + ORKSpatialSpanTargetView *view = _tileViews[tileIndex]; + [view setState:state animated:animated]; +} + +- (ORKSpatialSpanTargetState)stateForTileIndex:(NSInteger)tileIndex { + return [(ORKSpatialSpanTargetView *)_tileViews[tileIndex] state]; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return NO; +} + +@end + + +@implementation ORKSpatialSpanMemoryContentView { + ORKQuantityPairView *_quantityPairView; + UIView *_continueView; +} + +- (ORKActiveStepQuantityView *)countView { + return [_quantityPairView leftView]; +} + +- (ORKActiveStepQuantityView *)scoreView { + return [_quantityPairView rightView]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _gameView = [ORKSpatialSpanMemoryGameView new]; + _gameView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_gameView]; + + _quantityPairView = [ORKQuantityPairView new]; + _quantityPairView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_quantityPairView]; + + _continueView = [UIView new]; + _continueView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_continueView]; + + ORKActiveStepQuantityView *countView = [self countView]; + ORKActiveStepQuantityView *scoreView = [self scoreView]; + + _capitalizedPluralItemDescription = [ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE", nil) capitalizedStringWithLocale:[NSLocale currentLocale]]; + + countView.title = [NSString localizedStringWithFormat:ORKLocalizedString(@"MEMORY_GAME_ITEM_COUNT_TITLE_%@", nil), _capitalizedPluralItemDescription]; + scoreView.title = ORKLocalizedString(@"MEMORY_GAME_SCORE_TITLE", nil); + countView.enabled = YES; + scoreView.enabled = YES; + + self.numberOfItems = 0; + self.score = 0; + + [self updateMargins]; + +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.2]; + _gameView.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.2]; + _continueView.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; + _quantityPairView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.2]; + [self scoreView].backgroundColor = [[UIColor purpleColor] colorWithAlphaComponent:0.2]; + [self countView].backgroundColor = [[UIColor purpleColor] colorWithAlphaComponent:0.2]; +#endif + + [self setUpConstraints]; + } + return self; +} + +- (void)setCapitalizedPluralItemDescription:(NSString *)capitalizedPluralItemDescription { + _capitalizedPluralItemDescription = capitalizedPluralItemDescription; + [self countView].title = [NSString localizedStringWithFormat:ORKLocalizedString(@"MEMORY_GAME_ITEM_COUNT_TITLE_%@", nil), _capitalizedPluralItemDescription]; +} + +- (void)setNumberOfItems:(NSInteger)numberOfItems { + ORKActiveStepQuantityView *countView = [self countView]; + countView.value = [self stringWithNumberFormatter:numberOfItems]; +} + +- (void)setScore:(NSInteger)score { + ORKActiveStepQuantityView *scoreView = [self scoreView]; + scoreView.value = [self stringWithNumberFormatter:score]; +} + +- (NSString *)stringWithNumberFormatter: (NSInteger)integer { + NSNumberFormatter *formatter = [NSNumberFormatter new]; + formatter.numberStyle = NSNumberFormatterNoStyle; + formatter.locale = [NSLocale currentLocale]; + + return [NSString stringWithFormat:@"%@", [formatter stringFromNumber:[NSNumber numberWithLong:(long)integer]]]; +} + +- (void)updateFooterHidden { + _quantityPairView.hidden = (_footerHidden || (_buttonItem != nil)); +} + +- (void)setFooterHidden:(BOOL)footerHidden { + _footerHidden = footerHidden; + [self updateFooterHidden]; +} + +- (void)setButtonItem:(ORKBorderedButton *)buttonItem { + _buttonItem = buttonItem; + if (buttonItem) { + buttonItem.contentEdgeInsets = (UIEdgeInsets){.top = 2, .bottom = 2, .left = 8, .right = 8}; + buttonItem.translatesAutoresizingMaskIntoConstraints = NO; + [_continueView addSubview:buttonItem]; + [[NSLayoutConstraint constraintWithItem:_buttonItem + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_continueView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0] setActive:YES]; + [[NSLayoutConstraint constraintWithItem:_buttonItem + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_continueView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0] setActive:YES]; + } + else { + [_buttonItem removeFromSuperview]; + } + + _continueView.hidden = (buttonItem == nil); + [self updateFooterHidden]; +} + +- (void)updateMargins { + CGFloat margin = ORKStandardHorizontalMarginForView(self); + self.layoutMargins = (UIEdgeInsets){.left = margin, .right = margin}; + _quantityPairView.layoutMargins = self.layoutMargins; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self updateMargins]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self updateMargins]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_gameView, _quantityPairView, _continueView); + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_gameView(>=ORKScreenMetricMinimumGameViewHeightForMemoryGame)][_quantityPairView]|" + options:NSLayoutFormatAlignAllCenterX + metrics:@{@"ORKScreenMetricMinimumGameViewHeightForMemoryGame": @(ORKGetMetricForWindow(ORKScreenMetricMinimumGameViewHeightForMemoryGame, self.window))} + views:views]]; + NSLayoutConstraint *gameViewHeightConstraint = [NSLayoutConstraint constraintWithItem:_gameView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:CGFLOAT_MIN]; + gameViewHeightConstraint.priority = UILayoutPriorityDefaultLow - 1; + [constraints addObject:gameViewHeightConstraint]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_gameView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_quantityPairView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_continueView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_continueView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_quantityPairView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_continueView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_quantityPairView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + NSLayoutConstraint *maxWidthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + maxWidthConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:maxWidthConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.h new file mode 100755 index 0000000..c3e8e81 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.h @@ -0,0 +1,205 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKSpatialSpanMemoryGameRecord; +@class ORKSpatialSpanMemoryGameTouchSample; + +/// An enumeration of values that describe the status of a round of the spatial span memory game. +typedef NS_ENUM(NSInteger, ORKSpatialSpanMemoryGameStatus) { + + /// Unknown status. The game is still in progress or has not started. + ORKSpatialSpanMemoryGameStatusUnknown, + + /// Success. The user has completed the sequence. + ORKSpatialSpanMemoryGameStatusSuccess, + + /// Failure. The user has completed the sequence incorrectly. + ORKSpatialSpanMemoryGameStatusFailure, + + /// Timeout. The game timed out during play. + ORKSpatialSpanMemoryGameStatusTimeout +} ORK_ENUM_AVAILABLE; + + +/** + The `ORKSpatialSpanMemoryResult` class represents the result of a spatial span memory step (`ORKSpatialSpanMemoryStep`). + + A spatial span memory result records the score displayed to the user, the number of games, the + objects recording the actual game, and the user's taps in response + to the game. + + A spatial span memory result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpatialSpanMemoryResult : ORKResult + +/** + The score in the game. + + The score is an integer value that monotonically increases during the game, across multiple rounds. + */ +@property (nonatomic, assign) NSInteger score; + +/** + The number of games. + + The number of rounds that the user participated in, including successful, + failed, and timed out rounds. + */ +@property (nonatomic, assign) NSInteger numberOfGames; + +/** + The number of failures. + + The number of rounds in which the user participated, but did not correctly + complete the sequence. + */ +@property (nonatomic, assign) NSInteger numberOfFailures; + +/** + An array that contains the results of the games played. + + Each item in the array is an `ORKSpatialSpanMemoryGameRecord` object. + */ +@property (nonatomic, copy, nullable) NSArray *gameRecords; + +@end + + +/** + The `ORKSpatialSpanMemoryGameRecord` class records the results of a + single playable instance of the spatial span memory game. + + A spatial span memory game record is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + + These records are found in the `records` property of an `ORKSpatialSpanMemoryResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpatialSpanMemoryGameRecord : NSObject + +/** + An integer used as the seed for the sequence. + + If you pass a specific seed value to another game, you get the same sequence. + */ +@property (nonatomic, assign) uint32_t seed; + +/** + An array of `NSNumber` objects that represent the sequence that was presented to the user. + + The sequence is an array of length `sequenceLength` that contains a random permutation of integers (0..`gameSize`-1) + */ +@property (nonatomic, copy, nullable) NSArray *sequence; + +/** + The size of the game. + + The game size is the number of targets, such as flowers, in the game. + */ +@property (nonatomic, assign) NSInteger gameSize; + +/** + An array of `NSValue` objects wrapped in `CGRect` that record the frames of the target + tiles as displayed, relative to the step view. + */ +@property (nonatomic, copy, nullable) NSArray *targetRects; + +/** + An array of `ORKSpatialSpanMemoryGameTouchSample` objects that record the onscreen locations + the user tapped during the game. + */ +@property (nonatomic, copy, nullable) NSArray *touchSamples; + +/** + A value indicating whether the user completed the sequence and, if the game was not completed, why not. + */ +@property (nonatomic, assign) ORKSpatialSpanMemoryGameStatus gameStatus; + +/** + An integer that records the number of points obtained during this game toward + the total score. + */ +@property (nonatomic, assign) NSInteger score; + +@end + + +/** + The `ORKSpatialSpanMemoryGameTouchSample` class represents a tap during the + spatial span memory game. + + A spatial span memory game touch sample is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpatialSpanMemoryGameTouchSample : NSObject + +/** + A timestamp (in seconds) from the beginning of the game. + */ +@property (nonatomic, assign) NSTimeInterval timestamp; + +/** + The index of the target that was tapped. + + Usually, this index is a value that ranges between 0 and the number of targets, + indicating which target was tapped. + + If the touch was outside all of the targets, the value of this property is -1. + */ +@property (nonatomic, assign) NSInteger targetIndex; + +/** + A point that records the touch location in the step's view. + */ +@property (nonatomic, assign) CGPoint location; + +/** + A Boolean value indicating whether the tapped target was the correct one. + + The value of this property is `YES` when the tapped target is the correct + one, and `NO` otherwise. + */ +@property (nonatomic, assign, getter=isCorrect) BOOL correct; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.m new file mode 100755 index 0000000..0a3d6d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryResult.m @@ -0,0 +1,218 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanMemoryResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKSpatialSpanMemoryGameTouchSample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_INTEGER(aCoder, targetIndex); + ORK_ENCODE_CGPOINT(aCoder, location); + ORK_ENCODE_BOOL(aCoder, correct); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_INTEGER(aDecoder, targetIndex); + ORK_DECODE_CGPOINT(aDecoder, location); + ORK_DECODE_BOOL(aDecoder, correct); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return ((self.timestamp == castObject.timestamp) && + (self.targetIndex == castObject.targetIndex) && + (CGPointEqualToPoint(self.location, castObject.location)) && + (self.isCorrect == castObject.isCorrect)); +} + +- (NSUInteger)hash { + return super.hash ^ [self targetIndex] ^ [self isCorrect]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpatialSpanMemoryGameTouchSample *sample = [[[self class] allocWithZone:zone] init]; + sample.timestamp = self.timestamp; + sample.targetIndex = self.targetIndex; + sample.location = self.location; + sample.correct = self.isCorrect; + + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; timestamp: %@; targetIndex: %@; location: %@; correct: %@>", self.class.description, self, @(self.timestamp), @(self.targetIndex), NSStringFromCGPoint(self.location), @(self.isCorrect)]; +} + +@end + + +@implementation ORKSpatialSpanMemoryGameRecord + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_UINT32(aCoder, seed); + ORK_ENCODE_OBJ(aCoder, sequence); + ORK_ENCODE_INTEGER(aCoder, gameSize); + ORK_ENCODE_OBJ(aCoder, touchSamples); + ORK_ENCODE_INTEGER(aCoder, gameStatus); + ORK_ENCODE_INTEGER(aCoder, score); + ORK_ENCODE_OBJ(aCoder, targetRects); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_UINT32(aDecoder, seed); + ORK_DECODE_OBJ_ARRAY(aDecoder, sequence, NSNumber); + ORK_DECODE_INTEGER(aDecoder, gameSize); + ORK_DECODE_OBJ_ARRAY(aDecoder, touchSamples, ORKSpatialSpanMemoryGameTouchSample); + ORK_DECODE_INTEGER(aDecoder, gameStatus); + ORK_DECODE_INTEGER(aDecoder, score); + ORK_DECODE_OBJ_ARRAY(aDecoder, targetRects, NSValue); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return ((self.seed == castObject.seed) && + (ORKEqualObjects(self.sequence, castObject.sequence)) && + (ORKEqualObjects(self.touchSamples, castObject.touchSamples)) && + (self.gameSize == castObject.gameSize) && + (self.gameStatus == castObject.gameStatus) && + (self.score == castObject.score) && + (ORKEqualObjects(self.targetRects, castObject.targetRects))); +} + +- (NSUInteger)hash { + return super.hash ^ [self seed] ^ [self gameSize] ^ [self score] ^ [self gameStatus]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpatialSpanMemoryGameRecord *record = [[[self class] allocWithZone:zone] init]; + record.seed = self.seed; + record.sequence = [self.sequence copyWithZone:zone]; + record.touchSamples = [self.touchSamples copyWithZone:zone]; + record.gameSize = self.gameSize; + record.gameStatus = self.gameStatus; + record.score = self.score; + record.targetRects = [self.targetRects copyWithZone:zone]; + return record; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; seed: %@; sequence: %@; gameSize: %@; gameStatus: %@; score: %@>", self.class.description, self, @(self.seed), self.sequence, @(self.gameSize), @(self.gameStatus), @(self.score)]; +} + +@end + + +@implementation ORKSpatialSpanMemoryResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, score); + ORK_ENCODE_INTEGER(aCoder, numberOfGames); + ORK_ENCODE_INTEGER(aCoder, numberOfFailures); + ORK_ENCODE_OBJ(aCoder, gameRecords); + +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, score); + ORK_DECODE_INTEGER(aDecoder, numberOfGames); + ORK_DECODE_INTEGER(aDecoder, numberOfFailures); + ORK_DECODE_OBJ_ARRAY(aDecoder, gameRecords, ORKSpatialSpanMemoryGameRecord); + + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.score == castObject.score) && + (self.numberOfGames == castObject.numberOfGames) && + (self.numberOfFailures == castObject.numberOfFailures) && + (ORKEqualObjects(self.gameRecords, castObject.gameRecords))); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpatialSpanMemoryResult *result = [super copyWithZone:zone]; + result.score = self.score; + result.numberOfGames = self.numberOfGames; + result.numberOfFailures = self.numberOfFailures; + result.gameRecords = [self.gameRecords copyWithZone:zone]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; score: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], @(self.score), self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.h new file mode 100755 index 0000000..dbb4a3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Spatian span memory step. + + This step type is used to present the interactive spatial span memory activity. You are not + supposed to use this step on its own. Use `ORKOrderedTask`'s `+spatialSpanMemoryTaskWithIdentifier:intendedUseDescription:initialSpan:minimumSpan:maximumSpan:playSpeed:maximumTests:maximumConsecutiveFailures:customTargetImage:customTargetPluralName:requireReversal:options:` method to get a complete spatial + span memory activity task instead. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpatialSpanMemoryStep : ORKActiveStep + +@property (nonatomic, assign) NSInteger initialSpan; +@property (nonatomic, assign) NSInteger minimumSpan; +@property (nonatomic, assign) NSInteger maximumSpan; +@property (nonatomic, assign) NSTimeInterval playSpeed; +@property (nonatomic, assign) NSInteger maximumTests; +@property (nonatomic, assign) NSInteger maximumConsecutiveFailures; +@property (nonatomic, assign) BOOL requireReversal; +@property (nonatomic, strong, nullable) UIImage *customTargetImage; +@property (nonatomic, copy, nullable) NSString *customTargetPluralName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.m new file mode 100755 index 0000000..bbeec5f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStep.m @@ -0,0 +1,181 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanMemoryStep.h" + +#import "ORKSpatialSpanMemoryStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSpatialSpanMemoryStep + ++ (Class)stepViewControllerClass { + return [ORKSpatialSpanMemoryStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldStartTimerAutomatically = YES; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpatialSpanMemoryStep *step = [super copyWithZone:zone]; + step.initialSpan = self.initialSpan; + step.minimumSpan = self.minimumSpan; + step.maximumSpan = self.maximumSpan; + step.playSpeed = self.playSpeed; + step.maximumTests = self.maximumTests; + step.maximumConsecutiveFailures = self.maximumConsecutiveFailures; + step.requireReversal = self.requireReversal; + step.customTargetImage = self.customTargetImage; + step.customTargetPluralName = self.customTargetPluralName; + return step; +} + +- (void)validateParameters { + [super validateParameters]; + + NSInteger const ORKSpatialSpanMemoryTaskMinimumInitialSpan = 2; + NSInteger const ORKSpatialSpanMemoryTaskMaximumSpan = 20; + NSTimeInterval const ORKSpatialSpanMemoryTaskMinimumPlaySpeed = 0.5; + NSTimeInterval const ORKSpatialSpanMemoryTaskMaximumPlaySpeed = 20; + NSInteger const ORKSpatialSpanMemoryTaskMinimumMaxTests = 1; + NSInteger const ORKSpatialSpanMemoryTaskMinimumMaxConsecutiveFailures = 1; + + if ( self.initialSpan < ORKSpatialSpanMemoryTaskMinimumInitialSpan) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"initialSpan cannot be less than %@.", @(ORKSpatialSpanMemoryTaskMinimumInitialSpan)] + userInfo:nil]; + } + + if ( self.minimumSpan > self.initialSpan) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"initialSpan cannot be less than minimumSpan." userInfo:nil]; + } + + if ( self.initialSpan > self.maximumSpan) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"maximumSpan cannot be less than initialSpan." userInfo:nil]; + } + + if ( self.maximumSpan > ORKSpatialSpanMemoryTaskMaximumSpan) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"maximumSpan cannot be more than %@.", @(ORKSpatialSpanMemoryTaskMaximumSpan)] + userInfo:nil]; + } + + if (self.playSpeed < ORKSpatialSpanMemoryTaskMinimumPlaySpeed) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"playSpeed cannot be shorter than %@ seconds.", @(ORKSpatialSpanMemoryTaskMinimumPlaySpeed)] + userInfo:nil]; + } + + if (self.playSpeed > ORKSpatialSpanMemoryTaskMaximumPlaySpeed) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"playSpeed cannot be longer than %@ seconds.", @(ORKSpatialSpanMemoryTaskMaximumPlaySpeed)] + userInfo:nil]; + } + + if (self.maximumTests < ORKSpatialSpanMemoryTaskMinimumMaxTests) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"maximumTests cannot be less than %@.", @(ORKSpatialSpanMemoryTaskMinimumMaxTests)] + userInfo:nil]; + } + + if (self.maximumConsecutiveFailures < ORKSpatialSpanMemoryTaskMinimumMaxConsecutiveFailures) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"maximumConsecutiveFailures cannot be less than %@.", @(ORKSpatialSpanMemoryTaskMinimumMaxConsecutiveFailures)] + userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, initialSpan); + ORK_DECODE_INTEGER(aDecoder, minimumSpan); + ORK_DECODE_INTEGER(aDecoder, maximumSpan); + ORK_DECODE_INTEGER(aDecoder, playSpeed); + ORK_DECODE_INTEGER(aDecoder, maximumTests); + ORK_DECODE_INTEGER(aDecoder, maximumConsecutiveFailures); + ORK_DECODE_BOOL(aDecoder, requireReversal); + ORK_DECODE_IMAGE(aDecoder, customTargetImage); + ORK_DECODE_OBJ_CLASS(aDecoder, customTargetPluralName, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, initialSpan); + ORK_ENCODE_INTEGER(aCoder, minimumSpan); + ORK_ENCODE_INTEGER(aCoder, maximumSpan); + ORK_ENCODE_INTEGER(aCoder, playSpeed); + ORK_ENCODE_INTEGER(aCoder, maximumTests); + ORK_ENCODE_INTEGER(aCoder, maximumConsecutiveFailures); + ORK_ENCODE_BOOL(aCoder, requireReversal); + ORK_ENCODE_IMAGE(aCoder, customTargetImage); + ORK_ENCODE_OBJ(aCoder, customTargetPluralName); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.initialSpan == castObject.initialSpan) && + (self.minimumSpan == castObject.minimumSpan) && + (self.maximumSpan == castObject.maximumSpan) && + (self.playSpeed == castObject.playSpeed) && + (self.maximumTests == castObject.maximumTests) && + (self.maximumConsecutiveFailures == castObject.maximumConsecutiveFailures) && + (ORKEqualObjects(self.customTargetPluralName, castObject.customTargetPluralName)) && + (self.requireReversal == castObject.requireReversal)); +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.h new file mode 100755 index 0000000..855f60e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + View controller corresponding to `ORKSpatialSpanMemoryStep`. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpatialSpanMemoryStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.m new file mode 100755 index 0000000..285e448 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanMemoryStepViewController.m @@ -0,0 +1,783 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanMemoryStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKSpatialSpanMemoryContentView.h" +#import "ORKVerticalContainerView_Internal.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKStepHeaderView_Internal.h" + +#import "ORKActiveStep_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKSpatialSpanMemoryResult.h" +#import "ORKStep_Private.h" +#import "ORKSpatialSpanGame.h" +#import "ORKSpatialSpanGameState.h" +#import "ORKSpatialSpanMemoryStep.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +#import + + +static const NSTimeInterval MemoryGameActivityTimeout = 20; + +typedef NS_ENUM(NSInteger, ORKSpatialSpanStepState) { + ORKSpatialSpanStepStateInitial, + ORKSpatialSpanStepStatePlayback, + ORKSpatialSpanStepStateGameplay, + ORKSpatialSpanStepStateTimeout, + ORKSpatialSpanStepStateFailed, + ORKSpatialSpanStepStateSuccess, + ORKSpatialSpanStepStateRestart, + ORKSpatialSpanStepStateComplete, + ORKSpatialSpanStepStateStopped, + ORKSpatialSpanStepStatePaused +}; + +@class ORKState; + +typedef void (^_ORKStateHandler)(ORKState *fromState, ORKState *_toState, id context); + +// Poor man's state machine: +// Define entry and exit handlers for each state. +// Transitions are a free for all! +@interface ORKState : NSObject + ++ (ORKState *)stateWithState:(NSInteger)state entryHandler:(_ORKStateHandler)entryHandler exitHandler:(_ORKStateHandler)exitHandler context:(id)context; + +@property (nonatomic, assign) NSInteger state; + +@property (nonatomic, weak) id context; + +@property (nonatomic, copy) _ORKStateHandler entryHandler; +- (void)setEntryHandler:(_ORKStateHandler)entryHandler; + +@property (nonatomic, copy) _ORKStateHandler exitHandler; +- (void)setExitHandler:(_ORKStateHandler)exitHandler; + +@end + + +@implementation ORKState + ++ (ORKState *)stateWithState:(NSInteger)state entryHandler:(_ORKStateHandler)entryHandler exitHandler:(_ORKStateHandler)exitHandler context:(id)context { + ORKState *s = [ORKState new]; + s.state = state; + s.entryHandler = entryHandler; + s.exitHandler = exitHandler; + s.context = context; + return s; +} + +@end + + +@interface ORKSpatialSpanMemoryStepViewController () + +@end + + +@implementation ORKSpatialSpanMemoryStepViewController { + ORKSpatialSpanMemoryContentView *_contentView; + ORKState *_state; + NSDictionary *_states; + ORKGridSize _gridSize; + + ORKSpatialSpanGameState *_currentGameState; + UIBarButtonItem *_customLearnMoreButtonItem; + UIBarButtonItem *_learnMoreButtonItem; + + // ORKSpatialSpanMemoryGameRecord + NSMutableArray *_gameRecords; + NSTimeInterval _gameStartTime; + NSInteger _lastRoundScore; + + NSInteger _playbackIndex; + + NSInteger _score; + NSInteger _numberOfItems; + + NSInteger _gamesCounter; + NSInteger _consecutiveGamesFailed; + NSInteger _nextGameSequenceLength; + + NSTimer *_playbackTimer; + NSTimer *_activityTimer; +} + +- (ORKSpatialSpanMemoryStep *)spatialSpanStep { + return (ORKSpatialSpanMemoryStep *)self.step; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +#pragma mark Overrides + +- (void)viewDidLoad { + + // Setup to always have a learn more button item but with an empty title + BOOL usesDefaultCopyright = (self.learnMoreButtonItem == nil); + if (usesDefaultCopyright) { + self.learnMoreButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_COPYRIGHT", nil) style:UIBarButtonItemStylePlain target:self action:@selector(showCopyright)]; + } + + [super viewDidLoad]; + + _contentView = [ORKSpatialSpanMemoryContentView new]; + _contentView.translatesAutoresizingMaskIntoConstraints = NO; + _contentView.footerHidden = YES; + _contentView.gameView.delegate = self; + self.activeStepView.activeCustomView = _contentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + + [self resetUI]; + + UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleUserTap:)]; + [self.activeStepView addGestureRecognizer:tapGestureRecognizer]; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [self initializeStates]; + +} + +- (void)start { + [super start]; + + if (!_state) { + [self transitionToState:ORKSpatialSpanStepStateInitial]; + } + + [self transitionToState:ORKSpatialSpanStepStatePlayback]; +} + +- (void)suspend { + [super suspend]; + switch (_state.state) { + case ORKSpatialSpanStepStatePlayback: + case ORKSpatialSpanStepStateGameplay: + [self transitionToState:ORKSpatialSpanStepStatePaused]; + break; + default: + break; + } +} + +- (void)resume { + [super resume]; +} + +- (void)finish { + [super finish]; + [self transitionToState:ORKSpatialSpanStepStateStopped]; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = stepResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:stepResult.results]; + + ORKSpatialSpanMemoryResult *memoryResult = [[ORKSpatialSpanMemoryResult alloc] initWithIdentifier:self.step.identifier]; + memoryResult.startDate = stepResult.startDate; + memoryResult.endDate = now; + + NSMutableArray *records = [NSMutableArray new]; + + __block NSInteger numberOfFailures = 0; + __block NSInteger score = 0; + // Only include valid records + [_gameRecords enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKSpatialSpanMemoryGameRecord *record = (ORKSpatialSpanMemoryGameRecord *)obj; + if (record.gameStatus != ORKSpatialSpanMemoryGameStatusUnknown) { + [records addObject:record]; + + score += record.score; + + if (record.gameStatus != ORKSpatialSpanMemoryGameStatusSuccess) { + numberOfFailures++; + } + } + }]; + + memoryResult.score = score; + memoryResult.numberOfFailures = numberOfFailures; + memoryResult.numberOfGames = records.count; + memoryResult.gameRecords = [records copy]; + + [results addObject:memoryResult]; + stepResult.results = [results copy]; + + return stepResult; +} + +#pragma mark UpdateGameRecord + +- (ORKSpatialSpanMemoryGameRecord *)currentGameRecord { + return _gameRecords ? _gameRecords.lastObject : nil; +} + +- (void)createGameRecord { + if (_gameRecords == nil) { + _gameRecords = [NSMutableArray new]; + } + + ORKSpatialSpanMemoryGameRecord *gameRecord = [ORKSpatialSpanMemoryGameRecord new]; + gameRecord.seed = _currentGameState.game.seed; + gameRecord.gameSize = _currentGameState.game.gameSize; + + NSMutableArray *targetSequence = [NSMutableArray new]; + [_currentGameState.game enumerateSequenceWithHandler:^(NSInteger step, NSInteger tileIndex, BOOL isLastStep, BOOL *stop) { + [targetSequence addObject:@(tileIndex)]; + }]; + gameRecord.sequence = [targetSequence copy]; + [_gameRecords addObject:gameRecord]; + + _lastRoundScore = _score; +} + +- (void)updateGameRecordTargetRects { + ORKSpatialSpanMemoryGameRecord *record = [self currentGameRecord]; + NSArray *tileViews = _contentView.gameView.tileViews; + NSMutableArray *targetRects = [NSMutableArray new]; + for (UIView *tileView in tileViews) { + CGRect rect = [self.view convertRect:tileView.frame fromView:tileView.superview]; + [targetRects addObject:[NSValue valueWithCGRect:rect]]; + } + record.targetRects = [targetRects copy]; + NSAssert(tileViews.count == 0 || tileViews.count == record.gameSize, nil); +} + +- (void)updateGameRecordOnStartingGamePlay { + _gameStartTime = CACurrentMediaTime(); +} + +- (void)handleUserTap:(UITapGestureRecognizer *)tapRecognizer { + if (_state.state != ORKSpatialSpanStepStateGameplay) { + return; + } + [self updateGameRecordOnTouch:-1 location:[tapRecognizer locationInView: self.view]]; +} + +- (void)updateGameRecordOnTouch:(NSInteger)targetIndex location:(CGPoint)location { + ORKSpatialSpanMemoryGameTouchSample *sample = [ORKSpatialSpanMemoryGameTouchSample new]; + + sample.timestamp = CACurrentMediaTime() - _gameStartTime; + sample.location = location; + sample.targetIndex = targetIndex; + + ORKSpatialSpanMemoryGameRecord *record = [self currentGameRecord]; + + NSAssert(record, nil); + + NSInteger currentStep = 0; + + for (ORKSpatialSpanMemoryGameTouchSample *aSample in record.touchSamples) { + if (aSample.isCorrect) { + currentStep++; + } + } + + sample.correct = (targetIndex == [_currentGameState.game tileIndexForStep:currentStep]); + + NSMutableArray *sampleArray = [NSMutableArray arrayWithArray:record.touchSamples]; + + [sampleArray addObject:sample]; + + record.touchSamples = [sampleArray copy]; +} + +- (void)updateGameRecordOnSuccess { + [self currentGameRecord].gameStatus = ORKSpatialSpanMemoryGameStatusSuccess; +} + +- (void)updateGameRecordOnFailure { + [self currentGameRecord].gameStatus = ORKSpatialSpanMemoryGameStatusFailure; +} + +- (void)updateGameRecordOnTimeout { + [self currentGameRecord].gameStatus = ORKSpatialSpanMemoryGameStatusTimeout; +} + +- (void)updateGameRecordScore { + [self currentGameRecord].score = _score - _lastRoundScore; +} + +- (void)updateGameRecordOnPause { + [self currentGameRecord].gameStatus = ORKSpatialSpanMemoryGameStatusUnknown; +} + +#pragma mark ORKSpatialSpanStepStateInitial + +- (ORKGridSize)gridSizeForSpan:(NSInteger)span { + NSInteger numberOfGridEntriesDesired = span * 2; + NSInteger value = (NSInteger)ceil(sqrt(numberOfGridEntriesDesired)); + value = MAX(value, 2); + value = MIN(value, 6); + return (ORKGridSize){value,value}; +} + +- (void)resetGameAndUI { + _score = 0; + _numberOfItems = 0; + _gamesCounter = 0; + _consecutiveGamesFailed = 0; + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + _nextGameSequenceLength = step.initialSpan; + + [self resetForNewGame]; +} + +- (void)resetUI { + _contentView.numberOfItems = _score; + _contentView.score = _numberOfItems; + _contentView.footerHidden = YES; + _contentView.buttonItem = nil; + _contentView.gameView.gridSize = _gridSize; + + _contentView.gameView.customTargetImage = [[self spatialSpanStep] customTargetImage]; +} + +- (void)resetForNewGame { + [self.activeStepView updateTitle:nil text:self.step.text]; + + _numberOfItems = 0; + + NSInteger sequenceLength = _nextGameSequenceLength; + _gridSize = [self gridSizeForSpan:sequenceLength]; + + ORKSpatialSpanGame *game = [[ORKSpatialSpanGame alloc] initWithGameSize:_gridSize.width * _gridSize.height sequenceLength:sequenceLength seed:0]; + ORKSpatialSpanGameState *gameState = [[ORKSpatialSpanGameState alloc] initWithGame:game]; + + _currentGameState = gameState; + + [self createGameRecord]; + + [self resetUI]; +} + +#pragma mark ORKSpatialSpanStepStatePlayback + +- (void)applyTargetState:(ORKSpatialSpanTargetState)targetState toSequenceIndex:(NSInteger)index duration:(NSTimeInterval)duration { + ORKSpatialSpanGame *game = _currentGameState.game; + if (index == NSNotFound || index < 0 || index >= game.sequenceLength ) { + return; + } + + NSInteger tileIndex = [game tileIndexForStep:index]; + ORKSpatialSpanMemoryGameView *gameView = _contentView.gameView; + [gameView setState:targetState forTileIndex:tileIndex animated:YES]; + if (duration > 0 && targetState != ORKSpatialSpanTargetStateQuiescent) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self applyTargetState:ORKSpatialSpanTargetStateQuiescent toSequenceIndex:index duration:0]; + }); + } +} + +- (void)playbackNextItem { + const NSInteger sequenceLength = _currentGameState.game.sequenceLength; + if (_playbackIndex >= sequenceLength) { + [self transitionToState:ORKSpatialSpanStepStateGameplay]; + } else { + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + + NSInteger index = _playbackIndex; + NSInteger previousIndex = index - 1; + if (step.requireReversal) { + // Play the indexes in reverse order when we require reversal. The participant + // is then required to tap the sequence in the forward direction, which + // appears as a reversal to them. + index = sequenceLength - 1 - index; + previousIndex = sequenceLength - 1 - previousIndex; + } + + // Make sure the previous step *is *cleared + [self applyTargetState:ORKSpatialSpanTargetStateQuiescent toSequenceIndex:previousIndex duration:0]; + + // The active display should be visible for half the timer interval + [self applyTargetState:ORKSpatialSpanTargetStateActive toSequenceIndex:index duration:(step.playSpeed / 2)]; + } + _playbackIndex++; +} + +- (void)startPlayback { + _playbackIndex = 0; + _contentView.footerHidden = YES; + _contentView.buttonItem = nil; + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + NSString *title = [NSString localizedStringWithFormat:ORKLocalizedString(@"MEMORY_GAME_PLAYBACK_TITLE_%@", nil), step.customTargetPluralName ? : ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TARGET_PLURAL", nil)]; + + [self.activeStepView updateTitle:title text:nil]; + + [_contentView.gameView resetTilesAnimated:NO]; + + _playbackTimer = [NSTimer scheduledTimerWithTimeInterval:step.playSpeed target:self selector:@selector(playbackNextItem) userInfo:nil repeats:YES]; +} + +- (void)finishPlayback { + [_playbackTimer invalidate]; + _playbackTimer = nil; +} + +#pragma mark ORKSpatialSpanStepStateGameplay + +- (void)setNumberOfItems:(NSInteger)numberOfItems { + _numberOfItems = numberOfItems; + [_contentView setNumberOfItems:_numberOfItems]; +} + +- (void)setScore:(NSInteger)score { + _score = score; + [_contentView setScore:_score]; + [self updateGameRecordScore]; +} + +- (void)activityTimeout { + [self transitionToState:ORKSpatialSpanStepStateTimeout]; +} + +- (void)resetActivityTimer { + [_activityTimer invalidate]; + _activityTimer = nil; + + _activityTimer = [NSTimer scheduledTimerWithTimeInterval:MemoryGameActivityTimeout target:self selector:@selector(activityTimeout) userInfo:nil repeats:NO]; +} + +- (void)startGameplay { + [self setNumberOfItems:0]; + + // Update the target rects here, since layout will be complete by this point. + [self updateGameRecordTargetRects]; + + _contentView.footerHidden = NO; + _contentView.buttonItem = nil; + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + NSString *pluralItemName = step.customTargetPluralName ? : ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TARGET_PLURAL", nil); + NSString *standaloneItemName = step.customTargetPluralName ? : ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE", nil); + _contentView.capitalizedPluralItemDescription = [standaloneItemName capitalizedStringWithLocale:[NSLocale currentLocale]]; + NSString *titleFormat = step.requireReversal ? ORKLocalizedString(@"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@", nil) : ORKLocalizedString(@"MEMORY_GAME_GAMEPLAY_TITLE_%@", nil); + NSString *title = [NSString stringWithFormat:titleFormat, pluralItemName]; + [self.activeStepView updateTitle:title text:nil]; + + [self resetActivityTimer]; + + // Ensure tiles are all reset at this point + [_currentGameState reset]; + [_contentView.gameView resetTilesAnimated:NO]; + [_contentView setScore:_score]; + [_contentView setNumberOfItems:_numberOfItems]; + + [self updateGameRecordOnStartingGamePlay]; +} + +- (void)finishGameplay { + [_activityTimer invalidate]; + _activityTimer = nil; +} + +- (void)gameView:(ORKSpatialSpanMemoryGameView *)gameView didTapTileWithIndex:(NSInteger)tileIndex recognizer:(UITapGestureRecognizer *)recognizer { + if (_state.state != ORKSpatialSpanStepStateGameplay) { + return; + } + + [self updateGameRecordOnTouch:tileIndex location:[recognizer locationInView:self.view]]; + + ORKSpatialSpanResult result = [_currentGameState playTileIndex:tileIndex]; + switch (result) { + case ORKSpatialSpanResultIgnore: + break; + + case ORKSpatialSpanResultCorrect: + [gameView setState:ORKSpatialSpanTargetStateCorrect forTileIndex:tileIndex animated:YES]; + NSInteger stepIndex = [_currentGameState currentStepIndex]; + + [self setNumberOfItems:_numberOfItems + 1]; + [self setScore:_score + (round(log2(stepIndex)) + 1) * 5]; + + [self resetActivityTimer]; + if ([_currentGameState isComplete]) { + [self transitionToState:ORKSpatialSpanStepStateSuccess]; + } + break; + + case ORKSpatialSpanResultIncorrect: + [gameView setState:ORKSpatialSpanTargetStateIncorrect forTileIndex:tileIndex animated:YES]; + [self transitionToState:ORKSpatialSpanStepStateFailed]; + break; + } +} + +#pragma mark ORKSpatialSpanStepStateSuccess + +- (void)updateGameCountersForSuccess:(BOOL)success { + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + if (success) { + NSInteger sequenceLength = [_currentGameState.game sequenceLength]; + [self setScore:_score + (round(log2(sequenceLength)) + 1) * 5]; + _gamesCounter++; + _consecutiveGamesFailed = 0; + _nextGameSequenceLength = MIN(_nextGameSequenceLength + 1, step.maximumSpan); + } else { + _gamesCounter++; + _consecutiveGamesFailed++; + _nextGameSequenceLength = MAX(_nextGameSequenceLength - 1, step.minimumSpan); + } +} + +- (void)continueAction { + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + if (_gamesCounter < step.maximumTests && _consecutiveGamesFailed < step.maximumConsecutiveFailures) { + // Generate a new game + [self transitionToState:ORKSpatialSpanStepStateRestart]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + } else { + [self finish]; + } +} + +- (void)showSuccess { + [self updateGameRecordOnSuccess]; + + [self updateGameCountersForSuccess:YES]; + if ([self finishIfCompletedGames]) { + return; + } + + [self.activeStepView updateTitle:ORKLocalizedString(@"MEMORY_GAME_COMPLETE_TITLE", nil) text:ORKLocalizedString(@"MEMORY_GAME_COMPLETE_MESSAGE", nil)]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.75 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + _contentView.buttonItem = [ORKBorderedButton new]; + [_contentView.buttonItem setTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) forState:UIControlStateNormal]; + [_contentView.buttonItem addTarget:self action:@selector(continueAction) forControlEvents:UIControlEventTouchUpInside]; + }); +} + +#pragma mark ORKSpatialSpanStepStateFailed + +- (void)tryAgainAction { + // Restart with a new, shorter game + [self transitionToState:ORKSpatialSpanStepStateRestart]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (BOOL)finishIfCompletedGames { + ORKSpatialSpanMemoryStep *step = [self spatialSpanStep]; + if (_consecutiveGamesFailed >= step.maximumConsecutiveFailures || _gamesCounter >= step.maximumTests) { + [self transitionToState:ORKSpatialSpanStepStateComplete]; + return YES; + } + return NO; +} + +- (void)showFailed { + [self updateGameRecordOnFailure]; + + [self updateGameCountersForSuccess:NO]; + if ([self finishIfCompletedGames]) { + return; + } + [self.activeStepView updateTitle:ORKLocalizedString(@"MEMORY_GAME_FAILED_TITLE", nil) text:ORKLocalizedString(@"MEMORY_GAME_FAILED_MESSAGE", nil)]; + + _contentView.buttonItem = [ORKBorderedButton new]; + [_contentView.buttonItem setTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) forState:UIControlStateNormal]; + [_contentView.buttonItem addTarget:self action:@selector(tryAgainAction) forControlEvents:UIControlEventTouchUpInside]; +} + +#pragma mark ORKSpatialSpanStepStateTimeout + +- (void)showTimeout { + [self updateGameRecordOnTimeout]; + + [self updateGameCountersForSuccess:NO]; + if ([self finishIfCompletedGames]) { + return; + } + + [self.activeStepView updateTitle:ORKLocalizedString(@"MEMORY_GAME_TIMEOUT_TITLE", nil) text:ORKLocalizedString(@"MEMORY_GAME_TIMEOUT_MESSAGE", nil)]; + + _contentView.buttonItem = [ORKBorderedButton new]; + [_contentView.buttonItem setTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) forState:UIControlStateNormal]; + [_contentView.buttonItem addTarget:self action:@selector(tryAgainAction) forControlEvents:UIControlEventTouchUpInside]; +} + +#pragma mark ORKSpatialSpanStepStateComplete + +- (void)showComplete { + [self.activeStepView updateTitle:ORKLocalizedString(@"MEMORY_GAME_COMPLETE_TITLE", nil) text:nil]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.75 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + _contentView.buttonItem = [ORKBorderedButton new]; + [_contentView.buttonItem setTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) forState:UIControlStateNormal]; + [_contentView.buttonItem addTarget:self action:@selector(continueAction) forControlEvents:UIControlEventTouchUpInside]; + }); +} + +- (void)showCopyright { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil + message:ORKLocalizedString(@"MEMORY_GAME_COPYRIGHT_TEXT", nil) + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_OK", nil) + style:UIAlertActionStyleDefault + handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +#pragma mark ORKSpatialSpanStepStateRestart + +- (void)doRestart { + [self resetForNewGame]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Dispatch, so we don't do this in the middle of a state transition + if (_state.state == ORKSpatialSpanStepStateRestart) { + [self transitionToState:ORKSpatialSpanStepStatePlayback]; + } + }); +} + +- (void)showPausedFromState:(ORKState *)fromState { + [self updateGameRecordOnPause]; + + // Do not update game counters - doesn't count as a game. + + [_activityTimer invalidate]; _activityTimer = nil; + [_playbackTimer invalidate]; _playbackTimer = nil; + + [self resetForNewGame]; + [self.activeStepView updateTitle:ORKLocalizedString(@"MEMORY_GAME_PAUSED_TITLE", nil) text:ORKLocalizedString(@"MEMORY_GAME_PAUSED_MESSAGE", nil)]; + _contentView.buttonItem = [ORKBorderedButton new]; + [_contentView.buttonItem setTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) forState:UIControlStateNormal]; + [_contentView.buttonItem addTarget:self action:@selector(continueAction) forControlEvents:UIControlEventTouchUpInside]; +} + +#pragma mark State machine + +- (void)initializeStates { + NSMutableDictionary *states = [NSMutableDictionary dictionary]; + + states[@(ORKSpatialSpanStepStateInitial)] = [ORKState stateWithState:ORKSpatialSpanStepStateInitial + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this resetGameAndUI]; + } + exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStatePlayback)] = [ORKState stateWithState:ORKSpatialSpanStepStatePlayback + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this startPlayback]; + } + exitHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this finishPlayback]; + } context:self]; + + states[@(ORKSpatialSpanStepStateGameplay)] = [ORKState stateWithState:ORKSpatialSpanStepStateGameplay + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this startGameplay]; + } + exitHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this finishGameplay]; + } context:self]; + + states[@(ORKSpatialSpanStepStateSuccess)] = [ORKState stateWithState:ORKSpatialSpanStepStateSuccess + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this showSuccess]; + } + exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStateFailed)] = [ORKState stateWithState:ORKSpatialSpanStepStateFailed + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this showFailed]; + } + exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStateTimeout)] = [ORKState stateWithState:ORKSpatialSpanStepStateTimeout + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this showTimeout]; + } + exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStateRestart)] = [ORKState stateWithState:ORKSpatialSpanStepStateRestart + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this doRestart]; + } + exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStateComplete)] = [ORKState stateWithState:ORKSpatialSpanStepStateComplete + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this showComplete]; + } exitHandler:nil context:self]; + + states[@(ORKSpatialSpanStepStateStopped)] = [ORKState stateWithState:ORKSpatialSpanStepStateStopped + entryHandler:nil + exitHandler:nil + context:self]; + + states[@(ORKSpatialSpanStepStatePaused)] = [ORKState stateWithState:ORKSpatialSpanStepStatePaused + entryHandler:^(ORKState *from, ORKState *to, ORKSpatialSpanMemoryStepViewController *this) { + [this showPausedFromState:from]; + } exitHandler:nil context:self]; + + _states = states; + + [self transitionToState:ORKSpatialSpanStepStateInitial]; +} + +- (void)transitionToState:(ORKSpatialSpanStepState)state { + ORKState *stateObject = _states[@(state)]; + + ORKState *oldState = _state; + if (oldState.exitHandler != nil) { + oldState.exitHandler(oldState, stateObject, oldState.context); + } + _state = stateObject; + if (stateObject.entryHandler) { + stateObject.entryHandler(oldState, stateObject, stateObject.context); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.h new file mode 100755 index 0000000..ce66668 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSpatialSpanGameState.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKSpatialSpanTargetView; + +@protocol ORKSpatialSpanTargetViewDelegate + +- (void)targetView:(ORKSpatialSpanTargetView *)targetView recognizer:(UITapGestureRecognizer *)recognizer; + +@end + + +@interface ORKSpatialSpanTargetView : UIView + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, assign) ORKSpatialSpanTargetState state; +- (void)setState:(ORKSpatialSpanTargetState)state animated:(BOOL)animated; + +@property (nonatomic, strong, nullable) UIColor *color; + +@property (nonatomic, strong, nullable) UIImage *customTargetImage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.m new file mode 100755 index 0000000..37f104e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpatialSpanTargetView.m @@ -0,0 +1,377 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpatialSpanTargetView.h" + +#import "ORKTintedImageView.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const UIEdgeInsets ORKFlowerMargins = (UIEdgeInsets){12,12,12,12}; +static const CGSize ORKFlowerBezierPathSize = (CGSize){90,90}; +static UIBezierPath *ORKFlowerBezierPath() { + UIBezierPath *bezierPath = UIBezierPath.bezierPath; + [bezierPath moveToPoint: CGPointMake(58.8, 45)]; + [bezierPath addCurveToPoint: CGPointMake(51.9, 33.2) controlPoint1: CGPointMake(107.8, 41.8) controlPoint2: CGPointMake(79.3, -7.2)]; + [bezierPath addCurveToPoint: CGPointMake(38.1, 33.2) controlPoint1: CGPointMake(73.6, -10.4) controlPoint2: CGPointMake(16.5, -10.4)]; + [bezierPath addCurveToPoint: CGPointMake(31.2, 45) controlPoint1: CGPointMake(10.8, -7.2) controlPoint2: CGPointMake(-17.8, 41.8)]; + [bezierPath addCurveToPoint: CGPointMake(38.1, 56.8) controlPoint1: CGPointMake(-17.8, 48.2) controlPoint2: CGPointMake(10.7, 97.2)]; + [bezierPath addCurveToPoint: CGPointMake(51.9, 56.8) controlPoint1: CGPointMake(16.4, 100.4) controlPoint2: CGPointMake(73.5, 100.4)]; + [bezierPath addCurveToPoint: CGPointMake(58.8, 45) controlPoint1: CGPointMake(79.2, 97.2) controlPoint2: CGPointMake(107.8, 48.2)]; + [bezierPath closePath]; + [bezierPath moveToPoint: CGPointMake(45, 53.1)]; + [bezierPath addCurveToPoint: CGPointMake(36.7, 45) controlPoint1: CGPointMake(40.4, 53.1) controlPoint2: CGPointMake(36.7, 49.5)]; + [bezierPath addCurveToPoint: CGPointMake(45, 36.9) controlPoint1: CGPointMake(36.7, 40.5) controlPoint2: CGPointMake(40.4, 36.9)]; + [bezierPath addCurveToPoint: CGPointMake(53.3, 45) controlPoint1: CGPointMake(49.6, 36.9) controlPoint2: CGPointMake(53.3, 40.5)]; + [bezierPath addCurveToPoint: CGPointMake(45, 53.1) controlPoint1: CGPointMake(53.3, 49.5) controlPoint2: CGPointMake(49.6, 53.1)]; + [bezierPath closePath]; + bezierPath.miterLimit = 4; + + return bezierPath; +} + +static const CGSize ORKCheckBezierPathSize = (CGSize){28,28}; +static UIBezierPath *ORKCheckBezierPath() { + UIBezierPath *bezierPath = UIBezierPath.bezierPath; + [bezierPath moveToPoint: CGPointMake(11.6, 19)]; + [bezierPath addCurveToPoint: CGPointMake(11.1, 18.8) controlPoint1: CGPointMake(11.4, 19) controlPoint2: CGPointMake(11.2, 18.9)]; + [bezierPath addLineToPoint: CGPointMake(7.5, 15.5)]; + [bezierPath addCurveToPoint: CGPointMake(7.5, 14.4) controlPoint1: CGPointMake(7.2, 15.2) controlPoint2: CGPointMake(7.2, 14.7)]; + [bezierPath addCurveToPoint: CGPointMake(8.6, 14.4) controlPoint1: CGPointMake(7.8, 14.1) controlPoint2: CGPointMake(8.3, 14.1)]; + [bezierPath addLineToPoint: CGPointMake(11.6, 17.2)]; + [bezierPath addLineToPoint: CGPointMake(19.6, 9.2)]; + [bezierPath addCurveToPoint: CGPointMake(20.7, 9.2) controlPoint1: CGPointMake(19.9, 8.9) controlPoint2: CGPointMake(20.4, 8.9)]; + [bezierPath addCurveToPoint: CGPointMake(20.7, 10.3) controlPoint1: CGPointMake(21, 9.5) controlPoint2: CGPointMake(21, 10)]; + [bezierPath addLineToPoint: CGPointMake(12.2, 18.8)]; + [bezierPath addCurveToPoint: CGPointMake(11.6, 19) controlPoint1: CGPointMake(12, 18.9) controlPoint2: CGPointMake(11.8, 19)]; + [bezierPath closePath]; + bezierPath.miterLimit = 4; + + return bezierPath; +} + +static const CGSize ORKErrorBezierPathSize = (CGSize){28,28}; +static UIBezierPath *ORKErrorBezierPath() { + UIBezierPath *bezier3Path = UIBezierPath.bezierPath; + [bezier3Path moveToPoint: CGPointMake(15.1, 14)]; + [bezier3Path addLineToPoint: CGPointMake(18.8, 10.3)]; + [bezier3Path addCurveToPoint: CGPointMake(18.8, 9.2) controlPoint1: CGPointMake(19.1, 10) controlPoint2: CGPointMake(19.1, 9.5)]; + [bezier3Path addCurveToPoint: CGPointMake(17.7, 9.2) controlPoint1: CGPointMake(18.5, 8.9) controlPoint2: CGPointMake(18, 8.9)]; + [bezier3Path addLineToPoint: CGPointMake(14, 12.9)]; + [bezier3Path addLineToPoint: CGPointMake(10.3, 9.2)]; + [bezier3Path addCurveToPoint: CGPointMake(9.2, 9.2) controlPoint1: CGPointMake(10, 8.9) controlPoint2: CGPointMake(9.5, 8.9)]; + [bezier3Path addCurveToPoint: CGPointMake(9.2, 10.3) controlPoint1: CGPointMake(8.9, 9.5) controlPoint2: CGPointMake(8.9, 10)]; + [bezier3Path addLineToPoint: CGPointMake(12.9, 14)]; + [bezier3Path addLineToPoint: CGPointMake(9.2, 17.7)]; + [bezier3Path addCurveToPoint: CGPointMake(9.2, 18.8) controlPoint1: CGPointMake(8.9, 18) controlPoint2: CGPointMake(8.9, 18.5)]; + [bezier3Path addCurveToPoint: CGPointMake(9.7, 19) controlPoint1: CGPointMake(9.3, 18.9) controlPoint2: CGPointMake(9.5, 19)]; + [bezier3Path addCurveToPoint: CGPointMake(10.2, 18.8) controlPoint1: CGPointMake(9.9, 19) controlPoint2: CGPointMake(10.1, 18.9)]; + [bezier3Path addLineToPoint: CGPointMake(13.9, 15.1)]; + [bezier3Path addLineToPoint: CGPointMake(17.6, 18.8)]; + [bezier3Path addCurveToPoint: CGPointMake(18.1, 19) controlPoint1: CGPointMake(17.7, 18.9) controlPoint2: CGPointMake(17.9, 19)]; + [bezier3Path addCurveToPoint: CGPointMake(18.6, 18.8) controlPoint1: CGPointMake(18.3, 19) controlPoint2: CGPointMake(18.5, 18.9)]; + [bezier3Path addCurveToPoint: CGPointMake(18.6, 17.7) controlPoint1: CGPointMake(18.9, 18.5) controlPoint2: CGPointMake(18.9, 18)]; + [bezier3Path addLineToPoint: CGPointMake(15.1, 14)]; + [bezier3Path closePath]; + bezier3Path.miterLimit = 4; + return bezier3Path; +} + +@interface ORKPathView : UIView + +- (instancetype)initWithBezierPath:(UIBezierPath *)path canvasSize:(CGSize)canvasSize canvasMargins:(UIEdgeInsets)margins color:(UIColor *)color; + +@property (nonatomic, readonly) UIEdgeInsets canvasMargins; +@property (nonatomic, readonly) CGSize canvasSize; +@property (nonatomic, strong, readonly) UIBezierPath *path; +@property (nonatomic, strong, readonly) UIColor *color; + +@end + + +@implementation ORKPathView + +- (instancetype)initWithBezierPath:(UIBezierPath *)path canvasSize:(CGSize)canvasSize canvasMargins:(UIEdgeInsets)margins color:(UIColor *)color { + CGRect canvasRect = (CGRect){CGPointZero, canvasSize}; + CGRect outsetRect = UIEdgeInsetsInsetRect(canvasRect, (UIEdgeInsets){.top=-margins.top, .left=-margins.left, .right=-margins.right, .bottom=-margins.bottom}); + self = [super initWithFrame:outsetRect]; + if (self) { + _canvasMargins = margins; + _canvasSize = canvasSize; + _path = path; + _color = color; + self.tintColor = color; + self.opaque = NO; + [self setNeedsDisplay]; + } + return self; +} + +- (void)setColor:(UIColor *)color { + _color = color; + self.tintColor = color; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGRect bounds = self.bounds; + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + [[UIColor clearColor] setFill]; + CGContextFillRect(ctx, bounds); + + CGFloat baseWidth = _canvasSize.width + _canvasMargins.left + _canvasMargins.right; + CGFloat baseHeight = _canvasSize.height + _canvasMargins.top + _canvasMargins.bottom; + + CGFloat aspectRatio = MIN( bounds.size.width / baseWidth, bounds.size.height / baseHeight); + + CGContextSaveGState(ctx); + + CGContextScaleCTM(ctx, aspectRatio, aspectRatio); + CGContextTranslateCTM(ctx, _canvasMargins.left, _canvasMargins.top); + + [self.tintColor setFill]; + [_path fill]; + + CGContextRestoreGState(ctx); +} + +- (void)tintColorDidChange { + [self setNeedsDisplay]; +} + +@end + + +@implementation ORKSpatialSpanTargetView { + UITapGestureRecognizer *_tapRecognizer; + + CGFloat _flowerScaleFactor; + UIView *_flowerView; + UIView *_checkView; + UIView *_errorView; +} + +- (UIView *)newFlowerViewWithImage:(UIImage *)image { + if (image == nil) { + return [[ORKPathView alloc] initWithBezierPath:ORKFlowerBezierPath() canvasSize:ORKFlowerBezierPathSize canvasMargins:ORKFlowerMargins color:[UIColor blackColor]]; + } else { + ORKTintedImageView *imageView = [[ORKTintedImageView alloc] initWithImage:image]; + imageView.shouldApplyTint = YES; + imageView.contentMode = UIViewContentModeScaleAspectFit; + return imageView; + } +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; + [self addGestureRecognizer:_tapRecognizer]; + + _flowerScaleFactor = 1; + _flowerView = [self newFlowerViewWithImage:nil]; + [self addSubview:_flowerView]; + + _checkView = [[ORKPathView alloc] initWithBezierPath:ORKCheckBezierPath() canvasSize:ORKCheckBezierPathSize canvasMargins:UIEdgeInsetsZero color:[self tintColor]]; + _checkView.backgroundColor = [UIColor whiteColor]; + _checkView.layer.masksToBounds = YES; + _checkView.hidden = YES; + [self addSubview:_checkView]; + + _errorView = [[ORKPathView alloc] initWithBezierPath:ORKErrorBezierPath() canvasSize:ORKErrorBezierPathSize canvasMargins:UIEdgeInsetsZero color:[UIColor ork_redColor]]; + _errorView.backgroundColor = [UIColor whiteColor]; + _errorView.layer.masksToBounds = YES; + _errorView.hidden = YES; + [self addSubview:_errorView]; + + for (UIView *view in @[_flowerView, _checkView, _errorView]) { + view.isAccessibilityElement = NO; + } + } + return self; +} + +- (void)setCustomTargetImage:(UIImage *)customTargetImage { + UIImage *oldTargetImage = _customTargetImage; + _customTargetImage = customTargetImage; + if ((customTargetImage == nil) != (oldTargetImage == nil)) { + [_flowerView removeFromSuperview]; + _flowerView = [self newFlowerViewWithImage:customTargetImage]; + _flowerScaleFactor = (customTargetImage ? 0.8 : 1); + _flowerView.transform = CGAffineTransformMakeScale(_flowerScaleFactor, _flowerScaleFactor); + [self insertSubview:_flowerView atIndex:0]; + } else if (customTargetImage) { + [(UIImageView *)_flowerView setImage:customTargetImage]; + } + [self setNeedsLayout]; +} + +- (void)handleTap:(UITapGestureRecognizer *)recognizer { + [_delegate targetView:self recognizer:recognizer]; +} + +- (void)setState:(ORKSpatialSpanTargetState)state { + [self setState:state animated:NO]; +} + +- (void)tintColorDidChange { + if ([_checkView isKindOfClass:[ORKPathView class]]) { + [(ORKPathView *)_checkView setColor:[self tintColor]]; + } + [self setState:_state]; +} + +- (void)setState:(ORKSpatialSpanTargetState)state animated:(BOOL)animated { + _state = state; + + CGFloat newAlpha; + + BOOL checkHidden = YES; + BOOL errorHidden = YES; + CGAffineTransform newTransform = CGAffineTransformMakeScale(_flowerScaleFactor, _flowerScaleFactor); + + CGFloat oldCircleAlpha = [_errorView.layer.presentationLayer opacity]; + CGFloat newCircleAlpha; + CGAffineTransform oldCircleTransform = CGAffineTransformIdentity; + CGAffineTransform newCircleTransform = CGAffineTransformIdentity; + BOOL useSpring = NO; + NSTimeInterval duration = 0.3; + switch (state) { + case ORKSpatialSpanTargetStateQuiescent: + _flowerView.tintColor = [self tintColor]; + newAlpha = 0.2; + newCircleAlpha = 0.0; + newCircleTransform = CGAffineTransformMakeScale(0.2, 0.2); + break; + + case ORKSpatialSpanTargetStateActive: + _flowerView.tintColor = [self tintColor]; + newAlpha = 1.0; + newCircleTransform = CGAffineTransformMakeScale(0.2, 0.2); + newCircleAlpha = 0.0; + break; + + case ORKSpatialSpanTargetStateIncorrect: + _flowerView.tintColor = [UIColor ork_redColor]; + newTransform = CGAffineTransformMakeScale(0.9 * _flowerScaleFactor, 0.9 * _flowerScaleFactor); + oldCircleAlpha = 0; + newCircleAlpha = 1; + oldCircleTransform = CGAffineTransformMakeScale(0.2, 0.2); + newCircleTransform = CGAffineTransformMakeScale(1.0, 1.0); + newAlpha = 1.0; + errorHidden = NO; + useSpring = NO; + break; + + case ORKSpatialSpanTargetStateCorrect: + _flowerView.tintColor = [self tintColor]; + newTransform = CGAffineTransformMakeScale(1.1 * _flowerScaleFactor, 1.1 * _flowerScaleFactor); + oldCircleAlpha = 0; + newCircleAlpha = 1; + oldCircleTransform = CGAffineTransformMakeScale(0.2, 0.2); + newCircleTransform = CGAffineTransformMakeScale(1.0, 1.0); + newAlpha = 1.0; + checkHidden = NO; + useSpring = YES; + duration = 0.5; + break; + } + + _checkView.alpha = oldCircleAlpha; + _errorView.alpha = newCircleAlpha; + _checkView.transform = oldCircleTransform; + _errorView.transform = oldCircleTransform; + + _errorView.hidden = errorHidden; + _checkView.hidden = checkHidden; + _flowerView.transform = CGAffineTransformMakeScale(_flowerScaleFactor, _flowerScaleFactor); + + [UIView animateWithDuration:(animated ? duration : 0) delay:0 usingSpringWithDamping:useSpring ? 0.5 : 1 initialSpringVelocity:0 options:(UIViewAnimationOptions)UIViewAnimationOptionBeginFromCurrentState animations:^{ + _errorView.alpha = newCircleAlpha; + _checkView.alpha = newCircleAlpha; + _errorView.transform = newCircleTransform; + _checkView.transform = newCircleTransform; + self.alpha = newAlpha; + _flowerView.transform = newTransform; + } completion:NULL]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + CGRect bounds = self.bounds; + _flowerView.center = (CGPoint){CGRectGetMidX(bounds), CGRectGetMidY(bounds)}; + _flowerView.bounds = bounds; + _flowerView.transform = CGAffineTransformMakeScale(_flowerScaleFactor, _flowerScaleFactor); + + CGFloat designWidth = ORKFlowerBezierPathSize.width + ORKFlowerMargins.left + ORKFlowerMargins.right; + CGFloat scaleFactor = bounds.size.width / designWidth; + CGAffineTransform transform = CGAffineTransformMakeScale(scaleFactor, scaleFactor); + + CGRect checkRect = CGRectApplyAffineTransform((CGRect){CGPointZero, ORKCheckBezierPathSize}, transform); + [_checkView setBounds:checkRect]; + _checkView.layer.cornerRadius = checkRect.size.width / 2; + CGRect errorRect = CGRectApplyAffineTransform((CGRect){CGPointZero, ORKErrorBezierPathSize}, transform); + [_errorView setBounds:errorRect]; + _errorView.layer.cornerRadius = errorRect.size.width / 2; + _errorView.center = _flowerView.center; + _checkView.center = _flowerView.center; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + NSString *state; + switch (self.state) { + case ORKSpatialSpanTargetStateActive: + state = ORKLocalizedString(@"AX.MEMORY.TILE.ACTIVE", nil); + break; + case ORKSpatialSpanTargetStateCorrect: + state = ORKLocalizedString(@"AX.MEMORY.TILE.CORRECT", nil); + break; + case ORKSpatialSpanTargetStateIncorrect: + state = ORKLocalizedString(@"AX.MEMORY.TILE.INCORRECT", nil); + break; + case ORKSpatialSpanTargetStateQuiescent: + state = ORKLocalizedString(@"AX.MEMORY.TILE.QUIESCENT", nil); + break; + } + return ORKAccessibilityStringForVariables(ORKLocalizedString(@"AX.MEMORY.TILE.LABEL", nil), state); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.h new file mode 100755 index 0000000..70491b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN +@class ORKPlaybackButton; + +@interface ORKSpeechInNoiseContentView : ORKActiveStepCustomView + +@property (nonatomic, copy, nullable) UIColor *alertColor; + +@property (nonatomic, assign) BOOL failed; + +@property (nonatomic, assign, getter=isFinished) BOOL finished; + +@property (nonatomic, copy, nullable) NSArray *samples; + +@property (nonatomic) ORKPlaybackButton *playButton; + +// Samples should be in the range of (0, 1). +- (void)addSample:(NSNumber *)sample; +- (void)removeAllSamples; +- (void)setGraphViewHidden:(BOOL)hidden; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.m new file mode 100755 index 0000000..0d3766d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseContentView.m @@ -0,0 +1,192 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechInNoiseContentView.h" +#import "ORKAudioGraphView.h" + +#import "ORKHeadlineLabel.h" +#import "ORKSubheadlineLabel.h" +#import "ORKLabel.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKPlaybackButton.h" + +@interface ORKSpeechInNoiseContentView () + +@property (nonatomic, strong) ORKAudioGraphView *graphView; +@property (nonatomic, strong) ORKSubheadlineLabel *transcriptLabel; + +@end + + +@implementation ORKSpeechInNoiseContentView { + NSMutableArray *_samples; + UIColor *_alertColor; + ORKSubheadlineLabel *_textLabel; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setupGraphView]; + [self setupPlayButton]; + [self setupTextLabel]; + [self updateGraphSamples]; + [self applyAlertColor]; + [self setUpConstraints]; + } + return self; +} + +- (void)setupTextLabel { + _textLabel = [ORKSubheadlineLabel new]; + _textLabel.textAlignment = NSTextAlignmentCenter; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.lineBreakMode = NSLineBreakByWordWrapping; + _textLabel.numberOfLines = 0; + [self addSubview:_textLabel]; +} + +- (void)setupGraphView { + self.graphView = [ORKAudioGraphView new]; + _graphView.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_graphView]; +} + +- (void)setupPlayButton { + if (@available(iOS 13.0, *)) { + self.playButton = [[ORKPlaybackButton alloc] initWithText:ORKLocalizedString(@"SPEECH_IN_NOISE_START_AUDIO_LABEL", nil) image:[UIImage systemImageNamed:@"play.circle"]]; + } else { + self.playButton = [[ORKPlaybackButton alloc] initWithText:ORKLocalizedString(@"SPEECH_IN_NOISE_START_AUDIO_LABEL", nil) image:[UIImage imageNamed:@"play" inBundle:ORKBundle() compatibleWithTraitCollection:nil]]; + } + self.playButton.translatesAutoresizingMaskIntoConstraints = NO; + self.playButton.enabled = YES; + self.playButton.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitStartsMediaSession; + [self addSubview:_playButton]; +} + +- (void)tintColorDidChange { + [self applyAlertColor]; +} + +- (void)setFinished:(BOOL)finished { + _finished = finished; +} + +- (void)applyAlertColor { + UIColor *alertColor = [self alertColor]; + _graphView.alertColor = alertColor; +} + +- (UIColor *)alertColor { + return _alertColor ? : [self tintColor]; +} + +- (void)setAlertColor:(UIColor *)alertColor { + _alertColor = alertColor; + [self applyAlertColor]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_textLabel, _graphView, _playButton); + const CGFloat graphHeight = 150; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_textLabel]-(5)-[_graphView(graphHeight)]-buttonGap-[_playButton]-(>=topBottomMargin)-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ + @"graphHeight": @(graphHeight), + @"topBottomMargin" : @(5), + @"buttonGap" : @(20) + } + views:views]]; + + + const CGFloat sideMargin = self.layoutMargins.left + (2 * ORKStandardLeftMarginForTableViewCell(self)); + const CGFloat twiceSideMargin = sideMargin * 2; + + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_textLabel]-|" + options:0 + metrics: nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-sideMargin-[_graphView]-sideMargin-|" + options:0 + metrics: @{@"sideMargin": @(sideMargin)} + views:views]]; + + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-twiceSideMargin-[_playButton(>=200)]-twiceSideMargin-|" + options:0 + metrics: @{@"twiceSideMargin": @(twiceSideMargin)} + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateGraphSamples { + _graphView.values = _samples; +} + +- (void)setGraphViewHidden:(BOOL)hidden { + [_graphView setHidden:hidden]; +} + +- (void)addSample:(NSNumber *)sample { + NSAssert(sample != nil, @"Sample should be non-nil"); + if (!_samples) { + _samples = [NSMutableArray array]; + } + [_samples addObject:sample]; + // Try to keep around 250 samples + if (_samples.count > 500) { + _samples = [[_samples subarrayWithRange:(NSRange){250, _samples.count - 250}] mutableCopy]; + } + [self updateGraphSamples]; +} + + +- (void)removeAllSamples { + _samples = nil; + [self updateGraphSamples]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.h new file mode 100755 index 0000000..92cf3c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.h @@ -0,0 +1,73 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +/** + This active step programatically mixes the speech file with noise file and applies the filter. + */ +@interface ORKSpeechInNoiseStep : ORKActiveStep + +/** + This property accepts the speech file. + */ +@property (nonatomic, copy, nullable) NSString *speechFileNameWithExtension; + +/** + This property accepts the noise file. + */ +@property (nonatomic, copy, nullable) NSString *noiseFileNameWithExtension; + +/** + This property accepts the filter file. + */ +@property (nonatomic, copy, nullable) NSString *filterFileNameWithExtension; + +/** + The linear gain applied to the noise file before mixing it with the speech file. + */ +@property (nonatomic, assign) double gainAppliedToNoise; + +/** + This boolean determines the repetitions of the file. + */ +@property (nonatomic, assign) BOOL willAudioLoop; + +@property (nonatomic) BOOL hideGraphView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.m new file mode 100755 index 0000000..9ad10ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStep.m @@ -0,0 +1,126 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechInNoiseStep.h" +#import "ORKSpeechInNoiseStepViewController.h" + +#import "ORKHelpers_Internal.h" + +#define ORKSpeechInNoiseDefaultNoiseFileName "Noise.wav" +#define ORKSpeechInNoiseDefaultFilterFileName "Window.wav" +#define ORKSpeechInNoiseDefaultSpeechFileName "Sentence1.wav" + +@implementation ORKSpeechInNoiseStep + ++ (Class)stepViewControllerClass { + return [ORKSpeechInNoiseStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + _willAudioLoop = NO; + _noiseFileNameWithExtension = @ORKSpeechInNoiseDefaultNoiseFileName; + _filterFileNameWithExtension = @ORKSpeechInNoiseDefaultFilterFileName; + _speechFileNameWithExtension = @ORKSpeechInNoiseDefaultSpeechFileName; +} + +- (void)validateParameters { + [super validateParameters]; +} + +- (BOOL)startsFinished { + return NO; +} + +- (BOOL)shouldContinueOnFinish { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpeechInNoiseStep *step = [super copyWithZone:zone]; + step.speechFileNameWithExtension = self.speechFileNameWithExtension; + step.noiseFileNameWithExtension = self.noiseFileNameWithExtension; + step.filterFileNameWithExtension = self.filterFileNameWithExtension; + step.gainAppliedToNoise = self.gainAppliedToNoise; + step.willAudioLoop = self.willAudioLoop; + step.hideGraphView = self.hideGraphView; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, speechFileNameWithExtension); + ORK_DECODE_OBJ(aDecoder, noiseFileNameWithExtension); + ORK_DECODE_OBJ(aDecoder, filterFileNameWithExtension); + ORK_DECODE_DOUBLE(aDecoder, gainAppliedToNoise); + ORK_DECODE_BOOL(aDecoder, willAudioLoop); + ORK_DECODE_BOOL(aDecoder, hideGraphView); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, speechFileNameWithExtension); + ORK_ENCODE_OBJ(aCoder, noiseFileNameWithExtension); + ORK_ENCODE_OBJ(aCoder, filterFileNameWithExtension); + ORK_ENCODE_DOUBLE(aCoder, gainAppliedToNoise); + ORK_ENCODE_BOOL(aCoder, willAudioLoop); + ORK_ENCODE_BOOL(aCoder, hideGraphView); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.speechFileNameWithExtension, castObject.speechFileNameWithExtension) + && ORKEqualObjects(self.noiseFileNameWithExtension, castObject.noiseFileNameWithExtension) + && ORKEqualObjects(self.filterFileNameWithExtension, castObject.filterFileNameWithExtension) + && (self.gainAppliedToNoise == castObject.gainAppliedToNoise) + && (self.willAudioLoop == castObject.willAudioLoop) + && (self.hideGraphView == castObject.hideGraphView)); +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.h new file mode 100755 index 0000000..ea157dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +@interface ORKSpeechInNoiseStepViewController : ORKActiveStepViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.m new file mode 100755 index 0000000..2f83679 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechInNoiseStepViewController.m @@ -0,0 +1,202 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechInNoiseStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKStepContainerView_Private.h" +#import "ORKSpeechInNoiseContentView.h" +#import "ORKSpeechInNoiseStep.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKRoundTappingButton.h" +#import "ORKPlaybackButton.h" +#import "ORKSkin.h" + +#import +@import Accelerate; + +@interface ORKSpeechInNoiseStepViewController () { + AVAudioEngine *_audioEngine; + AVAudioPlayerNode *_playerNode; + AVAudioMixerNode *_mixerNode; + float _peakPower; + float _toneDuration; + AVAudioPCMBuffer *_noiseAudioBuffer; + AVAudioPCMBuffer *_speechAudioBuffer; + AVAudioPCMBuffer *_filterAudioBuffer; + AVAudioFrameCount _speechToneCapacity; + AVAudioFrameCount _noiseToneCapacity; + BOOL _installedTap; +} + +@property (nonatomic, strong) ORKSpeechInNoiseContentView *speechInNoiseContentView; + +@end + +@implementation ORKSpeechInNoiseStepViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + _noiseAudioBuffer = [[AVAudioPCMBuffer alloc] init]; + _speechAudioBuffer = [[AVAudioPCMBuffer alloc] init]; + _filterAudioBuffer = [[AVAudioPCMBuffer alloc] init]; + _installedTap = NO; + self.speechInNoiseContentView = [[ORKSpeechInNoiseContentView alloc] init]; + self.activeStepView.activeCustomView = self.speechInNoiseContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + _speechInNoiseContentView.alertColor = [UIColor blueColor]; + [self.speechInNoiseContentView.playButton addTarget:self action:@selector(tapButtonPressed) forControlEvents:UIControlEventTouchDown]; + [_speechInNoiseContentView setGraphViewHidden:[self speechInNoiseStep].hideGraphView]; + _audioEngine = [[AVAudioEngine alloc] init]; + _playerNode = [[AVAudioPlayerNode alloc] init]; + [_audioEngine attachNode:_playerNode]; + [self setupBuffers]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + if (_playerNode) { + [_playerNode stop]; + [_mixerNode removeTapOnBus:0]; + [_audioEngine stop]; + _noiseAudioBuffer = nil; + _speechAudioBuffer = nil; + _filterAudioBuffer = nil; + _audioEngine = nil; + _playerNode = nil; + _mixerNode = nil; + } +} + +- (void)setupBuffers { + [self loadFileName:[self speechInNoiseStep].speechFileNameWithExtension intoBuffer:&_speechAudioBuffer]; + [self loadFileName:[self speechInNoiseStep].noiseFileNameWithExtension intoBuffer:&_noiseAudioBuffer]; + [self loadFileName:[self speechInNoiseStep].filterFileNameWithExtension intoBuffer:&_filterAudioBuffer]; + + _mixerNode = _audioEngine.mainMixerNode; + [_audioEngine connect:_playerNode to:_mixerNode format:_speechAudioBuffer.format]; + [_audioEngine startAndReturnError:nil]; + + if ([self speechInNoiseStep].willAudioLoop) { + [_playerNode scheduleBuffer:_speechAudioBuffer atTime:nil options:AVAudioPlayerNodeBufferLoops completionHandler:nil]; + } else { + int randomOffset = arc4random_uniform(_noiseToneCapacity - _speechToneCapacity); + for (int i = 0; i < _speechToneCapacity; i++) { + _speechAudioBuffer.floatChannelData[0][i] += _noiseAudioBuffer.floatChannelData[0][i + randomOffset] * [self speechInNoiseStep].gainAppliedToNoise; + } + for (int i = 0; i < _speechToneCapacity; i++) { + _speechAudioBuffer.floatChannelData[0][i] *= _filterAudioBuffer.floatChannelData[0][i]; + } + [_playerNode scheduleBuffer:_speechAudioBuffer atTime:nil options:AVAudioPlayerNodeBufferInterrupts completionHandler:nil]; + } +} + +- (void)loadFileName: (NSString *)file intoBuffer: (AVAudioPCMBuffer * __strong *)buffer { + NSArray *fileComponents = [file componentsSeparatedByString:@"."]; + NSString *fileName = fileComponents[0]; + NSString *fileExtension = fileComponents[1]; + + NSURL *fileURL = [[NSBundle bundleForClass:[self class]] URLForResource:fileName withExtension:fileExtension]; + + AVAudioFile *audioFile = [[AVAudioFile alloc] initForReading:fileURL error:nil]; + AVAudioFormat *audioFileFormat = audioFile.processingFormat; + AVAudioFrameCount audioFileCapacity = (AVAudioFrameCount)audioFile.length; + if (*buffer == _filterAudioBuffer) { + _speechToneCapacity = audioFileCapacity; + } else if (*buffer == _noiseAudioBuffer) { + _noiseToneCapacity = audioFileCapacity; + } else { + AVAsset *asset = [AVURLAsset URLAssetWithURL:fileURL options:nil]; + CMTime audioDuration = asset.duration; + _toneDuration = CMTimeGetSeconds(audioDuration); + } + *buffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:audioFileFormat frameCapacity:audioFileCapacity]; + [audioFile readIntoBuffer:*buffer error:nil]; +} + +- (void)installTap { + + AVAudioFormat *mainMixerFormat = [[_audioEngine mainMixerNode] outputFormatForBus:0]; + + [_mixerNode installTapOnBus:0 bufferSize:1024 format:mainMixerFormat block:^(AVAudioPCMBuffer * _Nonnull buffer5, AVAudioTime * _Nonnull when) { + float * const *channelData = [buffer5 floatChannelData]; + if (channelData[0]) { + float avgValue = 0; + unsigned long nFrames = [buffer5 frameLength]; + + vDSP_maxmgv(channelData[0], 1 , &avgValue, nFrames); + float lvlLowPassTrig = 0.3; + _peakPower = lvlLowPassTrig * ((avgValue == 0)? -100 : 20* log10(avgValue)) + (1 - lvlLowPassTrig) * _peakPower; + float clampedValue = MAX(_peakPower / 60.0, -1) + 1; + + dispatch_async(dispatch_get_main_queue(), ^{ + [_speechInNoiseContentView addSample:@(clampedValue)]; + }); + } + }]; + +} + +- (void)tapButtonPressed { + if (_playerNode.isPlaying) { + [_playerNode stop]; + [_mixerNode removeTapOnBus:0]; + [self finish]; + } else { + [self installTap]; + [_playerNode play]; + if ([self speechInNoiseStep].willAudioLoop) { + [_speechInNoiseContentView.playButton setTitle:ORKLocalizedString(@"SPEECH_IN_NOISE_STOP_AUDIO_LABEL", nil) + forState:UIControlStateNormal]; + [_speechInNoiseContentView.playButton setTintColor:[UIColor ork_redColor]]; + } else { + ORKWeakTypeOf(self) weakSelf = self; + [_speechInNoiseContentView.playButton setEnabled:NO]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_toneDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + [_playerNode stop]; + [_mixerNode removeTapOnBus:0]; + [strongSelf finish]; + }); + } + } +} + +- (ORKSpeechInNoiseStep *)speechInNoiseStep { + return (ORKSpeechInNoiseStep *)self.step; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.h new file mode 100755 index 0000000..9336963 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN +@class ORKBorderedButton; + +@interface ORKSpeechRecognitionContentView : ORKActiveStepCustomView + +@property (nonatomic, copy, nullable) UIColor *keyColor; + +@property (nonatomic, assign) BOOL failed; + +@property (nonatomic, assign, getter=isFinished) BOOL finished; + +@property (nonatomic, copy, nullable) NSArray *samples; + +@property (nonatomic) ORKBorderedButton *recordButton; + +@property (nonatomic, copy, nullable) UIImage *speechRecognitionImage; + +@property (nonatomic, copy, nullable) NSString *speechRecognitionText; + +@property (nonatomic) BOOL shouldHideTranscript; + +// Samples should be in the range of (0, 1). +- (void)addSample:(NSNumber *)sample; +- (void)removeAllSamples; + +- (void)updateRecognitionText:(NSString *)recognitionText; + +- (void)addRecognitionError:(NSString *)errorMsg; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.m new file mode 100755 index 0000000..24ad525 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionContentView.m @@ -0,0 +1,256 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechRecognitionContentView.h" +#import "ORKAudioGraphView.h" + +#import "ORKHeadlineLabel.h" +#import "ORKSubheadlineLabel.h" +#import "ORKLabel.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKBorderedButton.h" + +@interface ORKSpeechRecognitionContentView () + +@property (nonatomic, strong) ORKAudioGraphView *graphView; +@property (nonatomic, strong) ORKSubheadlineLabel *transcriptLabel; + +@end + + +@implementation ORKSpeechRecognitionContentView { + NSMutableArray *_samples; + UIColor *_keyColor; + UIImageView *_imageView; + UILabel *_textLabel; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setupTranscriptLabel]; + [self setupGraphView]; + [self setupRecordButton]; + [self setupImageView]; + [self setupTextLabel]; + [self updateGraphSamples]; + [self applyKeyColor]; + [self setUpConstraints]; + } + return self; +} + +- (void)setupImageView { + _imageView = [UIImageView new]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_imageView]; +} + +- (void)setupTextLabel { + _textLabel = [UILabel new]; + _textLabel.font = [[UIFontMetrics metricsForTextStyle:UIFontTextStyleTitle2] scaledFontForFont:[UIFont systemFontOfSize:25.0 weight:UIFontWeightMedium]]; + _textLabel.textColor = [self tintColor]; + _textLabel.textAlignment = NSTextAlignmentCenter; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.lineBreakMode = NSLineBreakByWordWrapping; + _textLabel.numberOfLines = 0; + _textLabel.adjustsFontForContentSizeCategory = YES; + [self addSubview:_textLabel]; +} + +- (void)setupGraphView { + self.graphView = [ORKAudioGraphView new]; + _graphView.translatesAutoresizingMaskIntoConstraints = NO; + _graphView.isAccessibilityElement = YES; + _graphView.accessibilityLabel = ORKLocalizedString(@"AX_SPEECH_RECOGNITION_WAVEFORM", nil); + _graphView.accessibilityTraits = UIAccessibilityTraitImage; + + [self addSubview:_graphView]; +} + +- (void)setupTranscriptLabel { + _transcriptLabel = [ORKSubheadlineLabel new]; + _transcriptLabel.textAlignment = NSTextAlignmentCenter; + _transcriptLabel.translatesAutoresizingMaskIntoConstraints = NO; + _transcriptLabel.text = ORKLocalizedString(@"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL", nil); + _transcriptLabel.lineBreakMode = NSLineBreakByWordWrapping; + _transcriptLabel.numberOfLines = 0; + + [self addSubview:_transcriptLabel]; +} + +- (void)setupRecordButton { + self.recordButton = [[ORKBorderedButton alloc] init]; + self.recordButton.translatesAutoresizingMaskIntoConstraints = NO; + [self.recordButton setTitle:ORKLocalizedString(@"SPEECH_RECOGNITION_START_RECORD_LABEL", nil) + forState:UIControlStateNormal]; + self.recordButton.enabled = YES; + self.recordButton.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitStartsMediaSession; + self.recordButton.accessibilityHint = ORKLocalizedString(@"AX_SPEECH_RECOGNITION_START_RECORDING_HINT", nil); + [self addSubview:_recordButton]; +} + +- (void)setSpeechRecognitionText:(NSString *)speechRecognitionText { + _speechRecognitionText = speechRecognitionText; + [_textLabel setText:speechRecognitionText]; +} + +- (void)setSpeechRecognitionImage:(UIImage *)speechRecognitionImage { + _speechRecognitionImage = speechRecognitionImage; + [_imageView setImage:speechRecognitionImage]; +} + +- (void)tintColorDidChange { + [self applyKeyColor]; +} + +- (void)setFinished:(BOOL)finished { + _finished = finished; +} + +- (void)applyKeyColor { + UIColor *keyColor = [self keyColor]; + _graphView.keyColor = keyColor; +} + +- (UIColor *)keyColor { + return _keyColor ? : [self tintColor]; +} + +- (void)setKeyColor:(UIColor *)keyColor { + _keyColor = keyColor; + [self applyKeyColor]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_imageView, _textLabel, _transcriptLabel, _graphView, _recordButton); + const CGFloat graphHeight = 150; + + // In case the text on the button is large, ensure that the button can grow larger than the default height if needed + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_imageView]-[_textLabel]-(5)-[_graphView(graphHeight)]-[_transcriptLabel]-buttonGap-[_recordButton(50@250)]-topBottomMargin-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ + @"graphHeight": @(graphHeight), + @"topBottomMargin" : @(5), + @"buttonGap" : @(20) + } + views:views]]; + + + const CGFloat sideMargin = self.layoutMargins.left + (2 * ORKStandardLeftMarginForTableViewCell(self)); + const CGFloat twiceSideMargin = sideMargin * 2; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_imageView]-|" + options:0 + metrics: nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_textLabel]-|" + options:0 + metrics: nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-sideMargin-[_graphView]-sideMargin-|" + options:0 + metrics: @{@"sideMargin": @(sideMargin)} + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_transcriptLabel]-|" + options:0 + metrics: @{@"sideMargin": @(sideMargin)} + views:views]]; + + // In case the text on the button is large, ensure that the button can grow larger than the default width if needed + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-twiceSideMargin@250-[_recordButton(200@250)]-twiceSideMargin@250-|" + options:0 + metrics: @{@"twiceSideMargin": @(twiceSideMargin)} + views:views]]; + [constraints addObject:[_recordButton.centerXAnchor constraintEqualToAnchor:self.centerXAnchor]]; + [constraints addObject:[_recordButton.leadingAnchor constraintGreaterThanOrEqualToAnchor:self.layoutMarginsGuide.leadingAnchor]]; + [constraints addObject:[_recordButton.trailingAnchor constraintLessThanOrEqualToAnchor:self.layoutMarginsGuide.trailingAnchor]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setShouldHideTranscript:(BOOL)shouldHideTranscript { + _shouldHideTranscript = shouldHideTranscript; + if (shouldHideTranscript) { + _transcriptLabel.text = nil; + } +} + +- (void)updateGraphSamples { + _graphView.values = _samples; +} + +- (void)addSample:(NSNumber *)sample { + NSAssert(sample != nil, @"Sample should be non-nil"); + if (!_samples) { + _samples = [NSMutableArray array]; + } + [_samples addObject:sample]; + // Try to keep around 250 samples + if (_samples.count > 500) { + _samples = [[_samples subarrayWithRange:(NSRange){250, _samples.count - 250}] mutableCopy]; + } + [self updateGraphSamples]; +} + +- (void)updateRecognitionText:(NSString *)recognitionText { + if (!_shouldHideTranscript) { + _transcriptLabel.text = recognitionText; + } +} + +- (void)addRecognitionError:(NSString *)errorMsg { + _transcriptLabel.textColor = [UIColor ork_redColor]; + _transcriptLabel.text = errorMsg; +} + +- (void)removeAllSamples { + _samples = nil; + [self updateGraphSamples]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionError.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionError.h new file mode 100755 index 0000000..a236a6e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionError.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +typedef NS_ENUM(NSInteger, ORKSpeechRecognitionErrorCode) { + ORKSpeechRecognitionErrorLanguageNotAvailable = 1, + ORKSpeechRecognitionErrorResumeNotSupported, + ORKSpeechRecognitionErrorRecognitionFailed +} ORK_ENUM_AVAILABLE; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.h new file mode 100755 index 0000000..3648717 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKSpeechRecognitionResult` class represents the result of a single successful attempt of an ORKSpeechRecognitionStep. + + A speech recognition result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpeechRecognitionResult : ORKResult + +/** + A hypothesized textual representation of recognized speech + SFTranscription is described at: https://developer.apple.com/documentation/speech/sftranscription + */ +@property (nonatomic, copy, nullable) SFTranscription *transcription; + +@end + +NS_ASSUME_NONNULL_END + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.m new file mode 100755 index 0000000..8a5541f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionResult.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechRecognitionResult.h" +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKSpeechRecognitionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, transcription); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, transcription, SFTranscription); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.transcription, castObject.transcription)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpeechRecognitionResult *result = [super copyWithZone:zone]; + result.transcription = [self.transcription copy]; + return result; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"transcription = %@;", self.transcription]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.h new file mode 100755 index 0000000..4903b99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKSpeechRecognitionStep : ORKActiveStep + +/** + The language for speech recognition + + The default value of this property is @"en-US". + */ +@property (nonatomic, copy) ORKSpeechRecognizerLocale speechRecognizerLocale; + +/** + The property to hide transcription as the user speaks. + */ +@property (nonatomic) BOOL shouldHideTranscript; + +- (instancetype) initWithIdentifier:(NSString *)identifier image:(nullable UIImage *)image text:(nullable NSString *)text; + +- (nullable UIImage *)speechRecognitionImage; + +- (nullable NSString *)speechRecognitionText; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.m new file mode 100755 index 0000000..ab98993 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStep.m @@ -0,0 +1,114 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechRecognitionStep.h" + +#import "ORKSpeechRecognitionStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSpeechRecognitionStep { + UIImage *_speechRecognitionImage; + NSString *_text; +} + ++ (Class)stepViewControllerClass { + return [ORKSpeechRecognitionStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier image:(nullable UIImage *)image text:(nullable NSString *)text { + self = [super initWithIdentifier:identifier]; + _speechRecognitionImage = image; + _text = text; + _speechRecognizerLocale = ORKSpeechRecognizerLocaleEnglishUS; + return self; +} + +- (void)validateParameters { + [super validateParameters]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSpeechRecognitionStep *step = [super copyWithZone:zone]; + step.speechRecognizerLocale = self.speechRecognizerLocale; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, speechRecognizerLocale); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, speechRecognizerLocale); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + [self.speechRecognizerLocale isEqual:castObject.speechRecognizerLocale]); +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (BOOL)startsFinished { + return NO; +} + +- (BOOL)shouldContinueOnFinish { + return YES; +} + +- (nullable UIImage *)speechRecognitionImage { + return _speechRecognitionImage; +} + +- (nullable NSString *)speechRecognitionText { + return _text; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.h new file mode 100755 index 0000000..3c9e857 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Step view controller corresponding to `ORKSpeechRecognitionStep`. + */ +ORK_CLASS_AVAILABLE +@interface ORKSpeechRecognitionStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.m new file mode 100755 index 0000000..c82c98d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognitionStepViewController.m @@ -0,0 +1,283 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import AVFoundation; +@import Accelerate; + +#import "ORKSpeechRecognitionStepViewController.h" + +#import "ORKQuestionStep.h" +#import "ORKAnswerFormat.h" +#import "ORKTask.h" +#import "ORKActiveStepView.h" +#import "ORKActiveStepViewController_Internal.h" + +#import "ORKSpeechRecognitionContentView.h" +#import "ORKStreamingAudioRecorder.h" +#import "ORKSpeechRecognizer.h" +#import "ORKSpeechRecognitionStep.h" +#import "ORKSpeechRecognitionError.h" + +#import "ORKHelpers_Internal.h" +#import "ORKBorderedButton.h" +#import "ORKSpeechRecognitionResult.h" +#import "ORKResult_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController.h" + +#import "ORKOrderedTask.h" + + +@interface ORKSpeechRecognitionStepViewController () + +@end + + +@implementation ORKSpeechRecognitionStepViewController { + ORKSpeechRecognitionContentView *_speechRecognitionContentView; + ORKStreamingAudioRecorder *_audioRecorder; + ORKSpeechRecognizer *_speechRecognizer; + + dispatch_queue_t _speechRecognitionQueue; + ORKSpeechRecognitionResult *_localResult; + BOOL _errorState; + float _peakPower; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + ORKSpeechRecognitionStep *step = (ORKSpeechRecognitionStep *) self.step; + _speechRecognitionContentView = [ORKSpeechRecognitionContentView new]; + _speechRecognitionContentView.shouldHideTranscript = step.shouldHideTranscript; + self.activeStepView.activeCustomView = _speechRecognitionContentView; + _speechRecognitionContentView.speechRecognitionImage = step.speechRecognitionImage; + _speechRecognitionContentView.speechRecognitionText = step.speechRecognitionText; + + [_speechRecognitionContentView.recordButton addTarget:self + action:@selector(recordButtonPressed:) + forControlEvents:UIControlEventTouchDown]; + + _errorState = NO; + + [ORKSpeechRecognizer requestAuthorization]; + + _localResult = [[ORKSpeechRecognitionResult alloc] initWithIdentifier:self.step.identifier]; + _speechRecognitionQueue = dispatch_queue_create("SpeechRecognitionQueue", DISPATCH_QUEUE_SERIAL); +} + +- (void)initializeRecognizer { + _speechRecognizer = [[ORKSpeechRecognizer alloc] init]; + + if (_speechRecognizer) { + [_speechRecognizer startRecognitionWithLocale:[NSLocale localeWithLocaleIdentifier:((ORKSpeechRecognitionStep *)self.step).speechRecognizerLocale] reportPartialResults:YES responseDelegate:self errorHandler:^(NSError *error) { + if (error) { + [self stopWithError:error]; + } + }]; + } +} + +- (void)recordButtonPressed:(id)sender { + if (sender == _speechRecognitionContentView.recordButton) { + if ([_speechRecognitionContentView.recordButton.titleLabel.text + isEqualToString:ORKLocalizedString(@"SPEECH_RECOGNITION_STOP_RECORD_LABEL", nil)]) { + [self stopWithError:nil]; + } else { + + [self initializeRecognizer]; + + [self start]; + [_speechRecognitionContentView.recordButton setTitle:ORKLocalizedString(@"SPEECH_RECOGNITION_STOP_RECORD_LABEL", nil) + forState:UIControlStateNormal]; + _speechRecognitionContentView.recordButton.enabled = YES; + } + } +} + +- (void)recordersDidChange { + ORKStreamingAudioRecorder *audioRecorder = nil; + for (ORKRecorder *recorder in self.recorders) { + if ([recorder isKindOfClass:[ORKStreamingAudioRecorder class]]) { + audioRecorder = (ORKStreamingAudioRecorder *)recorder; + break; + } + } + _audioRecorder = audioRecorder; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + if (_speechRecognitionQueue) { + dispatch_sync(_speechRecognitionQueue, ^{ + if (_localResult != nil) { + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + [results addObject:_localResult]; + sResult.results = [results copy]; + } + }); + } + return sResult; +} + +- (void)stopWithError:(NSError *)error { + if (_speechRecognizer) { + [_speechRecognizer endAudio]; + } + + if (error) { + ORK_Log_Error("Speech recognition failed with error message: \"%@\"", error.localizedDescription); + [_speechRecognitionContentView addRecognitionError:error.localizedDescription]; + _speechRecognitionContentView.recordButton.enabled = NO; + _errorState = YES; + } + [self stopRecorders]; +} + +- (void)resume { + // Background processing is not supported +} + +- (void)goForward { + if ([self hasNextStep]) { + ORKQuestionStep *nextStep = [self nextStep]; + if (nextStep) { + [((ORKTextAnswerFormat *)nextStep.answerFormat) setDefaultTextAnswer: [_localResult.transcription formattedString]]; + } + } + [super goForward]; +} + +- (nullable ORKQuestionStep *)nextStep { + ORKOrderedTask *task = (ORKOrderedTask *)[self.taskViewController task]; + NSUInteger nextStepIndex = [task indexOfStep:[self step]] + 1; + ORKStep *nextStep = [task steps][nextStepIndex]; + + if ([nextStep isKindOfClass:[ORKQuestionStep class]]) { + return (ORKQuestionStep *)nextStep; + } else { + return nil; + } +} + +- (void)stepDidFinish { + _speechRecognitionContentView.finished = YES; +} + +- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + [super recorder:recorder didFailWithError:error]; + [self stopWithError:error]; +} + +// Methods running on a different thread + +#pragma mark - ORKStreamingAudioResultDelegate +- (void)audioAvailable:(AVAudioPCMBuffer *)buffer { + if (_errorState) { + return; + } + [_speechRecognizer addAudio:buffer]; + + // audio metering display + float * const *channelData = [buffer floatChannelData]; + if (channelData[0]) { + float avgValue = 0; + unsigned long nFrames = [buffer frameLength]; + vDSP_maxmgv(channelData[0], 1 , &avgValue, nFrames); + float lvlLowPassTrig = 0.3; + _peakPower = lvlLowPassTrig * ((avgValue == 0)? -100 : 20* log10(avgValue)) + (1 - lvlLowPassTrig) * _peakPower; + float clampedValue = MAX(_peakPower / 60.0, -1) + 1; + + dispatch_async(dispatch_get_main_queue(), ^{ + [_speechRecognitionContentView addSample:@(clampedValue)]; + }); + } +} + +#pragma mark - ORKSpeechRecognitionDelegate + +- (void)didFinishRecognitionWithError:(NSError *)error { + if (_errorState) { + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + ORK_Log_Error("Speech framework failed with error code: %ld, and error description: %@", (long)error.code, error.localizedDescription); + NSError *recognitionError = [NSError errorWithDomain:ORKErrorDomain + code:ORKSpeechRecognitionErrorRecognitionFailed + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"SPEECH_RECOGNITION_FAILED", nil)}]; + [self stopWithError:recognitionError]; + } else { + [self stopWithError:nil]; + [self finish]; + } + }); +} + +- (void)didHypothesizeTranscription:(SFTranscription *)transcription { + if (_errorState) { + return; + } + dispatch_sync(_speechRecognitionQueue, ^{ + _localResult.transcription = transcription; + }); + + dispatch_async(dispatch_get_main_queue(), ^{ + [_speechRecognitionContentView updateRecognitionText:[transcription formattedString]]; + }); +} + +- (void)availabilityDidChange:(BOOL)available { + if (!available) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self stopWithError:[NSError errorWithDomain:ORKErrorDomain + code:ORKSpeechRecognitionErrorLanguageNotAvailable + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"Speech recognizer not available", nil)}]]; + }); + } +} + +- (void)recordersWillStart { + ORK_Log_Debug("Recorder is starting"); +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.h new file mode 100755 index 0000000..3b7e520 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.h @@ -0,0 +1,89 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import AVFoundation; +@import Speech; + +@protocol ORKSpeechRecognitionDelegate + +@optional +/** + Tells the delegate when the recognition of requested utterance is finished. + */ +- (void)didFinishRecognitionWithError:(NSError *)error; + +/** + Tells the delegate that a hypothesized transcription is available. + */ +- (void)didHypothesizeTranscription:(SFTranscription *)transcription; + +/** + Tells the delegate when the availability of the speech recognizer has changed + */ +- (void)availabilityDidChange:(BOOL)available; + +@end + +/** + The `ORKSpeechRecognizer` class is a wrapper for the Speech API framework + */ +@interface ORKSpeechRecognizer: NSObject + +/** + Asks the user to grant your app permission to perform speech recognition. + */ ++ (void)requestAuthorization; + +/** + Starts speech recognition for the specified locale + + @param locale Device's locale + @param reportPartialResults A boolean value that indicates whether partial, nonfinal results for each utterance are reported. + @param delegate The delegate for speech recognition response + @param handler A handler to report errors + + */ +- (void)startRecognitionWithLocale:(NSLocale *)locale reportPartialResults:(BOOL)reportPartialResults responseDelegate:(id)delegate errorHandler:(void (^)(NSError *error))handler; + +/** + Appends audio to the end of the recognition request. + + @param audioBuffer A buffer of audio + */ +- (void)addAudio:(AVAudioPCMBuffer *)audioBuffer; + +/** + Indicates that the audio source is finished and no more audio will be appended to the + recognition request. + */ +- (void)endAudio; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.m new file mode 100755 index 0000000..c55e08a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSpeechRecognizer.m @@ -0,0 +1,165 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSpeechRecognizer.h" + +#import +#import +#import +#import +#import +#import + +#import +#import "ORKHelpers_Internal.h" +#import "ORKSpeechRecognitionError.h" + + +@interface ORKSpeechRecognizer() +@property(nonatomic, weak) id responseDelegate; +@end + +@implementation ORKSpeechRecognizer { + SFSpeechAudioBufferRecognitionRequest *request; + SFSpeechRecognizer *recognizer; + dispatch_queue_t _requestQueue; + dispatch_queue_t _responseQueue; +} + ++ (void)requestAuthorization { + + [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { + switch (status) { + case SFSpeechRecognizerAuthorizationStatusAuthorized: + ORK_Log_Debug("Speech recognition request was authorized"); + break; + default: + // User did not authorize speech recognition + break; + } + }]; +} + +- (void)startRecognitionWithLocale:(NSLocale *)locale reportPartialResults:(BOOL)reportPartialResults responseDelegate:(id)delegate errorHandler:(void (^)(NSError *error))handler +{ + + _requestQueue = dispatch_queue_create("SpeechRequestQueue", DISPATCH_QUEUE_SERIAL); + _responseQueue = dispatch_queue_create("SpeechResponseQueue", DISPATCH_QUEUE_SERIAL); + + recognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale]; + if (!recognizer) { + handler([NSError errorWithDomain:ORKErrorDomain + code:ORKSpeechRecognitionErrorLanguageNotAvailable + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"Speech recognizer could not be initialized", nil)}]); + return; + } + [recognizer setDelegate:self]; + + SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus]; + if (status != SFSpeechRecognizerAuthorizationStatusAuthorized) { + handler([NSError errorWithDomain:ORKErrorDomain + code:ORKSpeechRecognitionErrorLanguageNotAvailable + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"Speech recognizer not authorized", nil)}]); + return; + } + [recognizer isAvailable]; + + _responseDelegate = delegate; + + request = [[SFSpeechAudioBufferRecognitionRequest alloc] init]; + if (!request) { + handler([NSError errorWithDomain:ORKErrorDomain + code:ORKSpeechRecognitionErrorLanguageNotAvailable + userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"Speech recognizer could not be initialized", nil)}]); + return; + } + + request.shouldReportPartialResults = reportPartialResults; + request.taskHint = SFSpeechRecognitionTaskHintDictation; + [recognizer recognitionTaskWithRequest:request delegate:self]; + +} + +- (void)addAudio:(AVAudioPCMBuffer *)audioBuffer { + dispatch_async(_requestQueue, ^{ + [request appendAudioPCMBuffer:audioBuffer]; + }); +} + +- (void)endAudio { + dispatch_async(_requestQueue, ^{ + [request endAudio]; + }); +} + +// MARK: SFSpeechRecognizerDelegate + +- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available { + dispatch_async(_responseQueue, ^{ + ORK_Log_Debug("Availability did change = %d", available); + [_responseDelegate availabilityDidChange:available]; + }); +} + +// MARK: SFSpeechRecognizerTaskDelegate + +- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishRecognition:(SFSpeechRecognitionResult *)recognitionResult { + dispatch_async(_responseQueue, ^{ + ORK_Log_Debug("did produce final result %@", [[recognitionResult bestTranscription] formattedString]); + [_responseDelegate didHypothesizeTranscription:[recognitionResult bestTranscription]]; + }); +} +- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didHypothesizeTranscription:(SFTranscription *)transcription { + dispatch_async(_responseQueue, ^{ + // Produces transcription if shouldReportPartialResults is true + ORK_Log_Debug("did produce partial results %@", [transcription formattedString]); + [_responseDelegate didHypothesizeTranscription:transcription]; + }); +} + +- (void)speechRecognitionTask:(SFSpeechRecognitionTask *)task didFinishSuccessfully:(BOOL)successfully { + dispatch_async(_responseQueue, ^{ + if (!successfully) { + [_responseDelegate didFinishRecognitionWithError:task.error]; + } else { + [_responseDelegate didFinishRecognitionWithError:nil]; + } + }); +} + +- (void)speechRecognitionTaskWasCancelled:(SFSpeechRecognitionTask *)task { + dispatch_async(_responseQueue, ^{ + ORK_Log_Debug("Request cancelled"); + [_responseDelegate didFinishRecognitionWithError:nil]; + }); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.h new file mode 100755 index 0000000..3e6ba72 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.h @@ -0,0 +1,76 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import AVFoundation; +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKStreamingAudioResultDelegate + +@optional +- (void)audioAvailable:(AVAudioPCMBuffer *)buffer; + +@end + +/** + The ORKStreamingAudioRecorder class represents a recorder that uses the app's + `AVAudioSession` object to record audio. + + To audio recording will be discontinued if task enters the background. + */ +ORK_CLASS_AVAILABLE +@interface ORKStreamingAudioRecorder : ORKRecorder + +/** + Returns an initialized audio recorder using the specified step, and output directory. + + @param identifier The unique identifier of the recorder (assigned by the recorder configuration). + @param step The step that requested this recorder. + @param outputDirectory The directory in which the audio output should be stored. + + @return An initialized audio recorder. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + step:(nullable ORKStep *)step + outputDirectory:(nullable NSURL *)outputDirectory NS_DESIGNATED_INITIALIZER; + +/** + Reference to the audio recorder being used. + + The value of this property is used in the audio task in order to display recorded volume and metering in real time during the task. + */ +@property (nonatomic, strong, readonly, nullable) AVAudioEngine *audioEngine; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.m new file mode 100755 index 0000000..9b3b40d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStreamingAudioRecorder.m @@ -0,0 +1,285 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStreamingAudioRecorder.h" + +#import "ORKRecorder_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKStreamingAudioRecorder () + +@property (nonatomic, copy) NSString *savedSessionCategory; + +@end + + +@implementation ORKStreamingAudioRecorder + +- (void)dealloc { + ORK_Log_Debug("Remove audiorecorder %p", self); + if ([_audioEngine isRunning]) { + [_audioEngine stop]; + [[_audioEngine inputNode] removeTapOnBus:0]; + } + _audioEngine = nil; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + step:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier step:step outputDirectory:outputDirectory]; + if (self) { + + self.continuesInBackground = YES; + } + return self; +} + +- (void)restoreSavedAudioSessionCategory { + if (_savedSessionCategory) { + NSError *error; + if (![[AVAudioSession sharedInstance] setCategory:_savedSessionCategory error:&error]) { + ORK_Log_Error("Failed to restore the audio session category: %@", [error localizedDescription]); + } + _savedSessionCategory = nil; + } +} + +- (NSURL *)recordingFileURL { + return [[self recordingDirectoryURL] URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", [self logName], @"wav"]]; +} + +- (BOOL)recreateFileWithError:(NSError **)errorOut { + NSURL *url = [self recordingFileURL]; + if (!url) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteInvalidFileNameError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"ERROR_RECORDER_NO_OUTPUT_DIRECTORY", nil)}]; + } + return NO; + } + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (![fileManager createDirectoryAtURL:url withIntermediateDirectories:YES attributes:nil error:errorOut]) { + return NO; + } + + if ([fileManager fileExistsAtPath:[url path]]) { + if (![fileManager removeItemAtPath:[url path] error:errorOut]) { + return NO; + } + } + + [fileManager createFileAtPath:[url path] contents:nil attributes:nil]; + [fileManager setAttributes:@{NSFileProtectionKey: ORKFileProtectionFromMode(ORKFileProtectionCompleteUnlessOpen)} ofItemAtPath:[url path] error:errorOut]; + return YES; +} + +- (void)start { + if (self.outputDirectory == nil) { + @throw [NSException exceptionWithName:NSDestinationInvalidException reason:@"StreamingAudioRecorder requires an output directory" userInfo:nil]; + } + if (!_audioEngine) + { + NSError *error = nil; + + if (![self recreateFileWithError:&error]) { + [self finishRecordingWithError:error]; + return; + } + + AVAudioSession *audioSession = [AVAudioSession sharedInstance]; + _savedSessionCategory = audioSession.category; + if (![audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]) { + [self finishRecordingWithError:error]; + return; + } + [audioSession setMode:AVAudioSessionModeMeasurement error:&error]; + if (error) { + [self finishRecordingWithError:error]; + return; + } + [audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]; + if (error) { + [self finishRecordingWithError:error]; + return; + } + + ORK_Log_Debug("Create audioEngine recorder %p", self); + + _audioEngine = [[AVAudioEngine alloc] init]; + AVAudioInputNode *inputnode = _audioEngine.inputNode; + AVAudioFormat *recordingFormat = [inputnode inputFormatForBus:0]; + + NSURL *audiourl = [self recordingFileURL]; + + // Update the file type to be written to the file + NSMutableDictionary *modifiedSettings = [NSMutableDictionary dictionaryWithDictionary:[recordingFormat settings]]; + if (@available(iOS 11.0, *)) { + modifiedSettings[AVAudioFileTypeKey] = [NSNumber numberWithInt:kAudioFileWAVEType]; + } else { + // Fallback on earlier versions + ORK_Log_Info("ORKStreamingAudioRecorder can only be used with iOS 11.0 or above."); + } + + AVAudioFile *mixerOutputFile = [[AVAudioFile alloc] initForWriting:audiourl settings:modifiedSettings error:&error]; + if (error) { + [self finishRecordingWithError:error]; + return; + } + + [inputnode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) { + id delegate = (id)self.delegate; + NSError *recordingError; + [mixerOutputFile writeFromBuffer:buffer error:&recordingError]; + if (recordingError) { + [self finishRecordingWithError:recordingError]; + return; + } + + if (delegate && [delegate respondsToSelector:@selector(audioAvailable:)]) { + [delegate audioAvailable:buffer]; + } + }]; + + [_audioEngine prepare]; + [_audioEngine startAndReturnError:&error]; + if (error != nil) { + [self finishRecordingWithError:error]; + return; + } + } + + [super start]; + +} + +- (void)stop { + if (!_audioEngine) { + // Error has already been returned. + return; + } + [self doStopRecording]; + + NSURL *fileUrl = [self recordingFileURL]; + if (![[NSFileManager defaultManager] fileExistsAtPath:[[self recordingFileURL] path]]) { + fileUrl = nil; + } + [self reportFileResultWithFile:fileUrl error:nil]; + + [super stop]; +} + +- (BOOL)isRecording { + return [_audioEngine isRunning]; +} + +- (NSString *)recorderType { + return @"streamingAudio"; +} + +- (void)doStopRecording { + if (self.isRecording) { + if ([_audioEngine isRunning]) { + [_audioEngine stop]; + [[_audioEngine inputNode] removeTapOnBus:0]; + } + _audioEngine = nil; +#if !TARGET_IPHONE_SIMULATOR + [self applyFileProtection:ORKFileProtectionComplete toFileAtURL:[self recordingFileURL]]; +#endif + [self restoreSavedAudioSessionCategory]; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + + [super finishRecordingWithError:error]; +} + +- (void)reset { + if ([_audioEngine isRunning]) { + [_audioEngine stop]; + [[_audioEngine inputNode] removeTapOnBus:0]; + } + _audioEngine = nil; + [super reset]; +} + +@end + + +@implementation ORKStreamingAudioRecorderConfiguration + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" + + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + + return self; +} +#pragma clang diagnostic pop + +- (ORKRecorder *)recorderForStep:(ORKStep *)step + outputDirectory:(NSURL *)outputDirectory { + ORKStreamingAudioRecorder *obj = [[ORKStreamingAudioRecorder alloc] initWithIdentifier:self.identifier + step:step + outputDirectory:outputDirectory]; + return obj; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + return [super isEqual:object]; +} + +- (ORKPermissionMask)requestedPermissionMask { + return ORKPermissionAudioRecording; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.h new file mode 100755 index 0000000..ebcf863 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + +#import "ORKCustomStepView_Internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKBorderedButton; + +@interface ORKStroopContentView : ORKActiveStepCustomView + +@property (nonatomic) NSString * colorLabelText; +@property (nonatomic) UIColor * colorLabelColor; +@property (nonatomic) ORKBorderedButton * RButton; +@property (nonatomic) ORKBorderedButton * GButton; +@property (nonatomic) ORKBorderedButton * BButton; +@property (nonatomic) ORKBorderedButton * YButton; + +@end +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.m new file mode 100755 index 0000000..c73426c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopContentView.m @@ -0,0 +1,149 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStroopContentView.h" +#import "ORKUnitLabel.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKBorderedButton.h" + + +static const CGFloat minimumButtonHeight = 60; +static const CGFloat buttonStackViewSpacing = 20.0; + +@implementation ORKStroopContentView { + UILabel *_colorLabel; + UIStackView *_buttonStackView; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.translatesAutoresizingMaskIntoConstraints = NO; + _colorLabel = [UILabel new]; + _colorLabel.numberOfLines = 1; + _colorLabel.textAlignment = NSTextAlignmentCenter; + _colorLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_colorLabel setFont:[UIFont systemFontOfSize:60]]; + [_colorLabel setAdjustsFontSizeToFitWidth:YES]; + + + _RButton = [[ORKBorderedButton alloc] init]; + _RButton.translatesAutoresizingMaskIntoConstraints = NO; + [_RButton setTitle:ORKLocalizedString(@"STROOP_COLOR_RED_INITIAL", nil) forState:UIControlStateNormal]; + + _GButton = [[ORKBorderedButton alloc] init]; + _GButton.translatesAutoresizingMaskIntoConstraints = NO; + [_GButton setTitle:ORKLocalizedString(@"STROOP_COLOR_GREEN_INITIAL", nil) forState:UIControlStateNormal]; + + _BButton = [[ORKBorderedButton alloc] init]; + _BButton.translatesAutoresizingMaskIntoConstraints = NO; + [_BButton setTitle:ORKLocalizedString(@"STROOP_COLOR_BLUE_INITIAL", nil) forState:UIControlStateNormal]; + + _YButton = [[ORKBorderedButton alloc] init]; + _YButton.translatesAutoresizingMaskIntoConstraints = NO; + [_YButton setTitle:ORKLocalizedString(@"STROOP_COLOR_YELLOW_INITIAL", nil) forState:UIControlStateNormal]; + + if (!_buttonStackView) { + _buttonStackView = [[UIStackView alloc] initWithArrangedSubviews:@[_RButton, _GButton, _BButton, _YButton]]; + } + _buttonStackView.translatesAutoresizingMaskIntoConstraints = NO; + _buttonStackView.spacing = buttonStackViewSpacing; + _buttonStackView.axis = UILayoutConstraintAxisHorizontal; + + [self addSubview:_colorLabel]; + [self addSubview:_buttonStackView]; + + [self setUpConstraints]; + } + return self; +} + +- (void)setColorLabelText:(NSString *)colorLabelText { + [_colorLabel setText:colorLabelText]; + [self setNeedsDisplay]; +} + +- (void)setColorLabelColor:(UIColor *)colorLabelColor { + [_colorLabel setTextColor:colorLabelColor]; + [self setNeedsDisplay]; +} + +- (NSString *)colorLabelText { + return _colorLabel.text; +} + +- (UIColor *)colorLabelColor { + return _colorLabel.textColor; +} + +- (void)setUpConstraints { + + NSMutableArray *constraints = [[NSMutableArray alloc] init]; + NSDictionary *views = NSDictionaryOfVariableBindings(_colorLabel, _buttonStackView); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(==30)-[_colorLabel]-(>=10)-[_buttonStackView]-(==30)-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_buttonStackView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:minimumButtonHeight], + [NSLayoutConstraint constraintWithItem:_buttonStackView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0] + ]]; + for (ORKBorderedButton *button in @[_RButton, _GButton, _BButton, _YButton]) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:button + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + } + + [self addConstraints:constraints]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.h new file mode 100755 index 0000000..8fc475c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKStroopResult` class represents the result of a single successful attempt within an ORKStroopStep. + + A stroop result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKStroopResult: ORKResult + +/** + The `startTime` property is equal to the start time of the each step. + */ +@property (nonatomic, assign) NSTimeInterval startTime; + +/** + The `endTime` property is equal to the timestamp when user answers a particular step by selecting a color. + */ +@property (nonatomic, assign) NSTimeInterval endTime; + +/** + The `color` property is the color of the question string. + */ +@property (nonatomic, copy) NSString *color; + +/** + The `text` property is the text of the question string. + */ +@property (nonatomic, copy) NSString *text; + +/** + The `colorSelected` corresponds to the button tapped by the user as an answer. + */ +@property (nonatomic, copy, nullable) NSString *colorSelected; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.m new file mode 100755 index 0000000..ea5df39 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopResult.m @@ -0,0 +1,88 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKStroopResult.h" +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKStroopResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, startTime); + ORK_ENCODE_DOUBLE(aCoder, endTime); + ORK_ENCODE_OBJ(aCoder, color); + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, colorSelected); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, startTime); + ORK_DECODE_DOUBLE(aDecoder, endTime); + ORK_DECODE_OBJ_CLASS(aDecoder, color, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, colorSelected, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.startTime == castObject.startTime) && + (self.endTime == castObject.endTime) && + ORKEqualObjects(self.color, castObject.color) && + ORKEqualObjects(self.text, castObject.text) && + ORKEqualObjects(self.colorSelected, castObject.colorSelected)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKStroopResult *result = [super copyWithZone:zone]; + result.startTime = self.startTime; + result.endTime = self.endTime; + result -> _color = [self.color copy]; + result -> _text = [self.text copy]; + result -> _colorSelected = [self.colorSelected copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; color: %@; text: %@; colorselected: %@ %@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.color, self.text, self.colorSelected, self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.h new file mode 100755 index 0000000..e99dd86 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKStroopStep : ORKActiveStep + +@property (nonatomic, assign) NSInteger numberOfAttempts; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.m new file mode 100755 index 0000000..6f6077b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStep.m @@ -0,0 +1,100 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStroopStep.h" +#import "ORKStroopStepViewController.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKStroopStep + ++ (Class)stepViewControllerClass { + return [ORKStroopStepViewController class]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldVibrateOnStart = YES; + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + self.stepDuration = NSIntegerMax; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + NSInteger minimumAttempts = 10; + if (self.numberOfAttempts < minimumAttempts) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"number of attempts should be greater or equal to %ld.", (long)minimumAttempts] userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKStroopStep *step = [super copyWithZone:zone]; + step.numberOfAttempts = self.numberOfAttempts; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self ) { + ORK_DECODE_INTEGER(aDecoder, numberOfAttempts); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfAttempts); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && (self.numberOfAttempts == castObject.numberOfAttempts)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.h new file mode 100755 index 0000000..4b996b2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKStroopStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.m new file mode 100755 index 0000000..0c19676 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKStroopStepViewController.m @@ -0,0 +1,236 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStroopStepViewController.h" +#import "ORKActiveStepView.h" +#import "ORKStroopContentView.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKStroopResult.h" +#import "ORKResult_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKStroopStep.h" +#import "ORKHelpers_Internal.h" +#import "ORKBorderedButton.h" +#import "ORKNavigationContainerView_Internal.h" + + +@interface ORKStroopStepViewController () + +@property (nonatomic, strong) ORKStroopContentView *stroopContentView; +@property (nonatomic, strong) NSDictionary *colors; +@property (nonatomic, strong) NSDictionary *differentColorLabels; +@property (nonatomic) NSUInteger questionNumber; + +@end + + +@implementation ORKStroopStepViewController { + UIColor *_red; + UIColor *_green; + UIColor *_blue; + UIColor *_yellow; + NSString *_redString; + NSString *_greenString; + NSString *_blueString; + NSString *_yellowString; + NSTimer *_nextQuestionTimer; + + NSMutableArray *_results; + NSTimeInterval _startTime; + NSTimeInterval _endTime; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + self.suspendIfInactive = YES; + } + + return self; +} + +- (ORKStroopStep *)stroopStep { + return (ORKStroopStep *)self.step; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _results = [NSMutableArray new]; + _redString = ORKLocalizedString(@"STROOP_COLOR_RED", nil); + _greenString = ORKLocalizedString(@"STROOP_COLOR_GREEN", nil); + _blueString = ORKLocalizedString(@"STROOP_COLOR_BLUE", nil); + _yellowString = ORKLocalizedString(@"STROOP_COLOR_YELLOW", nil); + _red = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0]; + _green = [UIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0]; + _blue = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0]; + _yellow = [UIColor colorWithRed:1.0 green:1.0 blue:0.0 alpha:1.0]; + + self.colors = @{ + _redString: _red, + _blueString: _blue, + _yellowString: _yellow, + _greenString: _green, + }; + + self.differentColorLabels = @{ + _redString: @[_blue, _green, _yellow], + _blueString: @[_red, _green, _yellow,], + _yellowString: @[_red, _blue, _green], + _greenString: @[_red, _blue, _yellow], + }; + + self.questionNumber = 0; + _stroopContentView = [ORKStroopContentView new]; + self.activeStepView.activeCustomView = _stroopContentView; + + [self.stroopContentView.RButton addTarget:self + action:@selector(buttonPressed:) + forControlEvents:UIControlEventTouchUpInside]; + [self.stroopContentView.GButton addTarget:self + action:@selector(buttonPressed:) + forControlEvents:UIControlEventTouchUpInside]; + [self.stroopContentView.BButton addTarget:self + action:@selector(buttonPressed:) + forControlEvents:UIControlEventTouchUpInside]; + [self.stroopContentView.YButton addTarget:self + action:@selector(buttonPressed:) + forControlEvents:UIControlEventTouchUpInside]; +} + +- (void)buttonPressed:(id)sender { + if (![self.stroopContentView.colorLabelText isEqualToString:@" "]) { + [self setButtonsDisabled]; + if (sender == self.stroopContentView.RButton) { + [self createResult:[self.colors allKeysForObject:self.stroopContentView.colorLabelColor][0] withText:self.stroopContentView.colorLabelText withColorSelected:_redString]; + } + else if (sender == self.stroopContentView.GButton) { + [self createResult:[self.colors allKeysForObject:self.stroopContentView.colorLabelColor][0] withText:self.stroopContentView.colorLabelText withColorSelected:_greenString]; + } + else if (sender == self.stroopContentView.BButton) { + [self createResult:[self.colors allKeysForObject:self.stroopContentView.colorLabelColor][0] withText:self.stroopContentView.colorLabelText withColorSelected:_blueString]; + } + else if (sender == self.stroopContentView.YButton) { + [self createResult:[self.colors allKeysForObject:self.stroopContentView.colorLabelColor][0] withText:self.stroopContentView.colorLabelText withColorSelected:_yellowString]; + } + self.stroopContentView.colorLabelText = @" "; + _nextQuestionTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 + target:self + selector:@selector(startNextQuestionOrFinish) + userInfo:nil + repeats:NO]; + } +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; +} + +- (void)stepDidFinish { + [super stepDidFinish]; + [self.stroopContentView finishStep:self]; + [self goForward]; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + if (_results) { + stepResult.results = [_results copy]; + } + return stepResult; +} + +- (void)start { + [super start]; + [self startQuestion]; +} + + +#pragma mark - ORKResult + +- (void)createResult:(NSString *)color withText:(NSString *)text withColorSelected:(NSString *)colorSelected { + ORKStroopResult *stroopResult = [[ORKStroopResult alloc] initWithIdentifier:self.step.identifier]; + stroopResult.startTime = _startTime; + stroopResult.endTime = [NSProcessInfo processInfo].systemUptime; + stroopResult.color = color; + stroopResult.text = text; + stroopResult.colorSelected = colorSelected; + [_results addObject:stroopResult]; +} + +- (void)startNextQuestionOrFinish { + self.questionNumber = self.questionNumber + 1; + if (self.questionNumber == ([self stroopStep].numberOfAttempts)) { + [self finish]; + } else { + [self startQuestion]; + } +} + +- (void)startQuestion { + int pattern = arc4random() % 2; + if (pattern == 0) { + int index = arc4random() % [self.colors.allKeys count]; + NSString *text = [self.colors.allKeys objectAtIndex:index]; + self.stroopContentView.colorLabelText = text; + UIColor *color = [self.colors valueForKey:text]; + self.stroopContentView.colorLabelColor = color; + } + else { + int index = arc4random() % [self.differentColorLabels.allKeys count]; + NSString *text = [self.differentColorLabels.allKeys objectAtIndex:index]; + self.stroopContentView.colorLabelText = text; + NSArray *colorArray = [self.differentColorLabels valueForKey:text]; + int randomColor = arc4random() % colorArray.count; + UIColor *color = [colorArray objectAtIndex:randomColor]; + self.stroopContentView.colorLabelColor = color; + } + [self setButtonsEnabled]; + _startTime = [NSProcessInfo processInfo].systemUptime; +} + +- (void)setButtonsDisabled { + [self.stroopContentView.RButton setEnabled: NO]; + [self.stroopContentView.GButton setEnabled: NO]; + [self.stroopContentView.BButton setEnabled: NO]; + [self.stroopContentView.YButton setEnabled: NO]; +} + +- (void)setButtonsEnabled { + [self.stroopContentView.RButton setEnabled: YES]; + [self.stroopContentView.GButton setEnabled: YES]; + [self.stroopContentView.BButton setEnabled: YES]; + [self.stroopContentView.YButton setEnabled: YES]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopContentView.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopContentView.swift new file mode 100755 index 0000000..0428934 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopContentView.swift @@ -0,0 +1,168 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +internal class ORKSwiftStroopContentView: ORKActiveStepCustomView { + + public var colorLabelText: String? + public var colorLabelColor: UIColor? + + public let redButton: ORKBorderedButton = { + let button = ORKBorderedButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(ORKSwiftLocalizedString("STROOP_COLOR_RED_INITIAL", ""), for: .normal) + return button + }() + + public let greenButton: ORKBorderedButton = { + let button = ORKBorderedButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(ORKSwiftLocalizedString("STROOP_COLOR_GREEN_INITIAL", ""), for: .normal) + return button + }() + + public let blueButton: ORKBorderedButton = { + let button = ORKBorderedButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(ORKSwiftLocalizedString("STROOP_COLOR_BLUE_INITIAL", ""), for: .normal) + return button + }() + + public let yellowButton: ORKBorderedButton = { + let button = ORKBorderedButton() + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitle(ORKSwiftLocalizedString("STROOP_COLOR_YELLOW_INITIAL", ""), for: .normal) + return button + }() + + private let colorLabel: UILabel = { + let label = UILabel() + let colorLabelFontSize: CGFloat = 60.0 + label.numberOfLines = 1 + label.text = " " + label.textAlignment = .center + label.translatesAutoresizingMaskIntoConstraints = false + label.font = UIFont.systemFont(ofSize: colorLabelFontSize) + label.adjustsFontSizeToFitWidth = true + return label + }() + + private let buttonStackView: UIStackView + + private let minimumButtonHeight: CGFloat = 60.0 + private let buttonStackViewSpacing: CGFloat = 20.0 + + private override init(frame: CGRect) { + buttonStackView = UIStackView(arrangedSubviews: [redButton, greenButton, blueButton, yellowButton]) + super.init(frame: frame) + setup() + } + + internal required init?(coder aDecoder: NSCoder) { + buttonStackView = UIStackView(arrangedSubviews: [redButton, greenButton, blueButton, yellowButton]) + super.init(coder: aDecoder) + setup() + } + + internal func setup() { + self.translatesAutoresizingMaskIntoConstraints = false + buttonStackView.translatesAutoresizingMaskIntoConstraints = false + buttonStackView.spacing = buttonStackViewSpacing + buttonStackView.axis = .horizontal + self.addSubview(colorLabel) + self.addSubview(buttonStackView) + setUpConstraints() + } + + internal func setColorLabelText(colorLabelText text: String) { + colorLabelText = text + colorLabel.text = text + setNeedsDisplay() + } + + internal func setColorLabelColor(colorLabelColor color: UIColor) { + colorLabelColor = color + colorLabel.textColor = color + setNeedsDisplay() + } + + internal func getColorLabelText() -> String { + return colorLabel.text! + } + + internal func getColorLabelColor() -> UIColor { + return colorLabel.textColor + } + + internal func setUpConstraints() { + + var constraints = [NSLayoutConstraint]() + var views = [String: Any]() + views["colorLabel"] = colorLabel + views["buttonStackView"] = buttonStackView + + constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-(==30)-[colorLabel]-(>=10)-[buttonStackView]-(==30)-|", + options: .alignAllCenterX, + metrics: nil, + views: views) + + constraints += [ + NSLayoutConstraint(item: buttonStackView as Any, + attribute: .height, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 1.0, + constant: minimumButtonHeight), + NSLayoutConstraint(item: buttonStackView as Any, + attribute: .centerX, + relatedBy: .equal, + toItem: self, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0) + ] + + for button in [redButton, greenButton, blueButton, yellowButton] { + constraints += [ + NSLayoutConstraint(item: button, + attribute: .width, + relatedBy: .equal, + toItem: button, + attribute: .height, + multiplier: 1.0, + constant: 0.0) + ] + } + + self.addConstraints(constraints) + NSLayoutConstraint.activate(constraints) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopResult.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopResult.swift new file mode 100755 index 0000000..f544e4f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopResult.swift @@ -0,0 +1,106 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import ResearchKit.Private + +public class ORKSwiftStroopResult: ORKResult { + + public var startTime: TimeInterval? + public var endTime: TimeInterval? + public var color: String? + public var text: String? + public var colorSelected: String? + + enum Keys: String { + case startTime + case endTime + case color + case text + case colorSelected + } + + public override init(identifier: String) { + super.init(identifier: identifier) + } + + public override func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(startTime, forKey: Keys.startTime.rawValue) + aCoder.encode(endTime, forKey: Keys.endTime.rawValue) + aCoder.encode(color, forKey: Keys.color.rawValue) + aCoder.encode(text, forKey: Keys.text.rawValue) + aCoder.encode(colorSelected, forKey: Keys.colorSelected.rawValue) + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + startTime = aDecoder.decodeObject(forKey: Keys.startTime.rawValue) as? Double + endTime = aDecoder.decodeObject(forKey: Keys.endTime.rawValue) as? Double + color = aDecoder.decodeObject(forKey: Keys.color.rawValue) as? String + text = aDecoder.decodeObject(forKey: Keys.text.rawValue) as? String + colorSelected = aDecoder.decodeObject(forKey: Keys.colorSelected.rawValue) as? String + } + + public class func supportsSecureCoding() -> Bool { + return true + } + + override public func isEqual(_ object: Any?) -> Bool { + let isParentSame = super.isEqual(object) + + if let castObject = object as? ORKSwiftStroopResult { + return (isParentSame && + (startTime == castObject.startTime) && + (endTime == castObject.endTime) && + (color == castObject.color) && + (text == castObject.text) && + (colorSelected == castObject.colorSelected)) + } + return true + } + + override public func copy(with zone: NSZone? = nil) -> Any { + if let result = super.copy(with: zone) as? ORKSwiftStroopResult { + result.startTime = startTime + result.endTime = endTime + result.color = color + result.text = text + result.colorSelected = colorSelected + return result + } else { + return super.copy(with: zone) + } + } + + public override func description(withNumberOfPaddingSpaces numberOfPaddingSpaces: UInt) -> String { + return "\(descriptionPrefix(withNumberOfPaddingSpaces: numberOfPaddingSpaces)); color: \(color ?? "") text: \(text ?? "") colorSelected: \(colorSelected ?? "") \(descriptionSuffix())" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStep.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStep.swift new file mode 100755 index 0000000..1251938 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStep.swift @@ -0,0 +1,94 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation + +public class ORKSwiftStroopStep: ORKActiveStep { + + public var numberOfAttempts = 0 + private let minimumAttempts = 10 + + enum Key: String { + case numberOfAttempts + } + + public override class func stepViewControllerClass() -> AnyClass { + return ORKSwiftStroopStepViewController.self + } + + public class func supportsSecureCoding() -> Bool { + return true + } + + public override init(identifier: String) { + super.init(identifier: identifier) + + shouldVibrateOnStart = true + shouldShowDefaultTimer = false + shouldContinueOnFinish = true + stepDuration = TimeInterval(NSIntegerMax) + } + + public override func validateParameters() { + super.validateParameters() + assert(numberOfAttempts >= minimumAttempts, "number of attempts should be greater or equal to \(minimumAttempts)") + } + + public override func startsFinished() -> Bool { + return false + } + + public override var allowsBackNavigation: Bool { + return false + } + + public override func copy(with zone: NSZone? = nil) -> Any { + let stroopStep = super.copy(with: zone) + return stroopStep + } + + required init(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + numberOfAttempts = aDecoder.decodeInteger(forKey: Key.numberOfAttempts.rawValue) + } + + public override func encode(with aCoder: NSCoder) { + super.encode(with: aCoder) + aCoder.encode(numberOfAttempts, forKey: Key.numberOfAttempts.rawValue) + } + + public override func isEqual(_ object: Any?) -> Bool { + if let object = object as? ORKSwiftStroopStep { + return numberOfAttempts == object.numberOfAttempts + } + return false + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStepViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStepViewController.swift new file mode 100755 index 0000000..ebd8428 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKSwiftStroopStepViewController.swift @@ -0,0 +1,205 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import ResearchKit.Private + +public class ORKSwiftStroopStepViewController: ORKActiveStepViewController { + + private let stroopContentView = ORKSwiftStroopContentView() + private var colors = [String: UIColor]() + private var differentColorLabels = [String: [UIColor]]() + private var questionNumber = 0 + + private let red = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) + private let green = UIColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0) + private let blue = UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0) + private let yellow = UIColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0) + + private let redString = ORKSwiftLocalizedString("STROOP_COLOR_RED", "") + private let greenString = ORKSwiftLocalizedString("STROOP_COLOR_GREEN", "") + private let blueString = ORKSwiftLocalizedString("STROOP_COLOR_BLUE", "") + private let yellowString = ORKSwiftLocalizedString("STROOP_COLOR_YELLOW", "") + + private var nextQuestionTimer: Timer? + private var results: NSMutableArray? + private var startTime: TimeInterval? + private var endTime: TimeInterval? + + public override init(step: ORKStep?) { + super.init(step: step) + suspendIfInactive = true + } + + internal required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func stroopStep() -> ORKSwiftStroopStep { + return step as! ORKSwiftStroopStep + } + + public override func viewDidLoad() { + super.viewDidLoad() + + results = NSMutableArray() + + colors[redString] = red + colors[blueString] = blue + colors[yellowString] = yellow + colors[greenString] = green + + differentColorLabels[redString] = [blue, green, yellow] + differentColorLabels[blueString] = [red, green, yellow] + differentColorLabels[yellowString] = [red, blue, green] + differentColorLabels[greenString] = [red, blue, yellow] + + activeStepView?.activeCustomView = stroopContentView + activeStepView?.customContentFillsAvailableSpace = true + + stroopContentView.redButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) + stroopContentView.greenButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) + stroopContentView.blueButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) + stroopContentView.yellowButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) + } + + @objc + private func buttonPressed(sender: Any) { + + if stroopContentView.colorLabelText != " " { + setButtonDisabled() + if let button = sender as? ORKBorderedButton { + + if button == stroopContentView.redButton { + createResult(color: (colors as NSDictionary).allKeys(for: stroopContentView.colorLabelColor!).first as? String ?? "", withText: stroopContentView.colorLabelText!, withColorSelected: redString) + } else if button == stroopContentView.greenButton { + createResult(color: (colors as NSDictionary).allKeys(for: stroopContentView.colorLabelColor!).first as? String ?? "", withText: stroopContentView.colorLabelText!, withColorSelected: greenString) + } else if button == stroopContentView.blueButton { + createResult(color: (colors as NSDictionary).allKeys(for: stroopContentView.colorLabelColor!).first as? String ?? "", withText: stroopContentView.colorLabelText!, withColorSelected: blueString) + } else if button == stroopContentView.yellowButton { + createResult(color: (colors as NSDictionary).allKeys(for: stroopContentView.colorLabelColor!).first as? String ?? "", withText: stroopContentView.colorLabelText!, withColorSelected: yellowString) + } + + nextQuestionTimer = Timer.scheduledTimer(timeInterval: 0.5, + target: self, + selector: #selector(startNextQuestionOrFinish), + userInfo: nil, + repeats: false) + } + } + } + + public override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + start() + } + + public override func stepDidFinish() { + super.stepDidFinish() + stroopContentView.finishStep(self) + goForward() + } + + public override var result: ORKStepResult? { + let stepResult = super.result + if results != nil { + stepResult?.results = results?.copy() as? [ORKResult] + } + return stepResult! + } + + public override func start() { + super.start() + startQuestion() + } + + private func createResult(color: String, withText text: String, withColorSelected colorSelected: String) { + let stroopResult = ORKSwiftStroopResult(identifier: (step!.identifier)) + stroopResult.startTime = startTime + stroopResult.endTime = ProcessInfo.processInfo.systemUptime + stroopResult.color = color + stroopResult.text = text + stroopResult.colorSelected = colorSelected + results?.add(stroopResult) + } + + @objc + private func startNextQuestionOrFinish() { + if nextQuestionTimer != nil { + nextQuestionTimer?.invalidate() + nextQuestionTimer = nil + } + questionNumber += 1 + if questionNumber == stroopStep().numberOfAttempts { + finish() + } else { + startQuestion() + } + } + + private func startQuestion() { + let pattern: Int = Int(arc4random()) % 2 + if pattern == 0 { + let index: Int = Int(arc4random()) % differentColorLabels.keys.count + let text = Array(differentColorLabels.keys)[index] + stroopContentView.setColorLabelText(colorLabelText: text) + let color = colors[text]! + stroopContentView.colorLabelColor = color + stroopContentView.setColorLabelColor(colorLabelColor: color) + } else { + let index: Int = Int(arc4random()) % differentColorLabels.keys.count + let text = Array(differentColorLabels.keys)[index] + stroopContentView.setColorLabelText(colorLabelText: text) + let colorArray = differentColorLabels[text]! + let randomColorIndex = Int(arc4random()) % colorArray.count + let color = colorArray[randomColorIndex] + stroopContentView.setColorLabelColor(colorLabelColor: color) + } + + setButtonsEnabled() + startTime = ProcessInfo.processInfo.systemUptime + } + + private func setButtonDisabled() { + + stroopContentView.redButton.isEnabled = false + stroopContentView.greenButton.isEnabled = false + stroopContentView.blueButton.isEnabled = false + stroopContentView.yellowButton.isEnabled = false + } + + private func setButtonsEnabled() { + + stroopContentView.redButton.isEnabled = true + stroopContentView.greenButton.isEnabled = true + stroopContentView.blueButton.isEnabled = true + stroopContentView.yellowButton.isEnabled = true + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.h new file mode 100755 index 0000000..f22417b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKRoundTappingButton; + +@interface ORKTappingContentView : ORKActiveStepCustomView + +- (void)setTapCount:(NSUInteger)tapCount; +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; + +@property (nonatomic, assign) BOOL hasSkipButton; + +@property (nonatomic, strong, readonly) ORKRoundTappingButton *tapButton1; + +@property (nonatomic, strong, readonly) ORKRoundTappingButton *tapButton2; + +@property (nonatomic, assign) NSInteger lastTappedButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.m new file mode 100755 index 0000000..db7ac18 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingContentView.m @@ -0,0 +1,271 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTappingContentView.h" + +#import "ORKActiveStepTimer.h" +#import "ORKRoundTappingButton.h" +#import "ORKSubheadlineLabel.h" +#import "ORKTapCountLabel.h" + +#import "ORKResult.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +// #define LAYOUT_DEBUG 1 + +static const CGFloat ProgressViewTopPadding = 10.0; +static const CGFloat TapCaptionLabelTopPadding = 20.0; +static const CGFloat TapCountLabelTopPadding = 10.0; + +@interface ORKTappingContentView () + +@property (nonatomic, strong) ORKSubheadlineLabel *tapCaptionLabel; +@property (nonatomic, strong) ORKTapCountLabel *tapCountLabel; +@property (nonatomic, strong) UIProgressView *progressView; + +@end + + +@implementation ORKTappingContentView { + UIView *_buttonContainer; + NSNumberFormatter *_formatter; + NSLayoutConstraint *_topToProgressViewConstraint; + NSLayoutConstraint *_topToCaptionLabelConstraint; + NSLayoutConstraint *_captionLabelToTapCountLabelConstraint; + NSLayoutConstraint *_tapButtonToBottomConstraint; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _tapCaptionLabel = [ORKSubheadlineLabel new]; + _tapCaptionLabel.textAlignment = NSTextAlignmentCenter; + _tapCaptionLabel.translatesAutoresizingMaskIntoConstraints = NO; + _tapCountLabel = [ORKTapCountLabel new]; + _tapCountLabel.textAlignment = NSTextAlignmentCenter; + _tapCountLabel.translatesAutoresizingMaskIntoConstraints = NO; + _buttonContainer = [UIView new]; + _buttonContainer.translatesAutoresizingMaskIntoConstraints = NO; + + _progressView = [UIProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + _progressView.progressTintColor = [self tintColor]; + [_progressView setIsAccessibilityElement:YES]; + [_progressView setAlpha:0]; + + _tapButton1 = [[ORKRoundTappingButton alloc] init]; + _tapButton1.translatesAutoresizingMaskIntoConstraints = NO; + [_tapButton1 setTitle:ORKLocalizedString(@"TAP_BUTTON_TITLE", nil) forState:UIControlStateNormal]; + _tapButton1.accessibilityLabel = ORKLocalizedString(@"AX_TAP_BUTTON_1_LABEL", nil); + _tapButton1.accessibilityHint = ORKLocalizedString(@"AX_TAP_BUTTON_HINT", nil); + + _tapButton2 = [[ORKRoundTappingButton alloc] init]; + _tapButton2.translatesAutoresizingMaskIntoConstraints = NO; + [_tapButton2 setTitle:ORKLocalizedString(@"TAP_BUTTON_TITLE", nil) forState:UIControlStateNormal]; + _tapButton2.accessibilityLabel = ORKLocalizedString(@"AX_TAP_BUTTON_2_LABEL", nil); + _tapButton2.accessibilityHint = ORKLocalizedString(@"AX_TAP_BUTTON_HINT", nil); + + _lastTappedButton = -1; + + [self addSubview:_tapCaptionLabel]; + [self addSubview:_tapCountLabel]; + [self addSubview:_progressView]; + [self addSubview:_buttonContainer]; + + [_buttonContainer addSubview:_tapButton1]; + [_buttonContainer addSubview:_tapButton2]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + _tapCaptionLabel.text = ORKLocalizedString(@"TOTAL_TAPS_LABEL", nil); + [self setTapCount:0]; + + [self setUpConstraints]; + + _tapCountLabel.accessibilityTraits |= UIAccessibilityTraitUpdatesFrequently; + +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.5]; + self.tapCaptionLabel.backgroundColor = [UIColor orangeColor]; + self.tapCountLabel.backgroundColor = [UIColor greenColor]; + _buttonContainer.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.25]; +#endif + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + _progressView.progressTintColor = [self tintColor]; +} + +- (void)setTapCount:(NSUInteger)tapCount { + if (_formatter == nil) { + _formatter = [NSNumberFormatter new]; + _formatter.locale = [NSLocale currentLocale]; + _formatter.minimumIntegerDigits = 2; + } + _tapCountLabel.text = [_formatter stringFromNumber:@(tapCount)]; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [_progressView setProgress:progress animated:animated]; + + CGFloat previousAlpha = _progressView.alpha; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [_progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; + + if (UIAccessibilityIsVoiceOverRunning() && previousAlpha != _progressView.alpha) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); + } +} + +- (void)resetStep:(ORKActiveStepViewController *)viewController { + [super resetStep:viewController]; + [self setTapCount:0]; + _tapButton1.enabled = YES; + _tapButton2.enabled = YES; +} + +- (void)finishStep:(ORKActiveStepViewController *)viewController { + [super finishStep:viewController]; + _tapButton1.enabled = NO; + _tapButton2.enabled = NO; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_buttonContainer, _tapCaptionLabel, _tapCountLabel, _progressView, _tapButton1, _tapButton2); + _topToProgressViewConstraint = [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:ProgressViewTopPadding]; + [constraints addObject:_topToProgressViewConstraint]; + + _topToCaptionLabelConstraint = [NSLayoutConstraint constraintWithItem:_tapCaptionLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_progressView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:TapCaptionLabelTopPadding]; + [constraints addObject:_topToCaptionLabelConstraint]; + + _captionLabelToTapCountLabelConstraint = [NSLayoutConstraint constraintWithItem:_tapCountLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_tapCaptionLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:TapCountLabelTopPadding]; + [constraints addObject:_captionLabelToTapCountLabelConstraint]; + + _tapButtonToBottomConstraint = [NSLayoutConstraint constraintWithItem:_buttonContainer + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + [constraints addObject:_tapButtonToBottomConstraint]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_tapCountLabel]-(>=10)-[_buttonContainer]" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + NSLayoutConstraint *progressViewWidthConstraint = [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:0.8 + constant:0.0]; + progressViewWidthConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:progressViewWidthConstraint]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_tapCaptionLabel]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_tapCountLabel]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_tapButton1]-(==10)-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_tapButton2]-(==10)-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_tapButton1]-(>=24)-[_tapButton2(==_tapButton1)]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_tapButton1 + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_tapButton2 + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.h new file mode 100755 index 0000000..21f6d7b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.h @@ -0,0 +1,141 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Values that identify the button that was tapped in a tapping sample. + */ +typedef NS_ENUM(NSInteger, ORKTappingButtonIdentifier) { + + /// The touch landed outside of the two buttons. + ORKTappingButtonIdentifierNone, + + /// The touch landed in the left button. + ORKTappingButtonIdentifierLeft, + + /// The touch landed in the right button. + ORKTappingButtonIdentifierRight +} ORK_ENUM_AVAILABLE; + + +/** + The `ORKTappingSample` class represents a single tap on a button. + + The tapping sample object records the location of the tap, the + button that was tapped, and the time at which the event occurred. A tapping sample is + included in an `ORKTappingIntervalResult` object, and is recorded by the + step view controller for the corresponding task when a tap is + recognized. + + A tapping sample is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize the sample for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTappingSample : NSObject + +/** + A relative timestamp indicating the time of the tap event. + + The timestamp is relative to the value of `startDate` in the `ORKResult` object that includes this + sample. + */ +@property (nonatomic, assign) NSTimeInterval timestamp; + +/** + A duration of the tap event. + + The duration store time interval between touch down and touch release events. + */ +@property (nonatomic, assign) NSTimeInterval duration; + +/** + An enumerated value that indicates which button was tapped, if any. + + If the value of this property is `ORKTappingButtonIdentifierNone`, it indicates that the tap + was near, but not inside, one of the target buttons. + */ +@property (nonatomic, assign) ORKTappingButtonIdentifier buttonIdentifier; + +/** + The location of the tap within the step's view. + + The location coordinates are relative to a rectangle whose size corresponds to + the `stepViewSize` in the enclosing `ORKTappingIntervalResult` object. + */ +@property (nonatomic, assign) CGPoint location; + +@end + + +/** + The `ORKTappingIntervalResult` class records the results of a tapping interval test. + + The tapping interval result object records an array of touch samples (one for each tap) and also the geometry of the + task at the time it was displayed. You can use the information in the object for reference in interpreting the touch + samples. + + A tapping interval sample is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTappingIntervalResult : ORKResult + +/** + An array of collected samples, in which each item is an `ORKTappingSample` object that represents a + tapping event. + */ +@property (nonatomic, copy, nullable) NSArray *samples; + +/** + The size of the bounds of the step view containing the tap targets. + */ +@property (nonatomic) CGSize stepViewSize; + +/** + The frame of the left button, in points, relative to the step view bounds. + */ +@property (nonatomic) CGRect buttonRect1; + +/** + The frame of the right button, in points, relative to the step view bounds. + */ +@property (nonatomic) CGRect buttonRect2; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.m new file mode 100755 index 0000000..c01ccaf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalResult.m @@ -0,0 +1,147 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTappingIntervalResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTappingSample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_DOUBLE(aCoder, duration); + ORK_ENCODE_CGPOINT(aCoder, location); + ORK_ENCODE_ENUM(aCoder, buttonIdentifier); + +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, duration); + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_CGPOINT(aDecoder, location); + ORK_DECODE_ENUM(aDecoder, buttonIdentifier); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.timestamp == castObject.timestamp) && + (self.duration == castObject.duration) && + CGPointEqualToPoint(self.location, castObject.location) && + (self.buttonIdentifier == castObject.buttonIdentifier)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTappingSample *sample = [[[self class] allocWithZone:zone] init]; + sample.timestamp = self.timestamp; + sample.duration = self.duration; + sample.location = self.location; + sample.buttonIdentifier = self.buttonIdentifier; + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; button: %@; timestamp: %.03f; timestamp: %.03f; location: %@>", self.class.description, self, @(self.buttonIdentifier), self.timestamp, self.duration, NSStringFromCGPoint(self.location)]; +} + +@end + + +@implementation ORKTappingIntervalResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, samples); + ORK_ENCODE_CGRECT(aCoder, buttonRect1); + ORK_ENCODE_CGRECT(aCoder, buttonRect2); + ORK_ENCODE_CGSIZE(aCoder, stepViewSize); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, samples, ORKTappingSample); + ORK_DECODE_CGRECT(aDecoder, buttonRect1); + ORK_DECODE_CGRECT(aDecoder, buttonRect2); + ORK_DECODE_CGSIZE(aDecoder, stepViewSize); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.samples, castObject.samples) && + CGRectEqualToRect(self.buttonRect1, castObject.buttonRect1) && + CGRectEqualToRect(self.buttonRect2, castObject.buttonRect2) && + CGSizeEqualToSize(self.stepViewSize, castObject.stepViewSize)); +} + +- (NSUInteger)hash { + return super.hash ^ self.samples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTappingIntervalResult *result = [super copyWithZone:zone]; + result.samples = [self.samples copy]; + result.buttonRect1 = self.buttonRect1; + result.buttonRect2 = self.buttonRect2; + result.stepViewSize = self.stepViewSize; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; samples: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.samples, self.descriptionSuffix]; +} + +@end + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.h new file mode 100755 index 0000000..c0b5a29 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTappingIntervalStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.m new file mode 100755 index 0000000..926ead3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStep.m @@ -0,0 +1,62 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTappingIntervalStep.h" + +#import "ORKTappingIntervalStepViewController.h" + + +@implementation ORKTappingIntervalStep + ++ (Class)stepViewControllerClass { + return [ORKTappingIntervalStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.optional = NO; // default to *not* optional + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSTimeInterval const ORKTwoFingerTappingMinimumDuration = 5.0; + + if ( self.stepDuration < ORKTwoFingerTappingMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKTwoFingerTappingMinimumDuration)] userInfo:nil]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.h new file mode 100755 index 0000000..06133d9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTappingIntervalStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.m new file mode 100755 index 0000000..1cb2131 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTappingIntervalStepViewController.m @@ -0,0 +1,298 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTappingIntervalStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKRoundTappingButton.h" +#import "ORKTappingContentView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKActiveStepView.h" +#import "ORKCollectionResult_Private.h" +#import "ORKTappingIntervalResult.h" +#import "ORKStep.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKTappingIntervalStepViewController () + +@property (nonatomic, strong) NSMutableArray *samples; + +@end + + +@implementation ORKTappingIntervalStepViewController { + ORKTappingContentView *_tappingContentView; + NSTimeInterval _tappingStart; + BOOL _expired; + + CGRect _buttonRect1; + CGRect _buttonRect2; + CGSize _viewSize; + + NSUInteger _hitButtonCount; + + UIGestureRecognizer *_touchDownRecognizer; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _tappingStart = 0; + + _touchDownRecognizer = [UIGestureRecognizer new]; + _touchDownRecognizer.delegate = self; + [self.view addGestureRecognizer:_touchDownRecognizer]; + self.timerUpdateInterval = 0.1; + + _expired = NO; + + _tappingContentView = [[ORKTappingContentView alloc] init]; + self.activeStepView.activeCustomView = _tappingContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + + [_tappingContentView.tapButton1 addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchDown]; + [_tappingContentView.tapButton2 addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchDown]; + [_tappingContentView.tapButton1 addTarget:self action:@selector(buttonReleased:forEvent:) forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)]; + [_tappingContentView.tapButton2 addTarget:self action:@selector(buttonReleased:forEvent:) forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchUpOutside)]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + _buttonRect1 = [self.view convertRect:_tappingContentView.tapButton1.bounds fromView:_tappingContentView.tapButton1]; + _buttonRect2 = [self.view convertRect:_tappingContentView.tapButton2.bounds fromView:_tappingContentView.tapButton2]; + _viewSize = self.view.frame.size; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = sResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKTappingIntervalResult *tappingResult = [[ORKTappingIntervalResult alloc] initWithIdentifier:self.step.identifier]; + tappingResult.startDate = sResult.startDate; + tappingResult.endDate = now; + tappingResult.buttonRect1 = _buttonRect1; + tappingResult.buttonRect2 = _buttonRect2; + tappingResult.stepViewSize = _viewSize; + + tappingResult.samples = _samples; + + [results addObject:tappingResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)receiveTouch:(UITouch *)touch onButton:(ORKTappingButtonIdentifier)buttonIdentifier { + if (_expired || self.samples == nil) { + return; + } + + NSTimeInterval mediaTime = touch.timestamp; + + if (_tappingStart == 0) { + _tappingStart = mediaTime; + } + + CGPoint location = [touch locationInView:self.view]; + + // Add new sample + mediaTime = mediaTime-_tappingStart; + + ORKTappingSample *sample = [[ORKTappingSample alloc] init]; + sample.buttonIdentifier = buttonIdentifier; + sample.location = location; + sample.duration = 0; + sample.timestamp = mediaTime; + + [self.samples addObject:sample]; + + if (buttonIdentifier == ORKTappingButtonIdentifierLeft || buttonIdentifier == ORKTappingButtonIdentifierRight) { + _hitButtonCount++; + } + // Update label + [_tappingContentView setTapCount:_hitButtonCount]; + if (UIAccessibilityIsVoiceOverRunning()) { + static NSNumberFormatter *TapCountAnnouncementFormatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + TapCountAnnouncementFormatter = [[NSNumberFormatter alloc] init]; + }); + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, [TapCountAnnouncementFormatter stringFromNumber:@(_hitButtonCount)]); + } +} + +- (void)releaseTouch:(UITouch *)touch onButton:(ORKTappingButtonIdentifier)buttonIdentifier { + if (self.samples == nil) { + return; + } + NSTimeInterval mediaTime = touch.timestamp; + + // Take last sample for buttonIdentifier, and fill duration + ORKTappingSample *sample = [self lastSampleWithEmptyDurationForButton:buttonIdentifier]; + sample.duration = mediaTime - sample.timestamp - _tappingStart; +} + +- (ORKTappingSample *)lastSampleWithEmptyDurationForButton:(ORKTappingButtonIdentifier)buttonIdentifier{ + NSEnumerator *enumerator = [self.samples reverseObjectEnumerator]; + for (ORKTappingSample *sample in enumerator) { + if (sample.buttonIdentifier == buttonIdentifier && sample.duration == 0) { + return sample; + } + } + return nil; +} + +- (void)fillSampleDurationIfAnyButtonPressed { + /* + * Because we will not able to get UITouch from UIButton, we will use systemUptime. + * Documentation for -[UITouch timestamp] tells: + * The value of this property is the time, in seconds, since system startup the touch either originated or was last changed. + * For a definition of the time-since-boot value, see the description of the systemUptime method of the NSProcessInfo class. + */ + NSTimeInterval mediaTime = [[NSProcessInfo processInfo] systemUptime]; + + ORKTappingSample *tapButton1LastSample = [self lastSampleWithEmptyDurationForButton:ORKTappingButtonIdentifierLeft]; + if (tapButton1LastSample) { + tapButton1LastSample.duration = mediaTime - tapButton1LastSample.timestamp - _tappingStart; + } + + ORKTappingSample *tapButton2LastSample = [self lastSampleWithEmptyDurationForButton:ORKTappingButtonIdentifierRight]; + if (tapButton2LastSample) { + tapButton2LastSample.duration = mediaTime - tapButton2LastSample.timestamp - _tappingStart; + } +} + +- (void)stepDidFinish { + [super stepDidFinish]; + + // If user didn't release touch from button, fill manually duration for last sample + [self fillSampleDurationIfAnyButtonPressed]; + + _expired = YES; + [_tappingContentView finishStep:self]; + [self goForward]; +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + CGFloat progress = finished ? 1 : (timer.runtime / timer.duration); + [_tappingContentView setProgress:progress animated:YES]; + [super countDownTimerFired:timer finished:finished]; +} + +- (void)start { + [super start]; + self.skipButtonItem = nil; + [_tappingContentView setProgress:0.001 animated:NO]; +} + +#pragma mark buttonAction + +- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event { + + if (UIAccessibilityIsVoiceOverRunning()) { + if (!_tappingContentView.isAccessibilityElement) { + // Make the buttons directly tappable with VoiceOver + _tappingContentView.isAccessibilityElement = YES; + _tappingContentView.accessibilityLabel = ORKLocalizedString(@"AX_TAP_BUTTON_DIRECT_TOUCH_AREA", nil); + _tappingContentView.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction; + // Ensure that VoiceOver is aware of the direct touch area so that the first tap gets registered + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _tappingContentView); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // Work around an issue in VoiceOver where announcements don't get spoken if they happen during a button activation + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, ORKLocalizedString(@"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT", nil)); + }); + // Don't actually handle this as a tap yet. + return; + } + } + + if (self.samples == nil) { + // Start timer on first touch event on button + _samples = [NSMutableArray array]; + _hitButtonCount = 0; + [self start]; + } + + NSInteger index = (button == _tappingContentView.tapButton1) ? ORKTappingButtonIdentifierLeft : ORKTappingButtonIdentifierRight; + _tappingContentView.lastTappedButton = index; + + [self receiveTouch:[[event touchesForView:button] anyObject] onButton:index]; +} + +- (IBAction)buttonReleased:(id)button forEvent:(UIEvent *)event { + ORKTappingButtonIdentifier index = (button == _tappingContentView.tapButton1) ? ORKTappingButtonIdentifierLeft : ORKTappingButtonIdentifierRight; + + [self releaseTouch:[[event touchesForView:button] anyObject] onButton:index]; +} + +#pragma mark UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + CGPoint location = [touch locationInView:self.view]; + + BOOL shouldReceive = !(CGRectContainsPoint(_buttonRect1, location) || CGRectContainsPoint(_buttonRect2, location)); + + if (shouldReceive && touch.phase == UITouchPhaseBegan) { + [self receiveTouch:touch onButton:ORKTappingButtonIdentifierNone]; + } + + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.h new file mode 100755 index 0000000..49f8767 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTimedWalkContentView : ORKActiveStepCustomView + +@property (nonatomic, strong, nullable) UIImage *image; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.m new file mode 100755 index 0000000..2b25892 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkContentView.m @@ -0,0 +1,118 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTimedWalkContentView.h" + +#import "ORKActiveStepQuantityView.h" +#import "ORKProgressView.h" +#import "ORKTintedImageView.h" + +#import "ORKSkin.h" + + +@interface ORKTimedWalkContentView () + +@property (nonatomic, strong) ORKProgressView *progressView; +@property (nonatomic, strong) ORKTintedImageView *imageView; +@property (nonatomic, strong) NSLayoutConstraint *imageRatioConstraint; +@property (nonatomic, copy) NSArray *constraints; + +@end + + +@implementation ORKTimedWalkContentView + +- (instancetype)init { + self = [super init]; + if (self) { + _progressView = [ORKProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_progressView]; + + _imageView = [ORKTintedImageView new]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.shouldApplyTint = YES; + _imageView.isAccessibilityElement = NO; + [self addSubview:_imageView]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + [self setNeedsUpdateConstraints]; + } + + return self; +} + +- (void)setImage:(UIImage *)image { + _image = image; + self.imageView.image = image; + + self.imageRatioConstraint.active = NO; + + CGSize size = image.size; + if (size.width > 0 && size.height > 0) { + self.imageRatioConstraint = [NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_imageView + attribute:NSLayoutAttributeWidth + multiplier:size.height/size.width + constant:0]; + self.imageRatioConstraint.active = YES; + } +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:self.constraints]; + + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView, _imageView); + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_progressView]-(>=10)-[_imageView]-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; + [super updateConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.h new file mode 100755 index 0000000..977617c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKTimedWalkResult` class records the results of a Timed Walk test. + + The timed walk result object records the duration to complete the trial with a specific distance + and time limit. + */ +ORK_CLASS_AVAILABLE +@interface ORKTimedWalkResult : ORKResult +/** + The timed walk distance in meters. + */ +@property (nonatomic, assign) double distanceInMeters; + +/** + The time limit to complete the trials. + */ +@property (nonatomic, assign) NSTimeInterval timeLimit; + +/** + The trial duration (that is, the time taken to do the walk). + */ +@property (nonatomic, assign) NSTimeInterval duration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.m new file mode 100755 index 0000000..8fc4c70 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkResult.m @@ -0,0 +1,89 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTimedWalkResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTimedWalkResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, distanceInMeters); + ORK_ENCODE_DOUBLE(aCoder, timeLimit); + ORK_ENCODE_DOUBLE(aCoder, duration); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, distanceInMeters); + ORK_DECODE_DOUBLE(aDecoder, timeLimit); + ORK_DECODE_DOUBLE(aDecoder, duration); + } + return self; + +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.distanceInMeters == castObject.distanceInMeters) && + (self.timeLimit == castObject.timeLimit) && + (self.duration == castObject.duration)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTimedWalkResult *result = [super copyWithZone:zone]; + result.distanceInMeters = self.distanceInMeters; + result.timeLimit = self.timeLimit; + result.duration = self.duration; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; distance: %@; timeLimit: %@; duration: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], @(self.distanceInMeters), @(self.timeLimit), @(self.duration), self.descriptionSuffix]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.h new file mode 100755 index 0000000..3d79e9e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTimedWalkStep : ORKActiveStep + +@property (nonatomic, assign) double distanceInMeters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.m new file mode 100755 index 0000000..e367d16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStep.m @@ -0,0 +1,78 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTimedWalkStep.h" + +#import "ORKTimedWalkStepViewController.h" + + +@implementation ORKTimedWalkStep + ++ (Class)stepViewControllerClass { + return [ORKTimedWalkStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldStartTimerAutomatically = YES; + self.shouldShowDefaultTimer = NO; + self.shouldPlaySoundOnStart = YES; + self.shouldPlaySoundOnFinish = YES; + self.shouldVibrateOnStart = YES; + self.shouldVibrateOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + double const ORKTimedWalkMinimumDistanceInMeters = 1.0; + double const ORKTimedWalkMaximumDistanceInMeters = 10000.0; + + NSTimeInterval const ORKTimedWalkMinimumDuration = 1.0; + + if (self.distanceInMeters < ORKTimedWalkMinimumDistanceInMeters || + self.distanceInMeters > ORKTimedWalkMaximumDistanceInMeters) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"timed walk distance must be greater than or equal to %@ meters and less than or equal to %@ meters.", @(ORKTimedWalkMinimumDistanceInMeters), @(ORKTimedWalkMaximumDistanceInMeters)] userInfo:nil]; + } + + if (self.stepDuration < ORKTimedWalkMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"duration cannot be shorter than %@ seconds.", @(ORKTimedWalkMinimumDuration)] userInfo:nil]; + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.h new file mode 100755 index 0000000..9c2e27d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTimedWalkStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.m new file mode 100755 index 0000000..1625056 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTimedWalkStepViewController.m @@ -0,0 +1,121 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTimedWalkStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKTimedWalkContentView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult.h" +#import "ORKTimedWalkResult.h" +#import "ORKTimedWalkStep.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKTimedWalkStepViewController () + +@property (nonatomic, strong) NSMutableArray *samples; +@property (nonatomic, strong) ORKTimedWalkContentView *timedWalkContentView; +@property (nonatomic, assign) NSTimeInterval trialDuration; + +@end + + +@implementation ORKTimedWalkStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + self.suspendIfInactive = YES; + } + + return self; +} + +- (ORKTimedWalkStep *)timedWalkStep { + return (ORKTimedWalkStep *)self.step; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalDoneButtonItem = nil; + self.continueButtonTitle = ORKLocalizedString(@"BUTTON_NEXT", nil); +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.timedWalkContentView = [ORKTimedWalkContentView new]; + self.activeStepView.activeCustomView = self.timedWalkContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + _navigationFooterView.continueEnabled = YES; + + self.timerUpdateInterval = 0.1f; +} + +- (void)finish { + [super finish]; + + [self goForward]; +} + +- (void)countDownTimerFired:(ORKActiveStepTimer *)timer finished:(BOOL)finished { + self.trialDuration = timer.runtime; + [super countDownTimerFired:timer finished:finished]; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKTimedWalkResult *timedWalkResult = [[ORKTimedWalkResult alloc] initWithIdentifier:self.step.identifier]; + timedWalkResult.distanceInMeters = [self timedWalkStep].distanceInMeters; + timedWalkResult.timeLimit = [self timedWalkStep].stepDuration; + timedWalkResult.duration = self.trialDuration; + + [results addObject:timedWalkResult]; + + sResult.results = [results copy]; + + return sResult; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.h new file mode 100755 index 0000000..60c09cd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKRoundTappingButton; + +@interface ORKToneAudiometryContentView : ORKActiveStepCustomView + +- (void)setProgress:(CGFloat)progress + caption:(NSString *)caption + animated:(BOOL)animated; + +@property (nonatomic, strong, readonly) ORKRoundTappingButton *leftButton; +@property (nonatomic, strong, readonly) ORKRoundTappingButton *rightButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.m new file mode 100755 index 0000000..65da214 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryContentView.m @@ -0,0 +1,261 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKToneAudiometryContentView.h" + +#import "ORKRoundTappingButton.h" +#import "ORKUnitLabel.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const CGFloat TopToProgressViewMinPadding = 10.0; +static const CGFloat ProgressViewToCaptionMaxPadding = 20.0; +static const CGFloat ButtonToLabelPaddingStandard = 5.0; +static const CGFloat CaptionLabelToButtonMinPadding = 5.0; + +@interface ORKToneAudiometryContentView () + +@property (nonatomic, strong) ORKUnitLabel *captionLabel; +@property (nonatomic, strong) UIProgressView *progressView; + +@end + + +@implementation ORKToneAudiometryContentView { + NSLayoutConstraint *_topToProgressViewConstraint; + NSLayoutConstraint *_topToCaptionLabelConstraint; + NSLayoutConstraint *_leftButtonToBottomConstraint; + NSLayoutConstraint *_rightButtonToBottomConstraint; + UILabel *_leftLabel; + UILabel *_rightLabel; +} + +- (instancetype)init { + self = [super init]; + if (self) { + + _captionLabel = [ORKUnitLabel new]; + _captionLabel.textAlignment = NSTextAlignmentCenter; + _captionLabel.translatesAutoresizingMaskIntoConstraints = NO; + + _progressView = [UIProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + _progressView.progressTintColor = [self tintColor]; + [_progressView setAlpha:0]; + + _leftButton = [[ORKRoundTappingButton alloc] init]; + _leftButton.translatesAutoresizingMaskIntoConstraints = NO; + [_leftButton setTitle:ORKLocalizedString(@"TAP_BUTTON_TITLE", nil) forState:UIControlStateNormal]; + + _rightButton = [[ORKRoundTappingButton alloc] init]; + _rightButton.translatesAutoresizingMaskIntoConstraints = NO; + [_rightButton setTitle:ORKLocalizedString(@"TAP_BUTTON_TITLE", nil) forState: UIControlStateNormal]; + + _leftLabel = [ORKUnitLabel new]; + _rightLabel = [ORKUnitLabel new]; + + _leftLabel.text = ORKLocalizedString(@"TONE_AUDIOMETRY_LABEL_LEFT_EAR", nil); + _rightLabel.text = ORKLocalizedString(@"TONE_AUDIOMETRY_LABEL_RIGHT_EAR", nil); + + _leftLabel.textColor = [UIColor lightGrayColor]; + _rightLabel.textColor = [UIColor lightGrayColor]; + + _leftLabel.translatesAutoresizingMaskIntoConstraints = NO; + _rightLabel.translatesAutoresizingMaskIntoConstraints = NO; + + _leftButton.accessibilityLabel = ORKLocalizedString(@"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL", nil); + _leftButton.accessibilityHint = ORKLocalizedString(@"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT", nil); + _rightButton.accessibilityLabel = ORKLocalizedString(@"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL", nil); + _rightButton.accessibilityHint = ORKLocalizedString(@"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT", nil); + // The labels will be included in the button accessibility label, so we should not expose them additionally here. + _leftLabel.isAccessibilityElement = NO; + _rightLabel.isAccessibilityElement = NO; + + [self addSubview:_captionLabel]; + [self addSubview:_progressView]; + [self addSubview:_leftButton]; + [self addSubview:_rightButton]; + [self addSubview:_leftLabel]; + [self addSubview:_rightLabel]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + _captionLabel.text = nil; + [_captionLabel setHidden:YES]; + + [self setUpConstraints]; + } + + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.progressView.progressTintColor = [self tintColor]; +} + +- (void)setProgress:(CGFloat)progress + caption:(NSString *)caption + animated:(BOOL)animated { + self.captionLabel.text = caption; + + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; +} + +- (void)finishStep:(ORKActiveStepViewController *)viewController { + [super finishStep:viewController]; + self.leftButton.enabled = NO; + self.rightButton.enabled = NO; +} + +- (void)setUpConstraints { + NSArray *constraints = @[ + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:TopToProgressViewMinPadding], + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_captionLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_progressView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:ProgressViewToCaptionMaxPadding], + [NSLayoutConstraint constraintWithItem:_captionLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_leftButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:0.5 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_rightButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.5 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_leftLabel + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_rightLabel + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_leftLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_leftButton + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_rightLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_rightButton + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_leftButton + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_leftLabel + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:-ButtonToLabelPaddingStandard], + [NSLayoutConstraint constraintWithItem:_rightButton + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_rightLabel + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:-ButtonToLabelPaddingStandard], + + [NSLayoutConstraint constraintWithItem:_leftButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_captionLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:CaptionLabelToButtonMinPadding], + [NSLayoutConstraint constraintWithItem:_rightButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_captionLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:CaptionLabelToButtonMinPadding], + ]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.h new file mode 100755 index 0000000..d3adb19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.h @@ -0,0 +1,106 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKToneAudiometrySample; + +/** + The `ORKToneAudiometryResult` class records the results of a tone audiometry test. + + The audiometry samples are generated by the framework when the task completes. + It may be appropriate to serialize them for transmission to a server, + or to immediately perform analysis on them. + */ +ORK_CLASS_AVAILABLE +@interface ORKToneAudiometryResult : ORKResult + +/** + The system wide output volume set by the user during the audiometry test. + + A value in the range `0.0` to `1.0`, with `0.0` representing the minimum volume + and `1.0` representing the maximum volume. + */ +@property (nonatomic, copy, nullable) NSNumber *outputVolume; + +/** + An array of collected samples, in which each item is an `ORKToneAudiometrySample` + object that represents an audiometry sample. + */ +@property (nonatomic, copy, nullable) NSArray *samples; + +@end + + +/** + The `ORKToneAudiometrySample` class represents an audio amplitude associated + with a frequency and a channel. + + The sample object records the amplitude, the frequency, and the channel for the audio + tone being played. A tone audiometry sample is included in an `ORKToneAudiometryResult` + object, and is recorded by the step view controller for the corresponding task + when a tap is recognized for a given tone. + + A tone audiometry sample is typically generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize the sample for + transmission to a server or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKToneAudiometrySample : NSObject + +/** + The frequency value in hertz for the tone associated with the sample. + */ +@property (nonatomic, assign) double frequency; + +/** + The channel, either left or right, for the tone associated with the sample. + */ +@property (nonatomic, assign) ORKAudioChannel channel; + +/** + The channel selected by the user. + */ +@property (nonatomic, assign) ORKAudioChannel channelSelected; + +/** + The audio signal amplitude. + + The minimum audio sample amplitude needed for the participant to recognize the sound (a double value between 0 and 1). + */ +@property (nonatomic, assign) double amplitude; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.m new file mode 100755 index 0000000..23d77ae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryResult.m @@ -0,0 +1,136 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKToneAudiometryResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKToneAudiometryResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, outputVolume); + ORK_ENCODE_OBJ(aCoder, samples); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, outputVolume); + ORK_DECODE_OBJ_ARRAY(aDecoder, samples, ORKToneAudiometrySample); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.outputVolume, castObject.outputVolume) && + ORKEqualObjects(self.samples, castObject.samples)) ; +} + +- (NSUInteger)hash { + return super.hash ^ self.samples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKToneAudiometryResult *result = [super copyWithZone:zone]; + result.outputVolume = [self.outputVolume copy]; + result.samples = [self.samples copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; outputvolume: %@; samples: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.outputVolume, self.samples, self.descriptionSuffix]; +} + +@end + + +@implementation ORKToneAudiometrySample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, frequency); + ORK_ENCODE_ENUM(aCoder, channel); + ORK_ENCODE_ENUM(aCoder, channelSelected); + ORK_ENCODE_DOUBLE(aCoder, amplitude); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, frequency); + ORK_DECODE_ENUM(aDecoder, channel); + ORK_DECODE_ENUM(aDecoder, channelSelected); + ORK_DECODE_DOUBLE(aDecoder, amplitude); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.channel == castObject.channel) && + (self.channelSelected == castObject.channelSelected) && + (ABS(self.frequency - castObject.frequency) < DBL_EPSILON) && + (ABS(self.amplitude - castObject.amplitude) < DBL_EPSILON)) ; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKToneAudiometrySample *sample = [[[self class] allocWithZone:zone] init]; + sample.frequency = self.frequency; + sample.channel = self.channel; + sample.channelSelected = self.channelSelected; + sample.amplitude = self.amplitude; + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; frequency: %.1lf; channel %@; channelSelected %@; amplitude: %.4lf>", self.class.description, self, self.frequency, @(self.channel), @(self.channelSelected), self.amplitude]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.h new file mode 100755 index 0000000..1ebd771 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKToneAudiometryStep : ORKActiveStep + +@property (nonatomic, assign) NSTimeInterval toneDuration; + +@property (nonatomic, assign) BOOL practiceStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.m new file mode 100755 index 0000000..ba23343 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStep.m @@ -0,0 +1,94 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKToneAudiometryStep.h" + +#import "ORKToneAudiometryStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKToneAudiometryStep + ++ (Class)stepViewControllerClass { + return [ORKToneAudiometryStepViewController class]; +} + +- (void)validateParameters { + [super validateParameters]; + + NSTimeInterval const ORKToneAudiometryTaskToneMinimumDuration = 5.0; + + if (self.toneDuration < ORKToneAudiometryTaskToneMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"tone duration cannot be shorter than %@ seconds.", @(ORKToneAudiometryTaskToneMinimumDuration)] userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKToneAudiometryStep *step = [super copyWithZone:zone]; + step.toneDuration = self.toneDuration; + step.practiceStep = self.practiceStep; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, toneDuration); + ORK_DECODE_BOOL(aDecoder, practiceStep); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, toneDuration); + ORK_ENCODE_BOOL(aCoder, practiceStep); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && (self.toneDuration == castObject.toneDuration) + && (self.practiceStep == castObject.practiceStep)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.h new file mode 100755 index 0000000..058373a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKToneAudiometryStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.m new file mode 100755 index 0000000..6dafce7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKToneAudiometryStepViewController.m @@ -0,0 +1,270 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKToneAudiometryStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKAudioGenerator.h" +#import "ORKRoundTappingButton.h" +#import "ORKToneAudiometryContentView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKToneAudiometryResult.h" +#import "ORKToneAudiometryStep.h" +#import "ORKStepContainerView_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import + + +@interface ORKToneAudiometryStepViewController () + +@property (nonatomic, strong) ORKToneAudiometryContentView *toneAudiometryContentView; +@property (nonatomic, strong) ORKAudioGenerator *audioGenerator; +@property (nonatomic, assign) BOOL expired; + +@property (nonatomic) NSArray *listOfFrequencies; +@property (nonatomic) NSMutableArray *frequencies; +@property (nonatomic, assign) NSUInteger currentTestIndex; +@property (nonatomic, strong) NSMutableArray *samples; + +- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event; +@property (nonatomic) ORKAudioChannel currentTestChannel; +- (ORKToneAudiometryStep *)toneAudiometryStep; + +@end + + +@implementation ORKToneAudiometryStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + self.suspendIfInactive = YES; + } + + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.expired = NO; + self.listOfFrequencies = @[ @8000, @4000, @1000, @500, @250 ]; + + [self generateFrequencyCombination]; + self.toneAudiometryContentView = [[ORKToneAudiometryContentView alloc] init]; + self.activeStepView.activeCustomView = self.toneAudiometryContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + + [self.toneAudiometryContentView.leftButton addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchDown]; + [self.toneAudiometryContentView.rightButton addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchDown]; + self.currentTestIndex = 0; + self.audioGenerator = [ORKAudioGenerator new]; + + if (UIAccessibilityIsVoiceOverRunning() && !self.toneAudiometryStep.practiceStep) { + // Make it possible to tap the buttons as quickly as possible. + self.toneAudiometryContentView.isAccessibilityElement = YES; + self.toneAudiometryContentView.accessibilityLabel = ORKLocalizedString(@"AX_TAP_BUTTON_DIRECT_TOUCH_AREA", nil); + self.toneAudiometryContentView.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction; + } +} + +- (void)generateFrequencyCombination { + int numberOfChannels = 2; + self.frequencies = [[NSMutableArray alloc] init]; + for (int i = 0; i<[self.listOfFrequencies count]; i++) { + for (int j = 0; j < numberOfChannels; j++) { + [self.frequencies addObject:@[self.listOfFrequencies[i], [NSNumber numberWithInt:j]]]; + } + } + for (int k = 0; k<[self.frequencies count]; k++) { + [self.frequencies exchangeObjectAtIndex:(arc4random() % [self.frequencies count]) withObjectAtIndex:(arc4random() % [self.frequencies count])]; + } +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + [self start]; + + if (UIAccessibilityIsVoiceOverRunning() && !self.toneAudiometryStep.practiceStep) { + // Put focus on the buttons immediately so that the first tap gets registered instead of just moving focus + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self.toneAudiometryContentView); + } +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self.audioGenerator stop]; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = sResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKToneAudiometryResult *toneResult = [[ORKToneAudiometryResult alloc] initWithIdentifier:self.step.identifier]; + toneResult.startDate = sResult.startDate; + toneResult.endDate = now; + toneResult.samples = [self.samples copy]; + toneResult.outputVolume = @([AVAudioSession sharedInstance].outputVolume); + + [results addObject:toneResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)stepDidFinish { + [super stepDidFinish]; + + self.expired = YES; + [self.toneAudiometryContentView finishStep:self]; + [self goForward]; +} + +- (void)start { + [super start]; + if (self.toneAudiometryStep.practiceStep) { + [self.audioGenerator playSoundAtFrequency:1000.0]; + } else { + [self startCurrentTest]; + } +} + +- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event { + if (self.toneAudiometryStep.practiceStep) { + [self finish]; + } + if (self.samples == nil) { + _samples = [NSMutableArray array]; + } + + ORKToneAudiometrySample *sample = [ORKToneAudiometrySample new]; + NSUInteger frequencyIndex = self.currentTestIndex; + NSNumber *frequency = self.frequencies[frequencyIndex][0]; + sample.frequency = [frequency doubleValue]; + sample.channel = self.currentTestChannel; + sample.channelSelected = (button == self.toneAudiometryContentView.leftButton) ? ORKAudioChannelLeft : ORKAudioChannelRight; + sample.amplitude = self.audioGenerator.volumeAmplitude; + + [self.samples addObject:sample]; + + [self.audioGenerator stop]; + + [self startNextTestOrFinish]; +} + +- (void)testExpired { + if (self.samples == nil) { + _samples = [NSMutableArray array]; + } + + ORKToneAudiometrySample *sample = [ORKToneAudiometrySample new]; + NSUInteger frequencyIndex = self.currentTestIndex; + NSNumber *frequency = self.frequencies[frequencyIndex][0]; + sample.frequency = [frequency doubleValue]; + sample.channel = self.currentTestChannel; + sample.channelSelected = -1; + sample.amplitude = self.audioGenerator.volumeAmplitude; + + [self.samples addObject:sample]; + [self.audioGenerator stop]; + + [self startNextTestOrFinish]; +} + +- (void)startNextTestOrFinish { + self.currentTestIndex ++; + if (self.currentTestIndex == (self.frequencies.count)) { + [self finish]; + } else { + [self startCurrentTest]; + } +} + +- (ORKToneAudiometryStep *)toneAudiometryStep { + return (ORKToneAudiometryStep *)self.step; +} + +- (void)startCurrentTest { + const NSTimeInterval SoundDuration = self.toneAudiometryStep.toneDuration; + + NSUInteger testIndex = self.currentTestIndex; + NSUInteger frequencyIndex = testIndex; + NSAssert(frequencyIndex < self.frequencies.count, nil); + + NSNumber *frequency = self.frequencies[frequencyIndex][0]; + + self.currentTestChannel = ([self.frequencies[frequencyIndex][1] intValue] == 0) ? ORKAudioChannelLeft : ORKAudioChannelRight; + + ORKAudioChannel channel = self.currentTestChannel; + + CGFloat progress = 0.001 + (CGFloat)testIndex / self.frequencies.count; + [self.toneAudiometryContentView setProgress:progress + caption:(channel == ORKAudioChannelLeft) ? [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_LEFT", nil), ORKLocalizedStringFromNumber(frequency)] : [NSString stringWithFormat:ORKLocalizedString(@"TONE_LABEL_%@_RIGHT", nil), ORKLocalizedStringFromNumber(frequency)] + animated:YES]; + + [self.audioGenerator playSoundAtFrequency:frequency.doubleValue + onChannel:channel + fadeInDuration:SoundDuration]; + + ORKWeakTypeOf(self)weakSelf = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(SoundDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + + if (strongSelf.currentTestIndex == testIndex) { + [strongSelf testExpired]; + } + }); +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.h new file mode 100755 index 0000000..4c8847d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, ORKTouchAbilityArrowViewStyle) { + ORKTouchAbilityArrowViewStyleFill, + ORKTouchAbilityArrowViewStyleStroke +}; + +@interface ORKTouchAbilityArrowView : UIView + +@property (nonatomic, assign) ORKTouchAbilityArrowViewStyle style; + +- (instancetype)initWithFrame:(CGRect)frame style:(ORKTouchAbilityArrowViewStyle)style; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.m new file mode 100755 index 0000000..a71c262 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityArrowView.m @@ -0,0 +1,122 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityArrowView.h" + +@implementation ORKTouchAbilityArrowView + +- (CGSize)intrinsicContentSize { + return CGSizeMake(300.0, 300.0); +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.style = ORKTouchAbilityArrowViewStyleFill; + self.backgroundColor = [UIColor clearColor]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame style:(ORKTouchAbilityArrowViewStyle)style { + if (self = [super initWithFrame:frame]) { + self.style = style; + self.backgroundColor = [UIColor clearColor]; + } + return self; +} + +- (void)setStyle:(ORKTouchAbilityArrowViewStyle)style { + _style = style; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + [super drawRect:rect]; + + // Background color + + [self.backgroundColor setFill]; + [[UIBezierPath bezierPathWithRect:rect] fill]; + + + // Arrow dimensions + + CGFloat tailWidth = CGRectGetHeight(self.bounds) / 4; + CGFloat headWidth = CGRectGetHeight(self.bounds) / 2; + CGFloat headLength = CGRectGetWidth(self.bounds) / 3; + + CGPoint start = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMaxY(self.bounds)); + CGPoint end = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMinY(self.bounds)); + + CGFloat length = hypot(end.x - start.x, end.y -start.y); + CGFloat tailLength = length - headLength; + + // Path points + + CGPoint points[7]; // It's a C array. + points[0] = CGPointMake(0, tailWidth / 2); + points[1] = CGPointMake(tailLength, tailWidth / 2); + points[2] = CGPointMake(tailLength, headWidth / 2); + points[3] = CGPointMake(length, 0); + points[4] = CGPointMake(tailLength, -headWidth / 2); + points[5] = CGPointMake(tailLength, -tailWidth / 2); + points[6] = CGPointMake(0, -tailWidth / 2); + + CGFloat cosine = (end.x - start.x) / length; + CGFloat sine = (end.y - start.y) / length; + + CGAffineTransform transform = { cosine, sine, -sine, cosine, start.x, start.y }; + + CGMutablePathRef path = CGPathCreateMutable(); + CGPathAddLines(path, &transform, points, sizeof points / sizeof *points); + CGPathCloseSubpath(path); + + // Fill the path + + if (self.style == ORKTouchAbilityArrowViewStyleFill) { + [self.tintColor setFill]; + [[UIBezierPath bezierPathWithCGPath:path] fill]; + } else { + UIBezierPath *bPath = [UIBezierPath bezierPathWithCGPath:path]; + + CGFloat dashes[2] = {4.0, 4.0}; + [bPath setLineDash:dashes count:2 phase:0]; + [bPath setLineCapStyle:kCGLineCapButt]; + [bPath setLineWidth:4.0]; + + [UIColor.blackColor setStroke]; + [bPath stroke]; + } + + // Release path ref + CGPathRelease(path); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.h new file mode 100755 index 0000000..df9281a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" +#import "ORKTouchAbilityTouchTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityContentView; + +#pragma mark - ORKTouchAbilityContentViewDelegate + +@protocol ORKTouchAbilityContentViewDelegate + +@optional +- (void)touchAbilityContentViewDidBeginNewTrack:(ORKTouchAbilityContentView *)contentView; +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView; + +@end + +@class ORKTouchAbilityTrial; +@class ORKTouchAbilityTrack; +@class ORKTouchAbilityGestureRecoginzerEvent; + +#pragma mark - ORKTouchAbilityCustomView + +@interface ORKTouchAbilityContentView : ORKActiveStepCustomView + +@property (nonatomic, readonly) UIView *contentView; + +@property (nonatomic, readonly) ORKTouchAbilityTrial *trial; +@property (nonatomic, readonly) NSArray *tracks; +@property (nonatomic, readonly) NSArray *gestureRecognizerEvents; + +@property (nonatomic, weak) id _Nullable delegate; + +- (void)startTrial; +- (void)endTrial; + +- (void)resetTracks; +- (void)reloadData; + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; +- (void)setContentViewHidden:(BOOL)hidden animated:(BOOL)animated; +- (void)setContentViewHidden:(BOOL)hidden animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion; + ++ (Class)trialClass; + +- (void)touchTrackerDidBeginNewTrack:(ORKTouchAbilityTouchTracker *)touchTracker; +- (void)touchTrackerDidCompleteNewTracks:(ORKTouchAbilityTouchTracker *)touchTracker; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.m new file mode 100755 index 0000000..11d3ade --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityContentView.m @@ -0,0 +1,488 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityContentView.h" + +#import "ORKTouchAbilityTrial.h" +#import "ORKTouchAbilityTrial_Internal.h" +#import "ORKTouchAbilityTouchTracker.h" +#import "ORKTouchAbilityGestureRecoginzerEvent.h" + +#import "ORKSkin.h" + +@interface _ORKTouchAbilityContentView : UIView +@end + +@implementation _ORKTouchAbilityContentView +- (CGSize)intrinsicContentSize { + return CGSizeMake(UIViewNoIntrinsicMetric, 10000.0); +} +@end + +@interface ORKTouchAbilityContentView () + +@property (nonatomic, strong) ORKTouchAbilityTouchTracker *touchTracker; +@property (nonatomic, readwrite) NSArray *gestureRecognizerEvents; + +@property (nonatomic, assign) BOOL shouldSendDelegateCallbacks; + +@property (nonatomic, strong) UITapGestureRecognizer *tap; +@property (nonatomic, strong) UILongPressGestureRecognizer *longPress; +@property (nonatomic, strong) UIPanGestureRecognizer *pan; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeUp; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeDown; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeLeft; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeRight; +@property (nonatomic, strong) UIPinchGestureRecognizer *pinch; +@property (nonatomic, strong) UIRotationGestureRecognizer *rotation; + +@property (nonatomic, strong) UIView *contentView; +@property (nonatomic, strong) UIProgressView *progressView; + +@property (nonatomic, copy) NSArray *contentConstraints; + +@property (nonatomic, strong) NSDate *startDate; +@property (nonatomic, strong) NSDate *endDate; + +@end + +@implementation ORKTouchAbilityContentView + + +#pragma mark - Properties + ++ (Class)trialClass { + return [ORKTouchAbilityTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + ORKTouchAbilityTrial *trial = [[[[self class] trialClass] alloc] init]; + trial.startDate = self.startDate; + trial.endDate = self.endDate; + trial.tracks = self.tracks; + trial.gestureRecognizerEvents = self.gestureRecognizerEvents; + return trial; +} + +- (UIView *)contentView { + if (!_contentView) { + _contentView = [[_ORKTouchAbilityContentView alloc] initWithFrame:CGRectZero]; + } + return _contentView; +} + +- (ORKTouchAbilityTouchTracker *)touchTracker { + if (!_touchTracker) { + _touchTracker = [[ORKTouchAbilityTouchTracker alloc] init]; + _touchTracker.delaysTouchesBegan = NO; + _touchTracker.delaysTouchesEnded = NO; + _touchTracker.delegate = self; + } + return _touchTracker; +} + +- (NSArray *)tracks { + return self.touchTracker.tracks; +} + +- (NSArray *)gestureRecognizerEvents { + if (!_gestureRecognizerEvents) { + _gestureRecognizerEvents = [NSArray new]; + } + return _gestureRecognizerEvents; +} + +- (UIProgressView *)progressView { + if (!_progressView) { + _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; + } + return _progressView; +} + + +#pragma mark - Life Cycle + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + + self.translatesAutoresizingMaskIntoConstraints = NO; + self.shouldSendDelegateCallbacks = YES; + + // Views + + [self.contentView setBackgroundColor:UIColor.clearColor]; + + [self.progressView setProgressTintColor:self.tintColor]; + [self.progressView setIsAccessibilityElement:YES]; + [self.progressView setAlpha:0.0]; + [self.progressView setProgress:0.0 animated:NO]; + + self.contentView.translatesAutoresizingMaskIntoConstraints = NO; + self.progressView.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:self.contentView]; + [self addSubview:self.progressView]; + + [self setContentCompressionResistancePriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisVertical]; + + // Gesture recognizers + + [self addGestureRecognizer:self.touchTracker]; + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewTap:)]; + tap.cancelsTouchesInView = NO; + tap.delaysTouchesBegan = NO; + tap.delaysTouchesEnded = NO; + tap.delegate = self; + tap.enabled = NO; + self.tap = tap; + + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewLongPress:)]; + longPress.cancelsTouchesInView = NO; + longPress.delaysTouchesBegan = NO; + longPress.delaysTouchesEnded = NO; + longPress.delegate = self; + longPress.enabled = NO; + self.longPress = longPress; + + UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewPan:)]; + pan.cancelsTouchesInView = NO; + pan.delaysTouchesBegan = NO; + pan.delaysTouchesEnded = NO; + pan.delegate = self; + pan.enabled = NO; + self.pan = pan; + + UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewSwipe:)]; + swipeUp.direction = UISwipeGestureRecognizerDirectionUp; + swipeUp.cancelsTouchesInView = NO; + swipeUp.delaysTouchesBegan = NO; + swipeUp.delaysTouchesEnded = NO; + swipeUp.delegate = self; + swipeUp.enabled = NO; + self.swipeUp = swipeUp; + + UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewSwipe:)]; + swipeDown.direction = UISwipeGestureRecognizerDirectionDown; + swipeDown.cancelsTouchesInView = NO; + swipeDown.delaysTouchesBegan = NO; + swipeDown.delaysTouchesEnded = NO; + swipeDown.delegate = self; + swipeDown.enabled = NO; + self.swipeDown = swipeDown; + + UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewSwipe:)]; + swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft; + swipeLeft.cancelsTouchesInView = NO; + swipeLeft.delaysTouchesBegan = NO; + swipeLeft.delaysTouchesEnded = NO; + swipeLeft.delegate = self; + swipeLeft.enabled = NO; + self.swipeLeft = swipeLeft; + + UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewSwipe:)]; + swipeRight.direction = UISwipeGestureRecognizerDirectionRight; + swipeRight.cancelsTouchesInView = NO; + swipeRight.delaysTouchesBegan = NO; + swipeRight.delaysTouchesEnded = NO; + swipeRight.delegate = self; + swipeRight.enabled = NO; + self.swipeRight = swipeRight; + + UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewPinch:)]; + pinch.cancelsTouchesInView = NO; + pinch.delaysTouchesBegan = NO; + pinch.delaysTouchesEnded = NO; + pinch.delegate = self; + pinch.enabled = NO; + self.pinch = pinch; + + UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleTouchAbilityCustomViewRotation:)]; + rotation.cancelsTouchesInView = NO; + rotation.delaysTouchesBegan = NO; + rotation.delaysTouchesEnded = NO; + rotation.delegate = self; + rotation.enabled = NO; + self.rotation = rotation; + + [self addGestureRecognizer:tap]; + [self addGestureRecognizer:longPress]; + [self addGestureRecognizer:pan]; + [self addGestureRecognizer:swipeUp]; + [self addGestureRecognizer:swipeDown]; + [self addGestureRecognizer:swipeLeft]; + [self addGestureRecognizer:swipeRight]; + [self addGestureRecognizer:pinch]; + [self addGestureRecognizer:rotation]; + + self.startDate = [NSDate distantPast]; + self.endDate = [NSDate distantFuture]; + } + return self; +} + + +#pragma mark - ORKTouchAbilityCustomView + +- (void)startTrial { + [self.touchTracker startTracking]; + self.tap.enabled = YES; + self.longPress.enabled = YES; + self.pan.enabled = YES; + self.swipeUp.enabled = YES; + self.swipeDown.enabled = YES; + self.swipeLeft.enabled = YES; + self.swipeRight.enabled = YES; + self.pinch.enabled = YES; + self.rotation.enabled = YES; + + self.startDate = [NSDate date]; +} + +- (void)endTrial { + [self.touchTracker stopTracking]; + self.tap.enabled = NO; + self.longPress.enabled = NO; + self.pan.enabled = NO; + self.swipeUp.enabled = NO; + self.swipeDown.enabled = NO; + self.swipeLeft.enabled = NO; + self.swipeRight.enabled = NO; + self.pinch.enabled = NO; + self.rotation.enabled = NO; + + self.endDate = [NSDate date]; +} + +- (void)resetTracks { + [self.touchTracker resetTracks]; + self.gestureRecognizerEvents = @[]; +} + +- (BOOL)isTracking { + return self.touchTracker.isTracking; +} + +- (void)reloadData { + self.startDate = [NSDate distantPast]; + self.endDate = [NSDate distantFuture]; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; +} + +- (void)setContentViewHidden:(BOOL)hidden animated:(BOOL)animated { + [self setContentViewHidden:hidden animated:animated completion:nil]; +} + +- (void)setContentViewHidden:(BOOL)hidden animated:(BOOL)animated completion:(void (^)(BOOL))completion { + + self.shouldSendDelegateCallbacks = !hidden; + + NSTimeInterval totalDuration = 1.0; + NSTimeInterval hideDuration = 0.2; + NSTimeInterval remainDuration = totalDuration - hideDuration; + + [UIView animateWithDuration:animated ? hideDuration : 0 delay:0.0 options:0 animations:^{ + [self.contentView setAlpha:hidden ? 0 : 1]; + } completion:^(BOOL finished) { + if (completion) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(remainDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + completion(finished); + }); + } + }]; +} + + +#pragma mark - UIView + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self.progressView setProgressTintColor:self.tintColor]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self updateLayoutMargins]; + + if (self.superview != nil) { + [self setNeedsLayout]; + [self layoutIfNeeded]; + [self reloadData]; + } +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self updateLayoutMargins]; + + if (self.superview != nil) { + [self setNeedsLayout]; + [self layoutIfNeeded]; + [self reloadData]; + } +} + +- (void)updateConstraints { + [super updateConstraints]; + + if (self.contentConstraints != nil) { + [NSLayoutConstraint deactivateConstraints:self.contentConstraints]; + } + + NSDictionary *views = NSDictionaryOfVariableBindings(_contentView, _progressView); + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_contentView]|" + options:0 + metrics:nil + views:views]]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_contentView]|" + options:0 + metrics:nil + views:views]]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_progressView]-|" + options:0 + metrics:nil + views:views]]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_progressView]" + options:0 + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + + self.contentConstraints = constraintsArray; +} + +- (void)updateLayoutMargins { + CGFloat margin = ORKStandardHorizontalMarginForView(self); + self.layoutMargins = (UIEdgeInsets){.left = margin, .right = margin}; +} + +#pragma mark - GestureRecognizer Handlers + +- (void)handleTouchAbilityCustomViewTap:(UITapGestureRecognizer *)sender { + ORKTouchAbilityTapGestureRecoginzerEvent *event = [[ORKTouchAbilityTapGestureRecoginzerEvent alloc] initWithTapGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + +- (void)handleTouchAbilityCustomViewLongPress:(UILongPressGestureRecognizer *)sender { + ORKTouchAbilityLongPressGestureRecoginzerEvent *event = [[ORKTouchAbilityLongPressGestureRecoginzerEvent alloc] initWithLongPressGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + +- (void)handleTouchAbilityCustomViewPan:(UIPanGestureRecognizer *)sender { + ORKTouchAbilityPanGestureRecoginzerEvent *event = [[ORKTouchAbilityPanGestureRecoginzerEvent alloc] initWithPanGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + +- (void)handleTouchAbilityCustomViewSwipe:(UISwipeGestureRecognizer *)sender { + ORKTouchAbilitySwipeGestureRecoginzerEvent *event = [[ORKTouchAbilitySwipeGestureRecoginzerEvent alloc] initWithSwipeGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + +- (void)handleTouchAbilityCustomViewPinch:(UIPinchGestureRecognizer *)sender { + ORKTouchAbilityPinchGestureRecoginzerEvent *event = [[ORKTouchAbilityPinchGestureRecoginzerEvent alloc] initWithPinchGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + +- (void)handleTouchAbilityCustomViewRotation:(UIRotationGestureRecognizer *)sender { + ORKTouchAbilityRotationGestureRecoginzerEvent *event = [[ORKTouchAbilityRotationGestureRecoginzerEvent alloc] initWithRotationGestureRecognizer:sender]; + NSMutableArray *events = [self.gestureRecognizerEvents mutableCopy]; + [events addObject:event]; + self.gestureRecognizerEvents = [events copy]; +} + + +#pragma mark - ORKTouchAbilityTouchTrackerDelegate + +- (void)touchTrackerDidBeginNewTrack:(ORKTouchAbilityTouchTracker *)touchTracker { + + if (!self.isTracking || !self.shouldSendDelegateCallbacks) { + return; + } + + if ([self.delegate respondsToSelector:@selector(touchAbilityContentViewDidBeginNewTrack:)]) { + [self.delegate touchAbilityContentViewDidBeginNewTrack:self]; + } +} + +- (void)touchTrackerDidCompleteNewTracks:(ORKTouchAbilityTouchTracker *)touchTracker { + + if (!self.isTracking || !self.shouldSendDelegateCallbacks) { + return; + } + + if ([self.delegate respondsToSelector:@selector(touchAbilityContentViewDidCompleteNewTracks:)]) { + [self.delegate touchAbilityContentViewDidCompleteNewTracks:self]; + } +} + + +#pragma mark - UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return NO; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return NO; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.h new file mode 100755 index 0000000..265fd0c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.h @@ -0,0 +1,140 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - ORKTouchAbilityGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityGestureRecoginzerEvent : NSObject + +@property (nonatomic, readonly) NSTimeInterval timestamp; +@property (nonatomic, readonly) UIGestureRecognizerState state; +@property (nonatomic, readonly) NSArray *allowedTouchTypes; +@property (nonatomic, readonly) CGPoint locationInWindow; +@property (nonatomic, readonly) NSUInteger numberOfTouches; +@property (nonatomic, readonly) NSDictionary *locationInWindowOfTouchAtIndex; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilityTapGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) NSUInteger numberOfTapsRequired; +@property (nonatomic, readonly) NSUInteger numberOfTouchesRequired; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithTapGestureRecognizer:(UITapGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilityLongPressGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) NSUInteger numberOfTapsRequired; +@property (nonatomic, readonly) NSUInteger numberOfTouchesRequired; +@property (nonatomic, readonly) NSTimeInterval minimumPressDuration; +@property (nonatomic, readonly) CGFloat allowableMovement; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithLongPressGestureRecognizer:(UILongPressGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilityPanGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityPanGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) NSUInteger minimumNumberOfTouches; +@property (nonatomic, readonly) NSUInteger maximumNumberOfTouches; +@property (nonatomic, readonly) CGPoint velocityInWindow; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithPanGestureRecognizer:(UIPanGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilitySwipeGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilitySwipeGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) NSUInteger numberOfTouchesRequired; +@property (nonatomic, readonly) UISwipeGestureRecognizerDirection direction; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithSwipeGestureRecognizer:(UISwipeGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilitySwipeGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityPinchGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) CGFloat scale; +@property (nonatomic, readonly) CGFloat velocity; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithPinchGestureRecognizer:(UIPinchGestureRecognizer *)recognizer; + +@end + + +#pragma mark - ORKTouchAbilityRotationGestureRecoginzerEvent + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityRotationGestureRecoginzerEvent : ORKTouchAbilityGestureRecoginzerEvent + +@property (nonatomic, readonly) CGFloat rotation; +@property (nonatomic, readonly) CGFloat velocity; + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer NS_UNAVAILABLE; +- (instancetype)initWithRotationGestureRecognizer:(UIRotationGestureRecognizer *)recognizer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.m new file mode 100755 index 0000000..da84b97 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityGestureRecoginzerEvent.m @@ -0,0 +1,509 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityGestureRecoginzerEvent.h" +#import "ORKHelpers_Internal.h" + +#pragma mark - ORKTouchAbilityGestureRecoginzerEvent + +@interface ORKTouchAbilityGestureRecoginzerEvent () + +@property (nonatomic, assign) NSTimeInterval timestamp; +@property (nonatomic, assign) UIGestureRecognizerState state; +@property (nonatomic, copy) NSArray *allowedTouchTypes; +@property (nonatomic, assign) CGPoint locationInWindow; +@property (nonatomic, assign) NSUInteger numberOfTouches; +@property (nonatomic, copy) NSDictionary *locationInWindowOfTouchAtIndex; + +@end + +@implementation ORKTouchAbilityGestureRecoginzerEvent + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_ENUM(aCoder, state); + ORK_ENCODE_OBJ(aCoder, allowedTouchTypes); + ORK_ENCODE_CGPOINT(aCoder, locationInWindow); + ORK_ENCODE_INTEGER(aCoder, numberOfTouches); + ORK_ENCODE_OBJ(aCoder, locationInWindowOfTouchAtIndex); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_ENUM(aDecoder, state); + ORK_DECODE_OBJ(aDecoder, allowedTouchTypes); + ORK_DECODE_CGPOINT(aDecoder, locationInWindow); + ORK_DECODE_INTEGER(aDecoder, numberOfTouches); + ORK_DECODE_OBJ(aDecoder, locationInWindowOfTouchAtIndex); + } + return self; +} + +- (instancetype)initWithGestureRecognizer:(UIGestureRecognizer *)recognizer { + self = [super init]; + if (self) { + self.timestamp = [[NSDate date] timeIntervalSince1970]; + self.state = recognizer.state; + self.allowedTouchTypes = recognizer.allowedTouchTypes; + self.locationInWindow = [recognizer locationInView:nil]; + self.numberOfTouches = recognizer.numberOfTouches; + + if (recognizer.numberOfTouches == 0) { + self.locationInWindowOfTouchAtIndex = @{}; + } else { + NSMutableDictionary *dict = @{}.mutableCopy; + for (NSUInteger i = 0; i < recognizer.numberOfTouches; i++) { + CGPoint location = [recognizer locationOfTouch:i inView:nil]; + dict[@(i)] = [NSValue valueWithCGPoint:location]; + } + self.locationInWindowOfTouchAtIndex = [dict copy]; + } + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityGestureRecoginzerEvent *event = [[[self class] allocWithZone:zone] init]; + event.timestamp = self.timestamp; + event.state = self.state; + event.allowedTouchTypes = [self.allowedTouchTypes copy]; + event.locationInWindow = self.locationInWindow; + event.numberOfTouches = self.numberOfTouches; + event.locationInWindowOfTouchAtIndex = [self.locationInWindowOfTouchAtIndex copy]; + return event; +} + +- (BOOL)isEqual:(id)object { + + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.timestamp == castObject.timestamp) && + (self.state == castObject.state) && + ORKEqualObjects(self.allowedTouchTypes, castObject.allowedTouchTypes) && + CGPointEqualToPoint(self.locationInWindow, castObject.locationInWindow) && + self.numberOfTouches == castObject.numberOfTouches && + ORKEqualObjects(self.locationInWindowOfTouchAtIndex, castObject.locationInWindowOfTouchAtIndex)); +} + +- (NSArray *)allowedTouchTypes { + if (!_allowedTouchTypes) { + _allowedTouchTypes = @[]; + } + return _allowedTouchTypes; +} + +- (NSDictionary *)locationInWindowOfTouchAtIndex { + if (!_locationInWindowOfTouchAtIndex) { + _locationInWindowOfTouchAtIndex = @{}; + } + return _locationInWindowOfTouchAtIndex; +} + +- (NSString *)description { + NSString *stateString; + switch (self.state) { + case UIGestureRecognizerStatePossible: stateString = @"possible"; break; + case UIGestureRecognizerStateBegan: stateString = @"began"; break; + case UIGestureRecognizerStateChanged: stateString = @"changed"; break; + case UIGestureRecognizerStateEnded: stateString = @"ended"; break; + case UIGestureRecognizerStateFailed: stateString = @"failed"; break; + case UIGestureRecognizerStateCancelled: stateString = @"cancelled"; break; + } + + return [NSString stringWithFormat:@"<%@: %p; state: %@; numberOfTouches: %@; location: (%@, %@)>", self.class.description, self, stateString, @(self.numberOfTouches), @(self.locationInWindow.x), @(self.locationInWindow.y)]; +} + +@end + + +#pragma mark - ORKTouchAbilityTapGestureRecoginzerEvent + +@interface ORKTouchAbilityTapGestureRecoginzerEvent () + +@property (nonatomic, assign) NSUInteger numberOfTapsRequired; +@property (nonatomic, assign) NSUInteger numberOfTouchesRequired; + +@end + +@implementation ORKTouchAbilityTapGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfTapsRequired); + ORK_ENCODE_INTEGER(aCoder, numberOfTouchesRequired); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfTapsRequired); + ORK_DECODE_INTEGER(aDecoder, numberOfTouchesRequired); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTapGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.numberOfTapsRequired = self.numberOfTapsRequired; + event.numberOfTouchesRequired = self.numberOfTouchesRequired; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.numberOfTapsRequired == castObject.numberOfTapsRequired && + self.numberOfTouchesRequired == castObject.numberOfTouchesRequired); +} + +- (instancetype)initWithTapGestureRecognizer:(UITapGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.numberOfTapsRequired = recognizer.numberOfTapsRequired; + self.numberOfTouchesRequired = recognizer.numberOfTouchesRequired; + } + return self; +} + +@end + + +#pragma mark - ORKTouchAbilityLongPressGestureRecoginzerEvent + +@interface ORKTouchAbilityLongPressGestureRecoginzerEvent () + +@property (nonatomic, assign) NSUInteger numberOfTapsRequired; +@property (nonatomic, assign) NSUInteger numberOfTouchesRequired; +@property (nonatomic, assign) NSTimeInterval minimumPressDuration; +@property (nonatomic, assign) CGFloat allowableMovement; + +@end + +@implementation ORKTouchAbilityLongPressGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfTapsRequired); + ORK_ENCODE_INTEGER(aCoder, numberOfTouchesRequired); + ORK_ENCODE_ENUM(aCoder, minimumPressDuration); + ORK_ENCODE_DOUBLE(aCoder, allowableMovement); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfTapsRequired); + ORK_DECODE_INTEGER(aDecoder, numberOfTouchesRequired); + ORK_DECODE_ENUM(aDecoder, minimumPressDuration); + ORK_DECODE_DOUBLE(aDecoder, allowableMovement); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityLongPressGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.numberOfTapsRequired = self.numberOfTapsRequired; + event.numberOfTouchesRequired = self.numberOfTouchesRequired; + event.minimumPressDuration = self.minimumPressDuration; + event.allowableMovement = self.allowableMovement; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.numberOfTapsRequired == castObject.numberOfTapsRequired && + self.numberOfTouchesRequired == castObject.numberOfTouchesRequired && + self.minimumPressDuration == castObject.minimumPressDuration && + self.allowableMovement == castObject.allowableMovement); +} + + +- (instancetype)initWithLongPressGestureRecognizer:(UILongPressGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.numberOfTapsRequired = recognizer.numberOfTapsRequired; + self.numberOfTouchesRequired = recognizer.numberOfTouchesRequired; + self.minimumPressDuration = recognizer.minimumPressDuration; + self.allowableMovement = recognizer.allowableMovement; + } + return self; +} + +@end + + +#pragma mark - ORKTouchAbilityPanGestureRecoginzerEvent + +@interface ORKTouchAbilityPanGestureRecoginzerEvent () + +@property (nonatomic, assign) NSUInteger minimumNumberOfTouches; +@property (nonatomic, assign) NSUInteger maximumNumberOfTouches; +@property (nonatomic, assign) CGPoint velocityInWindow; + +@end + +@implementation ORKTouchAbilityPanGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, minimumNumberOfTouches); + ORK_ENCODE_INTEGER(aCoder, maximumNumberOfTouches); + ORK_ENCODE_CGPOINT(aCoder, velocityInWindow); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, minimumNumberOfTouches); + ORK_DECODE_INTEGER(aDecoder, maximumNumberOfTouches); + ORK_DECODE_CGPOINT(aDecoder, velocityInWindow); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityPanGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.minimumNumberOfTouches = self.minimumNumberOfTouches; + event.maximumNumberOfTouches = self.maximumNumberOfTouches; + event.velocityInWindow = self.velocityInWindow; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.minimumNumberOfTouches == castObject.minimumNumberOfTouches && + self.maximumNumberOfTouches == castObject.maximumNumberOfTouches && + CGPointEqualToPoint(self.velocityInWindow, castObject.velocityInWindow)); +} + +- (instancetype)initWithPanGestureRecognizer:(UIPanGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.minimumNumberOfTouches = recognizer.minimumNumberOfTouches; + self.maximumNumberOfTouches = recognizer.maximumNumberOfTouches; + self.velocityInWindow = [recognizer velocityInView:nil]; + } + return self; +} + +@end + + +#pragma mark - ORKTouchAbilityPanGestureRecoginzerEvent + +@interface ORKTouchAbilitySwipeGestureRecoginzerEvent () + +@property (nonatomic, assign) NSUInteger numberOfTouchesRequired; +@property (nonatomic, assign) UISwipeGestureRecognizerDirection direction; + +@end + +@implementation ORKTouchAbilitySwipeGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfTouchesRequired); + ORK_ENCODE_ENUM(aCoder, direction); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfTouchesRequired); + ORK_DECODE_ENUM(aDecoder, direction); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilitySwipeGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.numberOfTouchesRequired = self.numberOfTouchesRequired; + event.direction = self.direction; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.numberOfTouchesRequired == castObject.numberOfTouchesRequired && + self.direction == castObject.direction); +} + +- (instancetype)initWithSwipeGestureRecognizer:(UISwipeGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.numberOfTouchesRequired = recognizer.numberOfTouchesRequired; + self.direction = recognizer.direction; + } + return self; +} + +@end + + +#pragma mark - ORKTouchAbilitySwipeGestureRecoginzerEvent + +@interface ORKTouchAbilityPinchGestureRecoginzerEvent () + +@property (nonatomic, assign) CGFloat scale; +@property (nonatomic, assign) CGFloat velocity; + +@end + +@implementation ORKTouchAbilityPinchGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, scale); + ORK_ENCODE_DOUBLE(aCoder, velocity); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, scale); + ORK_DECODE_DOUBLE(aDecoder, velocity); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityPinchGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.scale = self.scale; + event.velocity = self.velocity; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.scale == castObject.scale && + self.velocity == castObject.velocity); +} + +- (instancetype)initWithPinchGestureRecognizer:(UIPinchGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.scale = recognizer.scale; + self.velocity = recognizer.velocity; + } + return self; +} + +@end + + +#pragma mark - ORKTouchAbilityRotationGestureRecoginzerEvent + +@interface ORKTouchAbilityRotationGestureRecoginzerEvent () + +@property (nonatomic, assign) CGFloat rotation; +@property (nonatomic, assign) CGFloat velocity; + +@end + +@implementation ORKTouchAbilityRotationGestureRecoginzerEvent + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, rotation); + ORK_ENCODE_DOUBLE(aCoder, velocity); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, rotation); + ORK_DECODE_DOUBLE(aDecoder, velocity); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityRotationGestureRecoginzerEvent *event = [super copyWithZone:zone]; + event.rotation = self.rotation; + event.velocity = self.velocity; + return event; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.rotation == castObject.rotation && + self.velocity == castObject.velocity); +} + +- (instancetype)initWithRotationGestureRecognizer:(UIRotationGestureRecognizer *)recognizer { + self = [super initWithGestureRecognizer:recognizer]; + if (self) { + self.rotation = recognizer.rotation; + self.velocity = recognizer.velocity; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.h new file mode 100755 index 0000000..acf5d58 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityLongPressContentView; +@protocol ORKTouchAbilityLongPressContentViewDataSource + +@required +- (NSUInteger)numberOfColumnsInLongPressContentView:(ORKTouchAbilityLongPressContentView *)longPressContentView; +- (NSUInteger)numberOfRowsInLongPressContentView:(ORKTouchAbilityLongPressContentView *)longPressContentView; +- (NSUInteger)targetColumnInLongPressContentView:(ORKTouchAbilityLongPressContentView *)longPressContentView; +- (NSUInteger)targetRowInLongPressContentView:(ORKTouchAbilityLongPressContentView *)longPressContentView; + +@optional +- (CGSize)targetSizeInLongPressContentView:(ORKTouchAbilityLongPressContentView *)longPressContentView; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressContentView : ORKTouchAbilityContentView + +@property (nonatomic, readonly) UIView *targetView; +@property (nonatomic, weak) id _Nullable dataSource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.m new file mode 100755 index 0000000..12c1541 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressContentView.m @@ -0,0 +1,214 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityLongPressContentView.h" +#import "ORKTouchAbilityLongPressTrial.h" + +#import "ORKHelpers_Internal.h" + +@interface ORKTouchAbilityLongPressContentView () + +@property (nonatomic, assign) BOOL success; + +@property (nonatomic, assign) NSUInteger numberOfColumns; +@property (nonatomic, assign) NSUInteger numberOfRows; +@property (nonatomic, assign) NSUInteger targetColumn; +@property (nonatomic, assign) NSUInteger targetRow; +@property (nonatomic, assign) CGSize targetSize; + +@property (nonatomic, strong) UIView *targetView; +@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGestureRecognizer; + +@property (nonatomic, copy) NSArray *targetConstraints; + +@end + +@implementation ORKTouchAbilityLongPressContentView + + +#pragma mark - Properties + +- (UIView *)targetView { + if (!_targetView) { + _targetView = [[UIView alloc] initWithFrame:CGRectZero]; + } + return _targetView; +} + +- (UILongPressGestureRecognizer *)longPressGestureRecognizer { + if (!_longPressGestureRecognizer) { + _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGestureRecognizer:)]; + } + return _longPressGestureRecognizer; +} + + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + self.targetView.backgroundColor = self.tintColor; + self.targetView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.targetView]; + + self.longPressGestureRecognizer.enabled = NO; + [self.contentView addGestureRecognizer:self.longPressGestureRecognizer]; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.targetView.backgroundColor = self.tintColor; +} + +- (void)updateConstraints { + [super updateConstraints]; + + if (self.numberOfColumns == 0 || self.numberOfRows == 0 || self.targetView.superview == nil) { + return; + } + + CGFloat width = self.contentView.frame.size.width / self.numberOfColumns; + CGFloat height = self.contentView.frame.size.height / self.numberOfRows; + + CGFloat columnMidX = width * (self.targetColumn + 1.0/2.0); + CGFloat rowMidY = height * (self.targetRow + 1.0/2.0); + + if (self.targetConstraints != nil) { + [NSLayoutConstraint deactivateConstraints:self.targetConstraints]; + self.targetConstraints = nil; + } + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:self.targetSize.width]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:self.targetSize.height]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:columnMidX]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:rowMidY]]; + + self.targetConstraints = constraintsArray; + [NSLayoutConstraint activateConstraints:self.targetConstraints]; +} + + +#pragma mark - ORKTouchAbilityCustomView + ++ (Class)trialClass { + return [ORKTouchAbilityLongPressTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + + ORKTouchAbilityLongPressTrial *trial = (ORKTouchAbilityLongPressTrial *)[super trial]; + trial.targetFrameInWindow = [self.targetView convertRect:self.targetView.bounds toView:nil]; + trial.success = self.success; + + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.longPressGestureRecognizer.enabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.longPressGestureRecognizer.enabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.success = NO; + + self.numberOfColumns = [self.dataSource numberOfColumnsInLongPressContentView:self] ?: 1; + self.numberOfRows = [self.dataSource numberOfRowsInLongPressContentView:self] ?: 1; + self.targetColumn = [self.dataSource targetColumnInLongPressContentView:self] ?: 0; + self.targetRow = [self.dataSource targetRowInLongPressContentView:self] ?: 0; + + NSAssert(self.targetColumn >= 0 && self.targetColumn < self.numberOfColumns, @"Target column out of bounds."); + NSAssert(self.targetRow >= 0 && self.targetRow < self.numberOfRows, @"target row out of bounds."); + + if ([self.dataSource respondsToSelector:@selector(targetSizeInLongPressContentView:)]) { + self.targetSize = [self.dataSource targetSizeInLongPressContentView:self]; + } else { + self.targetSize = CGSizeMake(76, 76); + } + + [self setNeedsUpdateConstraints]; + [self updateConstraintsIfNeeded]; +} + + +#pragma mark - Gesture Recognizer Handler + +- (void)handleLongPressGestureRecognizer:(UILongPressGestureRecognizer *)sender { + + if (sender.state == UIGestureRecognizerStateBegan) { + if (CGRectContainsPoint(self.targetView.bounds, [sender locationInView:self.targetView])) { + self.success = YES; + } else { + self.success = NO; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.h new file mode 100755 index 0000000..16fb776 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityLongPressTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.m new file mode 100755 index 0000000..14f1494 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressResult.m @@ -0,0 +1,80 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityLongPressResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKTouchAbilityTrial.h" + +@implementation ORKTouchAbilityLongPressResult + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityLongPressResult *result = [super copyWithZone:zone]; + result.trials = [self.trials mutableCopy]; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.h new file mode 100755 index 0000000..3232053 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.m new file mode 100755 index 0000000..df66df1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStep.m @@ -0,0 +1,74 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityLongPressStep.h" +#import "ORKTouchAbilityLongPressStepViewController.h" +#import "ORKhelpers_Internal.h" + +@implementation ORKTouchAbilityLongPressStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilityLongPressStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityLongPressStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)isEqual:(id)other { + return other == self || [super isEqual:other]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.h new file mode 100755 index 0000000..1dfc976 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.m new file mode 100755 index 0000000..71f492f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressStepViewController.m @@ -0,0 +1,230 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +#import "ORKTouchAbilityLongPressStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKTouchAbilityLongPressContentView.h" +#import "ORKTouchAbilityLongPressResult.h" +#import "ORKTouchAbilityLongPressTrial.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTouchAbilityLongPressStep.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + + +@interface ORKTouchAbilityLongPressStepViewController () + +// Data +@property (nonatomic, strong) NSMutableArray *targetPointsQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +// UI +@property (nonatomic, strong) ORKTouchAbilityLongPressContentView *longPressView; + +@end + +@implementation ORKTouchAbilityLongPressStepViewController + + +#pragma mark - ORKActiveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilityLongPressResult *lpResult = [[ORKTouchAbilityLongPressResult alloc] initWithIdentifier:self.step.identifier]; + + lpResult.trials = self.trials; + + [results addObject:lpResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.longPressView endTrial]; + [super finish]; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.trials = [NSMutableArray new]; + self.targetPointsQueue = [self targetPointsForTraitCollection:self.traitCollection]; + + self.longPressView = [[ORKTouchAbilityLongPressContentView alloc] init]; + self.longPressView.dataSource = self; + self.longPressView.delegate = self; + + self.activeStepView.activeCustomView = self.longPressView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.longPressView startTrial]; +} + + +#pragma mark - ORKTouchAbilityLongPressStepViewController + +- (NSUInteger)numberOfColumnsForTraitCollection:(UITraitCollection *)traitCollection { + return 3; +} + +- (NSUInteger)numberOfRowsForTraitCollection:(UITraitCollection *)traitCollection { + return 3; +} + +- (NSMutableArray *)targetPointsForTraitCollection:(UITraitCollection *)traitCollection { + + NSUInteger columns = [self numberOfColumnsForTraitCollection:self.traitCollection]; + NSUInteger rows = [self numberOfRowsForTraitCollection:self.traitCollection]; + + NSMutableArray *points = [NSMutableArray new]; + for (NSUInteger i = 0; i < columns; i++) { + for (NSUInteger j = 0; j < rows; j++) { + CGPoint point = CGPointMake(i, j); + [points addObject:[NSValue valueWithCGPoint:point]]; + } + } + + NSUInteger count = [points count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [points exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return points; +} + + +#pragma mark - ORKTouchAbilityTapContentViewDataSource + +- (NSUInteger)numberOfColumnsInLongPressContentView:(ORKTouchAbilityLongPressContentView *)tapContentView { + return [self numberOfColumnsForTraitCollection:self.traitCollection]; +} + +- (NSUInteger)numberOfRowsInLongPressContentView:(ORKTouchAbilityLongPressContentView *)tapContentView { + return [self numberOfRowsForTraitCollection:self.traitCollection]; +} + +- (NSUInteger)targetColumnInLongPressContentView:(ORKTouchAbilityLongPressContentView *)tapContentView { + return [self.targetPointsQueue.lastObject CGPointValue].x; +} + +- (NSUInteger)targetRowInLongPressContentView:(ORKTouchAbilityLongPressContentView *)tapContentView { + return [self.targetPointsQueue.lastObject CGPointValue].y; +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidBeginNewTrack:(ORKTouchAbilityContentView *)contentView { + +} + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + [self.targetPointsQueue removeLastObject]; + + + // Calculate current progress and display using progress view. + + NSUInteger total = [self numberOfColumnsForTraitCollection:self.traitCollection] * [self numberOfRowsForTraitCollection:self.traitCollection]; + NSUInteger done = total - self.targetPointsQueue.count; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [contentView setProgress:progress animated:YES]; + + + // Animate the target view. + + ORKWeakTypeOf(contentView) weakContentView = contentView; + [contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + + ORKStrongTypeOf(contentView) strongContentView = weakContentView; + + // Stop tracking new touch events. + + [strongContentView endTrial]; + + [self.trials addObject:(ORKTouchAbilityLongPressTrial *)strongContentView.trial]; + + // Determind if should continue or finish. + + if (self.targetPointsQueue.count > 0) { + + // Reload and start tracking again. + [strongContentView reloadData]; + [strongContentView setContentViewHidden:NO animated:NO]; + [strongContentView startTrial]; + + } else { + + // Finish step. + [self finish]; + } + + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.h new file mode 100755 index 0000000..1cc8e93 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityLongPressTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) CGRect targetFrameInWindow; +@property (nonatomic, assign) BOOL success; + +- (instancetype)initWithTargetFrameInWindow:(CGRect)targetFrame; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.m new file mode 100755 index 0000000..618e14e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityLongPressTrial.m @@ -0,0 +1,98 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityLongPressTrial.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTouchAbilityLongPressTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_CGRECT(aCoder, targetFrameInWindow); + ORK_ENCODE_BOOL(aCoder, success); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_CGRECT(aDecoder, targetFrameInWindow); + ORK_DECODE_BOOL(aDecoder, success); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityLongPressTrial *trial = [super copyWithZone:zone]; + trial.targetFrameInWindow = self.targetFrameInWindow; + trial.success = self.success; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + CGRectEqualToRect(self.targetFrameInWindow, castObject.targetFrameInWindow) && + self.success == castObject.success); +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.targetFrameInWindow = CGRectZero; + self.success = NO; + } + return self; +} + +- (instancetype)initWithTargetFrameInWindow:(CGRect)targetFrame { + self = [super init]; + if (self) { + self.targetFrameInWindow = targetFrame; + self.success = NO; + } + return self; +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + return [NSString stringWithFormat:@"<%@; target frame: %@; success: %@>", sDescription, [NSValue valueWithCGRect:self.targetFrameInWindow], self.success ? @"true" : @"false"]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.h new file mode 100755 index 0000000..e0a125d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityPinchContentView; +@protocol ORKTouchAbilityPinchContentViewDataSource + +@required +- (CGFloat)targetScaleInPinchContentView:(ORKTouchAbilityPinchContentView *)pinchContentView; + +@end + +@interface ORKTouchAbilityPinchContentView : ORKTouchAbilityContentView + +@property (nonatomic, weak) id _Nullable dataSource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.m new file mode 100755 index 0000000..36a374e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchContentView.m @@ -0,0 +1,264 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityPinchContentView.h" +#import "ORKTouchAbilityPinchGuideView.h" +#import "ORKTouchAbilityPinchTrial.h" + +@interface ORKTouchAbilityPinchContentView () + +@property (nonatomic, assign) CGFloat targetScale; + +@property (nonatomic, strong) UIView *targetView; +@property (nonatomic, strong) UIView *guideView; + +@property (nonatomic, strong) NSLayoutConstraint *guideWidthConstraint; +@property (nonatomic, strong) NSLayoutConstraint *guideHeightConstraint; + +@property (nonatomic, strong) UIPinchGestureRecognizer *pinchGestureRecognizer; + +@property (nonatomic, copy) NSArray *pinchTargetConstraints; + +@end + +@implementation ORKTouchAbilityPinchContentView + +#pragma mark - Properties + +- (UIView *)targetView { + if (!_targetView) { + _targetView = [[UIView alloc] initWithFrame:CGRectZero]; + } + return _targetView; +} + +- (UIView *)guideView { + if (!_guideView) { + _guideView = [[ORKTouchAbilityPinchGuideView alloc] initWithFrame:CGRectZero]; + } + return _guideView; +} + +- (CGFloat)currentScale { + CGAffineTransform t = self.targetView.transform; + + // x scale + // CGFloat xScale = sqrt(t.a * t.a + t.c * t.c); + + // y scale + // CGFloat yScale = sqrt(t.b * t.b + t.d * t.d); + + return sqrt(t.a * t.a + t.c * t.c); +} + +- (UIPinchGestureRecognizer *)pinchGestureRecognizer { + if (!_pinchGestureRecognizer) { + _pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGestureRecognizer:)]; + } + return _pinchGestureRecognizer; +} + + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + + if (self = [super initWithFrame:frame]) { + + self.targetView.backgroundColor = self.tintColor; + self.targetView.translatesAutoresizingMaskIntoConstraints = NO; + self.guideView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.targetView]; + [self.contentView addSubview:self.guideView]; + + [self.contentView addGestureRecognizer:self.pinchGestureRecognizer]; + self.pinchGestureRecognizer.enabled = NO; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.targetView.backgroundColor = self.tintColor; +} + +- (void)updateConstraints { + [super updateConstraints]; + + if (self.pinchTargetConstraints != nil) { + [NSLayoutConstraint deactivateConstraints:self.pinchTargetConstraints]; + } + + CGAffineTransform transform = self.targetView.transform; + self.targetView.transform = CGAffineTransformIdentity; + + BOOL isWidthLessThanHeight = CGRectGetWidth(self.bounds) < CGRectGetHeight(self.bounds); + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:isWidthLessThanHeight ? NSLayoutAttributeWidth : NSLayoutAttributeHeight + multiplier:1.0/3.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self.targetView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + + self.guideWidthConstraint = [NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self.targetView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]; + + self.guideHeightConstraint = [NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self.targetView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]; + + [constraintsArray addObject:self.guideWidthConstraint]; + [constraintsArray addObject:self.guideHeightConstraint]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + self.pinchTargetConstraints = constraintsArray; + + self.targetView.transform = transform; +} + +#pragma mark - ORKTouchAbilityCustomView + ++ (Class)trialClass { + return [ORKTouchAbilityPinchTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + ORKTouchAbilityPinchTrial *trial = (ORKTouchAbilityPinchTrial *)[super trial]; + trial.targetScale = [self targetScale]; + trial.resultScale = [self currentScale]; + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.pinchGestureRecognizer.enabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.pinchGestureRecognizer.enabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.targetView.transform = CGAffineTransformIdentity; + + self.targetScale = [self.dataSource targetScaleInPinchContentView:self] ?: 1.0; + + [NSLayoutConstraint deactivateConstraints:@[self.guideWidthConstraint, self.guideHeightConstraint]]; + + self.guideWidthConstraint = [NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self.targetView + attribute:NSLayoutAttributeWidth + multiplier:self.targetScale + constant:0.0]; + + self.guideHeightConstraint = [NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self.targetView + attribute:NSLayoutAttributeHeight + multiplier:self.targetScale + constant:0.0]; + + [NSLayoutConstraint activateConstraints:@[self.guideWidthConstraint, self.guideHeightConstraint]]; + +} + + +#pragma mark - Gesture Recognizer Handler + +- (void)handlePinchGestureRecognizer:(UIPinchGestureRecognizer *)sender { + + self.targetView.transform = CGAffineTransformScale(self.targetView.transform, sender.scale, sender.scale); + sender.scale = 1.0; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.h new file mode 100755 index 0000000..17b5fb6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityPinchGuideView : UIView + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.m new file mode 100755 index 0000000..543fcd6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchGuideView.m @@ -0,0 +1,84 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityPinchGuideView.h" + +@implementation ORKTouchAbilityPinchGuideView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor clearColor]; + } + return self; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self setNeedsDisplay]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + [super drawRect:rect]; + + UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect]; + + [self.backgroundColor setFill]; + [path fill]; + + CGFloat dashes[2] = {4.0, 4.0}; + [path setLineDash:dashes count:2 phase:0]; + [path setLineCapStyle:kCGLineCapButt]; + [path setLineWidth:4.0]; + + [UIColor.blackColor setStroke]; + [path stroke]; + + + + /* + let path = UIBezierPath(roundedRect: rect, cornerRadius: 0) + path.lineWidth = lineWidth + + let dashes: [CGFloat] = [lineWidth, lineWidth] + path.setLineDash(dashes, count: dashes.count, phase: 0) + path.lineCapStyle = CGLineCap.butt + + lineColor.setStroke() + + path.stroke() + */ +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.h new file mode 100755 index 0000000..f305bed --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityPinchTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityPinchResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.m new file mode 100755 index 0000000..a47eb61 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchResult.m @@ -0,0 +1,72 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#import "ORKTouchAbilityPinchResult.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilityPinchResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_ENCODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityPinchResult *result = [super copyWithZone:zone]; + result.trials = [self.trials mutableCopy]; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.h new file mode 100755 index 0000000..59be055 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityPinchStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.m new file mode 100755 index 0000000..96bfb8d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStep.m @@ -0,0 +1,72 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityPinchStep.h" +#import "ORKTouchAbilityPinchStepViewController.h" + +@implementation ORKTouchAbilityPinchStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilityPinchStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityPinchStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)isEqual:(id)other { + return other == self || [super isEqual:other]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.h new file mode 100755 index 0000000..db8d3c7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityPinchStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.m new file mode 100755 index 0000000..e6f8793 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchStepViewController.m @@ -0,0 +1,186 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityPinchStepViewController.h" + +#import "ORKTouchAbilityPinchContentView.h" +#import "ORKTouchAbilityPinchStep.h" +#import "ORKTouchAbilityPinchResult.h" + +#import "ORKActiveStepView.h" +#import "ORKNavigableOrderedTask.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + +@interface ORKTouchAbilityPinchStepViewController () + +// Data +@property (nonatomic, assign) NSUInteger currentTrialIndex; +@property (nonatomic, strong) NSArray *targetScaleQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +// UI +@property (nonatomic, strong) ORKTouchAbilityPinchContentView *contentView; + +@end + +@implementation ORKTouchAbilityPinchStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilityPinchResult *pinchResult = [[ORKTouchAbilityPinchResult alloc] initWithIdentifier:self.step.identifier]; + + pinchResult.trials = self.trials; + + [results addObject:pinchResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.contentView endTrial]; + [super finish]; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.trials = [NSMutableArray new]; + self.targetScaleQueue = [self targetScales]; + self.currentTrialIndex = 0; + + self.contentView = [[ORKTouchAbilityPinchContentView alloc] init]; + self.contentView.dataSource = self; + self.contentView.delegate = self; + + self.activeStepView.activeCustomView = self.contentView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.contentView startTrial]; +} + +- (NSArray *)targetScales { + + NSMutableArray *array = @[@(1.0/2.0), @(2.0/3.0), @(3.0/2.0), @2.0].mutableCopy; + [array addObjectsFromArray:array]; + + NSUInteger count = [array count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [array exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return [array copy]; +} + + +#pragma mark - ORKTouchAbilityPinchContentViewDataSource + +- (CGFloat)targetScaleInPinchContentView:(ORKTouchAbilityPinchContentView *)pinchContentView { + return [self.targetScaleQueue[self.currentTrialIndex] doubleValue]; +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + // Calculate current progress and display using progress view. + + NSUInteger total = self.targetScaleQueue.count; + NSUInteger done = self.currentTrialIndex + 1; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [contentView setProgress:progress animated:YES]; + + // Animate the target view. + ORKWeakTypeOf(contentView) weakContentView = contentView; + [contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + ORKStrongTypeOf(contentView) strongContentView = weakContentView; + + // Stop tracking new touch events. + + [strongContentView endTrial]; + + [self.trials addObject:(ORKTouchAbilityPinchTrial *)strongContentView.trial]; + + // Determind if should continue or finish. + + self.currentTrialIndex += 1; + if (self.currentTrialIndex < self.targetScaleQueue.count) { + + // Reload and start tracking again. + [strongContentView reloadData]; + [strongContentView setContentViewHidden:NO animated:NO]; + [strongContentView startTrial]; + + } else { + + // Finish step. + [self finish]; + } + + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.h new file mode 100755 index 0000000..c6842bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityPinchTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) CGFloat targetScale; +@property (nonatomic, assign) CGFloat resultScale; + +- (instancetype)initWithTargetScale:(CGFloat)targetScale; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.m new file mode 100755 index 0000000..da82fef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityPinchTrial.m @@ -0,0 +1,93 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityPinchTrial.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilityPinchTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, targetScale); + ORK_ENCODE_DOUBLE(aCoder, resultScale); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_DOUBLE(aDecoder, targetScale); + ORK_DECODE_DOUBLE(aDecoder, resultScale); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityPinchTrial *trial = [super copyWithZone:zone]; + trial.targetScale = self.targetScale; + trial.resultScale = self.resultScale; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.targetScale == castObject.targetScale && + self.resultScale == castObject.resultScale); +} + +- (instancetype)init { + if (self = [super init]) { + self.targetScale = 1.0; + self.resultScale = 1.0; + } + return self; +} + +- (instancetype)initWithTargetScale:(CGFloat)targetScale { + if (self = [super init]) { + self.targetScale = targetScale; + self.resultScale = 1.0; + } + return self; +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + return [NSString stringWithFormat:@"<%@; target scale: %@; result scale: %@>", sDescription, @(self.targetScale), @(self.resultScale)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.h new file mode 100755 index 0000000..d78ec65 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityRotationContentView; +@protocol ORKTouchAbilityRotationContentViewDataSource + +@required +- (CGFloat)targetRotationInRotationContentView:(ORKTouchAbilityRotationContentView *)rotationContentView; + +@end + +@interface ORKTouchAbilityRotationContentView : ORKTouchAbilityContentView + +@property (nonatomic, weak) id _Nullable dataSource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.m new file mode 100755 index 0000000..82f308b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationContentView.m @@ -0,0 +1,178 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityRotationContentView.h" +#import "ORKTouchAbilityArrowView.h" +#import "ORKTouchAbilityRotationTrial.h" + +@interface ORKTouchAbilityRotationContentView () + +@property (nonatomic, assign) CGFloat targetRotation; + +@property (nonatomic, strong) UIView *targetView; +@property (nonatomic, strong) UIView *guideView; + +@property (nonatomic, strong) UIRotationGestureRecognizer *rotationGestureRecognizer; + +@end + +@implementation ORKTouchAbilityRotationContentView + +#pragma mark - Properties + +- (UIView *)targetView { + if (!_targetView) { + _targetView = [[ORKTouchAbilityArrowView alloc] initWithFrame:CGRectZero style:ORKTouchAbilityArrowViewStyleFill]; + } + return _targetView; +} + +- (UIView *)guideView { + if (!_guideView) { + _guideView = [[ORKTouchAbilityArrowView alloc] initWithFrame:CGRectZero style:ORKTouchAbilityArrowViewStyleStroke]; + } + return _guideView; +} + +- (UIRotationGestureRecognizer *)rotationGestureRecognizer { + if (!_rotationGestureRecognizer) { + _rotationGestureRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotationGestureRecognizer:)]; + } + return _rotationGestureRecognizer; +} + +- (CGFloat)currentRotation { + CGAffineTransform t = self.targetView.transform; + return atan2(t.b, t.a); +} + + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + + self.translatesAutoresizingMaskIntoConstraints = NO; + + self.targetView.translatesAutoresizingMaskIntoConstraints = NO; + self.guideView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.targetView]; + [self.contentView addSubview:self.guideView]; + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.guideView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + + [self.contentView addGestureRecognizer:self.rotationGestureRecognizer]; + self.rotationGestureRecognizer.enabled = NO; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.targetView.backgroundColor = self.tintColor; +} + + +#pragma mark - ORKTouchAbilityCustomView + ++ (Class)trialClass { + return [ORKTouchAbilityRotationTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + ORKTouchAbilityRotationTrial *trial = (ORKTouchAbilityRotationTrial *)[super trial]; + trial.targetRotation = [self targetRotation]; + trial.resultRotation = [self currentRotation]; + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.rotationGestureRecognizer.enabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.rotationGestureRecognizer.enabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.targetRotation = [self.dataSource targetRotationInRotationContentView:self] ?: 0.0; + self.guideView.transform = CGAffineTransformMakeRotation(self.targetRotation); + self.targetView.transform = CGAffineTransformIdentity; +} + + +#pragma mark - Gesture Recognizer Handler + +- (void)handleRotationGestureRecognizer:(UIRotationGestureRecognizer *)sender { + + self.targetView.transform = CGAffineTransformRotate(self.targetView.transform, sender.rotation); + sender.rotation = 0.0; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.h new file mode 100755 index 0000000..f31058a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityRotationTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityRotationResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.m new file mode 100755 index 0000000..61ac2f0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationResult.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityRotationResult.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilityRotationResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_ENCODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityRotationResult *result = [super copyWithZone:zone]; + result.trials = [self.trials mutableCopy]; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.h new file mode 100755 index 0000000..38b3561 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityRotationStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.m new file mode 100755 index 0000000..16b4085 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStep.m @@ -0,0 +1,72 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityRotationStep.h" +#import "ORKTouchAbilityRotationStepViewController.h" + +@implementation ORKTouchAbilityRotationStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilityRotationStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityRotationStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)isEqual:(id)other { + return other == self || [super isEqual:other]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.h new file mode 100755 index 0000000..8702a5f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityRotationStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.m new file mode 100755 index 0000000..b4b91d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationStepViewController.m @@ -0,0 +1,185 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityRotationStepViewController.h" + +#import "ORKTouchAbilityRotationContentView.h" +#import "ORKTouchAbilityRotationStep.h" +#import "ORKTouchAbilityRotationResult.h" + +#import "ORKActiveStepView.h" +#import "ORKNavigableOrderedTask.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + +@interface ORKTouchAbilityRotationStepViewController () + +// Data +@property (nonatomic, assign) NSUInteger currentTrialIndex; +@property (nonatomic, strong) NSArray *targetRotationQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +// UI +@property (nonatomic, strong) ORKTouchAbilityRotationContentView *contentView; + +@end + +@implementation ORKTouchAbilityRotationStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilityRotationResult *rotationResult = [[ORKTouchAbilityRotationResult alloc] initWithIdentifier:self.step.identifier]; + + rotationResult.trials = self.trials; + + [results addObject:rotationResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.contentView endTrial]; + [super finish]; +} + + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.trials = [NSMutableArray new]; + self.targetRotationQueue = [self targetRotation]; + self.currentTrialIndex = 0; + + self.contentView = [[ORKTouchAbilityRotationContentView alloc] init]; + self.contentView.dataSource = self; + self.contentView.delegate = self; + + self.activeStepView.activeCustomView = self.contentView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.contentView startTrial]; +} + +- (NSArray *)targetRotation { + + NSMutableArray *array = @[@(M_PI/3.0), @(M_PI/6.0), @(-M_PI/6.0), @(-M_PI/3.0)].mutableCopy; + [array addObjectsFromArray:array]; + + NSUInteger count = [array count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [array exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return [array copy]; +} + + +#pragma mark - ORKTouchAbilityRotationContentViewDataSource + +- (CGFloat)targetRotationInRotationContentView:(ORKTouchAbilityRotationContentView *)rotationContentView { + return [self.targetRotationQueue[self.currentTrialIndex] doubleValue]; +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + NSUInteger total = self.targetRotationQueue.count; + NSUInteger done = self.currentTrialIndex + 1; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [contentView setProgress:progress animated:YES]; + + // Animate the target view. + + ORKWeakTypeOf(contentView) weakContentView = contentView; + [contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + ORKStrongTypeOf(contentView) strongContentView = weakContentView; + + // Stop tracking new touch events. + + [strongContentView endTrial]; + + [self.trials addObject:(ORKTouchAbilityRotationTrial *)strongContentView.trial]; + + // Determind if should continue or finish. + + self.currentTrialIndex += 1; + if (self.currentTrialIndex < self.targetRotationQueue.count) { + + // Reload and start tracking again. + [strongContentView reloadData]; + [strongContentView setContentViewHidden:NO animated:NO]; + [strongContentView startTrial]; + + } else { + + // Finish step. + [self finish]; + } + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.h new file mode 100755 index 0000000..bc964d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityRotationTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) CGFloat targetRotation; +@property (nonatomic, assign) CGFloat resultRotation; + +- (instancetype)initWithTargetRotation:(CGFloat)targetRotation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.m new file mode 100755 index 0000000..069c0d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityRotationTrial.m @@ -0,0 +1,98 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityRotationTrial.h" +#import "ORKHelpers_Internal.h" + +#define radian2Degree(a) (a * 180.0 / M_PI) + +@implementation ORKTouchAbilityRotationTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, targetRotation); + ORK_ENCODE_DOUBLE(aCoder, resultRotation); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_DOUBLE(aDecoder, targetRotation); + ORK_DECODE_DOUBLE(aDecoder, resultRotation); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityRotationTrial *trial = [super copyWithZone:zone]; + trial.targetRotation = self.targetRotation; + trial.resultRotation = self.resultRotation; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.targetRotation == castObject.targetRotation && + self.resultRotation == castObject.resultRotation); +} + +- (instancetype)init { + if (self = [super init]) { + self.targetRotation = 0.0; + self.resultRotation = 0.0; + } + return self; +} + +- (instancetype)initWithTargetRotation:(CGFloat)targetRotation { + if (self = [super init]) { + self.targetRotation = targetRotation; + self.resultRotation = 0.0; + } + return self; +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + return [NSString stringWithFormat:@"<%@; target rotation: %@; result rotation: %@>", + sDescription, + @(radian2Degree(self.targetRotation)), + @(radian2Degree(self.resultRotation))]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.h new file mode 100755 index 0000000..8274700 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" +#import "ORKTouchAbilityScrollTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityScrollContentView; +@protocol ORKTouchAbilityScrollContentViewDataSource + +@required +- (NSUInteger)numberOfItemsInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView; +- (NSUInteger)numberOfVisibleItemsInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView; +- (NSUInteger)initialItemInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView; +- (NSUInteger)targetItemInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView; + +@end + +@interface ORKTouchAbilityScrollContentView : ORKTouchAbilityContentView + +@property (nonatomic, assign) ORKTouchAbilityScrollTrialDirection direction; +@property (nonatomic, weak) id _Nullable dataSource; + +@property (nonatomic, readonly) NSTimeInterval timeIntervalBeforeStopDecelarating; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.m new file mode 100755 index 0000000..d947266 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollContentView.m @@ -0,0 +1,334 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityScrollContentView.h" +#import "ORKTouchAbilityPinchGuideView.h" + +@interface ORKTouchAbilityScrollContentView () < +UICollectionViewDataSource, +UICollectionViewDelegate +> + +@property (nonatomic, assign) NSUInteger numberOfItems; +@property (nonatomic, assign) NSUInteger visibleItems; +@property (nonatomic, assign) NSUInteger initialItem; +@property (nonatomic, assign) NSUInteger targetItem; + +@property (nonatomic, assign) BOOL success; + +@property (nonatomic, assign) CGPoint initialOffset; +@property (nonatomic, assign) CGPoint targetOffset; +@property (nonatomic, assign) CGPoint endDraggingOffset; +@property (nonatomic, assign) CGPoint endScrollingOffset; + +@property (nonatomic, assign) NSTimeInterval timeIntervalBeforeStopDecelarating; + +@property (nonatomic, strong) UIView *hintView; +@property (nonatomic, strong) UICollectionView *collectionView; +@property (nonatomic, strong) UICollectionViewFlowLayout *flowLayout; + +@end + +@implementation ORKTouchAbilityScrollContentView + +#pragma mark - Properties + +- (void)setDirection:(ORKTouchAbilityScrollTrialDirection)direction { + switch (direction) { + case ORKTouchAbilityScrollTrialDirectionVertical: + self.flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; + break; + + case ORKTouchAbilityScrollTrialDirectionHorizontal: + self.flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; + break; + } +} + +- (UICollectionView *)collectionView { + if (!_collectionView) { + _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.flowLayout]; + } + return _collectionView; +} + +- (UICollectionViewFlowLayout *)flowLayout { + if (!_flowLayout) { + _flowLayout = [[UICollectionViewFlowLayout alloc] init]; + _flowLayout.minimumLineSpacing = 0.0; + } + return _flowLayout; +} + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + + self.hintView = [[ORKTouchAbilityPinchGuideView alloc] init]; + + self.collectionView.showsVerticalScrollIndicator = NO; + self.collectionView.showsHorizontalScrollIndicator = NO; + self.collectionView.backgroundColor = UIColor.clearColor; + self.collectionView.delaysContentTouches = NO; + self.collectionView.dataSource = self; + self.collectionView.delegate = self; + [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; + + self.collectionView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.collectionView]; + [self.contentView insertSubview:self.hintView atIndex:10000]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_collectionView); + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_collectionView]|" + options:0 + metrics:nil + views:views]]; + + [constraintsArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_collectionView]|" + options:0 + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (self.visibleItems == 0) { + return; + } + + if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { + CGFloat width = CGRectGetWidth(self.contentView.bounds) / self.visibleItems; + CGFloat height = CGRectGetHeight(self.contentView.bounds); + self.flowLayout.itemSize = CGSizeMake(width, height); + + if (self.targetItem < self.initialItem) { + self.hintView.frame = CGRectMake(CGRectGetMinX(self.collectionView.frame) + width / 2, + CGRectGetMinY(self.collectionView.frame), + width, + height); + } else { + self.hintView.frame = CGRectMake(CGRectGetMaxX(self.collectionView.frame) - width * 1.5, + CGRectGetMinY(self.collectionView.frame), + width, + height); + } + } else { + CGFloat width = CGRectGetWidth(self.contentView.bounds); + CGFloat height = CGRectGetHeight(self.contentView.bounds) / self.visibleItems; + self.flowLayout.itemSize = CGSizeMake(width, height); + + if (self.targetItem < self.initialItem) { + self.hintView.frame = CGRectMake(CGRectGetMinX(self.collectionView.frame), + CGRectGetMinY(self.collectionView.frame) + height / 2, + width, + height); + } else { + self.hintView.frame = CGRectMake(CGRectGetMinX(self.collectionView.frame), + CGRectGetMaxY(self.collectionView.frame) - height * 1.5, + width, + height); + } + } +} + + +#pragma mark - ORKTouchAbilityContentView + ++ (Class)trialClass { + return [ORKTouchAbilityScrollTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + + ORKTouchAbilityScrollTrial *trial = (ORKTouchAbilityScrollTrial *)[super trial]; + + trial.direction = self.direction; + trial.initialOffset = self.initialOffset; + trial.targetOffsetLowerBound = self.targetOffset; + if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { + trial.targetOffsetUpperBound = CGPointMake(self.targetOffset.x + self.flowLayout.itemSize.width, self.targetOffset.y); + } else { + trial.targetOffsetUpperBound = CGPointMake(self.targetOffset.x, self.targetOffset.y + self.flowLayout.itemSize.height); + } + trial.endDraggingOffset = self.endDraggingOffset; + trial.endScrollingOffset = self.endScrollingOffset; + + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.collectionView.userInteractionEnabled = YES; + self.collectionView.scrollEnabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.collectionView.userInteractionEnabled = NO; + self.collectionView.scrollEnabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.success = NO; + self.numberOfItems = [self.dataSource numberOfItemsInScrollContentView:self] ?: 1; + self.visibleItems = [self.dataSource numberOfVisibleItemsInScrollContentView:self] ?: 1; + self.initialItem = [self.dataSource initialItemInScrollContentView:self] ?: 0; + self.targetItem = [self.dataSource targetItemInScrollContentView:self] ?: 0; + + [self.collectionView reloadData]; + [self setNeedsLayout]; + [self layoutIfNeeded]; + + NSInteger indexDiff = self.targetItem - self.initialItem; + + if (self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) { + + CGFloat width = CGRectGetWidth(self.collectionView.bounds) / self.visibleItems; + CGFloat offsetX = width * ((self.numberOfItems / 2) - 2.5); + CGFloat offsetY = self.collectionView.contentOffset.y; + + self.initialOffset = CGPointMake(offsetX, offsetY); + self.targetOffset = CGPointMake(offsetX - indexDiff * width, offsetY); + + } else { + + CGFloat height = CGRectGetHeight(self.collectionView.bounds) / self.visibleItems; + CGFloat offsetX = self.collectionView.contentOffset.x; + CGFloat offsetY = height * ((self.numberOfItems / 2) - 2.5); + + self.initialOffset = CGPointMake(offsetX, offsetY); + self.targetOffset = CGPointMake(offsetX, offsetY - indexDiff * height); + } + + [self.collectionView setContentOffset:self.initialOffset animated:NO]; + + self.endDraggingOffset = CGPointZero; + self.endScrollingOffset = CGPointZero; + + self.timeIntervalBeforeStopDecelarating = 0.0; +} + +- (void)touchTrackerDidBeginNewTrack:(ORKTouchAbilityTouchTracker *)touchTracker { + self.timeIntervalBeforeStopDecelarating = 0.0; + [super touchTrackerDidBeginNewTrack:touchTracker]; +} + +- (void)touchTrackerDidCompleteNewTracks:(ORKTouchAbilityTouchTracker *)touchTracker { + dispatch_async(dispatch_get_main_queue(), ^{ + [super touchTrackerDidCompleteNewTracks:touchTracker]; + }); +} + +#pragma mark - UICollectionViewDataSource + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.numberOfItems; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath]; + + if (![cell.contentView viewWithTag:10000]) { + UILabel *label = [[UILabel alloc] init]; + label.textAlignment = NSTextAlignmentCenter; + label.font = [UIFont systemFontOfSize:42 weight:UIFontWeightBold]; + + [cell.contentView addSubview:label]; + label.frame = cell.contentView.bounds; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + label.tag = 10000; + } + + UILabel *label = (UILabel *)[cell.contentView viewWithTag:10000]; + label.text = [NSString stringWithFormat:@"%@", @(indexPath.item + 1)]; + + + if (indexPath.item == self.initialItem) { + cell.contentView.backgroundColor = self.tintColor; + label.textColor = [UIColor whiteColor]; + } else if (indexPath.item % 2 == 0) { + cell.contentView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0]; + label.textColor = [UIColor blackColor]; + } else { + cell.contentView.backgroundColor = [UIColor whiteColor]; + label.textColor = [UIColor blackColor]; + } + + return cell; +} + + +#pragma mark - UICollectionViewDelegate + +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.item == self.targetItem) { + self.success = YES; + } +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.item == self.targetItem) { + self.success = NO; + } +} + + +#pragma mark - UIScrollViewDelegate + +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { + + self.endDraggingOffset = scrollView.contentOffset; + self.endScrollingOffset = *targetContentOffset; + + CGFloat velocityX = fabs(velocity.x); + CGFloat velocityY = fabs(velocity.y); + + CGFloat v = self.flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal ? velocityX : velocityY; + + if (v <= 0) { + self.timeIntervalBeforeStopDecelarating = 0.0; + } else { + self.timeIntervalBeforeStopDecelarating = (log(v) * 0.5) + 2.3; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.h new file mode 100755 index 0000000..056d06d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityScrollTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityScrollResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.m new file mode 100755 index 0000000..750808d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollResult.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityScrollResult.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilityScrollResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_ENCODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityScrollResult *result = [super copyWithZone:zone]; + result.trials = self.trials; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.h new file mode 100755 index 0000000..51953f1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityScrollStep : ORKActiveStep +@property (nonatomic, assign, getter=isHorizontal) BOOL horizontal; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.m new file mode 100755 index 0000000..01c148d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStep.m @@ -0,0 +1,90 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityScrollStep.h" +#import "ORKTouchAbilityScrollStepViewController.h" +#import "ORKhelpers_Internal.h" + +@implementation ORKTouchAbilityScrollStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilityScrollStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityScrollStep *step = [super copyWithZone:zone]; + step.horizontal = self.isHorizontal; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_BOOL(aDecoder, horizontal); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_BOOL(aCoder, horizontal); +} + +- (BOOL)isEqual:(id)other { + BOOL isParentSame = [super isEqual:other]; + + __typeof(self) castObject = other; + return isParentSame && self.isHorizontal == castObject.isHorizontal; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.h new file mode 100755 index 0000000..3f69bc2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityScrollStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.m new file mode 100755 index 0000000..ee284e3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollStepViewController.m @@ -0,0 +1,248 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityScrollStepViewController.h" +#import "ORKTouchAbilityScrollStep.h" + +#import "ORKActiveStepView.h" +#import "ORKTouchAbilityScrollContentView.h" +#import "ORKTouchAbilityScrollResult.h" +#import "ORKTouchAbilityScrollTrial.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTouchAbilitySwipeStep.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + + +#define TrialData(n, m, t, d) @[@(n), @(m), @(t), @(d)] + +#define TrialDataGetNumberOfItems(data) [data[0] unsignedIntegerValue] +#define TrialDataGetNumberOfMiddleItems(data) [data[1] unsignedIntegerValue] +#define TrialDataGetTargetItem(data) [data[2] unsignedIntegerValue] +#define TrialDataGetDestination(data) [data[3] unsignedIntegerValue] + +@interface ORKTouchAbilityScrollStepViewController () < +ORKTouchAbilityScrollContentViewDataSource, +ORKTouchAbilityContentViewDelegate +> + +// Data +@property (nonatomic, assign) NSUInteger currentTrialIndex; +@property (nonatomic, strong) NSArray *trialDataQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +@property (nonatomic, copy) dispatch_block_t endTrialWork; + +// UI +@property (nonatomic, strong) ORKTouchAbilityScrollContentView *contentView; + +@end + +@implementation ORKTouchAbilityScrollStepViewController + +- (BOOL)isHorizontalStep { + return ((ORKTouchAbilityScrollStep *)self.step).isHorizontal; +} + + +#pragma mark - ORKActiveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilityScrollResult *scrollResult = [[ORKTouchAbilityScrollResult alloc] initWithIdentifier:self.step.identifier]; + + scrollResult.trials = self.trials; + + [results addObject:scrollResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.contentView endTrial]; + [super finish]; +} + + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.currentTrialIndex = 0; + self.trialDataQueue = [self makeTrialDataQueue]; + self.trials = [NSMutableArray new]; + + self.contentView = [[ORKTouchAbilityScrollContentView alloc] init]; + self.contentView.direction = self.isHorizontalStep ? ORKTouchAbilityScrollTrialDirectionHorizontal : ORKTouchAbilityScrollTrialDirectionVertical; + self.contentView.dataSource = self; + self.contentView.delegate = self; + + self.activeStepView.activeCustomView = self.contentView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.contentView startTrial]; +} + +- (NSArray *)makeTrialDataQueue { + + NSMutableArray *array = [NSMutableArray array]; + + [array addObject:TrialData(19, 5, 7, 11)]; + [array addObject:TrialData(19, 5, 9, 11)]; + [array addObject:TrialData(19, 5, 9, 7)]; + [array addObject:TrialData(19, 5, 11, 7)]; + [array addObjectsFromArray:array]; + + NSUInteger count = [array count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [array exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return [array copy]; +} + +#pragma mark - ORKTouchAbilityScrollContentViewDataSource + +- (NSUInteger)numberOfItemsInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView { + return TrialDataGetNumberOfItems(self.trialDataQueue[self.currentTrialIndex]); +} + +- (NSUInteger)numberOfVisibleItemsInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView { + return TrialDataGetNumberOfMiddleItems(self.trialDataQueue[self.currentTrialIndex]) + 1; +} + +- (NSUInteger)initialItemInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView { + return TrialDataGetTargetItem(self.trialDataQueue[self.currentTrialIndex]); +} + +- (NSUInteger)targetItemInScrollContentView:(ORKTouchAbilityScrollContentView *)scrollContentView { + return TrialDataGetDestination(self.trialDataQueue[self.currentTrialIndex]); +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidBeginNewTrack:(ORKTouchAbilityContentView *)contentView { + + if (self.endTrialWork) { + dispatch_block_cancel(self.endTrialWork); + self.endTrialWork = nil; + } +} + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + self.endTrialWork = dispatch_block_create(DISPATCH_BLOCK_NO_QOS_CLASS, ^{ + [self endTrial]; + }); + + NSTimeInterval delay = self.contentView.timeIntervalBeforeStopDecelarating + 1.0; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), self.endTrialWork); +} + +- (void)endTrial { + + // Calculate current progress and display using progress view. + + NSUInteger total = self.trialDataQueue.count; + NSUInteger done = self.currentTrialIndex + 1; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [self.contentView setProgress:progress animated:YES]; + + + // Animate the target view. + + ORKWeakTypeOf(self) weakSelf = self; + [self.contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + + ORKStrongTypeOf(self) strongSelf = weakSelf; + + // Stop tracking new touch events. + + [strongSelf.contentView endTrial]; + + [strongSelf.trials addObject:(ORKTouchAbilityScrollTrial *)strongSelf.contentView.trial]; + + + // Determind if should continue or finish. + + strongSelf.currentTrialIndex += 1; + if (strongSelf.currentTrialIndex < strongSelf.trialDataQueue.count) { + + // Reload and start tracking again. + [strongSelf.contentView reloadData]; + [strongSelf.contentView setContentViewHidden:NO animated:NO]; + [strongSelf.contentView startTrial]; + + } else { + + // Finish step. + [strongSelf finish]; + } + + }]; + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.h new file mode 100755 index 0000000..617f8f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, ORKTouchAbilityScrollTrialDirection) { + ORKTouchAbilityScrollTrialDirectionHorizontal, + ORKTouchAbilityScrollTrialDirectionVertical +}; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityScrollTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) ORKTouchAbilityScrollTrialDirection direction; + +@property (nonatomic, assign) CGPoint initialOffset; +@property (nonatomic, assign) CGPoint targetOffsetUpperBound; +@property (nonatomic, assign) CGPoint targetOffsetLowerBound; +@property (nonatomic, assign) CGPoint endDraggingOffset; +@property (nonatomic, assign) CGPoint endScrollingOffset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.m new file mode 100755 index 0000000..e5c65d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityScrollTrial.m @@ -0,0 +1,107 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityScrollTrial.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilityScrollTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, direction); + ORK_ENCODE_CGPOINT(aCoder, initialOffset); + ORK_ENCODE_CGPOINT(aCoder, targetOffsetUpperBound); + ORK_ENCODE_CGPOINT(aCoder, targetOffsetLowerBound); + ORK_ENCODE_CGPOINT(aCoder, endDraggingOffset); + ORK_ENCODE_CGPOINT(aCoder, endScrollingOffset); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_ENUM(aDecoder, direction); + ORK_DECODE_CGPOINT(aDecoder, initialOffset); + ORK_DECODE_CGPOINT(aDecoder, targetOffsetUpperBound); + ORK_DECODE_CGPOINT(aDecoder, targetOffsetLowerBound); + ORK_DECODE_CGPOINT(aDecoder, endDraggingOffset); + ORK_ENCODE_CGPOINT(aDecoder, endScrollingOffset); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityScrollTrial *trial = [super copyWithZone:zone]; + trial.direction = self.direction; + trial.initialOffset = self.initialOffset; + trial.targetOffsetUpperBound = self.targetOffsetUpperBound; + trial.targetOffsetLowerBound = self.targetOffsetLowerBound; + trial.endDraggingOffset = self.endDraggingOffset; + trial.endScrollingOffset = self.endScrollingOffset; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.direction == castObject.direction && + CGPointEqualToPoint(self.initialOffset, castObject.initialOffset) && + CGPointEqualToPoint(self.targetOffsetUpperBound, castObject.targetOffsetUpperBound) && + CGPointEqualToPoint(self.targetOffsetLowerBound, castObject.targetOffsetLowerBound) && + CGPointEqualToPoint(self.endDraggingOffset, castObject.endDraggingOffset) && + CGPointEqualToPoint(self.endScrollingOffset, castObject.endScrollingOffset)); +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + NSString *directionString; + if (self.direction == ORKTouchAbilityScrollTrialDirectionVertical) { + directionString = @"vertical"; + } else { + directionString = @"horizontal"; + } + + return [NSString stringWithFormat:@"<%@; direction: %@; initial offset: %@; target offset: [%@, %@]; end dragging offset: %@; end scrolling offset: %@;>", + sDescription, + directionString, + [NSValue valueWithCGPoint:self.initialOffset], + [NSValue valueWithCGPoint:self.targetOffsetUpperBound], + [NSValue valueWithCGPoint:self.targetOffsetLowerBound], + [NSValue valueWithCGPoint:self.endDraggingOffset], + [NSValue valueWithCGPoint:self.endDraggingOffset]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.h new file mode 100755 index 0000000..4caf6ec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilitySwipeContentView; +@protocol ORKTouchAbilitySwipeContentViewDataSource + +@required +- (UISwipeGestureRecognizerDirection)targetDirectionInSwipeContentView:(ORKTouchAbilitySwipeContentView *)swipeContentView; + +@end + +@interface ORKTouchAbilitySwipeContentView : ORKTouchAbilityContentView + +@property (nonatomic, weak) id _Nullable dataSource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.m new file mode 100755 index 0000000..652bfcb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeContentView.m @@ -0,0 +1,223 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilitySwipeContentView.h" +#import "ORKTouchAbilityArrowView.h" +#import "ORKTouchAbilitySwipeTrial.h" + +@interface ORKTouchAbilitySwipeContentView () + +@property (nonatomic, assign) UISwipeGestureRecognizerDirection targetDirection; +@property (nonatomic, assign) UISwipeGestureRecognizerDirection resultDirection; +@property (nonatomic, assign) BOOL success; + +@property (nonatomic, strong) ORKTouchAbilityArrowView *arrowView; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeUpGestureRecognizer; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeDownGestureRecognizer; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeLeftGestureRecognizer; +@property (nonatomic, strong) UISwipeGestureRecognizer *swipeRightGestureRecognizer; + +@end + +@implementation ORKTouchAbilitySwipeContentView + +#pragma mark - Properties + +- (ORKTouchAbilityArrowView *)arrowView { + if (!_arrowView) { + _arrowView = [[ORKTouchAbilityArrowView alloc] initWithFrame:CGRectZero style:ORKTouchAbilityArrowViewStyleFill]; + } + return _arrowView; +} + +- (UISwipeGestureRecognizer *)swipeUpGestureRecognizer { + if (!_swipeUpGestureRecognizer) { + _swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGestureRecoginzer:)]; + _swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp; + } + return _swipeUpGestureRecognizer; +} + +- (UISwipeGestureRecognizer *)swipeDownGestureRecognizer { + if (!_swipeDownGestureRecognizer) { + _swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGestureRecoginzer:)]; + _swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown; + } + return _swipeDownGestureRecognizer; +} + +- (UISwipeGestureRecognizer *)swipeLeftGestureRecognizer { + if (!_swipeLeftGestureRecognizer) { + _swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGestureRecoginzer:)]; + _swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft; + } + return _swipeLeftGestureRecognizer; +} + +- (UISwipeGestureRecognizer *)swipeRightGestureRecognizer { + if (!_swipeRightGestureRecognizer) { + _swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGestureRecoginzer:)]; + _swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight; + } + return _swipeRightGestureRecognizer; +} + + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + self.arrowView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.arrowView]; + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.arrowView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.arrowView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraintsArray]; + + self.swipeUpGestureRecognizer.enabled = NO; + self.swipeDownGestureRecognizer.enabled = NO; + self.swipeLeftGestureRecognizer.enabled = NO; + self.swipeRightGestureRecognizer.enabled = NO; + + [self.contentView addGestureRecognizer:self.swipeUpGestureRecognizer]; + [self.contentView addGestureRecognizer:self.swipeDownGestureRecognizer]; + [self.contentView addGestureRecognizer:self.swipeLeftGestureRecognizer]; + [self.contentView addGestureRecognizer:self.swipeRightGestureRecognizer]; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.arrowView.tintColor = self.tintColor; +} + + +#pragma mark - ORKTouchAbilityCustomView + ++ (Class)trialClass { + return [ORKTouchAbilitySwipeTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + + ORKTouchAbilitySwipeTrial *trial = (ORKTouchAbilitySwipeTrial *)[super trial]; + trial.targetDirection = self.targetDirection; + trial.resultDirection = self.resultDirection; + trial.success = self.success; + + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.swipeUpGestureRecognizer.enabled = YES; + self.swipeDownGestureRecognizer.enabled = YES; + self.swipeLeftGestureRecognizer.enabled = YES; + self.swipeRightGestureRecognizer.enabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.swipeUpGestureRecognizer.enabled = NO; + self.swipeDownGestureRecognizer.enabled = NO; + self.swipeLeftGestureRecognizer.enabled = NO; + self.swipeRightGestureRecognizer.enabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.success = NO; + self.resultDirection = UISwipeGestureRecognizerDirectionRight; + + if ([self.dataSource respondsToSelector:@selector(targetDirectionInSwipeContentView:)]) { + self.targetDirection = [self.dataSource targetDirectionInSwipeContentView:self]; + } else { + self.targetDirection = UISwipeGestureRecognizerDirectionRight; + } + + switch (self.targetDirection) { + + case UISwipeGestureRecognizerDirectionRight: + self.arrowView.transform = CGAffineTransformMakeRotation(M_PI_2); + break; + + case UISwipeGestureRecognizerDirectionLeft: + self.arrowView.transform = CGAffineTransformMakeRotation(-M_PI_2); + break; + + case UISwipeGestureRecognizerDirectionUp: + self.arrowView.transform = CGAffineTransformIdentity; + break; + + case UISwipeGestureRecognizerDirectionDown: + self.arrowView.transform = CGAffineTransformMakeRotation(M_PI); + break; + } +} + + +#pragma mark - Gesture Recognizer Handler + +- (void)handleSwipeGestureRecoginzer:(UISwipeGestureRecognizer *)sender { + self.resultDirection = sender.direction; + [self checkSuccess]; +} + +- (void)checkSuccess { + if (self.resultDirection == self.targetDirection) { + self.success = YES; + } else { + self.success = NO; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.h new file mode 100755 index 0000000..e359bee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilitySwipeTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilitySwipeResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.m new file mode 100755 index 0000000..105a57b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeResult.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilitySwipeResult.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilitySwipeResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_ENCODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilitySwipeResult *result = [super copyWithZone:zone]; + result.trials = [self.trials mutableCopy]; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.h new file mode 100755 index 0000000..e43fe00 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilitySwipeStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.m new file mode 100755 index 0000000..3113ab0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStep.m @@ -0,0 +1,74 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilitySwipeStep.h" +#import "ORKTouchAbilitySwipeStepViewController.h" +#import "ORKhelpers_Internal.h" + +@implementation ORKTouchAbilitySwipeStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilitySwipeStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilitySwipeStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)isEqual:(id)other { + return other == self || [super isEqual:other]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.h new file mode 100755 index 0000000..e0e54f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilitySwipeStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.m new file mode 100755 index 0000000..c847542 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeStepViewController.m @@ -0,0 +1,206 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilitySwipeStepViewController.h" + + +#import "ORKActiveStepView.h" +#import "ORKTouchAbilitySwipeContentView.h" +#import "ORKTouchAbilitySwipeResult.h" +#import "ORKTouchAbilitySwipeTrial.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTouchAbilitySwipeStep.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + + +@interface ORKTouchAbilitySwipeStepViewController () + +// Data +@property (nonatomic, assign) NSUInteger currentTrialIndex; +@property (nonatomic, strong) NSArray *targetDirectionQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +// UI +@property (nonatomic, strong) ORKTouchAbilitySwipeContentView *swipeContentView; + +@end + +@implementation ORKTouchAbilitySwipeStepViewController + + +#pragma mark - ORKActiveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilitySwipeResult *swipeResult = [[ORKTouchAbilitySwipeResult alloc] initWithIdentifier:self.step.identifier]; + + swipeResult.trials = self.trials; + + [results addObject:swipeResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.swipeContentView endTrial]; + [super finish]; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.currentTrialIndex = 0; + self.targetDirectionQueue = [self targetDirections]; + self.trials = [NSMutableArray new]; + + self.swipeContentView = [[ORKTouchAbilitySwipeContentView alloc] init]; + self.swipeContentView.dataSource = self; + self.swipeContentView.delegate = self; + + self.activeStepView.activeCustomView = self.swipeContentView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.swipeContentView startTrial]; +} + +- (NSArray *)targetDirections { + + NSMutableArray *directions = @[@(UISwipeGestureRecognizerDirectionUp), + @(UISwipeGestureRecognizerDirectionDown), + @(UISwipeGestureRecognizerDirectionLeft), + @(UISwipeGestureRecognizerDirectionRight)].mutableCopy; + [directions addObjectsFromArray:directions]; + + NSUInteger count = [directions count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [directions exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return [directions copy]; +} + +#pragma mark - ORKTouchAbilitySwipeContentViewDataSource + +- (UISwipeGestureRecognizerDirection)targetDirectionInSwipeContentView:(ORKTouchAbilitySwipeContentView *)swipeContentView { + return [self.targetDirectionQueue[self.currentTrialIndex] intValue]; + +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidBeginNewTrack:(ORKTouchAbilityContentView *)contentView { + +} + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + + // Calculate current progress and display using progress view. + + NSUInteger total = self.targetDirectionQueue.count; + NSUInteger done = self.currentTrialIndex + 1; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [contentView setProgress:progress animated:YES]; + + + // Animate the target view. + + ORKWeakTypeOf(contentView) weakContentView = contentView; + + [contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + + ORKStrongTypeOf(contentView) strongContentView = weakContentView; + + // Stop tracking new touch events. + + [strongContentView endTrial]; + + [self.trials addObject:(ORKTouchAbilitySwipeTrial *)strongContentView.trial]; + + + // Determind if should continue or finish. + + self.currentTrialIndex += 1; + if (self.currentTrialIndex < self.targetDirectionQueue.count) { + + // Reload and start tracking again. + [strongContentView reloadData]; + [strongContentView setContentViewHidden:NO animated:NO]; + [strongContentView startTrial]; + + } else { + + // Finish step. + [self finish]; + } + + }]; + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.h new file mode 100755 index 0000000..38b61ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilitySwipeTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) UISwipeGestureRecognizerDirection targetDirection; +@property (nonatomic, assign) UISwipeGestureRecognizerDirection resultDirection; +@property (nonatomic, assign) BOOL success; + +- (instancetype)initWithTargetDirection:(UISwipeGestureRecognizerDirection)direction; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.m new file mode 100755 index 0000000..19db43b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilitySwipeTrial.m @@ -0,0 +1,103 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilitySwipeTrial.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKTouchAbilitySwipeTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, targetDirection); + ORK_ENCODE_ENUM(aCoder, resultDirection); + ORK_ENCODE_BOOL(aCoder, success); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_ENUM(aDecoder, targetDirection); + ORK_DECODE_ENUM(aDecoder, resultDirection); + ORK_DECODE_BOOL(aDecoder, success); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilitySwipeTrial *trial = [super copyWithZone:zone]; + trial.targetDirection = self.targetDirection; + trial.resultDirection = self.resultDirection; + trial.success = self.success; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + self.targetDirection == castObject.targetDirection && + self.resultDirection == castObject.resultDirection && + self.success == castObject.success); +} + +- (instancetype)initWithTargetDirection:(UISwipeGestureRecognizerDirection)direction { + if (self = [super init]) { + self.targetDirection = direction; + self.resultDirection = direction; + self.success = NO; + } + return self; +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + return [NSString stringWithFormat:@"<%@; target direction: %@; result direction: %@; success: %@>", sDescription, [self directionStringFor:self.targetDirection], [self directionStringFor:self.resultDirection], self.success ? @"true" : @"false"]; +} + +- (NSString *)directionStringFor:(UISwipeGestureRecognizerDirection)direction { + switch (direction) { + case UISwipeGestureRecognizerDirectionUp: + return @"up"; + case UISwipeGestureRecognizerDirectionDown: + return @"down"; + case UISwipeGestureRecognizerDirectionLeft: + return @"left"; + case UISwipeGestureRecognizerDirectionRight: + return @"right"; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.h new file mode 100755 index 0000000..551dd00 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTouchAbilityContentView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityTapContentView; +@protocol ORKTouchAbilityTapContentViewDataSource + +@required +- (NSUInteger)numberOfColumnsInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView; +- (NSUInteger)numberOfRowsInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView; +- (NSUInteger)targetColumnInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView; +- (NSUInteger)targetRowInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView; + +@optional +- (CGSize)targetSizeInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapContentView : ORKTouchAbilityContentView +@property (nonatomic, weak) id _Nullable dataSource; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.m new file mode 100755 index 0000000..7fe09a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapContentView.m @@ -0,0 +1,211 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityTapContentView.h" +#import "ORKTouchAbilityTapTrial.h" + +#import "ORKHelpers_Internal.h" + +@interface ORKTouchAbilityTapContentView () + +@property (nonatomic, assign) BOOL success; + +@property (nonatomic, assign) NSUInteger numberOfColumns; +@property (nonatomic, assign) NSUInteger numberOfRows; +@property (nonatomic, assign) NSUInteger targetColumn; +@property (nonatomic, assign) NSUInteger targetRow; +@property (nonatomic, assign) CGSize targetSize; + +@property (nonatomic, strong) UIView *targetView; +@property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer; + +@property (nonatomic, copy) NSArray *targetConstraints; + +@end + +@implementation ORKTouchAbilityTapContentView + + +#pragma mark - Properties + +- (UIView *)targetView { + if (!_targetView) { + _targetView = [[UIView alloc] initWithFrame:CGRectZero]; + } + return _targetView; +} + +- (UITapGestureRecognizer *)tapGestureRecognizer { + if (!_tapGestureRecognizer) { + _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGestureRecognizer:)]; + } + return _tapGestureRecognizer; +} + + +#pragma mark - UIView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + self.targetView.backgroundColor = self.tintColor; + self.targetView.translatesAutoresizingMaskIntoConstraints = NO; + + [self.contentView addSubview:self.targetView]; + + self.tapGestureRecognizer.enabled = NO; + [self.contentView addGestureRecognizer:self.tapGestureRecognizer]; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.targetView.backgroundColor = self.tintColor; +} + +- (void)updateConstraints { + [super updateConstraints]; + + if (self.numberOfColumns == 0 || self.numberOfRows == 0 || self.targetView.superview == nil) { + return; + } + + CGFloat width = self.contentView.frame.size.width / self.numberOfColumns; + CGFloat height = self.contentView.frame.size.height / self.numberOfRows; + + CGFloat columnMidX = width * (self.targetColumn + 1.0/2.0); + CGFloat rowMidY = height * (self.targetRow + 1.0/2.0); + + if (self.targetConstraints != nil) { + [NSLayoutConstraint deactivateConstraints:self.targetConstraints]; + self.targetConstraints = nil; + } + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:self.targetSize.width]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:self.targetSize.height]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:columnMidX]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.targetView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:rowMidY]]; + + self.targetConstraints = constraintsArray; + [NSLayoutConstraint activateConstraints:self.targetConstraints]; +} + + +#pragma mark - ORKTouchAbilityCustomView + ++ (Class)trialClass { + return [ORKTouchAbilityTapTrial class]; +} + +- (ORKTouchAbilityTrial *)trial { + + ORKTouchAbilityTapTrial *trial = (ORKTouchAbilityTapTrial *)[super trial]; + trial.targetFrameInWindow = [self.targetView convertRect:self.targetView.bounds toView:nil]; + trial.success = self.success; + + return trial; +} + +- (void)startTrial { + [super startTrial]; + self.tapGestureRecognizer.enabled = YES; +} + +- (void)endTrial { + [super endTrial]; + self.tapGestureRecognizer.enabled = NO; +} + +- (void)reloadData { + [self resetTracks]; + + self.success = NO; + + self.numberOfColumns = [self.dataSource numberOfColumnsInTapContentView:self] ?: 1; + self.numberOfRows = [self.dataSource numberOfRowsInTapContentView:self] ?: 1; + self.targetColumn = [self.dataSource targetColumnInTapContentView:self] ?: 0; + self.targetRow = [self.dataSource targetRowInTapContentView:self] ?: 0; + + NSAssert(self.targetColumn >= 0 && self.targetColumn < self.numberOfColumns, @"Target column out of bounds."); + NSAssert(self.targetRow >= 0 && self.targetRow < self.numberOfRows, @"target row out of bounds."); + + if ([self.dataSource respondsToSelector:@selector(targetSizeInTapContentView:)]) { + self.targetSize = [self.dataSource targetSizeInTapContentView:self]; + } else { + self.targetSize = CGSizeMake(76, 76); + } + + [self setNeedsUpdateConstraints]; + [self updateConstraintsIfNeeded]; +} + + +#pragma mark - Gesture Recognizer Handler + +- (void)handleTapGestureRecognizer:(UITapGestureRecognizer *)sender { + if (CGRectContainsPoint(self.targetView.bounds, [sender locationInView:self.targetView])) { + self.success = YES; + } else { + self.success = NO; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.h new file mode 100755 index 0000000..79ad7fb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityTapTrial; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapResult : ORKResult +@property (nonatomic, copy) NSArray *trials; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.m new file mode 100755 index 0000000..526ac5d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapResult.m @@ -0,0 +1,80 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTouchAbilityTapResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKTouchAbilityTrial.h" + +@implementation ORKTouchAbilityTapResult + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trials); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + ORK_DECODE_OBJ(aDecoder, trials); + } + return self; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.trials, castObject.trials); +} + +- (NSUInteger)hash { + return super.hash ^ self.trials.hash; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTapResult *result = [super copyWithZone:zone]; + result.trials = [self.trials mutableCopy]; + return result; +} + +- (NSArray *)trials { + if (!_trials) { + _trials = [NSArray new]; + } + return _trials; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.h new file mode 100755 index 0000000..eb24649 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapStep : ORKActiveStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.m new file mode 100755 index 0000000..0adadee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStep.m @@ -0,0 +1,74 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTapStep.h" +#import "ORKTouchAbilityTapStepViewController.h" +#import "ORKhelpers_Internal.h" + +@implementation ORKTouchAbilityTapStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAbilityTapStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + // TODO: +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTapStep *step = [super copyWithZone:zone]; + return step; +} + +- (BOOL)isEqual:(id)other { + return other == self || [super isEqual:other]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.h new file mode 100755 index 0000000..f5a994c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.m new file mode 100755 index 0000000..75fc3b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapStepViewController.m @@ -0,0 +1,238 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTapStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKTouchAbilityTapContentView.h" +#import "ORKTouchAbilityTapResult.h" +#import "ORKTouchAbilityTouchTracker.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTouchAbilityTapStep.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKVerticalContainerView_Internal.h" +#import "ORKHelpers_Internal.h" + + +@interface ORKTouchAbilityTapStepViewController () + +// Data +@property (nonatomic, strong) NSMutableArray *targetPointsQueue; +@property (nonatomic, strong) NSMutableArray *trials; + +// UI +@property (nonatomic, strong) ORKTouchAbilityTapContentView *trialView; + +@end + +@implementation ORKTouchAbilityTapStepViewController + + +#pragma mark - ORKActiveStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = YES; + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKStepResult *)result { + + ORKStepResult *sResult = [super result]; + + NSMutableArray *results = [[NSMutableArray alloc] initWithArray:sResult.results]; + + ORKTouchAbilityTapResult *tapResult = [[ORKTouchAbilityTapResult alloc] initWithIdentifier:self.step.identifier]; + + tapResult.trials = self.trials; + + [results addObject:tapResult]; + sResult.results = [results copy]; + + return sResult; +} + +- (void)finish { + [self.trialView endTrial]; + [super finish]; +} + + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.trials = [NSMutableArray new]; + self.targetPointsQueue = [self targetPointsForTraitCollection:self.traitCollection]; + + self.trialView = [[ORKTouchAbilityTapContentView alloc] init]; + self.trialView.dataSource = self; + self.trialView.delegate = self; + + self.activeStepView.activeCustomView = self.trialView; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + [self.trialView startTrial]; +} + +#pragma mark - ORKTouchAbilityTapStepViewController + +- (NSUInteger)numberOfColumnsForTraitCollection:(UITraitCollection *)traitCollection { + + if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular && + traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) { + return 5; + } else { + return 3; + } +} + +- (NSUInteger)numberOfRowsForTraitCollection:(UITraitCollection *)traitCollection { + + if (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular && + traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular) { + return 5; + } else { + return 3; + } +} + +- (NSMutableArray *)targetPointsForTraitCollection:(UITraitCollection *)traitCollection { + + NSUInteger columns = [self numberOfColumnsForTraitCollection:self.traitCollection]; + NSUInteger rows = [self numberOfRowsForTraitCollection:self.traitCollection]; + + NSMutableArray *points = [NSMutableArray new]; + for (NSUInteger i = 0; i < columns; i++) { + for (NSUInteger j = 0; j < rows; j++) { + CGPoint point = CGPointMake(i, j); + [points addObject:[NSValue valueWithCGPoint:point]]; + } + } + + NSUInteger count = [points count]; + for (NSUInteger i = 0; i < count; i++) { + NSUInteger nElements = count - i; + NSUInteger n = (arc4random() % nElements) + i; + [points exchangeObjectAtIndex:i withObjectAtIndex:n]; + } + + return points; +} + + +#pragma mark - ORKTouchAbilityTapContentViewDataSource + +- (NSUInteger)numberOfColumnsInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView { + return [self numberOfColumnsForTraitCollection:self.traitCollection]; +} + +- (NSUInteger)numberOfRowsInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView { + return [self numberOfRowsForTraitCollection:self.traitCollection]; +} + +- (NSUInteger)targetColumnInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView { + return [self.targetPointsQueue.lastObject CGPointValue].x; +} + +- (NSUInteger)targetRowInTapContentView:(ORKTouchAbilityTapContentView *)tapContentView { + return [self.targetPointsQueue.lastObject CGPointValue].y; +} + + +#pragma mark - ORKTouchAbilityContentViewDelegate + +- (void)touchAbilityContentViewDidBeginNewTrack:(ORKTouchAbilityContentView *)contentView { + +} + +- (void)touchAbilityContentViewDidCompleteNewTracks:(ORKTouchAbilityContentView *)contentView { + + [self.targetPointsQueue removeLastObject]; + + // Calculate current progress and display using progress view. + + NSUInteger total = [self numberOfColumnsForTraitCollection:self.traitCollection] * [self numberOfRowsForTraitCollection:self.traitCollection]; + NSUInteger done = total - self.targetPointsQueue.count; + CGFloat progress = (CGFloat)done/(CGFloat)total; + + [contentView setProgress:progress animated:YES]; + + // Animate the target view. + + ORKWeakTypeOf(contentView) weakContentView = contentView; + [contentView setContentViewHidden:YES animated:YES completion:^(BOOL finished) { + ORKStrongTypeOf(contentView) strongContentView = weakContentView; + + // Stop tracking new touch events. + + [strongContentView endTrial]; + + [self.trials addObject:(ORKTouchAbilityTapTrial *)strongContentView.trial]; + + // Determind if should continue or finish. + + if (self.targetPointsQueue.count > 0) { + + // Reload and start tracking again. + [strongContentView reloadData]; + [strongContentView setContentViewHidden:NO animated:NO]; + [strongContentView startTrial]; + + } else { + + // Finish step. + [self finish]; + } + + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.h new file mode 100755 index 0000000..1227e2e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKTouchAbilityTrial.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTapTrial : ORKTouchAbilityTrial + +@property (nonatomic, assign) CGRect targetFrameInWindow; +@property (nonatomic, assign) BOOL success; + +- (instancetype)initWithTargetFrameInWindow:(CGRect)targetFrame; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.m new file mode 100755 index 0000000..3961a73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTapTrial.m @@ -0,0 +1,98 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTapTrial.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTouchAbilityTapTrial + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_CGRECT(aCoder, targetFrameInWindow); + ORK_ENCODE_BOOL(aCoder, success); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_CGRECT(aDecoder, targetFrameInWindow); + ORK_DECODE_BOOL(aDecoder, success); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTapTrial *trial = [super copyWithZone:zone]; + trial.targetFrameInWindow = self.targetFrameInWindow; + trial.success = self.success; + return trial; +} + +- (BOOL)isEqual:(id)object { + + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + + return (isParentSame && + CGRectEqualToRect(self.targetFrameInWindow, castObject.targetFrameInWindow) && + self.success == castObject.success); +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.targetFrameInWindow = CGRectZero; + self.success = NO; + } + return self; +} + +- (instancetype)initWithTargetFrameInWindow:(CGRect)targetFrame { + self = [super init]; + if (self) { + self.targetFrameInWindow = targetFrame; + self.success = NO; + } + return self; +} + +- (NSString *)description { + + NSMutableString *sDescription = [[super description] mutableCopy]; + [sDescription deleteCharactersInRange:NSMakeRange(0, 1)]; + [sDescription deleteCharactersInRange:NSMakeRange(sDescription.length-1, 1)]; + + return [NSString stringWithFormat:@"<%@; target frame: %@; success: %@>", sDescription, [NSValue valueWithCGRect:self.targetFrameInWindow], self.success ? @"true" : @"false"]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.h new file mode 100755 index 0000000..ac5daba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKTouchAbilityTouch` class is a reflection of `UITouch` class. + + All of the location, azimuth and altitudeAngle properties are relative to the touch's window. + */ +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTouch: NSObject + + +/** + An ISO 8601 UNIX timestamp indicating the time of the touch. + + `ORKTouchAbilityTouch` convert `UITouch.timestamp` to UNIX timestamp automatically. The timestamp property of `UITouch` is relative to system uptime. + + @code ORKTouchAbilityTouch.timestamp = UITouch.timestamp + [NSDate dateWithTimeIntervalSinceNow:-[[NSProcessInfo processInfo] systemUptime]].timeIntervalSince1970; + */ +@property(nonatomic, readonly) NSTimeInterval timestamp; +@property(nonatomic, readonly) UITouchPhase phase; +@property(nonatomic, readonly) NSUInteger tapCount; +@property(nonatomic, readonly) UITouchType type; + +@property(nonatomic, readonly) CGFloat majorRadius; +@property(nonatomic, readonly) CGFloat majorRadiusTolerance; + +@property(nonatomic, readonly) CGPoint locationInWindow; +@property(nonatomic, readonly) CGPoint previousLocationInWindow; +@property(nonatomic, readonly) CGPoint preciseLocationInWindow; +@property(nonatomic, readonly) CGPoint precisePreviousLocationInWindow; + +/** + Force of the touch, where 1.0 represents the force of an average touch + */ +@property(nonatomic, readonly) CGFloat force; + +/** + Maximum possible force with this input mechanism + */ +@property(nonatomic, readonly) CGFloat maximumPossibleForce; + +/** + Azimuth angle relative to the touch's window. + Valid only for stylus touch types. Zero radians points along the positive X axis. + */ +@property(nonatomic, readonly) CGFloat azimuthAngleInWindow; + +/** + A unit vector relative to the touch's window that points in the direction of the azimuth angle. + Valid only for stylus touch types. + */ +@property(nonatomic, readonly) CGVector azimuthUnitVectorInWindow; + +/** + Altitude angle. Valid only for stylus touch types. + Zero radians indicates that the stylus is parallel to the screen surface, + while M_PI/2 radians indicates that it is normal to the screen surface. + */ +@property(nonatomic, readonly) CGFloat altitudeAngle; + +/** + An index which allows you to correlate updates with the original touch. + Is only guaranteed non-nil if this UITouch expects or is an update. + */ +@property(nonatomic, readonly) NSNumber * _Nullable estimationUpdateIndex; + +/** + A set of properties that has estimated values + Only denoting properties that are currently estimated + */ +@property(nonatomic, readonly) UITouchProperties estimatedProperties; + +/** + A set of properties that expect to have incoming updates in the future. + If no updates are expected for an estimated property the current value is our final estimate. + This happens e.g. for azimuth/altitude values when entering from the edges + */ +@property(nonatomic, readonly) UITouchProperties estimatedPropertiesExpectingUpdates; + + +/** + Initialize an `ORKTouchAbilityTouch` object with an `UITouch`. + + @param touch The `UITouch` object it reflects. + @return An `ORKTouchAbilityTouch` object. + */ +- (instancetype)initWithUITouch:(UITouch *)touch; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.m new file mode 100755 index 0000000..3358b5b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouch.m @@ -0,0 +1,222 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTouch.h" +#import "ORKHelpers_Internal.h" + +@interface ORKTouchAbilityTouch () + +@property(nonatomic, assign) NSTimeInterval timestamp; +@property(nonatomic, assign) UITouchPhase phase; +@property(nonatomic, assign) NSUInteger tapCount; +@property(nonatomic, assign) UITouchType type; + +@property(nonatomic, assign) CGFloat majorRadius; +@property(nonatomic, assign) CGFloat majorRadiusTolerance; + +@property(nonatomic, assign) CGPoint locationInWindow; +@property(nonatomic, assign) CGPoint previousLocationInWindow; +@property(nonatomic, assign) CGPoint preciseLocationInWindow; +@property(nonatomic, assign) CGPoint precisePreviousLocationInWindow; + +@property(nonatomic, assign) CGFloat force; +@property(nonatomic, assign) CGFloat maximumPossibleForce; + +@property(nonatomic, assign) CGFloat azimuthAngleInWindow; +@property(nonatomic, assign) CGVector azimuthUnitVectorInWindow; +@property(nonatomic, assign) CGFloat altitudeAngle; + +@property(nonatomic, copy) NSNumber * _Nullable estimationUpdateIndex; +@property(nonatomic, assign) UITouchProperties estimatedProperties; +@property(nonatomic, assign) UITouchProperties estimatedPropertiesExpectingUpdates; + +@end + +@implementation ORKTouchAbilityTouch + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_ENUM(aCoder, phase); + ORK_ENCODE_INTEGER(aCoder, tapCount); + ORK_ENCODE_ENUM(aCoder, type); + ORK_ENCODE_DOUBLE(aCoder, majorRadius); + ORK_ENCODE_DOUBLE(aCoder, majorRadiusTolerance); + ORK_ENCODE_CGPOINT(aCoder, locationInWindow); + ORK_ENCODE_CGPOINT(aCoder, previousLocationInWindow); + ORK_ENCODE_CGPOINT(aCoder, preciseLocationInWindow); + ORK_ENCODE_CGPOINT(aCoder, precisePreviousLocationInWindow); + ORK_ENCODE_DOUBLE(aCoder, force); + ORK_ENCODE_DOUBLE(aCoder, maximumPossibleForce); + ORK_ENCODE_DOUBLE(aCoder, azimuthAngleInWindow); + + [aCoder encodeCGVector:self.azimuthUnitVectorInWindow forKey:@ORK_STRINGIFY(azimuthUnitVectorInWindow)]; + + ORK_ENCODE_DOUBLE(aCoder, altitudeAngle); + + if (self.estimationUpdateIndex) { + ORK_ENCODE_OBJ(aCoder, estimationUpdateIndex); + } + + ORK_ENCODE_INTEGER(aCoder, estimatedProperties); + ORK_ENCODE_INTEGER(aCoder, estimatedPropertiesExpectingUpdates); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_ENUM(aDecoder, phase); + ORK_DECODE_INTEGER(aDecoder, tapCount); + ORK_DECODE_ENUM(aDecoder, type); + ORK_DECODE_DOUBLE(aDecoder, majorRadius); + ORK_DECODE_DOUBLE(aDecoder, majorRadiusTolerance); + ORK_DECODE_CGPOINT(aDecoder, locationInWindow); + ORK_DECODE_CGPOINT(aDecoder, previousLocationInWindow); + ORK_DECODE_CGPOINT(aDecoder, preciseLocationInWindow); + ORK_DECODE_CGPOINT(aDecoder, precisePreviousLocationInWindow); + ORK_DECODE_DOUBLE(aDecoder, force); + ORK_DECODE_DOUBLE(aDecoder, maximumPossibleForce); + ORK_DECODE_DOUBLE(aDecoder, azimuthAngleInWindow); + + self.azimuthUnitVectorInWindow = [aDecoder decodeCGVectorForKey:@ORK_STRINGIFY(azimuthUnitVectorInWindow)]; + + ORK_DECODE_DOUBLE(aDecoder, altitudeAngle); + ORK_DECODE_OBJ(aDecoder, estimationUpdateIndex); + ORK_DECODE_INTEGER(aDecoder, estimatedProperties); + ORK_DECODE_INTEGER(aDecoder, estimatedPropertiesExpectingUpdates); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTouch *touch = [[[self class] allocWithZone:zone] init]; + touch.timestamp = self.timestamp; + touch.phase = self.phase; + touch.tapCount = self.tapCount; + touch.type = self.type; + touch.majorRadius = self.majorRadius; + touch.majorRadiusTolerance = self.majorRadiusTolerance; + touch.locationInWindow = self.locationInWindow; + touch.previousLocationInWindow = self.previousLocationInWindow; + touch.preciseLocationInWindow = self.preciseLocationInWindow; + touch.precisePreviousLocationInWindow = self.precisePreviousLocationInWindow; + touch.force = self.force; + touch.maximumPossibleForce = self.maximumPossibleForce; + touch.azimuthAngleInWindow = self.azimuthAngleInWindow; + touch.azimuthUnitVectorInWindow = self.azimuthUnitVectorInWindow; + touch.altitudeAngle = self.altitudeAngle; + touch.estimationUpdateIndex = [self.estimationUpdateIndex copy]; + touch.estimatedProperties = self.estimatedProperties; + touch.estimatedPropertiesExpectingUpdates = self.estimatedPropertiesExpectingUpdates; + return touch; +} + +- (instancetype)initWithUITouch:(UITouch *)touch { + self = [super init]; + if (self) { + self.timestamp = touch.timestamp + [NSDate dateWithTimeIntervalSinceNow:-[[NSProcessInfo processInfo] systemUptime]].timeIntervalSince1970; + self.phase = touch.phase; + self.tapCount = touch.tapCount; + self.type = touch.type; + self.majorRadius = touch.majorRadius; + self.majorRadiusTolerance = touch.majorRadiusTolerance; + self.locationInWindow = [touch locationInView:nil]; + self.previousLocationInWindow = [touch previousLocationInView:nil]; + self.preciseLocationInWindow = [touch preciseLocationInView:nil]; + self.precisePreviousLocationInWindow = [touch precisePreviousLocationInView:nil]; + self.force = touch.force; + self.maximumPossibleForce = touch.maximumPossibleForce; + self.azimuthAngleInWindow = [touch azimuthAngleInView:nil]; + self.azimuthUnitVectorInWindow = [touch azimuthUnitVectorInView:nil]; + self.altitudeAngle = touch.altitudeAngle; + self.estimationUpdateIndex = touch.estimationUpdateIndex; + self.estimatedProperties = touch.estimatedProperties; + self.estimatedPropertiesExpectingUpdates = touch.estimatedPropertiesExpectingUpdates; + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.timestamp == castObject.timestamp) && + (self.phase == castObject.phase) && + (self.tapCount == castObject.tapCount) && + (self.type == castObject.type) && + (self.majorRadius == castObject.majorRadius) && + (self.majorRadiusTolerance == castObject.majorRadius) && + CGPointEqualToPoint(self.locationInWindow, castObject.locationInWindow) && + CGPointEqualToPoint(self.previousLocationInWindow, castObject.previousLocationInWindow) && + CGPointEqualToPoint(self.preciseLocationInWindow, castObject.preciseLocationInWindow) && + CGPointEqualToPoint(self.precisePreviousLocationInWindow, castObject.precisePreviousLocationInWindow) & + (self.force == castObject.force) && + (self.maximumPossibleForce == castObject.maximumPossibleForce) && + (self.azimuthAngleInWindow == castObject.azimuthAngleInWindow) && + (self.azimuthUnitVectorInWindow.dx == castObject.azimuthUnitVectorInWindow.dx) && + (self.azimuthUnitVectorInWindow.dy == castObject.azimuthUnitVectorInWindow.dy) && + (self.altitudeAngle == castObject.altitudeAngle) && + ORKEqualObjects(self.estimationUpdateIndex, castObject.estimationUpdateIndex) && + (self.estimatedProperties == castObject.estimatedProperties) && + (self.estimatedPropertiesExpectingUpdates == castObject.estimatedPropertiesExpectingUpdates)); +} + +- (NSString *)description { + NSString *phaseString; + switch (self.phase) { + case UITouchPhaseBegan: + phaseString = @"began"; + break; + case UITouchPhaseMoved: + phaseString = @"moved"; + break; + case UITouchPhaseEnded: + phaseString = @"ended"; + break; + case UITouchPhaseCancelled: + phaseString = @"cancelled"; + break; + case UITouchPhaseStationary: + phaseString = @"stationary"; + break; + } + + return [NSString stringWithFormat:@"<%@: %p; phase: %@; timestamp: %.6f; location: (%@, %@)>", self.class.description, self, phaseString, self.timestamp, @(self.locationInWindow.x), @(self.locationInWindow.y)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.h new file mode 100755 index 0000000..f71bd58 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.h @@ -0,0 +1,67 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - ORKTouchAbilityTouchTrackerDelegate + +@class ORKTouchAbilityTouchTracker; +@protocol ORKTouchAbilityTouchTrackerDelegate + +@required +- (void)touchTrackerDidBeginNewTrack:(ORKTouchAbilityTouchTracker *)touchTracker; +- (void)touchTrackerDidCompleteNewTracks:(ORKTouchAbilityTouchTracker *)touchTracker; + +@end + + +#pragma mark - ORKTouchAbilityTouchTracker + +@class ORKTouchAbilityTrack; +@interface ORKTouchAbilityTouchTracker : UIGestureRecognizer + +@property (nonatomic, strong) NSMutableArray *tracks; +@property (nonatomic, assign, getter=isTracking) BOOL tracking; + +@property (nonatomic, weak) id _Nullable delegate; + +- (void)startTracking; +- (void)stopTracking; +- (void)resetTracks; + +@end + + + + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.m new file mode 100755 index 0000000..8c94ac4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTouchTracker.m @@ -0,0 +1,205 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTouchTracker.h" +#import "ORKTouchAbilityTouch.h" +#import "ORKTouchAbilityTrack.h" +#import "ORKTouchAbilityTrack_Internal.h" + + +@interface ORKTouchAbilityTouchTracker () +@property (nonatomic, assign, getter=hasBegun) BOOL begun; +@end + + + +@implementation ORKTouchAbilityTouchTracker + + +#pragma mark - Properties + +@dynamic delegate; + +- (NSMutableArray *)tracks { + if (!_tracks) { + _tracks = [NSMutableArray new]; + } + return _tracks; +} + + +#pragma mark - Life Cycle + +- (instancetype)init { + if (self = [super init]) { + self.tracking = NO; + self.cancelsTouchesInView = NO; + } + return self; +} + +- (instancetype)initWithTarget:(id)target action:(SEL)action { + if (self = [super initWithTarget:target action:action]) { + self.tracking = NO; + self.cancelsTouchesInView = NO; + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; tracking: %@; tracks count: %@;>", + self.class.description, + self, + self.isTracking ? @"true" : @"false", + @(self.tracks.count)]; +} + + +#pragma mark - ORKTouchAbilityTouchTracker + +- (void)startTracking { + [self resetTracks]; + self.tracking = YES; +} + +- (void)stopTracking { + self.begun = NO; + self.tracking = NO; +} + +- (void)resetTracks { + self.begun = NO; + [self.tracks removeAllObjects]; +} + + +#pragma mark - UIGestureRecognizer + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesBegan:touches withEvent:event]; + + if (self.isTracking == NO) { + return; + } + + self.begun = YES; + + if ([self.delegate respondsToSelector:@selector(touchTrackerDidBeginNewTrack:)]) { + [self.delegate touchTrackerDidBeginNewTrack:self]; + } + + for (UITouch *touch in touches) { + + ORKTouchAbilityTrack *track = [[ORKTouchAbilityTrack alloc] init]; + track.touches = [NSArray arrayWithObject:[[ORKTouchAbilityTouch alloc] initWithUITouch:touch]]; + + [self.tracks addObject:track]; + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesMoved:touches withEvent:event]; + + if (self.isTracking == NO || self.hasBegun == NO) { + return; + } + + [self addTouchesToTracks:touches withEvent:event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesEnded:touches withEvent:event]; + + if (self.isTracking == NO || self.hasBegun == NO) { + return; + } + + [self addTouchesToTracks:touches withEvent:event]; + + if (event.allTouches.count == touches.count) { + if ([self.delegate respondsToSelector:@selector(touchTrackerDidCompleteNewTracks:)]) { + [self.delegate touchTrackerDidCompleteNewTracks:self]; + } + } +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [super touchesCancelled:touches withEvent:event]; + + if (self.isTracking == NO || self.hasBegun == NO) { + return; + } + + [self addTouchesToTracks:touches withEvent:event]; + + if (event.allTouches.count == touches.count) { + if ([self.delegate respondsToSelector:@selector(touchTrackerDidCompleteNewTracks:)]) { + [self.delegate touchTrackerDidCompleteNewTracks:self]; + } + } +} + + +#pragma mark - Private Methods + +- (void)addTouchesToTracks:(NSSet *)touches withEvent:(UIEvent *)event { + + for (UITouch *touch in touches) { + + NSArray *coalescedTouches = [event coalescedTouchesForTouch:touch] ?: [NSArray arrayWithObject:touch]; + NSMutableArray *translatedTouches = [NSMutableArray new]; + + for (UITouch *coalescedTouch in coalescedTouches) { + [translatedTouches addObject:[[ORKTouchAbilityTouch alloc] initWithUITouch:coalescedTouch]]; + } + + + for (ORKTouchAbilityTrack *track in self.tracks) { + + if (track.touches.count == 0) { + continue; + } + + ORKTouchAbilityTouch *lastTouch = track.touches.lastObject; + ORKTouchAbilityTouch *firstTranslatedTouch = translatedTouches.firstObject; + + if (lastTouch.phase != UITouchPhaseEnded && + CGPointEqualToPoint(lastTouch.locationInWindow, firstTranslatedTouch.previousLocationInWindow)) { + + NSMutableArray *trackTouches = [NSMutableArray arrayWithArray:track.touches]; + [trackTouches addObjectsFromArray:translatedTouches]; + track.touches = trackTouches; + } + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.h new file mode 100755 index 0000000..98e55c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityTouch; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTrack: NSObject +@property(nonatomic, readonly) NSArray *touches; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.m new file mode 100755 index 0000000..4aac524 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack.m @@ -0,0 +1,88 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTrack.h" +#import "ORKTouchAbilityTrack_Internal.h" +#import "ORKTouchAbilityTouch.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTouchAbilityTrack + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, touches); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ(aDecoder, touches); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTrack *track = [[[self class] allocWithZone:zone] init]; + track.touches = [self.touches copy]; + return track; +} + +- (BOOL)isEqual:(id)object { + + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ORKEqualObjects(self.touches, castObject.touches); +} + +- (NSUInteger)hash { + return super.hash ^ self.touches.hash; +} + +- (NSArray *)touches { + if (!_touches) { + _touches = [NSArray new]; + } + return _touches; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; touches: %@>", self.class.description, self, self.touches]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack_Internal.h new file mode 100755 index 0000000..4537e24 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrack_Internal.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityTrack () +@property(nonatomic, copy) NSArray *touches; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.h new file mode 100755 index 0000000..2ca8722 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTouchAbilityTrack; +@class ORKTouchAbilityGestureRecoginzerEvent; + +ORK_CLASS_AVAILABLE +@interface ORKTouchAbilityTrial : NSObject + +@property (nonatomic, strong) NSDate *startDate; +@property (nonatomic, strong) NSDate *endDate; + +@property (nonatomic, readonly) NSArray *tracks; +@property (nonatomic, readonly) NSArray *gestureRecognizerEvents; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.m new file mode 100755 index 0000000..359cdec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial.m @@ -0,0 +1,125 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAbilityTrial.h" +#import "ORKTouchAbilityTrial_Internal.h" +#import "ORKTouchAbilityTrack.h" +#import "ORKTouchAbilityGestureRecoginzerEvent.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKTouchAbilityTrial + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, startDate); + ORK_ENCODE_OBJ(aCoder, endDate); + ORK_ENCODE_OBJ(aCoder, tracks); + ORK_ENCODE_OBJ(aCoder, gestureRecognizerEvents); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ(aDecoder, startDate); + ORK_DECODE_OBJ(aDecoder, endDate); + ORK_DECODE_OBJ(aDecoder, tracks); + ORK_DECODE_OBJ(aDecoder, gestureRecognizerEvents); + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTouchAbilityTrial *trial = [[[self class] allocWithZone:zone] init]; + trial.startDate = [self.startDate copy]; + trial.endDate = [self.endDate copy]; + trial.tracks = [self.tracks copy]; + trial.gestureRecognizerEvents = [self.gestureRecognizerEvents copy]; + return trial; +} + +- (BOOL)isEqual:(id)object { + + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return (ORKEqualObjects(self.startDate, castObject.startDate) && + ORKEqualObjects(self.endDate, castObject.endDate) && + ORKEqualObjects(self.tracks, castObject.tracks) && + ORKEqualObjects(self.gestureRecognizerEvents, castObject.gestureRecognizerEvents)); +} + +- (NSDate *)startDate { + if (!_startDate) { + _startDate = [NSDate distantPast]; + } + return _startDate; +} + +- (NSDate *)endDate { + if (!_endDate) { + _endDate = [NSDate distantFuture]; + } + return _endDate; +} + +- (NSArray *)tracks { + if (!_tracks) { + _tracks = [NSArray new]; + } + return _tracks; +} + +- (NSArray *)gestureRecoginzerEvents { + if (!_gestureRecognizerEvents) { + _gestureRecognizerEvents = [NSArray new]; + } + return _gestureRecognizerEvents; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; start: %@; end: %@; tracks count: %@; gesture recognizer events count: %@>", + self.class.description, + self, + self.startDate, + self.endDate, + @(self.tracks.count), + @(self.gestureRecognizerEvents.count)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial_Internal.h new file mode 100755 index 0000000..d7d45eb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAbilityTrial_Internal.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2018, Muh-Tarng Lin. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTouchAbilityTrial () + +@property (nonatomic, copy) NSArray *tracks; +@property (nonatomic, copy) NSArray *gestureRecognizerEvents; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.h new file mode 100755 index 0000000..d240b8c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKTouchAnywhereStep` class represents a step that displays a title with custom instructions + and the text "Touch anywhere to continue." The user can touch almost anywhere on the + screen and the step will end and the task will continue. The back button is still + tappable. + */ +ORK_CLASS_AVAILABLE +@interface ORKTouchAnywhereStep : ORKActiveStep + +- (instancetype)init NS_UNAVAILABLE; + +/** + Init with an identifier and instruction text. Instruction text should be used to tell the user + where to place the device before touching anywhere. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier instructionText:(NSString *)instructionText; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.m new file mode 100755 index 0000000..1323f6b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStep.m @@ -0,0 +1,52 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAnywhereStep.h" +#import "ORKTouchAnywhereStepViewController.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTouchAnywhereStep + ++ (Class)stepViewControllerClass { + return [ORKTouchAnywhereStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier instructionText:(NSString *)instructionText { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldStartTimerAutomatically = YES; + self.text = [instructionText stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"TOUCH_ANYWHERE_LABEL", nil)]]; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.h new file mode 100755 index 0000000..b65a841 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTouchAnywhereStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.m new file mode 100755 index 0000000..335bf87 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchAnywhereStepViewController.m @@ -0,0 +1,131 @@ +/* + Copyright (c) 2016, Darren Levy. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchAnywhereStepViewController.h" +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKLabel.h" +#import "ORKActiveStepView.h" +#import "ORKProgressView.h" +#import "ORKSkin.h" + + +@interface ORKTouchAnywhereView : ORKActiveStepCustomView { + NSLayoutConstraint *_topConstraint; +} + +@property (nonatomic, strong) UIView *progressView; + +@end + + +@implementation ORKTouchAnywhereView + +- (instancetype)init { + self = [super init]; + if (self) { + _progressView = [ORKProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_progressView]; + + [self setUpConstraints]; + [self updateConstraintConstantsForWindow:self.window]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView); + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_progressView]-(>=0)-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + _topConstraint = [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; // constant will be set in updateConstraintConstantsForWindow: + [constraints addObject:_topConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + const CGFloat CaptionBaselineToProgressTop = 100; + const CGFloat CaptionBaselineToStepViewTop = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTop, window); + _topConstraint.constant = CaptionBaselineToProgressTop - CaptionBaselineToStepViewTop; +} + +@end + + +@interface ORKTouchAnywhereStepViewController () + +@property (nonatomic, strong) ORKTouchAnywhereView *touchAnywhereView; +@property (nonatomic, strong) UITapGestureRecognizer *gestureRecognizer; + +@end + + +@implementation ORKTouchAnywhereStepViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + _touchAnywhereView = [[ORKTouchAnywhereView alloc] init]; + _touchAnywhereView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _touchAnywhereView; + + _gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; + [self.activeStepView addGestureRecognizer:_gestureRecognizer]; + self.internalContinueButtonItem = nil; +} + +- (void)handleTap:(UIGestureRecognizer *)sender { + [self goForward]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.h new file mode 100755 index 0000000..cbf8915 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKTouchRecorder` class defines the attributes and behavior of touch events recorder. + + This class is considered private because its interface is not yet considered + stable. It is not currently used by any of the pre-defined active tasks. + */ +ORK_CLASS_AVAILABLE +@interface ORKTouchRecorder : ORKRecorder + +/** + The `ORKTouchRecorder` attaches a gesture recognizer to `touchView` to receive touch events. + + Use `-viewController:willStartStepWithView:` to set the `touchView` property before + the touch recorder starts. + */ +@property (nonatomic, strong, readonly, nullable) UIView *touchView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.m new file mode 100755 index 0000000..77f421f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTouchRecorder.m @@ -0,0 +1,230 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTouchRecorder.h" + +#import "ORKDataLogger.h" + +#import "ORKRecorder_Internal.h" + +#import "UITouch+ORKJSONDictionary.h" + + +@protocol ORKTouchRecordingDelegate + +- (void)view:(UIView *)view didDetectTouch:(UITouch *)touch; + +@end + + +@interface ORKTouchGestureRecognizer : UIGestureRecognizer + +@property (nonatomic, weak) id eventDelegate; + +@end + + +@implementation ORKTouchGestureRecognizer + +- (void)reportTouches:(NSSet *)touches { + + for (UITouch *touch in touches) { + [self.eventDelegate view:self.view didDetectTouch:touch]; + } +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self reportTouches:touches]; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self reportTouches:touches]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self reportTouches:touches]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + [self reportTouches:touches]; +} + +@end + + +@interface ORKTouchRecordingView : UIView + +@property (nonatomic, weak) id delegate; + +@end + + +@interface ORKTouchRecorder () { + ORKDataLogger *_logger; +} + +@property (nonatomic, strong) ORKTouchGestureRecognizer *gestureRecognizer; + +@property (nonatomic, strong) NSMutableArray *touchArray; + +@property (nonatomic) NSTimeInterval uptime; + +@property (nonatomic, strong) NSError *recordingError; + +@end + + +@implementation ORKTouchRecorder + +- (void)dealloc { + [_logger finishCurrentLog]; +} + +- (void)viewController:(UIViewController *)viewController willStartStepWithView:(UIView *)view { + if (self.isRecording == NO) { + _touchView = view; + } +} + +- (void)start { + if (!_logger) { + NSError *error = nil; + _logger = [self makeJSONDataLoggerWithError:&error]; + if (!_logger) { + [self finishRecordingWithError:error]; + return; + } + } + + if (self.touchView) { + [self.touchView addGestureRecognizer:self.gestureRecognizer]; + + [super start]; + + self.touchArray = [NSMutableArray array]; + _uptime = [NSProcessInfo processInfo].systemUptime; + } else { + @throw [NSException exceptionWithName:NSGenericException + reason:@"No touch capture view provided" + userInfo:@{@"recorder": self}]; + } +} + +- (ORKTouchGestureRecognizer *)gestureRecognizer { + if (_gestureRecognizer == nil) { + _gestureRecognizer = [ORKTouchGestureRecognizer new]; + _gestureRecognizer.eventDelegate = self; + } + return _gestureRecognizer; +} + +- (void)stop { + [self doStopRecording]; + [_logger finishCurrentLog]; + + NSError *error = nil; + __block NSURL *fileUrl = nil; + [_logger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + fileUrl = logFileUrl; + } error:&error]; + + [self reportFileResultWithFile:fileUrl error:error]; + + [super stop]; +} + +- (void)doStopRecording { + if (_touchView) { + [self.touchView removeGestureRecognizer:self.gestureRecognizer]; + _touchView = nil; + } +} + +- (void)finishRecordingWithError:(NSError *)error { + [self doStopRecording]; + [super finishRecordingWithError:error]; +} + +- (NSString *)recorderType { + return @"touch"; +} + +- (NSString *)mimeType { + return @"application/json"; +} + +- (void)reset { + [super reset]; + + _logger = nil; +} + +#pragma mark - ORKTouchRecordingDelegate + +- (void)view:(UIView *)view didDetectTouch:(UITouch *)touch { + + if ([self.touchArray containsObject:touch] == NO) { + [self.touchArray addObject:touch]; + } + + NSError *error = nil; + if (![_logger append:[touch ork_JSONDictionaryInView:view allTouches:self.touchArray] error:&error]) { + assert(error != nil); + [self finishRecordingWithError:error]; + } +} + +@end + + +@implementation ORKTouchRecorderConfiguration + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [super initWithIdentifier:identifier]; +} + +- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory { + ORKTouchRecorder *recorder = [[ORKTouchRecorder alloc] initWithIdentifier:self.identifier + step:step + outputDirectory:outputDirectory]; + return recorder; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + return [super initWithCoder:aDecoder]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.h new file mode 100755 index 0000000..6a2f133 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.h @@ -0,0 +1,113 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTowerOfHanoiMove; + + +/** + The `ORKTowerOfHanoiResult` class records the results of a Tower of Hanoi active task. + + An `ORKTowerOfHanoiResult` object records an array of `ORKTowerOfHanoiMove` objects (one for each move) + and a Boolean value representing whether the puzzle was solved or not. + + An `ORKTowerOfHanoiResult` object is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTowerOfHanoiResult : ORKResult + +/** + A Boolean value indicating whether the puzzle was solved. + + The value of this property is `YES` when the puzzle was solved and `NO` otherwise. + */ +@property (nonatomic, assign) BOOL puzzleWasSolved; + +/** + An array of moves, in which each item is an `ORKTowerOfHanoiMove` object that represents a move. + */ +@property (nonatomic, copy, nullable) NSArray *moves; + +@end + + +/** + The `ORKTowerOfHanoiMove` class represents a single move in a Tower of Hanoi puzzle. + + The Tower of Hanoi move object records the indexes of the donor and recipient towers + and the time at which the event occurred. A `towerOfHanoiMove` instance is included in + an `ORKTowerOfHanoiResult` object and is recorded by the step view controller for the + corresponding task when a move is made. + + A Tower of Hanoi move is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize the move for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTowerOfHanoiMove : NSObject + +/** + A relative timestamp indicating the time of the tap event. + + The timestamp is relative to the value of `startDate` in the `ORKResult` object that includes this move. + The start date of that object represents the time at which the first move was made. + */ +@property (nonatomic, assign) NSTimeInterval timestamp; + +/** + The index of the donor tower in the move. + + The Tower of Hanoi puzzle has three towers, and so the value of this property is + therefore always 0, 1, or 2. The indexes sequentially represent the towers from left to right when they are laid out + horizontally and from top to bottom when they are layed out vertically. The index for a given tower is consistent + between changes to and from the horizontal and vertical layouts. + */ +@property (nonatomic,assign) NSUInteger donorTowerIndex; + +/** + The index of the recipient tower in the move. + + The Tower of Hanoi puzzle has three towers, and so the value of this property is + therefore always 0, 1, or 2. The indexes sequentially represent the towers from left to right when they are laid out + horizontally and from top to bottom when they are layed out vertically. The index for a given tower is consistent + between changes to and from the horizontal and vertical layouts. + */ +@property (nonatomic,assign) NSUInteger recipientTowerIndex; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.m new file mode 100755 index 0000000..2006294 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiResult.m @@ -0,0 +1,132 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTowerOfHanoiResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTowerOfHanoiResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, moves); + ORK_ENCODE_BOOL(aCoder, puzzleWasSolved); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, moves, ORKTowerOfHanoiMove); + ORK_DECODE_BOOL(aDecoder, puzzleWasSolved); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return isParentSame && + self.puzzleWasSolved == castObject.puzzleWasSolved && + ORKEqualObjects(self.moves, castObject.moves); +} + +- (NSUInteger)hash { + return super.hash ^ self.puzzleWasSolved ^ self.moves.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTowerOfHanoiResult *result = [super copyWithZone:zone]; + result.puzzleWasSolved = self.puzzleWasSolved; + result.moves = [self.moves copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; puzzleSolved: %d; moves: %@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.puzzleWasSolved, self.moves, self.descriptionSuffix]; +} + +@end + + +@implementation ORKTowerOfHanoiMove + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_INTEGER(aCoder, donorTowerIndex); + ORK_ENCODE_INTEGER(aCoder, recipientTowerIndex); + +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_INTEGER(aDecoder, donorTowerIndex); + ORK_DECODE_INTEGER(aDecoder, recipientTowerIndex); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return self.timestamp == castObject.timestamp && + self.donorTowerIndex == castObject.donorTowerIndex && + self.recipientTowerIndex == castObject.recipientTowerIndex; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTowerOfHanoiMove *move = [[[self class] allocWithZone:zone] init]; + move.timestamp = self.timestamp; + move.donorTowerIndex = self.donorTowerIndex; + move.recipientTowerIndex = self.recipientTowerIndex; + return move; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; timestamp: %@; donorTower: %@; recipientTower: %@>", self.class.description, self, @(self.timestamp), @(self.donorTowerIndex), @(self.recipientTowerIndex)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.h new file mode 100755 index 0000000..21ddf6f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Tower of Hanoi step. + + This step is used to present the interactive Tower of Hanoi activity. + */ +ORK_CLASS_AVAILABLE +@interface ORKTowerOfHanoiStep : ORKActiveStep + +/** + The number of disks in the puzzle. + + It is not recommended that you use a large number of disks. As this provides a poor user experience. + The default value of this property is 3. + */ +@property (nonatomic, assign) NSUInteger numberOfDisks; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.m new file mode 100755 index 0000000..f072c65 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStep.m @@ -0,0 +1,106 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTowerOfHanoiStep.h" + +#import "ORKTowerOfHanoiStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +static const NSUInteger MaximumNumberOfDisks = 8; + +@implementation ORKTowerOfHanoiStep + ++ (Class)stepViewControllerClass { + return [ORKTowerOfHanoiViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.optional = YES; + self.numberOfDisks = 3; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfDisks); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfDisks); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTowerOfHanoiStep *step = [super copyWithZone:zone]; + step.numberOfDisks = self.numberOfDisks; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.numberOfDisks == castObject.numberOfDisks)); +} + +- (void)validateParameters { + [super validateParameters]; + if (self.numberOfDisks > MaximumNumberOfDisks) { + ORK_Log_Info("Having a large number of disks provides a poor user experience, consider reducing the number below %@.", @(MaximumNumberOfDisks)); + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (BOOL)startsFinished { + return NO; +} + +- (BOOL)shouldContinueOnFinish { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.h new file mode 100755 index 0000000..9ef9e72 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" +#import "ORKActiveStepViewController.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTowerOfHanoiViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.m new file mode 100755 index 0000000..efe1848 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiStepViewController.m @@ -0,0 +1,363 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTowerOfHanoiStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKTowerOfHanoiTowerView.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTowerOfHanoiResult.h" +#import "ORKTowerOfHanoiStep.h" +#import "ORKTowerOfHanoiTower.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const NSUInteger NumberOfTowers = 3; + +@interface ORKTowerOfHanoiViewController () + +@property (nonatomic, strong) NSDateComponentsFormatter *dateComponentsFormatter; +@property (nonatomic, strong) NSMutableArray *moves; + +@end + + +@implementation ORKTowerOfHanoiViewController { + ORKActiveStepCustomView *_towerOfHanoiCustomView; + NSNumber *_selectedIndex; + NSArray *_variableConstraints; + NSMutableArray *_towers; + NSArray *_towerViews; + NSTimer *_timer; + NSInteger _secondsElapsed; + NSDate *_firstMoveDate; +} + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + _towerOfHanoiCustomView = [ORKActiveStepCustomView new]; + _towerOfHanoiCustomView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _towerOfHanoiCustomView; + + [self setUpTowers]; + [self setUpTowerViews]; + [self reloadData]; + NSString *title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT", nil); + NSString *text = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_INTRO_TEXT", nil); + [self.activeStepView updateTitle:title text:text]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [_timer invalidate]; +} + +- (void)updateViewConstraints { + [super updateViewConstraints]; + + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + _variableConstraints = nil; + + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + BOOL needCompactLayout = + (self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) && + (self.traitCollection.verticalSizeClass != UIUserInterfaceSizeClassCompact); + _variableConstraints = needCompactLayout ? [self compactConstraints] : [self regularConstraints]; + [NSLayoutConstraint activateConstraints:_variableConstraints]; +} + +#pragma mark - ORKStepViewController + +- (void)skipForward { + [self finish]; +} + +#pragma mark - ORKActiveTaskViewController + +- (ORKResult *)result { + ORKStepResult *stepResult = [super result]; + ORKTowerOfHanoiResult *result = [[ORKTowerOfHanoiResult alloc] initWithIdentifier:self.step.identifier]; + result.moves = self.moves; + result.puzzleWasSolved = [self puzzleIsSolved]; + if (_firstMoveDate != nil) { + result.startDate = _firstMoveDate; + } + stepResult.results = [self.addedResults arrayByAddingObject:result] ? : @[result]; + return stepResult; +} + +#pragma mark - ORKTowerOfHanoiTowerViewDataSource + +- (NSUInteger)numberOfDisksInTowerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView { + NSInteger towerIndex = [_towerViews indexOfObject:towerView]; + ORKTowerOfHanoiTower *tower = _towers[towerIndex]; + return tower.disks.count; +} + +- (NSNumber *)towerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView diskAtIndex:(NSUInteger)index { + NSInteger towerIndex = [_towerViews indexOfObject:towerView]; + ORKTowerOfHanoiTower *tower = _towers[towerIndex]; + return (index >= tower.disks.count) ? nil :tower.disks[index]; +} + +#pragma mark - ORKTowerOfHanoiTowerViewDelegate + +- (void)towerOfHanoiTowerViewWasSelected:(ORKTowerOfHanoiTowerView *)towerView { + NSInteger newSelectedIndex = [_towerViews indexOfObject:towerView]; + if (_selectedIndex == nil) { + _selectedIndex = @(newSelectedIndex); + } + else if ([_selectedIndex isEqual:@(newSelectedIndex)]) { + _selectedIndex = nil; + } else { + [self transferDiskFromTowerAtIndex:_selectedIndex.integerValue toTowerAtIndex:newSelectedIndex]; + } + [self reloadData]; + [self evaluatePuzzle]; +} + +- (ORKTowerOfHanoiTowerView *)towerOfHanoiHighlightedTowerView { + return (_selectedIndex != nil ? _towerViews[_selectedIndex.integerValue] : nil); +} + +#pragma mark - ORKTowerOfHanoiViewController + +- (NSMutableArray *)moves { + if (_moves == nil) { + _moves = [NSMutableArray array]; + } + return _moves; +} + +- (NSDateComponentsFormatter *)dateComponentsFormatter { + if (_dateComponentsFormatter == nil) { + _dateComponentsFormatter = [NSDateComponentsFormatter new]; + _dateComponentsFormatter.unitsStyle = NSDateComponentsFormatterUnitsStylePositional; + _dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad; + _dateComponentsFormatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond; + } + return _dateComponentsFormatter; +} + +- (NSUInteger)numberOfDisks { + return ((ORKTowerOfHanoiStep *)self.step).numberOfDisks; +} + +- (void)updateTitleText { + NSString *moves = ORKLocalizedStringFromNumber(@(self.moves.count)); + NSString *time = [self.dateComponentsFormatter stringFromTimeInterval:_secondsElapsed]; + NSString *title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT", nil); + NSString *text = [NSString localizedStringWithFormat:ORKLocalizedString(@"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT", nil), moves, time]; + [self.activeStepView updateTitle:title text:text]; +} + +- (void)reloadData { + for (ORKTowerOfHanoiTowerView *towerView in _towerViews) { + towerView.highlighted = _selectedIndex != nil && [_towerViews indexOfObject:towerView] == _selectedIndex.integerValue; + [towerView reloadData]; + } +} + +- (BOOL)puzzleIsSolved { + return ((ORKTowerOfHanoiTower *)_towers.lastObject).disks.count == [self numberOfDisks]; +} + +- (void)evaluatePuzzle { + if ([self puzzleIsSolved]) { + [self finish]; + } +} + +- (void)setUpTowers { + NSMutableArray *diskStack = [NSMutableArray array]; + for (NSInteger disk = [self numberOfDisks] ; disk > 0 ; disk--) { + [diskStack addObject: @(disk)]; + } + _towers = [@[[[ORKTowerOfHanoiTower alloc] initWithDisks:diskStack], [ORKTowerOfHanoiTower emptyTower], [ORKTowerOfHanoiTower emptyTower]] mutableCopy]; +} + +- (void)setUpTowerViews { + NSMutableArray *towerViews = [NSMutableArray array]; + for (NSInteger index = 0 ; index < 3 ; index++) { + ORKTowerOfHanoiTowerView *towerView = [[ORKTowerOfHanoiTowerView alloc] initWithFrame:CGRectZero maximumNumberOfDisks:[self numberOfDisks]]; + towerView.delegate = self; + towerView.dataSource = self; + towerView.targeted = (index == NumberOfTowers - 1); + [towerViews addObject:towerView]; + towerView.translatesAutoresizingMaskIntoConstraints = NO; + [_towerOfHanoiCustomView addSubview:towerView]; + } + _towerViews = towerViews; +} + +- (void)transferDiskFromTowerAtIndex:(NSInteger)donorTowerIndex toTowerAtIndex:(NSInteger)recipientTowerIndex { + ORKTowerOfHanoiTower *donorTower = _towers[donorTowerIndex]; + ORKTowerOfHanoiTower *recipientTower = _towers[recipientTowerIndex]; + if ([recipientTower recieveDiskFrom:donorTower]) { + [self makeMoveFromTowerAtIndex:donorTowerIndex toTowerAtIndex:recipientTowerIndex]; + } else { + NSNumber *donorSize = [self towerOfHanoiView:_towerViews[donorTowerIndex] diskAtIndex:0]; + NSNumber *recipientSize = [self towerOfHanoiView:_towerViews[recipientTowerIndex] diskAtIndex:0]; + + if (donorSize && recipientSize) { + // Only announce if the both donor and recipient are valid + NSString *invalidMoveAnnouncement = [NSString stringWithFormat:ORKLocalizedString(@"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT", nil), donorSize.stringValue, recipientSize.stringValue]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, invalidMoveAnnouncement); + }); + } + } +} + +- (void)makeMoveFromTowerAtIndex:(NSUInteger)donorTowerIndex toTowerAtIndex:(NSUInteger)recipientTowerIndex { + ORKTowerOfHanoiMove *move = [[ORKTowerOfHanoiMove alloc] init]; + move.donorTowerIndex = donorTowerIndex; + move.recipientTowerIndex = recipientTowerIndex; + move.timestamp = (self.moves.count == 0) ? 0 : fabs([_firstMoveDate timeIntervalSinceNow]); + [_moves addObject:move]; + [self didMakeMove]; +} + +- (void)didMakeMove { + _selectedIndex = nil; + if (self.moves.count == 1) { + _firstMoveDate = [NSDate date]; + _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerTicked) userInfo:nil repeats:YES]; + } + [self updateTitleText]; +} + +- (void)timerTicked { + _secondsElapsed++; + [self updateTitleText]; +} + +- (NSArray *)compactConstraints { + CGFloat compactWidth = ([[UIScreen mainScreen]bounds].size.height - (3 * 8)) / 3; + NSDictionary *views = @{ @"A": _towerViews[0], @"B": _towerViews[1], @"C": _towerViews[2]}; + NSMutableArray *newConstraints = [NSMutableArray new]; + + [newConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-[A]-[B]-[C]-|"] + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[0] + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_towerViews[1] + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[2] + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_towerViews[1] + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + + for (int index = 0 ; index < _towerViews.count ; index++) { + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[index] + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:compactWidth]]; + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[index] + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_towerOfHanoiCustomView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + } + + return newConstraints; +} + +- (NSArray *)regularConstraints { + NSDictionary *views = @{ @"A": _towerViews[0], @"B": _towerViews[1], @"C": _towerViews[2]}; + NSMutableArray *newConstraints = [NSMutableArray new]; + + [newConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[A]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [newConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[B]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [newConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[C]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [newConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[A]-[B]-[C]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[0] + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_towerViews[1] + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + [newConstraints addObject:[NSLayoutConstraint constraintWithItem:_towerViews[2] + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_towerViews[1] + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + return newConstraints; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.h new file mode 100755 index 0000000..9804dbb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTowerOfHanoiTower : NSObject + +@property (nonatomic, copy, readonly) NSArray *disks; + ++ (instancetype)emptyTower; + +- (instancetype)initWithDisks:(NSArray *)disks; + +- (BOOL)recieveDiskFrom:(ORKTowerOfHanoiTower *)donorTower; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.m new file mode 100755 index 0000000..c337e0b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTower.m @@ -0,0 +1,74 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTowerOfHanoiTower.h" + + +@interface ORKTowerOfHanoiTower () + +@property (nonatomic, copy, readwrite) NSArray *disks; + +@end + + +@implementation ORKTowerOfHanoiTower + ++ (instancetype)emptyTower { + return [[ORKTowerOfHanoiTower alloc]initWithDisks:@[]]; +} + +- (instancetype)initWithDisks:(NSArray *)disks { + self = [super init]; + if (self) { + _disks = disks; + } + return self; +} + +- (BOOL)canRecieveDisk:(NSNumber *)disk { + return _disks.count == 0 || ((NSNumber *)_disks.lastObject).integerValue > disk.integerValue; +} + +- (BOOL)recieveDiskFrom:(ORKTowerOfHanoiTower*)donorTower { + if (donorTower.disks.count == 0 || ![self canRecieveDisk:donorTower.disks.lastObject]) { + return NO; + } + NSMutableArray *recipientDisks = [self.disks mutableCopy]; + NSMutableArray *donorDisks = [donorTower.disks mutableCopy]; + [recipientDisks addObject:donorTower.disks.lastObject]; + [donorDisks removeLastObject]; + self.disks = recipientDisks; + donorTower.disks = donorDisks; + + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.h new file mode 100755 index 0000000..2d8ea9d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTowerOfHanoiTowerView; + +@protocol ORKTowerOfHanoiTowerViewDataSource + +@required +- (NSUInteger)numberOfDisksInTowerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView; +- (NSNumber *)towerOfHanoiView:(ORKTowerOfHanoiTowerView *)towerView diskAtIndex:(NSUInteger)index; + +@end + +@protocol ORKTowerOfHanoiTowerViewDelegate + +@required +- (void)towerOfHanoiTowerViewWasSelected:(ORKTowerOfHanoiTowerView *)towerView; +- (ORKTowerOfHanoiTowerView *)towerOfHanoiHighlightedTowerView; + +@end + + +@interface ORKTowerOfHanoiTowerView : UIView + +@property (nonatomic, getter=isHighLighted) BOOL highlighted; +@property (nonatomic, getter=isTargeted) BOOL targeted; +@property (nonatomic, weak) id dataSource; +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithFrame:(CGRect)frame maximumNumberOfDisks:(NSUInteger)maximumNumberOfDisks; + +- (void)reloadData; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.m new file mode 100755 index 0000000..a4fc9d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTowerOfHanoiTowerView.m @@ -0,0 +1,275 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTowerOfHanoiTowerView.h" + +#import "ORKActiveStepView.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const CGFloat DiskHeight = 10; +static const CGFloat DiskSpacing = 8; +static const CGFloat BaseSpacing = 10; + +@implementation ORKTowerOfHanoiTowerView { + NSInteger _maximumNumberOfDisks; + UIView *_base; + NSMutableArray *_diskViews; + NSMutableArray *_diskSizes; + NSMutableArray *_variableConstraints; +} + +#pragma mark - Init + +- (instancetype)initWithFrame:(CGRect)frame maximumNumberOfDisks:(NSUInteger)maximumNumberOfDisks { + self = [super initWithFrame:frame]; + if (self) { + _maximumNumberOfDisks = maximumNumberOfDisks; + _base = [[UIView alloc] initWithFrame:CGRectZero]; + _base.backgroundColor = [UIColor ork_midGrayTintColor]; + _base.translatesAutoresizingMaskIntoConstraints = NO; + _base.layer.cornerRadius = 2.5; + _base.layer.masksToBounds = YES; + _diskViews = [NSMutableArray new]; + _diskSizes = [NSMutableArray new]; + [self addSubview:_base]; + [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userDidTapTower)]]; + } + return self; +} + +#pragma mark - UIView + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + CGFloat height = (DiskHeight * _maximumNumberOfDisks) + (DiskSpacing * _maximumNumberOfDisks); + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:height + BaseSpacing]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:2.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_base + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:(height * 0.5) + BaseSpacing]]; + + UIView *topDisk; + for (NSInteger index = 0 ; index < _diskSizes.count ; index++) { + UIView *disk = _diskViews[index]; + CGFloat divide = 1.0 / _maximumNumberOfDisks; + CGFloat multiply = ((NSNumber *)_diskSizes[index]).floatValue * divide; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_base + attribute:NSLayoutAttributeWidth + multiplier:multiply + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:DiskHeight]]; + + if (index == 0) { + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:height * 0.5]]; + } else { + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:disk + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:topDisk + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:-DiskSpacing]]; + } + topDisk = disk; + } + [NSLayoutConstraint activateConstraints:_variableConstraints]; + [super updateConstraints]; +} + +- (void)tintColorDidChange { + [self reloadData]; +} + +#pragma mark - Public + +- (void)reloadData { + [self updateDisks]; + [self highlightIfNeeded]; + [self indicateTargetIfNeeded]; + [self setNeedsUpdateConstraints]; +} + +#pragma mark - Private + +- (void)userDidTapTower { + [self.delegate towerOfHanoiTowerViewWasSelected:self]; +} + +- (void)updateDisks { + [_diskViews makeObjectsPerformSelector:@selector(removeFromSuperview)]; + ORKRemoveConstraintsForRemovedViews(_variableConstraints, _diskViews); + + [_diskViews removeAllObjects]; + [_diskSizes removeAllObjects]; + + NSInteger numberOfDisks = [self.dataSource numberOfDisksInTowerOfHanoiView:self]; + for (NSInteger index = 0 ; index < numberOfDisks ; index++) { + NSNumber *diskSize = [self.dataSource towerOfHanoiView:self diskAtIndex:index]; + [_diskSizes addObject:diskSize]; + UIView *diskView = [[UIView alloc] initWithFrame:CGRectZero]; + diskView.backgroundColor = [self tintColor]; + diskView.translatesAutoresizingMaskIntoConstraints = NO; + diskView.layer.cornerRadius = DiskHeight * 0.5; + diskView.clipsToBounds = YES; + [self addSubview:diskView]; + [_diskViews addObject:diskView]; + } +} + +- (void)highlightIfNeeded { + if (self.isHighLighted) { + ((UIView *)_diskViews.lastObject).alpha = 0.2; + } +} + +- (void)indicateTargetIfNeeded { + if (self.isTargeted) { + _base.backgroundColor = [self tintColor]; + } +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + NSString *targetDisk = (self.isTargeted ? ORKLocalizedString(@"AX_TOWER_OF_HANOI_TARGET_DISK", nil) : nil); + return ORKAccessibilityStringForVariables(ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER", nil), targetDisk); +} + +- (NSString *)accessibilityHint { + if (!self.isHighLighted && [self.delegate towerOfHanoiHighlightedTowerView] != nil) { + return ORKLocalizedString(@"AX_TOWER_OF_HANOI_PLACE_DISK", nil); + } + + BOOL hasDisks = ([self.dataSource numberOfDisksInTowerOfHanoiView:self] > 0); + return (self.isHighLighted ? nil : (hasDisks ? ORKLocalizedString(@"AX_TOWER_OF_HANOI_SELECT_DISK", nil) : nil)); +} + +- (UIAccessibilityTraits)accessibilityTraits { + UIAccessibilityTraits traits = [super accessibilityTraits]; + if (self.isHighLighted) { + traits |= UIAccessibilityTraitSelected; + } + + // Don't echo if when a disk is placed. + if (!self.isHighLighted && UIAccessibilityFocusedElement(UIAccessibilityNotificationVoiceOverIdentifier) == self) { + traits |= UIAccessibilityTraitStartsMediaSession; + } + + return traits; +} + +- (NSString *)accessibilityValue { + + NSString *disksString = @""; + + for (NSNumber *diskSize in _diskSizes) { + disksString = ORKAccessibilityStringForVariables(disksString, diskSize.stringValue, @", "); + } + + NSString *value = (_diskSizes.count > 0 ? [NSString stringWithFormat:ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER_CONTAINS", nil), disksString] : ORKLocalizedString(@"AX_TOWER_OF_HANOI_TOWER_EMPTY", nil)); + + return value; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.h new file mode 100755 index 0000000..f49229b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKRoundTappingButton; + +@interface ORKTrailmakingContentView : ORKActiveStepCustomView + +@property (nonatomic, copy) NSArray *tapButtons; + +- (instancetype)initWithType:(NSString *)trailType; +- (void)setLinesToDraw:(int)numLines; +- (CGRect)testArea; + +- (void)setError:(int)buttonIdex; +- (void)clearErrors; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.m new file mode 100755 index 0000000..ad3a07b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingContentView.m @@ -0,0 +1,217 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTrailmakingContentView.h" + +#import "ORKHeadlineLabel.h" +#import "ORKLabel.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +#import "ORKRoundTappingButton.h" + + +@interface ORKTrailmakingTestView : UIView { + int linesToDraw; +} + +@end + + +@implementation ORKTrailmakingTestView + +- (instancetype)init { + self = [super init]; + if (self) { + self.contentMode = UIViewContentModeRedraw; + [self setBackgroundColor:[UIColor clearColor]]; + } + return self; +} + +- (void)setLinesToDraw:(int)numLines { + linesToDraw = numLines; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + [super drawRect:rect]; + + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextClearRect(ctx, rect); + + int curLine = 0; + + UIView* lastChild = nil; + for (UIView* child in self.subviews) { + if (curLine == linesToDraw) + break; + + if (lastChild == nil) { + lastChild = child; + } else { + CGRect r1 = child.frame; + CGRect r2 = lastChild.frame; + + CGContextSetStrokeColorWithColor(ctx, child.tintColor.CGColor); + CGContextSetLineWidth(ctx, 5.0f); + + CGContextMoveToPoint(ctx, r1.origin.x + r1.size.width / 2, r1.origin.y + r1.size.height / 2); + CGContextAddLineToPoint(ctx, r2.origin.x + r2.size.width / 2, r2.origin.y + r2.size.height / 2); + CGContextStrokePath(ctx); + + lastChild = child; + curLine++; + } + } +} + +@end + + +@interface ORKTrailmakingButton : ORKRoundTappingButton + +@end + + +@implementation ORKTrailmakingButton + ++ (UIFont *)defaultFont { + // Don't scale too much, because all buttons need to fit on screen and be readable within the circle + return [[UIFontMetrics metricsForTextStyle:UIFontTextStyleTitle3] scaledFontForFont:[UIFont systemFontOfSize:20.0] maximumPointSize:30.0]; +} + +@end + + +@interface ORKTrailmakingContentView () + +@property (nonatomic, strong) ORKTrailmakingTestView* testView; + +@end + + +@implementation ORKTrailmakingContentView + +- (instancetype)initWithType:(NSString*)trailType { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); + self.translatesAutoresizingMaskIntoConstraints = NO; + self.isAccessibilityElement = YES; + self.accessibilityLabel = ORKLocalizedString(@"AX_TAP_BUTTON_DIRECT_TOUCH_AREA", nil); + self.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction; + + self.testView = [[ORKTrailmakingTestView alloc] init]; + _testView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_testView]; + + NSMutableArray* buttons = [NSMutableArray array]; + for (int i = 0; i < 13; i++) + { + ORKTrailmakingButton* b = [[ORKTrailmakingButton alloc] init]; + + NSString* title; + if ([trailType isEqual:@"A"]) { + title = [self stringWithNumberFormatter:i + 1]; + } else { + NSArray *letters = [[NSArray alloc] initWithObjects:ORKLocalizedString(@"TRAILMAKING_LETTER_A", nil), + ORKLocalizedString(@"TRAILMAKING_LETTER_B", nil), + ORKLocalizedString(@"TRAILMAKING_LETTER_C", nil), + ORKLocalizedString(@"TRAILMAKING_LETTER_D", nil), + ORKLocalizedString(@"TRAILMAKING_LETTER_E", nil), + ORKLocalizedString(@"TRAILMAKING_LETTER_F", nil), nil]; + + if (i % 2 == 0) + title = [self stringWithNumberFormatter:i / 2 + 1]; + else + title = letters[i/2]; + } + + [b setTitle:title forState:UIControlStateNormal]; + [buttons addObject:b]; + + [_testView addSubview:b]; + } + _tapButtons = [buttons copy]; + [self setUpConstraints]; + } + return self; +} + +- (NSString *)stringWithNumberFormatter: (double)value { + NSNumberFormatter *formatter = [NSNumberFormatter new]; + formatter.numberStyle = NSNumberFormatterNoStyle; + formatter.locale = [NSLocale currentLocale]; + + return [NSString stringWithFormat:@"%@", [formatter stringFromNumber:[NSNumber numberWithDouble:value]]]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_testView); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_testView(>=100)]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-32-[_testView(>=100)]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setLinesToDraw:(int)numLines { + _testView.linesToDraw = numLines; +} + +- (CGRect)testArea { + return _testView.bounds; +} + +- (void)setError:(int)buttonIdex { + ORKRoundTappingButton* button = [_tapButtons objectAtIndex:buttonIdex]; + [button setTintColor:[UIColor redColor]]; +} + +- (void)clearErrors { + for (ORKRoundTappingButton* button in _tapButtons) { + [button setTintColor:self.tintColor]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.h new file mode 100755 index 0000000..1b15e03 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.h @@ -0,0 +1,97 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTrailmakingTap; + +/** + The `ORKTrailmakingResult` class represents the result of a signature step (`ORKTrailmakingStep`). + + + A trail making result is produced by the task view controller when it presents a trail making step. + + */ +ORK_CLASS_AVAILABLE +@interface ORKTrailmakingResult : ORKResult + +/** + An array of all taps completed during the test + */ +@property (nonatomic, copy) NSArray *taps; + +/** + The number of errors generated during the test + */ +@property (nonatomic) NSUInteger numberOfErrors; + +@end + + +/** + The `ORKTrailmakingTap` class represents a single tap in a trail making test. + + The Trailmaking tap move object records the indexes of tap, if it was in error or not + and the time at which the event occurred. A `trailmakingTap` instance is included in + an `ORKTrailmakingResult` object and is recorded by the step view controller for the + corresponding task when a tap is made. + + A trail making tap is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize the move for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTrailmakingTap : NSObject + +/** + A relative timestamp indicating the time of the tap event. + + The timestamp is relative to the value of `startDate` in the `ORKResult` object that includes this move. + The start date of that object represents the time at which the first move was made. + */ +@property (nonatomic, assign) NSTimeInterval timestamp; + +/** + The index of the button tapped. + */ +@property (nonatomic,assign) NSUInteger index; + +/** + If the button was tapped in error. + */ +@property (nonatomic, assign) BOOL incorrect; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.m new file mode 100755 index 0000000..ca1f67b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingResult.m @@ -0,0 +1,141 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTrailmakingResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKTrailmakingResult + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + _taps = @[]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfErrors); + ORK_ENCODE_OBJ(aCoder, taps); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfErrors); + ORK_DECODE_OBJ_ARRAY(aDecoder, taps, ORKTrailmakingTap); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return super.hash ^ self.numberOfErrors ^ self.taps.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.numberOfErrors == castObject.numberOfErrors && + ORKEqualObjects(self.taps, castObject.taps)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTrailmakingResult *result = [super copyWithZone:zone]; + result.numberOfErrors = self.numberOfErrors; + result.taps = ORKArrayCopyObjects(self.taps); + return result; +} + +@end + + +@implementation ORKTrailmakingTap + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, timestamp); + ORK_ENCODE_INTEGER(aCoder, index); + ORK_ENCODE_BOOL(aCoder, incorrect); + +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, timestamp); + ORK_DECODE_INTEGER(aDecoder, index); + ORK_DECODE_BOOL(aDecoder, incorrect); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return [super hash] ^ (NSUInteger)self.timestamp*100 ^ self.index; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return self.timestamp == castObject.timestamp && + self.index == castObject.index && + self.incorrect == castObject.incorrect; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTrailmakingTap *tap = [[[self class] allocWithZone:zone] init]; + tap.timestamp = self.timestamp; + tap.index = self.index; + tap.incorrect = self.incorrect; + return tap; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; timestamp: %@; index: %@; error: %@>", self.class.description, self, @(self.timestamp), @(self.index), @(self.incorrect)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.h new file mode 100755 index 0000000..b585701 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTrailmakingStep : ORKActiveStep + +/** + The type of trail to show. Default = `ORKTrailMakingTypeIdentifierA` + */ +@property (nonatomic, copy) ORKTrailMakingTypeIdentifier trailType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.m new file mode 100755 index 0000000..c1007c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStep.m @@ -0,0 +1,109 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTrailmakingStep.h" + +#import "ORKTrailmakingStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKTrailmakingStep + ++ (Class)stepViewControllerClass { + return [ORKTrailmakingStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + self.shouldContinueOnFinish = YES; + self.optional = NO; // default to *not* optional + _trailType = ORKTrailMakingTypeIdentifierA; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSArray *supportedTypes = @[ORKTrailMakingTypeIdentifierA, ORKTrailMakingTypeIdentifierB]; + if (self.trailType == nil || ![supportedTypes containsObject:self.trailType]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"trailType must be A or B" + userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKTrailmakingStep *step = [super copyWithZone:zone]; + step.trailType = self.trailType; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, trailType); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, trailType); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return [super hash] ^ self.trailType.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + [self.trailType isEqual:castObject.trailType]); +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.h new file mode 100755 index 0000000..10fe384 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTrailmakingStepViewController : ORKActiveStepViewController { +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.m new file mode 100755 index 0000000..828104c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKTrailmakingStepViewController.m @@ -0,0 +1,296 @@ +/* + Copyright (c) 2016, Motus Design Group Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTrailmakingStepViewController.h" + +#import "ORKActiveStepTimer.h" +#import "ORKActiveStepView.h" +#import "ORKTrailmakingContentView.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKRoundTappingButton.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKTrailmakingResult.h" +#import "ORKTrailmakingStep.h" +#import "ORKStep_Private.h" +#import "ORKResult.h" + +#import "ORKHelpers_Internal.h" +#import "ORKStepViewController_Internal.h" + + +#define BOUND(lo, hi, v) (((v) < (lo)) ? (lo) : (((v) > (hi)) ? (hi) : (v))) + +@implementation ORKTrailmakingStepViewController { + ORKTrailmakingContentView *_trailmakingContentView; + NSArray *_testPoints; + ORKTrailMakingTypeIdentifier _trailType; + int _nextIndex; + int _errors; + NSMutableArray *_taps; + NSTimer *_updateTimer; + UILabel *_timerLabel; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + _testPoints = [self fetchRandomTest]; + _taps = [NSMutableArray array]; + + if ([step isKindOfClass:[ORKTrailmakingStep class]]) { + _trailType = [((ORKTrailmakingStep*)step) trailType]; + } else { + _trailType = ORKTrailMakingTypeIdentifierA; + } + } + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + _trailmakingContentView = [[ORKTrailmakingContentView alloc] initWithType:_trailType]; + + self.activeStepView.activeCustomView = _trailmakingContentView; + + for (ORKRoundTappingButton* b in _trailmakingContentView.tapButtons) { + [b addTarget:self action:@selector(buttonPressed:forEvent:) forControlEvents:UIControlEventTouchDown]; + } + + _timerLabel = [[UILabel alloc] init]; + _timerLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + _timerLabel.adjustsFontForContentSizeCategory = YES; + _timerLabel.textAlignment = NSTextAlignmentCenter; + + [self.view addSubview:_timerLabel]; +} + +- (void)timerUpdated:(NSTimer*)timer { + NSTimeInterval elapsed = [[NSDate date] timeIntervalSinceDate: self.presentedDate]; + + NSDateComponentsFormatter *durationFormatter = [NSDateComponentsFormatter new]; + [durationFormatter setUnitsStyle:NSDateComponentsFormatterUnitsStyleAbbreviated]; + [durationFormatter setAllowedUnits:NSCalendarUnitSecond]; + [durationFormatter setFormattingContext:NSFormattingContextDynamic]; + [durationFormatter setMaximumUnitCount:1]; + NSString *text = [durationFormatter stringFromTimeInterval:elapsed]; + + if(_errors > 0){ + NSString *localizedErrors = [NSString localizedStringWithFormat:ORKLocalizedString(@"TRAILMAKING_ERROR_FORMAT", nil), _errors]; + text = [NSString stringWithFormat:@"%@ %@", text, localizedErrors]; + } + + _timerLabel.text = text; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; + _updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timerUpdated:) userInfo:nil repeats:YES]; + if (UIAccessibilityIsVoiceOverRunning()) { + // Put focus on the direct touch area immediately so that the first touch gets registered + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _trailmakingContentView); + } + + [self layoutButtons]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + if (_updateTimer != nil) { + [_updateTimer invalidate]; + _updateTimer = nil; + } +} + +- (void)viewWillLayoutSubviews { + [super viewWillLayoutSubviews]; + [self layoutButtons]; +} + +- (void)layoutButtons { + CGRect screenRect = [[UIScreen mainScreen] bounds]; + int screenSize = MAX(screenRect.size.width, screenRect.size.height); + + int cx; + + if (screenSize >= 736) { + cx = 50; // iPhone 6+/7+ + } else if (screenSize >= 667) { + cx = 45; // iPhone 6/7 + } else { + cx = 40; // iPhone 5/SE + } + + CGRect labelRect = _trailmakingContentView.testArea; + labelRect.size.height = 20; + labelRect.origin = self.activeStepView.frame.origin; + [_timerLabel setFrame:labelRect]; + + CGRect r = _trailmakingContentView.testArea; + int idx = 0; + + /* When viewWillLayoutSubviews is called for the first time _trailmakingContentView.testArea height and width might not be set which can cause all the buttons to stack on top of one another. This check avoids that scenario */ + if (r.size.height == 0 && r.size.width == 0) { + return; + } + + for (ORKRoundTappingButton* b in _trailmakingContentView.tapButtons) { + CGPoint pp = [[_testPoints objectAtIndex:idx] CGPointValue]; + + if (r.size.width > r.size.height) { + float temp = pp.x; + pp.x = pp.y; + pp.y = temp; + } + + const int x = BOUND(5, r.size.width - cx - 5, pp.x * r.size.width); + const int y = BOUND(5, r.size.height - cx - 5, pp.y * r.size.height); + b.frame = CGRectMake(x, y, cx, cx); + b.diameter = cx; + + idx++; + } +} + +- (IBAction)buttonPressed:(id)button forEvent:(UIEvent *)event { + NSUInteger buttonIndex = [_trailmakingContentView.tapButtons indexOfObject:button]; + if (buttonIndex != NSNotFound) { + + ORKTrailmakingTap* tap = [[ORKTrailmakingTap alloc] init]; + tap.timestamp = [[NSDate date] timeIntervalSinceDate: self.presentedDate]; + tap.index = buttonIndex; + + if (buttonIndex == _nextIndex) { + _nextIndex++; + + _trailmakingContentView.linesToDraw = _nextIndex - 1; + if (_nextIndex == _trailmakingContentView.tapButtons.count) { + [self performSelector:@selector(finish) withObject:nil afterDelay:1.5]; + [_updateTimer invalidate]; + _updateTimer = nil; + } + tap.incorrect = NO; + + [_trailmakingContentView clearErrors]; + } else { + _errors++; + tap.incorrect = YES; + + [_trailmakingContentView clearErrors]; + [_trailmakingContentView setError:(int)buttonIndex]; + } + [_taps addObject:tap]; + } +} + +- (NSArray*)testData { + static NSArray *testData; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + testData = @[ + @"0.819257,0.121951,0.603041,0.214286,0.182432,0.121951,0.231419,0.490418,0.177365,0.836237,0.478041,0.812718,0.398649,0.442509,0.565878,0.670732,0.652027,0.804878,0.827703,0.343206,0.604730,0.306620,0.633446,0.533101,0.283784,0.267422", + @"0.779661,0.907746,0.722034,0.190601,0.906780,0.395997,0.869492,0.063534,0.161017,0.060923,0.223729,0.328111,0.105085,0.879896,0.286441,0.799826,0.461017,0.830287,0.505085,0.580505,0.654237,0.800696,0.640678,0.461271,0.337288,0.533507", + @"0.824027,0.881533,0.604061,0.790941,0.186125,0.876307,0.231810,0.509582,0.177665,0.163763,0.485618,0.183798,0.401015,0.554007,0.571912,0.332753,0.659898,0.195993,0.830795,0.657665,0.604061,0.695993,0.634518,0.466899,0.291032,0.735192", + @"0.777403,0.092334,0.728499,0.808362,0.905565,0.602787,0.854975,0.935540,0.166948,0.934669,0.225970,0.670732,0.109612,0.123693,0.288364,0.203833,0.463744,0.169861,0.505902,0.420732,0.654300,0.202962,0.644182,0.540941,0.338954,0.469512", + @"0.487310,0.475610,0.318105,0.262195,0.763113,0.186411,0.560068,0.758711,0.521151,0.614111,0.270728,0.450348,0.390863,0.865854,0.089679,0.935540,0.142132,0.686411,0.138748,0.141986,0.514382,0.164634,0.906937,0.082753,0.896785,0.710801", + @"0.634518,0.369338,0.678511,0.827526,0.448393,0.370209,0.509306,0.751742,0.257191,0.797909,0.087986,0.912021,0.145516,0.223868,0.076142,0.055749,0.873096,0.100174,0.912014,0.514808,0.737733,0.230836,0.839256,0.935540,0.411168,0.941638", + @"0.483871,0.530078,0.315789,0.744551,0.758913,0.816042,0.555178,0.242371,0.516129,0.391456,0.263158,0.552746,0.385399,0.136879,0.083192,0.071491,0.135823,0.315606,0.139219,0.861377,0.514431,0.838710,0.903226,0.919791,0.893039,0.293810", + @"0.633446,0.633827,0.673986,0.176112,0.445946,0.632084,0.503378,0.251962,0.260135,0.205754,0.087838,0.088056,0.146959,0.780296,0.081081,0.949433,0.869932,0.903226,0.908784,0.485615,0.736486,0.770706,0.837838,0.066260,0.410473,0.061029", + @"0.505068,0.481707,0.263514,0.751742,0.728041,0.816202,0.618243,0.162892,0.538851,0.323171,0.255068,0.577526,0.361486,0.136760,0.116554,0.087108,0.136824,0.418118,0.119932,0.890244,0.479730,0.837108,0.869932,0.922474,0.859797,0.438153", + @"0.587838,0.630662,0.699324,0.148955,0.479730,0.519164,0.481419,0.155052,0.263514,0.183798,0.076014,0.123693,0.231419,0.722997,0.131757,0.913763,0.878378,0.898955,0.912162,0.533972,0.711149,0.798781,0.854730,0.056620,0.334459,0.056620", + @"0.501689,0.523560,0.256757,0.253054,0.724662,0.185864,0.616554,0.841187,0.535473,0.678883,0.256757,0.424084,0.358108,0.866492,0.111486,0.915358,0.133446,0.583770,0.118243,0.109948,0.478041,0.164049,0.868243,0.079407,0.854730,0.564572", + @"0.587140,0.370435,0.695431,0.851304,0.478849,0.481739,0.483926,0.845217,0.265651,0.817391,0.074450,0.873043,0.233503,0.274783,0.133672,0.087826,0.878173,0.103478,0.920474,0.467826,0.717428,0.202609,0.852792,0.942609,0.314721,0.946087" + ]; + }); + return testData; +} + +- (NSArray*)fetchRandomTest { + const int testNum = arc4random_uniform((uint32_t)[[self testData] count]); + const bool invertX = arc4random_uniform(2) == 1; + const bool invertY = arc4random_uniform(2) == 1; + const bool reverse = arc4random_uniform(2) == 1; + + NSMutableArray* points = [NSMutableArray array]; + NSString* testPointsStr = [self.testData objectAtIndex:testNum]; + NSArray* chunks = [testPointsStr componentsSeparatedByString:@","]; + + for (int i = 0; i < chunks.count; i += 2) { + CGPoint pp; + pp.x = [[chunks objectAtIndex:i + 0] floatValue]; + pp.y = [[chunks objectAtIndex:i + 1] floatValue]; + + if (invertX) pp.x = 1.0f - pp.x; + if (invertY) pp.y = 1.0f - pp.y; + + [points addObject:[NSValue valueWithCGPoint:pp]]; + } + + return reverse ? [[points reverseObjectEnumerator] allObjects] : [points copy]; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = stepResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:stepResult.results]; + + ORKTrailmakingResult *trailmakingResult = [[ORKTrailmakingResult alloc] initWithIdentifier:self.step.identifier]; + trailmakingResult.startDate = stepResult.startDate; + trailmakingResult.endDate = now; + trailmakingResult.taps = [_taps copy]; + trailmakingResult.numberOfErrors = _errors; + + [results addObject:trailmakingResult]; + stepResult.results = [results copy]; + + return stepResult; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.h new file mode 100755 index 0000000..3406ad6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import AVFoundation; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVoiceEngine : NSObject + ++ (ORKVoiceEngine *)sharedVoiceEngine; + +- (void)speakText:(NSString *)text; + +- (void)speakInt:(NSInteger)number; + +- (void)stopTalking; + +- (BOOL)isSpeaking; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.m new file mode 100755 index 0000000..cef6264 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine.m @@ -0,0 +1,99 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVoiceEngine.h" +#import "ORKVoiceEngine_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKVoiceEngine + ++ (ORKVoiceEngine *)sharedVoiceEngine { + static ORKVoiceEngine *sharedVoiceEngine; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedVoiceEngine = [ORKVoiceEngine new]; + }); + return sharedVoiceEngine; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _speechSynthesizer = [[AVSpeechSynthesizer alloc] init]; + self.speechSynthesizer.delegate = self; + } + return self; +} + +- (void)dealloc { + [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate]; + self.speechSynthesizer.delegate = nil; +} + +- (void)speakText:(NSString *)text { + if (self.speechSynthesizer.isSpeaking) { + [self stopTalking]; + } + + if (UIAccessibilityIsVoiceOverRunning()) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, text); + return; + } + + AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc] initWithString:text]; + float speechRate = AVSpeechUtteranceDefaultSpeechRate; + if (![[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9, .minorVersion = 0, .patchVersion = 0}]) { + speechRate = AVSpeechUtteranceDefaultSpeechRate / 2.5; + } + utterance.rate = speechRate; + + [self.speechSynthesizer speakUtterance:utterance]; +} + +- (void)speakInt:(NSInteger)number { + [self speakText:[NSString stringWithFormat:@"%ld",(long)number]]; +} + +- (void)stopTalking { + [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryWord]; +} + + +- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance { +} + +- (BOOL)isSpeaking { + return self.speechSynthesizer.isSpeaking; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine_Internal.h new file mode 100755 index 0000000..e268ab0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKVoiceEngine_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Denis Lebedev. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVoiceEngine.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVoiceEngine () + +@property (nonatomic, strong, readonly) AVSpeechSynthesizer *speechSynthesizer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.h new file mode 100755 index 0000000..5a351a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKWalkingTaskStep` class implements a step that's used in the predefined + walking task. + + You don't usually need to instantiate a walking step directly; + instead, it is instantiated as part of a predefined task. See the + predefined active tasks defined in `ORKOrderedTask`. + */ +ORK_CLASS_AVAILABLE +@interface ORKWalkingTaskStep : ORKActiveStep + +/** + The number of steps the user should be asked to take in each leg of the + walking task step. + + The step finishes when the number of steps have been completed, + or after `1.5 * numberOfStepsPerLeg` seconds, whichever comes first. + */ +@property (nonatomic, assign) NSInteger numberOfStepsPerLeg; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.m new file mode 100755 index 0000000..e48c216 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStep.m @@ -0,0 +1,102 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWalkingTaskStep.h" + +#import "ORKWalkingTaskStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKWalkingTaskStep + ++ (Class)stepViewControllerClass { + return [ORKWalkingTaskStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.shouldShowDefaultTimer = NO; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + NSInteger const ORKShortWalkTaskMinimumNumberOfStepsPerLeg = 1; + + if ( self.numberOfStepsPerLeg < ORKShortWalkTaskMinimumNumberOfStepsPerLeg) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"numberOfStepsPerLeg cannot be less than %@.", @(ORKShortWalkTaskMinimumNumberOfStepsPerLeg)] + userInfo:nil]; + } +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKWalkingTaskStep *step = [super copyWithZone:zone]; + step.numberOfStepsPerLeg = self.numberOfStepsPerLeg; + return step; +} + +- (BOOL)startsFinished { + return NO; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, numberOfStepsPerLeg); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, numberOfStepsPerLeg); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.numberOfStepsPerLeg == castObject.numberOfStepsPerLeg)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.h new file mode 100755 index 0000000..59bb21f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + View controller corresponding to the `ORKWalkingTaskStep`. + + Observes the results of the pedometer, in order to finish early + when the threshold number of steps have been observed. + */ +ORK_CLASS_AVAILABLE +@interface ORKWalkingTaskStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.m new file mode 100755 index 0000000..b06df64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKWalkingTaskStepViewController.m @@ -0,0 +1,172 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWalkingTaskStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKCustomStepView_Internal.h" +#import "ORKProgressView.h" +#import "ORKVerticalContainerView_Internal.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKPedometerRecorder.h" + +#import "ORKStep_Private.h" +#import "ORKWalkingTaskStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKWalkingContentView : ORKActiveStepCustomView { + NSLayoutConstraint *_topConstraint; +} + +@property (nonatomic, strong, readonly) ORKProgressView *progressView; + +@end + + +@implementation ORKWalkingContentView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _progressView = [ORKProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + +#if LAYOUT_DEBUG + self.backgroundColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; + _progressView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.2]; +#endif + + [self addSubview:_progressView]; + [self setUpConstraints]; + [self updateConstraintConstantsForWindow:self.window]; + } + return self; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + const CGFloat CaptionBaselineToProgressTop = 100; + const CGFloat CaptionBaselineToStepViewTop = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTop, window); + _topConstraint.constant = CaptionBaselineToProgressTop - CaptionBaselineToStepViewTop; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_progressView); + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_progressView]-(>=0)-|" + options:NSLayoutFormatAlignAllCenterX + metrics:nil + views:views]]; + _topConstraint = [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; // constant will be set in updateConstraintConstantsForWindow: + [constraints addObject:_topConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraints { + [self updateConstraintConstantsForWindow:self.window]; + [super updateConstraints]; +} + +@end + + +@interface ORKWalkingTaskStepViewController () { + NSInteger _intendedSteps; + ORKWalkingContentView *_contentView; +} + +@end + + +@implementation ORKWalkingTaskStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.suspendIfInactive = NO; + } + return self; +} + +- (ORKWalkingTaskStep *)walkingTaskStep { + NSAssert(self.step == nil || [self.step isKindOfClass:[ORKWalkingTaskStep class]], @"Expected step subclass of ORKWalkingTaskStep"); + return (ORKWalkingTaskStep *)self.step; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _contentView = [ORKWalkingContentView new]; + _contentView.translatesAutoresizingMaskIntoConstraints = NO; + self.activeStepView.activeCustomView = _contentView; +} + +- (void)stepDidChange { + [super stepDidChange]; + + _intendedSteps = [[self walkingTaskStep] numberOfStepsPerLeg]; +} + +- (void)pedometerRecorderDidUpdate:(ORKPedometerRecorder *)pedometerRecorder { + NSInteger numberOfSteps = [pedometerRecorder totalNumberOfSteps]; + ORK_Log_Debug("Steps: %lld", (long long)numberOfSteps); + if (_intendedSteps > 0 && numberOfSteps >= _intendedSteps) { + [self finish]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.h new file mode 100755 index 0000000..ae38a3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.h @@ -0,0 +1,89 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + --- + + This software is based on the original source by Matt Gallagher. + http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html + + Copyright (c) 2009-2011 Matt Gallagher. All rights reserved. + + This software is provided 'as-is', without any express or implied warranty. In + no event will the authors be held liable for any damages arising from the use + of this software. Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + + +@import UIKit; +@import AVFoundation; +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKdBHLToneAudiometryAudioGeneratorDelegate; + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryAudioGenerator : NSObject + +@property (nonatomic, weak) id delegate; + +- (instancetype) initForHeadphones: (NSString *)headphones; + +- (void)playSoundAtFrequency:(double)playFrequency + onChannel:(ORKAudioChannel)playChannel + dBHL:(double)dBHL; + +/** + Stops the audio being played. + */ +- (void)stop; + +@end + +@protocol ORKdBHLToneAudiometryAudioGeneratorDelegate + +@required +-(void)toneWillStartClipping; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.m new file mode 100755 index 0000000..131fa19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryAudioGenerator.m @@ -0,0 +1,373 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + --- + + This software is based on the original source by Matt Gallagher. + http://www.cocoawithlove.com/2010/10/ios-tone-generator-introduction-to.html + + Copyright (c) 2009-2011 Matt Gallagher. All rights reserved. + + This software is provided 'as-is', without any express or implied warranty. In + no event will the authors be held liable for any damages arising from the use + of this software. Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + + +#import "ORKdBHLToneAudiometryAudioGenerator.h" + +@import AudioToolbox; + + +@interface ORKdBHLToneAudiometryAudioGenerator () { +@public + AudioComponentInstance _toneUnit; + AUGraph _mGraph; + AUNode _outputNode; + AUNode _mixerNode; + AudioUnit _mMixer; + double _frequency; + double _theta; + ORKAudioChannel _activeChannel; + BOOL _playsStereo; + BOOL _rampUp; + double _fadeInFactor; + double _globaldBHL; + NSNumber *_amplitudeGain; + NSTimeInterval _fadeInDuration; + NSDictionary *_sensitivityPerFrequency; + NSDictionary *_volumeCurve; + NSDictionary *_retspl; + int _lastNodeInput; +} + +- (NSNumber *)dbHLtoAmplitude: (double)dbHL atFrequency:(double)frequency; + +@end + +const double ORKdBHLSineWaveToneGeneratorSampleRateDefault = 44100.0f; + +static OSStatus ORKdBHLAudioGeneratorRenderTone(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { + // Get the tone parameters out of the view controller + ORKdBHLToneAudiometryAudioGenerator *audioGenerator = (__bridge ORKdBHLToneAudiometryAudioGenerator *)inRefCon; + double amplitude; + + amplitude = [audioGenerator->_amplitudeGain doubleValue]; + + double theta = audioGenerator->_theta; + double theta_increment = 2.0 * M_PI * audioGenerator->_frequency / ORKdBHLSineWaveToneGeneratorSampleRateDefault; + + double fadeInFactor = audioGenerator->_fadeInFactor; + + // This is a mono tone generator so we only need the first buffer + Float32 *bufferActive = (Float32 *)ioData->mBuffers[audioGenerator->_activeChannel].mData; + Float32 *bufferNonActive = (Float32 *)ioData->mBuffers[1 - audioGenerator->_activeChannel].mData; + + // Generate the samples + for (UInt32 frame = 0; frame < inNumberFrames; frame++) { + double bufferValue; + + bufferValue = sin(theta) * amplitude * pow(10, 2.0 * fadeInFactor - 2); + + bufferActive[frame] = bufferValue; + if (audioGenerator->_playsStereo) { + bufferNonActive[frame] = bufferValue; + } else { + bufferNonActive[frame] = 0; + } + + theta += theta_increment; + if (theta > 2.0 * M_PI) { + theta -= 2.0 * M_PI; + } + if (audioGenerator->_rampUp) { + fadeInFactor += 1.0 / (ORKdBHLSineWaveToneGeneratorSampleRateDefault * audioGenerator->_fadeInDuration); + if (fadeInFactor >= 1) { + fadeInFactor = 1; + } + } else { + fadeInFactor -= 1.0 / (ORKdBHLSineWaveToneGeneratorSampleRateDefault * audioGenerator->_fadeInDuration); + if (fadeInFactor <= 0) { + fadeInFactor = 0; + } + } + } + + // Store the theta back in the view controller + audioGenerator->_theta = theta; + audioGenerator->_fadeInFactor = fadeInFactor; + + return noErr; +} + +static OSStatus ORKdBHLAudioGeneratorZeroTone(void *inRefCon, + AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, + UInt32 inNumberFrames, + AudioBufferList *ioData) { + // Get the tone parameters out of the view controller + ORKdBHLToneAudiometryAudioGenerator *audioGenerator = (__bridge ORKdBHLToneAudiometryAudioGenerator *)inRefCon; + + // This is a mono tone generator so we only need the first buffer + Float32 *bufferActive = (Float32 *)ioData->mBuffers[audioGenerator->_activeChannel].mData; + Float32 *bufferNonActive = (Float32 *)ioData->mBuffers[1 - audioGenerator->_activeChannel].mData; + + // Generate the samples + for (UInt32 frame = 0; frame < inNumberFrames; frame++) { + double bufferValue = 0; + bufferActive[frame] = bufferValue; + bufferNonActive[frame] = bufferValue; + } + + return noErr; +} + +@implementation ORKdBHLToneAudiometryAudioGenerator + +- (instancetype)initForHeadphones: (NSString *)headphones { + self = [super init]; + if (self) { + _lastNodeInput = 0; + + _sensitivityPerFrequency = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:[NSString stringWithFormat:@"frequency_dBSPL_%@", [headphones uppercaseString]] ofType:@"plist"]]; + + _retspl = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:[NSString stringWithFormat:@"retspl_%@", [headphones uppercaseString]] ofType:@"plist"]]; + + if ([[headphones uppercaseString] isEqualToString:@"AIRPODS"]) { + _volumeCurve = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:@"volume_curve_AIRPODS" ofType:@"plist"]]; + } else { + _volumeCurve = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForResource:@"volume_curve_WIRED" ofType:@"plist"]]; + } + + [self setupGraph]; + } + return self; +} + +- (void)dealloc { + [self stop]; + + AUGraphStop(_mGraph); + AUGraphUninitialize(_mGraph); + _mGraph = nil; + _mMixer = nil; +} + +- (void)playSoundAtFrequency:(double)playFrequency + onChannel:(ORKAudioChannel)playChannel + dBHL:(double)dBHL { + _frequency = playFrequency; + _activeChannel = playChannel; + _fadeInFactor = 0; + _fadeInDuration = 0.2; + _rampUp = YES; + _globaldBHL = dBHL; + + [self play]; + +} + +- (void)setupGraph { + if (!_mGraph) { + NewAUGraph(&_mGraph); + AudioComponentDescription mixer_desc; + mixer_desc.componentType = kAudioUnitType_Mixer; + mixer_desc.componentSubType = kAudioUnitSubType_MultiChannelMixer; + mixer_desc.componentFlags = 0; + mixer_desc.componentFlagsMask = 0; + mixer_desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + AudioComponentDescription output_desc; + output_desc.componentType = kAudioUnitType_Output; + output_desc.componentSubType = kAudioUnitSubType_RemoteIO; + output_desc.componentFlags = 0; + output_desc.componentFlagsMask = 0; + output_desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + AUGraphAddNode(_mGraph, &output_desc, &_outputNode); + AUGraphAddNode(_mGraph, &mixer_desc, &_mixerNode ); + + AUGraphConnectNodeInput(_mGraph, _mixerNode, 0, _outputNode, 0); + + AUGraphOpen(_mGraph); + AUGraphNodeInfo(_mGraph, _mixerNode, NULL, &_mMixer); + + UInt32 numbuses = 3; + UInt32 size = sizeof(numbuses); + AudioUnitSetProperty(_mMixer, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &numbuses, size); + + AudioStreamBasicDescription desc; + for (int i = 0; i < numbuses; ++i) { + AURenderCallbackStruct renderCallbackStruct; + renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); + + if (i == 0) { + renderCallbackStruct.inputProc = ORKdBHLAudioGeneratorZeroTone; + AUGraphSetNodeInputCallback(_mGraph, _mixerNode, 0, &renderCallbackStruct); + } + size = sizeof(desc); + AudioUnitGetProperty( _mMixer, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + i, + &desc, + &size); + memset (&desc, 0, sizeof (desc)); + const int four_bytes_per_float = 4; + const int eight_bits_per_byte = 8; + + desc.mSampleRate = ORKdBHLSineWaveToneGeneratorSampleRateDefault; + desc.mFormatID = kAudioFormatLinearPCM; + desc.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved; + desc.mBytesPerPacket = four_bytes_per_float; + desc.mFramesPerPacket = 1; + desc.mBytesPerFrame = four_bytes_per_float; + desc.mChannelsPerFrame = 2; + desc.mBitsPerChannel = four_bytes_per_float * eight_bits_per_byte; + + AudioUnitSetProperty( _mMixer, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Input, + i, + &desc, + sizeof(desc)); + } + + AudioUnitSetProperty( _mMixer, + kAudioUnitProperty_StreamFormat, + kAudioUnitScope_Output, + 0, + &desc, + sizeof(desc)); + AUGraphInitialize(_mGraph); + AUGraphStart(_mGraph); + } +} + +- (void)play { + _amplitudeGain = [self dbHLtoAmplitude:_globaldBHL atFrequency:_frequency]; + AURenderCallbackStruct renderCallbackStruct; + renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); + renderCallbackStruct.inputProc = ORKdBHLAudioGeneratorRenderTone; + _lastNodeInput += 1; + int connect = 0; + int disconnect = 0; + if ((_lastNodeInput % 2) == 0) { + connect = 1; + disconnect = 2; + } else { + connect = 2; + disconnect = 1; + } + AUGraphDisconnectNodeInput(_mGraph, _mixerNode, disconnect); + AUGraphSetNodeInputCallback(_mGraph, _mixerNode, connect, &renderCallbackStruct); + AUGraphUpdate(_mGraph, NULL); +} + +- (void)stop { + if (_mGraph) { + _rampUp = NO; + int nodeInput = (_lastNodeInput % 2) + 1; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_fadeInDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (_mGraph) { + dispatch_async(dispatch_get_main_queue(), ^{ + AUGraphDisconnectNodeInput(_mGraph, _mixerNode, nodeInput); + AUGraphUpdate(_mGraph, NULL); + }); + } + }); + } +} + +- (double)dBToAmplitude:(double)dB { + return (powf(10, 0.05 * dB)); +} + +- (float)getCurrentSystemVolume { + return [[AVAudioSession sharedInstance] outputVolume]; +} + + +- (NSNumber *)dbHLtoAmplitude: (double)dbHL atFrequency:(double)frequency { + NSDecimalNumber *dBSPL = [NSDecimalNumber decimalNumberWithString:_sensitivityPerFrequency[[NSString stringWithFormat:@"%.0f",frequency]]]; + + // get current volume + float currentVolume = [self getCurrentSystemVolume]; + + currentVolume = (int)(currentVolume / 0.0625) * 0.0625; + + // check in volume curve table for offset + NSDecimalNumber *offsetDueToVolume = [NSDecimalNumber decimalNumberWithString:_volumeCurve[[NSString stringWithFormat:@"%.4f",currentVolume]]]; + + NSDecimalNumber *updated_dBSPLForVolumeCurve = [dBSPL decimalNumberByAdding:offsetDueToVolume]; + + NSDecimalNumber *dBFSCalibration = [NSDecimalNumber decimalNumberWithString:@"30"]; + + NSDecimalNumber *updated_dBSPLFor_dBFS = [updated_dBSPLForVolumeCurve decimalNumberByAdding:dBFSCalibration]; + + NSDecimalNumber *baselinedBSPL = [NSDecimalNumber decimalNumberWithString:_retspl[[NSString stringWithFormat:@"%.0f",frequency]]]; + + NSDecimalNumber *tempdBHL = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f", dbHL]]; + NSDecimalNumber *attenuationOffset = [baselinedBSPL decimalNumberByAdding:tempdBHL]; + + NSDecimalNumber *attenuation = [attenuationOffset decimalNumberBySubtracting:updated_dBSPLFor_dBFS]; + + // if the signal starts clipping + if ([attenuation doubleValue] >= -1) { + if (self.delegate && [self.delegate respondsToSelector:@selector(toneWillStartClipping)]) { + [self.delegate toneWillStartClipping]; + return nil; + } + } + + double linearAttenuation = [self dBToAmplitude:attenuation.doubleValue]; + + return [NSNumber numberWithDouble:linearAttenuation]; + +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.h new file mode 100755 index 0000000..cbba0d3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKCustomStepView_Internal.h" +#import "ORKUnitLabel.h" +#import "ORKRoundTappingButton.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKdBHLToneAudiometryButton : ORKRoundTappingButton + +@end + +@interface ORKdBHLToneAudiometryContentView : ORKActiveStepCustomView + +- (void)setProgress:(CGFloat)progress + animated:(BOOL)animated; + +@property (nonatomic, strong, readonly) ORKdBHLToneAudiometryButton *tapButton; +@property (nonatomic, strong) UIProgressView *progressView; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.m new file mode 100755 index 0000000..179fe50 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryContentView.m @@ -0,0 +1,204 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryContentView.h" + +#import "ORKRoundTappingButton.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat TopToProgressViewMinPadding = 10.0; +static const CGFloat BottomToProgressLabelPadding = 30.0; + +@implementation ORKdBHLToneAudiometryButton + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.layer.borderWidth = 15.0; + self.layer.borderColor = UIColor.whiteColor.CGColor; + self.layer.shadowRadius = 10.0; + self.layer.shadowOpacity = 0.2; + self.layer.masksToBounds = NO; + } + return self; +} + +- (void)updateBackgroundColor { + [super updateBackgroundColor]; + self.layer.borderColor = UIColor.whiteColor.CGColor; +} + +@end + +@implementation ORKdBHLToneAudiometryContentView { + NSLayoutConstraint *_topToProgressViewConstraint; + UILabel *_progressLabel; +} + +- (instancetype)init { + self = [super init]; + if (self) { + + _progressView = [UIProgressView new]; + _progressView.translatesAutoresizingMaskIntoConstraints = NO; + _progressView.progressTintColor = [self tintColor]; + [_progressView setAlpha:0]; + [_progressView setHidden:YES]; + [self addSubview:_progressView]; + _tapButton = [[ORKdBHLToneAudiometryButton alloc] init]; + [_tapButton setDiameter:150]; + _tapButton.translatesAutoresizingMaskIntoConstraints = NO; + _tapButton.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitAllowsDirectInteraction; + + [self addSubview:_tapButton]; + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setupProgressLabel]; + + [self setUpConstraints]; + } + + return self; +} + +- (void)setupProgressLabel { + if (!_progressLabel) { + _progressLabel = [UILabel new]; + } + _progressLabel.font = [self textFontBold]; + _progressLabel.textAlignment = NSTextAlignmentCenter; + if (@available(iOS 13.0, *)) { + _progressLabel.textColor = UIColor.secondaryLabelColor; + } else { + _progressLabel.textColor = UIColor.grayColor; + } + _progressLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_progressLabel]; +} + +- (UIFont *)textFontBold { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold | UIFontDescriptorTraitLooseLeading)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (void)didMoveToWindow { + if (self.window != nil && UIAccessibilityIsVoiceOverRunning()) { + // Ensure that VoiceOver is aware of the direct touch area so that the first tap gets registered + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _tapButton); + } +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.progressView.progressTintColor = [self tintColor]; +} + +- (void)setProgress:(CGFloat)progress + animated:(BOOL)animated { + [self.progressView setProgress:progress animated:animated]; + [UIView animateWithDuration:animated ? 0.2 : 0 animations:^{ + [self.progressView setAlpha:(progress == 0) ? 0 : 1]; + }]; + + NSNumberFormatter *formatter = [NSNumberFormatter new]; + formatter.numberStyle = NSNumberFormatterPercentStyle; + formatter.locale = [NSLocale currentLocale]; + + NSString *percentageText = [formatter stringFromNumber:[NSNumber numberWithFloat:progress]]; + _progressLabel.text = [NSString stringWithFormat:ORKLocalizedString(@"dBHL_PROGRESS_COMPLETION_%@", nil), percentageText]; +} + +- (void)finishStep:(ORKActiveStepViewController *)viewController { + [super finishStep:viewController]; + self.tapButton.enabled = NO; +} + +- (void)setUpConstraints { + NSArray *constraints = @[ + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:TopToProgressViewMinPadding], + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_progressView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tapButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tapButton + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_progressLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_progressLabel + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-BottomToProgressLabelPadding] + + ]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.h new file mode 100755 index 0000000..7ad524b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.h @@ -0,0 +1,37 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryOnboardingStep : ORKFormStep + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.m new file mode 100755 index 0000000..3c495fd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStep.m @@ -0,0 +1,41 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryOnboardingStep.h" +#import "ORKdBHLToneAudiometryOnboardingStepViewController.h" + +@implementation ORKdBHLToneAudiometryOnboardingStep + ++ (Class)stepViewControllerClass { + return [ORKdBHLToneAudiometryOnboardingStepViewController class]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.h new file mode 100755 index 0000000..370e14e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.h @@ -0,0 +1,36 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +@interface ORKdBHLToneAudiometryOnboardingStepViewController : ORKFormStepViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.m new file mode 100755 index 0000000..83fb455 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryOnboardingStepViewController.m @@ -0,0 +1,88 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryStep.h" +#import "ORKdBHLToneAudiometryOnboardingStepViewController.h" + +@implementation ORKdBHLToneAudiometryOnboardingStepViewController { + int indexOffset; +} + +- (void)goForward { + if ([self hasNextStep]) { + indexOffset = 3; + ORKdBHLToneAudiometryStep *toneAudiometryStep = [self getFutureStep]; + ORKAudioChannel userSelectedChannel = ORKAudioChannelLeft; + NSString *userSelectedChannelString = (NSString *)((ORKChoiceQuestionResult *)self.result.results[0]).choiceAnswers[0]; + NSString *userSelectedHeadphoneTypeString = (NSString *)((ORKChoiceQuestionResult *)self.result.results[1]).choiceAnswers[0]; + if ([userSelectedChannelString isEqualToString:@"RIGHT"]) { + userSelectedChannel = ORKAudioChannelRight; + } else { + userSelectedChannelString = @"LEFT"; + } + if (toneAudiometryStep) { + toneAudiometryStep.headphoneType = userSelectedHeadphoneTypeString; + toneAudiometryStep.earPreference = userSelectedChannel; + toneAudiometryStep.text = [NSString stringWithFormat:@"Playback occurring in the %@ channel of your headphones. Tap the button below every time you hear a tone.", userSelectedChannelString]; + } + indexOffset = 5; + // flip selections + if ([userSelectedChannelString isEqualToString:@"RIGHT"]) { + userSelectedChannelString = @"LEFT"; + userSelectedChannel = ORKAudioChannelLeft; + } else { + userSelectedChannel = ORKAudioChannelRight; + userSelectedChannelString = @"RIGHT"; + } + toneAudiometryStep = [self getFutureStep]; + if (toneAudiometryStep) { + toneAudiometryStep.headphoneType = userSelectedHeadphoneTypeString; + toneAudiometryStep.earPreference = userSelectedChannel; + toneAudiometryStep.text = [NSString stringWithFormat:@"Playback occurring in the %@ channel of your headphones. Tap the button below every time you hear a tone.", userSelectedChannelString]; + } + } + [super goForward]; +} + +- (nullable ORKdBHLToneAudiometryStep *)getFutureStep { + ORKOrderedTask *task = (ORKOrderedTask *)[self.taskViewController task]; + NSUInteger nextStepIndex = [task indexOfStep:[self step]] + indexOffset; + ORKStep *nextStep = [task steps][nextStepIndex]; + + if ([nextStep isKindOfClass:[ORKdBHLToneAudiometryStep class]]) { + return (ORKdBHLToneAudiometryStep *)nextStep; + } else { + return nil; + } +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.h new file mode 100755 index 0000000..6a53b3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.h @@ -0,0 +1,84 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKdBHLToneAudiometryFrequencySample; +@class ORKdBHLToneAudiometryUnit; + +ORK_EXTERN const double ORKInvalidDBHLValue ORK_AVAILABLE_DECL; + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryResult : ORKResult + +@property (nonatomic, assign) double outputVolume; + +@property (nonatomic, assign) NSTimeInterval tonePlaybackDuration; + +@property (nonatomic, assign) NSTimeInterval postStimulusDelay; + +@property (nonatomic, copy, nullable) ORKHeadphoneTypeIdentifier headphoneType; + +@property (nonatomic, copy, nullable) NSArray *samples; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryFrequencySample : NSObject + +@property (nonatomic, assign) double frequency; + +@property (nonatomic, assign) double calculatedThreshold; + +@property (nonatomic, assign) ORKAudioChannel channel; + +@property (nonatomic, copy, nullable) NSArray *units; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryUnit : NSObject + +@property (nonatomic, assign) double dBHLValue; + +@property (nonatomic, assign) NSTimeInterval startOfUnitTimeStamp; + +@property (nonatomic, assign) NSTimeInterval preStimulusDelay; + +@property (nonatomic, assign) NSTimeInterval userTapTimeStamp; + +@property (nonatomic, assign) NSTimeInterval timeoutTimeStamp; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.m new file mode 100755 index 0000000..951ab75 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryResult.m @@ -0,0 +1,206 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + +const double ORKInvalidDBHLValue = DBL_MAX; + +@implementation ORKdBHLToneAudiometryResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, outputVolume); + ORK_ENCODE_DOUBLE(aCoder, tonePlaybackDuration); + ORK_ENCODE_DOUBLE(aCoder, postStimulusDelay); + ORK_ENCODE_OBJ(aCoder, headphoneType); + ORK_ENCODE_OBJ(aCoder, samples); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, outputVolume); + ORK_DECODE_DOUBLE(aDecoder, tonePlaybackDuration); + ORK_DECODE_DOUBLE(aDecoder, postStimulusDelay); + ORK_DECODE_OBJ(aDecoder, headphoneType); + ORK_DECODE_OBJ_ARRAY(aDecoder, samples, ORKdBHLToneAudiometryFrequencySample); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.outputVolume == castObject.outputVolume && + self.tonePlaybackDuration == castObject.tonePlaybackDuration && + self.postStimulusDelay == castObject.postStimulusDelay && + ORKEqualObjects(self.headphoneType, castObject.headphoneType) && + ORKEqualObjects(self.samples, castObject.samples)) ; +} + +- (NSUInteger)hash { + return super.hash ^ self.samples.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKdBHLToneAudiometryResult *result = [super copyWithZone:zone]; + result.outputVolume = self.outputVolume; + result.headphoneType = [self.headphoneType copy]; + result.tonePlaybackDuration = self.tonePlaybackDuration; + result.postStimulusDelay = self.postStimulusDelay; + result.samples = [self.samples copy]; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; outputvolume: %.1lf; samples: %@; headphoneType: %@; tonePlaybackDuration: %.1lf; postStimulusDelay: %.1lf%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.outputVolume, self.samples, self.headphoneType, self.tonePlaybackDuration, self.postStimulusDelay, self.descriptionSuffix]; +} + +@end + + +@implementation ORKdBHLToneAudiometryFrequencySample + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, frequency); + ORK_ENCODE_DOUBLE(aCoder, calculatedThreshold); + ORK_ENCODE_INTEGER(aCoder, channel); + ORK_ENCODE_OBJ(aCoder, units); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, frequency); + ORK_DECODE_DOUBLE(aDecoder, calculatedThreshold); + ORK_DECODE_INTEGER(aDecoder, channel); + ORK_DECODE_OBJ_ARRAY(aDecoder, units, ORKdBHLToneAudiometryUnit); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.frequency == castObject.frequency) && + (self.calculatedThreshold == castObject.calculatedThreshold) && + (self.channel == castObject.channel) && + ORKEqualObjects(self.units, castObject.units)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKdBHLToneAudiometryFrequencySample *sample = [[[self class] allocWithZone:zone] init]; + sample.frequency = self.frequency; + sample.calculatedThreshold = self.calculatedThreshold; + sample.channel = self.channel; + sample.units = self.units; + return sample; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@: %p; frequency: %.1lf; calculatedThreshold: %.1lf; channel: %ld; units: %@>", self.class.description, self, self.frequency, self.calculatedThreshold, (long)self.channel, self.units]; +} + +@end + +@implementation ORKdBHLToneAudiometryUnit + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_DOUBLE(aCoder, dBHLValue); + ORK_ENCODE_DOUBLE(aCoder, timeoutTimeStamp); + ORK_ENCODE_DOUBLE(aCoder, userTapTimeStamp); + ORK_ENCODE_DOUBLE(aCoder, startOfUnitTimeStamp); + ORK_ENCODE_DOUBLE(aCoder, preStimulusDelay); +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, dBHLValue); + ORK_DECODE_DOUBLE(aDecoder, timeoutTimeStamp); + ORK_DECODE_DOUBLE(aDecoder, userTapTimeStamp); + ORK_DECODE_DOUBLE(aDecoder, startOfUnitTimeStamp); + ORK_DECODE_DOUBLE(aDecoder, preStimulusDelay); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + + return ((self.dBHLValue == castObject.dBHLValue) && + (self.timeoutTimeStamp == castObject.timeoutTimeStamp) && + (self.userTapTimeStamp == castObject.userTapTimeStamp) && + (self.preStimulusDelay == castObject.preStimulusDelay) && + (self.startOfUnitTimeStamp == castObject.startOfUnitTimeStamp)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKdBHLToneAudiometryUnit *unit = [[[self class] allocWithZone:zone] init]; + unit.dBHLValue = self.dBHLValue; + unit.timeoutTimeStamp = self.timeoutTimeStamp; + unit.userTapTimeStamp = self.userTapTimeStamp; + unit.startOfUnitTimeStamp = self.startOfUnitTimeStamp; + unit.preStimulusDelay = self.preStimulusDelay; + return unit; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@; dBHLValue: %.1lf; timeoutTimeStamp %.5lf; userTapTimeStamp %.5lf; startOfUnitTimeStamp: %.5lf; preStimulusDelay %.1lf>", self.class.description, self.dBHLValue, self.timeoutTimeStamp, self.userTapTimeStamp, self.startOfUnitTimeStamp, self.preStimulusDelay]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.h new file mode 100755 index 0000000..fdae01b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryStep : ORKActiveStep + +@property (nonatomic, assign) NSTimeInterval toneDuration; + +@property (nonatomic, assign) NSTimeInterval maxRandomPreStimulusDelay; + +@property (nonatomic, assign) NSTimeInterval postStimulusDelay; + +@property (nonatomic, assign) NSInteger maxNumberOfTransitionsPerFrequency; + +@property (nonatomic, assign) double initialdBHLValue; + +@property (nonatomic, assign) double dBHLStepUpSize; + +@property (nonatomic, assign) double dBHLStepUpSizeFirstMiss; + +@property (nonatomic, assign) double dBHLStepUpSizeSecondMiss; + +@property (nonatomic, assign) double dBHLStepUpSizeThirdMiss; + +@property (nonatomic, assign) double dBHLStepDownSize; + +@property (nonatomic, assign) double dBHLMinimumThreshold; + +@property (nonatomic, strong) ORKHeadphoneTypeIdentifier headphoneType; + +@property (nonatomic, assign) ORKAudioChannel earPreference; + +@property (nonatomic, copy, nullable) NSArray *frequencyList; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.m new file mode 100755 index 0000000..2feb371 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStep.m @@ -0,0 +1,186 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryStep.h" + +#import "ORKdBHLToneAudiometryStepViewController.h" + +#import "ORKHelpers_Internal.h" + +#define ORKdBHLToneAudiometryTaskToneMinimumDuration 1.0 +#define ORKdBHLToneAudiometryTaskDefaultMaxRandomPreStimulusDelay 2.0 +#define ORKdBHLToneAudiometryTaskDefaultMaxPostStimulusDelay 1.0 +#define ORKdBHLToneAudiometryTaskDefaultTransitionsPerFrequency 20 +#define ORKdBHLToneAudiometryTaskInitialdBHLValue 30.0 +#define ORKdBHLToneAudiometryTaskdBHLStepUpSize 5.0 +#define ORKdBHLToneAudiometryTaskdBHLStepUpSizeFirstMiss 20.0 +#define ORKdBHLToneAudiometryTaskdBHLStepUpSizeSecondMiss 10.0 +#define ORKdBHLToneAudiometryTaskdBHLStepUpSizeThirdMiss 10.0 +#define ORKdBHLToneAudiometryTaskdBHLStepDownSize 10.0 +#define ORKdBHLToneAudiometryTaskdBHLMinimumThreshold -10.0 + +@implementation ORKdBHLToneAudiometryStep + ++ (Class)stepViewControllerClass { + return [ORKdBHLToneAudiometryStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + self.toneDuration = ORKdBHLToneAudiometryTaskToneMinimumDuration; + self.maxRandomPreStimulusDelay = ORKdBHLToneAudiometryTaskDefaultMaxRandomPreStimulusDelay; + self.postStimulusDelay = ORKdBHLToneAudiometryTaskDefaultMaxPostStimulusDelay; + self.maxNumberOfTransitionsPerFrequency = ORKdBHLToneAudiometryTaskDefaultTransitionsPerFrequency; + self.initialdBHLValue = ORKdBHLToneAudiometryTaskInitialdBHLValue; + self.dBHLStepUpSize = ORKdBHLToneAudiometryTaskdBHLStepUpSize; + self.dBHLStepUpSizeFirstMiss = ORKdBHLToneAudiometryTaskdBHLStepUpSizeFirstMiss; + self.dBHLStepUpSizeSecondMiss = ORKdBHLToneAudiometryTaskdBHLStepUpSizeSecondMiss; + self.dBHLStepUpSizeThirdMiss = ORKdBHLToneAudiometryTaskdBHLStepUpSizeThirdMiss; + self.dBHLStepDownSize = ORKdBHLToneAudiometryTaskdBHLStepDownSize; + self.dBHLMinimumThreshold = ORKdBHLToneAudiometryTaskdBHLMinimumThreshold; + self.frequencyList = @[@1000.0, @2000.0, @3000.0, @4000.0, @8000.0, @1000.0, @500.0, @250.0]; + self.stepDuration = CGFLOAT_MAX; + self.shouldShowDefaultTimer = NO; +} + +- (void)validateParameters { + [super validateParameters]; + + if (self.toneDuration < ORKdBHLToneAudiometryTaskToneMinimumDuration) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"pulse duration cannot be shorter than %@ seconds.", @(ORKdBHLToneAudiometryTaskToneMinimumDuration)] userInfo:nil]; + } + if (self.maxNumberOfTransitionsPerFrequency <= 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"number of transitions per frequency cannot be less than or equal to 0"] userInfo:nil]; + } + if ((self.dBHLStepDownSize <= 0) || self.dBHLStepUpSize <=0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"step size cannot be less than or equal to 0"] userInfo:nil]; + } + if (self.frequencyList.count == 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"frequency list cannot be empty"] userInfo:nil]; + } +} + +- (BOOL)startsFinished { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKdBHLToneAudiometryStep *step = [super copyWithZone:zone]; + step.toneDuration = self.toneDuration; + step.maxRandomPreStimulusDelay = self.maxRandomPreStimulusDelay; + step.postStimulusDelay = self.postStimulusDelay; + step.maxNumberOfTransitionsPerFrequency = self.maxNumberOfTransitionsPerFrequency; + step.initialdBHLValue = self.initialdBHLValue; + step.dBHLStepDownSize = self.dBHLStepDownSize; + step.dBHLStepUpSize = self.dBHLStepUpSize; + step.dBHLMinimumThreshold = self.dBHLMinimumThreshold; + step.dBHLStepUpSizeFirstMiss = self.dBHLStepUpSizeFirstMiss; + step.dBHLStepUpSizeSecondMiss = self.dBHLStepUpSizeSecondMiss; + step.dBHLStepUpSizeThirdMiss = self.dBHLStepUpSizeThirdMiss; + step.headphoneType = self.headphoneType; + step.earPreference = self.earPreference; + step.frequencyList = self.frequencyList; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, toneDuration); + ORK_DECODE_DOUBLE(aDecoder, maxRandomPreStimulusDelay); + ORK_DECODE_DOUBLE(aDecoder, postStimulusDelay); + ORK_DECODE_DOUBLE(aDecoder, initialdBHLValue); + ORK_DECODE_DOUBLE(aDecoder, dBHLStepDownSize); + ORK_DECODE_DOUBLE(aDecoder, dBHLStepUpSize); + ORK_DECODE_DOUBLE(aDecoder, dBHLStepUpSizeFirstMiss); + ORK_DECODE_DOUBLE(aDecoder, dBHLStepUpSizeSecondMiss); + ORK_DECODE_DOUBLE(aDecoder, dBHLStepUpSizeThirdMiss); + ORK_DECODE_DOUBLE(aDecoder, dBHLMinimumThreshold); + ORK_DECODE_INTEGER(aDecoder, maxNumberOfTransitionsPerFrequency); + ORK_DECODE_INTEGER(aDecoder, earPreference); + ORK_DECODE_OBJ(aDecoder, headphoneType); + ORK_DECODE_OBJ_ARRAY(aDecoder, frequencyList, NSNumber); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, toneDuration); + ORK_ENCODE_DOUBLE(aCoder, maxRandomPreStimulusDelay); + ORK_ENCODE_DOUBLE(aCoder, postStimulusDelay); + ORK_ENCODE_DOUBLE(aCoder, initialdBHLValue); + ORK_ENCODE_DOUBLE(aCoder, dBHLStepDownSize); + ORK_ENCODE_DOUBLE(aCoder, dBHLStepUpSize); + ORK_ENCODE_DOUBLE(aCoder, dBHLStepUpSizeFirstMiss); + ORK_ENCODE_DOUBLE(aCoder, dBHLStepUpSizeSecondMiss); + ORK_ENCODE_DOUBLE(aCoder, dBHLStepUpSizeThirdMiss); + ORK_ENCODE_DOUBLE(aCoder, dBHLMinimumThreshold); + ORK_ENCODE_INTEGER(aCoder, maxNumberOfTransitionsPerFrequency); + ORK_ENCODE_INTEGER(aCoder, earPreference); + ORK_ENCODE_OBJ(aCoder, headphoneType); + ORK_ENCODE_OBJ(aCoder, frequencyList); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && (self.toneDuration == castObject.toneDuration) + && (self.maxRandomPreStimulusDelay == castObject.maxRandomPreStimulusDelay) + && (self.postStimulusDelay == castObject.postStimulusDelay) + && (self.maxNumberOfTransitionsPerFrequency == castObject.maxNumberOfTransitionsPerFrequency) + && (self.initialdBHLValue == castObject.initialdBHLValue) + && (self.dBHLStepDownSize == castObject.dBHLStepDownSize) + && (self.dBHLStepUpSize == castObject.dBHLStepUpSize) + && (self.dBHLStepUpSizeFirstMiss == castObject.dBHLStepUpSizeFirstMiss) + && (self.dBHLStepUpSizeSecondMiss == castObject.dBHLStepUpSizeSecondMiss) + && (self.dBHLStepUpSizeThirdMiss == castObject.dBHLStepUpSizeThirdMiss) + && (self.dBHLMinimumThreshold == castObject.dBHLMinimumThreshold) + && (self.earPreference == castObject.earPreference) + && ORKEqualObjects(self.headphoneType, castObject.headphoneType) + && ORKEqualObjects(self.frequencyList, castObject.frequencyList)); +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.h new file mode 100755 index 0000000..a9aea7d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKdBHLToneAudiometryStepViewController : ORKActiveStepViewController + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.m new file mode 100755 index 0000000..eae4e16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/ORKdBHLToneAudiometryStepViewController.m @@ -0,0 +1,435 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKdBHLToneAudiometryStepViewController.h" + +#import "ORKActiveStepView.h" +#import "ORKActiveStep_Internal.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKNavigationContainerView.h" +#import "ORKStepContainerView.h" + +#import "ORKdBHLToneAudiometryAudioGenerator.h" +#import "ORKRoundTappingButton.h" +#import "ORKdBHLToneAudiometryContentView.h" +#import "ORKStepContainerView_Private.h" + +#import "ORKActiveStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKdBHLToneAudiometryResult.h" +#import "ORKdBHLToneAudiometryStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKTaskViewController_Private.h" +#import "ORKOrderedTask.h" + +@interface ORKdBHLToneAudiometryTransitions: NSObject + +@property (nonatomic, assign) float userInitiated; +@property (nonatomic, assign) float totalTransitions; + +@end + +@implementation ORKdBHLToneAudiometryTransitions + +- (instancetype)init +{ + self = [super init]; + if (self) { + _userInitiated = 1; + _totalTransitions = 1; + } + return self; +} + +@end + +@interface ORKdBHLToneAudiometryStepViewController () { + double _prevFreq; + double _currentdBHL; + double _dBHLStepUpSize; + double _dBHLStepDownSize; + double _dBHLMinimumThreshold; + int _currentTestIndex; + int _indexOfFreqLoopList; + NSUInteger _indexOfStepUpMissingList; + int _numberOfTransitionsPerFreq; + NSInteger _maxNumberOfTransitionsPerFreq; + BOOL _initialDescent; + BOOL _ackOnce; + BOOL _usingMissingList; + ORKdBHLToneAudiometryAudioGenerator *_audioGenerator; + NSArray *_freqLoopList; + NSArray *_stepUpMissingList; + NSMutableArray *_arrayOfResultSamples; + NSMutableArray *_arrayOfResultUnits; + NSMutableDictionary *_transitionsDictionary; + UIImpactFeedbackGenerator *_hapticFeedback; + ORKdBHLToneAudiometryFrequencySample *_resultSample; + ORKdBHLToneAudiometryUnit *_resultUnit; + ORKAudioChannel _audioChannel; + dispatch_block_t _preStimulusDelayWorkBlock; + dispatch_block_t _pulseDurationWorkBlock; + dispatch_block_t _postStimulusDelayWorkBlock; +} + +@property (nonatomic, strong) ORKdBHLToneAudiometryContentView *dBHLToneAudiometryContentView; + +@end + +@implementation ORKdBHLToneAudiometryStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + + if (self) { + self.suspendIfInactive = YES; + _indexOfFreqLoopList = 0; + _indexOfStepUpMissingList = 0; + _initialDescent = YES; + _ackOnce = NO; + _usingMissingList = YES; + _prevFreq = 0; + _currentTestIndex = 0; + _transitionsDictionary = [NSMutableDictionary dictionary]; + _arrayOfResultSamples = [NSMutableArray array]; + _arrayOfResultUnits = [NSMutableArray array]; + } + + return self; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + // Don't show next button + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (ORKdBHLToneAudiometryStep *)dBHLToneAudiometryStep { + return (ORKdBHLToneAudiometryStep *)self.step; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self configureStep]; +} + +- (void)configureStep { + ORKdBHLToneAudiometryStep *dBHLTAStep = [self dBHLToneAudiometryStep]; + + _maxNumberOfTransitionsPerFreq = dBHLTAStep.maxNumberOfTransitionsPerFrequency; + _freqLoopList = dBHLTAStep.frequencyList; + _stepUpMissingList = @[ [NSNumber numberWithDouble:dBHLTAStep.dBHLStepUpSizeFirstMiss], + [NSNumber numberWithDouble:dBHLTAStep.dBHLStepUpSizeSecondMiss], + [NSNumber numberWithDouble:dBHLTAStep.dBHLStepUpSizeThirdMiss] ]; + _currentdBHL = dBHLTAStep.initialdBHLValue; + _dBHLStepDownSize = dBHLTAStep.dBHLStepDownSize; + _dBHLStepUpSize = dBHLTAStep.dBHLStepUpSize; + _dBHLMinimumThreshold = dBHLTAStep.dBHLMinimumThreshold; + + self.dBHLToneAudiometryContentView = [[ORKdBHLToneAudiometryContentView alloc] init]; + self.activeStepView.activeCustomView = self.dBHLToneAudiometryContentView; + self.activeStepView.customContentFillsAvailableSpace = YES; + [self.activeStepView.navigationFooterView setHidden:YES]; + + [self.dBHLToneAudiometryContentView.tapButton addTarget:self action:@selector(tapButtonPressed) forControlEvents:UIControlEventTouchDown]; + + _audioChannel = [self dBHLToneAudiometryStep].earPreference; + _audioGenerator = [[ORKdBHLToneAudiometryAudioGenerator alloc] initForHeadphones:[self dBHLToneAudiometryStep].headphoneType]; + _audioGenerator.delegate = self; + _hapticFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle: UIImpactFeedbackStyleHeavy]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [self start]; +} + +- (void)animatedBHLButton { + [self.dBHLToneAudiometryContentView.layer removeAllAnimations]; + [UIView animateWithDuration:0.1 + delay:0.0 + usingSpringWithDamping:0.1 + initialSpringVelocity:0.0 + options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionAllowUserInteraction + animations:^{ + [self.dBHLToneAudiometryContentView.tapButton setTransform:CGAffineTransformMakeScale(0.88, 0.88)]; + } completion:^(BOOL finished) { + [UIView animateWithDuration:1.0 + delay:0.0 + usingSpringWithDamping:0.4 + initialSpringVelocity:0.0 + options:UIViewAnimationOptionCurveLinear|UIViewAnimationOptionAllowUserInteraction + animations:^{ + [self.dBHLToneAudiometryContentView.tapButton setTransform:CGAffineTransformMakeScale(1.0, 1.0)]; + } completion:nil]; + }]; +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _audioGenerator.delegate = nil; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [self stopAudio]; +} + +- (ORKStepResult *)result { + ORKStepResult *sResult = [super result]; + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = sResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:sResult.results]; + + ORKdBHLToneAudiometryResult *toneResult = [[ORKdBHLToneAudiometryResult alloc] initWithIdentifier:self.step.identifier]; + toneResult.startDate = sResult.startDate; + toneResult.endDate = now; + toneResult.samples = [_arrayOfResultSamples copy]; + toneResult.outputVolume = [AVAudioSession sharedInstance].outputVolume; + toneResult.headphoneType = self.dBHLToneAudiometryStep.headphoneType; + toneResult.tonePlaybackDuration = [self dBHLToneAudiometryStep].toneDuration; + toneResult.postStimulusDelay = [self dBHLToneAudiometryStep].postStimulusDelay; + [results addObject:toneResult]; + + sResult.results = [results copy]; + + return sResult; +} + +- (void)stepDidFinish { + [super stepDidFinish]; + [self stopAudio]; + [self.dBHLToneAudiometryContentView finishStep:self]; + [self goForward]; +} + +- (void)start { + [super start]; + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; +} + +- (void)stopAudio { + [_audioGenerator stop]; + if (_preStimulusDelayWorkBlock) { + dispatch_block_cancel(_preStimulusDelayWorkBlock); + dispatch_block_cancel(_pulseDurationWorkBlock); + dispatch_block_cancel(_postStimulusDelayWorkBlock); + } +} + +- (void)estimatedBHLAndPlayToneWithFrequency: (NSNumber *)freq { + [self stopAudio]; + if (_prevFreq != [freq doubleValue]) { + CGFloat progress = 0.001 + (CGFloat)_indexOfFreqLoopList / _freqLoopList.count; + [self.dBHLToneAudiometryContentView setProgress:progress + animated:YES]; + + _numberOfTransitionsPerFreq = 0; + _currentdBHL = [self dBHLToneAudiometryStep].initialdBHLValue; + _initialDescent = YES; + _ackOnce = NO; + _transitionsDictionary = nil; + _transitionsDictionary = [NSMutableDictionary dictionary]; + if (_resultSample) { + _resultSample.units = [_arrayOfResultUnits copy]; + } + _arrayOfResultUnits = [NSMutableArray array]; + _prevFreq = [freq doubleValue]; + _resultSample = [ORKdBHLToneAudiometryFrequencySample new]; + _resultSample.channel = _audioChannel; + _resultSample.frequency = [freq doubleValue]; + _resultSample.calculatedThreshold = ORKInvalidDBHLValue; + [_arrayOfResultSamples addObject:_resultSample]; + } else { + _numberOfTransitionsPerFreq += 1; + if (_numberOfTransitionsPerFreq >= _maxNumberOfTransitionsPerFreq) { + _indexOfFreqLoopList += 1; + if (_indexOfFreqLoopList >= _freqLoopList.count) { + _resultSample.units = [_arrayOfResultUnits copy]; + [self finish]; + return; + } else { + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + return; + } + } + } + + _resultUnit = [ORKdBHLToneAudiometryUnit new]; + _resultUnit.dBHLValue = _currentdBHL; + _resultUnit.startOfUnitTimeStamp = self.runtime; + [_arrayOfResultUnits addObject:_resultUnit]; + + ORKdBHLToneAudiometryTransitions *currentTransition = [_transitionsDictionary objectForKey:[NSNumber numberWithFloat:_currentdBHL]]; + if (!_initialDescent) { + if (currentTransition) { + currentTransition.userInitiated += 1; + currentTransition.totalTransitions += 1; + } else { + currentTransition = [[ORKdBHLToneAudiometryTransitions alloc] init]; + [_transitionsDictionary setObject:currentTransition forKey:[NSNumber numberWithFloat:_currentdBHL]]; + } + } + const NSTimeInterval toneDuration = [self dBHLToneAudiometryStep].toneDuration; + const NSTimeInterval postStimulusDelay = [self dBHLToneAudiometryStep].postStimulusDelay; + + double delay1 = arc4random_uniform([self dBHLToneAudiometryStep].maxRandomPreStimulusDelay - 1); + double delay2 = (double)arc4random_uniform(10)/10; + double preStimulusDelay = delay1 + delay2 + 1; + _resultUnit.preStimulusDelay = preStimulusDelay; + + _preStimulusDelayWorkBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{ + [_audioGenerator playSoundAtFrequency:[freq floatValue] onChannel:_audioChannel dBHL:_currentdBHL]; + }); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(preStimulusDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), _preStimulusDelayWorkBlock); + + _pulseDurationWorkBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{ + [_audioGenerator stop]; + }); + // adding 0.2 seconds to account for the fadeInDuration which is being set in ORKdBHLToneAudiometryAudioGenerator + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((preStimulusDelay + toneDuration + 0.2) * NSEC_PER_SEC)), dispatch_get_main_queue(), _pulseDurationWorkBlock); + + ORKWeakTypeOf(self)weakSelf = self; + _postStimulusDelayWorkBlock = dispatch_block_create(DISPATCH_BLOCK_INHERIT_QOS_CLASS, ^{ + ORKStrongTypeOf(self) strongSelf = weakSelf; + NSUInteger storedTestIndex = _currentTestIndex; + if (_currentTestIndex == storedTestIndex) { + if (_initialDescent && _ackOnce) { + _initialDescent = NO; + ORKdBHLToneAudiometryTransitions *newTransition = [[ORKdBHLToneAudiometryTransitions alloc] init]; + newTransition.userInitiated -= 1; + [_transitionsDictionary setObject:newTransition forKey:[NSNumber numberWithFloat:_currentdBHL]]; + } + if (_usingMissingList && (_indexOfStepUpMissingList < _stepUpMissingList.count)) { + _currentdBHL = _currentdBHL + [_stepUpMissingList[_indexOfStepUpMissingList] doubleValue]; + _indexOfStepUpMissingList = _indexOfStepUpMissingList + 1; + } else { + _usingMissingList = NO; + _currentdBHL = _currentdBHL + _dBHLStepUpSize; + } + if (currentTransition) { + currentTransition.userInitiated -= 1; + } + _resultUnit.timeoutTimeStamp = self.runtime; + _currentTestIndex += 1; + [strongSelf estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + return; + } + }); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((preStimulusDelay + toneDuration + postStimulusDelay) * NSEC_PER_SEC)), dispatch_get_main_queue(), _postStimulusDelayWorkBlock); + +} + +- (void)tapButtonPressed { + [self animatedBHLButton]; + _ackOnce = YES; + [_hapticFeedback impactOccurred]; + _currentTestIndex += 1; + _resultUnit.userTapTimeStamp = self.runtime; + [self stopAudio]; + BOOL falseResponseTap = (_resultUnit.userTapTimeStamp - _resultUnit.startOfUnitTimeStamp < _resultUnit.preStimulusDelay); + if (falseResponseTap) { + NSNumber *currentKey = [NSNumber numberWithFloat:_currentdBHL]; + ORKdBHLToneAudiometryTransitions *currentTransitionObject = [_transitionsDictionary objectForKey:currentKey]; + currentTransitionObject.userInitiated -= 1; + } else if ([self validateResultFordBHL:_currentdBHL]) { + _resultSample.calculatedThreshold = _currentdBHL; + _indexOfFreqLoopList += 1; + if (_indexOfFreqLoopList >= _freqLoopList.count) { + _resultSample.units = [_arrayOfResultUnits copy]; + [self finish]; + return; + } else { + _currentdBHL = [self dBHLToneAudiometryStep].initialdBHLValue; + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + return; + } + } + + if ((_currentdBHL - _dBHLStepDownSize >= _dBHLMinimumThreshold) && !falseResponseTap) { + _usingMissingList = NO; + _currentdBHL = _currentdBHL - _dBHLStepDownSize; + } + + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + return; +} + +- (BOOL)validateResultFordBHL:(float)dBHL { + NSNumber *currentKey = [NSNumber numberWithFloat:_currentdBHL]; + ORKdBHLToneAudiometryTransitions *currentTransitionObject = [_transitionsDictionary objectForKey:currentKey]; + if ((currentTransitionObject.userInitiated/currentTransitionObject.totalTransitions >= 0.5) && currentTransitionObject.totalTransitions >= 2) { + ORKdBHLToneAudiometryTransitions *previousTransitionObject = [_transitionsDictionary objectForKey:[NSNumber numberWithFloat:(dBHL - _dBHLStepUpSize)]]; + if ((previousTransitionObject.userInitiated/previousTransitionObject.totalTransitions <= 0.5) && (previousTransitionObject.totalTransitions >= 2)) { + if (currentTransitionObject.totalTransitions == 2) { + if (currentTransitionObject.userInitiated/currentTransitionObject.totalTransitions == 1.0) { + _resultSample.calculatedThreshold = dBHL; + return YES; + } else { + return NO; + } + } else { + _resultSample.calculatedThreshold = dBHL; + return YES; + } + } + } + return NO; +} + +- (void)toneWillStartClipping { + if (_usingMissingList + && (_indexOfStepUpMissingList <= _stepUpMissingList.count)) { + _usingMissingList = NO; + _currentdBHL = _currentdBHL - [_stepUpMissingList[_indexOfStepUpMissingList - (_indexOfStepUpMissingList == 0 ? 0 : 1)] doubleValue] + _dBHLStepUpSize; + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + } else { + _indexOfFreqLoopList += 1; + if (_indexOfFreqLoopList >= _freqLoopList.count) { + _resultSample.units = [_arrayOfResultUnits copy]; + [self finish]; + } else { + [self estimatedBHLAndPlayToneWithFrequency:_freqLoopList[_indexOfFreqLoopList]]; + } + } +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence1.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence1.wav new file mode 100755 index 0000000..78eec34 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence1.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence2.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence2.wav new file mode 100755 index 0000000..f08df89 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence2.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence3.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence3.wav new file mode 100755 index 0000000..d54c17e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence3.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence4.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence4.wav new file mode 100755 index 0000000..76bc183 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence4.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence5.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence5.wav new file mode 100755 index 0000000..04e8d79 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence5.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence6.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence6.wav new file mode 100755 index 0000000..2d61698 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence6.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence7.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence7.wav new file mode 100755 index 0000000..74cbe81 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Sentence7.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/SentencesList.txt b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/SentencesList.txt new file mode 100755 index 0000000..ab9d32b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/SentencesList.txt @@ -0,0 +1,7 @@ +The actor tried three green pictures +The girl saved two great roses +The artist sent sixteen giant glasses +The boy wanted two small coats +The teacher saved three special roses +The actor takes nine big gifts +The actress has three special bags diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/TrackLayer.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/TrackLayer.swift new file mode 100755 index 0000000..2376aae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/TrackLayer.swift @@ -0,0 +1,105 @@ +/* + Copyright (c) 2019, Novartis. + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +internal class TrackLayer: CAShapeLayer { + + struct Setting { + var startAngle = Double() + var barWidth = CGFloat() + var barColor = UIColor() + var trackingColor = UIColor() + } + + internal var setting = Setting() + internal var degree: Double = 0 + internal var hollowRadius: CGFloat { + return (bounds.width * 0.5) - setting.barWidth + } + internal var currentCenter: CGPoint { + return CGPoint(x: bounds.midX, y: bounds.midY) + } + internal var hollowRect: CGRect { + return CGRect( + x: currentCenter.x - hollowRadius, + y: currentCenter.y - hollowRadius, + width: hollowRadius * 2.0, + height: hollowRadius * 2.0) + } + internal init(bounds: CGRect, setting: Setting) { + super.init() + self.bounds = bounds + self.setting = setting + cornerRadius = bounds.size.width * 0.5 + masksToBounds = true + position = currentCenter + backgroundColor = setting.barColor.cgColor + mask() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override internal func draw(in ctx: CGContext) { + drawTrack(ctx: ctx) + } + + private func mask() { + let maskLayer = CAShapeLayer() + maskLayer.bounds = bounds + let ovalRect = hollowRect + let path = UIBezierPath(ovalIn: ovalRect) + path.append(UIBezierPath(rect: maskLayer.bounds)) + maskLayer.path = path.cgPath + maskLayer.position = currentCenter + maskLayer.fillRule = CAShapeLayerFillRule.evenOdd + mask = maskLayer + } + + private func drawTrack(ctx: CGContext) { + let adjustDegree = Math.adjustDegree(setting.startAngle, degree: degree) + let centerX = currentCenter.x + let centerY = currentCenter.y + let radius = min(centerX, centerY) + ctx.setFillColor(setting.trackingColor.cgColor) + ctx.beginPath() + ctx.move(to: CGPoint(x: centerX, y: centerY)) + ctx.addArc(center: CGPoint(x: centerX, y: centerY), + radius: radius, + startAngle: CGFloat(Math.degreesToRadians(setting.startAngle)), + endAngle: CGFloat(Math.degreesToRadians(adjustDegree)), + clockwise: false) + + ctx.closePath() + ctx.fillPath() + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.h new file mode 100755 index 0000000..84f158e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface UITouch (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryInView:(UIView *)view allTouches:(NSArray *)allTouches; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.m new file mode 100755 index 0000000..e4e6551 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/UITouch+ORKJSONDictionary.m @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "UITouch+ORKJSONDictionary.h" + + +@implementation UITouch (ORKJSONDictionary) + +- (NSDictionary *)ork_JSONDictionaryInView:(UIView *)view allTouches:(NSArray *)allTouches { + CGPoint point = [self locationInView:view]; + + CGRect touchViewBounds = view.bounds; + + NSDictionary *dictionary = @{@"timestamp": [NSDecimalNumber numberWithDouble:self.timestamp], + @"phase": @(self.phase), + @"index": @([allTouches indexOfObject:self]), + @"x": @(point.x), + @"y": @(point.y), + @"width": @(touchViewBounds.size.width), + @"height": @(touchViewBounds.size.height) + }; + return dictionary; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/VolumeCalibration.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/VolumeCalibration.wav new file mode 100755 index 0000000..e4d99cf Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/VolumeCalibration.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Window.wav b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Window.wav new file mode 100755 index 0000000..34a5809 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/Window.wav differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_AIRPODS.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_AIRPODS.plist new file mode 100755 index 0000000..c98ca25 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_AIRPODS.plist @@ -0,0 +1,28 @@ + + + + + 125 + 88.97 + 250 + 86.30 + 500 + 84.49 + 750 + 83.59 + 1000 + 83.89 + 1500 + 87.60 + 2000 + 90.07 + 3000 + 92.51 + 4000 + 88.87 + 6000 + 91.46 + 8000 + 89.61 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_EARPODS.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_EARPODS.plist new file mode 100755 index 0000000..05a46de --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/frequency_dBSPL_EARPODS.plist @@ -0,0 +1,28 @@ + + + + + 125 + 91.28 + 250 + 88.38 + 500 + 86.82 + 750 + 86.16 + 1000 + 86.37 + 1500 + 89.83 + 2000 + 91.62 + 3000 + 92.31 + 4000 + 90.19 + 6000 + 93.91 + 8000 + 90.04 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_AIRPODS.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_AIRPODS.plist new file mode 100755 index 0000000..26dc1b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_AIRPODS.plist @@ -0,0 +1,28 @@ + + + + + 125 + 31 + 250 + 21 + 500 + 13 + 750 + 9 + 1000 + 7 + 1500 + 10 + 2000 + 12 + 3000 + 13.5 + 4000 + 16 + 6000 + 16 + 8000 + 15.5 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_EARPODS.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_EARPODS.plist new file mode 100755 index 0000000..26dc1b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/retspl_EARPODS.plist @@ -0,0 +1,28 @@ + + + + + 125 + 31 + 250 + 21 + 500 + 13 + 750 + 9 + 1000 + 7 + 1500 + 10 + 2000 + 12 + 3000 + 13.5 + 4000 + 16 + 6000 + 16 + 8000 + 15.5 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/splMeter_sensitivity_offset.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/splMeter_sensitivity_offset.plist new file mode 100755 index 0000000..ab67873 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/splMeter_sensitivity_offset.plist @@ -0,0 +1,12 @@ + + + + + iPhone + -23.3 + iPod touch + -23.3 + iPad + -29.3 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_AIRPODS.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_AIRPODS.plist new file mode 100755 index 0000000..b6ce2c3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_AIRPODS.plist @@ -0,0 +1,38 @@ + + + + + 1.0000 + 0 + 0.9375 + -3 + 0.8750 + -6.5 + 0.8125 + -10 + 0.7500 + -13.5 + 0.6875 + -17 + 0.6250 + -21 + 0.5625 + -25 + 0.5000 + -29 + 0.4375 + -33 + 0.3750 + -37.5 + 0.3125 + -42 + 0.2500 + -47 + 0.1875 + -52.5 + 0.1250 + -58.5 + 0.0625 + -65.5 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_WIRED.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_WIRED.plist new file mode 100755 index 0000000..45301d9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ActiveTasks/volume_curve_WIRED.plist @@ -0,0 +1,38 @@ + + + + + 1.0000 + -0.5 + 0.9375 + -3.2 + 0.8750 + -6.7 + 0.8125 + -10 + 0.7500 + -13.6 + 0.6875 + -16.9 + 0.6250 + -20.9 + 0.5625 + -24.9 + 0.5000 + -28.9 + 0.4375 + -32.9 + 0.3750 + -37.3 + 0.3125 + -42 + 0.2500 + -46.9 + 0.1875 + -52.3 + 0.1250 + -58.4 + 0.0625 + -65.6 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_01@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_01@2x.m4v new file mode 100755 index 0000000..bb5c8ba Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_01@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_02@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_02@2x.m4v new file mode 100755 index 0000000..5629fa6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_02@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_03@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_03@2x.m4v new file mode 100755 index 0000000..bb13aca Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_03@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_04@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_04@2x.m4v new file mode 100755 index 0000000..6855d61 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_04@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_05@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_05@2x.m4v new file mode 100755 index 0000000..6292b22 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_05@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_06@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_06@2x.m4v new file mode 100755 index 0000000..dc4b128 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_06@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_07@2x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_07@2x.m4v new file mode 100755 index 0000000..3982284 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@2x/consent_07@2x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_01@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_01@3x.m4v new file mode 100755 index 0000000..ab3cbda Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_01@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_02@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_02@3x.m4v new file mode 100755 index 0000000..dd836ec Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_02@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_03@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_03@3x.m4v new file mode 100755 index 0000000..851058c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_03@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_04@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_04@3x.m4v new file mode 100755 index 0000000..3c8bebd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_04@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_05@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_05@3x.m4v new file mode 100755 index 0000000..5d8c223 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_05@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_06@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_06@3x.m4v new file mode 100755 index 0000000..2905564 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_06@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_07@3x.m4v b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_07@3x.m4v new file mode 100755 index 0000000..64700cb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Animations/phone@3x/consent_07@3x.m4v differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/Contents.json new file mode 100755 index 0000000..d32c91b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ContrastExam.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "ContrastExam@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "ContrastExam@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam.png new file mode 100755 index 0000000..0c2c182 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@2x.png new file mode 100755 index 0000000..73dd7a6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@3x.png new file mode 100755 index 0000000..60da0ba Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/ContrastExam.imageset/ContrastExam@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/Contents.json new file mode 100755 index 0000000..e85b5ad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "VisualExam.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "VisualExam@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "VisualExam@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam.png new file mode 100755 index 0000000..c64546c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@2x.png new file mode 100755 index 0000000..429ff25 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@3x.png new file mode 100755 index 0000000..e1cd1ba Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/VisualExam.imageset/VisualExam@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/Contents.json new file mode 100755 index 0000000..8a22445 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "amslerGrid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "amslerGrid@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@2x.png new file mode 100755 index 0000000..ec20ab7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@3x.png new file mode 100755 index 0000000..ac7a09d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/amslerGrid.imageset/amslerGrid@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/Contents.json new file mode 100755 index 0000000..9f8190b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "audioGraph@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/audioGraph@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/audioGraph@3x.png new file mode 100755 index 0000000..726429c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audioGraph.imageset/audioGraph@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/Contents.json new file mode 100755 index 0000000..ef795ad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "audiometry@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "audiometry@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@2x.png new file mode 100755 index 0000000..7e48c31 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@3x.png new file mode 100755 index 0000000..56f0be2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/audiometry.imageset/audiometry@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/Contents.json new file mode 100755 index 0000000..56dd3e8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "handtapping01@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "handtapping01@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "handtapping01@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x.png new file mode 100755 index 0000000..b49859c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x~ipad.png new file mode 100755 index 0000000..7ab9be4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@3x.png new file mode 100755 index 0000000..7ab9be4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping01.imageset/handtapping01@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/Contents.json new file mode 100755 index 0000000..df23dd9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "handtapping02@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "handtapping02@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "handtapping02@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x.png new file mode 100755 index 0000000..bcf0789 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x~ipad.png new file mode 100755 index 0000000..1b6193e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@3x.png new file mode 100755 index 0000000..1b6193e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/handtapping02.imageset/handtapping02@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/Contents.json new file mode 100755 index 0000000..baaec02 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "heart-fitness@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "heart-fitness@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@2x.png new file mode 100755 index 0000000..e264670 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@3x.png new file mode 100755 index 0000000..89942a7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heart-fitness.imageset/heart-fitness@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/Contents.json new file mode 100755 index 0000000..c336b64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "heartbeat@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "heartbeat@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@2x.png new file mode 100755 index 0000000..c9137df Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@3x.png new file mode 100755 index 0000000..4c7f7e4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/heartbeat.imageset/heartbeat@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/Contents.json new file mode 100755 index 0000000..2493cd7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "holepegtest1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "holepegtest1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@2x.png new file mode 100755 index 0000000..fa02a9d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@3x.png new file mode 100755 index 0000000..445059f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest1.imageset/holepegtest1@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/Contents.json new file mode 100755 index 0000000..4b3f5a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest2@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "holepegtest2@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x.png new file mode 100755 index 0000000..3d64994 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x~ipad.png new file mode 100755 index 0000000..fc1d771 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@3x.png new file mode 100755 index 0000000..6f9e874 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest2.imageset/holepegtest2@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/Contents.json new file mode 100755 index 0000000..cbdc1d4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest3@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest3@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "holepegtest3@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x.png new file mode 100755 index 0000000..e8b9dec Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x~ipad.png new file mode 100755 index 0000000..a10b849 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@3x.png new file mode 100755 index 0000000..a10b849 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest3.imageset/holepegtest3@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/Contents.json new file mode 100755 index 0000000..1b24d15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest4@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest4@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "holepegtest4@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x.png new file mode 100755 index 0000000..451f9e1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x~ipad.png new file mode 100755 index 0000000..5e4ae34 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@3x.png new file mode 100755 index 0000000..5e4ae34 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest4.imageset/holepegtest4@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/Contents.json new file mode 100755 index 0000000..777e61c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest5@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest5@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "holepegtest5@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x.png new file mode 100755 index 0000000..5e9a1e5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x~ipad.png new file mode 100755 index 0000000..17f529d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@3x.png new file mode 100755 index 0000000..c9fe3b2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest5.imageset/holepegtest5@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/Contents.json new file mode 100755 index 0000000..810f840 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest6@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "holepegtest6@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "holepegtest6@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x.png new file mode 100755 index 0000000..d3c62d0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x~ipad.png new file mode 100755 index 0000000..9c83b29 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@3x.png new file mode 100755 index 0000000..9c83b29 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/holepegtest6.imageset/holepegtest6@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/Contents.json new file mode 100755 index 0000000..551f6a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "knee_maximum_left@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "knee_maximum_left@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@2x.png new file mode 100755 index 0000000..6a55a99 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@3x.png new file mode 100755 index 0000000..86c1b33 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_left.imageset/knee_maximum_left@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/Contents.json new file mode 100755 index 0000000..e2b12d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "knee_maximum_right@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "knee_maximum_right@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@2x.png new file mode 100755 index 0000000..39287f5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@3x.png new file mode 100755 index 0000000..bea0dd8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_maximum_right.imageset/knee_maximum_right@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/Contents.json new file mode 100755 index 0000000..a6baebe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "knee_start_left@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "knee_start_left@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@2x.png new file mode 100755 index 0000000..c1364eb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@3x.png new file mode 100755 index 0000000..648048e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_left.imageset/knee_start_left@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/Contents.json new file mode 100755 index 0000000..4742d8b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "knee_start_right@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "knee_start_right@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@2x.png new file mode 100755 index 0000000..b269602 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@3x.png new file mode 100755 index 0000000..9282110 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/knee_start_right.imageset/knee_start_right@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/Contents.json new file mode 100755 index 0000000..f432db7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "memory-second-screen@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "memory-second-screen@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "memory-second-screen@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x.png new file mode 100755 index 0000000..0f13cb3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x~ipad.png new file mode 100755 index 0000000..8592f37 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@3x.png new file mode 100755 index 0000000..8592f37 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory-second-screen.imageset/memory-second-screen@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/Contents.json new file mode 100755 index 0000000..8855040 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "memory@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "memory@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@2x.png new file mode 100755 index 0000000..335d3c9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@3x.png new file mode 100755 index 0000000..b1e0dc6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/memory.imageset/memory@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/Contents.json new file mode 100755 index 0000000..a682237 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phone-memory@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phone-memory@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phone-memory@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x.png new file mode 100755 index 0000000..82ea07e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x~ipad.png new file mode 100755 index 0000000..7efb366 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@3x.png new file mode 100755 index 0000000..7efb366 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-memory.imageset/phone-memory@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/Contents.json new file mode 100755 index 0000000..bbf6a4d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "filename" : "phone-tower-of-hanoi@2x.png" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "filename" : "phone-tower-of-hanoi@3x.png" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "filename" : "phone-tower-of-hanoi@2x~ipad.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x.png new file mode 100755 index 0000000..f0a7192 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x~ipad.png new file mode 100755 index 0000000..20d18d8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@3x.png new file mode 100755 index 0000000..20d18d8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phone-tower-of-hanoi.imageset/phone-tower-of-hanoi@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/Contents.json new file mode 100755 index 0000000..1ac31ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonefrequencywaves@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonefrequencywaves@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonefrequencywaves@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x.png new file mode 100755 index 0000000..7c390f5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x~ipad.png new file mode 100755 index 0000000..1bc7013 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@3x.png new file mode 100755 index 0000000..1bc7013 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonefrequencywaves.imageset/phonefrequencywaves@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/Contents.json new file mode 100755 index 0000000..1759aba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phoneholepeg@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phoneholepeg@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phoneholepeg@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x.png new file mode 100755 index 0000000..1507395 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x~ipad.png new file mode 100755 index 0000000..37c1303 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@3x.png new file mode 100755 index 0000000..c019a27 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneholepeg.imageset/phoneholepeg@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/Contents.json new file mode 100755 index 0000000..9d4977b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonepsat@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonepsat@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonepsat@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x.png new file mode 100755 index 0000000..142e72c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x~ipad.png new file mode 100755 index 0000000..7697fea Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@3x.png new file mode 100755 index 0000000..c792e58 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonepsat.imageset/phonepsat@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/Contents.json new file mode 100755 index 0000000..78416f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phoneshake@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phoneshake@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@2x.png new file mode 100755 index 0000000..0234389 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@3x.png new file mode 100755 index 0000000..b3aa2e9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshake.imageset/phoneshake@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/Contents.json new file mode 100755 index 0000000..5ed5de9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phoneshakecircle@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phoneshakecircle@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phoneshakecircle@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x.png new file mode 100755 index 0000000..bb62567 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x~ipad.png new file mode 100755 index 0000000..3bf95dd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@3x.png new file mode 100755 index 0000000..3bf95dd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phoneshakecircle.imageset/phoneshakecircle@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/Contents.json new file mode 100755 index 0000000..9867d5f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonesoundwaves@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonesoundwaves@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonesoundwaves@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x.png new file mode 100755 index 0000000..c75e0a9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x~ipad.png new file mode 100755 index 0000000..e930d6f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@3x.png new file mode 100755 index 0000000..e930d6f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonesoundwaves.imageset/phonesoundwaves@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/Contents.json new file mode 100755 index 0000000..acdb120 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonestroopbutton@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonestroopbutton@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonestroopbutton@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x.png new file mode 100755 index 0000000..cf9a5be Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x~ipad.png new file mode 100755 index 0000000..25b3510 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@3x.png new file mode 100755 index 0000000..5690cc6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestroopbutton.imageset/phonestroopbutton@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/Contents.json new file mode 100755 index 0000000..a732495 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonestrooplabel@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonestrooplabel@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@2x.png new file mode 100755 index 0000000..f6c31eb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@3x.png new file mode 100755 index 0000000..4f00c85 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonestrooplabel.imageset/phonestrooplabel@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/Contents.json new file mode 100755 index 0000000..45855c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonetapping@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonetapping@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@2x.png new file mode 100755 index 0000000..28b5d12 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@3x.png new file mode 100755 index 0000000..8264066 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping.imageset/phonetapping@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/Contents.json new file mode 100755 index 0000000..fcc0280 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonetapping_notap@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonetapping_notap@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonetapping_notap@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x.png new file mode 100755 index 0000000..2263f2c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x~ipad.png new file mode 100755 index 0000000..ea44dd4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@3x.png new file mode 100755 index 0000000..ea44dd4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonetapping_notap.imageset/phonetapping_notap@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/Contents.json new file mode 100755 index 0000000..2a14321 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonewaves@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonewaves@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@2x.png new file mode 100755 index 0000000..c356185 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@3x.png new file mode 100755 index 0000000..97b4d20 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves.imageset/phonewaves@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/Contents.json new file mode 100755 index 0000000..1d36cbf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonewaves_inverted@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonewaves_inverted@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@2x.png new file mode 100755 index 0000000..4a30f4f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@3x.png new file mode 100755 index 0000000..930447a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_inverted.imageset/phonewaves_inverted@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/Contents.json new file mode 100755 index 0000000..38102de --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "phonewaves_tapping@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "phonewaves_tapping@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonewaves_tapping@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x.png new file mode 100755 index 0000000..2d16192 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x~ipad.png new file mode 100755 index 0000000..fd9b5ef Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@3x.png new file mode 100755 index 0000000..2937fd3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewaves_tapping.imageset/phonewaves_tapping@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/Contents.json new file mode 100755 index 0000000..80d60bd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonewavesspeech@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonewavesspeech@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonewavesspeech@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x.png new file mode 100755 index 0000000..8b02ff8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x~ipad.png new file mode 100755 index 0000000..7f1da79 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@3x.png new file mode 100755 index 0000000..7f1da79 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavesspeech.imageset/phonewavesspeech@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/Contents.json new file mode 100755 index 0000000..26e1750 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "phonewavestext@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "phonewavestext@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "phonewavestext@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x.png new file mode 100755 index 0000000..33b9f0c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x~ipad.png new file mode 100755 index 0000000..64d44e5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@3x.png new file mode 100755 index 0000000..64d44e5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/phonewavestext.imageset/phonewavestext@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/Contents.json new file mode 100755 index 0000000..05865f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pocket@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "pocket@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@2x.png new file mode 100755 index 0000000..6c07faf Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@3x.png new file mode 100755 index 0000000..7e03078 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/pocket.imageset/pocket@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/Contents.json new file mode 100755 index 0000000..d0b7e5e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "psatDice@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "psatDice@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@2x.png new file mode 100755 index 0000000..ec7562d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@3x.png new file mode 100755 index 0000000..584171f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/psatDice.imageset/psatDice@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/Contents.json new file mode 100755 index 0000000..6db55af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_maximum@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_maximum@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "shoulder_maximum@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x.png new file mode 100755 index 0000000..99e088b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x~ipad.png new file mode 100755 index 0000000..52edddd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@3x.png new file mode 100755 index 0000000..52edddd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_left.imageset/shoulder_maximum@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/Contents.json new file mode 100755 index 0000000..6db55af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_maximum@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_maximum@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "shoulder_maximum@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x.png new file mode 100755 index 0000000..ba76d52 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x~ipad.png new file mode 100755 index 0000000..a02b242 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@3x.png new file mode 100755 index 0000000..a02b242 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_maximum_right.imageset/shoulder_maximum@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/Contents.json new file mode 100755 index 0000000..12f0716 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_start@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_start@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "shoulder_start@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x.png new file mode 100755 index 0000000..602a25d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x~ipad.png new file mode 100755 index 0000000..69b5ed8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@3x.png new file mode 100755 index 0000000..69b5ed8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_left.imageset/shoulder_start@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/Contents.json new file mode 100755 index 0000000..12f0716 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_start@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "shoulder_start@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "shoulder_start@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x.png new file mode 100755 index 0000000..8644034 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x~ipad.png new file mode 100755 index 0000000..a2c100e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@3x.png new file mode 100755 index 0000000..a2c100e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/shoulder_start_right.imageset/shoulder_start@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/Contents.json new file mode 100755 index 0000000..08ed472 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "sittingman@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "sittingman@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "sittingman@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x.png new file mode 100755 index 0000000..ae9245b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x~ipad.png new file mode 100755 index 0000000..3510da5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@3x.png new file mode 100755 index 0000000..3510da5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/sittingman.imageset/sittingman@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/Contents.json new file mode 100755 index 0000000..3f933ed --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "speechInNoise@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "speechInNoise@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@2x.png new file mode 100755 index 0000000..90ba4d2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@3x.png new file mode 100755 index 0000000..fb975a9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/speechInNoise.imageset/speechInNoise@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/Contents.json new file mode 100755 index 0000000..035ea4e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "timed-walkingman-outbound@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "timed-walkingman-outbound@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "timed-walkingman-outbound@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x.png new file mode 100755 index 0000000..0376b3d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x~ipad.png new file mode 100755 index 0000000..4004df4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@3x.png new file mode 100755 index 0000000..8b2ae80 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-outbound.imageset/timed-walkingman-outbound@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/Contents.json new file mode 100755 index 0000000..3e7b5e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "timed-walkingman-return@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "timed-walkingman-return@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "timed-walkingman-return@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x.png new file mode 100755 index 0000000..639e413 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x~ipad.png new file mode 100755 index 0000000..14b174f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@3x.png new file mode 100755 index 0000000..5c2a9df Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timed-walkingman-return.imageset/timed-walkingman-return@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/Contents.json new file mode 100755 index 0000000..a66ed82 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "timer@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "timer@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "timer@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x.png new file mode 100755 index 0000000..9fcc4d6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x~ipad.png new file mode 100755 index 0000000..d76f6fb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@3x.png new file mode 100755 index 0000000..d76f6fb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/timer.imageset/timer@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/Contents.json new file mode 100755 index 0000000..211ea10 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityHorizontalScroll.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityHorizontalScroll@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityHorizontalScroll@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll.png new file mode 100755 index 0000000..79610a2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@2x.png new file mode 100755 index 0000000..135776a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@3x.png new file mode 100755 index 0000000..1a3e19d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityHorizontalScroll.imageset/touchAbilityHorizontalScroll@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/Contents.json new file mode 100755 index 0000000..be18f5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityInstruction.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityInstruction@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityInstruction@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction.png new file mode 100755 index 0000000..37c2217 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@2x.png new file mode 100755 index 0000000..4293757 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@3x.png new file mode 100755 index 0000000..e837a09 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityInstruction.imageset/touchAbilityInstruction@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/Contents.json new file mode 100755 index 0000000..b02a018 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityPinch.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityPinch@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityPinch@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch.png new file mode 100755 index 0000000..b544a8a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@2x.png new file mode 100755 index 0000000..0b245d0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@3x.png new file mode 100755 index 0000000..f427914 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityPinch.imageset/touchAbilityPinch@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/Contents.json new file mode 100755 index 0000000..bd528fb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityRotation.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityRotation@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityRotation@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation.png new file mode 100755 index 0000000..89bbb4d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@2x.png new file mode 100755 index 0000000..71a0e16 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@3x.png new file mode 100755 index 0000000..f79b5b0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityRotation.imageset/touchAbilityRotation@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/Contents.json new file mode 100755 index 0000000..45687ab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe1.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1.png new file mode 100755 index 0000000..7fc9f5d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@2x.png new file mode 100755 index 0000000..b5913c8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@3x.png new file mode 100755 index 0000000..cce3f15 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe1.imageset/touchAbilitySwipe1@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/Contents.json new file mode 100755 index 0000000..5c59270 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe2.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe2@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe2@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2.png new file mode 100755 index 0000000..a3826b5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@2x.png new file mode 100755 index 0000000..2f4dda3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@3x.png new file mode 100755 index 0000000..765c147 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe2.imageset/touchAbilitySwipe2@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/Contents.json new file mode 100755 index 0000000..a3937bd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe3.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe3@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe3@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3.png new file mode 100755 index 0000000..5072e31 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@2x.png new file mode 100755 index 0000000..ebfa6ca Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@3x.png new file mode 100755 index 0000000..dc0541c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe3.imageset/touchAbilitySwipe3@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/Contents.json new file mode 100755 index 0000000..307df56 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe4.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe4@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilitySwipe4@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4.png new file mode 100755 index 0000000..b054a6f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@2x.png new file mode 100755 index 0000000..d3fd681 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@3x.png new file mode 100755 index 0000000..f691744 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilitySwipe4.imageset/touchAbilitySwipe4@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/Contents.json new file mode 100755 index 0000000..fe3d482 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityTap.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityTap@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityTap@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap.png new file mode 100755 index 0000000..f8e54c4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@2x.png new file mode 100755 index 0000000..4ab09bc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@3x.png new file mode 100755 index 0000000..cb4c857 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityTap.imageset/touchAbilityTap@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/Contents.json new file mode 100755 index 0000000..ed2a285 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "touchAbilityVerticalScroll.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityVerticalScroll@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "touchAbilityVerticalScroll@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll.png new file mode 100755 index 0000000..4bed673 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@2x.png new file mode 100755 index 0000000..f29c1f9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@3x.png new file mode 100755 index 0000000..238a435 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/touchAbilityVerticalScroll.imageset/touchAbilityVerticalScroll@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/Contents.json new file mode 100755 index 0000000..cf68a59 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tower-of-hanoi-second-screen@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tower-of-hanoi-second-screen@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@2x.png new file mode 100755 index 0000000..fb8963c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@3x.png new file mode 100755 index 0000000..d058a93 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tower-of-hanoi-second-screen.imageset/tower-of-hanoi-second-screen@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/Contents.json new file mode 100755 index 0000000..6a2a47c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "trailmaking@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "trailmaking@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@2x.png new file mode 100755 index 0000000..6afd965 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@3x.png new file mode 100755 index 0000000..c3247c2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/trailmaking.imageset/trailmaking@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/Contents.json new file mode 100755 index 0000000..b5f6cf4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "tremortest1@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "tremortest1@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@2x.png new file mode 100755 index 0000000..c514263 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@3x.png new file mode 100755 index 0000000..ec56c77 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest1.imageset/tremortest1@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/Contents.json new file mode 100755 index 0000000..c691b47 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortest3a.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/tremortest3a.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/tremortest3a.pdf new file mode 100755 index 0000000..1b0fa2f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3a.imageset/tremortest3a.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/Contents.json new file mode 100755 index 0000000..d35f83a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortest3b.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/tremortest3b.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/tremortest3b.pdf new file mode 100755 index 0000000..d78f710 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest3b.imageset/tremortest3b.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/Contents.json new file mode 100755 index 0000000..cb24de9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortest4a.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/tremortest4a.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/tremortest4a.pdf new file mode 100755 index 0000000..7387c85 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4a.imageset/tremortest4a.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/Contents.json new file mode 100755 index 0000000..267cf97 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortest4b.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/tremortest4b.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/tremortest4b.pdf new file mode 100755 index 0000000..29c8003 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest4b.imageset/tremortest4b.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Contents.json new file mode 100755 index 0000000..ce661d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Tremor_5A.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Tremor_5A.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Tremor_5A.pdf new file mode 100755 index 0000000..9e74026 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5a.imageset/Tremor_5A.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Contents.json new file mode 100755 index 0000000..fbde199 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Tremor_5B.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Tremor_5B.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Tremor_5B.pdf new file mode 100755 index 0000000..ac5c1c8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest5b.imageset/Tremor_5B.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Contents.json new file mode 100755 index 0000000..cbece6d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Tremor_6A.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Tremor_6A.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Tremor_6A.pdf new file mode 100755 index 0000000..f95bc3d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6a.imageset/Tremor_6A.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Contents.json new file mode 100755 index 0000000..3cc134e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Tremor_6B.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Tremor_6B.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Tremor_6B.pdf new file mode 100755 index 0000000..3e6e6e2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest6b.imageset/Tremor_6B.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Contents.json new file mode 100755 index 0000000..b9b330f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Tremor_7.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Tremor_7.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Tremor_7.pdf new file mode 100755 index 0000000..0e1f7e4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortest7.imageset/Tremor_7.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/Contents.json new file mode 100755 index 0000000..59fa025 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortestLeft.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/tremortestLeft.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/tremortestLeft.pdf new file mode 100755 index 0000000..ce22806 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestLeft.imageset/tremortestLeft.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/Contents.json new file mode 100755 index 0000000..0f54a90 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tremortestRight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/tremortestRight.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/tremortestRight.pdf new file mode 100755 index 0000000..657009b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/tremortestRight.imageset/tremortestRight.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/Contents.json new file mode 100755 index 0000000..41673f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/Contents.json @@ -0,0 +1,31 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "turnaround@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "turnaround@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "turnaround@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x.png new file mode 100755 index 0000000..5bf93ed Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x~ipad.png new file mode 100755 index 0000000..999a0ef Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@3x.png new file mode 100755 index 0000000..999a0ef Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/turnaround.imageset/turnaround@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/Contents.json new file mode 100755 index 0000000..4bab502 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "walkingman@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "walkingman@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@2x.png new file mode 100755 index 0000000..72aee68 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@3x.png new file mode 100755 index 0000000..dee28c0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman.imageset/walkingman@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/Contents.json new file mode 100755 index 0000000..cda3344 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "walkingman_monitor@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "walkingman_monitor@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "walkingman_monitor@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x.png new file mode 100755 index 0000000..5bc9570 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x~ipad.png new file mode 100755 index 0000000..40428fd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@3x.png new file mode 100755 index 0000000..40428fd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Active/walkingman_monitor.imageset/walkingman_monitor@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/Contents.json new file mode 100755 index 0000000..71aff3d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_01@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_01@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_01@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x.png new file mode 100755 index 0000000..5080638 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x~ipad.png new file mode 100755 index 0000000..5201b51 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@3x.png new file mode 100755 index 0000000..5201b51 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_01.imageset/consent_01@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/Contents.json new file mode 100755 index 0000000..9b73a6c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_02@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_02@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_02@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x.png new file mode 100755 index 0000000..ff32126 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x~ipad.png new file mode 100755 index 0000000..fcba5e1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@3x.png new file mode 100755 index 0000000..fcba5e1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_02.imageset/consent_02@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/Contents.json new file mode 100755 index 0000000..3bdeb95 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_03@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_03@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_03@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x.png new file mode 100755 index 0000000..7e7df3f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x~ipad.png new file mode 100755 index 0000000..781c5ed Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@3x.png new file mode 100755 index 0000000..781c5ed Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_03.imageset/consent_03@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/Contents.json new file mode 100755 index 0000000..915a6fb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_04@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_04@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_04@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x.png new file mode 100755 index 0000000..aa545cd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x~ipad.png new file mode 100755 index 0000000..3ab48e6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@3x.png new file mode 100755 index 0000000..3ab48e6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_04.imageset/consent_04@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/Contents.json new file mode 100755 index 0000000..a677c85 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_05@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_05@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_05@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x.png new file mode 100755 index 0000000..1d37e2d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x~ipad.png new file mode 100755 index 0000000..a2f3852 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@3x.png new file mode 100755 index 0000000..a2f3852 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_05.imageset/consent_05@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/Contents.json new file mode 100755 index 0000000..2e291ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_06@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_06@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_06@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x.png new file mode 100755 index 0000000..9d3e344 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x~ipad.png new file mode 100755 index 0000000..98f55a8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@3x.png new file mode 100755 index 0000000..98f55a8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_06.imageset/consent_06@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/Contents.json new file mode 100755 index 0000000..d3da1fc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "consent_07@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "consent_07@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "consent_07@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x.png new file mode 100755 index 0000000..c075701 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x~ipad.png new file mode 100755 index 0000000..3b1cdc5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@3x.png new file mode 100755 index 0000000..3b1cdc5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Consent/consent_07.imageset/consent_07@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/Contents.json new file mode 100755 index 0000000..6a77a11 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "annotation.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/annotation.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/annotation.png new file mode 100755 index 0000000..811eeb0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/annotation.imageset/annotation.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/Contents.json new file mode 100755 index 0000000..64d6329 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "UIButtonBarArrowLeft.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/UIButtonBarArrowLeft.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/UIButtonBarArrowLeft.pdf new file mode 100755 index 0000000..56402a4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeft.imageset/UIButtonBarArrowLeft.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/Contents.json new file mode 100755 index 0000000..a31e5d4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "UIButtonBarArrowLeftLandscape.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/UIButtonBarArrowLeftLandscape.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/UIButtonBarArrowLeftLandscape.pdf new file mode 100755 index 0000000..7917ebf Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowLeftLandscape.imageset/UIButtonBarArrowLeftLandscape.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/Contents.json new file mode 100755 index 0000000..31bb0c7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "UIButtonBarArrowRight.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/UIButtonBarArrowRight.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/UIButtonBarArrowRight.pdf new file mode 100755 index 0000000..5e1d0bc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRight.imageset/UIButtonBarArrowRight.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/Contents.json new file mode 100755 index 0000000..9d4ca6c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "UIButtonBarArrowRightLandscape.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/UIButtonBarArrowRightLandscape.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/UIButtonBarArrowRightLandscape.pdf new file mode 100755 index 0000000..5db44e1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/arrowRightLandscape.imageset/UIButtonBarArrowRightLandscape.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/Contents.json new file mode 100755 index 0000000..03ff7b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "checkmark.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/checkmark.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/checkmark.pdf new file mode 100755 index 0000000..88f45ac Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/checkmark.imageset/checkmark.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/Contents.json new file mode 100755 index 0000000..ed2b414 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "iCNDialPointerWithShadow.pdf", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/iCNDialPointerWithShadow.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/iCNDialPointerWithShadow.pdf new file mode 100755 index 0000000..4c1415d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNDialPointerWithShadow.imageset/iCNDialPointerWithShadow.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/Contents.json new file mode 100755 index 0000000..b31bec6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "iCNLandoltC.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/iCNLandoltC.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/iCNLandoltC.png new file mode 100755 index 0000000..33a321e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/iCNLandoltC.imageset/iCNLandoltC.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/Contents.json new file mode 100755 index 0000000..7efe8f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "orangeGrayCircle.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/orangeGrayCircle.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/orangeGrayCircle.png new file mode 100755 index 0000000..b183e4f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/orangeGrayCircle.imageset/orangeGrayCircle.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/Contents.json new file mode 100755 index 0000000..31dd139 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "pdfThumbnail.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/pdfThumbnail.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/pdfThumbnail.png new file mode 100755 index 0000000..da257b9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/pdfThumbnail.imageset/pdfThumbnail.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/Contents.json new file mode 100755 index 0000000..db7ffa0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "play.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "play@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "play@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play.png new file mode 100755 index 0000000..ef19355 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@2x.png new file mode 100755 index 0000000..84ac59d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@3x.png new file mode 100755 index 0000000..243b805 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/play.imageset/play@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/Contents.json new file mode 100755 index 0000000..4e7867e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "search.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/search.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/search.png new file mode 100755 index 0000000..ca50ca3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/search.imageset/search.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/Contents.json new file mode 100755 index 0000000..0d1507f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "share.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/share.png b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/share.png new file mode 100755 index 0000000..26e1a1a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Artwork.xcassets/share.imageset/share.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.h new file mode 100755 index 0000000..ed29194 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2015, Ramsundar Shandilya. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +/** + The `ORKBarGraphChartView` class presents the data provided by an object conforming to the + `ORKValueStackGraphChartViewDataSource` protocol as a bar graph. + + By default, the primary plot is colored by the `tintColor`, and any additional plots are colored + using the `referenceLineColor` property. You can customize the plot colors by implementing the + `-graphChartView:colorForPlotIndex:` method in the data source. + */ +ORK_CLASS_AVAILABLE +@interface ORKBarGraphChartView : ORKGraphChartView + +/** + The data source responsible for providing the data required to populate the graph chart view. + + See the `ORKValueStackGraphChartViewDataSource` protocol. + */ +@property (nonatomic, weak) id dataSource; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.m new file mode 100755 index 0000000..cfeded9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKBarGraphChartView.m @@ -0,0 +1,290 @@ +/* + Copyright (c) 2015, Ramsundar Shandilya. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKBarGraphChartView.h" + +#import "ORKGraphChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +#if TARGET_INTERFACE_BUILDER + +@interface ORKIBBarGraphChartViewDataSource : ORKIBGraphChartViewDataSource + ++ (instancetype)sharedInstance; + +@end + + +@implementation ORKIBBarGraphChartViewDataSource + ++ (instancetype)sharedInstance { + static id sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self class] new]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.plotPoints = @[ + @[ + [[ORKValueStack alloc] initWithStackedValues:@[ @4, @6 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @2, @4, @4 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @2, @6, @3, @6 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @3, @8, @10, @12 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @5, @10, @12, @8 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @8, @13, @18 ]], + ], + @[ + [[ORKValueStack alloc] initWithStackedValues:@[ @14 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @6, @6 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @3, @10, @12 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @5, @11, @14 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @7, @13, @20 ]], + [[ORKValueStack alloc] initWithStackedValues:@[ @10, @13, @25 ]], + ] + ]; + } + return self; +} + +- (ORKValueStack *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + return self.plotPoints[plotIndex][pointIndex]; +} + +@end + +#endif + +static const CGFloat BarWidth = 10.0; + + +@interface ORKBarGraphChartView () + +@property (nonatomic) NSMutableArray *> *dataPoints; // Actual data + +@property (nonatomic) NSMutableArray *> *yAxisPoints; // Normalized for the plot view height + +@end + + +@implementation ORKBarGraphChartView + +@dynamic dataSource; +@dynamic dataPoints; +@dynamic yAxisPoints; + +#pragma mark - Draw + +- (ORKValueStack *)dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + return [self.dataSource graphChartView:self dataPointForPointIndex:pointIndex plotIndex:plotIndex]; +} + +- (ORKValueStack *)dummyPoint { + return [ORKValueStack new]; +} + +- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex { + return YES; +} + +- (NSMutableArray *)normalizedCanvasDataPointsForPlotIndex:(NSInteger)plotIndex canvasHeight:(CGFloat)viewHeight { + NSMutableArray *normalizedDataPoints = [NSMutableArray new]; + + if (plotIndex < self.dataPoints.count) { + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + + NSMutableArray *normalizedDoubleStackValues = [NSMutableArray new]; + ORKValueStack *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + + if (!dataPointValue.isUnset) { + double range = self.maximumValue - self.minimumValue; + double sum = 0; + for (NSNumber *value in dataPointValue.stackedValues) { + // normalizedDoubleStackValues holds absolute canvas y-positions corresponding to each point + // (rather than incremental y-positions as the dataPoints valueStacks hold). + // E.g. (canvas height = 100) + // dataPoint valueStack = {10, 10, 20} + // -> + // normalized valueStack = {25, 50, 100} + sum += value.doubleValue; + double normalizedValue = (sum - self.minimumValue) / range * viewHeight; + normalizedValue = floor(viewHeight - normalizedValue); + + [normalizedDoubleStackValues addObject:@(normalizedValue)]; + } + } + [normalizedDataPoints addObject:[[ORKValueStack alloc] initWithStackedValues:normalizedDoubleStackValues]]; + } + } + + return normalizedDataPoints; +} + +- (void)calculateMinAndMaxValues { + self.minimumValue = ORKDoubleInvalidValue; + self.maximumValue = ORKDoubleInvalidValue; + + BOOL maximumValueProvided = NO; + + if ([self.dataSource respondsToSelector:@selector(minimumValueForGraphChartView:)]) { + self.minimumValue = [self.dataSource minimumValueForGraphChartView:self]; + } else { + self.minimumValue = 0; + } + + if ([self.dataSource respondsToSelector:@selector(maximumValueForGraphChartView:)]) { + self.maximumValue = [self.dataSource maximumValueForGraphChartView:self]; + maximumValueProvided = YES; + } + + if (!maximumValueProvided) { + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + NSInteger numberOfPlotPoints = self.dataPoints[plotIndex].count; + for (NSInteger pointIndex = 0; pointIndex < numberOfPlotPoints; pointIndex++) { + ORKValueStack *point = self.dataPoints[plotIndex][pointIndex]; + if (!maximumValueProvided && + point.totalValue != ORKDoubleInvalidValue && + ((self.maximumValue == ORKDoubleInvalidValue) || (point.totalValue > self.maximumValue))) { + self.maximumValue = point.totalValue; + } + } + } + } + + if (self.maximumValue == ORKDoubleInvalidValue) { + self.maximumValue = 0; + } +} + +- (UIColor *)colorForPlotIndex:(NSInteger)plotIndex subpointIndex:(NSInteger)subpointIndex totalSubpoints:(NSInteger)totalSubpoints { + return ORKOpaqueColorWithReducedAlphaFromBaseColor([super colorForPlotIndex:plotIndex subpointIndex:subpointIndex totalSubpoints:(NSInteger)totalSubpoints], subpointIndex, totalSubpoints); +} + +- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex { + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + ORKValueStack *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + NSMutableArray *lineLayers = [NSMutableArray new]; + if (!dataPointValue.isUnset) { + NSUInteger numberOfStackedValues = dataPointValue.stackedValues.count; + for (NSUInteger index = 0; index < numberOfStackedValues; index++) { + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + lineLayer.strokeColor = [self colorForPlotIndex:plotIndex subpointIndex:index totalSubpoints:numberOfStackedValues].CGColor; + lineLayer.lineWidth = BarWidth; + [self.plotView.layer addSublayer:lineLayer]; + [lineLayers addObject:lineLayer]; + } + } + [self.lineLayers[plotIndex] addObject:lineLayers]; + } +} + +- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex { + NSUInteger lineLayerIndex = 0; + double positionOnXAxis = ORKDoubleInvalidValue; + ORKValueStack *positionsOnYAxis = nil; + NSUInteger pointCount = self.yAxisPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + float previousYValue = self.plotView.bounds.size.height; + + ORKValueStack *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + positionsOnYAxis = self.yAxisPoints[plotIndex][pointIndex]; + + if (!dataPointValue.isUnset) { + NSUInteger numberOfSubpoints = positionsOnYAxis.stackedValues.count; + for (NSUInteger subpointIndex = 0; subpointIndex < numberOfSubpoints; subpointIndex++) { + double positionOnYAxis = positionsOnYAxis.stackedValues[subpointIndex].doubleValue; + UIBezierPath *linePath = [UIBezierPath bezierPath]; + + double barHeight = fabs(positionOnYAxis - previousYValue); + + positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width); + positionOnXAxis += [self xOffsetForPlotIndex:plotIndex]; + + [linePath moveToPoint:CGPointMake(positionOnXAxis, previousYValue + scalePixelAdjustment())]; + [linePath addLineToPoint:CGPointMake(positionOnXAxis, previousYValue + scalePixelAdjustment() - barHeight)]; + + previousYValue = positionOnYAxis; + + CAShapeLayer *lineLayer = self.lineLayers[plotIndex][pointIndex][subpointIndex]; + lineLayer.path = linePath.CGPath; + lineLayerIndex++; + } + } + } +} + +#pragma mark - Scrubbing + +- (double)scrubbingValueForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + return self.dataPoints[plotIndex][pointIndex].totalValue; +} + +- (double)scrubbingYAxisPointForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + return self.yAxisPoints[plotIndex][pointIndex].stackedValues.lastObject.doubleValue; // totalValue is not normalized to canvas coordinates +} + +- (CGFloat)xOffsetForPlotIndex:(NSInteger)plotIndex { + return xOffsetForPlotIndex(plotIndex, [self numberOfPlots], BarWidth); +} + +- (CGFloat)snappedXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super snappedXPosition:xPosition plotIndex:plotIndex] + [self xOffsetForPlotIndex:plotIndex]; +} + +- (NSInteger)pointIndexForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super pointIndexForXPosition:xPosition - [self xOffsetForPlotIndex:plotIndex] plotIndex:plotIndex]; +} + +- (BOOL)isXPositionSnapped:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super isXPositionSnapped:xPosition - [self xOffsetForPlotIndex:plotIndex] plotIndex:plotIndex]; +} + +#pragma mark - Interface Builder designable + +- (void)prepareForInterfaceBuilder { + [super prepareForInterfaceBuilder]; +#if TARGET_INTERFACE_BUILDER + self.dataSource = [ORKIBBarGraphChartViewDataSource sharedInstance]; +#endif +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.h new file mode 100755 index 0000000..b890d39 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.h @@ -0,0 +1,152 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ramsundar Shandilya. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN +/** + Defines the common attributes of chart values. + */ +@protocol ORKValueCollectionType + +/** + A Boolean value indicating that the value is unset. (read-only) + */ +@property (nonatomic, readonly) BOOL isUnset; + +@end + + +/** + The `ORKValueRange` class represents a range between two values of the double type. It can be used + in graph chart plots to draw value ranges. + */ +ORK_CLASS_AVAILABLE +@interface ORKValueRange : NSObject + +/** + Returns a value range initialized using the specified `minimumValue` and `maximumValue`. + + @param minimumValue The `minimumValue` to set. + @param maximumValue The `maximumValue` to set. + + @return A value range object. + */ +- (instancetype)initWithMinimumValue:(double)minimumValue maximumValue:(double)maximumValue NS_DESIGNATED_INITIALIZER; + +/** + Returns a value range initialized using the specified `value` for both `minimumValue` and + `maximumValue`. This is useful for plotting data points that model a single value with no range. + + This method is a convenience initializer. + + @param value The `minimumValue` and `maximumValue` to set. + + @return A value range object. + */ +- (instancetype)initWithValue:(double)value; + +/** + Returns a value range initialized using the `ORKDoubleInvalidValue` value for both `minimumValue` + and `maximumValue`. This denotes an unset or invalid value range. It is useful, for example, for + representing unavailable data in discontinous graph chart plots. + + This method is a convenience initializer. + + @return A value range object initialized with the `ORKDoubleInvalidValue` value. + */ +- (instancetype)init; + +/** + The upper limit of the value range. + */ +@property (nonatomic) double maximumValue; + +/** + The lower limit of the value range. + */ +@property (nonatomic) double minimumValue; + +/** + A Boolean value indicating that `minimumValue` is equal to `maximumValue`. (read-only) + */ +@property (nonatomic, readonly) BOOL isEmptyRange; + +/** + A Boolean value indicating that both `minimum value` and `maximum value` are equal to the + `ORKDoubleInvalidValue` value. (read-only) + */ +@property (nonatomic, readonly) BOOL isUnset; + +@end + + +/** + The `ORKValueStack` class represents an arbitrary list of values of the double type. It can be used + in graph chart plots to draw stacked values. + */ +ORK_CLASS_AVAILABLE +@interface ORKValueStack : NSObject + +/** + Returns an empty value stack. + + @return An empty value stack object. + */ +- (instancetype)init; + +/** + Returns a value stack initialized with the passed `NSNumber` array. + + @param stackedValues An array containing `NSNumber` objects. + + @return A value stack object initialized with the passed `NSNumber` values. + */ +- (instancetype)initWithStackedValues:(NSArray *)stackedValues NS_DESIGNATED_INITIALIZER; + +/** + An array of `NSNumber` objects, each one representing a stacked double value. + */ +@property (nonatomic, copy, readonly) NSArray *stackedValues; + +/** + The total sum of the stacked double values + */ +@property (nonatomic) double totalValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.m new file mode 100755 index 0000000..27d93c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKChartTypes.m @@ -0,0 +1,163 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ramsundar Shandilya. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKChartTypes.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKValueRange + +- (instancetype)initWithMinimumValue:(double)minimumValue maximumValue:(double)maximumValue { + if (maximumValue < minimumValue) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"maximumValue cannot be lower than minimumValue" + userInfo:nil]; + } + + self = [super init]; + if (self) { + _minimumValue = minimumValue; + _maximumValue = maximumValue; + } + return self; +} + +- (instancetype)init { + return [self initWithMinimumValue:ORKDoubleInvalidValue maximumValue:ORKDoubleInvalidValue]; +} + +- (instancetype)initWithValue:(double)value { + return [self initWithMinimumValue:value maximumValue:value]; +} + +- (BOOL)isUnset { + return (_minimumValue == ORKDoubleInvalidValue && _maximumValue == ORKDoubleInvalidValue); +} + +- (BOOL)isEmptyRange { + return (_minimumValue == _maximumValue); +} + +- (NSString *)description { + NSString *minimumValueString = (_minimumValue == ORKDoubleInvalidValue) ? @"ORKDoubleInvalidValue" : [NSString stringWithFormat:@"%0.0f", _minimumValue] ; + NSString *maximumValueString = (_maximumValue == ORKDoubleInvalidValue) ? @"ORKDoubleInvalidValue" : [NSString stringWithFormat:@"%0.0f", _maximumValue] ; + return [NSString stringWithFormat:@"<%@: %p; min = %@; max = %@>", self.class.description, self, minimumValueString, maximumValueString]; +} + +#pragma mark - Accessibility + +- (NSString *)accessibilityLabel { + if (self.isUnset) { + return nil; + } + + if (self.isEmptyRange || _minimumValue == _maximumValue) { + return @(_maximumValue).stringValue; + } else { + NSString *rangeFormat = ORKLocalizedString(@"AX_GRAPH_RANGE_FORMAT_%@_%@", nil); + return [NSString stringWithFormat:rangeFormat, @(_minimumValue).stringValue, @(_maximumValue).stringValue]; + } +} + +@end + + +@implementation ORKValueStack + +- (instancetype)init { + return [self initWithStackedValues:@[]]; +} + +- (instancetype)initWithStackedValues:(NSArray *)stackedValues { + self = [super init]; + if (self) { + if (stackedValues.count == 0) { + _totalValue = ORKDoubleInvalidValue; + } else { + _totalValue = 0; + for (NSNumber *number in stackedValues) { + if (![number isKindOfClass:[NSNumber class]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"stackedValues must only contain NSNumber objects" + userInfo:nil]; + } + _totalValue += number.doubleValue; + } + } + _stackedValues = [stackedValues copy]; + } + return self; +} + +- (BOOL)isUnset { + return !_stackedValues || _stackedValues.count == 0; +} + +- (NSString *)description { + NSMutableString *mutableString = [NSMutableString new]; + [mutableString appendFormat:@"<%@: %p; (", self.class.description, self]; + NSUInteger numberOfStackedValues = _stackedValues.count; + for (NSInteger index = 0; index < numberOfStackedValues; index++) { + [mutableString appendFormat:@"%0.0f", _stackedValues[index].doubleValue]; + if (index < numberOfStackedValues - 1) { + [mutableString appendString:@", "]; + } + } + [mutableString appendString:@")>"]; + return [mutableString copy]; +} + +#pragma mark - Accessibility + +- (NSString *)accessibilityLabel { + if (self.isUnset) { + return nil; + } + + NSMutableString *mutableString = [[NSMutableString alloc] initWithFormat:@"%@ %@", + ORKLocalizedString(@"AX_GRAPH_STACK_PREFIX", nil), _stackedValues[0].stringValue]; + + NSUInteger numberOfStackedValues = _stackedValues.count; + for (NSInteger index = 1; index < numberOfStackedValues; index++) { + [mutableString appendString:@", "]; + if (index == (numberOfStackedValues - 1)) { + [mutableString appendString:ORKLocalizedString(@"AX_GRAPH_AND_SEPARATOR", nil)]; + } + [mutableString appendFormat:@"%@", _stackedValues[index].stringValue]; + } + return [mutableString copy]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.h new file mode 100755 index 0000000..de94135 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKDiscreteGraphChartView` class presents data provided by an object conforming to the + `ORKValueRangeGraphChartViewDataSource` protocol as a discrete graph of ranged points. + + You can optionally display a line connecting each ranged point pair. + + By default, the primary plot is colored by the `tintColor`, and any additional plots are colored + using the `referenceLineColor` property. You can customize the plot colors by implementing the + `-graphChartView:colorForPlotIndex:` method in the data source. + */ +ORK_CLASS_AVAILABLE +@interface ORKDiscreteGraphChartView : ORKValueRangeGraphChartView + +/** + A Boolean value indicating whether to draw a line connecting the minimum value and maximum value of + each ranged point represented by the graph view. + + The default value for this property is `YES`. + */ +@property (nonatomic) IBInspectable BOOL drawsConnectedRanges; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.m new file mode 100755 index 0000000..2d75274 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKDiscreteGraphChartView.m @@ -0,0 +1,182 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#import "ORKDiscreteGraphChartView.h" + +#import "ORKChartTypes.h" +#import "ORKGraphChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +#if TARGET_INTERFACE_BUILDER + +@interface ORKIBDiscreteGraphChartViewDataSource : ORKIBValueRangeGraphChartViewDataSource + ++ (instancetype)sharedInstance; + +@end + + +@implementation ORKIBDiscreteGraphChartViewDataSource + ++ (instancetype)sharedInstance { + static id sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self class] new]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.plotPoints = @[ + @[ + [[ORKValueRange alloc] initWithMinimumValue:0 maximumValue: 2], + [[ORKValueRange alloc] initWithMinimumValue:1 maximumValue: 4], + [[ORKValueRange alloc] initWithMinimumValue:2 maximumValue: 6], + [[ORKValueRange alloc] initWithMinimumValue:3 maximumValue: 8], + [[ORKValueRange alloc] initWithMinimumValue:5 maximumValue:10], + [[ORKValueRange alloc] initWithMinimumValue:8 maximumValue:13] + ], + @[ + [[ORKValueRange alloc] initWithValue:1], + [[ORKValueRange alloc] initWithMinimumValue:2 maximumValue:6], + [[ORKValueRange alloc] initWithMinimumValue:3 maximumValue:10], + [[ORKValueRange alloc] initWithMinimumValue:5 maximumValue:11], + [[ORKValueRange alloc] initWithMinimumValue:7 maximumValue:13], + [[ORKValueRange alloc] initWithMinimumValue:10 maximumValue:13] + ] + ]; + } + return self; +} + +@end + +#endif + + +@implementation ORKDiscreteGraphChartView + +#pragma mark - Init + +- (void)sharedInit { + [super sharedInit]; + _drawsConnectedRanges = YES; +} + +- (void)setDrawsConnectedRanges:(BOOL)drawsConnectedRanges { + _drawsConnectedRanges = drawsConnectedRanges; + [super updateLineLayers]; + [super updatePointLayers]; + [super layoutLineLayers]; + [super layoutPointLayers]; +} + +#pragma mark - Draw + +- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex { + return [self numberOfValidValuesForPlotIndex:plotIndex] > 0 && _drawsConnectedRanges; +} + +- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex { + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + ORKValueRange *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + if (!dataPointValue.isUnset && !dataPointValue.isEmptyRange) { + CAShapeLayer *lineLayer = graphLineLayer(); + lineLayer.strokeColor = [self colorForPlotIndex:plotIndex].CGColor; + lineLayer.lineWidth = ORKGraphChartViewPointAndLineWidth; + + [self.plotView.layer addSublayer:lineLayer]; + [self.lineLayers[plotIndex] addObject:[NSMutableArray arrayWithObject:lineLayer]]; + } + } +} + +- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex { + NSUInteger lineLayerIndex = 0; + CGFloat positionOnXAxis = ORKCGFloatInvalidValue; + ORKValueRange *positionOnYAxis = nil; + NSUInteger pointCount = self.yAxisPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + + ORKValueRange *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + + if (!dataPointValue.isUnset && !dataPointValue.isEmptyRange) { + + UIBezierPath *linePath = [UIBezierPath bezierPath]; + + positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width); + positionOnXAxis += [self xOffsetForPlotIndex:plotIndex]; + positionOnYAxis = self.yAxisPoints[plotIndex][pointIndex]; + + [linePath moveToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)]; + [linePath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.maximumValue)]; + + CAShapeLayer *lineLayer = self.lineLayers[plotIndex][lineLayerIndex][0]; + lineLayer.path = linePath.CGPath; + lineLayerIndex++; + } + } +} + +- (CGFloat)xOffsetForPlotIndex:(NSInteger)plotIndex { + return xOffsetForPlotIndex(plotIndex, [self numberOfPlots], ORKGraphChartViewPointAndLineWidth); +} + +- (CGFloat)snappedXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super snappedXPosition:xPosition plotIndex:plotIndex] + [self xOffsetForPlotIndex:plotIndex]; +} + +- (NSInteger)pointIndexForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super pointIndexForXPosition:xPosition - [self xOffsetForPlotIndex:plotIndex] plotIndex:plotIndex]; + } + +- (BOOL)isXPositionSnapped:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + return [super isXPositionSnapped:xPosition - [self xOffsetForPlotIndex:plotIndex] plotIndex:plotIndex]; +} + +#pragma mark - Interface Builder designable + +- (void)prepareForInterfaceBuilder { + [super prepareForInterfaceBuilder]; +#if TARGET_INTERFACE_BUILDER + self.dataSource = [ORKIBDiscreteGraphChartViewDataSource sharedInstance]; +#endif +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.h new file mode 100755 index 0000000..137bce7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.h @@ -0,0 +1,558 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKValueRange; +@class ORKValueStack; +@class ORKGraphChartView; + +/** + The graph chart view delegate protocol forwards pan gesture events occuring + within the bounds of an `ORKGraphChartView` object. +*/ +ORK_AVAILABLE_DECL +@protocol ORKGraphChartViewDelegate + +@optional +/** + Notifies the delegate that a pan gesture has begun within the bounds of an `ORKGraphChartView` + object. + + @param graphChartView The graph chart view in which the gesture occurred. +*/ +- (void)graphChartViewTouchesBegan:(ORKGraphChartView *)graphChartView; + +/** + Notifies the delegate of updates in the x-coordinate of an ongoing pan gesture within the bounds + of an `ORKGraphChartView` object. + + @param graphChartView The graph chart view object in which the gesture occurred. + @param xPosition The updated x-coordinate of the ongoing pan gesture. +*/ +- (void)graphChartView:(ORKGraphChartView *)graphChartView touchesMovedToXPosition:(CGFloat)xPosition; + +/** + Notifies the delegate that a pan gesture that began within the bounds of an `ORKGraphChartView` + object has ended. + +@param graphChartView The graph chart view object in which the gesture occurred. +*/ +- (void)graphChartViewTouchesEnded:(ORKGraphChartView *)graphChartView; + +@end + + +/** + The abstract `ORKGraphChartViewDataSource` protocol is the base protocol which conforms the basis + for the `ORKValueRangeGraphChartViewDataSource` and `ORKValueStackGraphChartViewDataSource` + protocols, required to populate the concrete `ORKGraphChartView` subclass. + + At a minimum, a data source object must implement the `graphChartView:numberOfPointsInPlot:` and + `graphChartView:plot:valueForPointAtIndex:` methods. These methods return + the number of points in a plot and the points themselves. Each point in a plot is represented by + an object of the `ORKValueRange` or `ORKValueStack` class, depending on the concrete subprotocol. + + A data source object may provide additional information to the graph chart view by implementing the + optional methods. + + When configuring an `ORKGraphChartView` object, assign your data source to its `dataSource` + property. +*/ +@protocol ORKGraphChartViewDataSource + +@required +/** + Asks the data source for the number of value points to be plotted by the graph chart view at the + specified plot index. + + @param graphChartView The graph chart view asking for the number of value points. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view. + + @return The number of range points in the plot at `plotIndex`. +*/ +- (NSInteger)graphChartView:(ORKGraphChartView *)graphChartView numberOfDataPointsForPlotIndex:(NSInteger)plotIndex; + + +/** + Asks the data source for the number of plots to be plotted by the graph chart view. + + @param graphChartView The graph chart view asking for the number of plots. + + @return The number of plots in the graph chart view. +*/ +- (NSInteger)numberOfPlotsInGraphChartView:(ORKGraphChartView *)graphChartView; + +@optional +/** + Asks the data source for the color of the specified plot. + + If this method is not implemented, the first plot uses the graph chart view `tintColor`, and + all subsequent plots uses the current `referenceLineColor`. + + @param graphChartView The graph chart view asking for the color of the segment. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is always 0 in single-plot graph chart views. + + @return The color of the segment at the specified index in a pie chart view. + */ +- (UIColor *)graphChartView:(ORKGraphChartView *)graphChartView colorForPlotIndex:(NSInteger)plotIndex; + +/** + Asks the data source for the fill color of the specified plot. + + The fill color is only used by `ORKLineGraphChartView`. If this method is not implemented, the + chart uses the main color of the specified plot with a 0.4 opacity value. + + @param graphChartView The graph chart view asking for the color of the segment. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is always 0 in single-plot graph chart views. + + @return The color of the fill layer at the specified index in a line chart view. + */ +- (UIColor *)graphChartView:(ORKGraphChartView *)graphChartView fillColorForPlotIndex:(NSInteger)plotIndex; + +/** + Asks the data source which plot the scrubber should snap to in multigraph chart views. + + If this method is not implemented, the scrubber snaps over the first plot. + + @param graphChartView The graph chart view asking for the scrubbing plot index. + + @return The index of the plot that the scrubber should snap to. + */ +- (NSInteger)scrubbingPlotIndexForGraphChartView:(ORKGraphChartView *)graphChartView; + +/** + Asks the data source for the upper limit of the y-axis drawn by the graph chart view. + + If this method is not implemented, the greatest `maximumValue` of all `ORKValueRange` instances + returned in `graphChartView:plot:valueForPointAtIndex:` is used. + + See also: `graphChartView:plot:valueForPointAtIndex:`. + + @param graphChartView The graph chart view asking for the maximum value. + + @return The maximum value of the y-axis drawn by `graphChartView`. +*/ +- (double)maximumValueForGraphChartView:(ORKGraphChartView *)graphChartView; + +/** + Asks the data source for the lower limit of the y-axis drawn by the graph chart view. + + If this method is not implemented, the smallest `minimumValue` of all ORKValueRange instances + returned in `graphChartView:plot:valueForPointAtIndex:` is used. + + See also: `graphChartView:plot:valueForPointAtIndex:`. + + @param graphChartView The graph chart view asking for the minimum value. + + @return The minimum value of the y-axis drawn by `graphChartView`. +*/ +- (double)minimumValueForGraphChartView:(ORKGraphChartView *)graphChartView; + +/** + Asks the data source for the number of divisions in the x-axis. The value is ignored if it is lower + than the number of data points. A title appearing adjacent to each + division may optionally be returned by the `graphChartView:titleForXAxisAtPointIndex:` method. + + @param graphChartView The graph chart view asking for the number of divisions in its x-axis. + + @return The number of divisions in the x-axis for `graphChartView`. +*/ +- (NSInteger)numberOfDivisionsInXAxisForGraphChartView:(ORKGraphChartView *)graphChartView; + +/** + Asks the data source for the title to be displayed adjacent to each division in the x-axis (the + number returned by `numberOfDivisionsInXAxisForGraphChartView:`). You can return `nil` from this + method if you don't want to display a title for the specified point index. + + If this method is not implemented, the x-axis has no titles. + + See also: `numberOfDivisionsInXAxisForGraphChartView:`. + + @param graphChartView The graph chart view asking for the title. + @param pointIndex The index of the specified x-axis division. + + @return The title string to be displayed adjacent to each division of the x-axis of the graph chart + view. +*/ +- (nullable NSString *)graphChartView:(ORKGraphChartView *)graphChartView titleForXAxisAtPointIndex:(NSInteger)pointIndex; + +/** + Asks the data source if the vertical reference line at the specified point index should be drawn.. + + If this method is not implemented, the graph chart view will draw all vertical reference lines. + + @param graphChartView The graph view asking for the tile. + @param pointIndex The index corresponding to the number returned by + `numberOfDivisionsInXAxisForGraphChartView:`. + + @return Whether the graph chart view should draw the vertical reference line. + */ +- (BOOL)graphChartView:(ORKGraphChartView *)graphChartView drawsVerticalReferenceLineAtPointIndex:(NSInteger)pointIndex; + + +/** + Asks the data source if the plot at specified index should display circular indicators on its data points. + + This only applys to `ORKLineGrapthChartView`. + If this method is not implemented, point indicators will be drawn for all plots. + + @param graphChartView The graph view asking whether point indicators should be drawn. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is always 0 in single-plot graph chart views. + + @return Whether the graph chart view should draw point indicators for its points. + */ +- (BOOL)graphChartView:(ORKGraphChartView *)graphChartView drawsPointIndicatorsForPlotIndex:(NSInteger)plotIndex; + + +/** + Asks the data source for the unit label for the given plot index so VoiceOver's description of the graph can be read with units. + + If this method is not implemented, VoiceOver will speak the graph value without units. + + @param graphChartView The graph view asking for its unit label + @param plotIndex An index number identifying the plot in the graph chart view. This index + is always 0 in single-plot graph chart views. + + @return An appropriate unit label for the given plot. + */ +- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView accessibilityUnitLabelForPlotIndex:(NSInteger)plotIndex; + + +/** + Asks the data source for the accessibilityLabel at a given point on the x-axis + + This is used in cases where the UI may be displaying a shortened form (e.g. M, T, W, etc. for days of the week), but VoiceOver should be speaking the longer form. If this method isn't implemented, VoiceOver will speak the label displayed in the UI for the given index. + + @param graphChartView The graph view asking for its unit label + @param pointIndex The index corresponding to the number returned by `numberOfDivisionsInXAxisForGraphChartView:`. + + @return An appropriate accessibility label for the given index of the graph. + */ +- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView accessibilityLabelForXAxisAtPointIndex:(NSInteger)pointIndex; + +@end + + +/** + An object that adopts the `ORKValueRangeGraphChartViewDataSource` protocol is responsible for + providing data in the form of `ORKValueRange` values required to populate an + `ORKValueRangeGraphChartView` concrete subclass, such as `ORKLineGraphChartView` and + `ORKDiscreteGraphChartView`. + */ +ORK_AVAILABLE_DECL +@protocol ORKValueRangeGraphChartViewDataSource + +@required + +/** + Asks the data source for the value range to be plotted at the specified point index for the + specified plot. + + @param graphChartView The graph chart view that is asking for the value range. + @param pointIndex An index number identifying the value range in the graph chart view. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view. + + @return The value range specified by `pointIndex` in the plot specified by `plotIndex` for the + specified graph chart view`. + */ +- (ORKValueRange *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex; + +@end + + +/** + An object that adopts the `ORKValueStackGraphChartViewDataSource` protocol is responsible for + providing data in the form of `ORKValueStack` values required to populate an `ORKBarGraphChartView` + object. + */ +ORK_AVAILABLE_DECL +@protocol ORKValueStackGraphChartViewDataSource + +@required + +/** + Asks the data source for the value stack to be plotted at the specified point index for the + specified plot. + + @param graphChartView The graph chart view that is asking for the value stack. + @param pointIndex An index number identifying the value stack in the graph chart view. + @param plotIndex An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view. + + @return The value stack specified by `pointIndex` in the plot specified by `plotIndex` for the + specified graph chart view`. + */ +- (ORKValueStack *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex; + +@end + + +/** + The `ORKGraphChartView` class is an abstract class which holds properties and methods common to + concrete subclasseses. + + You should not instantiate this class directly; use one of the subclasses instead. The concrete + subclasses are `ORKLineGraphChartView`, `ORKDiscreteGraphChartView`, and `ORKBarGraphChartView`. +*/ +ORK_CLASS_AVAILABLE +IB_DESIGNABLE +@interface ORKGraphChartView : UIView + +/** + The minimum value of the y-axis. + + You can provide this value to an instance of `ORKGraphChartView` by implementing the optional + `minimumValueForGraphChartView:` method of the `ORKGraphChartViewDataSource` protocol. + + If `minimumValueForGraphChartView:` is not implemented, the minimum value is assigned to the + smallest value of the `minimumValue` property of all `ORKValueRange` instances returned by the + graph chart view data source. +*/ +@property (nonatomic, readonly) double minimumValue; + +/** + The maximum value of the y-axis. + + You can provide this value instance of `ORKGraphChartView` by implementing the + optional `maximumValueForGraphChartView:` method of the `ORKGraphChartViewDataSource` protocol. + + If `maximumValueForGraphChartView:` is not implemented, the maximum value is assigned to the + largest value of the `maximumValue` property of all `ORKValueRange` instances returned by the + graph chart view data source. +*/ +@property (nonatomic, readonly) double maximumValue; + +/** + A Boolean value indicating whether the graph chart view should draw horizontal reference lines. + + The default value of this property is NO. + */ +@property (nonatomic) IBInspectable BOOL showsHorizontalReferenceLines; + +/** + A Boolean value indicating whether the graph chart view should draw vertical reference lines. + + The default value of this property is NO. +*/ +@property (nonatomic) IBInspectable BOOL showsVerticalReferenceLines; + +/** + The delegate is notified of pan gesture events occuring within the bounds of the graph chart + view. + + See the `ORKGraphChartViewDelegate` protocol. +*/ +@property (nonatomic, weak, nullable) id delegate; + +/** + The data source responsible for providing the data required to populate the graph chart view. + + See the `ORKGraphChartViewDataSource` protocol. +*/ +@property (nonatomic, weak) id dataSource; + +/** + The color of the axes drawn by the graph chart view. + + The default value for this property is a light gray color. Setting this property to `nil` + resets it to its default value. +*/ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *axisColor; + +/** + The color of the vertical axis titles. + + The default value for this property is a light gray color. Setting this property to `nil` resets it + to its default value. + + @note The horizontal axis titles use the current `tintColor`. +*/ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *verticalAxisTitleColor; + +/** + The color of the reference lines. + + The default value for this property is a light gray color. Setting this property to `nil` resets it + to its default value. +*/ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *referenceLineColor; + +/** + The background color of the thumb on the scrubber line. + + The default value for this property is a white color. Setting this property to `nil` resets it to + its default value. +*/ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *scrubberThumbColor; + +/** + The color of the scrubber line. + + The default value for this property is a gray color. Setting this property to `nil` resets it to + its default value. +*/ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *scrubberLineColor; + +/** + The string that is displayed if no data points are provided by the data source. + + The default value for this property is an appropriate message string. Setting this property to + `nil` resets it to its default value. +*/ +@property (nonatomic, copy, null_resettable) IBInspectable NSString *noDataText; + +/** + An image to be optionally displayed in place of the maximum value label on the y-axis. + + The default value for this property is `nil`. +*/ +@property (nonatomic, strong, nullable) IBInspectable UIImage *maximumValueImage; + +/** + An image to be optionally displayed in place of the minimum value label on the y-axis. + + The default value for this property is `nil`. +*/ +@property (nonatomic, strong, nullable) IBInspectable UIImage *minimumValueImage; + +/** + The font used to for the x-axis of the chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *xAxisFont; + +/** + The font used to for the y-axis of the chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *yAxisFont; + +/** + The font used to display the value when scrubbing the chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *scrubberFont; + +/** + The font used for the "no data" label in the chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *noDataFont; + +/** + The long press gesture recognizer that is used for scrubbing by the graph chart view. You can use + this property to prioritize your own gesture recognizers. + + This object is instatiated and added to the view when it is created. + */ +@property (nonatomic, strong, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer; + +/** + The gesture recognizer that is used for scrubbing by the graph chart view. + + This object is instatiated and added to the view when it is created. + */ +@property (nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer; + +/** + The number of decimal places that is used on the y-axis and scrubber value labels. + + The default value of this property is 0. + */ +@property (nonatomic) NSUInteger decimalPlaces; + +/** + An array of factors for adding Y-Axis labels + */ +@property (nonatomic)NSArray *yAxisLabelFactors; + +/** + Animates the graph when it first displays on the screen. + + You can optionally call this method from the `viewWillAppear:` implementation of the view + controller that owns the graph chart view. + + @param animationDuration The duration of the appearing animation. + */ +- (void)animateWithDuration:(NSTimeInterval)animationDuration; + +/** + Reloads the plotted data. + + Call this method to reload the data and re-plot the graph. You should call it if the data provided by the dataSource changes. +*/ +- (void)reloadData; + +@end + + +/** + The `ORKValueRangeGraphChartView` class is an abstract class which holds a data source comforming + to the `ORKValueRangeGraphChartViewDataSource` protocol, common to concrete subclasseses. + + You should not instantiate this class directly; use one of the subclasses instead. The concrete + subclasses are `ORKLineGraphChartView` and `ORKDiscreteGraphChartView`. + */ +ORK_CLASS_AVAILABLE +@interface ORKValueRangeGraphChartView : ORKGraphChartView + +/** + The data source responsible for providing the data required to populate the graph chart view. + + See the `ORKValueRangeGraphChartViewDataSource` protocol. + */ +@property (nonatomic, weak) id dataSource; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.m new file mode 100755 index 0000000..509513f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView.m @@ -0,0 +1,1331 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKGraphChartView.h" +#import "ORKGraphChartView_Internal.h" + +#import "ORKChartTypes.h" +#import "ORKLineGraphChartView.h" +#import "ORKXAxisView.h" +#import "ORKYAxisView.h" + +#import "ORKAccessibility.h" +#import "ORKSkin.h" + + +#if TARGET_INTERFACE_BUILDER + +@implementation ORKIBGraphChartViewDataSource + +- (NSInteger)numberOfPlotsInGraphChartView:(ORKGraphChartView *)graphChartView { + return self.plotPoints.count; +} + +- (NSInteger)graphChartView:(ORKGraphChartView *)graphChartView numberOfDataPointsForPlotIndex:(NSInteger)plotIndex { + return self.plotPoints[plotIndex].count; +} + +- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView titleForXAxisAtPointIndex:(NSInteger)pointIndex { + return [@(pointIndex + 1) stringValue]; +} + +@end + + +@implementation ORKIBValueRangeGraphChartViewDataSource + +- (ORKValueRange *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + return self.plotPoints[plotIndex][pointIndex]; +} + +@end + +#endif + + +const CGFloat ORKGraphChartViewLeftPadding = 10.0; +const CGFloat ORKGraphChartViewPointAndLineWidth = 8.0; +const CGFloat ORKGraphChartViewScrubberMoveAnimationDuration = 0.1; +const CGFloat ORKGraphChartViewAxisTickLength = 12.0; +const CGFloat ORKGraphChartViewYAxisTickPadding = 2.0; + +static const CGFloat TopPadding = 7.0; +static const CGFloat XAxisViewHeight = 30.0; +static const CGFloat YAxisViewWidth = 45.0; +static const CGFloat SnappingClosenessFactor = 0.3; +static const CGSize ScrubberThumbSize = (CGSize){10.0, 10.0}; +static const CGFloat ScrubberFadeAnimationDuration = 0.2; +static const CGFloat ScrubberLineToLabelPadding = 6.0; +static const CGFloat ScrubberLabelCornerRadius = 4.0; +static const CGFloat ScrubberLabelHorizontalPadding = 12.0; +static const CGFloat ScrubberLabelVerticalPadding = 4.0; +#define ScrubberLabelColor ([UIColor colorWithWhite:0.98 alpha:0.8]) + +@interface ORKGraphChartView () + +@end + + +@implementation ORKGraphChartView { + UIView *_referenceLinesView; + UILabel *_noDataLabel; + ORKXAxisView *_xAxisView; + ORKYAxisView *_yAxisView; + CAShapeLayer *_horizontalReferenceLineLayer; + NSMutableArray *_verticalReferenceLineLayers; + UILabel *_scrubberLabel; + UIView *_scrubberThumbView; + NSString *_decimalFormat; +} + +#pragma mark - Init + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self sharedInit]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + [self sharedInit]; + } + return self; +} + +- (void)sharedInit { + _numberOfXAxisPoints = -1; + _showsHorizontalReferenceLines = NO; + _showsVerticalReferenceLines = NO; + _dataPoints = [NSMutableArray new]; + _yAxisPoints = [NSMutableArray new]; + _lineLayers = [NSMutableArray new]; + _hasDataPoints = NO; + + // init null resetable properties + _axisColor = ORKColor(ORKGraphAxisColorKey); + _verticalAxisTitleColor = ORKColor(ORKGraphAxisTitleColorKey); + _referenceLineColor = ORKColor(ORKGraphReferenceLineColorKey); + _scrubberLineColor = ORKColor(ORKGraphScrubberLineColorKey); + _scrubberThumbColor = ORKColor(ORKGraphScrubberThumbColorKey); + _noDataText = ORKLocalizedString(@"CHART_NO_DATA_TEXT", nil); + + // nil reset to default fonts + self.xAxisFont = nil; + self.yAxisFont = nil; + self.scrubberFont = nil; + self.noDataFont = nil; + + [self setDecimalPlaces:0]; + + _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleScrubbingGesture:)]; + _longPressGestureRecognizer.delaysTouchesBegan = YES; + _longPressGestureRecognizer.delegate = self; + [self addGestureRecognizer:_longPressGestureRecognizer]; + + _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleScrubbingGesture:)]; + _panGestureRecognizer.delaysTouchesBegan = YES; + _panGestureRecognizer.delegate = self; + [self addGestureRecognizer:_panGestureRecognizer]; + + [self setUpViews]; + + [self updateContentSizeCategoryFonts]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateContentSizeCategoryFonts) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(_axVoiceOverStatusChanged:) + name:UIAccessibilityVoiceOverStatusDidChangeNotification + object:nil]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)reloadData { + _numberOfXAxisPoints = -1; // reset cached number of x axis points + [self updateAndLayoutVerticalReferenceLineLayers]; + [self obtainDataPoints]; + [self calculateMinAndMaxValues]; + [_xAxisView updateTitles]; + [_yAxisView updateTicksAndLabels]; + [self updateLineLayers]; + [self updateNoDataLabel]; + + [self _axCreateAccessibilityElementsIfNeeded]; + + [self setNeedsLayout]; +} + +- (void)setDataSource:(id)dataSource { + _dataSource = dataSource; + [self reloadData]; +} + +#pragma mark - Configuration + +- (void)setAxisColor:(UIColor *)axisColor { + if (!axisColor) { + axisColor = ORKColor(ORKGraphAxisColorKey); + } + _axisColor = axisColor; + _xAxisView.axisColor = _axisColor; + _yAxisView.axisColor = _axisColor; +} + +- (void)setVerticalAxisTitleColor:(UIColor *)verticalAxisTitleColor { + if (!verticalAxisTitleColor) { + verticalAxisTitleColor = ORKColor(ORKGraphAxisTitleColorKey); + } + _verticalAxisTitleColor = verticalAxisTitleColor; + _yAxisView.titleColor = _verticalAxisTitleColor; +} + +- (void)setReferenceLineColor:(UIColor *)referenceLineColor { + if (!referenceLineColor) { + referenceLineColor = ORKColor(ORKGraphReferenceLineColorKey); + } + _referenceLineColor = referenceLineColor; + _horizontalReferenceLineLayer.strokeColor = referenceLineColor.CGColor; + [self updateAndLayoutVerticalReferenceLineLayers]; + [self updatePlotColors]; +} + +- (void)setScrubberLineColor:(UIColor *)scrubberLineColor { + if (!scrubberLineColor) { + scrubberLineColor = ORKColor(ORKGraphScrubberLineColorKey); + } + _scrubberLineColor = scrubberLineColor; + _scrubberLine.backgroundColor = _scrubberLineColor; + _scrubberThumbView.layer.borderColor = _scrubberLineColor.CGColor; + _scrubberLabel.layer.borderColor = _scrubberLineColor.CGColor; +} + +- (void)setScrubberThumbColor:(UIColor *)scrubberThumbColor { + if (!scrubberThumbColor) { + scrubberThumbColor = ORKColor(ORKGraphScrubberThumbColorKey); + } + _scrubberThumbColor = scrubberThumbColor; + _scrubberThumbView.backgroundColor = _scrubberThumbColor; +} + +- (void)setNoDataText:(NSString *)noDataText { + if (!noDataText) { + noDataText = ORKLocalizedString(@"CHART_NO_DATA_TEXT", nil); + } + _noDataText = [noDataText copy]; + _noDataLabel.text = _noDataText; +} + +- (void)setMaximumValueImage:(UIImage *)maximumValueImage { + _maximumValueImage = maximumValueImage; + [_yAxisView updateTicksAndLabels]; +} + +- (void)setMinimumValueImage:(UIImage *)minimumValueImage { + _minimumValueImage = minimumValueImage; + [_yAxisView updateTicksAndLabels]; +} + +- (void)setXAxisFont:(UIFont *)xAxisFont { + if (!xAxisFont) { + xAxisFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; + } + _xAxisFont = xAxisFont; + _xAxisView.titleFont = _xAxisFont; +} + +- (void)setYAxisFont:(UIFont *)yAxisFont { + if (!yAxisFont) { + yAxisFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2]; + } + _yAxisFont = yAxisFont; + _yAxisView.titleFont = _yAxisFont; +} + +- (void)setScrubberFont:(UIFont *)scrubberFont { + if (!scrubberFont) { + scrubberFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; + } + _scrubberFont = scrubberFont; + _scrubberLabel.font = _scrubberFont; +} + +- (void)setNoDataFont:(UIFont *)noDataFont { + if (!noDataFont) { + noDataFont = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + } + _noDataFont = noDataFont; + _noDataLabel.font = _noDataFont; +} + +- (void)setDecimalPlaces:(NSUInteger)decimalPlaces { + _decimalPlaces = decimalPlaces; + _decimalFormat = [NSString stringWithFormat:@"%%.%luf", (unsigned long)_decimalPlaces]; + [_yAxisView setDecimalPlaces:_decimalPlaces]; +} + +- (void)setYAxisLabelFactors:(NSArray *)yAxisLabelFactors { + _yAxisLabelFactors = yAxisLabelFactors; + _yAxisView.yAxisLabelFactors = yAxisLabelFactors; + [_yAxisView updateTicksAndLabels]; +} + +- (void)setShowsHorizontalReferenceLines:(BOOL)showsHorizontalReferenceLines { + _showsHorizontalReferenceLines = showsHorizontalReferenceLines; + [self updateHorizontalReferenceLines]; + [self layoutHorizontalReferenceLineLayers]; +} + +- (void)setShowsVerticalReferenceLines:(BOOL)showsVerticalReferenceLines { + _showsVerticalReferenceLines = showsVerticalReferenceLines; + [self updateAndLayoutVerticalReferenceLineLayers]; +} + +- (void)tintColorDidChange { + _xAxisView.tintColor = self.tintColor; + [self updatePlotColors]; +} + +- (UIColor *)colorForPlotIndex:(NSInteger)plotIndex subpointIndex:(NSInteger)subpointIndex totalSubpoints:(NSInteger)totalSubpoints { + // pointIndex and totalSubpoints only affect the derived color on the ORKBarGraphChartView subclass + UIColor *color = nil; + if ([_dataSource respondsToSelector:@selector(graphChartView:colorForPlotIndex:)]) { + color = [_dataSource graphChartView:self colorForPlotIndex:plotIndex]; + } else { + color = (plotIndex == 0) ? self.tintColor : _referenceLineColor; + } + return color; +} + +- (UIColor *)colorForPlotIndex:(NSInteger)plotIndex { + return [self colorForPlotIndex:plotIndex subpointIndex:0 totalSubpoints:0]; +} + +- (void)updatePlotColors { + for (NSUInteger plotIndex = 0; plotIndex < _lineLayers.count; plotIndex++) { + [self updatePlotColorsForPlotIndex:plotIndex]; + } +} + +- (void)updatePlotColorsForPlotIndex:(NSInteger)plotIndex { + NSUInteger numberOfPoints = _lineLayers[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < numberOfPoints; pointIndex++) { + NSUInteger numberOfSubpoints = _lineLayers[plotIndex][pointIndex].count; + for (NSUInteger subpointIndex = 0; subpointIndex < numberOfSubpoints; subpointIndex++) { + UIColor *color = [self colorForPlotIndex:plotIndex subpointIndex:subpointIndex totalSubpoints:numberOfSubpoints]; + CAShapeLayer *lineLayer = _lineLayers[plotIndex][pointIndex][subpointIndex]; + lineLayer.strokeColor = color.CGColor; + } + } +} + +- (void)updateContentSizeCategoryFonts { + _xAxisView.titleFont = self.xAxisFont; + _yAxisView.titleFont = self.yAxisFont; + _scrubberLabel.font = self.scrubberFont; + _noDataLabel.font = self.noDataFont; +} + +- (void)setUpViews { + _referenceLinesView = [UIView new]; + [self addSubview:_referenceLinesView]; + + _xAxisView = [[ORKXAxisView alloc] initWithParentGraphChartView:self]; + [self addSubview:_xAxisView]; + + _yAxisView = [[ORKYAxisView alloc] initWithParentGraphChartView:self]; + [self addSubview:_yAxisView]; + + _plotView = [UIView new]; + _plotView.backgroundColor = [UIColor clearColor]; + [self addSubview:_plotView]; + + [self updateHorizontalReferenceLines]; + + _scrubberLine = [UIView new]; + _scrubberLine.backgroundColor = _scrubberLineColor; + _scrubberLine.alpha = 0; + [self addSubview:_scrubberLine]; + + _scrubberLabel = [UILabel new]; + _scrubberLabel.alpha = 0; + _scrubberLabel.layer.cornerRadius = ScrubberLabelCornerRadius; + _scrubberLabel.layer.borderColor = _scrubberLineColor.CGColor; + _scrubberLabel.layer.borderWidth = 1.0f; + _scrubberLabel.textColor = [UIColor darkGrayColor]; + _scrubberLabel.textAlignment = NSTextAlignmentCenter; + _scrubberLabel.backgroundColor = ScrubberLabelColor; + [self addSubview:_scrubberLabel]; + + _scrubberThumbView = [[UIView alloc] initWithFrame:CGRectMake(0, + 0, + ScrubberThumbSize.width, + ScrubberThumbSize.height)]; + _scrubberThumbView.layer.cornerRadius = _scrubberThumbView.bounds.size.height / 2; + _scrubberThumbView.layer.borderWidth = 1.0; + _scrubberThumbView.backgroundColor = _scrubberThumbColor; + _scrubberThumbView.layer.borderColor = _scrubberLineColor.CGColor; + _scrubberThumbView.alpha = 0; + [self addSubview:_scrubberThumbView]; +} + +- (void)updateHorizontalReferenceLines { + [_horizontalReferenceLineLayer removeFromSuperlayer]; + _horizontalReferenceLineLayer = nil; + if (_showsHorizontalReferenceLines) { + _horizontalReferenceLineLayer = [CAShapeLayer layer]; + _horizontalReferenceLineLayer.strokeColor = _referenceLineColor.CGColor; + _horizontalReferenceLineLayer.lineDashPattern = @[@6, @4]; + + [_referenceLinesView.layer insertSublayer:_horizontalReferenceLineLayer atIndex:0]; + } +} + +ORK_INLINE UIImage *graphVerticalReferenceLineLayerImageWithColor(UIColor *color, CGFloat height) { + static UIImage *lineImage = nil; + static UIColor *lineImageColor = nil; + static CGFloat lineImageHeight = 0.0; + if (height > 0 && (!lineImage || ![lineImageColor isEqual:color] || lineImageHeight != height)) { + lineImageColor = color; + lineImageHeight = height; + UIBezierPath *referenceLinePath = [UIBezierPath bezierPath]; + [referenceLinePath moveToPoint:CGPointMake(0, 0)]; + [referenceLinePath addLineToPoint:CGPointMake(0, height)]; + + CAShapeLayer *referenceLineLayer = [CAShapeLayer new]; + referenceLineLayer.path = referenceLinePath.CGPath; + referenceLineLayer.lineWidth = [UIScreen mainScreen].scale; + referenceLineLayer.strokeColor = color.CGColor; + referenceLineLayer.lineDashPattern = @[@6, @4]; + + UIGraphicsBeginImageContextWithOptions((CGSize){1, height}, NO, [UIScreen mainScreen].scale); + [referenceLineLayer renderInContext:UIGraphicsGetCurrentContext()]; + lineImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + return lineImage; +} + +ORK_INLINE CALayer *graphVerticalReferenceLineLayerWithColor(UIColor *color, CGFloat height) { + CALayer *referenceLineLayer = [CALayer new]; + referenceLineLayer.frame = (CGRect){{0, 0}, {1, height}}; + referenceLineLayer.anchorPoint = CGPointMake(0, 0); + referenceLineLayer.contents = (__bridge id)(graphVerticalReferenceLineLayerImageWithColor(color, height).CGImage); + + return referenceLineLayer; +} + +- (void)obtainDataPoints { + [_dataPoints removeAllObjects]; + _hasDataPoints = NO; + + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + [self obtainDataPointsForPlotIndex:plotIndex]; + } +} + +- (void)obtainDataPointsForPlotIndex:(NSInteger)plotIndex { + [self.dataPoints addObject:[NSMutableArray new]]; + NSInteger numberOfPoints = [self.dataSource graphChartView:self numberOfDataPointsForPlotIndex:plotIndex]; + for (NSInteger pointIndex = 0; pointIndex < numberOfPoints; pointIndex++) { + NSObject *value = [self dataPointForPointIndex:pointIndex plotIndex:plotIndex]; + [self.dataPoints[plotIndex] addObject:value]; + if (!value.isUnset) { + self.hasDataPoints = YES; + } + } + // Add dummy points for empty data points + NSInteger emptyPointsCount = self.numberOfXAxisPoints - self.dataPoints[plotIndex].count; + for (NSInteger idx = 0; idx < emptyPointsCount; idx++) { + [self.dataPoints[plotIndex] addObject:[self dummyPoint]]; + } +} + +#pragma mark - Layout & Drawing + +- (void)setBounds:(CGRect)bounds { + BOOL sizeChanged = !CGSizeEqualToSize(bounds.size, self.bounds.size); + [super setBounds:bounds]; + if (sizeChanged) { + [self setNeedsLayout]; + } +} + +- (void)setFrame:(CGRect)frame { + BOOL sizeChanged = !CGSizeEqualToSize(frame.size, self.frame.size); + [super setFrame:frame]; + if (sizeChanged) { + [self setNeedsLayout]; + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect plotViewFrame = CGRectMake(ORKGraphChartViewLeftPadding, + TopPadding, + CGRectGetWidth(self.frame) - YAxisViewWidth - ORKGraphChartViewLeftPadding, + CGRectGetHeight(self.frame) - XAxisViewHeight - TopPadding); + + _referenceLinesView.frame = plotViewFrame; + _plotView.frame = plotViewFrame; + + _xAxisView.frame = CGRectMake(CGRectGetMinX(_plotView.frame), + CGRectGetMaxY(_plotView.frame), + CGRectGetWidth(_plotView.frame), + XAxisViewHeight); + + _yAxisView.frame = CGRectMake(CGRectGetWidth(self.frame) - YAxisViewWidth, + TopPadding, + YAxisViewWidth, + CGRectGetHeight(_plotView.frame)); + + [self layoutHorizontalReferenceLineLayers]; + [self updateAndLayoutVerticalReferenceLineLayers]; + + if (_noDataLabel) { + _noDataLabel.frame = CGRectMake(0, + 0, + CGRectGetWidth(_plotView.frame), + CGRectGetHeight(_plotView.frame)); + } + + // Scrubber Views + _scrubberLine.frame = CGRectMake(CGRectGetMinX(_scrubberLine.frame), + TopPadding, + 1, + CGRectGetHeight(_plotView.frame)); + + [self updateYAxisPoints]; + [self layoutLineLayers]; +} + +- (void)updateYAxisPoints { + [_yAxisPoints removeAllObjects]; + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + [_yAxisPoints addObject:[self normalizedCanvasDataPointsForPlotIndex:plotIndex canvasHeight:_plotView.bounds.size.height]]; + } +} + +- (void)layoutHorizontalReferenceLineLayers { + if (_showsHorizontalReferenceLines) { + CGSize plotViewSize = _plotView.bounds.size; + UIBezierPath *horizontalReferenceLinePath = [UIBezierPath bezierPath]; + [horizontalReferenceLinePath moveToPoint:CGPointMake(0 - scalePixelAdjustment(), + floor(plotViewSize.height / 2))]; + [horizontalReferenceLinePath addLineToPoint:CGPointMake(plotViewSize.width + _yAxisView.bounds.size.width, + floor(plotViewSize.height / 2))]; + _horizontalReferenceLineLayer.path = horizontalReferenceLinePath.CGPath; + } +} + +- (void)updateAndLayoutVerticalReferenceLineLayers { + [_verticalReferenceLineLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + _verticalReferenceLineLayers = nil; + if (_showsVerticalReferenceLines) { + _verticalReferenceLineLayers = [NSMutableArray new]; + CGFloat plotViewHeight = _plotView.bounds.size.height; + CGFloat plotViewWidth = _plotView.bounds.size.width; + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + for (NSUInteger pointIndex = 1; pointIndex < numberOfXAxisPoints; pointIndex++) { + if (![_dataSource respondsToSelector:@selector(graphChartView:drawsVerticalReferenceLineAtPointIndex:)] + || [_dataSource graphChartView:self drawsVerticalReferenceLineAtPointIndex:pointIndex]) { + CALayer *verticalReferenceLineLayer = graphVerticalReferenceLineLayerWithColor(_referenceLineColor, plotViewHeight); + CGFloat positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, plotViewWidth); + verticalReferenceLineLayer.position = CGPointMake(positionOnXAxis - scalePixelAdjustment(), 0); + [_referenceLinesView.layer insertSublayer:verticalReferenceLineLayer atIndex:0]; + [_verticalReferenceLineLayers addObject:verticalReferenceLineLayer]; + } + } + } +} + +ORK_INLINE UIImage *graphPointLayerImageWithColor(UIColor *color) { + const CGFloat pointSize = ORKGraphChartViewPointAndLineWidth; + const CGFloat pointLineWidth = 2.0; + + static UIImage *pointImage = nil; + static UIColor *pointImageColor = nil; + if (!pointImage || ![pointImageColor isEqual:color]) { + pointImageColor = color; + UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect: + (CGRect){{0 + (pointLineWidth / 2), 0 + (pointLineWidth / 2)}, {pointSize - pointLineWidth, pointSize - pointLineWidth}}]; + CAShapeLayer *pointLayer = [CAShapeLayer new]; + pointLayer.path = circlePath.CGPath; + pointLayer.fillColor = [UIColor whiteColor].CGColor; + pointLayer.strokeColor = color.CGColor; + pointLayer.lineWidth = pointLineWidth; + + UIGraphicsBeginImageContextWithOptions((CGSize){pointSize, pointSize}, NO, [UIScreen mainScreen].scale); + [pointLayer renderInContext:UIGraphicsGetCurrentContext()]; + pointImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + } + return pointImage; +} + +ORK_INLINE CALayer *graphPointLayerWithColor(UIColor *color, BOOL drawPointIndicator) { + const CGFloat pointSize = ORKGraphChartViewPointAndLineWidth; + CALayer *pointLayer = [CALayer new]; + pointLayer.frame = (CGRect){{0, 0}, {pointSize, pointSize}}; + if (drawPointIndicator) { + pointLayer.contents = (__bridge id)(graphPointLayerImageWithColor(color).CGImage); + } + + return pointLayer; +} + +- (BOOL)shouldDrawPointIndicatorForPointWithIndex:(NSInteger)pointIndex inPlotWithIndex:(NSInteger)plotIndex { + ORKValueRange *dataPoint = (ORKValueRange *)_dataPoints[plotIndex][pointIndex]; + if (dataPoint.isUnset) { + return NO; + } + if (!dataPoint.isEmptyRange) { + return YES; + } + if ([self isKindOfClass:[ORKLineGraphChartView class]] + && [_dataSource respondsToSelector:@selector(graphChartView:drawsPointIndicatorsForPlotIndex:)]) { + return [_dataSource graphChartView:self drawsPointIndicatorsForPlotIndex:plotIndex]; + } + return YES; +} + +- (void)updateLineLayers { + for (NSInteger plotIndex = 0; plotIndex < _lineLayers.count; plotIndex++) { + for (NSMutableArray *sublineLayers in self.lineLayers[plotIndex]) { + [sublineLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + } + } + [_lineLayers removeAllObjects]; + + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + // Add array even if it should not draw lines so all layer arays have the same number of elements for animating purposes + NSMutableArray *> *currentPlotLineLayers = [NSMutableArray new]; + [_lineLayers addObject:currentPlotLineLayers]; + if ([self shouldDrawLinesForPlotIndex:plotIndex]) { + [self updateLineLayersForPlotIndex:plotIndex]; + } + } +} + +- (void)layoutLineLayers { + + NSInteger numberOfPlots = [self numberOfPlots]; + if (_yAxisPoints.count != numberOfPlots) { + // avoid layout if points have not been normalized yet + return; + } + + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + if ([self shouldDrawLinesForPlotIndex:plotIndex]) { + [self layoutLineLayersForPlotIndex:plotIndex]; + } + } +} + +- (void)updateNoDataLabel { + if (!_hasDataPoints && !_noDataLabel) { + _noDataLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _noDataLabel.text = _noDataText; + _noDataLabel.textAlignment = NSTextAlignmentCenter; + _noDataLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + _noDataLabel.textColor = [UIColor lightGrayColor]; + [_plotView addSubview:_noDataLabel]; + } else if (_hasDataPoints && _noDataLabel) { + [_noDataLabel removeFromSuperview]; + _noDataLabel = nil; + } +} + +- (CGFloat)xOffsetForPlotIndex:(NSInteger)plotIndex { + return 0; +} + +#pragma mark - Plotting Points + +- (NSInteger)numberOfPlots { + NSInteger numberOfPlots = 0; + + if ([_dataSource respondsToSelector:@selector(numberOfPlotsInGraphChartView:)]) { + numberOfPlots = [_dataSource numberOfPlotsInGraphChartView:self]; + } + + return numberOfPlots; +} + +- (NSInteger)numberOfXAxisPoints { + if (_numberOfXAxisPoints != -1) { + return _numberOfXAxisPoints; + } + + _numberOfXAxisPoints = 0; + + if ([_dataSource respondsToSelector:@selector(numberOfDivisionsInXAxisForGraphChartView:)]) { + _numberOfXAxisPoints = [_dataSource numberOfDivisionsInXAxisForGraphChartView:self]; + } + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger idx = 0; idx < numberOfPlots; idx++) { + NSInteger numberOfPlotPoints = [_dataSource graphChartView:self numberOfDataPointsForPlotIndex:idx]; + if (_numberOfXAxisPoints < numberOfPlotPoints) { + _numberOfXAxisPoints = numberOfPlotPoints; + } + } + + return _numberOfXAxisPoints; +} + +#pragma mark - Scrubbing + +- (NSInteger)scrubbingPlotIndex { + NSInteger plotIndex = 0; + if ([_dataSource respondsToSelector:@selector(scrubbingPlotIndexForGraphChartView:)]) { + plotIndex = [_dataSource scrubbingPlotIndexForGraphChartView:self]; + if (plotIndex >= [self numberOfPlots]) { + plotIndex = 0; + } + } + return plotIndex; +} + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + BOOL shouldBegin = NO; + if (gestureRecognizer == _panGestureRecognizer) { + CGPoint translation = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:self]; + if (fabs(translation.x) > fabs(translation.y)) { + shouldBegin = YES; + } + } else if (gestureRecognizer == _longPressGestureRecognizer) { + shouldBegin = YES; + } + return shouldBegin; +} + +- (void)handleScrubbingGesture:(UIGestureRecognizer *)gestureRecognizer { + NSInteger scrubbingPlotIndex = [self scrubbingPlotIndex]; + if ((_dataPoints.count > scrubbingPlotIndex) && ([self numberOfValidValuesForPlotIndex:scrubbingPlotIndex] > 0)) { + + CGPoint location = [gestureRecognizer locationInView:_plotView]; + CGFloat maxX = round(CGRectGetWidth(_plotView.bounds)); + CGFloat normalizedX = MAX(MIN(location.x, maxX), 0); + location = CGPointMake(normalizedX, location.y); + CGFloat snappedXPosition = [self snappedXPosition:location.x plotIndex:scrubbingPlotIndex]; + [self updateScrubberViewForXPosition:snappedXPosition plotIndex:scrubbingPlotIndex]; + + if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { + [self setScrubberViewsHidden:NO animated:YES]; + if ([_delegate respondsToSelector:@selector(graphChartViewTouchesBegan:)]) { + [_delegate graphChartViewTouchesBegan:self]; + } + } else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) { + if ([_delegate respondsToSelector:@selector(graphChartView:touchesMovedToXPosition:)]) { + [_delegate graphChartView:self touchesMovedToXPosition:snappedXPosition]; + } + } else if (gestureRecognizer.state == UIGestureRecognizerStateEnded) { + [self setScrubberViewsHidden:YES animated:YES]; + if ([_delegate respondsToSelector:@selector(graphChartViewTouchesEnded:)]) { + [_delegate graphChartViewTouchesEnded:self]; + } + } + } +} + +- (void)updateScrubberViewForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + void (^updateScrubberLinePosition)(void) = ^{ + self.scrubberLine.center = CGPointMake(xPosition + ORKGraphChartViewLeftPadding, self.scrubberLine.center.y); + }; + BOOL scrubberlineAnimated = (self.scrubberLine.alpha > 0); + BOOL scrubberlineAccessoriesAnimated = !self.scrubberAccessoryViewsHidden; + if (scrubberlineAnimated || scrubberlineAccessoriesAnimated) { + [UIView animateWithDuration:ORKGraphChartViewScrubberMoveAnimationDuration animations:^{ + if (scrubberlineAnimated) { + updateScrubberLinePosition(); + } + if (scrubberlineAccessoriesAnimated) { + [self updateScrubberLineAccessories:xPosition plotIndex:plotIndex]; + } + }]; + } + if (!scrubberlineAnimated) { + updateScrubberLinePosition(); + } + if (!scrubberlineAccessoriesAnimated) { + [self updateScrubberLineAccessories:xPosition plotIndex:plotIndex]; + } +} + +- (BOOL)scrubberAccessoryViewsHidden { + return _scrubberLabel.hidden && _scrubberThumbView.hidden; +} + +- (void)setScrubberAccessoryViewsHidden:(BOOL)hidden { + _scrubberLabel.hidden = hidden; + _scrubberThumbView.hidden = hidden; +} + +- (void)updateScrubberLineAccessories:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + double scrubberYPosition = [self canvasYPositionForXPosition:xPosition plotIndex:plotIndex]; + double scrubbingValue = [self scrubbingLabelValueForCanvasXPosition:xPosition plotIndex:plotIndex]; + + if (scrubberYPosition == scrubberYPosition) { + _scrubberThumbView.center = CGPointMake(xPosition + ORKGraphChartViewLeftPadding, scrubberYPosition + TopPadding); + _scrubberLabel.text = [NSString stringWithFormat:_decimalFormat, scrubbingValue == ORKDoubleInvalidValue ? 0.0 : scrubbingValue ]; + CGSize textSize = [_scrubberLabel.text boundingRectWithSize:CGSizeMake(_plotView.bounds.size.width, + _plotView.bounds.size.height) + options:(NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin) + attributes:@{NSFontAttributeName: _scrubberLabel.font} + context:nil].size; + _scrubberLabel.frame = CGRectMake(xPosition + ORKGraphChartViewLeftPadding + ScrubberLineToLabelPadding, + CGRectGetMinY(_scrubberLine.frame), + textSize.width + ScrubberLabelHorizontalPadding, + textSize.height + ScrubberLabelVerticalPadding); + + if (scrubbingValue == ORKDoubleInvalidValue) { + [self setScrubberAccessoryViewsHidden:YES]; + } else { + [self setScrubberAccessoryViewsHidden:NO]; + } + } +} + +- (void)setScrubberViewsHidden:(BOOL)hidden animated:(BOOL)animated { + void (^updateAlpha)(BOOL) = ^(BOOL isHidden) { + CGFloat alpha = isHidden ? 0.0 : 1.0; + _scrubberThumbView.alpha = alpha; + _scrubberLine.alpha = alpha; + _scrubberLabel.alpha = alpha; + }; + + if (animated) { + [UIView animateWithDuration:ScrubberFadeAnimationDuration animations:^{ + updateAlpha(hidden); + }]; + } else { + updateAlpha(hidden); + } +} + +- (NSInteger)pointIndexForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + NSInteger pointIndex = 0; + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + for (pointIndex = 0; pointIndex < (numberOfXAxisPoints - 1); pointIndex++) { + CGFloat xAxisPointValue = xAxisPoint(pointIndex, numberOfXAxisPoints, _plotView.bounds.size.width); + if (xAxisPointValue >= xPosition) { + break; + } + } + return pointIndex; +} + +- (NSInteger)numberOfValidValuesForPlotIndex:(NSInteger)plotIndex { + NSInteger count = 0; + + if (plotIndex < _dataPoints.count) { + for (ORKValueRange *rangePoint in _dataPoints[plotIndex]) { + if (!rangePoint.isUnset) { + count++; + } + } + } + return count; +} + +- (BOOL)isXPositionSnapped:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + BOOL snapped = NO; + CGFloat viewWidth = _plotView.bounds.size.width; + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + for (NSInteger idx = 0; idx < numberOfXAxisPoints; idx++) { + if (xPosition == xAxisPoint(idx, numberOfXAxisPoints, viewWidth)) { + snapped = YES; + break; + } + } + return snapped; +} + +- (CGFloat)snappedXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + CGFloat widthBetweenPoints = CGRectGetWidth(self.plotView.frame) / numberOfXAxisPoints; + NSUInteger positionCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < positionCount; pointIndex++) { + + double scrubbingValue = [self scrubbingValueForPlotIndex:plotIndex pointIndex:pointIndex]; + + if (scrubbingValue != ORKDoubleInvalidValue) { + CGFloat snappedXPosition = xAxisPoint(pointIndex, numberOfXAxisPoints, self.plotView.bounds.size.width); + + if (fabs(snappedXPosition - xPosition) < (widthBetweenPoints * SnappingClosenessFactor)) { + xPosition = snappedXPosition; + } + } + } + return xPosition; +} + +- (double)scrubbingLabelValueForCanvasXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + double value = ORKDoubleInvalidValue; + BOOL snapped = [self isXPositionSnapped:xPosition plotIndex:(NSInteger)plotIndex]; + if (snapped) { + NSInteger pointIndex = [self pointIndexForXPosition:xPosition plotIndex:plotIndex]; + value = [self scrubbingValueForPlotIndex:plotIndex pointIndex:pointIndex];; + } + return value; +} + +- (double)canvasYPositionForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + BOOL snapped = [self isXPositionSnapped:xPosition plotIndex:plotIndex]; + double canvasYPosition = 0; + if (snapped) { + NSInteger pointIndex = [self pointIndexForXPosition:xPosition plotIndex:plotIndex]; + canvasYPosition = [self scrubbingYAxisPointForPlotIndex:plotIndex pointIndex:pointIndex]; + } + return canvasYPosition; +} + +#pragma mark - Animation + +- (void)animateWithDuration:(NSTimeInterval)duration { + if (duration < 0) { + @throw [NSException exceptionWithName:NSGenericException reason:@"animationDuration cannot be lower than 0" userInfo:nil]; + } + for (NSUInteger plotIndex = 0; plotIndex < [self numberOfPlots]; plotIndex++) { + [self prepareAnimationsForPlotIndex:plotIndex]; + [self animateLayersSequentiallyWithDuration:duration plotIndex:plotIndex]; + } + } + +- (void)prepareAnimationsForPlotIndex:(NSInteger)plotIndex { + for (NSMutableArray *sublineLayers in self.lineLayers[plotIndex]) { + [sublineLayers makeObjectsPerformSelector:@selector(removeAllAnimations)]; + for (CAShapeLayer *lineLayer in sublineLayers) { + lineLayer.strokeEnd = 0; + } +} + } + +- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration plotIndex:(NSInteger)plotIndex { + NSUInteger numberOfLines = self.lineLayers[plotIndex].count; + if (numberOfLines > 0) { + CGFloat lineFadeDuration = duration / numberOfLines; + CGFloat lineDelay = 0.0; + for (NSUInteger lineIndex = 0; lineIndex < numberOfLines; lineIndex++) { + NSUInteger numberOfSublines = self.lineLayers[plotIndex][lineIndex].count; + if (numberOfSublines > 0) { + CGFloat sublineFadeDuration = lineFadeDuration / numberOfSublines; + CGFloat sublineDelay = 0.0; + for (NSUInteger sublineIndex = 0; sublineIndex < numberOfSublines; sublineIndex++) { + CAShapeLayer *layer = self.lineLayers[plotIndex][lineIndex][sublineIndex]; + [self animateLayer:layer keyPath:@"strokeEnd" duration:sublineFadeDuration startDelay:lineDelay + sublineDelay]; + sublineDelay += sublineFadeDuration; + } + lineDelay += sublineDelay; + } + } + } +} + +- (void)animateLayer:(CALayer *)layer + keyPath:(NSString *)keyPath + duration:(CGFloat)duration + startDelay:(CGFloat)startDelay { + [self animateLayer:layer + keyPath:keyPath + duration:duration + startDelay:startDelay + timingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; +} + +- (void)animateLayer:(CALayer *)layer + keyPath:(NSString *)keyPath + duration:(CGFloat)duration + startDelay:(CGFloat)startDelay + timingFunction:(CAMediaTimingFunction *)timingFunction +{ + NSCAssert(layer && keyPath && duration >= 0.0 && startDelay >= 0.0 && timingFunction, @""); + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath]; + animation.beginTime = CACurrentMediaTime() + startDelay; + animation.fromValue = @(0.0); + animation.toValue = @(1.0); + animation.duration = duration; + animation.timingFunction = timingFunction; + animation.fillMode = kCAFillModeForwards; + animation.removedOnCompletion = NO; + [layer addAnimation:animation forKey:keyPath]; +} + +#pragma mark - Abstract + +- (void)throwOverrideException { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] + userInfo:nil]; +} + +- (NSObject *)dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + [self throwOverrideException]; + return nil; +} + +- (NSObject *)dummyPoint { + [self throwOverrideException]; + return nil; +} + +- (NSMutableArray *> *)normalizedCanvasDataPointsForPlotIndex:(NSInteger)plotIndex canvasHeight:(CGFloat)viewHeight { + [self throwOverrideException]; + return nil; +} + +- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex { + [self throwOverrideException]; +} + +- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex { + [self throwOverrideException]; +} + +- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex { + [self throwOverrideException]; + return NO; +} + +- (void)calculateMinAndMaxValues { + [self throwOverrideException]; +} + +- (double)scrubbingValueForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + [self throwOverrideException]; + return 0; +} + +- (double)scrubbingYAxisPointForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + [self throwOverrideException]; + return 0; +} + +- (void)updatePointLayers { + [self throwOverrideException]; +} + +- (void)layoutPointLayers { + [self throwOverrideException]; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return NO; +} + +#pragma mark - Accessibility Helpers + +- (void)_axVoiceOverStatusChanged:(NSNotification *)notification { + [self _axCreateAccessibilityElementsIfNeeded]; +} + +- (void)_axCreateAccessibilityElementsIfNeeded { + if (!UIAccessibilityIsVoiceOverRunning()) { + // No need to creating accessibility elements if Voice Over is not running + return; + } + + NSInteger maxNumberOfPoints = [[_dataPoints valueForKeyPath:@"@max.@count.self"] integerValue]; + NSMutableArray *accessibilityElements = [[NSMutableArray alloc] initWithCapacity:maxNumberOfPoints]; + + for (NSInteger pointIndex = 0; pointIndex < maxNumberOfPoints; pointIndex++) { + ORKGraphChartAccessibilityElement *element = [[ORKGraphChartAccessibilityElement alloc] initWithAccessibilityContainer:self index:pointIndex maxIndex:maxNumberOfPoints]; + + // Data points for all plots at any given pointIndex must be included (eg "2 and 4" or "range from 1-2 and range from 4-5"). + NSString *value = @""; + for (NSInteger plotIndex = 0; plotIndex < _dataPoints.count; plotIndex++) { + + // Boundary check + if (pointIndex < _dataPoints[plotIndex].count) { + NSString *and = (value.length == 0 ? @"" : ORKLocalizedString(@"AX_GRAPH_AND_SEPARATOR", nil)); + NSObject *dataPoint = _dataPoints[plotIndex][pointIndex]; + value = ORKAccessibilityStringForVariables(value, and, dataPoint.accessibilityLabel); + } + } + + if ([_dataSource respondsToSelector:@selector(graphChartView:titleForXAxisAtPointIndex:)]) { + element.accessibilityLabel = [self.dataSource graphChartView:self titleForXAxisAtPointIndex:pointIndex]; + } else { + element.accessibilityLabel = [NSString stringWithFormat:ORKLocalizedString(@"AX_GRAPH_POINT_%@", nil), ORKLocalizedStringFromNumber(@(pointIndex))]; + } + element.accessibilityValue = value; + [accessibilityElements addObject:element]; + } + + self.accessibilityElements = accessibilityElements; +} + +@end + + +@implementation ORKValueRangeGraphChartView { + NSMutableArray *> *_pointLayers; + } + +@dynamic dataSource; +@dynamic dataPoints; +@dynamic yAxisPoints; + +- (void)sharedInit { + [super sharedInit]; + _pointLayers = [NSMutableArray new]; + } + +- (void)reloadData { + [super reloadData]; + [self updatePointLayers]; + [self setNeedsLayout]; + } + +- (ORKValueRange *)dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + return [self.dataSource graphChartView:self dataPointForPointIndex:pointIndex plotIndex:plotIndex]; + } + +- (ORKValueRange *)dummyPoint { + return [ORKValueRange new]; +} + +- (NSMutableArray *)normalizedCanvasDataPointsForPlotIndex:(NSInteger)plotIndex canvasHeight:(CGFloat)viewHeight { + NSMutableArray *normalizedPoints = [NSMutableArray new]; + + if (plotIndex < self.dataPoints.count) { + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + + ORKValueRange *normalizedRangePoint = [ORKValueRange new]; + ORKValueRange *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + + if (dataPointValue.isUnset) { + normalizedRangePoint.minimumValue = normalizedRangePoint.maximumValue = viewHeight; + } else if (self.minimumValue == self.maximumValue) { + normalizedRangePoint.minimumValue = normalizedRangePoint.maximumValue = viewHeight / 2; + } else { + double range = self.maximumValue - self.minimumValue; + double normalizedMinimumValue = (dataPointValue.minimumValue - self.minimumValue) / range * viewHeight; + double normalizedMaximumValue = (dataPointValue.maximumValue - self.minimumValue) / range * viewHeight; + + normalizedRangePoint.minimumValue = viewHeight - normalizedMinimumValue; + normalizedRangePoint.maximumValue = viewHeight - normalizedMaximumValue; + } + [normalizedPoints addObject:normalizedRangePoint]; + } + } + + return normalizedPoints; +} + +- (void)calculateMinAndMaxValues { + self.minimumValue = ORKDoubleInvalidValue; + self.maximumValue = ORKDoubleInvalidValue; + + BOOL minimumValueProvided = NO; + BOOL maximumValueProvided = NO; + + if ([self.dataSource respondsToSelector:@selector(minimumValueForGraphChartView:)]) { + self.minimumValue = [self.dataSource minimumValueForGraphChartView:self]; + minimumValueProvided = YES; + } + + if ([self.dataSource respondsToSelector:@selector(maximumValueForGraphChartView:)]) { + self.maximumValue = [self.dataSource maximumValueForGraphChartView:self]; + maximumValueProvided = YES; + } + + if (!minimumValueProvided || !maximumValueProvided) { + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + NSInteger numberOfPlotPoints = self.dataPoints[plotIndex].count; + for (NSInteger pointIndex = 0; pointIndex < numberOfPlotPoints; pointIndex++) { + ORKValueRange *point = self.dataPoints[plotIndex][pointIndex]; + if (!minimumValueProvided && + point.minimumValue != ORKDoubleInvalidValue && + ((self.minimumValue == ORKDoubleInvalidValue) || (point.minimumValue < self.minimumValue))) { + self.minimumValue = point.minimumValue; + } + if (!maximumValueProvided && + point.maximumValue != ORKDoubleInvalidValue && + ((self.maximumValue == ORKDoubleInvalidValue) || (point.maximumValue > self.maximumValue))) { + self.maximumValue = point.maximumValue; + } + } + } + } + + if (self.minimumValue == ORKDoubleInvalidValue) { + self.minimumValue = 0; + } + if (self.maximumValue == ORKDoubleInvalidValue) { + self.maximumValue = 0; + } +} + +#pragma mark - Layout & Drawing + +- (void)updatePointLayersForPlotIndex:(NSInteger)plotIndex { + if (plotIndex < self.dataPoints.count) { + UIColor *color = [self colorForPlotIndex:plotIndex]; + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + ORKValueRange *dataPoint = self.dataPoints[plotIndex][pointIndex]; + if (!dataPoint.isUnset) { + BOOL drawPointIndicator = [self shouldDrawPointIndicatorForPointWithIndex:pointIndex inPlotWithIndex:plotIndex]; + CALayer *pointLayer = graphPointLayerWithColor(color, drawPointIndicator); + [self.plotView.layer addSublayer:pointLayer]; + [_pointLayers[plotIndex] addObject:pointLayer]; + + if (!dataPoint.isEmptyRange) { + pointLayer = graphPointLayerWithColor(color, drawPointIndicator); + [self.plotView.layer addSublayer:pointLayer]; + [_pointLayers[plotIndex] addObject:pointLayer]; + } + } + } + } +} + +- (void)updatePlotColorsForPlotIndex:(NSInteger)plotIndex { + [super updatePlotColorsForPlotIndex:plotIndex]; + UIColor *color = [self colorForPlotIndex:plotIndex]; + for (NSUInteger pointIndex = 0; pointIndex < _pointLayers[plotIndex].count; pointIndex++) { + CALayer *pointLayer = _pointLayers[plotIndex][pointIndex]; + if (pointLayer.contents) { + pointLayer.contents = (__bridge id)(graphPointLayerImageWithColor(color).CGImage); + } + } + } + +- (void)updatePointLayers { + for (NSInteger plotIndex = 0; plotIndex < _pointLayers.count; plotIndex++) { + [_pointLayers[plotIndex] makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + } + [_pointLayers removeAllObjects]; + + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + NSMutableArray *currentPlotPointLayers = [NSMutableArray new]; + [_pointLayers addObject:currentPlotPointLayers]; + [self updatePointLayersForPlotIndex:plotIndex]; + } + } + +- (void)layoutSubviews { + [super layoutSubviews]; + [self layoutPointLayers]; +} + +- (void)layoutPointLayers { + NSInteger numberOfPlots = [self numberOfPlots]; + + if (self.yAxisPoints.count != numberOfPlots) { + // avoid layout if points have not been normalized yet + return; + } + + for (NSInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + [self layoutPointLayersForPlotIndex:plotIndex]; + } +} + +- (void)layoutPointLayersForPlotIndex:(NSInteger)plotIndex { + if (plotIndex < self.dataPoints.count) { + NSUInteger pointLayerIndex = 0; + for (NSUInteger pointIndex = 0; pointIndex < self.dataPoints[plotIndex].count; pointIndex++) { + ORKValueRange *dataPointValue = self.dataPoints[plotIndex][pointIndex]; + if (!dataPointValue.isUnset) { + CGFloat positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width); + positionOnXAxis += [self xOffsetForPlotIndex:plotIndex]; + ORKValueRange *yAxisValueRange = self.yAxisPoints[plotIndex][pointIndex]; + CALayer *pointLayer = _pointLayers[plotIndex][pointLayerIndex]; + pointLayer.position = CGPointMake(positionOnXAxis, yAxisValueRange.minimumValue); + pointLayerIndex++; + + if (!yAxisValueRange.isEmptyRange) { + pointLayer = _pointLayers[plotIndex][pointLayerIndex]; + pointLayer.position = CGPointMake(positionOnXAxis, yAxisValueRange.maximumValue); + pointLayerIndex++; + } + } + } + } +} + +#pragma mark - Scrubbing + +- (double)scrubbingValueForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + return self.dataPoints[plotIndex][pointIndex].maximumValue; +} + +- (double)scrubbingYAxisPointForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex { + return self.yAxisPoints[plotIndex][pointIndex].maximumValue; +} + +#pragma mark - Animation + +- (void)prepareAnimationsForPlotIndex:(NSInteger)plotIndex { + [super prepareAnimationsForPlotIndex:plotIndex]; + [_pointLayers[plotIndex] makeObjectsPerformSelector:@selector(removeAllAnimations)]; + for (CAShapeLayer *pointLayer in _pointLayers[plotIndex]) { + pointLayer.opacity = 0; + } +} + +- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration plotIndex:(NSInteger)plotIndex { + [super animateLayersSequentiallyWithDuration:duration plotIndex:plotIndex]; + NSUInteger numberOfPoints = _pointLayers[plotIndex].count; + if (numberOfPoints > 0) { + CGFloat pointFadeDuration = duration / numberOfPoints; + CGFloat pointDelay = 0.0; + for (NSUInteger pointIndex = 0; pointIndex < numberOfPoints; pointIndex++) { + CALayer *layer = _pointLayers[plotIndex][pointIndex]; + [self animateLayer:layer keyPath:@"opacity" duration:pointFadeDuration startDelay:pointDelay]; + pointDelay += pointFadeDuration; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView_Internal.h new file mode 100755 index 0000000..2d011c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKGraphChartView_Internal.h @@ -0,0 +1,187 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + Copyright (c) 2016, Ricardo Sánchez-Sáez. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKGraphChartView.h" +#import "ORKChartTypes.h" +#import "ORKHelpers_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +#if TARGET_INTERFACE_BUILDER + +@interface ORKIBGraphChartViewDataSource : NSObject + +@property (nonatomic, strong, nullable) NSArray *plotPoints; + +@end + + +@interface ORKIBValueRangeGraphChartViewDataSource : ORKIBGraphChartViewDataSource + +@end + +#endif + + +@class ORKXAxisView; + +typedef NS_ENUM(NSUInteger, ORKGraphAnimationType) { + ORkGraphAnimationTypeNone, + ORKGraphAnimationTypeFade, + ORKGraphAnimationTypeGrow, + ORKGraphAnimationTypePop +}; + +extern const CGFloat ORKGraphChartViewLeftPadding; +extern const CGFloat ORKGraphChartViewPointAndLineWidth; +extern const CGFloat ORKGraphChartViewScrubberMoveAnimationDuration; +extern const CGFloat ORKGraphChartViewAxisTickLength; +extern const CGFloat ORKGraphChartViewYAxisTickPadding; + +ORK_INLINE CGFloat scalePixelAdjustment() { + return (1.0 / [UIScreen mainScreen].scale); +} + +ORK_INLINE CAShapeLayer *graphLineLayer() { + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + lineLayer.fillColor = [UIColor clearColor].CGColor; + lineLayer.lineJoin = kCALineJoinRound; + lineLayer.lineCap = kCALineCapRound; + lineLayer.opacity = 1.0; + return lineLayer; +} + +ORK_INLINE CGFloat xAxisPoint(NSInteger pointIndex, NSInteger numberOfXAxisPoints, CGFloat canvasWidth) { + return floor((canvasWidth / MAX(1, numberOfXAxisPoints - 1)) * pointIndex); +} + +ORK_INLINE CGFloat xOffsetForPlotIndex(NSInteger plotIndex, NSInteger numberOfPlots, CGFloat plotWidth) { + CGFloat offset = 0; + if (numberOfPlots % 2 == 0) { + // Even + offset = (plotIndex - numberOfPlots / 2 + 0.5) * plotWidth; + } else { + // Odd + offset = (plotIndex - numberOfPlots / 2) * plotWidth; + } + return offset; +} + + +@interface ORKGraphChartView () + +@property (nonatomic) NSMutableArray *> *> *lineLayers; + +@property (nonatomic) NSInteger numberOfXAxisPoints; + +@property (nonatomic) NSMutableArray *> *> *dataPoints; // Actual data + +@property (nonatomic) NSMutableArray *> *> *yAxisPoints; // Normalized for the plot view height + +@property (nonatomic) UIView *plotView; // Holds the plots + +@property (nonatomic) UIView *scrubberLine; + +@property (nonatomic) BOOL scrubberAccessoryViewsHidden; + +@property (nonatomic) BOOL hasDataPoints; + +@property (nonatomic) double minimumValue; + +@property (nonatomic) double maximumValue; + +- (void)sharedInit; + +- (void)calculateMinAndMaxValues; + +- (NSMutableArray *> *)normalizedCanvasDataPointsForPlotIndex:(NSInteger)plotIndex canvasHeight:(CGFloat)viewHeight; + +- (NSInteger)numberOfPlots; + +- (NSInteger)numberOfValidValuesForPlotIndex:(NSInteger)plotIndex; + +- (NSInteger)scrubbingPlotIndex; + +- (double)scrubbingValueForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex; + +- (double)scrubbingYAxisPointForPlotIndex:(NSInteger)plotIndex pointIndex:(NSInteger)pointIndex; + +- (double)scrubbingLabelValueForCanvasXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (NSInteger)pointIndexForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (void)updateScrubberViewForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (void)updateScrubberLineAccessories:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (CGFloat)snappedXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (BOOL)isXPositionSnapped:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex; + +- (void)updatePlotColors; + +- (void)updateLineLayers; + +- (void)layoutLineLayers; + +- (UIColor *)colorForPlotIndex:(NSInteger)plotIndex subpointIndex:(NSInteger)subpointIndex totalSubpoints:(NSInteger)totalSubpoints; + +- (UIColor *)colorForPlotIndex:(NSInteger)plotIndex; + +- (void)prepareAnimationsForPlotIndex:(NSInteger)plotIndex; + +- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration plotIndex:(NSInteger)plotIndex; + +- (void)animateLayer:(CALayer *)layer + keyPath:(NSString *)keyPath + duration:(CGFloat)duration + startDelay:(CGFloat)startDelay + timingFunction:(CAMediaTimingFunction *)timingFunction; + +@end + + +// Abstract base class for ORKDiscreteGraphChartView and ORKLineGraphChartView +@interface ORKValueRangeGraphChartView () + +@property (nonatomic) NSMutableArray *> *dataPoints; // Actual data + +@property (nonatomic) NSMutableArray *> *yAxisPoints; // Normalized for the plot view height + +- (void)updatePointLayers; + +- (void)layoutPointLayers; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.h new file mode 100755 index 0000000..9c05c1e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKLineGraphChartView` class presents the data provided by an object conforming to the + `ORKValueRangeGraphChartViewDataSource` protocol as a line graph. + + The primary plot is colored by the `tintColor`, and any additional plots are colored using the + `referenceLineColor` property. + */ +ORK_CLASS_AVAILABLE +@interface ORKLineGraphChartView : ORKValueRangeGraphChartView + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.m new file mode 100755 index 0000000..575064a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKLineGraphChartView.m @@ -0,0 +1,367 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLineGraphChartView.h" + +#import "ORKChartTypes.h" +#import "ORKGraphChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +#if TARGET_INTERFACE_BUILDER + +@interface ORKIBLineGraphChartViewDataSource : ORKIBValueRangeGraphChartViewDataSource + ++ (instancetype)sharedInstance; + +@end + + +@implementation ORKIBLineGraphChartViewDataSource + ++ (instancetype)sharedInstance { + static id sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self class] new]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.plotPoints = @[ + @[ + [[ORKValueRange alloc] initWithValue:10], + [[ORKValueRange alloc] initWithValue:20], + [[ORKValueRange alloc] initWithValue:25], + [[ORKValueRange alloc] init], + [[ORKValueRange alloc] initWithValue:30], + [[ORKValueRange alloc] initWithValue:40] + ], + @[ + [[ORKValueRange alloc] initWithValue:2], + [[ORKValueRange alloc] initWithValue:4], + [[ORKValueRange alloc] initWithValue:8], + [[ORKValueRange alloc] initWithValue:16], + [[ORKValueRange alloc] initWithValue:32], + [[ORKValueRange alloc] initWithValue:64] + ] + ]; + } + return self; +} + +- (CGFloat)minimumValueForGraphChartView:(ORKGraphChartView *)graphChartView { + return 0; +} + +- (CGFloat)maximumValueForGraphChartView:(ORKGraphChartView *)graphChartView { + return 70; +} + +@end + +#endif + + +const CGFloat FillColorAlpha = 0.4; + +@implementation ORKLineGraphChartView { + NSMutableDictionary *_fillLayers; +} + +#pragma mark - Init + +- (void)sharedInit { + [super sharedInit]; + _fillLayers = [NSMutableDictionary new]; +} + +- (BOOL)shouldDrawLinesForPlotIndex:(NSInteger)plotIndex { + return [self numberOfValidValuesForPlotIndex:plotIndex] > 1; +} + +#pragma mark - Drawing + +- (UIColor *)fillColorForPlotIndex:(NSInteger)plotIndex { + UIColor *color = nil; + if ([self.dataSource respondsToSelector:@selector(graphChartView:fillColorForPlotIndex:)]) { + color = [self.dataSource graphChartView:self fillColorForPlotIndex:plotIndex]; + } else { + color = [[self colorForPlotIndex:plotIndex] colorWithAlphaComponent:FillColorAlpha]; + } + return color; +} + +- (void)updatePlotColors { + [super updatePlotColors]; + NSInteger numberOfPlots = [self numberOfPlots]; + for (NSUInteger plotIndex = 0; plotIndex < numberOfPlots; plotIndex++) { + CAShapeLayer *fillLayer = _fillLayers[@(plotIndex)]; + fillLayer.fillColor = [self fillColorForPlotIndex:plotIndex].CGColor; + } +} + +- (void)updateLineLayers { + [_fillLayers.allValues makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + [_fillLayers removeAllObjects]; + [super updateLineLayers]; +} + +- (void)updateLineLayersForPlotIndex:(NSInteger)plotIndex { + // Fill + CAShapeLayer *fillLayer = [CAShapeLayer layer]; + fillLayer.fillColor = [self fillColorForPlotIndex:plotIndex].CGColor; + + [self.plotView.layer addSublayer:fillLayer]; + _fillLayers[@(plotIndex)] = fillLayer; + + // Lines + BOOL previousPointExists = NO; + BOOL emptyDataPresent = NO; + NSUInteger pointCount = self.dataPoints[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < pointCount; pointIndex++) { + [self.lineLayers[plotIndex] addObject:[NSMutableArray new]]; + if (self.dataPoints[plotIndex][pointIndex].isUnset) { + emptyDataPresent = YES; + continue; + } + + if (!previousPointExists) { + previousPointExists = YES; + emptyDataPresent = NO; + continue; + } + + CAShapeLayer *lineLayer = graphLineLayer(); + lineLayer.strokeColor = [self colorForPlotIndex:plotIndex].CGColor; + lineLayer.lineWidth = 2.0; + + if (emptyDataPresent) { + lineLayer.lineDashPattern = @[@12, @6]; + emptyDataPresent = NO; + } + + [self.plotView.layer addSublayer:lineLayer]; + [self.lineLayers[plotIndex][pointIndex - 1] addObject:lineLayer]; + } +} + +- (void)layoutLineLayersForPlotIndex:(NSInteger)plotIndex { + CAShapeLayer *fillLayer = _fillLayers[@(plotIndex)]; + + if (fillLayer == nil) { + // Skip for a nil fillLayer + return; + } + + UIBezierPath *fillPath = [UIBezierPath bezierPath]; + CGFloat positionOnXAxis = ORKCGFloatInvalidValue; + ORKValueRange *positionOnYAxis = nil; + BOOL previousPointExists = NO; + NSUInteger numberOfPoints = self.lineLayers[plotIndex].count; + for (NSUInteger pointIndex = 0; pointIndex < numberOfPoints; pointIndex++) { + if (self.dataPoints[plotIndex][pointIndex].isUnset) { + continue; + } + UIBezierPath *linePath = [UIBezierPath bezierPath]; + + if (positionOnXAxis != ORKCGFloatInvalidValue) { + [linePath moveToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)]; + if ([fillPath isEmpty]) { + // Substract scalePixelAdjustment() to the first horizontal position of the fillPath so if fully covers the start of the x axis + [fillPath moveToPoint:CGPointMake(positionOnXAxis - scalePixelAdjustment(), + CGRectGetHeight(self.plotView.frame) + scalePixelAdjustment())]; + [fillPath addLineToPoint:CGPointMake(positionOnXAxis - scalePixelAdjustment(), + positionOnYAxis.minimumValue)]; + } else { + [fillPath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)]; + } + } + + positionOnXAxis = xAxisPoint(pointIndex, self.numberOfXAxisPoints, self.plotView.bounds.size.width); + positionOnYAxis = self.yAxisPoints[plotIndex][pointIndex]; + + if (!previousPointExists) { + if (positionOnXAxis != ORKCGFloatInvalidValue) { + previousPointExists = YES; + } + continue; + } + + [linePath addLineToPoint:CGPointMake(positionOnXAxis, positionOnYAxis.minimumValue)]; + // Add scalePixelAdjustment() to the last vertical position of the fillPath so if fully covers the end of the x axis + [fillPath addLineToPoint:CGPointMake(positionOnXAxis + ( (pointIndex == (numberOfPoints - 1)) ? scalePixelAdjustment() : 0 ), + positionOnYAxis.minimumValue)]; + + CAShapeLayer *lineLayer = self.lineLayers[plotIndex][pointIndex - 1][0]; + lineLayer.path = linePath.CGPath; + } + + [fillPath addLineToPoint:CGPointMake(positionOnXAxis + scalePixelAdjustment(), + CGRectGetHeight(self.plotView.frame) + scalePixelAdjustment())]; + + fillLayer.path = fillPath.CGPath; +} + +#pragma mark - Graph Calculations + +- (double)scrubbingLabelValueForCanvasXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + double value = [super scrubbingLabelValueForCanvasXPosition:xPosition plotIndex:plotIndex]; + + if (value == ORKDoubleInvalidValue) { + CGFloat viewWidth = self.plotView.bounds.size.width; + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + NSInteger pointIndex = 0; + for (pointIndex = 0; pointIndex < (numberOfXAxisPoints - 1); pointIndex++) { + CGFloat xAxisPointValue = xAxisPoint(pointIndex, numberOfXAxisPoints, viewWidth); + if (xAxisPointValue > xPosition) { + break; + } + } + + NSInteger previousValidIndex = [self previousValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex]; + NSInteger nextValidIndex = [self nextValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex]; + + CGFloat x1 = xAxisPoint(previousValidIndex, numberOfXAxisPoints, viewWidth); + CGFloat x2 = xAxisPoint(nextValidIndex, numberOfXAxisPoints, viewWidth); + + double y1 = self.dataPoints[plotIndex][previousValidIndex].minimumValue; + double y2 = self.dataPoints[plotIndex][nextValidIndex].minimumValue; + + if (y1 == ORKDoubleInvalidValue || y2 == ORKDoubleInvalidValue) { + return ORKDoubleInvalidValue; + } + + double slope = (y2 - y1)/(x2 - x1); + + // (y2 - y3)/(x2 - x3) = m + value = y2 - (slope * (x2 - xPosition)); + } + return value; +} + +- (double)canvasYPositionForXPosition:(CGFloat)xPosition plotIndex:(NSInteger)plotIndex { + NSInteger pointIndex = [self pointIndexForXPosition:xPosition plotIndex:plotIndex]; + NSInteger nextValidIndex = [self nextValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex]; + NSInteger previousValidIndex = [self previousValidPointIndexForPointIndex:pointIndex plotIndex:plotIndex]; + + double canvasYPosition = 0; + if (nextValidIndex == previousValidIndex) { + canvasYPosition = self.yAxisPoints[plotIndex][previousValidIndex].minimumValue; + } else { + CGFloat viewWidth = self.plotView.bounds.size.width; + NSInteger numberOfXAxisPoints = self.numberOfXAxisPoints; + + CGFloat x1 = xAxisPoint(previousValidIndex, numberOfXAxisPoints, viewWidth); + CGFloat x2 = xAxisPoint(nextValidIndex, numberOfXAxisPoints, viewWidth); + + double y1 = self.yAxisPoints[plotIndex][previousValidIndex].minimumValue; + double y2 = self.yAxisPoints[plotIndex][nextValidIndex].minimumValue; + + double slope = (y2 - y1)/(x2 - x1); + + // (y2 - y3)/(x2 - x3) = m + canvasYPosition = y2 - (slope * (x2 - xPosition)); + } + return canvasYPosition; +} + +- (NSInteger)nextValidPointIndexForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + NSUInteger validPosition = pointIndex; + + NSUInteger pointCountMinusOne = (self.dataPoints[plotIndex].count - 1); + while (validPosition < pointCountMinusOne) { + if (self.dataPoints[plotIndex][validPosition].minimumValue != ORKDoubleInvalidValue) { + break; + } + validPosition++; + } + + return validPosition; +} + +- (NSInteger)previousValidPointIndexForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex { + NSInteger validPosition = pointIndex - 1; + if (validPosition < 0) { + validPosition = 0; + } + while (validPosition > 0) { + if (self.dataPoints[plotIndex][validPosition].minimumValue != ORKDoubleInvalidValue) { + break; + } + validPosition--; + } + return validPosition; +} + +#pragma mark - Animations + +- (void)prepareAnimationsForPlotIndex:(NSInteger)plotIndex { + [super prepareAnimationsForPlotIndex:plotIndex]; + // animate all fill layers at once at the beginning + if (plotIndex == 0) { + [_fillLayers enumerateKeysAndObjectsUsingBlock:^(id key, CAShapeLayer *fillLayer, BOOL *stop) { + [fillLayer removeAllAnimations]; + fillLayer.opacity = 0; + }]; + } +} + +- (void)animateLayersSequentiallyWithDuration:(NSTimeInterval)duration plotIndex:(NSInteger)plotIndex { + [super animateLayersSequentiallyWithDuration:duration plotIndex:plotIndex]; + // animate all fill layers at once at the beginning + if (plotIndex == 0) { + [_fillLayers enumerateKeysAndObjectsUsingBlock:^(id key, CAShapeLayer *layer, BOOL *stop) { + [self animateLayer:layer + keyPath:@"opacity" + duration:duration * (1.0 / 3.0) + startDelay:duration * (2.0 / 3.0) + timingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]]; + }]; + } +} + +#pragma mark - Interface Builder designable + +- (void)prepareForInterfaceBuilder { + [super prepareForInterfaceBuilder]; +#if TARGET_INTERFACE_BUILDER + self.dataSource = [ORKIBLineGraphChartViewDataSource sharedInstance]; +#endif +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.h new file mode 100755 index 0000000..7440af0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKPieChartLegendCell : UICollectionViewCell + +@property (nonatomic, strong) UILabel *titleLabel; + +@property (nonatomic, strong) UIView *dotView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.m new file mode 100755 index 0000000..3131de6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCell.m @@ -0,0 +1,133 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPieChartLegendCell.h" + +#import "ORKSkin.h" + + +const CGFloat DotViewSize = 10.0; +const CGFloat DotToLabelPadding = 6.0; + +@implementation ORKPieChartLegendCell + +#pragma mark - Init + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + [self sharedInit]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self sharedInit]; + } + return self; +} + +- (void)sharedInit { + _titleLabel = [UILabel new]; + _titleLabel.textColor = ORKColor(ORKChartDefaultTextColorKey); + _titleLabel.textAlignment = NSTextAlignmentCenter; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + _titleLabel.isAccessibilityElement = NO; + _dotView = [UIView new]; + _dotView.translatesAutoresizingMaskIntoConstraints = NO; + _dotView.layer.cornerRadius = DotViewSize * 0.5; + _dotView.layer.masksToBounds = YES; + [self.contentView addSubview:_titleLabel]; + [self.contentView addSubview:_dotView]; + + [self setUpConstraints]; +} + +#pragma mark - Layout + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _dotView); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_titleLabel]-(>=0)-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_dotView]-(>=0)-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_dotView]-DotToLabelPadding-[_titleLabel]|" + options:(NSLayoutFormatOptions)0 + metrics:@{@"DotToLabelPadding": @(DotToLabelPadding)} + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:0 + multiplier:1.0 + constant:DotViewSize]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_dotView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dotView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_titleLabel + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + return _titleLabel.accessibilityLabel; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.h new file mode 100755 index 0000000..7b3cf9c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +// This class implements a centered collection view layout, +// in which the cells are distributed as equally as possible between rows +// and each row is laid out as compactly as possible within its center +// (rather than spreading to take all available space like in the UICollectionViewFlowLayout) +@interface ORKPieChartLegendCollectionViewLayout : UICollectionViewFlowLayout + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.m new file mode 100755 index 0000000..9943d7a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendCollectionViewLayout.m @@ -0,0 +1,97 @@ +/* + Copyright (c) 2015, James Cox. All rights reserved. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPieChartLegendCollectionViewLayout.h" + +#import "ORKPieChartLegendView.h" + + +@interface ORKPieChartLegendCollectionViewLayout () + +@property (nonatomic, readonly) ORKPieChartLegendView *collectionView; + +@end + + +@implementation ORKPieChartLegendCollectionViewLayout + +@dynamic collectionView; + +- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { + NSArray *attributesArray = [super layoutAttributesForElementsInRect:rect]; + for (UICollectionViewLayoutAttributes *attributes in attributesArray) { + attributes.frame = [self layoutAttributesForItemAtIndexPath:attributes.indexPath].frame; + } + return attributesArray; +} + +- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { + UICollectionViewLayoutAttributes *currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; + NSInteger numberOfItems = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section]; + + // Spread items evenly between rows + NSInteger numberOfRows = ceil(self.collectionView.totalCellWidth / self.collectionView.bounds.size.width); + NSInteger numberOfItemsPerRow = ceil((float)numberOfItems / numberOfRows); + + // Calculate the row in which the current item sits + NSInteger currentItemIndex = indexPath.row; + NSInteger currentItemRow = currentItemIndex / numberOfItemsPerRow; + + // Adjust the Y position of the current item to the corresponding row + CGRect currentItemFrame = currentItemAttributes.frame; + currentItemFrame.origin.y = currentItemRow * (currentItemFrame.size.height + self.minimumLineSpacing); // Assume all items have the same height + + // Calculate the X position of the current item according to the width of preceding items in the same row + CGFloat xPosition = 0; + NSInteger currentRowItemIndex = currentItemRow * numberOfItemsPerRow; + NSInteger currentRowLastItemIndex = MIN(currentRowItemIndex + numberOfItemsPerRow - 1, numberOfItems - 1); + while (currentRowItemIndex < currentItemIndex) { + xPosition += self.collectionView.cellSizes[currentRowItemIndex].CGSizeValue.width + self.minimumInteritemSpacing; + currentRowItemIndex++; + } + currentItemFrame.origin.x = xPosition; + + // Adjust the frame according to the trailing padding of the current rown so all the items gather around the center + while (currentRowItemIndex < currentRowLastItemIndex) { + xPosition += self.collectionView.cellSizes[currentRowItemIndex].CGSizeValue.width + self.minimumInteritemSpacing; + currentRowItemIndex++; + } + CGFloat currentRowLastItemMaxXPosition = xPosition + self.collectionView.cellSizes[currentRowItemIndex].CGSizeValue.width; + CGFloat currentRowTrailingPadding = self.collectionView.bounds.size.width - currentRowLastItemMaxXPosition; + currentItemFrame = CGRectOffset(currentItemFrame, currentRowTrailingPadding * 0.5, 0); + + currentItemAttributes.frame = currentItemFrame; + + return currentItemAttributes; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.h new file mode 100755 index 0000000..76775c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPieChartView; + +@interface ORKPieChartLegendView : UICollectionView + +@property (nonatomic) UIFont *labelFont; +@property (nonatomic, readonly) NSMutableArray *cellSizes; +@property (nonatomic, readonly) CGFloat totalCellWidth; + +- (instancetype)initWithFrame:(CGRect)frame + collectionViewLayout:(UICollectionViewLayout *)collectionViewLayout NS_UNAVAILABLE; + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView NS_DESIGNATED_INITIALIZER; + +- (void)animateWithDuration:(NSTimeInterval)animationDuration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.m new file mode 100755 index 0000000..c9bffd5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartLegendView.m @@ -0,0 +1,195 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPieChartLegendView.h" + +#import "ORKPieChartLegendCell.h" +#import "ORKPieChartLegendCollectionViewLayout.h" +#import "ORKPieChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat MinimumInteritemSpacing = 10.0; +static const CGFloat MinimumLineSpacing = 6.0; +static NSString *const CellIdentifier = @"ORKPieChartLegendCell"; + +@implementation ORKPieChartLegendView { + __weak ORKPieChartView *_parentPieChartView; + ORKPieChartLegendCell *_sizingCell; + CGFloat _sumOfValues; +} + +- (instancetype)initWithFrame:(CGRect)frame + collectionViewLayout:(UICollectionViewLayout *)collectionViewLayout { + ORKThrowMethodUnavailableException(); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView { + ORKPieChartLegendCollectionViewLayout *pieChartLegendCollectionViewLayout = [[ORKPieChartLegendCollectionViewLayout alloc] init]; + pieChartLegendCollectionViewLayout.minimumInteritemSpacing = MinimumInteritemSpacing; + pieChartLegendCollectionViewLayout.minimumLineSpacing = MinimumLineSpacing; + pieChartLegendCollectionViewLayout.estimatedItemSize = CGSizeMake(100.0, 30.0); + self = [super initWithFrame:CGRectZero collectionViewLayout:pieChartLegendCollectionViewLayout]; + if (self) { + [self registerClass:[ORKPieChartLegendCell class] forCellWithReuseIdentifier:CellIdentifier]; + _sizingCell = [[ORKPieChartLegendCell alloc] initWithFrame:CGRectZero]; + + _parentPieChartView = parentPieChartView; + _sumOfValues = 0; + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger index = 0; index < numberOfSegments; index++) { + // Numerical value + CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:index]; + _sumOfValues += value; + } + [self cacheCellSizes]; + + self.backgroundColor = [UIColor clearColor]; + self.translatesAutoresizingMaskIntoConstraints = NO; + self.dataSource = self; + self.delegate = self; + + [self setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + [self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + + } + return self; +} + +- (NSArray *)_validIndexesWithReportedSegmentCount:(NSInteger)reportedSegmentCount { + NSMutableArray *validIndexes = [NSMutableArray new]; + for (NSInteger currentIndex = 0; currentIndex < reportedSegmentCount; currentIndex++) { + NSString *title = [_parentPieChartView.dataSource pieChartView:_parentPieChartView titleForSegmentAtIndex:currentIndex]; + if (title) { + [validIndexes addObject:@(currentIndex)]; + } + } + return [validIndexes copy]; +} + +- (void)cacheCellSizes { + _cellSizes = [NSMutableArray new]; + _totalCellWidth = 0; + NSArray *validIndexes = [self _validIndexesWithReportedSegmentCount:[_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]]; + for (NSNumber *indexNumber in validIndexes) { + NSInteger index = indexNumber.integerValue; + _sizingCell.titleLabel.text = [_parentPieChartView.dataSource pieChartView:_parentPieChartView titleForSegmentAtIndex:index]; + CGSize size = [_sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; + [_cellSizes addObject:[NSValue valueWithCGSize:size]]; + _totalCellWidth += size.width; + if (index != validIndexes.count - 1) { + _totalCellWidth += MinimumInteritemSpacing; + } + } +} + +- (void)setLabelFont:(UIFont *)labelFont { + _labelFont = labelFont; + _sizingCell.titleLabel.font = _labelFont; + [self cacheCellSizes]; + [self reloadData]; + [self invalidateIntrinsicContentSize]; +} + +- (CGSize)intrinsicContentSize { + CGSize size = CGSizeMake(UIViewNoIntrinsicMetric, [self.collectionViewLayout collectionViewContentSize].height); + return size; +} + +- (void)animateWithDuration:(NSTimeInterval)animationDuration { + NSArray *sortedCells = [self.visibleCells sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewCell *cell1, UICollectionViewCell *cell2) { + return cell1.tag > cell2.tag; + }]; + NSUInteger cellCount = sortedCells.count; + NSTimeInterval interAnimationDelay = 0.05; + NSTimeInterval singleAnimationDuration = animationDuration - (interAnimationDelay * (cellCount - 1)); + if (singleAnimationDuration < 0) { + interAnimationDelay = 0; + singleAnimationDuration = animationDuration; + } + for (NSUInteger index = 0; index < cellCount; index++) { + UICollectionViewCell *cell = sortedCells[index]; + cell.transform = CGAffineTransformMakeScale(0, 0); + [UIView animateWithDuration:singleAnimationDuration + delay:interAnimationDelay * index + options:(UIViewAnimationOptions)0 + animations:^{ + cell.transform = CGAffineTransformIdentity; + } completion:nil]; + } +} + +#pragma mark - UICollectionViewDataSource / UICollectionViewDelegate + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + NSAssert(indexPath.section == 0, @"Section cannot be non-zero on an ORKPieChartView."); + + NSArray *validIndexes = [self _validIndexesWithReportedSegmentCount:[_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]]; + + NSAssert(validIndexes.count > indexPath.item, @"A valid index path has not been found for item: %ld", (long)indexPath.item); + + NSInteger correctedIndex = validIndexes[indexPath.item].integerValue; + NSString *title = [_parentPieChartView.dataSource pieChartView:_parentPieChartView titleForSegmentAtIndex:correctedIndex]; + CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:correctedIndex]; + ORKPieChartLegendCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath]; + cell.tag = correctedIndex; + cell.titleLabel.text = title; + cell.titleLabel.font = _labelFont; + cell.dotView.backgroundColor = [_parentPieChartView colorForSegmentAtIndex:correctedIndex]; + + cell.accessibilityLabel = title; + cell.accessibilityValue = [NSString stringWithFormat:@"%0.0f%%", (value < .01) ? 1 : value / _sumOfValues * 100]; + return cell; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + NSInteger numberOfReportedCells = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + return (NSInteger)[self _validIndexesWithReportedSegmentCount:numberOfReportedCells].count; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout + sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + CGSize size = _cellSizes[indexPath.row].CGSizeValue; + return size; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.h new file mode 100755 index 0000000..720a9d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPieChartView; + +@interface ORKPieChartPieView : UIView + +@property (nonatomic) UIFont *percentageLabelFont; + +@property (nonatomic) CGFloat radiusScaleFactor; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView NS_DESIGNATED_INITIALIZER; + +- (CGFloat)normalizeValues; + +- (void)updatePieLayers; + +- (void)updatePercentageLabels; + +- (void)updateColors; + +- (void)animateWithDuration:(NSTimeInterval)animationDuration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.m new file mode 100755 index 0000000..89e479e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartPieView.m @@ -0,0 +1,406 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPieChartPieView.h" + +#import "ORKPieChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat OriginAngle = -M_PI_2; +static const CGFloat PercentageLabelOffset = 10.0; +static const CGFloat InterAnimationDelay = 0.05; + +@implementation ORKPieChartPieView { + __weak ORKPieChartView *_parentPieChartView; + + CAShapeLayer *_circleLayer; + NSMutableArray *_normalizedValues; + NSMutableArray *_segmentLayers; + NSMutableArray *_pieSections; +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView { + self = [super initWithFrame:CGRectZero]; + if (self) { + _parentPieChartView = parentPieChartView; + self.translatesAutoresizingMaskIntoConstraints = NO; + + _circleLayer = [CAShapeLayer layer]; + _circleLayer.fillColor = [UIColor clearColor].CGColor; + _circleLayer.strokeColor = [UIColor colorWithWhite:0.96 alpha:1.000].CGColor; + [self.layer addSublayer:_circleLayer]; + + _normalizedValues = [NSMutableArray new]; + _segmentLayers = [NSMutableArray new]; + _pieSections = [NSMutableArray new]; + _radiusScaleFactor = 0.5; + } + return self; +} + +- (void)setPercentageLabelFont:(UIFont *)percentageLabelFont { + _percentageLabelFont = percentageLabelFont; + for (ORKPieChartSection *pieSection in _pieSections) { + pieSection.label.font = percentageLabelFont; + [pieSection.label sizeToFit]; + } + [self setNeedsLayout]; +} + +#pragma mark - Data Normalization + +- (CGFloat)normalizeValues { + [_normalizedValues removeAllObjects]; + + CGFloat sumOfValues = 0; + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + CGFloat value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:idx]; + sumOfValues += value; + } + + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + CGFloat value = 0; + if (sumOfValues != 0) { + value = [_parentPieChartView.dataSource pieChartView:_parentPieChartView valueForSegmentAtIndex:idx] / sumOfValues; + } + [_normalizedValues addObject:@(value)]; + } + return sumOfValues; +} + +#pragma mark - Layout and drawing + +- (void)layoutSubviews { + [super layoutSubviews]; + CGRect bounds = self.bounds; + CGFloat startAngle = OriginAngle; + CGFloat endAngle = startAngle + (2 * M_PI); + CGFloat outerRadius = bounds.size.height * _radiusScaleFactor; + CGFloat labelHeight = [@"100%" boundingRectWithSize:CGRectInfinite.size + options:(NSStringDrawingOptions)0 + attributes:@{NSFontAttributeName : _percentageLabelFont} + context:nil].size.height; + CGFloat innerRadius = outerRadius - (labelHeight + PercentageLabelOffset); + CGFloat targetRadius = _parentPieChartView.showsPercentageLabels ? innerRadius : outerRadius; + CGFloat lineWidth = MIN(_parentPieChartView.lineWidth, targetRadius); + _circleLayer.lineWidth = lineWidth; + CGFloat drawingRadius = targetRadius - (lineWidth * 0.5); + + if (!_parentPieChartView.drawsClockwise) { + startAngle = 3 * M_PI_2; + endAngle = -M_PI_2; + } + UIBezierPath *circularArcBezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetMidX(bounds), + CGRectGetMidY(bounds)) + radius:drawingRadius + startAngle:startAngle + endAngle:endAngle + clockwise:_parentPieChartView.drawsClockwise]; + + _circleLayer.path = circularArcBezierPath.CGPath; + + [self layoutPieChartLayers]; + if (_parentPieChartView.showsPercentageLabels) { + [self layoutPercentageLabelsWithRadius:innerRadius]; + } +} + +- (void)updatePieLayers { + [_segmentLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + [_segmentLayers removeAllObjects]; + + CGFloat cumulativeValue = 0; + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + + CAShapeLayer *segmentLayer = [CAShapeLayer layer]; + segmentLayer.fillColor = [[UIColor clearColor] CGColor]; + segmentLayer.frame = _circleLayer.bounds; + segmentLayer.path = _circleLayer.path; + segmentLayer.lineWidth = _circleLayer.lineWidth; + segmentLayer.strokeColor = [_parentPieChartView colorForSegmentAtIndex:idx].CGColor; + CGFloat value = _normalizedValues[idx].floatValue; + + segmentLayer.strokeStart = cumulativeValue; + [_circleLayer addSublayer:segmentLayer]; + [_segmentLayers addObject:segmentLayer]; + segmentLayer.strokeEnd = cumulativeValue + value; + + cumulativeValue += value; + } +} + +- (void)updatePercentageLabels { + for (ORKPieChartSection *pieSection in _pieSections) { + [pieSection.label removeFromSuperview]; + } + [_pieSections removeAllObjects]; + + if (_parentPieChartView.showsPercentageLabels) { + CGFloat cumulativeValue = 0; + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + CGFloat value = _normalizedValues[idx].floatValue; + + // Create a label + UILabel *label = [UILabel new]; + label.text = [NSString stringWithFormat:@"%0.0f%%", value * 100]; + label.font = _percentageLabelFont; + label.textColor = [_parentPieChartView colorForSegmentAtIndex:idx]; + [label sizeToFit]; + + // Only if there are no legends + label.isAccessibilityElement = ![_parentPieChartView.dataSource respondsToSelector:@selector(pieChartView:titleForSegmentAtIndex:)]; + + // Calculate the angle to the centre of this segment in radians + CGFloat angle = 0; + if (_parentPieChartView.drawsClockwise) { + angle = (value / 2 + cumulativeValue) * M_PI * 2; + } else { + angle = (value / 2 + cumulativeValue) * - M_PI * 2; + } + + cumulativeValue += value; + ORKPieChartSection *pieSection = [[ORKPieChartSection alloc] initWithLabel:label angle:angle]; + [_pieSections addObject:pieSection]; + [self addSubview:label]; + } + } +} + +- (void)updateColors { + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + if (_segmentLayers.count == numberOfSegments) { + CAShapeLayer *segmentLayer = _segmentLayers[idx]; + segmentLayer.strokeColor = [_parentPieChartView colorForSegmentAtIndex:idx].CGColor; + } + if (_pieSections.count == numberOfSegments) { + ORKPieChartSection *pieSection = _pieSections[idx]; + UILabel *label = pieSection.label; + label.textColor = [_parentPieChartView colorForSegmentAtIndex:idx]; + } + } +} + +- (void)layoutPieChartLayers { + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + CAShapeLayer *segmentLayer = _segmentLayers[idx]; + segmentLayer.frame = _circleLayer.bounds; + segmentLayer.path = _circleLayer.path; + segmentLayer.lineWidth = _circleLayer.lineWidth; + } +} + +- (void)layoutPercentageLabelsWithRadius:(CGFloat)pieRadius { + CGFloat cumulativeValue = 0; + NSInteger numberOfSegments = [_parentPieChartView.dataSource numberOfSegmentsInPieChartView:_parentPieChartView]; + for (NSInteger idx = 0; idx < numberOfSegments; idx++) { + CGFloat value = _normalizedValues[idx].floatValue; + + // Get a label + ORKPieChartSection *pieSection = _pieSections[idx]; + UILabel *label = pieSection.label; + + // Calculate the angle to the centre of this segment in radians + CGFloat angle = (value / 2 + cumulativeValue) * M_PI * 2; + if (!_parentPieChartView.drawsClockwise) { + angle = (value / 2 + cumulativeValue) * - M_PI * 2; + } + + label.center = [self percentageLabel:label calculateCenterForAngle:angle pieRadius:pieRadius]; + cumulativeValue += value; + } + [self adjustIntersectionsOfPercentageLabels:_pieSections pieRadius:pieRadius]; +} + +- (CGPoint)percentageLabel:(UILabel *)label calculateCenterForAngle:(CGFloat)angle pieRadius:(CGFloat)pieRadius { + // Calculate the desired distance from the circle's centre. + const CGFloat offset = 10; + CGFloat length = pieRadius + offset; + + // Calculate x and y coordinates for the point at this distance at the specified angle. + CGSize size = self.bounds.size; + CGFloat cosine = cos(angle + OriginAngle); + CGFloat sine = sin(angle + OriginAngle); + CGFloat x = cosine * length + size.width / 2; + CGFloat y = sine * length + size.height / 2; + + // Offset (x,y) to normalise the spacing from the circle's centre to the intersection with the label's frame rather than its centre. + CGSize labelSize = [label systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; + CGFloat xIn = cosine * labelSize.width / 2; + CGFloat yIn = sine * labelSize.height / 2; + x += xIn; + y += yIn; + + return CGPointMake(x, y); +} + +- (void)adjustIntersectionsOfPercentageLabels:(NSArray *)pieSections pieRadius:(CGFloat)pieRadius { + if (pieSections.count == 0) { + return; + } + // Adjust labels while we have intersections + BOOL intersections = YES; + // We alternate directions in each iteration + BOOL shiftClockwise = NO; + CGFloat rotateDirection = _parentPieChartView.drawsClockwise ? 1 : -1; + // We use totalAngle to prevent from infinite loop + CGFloat totalAngle = 0; + while (intersections) { + intersections = NO; + shiftClockwise = !shiftClockwise; + + if (shiftClockwise) { + for (NSUInteger idx = 0; idx < (pieSections.count - 1); idx++) { + // Prevent from infinite loop + if (!idx) { + totalAngle += 0.01; + if (totalAngle >= 2 * M_PI) { + return; + } + } + ORKPieChartSection *pieLabel = pieSections[idx]; + ORKPieChartSection *nextPieLabel = pieSections[(idx + 1)]; + if ([self shiftSectionLabel:nextPieLabel fromSectionLabel:pieLabel direction:rotateDirection pieRadius:pieRadius]) { + intersections = YES; + } + } + } else { + for (NSInteger idx = pieSections.count - 1; idx > 0; idx--) { + ORKPieChartSection *pieLabel = pieSections[idx]; + ORKPieChartSection *nextPieLabel = pieSections[idx - 1]; + if ([self shiftSectionLabel:nextPieLabel fromSectionLabel:pieLabel direction:-rotateDirection pieRadius:pieRadius]) { + intersections = YES; + } + } + } + + // Adjust space between last and first element + ORKPieChartSection *firstPieLabel = pieSections.firstObject; + ORKPieChartSection *lastPieLabel = pieSections.lastObject; + UILabel *firstLabel = firstPieLabel.label; + UILabel *lastLabel = lastPieLabel.label; + if (CGRectIntersectsRect(lastLabel.frame, firstLabel.frame)) { + CGFloat firstLabelAngle = firstPieLabel.angle; + CGFloat lastLabelAngle = lastPieLabel.angle; + firstLabelAngle += rotateDirection * 0.01; + lastLabelAngle -= rotateDirection * 0.01; + firstPieLabel.angle = firstLabelAngle; + lastPieLabel.angle = lastLabelAngle; + } + } +} + +- (BOOL)shiftSectionLabel:(ORKPieChartSection *)nextPieSection + fromSectionLabel:(ORKPieChartSection *)fromPieSection + direction:(CGFloat)direction + pieRadius:(CGFloat)pieRadius { + CGFloat shiftStep = 0.01; + UILabel *label = fromPieSection.label; + UILabel *nextLabel = nextPieSection.label; + if (CGRectIntersectsRect(label.frame, nextLabel.frame)) { + CGFloat nextLabelAngle = nextPieSection.angle; + nextLabelAngle += direction * shiftStep; + nextPieSection.angle = nextLabelAngle; + nextLabel.center = [self percentageLabel:nextLabel calculateCenterForAngle:nextLabelAngle pieRadius:pieRadius]; + return YES; + } + return NO; +} + +- (void)animateWithDuration:(NSTimeInterval)animationDuration { + NSUInteger numberOfSegmentLayers = _segmentLayers.count; + NSTimeInterval interAnimationDelay = InterAnimationDelay; + NSTimeInterval singleAnimationDuration = animationDuration - (interAnimationDelay * (numberOfSegmentLayers - 1)); + if (singleAnimationDuration < 0) { + interAnimationDelay = 0; + singleAnimationDuration = animationDuration; + } + + CGFloat cumulativeValue = 0; + for (NSInteger idx = 0; idx < numberOfSegmentLayers ; idx++) { + CAShapeLayer *segmentLayer = _segmentLayers[idx]; + CGFloat value = _normalizedValues[idx].floatValue; + CABasicAnimation *strokeAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + strokeAnimation.fromValue = @(segmentLayer.strokeStart); + strokeAnimation.toValue = @(cumulativeValue + value); + strokeAnimation.duration = animationDuration; + strokeAnimation.removedOnCompletion = NO; + strokeAnimation.fillMode = kCAFillModeForwards; + strokeAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + [segmentLayer addAnimation:strokeAnimation forKey:@"strokeAnimation"]; + + if (_parentPieChartView.showsPercentageLabels && _pieSections.count == numberOfSegmentLayers) { + ORKPieChartSection *pieSection = _pieSections[idx]; + UILabel *label = pieSection.label; + label.alpha = 0; + [UIView animateWithDuration:singleAnimationDuration + delay:interAnimationDelay * idx + options:(UIViewAnimationOptions)0 + animations:^{ + label.alpha = 1.0; + } + completion:nil]; + } + + cumulativeValue += value; + } +} + +- (void)setRadiusScaleFactor:(CGFloat)radiusScaleFactor { + _radiusScaleFactor = radiusScaleFactor; +} + +#pragma mark - Accessibility + +- (NSArray *)accessibilityElements { + return _pieSections; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.h new file mode 100755 index 0000000..77c58b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPieChartView; + +@interface ORKPieChartTitleTextView : UIView + +@property (nonatomic) UILabel *titleLabel; +@property (nonatomic) UILabel *textLabel; +@property (nonatomic) UILabel *noDataLabel; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView NS_DESIGNATED_INITIALIZER; + +- (void)showNoDataLabel:(BOOL)showNoDataLabel; + +- (void)animateWithDuration:(NSTimeInterval)animationDuration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.m new file mode 100755 index 0000000..786eefe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartTitleTextView.m @@ -0,0 +1,182 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPieChartTitleTextView.h" + +#import "ORKPieChartView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKPieChartTitleTextView { + __weak ORKPieChartView *_parentPieChartView; + + NSMutableArray *_variableConstraints; +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithParentPieChartView:(ORKPieChartView *)parentPieChartView { + self = [super initWithFrame:CGRectZero]; + if (self) { + _parentPieChartView = parentPieChartView; + self.translatesAutoresizingMaskIntoConstraints = NO; + + _titleLabel = [UILabel new]; + _titleLabel.textColor = ORKColor(ORKChartDefaultTextColorKey); + [_titleLabel setTextAlignment:NSTextAlignmentCenter]; + + _textLabel = [UILabel new]; + _textLabel.textColor = ORKColor(ORKChartDefaultTextColorKey); + [_textLabel setTextAlignment:NSTextAlignmentCenter]; + + _noDataLabel = [UILabel new]; + _noDataLabel.textColor = [UIColor lightGrayColor]; + _noDataLabel.text = ORKLocalizedString(@"CHART_NO_DATA_TEXT", nil); + _noDataLabel.textAlignment = NSTextAlignmentCenter; + _noDataLabel.hidden = YES; + + [self addSubview:_titleLabel]; + [self addSubview:_textLabel]; + [self addSubview:_noDataLabel]; + + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _noDataLabel.translatesAutoresizingMaskIntoConstraints = NO; + + [self setUpConstraints]; + [self setNeedsUpdateConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_titleLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_noDataLabel + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + NSDictionary *views = NSDictionaryOfVariableBindings(_titleLabel, _textLabel, _noDataLabel); + if (_noDataLabel.hidden) { + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_titleLabel][_textLabel]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + } else { + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_noDataLabel]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + } + + [NSLayoutConstraint activateConstraints:_variableConstraints]; + [super updateConstraints]; +} + +- (void)showNoDataLabel:(BOOL)showNoDataLabel { + _titleLabel.hidden = showNoDataLabel; + _textLabel.hidden = showNoDataLabel; + _noDataLabel.hidden = !showNoDataLabel; + [self setNeedsUpdateConstraints]; +} + +- (void)animateWithDuration:(NSTimeInterval)animationDuration { + _titleLabel.alpha = 0.0; + _textLabel.alpha = 0.0; + _noDataLabel.alpha = 0.0; + [UIView animateWithDuration:animationDuration + animations:^{ + _titleLabel.alpha = 1.0; + _textLabel.alpha = 1.0; + _noDataLabel.alpha = 1.0; + }]; +} + +#pragma mark - Accessibility + +- (NSArray *)accessibilityElements { + if (!_titleLabel || !_textLabel || !_noDataLabel) { + return nil; + } + + NSMutableArray *accessibilityElements = [[NSMutableArray alloc] init]; + if (!_noDataLabel.hidden) { + [accessibilityElements addObject:_noDataLabel]; + } else { + [accessibilityElements addObject:_titleLabel]; + [accessibilityElements addObject:_textLabel]; + } + + return accessibilityElements; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.h new file mode 100755 index 0000000..4697961 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.h @@ -0,0 +1,263 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPieChartView; + +/** + An object that adopts the `ORKPieChartViewDataSource` protocol is responsible for providing the + data required to populate an `ORKPieChartView` object. + + At a minimumm, a data source object must implement the `numberOfSegmentsInPieChartView` and + `pieChartView:valueForSegmentAtIndex:` methods. These methods are responsible for returning the + number of segments in a pie chart view and the value for each segment. A data source object may + provide additional information to the pie chart by implementing the optional + `ORKPieChartViewDataSource` methods. + + When configuring an `ORKPieChartView` object, assign your data source to its `dataSource` property. +*/ +ORK_AVAILABLE_DECL +@protocol ORKPieChartViewDataSource + +@required +/** + Asks the data source for the number of segments in the pie chart view. + + @param pieChartView The pie chart view asking for the number of segments. + + @return The number of segments in the pie chart view. +*/ +- (NSInteger)numberOfSegmentsInPieChartView:(ORKPieChartView *)pieChartView; + +/** + Asks the data source for the value of a segment in the pie chart view. + + The value can be any arbitrary integer: the pie chart view normalizes them by the sum of all + returned values. + + @param pieChartView The pie chart view asking for the value of the segment. + @param index An index number specifying the segment in the pie chart view. + + @return The value of the segment at the specified `index` in the pie chart view. +*/ +- (CGFloat)pieChartView:(ORKPieChartView *)pieChartView valueForSegmentAtIndex:(NSInteger)index; + +@optional +/** + Asks the data source for the color of a segment in the pie chart view. + + If this method is not implemented, the pie chart view uses a unique shade of the current + tint color for each segment. + + @param pieChartView The pie chart view asking for the color of the segment. + @param index An index number specifying the segment in the pie chart view. + + @return The color of the segment at the specified `index` in the pie chart view. +*/ +- (UIColor *)pieChartView:(ORKPieChartView *)pieChartView colorForSegmentAtIndex:(NSInteger)index; + +/** + Asks the data source for the title to appear in the legend for a segment in the pie chart view. + + If this method is not implemented, the pie chart view does not display the legend. If you return + `nil` for a segment index, the label for that segment won't be displayed in the legend. + + @param pieChartView The pie chart view asking for the title. + @param index An index number specifying the segment in the pie chart view. + + @return The title of the segment at the specified index in the pie chat view's + legend. +*/ +- (nullable NSString *)pieChartView:(ORKPieChartView *)pieChartView titleForSegmentAtIndex:(NSInteger)index; + +@end + +/** + The `ORKPieChartView` class presents data provided by an object conforming to the + `ORKPieChartViewDataSource` protocol as a pie chart. +*/ +ORK_CLASS_AVAILABLE +IB_DESIGNABLE +@interface ORKPieChartView : UIView + +/** + The data source object responsible for populating the pie chart with data. +*/ +@property (nonatomic, weak, nullable) id dataSource; + +/** + The width of the line used to draw the circular sections of the pie chart. + + If you do not set a value for this property, the pie chart view assumes a sensible value. If + you set a number higher than the radius of the pie chart, the pie chart draws a completely + filled pie. +*/ +@property (nonatomic) IBInspectable CGFloat lineWidth; + +/** + The text to display as a title in the pie chart view. + + If you do not set a value for this property, the pie chart does not display a title. +*/ +@property (nonatomic, copy, nullable) IBInspectable NSString *title; + +/** + The text to display beneath the title in the pie chart view. + + If you do not set a value for this property, the pie chart does not display any text beneath the + title. +*/ +@property (nonatomic, copy, nullable) IBInspectable NSString *text; + +/** + The color used for the text of the title label. + + The default value for this property is a light gray color. Setting this property to `nil` resets it + to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *titleColor; + +/** + The color used for the text of the text label. + + The default value for this property is a light gray color. Setting this property to `nil` resets it + to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIColor *textColor; + +/** + A Boolean value indicating whether the title and text labels should be drawn above the chart. + + If this value of this property is `NO`, the title and text are drawn at the center of the chart. + The default value for this property is `NO`. + */ +@property (nonatomic) IBInspectable BOOL showsTitleAboveChart; + +/** + A Boolean value indicating whether the pie chart should draw percentage labels next to each + segement. + + The default value for this property is YES. +*/ +@property (nonatomic) IBInspectable BOOL showsPercentageLabels; + +/** + A Boolean value indicating whether the pie chart drawing animation draws clockwise or + counterclockwise. + + The default value for this property is YES. +*/ +@property (nonatomic) IBInspectable BOOL drawsClockwise; + +/** + The string that will be displayed if the sum of the values of all segments is zero. + + The default value for this property is an appropriate message string. Setting this property to + `nil` resets it to its default value. +*/ +@property (nonatomic, copy, null_resettable) IBInspectable NSString *noDataText; + +/** + The font used for the title text of the header. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *titleFont; + +/** + The font used for the subtitle text of the header. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *subtitleFont; + +/** + The font used for the "no data" label in the chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *noDataFont; + +/** + The font used for the percentage label of each segment of the pie chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *percentageLabelFont; + +/** + The font used for the legend that describes each color<->segment pair in the pie chart. + + The default value for this property is the appropriate font. Setting this property to + `nil` resets it to its default value. + */ +@property (nonatomic, strong, null_resettable) IBInspectable UIFont *legendFont; + +/** + Animates the pie chart when it is first displayed on the screen. + + You can optionally call this method from the `viewWillAppear:` implementation of the view + controller that owns the pie chart view. + + @param animationDuration The duration of the appearing animation. +*/ +- (void)animateWithDuration:(NSTimeInterval)animationDuration; + +/** + Reloads the plotted data. + + Call this method to reload the data and re-plot the graph. You should call it if the data provided by the dataSource changes. + */ +- (void)reloadData; + +/** + A scaling factor for the radius of the pie chart. + Increase it to increase the radius of the pie chart and vice versa. + + Defaults to 0.5. + */ +@property (nonatomic) CGFloat radiusScaleFactor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.m new file mode 100755 index 0000000..892c3d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView.m @@ -0,0 +1,531 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#import "ORKPieChartView.h" +#import "ORKPieChartView_Internal.h" + +#import "ORKPieChartLegendView.h" +#import "ORKPieChartPieView.h" +#import "ORKPieChartTitleTextView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +#if TARGET_INTERFACE_BUILDER + +@interface ORKIBPieChartViewDataSourceSegment : NSObject + +@property (nonatomic, assign) CGFloat value; + +@property (nonatomic, copy, nullable) NSString *title; + +@property (nonatomic, strong, nullable) UIColor *color; + +@end + + +@interface ORKIBPieChartViewDataSource : NSObject + ++ (instancetype)sharedInstance; + +@property (nonatomic, strong, nullable) NSArray *segments; + +@end + + +@implementation ORKIBPieChartViewDataSourceSegment + +@end + + +@implementation ORKIBPieChartViewDataSource + ++ (instancetype)sharedInstance { + static ORKIBPieChartViewDataSource *sharedInstance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self class] new]; + }); + return sharedInstance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + ORKIBPieChartViewDataSourceSegment *segment1 = [ORKIBPieChartViewDataSourceSegment new]; + segment1.value = 10.0; + segment1.title = @"Title 1"; + segment1.color = [UIColor colorWithRed:217.0/225 green:217.0/255 blue:217.0/225 alpha:1]; + + ORKIBPieChartViewDataSourceSegment *segment2 = [ORKIBPieChartViewDataSourceSegment new]; + segment2.value = 25.0; + segment2.title = @"Title 2"; + segment2.color = [UIColor colorWithRed:142.0/255 green:142.0/255 blue:147.0/255 alpha:1]; + + ORKIBPieChartViewDataSourceSegment *segment3 = [ORKIBPieChartViewDataSourceSegment new]; + segment3.value = 45.0; + segment3.title = @"Title 3"; + segment3.color = [UIColor colorWithRed:244.0/225 green:190.0/255 blue:74.0/225 alpha:1]; + + _segments = @[segment1, segment2, segment3]; + } + return self; +} +- (NSInteger)numberOfSegmentsInPieChartView:(ORKPieChartView *)pieChartView { + return self.segments.count; +} +- (CGFloat)pieChartView:(ORKPieChartView *)pieChartView valueForSegmentAtIndex:(NSInteger)index { + return self.segments[index].value; +} + +- (UIColor *)pieChartView:(ORKPieChartView *)pieChartView colorForSegmentAtIndex:(NSInteger)index { + return self.segments[index].color; +} + +- (NSString *)pieChartView:(ORKPieChartView *)pieChartView titleForSegmentAtIndex:(NSInteger)index { + return self.segments[index].title; +} + +@end + +#endif + + +static const CGFloat TitleToPiePadding = 8.0; +static const CGFloat PieToLegendPadding = 8.0; + + +@implementation ORKPieChartSection + +- (instancetype)initWithLabel:(UILabel *)label angle:(CGFloat)angle { + if (self = [super init]) { + _label = label; + _angle = angle; + } + return self; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return self.label.isAccessibilityElement; +} + +- (NSString *)accessibilityLabel { + return self.label.accessibilityLabel; +} + +- (CGRect)accessibilityFrame { + return self.label.accessibilityFrame; +} + +@end + + +@implementation ORKPieChartView { + NSMutableArray *_variableConstraints; + + ORKPieChartPieView *_pieView; + ORKPieChartLegendView *_legendView; + ORKPieChartTitleTextView *_titleTextView; + BOOL _shouldInvalidateLegendViewIntrinsicContentSize; +} + +#pragma mark - Init + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self sharedInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + [self sharedInit]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)sharedInit { + _lineWidth = 10; + _showsTitleAboveChart = NO; + _showsPercentageLabels = YES; + _drawsClockwise = YES; + + // nil reset to default fonts + self.titleFont = nil; + self.subtitleFont = nil; + self.noDataFont = nil; + self.percentageLabelFont = nil; + self.legendFont = nil; + + _legendView = nil; // legend lazily initialized on demand + + _pieView = [[ORKPieChartPieView alloc] initWithParentPieChartView:self]; + [self addSubview:_pieView]; + + _titleTextView = [[ORKPieChartTitleTextView alloc] initWithParentPieChartView:self]; + [self addSubview:_titleTextView]; + + [self updateContentSizeCategoryFonts]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateContentSizeCategoryFonts) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + [self setUpConstraints]; + [self setNeedsUpdateConstraints]; +} + +#pragma mark - API + +- (void)reloadData { + CGFloat sumOfValues = [_pieView normalizeValues]; + [_pieView updatePieLayers]; + [_pieView updatePercentageLabels]; + [_titleTextView showNoDataLabel:(sumOfValues == 0)]; + [self updateLegendView]; +} + +- (void)setDataSource:(id)dataSource { + _dataSource = dataSource; + [self reloadData]; +} + +- (void)tintColorDidChange { + [_pieView updateColors]; + [_legendView reloadData]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + _shouldInvalidateLegendViewIntrinsicContentSize = YES; + [self setNeedsLayout]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + _shouldInvalidateLegendViewIntrinsicContentSize = YES; + [self setNeedsLayout]; +} + +#pragma mark - Configuration + +- (void)setRadiusScaleFactor:(CGFloat)radiusScaleFactor { + _pieView.radiusScaleFactor = radiusScaleFactor; + [_pieView setNeedsLayout]; +} + +- (void)setLineWidth:(CGFloat)lineWidth { + _lineWidth = lineWidth; + [_pieView setNeedsLayout]; +} + +- (void)setTitle:(NSString *)title { + _titleTextView.titleLabel.text = title; +} + +- (NSString *)title { + return _titleTextView.titleLabel.text; +} + +- (void)setText:(NSString *)text { + _titleTextView.textLabel.text = text; +} + +- (NSString *)text { + return _titleTextView.textLabel.text; +} + +- (void)setNoDataText:(NSString *)noDataText { + if (!noDataText) { + noDataText = ORKLocalizedString(@"CHART_NO_DATA_TEXT", nil); + } + _titleTextView.noDataLabel.text = noDataText; +} + +- (NSString *)noDataText { + return _titleTextView.noDataLabel.text; +} + +- (void)setTitleFont:(UIFont *)titleFont { + if (!titleFont) { + titleFont = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + } + _titleFont = titleFont; + _titleTextView.titleLabel.font = _titleFont; +} + +- (void)setSubtitleFont:(UIFont *)subtitleFont { + if (!subtitleFont) { + subtitleFont = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; + } + _subtitleFont = subtitleFont; + _titleTextView.textLabel.font = _subtitleFont; +} + +- (void)setNoDataFont:(UIFont *)noDataFont { + if (!noDataFont) { + noDataFont = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + } + _noDataFont = noDataFont; + _titleTextView.noDataLabel.font = _noDataFont; +} + +- (void)setPercentageLabelFont:(UIFont *)percentageLabelFont { + if (!percentageLabelFont) { + percentageLabelFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2]; + } + _percentageLabelFont = percentageLabelFont; + _pieView.percentageLabelFont = _percentageLabelFont; +} + +- (void)setLegendFont:(UIFont *)legendFont { + if (!legendFont) { + legendFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; + } + _legendFont = legendFont; + _legendView.labelFont = _legendFont; +} + +- (void)setTitleColor:(UIColor *)titleColor { + if (!titleColor) { + titleColor = ORKColor(ORKChartDefaultTextColorKey); + } + _titleTextView.titleLabel.textColor = titleColor; +} + +- (UIColor *)titleColor { + return _titleTextView.titleLabel.textColor; +} + +- (void)setTextColor:(UIColor *)textColor { + if (!textColor) { + textColor = ORKColor(ORKChartDefaultTextColorKey); + } + _titleTextView.textLabel.textColor = textColor; +} + +- (UIColor *)textColor { + return _titleTextView.textLabel.textColor; +} + +- (void)setShowsTitleAboveChart:(BOOL)showsTitleAboveChart { + _showsTitleAboveChart = showsTitleAboveChart; + [self setNeedsUpdateConstraints]; +} + +- (void)setShowsPercentageLabels:(BOOL)showsPercentageLabels { + _showsPercentageLabels = showsPercentageLabels; + [_pieView updatePercentageLabels]; + [_pieView setNeedsLayout]; +} + +- (void)setDrawsClockwise:(BOOL)drawsClockwise { + _drawsClockwise = drawsClockwise; + [_pieView setNeedsLayout]; +} + +#pragma mark - Presentation + +- (void)updateContentSizeCategoryFonts { + _titleTextView.titleLabel.font = self.titleFont; + _titleTextView.textLabel.font = self.subtitleFont; + _titleTextView.noDataLabel.font = self.noDataFont; + _pieView.percentageLabelFont = self.percentageLabelFont; + _legendView.labelFont = self.legendFont; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + NSDictionary *views = NSDictionaryOfVariableBindings(_pieView); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_pieView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|->=0-[_pieView]->=0-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"PlotToLegendPadding": @(PieToLegendPadding) } + views:views]]; + + NSLayoutConstraint *maximumHeightConstraint = [NSLayoutConstraint constraintWithItem:_pieView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + maximumHeightConstraint.priority = UILayoutPriorityDefaultLow - 1; + [constraints addObject:maximumHeightConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_titleTextView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_pieView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + if (_showsTitleAboveChart) { + NSDictionary *views = NSDictionaryOfVariableBindings(_pieView, _titleTextView); + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_titleTextView]-TitleToPiePading-[_pieView]" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"TitleToPiePading": @(TitleToPiePadding) } + views:views]]; + + } else { + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_titleTextView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_pieView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + } + + if (_legendView) { + NSDictionary *views = NSDictionaryOfVariableBindings(_pieView, _legendView); + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_legendView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_pieView]-PlotToLegendPadding-[_legendView]|" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"PlotToLegendPadding": @(PieToLegendPadding) } + views:views]]; + } + + [NSLayoutConstraint activateConstraints:_variableConstraints]; + [super updateConstraints]; +} + +- (void)updateLegendView { + if ([_dataSource respondsToSelector:@selector(pieChartView:titleForSegmentAtIndex:)]) { + if (_legendView) { + [_legendView removeFromSuperview]; + ORKRemoveConstraintsForRemovedViews(_variableConstraints, @[_legendView]); + } + _legendView = [[ORKPieChartLegendView alloc] initWithParentPieChartView:self]; + [self addSubview:_legendView]; + _legendView.labelFont = [UIFont preferredFontForTextStyle:UIFontTextStyleCaption1]; + _shouldInvalidateLegendViewIntrinsicContentSize = YES; + } else { + [_legendView removeFromSuperview]; + _legendView = nil; + } + [self setNeedsUpdateConstraints]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + if (_shouldInvalidateLegendViewIntrinsicContentSize) { + _shouldInvalidateLegendViewIntrinsicContentSize = NO; + [_legendView invalidateIntrinsicContentSize]; + } +} + +#pragma mark - DataSource + +- (UIColor *)colorForSegmentAtIndex:(NSInteger)index { + UIColor *color = nil; + if ([_dataSource respondsToSelector:@selector(pieChartView:colorForSegmentAtIndex:)]) { + color = [_dataSource pieChartView:self colorForSegmentAtIndex:index]; + } else { + // Default colors: use tintColor reducing alpha progressively + NSInteger numberOfSegments = [_dataSource numberOfSegmentsInPieChartView:self]; + color = ORKOpaqueColorWithReducedAlphaFromBaseColor(self.tintColor, index, numberOfSegments); + } + return color; +} + +- (void)animateWithDuration:(NSTimeInterval)animationDuration { + if (animationDuration < 0) { + @throw [NSException exceptionWithName:NSGenericException reason:@"animationDuration cannot be lower than 0" userInfo:nil]; + } + [self layoutIfNeeded]; // layout pass needed so _legendView (a UICollectionView subclass) dequees and displays the cells + [_pieView animateWithDuration:animationDuration]; + [_legendView animateWithDuration:animationDuration]; + [_titleTextView animateWithDuration:animationDuration]; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return NO; +} + +- (NSArray *)accessibilityElements { + NSMutableArray *accessibilityElements = [[NSMutableArray alloc] init]; + [accessibilityElements addObjectsFromArray:_titleTextView.accessibilityElements]; + + // Use legends if there are any and percentage labels if not + if (_legendView) { + [accessibilityElements addObject:_legendView]; + } else { + [accessibilityElements addObjectsFromArray:_pieView.accessibilityElements]; + } + + return accessibilityElements; +} + +#pragma mark - Interface Builder designable + +- (void)prepareForInterfaceBuilder { + [super prepareForInterfaceBuilder]; +#if TARGET_INTERFACE_BUILDER + self.dataSource = [ORKIBPieChartViewDataSource sharedInstance]; +#endif +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView_Internal.h new file mode 100755 index 0000000..752bc51 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKPieChartView_Internal.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#import "ORKPieChartView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKPieChartSection : NSObject + +- (instancetype)initWithLabel:(UILabel *)label angle:(CGFloat)angle; + +@property (nonatomic, readonly) UILabel *label; +@property (nonatomic) CGFloat angle; + +@end + + +@interface ORKPieChartView () + +- (UIColor *)colorForSegmentAtIndex:(NSInteger)index; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.h new file mode 100755 index 0000000..f8cce22 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKGraphChartView; + +@interface ORKXAxisView : UIView + +@property (nonatomic) UIFont *titleFont; + +@property (nonatomic) UIColor *axisColor; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +- (instancetype)initWithParentGraphChartView:(ORKGraphChartView *)parentGraphChartView NS_DESIGNATED_INITIALIZER; + +- (void)updateTitles; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.m new file mode 100755 index 0000000..d64ac2a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKXAxisView.m @@ -0,0 +1,230 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, James Cox. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKXAxisView.h" + +#import "ORKGraphChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat LastLabelHeight = 20.0; + +@implementation ORKXAxisView { + __weak ORKGraphChartView *_parentGraphChartView; + CALayer *_lineLayer; + NSMutableArray *_titleLabels; + NSMutableArray *_titleTickLayers; +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithParentGraphChartView:(ORKGraphChartView *)parentGraphChartView { + self = [super initWithFrame:CGRectZero]; + if (self) { + _parentGraphChartView = parentGraphChartView; + _axisColor = _parentGraphChartView.axisColor; + + _lineLayer = [CALayer layer]; + _lineLayer.backgroundColor = _axisColor.CGColor; + [self.layer addSublayer:_lineLayer]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + CGFloat width = self.bounds.size.width; + _lineLayer.frame = CGRectMake(0, -0.5, width, 1); + NSUInteger index = 0; + NSUInteger numberOfTitleLabels = _titleTickLayers.count; + for (CALayer *titleTickLayer in _titleTickLayers) { + CGFloat positionOnXAxis = xAxisPoint(index, numberOfTitleLabels, width); + titleTickLayer.frame = CGRectMake(positionOnXAxis - scalePixelAdjustment(), -ORKGraphChartViewAxisTickLength + scalePixelAdjustment(), 1, ORKGraphChartViewAxisTickLength); + index++; + } + _titleLabels.lastObject.layer.cornerRadius = LastLabelHeight * 0.5; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSUInteger numberOfTitleLabels = _titleLabels.count; + for (NSUInteger i = 0; i < numberOfTitleLabels; i++) { + UILabel *label = _titleLabels[i]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:label + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:label.superview + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + if ((int)i == 0) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:label + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:label.superview + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:0.0]]; + } else { + // This "magic" multiplier constraints evenly space the labels among + // the superview without having to manually specify its width. + CGFloat multiplier = 1.0 - ((CGFloat)(numberOfTitleLabels - i - 1) / (numberOfTitleLabels - 1)); + [constraints addObject:[NSLayoutConstraint constraintWithItem:label + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:label.superview + attribute:NSLayoutAttributeTrailing + multiplier:multiplier + constant:0.0]]; + } + + if ((int)i == _titleLabels.count - 1) { + NSLayoutConstraint *constraint = nil; + + constraint = [NSLayoutConstraint constraintWithItem:label + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:LastLabelHeight]; + constraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:constraint]; + + constraint = [NSLayoutConstraint constraintWithItem:label + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:LastLabelHeight]; + constraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:constraint]; + } + } + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateTitles { + [_titleLabels makeObjectsPerformSelector:@selector(removeFromSuperview)]; // Old constraints automatically removed when removing the views + [_titleTickLayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + _titleLabels = nil; + _titleTickLayers = nil; + + if ([_parentGraphChartView.dataSource respondsToSelector:@selector(graphChartView:titleForXAxisAtPointIndex:)]) { + _titleLabels = [NSMutableArray new]; + _titleTickLayers = [NSMutableArray new]; + + NSInteger numberOfTitleLabels = _parentGraphChartView.numberOfXAxisPoints; + for (NSInteger i = 0; i < numberOfTitleLabels; i++) { + NSString *title = [_parentGraphChartView.dataSource graphChartView:_parentGraphChartView titleForXAxisAtPointIndex:i]; + UILabel *label = [UILabel new]; + label.text = title; + label.font = _titleFont; + label.numberOfLines = 2; + label.textAlignment = NSTextAlignmentCenter; + label.adjustsFontSizeToFitWidth = YES; + label.minimumScaleFactor = 0.7; + label.translatesAutoresizingMaskIntoConstraints = NO; + + if (i < (numberOfTitleLabels - 1)) { + label.textColor = self.tintColor; + } else { + label.textColor = [UIColor whiteColor]; + label.backgroundColor = self.tintColor; + label.layer.cornerRadius = LastLabelHeight * 0.5; + label.layer.masksToBounds = YES; + } + + [self addSubview:label]; + [_titleLabels addObject:label]; + } + + // Add vertical tick layers above labels + for (NSInteger i = 0; i < numberOfTitleLabels; i++) { + CALayer *titleTickLayer = [CALayer layer]; + CGFloat positionOnXAxis = xAxisPoint(i, numberOfTitleLabels, self.bounds.size.width); + titleTickLayer.frame = CGRectMake(positionOnXAxis - 0.5, -ORKGraphChartViewAxisTickLength, 1, ORKGraphChartViewAxisTickLength); + titleTickLayer.backgroundColor = _axisColor.CGColor; + + [self.layer addSublayer:titleTickLayer]; + [_titleTickLayers addObject:titleTickLayer]; + } + + [self setUpConstraints]; + } +} + +- (void)tintColorDidChange { + NSUInteger numberOfTitleLabels = _titleLabels.count; + for (NSUInteger i = 0; i < numberOfTitleLabels; i++) { + UILabel *label = _titleLabels[i]; + if (i < (numberOfTitleLabels - 1)) { + label.textColor = self.tintColor; + } else { + label.textColor = [UIColor whiteColor]; + label.backgroundColor = self.tintColor; + } + } +} + +- (void)setTitleFont:(UIFont *)titleFont { + _titleFont = titleFont; + for (UILabel *label in _titleLabels) { + label.font = _titleFont; + [label sizeToFit]; + } + [self setNeedsLayout]; +} + +- (void)setAxisColor:(UIColor *)axisColor { + _axisColor = axisColor; + _lineLayer.backgroundColor = _axisColor.CGColor; + for (CALayer *titleTickLayer in _titleTickLayers) { + titleTickLayer.backgroundColor = _axisColor.CGColor; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.h new file mode 100755 index 0000000..39d4996 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKGraphChartView; + +@interface ORKYAxisView : UIView + +@property (nonatomic) UIFont *titleFont; + +@property (nonatomic) UIColor *titleColor; + +@property (nonatomic) UIColor *axisColor; + +@property (nonatomic) NSUInteger decimalPlaces; + +@property (nonatomic) NSArray *yAxisLabelFactors; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; + +- (instancetype)initWithParentGraphChartView:(ORKGraphChartView *)parentGraphChartView NS_DESIGNATED_INITIALIZER; + +- (void)updateTicksAndLabels; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.m new file mode 100755 index 0000000..60a8fb1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Charts/ORKYAxisView.m @@ -0,0 +1,221 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKYAxisView.h" + +#import "ORKGraphChartView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat ImageVerticalPadding = 3.0; + +@implementation ORKYAxisView { + __weak ORKGraphChartView *_parentGraphChartView; + UIImageView *_maxImageView; + UIImageView *_minImageView; + + NSMutableDictionary *_tickLayersByFactor; + NSMutableDictionary *_tickLabelsByFactor; + + NSString *_decimalFormat; +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithParentGraphChartView:(ORKGraphChartView *)parentGraphChartView { + self = [super initWithFrame:CGRectZero]; + if (self) { + _parentGraphChartView = parentGraphChartView; + _axisColor = _parentGraphChartView.axisColor; + _titleColor = _parentGraphChartView.verticalAxisTitleColor; + [self setDecimalPlaces:0]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self layoutTicksAndLabels]; +} + +- (void)updateTicksAndLabels { + [_maxImageView removeFromSuperview]; + _maxImageView = nil; + [_minImageView removeFromSuperview]; + _minImageView = nil; + + [_tickLayersByFactor.allValues makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + [_tickLabelsByFactor.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)]; + _tickLayersByFactor = nil; + _tickLabelsByFactor = nil; + + CGRect bounds = self.bounds; + CGFloat width = bounds.size.width; + if (_parentGraphChartView.maximumValueImage && _parentGraphChartView.minimumValueImage) { + // Use image icons as legends + CGFloat halfWidth = width / 2; + + _maxImageView = [[UIImageView alloc] initWithImage:_parentGraphChartView.maximumValueImage]; + _maxImageView.contentMode = UIViewContentModeScaleAspectFit; + _maxImageView.frame = CGRectMake(width - halfWidth, + -halfWidth / 2, + halfWidth, + halfWidth); + [self addSubview:_maxImageView]; + + _minImageView = [[UIImageView alloc] initWithImage:_parentGraphChartView.minimumValueImage]; + _minImageView.contentMode = UIViewContentModeScaleAspectFit; + _minImageView.frame = CGRectMake(width - halfWidth, + CGRectGetMaxY(bounds) - halfWidth - ImageVerticalPadding, + halfWidth, + halfWidth); + [self addSubview:_minImageView]; + + } else { + _tickLayersByFactor = [NSMutableDictionary new]; + _tickLabelsByFactor = [NSMutableDictionary new]; + + CGFloat minimumValue = _parentGraphChartView.minimumValue; + CGFloat maximumValue = _parentGraphChartView.maximumValue; + if (!_yAxisLabelFactors) { + if (minimumValue == maximumValue) { + _yAxisLabelFactors = @[ @0.5f ]; + } else { + _yAxisLabelFactors = @[ @0.2f, @1.0f ]; + } + } + + for (NSNumber *factorNumber in _yAxisLabelFactors) { + + CGFloat factor = factorNumber.floatValue; + + CALayer *tickLayer = [CALayer layer]; + CGFloat tickYPosition = CGRectGetHeight(self.bounds) * (1 - factor); + CGFloat tickXOrigin = CGRectGetWidth(self.bounds) - ORKGraphChartViewAxisTickLength; + tickLayer.frame = CGRectMake(tickXOrigin, + tickYPosition - 0.5, + ORKGraphChartViewAxisTickLength, + 1); + tickLayer.backgroundColor = _parentGraphChartView.axisColor.CGColor; + + [self.layer addSublayer:tickLayer]; + _tickLayersByFactor[factorNumber] = tickLayer; + + CGFloat labelHeight = 20; + CGFloat labelYPosition = tickYPosition - labelHeight / 2; + UILabel *tickLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, + labelYPosition, + width - (ORKGraphChartViewAxisTickLength + ORKGraphChartViewYAxisTickPadding), + labelHeight)]; + + CGFloat yValue = minimumValue + (maximumValue - minimumValue) * factor; + if (yValue != 0) { + tickLabel.text = [NSString stringWithFormat:_decimalFormat, yValue]; + } + tickLabel.backgroundColor = [UIColor clearColor]; + tickLabel.textColor = _titleColor; + tickLabel.textAlignment = NSTextAlignmentRight; + tickLabel.font = _titleFont; + tickLabel.minimumScaleFactor = 0.8; + [tickLabel sizeToFit]; + [self addSubview:tickLabel]; + _tickLabelsByFactor[factorNumber] = tickLabel; + } + } +} + +- (void)layoutTicksAndLabels { + CGRect bounds = self.bounds; + CGFloat width = bounds.size.width; + CGFloat halfWidth = width / 2; + _maxImageView.frame = CGRectMake(width - halfWidth, + -halfWidth / 2, + halfWidth, + halfWidth); + _minImageView.frame = CGRectMake(width - halfWidth, + CGRectGetMaxY(bounds) - halfWidth - ImageVerticalPadding, + halfWidth, + halfWidth); + + for (NSNumber *factorNumber in _tickLayersByFactor.allKeys) { + CGFloat factor = factorNumber.floatValue; + CALayer *tickLayer = _tickLayersByFactor[factorNumber]; + CGFloat tickYPosition = CGRectGetHeight(self.bounds) * (1 - factor); + CGFloat tickXOrigin = CGRectGetWidth(self.bounds) - ORKGraphChartViewAxisTickLength; + tickLayer.frame = CGRectMake(tickXOrigin, + tickYPosition - 0.5, + ORKGraphChartViewAxisTickLength, + 1); + + UILabel *tickLabel = _tickLabelsByFactor[factorNumber]; + tickLabel.center = CGPointMake(tickXOrigin - (ORKGraphChartViewYAxisTickPadding + tickLabel.bounds.size.width / 2), tickYPosition); + } +} + +- (void)setTitleFont:(UIFont *)titleFont { + _titleFont = titleFont; + for (UILabel *label in _tickLabelsByFactor.allValues) { + label.font = _titleFont; + [label sizeToFit]; + } +} + +- (void)setTitleColor:(UIColor *)titleColor { + _titleColor = titleColor; + for (UILabel *label in _tickLabelsByFactor.allValues) { + label.textColor = titleColor; + } +} + +- (void)setAxisColor:(UIColor *)axisColor { + _axisColor = axisColor; + for (CALayer *tickLayer in _tickLayersByFactor.allValues) { + tickLayer.backgroundColor = _axisColor.CGColor; + } +} + +- (void)setDecimalPlaces:(NSUInteger)decimalPlaces { + _decimalPlaces = decimalPlaces; + _decimalFormat = [NSString stringWithFormat:@"%%.%luf", (unsigned long)_decimalPlaces]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.h new file mode 100755 index 0000000..c0c6e92 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import "ORKStepContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKActiveStep; +@class ORKActiveStepCustomView; + +@interface ORKActiveStepView : ORKStepContainerView; + +@property (nonatomic, strong, nullable) ORKActiveStep *activeStep; +@property (nonatomic, strong, nullable) ORKActiveStepCustomView *activeCustomView; + +- (void)updateTitle:(nullable NSString *)title text:(nullable NSString *)text; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.m new file mode 100755 index 0000000..0112e56 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveStepView.m @@ -0,0 +1,67 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKActiveStepView.h" + +#import "ORKCustomStepView_Internal.h" +#import "ORKTintedImageView.h" +#import "ORKStepContainerView_Private.h" + +#import "ORKActiveStep_Internal.h" +#import "ORKStep_Private.h" + + +@implementation ORKActiveStepView { + ORKTintedImageView *_imageView; +} + +- (void)setActiveStep:(ORKActiveStep *)step { + _activeStep = step; + self.stepTitle = step.title; + self.stepText = step.text; + self.stepDetailText = step.detailText; + self.stepTopContentImage = step.image; + self.stepTopContentImageContentMode = step.imageContentMode; +} + +- (void)updateTitle:(NSString *)title text:(NSString *)text { + self.stepTitle = title; + self.stepText = text; +} + +- (void)setActiveCustomView:(ORKActiveStepCustomView *)activeCustomView { + _activeCustomView = activeCustomView; + if (_activeCustomView) { + self.customContentView = activeCustomView; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveTaskResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveTaskResult.h new file mode 100755 index 0000000..eca5c2b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKActiveTaskResult.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.h new file mode 100755 index 0000000..d4810cf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.h @@ -0,0 +1,1949 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + Copyright (c) 2017, Sage Bionetworks. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKScaleAnswerFormat; +@class ORKContinuousScaleAnswerFormat; +@class ORKTextScaleAnswerFormat; +@class ORKValuePickerAnswerFormat; +@class ORKMultipleValuePickerAnswerFormat; +@class ORKImageChoiceAnswerFormat; +@class ORKTextChoiceAnswerFormat; +@class ORKBooleanAnswerFormat; +@class ORKNumericAnswerFormat; +@class ORKTimeOfDayAnswerFormat; +@class ORKDateAnswerFormat; +@class ORKTextAnswerFormat; +@class ORKEmailAnswerFormat; +@class ORKTimeIntervalAnswerFormat; +@class ORKHeightAnswerFormat; +@class ORKWeightAnswerFormat; +@class ORKLocationAnswerFormat; +@class ORKSESAnswerFormat; + +@class ORKTextChoice; +@class ORKImageChoice; + +/** + The `ORKAnswerFormat` class is the abstract base class for classes that describe the + format in which a survey question or form item should be answered. The ResearchKit framework uses + `ORKQuestionStep` and `ORKFormItem` to represent questions to ask the user. Each + question must have an associated answer format. + + To use an answer format, instantiate the appropriate answer format subclass and + attach it to a question step or form item. Incorporate the resulting step + into a task, and present the task with a task view controller. + + An answer format is validated when its owning step is validated. + + Some answer formats are constructed of other answer formats. When this is the + case, the answer format can override the method `impliedAnswerFormat` to return + the answer format that is implied. For example, a Boolean answer format + is presented in the same way as a single-choice answer format with the + choices Yes and No mapping to `@(YES)` and `@(NO)`, respectively. + */ +ORK_CLASS_AVAILABLE +@interface ORKAnswerFormat : NSObject + +/// @name Properties + +/** + The type of question. (read-only) + + You can use this enumerated value in your Objective-C code to switch on + a rough approximation of the type of question that is being asked. + + Note that answer format subclasses override the getter to return the appropriate question + type. + */ +@property (readonly) ORKQuestionType questionType; + +/** + Determines if the "I Don't Know" button will show. + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldShowDontKnowButton) BOOL showDontKnowButton; + +/** + Custom text that will be shown inside of the "I Don't Know" button if showDontKnowButton is set to true. + + Defults to nil. + */ +@property (nonatomic, nullable) NSString *customDontKnowButtonText; + +/// @name Factory methods + ++ (ORKScaleAnswerFormat *)scaleAnswerFormatWithMaximumValue:(NSInteger)scaleMaximum + minimumValue:(NSInteger)scaleMinimum + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription; + ++ (ORKContinuousScaleAnswerFormat *)continuousScaleAnswerFormatWithMaximumValue:(double)scaleMaximum + minimumValue:(double)scaleMinimum + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription; + ++ (ORKTextScaleAnswerFormat *)textScaleAnswerFormatWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex + vertical:(BOOL)vertical; + ++ (ORKBooleanAnswerFormat *)booleanAnswerFormat; + ++ (ORKBooleanAnswerFormat *)booleanAnswerFormatWithYesString:(NSString *)yes + noString:(NSString *)no; + ++ (ORKValuePickerAnswerFormat *)valuePickerAnswerFormatWithTextChoices:(NSArray *)textChoices; + ++ (ORKMultipleValuePickerAnswerFormat *)multipleValuePickerAnswerFormatWithValuePickers:(NSArray *)valuePickers; + ++ (ORKImageChoiceAnswerFormat *)choiceAnswerFormatWithImageChoices:(NSArray *)imageChoices; ++ (ORKImageChoiceAnswerFormat *)choiceAnswerFormatWithImageChoices:(NSArray *)imageChoices + style:(ORKChoiceAnswerStyle)style + vertical:(BOOL)vertical; + ++ (ORKTextChoiceAnswerFormat *)choiceAnswerFormatWithStyle:(ORKChoiceAnswerStyle)style + textChoices:(NSArray *)textChoices; + ++ (ORKNumericAnswerFormat *)decimalAnswerFormatWithUnit:(nullable NSString *)unit; ++ (ORKNumericAnswerFormat *)integerAnswerFormatWithUnit:(nullable NSString *)unit; + ++ (ORKTimeOfDayAnswerFormat *)timeOfDayAnswerFormat; ++ (ORKTimeOfDayAnswerFormat *)timeOfDayAnswerFormatWithDefaultComponents:(nullable NSDateComponents *)defaultComponents; + ++ (ORKDateAnswerFormat *)dateTimeAnswerFormat; ++ (ORKDateAnswerFormat *)dateTimeAnswerFormatWithDefaultDate:(nullable NSDate *)defaultDate + minimumDate:(nullable NSDate *)minimumDate + maximumDate:(nullable NSDate *)maximumDate + calendar:(nullable NSCalendar *)calendar; + ++ (ORKDateAnswerFormat *)dateAnswerFormat; ++ (ORKDateAnswerFormat *)dateAnswerFormatWithDefaultDate:(nullable NSDate *)defaultDate + minimumDate:(nullable NSDate *)minimumDate + maximumDate:(nullable NSDate *)maximumDate + calendar:(nullable NSCalendar *)calendar; + ++ (ORKTextAnswerFormat *)textAnswerFormat; + ++ (ORKTextAnswerFormat *)textAnswerFormatWithMaximumLength:(NSInteger)maximumLength; + ++ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage; + ++ (ORKEmailAnswerFormat *)emailAnswerFormat; + ++ (ORKTimeIntervalAnswerFormat *)timeIntervalAnswerFormat; + ++ (ORKTimeIntervalAnswerFormat *)timeIntervalAnswerFormatWithDefaultInterval:(NSTimeInterval)defaultInterval + step:(NSInteger)step; + ++ (ORKHeightAnswerFormat *)heightAnswerFormat; + ++ (ORKHeightAnswerFormat *)heightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem; + ++ (ORKWeightAnswerFormat *)weightAnswerFormat; + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem; + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision; + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision + minimumValue:(double)minimumValue + maximumValue:(double)maximumValue + defaultValue:(double)defaultValue; + ++ (ORKLocationAnswerFormat *)locationAnswerFormat; + ++ (ORKSESAnswerFormat *)socioEconomicAnswerFormatWithTopRungText:(NSString *)topRungText bottomRungText:(NSString *)bottomRungText; + +/// @name Validation + +/** + Validates the parameters of the answer format to ensure that they can be displayed. + + Typically, this method is called by the validation methods of the owning objects, which are + themselves called when a step view controller that contains this answer format is + about to be displayed. + */ +- (void)validateParameters; + +/** + Some answer formats are constructed of other answer formats. This method allows + a subclass to return a different answer format for use in defining the UI/UX for + the answer format type. For example, a Boolean answer format is presented in the + same way as a single-choice answer format with the choices Yes and No mapping to + `@(YES)` and `@(NO)`, respectively, so its `impliedAnswerFormat` is an + `ORKTextChoiceAnswerFormat` with those options. + */ +- (ORKAnswerFormat *)impliedAnswerFormat; + +@end + + +/** + The `ORKScaleAnswerFormat `class represents an answer format that includes a slider control. + + The scale answer format produces an `ORKScaleQuestionResult` object that contains an integer whose + value is between the scale's minimum and maximum values, and represents one of the quantized step + values. + + The following are the rules bound with scale answer format - + + * Minimum number of step in a task should not be less than 1. + * Minimum number of section on a scale (step count) should not be less than 1. + * Maximum number of section on a scale (step count) should not be more than 13. + * The lower bound value in scale answer format cannot be lower than - 10000. + * The upper bound value in scale answer format cannot be more than 10000. + + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized scale answer format using the specified values. + + This method is the designated initializer. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, + the slider is displayed without a default value. + @param step The size of each discrete offset on the scale. + @param vertical Pass `YES` to use a vertical scale; for the default horizontal + scale, pass `NO`. + @param maximumValueDescription A localized label to describe the maximum value of the scale. + For none, pass `nil`. + @param minimumValueDescription A localized label to describe the minimum value of the scale. + For none, pass `nil`. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription NS_DESIGNATED_INITIALIZER; + + +/** + Returns an initialized scale answer format using the specified values. + + This method is a convenience initializer. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, the slider is + displayed without a default value. + @param step The size of each discrete offset on the scale. + @param vertical Pass `YES` to use a vertical scale; for the default horizontal scale, + pass `NO`. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical; + +/** + Returns an initialized horizontal scale answer format using the specified values. + + This method is a convenience initializer. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, the slider is + displayed without a default value. + @param step The size of each discrete offset on the scale. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step; + +/** + The upper bound of the scale. (read-only) + */ +@property (readonly) NSInteger maximum; + +/** + The lower bound of the scale. (read-only) + */ +@property (readonly) NSInteger minimum; + +/** + The size of each discrete offset on the scale. (read-only) + + The value of this property should be greater than zero. + The difference between `maximumValue` and `minimumValue` should be divisible + by the step value. + */ +@property (readonly) NSInteger step; + +/** + The default value for the slider. (read-only) + + If the value of this property is less than `minimum` or greater than `maximum`, the slider has no + default. Otherwise, the value is rounded to the nearest valid `step` value. + */ +@property (readonly) NSInteger defaultValue; + +/** + A Boolean value indicating whether the scale is oriented vertically. (read-only) + */ +@property (readonly, getter=isVertical) BOOL vertical; + +/** + A Boolean value indicating whether the selected value should be hidden. + */ +@property (assign, getter=shouldHideSelectedValueLabel) BOOL hideSelectedValue; + +/** + Number formatter applied to the minimum, maximum, and slider values. Can be overridden by + subclasses. + */ +@property (readonly) NSNumberFormatter *numberFormatter; + +/** + A localized label to describe the maximum value of the scale. (read-only) + */ +@property (readonly, nullable) NSString *maximumValueDescription; + +/** + A localized label to describe the minimum value of the scale. (read-only) + */ +@property (readonly, nullable) NSString *minimumValueDescription; + +/** + An image for the upper bound of the slider. The recommended image size is 30 x 30 points. + The maximum range label will not be visible. + */ +@property (strong, nullable) UIImage *maximumImage; + +/** + An image for the lower bound of the slider. The recommended image size is 30 x 30 points. + The minimum range label will not be visible. + */ +@property (strong, nullable) UIImage *minimumImage; + +/** + The colors to use when drawing a color gradient above the slider. Colors are drawn such that + lower indexes correspond to the minimum side of the scale, while colors at higher indexes in + the array corresond to the maximum side of the scale. + + Setting this value to nil results in no gradient being drawn. Defaults to nil. + + An example usage would set an array of red and green to visually indicate a scale from bad to good. + */ +@property (copy, nullable) NSArray *gradientColors; + +/** + Indicates the position of gradient stops for the colors specified in `gradientColors`. + Gradient stops are specified as values between 0 and 1. The values must be monotonically + increasing. + + If nil, the stops are spread uniformly across the range. Defaults to nil. + */ +@property (copy, nullable) NSArray *gradientLocations; + +/** + Determines if the minimum and maximum numbers are hidden on the slider. + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideRanges) BOOL hideRanges; + +/** + Determines if the bottom left and bottom right description labels are hidden + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideLabels) BOOL hideLabels; + +/** + Determines if the value markers on the slider are hidden + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideValueMarkers) BOOL hideValueMarkers; + +@end + + +/** + The `ORKContinuousScaleAnswerFormat` class represents an answer format that lets participants + select a value on a continuous scale. + + The continuous scale answer format produces an `ORKScaleQuestionResult` object that has a + real-number value. + */ +ORK_CLASS_AVAILABLE +@interface ORKContinuousScaleAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized continuous scale answer format using the specified values. + + This method is the designated initializer. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, + the slider is displayed without a default value. + @param maximumFractionDigits The maximum number of fractional digits to display. + @param vertical Pass `YES` to use a vertical scale; for the default horizontal + scale, pass `NO`. + @param maximumValueDescription A localized label to describe the maximum value of the scale. + For none, pass `nil`. + @param minimumValueDescription A localized label to describe the minimum value of the scale. + For none, pass `nil`. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription NS_DESIGNATED_INITIALIZER; + +/** + Returns an initialized continuous scale answer format using the specified values. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, the + slider is displayed without a default value. + @param maximumFractionDigits The maximum number of fractional digits to display. + @param vertical Pass `YES` to use a vertical scale; for the default horizontal scale, + pass `NO`. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical; + +/** + Returns an initialized horizontal continous scale answer format using the specified values. + + This method is a convenience initializer. + + @param maximumValue The upper bound of the scale. + @param minimumValue The lower bound of the scale. + @param defaultValue The default value of the scale. If this value is out of range, the + slider is displayed without a default value. + @param maximumFractionDigits The maximum number of fractional digits to display. + + @return An initialized scale answer format. + */ +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits; + +/** + The upper bound of the scale. (read-only) + */ +@property (readonly) double maximum; + +/** + The lower bound of the scale. (read-only) + */ +@property (readonly) double minimum; + +/** + The default value for the slider. (read-only) + + If the value of this property is less than `minimum` or greater than `maximum`, the slider has no + default value. + */ +@property (readonly) double defaultValue; + +/** + The maximum number of fractional digits to display. (read-only) + */ +@property (readonly) NSInteger maximumFractionDigits; + +/** + A Boolean value indicating whether the scale is oriented vertically. (read-only) + */ +@property (readonly, getter=isVertical) BOOL vertical; + +/** + A formatting style applied to the minimum, maximum, and slider values. + */ +@property ORKNumberFormattingStyle numberStyle; + +/** + A number formatter applied to the minimum, maximum, and slider values. Can be overridden by + subclasses. + */ +@property (readonly) NSNumberFormatter *numberFormatter; + +/** + A Boolean value indicating whether the selected value should be hidden. + */ +@property (assign, getter=shouldHideSelectedValueLabel) BOOL hideSelectedValue; + +/** + A localized label to describe the maximum value of the scale. (read-only) + */ +@property (readonly, nullable) NSString *maximumValueDescription; + +/** + A localized label to describe the minimum value of the scale. (read-only) + */ +@property (readonly, nullable) NSString *minimumValueDescription; + +/** + An image for the upper bound of the slider. + @discussion The recommended image size is 30 x 30 points. The maximum range label will not be visible. + */ +@property (strong, nullable) UIImage *maximumImage; + +/** + An image for the lower bound of the slider. + @discussion The recommended image size is 30 x 30 points. The minimum range label will not be visible. + */ +@property (strong, nullable) UIImage *minimumImage; + +/** + The colors to use when drawing a color gradient above the slider. Colors are drawn such that + lower indexes correspond to the minimum side of the scale, while colors at higher indexes in + the array corresond to the maximum side of the scale. + + Setting this value to nil results in no gradient being drawn. Defaults to nil. + + An example usage would set an array of red and green to visually indicate a scale from bad to good. + */ +@property (copy, nullable) NSArray *gradientColors; + +/** + Indicates the position of gradient stops for the colors specified in `gradientColors`. + Gradient stops are specified as values between 0 and 1. The values must be monotonically + increasing. + + If nil, the stops are spread uniformly across the range. Defaults to nil. + */ +@property (copy, nullable) NSArray *gradientLocations; + +/** + Determines if the minimum and maximum numbers are hidden on the slider. + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideRanges) BOOL hideRanges; + +/** + Determines if the bottom left and bottom right description labels are hidden + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideLabels) BOOL hideLabels; + +@end + + +/** + The `ORKTextScaleAnswerFormat` represents an answer format that includes a discrete slider control + with a text label next to each step. + + The scale answer format produces an `ORKChoiceQuestionResult` object that contains the selected text + choice's value. */ +ORK_CLASS_AVAILABLE +@interface ORKTextScaleAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized text scale answer format using the specified values. + + This method is the designated initializer. + + @param textChoices An array of text choices which will be used to determine the + number of steps in the slider, and + to fill the text label next to each of the steps. The array must + contain between 2 and 8 text choices. + @param defaultIndex The default index of the scale. If this value is out of range, + the slider is displayed without a default value. + @param vertical Pass `YES` to use a vertical scale; for the default horizontal + scale, pass `NO`. + @return An initialized text scale answer format. + */ +- (instancetype)initWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex + vertical:(BOOL)vertical NS_DESIGNATED_INITIALIZER; + +/** + Returns an initialized text scale answer format using the specified values. + + This method is a convenience initializer. + + @param textChoices An array of text choices which will be used to determine the + number of steps in the slider, and + to fill the text label next to each of the steps. The array must + contain between 2 and 8 text choices. + @param defaultIndex The default index of the scale. If this value is out of range, + the slider is displayed without a default value. + + @return An initialized text scale answer format. + */ +- (instancetype)initWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex; + +/** + An array of text choices which provides the text to be shown next to each of the slider steps. + (read-only) + */ +@property (copy, readonly) NSArray *textChoices; + +/** + The default index for the slider. (read-only) + + If the value of this property is less than zero or greater than the number of text choices, + the slider has no default value. + */ +@property (readonly) NSInteger defaultIndex; + +/** + A Boolean value indicating whether the scale is oriented vertically. (read-only) + */ +@property (readonly, getter=isVertical) BOOL vertical; + +/** + A Boolean value indicating whether the selected value should be hidden. + */ +@property (assign, getter=shouldHideSelectedValueLabel) BOOL hideSelectedValue; + +/** + The colors to use when drawing a color gradient above the slider. Colors are drawn such that + lower indexes correspond to the minimum side of the scale, while colors at higher indexes in + the array corresond to the maximum side of the scale. + + Setting this value to nil results in no gradient being drawn. Defaults to nil. + + An example usage would set an array of red and green to visually indicate a scale from bad to good. + */ +@property (copy, nullable) NSArray *gradientColors; + +/** + Indicates the position of gradient stops for the colors specified in `gradientColors`. + Gradient stops are specified as values between 0 and 1. The values must be monotonically + increasing. + + If nil, the stops are spread uniformly across the range. Defaults to nil. + */ +@property (copy, nullable) NSArray *gradientLocations; + +/** + Determines if the minimum and maximum numbers are hidden on the slider. + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideRanges) BOOL hideRanges; + +/** + Determines if the bottom left and bottom right description labels are hidden + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideLabels) BOOL hideLabels; + +/** + Determines if the value markers on the slider are hidden + + Defults to false. + */ +@property (nonatomic, assign, getter=shouldHideValueMarkers) BOOL hideValueMarkers; + +@end + + +/** + The `ORKValuePickerAnswerFormat` class represents an answer format that lets participants use a + value picker to choose from a fixed set of text choices. + + When the number of choices is relatively large and the text that describes each choice + is short, you might want to use the value picker answer format instead of the text choice answer + format (`ORKTextChoiceAnswerFormat`). When the text that describes each choice is long, or there + are only a very small number of choices, it's usually better to use the text choice answer format. + + Note that the value picker answer format reports itself as being of the single choice question + type. The value picker answer format produces an `ORKChoiceQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKValuePickerAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a value picker answer format using the specified array of text choices. + + Note that the `detailText` property of each choice is ignored. Be sure to create localized text for + each choice that is short enough to fit in a `UIPickerView` object. + + @param textChoices Array of `ORKTextChoice` objects. + + @return An initialized value picker answer format. + */ +- (instancetype)initWithTextChoices:(NSArray *)textChoices NS_DESIGNATED_INITIALIZER; + +/** + An array of text choices that represent the options to display in the picker. (read-only) + + Note that the `detailText` property of each choice is ignored. Be sure to create localized text for + each choice that is short enough to fit in a `UIPickerView` object. + */ +@property (copy, readonly) NSArray *textChoices; + +@end + + +/** + The `ORKMultipleValuePickerAnswerFormat` class represents an answer format that lets participants use a + multiple-component value picker to choose from a fixed set of text choices. + + Note that the multiple value picker answer format reports itself as being of the multiple picker question + type. The multiple-component value picker answer format produces an `ORKMultipleComponentQuestionResult` + object where the index into the array matches the array of `ORKValuePickerAnswerFormat` objects. + + For example, if the picker shows two columns with choices of `[[A, B, C], [1, 2, 3, 4]]` and the user picked + `B` and `3` then this would result in `componentsAnswer = [B, 3]`. + */ +ORK_CLASS_AVAILABLE +@interface ORKMultipleValuePickerAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a multiple value picker answer format using the specified array of value pickers. + + @param valuePickers Array of `ORKValuePickerAnswerFormat` objects. + + @return An initialized multiple value picker answer format. + */ +- (instancetype)initWithValuePickers:(NSArray *)valuePickers; + +/** + Returns a multiple value picker answer format using the specified array of value pickers. + + @param valuePickers Array of `ORKValuePickerAnswerFormat` objects. + @param separator String used to separate the components + + @return An initialized multiple value picker answer format. + */ +- (instancetype)initWithValuePickers:(NSArray *)valuePickers separator:(NSString *)separator NS_DESIGNATED_INITIALIZER; + +/** + An array of value pickers that represent the options to display in the picker. (read-only) + */ +@property (copy, readonly) NSArray *valuePickers; + +/** + A string used to define the separator for the format of the string. Default = " ". + */ +@property (copy, readonly) NSString *separator; + +@end + + +/** + The `ORKImageChoiceAnswerFormat` class represents an answer format that lets participants choose + one image from a fixed set of images in a single choice question. + + For example, you might use the image choice answer format to represent a range of moods that range + from very sad + to very happy. + + The image choice answer format produces an `ORKChoiceQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKImageChoiceAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized image choice answer format using the specified array of images. + + @param imageChoices Array of `ORKImageChoice` objects. + + @return An initialized image choice answer format. + */ +- (instancetype)initWithImageChoices:(NSArray *)imageChoices; + +/** + Returns an initialized image choice answer format using the specified array of images. + + @param imageChoices Array of `ORKImageChoice` objects. + @param style The style of question, such as single or multiple choice. + @param vertical Pass `YES` to stack images vertically; for the default horizontal + layout, pass `NO`. + + @return An initialized image choice answer format. + */ +- (instancetype)initWithImageChoices:(NSArray *)imageChoices + style:(ORKChoiceAnswerStyle)style + vertical:(BOOL)vertical NS_DESIGNATED_INITIALIZER; + +/** + An array of `ORKImageChoice` objects that represent the available choices. (read-only) + + The text of the currently selected choice is displayed on screen. The text for + each choice is spoken by VoiceOver when an image is highlighted. + */ +@property (copy, readonly) NSArray *imageChoices; + +/** + The style of the question (that is, single or multiple choice). + */ +@property (readonly) ORKChoiceAnswerStyle style; + +/** + A Boolean value indicating whether the choices are stacked vertically. (read-only) + */ +@property (readonly, getter=isVertical) BOOL vertical; + +@end + + +/** + The `ORKTextChoiceAnswerFormat` class represents an answer format that lets participants choose + from a fixed set of text choices in a multiple or single choice question. + + The text choices are presented in a table view, using one row for each answer. + The text for each answer is given more prominence than the `detailText` in the row, but + both are shown. + + The text choice answer format produces an `ORKChoiceQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextChoiceAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized text choice answer format using the specified question style and array of + text choices. + + @param style The style of question, such as single or multiple choice. + @param textChoices An array of `ORKTextChoice` objects. + + @return An initialized text choice answer format. + */ +- (instancetype)initWithStyle:(ORKChoiceAnswerStyle)style + textChoices:(NSArray *)textChoices NS_DESIGNATED_INITIALIZER; + +/** + The style of the question (that is, single or multiple choice). + */ +@property (readonly) ORKChoiceAnswerStyle style; + +/** + An array of `ORKTextChoice` objects that represent the choices that are displayed to participants. + + The choices are presented as a table view, using one row for each answer. + The text for each answer is given more prominence than the `detailText` in the row, but + both are shown. + */ +@property (copy, readonly) NSArray *textChoices; + +@end + + +/** + The `ORKBooleanAnswerFormat` class behaves the same as the `ORKTextChoiceAnswerFormat` class, + except that it is preconfigured to use only Yes and No answers. + + The Boolean answer format produces an `ORKBooleanQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKBooleanAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized Boolean answer format using the specified strings for Yes and No answers. + + @param yes A string that describes the Yes answer. + @param no A string that describes the No answer. + + @return An initialized Boolean answer format. + */ +- (instancetype)initWithYesString:(NSString *)yes noString:(NSString *)no; + +/** + The string to describe the Yes answer. (read-only) + */ +@property (copy, readonly) NSString *yes; + +/** + The string to describe the No answer. (read-only) + */ +@property (copy, readonly) NSString *no; + +@end + + +/** + The `ORKTextChoice` class defines the text for a choice in answer formats such + as `ORKTextChoiceAnswerFormat` and `ORKValuePickerAnswerFormat`. + + When a participant chooses a text choice item, the value recorded in a result + is specified by the `value` property. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextChoice : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a text choice object that includes the specified primary text or text with string attributes, detail text or text with string attributes, and exclusivity. + + @param text The primary text that describes the choice in a localized string. + @param primaryTextAttributedString The primary text that describes the choice in an attributed string. Setting this will override `text`. + @param detailText The detail text to display below the primary text, in a localized string. + @param detailTextAttributedString The detail text to display below the primary text, in an attributed string. Setting this will override `detailText`. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + + @return A text choice instance. + */ ++ (instancetype)choiceWithText:(nullable NSString *)text primaryTextAttributedString:(nullable NSAttributedString *)primaryTextAttributedString detailText:(nullable NSString *)detailText detailTextAttributedString:(nullable NSAttributedString *)detailTextAttributedString value:(id)value exclusive:(BOOL)exclusive; + +/** + Returns a text choice object that includes the specified primary text, detail text, + and exclusivity. + + @param text The primary text that describes the choice in a localized string. + @param detailText The detail text to display below the primary text, in a localized string. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + + @return A text choice instance. + */ ++ (instancetype)choiceWithText:(NSString *)text detailText:(nullable NSString *)detailText value:(id)value exclusive:(BOOL)exclusive; + +/** + Returns a choice object that includes the specified primary text. + + @param text The primary text that describes the choice in a localized string. + @param value The value to record in a result object when this item is selected. + + @return A text choice instance. + */ ++ (instancetype)choiceWithText:(NSString *)text value:(id)value; + +/** + Returns an initialized text choice object using the specified primary text, detail text, + and exclusivity. + + @param text The primary text that describes the choice in a localized string. + @param detailText The detail text to display below the primary text, in a localized string. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + + @return An initialized text choice. + */ +- (instancetype)initWithText:(NSString *)text + detailText:(nullable NSString *)detailText + value:(id)value + exclusive:(BOOL)exclusive; + +/** + Returns an initialized text choice object using the specified primary text or text with string attributes, detail text or text with string attributes, and exclusivity. + + This method is the designated initializer. + + @param text The primary text that describes the choice in a localized string. + @param primaryTextAttributedString The primary text that describes the choice in an attributed string. Setting this will override `text`. + @param detailText The detail text to display below the primary text, in a localized string. + @param detailTextAttributedString The detail text to display below the primary text, in an attributed string. Setting this will override `detailText`. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + + @return An initialized text choice. + */ +- (instancetype)initWithText:(nullable NSString *)text + primaryTextAttributedString:(nullable NSAttributedString *)primaryTextAttributedString + detailText:(nullable NSString *)detailText + detailTextAttributedString:(nullable NSAttributedString *)detailTextAttributedString + value:(id)value + exclusive:(BOOL)exclusive NS_DESIGNATED_INITIALIZER; + +/** + The text that describes the choice in a localized string. + + In general, it's best when the text can fit on one line. + */ +@property (copy, readonly) NSString *text; + +/** + The text that describes the choice in an attributed string. + + In general, it's best when the text can fit on one line. + */ +@property (copy, readonly, nullable) NSAttributedString *primaryTextAttributedString; + +/** + The value to return when this choice is selected. + + The value of this property is expected to be a scalar property list type, such as `NSNumber` + or `NSString`. If no value is provided, the index of the option in the options list in the + answer format is used. + */ +@property (copy, readonly) id value; + +/** + The text that provides additional details about the choice in a localized string. + + The detail text can span multiple lines. Note that `ORKValuePickerAnswerFormat` ignores detail + text. + */ +@property (copy, readonly, nullable) NSString *detailText; + +/** + The text that provides additional details about the choice in an attributed string. + + The detail text can span multiple lines. Note that `ORKValuePickerAnswerFormat` ignores detail + text. + */ +@property (copy, readonly, nullable) NSAttributedString *detailTextAttributedString; + +/** + In a multiple choice format, this indicates whether this choice requires all other choices to be + unselected. + + In general, this is used to indicate a "None of the above" choice. + */ +@property (readonly) BOOL exclusive; + +@end + + +/** + The `ORKTextChoiceOther` class defines the choice option to describe an answer not + included in provided choices. + + The `ORKTextChoiceOther` provides an optional text view of type `ORKAnswerTextView` that allows users to enter free form text. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextChoiceOther : ORKTextChoice + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a text choice other object that includes the specified text, detail text, exclusivity and a text view with placeholder text for additional user input. + + @param text The primary text that describes the choice in a localized string. + @param detailText The detail text to display below the primary text, in a localized string. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + @param textViewPlaceholderText The placeholder text for the text view. + + @return A text choice other instance. + */ ++ (instancetype)choiceWithText:(nullable NSString *)text + detailText:(nullable NSString *)detailText + value:(id)value + exclusive:(BOOL)exclusive + textViewPlaceholderText:(NSString *)textViewPlaceholderText; + +/** + Returns an initialized text choice other object using the specified primary text or text with string attributes, detail text or text with string attributes, exclusivity and an optional view for free form text entry. + + This method is the designated initializer. + + @param text The primary text that describes the choice in a localized string. + @param primaryTextAttributedString The primary text that describes the choice in an attributed string. Setting this will override `text`. + @param detailText The detail text to display below the primary text, in a localized string. + @param detailTextAttributedString The detail text to display below the primary text, in an attributed string. Setting this will override `detailText`. + @param value The value to record in a result object when this item is selected. + @param exclusive Whether this choice is to be considered exclusive within the set of choices. + @param textViewPlaceholderText The placeholder text for the text view. + @param textViewInputOptional Whether the user is required to provide additional text when selecting this choice. + @param textViewStartsHidden Whether the text view should be hidden untill the cell is selected. + + @return An initialized text choice other object. + */ +- (instancetype)initWithText:(nullable NSString *)text + primaryTextAttributedString:(nullable NSAttributedString *)primaryTextAttributedString + detailText:(nullable NSString *)detailText + detailTextAttributedString:(nullable NSAttributedString *)detailTextAttributedString + value:(id)value + exclusive:(BOOL)exclusive + textViewPlaceholderText:(NSString *)textViewPlaceholderText + textViewInputOptional:(BOOL)textViewInputOptional + textViewStartsHidden:(BOOL)textViewStartsHidden; + +@property (copy, readonly, nullable) NSString *textViewPlaceholderText; + +@property (readonly) BOOL textViewInputOptional; + +@property (readonly) BOOL textViewStartsHidden; + +@end + + +/** + The `ORKImageChoice` class defines a choice that can + be included in an `ORKImageChoiceAnswerFormat` object. + + Typically, image choices are displayed in a horizontal row, so you need to use appropriate sizes. + For example, when five image choices are displayed in an `ORKImageChoiceAnswerFormat`, image sizes + of about 45 to 60 points allow the images to look good in apps that run on all versions of iPhone. + + The text that describes an image choice should be reasonably short. However, only the text for the + currently selected image choice is displayed, so text that wraps to more than one line + is supported. + */ +ORK_CLASS_AVAILABLE +@interface ORKImageChoice : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an image choice that includes the specified images and text. + + @param normal The image to display in the unselected state. + @param selected The image to display in the selected state. + @param text The text to display when the image is selected. + @param value The value to record in a result object when the image is selected. + + @return An image choice instance. + */ ++ (instancetype)choiceWithNormalImage:(nullable UIImage *)normal + selectedImage:(nullable UIImage *)selected + text:(nullable NSString *)text + value:(id)value; + +/** + Returns an initialized image choice using the specified images and text. + + This method is the designated initializer. + + @param normal The image to display in the unselected state. + @param selected The image to display in the selected state. + @param text The text to display when the image is selected. + @param value The value to record in a result object when the image is selected. + + @return An initialized image choice. + */ +- (instancetype)initWithNormalImage:(nullable UIImage *)normal + selectedImage:(nullable UIImage *)selected + text:(nullable NSString *)text + value:(id)value NS_DESIGNATED_INITIALIZER; + +/** + The image to display when the choice is not selected. (read-only) + + The size of the unselected image depends on the number of choices you need to display. As a + general rule, it's recommended that you start by creating an image that measures 44 x 44 points, + and adjust it if necessary. + */ +@property (strong, readonly) UIImage *normalStateImage; + +/** + The image to display when the choice is selected. (read-only) + + For best results, the selected image should be the same size as the unselected image (that is, + the value of the `normalStateImage` property). + If you don't specify a selected image, the default `UIButton` behavior is used to + indicate the selection state of the item. + */ +@property (strong, readonly, nullable) UIImage *selectedStateImage; + +/** + The text to display when the image is selected, in a localized string. (read-only) + + Note that the text you supply may be spoken by VoiceOver even when the item is not selected. + */ +@property (copy, readonly, nullable) NSString *text; + +/** + The value to return when the image is selected. (read-only) + + The value of this property is expected to be a scalar property list type, such as `NSNumber` or + `NSString`. If no value is provided, the index of the option in the `ORKImageChoiceAnswerFormat` + options list is used. + */ +@property (copy, readonly) id value; + +@end + + +/** + The style of answer for an `ORKNumericAnswerFormat` object, which controls the keyboard that is + presented during numeric entry. + */ +typedef NS_ENUM(NSInteger, ORKNumericAnswerStyle) { + + /** + A decimal question type asks the participant to enter a decimal number. + */ + ORKNumericAnswerStyleDecimal, + + /** + An integer question type asks the participant to enter an integer number. + */ + ORKNumericAnswerStyleInteger +} ORK_ENUM_AVAILABLE; + +/** + The `ORKNumericAnswerFormat` class defines the attributes for a numeric + answer format that participants enter using a numeric keyboard. + + If you specify maximum or minimum values and the user enters a value outside the + specified range, the question step view controller does not allow navigation + until the participant provides a value that is within the valid range. + + Questions and form items that use this answer format produce an + `ORKNumericQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKNumericAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized numeric answer format using the specified style. + + @param style The style of the numeric answer (decimal or integer). + + @return An initialized numeric answer format. + */ +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style; + +/** + Returns an initialized numeric answer format using the specified style and unit designation. + + @param style The style of the numeric answer (decimal or integer). + @param unit A string that displays a localized version of the unit designation. + + @return An initialized numeric answer format. + */ +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style + unit:(nullable NSString *)unit; + +/** +Returns an initialized numeric answer format using the specified style, unit designation, and range + values. + + @param style The style of the numeric answer (decimal or integer). + @param unit A string that displays a localized version of the unit designation. + @param minimum The minimum value to apply, or `nil` if none is specified. + @param maximum The maximum value to apply, or `nil` if none is specified. + + @return An initialized numeric answer format. + */ +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style + unit:(nullable NSString *)unit + minimum:(nullable NSNumber *)minimum + maximum:(nullable NSNumber *)maximum; + +/** + Returns an initialized numeric answer format using the specified style, unit designation, range + values, and precision. + + This method is the designated initializer. + + @param style The style of the numeric answer (decimal or integer). + @param unit A string that displays a localized version of the unit designation. + @param minimum The minimum value to apply, or `nil` if none is specified. + @param maximum The maximum value to apply, or `nil` if none is specified. + @param maximumFractionDigits The maximum fraction digits, or `nil` if no maximum is specified. + + @return An initialized numeric answer format. + */ +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style + unit:(nullable NSString *)unit + minimum:(nullable NSNumber *)minimum + maximum:(nullable NSNumber *)maximum + maximumFractionDigits:(nullable NSNumber *)maximumFractionDigits NS_DESIGNATED_INITIALIZER; + +/** + The style of numeric entry (decimal or integer). (read-only) + */ +@property (readonly) ORKNumericAnswerStyle style; + +/** + A string that displays a localized version of the unit designation next to the numeric value. + (read-only) + + Examples of unit designations are days, lbs, and liters. + The unit string is included in the `ORKNumericQuestionResult` object. + */ +@property (copy, readonly, nullable) NSString *unit; + +/** + The minimum allowed value for the numeric answer. + + The default value of this property is `nil`, which means that no minimum value is displayed. + */ +@property (copy, nullable) NSNumber *minimum; + +/** + The maximum allowed value for the numeric answer. + + The default value of this property is `nil`, which means that no maximum value is displayed. + */ +@property (copy, nullable) NSNumber *maximum; + +/** + The maximum number of fraction digits to the right of the decimal point for the + numeric answer. + + The default value of this property is `nil`, which means that there's no maximum number of fraction + digits. + */ +@property (copy, nullable) NSNumber *maximumFractionDigits; + +/** + The default numeric answer. + */ +@property (copy, nullable) NSNumber *defaultNumericAnswer; + +/** + A property that specifies whether the unit is hidden when the answer is empty. + + Defaults to `YES`. + */ +@property (assign) BOOL hideUnitWhenAnswerIsEmpty; + +/** +The placeholder to dislpay when the answer is empty. + +Overrides any specified step placeholder. Setting it to `nil` displays the default placeholeder. +*/ +@property (copy, nullable) NSString *placeholder; + +@end + + +/** + The `ORKTimeOfDayAnswerFormat` class represents the answer format for questions that require users + to enter a time of day. + + A time of day answer format produces an `ORKTimeOfDayQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKTimeOfDayAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized time of day answer format using the specified default value. + + This method is the designated initializer. + + @param defaultComponents The default value with which to configure the picker. + + @return An initialized time of day answer format. + */ +- (instancetype)initWithDefaultComponents:(nullable NSDateComponents *)defaultComponents NS_DESIGNATED_INITIALIZER; + +/** + The default time of day to display in the picker. (read-only) + + Note that both the hour and minute components are observed. If the value of this property is `nil`, + the picker displays the current time of day. + */ +@property (nonatomic, copy, readonly, nullable) NSDateComponents *defaultComponents; + +/** + The interval at which the date picker should display minutes. + + When the value of this property is not explicitly set, the picker defaults to an interval of + one minute. + */ +@property (nonatomic) NSInteger minuteInterval; + +@end + + +/** + The style of date picker to use in an `ORKDateAnswerFormat` object. + */ +typedef NS_ENUM(NSInteger, ORKDateAnswerStyle) { + + /** + The date and time question type asks participants to choose a time or a combination of date + and time, from a picker. + */ + ORKDateAnswerStyleDateAndTime, + + /** + The date question type asks participants to choose a particular date from a picker. + */ + ORKDateAnswerStyleDate +} ORK_ENUM_AVAILABLE; + +/** + The `ORKDateAnswerFormat` class represents the answer format for questions that require users + to enter a date, or a date and time. + + A date answer format produces an `ORKDateQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKDateAnswerFormat : ORKAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized date answer format using the specified date style. + + @param style The style of date answer, such as date, or date and time. + + @return An initialized date answer format. + */ +- (instancetype)initWithStyle:(ORKDateAnswerStyle)style; + +/** + Returns an initialized date answer format using the specified answer style and default date values. + + This method is the designated initializer. + + @param style The style of date answer, such as date, or date and time. + @param defaultDate The default date to display. When the value of this parameter is `nil`, the + picker displays the current time. + @param minimumDate The minimum date that is accessible in the picker. If the value of this + parameter is `nil`, there is no minimum. + @param maximumDate The maximum date that is accessible in the picker. If the value of this + parameter is `nil`, there is no maximum. + @param calendar The calendar to use. If the value of this parameter is `nil`, the picker + uses the default calendar for the current locale. + + @return An initialized date answer format. + */ +- (instancetype)initWithStyle:(ORKDateAnswerStyle)style + defaultDate:(nullable NSDate *)defaultDate + minimumDate:(nullable NSDate *)minimumDate + maximumDate:(nullable NSDate *)maximumDate + calendar:(nullable NSCalendar *)calendar NS_DESIGNATED_INITIALIZER; + +/** + The style of date entry. + */ +@property (readonly) ORKDateAnswerStyle style; + +/** + The date to use as the default. + + The date is displayed in the user's time zone. + When the value of this property is `nil`, the current time is used as the default. + */ +@property (copy, readonly, nullable) NSDate *defaultDate; + +/** + The minimum allowed date. + +When the value of this property is `nil`, there is no minimum. + */ +@property (copy, readonly, nullable) NSDate *minimumDate; + +/** + The maximum allowed date. + + When the value of this property is `nil`, there is no maximum. + */ +@property (copy, readonly, nullable) NSDate *maximumDate; + +/** + The calendar to use in the picker. + + When the value of this property is `nil`, the picker uses the default calendar for the current + locale. + */ +@property (copy, readonly, nullable) NSCalendar *calendar; + +/** + The interval at which the date picker should display minutes. + + When the value of this property is not explicitly set, the picker defaults to an interval of + one minute. + */ +@property (nonatomic) NSInteger minuteInterval; + +@end + + +/** + The `ORKTextAnswerFormat` class represents the answer format for questions that collect a text + response + from the user. + + An `ORKTextAnswerFormat` object produces an `ORKTextQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized text answer format using the regular expression. + + This method is one of the designated initializers. + + @param validationRegularExpression The regular expression used to validate the text. + @param invalidMessage The text presented to the user when invalid input is received. + + @return An initialized validated text answer format. + */ +- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage NS_DESIGNATED_INITIALIZER; + +/** + Returns an initialized text answer format using the specified maximum string length. + + This method is one of the designated initializers. + + @param maximumLength The maximum number of characters to accept. When the value of this parameter + is 0, there is no maximum. + + @return An initialized text answer format. + */ +- (instancetype)initWithMaximumLength:(NSInteger)maximumLength NS_DESIGNATED_INITIALIZER; + +/** + The regular expression used to validate user's input. + + The default value is nil. If set to nil, no validation will be performed. + */ +@property (nonatomic, copy, nullable) NSRegularExpression *validationRegularExpression; + +/** + The text presented to the user when invalid input is received. + + The default value is nil. + */ +@property (nonatomic, copy, nullable) NSString *invalidMessage; + +/** + The text to be used as an answer if user input is not mandatory. + + The default value is nil. If set to nil, user input is mandatory to answer. + */ +@property (nonatomic, copy, nullable) NSString *defaultTextAnswer; + +/** + The maximum length of the text users can enter. + + When the value of this property is 0, there is no maximum. + */ +@property NSInteger maximumLength; + +/** + A Boolean value indicating whether to expect more than one line of input. + + By default, the value of this property is `YES`. + */ +@property BOOL multipleLines; + +/** + The autocapitalization type that applies to the user's input. + + By default, the value of this property is `UITextAutocapitalizationTypeSentences`. + */ +@property UITextAutocapitalizationType autocapitalizationType; + +/** + The autocorrection type that applies to the user's input. + + By default, the value of this property is `UITextAutocorrectionTypeDefault`. + */ +@property UITextAutocorrectionType autocorrectionType; + +/** + The spell checking type that applies to the user's input. + + By default, the value of this property is `UITextSpellCheckingTypeDefault`. + */ +@property UITextSpellCheckingType spellCheckingType; + +/** + The keyboard type that applies to the user's input. + + By default, the value of this property is `UIKeyboardTypeDefault`. + */ +@property UIKeyboardType keyboardType; + +/** + The semantic UITextContentType that applies to the user's input. + + If specified the system can improve keyboard suggestions to help with filling forms and other + input. By default, the value of this property is `nil` meaning no specific type. + */ +@property (nonatomic, copy, nullable) UITextContentType textContentType; + +/** + The password generation rules to use for Automatic Secure Passwords. + + If specified, overrides the default passsword generation rules for fields with secureTextEntry. + */ +@property (nonatomic, copy, nullable) UITextInputPasswordRules *passwordRules API_AVAILABLE(ios(12)); + +/** + Identifies whether the text object should hide the text being entered. + + By default, the value of this property is NO. + */ +@property (nonatomic,getter=isSecureTextEntry) BOOL secureTextEntry; + +/** + The placeholder to dislpay when the answer is empty. + + Overrides any specified step placeholder. Setting it to `nil` displays the default placeholeder. + */ +@property (copy, nullable) NSString *placeholder; + +@end + + +/** + The `ORKEmailAnswerFormat` class represents the answer format for questions that collect an email + response from the user. + + An `ORKEmailAnswerFormat` object produces an `ORKTextQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKEmailAnswerFormat : ORKAnswerFormat + +/** + Identifies whether this email answer format is being used as a username. + + For integration with iOS 12's password management functionality. Use this answer format if your + username is also an email address, if it is not guaranteed to be an email address, use + `ORKTextAnswerFormat` and set the `textContentType` to `UITextContentTypeUsername`. + + By default, the value of this property is NO. + */ +@property (nonatomic,getter=isUsernameField) BOOL usernameField; + +@end + + +/** + The `ORKTimeIntervalAnswerFormat` class represents the answer format for questions that ask users + to specify a time interval. + + The time interval answer format is suitable for time intervals up to 24 hours. If you need to track + time intervals of longer duration, use a different answer format, such as + `ORKValuePickerAnswerFormat`. + + Note that the time interval answer format does not support the selection of 0. + + A time interval answer format produces an `ORKTimeIntervalQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKTimeIntervalAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized time interval answer format using the specified default interval and step + value. + + This method is the designated initializer. + + @param defaultInterval The default value to display in the picker. + @param step The step in the interval, in minutes. The value of this parameter must + be between 1 and 30. + + @return An initialized time interval answer format. + */ +- (instancetype)initWithDefaultInterval:(NSTimeInterval)defaultInterval + step:(NSInteger)step NS_DESIGNATED_INITIALIZER; + +/** + The initial time interval displayed in the picker. + */ +@property (readonly) NSTimeInterval defaultInterval; + +/** + The size of the allowed step in the interval, in minutes. + + By default, the value of this property is 1. The minimum value is 1, and the maximum value is 30. + */ +@property (readonly) NSInteger step; + +@end + + +/** + The `ORKHeightAnswerFormat` class represents the answer format for questions that require users + to enter a height. + + A height answer format produces an `ORKNumericQuestionResult` object. The result is always reported + in the metric system using the `cm` unit. + */ +ORK_CLASS_AVAILABLE +@interface ORKHeightAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized height answer format using the measurement system specified in the current + locale. + + @return An initialized height answer format. + */ +- (instancetype)init; + +/** + Returns an initialized height answer format using the specified measurement system. + + This method is the designated initializer. + + @param measurementSystem The measurement system to use. See `ORKMeasurementSystem` for the + accepted values. + + @return An initialized height answer format. + */ +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem NS_DESIGNATED_INITIALIZER; + +/** + The measurement system used by the answer format. + */ +@property (readonly) ORKMeasurementSystem measurementSystem; + +@end + + +/** + The `ORKWeightAnswerFormat` class represents the answer format for questions that require users + to enter a weight. + + A weight answer format produces an `ORKNumericQuestionResult` object. The result is always reported + in the metric system using the `kg` unit. + */ +ORK_CLASS_AVAILABLE +@interface ORKWeightAnswerFormat : ORKAnswerFormat + +/** + Returns an initialized weight answer format using the measurement system specified in the current + locale. + + @return An initialized weight answer format. + */ +- (instancetype)init; + +/** + Returns an initialized weight answer format using the specified measurement system. + + This method is the designated initializer. + + @param measurementSystem The measurement system to use. See `ORKMeasurementSystem` for the + accepted values. + + @return An initialized weight answer format. + */ +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem; + +/** + Returns an initialized weight answer format using the specified measurement system and numeric + precision. + + @param measurementSystem The measurement system to use. See `ORKMeasurementSystem` for the + accepted values. + @param numericPrecision The numeric precision used by the picker. If you pass + `ORKNumericPrecisionDefault`, the picker will use 0.5 kg + increments for the metric measurement system and whole pound + increments for the USC measurement system, which mimics the + default iOS behavior. If you pass `ORKNumericPrecisionLow`, the + picker will use 1 kg increments for the metric measurement + system and whole pound increments for the USC measurement + system. If you pass `ORKNumericPrecisionHigher`, the picker + use 0.01 gr increments for the metric measurement system, + and ounce increments for the USC measurement system. + + @return An initialized weight answer format. + */ +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision; + +/** + Returns an initialized weight answer format using the specified measurement system, numeric + precision, and default, minimum and maximum values. + + @param measurementSystem The measurement system to use. See `ORKMeasurementSystem` for the + accepted values. + @param numericPrecision The numeric precision used by the picker. If you pass + `ORKNumericPrecisionDefault`, the picker will use 0.5 kg + increments for the metric measurement system and whole pound + increments for the USC measurement system, which mimics the + default iOS behavior. If you pass `ORKNumericPrecisionLow`, the + picker will use 1 kg increments for the metric measurement + system and whole pound increments for the USC measurement + system. If you pass `ORKNumericPrecisionHigher`, the picker + use 0.01 gr increments for the metric measurement system, + and ounce increments for the USC measurement system. + @param minimumValue The minimum value that is displayed in the picker. If you specify + `ORKDefaultValue`, the minimum values are 0 kg when using the + metric measurement system and 0 lbs when using the USC + measurement system. + @param maximumValue The maximum value that is displayed in the picker. If you specify + `ORKDefaultValue`, the maximum values are 657 kg when using the + metric measurement system and 1,450 lbs when using the USC + measurement system. + @param defaultValue The default value to be initially selected in the picker. If you + specify `ORKDefaultValue`, the initally selected values are + 60 kg when using the metric measurement system and 133 lbs when + using the USC measurement system. This value must be between + `minimumValue` and `maximumValue`. + + @return An initialized weight answer format. + */ +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision + minimumValue:(double)minimumValue + maximumValue:(double)maximumValue + defaultValue:(double)defaultValue NS_DESIGNATED_INITIALIZER; + +/** + Indicates the measurement system used by the answer format. + */ +@property (readonly) ORKMeasurementSystem measurementSystem; + +/** + The numeric precision used by the picker. + + An `ORKNumericPrecisionDefault` value indicates that the picker will use 0.5 kg increments for the + metric measurement system and whole pound increments for the USC measurement system, which mimics + the default iOS behavior. An `ORKNumericPrecisionLow` value indicates that the picker will use + 1 kg increments for the metric measurement system and whole pound increments for the USC + measurement system. An `ORKNumericPrecisionHigher` value indicates that the picker will use + 0.01 gr increments for the metric measurement system and ounce increments for the USC measurement + system. + + The default value of this property is `ORKNumericPrecisionDefault`. + */ +@property (readonly, getter=isAdditionalPrecision) ORKNumericPrecision numericPrecision; + +/** + The minimum value that is displayed in the picker. + + When this property has a value equal to `ORKDefaultValue`, the minimum values are 0 kg when using + the metric measurement system and 0 lbs when using the USC measurement system. + */ +@property (readonly) double minimumValue; + +/** + The maximum value that is displayed in the picker. + + When this property has a value equal to `ORKDefaultValue`, the maximum values are 657 kg when using + the metric measurement system and 1,450 lbs when using the USC measurement system. + */ +@property (readonly) double maximumValue; + +/** + The default value to initially selected in the picker. + + When this property has a value equal to `ORKDefaultValue`, the initally selected values are 60 kg + when using the metric measurement system and 133 lbs when using the USC measurement system. This + value must be between `minimumValue` and `maximumValue`. + */ +@property (readonly) double defaultValue; + +@end + + +/** + The `ORKLocationAnswerFormat` class represents the answer format for questions that collect a location response + from the user. + + An `ORKLocationAnswerFormat` object produces an `ORKLocationQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKLocationAnswerFormat : ORKAnswerFormat + +/** + Indicates whether or not the user's current location should be automatically entered the first time they tap on the input field. + + By default, this value is YES. + */ +@property (nonatomic, assign) BOOL useCurrentLocation; + +/** + The placeholder to dislpay when the answer is empty. + + Overrides any specified step placeholder. Setting it to `nil` displays the default placeholeder. + */ +@property (copy, nullable) NSString *placeholder; + +@end + +/** + Socio-Economic Ladder Answer Format. + + This answer format works best in ORKFormStep, there is a known issue where the cell might get squished if presented inside an ORKQuestionStep. + */ +ORK_CLASS_AVAILABLE +@interface ORKSESAnswerFormat : ORKAnswerFormat + +- (instancetype)initWithTopRungText:(nullable NSString *)topRungText bottomRungText:(nullable NSString *)bottomRungText; + +@property (nonatomic, nullable) NSString *topRungText; +@property (nonatomic, nullable) NSString *bottomRungText; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.m new file mode 100755 index 0000000..da79390 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat.m @@ -0,0 +1,3427 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Scott Guelich. + Copyright (c) 2016, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Medable Inc. All rights reserved. + Copyright (c) 2017, Macro Yau. + Copyright (c) 2017, Sage Bionetworks. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAnswerFormat.h" +#import "ORKAnswerFormat_Internal.h" + +#import "ORKChoiceAnswerFormatHelper.h" +#import "ORKHealthAnswerFormat.h" +#import "ORKQuestionResult_Private.h" +#import "ORKResult_Private.h" + +#import "ORKHelpers_Internal.h" + +@import HealthKit; +@import MapKit; +@import Contacts; + +NSString *const EmailValidationRegularExpressionPattern = @"^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$"; + +id ORKNullAnswerValue() { + return [NSNull null]; +} + +BOOL ORKIsAnswerEmpty(id answer) { + return (answer == nil) || + (answer == ORKNullAnswerValue()) || + ([answer isKindOfClass:[NSArray class]] && ((NSArray *)answer).count == 0); // Empty answer of choice or value picker +} + +NSString *ORKQuestionTypeString(ORKQuestionType questionType) { +#define SQT_CASE(x) case ORKQuestionType ## x : return @ORK_STRINGIFY(ORKQuestionType ## x); + switch (questionType) { + SQT_CASE(None); + SQT_CASE(Scale); + SQT_CASE(SingleChoice); + SQT_CASE(MultipleChoice); + SQT_CASE(MultiplePicker); + SQT_CASE(Decimal); + SQT_CASE(Integer); + SQT_CASE(Boolean); + SQT_CASE(Text); + SQT_CASE(DateAndTime); + SQT_CASE(TimeOfDay); + SQT_CASE(Date); + SQT_CASE(TimeInterval); + SQT_CASE(Height); + SQT_CASE(Weight); + SQT_CASE(Location); + SQT_CASE(SES); + } +#undef SQT_CASE +} + +static NSNumberFormatterStyle ORKNumberFormattingStyleConvert(ORKNumberFormattingStyle style) { + return style == ORKNumberFormattingStylePercent ? NSNumberFormatterPercentStyle : NSNumberFormatterDecimalStyle; +} + + +@implementation ORKAnswerDefaultSource { + NSMutableDictionary *_unitsTable; +} + +@synthesize healthStore=_healthStore; + ++ (instancetype)sourceWithHealthStore:(HKHealthStore *)healthStore { + ORKAnswerDefaultSource *source = [[ORKAnswerDefaultSource alloc] initWithHealthStore:healthStore]; + return source; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} +#pragma clang diagnostic pop + +- (instancetype)initWithHealthStore:(HKHealthStore *)healthStore { + self = [super init]; + if (self) { + _healthStore = healthStore; + + if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 2, .patchVersion = 0}]) { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(healthKitUserPreferencesDidChange:) + name:HKUserPreferencesDidChangeNotification + object:healthStore]; + } + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)healthKitUserPreferencesDidChange:(NSNotification *)notification { + _unitsTable = nil; +} + +- (id)defaultValueForCharacteristicType:(HKCharacteristicType *)characteristicType error:(NSError **)errorOut { + id result = nil; + if ([[characteristicType identifier] isEqualToString:HKCharacteristicTypeIdentifierDateOfBirth]) { + NSDate *dob = [[NSCalendar currentCalendar] dateFromComponents:[_healthStore dateOfBirthComponentsWithError:errorOut]]; + if (dob) { + result = dob; + } + } + if ([[characteristicType identifier] isEqualToString:HKCharacteristicTypeIdentifierBloodType]) { + HKBloodTypeObject *bloodType = [_healthStore bloodTypeWithError:errorOut]; + if (bloodType && bloodType.bloodType != HKBloodTypeNotSet) { + result = ORKHKBloodTypeString(bloodType.bloodType); + } + if (result) { + result = @[result]; + } + } + if ([[characteristicType identifier] isEqualToString:HKCharacteristicTypeIdentifierBiologicalSex]) { + HKBiologicalSexObject *biologicalSex = [_healthStore biologicalSexWithError:errorOut]; + if (biologicalSex && biologicalSex.biologicalSex != HKBiologicalSexNotSet) { + result = ORKHKBiologicalSexString(biologicalSex.biologicalSex); + } + if (result) { + result = @[result]; + } + } + if ([[characteristicType identifier] isEqualToString:HKCharacteristicTypeIdentifierFitzpatrickSkinType]) { + HKFitzpatrickSkinTypeObject *skinType = [_healthStore fitzpatrickSkinTypeWithError:errorOut]; + if (skinType && skinType.skinType != HKFitzpatrickSkinTypeNotSet) { + result = @(skinType.skinType); + } + if (result) { + result = @[result]; + } + } + if (ORK_IOS_10_WATCHOS_3_AVAILABLE && [[characteristicType identifier] isEqualToString:HKCharacteristicTypeIdentifierWheelchairUse]) { + HKWheelchairUseObject *wheelchairUse = [_healthStore wheelchairUseWithError:errorOut]; + if (wheelchairUse && wheelchairUse.wheelchairUse != HKWheelchairUseNotSet) { + result = (wheelchairUse.wheelchairUse == HKWheelchairUseYes) ? @YES : @NO; + } + if (result) { + result = @[result]; + } + } + return result; +} + +- (void)fetchDefaultValueForQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit handler:(void(^)(id defaultValue, NSError *error))handler { + if (!unit) { + handler(nil, nil); + return; + } + + HKHealthStore *healthStore = _healthStore; + NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO]; + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + HKSampleQuery *sampleQuery = [[HKSampleQuery alloc] initWithSampleType:quantityType predicate:nil limit:1 sortDescriptors:@[sortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) { + HKQuantitySample *sample = results.firstObject; + id value = nil; + if (sample) { + if (unit == [HKUnit percentUnit]) { + value = @(100 * [sample.quantity doubleValueForUnit:unit]); + } else { + value = @([sample.quantity doubleValueForUnit:unit]); + } + } + handler(value, error); + }]; + [healthStore executeQuery:sampleQuery]; + }); +} + +- (void)fetchDefaultValueForAnswerFormat:(ORKAnswerFormat *)answerFormat handler:(void(^)(id defaultValue, NSError *error))handler { + HKObjectType *objectType = [answerFormat healthKitObjectType]; + BOOL handled = NO; + if (objectType) { + if ([HKHealthStore isHealthDataAvailable]) { + if ([answerFormat isKindOfClass:[ORKHealthKitCharacteristicTypeAnswerFormat class]]) { + NSError *error = nil; + id defaultValue = [self defaultValueForCharacteristicType:(HKCharacteristicType *)objectType error:&error]; + handler(defaultValue, error); + handled = YES; + } else if ([answerFormat isKindOfClass:[ORKHealthKitQuantityTypeAnswerFormat class]]) { + [self updateHealthKitUnitForAnswerFormat:answerFormat force:NO]; + HKUnit *unit = [answerFormat healthKitUserUnit]; + [self fetchDefaultValueForQuantityType:(HKQuantityType *)objectType unit:unit handler:handler]; + handled = YES; + } + } + } + if (!handled) { + handler(nil, nil); + } +} + +- (HKUnit *)defaultHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat { + __block HKUnit *unit = [answerFormat healthKitUnit]; + HKObjectType *objectType = [answerFormat healthKitObjectType]; + if (![[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 2, .patchVersion = 0}]) { + return unit; + } + + if (unit == nil && [objectType isKindOfClass:[HKQuantityType class]] && [HKHealthStore isHealthDataAvailable]) { + unit = _unitsTable[objectType]; + if (unit) { + return unit; + } + if (!_unitsTable) { + _unitsTable = [NSMutableDictionary dictionary]; + } + + HKQuantityType *quantityType = (HKQuantityType *)objectType; + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + [_healthStore preferredUnitsForQuantityTypes:[NSSet setWithObject:quantityType] completion:^(NSDictionary *preferredUnits, NSError *error) { + + unit = preferredUnits[quantityType]; + + dispatch_semaphore_signal(sem); + }]; + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + + if (unit) { + _unitsTable[objectType] = unit; + } + } + return unit; +} + +- (void)updateHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat force:(BOOL)force { + HKUnit *unit = [answerFormat healthKitUserUnit]; + HKUnit *healthKitDefault = [self defaultHealthKitUnitForAnswerFormat:answerFormat]; + if (!ORKEqualObjects(unit,healthKitDefault) && (force || (unit == nil))) { + [answerFormat setHealthKitUserUnit:healthKitDefault]; + } +} + +@end + + +#pragma mark - ORKAnswerFormat + +@implementation ORKAnswerFormat + ++ (ORKScaleAnswerFormat *)scaleAnswerFormatWithMaximumValue:(NSInteger)scaleMaximum + minimumValue:(NSInteger)scaleMinimum + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription { + return [[ORKScaleAnswerFormat alloc] initWithMaximumValue:scaleMaximum + minimumValue:scaleMinimum + defaultValue:defaultValue + step:step + vertical:vertical + maximumValueDescription:maximumValueDescription + minimumValueDescription:minimumValueDescription]; +} + ++ (ORKContinuousScaleAnswerFormat *)continuousScaleAnswerFormatWithMaximumValue:(double)scaleMaximum + minimumValue:(double)scaleMinimum + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription { + return [[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:scaleMaximum + minimumValue:scaleMinimum + defaultValue:defaultValue + maximumFractionDigits:maximumFractionDigits + vertical:vertical + maximumValueDescription:maximumValueDescription + minimumValueDescription:minimumValueDescription]; +} + ++ (ORKTextScaleAnswerFormat *)textScaleAnswerFormatWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex + vertical:(BOOL)vertical { + return [[ORKTextScaleAnswerFormat alloc] initWithTextChoices:textChoices + defaultIndex:defaultIndex + vertical:vertical]; +} + ++ (ORKBooleanAnswerFormat *)booleanAnswerFormat { + return [ORKBooleanAnswerFormat new]; +} + ++ (ORKBooleanAnswerFormat *)booleanAnswerFormatWithYesString:(NSString *)yes noString:(NSString *)no { + return [[ORKBooleanAnswerFormat alloc] initWithYesString:yes noString:no]; +} + ++ (ORKValuePickerAnswerFormat *)valuePickerAnswerFormatWithTextChoices:(NSArray *)textChoices { + return [[ORKValuePickerAnswerFormat alloc] initWithTextChoices:textChoices]; +} + ++ (ORKMultipleValuePickerAnswerFormat *)multipleValuePickerAnswerFormatWithValuePickers:(NSArray *)valuePickers { + return [[ORKMultipleValuePickerAnswerFormat alloc] initWithValuePickers:valuePickers]; +} + ++ (ORKImageChoiceAnswerFormat *)choiceAnswerFormatWithImageChoices:(NSArray *)imageChoices { + return [[ORKImageChoiceAnswerFormat alloc] initWithImageChoices:imageChoices]; +} + ++ (ORKImageChoiceAnswerFormat *)choiceAnswerFormatWithImageChoices:(NSArray *)imageChoices + style:(ORKChoiceAnswerStyle)style + vertical:(BOOL)vertical { + return [[ORKImageChoiceAnswerFormat alloc] initWithImageChoices:imageChoices + style:style + vertical:vertical]; +} + ++ (ORKTextChoiceAnswerFormat *)choiceAnswerFormatWithStyle:(ORKChoiceAnswerStyle)style + textChoices:(NSArray *)textChoices { + return [[ORKTextChoiceAnswerFormat alloc] initWithStyle:style textChoices:textChoices]; +} + ++ (ORKNumericAnswerFormat *)decimalAnswerFormatWithUnit:(NSString *)unit { + return [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal unit:unit minimum:nil maximum:nil]; +} ++ (ORKNumericAnswerFormat *)integerAnswerFormatWithUnit:(NSString *)unit { + return [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger unit:unit minimum:nil maximum:nil]; +} + ++ (ORKTimeOfDayAnswerFormat *)timeOfDayAnswerFormat { + return [ORKTimeOfDayAnswerFormat new]; +} ++ (ORKTimeOfDayAnswerFormat *)timeOfDayAnswerFormatWithDefaultComponents:(NSDateComponents *)defaultComponents { + return [[ORKTimeOfDayAnswerFormat alloc] initWithDefaultComponents:defaultComponents]; +} + ++ (ORKDateAnswerFormat *)dateTimeAnswerFormat { + return [[ORKDateAnswerFormat alloc] initWithStyle:ORKDateAnswerStyleDateAndTime]; +} ++ (ORKDateAnswerFormat *)dateTimeAnswerFormatWithDefaultDate:(NSDate *)defaultDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + calendar:(NSCalendar *)calendar { + return [[ORKDateAnswerFormat alloc] initWithStyle:ORKDateAnswerStyleDateAndTime + defaultDate:defaultDate + minimumDate:minimumDate + maximumDate:maximumDate + calendar:calendar]; +} + ++ (ORKDateAnswerFormat *)dateAnswerFormat { + return [[ORKDateAnswerFormat alloc] initWithStyle:ORKDateAnswerStyleDate]; +} ++ (ORKDateAnswerFormat *)dateAnswerFormatWithDefaultDate:(NSDate *)defaultDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + calendar:(NSCalendar *)calendar { + return [[ORKDateAnswerFormat alloc] initWithStyle:ORKDateAnswerStyleDate + defaultDate:defaultDate + minimumDate:minimumDate + maximumDate:maximumDate + calendar:calendar]; +} + ++ (ORKTextAnswerFormat *)textAnswerFormat { + return [ORKTextAnswerFormat new]; +} + ++ (ORKTextAnswerFormat *)textAnswerFormatWithMaximumLength:(NSInteger)maximumLength { + return [[ORKTextAnswerFormat alloc] initWithMaximumLength:maximumLength]; +} + ++ (ORKTextAnswerFormat *)textAnswerFormatWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage { + return [[ORKTextAnswerFormat alloc] initWithValidationRegularExpression:validationRegularExpression + invalidMessage:invalidMessage]; +} + ++ (ORKEmailAnswerFormat *)emailAnswerFormat { + return [ORKEmailAnswerFormat new]; +} + ++ (ORKTimeIntervalAnswerFormat *)timeIntervalAnswerFormat { + return [ORKTimeIntervalAnswerFormat new]; +} + ++ (ORKTimeIntervalAnswerFormat *)timeIntervalAnswerFormatWithDefaultInterval:(NSTimeInterval)defaultInterval + step:(NSInteger)step { + return [[ORKTimeIntervalAnswerFormat alloc] initWithDefaultInterval:defaultInterval step:step]; +} + ++ (ORKHeightAnswerFormat *)heightAnswerFormat { + return [ORKHeightAnswerFormat new]; +} + ++ (ORKHeightAnswerFormat *)heightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem { + return [[ORKHeightAnswerFormat alloc] initWithMeasurementSystem:measurementSystem]; +} + ++ (ORKWeightAnswerFormat *)weightAnswerFormat { + return [ORKWeightAnswerFormat new]; +} + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem { + return [[ORKWeightAnswerFormat alloc] initWithMeasurementSystem:measurementSystem]; +} + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision { + return [[ORKWeightAnswerFormat alloc] initWithMeasurementSystem:measurementSystem + numericPrecision:numericPrecision]; +} + ++ (ORKWeightAnswerFormat *)weightAnswerFormatWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision + minimumValue:(double)minimumValue + maximumValue:(double)maximumValue + defaultValue:(double)defaultValue { + return [[ORKWeightAnswerFormat alloc] initWithMeasurementSystem:measurementSystem + numericPrecision:numericPrecision + minimumValue:minimumValue + maximumValue:maximumValue + defaultValue:defaultValue]; +} + ++ (ORKLocationAnswerFormat *)locationAnswerFormat { + return [ORKLocationAnswerFormat new]; +} + ++ (ORKSESAnswerFormat *)socioEconomicAnswerFormatWithTopRungText:(NSString *)topRungText + bottomRungText:(NSString *)bottomRungText { + return [[ORKSESAnswerFormat alloc] initWithTopRungText:topRungText + bottomRungText:bottomRungText]; +} + +- (void)validateParameters { +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _showDontKnowButton = NO; + _customDontKnowButtonText = nil; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + + if (self) { + ORK_DECODE_BOOL(aDecoder, showDontKnowButton); + ORK_DECODE_OBJ(aDecoder, customDontKnowButtonText); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_BOOL(aCoder, showDontKnowButton); + ORK_ENCODE_OBJ(aCoder, customDontKnowButtonText); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + return YES; +} + +- (NSUInteger)hash { + // Ignore the task reference - it's not part of the content of the step. + return 0; +} + +- (BOOL)isHealthKitAnswerFormat { + return NO; +} + +- (HKObjectType *)healthKitObjectType { + return nil; +} + +- (HKObjectType *)healthKitObjectTypeForAuthorization { + return nil; +} + +- (HKUnit *)healthKitUnit { + return nil; +} + +- (HKUnit *)healthKitUserUnit { + return nil; +} + +- (void)setHealthKitUserUnit:(HKUnit *)unit { + +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeNone; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + return self; +} + +- (Class)questionResultClass { + return [ORKQuestionResult class]; +} + +- (ORKQuestionResult *)resultWithIdentifier:(NSString *)identifier answer:(id)answer { + ORKQuestionResult *questionResult = [[[self questionResultClass] alloc] initWithIdentifier:identifier]; + + /* + ContinuousScale navigation rules always evaluate to false because the result is different from what is displayed in the UI. + The fraction digits have to be taken into account in self.answer as well. + */ + if ([self isKindOfClass:[ORKContinuousScaleAnswerFormat class]] && ![answer isKindOfClass:[ORKDontKnowAnswer class]]) { + NSNumberFormatter* formatter = [(ORKContinuousScaleAnswerFormat*)self numberFormatter]; + answer = [formatter numberFromString:[formatter stringFromNumber:answer]]; + } + + questionResult.answer = answer; + questionResult.questionType = self.questionType; + return questionResult; +} + +- (BOOL)isAnswerValid:(id)answer { + ORKAnswerFormat *impliedFormat = [self impliedAnswerFormat]; + return impliedFormat == self ? YES : [impliedFormat isAnswerValid:answer]; +} + +- (BOOL)isAnswerValidWithString:(NSString *)text { + ORKAnswerFormat *impliedFormat = [self impliedAnswerFormat]; + return impliedFormat == self ? YES : [impliedFormat isAnswerValidWithString:text]; +} + +- (NSString *)localizedInvalidValueStringWithAnswerString:(NSString *)text { + return nil; +} + +- (NSString *)stringForAnswer:(id)answer { + ORKAnswerFormat *impliedFormat = [self impliedAnswerFormat]; + return impliedFormat == self ? nil : [impliedFormat stringForAnswer:answer]; +} + +- (BOOL)shouldShowDontKnowButton { + return _showDontKnowButton; +} + +@end + + +#pragma mark - ORKValuePickerAnswerFormat + +static void ork_validateChoices(NSArray *choices) { + const NSInteger ORKAnswerFormatMinimumNumberOfChoices = 1; + if (choices.count < ORKAnswerFormatMinimumNumberOfChoices) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"The number of choices cannot be less than %@.", @(ORKAnswerFormatMinimumNumberOfChoices)] + userInfo:nil]; + } +} + +static NSArray *ork_processTextChoices(NSArray *textChoices) { + NSMutableArray *choices = [[NSMutableArray alloc] init]; + for (ORKTextChoice *textObject in textChoices) { + if (![textObject isKindOfClass:[ORKTextChoice class]]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"The textChoices array should only containt objects of the ORKTextChoice kind." userInfo:@{@"nonConformingObject": textObject}]; + } + [choices addObject:[textObject isKindOfClass:[ORKTextChoiceOther class]] ? [textObject copyWithZone:nil] : textObject]; + } + return choices; +} + + +@implementation ORKValuePickerAnswerFormat { + ORKChoiceAnswerFormatHelper *_helper; + ORKTextChoice *_nullTextChoice; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithTextChoices:(NSArray *)textChoices { + self = [super init]; + if (self) { + [self commonInitWithTextChoices:textChoices nullChoice:nil]; + } + return self; +} + +- (instancetype)initWithTextChoices:(NSArray *)textChoices nullChoice:(ORKTextChoice *)nullChoice { + self = [super init]; + if (self) { + [self commonInitWithTextChoices:textChoices nullChoice:nullChoice]; + } + return self; +} + +- (void)commonInitWithTextChoices:(NSArray *)textChoices nullChoice:(ORKTextChoice *)nullChoice { + _textChoices = ork_processTextChoices(textChoices); + _nullTextChoice = nullChoice; + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:self]; +} + +- (void)validateParameters { + [super validateParameters]; + + ork_validateChoices(_textChoices); +} + +- (id)copyWithZone:(NSZone *)zone { + __typeof(self) copy = [[[self class] alloc] initWithTextChoices:_textChoices nullChoice:_nullTextChoice]; + return copy; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.textChoices, castObject.textChoices)); +} + +- (NSUInteger)hash { + return super.hash ^ _textChoices.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, textChoices, ORKTextChoice); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, textChoices); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (ORKTextChoice *)nullTextChoice { + return _nullTextChoice ?: [ORKTextChoice choiceWithText:ORKLocalizedString(@"NULL_ANSWER", nil) value:ORKNullAnswerValue()]; +} + +- (void)setNullTextChoice:(ORKTextChoice *)nullChoice { + _nullTextChoice = nullChoice; +} + +- (Class)questionResultClass { + return [ORKChoiceQuestionResult class]; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeSingleChoice; +} + +- (NSString *)stringForAnswer:(id)answer { + return [_helper stringForChoiceAnswer:answer]; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKMultipleValuePickerAnswerFormat + +@implementation ORKMultipleValuePickerAnswerFormat + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithValuePickers:(NSArray *)valuePickers { + return [self initWithValuePickers:valuePickers separator:@" "]; +} + +- (instancetype)initWithValuePickers:(NSArray *)valuePickers separator:(NSString *)separator { + self = [super init]; + if (self) { + for (ORKValuePickerAnswerFormat *valuePicker in valuePickers) { + // Do not show placeholder text for multiple component picker + [valuePicker setNullTextChoice: [ORKTextChoice choiceWithText:@"" value:ORKNullAnswerValue()]]; + } + _valuePickers = ORKArrayCopyObjects(valuePickers); + _separator = [separator copy]; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + for (ORKValuePickerAnswerFormat *valuePicker in self.valuePickers) { + [valuePicker validateParameters]; + } +} + +- (id)copyWithZone:(NSZone *)zone { + __typeof(self) copy = [[[self class] alloc] initWithValuePickers:self.valuePickers separator:self.separator]; + return copy; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.valuePickers, castObject.valuePickers)); +} + +- (NSUInteger)hash { + return super.hash ^ self.valuePickers.hash ^ self.separator.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, valuePickers, ORKValuePickerAnswerFormat); + ORK_DECODE_OBJ_CLASS(aDecoder, separator, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, valuePickers); + ORK_ENCODE_OBJ(aCoder, separator); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (Class)questionResultClass { + return [ORKMultipleComponentQuestionResult class]; +} + +- (ORKQuestionResult *)resultWithIdentifier:(NSString *)identifier answer:(id)answer { + ORKQuestionResult *questionResult = [super resultWithIdentifier:identifier answer:answer]; + if ([questionResult isKindOfClass:[ORKMultipleComponentQuestionResult class]]) { + ((ORKMultipleComponentQuestionResult*)questionResult).separator = self.separator; + } + return questionResult; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeMultiplePicker; +} + +- (NSString *)stringForAnswer:(id)answer { + if (![answer isKindOfClass:[NSArray class]] || ([(NSArray*)answer count] != self.valuePickers.count)) { + return nil; + } + + NSArray *answers = (NSArray*)answer; + __block NSMutableArray *answerTexts = [NSMutableArray new]; + [answers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *text = [self.valuePickers[idx] stringForAnswer:obj]; + if (text != nil) { + [answerTexts addObject:text]; + } else { + *stop = YES; + } + }]; + + if (answerTexts.count != self.valuePickers.count) { + return nil; + } + + return [answerTexts componentsJoinedByString:self.separator]; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKImageChoiceAnswerFormat + +@interface ORKImageChoiceAnswerFormat () { + ORKChoiceAnswerFormatHelper *_helper; + +} + +@end + + +@implementation ORKImageChoiceAnswerFormat + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithImageChoices:(NSArray *)imageChoices { + self = [self initWithImageChoices:imageChoices style:ORKChoiceAnswerStyleSingleChoice vertical:NO]; + return self; +} + +- (instancetype)initWithImageChoices:(NSArray *)imageChoices + style:(ORKChoiceAnswerStyle)style + vertical:(BOOL)vertical { + self = [super init]; + if (self) { + NSMutableArray *choices = [[NSMutableArray alloc] init]; + + for (NSObject *obj in imageChoices) { + if ([obj isKindOfClass:[ORKImageChoice class]]) { + + [choices addObject:obj]; + + } else { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Options should be instances of ORKImageChoice" userInfo:@{ @"option": obj }]; + } + } + _imageChoices = choices; + _style = style; + _vertical = vertical; + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:self]; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + ork_validateChoices(_imageChoices); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.imageChoices, castObject.imageChoices) && + (_style == castObject.style) && + (_vertical == castObject.vertical)); +} + +- (NSUInteger)hash { + return super.hash ^ self.imageChoices.hash ^ _style ^ _vertical; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, imageChoices, ORKImageChoice); + ORK_DECODE_ENUM(aDecoder, style); + ORK_DECODE_BOOL(aDecoder, vertical); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, imageChoices); + ORK_ENCODE_ENUM(aCoder, style); + ORK_ENCODE_BOOL(aCoder, vertical); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (ORKQuestionType)questionType { + return (_style == ORKChoiceAnswerStyleSingleChoice) ? ORKQuestionTypeSingleChoice : ORKQuestionTypeMultipleChoice; +} + +- (Class)questionResultClass { + return [ORKChoiceQuestionResult class]; +} + +- (NSString *)stringForAnswer:(id)answer { + return [_helper stringForChoiceAnswer:answer]; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKTextChoiceAnswerFormat + +@interface ORKTextChoiceAnswerFormat () { + + ORKChoiceAnswerFormatHelper *_helper; +} + +@end + + +@implementation ORKTextChoiceAnswerFormat + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithStyle:(ORKChoiceAnswerStyle)style + textChoices:(NSArray *)textChoices { + self = [super init]; + if (self) { + _style = style; + _textChoices = ork_processTextChoices(textChoices); + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:self]; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + ork_validateChoices(_textChoices); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTextChoiceAnswerFormat *answerFormat = [[[self class] allocWithZone:zone] initWithStyle:_style + textChoices:[_textChoices copy]]; + return answerFormat; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.textChoices, castObject.textChoices) && + (_style == castObject.style)); +} + +- (NSUInteger)hash { + return super.hash ^ _textChoices.hash ^ _style; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, textChoices, ORKTextChoice); + ORK_DECODE_ENUM(aDecoder, style); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, textChoices); + ORK_ENCODE_ENUM(aCoder, style); + +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (ORKQuestionType)questionType { + return (_style == ORKChoiceAnswerStyleSingleChoice) ? ORKQuestionTypeSingleChoice : ORKQuestionTypeMultipleChoice; +} + +- (Class)questionResultClass { + return [ORKChoiceQuestionResult class]; +} + +- (NSString *)stringForAnswer:(id)answer { + return [_helper stringForChoiceAnswer:answer]; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKTextChoice + +@implementation ORKTextChoice { + NSString *_text; + id _value; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + ++ (instancetype)choiceWithText:(NSString *)text primaryTextAttributedString:(NSAttributedString *)primaryTextAttributedString detailText:(NSString *)detailText detailTextAttributedString:(NSAttributedString *)detailTextAttributedString value:(id)value exclusive:(BOOL)exclusive { + return [[ORKTextChoice alloc] initWithText:text primaryTextAttributedString:primaryTextAttributedString detailText:detailText detailTextAttributedString:detailTextAttributedString value:value exclusive:exclusive]; +} + ++ (instancetype)choiceWithText:(NSString *)text detailText:(NSString *)detailText value:(id)value exclusive:(BOOL)exclusive { + ORKTextChoice *option = [[ORKTextChoice alloc] initWithText:text detailText:detailText value:value exclusive:exclusive]; + return option; +} + ++ (instancetype)choiceWithText:(NSString *)text value:(id)value { + return [ORKTextChoice choiceWithText:text detailText:nil value:value exclusive:NO]; +} + +- (instancetype)initWithText:(NSString *)text detailText:(NSString *)detailText value:(id)value exclusive:(BOOL)exclusive { + return [self initWithText:text primaryTextAttributedString:nil detailText:detailText detailTextAttributedString:nil value:value exclusive:exclusive]; +} + +- (instancetype)initWithText:(NSString *)text primaryTextAttributedString:(NSAttributedString *)primaryTextAttributedString detailText:(NSString *)detailText detailTextAttributedString:(NSAttributedString *)detailTextAttributedString value:(id)value exclusive:(BOOL)exclusive { + if (!text && !primaryTextAttributedString && !detailText && !detailTextAttributedString) { + NSAssert(NO, @"All the input parameters cannot be nil, please provide at least one non-nil value."); + } + self = [super init]; + if (self) { + _text = [text copy]; + _primaryTextAttributedString = [primaryTextAttributedString copy]; + _detailText = [detailText copy]; + _detailTextAttributedString = [detailTextAttributedString copy]; + _value = value; + _exclusive = exclusive; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + // Ignore the task reference - it's not part of the content of the step + __typeof(self) castObject = object; + return (ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.primaryTextAttributedString, castObject.primaryTextAttributedString) + && ORKEqualObjects(self.detailText, castObject.detailText) + && ORKEqualObjects(self.detailTextAttributedString, castObject.detailTextAttributedString) + && ORKEqualObjects(self.value, castObject.value) + && self.exclusive == castObject.exclusive); +} + +- (NSUInteger)hash { + // Ignore the task reference - it's not part of the content of the step + return _text.hash ^ _primaryTextAttributedString.hash ^ _detailText.hash ^ _detailTextAttributedString.hash ^ _value.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, primaryTextAttributedString, NSAttributedString); + ORK_DECODE_OBJ_CLASS(aDecoder, detailText, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, detailTextAttributedString, NSAttributedString); + ORK_DECODE_OBJ(aDecoder, value); + ORK_DECODE_BOOL(aDecoder, exclusive); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, primaryTextAttributedString); + ORK_ENCODE_OBJ(aCoder, detailText); + ORK_ENCODE_OBJ(aCoder, detailTextAttributedString); + ORK_ENCODE_OBJ(aCoder, value); + ORK_ENCODE_BOOL(aCoder, exclusive); +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKTextChoiceOther + +@implementation ORKTextChoiceOther + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + ++ (instancetype)choiceWithText:(NSString *)text + detailText:(NSString *)detailText + value:(id)value + exclusive:(BOOL)exclusive + textViewPlaceholderText:(NSString *)textViewPlaceholderText { + ORKTextChoiceOther *option = [[ORKTextChoiceOther alloc] initWithText:text primaryTextAttributedString:nil detailText:detailText detailTextAttributedString:nil value:value exclusive:exclusive textViewPlaceholderText:textViewPlaceholderText textViewInputOptional:YES textViewStartsHidden:YES]; + return option; +} + +- (instancetype)initWithText:(NSString *)text + primaryTextAttributedString:(NSAttributedString *)primaryTextAttributedString + detailText:(NSString *)detailText + detailTextAttributedString:(NSAttributedString *)detailTextAttributedString + value:(id)value + exclusive:(BOOL)exclusive + textViewPlaceholderText:(NSString *)textViewPlaceholderText + textViewInputOptional:(BOOL)textViewInputOptional + textViewStartsHidden:(BOOL)textViewStartsHidden { + + self = [super initWithText:text + primaryTextAttributedString:primaryTextAttributedString + detailText:detailText + detailTextAttributedString:detailTextAttributedString + value:value + exclusive:exclusive]; + + if (self) { + _textViewPlaceholderText = textViewPlaceholderText; + _textViewInputOptional = textViewInputOptional; + _textViewStartsHidden = textViewStartsHidden; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTextChoiceOther *other = [[ORKTextChoiceOther allocWithZone:zone] initWithText:[self.text copy] + primaryTextAttributedString:[self.primaryTextAttributedString copy] + detailText:[self.detailText copy] + detailTextAttributedString:[self.detailTextAttributedString copy] + value:[self.value copyWithZone:zone] + exclusive:self.exclusive + textViewPlaceholderText:[self.textViewPlaceholderText copy] + textViewInputOptional:self.textViewInputOptional + textViewStartsHidden:self.textViewStartsHidden]; + return other; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + // Ignore the task reference - it's not part of the content of the step + __typeof(self) castObject = object; + return (ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.primaryTextAttributedString, castObject.primaryTextAttributedString) + && ORKEqualObjects(self.detailText, castObject.detailText) + && ORKEqualObjects(self.detailTextAttributedString, castObject.detailTextAttributedString) + && ORKEqualObjects(self.value, castObject.value) + && self.exclusive == castObject.exclusive + && ORKEqualObjects(self.textViewPlaceholderText, castObject.textViewPlaceholderText) + && self.textViewInputOptional == castObject.textViewInputOptional + && self.textViewStartsHidden == castObject.textViewStartsHidden); +} + +- (NSUInteger)hash { + return [super hash] ^ _textViewPlaceholderText.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, textViewPlaceholderText, NSString); + ORK_DECODE_BOOL(aDecoder, textViewInputOptional); + ORK_DECODE_BOOL(aDecoder, textViewStartsHidden); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, textViewPlaceholderText); + ORK_ENCODE_BOOL(aCoder, textViewInputOptional); + ORK_ENCODE_BOOL(aCoder, textViewStartsHidden); +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + +#pragma mark - ORKImageChoice + +@implementation ORKImageChoice { + NSString *_text; + id _value; +} + ++ (instancetype)choiceWithNormalImage:(UIImage *)normal selectedImage:(UIImage *)selected text:(NSString *)text value:(id)value { + return [[ORKImageChoice alloc] initWithNormalImage:normal selectedImage:selected text:text value:value]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithNormalImage:(UIImage *)normal selectedImage:(UIImage *)selected text:(NSString *)text value:(id)value { + self = [super init]; + if (self) { + _text = [text copy]; + _value = value; + _normalStateImage = normal; + _selectedStateImage = selected; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + return self; +} + +- (NSString *)text { + return _text; +} + +- (id)value { + return _value; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + // Ignore the task reference - it's not part of the content of the step. + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.value, castObject.value) + && ORKEqualObjects(self.normalStateImage, castObject.normalStateImage) + && ORKEqualObjects(self.selectedStateImage, castObject.selectedStateImage)); +} + +- (NSUInteger)hash { + // Ignore the task reference - it's not part of the content of the step. + return _text.hash ^ _value.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ(aDecoder, value); + ORK_DECODE_IMAGE(aDecoder, normalStateImage); + ORK_DECODE_IMAGE(aDecoder, selectedStateImage); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, value); + ORK_ENCODE_IMAGE(aCoder, normalStateImage); + ORK_ENCODE_IMAGE(aCoder, selectedStateImage); +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKBooleanAnswerFormat + +@implementation ORKBooleanAnswerFormat + +- (instancetype)initWithYesString:(NSString *)yes noString:(NSString *)no { + self = [super init]; + if (self) { + _yes = [yes copy]; + _no = [no copy]; + } + return self; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeBoolean; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + if (!_yes.length) { + _yes = ORKLocalizedString(@"BOOL_YES", nil); + } + if (!_no.length) { + _no = ORKLocalizedString(@"BOOL_NO", nil); + } + + return [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:@[[ORKTextChoice choiceWithText:_yes value:@(YES)], + [ORKTextChoice choiceWithText:_no value:@(NO)]]]; +} + +- (Class)questionResultClass { + return [ORKBooleanQuestionResult class]; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self.impliedAnswerFormat stringForAnswer: @[answer]]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKBooleanAnswerFormat *answerFormat = [super copyWithZone:zone]; + answerFormat->_yes = [_yes copy]; + answerFormat->_no = [_no copy]; + return answerFormat; +} + +- (NSUInteger)hash { + return super.hash ^ _yes.hash ^ _no.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.yes, castObject.yes) && + ORKEqualObjects(self.no, castObject.no)); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, yes, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, no, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, yes); + ORK_ENCODE_OBJ(aCoder, no); +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + + +#pragma mark - ORKTimeOfDayAnswerFormat + +@implementation ORKTimeOfDayAnswerFormat + +- (instancetype)init { + self = [self initWithDefaultComponents:nil]; + return self; +} + +- (instancetype)initWithDefaultComponents:(NSDateComponents *)defaultComponents { + self = [super init]; + if (self) { + _defaultComponents = [defaultComponents copy]; + _minuteInterval = 1; + } + return self; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeTimeOfDay; +} + +- (Class)questionResultClass { + return [ORKTimeOfDayQuestionResult class]; +} + +- (NSDate *)pickerDefaultDate { + + if (self.defaultComponents) { + return ORKTimeOfDayDateFromComponents(self.defaultComponents); + } + + NSDateComponents *dateComponents = [[NSCalendar currentCalendar] componentsInTimeZone:[NSTimeZone systemTimeZone] fromDate:[NSDate date]]; + NSDateComponents *newDateComponents = [[NSDateComponents alloc] init]; + newDateComponents.calendar = ORKTimeOfDayReferenceCalendar(); + newDateComponents.hour = dateComponents.hour; + newDateComponents.minute = dateComponents.minute; + + return ORKTimeOfDayDateFromComponents(newDateComponents); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.defaultComponents, castObject.defaultComponents) && + (self.minuteInterval == castObject.minuteInterval)); +} + +- (NSUInteger)hash { + // Don't bother including everything + return super.hash & self.defaultComponents.hash; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, defaultComponents, NSDateComponents); + ORK_DECODE_INTEGER(aDecoder, minuteInterval); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, defaultComponents); + ORK_ENCODE_INTEGER(aCoder, minuteInterval); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSString *)stringForAnswer:(id)answer { + return ORKTimeOfDayStringFromComponents(answer); +} + +@end + + +#pragma mark - ORKDateAnswerFormat + +@implementation ORKDateAnswerFormat + +- (Class)questionResultClass { + return [ORKDateQuestionResult class]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithStyle:(ORKDateAnswerStyle)style { + self = [self initWithStyle:style defaultDate:nil minimumDate:nil maximumDate:nil calendar:nil]; + return self; +} + +- (instancetype)initWithStyle:(ORKDateAnswerStyle)style + defaultDate:(NSDate *)defaultDate + minimumDate:(NSDate *)minimum + maximumDate:(NSDate *)maximum + calendar:(NSCalendar *)calendar { + self = [super init]; + if (self) { + _style = style; + _defaultDate = [defaultDate copy]; + _minimumDate = [minimum copy]; + _maximumDate = [maximum copy]; + _calendar = [calendar copy]; + _minuteInterval = 1; + [self validateParameters]; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + if ((_minimumDate && _maximumDate) ? ([_minimumDate compare:_maximumDate] == NSOrderedDescending) : false) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Minimum date should be before the maximum date"] + userInfo:nil]; + } else if((_defaultDate && _minimumDate) ? ([_defaultDate compare:_minimumDate] == NSOrderedAscending) : false) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Default date should not be less than the minumum date"] + userInfo:nil]; + } else if ((_defaultDate && _maximumDate) ? ([_defaultDate compare:_maximumDate] == NSOrderedDescending) : false) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Default date should not be more than the maximum date"] + userInfo:nil]; + } +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.defaultDate, castObject.defaultDate) && + ORKEqualObjects(self.minimumDate, castObject.minimumDate) && + ORKEqualObjects(self.maximumDate, castObject.maximumDate) && + ORKEqualObjects(self.calendar, castObject.calendar) && + (self.minuteInterval == castObject.minuteInterval) && + (_style == castObject.style)); +} + +- (NSUInteger)hash { + // Don't bother including everything - style is the main item. + return ([super hash] & [self.defaultDate hash]) ^ _style; +} + +- (NSCalendar *)currentCalendar { + return (_calendar ? : [NSCalendar currentCalendar]); +} + +- (NSDateFormatter *)resultDateFormatter { + NSDateFormatter *dfm = nil; + switch (self.questionType) { + case ORKQuestionTypeDate: { + dfm = ORKResultDateFormatter(); + break; + } + case ORKQuestionTypeTimeOfDay: { + dfm = ORKResultTimeFormatter(); + break; + } + case ORKQuestionTypeDateAndTime: { + dfm = ORKResultDateTimeFormatter(); + break; + } + default: + break; + } + dfm = [dfm copy]; + dfm.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + return dfm; +} + +- (NSString *)stringFromDate:(NSDate *)date { + NSDateFormatter *dfm = [self resultDateFormatter]; + return [dfm stringFromDate:date]; +} + +- (NSDate *)dateFromString:(NSString *)string { + NSDateFormatter *dfm = [self resultDateFormatter]; + return [dfm dateFromString:string]; +} + +- (NSDate *)pickerDefaultDate { + return (self.defaultDate ? : [NSDate date]); + +} + +- (NSDate *)pickerMinimumDate { + return self.minimumDate; +} + +- (NSDate *)pickerMaximumDate { + return self.maximumDate; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, style); + ORK_DECODE_OBJ_CLASS(aDecoder, minimumDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, maximumDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, defaultDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, calendar, NSCalendar); + ORK_DECODE_INTEGER(aDecoder, minuteInterval); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, style); + ORK_ENCODE_OBJ(aCoder, minimumDate); + ORK_ENCODE_OBJ(aCoder, maximumDate); + ORK_ENCODE_OBJ(aCoder, defaultDate); + ORK_ENCODE_OBJ(aCoder, calendar); + ORK_ENCODE_INTEGER(aCoder, minuteInterval); +} + +- (ORKQuestionType)questionType { + return (_style == ORKDateAnswerStyleDateAndTime) ? ORKQuestionTypeDateAndTime : ORKQuestionTypeDate; +} + + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self stringFromDate:answer]; +} + +@end + + +#pragma mark - ORKNumericAnswerFormat + +@implementation ORKNumericAnswerFormat + +- (Class)questionResultClass { + return [ORKNumericQuestionResult class]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style { + return [self initWithStyle:style unit:nil minimum:nil maximum:nil]; +} + +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style + unit:(NSString *)unit + minimum:(NSNumber *)minimum + maximum:(NSNumber *)maximum { + return [self initWithStyle:style unit:unit minimum:minimum maximum:maximum maximumFractionDigits:nil]; +} + +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style + unit:(NSString *)unit + minimum:(NSNumber *)minimum + maximum:(NSNumber *)maximum + maximumFractionDigits:(NSNumber *)maximumFractionDigits { + self = [super init]; + if (self) { + _style = style; + _unit = [unit copy]; + _minimum = [minimum copy]; + _maximum = [maximum copy]; + _maximumFractionDigits = [maximumFractionDigits copy]; + _hideUnitWhenAnswerIsEmpty = YES; + _placeholder = nil; + + [self validateParameters]; + } + return self; +} + +- (void)validateParameters { + if (_minimum != NULL && _maximum != NULL) { + if ([_maximum compare: _minimum] == NSOrderedAscending) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Expect maximumValue larger than minimumValue"] userInfo:nil]; + } + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, style); + ORK_DECODE_OBJ_CLASS(aDecoder, unit, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, minimum, NSNumber); + ORK_DECODE_OBJ_CLASS(aDecoder, maximum, NSNumber); + ORK_DECODE_OBJ_CLASS(aDecoder, defaultNumericAnswer, NSNumber); + ORK_DECODE_OBJ_CLASS(aDecoder, maximumFractionDigits, NSNumber); + ORK_DECODE_BOOL(aDecoder, hideUnitWhenAnswerIsEmpty); + ORK_DECODE_OBJ_CLASS(aDecoder, placeholder, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, style); + ORK_ENCODE_OBJ(aCoder, unit); + ORK_ENCODE_OBJ(aCoder, minimum); + ORK_ENCODE_OBJ(aCoder, maximum); + ORK_ENCODE_OBJ(aCoder, defaultNumericAnswer); + ORK_ENCODE_OBJ(aCoder, maximumFractionDigits); + ORK_ENCODE_BOOL(aCoder, hideUnitWhenAnswerIsEmpty); + ORK_ENCODE_OBJ(aCoder, placeholder); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKNumericAnswerFormat *answerFormat = [[[self class] allocWithZone:zone] initWithStyle:_style + unit:[_unit copy] + minimum:[_minimum copy] + maximum:[_maximum copy] + maximumFractionDigits:[_maximumFractionDigits copy]]; + answerFormat->_defaultNumericAnswer = [_defaultNumericAnswer copy]; + answerFormat->_hideUnitWhenAnswerIsEmpty = _hideUnitWhenAnswerIsEmpty; + answerFormat->_placeholder = [_placeholder copy]; + answerFormat.showDontKnowButton = self.showDontKnowButton; + answerFormat.customDontKnowButtonText = [self.customDontKnowButtonText copy]; + return answerFormat; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + _style == castObject.style && + ORKEqualObjects(self.unit, castObject.unit) && + ORKEqualObjects(self.minimum, castObject.minimum) && + ORKEqualObjects(self.maximum, castObject.maximum) && + ORKEqualObjects(self.defaultNumericAnswer, castObject.defaultNumericAnswer) && + ORKEqualObjects(self.maximumFractionDigits, castObject.maximumFractionDigits) && + (_hideUnitWhenAnswerIsEmpty == castObject.hideUnitWhenAnswerIsEmpty) && + ORKEqualObjects(self.placeholder, castObject.placeholder)); +} + +- (NSUInteger)hash { + // Don't bother including everything - style is the main item + return [super hash] ^ ([self.unit hash] & _style); +} + +- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style unit:(NSString *)unit { + return [self initWithStyle:style unit:unit minimum:nil maximum:nil]; +} + ++ (instancetype)decimalAnswerFormatWithUnit:(NSString *)unit { + return [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal unit:unit]; +} + ++ (instancetype)integerAnswerFormatWithUnit:(NSString *)unit { + return [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger unit:unit]; +} + +- (ORKQuestionType)questionType { + return _style == ORKNumericAnswerStyleDecimal ? ORKQuestionTypeDecimal : ORKQuestionTypeInteger; + +} + +- (BOOL)isAnswerValid:(id)answer { + BOOL isValid = NO; + if ([answer isKindOfClass:[NSNumber class]]) { + return [self isAnswerValidWithNumber:(NSNumber *)answer]; + } else if ([answer isKindOfClass:[ORKDontKnowAnswer class]]) { + isValid = YES; + } + return isValid; +} + +- (BOOL)isAnswerValidWithNumber:(NSNumber *)number { + BOOL isValid = NO; + if (number) { + isValid = YES; + if (isnan(number.doubleValue)) { + isValid = NO; + } else if (self.minimum && (self.minimum.doubleValue > number.doubleValue)) { + isValid = NO; + } else if (self.maximum && (self.maximum.doubleValue < number.doubleValue)) { + isValid = NO; + } + } + return isValid; +} + +- (BOOL)isAnswerValidWithString:(NSString *)text { + BOOL isValid = NO; + if (text.length > 0) { + NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:text locale:[NSLocale currentLocale]]; + isValid = [self isAnswerValidWithNumber:number]; + } + return isValid; +} + +- (NSString *)localizedInvalidValueStringWithAnswerString:(NSString *)text { + if (!text.length) { + return nil; + } + NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:text locale:[NSLocale currentLocale]]; + if (!num) { + return nil; + } + NSString *string = nil; + NSNumberFormatter *formatter = ORKDecimalNumberFormatter(); + if (self.minimum && (self.minimum.doubleValue > num.doubleValue)) { + string = [NSString localizedStringWithFormat:ORKLocalizedString(@"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM", nil), text, [formatter stringFromNumber:self.minimum]]; + } else if (self.maximum && (self.maximum.doubleValue < num.doubleValue)) { + string = [NSString localizedStringWithFormat:ORKLocalizedString(@"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM", nil), text, [formatter stringFromNumber:self.maximum]]; + } else { + string = [NSString localizedStringWithFormat:ORKLocalizedString(@"RANGE_ALERT_MESSAGE_OTHER", nil), text]; + } + return string; +} + +- (NSString *)stringForAnswer:(id)answer { + NSString *answerString = nil; + if ([self isAnswerValid:answer]) { + NSNumberFormatter *formatter = ORKDecimalNumberFormatter(); + answerString = [formatter stringFromNumber:answer]; + if (self.unit && self.unit.length > 0) { + answerString = [NSString stringWithFormat:@"%@ %@", answerString, self.unit]; + } + } + return answerString; +} + +#pragma mark - Text Sanitization + +- (NSString *)removeDecimalSeparatorsFromText:(NSString *)text numAllowed:(NSInteger)numAllowed separator:(NSString *)decimalSeparator { + NSMutableString *scanningText = [text mutableCopy]; + NSMutableString *sanitizedText = [[NSMutableString alloc] init]; + BOOL finished = NO; + while (!finished) { + NSRange range = [scanningText rangeOfString:decimalSeparator]; + if (range.length == 0) { + // If our range's length is 0, there are no more decimal separators + [sanitizedText appendString:scanningText]; + finished = YES; + } else if (numAllowed <= 0) { + // If we found a decimal separator and no more are allowed, remove the substring + [scanningText deleteCharactersInRange:range]; + } else { + NSInteger maxRange = NSMaxRange(range); + NSString *processedString = [scanningText substringToIndex:maxRange]; + [sanitizedText appendString:processedString]; + [scanningText deleteCharactersInRange:NSMakeRange(0, maxRange)]; + --numAllowed; + } + } + return sanitizedText; +} + +- (NSString *)sanitizedTextFieldText:(NSString *)text decimalSeparator:(NSString *)separator { + NSString *sanitizedText = text; + if (_style == ORKNumericAnswerStyleDecimal) { + sanitizedText = [self removeDecimalSeparatorsFromText:text numAllowed:1 separator:(NSString *)separator]; + if (self.maximumFractionDigits) { + NSArray *components = [sanitizedText componentsSeparatedByString:separator]; + if([components count] >= 2 && [components[1] length] > [self.maximumFractionDigits integerValue]) { + NSString *rightOfDecimal = [components[1] substringToIndex:[self.maximumFractionDigits integerValue]]; + sanitizedText = [NSString stringWithFormat:@"%@%@%@", components[0], separator, rightOfDecimal]; + } + } + } else if (_style == ORKNumericAnswerStyleInteger) { + sanitizedText = [self removeDecimalSeparatorsFromText:text numAllowed:0 separator:(NSString *)separator]; + } + return sanitizedText; +} + +@end + + +#pragma mark - ORKScaleAnswerFormat + +@implementation ORKScaleAnswerFormat { + NSNumberFormatter *_numberFormatter; +} + +- (Class)questionResultClass { + return [ORKScaleQuestionResult class]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription { + self = [super init]; + if (self) { + _minimum = minimumValue; + _maximum = maximumValue; + _defaultValue = defaultValue; + _step = step; + _vertical = vertical; + _hideSelectedValue = NO; + _maximumValueDescription = maximumValueDescription; + _minimumValueDescription = minimumValueDescription; + _hideRanges = NO; + _hideLabels = NO; + _hideValueMarkers = NO; + + [self validateParameters]; + } + return self; +} + +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step + vertical:(BOOL)vertical { + return [self initWithMaximumValue:maximumValue + minimumValue:minimumValue + defaultValue:defaultValue + step:step + vertical:vertical + maximumValueDescription:nil + minimumValueDescription:nil]; +} + +- (instancetype)initWithMaximumValue:(NSInteger)maximumValue + minimumValue:(NSInteger)minimumValue + defaultValue:(NSInteger)defaultValue + step:(NSInteger)step { + return [self initWithMaximumValue:maximumValue + minimumValue:minimumValue + defaultValue:defaultValue + step:step + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; +} + +- (NSNumber *)minimumNumber { + return @(_minimum); +} +- (NSNumber *)maximumNumber { + return @(_maximum); +} +- (NSNumber *)defaultAnswer { + + if (_defaultValue > _maximum || _defaultValue < _minimum) { + return nil; + } + + NSInteger integer = round( (double)( _defaultValue - _minimum ) / (double)_step ) * _step + _minimum; + + return @(integer); +} +- (NSString *)localizedStringForNumber:(NSNumber *)number { + return [self.numberFormatter stringFromNumber:number]; +} + +- (NSArray *)textChoices { + return nil; +} + +- (NSNumberFormatter *)numberFormatter { + if (!_numberFormatter) { + _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + _numberFormatter.locale = [NSLocale autoupdatingCurrentLocale]; + _numberFormatter.maximumFractionDigits = 0; + } + return _numberFormatter; +} + +- (NSInteger)numberOfSteps { + return (_maximum - _minimum) / _step; +} + +- (NSNumber *)normalizedValueForNumber:(NSNumber *)number { + return @(number.integerValue); +} + +- (void)validateParameters { + [super validateParameters]; + + const NSInteger ORKScaleAnswerFormatMinimumStepSize = 1; + const NSInteger ORKScaleAnswerFormatMinimumStepCount = 1; + const NSInteger ORKScaleAnswerFormatMaximumStepCount = 13; + + const NSInteger ORKScaleAnswerFormatValueLowerbound = -10000; + const NSInteger ORKScaleAnswerFormatValueUpperbound = 10000; + + if (_maximum < _minimum) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Expect maximumValue larger than minimumValue"] userInfo:nil]; + } + + if (_step < ORKScaleAnswerFormatMinimumStepSize) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Expect step value not less than than %@.", @(ORKScaleAnswerFormatMinimumStepSize)] + userInfo:nil]; + } + + NSInteger mod = (_maximum - _minimum) % _step; + if (mod != 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Expect the difference between maximumValue and minimumValue is divisible by step value"] userInfo:nil]; + } + + NSInteger steps = (_maximum - _minimum) / _step; + if (steps < ORKScaleAnswerFormatMinimumStepCount || steps > ORKScaleAnswerFormatMaximumStepCount) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"Expect the total number of steps between minimumValue and maximumValue more than %@ and no more than %@.", @(ORKScaleAnswerFormatMinimumStepCount), @(ORKScaleAnswerFormatMaximumStepCount)] + userInfo:nil]; + } + + if (_minimum < ORKScaleAnswerFormatValueLowerbound) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"minimumValue should not less than %@", @(ORKScaleAnswerFormatValueLowerbound)] + userInfo:nil]; + } + + if (_maximum > ORKScaleAnswerFormatValueUpperbound) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"maximumValue should not more than %@", @(ORKScaleAnswerFormatValueUpperbound)] + userInfo:nil]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, maximum); + ORK_DECODE_INTEGER(aDecoder, minimum); + ORK_DECODE_INTEGER(aDecoder, step); + ORK_DECODE_INTEGER(aDecoder, defaultValue); + ORK_DECODE_BOOL(aDecoder, vertical); + ORK_DECODE_BOOL(aDecoder, hideSelectedValue); + ORK_DECODE_BOOL(aDecoder, hideRanges); + ORK_DECODE_BOOL(aDecoder, hideLabels); + ORK_DECODE_BOOL(aDecoder, hideValueMarkers); + ORK_DECODE_OBJ(aDecoder, maximumValueDescription); + ORK_DECODE_OBJ(aDecoder, minimumValueDescription); + ORK_DECODE_IMAGE(aDecoder, maximumImage); + ORK_DECODE_IMAGE(aDecoder, minimumImage); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientColors, UIColor); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientLocations, NSNumber); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, maximum); + ORK_ENCODE_INTEGER(aCoder, minimum); + ORK_ENCODE_INTEGER(aCoder, step); + ORK_ENCODE_INTEGER(aCoder, defaultValue); + ORK_ENCODE_BOOL(aCoder, vertical); + ORK_ENCODE_BOOL(aCoder, hideSelectedValue); + ORK_ENCODE_BOOL(aCoder, hideRanges); + ORK_ENCODE_BOOL(aCoder, hideLabels); + ORK_ENCODE_BOOL(aCoder, hideValueMarkers); + ORK_ENCODE_OBJ(aCoder, maximumValueDescription); + ORK_ENCODE_OBJ(aCoder, minimumValueDescription); + ORK_ENCODE_IMAGE(aCoder, maximumImage); + ORK_ENCODE_IMAGE(aCoder, minimumImage); + ORK_ENCODE_OBJ(aCoder, gradientColors); + ORK_ENCODE_OBJ(aCoder, gradientLocations); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (_maximum == castObject.maximum) && + (_minimum == castObject.minimum) && + (_step == castObject.step) && + (_defaultValue == castObject.defaultValue) && + (_hideLabels == castObject.hideLabels) && + (_hideRanges == castObject.hideRanges) && + (_hideValueMarkers == castObject.hideValueMarkers) && + (_hideSelectedValue == castObject.hideSelectedValue) && + ORKEqualObjects(self.maximumValueDescription, castObject.maximumValueDescription) && + ORKEqualObjects(self.minimumValueDescription, castObject.minimumValueDescription) && + ORKEqualObjects(self.maximumImage, castObject.maximumImage) && + ORKEqualObjects(self.minimumImage, castObject.minimumImage) && + ORKEqualObjects(self.gradientColors, castObject.gradientColors) && + ORKEqualObjects(self.gradientLocations, castObject.gradientLocations)); +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeScale; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self localizedStringForNumber:answer]; +} + +- (BOOL)shouldHideRanges { + return _hideRanges; +} + +- (BOOL)shouldHideLabels { + return _hideLabels; +} + +- (BOOL)shouldHideValueMarkers { + return _hideValueMarkers; +} + +@end + + +#pragma mark - ORKContinuousScaleAnswerFormat + +@implementation ORKContinuousScaleAnswerFormat { + NSNumberFormatter *_numberFormatter; +} + +- (Class)questionResultClass { + return [ORKScaleQuestionResult class]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical + maximumValueDescription:(nullable NSString *)maximumValueDescription + minimumValueDescription:(nullable NSString *)minimumValueDescription { + self = [super init]; + if (self) { + _minimum = minimumValue; + _maximum = maximumValue; + _defaultValue = defaultValue; + _maximumFractionDigits = maximumFractionDigits; + _vertical = vertical; + _hideSelectedValue = NO; + _maximumValueDescription = maximumValueDescription; + _minimumValueDescription = minimumValueDescription; + _hideRanges = NO; + _hideLabels = NO; + + [self validateParameters]; + } + return self; +} + +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits + vertical:(BOOL)vertical { + return [self initWithMaximumValue:maximumValue + minimumValue:minimumValue + defaultValue:defaultValue + maximumFractionDigits:maximumFractionDigits + vertical:vertical + maximumValueDescription:nil + minimumValueDescription:nil]; +} + +- (instancetype)initWithMaximumValue:(double)maximumValue + minimumValue:(double)minimumValue + defaultValue:(double)defaultValue + maximumFractionDigits:(NSInteger)maximumFractionDigits { + return [self initWithMaximumValue:maximumValue + minimumValue:minimumValue + defaultValue:defaultValue + maximumFractionDigits:maximumFractionDigits + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; +} + +- (NSNumber *)minimumNumber { + return @(_minimum); +} +- (NSNumber *)maximumNumber { + return @(_maximum); +} +- (NSNumber *)defaultAnswer { + if ( _defaultValue > _maximum || _defaultValue < _minimum) { + return nil; + } + return @(_defaultValue); +} +- (NSString *)localizedStringForNumber:(NSNumber *)number { + return [self.numberFormatter stringFromNumber:number]; +} + +- (NSArray *)textChoices { + return nil; +} + +- (NSNumberFormatter *)numberFormatter { + if (!_numberFormatter) { + _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = ORKNumberFormattingStyleConvert(_numberStyle); + _numberFormatter.maximumFractionDigits = _maximumFractionDigits; + } + return _numberFormatter; +} + +- (NSInteger)numberOfSteps { + return 0; +} + +- (NSNumber *)normalizedValueForNumber:(NSNumber *)number { + return number; +} + +- (void)validateParameters { + [super validateParameters]; + + const double ORKScaleAnswerFormatValueLowerbound = -10000; + const double ORKScaleAnswerFormatValueUpperbound = 10000; + + // Just clamp maximumFractionDigits to be 0-4. This is all aimed at keeping the maximum + // number of digits down to 6 or less. + _maximumFractionDigits = MAX(_maximumFractionDigits, 0); + _maximumFractionDigits = MIN(_maximumFractionDigits, 4); + + double effectiveUpperbound = ORKScaleAnswerFormatValueUpperbound * pow(0.1, _maximumFractionDigits); + double effectiveLowerbound = ORKScaleAnswerFormatValueLowerbound * pow(0.1, _maximumFractionDigits); + + if (_maximum <= _minimum) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Expect maximumValue larger than minimumValue"] userInfo:nil]; + } + + if (_minimum < effectiveLowerbound) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"minimumValue should not less than %@ with %@ fractional digits", @(effectiveLowerbound), @(_maximumFractionDigits)] + userInfo:nil]; + } + + if (_maximum > effectiveUpperbound) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"maximumValue should not more than %@ with %@ fractional digits", @(effectiveUpperbound), @(_maximumFractionDigits)] + userInfo:nil]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, maximum); + ORK_DECODE_DOUBLE(aDecoder, minimum); + ORK_DECODE_DOUBLE(aDecoder, defaultValue); + ORK_DECODE_INTEGER(aDecoder, maximumFractionDigits); + ORK_DECODE_BOOL(aDecoder, vertical); + ORK_DECODE_ENUM(aDecoder, numberStyle); + ORK_DECODE_BOOL(aDecoder, hideSelectedValue); + ORK_DECODE_BOOL(aDecoder, hideLabels); + ORK_DECODE_BOOL(aDecoder, hideRanges); + ORK_DECODE_OBJ(aDecoder, maximumValueDescription); + ORK_DECODE_OBJ(aDecoder, minimumValueDescription); + ORK_DECODE_IMAGE(aDecoder, maximumImage); + ORK_DECODE_IMAGE(aDecoder, minimumImage); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientColors, UIColor); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientLocations, NSNumber); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, maximum); + ORK_ENCODE_DOUBLE(aCoder, minimum); + ORK_ENCODE_DOUBLE(aCoder, defaultValue); + ORK_ENCODE_INTEGER(aCoder, maximumFractionDigits); + ORK_ENCODE_BOOL(aCoder, vertical); + ORK_ENCODE_BOOL(aCoder, hideSelectedValue); + ORK_ENCODE_BOOL(aCoder, hideLabels); + ORK_ENCODE_BOOL(aCoder, hideRanges); + ORK_ENCODE_ENUM(aCoder, numberStyle); + ORK_ENCODE_OBJ(aCoder, maximumValueDescription); + ORK_ENCODE_OBJ(aCoder, minimumValueDescription); + ORK_ENCODE_IMAGE(aCoder, maximumImage); + ORK_ENCODE_IMAGE(aCoder, minimumImage); + ORK_ENCODE_OBJ(aCoder, gradientColors); + ORK_ENCODE_OBJ(aCoder, gradientLocations); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (_maximum == castObject.maximum) && + (_minimum == castObject.minimum) && + (_defaultValue == castObject.defaultValue) && + (_maximumFractionDigits == castObject.maximumFractionDigits) && + (_numberStyle == castObject.numberStyle) && + (_hideSelectedValue == castObject.hideSelectedValue) && + (_hideLabels == castObject.hideLabels) && + (_hideRanges == castObject.hideRanges) && + ORKEqualObjects(self.maximumValueDescription, castObject.maximumValueDescription) && + ORKEqualObjects(self.minimumValueDescription, castObject.minimumValueDescription) && + ORKEqualObjects(self.maximumImage, castObject.maximumImage) && + ORKEqualObjects(self.minimumImage, castObject.minimumImage) && + ORKEqualObjects(self.gradientColors, castObject.gradientColors) && + ORKEqualObjects(self.gradientLocations, castObject.gradientLocations)); +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeScale; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self localizedStringForNumber:answer]; +} + +- (BOOL)shouldHideRanges { + return _hideRanges; +} + +- (BOOL)shouldHideLabels { + return _hideLabels; +} + +- (BOOL)shouldHideValueMarkers { + return NO; +} + +@end + + +#pragma mark - ORKTextScaleAnswerFormat + +@interface ORKTextScaleAnswerFormat () { + + ORKChoiceAnswerFormatHelper *_helper; +} + +@end + + +@implementation ORKTextScaleAnswerFormat { + NSNumberFormatter *_numberFormatter; +} + +- (Class)questionResultClass { + return [ORKChoiceQuestionResult class]; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex + vertical:(BOOL)vertical { + self = [super init]; + if (self) { + _textChoices = [textChoices copy]; + _defaultIndex = defaultIndex; + _vertical = vertical; + _hideSelectedValue = NO; + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:self]; + _hideRanges = NO; + _hideLabels = NO; + _hideValueMarkers = NO; + + [self validateParameters]; + } + return self; +} + +- (instancetype)initWithTextChoices:(NSArray *)textChoices + defaultIndex:(NSInteger)defaultIndex { + return [self initWithTextChoices:textChoices + defaultIndex:defaultIndex + vertical:NO]; +} + +- (NSNumber *)minimumNumber { + return @(1); +} +- (NSNumber *)maximumNumber { + return @(_textChoices.count); +} +- (id)defaultAnswer { + if (_defaultIndex < 0 || _defaultIndex >= _textChoices.count) { + return nil; + } + id value = [self textChoiceAtIndex:_defaultIndex].value; + return value ? @[value] : nil; +} +- (NSString *)localizedStringForNumber:(NSNumber *)number { + return [self.numberFormatter stringFromNumber:number]; +} +- (NSString *)minimumValueDescription { + return _textChoices.firstObject.text; +} +- (NSString *)maximumValueDescription { + return _textChoices.lastObject.text; +} +- (UIImage *)minimumImage { + return nil; +} +- (UIImage *)maximumImage { + return nil; +} + +- (NSNumberFormatter *)numberFormatter { + if (!_numberFormatter) { + _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + _numberFormatter.locale = [NSLocale autoupdatingCurrentLocale]; + _numberFormatter.maximumFractionDigits = 0; + } + return _numberFormatter; +} + +- (NSInteger)numberOfSteps { + return _textChoices.count - 1; +} + +- (NSNumber *)normalizedValueForNumber:(NSNumber *)number { + return @([number integerValue]); +} + +- (ORKTextChoice *)textChoiceAtIndex:(NSUInteger)index { + + if (index >= _textChoices.count) { + return nil; + } + return _textChoices[index]; +} + +- (ORKTextChoice *)textChoiceForValue:(id)value { + __block ORKTextChoice *choice = nil; + + [_textChoices enumerateObjectsUsingBlock:^(ORKTextChoice * _Nonnull textChoice, NSUInteger idx, BOOL * _Nonnull stop) { + if ([textChoice.value isEqual:value]) { + choice = textChoice; + *stop = YES; + } + }]; + + return choice; +} + +- (NSUInteger)textChoiceIndexForValue:(id)value { + ORKTextChoice *choice = [self textChoiceForValue:value]; + return choice ? [_textChoices indexOfObject:choice] : NSNotFound; +} + +- (void)validateParameters { + [super validateParameters]; + + if (_textChoices.count < 2) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Must have a minimum of 2 text choices." userInfo:nil]; + } else if (_textChoices.count > 8) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Cannot have more than 8 text choices." userInfo:nil]; + } + + ORKValidateArrayForObjectsOfClass(_textChoices, [ORKTextChoice class], @"Text choices must be of class ORKTextChoice."); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, textChoices, ORKTextChoice); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientColors, UIColor); + ORK_DECODE_OBJ_ARRAY(aDecoder, gradientLocations, NSNumber); + ORK_DECODE_INTEGER(aDecoder, defaultIndex); + ORK_DECODE_BOOL(aDecoder, vertical); + ORK_DECODE_BOOL(aDecoder, hideSelectedValue); + ORK_DECODE_BOOL(aDecoder, hideValueMarkers); + ORK_DECODE_BOOL(aDecoder, hideLabels); + ORK_DECODE_BOOL(aDecoder, hideRanges); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, textChoices); + ORK_ENCODE_OBJ(aCoder, gradientColors); + ORK_ENCODE_OBJ(aCoder, gradientLocations); + ORK_ENCODE_INTEGER(aCoder, defaultIndex); + ORK_ENCODE_BOOL(aCoder, vertical); + ORK_ENCODE_BOOL(aCoder, hideSelectedValue); + ORK_ENCODE_BOOL(aCoder, hideValueMarkers); + ORK_ENCODE_BOOL(aCoder, hideLabels); + ORK_ENCODE_BOOL(aCoder, hideRanges); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.textChoices, castObject.textChoices) && + (_defaultIndex == castObject.defaultIndex) && + (_vertical == castObject.vertical) && + (_hideSelectedValue == castObject.hideSelectedValue) && + (_hideValueMarkers == castObject.hideValueMarkers) && + (_hideLabels == castObject.hideLabels) && + (_hideRanges == castObject.hideRanges) && + ORKEqualObjects(self.gradientColors, castObject.gradientColors) && + ORKEqualObjects(self.gradientLocations, castObject.gradientLocations)); +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeScale; +} + +- (NSString *)stringForAnswer:(id)answer { + return [_helper stringForChoiceAnswer:answer]; +} + +- (BOOL)shouldHideRanges { + return _hideRanges; +} + +- (BOOL)shouldHideLabels { + return _hideLabels; +} + +- (BOOL)shouldHideValueMarkers { + return _hideValueMarkers; +} + +@end + + +#pragma mark - ORKTextAnswerFormat + +@implementation ORKTextAnswerFormat + +- (Class)questionResultClass { + return [ORKTextQuestionResult class]; +} + +- (void)commonInit { + _autocapitalizationType = UITextAutocapitalizationTypeSentences; + _autocorrectionType = UITextAutocorrectionTypeDefault; + _spellCheckingType = UITextSpellCheckingTypeDefault; + _keyboardType = UIKeyboardTypeDefault; + _multipleLines = NO; +} + +- (instancetype)initWithMaximumLength:(NSInteger)maximumLength { + self = [super init]; + if (self) { + _maximumLength = maximumLength; + [self commonInit]; + } + return self; +} + +- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage { + self = [super init]; + if (self) { + _validationRegularExpression = [validationRegularExpression copy]; + _invalidMessage = [invalidMessage copy]; + _maximumLength = 0; + [self commonInit]; + } + return self; +} + +- (instancetype)init { + self = [self initWithMaximumLength:0]; + return self; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeText; +} + +- (void)validateParameters { + [super validateParameters]; + + if ( (!self.validationRegularExpression && self.invalidMessage) || + (self.validationRegularExpression && !self.invalidMessage) ) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"Both regular expression and invalid message properties must be set." + userInfo:nil]; + } +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTextAnswerFormat *answerFormat = [[[self class] allocWithZone:zone] init]; + answerFormat->_maximumLength = _maximumLength; + answerFormat->_validationRegularExpression = [_validationRegularExpression copy]; + answerFormat->_invalidMessage = [_invalidMessage copy]; + answerFormat->_defaultTextAnswer = [_defaultTextAnswer copy]; + answerFormat->_autocapitalizationType = _autocapitalizationType; + answerFormat->_autocorrectionType = _autocorrectionType; + answerFormat->_spellCheckingType = _spellCheckingType; + answerFormat->_keyboardType = _keyboardType; + answerFormat->_multipleLines = _multipleLines; + answerFormat->_secureTextEntry = _secureTextEntry; + answerFormat->_textContentType = _textContentType; + answerFormat->_placeholder = _placeholder; + answerFormat.showDontKnowButton = self.showDontKnowButton; + answerFormat.customDontKnowButtonText = [self.customDontKnowButtonText copy]; + + if (@available(iOS 12.0, *)) { + answerFormat->_passwordRules = _passwordRules; + } + + return answerFormat; +} + +- (BOOL)isAnswerValid:(id)answer { + BOOL isValid = NO; + if ([answer isKindOfClass:[NSString class]]) { + isValid = [self isAnswerValidWithString:(NSString *)answer]; + } else if ([answer isKindOfClass:[ORKDontKnowAnswer class]]) { + isValid = YES; + } + return isValid; +} + +- (BOOL)isAnswerValidWithString:(NSString *)text { + BOOL isValid = YES; + if (text && text.length > 0) { + isValid = ([self isTextLengthValidWithString:text] && [self isTextRegularExpressionValidWithString:text]); + } + return isValid; +} + +- (BOOL)isTextLengthValidWithString:(NSString *)text { + return (_maximumLength == 0 || text.length <= _maximumLength); +} + +- (BOOL)isTextRegularExpressionValidWithString:(NSString *)text { + BOOL isValid = YES; + if (self.validationRegularExpression) { + NSUInteger regularExpressionMatches = [_validationRegularExpression numberOfMatchesInString:text + options:(NSMatchingOptions)0 + range:NSMakeRange(0, [text length])]; + isValid = (regularExpressionMatches != 0); + } + return isValid; +} + +- (NSString *)localizedInvalidValueStringWithAnswerString:(NSString *)text { + NSString *string = @""; + if (![self isTextLengthValidWithString:text]) { + string = [NSString localizedStringWithFormat:ORKLocalizedString(@"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE", nil), ORKLocalizedStringFromNumber(@(_maximumLength))]; + } + if (![self isTextRegularExpressionValidWithString:text]) { + if (string.length > 0) { + string = [string stringByAppendingString:@"\n"]; + } + string = [string stringByAppendingString:[NSString localizedStringWithFormat:ORKLocalizedString(_invalidMessage, nil), text]]; + } + return string; +} + + +- (ORKAnswerFormat *)confirmationAnswerFormatWithOriginalItemIdentifier:(NSString *)originalItemIdentifier + errorMessage:(NSString *)errorMessage { + + NSAssert(!self.multipleLines, @"Confirmation Answer Format is not currently defined for ORKTextAnswerFormat with multiple lines."); + + ORKTextAnswerFormat *answerFormat = [[ORKConfirmTextAnswerFormat alloc] initWithOriginalItemIdentifier:originalItemIdentifier errorMessage:errorMessage]; + + // Copy from ORKTextAnswerFormat being confirmed + answerFormat->_maximumLength = _maximumLength; + answerFormat->_keyboardType = _keyboardType; + answerFormat->_multipleLines = _multipleLines; + answerFormat->_secureTextEntry = _secureTextEntry; + answerFormat->_autocapitalizationType = _autocapitalizationType; + answerFormat->_textContentType = _textContentType; + + if (@available(iOS 12.0, *)) { + answerFormat->_passwordRules = _passwordRules; + } + + // Always set to no autocorrection or spell checking + answerFormat->_autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat->_spellCheckingType = UITextSpellCheckingTypeNo; + answerFormat->_placeholder = _placeholder; + + return answerFormat; +} + +#pragma mark NSSecureCoding + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + _multipleLines = NO; + ORK_DECODE_INTEGER(aDecoder, maximumLength); + ORK_DECODE_OBJ_CLASS(aDecoder, validationRegularExpression, NSRegularExpression); + ORK_DECODE_OBJ_CLASS(aDecoder, invalidMessage, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, defaultTextAnswer, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, textContentType, NSString); + if (@available(iOS 12.0, *)) { + ORK_DECODE_OBJ_CLASS(aDecoder, passwordRules, UITextInputPasswordRules); + } + ORK_DECODE_ENUM(aDecoder, autocapitalizationType); + ORK_DECODE_ENUM(aDecoder, autocorrectionType); + ORK_DECODE_ENUM(aDecoder, spellCheckingType); + ORK_DECODE_ENUM(aDecoder, keyboardType); + ORK_DECODE_BOOL(aDecoder, multipleLines); + ORK_DECODE_BOOL(aDecoder, secureTextEntry); + ORK_DECODE_OBJ_CLASS(aDecoder, placeholder, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, maximumLength); + ORK_ENCODE_OBJ(aCoder, validationRegularExpression); + ORK_ENCODE_OBJ(aCoder, invalidMessage); + ORK_ENCODE_OBJ(aCoder, defaultTextAnswer); + ORK_ENCODE_OBJ(aCoder, textContentType); + if (@available(iOS 12.0, *)) { + ORK_ENCODE_OBJ(aCoder, passwordRules); + } + ORK_ENCODE_ENUM(aCoder, autocapitalizationType); + ORK_ENCODE_ENUM(aCoder, autocorrectionType); + ORK_ENCODE_ENUM(aCoder, spellCheckingType); + ORK_ENCODE_ENUM(aCoder, keyboardType); + ORK_ENCODE_BOOL(aCoder, multipleLines); + ORK_ENCODE_BOOL(aCoder, secureTextEntry); + ORK_ENCODE_OBJ(aCoder, placeholder); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + BOOL equalPasswordRules = YES; + + __typeof(self) castObject = object; + + if (@available(iOS 12.0, *)) { + equalPasswordRules = ORKEqualObjects(self.passwordRules, castObject.passwordRules); + } + return (isParentSame && + (self.maximumLength == castObject.maximumLength && + ORKEqualObjects(self.validationRegularExpression, castObject.validationRegularExpression) && + ORKEqualObjects(self.invalidMessage, castObject.invalidMessage) && + ORKEqualObjects(self.defaultTextAnswer, castObject.defaultTextAnswer) && + self.autocapitalizationType == castObject.autocapitalizationType && + self.autocorrectionType == castObject.autocorrectionType && + self.spellCheckingType == castObject.spellCheckingType && + self.keyboardType == castObject.keyboardType && + ORKEqualObjects(self.textContentType, castObject.textContentType) && + equalPasswordRules && + self.multipleLines == castObject.multipleLines) && + self.secureTextEntry == castObject.secureTextEntry) && + ORKEqualObjects(self.placeholder, castObject.placeholder); +} + +static NSString *const kSecureTextEntryEscapeString = @"*"; + +- (NSString *)stringForAnswer:(id)answer { + NSString *answerString = nil; + if ([self isAnswerValid:answer]) { + answerString = _secureTextEntry ? [@"" stringByPaddingToLength:((NSString *)answer).length withString:kSecureTextEntryEscapeString startingAtIndex:0] : answer; + } + return answerString; +} + +@end + + +#pragma mark - ORKEmailAnswerFormat + +@implementation ORKEmailAnswerFormat { + ORKTextAnswerFormat *_impliedAnswerFormat; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeText; +} + +- (Class)questionResultClass { + return [ORKTextQuestionResult class]; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + if (!_impliedAnswerFormat) { + NSRegularExpression *validationRegularExpression = + [NSRegularExpression regularExpressionWithPattern:EmailValidationRegularExpressionPattern + options:(NSRegularExpressionOptions)0 + error:nil]; + NSString *invalidMessage = ORKLocalizedString(@"INVALID_EMAIL_ALERT_MESSAGE", nil); + _impliedAnswerFormat = [ORKTextAnswerFormat textAnswerFormatWithValidationRegularExpression:validationRegularExpression + invalidMessage:invalidMessage]; + _impliedAnswerFormat.keyboardType = UIKeyboardTypeEmailAddress; + _impliedAnswerFormat.multipleLines = NO; + _impliedAnswerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + _impliedAnswerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone; + _impliedAnswerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + _impliedAnswerFormat.textContentType = UITextContentTypeEmailAddress; + } + return _impliedAnswerFormat; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self.impliedAnswerFormat stringForAnswer:answer]; +} + +- (void)setUsernameField:(BOOL)usernameField { + _usernameField = usernameField; + if ([self.impliedAnswerFormat isMemberOfClass:[ORKTextAnswerFormat class]]) { + ORKTextAnswerFormat *textFormat = (ORKTextAnswerFormat *)self.impliedAnswerFormat; + textFormat.textContentType = usernameField ? UITextContentTypeUsername : UITextContentTypeEmailAddress; + } +} + +@end + + +#pragma mark - ORKConfirmTextAnswerFormat + +@implementation ORKConfirmTextAnswerFormat + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +// Don't throw on -init nor -initWithMaximumLength: because they're internally used by -copyWithZone: + +- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithOriginalItemIdentifier:(NSString *)originalItemIdentifier + errorMessage:(NSString *)errorMessage { + + NSParameterAssert(originalItemIdentifier); + NSParameterAssert(errorMessage); + + self = [super init]; + if (self) { + _originalItemIdentifier = [originalItemIdentifier copy]; + _errorMessage = [errorMessage copy]; + } + return self; +} + +- (BOOL)isAnswerValid:(id)answer { + BOOL isValid = NO; + if ([answer isKindOfClass:[NSString class]]) { + NSString *stringAnswer = (NSString *)answer; + isValid = (stringAnswer.length > 0); + } else if ([answer isKindOfClass:[ORKDontKnowAnswer class]]) { + isValid = YES; + } + return isValid; +} + +- (NSString *)localizedInvalidValueStringWithAnswerString:(NSString *)text { + return self.errorMessage; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConfirmTextAnswerFormat *answerFormat = [super copyWithZone:zone]; + answerFormat->_originalItemIdentifier = [_originalItemIdentifier copy]; + answerFormat->_errorMessage = [_errorMessage copy]; + return answerFormat; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, originalItemIdentifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, errorMessage, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, originalItemIdentifier); + ORK_ENCODE_OBJ(aCoder, errorMessage); +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.originalItemIdentifier, castObject.originalItemIdentifier) && + ORKEqualObjects(self.errorMessage, castObject.errorMessage)); +} + +@end + + +#pragma mark - ORKTimeIntervalAnswerFormat + +@implementation ORKTimeIntervalAnswerFormat + +- (Class)questionResultClass { + return [ORKTimeIntervalQuestionResult class]; +} + +- (instancetype)init { + self = [self initWithDefaultInterval:0 step:1]; + return self; +} + +- (instancetype)initWithDefaultInterval:(NSTimeInterval)defaultInterval step:(NSInteger)step { + self = [super init]; + if (self) { + _defaultInterval = defaultInterval; + _step = step; + [self validateParameters]; + } + return self; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeTimeInterval; +} + +- (NSTimeInterval)pickerDefaultDuration { + + NSTimeInterval value = MAX([self defaultInterval], 0); + + // imitate UIDatePicker's behavior + NSTimeInterval stepInSeconds = _step * 60; + value = floor(value/stepInSeconds)*stepInSeconds; + + return value; +} + +- (void)validateParameters { + [super validateParameters]; + + const NSInteger ORKTimeIntervalAnswerFormatStepLowerBound = 1; + const NSInteger ORKTimeIntervalAnswerFormatStepUpperBound = 30; + + if (_step < ORKTimeIntervalAnswerFormatStepLowerBound || _step > ORKTimeIntervalAnswerFormatStepUpperBound) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"Step should be between %@ and %@.", @(ORKTimeIntervalAnswerFormatStepLowerBound), @(ORKTimeIntervalAnswerFormatStepUpperBound)] userInfo:nil]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_DOUBLE(aDecoder, defaultInterval); + ORK_DECODE_DOUBLE(aDecoder, step); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_DOUBLE(aCoder, defaultInterval); + ORK_ENCODE_DOUBLE(aCoder, step); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (_defaultInterval == castObject.defaultInterval) && + (_step == castObject.step)); +} + +- (NSString *)stringForAnswer:(id)answer { + return [ORKTimeIntervalLabelFormatter() stringFromTimeInterval:((NSNumber *)answer).floatValue]; +} + +@end + + +#pragma mark - ORKHeightAnswerFormat + +@implementation ORKHeightAnswerFormat + +- (Class)questionResultClass { + return [ORKNumericQuestionResult class]; +} + +- (NSString *)canonicalUnitString { + return @"cm"; +} + +- (ORKNumericQuestionResult *)resultWithIdentifier:(NSString *)identifier answer:(NSNumber *)answer { + ORKNumericQuestionResult *questionResult = (ORKNumericQuestionResult *)[super resultWithIdentifier:identifier answer:answer]; + // Use canonical unit because we expect results to be consistent regardless of the user locale + questionResult.unit = [self canonicalUnitString]; + return questionResult; +} + +- (instancetype)init { + self = [self initWithMeasurementSystem:ORKMeasurementSystemLocal]; + return self; +} + +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem { + self = [super init]; + if (self) { + _measurementSystem = measurementSystem; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.measurementSystem == castObject.measurementSystem)); +} + +- (NSUInteger)hash { + return super.hash ^ _measurementSystem; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, measurementSystem); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, measurementSystem); +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeHeight; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)useMetricSystem { + return _measurementSystem == ORKMeasurementSystemMetric + || (_measurementSystem == ORKMeasurementSystemLocal && ((NSNumber *)[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem]).boolValue); +} + +- (NSString *)stringForAnswer:(id)answer { + NSString *answerString = nil; + + if (!ORKIsAnswerEmpty(answer)) { + NSNumberFormatter *formatter = ORKDecimalNumberFormatter(); + if (self.useMetricSystem) { + answerString = [NSString stringWithFormat:@"%@ %@", [formatter stringFromNumber:answer], ORKLocalizedString(@"MEASURING_UNIT_CM", nil)]; + } else { + double feet, inches; + ORKCentimetersToFeetAndInches(((NSNumber *)answer).doubleValue, &feet, &inches); + NSString *feetString = [formatter stringFromNumber:@(feet)]; + NSString *inchesString = [formatter stringFromNumber:@(inches)]; + answerString = [NSString stringWithFormat:@"%@ %@, %@ %@", + feetString, ORKLocalizedString(@"MEASURING_UNIT_FT", nil), inchesString, ORKLocalizedString(@"MEASURING_UNIT_IN", nil)]; + } + } + return answerString; +} + +@end + + +#pragma mark - ORKWeightAnswerFormat + +@implementation ORKWeightAnswerFormat + +- (Class)questionResultClass { + return [ORKNumericQuestionResult class]; +} + +- (NSString *)canonicalUnitString { + return @"kg"; +} + +- (ORKNumericQuestionResult *)resultWithIdentifier:(NSString *)identifier answer:(NSNumber *)answer { + ORKNumericQuestionResult *questionResult = (ORKNumericQuestionResult *)[super resultWithIdentifier:identifier answer:answer]; + // Use canonical unit because we expect results to be consistent regardless of the user locale + questionResult.unit = [self canonicalUnitString]; + return questionResult; +} + +- (instancetype)init { + return [self initWithMeasurementSystem:ORKMeasurementSystemLocal + numericPrecision:ORKNumericPrecisionDefault + minimumValue:ORKDoubleDefaultValue + maximumValue:ORKDoubleDefaultValue + defaultValue:ORKDoubleDefaultValue]; +} + +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem { + return [self initWithMeasurementSystem:measurementSystem + numericPrecision:ORKNumericPrecisionDefault + minimumValue:ORKDoubleDefaultValue + maximumValue:ORKDoubleDefaultValue + defaultValue:ORKDoubleDefaultValue]; +} + +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision { + return [self initWithMeasurementSystem:measurementSystem + numericPrecision:numericPrecision + minimumValue:ORKDoubleDefaultValue + maximumValue:ORKDoubleDefaultValue + defaultValue:ORKDoubleDefaultValue]; +} + +- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem + numericPrecision:(ORKNumericPrecision)numericPrecision + minimumValue:(double)minimumValue + maximumValue:(double)maximumValue + defaultValue:(double)defaultValue { + if ((defaultValue != ORKDoubleDefaultValue) && ((defaultValue < minimumValue) || (defaultValue > maximumValue))) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"defaultValue must be between minimumValue and maximumValue." + userInfo:nil]; + } + + self = [super init]; + if (self) { + _measurementSystem = measurementSystem; + _numericPrecision = numericPrecision; + _minimumValue = minimumValue; + _maximumValue = maximumValue; + _defaultValue = defaultValue; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (self.measurementSystem == castObject.measurementSystem) && + (self.numericPrecision == castObject.numericPrecision) && + (self.minimumValue == castObject.minimumValue) && + (self.maximumValue == castObject.maximumValue) && + (self.defaultValue == castObject.defaultValue)); +} + +- (NSUInteger)hash { + // Ignore minimumValue, maximumValue and defaultValue as they're unimportant + return super.hash ^ _measurementSystem ^ _numericPrecision; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, measurementSystem); + ORK_DECODE_ENUM(aDecoder, numericPrecision); + ORK_DECODE_DOUBLE(aDecoder, minimumValue); + ORK_DECODE_DOUBLE(aDecoder, maximumValue); + ORK_DECODE_DOUBLE(aDecoder, defaultValue); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, measurementSystem); + ORK_ENCODE_ENUM(aCoder, numericPrecision); + ORK_ENCODE_DOUBLE(aCoder, minimumValue); + ORK_ENCODE_DOUBLE(aCoder, maximumValue); + ORK_ENCODE_DOUBLE(aCoder, defaultValue); +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeWeight; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)useMetricSystem { + return _measurementSystem == ORKMeasurementSystemMetric || (_measurementSystem == ORKMeasurementSystemLocal && ((NSNumber *)[[NSLocale currentLocale] objectForKey:NSLocaleUsesMetricSystem]).boolValue); +} + +- (NSString *)stringForAnswer:(id)answer { + NSString *answerString = nil; + + if (!ORKIsAnswerEmpty(answer)) { + NSNumberFormatter *formatter = ORKDecimalNumberFormatter(); + if (self.useMetricSystem) { + answerString = [NSString stringWithFormat:@"%@ %@", [formatter stringFromNumber:answer], ORKLocalizedString(@"MEASURING_UNIT_KG", nil)]; + } else { + if (self.numericPrecision != ORKNumericPrecisionHigh) { + double pounds = ORKKilogramsToPounds(((NSNumber *)answer).doubleValue); + NSString *poundsString = [formatter stringFromNumber:@(pounds)]; + answerString = [NSString stringWithFormat:@"%@ %@", poundsString, ORKLocalizedString(@"MEASURING_UNIT_LB", nil)]; + } else { + double pounds, ounces; + ORKKilogramsToPoundsAndOunces(((NSNumber *)answer).doubleValue, £s, &ounces); + NSString *poundsString = [formatter stringFromNumber:@(pounds)]; + NSString *ouncesString = [formatter stringFromNumber:@(ounces)]; + answerString = [NSString stringWithFormat:@"%@ %@, %@ %@", poundsString, ORKLocalizedString(@"MEASURING_UNIT_LB", nil), ouncesString, ORKLocalizedString(@"MEASURING_UNIT_OZ", nil)]; + } + } + } + return answerString; +} + +@end + + +#pragma mark - ORKLocationAnswerFormat + +@implementation ORKLocationAnswerFormat + +- (instancetype)init { + self = [super init]; + if (self) { + _useCurrentLocation = YES; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_BOOL(aDecoder, useCurrentLocation); + ORK_DECODE_OBJ_CLASS(aDecoder, placeholder, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_BOOL(aCoder, useCurrentLocation); + ORK_ENCODE_OBJ(aCoder, placeholder); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeLocation; +} + +- (Class)questionResultClass { + return [ORKLocationQuestionResult class]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKLocationAnswerFormat *locationAnswerFormat = [[[self class] allocWithZone:zone] init]; + locationAnswerFormat->_useCurrentLocation = _useCurrentLocation; + return locationAnswerFormat; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + _useCurrentLocation == castObject.useCurrentLocation); +} + +- (NSString *)stringForAnswer:(id)answer { + NSString *answerString = nil; + if ([answer isKindOfClass:[ORKLocation class]]) { + ORKLocation *location = answer; + + CNPostalAddress *postalAddress = location.postalAddress; + answerString = postalAddress ? [CNPostalAddressFormatter stringFromPostalAddress:postalAddress + style:CNPostalAddressFormatterStyleMailingAddress] : + MKStringFromMapPoint(MKMapPointForCoordinate(location.coordinate)); + } + return answerString; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end + +#pragma mark ORKSESAnswerFormat + +@implementation ORKSESAnswerFormat { + NSNumberFormatter *_numberFormatter; +} + +- (instancetype)initWithTopRungText:(NSString *)topRungText bottomRungText:(NSString *)bottomRungText { + self = [super init]; + if (self) { + _topRungText = topRungText; + _bottomRungText = bottomRungText; + } + return self; +} + +- (ORKQuestionType)questionType { + return ORKQuestionTypeSES; +} + +- (Class)questionResultClass { + return [ORKSESQuestionResult class]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, topRungText, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, bottomRungText, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, topRungText); + ORK_ENCODE_OBJ(aCoder, bottomRungText); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSNumberFormatter *)numberFormatter { + if (!_numberFormatter) { + _numberFormatter = [[NSNumberFormatter alloc] init]; + _numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + _numberFormatter.locale = [NSLocale autoupdatingCurrentLocale]; + _numberFormatter.maximumFractionDigits = 0; + } + return _numberFormatter; +} + +- (NSString *)localizedStringForNumber:(NSNumber *)number { + return [self.numberFormatter stringFromNumber:number]; +} + +- (NSString *)stringForAnswer:(id)answer { + return [self localizedStringForNumber:answer]; +} + +- (BOOL)shouldShowDontKnowButton { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Internal.h new file mode 100755 index 0000000..34a02c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Internal.h @@ -0,0 +1,262 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import HealthKit; +#import "ORKAnswerFormat_Private.h" +#import "ORKChoiceAnswerFormatHelper.h" + + +NS_ASSUME_NONNULL_BEGIN + +BOOL ORKIsAnswerEmpty(_Nullable id answer); + +NSString *ORKHKBiologicalSexString(HKBiologicalSex biologicalSex); +NSString *ORKHKBloodTypeString(HKBloodType bloodType); +NSString *ORKQuestionTypeString(ORKQuestionType questionType); + +// Need to mark these as designated initializers to avoid warnings once we designate the others. +#define ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(C) \ +@interface C () \ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; \ +@end + +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKImageChoiceAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKValuePickerAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKMultipleValuePickerAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextChoiceAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextChoice) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKImageChoice) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTimeOfDayAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKDateAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTimeOfDayAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKNumericAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKScaleAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKContinuousScaleAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextScaleAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTextAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKTimeIntervalAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKHeightAnswerFormat) +ORK_DESIGNATE_CODING_AND_SERIALIZATION_INITIALIZERS(ORKWeightAnswerFormat) + + +@class ORKQuestionResult; + +@interface ORKAnswerFormat () + +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +- (BOOL)isHealthKitAnswerFormat; + +- (nullable HKObjectType *)healthKitObjectType; +- (nullable HKObjectType *)healthKitObjectTypeForAuthorization; + +@property (nonatomic, strong, readonly, nullable) HKUnit *healthKitUnit; + +@property (nonatomic, strong, nullable) HKUnit *healthKitUserUnit; + +- (nullable NSString *)localizedInvalidValueStringWithAnswerString:(nullable NSString *)text; + +- (nonnull Class)questionResultClass; + +- (nullable NSString *)stringForAnswer:(id)answer; + +@end + + +@interface ORKNumericAnswerFormat () + +- (nullable NSString *)sanitizedTextFieldText:(nullable NSString *)text decimalSeparator:(nullable NSString *)separator; + +@end + + +/** + The `ORKAnswerOption` protocol defines brief option text for a option which can be included within `ORK*ChoiceAnswerFormat`. + */ +@protocol ORKAnswerOption + +/** + Brief option text. + */ +- (NSString *)text; + +/** + The value to be returned if this option is selected. + + Expected to be a scalar type serializable to JSON, e.g. `NSNumber` or `NSString`. + If no value is provided, the index of the option in the `ORK*ChoiceAnswerFormat` options list will be used. + */ +- (nullable id)value; + +@end + + +@protocol ORKScaleAnswerFormatProvider + +- (nullable NSNumber *)minimumNumber; +- (nullable NSNumber *)maximumNumber; +- (nullable id)defaultAnswer; +- (nullable NSString *)localizedStringForNumber:(nullable NSNumber *)number; +- (NSInteger)numberOfSteps; +- (nullable NSNumber *)normalizedValueForNumber:(nullable NSNumber *)number; +- (BOOL)isVertical; +- (BOOL)shouldHideSelectedValueLabel; +- (BOOL)shouldHideRanges; +- (BOOL)shouldHideLabels; +- (BOOL)shouldHideValueMarkers; +- (BOOL)shouldShowDontKnowButton; +- (NSString *)maximumValueDescription; +- (NSString *)minimumValueDescription; +- (nullable NSString *)customDontKnowButtonText; +- (nullable UIImage *)maximumImage; +- (nullable UIImage *)minimumImage; +- (nullable NSArray *)gradientColors; +- (nullable NSArray *)gradientLocations; + +@end + + +@protocol ORKTextScaleAnswerFormatProvider + +- (NSArray *)textChoices; +- (nullable ORKTextChoice *)textChoiceAtIndex:(NSUInteger)index; +- (NSUInteger)textChoiceIndexForValue:(id)value; + +@end + +@protocol ORKConfirmAnswerFormatProvider + +- (ORKAnswerFormat *)confirmationAnswerFormatWithOriginalItemIdentifier:(NSString *)originalItemIdentifier + errorMessage:(NSString *)errorMessage; + +@end + + +@interface ORKScaleAnswerFormat () + +@end + + +@interface ORKContinuousScaleAnswerFormat () + +@end + + +@interface ORKTextScaleAnswerFormat () + +@end + + +@interface ORKTextChoice () + +@end + +@interface ORKValuePickerAnswerFormat () + +- (instancetype)initWithTextChoices:(NSArray *)textChoices nullChoice:(ORKTextChoice *)nullChoice NS_DESIGNATED_INITIALIZER; + +- (ORKTextChoice *)nullTextChoice; + +@end + + +@interface ORKImageChoice () + +@end + + +@interface ORKTimeOfDayAnswerFormat () + +- (NSDate *)pickerDefaultDate; + +@end + + +@interface ORKDateAnswerFormat () + +- (NSDate *)pickerDefaultDate; +- (nullable NSDate *)pickerMinimumDate; +- (nullable NSDate *)pickerMaximumDate; + +- (NSCalendar *)currentCalendar; + +@end + + +@interface ORKTimeIntervalAnswerFormat () + +- (NSTimeInterval)pickerDefaultDuration; + +@end + + +@interface ORKTextAnswerFormat () + +@end + + +@interface ORKHeightAnswerFormat () + +@property (nonatomic, readonly) BOOL useMetricSystem; + +@end + + +@interface ORKWeightAnswerFormat () + +@property (nonatomic, readonly) BOOL useMetricSystem; + +@end + + +@interface ORKAnswerDefaultSource : NSObject + ++ (instancetype)sourceWithHealthStore:(HKHealthStore *)healthStore; +- (instancetype)initWithHealthStore:(HKHealthStore *)healthStore NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, strong, readonly, nullable) HKHealthStore *healthStore; + +- (void)fetchDefaultValueForAnswerFormat:(nullable ORKAnswerFormat *)answerFormat handler:(void(^)(id defaultValue, NSError *error))handler; + +- (nullable HKUnit *)defaultHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat; +- (void)updateHealthKitUnitForAnswerFormat:(ORKAnswerFormat *)answerFormat force:(BOOL)force; + +@end + +@interface ORKTextChoiceOther() + +@property (nonatomic, nullable) NSString *textViewText; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Private.h new file mode 100755 index 0000000..73cb30b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerFormat_Private.h @@ -0,0 +1,93 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_EXTERN id ORKNullAnswerValue(void) ORK_AVAILABLE_DECL; + +@class ORKQuestionResult; + +@interface ORKAnswerFormat () + +- (BOOL)isAnswerValid:(id)answer; + +- (BOOL)isAnswerValidWithString:(nullable NSString *)text; + +- (ORKQuestionResult *)resultWithIdentifier:(NSString *)identifier answer:(id)answer; + +@end + + +/** + The `ORKConfirmTextAnswerFormat` class represents the answer format for questions that collect a text + response from the user and validates it with another text answer format. + + An `ORKConfirmTextAnswerFormat` object produces an `ORKBooleanQuestionResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKConfirmTextAnswerFormat : ORKTextAnswerFormat + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithMaximumLength:(NSInteger)maximumLength NS_UNAVAILABLE; + +- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression + invalidMessage:(NSString *)invalidMessage NS_UNAVAILABLE; + +/** + Returns an initialized text answer format using the original item identifier. + + @param originalItemIdentifier The form item identifier against which this answer item is validated. + @param errorMessage The error message displayed if validation fails. + + @return An initialized confirm text answer format. + */ +- (instancetype)initWithOriginalItemIdentifier:(NSString *)originalItemIdentifier + errorMessage:(NSString *)errorMessage; + +/** + The identifier for the form item that the current item will be validated against. + */ +@property (nonatomic, copy, readonly) NSString *originalItemIdentifier; + + +/** + The error message displayed if validation fails. + */ +@property (nonatomic, copy, readonly) NSString *errorMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.h new file mode 100755 index 0000000..2fc932f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefaultFont.h" +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Answer's text field. + */ +ORK_CLASS_AVAILABLE +@interface ORKAnswerTextField : UITextField + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.m new file mode 100755 index 0000000..bce073a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextField.m @@ -0,0 +1,111 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAnswerTextField.h" +#import "ORKSkin.h" + +#import "ORKAccessibility.h" + + +@implementation ORKAnswerTextField + +- (instancetype)init { + self = [super init]; + if (self) { + [self init_ORKAnswerTextField]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self init_ORKAnswerTextField]; + } + return self; +} + +- (void)init_ORKAnswerTextField { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateAppearance) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + [self addAccessoryViewWithDoneButton]; + [self updateAppearance]; +} + +- (void)addAccessoryViewWithDoneButton { + UIToolbar* accessoryViewWithDoneButton = [[UIToolbar alloc] init]; + [accessoryViewWithDoneButton sizeToFit]; + UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace + target:nil action:nil]; + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self action:@selector(keyboardAccessoryViewDoneButtonPressed)]; + accessoryViewWithDoneButton.items = @[flexibleSpace, doneButton]; + [accessoryViewWithDoneButton setBarTintColor:ORKColor(ORKBackgroundColorKey)]; + self.inputAccessoryView = accessoryViewWithDoneButton; +} + +- (void)keyboardAccessoryViewDoneButtonPressed { + [[NSNotificationCenter defaultCenter] + postNotificationName:ORKDoneButtonPressedKey + object:self]; + [self resignFirstResponder]; +} + +- (void)updateAppearance { + self.font = [[self class] defaultFont]; + [self invalidateIntrinsicContentSize]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +#pragma mark - Accessibility + +- (CGRect)accessibilityFrame { + UITableViewCell *containingCell = (UITableViewCell *)[self ork_superviewOfType:[UITableViewCell class]]; + if (containingCell != nil) { + return UIAccessibilityConvertFrameToScreenCoordinates(containingCell.bounds, containingCell); + } + return [super accessibilityFrame]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.h new file mode 100755 index 0000000..9fac193 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" +#import "ORKDefaultFont.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKAnswerTextView` class represents the text view of the answer. + + @note The answer text view is used in the answer page and the form page. + */ +ORK_CLASS_AVAILABLE +@interface ORKAnswerTextView : UITextView + +@end + + +@interface ORKAnswerTextView () + +@property (nonatomic, copy, nullable) NSString *placeholder; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.m new file mode 100755 index 0000000..4192db2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKAnswerTextView.m @@ -0,0 +1,198 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAnswerTextView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKAnswerTextView { + UITextView *_placeholderTextView; + NSArray *_accessibilityCustomActions; +} + +- (instancetype)init { + return [self initWithFrame:CGRectZero textContainer:nil]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + return [self initWithFrame:frame textContainer:nil]; +} + +- (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer { + self = [super initWithFrame:frame textContainer:textContainer]; + if (self) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateAppearance) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(textViewTextDidChange:) + name:UITextViewTextDidChangeNotification + object:self]; + + _placeholderTextView = [[UITextView alloc] initWithFrame:CGRectZero]; + _placeholderTextView.textColor = [UIColor ork_midGrayTintColor]; + _placeholderTextView.userInteractionEnabled = NO; + _placeholderTextView.translatesAutoresizingMaskIntoConstraints = NO; + [self insertSubview:_placeholderTextView atIndex:0]; + + [self setUpConstraints]; + [self addAccessoryViewWithDoneButton]; + [self updateAppearance]; +} + +- (void)addAccessoryViewWithDoneButton { + UIToolbar* accessoryViewWithDoneButton = [[UIToolbar alloc] init]; + [accessoryViewWithDoneButton sizeToFit]; + UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace + target:nil action:nil]; + UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self action:@selector(keyboardAccessoryViewDoneButtonPressed)]; + accessoryViewWithDoneButton.items = @[flexibleSpace, doneButton]; + [accessoryViewWithDoneButton setBarTintColor:ORKColor(ORKBackgroundColorKey)]; + self.inputAccessoryView = accessoryViewWithDoneButton; +} + +- (void)keyboardAccessoryViewDoneButtonPressed { + [self resignFirstResponder]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + // Setting the frame directly causes a layout error on a form step (it looks like an iOS bug, as setting the frame should produce the same effect as setting the bounds and the center) + CGRect answerTextViewBounds = self.bounds; + _placeholderTextView.bounds = answerTextViewBounds; + _placeholderTextView.center = CGPointMake(answerTextViewBounds.size.width / 2, answerTextViewBounds.size.height / 2); +} + +- (void)setUpConstraints { + // This shouldn't be needed, as we're directly setting the _placeholderTextView bounds and center, but it is needed, otherwise it diplays incorrectly in form steps + NSMutableArray *constraints = [NSMutableArray new]; + NSDictionary *views = @{@"placeholderTextView": _placeholderTextView}; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[placeholderTextView]|" + options:NSLayoutFormatDirectionLeftToRight + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[placeholderTextView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)textViewTextDidChange:(NSNotification *)notification { + [self ork_updatePlaceholder]; +} + +- (void)ork_updatePlaceholder { + _placeholderTextView.hidden = (self.text.length > 0); +} + +- (void)updateAppearance { + self.font = [[self class] defaultFont]; + [self invalidateIntrinsicContentSize]; +} + +- (void)setFont:(UIFont *)font { + [super setFont:font]; + _placeholderTextView.font = font; +} + +- (void)setTextContainerInset:(UIEdgeInsets)textContainerInset { + [super setTextContainerInset:textContainerInset]; + _placeholderTextView.textContainerInset = textContainerInset; +} + +- (void)setLayoutMargins:(UIEdgeInsets)layoutMargins { + [super setLayoutMargins:layoutMargins]; + _placeholderTextView.layoutMargins = layoutMargins; +} + +- (void)setPlaceholder:(NSString *)placeholder { + _placeholder = placeholder ? : ORKLocalizedString(@"PLACEHOLDER_LONG_TEXT", nil); + _placeholderTextView.text = _placeholder; +} + +- (void)setText:(NSString *)text { + [super setText:text]; + [self ork_updatePlaceholder]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (void)setBackgroundColor:(UIColor *)backgroundColor { + [super setBackgroundColor:backgroundColor]; + if (_placeholderTextView) { + [_placeholderTextView setBackgroundColor:backgroundColor]; + } +} + +- (BOOL)accessibilityDismissKeyboardForAction:(UIAccessibilityCustomAction *)customAction +{ + [self resignFirstResponder]; + return YES; +} + +- (NSArray *)accessibilityCustomActions +{ + NSArray *actions = nil; + if (self.isFirstResponder) { + if (_accessibilityCustomActions == nil) { + // Users of accessibility technologies may not be able to tap outside the view to dismiss the keyboard, so provide an action for it here. + UIAccessibilityCustomAction *dismissKeyboardAction = [[UIAccessibilityCustomAction alloc] initWithName:ORKLocalizedString(@"AX_DISMISS_KEYBOARD_CUSTOM_ACTION", nil) target:self selector:@selector(accessibilityDismissKeyboardForAction:)]; + _accessibilityCustomActions = @[dismissKeyboardAction]; + } + actions = _accessibilityCustomActions; + } + return actions; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.h new file mode 100755 index 0000000..47cb89c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.h @@ -0,0 +1,77 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKLearnMoreInstructionStep; +@protocol ORKBodyContainerViewDelegate + +@required +- (void)bodyContainerLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep; + +@end + +@protocol ORKBodyItemContainerViewDelegate + +@optional +- (void)bodyContainerViewDidLoadBodyItems; + +@end + + +@class ORKBodyItem; +@interface ORKBodyContainerView : UIStackView + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithBodyItems:(NSArray *)bodyItems + textAlignment:(NSTextAlignment)textAlignment + delegate:(id)delegate; + +- (void)updateBodyItemViews; +- (BOOL)hasShownAllBodyItem; +- (UIView *)lastVisibleBodyItem; + +@property (nonatomic, nonnull) NSArray *bodyItems; + +@property (nonatomic) BOOL buildsInBodyItems; + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, weak) id bodyItemDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.m new file mode 100755 index 0000000..c20a6dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyContainerView.m @@ -0,0 +1,552 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKBodyContainerView.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKBodyItem.h" +#import "ORKLearnMoreView.h" +#import "ORKLearnMoreInstructionStep.h" +#import "ORKTagLabel.h" + + +static const CGFloat ORKBodyToBulletPaddingStandard = 26.0; + +static const CGFloat ORKBulletToBulletPaddingStandard = 22.0; +static const CGFloat ORKBodyToLearnMorePaddingStandard = 15.0; +static const CGFloat ORKTagLabelBottomPadding = 8.0; +static const CGFloat ORKHorizontalRulePadding = 22.0; + +static const CGFloat ORKBodyTextToBodyDetailTextPaddingStandard = 6.0; +static const CGFloat ORKBodyTextToLearnMoreButtonPaddingStandard = 15.0; +static const CGFloat ORKBodyDetailTextToLearnMoreButtonPaddingStandard = 15.0; + +static const CGFloat ORKBulletIconToBodyPadding = 14.0; +static const CGFloat ORKBulletIconWidthStandard = 10.0; + +static const CGFloat ORKBulletIconDimension = 40.0; +static const CGFloat ORKCardStylePadding = 16.0; +static const CGFloat ORKCardStyleMediumTextPadding = 14.0; +static const CGFloat ORKCardStyleSmallTextPadding = 2.0; + +static const CGFloat ORKCardStyleBuildInPostitionStart = 31.0; +static const CGFloat ORKCardStyleBuildInPostitionEnd = 26.0; + +static NSString *ORKBulletUnicode = @"\u2981"; + +@protocol ORKBodyItemViewDelegate + +@required +- (void)bodyItemLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep; + +@end + +@interface ORKBodyItemView: UIStackView + +- (instancetype)initWithBodyItem:(ORKBodyItem *)bodyItem; + +@property (nonatomic, nonnull) ORKBodyItem *bodyItem; +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong) UIView *cardView; +@property (nonatomic, strong) UIView *cardStyleAccessoryView; + +@end + +@interface ORKBodyItemView() +@property (nonatomic) NSTextAlignment textAlignment; +@end + +@implementation ORKBodyItemView + +- (instancetype)initWithBodyItem:(ORKBodyItem *)bodyItem { + self = [super init]; + if (self) { + self.bodyItem = bodyItem; + self.textAlignment = NSTextAlignmentLeft; + [self setupBodyStyleView]; + + } + return self; +} + +- (instancetype)initWithBodyItem:(ORKBodyItem *)bodyItem textAlignment:(NSTextAlignment)textAlignment { + self = [super init]; + if (self) { + self.bodyItem = bodyItem; + self.textAlignment = textAlignment; + [self setupBodyStyleView]; + + } + return self; +} + +- (void)setupBodyStyleView { + // FIXME:- remove cardStyle property, not using it anymore + if (_bodyItem.useCardStyle == YES) { + _cardView = [[UIView alloc] init]; + _cardView.translatesAutoresizingMaskIntoConstraints = NO; + [self addArrangedSubview:_cardView]; + } + + if (_bodyItem.bodyItemStyle == ORKBodyItemStyleText) { + [self setupBodyStyleTextView]; + } else if (_bodyItem.bodyItemStyle == ORKBodyItemStyleImage) { + [self setupBulletPointStackView]; + [self setupBodyStyleImage]; + } else if (_bodyItem.bodyItemStyle == ORKBodyItemStyleBulletPoint) { + [self setupBulletPointStackView]; + [self setupBodyStyleBulletPointView]; + } else if (_bodyItem.bodyItemStyle == ORKBodyItemStyleHorizontalRule) { + [self setupBodyStyleHorizontalRule]; + } else if (_bodyItem.bodyItemStyle == ORKBodyItemStyleTag) { + [self setupBodyStyleTag]; + } +} + ++ (UIFont *)bodyTitleFontBold { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bodyTitleFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont fontWithDescriptor:descriptor size:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bodyTextFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont fontWithDescriptor:descriptor size:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bulletIconFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + descriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitTightLeading | UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:descriptor size:0]; +} + ++ (UIFont *)bulletTextFontBold { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold | UIFontDescriptorTraitLooseLeading)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bulletBodyTextFontBold { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold | UIFontDescriptorTraitLooseLeading)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bulletTextFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitLooseLeading)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + ++ (UIFont *)bulletDetailTextFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitLooseLeading)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; + +} + +- (void)setupBodyStyleHorizontalRule { + self.axis = UILayoutConstraintAxisVertical; + self.distribution = UIStackViewDistributionFill; + UIView *separator = [UIView new]; + separator.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + separator.backgroundColor = UIColor.separatorColor; + } else { + separator.backgroundColor = UIColor.lightGrayColor; + } + [separator.heightAnchor constraintEqualToConstant:1.0 / [UIScreen mainScreen].scale].active = YES; + [self addArrangedSubview:separator]; +} + +- (void)setupBodyStyleTextView { + self.axis = UILayoutConstraintAxisVertical; + self.distribution = UIStackViewDistributionFill; + self.alignment = self.textAlignment == NSTextAlignmentCenter ? UIStackViewAlignmentCenter : UIStackViewAlignmentLeading; + UILabel *textLabel; + UILabel *detailTextLabel; + + if (_bodyItem.text) { + + textLabel = [UILabel new]; + textLabel.numberOfLines = 0; + textLabel.font = _bodyItem.detailText == nil ? [ORKBodyItemView bodyTitleFont] : [ORKBodyItemView bodyTitleFontBold]; + textLabel.text = _bodyItem.text; + textLabel.textAlignment = _textAlignment; + textLabel.translatesAutoresizingMaskIntoConstraints = NO; + + if (_bodyItem.useCardStyle == YES) { + [_cardView addSubview:textLabel]; + [textLabel.leadingAnchor constraintEqualToAnchor: _cardView.leadingAnchor constant:ORKCardStyleMediumTextPadding].active = YES; + [textLabel.topAnchor constraintEqualToAnchor:_cardView.topAnchor constant:ORKCardStylePadding].active = YES; + [textLabel.trailingAnchor constraintEqualToAnchor:_cardView.trailingAnchor constant:-ORKCardStylePadding].active = YES; + + if (_bodyItem.detailText == nil) { + [textLabel.bottomAnchor constraintEqualToAnchor:_cardView.bottomAnchor constant:-ORKCardStylePadding].active = YES; + } + } else { + [self addArrangedSubview:textLabel]; + } + } + if (_bodyItem.detailText) { + detailTextLabel = [UILabel new]; + detailTextLabel.numberOfLines = 0; + detailTextLabel.font = [ORKBodyItemView bodyTextFont]; + detailTextLabel.text = _bodyItem.detailText; + detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + + if (_bodyItem.useCardStyle == YES) { + [_cardView addSubview:detailTextLabel]; + [detailTextLabel.leadingAnchor constraintEqualToAnchor: _cardView.leadingAnchor constant:ORKCardStyleMediumTextPadding].active = YES; + [detailTextLabel.topAnchor constraintEqualToAnchor:textLabel.bottomAnchor constant:ORKCardStyleSmallTextPadding].active = YES; + [detailTextLabel.trailingAnchor constraintEqualToAnchor:_cardView.trailingAnchor constant:-ORKCardStylePadding].active = YES; + [detailTextLabel.bottomAnchor constraintEqualToAnchor:_cardView.bottomAnchor constant:-ORKCardStylePadding].active = YES; + } else { + [self addArrangedSubview:detailTextLabel]; + if (textLabel) { + [self setCustomSpacing:ORKBodyTextToBodyDetailTextPaddingStandard afterView:textLabel]; + } + } + } + if (_bodyItem.learnMoreItem) { + ORKLearnMoreView *learnMoreView = _bodyItem.learnMoreItem.text ? [ORKLearnMoreView learnMoreCustomButtonViewWithText:_bodyItem.learnMoreItem.text LearnMoreInstructionStep:_bodyItem.learnMoreItem.learnMoreInstructionStep] : [ORKLearnMoreView learnMoreDetailDisclosureButtonViewWithLearnMoreInstructionStep:_bodyItem.learnMoreItem.learnMoreInstructionStep]; + [learnMoreView setLearnMoreButtonFont:[ORKBodyItemView bodyTextFont]]; + [learnMoreView setLearnMoreButtonTextAlignment:_textAlignment]; + learnMoreView.delegate = self; + learnMoreView.translatesAutoresizingMaskIntoConstraints = NO; + [self addArrangedSubview:learnMoreView]; + if (detailTextLabel) { + [self setCustomSpacing:ORKBodyDetailTextToLearnMoreButtonPaddingStandard afterView:detailTextLabel]; + } + else if (textLabel) { + [self setCustomSpacing:ORKBodyTextToLearnMoreButtonPaddingStandard afterView:textLabel]; + } + } +} + +- (void)setupBulletPointStackView { + self.axis = UILayoutConstraintAxisHorizontal; + self.layoutMargins = UIEdgeInsetsZero; + [self setLayoutMarginsRelativeArrangement:YES]; +} + +- (void)setupBodyStyleBulletPointView { + UILabel *bulletIcon = [self bulletIcon]; + + if (_bodyItem.useCardStyle == YES) { + bulletIcon.translatesAutoresizingMaskIntoConstraints = NO; + [_cardView addSubview:bulletIcon]; + [bulletIcon.leadingAnchor constraintEqualToAnchor:_cardView.leadingAnchor].active = YES; + [bulletIcon.topAnchor constraintEqualToAnchor:_cardView.topAnchor].active = YES; + _cardStyleAccessoryView = bulletIcon; + } else { + [self addArrangedSubview:bulletIcon]; // Stack this in substack for vertical bullet icon. + [self setCustomSpacing:ORKBulletIconToBodyPadding afterView:bulletIcon]; + } + + [self addSubStackView]; +} + +- (void)setupBodyStyleImage { + UIImageView *imageView = [self imageView]; + self.alignment = UIStackViewAlignmentCenter; + + if (_bodyItem.useCardStyle == YES) { + imageView.translatesAutoresizingMaskIntoConstraints = NO; + [_cardView addSubview:imageView]; + [imageView.leadingAnchor constraintEqualToAnchor:_cardView.leadingAnchor].active = YES; + [imageView.centerYAnchor constraintEqualToAnchor:_cardView.centerYAnchor].active = YES; + _cardStyleAccessoryView = imageView; + } else { + [self addArrangedSubview:imageView]; + [self setCustomSpacing:ORKBulletIconToBodyPadding afterView:imageView]; + } + + [self addSubStackView]; +} + +- (UILabel *)bulletIcon { + UILabel *bulletIconLabel = [UILabel new]; + bulletIconLabel.numberOfLines = 1; + bulletIconLabel.font = [ORKBodyItemView bulletIconFont]; + if (@available(iOS 13.0, *)) { + bulletIconLabel.textColor = [UIColor secondaryLabelColor]; + } else { + bulletIconLabel.textColor = [UIColor systemGrayColor]; + } + [bulletIconLabel setText:ORKBulletUnicode]; + bulletIconLabel.translatesAutoresizingMaskIntoConstraints = NO; + + [[bulletIconLabel.widthAnchor constraintGreaterThanOrEqualToConstant:ORKBulletIconWidthStandard] setActive:YES]; + + return bulletIconLabel; +} + +- (UIImageView *)imageView { + UIImageView *imageView = [UIImageView new]; + imageView.image = self.bodyItem.image; + imageView.translatesAutoresizingMaskIntoConstraints = NO; + if (self.bodyItem.useSecondaryColor) { + imageView.tintColor = UIColor.grayColor; + } + if (@available(iOS 13.0, *)) { + // To allow symbols to handle their own configuration + if (imageView.image.isSymbolImage) { + imageView.contentMode = UIViewContentModeCenter; + } else { + imageView.contentMode = UIViewContentModeScaleAspectFit; + } + } + + [imageView.heightAnchor constraintEqualToConstant:ORKBulletIconDimension].active = YES; + [imageView.widthAnchor constraintEqualToConstant:ORKBulletIconDimension].active = YES; + + return imageView; +} + +- (void)setupBodyStyleTag { + UIView *container = [UIView new]; + container.translatesAutoresizingMaskIntoConstraints = NO; + + ORKTagLabel *tagLabel = [ORKTagLabel new]; + tagLabel.translatesAutoresizingMaskIntoConstraints = NO; + tagLabel.text = _bodyItem.text; + [container addSubview:tagLabel]; + + [tagLabel.topAnchor constraintEqualToAnchor:container.topAnchor].active = YES; + [tagLabel.leadingAnchor constraintEqualToAnchor:container.leadingAnchor].active = YES; + [tagLabel.bottomAnchor constraintEqualToAnchor:container.bottomAnchor].active = YES; + [tagLabel.trailingAnchor constraintLessThanOrEqualToAnchor:container.trailingAnchor].active = YES; + + [self addArrangedSubview:container]; +} + +- (void)addSubStackView { + UILabel *textLabel; + UILabel *detailTextLabel; + UIStackView *subStackView = [[UIStackView alloc] init]; + + if (_bodyItem.useCardStyle == NO) { + subStackView.axis = UILayoutConstraintAxisVertical; + subStackView.distribution = UIStackViewDistributionFill; + subStackView.alignment = UIStackViewAlignmentLeading; + subStackView.translatesAutoresizingMaskIntoConstraints = NO; + [self addArrangedSubview:subStackView]; + } + + if (_bodyItem.text) { + textLabel = [UILabel new]; + textLabel.numberOfLines = 0; + textLabel.text = _bodyItem.text; + textLabel.translatesAutoresizingMaskIntoConstraints = NO; + + if (_bodyItem.useCardStyle == YES) { + textLabel.font = [ORKBodyItemView bulletBodyTextFontBold]; + + [_cardStyleAccessoryView setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal]; + + [_cardView addSubview:textLabel]; + [textLabel.leadingAnchor constraintEqualToAnchor: _cardStyleAccessoryView.trailingAnchor constant:ORKCardStyleMediumTextPadding].active = YES; + [textLabel.topAnchor constraintEqualToAnchor:_cardView.topAnchor constant:0].active = YES; + [textLabel.trailingAnchor constraintEqualToAnchor:_cardView.trailingAnchor].active = YES; + [textLabel setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal]; + + if (_bodyItem.detailText == nil) { + [textLabel.bottomAnchor constraintEqualToAnchor:_cardView.bottomAnchor].active = YES; + } + } else { + textLabel.font = _bodyItem.detailText ? [ORKBodyItemView bulletTextFontBold] : [ORKBodyItemView bulletTextFont]; + [subStackView addArrangedSubview:textLabel]; + } + } + if (_bodyItem.detailText) { + detailTextLabel = [UILabel new]; + detailTextLabel.numberOfLines = 0; + detailTextLabel.font = [ORKBodyItemView bulletDetailTextFont]; + detailTextLabel.text = _bodyItem.detailText; + if (_bodyItem.useCardStyle == YES) { + if (@available(iOS 13.0, *)) { + [detailTextLabel setTextColor:[UIColor labelColor]]; + } else{ + [detailTextLabel setTextColor:ORKColor(ORKBulletItemTextColorKey)]; + } + } else { + [detailTextLabel setTextColor:ORKColor(ORKBulletItemTextColorKey)]; + } + detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + + if (_bodyItem.useCardStyle == YES) { + [_cardView addSubview:detailTextLabel]; + [detailTextLabel.leadingAnchor constraintEqualToAnchor: _cardStyleAccessoryView.trailingAnchor constant:ORKCardStyleMediumTextPadding].active = YES; + [detailTextLabel.topAnchor constraintEqualToAnchor:textLabel.bottomAnchor constant:ORKCardStyleSmallTextPadding].active = YES; + [detailTextLabel.trailingAnchor constraintEqualToAnchor:_cardView.trailingAnchor].active = YES; + [detailTextLabel.bottomAnchor constraintEqualToAnchor:_cardView.bottomAnchor].active = YES; + } else { + [subStackView addArrangedSubview:detailTextLabel]; + } + } + if (_bodyItem.learnMoreItem) { + ORKLearnMoreView *learnMoreView = _bodyItem.learnMoreItem.text ? [ORKLearnMoreView learnMoreCustomButtonViewWithText:_bodyItem.learnMoreItem.text LearnMoreInstructionStep:_bodyItem.learnMoreItem.learnMoreInstructionStep] : [ORKLearnMoreView learnMoreDetailDisclosureButtonViewWithLearnMoreInstructionStep:_bodyItem.learnMoreItem.learnMoreInstructionStep]; + [learnMoreView setLearnMoreButtonFont:[ORKBodyItemView bulletDetailTextFont]]; + learnMoreView.delegate = self; + learnMoreView.translatesAutoresizingMaskIntoConstraints = NO; + [subStackView addArrangedSubview:learnMoreView]; + } +} + +#pragma mark - ORKLearnMoreViewDelegate + +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep { + [_delegate bodyItemLearnMoreButtonPressed:learnMoreStep]; +} + +@end + +@interface ORKBodyContainerView() +@property (nonatomic, strong) NSArray *views; +@property (nonatomic) NSTextAlignment textAlignment; +@property (nonatomic) NSUInteger currentBodyItemIndex; +@end + +@implementation ORKBodyContainerView + +- (instancetype)initWithBodyItems:(NSArray *)bodyItems + textAlignment:(NSTextAlignment)textAlignment + delegate:(nonnull id)delegate { + self.delegate = delegate; + if (bodyItems && bodyItems.count <= 0) { + NSAssert(NO, @"Body Items array cannot be empty"); + } + self = [super init]; + if (self) { + self.bodyItems = bodyItems; + self.textAlignment = textAlignment; + self.axis = UILayoutConstraintAxisVertical; + self.distribution = UIStackViewDistributionFill; + [self addBodyItemViews]; + } + return self; +} + +- (void)addBodyItemViews { + _views = [ORKBodyContainerView bodyItemViewsWithBodyItems:_bodyItems textAlignment:_textAlignment]; + for (NSInteger i = 0; i < _views.count; i++) { + [self addArrangedSubview:_views[i]]; + _views[i].delegate = self; + + if (i < _views.count - 1) { + CGFloat padding = [self spacingWithAboveStyle:_bodyItems[i].bodyItemStyle belowStyle:_bodyItems[i + 1].bodyItemStyle belowIsLearnMore:(_bodyItems[i + 1].learnMoreItem != nil) belowItemIndex:i+1]; + [self setCustomSpacing:padding afterView:_views[i]]; + } + } +} + +- (void)setBuildsInBodyItems:(BOOL)buildsInBodyItems { + _buildsInBodyItems = buildsInBodyItems; + if (buildsInBodyItems == YES) { + for (NSInteger i = 0; i < _views.count; i++) { + [self setCustomSpacing:ORKCardStyleBuildInPostitionStart afterView:_views[i]]; + if ((_buildsInBodyItems == YES) && (i != 0)) { + _views[i].alpha = 0; + } + } + + _currentBodyItemIndex = 0; + } +} + +- (void)updateBodyItemViews { + if (_buildsInBodyItems == NO) { return; } + + NSUInteger indexToShow = _currentBodyItemIndex + 1; + for (NSInteger i = 0; i < _views.count; i++) { + if (i == indexToShow) { + [UIView transitionWithView:_views[i] duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^ { + [self setCustomSpacing:ORKCardStyleBuildInPostitionEnd afterView:_views[i - 1]]; + _views[i].alpha = 1; + } completion:nil]; + } + } + + _currentBodyItemIndex++; +} + +- (BOOL)hasShownAllBodyItem { + return (_currentBodyItemIndex == (_views.count - 1)); +} + +- (UIView *)lastVisibleBodyItem { + return _views[_currentBodyItemIndex]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + if ([_bodyItemDelegate respondsToSelector:@selector(bodyContainerViewDidLoadBodyItems)]) { + [_bodyItemDelegate bodyContainerViewDidLoadBodyItems]; + } +} + +- (CGFloat)spacingWithAboveStyle:(ORKBodyItemStyle)aboveStyle belowStyle:(ORKBodyItemStyle )belowStyle belowIsLearnMore:(BOOL)belowIsLearnMore belowItemIndex:(NSInteger)belowItemIndex { + if (aboveStyle == ORKBodyItemStyleHorizontalRule || belowStyle == ORKBodyItemStyleHorizontalRule) { + return ORKHorizontalRulePadding; + } else if (belowIsLearnMore == YES) { + return ORKBodyToLearnMorePaddingStandard; + } else if (aboveStyle == ORKBodyItemStyleText) { + return belowStyle == ORKBodyItemStyleText ? (_bodyItems[belowItemIndex].text ? ORKBodyToBodyParagraphPaddingStandard : ORKBodyToBodyPaddingStandard) : ORKBodyToBulletPaddingStandard; + } else if (aboveStyle == ORKBodyItemStyleTag) { + return ORKTagLabelBottomPadding; + } else { + return belowStyle == ORKBodyItemStyleText ? ORKBodyToBulletPaddingStandard : ORKBulletToBulletPaddingStandard; + } +} + ++ (NSArray *)bodyItemViewsWithBodyItems:(NSArray *)bodyItems textAlignment:(NSTextAlignment)textAlignment { + NSMutableArray *viewsArray = [[NSMutableArray alloc] init]; + [bodyItems enumerateObjectsUsingBlock:^(ORKBodyItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + ORKBodyItemView *itemView = [[ORKBodyItemView alloc] initWithBodyItem:obj textAlignment:textAlignment]; + itemView.translatesAutoresizingMaskIntoConstraints = NO; + [viewsArray addObject:itemView]; + }]; + return [viewsArray copy]; +} + +#pragma mark - ORKBodyItemViewDelegate + +- (void)bodyItemLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep { + [_delegate bodyContainerLearnMoreButtonPressed:learnMoreStep]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.h new file mode 100755 index 0000000..d9cd9d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.h @@ -0,0 +1,91 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +#import +#import "ORKDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, ORKBodyItemStyle) { + /** + text style body item + */ + ORKBodyItemStyleText, + + /** + bullet style body item + */ + ORKBodyItemStyleBulletPoint, + + /** + image style body item + */ + ORKBodyItemStyleImage, + + /** + horizontal rule + */ + ORKBodyItemStyleHorizontalRule, + + /** + tag label + */ + ORKBodyItemStyleTag +} ORK_ENUM_AVAILABLE; + +@class ORKLearnMoreItem; + +ORK_CLASS_AVAILABLE +@interface ORKBodyItem : NSObject + +- (instancetype)initWithText:(nullable NSString *)text detailText:(nullable NSString *)detailText image:(nullable UIImage *)image learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem bodyItemStyle:(ORKBodyItemStyle)bodyItemStyle; + +- (instancetype)initWithText:(nullable NSString *)text detailText:(nullable NSString *)detailText image:(nullable UIImage *)image learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem bodyItemStyle:(ORKBodyItemStyle)bodyItemStyle useCardStyle:(BOOL)useCardStyle; + +- (instancetype)initWithHorizontalRule; + +@property (nonatomic, nullable) NSString *text; + +@property (nonatomic, nullable) NSString *detailText; + +@property (nonatomic, nullable) UIImage *image; + +@property (nonatomic, nullable) ORKLearnMoreItem *learnMoreItem; + +@property (nonatomic) ORKBodyItemStyle bodyItemStyle; + +@property (nonatomic) BOOL useCardStyle; + +@property (nonatomic) BOOL useSecondaryColor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.m new file mode 100755 index 0000000..df2c8b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyItem.m @@ -0,0 +1,131 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKBodyItem.h" +#import "ORKLearnMoreInstructionStep.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKBodyItem + +- (instancetype)initWithText:(NSString *)text detailText:(NSString *)detailText image:(nullable UIImage *)image learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem bodyItemStyle:(ORKBodyItemStyle)bodyItemStyle { + return [self initWithText:text detailText:detailText image:image learnMoreItem:learnMoreItem bodyItemStyle:bodyItemStyle useCardStyle:NO]; +} + +- (instancetype)initWithText:(NSString *)text detailText:(NSString *)detailText image:(nullable UIImage *)image learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem bodyItemStyle:(ORKBodyItemStyle)bodyItemStyle useCardStyle:(BOOL)useCardStyle { + self = [super init]; + if (self) { + self.text = text; + self.detailText = detailText; + self.learnMoreItem = learnMoreItem; + self.bodyItemStyle = bodyItemStyle; + self.image = image; + self.useCardStyle = useCardStyle; + self.useSecondaryColor = NO; + } + [self validateParameters]; + return self; +} + +- (instancetype)initWithHorizontalRule { + return [self initWithText:nil + detailText:nil + image:nil + learnMoreItem:nil + bodyItemStyle:ORKBodyItemStyleHorizontalRule + useCardStyle:NO]; +} + +- (void)validateParameters { + if (_bodyItemStyle != ORKBodyItemStyleHorizontalRule && !_text && !_detailText && !_learnMoreItem) { + NSAssert(NO, @"Parameters text, detailText and learnMoreItem cannot be nil at the same time."); + } +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, detailText, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, learnMoreItem, ORKLearnMoreItem); + ORK_DECODE_INTEGER(aDecoder, bodyItemStyle); + ORK_DECODE_IMAGE(aDecoder, image); + ORK_DECODE_BOOL(aDecoder, useCardStyle); + ORK_DECODE_BOOL(aDecoder, useSecondaryColor); + } + return self; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, detailText); + ORK_ENCODE_OBJ(aCoder, learnMoreItem); + ORK_ENCODE_INTEGER(aCoder, bodyItemStyle); + ORK_ENCODE_IMAGE(aCoder, image); + ORK_ENCODE_BOOL(aCoder, useCardStyle); + ORK_ENCODE_BOOL(aCoder, useSecondaryColor); +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + ORKBodyItem *bodyItem = [[[self class] allocWithZone:zone] init]; + bodyItem->_text = [self.text copy]; + bodyItem->_detailText = [self.detailText copy]; + bodyItem->_learnMoreItem = [self.learnMoreItem copy]; + bodyItem->_bodyItemStyle = self.bodyItemStyle; + bodyItem->_image = [self.image copy]; + bodyItem->_useCardStyle = self.useCardStyle; + bodyItem->_useSecondaryColor = self.useSecondaryColor; + return bodyItem; +} + +- (NSUInteger)hash { + return _text.hash ^ _detailText.hash ^ _learnMoreItem.hash ^ _image.hash; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.detailText, castObject.detailText) + && ORKEqualObjects(self.learnMoreItem, castObject.learnMoreItem) + && (self.bodyItemStyle == castObject.bodyItemStyle) + && ORKEqualObjects(self.image, castObject.image) + && (self.useCardStyle == castObject.useCardStyle) + && (self.useSecondaryColor == castObject.useSecondaryColor)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.h new file mode 100755 index 0000000..b3f653a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKBodyLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.m new file mode 100755 index 0000000..b7dab08 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBodyLabel.m @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKBodyLabel.h" + + +@implementation ORKBodyLabel + +- (void)updateAppearance { + self.font = [[self class] defaultFont]; + [self invalidateIntrinsicContentSize]; +} + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont systemFontOfSize:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.h new file mode 100755 index 0000000..bf5b5da --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.h @@ -0,0 +1,65 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKBorderedButton : ORKTextButton + +/** + The tint color of the button for UIControlStateNormal + */ +@property (nonatomic) UIColor *normalTintColor; + +/** + The tint color of the button for UIControlStateSelected or UIControlStateHighlighted + */ +@property (nonatomic) UIColor *normalHighlightOrSelectTintColor; + +/** + The tint color of the button for UIControlStateDisabled + */ +@property (nonatomic) UIColor *disableTintColor; + +/** + The delay in fading animation + */ +@property (nonatomic, assign) NSTimeInterval fadeDelay; + +- (void)updateBackgroundColor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.m new file mode 100755 index 0000000..9d8a4c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKBorderedButton.m @@ -0,0 +1,180 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKBorderedButton.h" +#import "ORKTextButton_Internal.h" + +static const CGFloat ORKBorderedButtonCornerRadii = 14.0; + +@implementation ORKBorderedButton { + + BOOL _appearsAsTextButton; + BOOL _useBoldFont; +} + +- (void)init_ORKTextButton { + [super init_ORKTextButton]; + [self setLayerAndFadeDelay]; + [self setEnabled:YES]; + [self setDefaultTintColors]; +} + +- (void)setLayerAndFadeDelay { + self.layer.cornerRadius = ORKBorderedButtonCornerRadii; + self.fadeDelay = 0.0; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + + if (!_appearsAsTextButton) { + [self setLayerAndFadeDelay]; + [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [self setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.7f] forState:UIControlStateHighlighted]; + [self setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.7f] forState:UIControlStateSelected]; + [self setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.3f] forState:UIControlStateDisabled]; + } + else { + [self setTitleColor:_normalTintColor forState:UIControlStateNormal]; + [self setTitleColor:_normalHighlightOrSelectTintColor forState:UIControlStateHighlighted]; + [self setTitleColor:_normalHighlightOrSelectTintColor forState:UIControlStateSelected]; + [self setTitleColor:_disableTintColor forState:UIControlStateDisabled]; + } + [self setDefaultTintColors]; + [self updateBackgroundColor]; + +} + +- (void)setDefaultTintColors { + _normalTintColor = [[self tintColor] colorWithAlphaComponent:1.0f]; + _normalHighlightOrSelectTintColor = [_normalTintColor colorWithAlphaComponent:0.7f]; +} + +- (void)setNormalTintColor:(UIColor *)normalTintColor { + _normalTintColor = normalTintColor; + _normalHighlightOrSelectTintColor = [normalTintColor colorWithAlphaComponent:0.7f]; + + _disableTintColor = [normalTintColor colorWithAlphaComponent:0.3f]; + [self updateBackgroundColor]; +} + +- (void)setNormalHighlightOrSelectTintColor:(UIColor *)normalHighlightOrSelectTintColor { + _normalHighlightOrSelectTintColor = normalHighlightOrSelectTintColor; + [self updateBackgroundColor]; +} + +- (void)setDisableTintColor:(UIColor *)disableTintColor { + _disableTintColor = disableTintColor; + [self updateBackgroundColor]; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + + [self updateBackgroundColor]; +} + +- (void)setSelected:(BOOL)selected { + [super setSelected:selected]; + + [self updateBackgroundColor]; +} + +- (void)setEnabled:(BOOL)enabled { + [super setEnabled:enabled]; + + [self updateBackgroundColor]; +} + +- (void)fadeHighlightOrSelectColor { + // Ignore if it's a race condition + if (self.enabled && !(self.highlighted || self.selected)) { + self.backgroundColor = _normalTintColor; + self.layer.borderColor = [_normalTintColor CGColor]; + } +} + +- (void)updateBackgroundColor { + if (!_appearsAsTextButton) { + if (self.enabled && (self.highlighted || self.selected)) { + self.backgroundColor = _normalHighlightOrSelectTintColor; + self.layer.borderColor = [_normalHighlightOrSelectTintColor CGColor]; // move + } else if(self.enabled && !(self.highlighted || self.selected)) { + if (self.fadeDelay > 0) { + [self performSelector:@selector(fadeHighlightOrSelectColor) withObject:nil afterDelay:self.fadeDelay]; + } else { + [self fadeHighlightOrSelectColor]; + } + } else { + self.backgroundColor = _disableTintColor; + self.layer.borderColor = [_disableTintColor CGColor]; + } + self.titleLabel.font = [[self class] defaultFont]; + } + else { + self.backgroundColor = [UIColor clearColor]; + self.layer.borderColor = [[UIColor clearColor] CGColor]; + self.titleLabel.font = _useBoldFont ? [[self class] defaultBoldTextFont] : [ORKTextButton defaultFont]; + } +} + ++ (UIFont *)defaultFont { + // bold, 17 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return [UIFont boldSystemFontOfSize:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue] + 1.0]; +} + ++ (UIFont *)defaultBoldTextFont { + // bold, 16 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1]; + return [UIFont boldSystemFontOfSize:((NSNumber *)[descriptor objectForKey: UIFontDescriptorSizeAttribute]).doubleValue + 4.0]; +} + +- (void)setAppearanceAsTextButton { + _appearsAsTextButton = YES; + _useBoldFont = NO; + [self tintColorDidChange]; +} + +- (void)setAppearanceAsBoldTextButton { + _appearsAsTextButton = YES; + _useBoldFont = YES; + [self tintColorDidChange]; +} + +- (void)resetAppearanceAsBorderedButton { + _appearsAsTextButton = NO; + _useBoldFont = NO; + [self setDefaultTintColors]; + [self tintColorDidChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.h new file mode 100755 index 0000000..262e998 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Intro step's first piece details text. + + @note Used as cell's caption text: in ORKConsentDocumentCell and ORKFormItemCell + */ +ORK_CLASS_AVAILABLE +@interface ORKCaption1Label : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.m new file mode 100755 index 0000000..b72621d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCaption1Label.m @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCaption1Label.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKCaption1Label + ++ (UIFont *)defaultFont { + // medium , 17 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1]; + const CGFloat defaultSize = 12; + return ORKMediumFontWithSize([[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue] + 17.0 - defaultSize); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.h new file mode 100755 index 0000000..19b592d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKCheckmarkView : UIImageView; + +- (instancetype)initWithRadius:(CGFloat)radius checkedImage:(nullable UIImage *)checkedImage uncheckedImage:(nullable UIImage *)uncheckedImage; +- (instancetype)initWithDefaults; +- (instancetype)initWithDefaultsWithoutCircle; + +@property (nonatomic, nullable) UIImage *checkedImage; +@property (nonatomic, nullable) UIImage *uncheckedImage; +@property (nonatomic) BOOL checked; + +- (CGFloat)getDimension; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.m new file mode 100755 index 0000000..076df17 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCheckmarkView.m @@ -0,0 +1,150 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCheckmarkView.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat CheckmarkViewBorderWidth = 2.0; + +@implementation ORKCheckmarkView { + CGFloat _dimension; + BOOL _shouldShowCircle; +} + +- (instancetype)initWithRadius:(CGFloat)radius checkedImage:(UIImage *)checkedImage uncheckedImage:(UIImage *)uncheckedImage shouldShowCircle:(BOOL)shouldShowCircle { + self = [super init]; + if (self) { + _dimension = 2*radius; + _checkedImage = checkedImage; + _uncheckedImage = uncheckedImage; + _shouldShowCircle = shouldShowCircle; + } + [self setupView]; + return self; +} + +- (instancetype)initWithRadius:(CGFloat)radius checkedImage:(UIImage *)checkedImage uncheckedImage:(UIImage *)uncheckedImage { + return [self initWithRadius:CheckmarkViewDimension*0.5 + checkedImage:[ORKCheckmarkView checkedImage] + uncheckedImage:[ORKCheckmarkView unCheckedImage] + shouldShowCircle:YES]; +} + +- (instancetype)initWithDefaults { + return [self initWithRadius:CheckmarkViewDimension*0.5 + checkedImage:[ORKCheckmarkView checkedImage] + uncheckedImage:[ORKCheckmarkView unCheckedImage]]; +} + +- (instancetype)initWithDefaultsWithoutCircle { + return [self initWithRadius:CheckmarkViewDimension*0.5 + checkedImage:[ORKCheckmarkView checkedImageWithoutCircle] + uncheckedImage:nil + shouldShowCircle:NO]; +} + +- (CGFloat)getDimension { + return _dimension; +} + ++ (UIImage *)unCheckedImage { + if (@available(iOS 13.0, *)) { + UIImageConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] scale:UIImageSymbolScaleLarge]; + return [UIImage systemImageNamed:@"circle" withConfiguration:configuration]; + } else { + return nil; + } +} + ++ (UIImage *)checkedImage { + if (@available(iOS 13.0, *)) { + UIImageConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] scale:UIImageSymbolScaleLarge]; + return [UIImage systemImageNamed:@"checkmark.circle.fill" withConfiguration:configuration]; + } else { + return [[UIImage imageNamed:@"checkmark" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } +} + ++ (UIImage *)checkedImageWithoutCircle { + if (@available(iOS 13.0, *)) { + UIImageConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] scale:UIImageSymbolScaleLarge]; + return [UIImage systemImageNamed:@"checkmark" withConfiguration:configuration]; + } else { + return [[UIImage imageNamed:@"checkmark" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } +} + +- (void)updateCheckView { + if (_checked) { + self.image = _checkedImage; + // FIXME: Need to be replaced. + if (@available(iOS 13.0, *)) { + self.tintColor = UIColor.systemBlueColor; + } else { + self.backgroundColor = [self tintColor]; + self.tintColor = UIColor.whiteColor; + } + } + else { + self.image = _uncheckedImage; + if (@available(iOS 13.0, *)) { + self.tintColor = [UIColor systemGray3Color]; + } else { + self.tintColor = nil; + self.image = nil; + self.backgroundColor = UIColor.clearColor; + } + } +} + +- (void)setupView { + [[self.widthAnchor constraintEqualToConstant:_dimension] setActive:YES]; + [[self.heightAnchor constraintEqualToConstant:_dimension] setActive:YES]; + + if (@available(iOS 13.0, *)) { + // use SFSymbols directly + } else { + self.layer.cornerRadius = _dimension * 0.5; + self.layer.borderWidth = CheckmarkViewBorderWidth; + self.layer.borderColor = self.tintColor.CGColor; + self.layer.masksToBounds = YES; + } + + self.contentMode = UIViewContentModeCenter; +} + +- (void)setChecked:(BOOL)checked { + _checked = checked; + [self updateCheckView]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.h new file mode 100755 index 0000000..6403591 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerFormat; +@class ORKImageChoice; +@class ORKTextChoice; +@protocol ORKAnswerOption; + +@interface ORKChoiceAnswerFormatHelper : NSObject + +- (instancetype)initWithAnswerFormat:(ORKAnswerFormat *)answerFormat; + +- (NSUInteger)choiceCount; + +- (nullable id)answerOptionAtIndex:(NSUInteger)index; +- (nullable ORKImageChoice *)imageChoiceAtIndex:(NSUInteger)index; +- (nullable ORKTextChoice *)textChoiceAtIndex:(NSUInteger)index; + +- (nullable id)answerForSelectedIndex:(NSUInteger)index; +- (nullable id)answerForSelectedIndexes:(NSArray *)indexes; + +- (nullable NSNumber *)selectedIndexForAnswer:(nullable id)answer; +- (NSArray *)selectedIndexesForAnswer:(nullable id)answer; + +- (nullable NSString *)stringForChoiceAnswer:(id)answer; +- (nullable NSString *)labelForChoiceAnswer:(id)answer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.m new file mode 100755 index 0000000..a8ab949 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceAnswerFormatHelper.m @@ -0,0 +1,220 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKChoiceAnswerFormatHelper.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionResult_Private.h" +#import "ORKResult_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKChoiceAnswerFormatHelper { + NSArray *_choices; + BOOL _isValuePicker; +} + +- (instancetype)initWithAnswerFormat:(ORKAnswerFormat *)answerFormat { + self = [super init]; + if (self) { + if ([answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]]) { + ORKValuePickerAnswerFormat *valuePickerAnswerFormat = (ORKValuePickerAnswerFormat *)answerFormat; + ORKTextChoice *nullChoice = valuePickerAnswerFormat.nullTextChoice; + _choices = [@[nullChoice] arrayByAddingObjectsFromArray:valuePickerAnswerFormat.textChoices]; + _isValuePicker = YES; + } else if ([answerFormat isKindOfClass:[ORKTextChoiceAnswerFormat class]]) { + ORKTextChoiceAnswerFormat *textChoiceAnswerFormat = (ORKTextChoiceAnswerFormat *)answerFormat; + _choices = textChoiceAnswerFormat.textChoices; + } else if ([answerFormat isKindOfClass:[ORKImageChoiceAnswerFormat class]]) { + ORKImageChoiceAnswerFormat *imageChoiceAnswerFormat = (ORKImageChoiceAnswerFormat *)answerFormat; + _choices = imageChoiceAnswerFormat.imageChoices; + } else if ([answerFormat isKindOfClass:[ORKTextScaleAnswerFormat class]]) { + ORKTextScaleAnswerFormat *textScaleAnswerFormat = (ORKTextScaleAnswerFormat *)answerFormat; + _choices = textScaleAnswerFormat.textChoices; + } else { + NSString *exceptionReason = [NSString stringWithFormat:@"%@ is not a currently supported answer format for the choice answer format helper.", NSStringFromClass([answerFormat class])]; + @throw [NSException exceptionWithName:NSGenericException reason:exceptionReason userInfo:nil]; + } + } + return self; +} + +- (NSUInteger)choiceCount { + return _choices.count; +} + +- (id)answerOptionAtIndex:(NSUInteger)index { + if (index >= _choices.count) { + return nil; + } + + return _choices[index]; +} + +- (ORKImageChoice *)imageChoiceAtIndex:(NSUInteger)index { + id option = [self answerOptionAtIndex:index]; + return option && [option isKindOfClass:[ORKImageChoice class]] ? (ORKImageChoice *) option : nil; +} + +- (ORKTextChoice *)textChoiceAtIndex:(NSUInteger)index { + id option = [self answerOptionAtIndex:index]; + return option && [option isKindOfClass:[ORKTextChoice class]] ? (ORKTextChoice *) option : nil; +} + +- (id)answerForSelectedIndex:(NSUInteger)index { + return [self answerForSelectedIndexes:@[ @(index) ]]; +} + +- (id)answerForSelectedIndexes:(NSArray *)indexes { + NSMutableArray *array = [NSMutableArray new]; + + for (NSNumber *indexNumber in indexes) { + + NSUInteger index = indexNumber.unsignedIntegerValue; + + if (index >= _choices.count) { + continue; + } + + id choice = _choices[index]; + ORKTextChoiceOther *textChoiceOther; + if ([choice isKindOfClass: [ORKTextChoiceOther class]]) { + textChoiceOther = (ORKTextChoiceOther *)choice; + } + id value = textChoiceOther.textViewText ? : choice.value; + if (value == nil) { + value = _isValuePicker ? @(index - 1) : @(index); + } + + if (_isValuePicker && index == 0) { + // Don't add to answer array if this index is the 1st value of a value picker + } else { + [array addObject:value]; + } + } + return array.count > 0 ? [array copy] : ORKNullAnswerValue(); +} + +- (NSNumber *)selectedIndexForAnswer:(nullable id)answer { + NSArray *indexes = [self selectedIndexesForAnswer:answer]; + return indexes.count > 0 ? indexes.firstObject : nil; +} + +- (NSArray *)selectedIndexesForAnswer:(nullable id)answer { + // Works with boolean result + if ([answer isKindOfClass:[NSNumber class]]) { + answer = @[answer]; + } + + NSMutableArray *indexArray = [NSMutableArray new]; + + if (answer != nil && answer != ORKNullAnswerValue() ) { + + if (![answer isKindOfClass:[ORKChoiceQuestionResult answerClass]]) { + @throw [NSException exceptionWithName:@"Wrong answer type" + reason:[NSString stringWithFormat:@"Expected answer type %@, but was given %@", [ORKChoiceQuestionResult answerClass], [answer class]] + userInfo:nil]; + } + + for (id answerValue in (NSArray *)answer) { + id matchedChoice = nil; + for ( id choice in _choices) { + if ([choice isKindOfClass:[ORKTextChoiceOther class]]) { + ORKTextChoiceOther *textChoiceOther = (ORKTextChoiceOther *)choice; + if ([textChoiceOther.textViewText isEqual:answerValue]) { + matchedChoice = choice; + break; + } else if (textChoiceOther.textViewInputOptional && textChoiceOther.textViewText.length <= 0 && [textChoiceOther.value isEqual:answerValue]) { + matchedChoice = choice; + break; + } + } else if ([choice.value isEqual:answerValue]) { + matchedChoice = choice; + break; + } + } + + if (nil == matchedChoice) { + + if (![answerValue isKindOfClass:[NSNumber class]]) { + @throw [NSException exceptionWithName:@"No matching choice found" + reason:[NSString stringWithFormat:@"Provided choice of type %@ not found in available choices", [answerValue class]] + userInfo:nil]; + } + + if (_isValuePicker) { + matchedChoice = _choices[((NSNumber *)answerValue).unsignedIntegerValue + 1]; + } else { + matchedChoice = _choices[((NSNumber *)answerValue).unsignedIntegerValue]; + } + } + + if (matchedChoice) { + [indexArray addObject:@([_choices indexOfObject:matchedChoice])]; + } + } + } + + if (_isValuePicker && indexArray.count == 0) { + // value picker should at least select the placeholder index + [indexArray addObject:@(0)]; + } + + return [indexArray copy]; + +} + +- (NSString *)stringForChoiceAnswer:(id)answer { + NSMutableArray *answerStrings = [[NSMutableArray alloc] init]; + NSArray *indexes = [self selectedIndexesForAnswer:answer]; + for (NSNumber *index in indexes) { + NSString *text = [[self answerOptionAtIndex:[index integerValue]] text]; + if (text != nil) { + [answerStrings addObject:text]; + } + } + return [answerStrings componentsJoinedByString:@"\n"]; +} + +- (NSString *)labelForChoiceAnswer:(id)answer { + NSMutableArray *answerStrings = [[NSMutableArray alloc] init]; + NSArray *indexes = [self selectedIndexesForAnswer:answer]; + for (NSNumber *index in indexes) { + NSString *text = [[self answerOptionAtIndex:[index integerValue]] text]; + if (text != nil) { + [answerStrings addObject:text]; + } + } + return [answerStrings componentsJoinedByString:@", "]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.h new file mode 100755 index 0000000..82e89c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerTextView; + +@interface ORKChoiceViewCell : UITableViewCell + +@property (nonatomic, assign, getter=isImmediateNavigation) BOOL immediateNavigation; + +@property (nonatomic, assign, getter=isCellSelected) BOOL cellSelected; + +@property (nonatomic) bool useCardView; + +@property (nonatomic) bool isLastItem; + +@property (nonatomic) BOOL isFirstItemInSectionWithoutTitle; + +@property (nonatomic) ORKCardViewStyle cardViewStyle; + +- (void)setPrimaryText:(NSString *)primaryText; +- (void)setPrimaryAttributedText: (NSAttributedString *)primaryAttributedText; +- (void)setDetailText:(NSString *)detailText; +- (void)setDetailAttributedText:(NSAttributedString *)detailAttributedText; +- (void)setCellSelected:(BOOL)cellSelected highlight:(BOOL)highlight; + +@end + +@interface ORKChoiceOtherViewCell : ORKChoiceViewCell + +@property (nonatomic, strong, readonly) ORKAnswerTextView *textView; + +@property (nonatomic, assign, setter=hideTextView:) BOOL textViewHidden; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.m new file mode 100755 index 0000000..14f58dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell.m @@ -0,0 +1,611 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKChoiceViewCell_Internal.h" + +#import "ORKSelectionTitleLabel.h" +#import "ORKSelectionSubTitleLabel.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKAnswerTextView.h" +#import "ORKSkin.h" +#import "ORKCheckmarkView.h" + +static const CGFloat CardTopBottomMargin = 2.0; +static const CGFloat LabelTopBottomMargin = 14.0; +static const CGFloat TextViewTopMargin = 20.0; +static const CGFloat TextViewHeight = 100.0; +static const CGFloat LabelCheckViewPadding = 10.0; + +@interface ORKChoiceViewCell() + +@property (nonatomic) UIView *containerView; +@property (nonatomic) ORKSelectionTitleLabel *primaryLabel; +@property (nonatomic) ORKSelectionSubTitleLabel *detailLabel; +@property (nonatomic) ORKCheckmarkView *checkView; +@property (nonatomic) NSMutableArray *containerConstraints; + +@end + +@implementation ORKChoiceViewCell { + + CGFloat _leftRightMargin; + CGFloat _topBottomMargin; + CAShapeLayer *_contentMaskLayer; + UIColor *_fillColor; + CAShapeLayer *_foreLayer; + CAShapeLayer *_animationLayer; + CGRect _foreLayerBounds; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + self.clipsToBounds = YES; + _leftRightMargin = 0.0; + _topBottomMargin = 0.0; + [self setupContainerView]; + [self setupCheckView]; + } + return self; +} + +- (void) drawRect:(CGRect)rect { + [super drawRect:rect]; + [self setMaskLayers]; +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + if (@available(iOS 13.0, *)) { + _fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + // FIXME:- dark mode color displays solid black after animation ends if the views are stacked + if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + _fillColor = [UIColor colorWithRed:0.173 green:0.173 blue:0.180 alpha:1.0]; + } + } else { + _fillColor = [UIColor ork_borderGrayColor]; + } +} + +- (void)setMaskLayers { + if (_useCardView && !_animationLayer) { + if (_contentMaskLayer) { + for (CALayer *sublayer in [_contentMaskLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + [_contentMaskLayer removeFromSuperlayer]; + _contentMaskLayer = nil; + } + _contentMaskLayer = [[CAShapeLayer alloc] init]; + UIColor *borderColor; + if (@available(iOS 13.0, *)) { + _fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + // FIXME:- dark mode color displays solid black after animation ends if the views are stacked + if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + _fillColor = [UIColor colorWithRed:0.173 green:0.173 blue:0.180 alpha:1.0]; + } + borderColor = UIColor.separatorColor; + } else { + _fillColor = [UIColor ork_borderGrayColor]; + borderColor = [UIColor ork_midGrayTintColor]; + } + [_contentMaskLayer setFillColor:[_fillColor CGColor]]; + + [_foreLayer removeFromSuperlayer]; + _foreLayer = nil; + _foreLayer = [CAShapeLayer layer]; + [_foreLayer setFillColor:[_fillColor CGColor]]; + _foreLayer.zPosition = 0.0f; + + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + + if (_isLastItem || _isFirstItemInSectionWithoutTitle) { + NSUInteger rectCorners; + if (_isLastItem && !_isFirstItemInSectionWithoutTitle) { + rectCorners = UIRectCornerBottomLeft | UIRectCornerBottomRight; + } + else if (!_isLastItem && _isFirstItemInSectionWithoutTitle) { + rectCorners = UIRectCornerTopLeft | UIRectCornerTopRight; + } + else { + rectCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight; + } + + _foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height - ORKCardDefaultBorderWidth); + + _contentMaskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.containerView.bounds + byRoundingCorners: rectCorners + cornerRadii: (CGSize){ORKCardDefaultCornerRadii, ORKCardDefaultCornerRadii}].CGPath; + + CGFloat foreLayerCornerRadii = ORKCardDefaultCornerRadii >= ORKCardDefaultBorderWidth ? ORKCardDefaultCornerRadii - ORKCardDefaultBorderWidth : ORKCardDefaultCornerRadii; + + _foreLayer.path = [UIBezierPath bezierPathWithRoundedRect: _foreLayerBounds + byRoundingCorners: rectCorners + cornerRadii: (CGSize){foreLayerCornerRadii, foreLayerCornerRadii}].CGPath; + } + else { + _foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height); + _foreLayer.path = [UIBezierPath bezierPathWithRect:_foreLayerBounds].CGPath; + _contentMaskLayer.path = [UIBezierPath bezierPathWithRect:self.containerView.bounds].CGPath; + + CGRect lineBounds = CGRectMake(ORKSurveyItemMargin, self.containerView.bounds.size.height - 1.0, self.containerView.bounds.size.width - ORKSurveyItemMargin, 0.5); + lineLayer.path = [UIBezierPath bezierPathWithRect:lineBounds].CGPath; + lineLayer.zPosition = 0.0f; + } + + lineLayer.fillColor = borderColor.CGColor; + if (_cardViewStyle == ORKCardViewStyleBordered) { + _contentMaskLayer.fillColor = borderColor.CGColor; + } + + [_contentMaskLayer addSublayer:_foreLayer]; + + [_contentMaskLayer addSublayer:lineLayer]; + [_containerView.layer insertSublayer:_contentMaskLayer atIndex:0]; + } +} + +- (void)setupContainerView { + if (!_containerView) { + _containerView = [UIView new]; + } + [self addSubview:_containerView]; +} + +- (void)addContainerViewToSelfConstraints { + [_containerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0], + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:_leftRightMargin], + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-_leftRightMargin] + ]]; +} + +- (void)addPrimaryLabelToContainerViewConstraints { + if (_primaryLabel) { + + [_containerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_primaryLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:LabelTopBottomMargin], + [NSLayoutConstraint constraintWithItem:_primaryLabel + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:_checkView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:-LabelCheckViewPadding], + [NSLayoutConstraint constraintWithItem:_primaryLabel + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:ORKSurveyItemMargin] + ]]; + } +} + +- (void)addDetailLabelConstraints { + if (_detailLabel) { + [_containerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_detailLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_primaryLabel ? : _containerView + attribute:_primaryLabel ? NSLayoutAttributeBottom : NSLayoutAttributeTop + multiplier:1.0 + constant:_primaryLabel ? 0.0 : LabelTopBottomMargin], + [NSLayoutConstraint constraintWithItem:_detailLabel + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:_checkView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:-LabelCheckViewPadding], + [NSLayoutConstraint constraintWithItem:_detailLabel + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:ORKSurveyItemMargin] + ]]; + } +} + +- (void)addContainerViewBottomConstraint { + [_containerConstraints addObject:[NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_detailLabel ? : _primaryLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:LabelTopBottomMargin]]; +} + +- (void)setupConstraints { + if (!_primaryLabel && !_detailLabel) { + return; + } + + if (_containerConstraints) { + [NSLayoutConstraint deactivateConstraints:_containerConstraints]; + } + + _containerView.translatesAutoresizingMaskIntoConstraints = NO; + _containerConstraints = [[NSMutableArray alloc] init]; + [self addContainerViewToSelfConstraints]; + [self addPrimaryLabelToContainerViewConstraints]; + [self addDetailLabelConstraints]; + [self addCheckViewToContainerViewConstraints]; + [self addContainerViewBottomConstraint]; + [_containerConstraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:_containerConstraints]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self updateSelectedItem]; + [self setMaskLayers]; +} + +- (void)setUseCardView:(bool)useCardView { + _useCardView = useCardView; + _leftRightMargin = ORKCardLeftRightMarginForWindow(self.window); + _topBottomMargin = CardTopBottomMargin; + [self setBackgroundColor:[UIColor clearColor]]; + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self setupConstraints]; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self updateSelectedItem]; +} + +- (void)updateSelectedItem { + [self updateCheckView]; +} + +- (void)setImmediateNavigation:(BOOL)immediateNavigation { + _immediateNavigation = immediateNavigation; +} + +- (void)setCellSelected:(BOOL)cellSelected highlight:(BOOL)highlight { + _cellSelected = cellSelected; + [self updateSelectedItem]; + + if (highlight) { + _animationLayer = [CAShapeLayer layer]; + [_animationLayer setOpaque:NO]; + _animationLayer.frame = _foreLayerBounds; + _animationLayer.zPosition = 1.0f; + [_contentMaskLayer addSublayer:_animationLayer]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; + if (@available(iOS 13.0, *)) { + animation.fromValue = (__bridge id _Nullable)(UIColor.systemGray5Color.CGColor); + } else { + animation.fromValue = (__bridge id _Nullable)([UIColor colorWithRed:0.282 green:0.282 blue:0.235 alpha:1.0].CGColor); + } + animation.toValue = (__bridge id _Nullable)(_fillColor.CGColor); + animation.beginTime = 0.0; + animation.duration = 0.45; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + animation.removedOnCompletion = YES; + animation.delegate = self; + [_animationLayer addAnimation:animation forKey:@"backgroundColor"]; + _animationLayer.backgroundColor = _fillColor.CGColor; + } +} + +- (void)setupPrimaryLabel { + if (!_primaryLabel) { + _primaryLabel = [ORKSelectionTitleLabel new]; + _primaryLabel.numberOfLines = 0; + if (@available(iOS 13.0, *)) { + _primaryLabel.textColor = [UIColor labelColor]; + } else { + _primaryLabel.textColor = [UIColor blackColor]; + } + [self.containerView addSubview:_primaryLabel]; + _primaryLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self setupConstraints]; + } +} + +- (void)setupDetailLabel { + if (!_detailLabel) { + _detailLabel = [ORKSelectionSubTitleLabel new]; + _detailLabel.numberOfLines = 0; + _detailLabel.textColor = [UIColor ork_darkGrayColor]; + [self.containerView addSubview:_detailLabel]; + _detailLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self setupConstraints]; + } +} + +- (UIImage *)unCheckedImage { + if (@available(iOS 13.0, *)) { + UIImageConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] scale:UIImageSymbolScaleLarge]; + return [UIImage systemImageNamed:@"circle" withConfiguration:configuration]; + } else { + return nil; + } +} + +- (UIImage *)checkedImage { + if (@available(iOS 13.0, *)) { + UIImageConfiguration *configuration = [UIImageSymbolConfiguration configurationWithFont:[UIFont preferredFontForTextStyle:UIFontTextStyleBody] scale:UIImageSymbolScaleLarge]; + return [UIImage systemImageNamed:@"checkmark.circle.fill" withConfiguration:configuration]; + } else { + return [[UIImage imageNamed:@"checkmark" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } +} + +- (void)setupCheckView { + if (!_checkView) { + _checkView = [[ORKCheckmarkView alloc] initWithDefaults]; + } + [_checkView setChecked:NO]; + [self.containerView addSubview:_checkView]; +} + +- (void)addCheckViewToContainerViewConstraints { + if (_checkView) { + _checkView.translatesAutoresizingMaskIntoConstraints = NO; + [_containerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_checkView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_checkView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-ORKSurveyItemMargin] + ]]; + } +} + +- (void)setPrimaryText:(NSString *)primaryText { + if (primaryText) { + [self setupPrimaryLabel]; + _primaryLabel.text = primaryText; + } +} + +- (void)setPrimaryAttributedText:(NSAttributedString *)primaryAttributedText { + if (primaryAttributedText) { + [self setupPrimaryLabel]; + _primaryLabel.attributedText = primaryAttributedText; + } +} + +- (void)setDetailText:(NSString *)detailText { + if (detailText) { + [self setupDetailLabel]; + _detailLabel.text = detailText; + } +} + +- (void)setDetailAttributedText:(NSAttributedString *)detailAttributedText { + if (detailAttributedText) { + [self setupDetailLabel]; + _detailLabel.attributedText = detailAttributedText; + } +} + +- (void)updateCheckView { + if (_checkView) { + [_checkView setChecked:_cellSelected]; + } +} + + +#pragma mark - Accessibility + +- (NSString *)accessibilityLabel { + return ORKAccessibilityStringForVariables(_primaryLabel.accessibilityLabel, _detailLabel.accessibilityLabel); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return UIAccessibilityTraitButton | (self.isCellSelected ? UIAccessibilityTraitSelected : 0); +} + +- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { + [super setHighlighted:highlighted + animated:animated]; + + if (highlighted) { + if (@available(iOS 13.0, *)) { + [_foreLayer setFillColor:UIColor.systemGray5Color.CGColor]; + } else { + self.layer.backgroundColor = [UIColor colorWithRed:0.282 green:0.282 blue:0.235 alpha:1.0].CGColor; + } + } + else { + _foreLayer.fillColor = _fillColor.CGColor; + } +} + +#pragma mark - Animation Delegate + +- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { + [_animationLayer removeFromSuperlayer]; + _animationLayer = nil; + [self setMaskLayers]; +} + +@end + + +@implementation ORKChoiceOtherViewCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + _textViewHidden = NO; + [self setupAnswerTextView]; + return self; +} + +- (void)setupAnswerTextView { + if (!_textView) { + _textView = [[ORKAnswerTextView alloc] init]; + _textView.delegate = self; + _textView.translatesAutoresizingMaskIntoConstraints = NO; + [self.containerView addSubview:_textView]; + [self updateTextView]; + } +} + +- (void)hideTextView:(BOOL)textViewHidden { + _textViewHidden = textViewHidden; + [self updateTextView]; + [self setupConstraints]; +} + +- (void)updateTextView { + [self.textView setHidden:_textViewHidden]; +} + +- (void)addOtherAnswerTextViewConstraints { + + NSLayoutConstraint *textViewHeightConstraint = [NSLayoutConstraint constraintWithItem:_textView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:MAX(_textView.font.pointSize, TextViewHeight)]; + textViewHeightConstraint.priority = UILayoutPriorityDefaultLow; + + [self.containerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_textView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.detailLabel ? : self.primaryLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:TextViewTopMargin], + [NSLayoutConstraint constraintWithItem:_textView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self.checkView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:-LabelCheckViewPadding], + [NSLayoutConstraint constraintWithItem:_textView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self.containerView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:ORKSurveyItemMargin], + textViewHeightConstraint, + [NSLayoutConstraint constraintWithItem:self.containerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_textView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:LabelTopBottomMargin] + ]]; +} + +// Overriding ContainerView Bottom Constraints +- (void)addContainerViewBottomConstraint { + if (_textViewHidden) { + [super addContainerViewBottomConstraint]; + } + else { + [self addOtherAnswerTextViewConstraints]; + } +} + +- (void)setMaskLayers { + [super setMaskLayers]; + _textView.layer.borderWidth = 0.25; + [_textView.layer setBorderColor:[UIColor lightGrayColor].CGColor]; + _textView.layer.cornerRadius = 10.0; +} + +# pragma mark - UITextViewDelegate + +- (void)textViewDidBeginEditing:(UITextView *)textView { + if (self.delegate && [self.delegate respondsToSelector:@selector(textChoiceOtherCellDidBecomeFirstResponder:)]) { + [self.delegate textChoiceOtherCellDidBecomeFirstResponder:self]; + } +} + +- (void) textViewDidEndEditing:(UITextView *)textView { + if (self.delegate && [self.delegate respondsToSelector:@selector(textChoiceOtherCellDidResignFirstResponder:)]) { + [self.delegate textChoiceOtherCellDidResignFirstResponder:self]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell_Internal.h new file mode 100755 index 0000000..ec21865 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKChoiceViewCell_Internal.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKChoiceViewCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKChoiceOtherViewCellDelegate + +- (void)textChoiceOtherCellDidBecomeFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell; +- (void)textChoiceOtherCellDidResignFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell; + +@end + + +@interface ORKChoiceOtherViewCell() + +@property (nonatomic, weak) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.h new file mode 100755 index 0000000..2a52a64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.h @@ -0,0 +1,214 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStepResult; + +/** + The `ORKCollectionResult` class represents a result that contains an array of + child results. + + `ORKCollectionResult` is the superclass of `ORKTaskResult` and `ORKStepResult`. + + Note that object of this class are not instantiated directly by the ResearchKit framework. + */ +ORK_CLASS_AVAILABLE +@interface ORKCollectionResult : ORKResult + +/** + An array of `ORKResult` objects that are the children of the result. + + For `ORKTaskResult`, the array contains `ORKStepResult` objects. + For `ORKStepResult` the array contains concrete result objects such as `ORKFileResult` + and `ORKQuestionResult`. + */ +@property (nonatomic, copy, nullable) NSArray *results; + +/** + Looks up the child result containing an identifier that matches the specified identifier. + + @param identifier The identifier of the step for which to search. + + @return The matching result, or `nil` if none was found. + */ +- (nullable ORKResult *)resultForIdentifier:(NSString *)identifier; + +/** + The first result. + + This is the first result, or `nil` if there are no results. + */ +@property (nonatomic, strong, readonly, nullable) ORKResult *firstResult; + +@end + + +/** + `ORKTaskResultSource` is the protocol for `[ORKTaskViewController defaultResultSource]`. + */ +@protocol ORKTaskResultSource + +/** + Returns a step result for the specified step identifier, if one exists. + + When it's about to present a step, the task view controller needs to look up a + suitable default answer. The answer can be used to prepopulate a survey with + the results obtained on a previous run of the same task, by passing an + `ORKTaskResult` object (which itself implements this protocol). + + @param stepIdentifier The identifier for which to search. + + @return The result for the specified step, or `nil` for none. + */ +- (nullable ORKStepResult *)stepResultForStepIdentifier:(NSString *)stepIdentifier; + +/** + Should the default result store be used even if there is a previous result? (due to + reverse navigation or looping) + + By default, the `[ORKTaskViewController defaultResultSource]` is only queried for a + result if the previous result is nil. This allows the result source to override that + default behavior. + + @return `YES` if the default result should be given priority over the previous result. + */ +@optional +- (BOOL)alwaysCheckForDefaultResult; + +@end + + +/** + An `ORKTaskResult` object is a collection result that contains all the step results + generated from one run of a task or ordered task (that is, `ORKTask` or `ORKOrderedTask`) in a task view controller. + + A task result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + + The `results` property of the `ORKCollectionResult` object contains the step results + for the task. + */ +ORK_CLASS_AVAILABLE +@interface ORKTaskResult : ORKCollectionResult + +/** + Returns an intialized task result using the specified identifiers and directory. + + @param identifier The identifier of the task that produced this result. + @param taskRunUUID The UUID of the run of the task that produced this result. + @param outputDirectory The directory in which any files referenced by results can be found. + + @return An initialized task result. + */ +- (instancetype)initWithTaskIdentifier:(NSString *)identifier + taskRunUUID:(NSUUID *)taskRunUUID + outputDirectory:(nullable NSURL *)outputDirectory; + +/** + A unique identifier (UUID) for the presentation of the task that generated + the result. + + The unique identifier for a run of the task typically comes directly + from the task view controller that was used to run the task. + */ +@property (nonatomic, copy, readonly) NSUUID *taskRunUUID; + +/** + The directory in which the generated data files were stored while the task was run. + + The directory comes directly from the task view controller that was used to run this + task. Generally, when archiving the results of a task, it is useful to archive + all the files found in the output directory. + + The file URL also prefixes the file URLs referenced in any child + `ORKFileResult` objects. + */ +@property (nonatomic, copy, readonly, nullable) NSURL *outputDirectory; + +@end + + +/** + The `ORKStepResult` class represents a collection result produced by a step view controller to + hold all child results produced by the step. + + A step result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + + For example, an `ORKQuestionStep` object produces an `ORKQuestionResult` object that becomes + a child of the `ORKStepResult` object. Similarly, an `ORKActiveStep` object may produce individual + child result objects for each of the recorder configurations that was active + during that step. + + The `results` property of the `ORKCollectionResult` object contains the step results + for the task. + */ +ORK_CLASS_AVAILABLE +@interface ORKStepResult : ORKCollectionResult + + +/** + Returns an initialized step result using the specified identifier. + + @param stepIdentifier The identifier of the step. + @param results The array of child results. The value of this parameter can be `nil` or empty + if no results were collected. + + @return An initialized step result. + */ +- (instancetype)initWithStepIdentifier:(NSString *)stepIdentifier results:(nullable NSArray *)results; + +/** + This property indicates whether the Voice Over or Switch Control assistive technologies were active + while performing the corresponding step. + + This information can be used, for example, to take into consideration the extra time needed by + handicapped participants to complete some tasks, such as the Tower of Hanoi activity. + + The property can have the following values: + - `UIAccessibilityNotificationVoiceOverIdentifier` if Voice Over was active + - `UIAccessibilityNotificationSwitchControlIdentifier` if Switch Control was active + + Note that the Voice Over and Switch Control assistive technologies are mutually exclusive. + + If the property is `nil`, none of these assistive technologies was used. + */ +@property (nonatomic, copy, readonly, nullable) NSString *enabledAssistiveTechnology; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.m new file mode 100755 index 0000000..23e6310 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult.m @@ -0,0 +1,383 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCollectionResult.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKPageStep.h" +#import "ORKQuestionResult_Private.h" +#import "ORKResult_Private.h" +#import "ORKStep.h" +#import "ORKTask.h" + +#import "ORKHelpers_Internal.h" + +@interface ORKCollectionResult () + +- (void)setResultsCopyObjects:(NSArray *)results; + +@end + + +@implementation ORKCollectionResult + +- (BOOL)isSaveable { + BOOL saveable = NO; + + for (ORKResult *result in _results) { + if ([result isSaveable]) { + saveable = YES; + break; + } + } + return saveable; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, results); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, results, ORKResult); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.results, castObject.results)); +} + +- (NSUInteger)hash { + return super.hash ^ self.results.hash; +} + +- (void)setResultsCopyObjects:(NSArray *)results { + _results = ORKArrayCopyObjects(results); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKCollectionResult *result = [super copyWithZone:zone]; + [result setResultsCopyObjects: self.results]; + return result; +} + +- (NSArray *)results { + if (_results == nil) { + _results = [NSArray new]; + } + return _results; +} + +- (ORKResult *)resultForIdentifier:(NSString *)identifier { + + if (identifier == nil) { + return nil; + } + + __block ORKQuestionResult *result = nil; + + // Look through the result set in reverse-order to account for the possibility of + // multiple results with the same identifier (due to a navigation loop) + NSEnumerator *enumerator = self.results.reverseObjectEnumerator; + id obj = enumerator.nextObject; + while ((result== nil) && (obj != nil)) { + + if (NO == [obj isKindOfClass:[ORKResult class]]) { + @throw [NSException exceptionWithName:NSGenericException reason:[NSString stringWithFormat: @"Expected result object to be ORKResult type: %@", obj] userInfo:nil]; + } + + NSString *anIdentifier = [(ORKResult *)obj identifier]; + if ([anIdentifier isEqual:identifier]) { + result = obj; + } + obj = enumerator.nextObject; + } + + return result; +} + +- (ORKResult *)firstResult { + + return self.results.firstObject; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + NSMutableString *description = [NSMutableString stringWithFormat:@"%@; results: (", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces]]; + + NSUInteger numberOfResults = self.results.count; + [self.results enumerateObjectsUsingBlock:^(ORKResult *result, NSUInteger idx, BOOL *stop) { + if (idx == 0) { + [description appendString:@"\n"]; + } + [description appendFormat:@"%@", [result descriptionWithNumberOfPaddingSpaces:numberOfPaddingSpaces + NumberOfPaddingSpacesForIndentationLevel]]; + if (idx != numberOfResults - 1) { + [description appendString:@",\n"]; + } else { + [description appendString:@"\n"]; + } + }]; + + [description appendFormat:@"%@)%@", ORKPaddingWithNumberOfSpaces((numberOfResults == 0) ? 0 : numberOfPaddingSpaces), self.descriptionSuffix]; + return [description copy]; +} + +@end + + +#pragma mark - ORKTaskResult + +@implementation ORKTaskResult + +- (instancetype)initWithTaskIdentifier:(NSString *)identifier + taskRunUUID:(NSUUID *)taskRunUUID + outputDirectory:(NSURL *)outputDirectory { + self = [super initWithIdentifier:identifier]; + if (self) { + self->_taskRunUUID = [taskRunUUID copy]; + self->_outputDirectory = [outputDirectory copy]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, taskRunUUID); + ORK_ENCODE_URL(aCoder, outputDirectory); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, taskRunUUID, NSUUID); + ORK_DECODE_URL(aDecoder, outputDirectory); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.taskRunUUID, castObject.taskRunUUID) && + ORKEqualFileURLs(self.outputDirectory, castObject.outputDirectory)); +} + +- (NSUInteger)hash { + return super.hash ^ self.taskRunUUID.hash ^ self.outputDirectory.hash; +} + + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTaskResult *result = [super copyWithZone:zone]; + result->_taskRunUUID = [self.taskRunUUID copy]; + result->_outputDirectory = [self.outputDirectory copy]; + return result; +} + +- (ORKStepResult *)stepResultForStepIdentifier:(NSString *)stepIdentifier { + return (ORKStepResult *)[self resultForIdentifier:stepIdentifier]; +} + +@end + + +#pragma mark - ORKStepResult + +@implementation ORKStepResult + +- (instancetype)initWithStepIdentifier:(NSString *)stepIdentifier results:(NSArray *)results { + self = [super initWithIdentifier:stepIdentifier]; + if (self) { + [self setResultsCopyObjects:results]; + [self updateEnabledAssistiveTechnology]; + } + return self; +} + +- (void)updateEnabledAssistiveTechnology { + if (UIAccessibilityIsVoiceOverRunning()) { + _enabledAssistiveTechnology = [UIAccessibilityNotificationVoiceOverIdentifier copy]; + } else if (UIAccessibilityIsSwitchControlRunning()) { + _enabledAssistiveTechnology = [UIAccessibilityNotificationSwitchControlIdentifier copy]; + } +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, enabledAssistiveTechnology); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, enabledAssistiveTechnology, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.enabledAssistiveTechnology, castObject.enabledAssistiveTechnology)); +} + +- (NSUInteger)hash { + return super.hash ^ _enabledAssistiveTechnology.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKStepResult *result = [super copyWithZone:zone]; + result->_enabledAssistiveTechnology = [_enabledAssistiveTechnology copy]; + return result; +} + +- (NSString *)descriptionPrefixWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; enabledAssistiveTechnology: %@", [super descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], _enabledAssistiveTechnology ? : @"None"]; +} + +@end + + +#pragma mark - ORKPageResult + +@implementation ORKPageResult + +- (instancetype)initWithPageStep:(ORKPageStep *)step stepResult:(ORKStepResult*)result { + self = [super initWithTaskIdentifier:step.identifier taskRunUUID:[NSUUID UUID] outputDirectory:nil]; + if (self) { + NSArray *stepIdentifiers = [step.steps valueForKey:@"identifier"]; + NSMutableArray *results = [NSMutableArray new]; + for (NSString *identifier in stepIdentifiers) { + NSString *prefix = [NSString stringWithFormat:@"%@.", identifier]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"identifier BEGINSWITH %@", prefix]; + NSArray *filteredResults = [result.results filteredArrayUsingPredicate:predicate]; + if (filteredResults.count > 0) { + NSMutableArray *subresults = [NSMutableArray new]; + for (ORKResult *subresult in filteredResults) { + ORKResult *copy = [subresult copy]; + copy.identifier = [subresult.identifier substringFromIndex:prefix.length]; + [subresults addObject:copy]; + } + [results addObject:[[ORKStepResult alloc] initWithStepIdentifier:identifier results:subresults]]; + } + } + self.results = results; + } + return self; +} + +- (void)addStepResult:(ORKStepResult *)stepResult { + if (stepResult == nil) { + return; + } + + // Remove previous step result and add the new one + NSMutableArray *results = [self.results mutableCopy] ?: [NSMutableArray new]; + ORKResult *previousResult = [self resultForIdentifier:stepResult.identifier]; + if (previousResult) { + [results removeObject:previousResult]; + } + [results addObject:stepResult]; + self.results = results; +} + +- (void)removeStepResultWithIdentifier:(NSString *)identifier { + ORKResult *result = [self resultForIdentifier:identifier]; + if (result != nil) { + NSMutableArray *results = [self.results mutableCopy]; + [results removeObject:result]; + self.results = results; + } +} + +- (void)removeStepResultsAfterStepWithIdentifier:(NSString *)identifier { + ORKResult *result = [self resultForIdentifier:identifier]; + if (result != nil) { + NSUInteger idx = [self.results indexOfObject:result]; + if (idx != NSNotFound) { + self.results = [self.results subarrayWithRange:NSMakeRange(0, idx)]; + } + } +} + +- (NSArray *)flattenResults { + NSMutableArray *results = [NSMutableArray new]; + for (ORKResult *result in self.results) { + if ([result isKindOfClass:[ORKStepResult class]]) { + ORKStepResult *stepResult = (ORKStepResult *)result; + if (stepResult.results.count > 0) { + // For each subresult in this step, append the step identifier onto the result + for (ORKResult *currentResult in stepResult.results) { + ORKResult *copy = [currentResult copy]; + NSString *subIdentifier = currentResult.identifier ?: [NSString stringWithFormat:@"%@", @(currentResult.hash)]; + copy.identifier = [NSString stringWithFormat:@"%@.%@", stepResult.identifier, subIdentifier]; + [results addObject:copy]; + } + } else { + // If this is an empty step result then add a base class instance with this identifier + [results addObject:[[ORKResult alloc] initWithIdentifier:stepResult.identifier]]; + } + } else { + // If this is *not* a step result then just add it as-is + [results addObject:result]; + } + } + return [results copy]; +} + +- (instancetype)copyWithOutputDirectory:(NSURL *)outputDirectory { + typeof(self) copy = [[[self class] alloc] initWithTaskIdentifier:self.identifier taskRunUUID:self.taskRunUUID outputDirectory:outputDirectory]; + copy.results = self.results; + return copy; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult_Private.h new file mode 100755 index 0000000..0ee0f29 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollectionResult_Private.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPageStep; + +/** + The `ORKPageResult` is an `ORKTaskResult` subclass of a collection of `ORKStepResult` + objects. This is considered private, and it is used internally by `ORKPageStepViewController` + to track the result set. + */ +ORK_CLASS_AVAILABLE +@interface ORKPageResult : ORKTaskResult + +- (instancetype)initWithPageStep:(ORKPageStep *)step stepResult:(ORKStepResult*)result; + +- (void)addStepResult:(nullable ORKStepResult *)stepResult; + +- (void)removeStepResultWithIdentifier:(NSString *)identifier; + +- (void)removeStepResultsAfterStepWithIdentifier:(NSString *)identifier; + +- (NSArray *)flattenResults; + +- (instancetype)copyWithOutputDirectory:(NSURL *)outputDirectory; + +@end + + +@interface ORKStepResult () + +@property (nonatomic) BOOL isPreviousResult; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.h new file mode 100755 index 0000000..254b465 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.h @@ -0,0 +1,173 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKCollector; +@class ORKHealthCollector; +@class ORKMotionActivityCollector; + + +/** + Abstract class of data collector. + */ +ORK_CLASS_AVAILABLE +@interface ORKCollector : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + Identifier of this collector. + */ +@property (copy, readonly) NSString *identifier; + +/** + Serialization helper that produces serialized output. + Subclasses should implement to provide a default serialization for upload. + + @params objects The objects to be serialized. + + @return Serialized data object. + */ +- (NSData *)serializedDataForObjects:(NSArray *)objects; + +/** + Serialization helper that produces objects suitable for serialization to JSON. + + Subclasses should implement to provide a default JSON serialization for upload. + Called by `serializedDataForObjects:`. + + @params objects The objects to be serialized. + + @return Serializable dictionary objects. + */ +- (NSArray *)serializableObjectsForObjects:(NSArray *)objects; + +@end + + +/** + ORKHealthCollector collects HKSample. + + It cannot be initiated directly. + Use `addHealthCollectorWithSampleType:`to add one to a `ORKDataCollectionManager`. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthCollector : ORKCollector + +/** + HealthKit sample type. + */ +@property (copy, readonly) HKSampleType *sampleType; + +/** + HealthKit unit into which data should be collected. + */ +@property (copy, readonly) HKUnit *unit; + +/** + Samples should be collected starting at this date. + */ +@property (copy, readonly) NSDate *startDate; + +/** + Last anchor already seen. + */ +@property (copy, readonly) HKQueryAnchor *lastAnchor; + +@end + + +/** + ORKHealthCollector collects HKCorrelation. + + It cannot be initiated directly. + Use `addHealthCorrelationCollectorWithCorrelationType:`to add one to a `ORKDataCollectionManager`. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthCorrelationCollector : ORKCollector + +/** + HealthKit correlation type. + */ +@property (copy, readonly) HKCorrelationType *correlationType; + +/** + Array of HKSampleType expected in the correlation. + */ +@property (copy, readonly) NSArray *sampleTypes; + +/** + Array of HKUnit to use when serializing the samples collected (should be same size as sampleTypes). + */ +@property (copy, readonly) NSArray *units; + +/** + Samples should be collected starting at this date. + */ +@property (copy, readonly) NSDate *startDate; + +/** + Last anchor already seen. + */ +@property (copy, readonly) HKQueryAnchor *lastAnchor; + +@end + + +/** + ORKHealthCollector collects CMMotionActivity. + + It cannot be initiated directly. + Use `addMotionActivityCollectorWithStartDate:`to add one to a `ORKDataCollectionManager`. + */ +ORK_CLASS_AVAILABLE +@interface ORKMotionActivityCollector : ORKCollector + +/** + Samples should be collected starting at this date. + */ +@property (copy, readonly) NSDate *startDate; + +/** + Last anchor already seen. + */ +@property (copy, readonly) NSDate *lastDate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.m new file mode 100755 index 0000000..5254584 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector.m @@ -0,0 +1,360 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCollector.h" +#import "ORKCollector_Internal.h" +#import "ORKHelpers_Internal.h" +#import "HKSample+ORKJSONDictionary.h" +#import "CMMotionActivity+ORKJSONDictionary.h" +#import "ORKHealthSampleQueryOperation.h" +#import "ORKMotionActivityQueryOperation.h" +#import + + +static NSString *const ItemsKey = @"items"; +static NSString *const ItemIdentifierFormat = @"org.researchkit.%@"; +static NSString *const ItemIdentifierFormatWithTwoPlaceholders = @"org.researchkit.%@.%@"; + +@implementation ORKCollector + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + _identifier = identifier; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + ORKCollector *collector = [[[self class] allocWithZone:zone] initWithIdentifier:_identifier]; + return collector; +} + +- (NSData *)serializedDataForObjects:(NSArray *)objects { + + NSDictionary *output = @{ ItemsKey : [self serializableObjectsForObjects:objects] }; + + NSError *localError; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:output + options:NSJSONWritingPrettyPrinted + error:&localError]; + if (!jsonData) { + [NSException raise:NSInternalInconsistencyException format:@"Error serializing objects to JSON: %@", [localError localizedDescription]]; + return nil; + } + + return jsonData; +} + +- (ORKOperation *)collectionOperationWithManager:(ORKDataCollectionManager *)mananger { + ORKThrowMethodUnavailableException(); + return nil; +} + +- (NSArray *)serializableObjectsForObjects:(NSArray *)objects { + ORKThrowMethodUnavailableException(); + return nil; +} + +- (BOOL)isEqual:(id)object { + BOOL classEqual = [self class] == [object class]; + + __typeof(self) castObject = object; + return (classEqual && + ORKEqualObjects(_identifier, castObject.identifier)); +} + +@end + + +@implementation ORKHealthCollector : ORKCollector + +- (instancetype)initWithSampleType:(HKSampleType*)sampleType unit:(HKUnit*)unit startDate:(NSDate*)startDate { + NSString *itemIdentifier = [NSString stringWithFormat:ItemIdentifierFormatWithTwoPlaceholders, sampleType.identifier, unit.unitString]; + self = [super initWithIdentifier:itemIdentifier]; + if (self) { + _sampleType = sampleType; + _unit = unit; + _startDate = startDate; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, sampleType); + ORK_DECODE_OBJ(aDecoder, unit); + ORK_DECODE_OBJ(aDecoder, startDate); + ORK_DECODE_OBJ(aDecoder, lastAnchor); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + ORK_ENCODE_OBJ(aCoder, sampleType); + ORK_ENCODE_OBJ(aCoder, unit); + ORK_ENCODE_OBJ(aCoder, startDate); + ORK_ENCODE_OBJ(aCoder, lastAnchor); +} + +- (NSArray *)serializableObjectsForObjects:(NSArray *)objects { + NSMutableArray *elements = [NSMutableArray arrayWithCapacity:[objects count]]; + for (HKSample *sample in objects) { + [elements addObject:[sample ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) unit:self.unit]]; + } + + return elements; +} + +- (ORKOperation*)collectionOperationWithManager:(ORKDataCollectionManager*)mananger { + if (! [HKHealthStore isHealthDataAvailable]) { + return nil; + } + + return [[ORKHealthSampleQueryOperation alloc] initWithCollector:self mananger:mananger]; +} + +- (NSArray *)collectableSampleTypes { + return @[_sampleType]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKHealthCollector *collector = [super copyWithZone:zone]; + collector->_startDate = self.startDate; + collector->_sampleType = self.sampleType; + collector->_unit = [self.unit copy]; + collector->_lastAnchor = self.lastAnchor; + + return collector; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(_sampleType, castObject.sampleType) && + ORKEqualObjects(_unit, castObject.unit) && + ORKEqualObjects(_startDate, castObject.startDate) && + ORKEqualObjects(_lastAnchor, castObject.lastAnchor)); +} + +@end + + +@implementation ORKHealthCorrelationCollector : ORKCollector + +- (instancetype)initWithCorrelationType:(HKCorrelationType *)correlationType + sampleTypes:(NSArray *)sampleTypes + units:(NSArray *)units + startDate:(NSDate *)startDate { + NSString *itemIdentifier = [NSString stringWithFormat:ItemIdentifierFormat, correlationType.identifier]; + self = [super initWithIdentifier:itemIdentifier]; + if (self) { + _correlationType = correlationType; + _sampleTypes = sampleTypes; + _units = units; + _startDate = startDate; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, correlationType); + ORK_DECODE_OBJ_ARRAY(aDecoder, sampleTypes, HKSampleType); + ORK_DECODE_OBJ_ARRAY(aDecoder, units, HKUnit); + ORK_DECODE_OBJ(aDecoder, startDate); + ORK_DECODE_OBJ(aDecoder, lastAnchor); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + ORK_ENCODE_OBJ(aCoder, correlationType); + ORK_ENCODE_OBJ(aCoder, sampleTypes); + ORK_ENCODE_OBJ(aCoder, units); + ORK_ENCODE_OBJ(aCoder, startDate); + ORK_ENCODE_OBJ(aCoder, lastAnchor); +} + +- (HKSampleType *)sampleType { + return _correlationType; +} + + +- (NSArray *)collectableSampleTypes { + return self.sampleTypes; +} + + +- (NSArray *)serializableObjectsForObjects:(NSArray *)objects { + NSMutableArray *elements = [NSMutableArray arrayWithCapacity:[objects count]]; + for (HKCorrelation *correlation in objects) { + [elements addObject:[correlation ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) sampleTypes:self.sampleTypes units:self.units]]; + } + + return elements; +} + +- (ORKOperation *)collectionOperationWithManager:(ORKDataCollectionManager *)manager { + if (! [HKHealthStore isHealthDataAvailable]) { + return nil; + } + + return [[ORKHealthSampleQueryOperation alloc] initWithCollector:self mananger:manager]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKHealthCorrelationCollector *collector = [super copyWithZone:zone]; + collector->_startDate = self.startDate; + collector->_correlationType = self.correlationType; + collector->_sampleTypes = [self.sampleTypes copy]; + collector->_units = [self.units copy]; + collector->_lastAnchor = self.lastAnchor; + + return collector; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(_correlationType, castObject.correlationType) && + ORKEqualObjects(_sampleTypes, castObject.sampleTypes) && + ORKEqualObjects(_units, castObject.units) && + ORKEqualObjects(_startDate, castObject.startDate) && + ORKEqualObjects(_lastAnchor, castObject.lastAnchor)); +} + +@end + + +@implementation ORKMotionActivityCollector : ORKCollector + +- (instancetype)initWithStartDate:(NSDate *)startDate { + NSString *itemIdentifier = [NSString stringWithFormat:ItemIdentifierFormat, @"activity"]; + self = [super initWithIdentifier:itemIdentifier]; + if (self) { + _startDate = startDate; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, startDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, lastDate, NSDate); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, startDate); + ORK_ENCODE_OBJ(aCoder, lastDate); +} + +- (NSArray *)serializableObjectsForObjects:(NSArray *)objects { + // Expect an array of CMMotionActivity objects + NSMutableArray *elements = [NSMutableArray arrayWithCapacity:[objects count]]; + for (CMMotionActivity *activity in objects) { + [elements addObject:[activity ork_JSONDictionary]]; + } + + return elements; +} + +- (ORKOperation *)collectionOperationWithManager:(ORKDataCollectionManager *)mananger { + if (! [CMMotionActivityManager isActivityAvailable]) { + return nil; + } + + return [[ORKMotionActivityQueryOperation alloc] initWithCollector:self queryQueue:nil manager:mananger]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKMotionActivityCollector *collector = [super copyWithZone:zone]; + collector->_startDate = self.startDate; + collector->_lastDate = self.lastDate; + + return collector; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(_startDate, castObject.startDate) && + ORKEqualObjects(_lastDate, castObject.lastDate)); +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector_Internal.h new file mode 100755 index 0000000..4007936 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCollector_Internal.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCollector.h" +#import "ORKDataCollectionManager_Internal.h" + + +@class ORKOperation; + +@interface ORKCollector () + +- (instancetype)initWithIdentifier:(NSString *)identifier; + +- (ORKOperation *)collectionOperationWithManager:(ORKDataCollectionManager *)mananger; + +@end + + +@protocol ORKHealthCollectable + +- (HKSampleType *)sampleType; +- (NSArray *)collectableSampleTypes; +- (NSDate *)startDate; +- (HKQueryAnchor *)lastAnchor; +- (void)setLastAnchor:(HKQueryAnchor *)lastAnchor; + +@end + + +@interface ORKHealthCollector() + +- (instancetype)initWithSampleType:(HKSampleType *)objectType unit:(HKUnit *)unit startDate:(NSDate *)startDate; + +@property (copy) HKQueryAnchor *lastAnchor; + +@end + + +@interface ORKHealthCorrelationCollector() + +- (instancetype)initWithCorrelationType:(HKCorrelationType *)objectType sampleTypes:(NSArray *)sampleTypes units:(NSArray *)units startDate:(NSDate *)startDate; + +@property (copy) HKQueryAnchor *lastAnchor; + +@end + + +@interface ORKMotionActivityCollector() + +- (instancetype)initWithStartDate:(NSDate *)startDate; + +@property (copy) NSDate *lastDate; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.h new file mode 100755 index 0000000..3c8a746 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKCompletionCheckmarkView : UIView ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithDimension:(CGFloat)dimension; +- (instancetype)initWithDefaultDimension; + +@property (nonatomic) CGFloat animationPoint; + +- (void)setAnimationPoint:(CGFloat)animationPoint animated:(BOOL)animated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.m new file mode 100755 index 0000000..7bab6a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionCheckmarkView.m @@ -0,0 +1,135 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCompletionCheckmarkView.h" +#import "ORKSkin.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKCompletionCheckmarkView { + CAShapeLayer *_shapeLayer; + CGFloat tickViewSize; + +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithDimension:(CGFloat)dimension { + self = [super init]; + if (self) { + tickViewSize = dimension; + self.layer.cornerRadius = tickViewSize / 2; + [self tintColorDidChange]; + + UIBezierPath *path = [UIBezierPath new]; + [path moveToPoint:(CGPoint){0.27*tickViewSize, 0.52*tickViewSize}]; + [path addLineToPoint:(CGPoint){0.42*tickViewSize, 0.68*tickViewSize}]; + [path addLineToPoint:(CGPoint){0.68*tickViewSize, 0.32*tickViewSize}]; + path.lineCapStyle = kCGLineCapRound; + + CAShapeLayer *shapeLayer = [CAShapeLayer new]; + shapeLayer.path = path.CGPath; + shapeLayer.lineWidth = 0.10*tickViewSize; + shapeLayer.lineCap = kCALineCapRound; + shapeLayer.lineJoin = kCALineJoinRound; + shapeLayer.frame = self.layer.bounds; + shapeLayer.strokeColor = [UIColor whiteColor].CGColor; + shapeLayer.backgroundColor = [UIColor clearColor].CGColor; + shapeLayer.fillColor = nil; + [self.layer addSublayer:shapeLayer]; + _shapeLayer = shapeLayer; + + self.translatesAutoresizingMaskIntoConstraints = NO; + } + return self; +} + +- (instancetype)initWithDefaultDimension { + return [self initWithDimension:ORKStepContentIconImageViewDimension]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _shapeLayer.frame = self.layer.bounds; +} + +- (CGSize)intrinsicContentSize { + return (CGSize){tickViewSize, tickViewSize}; +} + +- (CGSize)sizeThatFits:(CGSize)size { + return [self intrinsicContentSize]; +} + +- (void)tintColorDidChange { + self.backgroundColor = [self tintColor]; +} + +- (void)setAnimationPoint:(CGFloat)animationPoint { + _shapeLayer.strokeEnd = animationPoint; + _animationPoint = animationPoint; +} + +- (void)setAnimationPoint:(CGFloat)animationPoint animated:(BOOL)animated { + CAMediaTimingFunction *timing = [[CAMediaTimingFunction alloc] initWithControlPoints:0.180739998817444 :0 :0.577960014343262 :0.918200016021729]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; + [animation setTimingFunction:timing]; + [animation setFillMode:kCAFillModeBoth]; + animation.fromValue = @([(CAShapeLayer *)[_shapeLayer presentationLayer] strokeEnd]); + animation.toValue = @(animationPoint); + + animation.duration = 0.3; + _animationPoint = animationPoint; + + _shapeLayer.strokeEnd = animationPoint; + [_shapeLayer addAnimation:animation forKey:@"strokeEnd"]; + +} + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitImage; +} + +- (NSString *)accessibilityLabel { + return ORKLocalizedString(@"AX_COMPLETION_ILLUSTRATION", nil); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.h new file mode 100755 index 0000000..3830f7c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKCompletionStep` class is a subclass of `ORKInstructionStep` which behaves like + an instruction step, but includes animated imagery that thanks the user + for participating in the task. + */ +ORK_CLASS_AVAILABLE +@interface ORKCompletionStep : ORKInstructionStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.m new file mode 100755 index 0000000..3349338 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStep.m @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCompletionStep.h" + +#import "ORKCompletionStepViewController.h" + + +@implementation ORKCompletionStep + ++ (Class)stepViewControllerClass { + return [ORKCompletionStepViewController class]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.h new file mode 100755 index 0000000..9b5fa99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An `ORKCompletionStepViewController` object is the step view controller for an +`ORKCompletionStep` object. + + Typically, you don't need to instantiate a completion step view controller directly. + Instead, add a completion step to a task, and present the task with a + task view controller. The task view controller instantiates the step + view controller for the completion step. + */ +ORK_CLASS_AVAILABLE +@interface ORKCompletionStepViewController : ORKInstructionStepViewController + +// FIXME:Deprecate this property +/** + Optional property to allow showing the "Done/Next" button rather than moving this button + to the `rightBarButtonItem`. + */ +@property (nonatomic) BOOL shouldShowContinueButton; + +/** + Optional property to set the color of the checkmark. This allows the checkmark to use a different + color from the tintColor of the parent view. + */ +@property (nonatomic, copy, nullable) UIColor *checkmarkColor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.m new file mode 100755 index 0000000..5b3d7f8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCompletionStepViewController.m @@ -0,0 +1,84 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCompletionStepViewController.h" + +#import "ORKCustomStepView_Internal.h" +#import "ORKInstructionStepContainerView.h" +#import "ORKInstructionStepView.h" +#import "ORKNavigationContainerView.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKStepView_Private.h" +#import "ORKStepContainerView_Private.h" +#import "ORKStepContentView_Private.h" + +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKCompletionCheckmarkView.h" +#import "ORKSkin.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKCompletionStepViewController { + ORKCompletionCheckmarkView *_completionCheckmarkView; +} + +- (void)stepDidChange { + [super stepDidChange]; + + self.cancelButtonItem = nil; + _completionCheckmarkView = [self.stepView.stepContentView completionCheckmarkView]; + [_completionCheckmarkView setNeedsLayout]; + if (self.checkmarkColor) { + _completionCheckmarkView.tintColor = self.checkmarkColor; + } + self.stepView.customContentFillsAvailableSpace = YES; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + _completionCheckmarkView.animationPoint = animated ? 0 : 1; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + if (animated) { + [_completionCheckmarkView setAnimationPoint:1 animated:YES]; + } +} + +- (void)setCheckmarkColor:(UIColor *)checkmarkColor { + _checkmarkColor = [checkmarkColor copy]; + _completionCheckmarkView.tintColor = checkmarkColor; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.h new file mode 100755 index 0000000..bcb2667 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKContinueButton : ORKBorderedButton + +- (instancetype)initWithTitle:(NSString *)title isDoneButton:(BOOL)isDoneButton; + +@property (nonatomic) BOOL isDoneButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.m new file mode 100755 index 0000000..3464013 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKContinueButton.m @@ -0,0 +1,77 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKContinueButton.h" + +#import "ORKSkin.h" + + +static const CGFloat ContinueButtonTouchMargin = 10; +static const CGFloat ContinueButtonHeight = 50.0; + +@implementation ORKContinueButton { + NSLayoutConstraint *_heightConstraint; +} + +- (instancetype)initWithTitle:(NSString *)title isDoneButton:(BOOL)isDoneButton { + self = [super init]; + if (self) { + [self setTitle:title forState:UIControlStateNormal]; + self.isDoneButton = isDoneButton; + self.contentEdgeInsets = (UIEdgeInsets){.left = 6, .right = 6}; + + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + _heightConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ContinueButtonHeight]; + _heightConstraint.active = YES; +} + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { + CGRect outsetRect = UIEdgeInsetsInsetRect(self.bounds, + (UIEdgeInsets){-ContinueButtonTouchMargin, + -ContinueButtonTouchMargin, + -ContinueButtonTouchMargin, + -ContinueButtonTouchMargin}); + BOOL isInside = [super pointInside:point withEvent:event] || CGRectContainsPoint(outsetRect, point); + return isInside; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.h new file mode 100755 index 0000000..174f767 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Coundown label in active steps + */ +ORK_CLASS_AVAILABLE +@interface ORKCountdownLabel : ORKLabel + +@end + + +@interface ORKCountdownLabel () + +- (void)setCountDownValue:(NSInteger)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.m new file mode 100755 index 0000000..b776074 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCountdownLabel.m @@ -0,0 +1,86 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCountdownLabel.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKCountdownLabel { + NSInteger _currentCountDownValue; +} + ++ (UIFont *)defaultFont { + return [UIFont systemFontOfSize:65.f weight:UIFontWeightUltraLight]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _currentCountDownValue = 0; + } + return self; +} + +- (void)updateAppearance { + [self setCountDownValue:_currentCountDownValue]; +} + +- (void)setCountDownValue:(NSInteger)value { + _currentCountDownValue = value; + [self renderText]; +} + +- (void)renderText { + static dispatch_once_t onceToken; + static NSDateComponentsFormatter *durationFormatter = nil; + dispatch_once(&onceToken, ^{ + durationFormatter = [NSDateComponentsFormatter new]; + [durationFormatter setUnitsStyle:NSDateComponentsFormatterUnitsStylePositional]; + durationFormatter.allowedUnits = NSCalendarUnitMinute|NSCalendarUnitSecond; + durationFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad; + }); + + [self setText:[durationFormatter stringFromTimeInterval:_currentCountDownValue]]; + [self invalidateIntrinsicContentSize]; +} + +- (void)setFont:(UIFont *)font { + [super setFont:font]; + [self renderText]; +} + +- (CGSize)intrinsicContentSize { + CGSize intrinsic = [super intrinsicContentSize]; + return (CGSize){.width=intrinsic.width, self.frame.size.height == 0.0 ? ORKExpectedLabelHeight(self) : self.frame.size.height}; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.h new file mode 100755 index 0000000..60549b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKCustomStep : ORKStep + ++ (instancetype)customStepWithIdentifier:(NSString *)identifier + contentView:(UIView *)contentView; + +@property (nonatomic, strong, nullable) UIView *contentView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.m new file mode 100755 index 0000000..1cbdf9b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStep.m @@ -0,0 +1,42 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCustomStep.h" + +@implementation ORKCustomStep + ++ (instancetype)customStepWithIdentifier:(NSString *)identifier + contentView:(UIView *)contentView { + ORKCustomStep *step = [[ORKCustomStep alloc] initWithIdentifier:identifier]; + step.contentView = contentView; + return step; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.h new file mode 100755 index 0000000..b666f3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.h @@ -0,0 +1,91 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKQuestionStepCustomView; +@class ORKLearnMoreView; + +/** + The `ORKQuestionStepCustomViewDelegate` protocol defines the methods that a question step custom view should implement. + + Typically, a question step view controller (`ORKQuestionStepViewController`) is the delegate of a + custom question step view. + */ +@protocol ORKQuestionStepCustomViewDelegate + +- (void)customQuestionStepView:(ORKQuestionStepCustomView *)customQuestionStepView didChangeAnswer:(nullable id)answer; + +@end + +/** + The `ORKQuestionStepCustomView` class is a base class for views that are used to + display question steps (`ORKQuestionStep` objects) in a question step view controller + (an `ORKQuestionStepViewController` object). + + Typically, you subclass `ORKQuestionStepCustomView` only when you need to implement a new + answer format for the survey engine. + + To ensure that your subclass is allocated the display space it requires, you should implement + `sizeThatFits:`, or include internal constraints, or report an intrinsic content size. + */ +ORK_CLASS_AVAILABLE +@interface ORKQuestionStepCustomView : UIView + +/** The delegate of the question step custom view. + + A question step custom view should report changes in its `result` property. + +*/ +@property (nonatomic, weak, nullable) id delegate; + +/// The answer to the question, which should be represented as a JSON-serializable atomic type. +@property (nonatomic, copy, nullable) id answer; + +@end + + +@class ORKSurveyAnswerCell; + +ORK_CLASS_AVAILABLE +@interface ORKQuestionStepCellHolderView : ORKQuestionStepCustomView + +@property (nonatomic, strong, nullable) ORKSurveyAnswerCell *cell; + +- (void)useCardViewWithTitle:(NSString *)title detailText:(nullable NSString *)detailText learnMoreView:(nullable ORKLearnMoreView *)learnMoreView progressText:(nullable NSString *)progressText tagText:(nullable NSString *)tagText hasMultipleChoiceFormItem:(BOOL)hasMultipleChoiceFormItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.m new file mode 100755 index 0000000..7d13cf4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView.m @@ -0,0 +1,338 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCustomStepView.h" +#import "ORKCustomStepView_Internal.h" + +#import "ORKSurveyAnswerCell.h" +#import "ORKSurveyCardHeaderView.h" + +#import "ORKStepViewController.h" + +#import "ORKSkin.h" + + +@implementation ORKActiveStepCustomView + +- (void)resetStep:(ORKStepViewController *)viewController { +} + +- (void)startStep:(ORKStepViewController *)viewController { +} + +- (void)suspendStep:(ORKStepViewController *)viewController { +} + +- (void)resumeStep:(ORKStepViewController *)viewController { +} + +- (void)finishStep:(ORKStepViewController *)viewController { +} + +- (void)updateDisplay:(ORKActiveStepViewController *)viewController { +} + +@end + + +@implementation ORKQuestionStepCustomView + +@end + + +@implementation ORKQuestionStepCellHolderView { + CGFloat _leftRightMargin; + CAShapeLayer *_contentMaskLayer; + + ORKSurveyCardHeaderView * _cardHeaderView; + UIView *_containerView; + BOOL _useCardView; + NSArray *_containerConstraints; + NSString *_title; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.translatesAutoresizingMaskIntoConstraints = NO; + UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction)]; + [self addGestureRecognizer:recognizer]; + _leftRightMargin = 0.0; + [self setupContainerView]; + [self setBackgroundColor:[UIColor clearColor]]; + [self setupConstraints]; + } + return self; +} + +- (void)setupContainerView { + if (!_containerView) { + _containerView = [UIView new]; + } + _containerView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_containerView]; +} + +- (void)setupHeaderViewWithTitle:(NSString *)title detailText:(nullable NSString *)detailText learnMoreView:(nullable ORKLearnMoreView *)learnMoreView progressText:(nullable NSString *)progressText hasMultipleChoiceFormItem:(BOOL)hasMultipleChoiceFormItem { + if (!_cardHeaderView) { + _cardHeaderView = [[ORKSurveyCardHeaderView alloc]initWithTitle:title detailText:detailText learnMoreView:learnMoreView progressText:progressText tagText:nil showBorder:NO hasMultipleChoiceItem:hasMultipleChoiceFormItem]; + } + _cardHeaderView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_cardHeaderView]; + if (!title) { + [_cardHeaderView removeFromSuperview]; + _cardHeaderView = nil; + } +} + +- (void)tapAction { + [_cell becomeFirstResponder]; +} + +- (void)setCell:(ORKSurveyAnswerCell *)cell { + // Removing old cell from superview automatically removes its constraints + [_cell removeFromSuperview]; + _cell = cell; + + _cell.translatesAutoresizingMaskIntoConstraints = NO; + + if ([[_cell class] shouldDisplayWithSeparators]) { + _cell.showTopSeparator = YES; + _cell.showBottomSeparator = YES; + } + + [_containerView addSubview:_cell]; + [self setUpCellConstraints]; +} + +- (void)useCardViewWithTitle:(NSString *)title detailText:(NSString *)detailText learnMoreView:(ORKLearnMoreView *)learnMoreView progressText:(NSString *)progressText tagText:(NSString *)tagText hasMultipleChoiceFormItem:(BOOL)hasMultipleChoiceFormItem { + _title = title; + _useCardView = YES; + _leftRightMargin = 0.0; + [self setBackgroundColor:[UIColor clearColor]]; + [self setupHeaderViewWithTitle:title detailText:detailText learnMoreView:learnMoreView progressText:progressText hasMultipleChoiceFormItem:hasMultipleChoiceFormItem]; + [self setupConstraints]; +} + +- (void)setupConstraints { + + if (_containerConstraints) { + [NSLayoutConstraint deactivateConstraints:_containerConstraints]; + } + NSArray *topViewConstraints; + + if (_cardHeaderView) { + topViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:_cardHeaderView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_cardHeaderView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_cardHeaderView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_cardHeaderView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + } + else { + topViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0] + ]; + } + + _containerConstraints = [topViewConstraints arrayByAddingObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:ORKCardLeftRightMarginForWindow(self.window)], //Adding Padding to match surveyCardHeader in Question Step. + [NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-ORKCardLeftRightMarginForWindow(self.window)] //Adding Padding to match surveyCardHeader in Question Step. + ]]; + + [NSLayoutConstraint activateConstraints:_containerConstraints]; +} + +- (void)setUpCellConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_cell + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeTopMargin + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_cell + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottomMargin + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_cell + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_cell + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_containerView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_containerView + attribute:NSLayoutAttributeBottomMargin + relatedBy:NSLayoutRelationEqual + toItem:_cell + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + self.layoutMargins = ORKStandardFullScreenLayoutMarginsForView(self); +} + +-(void) drawRect:(CGRect)rect { + [super drawRect:rect]; + [self setMaskLayers]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self setMaskLayers]; +} + +- (void)setMaskLayers { + if (_useCardView) { + if (_contentMaskLayer) { + for (CALayer *sublayer in [_contentMaskLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + [_contentMaskLayer removeFromSuperlayer]; + _contentMaskLayer = nil; + } + _contentMaskLayer = [[CAShapeLayer alloc] init]; + + UIColor *fillColor; + if (@available(iOS 13.0, *)) { + fillColor = UIColor.secondarySystemGroupedBackgroundColor; + } else { + fillColor = [UIColor ork_borderGrayColor]; + } + [_contentMaskLayer setFillColor:[fillColor CGColor]]; + + CAShapeLayer *foreLayer = [CAShapeLayer layer]; + if (@available(iOS 13.0, *)) { + [foreLayer setFillColor:[[UIColor secondarySystemGroupedBackgroundColor] CGColor]]; + } else { + [foreLayer setFillColor:[[UIColor whiteColor] CGColor]]; + } + foreLayer.zPosition = 0.0f; + + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + + NSUInteger rectCorners = _title ? UIRectCornerBottomLeft | UIRectCornerBottomRight : UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerTopRight | UIRectCornerTopLeft; + + _contentMaskLayer.path = [UIBezierPath bezierPathWithRoundedRect: _containerView.bounds + byRoundingCorners: rectCorners + cornerRadii: (CGSize){ORKCardDefaultCornerRadii, ORKCardDefaultCornerRadii}].CGPath; + + CGRect foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, _containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, _containerView.bounds.size.height - ORKCardDefaultBorderWidth); + + CGFloat foreLayerCornerRadii = ORKCardDefaultCornerRadii >= ORKCardDefaultBorderWidth ? ORKCardDefaultCornerRadii - ORKCardDefaultBorderWidth : ORKCardDefaultCornerRadii; + + foreLayer.path = [UIBezierPath bezierPathWithRoundedRect: foreLayerBounds byRoundingCorners: rectCorners cornerRadii: (CGSize){foreLayerCornerRadii, foreLayerCornerRadii}].CGPath; + + + + [_contentMaskLayer addSublayer:foreLayer]; + [_contentMaskLayer addSublayer:lineLayer]; + if (@available(iOS 13.0, *)) { + _contentMaskLayer.fillColor = UIColor.separatorColor.CGColor; + } else { + _contentMaskLayer.fillColor = [UIColor ork_midGrayTintColor].CGColor; + } + [_containerView.layer insertSublayer:_contentMaskLayer atIndex:0]; + } +} + +- (NSArray *)accessibilityElements +{ + // Needed to support the "Edit Transcript" view for speech recognition pages + // This works around an issue with navigating table view cells outside of a table view using VoiceOver + return self.cell.accessibilityElements; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.h new file mode 100755 index 0000000..6a1cdb6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKStepViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKCustomStepViewController : ORKStepViewController + +- (BOOL)continueButtonEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.m new file mode 100755 index 0000000..421a7a9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepViewController.m @@ -0,0 +1,237 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCustomStepViewController.h" +#import "ORKStepViewController_Internal.h" +#import "ORKCustomStep.h" +#import "ORKNavigationContainerView_Internal.h" + +@interface ORKCustomStepViewController () + +@end + +@implementation ORKCustomStepViewController { + UIScrollView *_scrollView; + UIView *_contentView; + NSMutableArray *_constraints; +} + +- (ORKCustomStep *)customStep { + return (ORKCustomStep *)self.step; +} + +- (void)stepDidChange { + + [_scrollView removeFromSuperview]; + _scrollView = nil; + + [_contentView removeFromSuperview]; + _contentView = nil; + + if (self.step && [self isViewLoaded]) { + + _scrollView = [[UIScrollView alloc] init]; + _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + [self.view addSubview:_scrollView]; + + _contentView = [[UIView alloc] init]; + [_scrollView addSubview:_contentView]; + + [_contentView addSubview:[self customStep].contentView]; + + [self setupNavigationFooterView]; + [self setupConstraints]; + } +} + +- (void)setupConstraints { + + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + + UIView *viewForiPad = [self viewForiPadLayoutConstraints]; + + _constraints = nil; + [self customStep].contentView.translatesAutoresizingMaskIntoConstraints = NO; + _contentView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + _scrollView.translatesAutoresizingMaskIntoConstraints = NO; + + _constraints = [[NSMutableArray alloc] initWithArray:@[ + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_contentView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_contentView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_contentView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:[self customStep].contentView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_contentView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:[self customStep].contentView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_contentView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:[self customStep].contentView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_contentView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:[self customStep].contentView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_contentView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_contentView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + + ]]; + + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; +} + +- (void)setupNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = [ORKNavigationContainerView new]; + [_navigationFooterView removeStyling]; + } + + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.skipButtonItem = [self skipButtonItem]; + [_navigationFooterView updateContinueAndSkipEnabled]; + [_navigationFooterView setUseExtendedPadding:[self.step useExtendedPadding]]; + + [_scrollView addSubview:_navigationFooterView]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; + [self updateButtonStates]; +} + +- (BOOL)continueButtonEnabled { + return YES; +} + +- (void)updateButtonStates { + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView_Internal.h new file mode 100755 index 0000000..9234d84 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKCustomStepView_Internal.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKCustomStepView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKActiveStepViewController; + +@interface ORKActiveStepCustomView : UIView + +@property (nonatomic, weak, nullable) ORKActiveStepViewController *activeStepViewController; + +- (void)resetStep:(ORKActiveStepViewController *)viewController; +- (void)startStep:(ORKActiveStepViewController *)viewController; +- (void)suspendStep:(ORKActiveStepViewController *)viewController; +- (void)resumeStep:(ORKActiveStepViewController *)viewController; +- (void)finishStep:(ORKActiveStepViewController *)viewController; + +- (void)updateDisplay:(ORKActiveStepViewController *)viewController; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.h new file mode 100755 index 0000000..c00ca3a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.h @@ -0,0 +1,200 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKCollector; +@class ORKHealthCollector; +@class ORKHealthCorrelationCollector; +@class ORKMotionActivityCollector; +@class ORKDataCollectionManager; + + +/** + The data collection manager delegate is responsible for delivering collected data objects, + and reporting errors during the operation. + */ +@protocol ORKDataCollectionManagerDelegate + +@optional +/** + Method for delivering the collected health data samples. + + @param collector The data collector. + @param samples Collected health data samples. + + @return Boolean indicating whether the samples has be accepted. + If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, + until the data is accepted. + */ +- (BOOL)healthCollector:(ORKHealthCollector *)collector didCollectSamples:(NSArray *)samples; + +/** + Method for delivering the collected health correlations. + + @param collector The data collector. + @param correlations Collected health correlation samples. + + @return Boolean indicating whether the samples has be accepted. + If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, + until the data is accepted. + */ +- (BOOL)healthCorrelationCollector:(ORKHealthCorrelationCollector *)collector didCollectCorrelations:(NSArray *)correlations; + +/** + Method for delivering the collected motion activities. + + @param collector The data collector. + @param motionActivities Collected motion activities. + + @return Boolean indicating whether the samples has be accepted. + If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, + until the data is accepted. + */ +- (BOOL)motionActivityCollector:(ORKMotionActivityCollector *)collector didCollectMotionActivities:(NSArray *)motionActivities; + +/** + Indicating the collection is completed for all the collectors. + + @param manager The data collection manager. + */ +- (void)dataCollectionManagerDidCompleteCollection:(ORKDataCollectionManager *)manager; + +/** + Method for reporting the deteted error during collection. + + @param collector The data collector. + @param error The error object. + */ +- (void)collector:(ORKCollector *)collector didDetectError:(NSError *)error; + +@end + +/** + The data collection manager is used to collect HealthKit data and CoreMotion data. + + It uses collectors to track data types to be collected. + Anchors are used to track progress of each types of data to avoid duplications. + Collected data samples are returned in the delegation methods, return YES to confirm the samples has been accepted. + */ +ORK_CLASS_AVAILABLE +@interface ORKDataCollectionManager : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + Initiate the manager with a persistence directory. + The directory is used to store the configurations and progress of the collectors. + + @param directoryURL URL path for the directory. + + @return Initiated ORKDataCollectionManager instance. + */ +- (instancetype)initWithPersistenceDirectoryURL:(NSURL *)directoryURL NS_DESIGNATED_INITIALIZER; + +/** + An array of collectors. + */ +@property (copy, readonly) NSArray *collectors; + +/** + Implement the delegate to receive collected data objects. + */ +@property (nonatomic, weak, nullable) id delegate; + +/** + Add a collector for HealthKit quantity and category samples. + + @param sampleType HealthKit sample type. + @param unit HealthKit unit into which data should be collected. + @param startDate Samples should be collected starting at this date. + @param error Any error detected during this operation. + + @return Initiated health collector. + */ +- (ORKHealthCollector *)addHealthCollectorWithSampleType:(HKSampleType *)sampleType + unit:(HKUnit *)unit + startDate:(NSDate *)startDate + error:(NSError * _Nullable *)error; + +/** + Add a collector for HealthKit correlations. + + @param correlationType HealthKit correlation type. + @param sampleTypes Array of HKSampleType expected in the correlation. + @param units Array of HKUnit to use when serializing the samples collected (should be same size as sampleTypes). + @param startDate Samples should be collected starting at this date. + @param error Any error detected during this operation. + + @return Initiated health correlation collector. + */ +- (ORKHealthCorrelationCollector *)addHealthCorrelationCollectorWithCorrelationType:(HKCorrelationType *)correlationType + sampleTypes:(NSArray *)sampleTypes + units:(NSArray *)units + startDate:(NSDate *)startDate + error:(NSError * _Nullable *)error; + +/** + Add a collector for motion activity. + + @param startDate When data collection should start. + @param error Error during this operation. + + @return Initiated motion activity collector. + */ +- (ORKMotionActivityCollector *)addMotionActivityCollectorWithStartDate:(NSDate *)startDate + error:(NSError * _Nullable *)error; + +/** + Remove a collector. + + @param collector The collector to be removed. + @param error Error during this operation. + + @return If this operation is successful. + */ +- (BOOL)removeCollector:(ORKCollector *)collector error:(NSError* _Nullable *)error; + +/** + Start data collection. + This method triggers running all the RKCollector collections associated with the present manager. + When the collection is completed, delegate recieves a method call `dataCollectionManagerDidCompleteCollection:`. + */ +- (void)startCollection; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.m new file mode 100755 index 0000000..28708fb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager.m @@ -0,0 +1,342 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDataCollectionManager_Internal.h" +#import "ORKCollector_Internal.h" +#import "ORKOperation.h" +#import "ORKHelpers_Internal.h" +#import + + +static NSString *const ORKDataCollectionPersistenceFileName = @".dataCollection.ork.data"; + +@implementation ORKDataCollectionManager { + dispatch_queue_t _queue; + NSOperationQueue *_operationQueue; + NSString * _Nonnull _managedDirectory; + NSArray *_collectors; + HKHealthStore *_healthStore; + CMMotionActivityManager *_activityManager; + NSMutableArray *_completionHandlers; +} + +- (instancetype)initWithPersistenceDirectoryURL:(NSURL *)directoryURL { + + self = [super init]; + if (self) { + if (directoryURL == nil) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"directory cannot be nil" userInfo:nil]; + } + + _managedDirectory = directoryURL.path; + + BOOL isDir; + NSFileManager *defaultManager = [NSFileManager defaultManager]; + BOOL directoryExist = [defaultManager fileExistsAtPath:_managedDirectory isDirectory:&isDir]; + + if ((directoryExist && isDir == NO)) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"URL is not a directory" userInfo:nil]; + } + + // Create directory if needed + if (NO == directoryExist) { + NSError *error; + [defaultManager createDirectoryAtPath:_managedDirectory withIntermediateDirectories:YES attributes:nil error:&error]; + + if (error) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Failed to create directory at URL." userInfo:@{@"error" : error}]; + } + } + + // Create persistance file if needed + if (![defaultManager fileExistsAtPath:self.persistFilePath]) { + _collectors = [NSArray new]; + [self persistCollectors]; + } + + NSString *queueId = [@"ResearchKit.DataCollection." stringByAppendingString:_managedDirectory]; + _queue = dispatch_queue_create([queueId cStringUsingEncoding:NSUTF8StringEncoding], DISPATCH_QUEUE_SERIAL); + _operationQueue = [[NSOperationQueue alloc] init]; + } + return self; +} + +#pragma mark Data collection + +// dispatch_sync, but tries not to deadlock if we're already on the specified queue +static inline void dispatch_sync_if_not_on_queue(dispatch_queue_t queue, dispatch_block_t block) { + dispatch_queue_set_specific(queue, (__bridge const void *)(queue), (void*)1, NULL); + if (dispatch_get_specific((__bridge const void *)queue)) { + block(); + } else { + dispatch_sync(queue, block); + } +} + +- (void)onWorkQueueSync:(BOOL (^)(ORKDataCollectionManager *manager))block { + dispatch_sync_if_not_on_queue(_queue, ^{ + if (block(self)) { + [self persistCollectors]; + } + }); +} + +- (void)onWorkQueueAsync:(BOOL (^)(ORKDataCollectionManager *manager))block { + dispatch_async(_queue, ^{ + if (block(self)) { + [self persistCollectors]; + } + }); +} + +- (HKHealthStore *)healthStore { + if (!_healthStore && [HKHealthStore isHealthDataAvailable]){ + _healthStore = [[HKHealthStore alloc] init]; + } + return _healthStore; +} + +- (CMMotionActivityManager *)activityManager { + if (!_activityManager && [CMMotionActivityManager isActivityAvailable]) { + _activityManager = [[CMMotionActivityManager alloc] init]; + } + return _activityManager; +} + +- (NSArray *)collectors { + if (_collectors == nil) { + _collectors = [NSKeyedUnarchiver unarchiveObjectWithFile:[self persistFilePath]]; + if (_collectors == nil) { + @throw [NSException exceptionWithName:NSGenericException reason: [NSString stringWithFormat:@"Failed to read from path %@", [self persistFilePath]] userInfo:nil]; + } + } + return _collectors; +} + +- (NSString * _Nonnull)persistFilePath { + return [_managedDirectory stringByAppendingPathComponent:ORKDataCollectionPersistenceFileName]; +} + +- (void)persistCollectors { + NSArray *collectors = self.collectors; + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:collectors]; + NSError *error; + [data writeToFile:[self persistFilePath] options:NSDataWritingAtomic|NSDataWritingFileProtectionComplete error:&error]; + + if (error) { + @throw [NSException exceptionWithName:NSGenericException reason: [NSString stringWithFormat:@"Failed to write to path %@", [self persistFilePath]] userInfo:nil]; + } +} + +- (void)addCollector:(ORKCollector *)collector { + NSMutableArray *collectors = [self.collectors mutableCopy]; + [collectors addObject:collector]; + _collectors = [collectors copy]; +} + +- (ORKHealthCollector *)addHealthCollectorWithSampleType:(HKSampleType*)sampleType unit:(HKUnit *)unit startDate:(NSDate *)startDate error:(NSError**)error { + + if (!sampleType) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"sampleType cannot be nil" userInfo:nil]; + } + if (!unit) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"unit cannot be nil" userInfo:nil]; + } + + __block ORKHealthCollector *healthCollector = nil; + + [self onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager){ + + ORKHealthCollector *collector = [[ORKHealthCollector alloc] initWithSampleType:sampleType unit:unit startDate:startDate]; + [self addCollector:collector]; + healthCollector = collector; + + return YES; + }]; + + return healthCollector; +} + +- (ORKHealthCorrelationCollector *)addHealthCorrelationCollectorWithCorrelationType:(HKCorrelationType *)correlationType + sampleTypes:(NSArray *)sampleTypes + units:(NSArray *)units + startDate:(NSDate *)startDate + error:(NSError * __autoreleasing *)error { + if (!correlationType) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"correlationType cannot be nil" userInfo:nil]; + } + if (![sampleTypes count]) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"sampleTypes cannot be empty" userInfo:nil]; + } + if ([units count] != [sampleTypes count]) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"units should be same length as sampleTypes" userInfo:nil]; + } + + __block ORKHealthCorrelationCollector *healthCorrelationCollector = nil; + [self onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager) { + + ORKHealthCorrelationCollector *collector = [[ORKHealthCorrelationCollector alloc] initWithCorrelationType:correlationType + sampleTypes:sampleTypes + units:units + startDate:startDate]; + [self addCollector:collector]; + healthCorrelationCollector = collector; + return YES; + }]; + + return healthCorrelationCollector; +} + +- (ORKMotionActivityCollector *)addMotionActivityCollectorWithStartDate:(NSDate *)startDate + error:(NSError* __autoreleasing *)error { + + __block ORKMotionActivityCollector *motionActivityCollector = nil; + + [self onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager) { + + ORKMotionActivityCollector *collector = [[ORKMotionActivityCollector alloc] initWithStartDate:startDate]; + [self addCollector:collector]; + motionActivityCollector = collector; + + return YES; + }]; + + return motionActivityCollector; +} + +- (BOOL)removeCollector:(ORKCollector *)collector error:(NSError* __autoreleasing *)error { + if (!collector) { + @throw [NSException exceptionWithName:ORKInvalidArgumentException reason:@"collector cannot be nil" userInfo:nil]; + } + + __block BOOL success = NO; + __block NSError *errorOut = nil; + [self onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager) { + + if (_operationQueue.operationCount > 0) { + ORK_Log_Debug("[startWithObserving] returned due to operation queue is not empty (queue size = %@)", @(_operationQueue.operationCount)); + errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{NSLocalizedFailureReasonErrorKey: @"Cannot remove collector during collection."}]; + return NO; + } + + NSMutableArray *collectors = [self.collectors mutableCopy]; + + if (![collectors containsObject:collector]) { + errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorObjectNotFound userInfo:@{NSLocalizedFailureReasonErrorKey: @"Cannot find collector."}]; + return NO; + } + + + // Remove the collector from the collectors array + [collectors removeObject:collector]; + _collectors = [collectors copy]; + + success = YES; + return YES; + }]; + + if (error) { + *error = errorOut; + } + return success; +} + +- (void)startCollection { + + __weak typeof(self) weakSelf = self; + NSMutableArray *operations = [NSMutableArray array]; + [self onWorkQueueAsync:^BOOL(ORKDataCollectionManager *manager) { + + if (_operationQueue.operationCount > 0) { + ORK_Log_Debug("[startWithObserving] returned due to operation queue is not empty (queue size = %@)", @(_operationQueue.operationCount)); + return NO; + } + + self.lastCollectionDate = [NSDate date]; + + // Create an operation for each collector + for (ORKCollector *collector in self.collectors) { + + __block ORKOperation *operation = [collector collectionOperationWithManager:self]; + + // operation could be nil if this type of data collection is not possible + // on this device. + if (operation) { + __block ORKOperation *blockOp = operation; + + [operation setCompletionBlock:^{ + typeof(self) strongSelf = weakSelf; + if (blockOp.error) { + id delegate = strongSelf.delegate; + if (delegate && [delegate respondsToSelector:@selector(collector:didDetectError:)]) { + [delegate collector:collector didDetectError:blockOp.error]; + } + } + }]; + + [operations addObject:operation]; + } + } + + NSBlockOperation *completionOperation = [NSBlockOperation new]; + [completionOperation addExecutionBlock:^{ + + typeof(self) strongSelf = weakSelf; + [strongSelf onWorkQueueSync:^BOOL(ORKDataCollectionManager *collectionManager) { + if (_delegate && [_delegate respondsToSelector:@selector(dataCollectionManagerDidCompleteCollection:)]) { + [_delegate dataCollectionManagerDidCompleteCollection:self]; + } + + for (HKObserverQueryCompletionHandler handler in _completionHandlers) { + handler(); + } + [_completionHandlers removeAllObjects]; + + return NO; + }]; + }]; + + for (NSOperation *operation in operations) { + [completionOperation addDependency:operation]; + } + + ORK_Log_Debug("Data Collection queue - new operations:\n%@", operations); + [_operationQueue addOperations:operations waitUntilFinished:NO]; + [_operationQueue addOperation:completionOperation]; + + // No need to persist collectors + return NO; + }]; + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager_Internal.h new file mode 100755 index 0000000..1465471 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDataCollectionManager_Internal.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDataCollectionManager.h" +#import + + +@interface ORKDataCollectionManager () + +@property (nonatomic, strong, readonly) HKHealthStore *healthStore; + +@property (nonatomic, strong, readonly) CMMotionActivityManager *activityManager; + +- (void)onWorkQueueSync:(BOOL (^)(ORKDataCollectionManager *manager))block; + +- (void)onWorkQueueAsync:(BOOL (^)(ORKDataCollectionManager *manager))block; + +/** + Last collection date. + */ +@property (nonatomic, strong) NSDate *lastCollectionDate; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.h new file mode 100755 index 0000000..6c1536c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKPicker.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKDateTimePicker : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.m new file mode 100755 index 0000000..937537e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDateTimePicker.m @@ -0,0 +1,251 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDateTimePicker.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKDateTimePicker () + +@property (nonatomic, strong) ORKAnswerFormat *answerFormat; +@property (nonatomic, strong) NSCalendar *calendar; + +@end + + +@implementation ORKDateTimePicker { + NSDateFormatter *_labelFormatter; + UIDatePicker *_pickerView; + NSDate *_date; + NSInteger _minuteInterval; + __weak id _pickerDelegate; + id _answer; +} + +@synthesize pickerDelegate = _pickerDelegate; +@synthesize answer = _answer; + +- (instancetype)initWithAnswerFormat:(ORKAnswerFormat *)answerFormat answer:(id)answer pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(currentLocaleDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil]; + + self.answerFormat = answerFormat; + self.answer = answer; + self.pickerDelegate = delegate; + + } + return self; +} + +- (UIDatePicker *)pickerView { + if (_pickerView == nil) { + _pickerView = [[UIDatePicker alloc] init]; + [_pickerView addTarget:self action:@selector(valueDidChange:) forControlEvents:UIControlEventValueChanged]; + self.answerFormat = _answerFormat; + self.answer = _answer; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + if (answer == [ORKDontKnowAnswer answer]) { + return; + } + + if ([self isTimeOfDay]) { + ORKTimeOfDayAnswerFormat *timeOfDayAnswerFormat = (ORKTimeOfDayAnswerFormat *)self.answerFormat; + [self setMinuteInterval:timeOfDayAnswerFormat.minuteInterval]; + + if (answer && answer != ORKNullAnswerValue()) { + NSDateComponents *timeOfDayComponents = (NSDateComponents *)answer; + + NSDate *dateValue = ORKTimeOfDayDateFromComponents(timeOfDayComponents); + [self setDate:dateValue]; + + } else { + [self setDate:[timeOfDayAnswerFormat pickerDefaultDate]]; + } + } else { + ORKDateAnswerFormat *dateAnswerFormat = (ORKDateAnswerFormat *)self.answerFormat; + [self setMinuteInterval:dateAnswerFormat.minuteInterval]; + + if (answer && answer != ORKNullAnswerValue()) { + NSDate *defaultDate = (NSDate *)answer; + [self setDate:defaultDate]; + } else { + NSDate *defaultDate = [dateAnswerFormat pickerDefaultDate]; + [self setDate:defaultDate]; + } + } +} + +- (void)setAnswerFormat:(ORKAnswerFormat *)answerFormat { + ORKQuestionType questionType = answerFormat.questionType; + int datePickerMode = -1; + switch (questionType) { + case ORKQuestionTypeDate: + datePickerMode = UIDatePickerModeDate; + break; + case ORKQuestionTypeDateAndTime: + datePickerMode = UIDatePickerModeDateAndTime; + break; + case ORKQuestionTypeTimeOfDay: + datePickerMode = UIDatePickerModeTime; + break; + default: + break; + } + + NSAssert((datePickerMode >= 0), @"questionType should be Date, DateAndTime, or TimeOfDay."); + + _answerFormat = answerFormat; + + _pickerView.datePickerMode = datePickerMode; + + if ([self isTimeOfDay]) { + [self setDate:[(ORKTimeOfDayAnswerFormat *)answerFormat pickerDefaultDate]]; + } else { + ORKDateAnswerFormat *dateAnswerFormat = (ORKDateAnswerFormat *)answerFormat; + [self setDate:[dateAnswerFormat pickerDefaultDate]]; + + _pickerView.calendar = [dateAnswerFormat currentCalendar]; + _pickerView.timeZone = _pickerView.calendar.timeZone; + + _calendar = [dateAnswerFormat currentCalendar]; + + [_pickerView setMinimumDate:[dateAnswerFormat pickerMinimumDate]]; + [_pickerView setMaximumDate:[dateAnswerFormat pickerMaximumDate]]; + } + + _labelFormatter = nil; +} + +- (void)setDate:(NSDate *)date { + _date = date; + _pickerView.date = date; +} + +- (void)setMinuteInterval:(NSInteger)minuteInterval { + _minuteInterval = minuteInterval; + _pickerView.minuteInterval = minuteInterval; +} + +- (NSDateFormatter *)labelFormatter { + if (_labelFormatter) { + _labelFormatter.calendar = self.calendar; + return _labelFormatter; + } + + NSString *dateFormat = nil; + switch ([self questionType]) { + case ORKQuestionTypeDate: + dateFormat = [NSDateFormatter dateFormatFromTemplate:@"Mdy" options:0 locale:[NSLocale currentLocale]]; + break; + case ORKQuestionTypeDateAndTime: + dateFormat = [NSDateFormatter dateFormatFromTemplate:@"yEMdhma" options:0 locale:[NSLocale currentLocale]]; + break; + case ORKQuestionTypeTimeOfDay: + dateFormat = [NSDateFormatter dateFormatFromTemplate:@"hma" options:0 locale:[NSLocale currentLocale]]; + break; + default: + break; + } + + if (dateFormat != nil) { + NSDateFormatter *dfm = [NSDateFormatter new]; + dfm.dateFormat = dateFormat; + dfm.calendar = self.calendar; + + _labelFormatter = dfm; + } + + return _labelFormatter; +} + +- (NSString *)selectedLabelText { + if (_answer == nil || _answer == ORKNullAnswerValue()) { + return nil; + } + + return [[self labelFormatter] stringFromDate:_date]; +} + +- (void)pickerWillAppear { + // Report current value, since ORKTimeIntervalPicker always has a value + [self pickerView]; + [self valueDidChange:self]; +} + +- (void)valueDidChange:(id)sender { + _date = _pickerView.date; + + if (self.answer != [ORKDontKnowAnswer answer]) { + + if ([self isTimeOfDay]) { + NSDateComponents *answer = ORKTimeOfDayComponentsFromDate([_pickerView date]); + _answer = answer; + } else { + NSDate *dateAnswer = _date; + _answer = dateAnswer; + } + + } + + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:self.answer]; + } +} + +- (ORKQuestionType)questionType { + return self.answerFormat.questionType; +} + +- (BOOL)isTimeOfDay { + return [self questionType] == ORKQuestionTypeTimeOfDay; +} + +- (void)currentLocaleDidChange:(NSNotification *)notification { + _labelFormatter = nil; + [self valueDidChange:nil]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefaultFont.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefaultFont.h new file mode 100755 index 0000000..8be8b62 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefaultFont.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKDefaultFont + ++ (UIFont *)defaultFont; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefines.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefines.h new file mode 100755 index 0000000..38a4112 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDefines.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import Foundation; +@import HealthKit; + +#if defined(__cplusplus) +# define ORK_EXTERN extern "C" __attribute__((visibility("default"))) +#else +# define ORK_EXTERN extern __attribute__((visibility("default"))) +#endif + +#define ORK_CLASS_AVAILABLE __attribute__((visibility("default"))) +#define ORK_ENUM_AVAILABLE +#define ORK_AVAILABLE_DECL + +#define ORK_IOS_10_WATCHOS_3_AVAILABLE (NSClassFromString(@"HKWorkoutConfiguration") != nil) diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.h new file mode 100755 index 0000000..dfbebaf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKDirectionView : UIView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithOrientation:(ORKBodySagittal)orientation NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.m new file mode 100755 index 0000000..9eff751 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDirectionView.m @@ -0,0 +1,251 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDirectionView.h" + +#import "ORKHelpers_Internal.h" + + +static const CGFloat ArrowWidth = 8; +static const CGFloat ArrowLineWidth = 4; + + +@interface ORKArrowView : UIView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithOrientation:(ORKBodySagittal)orientation NS_DESIGNATED_INITIALIZER; + +@property (nonatomic, assign) ORKBodySagittal orientation; +@property (nonatomic, assign) BOOL completed; + +@end + + +@implementation ORKArrowView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithOrientation:(ORKBodySagittal)orientation { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.opaque = NO; + self.orientation = orientation; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self setNeedsDisplay]; +} + +- (CGSize)intrinsicContentSize { + return CGSizeMake(ArrowWidth + 2 * ArrowLineWidth, 2 * (ArrowWidth + ArrowLineWidth)); +} + +- (void)setCompleted:(BOOL)completed { + _completed = completed; + self.alpha = completed ? 1.0f : 0.6f; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + CGContextSetLineWidth(context, ArrowLineWidth); + CGContextSetLineJoin(context, kCGLineJoinRound); + CGContextSetLineCap(context, kCGLineCapRound); + [self.tintColor setStroke]; + + CGMutablePathRef path = CGPathCreateMutable(); + if (self.orientation == ORKBodySagittalLeft) { + CGPathMoveToPoint(path, NULL, ArrowLineWidth + ArrowWidth, ArrowLineWidth); + CGPathAddLineToPoint(path, NULL, ArrowLineWidth, ArrowLineWidth + ArrowWidth); + CGPathAddLineToPoint(path, NULL, ArrowLineWidth + ArrowWidth, ArrowLineWidth + 2 * ArrowWidth); + } else { + CGPathMoveToPoint(path, NULL, ArrowLineWidth, ArrowLineWidth); + CGPathAddLineToPoint(path, NULL, ArrowLineWidth + ArrowWidth, ArrowLineWidth + ArrowWidth); + CGPathAddLineToPoint(path, NULL, ArrowLineWidth, ArrowLineWidth + 2 * ArrowWidth); + } + + CGContextAddPath(context, path); + CGContextStrokePath(context); + CGPathRelease(path); + + CGContextRestoreGState(context); +} + +@end + + +@interface ORKDirectionView () + +@property (nonatomic, assign) ORKBodySagittal orientation; +@property (nonatomic, strong) ORKArrowView *leftArrow; +@property (nonatomic, strong) ORKArrowView *middleArrow; +@property (nonatomic, strong) ORKArrowView *rightArrow; +@property (nonatomic, assign) NSInteger index; +@property (nonatomic, strong) NSTimer *timer; +@property (nonatomic, copy) NSArray *constraints; + +@end + + +@implementation ORKDirectionView + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithFrame:(CGRect)frame { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithOrientation:(ORKBodySagittal)orientation { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.opaque = NO; + self.orientation = orientation; + + self.leftArrow = [[ORKArrowView alloc] initWithOrientation:self.orientation]; + self.leftArrow.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:self.leftArrow]; + + self.middleArrow = [[ORKArrowView alloc] initWithOrientation:self.orientation]; + self.middleArrow.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:self.middleArrow]; + + self.rightArrow = [[ORKArrowView alloc] initWithOrientation:self.orientation]; + self.rightArrow.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:self.rightArrow]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + } + return self; +} + +- (void)setIndex:(NSInteger)index { + _index = index; + + self.leftArrow.completed = NO; + self.middleArrow.completed = NO; + self.rightArrow.completed = NO; + + if (self.orientation == ORKBodySagittalLeft) { + switch (index) { + case 3: + self.leftArrow.completed = YES; + case 2: + self.middleArrow.completed = YES; + case 1: + self.rightArrow.completed = YES; + default: + break; + } + } else { + switch (index) { + case 3: + self.rightArrow.completed = YES; + case 2: + self.middleArrow.completed = YES; + case 1: + self.leftArrow.completed = YES; + default: + break; + } + } +} + +- (void)didMoveToWindow { + if (self.window) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} + +- (void)startAnimating { + [self stopAnimating]; + self.index = 0; + self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f target:self selector:@selector(incrementIndex) userInfo:nil repeats:YES]; +} + +- (void)stopAnimating { + [self.timer invalidate]; + self.timer = nil; +} + +- (void)incrementIndex { + self.index = (self.index + 1) % 4; +} + +- (void)setUpConstraints { + if ([_constraints count]) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + _constraints = nil; + } + + NSMutableArray *constraintsArray = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_leftArrow, _middleArrow, _rightArrow); + + [constraintsArray addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_leftArrow][_middleArrow][_rightArrow]|" + options:NSLayoutFormatAlignAllCenterY + metrics:nil views:views]]; + + [constraintsArray addObject:[NSLayoutConstraint constraintWithItem:self.middleArrow + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; + + self.constraints = constraintsArray; + [self addConstraints:self.constraints]; + + [NSLayoutConstraint activateConstraints:self.constraints]; +} + +- (void)dealloc { + [self stopAnimating]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.h new file mode 100755 index 0000000..3c9cce2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +#import "ORKDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKDontKnowButton : UIButton + +- (void)setButtonActive; +- (void)setButtonInactive; + +@property (nonatomic) BOOL isDontKnowButtonActive; +@property (nonatomic, nullable) NSString *customDontKnowButtonText; + +@end + +@interface ORKDontKnowButton() + +- (void)init_ORKDontKnowButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.m new file mode 100755 index 0000000..1a2b285 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKDontKnowButton.m @@ -0,0 +1,182 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKDontKnowButton.h" +#import "ORKHelpers_Internal.h" + +static const CGFloat DontKnowButtonCornerRadius = 10.0; +static const CGFloat DontKnowButtonEdgeInsetHorizontalSpacing = 10.0; +static const CGFloat DontKnowButtonEdgeInsetVerticalSpacing = 4.0; +static const CGFloat CheckMarkImageHeightOffset = 2.0; +static const CGFloat CheckMarkImageTrailingPadding = 2.0; + +@implementation ORKDontKnowButton { + UIView *_dontKnowButtonCustomView; + UILabel *_dontKnowButtonTextLabel; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self init_ORKDontKnowButton]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self init_ORKDontKnowButton]; + } + return self; +} + +- (void)init_ORKDontKnowButton { + _isDontKnowButtonActive = NO; + + [self setButtonInactive]; + [self tintColorDidChange]; +} + +- (void)updateAppearance { + self.layer.cornerRadius = DontKnowButtonCornerRadius; + self.clipsToBounds = YES; + + if (_dontKnowButtonCustomView) { + [_dontKnowButtonCustomView removeFromSuperview]; + } + + _dontKnowButtonCustomView = [UIView new]; + [_dontKnowButtonCustomView setUserInteractionEnabled:NO]; + _dontKnowButtonCustomView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_dontKnowButtonCustomView]; + + _dontKnowButtonTextLabel = [UILabel new]; + _dontKnowButtonTextLabel.text = _customDontKnowButtonText ? : ORKLocalizedString(@"SLIDER_I_DONT_KNOW", nil); + _dontKnowButtonTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + _dontKnowButtonTextLabel.numberOfLines = 0; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)setButtonInactive { + _isDontKnowButtonActive = NO; + [self updateAppearance]; + + UIFontDescriptor *dontKnowButtonDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *dontKnowButtonFontDescriptor = [dontKnowButtonDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + [_dontKnowButtonTextLabel setFont:[UIFont fontWithDescriptor:dontKnowButtonFontDescriptor size:[[dontKnowButtonDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + + [_dontKnowButtonCustomView addSubview:_dontKnowButtonTextLabel]; + + if (@available(iOS 13.0, *)) { + [_dontKnowButtonCustomView setBackgroundColor:[UIColor systemFillColor]]; + [_dontKnowButtonTextLabel setTextColor:[UIColor secondaryLabelColor]]; + } else { + [_dontKnowButtonCustomView setBackgroundColor:[UIColor grayColor]]; + [_dontKnowButtonTextLabel setTextColor:[UIColor grayColor]]; + } + + CGSize neededSize = [_dontKnowButtonTextLabel sizeThatFits:CGSizeMake( _dontKnowButtonTextLabel.frame.size.width, CGFLOAT_MAX)]; + [[_dontKnowButtonTextLabel.heightAnchor constraintEqualToConstant:neededSize.height] setActive: YES]; + [[_dontKnowButtonTextLabel.centerYAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.centerYAnchor] setActive:YES]; + + [[_dontKnowButtonCustomView.trailingAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.trailingAnchor constant:DontKnowButtonEdgeInsetHorizontalSpacing] setActive:YES]; + [[_dontKnowButtonCustomView.leadingAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.leadingAnchor constant:-DontKnowButtonEdgeInsetHorizontalSpacing] setActive:YES]; + [[_dontKnowButtonCustomView.heightAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.heightAnchor multiplier:1.0 constant:DontKnowButtonEdgeInsetVerticalSpacing * 2] setActive:YES]; + + [[self.trailingAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.trailingAnchor constant:0.0] setActive:YES]; + [[self.leadingAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.leadingAnchor constant:0.0] setActive:YES]; + [[self.topAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.topAnchor constant:0.0] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.bottomAnchor constant:0.0] setActive:YES]; +} + +- (void)setButtonActive { + _isDontKnowButtonActive = YES; + [self updateAppearance]; + + UIFontDescriptor *dontKnowButtonDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *dontKnowButtonFontDescriptor = [dontKnowButtonDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + [_dontKnowButtonTextLabel setFont:[UIFont fontWithDescriptor:dontKnowButtonFontDescriptor size:[[dontKnowButtonDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + + [_dontKnowButtonCustomView addSubview:_dontKnowButtonTextLabel]; + + if (@available(iOS 13.0, *)) { + [_dontKnowButtonTextLabel setTextColor:[UIColor systemBackgroundColor]]; + + //image, image view and add to custom view + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleSmall]; + UIImage *checkMarkImage = [UIImage systemImageNamed:@"checkmark.circle.fill" withConfiguration:imageConfig]; + UIImage *tintedCheckMarkImage = [checkMarkImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIImageView *imageView = [[UIImageView alloc] initWithImage:tintedCheckMarkImage]; + imageView.translatesAutoresizingMaskIntoConstraints = NO; + [imageView setTintColor:_dontKnowButtonTextLabel.textColor]; + + [_dontKnowButtonCustomView addSubview:imageView]; + + CGSize neededSize = [_dontKnowButtonTextLabel sizeThatFits:CGSizeMake( _dontKnowButtonTextLabel.frame.size.width, CGFLOAT_MAX)]; + [[_dontKnowButtonTextLabel.heightAnchor constraintEqualToConstant:neededSize.height] setActive: YES]; + + [imageView.trailingAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.leadingAnchor constant:-CheckMarkImageTrailingPadding].active = YES; + [[imageView.heightAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.heightAnchor multiplier:1.0 constant:CheckMarkImageHeightOffset] setActive:YES]; + [[imageView.widthAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.heightAnchor multiplier:1.0] setActive:YES]; + [imageView.centerYAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.centerYAnchor].active = YES; + + [_dontKnowButtonCustomView.trailingAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.trailingAnchor constant:DontKnowButtonEdgeInsetHorizontalSpacing].active = YES; + [_dontKnowButtonCustomView.topAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.topAnchor constant:-DontKnowButtonEdgeInsetVerticalSpacing].active = YES; + [_dontKnowButtonCustomView.bottomAnchor constraintEqualToAnchor:_dontKnowButtonTextLabel.bottomAnchor constant:DontKnowButtonEdgeInsetVerticalSpacing].active = YES; + [_dontKnowButtonCustomView.leadingAnchor constraintEqualToAnchor:imageView.leadingAnchor constant:-DontKnowButtonEdgeInsetHorizontalSpacing].active = YES; + + [[self.trailingAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.trailingAnchor constant:0.0] setActive:YES]; + [[self.leadingAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.leadingAnchor constant:0.0] setActive:YES]; + [[self.topAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.topAnchor constant:0.0] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_dontKnowButtonCustomView.bottomAnchor constant:0.0] setActive:YES]; + } else { + [_dontKnowButtonTextLabel setTextColor:[UIColor whiteColor]]; + } + + [_dontKnowButtonCustomView setBackgroundColor:[UIColor systemBlueColor]]; +} + +- (void)setCustomDontKnowButtonText:(NSString *)customDontKnowButtonText { + _customDontKnowButtonText = customDontKnowButtonText; + + if (_isDontKnowButtonActive) { + [self setButtonActive]; + } else { + [self setButtonInactive]; + } +} + +@end + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.h new file mode 100755 index 0000000..3ac58a4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/// Error domain for errors with codes in `ORKErrorCode`. +ORK_EXTERN NSString *const ORKErrorDomain ORK_AVAILABLE_DECL; + +/// The exception thrown when an invalid argument is passed to a method or function. +ORK_EXTERN NSString *const ORKInvalidArgumentException ORK_AVAILABLE_DECL; + +/// `ORKErrorCode` codes are used for errors in the domain `ORKErrorDomain`. +typedef NS_ENUM(NSInteger, ORKErrorCode) { + /// No matching object was found. + ORKErrorObjectNotFound = 1, + + /// An object was invalid and processing could not continue. + ORKErrorInvalidObject, + + /// An exception was caught during an operation. + ORKErrorException, + + /// Multiple errors were encountered during an operation. + ORKErrorMultipleErrors +} ORK_ENUM_AVAILABLE; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.m new file mode 100755 index 0000000..7572b28 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKErrors.m @@ -0,0 +1,36 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKErrors.h" + + +NSString *const ORKErrorDomain = @"ORKErrorDomain"; +NSString *const ORKInvalidArgumentException = @"ORKInvalidArgumentException"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.h new file mode 100755 index 0000000..22b8148 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2016, Sage Bionetworks. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Step's details text under title. + */ +ORK_CLASS_AVAILABLE +@interface ORKFootnoteLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.m new file mode 100755 index 0000000..301e07f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFootnoteLabel.m @@ -0,0 +1,44 @@ +/* + Copyright (c) 2016, Sage Bionetworks. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFootnoteLabel.h" +#import "ORKSkin.h" + + +@implementation ORKFootnoteLabel + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + const CGFloat defaultSize = 12; + return [UIFont systemFontOfSize:[[descriptor objectForKey:UIFontDescriptorSizeAttribute] doubleValue] - defaultSize + ORKGetMetricForWindow(ORKScreenMetricFontSizeFootnote, nil)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.h new file mode 100755 index 0000000..d51ce77 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.h @@ -0,0 +1,126 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKFormStep.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKFormItem; +@class ORKFormItemCell; + +@protocol ORKFormItemCellDelegate + +@required +- (void)formItemCell:(ORKFormItemCell *)cell answerDidChangeTo:(nullable id)answer; +- (void)formItemCellDidBecomeFirstResponder:(ORKFormItemCell *)cell; +- (void)formItemCellDidResignFirstResponder:(ORKFormItemCell *)cell; +- (void)formItemCell:(ORKFormItemCell *)cell invalidInputAlertWithMessage:(NSString *)input; +- (void)formItemCell:(ORKFormItemCell *)cell invalidInputAlertWithTitle:(NSString *)title message:(NSString *)message; +- (BOOL)formItemCellShouldDismissKeyboard:(ORKFormItemCell *)cell; + +@end + + +@interface ORKFormItemCell : UITableViewCell + +- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier + formItem:(ORKFormItem *)formItem + answer:(nullable id)answer + maxLabelWidth:(CGFloat)maxLabelWidth + delegate:(id)delegate; + +@property (nonatomic, weak, readonly) id delegate; +@property (nonatomic, copy, nullable) id answer; +@property (nonatomic, strong) ORKFormItem *formItem; +@property (nonatomic, copy, nullable) id defaultAnswer; +@property (nonatomic) CGFloat maxLabelWidth; +@property (nonatomic) CGFloat expectedLayoutWidth; +@property (nonatomic) NSDictionary *savedAnswers; +@property (nonatomic) BOOL useCardView; +@property (nonatomic) BOOL isLastItem; +@property (nonatomic) BOOL isFirstItemInSectionWithoutTitle; +@property (nonatomic) ORKCardViewStyle cardViewStyle; + +@end + + +@interface ORKFormItemTextFieldBasedCell : ORKFormItemCell + +- (void)removeEditingHighlight; + +@end + + +@interface ORKFormItemTextFieldCell : ORKFormItemTextFieldBasedCell + +@end + + +@interface ORKFormItemConfirmTextCell : ORKFormItemTextFieldCell + +@end + + +@interface ORKFormItemNumericCell : ORKFormItemTextFieldBasedCell + +@end + + +@interface ORKFormItemTextCell : ORKFormItemCell + +@end + + +@interface ORKFormItemImageSelectionCell : ORKFormItemCell + +@end + + +@interface ORKFormItemPickerCell : ORKFormItemTextFieldBasedCell + +@end + + +@interface ORKFormItemScaleCell : ORKFormItemCell + +@end + + +@interface ORKFormItemLocationCell : ORKFormItemCell + +@end + +@interface ORKFormItemSESCell : ORKFormItemCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.m new file mode 100755 index 0000000..83f0be2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItemCell.m @@ -0,0 +1,1696 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormItemCell.h" + +#import "ORKCaption1Label.h" +#import "ORKFormTextView.h" +#import "ORKImageSelectionView.h" +#import "ORKLocationSelectionView.h" +#import "ORKSESSelectionView.h" +#import "ORKPicker.h" +#import "ORKScaleSliderView.h" +#import "ORKTableContainerView.h" +#import "ORKTextFieldView.h" +#import "ORKDontKnowButton.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKFormItem_Internal.h" +#import "ORKResult_Private.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@import MapKit; + + +static const CGFloat VerticalMargin = 10.0; +static const CGFloat StandardSpacing = 8.0; +static const CGFloat ErrorLabelTopPadding = 4.0; +static const CGFloat ErrorLabelBottomPadding = 10.0; +static const CGFloat DontKnowButtonTopBottomPadding = 16.0; +static const CGFloat DividerViewTopPadding = 10.0; +static const CGFloat InlineFormItemLabelToTextFieldPadding = 3.0; + +@interface ORKFormItemCell () + +- (void)cellInit NS_REQUIRES_SUPER; +- (void)inputValueDidChange NS_REQUIRES_SUPER; +- (void)inputValueDidClear NS_REQUIRES_SUPER; +- (void)defaultAnswerDidChange NS_REQUIRES_SUPER; +- (void)answerDidChange; +- (void)cellNeedsToResize; +- (void)updateErrorLabelWithMessage:(NSString *)message; + +// For use when setting the answer in response to user action +- (void)ork_setAnswer:(id)answer; + +@property (nonatomic, strong) ORKCaption1Label *labelLabel; +@property (nonatomic, strong) UILabel *errorLabel; +@property (nonatomic, weak) UITableView *_parentTableView; + +// If hasChangedAnswer, then a new defaultAnswer should not change the answer +@property (nonatomic, assign) BOOL hasChangedAnswer; + +@end + + +@interface ORKSegmentedControl : UISegmentedControl + +@end + + +@implementation ORKSegmentedControl + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + NSInteger previousSelectedSegmentIndex = self.selectedSegmentIndex; + [super touchesEnded:touches withEvent:event]; + if (previousSelectedSegmentIndex == self.selectedSegmentIndex) { + [self sendActionsForControlEvents:UIControlEventValueChanged]; + } +} + +@end + + +#pragma mark - ORKFormItemCell + +@interface ORKFormItemCell () + +@property (nonatomic, copy) UIView *containerView; +- (void)showValidityAlertWithMessage:(NSString *)text; + +@end + + +@implementation ORKFormItemCell { + CGFloat _leftRightMargin; + CAShapeLayer *_contentMaskLayer; + NSLayoutConstraint *contentViewBottomConstraint; + NSArray *_containerConstraints; +} + +- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier + formItem:(ORKFormItem *)formItem + answer:(id)answer + maxLabelWidth:(CGFloat)maxLabelWidth + delegate:(id)delegate { + self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; + if (self) { + // Setting the 'delegate' on init is required, as some questions (such as the scale questions) + // need it when they wish to report their default answers to 'ORKFormStepViewController'. + _delegate = delegate; + + _maxLabelWidth = maxLabelWidth; + _answer = [answer copy]; + self.formItem = formItem; + _labelLabel = [[ORKCaption1Label alloc] init]; + _labelLabel.text = formItem.text; + _labelLabel.numberOfLines = 0; + [self setBackgroundColor:[UIColor clearColor]]; + _containerView = [UIView new]; + [_containerView addSubview:_labelLabel]; + [self.contentView addSubview:_containerView]; + [self setupConstraints]; + [self cellInit]; + [self setAnswer:_answer]; + } + return self; +} + +- (void)setExpectedLayoutWidth:(CGFloat)newWidth { + if (newWidth != _expectedLayoutWidth) { + _expectedLayoutWidth = newWidth; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setupConstraints { + if (_containerConstraints) { + [NSLayoutConstraint deactivateConstraints:_containerConstraints]; + } + _containerView.translatesAutoresizingMaskIntoConstraints = NO; + + _containerConstraints = @[ + [NSLayoutConstraint constraintWithItem:_containerView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0], + [NSLayoutConstraint constraintWithItem:_containerView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1.0 constant:_leftRightMargin], + [NSLayoutConstraint constraintWithItem:_containerView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeRight multiplier:1.0 constant:-_leftRightMargin] + ]; + + contentViewBottomConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_containerView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; + + _containerConstraints = [_containerConstraints arrayByAddingObject:contentViewBottomConstraint]; + + [NSLayoutConstraint activateConstraints:_containerConstraints]; +} + +-(void) drawRect:(CGRect)rect { + [super drawRect:rect]; + [self setMaskLayers]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self setMaskLayers]; +} + +- (void)setMaskLayers { + if (_useCardView) { + if (_contentMaskLayer) { + for (CALayer *sublayer in [_contentMaskLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + [_contentMaskLayer removeFromSuperlayer]; + _contentMaskLayer = nil; + } + _contentMaskLayer = [[CAShapeLayer alloc] init]; + + UIColor *fillColor; + UIColor *borderColor; + if (@available(iOS 13.0, *)) { + fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + borderColor = UIColor.separatorColor; + } else { + fillColor = [UIColor ork_borderGrayColor]; + borderColor = [UIColor ork_midGrayTintColor]; + } + [_contentMaskLayer setFillColor:[fillColor CGColor]]; + + CAShapeLayer *foreLayer = [CAShapeLayer layer]; + [foreLayer setFillColor:[fillColor CGColor]]; + foreLayer.zPosition = 0.0f; + + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + + if (_isLastItem || _isFirstItemInSectionWithoutTitle) { + CGRect foreLayerBounds; + NSUInteger rectCorners; + if (_isLastItem && !_isFirstItemInSectionWithoutTitle) { + rectCorners = UIRectCornerBottomLeft | UIRectCornerBottomRight; + foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height - ORKCardDefaultBorderWidth); + } + else if (!_isLastItem && _isFirstItemInSectionWithoutTitle) { + rectCorners = UIRectCornerTopLeft | UIRectCornerTopRight; + foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, ORKCardDefaultBorderWidth, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height - 2 * ORKCardDefaultBorderWidth); + } + else { + foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, ORKCardDefaultBorderWidth, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height - 2 * ORKCardDefaultBorderWidth); + rectCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight; + } + + + _contentMaskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.containerView.bounds + byRoundingCorners: rectCorners + cornerRadii: (CGSize){ORKCardDefaultCornerRadii, ORKCardDefaultCornerRadii}].CGPath; + + CGFloat foreLayerCornerRadii = ORKCardDefaultCornerRadii >= ORKCardDefaultBorderWidth ? ORKCardDefaultCornerRadii - ORKCardDefaultBorderWidth : ORKCardDefaultCornerRadii; + + foreLayer.path = [UIBezierPath bezierPathWithRoundedRect: foreLayerBounds + byRoundingCorners: rectCorners + cornerRadii: (CGSize){foreLayerCornerRadii, foreLayerCornerRadii}].CGPath; + } + else { + CGRect foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, self.containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, self.containerView.bounds.size.height); + foreLayer.path = [UIBezierPath bezierPathWithRect:foreLayerBounds].CGPath; + _contentMaskLayer.path = [UIBezierPath bezierPathWithRect:self.containerView.bounds].CGPath; + CGRect lineBounds = CGRectMake(0.0, self.containerView.bounds.size.height - 1.0, self.containerView.bounds.size.width, 0.5); + lineLayer.path = [UIBezierPath bezierPathWithRect:lineBounds].CGPath; + lineLayer.zPosition = 0.0f; + } + + [lineLayer setFillColor:[borderColor CGColor]]; + if (_cardViewStyle == ORKCardViewStyleBordered) { + _contentMaskLayer.fillColor = borderColor.CGColor; + } + + [_contentMaskLayer addSublayer:foreLayer]; + [_contentMaskLayer addSublayer:lineLayer]; + [_containerView.layer insertSublayer:_contentMaskLayer atIndex:0]; + } +} + +- (void)setUseCardView:(bool)useCardView { + _useCardView = useCardView; + _leftRightMargin = ORKCardLeftRightMarginForWindow(self.window); + [self setupConstraints]; +} + +- (UITableView *)parentTableView { + if (nil == __parentTableView) { + id view = [self superview]; + + while (view && [view isKindOfClass:[UITableView class]] == NO) { + view = [view superview]; + } + __parentTableView = (UITableView *)view; + } + return __parentTableView; +} + +- (void)cellInit { + // Subclasses should override this +} + +- (void)inputValueDidChange { + // Subclasses should override this, and should call _setAnswer: + self.hasChangedAnswer = YES; +} + +- (void)inputValueDidClear { + // Subclasses should override this, and should call _setAnswer: + self.hasChangedAnswer = YES; +} + +- (void)answerDidChange { +} + +- (BOOL)isAnswerValid { + // Subclasses should override this if validation of the answer is required. + return YES; +} + +- (void)defaultAnswerDidChange { + if (!self.hasChangedAnswer && !self.answer) { + if (self.answer != _defaultAnswer && _defaultAnswer && ![self.answer isEqual:_defaultAnswer]) { + self.answer = _defaultAnswer; + + // Inform delegate of the change too + [self ork_setAnswer:_answer]; + } + } +} + +- (void)setDefaultAnswer:(id)defaultAnswer { + _defaultAnswer = [defaultAnswer copy]; + [self defaultAnswerDidChange]; +} + +- (void)setSavedAnswers:(NSDictionary *)savedAnswers { + _savedAnswers = savedAnswers; + + if (!_savedAnswers) { + @throw [NSException exceptionWithName:NSGenericException + reason:@"Saved answers cannot be nil." + userInfo:nil]; + } + +} + +- (BOOL)becomeFirstResponder { + // Subclasses should override this + return YES; +} + +- (BOOL)resignFirstResponder { + [super resignFirstResponder]; + // Subclasses should override this + return YES; +} + +- (void)prepareForReuse { + self.hasChangedAnswer = NO; + [super prepareForReuse]; +} + +// Inform delegate of the change +- (void)ork_setAnswer:(id)answer { + _answer = [answer copy]; + [_delegate formItemCell:self answerDidChangeTo:answer]; +} + +// Receive change from outside +- (void)setAnswer:(id)answer { + _answer = [answer copy]; + [self answerDidChange]; +} + +- (void)showValidityAlertWithMessage:(NSString *)text { + [self.delegate formItemCell:self invalidInputAlertWithMessage:text]; +} + +- (void)showErrorAlertWithTitle:(NSString *)title message:(NSString *)message { + [self.delegate formItemCell:self invalidInputAlertWithTitle:title message:message]; +} + +- (void)cellNeedsToResize { + UITableView *tableView = [self parentTableView]; + [tableView beginUpdates]; + [tableView endUpdates]; +} + +- (void)updateErrorLabelWithMessage:(NSString *)message { + NSString *separatorString = @":"; + NSString *stringtoParse = message ? : ORKLocalizedString(@"RANGE_ALERT_TITLE", @""); + NSString *parsedString = [stringtoParse componentsSeparatedByString:separatorString].firstObject; + + if (@available(iOS 13.0, *)) { + + NSString *errorMessage = [NSString stringWithFormat:@" %@", parsedString]; + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:errorMessage]; + NSTextAttachment *imageAttachment = [NSTextAttachment new]; + + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithPointSize:12 weight:UIImageSymbolWeightRegular scale:UIImageSymbolScaleMedium]; + UIImage *exclamationMarkImage = [UIImage systemImageNamed:@"exclamationmark.circle"]; + UIImage *configuredImage = [exclamationMarkImage imageByApplyingSymbolConfiguration:imageConfig]; + + imageAttachment.image = [configuredImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + + NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:imageAttachment]; + + [fullString insertAttributedString:imageString atIndex:0]; + + self.errorLabel.attributedText = fullString; + } else { + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:parsedString]; + self.errorLabel.attributedText = fullString; + } + + [self updateConstraints]; + [self cellNeedsToResize]; +} + +@end + + +#pragma mark - ORKFormItemTextFieldBasedCell + +@interface ORKFormItemTextFieldBasedCell () + +- (ORKUnitTextField *)textField; + +@property (nonatomic, readonly) ORKTextFieldView *textFieldView; +@property (nonatomic) ORKDontKnowButton *dontKnowButton; +@property (nonatomic, assign) BOOL editingHighlight; +@property (nonatomic) BOOL doneButtonWasPressed; + +@end + + +@implementation ORKFormItemTextFieldBasedCell { + BOOL _shouldShowDontKnow; + NSString *_customDontKnowString; + UIView *_dividerView; + UIView *_dontKnowBackgroundView; +} + +- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier + formItem:(ORKFormItem *)formItem + answer:(id)answer + maxLabelWidth:(CGFloat)maxLabelWidth + delegate:(id)delegate{ + self = [super initWithReuseIdentifier:reuseIdentifier + formItem:formItem + answer:answer + maxLabelWidth:maxLabelWidth + delegate:delegate]; + if (self != nil) { + UILabel *label = self.labelLabel; + label.isAccessibilityElement = NO; + UITextField *textField = self.textFieldView.textField; + textField.isAccessibilityElement = YES; + textField.accessibilityLabel = label.text; + _doneButtonWasPressed = NO; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(orkDoneButtonPressed:) + name:ORKDoneButtonPressedKey + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(resetDoneButton:) + name:ORKResetDoneButtonKey + object:nil]; + } + return self; +} + +- (ORKUnitTextField *)textField { + return _textFieldView.textField; +} + +- (void)cellInit { + [super cellInit]; + + _textFieldView = [[ORKTextFieldView alloc] init]; + + ORKUnitTextField *textField = _textFieldView.textField; + textField.delegate = self; + textField.placeholder = self.formItem.placeholder; + + [self.containerView addSubview:_textFieldView]; + + self.errorLabel = [UILabel new]; + [self.errorLabel setTextColor: [UIColor redColor]]; + [self.errorLabel setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]]; + self.errorLabel.numberOfLines = 0; + + [self.containerView addSubview:self.errorLabel]; + + self.labelLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self.labelLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + _textFieldView.translatesAutoresizingMaskIntoConstraints = NO; + [_textFieldView setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + self.errorLabel.translatesAutoresizingMaskIntoConstraints = NO; + + _shouldShowDontKnow = NO; + _customDontKnowString = nil; + if ([self.formItem.answerFormat shouldShowDontKnowButton]) { + _shouldShowDontKnow = YES; + _customDontKnowString = self.formItem.answerFormat.customDontKnowButtonText; + [self setupDontKnowButton]; + } + + [self setUpContentConstraint]; + [self setNeedsUpdateConstraints]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self setNeedsUpdateConstraints]; +} + +- (void)setupDontKnowButton { + if(!_dontKnowBackgroundView) { + _dontKnowBackgroundView = [UIView new]; + _dontKnowBackgroundView.userInteractionEnabled = YES; + + UITapGestureRecognizer *tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)]; + [_dontKnowBackgroundView addGestureRecognizer:tapGesture1]; + _dontKnowBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + } + + if (!_dontKnowButton) { + _dontKnowButton = [ORKDontKnowButton new]; + _dontKnowButton.customDontKnowButtonText = self.formItem.answerFormat.customDontKnowButtonText; + _dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO; + [_dontKnowButton addTarget:self action:@selector(dontKnowButtonWasPressed) forControlEvents:UIControlEventTouchUpInside]; + } + + if (!_dividerView) { + _dividerView = [UIView new]; + _dividerView.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + [_dividerView setBackgroundColor:[UIColor separatorColor]]; + } else { + [_dividerView setBackgroundColor:[UIColor lightGrayColor]]; + } + } + + [self.containerView addSubview:_dontKnowBackgroundView]; + [self.containerView addSubview:_dontKnowButton]; + [self.containerView addSubview:_dividerView]; + + if (self.answer == [ORKDontKnowAnswer answer]) { + [self dontKnowButtonWasPressed]; + } +} + +- (void)dontKnowButtonWasPressed { + if (![_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonActive]; + [_textFieldView.textField setText:nil]; + + if (![_textFieldView.textField isFirstResponder]) { + [self inputValueDidChange]; + } else { + [self textFieldShouldClear:_textFieldView.textField]; + [_textFieldView.textField endEditing:YES]; + } + + if (self.errorLabel.attributedText) { + self.errorLabel.attributedText = nil; + [self updateConstraints]; + [self cellNeedsToResize]; + } + } +} + +- (void)tapGesture: (id)sender { + //this tap gesture is here to avoid the cell being selected if the user missed the dont know button +} + +- (void)setUpContentConstraint { + NSLayoutConstraint *contentConstraint = [NSLayoutConstraint constraintWithItem:self.contentView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]; + contentConstraint.priority = UILayoutPriorityDefaultHigh; + contentConstraint.active = YES; +} + +- (void)updateConstraints { + CGFloat labelWidth = self.maxLabelWidth; + + NSString *contentSize = [[UIApplication sharedApplication] preferredContentSizeCategory]; + NSArray *largeSizes = @[ + UIContentSizeCategoryExtraExtraLarge, + UIContentSizeCategoryExtraExtraExtraLarge, + UIContentSizeCategoryAccessibilityLarge, + UIContentSizeCategoryAccessibilityExtraLarge, + UIContentSizeCategoryAccessibilityExtraExtraLarge, + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]; + + if (self.labelLabel.text) { + [[self.labelLabel.topAnchor constraintEqualToAnchor:self.containerView.topAnchor constant:StandardSpacing] setActive:YES]; + [[self.labelLabel.leftAnchor constraintEqualToAnchor:self.containerView.leftAnchor constant:ORKSurveyItemMargin] setActive:YES]; + } + + if ([largeSizes containsObject:contentSize]) { + //stack label and textfieldview when the content size is large + if (self.labelLabel.text) { + [[self.labelLabel.rightAnchor constraintEqualToAnchor:self.containerView.rightAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + } + [[self.textFieldView.topAnchor constraintEqualToAnchor:self.labelLabel.text ? self.labelLabel.bottomAnchor : self.containerView.topAnchor + constant:self.labelLabel.text ? StandardSpacing : ORKSurveyItemMargin] setActive:YES]; + [[self.textFieldView.leftAnchor constraintEqualToAnchor:self.containerView.leftAnchor constant:ORKSurveyItemMargin] setActive:YES]; + + [[self.errorLabel.topAnchor constraintEqualToAnchor:self.textFieldView.bottomAnchor constant:ErrorLabelTopPadding] setActive:YES]; + } else { + if (self.labelLabel.text) { + [[self.labelLabel.widthAnchor constraintLessThanOrEqualToConstant:labelWidth] setActive:YES]; + [[self.textFieldView.centerYAnchor constraintEqualToAnchor:self.labelLabel.centerYAnchor constant:0.0] setActive:YES]; + [[self.textFieldView.leftAnchor constraintEqualToAnchor:self.labelLabel.rightAnchor constant:InlineFormItemLabelToTextFieldPadding] setActive:YES]; + [[self.errorLabel.topAnchor constraintEqualToAnchor:self.labelLabel.bottomAnchor constant:ErrorLabelTopPadding] setActive:YES]; + } else { + [[self.textFieldView.topAnchor constraintEqualToAnchor:self.containerView.topAnchor + constant:ORKSurveyItemMargin] setActive:YES]; + [[self.textFieldView.leftAnchor constraintEqualToAnchor:self.containerView.leftAnchor constant:ORKSurveyItemMargin] setActive:YES]; + [[self.errorLabel.topAnchor constraintEqualToAnchor:self.textFieldView.bottomAnchor constant:ErrorLabelTopPadding] setActive:YES]; + } + } + + [[self.textFieldView.rightAnchor constraintEqualToAnchor:self.containerView.rightAnchor constant:0.0] setActive:YES]; + + [[self.errorLabel.rightAnchor constraintEqualToAnchor:self.containerView.rightAnchor] setActive:YES]; + [[self.errorLabel.leftAnchor constraintEqualToAnchor:self.containerView.leftAnchor constant:ORKSurveyItemMargin] setActive:YES]; + + if (_shouldShowDontKnow) { + [[_dontKnowBackgroundView.topAnchor constraintEqualToAnchor:_dividerView.topAnchor] setActive:YES]; + [[_dontKnowBackgroundView.leadingAnchor constraintEqualToAnchor:self.containerView.leadingAnchor] setActive:YES]; + [[_dontKnowBackgroundView.trailingAnchor constraintEqualToAnchor:self.containerView.trailingAnchor] setActive:YES]; + [[_dontKnowBackgroundView.bottomAnchor constraintEqualToAnchor:self.containerView.bottomAnchor] setActive:YES]; + + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + [[_dividerView.topAnchor constraintEqualToAnchor:self.errorLabel.bottomAnchor constant:DividerViewTopPadding] setActive:YES]; + [[_dividerView.leadingAnchor constraintEqualToAnchor:self.containerView.leadingAnchor] setActive:YES]; + [[_dividerView.trailingAnchor constraintEqualToAnchor:self.containerView.trailingAnchor] setActive:YES]; + NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:_dividerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:separatorHeight]; + constraint1.priority = UILayoutPriorityRequired - 1; + constraint1.active = YES; + [[_dontKnowButton.topAnchor constraintEqualToAnchor:_dividerView.bottomAnchor constant:DontKnowButtonTopBottomPadding] setActive:YES]; + [[_dontKnowButton.centerXAnchor constraintEqualToAnchor:self.containerView.centerXAnchor] setActive:YES]; + NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.containerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_dontKnowButton + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:DontKnowButtonTopBottomPadding]; + constraint2.priority = UILayoutPriorityRequired - 1; + constraint2.active = YES; + } else { + [[self.containerView.bottomAnchor constraintEqualToAnchor:self.errorLabel.bottomAnchor constant:ErrorLabelBottomPadding] setActive:YES]; + } + + [super updateConstraints]; +} + +- (void)setEditingHighlight:(BOOL)editingHighlight { + _editingHighlight = editingHighlight; + UIColor *defaultColor; + if (@available(iOS 13.0, *)) { + defaultColor = [UIColor labelColor]; + } else { + defaultColor = [UIColor blackColor]; + } + self.labelLabel.textColor = _editingHighlight ? [self tintColor] : defaultColor; + [self textField].textColor = _editingHighlight ? [self tintColor] : defaultColor; +} + +- (void)dealloc { + [self textField].delegate = nil; +} + +- (void)setLabel:(NSString *)label { + self.labelLabel.text = label; + self.textField.accessibilityLabel = label; +} + +- (NSString *)label { + return self.labelLabel.text; +} + +- (NSString *)formattedValue { + return nil; +} + +- (NSString *)shortenedFormattedValue { + return [self formattedValue]; +} + +- (void)updateValueLabel { + ORKUnitTextField *textField = [self textField]; + + if (textField == nil) { + return; + } + + NSString *formattedValue = [self formattedValue]; + CGFloat formattedWidth = [formattedValue sizeWithAttributes:@{ NSFontAttributeName : textField.font }].width; + const CGFloat MinInputTextFieldPaddingRight = 6.0; + + // Shorten if necessary + if (formattedWidth > textField.frame.size.width - MinInputTextFieldPaddingRight) { + formattedValue = [self shortenedFormattedValue]; + } + + textField.text = formattedValue; +} + +- (BOOL)becomeFirstResponder { + return [self.textField becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder { + BOOL resign = [super resignFirstResponder]; + resign = [self.textField resignFirstResponder] || resign; + return resign; +} + +- (void)inputValueDidClear { + if ([_dontKnowButton isDontKnowButtonActive]) { + [self ork_setAnswer:[ORKDontKnowAnswer answer]]; + } else { + [self ork_setAnswer:ORKNullAnswerValue()]; + } + [super inputValueDidClear]; +} + +- (void)inputValueDidChange { + [super inputValueDidChange]; + + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive] && self.answer != [ORKDontKnowAnswer answer]) { + [self ork_setAnswer:[ORKDontKnowAnswer answer]]; + self.textField.text = @""; + } + + if (self.errorLabel.attributedText != nil) { + self.errorLabel.attributedText = nil; + [self setupConstraints]; + } +} + +- (void)removeEditingHighlight { + self.editingHighlight = NO; +} + +#pragma mark UITextFieldDelegate + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { + return YES; +} + +- (void)textFieldDidBeginEditing:(UITextField *)textField { + // Ask table view to adjust scrollview's position + self.editingHighlight = YES; + [self.delegate formItemCellDidBecomeFirstResponder:self]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); + + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonInactive]; + [self ork_setAnswer:ORKNullAnswerValue()]; + [self inputValueDidChange]; + } +} + +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + BOOL wasDoneButtonPressed = _doneButtonWasPressed; + + [[NSNotificationCenter defaultCenter] + postNotificationName:ORKResetDoneButtonKey + object:self]; + + if (textField.text.length > 0 && ![[self.formItem impliedAnswerFormat] isAnswerValidWithString:textField.text]) { + [self updateErrorLabelWithMessage:[[self.formItem impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:@""]]; + return YES; + } else { + self.errorLabel.attributedText = nil; + [self updateConstraints]; + [self cellNeedsToResize]; + } + + if (self.delegate && wasDoneButtonPressed && ![self.delegate formItemCellShouldDismissKeyboard:self]) { + self.editingHighlight = NO; + [self inputValueDidChange]; + + return NO; + } + + return YES; +} + +- (void)textFieldDidEndEditing:(UITextField *)textField { + self.editingHighlight = NO; + [self.delegate formItemCellDidResignFirstResponder:self]; +} + +- (BOOL)textFieldShouldClear:(UITextField *)textField { + [self inputValueDidClear]; + return YES; +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + if (![[self.formItem impliedAnswerFormat] isAnswerValidWithString:textField.text]) { + [self updateErrorLabelWithMessage:[[self.formItem impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:@""]]; + } else { + self.errorLabel.attributedText = nil; + [self updateConstraints]; + [self cellNeedsToResize]; + } + + [textField resignFirstResponder]; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); + return YES; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return NO; +} + +#pragma mark NSNotification Methods + +- (void) orkDoneButtonPressed:(NSNotification *) notification { + if ([[notification name] isEqualToString:ORKDoneButtonPressedKey]) { + _doneButtonWasPressed = YES; + } +} + +- (void) resetDoneButton:(NSNotification *) notification { + if ([[notification name] isEqualToString:ORKResetDoneButtonKey]) { + _doneButtonWasPressed = NO; + } +} + +@end + + +#pragma mark - ORKFormItemConfirmTextCell + +@implementation ORKFormItemConfirmTextCell + +- (void)setSavedAnswers:(NSDictionary *)savedAnswers { + [super setSavedAnswers:savedAnswers]; + + [savedAnswers addObserver:self + forKeyPath:[self originalItemIdentifier] + options:0 + context:nil]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqual:[self originalItemIdentifier]]) { + self.textField.text = nil; + if (self.answer) { + [self inputValueDidClear]; + } + } +} + +- (BOOL)isAnswerValidWithString:(NSString *)string { + BOOL isValid = NO; + if (string.length > 0) { + NSString *originalItemAnswer = self.savedAnswers[[self originalItemIdentifier]]; + if (!ORKIsAnswerEmpty(originalItemAnswer) && [originalItemAnswer isEqualToString:string]) { + isValid = YES; + } + } + return isValid; +} + +- (NSString *)originalItemIdentifier { + ORKConfirmTextAnswerFormat *answerFormat = (ORKConfirmTextAnswerFormat *)self.formItem.answerFormat; + return [answerFormat.originalItemIdentifier copy]; +} + +- (void)dealloc { + [self.savedAnswers removeObserver:self forKeyPath:[self originalItemIdentifier]]; +} + +#pragma mark UITextFieldDelegate + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + NSString *text = [textField.text stringByReplacingCharactersInRange:range withString:string]; + [self ork_setAnswer:([self isAnswerValidWithString:text] ? text : @"")]; + + return YES; +} + +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + [super textFieldShouldEndEditing:textField]; + if (![self isAnswerValidWithString:textField.text] && textField.text.length > 0) { + textField.text = nil; + if (self.answer) { + [self inputValueDidClear]; + } + [self updateErrorLabelWithMessage:[[self.formItem impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:@""]]; + } + return YES; +} + +@end + + +#pragma mark - ORKFormItemTextFieldCell + +@implementation ORKFormItemTextFieldCell { + NSString *_defaultTextAnswer; +} + +- (void)cellInit { + [super cellInit]; + self.textField.allowsSelection = YES; + ORKTextAnswerFormat *answerFormat = (ORKTextAnswerFormat *)[self.formItem impliedAnswerFormat]; + _defaultTextAnswer = answerFormat.defaultTextAnswer; + self.textField.autocorrectionType = answerFormat.autocorrectionType; + self.textField.autocapitalizationType = answerFormat.autocapitalizationType; + self.textField.spellCheckingType = answerFormat.spellCheckingType; + self.textField.keyboardType = answerFormat.keyboardType; + self.textField.secureTextEntry = answerFormat.secureTextEntry; + self.textField.textContentType = answerFormat.textContentType; + + if (@available(iOS 12.0, *)) { + self.textField.passwordRules = answerFormat.passwordRules; + } + + [self answerDidChange]; +} + +- (void)inputValueDidChange { + NSString *text = self.textField.text; + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; + + [super inputValueDidChange]; +} + +- (void)assignDefaultAnswer { + if (_defaultTextAnswer) { + [self ork_setAnswer:_defaultTextAnswer]; + if (self.textField) { + self.textField.text = _defaultTextAnswer; + } + } +} + +- (void)answerDidChange { + id answer = self.answer; + + ORKTextAnswerFormat *answerFormat = (ORKTextAnswerFormat *)[self.formItem impliedAnswerFormat]; + if (answer == [ORKDontKnowAnswer answer]) { + [self.dontKnowButton setButtonActive]; + self.textField.text = nil; + } else if (answer != ORKNullAnswerValue()) { + if (!answer) { + [self assignDefaultAnswer]; + } + NSString *text = (NSString *)answer; + NSInteger maxLength = answerFormat.maximumLength; + BOOL changedValue = NO; + if (maxLength > 0 && text.length > maxLength) { + text = [text substringToIndex:maxLength]; + changedValue = YES; + } + self.textField.text = text; + if (changedValue) { + [self inputValueDidChange]; + } + } else { + self.textField.text = nil; + } +} + +#pragma mark UITextFieldDelegate + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + ORKTextAnswerFormat *answerFormat = (ORKTextAnswerFormat *)[self.formItem impliedAnswerFormat]; + + NSString *text = [textField.text stringByReplacingCharactersInRange:range withString:string]; + + // Only need to validate the text if the user enters a character other than a backspace. + // For example, if the `textField.text = researchki` and the `text = researchkit`. + if (textField.text.length < text.length) { + + text = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; + + NSInteger maxLength = answerFormat.maximumLength; + + if (maxLength > 0 && text.length > maxLength) { + [self updateErrorLabelWithMessage:[[self.formItem impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:@""]]; + return NO; + } + } + + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; + [super inputValueDidChange]; + + return YES; +} + +@end + + +#pragma mark - ORKFormItemNumericCell + +@implementation ORKFormItemNumericCell { + NSNumberFormatter *_numberFormatter; + NSNumber *_defaultNumericAnswer; +} + +- (void)cellInit { + [super cellInit]; + ORKQuestionType questionType = [self.formItem questionType]; + self.textField.keyboardType = (questionType == ORKQuestionTypeInteger) ? UIKeyboardTypeNumberPad : UIKeyboardTypeDecimalPad; + [self.textField addTarget:self action:@selector(valueFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; + self.textField.allowsSelection = YES; + + ORKNumericAnswerFormat *answerFormat = (ORKNumericAnswerFormat *)[self.formItem impliedAnswerFormat]; + _defaultNumericAnswer = answerFormat.defaultNumericAnswer; + + self.textField.manageUnitAndPlaceholder = YES; + self.textField.unit = answerFormat.unit; + self.textField.placeholder = self.formItem.placeholder; + + _numberFormatter = ORKDecimalNumberFormatter(); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil]; + + [self answerDidChange]; + +} + +- (void) assignDefaultAnswer { + if (_defaultNumericAnswer) { + [self ork_setAnswer:_defaultNumericAnswer]; + if (self.textField) { + self.textField.text = [_numberFormatter stringFromNumber:_defaultNumericAnswer]; + } + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)localeDidChange:(NSNotification *)note { + // On a locale change, re-format the value with the current locale + _numberFormatter.locale = [NSLocale currentLocale]; + [self answerDidChange]; +} + +- (void)inputValueDidChange { + + NSString *text = self.textField.text; + [self setAnswerWithText:text]; + + [super inputValueDidChange]; +} + +- (void)answerDidChange { + id answer = self.answer; + if (answer == [ORKDontKnowAnswer answer]) { + [self.dontKnowButton setButtonActive]; + self.textField.text = nil; + } else if (answer != ORKNullAnswerValue()) { + if (!answer) { + [self assignDefaultAnswer]; + } + else { + NSString *displayValue = answer; + if ([answer isKindOfClass:[NSNumber class]]) { + displayValue = [_numberFormatter stringFromNumber:answer]; + } + self.textField.text = displayValue; + } + } else { + self.textField.text = nil; + } +} + +- (void)setAnswerWithText:(NSString *)text { + BOOL updateInput = NO; + id answer = ORKNullAnswerValue(); + if (text.length) { + answer = [[NSDecimalNumber alloc] initWithString:text locale:[NSLocale currentLocale]]; + if (!answer) { + answer = ORKNullAnswerValue(); + updateInput = YES; + } + } + + [self ork_setAnswer:answer]; + if (updateInput) { + [self answerDidChange]; + } +} + +#pragma mark UITextFieldDelegate + +- (void)valueFieldDidChange:(UITextField *)textField { + ORKNumericAnswerFormat *answerFormat = (ORKNumericAnswerFormat *)[self.formItem impliedAnswerFormat]; + NSString *sanitizedText = [answerFormat sanitizedTextFieldText:[textField text] decimalSeparator:[_numberFormatter decimalSeparator]]; + textField.text = sanitizedText; + + [self inputValueDidChange]; +} + +@end + + +#pragma mark - ORKFormItemTextCell + +@implementation ORKFormItemTextCell { + ORKFormTextView *_textView; + CGFloat _lastSeenLineCount; + NSInteger _maxLength; + NSString *_defaultTextAnswer; +} + +- (void)cellInit { + [super cellInit]; + + _lastSeenLineCount = 1; + self.labelLabel.text = nil; + _textView = [[ORKFormTextView alloc] init]; + _textView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; + _textView.delegate = self; + _textView.contentInset = UIEdgeInsetsMake(-5.0, -4.0, -5.0, 0.0); + _textView.textAlignment = NSTextAlignmentNatural; + _textView.scrollEnabled = NO; + _textView.placeholder = self.formItem.placeholder; + + [self applyAnswerFormat]; + [self answerDidChange]; + + [self.containerView addSubview:_textView]; + [self setUpConstraints]; +} + +- (void)setUpConstraints { + NSDictionary *views = @{ @"textView": _textView }; + ORKEnableAutoLayoutForViews(views.allValues); + NSDictionary *metrics = @{ @"vMargin":@(10), @"hMargin":@(self.separatorInset.left) }; + + NSMutableArray *constraints = [NSMutableArray new]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-hMargin-[textView]-hMargin-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:metrics + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-vMargin-[textView]-vMargin-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:metrics + views:views]]; + + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.contentView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:120.0]; + heightConstraint.priority = UILayoutPriorityDefaultHigh; + [constraints addObject:heightConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)applyAnswerFormat { + ORKAnswerFormat *answerFormat = [self.formItem impliedAnswerFormat]; + if ([answerFormat isKindOfClass:[ORKTextAnswerFormat class]]) { + ORKTextAnswerFormat *textAnswerFormat = (ORKTextAnswerFormat *)answerFormat; + _defaultTextAnswer = textAnswerFormat.defaultTextAnswer; + _maxLength = [textAnswerFormat maximumLength]; + _textView.autocorrectionType = textAnswerFormat.autocorrectionType; + _textView.autocapitalizationType = textAnswerFormat.autocapitalizationType; + _textView.spellCheckingType = textAnswerFormat.spellCheckingType; + _textView.keyboardType = textAnswerFormat.keyboardType; + _textView.secureTextEntry = textAnswerFormat.secureTextEntry; + _textView.textContentType = textAnswerFormat.textContentType; + + if (@available(iOS 12.0, *)) { + _textView.passwordRules = textAnswerFormat.passwordRules; + } + } else { + _maxLength = 0; + } +} + +- (void)setFormItem:(ORKFormItem *)formItem { + [super setFormItem:formItem]; + [self applyAnswerFormat]; +} + +- (void)assignDefaultAnswer { + if (_defaultTextAnswer) { + [self ork_setAnswer:_defaultTextAnswer]; + if (_textView) { + _textView.text = _defaultTextAnswer; + } + } +} + +- (void)answerDidChange { + id answer = self.answer; + if (answer == ORKNullAnswerValue()) { + answer = nil; + } + _textView.text = (NSString *)answer; + [self assignDefaultAnswer]; +} + +- (BOOL)becomeFirstResponder { + return [_textView becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder { + BOOL resign = [super resignFirstResponder]; + return [_textView resignFirstResponder] || resign; +} + +- (void)inputValueDidChange { + NSString *text = _textView.text; + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; + [super inputValueDidChange]; +} + +- (UIColor *)placeholderColor { + return [UIColor ork_midGrayTintColor]; +} + +#pragma mark UITextViewDelegate + +- (void)textViewDidChange:(UITextView *)textView { + NSInteger lineCount = [textView.text componentsSeparatedByCharactersInSet: + [NSCharacterSet newlineCharacterSet]].count; + + if (_lastSeenLineCount != lineCount) { + _lastSeenLineCount = lineCount; + + UITableView *tableView = [self parentTableView]; + + [tableView beginUpdates]; + [tableView endUpdates]; + + CGRect visibleRect = [textView caretRectForPosition:textView.selectedTextRange.start]; + CGRect convertedVisibleRect = [tableView convertRect:visibleRect fromView:_textView]; + [tableView scrollRectToVisible:convertedVisibleRect animated:YES]; + } + + [self inputValueDidChange]; +} + +- (void)textViewDidBeginEditing:(UITextView *)textView { + if (textView.textColor == [self placeholderColor]) { + textView.text = nil; + textView.textColor = [UIColor blackColor]; + } + // Ask table view to adjust scrollview's position + [self.delegate formItemCellDidBecomeFirstResponder:self]; +} + +- (void)textViewDidEndEditing:(UITextView *)textView { + if (textView.text.length == 0) { + textView.text = self.formItem.placeholder; + textView.textColor = [self placeholderColor]; + } + [self.delegate formItemCellDidResignFirstResponder:self]; +} + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { + NSString *string = [textView.text stringByReplacingCharactersInRange:range withString:text]; + + // Only need to validate the text if the user enters a character other than a backspace. + // For example, if the `textView.text = researchki` and the `string = researchkit`. + if (textView.text.length < string.length) { + + string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; + + if (_maxLength > 0 && string.length > _maxLength) { + [self showValidityAlertWithMessage:[[self.formItem impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:string]]; + return NO; + } + } + + return YES; +} + +@end + + +#pragma mark - ORKFormItemImageSelectionCell + +@interface ORKFormItemImageSelectionCell () + +@end + + +@implementation ORKFormItemImageSelectionCell { + ORKImageSelectionView *_selectionView; +} + +- (void)cellInit { + // Subclasses should override this + + self.labelLabel.text = nil; + + _selectionView = [[ORKImageSelectionView alloc] initWithImageChoiceAnswerFormat:(ORKImageChoiceAnswerFormat *)self.formItem.answerFormat + answer:self.answer]; + _selectionView.delegate = self; + + self.contentView.layoutMargins = UIEdgeInsetsMake(VerticalMargin, ORKSurveyItemMargin, VerticalMargin, ORKSurveyItemMargin); + + [self.containerView addSubview:_selectionView]; + [self setUpConstraints]; + + [super cellInit]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = @{@"selectionView": _selectionView }; + ORKEnableAutoLayoutForViews(views.allValues); + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[selectionView]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[selectionView]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +#pragma mark ORKImageSelectionViewDelegate + +- (void)selectionViewSelectionDidChange:(ORKImageSelectionView *)view { + [self ork_setAnswer:view.answer]; + [self inputValueDidChange]; +} + +#pragma mark recover answer + +- (void)answerDidChange { + [super answerDidChange]; + [_selectionView setAnswer:self.answer]; +} + +@end + + +#pragma mark - ORKFormItemScaleCell + +@interface ORKFormItemScaleCell () + +@end + + +@implementation ORKFormItemScaleCell { + ORKScaleSliderView *_sliderView; + id _formatProvider; +} + +- (id)formatProvider { + if (_formatProvider == nil) { + _formatProvider = (id)[self.formItem.answerFormat impliedAnswerFormat]; + } + return _formatProvider; +} + +- (void)cellInit { + self.labelLabel.text = nil; + + _sliderView = [[ORKScaleSliderView alloc] initWithFormatProvider:(ORKScaleAnswerFormat *)self.formItem.answerFormat delegate:self]; + + [self.containerView addSubview:_sliderView]; + [self setUpConstraints]; + + [super cellInit]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = @{ @"sliderView": _sliderView }; + ORKEnableAutoLayoutForViews(views.allValues); + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[sliderView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[sliderView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +#pragma mark recover answer + +- (void)answerDidChange { + [super answerDidChange]; + + id formatProvider = self.formatProvider; + id answer = self.answer; + if (answer && answer != ORKNullAnswerValue()) { + [_sliderView setCurrentAnswerValue:answer]; + } else { + if (answer == nil && [formatProvider defaultAnswer]) { + [_sliderView setCurrentAnswerValue:[formatProvider defaultAnswer]]; + [self ork_setAnswer:_sliderView.currentAnswerValue]; + } else { + [_sliderView setCurrentAnswerValue:nil]; + } + } +} + +- (void)scaleSliderViewCurrentValueDidChange:(ORKScaleSliderView *)sliderView { + + [self ork_setAnswer:sliderView.currentAnswerValue]; + [super inputValueDidChange]; +} + +@end + + +#pragma mark - ORKFormItemPickerCell + +@interface ORKFormItemPickerCell () + +@end + + +@implementation ORKFormItemPickerCell { + id _picker; +} + + +- (void)setFormItem:(ORKFormItem *)formItem { + ORKAnswerFormat *answerFormat = formItem.impliedAnswerFormat; + + if (!(!formItem || + [answerFormat isKindOfClass:[ORKDateAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKTimeOfDayAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKTimeIntervalAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKMultipleValuePickerAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKHeightAnswerFormat class]] || + [answerFormat isKindOfClass:[ORKWeightAnswerFormat class]])) { + @throw [NSException exceptionWithName:NSGenericException reason:@"formItem.answerFormat should be an ORKDateAnswerFormat, ORKTimeOfDayAnswerFormat, ORKTimeIntervalAnswerFormat, ORKValuePicker, ORKMultipleValuePickerAnswerFormat, ORKHeightAnswerFormat, or ORKWeightAnswerFormat instance" userInfo:nil]; + } + [super setFormItem:formItem]; +} + +- (void)setDefaultAnswer:(id)defaultAnswer { + ORK_Log_Debug("%@", defaultAnswer); + [super setDefaultAnswer:defaultAnswer]; +} + +- (void)answerDidChange { + + self.picker.answer = (self.answer == [ORKDontKnowAnswer answer]) ? nil : self.answer; + self.textField.text = self.picker.selectedLabelText; +} + +- (id)picker { + if (_picker == nil) { + ORKAnswerFormat *answerFormat = [self.formItem impliedAnswerFormat]; + _picker = [ORKPicker pickerWithAnswerFormat:answerFormat answer:self.answer delegate:self]; + } + + return _picker; +} + +- (void)inputValueDidChange { + if (!_picker) { + return; + } + + self.textField.text = [_picker selectedLabelText]; + + [self ork_setAnswer:_picker.answer]; + + [self.textField setSelectedTextRange:nil]; + + [super inputValueDidChange]; +} + +#pragma mark ORKPickerDelegate + +- (void)picker:(id)picker answerDidChangeTo:(id)answer { + [self inputValueDidChange]; +} + +#pragma mark UITextFieldDelegate + +- (BOOL)textFieldShouldClear:(UITextField *)textField { + dispatch_async(dispatch_get_main_queue(), ^{ + + // hide keyboard + [textField resignFirstResponder]; + + // clear value + [self inputValueDidClear]; + + // reset picker + [self answerDidChange]; + }); + return YES; +} + +- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { + BOOL shouldBeginEditing = [super textFieldShouldBeginEditing:textField]; + + if (shouldBeginEditing) { + if (self.textFieldView.inputView == nil) { + self.textField.inputView = self.picker.pickerView; + } + + [self.picker pickerWillAppear]; + } + + return shouldBeginEditing; +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + return NO; +} + +@end + + +#pragma mark - ORKFormItemLocationCell + +@interface ORKFormItemLocationCell () + +@property (nonatomic, assign) BOOL editingHighlight; + +@end + + +@implementation ORKFormItemLocationCell { + ORKLocationSelectionView *_selectionView; + NSLayoutConstraint *_heightConstraint; + NSLayoutConstraint *_bottomConstraint; +} + +- (void)cellInit { + [super cellInit]; + + _selectionView = [[ORKLocationSelectionView alloc] initWithFormMode:YES + useCurrentLocation:((ORKLocationAnswerFormat *)self.formItem.answerFormat).useCurrentLocation + leadingMargin:self.separatorInset.left]; + _selectionView.delegate = self; + + [self.containerView addSubview:_selectionView]; + + if (self.formItem.placeholder != nil) { + [_selectionView setPlaceholderText:self.formItem.placeholder]; + } + + [self setUpConstraints]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *dictionary = @{@"_selectionView":_selectionView}; + ORKEnableAutoLayoutForViews([dictionary allValues]); + NSDictionary *metrics = @{@"verticalMargin":@(VerticalMargin), @"horizontalMargin":@(ORKSurveyItemMargin), @"verticalMarginBottom":@(VerticalMargin - (1.0 / [UIScreen mainScreen].scale))}; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_selectionView]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:metrics views:dictionary]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_selectionView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:metrics views:dictionary]]; + _bottomConstraint = [NSLayoutConstraint constraintWithItem:_selectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; + [constraints addObject:_bottomConstraint]; + _heightConstraint = [NSLayoutConstraint constraintWithItem:_selectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:_selectionView.intrinsicContentSize.height]; + _heightConstraint.priority = UILayoutPriorityDefaultHigh; + [constraints addObject:_heightConstraint]; + + [self.contentView addConstraints:constraints]; +} + +- (void)setFormItem:(ORKFormItem *)formItem { + [super setFormItem:formItem]; + + if (_selectionView) { + [_selectionView setPlaceholderText:formItem.placeholder]; + } +} + +- (void)answerDidChange { + _selectionView.answer = self.answer; +} + +- (void)setEditingHighlight:(BOOL)editingHighlight { + _editingHighlight = editingHighlight; + [_selectionView setTextColor:( _editingHighlight ? [self tintColor] : [UIColor blackColor])]; +} + +- (void)locationSelectionViewDidBeginEditing:(ORKLocationSelectionView *)view { + self.editingHighlight = YES; + [_selectionView showMapViewIfNecessary]; + [self.delegate formItemCellDidBecomeFirstResponder:self]; +} + +- (void)locationSelectionViewDidEndEditing:(ORKLocationSelectionView *)view { + self.editingHighlight = NO; + [self.delegate formItemCellDidResignFirstResponder:self]; +} + +- (void)locationSelectionViewDidChange:(ORKLocationSelectionView *)view { + [self inputValueDidChange]; +} + +- (void)locationSelectionViewNeedsResize:(ORKLocationSelectionView *)view { + _heightConstraint.constant = _selectionView.intrinsicContentSize.height; + _bottomConstraint.constant = -(VerticalMargin - (1.0 / [UIScreen mainScreen].scale)); + + [self cellNeedsToResize]; +} + +- (void)locationSelectionView:(ORKLocationSelectionView *)view didFailWithErrorTitle:(NSString *)title message:(NSString *)message { + [self showErrorAlertWithTitle:title message:message]; +} + +- (void)inputValueDidChange { + [self ork_setAnswer:_selectionView.answer]; + [super inputValueDidChange]; +} + +- (BOOL)becomeFirstResponder { + return [_selectionView becomeFirstResponder]; +} + +- (BOOL)resignFirstResponder { + BOOL didResign = [super resignFirstResponder]; + didResign = [_selectionView resignFirstResponder] || didResign; + return didResign; +} + +@end + + +@interface ORKFormItemSESCell() + +@end + +@implementation ORKFormItemSESCell { + ORKSESSelectionView *_selectionView; + NSLayoutConstraint *_heightConstraint; + NSLayoutConstraint *_bottomConstraint; +} + +- (void)cellInit { + [super cellInit]; + + _selectionView = [[ORKSESSelectionView alloc] initWithAnswerFormat:(ORKSESAnswerFormat *)self.formItem.answerFormat answer:self.answer]; + _selectionView.delegate = self; + [self.containerView addSubview:_selectionView]; + + [self setUpConstraints]; +} + +- (void)setUpConstraints { + + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *dictionary = @{@"_selectionView":_selectionView}; + ORKEnableAutoLayoutForViews([dictionary allValues]); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_selectionView]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:dictionary]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_selectionView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:dictionary]]; + _bottomConstraint = [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_selectionView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:10.0]; + _heightConstraint = [NSLayoutConstraint constraintWithItem:_selectionView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:_selectionView.intrinsicContentSize.height]; + _heightConstraint.priority = UILayoutPriorityDefaultHigh; + [constraints addObject:_heightConstraint]; + [constraints addObject:_bottomConstraint]; + + [self.contentView addConstraints:constraints]; +} + +- (void)buttonPressedAtIndex:(NSInteger)index { + _selectionView.answer = [NSNumber numberWithInteger:index]; + [self inputValueDidChange]; +} + +- (void)inputValueDidChange { + [self ork_setAnswer:_selectionView.answer]; + [super inputValueDidChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItem_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItem_Internal.h new file mode 100755 index 0000000..e3f8d59 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormItem_Internal.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerFormat; + +@interface ORKFormItem () + +@property (nonatomic, weak, nullable) ORKFormStep *step; + +- (nullable ORKAnswerFormat *)impliedAnswerFormat; + +- (ORKQuestionType)questionType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.h new file mode 100755 index 0000000..3fd5fd5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKFormSectionTitleLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.m new file mode 100755 index 0000000..6cb4a05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormSectionTitleLabel.m @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormSectionTitleLabel.h" + + +@implementation ORKFormSectionTitleLabel + ++ (UIFont *)defaultFont { + // regular, 14 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return [UIFont systemFontOfSize:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue] - 3.0]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.h new file mode 100755 index 0000000..d4af75c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.h @@ -0,0 +1,278 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + +typedef NS_ENUM(NSInteger, ORKCardViewStyle) { + ORKCardViewStyleDefault, + ORKCardViewStyleBordered +} ORK_ENUM_AVAILABLE; + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerFormat; +@class ORKFormItem; +@class ORKLearnMoreItem; + +/** + The `ORKFormStep` class is a concrete subclass of `ORKStep`, used for presenting multiple questions + on a single scrollable page. + + To use `ORKFormStep`, instantiate the object, fill in its properties, and include it + in a task. Next, create a task view controller for the task and present it. + When the task completes, the user's answers are encoded in the result hierarchy + in the task view controller. + + Each question in the form is represented by an `ORKFormItem` object. The form items have an + `optional` property that defaults to `YES`. All required questions need to be answered for the + Continue button to be enabled. If all the form items are optional, at least one question needs to + be answered for the Continue button to be enabled. You can allow the user to completely skip a + form step using the Skip button, even if it has required form items, by setting the form step + `optional` property to yes. + + The form can be broken into sections by using an `ORKFormItem` object that includes only a section + title. + + The result of a form step is an `ORKStepResult` object that includes a child `ORKQuestionResult` + object for each form item. + */ + +ORK_CLASS_AVAILABLE +@interface ORKFormStep : ORKStep + +/** + Returns an initialized form step using the specified identifier, title, and text. + + @param identifier The string that identifies the step (see `ORKStep`). + @param title The title of the form (see `ORKStep`). + @param text The text shown immediately below the title (see `ORKStep`). + + @return As initialized form step object. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text; + +/** + The array of items in the form. + + A form step that contains no items is considered invalid and an exception will be thrown + when it is presented. + */ +@property (nonatomic, copy, nullable) NSArray *formItems; + +/** + The property to present the form with all the items in a card view. Default to YES; + */ +@property (nonatomic) BOOL useCardView; + +/** + Footer text to display beneath the last formItem. +*/ +@property (nonatomic, copy, nullable) NSString *footerText; + +@property (nonatomic) ORKCardViewStyle cardViewStyle; + +@end + + +/** + The `ORKFormItem` class represents a single item in a form step (`ORKFormStep`), and typically + represents a question. + + To use `ORKFormItem`, instantiate the object, fill in its properties, and incorporate + it in an `ORKFormStep` object. + + Usually, a form item corresponds to either a row or a section header in a form, but + if the answer format is a choice answer format, it may correspond to an entire + section. + + Each form item generates one question result (`ORKQuestionResult`), which becomes a child of its step's + result (`ORKStepResult`). + */ +ORK_CLASS_AVAILABLE +@interface ORKFormItem : NSObject + +/** + Returns an initialized form item using the specified identifier, title, and answer format. + + @param identifier The string that identifies the form item, which should be unique within the form step. + @param text The text displayed as a prompt for the form item's question. + @param answerFormat The answer format for the form item. + + @return An initialized form item. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + answerFormat:(nullable ORKAnswerFormat *)answerFormat; + +/** + Returns an initialized form item using the specified identifier, title, optionality and answer format. + + @param identifier The string that identifies the form item, which should be unique within the form step. + @param text The text displayed as a prompt for the form item's question. + @param answerFormat The answer format for the form item. + @param optional A Boolean that determines whether the item is optional + + @return An initialized form item. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + answerFormat:(nullable ORKAnswerFormat *)answerFormat + optional:(BOOL) optional; + +/** + Returns an initialized form item using the specified identifier, title, optionality and answer format. + + @param identifier The string that identifies the form item, which should be unique within the form step. + @param text The text displayed as a prompt for the form item's question. + @param detailText The detail text displayed below the form items title + @param learnMoreItem The `ORKLearnMoreItem` to be presented when button is pressed. + @param showsProgress A Boolean that determines if the formItem will display a progress indicator + @param answerFormat The answer format for the form item. + @param optional A Boolean that determines whether the item is optional + + @return An initialized form item. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + detailText:(nullable NSString *)detailText + learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem + showsProgress:(BOOL)showsProgress + answerFormat:(nullable ORKAnswerFormat *)answerFormat + tagText:(nullable NSString *)tagText + optional:(BOOL) optional; + +/** + Returns an initialized form item using the specified section title. + + @param sectionTitle The title of the section. + + @return An initialized form item for use as a section header in a form. + */ +- (instancetype)initWithSectionTitle:(nullable NSString *)sectionTitle; + +/** + Returns an initialized form item using the specified section title. + +@param sectionTitle The title of the section. +@param text The detail text displayed below the form items title +@param learnMoreItem The `ORKLearnMoreItem` to be presented when button is pressed. +@param showsProgress A Boolean that determines if the formItem will display a progress indicator + +@return An initialized form item for use as a section header in a form. +*/ + +- (instancetype)initWithSectionTitle:(nullable NSString *)sectionTitle + detailText:(nullable NSString *)text + learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem + showsProgress:(BOOL)showsProgress; +/** + A string that identifies the form item. + + The identifier should be unique within the form step that contains the form + item. The identifier is reproduced in the question result object (`ORKQuestionResult`) + generated for the item. + */ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + A Boolean value indicating whether the form item is optional. + + The default value of this property is `YES`. When the value is `YES`, this form item doesn't need + to be answered for the Continue button of a step form to be enabled. + */ +@property (nonatomic, getter=isOptional) BOOL optional; + +/** + A localized string that describes the form item. + + If the descriptive text is sufficiently short, you can display it as a prompt next to the item. + If it is too long to display next to the item, you can display it above the item. + */ +@property (nonatomic, copy, readonly, nullable) NSString *text; + +@property (nonatomic, copy, nullable) NSString *detailText; + +@property (nonatomic) BOOL showsProgress; + +@property (nonatomic, copy, nullable) ORKLearnMoreItem *learnMoreItem; + +@property (nonatomic, copy, nullable) NSString *tagText; + +/** + A localized string that displays placeholder information for the form item. + + You can display placeholder text in a text field or text area to help users understand how to answer the + item's question. A placeholder string is not appropriate for choice-based answer formats. + */ +@property (nonatomic, copy, nullable) NSString *placeholder; + +/** + The format of the expected answer for the item. + + The answer format specifies the type of answer that is expected, in addition to any + constraints on valid answers. + + By default, the answer format is `nil`. The answer format for a form item that represents a section + header is always `nil`, because no answer is expected. + */ +@property (nonatomic, copy, readonly, nullable) ORKAnswerFormat *answerFormat; + +/** + Returns an form item that can be used for confirming a text entry. + + This form item is intended to be used with an `ORKFormStep` in order to confirm a previous + formItem input. Example usage includes a password or participant identifier that is used to + anonymously identify a study participant. + + Currently, only `ORKTextAnswerFormat` is supported. Unsupported `ORKAnswerFormat` types will + throw an exception. + + The answer format for this item produces an `ORKBooleanQuestionResult` object. + + @param identifier The identifier for the `ORKFormItem` that is returned. + @param text The text for the `ORKFormItem` that is returned. + @param errorMessage The error message to display if the fields do not match + + @return An `ORKFormItem` with the indicated identifier and text and an ORKAnswerFormat + that is appropriate for confirming the input form item. + + */ +- (ORKFormItem *)confirmationAnswerFormItemWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + errorMessage:(NSString *)errorMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.m new file mode 100755 index 0000000..a0014df --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep.m @@ -0,0 +1,357 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormStep.h" + +#import "ORKFormStepViewController.h" +#import "ORKBodyItem.h" +#import "ORKLearnMoreItem.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKFormItem_Internal.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKFormStep + ++ (Class)stepViewControllerClass { + return [ORKFormStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(NSString *)title + text:(NSString *)text { + self = [super initWithIdentifier:identifier]; + if (self) { + self.title = title; + self.text = text; + self.optional = YES; + self.useSurveyMode = YES; + self.useCardView = YES; + self.cardViewStyle = ORKCardViewStyleDefault; + } + return self; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.optional = YES; + self.useSurveyMode = YES; + self.useCardView = YES; + self.cardViewStyle = ORKCardViewStyleDefault; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + for (ORKFormItem *item in _formItems) { + [item.answerFormat validateParameters]; + } + + [self validateIdentifiersUnique]; +} + +- (void)validateIdentifiersUnique { + NSArray *uniqueIdentifiers = [_formItems valueForKeyPath:@"@distinctUnionOfObjects.identifier"]; + NSArray *nonUniqueIdentifiers = [_formItems valueForKeyPath:@"@unionOfObjects.identifier"]; + BOOL itemsHaveNonUniqueIdentifiers = ( nonUniqueIdentifiers.count != uniqueIdentifiers.count ); + + if (itemsHaveNonUniqueIdentifiers) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Each form item should have a unique identifier" userInfo:nil]; + } +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKFormStep *step = [super copyWithZone:zone]; + step.formItems = ORKArrayCopyObjects(_formItems); + step.cardViewStyle = self.cardViewStyle; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (ORKEqualObjects(self.formItems, castObject.formItems)) && + self.cardViewStyle == castObject.cardViewStyle); +} + +- (NSUInteger)hash { + return super.hash ^ self.formItems.hash; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + // We enter this code-path only for formSteps which have ONE valid answer format (the other type of formItem would likely be a section header) + ORKFormItem *item; + for (item in self.formItems) { + if (item.answerFormat) { + break; + } + } + return item.answerFormat; +} + +- (ORKQuestionType)questionType { + ORKAnswerFormat *impliedFormat = [self impliedAnswerFormat]; + return impliedFormat.questionType; +} + +- (BOOL)isFormatImmediateNavigation { + // Only allow immediate navigation for formSteps which contain only ONE formItem with a valid answer format + int numberOfAnswerFormats = 0; + for (ORKFormItem *item in self.formItems) { + if (item.answerFormat) { + numberOfAnswerFormats += 1; + if (numberOfAnswerFormats > 1) { + return false; + } + } + } + ORKQuestionType questionType = self.questionType; + return (self.optional == NO) && ((questionType == ORKQuestionTypeBoolean) || (questionType == ORKQuestionTypeSingleChoice)); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, formItems, ORKFormItem); + ORK_DECODE_BOOL(aDecoder, useCardView); + ORK_DECODE_OBJ(aDecoder, footerText); + ORK_DECODE_ENUM(aDecoder, cardViewStyle); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, formItems); + ORK_ENCODE_BOOL(aCoder, useCardView); + ORK_ENCODE_OBJ(aCoder, footerText); + ORK_ENCODE_ENUM(aCoder, cardViewStyle); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)setFormItems:(NSArray *)formItems { + // unset removed formItems + for (ORKFormItem *item in _formItems) { + item.step = nil; + } + + _formItems = formItems; + + for (ORKFormItem *item in _formItems) { + item.step = self; + } +} + +- (NSSet *)requestedHealthKitTypesForReading { + NSMutableSet *healthTypes = [NSMutableSet set]; + + for (ORKFormItem *formItem in self.formItems) { + ORKAnswerFormat *answerFormat = [formItem answerFormat]; + HKObjectType *objType = [answerFormat healthKitObjectTypeForAuthorization]; + if (objType) { + [healthTypes addObject:objType]; + } + } + + return healthTypes.count ? healthTypes : nil; +} + +@end + + +@implementation ORKFormItem + +- (instancetype)initWithIdentifier:(NSString *)identifier text:(NSString *)text answerFormat:(ORKAnswerFormat *)answerFormat { + return [self initWithIdentifier:identifier + text:text + detailText:nil + learnMoreItem:nil + showsProgress:YES + answerFormat:answerFormat + tagText: nil + optional:YES]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier text:(NSString *)text answerFormat:(ORKAnswerFormat *)answerFormat optional:(BOOL)optional { + return [self initWithIdentifier:identifier + text:text + detailText:nil + learnMoreItem:nil + showsProgress:YES + answerFormat:answerFormat + tagText: nil + optional:optional]; +} + +- (instancetype)initWithSectionTitle:(NSString *)sectionTitle { + self = [super init]; + if (self) { + _text = [sectionTitle copy]; + } + return self; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier text:(nullable NSString *)text detailText:(nullable NSString *)detailText learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem showsProgress:(BOOL)showsProgress answerFormat:(nullable ORKAnswerFormat *)answerFormat tagText:(nullable NSString *)tagText optional:(BOOL) optional { + self = [super init]; + if (self) { + ORKThrowInvalidArgumentExceptionIfNil(identifier); + _identifier = [identifier copy]; + _text = [text copy]; + _detailText = [detailText copy]; + _learnMoreItem = [learnMoreItem copy]; + _showsProgress = showsProgress; + _answerFormat = [answerFormat copy]; + _tagText = [tagText copy]; + _optional = optional; + } + return self; +} + +- (instancetype)initWithSectionTitle:(nullable NSString *)sectionTitle detailText:(nullable NSString *)text learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem showsProgress:(BOOL)showsProgress { + self = [super init]; + if (self) { + _text = [sectionTitle copy]; + _detailText = [text copy]; + _learnMoreItem = [learnMoreItem copy]; + _showsProgress = showsProgress; + } + return self; +} + +- (ORKFormItem *)confirmationAnswerFormItemWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + errorMessage:(NSString *)errorMessage { + + if (![self.answerFormat conformsToProtocol:@protocol(ORKConfirmAnswerFormatProvider)]) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:[NSString stringWithFormat:@"Answer format %@ does not conform to confirmation protocol", self.answerFormat] + userInfo:nil]; + } + + ORKAnswerFormat *answerFormat = [(id )self.answerFormat + confirmationAnswerFormatWithOriginalItemIdentifier:self.identifier + errorMessage:errorMessage]; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:identifier + text:text + answerFormat:answerFormat + optional:self.optional]; + return item; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKFormItem *item = [[[self class] allocWithZone:zone] initWithIdentifier:[_identifier copy] text:[_text copy] answerFormat:[_answerFormat copy]]; + item->_optional = _optional; + item->_placeholder = _placeholder; + item->_detailText = [_detailText copy]; + item->_learnMoreItem = [_learnMoreItem copy]; + item->_showsProgress = _showsProgress; + item->_tagText = [_tagText copy]; + return item; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + ORK_DECODE_BOOL(aDecoder, optional); + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, detailText, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, learnMoreItem, ORKLearnMoreItem); + ORK_DECODE_BOOL(aDecoder, showsProgress); + ORK_DECODE_OBJ_CLASS(aDecoder, placeholder, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, answerFormat, ORKAnswerFormat); + ORK_DECODE_OBJ_CLASS(aDecoder, step, ORKFormStep); + ORK_DECODE_OBJ_CLASS(aDecoder, tagText, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); + ORK_ENCODE_BOOL(aCoder, optional); + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, detailText); + ORK_ENCODE_OBJ(aCoder, learnMoreItem); + ORK_ENCODE_BOOL(aCoder, showsProgress); + ORK_ENCODE_OBJ(aCoder, placeholder); + ORK_ENCODE_OBJ(aCoder, answerFormat); + ORK_ENCODE_OBJ(aCoder, step); + ORK_ENCODE_OBJ(aCoder, tagText); + +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + // Ignore the step reference - it's not part of the content of this item + __typeof(self) castObject = object; + return (ORKEqualObjects(self.identifier, castObject.identifier) + && self.optional == castObject.optional + && ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.detailText, castObject.detailText) + && ORKEqualObjects(self.learnMoreItem, castObject.learnMoreItem) + && self.showsProgress == castObject.showsProgress + && ORKEqualObjects(self.placeholder, castObject.placeholder) + && ORKEqualObjects(self.tagText, castObject.tagText) + && ORKEqualObjects(self.answerFormat, castObject.answerFormat)); +} + +- (NSUInteger)hash { + // Ignore the step reference - it's not part of the content of this item + return _identifier.hash ^ _text.hash ^ _placeholder.hash ^ _answerFormat.hash ^ (_optional ? 0xf : 0x0) ^ _detailText.hash ^ _learnMoreItem.hash ^ (_showsProgress ? 0xf : 0x0) ^ _tagText.hash; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + return [self.answerFormat impliedAnswerFormat]; +} + +- (ORKQuestionType)questionType { + return [[self impliedAnswerFormat] questionType]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.h new file mode 100755 index 0000000..044e697 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKFormStepViewController` class is the concrete `ORKStepViewController` + implementation for `ORKFormStep`. + + You should not need to instantiate a form step view controller + directly. Instead, create an `ORKFormStep` object and include it in a task for an + `ORKTaskViewController` object, and present the task view controller. The task view + controller automatically instantiates the form step view controller + when it encounters a form step and needs to present it. + */ +ORK_CLASS_AVAILABLE +@interface ORKFormStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.m new file mode 100755 index 0000000..ee05a21 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController.m @@ -0,0 +1,1474 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormStepViewController.h" + +#import "ORKCaption1Label.h" +#import "ORKChoiceViewCell_Internal.h" +#import "ORKFormItemCell.h" +#import "ORKFormSectionTitleLabel.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKTableContainerView.h" +#import "ORKStepContentView.h" +#import "ORKBodyItem.h" +#import "ORKLearnMoreView.h" + +#import "ORKSurveyCardHeaderView.h" +#import "ORKTextChoiceCellGroup.h" +#import "ORKLearnMoreStepViewController.h" +#import "ORKBodyItem.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKQuestionResult_Private.h" +#import "ORKFormItem_Internal.h" +#import "ORKFormStep_Internal.h" +#import "ORKResult_Private.h" +#import "ORKStep_Private.h" + +#import "ORKSESSelectionView.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat TableViewYOffsetStandard = 30.0; +static const CGFloat DelayBeforeAutoScroll = 0.25; + +@interface ORKTableCellItem : NSObject + +- (instancetype)initWithFormItem:(ORKFormItem *)formItem; +- (instancetype)initWithFormItem:(ORKFormItem *)formItem choiceIndex:(NSUInteger)index; + +@property (nonatomic, copy) ORKFormItem *formItem; + +@property (nonatomic, copy) ORKAnswerFormat *answerFormat; + +@property (nonatomic, readonly) CGFloat labelWidth; + +// For choice types only +@property (nonatomic, copy, readonly) ORKTextChoice *choice; + +@end + + +@implementation ORKTableCellItem + +- (instancetype)initWithFormItem:(ORKFormItem *)formItem { + self = [super init]; + if (self) { + self.formItem = formItem; + _answerFormat = [[formItem impliedAnswerFormat] copy]; + } + return self; +} + +- (instancetype)initWithFormItem:(ORKFormItem *)formItem choiceIndex:(NSUInteger)index { + self = [super init]; + if (self) { + self.formItem = formItem; + _answerFormat = [[formItem impliedAnswerFormat] copy]; + + if ([self textChoiceAnswerFormat] != nil) { + _choice = [self.textChoiceAnswerFormat.textChoices[index] copy]; + } + } + return self; +} + +- (ORKTextChoiceAnswerFormat *)textChoiceAnswerFormat { + if ([self.answerFormat isKindOfClass:[ORKTextChoiceAnswerFormat class]]) { + return (ORKTextChoiceAnswerFormat *)self.answerFormat; + } + return nil; +} + +- (CGFloat)labelWidth { + static ORKCaption1Label *sharedLabel; + + if (sharedLabel == nil) { + sharedLabel = [ORKCaption1Label new]; + } + + sharedLabel.text = _formItem.text; + + return [sharedLabel textRectForBounds:CGRectInfinite limitedToNumberOfLines:1].size.width; +} + +@end + + +@interface ORKTableSection : NSObject + +- (instancetype)initWithSectionIndex:(NSUInteger)index; + +@property (nonatomic, assign, readonly) NSUInteger index; + +@property (nonatomic, copy) NSString *title; + +@property (nonatomic, copy, nullable) NSString *detailText; + +@property (nonatomic) BOOL showsProgress; + +@property (nonatomic, nullable) ORKLearnMoreItem *learnMoreItem; + +@property (nonatomic, copy, nullable) NSString *tagText; + +// ORKTableCellItem +@property (nonatomic, copy, readonly) NSArray *items; + +@property (nonatomic, readonly) BOOL hasChoiceRows; + +@property (nonatomic, strong) ORKTextChoiceCellGroup *textChoiceCellGroup; + +- (void)addFormItem:(ORKFormItem *)item; + +@property (nonatomic, readonly) CGFloat maxLabelWidth; + +@end + + +@implementation ORKTableSection + +- (instancetype)initWithSectionIndex:(NSUInteger)index { + self = [super init]; + if (self) { + _items = [NSMutableArray new]; + self.title = nil; + _index = index; + } + return self; +} + +- (void)setTitle:(NSString *)title { + _title = title; +} + +- (void)addFormItem:(ORKFormItem *)item { + if ([[item impliedAnswerFormat] isKindOfClass:[ORKTextChoiceAnswerFormat class]]) { + _hasChoiceRows = YES; + ORKTextChoiceAnswerFormat *textChoiceAnswerFormat = (ORKTextChoiceAnswerFormat *)[item impliedAnswerFormat]; + + _textChoiceCellGroup = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:textChoiceAnswerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:_index] + immediateNavigation:NO]; + + [textChoiceAnswerFormat.textChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKTableCellItem *cellItem = [[ORKTableCellItem alloc] initWithFormItem:item choiceIndex:idx]; + [(NSMutableArray *)self.items addObject:cellItem]; + }]; + + } else { + ORKTableCellItem *cellItem = [[ORKTableCellItem alloc] initWithFormItem:item]; + [(NSMutableArray *)self.items addObject:cellItem]; + } +} + +- (CGFloat)maxLabelWidth { + CGFloat max = 0; + for (ORKTableCellItem *item in self.items) { + if (item.labelWidth > max) { + max = item.labelWidth; + } + } + return max; +} + +@end + +@interface ORKFormSectionHeaderView : UIView + +- (instancetype)initWithTitle:(NSString *)title tableView:(UITableView *)tableView firstSection:(BOOL)firstSection; + +@property (nonatomic, strong) NSLayoutConstraint *leftMarginConstraint; + +@property (nonatomic, weak) UITableView *tableView; + +@end + + +@implementation ORKFormSectionHeaderView { + ORKFormSectionTitleLabel *_label; + BOOL _firstSection; +} + +- (instancetype)initWithTitle:(NSString *)title tableView:(UITableView *)tableView firstSection:(BOOL)firstSection { + self = [super init]; + if (self) { + _tableView = tableView; + _firstSection = firstSection; + self.backgroundColor = [UIColor whiteColor]; + + _label = [ORKFormSectionTitleLabel new]; + _label.text = title; + _label.numberOfLines = 0; + _label.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_label]; + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + + const CGFloat LabelFirstBaselineToTop = _firstSection ? 20.0 : 40.0; + const CGFloat LabelLastBaselineToBottom = -10.0; + const CGFloat LabelRightMargin = -4.0; + + NSMutableArray *constraints = [NSMutableArray new]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_label + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:LabelFirstBaselineToTop]]; + + self.leftMarginConstraint = [NSLayoutConstraint constraintWithItem:_label + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]; + + [constraints addObject:self.leftMarginConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_label + attribute:NSLayoutAttributeLastBaseline + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:LabelLastBaselineToBottom]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_label + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:LabelRightMargin]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraints { + [super updateConstraints]; + self.leftMarginConstraint.constant = _tableView.layoutMargins.left; +} + +@end + + +@interface ORKFormStepViewController () + +@property (nonatomic, strong) ORKTableContainerView *tableContainer; +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) ORKStepContentView *headerView; + +@property (nonatomic, strong) NSMutableDictionary *savedAnswers; +@property (nonatomic, strong) NSMutableDictionary *savedAnswerDates; +@property (nonatomic, strong) NSMutableDictionary *savedSystemCalendars; +@property (nonatomic, strong) NSMutableDictionary *savedSystemTimeZones; +@property (nonatomic, strong) NSDictionary *originalAnswers; + +@property (nonatomic, strong) NSMutableDictionary *savedDefaults; + +@end + + +@implementation ORKFormStepViewController { + ORKAnswerDefaultSource *_defaultSource; + NSMutableSet *_formItemCells; + NSMutableArray *_sections; + NSMutableSet *_answeredSections; + BOOL _skipped; + UITableViewCell *_currentFirstResponderCell; + NSArray *_constraints; +} + +- (instancetype)ORKFormStepViewController_initWithResult:(ORKResult *)result { + _defaultSource = [ORKAnswerDefaultSource sourceWithHealthStore:[HKHealthStore new]]; + if (result) { + NSAssert([result isKindOfClass:[ORKStepResult class]], @"Expect a ORKStepResult instance"); + + NSArray *resultsArray = [(ORKStepResult *)result results]; + for (ORKQuestionResult *currentResult in resultsArray) { + id answer = currentResult.answer ? : ORKNullAnswerValue(); + [self setAnswer:answer forIdentifier:currentResult.identifier]; + } + self.originalAnswers = [[NSDictionary alloc] initWithDictionary:self.savedAnswers]; + } + return self; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + return [self ORKFormStepViewController_initWithResult:nil]; +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + + self = [super initWithStep:step]; + return [self ORKFormStepViewController_initWithResult:result]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; + + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [_tableContainer sizeHeaderToFit]; + [_tableContainer resizeFooterToFit]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self updateAnsweredSections]; + NSMutableSet *types = [NSMutableSet set]; + for (ORKFormItem *item in [self formItems]) { + ORKAnswerFormat *format = [item answerFormat]; + HKObjectType *objType = [format healthKitObjectTypeForAuthorization]; + if (objType) { + [types addObject:objType]; + } + } + + BOOL refreshDefaultsPending = NO; + if (types.count) { + NSSet *alreadyRequested = [[self taskViewController] requestedHealthTypesForRead]; + if (![types isSubsetOfSet:alreadyRequested]) { + refreshDefaultsPending = YES; + [_defaultSource.healthStore requestAuthorizationToShareTypes:nil readTypes:types completion:^(BOOL success, NSError *error) { + if (!success) { + ORK_Log_Debug("Authorization: %@",error); + } + dispatch_async(dispatch_get_main_queue(), ^{ + [self refreshDefaults]; + }); + }]; + } + } + if (!refreshDefaultsPending) { + [self refreshDefaults]; + } + + // Reset skipped flag - result can now be non-empty + _skipped = NO; + [_tableContainer sizeHeaderToFit]; + [_tableContainer resizeFooterToFit]; + [_tableContainer layoutIfNeeded]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (void)updateAnsweredSections { + _answeredSections = [NSMutableSet new]; + [_sections enumerateObjectsUsingBlock:^(ORKTableSection * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) { + for (ORKTableCellItem *cellItem in section.items) { + id answer = _savedAnswers[cellItem.formItem.identifier]; + if (!ORKIsAnswerEmpty(answer)) { + NSNumber *sectionNumber = [NSNumber numberWithUnsignedInteger:idx]; + [_answeredSections addObject:sectionNumber]; + } + } + }]; +} + +- (void)updateDefaults:(NSMutableDictionary *)defaults { + _savedDefaults = defaults; + + for (ORKFormItemCell *cell in [_tableView visibleCells]) { + NSIndexPath *indexPath = [_tableView indexPathForCell:cell]; + + ORKTableSection *section = _sections[indexPath.section]; + ORKTableCellItem *cellItem = [section items][indexPath.row]; + ORKFormItem *formItem = cellItem.formItem; + if ([cell isKindOfClass:[ORKChoiceViewCell class]]) { + id answer = _savedAnswers[formItem.identifier]; + answer = answer ? : _savedDefaults[formItem.identifier]; + + [section.textChoiceCellGroup setAnswer:answer]; + + // Answers need to be saved. + [self setAnswer:answer forIdentifier:formItem.identifier]; + + } else { + cell.defaultAnswer = _savedDefaults[formItem.identifier]; + } + } + + _skipped = NO; + [self updateButtonStates]; + [self notifyDelegateOnResultChange]; +} + +- (void)refreshDefaults { + NSArray *formItems = [self formItems]; + ORKAnswerDefaultSource *source = _defaultSource; + ORKWeakTypeOf(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block NSMutableDictionary *defaults = [NSMutableDictionary dictionary]; + for (ORKFormItem *formItem in formItems) { + [source fetchDefaultValueForAnswerFormat:formItem.answerFormat handler:^(id defaultValue, NSError *error) { + if (defaultValue != nil) { + defaults[formItem.identifier] = defaultValue; + } else if (error != nil) { + ORK_Log_Error("Error fetching default for %@: %@", formItem, error); + } + dispatch_semaphore_signal(semaphore); + }]; + } + for (__unused ORKFormItem *formItem in formItems) { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + + // All fetches have completed. + dispatch_async(dispatch_get_main_queue(), ^{ + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + [strongSelf updateDefaults:defaults]; + }); + + }); + + +} + +- (void)removeAnswerForIdentifier:(NSString *)identifier { + if (identifier == nil) { + return; + } + [_savedAnswers removeObjectForKey:identifier]; + _savedAnswerDates[identifier] = [NSDate date]; +} + +- (void)setAnswer:(id)answer forIdentifier:(NSString *)identifier { + if (answer == nil || identifier == nil) { + return; + } + if (_savedAnswers == nil) { + _savedAnswers = [NSMutableDictionary new]; + } + if (_savedAnswerDates == nil) { + _savedAnswerDates = [NSMutableDictionary new]; + } + if (_savedSystemCalendars == nil) { + _savedSystemCalendars = [NSMutableDictionary new]; + } + if (_savedSystemTimeZones == nil) { + _savedSystemTimeZones = [NSMutableDictionary new]; + } + _savedAnswers[identifier] = answer; + _savedAnswerDates[identifier] = [NSDate date]; + _savedSystemCalendars[identifier] = [NSCalendar currentCalendar]; + _savedSystemTimeZones[identifier] = [NSTimeZone systemTimeZone]; +} + +// Override to monitor button title change +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; + [self updateButtonStates]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + + _navigationFooterView.skipButtonItem = skipButtonItem; + [self updateButtonStates]; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_tableContainer removeFromSuperview]; + _tableContainer = nil; + + _tableView.delegate = nil; + _tableView.dataSource = nil; + _tableView = nil; + _formItemCells = nil; + _headerView = nil; + _navigationFooterView = nil; + + if (self.isViewLoaded && self.step) { + [self buildSections]; + + _formItemCells = [NSMutableSet new]; + + _tableContainer = [[ORKTableContainerView alloc] initWithStyle:UITableViewStyleGrouped pinNavigationContainer:NO]; + _tableContainer.tableContainerDelegate = self; + [self.view addSubview:_tableContainer]; + _tableContainer.tapOffView = self.view; + + _tableView = _tableContainer.tableView; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.clipsToBounds = YES; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + _tableView.estimatedRowHeight = ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, self.view.window); + _tableView.estimatedSectionHeaderHeight = 30.0; + + if ([self formStep].useCardView) { + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + + if (ORKNeedWideScreenDesign(self.view)) { + [_tableView setBackgroundColor:[UIColor clearColor]]; + [self.taskViewController.navigationBar setBarTintColor:ORKColor(ORKBackgroundColorKey)]; + [self.view setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } + else { + if (@available(iOS 13.0, *)) { + [_tableView setBackgroundColor:[UIColor systemGroupedBackgroundColor]]; + } else { + [_tableView setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } + [self.taskViewController.navigationBar setBarTintColor:[_tableView backgroundColor]]; + [self.view setBackgroundColor:[_tableView backgroundColor]]; + } + } else { + [_tableView setBackgroundColor:[UIColor clearColor]]; + } + _headerView = _tableContainer.stepContentView; + _headerView.stepTopContentImage = self.step.image; + _headerView.titleIconImage = self.step.iconImage; + _headerView.stepTitle = self.step.title; + _headerView.stepText = self.step.text; + _headerView.stepDetailText = self.step.detailText; + _headerView.stepHeaderTextAlignment = self.step.headerTextAlignment; + _headerView.bodyItems = self.step.bodyItems; + _tableContainer.stepTopContentImageContentMode = self.step.imageContentMode; + + _navigationFooterView = _tableContainer.navigationFooterView; + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.optional = self.step.optional; + _navigationFooterView.footnoteLabel.text = [self formStep].footnote; + + // Form steps should always force the navigation controller to be scrollable + // therefore we should always remove the styling. + [_navigationFooterView removeStyling]; + + if (self.readOnlyMode) { + _navigationFooterView.optional = YES; + [_navigationFooterView setNeverHasContinueButton:YES]; + _navigationFooterView.skipEnabled = [self skipButtonEnabled]; + _navigationFooterView.skipButton.accessibilityTraits = UIAccessibilityTraitStaticText; + } + [self setupConstraints]; + [_tableContainer setNeedsLayout]; + } +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _tableContainer.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; + +} + +- (void)buildSections { + NSArray *items = [self allFormItems]; + _sections = [NSMutableArray new]; + ORKTableSection *section = nil; + + for (ORKFormItem *item in items) { + BOOL itemRequiresSingleSection = [self doesItemRequireSingleSection:item]; + + if (!item.answerFormat) { + // Add new section + section = [self createSectionWithItem:item]; + [_sections addObject:section]; + + } else if (itemRequiresSingleSection || _sections.count == 0) { + + [self buildSingleSection:item]; + section = [_sections lastObject]; + } else { + if (section) { + [section addFormItem:item]; + } + } + } +} + +- (void)buildSingleSection:(ORKFormItem *)item { + ORKTableSection *section = nil; + + // Section header + if ([item impliedAnswerFormat] == nil) { + // Add new section + section = [self createSectionWithItem:item]; + [_sections addObject:section]; + + // Actual item + } else { + + // Items require individual section + if ([self doesItemRequireSingleSection:item]) { + // Add new section + section = [self createSectionWithItem:item]; + [_sections addObject:section]; + + [section addFormItem:item]; + + } else { + // In case no section available, create new one. + if (section == nil) { + section = [self createSectionWithItem:item]; + [_sections addObject:section]; + } + [section addFormItem:item]; + } + } +} + +- (ORKTableSection *)createSectionWithItem:(ORKFormItem *)item { + ORKTableSection *section = [[ORKTableSection alloc] initWithSectionIndex:_sections.count]; + section.title = item.text; + section.detailText = item.detailText; + section.learnMoreItem = item.learnMoreItem; + section.showsProgress = item.showsProgress; + section.tagText = item.tagText; + + return section; +} + +- (BOOL)doesItemRequireSingleSection:(ORKFormItem *)item { + if (item.impliedAnswerFormat == nil) { + return NO; + } + + ORKAnswerFormat *answerFormat = [item impliedAnswerFormat]; + + NSArray *singleSectionTypes = @[@(ORKQuestionTypeBoolean), + @(ORKQuestionTypeSingleChoice), + @(ORKQuestionTypeMultipleChoice), + @(ORKQuestionTypeLocation), + @(ORKQuestionTypeSES)]; + + BOOL multiCellChoices = ([singleSectionTypes containsObject:@(answerFormat.questionType)] && + NO == [answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]]); + + BOOL scale = (answerFormat.questionType == ORKQuestionTypeScale); + + // Items require individual section + if (multiCellChoices || scale) { + return YES; + } + + return NO; +} + +- (NSInteger)numberOfAnsweredFormItemsInDictionary:(NSDictionary *)dictionary { + __block NSInteger nonNilCount = 0; + [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id answer, BOOL *stop) { + if (ORKIsAnswerEmpty(answer) == NO) { + nonNilCount ++; + } + }]; + return nonNilCount; +} + +- (NSInteger)numberOfAnsweredFormItems { + return [self numberOfAnsweredFormItemsInDictionary:self.savedAnswers]; +} + +- (BOOL)allAnsweredFormItemsAreValid { + for (ORKFormItem *item in [self formItems]) { + id answer = _savedAnswers[item.identifier]; + if (ORKIsAnswerEmpty(answer) == NO && ![item.impliedAnswerFormat isAnswerValid:answer]) { + return NO; + } + } + return YES; +} + +- (BOOL)allNonOptionalFormItemsHaveAnswers { + for (ORKFormItem *item in [self formItems]) { + if (!item.optional) { + id answer = _savedAnswers[item.identifier]; + if (ORKIsAnswerEmpty(answer) || ![item.impliedAnswerFormat isAnswerValid:answer]) { + return NO; + } + } + } + return YES; +} + +- (BOOL)continueButtonEnabled { + BOOL enabled = ([self numberOfAnsweredFormItems] > 0 + && [self allAnsweredFormItemsAreValid] + && [self allNonOptionalFormItemsHaveAnswers]); + if (self.isBeingReviewed) { + enabled = enabled && ![self.savedAnswers isEqualToDictionary:self.originalAnswers]; + } + return enabled; +} + +- (BOOL)skipButtonEnabled { + BOOL enabled = self.formStep.optional; + if (self.isBeingReviewed) { + enabled = self.readOnlyMode ? NO : enabled && [self numberOfAnsweredFormItemsInDictionary:self.originalAnswers] > 0; + } + return enabled; +} + +- (void)updateButtonStates { + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.skipEnabled = [self skipButtonEnabled]; +} + +- (void)setShouldPresentInReview:(BOOL)shouldPresentInReview { + [super setShouldPresentInReview:shouldPresentInReview]; + [_navigationFooterView setHidden:YES]; +} + +#pragma mark Helpers + +- (ORKFormStep *)formStep { + NSAssert(!self.step || [self.step isKindOfClass:[ORKFormStep class]], nil); + return (ORKFormStep *)self.step; +} + +- (NSArray *)allFormItems { + return [[self formStep] formItems]; +} + +- (NSArray *)formItems { + NSArray *formItems = [self allFormItems]; + NSMutableArray *array = [NSMutableArray arrayWithCapacity:formItems.count]; + for (ORKFormItem *item in formItems) { + if (item.answerFormat != nil) { + [array addObject:item]; + } + } + + return [array copy]; +} + +- (BOOL)showValidityAlertWithMessage:(NSString *)text { + // Ignore if our answer is null + if (_skipped) { + return NO; + } + + return [super showValidityAlertWithMessage:text]; +} + +- (BOOL)hasAnswer { + return (self.savedAnswers != nil); +} + +// Not to use `ImmediateNavigation` when current step already has an answer. +// So user is able to review the answer when it is present. +- (BOOL)isStepImmediateNavigation { + // FIXME: - add explicit property in FormStep to dictate this behavior +// return [[self formStep] isFormatImmediateNavigation] && [self hasAnswer] == NO && !self.isBeingReviewed; + return NO; +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + + NSArray *items = [self formItems]; + + // "Now" is the end time of the result, which is either actually now, + // or the last time we were in the responder chain. + NSDate *now = parentResult.endDate; + + NSMutableArray *qResults = [NSMutableArray new]; + for (ORKFormItem *item in items) { + + // Skipped forms report a "null" value for every item -- by skipping, the user has explicitly said they don't want + // to report any values from this form. + + id answer = ORKNullAnswerValue(); + NSDate *answerDate = now; + NSCalendar *systemCalendar = [NSCalendar currentCalendar]; + NSTimeZone *systemTimeZone = [NSTimeZone systemTimeZone]; + if (!_skipped) { + answer = _savedAnswers[item.identifier]; + answerDate = _savedAnswerDates[item.identifier] ? : now; + systemCalendar = _savedSystemCalendars[item.identifier]; + NSAssert(answer == nil || answer == ORKNullAnswerValue() || systemCalendar != nil, @"systemCalendar NOT saved"); + systemTimeZone = _savedSystemTimeZones[item.identifier]; + NSAssert(answer == nil || answer == ORKNullAnswerValue() || systemTimeZone != nil, @"systemTimeZone NOT saved"); + } + + ORKQuestionResult *result = [item.answerFormat resultWithIdentifier:item.identifier answer:answer]; + ORKAnswerFormat *impliedAnswerFormat = [item impliedAnswerFormat]; + + if ([impliedAnswerFormat isKindOfClass:[ORKDateAnswerFormat class]]) { + ORKDateQuestionResult *dqr = (ORKDateQuestionResult *)result; + if (dqr.dateAnswer) { + NSCalendar *usedCalendar = [(ORKDateAnswerFormat *)impliedAnswerFormat calendar] ? : systemCalendar; + dqr.calendar = [NSCalendar calendarWithIdentifier:usedCalendar.calendarIdentifier]; + dqr.timeZone = systemTimeZone; + } + } else if ([impliedAnswerFormat isKindOfClass:[ORKNumericAnswerFormat class]]) { + ORKNumericQuestionResult *nqr = (ORKNumericQuestionResult *)result; + if (nqr.unit == nil) { + nqr.unit = [(ORKNumericAnswerFormat *)impliedAnswerFormat unit]; + } + } + + result.startDate = answerDate; + result.endDate = answerDate; + + [qResults addObject:result]; + } + + parentResult.results = [parentResult.results arrayByAddingObjectsFromArray:qResults] ? : qResults; + + return parentResult; +} + +- (void)skipForward { + // This _skipped flag is a hack so that the -result method can return an empty + // result after the skip action, without having to generate the result + // in advance. + _skipped = YES; + [self notifyDelegateOnResultChange]; + + [super skipForward]; +} + +- (void)goBackward { + if (self.isBeingReviewed) { + self.savedAnswers = [[NSMutableDictionary alloc] initWithDictionary:self.originalAnswers]; + } + [super goBackward]; +} + +- (BOOL)didAutoScrollToNextItem:(ORKFormItemCell *)cell { + NSIndexPath *currentIndexPath = [self.tableView indexPathForCell:cell]; + + if (cell.isLastItem) { + return NO; + } else { + NSIndexPath *nextIndexPath = [NSIndexPath indexPathForRow:currentIndexPath.row + 1 inSection:currentIndexPath.section]; + ORKFormItemCell *nextCell = [self.tableView cellForRowAtIndexPath:nextIndexPath]; + ORKQuestionType type = nextCell.formItem.impliedAnswerFormat.questionType; + + if ([self doesTableCellTypeUseKeyboard:type]) { + [_tableView deselectRowAtIndexPath:currentIndexPath animated:NO]; + + if ([nextCell isKindOfClass:[ORKFormItemCell class]]) { + [nextCell becomeFirstResponder]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; + }); + } + + } else { + return NO; + } + } + + return YES; +} + +- (BOOL)shouldAutoScrollToNextSection:(NSIndexPath *)indexPath { + NSIndexPath *nextIndexPath = [NSIndexPath indexPathForRow:0 inSection:(indexPath.section + 1)]; + ORKFormItemCell *nextCell = [self.tableView cellForRowAtIndexPath:nextIndexPath]; + + if ([nextCell respondsToSelector:@selector(formItem)]) { + ORKQuestionType type = nextCell.formItem.impliedAnswerFormat.questionType; + if ([self doesTableCellTypeUseKeyboard:type] && [nextCell isKindOfClass:[ORKFormItemCell class]]) { + return YES; + } + } + return NO; +} + +- (void)autoScrollToNextSection:(NSIndexPath *)indexPath { + NSIndexPath *nextIndexPath = [NSIndexPath indexPathForRow:0 inSection:(indexPath.section + 1)]; + ORKFormItemCell *nextCell = [self.tableView cellForRowAtIndexPath:nextIndexPath]; + [nextCell becomeFirstResponder]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; + }); +} + +- (void)handleAutoScrollForNonKeyboardCell:(ORKFormItemCell *)cell { + NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; + ORKTableSection *section = _sections[indexPath.section]; + NSNumber *sectionIndex = [NSNumber numberWithLong:indexPath.section]; + + if ([cell isKindOfClass:[ORKFormItemCell class]]) { + if (cell.formItem.answerFormat.impliedAnswerFormat.questionType != ORKQuestionTypeSES) { + return; + } + } else if (section.textChoiceCellGroup.answerFormat.style != ORKChoiceAnswerStyleSingleChoice) { + return; + } + + if ((indexPath.section < _sections.count - 1) && [self shouldAutoScrollToNextSection:indexPath] && ![_answeredSections containsObject:sectionIndex]) { + [self autoScrollToNextSection:indexPath]; + } else if ((indexPath.section == (_sections.count - 1)) && ![_answeredSections containsObject:sectionIndex]) { + [self.tableView scrollRectToVisible:[self.tableView convertRect:self.tableView.tableFooterView.bounds fromView:self.tableView.tableFooterView] animated:YES]; + } else if (indexPath.section < (_sections.count - 1) && ![_answeredSections containsObject:sectionIndex]) { + NSIndexPath *nextIndexPath = [NSIndexPath indexPathForRow:0 inSection:(indexPath.section + 1)]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_tableView scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; + }); + } +} + +- (BOOL)doesTableCellTypeUseKeyboard:(ORKQuestionType)questionType { + switch (questionType) { + case ORKQuestionTypeDecimal: + case ORKQuestionTypeInteger: + case ORKQuestionTypeText: + return YES; + + default: + return NO; + } +} + +#pragma mark NSNotification methods + +- (void)keyboardWillShow:(NSNotification *)notification { + CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; + + if ((_currentFirstResponderCell.frame.origin.y + _currentFirstResponderCell.frame.size.height) >= (self.view.frame.size.height - keyboardSize.height)) { + _tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height + TableViewYOffsetStandard, 0); + } +} + +- (void)keyboardWillHide:(NSNotification *)notification { + _tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); +} + +#pragma mark UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return _sections.count; +} + +- (NSInteger)numberOfRowsInSection:(NSInteger)section { + ORKTableSection *sectionObject = (ORKTableSection *)_sections[section]; + return sectionObject.items.count; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self numberOfRowsInSection:section]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + NSString *identifier = [NSString stringWithFormat:@"%ld-%ld",(long)indexPath.section, (long)indexPath.row]; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + + if (cell == nil) { + ORKTableSection *section = (ORKTableSection *)_sections[indexPath.section]; + ORKTableCellItem *cellItem = [section items][indexPath.row]; + bool isLastItem = [section items].count == indexPath.row + 1; + bool isFirstItemWithSectionWithoutTitle = indexPath.row == 0 && !section.title; + ORKFormItem *formItem = cellItem.formItem; + id answer = _savedAnswers[formItem.identifier]; + + if (section.textChoiceCellGroup && ([section.textChoiceCellGroup cellAtIndexPath:indexPath withReuseIdentifier:identifier] != nil)) { + [section.textChoiceCellGroup setAnswer:answer]; + section.textChoiceCellGroup.delegate = self; + ORKChoiceViewCell *choiceViewCell = nil; + choiceViewCell = [section.textChoiceCellGroup cellAtIndexPath:indexPath withReuseIdentifier:identifier]; + if ([choiceViewCell isKindOfClass:[ORKChoiceOtherViewCell class]]) { + ORKChoiceOtherViewCell *choiceOtherViewCell = (ORKChoiceOtherViewCell *)choiceViewCell; + choiceOtherViewCell.delegate = self; + } + choiceViewCell.useCardView = [self formStep].useCardView; + choiceViewCell.cardViewStyle = [self formStep].cardViewStyle; + choiceViewCell.isLastItem = isLastItem; + choiceViewCell.isFirstItemInSectionWithoutTitle = isFirstItemWithSectionWithoutTitle; + cell = choiceViewCell; + + } else { + ORKAnswerFormat *answerFormat = [cellItem.formItem impliedAnswerFormat]; + ORKQuestionType type = answerFormat.questionType; + + Class class = nil; + switch (type) { + case ORKQuestionTypeSingleChoice: + case ORKQuestionTypeMultipleChoice: { + if ([formItem.impliedAnswerFormat isKindOfClass:[ORKImageChoiceAnswerFormat class]]) { + class = [ORKFormItemImageSelectionCell class]; + } else if ([formItem.impliedAnswerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]]) { + class = [ORKFormItemPickerCell class]; + } + break; + } + + case ORKQuestionTypeDateAndTime: + case ORKQuestionTypeDate: + case ORKQuestionTypeTimeOfDay: + case ORKQuestionTypeTimeInterval: + case ORKQuestionTypeMultiplePicker: + case ORKQuestionTypeHeight: + case ORKQuestionTypeWeight: { + class = [ORKFormItemPickerCell class]; + break; + } + + case ORKQuestionTypeDecimal: + case ORKQuestionTypeInteger: { + class = [ORKFormItemNumericCell class]; + break; + } + + case ORKQuestionTypeText: { + if ([formItem.answerFormat isKindOfClass:[ORKConfirmTextAnswerFormat class]]) { + class = [ORKFormItemConfirmTextCell class]; + } else { + ORKTextAnswerFormat *textFormat = (ORKTextAnswerFormat *)answerFormat; + if (!textFormat.multipleLines) { + class = [ORKFormItemTextFieldCell class]; + } else { + class = [ORKFormItemTextCell class]; + } + } + break; + } + + case ORKQuestionTypeScale: { + class = [ORKFormItemScaleCell class]; + break; + } + + case ORKQuestionTypeLocation: { + class = [ORKFormItemLocationCell class]; + break; + } + case ORKQuestionTypeSES: { + class = [ORKFormItemSESCell class]; + break; + } + + default: + NSAssert(NO, @"SHOULD NOT FALL IN HERE %@ %@", @(type), answerFormat); + break; + } + + if (class) { + if ([class isSubclassOfClass:[ORKChoiceViewCell class]]) { + NSAssert(NO, @"SHOULD NOT FALL IN HERE"); + } else { + ORKFormItemCell *formCell = nil; + formCell = [[class alloc] initWithReuseIdentifier:identifier formItem:formItem answer:answer maxLabelWidth:section.maxLabelWidth delegate:self]; + [_formItemCells addObject:formCell]; + [formCell setExpectedLayoutWidth:self.tableView.bounds.size.width]; + formCell.selectionStyle = UITableViewCellSelectionStyleNone; + formCell.defaultAnswer = _savedDefaults[formItem.identifier]; + if (!_savedAnswers) { + _savedAnswers = [NSMutableDictionary new]; + } + formCell.savedAnswers = _savedAnswers; + formCell.useCardView = [self formStep].useCardView; + formCell.cardViewStyle = [self formStep].cardViewStyle; + formCell.isLastItem = isLastItem; + formCell.isFirstItemInSectionWithoutTitle = isFirstItemWithSectionWithoutTitle; + cell = formCell; + } + } else { + NSAssert(NO, @"SHOULD NOT FALL IN HERE"); + } + } + } + else { + [cell setNeedsDisplay]; + } + cell.userInteractionEnabled = !self.readOnlyMode; + + return cell; +} + +- (BOOL)isChoiceSelected:(id)value atIndex:(NSUInteger)index answer:(id)answer { + BOOL isSelected = NO; + if (answer != nil && answer != ORKNullAnswerValue()) { + if ([answer isKindOfClass:[NSArray class]]) { + if (value) { + isSelected = [(NSArray *)answer containsObject:value]; + } else { + isSelected = [(NSArray *)answer containsObject:@(index)]; + } + } else { + if (value) { + isSelected = ([answer isEqual:value]); + } else { + isSelected = (((NSNumber *)answer).integerValue == index); + } + } + } + return isSelected; +} + +#pragma mark UITableViewDelegate + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { + return YES; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:NO]; + + ORKFormItemCell *cell = (ORKFormItemCell *)[tableView cellForRowAtIndexPath:indexPath]; + if ([cell isKindOfClass:[ORKFormItemCell class]]) { + [cell becomeFirstResponder]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; + }); + } else { + // Dismiss other textField's keyboard + [tableView endEditing:NO]; + + ORKTableSection *section = _sections[indexPath.section]; + [section.textChoiceCellGroup didSelectCellAtIndexPath:indexPath]; + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { + NSString *title = _sections[section].title; + + // Make first section header view zero height when there is no title + return [self formStep].useCardView ? UITableViewAutomaticDimension : (title.length > 0) ? UITableViewAutomaticDimension : ((section == 0) ? 0 : UITableViewAutomaticDimension); +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + NSString *title = _sections[section].title; + NSString *detailText = _sections[section].detailText; + NSString *sectionProgressText = nil; + ORKLearnMoreView *learnMoreView; + NSString *tagText = _sections[section].tagText; + BOOL hasMultipleChoiceFormItem = NO; + + if (_sections[section].showsProgress) { + if ([self.delegate respondsToSelector:@selector(stepViewControllerTotalProgressInfoForStep:currentStep:)]) { + ORKTaskTotalProgress progressInfo = [self.delegate stepViewControllerTotalProgressInfoForStep:self currentStep:self.step]; + if (progressInfo.stepShouldShowTotalProgress) { + sectionProgressText = [NSString localizedStringWithFormat:ORKLocalizedString(@"FORM_ITEM_PROGRESS", nil) ,ORKLocalizedStringFromNumber(@(section + progressInfo.currentStepStartingProgressPosition)), ORKLocalizedStringFromNumber(@(progressInfo.total))]; + } + } + + if (!sectionProgressText) { + // only display progress label if there are more than 1 sections in the form step + if ([_sections count] > 1) { + sectionProgressText = [NSString localizedStringWithFormat:ORKLocalizedString(@"FORM_ITEM_PROGRESS", nil) ,ORKLocalizedStringFromNumber(@(section + 1)), ORKLocalizedStringFromNumber(@([_sections count]))]; + } + } + } + + if (_sections[section].learnMoreItem) { + learnMoreView = [ORKLearnMoreView learnMoreViewWithItem:_sections[section].learnMoreItem]; + learnMoreView.delegate = self; + } + + if (_sections[section].items.count > 0) { + ORKTableCellItem *tableCellItem = (ORKTableCellItem *)_sections[section].items.firstObject; + ORKFormItem *firstFormItem = tableCellItem.formItem; + + if (firstFormItem.impliedAnswerFormat != nil) { + if (firstFormItem.impliedAnswerFormat.questionType == ORKQuestionTypeMultipleChoice) { + hasMultipleChoiceFormItem = YES; + } + } + } + + ORKSurveyCardHeaderView *cardHeaderView = (ORKSurveyCardHeaderView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:@(section).stringValue]; + + if (cardHeaderView == nil && title) { + cardHeaderView = [[ORKSurveyCardHeaderView alloc] initWithTitle:title + detailText:detailText + learnMoreView:learnMoreView + progressText:sectionProgressText + tagText:tagText + showBorder:([self formStep].cardViewStyle == ORKCardViewStyleBordered) + hasMultipleChoiceItem:hasMultipleChoiceFormItem]; + } + + return cardHeaderView; +} + +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { + ORKFormStep *formStep = [self formStep]; + if (formStep.footerText != nil && (section == (tableView.numberOfSections - 1))) { + return formStep.footerText; + } + + return nil; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + return nil; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return section == tableView.numberOfSections - 1 ? UITableViewAutomaticDimension : 10; +} + +#pragma mark ORKFormItemCellDelegate + +- (void)formItemCellDidBecomeFirstResponder:(ORKFormItemCell *)cell { + if (_currentFirstResponderCell) { + ORKFormItemTextFieldBasedCell *previousSelectedCell = (ORKFormItemTextFieldBasedCell*)_currentFirstResponderCell; + if (previousSelectedCell != nil && [previousSelectedCell respondsToSelector:@selector(removeEditingHighlight)]) { + [previousSelectedCell removeEditingHighlight]; + } + } + + _currentFirstResponderCell = cell; + NSIndexPath *path = [_tableView indexPathForCell:cell]; + if (path) { + [_tableContainer scrollCellVisible:cell animated:YES]; + } +} + +- (void)formItemCellDidResignFirstResponder:(ORKFormItemCell *)cell { + if (_currentFirstResponderCell == cell) { + _currentFirstResponderCell = nil; + } + + //determines if the table should autoscroll to the next section + NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; + NSNumber *sectionIndex = [NSNumber numberWithLong:indexPath.section]; + if (cell.isLastItem && [self shouldAutoScrollToNextSection:indexPath]) { + [self autoScrollToNextSection:indexPath]; + return; + } else if (cell.isLastItem && indexPath.section == (_sections.count - 1) && ![_answeredSections containsObject:sectionIndex]) { + [self.tableView scrollRectToVisible:[self.tableView convertRect:self.tableView.tableFooterView.bounds fromView:self.tableView.tableFooterView] animated:YES]; + } + + NSIndexPath *path = [_tableView indexPathForCell:cell]; + + if (path) { + ORKTableSection *sectionObject = (ORKTableSection *)_sections[path.section]; + if (path.row < sectionObject.items.count - 1) { + NSIndexPath *nextPath = [NSIndexPath indexPathForRow:(path.row + 1) inSection:path.section]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + [_tableView scrollToRowAtIndexPath:nextPath atScrollPosition:UITableViewScrollPositionTop animated:YES]; + }); + } + } + +} + +- (void)formItemCell:(ORKFormItemCell *)cell invalidInputAlertWithMessage:(NSString *)input { + [self showValidityAlertWithMessage:input]; +} + +- (void)formItemCell:(ORKFormItemCell *)cell invalidInputAlertWithTitle:(NSString *)title message:(NSString *)message { + [self showValidityAlertWithTitle:title message:message]; +} + +- (void)formItemCell:(ORKFormItemCell *)cell answerDidChangeTo:(id)answer { + if (answer && cell.formItem.identifier) { + [self setAnswer:answer forIdentifier:cell.formItem.identifier]; + } else if (answer == nil && cell.formItem.identifier) { + [self removeAnswerForIdentifier:cell.formItem.identifier]; + } + + _skipped = NO; + [self updateButtonStates]; + [self notifyDelegateOnResultChange]; + [self handleAutoScrollForNonKeyboardCell:cell]; + [self updateAnsweredSections]; +} + +- (BOOL)formItemCellShouldDismissKeyboard:(ORKFormItemCell *)cell { + if ([self didAutoScrollToNextItem:cell]) { + return NO; + } + return YES; +} + +#pragma mark ORKTableContainerViewDelegate + +- (UITableViewCell *)currentFirstResponderCellForTableContainerView:(ORKTableContainerView *)tableContainerView { + return _currentFirstResponderCell; +} + +#pragma mark UIStateRestoration + +static NSString *const _ORKSavedAnswersRestoreKey = @"savedAnswers"; +static NSString *const _ORKSavedAnswerDatesRestoreKey = @"savedAnswerDates"; +static NSString *const _ORKSavedSystemCalendarsRestoreKey = @"savedSystemCalendars"; +static NSString *const _ORKSavedSystemTimeZonesRestoreKey = @"savedSystemTimeZones"; +static NSString *const _ORKOriginalAnswersRestoreKey = @"originalAnswers"; +static NSString *const _ORKAnsweredSectionsRestoreKey = @"answeredSections"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_savedAnswers forKey:_ORKSavedAnswersRestoreKey]; + [coder encodeObject:_savedAnswerDates forKey:_ORKSavedAnswerDatesRestoreKey]; + [coder encodeObject:_savedSystemCalendars forKey:_ORKSavedSystemCalendarsRestoreKey]; + [coder encodeObject:_savedSystemTimeZones forKey:_ORKSavedSystemTimeZonesRestoreKey]; + [coder encodeObject:_originalAnswers forKey:_ORKOriginalAnswersRestoreKey]; + [coder encodeObject:_answeredSections forKey:_ORKAnsweredSectionsRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + _savedAnswers = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKSavedAnswersRestoreKey]; + _savedAnswerDates = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKSavedAnswerDatesRestoreKey]; + _savedSystemCalendars = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKSavedSystemCalendarsRestoreKey]; + _savedSystemTimeZones = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKSavedSystemTimeZonesRestoreKey]; + _originalAnswers = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKOriginalAnswersRestoreKey]; + _answeredSections = [coder decodeObjectOfClass:[NSMutableSet class] forKey:_ORKAnsweredSectionsRestoreKey]; +} + +#pragma mark Rotate + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + for (ORKFormItemCell *cell in _formItemCells) { + [cell setExpectedLayoutWidth:size.width]; + } +} + + +#pragma mark ORKTextChoiceCellGroupDelegate + +- (void)answerChangedForIndexPath:(NSIndexPath *)indexPath { + BOOL immediateNavigation = [self isStepImmediateNavigation]; + ORKTableSection *section = _sections[indexPath.section]; + ORKTableCellItem *cellItem = section.items[indexPath.row]; + id answer = ([cellItem.formItem.answerFormat isKindOfClass:[ORKBooleanAnswerFormat class]]) ? [section.textChoiceCellGroup answerForBoolean] : [section.textChoiceCellGroup answer]; + NSString *formItemIdentifier = cellItem.formItem.identifier; + if (answer && formItemIdentifier) { + [self setAnswer:answer forIdentifier:formItemIdentifier]; + } else if (answer == nil && formItemIdentifier) { + [self removeAnswerForIdentifier:formItemIdentifier]; + } + + _skipped = NO; + [self updateButtonStates]; + [self notifyDelegateOnResultChange]; + + ORKFormItemCell *cell = (ORKFormItemCell *)[_tableView cellForRowAtIndexPath:indexPath]; + [self handleAutoScrollForNonKeyboardCell:cell]; + [self updateAnsweredSections]; + + if (immediateNavigation) { + // Proceed as continueButton tapped + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + ORKSuppressPerformSelectorWarning( + [self.continueButtonItem.target performSelector:self.continueButtonItem.action withObject:self.continueButtonItem];); + }); + } +} + +- (void)tableViewCellHeightUpdated { + [_tableView reloadData]; +} + +#pragma mark - ORKChoiceOtherViewCellDelegate + +- (void)textChoiceOtherCellDidBecomeFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell { + _currentFirstResponderCell = choiceOtherViewCell; + NSIndexPath *path = [_tableView indexPathForCell:choiceOtherViewCell]; + if (path) { + [_tableContainer scrollCellVisible:choiceOtherViewCell animated:YES]; + } +} + +- (void)textChoiceOtherCellDidResignFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell { + if (_currentFirstResponderCell == choiceOtherViewCell) { + _currentFirstResponderCell = nil; + } + NSIndexPath *indexPath = [_tableView indexPathForCell:choiceOtherViewCell]; + ORKTableSection *section = _sections[indexPath.section]; + [section.textChoiceCellGroup textViewDidResignResponderForCellAtIndexPath:indexPath]; +} + +#pragma mark - ORKlearnMoreStepViewControllerDelegate + +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep { + [self.taskViewController learnMoreButtonPressedWithStep:learnMoreStep fromStepViewController:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Internal.h new file mode 100755 index 0000000..c8dc7a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormStepViewController_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKFormStepViewController () + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Private.h new file mode 100755 index 0000000..5821e73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStepViewController_Private.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKFormStepViewController () + +/** + Set the answer for the specified formItem identifier. + */ +- (void)setAnswer:(id)answer forIdentifier:(NSString *)identifier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep_Internal.h new file mode 100755 index 0000000..cb92428 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormStep_Internal.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKFormStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKFormStep () + +- (BOOL)isFormatImmediateNavigation; + +- (nullable ORKAnswerFormat *)impliedAnswerFormat; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.h new file mode 100755 index 0000000..0e68034 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAnswerTextView.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Text view for use in forms + */ +ORK_CLASS_AVAILABLE +@interface ORKFormTextView : ORKAnswerTextView + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.m new file mode 100755 index 0000000..0ffd96e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFormTextView.m @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKFormTextView.h" + + +@implementation ORKFormTextView + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.h new file mode 100755 index 0000000..08f53ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sam Falconer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import PDFKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKFreehandDrawingView; + +@protocol ORKFreehandDrawingViewDelegate + +- (void)freehandDrawingViewDidEditImage:(ORKFreehandDrawingView *)freehandDrawingView; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKFreehandDrawingView : UIView + +- (instancetype)initWithPDFView:(PDFView *)pdfView; + +@property (nonatomic, strong, nullable) UIColor *lineColor; +@property (nonatomic) CGFloat lineWidth; +@property (nonatomic, strong, nullable) UIColor *backgroundColor; + +/** + lineWidthVariation defines the max amount by which the line + width can vary (default 3pts). + + The exact amount of the variation is determined by the amount + of force applied on 3D touch capable devices or by the speed + of the stroke if 3D touch is not available. + + If the user is signing with an Apple Pencil, its force will be used. + */ +@property (nonatomic) CGFloat lineWidthVariation; + +@property (nonatomic, weak, nullable) id delegate; +@property (nonatomic, copy, nullable) NSArray *freehandDrawingPath; + +- (UIImage *)freehandDrawingImage; + +@property (nonatomic, readonly) BOOL freehandDrawingExists; + +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.m new file mode 100755 index 0000000..e4b2bfb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKFreehandDrawingView.m @@ -0,0 +1,510 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sam Falconer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKHelpers_Internal.h" +#import "ORKFreehandDrawingView.h" +#import + + +@protocol ORKFreehandDrawingGestureRecognizerDelegate + +- (void)gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; + +@end + + +@interface ORKFreehandDrawingGestureRecognizer : UIGestureRecognizer + +@property (nonatomic, weak) id eventDelegate; + +@end + +@implementation ORKFreehandDrawingGestureRecognizer + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + if (touches.count > 1 || self.numberOfTouches > 1) { + for (UITouch *touch in touches) { + [self ignoreTouch:touch forEvent:event]; + } + } else { + self.state = UIGestureRecognizerStateBegan; + [self.eventDelegate gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event]; + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self.eventDelegate gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + self.state = UIGestureRecognizerStateEnded; + [self.eventDelegate gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + self.state = UIGestureRecognizerStateFailed; +} + +- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + // Prioritize over scrollView's pan gesture recognizer and swipe gesture recognizer + if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] + || [otherGestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]]) { + return YES; + } + return NO; +} + +@end + + +static const CGFloat PointMinDistance = 5; +static const CGFloat PointMinDistanceSquared = PointMinDistance * PointMinDistance; +static const CGFloat DefaultLineWidth = 1; +static const CGFloat DefaultLineWidthVariation = 3; +static const CGFloat MaxPressureForStrokeVelocity = 9; +static const CGFloat LineWidthStepValue = 0.25f; + +@interface ORKFreehandDrawingView () { + CGPoint currentPoint; + CGPoint previousPoint1; + CGPoint previousPoint2; + // Pressure scale based on if using force or speed of stroke. + CGFloat minPressure; + CGFloat maxPressure; + // Time used only to calculate speed when force isn't available on the device. + NSTimeInterval previousTouchTime; + + PDFView *_pdfView; + BOOL _touchedOutside; +} + +@property (nonatomic, strong) UIBezierPath *currentPath; +@property (nonatomic, strong) PDFKitPlatformBezierPath *pdfCurrentPath; + +@property (nonatomic, strong) NSMutableArray *pathArray; +@property (nonatomic, strong) NSMutableArray *pdfPathArray; + +@property (nonatomic, strong) ORKFreehandDrawingGestureRecognizer *freehandDrawingGestureRecognizer; + +@end + + +@implementation ORKFreehandDrawingView { + NSLayoutConstraint *_heightConstraint; + NSLayoutConstraint *_widthConstraint; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _lineWidth = DefaultLineWidth; + _lineWidthVariation = DefaultLineWidthVariation; + [self makeFreehandDrawingGestureRecognizer]; + } + return self; +} + +- (instancetype)initWithPDFView:(PDFView *)pdfView { + self = [self init]; + if (self) { + _pdfView = pdfView; + } + return self; +} + +- (UIBezierPath *)pathWithRoundedStyle { + UIBezierPath *path = [UIBezierPath bezierPath]; + path.lineCapStyle = kCGLineCapRound; + path.lineWidth = self.lineWidth; + path.lineJoinStyle = kCGLineJoinRound; + + return path; +} + +- (void)makeFreehandDrawingGestureRecognizer { + if (_freehandDrawingGestureRecognizer == nil) { + _freehandDrawingGestureRecognizer = [ORKFreehandDrawingGestureRecognizer new]; + _freehandDrawingGestureRecognizer.eventDelegate = self; + [self addGestureRecognizer:_freehandDrawingGestureRecognizer]; + } +} + +- (UIColor *)lineColor { + if (_lineColor == nil) { + _lineColor = [UIColor blackColor]; + } + return _lineColor; +} + +- (NSMutableArray *)pathArray { + if (_pathArray == nil) { + _pathArray = [NSMutableArray new]; + } + return _pathArray; +} + +- (NSMutableArray *)pdfPathArray { + if (_pdfPathArray == nil) { + _pdfPathArray = [NSMutableArray new]; + } + return _pdfPathArray; +} + +#pragma mark Touch Event Handlers + +- (BOOL)isForceTouchAvailable { + static BOOL isAvailable; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + + isAvailable = NO; + if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && + self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) { + isAvailable = YES; + } + }); + + return isAvailable; +} + +- (BOOL)isTouchTypeStylus:(UITouch*)touch { + BOOL isStylus = NO; + + if ([touch respondsToSelector:@selector(type)] && touch.type == UITouchTypeStylus) { + isStylus = YES; + } + + return isStylus; +} + +- (void)gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; + + if (_pdfView) { + CGPoint pdfPoint = [_pdfView convertPoint:point toPage:_pdfView.currentPage]; + CGRect pageBounds = [_pdfView.currentPage boundsForBox:[_pdfView displayBox]]; + if ( CGRectContainsPoint(pageBounds, pdfPoint) ) { + _touchedOutside = NO; + self.currentPath = [self pathWithRoundedStyle]; + self.pdfCurrentPath = [self pathWithRoundedStyle]; + + // Trigger full redraw - whether there's a path has changed + [self setNeedsDisplay]; + + previousPoint1 = [touch previousLocationInView:self]; + previousPoint2 = [touch previousLocationInView:self]; + currentPoint = point; + + if ([self isForceTouchAvailable] || [self isTouchTypeStylus:touch]) { + // This is a scale based on true force on the screen. + minPressure = 0.f; + maxPressure = [touch maximumPossibleForce] / 2.f; + } + else { + // This is a scale based on the speed of the stroke + // (scaled down logarithmically). + minPressure = 0.f; + maxPressure = MaxPressureForStrokeVelocity; + previousTouchTime = touch.timestamp; + } + + [self.currentPath moveToPoint:currentPoint]; + + [self.pdfCurrentPath moveToPoint:[_pdfView convertPoint:currentPoint toPage:_pdfView.currentPage]]; + + [self.currentPath addArcWithCenter:currentPoint radius:0.1 startAngle:0.0 endAngle:2.0 * M_PI clockwise:YES]; + [self.pdfCurrentPath addArcWithCenter:[_pdfView convertPoint:currentPoint toPage:_pdfView.currentPage] radius:0.1 startAngle:0.0 endAngle:2.0 * M_PI clockwise:YES]; + + [self gestureTouchesMoved:touches withEvent:event]; + } + else { + _touchedOutside = YES; + } + } + else { + self.currentPath = [self pathWithRoundedStyle]; + + // Trigger full redraw - whether there's a path has changed + [self setNeedsDisplay]; + + previousPoint1 = [touch previousLocationInView:self]; + previousPoint2 = [touch previousLocationInView:self]; + currentPoint = point; + + if ([self isForceTouchAvailable] || [self isTouchTypeStylus:touch]) { + // This is a scale based on true force on the screen. + minPressure = 0.f; + maxPressure = [touch maximumPossibleForce] / 2.f; + } + else { + // This is a scale based on the speed of the stroke + // (scaled down logarithmically). + minPressure = 0.f; + maxPressure = MaxPressureForStrokeVelocity; + previousTouchTime = touch.timestamp; + } + + [self.currentPath moveToPoint:currentPoint]; + [self.currentPath addArcWithCenter:currentPoint radius:0.1 startAngle:0.0 endAngle:2.0 * M_PI clockwise:YES]; + [self gestureTouchesMoved:touches withEvent:event]; + } +} + +static CGPoint mmid_Point(CGPoint p1, CGPoint p2) { + return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); +} + +- (void)gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + UITouch *touch = [touches anyObject]; + CGPoint point = [touch locationInView:self]; + CGFloat previousLineWidth = self.currentPath.lineWidth; + + if (_pdfView) { + CGPoint pdfPoint = [_pdfView convertPoint:point toPage:_pdfView.currentPage]; + CGRect pageBounds = [_pdfView.currentPage boundsForBox:[_pdfView displayBox]]; + if ( CGRectContainsPoint(pageBounds, pdfPoint) && !_touchedOutside) { + // Point lies inside the bounds. + + CGFloat proposedLineWidth = [self getProposedLineWidthWithTouch:touch WithEvent:event]; + if (proposedLineWidth == CGFLOAT_MIN) { + return; + } + + // Only step the line width up and down by a set value. + // This prevents the line looking jagged, and adding excessive + // separate line segments. + if (ABS(previousLineWidth - proposedLineWidth) >= LineWidthStepValue) { + + CGFloat lineWidth = previousLineWidth; + + if (proposedLineWidth > previousLineWidth) { + lineWidth = previousLineWidth + LineWidthStepValue; + } + else if (proposedLineWidth < previousLineWidth) { + lineWidth = previousLineWidth - LineWidthStepValue; + } + + [self commitCurrentPath]; + + self.currentPath = [self pathWithRoundedStyle]; + self.pdfCurrentPath = [self pathWithRoundedStyle]; + self.currentPath.lineWidth = lineWidth; + self.pdfCurrentPath.lineWidth = lineWidth; + + CGPoint previousMid2 = mmid_Point(currentPoint, previousPoint1); + [self.currentPath moveToPoint:previousMid2]; + + [self.pdfCurrentPath moveToPoint:[_pdfView convertPoint:previousMid2 toPage:_pdfView.currentPage]]; + } + + CGPoint mid2 = [self getMid2FromDrawBoxWithTouch:touch]; + + [self.pdfCurrentPath addQuadCurveToPoint:[_pdfView convertPoint:mid2 toPage:_pdfView.currentPage] controlPoint:[_pdfView convertPoint:previousPoint1 toPage:_pdfView.currentPage]]; + } + else { + _touchedOutside = YES; + } + } + else { + + CGFloat proposedLineWidth = [self getProposedLineWidthWithTouch:touch WithEvent:event]; + + // Only step the line width up and down by a set value. + // This prevents the line looking jagged, and adding excessive + // separate line segments. + if (ABS(previousLineWidth - proposedLineWidth) >= LineWidthStepValue) { + + CGFloat lineWidth = previousLineWidth; + + if (proposedLineWidth > previousLineWidth) { + lineWidth = previousLineWidth + LineWidthStepValue; + } + else if (proposedLineWidth < previousLineWidth) { + lineWidth = previousLineWidth - LineWidthStepValue; + } + + [self commitCurrentPath]; + + self.currentPath = [self pathWithRoundedStyle]; + self.currentPath.lineWidth = lineWidth; + + CGPoint previousMid2 = mmid_Point(currentPoint, previousPoint1); + [self.currentPath moveToPoint:previousMid2]; + } + CGPoint _ __attribute__((unused)) = [self getMid2FromDrawBoxWithTouch:touch]; + } +} + +- (CGFloat)getProposedLineWidthWithTouch:(UITouch *)touch WithEvent:(UIEvent *)event { + + CGPoint point = [touch locationInView:self]; + //check if the point is farther than min dist from previous + CGFloat dx = point.x - currentPoint.x; + CGFloat dy = point.y - currentPoint.y; + + CGFloat distanceSquared = (dx * dx + dy * dy); + + if (distanceSquared < PointMinDistanceSquared) { + return CGFLOAT_MIN; + } + // Will be assigned a real value on all devices. + CGFloat pressure; + if ([self isForceTouchAvailable] || [self isTouchTypeStylus:touch]) { + // If the device supports Force Touch, or is using a stylus, use it. + pressure = [touch force]; + } else { + // If not, use a heuristic based on the speed of + // the stroke. Scale this speed logarithmically to + // require very slow touches to max out the line width. + + // This value can become negative because of how it is + // inverted. It will be clamped right below. + pressure = maxPressure - logf((sqrt(distanceSquared) / + MAX(0.0001, event.timestamp - previousTouchTime))); + previousTouchTime = event.timestamp; + } + + // Clamp the pressure value to between the allowed min and max. + pressure = MAX(minPressure, pressure); + pressure = MIN(maxPressure, pressure); + + return ((pressure - minPressure) * self.lineWidthVariation / (maxPressure - minPressure)) + self.lineWidth; +} + +- (CGPoint)getMid2FromDrawBoxWithTouch:(UITouch *)touch { + previousPoint2 = previousPoint1; + previousPoint1 = [touch previousLocationInView:self]; + currentPoint = [touch locationInView:self]; + + CGPoint mid1 = mmid_Point(previousPoint1, previousPoint2); + CGPoint mid2 = mmid_Point(currentPoint, previousPoint1); + + UIBezierPath *subPath = [UIBezierPath bezierPath]; + [subPath moveToPoint:mid1]; + [subPath addQuadCurveToPoint:mid2 controlPoint:previousPoint1]; + CGRect bounds = CGPathGetBoundingBox(subPath.CGPath); + + [self.currentPath addQuadCurveToPoint:mid2 controlPoint:previousPoint1]; + + + CGRect drawBox = bounds; + drawBox.origin.x -= self.currentPath.lineWidth * 2.0; + drawBox.origin.y -= self.currentPath.lineWidth * 2.0; + drawBox.size.width += self.currentPath.lineWidth * 4.0; + drawBox.size.height += self.currentPath.lineWidth * 4.0; + + [self setNeedsDisplayInRect:drawBox]; + return mid2; +} + +- (void)gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self commitCurrentPath]; +} + +- (void)commitCurrentPath { + CGRect rect = self.currentPath.bounds; + if (CGSizeEqualToSize(rect.size, CGSizeZero)) { + return; + } + + [self.pathArray addObject:self.currentPath]; + if (_pdfView) { + [self.pdfPathArray addObject:self.pdfCurrentPath]; + } + [self.delegate freehandDrawingViewDidEditImage:self]; +} + +- (void)drawRect:(CGRect)rect { + if (_backgroundColor == nil) { + _backgroundColor = [UIColor whiteColor]; + } + [_backgroundColor setFill]; + CGContextFillRect(UIGraphicsGetCurrentContext(), rect); + + for (UIBezierPath *path in self.pathArray) { + [self.lineColor setStroke]; + [path stroke]; + } + + [self.lineColor setStroke]; + [self.currentPath stroke]; +} + +- (NSArray *)freehandDrawingPath { + return _pdfView ? [self.pdfPathArray copy] : [self.pathArray copy]; +} + +- (UIImage *)freehandDrawingImage { + CGSize imageContextSize; + imageContextSize = (self.bounds.size.width == 0 || self.bounds.size.height == 0) ? CGSizeMake(200, 200) : + self.bounds.size; + UIGraphicsBeginImageContext(imageContextSize); + + for (UIBezierPath *path in self.pathArray) { + [self.lineColor setStroke]; + [path stroke]; + } + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (BOOL)freehandDrawingExists { + return self.pathArray.count > 0; +} + +- (void)clear { + if (self.pathArray.count > 0) { + if (self.currentPath != nil) { + self.currentPath = [self pathWithRoundedStyle]; + } + + [self.pathArray removeAllObjects]; + [self setNeedsDisplayInRect:self.bounds]; + } + if (_pdfView) { + if (self.pdfPathArray.count > 0) { + if (self.pdfCurrentPath != nil) { + self.pdfCurrentPath = [self pathWithRoundedStyle]; + } + [self.pdfPathArray removeAllObjects]; + } + } +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.h new file mode 100755 index 0000000..28e609a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2017, Chris Ortman, University of Iowa, All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +#pragma mark - ORKHTMLPDFWriter Interface + +@interface ORKHTMLPDFPageRenderer : UIPrintPageRenderer + +@property (nonatomic) UIEdgeInsets pageMargins; + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.m new file mode 100755 index 0000000..cd49355 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFPageRenderer.m @@ -0,0 +1,65 @@ +/* + Copyright (c) 2017, Chris Ortman, University of Iowa, All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKErrors.h" +#import "ORKHelpers_Internal.h" +#import "ORKDefines.h" +#import "ORKHTMLPDFPageRenderer.h" + + +@implementation ORKHTMLPDFPageRenderer + +- (CGRect)paperRect { + return UIGraphicsGetPDFContextBounds(); +} + +- (CGRect)printableRect { + return UIEdgeInsetsInsetRect([self paperRect], _pageMargins); +} + +- (void)drawFooterForPageAtIndex:(NSInteger)pageIndex + inRect:(CGRect)footerRect { + NSString *footer = [NSString stringWithFormat:ORKLocalizedString(@"CONSENT_PAGE_NUMBER_FORMAT", nil), (long)(pageIndex + 1), (long)[self numberOfPages]]; + + if (footer) { + UIFont *font = [UIFont fontWithName:@"Helvetica" size:12]; + CGSize size = [footer sizeWithAttributes:@{ NSFontAttributeName: font}]; + + // Center Text + CGFloat drawX = (CGRectGetWidth(footerRect) / 2) + footerRect.origin.x - (size.width / 2); + CGFloat drawY = footerRect.origin.y + (footerRect.size.height / 2) - (size.height / 2); + CGPoint drawPoint = CGPointMake(drawX, drawY); + + [footer drawAtPoint:drawPoint withAttributes:@{ NSFontAttributeName: font}]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.h new file mode 100755 index 0000000..0a417d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + +@class ORKHTMLPDFPageRenderer; + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKHTMLPDFWriter : NSObject + +@property (nonatomic, nullable) ORKHTMLPDFPageRenderer *printRenderer; + +- (void)writePDFFromHTML:(NSString *)html completionBlock:(void (^)(NSData *data, NSError *error))completionBlock; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.m new file mode 100755 index 0000000..7482f85 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHTMLPDFWriter.m @@ -0,0 +1,174 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHTMLPDFWriter.h" +#import "ORKHTMLPDFPageRenderer.h" +#import + +#import "ORKHelpers_Internal.h" + + +#define ORKPPI 72 +#define ORKSizeMakeWithPPI(width, height) CGSizeMake(width * ORKPPI, height * ORKPPI) + +static const CGFloat A4Width = 8.27; +static const CGFloat A4Height = 11.69; +static const CGFloat LetterWidth = 8.5f; +static const CGFloat LetterHeight = 11.0f; + + + + + +@interface ORKHTMLPDFWriter () { + id _selfRetain; +} + +@property (nonatomic) CGSize pageSize; +@property (nonatomic) UIEdgeInsets pageMargins; +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, strong) NSData *data; +@property (nonatomic, copy) NSError *error; +@property (nonatomic, copy) void (^completionBlock)(NSData *data, NSError *error); + +@end + + +@implementation ORKHTMLPDFWriter + +static const CGFloat HeaderHeight = 25.0; +static const CGFloat FooterHeight = 25.0; +static const CGFloat PageEdge = 72.0 / 4; + +- (void)writePDFFromHTML:(NSString *)html completionBlock:(void (^)(NSData *data, NSError *error))completionBlock { + + _pageMargins = UIEdgeInsetsMake(PageEdge, PageEdge, PageEdge, PageEdge); + _pageSize = [ORKHTMLPDFWriter defaultPageSize]; + + _data = nil; + _error = nil; + + WKWebViewConfiguration *webViewConfiguration = [WKWebViewConfiguration new]; + WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfiguration]; + webView.navigationDelegate = self; + self.webView = webView; + [self.webView loadHTMLString:html baseURL:ORKCreateRandomBaseURL()]; + + _selfRetain = self; + self.completionBlock = completionBlock; +} + +#pragma mark - private + +- (void)timeout { + [self savePDF]; +} + +- (void)savePDF { + if (!self.webView) { + return; + } + + UIPrintFormatter *formatter = self.webView.viewPrintFormatter; + + ORKHTMLPDFPageRenderer *renderer = self.printRenderer; + if (renderer == nil) { + renderer = [[ORKHTMLPDFPageRenderer alloc] init]; + renderer.pageMargins = self.pageMargins; + renderer.footerHeight = FooterHeight; + renderer.headerHeight = HeaderHeight; + + } + + [renderer addPrintFormatter:formatter startingAtPageAtIndex:0]; + + NSMutableData *currentReportData = [NSMutableData data]; + + CGSize pageSize = [self pageSize]; + CGRect pageRect = CGRectMake(0, 0, pageSize.width, pageSize.height); + + UIGraphicsBeginPDFContextToData(currentReportData, pageRect, @{}); + + [renderer prepareForDrawingPages:NSMakeRange(0, 1)]; + + NSInteger pages = [renderer numberOfPages]; + + for (NSInteger i = 0; i < pages; i++) { + UIGraphicsBeginPDFPage(); + [renderer drawPageAtIndex:i inRect:renderer.printableRect]; + } + + UIGraphicsEndPDFContext(); + + _data = currentReportData; + + self.webView = nil; + + self.completionBlock(_data, nil); + _selfRetain = nil; +} + ++ (CGSize)defaultPageSize { + NSLocale *locale = [NSLocale currentLocale]; + BOOL useMetric = [[locale objectForKey:NSLocaleUsesMetricSystem] boolValue]; + CGSize pageSize = (useMetric ? ORKSizeMakeWithPPI(A4Width, A4Height) : ORKSizeMakeWithPPI(LetterWidth, LetterHeight)); // A4 and Letter + + return pageSize; +} + +#pragma mark - WKNavigationDelegate + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + [webView evaluateJavaScript:@"document.readyState" completionHandler:^(id _Nullable result, NSError * _Nullable error) { + NSString *readyState = [result isKindOfClass:NSString.class] ? result : [NSString new]; + BOOL complete = [readyState isEqualToString:@"complete"]; + + [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeout) object:nil]; + + if (complete) { + [self savePDF]; + } else { + [self performSelector:@selector(timeout) withObject:nil afterDelay:1.0f]; + } + }]; +} + +- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error { + [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeout) object:nil]; + + _error = error; + self.webView = nil; + + self.completionBlock(nil, error); + _selfRetain = nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.h new file mode 100755 index 0000000..8ed4ab3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Primary title for any step view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKHeadlineLabel : ORKLabel + +@property (nonatomic, assign) BOOL useSurveyMode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.m new file mode 100755 index 0000000..07e0c69 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeadlineLabel.m @@ -0,0 +1,75 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHeadlineLabel.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKHeadlineLabel + ++ (UIFont *)defaultFontInSurveyMode:(BOOL)surveyMode { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + const CGFloat defaultHeadlineSize = 17; + + CGFloat fontSize = [[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue] - defaultHeadlineSize + ORKGetMetricForWindow(surveyMode ? ORKScreenMetricFontSizeSurveyHeadline : ORKScreenMetricFontSizeHeadline, nil); + CGFloat maxFontSize = ORKGetMetricForWindow(surveyMode ? ORKScreenMetricMaxFontSizeSurveyHeadline : ORKScreenMetricMaxFontSizeHeadline, nil); + + return ORKLightFontWithSize(MIN(maxFontSize, fontSize)); +} + ++ (UIFont *)defaultFont { + return [self defaultFontInSurveyMode:NO]; +} + +- (UIFont *)defaultFont { + return [[self class] defaultFontInSurveyMode:_useSurveyMode]; +} + +- (void)setUseSurveyMode:(BOOL)useSurveyMode { + _useSurveyMode = useSurveyMode; + [self updateAppearance]; +} + +// Nasty override (hack) +- (void)updateAppearance { + self.font = [self defaultFont]; + [self invalidateIntrinsicContentSize]; +} + +#pragma mark Accessibility + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitHeader; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.h new file mode 100755 index 0000000..e2afa23 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.h @@ -0,0 +1,218 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import HealthKit; +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *ORKBiologicalSexIdentifier NS_STRING_ENUM; + +ORK_EXTERN ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierFemale; +ORK_EXTERN ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierMale; +ORK_EXTERN ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierOther; + +typedef NSString *ORKBloodTypeIdentifier NS_STRING_ENUM; + +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierAPositive; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierANegative; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierBPositive; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierBNegative; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierABPositive; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierABNegative; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierOPositive; +ORK_EXTERN ORKBloodTypeIdentifier const ORKBloodTypeIdentifierONegative; + + +/** + The `ORKHealthKitCharacteristicTypeAnswerFormat` class represents an answer format that lets participants enter values that correspond to a HealthKit characteristic type. + + The actual UI used for collecting data with this answer format depends on the HealthKit type being collected. + The default value displayed in the UI is the most recent value received from HealthKit, if such a value exists. + When a step or item is presented using this answer format, authorization is requested unless the property + `shouldRequestAuthorization` is set to `NO`. + + You can use the HealthKit characteristic answer format to let users autofill information, such as their blood type or date of birth. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthKitCharacteristicTypeAnswerFormat : ORKAnswerFormat + +/** + Returns a new answer format for the specified HealthKit characteristic type. + + @param characteristicType The characteristic type to collect. + + @return A new HealthKit characteristic type answer format instance. + */ ++ (instancetype)answerFormatWithCharacteristicType:(HKCharacteristicType *)characteristicType; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized HealthKit characteristic type answer format using the specified characteristic type. + + This method is the designated initializer. + + @param characteristicType The characteristic type to collect. + + @return An initialized HealthKit characteristic type answer format. + */ +- (instancetype)initWithCharacteristicType:(HKCharacteristicType *)characteristicType NS_DESIGNATED_INITIALIZER; + +/** + Should authorization be requested for the associated HealthKit data type. Default = `YES`. + */ +@property (nonatomic) BOOL shouldRequestAuthorization; + +/** + The HealthKit characteristic type to be collected by this answer format. (read-only) + */ +@property (nonatomic, copy, readonly) HKCharacteristicType *characteristicType; + +/** + The default date shown by the date picker. + + Only used for the `HKCharacteristicTypeIdentifierDateOfBirth` characteristic type. The date is + displayed in the user's time zone. If you set this property to `nil`, the date picker will default + to the date representing 35 years before the current date. + */ +@property (nonatomic, strong, nullable) NSDate *defaultDate; + +/** + The minimum date that is allowed by the date picker. + + Only used for the `HKCharacteristicTypeIdentifierDateOfBirth` characteristic type. If you set this + property to `nil`, the date picker will use the date representing 150 years before the curent date + as its minimum date. + */ +@property (nonatomic, strong, nullable) NSDate *minimumDate; + +/** + The maximum date that is allowed by the date picker. + + Only used for the `HKCharacteristicTypeIdentifierDateOfBirth` characteristic type. If you set this + property to `nil`, the date picker will use the date representing 1 day after curent date as its + maximum date + */ + +@property (nonatomic, strong, nullable) NSDate *maximumDate; + +/** + The calendar used by the date picker. + + Only used for the `HKCharacteristicTypeIdentifierDateOfBirth` characteristic type. If you set this + property to `nil`, the date picker will use the default calendar for the current locale. + */ +@property (nonatomic, strong, nullable) NSCalendar *calendar; + +@end + + +/** + The `ORKHealthKitQuantityTypeAnswerFormat` class represents an answer format that lets participants enter values that correspond to a HealthKit quantity type, such as systolic blood pressure. + + The actual UI used for collecting data with this answer format depends on the HealthKit type being collected. + The default value in the UI is the most recent value received from HealthKit, if such a value exists. + When a step or item is presented using this answer format, authorization is requested unless the property + `shouldRequestAuthorization` is set to `NO`. + + You can use the HealthKit quantity type answer format to let users autofill values such as their weight with the most + recent data from HealthKit. + */ +ORK_CLASS_AVAILABLE +@interface ORKHealthKitQuantityTypeAnswerFormat : ORKAnswerFormat + + +/** + Returns a new HealthKit quantity answer format with the specified quantity type. + + @param quantityType The HealthKit quantity type to collect. + @param unit The unit used to describe the quantity. If the value of this parameter is `nil`, the default HealthKit unit is used, when available. + @param style The numeric answer style to use when collecting this value. + + @return A HealthKit quantity answer format instance. + */ ++ (instancetype)answerFormatWithQuantityType:(HKQuantityType *)quantityType unit:(nullable HKUnit *)unit style:(ORKNumericAnswerStyle)style; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized HealthKit quantity answer format using the specified quantity type, unit, and numeric answer style. + + This method is the designated initializer. + + @param quantityType The HealthKit quantity type to collect. + @param unit The unit used to describe the quantity. If the value of this parameter is `nil`, the default HealthKit unit is used, when available. + @param style The numeric answer style to use when collecting this value. + + @return An initialized HealthKit quantity answer format. + */ +- (instancetype)initWithQuantityType:(HKQuantityType *)quantityType unit:(nullable HKUnit *)unit style:(ORKNumericAnswerStyle)style NS_DESIGNATED_INITIALIZER; + +/** + Should authorization be requested for the associated HealthKit data type. Default = `YES`. + */ +@property (nonatomic) BOOL shouldRequestAuthorization; + +/** + The HealthKit quantity type to collect. (read-only) + */ +@property (nonatomic, copy, readonly) HKQuantityType *quantityType; + +/** + The HealthKit unit in which to collect the answer. (read-only) + + The unit is displayed when the user is entering data, and is also +included in the question result generated by form items or question steps + that use this answer format. + */ +@property (nonatomic, strong, readonly, nullable) HKUnit *unit; + +/** + The numeric answer style. (read-only) + */ +@property (nonatomic, readonly) ORKNumericAnswerStyle numericAnswerStyle; + +@end + +@interface HKUnit (ORKLocalized) + +/** + Returns the localized string for the unit (if available) + */ +- (NSString *)localizedUnitString; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.m new file mode 100755 index 0000000..3e9a84a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthAnswerFormat.m @@ -0,0 +1,422 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHealthAnswerFormat.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKHelpers_Internal.h" + +#import "ORKQuestionResult_Private.h" +#import "ORKResult.h" + + +#pragma mark - ORKHealthAnswerFormat + +ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierFemale = @"HKBiologicalSexFemale"; +ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierMale = @"HKBiologicalSexMale"; +ORKBiologicalSexIdentifier const ORKBiologicalSexIdentifierOther = @"HKBiologicalSexOther"; + +NSString *ORKHKBiologicalSexString(HKBiologicalSex biologicalSex) { + NSString *string = nil; + switch (biologicalSex) { + case HKBiologicalSexFemale: string = ORKBiologicalSexIdentifierFemale; break; + case HKBiologicalSexMale: string = ORKBiologicalSexIdentifierMale; break; + case HKBiologicalSexOther: string = ORKBiologicalSexIdentifierOther; break; + case HKBiologicalSexNotSet: break; + } + return string; +} + +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierAPositive = @"HKBloodTypeAPositive"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierANegative = @"HKBloodTypeANegative"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierBPositive = @"HKBloodTypeBPositive"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierBNegative = @"HKBloodTypeBNegative"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierABPositive = @"HKBloodTypeABPositive"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierABNegative = @"HKBloodTypeABNegative"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierOPositive = @"HKBloodTypeOPositive"; +ORKBloodTypeIdentifier const ORKBloodTypeIdentifierONegative = @"HKBloodTypeONegative"; + +NSString *ORKHKBloodTypeString(HKBloodType bloodType) { + NSString *string = nil; + switch (bloodType) { + case HKBloodTypeAPositive: string = ORKBloodTypeIdentifierAPositive; break; + case HKBloodTypeANegative: string = ORKBloodTypeIdentifierANegative; break; + case HKBloodTypeBPositive: string = ORKBloodTypeIdentifierBPositive; break; + case HKBloodTypeBNegative: string = ORKBloodTypeIdentifierBNegative; break; + case HKBloodTypeABPositive: string = ORKBloodTypeIdentifierABPositive; break; + case HKBloodTypeABNegative: string = ORKBloodTypeIdentifierABNegative; break; + case HKBloodTypeOPositive: string = ORKBloodTypeIdentifierOPositive; break; + case HKBloodTypeONegative: string = ORKBloodTypeIdentifierONegative; break; + case HKBloodTypeNotSet: break; + } + return string; +} + +@interface ORKHealthKitCharacteristicTypeAnswerFormat () + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +@implementation ORKHealthKitCharacteristicTypeAnswerFormat { + ORKAnswerFormat *_impliedAnswerFormat; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (BOOL)isHealthKitAnswerFormat { + return YES; +} + +- (ORKQuestionType)questionType { + return [[self impliedAnswerFormat] questionType]; +} + +- (HKObjectType *)healthKitObjectType { + return _characteristicType; +} + +- (HKObjectType *)healthKitObjectTypeForAuthorization { + if (self.shouldRequestAuthorization) { + return [self healthKitObjectType]; + } + else { + return nil; + } +} + +- (Class)questionResultClass { + return [[self impliedAnswerFormat] questionResultClass]; +} + ++ (instancetype)answerFormatWithCharacteristicType:(HKCharacteristicType *)characteristicType { + ORKHealthKitCharacteristicTypeAnswerFormat *format = [[ORKHealthKitCharacteristicTypeAnswerFormat alloc] initWithCharacteristicType:characteristicType]; + return format; +} + +- (instancetype)initWithCharacteristicType:(HKCharacteristicType *)characteristicType { + self = [super init]; + if (self) { + // Characteristic types are immutable, so this should be equivalent to -copy + _characteristicType = characteristicType; + _shouldRequestAuthorization = YES; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.characteristicType, castObject.characteristicType) && + ORKEqualObjects(self.defaultDate, castObject.defaultDate) && + ORKEqualObjects(self.minimumDate, castObject.minimumDate) && + ORKEqualObjects(self.maximumDate, castObject.maximumDate) && + ORKEqualObjects(self.calendar, castObject.calendar)); +} + +- (NSUInteger)hash { + return super.hash ^ self.characteristicType.hash ^ self.defaultDate.hash ^ self.minimumDate.hash ^ self.maximumDate.hash ^ self.calendar.hash; +} + +// The bare answer format implied by the quantityType or characteristicType. +// This may be ORKTextChoiceAnswerFormat, ORKNumericAnswerFormat, or ORKDateAnswerFormat. +- (ORKAnswerFormat *)impliedAnswerFormat { + if (_impliedAnswerFormat) { + return _impliedAnswerFormat; + } + + if (_characteristicType) { + NSString *identifier = [_characteristicType identifier]; + if ([identifier isEqualToString:HKCharacteristicTypeIdentifierBiologicalSex]) { + NSArray *options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_FEMALE", nil) value: ORKHKBiologicalSexString(HKBiologicalSexFemale)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_MALE", nil) value:ORKHKBiologicalSexString(HKBiologicalSexMale)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_OTHER", nil) value:ORKHKBiologicalSexString(HKBiologicalSexOther)] + ]; + ORKTextChoiceAnswerFormat *format = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:options]; + _impliedAnswerFormat = format; + + } else if ([identifier isEqualToString:HKCharacteristicTypeIdentifierBloodType]) { + NSArray *options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A+", nil) value:ORKHKBloodTypeString(HKBloodTypeAPositive)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A-", nil) value:ORKHKBloodTypeString(HKBloodTypeANegative)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B+", nil) value:ORKHKBloodTypeString(HKBloodTypeBPositive)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B-", nil) value:ORKHKBloodTypeString(HKBloodTypeBNegative)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB+", nil) value:ORKHKBloodTypeString(HKBloodTypeABPositive)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB-", nil) value:ORKHKBloodTypeString(HKBloodTypeABNegative)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O+", nil) value:ORKHKBloodTypeString(HKBloodTypeOPositive)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O-", nil) value:ORKHKBloodTypeString(HKBloodTypeONegative)] + ]; + ORKValuePickerAnswerFormat *format = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options]; + _impliedAnswerFormat = format; + + } else if ([identifier isEqualToString:HKCharacteristicTypeIdentifierDateOfBirth]) { + NSCalendar *calendar = _calendar ? : [NSCalendar currentCalendar]; + NSDate *now = [NSDate date]; + NSDate *defaultDate = _defaultDate ? : [calendar dateByAddingUnit:NSCalendarUnitYear value:-35 toDate:now options:0]; + NSDate *minimumDate = _minimumDate ? : [calendar dateByAddingUnit:NSCalendarUnitYear value:-150 toDate:now options:0]; + NSDate *maximumDate = _maximumDate ? : [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:now options:0]; + + ORKDateAnswerFormat *format = [ORKDateAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate + minimumDate:minimumDate + maximumDate:maximumDate + calendar:calendar]; + _impliedAnswerFormat = format; + } else if ([identifier isEqualToString:HKCharacteristicTypeIdentifierFitzpatrickSkinType]) { + NSArray *options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_I", nil) value:@(HKFitzpatrickSkinTypeI)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_II", nil) value:@(HKFitzpatrickSkinTypeII)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_III", nil) value:@(HKFitzpatrickSkinTypeIII)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_IV", nil) value:@(HKFitzpatrickSkinTypeIV)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_V", nil) value:@(HKFitzpatrickSkinTypeV)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_VI", nil) value:@(HKFitzpatrickSkinTypeVI)], + ]; + ORKValuePickerAnswerFormat *format = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options]; + _impliedAnswerFormat = format; + } else if (ORK_IOS_10_WATCHOS_3_AVAILABLE && [identifier isEqualToString:HKCharacteristicTypeIdentifierWheelchairUse]) { + ORKBooleanAnswerFormat *boolAnswerFormat = [ORKAnswerFormat booleanAnswerFormat]; + _impliedAnswerFormat = boolAnswerFormat.impliedAnswerFormat; + } + } + + NSAssert(_impliedAnswerFormat, @"_impliedAnswerFormat should have been set"); + + return _impliedAnswerFormat; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, characteristicType, HKCharacteristicType); + ORK_DECODE_OBJ_CLASS(aDecoder, defaultDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, minimumDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, maximumDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, calendar, NSCalendar); + ORK_DECODE_BOOL(aDecoder, shouldRequestAuthorization); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, characteristicType); + ORK_ENCODE_OBJ(aCoder, defaultDate); + ORK_ENCODE_OBJ(aCoder, minimumDate); + ORK_ENCODE_OBJ(aCoder, maximumDate); + ORK_ENCODE_OBJ(aCoder, calendar); + ORK_ENCODE_BOOL(aCoder, shouldRequestAuthorization); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + + +@interface ORKHealthKitQuantityTypeAnswerFormat () + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +@implementation ORKHealthKitQuantityTypeAnswerFormat { + ORKAnswerFormat *_impliedAnswerFormat; + HKUnit *_userUnit; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (BOOL)isHealthKitAnswerFormat { + return YES; +} + +- (HKObjectType *)healthKitObjectType { + return _quantityType; +} + +- (HKObjectType *)healthKitObjectTypeForAuthorization { + if (self.shouldRequestAuthorization) { + return [self healthKitObjectType]; + } + else { + return nil; + } +} + +- (ORKQuestionType)questionType { + return [[self impliedAnswerFormat] questionType]; +} + +- (Class)questionResultClass { + return [[self impliedAnswerFormat] questionResultClass]; +} + ++ (instancetype)answerFormatWithQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit style:(ORKNumericAnswerStyle)style { + ORKHealthKitQuantityTypeAnswerFormat *format = [[ORKHealthKitQuantityTypeAnswerFormat alloc] initWithQuantityType:quantityType unit:unit style:style]; + return format; +} + +- (instancetype)initWithQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit style:(ORKNumericAnswerStyle)style { + self = [super init]; + if (self) { + // Quantity type and unit are immutable, so this should be equivalent to -copy + _quantityType = quantityType; + _unit = unit; + _numericAnswerStyle = style; + _shouldRequestAuthorization = YES; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.quantityType, castObject.quantityType) && + ORKEqualObjects(self.unit, castObject.unit) && + (_numericAnswerStyle == castObject.numericAnswerStyle)); +} + +- (NSUInteger)hash { + return super.hash ^ self.quantityType.hash ^ self.unit.hash ^ _numericAnswerStyle; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + if (_impliedAnswerFormat) { + return _impliedAnswerFormat; + } + + if ([_quantityType.identifier isEqualToString:HKQuantityTypeIdentifierHeight]) { + ORKHeightAnswerFormat *format = [ORKHeightAnswerFormat heightAnswerFormat]; + _impliedAnswerFormat = format; + _unit = [HKUnit meterUnitWithMetricPrefix:(HKMetricPrefixCenti)]; + } else if ([_quantityType.identifier isEqualToString:HKQuantityTypeIdentifierBodyMass]) { + ORKWeightAnswerFormat *format = [ORKWeightAnswerFormat weightAnswerFormat]; + _impliedAnswerFormat = format; + _unit = [HKUnit gramUnitWithMetricPrefix:(HKMetricPrefixKilo)]; + } else { + ORKNumericAnswerFormat *format = nil; + HKUnit *unit = [self healthKitUserUnit]; + if (_numericAnswerStyle == ORKNumericAnswerStyleDecimal) { + format = [ORKNumericAnswerFormat decimalAnswerFormatWithUnit:[unit localizedUnitString]]; + } else { + format = [ORKNumericAnswerFormat integerAnswerFormatWithUnit:[unit localizedUnitString]]; + } + _impliedAnswerFormat = format; + } + + return _impliedAnswerFormat; +} + +- (HKUnit *)healthKitUnit { + return _unit; +} + +- (HKUnit *)healthKitUserUnit { + return _unit ? : _userUnit; +} + +- (void)setHealthKitUserUnit:(HKUnit *)unit { + if (_unit == nil && _userUnit != unit) { + _userUnit = unit; + + // Clear the implied answer format + _impliedAnswerFormat = nil; + } +} + +- (id)resultWithIdentifier:(NSString *)identifier answer:(id)answer { + id result = [super resultWithIdentifier:identifier answer:answer]; + if ([result isKindOfClass:[ORKNumericQuestionResult class]]) { + ORKNumericQuestionResult *questionResult = (ORKNumericQuestionResult *)result; + if (questionResult.unit == nil) { + // The unit should *not* be localized. + questionResult.unit = [self healthKitUserUnit].unitString; + } + } + return result; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, quantityType, HKQuantityType); + ORK_DECODE_OBJ_CLASS(aDecoder, unit, HKUnit); + ORK_DECODE_ENUM(aDecoder, numericAnswerStyle); + ORK_DECODE_BOOL(aDecoder, shouldRequestAuthorization); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, quantityType); + ORK_ENCODE_ENUM(aCoder, numericAnswerStyle); + ORK_ENCODE_OBJ(aCoder, unit); + ORK_ENCODE_BOOL(aCoder, shouldRequestAuthorization); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end + + +@implementation HKUnit (ORKLocalized) + +- (NSString *)localizedUnitString { + NSUnit *unit = [[NSUnit alloc] initWithSymbol:self.unitString]; + if (unit != nil) { + NSMeasurementFormatter *formatter = [[NSMeasurementFormatter alloc] init]; + formatter.unitOptions = NSMeasurementFormatterUnitOptionsProvidedUnit; + return [formatter stringFromUnit:unit]; + } + return self.unitString; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.h new file mode 100755 index 0000000..b70c31c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKOperation.h" + + +@class ORKDataCollectionManager; +@class ORKCollector; +@protocol ORKHealthCollectable; + +/** + Operation for extracting and preparing HK data for upload. This operation + runs on the specified study / data type combo until there is no more HK data available, + or until file protection kicks in, stopping further preparation. + */ +@interface ORKHealthSampleQueryOperation : ORKOperation + +- (instancetype)initWithCollector:(ORKCollector *)collector mananger:(ORKDataCollectionManager *)manager; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.m new file mode 100755 index 0000000..09535ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHealthSampleQueryOperation.m @@ -0,0 +1,247 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHealthSampleQueryOperation.h" +#import "ORKCollector.h" +#import "ORKHelpers_Internal.h" +#import "ORKCollector_Internal.h" +#import "ORKDataCollectionManager_Internal.h" + + +static NSUInteger const QueryLimitSize = 1000; + +@implementation ORKHealthSampleQueryOperation { + // All of these are strong references created at init time + ORKCollector *_collector; + __weak ORKDataCollectionManager *_manager; + HKQueryAnchor *_currentAnchor; + dispatch_semaphore_t _sem; +} + + +// Run this only on the manager work queue +- (BOOL)_shouldContinue { + BOOL shouldContinue = YES; + + if (!_manager || !_collector) { + shouldContinue = NO; + } + if (![_manager.collectors containsObject:_collector]) { + shouldContinue = NO; + } + + return shouldContinue; +} + +- (instancetype)initWithCollector:(ORKCollector *)collector mananger:(ORKDataCollectionManager *)manager { + NSParameterAssert(collector); + NSParameterAssert(manager); + + self = [super init]; + if (self) { + _collector = collector; + _manager = manager; + _currentAnchor = nil; + _sem = dispatch_semaphore_create(0); + + self.startBlock = ^void(ORKOperation* operation) { + [(ORKHealthSampleQueryOperation*)operation doNextQuery]; + }; + + } + return self; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@(%p):%@>",NSStringFromClass([self class]), self, _collector]; +} + +- (void)finishWithErrorCode:(ORKErrorCode)error { + self.error = [NSError errorWithDomain:ORKErrorDomain code:error userInfo:nil]; + [self safeFinish]; +} + +- (void)doNextQuery { + [self.lock lock]; + + __block HKSampleType *sampleType = nil; + __block NSDate *startDate = nil; + + __block HKQueryAnchor *lastAnchor = nil; + __block NSString *itemIdentifier = nil; + + // Check if everything's valid and we should continue with collection + __block BOOL shouldContinue = YES; + + [_manager onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager) { + + shouldContinue = [self _shouldContinue]; + + BOOL changed = NO; + if (shouldContinue) { + // _currentAnchor will be NSNotFound on the first pass of the operation + if (_currentAnchor != nil) { + changed = YES; + // Update the anchor if we have one + _collector.lastAnchor = [_currentAnchor copy]; + } + + lastAnchor = _collector.lastAnchor; + sampleType = _collector.sampleType; + startDate = _collector.startDate; + itemIdentifier = _collector.identifier; + } + + return changed; + }]; + + if (_currentAnchor == nil) { + _currentAnchor = lastAnchor; + } + + if (!shouldContinue) { + [self finishWithErrorCode:ORKErrorInvalidObject]; + [self.lock unlock]; + return; + } + + __weak ORKHealthSampleQueryOperation * weakSelf = self; + + NSPredicate *predicate = nil; + if (startDate) { + predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:nil options:HKQueryOptionStrictStartDate]; + } + + HKQueryAnchor *anchor = _currentAnchor; + HKAnchoredObjectQuery *syncQuery = [[HKAnchoredObjectQuery alloc] initWithType:sampleType + predicate:predicate + anchor:anchor + limit:QueryLimitSize + resultsHandler:^(HKAnchoredObjectQuery *query, + NSArray<__kindof HKSample *> *sampleObjects, + NSArray *deletedObjects, + HKQueryAnchor *newAnchor, + NSError *error) { + + ORKHealthSampleQueryOperation *op = weakSelf; + ORK_Log_Debug("\nHK Query returned: %@\n", @{@"sampleType": sampleType, @"items":@([sampleObjects count]), @"newAnchor":[newAnchor description]?:@"nil"}); + // Signal that query returned + dispatch_semaphore_signal(_sem); + [op handleResults:sampleObjects newAnchor:newAnchor error:error itemIdentifier:itemIdentifier]; + }]; + + + ORK_Log_Debug("\nHK Query: %@ \n", @{@"identifier": sampleType.identifier, @"anchor": anchor.description ? :@"", @"startDate": [NSDateFormatter localizedStringFromDate:startDate dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]}); + [_manager.healthStore executeQuery:syncQuery]; + + [self.lock unlock]; + + dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + if (dispatch_semaphore_wait(_sem, timeout)) { + [self timeoutForAnchor:anchor]; + } + }); + +} + +- (void)timeoutForAnchor:(HKQueryAnchor *)anchor { + ORK_Log_Debug("Query timeout: cancel operation %@", self); + [self.lock lock]; + + if ([self isExecuting] && ![self isCancelled] && [anchor isEqual:_currentAnchor]) { + self.error = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{NSLocalizedDescriptionKey:@"Query timeout"}]; + [self safeFinish]; + } + + [self.lock unlock]; +} + +/* + Handles the result of an HKAnchoredObjectQuery, and starts a new query if needed + */ +- (void)handleResults:(NSArray *)results + newAnchor:(HKQueryAnchor *)newAnchor + error:(NSError *)error + itemIdentifier:(NSString *)itemIdentifier { + [self.lock lock]; + // Check our actual state under the lock + + if (![self isExecuting] || [self isCancelled]) { + // Give up immediately if we've been cancelled or are no longer executing + [self.lock unlock]; + return; + } + if (error) { + // Give up if there was an error performing the query + self.error = error; + [self safeFinish]; + [self.lock unlock]; + return; + } + + [self.lock unlock]; + + BOOL doContinue = (results && [results count] > 0); + if (doContinue) { + id delegate = _manager.delegate; + + BOOL handoutSuccess = NO; + + if (delegate) { + if ([_collector isKindOfClass:[ORKHealthCollector class]] + && [delegate respondsToSelector:@selector(healthCollector:didCollectSamples:)]) { + handoutSuccess = [delegate healthCollector:(ORKHealthCollector *)_collector didCollectSamples:results]; + } else if ([_collector isKindOfClass:[ORKHealthCorrelationCollector class]] + && [delegate respondsToSelector:@selector(healthCorrelationCollector:didCollectCorrelations:)]) { + handoutSuccess = [delegate healthCorrelationCollector:(ORKHealthCorrelationCollector *)_collector didCollectCorrelations:(NSArray *)results]; + } + } + + if (!handoutSuccess) { + doContinue = NO; + self.error = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{NSLocalizedFailureReasonErrorKey: @"Results were not properly delivered to the data collection manager delegate."}]; + } + } + + if (doContinue) { + // Do the next fetch + self->_currentAnchor = newAnchor; + [self doNextQuery]; + + } else { + // Stop for now (even if maybe we haven't fetched all the records) + [self safeFinish]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.h new file mode 100755 index 0000000..e55e8a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKHeightPicker : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.m new file mode 100755 index 0000000..c425e38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHeightPicker.m @@ -0,0 +1,279 @@ +/* + Copyright (c) 2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHeightPicker.h" +#import "ORKResult_Private.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKAccessibilityFunctions.h" + + +@interface ORKHeightPicker () + +@end + +static const CGFloat PickerSpacerHeight = 15.0; +static const CGFloat PickerMinimumHeight = 34.0; + +@implementation ORKHeightPicker { + UIPickerView *_pickerView; + ORKHeightAnswerFormat *_answerFormat; + id _answer; + __weak id _pickerDelegate; +} + +@synthesize pickerDelegate = _pickerDelegate; + +- (instancetype)initWithAnswerFormat:(ORKHeightAnswerFormat *)answerFormat answer:(id)answer pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + NSAssert([answerFormat isKindOfClass:[ORKHeightAnswerFormat class]], @"answerFormat should be ORKHeightAnswerFormat"); + + // Take into account locale changes so unit string can be updated + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(currentLocaleDidChange:) + name:NSCurrentLocaleDidChangeNotification object:nil]; + + _answerFormat = answerFormat; + _pickerDelegate = delegate; + self.answer = answer; + } + return self; +} + +- (UIView *)pickerView { + if (_pickerView == nil) { + _pickerView = [[UIPickerView alloc] init]; + _pickerView.dataSource = self; + _pickerView.delegate = self; + [self setAnswer:_answer]; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + if (ORKIsAnswerEmpty(answer)) { + answer = [self defaultAnswerValue]; + } + + if (_answerFormat.useMetricSystem) { + NSUInteger index = [[self centimeterValues] indexOfObject:answer]; + if (index == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:index inComponent:0 animated:NO]; + } else { + double feet, inches; + ORKCentimetersToFeetAndInches(((NSNumber *)answer).doubleValue, &feet, &inches); + NSUInteger feetIndex = [[self feetValues] indexOfObject:@((NSInteger)feet)]; + NSUInteger inchesIndex = [[self inchesValues] indexOfObject:@((NSInteger)inches)]; + if (feetIndex == NSNotFound || inchesIndex == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:feetIndex inComponent:0 animated:NO]; + [_pickerView selectRow:inchesIndex inComponent:1 animated:NO]; + } +} + +- (id)answer { + return _answer; +} + +- (NSNumber *)defaultAnswerValue { + NSNumber *defaultAnswerValue = nil; + if (_answerFormat.useMetricSystem) { + defaultAnswerValue = @(162); // Default metric height: 162 cm + } else { + defaultAnswerValue = @(162.56); // Default USC height: 5ft 4in (162.56 cm) + } + return defaultAnswerValue; +} + +- (NSNumber *)selectedAnswerValue { + NSNumber *answer = nil; + if (_answerFormat.useMetricSystem) { + NSInteger row = [_pickerView selectedRowInComponent:0]; + answer = [self centimeterValues][row]; + } else { + NSInteger feetRow = [_pickerView selectedRowInComponent:0]; + NSInteger inchesRow = [_pickerView selectedRowInComponent:1]; + NSNumber *feet = [self feetValues][feetRow]; + NSNumber *inches = [self inchesValues][inchesRow]; + answer = @( ORKFeetAndInchesToCentimeters(feet.doubleValue, inches.doubleValue) ); + } + return answer; +} + +- (NSString *)selectedLabelText { + return [_answerFormat stringForAnswer:_answer]; +} + +- (void)pickerWillAppear { + // Report current value, since ORKHeightPicker always has a value + [self pickerView]; + [self valueDidChange:self]; + [self accessibilityFocusOnPickerElement]; +} + +- (void)valueDidChange:(id)sender { + _answer = [self selectedAnswerValue]; + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:_answer]; + } +} + +#pragma mark - Accessibility + +- (void)accessibilityFocusOnPickerElement { + if (UIAccessibilityIsVoiceOverRunning()) { + ORKAccessibilityPerformBlockAfterDelay(0.75, ^{ + NSArray *axElements = [self.pickerView accessibilityElements]; + if ([axElements count] > 0) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, [axElements objectAtIndex:0]); + } + }); + } +} + +#pragma mark - UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return _answerFormat.useMetricSystem ? 1 : 2; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + NSInteger numberOfRows = 0; + if (_answerFormat.useMetricSystem) { + numberOfRows = [self centimeterValues].count; + } else { + if (component == 0) { + numberOfRows = [self feetValues].count; + } else { + numberOfRows = [self inchesValues].count; + } + } + return numberOfRows; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + NSString *title = nil; + if (_answerFormat.useMetricSystem) { + title = [NSString stringWithFormat:@"%@ %@", [self centimeterValues][row], ORKLocalizedString(@"MEASURING_UNIT_CM", nil)]; + } else { + if (component == 0) { + title = [NSString stringWithFormat:@"%@ %@", [self feetValues][row], ORKLocalizedString(@"MEASURING_UNIT_FT", nil)]; + } else { + title = [NSString stringWithFormat:@"%@ %@", [self inchesValues][row], ORKLocalizedString(@"MEASURING_UNIT_IN", nil)]; + } + } + return title; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view +{ + UILabel* valueLabel = (UILabel*)view; + if (!valueLabel) + { + valueLabel = [[UILabel alloc] init]; + [valueLabel setFont:[self defaultFont]]; + [valueLabel setTextAlignment:NSTextAlignmentCenter]; + } + valueLabel.text = [self pickerView:pickerView titleForRow:row forComponent:component]; + return valueLabel; +} + +- (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { + UIFont *font = [self defaultFont]; + CGFloat height = font.pointSize + PickerSpacerHeight; + return (height < PickerMinimumHeight ? PickerMinimumHeight : height); +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + [self valueDidChange:self]; +} + +- (NSArray *)centimeterValues { + static NSArray *centimeterValues = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableArray *mutableCentimeterValues = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i <= 299; i++) { + [mutableCentimeterValues addObject:[NSNumber numberWithInteger:i]]; + } + centimeterValues = [mutableCentimeterValues copy]; + }); + return centimeterValues; +} + +- (NSArray *)feetValues { + static NSArray *feetValues = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableArray *mutableFeetValues = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i <= 9; i++) { + [mutableFeetValues addObject:[NSNumber numberWithInteger:i]]; + } + feetValues = [mutableFeetValues copy]; + }); + return feetValues; +} + +- (NSArray *)inchesValues { + static NSArray *inchesValues = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSMutableArray *mutableInchesValues = [[NSMutableArray alloc] init]; + for (NSInteger i = 0; i <= 11; i++) { + [mutableInchesValues addObject:[NSNumber numberWithInteger:i]]; + } + inchesValues = [mutableInchesValues copy]; + }); + return inchesValues; +} + +- (void)currentLocaleDidChange:(NSNotification *)notification { + [_pickerView reloadAllComponents]; + [self setAnswer:[self defaultAnswerValue]]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers.m new file mode 100755 index 0000000..d58e858 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers.m @@ -0,0 +1,524 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKHelpers_Internal.h" + +#import "ORKStep.h" + +#import "ORKSkin.h" +#import "ORKTypes.h" + +#import + +BOOL ORKLoggingEnabled = YES; + +NSURL *ORKCreateRandomBaseURL() { + return [NSURL URLWithString:[NSString stringWithFormat:@"http://researchkit.%@/", [NSUUID UUID].UUIDString]]; +} + +NSBundle *ORKAssetsBundle(void) { + static NSBundle *bundle; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundle = [NSBundle bundleForClass:[ORKStep class]]; + }); + return bundle; +} + +ORK_INLINE CGFloat ORKCGFloor(CGFloat value) { + if (sizeof(value) == sizeof(float)) { + return (CGFloat)floorf((float)value); + } else { + return (CGFloat)floor((double)value); + } +} + +ORK_INLINE CGFloat ORKAdjustToScale(CGFloat (adjustFunction)(CGFloat), CGFloat value, CGFloat scale) { + if (scale == 0) { + static CGFloat screenScale = 1.0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + screenScale = [UIScreen mainScreen].scale; + }); + scale = screenScale; + } + if (scale == 1.0) { + return adjustFunction(value); + } else { + return adjustFunction(value * scale) / scale; + } +} + +CGFloat ORKFloorToViewScale(CGFloat value, UIView *view) { + return ORKAdjustToScale(ORKCGFloor, value, view.contentScaleFactor); +} + +id ORKFindInArrayByKey(NSArray *array, NSString *key, id value) { + NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K == %@", key, value]; + NSArray *matches = [array filteredArrayUsingPredicate:pred]; + if (matches.count) { + return matches[0]; + } + return nil; +} + +NSString *ORKStringFromDateISO8601(NSDate *date) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; + [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + }); + return [formatter stringFromDate:date]; +} + +NSDate *ORKDateFromStringISO8601(NSString *string) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; + [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + }); + return [formatter dateFromString:string]; +} + +NSString *ORKSignatureStringFromDate(NSDate *date) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [NSDateFormatter new]; + formatter.dateStyle = NSDateFormatterShortStyle; + formatter.timeStyle = NSDateFormatterNoStyle; + }); + return [formatter stringFromDate:date]; +} + +UIColor *ORKRGBA(uint32_t x, CGFloat alpha) { + CGFloat b = (x & 0xff) / 255.0f; x >>= 8; + CGFloat g = (x & 0xff) / 255.0f; x >>= 8; + CGFloat r = (x & 0xff) / 255.0f; + return [UIColor colorWithRed:r green:g blue:b alpha:alpha]; +} + +UIColor *ORKRGB(uint32_t x) { + return ORKRGBA(x, 1.0f); +} + +UIFontDescriptor *ORKFontDescriptorForLightStylisticAlternative(UIFontDescriptor *descriptor) { + UIFontDescriptor *fontDescriptor = [descriptor + fontDescriptorByAddingAttributes: + @{ UIFontDescriptorFeatureSettingsAttribute: @[ + @{ UIFontFeatureTypeIdentifierKey: @(kCharacterAlternativesType), + UIFontFeatureSelectorIdentifierKey: @(1) }]}]; + return fontDescriptor; +} + + +UIFont *ORKTimeFontForSize(CGFloat size) { + UIFontDescriptor *fontDescriptor = [ORKLightFontWithSize(size) fontDescriptor]; + fontDescriptor = ORKFontDescriptorForLightStylisticAlternative(fontDescriptor); + UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0]; + return font; +} + +NSString *ORKFileProtectionFromMode(ORKFileProtectionMode mode) { + switch (mode) { + case ORKFileProtectionComplete: + return NSFileProtectionComplete; + case ORKFileProtectionCompleteUnlessOpen: + return NSFileProtectionCompleteUnlessOpen; + case ORKFileProtectionCompleteUntilFirstUserAuthentication: + return NSFileProtectionCompleteUntilFirstUserAuthentication; + case ORKFileProtectionNone: + return NSFileProtectionNone; + } + //assert(0); + return NSFileProtectionNone; +} + +CGFloat ORKExpectedLabelHeight(UILabel *label) { + CGSize expectedLabelSize = [label.text boundingRectWithSize:CGSizeMake(label.frame.size.width, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{ NSFontAttributeName : label.font } + context:nil].size; + return expectedLabelSize.height; +} + +UIImage *ORKImageWithColor(UIColor *color) { + CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); + UIGraphicsBeginImageContext(rect.size); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSetFillColorWithColor(context, [color CGColor]); + CGContextFillRect(context, rect); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +void ORKEnableAutoLayoutForViews(NSArray *views) { + [views enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + [(UIView *)obj setTranslatesAutoresizingMaskIntoConstraints:NO]; + }]; +} + +NSDateFormatter *ORKResultDateTimeFormatter() { + static NSDateFormatter *dateTimeformatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dateTimeformatter = [[NSDateFormatter alloc] init]; + [dateTimeformatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; + dateTimeformatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + return dateTimeformatter; +} + +NSDateFormatter *ORKResultTimeFormatter() { + static NSDateFormatter *timeformatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + timeformatter = [[NSDateFormatter alloc] init]; + [timeformatter setDateFormat:@"HH:mm"]; + timeformatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + return timeformatter; +} + +NSDateFormatter *ORKResultDateFormatter() { + static NSDateFormatter *dateformatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + dateformatter = [[NSDateFormatter alloc] init]; + [dateformatter setDateFormat:@"yyyy-MM-dd"]; + dateformatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + return dateformatter; +} + +NSDateFormatter *ORKTimeOfDayLabelFormatter() { + static NSDateFormatter *timeformatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + timeformatter = [[NSDateFormatter alloc] init]; + NSString *dateFormat = [NSDateFormatter dateFormatFromTemplate:@"hma" options:0 locale:[NSLocale currentLocale]]; + [timeformatter setDateFormat:dateFormat]; + timeformatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + return timeformatter; +} + +NSBundle *ORKBundle() { + static NSBundle *bundle; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + bundle = [NSBundle bundleForClass:[ORKStep class]]; + }); + return bundle; +} + +NSBundle *ORKDefaultLocaleBundle() { + static NSBundle *bundle; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *path = [ORKBundle() pathForResource:[ORKBundle() objectForInfoDictionaryKey:@"CFBundleDevelopmentRegion"] ofType:@"lproj"]; + bundle = [NSBundle bundleWithPath:path]; + }); + return bundle; +} + +NSDateComponentsFormatter *ORKTimeIntervalLabelFormatter() { + static NSDateComponentsFormatter *durationFormatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + durationFormatter = [[NSDateComponentsFormatter alloc] init]; + [durationFormatter setUnitsStyle:NSDateComponentsFormatterUnitsStyleFull]; + [durationFormatter setAllowedUnits:NSCalendarUnitHour | NSCalendarUnitMinute]; + [durationFormatter setFormattingContext:NSFormattingContextStandalone]; + [durationFormatter setMaximumUnitCount: 2]; + }); + return durationFormatter; +} + +NSDateComponentsFormatter *ORKDurationStringFormatter() { + static NSDateComponentsFormatter *durationFormatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + durationFormatter = [[NSDateComponentsFormatter alloc] init]; + [durationFormatter setUnitsStyle:NSDateComponentsFormatterUnitsStyleFull]; + [durationFormatter setAllowedUnits: NSCalendarUnitMinute | NSCalendarUnitSecond]; + [durationFormatter setFormattingContext:NSFormattingContextStandalone]; + [durationFormatter setMaximumUnitCount: 2]; + }); + return durationFormatter; +} + +NSCalendar *ORKTimeOfDayReferenceCalendar() { + static NSCalendar *calendar; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + return calendar; +} + +NSString *ORKTimeOfDayStringFromComponents(NSDateComponents *dateComponents) { + static NSDateComponentsFormatter *timeOfDayFormatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + timeOfDayFormatter = [[NSDateComponentsFormatter alloc] init]; + [timeOfDayFormatter setUnitsStyle:NSDateComponentsFormatterUnitsStylePositional]; + [timeOfDayFormatter setAllowedUnits:NSCalendarUnitHour | NSCalendarUnitMinute]; + [timeOfDayFormatter setZeroFormattingBehavior:NSDateComponentsFormatterZeroFormattingBehaviorPad]; + }); + return [timeOfDayFormatter stringFromDateComponents:dateComponents]; +} + +NSDateComponents *ORKTimeOfDayComponentsFromString(NSString *string) { + // NSDateComponentsFormatter don't support parsing, this is a work around. + static NSDateFormatter *timeformatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + timeformatter = [[NSDateFormatter alloc] init]; + [timeformatter setDateFormat:@"HH:mm"]; + timeformatter.calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; + }); + NSDate *date = [timeformatter dateFromString:string]; + return [ORKTimeOfDayReferenceCalendar() components:(NSCalendarUnitMinute |NSCalendarUnitHour) fromDate:date]; +} + +NSDateComponents *ORKTimeOfDayComponentsFromDate(NSDate *date) { + if (date == nil) { + return nil; + } + return [ORKTimeOfDayReferenceCalendar() components:NSCalendarUnitHour|NSCalendarUnitMinute fromDate:date]; +} + +NSDate *ORKTimeOfDayDateFromComponents(NSDateComponents *dateComponents) { + return [ORKTimeOfDayReferenceCalendar() dateFromComponents:dateComponents]; +} + +BOOL ORKCurrentLocalePresentsFamilyNameFirst() { + NSString *language = [[NSLocale preferredLanguages].firstObject substringToIndex:2]; + static dispatch_once_t onceToken; + static NSArray *familyNameFirstLanguages = nil; + dispatch_once(&onceToken, ^{ + familyNameFirstLanguages = @[@"zh", @"ko", @"ja", @"vi"]; + }); + return (language != nil) && [familyNameFirstLanguages containsObject:language]; +} + +#define ORK_LAYOUT_MARGIN_WIDTH_THIN_BEZEL_REGULAR 20.0 +#define ORK_LAYOUT_MARGIN_WIDTH_THIN_BEZEL_COMPACT 16.0 +#define ORK_LAYOUT_MARGIN_WIDTH_REGULAR_BEZEL 15.0 + +UIFont *ORKThinFontWithSize(CGFloat size) { + UIFont *font = nil; + if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 2, .patchVersion = 0}]) { + font = [UIFont systemFontOfSize:size weight:UIFontWeightThin]; + } else { + font = [UIFont fontWithName:@".HelveticaNeueInterface-Thin" size:size]; + if (!font) { + font = [UIFont systemFontOfSize:size]; + } + } + return font; +} + +UIFont *ORKMediumFontWithSize(CGFloat size) { + UIFont *font = nil; + if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 2, .patchVersion = 0}]) { + font = [UIFont systemFontOfSize:size weight:UIFontWeightMedium]; + } else { + font = [UIFont fontWithName:@"HelveticaNeue-Medium" size:size]; + if (!font) { + font = [UIFont systemFontOfSize:size]; + } + } + return font; +} + +UIFont *ORKLightFontWithSize(CGFloat size) { + UIFont *font = nil; + if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 8, .minorVersion = 2, .patchVersion = 0}]) { + font = [UIFont systemFontOfSize:size weight:UIFontWeightLight]; + } else { + font = [UIFont fontWithName:@".HelveticaNeueInterface-Light" size:size]; + if (!font) { + font = [UIFont systemFontOfSize:size]; + } + } + return font; +} + +NSURL *ORKURLFromBookmarkData(NSData *data) { + if (data == nil) { + return nil; + } + + BOOL bookmarkIsStale = NO; + NSError *bookmarkError = nil; + NSURL *bookmarkURL = [NSURL URLByResolvingBookmarkData:data + options:NSURLBookmarkResolutionWithoutUI + relativeToURL:nil + bookmarkDataIsStale:&bookmarkIsStale + error:&bookmarkError]; + if (!bookmarkURL) { + ORK_Log_Error("Error loading URL from bookmark: %@", bookmarkError); + } + + return bookmarkURL; +} + +NSData *ORKBookmarkDataFromURL(NSURL *url) { + if (!url) { + return nil; + } + + NSError *error = nil; + NSData *bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationSuitableForBookmarkFile + includingResourceValuesForKeys:nil + relativeToURL:nil + error:&error]; + if (!bookmark) { + ORK_Log_Error("Error converting URL to bookmark: %@", error); + } + return bookmark; +} + +NSString *ORKPathRelativeToURL(NSURL *url, NSURL *baseURL) { + NSURL *standardizedURL = [url URLByStandardizingPath]; + NSURL *standardizedBaseURL = [baseURL URLByStandardizingPath]; + + NSString *path = [standardizedURL absoluteString]; + NSString *basePath = [standardizedBaseURL absoluteString]; + + if ([path hasPrefix:basePath]) { + NSString *relativePath = [path substringFromIndex:basePath.length]; + if ([relativePath hasPrefix:@"/"]) { + relativePath = [relativePath substringFromIndex:1]; + } + return relativePath; + } else { + return path; + } +} + +static NSURL *ORKHomeDirectoryURL() { + static NSURL *homeDirectoryURL = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + homeDirectoryURL = [NSURL fileURLWithPath:NSHomeDirectory()]; + }); + return homeDirectoryURL; +} + +NSURL *ORKURLForRelativePath(NSString *relativePath) { + if (!relativePath) { + return nil; + } + + NSURL *homeDirectoryURL = ORKHomeDirectoryURL(); + NSURL *url = [NSURL fileURLWithFileSystemRepresentation:relativePath.fileSystemRepresentation isDirectory:NO relativeToURL:homeDirectoryURL]; + + if (url != nil) { + BOOL isDirectory = NO;; + BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDirectory]; + if (fileExists && isDirectory) { + url = [NSURL fileURLWithFileSystemRepresentation:relativePath.fileSystemRepresentation isDirectory:YES relativeToURL:homeDirectoryURL]; + } + } + return url; +} +NSString *ORKRelativePathForURL(NSURL *url) { + if (!url) { + return nil; + } + + return ORKPathRelativeToURL(url, ORKHomeDirectoryURL()); +} + +id ORKDynamicCast_(id x, Class objClass) { + return [x isKindOfClass:objClass] ? x : nil; +} + +const CGFloat ORKScrollToTopAnimationDuration = 0.2; + +void ORKValidateArrayForObjectsOfClass(NSArray *array, Class expectedObjectClass, NSString *exceptionReason) { + NSCParameterAssert(array); + NSCParameterAssert(expectedObjectClass); + NSCParameterAssert(exceptionReason); + + for (id object in array) { + if (![object isKindOfClass:expectedObjectClass]) { + @throw [NSException exceptionWithName:NSGenericException reason:exceptionReason userInfo:nil]; + } + } +} + +void ORKRemoveConstraintsForRemovedViews(NSMutableArray *constraints, NSArray *removedViews) { + for (NSLayoutConstraint *constraint in [constraints copy]) { + for (UIView *view in removedViews) { + if (constraint.firstItem == view || constraint.secondItem == view) { + [constraints removeObject:constraint]; + } + } + } +} + +const double ORKDoubleInvalidValue = DBL_MAX; + +const CGFloat ORKCGFloatInvalidValue = CGFLOAT_MAX; + +void ORKAdjustPageViewControllerNavigationDirectionForRTL(UIPageViewControllerNavigationDirection *direction) { + if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) { + *direction = (*direction == UIPageViewControllerNavigationDirectionForward) ? UIPageViewControllerNavigationDirectionReverse : UIPageViewControllerNavigationDirectionForward; + } +} + +NSString *ORKPaddingWithNumberOfSpaces(NSUInteger numberOfPaddingSpaces) { + return [@"" stringByPaddingToLength:numberOfPaddingSpaces withString:@" " startingAtIndex:0]; +} + +NSNumberFormatter *ORKDecimalNumberFormatter() { + NSNumberFormatter *numberFormatter = [NSNumberFormatter new]; + numberFormatter.numberStyle = NSNumberFormatterDecimalStyle; + numberFormatter.maximumFractionDigits = NSDecimalNoScale; + numberFormatter.usesGroupingSeparator = NO; + return numberFormatter; +} + +NSString* ORKSwiftLocalizedString(NSString *key, NSString *comment) { + return ORKLocalizedString(key, comment); +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Internal.h new file mode 100755 index 0000000..5d86ca8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Internal.h @@ -0,0 +1,384 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import "ORKHelpers_Private.h" +#import "ORKErrors.h" +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_EXTERN BOOL ORKLoggingEnabled; + +#define ORK_Log(format, ...) __extension__({ \ + if (ORKLoggingEnabled) { \ + os_log(OS_LOG_DEFAULT, format, ##__VA_ARGS__); \ + } \ + }) + +#define ORK_Log_Info(format, ...) __extension__({ \ + if (ORKLoggingEnabled) { \ + os_log_info(OS_LOG_DEFAULT, format, ##__VA_ARGS__); \ + } \ + }) + +#define ORK_Log_Debug(format, ...) __extension__({ \ + if (ORKLoggingEnabled) { \ + os_log_debug(OS_LOG_DEFAULT, format, ##__VA_ARGS__); \ + } \ + }) + +#define ORK_Log_Error(format, ...) __extension__({ \ + if (ORKLoggingEnabled) { \ + os_log_error(OS_LOG_DEFAULT, format, ##__VA_ARGS__); \ + } \ + }) + +#define ORK_Log_Fault(format, ...) __extension__({ \ + if (ORKLoggingEnabled) { \ + os_log_fault(OS_LOG_DEFAULT, format, ##__VA_ARGS__); \ + } \ + }) + +#define ORK_NARG(...) ORK_NARG_(__VA_ARGS__,ORK_RSEQ_N()) +#define ORK_NARG_(...) ORK_ARG_N(__VA_ARGS__) +#define ORK_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, N, ...) N +#define ORK_RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define ORK_DECODE_OBJ(d,x) _ ## x = [d decodeObjectForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_OBJ(c,x) [c encodeObject:_ ## x forKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_URL(c,x) [c encodeObject:ORKRelativePathForURL(_ ## x) forKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_URL_BOOKMARK(c, x) [c encodeObject:ORKBookmarkDataFromURL(_ ## x) forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_OBJ_CLASS(d,x,cl) _ ## x = (cl *)[d decodeObjectOfClass:[cl class] forKey:@ORK_STRINGIFY(x)] +#define ORK_DECODE_OBJ_ARRAY(d,x,cl) _ ## x = (NSArray *)[d decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class],[cl class], nil] forKey:@ORK_STRINGIFY(x)] +#define ORK_DECODE_OBJ_MUTABLE_ORDERED_SET(d,x,cl) _ ## x = [(NSOrderedSet *)[d decodeObjectOfClasses:[NSSet setWithObjects:[NSOrderedSet class],[cl class], nil] forKey:@ORK_STRINGIFY(x)] mutableCopy] +#define ORK_DECODE_OBJ_MUTABLE_DICTIONARY(d,x,kcl,cl) _ ## x = [(NSDictionary *)[d decodeObjectOfClasses:[NSSet setWithObjects:[NSDictionary class],[kcl class],[cl class], nil] forKey:@ORK_STRINGIFY(x)] mutableCopy] + +#define ORK_ENCODE_COND_OBJ(c,x) [c encodeConditionalObject:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_IMAGE(d,x) _ ## x = (UIImage *)[d decodeObjectOfClass:[UIImage class] forKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_IMAGE(c,x) { if (_ ## x) { UIImage * orkTemp_ ## x = [UIImage imageWithCGImage:[_ ## x CGImage] scale:[_ ## x scale] orientation:[_ ## x imageOrientation]]; [c encodeObject:orkTemp_ ## x forKey:@ORK_STRINGIFY(x)]; } } + +#define ORK_DECODE_URL(d,x) _ ## x = ORKURLForRelativePath((NSString *)[d decodeObjectOfClass:[NSString class] forKey:@ORK_STRINGIFY(x)]) +#define ORK_DECODE_URL_BOOKMARK(d,x) _ ## x = ORKURLFromBookmarkData((NSData *)[d decodeObjectOfClass:[NSData class] forKey:@ORK_STRINGIFY(x)]) + +#define ORK_DECODE_BOOL(d,x) _ ## x = [d decodeBoolForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_BOOL(c,x) [c encodeBool:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_DOUBLE(d,x) _ ## x = [d decodeDoubleForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_DOUBLE(c,x) [c encodeDouble:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_INTEGER(d,x) _ ## x = [d decodeIntegerForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_INTEGER(c,x) [c encodeInteger:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_ENCODE_UINT32(c,x) [c encodeObject:[NSNumber numberWithUnsignedLongLong:_ ## x] forKey:@ORK_STRINGIFY(x)] +#define ORK_DECODE_UINT32(d,x) _ ## x = (uint32_t)[(NSNumber *)[d decodeObjectForKey:@ORK_STRINGIFY(x)] unsignedLongValue] + +#define ORK_DECODE_ENUM(d,x) _ ## x = [d decodeIntegerForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_ENUM(c,x) [c encodeInteger:(NSInteger)_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_CGRECT(d,x) _ ## x = [d decodeCGRectForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_CGRECT(c,x) [c encodeCGRect:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_CGSIZE(d,x) _ ## x = [d decodeCGSizeForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_CGSIZE(c,x) [c encodeCGSize:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_CGPOINT(d,x) _ ## x = [d decodeCGPointForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_CGPOINT(c,x) [c encodeCGPoint:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_UIEDGEINSETS(d,x) _ ## x = [d decodeUIEdgeInsetsForKey:@ORK_STRINGIFY(x)] +#define ORK_ENCODE_UIEDGEINSETS(c,x) [c encodeUIEdgeInsets:_ ## x forKey:@ORK_STRINGIFY(x)] + +#define ORK_DECODE_COORDINATE(d,x) _ ## x = CLLocationCoordinate2DMake([d decodeDoubleForKey:@ORK_STRINGIFY(x.latitude)],[d decodeDoubleForKey:@ORK_STRINGIFY(x.longitude)]) +#define ORK_ENCODE_COORDINATE(c,x) [c encodeDouble:_ ## x.latitude forKey:@ORK_STRINGIFY(x.latitude)];[c encodeDouble:_ ## x.longitude forKey:@ORK_STRINGIFY(x.longitude)]; + +/* + * Helpers for completions which call the block only if non-nil + * + */ +#define ORK_BLOCK_EXEC(block, ...) if (block) { block(__VA_ARGS__); }; + +#define ORK_DISPATCH_EXEC(queue, block, ...) if (block) { dispatch_async(queue, ^{ block(__VA_ARGS__); } ); } + +/* + * For testing background delivery + * + */ +#if ORK_BACKGROUND_DELIVERY_TEST +# define ORK_HEALTH_UPDATE_FREQUENCY HKUpdateFrequencyImmediate +#else +# define ORK_HEALTH_UPDATE_FREQUENCY HKUpdateFrequencyDaily +#endif + +// Find the first object of the specified class, using method as the iterator +#define ORKFirstObjectOfClass(C,p,method) ({ id v = p; while (v != nil) { if ([v isKindOfClass:[C class]]) { break; } else { v = [v method]; } }; v; }) + +#define ORKStrongTypeOf(x) __strong __typeof(x) +#define ORKWeakTypeOf(x) __weak __typeof(x) + +// Bundle for video assets +NSBundle *ORKAssetsBundle(void); +NSBundle *ORKBundle(void); +NSBundle *ORKDefaultLocaleBundle(void); + +// Pass 0xcccccc and get color #cccccc +UIColor *ORKRGB(uint32_t x); +UIColor *ORKRGBA(uint32_t x, CGFloat alpha); + +_Nullable id ORKFindInArrayByKey(NSArray *array, NSString *key, id value); + +NSString *ORKSignatureStringFromDate(NSDate *date); + +NSURL *ORKCreateRandomBaseURL(void); + +// Marked extern so it is accessible to unit tests +ORK_EXTERN NSString *ORKFileProtectionFromMode(ORKFileProtectionMode mode); + +CGFloat ORKExpectedLabelHeight(UILabel *label); + +// build a image with color +UIImage *ORKImageWithColor(UIColor *color); + +void ORKEnableAutoLayoutForViews(NSArray *views); + +NSDateComponentsFormatter *ORKTimeIntervalLabelFormatter(void); +NSDateComponentsFormatter *ORKDurationStringFormatter(void); + +NSDateFormatter *ORKTimeOfDayLabelFormatter(void); +NSCalendar *ORKTimeOfDayReferenceCalendar(void); + +NSDateComponents *ORKTimeOfDayComponentsFromDate(NSDate *date); +NSDate *ORKTimeOfDayDateFromComponents(NSDateComponents *dateComponents); + +BOOL ORKCurrentLocalePresentsFamilyNameFirst(void); + +UIFont *ORKTimeFontForSize(CGFloat size); +UIFontDescriptor *ORKFontDescriptorForLightStylisticAlternative(UIFontDescriptor *descriptor); + +CGFloat ORKFloorToViewScale(CGFloat value, UIView *view); + +ORK_INLINE bool +ORKEqualObjects(id o1, id o2) { + return (o1 == o2) || (o1 && o2 && [o1 isEqual:o2]); +} + +ORK_INLINE BOOL +ORKEqualFileURLs(NSURL *url1, NSURL *url2) { + return ORKEqualObjects(url1, url2) || ([url1 isFileURL] && [url2 isFileURL] && [[url1 absoluteString] isEqualToString:[url2 absoluteString]]); +} + +ORK_INLINE NSMutableOrderedSet * +ORKMutableOrderedSetCopyObjects(NSOrderedSet *a) { + if (!a) { + return nil; + } + NSMutableOrderedSet *b = [NSMutableOrderedSet orderedSetWithCapacity:a.count]; + [a enumerateObjectsUsingBlock:^(id obj, __unused NSUInteger idx, __unused BOOL *stop) { + [b addObject:[obj copy]]; + }]; + return b; +} + +ORK_INLINE NSMutableDictionary * +ORKMutableDictionaryCopyObjects(NSDictionary *a) { + if (!a) { + return nil; + } + NSMutableDictionary *b = [NSMutableDictionary dictionaryWithCapacity:a.count]; + [a enumerateKeysAndObjectsUsingBlock:^(id key, id obj, __unused BOOL *stop) { + b[key] = [obj copy]; + }]; + return b; +} + +#define ORKSuppressPerformSelectorWarning(PerformCall) \ +do { \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ +PerformCall; \ +_Pragma("clang diagnostic pop") \ +} while (0) + +UIFont *ORKThinFontWithSize(CGFloat size); +UIFont *ORKLightFontWithSize(CGFloat size); +UIFont *ORKMediumFontWithSize(CGFloat size); + +NSURL *ORKURLFromBookmarkData(NSData *data); +NSData *ORKBookmarkDataFromURL(NSURL *url); + +NSString *ORKPathRelativeToURL(NSURL *url, NSURL *baseURL); +NSURL *ORKURLForRelativePath(NSString *relativePath); +NSString *ORKRelativePathForURL(NSURL *url); + +_Nullable id ORKDynamicCast_(id x, Class objClass); + +#define ORKDynamicCast(x, c) ((c *) ORKDynamicCast_(x, [c class])) + +extern const CGFloat ORKScrollToTopAnimationDuration; + +ORK_INLINE CGFloat +ORKCGFloatNearlyEqualToFloat(CGFloat f1, CGFloat f2) { + const CGFloat ORKCGFloatEpsilon = 0.01; // 0.01 should be safe enough when dealing with screen point and pixel values + return (ABS(f1 - f2) <= ORKCGFloatEpsilon); +} + +#define ORKThrowMethodUnavailableException() @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"method unavailable" userInfo:nil]; +#define ORKThrowInvalidArgumentExceptionIfNil(argument) if (!argument) { @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@#argument" cannot be nil." userInfo:nil]; } + +void ORKValidateArrayForObjectsOfClass(NSArray *array, Class expectedObjectClass, NSString *exceptionReason); + +void ORKRemoveConstraintsForRemovedViews(NSMutableArray *constraints, NSArray *removedViews); + +extern const double ORKDoubleInvalidValue; + +extern const CGFloat ORKCGFloatInvalidValue; + +void ORKAdjustPageViewControllerNavigationDirectionForRTL(UIPageViewControllerNavigationDirection *direction); + +NSString *ORKPaddingWithNumberOfSpaces(NSUInteger numberOfPaddingSpaces); + +NSNumberFormatter *ORKDecimalNumberFormatter(void); + +ORK_INLINE double ORKFeetAndInchesToInches(double feet, double inches) { + return (feet * 12) + inches; +} + +ORK_INLINE void ORKInchesToFeetAndInches(double inches, double *outFeet, double *outInches) { + if (outFeet == NULL || outInches == NULL) { + return; + } + *outFeet = floor(inches / 12); + *outInches = round(fmod(inches, 12)); +} + +ORK_INLINE double ORKInchesToCentimeters(double inches) { + return inches * 2.54; +} + +ORK_INLINE double ORKCentimetersToInches(double centimeters) { + return centimeters / 2.54; +} + +ORK_INLINE void ORKCentimetersToFeetAndInches(double centimeters, double *outFeet, double *outInches) { + double inches = ORKCentimetersToInches(centimeters); + ORKInchesToFeetAndInches(inches, outFeet, outInches); +} + +ORK_INLINE double ORKFeetAndInchesToCentimeters(double feet, double inches) { + return ORKInchesToCentimeters(ORKFeetAndInchesToInches(feet, inches)); +} + +ORK_INLINE void ORKKilogramsToWholeAndFraction(double kilograms, double *outWhole, double *outFraction) { + if (outWhole == NULL || outFraction == NULL) { + return; + } + *outWhole = floor(kilograms); + *outFraction = round((kilograms - floor(kilograms)) * 100); +} + +ORK_INLINE void ORKKilogramsToPoundsAndOunces(double kilograms, double * _Nullable outPounds, double * _Nullable outOunces) { + const double ORKPoundsPerKilogram = 2.20462262; + double fractionalPounds = kilograms * ORKPoundsPerKilogram; + double pounds = floor(fractionalPounds); + double ounces = round((fractionalPounds - pounds) * 16); + if (ounces == 16) { + pounds += 1; + ounces = 0; + } + if (outPounds != NULL) { + *outPounds = pounds; + } + if (outOunces != NULL) { + *outOunces = ounces; + } +} + +ORK_INLINE double ORKKilogramsToPounds(double kilograms) { + double pounds; + ORKKilogramsToPoundsAndOunces(kilograms, £s, NULL); + return pounds; +} + +ORK_INLINE double ORKWholeAndFractionToKilograms(double whole, double fraction) { + double kg = (whole + (fraction / 100)); + return (round(100 * kg) / 100); +} + +ORK_INLINE double ORKPoundsAndOuncesToKilograms(double pounds, double ounces) { + const double ORKKilogramsPerPound = 0.45359237; + double kg = (pounds + (ounces / 16)) * ORKKilogramsPerPound; + return (round(100 * kg) / 100); +} + +ORK_INLINE double ORKPoundsToKilograms(double pounds) { + return ORKPoundsAndOuncesToKilograms(pounds, 0); +} + +ORK_INLINE UIColor *ORKOpaqueColorWithReducedAlphaFromBaseColor(UIColor *baseColor, NSUInteger colorIndex, NSUInteger totalColors) { + UIColor *color = baseColor; + if (totalColors > 1) { + CGFloat red = 0.0; + CGFloat green = 0.0; + CGFloat blue = 0.0; + CGFloat alpha = 0.0; + if ([baseColor getRed:&red green:&green blue:&blue alpha:&alpha]) { + // Avoid a pure transparent color (alpha = 0) + CGFloat targetAlphaFactor = ((1.0 / totalColors) * colorIndex); + return [UIColor colorWithRed:red + ((1.0 - red) * targetAlphaFactor) + green:green + ((1.0 - green) * targetAlphaFactor) + blue:blue + ((1.0 - blue) * targetAlphaFactor) + alpha:alpha]; + } + } + return color; +} + +// Localization +ORK_EXTERN NSBundle *ORKBundle(void) ORK_AVAILABLE_DECL; +ORK_EXTERN NSBundle *ORKDefaultLocaleBundle(void); + +#define ORKDefaultLocalizedValue(key) \ +[ORKDefaultLocaleBundle() localizedStringForKey:key value:@"" table:@"ResearchKit"] + +#define ORKLocalizedString(key, comment) \ +[ORKBundle() localizedStringForKey:(key) value:ORKDefaultLocalizedValue(key) table:@"ResearchKit"] + +#define ORKLocalizedStringFromNumber(number) \ +[NSNumberFormatter localizedStringFromNumber:number numberStyle:NSNumberFormatterNoStyle] + +NSString* ORKSwiftLocalizedString(NSString *key, NSString *comment); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Private.h new file mode 100755 index 0000000..c67e9a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKHelpers_Private.h @@ -0,0 +1,76 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +#if !defined(ORK_INLINE) +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define ORK_INLINE static inline +# elif defined(__cplusplus) +# define ORK_INLINE static inline +# elif defined(__GNUC__) +# define ORK_INLINE static __inline__ +# else +# define ORK_INLINE static +# endif +#endif + +#define ORK_STRINGIFY2( x) #x +#define ORK_STRINGIFY(x) ORK_STRINGIFY2(x) + +#define ORKDefineStringKey(x) static NSString *const x = @ORK_STRINGIFY(x) + +ORK_INLINE NSArray *ORKArrayCopyObjects(NSArray *a) { + if (!a) { + return nil; + } + NSMutableArray *b = [NSMutableArray arrayWithCapacity:a.count]; + [a enumerateObjectsUsingBlock:^(id obj, __unused NSUInteger idx, __unused BOOL *stop) { + [b addObject:[obj copy]]; + }]; + return [b copy]; +} + +ORK_EXTERN NSString *ORKStringFromDateISO8601(NSDate *date) ORK_AVAILABLE_DECL; +ORK_EXTERN NSDate *ORKDateFromStringISO8601(NSString *string) ORK_AVAILABLE_DECL; + +ORK_EXTERN NSString *ORKTimeOfDayStringFromComponents(NSDateComponents *dateComponents) ORK_AVAILABLE_DECL; +ORK_EXTERN NSDateComponents *ORKTimeOfDayComponentsFromString(NSString *string) ORK_AVAILABLE_DECL; + +ORK_EXTERN NSDateFormatter *ORKResultDateTimeFormatter(void) ORK_AVAILABLE_DECL; +ORK_EXTERN NSDateFormatter *ORKResultTimeFormatter(void) ORK_AVAILABLE_DECL; +ORK_EXTERN NSDateFormatter *ORKResultDateFormatter(void) ORK_AVAILABLE_DECL; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.h new file mode 100755 index 0000000..30c33c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import AVFoundation; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKImageCaptureCameraPreviewView : UIView + +@property (nonatomic, weak, nullable) AVCaptureSession *session; +@property (nonatomic) AVCaptureVideoOrientation videoOrientation; +@property (nonatomic, weak, nullable) UIImage *templateImage; +@property (nonatomic) UIEdgeInsets templateImageInsets; +@property (nonatomic, getter=isTemplateImageHidden) BOOL templateImageHidden; +@property (nonatomic, weak, nullable) UIImage *capturedImage; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.m new file mode 100755 index 0000000..29f0747 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureCameraPreviewView.m @@ -0,0 +1,261 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKImageCaptureCameraPreviewView.h" + +#import "ORKTintedImageView.h" + +#import "ORKHelpers_Internal.h" + +#import + + +@implementation ORKImageCaptureCameraPreviewView { + AVCaptureVideoPreviewLayer *_previewLayer; + ORKTintedImageView *_templateImageView; + NSLayoutConstraint *_templateImageViewTopInsetConstraint; + NSLayoutConstraint *_templateImageViewLeftInsetConstraint; + NSLayoutConstraint *_templateImageViewBottomInsetConstraint; + NSLayoutConstraint *_templateImageViewRightInseConstraint; + UIImageView *_capturedImageView; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _previewLayer = [[AVCaptureVideoPreviewLayer alloc] init]; + _previewLayer.videoGravity = AVLayerVideoGravityResizeAspect; + _previewLayer.needsDisplayOnBoundsChange = YES; + [self.layer addSublayer:_previewLayer]; + + _capturedImageView = [[UIImageView alloc] init]; + _capturedImageView.contentMode = UIViewContentModeScaleAspectFit; + [self addSubview:_capturedImageView]; + + _templateImageView = [[ORKTintedImageView alloc] init]; + _templateImageView.contentMode = UIViewContentModeScaleAspectFit; + _templateImageView.shouldApplyTint = YES; + _templateImageView.hidden = YES; + _templateImageView.alpha = 0; + [_capturedImageView addSubview:_templateImageView]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + _templateImageView.translatesAutoresizingMaskIntoConstraints = NO; + _capturedImageView.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + [_templateImageView setContentHuggingPriority:0 forAxis:UILayoutConstraintAxisHorizontal]; + [_templateImageView setContentHuggingPriority:0 forAxis:UILayoutConstraintAxisVertical]; + [_templateImageView setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisHorizontal]; + [_templateImageView setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisVertical]; + [_capturedImageView setContentHuggingPriority:0 forAxis:UILayoutConstraintAxisHorizontal]; + [_capturedImageView setContentHuggingPriority:0 forAxis:UILayoutConstraintAxisVertical]; + [_capturedImageView setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisHorizontal]; + [_capturedImageView setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisVertical]; + + // Make the insets for the template image view changeable later + _templateImageViewTopInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_capturedImageView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewTopInsetConstraint]; + + _templateImageViewLeftInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_capturedImageView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewLeftInsetConstraint]; + + _templateImageViewBottomInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_capturedImageView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewBottomInsetConstraint]; + + _templateImageViewRightInseConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_capturedImageView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewRightInseConstraint]; + + // Make the captured image view use the available space (taking into account the layout margins) + NSDictionary *views = @{ @"capturedImageView": _capturedImageView }; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[capturedImageView]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[capturedImageView]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (AVCaptureSession *)session { + return _previewLayer.session; +} + +- (void)setSession:(AVCaptureSession *)session { + _previewLayer.session = session; +} + +- (UIImage *)templateImage { + return _templateImageView.image; +} + +- (void)setTemplateImage:(UIImage *)templateImage { + _templateImageView.image = templateImage; +} + +- (void)setTemplateImageHidden:(BOOL)hidden { + if (!hidden) { + _templateImageView.hidden = NO; + } + [UIView animateWithDuration:0.15 + animations:^{ + _templateImageView.alpha = hidden ? 0 : 1; + } completion:^(BOOL finished) { + _templateImageView.hidden = hidden; + }]; +} + +- (BOOL)isTemplateImageHidden { + return _templateImageView.hidden; +} + +- (UIImage *)capturedImage { + return _capturedImageView.image; +} + +- (void)setCapturedImage:(UIImage *)capturedImage { + _capturedImageView.image = capturedImage; + _previewLayer.hidden = (capturedImage != nil); +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + // Ensure that the preview layer takes up all the space + _previewLayer.frame = self.frame; + + // Update the insets for the template and catpured image views + [self updateInsets]; +} + +- (void)updateInsets { + // Update the layoutMargins to match those being used by the preview layer content, if needed + UIEdgeInsets previewLayerContentFrameInsets = [self getPreviewLayerContentFrameInsets]; + if (!UIEdgeInsetsEqualToEdgeInsets(previewLayerContentFrameInsets, self.layoutMargins)) { + self.layoutMargins = previewLayerContentFrameInsets; + } + + // Update the insets on the template image view, if needed + CGRect previewLayerContentFrame = UIEdgeInsetsInsetRect(_previewLayer.frame, previewLayerContentFrameInsets); + UIEdgeInsets insets = UIEdgeInsetsMake(round(self.templateImageInsets.top * previewLayerContentFrame.size.height), + round(self.templateImageInsets.left * previewLayerContentFrame.size.width), + round(self.templateImageInsets.bottom * previewLayerContentFrame.size.height), + round(self.templateImageInsets.right * previewLayerContentFrame.size.width)); + + if (_templateImageViewTopInsetConstraint.constant != insets.top) { + _templateImageViewTopInsetConstraint.constant = insets.top; + } + if (_templateImageViewLeftInsetConstraint.constant != insets.left) { + _templateImageViewLeftInsetConstraint.constant = insets.left; + } + if (_templateImageViewBottomInsetConstraint.constant != -insets.bottom) { + _templateImageViewBottomInsetConstraint.constant = -insets.bottom; + } + if (_templateImageViewRightInseConstraint.constant != -insets.right) { + _templateImageViewRightInseConstraint.constant = -insets.right; + } +} + +- (UIEdgeInsets)getPreviewLayerContentFrameInsets { + // Determine the insets on the preview layer frame that correspond to the actual video content + // when using a videoGravity of AVLayerVideoGravityResizeAspect; + NSArray *inputs = _previewLayer.session.inputs; + if (!inputs || inputs.count == 0) + return UIEdgeInsetsZero; + AVCaptureDeviceInput *input = (AVCaptureDeviceInput*)inputs[0]; + CMVideoDimensions videoDimensions = CMVideoFormatDescriptionGetDimensions(input.device.activeFormat.formatDescription); + AVCaptureVideoOrientation orientation = _previewLayer.connection.videoOrientation; + BOOL landscape = (orientation == AVCaptureVideoOrientationLandscapeLeft || orientation == AVCaptureVideoOrientationLandscapeRight); + + CGRect contentFrame = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(landscape ? videoDimensions.width : videoDimensions.height, landscape ? videoDimensions.height : videoDimensions.width), _previewLayer.frame); + CGRect overallFrame = _previewLayer.frame; + return UIEdgeInsetsMake(contentFrame.origin.y - overallFrame.origin.y, + contentFrame.origin.x - overallFrame.origin.x, + (overallFrame.origin.y + overallFrame.size.height) - (contentFrame.origin.y + contentFrame.size.height), + (overallFrame.origin.x + overallFrame.size.width) - (contentFrame.origin.x + contentFrame.size.width)); +} + +- (AVCaptureVideoOrientation)videoOrientation { + return _previewLayer.connection.videoOrientation; +} + +- (void)setVideoOrientation:(AVCaptureVideoOrientation)videoOrientation { + _previewLayer.connection.videoOrientation = videoOrientation; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + return ORKLocalizedString(self.capturedImage ? @"AX_IMAGE_CAPTURED_LABEL" : @"AX_IMAGE_CAPTURE_LABEL", nil); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitImage; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.h new file mode 100755 index 0000000..afbbc23 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.h @@ -0,0 +1,101 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKImageCaptureStep` class represents a step that captures an image through the device + camera. A template image can optionally be laid over the camera preview to assist in properly + capturing the image. + + To use the image capture step, optionally set the `templateImage` and `templateImageInsets` + properties, incorporate the step into a task, and present the task with a task view controller. + + If implementing an image capture task like this one, remember that people will + take your instructions literally. So be cautious. Make sure your template image + is high contrast and very visible against a variety of backgrounds. + */ +ORK_CLASS_AVAILABLE +@interface ORKImageCaptureStep : ORKStep + +/** + An image to be displayed over the camera preview. + + The image is stretched to fit the available space while retaining its aspect ratio. + When choosing a size for this asset, be sure to take into account the variations in device + form factors. + */ +@property (nonatomic, strong) UIImage *templateImage; + +/** + Insets to be used in positioning and sizing the `templateImage`. + + The insets are interpreted as percentages relative to the preview frame size. The left + and right insets are relative to the width of the preview frame. The top and bottom + insets are relative to the height of the preview frame. + */ +@property (nonatomic) UIEdgeInsets templateImageInsets; + +/** + The accessibility hint for the capture preview. + + This property can be used to specify accessible instructions for capturing the image. The + use of this property can assist when the `templateImage` may not be visible + to the user. + + For example, if you want to capture an image of the user's right hand, you may use a template + image that displays the outline of the right hand. You may also want to set this property + to a string such as @"Extend your right hand, palm side down, one foot from your device. + Tap the Capture Image button, or two finger tap on the preview, to capture an image of your + extended right hand." + */ +@property (nonatomic, copy) NSString *accessibilityInstructions; + +/** + The accessibility hint for the capture button. + */ +@property (nonatomic, copy) NSString *accessibilityHint; + +/** + A boolean value indicating whether or not RAW image data should be captured. + + The default value of this property is 'NO'. If set to YES, the step will capture in RAW and + display preview using HEIC or JPEG. RAW format will only be captured if the device supports it. + */ +@property (nonatomic, assign) BOOL captureRaw; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.m new file mode 100755 index 0000000..6dab070 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStep.m @@ -0,0 +1,101 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKImageCaptureStep.h" + +#import "ORKImageCaptureStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKImageCaptureStep + ++ (Class)stepViewControllerClass { + return [ORKImageCaptureStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.optional = YES; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_IMAGE(aDecoder, templateImage); + ORK_DECODE_UIEDGEINSETS(aDecoder, templateImageInsets); + ORK_DECODE_OBJ(aDecoder, accessibilityHint); + ORK_DECODE_OBJ(aDecoder, accessibilityInstructions); + ORK_DECODE_BOOL(aDecoder, captureRaw); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_IMAGE(aCoder, templateImage); + ORK_ENCODE_UIEDGEINSETS(aCoder, templateImageInsets); + ORK_ENCODE_OBJ(aCoder, accessibilityHint); + ORK_ENCODE_OBJ(aCoder, accessibilityInstructions); + ORK_ENCODE_BOOL(aCoder, captureRaw); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKImageCaptureStep *step = [super copyWithZone:zone]; + step.templateImage = self.templateImage; + step.templateImageInsets = self.templateImageInsets; + step.accessibilityHint = self.accessibilityHint; + step.accessibilityInstructions = self.accessibilityInstructions; + step.captureRaw = self.captureRaw; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(self.templateImage, castObject.templateImage) + && UIEdgeInsetsEqualToEdgeInsets(self.templateImageInsets, castObject.templateImageInsets) + && ORKEqualObjects(self.accessibilityHint, castObject.accessibilityHint) + && ORKEqualObjects(self.accessibilityInstructions, castObject.accessibilityInstructions) + && self.captureRaw == castObject.captureRaw; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.h new file mode 100755 index 0000000..782cad5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKImageCaptureStepViewController` class represents the step view controller that + corresponds to an `ORKImageCaptureStep` class. + + It is not usually necessary to instantiate this view controller directly. + Instead, add an image capture step to a task, and present the task in a task + view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKImageCaptureStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.m new file mode 100755 index 0000000..a7c0a88 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureStepViewController.m @@ -0,0 +1,418 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepViewController_Internal.h" + +#import "ORKImageCaptureView.h" +#import "ORKImageCaptureStep.h" + +#import "ORKImageCaptureStepViewController.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKFileResult.h" +#import "ORKResult.h" +#import "ORKStep.h" + +#import "ORKHelpers_Internal.h" + +@import AVFoundation; + + +@interface ORKImageCaptureStepViewController () + +@end + + +@implementation ORKImageCaptureStepViewController { + ORKImageCaptureView *_imageCaptureView; + dispatch_queue_t _sessionQueue; + AVCaptureSession *_captureSession; + AVCapturePhotoOutput *_photoOutput; + NSData *_capturedImageData; + NSData *_compressedImageData; + NSData *_rawImageData; + NSURL *_fileURL; + UIImage *_previewImage; + BOOL _captureRaw; + NSString *_imageDataExtension; +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + self = [self initWithStep:step]; + if (self) { + ORKStepResult *stepResult = (ORKStepResult *)result; + if (stepResult && [stepResult results].count > 0) { + + ORKFileResult *fileResult = ORKDynamicCast([stepResult results].firstObject, ORKFileResult); + + if (fileResult.fileURL) { + // Setting these properties in this order allows us to reuse the existing file on disk + self.capturedImageData = [NSData dataWithContentsOfURL:fileResult.fileURL]; + _fileURL = fileResult.fileURL; + } + } + } + return self; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + NSParameterAssert([step isKindOfClass:[ORKImageCaptureStep class]]); + _imageCaptureView = [[ORKImageCaptureView alloc] initWithFrame:CGRectZero]; + _imageCaptureView.imageCaptureStep = (ORKImageCaptureStep *)step; + _imageCaptureView.delegate = self; + _captureRaw = NO; + [self.view addSubview:_imageCaptureView]; + + _imageCaptureView.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + UIView *iPadContentView = [self viewForiPadLayoutConstraints]; + [constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_imageCaptureView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_imageCaptureView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_imageCaptureView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_imageCaptureView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _imageCaptureView.continueButtonItem = continueButtonItem; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _imageCaptureView.skipButtonItem = skipButtonItem; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + [super setCancelButtonItem:cancelButtonItem]; + _imageCaptureView.cancelButtonItem = cancelButtonItem; +} + +- (void)retakePressed:(void (^)(void))handler { + // Start the capture session, and reset the captured image to nil + dispatch_async(_sessionQueue, ^{ + [_captureSession startRunning]; + dispatch_async(dispatch_get_main_queue(), ^{ + self.capturedImageData = nil; + if (handler) { + handler(); + } + }); + }); +} + +- (AVCapturePhotoSettings *)createRawPhotoSettings { + + AVCapturePhotoSettings *photoSettings; + OSType rawPixelFormatType = [[[_photoOutput availableRawPhotoPixelFormatTypes] firstObject] unsignedIntValue]; + + if ([[_photoOutput availablePhotoCodecTypes] containsObject:AVVideoCodecTypeHEVC]) { + photoSettings = [AVCapturePhotoSettings photoSettingsWithRawPixelFormatType:rawPixelFormatType + processedFormat:@{AVVideoCodecKey: AVVideoCodecTypeHEVC}]; + } else { + photoSettings = [AVCapturePhotoSettings photoSettingsWithRawPixelFormatType:rawPixelFormatType + processedFormat:@{AVVideoCodecKey: AVVideoCodecTypeJPEG}]; + } + [photoSettings setAutoStillImageStabilizationEnabled:NO]; + [photoSettings setFlashMode:(([_photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]] ? AVCaptureFlashModeAuto : AVCaptureFlashModeOff))]; + + return photoSettings; +} + +- (AVCapturePhotoSettings *)generatePhotoSetting { + + AVCapturePhotoSettings *photoSettings; + if ([[_photoOutput availablePhotoCodecTypes] containsObject:AVVideoCodecTypeHEVC]) { + photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey: AVVideoCodecTypeHEVC}]; + _imageDataExtension = @"heif"; + } else { + photoSettings = [AVCapturePhotoSettings photoSettings]; + _imageDataExtension = @"jpeg"; + } + + [photoSettings setAutoStillImageStabilizationEnabled: [_photoOutput isStillImageStabilizationSupported]]; + [photoSettings setFlashMode:(([_photoOutput.supportedFlashModes containsObject:[NSNumber numberWithInt:AVCaptureFlashModeOn]] ? AVCaptureFlashModeAuto : AVCaptureFlashModeOff))]; + + return photoSettings; +} + +- (void)capturePressed:(void (^)(BOOL))handler { + // Capture image + dispatch_async(_sessionQueue, ^{ + if (_captureRaw && [_photoOutput availableRawPhotoFileTypes]) { + [_photoOutput capturePhotoWithSettings:[self createRawPhotoSettings] delegate:self]; + _imageDataExtension = @"dng"; + } else { + [_photoOutput capturePhotoWithSettings:[self generatePhotoSetting] delegate:self]; + _captureRaw = NO; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + // Notify handler that we are done + if (handler) { + handler(_capturedImageData != nil); + } + }); + }); +} + +- (void)captureOutput:(AVCapturePhotoOutput *)captureOutput didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(nullable NSError *)error{ + + if (_captureRaw) { + if ([photo isRawPhoto]){ + _rawImageData = photo.fileDataRepresentation; + } else { + _previewImage = [UIImage imageWithData:photo.fileDataRepresentation]; + } + } else { + _compressedImageData = photo.fileDataRepresentation; + _previewImage = [UIImage imageWithData:photo.fileDataRepresentation]; + } +} + +- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishCaptureForResolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings error:(NSError *)error{ + // If something was captured, stop the capture session + if (_capturedImageData) { + [_captureSession stopRunning]; + } + + // Use the main queue, as UI components may need to be updated + dispatch_async(dispatch_get_main_queue(), ^{ + // Set this, even if there was an error and we got a nil buffer + if (_captureRaw) { + self.capturedImageData = _rawImageData; + } else { + self.capturedImageData = _compressedImageData; + } + }); +} + +- (void)videoOrientationDidChange:(AVCaptureVideoOrientation)videoOrientation { + // Keep the output orientation in sync with the input orientation + [[[_photoOutput connections] firstObject] setVideoOrientation:videoOrientation]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Capture actions should be performed off the main queue to keep the UI responsive + _sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL); + + // Setup the capture session + dispatch_async(_sessionQueue, ^{ + [self queue_SetupCaptureSession]; + }); +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // If we don't already have a captured image, then start the capture session running + if (!_capturedImageData) { + dispatch_async(_sessionQueue, ^{ + [_captureSession startRunning]; + }); + } +} + +- (void)viewWillDisappear:(BOOL)animated { + // If the capture session is running, stop it + if (_captureSession.isRunning) { + dispatch_async(_sessionQueue, ^{ + [_captureSession stopRunning]; + }); + } + + [super viewWillDisappear:animated]; +} + +- (void)queue_SetupCaptureSession { + // Create the session + _captureSession = [[AVCaptureSession alloc] init]; + [_captureSession beginConfiguration]; + + _captureSession.sessionPreset = AVCaptureSessionPresetPhoto; + _captureRaw = [self imageCaptureStep].captureRaw; + // Get the camera + AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + if (device) { + // Configure the input and output + AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; + AVCapturePhotoOutput *photoOutput = [[AVCapturePhotoOutput alloc] init]; + if ([_captureSession canAddInput:input] && [_captureSession canAddOutput:photoOutput]) { + [_captureSession addInput:input]; + [_captureSession addOutput:photoOutput]; + _photoOutput = photoOutput; + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_NO_PERMISSIONS", nil)}]]; + }); + _captureSession = nil; + } + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_CAMERA_NOT_FOUND", nil)}]]; + }); + _captureSession = nil; + } + + + [_captureSession commitConfiguration]; + + _imageCaptureView.session = _captureSession; +} + +- (void)handleError:(NSError *)error { + // Shut down the session, if running + if (_captureSession.isRunning) { + ORKStrongTypeOf(_captureSession) strongCaptureSession = _captureSession; + dispatch_async(_sessionQueue, ^{ + [strongCaptureSession stopRunning]; + }); + } + + // Reset the state to before the capture session was setup. Order here is important + _captureSession = nil; + _photoOutput = nil; + _imageCaptureView.session = nil; + _imageCaptureView.capturedImage = nil; + _capturedImageData = nil; + _fileURL = nil; + + // Show the error in the image capture view + _imageCaptureView.error = error; +} + +- (void)setCapturedImageData:(NSData *)capturedImageData { + _capturedImageData = capturedImageData; + _imageCaptureView.capturedImage = capturedImageData ? _previewImage : nil; + + // Remove the old file, if it exists, now that new data was acquired or reset + if (_fileURL) { + [[NSFileManager defaultManager] removeItemAtURL:_fileURL error:nil]; + // Force the file to be rewritten the next time the result is requested + _fileURL = nil; + } + + [self notifyDelegateOnResultChange]; +} + +- (NSURL *)writeCapturedDataWithError:(NSError **)errorOut { + NSURL *URL = [[self.outputDirectory URLByAppendingPathComponent:self.step.identifier] URLByAppendingPathExtension: _imageDataExtension]; + // Confirm the outputDirectory was set properly + if (!URL) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteInvalidFileNameError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY", nil)}]; + } + return nil; + } + + // If set properly, the outputDirectory is already created, so write the file into it + NSError *writeError = nil; + if (![_capturedImageData writeToURL:URL options:NSDataWritingAtomic|NSDataWritingFileProtectionCompleteUnlessOpen error:&writeError]) { + if (writeError) { + ORK_Log_Error("%@", writeError); + } + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteInvalidFileNameError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_CANNOT_WRITE_FILE", nil)}]; + } + return nil; + } + + return URL; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + NSDate *now = stepResult.endDate; + + // If we have captured data, but have not yet written that data to a file, do it now + if (!_fileURL && _capturedImageData) { + NSError *error = nil; + _fileURL = [self writeCapturedDataWithError:&error]; + if (error) { + [self handleError:error]; + } + } + + NSMutableArray *results = [NSMutableArray arrayWithArray:stepResult.results]; + ORKFileResult *fileResult = [[ORKFileResult alloc] initWithIdentifier:self.step.identifier]; + fileResult.startDate = stepResult.startDate; + fileResult.endDate = now; + NSString *contentType = [NSString stringWithFormat:@"image/%@", _imageDataExtension]; + fileResult.contentType = contentType; + fileResult.fileURL = _fileURL; + [results addObject:fileResult]; + stepResult.results = [results copy]; + return stepResult; +} + +- (ORKImageCaptureStep *)imageCaptureStep { + return (ORKImageCaptureStep *)self.step; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.h new file mode 100755 index 0000000..788ae04 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import AVFoundation; + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKImageCaptureViewDelegate + +- (void)capturePressed:(void (^ _Nullable)(BOOL captureSuccess))handler; +- (void)retakePressed:(void (^ _Nullable)(void))handler; +- (void)videoOrientationDidChange:(AVCaptureVideoOrientation)videoOrientation; + +@end + +@class ORKImageCaptureStep; + +@interface ORKImageCaptureView : UIView + +@property (nonatomic, strong, nullable) ORKImageCaptureStep *imageCaptureStep; +@property (nonatomic, weak, nullable) id delegate; +@property (nonatomic, weak, nullable) AVCaptureSession *session; +@property (nonatomic, strong, nullable) UIBarButtonItem *continueButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *skipButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem; +@property (nonatomic, strong, nullable) UIImage *capturedImage; +@property (nonatomic, strong, nullable) NSError *error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.m new file mode 100755 index 0000000..67951d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageCaptureView.m @@ -0,0 +1,335 @@ +/* + Copyright (c) 2015, Bruce Duncan. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKImageCaptureView.h" + +#import "ORKImageCaptureCameraPreviewView.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" + +#import "ORKImageCaptureStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKImageCaptureView { + ORKStepHeaderView *_headerView; + ORKImageCaptureCameraPreviewView *_previewView; + ORKNavigationContainerView *_navigationFooterView; + UIBarButtonItem *_captureButtonItem; + UIBarButtonItem *_recaptureButtonItem; + NSMutableArray *_variableConstraints; + + BOOL _capturePressesIgnored; + BOOL _retakePressesIgnored; + BOOL _showSkipButtonItem; +} + +- (instancetype)initWithFrame:(CGRect)aRect { + self = [super initWithFrame:aRect]; + if (self) { + _previewView = [[ORKImageCaptureCameraPreviewView alloc] init]; + [self addSubview:_previewView]; + + _headerView = [[ORKStepHeaderView alloc] init]; + _headerView.instructionLabel.text = @" "; // Need error placeholder string for constraints. + [self addSubview:_headerView]; + + _captureButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"CAPTURE_BUTTON_CAPTURE_IMAGE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(capturePressed)]; + _recaptureButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"CAPTURE_BUTTON_RECAPTURE_IMAGE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(retakePressed)]; + + _navigationFooterView = [ORKNavigationContainerView new]; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.topMargin = 5; + _navigationFooterView.bottomMargin = 15; + _navigationFooterView.optional = YES; + _navigationFooterView.backgroundColor = ORKColor(ORKNavigationContainerColorKey); + [self addSubview:_navigationFooterView]; + + NSDictionary *dictionary = NSDictionaryOfVariableBindings(self, _previewView, _navigationFooterView, _headerView); + ORKEnableAutoLayoutForViews(dictionary.allValues); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queue_sessionRunning) name:AVCaptureSessionDidStartRunningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionWasInterrupted:) name:AVCaptureSessionWasInterruptedNotification object:self.session]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionInterruptionEnded:) name:AVCaptureSessionInterruptionEndedNotification object:self.session]; + + [self updateAppearance]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)queue_sessionRunning { + dispatch_async(dispatch_get_main_queue(), ^{ + _previewView.templateImageHidden = NO; + }); +} + +- (void)orientationDidChange { + dispatch_async(dispatch_get_main_queue(), ^{ + AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationPortrait; + switch ([[UIApplication sharedApplication] statusBarOrientation]) { + case UIInterfaceOrientationLandscapeRight: + orientation = AVCaptureVideoOrientationLandscapeRight; + break; + case UIInterfaceOrientationLandscapeLeft: + orientation = AVCaptureVideoOrientationLandscapeLeft; + break; + case UIInterfaceOrientationPortraitUpsideDown: + orientation = AVCaptureVideoOrientationPortraitUpsideDown; + break; + case UIInterfaceOrientationPortrait: + orientation = AVCaptureVideoOrientationPortrait; + break; + case UIInterfaceOrientationUnknown: + // Do nothing in these cases, since we don't need to change display orientation. + return; + } + + [_previewView setVideoOrientation:orientation]; + [self.delegate videoOrientationDidChange:orientation]; + [self setNeedsUpdateConstraints]; + }); +} + +- (void)setImageCaptureStep:(ORKImageCaptureStep *)imageCaptureStep { + _imageCaptureStep = imageCaptureStep; + + _previewView.templateImage = imageCaptureStep.templateImage; + _previewView.templateImageInsets = imageCaptureStep.templateImageInsets; + + _captureButtonItem.accessibilityHint = imageCaptureStep.accessibilityHint; + + _showSkipButtonItem = imageCaptureStep.optional; + + [self updateAppearance]; +} + +- (void)updateAppearance { + + _headerView.alpha = (self.error) ? 1 : 0; + _previewView.alpha = (self.error) ? 0 : 1; + + if (self.error) { + // Display the error instruction. + _headerView.instructionLabel.text = [self.error.userInfo valueForKey:NSLocalizedDescriptionKey]; + + // Hide the template image if there is an error + _previewView.templateImageHidden = YES; + _previewView.accessibilityHint = nil; + + // Show skip, if available, and hide the template and continue/capture button + _navigationFooterView.continueButtonItem = nil; + _navigationFooterView.skipButtonItem = _skipButtonItem; + } else if (self.capturedImage) { + // Hide the template image after capturing + _previewView.templateImageHidden = YES; + _previewView.accessibilityHint = nil; + + // Set the continue button to the one we've saved and configure the skip button as a recapture button + _navigationFooterView.continueButtonItem = _continueButtonItem; + _navigationFooterView.skipButtonItem = _recaptureButtonItem; + } else { + // Show the template image during capturing + _previewView.templateImageHidden = NO; + _previewView.accessibilityHint = _imageCaptureStep.accessibilityInstructions; + + // Change the continue button back to capture, and change the recapture button back to skip (if available) + _navigationFooterView.continueButtonItem = _captureButtonItem; + _navigationFooterView.skipButtonItem = _skipButtonItem; + } +} + +- (void)setCapturedImage:(UIImage *)capturedImage { + _previewView.capturedImage = capturedImage; + [self updateAppearance]; +} + +- (UIImage *)capturedImage { + return _previewView.capturedImage; +} + +- (void)setError:(NSError *)error { + _error = error; + [self updateAppearance]; +} + +- (void)updateConstraints { + const CGFloat NavigationFooterViewTranslucentAlpha = 0.5; + const CGFloat NavigationFooterViewOpaqueAlpha = 0.0; + + if (_variableConstraints) { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + } + + if (!_variableConstraints) { + _variableConstraints = [[NSMutableArray alloc] init]; + } + + NSDictionary *views = NSDictionaryOfVariableBindings(self, _previewView, _navigationFooterView, _headerView); + ORKEnableAutoLayoutForViews(views.allValues); + + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_headerView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_previewView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_headerView]-(>=0)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_navigationFooterView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + // Float the continue view over the previewView if in landscape to give more room for the preview + if (UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_previewView]|" + options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil + views:views]]; + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + _navigationFooterView.backgroundColor = [_navigationFooterView.backgroundColor colorWithAlphaComponent:NavigationFooterViewTranslucentAlpha]; + } else { + [_variableConstraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_previewView]-[_navigationFooterView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + _navigationFooterView.backgroundColor = [_navigationFooterView.backgroundColor colorWithAlphaComponent:NavigationFooterViewOpaqueAlpha]; + } + + [NSLayoutConstraint activateConstraints:_variableConstraints]; + [super updateConstraints]; +} + +- (AVCaptureSession *)session { + return _previewView.session; +} + +- (void)setSession:(AVCaptureSession *)session { + _previewView.session = session; + // Set up the proper videoOrientation from the start + [self orientationDidChange]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + if (_showSkipButtonItem) { + _skipButtonItem = skipButtonItem; + [self updateAppearance]; + } +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + _cancelButtonItem = cancelButtonItem; + [self updateAppearance]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + _continueButtonItem = continueButtonItem; + [self updateAppearance]; +} + +- (void)capturePressed { + // If we are still waiting for the delegate to complete, ignore futher presses + if (_capturePressesIgnored) + return; + + // Ignore futher presses until the delegate completes + _capturePressesIgnored = YES; + + // Capture the image via the delegate + [self.delegate capturePressed:^(BOOL captureSuccess) { + // Stop ignoring presses + _capturePressesIgnored = NO; + }]; +} + +- (void)retakePressed { + // If we are still waiting for the delegate to complete, ignore futher presses + if (_retakePressesIgnored) + return; + + // Ignore futher presses until the delegate completes + _retakePressesIgnored = YES; + + // Tell the delegate to start capturing again + [self.delegate retakePressed:^{ + // Stop ignoring presses + _retakePressesIgnored = NO; + }]; +} + +- (void)sessionWasInterrupted:(NSNotification *)notification { + AVCaptureSessionInterruptionReason reason = [notification.userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]; + if (reason == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps) { + [self setError:[[NSError alloc] initWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"CAMERA_UNAVAILABLE_MESSAGE", nil)}]]; + } +} + +- (void)sessionInterruptionEnded:(NSNotification *)notification { + [self setError:nil]; +} + +- (BOOL)accessibilityPerformMagicTap { + if (self.error) { + return NO; + } + if (self.capturedImage) { + [self retakePressed]; + } else { + [self capturePressed]; + } + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.h new file mode 100755 index 0000000..8fc9949 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Text label under image answer option icon + */ +ORK_CLASS_AVAILABLE +@interface ORKImageChoiceLabel : ORKLabel + +@property (nonatomic, copy, nullable) NSArray *textArray; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.m new file mode 100755 index 0000000..d3e9813 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageChoiceLabel.m @@ -0,0 +1,68 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKImageChoiceLabel.h" + +#import "ORKSubheadlineLabel.h" + + +@implementation ORKImageChoiceLabel + ++ (UIFont *)defaultFont { + return [ORKSubheadlineLabel defaultFont]; +} + +- (CGSize)intrinsicContentSize { + CGSize textSize = CGSizeZero; + if (self.textArray && self.textArray.count > 0) { + // Find the tallest text to make sure cell allocate enough space to accommodate _choiceLabel + for (NSString *text in _textArray) { + CGRect boundingRect = [text boundingRectWithSize:CGSizeMake(self.preferredMaxLayoutWidth, CGFLOAT_MAX) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{NSFontAttributeName: self.font} + context:nil]; + + if (textSize.height < boundingRect.size.height) { + textSize = boundingRect.size; + } + } + return CGSizeMake(ceil(textSize.width), ceil(textSize.height)); + } else { + return [super intrinsicContentSize]; + } +} + +- (void)setTextArray:(NSArray *)textArray { + _textArray = textArray; + [self invalidateIntrinsicContentSize]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.h new file mode 100755 index 0000000..977923f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKAnswerFormat_Internal.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKImageSelectionView; + +@protocol ORKImageSelectionViewDelegate + +- (void)selectionViewSelectionDidChange:(ORKImageSelectionView *)view; + +@end + + +@interface ORKImageSelectionView : UIView + +- (instancetype)initWithImageChoiceAnswerFormat:(ORKImageChoiceAnswerFormat *)answerFormat answer:(nullable id)answer; + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, strong, nullable) id answer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.m new file mode 100755 index 0000000..9e8fb5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKImageSelectionView.m @@ -0,0 +1,450 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKImageSelectionView.h" + +#import "ORKImageChoiceLabel.h" + +#import "ORKChoiceAnswerFormatHelper.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKChoiceButtonView : UIView + +- (instancetype)initWithImageChoice:(ORKImageChoice *)choice; + +@property (nonatomic, strong) UIButton *button; +@property (nonatomic, copy) NSString *labelText; + +@end + + +@implementation ORKChoiceButtonView + +- (instancetype)initWithImageChoice:(ORKImageChoice *)choice { + self = [super init]; + if (self) { + _labelText = choice.text.length > 0 ? choice.text: @" "; + + self.button = [UIButton buttonWithType:UIButtonTypeCustom]; + _button.exclusiveTouch = YES; + + if (choice.selectedStateImage) { + [_button setImage:choice.selectedStateImage forState:UIControlStateSelected]; + } + + [_button setImage:choice.normalStateImage forState:UIControlStateNormal]; + + _button.imageView.contentMode = UIViewContentModeScaleAspectFit; + + [self addSubview:_button]; + ORKEnableAutoLayoutForViews(@[_button, _button.imageView]); + [self setUpConstraints]; + + // Accessibility + NSString *trimmedText = [self.labelText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + if ( trimmedText.length == 0 ) { + self.button.accessibilityLabel = ORKLocalizedString(@"AX_UNLABELED_IMAGE", nil); + } else { + self.button.accessibilityLabel = self.labelText; + } + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = @{ @"button": _button }; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[button]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + UIImage *image = [_button imageForState:UIControlStateNormal]; + if (image.size.height > 0 && image.size.width > 0) { + // Keep Aspect ratio + [constraints addObject:[NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_button.imageView + attribute:NSLayoutAttributeWidth + multiplier:image.size.height / image.size.width + constant:0.0]]; + // button's height <= image + [constraints addObject:[NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:nil attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:image.size.height]]; + } else { + // Keep Aspect ratio + [constraints addObject:[NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_button.imageView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + ORK_Log_Info("The size of imageChoice's normal image should not be zero. %@", image); + } + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end + + +static const CGFloat SpacerWidth = 10.0; +static const CGFloat SpacerHeight = 5.0; + +@implementation ORKImageSelectionView { + ORKChoiceAnswerFormatHelper *_helper; + NSArray *_buttonViews; + ORKImageChoiceLabel *_choiceLabel; + ORKImageChoiceLabel *_placeHolderLabel; + BOOL _isVertical; + BOOL _singleChoice; +} + +- (ORKImageChoiceLabel *)makeLabel { + ORKImageChoiceLabel *label = [[ORKImageChoiceLabel alloc] init]; + label.textAlignment = NSTextAlignmentCenter; + label.numberOfLines = 0; + return label; +} + +- (instancetype)initWithImageChoiceAnswerFormat:(ORKImageChoiceAnswerFormat *)answerFormat answer:(id)answer { + self = [self init]; + if (self) { + + NSAssert([answerFormat isKindOfClass:[ORKImageChoiceAnswerFormat class]], @"answerFormat should be an instance of ORKImageChoiceAnswerFormat"); + + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + _isVertical = answerFormat.isVertical; + + _singleChoice = answerFormat.style == ORKChoiceAnswerStyleSingleChoice; + + _placeHolderLabel = [self makeLabel]; + _placeHolderLabel.text = [ORKLocalizedString(@"PLACEHOLDER_IMAGE_CHOICES", nil) stringByAppendingString:@""]; + _placeHolderLabel.textColor = [UIColor ork_midGrayTintColor]; + + _choiceLabel = [self makeLabel]; + + [self resetLabelText]; + + [self addSubview:_choiceLabel]; + [self addSubview:_placeHolderLabel]; + + NSMutableArray *buttonViews = [NSMutableArray new]; + NSMutableArray *labelTextArray = [NSMutableArray new]; + + NSArray *imageChoices = answerFormat.imageChoices; + for (ORKImageChoice *imageChoice in imageChoices) { + if (imageChoice.text) { + [labelTextArray addObject:imageChoice.text]; + } + + ORKChoiceButtonView *buttonView = [[ORKChoiceButtonView alloc] initWithImageChoice:imageChoice]; + [buttonView.button addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; + [buttonViews addObject:buttonView]; + [self addSubview:buttonView]; + } + + _choiceLabel.textArray = labelTextArray; + _buttonViews = buttonViews; + + for (UILabel *label in @[_choiceLabel, _placeHolderLabel]) { + label.isAccessibilityElement = NO; + } + + ORKEnableAutoLayoutForViews(@[_placeHolderLabel, _choiceLabel]); + ORKEnableAutoLayoutForViews(_buttonViews); + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_choiceLabel]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:@{@"_choiceLabel": _choiceLabel}]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_placeHolderLabel]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:@{@"_placeHolderLabel": _placeHolderLabel}]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_placeHolderLabel + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_choiceLabel + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + ORKChoiceButtonView *previousView = nil; + for (ORKChoiceButtonView *buttonView in _buttonViews) { + NSDictionary *views = NSDictionaryOfVariableBindings(buttonView, _choiceLabel); + + if (!_isVertical) { + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[buttonView]-30-[_choiceLabel]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + if (previousView) { + // ButtonView left trailing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:previousView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:SpacerWidth]]; + + // All ButtonViews has equal width + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:previousView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + } else { + // ButtonView left trailing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:SpacerWidth]]; + } + } else { + if (previousView) { + // ButtonView top spacing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:previousView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:SpacerHeight]]; + + // All ButtonViews has equal height + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:previousView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + + // All ButtonViews has equal width + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:previousView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + } else { + // ButtonView top spacing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:SpacerHeight]]; + } + // ButtonView left trailing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:SpacerWidth]]; + // ButtonView right trailing + [constraints addObject:[NSLayoutConstraint constraintWithItem:buttonView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-SpacerWidth]]; + } + previousView = buttonView; + } + + if (!_isVertical) { + if (previousView) { + // ButtonView right trailing + [constraints addObject:[NSLayoutConstraint constraintWithItem:previousView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-SpacerWidth]]; + } + } else { + if (previousView) { + // ButtonView bottom spacing + [constraints addObject:[NSLayoutConstraint constraintWithItem:previousView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_choiceLabel + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:-30.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_choiceLabel + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + } + } + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + NSArray *selectedIndexes = [_helper selectedIndexesForAnswer:answer]; + + [self setSelectedIndexes:selectedIndexes]; +} + +- (void)resetLabelText { + _placeHolderLabel.hidden = NO; + _choiceLabel.hidden = !_placeHolderLabel.hidden; + +} + +- (void)setLabelText:(NSString *)text { + if (_singleChoice || [text length] > 0) { + _choiceLabel.text = text; + _choiceLabel.textColor = [UIColor blackColor]; + + _choiceLabel.hidden = NO; + _placeHolderLabel.hidden = !_choiceLabel.hidden; + } else { + [self resetLabelText]; + } +} + +- (IBAction)buttonTapped:(UIButton *)button { + button.selected = !button.selected; + + if (button.selected) { + [_buttonViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKChoiceButtonView *buttonView = obj; + if (buttonView.button != button) { + if (_singleChoice) { + buttonView.button.selected = NO; + } + } else { + if (_singleChoice) { + [self setLabelText:buttonView.labelText]; + } else { + [self setLabelText:[_helper labelForChoiceAnswer:[_helper answerForSelectedIndexes:[self selectedIndexes]]]]; + } + } + + }]; + + } else { + if (_singleChoice) { + [self resetLabelText]; + } else { + [self setLabelText:[_helper labelForChoiceAnswer:[_helper answerForSelectedIndexes:[self selectedIndexes]]]]; + } + } + + _answer = [_helper answerForSelectedIndexes:[self selectedIndexes]]; + + if ([_delegate respondsToSelector:@selector(selectionViewSelectionDidChange:)]) { + [_delegate selectionViewSelectionDidChange:self]; + } +} + +- (NSArray *)selectedIndexes { + NSMutableArray *array = [NSMutableArray new]; + + [_buttonViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKChoiceButtonView *buttonView = obj; + if (buttonView.button.selected) + { + [array addObject:@(idx)]; + } + }]; + + return [array copy]; +} + +- (void)setSelectedIndexes:(NSArray *)selectedIndexes { + [selectedIndexes enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) { + if (![object isKindOfClass:[NSNumber class]]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"selectedIndexes should only containt objects of the NSNumber kind" userInfo:nil]; + } + NSNumber *number = object; + if (number.unsignedIntegerValue < _buttonViews.count) { + ORKChoiceButtonView *buttonView = _buttonViews[number.unsignedIntegerValue]; + [buttonView button].selected = YES; + [self setLabelText:buttonView.labelText]; + } + }]; +} + +- (BOOL)isAccessibilityElement { + return NO; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.h new file mode 100755 index 0000000..a20cd28 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An `ORKInstructionStep` object gives the participant instructions for a task. + + You can use instruction steps to present various types of content during a task, such as + introductory content, instructions in the middle + of a task, or a final message at the completion of a task. + +To indicate the completion of a task, consider using an `ORKCompletionStep` object instead. + */ +ORK_CLASS_AVAILABLE +@interface ORKInstructionStep : ORKStep + +/** + Additional attributed explanation for the instruction. + + The attributed detail text is displayed below the content of the `text` property and overrides `detailText`. + */ +@property (nonatomic, copy, nullable) NSAttributedString *attributedDetailText; + +@property (nonatomic) BOOL centerImageVertically; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.m new file mode 100755 index 0000000..3f87128 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStep.m @@ -0,0 +1,81 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKInstructionStep.h" +#import "ORKInstructionStepViewController.h" +#import "ORKStep_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKInstructionStep + + + ++ (Class)stepViewControllerClass { + return [ORKInstructionStepViewController class]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, attributedDetailText, NSAttributedString); + ORK_DECODE_BOOL(aDecoder, centerImageVertically); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_BOOL(aCoder, centerImageVertically); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKInstructionStep *step = [super copyWithZone:zone]; + step.centerImageVertically = self.centerImageVertically; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && self.centerImageVertically == castObject.centerImageVertically; +} + +- (NSUInteger)hash { + return super.hash ^ (_centerImageVertically ? 0xf : 0x0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.h new file mode 100755 index 0000000..082f14c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import "ORKStepContainerView_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKInstructionStep; +@interface ORKInstructionStepContainerView : ORKStepContainerView + +- (instancetype)initWithInstructionStep:(ORKInstructionStep *)instructionStep; + +@property (nonatomic) ORKInstructionStep *instructionStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.m new file mode 100755 index 0000000..acf9046 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepContainerView.m @@ -0,0 +1,74 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKInstructionStepContainerView.h" +#import "ORKBodyItem.h" + +@implementation ORKInstructionStepContainerView + + +- (instancetype)initWithInstructionStep:(ORKInstructionStep *)instructionStep { + self = [super init]; + if (self) { + self.instructionStep = instructionStep; + } + [self setVariables]; + return self; +} + +- (void)setVariables { + self.stepTitle = _instructionStep.title; + self.stepText = _instructionStep.text; + self.stepDetailText = _instructionStep.detailText; + self.stepHeaderTextAlignment = _instructionStep.headerTextAlignment; + self.bodyTextAlignment = _instructionStep.bodyItemTextAlignment; + self.bodyItems = _instructionStep.bodyItems; + self.buildInBodyItems = _instructionStep.buildInBodyItems; + self.useExtendedPadding = _instructionStep.useExtendedPadding; + + self.auxiliaryImage = _instructionStep.auxiliaryImage; + self.titleIconImage = _instructionStep.iconImage; + + [super updatePaddingConstraints]; + if (_instructionStep.centerImageVertically) { + UIImageView *centeredImageView = [UIImageView new]; + centeredImageView.image = _instructionStep.image; + centeredImageView.contentMode = UIViewContentModeScaleAspectFit; + [self setCustomContentView:centeredImageView withTopPadding:80.0]; + [self customContentFillsAvailableSpace]; + } + else { + self.stepTopContentImage = _instructionStep.image; + self.stepTopContentImageContentMode = _instructionStep.imageContentMode; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.h new file mode 100755 index 0000000..08acd1e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKVerticalContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKInstructionStep; + +@interface ORKInstructionStepView : ORKVerticalContainerView + +@property (nonatomic, strong, nullable) ORKInstructionStep *instructionStep; + +@property (nonatomic, strong, nullable) UIImageView *instructionImageView; + +@property (nonatomic, strong, nullable) UIImageView *auxiliaryInstructionImageView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.m new file mode 100755 index 0000000..e881373 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepView.m @@ -0,0 +1,196 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKInstructionStepView.h" + +#import "ORKStepHeaderView_Internal.h" +#import "ORKTintedImageView.h" +#import "ORKVerticalContainerView_Internal.h" + +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKInstructionStep.h" +#import "ORKCompletionStep.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKInstructionStepView { + ORKTintedImageView *_auxiliaryInstructionImageView; + ORKTintedImageView *_instructionImageView; + UIView *_imageContainerView; + BOOL _isCompletionStep; + NSLayoutConstraint *_imageContainerHeightConstraint; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _instructionImageView = [ORKTintedImageView new]; + _instructionImageView.translatesAutoresizingMaskIntoConstraints = NO; + _instructionImageView.contentMode = UIViewContentModeScaleAspectFit; + + _auxiliaryInstructionImageView = [ORKTintedImageView new]; + _auxiliaryInstructionImageView.translatesAutoresizingMaskIntoConstraints = NO; + _auxiliaryInstructionImageView.contentMode = UIViewContentModeScaleAspectFit; + _auxiliaryInstructionImageView.tintColor = ORKColor(ORKAuxiliaryImageTintColorKey); + + _imageContainerView = [[UIView alloc] initWithFrame:frame]; + _imageContainerView.translatesAutoresizingMaskIntoConstraints = NO; + [_imageContainerView addSubview:_auxiliaryInstructionImageView]; + [_imageContainerView addSubview:_instructionImageView]; + + self.stepView = _imageContainerView; + } + return self; +} + +- (void)setInstructionStep:(ORKInstructionStep *)instructionStep { + _instructionStep = instructionStep; + UIImage *image = _instructionStep.image; + UIImage *auxiliaryImage = _instructionStep.auxiliaryImage; + BOOL hasImage = (image != nil); + BOOL hasFootnote = _instructionStep.footnote.length > 0; + + _isCompletionStep = [_instructionStep isKindOfClass:[ORKCompletionStep class]]; + + self.verticalCenteringEnabled = NO; + self.continueHugsContent = !hasImage && !hasFootnote; + self.stepViewFillsAvailableSpace = ((hasImage || hasFootnote) && !_isCompletionStep); + + _instructionImageView.image = image; + _instructionImageView.shouldApplyTint = instructionStep.shouldTintImages; + _auxiliaryInstructionImageView.image = auxiliaryImage; + _auxiliaryInstructionImageView.shouldApplyTint = instructionStep.shouldTintImages; + + CGSize imageSize = image.size; + if (imageSize.width > 0 && imageSize.height > 0) { + [NSLayoutConstraint deactivateConstraints:[_imageContainerView constraints]]; + NSMutableArray *constraints = [NSMutableArray new]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_imageContainerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_imageContainerView + attribute:NSLayoutAttributeWidth + multiplier:imageSize.height / imageSize.width + constant:0.0]]; + + _imageContainerHeightConstraint = [NSLayoutConstraint constraintWithItem:_imageContainerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:300.0]; + + [constraints addObject:_imageContainerHeightConstraint]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_instructionImageView, _auxiliaryInstructionImageView); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_instructionImageView]|" + options:0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_instructionImageView]|" + options:0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_auxiliaryInstructionImageView]|" + options:0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_auxiliaryInstructionImageView]|" + options:0 + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; + + _instructionImageView.isAccessibilityElement = YES; + _instructionImageView.accessibilityLabel = [NSString stringWithFormat:ORKLocalizedString(@"AX_IMAGE_ILLUSTRATION", nil), _instructionStep.title]; + } else { + _instructionImageView.isAccessibilityElement = NO; + } + + self.headerView.iconImageView.image = _instructionStep.iconImage; + + NSMutableAttributedString *attributedInstruction = [[NSMutableAttributedString alloc] init]; + NSAttributedString *attributedDetail = _instructionStep.attributedDetailText; + NSString *detail = _instructionStep.detailText; + NSString *text = _instructionStep.text; + attributedDetail = attributedDetail.length ? attributedDetail : nil; + detail = detail.length ? detail : nil; + text = text.length ? text : nil; + + if (attributedDetail && text) { + [attributedInstruction appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n", text] attributes:nil]]; + + NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; + [style setParagraphSpacingBefore:self.headerView.instructionLabel.font.lineHeight * 0.5]; + [style setAlignment:NSTextAlignmentNatural]; + + [attributedInstruction appendAttributedString:attributedDetail]; + + } else if (detail && text) { + [attributedInstruction appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n", text] attributes:nil]]; + + NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; + [style setParagraphSpacingBefore:self.headerView.instructionLabel.font.lineHeight * 0.5]; + [style setAlignment:NSTextAlignmentNatural]; + + NSAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:detail + attributes:@{NSParagraphStyleAttributeName: style}]; + [attributedInstruction appendAttributedString:attString]; + + } else if (attributedDetail || detail || text) { + if (attributedDetail) { + [attributedInstruction appendAttributedString:attributedDetail]; + } else { + [attributedInstruction appendAttributedString:[[NSAttributedString alloc] initWithString:detail ? : text attributes:nil]]; + } + } + + self.headerView.instructionLabel.attributedText = attributedInstruction; + + [self tintColorDidChange]; + + [self setNeedsUpdateConstraints]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + [super updateConstraintConstantsForWindow:window]; + + const CGFloat IllustrationHeight = ORKGetMetricForWindow(ORKScreenMetricInstructionImageHeight, window); + _imageContainerHeightConstraint.constant = (_instructionImageView.image ? IllustrationHeight : 0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.h new file mode 100755 index 0000000..9e2ce12 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An `ORKInstructionStepViewController` object is the view controller for an `ORKInstructionStep` object. + + In general, you don't need to instantiate an instruction step view controller directly. + Instead, add an instruction step to a task and present the task using a + task view controller. When appropriate, the task view controller instantiates the step + view controller for the step. + */ +ORK_CLASS_AVAILABLE +@interface ORKInstructionStepViewController : ORKStepViewController + +- (void)buildInNextBodyItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.m new file mode 100755 index 0000000..2120ddc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController.m @@ -0,0 +1,231 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKInstructionStepViewController.h" +#import "ORKLearnMoreStepViewController.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKInstructionStepContainerView.h" +#import "ORKStepView_Private.h" +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKInstructionStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +#import "ORKBodyContainerView.h" +#import "ORKStepContentView.h" +#import "ORKStepContentView_Private.h" + +@class ORKBodyContainerView; + +@interface ORKInstructionStepViewController() + +@end + +@implementation ORKInstructionStepViewController { + ORKNavigationContainerView *_navigationFooterView; + NSArray *_constraints; +} + +- (ORKInstructionStep *)instructionStep { + return (ORKInstructionStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [self.stepView removeFromSuperview]; + self.stepView = nil; + + if (self.step && [self isViewLoaded]) { + self.stepView = [[ORKInstructionStepContainerView alloc] initWithInstructionStep:[self instructionStep]]; + _stepView.delegate = self; + _stepView.stepContentView.bodyContainerView.bodyItemDelegate = self; + [self.view addSubview:self.stepView]; + [self setNavigationFooterView]; + [self setupConstraints]; + } +} + +- (void)setNavigationFooterView { + if (_stepView) { + _navigationFooterView = _stepView.navigationFooterView; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.hidden = self.isBeingReviewed; + _navigationFooterView.optional = [self instructionStep].isOptional; + _navigationFooterView.footnoteLabel.text = [self instructionStep].footnote; + [_navigationFooterView updateContinueAndSkipEnabled]; + } +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + self.stepView.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + _constraints = @[ + [NSLayoutConstraint constraintWithItem:self.stepView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewWillAppear:(BOOL)animated { + + if ([self.taskViewController isStepLastBeginningInstructionStep:self.step]) { + [self useAppropriateButtonTitleAsLastBeginningInstructionStep]; + } + + [super viewWillAppear:animated]; + [self.taskViewController.navigationBar setBarTintColor:self.view.backgroundColor]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self stepDidChange]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [_stepView setNeedsUpdateConstraints]; + + if (self.step.buildInBodyItems == YES) { + UIView *lastVisibleBodyItem = [_stepView.stepContentView.bodyContainerView lastVisibleBodyItem]; + [_stepView updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO customView:lastVisibleBodyItem]; + } else { + [_stepView updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO]; + } +} + +- (void)useAppropriateButtonTitleAsLastBeginningInstructionStep { + if (self.continueButtonTitle == nil) { + self.internalContinueButtonItem.title = ORKLocalizedString(@"BUTTON_GET_STARTED", nil); + } +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.skipEnabled = self.skipButtonItem ? YES : NO; +} + +- (void)buildInNextBodyItem { + [_stepView.stepContentView.bodyContainerView updateBodyItemViews]; + + UIView *lastView = [_stepView.stepContentView.bodyContainerView lastVisibleBodyItem]; + [_stepView scrollToBodyItem:lastView]; + [_stepView updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO customView:lastView]; +} + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; +} + +#pragma mark - ORKStepContainerLearnMoreItemDelegate + +- (void)stepViewLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep { + /* + In some cases we want to allow the parent application to intercept the learn more callback in learn more instruction steps. These + should get handled the same way as other learn more callbacks at the task level. If the app responds to this delegate, it get's + higher prioriy and it becomes the responsibility of the developer to handle all cases. + + If not implemented, default to showing the learnMore view controller for the the step. + */ + if ([self.taskViewController.delegate respondsToSelector:@selector(taskViewController:learnMoreButtonPressedWithStep:forStepViewController:)]) { + [self.taskViewController.delegate taskViewController:self.taskViewController learnMoreButtonPressedWithStep:learnMoreStep forStepViewController:self]; + } else { + UINavigationController *navigationViewController = [[UINavigationController alloc] initWithRootViewController: [self.taskViewController learnMoreViewControllerForStep:learnMoreStep]]; + [navigationViewController.navigationBar setPrefersLargeTitles:NO]; + [self presentViewController:navigationViewController + animated:YES + completion:nil]; + } +} + +- (void)goForward { + if (([self instructionStep].buildInBodyItems == YES) && ([_stepView.stepContentView.bodyContainerView hasShownAllBodyItem] == NO)) { + [self buildInNextBodyItem]; + } else { + [super goForward]; + } +} + +- (void)bodyContainerViewDidLoadBodyItems { + if ([self.stepView buildInBodyItems] == YES) { + UIView *lastVisibleBodyItem = [_stepView.stepContentView.bodyContainerView lastVisibleBodyItem]; + [_stepView updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO customView:lastVisibleBodyItem]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController_Internal.h new file mode 100755 index 0000000..14784cb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKInstructionStepViewController_Internal.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKInstructionStepContainerView; +@class ORKNavigationContainerView; + +@interface ORKInstructionStepViewController () + +@property (nonatomic, strong, nullable) ORKInstructionStepContainerView *stepView; + +// Use button title "Get started" instead of "Next". +- (void)useAppropriateButtonTitleAsLastBeginningInstructionStep; + +- (void)stepDidChange; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.h new file mode 100755 index 0000000..3b76b6a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.h @@ -0,0 +1,96 @@ + /** + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKKeychainWrapper` class is an abstraction layer for the iOS keychain + communication. + */ +ORK_CLASS_AVAILABLE +@interface ORKKeychainWrapper : NSObject + +/** + Sets the given object in the keychain for the provided key. + + @param object The data to be stored in the keychain. + @param key The key used to set the data in the keychain. + @param error If failure occurred, an `NSError` object indicating the reason for the + failure. The value of this parameter is `nil` if `result` does not + indicate failure. + + @return A boolean with a value `YES` if the object was saved; otherwise `NO'. + */ ++ (BOOL)setObject:(id)object forKey:(NSString *)key error:(NSError * _Nullable *)error; + + +/** + Returns the object in the keychain for the provided key. + + @param key The key used to set the data in the keychain. + @param error If failure occurred, an `NSError` object indicating the reason for the + failure. The value of this parameter is `nil` if `result` does not + indicate failure. + + @return An object or `nil` if key is not valid. + */ ++ (nullable id)objectForKey:(nonnull NSString *)key error:(NSError * __autoreleasing _Nullable *)error; + +/** + Removes the object in the keychain for the provided key. + + @param key The key used to set the value in the keychain. + @param error If failure occurred, an `NSError` object indicating the reason for the + failure. The value of this parameter is `nil` if `result` does not + indicate failure. + + @return A boolean with a value `YES` if the object was removed; otherwise `NO'. +*/ ++ (BOOL)removeObjectForKey:(NSString *)key error:(NSError * _Nullable *)error; + +/** + Removes all values stored in the keychain for the app. + + @param error If failure occurred, an `NSError` object indicating the reason for the + failure. The value of this parameter is `nil` if `result` does not + indicate failure. + + @return A boolean with a value `YES` if the keychain was reset; otherwise `NO'. +*/ ++ (BOOL)resetKeychainWithError:(NSError * _Nullable *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.m new file mode 100755 index 0000000..b3b18a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKKeychainWrapper.m @@ -0,0 +1,301 @@ + /** + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKKeychainWrapper.h" + +#import "ORKHelpers_Internal.h" + + +static NSString *ORKKeychainWrapperDefaultService() { + static NSString *defaultService; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + defaultService = [[NSBundle mainBundle] bundleIdentifier]; + }); + return defaultService; +} + +@implementation ORKKeychainWrapper + +#pragma mark - Public Methods + ++ (BOOL)setObject:(id)object + forKey:(NSString *)key + error:(NSError **)errorOut { + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object]; + return [self setData:data + forKey:key + service:ORKKeychainWrapperDefaultService() + accessGroup:nil + error:errorOut]; +} + ++ (id)objectForKey:(NSString *)key + error:(NSError **)errorOut { + NSData *data = [self dataForKey:key + service:ORKKeychainWrapperDefaultService() + accessGroup:nil + error:errorOut]; + return data ? [NSKeyedUnarchiver unarchiveObjectWithData:data] : nil; +} + ++ (BOOL)removeObjectForKey:(NSString *)key + error:(NSError **)errorOut { + return [self removeItemForKey:key + service:ORKKeychainWrapperDefaultService() + accessGroup:nil + error:errorOut]; +} + ++ (BOOL)resetKeychainWithError:(NSError **)errorOut { + return [self removeAllItemsForService:ORKKeychainWrapperDefaultService() + accessGroup:nil + error:errorOut]; +} + +#pragma mark - Private Methods + ++ (NSData *)dataForKey:(NSString *)key + service:(NSString *)service + accessGroup:(NSString *)accessGroup + error:(NSError **)errorOut { + NSData *returnValue = nil; + if (key) { + if (!service) { + service = ORKKeychainWrapperDefaultService(); + } + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; + [query setObject:service forKey:(__bridge id)kSecAttrService]; + [query setObject:key forKey:(__bridge id)kSecAttrAccount]; +#if !TARGET_IPHONE_SIMULATOR && defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + if (accessGroup) { + [query setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + + CFTypeRef data = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &data); + if (status != errSecSuccess) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_FIND_ERROR_MESSAGE", nil)}]; + } + } else { + returnValue = [NSData dataWithData:(__bridge NSData *)data]; + if (data) { + CFRelease(data); + } + } + } + return returnValue; +} + ++ (BOOL)setData:(NSData *)data + forKey:(NSString *)key + service:(NSString *)service + accessGroup:(NSString *)accessGroup + error:(NSError **)errorOut { + BOOL returnValue = YES; + if (key) { + if (!service) { + service = ORKKeychainWrapperDefaultService(); + } + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [query setObject:service forKey:(__bridge id)kSecAttrService]; + [query setObject:key forKey:(__bridge id)kSecAttrAccount]; +#if !TARGET_IPHONE_SIMULATOR && defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + if (accessGroup) { + [query setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL); + if (status == errSecSuccess) { + if (data) { + NSMutableDictionary *attributesToUpdate = [[NSMutableDictionary alloc] init]; + [attributesToUpdate setObject:data forKey:(__bridge id)kSecValueData]; + + status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributesToUpdate); + if (status != errSecSuccess) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_UPDATE_ERROR_MESSAGE", nil)}]; + } + returnValue = NO; + } + } else { + [self removeItemForKey:key service:service accessGroup:accessGroup error:errorOut]; + } + } else if (status == errSecItemNotFound) { + NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; + [attributes setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [attributes setObject:service forKey:(__bridge id)kSecAttrService]; + [attributes setObject:key forKey:(__bridge id)kSecAttrAccount]; +#if TARGET_OS_IPHONE || (defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9) + [attributes setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id)kSecAttrAccessible]; +#endif + [attributes setObject:data forKey:(__bridge id)kSecValueData]; +#if !TARGET_IPHONE_SIMULATOR && defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + if (accessGroup) { + [attributes setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + + status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL); + if (status != errSecSuccess) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_ADD_ERROR_MESSAGE", nil)}]; + } + returnValue = NO; + } + } else { + returnValue = NO; + } + } + return returnValue; +} + ++ (BOOL)removeItemForKey:(NSString *)key + service:(NSString *)service + accessGroup:(NSString *)accessGroup + error:(NSError **)errorOut { + BOOL returnValue = NO; + if (key) { + if (!service) { + service = ORKKeychainWrapperDefaultService(); + } + + NSMutableDictionary *itemToDelete = [[NSMutableDictionary alloc] init]; + [itemToDelete setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [itemToDelete setObject:service forKey:(__bridge id)kSecAttrService]; + [itemToDelete setObject:key forKey:(__bridge id)kSecAttrAccount]; +#if !TARGET_IPHONE_SIMULATOR && defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + if (accessGroup) { + [itemToDelete setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)itemToDelete); + if (status != errSecSuccess && status != errSecItemNotFound) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_DELETE_ERROR_MESSAGE", nil)}]; + } + returnValue = NO; + } else { + returnValue = YES; + } + } + return returnValue; +} + ++ (BOOL)removeAllItemsForService:(NSString *)service + accessGroup:(NSString *)accessGroup + error:(NSError **)errorOut { + NSArray *items = [self itemsForService:service accessGroup:accessGroup error:errorOut]; + BOOL returnValue = NO; + + if ([items count] > 0) { + for (NSDictionary *item in items) { + NSMutableDictionary *itemToDelete = [[NSMutableDictionary alloc] initWithDictionary:item]; + [itemToDelete setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)itemToDelete); + if (status != errSecSuccess) { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_DELETE_ERROR_MESSAGE", nil)}]; + } + returnValue = NO; + } else { + returnValue = YES; + } + } + } else { + returnValue = YES; + } + + return returnValue; +} + ++ (NSArray *)itemsForService:(NSString *)service + accessGroup:(NSString *)accessGroup + error:(NSError **)errorOut { + if (!service) { + service = ORKKeychainWrapperDefaultService(); + } + + NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; + [query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; + [query setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes]; + [query setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; + [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit]; + [query setObject:service forKey:(__bridge id)kSecAttrService]; +#if !TARGET_IPHONE_SIMULATOR && defined(__IPHONE_OS_VERSION_MIN_REQUIRED) + if (accessGroup) { + [query setObject:accessGroup forKey:(__bridge id)kSecAttrAccessGroup]; + } +#endif + + CFTypeRef result = nil; + NSArray *returnValue = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); + if (status == errSecSuccess || status == errSecItemNotFound) { + returnValue = (__bridge NSArray *)(result); + } else { + if (errorOut != NULL) { + *errorOut = [NSError errorWithDomain:NSOSStatusErrorDomain + code:status + userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"KEYCHAIN_FIND_ERROR_MESSAGE", nil)}]; + } + returnValue = nil; + } + + if(result) { + CFBridgingRelease(result); + } + + return returnValue; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.h new file mode 100755 index 0000000..18c06bd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefaultFont.h" +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + This is a base class, not being used directly. + */ +ORK_CLASS_AVAILABLE +@interface ORKLabel : UILabel + +@end + +@interface ORKLabel () + +- (void)init_ORKLabel; + +- (void)updateAppearance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.m new file mode 100755 index 0000000..dd76a15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLabel.m @@ -0,0 +1,82 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLabel.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKLabel + +- (instancetype)init { + self = [super init]; + if (self) { + [self init_ORKLabel]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self init_ORKLabel]; + } + return self; +} + +- (void)init_ORKLabel { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateAppearance) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + self.font = [[self class] defaultFont]; + [self updateAppearance]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateAppearance]; +} + +- (void)updateAppearance { + [self invalidateIntrinsicContentSize]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return ORKMediumFontWithSize(((NSNumber *)[descriptor objectForKey: UIFontDescriptorSizeAttribute]).doubleValue + 3.0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.h new file mode 100755 index 0000000..c001657 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKLearnMoreInstructionStep : ORKInstructionStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.m new file mode 100755 index 0000000..04d0388 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreInstructionStep.m @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLearnMoreInstructionStep.h" +#import "ORKLearnMoreStepViewController.h" + +@implementation ORKLearnMoreInstructionStep + ++ (Class)stepViewControllerClass { + return [ORKLearnMoreStepViewController class]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.h new file mode 100755 index 0000000..cea1f6e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "ORKDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKLearnMoreInstructionStep; + +ORK_CLASS_AVAILABLE +@interface ORKLearnMoreItem : NSObject + + +/** + * Returns an initialized `ORKLearnMoreItem` using specified values. + + @param text Text to be used in title label of button. If nil, the button is initialized with type `UIButtonTypeDetailDisclosure`. + @param learnMoreInstructionStep The `ORKLearnMoreInstructionStep` to be presented when button is pressed. + @return An initialized learn more item. + */ +- (instancetype)initWithText:(nullable NSString *)text learnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep; + +/** + * Convenience class initializer to create a button. + * Using this initializer initializes the button with type `UIButtonTypeCustom`, and assures that button's title label will have text. + * Returns an initialized `ORKLearnMoreItem` using specified values. + + @param text Text to be used as title label of button. + @param learnMoreInstructionStep The `ORKLearnMoreInstructionStep` to be used in `ORKLearnMoreStepViewController` to present when the button is pressed. + @return An inittialized learn more item. + */ ++ (instancetype)learnMoreItemWithText:(NSString *)text learnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep; + +/** + Text to be used in title label of button. + */ +@property (nonatomic, nullable) NSString *text; + +/** + The `ORKLearnMoreInstructionStep` to be presented when the button is pressed. + */ +@property (nonatomic, nonnull) ORKLearnMoreInstructionStep *learnMoreInstructionStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.m new file mode 100755 index 0000000..e038a02 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreItem.m @@ -0,0 +1,91 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLearnMoreItem.h" +#import "ORKLearnMoreInstructionStep.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKLearnMoreItem + +- (instancetype)initWithText:(nullable NSString *)text learnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep { + self = [super init]; + if (self) { + self.text = text; + self.learnMoreInstructionStep = learnMoreInstructionStep; + } + return self; +} + ++ (instancetype)learnMoreItemWithText:(NSString *)text learnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep { + return [[ORKLearnMoreItem alloc] initWithText:text learnMoreInstructionStep:learnMoreInstructionStep]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + ORKLearnMoreItem *learnMoreItem = [[[self class] allocWithZone:zone] init]; + learnMoreItem->_text = [self.text copy]; + learnMoreItem->_learnMoreInstructionStep = [self.learnMoreInstructionStep copy]; + return learnMoreItem; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, learnMoreInstructionStep); +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, learnMoreInstructionStep, ORKLearnMoreInstructionStep); + } + return self; +} + +- (NSUInteger)hash { + return _text.hash ^ _learnMoreInstructionStep.hash; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.learnMoreInstructionStep, castObject.learnMoreInstructionStep)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.h new file mode 100755 index 0000000..a79066d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKLearnMoreStepViewController : ORKInstructionStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.m new file mode 100755 index 0000000..43e9003 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreStepViewController.m @@ -0,0 +1,69 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLearnMoreStepViewController.h" +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKInstructionStepContainerView.h" +#import "ORKStepView_Private.h" +#import "ORKNavigationContainerView.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKLearnMoreStepViewController + +- (void)stepDidChange { + [super stepDidChange]; + [self.stepView.navigationFooterView setHidden:YES]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + if (self.navigationItem.leftBarButtonItem) { + self.navigationItem.leftBarButtonItem = nil; + } + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = [UIColor systemBackgroundColor]; + self.navigationController.navigationBar.backgroundColor = UIColor.systemBackgroundColor; + } else { + self.view.backgroundColor = [UIColor whiteColor]; + self.navigationController.navigationBar.backgroundColor = UIColor.whiteColor; + } + + [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + self.navigationController.navigationBar.shadowImage = [UIImage new]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_DONE", nil) style:UIBarButtonItemStyleDone target:self action:@selector(doneButtonPressed:)]; +} + +- (void)doneButtonPressed:(id)sender { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.h new file mode 100755 index 0000000..360c1dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + + + +@class ORKLearnMoreInstructionStep; +@class ORKLearnMoreItem; +@protocol ORKLearnMoreViewDelegate + +@required +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep; + +@end + + +@interface ORKLearnMoreView : UIView + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + ++ (instancetype)learnMoreCustomButtonViewWithText:(NSString *)text LearnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep; + ++ (instancetype)learnMoreDetailDisclosureButtonViewWithLearnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep; + ++ (instancetype)learnMoreViewWithItem:(ORKLearnMoreItem *)learnMoreItem; + +@property (nonatomic, nonnull) ORKLearnMoreInstructionStep *learnMoreInstructionStep; + +@property (nonatomic, weak) id delegate; + +- (void)setLearnMoreButtonFont: (UIFont *)font; + +- (void)setLearnMoreButtonTextAlignment:(NSTextAlignment)textAlignment; + +- (BOOL)isTextLink; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.m new file mode 100755 index 0000000..4f45a94 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLearnMoreView.m @@ -0,0 +1,197 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLearnMoreView.h" +#import "ORKLearnMoreItem.h" +#import "ORKHelpers_Internal.h" +#import "ORKBodyItem.h" + +ORK_CLASS_AVAILABLE +@interface ORKLearnMoreButton : UIButton + ++ (instancetype)buttonWithType:(UIButtonType)buttonType NS_UNAVAILABLE; + ++ (instancetype)learnMoreCustomButtonWithText:(NSString *)text; + ++ (instancetype)learnMoreDetailDisclosureButton; + + +@end + + +@implementation ORKLearnMoreButton + ++ (instancetype)buttonWithType:(UIButtonType)buttonType { + ORKThrowMethodUnavailableException(); +} + ++ (instancetype)learnMoreCustomButtonWithText:(NSString *)text { + ORKLearnMoreButton *button = [super buttonWithType:UIButtonTypeCustom]; + [button setTitle:text forState:UIControlStateNormal]; + [button setTitleColor:button.tintColor forState:UIControlStateNormal]; + button.titleLabel.numberOfLines = 0; + button.titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [button setContentEdgeInsets:UIEdgeInsetsMake(CGFLOAT_MIN, CGFLOAT_MIN, CGFLOAT_MIN, CGFLOAT_MIN)]; + return button; +} + ++ (instancetype)learnMoreDetailDisclosureButton { + ORKLearnMoreButton *button = [super buttonWithType:UIButtonTypeDetailDisclosure]; + return button; +} + +- (void)setNeedsLayout { + [super setNeedsLayout]; + [self.titleLabel invalidateIntrinsicContentSize]; +} + +@end + +@interface ORKLearnMoreView() + +@property (nonatomic, nonnull) ORKLearnMoreButton *learnMoreButton; + +@end + +@implementation ORKLearnMoreView { + ORKLearnMoreButton *_learnMoreButton; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + ORKThrowMethodUnavailableException(); +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithLearnMoreStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep { + self = [super init]; + if (self) { + self.learnMoreInstructionStep = learnMoreInstructionStep; + } + return self; +} + ++ (instancetype)learnMoreCustomButtonViewWithText:(NSString *)text LearnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep { + ORKLearnMoreView *learnMoreView = [[ORKLearnMoreView alloc] initWithLearnMoreStep:learnMoreInstructionStep]; + [learnMoreView setupCustomButtonWithText:text]; + return learnMoreView; +} + ++ (instancetype)learnMoreDetailDisclosureButtonViewWithLearnMoreInstructionStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep { + ORKLearnMoreView *learnMoreView = [[ORKLearnMoreView alloc] initWithLearnMoreStep:learnMoreInstructionStep]; + [learnMoreView setupDetailDisclosureButton]; + return learnMoreView; +} + ++ (instancetype)learnMoreViewWithItem:(ORKLearnMoreItem *)learnMoreItem { + return learnMoreItem.text ? [ORKLearnMoreView learnMoreCustomButtonViewWithText:learnMoreItem.text LearnMoreInstructionStep:learnMoreItem.learnMoreInstructionStep] : [ORKLearnMoreView learnMoreDetailDisclosureButtonViewWithLearnMoreInstructionStep:learnMoreItem.learnMoreInstructionStep]; +} + +- (void)setupCustomButtonWithText:(NSString *)text { + if (!_learnMoreButton) { + _learnMoreButton = [ORKLearnMoreButton learnMoreCustomButtonWithText:text]; + } + [self addSubview:_learnMoreButton]; + [_learnMoreButton addTarget:self action:@selector(presentLearnMoreViewController) forControlEvents:UIControlEventTouchUpInside]; + [self setupConstraints]; +} + +- (void)setupDetailDisclosureButton { + if (!_learnMoreButton) { + _learnMoreButton = [ORKLearnMoreButton learnMoreDetailDisclosureButton]; + } + [self addSubview:_learnMoreButton]; + [_learnMoreButton addTarget:self action:@selector(presentLearnMoreViewController) forControlEvents:UIControlEventTouchUpInside]; + [self setupConstraints]; +} + +- (void)setLearnMoreButtonFont: (UIFont *)font { + if (_learnMoreButton) { + [_learnMoreButton.titleLabel setFont:font]; + } +} + +- (void)setLearnMoreButtonTextAlignment:(NSTextAlignment)textAlignment { + if (textAlignment == NSTextAlignmentLeft) { + [_learnMoreButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft]; + } else { + _learnMoreButton.titleLabel.textAlignment = textAlignment; + } +} + +- (BOOL)isTextLink { + return _learnMoreButton.titleLabel.text.length > 0; +} + +- (void)setupConstraints { + _learnMoreButton.translatesAutoresizingMaskIntoConstraints = NO; + [_learnMoreButton setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; + NSArray *constraints = @[ + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_learnMoreButton + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_learnMoreButton + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_learnMoreButton + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_learnMoreButton + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)presentLearnMoreViewController { + NSAssert(_delegate, @"Learn More View requires a delegate"); + [_delegate learnMoreButtonPressedWithStep:_learnMoreInstructionStep]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.h new file mode 100755 index 0000000..acc27dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.h @@ -0,0 +1,94 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerTextField; +@class ORKLocationSelectionView; + +@protocol ORKLocationSelectionViewDelegate + +- (void)locationSelectionViewDidChange:(ORKLocationSelectionView *)view; + +@optional + +- (void)locationSelectionViewDidBeginEditing:(ORKLocationSelectionView *)view; + +- (void)locationSelectionViewDidEndEditing:(ORKLocationSelectionView *)view; + +- (void)locationSelectionViewNeedsResize:(ORKLocationSelectionView *)view; + +@required + +- (void)locationSelectionView:(ORKLocationSelectionView *)view didFailWithErrorTitle:(NSString *)title message:(NSString *)message; + +@end + + +@interface ORKLocationSelectionView : UIView + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, strong, nullable) id answer; + +@property (nonatomic, assign) BOOL useCurrentLocation; + +@property (nonatomic, strong, readonly) ORKAnswerTextField *textField; + +- (instancetype)initWithFormMode:(BOOL)formMode + useCurrentLocation:(BOOL)useCurrentLocation + leadingMargin:(CGFloat)leadingMargin; + +- (void)setPlaceholderText:(nullable NSString *)text; + +- (void)setTextColor:(UIColor *)color; + +- (void)showMapViewIfNecessary; + ++ (CGFloat)textFieldHeight; + ++ (CGFloat)textFieldBottomMargin; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.m new file mode 100755 index 0000000..d7a7447 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKLocationSelectionView.m @@ -0,0 +1,495 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLocationSelectionView.h" + +#import "ORKAnswerTextField.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionResult_Private.h" +#import "ORKResult_Private.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@import MapKit; + + +static const NSString *FormattedAddressLines = @"FormattedAddressLines"; + +@interface ORKLocationSelectionView () + +@property (nonatomic, strong) NSLayoutConstraint *mapViewHeightConstraint; +@property (nonatomic, strong, readwrite) ORKAnswerTextField *textField; +@property (nonatomic, strong) MKMapView *mapView; + +@end + + +@interface CLPlacemark (ork_addressLine) + +@property (nonatomic, copy, readonly) NSString* ork_addressLine; + +@end + + +@implementation CLPlacemark (ork_addressLine) + +- (NSString *)ork_addressLine { + return [CNPostalAddressFormatter stringFromPostalAddress:self.postalAddress + style:CNPostalAddressFormatterStyleMailingAddress]; +} + +@end + + +@implementation ORKLocationSelectionView { + CLLocationManager *_locationManager; + BOOL _userLocationNeedsUpdate; + MKCoordinateRegion _initalCoordinateRegion; + BOOL _setInitialCoordinateRegion; + CGFloat _mapHorizontalMargin; + CGFloat _textFieldHorizontalMargin; + + UIView *_seperator1; + UIView *_seperator2; + UIView *_seperator3; +} + ++ (CGFloat)textFieldHeight { + return ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, nil); +} + ++ (CGFloat)textFieldBottomMargin { + static CGFloat textFieldBottomMargin = 0; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + textFieldBottomMargin = 1.0 / [UIScreen mainScreen].scale; + }); + return textFieldBottomMargin; +} + +- (instancetype)initWithFormMode:(BOOL)formMode + useCurrentLocation:(BOOL)useCurrentLocation + leadingMargin:(CGFloat)leadingMargin { + if (NO == formMode) { + self = [super initWithFrame:CGRectMake(0.0, 0.0, 200.0, [self.class textFieldHeight] + [ORKLocationSelectionView.class textFieldBottomMargin]*2 + ORKGetMetricForWindow(ORKScreenMetricLocationQuestionMapHeight, self.window))]; + } else { + self = [super initWithFrame:CGRectMake(0.0, 0.0, 200.0, [self.class textFieldHeight])]; + } + + if (self) { + _textField = [[ORKAnswerTextField alloc] init]; + _textField.delegate = self; + _textField.placeholder = ORKLocalizedString(@"LOCATION_QUESTION_PLACEHOLDER", nil); + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.returnKeyType = UIReturnKeySearch; + _textField.adjustsFontSizeToFitWidth = YES; + + _mapView = [[MKMapView alloc] init]; + _mapView.delegate = self; + + _useCurrentLocation = useCurrentLocation; + _textFieldHorizontalMargin = leadingMargin; + _mapHorizontalMargin = formMode ? leadingMargin : 0; + + [self addSubview:_textField]; + + if (NO == formMode) { + // For Question step + _seperator1 = [[UIView alloc] init]; + _seperator1.backgroundColor = [UIColor ork_midGrayTintColor]; + _seperator2 = [[UIView alloc] init]; + _seperator2.backgroundColor = [UIColor ork_midGrayTintColor]; + _seperator3 = [[UIView alloc] init]; + _seperator3.backgroundColor = [UIColor ork_midGrayTintColor]; + [self addSubview:_seperator1]; + [self addSubview:_seperator2]; + [self addSubview:_seperator3]; + } + + [self setUpGestureRecognizer]; + [self setUpConstraints]; + + if (NO == formMode) { + [self showMapViewIfNecessary]; + } + + + } + + return self; +} + +- (void)setUpGestureRecognizer { + UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(addPlacemarkToMap:)]; + lpgr.minimumPressDuration = 1.0; // press for 1 second + [_mapView addGestureRecognizer:lpgr]; +} + +- (void)addPlacemarkToMap:(UIGestureRecognizer *)gestureRecognizer { + if (gestureRecognizer.state != UIGestureRecognizerStateBegan) { + return; + } + + CGPoint touchPoint = [gestureRecognizer locationInView:_mapView]; + CLLocationCoordinate2D touchMapCoordinate = [_mapView convertPoint:touchPoint toCoordinateFromView:_mapView]; + + MKPointAnnotation *annotation = [MKPointAnnotation new]; + annotation.coordinate = touchMapCoordinate; + [_mapView addAnnotation:annotation]; + + ORKLocation *pinLocation = [[ORKLocation alloc] initWithCoordinate:touchMapCoordinate region:nil userInput:nil postalAddress:nil]; + [self setAnswer:pinLocation]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_textField); + ORKEnableAutoLayoutForViews([views allValues]); + + NSDictionary *metrics = @{@"horizontalMargin": @(_textFieldHorizontalMargin)}; + if (_seperator1) { + _seperator1.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *seperators = NSDictionaryOfVariableBindings(_seperator1); + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textField attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_seperator1 attribute:NSLayoutAttributeTop multiplier:1.0 constant:-1.0/[UIScreen mainScreen].scale]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_seperator1 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:1.0 / [UIScreen mainScreen].scale]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_seperator1]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:seperators]]; + } + + if (_seperator2) { + _seperator2.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *seperators = NSDictionaryOfVariableBindings(_seperator2); + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textField attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_seperator2 attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_seperator2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:1.0 / [UIScreen mainScreen].scale]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_seperator2]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:seperators]]; + } + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textField attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textField attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:[self.class textFieldHeight]]]; + + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(horizontalMargin)-[_textField]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:metrics views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setPlaceholderText:(NSString *)text { + _textField.placeholder = text; +} + +- (void)setTextColor:(UIColor *)color { + _textField.textColor = color; +} + +- (NSString *)enteredLocation { + return [_textField.text copy]; +} + +- (BOOL)becomeFirstResponder { + return [_textField becomeFirstResponder]; +} + +- (BOOL)isFirstResponder { + return [_textField isFirstResponder]; +} + +- (BOOL)resignFirstResponder { + BOOL didResign = [super resignFirstResponder]; + didResign = [_textField resignFirstResponder] || didResign; + return didResign; +} + +- (CGSize)intrinsicContentSize { + CGFloat height = [self.class textFieldHeight] + (_mapView.superview == nil ? 0.0 : [ORKLocationSelectionView.class textFieldBottomMargin]*2 + ORKGetMetricForWindow(ORKScreenMetricLocationQuestionMapHeight, self.window)); + return CGSizeMake(40, height); +} + +- (void)showMapViewIfNecessary { + if (_mapView.superview) { + return; + } + + _mapView.frame = CGRectMake(0.0, 0.0, self.bounds.size.width, 0.0); + ORKEnableAutoLayoutForViews(@[_mapView]); + [self addSubview:_mapView]; + + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *metrics = @{@"horizontalMargin": @(_mapHorizontalMargin)}; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(horizontalMargin)-[_mapView]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:metrics views:NSDictionaryOfVariableBindings(_mapView)]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_mapView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_textField attribute:NSLayoutAttributeBottom multiplier:1.0 constant:[ORKLocationSelectionView.class textFieldBottomMargin]]]; + + _mapViewHeightConstraint = [NSLayoutConstraint constraintWithItem:_mapView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:ORKGetMetricForWindow(ORKScreenMetricLocationQuestionMapHeight, self.window)]; + [constraints addObject:_mapViewHeightConstraint]; + + if (_seperator3) { + [self bringSubviewToFront:_seperator3]; + _seperator3.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *seperators = NSDictionaryOfVariableBindings(_seperator3); + [constraints addObject:[NSLayoutConstraint constraintWithItem:_mapView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_seperator3 attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_seperator3 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:1.0 / [UIScreen mainScreen].scale]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_seperator3]|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:seperators]]; + } + + [NSLayoutConstraint activateConstraints:constraints]; + [self layoutIfNeeded]; + if ([_delegate respondsToSelector:@selector(locationSelectionViewNeedsResize:)]) { + [_delegate locationSelectionViewNeedsResize:self]; + } +} + +- (void)loadCurrentLocationIfNecessary { + if (_useCurrentLocation) { + CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; + + if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { + _userLocationNeedsUpdate = YES; + _mapView.showsUserLocation = YES; + } else { + _locationManager = [[CLLocationManager alloc] init]; + _locationManager.delegate = self; + [_locationManager requestWhenInUseAuthorization]; + } + } +} + +- (void)geocodeAndDisplay:(NSString *)string { + + if (string == nil || string.length == 0) { + [self setAnswer:ORKNullAnswerValue()]; + return; + } + + CLGeocoder *geocoder = [[CLGeocoder alloc] init]; + ORKWeakTypeOf(self) weakSelf = self; + [geocoder geocodeAddressString:string completionHandler:^(NSArray *placemarks, NSError *error) { + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + if (error) { + [self notifyDelegateOfError:error]; + [strongSelf setAnswer:ORKNullAnswerValue()]; + } else { + CLPlacemark *placemark = [placemarks lastObject]; + [strongSelf setAnswer:[[ORKLocation alloc] initWithPlacemark:placemark userInput:string]]; + } + }]; +} + +- (void)reverseGeocodeAndDisplay:(ORKLocation *)location { + + if (location == nil) { + [self setAnswer:ORKNullAnswerValue()]; + return; + } + + CLGeocoder *geocoder = [[CLGeocoder alloc] init]; + ORKWeakTypeOf(self) weakSelf = self; + CLLocation *cllocation = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude]; + [geocoder reverseGeocodeLocation:cllocation completionHandler:^(NSArray *placemarks, NSError *error) { + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + if (error) { + [self notifyDelegateOfError:error]; + [strongSelf setAnswer:ORKNullAnswerValue()]; + } else { + CLPlacemark *placemark = [placemarks lastObject]; + [strongSelf setAnswer:[[ORKLocation alloc] initWithPlacemark:placemark + userInput:location.userInput ? : placemark.ork_addressLine] + updateMap:YES]; + } + }]; +} + +- (void)setAnswer:(ORKLocation *)answer { + [self setAnswer:answer updateMap:YES]; +} + +- (void)setAnswer:(ORKLocation *)answer updateMap:(BOOL)updateMap { + + BOOL isAnswerClassORKLocation = [[answer class] isSubclassOfClass:[ORKLocation class]]; + _answer = (isAnswerClassORKLocation || answer == ORKNullAnswerValue()) ? answer : nil; + + if (_answer) { + _userLocationNeedsUpdate = NO; + } else { + [self loadCurrentLocationIfNecessary]; + } + + ORKLocation *location = isAnswerClassORKLocation ? (ORKLocation *)_answer : nil; + + if (location) { + + if (!location.userInput || !location.region |!location.postalAddress) { + // redo geo decoding if any of them is missing + [self reverseGeocodeAndDisplay:location]; + return; + } + + if (location.userInput) { + _textField.text = location.userInput; + } + } + + if (updateMap) { + [self updateMapWithLocation:location]; + } + + if ([_delegate respondsToSelector:@selector(locationSelectionViewDidChange:)]) { + [_delegate locationSelectionViewDidChange:self]; + } +} + +- (void)updateMapWithLocation:(ORKLocation *)location { + + MKPlacemark *placemark = location ? [[MKPlacemark alloc] initWithCoordinate:location.coordinate postalAddress:location.postalAddress] : nil; + + [_mapView removeAnnotations:_mapView.annotations]; + + if (placemark) { + [_mapView addAnnotation:placemark]; + CLLocationDistance span = MAX(200, location.region.radius); + MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(location.region.center, span, span); + [self setMapRegion:region]; + } else { + if (_setInitialCoordinateRegion) { + [self setMapRegion:_initalCoordinateRegion]; + } + } +} + +- (void)setMapRegion:(MKCoordinateRegion)region { + if (!_setInitialCoordinateRegion) { + _setInitialCoordinateRegion = YES; + _initalCoordinateRegion = _mapView.region; + } + [_mapView setRegion:region animated:YES]; +} + +- (void)notifyDelegateOfError:(NSError *)error { + NSString *title = ORKLocalizedString(@"LOCATION_ERROR_TITLE", @""); + NSString *message = nil; + + switch (error.code) { + case kCLErrorLocationUnknown: + case kCLErrorHeadingFailure: + message = ORKLocalizedString(@"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN", @""); + break; + case kCLErrorDenied: + case kCLErrorRegionMonitoringDenied: + message = ORKLocalizedString(@"LOCATION_ERROR_MESSAGE_DENIED", @""); + break; + case kCLErrorNetwork: + message = ORKLocalizedString(@"LOCATION_ERROR_GEOCODE_NETWORK", @""); + break; + case kCLErrorGeocodeFoundNoResult: + case kCLErrorGeocodeFoundPartialResult: + case kCLErrorGeocodeCanceled: + message = ORKLocalizedString(@"LOCATION_ERROR_GEOCODE", @""); + break; + default: + break; + } + + if ([_delegate respondsToSelector:@selector(locationSelectionView:didFailWithErrorTitle:message:)] && message != nil) { + [_delegate locationSelectionView:self didFailWithErrorTitle:title message:message]; + } +} + +# pragma mark CLLocationManagerDelegate + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) { + [self loadCurrentLocationIfNecessary]; + } +} + +#pragma mark MKMapViewDelegate + +- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { + if (_userLocationNeedsUpdate) { + [self reverseGeocodeAndDisplay:[[ORKLocation alloc] initWithCoordinate:userLocation.location.coordinate + region:nil + userInput:nil + postalAddress:nil]]; + _userLocationNeedsUpdate = NO; + } +} + +- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error { + // Be quiet if map cannot find user current location +} + +#pragma mark UITextFieldDelegate + +- (void)textFieldDidBeginEditing:(UITextField *)textField { + if ([_delegate respondsToSelector:@selector(locationSelectionViewDidBeginEditing:)]) { + [_delegate locationSelectionViewDidBeginEditing:self]; + } +} + +- (void)textFieldDidEndEditing:(UITextField *)textField { + [textField resignFirstResponder]; + [self geocodeAndDisplay:textField.text]; + if ([_delegate respondsToSelector:@selector(locationSelectionViewDidEndEditing:)]) { + [_delegate locationSelectionViewDidEndEditing:self]; + } +} + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + // Clear answer to prevent user continue with invalid answer. + if ( NO == ORKIsAnswerEmpty(_answer) ) { + [self setAnswer:ORKNullAnswerValue() updateMap:NO]; + } + + return YES; +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + [self geocodeAndDisplay:textField.text]; + [textField resignFirstResponder]; + return YES; +} + +- (BOOL)textFieldShouldClear:(UITextField *)textField { + [_mapView setRegion:_initalCoordinateRegion animated:YES]; + [self setAnswer:ORKNullAnswerValue()]; + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.h new file mode 100755 index 0000000..f254d83 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKOperation.h" +#import "ORKDataCollectionManager_Internal.h" + + +@class ORKMotionActivityCollector; + +/** + Operation for extracting and preparing CoreMotion data for upload. This operation + runs until there is no more CoreMotion data available, or until otherwise stopped. + */ +@interface ORKMotionActivityQueryOperation : ORKOperation + +- (instancetype)initWithCollector:(ORKMotionActivityCollector*)collector + queryQueue:(NSOperationQueue*)queue + manager:(ORKDataCollectionManager *)manager; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.m new file mode 100755 index 0000000..c09f8e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMotionActivityQueryOperation.m @@ -0,0 +1,206 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKMotionActivityQueryOperation.h" +#import +#import "ORKCollector.h" +#import "ORKHelpers_Internal.h" +#import "ORKCollector_Internal.h" +#import "ORKDataCollectionManager_Internal.h" + + +@implementation ORKMotionActivityQueryOperation { + + // All of these are strong references created at init time + ORKMotionActivityCollector *_collector; + NSOperationQueue *_queue; + NSDate *_currentDate; + __weak ORKDataCollectionManager *_manager; +} + +- (instancetype)initWithCollector:(ORKMotionActivityCollector*)collector + queryQueue:(NSOperationQueue*)queue + manager:(ORKDataCollectionManager *)manager { + self = [super init]; + if (self) { + _collector = collector; + _manager = manager; + _queue = queue ? : [NSOperationQueue mainQueue]; + _currentDate = nil; + + self.startBlock = ^void(ORKOperation* a) { + [(ORKMotionActivityQueryOperation*)a doQuery]; + }; + + } + return self; +} + +- (NSString*)description { + return [NSString stringWithFormat:@"<%@(%p):%@>",NSStringFromClass([self class]), self, _collector]; +} + +- (void)finishWithErrorCode:(ORKErrorCode)error { + self.error = [NSError errorWithDomain:ORKErrorDomain code:error userInfo:nil]; + [self safeFinish]; +} + +- (void)doQuery { + [self.lock lock]; + + __block NSDate *startDate = nil; + + __block NSDate *lastDate = nil; + __block NSString *itemIdentifier = nil; + + [_manager onWorkQueueSync:^BOOL(ORKDataCollectionManager *manager) { + BOOL changed = NO; + + // _currentAnchor will be NSNotFound on the first pass of the operation + if (_currentDate != nil) { + changed = YES; + + // Update the anchor if we have one + _collector.lastDate = _currentDate; + } + + lastDate = _collector.lastDate; + startDate = _collector.startDate; + itemIdentifier = _collector.identifier; + + return changed; + }]; + + if (_currentDate == nil) { + _currentDate = lastDate; + } + + __weak ORKMotionActivityQueryOperation * weakSelf = self; + + NSDate *queryBeginDate = _currentDate?:startDate; + NSDate *queryEndDate = [NSDate date]; + if (!queryBeginDate) { + queryBeginDate = [NSDate distantPast]; + } + + ORK_Log_Debug("\nMotion Query: %@\n", @{@"from": queryBeginDate, @"to":queryEndDate}); + + // Run a single query up to current date + [_manager.activityManager queryActivityStartingFromDate:queryBeginDate toDate:queryEndDate toQueue:_queue withHandler:^(NSArray *activities, NSError *error) { + ORKMotionActivityQueryOperation *op = weakSelf; + ORK_Log_Debug("\nMotion Query: %@\n", @{@"from": queryBeginDate, @"to":queryEndDate, @"returned count": @(activities.count)}); + [op handleResults:activities queryBegin:queryBeginDate queryEnd:queryEndDate error:error itemIdentifier:itemIdentifier]; + }]; + + [self.lock unlock]; + +} + +/* + Handles the results, and starts a new query if needed + */ +- (void)handleResults:(NSArray *)results + queryBegin:(NSDate *)queryBegin + queryEnd:(NSDate *)queryEnd + error:(NSError *)error + itemIdentifier:(NSString *)itemIdentifier { + [self.lock lock]; + // Check our actual state under the lock + + if ([self isCancelled]) { + // Give up immediately if we've been cancelled + [self.lock unlock]; + return; + } + if (error) { + // Give up if there was an error performing the query + self.error = error; + [self safeFinish]; + [self.lock unlock]; + return; + } + + [self.lock unlock]; + + if (results && [results count] > 0) { + CMMotionActivity *lastObject = (CMMotionActivity *)[results lastObject]; + NSDate *lastObservedDate = lastObject.startDate; + if (![lastObservedDate isEqual:queryBegin] && [lastObservedDate earlierDate:queryBegin] == lastObservedDate && [results count] == 1) { + // Ignore a one-off if it was before the beginning of the query + [self safeFinish]; + return; + } + + __block BOOL handoutSuccess = NO; + + dispatch_semaphore_t sem = dispatch_semaphore_create(0); + + // Dispatch the results back to the data handler, if any + [_manager onWorkQueueAsync:^BOOL(ORKDataCollectionManager *manager) { + id delegate = _manager.delegate; + + if (delegate && [delegate respondsToSelector:@selector(motionActivityCollector:didCollectMotionActivities:)]) { + handoutSuccess = [delegate motionActivityCollector:_collector didCollectMotionActivities:results]; + } + + dispatch_semaphore_signal(sem); + return YES; + }]; + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + + if (!handoutSuccess) { + self.error = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{NSLocalizedFailureReasonErrorKey: @"Results were not properly delivered to the data collection manager delegate."}]; + } + + // If successfully reported to delegate, and we observed at + // least one valid sample, update the "current" date + // (the start date of the next query) + if (lastObservedDate && handoutSuccess) { + + // Write the query end as the finish date. This is ok because in CoreMotion + // entries are local and unlikely to be written for dates prior to "now". + NSDate *nextStartDate = queryEnd ? : lastObservedDate; + self->_currentDate = nextStartDate; + + // Store it on the collector + [_manager onWorkQueueAsync:^BOOL(ORKDataCollectionManager *manager) { + _collector.lastDate = nextStartDate; + return YES; + }]; + + } + + } + + [self safeFinish]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.h new file mode 100755 index 0000000..bb36a3d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2017, Sage Bionetworks. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKPicker.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKMultipleValuePicker : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.m new file mode 100755 index 0000000..cdcd2af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKMultipleValuePicker.m @@ -0,0 +1,300 @@ +/* + Copyright (c) 2017, Sage Bionetworks. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKMultipleValuePicker.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKChoiceAnswerFormatHelper.h" +#import "ORKResult_Private.h" + +#import "ORKAccessibilityFunctions.h" + + +@interface ORKMultipleValuePicker () + +@property (nonatomic, strong) NSArray *helpers; + +@end + +static const CGFloat PickerSpacerHeight = 15.0; +static const CGFloat PickerMinimumHeight = 34.0; + +@implementation ORKMultipleValuePicker { + UIPickerView *_pickerView; + id _answer; + NSString *_separator; + BOOL _shouldShowSeparator; + __weak id _pickerDelegate; +} + +@synthesize pickerDelegate = _pickerDelegate; + +- (instancetype)initWithAnswerFormat:(ORKMultipleValuePickerAnswerFormat *)answerFormat answer:(id)answer pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + NSAssert([answerFormat isKindOfClass:[ORKMultipleValuePickerAnswerFormat class]], @"answerFormat should be ORKMultipleValuePickerAnswerFormat"); + + // setup the helpers + NSMutableArray *helpers = [NSMutableArray new]; + for (ORKValuePickerAnswerFormat *valuePicker in answerFormat.valuePickers) { + [helpers addObject:[[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:valuePicker]]; + } + _helpers = [helpers copy]; + + _separator = answerFormat.separator ?: @" "; + _shouldShowSeparator = [[_separator stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] > 0; + _answer = answer; + _pickerDelegate = delegate; + } + return self; +} + +- (UIView *)pickerView { + if (_pickerView == nil) { + _pickerView = [[UIPickerView alloc] init]; + _pickerView.dataSource = self; + _pickerView.delegate = self; + [self setAnswer:_answer]; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + NSArray *indexNumbers = [self indexNumbersForAnswer:answer]; + if (indexNumbers) { + [indexNumbers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop __unused) { + NSUInteger pickerIdx = [self convertToPickerViewComponent:idx]; + [_pickerView selectRow:[obj integerValue] inComponent:pickerIdx animated:NO]; + if (_shouldShowSeparator && idx > 0) { + [_pickerView selectRow:0 inComponent:pickerIdx - 1 animated:NO]; + } + }]; + } + else { + NSUInteger count = [self numberOfComponentsInPickerView:_pickerView]; + for (NSInteger ii = 0; ii < count; ii++) { + [_pickerView selectRow:0 inComponent:ii animated:NO]; + } + } +} + +- (id)answer { + return _answer; +} + +- (NSUInteger)convertToPickerViewComponent:(NSUInteger)idx { + if (_shouldShowSeparator) { + return idx * 2; + } else { + return idx; + } +} + +- (NSUInteger)convertFromPickerViewComponent:(NSUInteger)component { + if (_shouldShowSeparator) { + if (component % 2 == 0) { + return component / 2; + } else { + return NSNotFound; + } + } else { + return component; + } +} + +- (NSArray *)indexNumbersForAnswer:(id)answer { + if ([answer isKindOfClass:[NSArray class]] && + ([(NSArray*)answer count] == self.helpers.count)) { + + __block NSMutableArray *indexNumbers = [NSMutableArray new]; + [(NSArray*)answer enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop __unused) { + NSNumber *indexNumber = [self.helpers[idx] selectedIndexForAnswer:@[obj]]; + if (indexNumber) { + [indexNumbers addObject:indexNumber]; + } else { + [indexNumbers addObject:@0]; + } + }]; + return indexNumbers; + } + else { + return nil; + } +} + +- (NSString *)selectedLabelText { + if ( _answer == ORKNullAnswerValue() || _answer == nil ) { + return nil; + } + + NSArray *indexNumbers = [self indexNumbersForAnswer:_answer]; + if (indexNumbers == nil) { + return nil; + } + + __block NSMutableArray *strings = [NSMutableArray new]; + [indexNumbers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *title = [[self.helpers[idx] textChoiceAtIndex:[obj integerValue]] text]; + NSAttributedString *attributedText = [[self.helpers[idx] textChoiceAtIndex:[obj integerValue]] primaryTextAttributedString]; + if (title) { + [strings addObject:title]; + } else if (attributedText) { + [strings addObject:attributedText.string]; + } else { + *stop = YES; + } + }]; + + if (strings.count == self.helpers.count) { + return [strings componentsJoinedByString:_separator]; + } else { + return nil; + } +} + +- (void)pickerWillAppear { + [self pickerView]; + [self valueDidChange]; + [self accessibilityFocusOnPickerElement]; +} + +- (void)valueDidChange { + + __block NSMutableArray *answers = [NSMutableArray new]; + [self.helpers enumerateObjectsUsingBlock:^(ORKChoiceAnswerFormatHelper * _Nonnull helper, NSUInteger idx, BOOL * _Nonnull stop) { + NSUInteger pickerIdx = [self convertToPickerViewComponent:idx]; + NSInteger row = [_pickerView selectedRowInComponent:pickerIdx]; + id answer = [helper answerForSelectedIndex:row]; + if ([answer isKindOfClass:[NSArray class]]) { + id obj = [(NSArray*)answer firstObject]; + if ((obj != nil) && (obj != ORKNullAnswerValue())) { + [answers addObject: obj]; + } + } else { + *stop = YES; + } + }]; + + _answer = (answers.count == self.helpers.count) ? answers : ORKNullAnswerValue(); + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:_answer]; + } +} + + +#pragma mark - Accessibility + +- (void)accessibilityFocusOnPickerElement { + if (UIAccessibilityIsVoiceOverRunning()) { + ORKAccessibilityPerformBlockAfterDelay(0.75, ^{ + NSArray *axElements = [self.pickerView accessibilityElements]; + if ([axElements count] > 0) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, [axElements objectAtIndex:0]); + } + }); + } +} + + +#pragma mark - UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + if (_shouldShowSeparator) { + return self.helpers.count*2 - 1; + } else { + return self.helpers.count; + } +} + +// returns the # of rows in each component.. +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + NSUInteger idx = [self convertFromPickerViewComponent:component]; + if (idx == NSNotFound) { + return 1; + } else { + return self.helpers[idx].choiceCount; + } +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + NSUInteger idx = [self convertFromPickerViewComponent:component]; + if (idx == NSNotFound) { + return _separator; + } else { + return [[self.helpers[idx] textChoiceAtIndex:row] text] ?: @""; + } +} + +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + NSUInteger idx = [self convertFromPickerViewComponent:component]; + if (idx == NSNotFound) { + return nil; + } else { + return [[self.helpers[idx] textChoiceAtIndex:row] primaryTextAttributedString] ?: nil; + } +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view +{ + UILabel* valueLabel = (UILabel*)view; + if (!valueLabel) + { + valueLabel = [[UILabel alloc] init]; + [valueLabel setFont:[self defaultFont]]; + [valueLabel setTextAlignment:NSTextAlignmentCenter]; + } + valueLabel.text = [self pickerView:pickerView titleForRow:row forComponent:component]; + NSAttributedString *attributedText = [self pickerView:pickerView attributedTitleForRow:row forComponent:component]; + if (attributedText) { + valueLabel.attributedText = attributedText; + } + return valueLabel; +} + +- (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { + UIFont *font = [self defaultFont]; + CGFloat height = font.pointSize + PickerSpacerHeight; + return (height < PickerMinimumHeight ? PickerMinimumHeight : height); +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + [self valueDidChange]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.h new file mode 100755 index 0000000..bff33ab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.h @@ -0,0 +1,189 @@ +/* + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStepNavigationRule; +@class ORKSkipStepNavigationRule; +@class ORKStepModifier; + +/** + The `ORKNavigableOrderedTask` class adds conditional step navigation to the behavior inherited from + the `ORKOrderedTask` class. + + For implementing conditional task navigation, you must instantiate concrete subclasses of + `ORKStepNavigationRule` and `ORKSkipStepNavigationRule` and attach them to trigger steps by using + the `setNavigationRule:forTriggerStepIdentifier:` and `setSkipNavigationRule:forStepIdentifier:` + methods. + + For example, if you want to display a survey question only when the user answered Yes to a previous + question you can use `ORKPredicateStepNavigationRule`; or if you want to define an arbitrary jump + between two steps you can use `ORKDirectStepNavigationRule`. You can also optionally omit steps by + using `ORKPredicateSkipStepNavigationRule` objects. + + Note that each step in the task can have at most one attached navigation rule and one attached skip + navigation rule. + + Navigable ordered tasks support looping over previously visited steps. Note, however, that results + for steps that are visited more than once will be ovewritten when you revisit the step on the loop. + Thus, going over a loop will produce duplicate results within the task results for the steps that + are seen more than once, but all the duplicate step results will point to the same result instance: + the one corresponding to the last time you visited the step. + + The same applies when navigating backwards over looped steps: only your last valid answer is shown + every time you encounter a revisited step. + */ +ORK_CLASS_AVAILABLE +@interface ORKNavigableOrderedTask : ORKOrderedTask + +/** + Adds a navigation rule for a trigger step identifier. + + The rule will be used to obtain a new destination step when the participant goes forward from the + trigger step. You cannot add two different navigation rules to the same trigger step identifier; + only the most recently added rule is kept. + + @param stepNavigationRule The step navigation rule to be used when navigating forward from the + trigger step. A strong reference to the rule is kept by the + task. + @param triggerStepIdentifier The identifier of the step that triggers the rule. + */ +- (void)setNavigationRule:(ORKStepNavigationRule *)stepNavigationRule forTriggerStepIdentifier:(NSString *)triggerStepIdentifier; + +/** + Returns the step navigation rule associated with a trigger step identifier, or `nil` if there is + no rule associated with that step identifier. + + @param triggerStepIdentifier The identifier of the step whose rule you want to retrieve. + + @return A step navigation rule, or `nil` if the trigger step identifier has none. + */ +- (nullable ORKStepNavigationRule *)navigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier; + +/** + Removes the navigation rule, if any, associated with the specified trigger step identifier. + + @param triggerStepIdentifier The identifier of the step whose rule is to be removed. + */ +- (void)removeNavigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier; + +/** + A dictionary of step navigation rules in the task, keyed by trigger step identifier. + + Each object in the dictionary should be a `ORKStepNavigationRule` subclass. + */ +@property (nonatomic, copy, readonly) NSDictionary *stepNavigationRules; + +/** + Adds a skip step navigation rule for a step identifier. + + The rule will be used to decide if the identified step needs to be skipped. You cannot add two + different skip navigation rules to the same step identifier; only the most recently added rule is + kept. + + @param skipStepNavigationRule The skip step navigation rule to be used to determine if the + step should be skipped. A strong reference to the rule is + kept by the task. + @param stepIdentifier The identifier of the step that is checked against the skip + rule. + */ +- (void)setSkipNavigationRule:(ORKSkipStepNavigationRule *)skipStepNavigationRule forStepIdentifier:(NSString *)stepIdentifier; + +/** + Returns the skip step navigation rule associated with a step identifier, or `nil` if there is no + skip rule associated with that step identifier. + + @param stepIdentifier The identifier of the step whose skip rule you want to retrieve. + + @return A skip step navigation rule, or `nil` if the step identifier has none. + */ +- (nullable ORKSkipStepNavigationRule *)skipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier; + +/** + Removes the skip step navigation rule, if any, associated with the specified step identifier. + + @param stepIdentifier The identifier of the step whose rule is to be removed. + */ +- (void)removeSkipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier; + +/** + A dictionary of step navigation rules in the task, keyed by trigger step identifier. + + Each object in the dictionary should be a `ORKStepNavigationRule` subclass. + */ +@property (nonatomic, copy, readonly) NSDictionary *skipStepNavigationRules; + +/** + Adds a step modifier for a step identifier. + + @param stepModifier The step modifier associated with this step + @param stepIdentifier The identifier of the step that is checked against the skip + rule. + */ +- (void)setStepModifier:(ORKStepModifier *)stepModifier forStepIdentifier:(NSString *)stepIdentifier; + +/** + Returns the step modifier associated with a step identifier, or `nil` if there is no + step modifier associated with that step identifier. + + @param stepIdentifier The identifier of the step to be modified + + @return A step modifier, or `nil` if the step identifier has none. + */ +- (nullable ORKStepModifier *)stepModifierForStepIdentifier:(NSString *)stepIdentifier; + +/** + Removes the step modifier, if any, associated with the specified step identifier. + + @param stepIdentifier The identifier of the step whose rule is to be removed. + */ +- (void)removeStepModifierForStepIdentifier:(NSString *)stepIdentifier; + +/** + A dictionary of step modifiers in the task, keyed by trigger step identifier. + + Each object in the dictionary should be a `ORKStepModifier` subclass. + */ +@property (nonatomic, copy, readonly) NSDictionary *stepModifiers; + +/** + Determines whether the task should report its progress as a linear ordered task or not. + The default value of this property is `NO`. + */ +@property (nonatomic) BOOL shouldReportProgress; + +@end + + NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.m new file mode 100755 index 0000000..0b52b5d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigableOrderedTask.m @@ -0,0 +1,262 @@ +/* + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKNavigableOrderedTask.h" + +#import "ORKOrderedTask_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKResult.h" +#import "ORKStep_Private.h" +#import "ORKStepNavigationRule.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKNavigableOrderedTask { + NSMutableDictionary *_stepNavigationRules; + NSMutableDictionary *_skipStepNavigationRules; + NSMutableDictionary *_stepModifiers; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray *)steps { + self = [super initWithIdentifier:identifier steps:steps]; + if (self) { + _stepNavigationRules = nil; + _skipStepNavigationRules = nil; + _shouldReportProgress = NO; + } + return self; +} + +- (void)setNavigationRule:(ORKStepNavigationRule *)stepNavigationRule forTriggerStepIdentifier:(NSString *)triggerStepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepNavigationRule); + ORKThrowInvalidArgumentExceptionIfNil(triggerStepIdentifier); + + if (!_stepNavigationRules) { + _stepNavigationRules = [NSMutableDictionary new]; + } + _stepNavigationRules[triggerStepIdentifier] = stepNavigationRule; +} + +- (ORKStepNavigationRule *)navigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(triggerStepIdentifier); + + return _stepNavigationRules[triggerStepIdentifier]; +} + +- (void)removeNavigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(triggerStepIdentifier); + + [_stepNavigationRules removeObjectForKey:triggerStepIdentifier]; +} + +- (NSDictionary *)stepNavigationRules { + if (!_stepNavigationRules) { + return @{}; + } + return [_stepNavigationRules copy]; +} + +- (void)setSkipNavigationRule:(ORKSkipStepNavigationRule *)skipStepNavigationRule forStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(skipStepNavigationRule); + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + + if (!_skipStepNavigationRules) { + _skipStepNavigationRules = [NSMutableDictionary new]; + } + _skipStepNavigationRules[stepIdentifier] = skipStepNavigationRule; +} + +- (ORKSkipStepNavigationRule *)skipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + + return _skipStepNavigationRules[stepIdentifier]; +} + +- (void)removeSkipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + + [_skipStepNavigationRules removeObjectForKey:stepIdentifier]; +} + +- (NSDictionary *)skipStepNavigationRules { + if (!_skipStepNavigationRules) { + return @{}; + } + return [_skipStepNavigationRules copy]; +} + +- (void)setStepModifier:(ORKStepModifier *)stepModifier forStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepModifier); + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + + if (!_stepModifiers) { + _stepModifiers = [NSMutableDictionary new]; + } + _stepModifiers[stepIdentifier] = stepModifier; +} + +- (ORKStepModifier *)stepModifierForStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + return _stepModifiers[stepIdentifier]; +} + +- (void)removeStepModifierForStepIdentifier:(NSString *)stepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(stepIdentifier); + + [_stepModifiers removeObjectForKey:stepIdentifier]; +} + +- (NSDictionary *)stepModifiers { + if (!_stepModifiers) { + return @{}; + } + return [_stepModifiers copy]; +} + +- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + ORKStep *nextStep = nil; + ORKStepNavigationRule *navigationRule = _stepNavigationRules[step.identifier]; + NSString *nextStepIdentifier = [navigationRule identifierForDestinationStepWithTaskResult:result]; + if (![nextStepIdentifier isEqualToString:ORKNullStepIdentifier]) { // If ORKNullStepIdentifier, return nil to end task + if (nextStepIdentifier) { + nextStep = [self stepWithIdentifier:nextStepIdentifier]; + + if (step && nextStep && [self indexOfStep:nextStep] <= [self indexOfStep:step]) { + ORK_Log_Info("Index of next step (\"%@\") is equal or lower than index of current step (\"%@\") in navigable ordered task. Make sure this is intentional as you could loop idefinitely without appropriate navigation rules. Also please note that you'll get duplicate result entries each time you loop over the same step.", nextStep.identifier, step.identifier); + } + } else { + nextStep = [super stepAfterStep:step withResult:result]; + } + + ORKSkipStepNavigationRule *skipNavigationRule = _skipStepNavigationRules[nextStep.identifier]; + if ([skipNavigationRule stepShouldSkipWithTaskResult:result]) { + nextStep = [self stepAfterStep:nextStep withResult:result]; + } + } + + if (nextStep != nil) { + ORKStepModifier *stepModifier = [self stepModifierForStepIdentifier:nextStep.identifier]; + [stepModifier modifyStep:nextStep withTaskResult:result]; + } + + return nextStep; +} + +- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + ORKStep *previousStep = nil; + __block NSInteger indexOfCurrentStepResult = -1; + // Use results to account for ORKNavigableOrderedTask loops + [result.results enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(ORKResult *enumeratedResult, NSUInteger idx, BOOL *stop) { + if ([enumeratedResult.identifier isEqualToString:step.identifier]) { + indexOfCurrentStepResult = idx; + *stop = YES; + } + }]; + if (indexOfCurrentStepResult > 0) { + previousStep = [self stepWithIdentifier:result.results[indexOfCurrentStepResult - 1].identifier]; + } + return previousStep; +} + +// Assume ORKNavigableOrderedTask doesn't have a linear order unless user specifically overrides +- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + if (_shouldReportProgress) { + return [super progressOfCurrentStep:step withResult:result]; + } + + return ORKTaskProgressMake(0, 0); +} + +#pragma mark Serialization private methods + +// These methods should only be used by serialization tests (the stepNavigationRules and skipStepNavigationRules properties are published as readonly) +- (void)setStepNavigationRules:(NSDictionary *)stepNavigationRules { + _stepNavigationRules = [stepNavigationRules mutableCopy]; +} + +- (void)setSkipStepNavigationRules:(NSDictionary *)skipStepNavigationRules { + _skipStepNavigationRules = [skipStepNavigationRules mutableCopy]; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_MUTABLE_DICTIONARY(aDecoder, stepNavigationRules, NSString, ORKStepNavigationRule); + ORK_DECODE_OBJ_MUTABLE_DICTIONARY(aDecoder, skipStepNavigationRules, NSString, ORKSkipStepNavigationRule); + ORK_DECODE_OBJ_MUTABLE_DICTIONARY(aDecoder, stepModifiers, NSString, ORKStepModifier); + ORK_DECODE_BOOL(aDecoder, shouldReportProgress); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + ORK_ENCODE_OBJ(aCoder, stepNavigationRules); + ORK_ENCODE_OBJ(aCoder, skipStepNavigationRules); + ORK_ENCODE_OBJ(aCoder, stepModifiers); + ORK_ENCODE_BOOL(aCoder, shouldReportProgress); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) task = [super copyWithZone:zone]; + task->_stepNavigationRules = ORKMutableDictionaryCopyObjects(_stepNavigationRules); + task->_skipStepNavigationRules = ORKMutableDictionaryCopyObjects(_skipStepNavigationRules); + task->_stepModifiers = ORKMutableDictionaryCopyObjects(_stepModifiers); + task->_shouldReportProgress = _shouldReportProgress; + return task; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame + && ORKEqualObjects(self.stepNavigationRules, castObject.stepNavigationRules) + && ORKEqualObjects(self.skipStepNavigationRules, castObject.skipStepNavigationRules) + && ORKEqualObjects(self.stepModifiers, castObject.stepModifiers) + && self.shouldReportProgress == castObject.shouldReportProgress; +} + +- (NSUInteger)hash { + return super.hash ^ _stepNavigationRules.hash ^ _skipStepNavigationRules.hash ^ _stepModifiers.hash ^ (_shouldReportProgress ? 0xf : 0x0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.h new file mode 100755 index 0000000..c9a539c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.h @@ -0,0 +1,86 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKNavigablePageStep` class is a concrete subclass of `ORKPageStep`, used for presenting a subgrouping of + `ORKStepViewController` views using a `UIPageViewController`. It allows for using an `ORKOrderedTask` as + the model object used to define navigation, and has been added specifically to allow developers to use + `ORKNavigableOrderedTask` and other subclasses of ORKOrderedTask with the `ORKPageStep`. + + To use `ORKNavigablePageStep`, instantiate the object, fill in its properties, and include it in a task. + Next, create a task view controller for the task and present it. + + The base class implementation will instatiate a read-only `ORKPageStepViewController` to display + a series of substeps. For each substep, the `ORKStepViewController` will be instantiated and added + as a child of the `UIPageViewController` contained by the parent `ORKPageStepViewController`.. + + Customization can be handled by overriding the base class implementations in either `ORKNavigablePageStep` + or `ORKPageStepViewController`. + */ + +ORK_CLASS_AVAILABLE +@interface ORKNavigablePageStep : ORKPageStep + +/** + The subtask used to determine the next/previous steps that are in this grouping + */ +@property (nonatomic, copy, readonly) ORKOrderedTask *pageTask; + +/** + Returns an initialized page step using the specified identifier and task. + + @param identifier The unique identifier for the step. + @param task The task used to run the subtask. + + @return An initialized navigable page step. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + pageTask:(ORKOrderedTask *)task NS_DESIGNATED_INITIALIZER; + +/** + Returns a page step initialized from data in the given unarchiver. + + A page step can be serialized and deserialized with `NSKeyedArchiver`. Note + that this serialization includes strings that might need to be localized. + + @param aDecoder The coder from which to initialize the ordered task. + + @return An initialized navigable page step. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.m new file mode 100755 index 0000000..b2c2b17 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigablePageStep.m @@ -0,0 +1,60 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKNavigablePageStep.h" +#import "ORKPageStep_Private.h" + + +@implementation ORKNavigablePageStep + +@dynamic pageTask; + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [self initWithIdentifier:identifier pageTask:[[ORKOrderedTask alloc] initWithIdentifier:identifier steps:nil]]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray *)steps { + return [self initWithIdentifier:identifier pageTask:[[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + pageTask:(ORKOrderedTask *)task { + return [super initWithIdentifier:identifier pageTask:task]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + return [super initWithCoder:aDecoder]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.h new file mode 100755 index 0000000..ee1b66a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@class ORKBorderedButton; +@interface ORKNavigationContainerView : UIView + +@property (nonatomic, strong, nullable) UIBarButtonItem *continueButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *skipButtonItem; + +@property (nonatomic, assign) BOOL continueEnabled; +@property (nonatomic, assign) BOOL neverHasContinueButton; + +@property (nonatomic, assign) BOOL skipEnabled; + +@property (nonatomic, assign) CGFloat topMargin; +@property (nonatomic, assign) CGFloat bottomMargin; + +@property (nonatomic, assign) BOOL useExtendedPadding; + +- (BOOL)hasContinueOrSkip; +- (void)removeStyling; + +- (CGFloat)effectViewOpacity; +- (void)setStylingOpactity:(CGFloat)opacity animated:(BOOL)animated; + +- (void)showActivityIndicator:(BOOL)showActivityIndicator; +- (void)flattenIfNeeded; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.m new file mode 100755 index 0000000..84307d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView.m @@ -0,0 +1,472 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKNavigationContainerView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat standardSpacing = 5.0; +static const CGFloat skipButtonHeight = 50.0; +static const CGFloat topSpacing = 24.0; +static const CGFloat bottomSpacing = 34.0; +static const CGFloat activityIndicatorPadding = 24.0; + +@implementation ORKNavigationContainerView { + UIActivityIndicatorView *_activityIndicatorView; + + NSArray *_leftRightPaddingConstraints; + UIVisualEffectView *effectView; + UIColor *_appTintColor; + + BOOL _continueButtonJustTapped; + BOOL _removeVisualEffect; + NSMutableArray *_regularConstraints; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self setBackgroundColor:ORKColor(ORKNavigationContainerColorKey)]; + [self setupVisualEffectView]; + [self setupViews]; + [self setupFootnoteLabel]; + self.preservesSuperviewLayoutMargins = NO; + _appTintColor = nil; + self.skipButtonStyle = ORKNavigationContainerButtonStyleTextBold; + [self updateContinueAndSkipEnabled]; + } + return self; +} + +- (void)removeStyling { + _removeVisualEffect = YES; + if (effectView) { + [effectView removeFromSuperview]; + effectView = nil; + } +} + +- (void)flattenIfNeeded { + if (![self hasContinueOrSkip] || (self.continueButtonItem == nil && [self neverHasSkipButton] && [self neverHasFootnote])) { + [[self.heightAnchor constraintEqualToConstant:0] setActive:YES]; + } +} + +- (void)setupVisualEffectView { + if (!effectView && !_removeVisualEffect) { + self.backgroundColor = [UIColor clearColor]; + UIVisualEffect *blurEffect; + if (@available(iOS 13.0, *)) { + blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemChromeMaterial]; + } else { + blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]; + } + effectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; + } + effectView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:effectView]; +} + +- (CGFloat)effectViewOpacity { + return effectView.alpha; +} + +- (void)setStylingOpactity:(CGFloat)opacity animated:(BOOL)animated { + if (animated == YES) { + [UIView animateWithDuration:0.2 animations:^(void) { + effectView.alpha = opacity; + }]; + } else { + effectView.alpha = opacity; + } +} + +- (void)setupContinueButton { + if (!_continueButton) { + _continueButton = [[ORKContinueButton alloc] initWithTitle:@"" isDoneButton:NO]; + } + _continueButton.alpha = 0; + _continueButton.exclusiveTouch = YES; + _continueButton.translatesAutoresizingMaskIntoConstraints = NO; + [_continueButton addTarget:self action:@selector(continueButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_continueButton]; +} + +- (void)setupSkipButton { + if (!_skipButton) { + _skipButton = [ORKBorderedButton new]; + } + _skipButton.exclusiveTouch = YES; + [_skipButton setTitle:nil forState:UIControlStateNormal]; + [_skipButton addTarget:self action:@selector(skipButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + _skipButton.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_skipButton]; +} + +- (void)setupFootnoteLabel { + _footnoteLabel = [ORKFootnoteLabel new]; + _footnoteLabel.numberOfLines = 0; + _footnoteLabel.textAlignment = NSTextAlignmentNatural; + _footnoteLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_footnoteLabel]; +} + +- (void)setupViews { + [self setupContinueButton]; + [self setupSkipButton]; + [self setUpConstraints]; +} + +- (void)didMoveToWindow { + _appTintColor = self.window.tintColor ? : ORKColor(ORKBlueHighlightColorKey); + _continueButton.normalTintColor = _appTintColor; + _skipButton.normalTintColor = _appTintColor; +} + +- (void)setSkipButtonStyle:(ORKNavigationContainerButtonStyle)skipButtonStyle { + _skipButtonStyle = skipButtonStyle; + switch (skipButtonStyle) { + case ORKNavigationContainerButtonStyleTextStandard: + [_skipButton setAppearanceAsTextButton]; + break; + case ORKNavigationContainerButtonStyleTextBold: + [_skipButton setAppearanceAsBoldTextButton]; + break; + case ORKNavigationContainerButtonStyleRoundedRect: + [_skipButton resetAppearanceAsBorderedButton]; + break; + default: + [_skipButton setAppearanceAsTextButton]; + break; + } +} + +- (void)setTopMargin:(CGFloat)topMargin { + _topMargin = topMargin; + [self updateContinueAndSkipEnabled]; +} + +- (void)setBottomMargin:(CGFloat)bottomMargin { + _bottomMargin = bottomMargin; + [self updateContinueAndSkipEnabled]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; +} + +- (void)skipButtonAction:(id)sender { + [self skipAction:sender]; + + // Disable button for 0.5s + ((UIView *)sender).userInteractionEnabled = NO; + ((ORKTextButton *)sender).isInTransition = YES; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + // Re-enable skip button + ((UIView *)sender).userInteractionEnabled = YES; + ((ORKTextButton *)sender).isInTransition = NO; + }); +} + +- (void)continueButtonAction:(id)sender { + if (_useNextForSkip && _skipButtonItem && !_continueButtonItem) { + [self skipAction:sender]; + } else { + [self continueAction:sender]; + } + + // Disable button for 0.5s + ((UIView *)sender).userInteractionEnabled = NO; + ((ORKTextButton *)sender).isInTransition = YES; + _continueButtonJustTapped = YES; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + _continueButtonJustTapped = NO; + ((ORKTextButton *)sender).isInTransition = NO; + [self updateContinueAndSkipEnabled]; + }); +} + +- (void)continueAction:(id)sender { + ORKSuppressPerformSelectorWarning( + (void)[_continueButtonItem.target performSelector:_continueButtonItem.action withObject:self]; + ); +} + +- (void)skipAction:(id)sender { + ORKSuppressPerformSelectorWarning( + (void)[_skipButtonItem.target performSelector:_skipButtonItem.action withObject:_skipButton]; + ); +} + +- (void)setNeverHasContinueButton:(BOOL)neverHasContinueButton { + _neverHasContinueButton = neverHasContinueButton; + [self setNeedsUpdateConstraints]; +} + +- (BOOL)neverHasSkipButton { + return !self.optional; +} + +- (BOOL)neverHasFootnote { + return _footnoteLabel.text.length == 0; +} + +- (BOOL)skipButtonHidden { + return (!_skipButtonItem) || _useNextForSkip || !self.optional; +} + +- (CGFloat)skipButtonAlpha { + return ([self skipButtonHidden] ? 0.0 : 1.0); +} + +- (BOOL)hasContinueOrSkip { + return !([self neverHasContinueButton] && [self neverHasSkipButton] && [self neverHasFootnote]); +} + +- (void)updateContinueAndSkipEnabled { + [_skipButton setTitle:_skipButtonItem.title ? : ORKLocalizedString(@"BUTTON_SKIP", nil) forState:UIControlStateNormal]; + + if ([self neverHasContinueButton]) { + _continueButton.hidden = YES; + } + + if (_useNextForSkip && _skipButtonItem) { + _continueButton.alpha = (_continueButtonItem == nil && _skipButtonItem == nil) ? 0 : 1; + [_continueButton setTitle: _continueButtonItem.title ? : _skipButtonItem.title forState:UIControlStateNormal]; + _continueButton.accessibilityHint = _continueButtonItem.accessibilityHint ? : _skipButtonItem.accessibilityHint; + } else { + _continueButton.alpha = (_continueButtonItem == nil) ? 0 : 1; + [_continueButton setTitle: _continueButtonItem.title forState:UIControlStateNormal]; + _continueButton.accessibilityHint = _continueButtonItem.accessibilityHint; + } + + _continueButton.enabled = (_continueEnabled || (_useNextForSkip && _skipButtonItem)); + _continueButton.disableTintColor = [[self tintColor] colorWithAlphaComponent:0.3]; + + // Do not modify _continueButton.userInteractionEnabled during continueButton disable period + // or when the activity indicator is present + if (_continueButtonJustTapped == NO && _activityIndicatorView == nil) { + _continueButton.userInteractionEnabled = (_continueEnabled || (_useNextForSkip && _skipButtonItem)); + } + + _skipButton.alpha = [self skipButtonAlpha]; + [self setNeedsUpdateConstraints]; + [self setUpConstraints]; +} + +- (void)showActivityIndicator:(BOOL)showActivityIndicator { + + [_continueButton setUserInteractionEnabled:!showActivityIndicator]; + + if (showActivityIndicator == YES) { + if (_activityIndicatorView == nil) { + _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + [_activityIndicatorView startAnimating]; + + [_continueButton addSubview:_activityIndicatorView]; + CGPoint center = CGPointMake(_continueButton.titleLabel.frame.origin.x - activityIndicatorPadding, _continueButton.titleLabel.center.y); + [_activityIndicatorView setCenter:center]; + } else { + [_activityIndicatorView startAnimating]; + } + } else { + [_activityIndicatorView stopAnimating]; + } +} + +- (void)setContinueEnabled:(BOOL)continueEnabled { + _continueEnabled = continueEnabled; + [self updateContinueAndSkipEnabled]; +} + +- (void)setSkipEnabled:(BOOL)skipEnabled { + _skipEnabled = skipEnabled; + self.skipButton.enabled = _skipEnabled; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + _skipButtonItem = skipButtonItem; + [self updateContinueAndSkipEnabled]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + _continueButtonItem = continueButtonItem; + [self updateContinueAndSkipEnabled]; +} + +- (void)setUpConstraints { + + CGFloat leftRightPadding = _useExtendedPadding ? ORKStepContainerExtendedLeftRightPaddingForWindow(self.window) : ORKStepContainerLeftRightPaddingForWindow(self.window); + + if (_regularConstraints) { + [NSLayoutConstraint deactivateConstraints:_regularConstraints]; + } + [_regularConstraints removeAllObjects]; + _regularConstraints = [NSMutableArray new]; + + if (_continueButton) { + [_regularConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:topSpacing], + [NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:leftRightPadding], + [NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-leftRightPadding], + ]]; + } + + if (_skipButton) { + [_regularConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_skipButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_continueButton ? : self.safeAreaLayoutGuide + attribute:_continueButton ? NSLayoutAttributeBottom : NSLayoutAttributeTop + multiplier:1.0 + constant:_continueButton ? standardSpacing : topSpacing], + [NSLayoutConstraint constraintWithItem:_skipButton + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:skipButtonHeight], + [NSLayoutConstraint constraintWithItem:_skipButton + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:leftRightPadding], + [NSLayoutConstraint constraintWithItem:_skipButton + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-leftRightPadding], + ]]; + } + + UIView *lastView = _skipButton ? : _continueButton; + + if (lastView) { + + [_regularConstraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:lastView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:bottomSpacing] + ]; + } + else { + [_regularConstraints addObject:[NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0] + ]; + } + if (effectView) { + [_regularConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:effectView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:effectView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:effectView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:effectView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + + } + + [NSLayoutConstraint activateConstraints:_regularConstraints]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self setUpConstraints]; +} + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { + BOOL isInside = [super pointInside:point withEvent:event]; + if (!isInside) { + isInside = [self.continueButton pointInside:[self convertPoint:point toView:self.continueButton] withEvent:event]; + } + return isInside; +} + +- (void)setUseExtendedPadding:(BOOL)useExtendedPadding { + _useExtendedPadding = useExtendedPadding; + [self setUpConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView_Internal.h new file mode 100755 index 0000000..ea60c87 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKNavigationContainerView_Internal.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import +#import "ORKNavigationContainerView.h" +#import "ORKFootnoteLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKBorderedButton () + +- (void)setAppearanceAsTextButton; +- (void)setAppearanceAsBoldTextButton; +- (void)resetAppearanceAsBorderedButton; + +@end + +@interface ORKNavigationContainerView () + +@property (nonatomic, strong, readonly) ORKContinueButton *continueButton; +@property (nonatomic, strong, readonly) ORKBorderedButton *skipButton; +@property (nonatomic, strong, readonly) ORKFootnoteLabel *footnoteLabel; +@property (nonatomic, strong, readonly) ORKBorderedButton *cancelButton; + +@property (nonatomic) BOOL useNextForSkip; +@property (nonatomic, getter=isOptional) BOOL optional; + +@property (nonatomic) ORKNavigationContainerButtonStyle skipButtonStyle; +@property (nonatomic) ORKNavigationContainerButtonStyle cancelButtonStyle; + +- (void)updateContinueAndSkipEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.h new file mode 100755 index 0000000..13b5767 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKObserver : NSObject + +@property (nonatomic, strong) NSArray *keyPaths; +@property (nonatomic, strong) id target; +@property (nonatomic) BOOL observing; +@property (nonatomic) void *context; + +@property (nonatomic, weak, nullable) id delegate; +@property (nonatomic) SEL action; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithTarget:(id)target keyPaths:(NSArray *)keyPaths delegate:(id)delegate action:(SEL)action context:(void *)context NS_DESIGNATED_INITIALIZER; + +- (void)startObserving; + +@end + + +@protocol ORKScrollViewObserverDelegate + +@required +- (void)observedScrollViewDidScroll:(UIScrollView *)scrollView; + +@end + + +@interface ORKScrollViewObserver : ORKObserver + +- (instancetype)initWithTargetView:(UIScrollView *)scrollView delegate:(id )delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.m new file mode 100755 index 0000000..3c4c615 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKObserver.m @@ -0,0 +1,112 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKObserver.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKObserver + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithTarget:(id)target keyPaths:(NSArray *)keyPaths delegate:(id)delegate action:(SEL)action context:(void *)context { + self = [super init]; + if (self) { + self.keyPaths = keyPaths; + self.target = target; + self.delegate = delegate; + self.action = action; + self.context = context; + [self startObserving]; + } + return self; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { + NSAssert(context == self.context, @"Unexpected KVO"); + ORKSuppressPerformSelectorWarning( + (void)[self.delegate performSelector:self.action withObject:self.target]; + ); +} + +- (void)startObserving { + if (_observing == NO) { + NSAssert(self.keyPaths, @""); + NSAssert(self.target, @""); + NSAssert(self.context, @""); + NSAssert(self.delegate, @""); + NSAssert(self.action, @""); + for (NSString *keyPath in self.keyPaths) { + [self.target addObserver:self forKeyPath:keyPath options:(NSKeyValueObservingOptions)0 context:self.context]; + } + self.observing = YES; + } +} + +- (void)stopObserving { + if (_observing) { + for (NSString *keyPath in _keyPaths) { + [self.target removeObserver:self forKeyPath:keyPath]; + } + _observing = NO; + } +} + +- (void)dealloc { + [self stopObserving]; +} + +@end + + +@implementation ORKScrollViewObserver + +static void *_ORKScrollViewObserverContext = &_ORKScrollViewObserverContext; + +- (instancetype)initWithTargetView:(UIScrollView *)scrollView delegate:(id )delegate { + return [super initWithTarget:scrollView + keyPaths:@[ @"contentOffset" ] + delegate:delegate + action:@selector(observedScrollViewDidScroll:) + context:_ORKScrollViewObserverContext]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.h new file mode 100755 index 0000000..10dfb65 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +typedef NS_ENUM(NSInteger, ORKOperationState) { + ORKOperationReady, + ORKOperationExecuting, + ORKOperationFinished +}; + + +@class ORKOperation; + +typedef void (^ORKOperationBlock)(ORKOperation *operation); + + +/** + A concurrent operation for collecting data for upload. + */ +@interface ORKOperation : NSOperation + +@property (nonatomic, strong) NSRecursiveLock *lock; +@property (readwrite, nonatomic, assign) ORKOperationState state; +@property (nonatomic, strong) NSError *error; + +/** + Block that will be called inside the lock during -start, + just after transitioning to RKOperationExecuting. + */ +@property (nonatomic, strong) ORKOperationBlock startBlock; + +/** + Finishes the operation cleanly. + */ +- (void)safeFinish; + +/** + Sets the error to indicate a timeout, and finishes. + */ +- (void)doTimeout; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.m new file mode 100755 index 0000000..c732615 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOperation.m @@ -0,0 +1,172 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKOperation.h" +#import "ORKErrors.h" +#import "ORKHelpers_Internal.h" + + +static NSString *keyPathFromOperationState(ORKOperationState state) { + switch (state) { + case ORKOperationReady: + return @"isReady"; + case ORKOperationExecuting: + return @"isExecuting"; + case ORKOperationFinished: + return @"isFinished"; + default: + return @"state"; + } +} + +static BOOL stateTransitionIsValid(ORKOperationState fromState, ORKOperationState toState, BOOL isCancelled) { + switch (fromState) { + case ORKOperationReady: + switch (toState) { + case ORKOperationExecuting: + return YES; + case ORKOperationFinished: + return isCancelled; + default: + return NO; + } + case ORKOperationExecuting: + switch (toState) { + case ORKOperationFinished: + return YES; + default: + return NO; + } + case ORKOperationFinished: + return NO; + default: + return YES; + } +} + + +@implementation ORKOperation + +- (instancetype)init { + self = [super init]; + if (self) { + self.lock = [[NSRecursiveLock alloc] init]; + self.lock.name = @"com.apple.ResearchKit.Operation"; + self.state = ORKOperationReady; + } + return self; +} + +- (void)setState:(ORKOperationState)state { + [self.lock lock]; + if (stateTransitionIsValid(self.state, state, [self isCancelled])) { + NSString *oldStateKey = keyPathFromOperationState(self.state); + NSString *newStateKey = keyPathFromOperationState(state); + + [self willChangeValueForKey:newStateKey]; + [self willChangeValueForKey:oldStateKey]; + _state = state; + [self didChangeValueForKey:oldStateKey]; + [self didChangeValueForKey:newStateKey]; + + } + [self.lock unlock]; +} + + +#pragma mark - NSOperation + +- (BOOL)isReady { + return self.state == ORKOperationReady && [super isReady]; +} + +- (BOOL)isExecuting { + return self.state == ORKOperationExecuting; +} + +- (BOOL)isFinished { + return self.state == ORKOperationFinished; +} + +- (BOOL)isConcurrent { + return YES; +} + +- (void)start { + [self.lock lock]; + + if ([self isCancelled]) { + [self finish]; + } else if ([self isReady]) { + self.state = ORKOperationExecuting; + + ORK_Log_Debug("%@ start", self.class); + _startBlock(self); + } + [self.lock unlock]; +} + +- (void)finish { + ORK_Log_Debug("%@ finish: %@", self, (self.error ? : @"OK")); + self.state = ORKOperationFinished; +} + +- (void)cancel { + [self.lock lock]; + if (![self isFinished] && ![self isCancelled]) { + if (! self.error) { + self.error = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:nil]; + } + [self willChangeValueForKey:@"isCancelled"]; + [super cancel]; + [self didChangeValueForKey:@"isCancelled"]; + } + [self.lock unlock]; +} + +- (void)safeFinish { + [self.lock lock]; + if ([self isExecuting]) { + [self finish]; + } + [self.lock unlock]; +} + +- (void)doTimeout { + [self.lock lock]; + if (self.state == ORKOperationExecuting) { + self.error = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:nil]; + [self finish]; + } + [self.lock unlock]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.h new file mode 100755 index 0000000..307de76 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.h @@ -0,0 +1,717 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + +@class ORKNavigableOrderedTask; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKOrderedTask (ORKPredefinedActiveTask) + +/** + Returns a predefined Amsler Grid task that helps in detecting problems in user's vision. + + In an Amsler Grid task, the participant is shown a square grid. The participant is asked to mark the areas where they notice disctortions in the grid. + + Data collected by the task is in the form of an `ORKAmslerGridResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data collected. + If the value of this parameter is `nil`, the default localized text is displayed. + @param options Options that affect the features of the predefined task. + */ ++ (ORKNavigableOrderedTask *)amslerGridTaskWithIdentifier:(NSString *)identifier + intendedUseDescription: (nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that measures the upper extremity function. + + In a hole peg test task, the participant is asked to fill holes with pegs. + + A hole peg test task can be used to assess arm and hand function, especially in patients with severe disability. + + Data collected in this task is in the form of an `ORKHolePegTestResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text will be displayed. + @param dominantHand The participant dominant hand that will be tested first. + @param numberOfPegs The number of pegs to place in the pegboard. + @param threshold The threshold value used for the detection area. + @param rotated A test variant that also requires peg rotation. + @param timeLimit The duration allowed to validate the peg position. + @param options Options that affect the features of the predefined task. + + @return An active hole peg test task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKNavigableOrderedTask *)holePegTestTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + dominantHand:(ORKBodySagittal)dominantHand + numberOfPegs:(int)numberOfPegs + threshold:(double)threshold + rotated:(BOOL)rotated + timeLimit:(NSTimeInterval)timeLimit + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that consists of a fitness check. + + In a fitness check task, the participant is asked to walk for a specified duration + (typically several minutes). During this period, various sensor data is collected and returned by + the task view controller's delegate. Sensor data can include accelerometer, device motion, + pedometer, location, and heart rate data where available. + + At the conclusion of the walk, if heart rate data is available, the participant is asked to sit + down and rest for a period. Data collection continues during this period. + + By default, the task includes an instruction step that explains what the user needs to do during + the task, but this can be excluded with `ORKPredefinedTaskOptionExcludeInstructions`. + + Data collected from this task can be used to compute measures of general fitness. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param walkDuration The duration of the walk (the maximum is 10 minutes). + @param restDuration The duration of the post walk rest period. + @param options Options that affect the features of the predefined task. + + @return An active fitness check task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)fitnessCheckTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + walkDuration:(NSTimeInterval)walkDuration + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that consists of a short walk. + + In a short walk task, the participant is asked to walk a short distance, which may be indoors. + Typical uses of the resulting data are to assess stride length, smoothness, sway, or other aspects + of the participant's gait. + + The presentation of the short walk task differs from the fitness check task in that the distance is + replaced by the number of steps taken, and the walk is split into a series of legs. After each leg, + the user is asked to turn and reverse direction. + + The data collected by this task can include accelerometer, device motion, and pedometer data. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param numberOfStepsPerLeg The number of steps the participant is asked to walk. If the + pedometer is unavailable, a distance is suggested and a suitable + count down timer is displayed for each leg of the walk. + @param restDuration The duration of the rest period. When the value of this parameter is + nonzero, the user is asked to stand still for the specified rest + period after the turn sequence has been completed, and baseline + data is collected. + @param options Options that affect the features of the predefined task. + + @return An active short walk task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)shortWalkTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + numberOfStepsPerLeg:(NSInteger)numberOfStepsPerLeg + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that consists of a short walk back and forth. + + In a short walk task, the participant is asked to walk a short distance, which may be indoors. + Typical uses of the resulting data are to assess stride length, smoothness, sway, or other aspects + of the participant's gait. + + The presentation of the back and forth walk task differs from the short walk in that the participant + is asked to walk back and forth rather than walking in a straight line for a certain number of steps. + + The participant is then asked to turn in a full circle and then stand still. + + This task is intended to allow the participant to walk in a confined space where the participant + does not have access to a long hallway to walk in a continuous straight line. Additionally, by asking + the participant to turn in a full circle and then stand still, the activity can access balance and + concentration. + + The data collected by this task can include accelerometer, device motion, and pedometer data. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param walkDuration The duration of the walking period. + @param restDuration The duration of the rest period. When the value of this parameter is + nonzero, the user is asked to stand still for the specified rest + period after the turn sequence has been completed, and baseline + data is collected. + @param options Options that affect the features of the predefined task. + + @return An active short walk task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)walkBackAndForthTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + walkDuration:(NSTimeInterval)walkDuration + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options; + + +/** + The knee range of motion task returns a task that measures the range of motion for either a left or right knee. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param limbOption Which knee is being measured. + @param intendedUseDescription A localized string describing the intended use of the data collected. If the value of this parameter is `nil`, default localized text is used. + @param options Options that affect the features of the predefined task. + */ ++ (ORKOrderedTask *)kneeRangeOfMotionTaskWithIdentifier:(NSString *)identifier + limbOption:(ORKPredefinedTaskLimbOption)limbOption + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options; + + +/** + The shoulder range of motion task returns a task that measures the range of motion for either a left or right shoulder. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param limbOption Which shoulder is being measured. + @param intendedUseDescription A localized string describing the intended use of the data collected. If the value of this parameter is `nil`, default localized text is used. + @param options Options that affect the features of the predefined task. + */ ++ (ORKOrderedTask *)shoulderRangeOfMotionTaskWithIdentifier:(NSString *)identifier + limbOption:(ORKPredefinedTaskLimbOption)limbOption + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that enables an audio recording WITH a check of the audio level. + + In an audio recording task, the participant is asked to make some kind of sound + with their voice, and the audio data is collected. + + An audio task can be used to measure properties of the user's voice, such as + frequency range, or the ability to pronounce certain sounds. + + If `checkAudioLevel == YES` then a navigation rule is added to do a simple check of the background + noise level. If the background noise is too loud, then the participant is instructed to move to a + quieter location before trying again. + + Data collected in this task consists of audio information. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, default + localized text is used. + @param speechInstruction Instructional content describing what the user needs to do when + recording begins. If the value of this parameter is `nil`, + default localized text is used. + @param shortSpeechInstruction Instructional content shown during audio recording. If the value of + this parameter is `nil`, default localized text is used. + @param duration The length of the count down timer that runs while audio data is + collected. + @param recordingSettings See "AV Foundation Audio Settings Constants" for possible values. + @param checkAudioLevel If `YES` then add navigational rules to check the background noise level. + @param options Options that affect the features of the predefined task. + + @return An active audio task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKNavigableOrderedTask *)audioTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechInstruction:(nullable NSString *)speechInstruction + shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction + duration:(NSTimeInterval)duration + recordingSettings:(nullable NSDictionary *)recordingSettings + checkAudioLevel:(BOOL)checkAudioLevel + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that consists of two finger tapping (Optionally with a hand specified) + + In a two finger tapping task, the participant is asked to rhythmically and alternately tap two + targets on the device screen. + + A two finger tapping task can be used to assess basic motor capabilities including speed, accuracy, + and rhythm. + + Data collected in this task includes touch activity and accelerometer information. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text will be displayed. + @param duration The length of the count down timer that runs while touch data is + collected. + @param handOptions Options for determining which hand(s) to test. + @param options Options that affect the features of the predefined task. + + @return An active two finger tapping task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)twoFingerTappingIntervalTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + duration:(NSTimeInterval)duration + handOptions:(ORKPredefinedTaskHandOption)handOptions + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that tests spatial span memory. + + In a spatial span memory task, the participant is asked to repeat pattern sequences of increasing + length in a game-like environment. You can use this task to assess visuospatial memory and + executive function. + + + In each round of the task, an array of + target images are shown in a grid (by default, the images are flowers). The round consists of a + demonstration phase and an interactive phase. In the demonstration phase, some of the flowers + change color in a specific sequence. After the demonstration, the user is asked to tap the flowers + in the same sequence for the interactive phase. + + The span (that is, the length of the pattern sequence) is automatically varied during the task, + increasing after users succeed and decreasing after they fail, within the range specified by + minimum and maximum values that you specify. You can also customize the speed of sequence playback + and the shape of the tap target. + + A spatial span memory task finishes when the user has either completed the maximum number of tests + or made the maximum number of errors. + + Data collected by the task is in the form of an `ORKSpatialSpanMemoryResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param initialSpan The sequence length of the initial memory pattern. + @param minimumSpan The minimum pattern sequence length. + @param maximumSpan The maximum pattern sequence length. + @param playSpeed The time per sequence item; a smaller value means faster sequence + play. + @param maximumTests The maximum number of rounds to conduct. + @param maximumConsecutiveFailures The maximum number of consecutive failures the user can make before + the task is terminated. + @param customTargetImage The image to use for the task. By default, and if the value of this + parameter is `nil`, the image is a flower. To supply a custom + image, create a template image to which iOS adds the tint color. + @param customTargetPluralName The name associated with `customTargetImage`; by default, the value + of this parameter is @"flowers". + @param requireReversal A Boolean value that indicates whether to require the user to tap + the sequence in reverse order. + @param options Options that affect the features of the predefined task. + + @return An active spatial span memory task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)spatialSpanMemoryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + initialSpan:(NSInteger)initialSpan + minimumSpan:(NSInteger)minimumSpan + maximumSpan:(NSInteger)maximumSpan + playSpeed:(NSTimeInterval)playSpeed + maximumTests:(NSInteger)maximumTests + maximumConsecutiveFailures:(NSInteger)maximumConsecutiveFailures + customTargetImage:(nullable UIImage *)customTargetImage + customTargetPluralName:(nullable NSString *)customTargetPluralName + requireReversal:(BOOL)requireReversal + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined Stroop task that tests participants selective attention and cognitive flexibility. + + In a stroop task, the participant is shown a text. The text is a name of a color, but the text is printed in a color that may or may not be denoted by the name. In each attempt of the task, the participant has to press the button that corresponds to the first letter of the color in which the text is printed. The participant has to ignore the name of the color written in the text, but respond based on the color of the text. + + A stroop task finishes when the user has completed all the attempts, irrespective of correct or incorrect answers. + + Data collected by the task is in the form of an `ORKStroopResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param numberOfAttempts Total number of stroop questions to include in the task. + @param options Options that affect the features of the predefined task. + */ ++ (ORKOrderedTask *)stroopTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + numberOfAttempts:(NSInteger)numberOfAttempts + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined Speech Recognition task that transcribes participant's speech. + + In a Speech Recognition task, the participant is shown a text or image or both. The participant has to read the text aloud, or describe the image. + + A Speech Recognition task finishes when the user presses the Stop Recording button. + + Data collected by the task is in the form of an `ORKSpeechRecognitionResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data collected. + If the value of this parameter is `nil`, the default localized text is displayed. + @param speechRecognizerLocale An enum that represents the locale to be used by speech recognition API. + @param speechRecognitionImage The image shown to the participant. + @param speechRecognitionText The text shown to the participant. + @param shouldHideTranscript The boolean value used to show or hide the transcription from the user. + @param allowsEdittingTranscript The boolean value used to present step that allows editting transcription. + @param options Options that affect the features of the predefined task. + */ ++ (ORKOrderedTask *)speechRecognitionTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechRecognizerLocale:(ORKSpeechRecognizerLocale)speechRecognizerLocale + speechRecognitionImage:(nullable UIImage *)speechRecognitionImage + speechRecognitionText:(nullable NSString *)speechRecognitionText + shouldHideTranscript:(BOOL)shouldHideTranscript + allowsEdittingTranscript:(BOOL)allowsEdittingTranscript + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that tests speech audiometry. + + In a speech in noise task, the participant is asked to listen to some sentences mixed with background noise at varying signal to noise ratio (SNR). + + You can use a speech in noise task to measure the speech reception threshold (SRT) of an individual. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, default + localized text is used. + @param options Options that affect the features of the predefined task. + + @return An active speech in noise task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)speechInNoiseTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options; + + + +/** + Returns a predefined task that tests tone audiometry. + + In a tone audiometry task, the participant is asked to listen to some tones with different audio + frequencies, playing on different channels (left and right), with the volume being progressively + increased until the participant taps a button. + + You can use a tone audiometry task to measure properties of the user's hearing, based on their + reaction to a wide range of frequencies. + + Data collected in this task consists of audio signal amplitude for specific frequencies and + channels. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, default + localized text is used. + @param speechInstruction Instructional content describing what the user needs to do when + recording begins. If the value of this parameter is `nil`, + default localized text is used. + @param shortSpeechInstruction Instructional content shown during audio recording. If the value of + this parameter is `nil`, default localized text is used. + @param toneDuration The maximum length of the duration for each tone (each tone can be + interrupted sooner, after the participant presses the main + button). + @param options Options that affect the features of the predefined task. + + @return An active tone audiometry task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)toneAudiometryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechInstruction:(nullable NSString *)speechInstruction + shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction + toneDuration:(NSTimeInterval)toneDuration + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that tests dBHL tone audiometry. + + In the dBHL tone audiometry task, the participant is asked to listen to some tones with different audio + frequencies, playing on different channels (left and right), that vary in dB HL values depending on whether or not the user tapped the button. + + You can use a tone audiometry task to measure the hearing threshold of the user. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, default + localized text is used. + @param options Options that affect the features of the predefined task. + + @return An active dBHL tone audiometry task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)dBHLToneAudiometryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that tests the participant's reaction time. + + In a reaction time task, the participant is asked to move the device sharply in any + direction in response to a visual cue. You can use this task to accurately assess the participant's + simple reaction time. + + A reaction time task finishes when the participant has completed the required + number of attempts successfully. An attempt is successful when the participant exerts acceleration + greater than `thresholdAcceleration` to the device after the stimulus has been delivered and before + `timeout` has elapsed. An attempt is unsuccessful if acceleration greater than + `thresholdAcceleration` is applied to the device before the stimulus or if this does not occur + before `timeout` has elapsed. If unsuccessful, the result is not reported and the participant must + try again to proceed with the task. + + Data collected by the task is in the form of ORKReactionTimeResult objects. These + objects contain a timestamp representing the delivery of the stimulus and an ORKFileResult, which + references the motion data collected during an attempt. The researcher can use these to evaluate + the response to the stimulus and calculate the reaction time. + + @param identifier The task identifier to use for this task, appropriate to the + study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the + default localized text is displayed. + @param maximumStimulusInterval The maximum interval before the stimulus is delivered. + @param minimumStimulusInterval The minimum interval before the stimulus is delivered. + @param thresholdAcceleration The acceleration required to end a reaction time test. + @param numberOfAttempts The number of successful attempts required before the task is + complete. The active step result will contain this many + child results if the task is completed. + @param timeout The interval permitted after the stimulus until the test fails, + if the threshold is not reached. + @param successSoundID The sound to play after a successful attempt. + @param timeoutSoundID The sound to play after an attempt that times out. + @param failureSoundID The sound to play after an unsuccessful attempt. + @param options Options that affect the features of the predefined task. + + @return An active device motion reaction time task that can be presented with an `ORKTaskViewController` object. + */ + ++ (ORKOrderedTask *)reactionTimeTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + maximumStimulusInterval:(NSTimeInterval)maximumStimulusInterval + minimumStimulusInterval:(NSTimeInterval)minimumStimulusInterval + thresholdAcceleration:(double)thresholdAcceleration + numberOfAttempts:(int)numberOfAttempts + timeout:(NSTimeInterval)timeout + successSound:(UInt32)successSoundID + timeoutSound:(UInt32)timeoutSoundID + failureSound:(UInt32)failureSoundID + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that consists of a Tower of Hanoi puzzle. + + In a Tower of Hanoi task, the participant is asked to solve the classic puzzle in as few moves as possible. + You can use this task to assess the participant's problem-solving skills. + + A Tower of Hanoi task finishes when the participant has completed the puzzle correctly or concedes that he or she cannot solve it. + + Data collected by the task is in the form of an `ORKTowerOfHanoiResult` object. Data collected in this task consists of how many moves were taken and whether the puzzle was successfully completed or not. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the + default localized text is displayed. + @param numberOfDisks The number of disks in the puzzle; the default value for this property is 3. + @param options Options that affect the features of the predefined task. + + @return An active device motion reaction time task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)towerOfHanoiTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + numberOfDisks:(NSUInteger)numberOfDisks + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that consists of a timed walk, with a distinct turn around step. + + In a timed walk task, the participant is asked to walk for a specific distance as quickly as + possible, but safely. Then the participant is asked to turn around. The task is immediately + administered again by having the patient walk back the same distance. + A timed walk task can be used to measure lower extremity function. + + The presentation of the timed walk task differs from both the fitness check task and the short + walk task in that the distance is fixed. After a first walk, the user is asked to turn, then reverse + direction. + + The data collected by this task can include accelerometer, device motion, pedometer data, + and location where available. + + Data collected by the task is in the form of an `ORKTimedWalkResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param distanceInMeters The timed walk distance in meters. + @param timeLimit The time limit to complete the trials. + @param turnAroundTimeLimit The time limit to complete the turn around step, passing zero or negative value to this parameter will bypass the turnAroundTime step. + @param includeAssistiveDeviceForm A Boolean value that indicates whether to inlude the form step + about the usage of an assistive device. + @param options Options that affect the features of the predefined task. + + @return An active timed walk task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)timedWalkTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + distanceInMeters:(double)distanceInMeters + timeLimit:(NSTimeInterval)timeLimit + turnAroundTimeLimit:(NSTimeInterval)turnAroundTimeLimit + includeAssistiveDeviceForm:(BOOL)includeAssistiveDeviceForm + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that consists of the paced serial addition test (PSAT). + + In a PSAT task, the participant is asked to add a new digit to the one immediately before it + every 2 or 3 seconds. + + A PSAT task can be used to measure the cognitive function that assesses auditory and/or + visual information processing speed and flexibility, as well as calculation ability. + + Data collected by the task is in the form of an `ORKPSATResult` object. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param presentationMode The presentation mode of the PSAT test (auditory or visual or both). + @param interStimulusInterval The time interval between two digits presented. + @param stimulusDuration The time duration the digit is shown on screen (only for + visual PSAT, that is PVSAT and PAVSAT). + @param seriesLength The number of digits that will be presented during the task. + @param options Options that affect the features of the predefined task. + + @return An active PSAT task that can be presented with an `ORKTaskViewController` object. + + */ ++ (ORKOrderedTask *)PSATTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + presentationMode:(ORKPSATPresentationMode)presentationMode + interStimulusInterval:(NSTimeInterval)interStimulusInterval + stimulusDuration:(NSTimeInterval)stimulusDuration + seriesLength:(NSInteger)seriesLength + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that measures hand tremor. + + In a tremor assessment task, the participant is asked to hold the device with their most affected + hand in various positions while accelerometer and motion data are captured. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param activeStepDuration The duration for each active step in the task. + @param activeTaskOptions Options that affect which active steps are presented for this task. + @param handOptions Options for determining which hand(s) to test. + @param options Options that affect the features of the predefined task. + + @return An active tremor test task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKNavigableOrderedTask *)tremorTestTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + activeStepDuration:(NSTimeInterval)activeStepDuration + activeTaskOptions:(ORKTremorActiveTaskOption)activeTaskOptions + handOptions:(ORKPredefinedTaskHandOption)handOptions + options:(ORKPredefinedTaskOption)options; + + +/** + Returns a predefined task that measures visual attention and task switching. + + In a trail making test, the participant is asked to connect a series of cicles labeled 1,2,3... or + 1,A,2,B,3,C... and time to complete the test is recorded. + + `ORKTrailMakingTypeIdentifierA` uses the pattern: 1-2-3-4-5-6-7. + `ORKTrailMakingTypeIdentifierB` uses the pattern: 1-A-2-B-3-C-4-D-5-E-6-F-7 + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + @param trailmakingInstruction Instructional content describing what the user needs to do when + the task begins. If the value of this parameter is `nil`, + @param trailType Type of trail to display. Either `ORKTrailMakingTypeIdentifierA` or `ORKTrailMakingTypeIdentifierB` + @param options Options that affect the features of the predefined task. + + @return An active trail making test task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)trailmakingTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + trailmakingInstruction:(nullable NSString *)trailmakingInstruction + trailType:(ORKTrailMakingTypeIdentifier)trailType + options:(ORKPredefinedTaskOption)options; + +/** + Returns a predefined task that measures visual acuity using landolt C. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + + @return An landolt C visual acuity task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)landoltCVisualAcuityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)itendedDescription; + +/** + Returns a predefined task that measures contrast sensitivity using landolt C. + + @param identifier The task identifier to use for this task, appropriate to the study. + @param intendedUseDescription A localized string describing the intended use of the data + collected. If the value of this parameter is `nil`, the default + localized text is displayed. + + @return An landolt C contrast sensitivity task that can be presented with an `ORKTaskViewController` object. + */ ++ (ORKOrderedTask *)landoltCContrastSensitivityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)itendedDescription; + + ++ (ORKOrderedTask *)touchAbilityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + taskOptions:(ORKTouchAbilityTaskOption)taskOptions + options:(ORKPredefinedTaskOption)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.m new file mode 100755 index 0000000..fcaab32 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask+ORKPredefinedActiveTask.m @@ -0,0 +1,2973 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKOrderedTask+ORKPredefinedActiveTask.h" +#import "ORKOrderedTask_Private.h" + +#import "ORKAudioStepViewController.h" +#import "ORKAmslerGridStepViewController.h" +#import "ORKCountdownStepViewController.h" +#import "ORKTouchAnywhereStepViewController.h" +#import "ORKFitnessStepViewController.h" +#import "ORKToneAudiometryStepViewController.h" +#import "ORKSpatialSpanMemoryStepViewController.h" +#import "ORKSpeechRecognitionStepViewController.h" +#import "ORKStroopStepViewController.h" +#import "ORKWalkingTaskStepViewController.h" + +#import "ORKAccelerometerRecorder.h" +#import "ORKActiveStep_Internal.h" +#import "ORKAmslerGridStep.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKAudioLevelNavigationRule.h" +#import "ORKAudioRecorder.h" +#import "ORKAudioStep.h" +#import "ORKCompletionStep.h" +#import "ORKCountdownStep.h" +#import "ORKEnvironmentSPLMeterStep.h" +#import "ORKHolePegTestPlaceStep.h" +#import "ORKHolePegTestRemoveStep.h" +#import "ORKTouchAnywhereStep.h" +#import "ORKFitnessStep.h" +#import "ORKFormStep.h" +#import "ORKNavigableOrderedTask.h" +#import "ORKPSATStep.h" +#import "ORKQuestionStep.h" +#import "ORKReactionTimeStep.h" +#import "ORKSpatialSpanMemoryStep.h" +#import "ORKSpeechRecognitionStep.h" +#import "ORKStep_Private.h" +#import "ORKStroopStep.h" +#import "ORKTappingIntervalStep.h" +#import "ORKTimedWalkStep.h" +#import "ORKToneAudiometryStep.h" +#import "ORKTowerOfHanoiStep.h" +#import "ORKTrailmakingStep.h" +#import "ORKVisualConsentStep.h" +#import "ORKRangeOfMotionStep.h" +#import "ORKShoulderRangeOfMotionStep.h" +#import "ORKWaitStep.h" +#import "ORKWalkingTaskStep.h" +#import "ORKResultPredicate.h" +#import "ORKSpeechInNoiseStep.h" +#import "ORKdBHLToneAudiometryStep.h" +#import "ORKdBHLToneAudiometryOnboardingStep.h" +#import "ORKSkin.h" +#import +#import "ORKTouchAbilityTapStep.h" +#import "ORKTouchAbilityLongPressStep.h" +#import "ORKTouchAbilitySwipeStep.h" +#import "ORKTouchAbilityPinchStep.h" +#import "ORKTouchAbilityRotationStep.h" +#import "ORKTouchAbilityScrollStep.h" + +#import "ORKHelpers_Internal.h" +#import "UIImage+ResearchKit.h" +#import + + +ORKTaskProgress ORKTaskProgressMake(NSUInteger current, NSUInteger total) { + return (ORKTaskProgress){.current=current, .total=total}; +} + +#pragma mark - Predefined + +NSString *const ORKInstruction0StepIdentifier = @"instruction"; +NSString *const ORKInstruction1StepIdentifier = @"instruction1"; +NSString *const ORKInstruction2StepIdentifier = @"instruction2"; +NSString *const ORKInstruction3StepIdentifier = @"instruction3"; +NSString *const ORKInstruction4StepIdentifier = @"instruction4"; +NSString *const ORKInstruction5StepIdentifier = @"instruction5"; +NSString *const ORKInstruction6StepIdentifier = @"instruction6"; +NSString *const ORKInstruction7StepIdentifier = @"instruction7"; + +NSString *const ORKCountdownStepIdentifier = @"countdown"; +NSString *const ORKCountdown1StepIdentifier = @"countdown1"; +NSString *const ORKCountdown2StepIdentifier = @"countdown2"; +NSString *const ORKCountdown3StepIdentifier = @"countdown3"; +NSString *const ORKCountdown4StepIdentifier = @"countdown4"; +NSString *const ORKCountdown5StepIdentifier = @"countdown5"; + +NSString *const ORKEditSpeechTranscript0StepIdentifier = @"editSpeechTranscript0"; + +NSString *const ORKConclusionStepIdentifier = @"conclusion"; + +NSString *const ORKActiveTaskLeftHandIdentifier = @"left"; +NSString *const ORKActiveTaskMostAffectedHandIdentifier = @"mostAffected"; +NSString *const ORKActiveTaskRightHandIdentifier = @"right"; +NSString *const ORKActiveTaskSkipHandStepIdentifier = @"skipHand"; + +NSString *const ORKTouchAnywhereStepIdentifier = @"touch.anywhere"; + +NSString *const ORKAudioRecorderIdentifier = @"audio"; +NSString *const ORKAccelerometerRecorderIdentifier = @"accelerometer"; +NSString *const ORKStreamingAudioRecorderIdentifier = @"streamingAudio"; +NSString *const ORKPedometerRecorderIdentifier = @"pedometer"; +NSString *const ORKDeviceMotionRecorderIdentifier = @"deviceMotion"; +NSString *const ORKLocationRecorderIdentifier = @"location"; +NSString *const ORKHeartRateRecorderIdentifier = @"heartRate"; + +void ORKStepArrayAddStep(NSMutableArray *array, ORKStep *step) { + [step validateParameters]; + [array addObject:step]; +} + +@implementation ORKOrderedTask (ORKMakeTaskUtilities) + ++ (ORKCompletionStep *)makeCompletionStep { + ORKCompletionStep *step = [[ORKCompletionStep alloc] initWithIdentifier:ORKConclusionStepIdentifier]; + step.title = ORKLocalizedString(@"TASK_COMPLETE_TITLE", nil); + step.text = ORKLocalizedString(@"TASK_COMPLETE_TEXT", nil); + step.shouldTintImages = YES; + return step; +} + ++ (NSDateComponentsFormatter *)textTimeFormatter { + NSDateComponentsFormatter *formatter = [NSDateComponentsFormatter new]; + formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleSpellOut; + + // Exception list: Korean, Chinese (all), Thai, and Vietnamese. + NSArray *nonSpelledOutLanguages = @[@"ko", @"zh", @"th", @"vi", @"ja"]; + NSString *currentLanguage = [[NSBundle mainBundle] preferredLocalizations].firstObject; + NSString *currentLanguageCode = [NSLocale componentsFromLocaleIdentifier:currentLanguage][NSLocaleLanguageCode]; + if ((currentLanguageCode != nil) && [nonSpelledOutLanguages containsObject:currentLanguageCode]) { + formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull; + } + + formatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond; + formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll; + return formatter; +} + +@end + + +@implementation ORKOrderedTask (ORKPredefinedActiveTask) + +#pragma mark - AmslerGridTask + +NSString *const ORKAmslerGridStepLeftIdentifier = @"amsler.grid.left"; +NSString *const ORKAmslerGridStepRightIdentifier = @"amsler.grid.right"; +NSString *const ORKAmslerGridCalibrationLeftIdentifier = @"amsler.grid.calibration.left"; +NSString *const ORKAmslerGridCalibrationRightIdentifier = @"amsler.grid.calibration.Right"; + ++ (ORKOrderedTask *)amslerGridTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + UIColor *tintColor = [[[UIApplication sharedApplication] delegate] window].tintColor ? : ORKColor(ORKBlueHighlightColorKey); + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"AMSLER_GRID_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"AMSLER_GRID_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + ORKStepArrayAddStep(steps, step); + } + { + + + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"AMSLER_GRID_TITLE", nil); + step.text = ORKLocalizedString(@"AMSLER_GRID_INSTRUCTION_TEXT", nil); + + NSString *leftEye = ORKLocalizedString(@"AMSLER_GRID_LEFT_EYE", nil); + NSString *detailText = [@"\n" stringByAppendingString:[NSString stringWithFormat:ORKLocalizedString(@"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT", nil), leftEye]]; + + NSMutableAttributedString *attributedDetailText = [[NSMutableAttributedString alloc] initWithString:detailText]; + [attributedDetailText addAttribute:NSForegroundColorAttributeName + value:tintColor + range:[detailText rangeOfString:leftEye]]; + step.attributedDetailText = attributedDetailText; + + step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + } + { + ORKAmslerGridStep *step = [[ORKAmslerGridStep alloc] initWithIdentifier:ORKAmslerGridStepLeftIdentifier]; + step.eyeSide = ORKAmslerGridEyeSideLeft; + ORKStepArrayAddStep(steps, step); + } + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + step.title = ORKLocalizedString(@"AMSLER_GRID_TITLE", nil); + step.text = ORKLocalizedString(@"AMSLER_GRID_INSTRUCTION_TEXT", nil); + NSString *rightEye = ORKLocalizedString(@"AMSLER_GRID_RIGHT_EYE", nil); + NSString *detailText = [@"\n" stringByAppendingString:[NSString stringWithFormat:ORKLocalizedString(@"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT", nil), rightEye]]; + + NSMutableAttributedString *attributedDetailText = [[NSMutableAttributedString alloc] initWithString:detailText]; + [attributedDetailText addAttribute:NSForegroundColorAttributeName + value:tintColor + range:[detailText rangeOfString:rightEye]]; + step.attributedDetailText = attributedDetailText; + step.image = [UIImage imageNamed:@"amslerGrid" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + { + ORKAmslerGridStep *step = [[ORKAmslerGridStep alloc] initWithIdentifier:ORKAmslerGridStepRightIdentifier]; + step.eyeSide = ORKAmslerGridEyeSideRight; + ORKStepArrayAddStep(steps, step); + } + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKCompletionStep *completionStep = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, completionStep); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +#pragma mark - holePegTestTask + +NSString *const ORKHolePegTestDominantPlaceStepIdentifier = @"hole.peg.test.dominant.place"; +NSString *const ORKHolePegTestDominantRemoveStepIdentifier = @"hole.peg.test.dominant.remove"; +NSString *const ORKHolePegTestNonDominantPlaceStepIdentifier = @"hole.peg.test.non.dominant.place"; +NSString *const ORKHolePegTestNonDominantRemoveStepIdentifier = @"hole.peg.test.non.dominant.remove"; + ++ (ORKNavigableOrderedTask *)holePegTestTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + dominantHand:(ORKBodySagittal)dominantHand + numberOfPegs:(int)numberOfPegs + threshold:(double)threshold + rotated:(BOOL)rotated + timeLimit:(NSTimeInterval)timeLimit + options:(ORKPredefinedTaskOption)options { + + NSMutableArray *steps = [NSMutableArray array]; + BOOL dominantHandLeft = (dominantHand == ORKBodySagittalLeft); + NSTimeInterval stepDuration = (timeLimit == 0) ? CGFLOAT_MAX : timeLimit; + NSString *pegs = [NSNumberFormatter localizedStringFromNumber:@(numberOfPegs) numberStyle:NSNumberFormatterNoStyle]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = intendedUseDescription; + step.detailText = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_INTRO_TEXT_%@", nil), pegs]; + step.image = [UIImage imageNamed:@"phoneholepeg" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = dominantHandLeft ? [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@", nil), pegs, pegs] : [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@", nil), pegs, pegs]; + step.detailText = ORKLocalizedString(@"HOLE_PEG_TEST_CALL_TO_ACTION", nil); + UIImage *image1 = [UIImage imageNamed:@"holepegtest1" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *image2 = [UIImage imageNamed:@"holepegtest2" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *image3 = [UIImage imageNamed:@"holepegtest3" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *image4 = [UIImage imageNamed:@"holepegtest4" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *image5 = [UIImage imageNamed:@"holepegtest5" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *image6 = [UIImage imageNamed:@"holepegtest6" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.image = [UIImage animatedImageWithImages:@[image1, image2, image3, image4, image5, image6] duration:4]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + { + { + ORKHolePegTestPlaceStep *step = [[ORKHolePegTestPlaceStep alloc] initWithIdentifier:ORKHolePegTestDominantPlaceStepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = [dominantHandLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.movingDirection = dominantHand; + step.dominantHandTested = YES; + step.numberOfPegs = numberOfPegs; + step.threshold = threshold; + step.rotated = rotated; + step.shouldTintImages = YES; + step.stepDuration = stepDuration; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKHolePegTestRemoveStep *step = [[ORKHolePegTestRemoveStep alloc] initWithIdentifier:ORKHolePegTestDominantRemoveStepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = [dominantHandLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.movingDirection = (dominantHand == ORKBodySagittalLeft) ? ORKBodySagittalRight : ORKBodySagittalLeft; + step.dominantHandTested = YES; + step.numberOfPegs = numberOfPegs; + step.threshold = threshold; + step.shouldTintImages = YES; + step.stepDuration = stepDuration; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKHolePegTestPlaceStep *step = [[ORKHolePegTestPlaceStep alloc] initWithIdentifier:ORKHolePegTestNonDominantPlaceStepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = [dominantHandLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.movingDirection = (dominantHand == ORKBodySagittalLeft) ? ORKBodySagittalRight : ORKBodySagittalLeft; + step.dominantHandTested = NO; + step.numberOfPegs = numberOfPegs; + step.threshold = threshold; + step.rotated = rotated; + step.shouldTintImages = YES; + step.stepDuration = stepDuration; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKHolePegTestRemoveStep *step = [[ORKHolePegTestRemoveStep alloc] initWithIdentifier:ORKHolePegTestNonDominantRemoveStepIdentifier]; + step.title = [[NSString alloc] initWithFormat:ORKLocalizedString(@"HOLE_PEG_TEST_TITLE_%@", nil), pegs]; + step.text = [dominantHandLeft ? ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND", nil) : ORKLocalizedString(@"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"HOLE_PEG_TEST_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.movingDirection = dominantHand; + step.dominantHandTested = NO; + step.numberOfPegs = numberOfPegs; + step.threshold = threshold; + step.shouldTintImages = YES; + step.stepDuration = stepDuration; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKCompletionStep *step = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, step); + } + + + // The task is actually dynamic. The direct navigation rules are used for skipping the peg + // removal steps if the user doesn't succeed in placing all the pegs in the allotted time + // (the rules are removed from `ORKHolePegTestPlaceStepViewController` if she succeeds). + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + ORKStepNavigationRule *navigationRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKHolePegTestNonDominantPlaceStepIdentifier]; + [task setNavigationRule:navigationRule forTriggerStepIdentifier:ORKHolePegTestDominantPlaceStepIdentifier]; + navigationRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKConclusionStepIdentifier]; + [task setNavigationRule:navigationRule forTriggerStepIdentifier:ORKHolePegTestNonDominantPlaceStepIdentifier]; + + return task; +} + + +#pragma mark - twoFingerTappingInterval + +NSString *const ORKTappingStepIdentifier = @"tapping"; + ++ (ORKOrderedTask *)twoFingerTappingIntervalTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + duration:(NSTimeInterval)duration + handOptions:(ORKPredefinedTaskHandOption)handOptions + options:(ORKPredefinedTaskOption)options { + + NSString *durationString = [ORKDurationStringFormatter() stringFromTimeInterval:duration]; + + NSMutableArray *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TAPPING_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TAPPING_INTRO_TEXT", nil); + + NSString *imageName = @"phonetapping"; + if (![[NSLocale preferredLanguages].firstObject hasPrefix:@"en"]) { + imageName = [imageName stringByAppendingString:@"_notap"]; + } + step.image = [UIImage imageNamed:imageName inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + } + + // Setup which hand to start with and how many hands to add based on the handOptions parameter + // Hand order is randomly determined. + NSUInteger handCount = ((handOptions & ORKPredefinedTaskHandOptionBoth) == ORKPredefinedTaskHandOptionBoth) ? 2 : 1; + BOOL undefinedHand = (handOptions == 0); + BOOL rightHand; + switch (handOptions) { + case ORKPredefinedTaskHandOptionLeft: + rightHand = NO; break; + case ORKPredefinedTaskHandOptionRight: + case ORKPredefinedTaskHandOptionUnspecified: + rightHand = YES; break; + default: + rightHand = (arc4random()%2 == 0); break; + } + + for (NSUInteger hand = 1; hand <= handCount; hand++) { + + NSString * (^appendIdentifier) (NSString *) = ^ (NSString * stepIdentifier) { + if (undefinedHand) { + return stepIdentifier; + } else { + NSString *handIdentifier = rightHand ? ORKActiveTaskRightHandIdentifier : ORKActiveTaskLeftHandIdentifier; + return [NSString stringWithFormat:@"%@.%@", stepIdentifier, handIdentifier]; + } + }; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:appendIdentifier(ORKInstruction1StepIdentifier)]; + + // Set the title based on the hand + if (undefinedHand) { + step.title = ORKLocalizedString(@"TAPPING_TASK_TITLE", nil); + } else if (rightHand) { + step.title = ORKLocalizedString(@"TAPPING_TASK_TITLE_RIGHT", nil); + } else { + step.title = ORKLocalizedString(@"TAPPING_TASK_TITLE_LEFT", nil); + } + + // Set the instructions for the tapping test screen that is displayed prior to each hand test + NSString *restText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_REST_PHONE", nil); + NSString *tappingTextFormat = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_FORMAT", nil); + NSString *tappingText = [NSString localizedStringWithFormat:tappingTextFormat, durationString]; + NSString *handText = nil; + + if (hand == 1) { + if (undefinedHand) { + handText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_MOST_AFFECTED", nil); + } else if (rightHand) { + handText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_RIGHT_FIRST", nil); + } else { + handText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_LEFT_FIRST", nil); + } + } else { + if (rightHand) { + handText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_RIGHT_SECOND", nil); + } else { + handText = ORKLocalizedString(@"TAPPING_INTRO_TEXT_2_LEFT_SECOND", nil); + } + } + + step.text = [NSString localizedStringWithFormat:@"%@ %@ %@", restText, handText, tappingText]; + + // Continue button will be different from first hand and second hand + if (hand == 1) { + step.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + step.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + // Set the image + UIImage *im1 = [UIImage imageNamed:@"handtapping01" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *im2 = [UIImage imageNamed:@"handtapping02" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *imageAnimation = [UIImage animatedImageWithImages:@[im1, im2] duration:1]; + + if (rightHand || undefinedHand) { + step.image = imageAnimation; + } else { + step.image = [imageAnimation ork_flippedImage:UIImageOrientationUpMirrored]; + } + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + // TAPPING STEP + { + NSMutableArray *recorderConfigurations = [NSMutableArray arrayWithCapacity:5]; + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + + ORKTappingIntervalStep *step = [[ORKTappingIntervalStep alloc] initWithIdentifier:appendIdentifier(ORKTappingStepIdentifier)]; + step.title = ORKLocalizedString(@"TAPPING_TASK_TITLE", nil); + + if (undefinedHand) { + step.text = ORKLocalizedString(@"TAPPING_INSTRUCTION", nil); + } else if (rightHand) { + step.text = ORKLocalizedString(@"TAPPING_INSTRUCTION_RIGHT", nil); + } else { + step.text = ORKLocalizedString(@"TAPPING_INSTRUCTION_LEFT", nil); + } + if (UIAccessibilityIsVoiceOverRunning()) { + step.text = [NSString stringWithFormat:ORKLocalizedString(@"AX_TAPPING_INSTRUCTION_VOICEOVER", nil), step.text]; + } + step.stepDuration = duration; + step.shouldContinueOnFinish = YES; + step.recorderConfigurations = recorderConfigurations; + step.optional = (handCount == 2); + + ORKStepArrayAddStep(steps, step); + } + + // Flip to the other hand (ignored if handCount == 1) + rightHand = !rightHand; + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:[steps copy]]; + + return task; +} + + +#pragma mark - audioTask + +NSString *const ORKAudioStepIdentifier = @"audio"; +NSString *const ORKAudioTooLoudStepIdentifier = @"audio.tooloud"; + ++ (ORKNavigableOrderedTask *)audioTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechInstruction:(nullable NSString *)speechInstruction + shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction + duration:(NSTimeInterval)duration + recordingSettings:(nullable NSDictionary *)recordingSettings + checkAudioLevel:(BOOL)checkAudioLevel + options:(ORKPredefinedTaskOption)options { + + recordingSettings = recordingSettings ? : @{ AVFormatIDKey : @(kAudioFormatAppleLossless), + AVNumberOfChannelsKey : @(2), + AVSampleRateKey: @(44100.0) }; + + if (options & ORKPredefinedTaskOptionExcludeAudio) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Audio collection cannot be excluded from audio task" userInfo:nil]; + } + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"AUDIO_INTENDED_USE", nil); + step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil); + step.text = speechInstruction ? : ORKLocalizedString(@"AUDIO_INTRO_TEXT", nil); + step.detailText = ORKLocalizedString(@"AUDIO_CALL_TO_ACTION", nil); + step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.stepDuration = 5.0; + step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil); + + // Collect audio during the countdown step too, to provide a baseline. + step.recorderConfigurations = @[[[ORKAudioRecorderConfiguration alloc] initWithIdentifier:ORKAudioRecorderIdentifier + recorderSettings:recordingSettings]]; + + // If checking the sound level then add text indicating that's what is happening + if (checkAudioLevel) { + step.text = ORKLocalizedString(@"AUDIO_LEVEL_CHECK_LABEL", nil); + } + + ORKStepArrayAddStep(steps, step); + } + + if (checkAudioLevel) { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKAudioTooLoudStepIdentifier]; + step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"AUDIO_TOO_LOUD_MESSAGE", nil); + step.detailText = ORKLocalizedString(@"AUDIO_TOO_LOUD_ACTION_NEXT", nil); + + ORKStepArrayAddStep(steps, step); + } + + { + ORKAudioStep *step = [[ORKAudioStep alloc] initWithIdentifier:ORKAudioStepIdentifier]; + step.title = ORKLocalizedString(@"AUDIO_TASK_TITLE", nil); + step.text = shortSpeechInstruction ? : ORKLocalizedString(@"AUDIO_INSTRUCTION", nil); + step.recorderConfigurations = @[[[ORKAudioRecorderConfiguration alloc] initWithIdentifier:ORKAudioRecorderIdentifier + recorderSettings:recordingSettings]]; + step.stepDuration = duration; + step.shouldContinueOnFinish = YES; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + if (checkAudioLevel) { + + // Add rules to check for audio and fail, looping back to the countdown step if required + ORKAudioLevelNavigationRule *audioRule = [[ORKAudioLevelNavigationRule alloc] initWithAudioLevelStepIdentifier:ORKCountdownStepIdentifier destinationStepIdentifier:ORKAudioStepIdentifier recordingSettings:recordingSettings]; + ORKDirectStepNavigationRule *loopRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKCountdownStepIdentifier]; + + [task setNavigationRule:audioRule forTriggerStepIdentifier:ORKCountdownStepIdentifier]; + [task setNavigationRule:loopRule forTriggerStepIdentifier:ORKAudioTooLoudStepIdentifier]; + } + + return task; +} + + +#pragma mark - fitnessCheckTask + +NSString *const ORKFitnessWalkStepIdentifier = @"fitness.walk"; +NSString *const ORKFitnessRestStepIdentifier = @"fitness.rest"; + ++ (ORKOrderedTask *)fitnessCheckTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + walkDuration:(NSTimeInterval)walkDuration + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options { + + NSDateComponentsFormatter *formatter = [self textTimeFormatter]; + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"FITNESS_TASK_TITLE", nil); + step.text = intendedUseDescription ? : [NSString localizedStringWithFormat:ORKLocalizedString(@"FITNESS_INTRO_TEXT_FORMAT", nil), [formatter stringFromTimeInterval:walkDuration]]; + step.image = [UIImage imageNamed:@"heartbeat" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"FITNESS_TASK_TITLE", nil); + step.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"FITNESS_INTRO_2_TEXT_FORMAT", nil), [formatter stringFromTimeInterval:walkDuration], [formatter stringFromTimeInterval:restDuration]]; + step.image = [UIImage imageNamed:@"walkingman" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"FITNESS_TASK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + + HKUnit *bpmUnit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]; + HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; + { + if (walkDuration > 0) { + NSMutableArray *recorderConfigurations = [NSMutableArray arrayWithCapacity:5]; + if (!(ORKPredefinedTaskOptionExcludePedometer & options)) { + [recorderConfigurations addObject:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:ORKPedometerRecorderIdentifier]]; + } + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeLocation & options)) { + [recorderConfigurations addObject:[[ORKLocationRecorderConfiguration alloc] initWithIdentifier:ORKLocationRecorderIdentifier]]; + } + if (!(ORKPredefinedTaskOptionExcludeHeartRate & options)) { + [recorderConfigurations addObject:[[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:ORKHeartRateRecorderIdentifier + healthQuantityType:heartRateType unit:bpmUnit]]; + } + ORKFitnessStep *fitnessStep = [[ORKFitnessStep alloc] initWithIdentifier:ORKFitnessWalkStepIdentifier]; + fitnessStep.stepDuration = walkDuration; + fitnessStep.title = ORKLocalizedString(@"FITNESS_TASK_TITLE", nil); + fitnessStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"FITNESS_WALK_INSTRUCTION_FORMAT", nil), [formatter stringFromTimeInterval:walkDuration]]; + fitnessStep.spokenInstruction = fitnessStep.text; + fitnessStep.recorderConfigurations = recorderConfigurations; + fitnessStep.shouldContinueOnFinish = YES; + fitnessStep.optional = NO; + fitnessStep.shouldStartTimerAutomatically = YES; + fitnessStep.shouldTintImages = YES; + fitnessStep.image = [UIImage imageNamed:@"walkingman" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + fitnessStep.imageContentMode = UIViewContentModeCenter; + fitnessStep.shouldVibrateOnStart = YES; + fitnessStep.shouldPlaySoundOnStart = YES; + + ORKStepArrayAddStep(steps, fitnessStep); + } + + if (restDuration > 0) { + NSMutableArray *recorderConfigurations = [NSMutableArray arrayWithCapacity:5]; + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeHeartRate & options)) { + [recorderConfigurations addObject:[[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:ORKHeartRateRecorderIdentifier + healthQuantityType:heartRateType unit:bpmUnit]]; + } + + ORKFitnessStep *stillStep = [[ORKFitnessStep alloc] initWithIdentifier:ORKFitnessRestStepIdentifier]; + stillStep.stepDuration = restDuration; + stillStep.title = ORKLocalizedString(@"FITNESS_TASK_TITLE", nil); + stillStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"FITNESS_SIT_INSTRUCTION_FORMAT", nil), [formatter stringFromTimeInterval:restDuration]]; + stillStep.spokenInstruction = stillStep.text; + stillStep.recorderConfigurations = recorderConfigurations; + stillStep.shouldContinueOnFinish = YES; + stillStep.optional = NO; + stillStep.shouldStartTimerAutomatically = YES; + stillStep.shouldTintImages = YES; + stillStep.image = [UIImage imageNamed:@"sittingman" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + stillStep.imageContentMode = UIViewContentModeCenter; + stillStep.shouldVibrateOnStart = YES; + stillStep.shouldPlaySoundOnStart = YES; + stillStep.shouldPlaySoundOnFinish = YES; + stillStep.shouldVibrateOnFinish = YES; + + ORKStepArrayAddStep(steps, stillStep); + } + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + + +#pragma mark - shortWalkTask + +NSString *const ORKShortWalkOutboundStepIdentifier = @"walking.outbound"; +NSString *const ORKShortWalkReturnStepIdentifier = @"walking.return"; +NSString *const ORKShortWalkRestStepIdentifier = @"walking.rest"; + ++ (ORKOrderedTask *)shortWalkTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + numberOfStepsPerLeg:(NSInteger)numberOfStepsPerLeg + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options { + + NSDateComponentsFormatter *formatter = [self textTimeFormatter]; + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"WALK_INTRO_TEXT", nil); + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_INTRO_2_TEXT_%ld", nil),numberOfStepsPerLeg]; + step.detailText = ORKLocalizedString(@"WALK_INTRO_2_DETAIL", nil); + step.image = [UIImage imageNamed:@"pocket" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + + { + { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(ORKPredefinedTaskOptionExcludePedometer & options)) { + [recorderConfigurations addObject:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:ORKPedometerRecorderIdentifier]]; + } + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + + ORKWalkingTaskStep *walkingStep = [[ORKWalkingTaskStep alloc] initWithIdentifier:ORKShortWalkOutboundStepIdentifier]; + walkingStep.numberOfStepsPerLeg = numberOfStepsPerLeg; + walkingStep.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + walkingStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_OUTBOUND_INSTRUCTION_FORMAT", nil), (long long)numberOfStepsPerLeg]; + walkingStep.spokenInstruction = walkingStep.text; + walkingStep.recorderConfigurations = recorderConfigurations; + walkingStep.shouldContinueOnFinish = YES; + walkingStep.optional = NO; + walkingStep.shouldStartTimerAutomatically = YES; + walkingStep.stepDuration = numberOfStepsPerLeg * 1.5; // fallback duration in case no step count + walkingStep.shouldVibrateOnStart = YES; + walkingStep.shouldPlaySoundOnStart = YES; + + ORKStepArrayAddStep(steps, walkingStep); + } + + { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(ORKPredefinedTaskOptionExcludePedometer & options)) { + [recorderConfigurations addObject:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:ORKPedometerRecorderIdentifier]]; + } + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + + ORKWalkingTaskStep *walkingStep = [[ORKWalkingTaskStep alloc] initWithIdentifier:ORKShortWalkReturnStepIdentifier]; + walkingStep.numberOfStepsPerLeg = numberOfStepsPerLeg; + walkingStep.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + walkingStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_RETURN_INSTRUCTION_FORMAT", nil), (long long)numberOfStepsPerLeg]; + walkingStep.spokenInstruction = walkingStep.text; + walkingStep.recorderConfigurations = recorderConfigurations; + walkingStep.shouldContinueOnFinish = YES; + walkingStep.shouldStartTimerAutomatically = YES; + walkingStep.optional = NO; + walkingStep.stepDuration = numberOfStepsPerLeg * 1.5; // fallback duration in case no step count + walkingStep.shouldVibrateOnStart = YES; + walkingStep.shouldPlaySoundOnStart = YES; + + ORKStepArrayAddStep(steps, walkingStep); + } + + if (restDuration > 0) { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + + ORKFitnessStep *activeStep = [[ORKFitnessStep alloc] initWithIdentifier:ORKShortWalkRestStepIdentifier]; + activeStep.recorderConfigurations = recorderConfigurations; + NSString *durationString = [formatter stringFromTimeInterval:restDuration]; + activeStep.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + activeStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_STAND_INSTRUCTION_FORMAT", nil), durationString]; + activeStep.spokenInstruction = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_STAND_VOICE_INSTRUCTION_FORMAT", nil), durationString]; + activeStep.shouldStartTimerAutomatically = YES; + activeStep.stepDuration = restDuration; + activeStep.shouldContinueOnFinish = YES; + activeStep.optional = NO; + activeStep.shouldVibrateOnStart = YES; + activeStep.shouldPlaySoundOnStart = YES; + activeStep.shouldVibrateOnFinish = YES; + activeStep.shouldPlaySoundOnFinish = YES; + + ORKStepArrayAddStep(steps, activeStep); + } + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - walkBackAndForthTask + ++ (ORKOrderedTask *)walkBackAndForthTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + walkDuration:(NSTimeInterval)walkDuration + restDuration:(NSTimeInterval)restDuration + options:(ORKPredefinedTaskOption)options { + + NSDateComponentsFormatter *formatter = [self textTimeFormatter]; + formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull; + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"WALK_INTRO_TEXT", nil); + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION", nil); + step.detailText = ORKLocalizedString(@"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION", nil); + step.image = [UIImage imageNamed:@"pocket" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + + { + { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(ORKPredefinedTaskOptionExcludePedometer & options)) { + [recorderConfigurations addObject:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:ORKPedometerRecorderIdentifier]]; + } + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + + ORKWalkingTaskStep *walkingStep = [[ORKWalkingTaskStep alloc] initWithIdentifier:ORKShortWalkOutboundStepIdentifier]; + walkingStep.numberOfStepsPerLeg = 1000; // Set the number of steps very high so it is ignored + NSString *walkingDurationString = [formatter stringFromTimeInterval:walkDuration]; + walkingStep.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + + walkingStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT", nil), walkingDurationString]; + walkingStep.spokenInstruction = walkingStep.text; + walkingStep.recorderConfigurations = recorderConfigurations; + walkingStep.shouldContinueOnFinish = YES; + walkingStep.optional = NO; + walkingStep.shouldStartTimerAutomatically = YES; + walkingStep.stepDuration = walkDuration; // Set the walking duration to the step duration + walkingStep.shouldVibrateOnStart = YES; + walkingStep.shouldPlaySoundOnStart = YES; + walkingStep.shouldSpeakRemainingTimeAtHalfway = (walkDuration > 20); + + ORKStepArrayAddStep(steps, walkingStep); + } + + if (restDuration > 0) { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(ORKPredefinedTaskOptionExcludeAccelerometer & options)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(ORKPredefinedTaskOptionExcludeDeviceMotion & options)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + + ORKFitnessStep *activeStep = [[ORKFitnessStep alloc] initWithIdentifier:ORKShortWalkRestStepIdentifier]; + activeStep.recorderConfigurations = recorderConfigurations; + NSString *durationString = [formatter stringFromTimeInterval:restDuration]; + activeStep.title = ORKLocalizedString(@"WALK_TASK_TITLE", nil); + activeStep.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT", nil), durationString]; + activeStep.spokenInstruction = activeStep.text; + activeStep.shouldStartTimerAutomatically = YES; + activeStep.stepDuration = restDuration; + activeStep.shouldContinueOnFinish = YES; + activeStep.optional = NO; + activeStep.shouldVibrateOnStart = YES; + activeStep.shouldPlaySoundOnStart = YES; + activeStep.shouldVibrateOnFinish = YES; + activeStep.shouldPlaySoundOnFinish = YES; + activeStep.finishedSpokenInstruction = ORKLocalizedString(@"WALK_BACK_AND_FORTH_FINISHED_VOICE", nil); + activeStep.shouldSpeakRemainingTimeAtHalfway = (restDuration > 20); + + ORKStepArrayAddStep(steps, activeStep); + } + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - kneeRangeOfMotionTask + +NSString *const ORKKneeRangeOfMotionStepIdentifier = @"knee.range.of.motion"; + ++ (ORKOrderedTask *)kneeRangeOfMotionTaskWithIdentifier:(NSString *)identifier + limbOption:(ORKPredefinedTaskLimbOption)limbOption + intendedUseDescription:(NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + NSString *limbType = ORKLocalizedString(@"LIMB_RIGHT", nil); + UIImage *kneeStartImage = [UIImage imageNamed:@"knee_start_right" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *kneeMaximumImage = [UIImage imageNamed:@"knee_maximum_right" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + + if (limbOption == ORKPredefinedTaskLimbOptionLeft) { + limbType = ORKLocalizedString(@"LIMB_LEFT", nil); + + kneeStartImage = [UIImage imageNamed:@"knee_start_left" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + kneeMaximumImage = [UIImage imageNamed:@"knee_maximum_left" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + } + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + ORKInstructionStep *instructionStep0 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + instructionStep0.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep0.text = intendedUseDescription; + instructionStep0.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT", nil); + instructionStep0.shouldTintImages = YES; + instructionStep0.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, instructionStep0); + + ORKInstructionStep *instructionStep1 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + instructionStep1.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep1.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT", nil); + ORKStepArrayAddStep(steps, instructionStep1); + + ORKInstructionStep *instructionStep2 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + instructionStep2.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep2.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TITLE_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TITLE_RIGHT", nil); + + instructionStep2.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT", nil); + instructionStep2.image = kneeStartImage; + instructionStep2.imageContentMode = UIViewContentModeCenter; + instructionStep2.shouldTintImages = YES; + ORKStepArrayAddStep(steps, instructionStep2); + + ORKInstructionStep *instructionStep3 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier]; + instructionStep3.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep3.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT", nil); + + instructionStep3.image = kneeMaximumImage; + instructionStep3.imageContentMode = UIViewContentModeCenter; + instructionStep3.shouldTintImages = YES; + ORKStepArrayAddStep(steps, instructionStep3); + } + NSString *instructionText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT", nil) : ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT", nil); + ORKTouchAnywhereStep *touchAnywhereStep = [[ORKTouchAnywhereStep alloc] initWithIdentifier:ORKTouchAnywhereStepIdentifier instructionText:instructionText]; + touchAnywhereStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + ORKStepArrayAddStep(steps, touchAnywhereStep); + + touchAnywhereStep.spokenInstruction = touchAnywhereStep.text; + + ORKDeviceMotionRecorderConfiguration *deviceMotionRecorderConfig = [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier frequency:100]; + + ORKRangeOfMotionStep *kneeRangeOfMotionStep = [[ORKRangeOfMotionStep alloc] initWithIdentifier:ORKKneeRangeOfMotionStepIdentifier limbOption:limbOption]; + kneeRangeOfMotionStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + kneeRangeOfMotionStep.text = ([limbType isEqualToString: ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT", nil) : + ORKLocalizedString(@"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT", nil); + + kneeRangeOfMotionStep.spokenInstruction = kneeRangeOfMotionStep.text; + kneeRangeOfMotionStep.recorderConfigurations = @[deviceMotionRecorderConfig]; + kneeRangeOfMotionStep.optional = NO; + + ORKStepArrayAddStep(steps, kneeRangeOfMotionStep); + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKCompletionStep *completionStep = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, completionStep); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - shoulderRangeOfMotionTask + +NSString *const ORKShoulderRangeOfMotionStepIdentifier = @"shoulder.range.of.motion"; + ++ (ORKOrderedTask *)shoulderRangeOfMotionTaskWithIdentifier:(NSString *)identifier + limbOption:(ORKPredefinedTaskLimbOption)limbOption + intendedUseDescription:(NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + NSString *limbType = ORKLocalizedString(@"LIMB_RIGHT", nil); + UIImage *shoulderStartImage = [UIImage imageNamed:@"shoulder_start_right" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + UIImage *shoulderMaximumImage = [UIImage imageNamed:@"shoulder_maximum_right" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + + if (limbOption == ORKPredefinedTaskLimbOptionLeft) { + limbType = ORKLocalizedString(@"LIMB_LEFT", nil); + shoulderStartImage = [UIImage imageNamed:@"shoulder_start_left" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + shoulderMaximumImage = [UIImage imageNamed:@"shoulder_maximum_left" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + } + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + ORKInstructionStep *instructionStep0 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + instructionStep0.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep0.text = intendedUseDescription; + instructionStep0.detailText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT", nil); + instructionStep0.shouldTintImages = YES; + instructionStep0.imageContentMode = UIViewContentModeCenter; + ORKStepArrayAddStep(steps, instructionStep0); + + ORKInstructionStep *instructionStep1 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + instructionStep1.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep1.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT", nil); + ORKStepArrayAddStep(steps, instructionStep1); + + ORKInstructionStep *instructionStep2 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + instructionStep2.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep2.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT", nil); + instructionStep2.image = shoulderStartImage; + instructionStep2.imageContentMode = UIViewContentModeCenter; + instructionStep2.shouldTintImages = YES; + ORKStepArrayAddStep(steps, instructionStep2); + + ORKInstructionStep *instructionStep3 = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier]; + instructionStep3.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + instructionStep3.text = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT", nil); + instructionStep3.image = shoulderMaximumImage; + instructionStep3.imageContentMode = UIViewContentModeCenter; + instructionStep3.shouldTintImages = YES; + ORKStepArrayAddStep(steps, instructionStep3); + } + + NSString *instructionText = ([limbType isEqualToString:ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT", nil) : ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT", nil); + ORKTouchAnywhereStep *touchAnywhereStep = [[ORKTouchAnywhereStep alloc] initWithIdentifier:ORKTouchAnywhereStepIdentifier instructionText:instructionText]; + touchAnywhereStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + ORKStepArrayAddStep(steps, touchAnywhereStep); + + touchAnywhereStep.spokenInstruction = touchAnywhereStep.text; + + ORKDeviceMotionRecorderConfiguration *deviceMotionRecorderConfig = [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier frequency:100]; + + ORKShoulderRangeOfMotionStep *shoulderRangeOfMotionStep = [[ORKShoulderRangeOfMotionStep alloc] initWithIdentifier:ORKShoulderRangeOfMotionStepIdentifier limbOption:limbOption]; + shoulderRangeOfMotionStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + shoulderRangeOfMotionStep.text = ([limbType isEqualToString: ORKLocalizedString(@"LIMB_LEFT", nil)])? ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT", nil) : + ORKLocalizedString(@"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT", nil); + + shoulderRangeOfMotionStep.spokenInstruction = shoulderRangeOfMotionStep.text; + + shoulderRangeOfMotionStep.recorderConfigurations = @[deviceMotionRecorderConfig]; + shoulderRangeOfMotionStep.optional = NO; + + ORKStepArrayAddStep(steps, shoulderRangeOfMotionStep); + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKCompletionStep *completionStep = [self makeCompletionStep]; + completionStep.title = ORKLocalizedString(@"RANGE_OF_MOTION_TITLE", nil); + ORKStepArrayAddStep(steps, completionStep); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - spatialSpanMemoryTask + +NSString *const ORKSpatialSpanMemoryStepIdentifier = @"cognitive.memory.spatialspan"; + ++ (ORKOrderedTask *)spatialSpanMemoryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(NSString *)intendedUseDescription + initialSpan:(NSInteger)initialSpan + minimumSpan:(NSInteger)minimumSpan + maximumSpan:(NSInteger)maximumSpan + playSpeed:(NSTimeInterval)playSpeed + maximumTests:(NSInteger)maximumTests + maximumConsecutiveFailures:(NSInteger)maximumConsecutiveFailures + customTargetImage:(UIImage *)customTargetImage + customTargetPluralName:(NSString *)customTargetPluralName + requireReversal:(BOOL)requireReversal + options:(ORKPredefinedTaskOption)options { + + NSString *targetPluralName = customTargetPluralName ? : ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TARGET_PLURAL", nil); + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = [NSString localizedStringWithFormat:ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@", nil),targetPluralName]; + + step.image = [UIImage imageNamed:@"memory" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TITLE", nil); + step.text = [NSString localizedStringWithFormat:requireReversal ? ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@", nil) : ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@", nil), targetPluralName, targetPluralName]; + step.detailText = ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION", nil); + + if (!customTargetImage) { + step.image = [UIImage imageNamed:@"memory" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + } else { + step.image = customTargetImage; + } + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKSpatialSpanMemoryStep *step = [[ORKSpatialSpanMemoryStep alloc] initWithIdentifier:ORKSpatialSpanMemoryStepIdentifier]; + step.title = ORKLocalizedString(@"SPATIAL_SPAN_MEMORY_TITLE", nil); + step.text = nil; + + step.initialSpan = initialSpan; + step.minimumSpan = minimumSpan; + step.maximumSpan = maximumSpan; + step.playSpeed = playSpeed; + step.maximumTests = maximumTests; + step.maximumConsecutiveFailures = maximumConsecutiveFailures; + step.customTargetImage = customTargetImage; + step.customTargetPluralName = customTargetPluralName; + step.requireReversal = requireReversal; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - speechRecognitionTask + +NSString *const ORKSpeechRecognitionStepIdentifier = @"speech.recognition"; + ++ (ORKOrderedTask *)speechRecognitionTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechRecognizerLocale:(ORKSpeechRecognizerLocale)speechRecognizerLocale + speechRecognitionImage:(nullable UIImage *)speechRecognitionImage + speechRecognitionText:(nullable NSString *)speechRecognitionText + shouldHideTranscript:(BOOL)shouldHideTranscript + allowsEdittingTranscript:(BOOL)allowsEdittingTranscript + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"SPEECH_RECOGNITION_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"phonewaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + step.imageContentMode = UIViewContentModeCenter; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"SPEECH_RECOGNITION_INTRO_2_TEXT", nil); + step.detailText = ORKLocalizedString(@"SPEECH_RECOGNITION_CALL_TO_ACTION", nil); + step.image = [UIImage imageNamed:@"phonewavesspeech" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + ORKSpeechRecognitionStep *step = [[ORKSpeechRecognitionStep alloc] initWithIdentifier: ORKSpeechRecognitionStepIdentifier image:speechRecognitionImage text:speechRecognitionText]; + ORKStreamingAudioRecorderConfiguration *config = [[ORKStreamingAudioRecorderConfiguration alloc] initWithIdentifier: ORKStreamingAudioRecorderIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_TASK_TITLE", nil); + step.shouldHideTranscript = shouldHideTranscript; + step.recorderConfigurations = @[config]; + step.speechRecognizerLocale = speechRecognizerLocale; + step.shouldContinueOnFinish = NO; + + ORKStepArrayAddStep(steps, step); + + if (allowsEdittingTranscript) { + ORKTextAnswerFormat *answerFormat = [ORKTextAnswerFormat new]; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.multipleLines = YES; + answerFormat.maximumLength = 280; + ORKQuestionStep *editTranscriptStep = [ORKQuestionStep questionStepWithIdentifier:ORKEditSpeechTranscript0StepIdentifier + title:ORKLocalizedString(@"SPEECH_RECOGNITION_QUESTION_TITLE", nil) + question:nil + answer:answerFormat]; + editTranscriptStep.text = ORKLocalizedString(@"SPEECH_RECOGNITION_QUESTION_TEXT", nil); + ORKStepArrayAddStep(steps, editTranscriptStep); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *completionStep = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, completionStep); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +#pragma mark - speechInNoiseTask + +NSString *const ORKSpeechInNoiseStep0Identifier = @"speech.in.noise0"; +NSString *const ORKSpeechInNoiseStep1Identifier = @"speech.in.noise1"; +NSString *const ORKSpeechInNoiseStep2Identifier = @"speech.in.noise2"; + ++ (ORKOrderedTask *)speechInNoiseTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_IN_NOISE_TITLE", nil); + step.detailText = intendedUseDescription; + step.text = intendedUseDescription ? : ORKLocalizedString(@"SPEECH_IN_NOISE_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"speechInNoise" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_IN_NOISE_TITLE", nil); + step.detailText = ORKLocalizedString(@"SPEECH_IN_NOISE_DETAIL_TEXT", nil); + step.image = [UIImage imageNamed:@"speechInNoise" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + // SNR ranging from 18 dB to 0 dB with a 3 dB step + NSMutableArray *gainValues = [NSMutableArray new]; + [gainValues addObject:[NSNumber numberWithDouble:0.18]]; + [gainValues addObject:[NSNumber numberWithDouble:0.25]]; + [gainValues addObject:[NSNumber numberWithDouble:0.36]]; + [gainValues addObject:[NSNumber numberWithDouble:0.51]]; + [gainValues addObject:[NSNumber numberWithDouble:0.73]]; + [gainValues addObject:[NSNumber numberWithDouble:1.03]]; + [gainValues addObject:[NSNumber numberWithDouble:1.46]]; + + + { + ORKSpeechInNoiseStep *step = [[ORKSpeechInNoiseStep alloc] initWithIdentifier:ORKSpeechInNoiseStep1Identifier]; + step.speechFileNameWithExtension = @"Sentence1.wav"; + step.gainAppliedToNoise = [gainValues[0] doubleValue]; + step.title = ORKLocalizedString(@"SPEECH_IN_NOISE_STEP_TITLE", nil); + step.text = ORKLocalizedString(@"SPEECH_IN_NOISE_STEP_TEXT", nil); + ORKStepArrayAddStep(steps, step); + } + + { + ORKSpeechRecognitionStep *step = [[ORKSpeechRecognitionStep alloc] initWithIdentifier: ORKSpeechInNoiseStep2Identifier image:nil text:nil]; + ORKStreamingAudioRecorderConfiguration *config = [[ORKStreamingAudioRecorderConfiguration alloc] initWithIdentifier: ORKStreamingAudioRecorderIdentifier]; + step.title = ORKLocalizedString(@"SPEECH_IN_NOISE_SPEAK_TITLE", nil); + step.text = ORKLocalizedString(@"SPEECH_IN_NOISE_SPEAK_TEXT", nil); + step.shouldHideTranscript = YES; + step.recorderConfigurations = @[config]; + step.speechRecognizerLocale = ORKSpeechRecognizerLocaleEnglishUS; + step.shouldContinueOnFinish = NO; + step.optional = YES; + + ORKStepArrayAddStep(steps, step); + } + { + ORKTextAnswerFormat *answerFormat = [ORKTextAnswerFormat new]; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.multipleLines = YES; + answerFormat.maximumLength = 280; + ORKQuestionStep *editTranscriptStep = [ORKQuestionStep questionStepWithIdentifier:ORKEditSpeechTranscript0StepIdentifier + title:ORKLocalizedString(@"SPEECH_RECOGNITION_QUESTION_TITLE", nil) + question:nil + answer:answerFormat]; + editTranscriptStep.text = ORKLocalizedString(@"SPEECH_RECOGNITION_QUESTION_TEXT", nil); + ORKStepArrayAddStep(steps, editTranscriptStep); + } + + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, step); + } + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; + +} + +#pragma mark - stroopTask + +NSString *const ORKStroopStepIdentifier = @"stroop"; + ++ (ORKOrderedTask *)stroopTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + numberOfAttempts:(NSInteger)numberOfAttempts + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"STROOP_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"STROOP_TASK_INTRO1_DETAIL_TEXT", nil); + step.image = [UIImage imageNamed:@"phonestrooplabel" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"STROOP_TASK_TITLE", nil); + step.detailText = ORKLocalizedString(@"STROOP_TASK_INTRO2_DETAIL_TEXT", nil); + step.image = [UIImage imageNamed:@"phonestroopbutton" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"STROOP_TASK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + { + ORKStroopStep *step = [[ORKStroopStep alloc] initWithIdentifier:ORKStroopStepIdentifier]; + step.title = ORKLocalizedString(@"STROOP_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"STROOP_TASK_STEP_TEXT", nil); + step.spokenInstruction = step.text; + step.numberOfAttempts = numberOfAttempts; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - toneAudiometryTask + +NSString *const ORKToneAudiometryPracticeStepIdentifier = @"tone.audiometry.practice"; +NSString *const ORKToneAudiometryStepIdentifier = @"tone.audiometry"; + ++ (ORKOrderedTask *)toneAudiometryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + speechInstruction:(nullable NSString *)speechInstruction + shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction + toneDuration:(NSTimeInterval)toneDuration + options:(ORKPredefinedTaskOption)options { + + if (options & ORKPredefinedTaskOptionExcludeAudio) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Audio collection cannot be excluded from audio task" userInfo:nil]; + } + + NSMutableArray *steps = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TONE_AUDIOMETRY_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TONE_AUDIOMETRY_INTENDED_USE", nil); + step.image = [UIImage imageNamed:@"phonewaves_inverted" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"TONE_AUDIOMETRY_TASK_TITLE", nil); + step.text = speechInstruction ? : ORKLocalizedString(@"TONE_AUDIOMETRY_INTRO_TEXT", nil); + step.detailText = ORKLocalizedString(@"TONE_AUDIOMETRY_CALL_TO_ACTION", nil); + step.image = [UIImage imageNamed:@"phonefrequencywaves" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + NSString *instructionText = shortSpeechInstruction ? : ORKLocalizedString(@"TONE_AUDIOMETRY_INSTRUCTION", nil); + { + ORKToneAudiometryStep *step = [[ORKToneAudiometryStep alloc] initWithIdentifier:ORKToneAudiometryPracticeStepIdentifier]; + step.title = ORKLocalizedString(@"TONE_AUDIOMETRY_TASK_TITLE", nil); + NSString *prepText = speechInstruction ? : ORKLocalizedString(@"TONE_AUDIOMETRY_PREP_TEXT", nil); + if (UIAccessibilityIsVoiceOverRunning()) { + prepText = [NSString stringWithFormat:ORKLocalizedString(@"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER", nil), prepText, instructionText]; + } + step.text = prepText; + step.toneDuration = CGFLOAT_MAX; + step.practiceStep = YES; + ORKStepArrayAddStep(steps, step); + + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"TONE_AUDIOMETRY_TASK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKToneAudiometryStep *step = [[ORKToneAudiometryStep alloc] initWithIdentifier:ORKToneAudiometryStepIdentifier]; + step.title = ORKLocalizedString(@"TONE_AUDIOMETRY_TASK_TITLE", nil); + step.text = instructionText; + step.toneDuration = toneDuration; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +#pragma mark - dBHLToneAudiometryTask + +NSString *const ORKdBHLToneAudiometryStepIdentifier = @"dBHL.tone.audiometry"; +NSString *const ORKdBHLToneAudiometryStep0Identifier = @"dBHL0.tone.audiometry"; +NSString *const ORKdBHLToneAudiometryStep1Identifier = @"dBHL1.tone.audiometry"; +NSString *const ORKdBHLToneAudiometryStep2Identifier = @"dBHL2.tone.audiometry"; +NSString *const ORKdBHLToneAudiometryStep3Identifier = @"dBHL3.tone.audiometry"; + ++ (ORKOrderedTask *)dBHLToneAudiometryTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + options:(ORKPredefinedTaskOption)options { + + if (options & ORKPredefinedTaskOptionExcludeAudio) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Audio collection cannot be excluded from audio task" userInfo:nil]; + } + + NSMutableArray *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_INTRO_TITLE", nil); + step.detailText = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2", nil); + step.image = [UIImage imageNamed:@"audiometry" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + if (@available(iOS 13.0, *)) { + ORKBodyItem * item1 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1", nil) detailText:nil image:[UIImage systemImageNamed:@"ear"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage]; + ORKBodyItem * item2 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2", nil) detailText:nil image:[UIImage systemImageNamed:@"hand.draw.fill"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage]; + ORKBodyItem * item3 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3", nil) detailText:nil image:[UIImage systemImageNamed:@"volume.2.fill"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage]; + ORKBodyItem * item4 = [[ORKBodyItem alloc] initWithHorizontalRule]; + ORKBodyItem * item5 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4", nil) detailText:nil image:[UIImage systemImageNamed:@"stopwatch"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage]; + item5.useSecondaryColor = YES; + ORKBodyItem * item6 = [[ORKBodyItem alloc] initWithText:ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5", nil) detailText:nil image:[UIImage systemImageNamed:@"moon.fill"] learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleImage]; + item6.useSecondaryColor = YES; + step.bodyItems = @[item1, item2, item3, item4, item5, item6]; + } else { + // Fallback on earlier versions + } + + ORKStepArrayAddStep(steps, step); + } + + } + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_INTRO_TEXT", nil); + if (UIAccessibilityIsVoiceOverRunning()) { + step.text = [NSString stringWithFormat:ORKLocalizedString(@"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT", nil), step.text]; + } + step.image = [UIImage imageNamed:@"audiometry" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + } + + { + ORKEnvironmentSPLMeterStep *step = [[ORKEnvironmentSPLMeterStep alloc] initWithIdentifier:@"splMeter"]; + step.requiredContiguousSamples = 5; + step.thresholdValue = 45; + step.title = ORKLocalizedString(@"ENVIRONMENTSPL_TITLE_2", nil); + step.text = ORKLocalizedString(@"ENVIRONMENTSPL_INTRO_TEXT_2", nil); + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR", nil); + ORKStepArrayAddStep(steps, step); + } + + { + ORKdBHLToneAudiometryStep *step = [[ORKdBHLToneAudiometryStep alloc] initWithIdentifier:ORKdBHLToneAudiometryStep1Identifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2", nil); + step.stepDuration = CGFLOAT_MAX; + step.earPreference = ORKAudioChannelLeft; + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR", nil); + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKdBHLToneAudiometryStep *step = [[ORKdBHLToneAudiometryStep alloc] initWithIdentifier:ORKdBHLToneAudiometryStep2Identifier]; + step.title = ORKLocalizedString(@"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2", nil); + step.stepDuration = CGFLOAT_MAX; + step.earPreference = ORKAudioChannelRight; + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + + + +#pragma mark - towerOfHanoiTask + +NSString *const ORKTowerOfHanoiStepIdentifier = @"towerOfHanoi"; + ++ (ORKOrderedTask *)towerOfHanoiTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + numberOfDisks:(NSUInteger)numberOfDisks + options:(ORKPredefinedTaskOption)options { + + NSMutableArray *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_INTENDED_USE", nil); + step.image = [UIImage imageNamed:@"phone-tower-of-hanoi" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_TITLE", nil); + step.text = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_INTRO_TEXT", nil); + step.detailText = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION", nil); + step.image = [UIImage imageNamed:@"tower-of-hanoi-second-screen" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + ORKTowerOfHanoiStep *towerOfHanoiStep = [[ORKTowerOfHanoiStep alloc]initWithIdentifier:ORKTowerOfHanoiStepIdentifier]; + towerOfHanoiStep.title = ORKLocalizedString(@"TOWER_OF_HANOI_TASK_TITLE", nil); + towerOfHanoiStep.numberOfDisks = numberOfDisks; + ORKStepArrayAddStep(steps, towerOfHanoiStep); + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc]initWithIdentifier:identifier steps:steps]; + + return task; +} + + +#pragma mark - reactionTimeTask + +NSString *const ORKReactionTimeStepIdentifier = @"reactionTime"; + ++ (ORKOrderedTask *)reactionTimeTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + maximumStimulusInterval:(NSTimeInterval)maximumStimulusInterval + minimumStimulusInterval:(NSTimeInterval)minimumStimulusInterval + thresholdAcceleration:(double)thresholdAcceleration + numberOfAttempts:(int)numberOfAttempts + timeout:(NSTimeInterval)timeout + successSound:(UInt32)successSoundID + timeoutSound:(UInt32)timeoutSoundID + failureSound:(UInt32)failureSoundID + options:(ORKPredefinedTaskOption)options { + + NSMutableArray *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"REACTION_TIME_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"REACTION_TIME_TASK_INTENDED_USE", nil); + step.image = [UIImage imageNamed:@"phoneshake" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"REACTION_TIME_TASK_TITLE", nil); + step.text = [NSString localizedStringWithFormat: ORKLocalizedString(@"REACTION_TIME_TASK_INTRO_TEXT_FORMAT", nil), numberOfAttempts]; + step.detailText = ORKLocalizedString(@"REACTION_TIME_TASK_CALL_TO_ACTION", nil); + step.image = [UIImage imageNamed:@"phoneshakecircle" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + ORKReactionTimeStep *step = [[ORKReactionTimeStep alloc] initWithIdentifier:ORKReactionTimeStepIdentifier]; + step.title = ORKLocalizedString(@"REACTION_TIME_TASK_TITLE", nil); + step.maximumStimulusInterval = maximumStimulusInterval; + step.minimumStimulusInterval = minimumStimulusInterval; + step.thresholdAcceleration = thresholdAcceleration; + step.numberOfAttempts = numberOfAttempts; + step.timeout = timeout; + step.successSound = successSoundID; + step.timeoutSound = timeoutSoundID; + step.failureSound = failureSoundID; + step.recorderConfigurations = @[ [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier frequency: 100]]; + + ORKStepArrayAddStep(steps, step); + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *completionStep = [self makeCompletionStep]; + ORKStepArrayAddStep(steps, completionStep); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +#pragma mark - timedWalkTask + +NSString *const ORKTimedWalkFormStepIdentifier = @"timed.walk.form"; +NSString *const ORKTimedWalkFormAFOStepIdentifier = @"timed.walk.form.afo"; +NSString *const ORKTimedWalkFormAssistanceStepIdentifier = @"timed.walk.form.assistance"; +NSString *const ORKTimedWalkTrial1StepIdentifier = @"timed.walk.trial1"; +NSString *const ORKTimedWalkTurnAroundStepIdentifier = @"timed.walk.turn.around"; +NSString *const ORKTimedWalkTrial2StepIdentifier = @"timed.walk.trial2"; + ++ (ORKOrderedTask *)timedWalkTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + distanceInMeters:(double)distanceInMeters + timeLimit:(NSTimeInterval)timeLimit + turnAroundTimeLimit:(NSTimeInterval)turnAroundTimeLimit + includeAssistiveDeviceForm:(BOOL)includeAssistiveDeviceForm + options:(ORKPredefinedTaskOption)options { + + NSMutableArray *steps = [NSMutableArray array]; + + NSLengthFormatter *lengthFormatter = [NSLengthFormatter new]; + lengthFormatter.numberFormatter.maximumFractionDigits = 1; + lengthFormatter.numberFormatter.maximumSignificantDigits = 3; + NSString *formattedLength = [lengthFormatter stringFromMeters:distanceInMeters]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TIMED_WALK_INTRO_DETAIL", nil); + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + if (includeAssistiveDeviceForm) { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:ORKTimedWalkFormStepIdentifier + title:ORKLocalizedString(@"TIMED_WALK_FORM_TITLE", nil) + text:ORKLocalizedString(@"TIMED_WALK_FORM_TEXT", nil)]; + + ORKAnswerFormat *answerFormat1 = [ORKAnswerFormat booleanAnswerFormat]; + ORKFormItem *formItem1 = [[ORKFormItem alloc] initWithIdentifier:ORKTimedWalkFormAFOStepIdentifier + text:ORKLocalizedString(@"TIMED_WALK_QUESTION_TEXT", nil) + answerFormat:answerFormat1]; + formItem1.optional = NO; + + NSArray *textChoices = @[ [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE_2", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE_2"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE_3", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE_3"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE_4", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE_4"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE_5", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE_5"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_CHOICE_6", nil) value:@"TIMED_WALK_QUESTION_2_CHOICE_6"] ]; + ORKAnswerFormat *answerFormat2 = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]; + + ORKFormItem *formItem2 = [[ORKFormItem alloc] initWithSectionTitle:ORKLocalizedString(@"TIMED_WALK_QUESTION_2_TITLE", nil) detailText:nil learnMoreItem:nil showsProgress:YES]; + + ORKFormItem *formItem3 = [[ORKFormItem alloc] initWithIdentifier:ORKTimedWalkFormAssistanceStepIdentifier + text:nil + answerFormat:answerFormat2]; + formItem3.placeholder = ORKLocalizedString(@"TIMED_WALK_QUESTION_2_TEXT", nil); + formItem3.optional = NO; + + step.formItems = @[formItem1, formItem2, formItem3]; + step.optional = NO; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"TIMED_WALK_INTRO_2_TEXT_%@", nil), formattedLength]; + step.detailText = ORKLocalizedString(@"TIMED_WALK_INTRO_2_DETAIL", nil); + step.image = [UIImage imageNamed:@"timer" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.stepDuration = 5.0; + + ORKStepArrayAddStep(steps, step); + } + + { + NSMutableArray *recorderConfigurations = [NSMutableArray array]; + if (!(options & ORKPredefinedTaskOptionExcludePedometer)) { + [recorderConfigurations addObject:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:ORKPedometerRecorderIdentifier]]; + } + if (!(options & ORKPredefinedTaskOptionExcludeAccelerometer)) { + [recorderConfigurations addObject:[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:ORKAccelerometerRecorderIdentifier + frequency:100]]; + } + if (!(options & ORKPredefinedTaskOptionExcludeDeviceMotion)) { + [recorderConfigurations addObject:[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:ORKDeviceMotionRecorderIdentifier + frequency:100]]; + } + if (! (options & ORKPredefinedTaskOptionExcludeLocation)) { + [recorderConfigurations addObject:[[ORKLocationRecorderConfiguration alloc] initWithIdentifier:ORKLocationRecorderIdentifier]]; + } + + { + ORKTimedWalkStep *step = [[ORKTimedWalkStep alloc] initWithIdentifier:ORKTimedWalkTrial1StepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.text = [[[NSString alloc] initWithFormat:ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_%@", nil), formattedLength] stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.recorderConfigurations = recorderConfigurations; + step.distanceInMeters = distanceInMeters; + step.shouldTintImages = YES; + step.image = [UIImage imageNamed:@"timed-walkingman-outbound" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.stepDuration = timeLimit == 0 ? CGFLOAT_MAX : timeLimit; + + ORKStepArrayAddStep(steps, step); + } + + { + if (turnAroundTimeLimit > 0) { + ORKTimedWalkStep *step = [[ORKTimedWalkStep alloc] initWithIdentifier:ORKTimedWalkTurnAroundStepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.text = [ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_TURN", nil) stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.recorderConfigurations = recorderConfigurations; + step.distanceInMeters = 1; + step.shouldTintImages = YES; + step.image = [UIImage imageNamed:@"turnaround" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.stepDuration = turnAroundTimeLimit == 0 ? CGFLOAT_MAX : turnAroundTimeLimit; + + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKTimedWalkStep *step = [[ORKTimedWalkStep alloc] initWithIdentifier:ORKTimedWalkTrial2StepIdentifier]; + step.title = ORKLocalizedString(@"TIMED_WALK_TITLE", nil); + step.text = [[[NSString alloc] initWithFormat:ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_2", nil), formattedLength] stringByAppendingString:[@"\n" stringByAppendingString:ORKLocalizedString(@"TIMED_WALK_INSTRUCTION_TEXT", nil)]]; + step.spokenInstruction = step.text; + step.recorderConfigurations = recorderConfigurations; + step.distanceInMeters = distanceInMeters; + step.shouldTintImages = YES; + step.image = [UIImage imageNamed:@"timed-walkingman-return" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.stepDuration = timeLimit == 0 ? CGFLOAT_MAX : timeLimit; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + + +#pragma mark - PSATTask + +NSString *const ORKPSATStepIdentifier = @"psat"; + ++ (ORKOrderedTask *)PSATTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + presentationMode:(ORKPSATPresentationMode)presentationMode + interStimulusInterval:(NSTimeInterval)interStimulusInterval + stimulusDuration:(NSTimeInterval)stimulusDuration + seriesLength:(NSInteger)seriesLength + options:(ORKPredefinedTaskOption)options { + + NSMutableArray *steps = [NSMutableArray array]; + NSString *versionTitle = @""; + NSString *versionDetailText = @""; + + if (presentationMode == ORKPSATPresentationModeAuditory) { + versionTitle = ORKLocalizedString(@"PASAT_TITLE", nil); + versionDetailText = ORKLocalizedString(@"PASAT_INTRO_TEXT", nil); + } else if (presentationMode == ORKPSATPresentationModeVisual) { + versionTitle = ORKLocalizedString(@"PVSAT_TITLE", nil); + versionDetailText = ORKLocalizedString(@"PVSAT_INTRO_TEXT", nil); + } else { + versionTitle = ORKLocalizedString(@"PAVSAT_TITLE", nil); + versionDetailText = ORKLocalizedString(@"PAVSAT_INTRO_TEXT", nil); + } + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = versionTitle; + step.detailText = versionDetailText; + step.text = intendedUseDescription; + step.image = [UIImage imageNamed:@"psatDice" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = versionTitle; + + NSDateComponentsFormatter *secondsFormatter = [NSDateComponentsFormatter new]; + secondsFormatter.unitsStyle = NSDateFormatterFullStyle; + secondsFormatter.allowedUnits = NSCalendarUnitSecond; + secondsFormatter.formattingContext = NSFormattingContextDynamic; + secondsFormatter.maximumUnitCount = 1; + + NSString *seconds = [secondsFormatter stringFromTimeInterval:interStimulusInterval]; + step.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"PSAT_INTRO_TEXT_2_%@", nil), seconds]; + step.detailText = ORKLocalizedString(@"PSAT_CALL_TO_ACTION", nil); + + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.stepDuration = 5.0; + step.title = versionTitle; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKPSATStep *step = [[ORKPSATStep alloc] initWithIdentifier:ORKPSATStepIdentifier]; + step.title = versionTitle; + step.text = ORKLocalizedString(@"PSAT_INITIAL_INSTRUCTION", nil); + step.stepDuration = (seriesLength + 1) * interStimulusInterval; + step.presentationMode = presentationMode; + step.interStimulusInterval = interStimulusInterval; + step.stimulusDuration = stimulusDuration; + step.seriesLength = seriesLength; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:[steps copy]]; + + return task; +} + + +#pragma mark - tremorTestTask + +NSString *const ORKTremorTestInLapStepIdentifier = @"tremor.handInLap"; +NSString *const ORKTremorTestExtendArmStepIdentifier = @"tremor.handAtShoulderLength"; +NSString *const ORKTremorTestBendArmStepIdentifier = @"tremor.handAtShoulderLengthWithElbowBent"; +NSString *const ORKTremorTestTouchNoseStepIdentifier = @"tremor.handToNose"; +NSString *const ORKTremorTestTurnWristStepIdentifier = @"tremor.handQueenWave"; + ++ (NSString *)stepIdentifier:(NSString *)stepIdentifier withHandIdentifier:(NSString *)handIdentifier { + return [NSString stringWithFormat:@"%@.%@", stepIdentifier, handIdentifier]; +} + ++ (NSMutableArray *)stepsForOneHandTremorTestTaskWithIdentifier:(NSString *)identifier + activeStepDuration:(NSTimeInterval)activeStepDuration + activeTaskOptions:(ORKTremorActiveTaskOption)activeTaskOptions + lastHand:(BOOL)lastHand + leftHand:(BOOL)leftHand + handIdentifier:(NSString *)handIdentifier + introDetailText:(NSString *)detailText + options:(ORKPredefinedTaskOption)options { + NSMutableArray *steps = [NSMutableArray array]; + NSString *stepFinishedInstruction = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION", nil); + BOOL rightHand = !leftHand && ![handIdentifier isEqualToString:ORKActiveTaskMostAffectedHandIdentifier]; + + { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction1StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + + if ([identifier isEqualToString:ORKActiveTaskMostAffectedHandIdentifier]) { + step.detailText = ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DEFAULT_TEXT", nil); + step.text = detailText; + } else { + if (leftHand) { + step.detailText = ORKLocalizedString(@"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT", nil); + } else { + step.detailText = ORKLocalizedString(@"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT", nil); + } + } + + NSString *imageName = leftHand ? @"tremortestLeft" : @"tremortestRight"; + step.image = [UIImage imageNamed:imageName inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + if (!(activeTaskOptions & ORKTremorActiveTaskOptionExcludeHandInLap)) { + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction2StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO", nil); + step.detailText = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"tremortest3a" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.auxiliaryImage = [UIImage imageNamed:@"tremortest3b" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + if (leftHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT", nil); + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + step.auxiliaryImage = [step.auxiliaryImage ork_flippedImage:UIImageOrientationUpMirrored]; + } else if (rightHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT", nil); + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + NSString *stepIdentifier = [self stepIdentifier:ORKCountdown1StepIdentifier withHandIdentifier:handIdentifier]; + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + ORKStepArrayAddStep(steps, step); + } + + { + NSString *titleFormat = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld", nil); + NSString *stepIdentifier = [self stepIdentifier:ORKTremorTestInLapStepIdentifier withHandIdentifier:handIdentifier]; + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:stepIdentifier]; + step.recorderConfigurations = @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"ac1_acc" frequency:100.0], [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"ac1_motion" frequency:100.0]]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = [NSString localizedStringWithFormat:titleFormat, (long)activeStepDuration]; + step.spokenInstruction = step.text; + step.finishedSpokenInstruction = stepFinishedInstruction; + step.stepDuration = activeStepDuration; + step.shouldPlaySoundOnStart = YES; + step.shouldVibrateOnStart = YES; + step.shouldPlaySoundOnFinish = YES; + step.shouldVibrateOnFinish = YES; + step.shouldContinueOnFinish = NO; + step.shouldStartTimerAutomatically = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(activeTaskOptions & ORKTremorActiveTaskOptionExcludeHandAtShoulderHeight)) { + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction4StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO", nil); + step.detailText = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"tremortest4a" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.auxiliaryImage = [UIImage imageNamed:@"tremortest4b" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + if (leftHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT", nil); + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + step.auxiliaryImage = [step.auxiliaryImage ork_flippedImage:UIImageOrientationUpMirrored]; + } else if (rightHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT", nil); + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + NSString *stepIdentifier = [self stepIdentifier:ORKCountdown2StepIdentifier withHandIdentifier:handIdentifier]; + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + ORKStepArrayAddStep(steps, step); + } + + { + NSString *titleFormat = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld", nil); + NSString *stepIdentifier = [self stepIdentifier:ORKTremorTestExtendArmStepIdentifier withHandIdentifier:handIdentifier]; + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:stepIdentifier]; + step.recorderConfigurations = @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"ac2_acc" frequency:100.0], [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"ac2_motion" frequency:100.0]]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = [NSString localizedStringWithFormat:titleFormat, (long)activeStepDuration]; + step.spokenInstruction = step.text; + step.finishedSpokenInstruction = stepFinishedInstruction; + step.stepDuration = activeStepDuration; + step.image = [UIImage imageNamed:@"tremortest4a" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + if (leftHand) { + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + } + step.imageContentMode = UIViewContentModeScaleAspectFit; + + step.shouldPlaySoundOnStart = YES; + step.shouldVibrateOnStart = YES; + step.shouldPlaySoundOnFinish = YES; + step.shouldVibrateOnFinish = YES; + step.shouldContinueOnFinish = NO; + step.shouldStartTimerAutomatically = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(activeTaskOptions & ORKTremorActiveTaskOptionExcludeHandAtShoulderHeightElbowBent)) { + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction5StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO", nil); + step.detailText = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"tremortest5a" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeScaleAspectFit; + step.auxiliaryImage = [UIImage imageNamed:@"tremortest5b" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + if (leftHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT", nil); + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + step.auxiliaryImage = [step.auxiliaryImage ork_flippedImage:UIImageOrientationUpMirrored]; + } else if (rightHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT", nil); + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + NSString *stepIdentifier = [self stepIdentifier:ORKCountdown3StepIdentifier withHandIdentifier:handIdentifier]; + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + ORKStepArrayAddStep(steps, step); + } + + { + NSString *titleFormat = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld", nil); + NSString *stepIdentifier = [self stepIdentifier:ORKTremorTestBendArmStepIdentifier withHandIdentifier:handIdentifier]; + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:stepIdentifier]; + step.recorderConfigurations = @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"ac3_acc" frequency:100.0], [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"ac3_motion" frequency:100.0]]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = [NSString localizedStringWithFormat:titleFormat, (long)activeStepDuration]; + step.spokenInstruction = step.text; + step.finishedSpokenInstruction = stepFinishedInstruction; + step.stepDuration = activeStepDuration; + step.shouldPlaySoundOnStart = YES; + step.shouldVibrateOnStart = YES; + step.shouldPlaySoundOnFinish = YES; + step.shouldVibrateOnFinish = YES; + step.shouldContinueOnFinish = NO; + step.shouldStartTimerAutomatically = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(activeTaskOptions & ORKTremorActiveTaskOptionExcludeHandToNose)) { + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction6StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO", nil); + step.detailText = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"tremortest6a" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.auxiliaryImage = [UIImage imageNamed:@"tremortest6b" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + if (leftHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT", nil); + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + step.auxiliaryImage = [step.auxiliaryImage ork_flippedImage:UIImageOrientationUpMirrored]; + } else if (rightHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT", nil); + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + NSString *stepIdentifier = [self stepIdentifier:ORKCountdown4StepIdentifier withHandIdentifier:handIdentifier]; + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + ORKStepArrayAddStep(steps, step); + } + + { + NSString *titleFormat = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld", nil); + NSString *stepIdentifier = [self stepIdentifier:ORKTremorTestTouchNoseStepIdentifier withHandIdentifier:handIdentifier]; + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:stepIdentifier]; + step.recorderConfigurations = @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"ac4_acc" frequency:100.0], [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"ac4_motion" frequency:100.0]]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = [NSString localizedStringWithFormat:titleFormat, (long)activeStepDuration]; + step.spokenInstruction = step.text; + step.finishedSpokenInstruction = stepFinishedInstruction; + step.stepDuration = activeStepDuration; + step.shouldPlaySoundOnStart = YES; + step.shouldVibrateOnStart = YES; + step.shouldPlaySoundOnFinish = YES; + step.shouldVibrateOnFinish = YES; + step.shouldContinueOnFinish = NO; + step.shouldStartTimerAutomatically = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + if (!(activeTaskOptions & ORKTremorActiveTaskOptionExcludeQueenWave)) { + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + NSString *stepIdentifier = [self stepIdentifier:ORKInstruction7StepIdentifier withHandIdentifier:handIdentifier]; + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO", nil); + step.detailText = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT", nil); + step.image = [UIImage imageNamed:@"tremortest7" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + if (leftHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT", nil); + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + } else if (rightHand) { + step.text = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT", nil); + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + NSString *stepIdentifier = [self stepIdentifier:ORKCountdown5StepIdentifier withHandIdentifier:handIdentifier]; + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:stepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + ORKStepArrayAddStep(steps, step); + } + + { + NSString *titleFormat = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld", nil); + NSString *stepIdentifier = [self stepIdentifier:ORKTremorTestTurnWristStepIdentifier withHandIdentifier:handIdentifier]; + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:stepIdentifier]; + step.recorderConfigurations = @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"ac5_acc" frequency:100.0], [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"ac5_motion" frequency:100.0]]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.text = [NSString localizedStringWithFormat:titleFormat, (long)activeStepDuration]; + step.spokenInstruction = step.text; + step.finishedSpokenInstruction = stepFinishedInstruction; + step.stepDuration = activeStepDuration; + step.shouldPlaySoundOnStart = YES; + step.shouldVibrateOnStart = YES; + step.shouldPlaySoundOnFinish = YES; + step.shouldVibrateOnFinish = YES; + step.shouldContinueOnFinish = NO; + step.shouldStartTimerAutomatically = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + // fix the spoken instruction on the last included step, depending on which hand we're on + ORKActiveStep *lastStep = (ORKActiveStep *)[steps lastObject]; + if (lastHand) { + lastStep.finishedSpokenInstruction = ORKLocalizedString(@"TREMOR_TEST_COMPLETED_INSTRUCTION", nil); + } else if (leftHand) { + lastStep.finishedSpokenInstruction = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION", nil); + } else { + lastStep.finishedSpokenInstruction = ORKLocalizedString(@"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION", nil); + } + + return steps; +} + ++ (ORKNavigableOrderedTask *)tremorTestTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + activeStepDuration:(NSTimeInterval)activeStepDuration + activeTaskOptions:(ORKTremorActiveTaskOption)activeTaskOptions + handOptions:(ORKPredefinedTaskHandOption)handOptions + options:(ORKPredefinedTaskOption)options { + + NSMutableArray<__kindof ORKStep *> *steps = [NSMutableArray array]; + // coin toss for which hand first (in case we're doing both) + BOOL leftFirstIfDoingBoth = arc4random_uniform(2) == 1; + BOOL doingBoth = ((handOptions & ORKPredefinedTaskHandOptionLeft) && (handOptions & ORKPredefinedTaskHandOptionRight)); + BOOL firstIsLeft = (leftFirstIfDoingBoth && doingBoth) || (!doingBoth && (handOptions & ORKPredefinedTaskHandOptionLeft)); + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TREMOR_TEST_TITLE", nil); + step.detailText = intendedUseDescription; + step.text = ORKLocalizedString(@"TREMOR_TEST_INTRO_1_DETAIL", nil); + step.image = [UIImage imageNamed:@"tremortest1" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + if (firstIsLeft) { + step.image = [step.image ork_flippedImage:UIImageOrientationUpMirrored]; + } + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + // Build the string for the detail texts + NSArray*detailStringForNumberOfTasks = @[ + ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_1_TASK", nil), + ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_2_TASK", nil), + ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_3_TASK", nil), + ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_4_TASK", nil), + ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_5_TASK", nil) + ]; + + // start with the count for all the tasks, then subtract one for each excluded task flag + static const NSInteger allTasks = 5; // hold in lap, outstretched arm, elbow bent, repeatedly touching nose, queen wave + NSInteger actualTasksIndex = allTasks - 1; + for (NSInteger i = 0; i < allTasks; ++i) { + if (activeTaskOptions & (1 << i)) { + actualTasksIndex--; + } + } + + NSString *detailFormat = doingBoth ? ORKLocalizedString(@"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@", nil) : ORKLocalizedString(@"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@", nil); + NSString *detailText = [NSString localizedStringWithFormat:detailFormat, detailStringForNumberOfTasks[actualTasksIndex]]; + + if (doingBoth) { + // If doing both hands then ask the user if they need to skip one of the hands + ORKTextChoice *skipRight = [ORKTextChoice choiceWithText:ORKLocalizedString(@"TREMOR_SKIP_RIGHT_HAND", nil) + value:ORKActiveTaskRightHandIdentifier]; + ORKTextChoice *skipLeft = [ORKTextChoice choiceWithText:ORKLocalizedString(@"TREMOR_SKIP_LEFT_HAND", nil) + value:ORKActiveTaskLeftHandIdentifier]; + ORKTextChoice *skipNeither = [ORKTextChoice choiceWithText:ORKLocalizedString(@"TREMOR_SKIP_NEITHER", nil) + value:@""]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:@[skipRight, skipLeft, skipNeither]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:ORKActiveTaskSkipHandStepIdentifier + title:ORKLocalizedString(@"TREMOR_TEST_TITLE", nil) + question:detailText + answer:answerFormat]; + step.optional = NO; + + ORKStepArrayAddStep(steps, step); + } + + // right or most-affected hand + NSArray<__kindof ORKStep *> *rightSteps = nil; + if (handOptions == ORKPredefinedTaskHandOptionUnspecified) { + rightSteps = [self stepsForOneHandTremorTestTaskWithIdentifier:identifier + activeStepDuration:activeStepDuration + activeTaskOptions:activeTaskOptions + lastHand:YES + leftHand:NO + handIdentifier:ORKActiveTaskMostAffectedHandIdentifier + introDetailText:detailText + options:options]; + } else if (handOptions & ORKPredefinedTaskHandOptionRight) { + rightSteps = [self stepsForOneHandTremorTestTaskWithIdentifier:identifier + activeStepDuration:activeStepDuration + activeTaskOptions:activeTaskOptions + lastHand:firstIsLeft + leftHand:NO + handIdentifier:ORKActiveTaskRightHandIdentifier + introDetailText:nil + options:options]; + } + + // left hand + NSArray<__kindof ORKStep *> *leftSteps = nil; + if (handOptions & ORKPredefinedTaskHandOptionLeft) { + leftSteps = [self stepsForOneHandTremorTestTaskWithIdentifier:identifier + activeStepDuration:activeStepDuration + activeTaskOptions:activeTaskOptions + lastHand:!firstIsLeft || !(handOptions & ORKPredefinedTaskHandOptionRight) + leftHand:YES + handIdentifier:ORKActiveTaskLeftHandIdentifier + introDetailText:nil + options:options]; + } + + if (firstIsLeft && leftSteps != nil) { + [steps addObjectsFromArray:leftSteps]; + } + + if (rightSteps != nil) { + [steps addObjectsFromArray:rightSteps]; + } + + if (!firstIsLeft && leftSteps != nil) { + [steps addObjectsFromArray:leftSteps]; + } + + BOOL hasCompletionStep = NO; + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + hasCompletionStep = YES; + ORKCompletionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + if (doingBoth) { + // Setup rules for skipping all the steps in either the left or right hand if called upon to do so. + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithStepIdentifier:ORKActiveTaskSkipHandStepIdentifier + resultIdentifier:ORKActiveTaskSkipHandStepIdentifier]; + NSPredicate *predicateRight = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValue:ORKActiveTaskRightHandIdentifier]; + NSPredicate *predicateLeft = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValue:ORKActiveTaskLeftHandIdentifier]; + + // Setup rule for skipping first hand + NSString *secondHandIdentifier = firstIsLeft ? [[rightSteps firstObject] identifier] : [[leftSteps firstObject] identifier]; + NSPredicate *firstPredicate = firstIsLeft ? predicateLeft : predicateRight; + ORKStepNavigationRule *skipFirst = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[firstPredicate] + destinationStepIdentifiers:@[secondHandIdentifier]]; + [task setNavigationRule:skipFirst forTriggerStepIdentifier:ORKActiveTaskSkipHandStepIdentifier]; + + // Setup rule for skipping the second hand + NSString *triggerIdentifier = firstIsLeft ? [[leftSteps lastObject] identifier] : [[rightSteps lastObject] identifier]; + NSString *conclusionIdentifier = hasCompletionStep ? [[steps lastObject] identifier] : ORKNullStepIdentifier; + NSPredicate *secondPredicate = firstIsLeft ? predicateRight : predicateLeft; + ORKStepNavigationRule *skipSecond = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[secondPredicate] + destinationStepIdentifiers:@[conclusionIdentifier]]; + [task setNavigationRule:skipSecond forTriggerStepIdentifier:triggerIdentifier]; + + // Setup step modifier to change the finished spoken step if skipping the second hand + NSString *key = NSStringFromSelector(@selector(finishedSpokenInstruction)); + NSString *value = ORKLocalizedString(@"TREMOR_TEST_COMPLETED_INSTRUCTION", nil); + ORKStepModifier *stepModifier = [[ORKKeyValueStepModifier alloc] initWithResultPredicate:secondPredicate + keyValueMap:@{key: value}]; + [task setStepModifier:stepModifier forStepIdentifier:triggerIdentifier]; + } + + return task; +} + + +#pragma mark - trailmakingTask + +NSString *const ORKTrailmakingStepIdentifier = @"trailmaking"; + ++ (ORKOrderedTask *)trailmakingTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + trailmakingInstruction:(nullable NSString *)trailmakingInstruction + trailType:(ORKTrailMakingTypeIdentifier)trailType + options:(ORKPredefinedTaskOption)options { + NSMutableArray<__kindof ORKStep *> *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TRAILMAKING_TASK_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TRAILMAKING_INTENDED_USE", nil); + step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + step.title = ORKLocalizedString(@"TRAILMAKING_TASK_TITLE", nil); + if ([trailType isEqualToString:ORKTrailMakingTypeIdentifierA]) { + step.detailText = ORKLocalizedString(@"TRAILMAKING_INTENDED_USE2_A", nil); + } else { + step.detailText = ORKLocalizedString(@"TRAILMAKING_INTENDED_USE2_B", nil); + } + step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + step.title = ORKLocalizedString(@"TRAILMAKING_TASK_TITLE", nil); + step.text = trailmakingInstruction ? : ORKLocalizedString(@"TRAILMAKING_INTRO_TEXT", nil); + step.detailText = ORKLocalizedString(@"TRAILMAKING_CALL_TO_ACTION", nil); + if (UIAccessibilityIsVoiceOverRunning()) { + step.detailText = [NSString stringWithFormat:ORKLocalizedString(@"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER", nil), step.detailText]; + } + step.image = [UIImage imageNamed:@"trailmaking" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.imageContentMode = UIViewContentModeCenter; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + { + ORKCountdownStep *step = [[ORKCountdownStep alloc] initWithIdentifier:ORKCountdownStepIdentifier]; + step.title = ORKLocalizedString(@"TRAILMAKING_TASK_TITLE", nil); + step.stepDuration = 3.0; + + ORKStepArrayAddStep(steps, step); + } + + { + ORKTrailmakingStep *step = [[ORKTrailmakingStep alloc] initWithIdentifier:ORKTrailmakingStepIdentifier]; + step.title = ORKLocalizedString(@"TRAILMAKING_TASK_TITLE", nil); + step.trailType = trailType; + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +#pragma mark - landoltC Visual Acuity + ++ (ORKOrderedTask *)landoltCVisualAcuityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedDescription { + + + NSMutableArray<__kindof ORKStep *> *steps = [NSMutableArray array]; + + ORKInstructionStep *instructionStep = [[ORKInstructionStep alloc] initWithIdentifier:@"visualAcuityLandoltCInstructionStep"]; + instructionStep.title = @"Landolt C Acuity Task"; + instructionStep.text = @"This task collects data to better understand your visual acuity."; + instructionStep.image = [UIImage imageNamed:@"VisualExam" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instructionStep.imageContentMode = UIViewContentModeCenter; + instructionStep.shouldTintImages = YES; + + ORKLearnMoreInstructionStep *learnMoreStep = [[ORKLearnMoreInstructionStep alloc] initWithIdentifier:@"LearnMoreInstructionIdentifier"]; + ORKLearnMoreItem *learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:@"Learn more about Landolt C." learnMoreInstructionStep:learnMoreStep]; + + ORKBodyItem *bodyItemOne = [[ORKBodyItem alloc] initWithText:nil detailText:@"During this task, a Landolt C will appear on the screen in various orientations and sizes for a few seconds." image:nil learnMoreItem:learnMoreItem bodyItemStyle:ORKBodyItemStyleBulletPoint]; + + ORKBodyItem *bodyItemTwo = [[ORKBodyItem alloc] initWithText:nil detailText:@"Each time this happens, use your finger to align the dial with the opening gap in the C and tap the 'Next' button." image:nil learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleBulletPoint]; + + NSMutableArray *bodyItems = [[NSMutableArray alloc] initWithObjects:bodyItemOne, bodyItemTwo, nil]; + + instructionStep.bodyItems = bodyItems; + + ORKStepArrayAddStep(steps, instructionStep); + + ORKLandoltCStep *landoltCStep = [[ORKLandoltCStep alloc]initWithIdentifier:@"landoltCStep" testType:VisionStepTypeVisualAcuity eyeToTest:VisionStepLeftOrRightEyeRight]; + ORKStepArrayAddStep(steps, landoltCStep); + + ORKCompletionStep *completionStep = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, completionStep); + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +#pragma mark - landoltC Contrast Sensitivity + ++ (ORKOrderedTask *)landoltCContrastSensitivityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedDescription { + + + NSMutableArray<__kindof ORKStep *> *steps = [NSMutableArray array]; + + ORKInstructionStep *instructionStep = [[ORKInstructionStep alloc] initWithIdentifier:@"contrastSensitivityInstructionStep"]; + instructionStep.title = @"Landolt C Contrast Sensitivity"; + instructionStep.text = @"This task collects data to better understand your visual contrast sensitivity."; + instructionStep.image = [UIImage imageNamed:@"ContrastExam" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instructionStep.imageContentMode = UIViewContentModeCenter; + instructionStep.shouldTintImages = YES; + + ORKLearnMoreInstructionStep *learnMoreStep = [[ORKLearnMoreInstructionStep alloc] initWithIdentifier:@"LearnMoreInstructionIdentifier"]; + ORKLearnMoreItem *learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:@"Learn more about Landolt C." learnMoreInstructionStep:learnMoreStep]; + + ORKBodyItem *bodyItemOne = [[ORKBodyItem alloc] initWithText:nil detailText:@"During this task, a Landolt C will appear on the screen in various orientations and contrasts for a few seconds." image:nil learnMoreItem:learnMoreItem bodyItemStyle:ORKBodyItemStyleBulletPoint]; + + ORKBodyItem *bodyItemTwo = [[ORKBodyItem alloc] initWithText:nil detailText:@"Each time this happens, use your finger to align the dial with the opening gap in the C and tap the 'Next' button.\n" image:nil learnMoreItem:nil bodyItemStyle:ORKBodyItemStyleBulletPoint]; + + NSMutableArray *bodyItems = [[NSMutableArray alloc] initWithObjects:bodyItemOne, bodyItemTwo, nil]; + instructionStep.bodyItems = bodyItems; + + ORKStepArrayAddStep(steps, instructionStep); + + ORKLandoltCStep *landoltCStep = [[ORKLandoltCStep alloc]initWithIdentifier:@"landoltCStep" testType:VisionStepTypeContrastSensitivity eyeToTest:VisionStepLeftOrRightEyeLeft]; + ORKStepArrayAddStep(steps, landoltCStep); + + ORKCompletionStep *completionStep = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, completionStep); + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +#pragma mark - touch ability + +NSString *const ORKTouchAbilityTapStepIdentifier = @"touchAbilityTap"; +NSString *const ORKTouchAbilityLongPressStepIdentifier = @"touchAbilityLongPress"; +NSString *const ORKTouchAbilitySwipeStepIdentifier = @"touchAbilitySwipe"; +NSString *const ORKTouchAbilityPinchStepIdentifier = @"touchAbilityPinch"; +NSString *const ORKTouchAbilityRotationStepIdentifier = @"touchAbilityRotation"; +NSString *const ORKTouchAbilityVerticalScrollStepIdentifier = @"touchAbilityVerticalScroll"; +NSString *const ORKTouchAbilityHorizontalScrollStepIdentifier = @"touchAbilityHorizontalScroll"; + ++ (ORKOrderedTask *)touchAbilityTaskWithIdentifier:(NSString *)identifier + intendedUseDescription:(nullable NSString *)intendedUseDescription + taskOptions:(ORKTouchAbilityTaskOption)taskOptions + options:(ORKPredefinedTaskOption)options { + + NSMutableArray<__kindof ORKStep *> *steps = [NSMutableArray array]; + + if (!(options & ORKPredefinedTaskOptionExcludeInstructions)) { + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction0StepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_INSTRUCTION_TITLE", nil); + step.text = intendedUseDescription; + step.detailText = ORKLocalizedString(@"TOUCH_ABILITY_INSTRUCTION_DETAIL", nil); + step.image = [UIImage imageNamed:@"touchAbilityInstruction" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + step.shouldTintImages = YES; + + ORKStepArrayAddStep(steps, step); + } + } + + NSUInteger count = 0; + + if (taskOptions & ORKTouchAbilityTaskOptionTap) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction1StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_TAP_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_TAP_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityTap" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityTapStep *step = [[ORKTouchAbilityTapStep alloc] initWithIdentifier:ORKTouchAbilityTapStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_TAP_TITLE", nil); + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + if (taskOptions & ORKTouchAbilityTaskOptionLongPress) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction2StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_LONG_PRESS_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_LONG_PRESS_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityTap" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityLongPressStep *step = [[ORKTouchAbilityLongPressStep alloc] initWithIdentifier:ORKTouchAbilityLongPressStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_LONG_PRESS_TITLE", nil); + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + if (taskOptions & ORKTouchAbilityTaskOptionSwipe) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction3StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_SWIPE_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_SWIPE_TEXT", nil); + + NSArray *images = @[[UIImage imageNamed:@"touchAbilitySwipe1" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil], + [UIImage imageNamed:@"touchAbilitySwipe2" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil], + [UIImage imageNamed:@"touchAbilitySwipe3" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil], + [UIImage imageNamed:@"touchAbilitySwipe4" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil], + [UIImage imageNamed:@"touchAbilitySwipe1" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]]; + + instruction.image = [UIImage animatedImageWithImages:images duration:2]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilitySwipeStep *step = [[ORKTouchAbilitySwipeStep alloc] initWithIdentifier:ORKTouchAbilitySwipeStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_SWIPE_TITLE", nil); + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + + if (taskOptions & ORKTouchAbilityTaskOptionVerticalScroll) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction4StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_VERTICAL_SCROLL_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_VERTICAL_SCROLL_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityVerticalScroll" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityScrollStep *step = [[ORKTouchAbilityScrollStep alloc] initWithIdentifier:ORKTouchAbilityVerticalScrollStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_VERTICAL_SCROLL_TITLE", nil); + step.horizontal = NO; + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + if (taskOptions & ORKTouchAbilityTaskOptionHorizontalScroll) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction5StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_HORIZONTAL_SCROLL_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_HORIZONTAL_SCROLL_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityHorizontalScroll" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityScrollStep *step = [[ORKTouchAbilityScrollStep alloc] initWithIdentifier:ORKTouchAbilityHorizontalScrollStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_HORIZONTAL_SCROLL_TITLE", nil); + step.horizontal = YES; + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + if (taskOptions & ORKTouchAbilityTaskOptionPinch) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction6StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_PINCH_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_PINCH_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityPinch" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityPinchStep *step = [[ORKTouchAbilityPinchStep alloc] initWithIdentifier:ORKTouchAbilityPinchStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_PINCH_TITLE", nil); + + ORKStepArrayAddStep(steps, step); + + count += 1; + } + + if (taskOptions & ORKTouchAbilityTaskOptionRotation) { + + ORKInstructionStep *instruction = [[ORKInstructionStep alloc] initWithIdentifier:ORKInstruction7StepIdentifier]; + instruction.title = ORKLocalizedString(@"TOUCH_ABILITY_ROTATION_TITLE", nil); + instruction.text = ORKLocalizedString(@"TOUCH_ABILITY_ROTATION_TEXT", nil); + instruction.image = [UIImage imageNamed:@"touchAbilityRotation" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil]; + instruction.shouldTintImages = YES; + + if (count == 0) { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION", nil); + } else { + instruction.detailText = ORKLocalizedString(@"TAPPING_CALL_TO_ACTION_NEXT", nil); + } + + ORKStepArrayAddStep(steps, instruction); + + ORKTouchAbilityRotationStep *step = [[ORKTouchAbilityRotationStep alloc] initWithIdentifier:ORKTouchAbilityRotationStepIdentifier]; + step.title = ORKLocalizedString(@"TOUCH_ABILITY_ROTATION_TITLE", nil); + + ORKStepArrayAddStep(steps, step); + } + + if (!(options & ORKPredefinedTaskOptionExcludeConclusion)) { + ORKInstructionStep *step = [self makeCompletionStep]; + + ORKStepArrayAddStep(steps, step); + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.h new file mode 100755 index 0000000..9e19430 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.h @@ -0,0 +1,144 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKOrderedTask` class implements all the methods in the `ORKTask` protocol and represents a + task that assumes a fixed order for its steps. + + In the ResearchKit framework, any simple sequential task, such as a survey or an active task, can + be represented as an ordered task. + + If you want further custom conditional behaviors in a task, it can be easier to subclass + `ORKOrderedTask` or `ORKNavigableOrderedTask` and override particular `ORKTask` methods than it is + to implement the `ORKTask` protocol directly. Override the methods `stepAfterStep:withResult:` and + `stepBeforeStep:withResult:`, and call super for all other methods. + */ +ORK_CLASS_AVAILABLE +@interface ORKOrderedTask : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/// @name Initializers + +/** + Returns an initialized ordered task using the specified identifier and array of steps. + + @param identifier The unique identifier for the task. + @param steps An array of `ORKStep` objects in the order in which they should be presented. + + @return An initialized ordered task. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + steps:(nullable NSArray *)steps NS_DESIGNATED_INITIALIZER; + +/** + Returns an ordered task initialized from data in the given unarchiver. + + An ordered task can be serialized and deserialized with `NSKeyedArchiver`. Note + that this serialization includes strings that might need to be + localized. + + @param aDecoder The coder from which to initialize the ordered task. + + @return An initialized ordered task. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/// @name Properties + +/** + The array of steps in the task. (read-only) + + Each element in the array must be a subclass of `ORKStep`. + The associated task view controller presents the steps in + array order. + */ +@property (nonatomic, copy, readonly) NSArray *steps; + +/** + Color property of the progress label. + Default is black. + */ +@property (nonatomic) UIColor *progressLabelColor; + +/** + Return a mutated copy of self replacing the steps by the passed ones. + + This method is intended to allow for mutating an ordered task (or subclass) while retaining + the original class and properties that may not be publicly exposed, but with a mutated set + of steps. An example of where this might be useful is if before performing an `ORKPredefinedActiveTask`, + the app needed to query the participant about medications, diet or sleep. The app + would need to mutate the steps in order to insert their own steps. While an ORKOrderedTask could + then be created with the same identifier and the new steps, subclass information such rules on an + `ORKNavigableOrderedTask` would be lost. + + @param steps An array of `ORKStep` objects in the order in which they should be presented. + + @return An initialized ordered task. + */ +- (instancetype)copyWithSteps:(NSArray *)steps; + +/** + Return a mutated copy of self replacing the steps and identifier by the ones passed. + + This method is intended to allow for mutating an ordered task (or subclass) while retaining + the original class and properties that may not be publicly exposed, but with a mutated set + of steps. An example of where this might be useful is if before performing an `ORKPredefinedActiveTask`, + the app needed to query the participant about medications, diet or sleep. The app + would need to mutate the steps in order to insert their own steps. While an ORKOrderedTask could + then be created with the same identifier and the new steps, subclass information such rules on an + `ORKNavigableOrderedTask` would be lost. + + @param steps An array of `ORKStep` objects in the order in which they should be presented. + @param identifier The new task identifier + + @return An initialized ordered task. + */ +- (instancetype)copyWithSteps:(NSArray *)steps identifier:(NSString *)identifier; + +/** + Find the index of a given step. + + @param step The step to look for + @return The index position of the step (or NSNotFound if not found) + */ +- (NSUInteger)indexOfStep:(ORKStep *)step; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.m new file mode 100755 index 0000000..718afd5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask.m @@ -0,0 +1,393 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKOrderedTask.h" +#import "ORKFormStep.h" +#import "ORKQuestionStep.h" +#import "ORKFormStepViewController.h" +#import "ORKAnswerFormat.h" +#import "ORKInstructionStep.h" +#import "ORKCompletionStep.h" +#import "ORKFormItem_Internal.h" + +#import "ORKActiveStep_Internal.h" +#import "ORKStep_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@implementation ORKOrderedTask { + NSString *_identifier; + NSMutableArray *_stepsThatDisplayProgress; +} + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray *)steps { + self = [super init]; + if (self) { + ORKThrowInvalidArgumentExceptionIfNil(identifier); + + _identifier = [identifier copy]; + _steps = steps; + + _progressLabelColor = ORKColor(ORKProgressLabelColorKey); + [self setUpArrayOfStepsThatShowProgress]; + [self validateParameters]; + } + return self; +} + +- (instancetype)copyWithSteps:(NSArray *)steps { + ORKOrderedTask *task = [self copyWithZone:nil]; + task->_steps = ORKArrayCopyObjects(steps); + return task; +} + +- (instancetype)copyWithSteps:(NSArray *)steps identifier:(NSString *)identifier { + ORKOrderedTask *task = [self copyWithZone:nil]; + task->_steps = ORKArrayCopyObjects(steps); + task->_identifier = [identifier copy]; + return task; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKOrderedTask *task = [[[self class] allocWithZone:zone] initWithIdentifier:[_identifier copy] + steps:ORKArrayCopyObjects(_steps)]; + return task; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.identifier, castObject.identifier) + && ORKEqualObjects(self.steps, castObject.steps)); +} + +- (NSUInteger)hash { + return _identifier.hash ^ _steps.hash; +} + +#pragma mark - ORKTask + +- (void)validateParameters { + NSArray *uniqueIdentifiers = [self.steps valueForKeyPath:@"@distinctUnionOfObjects.identifier"]; + BOOL itemsHaveNonUniqueIdentifiers = ( self.steps.count != uniqueIdentifiers.count ); + + if (itemsHaveNonUniqueIdentifiers) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Each step should have a unique identifier" userInfo:nil]; + } +} + +- (NSString *)identifier { + return _identifier; +} + +- (void)setUpArrayOfStepsThatShowProgress { + _stepsThatDisplayProgress = [NSMutableArray new]; + + // Steps will not be included in the _stepsThatDisplayProgress array if: + // 1) The step is a instruction or completion step (or inherits from it) and is the first or last step in the task + // 3) There is only ONE step in the entire task + // 4) The showsProgress property is set to false + + for (ORKStep *stepObject in _steps) { + NSUInteger indexOfStep = [self indexOfStep:stepObject]; + BOOL isFirstOrLastStep = indexOfStep == 0 || indexOfStep == _steps.count - 1; + BOOL isInstructionOrCompletionStep = [stepObject isKindOfClass:[ORKInstructionStep class]] || [stepObject isKindOfClass:[ORKCompletionStep class]]; + + if (!(isInstructionOrCompletionStep && isFirstOrLastStep) && [stepObject showsProgress]) { + [_stepsThatDisplayProgress addObject:stepObject.identifier]; + } + } +} + +- (NSUInteger)indexOfStep:(ORKStep *)step { + NSUInteger index = [_steps indexOfObject:step]; + if (index == NSNotFound) { + NSArray *identifiers = [_steps valueForKey:@"identifier"]; + index = [identifiers indexOfObject:step.identifier]; + } + return index; +} + +- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + NSArray *steps = _steps; + + if (steps.count <= 0) { + return nil; + } + + ORKStep *currentStep = step; + ORKStep *nextStep = nil; + + if (currentStep == nil) { + nextStep = steps[0]; + } else { + NSUInteger index = [self indexOfStep:step]; + + if (NSNotFound != index && index != (steps.count - 1)) { + nextStep = steps[index + 1]; + } + } + return nextStep; +} + +- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + NSArray *steps = _steps; + + if (steps.count <= 0) { + return nil; + } + + ORKStep *currentStep = step; + ORKStep *previousStep = nil; + + if (currentStep == nil) { + previousStep = nil; + + } else { + NSUInteger index = [self indexOfStep:step]; + + if (NSNotFound != index && index != 0) { + previousStep = steps[index - 1]; + } + } + return previousStep; +} + +- (ORKStep *)stepWithIdentifier:(NSString *)identifier { + __block ORKStep *step = nil; + [_steps enumerateObjectsUsingBlock:^(ORKStep *obj, NSUInteger idx, BOOL *stop) { + if ([obj.identifier isEqualToString:identifier]) { + step = obj; + *stop = YES; + } + }]; + return step; +} + +- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)taskResult { + ORKTaskProgress progress; + + if ([_stepsThatDisplayProgress containsObject:step.identifier]) { + progress.current = [_stepsThatDisplayProgress indexOfObject:step.identifier]; + progress.total = _stepsThatDisplayProgress.count; + progress.shouldBePresented = progress.total > 1 ? YES : NO; + } else { + progress.current = [self indexOfStep:step]; + progress.total = 0; + progress.shouldBePresented = NO; + } + + return progress; +} + +- (ORKTaskTotalProgress)totalProgressOfCurrentStep:(ORKStep *)currentStep { + ORKTaskTotalProgress totalProgress; + int totalQuestions = 0; + int currentStepStartingProgressNumber = 0; + + for (ORKStep *step in self.steps) { + if ([step isKindOfClass:[ORKFormStep class]]) { + ORKFormStep *formStep = (ORKFormStep *)step; + if (formStep.identifier == currentStep.identifier) { + currentStepStartingProgressNumber = (totalQuestions + 1); + } + NSMutableArray *allSections = [self calculateSectionsForFormItems:formStep.formItems]; + totalQuestions += allSections.count; + } else if ([step isKindOfClass:[ORKQuestionStep class]]) { + if (step.identifier == currentStep.identifier) { + currentStepStartingProgressNumber = (totalQuestions + 1); + } + totalQuestions += 1; + } + } + + totalProgress.currentStepStartingProgressPosition = currentStepStartingProgressNumber; + totalProgress.total = totalQuestions; + + return totalProgress; +} + +- (NSMutableArray *)calculateSectionsForFormItems:(NSArray *)formItems { + NSMutableArray *_sections = [NSMutableArray new]; + NSMutableArray *section = nil; + + for (ORKFormItem *item in formItems) { + BOOL itemRequiresSingleSection = [self doesItemRequireSingleSection:item]; + + if (!item.answerFormat) { + // Add new section + section = [NSMutableArray new]; + [_sections addObject:section]; + + } else if (itemRequiresSingleSection || _sections.count == 0) { + + NSMutableArray *newSection = [self buildSingleSection:item]; + [_sections addObject:newSection]; + section = newSection; + } else { + if (section) { + [section addObject:item]; + } + } + } + return _sections; +} + +- (NSMutableArray *)buildSingleSection:(ORKFormItem *)item { + NSMutableArray *section = nil; + + // Section header + if ([item impliedAnswerFormat] == nil) { + // Add new section + section = [NSMutableArray new]; + return section; + } else { + + if ([self doesItemRequireSingleSection:item]) { + // Add new section + section = [NSMutableArray new]; + [section addObject:item]; + return section; + + } else { + // In case no section available, create new one. + if (section == nil) { + section = [NSMutableArray new]; + } + [section addObject:item]; + return section; + } + } +} + +- (BOOL)doesItemRequireSingleSection:(ORKFormItem *)item { + if (item.impliedAnswerFormat == nil) { + return NO; + } + + ORKAnswerFormat *answerFormat = [item impliedAnswerFormat]; + + NSArray *singleSectionTypes = @[@(ORKQuestionTypeBoolean), + @(ORKQuestionTypeSingleChoice), + @(ORKQuestionTypeMultipleChoice), + @(ORKQuestionTypeLocation)]; + + BOOL multiCellChoices = ([singleSectionTypes containsObject:@(answerFormat.questionType)] && + NO == [answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]]); + + BOOL multilineTextEntry = (answerFormat.questionType == ORKQuestionTypeText && [(ORKTextAnswerFormat *)answerFormat multipleLines]); + + BOOL scale = (answerFormat.questionType == ORKQuestionTypeScale); + + // Items that require individual section + if (multiCellChoices || multilineTextEntry || scale) { + return YES; + } + + return NO; +} + +- (NSSet *)requestedHealthKitTypesForReading { + NSMutableSet *healthTypes = [NSMutableSet set]; + for (ORKStep *step in self.steps) { + NSSet *stepSet = [step requestedHealthKitTypesForReading]; + if (stepSet) { + [healthTypes unionSet:stepSet]; + } + } + return healthTypes.count ? healthTypes : nil; +} + +- (NSSet *)requestedHealthKitTypesForWriting { + return nil; +} + +- (ORKPermissionMask)requestedPermissions { + ORKPermissionMask mask = ORKPermissionNone; + for (ORKStep *step in self.steps) { + mask |= [step requestedPermissions]; + } + return mask; +} + +- (BOOL)providesBackgroundAudioPrompts { + BOOL providesAudioPrompts = NO; + for (ORKStep *step in self.steps) { + if ([step isKindOfClass:[ORKActiveStep class]]) { + ORKActiveStep *activeStep = (ORKActiveStep *)step; + if ([activeStep hasVoice] || [activeStep hasCountDown]) { + providesAudioPrompts = YES; + break; + } + } + } + return providesAudioPrompts; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); + ORK_ENCODE_OBJ(aCoder, steps); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + ORK_DECODE_OBJ_ARRAY(aDecoder, steps, ORKStep); + + for (ORKStep *step in _steps) { + if ([step isKindOfClass:[ORKStep class]]) { + [step setTask:self]; + } + } + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask_Private.h new file mode 100755 index 0000000..ea25f97 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKOrderedTask_Private.h @@ -0,0 +1,77 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKCompletionStep, ORKStep; + + +FOUNDATION_EXPORT NSString *const ORKInstruction0StepIdentifier; +FOUNDATION_EXPORT NSString *const ORKInstruction1StepIdentifier; +FOUNDATION_EXPORT NSString *const ORKCountdownStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKAudioStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKAudioTooLoudStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKTappingStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKConclusionStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKFitnessWalkStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKFitnessRestStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKShortWalkOutboundStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKShortWalkReturnStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKShortWalkRestStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKSpatialSpanMemoryStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKStroopStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKToneAudiometryPracticeStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKToneAudiometryStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKReactionTimeStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKHolePegTestDominantPlaceStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKHolePegTestDominantRemoveStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKHolePegTestNonDominantPlaceStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKHolePegTestNonDominantRemoveStepIdentifier; +FOUNDATION_EXPORT NSString *const ORKAudioRecorderIdentifier; +FOUNDATION_EXPORT NSString *const ORKAccelerometerRecorderIdentifier; +FOUNDATION_EXPORT NSString *const ORKPedometerRecorderIdentifier; +FOUNDATION_EXPORT NSString *const ORKDeviceMotionRecorderIdentifier; +FOUNDATION_EXPORT NSString *const ORKLocationRecorderIdentifier; +FOUNDATION_EXPORT NSString *const ORKHeartRateRecorderIdentifier; + +FOUNDATION_EXPORT void ORKStepArrayAddStep(NSMutableArray *array, ORKStep *step); + +@interface ORKOrderedTask (ORKMakeTaskUtilities) + ++ (ORKCompletionStep *)makeCompletionStep; ++ (NSDateComponentsFormatter *)textTimeFormatter; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.h new file mode 100755 index 0000000..2aed298 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKPDFViewerStep` class is a concrete subclass of `ORKStep`, used for presenting a PDF document for reading and limited editing. + + To use `ORKPDFViewerStep`, instantiate the object, fill in its properties, and include it in a task. + Next, create a task view controller for the task and present it. + */ + +ORK_CLASS_AVAILABLE +@interface ORKPDFViewerStep : ORKStep + +- (instancetype) initWithIdentifier:(NSString *)identifier pdfURL:(nullable NSURL *)pdfURL; + +@property (nonatomic, copy, nullable) NSURL *pdfURL; + +@property (nonatomic, assign) ORKPDFViewerActionBarOption actionBarOption; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.m new file mode 100755 index 0000000..364ea3c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStep.m @@ -0,0 +1,104 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPDFViewerStep.h" +#import "ORKPDFViewerStepViewController.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKPDFViewerStep { + + BOOL _allowThumbnail; + BOOL _allowEditing; + BOOL _allowSearching; + BOOL _allowSharing; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + _allowThumbnail = YES; + _allowEditing = YES; + _allowSearching = YES; + _allowSharing = YES; + } + return self; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier pdfURL:(nullable NSURL *)pdfURL { + self = [self initWithIdentifier:identifier]; + if (self) { + self.pdfURL = pdfURL; + } + return self; +} + +#pragma mark - view controller instantiation + ++ (Class)stepViewControllerClass { + return [ORKPDFViewerStepViewController class]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPDFViewerStep *step = [super copyWithZone:zone]; + step.pdfURL = self.pdfURL; + return step; +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(castObject.pdfURL, self.pdfURL); +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_URL(aCoder, pdfURL); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_URL(aDecoder, pdfURL); + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.h new file mode 100755 index 0000000..88c7cd0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKCustomStepView_Internal.h" +@import PDFKit; + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKPDFViewerStepViewDelegate + +- (void)didSelectShareButton:(id)sender; + +@end + +@interface ORKPDFViewerStepView : ORKActiveStepCustomView + +@property (nonatomic) NSURL *pdfURL; + +@property (nonatomic) id delegate; + +- (void)updateShareButton; + +- (nullable PDFDocument *)getDocument; + +- (BOOL)pdfModified; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.m new file mode 100755 index 0000000..105b235 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView.m @@ -0,0 +1,842 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import PDFKit; +#import "ORKPDFViewerStepView_Internal.h" +#import "ORKFreehandDrawingView.h" +#import "ORKHelpers_Internal.h" +#import "ORKBorderedButton.h" +#import "ORKSkin.h" + +const CGFloat PDFSearchBarHeight = 40.0; +const CGFloat PDFActionViewHeight = 25.0; +const CGFloat PDFActionItemPadding = 1.0; +const CGFloat PDFThumbnailViewWidth = 60.0; +const CGFloat PDFActionsViewLeftRightPadding = 20.0; +const CGFloat PDFParentStackViewSpacing = 10.0; +const CGFloat PDFInactiveButtonAlpha = 0.5; + +const CGFloat PDFhideViewAnimationDuration = 0.5; + +@interface ORKPDFViewerActionsView: UIView + +@property (nonatomic, nonnull) UIView *thumbnailActionView; +@property (nonatomic, nonnull) UIView *annotationActionView; +@property (nonatomic, nonnull) UIView *searchActionView; +@property (nonatomic, nonnull) UIView *shareActionView; +@property (nonatomic, nonnull) UIView *clearButtonView; +@property (nonatomic, nonnull) UIView *applyButtonView; +@property (nonatomic, nonnull) UIView *exitButtonView; + +@property (nonatomic, nonnull) UIStackView *stackView; + +@property (nonatomic, nonnull) UIButton *thumbnailActionButton; +@property (nonatomic, nonnull) UIButton *annotationActionButton; +@property (nonatomic, nonnull) UIButton *searchActionButton; +@property (nonatomic, nonnull) UIButton *shareActionButton; +@property (nonatomic, nonnull) ORKBorderedButton *clearAnnotationsButton; +@property (nonatomic, nonnull) ORKBorderedButton *applyAnnotationsButton; +@property (nonatomic, nonnull) UIButton *exitAnnotationsButton; + + + +@end + +@implementation ORKPDFViewerActionsView + +- (instancetype)init +{ + self = [super init]; + if (self) { + } + [self setupStackView]; + [self setupConstraints]; + return self; +} + +- (void)setupStackView { + if (!_stackView) { + _stackView = [[UIStackView alloc] init]; + } + _stackView.translatesAutoresizingMaskIntoConstraints = NO; + _stackView.spacing = 0.0; + _stackView.layoutMargins = UIEdgeInsetsMake(0.0, PDFActionsViewLeftRightPadding, 0.0, PDFActionsViewLeftRightPadding); + [_stackView setLayoutMarginsRelativeArrangement:YES]; + _stackView.axis = UILayoutConstraintAxisHorizontal; + _stackView.distribution = UIStackViewDistributionFillEqually; + [self setupThumbnailAction]; + [self setupAnnotationAction]; + [self setupSearchAction]; + [self setupShareAction]; + [self setupClearAnnotationsButton]; + [self setupApplyAnnotationsButton]; + [self setupExitAnnotationsButton]; + [self addSubview:_stackView]; +} + +- (void)setupThumbnailAction { + if (!_thumbnailActionButton) { + _thumbnailActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + } + + [_thumbnailActionButton setImage:[[UIImage imageNamed:@"pdfThumbnail" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; + _thumbnailActionView = [UIView new]; + _thumbnailActionView.translatesAutoresizingMaskIntoConstraints = NO; + _thumbnailActionButton.translatesAutoresizingMaskIntoConstraints = NO; + [_thumbnailActionView addSubview:_thumbnailActionButton]; + [_stackView insertArrangedSubview:_thumbnailActionView atIndex:0]; + [self activateConstraintsForButton:_thumbnailActionButton withView:_thumbnailActionView]; +} + +- (void)setupAnnotationAction { + if (!_annotationActionButton) { + _annotationActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + } + + [_annotationActionButton setImage:[[UIImage imageNamed:@"annotation" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; + _annotationActionView = [UIView new]; + _annotationActionView.translatesAutoresizingMaskIntoConstraints = NO; + _annotationActionButton.translatesAutoresizingMaskIntoConstraints = NO; + [_annotationActionView addSubview:_annotationActionButton]; + [_stackView addArrangedSubview:_annotationActionView]; + [self activateConstraintsForButton:_annotationActionButton withView:_annotationActionView]; +} + +- (void)setupSearchAction { + if (!_searchActionButton) { + _searchActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + } + + [_searchActionButton setImage:[[UIImage imageNamed:@"search" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; + _searchActionView = [UIView new]; + _searchActionView.translatesAutoresizingMaskIntoConstraints = NO; + _searchActionButton.translatesAutoresizingMaskIntoConstraints = NO; + [_searchActionView addSubview:_searchActionButton]; + [_stackView addArrangedSubview:_searchActionView]; + [self activateConstraintsForButton:_searchActionButton withView:_searchActionView]; +} + +- (void)setupShareAction { + if (!_shareActionButton) { + _shareActionButton = [UIButton buttonWithType:UIButtonTypeCustom]; + } + + [_shareActionButton setImage:[[UIImage imageNamed:@"share" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; + _shareActionView = [UIView new]; + _shareActionView.translatesAutoresizingMaskIntoConstraints = NO; + _shareActionButton.translatesAutoresizingMaskIntoConstraints = NO; + [_shareActionView addSubview:_shareActionButton]; + [_stackView addArrangedSubview:_shareActionView]; + [self activateConstraintsForButton:_shareActionButton withView:_shareActionView]; +} + +- (void)setupClearAnnotationsButton { + if (!_clearAnnotationsButton) { + _clearAnnotationsButton = [ORKBorderedButton new]; + } + _clearAnnotationsButton.contentEdgeInsets = (UIEdgeInsets){.left = 6, .right = 6}; + _clearAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; + _clearButtonView = [UIView new]; + _clearButtonView.translatesAutoresizingMaskIntoConstraints = NO; + [_clearAnnotationsButton setTitle:ORKLocalizedString(@"BUTTON_CLEAR", nil) forState:UIControlStateNormal]; + [_clearButtonView addSubview:_clearAnnotationsButton]; + [_stackView addArrangedSubview:_clearButtonView]; + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_clearButtonView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_clearButtonView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_clearAnnotationsButton + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_clearButtonView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0] + ]]; +} + +- (void)setupApplyAnnotationsButton { + if (!_applyAnnotationsButton) { + _applyAnnotationsButton = [ORKBorderedButton new]; + } + _applyAnnotationsButton.contentEdgeInsets = (UIEdgeInsets){.left = 6, .right = 6}; + _applyAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; + _applyButtonView = [UIView new]; + _applyButtonView.translatesAutoresizingMaskIntoConstraints = NO; + [_applyAnnotationsButton setTitle:ORKLocalizedString(@"BUTTON_APPLY", nil) forState:UIControlStateNormal]; + [_applyButtonView addSubview:_applyAnnotationsButton]; + [_stackView addArrangedSubview:_applyButtonView]; + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_applyButtonView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_applyButtonView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_applyAnnotationsButton + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_applyButtonView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0] + ]];} + +- (void)setupExitAnnotationsButton { + if (!_exitAnnotationsButton) { + _exitAnnotationsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + } + [_exitAnnotationsButton setTitle:@"X" forState:UIControlStateNormal]; + [_exitAnnotationsButton.titleLabel setAdjustsFontSizeToFitWidth:YES]; + [_exitAnnotationsButton.titleLabel setFont:[UIFont boldSystemFontOfSize:[UIFont systemFontSize]]]; + _exitAnnotationsButton.translatesAutoresizingMaskIntoConstraints = NO; + _exitButtonView = [UIView new]; + _exitButtonView.translatesAutoresizingMaskIntoConstraints = NO; + [_exitButtonView addSubview:_exitAnnotationsButton]; + [_stackView addArrangedSubview:_exitButtonView]; + [self activateConstraintsForButton:_exitAnnotationsButton withView:_exitButtonView]; + [self setExitAnnotationsButtonStyle]; +} + +- (void)activateConstraintsForButton:(UIButton *)button withView:(UIView *)view { + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:PDFActionViewHeight], + [NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:PDFActionViewHeight], + [NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:button + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:view + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]]; +} + +- (void)setExitAnnotationsButtonStyle { + [_exitAnnotationsButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [_exitAnnotationsButton setBackgroundColor:[[self tintColor] colorWithAlphaComponent:PDFInactiveButtonAlpha]]; + + [_exitAnnotationsButton.layer setCornerRadius:PDFActionViewHeight/2.0]; +} + +- (void)setupConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_stackView); + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_stackView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_stackView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + + + +@end + +@interface ORKPDFViewerStepView () + +@end + +@implementation ORKPDFViewerStepView { + + UIStackView *_parentStackView, *_pdfStackView; + UISearchBar *_searchBar; + ORKPDFViewerActionsView *_pdfActionsView; + + PDFView *_pdfView; + PDFThumbnailView *_pdfThumbnailView; + ORKFreehandDrawingView *_freehandDrawingView; + + BOOL _isFreehandDrawingActive; + BOOL _isShareActive; + BOOL _annotationsAdded; + UIView *_keyboardUnderlapView; +} + + +- (instancetype)init { + self = [super init]; + if (self) { + [self setupParentStackView]; + [self setupSearchBar]; + [self setupPDFActionsView]; + [self setupPDFStackView]; + [self setupKeyboardUnderlapView]; + [self setupConstraints]; + + } + return self; +} + +- (void)setupParentStackView { + if (!_parentStackView) { + _parentStackView = [[UIStackView alloc] init]; + } + _parentStackView.translatesAutoresizingMaskIntoConstraints = NO; + _parentStackView.spacing = PDFParentStackViewSpacing; + _parentStackView.axis = UILayoutConstraintAxisVertical; + _parentStackView.distribution = UIStackViewDistributionFill; + [self addSubview:_parentStackView]; +} + +- (void)setupSearchBar { + if (!_searchBar) { + _searchBar = [[UISearchBar alloc] init]; + } + [NSLayoutConstraint constraintWithItem:_searchBar + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:PDFSearchBarHeight].active = YES; + _searchBar.hidden = YES; + _searchBar.delegate = self; + _searchBar.barTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3]; + _searchBar.translatesAutoresizingMaskIntoConstraints = NO; + [_parentStackView insertArrangedSubview:_searchBar atIndex:0]; +} + +- (void)setupPDFActionsView { + if (!_pdfActionsView) { + _pdfActionsView = [ORKPDFViewerActionsView new]; + } + [NSLayoutConstraint constraintWithItem:_pdfActionsView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:PDFActionViewHeight].active = YES; + + [self setupClearApplyExitButtons]; + + [_pdfActionsView.thumbnailActionButton addTarget:self action:@selector(thumbnailButtonAction) forControlEvents:UIControlEventTouchUpInside]; + [_pdfActionsView.annotationActionButton addTarget:self action:@selector(annotationButtonAction) forControlEvents:UIControlEventTouchUpInside]; + [_pdfActionsView.searchActionButton addTarget:self action:@selector(searchButtonAction) forControlEvents:UIControlEventTouchUpInside]; + [_pdfActionsView.shareActionButton addTarget:self action:@selector(shareButtonAction) forControlEvents:UIControlEventTouchUpInside]; + + _pdfActionsView.translatesAutoresizingMaskIntoConstraints = NO; + [_parentStackView addArrangedSubview:_pdfActionsView]; + + [self updateActionButtonAccessibilityLabels]; +} + +- (void)setupPDFStackView { + if (!_pdfStackView) { + [self setupPDFView]; + _pdfStackView = [[UIStackView alloc] initWithArrangedSubviews:@[_pdfThumbnailView, _pdfView]]; + } + _pdfStackView.translatesAutoresizingMaskIntoConstraints = NO; + _pdfStackView.spacing = 10.0; + _pdfStackView.axis = UILayoutConstraintAxisHorizontal; + _pdfStackView.distribution = UIStackViewDistributionFill; + [_parentStackView addArrangedSubview:_pdfStackView]; +} + +- (void)setupPDFView { + if (!_pdfView) { + _pdfView = [PDFView new]; + } + PDFDocument *document; + if (_pdfURL) { + document = [[PDFDocument alloc] initWithURL:_pdfURL]; + _pdfView.document = document; + _pdfView.document.delegate = self; + + } + if (document) { + [self setEnableAllButtons:!document.isLocked]; + } + else { + [self setEnableAllButtons:document]; + } + _pdfView.autoScales = YES; + _pdfView.displayMode = kPDFDisplaySinglePageContinuous; + _pdfView.translatesAutoresizingMaskIntoConstraints = NO; + + _pdfThumbnailView = [PDFThumbnailView new]; + _pdfThumbnailView.translatesAutoresizingMaskIntoConstraints = NO; + _pdfThumbnailView.thumbnailSize = CGSizeMake(40, 40); + [NSLayoutConstraint constraintWithItem:_pdfThumbnailView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:PDFThumbnailViewWidth].active = YES; + _pdfThumbnailView.layoutMode = PDFThumbnailLayoutModeVertical; + _pdfThumbnailView.PDFView = _pdfView; + _pdfThumbnailView.hidden = YES; + + [self updateActionButtonsAppearance]; +} + +- (void)setupClearApplyExitButtons { + [_pdfActionsView.clearButtonView setHidden:YES]; + [_pdfActionsView.applyButtonView setHidden:YES]; + [_pdfActionsView.exitButtonView setHidden:YES]; + + [self updateClearApplyAnnotationButtons]; + + [_pdfActionsView.clearAnnotationsButton addTarget:self action:@selector(clearButtonAction) forControlEvents:UIControlEventTouchUpInside]; + [_pdfActionsView.applyAnnotationsButton addTarget:self action:@selector(applybuttonAction) forControlEvents:UIControlEventTouchUpInside]; + [_pdfActionsView.exitAnnotationsButton addTarget:self action:@selector(exitButtonAction) forControlEvents:UIControlEventTouchUpInside]; +} + +- (void)updateClearApplyAnnotationButtons { + [_pdfActionsView.clearAnnotationsButton setEnabled:_freehandDrawingView.freehandDrawingExists]; + [_pdfActionsView.applyAnnotationsButton setEnabled:_freehandDrawingView.freehandDrawingExists]; +} + +- (void)thumbnailButtonAction { + [self animateViews:@[_pdfThumbnailView] setHidden:!_pdfThumbnailView.isHidden]; + [self updateActionButtonsAppearance]; + [_pdfView setAutoScales:YES]; +} + +- (void)annotationButtonAction { + + [self setPDFViewDisplayModeSinglePage:_isFreehandDrawingActive]; + + if (!_isFreehandDrawingActive && !_freehandDrawingView) { + [self addFreehandDrawingView]; + } + + [self setIsScibbleActive:YES]; + [self updateActionButtonsAppearance]; +} + +- (void)addAnnotations: (PDFAnnotation *)annotations { + [_pdfView.currentPage addAnnotation:annotations]; +} + +- (void)setPDFViewDisplayModeSinglePage:(BOOL) isContinuous { + PDFPage *currentPage = _pdfView.currentPage; + [_pdfView setScaleFactor:[_pdfView minScaleFactor]]; + [_pdfView setDisplayMode:isContinuous ? kPDFDisplaySinglePageContinuous : kPDFDisplaySinglePage]; + [_pdfView setScaleFactor:[_pdfView scaleFactorForSizeToFit]]; + [_pdfView goToPage:currentPage]; +} + +- (void)searchButtonAction { + [UIView animateWithDuration:0.5 animations:^{ + if (!_searchBar.isHidden) { + [self searchBarDismissKeyboard]; + } + _searchBar.hidden = !_searchBar.isHidden; + }]; + [self updateActionButtonsAppearance]; +} + +- (void)setEnableAllButtons:(BOOL)enable { + [_pdfActionsView.thumbnailActionButton setEnabled:enable]; + [_pdfActionsView.annotationActionButton setEnabled:enable]; + [_pdfActionsView.searchActionButton setEnabled:enable]; + [_pdfActionsView.shareActionButton setEnabled:enable]; +} + +- (void)updateActionButtonsAppearance { + _pdfActionsView.thumbnailActionButton.alpha = _pdfThumbnailView.isHidden ? PDFInactiveButtonAlpha : 1.0; + _pdfActionsView.annotationActionButton.alpha = !_isFreehandDrawingActive ? PDFInactiveButtonAlpha : 1.0; + _pdfActionsView.searchActionButton.alpha = _searchBar.isHidden ? PDFInactiveButtonAlpha : 1.0; + _pdfActionsView.shareActionButton.alpha = PDFInactiveButtonAlpha; + [self updateActionButtonAccessibilityLabels]; +} + +- (void)updateActionButtonAccessibilityLabels { + _pdfActionsView.thumbnailActionButton.accessibilityLabel = _pdfThumbnailView.isHidden ?ORKLocalizedString(@"AX_BUTTON_SHOW_PDF_THUMBNAIL" , nil) : ORKLocalizedString(@"AX_BUTTON_HIDE_PDF_THUMBNAIL", nil); + _pdfActionsView.annotationActionButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_ANNOTATE" , nil); + _pdfActionsView.searchActionButton.accessibilityLabel = _searchBar.isHidden ? ORKLocalizedString(@"AX_BUTTON_SHOW_SEARCH", nil) : ORKLocalizedString(@"AX_BUTTON_HIDE_SEARCH", nil); + _pdfActionsView.shareActionButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_SHARE", nil); +} + +- (void)shareButtonAction { + if (_isShareActive) { + + } + else { + if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectShareButton:)]) { + [self.delegate didSelectShareButton:_pdfActionsView.shareActionButton]; + } + } + _isShareActive = !_isShareActive; + [self updateActionButtonsAppearance]; +} + +- (void)setPdfURL:(NSURL *)pdfURL { + if (_pdfURL != pdfURL) { + _pdfURL = pdfURL; + _pdfView.document = nil; + PDFDocument *document; + if (pdfURL) { + document = [[PDFDocument alloc] initWithURL:pdfURL]; + _pdfView.document = document; + _pdfView.document.delegate = self; + } + if (document) { + [self setEnableAllButtons:!document.isLocked]; + _annotationsAdded = NO; + } + else { + [self setEnableAllButtons:document]; + } + } +} + +- (void)addFreehandDrawingView { + if (!_freehandDrawingView) { + _freehandDrawingView = [[ORKFreehandDrawingView alloc] initWithPDFView:_pdfView]; + _freehandDrawingView.translatesAutoresizingMaskIntoConstraints = NO; + _freehandDrawingView.backgroundColor = [UIColor clearColor]; + _freehandDrawingView.opaque = NO; + _freehandDrawingView.delegate = self; + [self addSubview:_freehandDrawingView]; + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_pdfView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_pdfView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_pdfView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_freehandDrawingView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_pdfView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + } +} + +- (void)setupKeyboardUnderlapView { + if (!_keyboardUnderlapView) { + _keyboardUnderlapView = [UIView new]; + } + _keyboardUnderlapView.translatesAutoresizingMaskIntoConstraints = NO; + _keyboardUnderlapView.hidden = YES; + [_keyboardUnderlapView setBackgroundColor:[UIColor clearColor]]; + [_parentStackView addArrangedSubview:_keyboardUnderlapView]; +} + + +- (void)setIsScibbleActive:(BOOL)isActive { + _isFreehandDrawingActive = isActive; + if (isActive) { + [self searchBarDismissKeyboard]; + [_pdfActionsView.thumbnailActionButton setHidden:YES]; + [_pdfActionsView.annotationActionButton setHidden:YES]; + [_pdfActionsView.searchActionButton setHidden:YES]; + [_pdfActionsView.shareActionButton setHidden:YES]; + + [_pdfActionsView.clearAnnotationsButton setHidden:NO]; + [_pdfActionsView.applyAnnotationsButton setHidden:NO]; + [_pdfActionsView.exitAnnotationsButton setHidden:NO]; + [self animateViews:@[ + _pdfThumbnailView, + _pdfActionsView.thumbnailActionView, + _pdfActionsView.annotationActionView, + _searchBar, + _pdfActionsView.searchActionView, + _pdfActionsView.shareActionView + ] + setHidden:YES]; + [self animateViews:@[ + _pdfActionsView.clearButtonView, + _pdfActionsView.applyButtonView, + _pdfActionsView.exitButtonView + ] setHidden:NO]; + + } + else { + NSMutableArray *allowedViews = [[NSMutableArray alloc] init]; + [_pdfActionsView.thumbnailActionButton setHidden:NO]; + [_pdfActionsView.annotationActionButton setHidden:NO]; + [_pdfActionsView.clearAnnotationsButton setHidden:YES]; + [_pdfActionsView.applyAnnotationsButton setHidden:YES]; + [_pdfActionsView.exitAnnotationsButton setHidden:YES]; + + [allowedViews addObjectsFromArray:@[_pdfActionsView.thumbnailActionView, + _pdfActionsView.annotationActionView]]; + if (!_hideSearchButton) { + + [_pdfActionsView.searchActionButton setHidden:NO]; + [allowedViews addObject:_pdfActionsView.searchActionView]; + } + if (!_hideShareButton) { + [_pdfActionsView.shareActionButton setHidden:NO]; + [allowedViews addObject:_pdfActionsView.shareActionView]; + } + [self animateViews:allowedViews setHidden:NO]; + [self animateViews:@[_pdfActionsView.clearButtonView, + _pdfActionsView.applyButtonView, + _pdfActionsView.exitButtonView] + setHidden:YES]; + } + [self updateActionButtonsAppearance]; +} + +- (void)clearButtonAction { + if (_freehandDrawingView.freehandDrawingPath && _freehandDrawingView.freehandDrawingExists) { + [_freehandDrawingView clear]; + } + [self updateClearApplyAnnotationButtons]; +} + +- (void)applybuttonAction { + if (_freehandDrawingView.freehandDrawingPath && _freehandDrawingView.freehandDrawingExists) { + CGRect annotationRect = _pdfView.documentView.bounds; + PDFAnnotation *annotation = [[PDFAnnotation alloc] initWithBounds:annotationRect forType:PDFAnnotationSubtypeInk withProperties:nil]; + annotation.border.lineWidth = 2.0; + + for (UIBezierPath *path in _freehandDrawingView.freehandDrawingPath) { + [annotation addBezierPath:path]; + } + [_pdfView.currentPage addAnnotation:annotation]; + + [_freehandDrawingView clear]; + _annotationsAdded = YES; + } + [self updateClearApplyAnnotationButtons]; +} + +- (void)exitButtonAction { + [self setPDFViewDisplayModeSinglePage:_isFreehandDrawingActive]; + + if (_isFreehandDrawingActive && _freehandDrawingView) { + [_freehandDrawingView removeFromSuperview]; + _freehandDrawingView = nil; + [self setIsScibbleActive:NO]; + } +} + +- (void)setHideThumbnailButton:(BOOL)hideThumbnailButton { + if (hideThumbnailButton) { + [_pdfActionsView.thumbnailActionView setHidden:YES]; + [_pdfThumbnailView setHidden:YES]; + } +} + +- (void)setHideAnnotationButton:(BOOL)hideAnnotationButton { + if (hideAnnotationButton) { + [_pdfActionsView.annotationActionView setHidden:YES]; + [_pdfActionsView.clearButtonView setHidden:YES]; + [_pdfActionsView.applyButtonView setHidden:YES]; + [_pdfActionsView.exitButtonView setHidden:YES]; + } +} + +- (void)setHideSearchButton:(BOOL)hideSearchButton { + if (hideSearchButton) { + [_pdfActionsView.searchActionView setHidden:YES]; + [_searchBar setHidden:YES]; + } +} + +- (void)setHideShareButton:(BOOL)hideShareButton { + [_pdfActionsView.shareActionView setHidden:hideShareButton]; +} + +- (void)setupConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_parentStackView); + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_parentStackView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_parentStackView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)searchBarDismissKeyboard { + [_searchBar resignFirstResponder]; + if (_keyboardUnderlapView) { + _keyboardUnderlapView.hidden = YES; + } +} + +- (BOOL)pdfModified { + return _annotationsAdded; +} + +- (void)animateViews:(NSArray *)views setHidden:(BOOL)hidden { + [UIView animateWithDuration:PDFhideViewAnimationDuration animations:^{ + for (UIView *view in views) { + [view setHidden:hidden]; + } + }]; +} + +- (PDFDocument *)getDocument { + return _pdfView.document; +} + +#pragma mark UISearchBarDelegate + +- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { + [_pdfView.document beginFindString:searchText withOptions:NSCaseInsensitiveSearch]; +} + +- (void)didMatchString:(PDFSelection *)instance { + instance.color = [UIColor yellowColor]; + [_pdfView setCurrentSelection:instance animate:YES]; +} + +- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { + [_pdfView.document beginFindString:searchBar.text withOptions:NSCaseInsensitiveSearch]; + [self searchBarDismissKeyboard]; +} + +- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { + [searchBar resignFirstResponder]; +} + +- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil]; +} + +- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar { + if (_keyboardUnderlapView) { + _keyboardUnderlapView.hidden = YES; + } +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWillAppear:(NSNotification *)aNotification { + + NSDictionary *userInfo = aNotification.userInfo; + CGSize keyboardSize = ((NSValue *)userInfo[UIKeyboardFrameEndUserInfoKey]).CGRectValue.size; + // Offset with assumed view controller's navigation container's height. + keyboardSize.height = keyboardSize.height - 200.0; + + if (_keyboardUnderlapView && _keyboardUnderlapView.isHidden) { + [_keyboardUnderlapView removeFromSuperview]; + [NSLayoutConstraint constraintWithItem:_keyboardUnderlapView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:keyboardSize.height].active = YES; + _keyboardUnderlapView.hidden = NO; + [_parentStackView insertArrangedSubview:_keyboardUnderlapView atIndex:[[_parentStackView subviews] count]]; + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)updateShareButton { + _isShareActive = NO; + [self updateActionButtonsAppearance]; +} + +#pragma mark ORKFreehandDrawingViewDelegate + +- (void)freehandDrawingViewDidEditImage:(ORKFreehandDrawingView *)freehandDrawingView { + [self updateClearApplyAnnotationButtons]; +} + +#pragma mark PDFDocumentDelegate + +- (void)documentDidUnlock:(NSNotification *)notification { + [self setEnableAllButtons:YES]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.h new file mode 100755 index 0000000..50cceb8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + + +ORK_CLASS_AVAILABLE +@interface ORKPDFViewerStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.m new file mode 100755 index 0000000..58afd5f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepViewController.m @@ -0,0 +1,233 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPDFViewerStepViewController.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" + +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKPDFViewerStep.h" +#import "ORKPDFViewerStepView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@interface ORKPDFViewerStepViewController() + +@end + +@implementation ORKPDFViewerStepViewController { + NSArray *_constraints; + ORKPDFViewerStepView *_pdfView; + + NSString *_newFilename; +} + +- (ORKPDFViewerStep *)pdfViewerStep { + return (ORKPDFViewerStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_pdfView removeFromSuperview]; + _pdfView = nil; + + if (self.step && [self isViewLoaded]) { + _pdfView = [ORKPDFViewerStepView new]; + [self hidePDFViewerButtons]; + _pdfView.delegate = self; + [self.view addSubview:_pdfView]; + [self setNavigationFooterView]; + [self setupConstraints]; + } +} + +- (void)hidePDFViewerButtons { + ORKPDFViewerStep *pdfStep = [self pdfViewerStep]; + + _pdfView.hideThumbnailButton = ((pdfStep.actionBarOption & ORKPDFViewerActionBarOptionExcludeThumbnail) == ORKPDFViewerActionBarOptionExcludeThumbnail); + _pdfView.hideAnnotationButton = ((pdfStep.actionBarOption & ORKPDFViewerActionBarOptionExcludeAnnotation) == ORKPDFViewerActionBarOptionExcludeAnnotation); + _pdfView.hideSearchButton = ((pdfStep.actionBarOption & ORKPDFViewerActionBarOptionExcludeSearch) == ORKPDFViewerActionBarOptionExcludeSearch); + _pdfView.hideShareButton = ((pdfStep.actionBarOption & ORKPDFViewerActionBarOptionExcludeShare) == ORKPDFViewerActionBarOptionExcludeShare); +} + +- (void)setNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = [ORKNavigationContainerView new]; + } + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.hidden = self.isBeingReviewed; + [_navigationFooterView updateContinueAndSkipEnabled]; + [self.view addSubview:_navigationFooterView]; +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _pdfView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + + UIView *viewForiPad = [self viewForiPadLayoutConstraints]; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_pdfView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_pdfView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_pdfView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_pdfView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_navigationFooterView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self stepDidChange]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + if (_pdfView) { + _pdfView.pdfURL = [self pdfViewerStep].pdfURL; + } +} + +- (void)createNewPDFFile { + NSURL *fileURL = [self.outputDirectory URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", _newFilename]]; + NSData *pdfData = [[_pdfView getDocument] dataRepresentation]; + [[NSFileManager defaultManager] createFileAtPath:[fileURL path] contents:pdfData attributes:nil]; +} + + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + if ([_pdfView pdfModified]) { + if (!_newFilename) { + _newFilename = [[NSUUID UUID] UUIDString]; + [self createNewPDFFile]; + } + NSURL *fileURL = [self.outputDirectory URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", _newFilename]]; + + NSDate *now = stepResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:stepResult.results]; + ORKFileResult *fileResult = [[ORKFileResult alloc] initWithIdentifier:self.step.identifier]; + fileResult.startDate = stepResult.startDate; + fileResult.endDate = now; + fileResult.contentType = @"document/pdf"; + fileResult.fileURL = fileURL; + [results addObject:fileResult]; + stepResult.results = [results copy]; + } + return stepResult; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + [super setCancelButtonItem:cancelButtonItem]; +} + +#pragma mark ORKPDFViewerStepViewDelegate + +- (void)didSelectShareButton:(id)sender { + NSData *pdfData = [[_pdfView getDocument] dataRepresentation]; + + UIActivityViewController * activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[@"sendPDF", pdfData] applicationActivities:nil]; + [activityViewController setCompletionWithItemsHandler:^(UIActivityType _Nullable activityType, BOOL completed, NSArray * _Nullable returnedItems, NSError * _Nullable activityError) { + [_pdfView updateShareButton]; + }]; + + if ( [activityViewController respondsToSelector:@selector(popoverPresentationController)] ) { + activityViewController.popoverPresentationController.sourceView = sender; + UIView *shareButtonView = (UIView *)sender; + activityViewController.popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(shareButtonView.bounds), CGRectGetMidY(shareButtonView.bounds),0,0); + + } + [self presentViewController:activityViewController animated:YES completion:nil]; +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView_Internal.h new file mode 100755 index 0000000..d62b45e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPDFViewerStepView_Internal.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPDFViewerStepView.h" + + +@interface ORKPDFViewerStepView () + +@property (nonatomic, assign)BOOL hideThumbnailButton; +@property (nonatomic, assign)BOOL hideAnnotationButton; +@property (nonatomic, assign)BOOL hideSearchButton; +@property (nonatomic, assign)BOOL hideShareButton; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.h new file mode 100755 index 0000000..83126f4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.h @@ -0,0 +1,126 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKPageStep` class is a concrete subclass of `ORKStep`, used for presenting a subgrouping of + `ORKStepViewController` views using a `UIPageViewController`. + + To use `ORKPageStep`, instantiate the object, fill in its properties, and include it in a task. + Next, create a task view controller for the task and present it. + + The base class implementation will instatiate a read-only `ORKPageStepViewController` to display + a series of substeps. For each substep, the `ORKStepViewController` will be instantiated and added + as a child of the `UIPageViewController` contained by the parent `ORKPageStepViewController`.. + + Customization can be handled by overriding the base class implementations in either `ORKPageStep` + or `ORKPageStepViewController`. + */ + +ORK_CLASS_AVAILABLE +@interface ORKPageStep : ORKStep + +/** + Returns an initialized page step using the specified identifier and array of steps. + + @param identifier The unique identifier for the step. + @param steps An array of `ORKStep` objects in the order in which they should be presented. + + @return An initialized page step. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + steps:(nullable NSArray *)steps NS_DESIGNATED_INITIALIZER; + +/** + Returns a page step initialized from data in the given unarchiver. + + A page step can be serialized and deserialized with `NSKeyedArchiver`. Note + that this serialization includes strings that might need to be localized. + + @param aDecoder The coder from which to initialize the ordered task. + + @return An initialized page step. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + The array of steps in the page step. (read-only) + + Each element in the array must be a subclass of `ORKStep`. + The associated page step view controller presents the steps in + array order. + */ +@property (nonatomic, copy, readonly) NSArray *steps; + +/** + Returns the step after the specified step, if there is one. + + The page view controller calls this method to determine the step to display after the specified step. + The page view controller can also call this method every time the result updates, to determine if the + new result changes which steps are available. + + @param identifier The reference step identifier. Pass `nil` to specify the first step. + @param result A snapshot of the current set of results. + + @return The step that comes after the specified step, or `nil` if there isn't one. + */ +- (nullable ORKStep *)stepAfterStepWithIdentifier:(nullable NSString *)identifier withResult:(ORKTaskResult *)result; + +/** + Returns the step that precedes the specified step, if there is one. + + The page view controller calls this method to determine the step to display before the specified step. + The page view controller can also call this method every time the result changes, to determine if the + new result changes which steps are available. + + @param identifier The reference step identifier. + @param result A snapshot of the current set of results. + + @return The step that precedes the reference step, or `nil` if there isn't one. + */ +- (nullable ORKStep *)stepBeforeStepWithIdentifier:(NSString *)identifier withResult:(ORKTaskResult *)result; + + +/** + Returns the step that matches the specified identifier. + + @param identifier The identifier of the step to restore. + @return The step that matches the specified identifier, or `nil` if there isn't one. + */ +- (nullable ORKStep *)stepWithIdentifier:(NSString *)identifier; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.m new file mode 100755 index 0000000..0b4e92d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep.m @@ -0,0 +1,156 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKPageStep_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKPageStepViewController.h" +#import "ORKResult.h" + + +@implementation ORKPageStep + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [self initWithIdentifier:identifier steps:@[]]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray *)steps { + self = [super initWithIdentifier:identifier]; + if (self) { + [self ork_initializePageTask:[[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]]; + } + return self; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier pageTask:(ORKOrderedTask *)task { + self = [super initWithIdentifier:identifier]; + if (self) { + [self ork_initializePageTask:task]; + } + return self; +} + +- (void)ork_initializePageTask:(ORKOrderedTask *)task { + _pageTask = [task copy]; + [self validateParameters]; +} + +- (NSArray *)steps { + return self.pageTask.steps; +} + +#pragma mark - view controller instantiation + ++ (Class)stepViewControllerClass { + return [ORKPageStepViewController class]; +} + +#pragma mark - permissions + +- (ORKPermissionMask)requestedPermissions { + if ([self.pageTask respondsToSelector:@selector(requestedPermissions)]) { + return [self.pageTask requestedPermissions]; + } + return ORKPermissionNone; +} + +- (NSSet *)requestedHealthKitTypesForReading { + if ([self.pageTask respondsToSelector:@selector(requestedHealthKitTypesForReading)]) { + return [self.pageTask requestedHealthKitTypesForReading]; + } + return nil; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPageStep *copy = [super copyWithZone:zone]; + copy->_pageTask = [_pageTask copyWithZone:zone]; + return copy; +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return ([super isEqual:object] + && ORKEqualObjects(self.pageTask, castObject.pageTask)); +} + +- (NSUInteger)hash { + return [super hash] ^ [self.pageTask hash]; +} + +#pragma mark - step handling + +- (void)validateParameters { + if ([self.pageTask respondsToSelector:@selector(validateParameters)]) { + [self.pageTask validateParameters]; + } +} + +- (ORKStep *)stepAfterStepWithIdentifier:(NSString *)identifier withResult:(ORKTaskResult *)result { + ORKStep *step = (identifier != nil) ? [self stepWithIdentifier:identifier] : nil; + return [self.pageTask stepAfterStep:step withResult:result]; +} + +- (ORKStep *)stepBeforeStepWithIdentifier:(NSString *)identifier withResult:(ORKTaskResult *)result { + ORKStep *step = (identifier != nil) ? [self stepWithIdentifier:identifier] : nil; + return [self.pageTask stepBeforeStep:step withResult:result]; +} + +- (ORKStep *)stepWithIdentifier:(NSString *)identifier { + return [self.pageTask stepWithIdentifier:identifier]; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, pageTask); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, pageTask, ORKOrderedTask); + } + return self; +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.h new file mode 100755 index 0000000..3220d08 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKPageStepViewController : ORKStepViewController + +/** + The `ORKPageStep` associated with this view controller. + */ +@property (nonatomic, readonly, nullable) ORKPageStep *pageStep; + +/** + Returns the step view controller to associate with this step. By default, this will + return the step view controller instantiated by the given step. + + @returns `ORKStepViewController` subclass for this step. + */ +- (ORKStepViewController *)stepViewControllerForStep:(ORKStep *)step; + +/** + Returns an `ORKTaskResultSource` for the steps that are included as substeps for this + page view controller. + + @returns `ORKTaskResultSource` for the step results + */ +- (id )resultSource; + +/** + Go to the given step. + + @param step The step to go to + @param direction The direction in which navigate + @param animated Should the change of view controllers be animated. + */ +- (void)goToStep:(ORKStep *)step direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.m new file mode 100755 index 0000000..e229c95 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStepViewController.m @@ -0,0 +1,308 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPageStepViewController.h" +#import +#import "ORKStepViewController_Internal.h" +#import "UIBarButtonItem+ORKBarButtonItem.h" +#import "ORKHelpers_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKResult_Private.h" +#import "ORKStep_Private.h" + +typedef NS_ENUM(NSInteger, ORKPageNavigationDirection) { + ORKPageNavigationDirectionNone = 0, + ORKPageNavigationDirectionForward = 1, + ORKPageNavigationDirectionReverse = -1 +} ORK_ENUM_AVAILABLE; + +@interface ORKPageStepViewController () + +@property (nonatomic, readonly) ORKPageResult *initialResult; +@property (nonatomic, readonly) ORKPageResult *pageResult; +@property (nonatomic, readonly) UIPageViewController *pageViewController; +@property (nonatomic, copy, readonly, nullable) NSString *currentStepIdentifier; +@property (nonatomic, readonly) ORKStepViewController *currentStepViewController; + +@end + + +@implementation ORKPageStepViewController + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + self = [super initWithStep:step result:result]; + if (self && [step isKindOfClass:[ORKPageStep class]] && [result isKindOfClass:[ORKStepResult class]]) { + _pageResult = [[ORKPageResult alloc] initWithPageStep:(ORKPageStep *)step stepResult:(ORKStepResult *)result]; + _initialResult = [_pageResult copy]; + } + return self; +} + +- (ORKPageStep *)pageStep { + if ([self.step isKindOfClass:[ORKPageStep class]]) { + return (ORKPageStep *)self.step; + } + return nil; +} + +- (ORKStepViewController *)currentStepViewController { + UIViewController *viewController = [self.pageViewController.viewControllers firstObject]; + if ([viewController isKindOfClass:[ORKStepViewController class]]) { + return (ORKStepViewController *)viewController; + } + return nil; +} + +@synthesize pageResult = _pageResult; +- (ORKPageResult *)pageResult { + if (_pageResult == nil) { + _pageResult = [[ORKPageResult alloc] initWithIdentifier:self.step.identifier]; + } + if (!ORKEqualObjects(_pageResult.outputDirectory, self.outputDirectory)) { + _pageResult = [_pageResult copyWithOutputDirectory:self.outputDirectory]; + } + return _pageResult; +} + +- (void)stepDidChange { + if (![self isViewLoaded]) { + return; + } + + _currentStepIdentifier = nil; + _pageResult = nil; + [self navigateInDirection:ORKPageNavigationDirectionNone animated:NO]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Prepare pageViewController + _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll + navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal + options:nil]; + _pageViewController.delegate = self; + + if ([_pageViewController respondsToSelector:@selector(edgesForExtendedLayout)]) { + _pageViewController.edgesForExtendedLayout = UIRectEdgeNone; + } + + _pageViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + _pageViewController.view.frame = self.view.bounds; + [self.view addSubview:_pageViewController.view]; + [self addChildViewController:_pageViewController]; + [_pageViewController didMoveToParentViewController:self]; + + [self navigateInDirection:ORKPageNavigationDirectionNone animated:NO]; +} + +- (void)updateBarButtonItems { + if ((self.currentStepIdentifier == nil) || ([self stepInDirection:ORKPageNavigationDirectionReverse] == nil)) { + [super updateBarButtonItems]; + } else { + self.navigationItem.leftBarButtonItem = [self goToPreviousPageButtonItem]; + } +} + +- (UIBarButtonItem *)goToPreviousPageButtonItem { + // Hide the back navigation item if not allowed + if (!self.currentStepViewController.step.allowsBackNavigation) { + return nil; + } + UIBarButtonItem *button = [UIBarButtonItem ork_backBarButtonItemWithTarget:self action:@selector(goToPreviousPage)]; + button.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + return button; +} + +- (void)goToPreviousPage { + [self navigateInDirection:ORKPageNavigationDirectionReverse animated:YES]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (void)willNavigateDirection:(ORKStepViewControllerNavigationDirection)direction { + // update the current step based on the direction of navigation + if (direction == ORKStepViewControllerNavigationDirectionForward) { + _currentStepIdentifier = nil; + } + else { + NSString *lastStepIdentifier = [[self.pageResult.results lastObject] identifier]; + if ([self.pageStep stepWithIdentifier:lastStepIdentifier] != nil) { + _currentStepIdentifier = lastStepIdentifier; + } + } + [super willNavigateDirection:direction]; +} + +#pragma mark - result handling + +- (id )resultSource { + return self.pageResult; +} + +- (ORKStepResult *)result { + ORKStepResult *result = [super result]; + NSArray *pageResults = [self.pageResult flattenResults]; + result.results = [result.results arrayByAddingObjectsFromArray:pageResults] ? : pageResults; + return result; +} + + +#pragma mark ORKStepViewControllerDelegate + +- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction { + NSInteger delta = (direction == ORKStepViewControllerNavigationDirectionForward) ? 1 : -1; + if (direction == ORKStepViewControllerNavigationDirectionForward) { + // If going forward, update the page result with the final stepResult + ORKStepResult *stepResult = stepViewController.result; + [self.pageResult addStepResult:stepResult]; + } + [self navigateInDirection:delta animated:YES]; +} + +- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController { + [self.pageResult addStepResult:stepViewController.result]; + [self notifyDelegateOnResultChange]; +} + +- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(NSError *)error { + ORKStrongTypeOf(self.delegate) delegate = self.delegate; + if ([delegate respondsToSelector:@selector(stepViewControllerDidFail:withError:)]) { + [delegate stepViewControllerDidFail:self withError:error]; + } +} + +- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController { + return [self hasNextStep] || ([self stepInDirection:ORKPageNavigationDirectionForward] != nil); +} + +- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController { + return [self hasPreviousStep] || ([self stepInDirection:ORKPageNavigationDirectionReverse] != nil); +} + +- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + ORKStrongTypeOf(self.delegate) delegate = self.delegate; + if ([delegate respondsToSelector:@selector(stepViewController:recorder:didFailWithError:)]) { + [delegate stepViewController:self recorder:recorder didFailWithError:error]; + } +} + +#pragma mark Navigation + +- (ORKStep *)stepInDirection:(ORKPageNavigationDirection)delta { + if ((delta == ORKPageNavigationDirectionNone) && (self.currentStepIdentifier != nil)) { + return [self.pageStep stepWithIdentifier:self.currentStepIdentifier]; + } else if ((delta >= 0) || (self.currentStepIdentifier == nil)) { + return [self.pageStep stepAfterStepWithIdentifier:self.currentStepIdentifier withResult:self.pageResult]; + } else { + [self.pageResult removeStepResultWithIdentifier:self.currentStepIdentifier]; + return [self.pageStep stepBeforeStepWithIdentifier:self.currentStepIdentifier withResult:self.pageResult]; + } +} + +- (void)navigateInDirection:(ORKPageNavigationDirection)delta animated:(BOOL)animated { + ORKStep *step = [self stepInDirection:delta]; + if (step == nil) { + if (delta < 0) { + [self goBackward]; + } + else { + [self goForward]; + } + } else { + UIPageViewControllerNavigationDirection direction = (!animated || delta >= 0) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse; + [self goToStep:step direction:direction animated:animated]; + } +} + +- (ORKStepViewController *)stepViewControllerForStep:(ORKStep *)step { + ORKStepResult *stepResult = [self.pageResult stepResultForStepIdentifier:step.identifier]; + if (stepResult == nil) { + // If the pageResult does not carry a step result, then check the initial result + stepResult = [self.initialResult stepResultForStepIdentifier:step.identifier]; + } + ORKStepViewController *viewController = [step instantiateStepViewControllerWithResult:stepResult]; + return viewController; +} + +- (void)goToStep:(ORKStep *)step direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated { + ORKStepViewController *stepViewController = [self stepViewControllerForStep:step]; + + if (!stepViewController) { + ORK_Log_Debug("No view controller!"); + [self goForward]; + return; + } + + // Flush the page result + [self.pageResult removeStepResultsAfterStepWithIdentifier: step.identifier]; + + // Setup view controller + stepViewController.delegate = self; + stepViewController.cancelButtonItem = self.cancelButtonItem; + stepViewController.outputDirectory = self.outputDirectory; + + // Setup page direction + ORKAdjustPageViewControllerNavigationDirectionForRTL(&direction); + + _currentStepIdentifier = step.identifier; + __weak typeof(self) weakSelf = self; + + // unregister ScrollView to clear hairline + [self.taskViewController setRegisteredScrollView:nil]; + + [self.pageViewController setViewControllers:@[stepViewController] direction:direction animated:animated completion:^(BOOL finished) { + if (finished) { + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + [strongSelf updateBarButtonItems]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, strongSelf.navigationItem.leftBarButtonItem); + } + }]; +} + +#pragma mark - UIStateRestoring + +static NSString *const _ORKCurrentStepIdentifierRestoreKey = @"currentStepIdentifier"; +static NSString *const _ORKPageResultRestoreKey = @"pageResult"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + [coder encodeObject:_currentStepIdentifier forKey:_ORKCurrentStepIdentifierRestoreKey]; + [coder encodeObject:_pageResult forKey:_ORKPageResultRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + _currentStepIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKCurrentStepIdentifierRestoreKey]; + _pageResult = [coder decodeObjectOfClass:[ORKPageResult class] forKey:_ORKPageResultRestoreKey]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep_Private.h new file mode 100755 index 0000000..1b289a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPageStep_Private.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + + +@interface ORKPageStep () + +@property (nonatomic, copy, readonly) ORKOrderedTask *pageTask; + +- (instancetype)initWithIdentifier:(NSString *)identifier + pageTask:(ORKOrderedTask *)task NS_DESIGNATED_INITIALIZER; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.h new file mode 100755 index 0000000..7c06c8c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKPasscodeResult` class records the results of a passcode step. + + The passcode result object contains a boolean indicating whether the passcode was saved or not. + */ +ORK_CLASS_AVAILABLE +@interface ORKPasscodeResult : ORKResult + +/** + A boolean indicating if a passcode was saved or not. + */ +@property (nonatomic, assign, getter=isPasscodeSaved) BOOL passcodeSaved; + +/** + A boolean that indicates if the user has enabled/disabled TouchID + */ +@property (nonatomic, assign, getter=isTouchIdEnabled) BOOL touchIdEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.m new file mode 100755 index 0000000..1093087 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeResult.m @@ -0,0 +1,79 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKPasscodeResult + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_BOOL(aCoder, passcodeSaved); + ORK_ENCODE_BOOL(aCoder, touchIdEnabled); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_BOOL(aDecoder, passcodeSaved); + ORK_DECODE_BOOL(aDecoder, touchIdEnabled); + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.isPasscodeSaved == castObject.isPasscodeSaved && + self.isTouchIdEnabled == castObject.isTouchIdEnabled); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPasscodeResult *result = [super copyWithZone:zone]; + result.passcodeSaved = self.isPasscodeSaved; + result.touchIdEnabled = self.isTouchIdEnabled; + return result; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; passcodeSaved: %d touchIDEnabled: %d%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.isPasscodeSaved, self.isTouchIdEnabled, self.descriptionSuffix]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.h new file mode 100755 index 0000000..2b0ced5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.h @@ -0,0 +1,91 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An enumeration of values used in `ORKPasscodeStepViewController` to indicate the type of flow used + by the view controller. + */ +typedef NS_ENUM(NSUInteger, ORKPasscodeFlow) { + ORKPasscodeFlowCreate, + ORKPasscodeFlowAuthenticate, + ORKPasscodeFlowEdit +}; + +/** + An `ORKPasscodeStep` object provides the participant a passcode creation step. + + It is recommended to use a passcode step as part of the consent process to ensure + that the participant signing the consent is the same participant completing other + modules within that context. + */ +ORK_CLASS_AVAILABLE +@interface ORKPasscodeStep : ORKStep + +/** + Returns a new passcode step with the specified identifier and passcode flow. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param passcodeFlow The passcode flow to be used for the step. + */ ++ (instancetype)passcodeStepWithIdentifier:(NSString *)identifier + passcodeFlow:(ORKPasscodeFlow)passcodeFlow; + +/** + The passcode flow to be used for the step. + + The default value of this property is `ORKPasscodeFlowCreate`. + */ +@property (nonatomic) ORKPasscodeFlow passcodeFlow; + +/** + The passcode type to be used for the step. + + The default value of this property is `ORKPasscodeType4Digit`. + */ +@property (nonatomic) ORKPasscodeType passcodeType; + +/** + This will toggle if biometrics (TouchId or FaceId) will be used or not + + The default value of this property is `YES` + */ +@property (nonatomic) BOOL useBiometrics; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.m new file mode 100755 index 0000000..0db6269 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStep.m @@ -0,0 +1,94 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeStep.h" + +#import "ORKPasscodeStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKPasscodeStep + ++ (Class)stepViewControllerClass { + return [ORKPasscodeStepViewController class]; +} + ++ (instancetype)passcodeStepWithIdentifier:(NSString *)identifier + passcodeFlow:(ORKPasscodeFlow)passcodeFlow { + + ORKPasscodeStep *step = [[ORKPasscodeStep alloc] initWithIdentifier:identifier]; + step.passcodeFlow = passcodeFlow; + step.showsProgress = NO; + step.useBiometrics = YES; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_INTEGER(aDecoder, passcodeType); + ORK_DECODE_ENUM(aDecoder, passcodeFlow); + ORK_DECODE_BOOL(aDecoder, useBiometrics); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_INTEGER(aCoder, passcodeType); + ORK_ENCODE_ENUM(aCoder, passcodeFlow); + ORK_ENCODE_BOOL(aCoder, useBiometrics); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKPasscodeStep *step = [super copyWithZone:zone]; + step.passcodeType = self.passcodeType; + step.passcodeFlow = self.passcodeFlow; + step.useBiometrics = self.useBiometrics; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.passcodeFlow == castObject.passcodeFlow && + self.passcodeType == castObject.passcodeType && + self.useBiometrics == castObject.useBiometrics); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.h new file mode 100755 index 0000000..470ec04 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKPasscodeTextField; + +@interface ORKPasscodeStepView : ORKStepContainerView + +@property (nonatomic, strong, readonly) ORKPasscodeTextField *textField; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.m new file mode 100755 index 0000000..3e3d54f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepView.m @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeStepView.h" +#import "ORKStepContainerView_Private.h" + +#import "ORKStepHeaderView_Internal.h" +#import "ORKTextFieldView.h" + + +@implementation ORKPasscodeStepView { + ORKPasscodeTextField *_textField; +} + +- (instancetype)init { + self = [super init]; + if (self) { + // Additional configuration for the passcode text field. + _textField = [ORKPasscodeTextField new]; + _textField.translatesAutoresizingMaskIntoConstraints = NO; + self.customContentView = _textField; + + // Setting image view with app icon (if available). + NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary]; + NSString *icon = [[infoPlist valueForKeyPath:@"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles"] lastObject]; + self.titleIconImage = [UIImage imageNamed:icon]; + } + return self; +} + +- (ORKPasscodeTextField *)textField { + return _textField; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.h new file mode 100755 index 0000000..b32f4e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An `ORKPasscodeStepViewController` object is the view controller for an `ORKPasscodeStep` object. + + A passcode view controller can be instantiated indirectly by adding a passcode step to a consent task + and present the task using a task view controller. When appropriate, the task view controller instantiates the step + view controller for the step. + */ +@interface ORKPasscodeStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.m new file mode 100755 index 0000000..4fe894f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController.m @@ -0,0 +1,812 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeStepViewController.h" +#import "ORKPasscodeStepViewController_Internal.h" + +#import "ORKPasscodeStepView.h" +#import "ORKStepView_Private.h" +#import "ORKTextFieldView.h" + +#import "ORKPasscodeViewController.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKCollectionResult_Private.h" +#import "ORKPasscodeResult.h" +#import "ORKPasscodeStep.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKResult.h" + +#import "ORKKeychainWrapper.h" +#import "ORKHelpers_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import +#import + +static CGFloat const kForgotPasscodeVerticalPadding = 50.0f; +static CGFloat const kForgotPasscodeHorizontalPadding = 30.0f; +static CGFloat const kForgotPasscodeHeight = 100.0f; + +@implementation ORKPasscodeStepViewController { + ORKPasscodeStepView *_passcodeStepView; + CGFloat _originalForgotPasscodeY; + UIButton* _forgotPasscodeButton; + UITextField *_accessibilityPasscodeField; + NSMutableString *_passcode; + NSMutableString *_confirmPasscode; + NSInteger _numberOfFilledBullets; + ORKPasscodeState _passcodeState; + BOOL _shouldResignFirstResponder; + BOOL _isChangingState; + BOOL _isTouchIdAuthenticated; + BOOL _isPasscodeSaved; + LAContext *_touchContext; + ORKPasscodeType _authenticationPasscodeType; + BOOL _useTouchId; +} + +- (ORKPasscodeStep *)passcodeStep { + return (ORKPasscodeStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_accessibilityPasscodeField removeFromSuperview]; + _accessibilityPasscodeField = nil; + + [_passcodeStepView removeFromSuperview]; + _passcodeStepView = nil; + + if (self.step && [self isViewLoaded]) { + + _accessibilityPasscodeField = [UITextField new]; + _accessibilityPasscodeField.hidden = YES; + _accessibilityPasscodeField.delegate = self; + _accessibilityPasscodeField.secureTextEntry = YES; + _accessibilityPasscodeField.keyboardType = UIKeyboardTypeNumberPad; + [self.view addSubview:_accessibilityPasscodeField]; + + _passcodeStepView = [ORKPasscodeStepView new]; + _passcodeStepView.stepText = [self passcodeStep].text; + _passcodeStepView.textField.delegate = self; + + [_passcodeStepView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showHideKeyboard)]]; + + [self.view addSubview:_passcodeStepView]; + _navigationFooterView = _passcodeStepView.navigationFooterView; + _navigationFooterView.neverHasContinueButton = YES; + _navigationFooterView.skipEnabled = NO; + [_navigationFooterView updateContinueAndSkipEnabled]; + + _passcode = [NSMutableString new]; + _confirmPasscode = [NSMutableString new]; + _numberOfFilledBullets = 0; + _shouldResignFirstResponder = NO; + _isChangingState = NO; + _isTouchIdAuthenticated = NO; + _isPasscodeSaved = NO; + _useTouchId = [self passcodeStep].useBiometrics; + + // If this has text, we should add the forgot passcode button with this title + if ([self hasForgotPasscode]) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; + + CGFloat x = kForgotPasscodeHorizontalPadding; + _originalForgotPasscodeY = self.view.bounds.size.height - kForgotPasscodeVerticalPadding - kForgotPasscodeHeight; + CGFloat width = self.view.bounds.size.width - 2 * kForgotPasscodeHorizontalPadding; + + UIButton *forgotPasscodeButton = [ORKTextButton new]; + forgotPasscodeButton.contentEdgeInsets = (UIEdgeInsets){12, 10, 8, 10}; + forgotPasscodeButton.frame = CGRectMake(x, _originalForgotPasscodeY, width, kForgotPasscodeHeight); + + NSString *buttonTitle = [self forgotPasscodeButtonText]; + [forgotPasscodeButton setTitle:buttonTitle forState:UIControlStateNormal]; + [forgotPasscodeButton addTarget:self + action:@selector(forgotPasscodeTapped) + forControlEvents:UIControlEventTouchUpInside]; + + [self.view addSubview:forgotPasscodeButton]; + _forgotPasscodeButton = forgotPasscodeButton; + } + + // Set the starting passcode state and textfield based on flow. + ORKPasscodeStep *passcodeStep = [self passcodeStep]; + switch (passcodeStep.passcodeFlow) { + case ORKPasscodeFlowCreate: + _passcodeStepView.textField.numberOfDigits = [self numberOfDigitsForPasscodeType:passcodeStep.passcodeType]; + [self changeStateTo:ORKPasscodeStateEntry]; + break; + + case ORKPasscodeFlowAuthenticate: + [self setValuesFromKeychain]; + _passcodeStepView.textField.numberOfDigits = [self numberOfDigitsForPasscodeType:_authenticationPasscodeType]; + [self changeStateTo:ORKPasscodeStateEntry]; + break; + + case ORKPasscodeFlowEdit: + [self setValuesFromKeychain]; + _passcodeStepView.textField.numberOfDigits = [self numberOfDigitsForPasscodeType:_authenticationPasscodeType]; + [self changeStateTo:ORKPasscodeStateOldEntry]; + break; + } + + // If Touch ID was enabled then present it for authentication flow. + if (_useTouchId && + passcodeStep.passcodeFlow == ORKPasscodeFlowAuthenticate) { + [self promptTouchId]; + } + + // Check to see if cancel button should be set or not. + if (self.passcodeDelegate && + [self.passcodeDelegate respondsToSelector:@selector(passcodeViewControllerDidCancel:)]) { + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) + style:UIBarButtonItemStylePlain + target:self + action:@selector(cancelButtonAction)]; + } + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(makePasscodeViewBecomeFirstResponder) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + [self setupConstraints]; + } +} + +- (void)showHideKeyboard { + if ([_accessibilityPasscodeField isFirstResponder]) { + [self makePasscodeViewResignFirstResponder]; + } + else { + [self makePasscodeViewBecomeFirstResponder]; + } +} + +- (void)setupConstraints { + _passcodeStepView.translatesAutoresizingMaskIntoConstraints = NO; + + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:_passcodeStepView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_passcodeStepView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_passcodeStepView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_passcodeStepView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + // Destructive: Only clear the passcode when the step starts in creation mode + if ([self passcodeStep].passcodeFlow == ORKPasscodeFlowCreate) { + [self removePasscodeFromKeychain]; + } + + if (!_shouldResignFirstResponder) { + [self.view layoutIfNeeded]; // layout pass might be required before showing the keyboard + [self makePasscodeViewBecomeFirstResponder]; + } +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + [self makePasscodeViewResignFirstResponder]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; +} + +- (void)updatePasscodeView { + + switch (_passcodeState) { + case ORKPasscodeStateEntry: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_PROMPT_MESSAGE", nil); + _numberOfFilledBullets = 0; + _accessibilityPasscodeField.text = @""; + _passcode = [NSMutableString new]; + _confirmPasscode = [NSMutableString new]; + break; + + case ORKPasscodeStateConfirm: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_CONFIRM_MESSAGE", nil); + _numberOfFilledBullets = 0; + _accessibilityPasscodeField.text = @""; + _confirmPasscode = [NSMutableString new]; + break; + + case ORKPasscodeStateSaved: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_SAVED_MESSAGE", nil); + _passcodeStepView.stepDetailText = @""; + _passcodeStepView.textField.hidden = YES; + [self makePasscodeViewResignFirstResponder]; + break; + + case ORKPasscodeStateOldEntry: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_OLD_ENTRY_MESSAGE", nil); + _numberOfFilledBullets = 0; + _accessibilityPasscodeField.text = @""; + _passcode = [NSMutableString new]; + _confirmPasscode = [NSMutableString new]; + break; + + case ORKPasscodeStateNewEntry: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_NEW_ENTRY_MESSAGE", nil); + _numberOfFilledBullets = 0; + _accessibilityPasscodeField.text = @""; + _passcode = [NSMutableString new]; + _confirmPasscode = [NSMutableString new]; + break; + + case ORKPasscodeStateConfirmNewEntry: + _passcodeStepView.stepText = ORKLocalizedString(@"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE", nil); + _numberOfFilledBullets = 0; + _accessibilityPasscodeField.text = @""; + _confirmPasscode = [NSMutableString new]; + break; + } + + // Regenerate the textField. + [_passcodeStepView.textField updateTextWithNumberOfFilledBullets:_numberOfFilledBullets]; + + // Enable input. + _isChangingState = NO; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + + self.internalContinueButtonItem = nil; + self.internalDoneButtonItem = nil; +} + +- (BOOL)showValidityAlertWithMessage:(NSString *)text { + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:ORKLocalizedString(@"PASSCODE_INVALID_ALERT_TITLE", nil) + message:text + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_OK", nil) + style:UIAlertActionStyleDefault + handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; + + return YES; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + NSDate *now = stepResult.endDate; + + ORKPasscodeResult *passcodeResult = [[ORKPasscodeResult alloc] initWithIdentifier:[self passcodeStep].identifier]; + passcodeResult.passcodeSaved = _isPasscodeSaved; + passcodeResult.touchIdEnabled = _isTouchIdAuthenticated; + passcodeResult.startDate = stepResult.startDate; + passcodeResult.endDate = now; + + stepResult.results = @[passcodeResult]; + return stepResult; +} + +- (void)addResult:(ORKResult *)result { + ORKThrowMethodUnavailableException(); +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return [[ORKPasscodeStepViewController class] supportedInterfaceOrientations]; +} + ++ (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return UIInterfaceOrientationMaskAll; +} + +#pragma mark - Helpers + +- (void)changeStateTo:(ORKPasscodeState)passcodeState { + _passcodeState = passcodeState; + [self updatePasscodeView]; +} + +- (NSInteger)numberOfDigitsForPasscodeType:(ORKPasscodeType)passcodeType { + switch (passcodeType) { + case ORKPasscodeType4Digit: + return 4; + case ORKPasscodeType6Digit: + return 6; + } +} + +- (void)cancelButtonAction { + if (self.passcodeDelegate && + [self.passcodeDelegate respondsToSelector:@selector(passcodeViewControllerDidCancel:)]) { + [self.passcodeDelegate passcodeViewControllerDidCancel:self]; + } +} + +- (void)makePasscodeViewBecomeFirstResponder { + _shouldResignFirstResponder = NO; + if (![_accessibilityPasscodeField isFirstResponder]) { + [_accessibilityPasscodeField becomeFirstResponder]; + } +} + +- (void)makePasscodeViewResignFirstResponder { + _shouldResignFirstResponder = YES; + if ([_accessibilityPasscodeField isFirstResponder]) { + [_accessibilityPasscodeField resignFirstResponder]; + } +} + +- (void)promptTouchId { + _touchContext = [LAContext new]; + _touchContext.localizedFallbackTitle = @""; + + // Check to see if the device supports Touch ID. + if (_useTouchId && + [_touchContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]) { + /// Device does support Touch ID. + + // Resign the keyboard to allow the alert to be centered on the screen. + [self makePasscodeViewResignFirstResponder]; + + NSString *localizedReason = ORKLocalizedString(@"PASSCODE_TOUCH_ID_MESSAGE", nil); + ORKWeakTypeOf(self) weakSelf = self; + [_touchContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics + localizedReason:localizedReason + reply:^(BOOL success, NSError *error) { + dispatch_sync(dispatch_get_main_queue(), ^{ + + ORKStrongTypeOf(self) strongSelf = weakSelf; + + if (success) { + // Store that user passed authentication. + _isTouchIdAuthenticated = YES; + + // Send a delegate callback for authentication flow. + if ([strongSelf passcodeStep].passcodeFlow == ORKPasscodeFlowAuthenticate) { + [strongSelf.passcodeDelegate passcodeViewControllerDidFinishWithSuccess:strongSelf]; + } + } else if (error.code != LAErrorUserCancel) { + // Display the error message. + UIAlertController *alert = [UIAlertController alertControllerWithTitle:ORKLocalizedString(@"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE", nil) + message:error.localizedDescription + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_OK", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + ORKStrongTypeOf(self) innerStrongSelf = weakSelf; + [innerStrongSelf makePasscodeViewBecomeFirstResponder]; + }]]; + [strongSelf presentViewController:alert animated:YES completion:nil]; + } + + [strongSelf finishTouchId]; + }); + }]; + + } else { + /// Device does not support Touch ID. + [self finishTouchId]; + } +} + +- (void)promptTouchIdWithDelay { + + double delayInSeconds = 0.5; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + ORKWeakTypeOf(self) weakSelf = self; + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf promptTouchId]; + }); +} + +- (void)finishTouchId { + // Only save to keychain if it is not in authenticate flow. + ORKPasscodeFlow passcodeFlow = [self passcodeStep].passcodeFlow; + if (passcodeFlow != ORKPasscodeFlowAuthenticate) { + [self savePasscodeToKeychain]; + } + + if (passcodeFlow == ORKPasscodeFlowCreate) { + // If it is in creation flow (consent step), go to the next step. + [self goForward]; + } else if (passcodeFlow == ORKPasscodeFlowAuthenticate) { + // If it is in authentication flow (any task), go to the next step. + [self goForward]; + } else if (passcodeFlow == ORKPasscodeFlowEdit) { + // If it is in editing flow, send a delegate callback. + [self.passcodeDelegate passcodeViewControllerDidFinishWithSuccess:self]; + } +} + +- (void)savePasscodeToKeychain { + [[self class] savePasscode:_passcode withTouchIdEnabled:_isTouchIdAuthenticated]; + _isPasscodeSaved = YES; // otherwise an exception would have been thrown +} + ++ (void)savePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled { + ORKThrowInvalidArgumentExceptionIfNil(passcode) + NSDictionary *dictionary = @{ + KeychainDictionaryPasscodeKey: [passcode copy], + KeychainDictionaryTouchIdKey: @(touchIdEnabled) + }; + NSError *error; + [ORKKeychainWrapper setObject:dictionary forKey:PasscodeKey error:&error]; + if (error) { + @throw [NSException exceptionWithName:NSGenericException reason:error.localizedDescription userInfo:nil]; + } +} + +- (void)removePasscodeFromKeychain { + NSError *error; + [ORKKeychainWrapper objectForKey:PasscodeKey error:&error]; + + if (!error) { + [ORKKeychainWrapper removeObjectForKey:PasscodeKey error:&error]; + + if (error) { + @throw [NSException exceptionWithName:NSGenericException reason:error.localizedDescription userInfo:nil]; + } + } +} + +- (BOOL)passcodeMatchesKeychain { + NSError *error; + NSDictionary *dictionary = (NSDictionary *) [ORKKeychainWrapper objectForKey:PasscodeKey error:&error]; + if (error) { + [self throwExceptionWithKeychainError:error]; + } + + NSString *storedPasscode = dictionary[KeychainDictionaryPasscodeKey]; + return [storedPasscode isEqualToString:_passcode]; +} + +- (void)setValuesFromKeychain { + NSError *error; + NSDictionary *dictionary = (NSDictionary*) [ORKKeychainWrapper objectForKey:PasscodeKey error:&error]; + if (error) { + [self throwExceptionWithKeychainError:error]; + } + + NSString *storedPasscode = dictionary[KeychainDictionaryPasscodeKey]; + _authenticationPasscodeType = (storedPasscode.length == 4) ? ORKPasscodeType4Digit : ORKPasscodeType6Digit; + + if ([self passcodeStep].passcodeFlow == ORKPasscodeFlowAuthenticate) { + _useTouchId = [dictionary[KeychainDictionaryTouchIdKey] boolValue]; + } +} + +- (void)wrongAttempt { + + // Vibrate the device, if available. + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + + // Shake animation. + CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation]; + shakeAnimation.keyPath = @"position.x"; + shakeAnimation.values = @[ @0, @15, @-15, @15, @-15, @0 ]; + shakeAnimation.keyTimes = @[ @0, @(1 / 8.0), @(3 / 8.0), @(5 / 8.0), @(7 / 8.0), @1 ]; + shakeAnimation.duration = 0.27; + shakeAnimation.delegate = self; + shakeAnimation.additive = YES; + + [_passcodeStepView.textField.layer addAnimation:shakeAnimation forKey:@"shakeAnimation"]; + + // Update the passcode view after the shake animation has ended. + double delayInSeconds = 0.27; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + ORKWeakTypeOf(self) weakSelf = self; + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf updatePasscodeView]; + }); +} + +- (void)throwExceptionWithKeychainError:(NSError *)error { + NSString *errorReason = error.localizedDescription; + if (error.code == errSecItemNotFound) { + errorReason = @"There is no passcode stored in the keychain."; + } + @throw [NSException exceptionWithName:NSGenericException reason:errorReason userInfo:nil]; +} + +#pragma mark - Passcode flows + +- (void)passcodeFlowCreate { + + /* Passcode Flow Create + 1) ORKPasscodeStateEntry - User enters a passcode. + 2) ORKPasscodeStateConfirm - User re-enters the passcode. + 3) ORKSavedStateSaved - User is shown a passcode saved message. + 4) TouchID - A Touch ID prompt is shown. + */ + + if (_passcodeState == ORKPasscodeStateEntry) { + // Move to confirm state. + [self changeStateTo:ORKPasscodeStateConfirm]; + } else if (_passcodeState == ORKPasscodeStateConfirm) { + // Check to see if the input matches the first passcode. + if ([_passcode isEqualToString:_confirmPasscode]) { + // Move to saved state. + [self changeStateTo:ORKPasscodeStateSaved]; + + // Show Touch ID prompt after a short delay of showing passcode saved message. + [self promptTouchIdWithDelay]; + } else { + // Visual cue. + [self wrongAttempt]; + + // If the input does not match, change back to entry state. + [self changeStateTo:ORKPasscodeStateEntry]; + + // Show an alert to the user. + [self showValidityAlertWithMessage:ORKLocalizedString(@"PASSCODE_INVALID_ALERT_MESSAGE", nil)]; + } + } +} + +- (void)passcodeFlowEdit { + + /* Passcode Flow Edit + 1) ORKPasscodeStateOldEntry - User enters their old passcode. + 2) ORKPasscodeStateNewEntry - User enters a new passcode. + 3) ORKPasscodeStateConfirmNewEntry - User re-enters the new passcode. + 4) ORKPasscodeSaved - User is shown a passcode saved message. + 5) TouchID - A Touch ID prompt is shown. + */ + + if (_passcodeState == ORKPasscodeStateOldEntry) { + // Check if the inputted passcode matches the old user passcode. + if ([self passcodeMatchesKeychain]) { + // Move to new entry step. + _passcodeStepView.textField.numberOfDigits = [self numberOfDigitsForPasscodeType:[self passcodeStep].passcodeType]; + [self changeStateTo:ORKPasscodeStateNewEntry]; + } else { + // Failed authentication, send delegate callback. + [self.passcodeDelegate passcodeViewControllerDidFailAuthentication:self]; + + // Visual cue. + [self wrongAttempt]; + } + } else if (_passcodeState == ORKPasscodeStateNewEntry) { + // Move to confirm new entry state. + [self changeStateTo:ORKPasscodeStateConfirmNewEntry]; + } else if ( _passcodeState == ORKPasscodeStateConfirmNewEntry) { + // Check to see if the input matches the first passcode. + if ([_passcode isEqualToString:_confirmPasscode]) { + // Move to saved state. + [self changeStateTo:ORKPasscodeStateSaved]; + + // Show Touch ID prompt after a short delay of showing passcode saved message. + [self promptTouchIdWithDelay]; + } else { + // Visual cue. + [self wrongAttempt]; + + // If the input does not match, change back to entry state. + [self changeStateTo:ORKPasscodeStateNewEntry]; + + // Show an alert to the user. + [self showValidityAlertWithMessage:ORKLocalizedString(@"PASSCODE_INVALID_ALERT_MESSAGE", nil)]; + } + } + +} + +- (void)passcodeFlowAuthenticate { + + /* Passcode Flow Authenticate + 1) TouchID - A Touch ID prompt is shown. + 1) ORKPasscodeStateEntry - User enters their passcode. + */ + + if (_passcodeState == ORKPasscodeStateEntry) { + if ([self passcodeMatchesKeychain]) { + // Passed authentication, send delegate callback. + [self.passcodeDelegate passcodeViewControllerDidFinishWithSuccess:self]; + + // If we're in a task with many steps, time to go to the next one. + [self goForward]; + } else { + // Failed authentication, send delegate callback. + [self.passcodeDelegate passcodeViewControllerDidFailAuthentication:self]; + + // Visual cue. + [self wrongAttempt]; + } + } +} + +#pragma mark - UITextFieldDelegate + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + + ORKPasscodeTextField *passcodeTextField = _passcodeStepView.textField; + if (passcodeTextField.text.length < passcodeTextField.numberOfDigits) { + [passcodeTextField insertText:string]; + } + + // Disable input while changing states. + if (_isChangingState) { + return !_isChangingState; + } + + NSString *text = [passcodeTextField.text stringByReplacingCharactersInRange:range withString:string]; + + // User entered a character. + if (text.length < passcodeTextField.text.length) { + // User hit the backspace button. + if (_numberOfFilledBullets > 0) { + _numberOfFilledBullets--; + + // Remove last character + if (_passcodeState == ORKPasscodeStateEntry || + _passcodeState == ORKPasscodeStateOldEntry || + _passcodeState == ORKPasscodeStateNewEntry) { + [_passcode deleteCharactersInRange:NSMakeRange([_passcode length]-1, 1)]; + } else if (_passcodeState == ORKPasscodeStateConfirm || + _passcodeState == ORKPasscodeStateConfirmNewEntry) { + [_confirmPasscode deleteCharactersInRange:NSMakeRange([_confirmPasscode length]-1, 1)]; + } + } + } else if (_numberOfFilledBullets < passcodeTextField.numberOfDigits) { + // Only allow numeric characters besides backspace (covered by the previous if statement). + if (![[NSScanner scannerWithString:string] scanFloat:NULL]) { + [self showValidityAlertWithMessage:ORKLocalizedString(@"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE", nil)]; + return NO; + } + + // Store the typed input. + if (_passcodeState == ORKPasscodeStateEntry || + _passcodeState == ORKPasscodeStateOldEntry || + _passcodeState == ORKPasscodeStateNewEntry) { + [_passcode appendString:string]; + } else if (_passcodeState == ORKPasscodeStateConfirm || + _passcodeState == ORKPasscodeStateConfirmNewEntry) { + [_confirmPasscode appendString:string]; + } + + // User entered a new character. + _numberOfFilledBullets++; + } + [passcodeTextField updateTextWithNumberOfFilledBullets:_numberOfFilledBullets]; + + // User entered all characters. + if (_numberOfFilledBullets == passcodeTextField.numberOfDigits) { + // Disable input. + _isChangingState = YES; + + // Show the user the last digit was entered before continuing. + double delayInSeconds = 0.25; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + ORKWeakTypeOf(self) weakSelf = self; + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + ORKStrongTypeOf(self) strongSelf = weakSelf; + + switch ([strongSelf passcodeStep].passcodeFlow) { + case ORKPasscodeFlowCreate: + [strongSelf passcodeFlowCreate]; + break; + + case ORKPasscodeFlowAuthenticate: + [strongSelf passcodeFlowAuthenticate]; + break; + + case ORKPasscodeFlowEdit: + [strongSelf passcodeFlowEdit]; + break; + } + }); + } + + return YES; +} + +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + return _shouldResignFirstResponder; +} + +- (void)forgotPasscodeTapped { + if ([self.passcodeDelegate respondsToSelector:@selector(passcodeViewControllerForgotPasscodeTapped:)]) { + [self.passcodeDelegate passcodeViewControllerForgotPasscodeTapped:self ]; + } +} + +- (BOOL)hasForgotPasscode { + if (([self passcodeStep].passcodeFlow == ORKPasscodeFlowAuthenticate) && + [self.passcodeDelegate respondsToSelector:@selector(passcodeViewControllerForgotPasscodeTapped:)]) { + return YES; + } + return NO; +} + +- (NSString *)forgotPasscodeButtonText { + if ([self.passcodeDelegate respondsToSelector:@selector(passcodeViewControllerTextForForgotPasscode:)]) { + return [self.passcodeDelegate passcodeViewControllerTextForForgotPasscode: self]; + } + return ORKLocalizedString(@"PASSCODE_FORGOT_BUTTON_TITLE", @"Prompt for user forgetting their passcode"); +} + +#pragma mark - Keyboard Notifications + +- (void)keyboardWillShow:(NSNotification *)notification { + + CGFloat keyboardHeight = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; + + double animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + [UIView animateWithDuration:animationDuration animations:^{ + [_forgotPasscodeButton setFrame:CGRectMake(_forgotPasscodeButton.frame.origin.x, _originalForgotPasscodeY - keyboardHeight, _forgotPasscodeButton.frame.size.width, _forgotPasscodeButton.frame.size.height)]; + }]; +} + +- (void)keyboardWillHide:(NSNotification *)notification { + + double animationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; + + [UIView animateWithDuration:animationDuration animations:^{ + [_forgotPasscodeButton setFrame:CGRectMake(_forgotPasscodeButton.frame.origin.x, _originalForgotPasscodeY, _forgotPasscodeButton.frame.size.width, _forgotPasscodeButton.frame.size.height)]; + }]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController_Internal.h new file mode 100755 index 0000000..973c3ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeStepViewController_Internal.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeStepViewController.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKPasscodeDelegate; + +static NSString *const KeychainDictionaryPasscodeKey = @"passcode"; +static NSString *const KeychainDictionaryTouchIdKey = @"touchIdEnabled"; +static NSString *const PasscodeStepIdentifier = @"passcode_step"; +static NSString *const PasscodeKey = @"ORKPasscode"; + +typedef NS_ENUM(NSUInteger, ORKPasscodeState) { + ORKPasscodeStateEntry, + ORKPasscodeStateConfirm, + ORKPasscodeStateSaved, + ORKPasscodeStateOldEntry, + ORKPasscodeStateNewEntry, + ORKPasscodeStateConfirmNewEntry +}; + +@interface ORKPasscodeStepViewController() + +@property (nonatomic, weak) id passcodeDelegate; + +/** + Stores the given passcode as the user's unlock passcode to the keychain. + + This method will raise an exception if `passcode` is nil. + + @param passcode The passcode to store + @param touchIdEnabled Whether TouchId will be available during passcode entry + */ ++ (void)savePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.h new file mode 100755 index 0000000..9d74c6c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.h @@ -0,0 +1,164 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKStepViewController.h" +#import "ORKDefines.h" +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + The passcode delegate protocol declares methods which forward the success or failure of passcode modification + or authentication. + */ +ORK_AVAILABLE_DECL +@protocol ORKPasscodeDelegate + +@required +/** + Notifies the delegate that the user has finished authenticating or editing the passcode. + + @param viewController The `ORKPasscodeStepViewController` object in which the passcode input is entered. + */ +- (void)passcodeViewControllerDidFinishWithSuccess:(UIViewController *)viewController; + +/** + Notifies the delegate that the user failed authentication. + + @param viewController The `ORKPasscodeStepViewController` object in which the passcode input is entered. + */ +- (void)passcodeViewControllerDidFailAuthentication:(UIViewController *)viewController; + +@optional + +/** + Notifies the delegate that the user hit the cancel button item. The cancel button is only visible if this method + is implemented. + + @param viewController The `ORKPasscodeStepViewController` object in which the passcode input is entered. + */ +- (void)passcodeViewControllerDidCancel:(UIViewController *)viewController; + +/** + Defaults to Localized "Forgot Passcode?" text + + @param viewController The `ORKPasscodeStepViewController` object in which the passcode input is entered. + @return Text to display for the forgot passcode button + */ +- (NSString *)passcodeViewControllerTextForForgotPasscode:(UIViewController *)viewController; + +/** + Notifies the delegate that forgot passcode button has been tapped. + + @param viewController The `ORKPasscodeStepViewController` object in which the passcode input is entered. + */ +- (void)passcodeViewControllerForgotPasscodeTapped:(UIViewController *)viewController; + +@end + + +/** + An `ORKPasscodeStepViewController` object is the view controller for an `ORKPasscodeStep` object. + + A passcode view controller can also be instantiated directly for authentication and editing by using one + of the factory methods below. Each factory method requires a delegate to be implemented. + */ +ORK_CLASS_AVAILABLE +@interface ORKPasscodeViewController : UINavigationController + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + An authenticaiton passcode view controller allows a user to be authenticated using + the passcode stored in the keychain. + + A passcode must already have been created using a passcode step before presenting + this view controller (see `ORKPasscodeStep`). + + You must check to see if the passcode is stored in the keychain before presenting + this view controller. A helper method, `isPasscodeStoredInKeychain`, is provided as + part of this class. + + @param text The message displayed to the user. + @param delegate The delegate for the passcode view controller. + + @return A passcode authentication view controller. + */ ++ (instancetype)passcodeAuthenticationViewControllerWithText:(nullable NSString *)text + delegate:(id)delegate; + +/** + An editing passcode view controller allows a user to be authenticated using + the passcode stored in the keychain and create a new passcode. + + A passcode must already have been created using a passcode step before presenting + this view controller (see `ORKPasscodeStep`). + + You must check to see if the passcode is stored in the keychain before presenting + this view controller. A helper method, `isPasscodeStoredInKeychain`, is provided as + part of this class. + + @param text The message displayed to the user. + @param delegate The delegate for the passcode view controller. + @param passcodeType The passcode type for the new passcode. + + @return A passcode editing view controller. + */ ++ (instancetype)passcodeEditingViewControllerWithText:(nullable NSString *)text + delegate:(id)delegate + passcodeType:(ORKPasscodeType)passcodeType; +/** + Returns 'YES' if a passcode is stored in the keychain, otherwise 'NO'. + */ ++ (BOOL)isPasscodeStoredInKeychain; + +/** + Returns 'YES' if passcode was successfully removed from the keychain, otherwise 'NO'. + */ ++ (BOOL)removePasscodeFromKeychain; + +/** + This method allows to force the passcode to be a certain value. You only want to use this capability when you're moving your existing users + from a custom passcode entry mechanism to the one provided by ResearchKit. + + This method will raise an exception if `passcode` is nil. + + @param passcode The passcode to store + @param touchIdEnabled Whether TouchId will be available during passcode entry + */ ++ (void)forcePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.m new file mode 100755 index 0000000..d86a0c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPasscodeViewController.m @@ -0,0 +1,116 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPasscodeViewController.h" + +#import "ORKPasscodeStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKPasscodeStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKKeychainWrapper.h" + + +@implementation ORKPasscodeViewController + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithRootViewController:(UIViewController *)rootViewController { + self = [super initWithRootViewController:rootViewController]; + if (self) { + [self.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + self.navigationBar.shadowImage = [UIImage new]; + self.navigationBar.translucent = NO; + } + return self; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + return [[ORKPasscodeStepViewController class] supportedInterfaceOrientations]; +} + ++ (instancetype)passcodeAuthenticationViewControllerWithText:(NSString *)text + delegate:(id)delegate { + return [self passcodeViewControllerWithText:text + delegate:delegate + passcodeFlow:ORKPasscodeFlowAuthenticate + passcodeType:0]; +} + ++ (instancetype)passcodeEditingViewControllerWithText:(NSString *)text + delegate:(id)delegate + passcodeType:(ORKPasscodeType)passcodeType { + return [self passcodeViewControllerWithText:text + delegate:delegate + passcodeFlow:ORKPasscodeFlowEdit + passcodeType:passcodeType]; +} + ++ (instancetype)passcodeViewControllerWithText:(NSString *)text + delegate:(id)delegate + passcodeFlow:(ORKPasscodeFlow)passcodeFlow + passcodeType:(ORKPasscodeType)passcodeType { + + ORKPasscodeStep *step = [[ORKPasscodeStep alloc] initWithIdentifier:PasscodeStepIdentifier]; + step.passcodeFlow = passcodeFlow; + step.passcodeType = passcodeType; + step.text = text; + + ORKPasscodeStepViewController *passcodeStepViewController = [ORKPasscodeStepViewController new]; + passcodeStepViewController.passcodeDelegate = delegate; + passcodeStepViewController.step = step; + + ORKPasscodeViewController *navigationController = [[ORKPasscodeViewController alloc] initWithRootViewController:passcodeStepViewController]; + return navigationController; +} + ++ (BOOL)isPasscodeStoredInKeychain { + NSDictionary *dictionary = (NSDictionary *)[ORKKeychainWrapper objectForKey:PasscodeKey error:nil]; + return ([dictionary objectForKey:KeychainDictionaryPasscodeKey]) ? YES : NO; +} + ++ (BOOL)removePasscodeFromKeychain { + return [ORKKeychainWrapper removeObjectForKey:PasscodeKey error:nil]; +} + ++ (void)forcePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled { + ORKThrowInvalidArgumentExceptionIfNil(passcode) + [ORKPasscodeStepViewController savePasscode:passcode withTouchIdEnabled:touchIdEnabled]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.h new file mode 100755 index 0000000..2ef2540 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKPickerDelegate + +- (void)picker:(id)picker answerDidChangeTo:(nullable id)answer; + +@end + + +@class ORKAnswerFormat; + +@protocol ORKPicker + +- (instancetype)initWithAnswerFormat:(ORKAnswerFormat *)answerFormat answer:(nullable id)answer pickerDelegate:(id)delegate; + +@property (nonatomic, weak, nullable) id pickerDelegate; + +@property (nonatomic, strong, nullable) id answer; + +@property (nonatomic, readonly, nullable) NSString *selectedLabelText; + +- (void)pickerWillAppear; + +@property (nonatomic, strong, readonly) UIView *pickerView; + +@end + + +@interface ORKPicker : NSObject + ++ (id)pickerWithAnswerFormat:(ORKAnswerFormat *)answerFormat answer:(nullable id)answer delegate:(id) delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.m new file mode 100755 index 0000000..0b93c2d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPicker.m @@ -0,0 +1,80 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKPicker.h" + +#import "ORKDateTimePicker.h" +#import "ORKHeightPicker.h" +#import "ORKWeightPicker.h" +#import "ORKTimeIntervalPicker.h" +#import "ORKValuePicker.h" +#import "ORKMultipleValuePicker.h" + +#import "ORKAnswerFormat.h" + +@implementation ORKPicker : NSObject + +/** + Creates a picker appropriate to the type required by answerformat + + @param answerFormat An ORKAnswerFormat object which specified the format of the result + @param answer A default answer (to set as the picker's current result), or nil if no answer specified. + @param delegate A delegate who conforms to ORKPickerDelegate + + @return The picker object + */ ++ (id)pickerWithAnswerFormat:(ORKAnswerFormat *)answerFormat answer:(id)answer delegate:(id) delegate { + id picker = nil; + + if ([answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answer = nil; + } + + if ([answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]]) { + picker = [[ORKValuePicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } else if ([answerFormat isKindOfClass:[ORKTimeIntervalAnswerFormat class]]) { + picker = [[ORKTimeIntervalPicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } else if ([answerFormat isKindOfClass:[ORKDateAnswerFormat class]] || [answerFormat isKindOfClass:[ORKTimeOfDayAnswerFormat class]]) { + picker = [[ORKDateTimePicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } else if ([answerFormat isKindOfClass:[ORKHeightAnswerFormat class]]) { + picker = [[ORKHeightPicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } else if ([answerFormat isKindOfClass:[ORKWeightAnswerFormat class]]) { + picker = [[ORKWeightPicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } else if ([answerFormat isKindOfClass:[ORKMultipleValuePickerAnswerFormat class]]) { + picker = [[ORKMultipleValuePicker alloc] initWithAnswerFormat:answerFormat answer:answer pickerDelegate:delegate]; + } + + NSAssert(picker, @"Cannot create picker for answer format %@", answerFormat); + + return picker; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.h new file mode 100755 index 0000000..a166655 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKPlaybackButton : UIButton + +- (instancetype)initWithText:(NSString *)text image:(UIImage *)image; + +@property (nonatomic) NSString *text; +@property (nonatomic) UIImage *image; +@property (nonatomic) UIColor *highlightTintColor; +@property (nonatomic) UIColor *normalTintColor; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.m new file mode 100755 index 0000000..8f7e8a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKPlaybackButton.m @@ -0,0 +1,144 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKPlaybackButton.h" + +static const CGFloat ImageViewDimension = 60.0; +static const CGFloat ImageToLabelPadding = 2.0; + +@implementation ORKPlaybackButton { + UILabel *_textLabel; + UIImageView *_imageView; +} + +- (instancetype)initWithText:(NSString *)text image:(UIImage *)image { + self = [super init]; + if (self) { + self.text = text; + self.image = image; + } + [self setColors]; + [self setupImageView]; + [self setupTextLabel]; + return self; +} + +- (void)setColors { + _highlightTintColor = self.tintColor; + _normalTintColor = [self.tintColor colorWithAlphaComponent:0.4]; +} + +- (void)setupImageView { + if (!_imageView) { + _imageView = [UIImageView new]; + } + _imageView.image = _image; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_imageView]; + + [[_imageView.topAnchor constraintEqualToAnchor:self.topAnchor] setActive:YES]; + [[_imageView.widthAnchor constraintEqualToConstant:ImageViewDimension] setActive:YES]; + [[_imageView.heightAnchor constraintEqualToConstant:ImageViewDimension] setActive:YES]; + [[_imageView.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; +} + +- (UIFont *)bodyTextFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont fontWithDescriptor:descriptor size:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (void)setupTextLabel { + if (!_textLabel) { + _textLabel = [UILabel new]; + } + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + _textLabel.text = _text; + _textLabel.textAlignment = NSTextAlignmentCenter; + _textLabel.textColor = self.tintColor; + _textLabel.font = [self bodyTextFont]; + [self addSubview:_textLabel]; + + [[_textLabel.topAnchor constraintEqualToAnchor:_imageView.bottomAnchor constant:ImageToLabelPadding] setActive:YES]; + [[_textLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + [[self.widthAnchor constraintEqualToAnchor:_textLabel.widthAnchor] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_textLabel.bottomAnchor] setActive:YES]; +} + +- (void)setTintColor:(UIColor *)tintColor { + [super setTintColor:tintColor]; + _imageView.tintColor = tintColor; + _textLabel.textColor = tintColor; +} + +- (void)setNormalTintColor:(UIColor *)normalTintColor { + _normalTintColor = normalTintColor; + [self setHighlighted:self.isHighlighted]; +} + +- (void)setHighlightTintColor:(UIColor *)highlightTintColor { + _highlightTintColor = highlightTintColor; + [self setHighlighted:self.isHighlighted]; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + if (highlighted) { + _textLabel.textColor = _highlightTintColor; + _imageView.tintColor = _highlightTintColor; + } + else { + _textLabel.textColor = _normalTintColor; + _imageView.tintColor = _normalTintColor; + } +} + +- (void)setEnabled:(BOOL)enabled { + [super setEnabled:enabled]; + if (enabled) { + _textLabel.textColor = _highlightTintColor; + _imageView.tintColor = _highlightTintColor; + } + else { + _textLabel.textColor = _normalTintColor; + _imageView.tintColor = _normalTintColor; + } +} + +- (void)setText:(NSString *)text { + _text = text; + _textLabel.text = text; +} + +- (void)setImage:(UIImage *)image { + _image = image; + _imageView.image = image; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.h new file mode 100755 index 0000000..4c3c82e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKProgressView : UIView + +@property (nonatomic, assign) NSInteger count; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.m new file mode 100755 index 0000000..3d0b498 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKProgressView.m @@ -0,0 +1,166 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKProgressView.h" + + +static const CGFloat ProgressCircleDiameter = 10; +static const CGFloat ProgressCircleSpacing = 4; + +@interface ORKProgressCircleView : UIView + +@property (nonatomic, assign) BOOL completed; + +@end + + +@implementation ORKProgressCircleView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setCompleted:NO]; + self.backgroundColor = [self tintColor]; + self.layer.cornerRadius = ProgressCircleDiameter / 2; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.backgroundColor = [self tintColor]; +} + +- (CGSize)intrinsicContentSize { + return (CGSize){ProgressCircleDiameter, ProgressCircleDiameter}; +} + +- (CGSize)sizeThatFits:(CGSize)size { + return (CGSize){ProgressCircleDiameter, ProgressCircleDiameter}; +} + +- (void)setCompleted:(BOOL)completed { + _completed = completed; + self.alpha = (completed ? 1.0 : 0.6); +} + +@end + + +@implementation ORKProgressView { + NSArray *_circles; + NSInteger _index; + NSTimer *_timer; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.count = 3; + } + return self; +} + +- (void)dealloc { + [_timer invalidate]; + _timer = nil; +} + +- (void)setCount:(NSInteger)count { + _count = count; + if (count != _circles.count) { + for (UIView *v in _circles) { + [v removeFromSuperview]; + } + NSMutableArray *newCircles = [NSMutableArray array]; + for (NSInteger idx = 0; idx < count; idx ++) { + ORKProgressCircleView *circle = [ORKProgressCircleView new]; + [newCircles addObject:circle]; + [self addSubview:circle]; + } + + _circles = newCircles; + [self invalidateIntrinsicContentSize]; + [self setNeedsLayout]; + self.index = _index; + } +} + +- (void)setIndex:(NSInteger)index { + _index = index; + [_circles enumerateObjectsUsingBlock:^(ORKProgressCircleView *circle, NSUInteger idx, BOOL *stop) { + circle.completed = (idx < _index); + }]; +} + +- (void)didMoveToWindow { + if (self.window) { + [self startAnimating]; + } else { + [self stopAnimating]; + } +} +- (void)stopAnimating { + [_timer invalidate]; + _timer = nil; +} + +- (void)incrementIndex { + self.index = (_index + 1) % (_count + 1); +} + +- (void)startAnimating { + [self stopAnimating]; + self.index = 0; + _timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(incrementIndex) userInfo:nil repeats:YES]; +} + +- (CGSize)sizeThatFits:(CGSize)size { + size.height = ProgressCircleDiameter; + size.width = (_count * ProgressCircleDiameter) + MAX(_count - 1,0) * ProgressCircleSpacing; + return size; +} + +- (CGSize)intrinsicContentSize { + return [self sizeThatFits:CGSizeZero]; +} + +- (void)layoutSubviews { + CGSize size = (CGSize){ProgressCircleDiameter,ProgressCircleDiameter}; + CGFloat xStep = ProgressCircleDiameter + ProgressCircleSpacing; + CGFloat x0 = 0; + for (UIView *view in _circles) { + view.frame = (CGRect){{x0, 0}, size}; + x0 += xStep; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.h new file mode 100755 index 0000000..119affa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.h @@ -0,0 +1,340 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +@import CoreLocation; +@import Contacts; + +NS_ASSUME_NONNULL_BEGIN + +@class ORKQuestionStep; +@class ORKFormItem; +@class ORKFormStep; +@class ORKQuestionResult; + + +/** + The `ORKQuestionResult` class is the base class for leaf results from an item that uses an answer format (`ORKAnswerFormat`). + + A question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + + See also: `ORKQuestionStep` and `ORKFormItem`. + */ +ORK_CLASS_AVAILABLE +@interface ORKQuestionResult : ORKResult + +/** + A value that indicates the type of question the result came from. + + The value of `questionType` generally correlates closely with the class, but it can be + easier to use this value in a switch statement in Objective-C. + */ +@property (nonatomic) ORKQuestionType questionType; + +@end + + +/** + The `ORKBooleanQuestionResult` class represents the answer to a Yes/No question. + + A Boolean question result is produced by the task view controller when it presents a question or form + item with a Boolean answer format (that is, `ORKBooleanAnswerFormat`). + + A Boolean question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKBooleanQuestionResult : ORKQuestionResult + +/** The answer, or `nil` if the user skipped the question. */ +@property (nonatomic, copy, nullable) NSNumber *booleanAnswer; + +@end + + +/** + The `ORKChoiceQuestionResult` class represents the single or multiple choice + answers from a choice-based answer format. + + For example, an `ORKTextChoiceAnswerFormat` or an `ORKImageChoiceAnswerFormat` + format produces an `ORKChoiceQuestionResult` object. + + A choice question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKChoiceQuestionResult : ORKQuestionResult + +/** + An array of selected values, from the `value` property of an `ORKTextChoice` or `ORKImageChoice` object. + In the case of a single choice, the array has exactly one entry. + + If the user skipped the question, the value of the corresponding array member is `nil`. + */ +@property (nonatomic, copy, nullable) NSArray> *choiceAnswers; + +@end + + +/** + The `ORKDateQuestionResult` class represents the result of a question or form item that asks for a date (`ORKDateAnswerFormat`). + + The calendar and time zone are recorded in addition to the answer itself, + to give the answer context. Usually, this data corresponds to the current calendar + and time zone at the time of the activity, but it can be overridden by setting + these properties explicitly in the `ORKDateAnswerFormat` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKDateQuestionResult : ORKQuestionResult + +/** + The date that the user entered, or `nil` if the user skipped the question. + */ +@property (nonatomic, copy, nullable) NSDate *dateAnswer; + +/** + The calendar used when selecting date and time. + + If the calendar in the `ORKDateAnswerFormat` object is `nil`, this calendar is the system + calendar at the time of data entry. + */ +@property (nonatomic, copy, nullable) NSCalendar *calendar; + +/** + The time zone that was current when selecting the date and time. + */ +@property (nonatomic, copy, nullable) NSTimeZone *timeZone; + +@end + + +/** + The `ORKLocation` class represents the location addess obtained from a locaton question. + */ +ORK_CLASS_AVAILABLE +@interface ORKLocation : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + The geographical coordinate information. + */ +@property (nonatomic, readonly) CLLocationCoordinate2D coordinate; + +/** + The region describes the size of the placemark of the location. + */ +@property (nonatomic, copy, readonly, nullable) CLCircularRegion *region; + +/** + The human readable address typed in by user. + */ +@property (nonatomic, copy, readonly, nullable) NSString *userInput; + +/** + The postal address for this coordinate + */ +@property (nonatomic, copy, readonly, nullable) CNPostalAddress *postalAddress; + +@end + + +/** + The `ORKLocationQuestionResult` class represents the result of a question or form item that asks for a location (`ORKLocationAnswerFormat`). + + A Location question result is produced by the task view controller when it presents a question or form + item with a Location answer format (that is, `ORKLocationAnswerFormat`). + + A Location question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKLocationQuestionResult : ORKQuestionResult + +/** + The answer representing the coordinate and the address of a specific location. + */ +@property (nonatomic, copy, nullable) ORKLocation *locationAnswer; + +@end + + +/** + The `ORKMultipleComponentQuestionResult` class represents the choice + answers from a multiple-component picker-style choice-based answer format. + + For example, an `ORKMultipleValuePickerAnswerFormat` produces an `ORKMultipleComponentQuestionResult` object. + + A multiple component question result is typically generated by the framework as the task proceeds. + When the task completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKMultipleComponentQuestionResult : ORKQuestionResult + +/** + An array of selected components, from the `value` property of an `ORKTextChoice` object. + The array will have the same count as the number of components. + + If the user skipped the question, the value of the corresponding array member is `nil`. + */ +@property (nonatomic, copy, nullable) NSArray *componentsAnswer; + +/** + The string separator used to join the components (if applicable) + */ +@property (nonatomic, copy, nullable) NSString *separator; + +@end + + +/** + The `ORKNumericQuestionResult` class represents a question or form item that uses an answer format that produces a numeric answer. + + Examples of this type of answer format include `ORKScaleAnswerFormat` and `ORKNumericAnswerFormat`. + + A numeric question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKNumericQuestionResult : ORKQuestionResult + +/// The number collected, or `nil` if the user skipped the question. +@property (nonatomic, copy, nullable) NSNumber *numericAnswer; + +/** + The unit string displayed to the user when the value was entered, or `nil` if no unit string was displayed. + */ +@property (nonatomic, copy, nullable) NSString *unit; + +@end + + +/** + The `ORKScaleQuestionResult` class represents the answer to a continuous or + discrete-value scale answer format. + + A scale question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleQuestionResult : ORKQuestionResult + +/** + The answer obtained from the scale question. + + The value of this property is `nil` when the user skipped the question or otherwise did not + enter an answer. + */ +@property (nonatomic, copy, nullable) NSNumber *scaleAnswer; + +@end + + +/** + The `ORKTextQuestionResult` class represents the answer to a question or + form item that uses an `ORKTextAnswerFormat` format. + + A text question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextQuestionResult : ORKQuestionResult + +/** + The answer that the user entered. + + If the user skipped the question, the value of this property is `nil`. + */ +@property (nonatomic, copy, nullable) NSString *textAnswer; + +@end + + +/** + The `ORKTimeIntervalQuestionResult` class represents the result of a question + that uses the `ORKTimeIntervalAnswerFormat` format. + + A time interval question result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKTimeIntervalQuestionResult : ORKQuestionResult + +/** + The selected interval, in seconds. + + The value of this property is `nil` if the user skipped the question. + */ +@property (nonatomic, copy, nullable) NSNumber *intervalAnswer; + +@end + + +/** + The `ORKTimeOfDayQuestionResult` class represents the result of a question that uses the `ORKTimeOfDayAnswerFormat` format. + */ +ORK_CLASS_AVAILABLE +@interface ORKTimeOfDayQuestionResult : ORKQuestionResult + +/** + The date components picked by the user. + + Typically only hour, minute, and AM/PM data are of interest. + */ +@property (nonatomic, copy, nullable) NSDateComponents *dateComponentsAnswer; + +@end + +/** + The `ORKSESQuestionResult` class represents the result of socio-economic ladder answer format. + */ +ORK_CLASS_AVAILABLE +@interface ORKSESQuestionResult : ORKQuestionResult + +/** + The socio-economic status picked by the user. + */ +@property (nonatomic, copy, nullable) NSNumber *rungPicked; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.m new file mode 100755 index 0000000..08440fd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult.m @@ -0,0 +1,866 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKQuestionResult_Private.h" + +#import "ORKResult_Private.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKFormStep.h" +#import "ORKQuestionStep.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKQuestionResult + +- (BOOL)isSaveable { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, questionType); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, questionType); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + (_questionType == castObject.questionType)); +} + +- (NSUInteger)hash { + return super.hash ^ ((id)self.answer).hash ^ _questionType; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKQuestionResult *result = [super copyWithZone:zone]; + result.questionType = self.questionType; + return result; +} + +- (NSObject *)validateAnswer:(id)answer { + if (answer == ORKNullAnswerValue()) { + answer = nil; + } + NSParameterAssert(!answer || [answer isKindOfClass:[[self class] answerClass]] || [answer isKindOfClass:[ORKDontKnowAnswer class]]); + return answer; +} + ++ (Class)answerClass { + return nil; +} + +- (void)setAnswer:(id)answer { +} + +- (id)answer { + return nil; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + NSMutableString *description = [NSMutableString stringWithFormat:@"%@; answer:", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces]]; + id answer = self.answer; + if ([answer isKindOfClass:[NSArray class]] + || [answer isKindOfClass:[NSDictionary class]] + || [answer isKindOfClass:[NSSet class]] + || [answer isKindOfClass:[NSOrderedSet class]]) { + NSMutableString *indentatedAnswerDescription = [NSMutableString new]; + NSString *answerDescription = [answer description]; + NSArray *answerLines = [answerDescription componentsSeparatedByString:@"\n"]; + const NSUInteger numberOfAnswerLines = answerLines.count; + [answerLines enumerateObjectsUsingBlock:^(NSString *answerLineString, NSUInteger idx, BOOL *stop) { + [indentatedAnswerDescription appendFormat:@"%@%@", ORKPaddingWithNumberOfSpaces(numberOfPaddingSpaces + NumberOfPaddingSpacesForIndentationLevel), answerLineString]; + if (idx != numberOfAnswerLines - 1) { + [indentatedAnswerDescription appendString:@"\n"]; + } + }]; + + [description appendFormat:@"\n%@>", indentatedAnswerDescription]; + } else { + [description appendFormat:@" %@%@", answer, self.descriptionSuffix]; + } + + return [description copy]; +} + +@end + + +#pragma mark - ORKBooleanQuestionResult + +@implementation ORKBooleanQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, booleanAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, booleanAnswer, NSNumber); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.booleanAnswer, castObject.booleanAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKBooleanQuestionResult *result = [super copyWithZone:zone]; + result->_booleanAnswer = [self.booleanAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSNumber class]; +} + +- (void)setAnswer:(id)answer { + if ([answer isKindOfClass:[NSArray class]]) { + // Because ORKBooleanAnswerFormat has ORKChoiceAnswerFormat as its implied format. + NSArray *answerArray = answer; + NSAssert(answerArray.count <= 1, @"Should be no more than one answer"); + answer = answerArray.firstObject; + } + answer = [self validateAnswer:answer]; + self.booleanAnswer = answer; +} + +- (id)answer { + return self.booleanAnswer; +} + +@end + + +#pragma mark - ORKChoiceQuestionResult + +@implementation ORKChoiceQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, choiceAnswers); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, choiceAnswers, NSObject); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.choiceAnswers, castObject.choiceAnswers)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKChoiceQuestionResult *result = [super copyWithZone:zone]; + result->_choiceAnswers = [self.choiceAnswers copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSArray class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.choiceAnswers = answer; +} + +- (id)answer { + return self.choiceAnswers; +} + +@end + + +#pragma mark - ORKDateQuestionResult + +@implementation ORKDateQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, calendar); + ORK_ENCODE_OBJ(aCoder, timeZone); + ORK_ENCODE_OBJ(aCoder, dateAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, calendar, NSCalendar); + ORK_DECODE_OBJ_CLASS(aDecoder, timeZone, NSTimeZone); + ORK_DECODE_OBJ_CLASS(aDecoder, dateAnswer, NSDate); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.timeZone, castObject.timeZone) && + ORKEqualObjects(self.calendar, castObject.calendar) && + ORKEqualObjects(self.dateAnswer, castObject.dateAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKDateQuestionResult *result = [super copyWithZone:zone]; + result->_calendar = [self.calendar copyWithZone:zone]; + result->_timeZone = [self.timeZone copyWithZone:zone]; + result->_dateAnswer = [self.dateAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSDate class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.dateAnswer = answer; +} + +- (id)answer { + return self.dateAnswer; +} + +@end + + +#pragma mark - ORKLocationQuestionResult + +@implementation ORKLocation + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate + region:(CLCircularRegion *)region + userInput:(NSString *)userInput + postalAddress:(CNPostalAddress *)postalAddress{ + self = [super init]; + if (self) { + _coordinate = coordinate; + _region = [region copy]; + _userInput = [userInput copy]; + _postalAddress = [postalAddress copy]; + } + return self; +} + +- (instancetype)initWithPlacemark:(CLPlacemark *)placemark userInput:(NSString *)userInput { + self = [super init]; + if (self) { + _coordinate = placemark.location.coordinate; + _userInput = [userInput copy]; + _region = [placemark.region isKindOfClass:[CLCircularRegion class]] ? [placemark.region copy] : nil; + _postalAddress = [placemark.postalAddress copy]; + } + return self; +} + +- (id)copyWithZone:(NSZone *)zone { + return [[[self class] alloc] initWithCoordinate:self.coordinate + region:self.region + userInput:self.userInput + postalAddress:self.postalAddress]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +static NSString *const RegionCenterLatitudeKey = @"region.center.latitude"; +static NSString *const RegionCenterLongitudeKey = @"region.center.longitude"; +static NSString *const RegionRadiusKey = @"region.radius"; +static NSString *const RegionIdentifierKey = @"region.identifier"; + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, userInput); + ORK_ENCODE_COORDINATE(aCoder, coordinate); + ORK_ENCODE_OBJ(aCoder, postalAddress); + + [aCoder encodeObject:@(_region.center.latitude) forKey:RegionCenterLatitudeKey]; + [aCoder encodeObject:@(_region.center.longitude) forKey:RegionCenterLongitudeKey]; + [aCoder encodeObject:_region.identifier forKey:RegionIdentifierKey]; + [aCoder encodeObject:@(_region.radius) forKey:RegionRadiusKey]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, userInput, NSString); + ORK_DECODE_COORDINATE(aDecoder, coordinate); + ORK_DECODE_OBJ_CLASS(aDecoder, postalAddress, CNPostalAddress); + ORK_DECODE_OBJ_CLASS(aDecoder, region, CLCircularRegion); + + NSNumber *latitude = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:RegionCenterLatitudeKey]; + NSNumber *longitude = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:RegionCenterLongitudeKey]; + NSNumber *radius = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:RegionRadiusKey]; + CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude.doubleValue, longitude.doubleValue); + _region = [[CLCircularRegion alloc] initWithCenter:coordinate + radius:radius.doubleValue + identifier:[aDecoder decodeObjectOfClass:[NSString class] forKey:RegionIdentifierKey]]; + } + return self; +} + +- (NSUInteger)hash { + NSUInteger regionHash = (NSUInteger)(self.region.center.latitude * 1000) ^ (NSUInteger)(self.region.center.longitude * 1000) ^ (NSUInteger)(self.region.radius * 1000); + NSUInteger coordinateHash = (NSUInteger)(self.coordinate.latitude * 1000) ^ (NSUInteger)(self.coordinate.longitude * 1000); + return coordinateHash ^ regionHash ^ self.userInput.hash ^ self.postalAddress.hash; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.userInput, castObject.userInput) && + ORKEqualObjects(self.postalAddress, castObject.postalAddress)&& + // The region is not checking for equality properly so check the values + (self.region.center.latitude == castObject.region.center.latitude) && + (self.region.center.longitude == castObject.region.center.longitude) && + (self.region.radius == castObject.region.radius) && + ORKEqualObjects([NSValue valueWithMKCoordinate:self.coordinate], [NSValue valueWithMKCoordinate:castObject.coordinate])); +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%@ region:%@ userInput:%@ postalAddress:%@>", [super description], self.region, self.userInput, self.postalAddress]; +} + +@end + + +@implementation ORKLocationQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, locationAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, locationAnswer, ORKLocation); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && ORKEqualObjects(self.locationAnswer, castObject.locationAnswer)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKLocationQuestionResult *result = [super copyWithZone:zone]; + result->_locationAnswer = [self.locationAnswer copy]; + return result; +} + ++ (Class)answerClass { + return [ORKLocation class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.locationAnswer = [answer copy]; +} + +- (id)answer { + return self.locationAnswer; +} + +@end + +#pragma mark ORKSESQuestionResult + +@implementation ORKSESQuestionResult + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.rungPicked = [answer copy]; +} + ++ (Class)answerClass { + return [NSNumber class]; +} + +- (id)answer { + return self.rungPicked; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, rungPicked); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, rungPicked, NSNumber); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && ORKEqualObjects(self.rungPicked, castObject.rungPicked)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSESQuestionResult *result = [super copyWithZone:zone]; + result->_rungPicked = [self.rungPicked copy]; + return result; +} + +@end + + +#pragma mark - ORKMultipleComponentQuestionResult + +@implementation ORKMultipleComponentQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, componentsAnswer); + ORK_ENCODE_OBJ(aCoder, separator); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, componentsAnswer, NSObject); + ORK_DECODE_OBJ_CLASS(aDecoder, separator, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.componentsAnswer, castObject.componentsAnswer) && + ORKEqualObjects(self.separator, castObject.separator)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) copy = [super copyWithZone:zone]; + copy.componentsAnswer = self.componentsAnswer; + copy.separator = self.separator; + return copy; +} + ++ (Class)answerClass { + return [NSArray class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.componentsAnswer = answer; +} + +- (id)answer { + return self.componentsAnswer; +} + +@end + + +#pragma mark - ORKNumericQuestionResult + +@implementation ORKNumericQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, numericAnswer); + ORK_ENCODE_OBJ(aCoder, unit); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, numericAnswer, NSNumber); + ORK_DECODE_OBJ_CLASS(aDecoder, unit, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.numericAnswer, castObject.numericAnswer) && + ORKEqualObjects(self.unit, castObject.unit)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKNumericQuestionResult *result = [super copyWithZone:zone]; + result->_unit = [self.unit copyWithZone:zone]; + result->_numericAnswer = [self.numericAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSNumber class]; +} + +- (void)setAnswer:(id)answer { + if (answer == ORKNullAnswerValue()) { + answer = nil; + } + NSAssert(!answer || [answer isKindOfClass:[[self class] answerClass]] || [answer isKindOfClass:[ORKDontKnowAnswer class]], @"Answer should be of class %@", NSStringFromClass([[self class] answerClass])); + self.numericAnswer = answer; +} + +- (id)answer { + return self.numericAnswer; +} + +- (NSString *)descriptionSuffix { + return [NSString stringWithFormat:@" %@>", _unit]; +} + +@end + + +#pragma mark - ORKScaleQuestionResult + +@implementation ORKScaleQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, scaleAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, scaleAnswer, NSNumber); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.scaleAnswer, castObject.scaleAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKScaleQuestionResult *result = [super copyWithZone:zone]; + result->_scaleAnswer = [self.scaleAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSNumber class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.scaleAnswer = answer; +} + +- (id)answer { + return self.scaleAnswer; +} + +@end + + +#pragma mark - ORKTextQuestionResult + +@implementation ORKTextQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, textAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, textAnswer, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.textAnswer, castObject.textAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTextQuestionResult *result = [super copyWithZone:zone]; + result->_textAnswer = [self.textAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSString class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.textAnswer = answer; +} + +- (id)answer { + return self.textAnswer; +} + +@end + + +#pragma mark - ORKTimeIntervalQuestionResult + +@implementation ORKTimeIntervalQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, intervalAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, intervalAnswer, NSNumber); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.intervalAnswer, castObject.intervalAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTimeIntervalQuestionResult *result = [super copyWithZone:zone]; + result->_intervalAnswer = [self.intervalAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSNumber class]; +} + +- (void)setAnswer:(id)answer { + answer = [self validateAnswer:answer]; + self.intervalAnswer = answer; +} + +- (id)answer { + return self.intervalAnswer; +} + +@end + + +#pragma mark - ORKTimeOfDayQuestionResult + +@implementation ORKTimeOfDayQuestionResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, dateComponentsAnswer); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, dateComponentsAnswer, NSDateComponents); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.dateComponentsAnswer, castObject.dateComponentsAnswer)); +} + +- (NSUInteger)hash { + return super.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTimeOfDayQuestionResult *result = [super copyWithZone:zone]; + result->_dateComponentsAnswer = [self.dateComponentsAnswer copyWithZone:zone]; + return result; +} + ++ (Class)answerClass { + return [NSDateComponents class]; +} + +- (void)setAnswer:(id)answer { + NSDateComponents *dateComponents = (NSDateComponents *)[self validateAnswer:answer]; + // For time of day, the day, month and year should be zero + dateComponents.day = 0; + dateComponents.month = 0; + dateComponents.year = 0; + self.dateComponentsAnswer = dateComponents; +} + +- (id)answer { + return self.dateComponentsAnswer; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult_Private.h new file mode 100755 index 0000000..e3f1131 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionResult_Private.h @@ -0,0 +1,60 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +@import MapKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKQuestionResult () + +// Used internally for unit testing. ++ (nullable Class)answerClass; + +// Used internally for unit testing. +@property (nonatomic, strong, nullable) id answer; + +@end + + +@interface ORKLocation () + +- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate + region:(nullable CLCircularRegion *)region + userInput:(nullable NSString *)userInput + postalAddress:(nullable CNPostalAddress *)postalAddress; + +- (instancetype)initWithPlacemark:(CLPlacemark *)placemark userInput:(NSString *)userInput; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.h new file mode 100755 index 0000000..35e69e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.h @@ -0,0 +1,139 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKAnswerFormat; +@class ORKLearnMoreItem; + +/** + The `ORKQuestionStep` class is a concrete subclass of `ORKStep` that represents + a step in which a single question is presented to the user. + + To use a question step, instantiate an `ORKQuestionStep` object, fill in its properties, and include it + in a task. Next, create a task view controller for the task and present it. + When the task completes, the user's answer is encoded in the result hierarchy + in the task view controller. + + When a task view controller presents an `ORKQuestionStep` object, it instantiates an `ORKQuestionStepViewController` object to present the step. The actual + visual presentation depends on the answer format. + + When you need to present more than one question at the same time, it can be appropriate + to use `ORKFormStep` instead of `ORKQuestionStep`. + + The result of a question step is an `ORKStepResult` object that includes a single child + (`ORKQuestionResult`). + */ +ORK_CLASS_AVAILABLE +@interface ORKQuestionStep : ORKStep + + +/** + Returns a new question step that includes the specified identifier, title, question, and answer format. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param title A localized string that represents the primary text of the question. + @param question A localized string that represents the question as a text. + @param answerFormat The format in which the answer is expected. + */ ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + question:(nullable NSString *)question + answer:(nullable ORKAnswerFormat *)answerFormat; + +/** + Returns a new question step that includes the specified identifier, title, question, answer, and learnMoreItem format. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param title A localized string that represents the primary text of the question. + @param question A localized string that represents the question as a text. + @param answerFormat The format in which the answer is expected. + @param learnMoreItem A LearnMoreItem object that presents a learn more button in the card header view + */ ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + question:(nullable NSString *)question + answer:(nullable ORKAnswerFormat *)answerFormat + learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem; + +/** + The format of the answer. + + For example, the answer format might include the type of data to collect, the constraints + to place on the answer, or a list of available choices (in the case of single + or multiple select questions). + */ +@property (nonatomic, strong, nullable) ORKAnswerFormat *answerFormat; + +/** + The question for the step. + + Different from the step title. + */ +@property (nonatomic, strong, nullable) NSString *question; + +/** + The question type. (read-only) + + The value of this property is derived from the answer format. + */ +@property (nonatomic, readonly) ORKQuestionType questionType; + +/** + A localized string that represents the placeholder text displayed before an answer has been entered. + + For numeric and text-based answers, the placeholder content is displayed in the + text field or text area when an answer has not yet been entered. + */ +@property (nonatomic, copy, nullable) NSString *placeholder; + +/** + A property to present the question with a card view. Default to YES; + */ +@property (nonatomic) BOOL useCardView; + +/** + A property that presents a learn more button within the question's card header view; + */ +@property (nonatomic, copy, nullable) ORKLearnMoreItem *learnMoreItem; + +/** + The value displayed as a tag if set. + */ +@property (nonatomic, copy, nullable) NSString *tagText; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.m new file mode 100755 index 0000000..55bb520 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep.m @@ -0,0 +1,201 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKQuestionStep.h" +#import "ORKLearnMoreItem.h" + +#import "ORKQuestionStepViewController.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKQuestionStep + ++ (Class)stepViewControllerClass { + return [ORKQuestionStepViewController class]; +} + ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + question:(nullable NSString *)question + answer:(nullable ORKAnswerFormat *)answerFormat { + + ORKQuestionStep *step = [[ORKQuestionStep alloc] initWithIdentifier:identifier]; + step.title = title; + step.question = question; + step.answerFormat = answerFormat; + step.tagText = nil; + return step; +} + ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + question:(nullable NSString *)question + answer:(nullable ORKAnswerFormat *)answerFormat + learnMoreItem:(nullable ORKLearnMoreItem *)learnMoreItem { + + ORKQuestionStep *step = [[ORKQuestionStep alloc] initWithIdentifier:identifier]; + step.title = title; + step.question = question; + step.answerFormat = answerFormat; + step.learnMoreItem = learnMoreItem; + step.tagText = nil; + return step; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + + self = [super initWithIdentifier:identifier]; + if (self) { + self.optional = YES; + self.useSurveyMode = YES; + self.useCardView = YES; + self.showsProgress = YES; + self.tagText = nil; + } + return self; +} + +- (void)validateParameters { + [super validateParameters]; + + if([self.answerFormat isKindOfClass:[ORKConfirmTextAnswerFormat class]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"ORKConfirmTextAnswerFormat can only be used with an ORKFormStep." + userInfo:nil]; + } + + [[self impliedAnswerFormat] validateParameters]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKQuestionStep *questionStep = [super copyWithZone:zone]; + questionStep.answerFormat = [self.answerFormat copy]; + questionStep.placeholder = [self.placeholder copy]; + questionStep.learnMoreItem = [self.learnMoreItem copy]; + questionStep.question = [self.question copy]; + questionStep.tagText = [self.tagText copy]; + return questionStep; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && + ORKEqualObjects(self.answerFormat, castObject.answerFormat) && + ORKEqualObjects(self.placeholder, castObject.placeholder) && + ORKEqualObjects(self.learnMoreItem, castObject.learnMoreItem) && + ORKEqualObjects(self.tagText, castObject.tagText); +} + +- (NSUInteger)hash { + return super.hash ^ self.answerFormat.hash ^ self.question.hash ^ self.questionType ^ self.placeholder.hash ^ (_useCardView ? 0xf : 0x0) ^ self.learnMoreItem.hash ^ self.tagText.hash; +} + +- (void)setQuestion:(NSString *)question { + _question = question; +} + +- (ORKQuestionType)questionType { + ORKAnswerFormat *impliedFormat = [self impliedAnswerFormat]; + return impliedFormat.questionType; +} + +- (ORKAnswerFormat *)impliedAnswerFormat { + return [self.answerFormat impliedAnswerFormat]; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, answerFormat, ORKAnswerFormat); + ORK_DECODE_OBJ_CLASS(aDecoder, placeholder, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, question, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, learnMoreItem, ORKLearnMoreItem); + ORK_DECODE_BOOL(aDecoder, useCardView); + ORK_DECODE_OBJ_CLASS(aDecoder, tagText, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + ORK_ENCODE_OBJ(aCoder, answerFormat); + ORK_ENCODE_OBJ(aCoder, placeholder); + ORK_ENCODE_OBJ(aCoder, question); + ORK_ENCODE_OBJ(aCoder, learnMoreItem); + ORK_ENCODE_BOOL(aCoder, useCardView); + ORK_ENCODE_OBJ(aCoder, tagText); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isFormatImmediateNavigation { + ORKQuestionType questionType = self.questionType; + return (self.optional == NO) && ((questionType == ORKQuestionTypeBoolean) || (questionType == ORKQuestionTypeSingleChoice)); +} + +- (BOOL)isFormatChoiceWithImageOptions { + return [[self impliedAnswerFormat] isKindOfClass:[ORKImageChoiceAnswerFormat class]]; +} + +- (BOOL)isFormatChoiceValuePicker { + return [[self impliedAnswerFormat] isKindOfClass:[ORKValuePickerAnswerFormat class]]; +} + +- (BOOL)isFormatTextfield { + ORKAnswerFormat *impliedAnswerFormat = [self impliedAnswerFormat]; + return [impliedAnswerFormat isKindOfClass:[ORKTextAnswerFormat class]] && ![(ORKTextAnswerFormat *)impliedAnswerFormat multipleLines]; +} + +- (BOOL)isFormatFitsChoiceCells { + return ((self.questionType == ORKQuestionTypeSingleChoice && ![self isFormatChoiceWithImageOptions] && ![self isFormatChoiceValuePicker]) || + (self.questionType == ORKQuestionTypeMultipleChoice && ![self isFormatChoiceWithImageOptions]) || + self.questionType == ORKQuestionTypeBoolean); +} + +- (BOOL)formatRequiresTableView { + return [self isFormatFitsChoiceCells]; +} + +- (NSSet *)requestedHealthKitTypesForReading { + HKObjectType *objType = [[self answerFormat] healthKitObjectTypeForAuthorization]; + return (objType != nil) ? [NSSet setWithObject:objType] : nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.h new file mode 100755 index 0000000..ecc2064 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.h @@ -0,0 +1,49 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKStepContainerView_Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKQuestionStep; +@class ORKQuestionStepCustomView; + +@interface ORKQuestionStepView : ORKStepContainerView + +@property (nonatomic, strong, nullable) ORKQuestionStep *questionStep; +@property (nonatomic, strong, nullable) ORKQuestionStepCustomView *questionCustomView; + +- (void)setCustomHeaderTitle:(nullable NSString *)text; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.m new file mode 100755 index 0000000..584e541 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepView.m @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKQuestionStepView.h" + +#import "ORKCustomStepView.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" + +#import "ORKBodyItem.h" +#import "ORKStep_Private.h" +#import "ORKQuestionStep_Internal.h" +#import "ORKSkin.h" + +@implementation ORKQuestionStepView + +- (void)setQuestionCustomView:(ORKQuestionStepCustomView *)questionCustomView { + _questionCustomView = questionCustomView; + questionCustomView.translatesAutoresizingMaskIntoConstraints = NO; + self.customContentView = _questionCustomView; +} + +- (void)setQuestionStep:(ORKQuestionStep *)step { + _questionStep = step; + self.stepTitle = step.title; + self.stepTopContentImage = step.image; + self.stepTopContentImageContentMode = step.imageContentMode; + self.titleIconImage = step.iconImage; + self.stepText = step.text; + // TODO:- we are currently not setting detailText to _headerView because we are restricting detailText to be displayed only inside ORKSurveyCardHeaderView, might wanna rethink this later. Please use the text property on ORKQuestionStep for adding extra information. + self.stepHeaderTextAlignment = step.headerTextAlignment; + self.bodyItems = step.bodyItems; +} + +- (void)setCustomHeaderTitle:(nullable NSString *)text { + if (text) { + self.stepTitle = text; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.h new file mode 100755 index 0000000..7367376 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKQuestionStepViewController` class is the concrete `ORKStepViewController` + implementation for `ORKQuestionStep`. + + You should not need to instantiate an `ORKQuestionStepViewController` object + directly. Instead, create an `ORKQuestionStep` object, include it in a task + the task using a task view controller. The task view + controller automatically instantiates the question step view controller + when it needs to present a question step. + + To use `ORKQuestionStepViewController` directly, create an `ORKQuestionStep` object and use + `initWithStep:` to initialize it. To receive the result of the question, and to determine + when to dismiss the view controller, implement `ORKStepViewControllerDelegate`. + */ + +ORK_CLASS_AVAILABLE +@interface ORKQuestionStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.m new file mode 100755 index 0000000..bd876dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController.m @@ -0,0 +1,997 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKQuestionStepViewController_Private.h" + +#import "ORKChoiceViewCell_Internal.h" +#import "ORKQuestionStepView.h" +#import "ORKLearnMoreView.h" +#import "ORKLearnMoreStepViewController.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKSurveyAnswerCellForScale.h" +#import "ORKSurveyAnswerCellForNumber.h" +#import "ORKSurveyAnswerCellForText.h" +#import "ORKSurveyAnswerCellForPicker.h" +#import "ORKSurveyAnswerCellForImageSelection.h" +#import "ORKSurveyAnswerCellForLocation.h" +#import "ORKSurveyAnswerCellForSES.h" +#import "ORKTableContainerView.h" +#import "ORKSurveyCardHeaderView.h" +#import "ORKTextChoiceCellGroup.h" +#import "ORKBodyItem.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKQuestionResult_Private.h" +#import "ORKQuestionStep_Internal.h" +#import "ORKResult_Private.h" +#import "ORKStep_Private.h" +#import "ORKStepContentView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +typedef NS_ENUM(NSInteger, ORKQuestionSection) { + ORKQuestionSectionAnswer = 0, + ORKQuestionSection_COUNT +}; + +static const CGFloat DelayBeforeAutoScroll = 0.25; + +@interface ORKQuestionStepViewController () { + id _answer; + + ORKTableContainerView *_tableContainer; + ORKStepContentView *_headerView; + ORKAnswerDefaultSource *_defaultSource; + + NSCalendar *_savedSystemCalendar; + NSTimeZone *_savedSystemTimeZone; + + ORKTextChoiceCellGroup *_choiceCellGroup; + ORKQuestionStepCellHolderView *_cellHolderView; + + id _defaultAnswer; + + BOOL _visible; + UITableViewCell *_currentFirstResponderCell; +} + +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, strong) ORKQuestionStepView *questionView; + +@property (nonatomic, strong) ORKAnswerFormat *answerFormat; +@property (nonatomic, copy) id answer; + +@property (nonatomic, strong) ORKContinueButton *continueActionButton; + +@property (nonatomic, strong) ORKSurveyAnswerCell *answerCell; + +@property (nonatomic, readonly) UILabel *questionLabel; +@property (nonatomic, readonly) UILabel *promptLabel; + +// If `hasChangedAnswer`, then a new `defaultAnswer` should not change the answer +@property (nonatomic, assign) BOOL hasChangedAnswer; + +@property (nonatomic, copy) id originalAnswer; + +@end + + +@implementation ORKQuestionStepViewController { + NSArray *_constraints; +} + +- (void)initializeInternalButtonItems { + [super initializeInternalButtonItems]; + self.internalSkipButtonItem.title = ORKLocalizedString(@"BUTTON_SKIP", nil); +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + self = [self initWithStep:step]; + if (self) { + ORKStepResult *stepResult = (ORKStepResult *)result; + if (stepResult && [stepResult results].count > 0) { + ORKQuestionResult *questionResult = ORKDynamicCast([stepResult results].firstObject, ORKQuestionResult); + id answer = [questionResult answer]; + if (questionResult != nil && answer == nil) { + answer = ORKNullAnswerValue(); + } + self.answer = answer; + self.originalAnswer = answer; + } + } + return self; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + _defaultSource = [ORKAnswerDefaultSource sourceWithHealthStore:[HKHealthStore new]]; + } + return self; +} + +- (void)stepDidChange { + [super stepDidChange]; + _answerFormat = [self.questionStep impliedAnswerFormat]; + + self.hasChangedAnswer = NO; + + if ([self isViewLoaded]) { + BOOL neediPadDesign = ORKNeedWideScreenDesign(self.view); + [_tableContainer removeFromSuperview]; + _tableView.delegate = nil; + _tableView.dataSource = nil; + _tableView = nil; + _headerView = nil; + _cellHolderView = nil; + _navigationFooterView = nil; + [_questionView removeFromSuperview]; + _questionView = nil; + + if ([self.questionStep formatRequiresTableView] && !_customQuestionView) { + _tableContainer = [[ORKTableContainerView alloc] initWithStyle:UITableViewStyleGrouped pinNavigationContainer:NO]; + + // Create a new one (with correct style) + _tableView = _tableContainer.tableView; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.clipsToBounds = YES; + + _navigationFooterView = _tableContainer.navigationFooterView; + [self setNavigationFooterButtonItems]; + + [self.view addSubview:_tableContainer]; + _tableContainer.tapOffView = self.view; + + _headerView = _tableContainer.stepContentView; + if (self.questionStep.useCardView) { + _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 13.0, *)) { + [_tableView setBackgroundColor:UIColor.systemGroupedBackgroundColor]; + } else { + [_tableView setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } + [self.taskViewController.navigationBar setBarTintColor:[_tableView backgroundColor]]; + [self.view setBackgroundColor:[_tableView backgroundColor]]; + } + + _headerView.stepTopContentImage = self.step.image; + _headerView.titleIconImage = self.step.iconImage; + _headerView.stepTitle = self.step.title; + _headerView.stepText = self.step.text; + // TODO:- we are currently not setting detailText to _headerView because we are restricting detailText to be displayed only inside ORKSurveyCardHeaderView, might wanna rethink this later. Please use the text property on ORKQuestionStep for adding extra information. + _headerView.stepHeaderTextAlignment = self.step.headerTextAlignment; + _headerView.bodyItems = self.step.bodyItems; + _tableContainer.stepTopContentImageContentMode = self.step.imageContentMode; + _navigationFooterView.optional = self.step.optional; + if (self.readOnlyMode) { + _navigationFooterView.optional = YES; + [_navigationFooterView setNeverHasContinueButton:YES]; + _navigationFooterView.skipEnabled = [self skipButtonEnabled]; + _navigationFooterView.skipButton.accessibilityTraits = UIAccessibilityTraitStaticText; + } + if (neediPadDesign) { + [_tableContainer setBackgroundColor:[UIColor clearColor]]; + [_tableView setBackgroundColor:[UIColor clearColor]]; + } + [self setupConstraints:_tableContainer]; + [_tableContainer setNeedsLayout]; + + // Question steps should always force the navigation controller to be scrollable + // therefore we should always remove the styling. + [_navigationFooterView removeStyling]; + } else if (self.step) { + _questionView = [ORKQuestionStepView new]; + _questionView.isNavigationContainerScrollable = YES; + + ORKQuestionStep *step = [self questionStep]; + _navigationFooterView = _questionView.navigationFooterView; + [self setNavigationFooterButtonItems]; + _navigationFooterView.useNextForSkip = (step ? NO : YES); + _questionView.questionStep = step; + _navigationFooterView.optional = step.optional; + [_navigationFooterView updateContinueAndSkipEnabled]; + + [self.view addSubview:_questionView]; + + if (_customQuestionView) { + _questionView.questionCustomView = _customQuestionView; + _customQuestionView.delegate = self; + _customQuestionView.answer = [self answer]; + _customQuestionView.userInteractionEnabled = !self.readOnlyMode; + } else { + _cellHolderView = [ORKQuestionStepCellHolderView new]; + _cellHolderView.delegate = self; + _cellHolderView.cell = [self answerCellForTableView:nil]; + [NSLayoutConstraint activateConstraints: + [_cellHolderView.cell suggestedCellHeightConstraintsForView:self.parentViewController.view]]; + _cellHolderView.answer = [self answer]; + _cellHolderView.userInteractionEnabled = !self.readOnlyMode; + if (self.questionStep.useCardView) { + if (@available(iOS 13.0, *)) { + [_questionView setBackgroundColor:UIColor.systemGroupedBackgroundColor]; + } else { + [_questionView setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } + [self.taskViewController.navigationBar setBarTintColor:[_questionView backgroundColor]]; + [self.view setBackgroundColor:[_questionView backgroundColor]]; + ORKLearnMoreView *learnMoreView; + NSString *sectionProgressText = nil; + + if (self.step.showsProgress) { + if ([self.delegate respondsToSelector:@selector(stepViewControllerTotalProgressInfoForStep:currentStep:)]) { + ORKTaskTotalProgress progressInfo = [self.delegate stepViewControllerTotalProgressInfoForStep:self currentStep:self.step]; + if (progressInfo.stepShouldShowTotalProgress) { + sectionProgressText = [NSString localizedStringWithFormat:ORKLocalizedString(@"FORM_ITEM_PROGRESS", nil) ,ORKLocalizedStringFromNumber(@(progressInfo.currentStepStartingProgressPosition)), ORKLocalizedStringFromNumber(@(progressInfo.total))]; + } + } + } + + if (self.questionStep.learnMoreItem) { + learnMoreView = [ORKLearnMoreView learnMoreViewWithItem:self.questionStep.learnMoreItem]; + learnMoreView.delegate = self; + } + + BOOL hasMultipleChoiceFormItem = NO; + if (self.questionStep.impliedAnswerFormat != nil && self.questionStep.impliedAnswerFormat.questionType == ORKQuestionTypeMultipleChoice) { + hasMultipleChoiceFormItem = YES; + } + + [_cellHolderView useCardViewWithTitle:self.questionStep.question detailText:self.step.detailText learnMoreView:learnMoreView progressText:sectionProgressText tagText:self.questionStep.tagText hasMultipleChoiceFormItem:hasMultipleChoiceFormItem]; + } + _questionView.questionCustomView = _cellHolderView; + } + + _questionView.translatesAutoresizingMaskIntoConstraints = NO; + [_questionView removeCustomContentPadding]; + + if (self.readOnlyMode) { + _navigationFooterView.optional = YES; + [_navigationFooterView setNeverHasContinueButton:YES]; + _navigationFooterView.skipEnabled = [self skipButtonEnabled]; + _navigationFooterView.skipButton.accessibilityTraits = UIAccessibilityTraitStaticText; + } + if (neediPadDesign) { + [_questionView setBackgroundColor:[UIColor clearColor]]; + } + [self setupConstraints:_questionView]; + } + } + + if ([self allowContinue] == NO) { + self.continueButtonItem = self.internalContinueButtonItem; + } +} + +- (void)setNavigationFooterButtonItems { + if (_navigationFooterView) { + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + } +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + if (_tableContainer) { + [_tableContainer sizeHeaderToFit]; + [_tableContainer resizeFooterToFit]; + } +} + +- (void)setupConstraints:(UIView *)view { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + + view.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self stepDidChange]; + +} + +- (BOOL)showValidityAlertWithMessage:(NSString *)text { + // Ignore if our answer is null + if (self.answer == ORKNullAnswerValue()) { + return NO; + } + + return [super showValidityAlertWithMessage:text]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + if (_tableView) { + [self.taskViewController setRegisteredScrollView:_tableView]; + } + + + NSMutableSet *types = [NSMutableSet set]; + ORKAnswerFormat *format = [[self questionStep] answerFormat]; + HKObjectType *objType = [format healthKitObjectTypeForAuthorization]; + if (objType) { + [types addObject:objType]; + } + + BOOL scheduledRefresh = NO; + if (types.count) { + NSSet *alreadyRequested = [[self taskViewController] requestedHealthTypesForRead]; + if (![types isSubsetOfSet:alreadyRequested]) { + scheduledRefresh = YES; + [_defaultSource.healthStore requestAuthorizationToShareTypes:nil readTypes:types completion:^(BOOL success, NSError *error) { + if (success) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self refreshDefaults]; + }); + } + }]; + } + } + if (!scheduledRefresh) { + [self refreshDefaults]; + } + if (_tableContainer) { + [_tableContainer sizeHeaderToFit]; + [_tableContainer resizeFooterToFit]; + [_tableContainer layoutIfNeeded]; + } + + if (_tableView) { + [_tableView reloadData]; + } +} + +- (void)answerDidChange { + if ([self.questionStep formatRequiresTableView] && !_customQuestionView) { + [self.tableView reloadData]; + } else { + if (_customQuestionView) { + _customQuestionView.answer = _answer; + } else { + ORKQuestionStepCellHolderView *holder = (ORKQuestionStepCellHolderView *)_questionView.questionCustomView; + holder.answer = _answer; + [self.answerCell setAnswer:_answer]; + } + } + [self updateButtonStates]; +} + +- (void)refreshDefaults { + [_defaultSource fetchDefaultValueForAnswerFormat:[[self questionStep] answerFormat] handler:^(id defaultValue, NSError *error) { + if (defaultValue != nil || error == nil) { + dispatch_async(dispatch_get_main_queue(), ^{ + _defaultAnswer = defaultValue; + [self defaultAnswerDidChange]; + }); + } else { + ORK_Log_Error("Error fetching default: %@", error); + } + }]; +} + +- (void)defaultAnswerDidChange { + id defaultAnswer = _defaultAnswer; + if (![self hasAnswer] && defaultAnswer && !self.hasChangedAnswer) { + _answer = defaultAnswer; + + [self answerDidChange]; + } +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + _visible = YES; + + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + // TODO: Remove reloadData later. + [_tableView reloadData]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + _visible = NO; +} + +- (void)setCustomQuestionView:(ORKQuestionStepCustomView *)customQuestionView { + [_customQuestionView removeFromSuperview]; + _customQuestionView = customQuestionView; + if ([_customQuestionView constraints].count == 0) { + _customQuestionView.translatesAutoresizingMaskIntoConstraints = NO; + + CGSize requiredSize = [_customQuestionView sizeThatFits:(CGSize){self.view.bounds.size.width, CGFLOAT_MAX}]; + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:_customQuestionView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:requiredSize.height]; + + heightConstraint.priority = UILayoutPriorityDefaultLow; + [NSLayoutConstraint activateConstraints:@[heightConstraint]]; + } + [self stepDidChange]; +} + +- (void)updateButtonStates { + if ([self isStepImmediateNavigation]) { +// _navigationFooterView.neverHasContinueButton = YES; +// _navigationFooterView.continueButtonItem = nil; + } + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.skipEnabled = [self skipButtonEnabled]; +} + +// Override to monitor button title change +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; + [self updateButtonStates]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + + _navigationFooterView.skipButtonItem = self.skipButtonItem; + [self updateButtonStates]; +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + ORKQuestionStep *questionStep = self.questionStep; + + if (self.answer) { + ORKQuestionResult *result = [questionStep.answerFormat resultWithIdentifier:questionStep.identifier answer:self.answer]; + ORKAnswerFormat *impliedAnswerFormat = [questionStep impliedAnswerFormat]; + + if ([impliedAnswerFormat isKindOfClass:[ORKDateAnswerFormat class]]) { + ORKDateQuestionResult *dateQuestionResult = (ORKDateQuestionResult *)result; + if (dateQuestionResult.dateAnswer) { + NSCalendar *usedCalendar = [(ORKDateAnswerFormat *)impliedAnswerFormat calendar] ? : _savedSystemCalendar; + dateQuestionResult.calendar = [NSCalendar calendarWithIdentifier:usedCalendar.calendarIdentifier ? : [NSCalendar currentCalendar].calendarIdentifier]; + dateQuestionResult.timeZone = _savedSystemTimeZone ? : [NSTimeZone systemTimeZone]; + } + } else if ([impliedAnswerFormat isKindOfClass:[ORKNumericAnswerFormat class]]) { + ORKNumericQuestionResult *nqr = (ORKNumericQuestionResult *)result; + if (nqr.unit == nil) { + nqr.unit = [(ORKNumericAnswerFormat *)impliedAnswerFormat unit]; + } + } + + result.startDate = parentResult.startDate; + result.endDate = parentResult.endDate; + + parentResult.results = @[result]; + } + + return parentResult; +} + +#pragma mark - Internal + +- (ORKQuestionStep *)questionStep { + assert(!self.step || [self.step isKindOfClass:[ORKQuestionStep class]]); + return (ORKQuestionStep *)self.step; +} + +- (BOOL)hasAnswer { + return !ORKIsAnswerEmpty(self.answer); +} + +- (void)saveAnswer:(id)answer { + self.answer = answer; + _savedSystemCalendar = [NSCalendar currentCalendar]; + _savedSystemTimeZone = [NSTimeZone systemTimeZone]; + [self notifyDelegateOnResultChange]; +} + +- (void)skipForward { + // Null out the answer before proceeding + [self saveAnswer:ORKNullAnswerValue()]; + ORKSurveyAnswerCell *cell = self.answerCell; + cell.answer = ORKNullAnswerValue(); + + [super skipForward]; +} + +- (void)notifyDelegateOnResultChange { + [super notifyDelegateOnResultChange]; + + if (self.hasNextStep == NO) { + self.continueButtonItem = self.internalDoneButtonItem; + } else { + self.continueButtonItem = self.internalContinueButtonItem; + } + + self.skipButtonItem = self.internalSkipButtonItem; + if (!self.questionStep.optional && !self.readOnlyMode) { + self.skipButtonItem = nil; + } + + if ([self allowContinue] == NO) { + self.continueButtonItem = self.internalContinueButtonItem; + } + + [self.tableView reloadData]; +} + +- (id)answer { + if (self.questionStep.questionType == ORKQuestionTypeMultipleChoice && (_answer == nil || _answer == ORKNullAnswerValue())) { + _answer = [NSMutableArray array]; + } + return _answer; +} + +- (void)setAnswer:(id)answer { + _answer = answer; +} + +- (BOOL)continueButtonEnabled { + BOOL enabled = ([self hasAnswer] || (self.questionStep.optional && !self.skipButtonItem)); + if (self.isBeingReviewed) { + enabled = enabled && (![self.answer isEqual:self.originalAnswer]); + } + return enabled; +} + +- (BOOL)skipButtonEnabled { + BOOL enabled = [self questionStep].optional; + if (self.isBeingReviewed) { + enabled = self.readOnlyMode ? NO : enabled && !ORKIsAnswerEmpty(self.originalAnswer); + } + return enabled; +} + +- (BOOL)allowContinue { + return !(self.questionStep.optional == NO && [self hasAnswer] == NO); +} + +// Not to use `ImmediateNavigation` when current step already has an answer. +// So user is able to review the answer when it is present. +- (BOOL)isStepImmediateNavigation { + // FIXME: - add explicit property in QuestionStep to dictate this behavior +// return [self.questionStep isFormatImmediateNavigation] && [self hasAnswer] == NO && !self.isBeingReviewed; + return NO; +} + +#pragma mark - ORKQuestionStepCustomViewDelegate + +- (void)customQuestionStepView:(ORKQuestionStepCustomView *)customQuestionStepView didChangeAnswer:(id)answer { + [self saveAnswer:answer]; + self.hasChangedAnswer = YES; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return ORKQuestionSection_COUNT; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + + if ([self questionStep].useCardView && [self questionStep].question) { + ORKLearnMoreView *learnMoreView; + NSString *sectionProgressText = nil; + BOOL hasMultipleChoiceFormItem = NO; + + if (self.step.showsProgress) { + if ([self.delegate respondsToSelector:@selector(stepViewControllerTotalProgressInfoForStep:currentStep:)]) { + ORKTaskTotalProgress progressInfo = [self.delegate stepViewControllerTotalProgressInfoForStep:self currentStep:self.step]; + if (progressInfo.stepShouldShowTotalProgress) { + sectionProgressText = [NSString localizedStringWithFormat:ORKLocalizedString(@"FORM_ITEM_PROGRESS", nil) ,ORKLocalizedStringFromNumber(@(section + progressInfo.currentStepStartingProgressPosition)), ORKLocalizedStringFromNumber(@(progressInfo.total))]; + } + } + } + + if (self.questionStep.learnMoreItem) { + learnMoreView = [ORKLearnMoreView learnMoreViewWithItem:self.questionStep.learnMoreItem]; + learnMoreView.delegate = self; + } + + if (self.questionStep.impliedAnswerFormat != nil && self.questionStep.impliedAnswerFormat.questionType == ORKQuestionTypeMultipleChoice) { + hasMultipleChoiceFormItem = YES; + } + + return [[ORKSurveyCardHeaderView alloc] initWithTitle:self.questionStep.question detailText:self.questionStep.detailText learnMoreView:learnMoreView progressText:sectionProgressText tagText:self.questionStep.tagText showBorder:NO hasMultipleChoiceItem:hasMultipleChoiceFormItem]; + } + return nil; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + ORKAnswerFormat *impliedAnswerFormat = [_answerFormat impliedAnswerFormat]; + + if (section == ORKQuestionSectionAnswer) { + if (!_choiceCellGroup) { + _choiceCellGroup = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:(ORKTextChoiceAnswerFormat *)impliedAnswerFormat + answer:self.answer + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:section] + immediateNavigation:[self isStepImmediateNavigation]]; + _choiceCellGroup.delegate = self; + } + return _choiceCellGroup.size; + } + return 0; +} + +- (ORKSurveyAnswerCell *)answerCellForTableView:(UITableView *)tableView { + static NSDictionary *typeAndCellMapping = nil; + static NSString *identifier = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + typeAndCellMapping = @{@(ORKQuestionTypeScale): [ORKSurveyAnswerCellForScale class], + @(ORKQuestionTypeDecimal): [ORKSurveyAnswerCellForNumber class], + @(ORKQuestionTypeText): [ORKSurveyAnswerCellForText class], + @(ORKQuestionTypeTimeOfDay): [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeDate): [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeDateAndTime): [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeTimeInterval): [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeHeight) : [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeWeight) : [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeMultiplePicker) : [ORKSurveyAnswerCellForPicker class], + @(ORKQuestionTypeInteger): [ORKSurveyAnswerCellForNumber class], + @(ORKQuestionTypeLocation): [ORKSurveyAnswerCellForLocation class], + @(ORKQuestionTypeSES): [ORKSurveyAnswerCellForSES class]}; + }); + + // SingleSelectionPicker Cell && Other Cells + Class class = typeAndCellMapping[@(self.questionStep.questionType)]; + + if ([self.questionStep isFormatChoiceWithImageOptions]) { + class = [ORKSurveyAnswerCellForImageSelection class]; + } else if ([self.questionStep isFormatTextfield]) { + // Override for single-line text entry + class = [ORKSurveyAnswerCellForTextField class]; + } else if ([[self.questionStep impliedAnswerFormat] isKindOfClass:[ORKValuePickerAnswerFormat class]]) { + class = [ORKSurveyAnswerCellForPicker class]; + } + + identifier = NSStringFromClass(class); + + NSAssert(class != nil, @"class should not be nil"); + + ORKSurveyAnswerCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + + if (cell == nil) { + cell = [[class alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier step:[self questionStep] answer:self.answer delegate:self]; + } + + self.answerCell = cell; + + if ([self.questionStep isFormatTextfield] || + [cell isKindOfClass:[ORKSurveyAnswerCellForScale class]] || + [cell isKindOfClass:[ORKSurveyAnswerCellForPicker class]]) { + cell.separatorInset = UIEdgeInsetsMake(0, ORKScreenMetricMaxDimension, 0, 0); + } + + if ([cell isKindOfClass:[ORKSurveyAnswerCellForPicker class]] && _visible) { + [(ORKSurveyAnswerCellForPicker *)cell loadPicker]; + } + + return cell; +} + +// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: +// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + tableView.layoutMargins = UIEdgeInsetsZero; + + ////////////////////////////////// + // Section for Answer Area + ////////////////////////////////// + + static NSString *identifier = nil; + + assert (self.questionStep.isFormatFitsChoiceCells); + + identifier = [NSStringFromClass([self class]) stringByAppendingFormat:@"%@", @(indexPath.row)]; + + ORKChoiceViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + if (!cell) { + cell = [_choiceCellGroup cellAtIndexPath:indexPath withReuseIdentifier:identifier]; + } + + if ([cell isKindOfClass:[ORKChoiceOtherViewCell class]]) { + ORKChoiceOtherViewCell *otherCell = (ORKChoiceOtherViewCell *)cell; + otherCell.delegate = self; + cell = otherCell; + } + + cell.useCardView = self.questionStep.useCardView; + cell.userInteractionEnabled = !self.readOnlyMode; + + cell.isLastItem = indexPath.row == _choiceCellGroup.size - 1; + cell.isFirstItemInSectionWithoutTitle = (indexPath.row == 0 && ![self questionStep].question); + return cell; +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { + cell.layoutMargins = UIEdgeInsetsZero; + cell.separatorInset = (UIEdgeInsets){.left = ORKStandardLeftMarginForTableViewCell(tableView)}; +} + +- (BOOL)shouldContinue { + ORKSurveyAnswerCell *cell = self.answerCell; + if (!cell) { + return YES; + } + + return [cell shouldContinue]; +} + +- (void)goForward { + if (![self shouldContinue]) { + return; + } + + [self notifyDelegateOnResultChange]; + [super goForward]; +} + +- (void)goBackward { + if (self.isBeingReviewed) { + [self saveAnswer:self.originalAnswer]; + } + [self notifyDelegateOnResultChange]; + [super goBackward]; +} + +- (void)continueAction:(id)sender { + if (self.continueActionButton.enabled) { + if (![self shouldContinue]) { + return; + } + + ORKSuppressPerformSelectorWarning( + [self.continueButtonItem.target performSelector:self.continueButtonItem.action withObject:self.continueButtonItem];); + } +} + +- (void)setShouldPresentInReview:(BOOL)shouldPresentInReview { + [super setShouldPresentInReview:shouldPresentInReview]; + [_navigationFooterView setHidden:YES]; +} + +#pragma mark - UITableViewDelegate + +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.section != ORKQuestionSectionAnswer) { + return nil; + } + if (NO == self.questionStep.isFormatFitsChoiceCells) { + return nil; + } + return indexPath; +} + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { + return indexPath.section == ORKQuestionSectionAnswer; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + if (_choiceCellGroup.answerFormat.style == ORKChoiceAnswerStyleSingleChoice && ![self hasAnswer]) { + [self.tableView scrollRectToVisible:[self.tableView convertRect:self.tableView.tableFooterView.bounds fromView:self.tableView.tableFooterView] animated:YES]; + } + + [_choiceCellGroup didSelectCellAtIndexPath:indexPath]; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + CGFloat height = [ORKSurveyAnswerCell suggestedCellHeightForView:tableView]; + + switch (self.questionStep.questionType) { + case ORKQuestionTypeSingleChoice: + case ORKQuestionTypeMultipleChoice:{ + if ([self.questionStep isFormatFitsChoiceCells]) { + return UITableViewAutomaticDimension; + } else { + height = [ORKSurveyAnswerCellForPicker suggestedCellHeightForView:tableView]; + } + } + break; + case ORKQuestionTypeInteger: + case ORKQuestionTypeDecimal:{ + height = [ORKSurveyAnswerCellForNumber suggestedCellHeightForView:tableView]; + } + break; + case ORKQuestionTypeText:{ + height = [ORKSurveyAnswerCellForText suggestedCellHeightForView:tableView]; + } + break; + case ORKQuestionTypeTimeOfDay: + case ORKQuestionTypeTimeInterval: + case ORKQuestionTypeDate: + case ORKQuestionTypeDateAndTime:{ + height = [ORKSurveyAnswerCellForPicker suggestedCellHeightForView:tableView]; + } + break; + default:{ + } + break; + } + + return height; +} + + +#pragma mark - ORKSurveyAnswerCellDelegate + +- (void)answerCell:(ORKSurveyAnswerCell *)cell answerDidChangeTo:(id)answer dueUserAction:(BOOL)dueUserAction { + [self saveAnswer:answer]; + + if (self.hasChangedAnswer == NO && dueUserAction == YES) { + self.hasChangedAnswer = YES; + } +} + +- (void)answerCell:(ORKSurveyAnswerCell *)cell invalidInputAlertWithMessage:(NSString *)input { + [self showValidityAlertWithMessage:input]; +} + +- (void)answerCell:(ORKSurveyAnswerCell *)cell invalidInputAlertWithTitle:(NSString *)title message:(NSString *)message { + [self showValidityAlertWithTitle:title message:message]; +} + +static NSString *const _ORKAnswerRestoreKey = @"answer"; +static NSString *const _ORKHasChangedAnswerRestoreKey = @"hasChangedAnswer"; +static NSString *const _ORKOriginalAnswerRestoreKey = @"originalAnswer"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_answer forKey:_ORKAnswerRestoreKey]; + [coder encodeBool:_hasChangedAnswer forKey:_ORKHasChangedAnswerRestoreKey]; + [coder encodeObject:_originalAnswer forKey:_ORKOriginalAnswerRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + NSSet *decodeableSet = [NSSet setWithObjects:[NSNumber class], [NSString class], [NSDateComponents class], [NSArray class], nil]; + self.answer = [coder decodeObjectOfClasses:decodeableSet forKey:_ORKAnswerRestoreKey]; + self.hasChangedAnswer = [coder decodeBoolForKey:_ORKHasChangedAnswerRestoreKey]; + self.originalAnswer = [coder decodeObjectOfClasses:decodeableSet forKey:_ORKOriginalAnswerRestoreKey]; + + [self answerDidChange]; +} + +#pragma mark - ORKTableContainerViewDelegate; + +- (nonnull UITableViewCell *)currentFirstResponderCellForTableContainerView:(nonnull ORKTableContainerView *)tableContainerView { + return _currentFirstResponderCell; +} + +#pragma mark - ORKTextChoiceCellGroupDelegate + +- (void)answerChangedForIndexPath:(NSIndexPath *)indexPath { + // Capture `isStepImmediateNavigation` before saving an answer. + BOOL immediateNavigation = [self isStepImmediateNavigation]; + + id answer = (self.questionStep.questionType == ORKQuestionTypeBoolean) ? [_choiceCellGroup answerForBoolean] :[_choiceCellGroup answer]; + + [self saveAnswer:answer]; + self.hasChangedAnswer = YES; + + if (immediateNavigation) { + // Proceed as continueButton tapped + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayBeforeAutoScroll * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + ORKSuppressPerformSelectorWarning( + [self.continueButtonItem.target performSelector:self.continueButtonItem.action withObject:self.continueButtonItem];); + }); + } +} + +- (void)tableViewCellHeightUpdated { + [_tableView reloadData]; +} + +#pragma mark - ORKChoiceOtherViewCellDelegate + +- (void)textChoiceOtherCellDidBecomeFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell { + _currentFirstResponderCell = choiceOtherViewCell; + NSIndexPath *indexPath = [_tableView indexPathForCell:choiceOtherViewCell]; + if (indexPath) { + [_tableContainer scrollCellVisible:choiceOtherViewCell animated:YES]; + } +} + +- (void)textChoiceOtherCellDidResignFirstResponder:(ORKChoiceOtherViewCell *)choiceOtherViewCell { + if (_currentFirstResponderCell == choiceOtherViewCell) { + _currentFirstResponderCell = nil; + } + NSIndexPath *indexPath = [_tableView indexPathForCell:choiceOtherViewCell]; + [_choiceCellGroup textViewDidResignResponderForCellAtIndexPath:indexPath]; +} + +//FIXME: Need Accessibility for Continue and skip button. Lost support when moved navigationFooterViewView outside VerticalContainerView. + +// if (_navigationFooterView.continueButton != nil) { +// [elements addObject:self.continueSkipContainer.continueButton]; +// } +// if (_navigationFooterView.skipButton != nil) { +// [elements addObject:self.continueSkipContainer.skipButton]; +// } + +#pragma mark - ORKLearnViewDelegate + +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep { + [self.taskViewController learnMoreButtonPressedWithStep:learnMoreStep fromStepViewController:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController_Private.h new file mode 100755 index 0000000..204bed4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStepViewController_Private.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKQuestionStepViewController () + +/** + Provide a custom question view. + + If a question requires a custom control for data entry, provide a suitable + custom step view. This view should provide `-sizeThatFits:` or autolayout + constraints which determine the vertical space required. + */ +@property (nonatomic, strong, nullable) ORKQuestionStepCustomView *customQuestionView; + +/** + Set the step answer. + */ +- (void)setAnswer:(id)answer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep_Internal.h new file mode 100755 index 0000000..87d2cca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKQuestionStep_Internal.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKQuestionStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKQuestionStep () + +- (BOOL)isFormatImmediateNavigation; +- (BOOL)isFormatChoiceWithImageOptions; +- (BOOL)isFormatFitsChoiceCells; +- (BOOL)isFormatTextfield; + +- (BOOL)formatRequiresTableView; + +- (nullable ORKAnswerFormat *)impliedAnswerFormat; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.h new file mode 100755 index 0000000..67a25dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKResult` class defines the attributes of a result from one step or a group + of steps. When you use the ResearchKit framework APIs, you typically get a result from the `result` property + of either `ORKTaskViewController` or `ORKStepViewController`. + Certain types of results can contain other results, which together express a hierarchy; examples of these types of results are `ORKCollectionResult` subclasses, such as `ORKStepResult` and `ORKTaskResult`. + + When you receive a result, you can store it temporarily by archiving it with + `NSKeyedArchiver`, because all `ORKResult` objects implement `NSSecureCoding`. If you want to serialize the result object to other formats, you're responsible for implementing this. + + The result object hierarchy does not necessarily include all the data collected + during a task. Some result objects, such as `ORKFileResult`, may refer to files + in the filesystem that were generated during the task. These files are easy to find, because they are all + located in the output directory of the task view controller. + + It's recommended that you use `NSFileProtectionComplete` (at a minimum) to protect these files, and that you similarly protect all serialization of `ORKResult` objects that you write to disk. It is also generally helpful to keep the results together with the referenced files as you submit them to a back-end server. For example, it can be convenient to zip all data corresponding to a particular task result into a single compressed archive. + + Every object in the result hierarchy has an identifier that should correspond + to the identifier of an object in the original step hierarchy. Similarly, every + object has a start date and an end date that correspond to the range of + times during which the result was collected. In an `ORKStepResult` object, for example, + the start and end dates cover the range of time during which the step view controller was visible on + screen. + + When you implement a new type of step, it is usually helpful to create a new + `ORKResult` subclass to hold the type of result data the step can generate, unless it makes sense to use an existing subclass. Return your custom result subclass as one of the results attached to the step's `ORKStepResult` object. + */ +ORK_CLASS_AVAILABLE +@interface ORKResult : NSObject + +/** + Returns an initialized result using the specified identifier. + + Typically, objects such as `ORKStepViewController` and `ORKTaskViewController` instantiate result (and `ORKResult` subclass) objects; you seldom need to instantiate a result object in your code. + + @param identifier The unique identifier of the result. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier; + +/** + A meaningful identifier for the result. + + The identifier can be used to identify the question + that was asked or the task that was completed to produce the result. Typically, the identifier is copied from the originating object by the view controller or recorder that produces it. + + For example, a task result receives its identifier from a task, + a step result receives its identifier from a step, + and a question result receives its identifier from a step or a form item. + Results that are generated by recorders also receive an identifier that corresponds to + that recorder. + */ +@property (nonatomic, copy) NSString *identifier; + +/** + The time when the task, step, or data collection began. + + The value of this property is set by the view controller or recorder that produces the result, + to indicate when data collection started. + + Note that for instantaneous items, `startDate` and `endDate` can have the same value, and should + generally correspond to the end of the instantaneous data collection period. + */ +@property (nonatomic, copy) NSDate *startDate; + +/** + The time when the task, step, or data collection stopped. + + The value of this property is set by the view controller or recorder that produces the result, + to indicate when data collection stopped. + + Note that for instantaneous items, `startDate` and `endDate` can have the same value, and should + generally correspond to the end of the instantaneous data collection period. + */ +@property (nonatomic, copy) NSDate *endDate; + +/** + Metadata that describes the conditions under which the result was acquired. + + The `userInfo` dictionary can be set by the view controller or recorder + that produces the result. However, it's often a better choice to use a new `ORKResult` subclass for passing additional information back to code that uses + the framework, because using + typed accessors is safer than using a dictionary. + + The user info dictionary must contain only keys and values that are suitable for property + list or JSON serialization. + */ +@property (nonatomic, copy, nullable) NSDictionary *userInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.m new file mode 100755 index 0000000..ea69f0e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult.m @@ -0,0 +1,128 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKResult.h" +#import "ORKResult_Private.h" + +#import "ORKHelpers_Internal.h" + + +const NSUInteger NumberOfPaddingSpacesForIndentationLevel = 4; + +@implementation ORKResult + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + self.identifier = identifier; + self.startDate = [NSDate date]; + self.endDate = [NSDate date]; + } + return self; +} + +- (BOOL)isSaveable { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); + ORK_ENCODE_OBJ(aCoder, startDate); + ORK_ENCODE_OBJ(aCoder, endDate); + ORK_ENCODE_OBJ(aCoder, userInfo); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, startDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, endDate, NSDate); + ORK_DECODE_OBJ_CLASS(aDecoder, userInfo, NSDictionary); + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.identifier, castObject.identifier) + && ORKEqualObjects(self.startDate, castObject.startDate) + && ORKEqualObjects(self.endDate, castObject.endDate) + && ORKEqualObjects(self.userInfo, castObject.userInfo)); +} + +- (NSUInteger)hash { + return _identifier.hash ^ _startDate.hash ^ _endDate.hash ^ _userInfo.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKResult *result = [[[self class] allocWithZone:zone] init]; + result.startDate = [self.startDate copy]; + result.endDate = [self.endDate copy]; + result.userInfo = [self.userInfo copy]; + result.identifier = [self.identifier copy]; + return result; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.startDate = [NSDate date]; + self.endDate = [NSDate date]; + } + return self; +} + +- (NSString *)descriptionPrefixWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@<%@: %p; identifier: \"%@\"", ORKPaddingWithNumberOfSpaces(numberOfPaddingSpaces), self.class.description, self, self.identifier]; +} + +- (NSString *)descriptionSuffix { + return @">"; +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.descriptionSuffix]; +} + +- (NSString *)description { + return [self descriptionWithNumberOfPaddingSpaces:0]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.h new file mode 100755 index 0000000..2c3fd51 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.h @@ -0,0 +1,538 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_EXTERN NSString *const ORKResultPredicateTaskIdentifierVariableName ORK_AVAILABLE_DECL; + +#define ORKIgnoreDoubleValue (NAN) +#define ORKIgnoreTimeIntervalValue (ORKIgnoreDoubleValue) + +/** + The `ORKResultSelector` class unequivocally identifies a result within a set of task results. + + You must use an instance of this object to specify the question result you are interested in when + building a result predicate. See `ORKResultPredicate` for more information. + + A result selector object contains a result identifier and, optionally, a task identifier and a step + identifier. If the task identifier is `nil`, the selector refers to a result in the ongoing task. + If you set the step identifier to `nil`, its value will be the same as the result identifier. + */ +ORK_CLASS_AVAILABLE +@interface ORKResultSelector : NSObject + +/* + The `init` and `new` methods are unavailable. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a result selector initialized with the specified arguments. + + @param taskIdentifier An optional task identifier string. + @param stepIdentifier An optional step identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ ++ (instancetype)selectorWithTaskIdentifier:(nullable NSString *)taskIdentifier + stepIdentifier:(nullable NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param taskIdentifier An optional task identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ ++ (instancetype)selectorWithTaskIdentifier:(nullable NSString *)taskIdentifier + resultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param stepIdentifier An optional step identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ ++ (instancetype)selectorWithStepIdentifier:(nullable NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param resultIdentifier The result identifier string. + + @return A result selector. + */ ++ (instancetype)selectorWithResultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param taskIdentifier An optional task identifier string. + @param stepIdentifier An optional step identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ +- (instancetype)initWithTaskIdentifier:(nullable NSString *)taskIdentifier + stepIdentifier:(nullable NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a result selector initialized with the specified arguments. + + @param taskIdentifier An optional task identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ +- (instancetype)initWithTaskIdentifier:(nullable NSString *)taskIdentifier + resultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param stepIdentifier An optional step identifier string. + @param resultIdentifier The result identifier string. + + @return A result selector. + */ +- (instancetype)initWithStepIdentifier:(nullable NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier; + +/** + Returns a result selector initialized with the specified arguments. + + @param resultIdentifier The result identifier string. + + @return A result selector. + */ +- (instancetype)initWithResultIdentifier:(NSString *)resultIdentifier; + +/** + The encapsulated task identifier. + + A `nil` value means that the referenced task is the current one. + */ +@property (nonatomic, copy, nullable) NSString *taskIdentifier; + +/** + The encapsulated step identifier. + + Setting this property to `nil` makes it have the same value as the result identifier. + */ +@property (nonatomic, copy, nullable) NSString *stepIdentifier; + +/** + The encapsulated result identifier. + + This property cannot be `nil`. + */ +@property (nonatomic, copy) NSString *resultIdentifier; + +@end + + +/** + The `ORKResultPredicate` class provides convenience class methods to build predicates for most of + the `ORKQuestionResult` subtypes. + + You use result predicates to create `ORKPredicateStepNavigationRule` objects. The result predicates + are used to match specific ORKQuestionResult instances (created in response to the participant's + answers) and navigate accordingly. You can match results both in an ongoing task or in previously + completed tasks. + + You chose which question result to match by using an `ORKResultSelector` object. + + Note that each `ORKStep` object produces one `ORKStepResult` collection object. A step + result produced by an `ORKQuestionStep` object contains one `ORKQuestionResult` object which has + + the same identifier as the step that generated it. A step result produced by an `ORKFormStep` + object can contain one or more `ORKQuestionResult` objects that have the identifiers of the + `ORKFormItem` objects that generated them. + + For matching a single-question step result, you only need to set the `resultIdentifier` when + building the result selector object. The `stepIdentifier` will take the same value. + + For matching a form item result, you need to build a result selector with a `stepIdentifier` (the + form step identifier) and a `resultIdentifier` (the form item result identifier). + + For matching results in the ongoing task, leave the `taskIdentifier` in the the form step identifier + as `nil`. For matching results in different tasks, set the `taskIdentifier` appropriately. + + */ +ORK_CLASS_AVAILABLE +@interface ORKResultPredicate : NSObject + +/* + The `init` and `new` methods are unavailable. `ORKResultPredicate` only provides class methods and + should not be instantiated. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a predicate matching a result of the kind `ORKQuestionResult` whose answer is `nil`. + A question result has a `nil` answer if it was generated by a step that was skipped by + the user or if it was part of a form step and the question was left unanswered. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForNilQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector; + +/** + Returns a predicate matching a result of type `ORKScaleQuestionResult` whose answer is the + specified integer value. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param expectedAnswer The expected integer value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(NSInteger)expectedAnswer; + +/** + Returns a predicate matching a result of type `ORKScaleQuestionResult` whose answer is within the + specified double values. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected double value. Pass `ORKIgnoreDoubleValue` + if you don't want to compare the answer against a maximum + double value. + @param maximumExpectedAnswerValue The maximum expected double value. Pass `ORKIgnoreDoubleValue` + if you don't want to compare the answer against a maximum + double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKScaleQuestionResult` whose answer is greater than + or equal to the specified double value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKScaleQuestionResult` whose answer is less than or + equal to the specified double value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param maximumExpectedAnswerValue The maximum expected double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKChoiceQuestionResult` whose answer is equal to + the specified object. + + @param resultSelector The result selector object which specifies the question result you + are interested in. + @param expectedAnswerValue The expected answer object. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswerValue:(id)expectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKChoiceQuestionResult` whose answers are equal to + the specified objects. + + @param resultSelector The result selector object which specifies the question result you + are interested in. + @param expectedAnswerValues An array with a some or of all of the expected answer objects. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswerValues:(NSArray> *)expectedAnswerValues; + +/** + Returns a predicate matching a result of type `ORKChoiceQuestionResult` whose answer matches the + specified regular expression pattern. This predicate can solely be used to match choice results + which only contain string answers. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param pattern An ICU-compliant regular expression pattern that matches the answer string. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPattern:(NSString *)pattern; + +/** + Returns a predicate matching a result of type `ORKChoiceQuestionResult` whose answers match the + specified regular expression patterns. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param patterns An array of ICU-compliant regular expression patterns that match the answer strings. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPatterns:(NSArray *)patterns; + +/** + Returns a predicate matching a result of type `ORKBooleanQuestionResult` whose answer is the + specified Boolean value. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param expectedAnswer The expected boolean value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForBooleanQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(BOOL)expectedAnswer; + +/** + + Returns a predicate matching a result of type `ORKTextQuestionResult` whose answer is equal to the + specified string. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param expectedString The expected result string. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedString:(NSString *)expectedString; + +/** + Returns a predicate matching a result of type `ORKTextQuestionResult` whose answer matches the + specified regular expression pattern. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param pattern An ICU-compliant regular expression pattern that matches the answer string. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPattern:(NSString *)pattern; + +/** + Returns a predicate matching a result of type `ORKNumericQuestionResult` whose answer is the + specified integer value. + + @param resultSelector The result selector object which specifies the question result you are + interested in. + @param expectedAnswer The expected integer value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(NSInteger)expectedAnswer; + +/** + Returns a predicate matching a result of type `ORKNumericQuestionResult` whose answer is within the + specified double values. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected double value. Pass `ORKIgnoreDoubleValue` + if you don't want to compare the answer against a maximum + double value. + @param maximumExpectedAnswerValue The maximum expected double value. Pass `ORKIgnoreDoubleValue` + if you don't want to compare the answer against a minimum + double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKNumericQuestionResult` whose answer is greater + than or equal to the specified double value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKNumericQuestionResult` whose answer is less than + or equal to the specified double value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param maximumExpectedAnswerValue The maximum expected double value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKTimeOfDayQuestionResult` whose answer is within + the specified hour and minute values. + + Note that `ORKTimeOfDayQuestionResult` internally stores its answer as an `NSDateComponents` object. + If you are interested in additional components, you must build the predicate manually. + + @param resultSelector The result selector object which specifies the question result you + are interested in. + @param minimumExpectedHour The minimum expected hour component value. + @param minimumExpectedMinute The minimum expected minute component value. + @param maximumExpectedHour The maximum integer hour component value. + @param maximumExpectedMinute The maximum expected minute component value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTimeOfDayQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedHour:(NSInteger)minimumExpectedHour + minimumExpectedMinute:(NSInteger)minimumExpectedMinute + maximumExpectedHour:(NSInteger)maximumExpectedHour + maximumExpectedMinute:(NSInteger)maximumExpectedMinute; + +/** + Returns a predicate matching a result of type `ORKTimeIntervalQuestionResult` whose answer is +within the specified `NSTimeInterval` values. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected `NSTimeInterval` value. Pass + `ORKIgnoreTimeIntervlValue` if you don't want to compare the + answer against a maximum `NSTimeInterval` value. + @param maximumExpectedAnswerValue The maximum expected `NSTimeInterval` value. Pass + `ORKIgnoreTimeIntervlValue` if you don't want to compare the + answer against a minimum `NSTimeInterval` value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKTimeIntervalQuestionResult` whose answer is the + specified integer value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerValue The minimum expected `NSTimeInterval` value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKTimeIntervalQuestionResult` whose answer is the + specified integer value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param maximumExpectedAnswerValue The maximum expected `NSTimeInterval` value. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue; + +/** + Returns a predicate matching a result of type `ORKDateQuestionResult` whose answer is a date within + the specified dates. + + @param resultSelector The result selector object which specifies the question result + you are interested in. + @param minimumExpectedAnswerDate The minimum expected date. Pass `nil` if you don't want to + compare the answer against a minimum date. + @param maximumExpectedAnswerDate The maximum expected date. Pass `nil` if you don't want to + compare the answer against a maximum date. + + @return A result predicate. + */ ++ (NSPredicate *)predicateForDateQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerDate:(nullable NSDate *)minimumExpectedAnswerDate + maximumExpectedAnswerDate:(nullable NSDate *)maximumExpectedAnswerDate; + +/** + Returns a predicate matching a result of type `ORKConsentSignatureResult` whose `consented` value + matches the specified boolean value. + + @param resultSelector The result selector object which specifies the question result + you are interested in. Note that when creating this result + selector you must provide the desired step identifier as the + `stepIdentifier` argument and the corresponding signature + identifier as the `resultIdentifier` argument). The step + identifier will normally refer to the result of a + `ORKConsentReviewStep` and the signature identifier will + refer to the contained `ORKConsentSignatureResult` + corresponding to the signature collected by the consent + review step. + @return A result predicate. + */ ++ (NSPredicate *)predicateForConsentWithResultSelector:(ORKResultSelector *)resultSelector + didConsent:(BOOL)didConsent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.m new file mode 100755 index 0000000..19d91b2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResultPredicate.m @@ -0,0 +1,458 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKResultPredicate.h" + +#import "ORKHelpers_Internal.h" + + +NSString *const ORKResultPredicateTaskIdentifierVariableName = @"ORK_TASK_IDENTIFIER"; + + +@interface ORKResultSelector () + +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + + +@implementation ORKResultSelector + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + ++ (instancetype)selectorWithTaskIdentifier:(NSString *)taskIdentifier + stepIdentifier:(NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier { + return [[[self class] alloc] initWithTaskIdentifier:taskIdentifier + stepIdentifier:stepIdentifier + resultIdentifier:resultIdentifier]; +} + ++ (instancetype)selectorWithStepIdentifier:(NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier { + return [[[self class] alloc] initWithStepIdentifier:stepIdentifier + resultIdentifier:resultIdentifier]; +} + ++ (instancetype)selectorWithTaskIdentifier:(NSString *)taskIdentifier + resultIdentifier:(NSString *)resultIdentifier { + return [[[self class] alloc] initWithTaskIdentifier:taskIdentifier + resultIdentifier:resultIdentifier]; +} + ++ (instancetype)selectorWithResultIdentifier:(NSString *)resultIdentifier { + return [[[self class] alloc] initWithResultIdentifier:resultIdentifier]; +} + +- (instancetype)initWithTaskIdentifier:(NSString *)taskIdentifier + stepIdentifier:(NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier { + if (self = [super init]) { + _taskIdentifier = [taskIdentifier copy]; + _stepIdentifier = [stepIdentifier copy]; + _resultIdentifier = [resultIdentifier copy]; + } + return self; +} + +- (instancetype)initWithTaskIdentifier:(NSString *)taskIdentifier + resultIdentifier:(NSString *)resultIdentifier { + return [self initWithTaskIdentifier:taskIdentifier + stepIdentifier:nil + resultIdentifier:resultIdentifier]; +} + +- (instancetype)initWithStepIdentifier:(NSString *)stepIdentifier + resultIdentifier:(NSString *)resultIdentifier { + return [self initWithTaskIdentifier:nil + stepIdentifier:stepIdentifier + resultIdentifier:resultIdentifier]; +} + + +- (instancetype)initWithResultIdentifier:(NSString *)resultIdentifier { + return [self initWithTaskIdentifier:nil + stepIdentifier:nil + resultIdentifier:resultIdentifier]; +} + +- (NSString *)stepIdentifier { + NSString *stepIdentifier = nil; + if (_stepIdentifier) { + stepIdentifier = _stepIdentifier; + } else { + stepIdentifier = _resultIdentifier; + } + return stepIdentifier; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) resultIdentifier = [[[self class] allocWithZone:zone] initWithTaskIdentifier:_taskIdentifier + stepIdentifier:_stepIdentifier + resultIdentifier:_resultIdentifier]; + return resultIdentifier; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.taskIdentifier, castObject.taskIdentifier) + && ORKEqualObjects(self.stepIdentifier, castObject.stepIdentifier) + && ORKEqualObjects(self.resultIdentifier, castObject.resultIdentifier)); +} + +- (NSUInteger)hash { + return _taskIdentifier.hash ^ _stepIdentifier.hash ^ _resultIdentifier.hash; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, taskIdentifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, stepIdentifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, resultIdentifier, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, taskIdentifier); + ORK_ENCODE_OBJ(aCoder, stepIdentifier); + ORK_ENCODE_OBJ(aCoder, resultIdentifier); +} + +- (NSString *)description { + return [NSString stringWithFormat:@"{%@, %@, %@}", + _taskIdentifier ? _taskIdentifier : @"", + _stepIdentifier ? _stepIdentifier : _resultIdentifier, + _resultIdentifier]; +} + +@end + + +@implementation ORKResultPredicate + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + ++ (NSPredicate *)predicateMatchingResultSelector:(ORKResultSelector *)resultSelector + subPredicateFormatArray:(NSArray *)subPredicateFormatArray + subPredicateFormatArgumentArray:(NSArray *)subPredicateFormatArgumentArray + areSubPredicateFormatsSubquery:(BOOL)areSubPredicateFormatsSubquery { + ORKThrowInvalidArgumentExceptionIfNil(resultSelector); + + NSString *taskIdentifier = resultSelector.taskIdentifier; + NSString *stepIdentifier = resultSelector.stepIdentifier; + NSString *resultIdentifier = resultSelector.resultIdentifier; + + NSMutableString *format = [[NSMutableString alloc] init]; + NSMutableArray *formatArgumentArray = [[NSMutableArray alloc] init]; + + // Match task identifier + if (taskIdentifier) { + [format appendString:@"SUBQUERY(SELF, $x, $x.identifier == %@"]; + [formatArgumentArray addObject:taskIdentifier]; + } else { + // If taskIdentifier is nil, ORKPredicateStepNavigationRule will substitute the + // ORKResultPredicateTaskIdentifierSubstitutionVariableName variable by the identifier of the ongoing task + [format appendFormat:@"SUBQUERY(SELF, $x, $x.identifier == $%@", ORKResultPredicateTaskIdentifierVariableName]; + } + + { + // Match question result identifier + [format appendString:@" AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == NO AND SUBQUERY($y.results, $z, $z.identifier == %@"]; + [formatArgumentArray addObject:stepIdentifier]; + [formatArgumentArray addObject:resultIdentifier]; + { + // Add question sub predicates. They can be normal predicates (for question results with only one answer) + // or part of an additional subquery predicate (for question results with an array of answers, like ORKChoiceQuestionResult). + for (NSString *subPredicateFormat in subPredicateFormatArray) { + if (!areSubPredicateFormatsSubquery) { + [format appendString:@" AND $z."]; + [format appendString:subPredicateFormat]; + } else { + [format appendString:@" AND SUBQUERY($z."]; + [format appendString:subPredicateFormat]; + [format appendString:@").@count > 0"]; + } + } + [formatArgumentArray addObjectsFromArray:subPredicateFormatArgumentArray]; + } + [format appendString:@").@count > 0"]; + [format appendString:@").@count > 0"]; + } + + [format appendString:@").@count > 0"]; + + NSPredicate *predicate = [NSPredicate predicateWithFormat:format argumentArray:formatArgumentArray]; + return predicate; +} + ++ (NSPredicate *)predicateMatchingResultSelector:(ORKResultSelector *)resultSelector + subPredicateFormatArray:(NSArray *)subPredicateFormatArray + subPredicateFormatArgumentArray:(NSArray *)subPredicateFormatArgumentArray { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:subPredicateFormatArray + subPredicateFormatArgumentArray:subPredicateFormatArgumentArray + areSubPredicateFormatsSubquery:NO]; +} + ++ (NSPredicate *)predicateForNilQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer == nil" ] + subPredicateFormatArgumentArray:@[ ]]; +} + ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(NSInteger)expectedAnswer { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:expectedAnswer]; +} + ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:minimumExpectedAnswerValue + maximumExpectedAnswerValue:maximumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:minimumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:maximumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswers:(NSArray *)expectedAnswers + usePatterns:(BOOL)usePatterns { + ORKThrowInvalidArgumentExceptionIfNil(expectedAnswers); + if (expectedAnswers.count == 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"expectedAnswer cannot be empty." userInfo:nil]; + } + + NSMutableArray *subPredicateFormatArray = [NSMutableArray new]; + + NSString *repeatingSubPredicateFormat = + usePatterns ? + @"answer, $w, $w matches %@" : + @"answer, $w, $w == %@"; + + for (NSInteger i = 0; i < expectedAnswers.count; i++) { + [subPredicateFormatArray addObject:repeatingSubPredicateFormat]; + } + + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:subPredicateFormatArray + subPredicateFormatArgumentArray:expectedAnswers + areSubPredicateFormatsSubquery:YES]; +} + ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswerValue:(id)expectedAnswerValue { + return [self predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswers:@[ expectedAnswerValue ] + usePatterns:NO]; +} + ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswerValues:(NSArray> *)expectedAnswerValues { + return [self predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswers:expectedAnswerValues + usePatterns:NO]; +} + ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPattern:(NSString *)pattern { + return [self predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswers:@[ pattern ] + usePatterns:YES]; +} + ++ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPatterns:(NSArray *)patterns { + return [self predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswers:patterns + usePatterns:YES]; +} + ++ (NSPredicate *)predicateForBooleanQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(BOOL)expectedAnswer { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer == %@" ] + subPredicateFormatArgumentArray:@[ @(expectedAnswer) ]]; +} + ++ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedString:(NSString *)expectedString { + ORKThrowInvalidArgumentExceptionIfNil(expectedString); + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer == %@" ] + subPredicateFormatArgumentArray:@[ expectedString ]]; +} + ++ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + matchingPattern:(NSString *)pattern { + ORKThrowInvalidArgumentExceptionIfNil(pattern); + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer matches %@" ] + subPredicateFormatArgumentArray:@[ pattern ]]; +} + ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + expectedAnswer:(NSInteger)expectedAnswer { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer == %@" ] + subPredicateFormatArgumentArray:@[ @(expectedAnswer) ]]; +} + ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue { + NSMutableArray *subPredicateFormatArray = [NSMutableArray new]; + NSMutableArray *subPredicateFormatArgumentArray = [NSMutableArray new]; + + if (!isnan(minimumExpectedAnswerValue)) { + [subPredicateFormatArray addObject:@"answer >= %@"]; + [subPredicateFormatArgumentArray addObject:@(minimumExpectedAnswerValue)]; + } + if (!isnan(maximumExpectedAnswerValue)) { + [subPredicateFormatArray addObject:@"answer <= %@"]; + [subPredicateFormatArgumentArray addObject:@(maximumExpectedAnswerValue)]; + } + + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:subPredicateFormatArray + subPredicateFormatArgumentArray:subPredicateFormatArgumentArray]; +} + ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:minimumExpectedAnswerValue + maximumExpectedAnswerValue:ORKIgnoreDoubleValue]; +} + ++ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:ORKIgnoreDoubleValue + maximumExpectedAnswerValue:maximumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForTimeOfDayQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedHour:(NSInteger)minimumExpectedHour + minimumExpectedMinute:(NSInteger)minimumExpectedMinute + maximumExpectedHour:(NSInteger)maximumExpectedHour + maximumExpectedMinute:(NSInteger)maximumExpectedMinute { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"answer.hour >= %@", + @"answer.minute >= %@", + @"answer.hour <= %@", + @"answer.minute <= %@" ] + subPredicateFormatArgumentArray:@[ @(minimumExpectedHour), + @(minimumExpectedMinute), + @(maximumExpectedHour), + @(maximumExpectedMinute) ]]; +} + ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue + maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:minimumExpectedAnswerValue + maximumExpectedAnswerValue:maximumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:minimumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue { + return [self predicateForNumericQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:maximumExpectedAnswerValue]; +} + ++ (NSPredicate *)predicateForDateQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector + minimumExpectedAnswerDate:(nullable NSDate *)minimumExpectedAnswerDate + maximumExpectedAnswerDate:(nullable NSDate *)maximumExpectedAnswerDate { + NSMutableArray *subPredicateFormatArray = [NSMutableArray new]; + NSMutableArray *subPredicateFormatArgumentArray = [NSMutableArray new]; + + if (minimumExpectedAnswerDate) { + [subPredicateFormatArray addObject:@"answer >= %@"]; + [subPredicateFormatArgumentArray addObject:minimumExpectedAnswerDate]; + } + if (maximumExpectedAnswerDate) { + [subPredicateFormatArray addObject:@"answer <= %@"]; + [subPredicateFormatArgumentArray addObject:maximumExpectedAnswerDate]; + } + + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:subPredicateFormatArray + subPredicateFormatArgumentArray:subPredicateFormatArgumentArray]; +} + ++ (NSPredicate *)predicateForConsentWithResultSelector:(ORKResultSelector *)resultSelector didConsent:(BOOL)didConsent { + return [self predicateMatchingResultSelector:resultSelector + subPredicateFormatArray:@[ @"consented == %@" ] + subPredicateFormatArgumentArray:@[ @(didConsent) ]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult_Private.h new file mode 100755 index 0000000..bf31adf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKResult_Private.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_EXTERN const NSUInteger NumberOfPaddingSpacesForIndentationLevel; + +@interface ORKResult () + +/** + A boolean value indicating whether this result can be saved in a save and + restore procedure. + + This is currently considered a private method, but overriding the getter in a result + is the correct way to prevent this result being considered as saveable for + the purpose of deciding whether to offer a "Save" option when the user + cancels a task in progress. + + `ORKResult` subclasses should return YES if they have data that the user + might want to be able to restore if the task were interrupted and later + resumed from the current state. + */ +@property (nonatomic, readonly, getter=isSaveable) BOOL saveable; + +// Description formatting +- (NSString *)descriptionPrefixWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces; +- (NSString *)descriptionSuffix; +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.h new file mode 100755 index 0000000..6a3f0e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKReviewIncompleteCell : UITableViewCell + +@property (nonatomic, strong) NSString *text; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.m new file mode 100755 index 0000000..d4d8387 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewIncompleteCell.m @@ -0,0 +1,108 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKReviewIncompleteCell.h" +#import "ORKSkin.h" + +static const CGFloat topPadding = 8.0; +static const CGFloat horizontalPadding = 16.0; +static const CGFloat verticalPadding = 10.0; + +@implementation ORKReviewIncompleteCell { + UIView *cardView; + UILabel *label; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + [self setBackgroundColor:UIColor.clearColor]; + + [self setupView]; + [self setupConstraints]; + } + return self; +} + +- (void)setupView { + cardView = [[UIView alloc] init]; + cardView.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + cardView.backgroundColor = [UIColor secondarySystemGroupedBackgroundColor]; + } else { + cardView.backgroundColor = [UIColor whiteColor]; + } + cardView.layer.cornerRadius = ORKCardDefaultCornerRadii; + [self.contentView addSubview:cardView]; + + label = [[UILabel alloc] init]; + label.textColor = [UIColor systemBlueColor]; + label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; + label.numberOfLines = 0; + label.translatesAutoresizingMaskIntoConstraints = NO; + [cardView addSubview:label]; +} + +- (void)setupConstraints { + CGFloat leftRightPadding = ORKStepContainerLeftRightPaddingForWindow(self.window); + + [cardView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:topPadding].active = YES; + [cardView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:leftRightPadding].active = YES; + [cardView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-leftRightPadding].active = YES; + [cardView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor].active = YES; + + [label.topAnchor constraintEqualToAnchor:cardView.topAnchor constant:verticalPadding].active = YES; + [label.leadingAnchor constraintEqualToAnchor:cardView.leadingAnchor constant:horizontalPadding].active = YES; + [label.trailingAnchor constraintEqualToAnchor:cardView.trailingAnchor constant:-horizontalPadding].active = YES; + [label.bottomAnchor constraintEqualToAnchor:cardView.bottomAnchor constant:-verticalPadding].active = YES; +} + +- (void)setText:(NSString *)text { + _text = text; + label.text = text; +} + +- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { + if (highlighted == YES) { + if (@available(iOS 13.0, *)) { + cardView.backgroundColor = [UIColor systemGray5Color]; + } else { + cardView.backgroundColor = [UIColor grayColor]; + } + } else { + if (@available(iOS 13.0, *)) { + cardView.backgroundColor = [UIColor secondarySystemGroupedBackgroundColor]; + } else { + cardView.backgroundColor = [UIColor whiteColor]; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.h new file mode 100755 index 0000000..2cea4a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.h @@ -0,0 +1,104 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKTaskResultSource; + +/** + The `ORKReviewStep` class is a concrete subclass of `ORKStep` that represents + a step in which existing question results can be reviewed by the user. + + There are two separate scenarios for using `ORKReviewStep`. The first one is to embed a review step within an ongoing + survey, which means an instance of `ORKReviewStep` might be placed at the end or in the middle of a task. The second + scenario is meant to use `ORKReviewStep` standalone for reviewing an already completed task. + + To use a review step, instantiate an `ORKReviewStep` object, fill in its properties, and include it in a task. Next, + create a task view controller for the task and present it. + + When a task view controller presents an `ORKReviewStep` object, it instantiates an `ORKReviewStepViewController` object + to present the step. This view controller lists both steps and step results to provide all entered data at a glance. It + also allows the user to navigate directly to a certain step. However, results may only be changed from there, if the + review step is used within an ongoing survey (`embedded`). + */ +ORK_CLASS_AVAILABLE +@interface ORKReviewStep : ORKStep + +/** + Returns a new standalone review step that includes the specified identifier, steps, and result source. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param steps The steps that should be reviewed. Currently, only question, instruction and + form steps can be reviewed. Any other step type will be ignored. + @param resultSource The source that should be consulted to obtain the corresponding step results. + */ ++ (instancetype)standaloneReviewStepWithIdentifier:(NSString *)identifier + steps:(nullable NSArray *)steps + resultSource:(nullable id)resultSource; + +/** + Returns a new embedded review step that includes the specified identifier. Steps and step results are directly taken + from the current task. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + */ ++ (instancetype)embeddedReviewStepWithIdentifier:(NSString *)identifier; + +/** + The steps to be reviewed. (read-only) + + This property contains all steps that are included in the review process. Currently, only question, instruction and + form steps can be reviewed. Any other step type will be ignored. + */ +@property (nonatomic, copy, readonly, nullable) NSArray *steps; + +/** + The result source to obtain step results from. (read-only) + + This property contains the source that should be consulted to obtain step results. + */ +@property (nonatomic, readonly, nullable) id resultSource; + +/** + A Boolean value indicating whether instruction steps should be excluded from review. + + The default value of this property is `NO`. When the value is `YES`, any instances of `ORKInstructionStep` are + excluded from the review step in either embedded or standalone mode. + */ +@property (nonatomic) BOOL excludeInstructionSteps; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.m new file mode 100755 index 0000000..e6b4571 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep.m @@ -0,0 +1,122 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReviewStep.h" +#import "ORKReviewStep_Internal.h" + +#import "ORKReviewStepViewController.h" + +#import "ORKResult.h" +#import "ORKCollectionResult_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKReviewStep + +- (instancetype)initWithIdentifier:(NSString *)identifier + steps:(NSArray *)steps + resultSource:(id)resultSource { + self = [super initWithIdentifier:identifier]; + if (self) { + if (steps) { + _steps = [steps copy]; + } else { + _steps = @[]; + } + _resultSource = resultSource; + _excludeInstructionSteps = NO; + } + return self; +} + ++ (instancetype)standaloneReviewStepWithIdentifier:(NSString *)identifier + steps:(NSArray *)steps + resultSource:(id)resultSource { + return [[ORKReviewStep alloc] initWithIdentifier:identifier steps:steps resultSource:resultSource]; +} + ++ (instancetype)embeddedReviewStepWithIdentifier:(NSString *)identifier { + return [[ORKReviewStep alloc] initWithIdentifier:identifier steps:nil resultSource:nil]; +} + ++ (Class)stepViewControllerClass { + return [ORKReviewStepViewController class]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, steps, NSArray); + ORK_DECODE_OBJ(aDecoder, resultSource); + ORK_DECODE_BOOL(aDecoder, excludeInstructionSteps); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, steps); + ORK_ENCODE_OBJ(aCoder, resultSource); + ORK_ENCODE_BOOL(aCoder, excludeInstructionSteps); +} + +- (NSUInteger)hash { + return super.hash ^ _steps.hash ^ _resultSource.hash ^ (_excludeInstructionSteps ? 0xf : 0x0); +} + + +- (BOOL)isEqual:(id)object { + __typeof(self) castObject = object; + return [super isEqual:object] && + ORKEqualObjects(self.steps, castObject.steps) && + ORKEqualObjects(self.resultSource, castObject.resultSource) && + self.excludeInstructionSteps == castObject.excludeInstructionSteps; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKReviewStep *reviewStep = [super copyWithZone:zone]; + reviewStep->_steps = [self.steps copy]; + reviewStep->_resultSource = self.resultSource; + reviewStep->_excludeInstructionSteps = self.excludeInstructionSteps; + return reviewStep; +} + +- (BOOL)isStandalone { + return _steps.count > 0; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.h new file mode 100755 index 0000000..122764c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKReviewStepViewController; + +@protocol ORKReviewStepViewControllerDelegate + +- (void)reviewStepViewController:(ORKReviewStepViewController*)reviewStepViewController + willReviewStep:(ORKStep*)step; +@end + + +@protocol ORKTaskResultSource; + +ORK_CLASS_AVAILABLE +@interface ORKReviewStepViewController : ORKStepViewController + +- (instancetype)initWithReviewStep:(ORKReviewStep *)reviewStep steps:(NSArray *)steps resultSource:(id)resultSource; + +@property (nonatomic, weak, nullable) id reviewDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.m new file mode 100755 index 0000000..e3e7510 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController.m @@ -0,0 +1,288 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReviewStepViewController.h" +#import "ORKReviewStepViewController_Internal.h" + +#import "ORKChoiceViewCell.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKSelectionTitleLabel.h" +#import "ORKSelectionSubTitleLabel.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKTableContainerView.h" +#import "ORKBodyItem.h" + +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKStepContentView.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKFormStep.h" +#import "ORKInstructionStep.h" +#import "ORKQuestionResult_Private.h" +#import "ORKQuestionStep.h" +#import "ORKReviewStep_Internal.h" +#import "ORKResult_Private.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKReviewStepViewController () + +@property (nonatomic, strong) ORKTableContainerView *tableContainer; + +@end + + + +@implementation ORKReviewStepViewController { + NSArray *_constraints; +} + +- (instancetype)initWithReviewStep:(ORKReviewStep *)reviewStep steps:(NSArray*)steps resultSource:(id)resultSource { + self = [self initWithStep:reviewStep]; + if (self && [self reviewStep]) { + NSArray *stepsToFilter = [self reviewStep].isStandalone ? [self reviewStep].steps : steps; + NSMutableArray *filteredSteps = [[NSMutableArray alloc] init]; + ORKWeakTypeOf(self) weakSelf = self; + [stepsToFilter enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + BOOL includeStep = [obj isKindOfClass:[ORKQuestionStep class]] || [obj isKindOfClass:[ORKFormStep class]] || (![[strongSelf reviewStep] excludeInstructionSteps] && [obj isKindOfClass:[ORKInstructionStep class]]); + if (includeStep) { + [filteredSteps addObject:obj]; + } + }]; + _steps = [filteredSteps copy]; + _resultSource = [self reviewStep].isStandalone ? [self reviewStep].resultSource : resultSource; + } + return self; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [self.taskViewController setRegisteredScrollView: _tableContainer.tableView]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _navigationFooterView.skipButtonItem = self.skipButtonItem; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_tableContainer removeFromSuperview]; + _tableContainer = nil; + + _tableContainer.tableView.delegate = nil; + _tableContainer.tableView.dataSource = nil; + _navigationFooterView = nil; + + if ([self reviewStep]) { + _tableContainer = [ORKTableContainerView new]; + _tableContainer.tableView.delegate = self; + _tableContainer.tableView.dataSource = self; + _tableContainer.tableView.clipsToBounds = YES; + + [self.view addSubview:_tableContainer]; + _tableContainer.tapOffView = self.view; + + _tableContainer.stepContentView.stepTitle = [[self reviewStep] title]; + _tableContainer.stepContentView.stepText = [[self reviewStep] text]; + _tableContainer.stepContentView.bodyItems = [[self reviewStep] bodyItems]; + + [_tableContainer.tableView setBackgroundColor:ORKNeedWideScreenDesign(self.view) ? [UIColor clearColor] : ORKColor(ORKBackgroundColorKey)]; + _navigationFooterView = _tableContainer.navigationFooterView; + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.optional = self.step.optional; + [self setupConstraints]; + [_tableContainer setNeedsLayout]; + } +} + + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _tableContainer.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (ORKReviewStep *)reviewStep { + return [self.step isKindOfClass:[ORKReviewStep class]] ? (ORKReviewStep *) self.step : nil; +} + +#pragma mark UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return _steps.count > 0 ? 1 : 0; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _steps.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + tableView.layoutMargins = UIEdgeInsetsZero; + static NSString *identifier = nil; + identifier = [NSStringFromClass([self class]) stringByAppendingFormat:@"%@", @(indexPath.row)]; + ORKChoiceViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + if (cell == nil) { + cell = [[ORKChoiceViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + } + cell.immediateNavigation = YES; + ORKStep *step = _steps[indexPath.row]; + ORKStepResult *stepResult = [_resultSource stepResultForStepIdentifier:step.identifier]; + [cell setPrimaryText:step.title ? : step.text]; + [cell setDetailText:[self answerStringForStep:step withStepResult:stepResult]]; + return cell; +} + +#pragma mark answer string + +- (NSString *)answerStringForStep:(ORKStep *)step withStepResult:(ORKStepResult *)stepResult { + NSString *answerString = nil; + if (step && stepResult && [step.identifier isEqualToString:stepResult.identifier]) { + if ([step isKindOfClass:[ORKQuestionStep class]]) { + ORKQuestionStep *questionStep = (ORKQuestionStep *)step; + if (stepResult.firstResult && [stepResult.firstResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)stepResult.firstResult; + answerString = [self answerStringForQuestionStep:questionStep withQuestionResult:questionResult]; + } + } else if ([step isKindOfClass:[ORKFormStep class]]) { + answerString = [self answerStringForFormStep:(ORKFormStep *)step withStepResult:stepResult]; + } + } + return answerString; +} + +- (NSString *)answerStringForQuestionStep:(ORKQuestionStep *)questionStep withQuestionResult:(ORKQuestionResult *)questionResult { + NSString *answerString = nil; + if (questionStep && questionResult && questionStep.answerFormat && [questionResult isKindOfClass:questionStep.answerFormat.questionResultClass] && questionResult.answer) { + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answerString = questionStep.answerFormat.customDontKnowButtonText; + } else { + answerString = [questionStep.answerFormat stringForAnswer:questionResult.answer]; + } + } + return answerString; +} + +- (NSString *)answerStringForFormStep:(ORKFormStep *)formStep withStepResult:(ORKStepResult *)stepResult { + NSString *answerString = nil; + if (formStep && formStep.formItems && stepResult) { + NSMutableArray *answerStrings = [[NSMutableArray alloc] init]; + for (ORKFormItem *formItem in formStep.formItems) { + ORKResult *formItemResult = [stepResult resultForIdentifier:formItem.identifier]; + if (formItemResult && [formItemResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)formItemResult; + if (formItem.answerFormat && [questionResult isKindOfClass:formItem.answerFormat.questionResultClass] && questionResult.answer) { + NSString *formItemTextString = formItem.text; + NSString *formItemAnswerString; + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + formItemAnswerString = formItem.answerFormat.customDontKnowButtonText; + } else { + formItemAnswerString = [formItem.answerFormat stringForAnswer:questionResult.answer]; + } + if (formItemTextString && formItemAnswerString) { + [answerStrings addObject:[@[formItemTextString, formItemAnswerString] componentsJoinedByString:@"\n"]]; + } + } + } + } + answerString = [answerStrings componentsJoinedByString:@"\n\n"]; + } + return answerString; +} + +#pragma mark UITableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + if ([self.reviewDelegate respondsToSelector:@selector(reviewStepViewController:willReviewStep:)]) { + [self.reviewDelegate reviewStepViewController:self willReviewStep:_steps[indexPath.row]]; + } +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + return UITableViewAutomaticDimension; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController_Internal.h new file mode 100755 index 0000000..26a9d9c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStepViewController_Internal.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReviewStepViewController.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKReviewStepViewController () + +@property (nonatomic, copy, nullable, readonly) NSArray *steps; + +@property (nonatomic, nullable, readonly) id resultSource; + +@property (nonatomic, nullable, readonly) ORKReviewStep *reviewStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep_Internal.h new file mode 100755 index 0000000..7dd320e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewStep_Internal.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKReviewStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKReviewStep () + +/** + A Boolean value indicating whether this review step is used in standalone mode (read-only). + */ +@property (nonatomic, readonly) BOOL isStandalone; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.h new file mode 100755 index 0000000..3b5851a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.h @@ -0,0 +1,76 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "ORKDefines.h" + +@class ORKOrderedTask; +@class ORKTaskResult; +@class ORKBodyItem; +@class ORKStepResult; +@class ORKReviewViewController; +@class ORKNavigableOrderedTask; +@class ORKTaskViewController; +@class ORKLearnMoreInstructionStep; +@class ORKStepViewController; + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKReviewViewControllerDelegate + +@required +- (void)reviewViewController:(ORKReviewViewController *)reviewViewController didUpdateResult:(ORKTaskResult *)updatedResult source:(ORKTaskResult *)resultSource; +- (void)reviewViewControllerDidSelectIncompleteCell:(ORKReviewViewController *)reviewViewController; +@optional +- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep; +@end + +ORK_CLASS_AVAILABLE +@interface ORKReviewViewController : UIViewController + +- (instancetype)initWithTask:(ORKOrderedTask *)task result:(ORKTaskResult *)result delegate:(id)delegate; +- (instancetype)initWithTask:(ORKNavigableOrderedTask *)task delegate:(id)delegate isCompleted:(BOOL)isCompleted incompleteText:(NSString *)incompleteText; + +- (void)updateResultSource:(ORKTaskResult *)result forTask:(ORKOrderedTask *)task; + +- (void)updateResultSource:(ORKTaskResult *)result; + +@property (nonatomic, weak)id delegate; + +@property (nonatomic) NSString *reviewTitle; +@property (nonatomic) NSString *text; +@property (nonatomic) NSString *detailText; + +@property (nonatomic) UIImage *image; +@property (nonatomic) NSArray *bodyItems; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.m new file mode 100755 index 0000000..a655c8b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKReviewViewController.m @@ -0,0 +1,458 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKReviewViewController.h" +#import "ORKTaskReviewViewController.h" +#import "ORKTaskViewController_Private.h" +#import "ORKStepView_Private.h" +#import "ORKTableContainerView.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepContentView_Private.h" +#import "ORKStep.h" +#import "ORKOrderedTask_Private.h" +#import "ORKFormStep.h" +#import "ORKQuestionStep.h" +#import "ORKCollectionResult.h" +#import "ORKQuestionResult_Private.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKSurveyCardHeaderView.h" +#import "ORKChoiceViewCell_Internal.h" +#import "ORKSkin.h" +#import "ORKHelpers_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKReviewIncompleteCell.h" +#import "ORKNavigableOrderedTask.h" + +static const float FirstSectionHeaderPadding = 24.0; + +@interface ORKReviewViewController () + +@property (nonatomic, nonnull) ORKTableContainerView *tableContainerView; +@property (nonatomic) NSMutableArray *reviewSections; +@property (nonatomic) id resultSource; +@property (nonatomic, nonnull) NSArray *steps; +@property (nonatomic, strong) ORKNavigableOrderedTask *navigableOrderedTask; +@property (nonatomic, assign) BOOL isCompleted; +@property (nonatomic, strong) NSString *incompleteText; + +@end + +@implementation ORKReviewViewController { + ORKStep *_reviewInstructionStep; + NSString *_currentSectionTitle; +} + +- (instancetype)initWithTask:(ORKOrderedTask *)task result:(ORKTaskResult *)result delegate:(nonnull id)delegate { + self = [super init]; + if (self) { + _steps = task.steps; + _resultSource = result; + _delegate = delegate; + _isCompleted = YES; + [self createReviewSectionsWithDefaultResultSource:_resultSource]; + } + return self; +} + +- (instancetype)initWithTask:(ORKNavigableOrderedTask *)task delegate:(id)delegate isCompleted:(BOOL)isCompleted incompleteText:(NSString *)incompleteText { + self = [super init]; + if (self) { + _steps = task.steps; + _navigableOrderedTask = task; + _isCompleted = isCompleted; + _delegate = delegate; + _incompleteText = incompleteText; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + if (@available(iOS 13.0, *)) { + self.view.backgroundColor = [UIColor systemGroupedBackgroundColor]; + } else { + self.view.backgroundColor = ORKColor(ORKBackgroundColorKey); + } + + [self setupTableContainerView]; + + _tableContainerView.stepTitle = _reviewTitle; + _tableContainerView.stepText = _text; + _tableContainerView.stepDetailText = _detailText; + _tableContainerView.stepTopContentImage = _image; + _tableContainerView.bodyItems = _bodyItems; + + [_tableContainerView.navigationFooterView setHidden:YES]; + [_tableContainerView setNeedsLayout]; +} + +- (void)setReviewTitle:(NSString *)reviwTitle { + _reviewTitle = reviwTitle; + _tableContainerView.stepTitle = reviwTitle; +} + +- (void)setText:(NSString *)text { + _text = text; + _tableContainerView.stepText = text; + [_tableContainerView sizeHeaderToFit]; +} + +- (void)setDetailText:(NSString *)detailText { + _detailText = detailText; + _tableContainerView.stepDetailText = detailText; +} + +- (void)setImage:(UIImage *)image { + _image = image; + _tableContainerView.stepTopContentImage = image; +} + +- (void)setBodyItems:(NSArray *)bodyItems { + _bodyItems = bodyItems; + _tableContainerView.bodyItems = bodyItems; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [_tableContainerView sizeHeaderToFit]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [_tableContainerView layoutIfNeeded]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [_tableContainerView sizeHeaderToFit]; + [_tableContainerView.tableView reloadData]; + [self.view layoutSubviews]; +} + +- (void)setupTableContainerView { + if (!_tableContainerView) { + _tableContainerView = [[ORKTableContainerView alloc] initWithStyle:UITableViewStyleGrouped pinNavigationContainer:NO]; + _tableContainerView.tableView.dataSource = self; + _tableContainerView.tableView.delegate = self; + _tableContainerView.tableView.clipsToBounds = YES; + _tableContainerView.tableView.rowHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.sectionFooterHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.estimatedRowHeight = ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, self.view.window); + _tableContainerView.tableView.estimatedSectionHeaderHeight = 30.0; + _tableContainerView.tableView.estimatedSectionFooterHeight = 30.0; + _tableContainerView.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + if (@available(iOS 13.0, *)) { + _tableContainerView.tableView.backgroundColor = [UIColor systemGroupedBackgroundColor]; + } else { + _tableContainerView.tableView.backgroundColor = ORKColor(ORKBackgroundColorKey); + } + + } + [self.view addSubview:_tableContainerView]; + _tableContainerView.translatesAutoresizingMaskIntoConstraints = NO; + [[_tableContainerView.topAnchor constraintEqualToAnchor:self.view.topAnchor] setActive:YES]; + [[_tableContainerView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] setActive:YES]; + [[_tableContainerView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor] setActive:YES]; + [[_tableContainerView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor] setActive:YES]; +} + +- (void)createReviewSectionsWithDefaultResultSource:(id)defaultResultSource { + _reviewSections = nil; + _reviewSections = [[NSMutableArray alloc] init]; + for (ORKStep *step in _steps) { + if ([step isKindOfClass:[ORKFormStep class]]) { + ORKFormStep *formStep = (ORKFormStep *)step; + ORKStepResult *result = [defaultResultSource stepResultForStepIdentifier:formStep.identifier]; + if (result) { + [_reviewSections addObject:[self reviewSectionForFormStep:formStep withResult:result]]; + } + } + else if ([step isKindOfClass:[ORKQuestionStep class]]) { + ORKQuestionStep *questionStep = (ORKQuestionStep *)step; + ORKStepResult *result = [defaultResultSource stepResultForStepIdentifier:questionStep.identifier]; + if (result) { + [_reviewSections addObject:[self reviewSectionForQuestionStep:questionStep withResult:result]]; + } + } + } +} + +- (ORKReviewSection *)reviewSectionForFormStep:(ORKFormStep *)formStep withResult:(ORKStepResult *)result { + if (formStep && formStep.formItems && result) { + NSMutableArray *formReviewItems = [[NSMutableArray alloc] init]; + for (ORKFormItem *formItem in formStep.formItems) { + if (formItem.answerFormat) { + ORKResult *formItemResult = [result resultForIdentifier:formItem.identifier]; + ORKReviewItem *formReviewItem = [[ORKReviewItem alloc] init]; + if (formItem.text) { + formReviewItem.question = formItem.text; + } else { + // formItem.text will return nil if a question was constructed as follows + // - you create a section header with the ORKFormItem(sectionTitle: API + // - you then add a ORKFormItem with the relevant answer format and expect it to be grouped under the section title + formReviewItem.question = _currentSectionTitle; + } + formReviewItem.answer = [self answerStringForFormItem:formItem withFormItemResult:formItemResult]; + [formReviewItems addObject:formReviewItem]; + } + else { + // formItem.answerFormat will return nil if a question was constructed as follows + // - you create a section header with the ORKFormItem(sectionTitle: API + // - you then add a ORKFormItem with the relevant answer format and expect it to be grouped under the section title + _currentSectionTitle = formItem.text; + } + } + ORKReviewSection *section = [[ORKReviewSection alloc] init]; + section.title = formStep.title; + section.text = formStep.text; + section.stepIdentifier = formStep.identifier; + section.items = [formReviewItems copy]; + + return section; + } + return nil; +} + +- (NSString *)answerStringForFormItem:(ORKFormItem *)formItem withFormItemResult:(ORKResult *)formItemResult { + NSString *answerString = nil; + if (formItem && formItemResult && [formItemResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)formItemResult; + if (formItem.answerFormat && [questionResult isKindOfClass:formItem.answerFormat.questionResultClass] && questionResult.answer) { + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answerString = formItem.answerFormat.customDontKnowButtonText; + } else { + answerString = [formItem.answerFormat stringForAnswer:questionResult.answer]; + } + } + } + return answerString; +} + +- (ORKReviewSection *)reviewSectionForQuestionStep:(ORKQuestionStep *)questionStep withResult:(ORKStepResult *)result { + ORKReviewItem *item = [[ORKReviewItem alloc] init]; + item.question = questionStep.question; + if (result.firstResult && [result.firstResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)result.firstResult; + item.answer = [self answerStringForQuestionStep:questionStep withQuestionResult:questionResult]; + } + ORKReviewSection *section = [[ORKReviewSection alloc] init]; + section.title = questionStep.title; + section.text = questionStep.text; + section.stepIdentifier = questionStep.identifier; + section.items = @[item]; + + return section; + +} + +- (NSString *)answerStringForQuestionStep:(ORKQuestionStep *)questionStep withQuestionResult:(ORKQuestionResult *)questionResult { + NSString *answerString = nil; + if (questionStep && questionResult && questionStep.answerFormat && [questionResult isKindOfClass:questionStep.answerFormat.questionResultClass] && questionResult.answer) { + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answerString = questionStep.answerFormat.customDontKnowButtonText; + } else { + answerString = [questionStep.answerFormat stringForAnswer:questionResult.answer]; + } + } + return answerString; +} + +- (void)updateResultSource:(ORKTaskResult *)result { + _resultSource = nil; + _reviewSections = nil; + + _resultSource = result; + _isCompleted = YES; + [self createReviewSectionsWithDefaultResultSource:_resultSource]; + [_tableContainerView.tableView reloadData]; +} + +- (void)updateResultSource:(ORKTaskResult *)result forTask:(ORKOrderedTask *)task { + _steps = task.steps; + _isCompleted = YES; + [self updateResultSource:result]; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + if (_isCompleted == NO) { + return 1; + } + + return _reviewSections ? _reviewSections.count : 0; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + if (_isCompleted == NO) { + return 1; + } + + return _reviewSections[section].items.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + + if (_isCompleted == NO) { + if (cell == nil || ![cell isKindOfClass:ORKReviewIncompleteCell.class]) { + ORKReviewIncompleteCell *reviewIncompleteCell = [[ORKReviewIncompleteCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"incompleteCell"]; + reviewIncompleteCell.text = _incompleteText; + reviewIncompleteCell.selectionStyle = UITableViewCellSelectionStyleNone; + cell = reviewIncompleteCell; + } + } else { + if (cell == nil || ![cell isKindOfClass:ORKReviewCell.class]) { + ORKReviewCell *reviewCell = [[ORKReviewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + cell = reviewCell; + } + ORKReviewCell *reviewCell = (ORKReviewCell *)cell; + reviewCell.question = _reviewSections[indexPath.section].items[indexPath.row].question; + reviewCell.answer = _reviewSections[indexPath.section].items[indexPath.row].answer; + reviewCell.isLastCell = _reviewSections[indexPath.section].items.count - 1 == indexPath.row; + } + + return cell; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + if (_isCompleted == NO) { + return nil; + } + + UIView *headerView; + + ORKSurveyCardHeaderView *cardHeaderView = (ORKSurveyCardHeaderView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:@(section).stringValue]; + + if (cardHeaderView == nil) { + ORKReviewSection *reviewSection = _reviewSections[section]; + cardHeaderView = [[ORKSurveyCardHeaderView alloc] initWithTitle:reviewSection.title detailText:reviewSection.text learnMoreView:nil progressText:[NSString stringWithFormat:@"%@ %@", ORKLocalizedString(@"REVIEW_STEP_PAGE", nil), ORKLocalizedStringFromNumber(@(section + 1))] tagText:nil showBorder:YES hasMultipleChoiceItem:NO]; + } + + // The first section needs extra padding at the top to account for space between the content in + // the table header and the first review card. + if (section == 0) { + UIView *cardHeaderViewWithPadding = [[UIView alloc] init]; + cardHeaderView.translatesAutoresizingMaskIntoConstraints = NO; + [cardHeaderViewWithPadding addSubview:cardHeaderView]; + + [cardHeaderView.leadingAnchor constraintEqualToAnchor:cardHeaderViewWithPadding.leadingAnchor].active = YES; + [cardHeaderView.trailingAnchor constraintEqualToAnchor:cardHeaderViewWithPadding.trailingAnchor].active = YES; + [cardHeaderView.bottomAnchor constraintEqualToAnchor:cardHeaderViewWithPadding.bottomAnchor].active = YES; + [cardHeaderView.topAnchor constraintEqualToAnchor:cardHeaderViewWithPadding.topAnchor constant:FirstSectionHeaderPadding].active = YES; + + headerView = cardHeaderViewWithPadding; + } else { + headerView = cardHeaderView; + } + + return headerView; +} + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { + return !_isCompleted; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + if (_isCompleted == NO) { + return nil; + } + + ORKReviewSectionFooter *sectionFooter = (ORKReviewSectionFooter *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:[NSString stringWithFormat:@"Footer%@", @(section).stringValue]]; + if (!sectionFooter) { + sectionFooter = [ORKReviewSectionFooter new]; + sectionFooter.button.tag = section; + [sectionFooter.button addTarget:self action:@selector(footerButtonTappedForSection:) forControlEvents:UIControlEventTouchUpInside]; + } + + return sectionFooter; +} + +- (nullable ORKStep *)stepForIdentifier:(NSString *)identifier { + for (ORKStep *step in _steps) { + if ([step.identifier isEqualToString:identifier]) { + return step; + } + } + return nil; +} + +- (void)footerButtonTappedForSection:(id)sender { + UIButton *button = (UIButton *)sender; + + ORKOrderedTask *subOrderedTask = [[ORKOrderedTask alloc] initWithIdentifier:[[NSUUID UUID] UUIDString] steps:@[[self stepForIdentifier:_reviewSections[button.tag].stepIdentifier]]]; + ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:subOrderedTask taskRunUUID:[NSUUID UUID]]; + taskViewController.delegate = self; + [taskViewController.navigationBar setTranslucent:YES]; + taskViewController.navigationBar.prefersLargeTitles = NO; + taskViewController.defaultResultSource = _resultSource; + taskViewController.discardable = YES; + taskViewController.showsProgressInNavigationBar = NO; + [self presentViewController:taskViewController animated:YES completion:nil]; +} + +#pragma mark - UItableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + if ((_isCompleted == NO) && (indexPath.row == 0)) { + if (_delegate && [_delegate respondsToSelector:@selector(reviewViewControllerDidSelectIncompleteCell:)]) { + [_delegate reviewViewControllerDidSelectIncompleteCell:self]; + } + } + + [tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + +#pragma mark - ORKTaskViewControllerDelegate + +- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error { + if (reason == ORKTaskViewControllerFinishReasonCompleted) { + if (_delegate && [_delegate respondsToSelector:@selector(reviewViewController:didUpdateResult:source:)]) { + ORKTaskResult *taskResult = ORKDynamicCast(_resultSource, ORKTaskResult); + [_delegate reviewViewController:self didUpdateResult:taskViewController.result source:taskResult]; + } + } + [taskViewController dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillAppear:(ORKStepViewController *)stepViewController { + stepViewController.shouldPresentInReview = _isCompleted; +} + +- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep forStepViewController:(ORKStepViewController *)stepViewController { + if (_delegate && [_delegate respondsToSelector:@selector(taskViewController:learnMoreButtonPressedWithStep:)]) { + [_delegate taskViewController:taskViewController learnMoreButtonPressedWithStep:learnMoreStep]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.h new file mode 100755 index 0000000..d364b47 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.h @@ -0,0 +1,62 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKRingViewDelegate + +@optional +- (void)ringViewDidFinishFillAnimation; + +@end + +@interface ORKRingView : UIView + +@property (nonatomic) double value; +@property (nonatomic) UIColor *color; +@property (nonatomic) CFTimeInterval animationDuration; +@property (nonatomic, weak, nullable) id delegate; + +- (void)setValue:(double)value WithColor:(nullable UIColor *)color; + +- (void)fillRingWithDuration:(NSTimeInterval)duration; + +- (void)setBackgroundLayerStrokeColor:(UIColor *)backgroundStrokeColor circleStrokeColor:(UIColor *)circleStrokeColor; + +- (void)resetLayerColors; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.m new file mode 100755 index 0000000..9b4df59 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRingView.m @@ -0,0 +1,233 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +#import "ORKRingView.h" + +static const double VALUE_MIN = 0.0; +static const double VALUE_MAX = 1.0; +static const double VIEW_DIMENSION = 150.0; +static const CFTimeInterval DEFAULT_ANIMATION_DURATION = 1.25; +static const CGFloat RingLineWidth = 3.0; +static const CGFloat CircleLineWidth = 6.0; + +@implementation ORKRingView { + CAShapeLayer *_circleLayer; + CAShapeLayer *_backgroundLayer; + CAShapeLayer *_filledCircleLayer; + + NSUUID *_transactionID; +} + + +- (instancetype)init { + self = [super init]; + if (self) { + _color = [[self tintColor] colorWithAlphaComponent:0.8]; + _animationDuration = DEFAULT_ANIMATION_DURATION; + _value = VALUE_MIN; + _backgroundLayer = [self createShapeLayer]; + _backgroundLayer.borderColor = _color.CGColor; + + if (@available(iOS 13.0, *)) { + _backgroundLayer.strokeColor = [[UIColor systemGray6Color] CGColor]; + } else { + // Fallback on earlier versions + _backgroundLayer.strokeColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3].CGColor; + } + [self.layer addSublayer:_backgroundLayer]; + + _filledCircleLayer = [self filledCircleLayer]; + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:VIEW_DIMENSION], + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:VIEW_DIMENSION] + ]]; + + } + + return self; +} + +- (CAShapeLayer *)createShapeLayer { + CAShapeLayer *layer = [CAShapeLayer layer]; + layer.lineCap = kCALineCapRound; + layer.path = [self createPath].CGPath; + layer.fillColor = [UIColor clearColor].CGColor; + layer.strokeColor = _color.CGColor; + + layer.lineWidth = RingLineWidth; + return layer; +} + +- (UIBezierPath *)createPath { + CGFloat radius = VIEW_DIMENSION / 2.0; + UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:[self ringCenter] + radius:radius + startAngle:2 * M_PI * (VALUE_MAX - 0.25) + endAngle:-M_PI_2 + clockwise:NO]; + return path; +} + +- (CGPoint)ringCenter { + CGFloat radius = VIEW_DIMENSION / 2.0; + return CGPointMake(radius, radius); +} + +- (CAShapeLayer *)filledCircleLayer { + CAShapeLayer *filledCircle = [CAShapeLayer layer]; + CGRect bounds = self.bounds; + UIBezierPath *maskLayerPath = [UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:VIEW_DIMENSION / 2.0]; + filledCircle.path = maskLayerPath.CGPath; + filledCircle.fillColor = [UIColor whiteColor].CGColor; + return filledCircle; +} + +- (void)setValue:(double)value { + if (value != _value) { + + double oldValue = _value; + _value = value; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + NSNumber *presentationLayerValue; + if (![_circleLayer.presentationLayer animationForKey:@"strokeStart"]) { + presentationLayerValue = @(1.0 - oldValue); + } else { + presentationLayerValue = [_circleLayer.presentationLayer valueForKey:@"strokeStart"]; + [_circleLayer removeAllAnimations]; + } + + NSUUID *caid = [NSUUID UUID]; + _transactionID = caid; + + [CATransaction begin]; + + [_circleLayer removeFromSuperlayer]; + _circleLayer = [self createShapeLayer]; + _circleLayer.lineWidth = CircleLineWidth; + _circleLayer.strokeColor = UIColor.systemGrayColor.CGColor; + [self.layer addSublayer:_circleLayer]; + + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeStart"]; + animation.fromValue = @([presentationLayerValue doubleValue]); + animation.toValue = @(1.0 - value); + animation.beginTime = 0.0; + animation.duration = _animationDuration; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + animation.fillMode = kCAFillModeBoth; + animation.removedOnCompletion = NO; + + [CATransaction setCompletionBlock:^{ + if([caid isEqual:_transactionID]){ + if (_value == VALUE_MIN) { + [_circleLayer removeFromSuperlayer]; + } + else { + [_circleLayer setStrokeColor:_color.CGColor]; + if (_value == VALUE_MAX && self.delegate && [self.delegate respondsToSelector:@selector(ringViewDidFinishFillAnimation)]) { + [self.delegate ringViewDidFinishFillAnimation]; + } + } + } + }]; + + [_circleLayer addAnimation:animation forKey:animation.keyPath]; + [CATransaction commit]; + }); + + } else { + if (value != VALUE_MAX) { + _backgroundLayer.fillColor = [UIColor clearColor].CGColor; + [_filledCircleLayer removeFromSuperlayer]; + } + } +} + +- (void)setValue:(double)value WithColor:(nullable UIColor *)color { + if (color) { + _color = color; + } + [self setValue:value]; +} + +- (void)setBackgroundLayerStrokeColor:(UIColor *)backgroundStrokeColor circleStrokeColor:(UIColor *)circleStrokeColor { + if (_backgroundLayer) { + _backgroundLayer.strokeColor = backgroundStrokeColor.CGColor; + } + if (_circleLayer) { + _circleLayer.strokeColor = circleStrokeColor.CGColor; + } +} + +- (void)resetLayerColors { + if (@available(iOS 13.0, *)) { + _backgroundLayer.strokeColor = [[UIColor systemGray6Color] CGColor]; + } else { + // Fallback on earlier versions + _backgroundLayer.strokeColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.3].CGColor; + } + _circleLayer.strokeColor = UIColor.systemGrayColor.CGColor; +} + +- (void)fillRingWithDuration:(NSTimeInterval)duration { + _animationDuration = duration; + [self setValue:1.0]; +} + +- (void)ringAnimation { + [self.layer insertSublayer:_filledCircleLayer above:_backgroundLayer]; + _backgroundLayer.fillColor = _color.CGColor; + + UIBezierPath *endShape = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(55, 55, 0, 0) + cornerRadius:VIEW_DIMENSION / 2.0]; + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; + animation.toValue = (__bridge id _Nullable)(endShape.CGPath); + animation.duration = 0.5; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; + animation.fillMode = kCAFillModeBoth; + animation.removedOnCompletion = NO; + + [_filledCircleLayer addAnimation:animation forKey:animation.keyPath]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.h new file mode 100755 index 0000000..e6b14dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKRoundTappingButton : ORKBorderedButton + +@property (nonatomic, assign) CGFloat diameter; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.m new file mode 100755 index 0000000..8972763 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKRoundTappingButton.m @@ -0,0 +1,92 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTextButton_Internal.h" +#import "ORKRoundTappingButton.h" + + +static const CGFloat RoundTappingButtonDefaultDiameter = 104; + + +@implementation ORKRoundTappingButton { + NSLayoutConstraint *_widthConstraint; + NSLayoutConstraint *_heightConstraint; +} + + +- (void)init_ORKTextButton { + [super init_ORKTextButton]; + self.fadeDelay = 0.2; + [self setDiameter:RoundTappingButtonDefaultDiameter]; + [self updateDimensionConstraints]; +} + +- (void)setDiameter:(CGFloat)diameter { + _diameter = diameter; + self.layer.cornerRadius = diameter * 0.5; + [self updateDimensionConstraints]; +} + +- (void)updateDimensionConstraints { + if (_widthConstraint && _widthConstraint.active) { + [NSLayoutConstraint deactivateConstraints:@[_widthConstraint]]; + } + if (_heightConstraint && _heightConstraint.active) { + [NSLayoutConstraint deactivateConstraints:@[_heightConstraint]]; + } + _widthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:_diameter]; + _heightConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:_diameter]; + [NSLayoutConstraint activateConstraints:@[_widthConstraint, _heightConstraint]]; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + self.layer.cornerRadius = _diameter * 0.5; +} + ++ (UIFont *)defaultFont { + // regular, 20 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 3.0]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.h new file mode 100755 index 0000000..e481eac --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKSESAnswerFormat; + +@protocol ORKSESSelectionViewDelegate + +- (void)buttonPressedAtIndex:(NSInteger)index; + +@end + +@interface ORKSESSelectionView : UIView + +- (instancetype)initWithAnswerFormat:(ORKSESAnswerFormat *)answerFormat answer:(nullable id)answer; +- (instancetype)initWithAnswerFormat:(ORKSESAnswerFormat *)answerFormat; + +@property (nonatomic, weak) id delegate; +@property (nonatomic, strong, nullable) id answer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.m new file mode 100755 index 0000000..94c856f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSESSelectionView.m @@ -0,0 +1,358 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKSESSelectionView.h" +#import "ORKAnswerFormat.h" +#import "ORKCheckmarkView.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +/* + + |-(UILabel)-(UIImageView)-(UILabel)-(ORKCheckmarkView)-| + + __ + __| <---rungIndex0 + __| + __| + __| + __| + __| + __| + __| + __| + | <---rungIndex9 + */ + +static const int defaultNumberOfRungs = 10; +static const CGFloat rungHeight = 36.0; +static const CGFloat rungWidth = 40.0; +static const CGFloat labelToRungPadding = 20.0; +static const CGFloat labelToCheckmarkPadding = 8.0; +static const CGFloat rungToRungPadding = 6.0; +static const CGFloat rungButtonPadding = 10.0; + +@interface ORKSESRungView : UIView + +- (instancetype)initWithRungAtIndex:(NSUInteger)rungIndex text:(nullable NSString *)text; + +- (void)setText:(NSString *)text; + +- (void)setChecked:(BOOL)checked; + +@end + +@implementation ORKSESRungView { + UILabel *_frontLabel; + UILabel *_rearLabel; + UIImageView *_rungImageView; + ORKCheckmarkView *_checkmarkView; + CGFloat _paddingMultiplier; + NSUInteger _rungIndex; + NSLayoutConstraint *_labelToRungConstraint; + NSLayoutConstraint *_rungToLabelConstraint; +} + +- (instancetype)initWithRungAtIndex:(NSUInteger)rungIndex text:(nullable NSString *)text { + self = [super init]; + if (self) { + _rungIndex = rungIndex; + [self setupLabels]; + [self setText:text]; + [self setupCheckmarkView]; + [self setupRungImageView]; + [self setupVariableConstraints]; + } + return self; +} + +- (void)setText:(NSString *)text { + if (_rungIndex == defaultNumberOfRungs-1) { + _rearLabel.text = text; + } + else if (_rungIndex == 0) { + _frontLabel.text = text; + } +} + +- (void)setupCheckmarkView { + if (!_checkmarkView) { + _checkmarkView = [[ORKCheckmarkView alloc] initWithDefaults]; + } + [_checkmarkView setChecked:NO]; + [self addSubview:_checkmarkView]; + _checkmarkView.contentMode = UIViewContentModeScaleAspectFill; + _checkmarkView.translatesAutoresizingMaskIntoConstraints = NO; +} + +- (void)setupRungImageView { + if (!_rungImageView) { + _rungImageView = [UIImageView new]; + } + _rungImageView.translatesAutoresizingMaskIntoConstraints = NO; + _rungImageView.contentMode = UIViewContentModeScaleAspectFit; + _rungImageView.image = [[UIImage imageNamed:@"socioEconomicLadderRung" inBundle:ORKBundle() compatibleWithTraitCollection:nil] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + _rungImageView.tintColor = self.tintColor; + [self addSubview:_rungImageView]; +} + +- (void)setupLabels { + _frontLabel = [UILabel new]; + _rearLabel = [UILabel new]; + for (UILabel *label in @[_frontLabel, _rearLabel]) { + label.numberOfLines = 1; + label.font = [self bodyTextFont]; + label.textColor = [UIColor grayColor]; + label.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:label]; + } + _frontLabel.textAlignment = NSTextAlignmentRight; + _rearLabel.textAlignment = NSTextAlignmentLeft; +} + +- (UIFont *)bodyTextFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (void)setupVariableConstraints { + [[_checkmarkView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-rungButtonPadding] setActive:YES]; + [[_checkmarkView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor] setActive:YES]; + + [[_rearLabel.trailingAnchor constraintEqualToAnchor:_checkmarkView.leadingAnchor constant:-labelToCheckmarkPadding] setActive:YES]; + [[_rearLabel.centerYAnchor constraintEqualToAnchor:self.centerYAnchor] setActive:YES]; + + [[_rungImageView.heightAnchor constraintEqualToConstant:rungHeight] setActive:YES]; + [[_rungImageView.widthAnchor constraintEqualToConstant:rungWidth] setActive:YES]; + [[_rungImageView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor] setActive:YES]; + [[_rearLabel.leadingAnchor constraintEqualToAnchor:_rungImageView.trailingAnchor constant:_rearLabel.text ? labelToRungPadding : 0.0] setActive:YES]; + + [[_frontLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:rungButtonPadding] setActive:YES]; + [[_frontLabel.centerYAnchor constraintEqualToAnchor:self.centerYAnchor] setActive:YES]; + [[_frontLabel.trailingAnchor constraintEqualToAnchor:_rungImageView.leadingAnchor constant:_frontLabel.text ? -labelToRungPadding : 0.0] setActive:YES]; + + CGFloat unavialableConstantSpace = rungButtonPadding + CheckmarkViewDimension + labelToCheckmarkPadding + (_rearLabel.text ? labelToRungPadding : 0.0) + rungWidth; + + CGFloat multiplier = ((CGFloat)_rungIndex)/(CGFloat)defaultNumberOfRungs; + + [[_rearLabel.widthAnchor constraintEqualToAnchor:self.widthAnchor multiplier:multiplier constant:-multiplier*unavialableConstantSpace] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_rungImageView.bottomAnchor] setActive:YES]; +} + +- (void)setChecked:(BOOL)checked { + [_checkmarkView setChecked:checked]; +} + +@end + +@interface ORKSESRungButton : UIButton + +@property (nonatomic) NSUInteger rungIndex; + +- (instancetype)initTopRungButtonWithText:(NSString *)text; +- (instancetype)initBottomRungButtonWithText:(NSString *)text; +- (instancetype)initWithRungAtIndex:(NSUInteger)rungIndex; +- (void)setSelected:(BOOL)selected highlight:(BOOL)highlight; + +@end + +@implementation ORKSESRungButton { + ORKSESRungView *_rungView; + UIColor *_fillColor; +} + +- (instancetype)initWithRungAtIndex:(NSUInteger)rungIndex + text:(nullable NSString *)text { + self = [super init]; + if (self) { + _rungIndex = rungIndex; + _rungView = [[ORKSESRungView alloc] initWithRungAtIndex:rungIndex text:text]; + [_rungView setUserInteractionEnabled:NO]; + [self setupRungView]; + self.tag = _rungIndex; + [self updateFillColor]; + self.layer.backgroundColor = _fillColor.CGColor; + } + return self; +} + +- (void)setupRungView { + if (_rungView) { + _rungView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_rungView]; + [[_rungView.topAnchor constraintEqualToAnchor:self.topAnchor] setActive:YES]; + [[_rungView.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[_rungView.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_rungView.bottomAnchor] setActive:YES]; + } +} + +- (instancetype)initTopRungButtonWithText:(NSString *)text { + return [self initWithRungAtIndex:0 text:text]; +} + +- (instancetype)initBottomRungButtonWithText:(NSString *)text { + return [self initWithRungAtIndex:defaultNumberOfRungs-1 text:text]; +} + +- (instancetype)initWithRungAtIndex:(NSUInteger)rungIndex { + return [self initWithRungAtIndex:rungIndex text:nil]; +} + +- (void)setSelected:(BOOL)selected highlight:(BOOL)highlight { + [super setSelected:selected]; + [_rungView setChecked:selected]; + if (highlight) { + [self tapAnimation]; + } +} + +- (void)tapAnimation { + CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"]; + if (@available(iOS 13.0, *)) { + animation.fromValue = (__bridge id _Nullable)(UIColor.systemGray5Color.CGColor); + } else { + animation.fromValue = (__bridge id _Nullable)([UIColor colorWithRed:0.282 green:0.282 blue:0.235 alpha:1.0].CGColor); + } + animation.toValue = (__bridge id _Nullable)(_fillColor.CGColor); + animation.beginTime = 0.0; + animation.duration = 0.45; + animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; + animation.removedOnCompletion = YES; + [self.layer addAnimation:animation forKey:@"backgroundColor"]; + self.layer.backgroundColor = _fillColor.CGColor; +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { + [super traitCollectionDidChange:previousTraitCollection]; + [self updateFillColor]; +} + +- (void)updateFillColor { + if (@available(iOS 13.0, *)) { + _fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + // FIXME:- dark mode color displays solid black after animation ends if the views are stacked + if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) { + _fillColor = [UIColor colorWithRed:0.173 green:0.173 blue:0.180 alpha:1.0]; + } + } else { + _fillColor = [UIColor ork_borderGrayColor]; + } + self.layer.backgroundColor = _fillColor.CGColor; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + if (highlighted) { + if (@available(iOS 13.0, *)) { + self.layer.backgroundColor = UIColor.systemGray5Color.CGColor; + } else { + self.layer.backgroundColor = [UIColor colorWithRed:0.282 green:0.282 blue:0.235 alpha:1.0].CGColor; + } + } + else { + self.layer.backgroundColor = _fillColor.CGColor; + } +} + +@end + +@implementation ORKSESSelectionView { + NSMutableArray *_buttons; + ORKSESAnswerFormat *_answerFormat; +} + +- (instancetype)initWithAnswerFormat:(ORKSESAnswerFormat *)answerFormat answer:(nullable id)answer { + self = [super init]; + if (self) { + _answerFormat = answerFormat; + _answer = answer; + [self addRungButtonsWithTopRungText:_answerFormat.topRungText bottomRungText:_answerFormat.bottomRungText]; + } + return self; +} + +- (instancetype)initWithAnswerFormat:(ORKSESAnswerFormat *)answerFormat { + self = [self initWithAnswerFormat:answerFormat answer:nil]; + return self; +} + +- (void)addRungButtonsWithTopRungText:(NSString *)topRungText bottomRungText:(NSString *)bottomRungText { + _buttons = [[NSMutableArray alloc] init]; + ORKSESRungButton *topButton = [[ORKSESRungButton alloc] initTopRungButtonWithText:topRungText]; + [_buttons addObject:topButton]; + for (int rungIndex = 1; rungIndex < defaultNumberOfRungs-1; rungIndex++) { + ORKSESRungButton *button = [[ORKSESRungButton alloc] initWithRungAtIndex:rungIndex]; + [_buttons addObject:button]; + } + ORKSESRungButton *bottomButton = [[ORKSESRungButton alloc] initBottomRungButtonWithText:bottomRungText]; + [_buttons addObject:bottomButton]; + + for (int i = 0; i < _buttons.count; i++) { + ORKSESRungButton *rungButton = _buttons[i]; + rungButton.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:rungButton]; + [rungButton addTarget:self action:@selector(rungButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; + + [[rungButton.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[rungButton.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + [[rungButton.topAnchor constraintEqualToAnchor:(i==0) ? self.topAnchor : _buttons[i-1].bottomAnchor constant:(i==0) ? rungButtonPadding : rungToRungPadding] setActive:YES]; + if (i==_buttons.count-1) { + [[self.bottomAnchor constraintGreaterThanOrEqualToAnchor:rungButton.bottomAnchor constant:rungButtonPadding] setActive:YES]; + } + + if (self.answer && ![self.answer isEqual:[NSNull null]]) { + // calling intValue on NSNull will cause a crash + if ([self.answer intValue] == i) { + [rungButton setSelected:YES highlight:NO]; + } else { + [rungButton setSelected:NO highlight:NO]; + } + } else { + [rungButton setSelected:NO highlight:NO]; + } + } +} + +- (void)rungButtonPressed:(id)sender { + ORKSESRungButton *buttonPressed = (ORKSESRungButton *)sender; + [buttonPressed setSelected:YES highlight:YES]; + for (ORKSESRungButton *button in _buttons) { + if (buttonPressed.tag != button.tag) { + [button setSelected:NO highlight:NO]; + } + } + if (self.delegate && [self.delegate respondsToSelector:@selector(buttonPressedAtIndex:)]) { + [self.delegate buttonPressedAtIndex:buttonPressed.tag]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.h new file mode 100755 index 0000000..3c961a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKScaleRangeLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Start/End description of the range in scale slider. + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleRangeDescriptionLabel : ORKScaleRangeLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.m new file mode 100755 index 0000000..c73d0df --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeDescriptionLabel.m @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleRangeDescriptionLabel.h" + +#import "ORKSkin.h" + + +@implementation ORKScaleRangeDescriptionLabel + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.textColor = [UIColor ork_grayColor]; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.h new file mode 100755 index 0000000..4b3200a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Start/End image of the range in scale slider. + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleRangeImageView : UIImageView + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.m new file mode 100755 index 0000000..ee7d844 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeImageView.m @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleRangeImageView.h" + + +static const CGFloat ScaleRangeImageHeight = 30; +static const CGFloat ScaleRangeImageWidth = 30; + +@implementation ORKScaleRangeImageView + +- (CGSize)intrinsicContentSize { + return CGSizeMake(ScaleRangeImageWidth, ScaleRangeImageHeight); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.h new file mode 100755 index 0000000..8a76316 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Start/End of the range in scale slider. + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleRangeLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.m new file mode 100755 index 0000000..78d3387 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleRangeLabel.m @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleRangeLabel.h" + + +@implementation ORKScaleRangeLabel + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return [UIFont systemFontOfSize:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.h new file mode 100755 index 0000000..c47923b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKScaleSlider : UISlider + +@property (nonatomic, assign) BOOL showThumb; + +@property (nonatomic, assign) BOOL hideValueMarkers; + +@property (nonatomic, assign) BOOL isWaitingForUserFeedback; + +@property (nonatomic, assign) NSUInteger numberOfSteps; + +@property (nonatomic, assign, getter=isVertical) BOOL vertical; + +@property (nonatomic, copy, nullable) NSArray *textChoices; + +@property (nonatomic, copy, nullable) NSArray *gradientColors; + +@property (nonatomic, copy, nullable) NSArray *gradientLocations; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.m new file mode 100755 index 0000000..75e6c83 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSlider.m @@ -0,0 +1,382 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2015, Bruce Duncan. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleSlider.h" + +#import "ORKScaleRangeDescriptionLabel.h" +#import "ORKScaleRangeImageView.h" +#import "ORKScaleSliderView.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKAccessibility.h" +#import "ORKSkin.h" + + +@interface ORKScaleSlider () + +@property (nonatomic, strong, nullable) CAGradientLayer *gradientLayer; + +@end + + +@implementation ORKScaleSlider { + CFAbsoluteTime _axLastOutputTime; + BOOL _thumbImageNeedsTransformUpdate; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sliderTouched:)]; + [self addGestureRecognizer:tapGesture]; + + UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(sliderTouched:)]; + [self addGestureRecognizer:panGesture]; + + if (@available(iOS 13.0, *)) { + self.maximumTrackTintColor = [UIColor systemGray3Color]; + } else { + self.maximumTrackTintColor = [UIColor systemGrayColor]; + } + + self.gradientLayer = [CAGradientLayer layer]; + + _numberOfSteps = 2; + + self.showThumb = NO; + self.hideValueMarkers = NO; + self.isWaitingForUserFeedback = NO; + + _axLastOutputTime = 0; + _thumbImageNeedsTransformUpdate = NO; + } + return self; +} + +- (void)setShowThumb:(BOOL)showThumb { + _showThumb = showThumb; + [self setNeedsLayout]; +} + +- (void)setVertical:(BOOL)vertical { + if (vertical != _vertical) { + _vertical = vertical; + self.transform = _vertical ? CGAffineTransformMakeRotation(-M_PI_2) : CGAffineTransformIdentity; + _thumbImageNeedsTransformUpdate = YES; + [self invalidateIntrinsicContentSize]; + } +} + +- (void)setGradientColors:(nullable NSArray *)gradientColors { + _gradientColors = [gradientColors copy]; + if (gradientColors) { + NSMutableArray *cgGolors = [[NSMutableArray alloc] init]; + for (UIColor *uiColor in gradientColors) { + [cgGolors addObject:(id)uiColor.CGColor]; + } + _gradientLayer.colors = cgGolors; + [self.layer insertSublayer:_gradientLayer atIndex:0]; + } else { + [_gradientLayer removeFromSuperlayer]; + } +} + +- (void)setGradientLocations:(nullable NSArray *)gradientLocations { + _gradientLocations = [gradientLocations copy]; + _gradientLayer.locations = gradientLocations; +} + +// Error prone: needs to be replaced by a custom thumb asset +// Details here: https://github.com/ResearchKit/ResearchKit/pull/33#discussion_r28804792 +// Tracked here: https://github.com/ResearchKit/ResearchKit/issues/67 +- (UIView *)thumbImageSubview { + UIView *thumbImageSubview = nil; + CGRect bounds = self.bounds; + CGRect trackRect = [self trackRectForBounds:bounds]; + CGRect thumbRect = [self thumbRectForBounds:bounds trackRect:trackRect value:self.value]; + for (UIView *subview in self.subviews) { + if (CGRectEqualToRect(thumbRect, subview.frame)) { + thumbImageSubview = subview; + break; + } + } + return thumbImageSubview; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + if (_thumbImageNeedsTransformUpdate) { + _thumbImageNeedsTransformUpdate = NO; + [self thumbImageSubview].transform = _vertical ? CGAffineTransformMakeRotation(M_PI_2) : CGAffineTransformIdentity; + } +} + +- (CGSize)intrinsicContentSize { + CGSize intrinsicContentSize = [super intrinsicContentSize]; + if (_vertical) { + CGFloat verticalScaleHeight = ORKGetMetricForWindow(ORKScreenMetricVerticalScaleHeight, self.window); + intrinsicContentSize = (CGSize){.width = verticalScaleHeight, .height = verticalScaleHeight}; + } + return intrinsicContentSize; +} + +- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { + BOOL pointInside = NO; + if (_vertical) { + + const CGFloat desiredSliderWidth = 44.0; + + if (_textChoices) { + if (point.y > (self.bounds.size.width - desiredSliderWidth) / 2) { + pointInside = [super pointInside:point withEvent:event]; + } + } else { + // In vertical mode, we need to ignore the touch area for the needed extra width + const CGFloat actualWidth = self.bounds.size.width; + const CGFloat centerX = actualWidth / 2; + if (fabs(point.y - centerX) < desiredSliderWidth / 2) { + pointInside = [super pointInside:point withEvent:event]; + } + } + } else { + pointInside = [super pointInside:point withEvent:event]; + } + return pointInside; +} + +- (void)sliderTouched:(UIGestureRecognizer *)gesture { + self.showThumb = YES; + + CGPoint touchPoint = [gesture locationInView:self]; + [self updateValueForTouchAtPoint:touchPoint]; + + [self sendActionsForControlEvents:UIControlEventValueChanged]; + [self _announceNewValue]; +} + +- (void)updateValueForTouchAtPoint:(CGPoint)touchPoint { + // Ignore negative (out of bounds) positions + if (touchPoint.x < 0) { + touchPoint.x = 0; + } + CGRect trackRect = [self trackRectForBounds:self.bounds]; + CGFloat position = (touchPoint.x - CGRectGetMinX(trackRect)) / CGRectGetWidth(trackRect); + + CGFloat newValue = position * (self.maximumValue - self.minimumValue) + self.minimumValue; + if (_numberOfSteps > 0) { + CGFloat stepSize = 1.0 / _numberOfSteps; + NSUInteger steps = round(position / stepSize); + + newValue = stepSize*steps * (self.maximumValue - self.minimumValue) + self.minimumValue; + } + [self setValue:newValue animated:YES]; +} + +static CGFloat LineWidth = 1.0; +- (void)drawRect:(CGRect)rect { + CGRect bounds = self.bounds; + CGRect trackRect = [self trackRectForBounds:bounds]; + CGFloat centerY = bounds.size.height / 2.0; + + if (@available(iOS 13.0, *)) { + [[UIColor systemGray3Color] set]; + } else { + [[UIColor systemGrayColor] setStroke]; + } + + if (_numberOfSteps > 0 && !_hideValueMarkers) { + + UIBezierPath *path = [[UIBezierPath alloc] init]; + [path setLineWidth:LineWidth]; + + for (int discreteOffset = 0; discreteOffset <= _numberOfSteps; ++discreteOffset) { + CGFloat x = trackRect.origin.x + (trackRect.size.width - LineWidth) * discreteOffset / _numberOfSteps; + x += LineWidth / 2; // Draw in center of line (center of pixel on 1x devices) + [path moveToPoint:CGPointMake(x, centerY - 6)]; + [path addLineToPoint:CGPointMake(x, centerY + 6)]; + } + + [path stroke]; + [[UIBezierPath bezierPathWithRect:trackRect] fill]; + } + + UIBezierPath *path2 = [[UIBezierPath alloc] init]; + [path2 setLineWidth:2.5]; + [path2 moveToPoint:CGPointMake(2.0, centerY)]; + [path2 addLineToPoint:CGPointMake(trackRect.size.width + 2.0, centerY)]; + [path2 stroke]; + + [[UIBezierPath bezierPathWithRect:trackRect] fill]; +} + +static const CGFloat Padding = 2.0; +- (CGRect)trackRectForBounds:(CGRect)bounds { + CGFloat centerY = (bounds.size.height / 2.0) - (LineWidth / 2.0); + CGRect rect = CGRectMake(bounds.origin.x + Padding, centerY, bounds.size.width - 2 * Padding, 1.0); + return rect; +} + +- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)trackRect value:(float)value { + CGRect rect = [super thumbRectForBounds:bounds trackRect:trackRect value:value]; + + // VO needs the thumb to be visible, so we don't hide it if VO is running. + if (_showThumb == NO && !UIAccessibilityIsVoiceOverRunning()) { + rect.origin.x = -1000; + return rect; + } + + CGFloat centerX = (value - self.minimumValue) / (self.maximumValue - self.minimumValue) * trackRect.size.width + trackRect.origin.x; + rect.origin.x = centerX - rect.size.width / 2.0; + + return rect; +} + +- (void)layoutSublayersOfLayer:(CALayer *)layer { + [super layoutSublayersOfLayer:layer]; + if (_gradientColors) { + const CGFloat maxGradientHeight = 5; + CGRect trackRect = [self trackRectForBounds:self.bounds]; + CGFloat gradientHeight = MIN(maxGradientHeight, CGRectGetMinY(trackRect) - CGRectGetMinY(self.bounds)); + + if (_vertical) { + _gradientLayer.frame = CGRectMake(CGRectGetMinX(trackRect), + CGRectGetMidY(self.bounds) + 2 * gradientHeight, + CGRectGetWidth(trackRect), + gradientHeight); + } else { + _gradientLayer.frame = CGRectMake(CGRectGetMinX(trackRect), + CGRectGetMinY(self.bounds), + CGRectGetWidth(trackRect), + gradientHeight); + } + + _gradientLayer.startPoint = CGPointMake(0, 0.5); + _gradientLayer.endPoint = CGPointMake(1, 0.5); + } +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (void)accessibilityIncrement { + [self axBumpValue:YES]; +} + +- (void)accessibilityDecrement { + [self axBumpValue:NO]; +} + +- (NSString *)accessibilityLabel { + ORKScaleSliderView *sliderView = (ORKScaleSliderView *)[self ork_superviewOfType:[ORKScaleSliderView class]]; + NSString *minimumValue = [self _axFormattedValue:self.minimumValue]; + NSString *maximumValue = [self _axFormattedValue:self.maximumValue]; + + // Include the range description labels if they are set. + if (sliderView.leftRangeDescriptionLabel.text.length > 0 && sliderView.rightRangeDescriptionLabel.text.length > 0) { + minimumValue = [minimumValue stringByAppendingFormat:@", %@, ", sliderView.leftRangeDescriptionLabel.text]; + maximumValue = [maximumValue stringByAppendingFormat:@", %@, ", sliderView.rightRangeDescriptionLabel.text]; + } + + // Include the range image accessibilty hints if they are set. + if (sliderView.leftRangeImageView.image.accessibilityHint.length > 0) { + minimumValue = [minimumValue stringByAppendingString:sliderView.leftRangeImageView.image.accessibilityHint]; + } + if (sliderView.rightRangeImageView.image.accessibilityHint.length > 0) { + maximumValue = [maximumValue stringByAppendingString:sliderView.rightRangeImageView.image.accessibilityHint]; + } + + + return [NSString stringWithFormat:ORKLocalizedString(@"AX_SLIDER_LABEL", nil), minimumValue, maximumValue]; +} + +- (NSString *)accessibilityValue { + // If thumb is hidden it means that the slider hasn't been touched yet. That is, there's currently + // no value (nor a default value), hence we shouldn't return one to VO. + if (!self.showThumb) { + return nil; + } else if (self.textChoices) { + ORKTextChoice *textChoice = self.textChoices[(NSInteger)self.value - 1]; + return textChoice.text; + } + return [self _axFormattedValue:self.value]; +} + +- (CGRect)accessibilityFrame { + UIView *containingCell = [self ork_superviewOfType:[UITableViewCell class]]; + + // Let the accessibilityFrame be equal to that of the containing cell so it's easier for VO users to touch. + if ([self isDescendantOfView:containingCell]) { + return UIAccessibilityConvertFrameToScreenCoordinates(containingCell.bounds, containingCell); + } + return CGRectZero; +} + +#pragma mark Accessibility Helpers + +- (NSString *)_axFormattedValue:(CGFloat)value { + if (_numberOfSteps == 0) { + return ORKAccessibilityFormatContinuousScaleSliderValue(value, self); + } else { + return ORKAccessibilityFormatScaleSliderValue(value, self); + } +} + +- (void)axBumpValue:(BOOL)increment { + self.showThumb = YES; + + // If there's no fixed number of steps, we rely on the default implementation. + if (_numberOfSteps == 0) { + (increment ? [super accessibilityIncrement] : [super accessibilityDecrement]); + return; + } + + // If there is a fixed number of steps, we must accommodate that, and don't allow VO users to set invalid values. + CGFloat stepSize = (self.maximumValue - self.minimumValue) / _numberOfSteps; + CGFloat newValue = self.value + (increment ? stepSize : -stepSize); + self.value = newValue; + [self sendActionsForControlEvents:UIControlEventValueChanged]; +} + +static const NSTimeInterval TimeoutSpeakThreshold = 1.0; +- (void)_announceNewValue { + if ( (CFAbsoluteTimeGetCurrent() - _axLastOutputTime) > TimeoutSpeakThreshold ) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.accessibilityValue); + _axLastOutputTime = CFAbsoluteTimeGetCurrent(); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.h new file mode 100755 index 0000000..2b20b8a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKScaleRangeLabel; +@class ORKScaleValueLabel; +@class ORKScaleRangeDescriptionLabel; +@class ORKScaleRangeImageView; +@class ORKScaleSliderView; +@protocol ORKScaleAnswerFormatProvider; + +@protocol ORKScaleSliderViewDelegate + +- (void)scaleSliderViewCurrentValueDidChange:(ORKScaleSliderView *)sliderView; + +@end + + +@interface ORKScaleSliderView : UIView + +- (instancetype)initWithFormatProvider:(id)formatProvider delegate:(id)delegate; + +@property (nonatomic, weak, readonly) id delegate; + +@property (nonatomic, strong, readonly) id formatProvider; + +@property (nonatomic, strong, readonly) ORKScaleRangeLabel *leftRangeLabel; + +@property (nonatomic, strong, readonly) ORKScaleRangeLabel *rightRangeLabel; + +@property (nonatomic, strong, readonly) ORKScaleRangeImageView *leftRangeImageView; + +@property (nonatomic, strong, readonly) ORKScaleRangeImageView *rightRangeImageView; + +@property (nonatomic, strong, readonly) ORKScaleRangeDescriptionLabel *leftRangeDescriptionLabel; + +@property (nonatomic, strong, readonly) ORKScaleRangeDescriptionLabel *rightRangeDescriptionLabel; + +@property (nonatomic, strong, readonly) ORKScaleValueLabel *valueLabel; + +// Accepts NSNumber for continous scale or discrete scale. +// Accepts NSArray> for text scale. +@property (nonatomic, strong, nullable) id currentAnswerValue; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.m new file mode 100755 index 0000000..3e49a13 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleSliderView.m @@ -0,0 +1,887 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleSliderView.h" + +#import "ORKScaleRangeDescriptionLabel.h" +#import "ORKScaleRangeImageView.h" +#import "ORKScaleRangeLabel.h" +#import "ORKScaleSlider.h" +#import "ORKScaleValueLabel.h" +#import "ORKDontKnowButton.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKSkin.h" + +#import "ORKHelpers_Internal.h" + +static const CGFloat ValueLabelTopPadding = 16.0; +static const CGFloat ValueLabelBottomPadding = 20.5; +static const CGFloat MoveSliderLabelTopPadding = 8.0; +static const CGFloat MoveSliderLabelBottomPadding = 38.0; +static const CGFloat RangeViewHorizontalPadding = 16.0; +static const CGFloat SliderBottomPadding = 16.0; +static const CGFloat DontKnowButtonTopBottomPadding = 16.0; +static const CGFloat kMargin = 25.0; + + +// #define LAYOUT_DEBUG 1 + +@implementation ORKScaleSliderView { + id _formatProvider; + UIStackView *_topStackView; + ORKScaleSlider *_slider; + UILabel *_moveSliderLabel; + ORKDontKnowButton *_dontKnowButton; + UIView *_dontKnowBackgroundView; + ORKScaleRangeDescriptionLabel *_leftRangeDescriptionLabel; + ORKScaleRangeDescriptionLabel *_rightRangeDescriptionLabel; + UIView *_leftRangeView; + UIView *_rightRangeView; + UIView *_dividerView; + ORKScaleValueLabel *_valueLabel; + NSMutableArray *_textChoiceLabels; + NSNumber *_currentNumberValue; + NSMutableArray *constraints; +} + +- (instancetype)initWithFormatProvider:(id)formatProvider + delegate:(id)delegate { + self = [self initWithFrame:CGRectZero]; + if (self) { + _formatProvider = formatProvider; + _delegate = delegate; + + _slider = [[ORKScaleSlider alloc] initWithFrame:CGRectZero]; + _slider.hideValueMarkers = [formatProvider shouldHideValueMarkers]; + _slider.isWaitingForUserFeedback = ([formatProvider defaultAnswer] == nil && ![formatProvider isVertical]) ? YES : NO; + _slider.minimumTrackTintColor = [UIColor systemBlueColor]; + _slider.userInteractionEnabled = YES; + _slider.contentMode = UIViewContentModeRedraw; + [self addSubview:_slider]; + + _slider.maximumValue = [formatProvider maximumNumber].floatValue; + _slider.minimumValue = [formatProvider minimumNumber].floatValue; + + NSInteger numberOfSteps = [formatProvider numberOfSteps]; + _slider.numberOfSteps = numberOfSteps; + + [_slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventValueChanged]; + + BOOL isVertical = [formatProvider isVertical]; + _slider.vertical = isVertical; + + NSArray *textChoices = [[self textScaleFormatProvider] textChoices]; + _slider.textChoices = textChoices; + + _slider.gradientColors = [formatProvider gradientColors]; + _slider.gradientLocations = [formatProvider gradientLocations]; + + if (isVertical && textChoices) { + // Generate an array of labels for all the text choices + _textChoiceLabels = [NSMutableArray new]; + for (int i = 0; i <= numberOfSteps; i++) { + ORKTextChoice *textChoice = textChoices[i]; + ORKScaleRangeLabel *stepLabel = [[ORKScaleRangeLabel alloc] initWithFrame:CGRectZero]; + stepLabel.text = textChoice.text; + stepLabel.textAlignment = NSTextAlignmentLeft; + stepLabel.numberOfLines = 0; + stepLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:stepLabel]; + [_textChoiceLabels addObject:stepLabel]; + } + } else { + [self setupTopLabels]; + [self setUpSliderAndRangeLabels]; + [self setupRangeDescriptionLabels]; + [self setupDontKnowButton]; + + _topStackView = [[UIStackView alloc] init]; + _topStackView.axis = UILayoutConstraintAxisHorizontal; + _topStackView.distribution = UIStackViewDistributionFill; + _topStackView.alignment = _slider.isWaitingForUserFeedback ? UIStackViewAlignmentLeading : UIStackViewAlignmentCenter; + _topStackView.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_leftRangeView]; + [self addSubview:_rightRangeView]; + [self addSubview:_leftRangeDescriptionLabel]; + [self addSubview:_rightRangeDescriptionLabel]; + [self addSubview:_valueLabel]; + + if (![formatProvider isVertical]) { + [self addSubview:_topStackView]; + + [_topStackView addArrangedSubview: _slider.isWaitingForUserFeedback ? _moveSliderLabel : _valueLabel]; + + if ([formatProvider shouldShowDontKnowButton]) { + [self addSubview:_dontKnowBackgroundView]; + [self addSubview:_dividerView]; + [self addSubview:_dontKnowButton]; + } + } + + if (textChoices) { + if (@available(iOS 13.0, *)) { + [_leftRangeDescriptionLabel setTextColor:[UIColor labelColor]]; + [_rightRangeDescriptionLabel setTextColor:[UIColor labelColor]]; + } else { + _leftRangeDescriptionLabel.textColor = [UIColor blackColor]; + _rightRangeDescriptionLabel.textColor = [UIColor blackColor]; + } + + _leftRangeLabel.text = @""; + _rightRangeLabel.text = @""; + } + +#if LAYOUT_DEBUG + self.backgroundColor = [UIColor greenColor]; + _valueLabel.backgroundColor = [UIColor blueColor]; + _slider.backgroundColor = [UIColor redColor]; + _leftRangeDescriptionLabel.backgroundColor = [UIColor yellowColor]; + _rightRangeDescriptionLabel.backgroundColor = [UIColor yellowColor]; +#endif + + + if (isVertical) { + _leftRangeDescriptionLabel.textAlignment = NSTextAlignmentLeft; + _rightRangeDescriptionLabel.textAlignment = NSTextAlignmentLeft; + } else { + _leftRangeDescriptionLabel.textAlignment = NSTextAlignmentLeft; + _rightRangeDescriptionLabel.textAlignment = NSTextAlignmentRight; + } + + _leftRangeDescriptionLabel.text = [formatProvider shouldHideLabels] ? @"" : [formatProvider minimumValueDescription]; + _rightRangeDescriptionLabel.text = [formatProvider shouldHideLabels] ? @"" : [formatProvider maximumValueDescription]; + + _moveSliderLabel.translatesAutoresizingMaskIntoConstraints = NO; + _valueLabel.translatesAutoresizingMaskIntoConstraints = NO; + _leftRangeView.translatesAutoresizingMaskIntoConstraints = NO; + _rightRangeView.translatesAutoresizingMaskIntoConstraints = NO; + _leftRangeLabel.translatesAutoresizingMaskIntoConstraints = NO; + _rightRangeLabel.translatesAutoresizingMaskIntoConstraints = NO; + _rightRangeDescriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; + _leftRangeDescriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; + _dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO; + _dividerView.translatesAutoresizingMaskIntoConstraints = NO; + } + + self.translatesAutoresizingMaskIntoConstraints = NO; + _slider.translatesAutoresizingMaskIntoConstraints = NO; + + [self setUpConstraints]; + } + return self; +} + +- (void)setupTopLabels { + _moveSliderLabel = [UILabel new]; + _moveSliderLabel.text = ORKLocalizedString(@"SLIDER_MOVE_SLIDER_FOR_VALUE", nil); + _moveSliderLabel.textAlignment = NSTextAlignmentLeft; + _moveSliderLabel.numberOfLines = 0; + _moveSliderLabel.lineBreakMode = NSLineBreakByWordWrapping; + UIFontDescriptor *moveSliderDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *moveSliderFontDescriptor = [moveSliderDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + [_moveSliderLabel setFont: [UIFont fontWithDescriptor:moveSliderFontDescriptor size:[[moveSliderFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + if (@available(iOS 13.0, *)) { + _moveSliderLabel.textColor = [UIColor secondaryLabelColor]; + } else { + _moveSliderLabel.textColor = [UIColor grayColor]; + } + + _valueLabel = [[ORKScaleValueLabel alloc] initWithFrame:CGRectZero]; + _valueLabel.text = @""; + _valueLabel.textAlignment = NSTextAlignmentCenter; + UIFontDescriptor *valueLabelDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleTitle2]; + UIFontDescriptor *valueLabelFontDescriptor = [valueLabelDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + [_valueLabel setFont: [UIFont fontWithDescriptor:valueLabelFontDescriptor size:[[valueLabelFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + [_valueLabel setTextColor:[UIColor systemBlueColor]]; +} + +- (void)setUpSliderAndRangeLabels { + UIFontDescriptor *rangeLabelDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + UIFontDescriptor *rangeLabelRangeFontDescriptor = [rangeLabelDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + + _leftRangeLabel = [[ORKScaleRangeLabel alloc] initWithFrame:CGRectZero]; + _leftRangeLabel.textAlignment = NSTextAlignmentCenter; + if (@available(iOS 13.0, *)) { + [_leftRangeLabel setTextColor:[UIColor labelColor]]; + } + [_leftRangeLabel setFont: [UIFont fontWithDescriptor:rangeLabelRangeFontDescriptor size:[[rangeLabelRangeFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + + _rightRangeLabel = [[ORKScaleRangeLabel alloc] initWithFrame:CGRectZero]; + _rightRangeLabel.textAlignment = NSTextAlignmentCenter; + if (@available(iOS 13.0, *)) { + [_rightRangeLabel setTextColor:[UIColor labelColor]]; + } + [_rightRangeLabel setFont: [UIFont fontWithDescriptor:rangeLabelRangeFontDescriptor size:[[rangeLabelRangeFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + + if ([_formatProvider minimumImage]) { + _leftRangeView = [[ORKScaleRangeImageView alloc] initWithImage:[_formatProvider minimumImage]]; + } else { + ORKScaleRangeLabel *leftRangeLabel = [[ORKScaleRangeLabel alloc] initWithFrame:CGRectZero]; + leftRangeLabel.textAlignment = NSTextAlignmentCenter; + leftRangeLabel.text = [_formatProvider localizedStringForNumber:[_formatProvider minimumNumber]]; + if ([_formatProvider shouldHideRanges]) { + leftRangeLabel.text = @""; + } else { + leftRangeLabel.text = [_formatProvider localizedStringForNumber:[_formatProvider minimumNumber]]; + } + _leftRangeView = leftRangeLabel; + } + + if ([_formatProvider maximumImage]) { + _rightRangeView = [[ORKScaleRangeImageView alloc] initWithImage:[_formatProvider maximumImage]]; + } else { + ORKScaleRangeLabel *rightRangeLabel = [[ORKScaleRangeLabel alloc] initWithFrame:CGRectZero]; + rightRangeLabel.textAlignment = NSTextAlignmentCenter; + if ([_formatProvider shouldHideRanges]) { + rightRangeLabel.text = @""; + } else { + rightRangeLabel.text = [_formatProvider localizedStringForNumber:[_formatProvider maximumNumber]]; + } + + _rightRangeView = rightRangeLabel; + } +} + +- (void)setupRangeDescriptionLabels { + UIFontDescriptor *rangeDescriptionLabelDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *rangeDescriptionLabelFontDescriptor = [rangeDescriptionLabelDescriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + + _leftRangeDescriptionLabel = [[ORKScaleRangeDescriptionLabel alloc] initWithFrame:CGRectZero]; + _leftRangeDescriptionLabel.numberOfLines = -1; + [_leftRangeDescriptionLabel setFont: [UIFont fontWithDescriptor:rangeDescriptionLabelFontDescriptor size:[[rangeDescriptionLabelFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + _leftRangeDescriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + [_leftRangeDescriptionLabel setTextColor:[UIColor labelColor]]; + } + + _rightRangeDescriptionLabel = [[ORKScaleRangeDescriptionLabel alloc] initWithFrame:CGRectZero]; + _rightRangeDescriptionLabel.numberOfLines = -1; + [_rightRangeDescriptionLabel setFont: [UIFont fontWithDescriptor:rangeDescriptionLabelFontDescriptor size:[[rangeDescriptionLabelFontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]]; + _rightRangeDescriptionLabel.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + [_rightRangeDescriptionLabel setTextColor:[UIColor labelColor]]; + } +} + +- (void)setupDontKnowButton { + if(!_dontKnowBackgroundView) { + _dontKnowBackgroundView = [UIView new]; + + UITapGestureRecognizer *tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)]; + [_dontKnowBackgroundView addGestureRecognizer:tapGesture1]; + _dontKnowBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + } + + if (!_dontKnowButton) { + _dontKnowButton = [ORKDontKnowButton new]; + _dontKnowButton.customDontKnowButtonText = [_formatProvider customDontKnowButtonText]; + [_dontKnowButton addTarget:self action:@selector(dontKnowButtonWasPressed) forControlEvents:UIControlEventTouchUpInside]; + } + + if (!_dividerView) { + _dividerView = [UIView new]; + if (@available(iOS 13.0, *)) { + [_dividerView setBackgroundColor:[UIColor separatorColor]]; + } else { + [_dividerView setBackgroundColor:[UIColor lightGrayColor]]; + } + } +} + +- (void)setUpConstraints { + BOOL isVertical = [_formatProvider isVertical]; + NSArray *textChoices = _slider.textChoices; + NSDictionary *views = nil; + + NSDictionary *metrics = @{@"valueLabelTopPadding":@(ValueLabelTopPadding), + @"valueLabelBottomPadding":@(ValueLabelBottomPadding), + @"moveSliderLabelTopPadding":@(MoveSliderLabelTopPadding), + @"moveSliderLabelBottomPadding":@(MoveSliderLabelBottomPadding), + @"rangeViewHorizontalPadding": @(RangeViewHorizontalPadding), + @"sliderBottomPadding": @(SliderBottomPadding), + @"dontKnowButtonTopBottomPadding": @(DontKnowButtonTopBottomPadding), + @"kMargin": @(kMargin)}; + + if (isVertical && textChoices) { + views = NSDictionaryOfVariableBindings(_slider); + } else { + views = NSDictionaryOfVariableBindings(_topStackView, _slider, _leftRangeView, _rightRangeView, _leftRangeDescriptionLabel, _rightRangeDescriptionLabel, _dividerView, _dontKnowButton, _valueLabel); + } + + if (constraints) { + [NSLayoutConstraint deactivateConstraints:constraints]; + } + + constraints = [NSMutableArray new]; + if (isVertical) { + _leftRangeDescriptionLabel.textAlignment = NSTextAlignmentLeft; + _rightRangeDescriptionLabel.textAlignment = NSTextAlignmentLeft; + + // Vertical slider constraints + // Keep the thumb the same distance from the value label as in horizontal mode + const CGFloat ValueLabelSliderMargin = 23.0; + // Keep the shadow of the thumb inside the bounds + const CGFloat SliderMargin = 20.0; + const CGFloat SideLabelMargin = 24; + + if (textChoices) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:_slider + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_slider + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:0.25 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-kSliderMargin-[_slider]-kSliderMargin-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:@{@"kSliderMargin": @(SliderMargin)} + views:views]]; + + + for (int i = 0; i < _textChoiceLabels.count; i++) { + // Put labels to the right side of the slider. + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:SideLabelMargin]]; + + if (i == 0) { + // First label + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:0.75 + constant:0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-SideLabelMargin]]; + + } else { + // Middle labels + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i - 1] + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i - 1] + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i - 1] + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + // Last label + if (i == (_textChoiceLabels.count - 1)) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textChoiceLabels[i] + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + } + } + } + } else { + [constraints addObject:[NSLayoutConstraint constraintWithItem:_slider + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_valueLabel]-(>=kValueLabelSliderMargin)-[_slider]-(>=kSliderMargin)-|" + options:NSLayoutFormatAlignAllCenterX | NSLayoutFormatDirectionLeadingToTrailing + metrics:@{@"kValueLabelSliderMargin": @(ValueLabelSliderMargin), @"kSliderMargin": @(SliderMargin)} + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_valueLabel]-(>=8)-[_rightRangeDescriptionLabel]" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObjectsFromArray + :[NSLayoutConstraint constraintsWithVisualFormat:@"H:[_rightRangeView(==_leftRangeView)]" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + // Set the margin between slider and the rangeViews + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:-SideLabelMargin]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftRangeView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:-SideLabelMargin]]; + + // Align the rangeViews with the slider's bottom + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftRangeView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_rightRangeDescriptionLabel]-(>=8)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_leftRangeDescriptionLabel(==_rightRangeDescriptionLabel)]-(>=8)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_rightRangeDescriptionLabel]-(>=8)-[_leftRangeDescriptionLabel]-(>=8)-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + // Set the margin between the slider and the descriptionLabels + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeDescriptionLabel + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:SideLabelMargin]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftRangeDescriptionLabel + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:SideLabelMargin]]; + + // Limit the height of the descriptionLabels + [self addConstraint:[NSLayoutConstraint constraintWithItem:self.rightRangeDescriptionLabel + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_slider + attribute:NSLayoutAttributeHeight + multiplier:0.5 + constant:SliderMargin]]; + + [self addConstraint:[NSLayoutConstraint constraintWithItem:self.leftRangeDescriptionLabel + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_slider + attribute:NSLayoutAttributeHeight + multiplier:0.5 + constant:SliderMargin]]; + + + // Align the descriptionLabels with the rangeViews + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeDescriptionLabel + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_rightRangeView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftRangeDescriptionLabel + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_leftRangeView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + } + } else { + + if (_slider.isWaitingForUserFeedback) { + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-moveSliderLabelTopPadding-[_topStackView]-moveSliderLabelBottomPadding-[_slider]-sliderBottomPadding-[_leftRangeDescriptionLabel]-(>=8)-|" + options:0 + metrics:metrics + views:views]]; + } else { + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-valueLabelTopPadding-[_topStackView]-valueLabelBottomPadding-[_slider]-sliderBottomPadding-[_leftRangeDescriptionLabel]-(>=8)-|" + options:0 + metrics:metrics + views:views]]; + } + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-kMargin-[_topStackView]-kMargin-|" + options:0 + metrics:metrics + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-kMargin-[_leftRangeView]-rangeViewHorizontalPadding-[_slider]-rangeViewHorizontalPadding-[_rightRangeView(==_leftRangeView)]-kMargin-|" + options:NSLayoutFormatAlignAllCenterY + metrics:metrics + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_leftRangeDescriptionLabel + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeDescriptionLabel + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_slider + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_rightRangeDescriptionLabel + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_leftRangeDescriptionLabel + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + + if ([_formatProvider shouldShowDontKnowButton]) { + [[_dontKnowBackgroundView.topAnchor constraintEqualToAnchor:_dividerView.topAnchor] setActive:YES]; + [[_dontKnowBackgroundView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor] setActive:YES]; + [[_dontKnowBackgroundView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor] setActive:YES]; + [[_dontKnowBackgroundView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] setActive:YES]; + + + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_dividerView]|" + options:0 + metrics:metrics + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dividerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:separatorHeight]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dividerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_leftRangeDescriptionLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:8.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dontKnowButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_dividerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:DontKnowButtonTopBottomPadding]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dontKnowButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_dividerView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dontKnowButton + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_dividerView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_dontKnowButton + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_dividerView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + [[self.bottomAnchor constraintEqualToAnchor:_dontKnowButton.bottomAnchor constant:DontKnowButtonTopBottomPadding] setActive: YES]; + } + } + + if ([_formatProvider shouldHideSelectedValueLabel] && + !([_formatProvider isVertical] && [self textScaleFormatProvider]) && !_slider.isWaitingForUserFeedback) { + _valueLabel.layer.opacity = 0.0; + } else { + _valueLabel.layer.opacity = 1.0; + } + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (id)textScaleFormatProvider { + if ([[_formatProvider class] conformsToProtocol:@protocol(ORKTextScaleAnswerFormatProvider)]) { + return (id)_formatProvider; + } + return nil; +} + +- (void)setCurrentNumberValue:(NSNumber *)value { + _currentNumberValue = value ? [_formatProvider normalizedValueForNumber:value] : nil; + _slider.showThumb = YES; + + if (_currentNumberValue && _slider.isWaitingForUserFeedback) { + [self resetViewToDefault]; + } + + [self updateCurrentValueLabel]; + _slider.value = _currentNumberValue.floatValue; +} + +- (NSUInteger)currentTextChoiceIndex { + return _currentNumberValue.unsignedIntegerValue - 1; +} + +- (void)updateCurrentValueLabel { + + if (_currentNumberValue) { + if ([self textScaleFormatProvider]) { + ORKTextChoice *textChoice = [[self textScaleFormatProvider] textChoiceAtIndex:[self currentTextChoiceIndex]]; + self.valueLabel.text = textChoice.text; + if (textChoice.primaryTextAttributedString) { + self.valueLabel.attributedText = textChoice.primaryTextAttributedString; + } + } else { + NSNumber *newValue = [_formatProvider normalizedValueForNumber:_currentNumberValue]; + _valueLabel.text = [_formatProvider localizedStringForNumber:newValue]; + } + } else { + _valueLabel.text = @""; + } +} + +- (IBAction)sliderValueChanged:(id)sender { + if (_slider.isWaitingForUserFeedback) { + [self resetViewToDefault]; + } + + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonInactive]; + } + + _currentNumberValue = [_formatProvider normalizedValueForNumber:@(_slider.value)]; + [self updateCurrentValueLabel]; + [self notifyDelegate]; +} + +- (void)resetViewToDefault { + _slider.isWaitingForUserFeedback = NO; + [_topStackView removeArrangedSubview:_moveSliderLabel]; + [_moveSliderLabel removeFromSuperview]; + [_topStackView addArrangedSubview:_valueLabel]; + _topStackView.alignment = UIStackViewAlignmentCenter; + + [NSLayoutConstraint deactivateConstraints:constraints]; + [constraints removeAllObjects]; + [self setUpConstraints]; +} + +- (void)dontKnowButtonWasPressed { + + if (_dontKnowButton && ![_dontKnowButton isDontKnowButtonActive]) { + [_slider setShowThumb:YES]; + [_dontKnowButton setButtonActive]; + _currentNumberValue = nil; + [self notifyDelegate]; + } + + if (!_slider.isWaitingForUserFeedback) { + _slider.isWaitingForUserFeedback = YES; + + [_topStackView removeArrangedSubview:_valueLabel]; + [_valueLabel removeFromSuperview]; + + [_topStackView addArrangedSubview:_moveSliderLabel]; + _topStackView.alignment = UIStackViewAlignmentLeading; + + [NSLayoutConstraint deactivateConstraints:constraints]; + [constraints removeAllObjects]; + [self setUpConstraints]; + _slider.value = [_formatProvider minimumNumber].floatValue; + } +} + +- (void) tapGesture: (id)sender { + //this tap gesture is here to avoid the cell being selected if the user missed the dont know button +} + +- (void)notifyDelegate { + + if (self.delegate && [self.delegate respondsToSelector:@selector(scaleSliderViewCurrentValueDidChange:)]) { + [self.delegate scaleSliderViewCurrentValueDidChange:self]; + } +} + +- (void)setCurrentTextChoiceValue:(id)currentTextChoiceValue { + + if (currentTextChoiceValue) { + NSUInteger index = [[self textScaleFormatProvider] textChoiceIndexForValue:currentTextChoiceValue]; + if (index != NSNotFound) { + [self setCurrentNumberValue:@(index + 1)]; + } else { + [self setCurrentNumberValue:nil]; + } + } else { + [self setCurrentNumberValue:nil]; + } +} + +- (id)currentTextChoiceValue { + id value = [[self textScaleFormatProvider] textChoiceAtIndex:[self currentTextChoiceIndex]].value; + return value; +} + +- (id)currentAnswerValue { + if ([_dontKnowButton isDontKnowButtonActive]) { + return [ORKDontKnowAnswer answer]; + } + if ([self textScaleFormatProvider]) { + id value = [self currentTextChoiceValue]; + return value ? @[value] : @[]; + } else { + return _currentNumberValue; + } +} + +- (void)setCurrentAnswerValue:(id)currentAnswerValue { + if (currentAnswerValue == [ORKDontKnowAnswer answer] && _dontKnowButton) { + [self dontKnowButtonWasPressed]; + } else if ([self textScaleFormatProvider]) { + + if (ORKIsAnswerEmpty(currentAnswerValue)) { + [self setCurrentTextChoiceValue:nil]; + } else { + [self setCurrentTextChoiceValue:[currentAnswerValue firstObject]]; + } + } else { + [self setCurrentNumberValue:currentAnswerValue]; + } + +} + +#pragma mark - Accessibility + +// Since the slider is the only interesting thing within this cell, we make the +// cell a container with only one element, i.e. the slider. + +- (BOOL)isAccessibilityElement { + return NO; +} + +- (NSInteger)accessibilityElementCount { + return (_slider != nil ? 1 : 0); +} + +- (id)accessibilityElementAtIndex:(NSInteger)index { + return _slider; +} + +- (NSInteger)indexOfAccessibilityElement:(id)element { + return (element == _slider ? 0 : NSNotFound); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.h new file mode 100755 index 0000000..dbf3894 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Large label shown separately from the scale slider to indicate the current value. + */ +ORK_CLASS_AVAILABLE +@interface ORKScaleValueLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.m new file mode 100755 index 0000000..327c41d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKScaleValueLabel.m @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKScaleValueLabel.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKScaleValueLabel + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return ORKLightFontWithSize(((NSNumber *)[descriptor objectForKey: UIFontDescriptorSizeAttribute]).doubleValue + 18.0); +} + +- (CGSize)intrinsicContentSize { + CGSize intrinsic = [super intrinsicContentSize]; + // Force the intrinsic content height to always be the height of the font, so that an + // empty label height doesnt go to 0, which would cause slider controls to jump + return (CGSize){.width=intrinsic.width,self.font.lineHeight}; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.h new file mode 100755 index 0000000..787672d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Details text in selection question's choice cell. + */ +ORK_CLASS_AVAILABLE +@interface ORKSelectionSubTitleLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.m new file mode 100755 index 0000000..35ddf50 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionSubTitleLabel.m @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSelectionSubTitleLabel.h" + + +@implementation ORKSelectionSubTitleLabel + ++ (UIFont *)defaultFont { + // regular, 14. Increased by 1 due review feedback. + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return [UIFont systemFontOfSize:([[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue])]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.h new file mode 100755 index 0000000..8bdec95 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Title line in selection question's choice cell. + */ +ORK_CLASS_AVAILABLE +@interface ORKSelectionTitleLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.m new file mode 100755 index 0000000..e489994 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSelectionTitleLabel.m @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSelectionTitleLabel.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSelectionTitleLabel + ++ (UIFont *)defaultFont { + return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.h new file mode 100755 index 0000000..c754fdf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKSeparatorView : UIView + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.m new file mode 100755 index 0000000..def7d78 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSeparatorView.m @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Shazino SAS. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSeparatorView.h" + + +static const CGFloat ORKLineWidth = 2.0f; +static const CGFloat ORKLengths[2] = {4.0f, 4.0f}; + + +@implementation ORKSeparatorView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.opaque = NO; + } + return self; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSaveGState(context); + + UIBezierPath *path = [UIBezierPath bezierPath]; + [path moveToPoint:CGPointMake(ORKLineWidth / 2, 0.0f)]; + [path addLineToPoint:CGPointMake(ORKLineWidth / 2, CGRectGetHeight(self.bounds))]; + path.lineWidth = ORKLineWidth; + [path setLineDash:ORKLengths count:2 phase:0.0f]; + [self.tintColor setStroke]; + [path stroke]; + + CGContextRestoreGState(context); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.h new file mode 100755 index 0000000..bb2d152 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKSignatureResult` class represents the result of a signature step (`ORKSignatureStep`). + + A signature result is produced by the task view controller when it presents a signature step. + + */ +ORK_CLASS_AVAILABLE +@interface ORKSignatureResult : ORKResult + +/** + The signature image generated by this step. + */ +@property (nonatomic, nullable) UIImage *signatureImage; + +/** + The bezier path components used to create the signature image. + */ +@property (nonatomic, copy, nullable) NSArray *signaturePath; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.m new file mode 100755 index 0000000..4fa26c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult.m @@ -0,0 +1,89 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSignatureResult_Private.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKSignatureResult + +- (instancetype)initWithSignatureImage:(UIImage *)signatureImage + signaturePath:(NSArray *)signaturePath { + self = [super init]; + if (self) { + _signatureImage = [signatureImage copy]; + _signaturePath = ORKArrayCopyObjects(signaturePath); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_IMAGE(aCoder, signatureImage); + ORK_ENCODE_OBJ(aCoder, signaturePath); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_IMAGE(aDecoder, signatureImage); + ORK_DECODE_OBJ_ARRAY(aDecoder, signaturePath, UIBezierPath); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return super.hash ^ self.signatureImage.hash ^ self.signaturePath.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.signatureImage, castObject.signatureImage) && + ORKEqualObjects(self.signaturePath, castObject.signaturePath)); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKSignatureResult *result = [super copyWithZone:zone]; + result->_signatureImage = [_signatureImage copy]; + result->_signaturePath = ORKArrayCopyObjects(_signaturePath); + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult_Private.h new file mode 100755 index 0000000..46294ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureResult_Private.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSignatureResult () + +- (instancetype)initWithSignatureImage:(UIImage *)signatureImage + signaturePath:(NSArray *)signaturePath; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.h new file mode 100755 index 0000000..37c95d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKSignatureStep` class is used to represent collecting a signature. + Typically, the consent signature is collected as a part of the consent review process. + + However, since in some cases the signature is collected after displaying custom + consent review steps, it is exposed to allow showing this as it's own step. + + To use a consent signature step, configure it and include it in a task. Then + present the task in a task view controller. + + The result of this step is an `ORKSignatureResult` which will include both the `UIImage` and + the path used to draw the image. + */ +ORK_CLASS_AVAILABLE +@interface ORKSignatureStep : ORKStep + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.m new file mode 100755 index 0000000..9085750 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStep.m @@ -0,0 +1,60 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSignatureStep.h" + +#import "ORKSignatureStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKSignatureStep + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + // Set default values for the title and text + self.title = ORKLocalizedString(@"CONSENT_SIGNATURE_TITLE", nil); + self.text = ORKLocalizedString(@"CONSENT_SIGNATURE_INSTRUCTION", nil); + } + return self; +} + ++ (Class)stepViewControllerClass { + return [ORKSignatureStepViewController class]; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.h new file mode 100755 index 0000000..2371db5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKSignatureStepViewController` class is a step view controller subclass + used to manage a signature step (`ORKSignatureStep`). + + You should not need to instantiate a signature step view controller directly. Instead, include + a signature step in a task, and present a task view controller for that stask. + */ +ORK_CLASS_AVAILABLE +@interface ORKSignatureStepViewController : ORKStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.m new file mode 100755 index 0000000..6b44fe2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureStepViewController.m @@ -0,0 +1,368 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSignatureStepViewController.h" + +#import "ORKSignatureView.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKStepContainerView_Private.h" +#import "ORKStepView_Private.h" + +#import "ORKResult_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKSignatureResult_Private.h" +#import "ORKStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKSignatureWrapperView : UIView + +@property (nonatomic, strong) ORKSignatureView *signatureView; + +@property (nonatomic, strong) ORKTextButton *clearButton; + +@property (nonatomic, assign) BOOL clearButtonEnabled; + +@end + + +@implementation ORKSignatureWrapperView + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self setNeedsLayout]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + { + _clearButton = [ORKTextButton new]; + _clearButton.contentEdgeInsets = (UIEdgeInsets){12,10,8,10}; // insets adjusted to get correct vertical height from bottom of screen when aligned to margin + _clearButton.exclusiveTouch = YES; + [_clearButton setTitle:ORKLocalizedString(@"BUTTON_CLEAR", nil) forState:UIControlStateNormal]; + _clearButton.translatesAutoresizingMaskIntoConstraints = NO; + _clearButton.alpha = 0; + [self addSubview:_clearButton]; + } + + { + _signatureView = [ORKSignatureView new]; + [_signatureView setClipsToBounds:YES]; + + _signatureView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_signatureView]; + } + + [self setUpConstraints]; + } + return self; +} + +- (void)updateLayoutMargins { + CGFloat margin = ORKStandardHorizontalMarginForView(self); + self.layoutMargins = (UIEdgeInsets){.left = margin, .right = margin }; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self updateLayoutMargins]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self updateLayoutMargins]; +} + +- (void)setClearButtonEnabled:(BOOL)clearButtonEnabled { + _clearButtonEnabled = clearButtonEnabled; + + if (clearButtonEnabled) { + NSTimeInterval duration = (UIAccessibilityIsVoiceOverRunning() ? 0 : 0.2); + [UIView animateWithDuration:duration delay:0 options:(UIViewAnimationOptions)UIViewAnimationOptionBeginFromCurrentState animations:^{ + _clearButton.alpha = 1; + } completion:^(BOOL finished) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil); + }]; + } else { + _clearButton.alpha = 0; + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, _signatureView); + } +} + +- (void)setUpConstraints { + // Static constraints + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_clearButton, _signatureView); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_signatureView]-(>=0)-[_clearButton]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_signatureView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[_clearButton]-(>=0)-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_signatureView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_clearButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_clearButton + attribute:NSLayoutAttributeBaseline + relatedBy:NSLayoutRelationEqual + toItem:_signatureView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:30.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end + + +@interface ORKConsentSigningView : ORKStepContainerView + +@property (nonatomic, strong) ORKSignatureWrapperView *wrapperView; + +@end + + +@implementation ORKConsentSigningView + +- (instancetype)init +{ + self = [super init]; + if (self) { + [self setupWrapperView]; + } + return self; +} + +- (void)setupWrapperView { + _wrapperView = [ORKSignatureWrapperView new]; + _wrapperView.translatesAutoresizingMaskIntoConstraints = NO; + self.customContentView = _wrapperView; +} + +@end + + +@interface ORKSignatureStepViewController () + +@property (nonatomic, strong, readonly, nullable) ORKSignatureView *signatureView; +@property (nonatomic, strong) ORKConsentSigningView *signingView; +@property (nonatomic, strong) NSArray *originalPath; + +@end + + +@implementation ORKSignatureStepViewController { + NSArray *_constraints; +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + self = [super initWithStep:step result:result]; + if (self && step) { + if ([result isKindOfClass:[ORKStepResult class]]) { + [[(ORKStepResult *)result results] enumerateObjectsUsingBlock:^(ORKResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[ORKSignatureResult class]]) { + _originalPath = [(ORKSignatureResult*)obj signaturePath]; + *stop = YES; + } + }]; + + } + } + return self; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // set the original path and update state + self.signatureView.signaturePath = self.originalPath; + [self updateButtonStates]; +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + + if (self.signatureView.signatureExists) { + ORKSignatureResult *sigResult = [[ORKSignatureResult alloc] initWithSignatureImage:self.signatureView.signatureImage + signaturePath:self.signatureView.signaturePath]; + parentResult.results = @[sigResult]; + } + + return parentResult; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; + [self updateButtonStates]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _navigationFooterView.skipButtonItem = skipButtonItem; + [self updateButtonStates]; +} + +- (void)updateButtonStates { + BOOL hasSigned = self.signatureView.signatureExists; + _navigationFooterView.continueEnabled = hasSigned; + _navigationFooterView.optional = self.step.optional; + [_signingView.wrapperView setClearButtonEnabled:hasSigned]; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_signingView removeFromSuperview]; + _signingView.wrapperView.signatureView.delegate = nil; + + _signingView = [ORKConsentSigningView new]; + _signingView.wrapperView.signatureView.delegate = self; + _signingView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + _signingView.frame = self.view.bounds; + _signingView.stepTitle = self.step.title; + _signingView.stepText = self.step.text; + _signingView.stepDetailText = self.step.detailText; + _signingView.stepHeaderTextAlignment = self.step.headerTextAlignment; + _signingView.stepTopContentImage = self.step.image; + _signingView.stepTopContentImageContentMode = self.step.imageContentMode; + _signingView.bodyItems = self.step.bodyItems; + [self setupNavigationFooterView]; + + [self updateButtonStates]; + + [_signingView.wrapperView.clearButton addTarget:self action:@selector(clearAction:) forControlEvents:UIControlEventTouchUpInside]; + + [self.view addSubview:_signingView]; + [self setupConstraints]; +} + +- (void)setupNavigationFooterView { + if (!_navigationFooterView && _signingView) { + _navigationFooterView = _signingView.navigationFooterView; + } + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + + _navigationFooterView.optional = NO; + [_navigationFooterView updateContinueAndSkipEnabled]; +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _constraints = nil; + _signingView.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_signingView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_signingView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_signingView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_signingView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (ORKSignatureView *)signatureView { + return _signingView.wrapperView.signatureView; +} + +- (void)clearAction:(id)sender { + [_signingView.wrapperView.signatureView clear]; + [self updateButtonStates]; + [self notifyDelegateOnResultChange]; +} + +- (void)signatureViewDidEditImage:(ORKSignatureView *)signatureView { + [self updateButtonStates]; + [self notifyDelegateOnResultChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.h new file mode 100755 index 0000000..315bfba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.h @@ -0,0 +1,83 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sam Falconer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKSignatureView; + +@protocol ORKSignatureViewDelegate + +- (void)signatureViewDidEditImage:(ORKSignatureView *)signatureView; + +@optional +- (void)signatureViewDidEndEditingWithTimeInterval; + +@end + + +@interface ORKSignatureView : UIView + +- (instancetype)initWithoutDefaultWidth; + +@property (nonatomic, strong, nullable) UIColor *lineColor; +@property (nonatomic) CGFloat lineWidth; +@property (nonatomic) BOOL enabled; + +/** + lineWidthVariation defines the max amount by which the line + width can vary (default 3pts). + + The exact amount of the variation is determined by the amount + of force applied on 3D touch capable devices or by the speed + of the stroke if 3D touch is not available. + + If the user is signing with an Apple Pencil, its force will be used. + */ +@property (nonatomic) CGFloat lineWidthVariation; + +@property (nonatomic, weak, nullable) id delegate; +@property (nonatomic, strong, nullable) UIGestureRecognizer *signatureGestureRecognizer; +@property (nonatomic, copy, nullable) NSArray *signaturePath; + +- (UIImage *)signatureImage; + +@property (nonatomic, readonly) BOOL signatureExists; + +- (void)clear; +- (void)cancelAutoScrollTimer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.m new file mode 100755 index 0000000..5ae9fa6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSignatureView.m @@ -0,0 +1,578 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2016, Sam Falconer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSignatureView.h" + +#import "ORKSelectionTitleLabel.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +#import + + +@protocol ORKSignatureGestureRecognizerDelegate + +- (void)gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; +- (void)gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event; + +@optional +- (void)gestureTouchesHaveEndedWithTimeInterval; + +@end + + +@interface ORKSignatureGestureRecognizer : UIGestureRecognizer + +@property (nonatomic, weak) id eventDelegate; +@property (nonatomic, strong) NSTimer *endEditingTimer; + +- (void)cancelAutoScrollTimer; + +@end + + +static const CGFloat TopToSigningLineRatio = 0.7; +static const CGFloat TouchesEndedTimeInterval = 2.0; + +@implementation ORKSignatureGestureRecognizer + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + [self.endEditingTimer invalidate]; + + if (touches.count > 1 || self.numberOfTouches > 1) { + for (UITouch *touch in touches) { + [self ignoreTouch:touch forEvent:event]; + } + } else { + self.state = UIGestureRecognizerStateBegan; + [self.eventDelegate gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event]; + } +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + [self.endEditingTimer invalidate]; + [self.eventDelegate gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + self.state = UIGestureRecognizerStateEnded; + [self.eventDelegate gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event]; + + self.endEditingTimer = [NSTimer scheduledTimerWithTimeInterval:TouchesEndedTimeInterval target:self selector:@selector(timerDidEnd) userInfo:nil repeats:NO]; +} + +- (void)timerDidEnd { + [self.eventDelegate gestureTouchesHaveEndedWithTimeInterval]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { + (void)touches; (void)event; + self.state = UIGestureRecognizerStateFailed; +} + +- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + // Prioritize over scrollView's pan gesture recognizer and swipe gesture recognizer + if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] + || [otherGestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]]) { + return YES; + } + return NO; +} + +- (void)cancelAutoScrollTimer { + [self.endEditingTimer invalidate]; +} + +@end + + +static const CGFloat PointMinDistance = 5; +static const CGFloat PointMinDistanceSquared = PointMinDistance * PointMinDistance; +static const CGFloat DefaultLineWidth = 1; +static const CGFloat DefaultLineWidthVariation = 3; +static const CGFloat MaxPressureForStrokeVelocity = 9; +static const CGFloat LineWidthStepValue = 0.25f; + +@interface ORKSignatureView () { + CGPoint currentPoint; + CGPoint previousPoint1; + CGPoint previousPoint2; + // Pressure scale based on if using force or speed of stroke. + CGFloat minPressure; + CGFloat maxPressure; + // Time used only to calculate speed when force isn't available on the device. + NSTimeInterval previousTouchTime; +} + +@property (nonatomic, strong) UIBezierPath *currentPath; +@property (nonatomic, strong) NSMutableArray *pathArray; +@property (nonatomic, strong) NSArray *backgroundLines; +@property (nonatomic) BOOL setWidth; + +@end + + +@implementation ORKSignatureView { + NSLayoutConstraint *_heightConstraint; + NSLayoutConstraint *_widthConstraint; +} + ++ (void)initialize { + if (self == [ORKSignatureView class]) { + if ([[ORKSignatureView appearance] backgroundColor] == nil) { + [[ORKSignatureView appearance] setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } + } +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.setWidth = YES; + [self commonInit]; + } + return self; +} + +- (instancetype)initWithoutDefaultWidth { + self = [super init]; + if (self) { + self.setWidth = NO; + [self commonInit]; + } + return self; +} + +- (void)commonInit { + _lineWidth = DefaultLineWidth; + _lineWidthVariation = DefaultLineWidthVariation; + + if (@available(iOS 13.0, *)) { + self.layer.borderColor = [[UIColor separatorColor] CGColor]; + } else { + self.layer.borderColor = [[UIColor ork_midGrayTintColor] CGColor]; + } + self.layer.borderWidth = 1.0; + self.layer.cornerRadius = 10.0; + self.clipsToBounds = YES; + + [self makeSignatureGestureRecognizer]; + [self setUpConstraints]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + _heightConstraint.constant = ORKGetMetricForWindow(ORKScreenMetricSignatureViewHeight, window); + + if (self.setWidth) { + _widthConstraint.constant = ORKWidthForSignatureView(window); + } +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + _heightConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; // constant set in updateConstraintConstantsForWindow: + [constraints addObject:_heightConstraint]; + + if (self.setWidth) { + _widthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; // constant set in updateConstraintConstantsForWindow: + [constraints addObject:_widthConstraint]; + } + + [NSLayoutConstraint activateConstraints:constraints]; + [self updateConstraintConstantsForWindow:self.window]; +} + +- (void)updateConstraints { + [self updateConstraintConstantsForWindow:self.window]; + [super updateConstraints]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self setNeedsDisplay]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self setNeedsDisplay]; +} + +- (UIBezierPath *)pathWithRoundedStyle { + UIBezierPath *path = [UIBezierPath bezierPath]; + path.lineCapStyle = kCGLineCapRound; + path.lineWidth = self.lineWidth; + path.lineJoinStyle = kCGLineJoinRound; + + return path; +} + +- (void)makeSignatureGestureRecognizer { + if (nil == _signatureGestureRecognizer) { + _signatureGestureRecognizer = [ORKSignatureGestureRecognizer new]; + ((ORKSignatureGestureRecognizer *)_signatureGestureRecognizer).eventDelegate = self; + [self addGestureRecognizer:_signatureGestureRecognizer]; + } +} + +- (UIColor *)lineColor { + if (_lineColor == nil) { + if (@available(iOS 13.0, *)) { + _lineColor = [UIColor labelColor]; + } else { + _lineColor = ORKColor(ORKSignatureColorKey); + } + } + return _lineColor; +} + +- (NSMutableArray *)pathArray { + if (_pathArray == nil) { + _pathArray = [NSMutableArray new]; + } + return _pathArray; +} + +- (CGFloat)placeholderPoint { + CGFloat height = self.bounds.size.height; + CGFloat y1 = height * TopToSigningLineRatio; + UIFont *font = [ORKSelectionTitleLabel defaultFont]; + return y1 - 5 - font.pointSize + font.descender; +} + +- (NSArray *)backgroundLines { + if (_backgroundLines == nil) { + CGFloat width = self.bounds.size.width; + CGFloat height = self.bounds.size.height; + + UIBezierPath *path = [UIBezierPath bezierPath]; + { + CGFloat x1 = 0; + CGFloat x2 = width; + + CGFloat y1 = height * TopToSigningLineRatio; + CGFloat y2 = height * TopToSigningLineRatio; + + [path moveToPoint:CGPointMake(x1, y1)]; + [path addLineToPoint:CGPointMake(x2, y2)]; + } + + _backgroundLines = @[path]; + } + return _backgroundLines; +} + +#pragma mark Touch Event Handlers + +- (BOOL)isForceTouchAvailable { + static BOOL isAvailable; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + + isAvailable = NO; + if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && + self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) { + isAvailable = YES; + } + }); + + return isAvailable; +} + +- (BOOL)isTouchTypeStylus:(UITouch*)touch { + BOOL isStylus = NO; + + if ([touch respondsToSelector:@selector(type)] && touch.type == UITouchTypeStylus) { + isStylus = YES; + } + + return isStylus; +} + +- (void)gestureTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { + UITouch *touch = [touches anyObject]; + + self.currentPath = [self pathWithRoundedStyle]; + + // Trigger full redraw - whether there's a path has changed + [self setNeedsDisplay]; + + previousPoint1 = [touch previousLocationInView:self]; + previousPoint2 = [touch previousLocationInView:self]; + currentPoint = [touch locationInView:self]; + + if ([self isForceTouchAvailable] || [self isTouchTypeStylus:touch]) { + // This is a scale based on true force on the screen. + minPressure = 0.f; + maxPressure = [touch maximumPossibleForce] / 2.f; + } + else { + // This is a scale based on the speed of the stroke + // (scaled down logarithmically). + minPressure = 0.f; + maxPressure = MaxPressureForStrokeVelocity; + previousTouchTime = touch.timestamp; + } + + [self.currentPath moveToPoint:currentPoint]; + [self.currentPath addArcWithCenter:currentPoint radius:0.1 startAngle:0.0 endAngle:2.0 * M_PI clockwise:YES]; + [self gestureTouchesMoved:touches withEvent:event]; +} + +static CGPoint mmid_Point(CGPoint p1, CGPoint p2) { + return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5); +} + +- (void)gestureTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { + UITouch *touch = [touches anyObject]; + + CGPoint point = [touch locationInView:self]; + + //check if the point is farther than min dist from previous + CGFloat dx = point.x - currentPoint.x; + CGFloat dy = point.y - currentPoint.y; + + CGFloat distanceSquared = (dx * dx + dy * dy); + + if (distanceSquared < PointMinDistanceSquared) { + return; + } + + // Will be assigned a real value on all devices. + CGFloat pressure; + if ([self isForceTouchAvailable] || [self isTouchTypeStylus:touch]) { + // If the device supports Force Touch, or is using a stylus, use it. + pressure = [touch force]; + } else { + // If not, use a heuristic based on the speed of + // the stroke. Scale this speed logarithmically to + // require very slow touches to max out the line width. + + // This value can become negative because of how it is + // inverted. It will be clamped right below. + pressure = maxPressure - log((sqrt(distanceSquared) / + MAX(0.0001, event.timestamp - previousTouchTime))); + previousTouchTime = event.timestamp; + } + + // Clamp the pressure value to between the allowed min and max. + pressure = MAX(minPressure, pressure); + pressure = MIN(maxPressure, pressure); + + CGFloat previousLineWidth = self.currentPath.lineWidth; + CGFloat proposedLineWidth = ((pressure - minPressure) * + self.lineWidthVariation / + (maxPressure - minPressure)) + + self.lineWidth; + + // Only step the line width up and down by a set value. + // This prevents the line looking jagged, and adding excessive + // separate line segments. + if (ABS(previousLineWidth - proposedLineWidth) >= LineWidthStepValue) { + + CGFloat lineWidth = previousLineWidth; + + if (proposedLineWidth > previousLineWidth) { + lineWidth = previousLineWidth + LineWidthStepValue; + } + else if (proposedLineWidth < previousLineWidth) { + lineWidth = previousLineWidth - LineWidthStepValue; + } + + [self commitCurrentPath]; + + self.currentPath = [self pathWithRoundedStyle]; + self.currentPath.lineWidth = lineWidth; + + CGPoint previousMid2 = mmid_Point(currentPoint, previousPoint1); + [self.currentPath moveToPoint:previousMid2]; + } + + previousPoint2 = previousPoint1; + previousPoint1 = [touch previousLocationInView:self]; + currentPoint = [touch locationInView:self]; + + CGPoint mid1 = mmid_Point(previousPoint1, previousPoint2); + CGPoint mid2 = mmid_Point(currentPoint, previousPoint1); + + UIBezierPath *subPath = [UIBezierPath bezierPath]; + [subPath moveToPoint:mid1]; + [subPath addQuadCurveToPoint:mid2 controlPoint:previousPoint1]; + CGRect bounds = CGPathGetBoundingBox(subPath.CGPath); + + [self.currentPath addQuadCurveToPoint:mid2 controlPoint:previousPoint1]; + + CGRect drawBox = bounds; + drawBox.origin.x -= self.currentPath.lineWidth * 2.0; + drawBox.origin.y -= self.currentPath.lineWidth * 2.0; + drawBox.size.width += self.currentPath.lineWidth * 4.0; + drawBox.size.height += self.currentPath.lineWidth * 4.0; + + [self setNeedsDisplayInRect:drawBox]; +} + +- (void)gestureTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { + [self commitCurrentPath]; +} + +- (void)gestureTouchesHaveEndedWithTimeInterval { + if (self.delegate && [self.delegate respondsToSelector:@selector(signatureViewDidEndEditingWithTimeInterval)]) { + [self.delegate signatureViewDidEndEditingWithTimeInterval]; + } +} + +- (void)commitCurrentPath { + CGRect rect = self.currentPath.bounds; + if (CGSizeEqualToSize(rect.size, CGSizeZero)) { + return; + } + + [self.pathArray addObject:self.currentPath]; + + [self.delegate signatureViewDidEditImage:self]; +} + +- (void)drawRect:(CGRect)rect { + UIColor *fillColor; + if (@available(iOS 13.0, *)) { + fillColor = [UIColor systemBackgroundColor]; + } else { + fillColor = [UIColor whiteColor]; + } + + [fillColor setFill]; + CGContextFillRect(UIGraphicsGetCurrentContext(), rect); + + for (UIBezierPath *path in self.pathArray) { + [self.lineColor setStroke]; + [path stroke]; + } + + [self.lineColor setStroke]; + [self.currentPath stroke]; +} + +- (NSArray *)signaturePath { + return [self.pathArray copy]; +} + +- (void)setSignaturePath:(NSArray *)signaturePath { + if (signaturePath) { + _pathArray = [signaturePath mutableCopy]; + [self setNeedsDisplay]; + } +} + +- (UIImage *)signatureImage { + CGSize imageContextSize; + imageContextSize = (self.bounds.size.width == 0 || self.bounds.size.height == 0) ? CGSizeMake(200, 200) : + self.bounds.size; + UIGraphicsBeginImageContext(imageContextSize); + + for (UIBezierPath *path in self.pathArray) { + [[UIColor blackColor] setStroke]; + [path stroke]; + } + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (BOOL)signatureExists { + return self.pathArray.count > 0; +} + +- (void)clear { + if (self.pathArray.count > 0) { + if (self.currentPath != nil) { + self.currentPath = [self pathWithRoundedStyle]; + } + + [self.pathArray removeAllObjects]; + [self setNeedsDisplayInRect:self.bounds]; + } +} + +- (void)cancelAutoScrollTimer { + [(ORKSignatureGestureRecognizer *)_signatureGestureRecognizer cancelAutoScrollTimer]; +} + +- (void)setEnabled:(BOOL)enabled { + _enabled = enabled; + [self setUserInteractionEnabled:enabled]; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return YES; +} + +- (NSString *)accessibilityLabel { + return ORKLocalizedString(@"AX_SIGNVIEW_LABEL", @"comment"); +} + +- (NSString *)accessibilityValue { + return (self.signatureExists ? ORKLocalizedString(@"AX_SIGNVIEW_SIGNED", @"comment") : ORKLocalizedString(@"AX_SIGNVIEW_UNSIGNED", @"comment")); +} + +- (NSString *)accessibilityHint { + return ORKLocalizedString(@"AX_SIGNVIEW_HINT", @"comment"); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitAllowsDirectInteraction; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.h new file mode 100755 index 0000000..23f1c4b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.h @@ -0,0 +1,252 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/// Color used for toolbar +ORK_EXTERN NSString *const ORKToolBarTintColorKey; + +/// Color used for view's backgroud +ORK_EXTERN NSString *const ORKBackgroundColorKey; + +/// Color used for consent view's backgroud +ORK_EXTERN NSString *const ORKConsentBackgroundColorKey; + +/// Color used for signature +ORK_EXTERN NSString *const ORKSignatureColorKey; + +/// Color used for a light-colored tint +ORK_EXTERN NSString *const ORKLightTintColorKey; + +/// Color used for a dark-colored tint +ORK_EXTERN NSString *const ORKDarkTintColorKey; + +/// Color used for caption text +ORK_EXTERN NSString *const ORKCaptionTextColorKey; + +/// Color used for a "blue" highlight +ORK_EXTERN NSString *const ORKBlueHighlightColorKey; + +/// Default color used for legend, title and text on ORKPieChartView +ORK_EXTERN NSString *const ORKChartDefaultTextColorKey; + +/// Default color used for axes of ORKGraphChartView +ORK_EXTERN NSString *const ORKGraphAxisColorKey; + +/// Default color used for titles on axes of ORKGraphChartView +ORK_EXTERN NSString *const ORKGraphAxisTitleColorKey; + +/// Default color used for scrubber line of ORKGraphChartView +ORK_EXTERN NSString *const ORKGraphScrubberLineColorKey; + +/// Default color used for scrubber thumb of ORKGraphChartView +ORK_EXTERN NSString *const ORKGraphScrubberThumbColorKey; + +/// Default color used for reference line of ORKGraphChartView +ORK_EXTERN NSString *const ORKGraphReferenceLineColorKey; + +/// Default color used for auxiliary image tint of ORKInstructionStepView +ORK_EXTERN NSString *const ORKAuxiliaryImageTintColorKey; + +/// Default color used for navigation container view +ORK_EXTERN NSString *const ORKNavigationContainerColorKey; + +/// Color used for view's backgroud +ORK_EXTERN NSString *const ORKNavigationContainerShadowColorKey; + +/// Default color progress label +ORK_EXTERN NSString *const ORKProgressLabelColorKey; + +/// Default color used by iPadBackgroundView +ORK_EXTERN NSString *const ORKiPadBackgroundViewColorKey; + +/// Background color of TopContentImageView in ORKStepContainerView +ORK_EXTERN NSString *const ORKTopContentImageViewBackgroundColorKey; + +/// Font color for detail text in bullet item +ORK_EXTERN NSString *const ORKBulletItemTextColorKey; + +/// ORKStepContentView stepTopContentImage KVO keyPath image changed +ORK_EXTERN NSString *const ORKStepTopContentImageChangedKey; + +/// Name of notification that is triggered when the keyboard's done button is pressed +ORK_EXTERN NSString *const ORKDoneButtonPressedKey; + +/// Name of notification that is triggered when the keyboard's done button is pressed +ORK_EXTERN NSString *const ORKResetDoneButtonKey; + +/// Return the color for a specified ORK...ColorKey +UIColor *ORKColor(NSString *colorKey); + +/// Return minimum height for question step header view +ORK_EXTERN CGFloat ORKQuestionStepMinimumHeaderHeight; + +/// Default CGFloat used for rounded corner radii for card view +ORK_EXTERN CGFloat ORKCardDefaultCornerRadii; + +/// Default CGFloat used for border width for card view +ORK_EXTERN CGFloat ORKCardDefaultBorderWidth; + +/// Default font size for card view +ORK_EXTERN CGFloat ORKCardDefaultFontSize; + +/// Default Top and Bottom margin for card view +ORK_EXTERN CGFloat ORKSurveyItemMargin; + +/// Padding for Form and Question Step Table Containers +ORK_EXTERN CGFloat ORKSurveyTableContainerLeftRightPadding; + +/// Default corner radius for iPadBackgroundView; +ORK_EXTERN CGFloat ORKiPadBackgroundViewCornerRadius; + +/// Default Bottom margin for iPadBackgroundView; +ORK_EXTERN CGFloat ORKiPadBackgroundViewBottomPadding; + +/// Default Left Right margin for iPadBackgroundView; +ORK_EXTERN CGFloat ORKiPadBackgroundViewLeftRightPadding; + +/// Default body to body item padding; +ORK_EXTERN CGFloat ORKBodyToBodyPaddingStandard; + +/// Default body to body item padding; +ORK_EXTERN CGFloat ORKBodyToBodyParagraphPaddingStandard; + +/// Step Content Icon Image View Dimension +ORK_EXTERN CGFloat ORKStepContentIconImageViewDimension; + +/// Navigation Container Effect View Style +ORK_EXTERN CGFloat ORKEffectViewOpacityHidden; + +/// Navigation Container Effect View Style +ORK_EXTERN CGFloat ORKEffectViewOpacityVisible; + +/// Checkmark View dimension +ORK_EXTERN CGFloat CheckmarkViewDimension; + +/// Modify the color for a specified ORK...ColorKey. (for customization) +void ORKColorSetColorForKey(NSString *key, UIColor *color); + +@interface UIColor (ORKColor) + ++ (UIColor *)ork_midGrayTintColor; ++ (UIColor *)ork_redColor; ++ (UIColor *)ork_grayColor; ++ (UIColor *)ork_darkGrayColor; ++ (UIColor *)ork_borderGrayColor; + +@end + +extern const CGFloat ORKScreenMetricMaxDimension; + +typedef NS_ENUM(NSInteger, ORKScreenMetric) { + ORKScreenMetricTopToCaptionBaseline, + ORKScreenMetricFontSizeHeadline, + ORKScreenMetricMaxFontSizeHeadline, + ORKScreenMetricFontSizeSurveyHeadline, + ORKScreenMetricMaxFontSizeSurveyHeadline, + ORKScreenMetricFontSizeSubheadline, + ORKScreenMetricFontSizeFootnote, + ORKScreenMetricCaptionBaselineToFitnessTimerTop, + ORKScreenMetricCaptionBaselineToTappingLabelTop, + ORKScreenMetricCaptionBaselineToInstructionBaseline, + ORKScreenMetricInstructionBaselineToLearnMoreBaseline, + ORKScreenMetricLearnMoreBaselineToStepViewTop, + ORKScreenMetricLearnMoreBaselineToStepViewTopWithNoLearnMore, + ORKScreenMetricContinueButtonTopMargin, + ORKScreenMetricContinueButtonTopMarginForIntroStep, + ORKScreenMetricTopToIllustration, + ORKScreenMetricIllustrationToCaptionBaseline, + ORKScreenMetricIllustrationHeight, + ORKScreenMetricInstructionImageHeight, + ORKScreenMetricContinueButtonWidth, + ORKScreenMetricMinimumStepHeaderHeightForMemoryGame, + ORKScreenMetricMinimumGameViewHeightForMemoryGame, + ORKScreenMetricMinimumStepHeaderHeightForTowerOfHanoiPuzzle, + ORKScreenMetricTableCellDefaultHeight, + ORKScreenMetricTextFieldCellHeight, + ORKScreenMetricChoiceCellFirstBaselineOffsetFromTop, + ORKScreenMetricChoiceCellLastBaselineToBottom, + ORKScreenMetricChoiceCellLabelLastBaselineToLabelFirstBaseline, + ORKScreenMetricLearnMoreButtonSideMargin, + ORKScreenMetricHeadlineSideMargin, + ORKScreenMetricToolbarHeight, + ORKScreenMetricVerticalScaleHeight, + ORKScreenMetricSignatureViewHeight, + ORKScreenMetricPSATKeyboardViewWidth, + ORKScreenMetricPSATKeyboardViewHeight, + ORKScreenMetricLocationQuestionMapHeight, + ORKScreenMetricTopToIconImageViewTop, + ORKScreenMetricIconImageViewToCaptionBaseline, + ORKScreenMetricVerificationTextBaselineToResendButtonBaseline, + ORKScreenMetric_COUNT +}; + +typedef NS_ENUM(NSInteger, ORKScreenType) { + ORKScreenTypeiPhoneX, + ORKScreenTypeiPhoneXSMax, + ORKScreenTypeiPhone6Plus, + ORKScreenTypeiPhone6, + ORKScreenTypeiPhone5, + ORKScreenTypeiPad, + ORKScreenTypeiPad10_5, + ORKScreenTypeiPad12_9, + ORKScreenType_COUNT +}; + +ORKScreenType ORKGetVerticalScreenTypeForWindow(UIWindow * _Nullable window); +CGFloat ORKGetMetricForWindow(ORKScreenMetric metric, UIWindow * _Nullable window); + +CGFloat ORKStandardLeftMarginForTableViewCell(UIView *view); +CGFloat ORKStandardHorizontalMarginForView(UIView *view); +UIEdgeInsets ORKStandardLayoutMarginsForTableViewCell(UIView *view); +UIEdgeInsets ORKStandardFullScreenLayoutMarginsForView(UIView *view); +UIEdgeInsets ORKScrollIndicatorInsetsForScrollView(UIView *view); +CGFloat ORKWidthForSignatureView(UIWindow * _Nullable window); +BOOL ORKNeedWideScreenDesign(UIView *view); + +void ORKUpdateScrollViewBottomInset(UIScrollView *scrollView, CGFloat bottomInset); + +CGFloat ORKStepContainerLeftRightPaddingForWindow(UIWindow *window); +CGFloat ORKStepContainerExtendedLeftRightPaddingForWindow(UIWindow *window); +CGFloat ORKStepContainerTopPaddingForWindow(UIWindow *window); +CGFloat ORKStepContainerTopContentHeightForWindow(UIWindow *window); +CGFloat ORKStepContainerFirstItemTopPaddingForWindow(UIWindow *window); +CGFloat ORKStepContainerTitleToBodyTopPaddingForWindow(UIWindow *window); +CGFloat ORKStepContainerTitleToBulletTopPaddingForWindow(UIWindow *window); +CGFloat ORKCardLeftRightMarginForWindow(UIWindow *window); + +UIFontTextStyle ORKTitleLabelFontTextStyleForWindow(UIWindow *window); + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.m new file mode 100755 index 0000000..6e92d0f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSkin.m @@ -0,0 +1,582 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSkin.h" + +#import "ORKHelpers_Internal.h" + + +NSString *const ORKSignatureColorKey = @"ORKSignatureColorKey"; +NSString *const ORKBackgroundColorKey = @"ORKBackgroundColorKey"; +NSString *const ORKConsentBackgroundColorKey = @"ORKConsentBackgroundColorKey"; +NSString *const ORKToolBarTintColorKey = @"ORKToolBarTintColorKey"; +NSString *const ORKLightTintColorKey = @"ORKLightTintColorKey"; +NSString *const ORKDarkTintColorKey = @"ORKDarkTintColorKey"; +NSString *const ORKCaptionTextColorKey = @"ORKCaptionTextColorKey"; +NSString *const ORKBlueHighlightColorKey = @"ORKBlueHighlightColorKey"; +NSString *const ORKChartDefaultTextColorKey = @"ORKChartDefaultTextColorKey"; +NSString *const ORKGraphAxisColorKey = @"ORKGraphAxisColorKey"; +NSString *const ORKGraphAxisTitleColorKey = @"ORKGraphAxisTitleColorKey"; +NSString *const ORKGraphReferenceLineColorKey = @"ORKGraphReferenceLineColorKey"; +NSString *const ORKGraphScrubberLineColorKey = @"ORKGraphScrubberLineColorKey"; +NSString *const ORKGraphScrubberThumbColorKey = @"ORKGraphScrubberThumbColorKey"; +NSString *const ORKAuxiliaryImageTintColorKey = @"ORKAuxiliaryImageTintColorKey"; +NSString *const ORKNavigationContainerColorKey = @"ORKNavigationContainerColorKey"; +NSString *const ORKNavigationContainerShadowColorKey = @"ORKNavigationContainerShadowColorKey"; +NSString *const ORKProgressLabelColorKey = @"ORKProgressLabelColorKey"; +NSString *const ORKiPadBackgroundViewColorKey = @"ORKiPadBacgroundViewColorKey"; +NSString *const ORKTopContentImageViewBackgroundColorKey = @"ORKTopContentImageViewBackgroundColorKey"; +NSString *const ORKBulletItemTextColorKey = @"ORKBulletItemTextColorKey"; +NSString *const ORKStepTopContentImageChangedKey = @"ORKStepTopContentImageChanged"; +NSString *const ORKDoneButtonPressedKey = @"ORKDoneButtonPressed"; +NSString *const ORKResetDoneButtonKey = @"ORKResetDoneButton"; +CGFloat ORKQuestionStepMinimumHeaderHeight = 29.75; +CGFloat ORKCardDefaultCornerRadii = 10.0; +CGFloat ORKCardDefaultBorderWidth = 0.0; +CGFloat ORKCardDefaultFontSize = 25.0; +CGFloat ORKSurveyItemMargin = 16.0; +CGFloat ORKSurveyTableContainerLeftRightPadding = 20.0; +CGFloat ORKiPadBackgroundViewCornerRadius = 20.0; +CGFloat ORKiPadBackgroundViewBottomPadding = 50.0; +CGFloat ORKiPadBackgroundViewLeftRightPadding = 115.0; + +CGFloat ORKStepContainerLeftRightMarginForXSMax = 20.0; +CGFloat ORKStepContainerLeftRightMarginForXS = 16.0; +CGFloat ORKStepContainerLeftRightMarginFor7Plus = 20.0; +CGFloat ORKStepContainerLeftRightMarginFor7 = 16.0; +CGFloat ORKStepContainerLeftRightMarginForSE = 16.0; +CGFloat ORKStepContainerLeftRightMarginForDefault = 16.0; + +CGFloat ORKStepContainerExtendedLeftRightMarginForXSMax = 24.0; +CGFloat ORKStepContainerExtendedLeftRightMarginForXS = 24.0; +CGFloat ORKStepContainerExtendedLeftRightMarginFor7Plus = 24.0; +CGFloat ORKStepContainerExtendedLeftRightMarginFor7 = 24.0; +CGFloat ORKStepContainerExtendedLeftRightMarginForSE = 16.0; +CGFloat ORKStepContainerExtendedLeftRightMarginForDefault = 24.0; + +CGFloat ORKStepContainerTopMarginForXSMax = 44.0; +CGFloat ORKStepContainerTopMarginForXS = 44.0; +CGFloat ORKStepContainerTopMarginFor7Plus = 20.0; +CGFloat ORKStepContainerTopMarginFor7 = 20.0; +CGFloat ORKStepContainerTopMarginForSE = 20.0; +CGFloat ORKStepContainerTopMarginForDefault = 20.0; + +CGFloat ORKStepContainerTitleToBodyTopPaddingStandard = 15.0; +CGFloat ORKStepContainerTitleToBodyTopPaddingShort = 11.0; +CGFloat ORKBodyToBodyPaddingStandard = 12.0; +CGFloat ORKBodyToBodyParagraphPaddingStandard = 22.0; + +CGFloat ORKStepContainerTitleToBulletTopPaddingShort = 37.0; + +CGFloat ORKStepContainerTopContentHeightPercentage = 36.0; +CGFloat ORKStepContainerFirstItemTopPaddingPercentage = 9.0; + +CGFloat ORKStepContentIconImageViewDimension = 80.0; + +CGFloat ORKEffectViewOpacityHidden = 0.0; +CGFloat ORKEffectViewOpacityVisible = 1.0; + +CGFloat CheckmarkViewDimension = 25.0; + +@implementation UIColor (ORKColor) + +#define ORKCachedColorMethod(m, r, g, b, a) \ ++ (UIColor *)m { \ + static UIColor *c##m = nil; \ + static dispatch_once_t onceToken##m; \ + dispatch_once(&onceToken##m, ^{ \ + c##m = [[UIColor alloc] initWithRed:r green:g blue:b alpha:a]; \ + }); \ + return c##m; \ +} + +ORKCachedColorMethod(ork_midGrayTintColor, 0.0 / 255.0, 0.0 / 255.0, 25.0 / 255.0, 0.22) +ORKCachedColorMethod(ork_redColor, 255.0 / 255.0, 59.0 / 255.0, 48.0 / 255.0, 1.0) +ORKCachedColorMethod(ork_grayColor, 142.0 / 255.0, 142.0 / 255.0, 147.0 / 255.0, 1.0) +ORKCachedColorMethod(ork_darkGrayColor, 102.0 / 255.0, 102.0 / 255.0, 102.0 / 255.0, 1.0) +ORKCachedColorMethod(ork_borderGrayColor, 239.0 / 255.0, 239.0 / 255.0, 244.0 / 255.0, 1.0) + +#undef ORKCachedColorMethod + +@end + +static NSMutableDictionary *colors() { + static NSMutableDictionary *colors = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + UIColor *backgroundColor; + if (@available(iOS 13.0, *)) { + backgroundColor = [UIColor secondarySystemBackgroundColor]; + } else { + backgroundColor = [UIColor colorWithRed:239.0 / 255.0 green:239.0 / 255.0 blue:244.0 / 255.0 alpha:1.0]; + } + + colors = [@{ + ORKSignatureColorKey: ORKRGB(0x000000), + ORKBackgroundColorKey: backgroundColor, + ORKConsentBackgroundColorKey: ORKRGB(0xffffff), + ORKToolBarTintColorKey: ORKRGB(0xffffff), + ORKLightTintColorKey: ORKRGB(0xeeeeee), + ORKDarkTintColorKey: ORKRGB(0x888888), + ORKCaptionTextColorKey: ORKRGB(0xcccccc), + ORKBlueHighlightColorKey: [UIColor colorWithRed:0.0 green:122.0 / 255.0 blue:1.0 alpha:1.0], + ORKChartDefaultTextColorKey: [UIColor lightGrayColor], + ORKGraphAxisColorKey: [UIColor colorWithRed:217.0 / 255.0 green:217.0 / 255.0 blue:217.0 / 255.0 alpha:1.0], + ORKGraphAxisTitleColorKey: [UIColor colorWithRed:142.0 / 255.0 green:142.0 / 255.0 blue:147.0 / 255.0 alpha:1.0], + ORKGraphReferenceLineColorKey: [UIColor colorWithRed:225.0 / 255.0 green:225.0 / 255.0 blue:229.0 / 255.0 alpha:1.0], + ORKGraphScrubberLineColorKey: [UIColor grayColor], + ORKGraphScrubberThumbColorKey: [UIColor colorWithWhite:1.0 alpha:1.0], + ORKAuxiliaryImageTintColorKey: [UIColor colorWithRed:228.0 / 255.0 green:233.0 / 255.0 blue:235.0 / 255.0 alpha:1.0], + ORKNavigationContainerColorKey: [UIColor colorWithRed:249.0 / 255.0 green:249.0 / 255.0 blue:251.0 / 255.0 alpha:0.0], + ORKNavigationContainerShadowColorKey: [UIColor blackColor], + ORKProgressLabelColorKey: [UIColor colorWithRed:142.0/255.0 green:142.0/255.0 blue:142.0/255.0 alpha:1.0], + ORKiPadBackgroundViewColorKey: [UIColor colorWithRed:249.0 / 255.0 green:249.0 / 255.0 blue:251.0 / 255.0 alpha:1.0], + ORKTopContentImageViewBackgroundColorKey: (ORKRGB(0xD7D7D7)), + ORKBulletItemTextColorKey: [UIColor colorWithRed:0.56 green:0.56 blue:0.58 alpha:1.0] + } mutableCopy]; + }); + return colors; +} + +UIColor *ORKColor(NSString *colorKey) { + return colors()[colorKey]; +} + +void ORKColorSetColorForKey(NSString *key, UIColor *color) { + NSMutableDictionary *d = colors(); + d[key] = color; +} + +const CGSize ORKiPhone4ScreenSize = (CGSize){320, 480}; +const CGSize ORKiPhone5ScreenSize = (CGSize){320, 568}; +const CGSize ORKiPhone6ScreenSize = (CGSize){375, 667}; +const CGSize ORKiPhone6PlusScreenSize = (CGSize){414, 736}; +const CGSize ORKiPhoneXScreenSize = (CGSize){375, 812}; +const CGSize ORKiPhoneXSMaxScreenSize = (CGSize){414, 896}; +const CGSize ORKiPadScreenSize = (CGSize){768, 1024}; +const CGSize ORKiPad10_5ScreenSize = (CGSize){834, 1112}; +const CGSize ORKiPad12_9ScreenSize = (CGSize){1024, 1366}; + +static ORKScreenType ORKGetVerticalScreenTypeForBounds(CGRect bounds) { + ORKScreenType screenType = ORKScreenTypeiPhone6; + CGFloat maximumDimension = MAX(bounds.size.width, bounds.size.height); + if (maximumDimension < ORKiPhone5ScreenSize.height + 1) { + screenType = ORKScreenTypeiPhone5; + } else if (maximumDimension < ORKiPhone6ScreenSize.height + 1) { + screenType = ORKScreenTypeiPhone6; + } else if (maximumDimension < ORKiPhone6PlusScreenSize.height + 1) { + screenType = ORKScreenTypeiPhone6Plus; + } else if (maximumDimension < ORKiPhoneXScreenSize.height + 1) { + screenType = ORKScreenTypeiPhoneX; + } else if (maximumDimension < ORKiPhoneXSMaxScreenSize.height + 1) { + screenType = ORKScreenTypeiPhoneXSMax; + } else if (maximumDimension < ORKiPadScreenSize.height + 1) { + screenType = ORKScreenTypeiPad; + } else if (maximumDimension < ORKiPad10_5ScreenSize.height + 1) { + screenType = ORKScreenTypeiPad10_5; + } else { + screenType = ORKScreenTypeiPad12_9; + } + return screenType; +} + +static ORKScreenType ORKGetHorizontalScreenTypeForBounds(CGRect bounds) { + ORKScreenType screenType = ORKScreenTypeiPhone6; + CGFloat minimumDimension = MIN(bounds.size.width, bounds.size.height); + if (minimumDimension < ORKiPhone5ScreenSize.width + 1) { + screenType = ORKScreenTypeiPhone5; + } else if (minimumDimension < ORKiPhone6ScreenSize.width + 1) { + screenType = ORKScreenTypeiPhone6; + } else if (minimumDimension < ORKiPhoneXScreenSize.width + 1) { + screenType = ORKScreenTypeiPhoneX; + } else if (minimumDimension < ORKiPhoneXSMaxScreenSize.width + 1) { + screenType = ORKScreenTypeiPhoneXSMax; + } else if (minimumDimension < ORKiPhone6PlusScreenSize.width + 1) { + screenType = ORKScreenTypeiPhone6Plus; + } else if (minimumDimension < ORKiPadScreenSize.width + 1) { + screenType = ORKScreenTypeiPad; + } else if (minimumDimension < ORKiPad10_5ScreenSize.width + 1) { + screenType = ORKScreenTypeiPad10_5; + } else { + screenType = ORKScreenTypeiPad12_9; + } + return screenType; +} + +static UIWindow *ORKDefaultWindowIfWindowIsNil(UIWindow *window) { + if (!window) { + // Use this method instead of UIApplication's keyWindow or UIApplication's delegate's window + // because we may need the window before the keyWindow is set (e.g., if a view controller + // loads programmatically on the app delegate to be assigned as the root view controller) + window = [UIApplication sharedApplication].windows.firstObject; + } + return window; +} + +ORKScreenType ORKGetVerticalScreenTypeForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); + return ORKGetVerticalScreenTypeForBounds(window.bounds); +} + +static ORKScreenType ORKGetHorizontalScreenTypeForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); + return ORKGetHorizontalScreenTypeForBounds(window.bounds); +} + +const CGFloat ORKScreenMetricMaxDimension = 10000.0; + +static CGFloat ORKGetMetricForScreenType(ORKScreenMetric metric, ORKScreenType screenType) { + static const CGFloat metrics[ORKScreenMetric_COUNT][ORKScreenType_COUNT] = { + // iPhoneX, iPhoneXSMAX, iPhone 6+, iPhone 6, iPhone 5, iPad, iPad 10.5, iPad 12.9 + { 128, 128, 128, 128, 100, 218, 218, 218}, // ORKScreenMetricTopToCaptionBaseline + { 35, 35, 35, 35, 32, 35, 35, 35}, // ORKScreenMetricFontSizeHeadline + { 38, 38, 38, 38, 32, 38, 38, 38}, // ORKScreenMetricMaxFontSizeHeadline + { 30, 30, 30, 30, 30, 30, 30, 30}, // ORKScreenMetricFontSizeSurveyHeadline + { 32, 32, 32, 32, 32, 32, 32, 32}, // ORKScreenMetricMaxFontSizeSurveyHeadline + { 17, 17, 17, 17, 17, 17, 17, 17}, // ORKScreenMetricFontSizeSubheadline + { 12, 12, 12, 12, 12, 12, 12, 12}, // ORKScreenMetricFontSizeFootnote + { 62, 62, 62, 62, 51, 62, 62, 62}, // ORKScreenMetricCaptionBaselineToFitnessTimerTop + { 62, 62, 62, 62, 43, 62, 62, 62}, // ORKScreenMetricCaptionBaselineToTappingLabelTop + { 36, 36, 36, 36, 32, 36, 36, 36}, // ORKScreenMetricCaptionBaselineToInstructionBaseline + { 30, 30, 30, 30, 28, 30, 30, 30}, // ORKScreenMetricInstructionBaselineToLearnMoreBaseline + { 44, 44, 44, 44, 20, 44, 44, 44}, // ORKScreenMetricLearnMoreBaselineToStepViewTop + { 40, 40, 40, 40, 30, 40, 40, 40}, // ORKScreenMetricLearnMoreBaselineToStepViewTopWithNoLearnMore + { 36, 36, 36, 36, 20, 36, 36, 36}, // ORKScreenMetricContinueButtonTopMargin + { 40, 40, 40, 40, 20, 40, 40, 40}, // ORKScreenMetricContinueButtonTopMarginForIntroStep + { 0, 0, 0, 0, 0, 80, 170, 170}, // ORKScreenMetricTopToIllustration + { 44, 44, 44, 40, 40, 44, 44, 44}, // ORKScreenMetricIllustrationToCaptionBaseline + { 198, 198, 198, 194, 152, 297, 297, 297}, // ORKScreenMetricIllustrationHeight + { 300, 300, 300, 176, 152, 300, 300, 300}, // ORKScreenMetricInstructionImageHeight + { 150, 150, 150, 146, 146, 150, 150, 150}, // ORKScreenMetricContinueButtonWidth + { 162, 162, 162, 120, 116, 240, 240, 240}, // ORKScreenMetricMinimumStepHeaderHeightForMemoryGame + { 200, 250, 200, 180, 150, 250, 250, 250}, // ORKScreenMetricMinimumGameViewHeightForMemoryGame + { 162, 162, 162, 120, 116, 240, 240, 240}, // ORKScreenMetricMinimumStepHeaderHeightForTowerOfHanoiPuzzle + { 60, 60, 60, 60, 44, 60, 60, 60}, // ORKScreenMetricTableCellDefaultHeight + { 55, 55, 55, 55, 44, 55, 55, 55}, // ORKScreenMetricTextFieldCellHeight + { 36, 36, 36, 36, 26, 36, 36, 36}, // ORKScreenMetricChoiceCellFirstBaselineOffsetFromTop, + { 24, 24, 24, 24, 18, 24, 24, 24}, // ORKScreenMetricChoiceCellLastBaselineToBottom, + { 24, 24, 24, 24, 24, 24, 24, 24}, // ORKScreenMetricChoiceCellLabelLastBaselineToLabelFirstBaseline, + { 30, 30, 30, 30, 20, 30, 30, 30}, // ORKScreenMetricLearnMoreButtonSideMargin + { 10, 10, 10, 10, 0, 10, 10, 10}, // ORKScreenMetricHeadlineSideMargin + { 44, 44, 44, 44, 44, 44, 44, 44}, // ORKScreenMetricToolbarHeight + { 274, 322, 274, 217, 217, 446, 446, 446}, // ORKScreenMetricVerticalScaleHeight + { 200, 200, 200, 200, 198, 256, 256, 256}, // ORKScreenMetricSignatureViewHeight + { 324, 384, 324, 304, 304, 384, 384, 384}, // ORKScreenMetricPSATKeyboardViewWidth + { 197, 197, 167, 157, 157, 197, 197, 197}, // ORKScreenMetricPSATKeyboardViewHeight + { 238, 238, 238, 150, 90, 238, 238, 238}, // ORKScreenMetricLocationQuestionMapHeight + { 40, 40, 40, 20, 14, 40, 40, 40}, // ORKScreenMetricTopToIconImageViewTop + { 44, 44, 44, 40, 40, 80, 80, 80}, // ORKScreenMetricIconImageViewToCaptionBaseline + { 30, 30, 30, 26, 22, 30, 30, 30}, // ORKScreenMetricVerificationTextBaselineToResendButtonBaseline + }; + return metrics[metric][screenType]; +} + +CGFloat ORKGetMetricForWindow(ORKScreenMetric metric, UIWindow *window) { + CGFloat metricValue = 0; + switch (metric) { + case ORKScreenMetricContinueButtonWidth: + case ORKScreenMetricHeadlineSideMargin: + case ORKScreenMetricLearnMoreButtonSideMargin: + metricValue = ORKGetMetricForScreenType(metric, ORKGetHorizontalScreenTypeForWindow(window)); + break; + + default: + metricValue = ORKGetMetricForScreenType(metric, ORKGetVerticalScreenTypeForWindow(window)); + break; + } + + return metricValue; +} + +const CGFloat ORKLayoutMarginWidthRegularBezel = 15.0; +const CGFloat ORKLayoutMarginWidthThinBezelRegular = 20.0; +const CGFloat ORKLayoutMarginWidthiPad = 0.0; + +static CGFloat ORKStandardLeftTableViewCellMarginForWindow(UIWindow *window) { + CGFloat margin = 0; + switch (ORKGetHorizontalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhone5: + case ORKScreenTypeiPhone6: + margin = ORKLayoutMarginWidthRegularBezel; + break; + case ORKScreenTypeiPhone6Plus: + case ORKScreenTypeiPad: + case ORKScreenTypeiPad10_5: + case ORKScreenTypeiPad12_9: + default: + margin = ORKLayoutMarginWidthThinBezelRegular; + break; + } + return margin; +} + +CGFloat ORKStandardLeftMarginForTableViewCell(UITableViewCell *cell) { + return ORKStandardLeftTableViewCellMarginForWindow(cell.window); +} + +static CGFloat ORKStandardHorizontalAdaptiveSizeMarginForiPadWidth(CGFloat screenSizeWidth, UIWindow *window) { + // Use adaptive side margin, if window is wider than iPhone6 Plus. + // Min Marign = ORKLayoutMarginWidthThinBezelRegular, Max Marign = ORKLayoutMarginWidthiPad or iPad12_9 + + CGFloat ratio = (window.bounds.size.width - ORKiPhone6PlusScreenSize.width) / (screenSizeWidth - ORKiPhone6PlusScreenSize.width); + ratio = MIN(1.0, ratio); + ratio = MAX(0.0, ratio); + return ORKLayoutMarginWidthThinBezelRegular + (ORKLayoutMarginWidthiPad - ORKLayoutMarginWidthThinBezelRegular)*ratio; +} + +static CGFloat ORKStandardHorizontalMarginForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); // need a proper window to use bounds + CGFloat margin = 0; + switch (ORKGetHorizontalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhone5: + case ORKScreenTypeiPhone6: + case ORKScreenTypeiPhoneX: + case ORKScreenTypeiPhoneXSMax: + case ORKScreenTypeiPhone6Plus: + default: + margin = ORKStandardLeftTableViewCellMarginForWindow(window); + break; + case ORKScreenTypeiPad:{ + margin = ORKStandardHorizontalAdaptiveSizeMarginForiPadWidth(ORKiPadScreenSize.width, window); + break; + } + case ORKScreenTypeiPad10_5:{ + margin = ORKStandardHorizontalAdaptiveSizeMarginForiPadWidth(ORKiPad10_5ScreenSize.width, window); + break; + } + case ORKScreenTypeiPad12_9:{ + margin = ORKStandardHorizontalAdaptiveSizeMarginForiPadWidth(ORKiPad12_9ScreenSize.width, window); + break; + } + } + return margin; +} + +CGFloat ORKStandardHorizontalMarginForView(UIView *view) { + return ORKStandardHorizontalMarginForWindow(view.window); +} + +UIEdgeInsets ORKStandardLayoutMarginsForTableViewCell(UITableViewCell *cell) { + const CGFloat StandardVerticalTableViewCellMargin = 8.0; + return (UIEdgeInsets){.left = ORKStandardLeftMarginForTableViewCell(cell), + .right = ORKStandardLeftMarginForTableViewCell(cell), + .bottom = StandardVerticalTableViewCellMargin, + .top = StandardVerticalTableViewCellMargin}; +} + +UIEdgeInsets ORKStandardFullScreenLayoutMarginsForView(UIView *view) { + UIEdgeInsets layoutMargins = UIEdgeInsetsZero; + ORKScreenType screenType = ORKGetHorizontalScreenTypeForWindow(view.window); + if (screenType == ORKScreenTypeiPad || screenType == ORKScreenTypeiPad10_5 || screenType == ORKScreenTypeiPad12_9) { + CGFloat margin = ORKStandardHorizontalMarginForView(view); + layoutMargins = (UIEdgeInsets){.left = margin, .right = margin }; + } + return layoutMargins; +} + +UIEdgeInsets ORKScrollIndicatorInsetsForScrollView(UIView *view) { + UIEdgeInsets scrollIndicatorInsets = UIEdgeInsetsZero; + ORKScreenType screenType = ORKGetHorizontalScreenTypeForWindow(view.window); + if (screenType == ORKScreenTypeiPad || screenType == ORKScreenTypeiPad10_5 || screenType == ORKScreenTypeiPad12_9) { + CGFloat margin = ORKStandardHorizontalMarginForView(view); + scrollIndicatorInsets = (UIEdgeInsets){.left = -margin, .right = -margin }; + } + return scrollIndicatorInsets; +} + +CGFloat ORKWidthForSignatureView(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); // need a proper window to use bounds + const CGSize windowSize = window.bounds.size; + const CGFloat windowPortraitWidth = MIN(windowSize.width, windowSize.height); + const CGFloat signatureViewWidth = windowPortraitWidth - (2 * ORKStandardHorizontalMarginForView(window) + 2 * ORKStandardLeftMarginForTableViewCell(window)); + if (ORKNeedWideScreenDesign(window)) { + return signatureViewWidth - 2 * ORKiPadBackgroundViewLeftRightPadding; + } + return signatureViewWidth; +} + +BOOL ORKNeedWideScreenDesign(UIView *view) { + return ORKStandardHorizontalMarginForView(view) == ORKLayoutMarginWidthiPad; +} + +void ORKUpdateScrollViewBottomInset(UIScrollView *scrollView, CGFloat bottomInset) { + UIEdgeInsets insets = scrollView.contentInset; + if (!ORKCGFloatNearlyEqualToFloat(insets.bottom, bottomInset)) { + CGPoint savedOffset = scrollView.contentOffset; + + insets.bottom = bottomInset; + scrollView.contentInset = insets; + + insets = scrollView.scrollIndicatorInsets; + insets.bottom = bottomInset; + scrollView.scrollIndicatorInsets = insets; + + scrollView.contentOffset = savedOffset; + } +} + +CGFloat ORKStepContainerLeftRightPaddingForWindow(UIWindow *window) { + CGFloat margin = 0; + switch (ORKGetHorizontalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhoneXSMax: + margin = ORKStepContainerLeftRightMarginForXSMax; + break; + case ORKScreenTypeiPhoneX: + margin = ORKStepContainerLeftRightMarginForXS; + break; + case ORKScreenTypeiPhone6Plus: + margin = ORKStepContainerLeftRightMarginFor7Plus; + break; + case ORKScreenTypeiPhone6: + margin = ORKStepContainerLeftRightMarginFor7; + break; + case ORKScreenTypeiPhone5: + margin = ORKStepContainerLeftRightMarginForSE; + break; + default: + margin = ORKStepContainerLeftRightMarginForDefault; + break; + } + return margin; +} + +CGFloat ORKStepContainerExtendedLeftRightPaddingForWindow(UIWindow *window) { + CGFloat margin = 0; + switch (ORKGetHorizontalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhoneXSMax: + margin = ORKStepContainerExtendedLeftRightMarginForXSMax; + break; + case ORKScreenTypeiPhoneX: + margin = ORKStepContainerExtendedLeftRightMarginForXS; + break; + case ORKScreenTypeiPhone6Plus: + margin = ORKStepContainerExtendedLeftRightMarginFor7Plus; + break; + case ORKScreenTypeiPhone6: + margin = ORKStepContainerExtendedLeftRightMarginFor7; + break; + case ORKScreenTypeiPhone5: + margin = ORKStepContainerExtendedLeftRightMarginForSE; + break; + default: + margin = ORKStepContainerExtendedLeftRightMarginForDefault; + break; + } + return margin; +} + +CGFloat ORKStepContainerTopPaddingForWindow(UIWindow *window) { + CGFloat margin = 0; + switch (ORKGetVerticalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhoneXSMax: + margin = ORKStepContainerTopMarginForXSMax; + break; + case ORKScreenTypeiPhoneX: + margin = ORKStepContainerTopMarginForXS; + break; + case ORKScreenTypeiPhone6Plus: + margin = ORKStepContainerTopMarginFor7Plus; + break; + case ORKScreenTypeiPhone6: + margin = ORKStepContainerTopMarginFor7; + break; + case ORKScreenTypeiPhone5: + margin = ORKStepContainerTopMarginForSE; + break; + default: + margin = ORKStepContainerTopMarginForDefault; + break; + } + return margin; +} + +CGFloat ORKStepContainerTopContentHeightForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); + const CGSize windowSize = window.bounds.size; + return ceil((ORKStepContainerTopContentHeightPercentage / 100.0) * windowSize.height); +} + +CGFloat ORKStepContainerFirstItemTopPaddingForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); + const CGSize windowSize = window.bounds.size; + return ceil((ORKStepContainerFirstItemTopPaddingPercentage / 100.0) * windowSize.height); +} + +//FIXME: Consolidate title/Icon to Body/Bullet methods into one. remove copy paste. + +CGFloat ORKStepContainerTitleToBodyTopPaddingForWindow(UIWindow *window) { + CGFloat padding = 0; + switch (ORKGetVerticalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhone5: + padding = ORKStepContainerTitleToBodyTopPaddingShort; + break; + case ORKScreenTypeiPhoneXSMax: + case ORKScreenTypeiPhoneX: + case ORKScreenTypeiPhone6Plus: + case ORKScreenTypeiPhone6: + default: + padding = ORKStepContainerTitleToBodyTopPaddingStandard; + break; + } + return padding; +} + +CGFloat ORKStepContainerTitleToBulletTopPaddingForWindow(UIWindow *window) { + CGFloat padding = 0; + switch (ORKGetVerticalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhone5: + padding = ORKStepContainerTitleToBulletTopPaddingShort; + break; + case ORKScreenTypeiPhoneXSMax: + case ORKScreenTypeiPhoneX: + case ORKScreenTypeiPhone6Plus: + case ORKScreenTypeiPhone6: + default: + // FIXME:- defaulting to short padding for larger devices as well + padding = ORKStepContainerTitleToBulletTopPaddingShort; + break; + } + return padding; +} + +CGFloat ORKCardLeftRightMarginForWindow(UIWindow *window) { + return ORKStepContainerLeftRightPaddingForWindow(window); +} + +UIFontTextStyle ORKTitleLabelFontTextStyleForWindow(UIWindow *window) { + window = ORKDefaultWindowIfWindowIsNil(window); + switch (ORKGetVerticalScreenTypeForWindow(window)) { + case ORKScreenTypeiPhone5: + return UIFontTextStyleTitle1; + default: + return UIFontTextStyleLargeTitle; + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.h new file mode 100755 index 0000000..2f3f8e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.h @@ -0,0 +1,309 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import UIKit; +@import HealthKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +ORK_EXTERN NSString *const ORKNullStepIdentifier ORK_AVAILABLE_DECL; + +@class ORKStepViewController; +@class ORKResult; +@class ORKBodyItem; + +@protocol ORKTask; + +/** + `ORKStep` is the base class for the steps that can compose a task for presentation + in an `ORKTaskViewController` object. Each `ORKStep` object represents one logical piece of data + entry or activity in a larger task. + + A step can be a question, an active test, or a simple instruction. An `ORKStep` + subclass is usually paired with an `ORKStepViewController` subclass that displays the step. + + To use a step, instantiate an `ORKStep` object and populate its properties. Add the step to a task, + such as an `ORKOrderedTask` object, and then present the task using a task view controller (an + `ORKTaskViewController` object). + + To implement a new type of step, subclass `ORKStep` and add your additional + properties. Separately, subclass `ORKStepViewController` and implement + your user interface. Note that if your step is timed or requires sensor data collection, + you should consider subclassing `ORKActiveStep` and `ORKActiveStepViewController` + instead. + */ + + +ORK_CLASS_AVAILABLE + +@interface ORKStep : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns a new step initialized with the specified identifier. + + This method is the primary designated initializer. + + @param identifier The unique identifier of the step. + + @return A new step. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new step initialized from data in the given unarchiver. + + @param aDecoder Coder from which to initialize the step. + + @return A new step. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Returns a copy of this step initialized with the specified identifier. + + @param identifier The unique identifier for the new step to be returned. + + @return A new step. + */ +- (instancetype)copyWithIdentifier:(NSString *)identifier; + +/** + A short string that uniquely identifies the step within the task. + + The identifier is reproduced in the results of a step. In fact, the only way to link a result + (an `ORKStepResult` object) to the step that generated it is to look at the value of + `identifier`. To accurately identify step results, you need to ensure that step identifiers + are unique within each task. + + In some cases, it can be useful to link the step identifier to a unique identifier in a + database; in other cases, it can make sense to make the identifier human + readable. + */ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + A Boolean value indicating whether a task can be restored to the step + during state restoration. (read-only) + + By default, the value of this property is `YES`, but subclasses of `ORKStep` might use `NO`. + + If a task cannot be restored to the step, the task is typically restored to the + last restorable step in the task, or to the first step, if + no restorable steps are available. + */ +@property (nonatomic, readonly, getter=isRestorable) BOOL restorable; + +/** + A Boolean value indicating whether the user can skip the step + without providing an answer. + + The default value of this property is `YES`. When the value is `NO`, the Skip button does not + appear on this step. + + This property may not be meaningful for all steps; for example, an active step + might not provide a way to skip, because it requires a timer to finish. + */ +@property (nonatomic, getter=isOptional) BOOL optional; + +/** + The primary text to display for the step in a localized string. + */ +@property (nonatomic, copy, nullable) NSString *title; + +/** + Additional text to display for the step in a localized string. + + The additional text is displayed in a smaller font below `title`. If you need to display a + long question, it can work well to keep the title short and put the additional content in + the `text` property. + */ + +@property (nonatomic, copy, nullable) NSString *text; + +/** + Additional detailed explanation for the instruction. + + The detail text is displayed below the content of the `text` property. + */ +@property (nonatomic, copy, nullable) NSString *detailText; + +/** + An 'NSTextAlignment' that controls the text alignment for step title, text and detailText. + */ +@property (nonatomic) NSTextAlignment headerTextAlignment; + +/** + Array of `ORKBodyItem` type items to display textual info. + */ +@property (nonatomic) NSArray *bodyItems; + +/** + An 'NSTextAlignment' that controls the text alignment for text bodyItems. + */ +@property (nonatomic) NSTextAlignment bodyItemTextAlignment; + +/** + A `Boolen` value indicating if the body items of the step should build in. + + Default value is NO resulting in all body items being displayed. Set to YES to + only show the first item and subsequent items will build in on continue. + */ +@property (nonatomic, assign) BOOL buildInBodyItems; + +/** + Additional text to display for the step in a localized string at the bottom of the view. + + The footnote is displayed in a smaller font below the continue button. It is intended to be used + in order to include disclaimer, copyright, etc. that is important to display in the step but + should not distract from the main purpose of the step. + */ +@property (nonatomic, copy, nullable) NSString *footnote; + +/** + An image that provides visual context for the instruction. + + The image is displayed with aspect fit. Depending on the device, the screen area + available for this image can vary. + */ +@property (nonatomic, copy, nullable) UIImage *image; + +/** + A `UIViewContentMode` used to position image inside a `UIImageView` used by the step. + + Depending on the subclass of the step, the `ORKStepView` uses specific 'UIImageView', and the + imageContentMode property sets the content mode of used image view. + */ +@property (nonatomic) UIViewContentMode imageContentMode; + +/** + An image that provides visual context for the instruction that will allow for showing + a two-part composite image where the `image` is tinted and the `auxiliaryImage` is + shown with light grey. + + The image is displayed with the same frame as the `image` so both the `auxiliaryImage` + and `image` should have transparently to allow for overlay. + */ +@property (nonatomic, copy, nullable) UIImage *auxiliaryImage; + +/** + Optional icon image to show above the title and text. + */ +@property (nonatomic, copy, nullable) UIImage *iconImage; + +/** +Whether to show progress for this step when it is presented. The default is YES. + */ +@property (nonatomic, assign) BOOL showsProgress; + +/** + Whether to use extended outer padding for views + */ +@property (nonatomic, assign) BOOL useExtendedPadding; + +/** + The task that contains the step. + + The value of `task` is usually set when a step is added to the `ORKOrderedTask` object. + Although it's a good idea to set this property when you implement a custom task, it's important + to note that the use of this property is a convenience, and should not be relied + upon within the ResearchKit framework. + */ +@property (nonatomic, weak, nullable) id task; + +/** + The set of access permissions required for the step. (read-only) + + The permission mask is used by the task view controller to determine the types of + access to request from users when they complete the initial instruction steps + in a task. If your step requires access to APIs that limit access, include + the permissions you require in this mask. + + By default, the property scans the recorders and collates the permissions + required by the recorders. Subclasses may override this implementation. + */ +@property (nonatomic, readonly) ORKPermissionMask requestedPermissions; + +/** + The set of HealthKit types the step requests for reading. (read-only) + + The task view controller uses this set of types when constructing a list of + all the HealthKit types required by all the steps in a task, so that it can + present the HealthKit access dialog just once during that task. + + By default, the property scans the recorders and collates the HealthKit + types the recorders require. Subclasses may override this implementation. + */ +@property (nonatomic, readonly, nullable) NSSet *requestedHealthKitTypesForReading; + +/** + Checks the parameters of the step and throws exceptions on invalid parameters. + + This method is called when there is a need to validate the step's parameters, which is typically + the case when adding a step to an `ORKStepViewController` object, and when presenting the + step view controller. + + Subclasses should override this method to provide validation of their additional + properties, and must call super. + */ +- (void)validateParameters; + +/** + Returns the class that the task view controller should instantiate to display + this step. + */ +- (Class)stepViewControllerClass; + +/** + Instantiates a step view controller for this class. + + This method is called when a step is about to be presented. The default implementation returns + a view controller that is appropriate to this step by allocating an instance of `ORKStepViewController` + using the `-stepViewControllerClass` method and initializing that instance by calling `initWithIdentifier:result:` + on the provided `ORKStepViewController` class instance. + + Override this method if you need to customize the behavior before presenting the step or if + the view controller is presented using a nib or storyboard. + + @param result The result associated with this step + + @return A newly initialized step view controller. + */ +- (ORKStepViewController *)instantiateStepViewControllerWithResult:(ORKResult *)result; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.m new file mode 100755 index 0000000..5672ca3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep.m @@ -0,0 +1,230 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStep.h" +#import "ORKStep_Private.h" + +#import "ORKStepViewController.h" + +#import "ORKOrderedTask.h" +#import "ORKStepViewController_Internal.h" +#import "ORKBodyItem.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKStep + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super init]; + if (self) { + ORKThrowInvalidArgumentExceptionIfNil(identifier); + _identifier = [identifier copy]; + self.showsProgress = YES; + } + return self; +} + ++ (Class)stepViewControllerClass { + return [ORKStepViewController class]; +} + +- (Class)stepViewControllerClass { + return [[self class] stepViewControllerClass]; +} + +- (ORKStepViewController *)instantiateStepViewControllerWithResult:(ORKResult *)result { + Class stepViewControllerClass = [self stepViewControllerClass]; + + ORKStepViewController *stepViewController = [[stepViewControllerClass alloc] initWithStep:self result:result]; + + // Set the restoration info using the given class + stepViewController.restorationIdentifier = self.identifier; + stepViewController.restorationClass = stepViewControllerClass; + + return stepViewController; +} + +- (instancetype)copyWithIdentifier:(NSString *)identifier { + ORKThrowInvalidArgumentExceptionIfNil(identifier) + ORKStep *step = [self copy]; + step->_identifier = [identifier copy]; + return step; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKStep *step = [[[self class] allocWithZone:zone] initWithIdentifier:[_identifier copy]]; + step.title = _title; + step.optional = _optional; + step.text = _text; + step.detailText = self.detailText; + step.headerTextAlignment = _headerTextAlignment; + step.bodyItemTextAlignment = _bodyItemTextAlignment; + step.buildInBodyItems = _buildInBodyItems; + step.footnote = self.footnote; + step.image = self.image; + step.imageContentMode = self.imageContentMode; + step.auxiliaryImage = self.auxiliaryImage; + step.iconImage = self.iconImage; + step.bodyItems = [_bodyItems copy]; + step.showsProgress = _showsProgress; + step.shouldTintImages = _shouldTintImages; + step.useSurveyMode = _useSurveyMode; + step.useExtendedPadding = _useExtendedPadding; + return step; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + // Ignore the task reference - it's not part of the content of the step. + __typeof(self) castObject = object; + return (ORKEqualObjects(self.identifier, castObject.identifier) + && ORKEqualObjects(self.title, castObject.title) + && ORKEqualObjects(self.text, castObject.text) + && ORKEqualObjects(self.detailText, castObject.detailText) + && (self.headerTextAlignment == castObject.headerTextAlignment) + && (self.bodyItemTextAlignment == castObject.bodyItemTextAlignment) + && (self.buildInBodyItems == castObject.buildInBodyItems) + && ORKEqualObjects(self.footnote, castObject.footnote) + && ORKEqualObjects(self.image, castObject.image) + && ORKEqualObjects(self.auxiliaryImage, castObject.auxiliaryImage) + && ORKEqualObjects(self.iconImage, castObject.iconImage) + && ORKEqualObjects(self.bodyItems, castObject.bodyItems) + && (self.imageContentMode == castObject.imageContentMode) + && (self.showsProgress == castObject.showsProgress) + && (self.optional == castObject.optional) + && (self.shouldTintImages == castObject.shouldTintImages) + && (self.useSurveyMode == castObject.useSurveyMode) + && (self.useExtendedPadding == castObject.useExtendedPadding)); +} + +- (NSUInteger)hash { + // Ignore the task reference - it's not part of the content of the step. + return _identifier.hash ^ _title.hash ^ _text.hash ^ self.detailText.hash ^_headerTextAlignment ^ _bodyItemTextAlignment ^ (_buildInBodyItems ? 0xf : 0x0) ^ _imageContentMode ^ self.footnote.hash ^ (_optional ? 0xf : 0x0) ^ _bodyItems.hash ^ (_showsProgress ? 0xf : 0x0) ^ (_useExtendedPadding ? 0xf : 0x0); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, title, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, text, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, detailText, NSString); + ORK_DECODE_ENUM(aDecoder, headerTextAlignment); + ORK_DECODE_ENUM(aDecoder, bodyItemTextAlignment); + ORK_DECODE_OBJ_CLASS(aDecoder, footnote, NSString); + ORK_DECODE_IMAGE(aDecoder, image); + ORK_DECODE_ENUM(aDecoder, imageContentMode); + ORK_DECODE_IMAGE(aDecoder, auxiliaryImage); + ORK_DECODE_IMAGE(aDecoder, iconImage); + ORK_DECODE_OBJ_ARRAY(aDecoder, bodyItems, ORKBodyItem); + ORK_DECODE_BOOL(aDecoder, showsProgress); + ORK_DECODE_BOOL(aDecoder, optional); + ORK_DECODE_OBJ_CLASS(aDecoder, task, ORKOrderedTask); + ORK_DECODE_BOOL(aDecoder, shouldTintImages); + ORK_DECODE_BOOL(aDecoder, useSurveyMode); + ORK_DECODE_BOOL(aDecoder, buildInBodyItems); + ORK_DECODE_BOOL(aDecoder, useExtendedPadding); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); + ORK_ENCODE_OBJ(aCoder, title); + ORK_ENCODE_OBJ(aCoder, text); + ORK_ENCODE_OBJ(aCoder, detailText); + ORK_ENCODE_ENUM(aCoder, headerTextAlignment); + ORK_ENCODE_ENUM(aCoder, bodyItemTextAlignment); + ORK_ENCODE_OBJ(aCoder, footnote); + ORK_ENCODE_IMAGE(aCoder, image); + ORK_ENCODE_ENUM(aCoder, imageContentMode); + ORK_ENCODE_IMAGE(aCoder, auxiliaryImage); + ORK_ENCODE_IMAGE(aCoder, iconImage); + ORK_ENCODE_OBJ(aCoder, bodyItems); + ORK_ENCODE_BOOL(aCoder, showsProgress); + ORK_ENCODE_BOOL(aCoder, optional); + ORK_ENCODE_BOOL(aCoder, shouldTintImages); + ORK_ENCODE_BOOL(aCoder, useSurveyMode); + ORK_ENCODE_BOOL(aCoder, buildInBodyItems); + ORK_ENCODE_BOOL(aCoder, useExtendedPadding); + if ([_task isKindOfClass:[ORKOrderedTask class]]) { + ORK_ENCODE_OBJ(aCoder, task); + } +} + +- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage { + _auxiliaryImage = auxiliaryImage; + if (auxiliaryImage) { + self.shouldTintImages = YES; + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"<%@ %@ %@>", super.description, self.identifier, self.title]; +} + +- (BOOL)allowsBackNavigation { + return YES; +} + +- (BOOL)isRestorable { + return YES; +} + +- (void)validateParameters { + +} + +- (ORKPermissionMask)requestedPermissions { + return ORKPermissionNone; +} + +- (NSSet *)requestedHealthKitTypesForReading { + return nil; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.h new file mode 100755 index 0000000..38281fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + +NS_ASSUME_NONNULL_BEGIN + + +@interface ORKStepContainerView : ORKStepView + +- (void)topContentImageShouldStickToTop; +- (void)removeCustomContentPadding; +- (void)updatePaddingConstraints; +- (void)placeNavigationContainerInsideScrollView; +- (void)scrollToBodyItem:(UIView *)bodyItem; +- (void)updateEffectViewStylingAndAnimate:(BOOL)animated checkCurrentValue:(BOOL)checkCurrentValue; +- (void)updateEffectViewStylingAndAnimate:(BOOL)animated checkCurrentValue:(BOOL)checkCurrentValue customView:(UIView *)customView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.m new file mode 100755 index 0000000..feaa465 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView.m @@ -0,0 +1,791 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKStepView_Private.h" +#import "ORKStepContainerView_Private.h" +#import "ORKTitleLabel.h" +#import "ORKBodyItem.h" +#import "ORKStepContentView_Private.h" +#import "ORKBodyContainerView.h" +#import "ORKSkin.h" +#import "ORKActiveStep.h" +#import "ORKNavigationContainerView_Internal.h" + +/** + +-----------------------------------------+ + | +-------------------------------------+ |<---_stepContainerView + | | _topContentImageView | | + | | | | + | | | | + | |_____________________________________| | + | +-------------------------------------+ | + | | +-------------------------------+ | | + | | | +_________________________+ | | |<-----_scrollView + | | | | | | | | + | | | | +-------+ | |<----------_scrollContainerView + | | | | | _icon | | | | | + | | | | | | | | | | + | | | | +-------+ |<-------------_stepContentView + | | | | | | | | + | | | | +---------------------+ | | | | + | | | | | _titleLabel | | | | | + | | | | |_____________________| | | | | + | | | | +---------------------+ | | | | + | | | | | _textLabel | | | | | + | | | | |_____________________| | | | | + | | | | +---------------------+ | | | | + | | | | | _detailTextLabel | | | | | + | | | | |_____________________| | | | | + | | | | | | | | + | | | | +---------------------+ | | | | + | | | | | |<-------------_bodyContainerView: UIstackView + | | | | | +-----------------+ | | | | | + | | | | | | | | | | | | + | | | | | |--Title | | | | | | + | | | | | |--Text |<-------------- BodyItemStyleText + | | | | | |--LearnMore | | | | | | + | | | | | |_________________| | | | | | + | | | | | | | | | | + | | | | | +---+-------------+ | | | | | + | | | | | | |--Title | | | | | | + | | | | | | o |--Text |<-------------- BodyItemStyleBullet + | | | | | | |--LearnMore | | | | | | + | | | | | |___|_____________| | | | | | + | | | | |_____________________| | | | | + | | | |_________________________| | | | + | | | | | | + | | | +-------------------------+ | | | + | | | | _CustomContentView | | | | + | | | |_________________________| | | | + | |__|_______________________________|__| | + |____|_______________________________|____| + | | + | | + | +-------------------------+ | + | | _navigationFooter | | + | |_________________________| | + vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + */ + +static NSString *scrollContentChangedNotification = @"scrollContentChanged"; + +@interface ScrollView : UIScrollView + +@end + +@implementation ScrollView + +- (void)setContentSize:(CGSize)contentSize { + [super setContentSize:contentSize]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:scrollContentChangedNotification object:nil]]; +} + +@end + +static const CGFloat ORKStepContainerTopCustomContentPaddingStandard = 20.0; +static const CGFloat ORKStepContainerNavigationFooterTopPaddingStandard = 10.0; +static const CGFloat ORKContentBottomPadding = 19.0; +static const CGFloat ORKBodyItemScrollPadding = 24.0; + +@implementation ORKStepContainerView { + CGFloat _leftRightPadding; + CGFloat _customContentLeftRightPadding; + ScrollView *_scrollView; + UIView *_scrollContainerView; + BOOL _topContentImageShouldScroll; + CGFloat _customContentTopPadding; + + UIImageView *_topContentImageView; + +// variable constraints: + NSLayoutConstraint *_scrollViewTopConstraint; + NSLayoutConstraint *_scrollViewBottomConstraint; + NSLayoutConstraint *_stepContentViewTopConstraint; + NSLayoutConstraint *_customContentViewTopConstraint; + + NSArray *_topContentImageViewConstraints; + + NSLayoutConstraint *_navigationContainerViewTopConstraint; + NSArray *_navigationContainerViewConstraints; + NSLayoutConstraint *_customContentWidthConstraint; + NSLayoutConstraint *_customContentHeightConstraint; + NSMutableArray *_updatedConstraints; + + NSLayoutConstraint *_scrollContentBottomConstraint; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _customContentLeftRightPadding = ORKStepContainerLeftRightPaddingForWindow(self.window); + _leftRightPadding = ORKStepContainerExtendedLeftRightPaddingForWindow(self.window); + self.isNavigationContainerScrollable = NO; + [self setupScrollView]; + [self setupScrollContainerView]; + [self addStepContentView]; + [self setupConstraints]; + [self setupUpdatedConstraints]; + [self placeNavigationContainerView]; + _topContentImageShouldScroll = YES; + + _customContentTopPadding = ORKStepContainerTopCustomContentPaddingStandard; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollContentChanged) name:scrollContentChangedNotification object:nil]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:scrollContentChangedNotification object:nil]; +} + +- (void)setStepTopContentImage:(UIImage *)stepTopContentImage { + + [super setStepTopContentImage:stepTopContentImage]; + if (_topContentImageShouldScroll) { + [self.stepContentView setStepTopContentImage:stepTopContentImage]; + } + else { + // 1.) nil Image; updateConstraints + if (!stepTopContentImage && _topContentImageView) { + [_topContentImageView removeFromSuperview]; + _topContentImageView = nil; + [self deactivateTopContentImageViewConstraints]; + [self updateScrollViewTopConstraint]; + [self setNeedsUpdateConstraints]; + } + + // 2.) First Image; updateConstraints + if (stepTopContentImage && !_topContentImageView) { + [self setupTopContentImageView]; + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + [self updateScrollViewTopConstraint]; + [self setNeedsUpdateConstraints]; + } + + // 3.) >= second Image; + if (stepTopContentImage && _topContentImageView) { + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + } + } +} + +- (void)setupScrollView { + if (!_scrollView) { + _scrollView = [[ScrollView alloc] init]; + } + _scrollView.showsVerticalScrollIndicator = self.showScrollIndicator; + _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + _scrollView.delegate = self; + [self addSubview:_scrollView]; +} + +- (void)setShowScrollIndicator:(BOOL)showScrollIndicator { + self.showScrollIndicator = showScrollIndicator; + _scrollView.showsVerticalScrollIndicator = showScrollIndicator; +} + +- (void)setupScrollContainerView { + if (!_scrollContainerView) { + _scrollContainerView = [UIView new]; + } + [_scrollView addSubview:_scrollContainerView]; +} + +- (void)setupUpdatedConstraints { + _updatedConstraints = [[NSMutableArray alloc] init]; +} + +- (void)setupTopContentImageView { + if (!_topContentImageView) { + _topContentImageView = [UIImageView new]; + } + _topContentImageView.contentMode = UIViewContentModeScaleAspectFit; + [_topContentImageView setBackgroundColor:ORKColor(ORKTopContentImageViewBackgroundColorKey)]; + [self addSubview:_topContentImageView]; + [self setTopContentImageViewConstraints]; +} + +- (void)setStepTopContentImageContentMode:(UIViewContentMode)stepTopContentImageContentMode { + [super setStepTopContentImageContentMode:stepTopContentImageContentMode]; + if (_topContentImageView) { + _topContentImageView.contentMode = stepTopContentImageContentMode; + } +} + +- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage { + [super setAuxiliaryImage:auxiliaryImage]; + if (self.stepTopContentImage) { + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + } +} + +- (void)addStepContentView { + [_scrollContainerView addSubview:self.stepContentView]; +} + +- (void)stepContentViewImageChanged:(NSNotification *)notification { + [super stepContentViewImageChanged:notification]; + [self updateStepContentViewTopConstraint]; + [self setNeedsUpdateConstraints]; +} + +- (void)setStepContentViewConstraints { + self.stepContentView.translatesAutoresizingMaskIntoConstraints = NO; + [self setStepContentViewTopConstraint]; + + [NSLayoutConstraint activateConstraints:@[ + _stepContentViewTopConstraint, + [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainerView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainerView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0] + ]]; +} + +- (void)setStepContentViewTopConstraint { + _stepContentViewTopConstraint = [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.stepContentView.topContentImageView.image ? _scrollContainerView : _scrollContainerView.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; +} + +- (void)updateStepContentViewTopConstraint { + if (_stepContentViewTopConstraint && _stepContentViewTopConstraint.isActive) { + [NSLayoutConstraint deactivateConstraints:@[_stepContentViewTopConstraint]]; + } + if ([_updatedConstraints containsObject:_stepContentViewTopConstraint]) { + [_updatedConstraints removeObject:_stepContentViewTopConstraint]; + } + [self setStepContentViewTopConstraint]; + if (_stepContentViewTopConstraint) { + [_updatedConstraints addObject:_stepContentViewTopConstraint]; + } +} + +- (void)setCustomContentView:(UIView *)customContentView { + _customContentView = customContentView; + [_scrollContainerView addSubview:_customContentView]; + [self setupCustomContentViewConstraints]; + [self updateNavigationContainerViewTopConstraint]; + [self setNeedsUpdateConstraints]; +} + +- (void)removeNavigationFooterView { + [self.navigationFooterView removeFromSuperview]; + if (_navigationContainerViewConstraints) { + [NSLayoutConstraint deactivateConstraints:_navigationContainerViewConstraints]; + for (NSLayoutConstraint *constraint in _navigationContainerViewConstraints) { + if ([_updatedConstraints containsObject:constraint]) { + [_updatedConstraints removeObject:constraint]; + } + } + _navigationContainerViewConstraints = nil; + } +} + +- (void)placeNavigationContainerView { + [self removeNavigationFooterView]; + + if (self.isNavigationContainerScrollable) { + [_scrollContainerView addSubview:self.navigationFooterView]; + } else { + [self addSubview:self.navigationFooterView]; + } + [self setupNavigationContainerViewConstraints]; +} + +- (void)placeNavigationContainerInsideScrollView { + self.isNavigationContainerScrollable = YES; + [self placeNavigationContainerView]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self updateScrollContentConstraints]; + [self updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO]; +} + +- (void)updateScrollContentConstraints { + if (_scrollContentBottomConstraint != nil) { + [NSLayoutConstraint deactivateConstraints:@[_scrollContentBottomConstraint]]; + } + + _scrollContentBottomConstraint = [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_scrollContainerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-(self.navigationFooterView.frame.size.height + ORKContentBottomPadding)]; + + [NSLayoutConstraint activateConstraints:@[_scrollContentBottomConstraint]]; +} + +- (void)setupNavigationContainerViewConstraints { + self.navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationContainerViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.isNavigationContainerScrollable ? _scrollContainerView : self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.isNavigationContainerScrollable ? _scrollContainerView : self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.isNavigationContainerScrollable ? _scrollContainerView : self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + [_updatedConstraints addObjectsFromArray:_navigationContainerViewConstraints]; + [self updateNavigationContainerViewTopConstraint]; + + if (!self.isNavigationContainerScrollable) { + [NSLayoutConstraint deactivateConstraints:@[_scrollViewBottomConstraint]]; + if ([_updatedConstraints containsObject:_scrollViewBottomConstraint]) { + [_updatedConstraints removeObject:_scrollViewBottomConstraint]; + } + + _scrollViewBottomConstraint = [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-ORKContentBottomPadding]; + [_updatedConstraints addObject:_scrollViewBottomConstraint]; + } + + [self setNeedsUpdateConstraints]; +} + +- (void)setupNavigationContainerViewTopConstraint { + if (self.navigationFooterView && self.isNavigationContainerScrollable) { + + id topItem; + NSLayoutAttribute topItemAttribute; + if (_customContentView) { + topItem = _customContentView; + topItemAttribute = NSLayoutAttributeBottom; + } + else if(self.stepContentView) { + topItem = self.stepContentView; + topItemAttribute = NSLayoutAttributeBottom; + } + else { + topItem = _scrollContainerView; + topItemAttribute = NSLayoutAttributeTop; + } + + _navigationContainerViewTopConstraint = [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:topItem + attribute:topItemAttribute + multiplier:1.0 + constant:ORKStepContainerNavigationFooterTopPaddingStandard]; + } +} + +- (void)updateNavigationContainerViewTopConstraint { + if (self.navigationFooterView && self.isNavigationContainerScrollable) { + if (_navigationContainerViewTopConstraint) { + [NSLayoutConstraint deactivateConstraints:@[_navigationContainerViewTopConstraint]]; + if ([_updatedConstraints containsObject:_navigationContainerViewTopConstraint]) { + [_updatedConstraints removeObject:_navigationContainerViewTopConstraint]; + } + } + [self setupNavigationContainerViewTopConstraint]; + [_updatedConstraints addObject:_navigationContainerViewTopConstraint]; + } +} + +- (void)setupCustomContentViewConstraints { + _customContentView.translatesAutoresizingMaskIntoConstraints = NO; + [self setCustomContentViewTopConstraint]; + [self setCustomContentWidthConstraint]; + [_updatedConstraints addObjectsFromArray:@[ + _customContentViewTopConstraint, + [NSLayoutConstraint constraintWithItem:_customContentView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainerView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + _customContentWidthConstraint + ]]; + [self updateCustomContentHeightConstraint]; + [self setNeedsUpdateConstraints]; + + +} + +- (void)setCustomContentFillsAvailableSpace:(BOOL)customContentFillsAvailableSpace { + _customContentFillsAvailableSpace = customContentFillsAvailableSpace; + [self updateCustomContentHeightConstraint]; +} + +- (void)setCustomContentHeightConstraint { + if (_customContentView) { + _customContentHeightConstraint = [NSLayoutConstraint constraintWithItem:_customContentView + attribute:NSLayoutAttributeBottom + relatedBy:_customContentFillsAvailableSpace ? NSLayoutRelationEqual : NSLayoutRelationLessThanOrEqual + toItem:self.isNavigationContainerScrollable ? self.navigationFooterView : _scrollContainerView + attribute:self.isNavigationContainerScrollable ? NSLayoutAttributeTop : NSLayoutAttributeBottom + multiplier:1.0 + constant:self.isNavigationContainerScrollable ? -ORKStepContainerNavigationFooterTopPaddingStandard : 0.0]; + } +} + +- (void)updateCustomContentHeightConstraint { + if (_customContentView) { + if (_customContentHeightConstraint && _customContentHeightConstraint.isActive) { + [NSLayoutConstraint deactivateConstraints:@[_customContentHeightConstraint]]; + } + if ([_updatedConstraints containsObject:_customContentHeightConstraint]) { + [_updatedConstraints removeObject:_customContentHeightConstraint]; + } + [self setCustomContentHeightConstraint]; + if (_customContentHeightConstraint) { + [_updatedConstraints addObject:_customContentHeightConstraint]; + } + } +} + +- (void)setCustomContentWidthConstraint { + if (_customContentView) { + _customContentWidthConstraint = [NSLayoutConstraint constraintWithItem:_customContentView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainerView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:-2*_customContentLeftRightPadding]; + } +} + +- (void)removeCustomContentPadding { + _customContentLeftRightPadding = 0.0; + if (_customContentWidthConstraint) { + _customContentWidthConstraint.constant = _customContentLeftRightPadding; + } +} + +- (void)setCustomContentViewTopConstraint { + id topItem; + NSLayoutAttribute attribute; + + if (self.stepContentView) { + topItem = self.stepContentView; + attribute = NSLayoutAttributeBottom; + } + else { + topItem = _scrollContainerView; + attribute = NSLayoutAttributeTop; + } + + _customContentViewTopConstraint = [NSLayoutConstraint constraintWithItem:_customContentView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:topItem + attribute:attribute + multiplier:1.0 + constant:_customContentTopPadding]; +} + +- (void)setCustomContentView:(UIView *)customContentView withTopPadding:(CGFloat)topPadding { + _customContentTopPadding = topPadding; + [self setCustomContentView:customContentView]; +} + +- (void)updateCustomContentViewTopConstraint { + if (_customContentView) { + if (_customContentViewTopConstraint && _customContentViewTopConstraint.isActive) { + [NSLayoutConstraint deactivateConstraints:@[_customContentViewTopConstraint]]; + } + if ([_updatedConstraints containsObject:_customContentViewTopConstraint]) { + [_updatedConstraints removeObject:_customContentViewTopConstraint]; + } + [self setCustomContentViewTopConstraint]; + if (_customContentViewTopConstraint) { + [_updatedConstraints addObject:_customContentViewTopConstraint]; + } + } +} + +- (NSArray *)scrollViewStaticConstraints { + _scrollViewBottomConstraint = [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + return @[ + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + _scrollViewBottomConstraint + ]; +} + +- (NSArray *)scrollContainerStaticConstraints { + return @[ + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollContainerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_scrollView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0] + ]; +} + +- (void)setScrollViewTopConstraint { + _scrollViewTopConstraint = [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_topContentImageView ? : self + attribute:_topContentImageView ? NSLayoutAttributeBottom : NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [_updatedConstraints addObject:_scrollViewTopConstraint]; +} + +- (void)updateScrollViewTopConstraint { + if (_scrollViewTopConstraint) { + [NSLayoutConstraint deactivateConstraints:@[_scrollViewTopConstraint]]; + } + if ([_updatedConstraints containsObject:_scrollViewTopConstraint]) { + [_updatedConstraints removeObject:_scrollViewTopConstraint]; + } + [self setScrollViewTopConstraint]; +} + +- (void)setTopContentImageViewConstraints { + _topContentImageView.translatesAutoresizingMaskIntoConstraints = NO; + _topContentImageViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKStepContainerTopContentHeightForWindow(self.window)] + ]; + [_updatedConstraints addObjectsFromArray:_topContentImageViewConstraints]; +} + +- (void)deactivateTopContentImageViewConstraints { + if (_topContentImageViewConstraints) { + [NSLayoutConstraint deactivateConstraints:_topContentImageViewConstraints]; + for (NSLayoutConstraint *constraint in _topContentImageViewConstraints) { + if ([_updatedConstraints containsObject:constraint]) { + [_updatedConstraints removeObject:constraint]; + } + } + } + _topContentImageViewConstraints = nil; +} + +- (void)setupConstraints { + _scrollView.translatesAutoresizingMaskIntoConstraints = NO; + _scrollContainerView.translatesAutoresizingMaskIntoConstraints = NO; + + [self setScrollViewTopConstraint]; + NSMutableArray *staticConstraints = [[NSMutableArray alloc] initWithArray:[self scrollViewStaticConstraints]]; + [staticConstraints addObject:_scrollViewTopConstraint]; + [staticConstraints addObjectsFromArray:[self scrollContainerStaticConstraints]]; + [NSLayoutConstraint activateConstraints:staticConstraints]; + [self setStepContentViewConstraints]; +} + +- (void)updateContainerConstraints { + [NSLayoutConstraint activateConstraints:_updatedConstraints]; + [_updatedConstraints removeAllObjects]; +} + +- (void)updateConstraints { + [self updateContainerConstraints]; + [super updateConstraints]; +} + +- (void)topContentImageShouldStickToTop { + if (self.stepTopContentImage) { + UIImage *stepTopContentImage = self.stepTopContentImage; + [self setStepTopContentImage:nil]; + _topContentImageShouldScroll = NO; + [self setStepTopContentImage:stepTopContentImage]; + } + _topContentImageShouldScroll = NO; +} + +- (void)updatePaddingConstraints { + [self.stepContentView setUseExtendedPadding:[self useExtendedPadding]]; + [self.navigationFooterView setUseExtendedPadding:[self useExtendedPadding]]; +} + +- (void)scrollToBodyItem:(UIView *)bodyItem { + CGPoint pointInScrollView = [bodyItem.superview convertPoint:bodyItem.frame.origin toView:_scrollView]; + CGFloat bottomOfView = pointInScrollView.y + bodyItem.frame.size.height; + CGFloat bottomOfScrollView = _scrollView.frame.size.height - [self navigationFooterView].frame.size.height; + + // TODO:- update ORKBodyItemScrollPadding depending on device size + if (bottomOfView > bottomOfScrollView) { + [_scrollView setContentOffset:CGPointMake(0, (bottomOfView - bottomOfScrollView) + ORKBodyItemScrollPadding) animated:YES]; + } +} + +- (void)updateEffectViewStylingAndAnimate:(BOOL)animated checkCurrentValue:(BOOL)checkCurrentValue { + CGFloat startOfFooter = self.navigationFooterView.frame.origin.y; + CGFloat contentPosition = (_scrollView.contentSize.height - _scrollView.contentOffset.y - self.navigationFooterView.frame.size.height) - ORKContentBottomPadding; + CGFloat newOpacity = (contentPosition < startOfFooter) ? ORKEffectViewOpacityHidden : ORKEffectViewOpacityVisible; + [self updateEffectStyleWithNewOpacity:newOpacity animated:animated checkCurrentValue:checkCurrentValue]; +} + +- (void)updateEffectViewStylingAndAnimate:(BOOL)animated checkCurrentValue:(BOOL)checkCurrentValue customView:(UIView *)customView { + CGFloat startOfFooter = self.navigationFooterView.frame.origin.y; + CGPoint newPoint = [customView convertPoint:customView.frame.origin toView:_scrollView]; + CGFloat endOfContent = newPoint.y + customView.frame.size.height; + CGFloat newOpacity = (endOfContent < startOfFooter) ? ORKEffectViewOpacityHidden : ORKEffectViewOpacityVisible; + [self updateEffectStyleWithNewOpacity:newOpacity animated:animated checkCurrentValue:checkCurrentValue]; +} + +- (void)updateEffectStyleWithNewOpacity:(CGFloat)newOpacity animated:(BOOL)animated checkCurrentValue:(BOOL)checkCurrentValue { + CGFloat currentOpacity = [self.navigationFooterView effectViewOpacity]; + if (!checkCurrentValue || (newOpacity != currentOpacity)) { + // Don't animate transition from hidden to visible as text appears behind during animation + if (currentOpacity == ORKEffectViewOpacityHidden) { animated = NO; } + [self.navigationFooterView setStylingOpactity:newOpacity animated:animated]; + } +} + +// MARK: ScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + [self updateEffectViewStylingAndAnimate:YES checkCurrentValue:YES]; +} + +- (void)scrollContentChanged { + [self updateEffectViewStylingAndAnimate:NO checkCurrentValue:NO]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView_Private.h new file mode 100755 index 0000000..16cf201 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContainerView_Private.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStepContentView; +@interface ORKStepContainerView () + +@property (nonatomic) UIView *customContentView; +@property (nonatomic, assign) BOOL customContentFillsAvailableSpace; + +- (void)setCustomContentView:(UIView *)customContentView withTopPadding:(CGFloat)topPadding; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.h new file mode 100755 index 0000000..eb38766 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKLearnMoreInstructionStep; +@protocol ORKStepContentLearnMoreItemDelegate + +@required +- (void)stepContentLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep; + +@end + +@class ORKBodyItem; +@interface ORKStepContentView : UIView + +@property (nonatomic, nullable) UIImage *stepTopContentImage; + +@property (nonatomic, nullable) UIImage *auxiliaryImage; // Only underlayed when stepTopContentImage is added. + +@property (nonatomic) NSString *stepTitle; + +@property (nonatomic, nullable) NSString *stepText; + +@property (nonatomic, nullable) NSString *stepDetailText; + +@property (nonatomic) NSTextAlignment stepHeaderTextAlignment; + +@property (nonatomic) NSTextAlignment bodyTextAlignment; + +@property (nonatomic, nullable) UIImage *titleIconImage; + +@property (nonatomic) NSArray *bodyItems; + +@property (nonatomic) BOOL buildsInBodyItems; + +@property (nonatomic) BOOL useExtendedPadding; + +@property (nonatomic, weak) id delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.m new file mode 100755 index 0000000..79b63b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView.m @@ -0,0 +1,1007 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepContentView_Private.h" +#import "ORKTitleLabel.h" +#import "ORKBodyLabel.h" +#import "ORKBodyItem.h" +#import "ORKCompletionCheckmarkView.h" +#import "ORKBodyContainerView.h" +#import "ORKSkin.h" + + +/** + +_________________________+ + | |<-------------_stepContentView + | +-------+ | + | | _icon | | + | | | | + | +-------+ | + | | + | +---------------------+ | + | | _titleLabel | | + | |_____________________| | + | | + | +---------------------+ | + | | _textLabel | | + | |_____________________| | + | | + | +---------------------+ | + | | _detailTextLabel | | + | |_____________________| | + | | + | +---------------------+ | + | | |<-------------_bodyContainerView: UIstackView + | | +-----------------+ | | + | | | | | | + | | |--Title | | | + | | |--Text |<-------------- BodyItemStyleText + | | |--LearnMore | | | + | | |_________________| | | + | | | | + | | +---+-------------+ | | + | | | |--Title | | | + | | | o |--Text |<-------------- BodyItemStyleBullet + | | | |--LearnMore | | | + | | |___|_____________| | | + | |_____________________| | + |_________________________| + */ + +static const CGFloat ORKStepContentIconImageViewToTitleLabelPadding = 15.0; +static const CGFloat ORKStepContentIconToBodyTopPaddingStandard = 20.0; +static const CGFloat ORKStepContentIconToBulletTopPaddingStandard = 20.0; +static const CGFloat ORKStepContentTagPaddingTop = 15.0; + +typedef NS_CLOSED_ENUM(NSInteger, ORKUpdateConstraintSequence) { + ORKUpdateConstraintSequenceTopContentImageView = 0, + ORKUpdateConstraintSequenceIconImageView, + ORKUpdateConstraintSequenceTitleLabel, + ORKUpdateConstraintSequenceTextLabel, + ORKUpdateConstraintSequenceDetailTextLabel, + ORKUpdateConstraintSequenceBodyContainerView +} ORK_ENUM_AVAILABLE; + + +@interface ORKStepContentView() + +@end + + +@implementation ORKStepContentView { + CGFloat _additionalTopPaddingForTopLabel; + CGFloat _leftRightPadding; + NSMutableArray *_updatedConstraints; + + NSArray *_topContentImageViewConstraints; + NSArray *_iconImageViewConstraints; + NSArray *_textLabelConstraints; + NSArray *_detailTextLabelConstraints; + NSMutableArray *_leftRightPaddingConstraints; + + NSLayoutConstraint *_iconImageViewTopConstraint; + NSLayoutConstraint *_titleLabelTopConstraint; + NSLayoutConstraint *_textLabelTopConstraint; + NSLayoutConstraint *_detailTextLabelTopConstraint; + NSLayoutConstraint *_bodyContainerViewTopConstraint; + NSArray *_bodyContainerLeftRightConstraints; + NSLayoutConstraint *_stepContentBottomConstraint; + ORKCompletionCheckmarkView *_completionCheckmarkView; + +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self setupUpdatedConstraints]; + [self setStepContentViewBottomConstraint]; + _leftRightPadding = ORKStepContainerLeftRightPaddingForWindow(self.window); + } + return self; +} + +// top content image + +- (void)setStepTopContentImage:(UIImage *)stepTopContentImage { + _stepTopContentImage = stepTopContentImage; + + // 1.) nil Image; updateConstraints + if (!stepTopContentImage && _topContentImageView) { + [_topContentImageView removeFromSuperview]; + _topContentImageView = nil; + [self deactivateTopContentImageViewConstraints]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTopContentImageView]; + [self setNeedsUpdateConstraints]; + } + + // 2.) First Image; updateConstraints + if (stepTopContentImage && !_topContentImageView) { + [self setupTopContentImageView]; + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTopContentImageView]; + [self setNeedsUpdateConstraints]; + } + + // 3.) >= second Image; + if (stepTopContentImage && _topContentImageView) { + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:ORKStepTopContentImageChangedKey object:nil]; +} + +- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage { + _auxiliaryImage = auxiliaryImage; + if (_stepTopContentImage) { + _topContentImageView.image = [self topContentAndAuxiliaryImage]; + } +} + +- (UIImage *)topContentAndAuxiliaryImage { + if (!_auxiliaryImage) { + return _stepTopContentImage; + } + CGSize size = _auxiliaryImage.size; + UIGraphicsBeginImageContext(size); + + CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height); + + [_auxiliaryImage drawInRect:rect]; + [_stepTopContentImage drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (void)setupTopContentImageView { + if (!_topContentImageView) { + _topContentImageView = [UIImageView new]; + } + _topContentImageView.contentMode = UIViewContentModeScaleAspectFit; + [_topContentImageView setBackgroundColor:ORKColor(ORKTopContentImageViewBackgroundColorKey)]; + [self addSubview:_topContentImageView]; + [self setTopContentImageViewConstraints]; +} + +- (void)setTopContentImageViewConstraints { + _topContentImageView.translatesAutoresizingMaskIntoConstraints = NO; + _topContentImageViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_topContentImageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKStepContainerTopContentHeightForWindow(self.window)] + ]; + [_updatedConstraints addObjectsFromArray:_topContentImageViewConstraints]; +} + +- (void)deactivateTopContentImageViewConstraints { + [self deactivateConstraints:_topContentImageViewConstraints]; + _topContentImageViewConstraints = nil; +} + + +// icon image + +- (void)setTitleIconImage:(UIImage *)titleIconImage { + _titleIconImage = titleIconImage; + + if (!titleIconImage && _iconImageView) { + [_iconImageView removeFromSuperview]; + _iconImageView = nil; + [self deactivateIconImageViewConstraints]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceIconImageView]; + [self setNeedsUpdateConstraints]; + } + if (titleIconImage && !_iconImageView) { + [self setupIconImageView]; + _iconImageView.image = titleIconImage; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceIconImageView]; + [self setNeedsUpdateConstraints]; + } + if (titleIconImage && _iconImageView) { + _iconImageView.image = titleIconImage; + } +} + +- (void)updateTitleLabelTopConstraint { + if (_titleLabelTopConstraint && _titleLabelTopConstraint.isActive) { + [NSLayoutConstraint deactivateConstraints:@[_titleLabelTopConstraint]]; + } + if ([_updatedConstraints containsObject:_titleLabelTopConstraint]) { + [_updatedConstraints removeObject:_titleLabelTopConstraint]; + } + [self setTitleLabelTopConstraint]; + if (_titleLabelTopConstraint) { + [_updatedConstraints addObject:_titleLabelTopConstraint]; + } +} + +- (void)setupIconImageView { + if (!_iconImageView) { + _iconImageView = [UIImageView new]; + } + _iconImageView.contentMode = UIViewContentModeScaleAspectFit; + + [self addSubview:_iconImageView]; + [self setIconImageViewConstraints]; +} + +- (void)setIconImageViewTopConstraint { + if (_iconImageView) { + _iconImageViewTopConstraint = [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_topContentImageView ? : self + attribute:_topContentImageView ? NSLayoutAttributeBottom : NSLayoutAttributeTop + multiplier:1.0 + constant:ORKStepContentIconImageViewToTitleLabelPadding]; // This needs to match what the text padding is + } +} + +- (void)updateIconImageViewTopConstraint { + if (_iconImageViewTopConstraint) { + [self deactivateConstraints:@[_iconImageViewTopConstraint]]; + } + [self setIconImageViewTopConstraint]; + if (_iconImageViewTopConstraint) { + [_updatedConstraints addObject:_iconImageViewTopConstraint]; + } +} + +- (void)setIconImageViewConstraints { + _iconImageView.translatesAutoresizingMaskIntoConstraints = NO; + [self setIconImageViewTopConstraint]; + + _iconImageViewConstraints = @[ + _iconImageViewTopConstraint, + [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKStepContentIconImageViewDimension], + [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKStepContentIconImageViewDimension]]; + [_updatedConstraints addObjectsFromArray:_iconImageViewConstraints]; + [self setNeedsUpdateConstraints]; +} + +- (void)deactivateIconImageViewConstraints { + [self deactivateConstraints:_iconImageViewConstraints]; + _iconImageViewConstraints = nil; +} + +// step title + +- (void)setStepTitle:(NSString *)stepTitle { + _stepTitle = stepTitle; + if (!_titleLabel) { + [self setupTitleLabel]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTitleLabel]; + [self setNeedsUpdateConstraints]; + } + [_titleLabel setText:stepTitle]; +} + +- (void)setupTitleLabel { + if (!_titleLabel) { + _titleLabel = [ORKTitleLabel new]; + } + + _titleLabel.numberOfLines = 0; + _titleLabel.textAlignment = _stepHeaderTextAlignment; + [self addSubview:_titleLabel]; + [self setupTitleLabelConstraints]; + [self setContainerLeftRightConstraints]; +} + +- (void)setupTitleLabelConstraints { + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self setTitleLabelTopConstraint]; + [_updatedConstraints addObjectsFromArray:@[ + _titleLabelTopConstraint + ]]; + [self setNeedsUpdateConstraints]; +} + +- (void)setTitleLabelTopConstraint { + if (_titleLabel) { + id topItem; + NSLayoutAttribute attribute; + CGFloat constant; + + if (_iconImageView) { + topItem = _iconImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContentIconImageViewToTitleLabelPadding; + } + else if (_topContentImageView) { + topItem = _topContentImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContentIconImageViewToTitleLabelPadding; + } + else { + topItem = self; + attribute = NSLayoutAttributeTop; + constant = ORKStepContentIconImageViewToTitleLabelPadding; + } + + _titleLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_titleLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:topItem + attribute:attribute + multiplier:1.0 + constant:constant]; + } +} + + +// step text + +- (void)setStepText:(NSString *)stepText { + _stepText = stepText; + if (stepText && !_textLabel) { + [self setupTextLabel]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTextLabel]; + [self setNeedsUpdateConstraints]; + [_textLabel setText:stepText]; + } + else if (stepText && _textLabel) { + [_textLabel setText:_stepText]; + } + else if (!stepText) { + [_textLabel removeFromSuperview]; + _textLabel = nil; + [self deactivateTextLabelConstraints]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceTextLabel]; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setupTextLabel { + if (!_textLabel) { + _textLabel = [ORKBodyLabel new]; + } + _textLabel.textAlignment = _stepHeaderTextAlignment; + _textLabel.numberOfLines = 0; + _textLabel.lineBreakMode = NSLineBreakByWordWrapping; + [self addSubview:_textLabel]; + [self setupTextLabelConstraints]; + [self setContainerLeftRightConstraints]; +} + +- (void)setupTextLabelConstraints { + _textLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self setTextLabelTopConstraint]; + _textLabelConstraints = @[_textLabelTopConstraint]; + + [_updatedConstraints addObjectsFromArray:_textLabelConstraints]; + [self setNeedsUpdateConstraints]; +} + +- (void)setTextLabelTopConstraint { + if (_textLabel) { + id topItem; + NSLayoutAttribute attribute; + CGFloat constant; + + if (_titleLabel) { + topItem = _titleLabel; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContainerTitleToBodyTopPaddingForWindow(self.window); + } + else if (_iconImageView) { + topItem = _iconImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContentIconToBodyTopPaddingStandard; + } + else if (_topContentImageView) { + topItem = _topContentImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window); + } + else { + topItem = self; + attribute = NSLayoutAttributeTop; + constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window) + _additionalTopPaddingForTopLabel; + } + + _textLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_textLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:topItem + attribute:attribute + multiplier:1.0 + constant:constant]; + } +} + +- (void)updateTextLabelTopConstraint { + if (_textLabelTopConstraint) { + [self deactivateConstraints:@[_textLabelTopConstraint]]; + } + [self setTextLabelTopConstraint]; + if (_textLabelTopConstraint) { + [_updatedConstraints addObject:_textLabelTopConstraint]; + } +} + +- (void)deactivateTextLabelConstraints { + [self deactivateConstraints:_textLabelConstraints]; + _textLabelConstraints = nil; +} + + +// step detail text + +- (void)setStepDetailText:(NSString *)stepDetailText { + _stepDetailText = stepDetailText; + if (stepDetailText && !_detailTextLabel) { + [self setupDetailTextLabel]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceDetailTextLabel]; + [self setNeedsUpdateConstraints]; + [_detailTextLabel setText:stepDetailText]; + } + else if (stepDetailText && _detailTextLabel) { + [_detailTextLabel setText:_stepDetailText]; + } + else if (!stepDetailText) { + [_detailTextLabel removeFromSuperview]; + _detailTextLabel = nil; + [self deactivateDetailTextLabelConstraints]; + [self updateViewConstraintsForSequence:ORKUpdateConstraintSequenceDetailTextLabel]; + [self setNeedsUpdateConstraints]; + } +} + +- (void)setupDetailTextLabel { + if (!_detailTextLabel) { + _detailTextLabel = [ORKBodyLabel new]; + } + _detailTextLabel.textAlignment = _stepHeaderTextAlignment; + _detailTextLabel.numberOfLines = 0; + _detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; + [self addSubview:_detailTextLabel]; + [self setupDetailTextLabelConstraints]; + [self setContainerLeftRightConstraints]; +} + +- (void)setStepHeaderTextAlignment:(NSTextAlignment)stepHeaderTextAlignment { + _stepHeaderTextAlignment = stepHeaderTextAlignment; + _titleLabel.textAlignment = _stepHeaderTextAlignment; + _detailTextLabel.textAlignment = _stepHeaderTextAlignment; + _textLabel.textAlignment = _stepHeaderTextAlignment; +} + +- (void)setBodyTextAlignment:(NSTextAlignment)bodyTextAlignment { + _bodyTextAlignment = bodyTextAlignment; +} + +- (void)setUseExtendedPadding:(BOOL)useExtendedPadding { + _useExtendedPadding = useExtendedPadding; + _leftRightPadding = useExtendedPadding ? ORKStepContainerExtendedLeftRightPaddingForWindow(self.window) : ORKStepContainerLeftRightPaddingForWindow(self.window); + [NSLayoutConstraint deactivateConstraints:_leftRightPaddingConstraints]; + [_updatedConstraints removeObjectsInArray:_leftRightPaddingConstraints]; + [self setContainerLeftRightConstraints]; +} + +- (void)setupDetailTextLabelConstraints { + _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self setDetailTextLabelTopConstraint]; + _detailTextLabelConstraints = @[_detailTextLabelTopConstraint]; + + [_updatedConstraints addObjectsFromArray:_detailTextLabelConstraints]; + [self setNeedsUpdateConstraints]; +} + +- (void)setDetailTextLabelTopConstraint { + if (_detailTextLabel) { + id topItem; + NSLayoutAttribute attribute; + CGFloat constant; + if (_textLabel) { + topItem = _textLabel; + attribute = NSLayoutAttributeBottom; + constant = ORKBodyToBodyPaddingStandard; + } + + else if (_titleLabel) { + topItem = _titleLabel; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContainerTitleToBodyTopPaddingForWindow(self.window); + } + else if (_iconImageView) { + topItem = _iconImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContentIconToBodyTopPaddingStandard; + } + else if (_topContentImageView) { + topItem = _topContentImageView; + attribute = NSLayoutAttributeBottom; + constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window); + } + else { + topItem = self; + attribute = NSLayoutAttributeTop; + constant = ORKStepContainerFirstItemTopPaddingForWindow(self.window) + _additionalTopPaddingForTopLabel; + } + + _detailTextLabelTopConstraint = [NSLayoutConstraint constraintWithItem:_detailTextLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:topItem + attribute:attribute + multiplier:1.0 + constant:constant]; + } +} + +- (void)updateDetailTextLabelTopConstraint { + if (_detailTextLabelTopConstraint) { + [self deactivateConstraints:@[_detailTextLabelTopConstraint]]; + } + [self setDetailTextLabelTopConstraint]; + if (_detailTextLabelTopConstraint) { + [_updatedConstraints addObject:_detailTextLabelTopConstraint]; + } +} + +- (void)deactivateDetailTextLabelConstraints { + [self deactivateConstraints:_detailTextLabelConstraints]; + _detailTextLabelConstraints = nil; +} + + +// body container + +- (void)setBodyItems:(NSArray *)bodyItems { + _bodyItems = bodyItems; + if (_bodyItems) { + if (!_bodyContainerView) { + [self setupBodyContainerView]; + [self updateStepContentViewBottomConstraint]; + [self setNeedsUpdateConstraints]; + } + else { + _bodyContainerView.bodyItems = _bodyItems; + } + } +} + +- (void)setBuildsInBodyItems:(BOOL)buildsInBodyItems { + _buildsInBodyItems = buildsInBodyItems; + _bodyContainerView.buildsInBodyItems = _buildsInBodyItems; +} + +- (void)setupBodyContainerView { + __weak id weakSelf = self; + if (!_bodyContainerView) { + _bodyContainerView = [[ORKBodyContainerView alloc] initWithBodyItems:_bodyItems + textAlignment:_bodyTextAlignment + delegate:weakSelf]; + } + [self addSubview:_bodyContainerView]; + [self setupBodyContainerViewConstraints]; +} + +- (void)updateBodyContainerViewTopConstraint { + if (_bodyContainerView) { + if (_bodyContainerViewTopConstraint) { + [self deactivateConstraints:@[_bodyContainerViewTopConstraint]]; + } + [self setBodyContainerViewTopConstraint]; + if (_bodyContainerViewTopConstraint) { + [_updatedConstraints addObject:_bodyContainerViewTopConstraint]; + } + } +} + +- (void)setupBodyContainerViewConstraints { + _bodyContainerView.translatesAutoresizingMaskIntoConstraints = NO; + [self setBodyContainerViewTopConstraint]; + [_updatedConstraints addObjectsFromArray:@[ + _bodyContainerViewTopConstraint, + ]]; + [self setNeedsUpdateConstraints]; +} + +- (void)setContainerLeftRightConstraints { + [NSLayoutConstraint deactivateConstraints:_leftRightPaddingConstraints]; + [_updatedConstraints removeObjectsInArray:_leftRightPaddingConstraints]; + + _leftRightPaddingConstraints = [[NSMutableArray alloc] init]; + if (_textLabel != nil) { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_textLabel + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_textLabel + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-_leftRightPadding] + ]]; + } + + if (_titleLabel != nil) { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_titleLabel + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_titleLabel + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-_leftRightPadding] + ]]; + } + + if (_detailTextLabel != nil) { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_detailTextLabel + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_detailTextLabel + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-_leftRightPadding] + ]]; + } + + if (_bodyContainerView != nil) { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_bodyContainerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_bodyContainerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-_leftRightPadding] + ]]; + } + + if (_iconImageView != nil) { + if (_stepHeaderTextAlignment == NSTextAlignmentLeft) { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0] + ]]; + } else { + [_leftRightPaddingConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0] + ]]; + } + } + + [_updatedConstraints addObjectsFromArray:_leftRightPaddingConstraints]; + [self setNeedsUpdateConstraints]; +} + +- (void)setBodyContainerViewTopConstraint { + id topItem; + CGFloat topPadding; + NSLayoutAttribute attribute; + + // Checking empty string as we have an odd case where the label gets created because the text + // is an empty string. This causes the layout to be bigger than expected as the label is given + // some amount of height and we are calculating vertical padding based off a label that is not + // visible. TODO - rework the labels so they do not get created with empty text. + if (_detailTextLabel && ![_stepDetailText isEqualToString:@""]) { + topItem = _detailTextLabel; + topPadding = ORKBodyToBodyPaddingStandard; + attribute = NSLayoutAttributeBottom; + } + + else if (_textLabel && ![_stepText isEqualToString:@""]) { + topItem = _textLabel; + topPadding = ORKBodyToBodyPaddingStandard; + attribute = NSLayoutAttributeBottom; + } + + else if (_titleLabel) { + topItem = _titleLabel; + + if (_bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleTag) { + topPadding = ORKStepContentTagPaddingTop; + } else { + topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContainerTitleToBodyTopPaddingForWindow(self.window) : ORKStepContainerTitleToBulletTopPaddingForWindow(self.window); + } + + attribute = NSLayoutAttributeBottom; + } + else if (_iconImageView) { + topItem = _iconImageView; + topPadding = _bodyItems.firstObject.bodyItemStyle == ORKBodyItemStyleText ? ORKStepContentIconToBodyTopPaddingStandard : ORKStepContentIconToBulletTopPaddingStandard; + attribute = NSLayoutAttributeBottom; + } + + else if (_topContentImageView) { + topItem = _topContentImageView; + topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window); + attribute = NSLayoutAttributeBottom; + } + else { + topItem = self; + topPadding = ORKStepContainerFirstItemTopPaddingForWindow(self.window); + attribute = NSLayoutAttributeTop; + } + + + _bodyContainerViewTopConstraint = [NSLayoutConstraint constraintWithItem:_bodyContainerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:topItem + attribute:attribute + multiplier:1.0 + constant:topPadding]; +} + + +// Variable constraints methods + +- (void)updateViewConstraintsForSequence:(ORKUpdateConstraintSequence)sequence { + switch (sequence) { + case ORKUpdateConstraintSequenceTopContentImageView: + [self updateIconImageViewTopConstraint]; + case ORKUpdateConstraintSequenceIconImageView: + [self updateTitleLabelTopConstraint]; + case ORKUpdateConstraintSequenceTitleLabel: + [self updateTextLabelTopConstraint]; + case ORKUpdateConstraintSequenceTextLabel: + [self updateDetailTextLabelTopConstraint]; + case ORKUpdateConstraintSequenceDetailTextLabel: + [self updateBodyContainerViewTopConstraint]; + + default: + break; + } + [self updateStepContentViewBottomConstraint]; +} + +- (void)updateStepContentViewBottomConstraint { + [self deactivateConstraints:@[_stepContentBottomConstraint]]; + [self setStepContentViewBottomConstraint]; + [_updatedConstraints addObject:_stepContentBottomConstraint]; +} + +- (void)setStepContentViewBottomConstraint { + id bottomItem; + NSLayoutAttribute attribute; + CGFloat constant; + + if (_bodyContainerView) { + bottomItem = _bodyContainerView; + attribute = NSLayoutAttributeBottom; + constant = 0.0; + } + else if (_detailTextLabel && ![_stepDetailText isEqualToString:@""]) { + bottomItem = _detailTextLabel; + attribute = NSLayoutAttributeBottom; + constant = 0.0; + } + else if (_textLabel && ![_stepText isEqualToString:@""]) { + bottomItem = _textLabel; + attribute = NSLayoutAttributeBottom; + constant = 0.0; + } + else if (_titleLabel) { + bottomItem = _titleLabel; + attribute = NSLayoutAttributeBottom; + constant = 0.0; + } + else if (_iconImageView) { + bottomItem = _iconImageView; + attribute = NSLayoutAttributeBottom; + constant = 0.0; + } + else { + bottomItem = nil; + attribute = NSLayoutAttributeNotAnAttribute; + constant = 0.0; + } + + _stepContentBottomConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:bottomItem ? NSLayoutAttributeBottom : NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:bottomItem + attribute:attribute + multiplier:1.0 + constant:constant]; +} + +- (void)setupUpdatedConstraints { + _updatedConstraints = [[NSMutableArray alloc] init]; +} + +- (void)deactivateConstraints:(nullable NSArray *)constraints { + if (constraints) { + [NSLayoutConstraint deactivateConstraints:constraints]; + } + [self updatedConstraintsWithdrawConstraints:constraints]; + [self setNeedsUpdateConstraints]; +} + +- (void)updatedConstraintsWithdrawConstraints:(nullable NSArray *)constraints { + if (constraints && constraints.count > 0) { + for (NSLayoutConstraint *constraint in constraints) { + if ([_updatedConstraints containsObject:constraint]) { + [_updatedConstraints removeObject:constraint]; + } + } + } +} + +- (void)updateContentConstraints { + [NSLayoutConstraint activateConstraints:_updatedConstraints]; + [_updatedConstraints removeAllObjects]; +} + +- (void)updateConstraints { + [self updateContentConstraints]; + [super updateConstraints]; +} + + +// Private methods + +- (void)setAdditionalTopPaddingForTopLabel:(CGFloat)padding { + _additionalTopPaddingForTopLabel = padding; + if (!_topContentImageView && !_iconImageView) { + if (_titleLabel) { + [self updateTitleLabelTopConstraint]; + } + else if (_textLabel) { + [self updateTextLabelTopConstraint]; + } + else if (_detailTextLabel) { + [self updateDetailTextLabelTopConstraint]; + } + } +} + +- (nullable ORKCompletionCheckmarkView *)completionCheckmarkView { + if (!_completionCheckmarkView) { + _completionCheckmarkView = [[ORKCompletionCheckmarkView alloc] initWithDefaultDimension]; + [self addSubview:_completionCheckmarkView]; + self.titleIconImage = [UIImage new]; + [_iconImageView setHidden:YES]; + _completionCheckmarkView.translatesAutoresizingMaskIntoConstraints = NO; + [self setContainerLeftRightConstraints]; + [_updatedConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_completionCheckmarkView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:_iconImageView + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_completionCheckmarkView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_iconImageView + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_completionCheckmarkView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_iconImageView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_completionCheckmarkView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_iconImageView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0] + ]]; + } + return _completionCheckmarkView; +} + +#pragma mark - ORKBodycontainerViewDelegate + +- (void)bodyContainerLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep { + [_delegate stepContentLearnMoreButtonPressed:learnMoreStep]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView_Private.h new file mode 100755 index 0000000..9c90724 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepContentView_Private.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTitleLabel; +@class ORKBodyContainerView; +@class ORKCompletionCheckmarkView; +@interface ORKStepContentView () + +@property (nonatomic, nullable) UIImageView *topContentImageView; +@property (nonatomic) ORKTitleLabel *titleLabel; +@property (nonatomic, nullable) UILabel *textLabel; +@property (nonatomic, nullable) UILabel *detailTextLabel; +@property (nonatomic, nullable) UIImageView *iconImageView; +@property (nonatomic) ORKBodyContainerView *bodyContainerView; + +// This padding is ignored if there is a `topContentImageView` or `iconImageView` above the label. +- (void)setAdditionalTopPaddingForTopLabel:(CGFloat)padding; + +- (nullable ORKCompletionCheckmarkView *)completionCheckmarkView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.h new file mode 100755 index 0000000..c77db19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKStepHeaderView : UIView + +@property (nonatomic, strong, nullable) UIBarButtonItem *learnMoreButtonItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.m new file mode 100755 index 0000000..47a05f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView.m @@ -0,0 +1,446 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepHeaderView.h" +#import "ORKStepHeaderView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +#define ORKVerticalContainerLog(...) + +@implementation ORKStepHeaderView { + NSLayoutConstraint *_captionMinBottomSpacingConstraint; + NSLayoutConstraint *_captionToInstructionConstraint; + NSLayoutConstraint *_headerZeroHeightConstraint; + NSLayoutConstraint *_illustrationToCaptionBaselineConstraint; + NSLayoutConstraint *_illustrationToCaptionTopConstraint; + NSLayoutConstraint *_instructionMinBottomSpacingConstraint; + NSLayoutConstraint *_instructionToLearnMoreConstraint; + NSLayoutConstraint *_learnMoreToStepViewConstraint; + NSLayoutConstraint *_topToIconImageViewConstraint; +} + +- (void)updateCaptionLabelPreferredWidth { + CGFloat sideMargin = ORKGetMetricForWindow(ORKScreenMetricHeadlineSideMargin, self.window); + UIEdgeInsets layoutMargins = self.layoutMargins; + + // If we don't do this, sometimes the label doesn't split onto two lines properly. + CGFloat maxLabelLayoutWidth = MAX(self.bounds.size.width - sideMargin * 2 - layoutMargins.left - layoutMargins.right, 0); + + _captionLabel.preferredMaxLayoutWidth = maxLabelLayoutWidth; + _instructionLabel.preferredMaxLayoutWidth = maxLabelLayoutWidth; + [self setNeedsUpdateConstraints]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self updateCaptionLabelPreferredWidth]; +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self updateCaptionLabelPreferredWidth]; +} + +- (void)setLayoutMargins:(UIEdgeInsets)layoutMargins { + [super setLayoutMargins:layoutMargins]; + [self updateCaptionLabelPreferredWidth]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + { + _iconImageView = [UIImageView new]; + _iconImageView.contentMode = UIViewContentModeScaleAspectFit; + [self addSubview:_iconImageView]; + } + + // Text Label + { + _captionLabel = [ORKHeadlineLabel new]; + _captionLabel.numberOfLines = 0; + _captionLabel.textAlignment = NSTextAlignmentNatural; + [self addSubview:_captionLabel]; + } + + { + _learnMoreButton = [ORKTextButton new]; + _learnMoreButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeading; + _learnMoreButton.contentEdgeInsets = (UIEdgeInsets){10,0,10,10}; + [_learnMoreButton setTitle:nil forState:UIControlStateNormal]; + [_learnMoreButton addTarget:self action:@selector(learnMoreAction:) forControlEvents:UIControlEventTouchUpInside]; + _learnMoreButton.exclusiveTouch = YES; + _learnMoreButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + _learnMoreButton.titleLabel.textAlignment = NSTextAlignmentNatural; + [self addSubview:_learnMoreButton]; + self.learnMoreButtonItem = nil; + } + + { + _instructionLabel = [ORKSubheadlineLabel new]; + _instructionLabel.numberOfLines = 0; + _instructionLabel.textAlignment = NSTextAlignmentNatural; + + [self addSubview:_instructionLabel]; + } + + [_learnMoreButton setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + [_learnMoreButton setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; + +#ifdef LAYOUT_DEBUG + _captionLabel.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.2]; + _captionLabel.layer.borderColor = [UIColor yellowColor].CGColor; + _captionLabel.layer.borderWidth = 1.0; + _learnMoreButton.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.2]; + _learnMoreButton.layer.borderColor = [UIColor blueColor].CGColor; + _learnMoreButton.layer.borderWidth = 1.0; + _instructionLabel.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.2]; + _instructionLabel.layer.borderColor = [UIColor greenColor].CGColor; + _instructionLabel.layer.borderWidth = 1.0; + self.backgroundColor = [[UIColor purpleColor] colorWithAlphaComponent:0.2]; +#endif + [self setUpConstraints]; + [self setNeedsUpdateConstraints]; + } + return self; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; + [self updateCaptionLabelPreferredWidth]; +} + +- (void)learnMoreAction:(id)sender { + ORKSuppressPerformSelectorWarning( + (void)[_learnMoreButtonItem.target performSelector:_learnMoreButtonItem.action withObject:self]; + ); +} + +- (void)setLearnMoreButtonItem:(UIBarButtonItem *)learnMoreButtonItem { + _learnMoreButtonItem = learnMoreButtonItem; + [_learnMoreButton setTitle:learnMoreButtonItem.title forState:UIControlStateNormal]; + _learnMoreButton.alpha = (learnMoreButtonItem.title.length > 0) ? 1 : 0; + [self updateConstraintConstantsForWindow:self.window]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + CGRect bounds = self.bounds; + CGRect insetBounds = UIEdgeInsetsInsetRect(bounds, self.layoutMargins); + + CGFloat sideMargin = ORKGetMetricForWindow(ORKScreenMetricLearnMoreButtonSideMargin, self.window); + _learnMoreButton.titleLabel.preferredMaxLayoutWidth = insetBounds.size.width - sideMargin * 2; +} + +const CGFloat IconHeight = 60; + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + static const CGFloat AssumedNavBarHeight = 44; + static const CGFloat AssumedStatusBarHeight = 20; + + const CGFloat IconBottomToCaptionBaseline = ORKGetMetricForWindow(ORKScreenMetricIconImageViewToCaptionBaseline, window);; + + const CGFloat TopToIconTop = ORKGetMetricForWindow(ORKScreenMetricTopToIconImageViewTop, window); + BOOL hasIconView = _iconImageView.image != nil; + + const CGFloat IllustrationToCaptionBaseline = ORKGetMetricForWindow(ORKScreenMetricIllustrationToCaptionBaseline, window); + const CGFloat TopToCaptionBaseline = hasIconView ? (IconBottomToCaptionBaseline + IconHeight + TopToIconTop) : (ORKGetMetricForWindow(ORKScreenMetricTopToCaptionBaseline, window) - AssumedStatusBarHeight - AssumedNavBarHeight); + + const CGFloat CaptionBaselineToInstructionBaseline_WithInstruction = ORKGetMetricForWindow(ORKScreenMetricCaptionBaselineToInstructionBaseline, window); + const CGFloat CaptionBaselineToInstructionBaseline_NoInstruction = MIN(26, CaptionBaselineToInstructionBaseline_WithInstruction); // Not part of spec + const CGFloat InstructionBaselineToLearnMoreBaseline = ORKGetMetricForWindow(ORKScreenMetricInstructionBaselineToLearnMoreBaseline, window); + const CGFloat LearnMoreBaselineToStepViewTop = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTop, window); + const CGFloat InstructionBaselineToStepViewTopWithNoLearnMore = ORKGetMetricForWindow(ORKScreenMetricLearnMoreBaselineToStepViewTopWithNoLearnMore, window); + + BOOL hasCaptionLabel = _captionLabel.text.length > 0 || hasIconView; + BOOL hasInstructionLabel = _instructionLabel.text.length > 0; + BOOL hasLearnMoreButton = (_learnMoreButton.alpha > 0); + + ORKVerticalContainerLog(@"hasCaption=%@ hasInstruction=%@ hasLearnMore=%@", @(hasCaption), @(hasInstruction), @(hasLearnMore)); + + // If one label is empty and the other is not, then allow the empty label to shrink to nothing + // and the other label to grow to fill + UILayoutPriority captionVerticalHugging = hasCaptionLabel && !hasInstructionLabel ? UILayoutPriorityDefaultLow - 1 : UILayoutPriorityDefaultLow; + UILayoutPriority instructionVerticalHugging = hasInstructionLabel && !hasCaptionLabel ? UILayoutPriorityDefaultLow - 1 : UILayoutPriorityDefaultLow; + [_captionLabel setContentHuggingPriority:captionVerticalHugging forAxis:UILayoutConstraintAxisVertical]; + [_instructionLabel setContentHuggingPriority:instructionVerticalHugging forAxis:UILayoutConstraintAxisVertical]; + + { + _headerZeroHeightConstraint.active = !(hasCaptionLabel || hasInstructionLabel || hasLearnMoreButton || hasIconView); + } + + { + _illustrationToCaptionBaselineConstraint.constant = _hasContentAbove ? IllustrationToCaptionBaseline : TopToCaptionBaseline; + _illustrationToCaptionBaselineConstraint.active = hasCaptionLabel; + _illustrationToCaptionTopConstraint.constant = 0; + _illustrationToCaptionTopConstraint.active = !hasCaptionLabel; + } + + { + _topToIconImageViewConstraint.active = hasIconView; + _topToIconImageViewConstraint.constant = TopToIconTop; + } + + { + _captionToInstructionConstraint.constant = hasInstructionLabel ? CaptionBaselineToInstructionBaseline_WithInstruction : CaptionBaselineToInstructionBaseline_NoInstruction; + } + + { + _instructionToLearnMoreConstraint.constant = hasLearnMoreButton ? InstructionBaselineToLearnMoreBaseline : 0; + } + + { + _learnMoreToStepViewConstraint.constant = LearnMoreBaselineToStepViewTop; + _learnMoreToStepViewConstraint.active = hasLearnMoreButton; + } + + { + _captionMinBottomSpacingConstraint.active = hasCaptionLabel && !(hasLearnMoreButton || hasInstructionLabel); + } + + { + _instructionMinBottomSpacingConstraint.constant = InstructionBaselineToStepViewTopWithNoLearnMore; + _instructionMinBottomSpacingConstraint.active = hasInstructionLabel && !(hasLearnMoreButton); + } +} + +- (void)setHasContentAbove:(BOOL)hasContentAbove { + _hasContentAbove = hasContentAbove; + [self setNeedsUpdateConstraints]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + // Fill all available horizontal space + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + widthConstraint.priority = UILayoutPriorityDefaultLow - 1; + [constraints addObject:widthConstraint]; + + NSArray *views = @[_iconImageView, _captionLabel, _instructionLabel, _learnMoreButton]; + [_iconImageView setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal]; + [_captionLabel setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal]; + [_instructionLabel setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal]; + [_learnMoreButton setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal]; + ORKEnableAutoLayoutForViews(views); + + { + _topToIconImageViewConstraint = [NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:40.0]; + [constraints addObject:_topToIconImageViewConstraint]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_iconImageView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_iconImageView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:IconHeight]]; + } + + { + _captionToInstructionConstraint = [NSLayoutConstraint constraintWithItem:_instructionLabel + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:_captionLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:36.0]; + [constraints addObject:_captionToInstructionConstraint]; + } + + { + _instructionToLearnMoreConstraint = [NSLayoutConstraint constraintWithItem:_learnMoreButton + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:_instructionLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:30.0]; + [constraints addObject:_instructionToLearnMoreConstraint]; + } + + { + _illustrationToCaptionBaselineConstraint = [NSLayoutConstraint constraintWithItem:_captionLabel + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:44.0]; + _illustrationToCaptionBaselineConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:_illustrationToCaptionBaselineConstraint]; + } + + { + _illustrationToCaptionTopConstraint = [NSLayoutConstraint constraintWithItem:_captionLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + _illustrationToCaptionTopConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:_illustrationToCaptionTopConstraint]; + } + + { + _learnMoreToStepViewConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_learnMoreButton + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:44.0]; + _learnMoreToStepViewConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:_learnMoreToStepViewConstraint]; + } + + { + _captionMinBottomSpacingConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_captionLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:44.0]; + _captionMinBottomSpacingConstraint.priority = UILayoutPriorityDefaultHigh - 1; + [constraints addObject:_captionMinBottomSpacingConstraint]; + } + + { + _instructionMinBottomSpacingConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_instructionLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:44.0]; + _instructionMinBottomSpacingConstraint.priority = UILayoutPriorityDefaultHigh - 2; + [constraints addObject:_instructionMinBottomSpacingConstraint]; + } + + for (UIView *view in views) { + + if (view != _iconImageView) { + [constraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeftMargin + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRightMargin + multiplier:1.0 + constant:0.0]]; + } + + NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + bottomConstraint.priority = UILayoutPriorityDefaultHigh; + // All views must fit inside, vertically + [constraints addObject:bottomConstraint]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + } + + { + // This constraint will only be set active if there is no content. + // Priority is less than required, so that if it is temporarily active it doesn't cause an + // exception. + _headerZeroHeightConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; + _headerZeroHeightConstraint.priority = UILayoutPriorityRequired - 1; + [constraints addObject:_headerZeroHeightConstraint]; + } + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateConstraints { + [self updateConstraintConstantsForWindow:self.window]; + [super updateConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView_Internal.h new file mode 100755 index 0000000..84efbfb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepHeaderView_Internal.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepHeaderView.h" +#import "ORKHeadlineLabel.h" +#import "ORKSubheadlineLabel.h" +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKStepHeaderView () + +@property (nonatomic, strong, readonly) UIImageView *iconImageView; +@property (nonatomic, strong, readonly) ORKHeadlineLabel *captionLabel; +@property (nonatomic, strong, readonly) ORKTextButton *learnMoreButton; +@property (nonatomic, strong, readonly) ORKSubheadlineLabel *instructionLabel; + +@property (nonatomic) BOOL hasContentAbove; + +- (void)updateCaptionLabelPreferredWidth; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.h new file mode 100755 index 0000000..05a1ee1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.h @@ -0,0 +1,416 @@ +/* + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKNullStepIdentifier` constant can be used as the destination step identifier for any + `ORKStepNavigationRule` concrete subclass to denote that the ongoing task should end after the + navigation rule is triggered. + */ +ORK_EXTERN NSString *const ORKNullStepIdentifier ORK_AVAILABLE_DECL; + +@class ORKStep; +@class ORKResult; +@class ORKTaskResult; +@class ORKResultPredicate; + +/** + The `ORKStepNavigationRule` class is the abstract base class for concrete step navigation rules. + + Step navigation rules can be used within an `ORKNavigableOrderedTask` object. You assign step + navigation rules to be triggered by the task steps. Each step can have one rule at most. + + Subclasses must implement the `identifierForDestinationStepWithTaskResult:` method, which returns + the identifier of the destination step for the rule. + + Two concrete subclasses are included: `ORKPredicateStepNavigationRule` can match any answer + combination in the results of the ongoing task and jump accordingly; `ORKDirectStepNavigationRule` + unconditionally navigates to the step specified by the destination step identifier. + */ +ORK_CLASS_AVAILABLE +@interface ORKStepNavigationRule : NSObject + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Returns the target step identifier. + + Subclasses must implement this method to calculate the next step based on the passed task result. + The `ORKNullStepIdentifier` constant can be returned to indicate that the ongoing task should end + after the step navigation rule is triggered. Returning `nil` makes the task to go to the next + contiguous step. + + @param taskResult The up-to-date task result, used for calculating the destination step. + + @return The identifier of the destination step. + */ +- (nullable NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult; + +@end + + +/** + The `ORKPredicateStepNavigationRule` can be used to match any answer combination in the results of + the ongoing task (or in those of previously completed tasks) and jump accordingly. You must provide + one or more result predicates (each predicate can match one or more step results within the task). + + Predicate step navigation rules contain an arbitrary number of result predicates with a + corresponding number of destination step identifiers, plus an optional default step identifier that + is used if none of the result predicates match. One result predicate can match one or more question + results; if matching several question results, that predicate can belong to the same or to + different task results). This rule allows you to define arbitrarily complex task navigation + behaviors. + + The `ORKResultPredicate` class provides convenience class methods to build predicates for all the + `ORKQuestionResult` subtypes. Predicates must supply both the task result identifier and the + question result identifier, in addition to one or more expected answers. + */ +ORK_CLASS_AVAILABLE +@interface ORKPredicateStepNavigationRule : ORKStepNavigationRule + +/* + The `init` and `new` methods are unavailable. + + `ORKStepNavigationRule` classes should be initialized with custom designated initializers on each + subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized predicate step navigation rule using the specified result predicates, + destination step identifiers, and an optional default step identifier. + + @param resultPredicates An array of result predicates. Each result predicate can match + one or more question results in the ongoing task result or + in any of the additional task results. + @param destinationStepIdentifiers An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the result predicates parameters. If you want for a + certain predicate match to end te task, you achieve that by + using the `ORKNullStepIdentifier` constant. + @param defaultStepIdentifier The identifier of the step, which is used if none of the + result predicates match. If this argument is `nil` and none + of the predicates match, the default ordered task navigation + behavior takes place (that is, the task goes to the next + step in order). + + @return An initialized predicate step navigation rule. + */ +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers + defaultStepIdentifier:(nullable NSString *)defaultStepIdentifier NS_DESIGNATED_INITIALIZER NS_SWIFT_UNAVAILABLE("Use the Swift init(resultPredicatesAndDestinationStepIdentifiers: [(NSPredicate, String)], defaultStepIdentifierOrNil: String?) initializer instead."); + +/** + Returns an initialized predicate step navigation rule using the specified result predicates and + destination step identifiers. + + @param resultPredicates An array of result predicates. Each result predicate can match + one or more question results in the ongoing task result or + in any of the additional task results. + @param destinationStepIdentifiers An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the result predicates parameters. + + @return An initialized predicate step navigation rule. + */ +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers NS_SWIFT_UNAVAILABLE("Use the Swift init(resultPredicatesAndDestinationStepIdentifiers: [(NSPredicate, String)], defaultStepIdentifierOrNil: String?) initializer instead."); + +/** + Returns a new predicate step navigation rule that was initialized from data in the given + unarchiver. + + @param aDecoder The coder from which to initialize the step navigation rule. + + @return A new predicate step navigation rule. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + An optional array of additional task results. + + With this property, a task can have different navigation behavior depending on the results of + related tasks that the user may have already completed. The predicate step navigation rule can use + the question results within these tasks, in addition to the current task question results, to match + the result predicates. + + You must ensure that all the task result identifiers are unique and that they are different from + the ongoing task result identifier. Also ensure that no task result contains question + results with duplicate identifiers. Question results *can have* equal identifiers provided that + they belong to different task results. + + Each object in the array should be of the `ORKTaskResult` class. + */ +@property (nonatomic, copy, nullable) NSArray *additionalTaskResults; + +/** + The array of result predicates. + + @discussion This property contains one result predicate for each of the step identifiers in the + `destinationStepIdentifiers` property. +*/ +@property (nonatomic, copy, readonly) NSArray *resultPredicates; + +/** + The array of destination step identifiers. It contains one step identifier for each of the + predicates in the `resultPredicates` parameter. + */ +@property (nonatomic, copy, readonly) NSArray *destinationStepIdentifiers; + +/** + The identifier of the step that is used if none of the result predicates match. + */ +@property (nonatomic, copy, readonly, nullable) NSString *defaultStepIdentifier; + +@end + + +/** + The `ORKDirectStepNavigationRule` class can be used to unconditionally jump to a destination step + specified by its identifier or to finish the task early. + */ +ORK_CLASS_AVAILABLE +@interface ORKDirectStepNavigationRule : ORKStepNavigationRule + +/* + The `init` and `new` methods are unavailable. + + `ORKStepNavigationRule` classes should be initialized with custom designated initializers on each + subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized direct-step navigation rule using the specified destination step identifier. + + @param destinationStepIdentifier The identifier of the destination step. Pass the + `ORKNullStepIdentifier` constant if you want to finish the + ongoing task when the direct-step navigation rule is + triggered. + + @return A direct-step navigation rule. + */ +- (instancetype)initWithDestinationStepIdentifier:(NSString *)destinationStepIdentifier NS_DESIGNATED_INITIALIZER; + +/** + Returns a new direct-step navigation rule initialized from data in a given unarchiver. + + @param aDecoder The coder from which to initialize the step navigation rule. + + @return A new direct-step navigation rule. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + The identifier of the destination step. + */ +@property (nonatomic, copy, readonly) NSString *destinationStepIdentifier; + +@end + + +/** + The `ORKSkipStepNavigationRule` class is the abstract base class for concrete skip step navigation + rules. + + Skip step navigation rules can be used within an `ORKNavigableOrderedTask` object. You assign skip + step navigation rules to be triggered before a task step is shown. Each step can have one skip rule + at most. + + Subclasses must implement the `stepShouldSkipWithTaskResult:` method, which returns whether the + step should be skipped. + + A concrete subclass is included: `ORKPredicateSkipStepNavigationRule`, which will skip the step + if the results of the ongoing task match the provided `resultPredicate`. + */ +ORK_CLASS_AVAILABLE +@interface ORKSkipStepNavigationRule : NSObject + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Returns whether the targeted step should skip. + + Subclasses must implement this method to calculate if the targeted step should skip based on the + passed task result. + + @param taskResult The up-to-date task result, used for calculating whether the task should + skip. + + @return YES if the step should skip. + */ +- (BOOL)stepShouldSkipWithTaskResult:(ORKTaskResult *)taskResult; + +@end + +ORK_CLASS_AVAILABLE +@interface ORKPredicateSkipStepNavigationRule : ORKSkipStepNavigationRule + +/* + The `init` and `new` methods are unavailable. + + `ORKStepNavigationRule` classes should be initialized with custom designated initializers on each + subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + Returns an initialized predicate skip step navigation rule using the specified result predicate. + + @param resultPredicate A result predicate. If the result predicate matches, the step + will skip. + + @return An initialized skip predicate step navigation rule. + */ +- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate NS_DESIGNATED_INITIALIZER; + +/** + Returns a new predicate step navigation rule that was initialized from data in the given + unarchiver. + + @param aDecoder The coder from which to initialize the step navigation rule. + + @return A new predicate skip step navigation rule. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + An optional array of additional task results. + + With this property, a task can have different navigation behavior depending on the results of + related tasks that the user may have already completed. The predicate skip step navigation rule can + use the question results within these tasks, in addition to the current task question results, to + match the result predicates. + + You must ensure that all the task result identifiers are unique and that they are different from + the ongoing task result identifier. Also ensure that no task result contains question + results with duplicate identifiers. Question results *can have* equal identifiers provided that + they belong to different task results. + + Each object in the array should be of the `ORKTaskResult` class. + */ +@property (nonatomic, copy, nullable) NSArray *additionalTaskResults; + +/** + The result predicate to match. + */ +@property (nonatomic, strong, readonly) NSPredicate *resultPredicate; + +@end + + +/** + The `ORKStepModifier` class is an abstract base class for an object that can be used to modify a step + if a given navigation rule is matched. + + Step modifiers can be used within an `ORKNavigableOrderedTask` object. You assign step modifiers + to be triggered after a task step is shown. Each step can have one step modifier at most. + */ +ORK_CLASS_AVAILABLE +@interface ORKStepModifier: NSObject + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Modify the steps for a task. + + @param step The step that is associated with this modifier + @param taskResult The current task result + */ +- (void)modifyStep:(ORKStep *)step withTaskResult:(ORKTaskResult *)taskResult; + +@end + + +/** + The `ORKKeyValueStepModifier` class is an class for an object that can be used to modify a step + if a given navigation rule is matched. + + Step modifiers can be used within an `ORKNavigableOrderedTask` object. You assign step modifiers + to be triggered after a task step is shown. Each step can have one step modifier at most. + */ +ORK_CLASS_AVAILABLE +@interface ORKKeyValueStepModifier: ORKStepModifier + +/* + The `init` and `new` methods are unavailable. + + `ORKStepNavigationRule` classes should be initialized with custom designated initializers on each + subclass. + */ ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +/** + The result predicate to match. + */ +@property (nonatomic, strong, readonly) NSPredicate *resultPredicate; + +/** + A key-value mapping to apply to the modified step if the result predicate matches. + The keys in this are assumed to map using key-value coding. + + See https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueCoding/ + */ +@property (nonatomic, strong, readonly) NSDictionary *keyValueMap; + +/** + Returns a new step modifier. + + @param resultPredicate The result predicate to use to determine if the step should be modified + @param keyValueMap The mapping dictionary for this object + @return A new step modifier + */ +- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate + keyValueMap:(NSDictionary *)keyValueMap NS_DESIGNATED_INITIALIZER; + +/** + Returns a new step modifier. + + @param aDecoder The coder from which to initialize the step navigation rule. + @return A new step modifier + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.m new file mode 100755 index 0000000..a1a161d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.m @@ -0,0 +1,597 @@ +/* + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepNavigationRule.h" +#import "ORKStepNavigationRule_Private.h" + +#import "ORKStep.h" +#import "ORKCollectionResult_Private.h" +#import "ORKResult.h" +#import "ORKResultPredicate.h" + +#import "ORKHelpers_Internal.h" + + +NSString *const ORKNullStepIdentifier = @"org.researchkit.step.null"; + +@implementation ORKStepNavigationRule + +- (instancetype)init { + if ([self isMemberOfClass:[ORKStepNavigationRule class]]) { + ORKThrowMethodUnavailableException(); + } + return [super init]; +} + +- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult { + @throw [NSException exceptionWithName:NSGenericException reason:@"You should override this method in a subclass" userInfo:nil]; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + return [super init]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) rule = [[[self class] allocWithZone:zone] init]; + return rule; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + return YES; +} + +@end + + +@interface ORKPredicateStepNavigationRule () + +@property (nonatomic, copy) NSArray *resultPredicates; +@property (nonatomic, copy) NSArray *destinationStepIdentifiers; +@property (nonatomic, copy) NSString *defaultStepIdentifier; + +@end + + +@implementation ORKPredicateStepNavigationRule + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +// Internal init without array validation, for serialization support +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers + defaultStepIdentifier:(NSString *)defaultStepIdentifier + validateArrays:(BOOL)validateArrays { + if (validateArrays) { + ORKThrowInvalidArgumentExceptionIfNil(resultPredicates); + ORKThrowInvalidArgumentExceptionIfNil(destinationStepIdentifiers); + + NSUInteger resultPredicatesCount = resultPredicates.count; + NSUInteger destinationStepIdentifiersCount = destinationStepIdentifiers.count; + if (resultPredicatesCount == 0) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"resultPredicates cannot be an empty array" userInfo:nil]; + } + if (resultPredicatesCount != destinationStepIdentifiersCount) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Each predicate in resultPredicates must have a destination step identifier in destinationStepIdentifiers" userInfo:nil]; + } + ORKValidateArrayForObjectsOfClass(resultPredicates, [NSPredicate class], @"resultPredicates objects must be of a NSPredicate class kind"); + ORKValidateArrayForObjectsOfClass(destinationStepIdentifiers, [NSString class], @"destinationStepIdentifiers objects must be of a NSString class kind"); + if (defaultStepIdentifier != nil && ![defaultStepIdentifier isKindOfClass:[NSString class]]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"defaultStepIdentifier must be of a NSString class kind or nil" userInfo:nil]; + } + } + self = [super init]; + if (self) { + _resultPredicates = [resultPredicates copy]; + _destinationStepIdentifiers = [destinationStepIdentifiers copy]; + _defaultStepIdentifier = [defaultStepIdentifier copy]; + } + + return self; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers + defaultStepIdentifier:(NSString *)defaultStepIdentifier { + return [self initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers + defaultStepIdentifier:defaultStepIdentifier + validateArrays:YES]; +} +#pragma clang diagnostic pop + +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers { + return [self initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers + defaultStepIdentifier:nil]; +} + +static NSArray *ORKLeafQuestionResultsFromTaskResult(ORKTaskResult *ORKTaskResult) { + NSMutableArray *leafResults = [NSMutableArray new]; + for (ORKResult *result in ORKTaskResult.results) { + if ([result isKindOfClass:[ORKCollectionResult class]]) { + [leafResults addObjectsFromArray:[(ORKCollectionResult *)result results]]; + } + } + return leafResults; +} + +// the results array should only contain objects that respond to the 'identifier' method (e.g., ORKResult objects). +// Usually you want all result objects to be of the same type. +static void ORKValidateIdentifiersUnique(NSArray *results, NSString *exceptionReason) { + NSCParameterAssert(results); + NSCParameterAssert(exceptionReason); + + NSArray *uniqueIdentifiers = [results valueForKeyPath:@"@distinctUnionOfObjects.identifier"]; + BOOL itemsHaveNonUniqueIdentifiers = (results.count != uniqueIdentifiers.count); + if (itemsHaveNonUniqueIdentifiers) { + @throw [NSException exceptionWithName:NSGenericException reason:exceptionReason userInfo:nil]; + } +} + +- (void)setAdditionalTaskResults:(NSArray *)additionalTaskResults { + for (ORKTaskResult *taskResult in additionalTaskResults) { + ORKValidateIdentifiersUnique(ORKLeafQuestionResultsFromTaskResult(taskResult), @"All question results should have unique identifiers"); + } + _additionalTaskResults = additionalTaskResults; +} + +- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult { + NSMutableArray *allTaskResults = [[NSMutableArray alloc] initWithObjects:taskResult, nil]; + if (_additionalTaskResults) { + [allTaskResults addObjectsFromArray:_additionalTaskResults]; + } + ORKValidateIdentifiersUnique(allTaskResults, @"All tasks should have unique identifiers"); + + NSString *destinationStepIdentifier = nil; + for (NSInteger i = 0; i < _resultPredicates.count; i++) { + NSPredicate *predicate = _resultPredicates[i]; + // The predicate can either have: + // - an ORKResultPredicateTaskIdentifierVariableName variable which will be substituted by the ongoing task identifier; + // - a hardcoded task identifier set by the developer (the substitutionVariables dictionary is ignored in this case) + if ([predicate evaluateWithObject:allTaskResults + substitutionVariables:@{ORKResultPredicateTaskIdentifierVariableName: taskResult.identifier}]) { + destinationStepIdentifier = _destinationStepIdentifiers[i]; + break; + } + } + return destinationStepIdentifier ? : _defaultStepIdentifier; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, resultPredicates, NSPredicate); + ORK_DECODE_OBJ_ARRAY(aDecoder, destinationStepIdentifiers, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, defaultStepIdentifier, NSString); + ORK_DECODE_OBJ_ARRAY(aDecoder, additionalTaskResults, ORKTaskResult); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, resultPredicates); + ORK_ENCODE_OBJ(aCoder, destinationStepIdentifiers); + ORK_ENCODE_OBJ(aCoder, defaultStepIdentifier); + ORK_ENCODE_OBJ(aCoder, additionalTaskResults); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) rule = [[[self class] allocWithZone:zone] initWithResultPredicates:ORKArrayCopyObjects(_resultPredicates) + destinationStepIdentifiers:ORKArrayCopyObjects(_destinationStepIdentifiers) + defaultStepIdentifier:[_defaultStepIdentifier copy] + validateArrays:YES]; + rule->_additionalTaskResults = ORKArrayCopyObjects(_additionalTaskResults); + return rule; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.resultPredicates, castObject.resultPredicates) + && ORKEqualObjects(self.destinationStepIdentifiers, castObject.destinationStepIdentifiers) + && ORKEqualObjects(self.defaultStepIdentifier, castObject.defaultStepIdentifier) + && ORKEqualObjects(self.additionalTaskResults, castObject.additionalTaskResults)); +} + +- (NSUInteger)hash { + return _resultPredicates.hash ^ _destinationStepIdentifiers.hash ^ _defaultStepIdentifier.hash ^ _additionalTaskResults.hash; +} + +@end + + +@interface ORKDirectStepNavigationRule () + +@property (nonatomic, copy) NSString *destinationStepIdentifier; + +@end + + +@implementation ORKDirectStepNavigationRule + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithDestinationStepIdentifier:(NSString *)destinationStepIdentifier { + ORKThrowInvalidArgumentExceptionIfNil(destinationStepIdentifier); + self = [super init]; + if (self) { + _destinationStepIdentifier = destinationStepIdentifier; + } + + return self; +} + +- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)ORKTaskResult { + return _destinationStepIdentifier; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, destinationStepIdentifier, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, destinationStepIdentifier); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + __typeof(self) rule = [[[self class] allocWithZone:zone] initWithDestinationStepIdentifier:[_destinationStepIdentifier copy]]; + return rule; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.destinationStepIdentifier, castObject.destinationStepIdentifier)); +} + +- (NSUInteger)hash { + return _destinationStepIdentifier.hash; +} + +@end + + +@implementation ORKSkipStepNavigationRule + +- (instancetype)init { + if ([self isMemberOfClass:[ORKSkipStepNavigationRule class]]) { + ORKThrowMethodUnavailableException(); + } + return [super init]; +} + +- (BOOL)stepShouldSkipWithTaskResult:(ORKTaskResult *)taskResult { + @throw [NSException exceptionWithName:NSGenericException reason:@"You should override this method in a subclass" userInfo:nil]; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + return [super init]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + typeof(self) rule = [[[self class] allocWithZone:zone] init]; + return rule; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + return YES; +} + +@end + + +@interface ORKPredicateSkipStepNavigationRule() + +@property (nonatomic) NSPredicate *resultPredicate; + +@end + + +@implementation ORKPredicateSkipStepNavigationRule + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate { + ORKThrowInvalidArgumentExceptionIfNil(resultPredicate); + self = [super init]; + if (self) { + _resultPredicate = resultPredicate; + } + + return self; +} + +- (void)setAdditionalTaskResults:(NSArray *)additionalTaskResults { + for (ORKTaskResult *taskResult in additionalTaskResults) { + ORKValidateIdentifiersUnique(ORKLeafQuestionResultsFromTaskResult(taskResult), @"All question results should have unique identifiers"); + } + _additionalTaskResults = additionalTaskResults; +} + +- (BOOL)stepShouldSkipWithTaskResult:(ORKTaskResult *)taskResult { + NSMutableArray *allTaskResults = [[NSMutableArray alloc] initWithObjects:taskResult, nil]; + if (_additionalTaskResults) { + [allTaskResults addObjectsFromArray:_additionalTaskResults]; + } + ORKValidateIdentifiersUnique(allTaskResults, @"All tasks should have unique identifiers"); + + // The predicate can either have: + // - an ORKResultPredicateTaskIdentifierVariableName variable which will be substituted by the ongoing task identifier; + // - a hardcoded task identifier set by the developer (the substitutionVariables dictionary is ignored in this case) + BOOL predicateDidMatch = [_resultPredicate evaluateWithObject:allTaskResults + substitutionVariables:@{ORKResultPredicateTaskIdentifierVariableName: taskResult.identifier}]; + return predicateDidMatch; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, resultPredicate, NSPredicate); + ORK_DECODE_OBJ_ARRAY(aDecoder, additionalTaskResults, ORKTaskResult); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, resultPredicate); + ORK_ENCODE_OBJ(aCoder, additionalTaskResults); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + typeof(self) rule = [[[self class] allocWithZone:zone] initWithResultPredicate:_resultPredicate]; + rule->_additionalTaskResults = ORKArrayCopyObjects(_additionalTaskResults); + return rule; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.resultPredicate, castObject.resultPredicate) + && ORKEqualObjects(self.additionalTaskResults, castObject.additionalTaskResults)); +} + +- (NSUInteger)hash { + return _resultPredicate.hash ^ _additionalTaskResults.hash; +} + +@end + + +@implementation ORKStepModifier + +- (instancetype)init { + if ([self isMemberOfClass:[ORKStepModifier class]]) { + ORKThrowMethodUnavailableException(); + } + return [super init]; +} + +- (void)modifyStep:(ORKStep *)step withTaskResult:(ORKTaskResult *)taskResult { + @throw [NSException exceptionWithName:NSGenericException reason:@"You should override this method in a subclass" userInfo:nil]; +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + return [super init]; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[[self class] allocWithZone:zone] init]; +} + +- (NSUInteger)hash { + return [[self class] hash]; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + return YES; +} + +@end + + +@implementation ORKKeyValueStepModifier + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate + keyValueMap:(NSDictionary *)keyValueMap { + ORKThrowInvalidArgumentExceptionIfNil(resultPredicate); + ORKThrowInvalidArgumentExceptionIfNil(keyValueMap); + self = [super init]; + if (self) { + _resultPredicate = [resultPredicate copy]; + _keyValueMap = ORKMutableDictionaryCopyObjects(keyValueMap); + } + return self; +} + +- (void)modifyStep:(ORKStep *)step withTaskResult:(ORKTaskResult *)taskResult { + + // The predicate can either have: + // - an ORKResultPredicateTaskIdentifierVariableName variable which will be substituted by the ongoing task identifier; + // - a hardcoded task identifier set by the developer (the substitutionVariables dictionary is ignored in this case) + BOOL predicateDidMatch = [_resultPredicate evaluateWithObject:@[taskResult] + substitutionVariables:@{ORKResultPredicateTaskIdentifierVariableName: taskResult.identifier}]; + if (predicateDidMatch) { + for (NSString *key in self.keyValueMap.allKeys) { + @try { + [step setValue:self.keyValueMap[key] forKey:key]; + } @catch (NSException *exception) { + NSAssert1(NO, @"You are attempting to set a key-value that is not key-value compliant. %@", exception); + } + } + } +} + +#pragma mark NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, resultPredicate, NSPredicate); + ORK_DECODE_OBJ_MUTABLE_DICTIONARY(aDecoder, keyValueMap, NSString, NSObject); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, resultPredicate); + ORK_ENCODE_OBJ(aCoder, keyValueMap); +} + +#pragma mark NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithResultPredicate:self.resultPredicate + keyValueMap:self.keyValueMap]; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.resultPredicate, castObject.resultPredicate) + && ORKEqualObjects(self.keyValueMap, castObject.keyValueMap)); +} + +- (NSUInteger)hash { + return _resultPredicate.hash ^ _keyValueMap.hash; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.swift new file mode 100755 index 0000000..cd1bdfb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule.swift @@ -0,0 +1,44 @@ +/* +Copyright (c) 2015, Ricardo Sánchez-Sáez. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import Foundation + +public extension ORKPredicateStepNavigationRule { + + convenience init(resultPredicatesAndDestinationStepIdentifiers tuples: [ (resultPredicate: NSPredicate, destinationStepIdentifier: String) ], defaultStepIdentifierOrNil: String? = nil ) { + var resultPredicates: [NSPredicate] = [] + var destinationStepIdentifiers: [String] = [] + for tuple in tuples { + resultPredicates.append(tuple.resultPredicate) + destinationStepIdentifiers.append(tuple.destinationStepIdentifier) + } + self.init(resultPredicates: resultPredicates, destinationStepIdentifiers: destinationStepIdentifiers, defaultStepIdentifier: defaultStepIdentifierOrNil, validateArrays: true) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Internal.h new file mode 100755 index 0000000..d64b348 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepNavigationRule_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKPredicateStepNavigationRule () + ++ (NSArray *)leafResultsFromTaskResult:(ORKTaskResult *)ORKTaskResult; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Private.h new file mode 100755 index 0000000..439679f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepNavigationRule_Private.h @@ -0,0 +1,68 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +// This 'Private' header is needed because ORKESerialization uses ORKPredicateStepNavigationRule's +// internal initializer in order to avoid argument array validation. +NS_ASSUME_NONNULL_BEGIN + +@interface ORKPredicateStepNavigationRule () + +/** + Returns an initialized predicate step navigation rule using the specified result predicates, + destination step identifiers, and an optional default step identifier. + + @param resultPredicates An array of result predicates. Each result predicate can match + one or more step results in the ongoing task. + @param destinationStepIdentifiers An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the `resultPredicates` parameter. + @param defaultStepIdentifier The identifier of the step which is used if none of the + result predicates match. If this argument is `nil` and none + of the predicates match, the default ordered task navigation + behavior takes place (that is, the task goes to the next step in + order). + @param validateArrays `YES` to throw an exception if result predicates or + destination step identifiers are `nil` or empty; `NO` to skip + their validation. + + @return An initialized predicate step navigation rule. + */ +- (instancetype)initWithResultPredicates:(NSArray *)resultPredicates + destinationStepIdentifiers:(NSArray *)destinationStepIdentifiers + defaultStepIdentifier:(nullable NSString *)defaultStepIdentifier + validateArrays:(BOOL)validateArrays NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.h new file mode 100755 index 0000000..74b2a94 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.h @@ -0,0 +1,85 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKBodyItem; +@class ORKLearnMoreInstructionStep; +@class ORKNavigationContainerView; + +ORK_CLASS_AVAILABLE + +@protocol ORKStepViewLearnMoreItemDelegate + +@required +- (void)stepViewLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep; + +@end + +@interface ORKStepView : UIView + +@property (nonatomic, nullable) UIImage *stepTopContentImage; + +@property (nonatomic) UIViewContentMode stepTopContentImageContentMode; + +@property (nonatomic, nullable) UIImage *auxiliaryImage; // Only underlayed when stepTopContentImage is added. + +@property (nonatomic) NSString *stepTitle; + +@property (nonatomic, nullable) NSString *stepText; + +@property (nonatomic, nullable) NSString *stepDetailText; + +@property (nonatomic) NSTextAlignment stepHeaderTextAlignment; + +@property (nonatomic) NSTextAlignment bodyTextAlignment; + +@property (nonatomic) BOOL buildInBodyItems; + +@property (nonatomic, nullable) UIImage *titleIconImage; + +@property (nonatomic) BOOL showScrollIndicator; + +@property (nonatomic) NSArray *bodyItems; + +@property (nonatomic, nullable) ORKNavigationContainerView *navigationFooterView; + +@property (nonatomic, weak) id delegate; + +@property (nonatomic) BOOL useExtendedPadding; + +- (void)pinNavigationContainerToBottom; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.m new file mode 100755 index 0000000..981eaaf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView.m @@ -0,0 +1,165 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKStepView_Private.h" +#import "ORKStepContentView_Private.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKSkin.h" + +@interface ORKStepView () + +@end + +@implementation ORKStepView + +- (instancetype)init { + self = [super init]; + if (self) { + self.isNavigationContainerScrollable = YES; + _stepTopContentImageContentMode = UIViewContentModeScaleAspectFit; + [self setupStepContentView]; + [self setupNavigationContainerView]; + } + return self; +} + +- (void)setupStepContentView { + if (!self.stepContentView) { + self.stepContentView = [ORKStepContentView new]; + } + self.stepContentView.delegate = self; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stepContentViewImageChanged:) name:ORKStepTopContentImageChangedKey object:nil]; +} + +- (void)stepContentViewImageChanged:(NSNotification *)notification { + +} + +- (void)setupNavigationContainerView { + if (!self.navigationFooterView) { + self.navigationFooterView = [ORKNavigationContainerView new]; + } + + if (_isNavigationContainerScrollable == NO) { + [self.navigationFooterView removeStyling]; + } +} + +- (void)setStepTopContentImage:(UIImage *)stepTopContentImage { + _stepTopContentImage = stepTopContentImage; +} + +- (void)setStepTopContentImageContentMode:(UIViewContentMode)stepTopContentImageContentMode { + _stepContentView.topContentImageView.contentMode = stepTopContentImageContentMode; +} + +- (void)setAuxiliaryImage:(UIImage *)auxiliaryImage { + _auxiliaryImage = auxiliaryImage; +} + +- (void)pinNavigationContainerToBottom { + _isNavigationContainerScrollable = NO; + [self placeNavigationContainerView]; +} + +- (void)placeNavigationContainerView { + +} + +- (void)setTitleIconImage:(UIImage *)titleIconImage { + _titleIconImage = titleIconImage; + [_stepContentView setTitleIconImage:_titleIconImage]; +} + +- (void)setStepTitle:(NSString *)stepTitle { + _stepTitle = stepTitle; + [_stepContentView setStepTitle:_stepTitle]; +} + +- (void)setStepText:(NSString *)stepText { + _stepText = stepText; + [_stepContentView setStepText:_stepText]; +} + +- (void)setStepDetailText:(NSString *)stepDetailText { + _stepDetailText = stepDetailText; + [_stepContentView setStepDetailText:_stepDetailText]; +} + +- (void)setStepHeaderTextAlignment:(NSTextAlignment)stepHeaderTextAlignment { + _stepHeaderTextAlignment = stepHeaderTextAlignment; + [_stepContentView setStepHeaderTextAlignment:_stepHeaderTextAlignment]; +} + +- (void)setBodyTextAlignment:(NSTextAlignment)bodyTextAlignment { + _bodyTextAlignment = bodyTextAlignment; + [_stepContentView setBodyTextAlignment:_bodyTextAlignment]; +} + +- (void)setBodyItems:(NSArray *)bodyItems { + _bodyItems = bodyItems; + [_stepContentView setBodyItems:_bodyItems]; +} + +- (void)setBuildInBodyItems:(BOOL)buildInBodyItems { + _buildInBodyItems = buildInBodyItems; + [_stepContentView setBuildsInBodyItems:_buildInBodyItems]; +} + + +- (void)setUseExtendedPadding:(BOOL)useExtendedPadding { + _useExtendedPadding = useExtendedPadding; + [_stepContentView setUseExtendedPadding:_useExtendedPadding]; +} + +- (UIImage *)topContentAndAuxiliaryImage { + if (!_auxiliaryImage) { + return _stepTopContentImage; + } + CGSize size = _auxiliaryImage.size; + UIGraphicsBeginImageContext(size); + + CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height); + + [_auxiliaryImage drawInRect:rect]; + [_stepTopContentImage drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +#pragma mark - ORKStepContentLearnMoreItemDelegate + +- (void)stepContentLearnMoreButtonPressed:(ORKLearnMoreInstructionStep *)learnMoreStep { + [_delegate stepViewLearnMoreButtonPressed:learnMoreStep]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.h new file mode 100755 index 0000000..0de5111 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.h @@ -0,0 +1,414 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import "ORKTask.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKEditableResult; +@class ORKRecorder; +@class ORKResult; +@class ORKReviewStep; +@class ORKStep; +@class ORKStepResult; +@class ORKStepViewController; +@class ORKTaskViewController; + +/** + An enumeration of values used in `ORKStepViewControllerDelegate` to indicate the direction of navigation + requested by the participant. + */ +typedef NS_ENUM(NSInteger, ORKStepViewControllerNavigationDirection) { + + /// Forward navigation. Indicates that the user tapped the Continue or Next button. + ORKStepViewControllerNavigationDirectionForward, + + /// Backward navigation. Indicates that the user tapped the Back button. + ORKStepViewControllerNavigationDirectionReverse +} ORK_ENUM_AVAILABLE; + + +/** + The primary implementer of the `ORKStepViewControllerDelegate` protocol is the + task view controller (`ORKTaskViewController`). The task view controller observes the messages + of the protocol to correctly update its `result` property, and to control navigation + through the task. + + If you present step view controllers outside of a task view controller, it + can be helpful to implement this protocol to facilitate navigation and + results collection. + */ +@protocol ORKStepViewControllerDelegate + +@required +/** + Tells the delegate when the user has done something that requires navigation, such as + tap the Back or a Next button, or enter a response to a nonoptional + survey question. + + @param stepViewController The step view controller providing the callback. + @param direction Direction of navigation requested. + */ +- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction; + +/** + Tells the delegate when a substantial change has occurred to the result. + + The result is always available in the step view controller. Although the result is continuously changing + while the step view controller is active (because the time stamp in the result property is different each time it's called), this method is called only when a substantive change + to the result occurs, such as when the user enters a survey answer or completes + an active step. + + In your implementation of this delegate method, you can collect the value of `result` from the step view controller. + + @param stepViewController The step view controller providing the callback. + */ +- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController; + +/** + Tells the delegate when a step fails due to an error. + + A step view controller can use this method to report its failure to the task view controller. + The task view controller sends the error to its delegate indicating that the task has failed (using `ORKTaskViewControllerFinishReasonFailed`). + Note that recorder errors are reported by calling the `ORKStepViewControllerDelegate` method `stepViewController:recorder:didFailWithError:`. + + @param stepViewController The step view controller providing the callback. + @param error The error detected. + */ +- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(nullable NSError *)error; + +/** + Tells the delegate when a recorder error has been detected during the step. + + Recorder errors can occur during active steps, usually due to the + unavailability of sensor data or disk space in which to record results. + + @param stepViewController The step view controller providing the callback. + @param recorder The recorder that detected the error. + @param error The error detected. + */ +- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error; + +@optional +/** + Tells the delegate that the step view controller's view is about to appear. + + This method is called from the step view controller's `viewWillAppear:` method. + You can use this method to customize the appearance of the step view + controller without subclassing it. + + @param stepViewController The step view controller providing the callback. +*/ +- (void)stepViewControllerWillAppear:(ORKStepViewController *)stepViewController; + +/** + Asks the delegate whether there is a previous step. + + If there is a previous step, the step view controller adds a Back button to its + navigation item; if not, no Back button is added to the navigation item. + + @param stepViewController The step view controller providing the callback. + + @return `YES` if a Back button should be visible; otherwise, `NO`. + */ +- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController; + +/** + Asks the delegate whether there is a next step. + + Depending on the result of the step, the step view controller can adjust the language for the + Next button. + + @param stepViewController The step view controller providing the callback. + + @return `YES` if there is a step following the current one; otherwise, `NO`. + */ +- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController; + +/** + Asks the delegate for the total amount of questions for the entire task and the position of the current step. + + Depending on the result of the step, the step view controller can adjust the language for the + Next button. + + @param stepViewController The step view controller providing the callback. + + @param currentStep The current step that is being presented. + + @return a struct + */ +- (ORKTaskTotalProgress)stepViewControllerTotalProgressInfoForStep:(ORKStepViewController *)stepViewController currentStep:(ORKStep *)currentStep; + +@end + + +/** + The `ORKStepViewController` class is a base class for view controllers that are + presented by an `ORKTaskViewController` object for the steps in a task. + + In the ResearchKit framework, each step collects some information or data from the user. + Typically, the task view controller instantiates the step view controller + before presenting the next step (`ORKStep`) in the task. + + When you create a new type of step, you usually have to subclass + `ORKStepViewController` to manage the step. For examples of subclasses, see + `ORKQuestionStepViewController` and `ORKFormStepViewController`. In contrast, the view + controller for an active step is typically a subclass of `ORKActiveStepViewController`, + because active steps include the concept of life cycle. + + If you are simply trying to change some of the runtime behaviors of `ORKStepViewController`, + it's usually not necessary to subclass it. Instead, implement the + `[ORKTaskViewControllerDelegate taskViewController:stepViewControllerWillAppear:]` method in + the `ORKTaskViewControllerDelegate` protocol, and modify the appropriate properties + of the step view controller. For example, to change the title of the Learn More + or Next buttons, set the `learnMoreButtonTitle` or `continueButtonTitle` + properties in your implementation of this delegate method. + */ +ORK_CLASS_AVAILABLE +@interface ORKStepViewController : UIViewController + +/** + Returns a new step view controller for the specified step. + + @param step The step to be presented. + + @return A newly initialized step view controller. + */ +- (instancetype)initWithStep:(nullable ORKStep *)step NS_DESIGNATED_INITIALIZER; + +/** + Returns a new step view controller for the specified step. + + @param step The step to be presented. + @param result The current step result for this step. + + @return A newly initialized step view controller. + */ +- (instancetype)initWithStep:(ORKStep *)step result:(nullable ORKResult *)result; + +/** + The step presented by the step view controller. + + If you use a storyboard to initialize the step view controller, `initWithStep:` isn't called, + so you need to set the `step` property directly before the step view controller is presented. + + Setting the value of `step` after the controller has been presented is an error that + generates an exception. + Modifying the value of `step` after the controller has been presented is an error that + has undefined results. + + Subclasses that override the setter of this property must call super. + */ +@property (nonatomic, strong, nullable) ORKStep *step; + +/** + The delegate of the step view controller. + + The delegate is usually the `ORKTaskViewController` object that presents the step view + controller. If you need to intercept the delegate methods, you can + assign an intermediary object as the delegate and forward the messages + to the task view controller. + */ +@property (nonatomic, weak, nullable) id delegate; + +/** + A localized string that represents the title of the Continue button. + + Most steps display a button that enables forward navigation. This button can have titles + such as Next, Continue, or Done. Use this property to override the forward navigationORKTableSection + button title for the step. + */ +@property (nonatomic, copy, nullable) NSString *continueButtonTitle; + +/** + A localized string that represents the title of the Learn More button. + + Many steps have a button that lets users view more information about the + step than can fit on the screen. Use this property to override the title + of the Learn More button for the step. + */ +@property (nonatomic, copy, nullable) NSString *learnMoreButtonTitle; + +/** + A localized string that represents the title of the "Skip" button. + + Many steps are optional and can be skipped. Set this property to override + the title of the Skip button for the step. Note that setting this property + has no effect if the Skip button is not visible, which is the case in a required question step. + */ +@property (nonatomic, copy, nullable) NSString *skipButtonTitle; + +/** + The back button item. + + The back button item controls the Back button displayed in the navigation bar when + the step view controller is current. + This property lets you control the appearance and target of the + Back button at runtime. + + When the value of the property is `nil`, the default Back button is displayed; otherwise passed Back button item is used . If you want to hide the back button, set it to a newly allocated `UIBarButtonItem` instance. + + The back button item is updated during view loading and when the value of the `step` property + is changed, but they are safe to set in the `taskViewController:stepViewControllerWillAppear:` delegate callback. + + Subclasses can safely modify this property any time after calling `viewWillAppear:` on super. + */ +@property (nonatomic, strong, nullable) UIBarButtonItem *backButtonItem; + +/** + The cancel button item. + + The cancel button item controls the Cancel button displayed in the navigation bar + when the step view controller is current. + This property lets you control the appearance and target of the + Cancel button at runtime. + + When the value of the property is `nil`, the Cancel button is not displayed; otherwise, the title, target, + and action associated with the Cancel button item are used (other properties of `UIBarButtonItem` + are ignored). + + The cancel button item is updated during view loading and when the value of the `step` property + is changed, but is safe to + set in the `taskViewController:stepViewControllerWillAppear:` delegate callback. + + Subclasses can safely modify this property any time after calling `viewWillAppear:` on super. + */ +@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem; + +/** + The current state of the result. (read-only) + + The task view controller uses this property to get the results for the + step, and to collate them into the task result. + + The current step result and any subsidiary results representing data collected + so far are available in this property. You can detect significant changes to the result, + such as when the user enters a new answer, using the + `stepViewControllerResultDidChange:` delegate callback. + + Subclasses *must* use this property to return the current results. + Subclasses *may* call super to obtain + a clean, empty result object appropriate for the step, to which they can + attach appropriate child results. + + The implementations of this method in the ResearchKit framework currently create a new + result object on every call, so do not call this method unless it is + actually necessary. + */ +@property (nonatomic, copy, readonly, nullable) ORKStepResult *result; + +/** + A boolean indicating if the step was skipped or not. + */ +@property (nonatomic, assign, readonly) BOOL wasSkipped; + +/** + Add a result to the step view controller's `ORKStepResult`. By default, the property for + the step view controller's result will instantiate a copy of the result each time it is + called. Therefore, the result cannot be mutated by adding a result to its result array. + + This method can be called by a delegate to add a result to a given step in a way that will + be retained by the step. + + @param result The result to add to the step results. + */ +- (void)addResult:(ORKResult*)result; + +/** + Returns a Boolean value indicating whether there is a previous step. + + This method is a convenience accessor that subclasses can call to make a delegate callback to + determine whether a previous step exists. Subclasses can also override this method if the step + view controller should always behave as if backward navigation is disabled. + + See also: `stepViewControllerHasPreviousStep:` + + @return `YES` if there is a previous step; otherwise, `NO`. + */ +- (BOOL)hasPreviousStep; + +/** + Returns a Boolean value indicating whether there is a next step. + + This method is a convenience method that subclasses can call to make a delegate callback to + determine whether a next step exists. + + See also: `stepViewControllerHasNextStep:` + + @return `YES` if there is a next step; otherwise, `NO`. + */ +- (BOOL)hasNextStep; + +/** + The presenting task view controller. (read-only) + */ +@property (nonatomic, weak, readonly, nullable) ORKTaskViewController *taskViewController; + +/** + Navigates forward to the next step. + + When a user taps a Next button, the information passes through this method. You can use this method as an override + point or a target action for a subclass. + */ +- (void)goForward; + +/** + Navigates backward to the previous step. + + When a user taps the Back button, the information passes through this method. You can use this method as an override + point or a target action for a subclass. + */ +- (void)goBackward; + +/** + This method is called when the user taps the skip button. By default, it calls `-goForward`. + */ +- (void)skipForward; + +/** + Control the activity indicator on the Continue buttom. + + @param showActivityIndicator Set this value to `true` to show an animating activity indicator to the left of the + Continue button. Set this value to `false` to hide the activity indicator. +*/ +- (void)showActivityIndicatorInContinueButton:(BOOL)showActivityIndicator; + +/** + A Boolean value indicating whether the view controller has been presented before. + */ +@property (nonatomic, readonly) BOOL hasBeenPresented; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.m new file mode 100755 index 0000000..e89c9de --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController.m @@ -0,0 +1,605 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepViewController_Internal.h" + +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKCollectionResult.h" +#import "ORKReviewStep_Internal.h" + +#import "ORKNavigationContainerView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKStepContentView.h" + +static const CGFloat iPadStepTitleLabelPadding = 15.0; +static const CGFloat iPadStepTitleLabelFontSize = 50.0; + +@interface ORKStepViewController () { + BOOL _hasBeenPresented; + BOOL _dismissing; + BOOL _presentingAlert; +} + +@property (nonatomic, strong,readonly) UIBarButtonItem *flexSpace; +@property (nonatomic, strong,readonly) UIBarButtonItem *fixedSpace; + +@end + + +@implementation ORKStepViewController { + UIView *_iPadBackgroundView; + UIView *_iPadContentView; + UILabel *_iPadStepTitleLabel; + NSArray *_iPadConstraints; +} + +- (void)initializeInternalButtonItems { + _internalContinueButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_NEXT", nil) style:UIBarButtonItemStylePlain target:self action:@selector(goForward)]; + _internalDoneButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_DONE", nil) style:UIBarButtonItemStyleDone target:self action:@selector(goForward)]; + _internalSkipButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_SKIP", nil) style:UIBarButtonItemStylePlain target:self action:@selector(skip:)]; + _backButtonItem = nil; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + [self initializeInternalButtonItems]; + } + return self; +} + +#pragma clang diagnostic pop + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithNibName:nil bundle:nil]; + if (self) { + _wasSkipped = false; + [self initializeInternalButtonItems]; + [self setStep:step]; + } + return self; +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + // The default implementation ignores the previous result. + return [self initWithStep:step]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.view.backgroundColor = ORKColor(ORKBackgroundColorKey); + if (!_shouldIgnoreiPadDesign && ORKNeedWideScreenDesign(self.view)) { + [self setupiPadBackgroundView]; + [self setupiPadContentView]; + [self setupiPadStepTitleLabel]; + [self setupiPadConstraints]; + } +} + +- (void)updateBarButtonItems { + if (self.shouldPresentInReview) { + self.navigationItem.leftBarButtonItem = self.cancelButtonItem; + self.navigationItem.rightBarButtonItem = self.internalDoneButtonItem; + } else { + self.navigationItem.leftBarButtonItem = self.backButtonItem; + self.navigationItem.rightBarButtonItem = self.cancelButtonItem; + } +} + +- (void)setShouldPresentInReview:(BOOL)shouldPresentInReview { + _shouldPresentInReview = shouldPresentInReview; + [self updateBarButtonItems]; +} + +- (void)setupiPadBackgroundView { + if (!_iPadBackgroundView) { + _iPadBackgroundView = [UIView new]; + } + [self.view addSubview:_iPadBackgroundView]; +} + +- (void)setupiPadContentView { + if (!_iPadContentView) { + _iPadContentView = [UIView new]; + } + [_iPadBackgroundView addSubview:_iPadContentView]; +} + +- (void)setupiPadStepTitleLabel { + if (!_iPadStepTitleLabel) { + _iPadStepTitleLabel = [UILabel new]; + } + _iPadStepTitleLabel.numberOfLines = 0; + _iPadStepTitleLabel.textAlignment = NSTextAlignmentNatural; + [_iPadStepTitleLabel setFont:[UIFont systemFontOfSize:iPadStepTitleLabelFontSize weight:UIFontWeightBold]]; + [_iPadStepTitleLabel setAdjustsFontSizeToFitWidth:YES]; + [_iPadBackgroundView addSubview:_iPadStepTitleLabel]; +} + +- (void)setiPadStepTitleLabelText:(NSString *)text { + if (_iPadStepTitleLabel) { + // [_iPadStepTitleLabel setText: text]; + } +} + +- (void)setiPadBackgroundViewColor:(UIColor *)color { + if (_iPadBackgroundView) { + // [_iPadBackgroundView setBackgroundColor:color]; + } +} + +- (void)setupiPadConstraints { + _iPadBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + _iPadContentView.translatesAutoresizingMaskIntoConstraints = NO; + _iPadStepTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + + if (_iPadConstraints) { + [NSLayoutConstraint deactivateConstraints:_iPadConstraints]; + } + + _iPadConstraints = @[ + [NSLayoutConstraint constraintWithItem:_iPadBackgroundView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_iPadBackgroundView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:ORKiPadBackgroundViewLeftRightPadding], + [NSLayoutConstraint constraintWithItem:_iPadBackgroundView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-ORKiPadBackgroundViewLeftRightPadding], + [NSLayoutConstraint constraintWithItem:_iPadBackgroundView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-ORKiPadBackgroundViewBottomPadding], + [NSLayoutConstraint constraintWithItem:_iPadStepTitleLabel + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:ORKiPadBackgroundViewBottomPadding], + [NSLayoutConstraint constraintWithItem:_iPadStepTitleLabel + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:iPadStepTitleLabelPadding], + [NSLayoutConstraint constraintWithItem:_iPadStepTitleLabel + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-iPadStepTitleLabelPadding], + [NSLayoutConstraint constraintWithItem:_iPadContentView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_iPadStepTitleLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:iPadStepTitleLabelPadding], + [NSLayoutConstraint constraintWithItem:_iPadContentView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:iPadStepTitleLabelPadding], + [NSLayoutConstraint constraintWithItem:_iPadContentView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:-iPadStepTitleLabelPadding], + [NSLayoutConstraint constraintWithItem:_iPadContentView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_iPadBackgroundView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-iPadStepTitleLabelPadding] + ]; + [NSLayoutConstraint activateConstraints:_iPadConstraints]; +} + +- (void)setupButtons { + if (self.hasNextStep == YES) { + self.continueButtonItem = _internalContinueButtonItem; + } else { + self.continueButtonItem = _internalDoneButtonItem; + } + + self.skipButtonItem = _internalSkipButtonItem; +} + +- (void)setStep:(ORKStep *)step { + if (_hasBeenPresented) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot set step after presenting step view controller" userInfo:nil]; + } + if (step && step.identifier == nil) { + ORK_Log_Debug("Step identifier should not be nil."); + } + + _step = step; + + [step validateParameters]; + + [self setupButtons]; + [self stepDidChange]; +} + +- (void)stepDidChange { +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + ORK_Log_Debug("%@", self); + + + // Required here (instead of viewDidLoad) because any custom buttons are set once the delegate responds to the stepViewControllerWillAppear, + // otherwise there is a minor visual glitch, where the original buttons are displayed on the UI for a short period. This is not placed after + // the delegate responds to the stepViewControllerWillAppear, so that the target from the button's item can be used, if the intention is to + // only modify the title of the button. + [self setupButtons]; + + if ([self.delegate respondsToSelector:@selector(stepViewControllerWillAppear:)]) { + [self.delegate stepViewControllerWillAppear:self]; + } + + if (!_step) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot present step view controller without a step" userInfo:nil]; + } + _hasBeenPresented = YES; + + // Set presentedDate on first time viewWillAppear + if (!self.presentedDate) { + self.presentedDate = [NSDate date]; + } + + // clear dismissedDate + self.dismissedDate = nil; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + _dismissing = YES; +} + +- (void)viewDidDisappear:(BOOL)animated { + + [super viewDidDisappear:animated]; + + // Set endDate if the current ORKStepViewController's view disappears, and is not the topViewController anymore + // That way, if the step view controller is just covered by a modal view, dismissedDate will not be set. + if (self.nextResponder == nil || + ([self.parentViewController isKindOfClass:[UINavigationController class]] + && ((UINavigationController *)self.parentViewController).topViewController != self)) { + self.dismissedDate = [NSDate date]; + } + _dismissing = NO; +} + +- (void)willNavigateDirection:(ORKStepViewControllerNavigationDirection)direction { +} + +- (void)setContinueButtonTitle:(NSString *)continueButtonTitle { + _continueButtonTitle = continueButtonTitle; + self.internalContinueButtonItem.title = continueButtonTitle; + self.internalDoneButtonItem.title = continueButtonTitle; + + self.continueButtonItem = self.internalContinueButtonItem; +} + +- (void)showActivityIndicatorInContinueButton:(BOOL)showActivityIndicator { + [_navigationFooterView showActivityIndicator:showActivityIndicator]; +} + +- (void)setLearnMoreButtonTitle:(NSString *)learnMoreButtonTitle { + self.learnMoreButtonItem.title = learnMoreButtonTitle; + self.learnMoreButtonItem = self.learnMoreButtonItem; +} + +- (NSString *)learnMoreButtonTitle { + return self.learnMoreButtonItem.title; +} + +- (void)setSkipButtonTitle:(NSString *)skipButtonTitle { + self.internalSkipButtonItem.title = skipButtonTitle; + self.skipButtonItem = self.internalSkipButtonItem; +} + +- (NSString *)skipButtonTitle { + return self.skipButtonItem.title; +} + +- (void)setBackButtonItem:(UIBarButtonItem *)backButton { + backButton.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + _backButtonItem = backButton; + [self updateBarButtonItems]; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButton { + _cancelButtonItem = cancelButton; + [self updateBarButtonItems]; +} + +- (BOOL)hasPreviousStep { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(stepViewControllerHasPreviousStep:)]) { + return [strongDelegate stepViewControllerHasPreviousStep:self]; + } + + return NO; +} + +- (BOOL)hasNextStep { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if (strongDelegate && [strongDelegate respondsToSelector:@selector(stepViewControllerHasNextStep:)]) { + return [strongDelegate stepViewControllerHasNextStep:self]; + } + + return NO; +} + +- (ORKStepResult *)result { + + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:self.step.identifier results:_addedResults ? : @[]]; + stepResult.startDate = self.presentedDate ? : [NSDate date]; + stepResult.endDate = self.dismissedDate ? : [NSDate date]; + + return stepResult; +} + +- (void)addResult:(ORKResult *)result { + ORKResult *copy = [result copy]; + if (_addedResults == nil) { + _addedResults = @[copy]; + } else { + NSUInteger idx = [_addedResults indexOfObject:copy]; + if (idx == NSNotFound) { + _addedResults = [_addedResults arrayByAddingObject:copy]; + } else { + NSMutableArray *results = [_addedResults mutableCopy]; + [results insertObject:copy atIndex:idx]; + _addedResults = [results copy]; + } + } +} + +- (void)notifyDelegateOnResultChange { + + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(stepViewControllerResultDidChange:)]) { + [strongDelegate stepViewControllerResultDidChange:self]; + } +} + +- (BOOL)hasBeenPresented { + return _hasBeenPresented; +} + ++ (UIInterfaceOrientationMask)supportedInterfaceOrientations { + // The default values for a view controller'€™s supported interface orientations is set to + // UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom. + UIInterfaceOrientationMask supportedOrientations = UIInterfaceOrientationMaskAllButUpsideDown; + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + supportedOrientations = UIInterfaceOrientationMaskAll; + } + return supportedOrientations; +} + +- (BOOL)isBeingReviewed { + return _parentReviewStep != nil; +} + +- (BOOL)readOnlyMode { + return self.isBeingReviewed && _parentReviewStep.isStandalone; +} + +#pragma mark - Action Handlers + +- (void)goForward { + _wasSkipped = false; + [self navigateForward]; +} + +- (void)navigateForward { + ORKStepViewControllerNavigationDirection direction = self.isBeingReviewed ? ORKStepViewControllerNavigationDirectionReverse : ORKStepViewControllerNavigationDirectionForward; + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + [strongDelegate stepViewController:self didFinishWithNavigationDirection:direction]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (void)goBackward { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + [strongDelegate stepViewController:self didFinishWithNavigationDirection:ORKStepViewControllerNavigationDirectionReverse]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (void)skip:(UIView *)sender { + if (self.isBeingReviewed && !self.readOnlyMode) { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_CLEAR_ANSWER", nil) + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *action) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self skipForward]; + }); + }]]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) + style:UIAlertActionStyleCancel + handler:nil + ]]; + alert.popoverPresentationController.sourceView = sender; + alert.popoverPresentationController.sourceRect = sender.bounds; + [self presentViewController:alert animated:YES completion:nil]; + } else { + [self skipForward]; + } +} + +- (void)skipForward { + _wasSkipped = true; + [self navigateForward]; +} + +- (UIView *)viewForiPadLayoutConstraints { + return _iPadContentView; +} + +- (ORKTaskViewController *)taskViewController { + // look to parent view controller for a task view controller + UIViewController *parentViewController = [self parentViewController]; + while (parentViewController && ![parentViewController isKindOfClass:[ORKTaskViewController class]]) { + parentViewController = [parentViewController parentViewController]; + } + return (ORKTaskViewController *)parentViewController; +} + +- (BOOL)showValidityAlertWithMessage:(NSString *)text { + return [self showValidityAlertWithTitle:ORKLocalizedString(@"RANGE_ALERT_TITLE", nil) message:text]; +} + +- (BOOL)showValidityAlertWithTitle:(NSString *)title message:(NSString *)message { + if (![title length] && ![message length]) { + // No alert if the value is empty + return NO; + } + if (_dismissing || ![self isViewLoaded] || !self.view.window) { + // No alert if not in view chain. + return NO; + } + + if (_presentingAlert) { + return NO; + } + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) + style:UIAlertActionStyleDefault + handler:nil]]; + + _presentingAlert = YES; + [self presentViewController:alert animated:YES completion:^{ + _presentingAlert = NO; + }]; + + return YES; +} + + +#pragma mark - UIStateRestoring + +static NSString *const _ORKStepIdentifierRestoreKey = @"stepIdentifier"; +static NSString *const _ORKPresentedDateRestoreKey = @"presentedDate"; +static NSString *const _ORKOutputDirectoryKey = @"outputDirectory"; +static NSString *const _ORKParentReviewStepKey = @"parentReviewStep"; +static NSString *const _ORKAddedResultsKey = @"addedResults"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_step.identifier forKey:_ORKStepIdentifierRestoreKey]; + [coder encodeObject:_presentedDate forKey:_ORKPresentedDateRestoreKey]; + [coder encodeObject:ORKBookmarkDataFromURL(_outputDirectory) forKey:_ORKOutputDirectoryKey]; + [coder encodeObject:_parentReviewStep forKey:_ORKParentReviewStepKey]; + [coder encodeObject:_addedResults forKey:_ORKAddedResultsKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + self.outputDirectory = ORKURLFromBookmarkData([coder decodeObjectOfClass:[NSData class] forKey:_ORKOutputDirectoryKey]); + + if (!self.step) { + // Just logging to the console in this case, since this can happen during a taskVC restoration of a dynamic task. + // The step VC will get restored, but then never added back to the hierarchy. + ORK_Log_Debug("%@",[NSString stringWithFormat:@"No step provided while restoring %@", NSStringFromClass([self class])]); + } + + self.presentedDate = [coder decodeObjectOfClass:[NSDate class] forKey:_ORKPresentedDateRestoreKey]; + self.restoredStepIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKStepIdentifierRestoreKey]; + + if (self.step && _restoredStepIdentifier && ![self.step.identifier isEqualToString:_restoredStepIdentifier]) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:[NSString stringWithFormat:@"Attempted to restore step with identifier %@ but got step identifier %@", _restoredStepIdentifier, self.step.identifier] + userInfo:nil]; + } + + self.parentReviewStep = [coder decodeObjectOfClass:[ORKReviewStep class] forKey:_ORKParentReviewStepKey]; + + _addedResults = [coder decodeObjectOfClass:[NSArray class] forKey:_ORKAddedResultsKey]; +} + ++ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder { + ORKStepViewController *viewController = [[[self class] alloc] initWithStep:nil]; + viewController.restorationIdentifier = identifierComponents.lastObject; + viewController.restorationClass = self; + return viewController; +} + +#pragma mark - Accessibility + +- (BOOL)accessibilityPerformEscape { + [self goBackward]; + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController_Internal.h new file mode 100755 index 0000000..5e6d3b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepViewController_Internal.h @@ -0,0 +1,99 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKNavigationContainerView; + +@interface ORKStepViewController () { + @protected ORKNavigationContainerView *_navigationFooterView; +} + +- (void)stepDidChange; + +@property (nonatomic, copy, nullable) NSURL *outputDirectory; +@property (nonatomic, copy, readonly, nullable) NSArray *addedResults; + +@property (nonatomic, strong, nullable) UIBarButtonItem *internalContinueButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *internalDoneButtonItem; + +@property (nonatomic, strong, nullable) UIBarButtonItem *internalSkipButtonItem; + +@property (nonatomic, strong, nullable) UIBarButtonItem *continueButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *learnMoreButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *skipButtonItem; + +@property (nonatomic, copy, nullable) NSDate *presentedDate; +@property (nonatomic, copy, nullable) NSDate *dismissedDate; + +@property (nonatomic, copy, nullable) NSString *restoredStepIdentifier; +@property (nonatomic, assign) BOOL shouldIgnoreiPadDesign; +@property (nonatomic) BOOL shouldPresentInReview; + ++ (UIInterfaceOrientationMask)supportedInterfaceOrientations; + +// this property is set to `YES` when the step is part of a standalone review step. If set to `YES it will prevent any user input that might change the step result. +@property (nonatomic, readonly) BOOL readOnlyMode; + +@property (nonatomic, readonly) BOOL isBeingReviewed; + +@property (nonatomic, nullable) ORKReviewStep* parentReviewStep; + +- (void)willNavigateDirection:(ORKStepViewControllerNavigationDirection)direction; + +- (void)notifyDelegateOnResultChange; + +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE; + +- (BOOL)showValidityAlertWithMessage:(NSString *)text; + +- (BOOL)showValidityAlertWithTitle:(NSString *)title message:(NSString *)message; + +- (void)initializeInternalButtonItems; + +// internal method for updating the bar button items. +- (void)updateBarButtonItems; + +// Use this view to layout iPad Constraints. +- (UIView *)viewForiPadLayoutConstraints; + +// internal method for updating title label for iPad designs. +- (void)setiPadStepTitleLabelText:(NSString *)text; + +// internal method for updating iPadBackgroundViewColor. +- (void)setiPadBackgroundViewColor:(UIColor *)color; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView_Private.h new file mode 100755 index 0000000..84544cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStepView_Private.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +#import + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStepContentView; +@interface ORKStepView () + +@property (nonatomic, nullable) ORKStepContentView *stepContentView; + +@property (nonatomic) BOOL isNavigationContainerScrollable; + +- (void)placeNavigationContainerView; + +- (UIImage *)topContentAndAuxiliaryImage; + +- (void)stepContentViewImageChanged:(NSNotification *)notification; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep_Private.h new file mode 100755 index 0000000..5902077 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKStep_Private.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKStep () + +/** + Returns the class that the task view controller should instantiate to display + this step. + + This method is used within the framework so that steps can define their + step view controller pairing. + + Outside the framework, developers should instantiate the required view + controller in their task view controller delegate to override the task + view controller's default. + */ ++ (Class)stepViewControllerClass; + +- (Class)stepViewControllerClass; + +@property (nonatomic, assign) BOOL shouldTintImages; + +// Whether to allow navigation back from this step. +@property (nonatomic, assign, readonly) BOOL allowsBackNavigation; + +@property (nonatomic, assign) BOOL useSurveyMode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.h new file mode 100755 index 0000000..737f679 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Step's details text under title. + */ +ORK_CLASS_AVAILABLE +@interface ORKSubheadlineLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.m new file mode 100755 index 0000000..0be7149 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSubheadlineLabel.m @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSubheadlineLabel.h" + +#import "ORKSkin.h" + + +@implementation ORKSubheadlineLabel + ++ (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + const CGFloat defaultSize = 15; + return [UIFont systemFontOfSize:[[descriptor objectForKey:UIFontDescriptorSizeAttribute] doubleValue] - defaultSize + ORKGetMetricForWindow(ORKScreenMetricFontSizeSubheadline, nil)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.h new file mode 100755 index 0000000..adae97a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.h @@ -0,0 +1,98 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKTableViewCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKQuestionStep; +@class ORKSurveyAnswerCell; + +@protocol ORKSurveyAnswerCellDelegate + +@required +- (void)answerCell:(ORKSurveyAnswerCell *)cell answerDidChangeTo:(id)answer dueUserAction:(BOOL)dueUserAction; +- (void)answerCell:(ORKSurveyAnswerCell *)cell invalidInputAlertWithMessage:(NSString *)input; +- (void)answerCell:(ORKSurveyAnswerCell *)cell invalidInputAlertWithTitle:(NSString *)title message:(NSString *)message; + +@end + + +@interface ORKSurveyAnswerCell : ORKTableViewCell { +@protected + id _answer; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString *)reuseIdentifier + step:(ORKQuestionStep *)step + answer:(id)answer + delegate:(id)delegate; + +@property (nonatomic, weak, nullable) ORKQuestionStep *step; + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, copy, nullable) id answer; + +// Gives an opportunity for cells to prevent navigation if the value has not been set +- (BOOL)shouldContinue; + +@end + + +@interface ORKSurveyAnswerCell (ORKSurveyAnswerCellInternal) + +- (void)prepareView; + +- (nullable UITextView *)textView; + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view; + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view; + +- (void)ork_setAnswer:(nullable id)answer; +- (void)answerDidChange; + ++ (BOOL)shouldDisplayWithSeparators; + +- (void)showValidityAlertWithMessage:(nullable NSString *)text; + +- (void)showValidityAlertWithTitle:(NSString *)title message:(NSString *)message; + +// Get full width layout for some subclass cells ++ (NSLayoutConstraint *)fullWidthLayoutConstraint:(UIView *)view; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.m new file mode 100755 index 0000000..791d54d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCell.m @@ -0,0 +1,229 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCell.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKSurveyAnswerCell () + +// Handle keyboard +@property (nonatomic) UIEdgeInsets cachedContentInsets; +@property (nonatomic) UIEdgeInsets cachedScrollIndicatorInsets; + +@end + + +@implementation ORKSurveyAnswerCell + +- (instancetype)initWithStyle:(UITableViewCellStyle)style + reuseIdentifier:(NSString *)reuseIdentifier + step:(ORKQuestionStep *)step + answer:(id)answer + delegate:(id)delegate { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + _delegate = delegate; + // Set _answer first to resolve the dependency loop between setStep and setAnswer. + _answer = answer; + self.step = step; + self.answer = answer; + self.clipsToBounds = YES; + } + return self; +} + +- (void)setStep:(ORKQuestionStep *)step { + _step = step; + [self prepareView]; +} + +- (void)prepareView { + if (self.textField != nil || self.textView != nil) { + [self registerForKeyboardNotifications]; + } +} + +- (UITextField *)textField { + return nil; +} + +- (BOOL)shouldContinue { + return YES; +} + +- (UITextView *)textView { + return nil; +} + +- (void)answerDidChange { + +} + ++ (BOOL)shouldDisplayWithSeparators { + return NO; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)ork_setAnswer:(id)answer { + _answer = [answer copy]; + [_delegate answerCell:self answerDidChangeTo:answer dueUserAction:YES]; +} + +- (void)setAnswer:(id)answer { + _answer = [answer copy]; + [self answerDidChange]; +} + +- (void)showValidityAlertWithMessage:(NSString *)text { + [self.delegate answerCell:self invalidInputAlertWithMessage:text]; +} + +- (void)showValidityAlertWithTitle:(NSString *)title message:(NSString *)message { + [self.delegate answerCell:self invalidInputAlertWithTitle:title message:message]; +} + +#pragma mark - KeyboardNotifications + +// Call this method somewhere in your view controller setup code. +- (void)registerForKeyboardNotifications { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillAppear:) + name:UIKeyboardWillShowNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification object:nil]; +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWillAppear:(NSNotification *)aNotification { + UIView *inputView = self.textView == nil ? self.textField : self.textView; + + if (inputView == nil) { + return; + } + + UITableViewCell *cell = ORKFirstObjectOfClass(UITableViewCell, inputView, superview); + UITableView *tableView = ORKFirstObjectOfClass(UITableView, cell, superview); + + _cachedContentInsets = tableView.contentInset; + _cachedScrollIndicatorInsets = tableView.scrollIndicatorInsets; + + NSDictionary *userInfo = aNotification.userInfo; + CGSize keyboardSize = ((NSValue *)userInfo[UIKeyboardFrameEndUserInfoKey]).CGRectValue.size; + keyboardSize.height = keyboardSize.height - 44; + + UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0); + + tableView.contentInset = contentInsets; + tableView.scrollIndicatorInsets = contentInsets; + + CGRect cellFrame = cell.frame; + CGPoint desiredOffset = cellFrame.origin; + + CGRect availableFrame = tableView.frame; + availableFrame.size.height -= keyboardSize.height; + + desiredOffset.y = cellFrame.origin.y - (availableFrame.size.height / 2); + + if (availableFrame.size.height > cellFrame.size.height) { + desiredOffset.y = cellFrame.origin.y - (availableFrame.size.height - cellFrame.size.height) - (cellFrame.size.height - 55); + } + desiredOffset.y = MAX(desiredOffset.y, 0); + + [tableView setContentOffset:desiredOffset animated:NO]; +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillHide:(NSNotification *)aNotification { + UIView *inputView = self.textView == nil ? self.textField : self.textView; + + if (inputView == nil) { + return; + } + + UITableView *tableView = ORKFirstObjectOfClass(UITableView, inputView, superview); + + [UIView animateWithDuration:2.0 + delay:0.0 + options:UIViewAnimationOptionCurveEaseInOut + animations:^ { + if (UIEdgeInsetsEqualToEdgeInsets(tableView.contentInset, _cachedContentInsets) == NO) { + tableView.contentInset = _cachedContentInsets; + } + + if (UIEdgeInsetsEqualToEdgeInsets(tableView.scrollIndicatorInsets, _cachedScrollIndicatorInsets) == NO) { + tableView.scrollIndicatorInsets = _cachedScrollIndicatorInsets; + } + } + completion:^(BOOL finished) { + //tableView.scrollEnabled = NO; + }]; + +} + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view { + NSLayoutConstraint *constaint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:[[self class] suggestedCellHeightForView:view]]; + constaint.priority = UILayoutPriorityDefaultHigh; + return @[constaint]; +} + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view { + return ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, view.window); +} + ++ (NSLayoutConstraint *)fullWidthLayoutConstraint:(UIView *)view { + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:10000]; + + widthConstraint.priority = UILayoutPriorityDefaultLow + 1; + return widthConstraint; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.h new file mode 100755 index 0000000..2c30558 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForImageSelection : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.m new file mode 100755 index 0000000..5f31b70 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForImageSelection.m @@ -0,0 +1,111 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForImageSelection.h" + +#import "ORKImageSelectionView.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKSurveyAnswerCellForImageSelection () + +@end + + +@implementation ORKSurveyAnswerCellForImageSelection { + ORKImageSelectionView *_selectionView; +} + +- (void)prepareView { + [super prepareView]; + + _selectionView = [[ORKImageSelectionView alloc] initWithImageChoiceAnswerFormat:(ORKImageChoiceAnswerFormat *)self.step.answerFormat answer:self.answer]; + _selectionView.delegate = self; + _selectionView.frame = self.bounds; + + [self addSubview:_selectionView]; + + _selectionView.translatesAutoresizingMaskIntoConstraints = NO; + + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = @{ @"selectionView": _selectionView }; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[selectionView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[selectionView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + NSLayoutConstraint *resistCompressingConstraint = [NSLayoutConstraint constraintWithItem:_selectionView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + resistCompressingConstraint.priority = UILayoutPriorityDefaultHigh; + [constraints addObject:resistCompressingConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +#pragma mark ORKImageSelectionViewDelegate +- (void)selectionViewSelectionDidChange:(ORKImageSelectionView *)view { + [self ork_setAnswer:view.answer]; +} + +- (void)answerDidChange { + [_selectionView setAnswer:self.answer]; +} + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view { + return @[]; +} + +#pragma mark Accessibility + +- (BOOL)isAccessibilityElement { + return NO; +} + +- (NSArray *)accessibilityElements { + return @[_selectionView]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.h new file mode 100755 index 0000000..d0b2fea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Brandon McQuilkin, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForLocation : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.m new file mode 100755 index 0000000..c9ca966 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForLocation.m @@ -0,0 +1,125 @@ +/* + Copyright (c) 2015, Brandon McQuilkin, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForLocation.h" + +#import "ORKAnswerTextField.h" +#import "ORKLocationSelectionView.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionStep_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@import MapKit; + + +@interface ORKSurveyAnswerCellForLocation () + +@end + + +@implementation ORKSurveyAnswerCellForLocation { + ORKLocationSelectionView *_selectionView; +} + +- (BOOL)becomeFirstResponder { + return [_selectionView becomeFirstResponder]; +} + +- (void)setStep:(ORKQuestionStep *)step { + [super setStep:step]; +} + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view { + return [ORKLocationSelectionView.class textFieldHeight] + [ORKLocationSelectionView.class textFieldBottomMargin]*2 + ORKGetMetricForWindow(ORKScreenMetricLocationQuestionMapHeight, nil); +} + +- (void)prepareView { + _selectionView = [[ORKLocationSelectionView alloc] initWithFormMode:NO + useCurrentLocation:((ORKLocationAnswerFormat *)self.step.answerFormat).useCurrentLocation + leadingMargin:self.separatorInset.left]; + _selectionView.delegate = self; + _selectionView.tintColor = self.tintColor; + [self addSubview:_selectionView]; + + [self setUpConstraints]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_selectionView); + ORKEnableAutoLayoutForViews([views allValues]); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_selectionView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_selectionView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + NSLayoutConstraint *resistsCompressingMapConstraint = [NSLayoutConstraint constraintWithItem:_selectionView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:20000.0]; + resistsCompressingMapConstraint.priority = UILayoutPriorityDefaultHigh; + [constraints addObject:resistsCompressingMapConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)answerDidChange { + ORKAnswerFormat *answerFormat = [self.step impliedAnswerFormat]; + ORKLocationAnswerFormat *locationAnswerFormat = ORKDynamicCast(answerFormat, ORKLocationAnswerFormat); + + _selectionView.answer = self.answer; + NSString *placeholder = locationAnswerFormat.placeholder ? : + (self.step.placeholder ? : ORKLocalizedString(@"PLACEHOLDER_TEXT_OR_NUMBER", nil)); + [_selectionView setPlaceholderText:placeholder]; +} + +- (void)locationSelectionViewDidChange:(ORKLocationSelectionView *)view { + [self ork_setAnswer:_selectionView.answer]; +} + +- (void)locationSelectionView:(ORKLocationSelectionView *)view didFailWithErrorTitle:(NSString *)title message:(NSString *)message { + [self showValidityAlertWithTitle:title message:message]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.h new file mode 100755 index 0000000..d03fba9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForNumber : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.m new file mode 100755 index 0000000..83fc7e2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForNumber.m @@ -0,0 +1,382 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForNumber.h" + +#import "ORKTextFieldView.h" +#import "ORKDontKnowButton.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionStep_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat ErrorLabelTopPadding = 4.0; +static const CGFloat DefaultPadding = 8.0; +static const CGFloat HorizontalPadding = 16.0; +static const CGFloat MinTextFieldViewHeight = 40.0; +static const CGFloat ErrorLabelBottomPadding = 10.0; +static const CGFloat DontKnowButtonTopBottomPadding = 16.0; + + +@interface ORKSurveyAnswerCellForNumber () + +@property (nonatomic, strong) ORKTextFieldView *textFieldView; +@property (nonatomic, strong) UILabel *errorLabel; + +@end + + +@implementation ORKSurveyAnswerCellForNumber { + NSNumberFormatter *_numberFormatter; + NSNumber *_defaultNumericAnswer; + NSMutableArray *constraints; + ORKDontKnowButton *_dontKnowButton; + UIView *_dividerView; + BOOL _dontKnowButtonActive; +} + +- (ORKUnitTextField *)textField { + return _textFieldView.textField; +} + +- (void)numberCell_initialize { + ORKQuestionType questionType = self.step.questionType; + _numberFormatter = ORKDecimalNumberFormatter(); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(localeDidChange:) name:NSCurrentLocaleDidChangeNotification object:nil]; + + _dontKnowButtonActive = NO; + + ORKNumericAnswerFormat *numericAnswerFormat = (ORKNumericAnswerFormat *)self.step.answerFormat; + + _textFieldView = [[ORKTextFieldView alloc] init]; + _textFieldView.hideUnitWhenAnswerEmpty = numericAnswerFormat.hideUnitWhenAnswerIsEmpty; + ORKUnitTextField *textField = _textFieldView.textField; + + textField.delegate = self; + textField.allowsSelection = YES; + + if (questionType == ORKQuestionTypeDecimal) { + textField.keyboardType = UIKeyboardTypeDecimalPad; + } else if (questionType == ORKQuestionTypeInteger) { + textField.keyboardType = UIKeyboardTypeNumberPad; + } + + [textField addTarget:self action:@selector(valueFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; + [self addSubview:_textFieldView]; + + _errorLabel = [UILabel new]; + [_errorLabel setTextColor: [UIColor redColor]]; + [self.errorLabel setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]]; + _errorLabel.numberOfLines = 0; + _errorLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_errorLabel]; + + if (numericAnswerFormat.shouldShowDontKnowButton) { + if (!_dontKnowButton) { + _dontKnowButton = [ORKDontKnowButton new]; + _dontKnowButton.customDontKnowButtonText = numericAnswerFormat.customDontKnowButtonText; + _dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO; + [_dontKnowButton addTarget:self action:@selector(dontKnowButtonWasPressed) forControlEvents:UIControlEventTouchUpInside]; + } + + if (!_dividerView) { + _dividerView = [UIView new]; + _dividerView.translatesAutoresizingMaskIntoConstraints = NO; + if (@available(iOS 13.0, *)) { + [_dividerView setBackgroundColor:[UIColor separatorColor]]; + } else { + [_dividerView setBackgroundColor:[UIColor lightGrayColor]]; + } + } + + [self addSubview:_dontKnowButton]; + [self addSubview:_dividerView]; + + if (self.answer == [ORKDontKnowAnswer answer]) { + [_dontKnowButton setButtonActive]; + } + } + + self.layoutMargins = ORKStandardLayoutMarginsForTableViewCell(self); + ORKEnableAutoLayoutForViews(@[_textFieldView]); + [self setUpConstraints]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)localeDidChange:(NSNotification *)note { + // On a locale change, re-format the value with the current locale + _numberFormatter.locale = [NSLocale currentLocale]; + [self answerDidChange]; +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { + self.layoutMargins = ORKStandardLayoutMarginsForTableViewCell(self); +} + +- (void)dontKnowButtonWasPressed { + if (![_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonActive]; + [_textFieldView.textField setText:nil]; + [_textFieldView endEditing:YES]; + [self textFieldShouldClear:_textFieldView.textField]; + } +} + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view { + return @[ + [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_dontKnowButton ?: _errorLabel + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:_dontKnowButton ? (DontKnowButtonTopBottomPadding - self.layoutMargins.bottom): (ErrorLabelBottomPadding - self.layoutMargins.bottom)] + ]; +} + +- (void)setUpConstraints { + _textFieldView.translatesAutoresizingMaskIntoConstraints = NO; + _errorLabel.translatesAutoresizingMaskIntoConstraints = NO; + _dividerView.translatesAutoresizingMaskIntoConstraints = NO; + _dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO; + + [[_textFieldView.topAnchor constraintEqualToAnchor:self.topAnchor constant:DefaultPadding] setActive:YES]; + [[_textFieldView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:HorizontalPadding] setActive:YES]; + [[_textFieldView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-HorizontalPadding] setActive:YES]; + [[_textFieldView.heightAnchor constraintGreaterThanOrEqualToConstant:MinTextFieldViewHeight] setActive:YES]; + + [[_errorLabel.topAnchor constraintEqualToAnchor:_textFieldView.bottomAnchor constant:ErrorLabelTopPadding] setActive:YES]; + [[_errorLabel.leftAnchor constraintEqualToAnchor:_textFieldView.leftAnchor] setActive:YES]; + [[_errorLabel.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + + if (_dontKnowButton) { + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + [[_dividerView.topAnchor constraintEqualToAnchor:_errorLabel.bottomAnchor constant:ErrorLabelBottomPadding] setActive:YES]; + [[_dividerView.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[_dividerView.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + [[_dividerView.heightAnchor constraintGreaterThanOrEqualToConstant:separatorHeight] setActive:YES]; + + [[_dontKnowButton.topAnchor constraintEqualToAnchor:_dividerView.bottomAnchor constant:DontKnowButtonTopBottomPadding] setActive:YES]; + [[_dontKnowButton.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + } +} + +- (BOOL)becomeFirstResponder { + return [[self textField] becomeFirstResponder]; +} + +- (void)prepareView { + if (self.textField == nil ) { + [self numberCell_initialize]; + } + + [self answerDidChange]; + + [super prepareView]; +} + +- (BOOL)isAnswerValid { + id answer = self.answer; + + if (answer == ORKNullAnswerValue() || answer == [ORKDontKnowAnswer answer]) { + return YES; + } + + ORKAnswerFormat *answerFormat = [self.step impliedAnswerFormat]; + ORKNumericAnswerFormat *numericFormat = (ORKNumericAnswerFormat *)answerFormat; + return [numericFormat isAnswerValidWithString:self.textField.text]; +} + +- (BOOL)shouldContinue { + BOOL isValid = [self isAnswerValid]; + + if (!isValid) { + [self updateErrorLabelWithMessage:ORKLocalizedString(@"RANGE_ALERT_TITLE", nil)]; + } + + return isValid; +} + +- (void)assignDefaultAnswer { + if (_defaultNumericAnswer) { + [self ork_setAnswer:_defaultNumericAnswer]; + if (self.textField) { + self.textField.text = [_numberFormatter stringFromNumber:_defaultNumericAnswer]; + } + } +} + +- (void)answerDidChange { + id answer = self.answer; + ORKAnswerFormat *answerFormat = [self.step impliedAnswerFormat]; + ORKNumericAnswerFormat *numericAnswerFormat = ORKDynamicCast(answerFormat, ORKNumericAnswerFormat); + + _defaultNumericAnswer = numericAnswerFormat.defaultNumericAnswer; + NSString *placeholder = numericAnswerFormat.placeholder ? : + (self.step.placeholder ? : ORKLocalizedString(@"PLACEHOLDER_TEXT_OR_NUMBER", nil)); + + self.textField.manageUnitAndPlaceholder = YES; + self.textField.unit = numericAnswerFormat.unit; + self.textField.placeholder = placeholder; + + if (answer == [ORKDontKnowAnswer answer]) { + [self dontKnowButtonWasPressed]; + } else if (answer != ORKNullAnswerValue() && ![_dontKnowButton isDontKnowButtonActive]) { + if (!answer) { + [self assignDefaultAnswer]; + } + else { + NSString *displayValue = answer; + if ([answer isKindOfClass:[NSNumber class]]) { + displayValue = [_numberFormatter stringFromNumber:answer]; + } + self.textField.text = displayValue; + } + } +} + +- (void)updateErrorLabelWithMessage:(NSString *)message { + NSString *separatorString = @":"; + NSString *stringtoParse = message ? : ORKLocalizedString(@"RANGE_ALERT_TITLE", @""); + NSString *parsedString = [stringtoParse componentsSeparatedByString:separatorString].firstObject; + + if (@available(iOS 13.0, *)) { + + NSString *errorMessage = [NSString stringWithFormat:@" %@", parsedString]; + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:errorMessage]; + NSTextAttachment *imageAttachment = [NSTextAttachment new]; + + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithPointSize:12 weight:UIImageSymbolWeightRegular scale:UIImageSymbolScaleMedium]; + UIImage *exclamationMarkImage = [UIImage systemImageNamed:@"exclamationmark.circle"]; + UIImage *configuredImage = [exclamationMarkImage imageByApplyingSymbolConfiguration:imageConfig]; + + imageAttachment.image = [configuredImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + + NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:imageAttachment]; + + [fullString insertAttributedString:imageString atIndex:0]; + + self.errorLabel.attributedText = fullString; + } else { + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:parsedString]; + self.errorLabel.attributedText = fullString; + } + + [self setUpConstraints]; +} + +#pragma mark - UITextFieldDelegate + +- (void)valueFieldDidChange:(UITextField *)textField { + ORKNumericAnswerFormat *answerFormat = (ORKNumericAnswerFormat *)[self.step impliedAnswerFormat]; + NSString *sanitizedText = [answerFormat sanitizedTextFieldText:[textField text] decimalSeparator:[_numberFormatter decimalSeparator]]; + textField.text = sanitizedText; + [self setAnswerWithText:textField.text]; + + BOOL isValid = [self isAnswerValid]; + + if (isValid && _errorLabel.attributedText != nil) { + _errorLabel.attributedText = nil; + [self setUpConstraints]; + } + + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonInactive]; + } +} + +- (BOOL)textFieldShouldClear:(UITextField *)textField { + if ([_dontKnowButton isDontKnowButtonActive]) { + [self ork_setAnswer:[ORKDontKnowAnswer answer]]; + } else { + [self ork_setAnswer:ORKNullAnswerValue()]; + } + return YES; +} + +- (void)setAnswerWithText:(NSString *)text { + BOOL updateInput = NO; + id answer = ORKNullAnswerValue(); + if (text.length) { + answer = [[NSDecimalNumber alloc] initWithString:text locale:[NSLocale currentLocale]]; + if (!answer) { + answer = ORKNullAnswerValue(); + updateInput = YES; + } + } + + [self ork_setAnswer:answer]; + if (updateInput) { + [self answerDidChange]; + } +} + +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + BOOL isValid = [self isAnswerValid]; + if (!isValid) { + + } + + return YES; +} + ++ (BOOL)shouldDisplayWithSeparators { + return NO; +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + BOOL isValid = [self isAnswerValid]; + + if (!isValid) { + [self updateErrorLabelWithMessage:ORKLocalizedString(@"RANGE_ALERT_TITLE", nil)]; + return NO; + } + + [self.textField resignFirstResponder]; + return YES; +} + +- (void)textFieldDidEndEditing:(UITextField *)textField { + NSString *text = self.textField.text; + [self setAnswerWithText:text]; +} + +- (void)textFieldDidBeginEditing:(UITextField *)textField { + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonInactive]; + } +} +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.h new file mode 100755 index 0000000..818e99b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForPicker : ORKSurveyAnswerCell + +// Delay creating the date picker until the view has appeared (to avoid animation stutter). +- (void)loadPicker; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.m new file mode 100755 index 0000000..a541b6e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForPicker.m @@ -0,0 +1,186 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForPicker.h" + +#import "ORKPicker.h" +#import "ORKDontKnowButton.h" + +#import "ORKQuestionStep_Internal.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKHelpers_Internal.h" + +static const CGFloat DividerViewTopPadding = 10.0; +static const CGFloat DontKnowButtonTopBottomPadding = 16.0; +static const CGFloat DontKnowButtonBottomPaddingOffset = 10.0; + + +@interface ORKSurveyAnswerCellForPicker () { + BOOL _valueChangedDueUserAction; +} + +@property (nonatomic, strong) id picker; + +@end + + +@implementation ORKSurveyAnswerCellForPicker { + ORKDontKnowButton *_dontKnowButton; + UIView *_dividerView; + BOOL _dontKnowButtonActive; +} + +- (void)prepareView { + [super prepareView]; + + [self loadPicker]; + _valueChangedDueUserAction = NO; +} + +- (void)loadPicker { + if (_picker == nil) { + _picker = [ORKPicker pickerWithAnswerFormat:[self.step impliedAnswerFormat] answer:self.answer delegate:self]; + + if (@available(iOS 13.0, *)) { + _picker.pickerView.backgroundColor = UIColor.secondarySystemGroupedBackgroundColor; + } + + [self.picker pickerWillAppear]; + + [self addSubview:_picker.pickerView]; + + if ([self.step.answerFormat shouldShowDontKnowButton] && !_dontKnowButton) { + [self setupDontKnowButton]; + } + + [self setupConstraintsForView:_picker.pickerView]; + } +} + +- (void)setupDontKnowButton { + if (!_dontKnowButton) { + _dontKnowButton = [ORKDontKnowButton new]; + _dontKnowButton.customDontKnowButtonText = self.step.answerFormat.customDontKnowButtonText; + [_dontKnowButton addTarget:self action:@selector(dontKnowButtonWasPressed) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:_dontKnowButton]; + } + + if (!_dividerView) { + _dividerView = [UIView new]; + if (@available(iOS 13.0, *)) { + [_dividerView setBackgroundColor:[UIColor separatorColor]]; + } else { + [_dividerView setBackgroundColor:[UIColor lightGrayColor]]; + } + [self addSubview:_dividerView]; + } + + _dontKnowButton.translatesAutoresizingMaskIntoConstraints = NO; + _dividerView.translatesAutoresizingMaskIntoConstraints = NO; + + if (self.answer == [ORKDontKnowAnswer answer]) { + [self dontKnowButtonWasPressed]; + } +} + +- (void)dontKnowButtonWasPressed { + if (![_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonActive]; + [self ork_setAnswer:[ORKDontKnowAnswer answer]]; + if (_picker) { + [_picker setAnswer:nil]; + } + } +} + +- (void)setupConstraintsForView:(UIView *)view { + if (view) { + view.translatesAutoresizingMaskIntoConstraints = NO; + + [[view.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + [[view.topAnchor constraintEqualToAnchor:self.topAnchor] setActive:YES]; + + if (_dontKnowButton) { + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + [[_dividerView.topAnchor constraintEqualToAnchor:view.bottomAnchor constant:DividerViewTopPadding] setActive:YES]; + [[_dividerView.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[_dividerView.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + [[_dividerView.heightAnchor constraintGreaterThanOrEqualToConstant:separatorHeight] setActive:YES]; + + [[_dontKnowButton.topAnchor constraintEqualToAnchor:_dividerView.bottomAnchor constant:DontKnowButtonTopBottomPadding] setActive:YES]; + [[_dontKnowButton.centerXAnchor constraintEqualToAnchor:self.centerXAnchor] setActive:YES]; + [[_dontKnowButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-DontKnowButtonTopBottomPadding + DontKnowButtonBottomPaddingOffset] setActive:YES]; + } else { + [[view.bottomAnchor constraintEqualToAnchor:self.bottomAnchor] setActive:YES]; + } + + } +} + +- (void)answerDidChange { + if (self.answer != [ORKDontKnowAnswer answer]) { + [_picker setAnswer:self.answer]; + } +} + +- (void)valueChangedDueUserAction:(BOOL)userAction { + if (userAction) { + _valueChangedDueUserAction = userAction; + if (_dontKnowButton && [_dontKnowButton isDontKnowButtonActive]) { + [_dontKnowButton setButtonInactive]; + } + } + + [self ork_setAnswer:_picker.answer]; +} + +- (void)ork_setAnswer:(id)answer { + // Override + _answer = [answer copy]; + [self.delegate answerCell:self answerDidChangeTo:answer dueUserAction:_valueChangedDueUserAction]; +} + +- (void)picker:(id)picker answerDidChangeTo:(id)answer { + [self valueChangedDueUserAction:YES]; +} + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view { + return 162.0 + 30.0; +} + +#pragma mark UIPickerViewDelegate + +- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { + assert(pickerView == _picker.pickerView); + return 32; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.h new file mode 100755 index 0000000..4422d52 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKSurveyAnswerCell.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForSES : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.m new file mode 100755 index 0000000..8b7ea99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForSES.m @@ -0,0 +1,72 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKSurveyAnswerCellForSES.h" +#import "ORKSESSelectionView.h" +#import "ORKQuestionStep.h" + + +@interface ORKSurveyAnswerCellForSES() + +@end +@implementation ORKSurveyAnswerCellForSES { + ORKSESSelectionView *_selectionView; +} + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view { + return UITableViewAutomaticDimension; +} + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view { + return @[]; +} + +- (void)prepareView { + [super prepareView]; + _selectionView = [[ORKSESSelectionView alloc] initWithAnswerFormat:(ORKSESAnswerFormat *)self.step.answerFormat answer:self.answer]; + _selectionView.delegate = self; + _selectionView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_selectionView]; + + [[_selectionView.topAnchor constraintEqualToAnchor:self.topAnchor] setActive:YES]; + [[_selectionView.leftAnchor constraintEqualToAnchor:self.leftAnchor] setActive:YES]; + [[_selectionView.rightAnchor constraintEqualToAnchor:self.rightAnchor] setActive:YES]; + [[self.bottomAnchor constraintEqualToAnchor:_selectionView.bottomAnchor] setActive:YES]; + +} + +#pragma mark - ORKSESSelectionViewDelegate + +- (void)buttonPressedAtIndex:(NSInteger)index { + _selectionView.answer = [NSNumber numberWithInteger:index]; + [self ork_setAnswer:_selectionView.answer]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.h new file mode 100755 index 0000000..36d7717 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForScale : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.m new file mode 100755 index 0000000..b48ef27 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForScale.m @@ -0,0 +1,112 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForScale.h" + +#import "ORKScaleSlider.h" +#import "ORKScaleSliderView.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionStep_Internal.h" + +#import "ORKSkin.h" + + +@interface ORKSurveyAnswerCellForScale () + +@property (nonatomic, strong) ORKScaleSliderView *sliderView; +@property (nonatomic, strong) id formatProvider; + +@end + + +@implementation ORKSurveyAnswerCellForScale + +- (id)formatProvider { + if (_formatProvider == nil) { + _formatProvider = (id)[self.step impliedAnswerFormat]; + } + return _formatProvider; +} + +- (void)prepareView { + [super prepareView]; + + id formatProvider = self.formatProvider; + + if (_sliderView == nil) { + _sliderView = [[ORKScaleSliderView alloc] initWithFormatProvider:formatProvider delegate:self]; + + [self addSubview:_sliderView]; + + self.sliderView.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *views = @{ @"sliderView": _sliderView }; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[sliderView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[sliderView]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + // Get a full width layout + NSLayoutConstraint *widthConstraint = [self.class fullWidthLayoutConstraint:_sliderView]; + [self addConstraints:@[widthConstraint]]; + } + + [self answerDidChange]; +} + +- (void)answerDidChange { + id formatProvider = self.formatProvider; + id answer = self.answer; + if (answer && answer != ORKNullAnswerValue()) { + [_sliderView setCurrentAnswerValue:answer]; + } else { + if (answer == nil && [formatProvider defaultAnswer]) { + [self.sliderView setCurrentAnswerValue:[formatProvider defaultAnswer]]; + [self ork_setAnswer:self.sliderView.currentAnswerValue]; + } else { + [self.sliderView setCurrentAnswerValue:nil]; + } + } +} + +- (NSArray *)suggestedCellHeightConstraintsForView:(UIView *)view { + return @[]; +} + +- (void)scaleSliderViewCurrentValueDidChange:(ORKScaleSliderView *)sliderView { + [self ork_setAnswer:sliderView.currentAnswerValue]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.h new file mode 100755 index 0000000..b301f3f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.h @@ -0,0 +1,48 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKSurveyAnswerCell.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKSurveyAnswerCellForText : ORKSurveyAnswerCell + +@end + + +@interface ORKSurveyAnswerCellForTextField : ORKSurveyAnswerCell + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.m new file mode 100755 index 0000000..c2ded05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyAnswerCellForText.m @@ -0,0 +1,553 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyAnswerCellForText.h" + +#import "ORKAnswerTextField.h" +#import "ORKAnswerTextView.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKQuestionStep_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +static const CGFloat TextViewTopPadding = 8.0; +static const CGFloat TextViewBottomPadding = 16.0; +static const CGFloat TextViewMinimumHeight = 140.0; +static const CGFloat ErrorLabelTopPadding = 4.0; +static const CGFloat ErrorLabelBottomPadding = 10.0; + +@interface ORKSurveyAnswerCellForText () + +@property (nonatomic, strong) ORKAnswerTextView *textView; + +@end + + +@implementation ORKSurveyAnswerCellForText { + NSInteger _maxLength; + NSString *_defaultTextAnswer; + UILabel *_textCountLabel; + UIButton *_clearTextViewButton; + UIView *_bottomSeperatorView; +} + +- (void)applyAnswerFormat { + ORKAnswerFormat *answerFormat = [self.step.answerFormat impliedAnswerFormat]; + + if ([answerFormat isKindOfClass:[ORKTextAnswerFormat class]]) { + ORKTextAnswerFormat *textAnswerFormat = (ORKTextAnswerFormat *)answerFormat; + _maxLength = [textAnswerFormat maximumLength]; + _defaultTextAnswer = textAnswerFormat.defaultTextAnswer; + self.textView.autocorrectionType = textAnswerFormat.autocorrectionType; + self.textView.autocapitalizationType = textAnswerFormat.autocapitalizationType; + self.textView.spellCheckingType = textAnswerFormat.spellCheckingType; + self.textView.keyboardType = textAnswerFormat.keyboardType; + self.textView.secureTextEntry = textAnswerFormat.secureTextEntry; + self.textView.textContentType = textAnswerFormat.textContentType; + + if (@available(iOS 12.0, *)) { + self.textView.passwordRules = textAnswerFormat.passwordRules; + } + } else { + _maxLength = 0; + } +} + +- (BOOL)becomeFirstResponder { + return [self.textView becomeFirstResponder]; +} + +- (void)setStep:(ORKQuestionStep *)step { + [super setStep:step]; + [self applyAnswerFormat]; +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { + self.layoutMargins = ORKStandardLayoutMarginsForTableViewCell(self); +} + +- (void)prepareView { + if (self.textView == nil ) { + self.preservesSuperviewLayoutMargins = NO; + self.layoutMargins = ORKStandardLayoutMarginsForTableViewCell(self); + + self.textView = [[ORKAnswerTextView alloc] initWithFrame:CGRectZero]; + + self.textView.delegate = self; + self.textView.editable = YES; + + [self addSubview:self.textView]; + + self.textView.placeholder = self.step.placeholder; + + ORKEnableAutoLayoutForViews(@[_textView]); + + [self applyAnswerFormat]; + + [self answerDidChange]; + + // Avoid exposing both this cell and its inner text view as elements to accessibility + // See also ORKCustomStepView -accessibilityElements + self.accessibilityElements = @[self.textView]; + } + + if (_bottomSeperatorView == nil) { + _bottomSeperatorView = [UIView new]; + + if (@available(iOS 13.0, *)) { + [_bottomSeperatorView setBackgroundColor:[UIColor separatorColor]]; + } else { + [_bottomSeperatorView setBackgroundColor:[UIColor lightGrayColor]]; + } + _bottomSeperatorView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_bottomSeperatorView]; + } + + if (_textCountLabel == nil) { + _textCountLabel = [UILabel new]; + if (@available(iOS 13.0, *)) { + [_textCountLabel setTextColor:[UIColor labelColor]]; + } else { + [_textCountLabel setTextColor:[UIColor grayColor]]; + } + if (_maxLength > 0) { + [self updateTextCountLabel]; + } else { + [_textCountLabel setHidden:YES]; + } + + _textCountLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview: _textCountLabel]; + } + + if (_clearTextViewButton == nil) { + _clearTextViewButton = [UIButton new]; + [_clearTextViewButton setTitle:ORKLocalizedString(@"BUTTON_CLEAR", nil) forState:UIControlStateNormal]; + [_clearTextViewButton setBackgroundColor:[UIColor clearColor]]; + [_clearTextViewButton setTitleColor:self.tintColor forState:UIControlStateNormal]; + [_clearTextViewButton addTarget:self action:@selector(clearTextView) forControlEvents:UIControlEventTouchUpInside]; + _clearTextViewButton.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview: _clearTextViewButton]; + } + + [self setUpConstraints]; + [super prepareView]; +} + +- (void)assignDefaultAnswer { + if (_defaultTextAnswer) { + [self ork_setAnswer:_defaultTextAnswer]; + if (self.textView) { + self.textView.text = _defaultTextAnswer; + } + } +} + +- (void)answerDidChange { + id answer = self.answer; + self.textView.text = (answer == ORKNullAnswerValue()) ? nil : self.answer; + [self assignDefaultAnswer]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray array]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_textView,_bottomSeperatorView, _textCountLabel); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-textViewTopPadding-[_textView(>=textViewMinimumHeight)]-textViewBottomPadding-[_bottomSeperatorView]-textViewBottomPadding-[_textCountLabel]-|" + options:(NSLayoutFormatOptions)0 + metrics:@{@"textViewTopPadding": @(TextViewTopPadding), @"textViewBottomPadding": @(TextViewBottomPadding), @"textViewMinimumHeight": @(TextViewMinimumHeight)} + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_textView]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_bottomSeperatorView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_bottomSeperatorView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:separatorHeight]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textCountLabel + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_textView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_textCountLabel + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:_clearTextViewButton + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_clearTextViewButton + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_textView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_clearTextViewButton + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_textCountLabel + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + + // Get full width layout + [constraints addObject:[self.class fullWidthLayoutConstraint:_textView]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + ++ (BOOL)shouldDisplayWithSeparators { + return NO; +} + +- (void)textDidChange { + [self ork_setAnswer:(self.textView.text.length > 0) ? self.textView.text : ORKNullAnswerValue()]; +} + +- (void)updateTextCountLabel { + if (_maxLength > 0) { + NSString *text = [[self.textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; + NSString *textCountLabelText = [[NSString alloc] initWithFormat:@"%lu/%li", (unsigned long)text.length, (long)_maxLength]; + _textCountLabel.text = textCountLabelText; + } +} + +- (void)clearTextView { + self.textView.text = @""; + [self textDidChange]; + [self updateTextCountLabel]; +} + +- (BOOL)shouldContinue { + ORKTextAnswerFormat *answerFormat = (ORKTextAnswerFormat *)[self.step impliedAnswerFormat]; + if (![answerFormat isAnswerValidWithString:self.textView.text]) { + [self showValidityAlertWithMessage:[[self.step impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:self.answer]]; + return NO; + } + return YES; +} + +#pragma mark - UITextViewDelegate + +- (void)textViewDidEndEditing:(UITextView *)textView { + [self textDidChange]; +} + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { + + NSString *string = [textView.text stringByReplacingCharactersInRange:range withString:text]; + + // Only need to validate the text if the user enters a character other than a backspace. + // For example, if the `textView.text = researchki` and the `string = researchkit`. + if (textView.text.length < string.length) { + + string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; + + if (_maxLength > 0 && string.length > _maxLength) { + [self showValidityAlertWithMessage:[[self.step impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:string]]; + return NO; + } + } + + return YES; +} + +- (void)textViewDidChange:(UITextView *)textView { + [self textDidChange]; + [self updateTextCountLabel]; +} + ++ (CGFloat)suggestedCellHeightForView:(UIView *)view { + return 180.0; +} + +@end + + +@interface ORKSurveyAnswerCellForTextField () + +@property (nonatomic, strong) ORKAnswerTextField *textField; +@property (nonatomic, strong) UILabel *errorLabel; + +@end + + +@implementation ORKSurveyAnswerCellForTextField { + NSMutableArray *constraints; + NSString *_defaultTextAnswer; +} + +- (BOOL)becomeFirstResponder { + return [self.textField becomeFirstResponder]; +} + +- (void)textFieldCell_initialize { + ORKAnswerFormat *answerFormat = [self.step impliedAnswerFormat]; + ORKTextAnswerFormat *textAnswerFormat = ORKDynamicCast(answerFormat, ORKTextAnswerFormat); + + _defaultTextAnswer = textAnswerFormat.defaultTextAnswer; + + _textField = [[ORKAnswerTextField alloc] initWithFrame:CGRectZero]; + _textField.text = @""; + + NSString *placeholder = textAnswerFormat.placeholder ? : + (self.step.placeholder ? : ORKLocalizedString(@"PLACEHOLDER_TEXT_OR_NUMBER", nil)); + _textField.placeholder = placeholder; + _textField.textAlignment = NSTextAlignmentNatural; + _textField.delegate = self; + _textField.keyboardType = UIKeyboardTypeDefault; + + [_textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; + + [self addSubview:_textField]; + ORKEnableAutoLayoutForViews(@[_textField]); + + if (_errorLabel == nil) { + _errorLabel = [UILabel new]; + [_errorLabel setTextColor: [UIColor redColor]]; + [self.errorLabel setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]]; + _errorLabel.numberOfLines = 0; + _errorLabel.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_errorLabel]; + } + + + [self setUpConstraints]; +} + +- (void)assignDefaultAnswer { + if (_defaultTextAnswer) { + [self ork_setAnswer:_defaultTextAnswer]; + if (self.textField) { + self.textField.text = _defaultTextAnswer; + } + } +} + +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { + self.contentView.layoutMargins = ORKStandardLayoutMarginsForTableViewCell(self); +} + +- (void)setUpConstraints { + if (constraints != nil) { + [NSLayoutConstraint deactivateConstraints:constraints]; + } + + constraints = [NSMutableArray new]; + NSDictionary *metrics = @{@"errorLabelTopPadding":@(ErrorLabelTopPadding), @"errorLabelBottomPadding":@(ErrorLabelBottomPadding)}; + NSDictionary *views = NSDictionaryOfVariableBindings(_textField, _errorLabel); + if (self.errorLabel.attributedText == nil) { + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_textField]-|" + options:NSLayoutFormatDirectionLeadingToTrailing | NSLayoutFormatAlignAllLeading + metrics:nil + views:views]]; + + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_errorLabel(==0)]" + options:0 + metrics:nil + views:views]]; + } else { + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_textField]-errorLabelTopPadding-[_errorLabel]-errorLabelBottomPadding-|" + options:NSLayoutFormatDirectionLeadingToTrailing | NSLayoutFormatAlignAllLeading + metrics:metrics + views:views]]; + } + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_textField]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_errorLabel + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_textField + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + // Get a full width layout + [constraints addObject:[self.class fullWidthLayoutConstraint:_textField]]; + [NSLayoutConstraint activateConstraints:constraints]; +} + ++ (BOOL)shouldDisplayWithSeparators { + return NO; +} + +- (void)prepareView { + if (self.textField == nil ) { + [self textFieldCell_initialize]; + } + + [self answerDidChange]; + + [super prepareView]; +} + +- (BOOL)shouldContinue { + ORKTextAnswerFormat *answerFormat = (ORKTextAnswerFormat *)[self.step impliedAnswerFormat]; + if (![answerFormat isAnswerValidWithString:self.textField.text]) { + [self updateErrorLabelWithMessage:[[self.step impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:self.textField.text]]; + return NO; + } + + return YES; +} + +- (void)answerDidChange { + id answer = self.answer; + ORKAnswerFormat *answerFormat = [self.step impliedAnswerFormat]; + ORKTextAnswerFormat *textFormat = (ORKTextAnswerFormat *)answerFormat; + if (textFormat) { + self.textField.autocorrectionType = textFormat.autocorrectionType; + self.textField.autocapitalizationType = textFormat.autocapitalizationType; + self.textField.spellCheckingType = textFormat.spellCheckingType; + self.textField.keyboardType = textFormat.keyboardType; + self.textField.secureTextEntry = textFormat.secureTextEntry; + self.textField.textContentType = textFormat.textContentType; + + if (@available(iOS 12.0, *)) { + self.textField.passwordRules = textFormat.passwordRules; + } + } + NSString *displayValue = (answer && answer != ORKNullAnswerValue()) ? answer : nil; + + if (displayValue == nil && _defaultTextAnswer) { + [self assignDefaultAnswer]; + } else { + self.textField.text = displayValue; + } +} + +- (void)textFieldDidChange:(UITextField *)textField { + NSString *text = self.textField.text; + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; +} + +- (void)updateErrorLabelWithMessage:(NSString *)message { + NSString *separatorString = @":"; + NSString *stringtoParse = message ? : ORKLocalizedString(@"RANGE_ALERT_TITLE", @""); + NSString *parsedString = [stringtoParse componentsSeparatedByString:separatorString].firstObject; + + if (@available(iOS 13.0, *)) { + + NSString *errorMessage = [NSString stringWithFormat:@" %@", parsedString]; + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:errorMessage]; + NSTextAttachment *imageAttachment = [NSTextAttachment new]; + + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithPointSize:12 weight:UIImageSymbolWeightRegular scale:UIImageSymbolScaleMedium]; + UIImage *exclamationMarkImage = [UIImage systemImageNamed:@"exclamationmark.circle"]; + UIImage *configuredImage = [exclamationMarkImage imageByApplyingSymbolConfiguration:imageConfig]; + + imageAttachment.image = [configuredImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + + NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:imageAttachment]; + + [fullString insertAttributedString:imageString atIndex:0]; + + self.errorLabel.attributedText = fullString; + } else { + NSMutableAttributedString *fullString = [[NSMutableAttributedString alloc] initWithString:parsedString]; + self.errorLabel.attributedText = fullString; + } + + [self setUpConstraints]; +} + +#pragma mark - UITextFieldDelegate + +- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { + ORKAnswerFormat *impliedFormat = [self.step impliedAnswerFormat]; + NSAssert([impliedFormat isKindOfClass:[ORKTextAnswerFormat class]], @"answerFormat should be ORKTextAnswerFormat type instance."); + + NSString *text = [textField.text stringByReplacingCharactersInRange:range withString:string]; + + // Only need to validate the text if the user enters a character other than a backspace. + // For example, if the `textField.text = researchki` and the `text = researchkit`. + if (textField.text.length < text.length) { + + text = [[text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@""]; + + NSInteger maxLength = [(ORKTextAnswerFormat *)impliedFormat maximumLength]; + + if (maxLength > 0 && text.length > maxLength) { + [self updateErrorLabelWithMessage:[[self.step impliedAnswerFormat] localizedInvalidValueStringWithAnswerString:text]]; + return NO; + } + } + + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; + + return YES; +} + +- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { + return YES; +} + +- (BOOL)textFieldShouldReturn:(UITextField *)textField { + [self.textField resignFirstResponder]; + return YES; +} + +- (void)textFieldDidEndEditing:(UITextField *)textField { + NSString *text = self.textField.text; + [self ork_setAnswer:text.length ? text : ORKNullAnswerValue()]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.h new file mode 100755 index 0000000..71944fc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN +@class ORKLearnMoreView; + +@interface ORKSurveyCardHeaderView: UIView + +- (instancetype) initWithTitle:(NSString *)title; + +- (instancetype) initWithTitle:(NSString *)title + detailText:(nullable NSString *)text + learnMoreView:(nullable ORKLearnMoreView *)learnMoreView + progressText:(nullable NSString *)progressText + tagText:(nullable NSString *)tagText; + +- (instancetype) initWithTitle:(NSString *)title + detailText:(nullable NSString *)text + learnMoreView:(nullable ORKLearnMoreView *)learnMoreView + progressText:(nullable NSString *)progressText + tagText:(nullable NSString *)tagText + showBorder:(BOOL)showBorder + hasMultipleChoiceItem:(BOOL)hasMultipleChoiceItem; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.m new file mode 100755 index 0000000..499db31 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKSurveyCardHeaderView.m @@ -0,0 +1,416 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKSurveyCardHeaderView.h" +#import "ORKSkin.h" +#import "ORKLearnMoreView.h" +#import "ORKTagLabel.h" +#import "ORKHelpers_Internal.h" + +static const CGFloat HeaderViewLabelTopBottomPadding = 6.0; +static const CGFloat TagBottomPadding = 4.0; +static const CGFloat TagTopPadding = 8.0; +static const CGFloat HeaderViewBottomPadding = 24.0; +static const CGFloat SelectAllThatApplyTopPadding = 24.0; +static const CGFloat SelectAllThatApplyBottomPadding = 6.0; + +@implementation ORKSurveyCardHeaderView { + + UIView *_headlineView; + NSString *_title; + UILabel *_titleLabel; + NSString *_detailText; + UILabel *_detailTextLabel; + ORKLearnMoreView *_learnMoreView; + NSString *_progressText; + UILabel *_progressLabel; + UILabel *_tagLabel; + UILabel *_selectAllThatApplyLabel; + BOOL _showBorder; + BOOL _hasMultipleChoiceItem; + NSString *_tagText; + CAShapeLayer *_headlineMaskLayer; + UIStackView *_headlineStackView; + NSArray *_headerViewConstraints; + NSArray *_learnMoreViewConstraints; +} + +- (instancetype)initWithTitle:(NSString *)title { + + self = [super init]; + if (self) { + _title = title; + [self setBackgroundColor:[UIColor clearColor]]; + [self setupHeaderView]; + [self setupConstraints]; + } + return self; +} + +- (instancetype)initWithTitle:(NSString *)title detailText:(nullable NSString *)text learnMoreView:(nullable ORKLearnMoreView *)learnMoreView progressText:(nullable NSString *)progressText tagText:(nullable NSString *)tagText { + + self = [super init]; + if (self) { + _title = title; + _detailText = text; + _learnMoreView = learnMoreView; + _progressText = progressText; + _showBorder = NO; + _hasMultipleChoiceItem = NO; + _tagText = tagText; + [self setBackgroundColor:[UIColor clearColor]]; + [self setupHeaderView]; + [self setupConstraints]; + } + return self; +} + +- (instancetype)initWithTitle:(NSString *)title detailText:(NSString *)text learnMoreView:(ORKLearnMoreView *)learnMoreView progressText:(NSString *)progressText tagText:(nullable NSString *)tagText showBorder:(BOOL)showBorder hasMultipleChoiceItem:(BOOL)hasMultipleChoiceItem { + + self = [super init]; + if (self) { + _title = title; + _detailText = text; + _learnMoreView = learnMoreView; + _progressText = progressText; + _showBorder = showBorder; + _tagText = tagText; + _hasMultipleChoiceItem = hasMultipleChoiceItem; + [self setBackgroundColor:[UIColor clearColor]]; + [self setupHeaderView]; + [self setupConstraints]; + } + return self; +} + +- (void)setupHeaderView { + [self setupHeadlineView]; + [self addSubview:_headlineView]; + + if (_tagText) { + [self setupTagLabel]; + [_headlineView addSubview:_tagLabel]; + } + + if (_progressText) { + [self setUpProgressLabel]; + [_headlineView addSubview:_progressLabel]; + } + + [self setupTitleLabel]; + [_headlineView addSubview:_titleLabel]; + + if (_detailText) { + [self setUpDetailTextLabel]; + [_headlineView addSubview:_detailTextLabel]; + } + + if (_learnMoreView) { + [_headlineView addSubview:_learnMoreView]; + } + + if (_hasMultipleChoiceItem) { + [self setupSelectAllThatApplyLabel]; + [_headlineView addSubview:_selectAllThatApplyLabel]; + } +} + +- (void)setupHeadlineView { + if (!_headlineView) { + _headlineView = [UIView new]; + } +} + +- (void)setupTitleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel new]; + } + _titleLabel.text = _title; + _titleLabel.numberOfLines = 0; + if (@available(iOS 13.0, *)) { + _titleLabel.textColor = [UIColor labelColor]; + } else { + _titleLabel.textColor = [UIColor blackColor]; + } + _titleLabel.lineBreakMode = NSLineBreakByWordWrapping; + _titleLabel.textAlignment = NSTextAlignmentNatural; + [_titleLabel setFont:[self titleLabelFont]]; +} + +- (void)setUpDetailTextLabel { + if (!_detailTextLabel) { + _detailTextLabel = [UILabel new]; + } + _detailTextLabel.text = _detailText; + _detailTextLabel.numberOfLines = 0; + _detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; + _detailTextLabel.textAlignment = NSTextAlignmentNatural; + [_detailTextLabel setFont:[self detailTextLabelFont]]; +} + +- (void)setUpProgressLabel { + if (!_progressLabel) { + _progressLabel = [UILabel new]; + } + _progressLabel.text = _progressText; + _progressLabel.numberOfLines = 0; + if (@available(iOS 13.0, *)) { + _progressLabel.textColor = [UIColor secondaryLabelColor]; + } else { + _progressLabel.textColor = [UIColor lightGrayColor]; + } + _progressLabel.textAlignment = NSTextAlignmentNatural; + [_progressLabel setFont:[self progressLabelFont]]; +} + +- (void)setupTagLabel { + if (!_tagLabel) { + _tagLabel = [ORKTagLabel new]; + } + _tagLabel.text = _tagText; +} + +- (void)setupSelectAllThatApplyLabel { + if (!_selectAllThatApplyLabel) { + _selectAllThatApplyLabel = [UILabel new]; + } + + _selectAllThatApplyLabel.text = ORKLocalizedString(@"AX_SELECT_ALL_THAT_APPLY", nil); + _selectAllThatApplyLabel.numberOfLines = 0; + if (@available(iOS 13.0, *)) { + _selectAllThatApplyLabel.textColor = [UIColor secondaryLabelColor]; + } else { + _selectAllThatApplyLabel.textColor = [UIColor lightGrayColor]; + } + _selectAllThatApplyLabel.textAlignment = NSTextAlignmentNatural; + [_selectAllThatApplyLabel setFont:[self selectAllThatApplyFont]]; +} + +- (UIFont *)titleLabelFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (UIFont *)detailTextLabelFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleSubheadline]; + return [UIFont fontWithDescriptor:descriptor size:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (UIFont *)progressLabelFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (UIFont *)selectAllThatApplyFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleFootnote]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (_headlineView) { + if (!_headlineMaskLayer) { + _headlineMaskLayer = [CAShapeLayer layer]; + } + for (CALayer *sublayer in [_headlineMaskLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + [_headlineMaskLayer removeFromSuperlayer]; + + _headlineMaskLayer.path = [UIBezierPath bezierPathWithRoundedRect: _headlineView.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){ORKCardDefaultCornerRadii, ORKCardDefaultCornerRadii}].CGPath; + + CAShapeLayer *foreLayer = [CAShapeLayer layer]; + UIColor *fillColor; + UIColor *borderColor; + if (@available(iOS 13.0, *)) { + fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + borderColor = UIColor.separatorColor; + } else { + fillColor = [UIColor whiteColor]; + borderColor = [UIColor ork_midGrayTintColor]; + } + + [foreLayer setFillColor:[fillColor CGColor]]; + CGRect foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, ORKCardDefaultBorderWidth, _headlineView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, _headlineView.bounds.size.height - ORKCardDefaultBorderWidth); + + CGFloat foreLayerCornerRadii = ORKCardDefaultCornerRadii >= ORKCardDefaultBorderWidth ? ORKCardDefaultCornerRadii - ORKCardDefaultBorderWidth : ORKCardDefaultCornerRadii; + + foreLayer.path = [UIBezierPath bezierPathWithRoundedRect: foreLayerBounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){foreLayerCornerRadii, foreLayerCornerRadii}].CGPath; + foreLayer.zPosition = 0.0f; + + [_headlineMaskLayer addSublayer:foreLayer]; + + if (_titleLabel.text) { + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + CGRect lineBounds = CGRectMake(0.0, _headlineView.bounds.size.height - 1.0, _headlineView.bounds.size.width, 0.5); + lineLayer.path = [UIBezierPath bezierPathWithRect:lineBounds].CGPath; + lineLayer.zPosition = 0.0f; + [lineLayer setFillColor:[borderColor CGColor]]; + + [_headlineMaskLayer addSublayer:lineLayer]; + } + + if (_showBorder) { + [_headlineMaskLayer setFillColor:[borderColor CGColor]]; + } else { + [_headlineMaskLayer setFillColor:[[UIColor clearColor] CGColor]]; + } + + [_headlineView.layer insertSublayer:_headlineMaskLayer atIndex:0]; + } + +} + +- (BOOL)useLearnMoreLeftAlignmentLayout { + return ((_learnMoreView != nil) && ([_learnMoreView isTextLink] == NO)); +} + +- (void)setupConstraints { + NSLayoutXAxisAnchor *trailingAnchor = [self useLearnMoreLeftAlignmentLayout] ? _learnMoreView.leadingAnchor : _headlineView.trailingAnchor; + NSLayoutYAxisAnchor *lastYAxisAnchor = self.topAnchor; + + _headlineView.translatesAutoresizingMaskIntoConstraints = NO; + + if (_progressLabel) { + _progressLabel.translatesAutoresizingMaskIntoConstraints = NO; + [[_progressLabel.topAnchor constraintEqualToAnchor:lastYAxisAnchor constant:ORKSurveyItemMargin] setActive:YES]; + [[_progressLabel.leadingAnchor constraintEqualToAnchor:_titleLabel.leadingAnchor] setActive:YES]; + [[_progressLabel.trailingAnchor constraintEqualToAnchor:trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + lastYAxisAnchor = _progressLabel.bottomAnchor; + } + + if (_tagLabel) { + CGFloat topPadding = _progressLabel ? TagTopPadding : ORKSurveyItemMargin; + _tagLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_tagLabel.topAnchor constraintEqualToAnchor:lastYAxisAnchor constant:topPadding].active = YES; + [_tagLabel.leadingAnchor constraintEqualToAnchor:_titleLabel.leadingAnchor].active = YES; + // FIXME:- learnMoreView gets compressed if we use _learnMoreView.leadingAnchor + [_tagLabel.trailingAnchor constraintLessThanOrEqualToAnchor:_headlineView.trailingAnchor constant:-ORKSurveyItemMargin].active = YES; + lastYAxisAnchor = _tagLabel.bottomAnchor; + } + + CGFloat titlePadding; + if (_tagLabel) { + titlePadding = TagBottomPadding; + } else if (_progressLabel) { + titlePadding = HeaderViewLabelTopBottomPadding; + } else { + titlePadding = ORKSurveyItemMargin; + } + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [[_titleLabel.topAnchor constraintEqualToAnchor:lastYAxisAnchor constant:titlePadding] setActive:YES]; + [[_titleLabel.leadingAnchor constraintEqualToAnchor:_headlineView.leadingAnchor constant:ORKSurveyItemMargin] setActive:YES]; + [[_titleLabel.trailingAnchor constraintEqualToAnchor:[self useLearnMoreLeftAlignmentLayout] ? _learnMoreView.leadingAnchor : _headlineView.trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + lastYAxisAnchor = _titleLabel.bottomAnchor; + NSLayoutYAxisAnchor *headlineViewBottomAnchor = _titleLabel.bottomAnchor; + + if (_detailTextLabel) { + _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; + + [[_detailTextLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor constant:HeaderViewLabelTopBottomPadding] setActive:YES]; + [[_detailTextLabel.leadingAnchor constraintEqualToAnchor:_titleLabel.leadingAnchor] setActive:YES]; + [[_detailTextLabel.trailingAnchor constraintEqualToAnchor:[self useLearnMoreLeftAlignmentLayout] ? _learnMoreView.leadingAnchor : _headlineView.trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + lastYAxisAnchor = _detailTextLabel.bottomAnchor; + headlineViewBottomAnchor = _detailTextLabel.bottomAnchor; + } + + if (_learnMoreView) { + [self setupLearnMoreViewConstraints]; + if ([_learnMoreView isTextLink] == YES) { + [_learnMoreView setLearnMoreButtonFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]]; + [_learnMoreView setLearnMoreButtonTextAlignment:NSTextAlignmentLeft]; + + [[_learnMoreView.topAnchor constraintEqualToAnchor:_detailTextLabel ? _detailTextLabel.bottomAnchor : _titleLabel.bottomAnchor constant:HeaderViewLabelTopBottomPadding] setActive:YES]; + [[_learnMoreView.leadingAnchor constraintEqualToAnchor:_titleLabel.leadingAnchor] setActive:YES]; + [[_learnMoreView.trailingAnchor constraintEqualToAnchor:[self useLearnMoreLeftAlignmentLayout] ? _learnMoreView.leadingAnchor : _headlineView.trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + + lastYAxisAnchor = _learnMoreView.bottomAnchor; + headlineViewBottomAnchor = _learnMoreView.bottomAnchor; + } + } + + if (_selectAllThatApplyLabel) { + _selectAllThatApplyLabel.translatesAutoresizingMaskIntoConstraints = NO; + [[_selectAllThatApplyLabel.topAnchor constraintEqualToAnchor:lastYAxisAnchor constant:SelectAllThatApplyTopPadding] setActive:YES]; + [[_selectAllThatApplyLabel.leadingAnchor constraintEqualToAnchor:_titleLabel.leadingAnchor] setActive:YES]; + [[_selectAllThatApplyLabel.trailingAnchor constraintEqualToAnchor:_titleLabel.trailingAnchor] setActive:YES]; + + headlineViewBottomAnchor = _selectAllThatApplyLabel.bottomAnchor; + } + + [[_headlineView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0.0] setActive:YES]; + [[_headlineView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:ORKCardLeftRightMarginForWindow(self.window)] setActive:YES]; + [[_headlineView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-ORKCardLeftRightMarginForWindow(self.window)] setActive:YES]; + [[_headlineView.bottomAnchor constraintEqualToAnchor: headlineViewBottomAnchor constant: _selectAllThatApplyLabel ? SelectAllThatApplyBottomPadding : HeaderViewBottomPadding] setActive:YES]; + + [[self.bottomAnchor constraintEqualToAnchor:_headlineView.bottomAnchor constant:0.0] setActive:YES]; +} + +- (void) setupLearnMoreViewConstraints { + if (_learnMoreViewConstraints) { + [NSLayoutConstraint deactivateConstraints:_learnMoreViewConstraints]; + } + _learnMoreView.translatesAutoresizingMaskIntoConstraints = NO; + + if ([_learnMoreView isTextLink] == NO) { + _learnMoreViewConstraints = @[ + [NSLayoutConstraint constraintWithItem:_learnMoreView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem: _titleLabel ? : _headlineView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:_titleLabel ? 0.0 : ORKSurveyItemMargin], + [NSLayoutConstraint constraintWithItem:_learnMoreView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem: _headlineView + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-ORKSurveyItemMargin], + [NSLayoutConstraint constraintWithItem:_learnMoreView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem: _learnMoreView + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant: 0.0] + ]; + } + + [NSLayoutConstraint activateConstraints:_learnMoreViewConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.h new file mode 100755 index 0000000..d7efd19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKStepView_Private.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKTableContainerView; +@class ORKStepContentView; + +@protocol ORKTableContainerViewDelegate + +@required +- (UITableViewCell *)currentFirstResponderCellForTableContainerView:(ORKTableContainerView *)tableContainerView; + +@end + +@class ORKNavigationContainerView; + +@interface ORKTableContainerView : ORKStepView + +@property (nonatomic, weak, nullable) id tableContainerDelegate; + +@property (nonatomic, strong, readonly) UITableView *tableView; + +/* + If tap off events should be accepted from outside this view's bounds, provide + the parent view where the tap off gesture recognizer should be attached. + */ +@property (nonatomic, weak, nullable) UIView *tapOffView; + +- (void)scrollCellVisible:(UITableViewCell *)cell animated:(BOOL)animated; + +- (instancetype)initWithStyle:(UITableViewStyle)style pinNavigationContainer:(BOOL)pinNavigationContainer; + +- (void)sizeHeaderToFit; + +- (void)resizeFooterToFit; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.m new file mode 100755 index 0000000..b853df3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableContainerView.m @@ -0,0 +1,432 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTableContainerView.h" +#import "ORKStepContentView_Private.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView.h" + +#import "ORKTitleLabel.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +#import "ORKBodyItem.h" +#import "ORKBodyContainerView.h" + +// Enable this define to see outlines and colors of all the views laid out at this level. +// #define LAYOUT_DEBUG + +@interface ORKTableContainerView () + +@end + + +@implementation ORKTableContainerView { + CGFloat _leftRightPadding; + UIView *_footerView; + NSLayoutConstraint *_bottomConstraint; + NSLayoutConstraint *_tableViewTopConstraint; + NSLayoutConstraint *_tableViewBottomConstraint; + + UIScrollView *_scrollView; + + UITapGestureRecognizer *_tapOffGestureRecognizer; + NSMutableArray *_navigationContainerConstraints; +} + +- (instancetype)init { + return [self initWithStyle:UITableViewStyleGrouped pinNavigationContainer:YES]; +} + +- (instancetype)initWithStyle:(UITableViewStyle)style pinNavigationContainer:(BOOL)pinNavigationContainer { + self = [super init]; + if (self) { + _leftRightPadding = ORKStepContainerLeftRightPaddingForWindow(self.window); + [self setupTableViewWithStyle:style]; + + _scrollView = _tableView; + self.isNavigationContainerScrollable = !pinNavigationContainer; + + [self addStepContentView]; + [self setupTableViewConstraints]; + + [self placeNavigationContainerView]; + + _tapOffGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOffAction:)]; + _tapOffGestureRecognizer.delegate = self; + [_tableView addGestureRecognizer:_tapOffGestureRecognizer]; + } + return self; +} + +- (void)setupTableViewWithStyle:(UITableViewStyle)style { + if (!_tableView) { + _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:style]; + } + _tableView.backgroundColor = ORKColor(ORKBackgroundColorKey); + _tableView.allowsSelection = YES; + _tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; + _tableView.preservesSuperviewLayoutMargins = YES; + _tableView.layer.masksToBounds = YES; + [_tableView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; + _tableView.scrollIndicatorInsets = ORKScrollIndicatorInsetsForScrollView(self); + [self addSubview:_tableView]; + [self setupFooterView]; +} + +- (void)placeNavigationContainerView { + [self.navigationFooterView removeFromSuperview]; + if (_navigationContainerConstraints) { + [NSLayoutConstraint deactivateConstraints:_navigationContainerConstraints]; + _navigationContainerConstraints = nil; + } + if (self.isNavigationContainerScrollable) { + [_footerView addSubview:self.navigationFooterView]; + } + else { + [self removeFooterView]; + [self addSubview:self.navigationFooterView]; + } + [self setupNavigationContainerViewConstraints]; + [self updateTableViewBottomConstraint]; +} + +- (void)setupNavigationContainerViewConstraints { + self.navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationContainerConstraints = [[NSMutableArray alloc] init]; + if (self.isNavigationContainerScrollable) { + + NSLayoutConstraint *_footerWidthConstraint = [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_footerView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]; + + _footerWidthConstraint.priority = UILayoutPriorityRequired-1; + [_navigationContainerConstraints addObject:_footerWidthConstraint]; + + [_navigationContainerConstraints addObject:[NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_footerView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + _bottomConstraint = [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_footerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + _bottomConstraint.priority = UILayoutPriorityDefaultHigh - 1; + [_navigationContainerConstraints addObject:_bottomConstraint]; + } + else { + [_navigationContainerConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + } + [NSLayoutConstraint activateConstraints:_navigationContainerConstraints]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self resizeFooterToFit]; + [self updateTableViewBottomConstraint]; +} + +- (void)addStepContentView { + _tableView.tableHeaderView = self.stepContentView; +} + +- (void)setupFooterView { + if (!_footerView) { + _footerView = [UIView new]; + } + _footerView.layoutMargins = UIEdgeInsetsZero; + _tableView.tableFooterView = _footerView; +} + +- (void)removeFooterView { + if (_footerView) { + [_footerView removeFromSuperview]; + _footerView = nil; + } + _tableView.tableFooterView = nil; +} + +- (void)resizeFooterToFit { +// This method would resize the tableFooterView, so that navigationContainerView can have appropriate height. + if (self.isNavigationContainerScrollable) { // only need to resize if navigationFooter is non-sticky to the bottom. + CGFloat navigationFooterHeight = self.navigationFooterView.bounds.size.height; + _tableView.tableFooterView = nil; + [_footerView removeFromSuperview]; //removing footerView so that table's contentSize does not account for navigationContainerView. + + /* + if tableViews content's height is less than tableView's height,the footerView will be pinned to the bottom of the screen. Otherwise, the footerView's height will be set the current navigationFooterView's height. + */ + if (_tableView.contentSize.height < _tableView.bounds.size.height) { + [self pinNavigationContainerToBottom]; + } else { + CGFloat requiredTableFooterHeight = navigationFooterHeight; + + CGRect footerBounds = CGRectMake(0.0, 0.0, _tableView.bounds.size.width, requiredTableFooterHeight); + [_footerView setBounds:footerBounds]; + _tableView.tableFooterView = _footerView; + } + } + +} + +- (void)sizeHeaderToFit { + CGFloat width = self.stepContentView.bounds.size.width > CGFLOAT_MIN ? self.stepContentView.bounds.size.width : self.bounds.size.width; + CGFloat padding = [[self stepContentView] useExtendedPadding] ? ORKStepContainerExtendedLeftRightPaddingForWindow(self.window) : ORKStepContainerLeftRightPaddingForWindow(self.window); + + CGFloat preferredWidth = (width - (padding * 2)); + [self.stepContentView.titleLabel setPreferredMaxLayoutWidth:preferredWidth]; + [self.stepContentView.textLabel setPreferredMaxLayoutWidth:preferredWidth]; + [self.stepContentView.detailTextLabel setPreferredMaxLayoutWidth:preferredWidth]; + + CGFloat estimatedHeight = [self.stepContentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; + CGRect bounds = CGRectMake(0.0, 0.0, self.stepContentView.bounds.size.width, self.stepContentView.bounds.size.height); + bounds.size.height = estimatedHeight; + [self.stepContentView setBounds:bounds]; +} + +- (void)setTapOffView:(UIView *)tapOffView { + _tapOffView = tapOffView; + + [_tapOffGestureRecognizer.view removeGestureRecognizer:_tapOffGestureRecognizer]; + + _tapOffGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOffAction:)]; + _tapOffGestureRecognizer.delegate = self; + [(tapOffView ? : _tableView) addGestureRecognizer:_tapOffGestureRecognizer]; +} + +- (void)setupTableViewConstraints { + _tableView.translatesAutoresizingMaskIntoConstraints = NO; + self.stepContentView.translatesAutoresizingMaskIntoConstraints = NO; + [self setTableViewTopConstraint]; + [self setTableViewBottomConstraint]; + [NSLayoutConstraint activateConstraints:@[ + _tableViewTopConstraint, + [NSLayoutConstraint constraintWithItem:_tableView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_tableView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:self.stepContentView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_tableView + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0] + ]]; +} + +- (void)setTableViewTopConstraint { + _tableViewTopConstraint = [NSLayoutConstraint constraintWithItem:_tableView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.stepTopContentImage ? self : self.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; +} + +- (void)updateTableViewTopConstraint { + if (_tableViewTopConstraint && _tableViewTopConstraint.isActive) { + [NSLayoutConstraint deactivateConstraints:@[_tableViewTopConstraint]]; + } + [self setTableViewTopConstraint]; + [NSLayoutConstraint activateConstraints:@[_tableViewTopConstraint]]; +} + +- (void)stepContentViewImageChanged:(NSNotification *)notification { + [super stepContentViewImageChanged:notification]; + [self updateTableViewTopConstraint]; +} + +- (void)setTableViewBottomConstraint { + CGFloat bottomConstant = (self.isNavigationContainerScrollable == YES) ? 0 : -self.navigationFooterView.frame.size.height; + _tableViewBottomConstraint = [NSLayoutConstraint constraintWithItem:_tableView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:bottomConstant]; +} + +- (void)updateTableViewBottomConstraint { + if (_tableViewBottomConstraint) { + [NSLayoutConstraint deactivateConstraints:@[_tableViewBottomConstraint]]; + } + [self setTableViewBottomConstraint]; + [NSLayoutConstraint activateConstraints:@[_tableViewBottomConstraint]]; +} + +- (BOOL)view:(UIView *)view hasFirstResponderOrTableViewCellContainingPoint:(CGPoint)point { + UIView *subview = [_tableView hitTest:point withEvent:nil]; + BOOL viewIsChildOfFirstResponder = NO; + while (subview) { + // Ignore table view cells, since first responder will be manually managed for taps on them + if ([subview isFirstResponder] || [subview isKindOfClass:[UITableViewCell class]]) { + viewIsChildOfFirstResponder = YES; + break; + } + subview = [subview superview]; + } + return viewIsChildOfFirstResponder; +} + +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + BOOL shouldReceiveTouch = [self view:_tableView hasFirstResponderOrTableViewCellContainingPoint:[touch locationInView:_tableView]]; + return !shouldReceiveTouch; +} + +- (void)tapOffAction:(UITapGestureRecognizer *)recognizer { + // On a tap, dismiss the keyboard if the tap was not inside a view that is first responder or a child of a first responder. + BOOL viewIsChildOfFirstResponder = [self view:_tableView hasFirstResponderOrTableViewCellContainingPoint:[recognizer locationInView:_tableView]]; + + if (!viewIsChildOfFirstResponder) { + [_tableView endEditing:NO]; + } +} + +- (CGSize)keyboardIntersectionSizeFromNotification:(NSNotification *)notification { + CGRect keyboardFrame = [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + keyboardFrame = [self convertRect:keyboardFrame fromView:nil]; + + CGRect scrollFrame = self.bounds; + + // The origin of this is in our superview's coordinate system, but I don't think + // we actually use the origin - so just return the size. + CGRect intersectionFrame = CGRectIntersection(scrollFrame, keyboardFrame); + return intersectionFrame.size; +} + +- (void)scrollCellVisible:(UITableViewCell *)cell animated:(BOOL)animated { + if (cell == nil) { + return; + } + + UIScrollView *scrollView = _scrollView; + + CGFloat visibleHeight = (scrollView.bounds.size.height - scrollView.contentInset.bottom); + CGRect visibleRect = CGRectMake(0, scrollView.contentOffset.y, scrollView.bounds.size.width, visibleHeight); + CGRect desiredRect = [scrollView convertRect:cell.bounds fromView:cell]; + + CGRect bounds = scrollView.bounds; + CGFloat offsetY = bounds.origin.y; + BOOL containByVisibleRect = CGRectContainsRect(visibleRect, desiredRect); + + if (containByVisibleRect == NO) { + if (CGRectGetHeight(desiredRect) > CGRectGetHeight(visibleRect)) { + CGFloat desiredCenterY = CGRectGetMidY(desiredRect); + offsetY = desiredCenterY - visibleRect.size.height * 0.5; + } else { + if (CGRectGetMinY(desiredRect) < CGRectGetMinY(visibleRect)) { + offsetY = CGRectGetMinY(desiredRect); + } else { + offsetY = CGRectGetMinY(desiredRect) - (CGRectGetHeight(visibleRect) - CGRectGetHeight(desiredRect)); + } + } + offsetY = MAX(offsetY, 0); + } + + // If there's room, we'd like to leave space below so you can tap on the next cell + // Only go 3/4 of a cell extra; otherwise user might think they tapped the wrong cell + CGFloat desiredExtraSpace = floor(ORKGetMetricForWindow(ORKScreenMetricTextFieldCellHeight, self.window) * (3 / 4.0)); + CGFloat visibleSpaceAboveDesiredRect = CGRectGetMinY(desiredRect) - offsetY; + CGFloat visibleSpaceBelowDesiredRect = offsetY + visibleHeight - CGRectGetMaxY(desiredRect); + if ((visibleSpaceAboveDesiredRect > 0) && (visibleSpaceBelowDesiredRect < desiredExtraSpace)) { + CGFloat additionalOffset = MIN(visibleSpaceAboveDesiredRect, desiredExtraSpace - visibleSpaceBelowDesiredRect); + offsetY += additionalOffset; + offsetY = MAX(offsetY, 0); + } + + if (offsetY != bounds.origin.y) { + bounds.origin.y = offsetY; + + if (animated) { + [UIView animateWithDuration:0.3 animations:^{ + scrollView.bounds = bounds; + }]; + } else { + scrollView.bounds = bounds; + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.h new file mode 100755 index 0000000..90b5aec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.h @@ -0,0 +1,224 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, ORKBulletType) { + ORKBulletTypeNone = 0, + ORKBulletTypeCircle, + ORKBulletTypeImage, + ORKBulletTypeNumber +} ORK_ENUM_AVAILABLE; + +/** + The `ORKTableStepSource` is a protocol that can be used for presenting a list of model + objects in a UITableView. Any `ORKStep` subclass that implements this protocol can be used with + an `ORKTableStepViewController` to display the list of items. + */ +@protocol ORKTableStepSource + +/** + Returns the number of rows in the section. + + @param section The section of the table + @return The number of rows in the tableview section + */ +- (NSInteger)numberOfRowsInSection:(NSInteger)section; + +/** + Method for configuring a cell. + + @param cell The `UITableViewCell` to configure. + @param indexPath The indexpath for the cell. + @param tableView The table view for this cell. + */ +- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView; + +/** + Returns the number of sections in the tableview used to display this step. Default = `1`. + + @return The number of sections in the tableview. + */ +@optional +- (NSInteger)numberOfSections; + +/** + Returns the reuseIdentifier for the object at this index path. Default = `ORKBasicCellReuseIdentifier` + + @param indexPath The indexpath of the section/row for the cell + @return The model object for this section/row + */ +@optional +- (NSString *)reuseIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + Optional override for registering UITableViewCell instances. The default registers a `UITableViewCell` + for `ORKBasicCellReuseIdentifier`. + + @param tableView The table view to register cells + */ +@optional +- (void)registerCellsForTableView:(UITableView *)tableView; + +/** + Optional override to return custom header title for section. The default returns `nil`. + + @param section The section for this custom header title + @param tableView The table view for custom section header title + + @return The custom header title for this section + */ +@optional +- (nullable NSString *)titleForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView; + +/** + Optional override to return custom header view for section. The default returns `nil`. + + @param section The section for this custom header view + @param tableView The table view for custom section header view + + @return The custom header view for this section + */ +@optional +- (nullable UIView *)viewForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView; + +/** + Optional override for configuring the table style. + */ +@optional +- (UITableViewStyle)customTableViewStyle; + +@end + +/** + The `ORKTableStep` class is a concrete subclass of `ORKStep`, used for presenting a list of model + objects in a UITableView. + + To use `ORKTableStep`, instantiate the object, fill in its properties, and include it + in a task. Next, create a task view controller for the task and present it. + + The base class implementation will instatiate a read-only `ORKTableStepViewController` to display + the list of items using `UITableViewCell` with the text set to the `-description` for each item in + the `items` array. + + Customization can be handled by overriding the base class implementations in either `ORKTableStep` + or `ORKTableStepViewController`. + */ + +ORK_CLASS_AVAILABLE +@interface ORKTableStep : ORKStep + +/** + The array of items in table. These items must conform to NSCopying and NSSecureCoding protocols. + */ +@property (nonatomic, copy, nullable) NSArray > *items; + +/** + Boolean flag representing if the table data should be displayed in a bulleted format. + */ +@property (nonatomic) BOOL isBulleted DEPRECATED_MSG_ATTRIBUTE("isBulleted property has been deprecated. Please use 'bulletType' property to indicate `ORKBulletType` enum."); + +/** + The bullet type to use for bullet items. + */ +@property (nonatomic) ORKBulletType bulletType; + +/** + The array of icon names to display instead of bullets. + + Images are only visible if the isBulleted property is set to YES. Images names must reference + images in you application project not the ResearchKit framework. + */ +@property (nonatomic, copy, nullable) NSArray *bulletIconNames; + +/** + Boolean flag representing if the table rows should be selectable. + + Default value is NO + */ +@property (nonatomic) BOOL allowsSelection; + +/** + Boolean flag representing if the navigation container should get pinned to the bottom of the view + + Default value is NO + */ +@property (nonatomic) BOOL pinNavigationContainer; + +/** + Returns the number of sections in the tableview used to display this step. Default = `1`. + + @return The number of sections in the tableview. + */ +- (NSInteger)numberOfSections; + +/** + Returns the number of rows in the section. Default = `items.count` + + @param section The section of the table + @return The number of rows in the tableview section + */ +- (NSInteger)numberOfRowsInSection:(NSInteger)section; + +/** + Returns the model object for this section/row. Default = `items[indexPath.row]` + + @param indexPath The indexpath of the section/row for the cell + @return The model object for this section/row + */ +- (id )objectForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + Returns the reuseIdentifier for the object at this index path. Default = `ORKBasicCellReuseIdentifier` + + @param indexPath The indexpath of the section/row for the cell + @return The model object for this section/row + */ +- (NSString *)reuseIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath; + +/** + Optional override for registering UITableViewCell instances. The default registers for `ORKBasicCellReuseIdentifier`. + */ +- (void)registerCellsForTableView:(UITableView *)tableView; + +/** + Optional override for configuring a cell. The default will set the text label using the object description for + the object at a given index path. + */ +- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.m new file mode 100755 index 0000000..5f6af04 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStep.m @@ -0,0 +1,225 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTableStep.h" +#import "ORKTableStepViewController.h" +#import "ORKHelpers_Internal.h" + +static const CGFloat CellPadding = 20.0; +static const CGFloat BulletNumberMaxWidth = 24.0 ; +static const CGFloat BulletNumberToTextPadding = 20.0; + + +ORKDefineStringKey(ORKBasicCellReuseIdentifier); + + +@implementation ORKTableStep { + UIImage * _circleBulletImage; +} + ++ (Class)stepViewControllerClass { + return [ORKTableStepViewController class]; +} + +- (NSInteger)numberOfSections { + return 1; +} + +- (NSInteger)numberOfRowsInSection:(NSInteger)section { + return _items.count; +} + +- (id )objectForRowAtIndexPath:(NSIndexPath *)indexPath { + return _items[indexPath.row]; +} + +- (NSString *)reuseIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath { + return ORKBasicCellReuseIdentifier; +} + +- (void)registerCellsForTableView:(UITableView *)tableView { + [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ORKBasicCellReuseIdentifier]; +} + +- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView { + for (UIView *view in cell.subviews) { + [view removeFromSuperview]; + } + + UILabel *textLabel = [[UILabel alloc] init]; + textLabel.text = [[self objectForRowAtIndexPath:indexPath] description]; + textLabel.numberOfLines = 0; + textLabel.translatesAutoresizingMaskIntoConstraints = NO; + [cell addSubview:textLabel]; + + [textLabel.topAnchor constraintEqualToAnchor:cell.topAnchor constant:CellPadding].active = YES; + [cell.bottomAnchor constraintEqualToAnchor:textLabel.bottomAnchor constant:CellPadding].active = YES; + [textLabel.trailingAnchor constraintEqualToAnchor:cell.trailingAnchor constant:-24.0].active = YES; + + UIImage *bullet = nil; + UILabel *numberLabel = nil; + + if (self.bulletType == ORKBulletTypeCircle) { + if (!_circleBulletImage) { + _circleBulletImage = [self circleImage]; + } + bullet = [_circleBulletImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } else if (self.bulletType == ORKBulletTypeImage && _bulletIconNames != nil) { + if (indexPath.row < self.bulletIconNames.count) { + NSString *iconName = [self.bulletIconNames objectAtIndex:indexPath.row]; + bullet = [[UIImage imageNamed:iconName] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + } else if (self.bulletType == ORKBulletTypeNumber) { + numberLabel = [[UILabel alloc] init]; + numberLabel.text = [NSString stringWithFormat: @"%ld.", indexPath.row + 1]; + numberLabel.numberOfLines = 0; + numberLabel.translatesAutoresizingMaskIntoConstraints = NO; + [cell addSubview:numberLabel]; + } + + if (bullet != nil) { + UIImageView *bulletView = [[UIImageView alloc] initWithImage:bullet]; + bulletView.translatesAutoresizingMaskIntoConstraints = NO; + [cell addSubview:bulletView]; + + CGFloat size = (self.bulletIconNames && self.bulletType == ORKBulletTypeImage) ? 40.0 : 8.0; + CGFloat topPadding = self.bulletIconNames != nil ? 20.0 : (20 + (size * .5)); + CGFloat leadingPadding = self.bulletIconNames != nil ? 24.0 : (24 + (size * .5)); + + [bulletView.topAnchor constraintEqualToAnchor:cell.topAnchor constant:topPadding].active = YES; + [bulletView.bottomAnchor constraintLessThanOrEqualToAnchor:cell.bottomAnchor constant:-20.0].active = YES; + [bulletView.heightAnchor constraintEqualToConstant:size].active = YES; + [bulletView.widthAnchor constraintEqualToConstant:size].active = YES; + [bulletView.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:leadingPadding].active = YES; + [textLabel.leadingAnchor constraintEqualToAnchor:bulletView.trailingAnchor constant:20.0].active = YES; + } + else if (numberLabel != nil) { + [numberLabel.topAnchor constraintEqualToAnchor:textLabel.topAnchor constant:0.0].active = YES; + [numberLabel.widthAnchor constraintEqualToConstant:BulletNumberMaxWidth].active = YES; + numberLabel.textAlignment = NSTextAlignmentRight; + [numberLabel.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:0.0].active = YES; + [textLabel.leadingAnchor constraintEqualToAnchor:numberLabel.trailingAnchor constant:BulletNumberToTextPadding].active = YES; + } else { + [textLabel.leadingAnchor constraintEqualToAnchor:cell.leadingAnchor constant:24.0].active = YES; + } +} + +- (UITableViewStyle)customTableViewStyle { + return [self numberOfSections] > 1 ? UITableViewStyleGrouped : UITableViewStylePlain; +} + +- (UIImage*)resizeImage:(UIImage*)image toSize:(CGSize)size { + UIGraphicsBeginImageContext(size); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return newImage; +} + +- (UIImage *)circleImage { + static UIImage *circleImage = nil; + static dispatch_once_t once; + + dispatch_once(&once, ^{ + UIGraphicsBeginImageContextWithOptions(CGSizeMake(8.f, 8.f), NO, 0.0f); + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextSaveGState(ctx); + + CGRect rect = CGRectMake(0, 0, 8, 8); + CGContextSetFillColorWithColor(ctx, [UIColor lightGrayColor].CGColor); + CGContextFillEllipseInRect(ctx, rect); + + CGContextRestoreGState(ctx); + circleImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + }); + + return circleImage; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKTableStep *step = [super copyWithZone:zone]; + step->_items = ORKArrayCopyObjects(_items); + step->_bulletType = _bulletType; + step->_bulletIconNames = ORKArrayCopyObjects(_bulletIconNames); + step->_allowsSelection = _allowsSelection; + return step; +} + +#pragma mark - NSSecureCoding + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_ARRAY(aDecoder, items, NSObject); + ORK_DECODE_INTEGER(aDecoder, bulletType); + ORK_DECODE_OBJ_ARRAY(aDecoder, bulletIconNames, NSString); + ORK_DECODE_BOOL(aDecoder, allowsSelection); + ORK_DECODE_BOOL(aDecoder, pinNavigationContainer); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, items); + ORK_ENCODE_INTEGER(aCoder, bulletType); + ORK_ENCODE_OBJ(aCoder, bulletIconNames); + ORK_ENCODE_BOOL(aCoder, allowsSelection); + ORK_ENCODE_BOOL(aCoder, pinNavigationContainer); +} + +#pragma mark - Equality + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame + && ORKEqualObjects(self.items, castObject.items) + && (self.bulletType == castObject.bulletType) + && (self.allowsSelection == castObject.allowsSelection) + && ORKEqualObjects(self.bulletIconNames, castObject.bulletIconNames) + && self.pinNavigationContainer == castObject.pinNavigationContainer); +} + +- (NSUInteger)hash { + return super.hash ^ self.items.hash ^ self.bulletIconNames.hash ^ (_bulletType ? 0xf : 0x0) ^ (_allowsSelection ? 0xf : 0x0) ^ (_pinNavigationContainer ? 0xf : 0x0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.h new file mode 100755 index 0000000..6288951 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2016, Sage Bionetworks + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKTableStepSource; + +/** + The `ORKTableStepViewController` class is an base class that inherits from `ORKStepViewController` + and provides a UITableView. + + `ORKTableStepViewController` is designed to take advantage of the internal class methods + used by `ORKFormStepViewController`, `ORKQuestionStepViewController` and `ORKReviewStepViewController` + to allow for a consistent UI in a custom implementation of a main view that is a UITableView. + + This will class will setup a consistent look for the title, text, learn more, skip and next UI elements + that are used by these classes as well as most of the other view controllers within this framework by + automatically adding them as the header and footer of the tableview. + + The base class implementation REQUIRES using an `ORKTableStep` as its data source. If you do not inherit + the step from ORKTableStep, then subclasses MUST override `-cellForRowAtIndexPath`. + + */ +ORK_CLASS_AVAILABLE +@interface ORKTableStepViewController : ORKStepViewController + +/** + @return The step associated with this view controller if it conforms to ORKTableStepSource. + */ +@property (nonatomic, readonly, nullable) id tableStep; + +/** + @return The table view managed by the controller object. + */ +@property (nonatomic, readonly, nullable) UITableView *tableView; + +/** + Whether or not the continue button should be enabled for this step. Default = YES + + Set to `NO` if there is a validation that needs to be handled before the step + can progress. Your implementation is responsible for overriding selection as needed + to trigger validation and state changes. + + @return State of continue button + */ +- (BOOL)continueButtonEnabled; + +/** + Update the button state for the skip and continue buttons + */ +- (void)updateButtonStates; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.m new file mode 100755 index 0000000..28d5c9a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController.m @@ -0,0 +1,312 @@ + +/* + Copyright (c) 2016, Sage Bionetworks + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTableStepViewController.h" +#import "ORKTableStepViewController_Internal.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKTableContainerView.h" + +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKTableStep.h" +#import "ORKStepContentView.h" +#import "ORKBodyItem.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +ORKDefineStringKey(ORKBasicCellReuseIdentifier); + + +@implementation ORKTableStepViewController { + NSArray *_constraints; + UIColor *_tableViewColor; +} + +- (id )tableStep { + if ([self.step conformsToProtocol:@protocol(ORKTableStepSource)]) { + return (id )self.step; + } + return nil; +} + +- (ORKTableStep *)tableStepRef { + return (ORKTableStep *)self.step; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self.taskViewController setRegisteredScrollView:_tableView]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +// Override to monitor button title change +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; + [self updateButtonStates]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _navigationFooterView.skipButtonItem = skipButtonItem; + [self updateButtonStates]; +} + +- (UITableViewStyle)tableViewStyle { + if ([self.tableStep respondsToSelector:@selector(customTableViewStyle)]) { + return [self.tableStep customTableViewStyle]; + } + + return [self numSections] > 1 ? UITableViewStyleGrouped : UITableViewStylePlain; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [_tableContainer sizeHeaderToFit]; + + // Recalculate the footer view size if needed. + [_tableContainer layoutSubviews]; + [self updateEffectViewStylingAndAnimate:NO]; +} + +- (void)stepDidChange { + [super stepDidChange]; + + _tableViewColor = ORKNeedWideScreenDesign(self.view) ? [UIColor clearColor] : ORKColor(ORKBackgroundColorKey); + [_tableContainer removeFromSuperview]; + _tableContainer = nil; + + _tableView.delegate = nil; + _tableView.dataSource = nil; + _tableView = nil; + + _headerView = nil; + _navigationFooterView = nil; + + if (self.step) { + _tableContainer = [[ORKTableContainerView alloc] initWithStyle:self.tableViewStyle pinNavigationContainer:self.tableStepRef.pinNavigationContainer]; + if ([self conformsToProtocol:@protocol(ORKTableContainerViewDelegate)]) { + _tableContainer.tableContainerDelegate = (id)self; + } + [self.view addSubview:_tableContainer]; + _tableContainer.tapOffView = self.view; + + _tableView = _tableContainer.tableView; + _tableView.delegate = self; + _tableView.dataSource = self; + _tableView.rowHeight = UITableViewAutomaticDimension; + _tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + _tableView.estimatedRowHeight = ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, self.view.window); + _tableView.estimatedSectionHeaderHeight = [self numSections] > 1 ? 30.0 : 0.0; + _tableView.allowsSelection = self.tableStepRef.allowsSelection; + + _tableView.separatorColor = self.tableStepRef.bulletType == ORKBulletTypeNone ? [UIColor clearColor] : nil; + [_tableView setBackgroundColor:_tableViewColor]; + _tableView.alwaysBounceVertical = NO; + _headerView = _tableContainer.stepContentView; + [_tableContainer.stepContentView setUseExtendedPadding:[[self step] useExtendedPadding]]; + + _headerView.stepTitle = [[self step] title]; + _headerView.stepText = [[self step] text]; + _headerView.bodyItems = [[self step] bodyItems]; + _headerView.stepTopContentImage = [[self step] image]; + _headerView.auxiliaryImage = [[self step] auxiliaryImage]; + _headerView.titleIconImage = [[self step] iconImage]; + _headerView.stepHeaderTextAlignment = [[self step] headerTextAlignment]; + _tableContainer.stepTopContentImageContentMode = [[self step] imageContentMode]; + _navigationFooterView = _tableContainer.navigationFooterView; + _navigationFooterView.skipButtonItem = self.skipButtonItem; + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.optional = self.step.optional; + + [_navigationFooterView setUseExtendedPadding:[[self step] useExtendedPadding]]; + + [self setupConstraints]; + // Register the cells for the table view + if ([self.tableStep respondsToSelector:@selector(registerCellsForTableView:)]) { + [self.tableStep registerCellsForTableView:_tableView]; + } else { + [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ORKBasicCellReuseIdentifier]; + } + + if (self.tableStepRef.pinNavigationContainer == NO) { + [_navigationFooterView removeStyling]; + } + } +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _tableContainer.translatesAutoresizingMaskIntoConstraints = NO; + _constraints = nil; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_tableContainer + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (BOOL)continueButtonEnabled { + return YES; +} + +- (void)updateButtonStates { + _navigationFooterView.continueEnabled = [self continueButtonEnabled]; +} + +- (void)updateEffectViewStylingAndAnimate:(BOOL)animated { + CGFloat currentOpacity = [_navigationFooterView effectViewOpacity]; + CGFloat startOfFooter = _navigationFooterView.frame.origin.y; + CGFloat contentPosition = (_tableView.contentSize.height - _tableView.contentOffset.y); + + CGFloat newOpacity = (contentPosition < startOfFooter) ? ORKEffectViewOpacityHidden : ORKEffectViewOpacityVisible; + if (newOpacity != currentOpacity) { + // Don't animate transition from hidden to visible as text appears behind during animation + if (currentOpacity == ORKEffectViewOpacityHidden) { animated = NO; } + [_navigationFooterView setStylingOpactity:newOpacity animated:animated]; + } +} + +#pragma mark UITableViewDataSource + +- (NSInteger)numSections { + if ([self.tableStep respondsToSelector:@selector(numberOfSections)]) { + return [self.tableStep numberOfSections] ?: 1; + } else { + return 1; + } +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return [self numSections]; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [self.tableStep numberOfRowsInSection:section]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + ORKThrowInvalidArgumentExceptionIfNil(self.tableStep); + + NSString *reuseIdentifier; + if ([self.tableStep respondsToSelector:@selector(reuseIdentifierForRowAtIndexPath:)]) { + reuseIdentifier = [self.tableStep reuseIdentifierForRowAtIndexPath:indexPath]; + } else { + reuseIdentifier = ORKBasicCellReuseIdentifier; + } + ORKThrowInvalidArgumentExceptionIfNil(reuseIdentifier); + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; + [self.tableStep configureCell:cell indexPath:indexPath tableView:tableView]; + + // Only set the background color if it is using the default cell type + if ([reuseIdentifier isEqualToString:ORKBasicCellReuseIdentifier]) { + if (@available(iOS 13.0, *)) { + [cell setBackgroundColor:[UIColor clearColor]]; + } else { + [cell setBackgroundColor:[UIColor whiteColor]]; + } + } + + return cell; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + if ([self.tableStep respondsToSelector:@selector(titleForHeaderInSection:tableView:)]) { + return [self.tableStep titleForHeaderInSection:section tableView:tableView]; + } else { + return nil; + } +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + if ([self.tableStep respondsToSelector:@selector(viewForHeaderInSection:tableView:)]) { + return [self.tableStep viewForHeaderInSection:section tableView:tableView]; + } else { + return nil; + } +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { + // FIXME:- temporary fix for estimating tableFooterView's height + if (indexPath == tableView.indexPathsForVisibleRows.lastObject) { + [self.view setNeedsLayout]; + } +} + +// MARK: ScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + [self updateEffectViewStylingAndAnimate:YES]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController_Internal.h new file mode 100755 index 0000000..3b08696 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableStepViewController_Internal.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2016, Sage Bionetworks + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTableStepViewController.h" + + +@class ORKTableContainerView; +@class ORKNavigationContainerView; +@class ORKStepContentView; + +@interface ORKTableStepViewController () + +@property (nonatomic, strong, readonly) ORKTableContainerView *tableContainer; + +@property (nonatomic, strong, readonly) ORKStepContentView *headerView; + +/** + @return The style to use for the tableView. default = `UITableViewStyleGrouped` if more than one section + and `UITableViewStylePlain` if there is only 1 section. + */ +@property (nonatomic, readonly) UITableViewStyle tableViewStyle; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.h new file mode 100755 index 0000000..93ce13f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.h @@ -0,0 +1,61 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Base class, not being used directly. + */ +ORK_CLASS_AVAILABLE +@interface ORKTableViewCell : UITableViewCell + +@end + + +@interface ORKTableViewCell () + +@property (nonatomic, copy, nullable) UIColor *orkSeparatorColor; + +@property (nonatomic) BOOL showBottomSeparator; + +@property (nonatomic) BOOL showTopSeparator; + +@property (nonatomic) CGFloat topSeparatorLeftInset; + +@property (nonatomic) CGFloat bottomSeparatorLeftInset; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.m new file mode 100755 index 0000000..3628d65 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTableViewCell.m @@ -0,0 +1,200 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTableViewCell.h" + +#import "ORKSelectionTitleLabel.h" + +#import "ORKSkin.h" + + +@implementation ORKTableViewCell { + UIView *_topSeparator; + NSLayoutConstraint *_topSeparatorLeftMarginConstraint; + UIView *_bottomSeparator; + NSLayoutConstraint *_bottomSeparatorLeftMarginConstraint; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + static UIColor *defaultSeparatorColor = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + UITableView *tableView = [[UITableView alloc] init]; + defaultSeparatorColor = [tableView separatorColor]; + }); + if (!defaultSeparatorColor) { + defaultSeparatorColor = [UIColor lightGrayColor]; + } + + _orkSeparatorColor = defaultSeparatorColor; + _topSeparatorLeftInset = 0; + _bottomSeparatorLeftInset = 0; + + + [self init_ORKTableViewCell]; + + } + return self; +} + +- (void)setShowBottomSeparator:(BOOL)showBottomSeparator { + _showBottomSeparator = showBottomSeparator; + if (showBottomSeparator && _bottomSeparator == nil) { + _bottomSeparator = [UIView new]; + _bottomSeparator.backgroundColor = _orkSeparatorColor; + + [self addSubview:_bottomSeparator]; + _bottomSeparator.translatesAutoresizingMaskIntoConstraints = NO; + + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + + NSMutableArray *constraints = [NSMutableArray array]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_bottomSeparator + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_bottomSeparator + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:separatorHeight]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_bottomSeparator + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + _bottomSeparatorLeftMarginConstraint = [NSLayoutConstraint constraintWithItem:_bottomSeparator + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:_bottomSeparatorLeftInset]; + + [constraints addObject:_bottomSeparatorLeftMarginConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; + } + _bottomSeparator.hidden = !showBottomSeparator; +} + +- (void)setShowTopSeparator:(BOOL)showTopSeparator { + _showTopSeparator = showTopSeparator; + + if (showTopSeparator && _topSeparator == nil) { + _topSeparator = [UIView new]; + _topSeparator.backgroundColor = _orkSeparatorColor; + + [self addSubview:_topSeparator]; + _topSeparator.translatesAutoresizingMaskIntoConstraints = NO; + + CGFloat separatorHeight = 1.0 / [UIScreen mainScreen].scale; + + NSMutableArray *constraints = [NSMutableArray array]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_topSeparator + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_topSeparator + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:separatorHeight]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_topSeparator + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]]; + + _topSeparatorLeftMarginConstraint = [NSLayoutConstraint constraintWithItem:_topSeparator + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:_topSeparatorLeftInset]; + + [constraints addObject:_topSeparatorLeftMarginConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; + } + _topSeparator.hidden = !showTopSeparator; +} + +- (void)setBottomSeparatorLeftInset:(CGFloat)bottomSeparatorLeftInset { + _bottomSeparatorLeftInset = bottomSeparatorLeftInset; + _bottomSeparatorLeftMarginConstraint.constant = _bottomSeparatorLeftInset; +} + +- (void)setTopSeparatorLeftInset:(CGFloat)topSeparatorLeftInset { + _topSeparatorLeftInset = topSeparatorLeftInset; + _topSeparatorLeftMarginConstraint.constant = _topSeparatorLeftInset; +} + +- (void)init_ORKTableViewCell { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateAppearance) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + self.textLabel.font = [ORKSelectionTitleLabel defaultFont]; + [self updateAppearance]; +} + +- (void)updateAppearance { + [self invalidateIntrinsicContentSize]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.h new file mode 100755 index 0000000..9e798b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; + +#import + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTagLabel : UILabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.m new file mode 100755 index 0000000..fb8aa18 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTagLabel.m @@ -0,0 +1,73 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTagLabel.h" + +@implementation ORKTagLabel + +static const CGFloat horizontalInset = 6; +static const CGFloat verticalInset = 4; + +- (instancetype)init { + self = [super initWithFrame:CGRectZero]; + if (self) { + self.numberOfLines = 0; + self.clipsToBounds = YES; + self.layer.cornerRadius = 2.0; + + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption2]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:(UIFontDescriptorTraitBold)]; + + self.font = [UIFont fontWithDescriptor:fontDescriptor size:[[fontDescriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; + + if (@available(iOS 13.0, *)) { + self.textColor = [UIColor systemGrayColor]; + self.backgroundColor = [UIColor tertiarySystemGroupedBackgroundColor]; + } else { + self.textColor = [UIColor darkGrayColor]; + self.backgroundColor = [UIColor lightGrayColor]; + } + } + return self; +} + +- (void)drawTextInRect:(CGRect)rect { + UIEdgeInsets insets = {verticalInset, horizontalInset, verticalInset, horizontalInset}; + [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)]; +} + +- (CGSize)intrinsicContentSize { + CGSize contentSize = [super intrinsicContentSize]; + contentSize.height += (verticalInset * 2); + contentSize.width += (horizontalInset * 2); + return contentSize; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.h new file mode 100755 index 0000000..293e113 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLabel.h" +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Display tapping count in tapping interval active task + */ +ORK_CLASS_AVAILABLE +@interface ORKTapCountLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.m new file mode 100755 index 0000000..65d70bf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTapCountLabel.m @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTapCountLabel.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKTapCountLabel + ++ (UIFont *)defaultFont { + // Thin, 56 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return ORKThinFontWithSize([[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]+ 39.0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTask.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTask.h new file mode 100755 index 0000000..85912f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTask.h @@ -0,0 +1,284 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import HealthKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKStep; +@class ORKTaskResult; + +/** + + `ORKTaskProgress` is a structure that represents how far a task has progressed. + + Objects that implement the `ORKTask` protocol return the task progress structure to indicate + to the task view controller how far the task has progressed. + + Note that the values in an `ORKTaskProgress` structure are used only for display; you don't use the values to access the steps in a task. + */ +typedef struct { + /// The index of the current step, starting from 0. + NSUInteger current; + + /// The total number of steps in the task. + NSUInteger total; + + /// Indicates if the the step should present a progress label + BOOL shouldBePresented; +} ORKTaskProgress ORK_AVAILABLE_DECL; + +/** + Returns a task progress structure with the specified current and total values. + + @param current The index of the current step, starting from 0. + @param total The total number of steps. + + @return A task progress structure. + */ +ORK_EXTERN ORKTaskProgress ORKTaskProgressMake(NSUInteger current, NSUInteger total) ORK_AVAILABLE_DECL; + +/** + + `ORKTaskTotalProgress` is a structure that represents how far a task has progressed based on the total amount of questions. + + Note that the values in an `ORKTotalTaskProgress` structure are used only for display; you don't use the values to access the steps in a task. + */ +typedef struct { + /// The position of the current question based on the total amount of questions within the task. + NSUInteger currentStepStartingProgressPosition; + + /// The total number of questions in the task. + NSUInteger total; + + /// Determines if the task should display the progress based on the total amount of questions in the task or the total amount in each step + BOOL stepShouldShowTotalProgress; +} ORKTaskTotalProgress ORK_AVAILABLE_DECL; + +/** + Returns a task progress structure with the specified current and total values. + + @param currentStepStartingProgressPosition The position of the current question based on the total amount of questions within the task. + @param total The total number of questions in the task. + @param stepShouldShowTotalProgress Determines if the task should display the progress based on the total amount of questions in the task or the total amount in each step + + @return A task progress structure. + */ +ORK_EXTERN ORKTaskTotalProgress ORKTaskTotalProgressMake(NSUInteger currentStepStartingProgressPosition, NSUInteger total, BOOL stepShouldShowTotalProgress) ORK_AVAILABLE_DECL; + +/** + The `ORKTask` protocol defines a task to be carried out by a participant + in a research study. To present the ResearchKit framework UI in your app, instantiate an + object that implements the `ORKTask` protocol (such as `ORKOrderedTask`) and + provide it to an `ORKTaskViewController` object. + + Implement this protocol to enable dynamic selection of the steps for a given task. + By default, `ORKOrderedTask` implements this protocol for simple sequential tasks. + + Each step (`ORKStep`) in a task roughly corresponds to one screen, and represents the + primary unit of work in any task presented by a task view controller. For example, + an `ORKQuestionStep` object corresponds to a single question presented on screen, + together with controls the participant uses to answer the question. Another example is `ORKFormStep`, which corresponds to a single + screen that displays multiple questions or items for which participants provide information, such as first name, last name, and birth date. + + Each step corresponds to one + `ORKStepViewController` object, which may manage child view controllers in a particular + sequence. The correspondence of step to view controller holds even though some steps, such as `ORKVisualConsentStep` and + `ORKConsentReviewStep`, can produce multiple screens. + */ +ORK_AVAILABLE_DECL +@protocol ORKTask + +@required +/** + The unique identifier for this task. + + The identifier should be a short string that identifies the task. The identifier is copied + into the `ORKTaskResult` objects generated by the task view controller for this + task. You can use a human-readable string for the task identifier + or a UUID; the exact string you use depends on your app. + + In the case of apps whose tasks come from a server, the unique + identifier for the task may be in an external database. + + The task view controller uses the identifier when constructing the task result. + The identifier can also be used during UI state restoration to identify the + task that needs to be restored. + */ +@property (nonatomic, copy, readonly) NSString *identifier; + +/** + Returns the step after the specified step, if there is one. + + This method lets you use a result to determine the next step. + + The task view controller calls this method to determine the step to display + after the specified step. The task view controller can also call this method every time the result updates, to determine if the new result changes which steps are available. + + If you need to implement this method, take care to avoid creating a confusing sequence of steps. As much as possible, use `ORKOrderedTask` instead. + + @param step The reference step. Pass `nil` to specify the first step. + @param result A snapshot of the current set of results. + + @return The step that comes after the specified step, or `nil` if there isn't one. + */ +- (nullable ORKStep *)stepAfterStep:(nullable ORKStep *)step withResult:(ORKTaskResult *)result; + +/** + Returns the step that precedes the specified step, if there is one. + + The task view controller calls this method to determine the step to display + before the specified step. The task view controller can also call this method every time the result changes, to determine if the new result changes which steps are available. + + If you need to implement this method, take care to avoid creating a confusing sequence of steps. As much as possible, use `ORKOrderedTask` instead. Returning `nil` prevents the user from navigating back to a previous step. + + @param step The reference step. Pass `nil` to specify the last step. + @param result A snapshot of the current set of results. + + @return The step that precedes the reference step, or `nil` if there isn't one. + */ +- (nullable ORKStep *)stepBeforeStep:(nullable ORKStep *)step withResult:(ORKTaskResult *)result; + +@optional +/** + Returns the step that matches the specified identifier. + + Implementing this method allows state restoration of a task + to a particular step. If you don't implement this method, `ORKTaskViewController` restores the state + to the first step of the task. + + @param identifier The identifier of the step to restore. + + @return The step that matches the specified identifier. + */ +- (nullable ORKStep *)stepWithIdentifier:(NSString *)identifier; + +/** + Returns the progress of the current step. + + During a task, the task view controller can display the progress (that is, the current step number + out of the total number of steps) in the navigation bar. Implement + this method to control what is displayed; if you don't implement this method, the progress label does not appear. + If the returned `ORKTaskProgress` object has a count of 0, the progress is not displayed. + + @param step The current step. + @param result A snapshot of the current set of results. + + @return The current step's index and the total number of steps in the task, as an `ORKTaskProgress` object. + */ +- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)result; + +/** + Returns the progress of the current step based on the total amount of questions in the task. + + During a task, each questions can display its progress (that is, the current question number out of the total amount of questions in the task) in its header view. + + @param currentStep The current step. + + @return The current step's index and the total number of steps in the task, as an `ORKTaskProgress` object. + The index of the current step's first question, the total amount of questions in the task, and a BOOL to determine if the step should display its progress labels in this manner. + */ +- (ORKTaskTotalProgress)totalProgressOfCurrentStep:(ORKStep *)currentStep; + +/** + Returns true if the provided step is the first or last object in the array of steps + + @param step The current step. + */ + +- (BOOL)shouldHideProgressFor:(ORKStep *)step; + +/** + Validates the task parameters. + + The implementation of this method should check that all the task parameters are correct. An invalid task + is considered an unrecoverable error: the implementation should throw an exception on parameter validation failure. + For example, the `ORKOrderedTask` implementation makes sure that all its step identifiers are unique, throwing an + exception otherwise. + + This method is usually called by a task view controller when its task is set. + */ +- (void)validateParameters; + +/** + The set of HealthKit types that steps in the task need to be able to + read. (read-only) + + The value of this property is a set of `HKObjectType` values to request for reading from HealthKit during this task. After the last of the initial instruction steps, the task view controller +requests access to these HealthKit types. + + To set this property, you can scan the steps in the task + and collate the HealthKit types that are requested by each active step, question, or + form step that has a Health answer format, and then include any additional types known + to be required. (Note that `ORKOrderedTask` does something similar for this property.) + + See also: `requestedHealthKitTypesForWriting`. + */ +@property (nonatomic, copy, readonly, nullable) NSSet *requestedHealthKitTypesForReading; + +/** + The set of HealthKit types for which the task needs to request write access. + + The requested `HKObjectType` values for writing can be returned by an extended task, + to request write access to these HealthKit types together with the read access + requested by the task view controller by calling `requestedHealthKitTypesForReading`. + + See also: `requestedHealthKitTypesForReading`. + */ +@property (nonatomic, copy, readonly, nullable) NSSet *requestedHealthKitTypesForWriting; + +/** + The set of permissions requested by the task. + + By default in `ORKOrderedTask` object, these permissions are collected from the + recorder configurations associated with the active steps in the task. + */ +@property (nonatomic, readonly) ORKPermissionMask requestedPermissions; + +/** + A Boolean value indicating whether this task involves spoken audio prompts. (read-only) + + If the value of this property is `YES`, the shared `AVAudioSession` is configured for playback in the background. + The audio `UIBackgroundMode` value must be set in the application's `Info.plist` file + for this to be effective. + + By default, this property looks for active steps that have + audio prompts or count down enabled, and returns `YES` if such steps exist in + the task. + */ +@property (nonatomic, readonly) BOOL providesBackgroundAudioPrompts; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.h new file mode 100755 index 0000000..cf5ce01 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKTaskResultSource; +@class ORKInstructionStep; +@class ORKTaskResult; +@class ORKStep; + +@protocol ORKTaskReviewViewControllerDelegate + +@required +- (void)editAnswerTappedForStepWithIdentifier:(NSString *)stepIdentifier; + +- (void)doneButtonTappedWithResultSource:(id)resultSource; + +@end + + +@interface ORKReviewItem : NSObject +@property (nonatomic) NSString *question; +@property (nonatomic, nullable) NSString *answer; +@end + +@interface ORKReviewSection : NSObject +@property (nonatomic) NSString *title; +@property (nonatomic) NSString *text; +@property (nonatomic) NSString *stepIdentifier; +@property (nonatomic) NSArray *items; +@end + +@interface ORKReviewCell : UITableViewCell + +@property (nonatomic) BOOL isLastCell; +@property (nonatomic) NSString *question; +@property (nonatomic) NSString *answer; +@end + +@interface ORKReviewSectionFooter : UIView +@property (nonatomic) UIButton *button; +@end + + +@interface ORKTaskReviewViewController : UIViewController + +@property (nonatomic, weak) id delegate; + +- (instancetype)initWithResultSource:(id)resultSource forSteps:(NSArray *)steps withContentFrom:(nullable ORKInstructionStep *)reviewInstructionStep; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.m new file mode 100755 index 0000000..e7d808f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskReviewViewController.m @@ -0,0 +1,566 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKTaskReviewViewController.h" +#import "ORKStepView_Private.h" +#import "ORKTableContainerView.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepContentView_Private.h" +#import "ORKStep.h" +#import "ORKFormStep.h" +#import "ORKQuestionStep.h" +#import "ORKCollectionResult.h" +#import "ORKQuestionResult_Private.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKSurveyCardHeaderView.h" +#import "ORKChoiceViewCell_Internal.h" +#import "ORKSkin.h" +#import "ORKHelpers_Internal.h" + +static const float ReviewCellTopBottomPadding = 15.0; +static const float EditAnswerButtonTopBottomPadding = 10.0; +static const float ReviewCardBottomPadding = 10.0; +static const float ReviewQuestionAnswerPadding = 2.0; + +@implementation ORKReviewItem +@end + +@implementation ORKReviewSection +@end + +@implementation ORKReviewCell { + NSString *_question; + NSString *_answer; + + UILabel *_questionLabel; + UILabel *_answerLabel; + + UIView *_containerView; + CAShapeLayer *_contentMaskLayer; +} + +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; + if (self) { + [self setupContainerView]; + [self setupLabels]; + [self setupConstraints]; + [self setBackgroundColor:UIColor.clearColor]; + } + return self; +} + +- (void) drawRect:(CGRect)rect { + [super drawRect:rect]; + [self setMaskLayers]; +} + +- (void)setQuestion:(NSString *)question { + _question = question; + _questionLabel.text = _question; +} + +- (void)setAnswer:(NSString *)answer { + _answer = answer; + if (@available(iOS 13.0, *)) { + _answerLabel.textColor = _answer ? UIColor.secondaryLabelColor : UIColor.tertiaryLabelColor; + } else { + _answerLabel.textColor = _answer ? UIColor.blackColor : UIColor.lightGrayColor; + } + _answerLabel.text = _answer ? : ORKLocalizedString(@"REVIEW_SKIPPED_ANSWER", nil); +} + +- (void)setMaskLayers { + if (_contentMaskLayer) { + for (CALayer *sublayer in [_contentMaskLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + [_contentMaskLayer removeFromSuperlayer]; + _contentMaskLayer = nil; + } + _contentMaskLayer = [[CAShapeLayer alloc] init]; + UIColor *fillColor; + UIColor *borderColor; + if (@available(iOS 13.0, *)) { + fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + borderColor = UIColor.separatorColor; + } else { + fillColor = [UIColor ork_borderGrayColor]; + borderColor = [UIColor ork_midGrayTintColor]; + } + [_contentMaskLayer setFillColor:[fillColor CGColor]]; + CAShapeLayer *foreLayer = [CAShapeLayer layer]; + [foreLayer setFillColor:[fillColor CGColor]]; + foreLayer.zPosition = 0.0f; + + CAShapeLayer *lineLayer = [CAShapeLayer layer]; + + CGRect foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, 0, _containerView.bounds.size.width - 2 * ORKCardDefaultBorderWidth, _containerView.bounds.size.height); + foreLayer.path = [UIBezierPath bezierPathWithRect:foreLayerBounds].CGPath; + _contentMaskLayer.path = [UIBezierPath bezierPathWithRect:_containerView.bounds].CGPath; + CGFloat leftRightMargin = ORKCardLeftRightMarginForWindow(self.window); + CGRect lineBounds = CGRectMake(leftRightMargin, _containerView.bounds.size.height - 1.0, _containerView.bounds.size.width - leftRightMargin, 0.5); + lineLayer.path = [UIBezierPath bezierPathWithRect:lineBounds].CGPath; + lineLayer.zPosition = 0.0f; + + lineLayer.fillColor = _isLastCell ? UIColor.clearColor.CGColor : borderColor.CGColor; + _contentMaskLayer.fillColor = borderColor.CGColor; + [_contentMaskLayer addSublayer:foreLayer]; + [_contentMaskLayer addSublayer:lineLayer]; + [_containerView.layer insertSublayer:_contentMaskLayer atIndex:0]; +} + +- (void)setupContainerView { + if (!_containerView) { + _containerView = [UIView new]; + } + if (@available(iOS 13.0, *)) { + _containerView.backgroundColor = UIColor.systemBackgroundColor; + } else { + _containerView.backgroundColor = UIColor.whiteColor; + } + _containerView.translatesAutoresizingMaskIntoConstraints = NO; + [self.contentView addSubview:_containerView]; +} + +- (void)setupLabels { + if (!_questionLabel) { + _questionLabel = [UILabel new]; + } + if (!_answerLabel) { + _answerLabel = [UILabel new]; + } + if (@available(iOS 13.0, *)) { + _questionLabel.textColor = [UIColor labelColor]; + } else { + _questionLabel.textColor = [UIColor blackColor]; + } + _questionLabel.numberOfLines = 0; + _questionLabel.textAlignment = NSTextAlignmentLeft; + + _answerLabel.numberOfLines = 0; + _answerLabel.textAlignment = NSTextAlignmentLeft; + + [_containerView addSubview:_questionLabel]; + [_containerView addSubview:_answerLabel]; + + _questionLabel.translatesAutoresizingMaskIntoConstraints = NO; + _answerLabel.translatesAutoresizingMaskIntoConstraints = NO; +} + +- (void)setupConstraints { + [[_containerView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:1.0 / [UIScreen mainScreen].scale] setActive:YES]; + [[_containerView.leftAnchor constraintEqualToAnchor:self.contentView.leftAnchor constant:ORKCardLeftRightMarginForWindow(self.window)] setActive:YES]; + [[_containerView.rightAnchor constraintEqualToAnchor:self.contentView.rightAnchor constant:-ORKCardLeftRightMarginForWindow(self.window)] setActive:YES]; + + [[_questionLabel.topAnchor constraintEqualToAnchor:_containerView.topAnchor constant:ReviewCellTopBottomPadding] setActive:YES]; + [[_questionLabel.leadingAnchor constraintEqualToAnchor:_containerView.leadingAnchor constant:ORKSurveyItemMargin] setActive:YES]; + [[_questionLabel.trailingAnchor constraintEqualToAnchor:_containerView.trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + + [[_answerLabel.topAnchor constraintEqualToAnchor:_questionLabel.bottomAnchor constant:ReviewQuestionAnswerPadding] setActive:YES]; + [[_answerLabel.trailingAnchor constraintEqualToAnchor:_containerView.trailingAnchor constant:-ORKSurveyItemMargin] setActive:YES]; + [[_answerLabel.leadingAnchor constraintEqualToAnchor:_containerView.leadingAnchor constant:ORKSurveyItemMargin] setActive:YES]; + [[_answerLabel.bottomAnchor constraintEqualToAnchor:_containerView.bottomAnchor constant:-ReviewCellTopBottomPadding] setActive:YES]; + + [[self.contentView.bottomAnchor constraintEqualToAnchor:_containerView.bottomAnchor] setActive:YES]; +} + +@end + +@implementation ORKReviewSectionFooter { + UIView *_containerView; + CAShapeLayer *_contentLayer; + UIView *_separator; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + [self setupContainerView]; + [self setupButton]; + [self setupConstraints]; + } + return self; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (!_contentLayer) { + _contentLayer = [CAShapeLayer layer]; + } + + for (CALayer *sublayer in [_contentLayer.sublayers mutableCopy]) { + [sublayer removeFromSuperlayer]; + } + + [_contentLayer removeFromSuperlayer]; + CGRect contentBounds = _containerView.bounds; + + _contentLayer.path = [UIBezierPath bezierPathWithRoundedRect: contentBounds + byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight + cornerRadii: (CGSize){ORKCardDefaultCornerRadii, ORKCardDefaultCornerRadii}].CGPath; + + CAShapeLayer *foreLayer = [CAShapeLayer layer]; + UIColor *fillColor; + UIColor *borderColor; + + if (@available(iOS 13.0, *)) { + fillColor = [UIColor secondarySystemGroupedBackgroundColor]; + borderColor = UIColor.separatorColor; + } else { + fillColor = [UIColor whiteColor]; + borderColor = [UIColor ork_midGrayTintColor]; + } + [foreLayer setFillColor:[fillColor CGColor]]; + + CGFloat foreLayerCornerRadii = ORKCardDefaultCornerRadii >= ORKCardDefaultBorderWidth ? ORKCardDefaultCornerRadii - ORKCardDefaultBorderWidth : ORKCardDefaultCornerRadii; + + CGRect foreLayerBounds = CGRectMake(ORKCardDefaultBorderWidth, ORKCardDefaultBorderWidth, contentBounds.size.width - 2 * ORKCardDefaultBorderWidth, contentBounds.size.height - 2 * ORKCardDefaultBorderWidth); + + foreLayer.path = [UIBezierPath bezierPathWithRoundedRect: foreLayerBounds + byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight + cornerRadii: (CGSize){foreLayerCornerRadii, foreLayerCornerRadii}].CGPath; + foreLayer.zPosition = 0.0f; + foreLayer.borderWidth = ORKCardDefaultBorderWidth; + [_contentLayer addSublayer:foreLayer]; + [_contentLayer setFillColor:[borderColor CGColor]]; + [_containerView.layer insertSublayer:_contentLayer atIndex:0]; +} + +- (void)setupContainerView { + if (!_containerView) { + _containerView = [UIView new]; + } + [_containerView setBackgroundColor:[UIColor clearColor]]; + + _separator = [UIView new]; + if (@available(iOS 13.0, *)) { + _separator.backgroundColor = UIColor.separatorColor; + } else { + _separator.backgroundColor = UIColor.lightGrayColor; + } + [_containerView addSubview:_separator]; + + _containerView.translatesAutoresizingMaskIntoConstraints = NO; + _separator.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_containerView]; +} + +- (void)setupButton { + if(!_button) { + _button = [[UIButton alloc] init]; + } + [_button setTitle:ORKLocalizedString(@"REVIEW_EDIT_ANSWER", nil) forState:UIControlStateNormal]; + [_button setTitleColor:self.tintColor forState:UIControlStateNormal]; + + _button.translatesAutoresizingMaskIntoConstraints = NO; + [_containerView addSubview:_button]; +} + +- (void)setupConstraints { + // TODO: replace padding constants + + CGFloat leftRightPadding = ORKCardLeftRightMarginForWindow(self.window); + + [[_containerView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0.0] setActive:YES]; + [[_containerView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:leftRightPadding] setActive:YES]; + [[_containerView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-leftRightPadding] setActive:YES]; + [[_button.topAnchor constraintEqualToAnchor:_containerView.topAnchor constant:EditAnswerButtonTopBottomPadding] setActive:YES]; + [[_button.centerXAnchor constraintEqualToAnchor:_containerView.centerXAnchor] setActive:YES]; + [[_containerView.bottomAnchor constraintEqualToAnchor:_button.bottomAnchor constant:EditAnswerButtonTopBottomPadding] setActive:YES]; + + [_separator.heightAnchor constraintEqualToConstant:1.0 / [UIScreen mainScreen].scale].active = YES; + [_separator.leadingAnchor constraintEqualToAnchor:_containerView.leadingAnchor].active = YES; + [_separator.trailingAnchor constraintEqualToAnchor:_containerView.trailingAnchor].active = YES; + [_separator.topAnchor constraintEqualToAnchor:_containerView.topAnchor].active = YES; + + [[self.bottomAnchor constraintEqualToAnchor:_containerView.bottomAnchor constant:ReviewCardBottomPadding] setActive:YES]; +} + +@end + +@interface ORKTaskReviewViewController () + +@property (nonatomic, nonnull) ORKTableContainerView *tableContainerView; +@property (nonatomic) NSMutableArray *reviewSections; +@property (nonatomic) id resultSource; +@property (nonatomic, nonnull) NSArray *steps; + +@end + +@implementation ORKTaskReviewViewController { + ORKNavigationContainerView *_navigationFooterView; + ORKStep *_reviewInstructionStep; +} + +- (instancetype)initWithResultSource:(id)resultSource forSteps:(NSArray *)steps withContentFrom:(ORKInstructionStep *)reviewInstructionStep { + self = [super init]; + if (self) { + _steps = steps; + _resultSource = resultSource; + _reviewInstructionStep = (ORKStep *)reviewInstructionStep; + [self createReviewSectionsWithDefaultResultSource:resultSource]; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setupTableContainerView]; + [self setupNavigationFooterView]; + if (_reviewInstructionStep) { + _tableContainerView.stepTitle = _reviewInstructionStep.title; + _tableContainerView.stepText = _reviewInstructionStep.text; + _tableContainerView.stepDetailText = _reviewInstructionStep.detailText; + _tableContainerView.titleIconImage = _reviewInstructionStep.iconImage; + _tableContainerView.stepTopContentImage = _reviewInstructionStep.image; + _tableContainerView.bodyItems = _reviewInstructionStep.bodyItems; + } + [_tableContainerView setNeedsLayout]; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + [_tableContainerView sizeHeaderToFit]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + [_tableContainerView layoutIfNeeded]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [_tableContainerView sizeHeaderToFit]; + [_tableContainerView.tableView reloadData]; + [self.view layoutSubviews]; +} + +- (void)setupTableContainerView { + if (!_tableContainerView) { + _tableContainerView = [[ORKTableContainerView alloc] initWithStyle:UITableViewStyleGrouped pinNavigationContainer:NO]; + _tableContainerView.tableView.dataSource = self; + _tableContainerView.tableView.delegate = self; + _tableContainerView.tableView.clipsToBounds = YES; + _tableContainerView.tableView.rowHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.sectionHeaderHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.sectionFooterHeight = UITableViewAutomaticDimension; + _tableContainerView.tableView.estimatedRowHeight = ORKGetMetricForWindow(ORKScreenMetricTableCellDefaultHeight, self.view.window); + _tableContainerView.tableView.estimatedSectionHeaderHeight = 30.0; + _tableContainerView.tableView.estimatedSectionFooterHeight = 30.0; + _tableContainerView.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + + } + [self.view addSubview:_tableContainerView]; + _tableContainerView.translatesAutoresizingMaskIntoConstraints = NO; + [[_tableContainerView.topAnchor constraintEqualToAnchor:self.view.topAnchor] setActive:YES]; + [[_tableContainerView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] setActive:YES]; + [[_tableContainerView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor] setActive:YES]; + [[_tableContainerView.rightAnchor constraintEqualToAnchor:self.view.rightAnchor] setActive:YES]; +} + +- (void)setupNavigationFooterView { + _navigationFooterView = _tableContainerView.navigationFooterView; + [_navigationFooterView removeStyling]; + _navigationFooterView.skipButtonItem = nil; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.continueButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_DONE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(doneButtonTapped)]; +} + +- (void)createReviewSectionsWithDefaultResultSource:(id)defaultResultSource { + _reviewSections = nil; + _reviewSections = [[NSMutableArray alloc] init]; + for (ORKStep *step in _steps) { + if ([step isKindOfClass:[ORKFormStep class]]) { + ORKFormStep *formStep = (ORKFormStep *)step; + ORKStepResult *result = [defaultResultSource stepResultForStepIdentifier:formStep.identifier]; + if (result) { + [_reviewSections addObject:[self reviewSectionForFormStep:formStep withResult:result]]; + } + } + else if ([step isKindOfClass:[ORKQuestionStep class]]) { + ORKQuestionStep *questionStep = (ORKQuestionStep *)step; + ORKStepResult *result = [defaultResultSource stepResultForStepIdentifier:questionStep.identifier]; + if (result) { + [_reviewSections addObject:[self reviewSectionForQuestionStep:questionStep withResult:result]]; + } + } + } +} + +- (ORKReviewSection *)reviewSectionForFormStep:(ORKFormStep *)formStep withResult:(ORKStepResult *)result { + if (formStep && formStep.formItems && result) { + NSMutableArray *formReviewItems = [[NSMutableArray alloc] init]; + for (ORKFormItem *formItem in formStep.formItems) { + if (formItem.answerFormat) { + ORKResult *formItemResult = [result resultForIdentifier:formItem.identifier]; + ORKReviewItem *formReviewItem = [[ORKReviewItem alloc] init]; + formReviewItem.question = formItem.text; + formReviewItem.answer = [self answerStringForFormItem:formItem withFormItemResult:formItemResult]; + [formReviewItems addObject:formReviewItem]; + } + else { + // Use this for grouping form items without answer formats. + } + } + ORKReviewSection *section = [[ORKReviewSection alloc] init]; + section.title = formStep.title; + section.text = formStep.text; + section.stepIdentifier = formStep.identifier; + section.items = [formReviewItems copy]; + + return section; + } + return nil; +} + +- (NSString *)answerStringForFormItem:(ORKFormItem *)formItem withFormItemResult:(ORKResult *)formItemResult { + NSString *answerString = nil; + if (formItem && formItemResult && [formItemResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)formItemResult; + if (formItem.answerFormat && [questionResult isKindOfClass:formItem.answerFormat.questionResultClass] && questionResult.answer) { + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answerString = formItem.answerFormat.customDontKnowButtonText; + } else { + answerString = [formItem.answerFormat stringForAnswer:questionResult.answer]; + } + } + } + return answerString; +} + +- (ORKReviewSection *)reviewSectionForQuestionStep:(ORKQuestionStep *)questionStep withResult:(ORKStepResult *)result { + ORKReviewItem *item = [[ORKReviewItem alloc] init]; + item.question = questionStep.question; + if (result.firstResult && [result.firstResult isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)result.firstResult; + item.answer = [self answerStringForQuestionStep:questionStep withQuestionResult:questionResult]; + } + ORKReviewSection *section = [[ORKReviewSection alloc] init]; + section.title = questionStep.title; + section.text = questionStep.text; + section.stepIdentifier = questionStep.identifier; + section.items = @[item]; + + return section; + +} + +- (NSString *)answerStringForQuestionStep:(ORKQuestionStep *)questionStep withQuestionResult:(ORKQuestionResult *)questionResult { + NSString *answerString = nil; + if (questionStep && questionResult && questionStep.answerFormat && [questionResult isKindOfClass:questionStep.answerFormat.questionResultClass] && questionResult.answer) { + if ([questionResult.answer isKindOfClass:[ORKDontKnowAnswer class]]) { + answerString = questionStep.answerFormat.customDontKnowButtonText; + } else { + answerString = [questionStep.answerFormat stringForAnswer:questionResult.answer]; + } + } + return answerString; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return _reviewSections ? _reviewSections.count : 0; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return _reviewSections[section].items.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; + if (cell == nil) { + ORKReviewCell *reviewCell = [[ORKReviewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + cell = reviewCell; + } + ORKReviewCell *reviewCell = (ORKReviewCell *)cell; + reviewCell.question = _reviewSections[indexPath.section].items[indexPath.row].question; + reviewCell.answer = _reviewSections[indexPath.section].items[indexPath.row].answer; + reviewCell.isLastCell = _reviewSections[indexPath.section].items.count - 1 == indexPath.row; + return cell; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { + ORKSurveyCardHeaderView *cardHeaderView = (ORKSurveyCardHeaderView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:@(section).stringValue]; + + if (cardHeaderView == nil) { + ORKReviewSection *reviewSection = _reviewSections[section]; + cardHeaderView = [[ORKSurveyCardHeaderView alloc] initWithTitle:reviewSection.title detailText:reviewSection.text learnMoreView:nil progressText:[NSString stringWithFormat:@"%@ %@", ORKLocalizedString(@"REVIEW_STEP_PAGE", nil), ORKLocalizedStringFromNumber(@(section + 1))] tagText:nil showBorder:YES hasMultipleChoiceItem:NO]; + } + + return cardHeaderView; +} + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { + return NO; +} + +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + ORKReviewSectionFooter *sectionFooter = (ORKReviewSectionFooter *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:[NSString stringWithFormat:@"Footer%@", @(section).stringValue]]; + if (!sectionFooter) { + sectionFooter = [ORKReviewSectionFooter new]; + sectionFooter.button.tag = section; + [sectionFooter.button addTarget:self action:@selector(footerButtonTappedForSection:) forControlEvents:UIControlEventTouchUpInside]; + } + + return sectionFooter; +} + +- (nullable ORKStep *)stepForIdentifier:(NSString *)identifier { + for (ORKStep *step in _steps) { + return [step.identifier isEqualToString:identifier] ? step : nil; + } + return nil; +} + +- (void)footerButtonTappedForSection:(id)sender { + UIButton *button = (UIButton *)sender; + if (self.delegate && [self.delegate respondsToSelector:@selector(editAnswerTappedForStepWithIdentifier:)]) { + [self.delegate editAnswerTappedForStepWithIdentifier:_reviewSections[button.tag].stepIdentifier]; + } +} + +- (void)doneButtonTapped { + if (self.delegate && [self.delegate respondsToSelector:@selector(doneButtonTappedWithResultSource:)]) { + [self.delegate doneButtonTappedWithResultSource:_resultSource]; + } +} + +#pragma mark - UItableViewDelegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:NO]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.h new file mode 100755 index 0000000..b125abf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.h @@ -0,0 +1,600 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKResult; +@class ORKStep; +@class ORKStepViewController; +@class ORKTaskResult; +@class ORKTaskViewController; +@class ORKLearnMoreInstructionStep; +@class ORKLearnMoreStepViewController; +@protocol ORKStepViewControllerDelegate; +@protocol ORKTask; +@protocol ORKTaskResultSource; +@class ORKInstructionStep; + + +/** + The `ORKTaskViewControllerReviewMode` value indicates how the task view controller reviews the task. + */ +typedef NS_ENUM(NSInteger, ORKTaskViewControllerReviewMode) { + + ORKTaskViewControllerReviewModeNever = 0, + + ORKTaskViewControllerReviewModeStandalone +}; + +/** + The `ORKTaskViewControllerFinishReason` value indicates how the task view controller has finished + the task. + */ +typedef NS_ENUM(NSInteger, ORKTaskViewControllerFinishReason) { + + /// The task was canceled by the participant or the developer, and the participant asked to save the current result. + ORKTaskViewControllerFinishReasonSaved, + + /// The task was canceled by the participant or the developer, and the participant asked to discard the current result. + ORKTaskViewControllerFinishReasonDiscarded, + + /// The task has completed successfully, because all steps have been completed. + ORKTaskViewControllerFinishReasonCompleted, + + /// An error was detected during the current step. + ORKTaskViewControllerFinishReasonFailed +}; + +/** + The `ORKTaskViewControllerProgressMode` value indicates how the question progress labels will be presented during the task + */ +typedef NS_ENUM(NSInteger, ORKTaskViewControllerProgressMode) { + + /// The displayed progress numbers for each step will be dependent on the total amount of questions throughout the entire task. + ORKTaskViewControllerProgressModeTotalQuestions = 0, + + /// The displayed progress numbers for each step will be dependent on amount of questions within that particular step. + ORKTaskViewControllerProgressModeQuestionsPerStep +} ORK_ENUM_AVAILABLE; + + + +/** + The task view controller delegate is responsible for processing the results + of the task, exerting some control over how the controller behaves, and providing + auxiliary content as needed. + */ +@protocol ORKTaskViewControllerDelegate + +/** + Tells the delegate that the task has finished. + + The task view controller calls this method when an unrecoverable error occurs, + when the user has canceled the task (with or without saving), or when the user + completes the last step in the task. + + In most circumstances, the receiver should dismiss the task view controller + in response to this method, and may also need to collect and process the results + of the task. + + @param taskViewController The `ORKTaskViewController `instance that is returning the result. + @param reason An `ORKTaskViewControllerFinishReason` value indicating how the user chose to complete the task. + @param error If failure occurred, an `NSError` object indicating the reason for the failure. The value of this parameter is `nil` if `result` does not indicate failure. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(nullable NSError *)error; + +@optional +/** + Signals that an error has been detected by a recorder. + + Recorder errors can occur during active steps, typically because sensor data is unavailable or there isn't enough disk space to record the results. + You can use this method as an opportunity to respond to the error by, for example, logging and ignoring it. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param recorder The recorder that detected the error. `ORKStep` and `ORKRecorderConfiguration` objects can be found in the recorder instance. + @param error The error that was detected. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error; + +/** + Asks the delegate if the state of the current uncompleted task should be saved. + + The task view controller calls this method to determine whether to offer + a save option when the user attempts to cancel a task that is in progress. + + If this method is not implemented, the task view controller assumes that save and restore are not supported. + If this method returns `YES`, it's recommended that you copy the value of the `restorationData` property of the +task view controller and pass that data to `initWithTask:restorationData:` when it is time + to create a new task view controller to continue from the point at which the user stopped. + + @param taskViewController The calling `ORKTaskViewController` instance. + + @return `YES` if save and restore should be supported; otherwise, `NO`. + */ +- (BOOL)taskViewControllerSupportsSaveAndRestore:(ORKTaskViewController *)taskViewController; + +/** + Asks the delegate if the cancel action should be confirmed + + The task view controller calls this method to determine whether or not to confirm + result save or discard when user attempts to cancel a task that is in progress. + + If this method is not implemented, the task view controller assumes that cancel should be confirmed. + If this method returns `YES`, then cancel action will be confirmed. + If this method returns `NO`, then the results will immediately be discarded. + + @param taskViewController The calling `ORKTaskViewController` instance. + + @return `YES` to confirm cancel action; `NO` to immediately discard the results. + */ +- (BOOL)taskViewControllerShouldConfirmCancel:(ORKTaskViewController *)taskViewController; + +/** + Asks the delegate if there is Learn More content for this step. + + The task view controller calls this method to determine whether a + Learn More button should be displayed for the step. + + The standard templates in ResearchKit for all types of steps include a button + labeled Learn More (or a variant). In consent steps, this is internal to + the implementations of the step and step view controller, but in all other steps, + the task view controller asks its delegate to determine if Learn More content is available, + and to request that it be displayed. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param step The step for which the task view controller needs to know if there is Learn More content. + + @return `NO` if there is no Learn More content to display. + */ +- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController hasLearnMoreForStep:(ORKStep *)step; + +/** + Tells the delegate that the user has tapped the Learn More button in the step. + + The standard templates in ResearchKit for all types of steps include a button + labeled Learn More (or a variant). In consent steps this is internal to + the implementations of the step and step view controller, but in all other steps, + the task view controller asks its delegate to determine if Learn More content is available. + + This method is called only if the delegate returns `YES` to + `taskViewController:hasLearnMoreForStep:` for the current step, and the user + subsequently taps on the Learn More button. + + When this method is called, the app should respond to the Learn More action by + presenting a dialog or other view (possibly modal) that contains the Learn More content. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param stepViewController The `ORKStepViewController` that reported the Learn More event to the task view controller. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreForStep:(ORKStepViewController *)stepViewController; + +/** + Asks the delegate for a custom view Learn More view controller for the specified step. + + If this method is implemented, the task view controller calls it to obtain a + view controller for the learn more item in the step. + + @param step The step for which the learn more controller should be overridden. + + @return A custom `ORKLearMoreStepViewController`, or `nil` to request the default learn more step controller for this step. + */ +- (nullable ORKLearnMoreStepViewController *)taskViewController:(ORKTaskViewController *)taskViewController learnMoreViewControllerForStep:(ORKLearnMoreInstructionStep *)step; + +/** + Asks the delegate for a custom view controller for the specified step. + + If this method is implemented, the task view controller calls it to obtain a + step view controller for the step. + + In most circumstances, the task view controller + can determine which view controller to instantiate for a step. However, if + you want to provide a specific view controller instance, you can call this method to do so. + + The delegate should provide a step view controller implementation for any custom step. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param step The step for which a view controller is requested. + + @return A custom view controller, or `nil` to request the default step controller for this step. + */ +- (nullable ORKStepViewController *)taskViewController:(ORKTaskViewController *)taskViewController viewControllerForStep:(ORKStep *)step; + +/** + Asks the delegate if the task view controller should proceed to the specified step. + + The task view controller calls this method before creating a step view + controller for the next or previous step. + + Generally, when a step is available, the task view controller presents it when + the user taps a forward or backward navigation button, but the results entered or other circumstances can make this action inappropriate. In these + circumstances, you can implement this delegate method and return `NO`. + + If you return `NO`, it's often appropriate to present a dialog or take + some other UI action to explain why navigation was denied. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param step The step for which presentation is requested. + + @return `YES` if navigation should proceed to the specified step; `NO` if navigation should not proceed. + */ +- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController shouldPresentStep:(ORKStep *)step; + +/** + Tells the delegate that a step view controller is about to be displayed. + + The task view controller calls this method before presenting the step + view controller. + + This method gives you an opportunity to modify the step view controller before presentation. + For example, you might want to modify the `learnMoreButtonTitle` or `continueButtonTitle` + properties, or modify other button state. Another possible use case is when a particular + step view controller requires additional setup before presentation. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param stepViewController The `ORKStepViewController` that is about to be displayed. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillAppear:(ORKStepViewController *)stepViewController; + +/** + Tells the delegate that a step will disappear. + + This is called in the `ORKStepViewControllerDelegate` method for `stepViewController:didFinishWithNavigationDirection:` + after saving the result of the step to the task view controller and before navigating to the next/previous step. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param stepViewController The `ORKStepViewController` that has just finished. + @param direction The `ORKStepViewControllerNavigationDirection` of navigation. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillDisappear:(ORKStepViewController *)stepViewController navigationDirection:(ORKStepViewControllerNavigationDirection)direction; + +/** + Tells the delegate that the result has substantively changed. + + The task view controller calls this method when steps start or finish, or if an answer has + changed in the current step due to editing or other user interaction. + + @param taskViewController The calling `ORKTaskViewController` instance. + @param result The current value of the result. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController didChangeResult:(ORKTaskResult *)result; + +/** + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreStep forStepViewController:(ORKStepViewController *)stepViewController; + +@end + + +/** + The `ORKTaskViewController` class is the primary entry point for the presentation of the + ResearchKit framework UI. Note that a task view controller usually presents an `ORKOrderedTask` instance, but it can present any object that implements `ORKTask`. + + The task view controller is intended for modal presentation, which lets the user cancel participation in the task at any time. Typically, the task view + controller displays a navigation bar and conducts right-to-left + navigation for each step as the user progresses through the task. + + The task view controller supports UI state restoration, which allows users to continue a long task when they resume your app. To enable state restoration, set the restoration + identifier and take the appropriate action to restore the task view controller when your app restarts or resumes. + + The task view controller also lets users save their progress in the middle of a task. To support + this scenario in your app, implement `[ORKTaskViewControllerDelegate taskViewControllerSupportsSaveAndRestore:]` in your + task view controller delegate, and return `YES`. If the task completes with the + status `ORKTaskViewControllerFinishReasonSaved`, copy and store the value of the + `restorationData` property. When the user resumes the task, create a + new task view controller using the `initWithTask:restorationData:` initializer, + and present it. + + It is possible to configure the task view controller to prefill surveys with + data from another source, such as a previous run of the same task. + Set the `defaultResultSource` property to use this feature. + + When conducting active tasks which may produce file results, always set the + `outputDirectory` property. Files generated during active steps are written to + the output directory that you specify, and references to these files are returned by `ORKFileResult` + objects in the result hierarchy. + */ +ORK_CLASS_AVAILABLE +@interface ORKTaskViewController : UIViewController + +/** + Returns a newly initialized task view controller. + + This method is the primary designated initializer. + + @param task The task to be presented. + @param taskRunUUID The UUID of this instance of the task. If `nil`, a new UUID is generated. + + @return A new task view controller. + */ +- (instancetype)initWithTask:(nullable id)task taskRunUUID:(nullable NSUUID *)taskRunUUID NS_DESIGNATED_INITIALIZER; + +/** + Returns a new task view controller initialized from data in the given unarchiver. + + This method lets you instantiate a task view controller from a storyboard, although this is an atypical use case. This method is a designated initializer. + + @param aDecoder The coder from which to initialize the task view controller. + + @return A new task view controller. + */ +- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER; + +/** + Returns a newly initialized task view controller using the nib file in the specified bundle. + + This method is a designated initializer. + + @param nibNameOrNil The name of the nib file from which to instantiate the task view controller. + @param nibBundleOrNil The name of the bundle in which to search for the nib file. + + @return A new task view controller. + */ +- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil bundle:(nullable NSBundle *)nibBundleOrNil NS_DESIGNATED_INITIALIZER; + +/** + Creates a new task view controller from the specified restoration data. + + Call this method to restart a task when you have restoration data stored for a + previous run of the task, in which the user canceled their current task and saved their progress. + + This method restores the presentation of the task to the point at which the user stopped. + If the restoration data is not valid, an exception may be thrown. + + @param task The task to be presented. + @param data Data obtained from the `restorationData` property of a previous + task view controller instance. + @param delegate The delegate for the task view controller. + + @return A new task view controller. + */ +- (instancetype)initWithTask:(id)task restorationData:(nullable NSData *)data delegate:(id)delegate error:(NSError* __autoreleasing *)errorOut; + +/** + Creates a new task view controller that starts the task at the step that has the specified step identifier. + + Call this method to start a task from a specific step. Additionally, you can supply a defaultResultSource to resume a + partially completed task, or to provide your own prefilled results. + + if `startingStepIdentifier` is nil, the task starts from the first step. + + @param task The task to be presented. + @param startingStepIdentifier The identifier of the step to start the task on. + @param ongoingResult An optional task result from a previous run of the task. If you provide a startingStepIdentifier, it is recommended that you provide a partial task result including results of the steps preceeding the starting step. Not doing so will disable back navigtion on ORKNavigableOrderedTasks. + @param defaultResultSource A source that the task view controller can consult to obtain default answers for questions provided in question steps and form steps. + @param delegate The delegate for the task view controller. + + @return A new task view controller. + */ +- (instancetype)initWithTask:(id)task + startingStepIdentifier:(nullable NSString *)startingStepIdentifier + ongoingResult:(nullable ORKTaskResult *)ongoingResult + defaultResultSource:(nullable id)defaultResultSource + delegate:(id)delegate; + +/** + The delegate for the task view controller. + + There are many optional methods in the task view controller protocol, but the delegate must support + completion. When the task view controller completes its task, it is the delegate's + responsibility to dismiss it. + + See also: `[ORKTaskViewControllerDelegate taskViewController:didFinishWithReason:error:]`. + */ +@property (nonatomic, weak, nullable) id delegate; + +/** + The task for this task view controller. + + The task functions as the data source for an `ORKTaskViewController` object, providing + the steps that the user must complete in order to complete the task. + It is an error to change the task after presenting the task view controller. + */ +@property (nonatomic, strong, nullable) id task; + +/** + A source that the task view controller can consult to obtain default answers + for questions provided in question steps and form steps. + + The source can provide default answers, perhaps based on previous runs of + the same task, which will be used to prefill question and form items. + For example, an `ORKTaskResult` object from a previous run of the task can function as + an `ORKTaskResultSource` object, because `ORKTaskResult` implements the protocol. + */ +@property (nonatomic, strong, nullable) id defaultResultSource; + +/** + A unique identifier (UUID) for this presentation of the task. + + The task run UUID is a unique identifier for this run of the task view controller. + All results produced by this instance are tagged with this UUID. + + The task run UUID is preserved across UI state restoration, or across task + save and restore. + + @note It is an error to set the value of `taskRunUUID` after the first time the task view controller + is presented. + */ +@property (nonatomic, copy) NSUUID *taskRunUUID; + +/** + The current state of the task result. (read-only) + + Use this property to obtain or inspect the results of the task. The results + are hierarchical; the children of `result` are `ORKStepResult` instances, + one for each step that the user visited during the task. + + If the user uses the Back button to go back through the steps, the + results of steps that are ahead of the currently visible step are not included + in the result. + */ +@property (nonatomic, copy, readonly) ORKTaskResult *result; + +/** + Snapshot data that can be used for future restoration. + + When the user taps Cancel during a task and selects the Save option, + the `[ORKTaskViewControllerDelegate taskViewController:didFinishWithReason:error:]` + method is called with `ORKTaskViewControllerFinishReasonSaved`. When that happens, + use `restorationData` to obtain restoration data that can be used to restore + the task at a later date. + + Use `initWithTask:restorationData:` to create a new task view controller that + restores the current state. + */ +@property (nonatomic, copy, readonly, nullable) NSData *restorationData; + +/** + File URL for the directory in which to store generated data files. + + Active steps with recorders (and potentially other steps) can save data + to files during the progress of the task. This property specifies where such + data should be written. If no output directory is specified, active steps + that require writing data to disk, such as those with recorders, will typically + fail at runtime. + + In general, set this property after instantiating the task view + controller and before presenting it. + + Before presenting the view controller, set the `outputDirectory` property to specify a + path where files should be written when an `ORKFileResult` object must be returned for + a step. + */ +@property (nonatomic, copy, nullable) NSURL *outputDirectory; + +/** + A Boolean value indicating whether progress is shown in the navigation bar. + + Setting this property to `YES` does not display progress if you don't also implement the `progress` + method of `ORKTask`. + + The default value of this property is `YES`. To disable the display of progress in the navigation bar, set the value to `NO`. + */ +@property (nonatomic, assign) BOOL showsProgressInNavigationBar; + +/** + The current step view controller. + + The task view controller instantiates and presents a series of step view + controllers. The current step view controller is the one that is currently + visible on screen. + + The value of this property may be `nil` if the task view controller has not yet been presented. + */ +@property (nonatomic, strong, readonly, nullable) ORKStepViewController *currentStepViewController; + +/** + Forces navigation to the next step. + + Call this method to force forward navigation. This method is called by the framework + if the user takes an action that requires navigation, or if the step is timed + and the timer completes. + */ +- (void)goForward; + +/** + Forces navigation to the previous step. + + Call this method to force backward navigation. This method is called by the framework + if the user takes an action that requires backward navigation. + */ +- (void)goBackward; + +- (void)flipToFirstPage; + +/** + Returns the step after the provided step + + @param step The `ORKStep` before the one returned. + @return The `ORKStep` after `step`. + */ +- (ORKStep *)stepAfterStep:(ORKStep *)step; + +/** + Returns true if the step provided is instruction step and is the first step in the task. + */ +- (BOOL)isStepLastBeginningInstructionStep:(ORKStep *)step; + +/** + A Boolean value indicating whether the navigation bar is hidden. + + By default, the task view controller includes a visible navigation bar. To disable the display of the navigation bar, set this property to `NO`. + */ +@property (nonatomic, getter=isNavigationBarHidden) BOOL navigationBarHidden; + +/** + Shows or hides the navigation bar, with optional animation. + + @param hidden `YES` to hide the navigation bar; otherwise, `NO`. + @param animated `YES` to animate the show or hide operation; otherwise, `NO`. + */ +- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated; + +/** + Returns a learn more view controller for the given step. + @param step The step needing a learn more view controller + */ +-(ORKLearnMoreStepViewController *)learnMoreViewControllerForStep:(ORKLearnMoreInstructionStep *)step; + +/** + The navigation bar for the task view controller. (read-only) + + You can use this method to customize the appearance of the task view controller's navigation bar. + */ +@property (nonatomic, readonly) UINavigationBar *navigationBar; + +/** + A Boolean value indicating whether the task view controller can be dismissed directly, without showing the "End Task" action sheet, when + a user taps the "Cancel" button. + + The default value of this property is `NO`. To allow the task view controller to be dismissed directly with its results discarded, set + the value to `YES`. + */ +@property (nonatomic, assign) BOOL discardable; + +@property (nonatomic) ORKTaskViewControllerReviewMode reviewMode; + +@property (nonatomic, nullable) ORKInstructionStep * reviewInstructionStep; + +/** + A enum that determines if the progress numbers displayed within each step is based on the total amount of questions throughout the task or the total amount of questoins within that particular step. + + The default value is ORKTaskViewControllerProgressModeTotalQuestions + */ + +@property (nonatomic) ORKTaskViewControllerProgressMode progressMode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.m new file mode 100755 index 0000000..f3721da --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController.m @@ -0,0 +1,1673 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTaskViewController.h" + +#import "ORKActiveStepViewController.h" +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKFormStepViewController.h" +#import "ORKQuestionStepViewController.h" +#import "ORKReviewStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTappingIntervalStepViewController.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKVisualConsentStepViewController.h" +#import "ORKLearnMoreStepViewController.h" + +#import "ORKActiveStep.h" +#import "ORKCollectionResult_Private.h" +#import "ORKFormStep.h" +#import "ORKInstructionStep.h" +#import "ORKOrderedTask.h" +#import "ORKQuestionStep.h" +#import "ORKResult_Private.h" +#import "ORKReviewStep_Internal.h" +#import "ORKStep_Private.h" +#import "ORKTappingIntervalStep.h" +#import "ORKVisualConsentStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKObserver.h" +#import "ORKSkin.h" +#import "ORKBorderedButton.h" +#import "ORKTaskReviewViewController.h" + +@import AVFoundation; +@import CoreMotion; +#import + +typedef void (^_ORKLocationAuthorizationRequestHandler)(BOOL success); + +@interface ORKLocationAuthorizationRequester : NSObject + +- (instancetype)initWithHandler:(_ORKLocationAuthorizationRequestHandler)handler; + +- (void)resume; + +@end + + +@implementation ORKLocationAuthorizationRequester { + CLLocationManager *_manager; + _ORKLocationAuthorizationRequestHandler _handler; + BOOL _started; +} + +- (instancetype)initWithHandler:(_ORKLocationAuthorizationRequestHandler)handler { + self = [super init]; + if (self) { + _handler = handler; + _manager = [CLLocationManager new]; + _manager.delegate = self; + } + return self; +} + +- (void)dealloc { + _manager.delegate = nil; +} + +- (void)resume { + if (_started) { + return; + } + + _started = YES; + NSString *whenInUseKey = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]; + NSString *alwaysKey = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]; + + CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; + if ((status == kCLAuthorizationStatusNotDetermined) && (whenInUseKey || alwaysKey)) { + if (alwaysKey) { + [_manager requestAlwaysAuthorization]; + } else { + [_manager requestWhenInUseAuthorization]; + } + } else { + [self finishWithResult:(status != kCLAuthorizationStatusDenied)]; + } +} + +- (void)finishWithResult:(BOOL)result { + if (_handler) { + _handler(result); + _handler = nil; + } +} + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + if (_handler && _started && status != kCLAuthorizationStatusNotDetermined) { + [self finishWithResult:(status != kCLAuthorizationStatusDenied)]; + } +} + +@end + +@interface ORKTaskViewController () { + NSMutableDictionary *_managedResults; + NSMutableArray *_managedStepIdentifiers; + ORKScrollViewObserver *_scrollViewObserver; + BOOL _hasBeenPresented; + BOOL _hasRequestedHealthData; + BOOL _saveable; + ORKPermissionMask _grantedPermissions; + NSSet *_requestedHealthTypesForRead; + NSSet *_requestedHealthTypesForWrite; + NSURL *_outputDirectory; + + NSDate *_presentedDate; + NSDate *_dismissedDate; + + NSString *_lastBeginningInstructionStepIdentifier; + NSString *_lastRestorableStepIdentifier; + + BOOL _hasAudioSession; // does not need state restoration - temporary + + NSString *_restoredTaskIdentifier; + NSString *_restoredStepIdentifier; + BOOL _hasLockedVolume; + float _savedVolume; + float _lockedVolume; + + UINavigationController *_childNavigationController; + UIViewController *_previousToTopControllerInNavigationStack; +} + +@property (nonatomic, strong) ORKStepViewController *currentStepViewController; +@property (nonatomic) ORKTaskReviewViewController *taskReviewViewController; + +@end + + +@implementation ORKTaskViewController + +@synthesize taskRunUUID=_taskRunUUID; + +static NSString *const _ChildNavigationControllerRestorationKey = @"childNavigationController"; + +- (void)setUpChildNavigationController { + _previousToTopControllerInNavigationStack = nil; + UIViewController *emptyViewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; + _childNavigationController = [[UINavigationController alloc] initWithRootViewController:emptyViewController]; + _childNavigationController.delegate = self; + + [_childNavigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; + [_childNavigationController.navigationBar setShadowImage:[UIImage new]]; + [_childNavigationController.navigationBar setTranslucent:NO]; + [_childNavigationController.navigationBar setBarTintColor:ORKColor(ORKBackgroundColorKey)]; + + if (@available(iOS 13.0, *)) { + [_childNavigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor secondaryLabelColor]}]; + _childNavigationController.navigationBar.prefersLargeTitles = NO; + } else { + [_childNavigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor systemGrayColor]}]; + } + [_childNavigationController.view setBackgroundColor:UIColor.clearColor]; + + [self addChildViewController:_childNavigationController]; + _childNavigationController.view.frame = self.view.frame; + _childNavigationController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_childNavigationController.view]; + [_childNavigationController didMoveToParentViewController:self]; + _childNavigationController.restorationClass = [self class]; + _childNavigationController.restorationIdentifier = _ChildNavigationControllerRestorationKey; +} + +- (instancetype)commonInitWithTask:(id)task taskRunUUID:(NSUUID *)taskRunUUID { + [self setTask: task]; + + self.showsProgressInNavigationBar = YES; + self.discardable = NO; + self.progressMode = ORKTaskViewControllerProgressModeQuestionsPerStep; + _saveable = NO; + + _managedResults = [NSMutableDictionary dictionary]; + _managedStepIdentifiers = [NSMutableArray array]; + + self.taskRunUUID = taskRunUUID ?: [NSUUID UUID]; + + // Ensure taskRunUUID has non-nil valuetaskRunUUID + (void)[self taskRunUUID]; + self.restorationClass = [ORKTaskViewController class]; + + _hasLockedVolume = NO; + + return self; +} + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + return [self commonInitWithTask:nil taskRunUUID:nil]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + return [self commonInitWithTask:nil taskRunUUID:nil]; +} +#pragma clang diagnostic pop + +- (instancetype)initWithTask:(id)task taskRunUUID:(NSUUID *)taskRunUUID { + self = [super initWithNibName:nil bundle:nil]; + return [self commonInitWithTask:task taskRunUUID:taskRunUUID]; +} + +- (instancetype)initWithTask:(id)task restorationData:(nullable NSData *)data delegate:(id)delegate error:(NSError* __autoreleasing *)errorOut { + + self = [self initWithTask:task taskRunUUID:nil]; + + if (self) { + self.delegate = delegate; + if (data != nil) { + self.restorationClass = [self class]; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + [self decodeRestorableStateWithCoder:unarchiver]; + [self applicationFinishedRestoringState]; + + if (unarchiver == nil) { + *errorOut = [NSError errorWithDomain:ORKErrorDomain code:ORKErrorException userInfo:@{NSLocalizedDescriptionKey: ORKLocalizedString(@"RESTORE_ERROR_CANNOT_DECODE", nil)}]; + } + } + } + return self; +} + +- (instancetype)initWithTask:(id)task + startingStepIdentifier:(NSString *)startingStepIdentifier + ongoingResult:(nullable ORKTaskResult *)ongoingResult + defaultResultSource:(nullable id)defaultResultSource + delegate:(id)delegate { + + self = [self initWithTask:task taskRunUUID:nil]; + + if (self) { + _delegate = delegate; + _defaultResultSource = defaultResultSource; + if (ongoingResult != nil) { + for (ORKResult *stepResult in ongoingResult.results) { + [_managedStepIdentifiers addObject:stepResult.identifier]; + _managedResults[stepResult.identifier] = stepResult; + } + } + if (startingStepIdentifier != nil) { + _restoredStepIdentifier = startingStepIdentifier; + } + } + return self; +} + +- (void)setTaskRunUUID:(NSUUID *)taskRunUUID { + if (_hasBeenPresented) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot change task instance UUID after presenting task controller" userInfo:nil]; + } + + _taskRunUUID = [taskRunUUID copy]; +} + +- (void)setTask:(id)task { + if (_hasBeenPresented) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot change task after presenting task controller" userInfo:nil]; + } + + if (task) { + if (![task conformsToProtocol:@protocol(ORKTask)]) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"Expected a task" userInfo:nil]; + } + if (task.identifier == nil) { + ORK_Log_Debug("Task identifier should not be nil."); + } + if ([task respondsToSelector:@selector(validateParameters)]) { + [task validateParameters]; + } + } + + _hasRequestedHealthData = NO; + _task = task; +} + +- (UIBarButtonItem *)defaultCancelButtonItem { + return [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) style:UIBarButtonItemStylePlain target:self action:@selector(cancelAction:)]; +} + +- (UIBarButtonItem *)defaultLearnMoreButtonItem { + return [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_LEARN_MORE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(learnMoreAction:)]; +} + +- (void)requestHealthStoreAccessWithReadTypes:(NSSet *)readTypes + writeTypes:(NSSet *)writeTypes + handler:(void (^)(void))handler { + NSParameterAssert(handler != nil); + if ((![HKHealthStore isHealthDataAvailable]) || (!readTypes && !writeTypes)) { + _requestedHealthTypesForRead = nil; + _requestedHealthTypesForWrite = nil; + handler(); + return; + } + + _requestedHealthTypesForRead = readTypes; + _requestedHealthTypesForWrite = writeTypes; + + __block HKHealthStore *healthStore = [HKHealthStore new]; + [healthStore requestAuthorizationToShareTypes:writeTypes readTypes:readTypes completion:^(BOOL success, NSError *error) { + ORK_Log_Error("Health access: error=%@", error); + dispatch_async(dispatch_get_main_queue(), handler); + + // Clear self-ref. + healthStore = nil; + }]; +} + +- (void)requestPedometerAccessWithHandler:(void (^)(BOOL success))handler { + NSParameterAssert(handler != nil); + if (![CMPedometer isStepCountingAvailable]) { + handler(NO); + return; + } + + __block CMPedometer *pedometer = [CMPedometer new]; + [pedometer queryPedometerDataFromDate:[NSDate dateWithTimeIntervalSinceNow:-100] + toDate:[NSDate date] + withHandler:^(CMPedometerData *pedometerData, NSError *error) { + ORK_Log_Error("Pedometer access: error=%@", error); + + BOOL success = YES; + if ([[error domain] isEqualToString:CMErrorDomain]) { + switch (error.code) { + case CMErrorMotionActivityNotAuthorized: + case CMErrorNotAuthorized: + case CMErrorNotAvailable: + case CMErrorNotEntitled: + case CMErrorMotionActivityNotAvailable: + case CMErrorMotionActivityNotEntitled: + success = NO; + break; + default: + break; + } + } + + dispatch_async(dispatch_get_main_queue(), ^(void) { handler(success); }); + + // Clear self ref to release. + pedometer = nil; + }]; +} + +- (void)requestAudioRecordingAccessWithHandler:(void (^)(BOOL success))handler { + NSParameterAssert(handler != nil); + [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(granted); + }); + }]; +} + +- (void)requestCameraAccessWithHandler:(void (^)(BOOL success))handler { + NSParameterAssert(handler != nil); + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + dispatch_async(dispatch_get_main_queue(), ^{ + handler(granted); + }); + }]; +} + +- (void)requestLocationAccessWithHandler:(void (^)(BOOL success))handler { + NSParameterAssert(handler != nil); + + // Self-retain; clear the retain cycle in the handler block. + __block ORKLocationAuthorizationRequester *requester = + [[ORKLocationAuthorizationRequester alloc] + initWithHandler:^(BOOL success) { + handler(success); + + requester = nil; + }]; + + [requester resume]; +} + +- (ORKPermissionMask)desiredPermissions { + ORKPermissionMask permissions = ORKPermissionNone; + if ([self.task respondsToSelector:@selector(requestedPermissions)]) { + permissions = [self.task requestedPermissions]; + } + return permissions; +} + +- (void)requestHealthAuthorizationWithCompletion:(void (^)(void))completion { + if (_hasRequestedHealthData) { + if (completion) completion(); + return; + } + + NSSet *readTypes = nil; + if ([self.task respondsToSelector:@selector(requestedHealthKitTypesForReading)]) { + readTypes = [self.task requestedHealthKitTypesForReading]; + } + + NSSet *writeTypes = nil; + if ([self.task respondsToSelector:@selector(requestedHealthKitTypesForWriting)]) { + writeTypes = [self.task requestedHealthKitTypesForWriting]; + } + + ORKPermissionMask permissions = [self desiredPermissions]; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + ORK_Log_Debug("Requesting health access"); + [self requestHealthStoreAccessWithReadTypes:readTypes + writeTypes:writeTypes + handler:^{ + dispatch_semaphore_signal(semaphore); + }]; + }); + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + if (permissions & ORKPermissionCoreMotionAccelerometer) { + _grantedPermissions |= ORKPermissionCoreMotionAccelerometer; + } + if (permissions & ORKPermissionCoreMotionActivity) { + dispatch_async(dispatch_get_main_queue(), ^{ + ORK_Log_Debug("Requesting pedometer access"); + [self requestPedometerAccessWithHandler:^(BOOL success) { + if (success) { + _grantedPermissions |= ORKPermissionCoreMotionActivity; + } else { + _grantedPermissions &= ~ORKPermissionCoreMotionActivity; + } + dispatch_semaphore_signal(semaphore); + }]; + }); + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + if (permissions & ORKPermissionAudioRecording) { + dispatch_async(dispatch_get_main_queue(), ^{ + ORK_Log_Debug("Requesting audio access"); + [self requestAudioRecordingAccessWithHandler:^(BOOL success) { + if (success) { + _grantedPermissions |= ORKPermissionAudioRecording; + } else { + _grantedPermissions &= ~ORKPermissionAudioRecording; + } + dispatch_semaphore_signal(semaphore); + }]; + }); + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + if (permissions & ORKPermissionCoreLocation) { + dispatch_async(dispatch_get_main_queue(), ^{ + ORK_Log_Debug("Requesting location access"); + [self requestLocationAccessWithHandler:^(BOOL success) { + if (success) { + _grantedPermissions |= ORKPermissionCoreLocation; + } else { + _grantedPermissions &= ~ORKPermissionCoreLocation; + } + dispatch_semaphore_signal(semaphore); + }]; + }); + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + if (permissions & ORKPermissionCamera) { + dispatch_async(dispatch_get_main_queue(), ^{ + ORK_Log_Debug("Requesting camera access"); + [self requestCameraAccessWithHandler:^(BOOL success) { + if (success) { + _grantedPermissions |= ORKPermissionCamera; + } else { + _grantedPermissions &= ~ORKPermissionCamera; + } + dispatch_semaphore_signal(semaphore); + }]; + }); + + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + + _hasRequestedHealthData = YES; + dispatch_async(dispatch_get_main_queue(), ^{ + _hasRequestedHealthData = YES; + if (completion) completion(); + }); + }); +} + +- (void)startAudioPromptSessionIfNeeded { + id task = self.task; + if ([task isKindOfClass:[ORKOrderedTask class]]) { + if ([(ORKOrderedTask *)task providesBackgroundAudioPrompts]) { + NSError *error = nil; + if (![self startAudioPromptSessionWithError:&error]) { + // User-visible console log message + ORK_Log_Error("Failed to start audio prompt session: %@", error); + } + } + } +} + +- (BOOL)startAudioPromptSessionWithError:(NSError **)errorOut { + NSError *error = nil; + AVAudioSession *session = [AVAudioSession sharedInstance]; + BOOL success = YES; + // Use PlayAndRecord to avoid overwriting the category being used by + // recording configurations. + if (![session setCategory:AVAudioSessionCategoryPlayback + withOptions:0 + error:&error]) { + success = NO; + ORK_Log_Error("Could not start audio session: %@", error); + } + + // We are setting the session active so that we can stay live to play audio + // in the background. + if (success && ![session setActive:YES withOptions:0 error:&error]) { + success = NO; + ORK_Log_Error("Could not set audio session active: %@", error); + } + + if (errorOut != NULL) { + *errorOut = error; + } + + _hasAudioSession = _hasAudioSession || success; + if (_hasAudioSession) { + ORK_Log_Debug("*** Started audio session"); + } + return success; +} + +- (void)finishAudioPromptSession { + if (_hasAudioSession) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + NSError *error = nil; + if (![session setActive:NO withOptions:0 error:&error]) { + ORK_Log_Error("Could not deactivate audio session: %@", error); + } else { + ORK_Log_Debug("*** Finished audio session"); + } + } +} + +- (NSSet *)requestedHealthTypesForRead { + return _requestedHealthTypesForRead; +} + +- (NSSet *)requestedHealthTypesForWrite { + return _requestedHealthTypesForWrite; +} + +- (void)loadView { + self.view = [[UIView alloc] initWithFrame:CGRectZero]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self setUpChildNavigationController]; + + if (_restoredStepIdentifier) { + [self applicationFinishedRestoringState]; + } +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + if (!_task) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Attempted to present task view controller without a task" userInfo:nil]; + } + + if (!_hasBeenPresented) { + // Add first step viewController + ORKStep *step = [self nextStep]; + if ([self shouldPresentStep:step]) { + + if (![step isKindOfClass:[ORKInstructionStep class]]) { + [self startAudioPromptSessionIfNeeded]; + [self requestHealthAuthorizationWithCompletion:nil]; + } + + ORKStepViewController *firstViewController = [self viewControllerForStep:step]; + [self showStepViewController:firstViewController goForward:YES animated:NO]; + + } + _hasBeenPresented = YES; + } + + // Record TaskVC's start time. + // TaskVC is one time use only, no need to update _startDate later. + if (!_presentedDate) { + _presentedDate = [NSDate date]; + } + + // Clear endDate if current TaskVC got presented again + _dismissedDate = nil; + + #if defined(__IPHONE_13_0) + if (@available(iOS 13.0, *)) { + if ([self shouldDismissWithSwipe] == NO) { + self.modalInPresentation = YES; + } + } + #endif + + if (_taskReviewViewController) { + [_childNavigationController setViewControllers:@[_taskReviewViewController] animated:NO]; + [self setTaskReviewViewControllerNavbar]; + } +} + +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; + + // Set endDate on TaskVC is dismissed, + // because nextResponder is not nil when current TaskVC is covered by another modal view + if (self.nextResponder == nil) { + _dismissedDate = [NSDate date]; + } +} + +- (NSArray *)managedResults { + NSMutableArray *results = [NSMutableArray new]; + + [_managedStepIdentifiers enumerateObjectsUsingBlock:^(NSString *identifier, NSUInteger idx, BOOL *stop) { + id key = identifier; + ORKResult *result = _managedResults[key]; + NSAssert2(result, @"Result should not be nil for identifier %@ with key %@", identifier, key); + [results addObject:result]; + }]; + + return [results copy]; +} + +- (void)setManagedResult:(ORKStepResult *)result forKey:(NSString *)aKey { + if (aKey == nil) { + return; + } + + if (result == nil || NO == [result isKindOfClass:[ORKStepResult class]]) { + @throw [NSException exceptionWithName:NSGenericException reason:[NSString stringWithFormat: @"Expect result object to be `ORKStepResult` type and not nil: {%@ : %@}", aKey, result] userInfo:nil]; + return; + } + + // Manage last result tracking (used in predicate navigation) + // If the previous result and the replacement result are the same result then `isPreviousResult` + // will be set to `NO` otherwise it will be marked with `YES`. + ORKStepResult *previousResult = _managedResults[aKey]; + previousResult.isPreviousResult = YES; + result.isPreviousResult = NO; + + if (_managedResults == nil) { + _managedResults = [NSMutableDictionary new]; + } + _managedResults[aKey] = result; + + // Also point to the object using a unique key + NSUInteger idx = _managedStepIdentifiers.count; + if ([_managedStepIdentifiers.lastObject isEqualToString:aKey]) { + idx--; + } + _managedResults[aKey] = result; +} + +- (ORKTaskResult *)result { + // TODO: update current implementation. + // setManagedResult for currentStepViewController should not be called every single time this method is called. + ORKTaskResult *result = [[ORKTaskResult alloc] initWithTaskIdentifier:[self.task identifier] taskRunUUID:self.taskRunUUID outputDirectory:self.outputDirectory]; + result.startDate = _presentedDate; + result.endDate = _dismissedDate ? :[NSDate date]; + + // Update current step result + [self setManagedResult:[self.currentStepViewController result] forKey:self.currentStepViewController.step.identifier]; + + result.results = [self managedResults]; + + return result; +} + +- (NSData *)restorationData { + NSMutableData *data = [[NSMutableData alloc] init]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [self encodeRestorableStateWithCoder:archiver]; + [archiver finishEncoding]; + + return [data copy]; +} + +- (void)ensureDirectoryExists:(NSURL *)outputDirectory { + // Only verify existence if the output directory is non-nil. + // But, even if the output directory is nil, we still set it and forward to the step VC. + if (outputDirectory != nil) { + BOOL isDirectory = NO; + BOOL directoryExists = [[NSFileManager defaultManager] fileExistsAtPath:outputDirectory.path isDirectory:&isDirectory]; + + if (!directoryExists) { + NSError *error = nil; + if (![[NSFileManager defaultManager] createDirectoryAtURL:outputDirectory withIntermediateDirectories:YES attributes:nil error:&error]) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Could not create output directory and output directory does not exist" userInfo:@{@"error": error}]; + } + isDirectory = YES; + } else if (!isDirectory) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Desired outputDirectory is not a directory or could not be created." userInfo:nil]; + } + } +} + +- (void)setOutputDirectory:(NSURL *)outputDirectory { + if (_hasBeenPresented) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot change outputDirectory after presenting task controller" userInfo:nil]; + } + [self ensureDirectoryExists:outputDirectory]; + + _outputDirectory = [outputDirectory copy]; + + [[self currentStepViewController] setOutputDirectory:_outputDirectory]; +} + +- (void)setRegisteredScrollView:(UIScrollView *)registeredScrollView { + if (_registeredScrollView != registeredScrollView) { + + _registeredScrollView = registeredScrollView; + + // Stop old observer + _scrollViewObserver = nil; + } +} + +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep fromStepViewController:(nonnull ORKStepViewController *)stepViewController { + if ([self.delegate respondsToSelector:@selector(taskViewController:learnMoreButtonPressedWithStep:forStepViewController:)]) { + [self.delegate taskViewController:self learnMoreButtonPressedWithStep:learnMoreInstructionStep forStepViewController:stepViewController]; + } +} + +- (void)suspend { + [self finishAudioPromptSession]; + [ORKDynamicCast(_currentStepViewController, ORKActiveStepViewController) suspend]; +} + +- (void)resume { + [self startAudioPromptSessionIfNeeded]; + [ORKDynamicCast(_currentStepViewController, ORKActiveStepViewController) resume]; +} + +- (void)goForward { + [_currentStepViewController goForward]; +} + +- (void)goBackward { + [_currentStepViewController goBackward]; +} + +- (UIInterfaceOrientationMask)supportedInterfaceOrientations { + UIInterfaceOrientationMask supportedOrientations; + if (self.currentStepViewController) { + supportedOrientations = self.currentStepViewController.supportedInterfaceOrientations; + } else { + supportedOrientations = [[self nextStep].stepViewControllerClass supportedInterfaceOrientations]; + } + return supportedOrientations; +} + +#pragma mark - internal helpers + +- (void)updateLastBeginningInstructionStepIdentifierForStep:(ORKStep *)step + goForward:(BOOL)goForward { + if (NO == goForward) { + // Going backward, check current step to nil saved state + if (_lastBeginningInstructionStepIdentifier != nil && + [_currentStepViewController.step.identifier isEqualToString:_lastBeginningInstructionStepIdentifier]) { + + _lastBeginningInstructionStepIdentifier = nil; + } + // Don't return here, because the *next* step might NOT be an instruction step + // the next time we look. + } + + ORKStep *nextStep = [self.task stepAfterStep:step withResult:[self result]]; + BOOL isNextStepInstructionStep = [nextStep isKindOfClass:[ORKInstructionStep class]]; + + if (_lastBeginningInstructionStepIdentifier == nil && + nextStep && NO == isNextStepInstructionStep) { + _lastBeginningInstructionStepIdentifier = step.identifier; + } +} + +- (BOOL)isStepLastBeginningInstructionStep:(ORKStep *)step { + if (!step) { + return NO; + } + return (_lastBeginningInstructionStepIdentifier != nil && + [step isKindOfClass:[ORKInstructionStep class]]&& + [step.identifier isEqualToString:_lastBeginningInstructionStepIdentifier]); +} + +- (BOOL)grantedAtLeastOnePermission { + // Return YES, if no desired permission or granted at least one permission. + ORKPermissionMask desiredMask = [self desiredPermissions]; + return (desiredMask == 0 || ((desiredMask & _grantedPermissions) != 0)); +} + +- (void)showStepViewController:(ORKStepViewController *)stepViewController goForward:(BOOL)goForward animated:(BOOL)animated { + if (nil == stepViewController) { + return; + } + + ORKStep *step = stepViewController.step; + [self updateLastBeginningInstructionStepIdentifierForStep:step goForward:goForward]; + + ORKStepViewController *fromController = self.currentStepViewController; + if (fromController && animated && [self isStepLastBeginningInstructionStep:fromController.step]) { + [self startAudioPromptSessionIfNeeded]; + + if ( [self grantedAtLeastOnePermission] == NO) { + // Do the health request and THEN proceed. + [self requestHealthAuthorizationWithCompletion:^{ + + // If we are able to collect any data, proceed. + // An alternative rule would be to never proceed if any permission fails. + // However, since iOS does not re-present requests for access, we + // can easily fail even if the user does not see a dialog, which would + // be highly unexpected. + if ([self grantedAtLeastOnePermission] == NO) { + [self reportError:[NSError errorWithDomain:NSCocoaErrorDomain + code:NSUserCancelledError + userInfo:@{@"reason": @"Required permissions not granted."}] + onStep:fromController.step]; + } else { + [self showStepViewController:stepViewController goForward:goForward animated:animated]; + } + }]; + return; + } + } + + if (step.identifier && ![_managedStepIdentifiers.lastObject isEqualToString:step.identifier]) { + [_managedStepIdentifiers addObject:step.identifier]; + } + if ([step isRestorable] && !(stepViewController.isBeingReviewed && stepViewController.parentReviewStep.isStandalone)) { + _lastRestorableStepIdentifier = step.identifier; + } + + ORKStepViewControllerNavigationDirection stepDirection = goForward ? ORKStepViewControllerNavigationDirectionForward : ORKStepViewControllerNavigationDirectionReverse; + + [stepViewController willNavigateDirection:stepDirection]; + + ORK_Log_Debug("%@ %@", self, stepViewController); + + self.registeredScrollView = nil; + + // Switch to non-animated transition if the application is not in the foreground. + animated = animated && ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground); + + // Update currentStepViewController now, so we don't accept additional transition requests + // from the same VC. + _currentStepViewController = stepViewController; + [self setUpProgressLabelForStepViewController:stepViewController]; + + NSMutableArray *newViewControllers = [NSMutableArray new]; + // Add at most two previous step view controllers to support the back action on the navigation controller stack + _previousToTopControllerInNavigationStack = nil; + if (stepViewController.hasPreviousStep) { + ORKStep *previousStep = [self.task stepBeforeStep:step withResult:self.result]; + if (previousStep) { + ORKStepViewController *previousStepViewController = [self viewControllerForStep:previousStep isPreviousViewController:YES]; + previousStepViewController.navigationItem.title = nil; // Make sure the back button shows "Back" + if (previousStepViewController.hasPreviousStep) { + ORKStep *previousToPreviousStep = [self.task stepBeforeStep:previousStep withResult:self.result]; + if (previousToPreviousStep) { + ORKStepViewController *previousToPreviousStepViewController = [self viewControllerForStep:previousToPreviousStep isPreviousViewController:YES]; + previousToPreviousStepViewController.navigationItem.title = nil; // Make sure the back button shows "Back" + [newViewControllers addObject:previousToPreviousStepViewController]; + } + } + _previousToTopControllerInNavigationStack = previousStepViewController; + [newViewControllers addObject:previousStepViewController]; + } + } + [newViewControllers addObject:stepViewController]; + if (newViewControllers != _childNavigationController.viewControllers) { + [_childNavigationController setViewControllers:newViewControllers animated:animated]; + } +} + +- (BOOL)shouldPresentStep:(ORKStep *)step { + BOOL shouldPresent = (step != nil); + + if (shouldPresent && [self.delegate respondsToSelector:@selector(taskViewController:shouldPresentStep:)]) { + shouldPresent = [self.delegate taskViewController:self shouldPresentStep:step]; + } + + return shouldPresent; +} + +- (ORKStep *)nextStep { + ORKStep *step = nil; + + if ([self.task respondsToSelector:@selector(stepAfterStep:withResult:)]) { + step = [self.task stepAfterStep:self.currentStepViewController.step withResult:[self result]]; + } + + return step; + +} + +- (ORKStep *)prevStep { + ORKStep *step = nil; + + if ([self.task respondsToSelector:@selector(stepBeforeStep:withResult:)]) { + step = [self.task stepBeforeStep:self.currentStepViewController.step withResult:[self result]]; + } + + return step; +} + +- (NSArray *)stepsForReviewStep:(ORKReviewStep *)reviewStep { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + if (reviewStep.isStandalone) { + steps = nil; + } else { + ORKWeakTypeOf(self) weakSelf = self; + [_managedStepIdentifiers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + ORKStep *nextStep = [strongSelf.task stepWithIdentifier:(NSString*) obj]; + if (nextStep && ![nextStep.identifier isEqualToString:reviewStep.identifier]) { + [steps addObject:nextStep]; + } else { + *stop = YES; + } + }]; + } + return [steps copy]; +} + +-(ORKLearnMoreStepViewController *)learnMoreViewControllerForStep:(ORKLearnMoreInstructionStep *)step { + if (step == nil) { + return nil; + } + + ORKLearnMoreStepViewController *learnMoreViewController = nil; + + if ([self.delegate respondsToSelector:@selector(taskViewController:learnMoreViewControllerForStep:)]) { + learnMoreViewController = [self.delegate taskViewController:self learnMoreViewControllerForStep:step]; + } + + if (!learnMoreViewController) { + learnMoreViewController = [[ORKLearnMoreStepViewController alloc] initWithStep:step]; + } + + return learnMoreViewController; +} + +- (ORKStepViewController *)viewControllerForStep:(ORKStep *)step isPreviousViewController:(BOOL)isPreviousViewController { + if (step == nil) { + return nil; + } + + ORKStepViewController *stepViewController = nil; + + if ([self.delegate respondsToSelector:@selector(taskViewController:viewControllerForStep:)]) { + // NOTE: While the delegate does not have direct access to the defaultResultSource, + // it is assumed that it can set results as needed on the custom implementation of an + // ORKStepViewController that it returns. + stepViewController = [self.delegate taskViewController:self viewControllerForStep:step]; + } + + // If the delegate did not return a step view controller then instantiate one + if (!stepViewController) { + + // Special-case the ORKReviewStep + if ([step isKindOfClass:[ORKReviewStep class]]) { + ORKReviewStep *reviewStep = (ORKReviewStep *)step; + NSArray *steps = [self stepsForReviewStep:reviewStep]; + id resultSource = reviewStep.isStandalone ? reviewStep.resultSource : self.result; + stepViewController = [[ORKReviewStepViewController alloc] initWithReviewStep:(ORKReviewStep *) step steps:steps resultSource:resultSource]; + ORKReviewStepViewController *reviewStepViewController = (ORKReviewStepViewController *) stepViewController; + reviewStepViewController.reviewDelegate = self; + } + else { + + // Get the step result associated with this step + ORKStepResult *result = nil; + ORKStepResult *previousResult = _managedResults[step.identifier]; + + // Check the default source first + BOOL alwaysCheckForDefaultResult = ([self.defaultResultSource respondsToSelector:@selector(alwaysCheckForDefaultResult)] && + [self.defaultResultSource alwaysCheckForDefaultResult]); + if ((previousResult == nil) || alwaysCheckForDefaultResult) { + result = [self.defaultResultSource stepResultForStepIdentifier:step.identifier]; + } + + // If nil, assign to the previous result (if available) otherwise create new instance + if (!result) { + result = previousResult ? : [[ORKStepResult alloc] initWithIdentifier:step.identifier]; + } + + // Allow the step to instantiate the view controller. This will allow either the default + // implementation using an override of the internal method `-stepViewControllerClass` or + // allow for storyboard implementations. + stepViewController = [step instantiateStepViewControllerWithResult:result]; + } + } + + // Throw an exception if the created step view controller is not a subclass of ORKStepViewController + ORKThrowInvalidArgumentExceptionIfNil(stepViewController); + if (![stepViewController isKindOfClass:[ORKStepViewController class]]) { + @throw [NSException exceptionWithName:NSGenericException reason:[NSString stringWithFormat:@"View controller should be of class %@", [ORKStepViewController class]] userInfo:@{@"viewController": stepViewController}]; + } + + // If this is a restorable task view controller, check that the restoration identifier and class + // are set on the step result. If not, do so here. This gives the instantiator the opportunity to + // set this value, but ensures that it is set to the default if the instantiator does not do so. + if ([self.delegate respondsToSelector:@selector(taskViewControllerSupportsSaveAndRestore:)] && + [self.delegate taskViewControllerSupportsSaveAndRestore:self]){ + if (stepViewController.restorationIdentifier == nil) { + stepViewController.restorationIdentifier = step.identifier; + } + if (stepViewController.restorationClass == nil) { + stepViewController.restorationClass = [stepViewController class]; + } + } + + stepViewController.outputDirectory = self.outputDirectory; + if (!isPreviousViewController) { + // Do not update the task's managed result if we are instantiating a previous view controllers for the + // navigation stack. Some active view controllers don't feature + // a result retoration path on init and we don't want to overwrite the most current result stored by the task + [self setManagedResult:stepViewController.result forKey:step.identifier]; + } + + + if (stepViewController.cancelButtonItem == nil) { + stepViewController.cancelButtonItem = [self defaultCancelButtonItem]; + } + + if ([self.delegate respondsToSelector:@selector(taskViewController:hasLearnMoreForStep:)] && + [self.delegate taskViewController:self hasLearnMoreForStep:step]) { + + stepViewController.learnMoreButtonItem = [self defaultLearnMoreButtonItem]; + } + + stepViewController.delegate = self; + return stepViewController; +} + +- (ORKStepViewController *)viewControllerForStep:(ORKStep *)step { + return [self viewControllerForStep:step isPreviousViewController:NO]; +} + +- (BOOL)shouldDisplayProgressLabelWithStepViewController:(ORKStepViewController *)stepViewController { + return self.showsProgressInNavigationBar && [_task respondsToSelector:@selector(progressOfCurrentStep:withResult:)] && stepViewController.step.showsProgress && !(stepViewController.parentReviewStep.isStandalone); +} + +- (void)setUpProgressLabelForStepViewController:(ORKStepViewController *)stepViewController { + NSString *progressLabel = nil; + if ([self shouldDisplayProgressLabelWithStepViewController:stepViewController]) { + ORKTaskProgress progress = [_task progressOfCurrentStep:stepViewController.step withResult:[self result]]; + if (progress.shouldBePresented) { + progressLabel = [NSString localizedStringWithFormat:ORKLocalizedString(@"STEP_PROGRESS_FORMAT", nil), ORKLocalizedStringFromNumber(@(progress.current+1)), ORKLocalizedStringFromNumber(@(progress.total))]; + } + } + stepViewController.navigationItem.title = progressLabel; +} + +#pragma mark - internal action Handlers + +- (void)finishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(taskViewController:didFinishWithReason:error:)]) { + [strongDelegate taskViewController:self didFinishWithReason:reason error:error]; + } +} + +- (void)presentCancelOptions:(BOOL)saveable sender:(id)sender { + + if ([self.delegate respondsToSelector:@selector(taskViewControllerShouldConfirmCancel:)] && + ![self.delegate taskViewControllerShouldConfirmCancel:self]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self finishWithReason:ORKTaskViewControllerFinishReasonDiscarded error:nil]; + }); + return; + } + + BOOL supportSaving = NO; + if ([self.delegate respondsToSelector:@selector(taskViewControllerSupportsSaveAndRestore:)]) { + supportSaving = [self.delegate taskViewControllerSupportsSaveAndRestore:self]; + } + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + + if ([sender isKindOfClass:[ORKBorderedButton class]]) { + UIView *cancelButtonView = (UIView *)sender; + alert.popoverPresentationController.sourceView = cancelButtonView; + alert.popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(cancelButtonView.bounds), CGRectGetMidY(cancelButtonView.bounds),0,0); + } + else if ([sender isKindOfClass:[UIBarButtonItem class]]) { + alert.popoverPresentationController.barButtonItem = sender; + } + + if (supportSaving && saveable) { + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_OPTION_SAVE", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction *action) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self finishWithReason:ORKTaskViewControllerFinishReasonSaved error:nil]; + }); + }]]; + } + + NSString *discardTitle = saveable ? ORKLocalizedString(@"BUTTON_OPTION_DISCARD", nil) : ORKLocalizedString(@"BUTTON_OPTION_STOP_TASK", nil); + + [alert addAction:[UIAlertAction actionWithTitle:discardTitle + style:UIAlertActionStyleDestructive + handler:^(UIAlertAction *action) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self finishWithReason:ORKTaskViewControllerFinishReasonDiscarded error:nil]; + }); + }]]; + + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) + style:UIAlertActionStyleCancel + handler:nil]]; + + [self presentViewController:alert animated:YES completion:nil]; +} + +- (IBAction)cancelAction:(UIBarButtonItem *)sender { + + if (self.discardable) { + [self finishWithReason:ORKTaskViewControllerFinishReasonDiscarded error:nil]; + } else { + [self presentCancelOptions:_saveable sender:sender]; + } +} + +- (BOOL)shouldDismissWithSwipe { + // Should we also include visualConsentStep here? Others? + BOOL isCurrentInstructionStep = [self.currentStepViewController.step isKindOfClass:[ORKInstructionStep class]]; + + // [self result] would not include any results beyond current step. + // Use _managedResults to get the completed result set. + NSArray *results = _managedResults.allValues; + _saveable = NO; + for (ORKStepResult *result in results) { + if ([result isSaveable]) { + _saveable = YES; + break; + } + } + + BOOL isStandaloneReviewStep = NO; + if ([self.currentStepViewController.step isKindOfClass:[ORKReviewStep class]]) { + ORKReviewStep *reviewStep = (ORKReviewStep *)self.currentStepViewController.step; + isStandaloneReviewStep = reviewStep.isStandalone; + } + + if ((isCurrentInstructionStep && _saveable == NO) || isStandaloneReviewStep || self.currentStepViewController.readOnlyMode) { + return YES; + } else { + return NO; + } +} + +- (IBAction)learnMoreAction:(id)sender { + if (self.delegate && [self.delegate respondsToSelector:@selector(taskViewController:learnMoreForStep:)]) { + [self.delegate taskViewController:self learnMoreForStep:self.currentStepViewController]; + } +} + +- (void)reportError:(NSError *)error onStep:(ORKStep *)step { + [self finishWithReason:ORKTaskViewControllerFinishReasonFailed error:error]; +} + +- (void)flipToNextPageFrom:(ORKStepViewController *)fromController animated:(BOOL)animated { + if (fromController != _currentStepViewController) { + return; + } + + ORKStep *step = fromController.parentReviewStep; + if (!step) { + step = [self nextStep]; + } + + if (step == nil) { + if ([self.delegate respondsToSelector:@selector(taskViewController:didChangeResult:)]) { + [self.delegate taskViewController:self didChangeResult:[self result]]; + } + [self finishAudioPromptSession]; + if (self.reviewMode == ORKTaskViewControllerReviewModeStandalone) { + [_taskReviewViewController removeFromParentViewController]; + _taskReviewViewController = nil; + if ([self.task isKindOfClass:[ORKOrderedTask class]]) { + ORKOrderedTask *orderedTask = (ORKOrderedTask *)self.task; + if (!_taskReviewViewController) { + _taskReviewViewController = [[ORKTaskReviewViewController alloc] initWithResultSource:self.result forSteps:orderedTask.steps withContentFrom:_reviewInstructionStep]; + _taskReviewViewController.delegate = self; + + [_childNavigationController setViewControllers:@[_taskReviewViewController] animated:YES]; + [self setTaskReviewViewControllerNavbar]; + + } + } + } + else { + [self finishWithReason:ORKTaskViewControllerFinishReasonCompleted error:nil]; + } + } else if ([self shouldPresentStep:step]) { + ORKStepViewController *stepViewController = [self viewControllerForStep:step]; + NSAssert(stepViewController != nil, @"A non-nil step should always generate a step view controller"); + if (fromController.isBeingReviewed) { + [_managedStepIdentifiers removeLastObject]; + } + [self showStepViewController:stepViewController goForward:YES animated:animated]; + } + +} + +- (void)setTaskReviewViewControllerNavbar { + if (_taskReviewViewController && _taskReviewViewController.navigationController) { + _taskReviewViewController.navigationController.navigationBar.topItem.title = @""; + [_taskReviewViewController.navigationController.navigationBar setBackgroundColor:ORKColor(ORKBackgroundColorKey)]; + } +} + +- (void)flipToFirstPage { + if ([self.task isKindOfClass:[ORKOrderedTask class]]) { + ORKOrderedTask *orderedTask = (ORKOrderedTask *)self.task; + ORKStep *firstStep = [[orderedTask steps] firstObject]; + if (firstStep) { + [_managedStepIdentifiers removeAllObjects]; + [self showStepViewController:[self viewControllerForStep:firstStep] goForward:YES animated:NO]; + } + } +} + +- (void)flipToPreviousPageFrom:(ORKStepViewController *)fromController animated:(BOOL)animated { + if (fromController != _currentStepViewController) { + return; + } + + ORKStep *step = fromController.parentReviewStep; + if (!step) { + step = [self prevStep]; + } + ORKStepViewController *stepViewController = nil; + + if ([self shouldPresentStep:step]) { + ORKStep *currentStep = _currentStepViewController.step; + NSString *itemId = currentStep.identifier; + + stepViewController = [self viewControllerForStep:step]; + if (stepViewController) { + // Remove the identifier from the list + assert([itemId isEqualToString:_managedStepIdentifiers.lastObject]); + [_managedStepIdentifiers removeLastObject]; + + [self showStepViewController:stepViewController goForward:NO animated:animated]; + } + } +} + +#pragma mark - ORKStepViewControllerDelegate + +- (void)stepViewControllerWillAppear:(ORKStepViewController *)viewController { + if ([self.delegate respondsToSelector:@selector(taskViewController:stepViewControllerWillAppear:)]) { + [self.delegate taskViewController:self stepViewControllerWillAppear:viewController]; + } +} + +- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction + animated:(BOOL)animated { + + if (!stepViewController.readOnlyMode) { + // Add step result object + [self setManagedResult:[stepViewController result] forKey:stepViewController.step.identifier]; + } + + // Alert the delegate that the step is finished + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(taskViewController:stepViewControllerWillDisappear:navigationDirection:)]) { + [strongDelegate taskViewController:self stepViewControllerWillDisappear:stepViewController navigationDirection:direction]; + } + + if (direction == ORKStepViewControllerNavigationDirectionForward) { + [self flipToNextPageFrom:stepViewController animated:animated]; + } else { + [self flipToPreviousPageFrom:stepViewController animated:animated]; + } +} + +- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction { + [self stepViewController:stepViewController didFinishWithNavigationDirection:direction animated:YES]; +} + +- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(NSError *)error { + [self finishWithReason:ORKTaskViewControllerFinishReasonFailed error:error]; +} + +- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController { + if (!stepViewController.readOnlyMode) { + [self setManagedResult:stepViewController.result forKey:stepViewController.step.identifier]; + } + + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(taskViewController:didChangeResult:)]) { + [strongDelegate taskViewController:self didChangeResult:[self result]]; + } +} + +- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController { + ORKStep *thisStep = stepViewController.step; + if (!thisStep) { + return NO; + } + ORKStep *previousStep = stepViewController.parentReviewStep; + if (!previousStep) { + previousStep = [self stepBeforeStep:thisStep]; + } + if ([previousStep isKindOfClass:[ORKActiveStep class]] || ([thisStep allowsBackNavigation] == NO)) { + previousStep = nil; // Can't go back to an active step + } + return (previousStep != nil); +} + +- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController { + ORKStep *thisStep = stepViewController.step; + if (!thisStep) { + return NO; + } + ORKStep *nextStep = [self stepAfterStep:thisStep]; + return (nextStep != nil); +} + +- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(taskViewController:recorder:didFailWithError:)]) { + [strongDelegate taskViewController:self recorder:recorder didFailWithError:error]; + } +} + +- (ORKTaskTotalProgress)stepViewControllerTotalProgressInfoForStep:(ORKStepViewController *)stepViewController currentStep:(ORKStep *)currentStep { + + ORKTaskTotalProgress progressData = [self.task totalProgressOfCurrentStep:currentStep]; + + if (self.progressMode != ORKTaskViewControllerProgressModeTotalQuestions) { + progressData.stepShouldShowTotalProgress = NO; + } else { + progressData.stepShouldShowTotalProgress = YES; + } + + return progressData; +} + +- (ORKStep *)stepBeforeStep:(ORKStep *)step { + return [self.task stepBeforeStep:step withResult:[self result]]; +} + +- (ORKStep *)stepAfterStep:(ORKStep *)step { + return [self.task stepAfterStep:step withResult:[self result]]; +} + +#pragma mark - ORKReviewStepViewControllerDelegate + +- (void)reviewStepViewController:(ORKReviewStepViewController *)reviewStepViewController + willReviewStep:(ORKStep *)step { + id resultSource = _defaultResultSource; + if (reviewStepViewController.reviewStep && reviewStepViewController.reviewStep.isStandalone) { + _defaultResultSource = reviewStepViewController.reviewStep.resultSource; + } + ORKStepViewController *stepViewController = [self viewControllerForStep:step]; + _defaultResultSource = resultSource; + NSAssert(stepViewController != nil, @"A non-nil step should always generate a step view controller"); + stepViewController.continueButtonTitle = ORKLocalizedString(@"BUTTON_SAVE", nil); + stepViewController.parentReviewStep = (ORKReviewStep *) reviewStepViewController.step; + stepViewController.skipButtonTitle = stepViewController.readOnlyMode ? ORKLocalizedString(@"BUTTON_READ_ONLY_MODE", nil) : ORKLocalizedString(@"BUTTON_CLEAR_ANSWER", nil); + if (stepViewController.parentReviewStep.isStandalone) { + stepViewController.navigationItem.title = stepViewController.parentReviewStep.title; + } + [self showStepViewController:stepViewController goForward:YES animated:YES]; +} + +#pragma mark - UIStateRestoring + +static NSString *const _ORKTaskRunUUIDRestoreKey = @"taskRunUUID"; +static NSString *const _ORKShowsProgressInNavigationBarRestoreKey = @"showsProgressInNavigationBar"; +static NSString *const _ORKDiscardableTaskRestoreKey = @"discardableTask"; +static NSString *const _ORKManagedResultsRestoreKey = @"managedResults"; +static NSString *const _ORKManagedStepIdentifiersRestoreKey = @"managedStepIdentifiers"; +static NSString *const _ORKHasSetProgressLabelRestoreKey = @"hasSetProgressLabel"; +static NSString *const _ORKHasRequestedHealthDataRestoreKey = @"hasRequestedHealthData"; +static NSString *const _ORKRequestedHealthTypesForReadRestoreKey = @"requestedHealthTypesForRead"; +static NSString *const _ORKRequestedHealthTypesForWriteRestoreKey = @"requestedHealthTypesForWrite"; +static NSString *const _ORKOutputDirectoryRestoreKey = @"outputDirectory"; +static NSString *const _ORKLastBeginningInstructionStepIdentifierKey = @"lastBeginningInstructionStepIdentifier"; +static NSString *const _ORKTaskIdentifierRestoreKey = @"taskIdentifier"; +static NSString *const _ORKStepIdentifierRestoreKey = @"stepIdentifier"; +static NSString *const _ORKPresentedDate = @"presentedDate"; +static NSString *const _ORKProgressMode = @"progressMode"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_taskRunUUID forKey:_ORKTaskRunUUIDRestoreKey]; + [coder encodeBool:self.showsProgressInNavigationBar forKey:_ORKShowsProgressInNavigationBarRestoreKey]; + [coder encodeBool:self.discardable forKey:_ORKDiscardableTaskRestoreKey]; + [coder encodeObject:_managedResults forKey:_ORKManagedResultsRestoreKey]; + [coder encodeObject:_managedStepIdentifiers forKey:_ORKManagedStepIdentifiersRestoreKey]; + [coder encodeObject:_requestedHealthTypesForRead forKey:_ORKRequestedHealthTypesForReadRestoreKey]; + [coder encodeObject:_requestedHealthTypesForWrite forKey:_ORKRequestedHealthTypesForWriteRestoreKey]; + [coder encodeObject:_presentedDate forKey:_ORKPresentedDate]; + [coder encodeInteger:_progressMode forKey:_ORKProgressMode]; + [coder encodeObject:ORKBookmarkDataFromURL(_outputDirectory) forKey:_ORKOutputDirectoryRestoreKey]; + [coder encodeObject:_lastBeginningInstructionStepIdentifier forKey:_ORKLastBeginningInstructionStepIdentifierKey]; + + [coder encodeObject:_task.identifier forKey:_ORKTaskIdentifierRestoreKey]; + + ORKStep *step = [_currentStepViewController step]; + if ([step isRestorable] && !(_currentStepViewController.isBeingReviewed && _currentStepViewController.parentReviewStep.isStandalone)) { + [coder encodeObject:step.identifier forKey:_ORKStepIdentifierRestoreKey]; + } else if (_lastRestorableStepIdentifier) { + [coder encodeObject:_lastRestorableStepIdentifier forKey:_ORKStepIdentifierRestoreKey]; + } +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + _taskRunUUID = [coder decodeObjectOfClass:[NSUUID class] forKey:_ORKTaskRunUUIDRestoreKey]; + self.showsProgressInNavigationBar = [coder decodeBoolForKey:_ORKShowsProgressInNavigationBarRestoreKey]; + self.discardable = [coder decodeBoolForKey:_ORKDiscardableTaskRestoreKey]; + self.progressMode = [coder decodeIntegerForKey:_ORKProgressMode]; + + _outputDirectory = ORKURLFromBookmarkData([coder decodeObjectOfClass:[NSData class] forKey:_ORKOutputDirectoryRestoreKey]); + [self ensureDirectoryExists:_outputDirectory]; + + // Must have a task object already provided by this point in the restoration, in order to restore any other state. + if (_task) { + + // Recover partially entered results, even if we may not be able to jump to the desired step. + _managedResults = [coder decodeObjectOfClass:[NSMutableDictionary class] forKey:_ORKManagedResultsRestoreKey]; + _managedStepIdentifiers = [coder decodeObjectOfClass:[NSMutableArray class] forKey:_ORKManagedStepIdentifiersRestoreKey]; + + _restoredTaskIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKTaskIdentifierRestoreKey]; + if (_restoredTaskIdentifier) { + if (![_task.identifier isEqualToString:_restoredTaskIdentifier]) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:[NSString stringWithFormat:@"Restored task identifier %@ does not match task %@ provided",_restoredTaskIdentifier,_task.identifier] + userInfo:nil]; + } + } + + if ([_task respondsToSelector:@selector(stepWithIdentifier:)]) { + _requestedHealthTypesForRead = [coder decodeObjectOfClass:[NSSet class] forKey:_ORKRequestedHealthTypesForReadRestoreKey]; + _requestedHealthTypesForWrite = [coder decodeObjectOfClass:[NSSet class] forKey:_ORKRequestedHealthTypesForWriteRestoreKey]; + _presentedDate = [coder decodeObjectOfClass:[NSDate class] forKey:_ORKPresentedDate]; + _lastBeginningInstructionStepIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKLastBeginningInstructionStepIdentifierKey]; + + _restoredStepIdentifier = [coder decodeObjectOfClass:[NSString class] forKey:_ORKStepIdentifierRestoreKey]; + } else { + ORK_Log_Info("Not restoring current step of task %@ because it does not implement -stepWithIdentifier:", _task.identifier); + } + } +} + +- (void)applicationFinishedRestoringState { + [super applicationFinishedRestoringState]; + + if (!_task) { + @throw [NSException exceptionWithName:NSInternalInconsistencyException + reason:@"Task must be provided to restore task view controller" + userInfo:nil]; + } + + if (_restoredStepIdentifier) { + ORKStepViewController *stepViewController = _currentStepViewController; + if (stepViewController) { + stepViewController.delegate = self; + + if (stepViewController.cancelButtonItem == nil) { + stepViewController.cancelButtonItem = [self defaultCancelButtonItem]; + } + + if ([self.delegate respondsToSelector:@selector(taskViewController:hasLearnMoreForStep:)] && + [self.delegate taskViewController:self hasLearnMoreForStep:stepViewController.step]) { + + stepViewController.learnMoreButtonItem = [self defaultLearnMoreButtonItem]; + } + + } else if ([_task respondsToSelector:@selector(stepWithIdentifier:)]) { + stepViewController = [self viewControllerForStep:[_task stepWithIdentifier:_restoredStepIdentifier]]; + } else { + stepViewController = [self viewControllerForStep:[_task stepAfterStep:nil withResult:[self result]]]; + } + + if (stepViewController != nil) { + [self showStepViewController:stepViewController goForward:YES animated:NO]; + _hasBeenPresented = YES; + } + } +} + ++ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder { + if ([identifierComponents.lastObject isEqualToString:_ChildNavigationControllerRestorationKey]) { + UINavigationController *navigationController = [UINavigationController new]; + navigationController.restorationIdentifier = identifierComponents.lastObject; + navigationController.restorationClass = self; + return navigationController; + } + + ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:nil taskRunUUID:nil]; + taskViewController.restorationIdentifier = identifierComponents.lastObject; + taskViewController.restorationClass = self; + return taskViewController; +} + +#pragma mark UINavigationController pass-throughs + +- (void)setNavigationBarHidden:(BOOL)navigationBarHidden { + _childNavigationController.navigationBarHidden = navigationBarHidden; +} + +- (BOOL)isNavigationBarHidden { + return _childNavigationController.navigationBarHidden; +} + +- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated { + [_childNavigationController setNavigationBarHidden:hidden animated:YES]; +} + +- (UINavigationBar *)navigationBar { + return _childNavigationController.navigationBar; +} + +#pragma mark Review mode + +- (void)addStepResultsUntilStepWithIdentifier:(NSString *)stepIdentifier { + ORKTaskResult * taskResult = (ORKTaskResult *) _defaultResultSource; + for (ORKStepResult * stepResult in taskResult.results) { + if (![stepIdentifier isEqualToString: stepResult.identifier]) { + if (![_managedStepIdentifiers containsObject:stepResult.identifier]) { + [_managedStepIdentifiers addObject:stepResult.identifier]; + } + _managedResults[stepResult.identifier] = stepResult; + } + else { + break; + } + } +} + +- (void)updateResultWithSource:(id)resultSource { + ORKTaskResult * taskResult = (ORKTaskResult *) resultSource; + for (ORKStepResult * stepResult in taskResult.results) { + if (![_managedStepIdentifiers containsObject:stepResult.identifier]) { + [_managedStepIdentifiers addObject:stepResult.identifier]; + } + _managedResults[stepResult.identifier] = stepResult; + } +} + +- (void)setDefaultResultSource:(id)defaultResultSource { + _defaultResultSource = defaultResultSource; + [self setReviewMode:_reviewMode]; +} + +- (void)setReviewMode:(ORKTaskViewControllerReviewMode)reviewMode { + if (_hasBeenPresented) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Cannot change review mode after presenting the task controller for now." userInfo:nil]; + } + _reviewMode = reviewMode; + [self setupTaskReviewViewController]; +} + +- (void)setupTaskReviewViewController { + if (_reviewMode == ORKTaskViewControllerReviewModeNever) { + _taskReviewViewController = nil; + return; + } + + _taskReviewViewController = nil; + + if ([self.task isKindOfClass:[ORKOrderedTask class]]) { + ORKOrderedTask *orderedTask = (ORKOrderedTask *)self.task; + + _taskReviewViewController = [[ORKTaskReviewViewController alloc] initWithResultSource:_defaultResultSource forSteps:orderedTask.steps withContentFrom:_reviewInstructionStep]; + _taskReviewViewController.delegate = self; + } +} + +- (void)setReviewInstructionStep:(ORKInstructionStep *)reviewInstructionStep { + _reviewInstructionStep = reviewInstructionStep; + if (_taskReviewViewController) { + _taskReviewViewController = nil; + } + [self setupTaskReviewViewController]; +} + +#pragma mark ORKTaskReviewViewControllerDelegate + +- (void)doneButtonTappedWithResultSource:(id)resultSource { + // FIXME: might need to queue the operations if the number of steps are too many. open to debate. + [self updateResultWithSource:resultSource]; + [self finishWithReason:ORKTaskViewControllerFinishReasonCompleted error:nil]; +} + +- (void)editAnswerTappedForStepWithIdentifier:(NSString *)stepIdentifier { + [self addStepResultsUntilStepWithIdentifier:stepIdentifier]; + [self showStepViewController:[self viewControllerForStep:[self.task stepWithIdentifier:stepIdentifier]] goForward:YES animated:YES]; +} + +#pragma mark - UINavigationController delegate + +- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { + if (viewController == _previousToTopControllerInNavigationStack && [viewController isKindOfClass:[ORKStepViewController class]]) { + // Make sure that the previous step view controller that will shows during an (interactive or non-interactive) + // pop action shows the progress in the navigation bar when appropriate + [self setUpProgressLabelForStepViewController:(ORKStepViewController *)viewController]; + } +} + +- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { + if (viewController == _previousToTopControllerInNavigationStack && [viewController isKindOfClass:[ORKStepViewController class]]) { + // _childNavigationController has completed either: a non-interactive animated pop transition by tapping on the + // back button; or an interactive animated pop transition by completing a drag-from-the-edge action. Update view + // controller stack and task view controller state. + [self stepViewController:_currentStepViewController didFinishWithNavigationDirection:ORKStepViewControllerNavigationDirectionReverse + animated:NO]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Internal.h new file mode 100755 index 0000000..033f754 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Internal.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTaskViewController_Private.h" +#import "ORKReviewStepViewController.h" +@import HealthKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKLearnMoreInstructionStep; + +@interface ORKTaskViewController () + +- (nullable NSSet *)requestedHealthTypesForRead; +- (nullable NSSet *)requestedHealthTypesForWrite; + +// Any StepVC contains a vertical scroll view should register here. +// So taskVC can monitor scroll view's content offset and update hairline's alpha. +@property (nonatomic, weak, nullable) UIScrollView *registeredScrollView; + +- (void)learnMoreButtonPressedWithStep:(ORKLearnMoreInstructionStep *)learnMoreInstructionStep fromStepViewController:(ORKStepViewController *)stepViewController; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Private.h new file mode 100755 index 0000000..6045394 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTaskViewController_Private.h @@ -0,0 +1,78 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTaskViewController (ORKActiveTaskSupport) + +/** + Suspends the task. + + Call this method to suspend an active step. To resume later, call + `resume`. Not all active steps will respond to `suspend` / `resume`, so test + thoroughly to verify correct behavior in your tasks. + + This method will disable any background audio prompt session, and suspend + any active step in progress. + */ +- (void)suspend; + +/** + Resumes any current active step. + + Call this method to force resuming an active step may call this + method. Should be paired with a call to `suspend`. + + This method re-enables background audio prompts, if needed, and resumes + any active step. If not in an active step, it has no effect. + + See also: `suspend` + */ +- (void)resume; + + +/** + Creates a default step view controller suitable for presenting the passed step, + and, if applicable, prefills its results using the `defaultResultSource`. + */ +- (ORKStepViewController *)viewControllerForStep:(ORKStep *)step; + +/** + Locks the device volume to a specific value. Will ignore a new locked value if the method was called before. + */ +- (void)lockDeviceVolume:(float)volume; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.h new file mode 100755 index 0000000..4011f2b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + "Skip" button or "Learn More" button. + */ +ORK_CLASS_AVAILABLE +@interface ORKTextButton : UIButton +@property (nonatomic) BOOL isInTransition; +@end + + +@interface ORKTextButton () + +- (void)init_ORKTextButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.m new file mode 100755 index 0000000..8a448fc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton.m @@ -0,0 +1,124 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTextButton.h" + + +@implementation ORKTextButton + ++ (instancetype)buttonWithType:(UIButtonType)buttonType { + assert(buttonType == UIButtonTypeCustom); + return [super buttonWithType:buttonType]; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self init_ORKTextButton]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self init_ORKTextButton]; + } + return self; +} + +- (void)init_ORKTextButton { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateAppearance) + name:UIContentSizeCategoryDidChangeNotification + object:nil]; + + [self updateAppearance]; + [self tintColorDidChange]; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + + [self setTitleColor:[self tintColor] forState:UIControlStateNormal]; + [self setTitleColor:[[self tintColor] colorWithAlphaComponent:0.7] forState:UIControlStateHighlighted]; +} + +- (void)updateAppearance { + + self.titleLabel.font = [[self class] defaultFont]; + [self invalidateIntrinsicContentSize]; + +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + ++ (UIFont *)defaultFont { + // regular, 14 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleCaption1]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey: UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (CGSize)intrinsicContentSize { + UILabel *label = nil; + + for (UIView *view in self.subviews) { + if ([view isKindOfClass:[UILabel class]]) { + label = (UILabel *)view; + break; + } + } + + // This is to avoid calling self.titleLabel when recalculation of content size is not needed. + // Calling self.titleLabel at here can cause weird layout error. + if (label && label.preferredMaxLayoutWidth > 0 && self.currentTitle.length > 0) { + CGSize labelSize = [self.titleLabel sizeThatFits:CGSizeMake(self.titleLabel.preferredMaxLayoutWidth, CGFLOAT_MAX)]; + + CGFloat verticalPadding = MAX(self.contentEdgeInsets.top, self.titleEdgeInsets.top) + MAX(self.contentEdgeInsets.bottom, self.titleEdgeInsets.bottom); + CGFloat horizontalPadding = MAX(self.contentEdgeInsets.left, self.titleEdgeInsets.left) + MAX(self.contentEdgeInsets.right, self.titleEdgeInsets.right); + + return CGSizeMake(labelSize.width+horizontalPadding, + labelSize.height+verticalPadding); + } + return [super intrinsicContentSize]; +} + +- (UIAccessibilityTraits)accessibilityTraits { + // prevent VoiceOver from speaking "dimmed" when transitioning between pages + if (self.isInTransition) { + return [super accessibilityTraits] & ~UIAccessibilityTraitNotEnabled; + } + return [super accessibilityTraits]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton_Internal.h new file mode 100755 index 0000000..b9be96e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextButton_Internal.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTextButton.h" +#import "ORKDefaultFont.h" + + +@interface ORKTextButton () + +- (void)init_ORKTextButton; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.h new file mode 100755 index 0000000..9ded56f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.h @@ -0,0 +1,76 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import UIKit; + +NS_ASSUME_NONNULL_BEGIN + +@class ORKChoiceViewCell; +@class ORKTextChoiceAnswerFormat; + +@protocol ORKTextChoiceCellGroupDelegate + +@required +- (void)answerChangedForIndexPath:(NSIndexPath *)indexPath; + +- (void)tableViewCellHeightUpdated; + +@end + +@interface ORKTextChoiceCellGroup : NSObject + +- (instancetype)initWithTextChoiceAnswerFormat:(ORKTextChoiceAnswerFormat *)answerFormat + answer:(nullable id)answer + beginningIndexPath:(NSIndexPath *)indexPath + immediateNavigation:(BOOL)immediateNavigation; + +@property (nonatomic, strong, nullable) id answer; + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, copy) ORKTextChoiceAnswerFormat *answerFormat; + +- (void)textViewDidResignResponderForCellAtIndexPath:(NSIndexPath *)indexPath; + +- (nullable ORKChoiceViewCell *)cellAtIndexPath:(NSIndexPath *)indexPath withReuseIdentifier:(nullable NSString *)identifier; + +- (BOOL)containsIndexPath:(NSIndexPath *)indexPath; + +- (void)didSelectCellAtIndexPath:(NSIndexPath *)indexPath; + +- (nullable id)answerForBoolean; + +- (NSUInteger)size; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.m new file mode 100755 index 0000000..d898280 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextChoiceCellGroup.m @@ -0,0 +1,249 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTextChoiceCellGroup.h" + +#import "ORKSelectionTitleLabel.h" +#import "ORKSelectionSubTitleLabel.h" + +#import "ORKChoiceViewCell.h" +#import "ORKAnswerTextView.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKChoiceAnswerFormatHelper.h" + +#import "ORKHelpers_Internal.h" + +@implementation ORKTextChoiceCellGroup { + ORKChoiceAnswerFormatHelper *_helper; + BOOL _singleChoice; + BOOL _immediateNavigation; + NSIndexPath *_beginningIndexPath; + + NSMutableDictionary *_cells; +} + +- (instancetype)initWithTextChoiceAnswerFormat:(ORKTextChoiceAnswerFormat *)answerFormat + answer:(id)answer + beginningIndexPath:(NSIndexPath *)indexPath + immediateNavigation:(BOOL)immediateNavigation { + self = [super init]; + if (self) { + _beginningIndexPath = indexPath; + _helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + _answerFormat = answerFormat; + _singleChoice = answerFormat.style == ORKChoiceAnswerStyleSingleChoice; + _immediateNavigation = immediateNavigation; + _cells = [NSMutableDictionary new]; + [self setAnswer:answer]; + } + return self; +} + +- (NSUInteger)size { + return [_helper choiceCount]; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + [self safelySetSelectedIndexesForAnswer:answer]; +} + +- (ORKChoiceViewCell *)cellAtIndexPath:(NSIndexPath *)indexPath withReuseIdentifier:(NSString *)identifier { + if ([self containsIndexPath:indexPath] == NO) { + return nil; + } + + return [self cellAtIndex:indexPath.row-_beginningIndexPath.row withReuseIdentifier:identifier]; +} + +- (ORKChoiceViewCell *)cellAtIndex:(NSUInteger)index withReuseIdentifier:(NSString *)identifier { + ORKChoiceViewCell *cell = _cells[@(index)]; + + if (cell == nil) { + ORKTextChoice *textChoice = [_helper textChoiceAtIndex:index]; + if ([textChoice isKindOfClass:[ORKTextChoiceOther class]]) { + ORKChoiceOtherViewCell *choiceOtherViewCell = [[ORKChoiceOtherViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + ORKTextChoiceOther *textChoiceOther = (ORKTextChoiceOther *)textChoice; + choiceOtherViewCell.textView.placeholder = textChoiceOther.textViewPlaceholderText; + choiceOtherViewCell.textView.text = textChoiceOther.textViewText; + [choiceOtherViewCell hideTextView:textChoiceOther.textViewStartsHidden]; + cell = choiceOtherViewCell; + } else { + cell = [[ORKChoiceViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; + } + cell.immediateNavigation = _immediateNavigation; + [cell setPrimaryText:textChoice.text]; + [cell setDetailText:textChoice.detailText]; + if (textChoice.primaryTextAttributedString) { + [cell setPrimaryAttributedText:textChoice.primaryTextAttributedString]; + } + if (textChoice.detailTextAttributedString) { + [cell setDetailAttributedText:textChoice.detailTextAttributedString]; + } + _cells[@(index)] = cell; + + [self safelySetSelectedIndexesForAnswer:_answer]; + } + + return cell; +} + +- (void)updateTextViewForChoiceOtherCell:(ORKChoiceOtherViewCell *)choiceCell withTextChoiceOther:(ORKTextChoiceOther *)choiceOther { + if (choiceOther.textViewStartsHidden && choiceCell.textView.text.length <= 0) { + [choiceCell hideTextView:!choiceCell.textViewHidden]; + [self.delegate tableViewCellHeightUpdated]; + } +} + +- (void)textViewDidResignResponderForCellAtIndexPath:(NSIndexPath *)indexPath { + if ([self containsIndexPath:indexPath]== NO) { + return; + } + NSUInteger index = indexPath.row - _beginningIndexPath.row; + ORKChoiceOtherViewCell *touchedCell = (ORKChoiceOtherViewCell *) [self cellAtIndex:index withReuseIdentifier:nil]; + ORKTextChoiceOther *textChoice = (ORKTextChoiceOther *) [_helper textChoiceAtIndex:index]; + + if (touchedCell.textView.text.length > 0) { + textChoice.textViewText = touchedCell.textView.text; + [self didSelectCellAtIndexPath:indexPath]; + } else { + textChoice.textViewText = nil; + if (!textChoice.textViewInputOptional) { + [touchedCell setCellSelected:NO highlight:NO]; + } + _answer = [_helper answerForSelectedIndexes:[self selectedIndexes]]; + [self.delegate answerChangedForIndexPath:indexPath]; + } +} + +- (void)didSelectCellAtIndexPath:(NSIndexPath *)indexPath { + if ([self containsIndexPath:indexPath]== NO) { + return; + } + NSUInteger index = indexPath.row - _beginningIndexPath.row; + ORKChoiceViewCell *touchedCell = [self cellAtIndex:index withReuseIdentifier:nil]; + ORKTextChoice *textChoice = [_helper textChoiceAtIndex:index]; + + if ([textChoice isKindOfClass:[ORKTextChoiceOther class]] && [touchedCell isKindOfClass:[ORKChoiceOtherViewCell class]]) { + ORKTextChoiceOther *otherTextChoice = (ORKTextChoiceOther *)textChoice; + ORKChoiceOtherViewCell *touchedOtherCell = (ORKChoiceOtherViewCell *)touchedCell; + [self updateTextViewForChoiceOtherCell:touchedOtherCell withTextChoiceOther:otherTextChoice]; + if (!otherTextChoice.textViewInputOptional && otherTextChoice.textViewText.length <= 0) { + return; + } + } + + if (_singleChoice) { + [touchedCell setCellSelected:YES highlight:YES]; + for (ORKChoiceViewCell *cell in _cells.allValues) { + if (cell != touchedCell) { + [cell setCellSelected:NO highlight:NO]; + } + } + } else { + [touchedCell setCellSelected:!touchedCell.isCellSelected highlight:YES]; + if (touchedCell.isCellSelected) { + ORKTextChoice *touchedChoice = [_helper textChoiceAtIndex:index]; + for (NSNumber *num in _cells.allKeys) { + ORKChoiceViewCell *cell = _cells[num]; + ORKTextChoice *choice = [_helper textChoiceAtIndex:num.unsignedIntegerValue]; + if (cell != touchedCell && (touchedChoice.exclusive || (cell.isCellSelected && choice.exclusive))) { + [cell setCellSelected:NO highlight:NO]; + } + } + } + } + + _answer = [_helper answerForSelectedIndexes:[self selectedIndexes]]; + [self.delegate answerChangedForIndexPath:indexPath]; +} + +- (BOOL)containsIndexPath:(NSIndexPath *)indexPath { + NSUInteger count = _helper.choiceCount; + + return (indexPath.section == _beginningIndexPath.section) && + (indexPath.row >= _beginningIndexPath.row) && + (indexPath.row < (_beginningIndexPath.row + count)); +} + +-(void)safelySetSelectedIndexesForAnswer:(nullable id)answer { + NSArray *selectedIndexes; + @try { + selectedIndexes = [_helper selectedIndexesForAnswer:answer]; + } @catch (NSException *exception) { + selectedIndexes = [[NSArray alloc] init]; + ORK_Log_Error("Error getting selected indexes: %@", exception.reason); + } @finally { + [self setSelectedIndexes: selectedIndexes]; + } +} + +- (void)setSelectedIndexes:(NSArray *)indexes { + for (NSUInteger index = 0; index < self.size; index++ ) { + BOOL selected = [indexes containsObject:@(index)]; + + if (selected) { + // In case the cell has not been created, need to create cell + ORKChoiceViewCell *cell = [self cellAtIndex:index withReuseIdentifier:nil]; + [cell setCellSelected:YES highlight:NO]; + } else { + // It is ok to not create the cell at here + ORKChoiceViewCell *cell = _cells[@(index)]; + [cell setCellSelected:NO highlight:NO]; + } + } +} + +- (NSArray *)selectedIndexes { + NSMutableArray *indexes = [NSMutableArray new]; + + for (NSUInteger index = 0; index < self.size; index++ ) { + ORKChoiceViewCell *cell = _cells[@(index)]; + if (cell.isCellSelected) { + [indexes addObject:@(index)]; + } + } + + return [indexes copy]; +} + +- (id)answerForBoolean { + // Boolean type uses a different format + if ([_answer isKindOfClass:[NSArray class]] ) { + NSArray *answerArray = _answer; + return (answerArray.count > 0) ? answerArray.firstObject : nil; + } + return _answer; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.h new file mode 100755 index 0000000..ac762ca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKAnswerTextField.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKCaretOptionalTextField : ORKAnswerTextField + +@property (nonatomic) BOOL allowsSelection; // Defaults to NO + +@property (nonatomic) BOOL hitClearButton; + +@end + + +@interface ORKPasscodeTextField : ORKCaretOptionalTextField + +- (void)updateTextWithNumberOfFilledBullets:(NSInteger)filledBullets; + +@property (nonatomic) NSInteger numberOfDigits; + +@end + + +@interface ORKUnitTextField : ORKCaretOptionalTextField + +@property (nonatomic, copy, nullable) NSString *unit; + +@property (nonatomic) BOOL manageUnitAndPlaceholder; + +@property (nonatomic) BOOL hideUnitWhenAnswerEmpty; + +@end + + +/** + Manages a text field with unit label and a clear button: [text unit (x)] + */ +@interface ORKTextFieldView : UIView + +@property (nonatomic, strong, readonly) ORKUnitTextField *textField; + +@property (nonatomic, strong) UILabel *errorMessageLabel; + +@property (nonatomic, readonly) CGFloat estimatedWidth; + +@property (nonatomic) BOOL hideUnitWhenAnswerEmpty; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.m new file mode 100755 index 0000000..f20e327 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTextFieldView.m @@ -0,0 +1,516 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTextFieldView.h" + +#import "ORKAccessibility.h" +#import "ORKSkin.h" + + +static NSString *const EmptyBulletString = @"\u25CB"; +static NSString *const FilledBulletString = @"\u25CF"; + +@implementation ORKCaretOptionalTextField + +- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + _hitClearButton = NO; + if ([self allowsSelection]) { + return [super hitTest:point withEvent:event]; + } else { + // Make exception for clear button, which is hittable + if ( CGRectContainsPoint([self clearButtonRectForBounds:self.bounds], point)) { + UIView *hitView = [super hitTest:point withEvent:event]; + // Where we are using a picker for date, time interval, and choice + // Turn on flag to avoid bring up the keyboard when the field is not active. + _hitClearButton = [hitView isKindOfClass:[UIButton class]]; + return hitView; + } + return nil; + } +} + +- (CGRect)caretRectForPosition:(UITextPosition *)position { + if (_allowsSelection) { + return [super caretRectForPosition:position]; + } else { + return CGRectZero; + } +} + +@end + + +@implementation ORKPasscodeTextField + +- (instancetype)init { + self = [super init]; + if (self) { + self.font = [UIFont fontWithName:@"Courier" size:35.0]; + self.textAlignment = NSTextAlignmentCenter; + } + return self; +} + +- (UIKeyboardType)keyboardType { + return UIKeyboardTypeNumberPad; +} + +- (BOOL)allowsSelection { + return NO; +} + +- (void)updateTextWithNumberOfFilledBullets:(NSInteger)filledBullets { + // Error checking. + if (filledBullets > self.numberOfDigits) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"The number of filled bullets cannot exceed the number of pin digits." + userInfo:nil]; + } + + // Append the string with the correct number of filled and empty bullets. + NSString *text = [NSString new]; + text = [text stringByPaddingToLength:filledBullets withString:FilledBulletString startingAtIndex:0]; + text = [text stringByPaddingToLength:self.numberOfDigits withString:EmptyBulletString startingAtIndex:0]; + + // Apply spacing attribute to string. + NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text]; + [attributedText addAttribute:NSKernAttributeName + value:@(20.0f) + range:NSMakeRange(0, [text length]-1)]; + + // Set the textfield's text property. + self.attributedText = attributedText; +} + +- (void)setNumberOfDigits:(NSInteger)numberOfDigits { + _numberOfDigits = numberOfDigits; + [self updateTextWithNumberOfFilledBullets:0]; +} + +#pragma mark - Accessibility + +- (NSString *)accessibilityLabel { + return ORKLocalizedString(@"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL", nil); +} + +- (NSString *)accessibilityValue { + NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:FilledBulletString options:NSRegularExpressionCaseInsensitive error:nil]; + NSUInteger numberOfFilledBullets = [regularExpression numberOfMatchesInString:self.text options:0 range:NSMakeRange(0, [self.text length])]; + return [NSString stringWithFormat:ORKLocalizedString(@"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE", nil), ORKLocalizedStringFromNumber(@(numberOfFilledBullets)), ORKLocalizedStringFromNumber(@([self.text length]))]; +} + +- (UIAccessibilityTraits)accessibilityTraits { + return UIAccessibilityTraitNone; +} + +@end + + +@implementation ORKUnitTextField { + NSString *_managedPlaceholder; + + NSString *_unitWithNumber; + + UIColor *_unitRegularColor; + UIColor *_unitActiveColor; + + UIColor *_savedSuffixColor; + NSString *_savedSuffixText; + + UILabel *_suffixLabel; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldTextDidBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldTextDidEndEditing:) name:UITextFieldTextDidEndEditingNotification object:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldTextDidChange:) name:UITextFieldTextDidChangeNotification object:self]; + + } + return self; +} + +- (id)ork_createTextLabelWithTextColor:(UIColor *)textColor { + UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + textLabel.font = [UIFont systemFontOfSize:17]; + [textLabel setOpaque:NO]; + [textLabel setBackgroundColor:nil]; + textLabel.contentMode = UIViewContentModeRedraw; + if (textColor != nil) { + textLabel.textColor = textColor; + } + return textLabel; +} + +- (void)ork_setSuffix:(NSString *)suffix withColor:(UIColor *)color { + CGRect previousSuffixFrame = CGRectZero; + if (_suffixLabel) { + previousSuffixFrame = _suffixLabel.frame; + [_suffixLabel removeFromSuperview]; + _suffixLabel = nil; + [self setNeedsLayout]; + } else { + previousSuffixFrame.size.height = CGRectGetHeight(self.bounds); + } + if (suffix.length == 0) { + return; + } + if (@available(iOS 13.0, *)) { + _suffixLabel = [self ork_createTextLabelWithTextColor:(color ? : [UIColor placeholderTextColor])]; + } else { + _suffixLabel = [self ork_createTextLabelWithTextColor:(color ? : [UIColor ork_midGrayTintColor])]; + } + _suffixLabel.text = suffix; + _suffixLabel.font = self.font; + _suffixLabel.textAlignment = NSTextAlignmentLeft; + _suffixLabel.userInteractionEnabled = NO; + _suffixLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; + _suffixLabel.frame = previousSuffixFrame; + + // re-layout to position the suffix + [self setNeedsLayout]; +} + +- (void)ork_updateSuffix:(NSString *)suffix { + if (!_suffixLabel) { + [self ork_setSuffix:suffix withColor:nil]; + } else { + _suffixLabel.text = suffix; + [self setNeedsLayout]; + } +} + +- (void)ork_updateSuffix:(NSString *)suffix withColor:(UIColor *)color { + if (NO == [color isEqual:_savedSuffixColor]) { + if (suffix != nil) { + _savedSuffixColor = color; + } + _savedSuffixText = suffix; + [self ork_setSuffix:suffix withColor:color]; + return; + } + + if (NO == [suffix isEqualToString:_savedSuffixText]) { + _savedSuffixText = suffix; + [self ork_updateSuffix:suffix]; + } +} + +- (void)setManageUnitAndPlaceholder:(BOOL)manageUnitAndPlaceholder { + _manageUnitAndPlaceholder = manageUnitAndPlaceholder; + [self updateManagedUnitAndPlaceholder]; +} + +- (void)setPlaceholder:(NSString *)placeholder { + _managedPlaceholder = placeholder; + [self updateManagedUnitAndPlaceholder]; +} + +- (void)ork_setPlaceholder:(NSString *)placeholder { + [super setPlaceholder:placeholder]; +} + +- (void)setUnit:(NSString *)unit { + _unit = unit; + + if (_unit.length > 0) { + _unitWithNumber = [NSString stringWithFormat:@" %@", unit]; + + if (@available(iOS 13.0, *)) { + _unitRegularColor = [UIColor placeholderTextColor]; + _unitActiveColor = [UIColor placeholderTextColor]; + } else { + _unitRegularColor = [UIColor blackColor]; + _unitActiveColor = [UIColor ork_midGrayTintColor]; + } + } else { + _unitWithNumber = nil; + } + + [self updateManagedUnitAndPlaceholder]; +} + +- (void)updateManagedUnitAndPlaceholder { + if (_manageUnitAndPlaceholder) { + BOOL isEditing = self.isEditing; + + UIColor *suffixColor = isEditing ? _unitActiveColor : _unitRegularColor; + if (_managedPlaceholder.length > 0) { + [self ork_setPlaceholder:((isEditing && _unit.length > 0) ? nil : _managedPlaceholder)]; + if (!(_hideUnitWhenAnswerEmpty && !isEditing && self.text.length == 0)) { + [self ork_updateSuffix:_unitWithNumber withColor:suffixColor]; + } else { + [self ork_updateSuffix:nil withColor:suffixColor]; + } + } else { + if (self.text.length > 0 || isEditing) { + [self ork_setPlaceholder:nil]; + [self ork_updateSuffix:_unitWithNumber withColor:suffixColor]; + } else { + if (!(_hideUnitWhenAnswerEmpty && !isEditing && self.text.length == 0)) { + [self ork_setPlaceholder:_unit]; + [self ork_updateSuffix:nil withColor:suffixColor]; + } else { + [self ork_setPlaceholder:nil]; + [self ork_updateSuffix:nil withColor:suffixColor]; + } + } + } + } else { + // remove unit string + if (_savedSuffixText.length > 0) { + [self ork_updateSuffix:nil withColor:nil]; + } + // put back unit string + if ([self.placeholder isEqualToString:_managedPlaceholder] == NO) { + [self ork_setPlaceholder:_managedPlaceholder]; + } + } + [self invalidateIntrinsicContentSize]; + [self layoutIfNeeded]; // layout immediatly to avoid animation glitch in which the unit label frame grows from left to right +} + +- (void)textFieldTextDidBeginEditing:(NSNotification *)notification { + [self updateManagedUnitAndPlaceholder]; +} + +- (void)textFieldTextDidEndEditing:(NSNotification *)notification { + [self updateManagedUnitAndPlaceholder]; + +} + +- (void)textFieldTextDidChange:(NSNotification *)notification { + [self updateManagedUnitAndPlaceholder]; +} + +- (void)setText:(NSString *)text { + [super setText:text]; + [self updateManagedUnitAndPlaceholder]; +} + +- (BOOL)isPlaceholderVisible { + BOOL isEditing = self.isEditing; + return (self.placeholder.length > 0) && + ((!isEditing && self.text.length == 0) || (isEditing && self.text.length == 0 && _unit.length == 0)); +} + +- (CGFloat)suffixWidthForBounds:(CGRect)bounds { + CGFloat suffixWidth = [_suffixLabel.text sizeWithAttributes:@{NSFontAttributeName: _suffixLabel.font}].width; + suffixWidth = MIN(suffixWidth, bounds.size.width / 2); + return suffixWidth; +} + +static const UIEdgeInsets paddingGuess = (UIEdgeInsets){.left = 2, .right = 6}; + +- (CGRect)textRectForBounds:(CGRect)bounds { + CGRect textRect = [super textRectForBounds:bounds]; + + // Leave room for the suffix label + if (_suffixLabel.text.length) { + CGFloat suffixWidth = [self suffixWidthForBounds:bounds]; + if (suffixWidth > 0) { + suffixWidth += paddingGuess.right; + } + textRect.size.width = MAX(0, textRect.size.width - suffixWidth); + } + return textRect; +} + + +- (CGRect)editingRectForBounds:(CGRect)bounds { + CGRect rect = [super editingRectForBounds:bounds]; + + // Leave room for the suffix label + if (_suffixLabel.text.length) { + CGFloat suffixWidth = [self suffixWidthForBounds:bounds]; + if (suffixWidth > 0) { + suffixWidth += paddingGuess.right; + } + rect.size.width = MAX(0, rect.size.width - suffixWidth); + } + + return rect; +} + +- (CGRect)ork_suffixFrame { + // Get the text currently 'in' the edit field + NSString *textToMeasure = [self isPlaceholderVisible] ? self.placeholder : self.text; + CGSize sizeOfText = [textToMeasure sizeWithAttributes:[self defaultTextAttributes]]; + + // Get the maximum size of the actual editable area (taking into account prefix/suffix/views/clear button + CGRect textFrame = [self textRectForBounds:self.bounds]; + + // Work out the size of our suffix frame + CGRect suffixFrame = [super placeholderRectForBounds:self.bounds]; + suffixFrame.size.width = [self suffixWidthForBounds:self.bounds]; + + // Take padding into account + CGFloat xMaximum = CGRectGetMaxX(textFrame); + if (sizeOfText.width < (textFrame.size.width - (paddingGuess.left + paddingGuess.right))) { + // Adjust the rectangle to include the padding + textFrame.origin.x += paddingGuess.left; + textFrame.size.width -= paddingGuess.left + paddingGuess.right; + } else { + // Cover the fringe case where the padding is not applied, but the field editor has not scrolled, so the prefix/suffix could + // overlap the text slightly. + sizeOfText.width += paddingGuess.left + paddingGuess.right; + } + + // Calculate position for alignment + CGFloat xOffset = CGRectGetMinX(textFrame) + sizeOfText.width; + + // Make sure it can't escape out the right of the view + suffixFrame.origin.x = MIN(xOffset, xMaximum); + + suffixFrame.size.height = CGRectGetHeight(self.bounds); + suffixFrame.origin.y = 0; + + return suffixFrame; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + if (_suffixLabel) { + [self addSubview:_suffixLabel]; + _suffixLabel.frame = [self ork_suffixFrame]; + [_suffixLabel setNeedsDisplay]; + } +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +#pragma mark Accessibility + +- (NSString *)accessibilityValue { + if (self.text.length > 0) { + return ORKAccessibilityStringForVariables([super accessibilityValue], _unitWithNumber); + + } + else if ( _managedPlaceholder ) { + return ORKAccessibilityStringForVariables(_managedPlaceholder, _unitWithNumber); + } + + return [super accessibilityValue]; +} + +@end + + +@implementation ORKTextFieldView { + + NSMutableArray *_errorLabelConstraints; + +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _textField = [[ORKUnitTextField alloc] init]; + _textField.clearButtonMode = UITextFieldViewModeWhileEditing; + _textField.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_textField]; + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_textField); + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_textField]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_textField]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_textField + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + + // Ask to fill the available horizontal space + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:_textField + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + + widthConstraint.priority = UILayoutPriorityDefaultLow; + [constraints addObject:bottomConstraint]; + [constraints addObject:widthConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (CGFloat)estimatedWidth { + + NSString *placeholderAndUnit = self.textField.placeholder; + NSString *textAndUnit = self.textField.text; + + if (self.textField.unit.length > 0) { + NSString *unitString = [NSString stringWithFormat:@" %@", self.textField.unit]; + placeholderAndUnit = [placeholderAndUnit stringByAppendingString:unitString]; + textAndUnit = [textAndUnit stringByAppendingString:unitString]; + } + + NSDictionary *attributes = @{ NSFontAttributeName : self.textField.font }; + CGFloat fieldWidth = MAX([placeholderAndUnit sizeWithAttributes:attributes].width, + [textAndUnit sizeWithAttributes:attributes].width); + + return fieldWidth; +} + +- (void)setHideUnitWhenAnswerEmpty:(BOOL)hideUnitWhenAnswerEmpty { + _textField.hideUnitWhenAnswerEmpty = hideUnitWhenAnswerEmpty; +} + +- (BOOL)hideUnitWhenAnswerEmpty { + return _textField.hideUnitWhenAnswerEmpty; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.h new file mode 100755 index 0000000..bd15f70 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKPicker.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTimeIntervalPicker : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.m new file mode 100755 index 0000000..4295871 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTimeIntervalPicker.m @@ -0,0 +1,135 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTimeIntervalPicker.h" + +#import "ORKAnswerFormat_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@interface ORKDatePicker : UIDatePicker + +@end + + +@implementation ORKDatePicker + +- (void)didMoveToWindow { + [super didMoveToWindow]; + + // Work around for UIDatePicker UIControlEventValueChanged only fired on second selection + dispatch_async(dispatch_get_main_queue(), ^{ + self.countDownDuration = self.countDownDuration; + }); +} + +@end + + +@interface ORKTimeIntervalPicker () + +@property (nonatomic, strong) ORKTimeIntervalAnswerFormat *answerFormat; + +@end + + +@implementation ORKTimeIntervalPicker { + id _answer; + __weak id _pickerDelegate; + ORKDatePicker *_pickerView; +} + +@synthesize pickerDelegate = _pickerDelegate; +@synthesize answer = _answer; + +- (instancetype)initWithAnswerFormat:(ORKTimeIntervalAnswerFormat *)answerFormat + answer:(id)answer + pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + self.answerFormat = answerFormat; + self.answer = answer; + self.pickerDelegate = delegate; + } + return self; +} + +- (UIView *)pickerView { + if (_pickerView == nil) { + _pickerView = [[ORKDatePicker alloc] init]; + _pickerView.datePickerMode = UIDatePickerModeCountDownTimer; + [_pickerView addTarget:self action:@selector(valueDidChange:) forControlEvents:UIControlEventValueChanged]; + [self setAnswerFormat:_answerFormat]; + [self setAnswer:_answer]; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + NSTimeInterval value; + if (answer != nil && answer != ORKNullAnswerValue() && [answer isKindOfClass:[NSNumber class]]) { + value = ((NSNumber *)answer).doubleValue; + } else { + value = [_answerFormat pickerDefaultDuration]; + } + + _pickerView.countDownDuration = value; +} + +- (void)setAnswerFormat:(ORKTimeIntervalAnswerFormat *)answerFormat { + _answerFormat = answerFormat; + NSAssert([answerFormat isKindOfClass:[ORKTimeIntervalAnswerFormat class]], @""); + + _pickerView.minuteInterval = [answerFormat step]; +} + +- (NSString *)selectedLabelText { + return (_answer == nil || _answer == ORKNullAnswerValue()) ? nil : [ORKTimeIntervalLabelFormatter() stringFromTimeInterval:((NSNumber *)self.answer).floatValue]; +} + +- (void)pickerWillAppear { + [self pickerView]; + [self valueDidChange:nil]; +} + +- (void)valueDidChange:(id)sender { + NSTimeInterval interval = _pickerView.countDownDuration; + _answer = @(interval); + + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:self.answer]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.h new file mode 100755 index 0000000..931d59f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +UIImage *ORKImageByTintingImage(UIImage *image, UIColor *tintColor, CGFloat scale); + +@interface ORKTintedImageView : UIImageView + +@property (nonatomic, assign) BOOL shouldApplyTint; + +@property (nonatomic, assign) BOOL enableTintedImageCaching; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.m new file mode 100755 index 0000000..ef7e7dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView.m @@ -0,0 +1,219 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTintedImageView.h" +#import "ORKTintedImageView_Internal.h" + +#import "ORKHelpers_Internal.h" + + +#define ORKTintedImageLog(...) + +ORK_INLINE BOOL ORKIsImageAnimated(UIImage *image) { + return image.images.count > 1; +} + +UIImage *ORKImageByTintingImage(UIImage *image, UIColor *tintColor, CGFloat scale) { + if (!image || !tintColor || !(scale > 0)) { + return nil; + } + + ORKTintedImageLog(@"%@ %@ %f", image, tintColor, scale); + + UIGraphicsBeginImageContextWithOptions(image.size, NO, scale); + CGContextRef context = UIGraphicsGetCurrentContext(); + CGContextSetBlendMode(context, kCGBlendModeNormal); + CGContextSetAlpha(context, 1); + + CGRect r = (CGRect){{0,0},image.size}; + CGContextBeginTransparencyLayerWithRect(context, r, NULL); + [tintColor setFill]; + [image drawInRect:r]; + UIRectFillUsingBlendMode(r, kCGBlendModeSourceIn); + CGContextEndTransparencyLayer(context); + + UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return outputImage; +} + + +@interface ORKTintedImageCacheKey : NSObject + +- (instancetype)initWithImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale; + +@property (nonatomic, readonly) UIImage *image; +@property (nonatomic, readonly) UIColor *tintColor; +@property (nonatomic, readonly) CGFloat scale; + +@end + + +@implementation ORKTintedImageCacheKey { + UIImage *_image; + UIColor *_tintColor; + CGFloat _scale; +} + +- (instancetype)initWithImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale { + self = [super init]; + if (self) { + _image = image; + _tintColor = tintColor; + _scale = scale; + } + return self; +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.image, castObject.image) + && ORKEqualObjects(self.tintColor, castObject.tintColor) + && ORKCGFloatNearlyEqualToFloat(self.scale, castObject.scale)); +} + +@end + + +@interface ORKTintedImageCache () + +- (UIImage *)tintedImageForImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale; + +@end + + +@implementation ORKTintedImageCache + ++ (instancetype)sharedCache +{ + static dispatch_once_t onceToken; + static id sharedInstance = nil; + dispatch_once(&onceToken, ^{ + sharedInstance = [[[self class] alloc] init]; + }); + return sharedInstance; +} + +- (UIImage *)tintedImageForImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale { + UIImage *tintedImage = nil; + + ORKTintedImageCacheKey *key = [[ORKTintedImageCacheKey alloc] initWithImage:image tintColor:tintColor scale:scale]; + tintedImage = [self objectForKey:key]; + if (!tintedImage) { + tintedImage = ORKImageByTintingImage(image, tintColor, scale); + if (tintedImage) { + [self setObject:tintedImage forKey:key]; + } + } + return tintedImage; +} + +- (void)cacheImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale { + [[ORKTintedImageCache sharedCache] tintedImageForImage:image tintColor:tintColor scale:scale]; +} + +@end + + +@implementation ORKTintedImageView { + UIImage *_originalImage; + UIImage *_tintedImage; + UIColor *_appliedTintColor; + CGFloat _appliedScaleFactor; +} + +- (void)setShouldApplyTint:(BOOL)shouldApplyTint { + _shouldApplyTint = shouldApplyTint; + self.image = _originalImage; +} + +- (UIImage *)imageByTintingImage:(UIImage *)image { + if (!image || (image.renderingMode == UIImageRenderingModeAlwaysOriginal + || (image.renderingMode == UIImageRenderingModeAutomatic && !_shouldApplyTint))) { + return image; + } + + UIColor *tintColor = self.tintColor; + CGFloat screenScale = self.window.screen.scale; // Use screen.scale; self.contentScaleFactor remains 1.0 until later + if (screenScale > 0 && (![_appliedTintColor isEqual:tintColor] || !ORKCGFloatNearlyEqualToFloat(_appliedScaleFactor, screenScale))) { + _appliedTintColor = tintColor; + _appliedScaleFactor = screenScale; + + if (!ORKIsImageAnimated(image)) { + if (_enableTintedImageCaching) { + _tintedImage = [[ORKTintedImageCache sharedCache] tintedImageForImage:image tintColor:tintColor scale:screenScale]; + } else { + _tintedImage = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } + } else { + NSArray *animationImages = image.images; + NSMutableArray *tintedAnimationImages = [[NSMutableArray alloc] initWithCapacity:animationImages.count]; + for (UIImage *animationImage in animationImages) { + UIImage *tintedAnimationImage = nil; + if (_enableTintedImageCaching) { + tintedAnimationImage = [[ORKTintedImageCache sharedCache] tintedImageForImage:animationImage tintColor:tintColor scale:screenScale]; + } else { + tintedAnimationImage = ORKImageByTintingImage(animationImage, tintColor, screenScale); + } + if (tintedAnimationImage) { + [tintedAnimationImages addObject:tintedAnimationImage]; + } + } + _tintedImage = [UIImage animatedImageWithImages:tintedAnimationImages duration:image.duration]; + } + } + return _tintedImage; +} + +- (void)setImage:(UIImage *)image { + _originalImage = image; + image = [self imageByTintingImage:image]; + [super setImage:image]; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + // recompute for new tint color + self.image = _originalImage; +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + // recompute for new screen.scale + self.image = _originalImage; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView_Internal.h new file mode 100755 index 0000000..5ccd556 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTintedImageView_Internal.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTintedImageView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKTintedImageCache : NSCache + ++ (instancetype)sharedCache; + +- (void)cacheImage:(UIImage *)image tintColor:(UIColor *)tintColor scale:(CGFloat)scale; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.h new file mode 100755 index 0000000..cae30fd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +ORK_CLASS_AVAILABLE +@interface ORKTitleLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.m new file mode 100755 index 0000000..20d1cbd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTitleLabel.m @@ -0,0 +1,49 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTitleLabel.h" +#import "ORKSkin.h" + +@implementation ORKTitleLabel + +- (void)updateAppearance { + self.font = [[self class] defaultFont]; + [self invalidateIntrinsicContentSize]; +} + ++ (UIFont *)defaultFont { + UIFontTextStyle style = ORKTitleLabelFontTextStyleForWindow([UIView new].window); + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:style]; + UIFontDescriptor *fontDescriptor = [descriptor fontDescriptorWithSymbolicTraits:style == UIFontTextStyleTitle1 ? (UIFontDescriptorTraitBold | UIFontDescriptorTraitTightLeading) : (UIFontDescriptorTraitBold)]; + return [UIFont fontWithDescriptor:fontDescriptor size:0]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.h new file mode 100755 index 0000000..a5637ac --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.h @@ -0,0 +1,695 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An enumeration of values that identify the different types of questions that the ResearchKit + framework supports. + */ +typedef NS_ENUM(NSInteger, ORKQuestionType) { + /** + No question. + */ + ORKQuestionTypeNone, + + /** + The scale question type asks participants to place a mark at an appropriate position on a + continuous or discrete line. + */ + ORKQuestionTypeScale, + + /** + In a single choice question, the participant can pick only one predefined option. + */ + ORKQuestionTypeSingleChoice, + + /** + In a multiple choice question, the participant can pick one or more predefined options. + */ + ORKQuestionTypeMultipleChoice, + + /** + In a multiple component choice picker, the participant can pick one choice from each component. + */ + ORKQuestionTypeMultiplePicker, + + /** + The decimal question type asks the participant to enter a decimal number. + */ + ORKQuestionTypeDecimal, + + /** + The integer question type asks the participant to enter an integer number. + */ + ORKQuestionTypeInteger, + + /** + The Boolean question type asks the participant to enter Yes or No (or the appropriate + equivalents). + */ + ORKQuestionTypeBoolean, + + /** + In a text question, the participant can enter multiple lines of text. + */ + ORKQuestionTypeText, + + /** + In a time of day question, the participant can enter a time of day by using a picker. + */ + ORKQuestionTypeTimeOfDay, + + /** + In a date and time question, the participant can enter a combination of date and time by using + a picker. + */ + ORKQuestionTypeDateAndTime, + + /** + In a date question, the participant can enter a date by using a picker. + */ + ORKQuestionTypeDate, + + /** + In a time interval question, the participant can enter a time span by using a picker. + */ + ORKQuestionTypeTimeInterval, + + /** + In a height question, the participant can enter a height by using a height picker. + */ + ORKQuestionTypeHeight, + + /** + In a weight question, the participant can enter a weight by using a weight picker. + */ + ORKQuestionTypeWeight, + + /** + In a location question, the participant can enter a location using a map view. + */ + ORKQuestionTypeLocation, + + /** + In a socio-economic ladder, participant can pick their socio economic status. + */ + ORKQuestionTypeSES +} ORK_ENUM_AVAILABLE; + + +/** + An enumeration of the types of answer choices available. + */ +typedef NS_ENUM(NSInteger, ORKChoiceAnswerStyle) { + /** + A single choice question lets the participant pick a single predefined answer option. + */ + ORKChoiceAnswerStyleSingleChoice, + + /** + A multiple choice question lets the participant pick one or more predefined answer options. + */ + ORKChoiceAnswerStyleMultipleChoice +} ORK_ENUM_AVAILABLE; + + +/** + An enumeration of the format styles available for scale answers. + */ +typedef NS_ENUM(NSInteger, ORKNumberFormattingStyle) { + /** + The default decimal style. + */ + ORKNumberFormattingStyleDefault, + + /** + Percent style. + */ + ORKNumberFormattingStylePercent +} ORK_ENUM_AVAILABLE; + + +/** + You can use a permission mask to specify a set of permissions to acquire or + that have been acquired for a task or step. + */ +typedef NS_OPTIONS(NSInteger, ORKPermissionMask) { + /// No permissions. + ORKPermissionNone = 0, + + /// Access to CoreMotion activity is required. + ORKPermissionCoreMotionActivity = (1 << 1), + + /// Access to CoreMotion accelerometer data. + ORKPermissionCoreMotionAccelerometer = (1 << 2), + + /// Access for audio recording. + ORKPermissionAudioRecording = (1 << 3), + + /// Access to location. + ORKPermissionCoreLocation = (1 << 4), + + /// Access to camera. + ORKPermissionCamera = (1 << 5), +} ORK_ENUM_AVAILABLE; + + +/** + File protection mode constants. + + The file protection mode constants correspond directly to `NSFileProtection` constants, but are + more convenient to manipulate than strings. Complete file protection is + highly recommended for files containing personal data that will be kept + persistently. + */ +typedef NS_ENUM(NSInteger, ORKFileProtectionMode) { + /// No file protection. + ORKFileProtectionNone = 0, + + /// Complete file protection until first user authentication. + ORKFileProtectionCompleteUntilFirstUserAuthentication, + + /// Complete file protection unless there was an open file handle before lock. + ORKFileProtectionCompleteUnlessOpen, + + /// Complete file protection while the device is locked. + ORKFileProtectionComplete +} ORK_ENUM_AVAILABLE; + + +/** + Audio channel constants. + */ +typedef NS_ENUM(NSInteger, ORKAudioChannel) { + /// The left audio channel. + ORKAudioChannelLeft, + + /// The right audio channel. + ORKAudioChannelRight +} ORK_ENUM_AVAILABLE; + + +/** + Body side constants. + */ +typedef NS_ENUM(NSInteger, ORKBodySagittal) { + /// The left side. + ORKBodySagittalLeft, + + /// The right side. + ORKBodySagittalRight +} ORK_ENUM_AVAILABLE; + + +/** + Values that identify the left or right limb to be used in an active task. + */ +typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskLimbOption) { + /// Which limb to use is undefined + ORKPredefinedTaskLimbOptionUnspecified = 0, + + /// Task should test the left limb + ORKPredefinedTaskLimbOptionLeft = 1 << 1, + + /// Task should test the right limb + ORKPredefinedTaskLimbOptionRight = 1 << 2, + + /// Task should test the both limbs (random order) + ORKPredefinedTaskLimbOptionBoth = ORKPredefinedTaskLimbOptionLeft | ORKPredefinedTaskLimbOptionRight, +} ORK_ENUM_AVAILABLE; + + +/** + Values that identify the presentation mode of paced serial addition tests that are auditory and/or visual (PSAT). + */ +typedef NS_OPTIONS(NSInteger, ORKPSATPresentationMode) { + /// The PASAT (Paced Auditory Serial Addition Test). + ORKPSATPresentationModeAuditory = 1 << 0, + + /// The PVSAT (Paced Visual Serial Addition Test). + ORKPSATPresentationModeVisual = 1 << 1 +} ORK_ENUM_AVAILABLE; + + +/** + Identify the type of passcode authentication for `ORKPasscodeStepViewController`. + */ +typedef NS_ENUM(NSInteger, ORKPasscodeType) { + /// 4 digit pin entry + ORKPasscodeType4Digit, + + /// 6 digit pin entry + ORKPasscodeType6Digit +} ORK_ENUM_AVAILABLE; + + +/** + Values that identify the hand(s) to be used in an active task. + + By default, the participant will be asked to use their most affected hand. + */ +typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskHandOption) { + /// Which hand to use is undefined + ORKPredefinedTaskHandOptionUnspecified = 0, + + /// Task should test the left hand + ORKPredefinedTaskHandOptionLeft = 1 << 1, + + /// Task should test the right hand + ORKPredefinedTaskHandOptionRight = 1 << 2, + + /// Task should test both hands (random order) + ORKPredefinedTaskHandOptionBoth = ORKPredefinedTaskHandOptionLeft | ORKPredefinedTaskHandOptionRight, +} ORK_ENUM_AVAILABLE; + + +/** + The `ORKPredefinedTaskOption` flags let you exclude particular behaviors from the predefined active + tasks in the predefined category of `ORKOrderedTask`. + + By default, all predefined tasks include instructions and conclusion steps, and may also include + one or more data collection recorder configurations. Although not all predefined tasks include all + of these data collection types, the predefined task option flags can be used to explicitly specify + that a task option not be included. + */ +typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskOption) { + /// Default behavior. + ORKPredefinedTaskOptionNone = 0, + + /// Exclude the initial instruction steps. + ORKPredefinedTaskOptionExcludeInstructions = (1 << 0), + + /// Exclude the conclusion step. + ORKPredefinedTaskOptionExcludeConclusion = (1 << 1), + + /// Exclude accelerometer data collection. + ORKPredefinedTaskOptionExcludeAccelerometer = (1 << 2), + + /// Exclude device motion data collection. + ORKPredefinedTaskOptionExcludeDeviceMotion = (1 << 3), + + /// Exclude pedometer data collection. + ORKPredefinedTaskOptionExcludePedometer = (1 << 4), + + /// Exclude location data collection. + ORKPredefinedTaskOptionExcludeLocation = (1 << 5), + + /// Exclude heart rate data collection. + ORKPredefinedTaskOptionExcludeHeartRate = (1 << 6), + + /// Exclude audio data collection. + ORKPredefinedTaskOptionExcludeAudio = (1 << 7) +} ORK_ENUM_AVAILABLE; + + +/** + Progress indicator type for `ORKWaitStep`. + */ +typedef NS_ENUM(NSInteger, ORKProgressIndicatorType) { + /// Spinner animation. + ORKProgressIndicatorTypeIndeterminate = 0, + + /// Progressbar animation. + ORKProgressIndicatorTypeProgressBar, +} ORK_ENUM_AVAILABLE; + + +/** + Measurement system. + + Used by ORKHeightAnswerFormat and ORKWeightAnswerFormat. + */ +typedef NS_ENUM(NSInteger, ORKMeasurementSystem) { + /// Measurement system in use by the current locale. + ORKMeasurementSystemLocal = 0, + + /// Metric measurement system. + ORKMeasurementSystemMetric, + + /// United States customary system. + ORKMeasurementSystemUSC, +} ORK_ENUM_AVAILABLE; + +/** + Route Identifiers for supported headphone types. + */ +typedef NSString *ORKHeadphoneTypeIdentifier NS_STRING_ENUM; +ORK_EXTERN ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierAirPods; +ORK_EXTERN ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierEarPods; +ORK_EXTERN ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierUnknown; + +ORK_CLASS_AVAILABLE +@interface ORKDontKnowAnswer : NSObject + ++ (instancetype)answer; + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@end + + +/** + Trailmaking Type Identifiers for supported trailmaking types. + */ +typedef NSString * ORKTrailMakingTypeIdentifier NS_STRING_ENUM; + +/// Trail making for Type-A trail where the pattern is 1-2-3-4-5-6-7 +ORK_EXTERN ORKTrailMakingTypeIdentifier const ORKTrailMakingTypeIdentifierA; + +/// Trail making for Type-B trail where the pattern is 1-A-2-B-3-C-4-D-5-E-6-F-7 +ORK_EXTERN ORKTrailMakingTypeIdentifier const ORKTrailMakingTypeIdentifierB; + + +/** + The `ORKTremorActiveTaskOption` flags let you exclude particular steps from the predefined active + tasks in the predefined Tremor `ORKOrderedTask`. + + By default, all predefined active tasks will be included. The tremor active task option flags can + be used to explicitly specify that an active task is not to be included. + */ +typedef NS_OPTIONS(NSUInteger, ORKTremorActiveTaskOption) { + /// Default behavior. + ORKTremorActiveTaskOptionNone = 0, + + /// Exclude the hand-in-lap steps. + ORKTremorActiveTaskOptionExcludeHandInLap = (1 << 0), + + /// Exclude the hand-extended-at-shoulder-height steps. + ORKTremorActiveTaskOptionExcludeHandAtShoulderHeight = (1 << 1), + + /// Exclude the elbow-bent-at-shoulder-height steps. + ORKTremorActiveTaskOptionExcludeHandAtShoulderHeightElbowBent = (1 << 2), + + /// Exclude the elbow-bent-touch-nose steps. + ORKTremorActiveTaskOptionExcludeHandToNose = (1 << 3), + + /// Exclude the queen-wave steps. + ORKTremorActiveTaskOptionExcludeQueenWave = (1 << 4) +} ORK_ENUM_AVAILABLE; + + +/** + Enums to exclude options from `ORKPDFViewerStep`. + */ +typedef NS_OPTIONS(NSUInteger, ORKPDFViewerActionBarOption) { + ORKPDFViewerActionBarOptionExcludeThumbnail = 1 << 0, + ORKPDFViewerActionBarOptionExcludeAnnotation = 1 << 1, + ORKPDFViewerActionBarOptionExcludeSearch = 1 << 2, + ORKPDFViewerActionBarOptionExcludeShare = 1 << 3, +}ORK_ENUM_AVAILABLE; + + +/** + Numeric precision. + + Used by ORKWeightAnswerFormat. + */ +typedef NS_ENUM(NSInteger, ORKNumericPrecision) { + /// Default numeric precision. + ORKNumericPrecisionDefault = 0, + + /// Low numeric precision. + ORKNumericPrecisionLow, + + /// High numeric preicision. + ORKNumericPrecisionHigh, +} ORK_ENUM_AVAILABLE; + +/** + Eye side for amsler grid + */ +typedef NS_ENUM(NSInteger, ORKAmslerGridEyeSide) { + /** + Not Specified + */ + ORKAmslerGridEyeSideNotSpecified = 0, + + /** + Left Eye + */ + ORKAmslerGridEyeSideLeft, + + /** + Right Eye + */ + ORKAmslerGridEyeSideRight +} ORK_ENUM_AVAILABLE; + +/** + An enumeration of the types of button styles for Navigation Containers. + */ +typedef NS_ENUM(NSInteger, ORKNavigationContainerButtonStyle) { + /** + A standard ORKText button. + */ + ORKNavigationContainerButtonStyleTextStandard = 0, + + /** + A text button with Bold title. + */ + ORKNavigationContainerButtonStyleTextBold, + + /** + A rounded rect button. + */ + ORKNavigationContainerButtonStyleRoundedRect +} ORK_ENUM_AVAILABLE; + +extern const double ORKDoubleDefaultValue ORK_AVAILABLE_DECL; + +/** + Identifiers for locales that support speech recognition. + */ +typedef NSString * ORKSpeechRecognizerLocale NS_STRING_ENUM; + +/// Arabic (Saudi Arabia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleArabic; + +/// Catalan (Spain) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCatalan; + +/// Czech (Czechia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCzech; + +/// Danish (Denmark) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDanish; + +/// German (Austria) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanAT; + +/// German (Switzerland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanCH; + +/// German (Germany) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanDE; + +/// Greek (Greece) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGreek; + +/// English (United Arab Emirates) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishAE; + +/// English (Australia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishAU; + +/// English (Canada) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishCA; + +/// English (United Kingdom) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishGB; + +/// English (Indonesia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishID; + +/// English (Ireland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishIE; + +/// English (India) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishIN; + +/// English (New Zealand) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishNZ; + +/// English (Philippines) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishPH; + +/// English (Saudi Arabia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishSA; + +/// English (Singapore) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishSG; + +/// English (United States) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishUS; + +/// English (South Africa) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishZA; + +/// Spanish (Chile) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishCL; + +/// Spanish (Colombia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishCO; + +/// Spanish (Spain) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishES; + +/// Spanish (Mexico) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishMX; + +/// Spanish (United States) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishUS; + +/// Finnish (Finland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFinnish; + +/// French (Belgium) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchBE; + +/// French (Canada) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchCA; + +/// French (Switzerland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchCH; + +/// French (France) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchFR; + +/// Hebrew (Israel) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHebrew; + +/// Hindi (India) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindi; + +/// Hindi (India, TRANSLIT) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindiINTRANSLIT; + +/// Hindi (Latin) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindiLATN; + +/// Croatian (Croatia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCroatian; + +/// Hungarian (Hungary) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHungarian; + +/// Indonesian (Indonesia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleIndonesian; + +/// Italian (Switzerland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleItalianCH; + +/// Italian (Italy) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleItalianIT; + +/// Japanese (Japan) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleJapaneseJP; + +/// Korean (South Korea) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleKorean; + +/// Malay (Malaysia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleMalay; + +/// Norwegian Bokmål (Norway) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleNorwegian; + +/// Dutch (Belgium) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDutchBE; + +/// Dutch (Netherlands) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDutchNL; + +/// Polish (Poland) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePolish; + +/// Portuguese (Brazil) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePortugeseBR; + +/// Portuguese (Portugal) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePortugesePT; + +/// Romanian (Romania) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleRomanian; + +/// Russian (Russia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleRussian; + +/// Slovak (Slovakia) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSlovak; + +/// Swedish (Sweden) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSwedish; + +/// Thai (Thailand) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleThai; + +/// Turkish (Turkey) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleTurkish; + +/// Ukrainian (Ukraine) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleUkranian; + +/// Vietnamese (Vietnam) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleVietnamese; + +/// Shanghainese (China) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleShanghainese; + +/// Cantonese (China) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCantonese; + +/// Chinese (China) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseCN; + +/// Chinese (Hong Kong [China]) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseHK; + +/// Chinese (Taiwan) +ORK_EXTERN ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseTW; + +typedef NS_OPTIONS(NSUInteger, ORKTouchAbilityTaskOption) { + ORKTouchAbilityTaskOptionTap = 1 << 0, + ORKTouchAbilityTaskOptionLongPress = 1 << 1, + ORKTouchAbilityTaskOptionSwipe = 1 << 2, + ORKTouchAbilityTaskOptionVerticalScroll = 1 << 3, + ORKTouchAbilityTaskOptionHorizontalScroll = 1 << 4, + ORKTouchAbilityTaskOptionPinch = 1 << 5, + ORKTouchAbilityTaskOptionRotation = 1 << 6 +} ORK_ENUM_AVAILABLE; + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.m new file mode 100755 index 0000000..22a8a79 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKTypes.m @@ -0,0 +1,212 @@ +/* + Copyright (c) 2017, Apple Inc. All rights reserved. + Copyright (c) 2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKTypes.h" +#import "ORKHelpers_Internal.h" + +ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierAirPods = @"AIRPODS"; + +ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierEarPods = @"EARPODS"; + +ORKHeadphoneTypeIdentifier const ORKHeadphoneTypeIdentifierUnknown = @"UNKNOWN"; + +ORKTrailMakingTypeIdentifier const ORKTrailMakingTypeIdentifierA = @"A"; + +ORKTrailMakingTypeIdentifier const ORKTrailMakingTypeIdentifierB = @"B"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleArabic = @"ar-SA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCatalan = @"ca-ES"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCzech = @"cs-CZ"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDanish = @"da-DK"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanAT = @"de-AT"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanCH = @"de-CH"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGermanDE = @"de-DE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleGreek = @"el-GR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishAE = @"en-AE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishAU = @"en-AU"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishCA = @"en-CA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishGB = @"en-GB"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishID = @"en-ID"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishIE = @"en-IE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishIN = @"en-IN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishNZ = @"en-NZ"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishPH = @"en-PH"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishSA = @"en-SA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishSG = @"en-SG"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishUS = @"en-US"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleEnglishZA = @"en-ZA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishCL = @"es-CL"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishCO = @"es-CO"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishES = @"es-ES"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishMX = @"es-MX"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSpanishUS = @"es-US"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFinnish = @"fi-FI"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchBE = @"fr-BE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchCA = @"fr-CA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchCH = @"fr-CH"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleFrenchFR = @"fr-FR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHebrew = @"he-IL"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindi = @"hi-IN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindiINTRANSLIT = @"hi-IN-translit"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHindiLATN = @"hi-Latn"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCroatian = @"hr-HR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleHungarian = @"hu-HU"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleIndonesian = @"id-ID"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleItalianCH = @"it-CH"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleItalianIT = @"it-IT"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleJapanese = @"ja-JP"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleKorean = @"ko-KR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleMalay = @"ms-MY"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleNorwegian = @"nb-NO"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDutchBE = @"nl-BE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleDutchNL = @"nl-NL"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePolish = @"pl-PL"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePortugeseBR = @"pt-BR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocalePortugesePT = @"pt-PT"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleRomanian = @"ro-RO"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleRussian = @"ru-RU"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSlovak = @"sk-SK"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleSwedish = @"sv-SE"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleThai = @"th-TH"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleTurkish = @"tr-TR"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleUkranian = @"uk-UA"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleVietnamese = @"vi-VN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleShanghainese = @"wuu-CN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleCantonese = @"yue-CN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseCN = @"zh-CN"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseHK = @"zh-HK"; + +ORKSpeechRecognizerLocale const ORKSpeechRecognizerLocaleChineseTW = @"zh-TW"; + +const double ORKDoubleDefaultValue = DBL_MAX; + +@implementation ORKDontKnowAnswer + ++ (instancetype)new { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)init_ORKDontKnowAnswer { + return [super init]; +} + ++ (instancetype)answer { + static ORKDontKnowAnswer *instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[ORKDontKnowAnswer alloc] init_ORKDontKnowAnswer]; + }); + return instance; +} + +- (nonnull id)copyWithZone:(nullable NSZone *)zone { + return self; +} + +- (void)encodeWithCoder:(nonnull NSCoder *)coder { + return; +} + +- (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder { + ORKDontKnowAnswer *instance = [ORKDontKnowAnswer answer]; + return instance; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.h new file mode 100755 index 0000000..c74a772 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKLabel.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Text label for units during numeric value entry + */ +ORK_CLASS_AVAILABLE +@interface ORKUnitLabel : ORKLabel + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.m new file mode 100755 index 0000000..020e8fc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKUnitLabel.m @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKUnitLabel.h" + + +@implementation ORKUnitLabel + ++ (UIFont *)defaultFont { + // regular, 17 + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline]; + return [UIFont systemFontOfSize:[[descriptor objectForKey: UIFontDescriptorSizeAttribute] doubleValue]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.h new file mode 100755 index 0000000..4a1169b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKPicker.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKValuePicker : NSObject + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.m new file mode 100755 index 0000000..6e37345 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKValuePicker.m @@ -0,0 +1,189 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKValuePicker.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKChoiceAnswerFormatHelper.h" +#import "ORKResult_Private.h" + +#import "ORKAccessibilityFunctions.h" + + +@interface ORKValuePicker () + +@property (nonatomic, strong) ORKChoiceAnswerFormatHelper *helper; + +@end + +static const CGFloat PickerSpacerHeight = 15.0; +static const CGFloat PickerMinimumHeight = 34.0; + +@implementation ORKValuePicker { + UIPickerView *_pickerView; + id _answer; + __weak id _pickerDelegate; +} + +@synthesize pickerDelegate = _pickerDelegate; + +- (instancetype)initWithAnswerFormat:(ORKValuePickerAnswerFormat *)answerFormat answer:(id)answer pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + NSAssert([answerFormat isKindOfClass:[ORKValuePickerAnswerFormat class]], @"answerFormat should be ORKValuePickerAnswerFormat"); + + self.helper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + self.answer = answer; + _pickerDelegate = delegate; + + } + return self; +} + +- (UIView *)pickerView { + if (_pickerView == nil) { + _pickerView = [[UIPickerView alloc] init]; + _pickerView.dataSource = self; + _pickerView.delegate = self; + [self setAnswer:_answer]; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + NSNumber *indexNumber = [_helper selectedIndexForAnswer:answer]; + if (indexNumber) { + [_pickerView selectRow:indexNumber.unsignedIntegerValue inComponent:0 animated:NO]; + } else { + [_pickerView selectRow:0 inComponent:0 animated:NO]; + } +} + +- (id)answer { + return _answer; +} + +- (NSString *)selectedLabelText { + if ( _answer == ORKNullAnswerValue() || _answer == nil ) { + return nil; + } + + NSNumber *indexNumber = [_helper selectedIndexForAnswer:_answer]; + NSInteger row = indexNumber.integerValue; + + if (row == 0) { + return nil; + } + + return [self pickerView:_pickerView titleForRow:row forComponent:0]; +} + +- (void)pickerWillAppear { + [self pickerView]; + [self valueDidChange]; + [self accessibilityFocusOnPickerElement]; +} + +- (void)valueDidChange { + NSInteger row = [_pickerView selectedRowInComponent:0]; + _answer = [_helper answerForSelectedIndex:row]; + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:_answer]; + } +} + +#pragma mark - Accessibility + +- (void)accessibilityFocusOnPickerElement { + if (UIAccessibilityIsVoiceOverRunning()) { + ORKAccessibilityPerformBlockAfterDelay(0.75, ^{ + NSArray *axElements = [self.pickerView accessibilityElements]; + if ([axElements count] > 0) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, [axElements objectAtIndex:0]); + } + }); + } +} + +#pragma mark - UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return 1; +} + +// returns the # of rows in each component.. +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return _helper.choiceCount; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + return [[_helper textChoiceAtIndex:row] text]; +} + +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + return [[_helper textChoiceAtIndex:row] primaryTextAttributedString]; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view +{ + UILabel* valueLabel = (UILabel*)view; + if (!valueLabel) + { + valueLabel = [[UILabel alloc] init]; + [valueLabel setFont:[self defaultFont]]; + [valueLabel setTextAlignment:NSTextAlignmentCenter]; + } + valueLabel.text = [self pickerView:pickerView titleForRow:row forComponent:component]; + NSAttributedString *attributedText = [self pickerView:pickerView attributedTitleForRow:row forComponent:component]; + if (attributedText) { + valueLabel.attributedText = attributedText; + } + return valueLabel; +} + +- (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { + UIFont *font = [self defaultFont]; + CGFloat height = font.pointSize + PickerSpacerHeight; + return (height < PickerMinimumHeight ? PickerMinimumHeight : height); +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + [self valueDidChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.h new file mode 100755 index 0000000..d13993c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKNavigationContainerView; +@class ORKStepHeaderView; +@class ORKTintedImageView; + +@interface ORKVerticalContainerView : UIScrollView + +@property (nonatomic, strong, readonly) ORKTintedImageView *imageView; + +@property (nonatomic, strong, readonly) UIView *customViewContainer; + +// The primary content view for the step (?) +@property (nonatomic, strong, nullable) UIView *stepView; + +@property (nonatomic, strong, nullable) UIView *customView; + +@property (nonatomic, strong, readonly) ORKStepHeaderView *headerView; + +@property (nonatomic, assign) BOOL continueHugsContent; + +@property (nonatomic, assign) BOOL verticalCenteringEnabled; + +@property (nonatomic, assign) BOOL stepViewFillsAvailableSpace; + +@property (nonatomic, assign) CGFloat minimumStepHeaderHeight; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.m new file mode 100755 index 0000000..abf1e26 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView.m @@ -0,0 +1,759 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerticalContainerView.h" +#import "ORKVerticalContainerView_Internal.h" + +#import "ORKCustomStepView_Internal.h" +#import "ORKNavigationContainerView.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKTintedImageView.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +// Enable this define to see outlines and colors of all the views laid out at this level. +// #define LAYOUT_DEBUG + +/* + view hierachy in ORKVerticalContainerView (from top to bottom): + + scrollContainer + - container + - customViewContainer + - headerView + - stepViewContainer + */ + +@implementation ORKVerticalContainerView { + UIView *_scrollContainer; + UIView *_container; + + ORKTintedImageView *_imageView; + + NSMutableArray *_variableConstraints; + + NSLayoutConstraint *_headerMinimumHeightConstraint; + NSLayoutConstraint *_illustrationHeightConstraint; + NSLayoutConstraint *_stepViewCenterInStepViewContainerConstraint; + NSLayoutConstraint *_topToIllustrationConstraint; + NSLayoutConstraint *_scrollContainerHeightConstraint; + + CGFloat _keyboardOverlap; + + UIView *_stepViewContainer; + + BOOL _keyboardIsUp; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _scrollContainerShouldCollapseNavbar = YES; + _scrollContainer = [UIView new]; + [self addSubview:_scrollContainer]; + _container = [UIView new]; + [_scrollContainer addSubview:_container]; + + { + _headerView = [ORKStepHeaderView new]; + _headerView.layoutMargins = UIEdgeInsetsZero; + _headerView.translatesAutoresizingMaskIntoConstraints = NO; + [_container addSubview:_headerView]; + } + + { + _stepViewContainer = [UIView new]; + _stepViewContainer.preservesSuperviewLayoutMargins = YES; + [_container addSubview:_stepViewContainer]; + } + + { + // Custom View + _customViewContainer = [UIView new]; + [_container addSubview:self.customViewContainer]; + } + + ORKEnableAutoLayoutForViews(@[_scrollContainer, _container, _headerView, _stepViewContainer, _customViewContainer]); + + [self setUpStaticConstraints]; + [self setNeedsUpdateConstraints]; + + UITapGestureRecognizer *tapOffRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapOffAction:)]; + [self addGestureRecognizer:tapOffRecognizer]; + + UISwipeGestureRecognizer *swipeOffRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeOffAction:)]; + swipeOffRecognizer.direction = UISwipeGestureRecognizerDirectionDown; + [self addGestureRecognizer:swipeOffRecognizer]; + } + return self; +} + +- (void)setUpStaticConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_scrollContainer, _container); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_scrollContainer]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_scrollContainer]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + _scrollContainerHeightConstraint = [NSLayoutConstraint constraintWithItem:_scrollContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:self + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:_scrollContainerShouldCollapseNavbar ? 0.3 : 0.0]; //anything less than 0.3 does not work for smaller devices. + [constraints addObject: _scrollContainerHeightConstraint]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_scrollContainer + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + // This constraint is needed to get the scroll container not to size itself too large (we don't want scrolling if it's not needed) + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:_scrollContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]; + heightConstraint.priority = UILayoutPriorityDefaultLow; + [constraints addObject:heightConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setScrollContainerShouldCollapseNavbar:(BOOL)scrollContainerShouldCollapseNavbar { + if (!scrollContainerShouldCollapseNavbar) { + _scrollContainerShouldCollapseNavbar = scrollContainerShouldCollapseNavbar; + [NSLayoutConstraint deactivateConstraints:@[_scrollContainerHeightConstraint]]; + _scrollContainerHeightConstraint = [NSLayoutConstraint constraintWithItem:_scrollContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]; + [_scrollContainerHeightConstraint setActive:YES]; + [self setNeedsUpdateConstraints]; + } +} + +- (void)swipeOffAction:(UITapGestureRecognizer *)recognizer { + [self endEditing:NO]; +} + +- (void)tapOffAction:(UITapGestureRecognizer *)recognizer { + // On a tap, dismiss the keyboard if the tap was not inside a view that is first responder or a child of a first responder. + CGPoint point = [recognizer locationInView:self]; + UIView *view = [self hitTest:point withEvent:nil]; + BOOL viewIsChildOfFirstResponder = NO; + while (view) { + if ([view isFirstResponder]) { + viewIsChildOfFirstResponder = YES; + break; + } + view = [view superview]; + } + + if (!viewIsChildOfFirstResponder) { + [self endEditing:NO]; + } +} + +- (void)dealloc { + [self registerForKeyboardNotifications:NO]; +} + +- (void)registerForKeyboardNotifications:(BOOL)shouldRegister { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + if (shouldRegister) { + [notificationCenter addObserver:self + selector:@selector(keyboardWillShow:) + name:UIKeyboardWillShowNotification object:nil]; + + [notificationCenter addObserver:self + selector:@selector(keyboardWillHide:) + name:UIKeyboardWillHideNotification object:nil]; + [notificationCenter addObserver:self + selector:@selector(keyboardFrameWillChange:) + name:UIKeyboardWillChangeFrameNotification object:nil]; + } else { + [notificationCenter removeObserver:self name:UIKeyboardWillShowNotification object:nil]; + [notificationCenter removeObserver:self name:UIKeyboardWillHideNotification object:nil]; + [notificationCenter removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil]; + } +} + +- (void)setBounds:(CGRect)bounds { + [super setBounds:bounds]; + [self updateLayoutMargins]; +} + +- (void)setFrame:(CGRect)frame { + [super setFrame:frame]; + [self updateLayoutMargins]; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + [self updateConstraintConstantsForWindow:newWindow]; + if (newWindow) { + [self registerForKeyboardNotifications:YES]; + } else { + [self registerForKeyboardNotifications:NO]; + } +} + +- (CGSize)keyboardIntersectionSizeFromNotification:(NSNotification *)notification { + CGRect keyboardFrame = [[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; + keyboardFrame = [self convertRect:keyboardFrame fromView:nil]; + + CGRect scrollFrame = self.bounds; + + // The origin of this is in our superview's coordinate system, but I don't think + // we actually use the origin - so just return the size. + CGRect intersectionFrame = CGRectIntersection(scrollFrame, keyboardFrame); + return intersectionFrame.size; +} + +- (void)animateLayoutForKeyboardNotification:(NSNotification *)notification { + NSTimeInterval animationDuration = ((NSNumber *)notification.userInfo[UIKeyboardAnimationDurationUserInfoKey]).doubleValue; + + [UIView animateWithDuration:animationDuration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ + CGRect bounds = self.bounds; + CGSize contentSize = self.contentSize; + + CGSize intersectionSize = [self keyboardIntersectionSizeFromNotification:notification]; + CGFloat visibleHeight = bounds.size.height - intersectionSize.height; + + // Keep track of the keyboard overlap, so we can adjust the constraint properly. + _keyboardOverlap = intersectionSize.height; + + // Trigger layout inside the animation block to get the constraint change to animate. + [self layoutIfNeeded]; + + if (_keyboardIsUp) { + + CGFloat contentMaxY = CGRectGetMaxY([self convertRect:_container.bounds fromView:_container]); + + // First compute the contentOffset.y that would make the continue and skip buttons visible + CGFloat yOffset = MAX(contentMaxY - visibleHeight, 0); + yOffset = MIN(yOffset, contentSize.height - visibleHeight); + + // If that yOffset would not make the stepView visible, override to align with the top of the stepView. + CGRect potentialVisibleRect = (CGRect){{0,yOffset},{bounds.size.width,visibleHeight}}; + CGRect targetBounds = [self convertRect:_stepView.bounds fromView:_stepView]; + if (!CGRectContainsRect(potentialVisibleRect, targetBounds)) { + yOffset = targetBounds.origin.y; + } + + CGFloat keyboardOverlapWithActualContent = MAX(contentMaxY - (contentSize.height - intersectionSize.height), 0); + UIEdgeInsets insets = (UIEdgeInsets){.bottom = keyboardOverlapWithActualContent }; + self.contentInset = insets; + + // Rather than setContentOffset, setBounds so that we get a smooth animation + if (ABS(yOffset - bounds.origin.y) > 1) { + bounds.origin.y = yOffset; + [self setBounds:bounds]; + } + } + } completion:nil]; +} + +- (void)keyboardFrameWillChange:(NSNotification *)notification { + CGSize intersectionSize = [self keyboardIntersectionSizeFromNotification:notification]; + + // Assume the overlap is at the bottom of the view + ORKUpdateScrollViewBottomInset(self, intersectionSize.height); + + _keyboardIsUp = YES; + [self animateLayoutForKeyboardNotification:notification]; +} + +- (void)keyboardWillShow:(NSNotification *)notification { + CGSize intersectionSize = [self keyboardIntersectionSizeFromNotification:notification]; + + // Assume the overlap is at the bottom of the view + ORKUpdateScrollViewBottomInset(self, intersectionSize.height); + + _keyboardIsUp = YES; + [self animateLayoutForKeyboardNotification:notification]; +} + +- (void)keyboardWillHide:(NSNotification *)notification { + ORKUpdateScrollViewBottomInset(self, 0); + + _keyboardIsUp = NO; + [self animateLayoutForKeyboardNotification:notification]; +} + +- (void)updateStepViewCenteringConstraint { + BOOL hasIllustration = (_imageView.image != nil); + BOOL hasCaption = _headerView.captionLabel.text.length > 0; + BOOL hasInstruction = _headerView.instructionLabel.text.length > 0; + BOOL hasLearnMore = (_headerView.learnMoreButton.alpha > 0); + + if (_stepViewCenterInStepViewContainerConstraint) { + BOOL offsetCentering = !(hasIllustration || hasCaption || hasInstruction || hasLearnMore); + _stepViewCenterInStepViewContainerConstraint.active = offsetCentering; + } +} + +- (void)updateLayoutMargins { + CGFloat margin = ORKStandardHorizontalMarginForView(self); + UIEdgeInsets layoutMargins = (UIEdgeInsets){.left = margin, .right = margin}; + self.layoutMargins = layoutMargins; + _scrollContainer.layoutMargins = layoutMargins; + _container.layoutMargins = layoutMargins; +} + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window { + { + BOOL hasIllustration = (_imageView.image != nil); + _headerView.hasContentAbove = hasIllustration; + + const CGFloat IllustrationHeight = ORKGetMetricForWindow(ORKScreenMetricIllustrationHeight, window); + const CGFloat IllustrationTopMargin = ORKGetMetricForWindow(ORKScreenMetricTopToIllustration, window); + + _illustrationHeightConstraint.constant = (_imageView.image ? IllustrationHeight : 0); + _topToIllustrationConstraint.constant = (_imageView.image ?IllustrationTopMargin : 0); + } + + { + _headerMinimumHeightConstraint.constant = _minimumStepHeaderHeight; + } +} + +- (void)setContinueHugsContent:(BOOL)continueHugsContent { + _continueHugsContent = continueHugsContent; + [self setNeedsUpdateConstraints]; +} + +- (void)setVerticalCenteringEnabled:(BOOL)verticalCenteringEnabled { + _verticalCenteringEnabled = verticalCenteringEnabled; + [self setNeedsUpdateConstraints]; +} + +- (void)setStepViewFillsAvailableSpace:(BOOL)stepViewFillsAvailableSpace { + _stepViewFillsAvailableSpace = stepViewFillsAvailableSpace; + [self setNeedsUpdateConstraints]; +} + +- (void)setMinimumStepHeaderHeight:(CGFloat)minimumStepHeaderHeight { + _minimumStepHeaderHeight = minimumStepHeaderHeight; + [self updateConstraintConstantsForWindow:self.window]; +} + +- (void)updateConstraints { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + NSArray *views = @[_headerView, _customViewContainer, _stepViewContainer]; + + // Roughly center the container, but put it a little above the center if possible + if (_verticalCenteringEnabled) { + NSLayoutConstraint *verticalCentering1 = [NSLayoutConstraint constraintWithItem:_container + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainer + attribute:NSLayoutAttributeCenterY + multiplier:0.8 + constant:0.0]; + verticalCentering1.priority = UILayoutPriorityDefaultLow; + [_variableConstraints addObject:verticalCentering1]; + + NSLayoutConstraint *verticalCentering2 = [NSLayoutConstraint constraintWithItem:_container + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_scrollContainer + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]; + verticalCentering2.priority = UILayoutPriorityDefaultHigh; + [_variableConstraints addObject:verticalCentering2]; + + NSLayoutConstraint *verticalCentering3 = [NSLayoutConstraint constraintWithItem:_container + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:_scrollContainer + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + verticalCentering3.priority = UILayoutPriorityDefaultHigh; + [_variableConstraints addObject:verticalCentering3]; + } else { + NSLayoutConstraint *verticalTop = [NSLayoutConstraint constraintWithItem:_container + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_scrollContainer + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [_variableConstraints addObject:verticalTop]; + } + + // Don't let the container get too tall + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:_container + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_scrollContainer + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]; + [_variableConstraints addObject:heightConstraint]; + + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[container]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"container":_container}]]; +#ifdef LAYOUT_DEBUG + _container.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.3]; + _scrollContainer.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.3]; +#endif + + // All items with constants use constraint ivars + _illustrationHeightConstraint = [NSLayoutConstraint constraintWithItem:_customViewContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:198.0]; + [_variableConstraints addObject:_illustrationHeightConstraint]; + + _topToIllustrationConstraint = [NSLayoutConstraint constraintWithItem:_customViewContainer + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_container + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [_variableConstraints addObject:_topToIllustrationConstraint]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_headerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_customViewContainer + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_stepViewContainer + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_headerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]]; + + _headerMinimumHeightConstraint = [NSLayoutConstraint constraintWithItem:_headerView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationGreaterThanOrEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:_minimumStepHeaderHeight]; + [_variableConstraints addObject:_headerMinimumHeightConstraint]; + + // Force all to stay within the container's width. + for (UIView *view in views) { +#ifdef LAYOUT_DEBUG + view.backgroundColor = [[UIColor greenColor] colorWithAlphaComponent:0.3]; + view.layer.borderColor = [UIColor redColor].CGColor; + view.layer.borderWidth = 1.0; +#endif + if (view == _stepViewContainer) { + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_container + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + } else { + + NSLayoutRelation relation = NSLayoutRelationGreaterThanOrEqual; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeLeft + relatedBy:relation + toItem:_container + attribute:NSLayoutAttributeLeftMargin + multiplier:1.0 + constant:0.0]]; + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeRight + relatedBy:relation + toItem:_container + attribute:NSLayoutAttributeRightMargin + multiplier:1.0 + constant:0.0]]; + } + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_container + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + NSLayoutConstraint *viewToContainerBottomConstraint = [NSLayoutConstraint constraintWithItem:view + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_container + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + + // Because the bottom items are not always present, we add individual "bottom" constraints + // for all views to ensure the parent sizes large enough to contain everything. + [_variableConstraints addObject:viewToContainerBottomConstraint]; + } + + [self prepareCustomViewContainerConstraints]; + [self prepareStepViewContainerConstraints]; + [NSLayoutConstraint activateConstraints:_variableConstraints]; + + [self updateLayoutMargins]; + + [self updateConstraintConstantsForWindow:self.window]; + [self updateStepViewCenteringConstraint]; + + [super updateConstraints]; +} + +- (void)prepareStepViewContainerConstraints { + if (_stepView) { + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:_stepViewContainer + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + widthConstraint.priority = UILayoutPriorityFittingSizeLevel; + [_variableConstraints addObject:widthConstraint]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_stepView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_stepViewContainer + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + + NSLayoutConstraint *stepViewWidthConstraint = [NSLayoutConstraint constraintWithItem:_stepView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:_stepViewContainer + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]; + stepViewWidthConstraint.priority = UILayoutPriorityRequired; + [_variableConstraints addObject:stepViewWidthConstraint]; + + if (_stepViewFillsAvailableSpace) { + NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_stepViewContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKScreenMetricMaxDimension]; + constraint.priority = UILayoutPriorityFittingSizeLevel; + [_variableConstraints addObject:constraint]; + + NSLayoutConstraint *verticalCentering = [NSLayoutConstraint constraintWithItem:_stepView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_stepViewContainer + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]; + verticalCentering.priority = UILayoutPriorityRequired - 2; + [_variableConstraints addObject:verticalCentering]; + + { + NSLayoutConstraint *verticalCentering2 = [NSLayoutConstraint constraintWithItem:_stepView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_stepViewContainer + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]; + verticalCentering2.priority = UILayoutPriorityRequired - 1; + [_variableConstraints addObject:verticalCentering2]; + _stepViewCenterInStepViewContainerConstraint = verticalCentering2; + } + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_stepView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_stepViewContainer + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + } else { + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[stepView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"stepView": _stepView}]]; + } + } else { + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:_stepViewContainer + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]; + widthConstraint.priority = UILayoutPriorityFittingSizeLevel; + [_variableConstraints addObject:widthConstraint]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_stepViewContainer + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:0.0]]; + } +} + +- (void)prepareCustomViewContainerConstraints { + if (_customView) { + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[customView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"customView": _customView}]]; + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[customView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"customView": _customView}]]; + } + if (_imageView) { + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_customViewContainer + attribute:NSLayoutAttributeHeight + multiplier:1.0 + constant:0.0]]; + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:_customViewContainer + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [_variableConstraints addObject:[NSLayoutConstraint constraintWithItem:_imageView + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:_customViewContainer + attribute:NSLayoutAttributeCenterY + multiplier:1.0 + constant:0.0]]; + } +} + +- (void)setCustomView:(UIView *)customView { + [_customView removeFromSuperview]; + _customView = customView; + [_customViewContainer addSubview:_customView]; + + if (_customView && [_customView constraints].count == 0) { + [_customView setTranslatesAutoresizingMaskIntoConstraints:NO]; + CGSize requiredSize = [_customView sizeThatFits:(CGSize){self.bounds.size.width, CGFLOAT_MAX}]; + + NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:_customView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:requiredSize.width]; + NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:_customView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:requiredSize.height]; + + widthConstraint.priority = UILayoutPriorityDefaultLow; + heightConstraint.priority = UILayoutPriorityDefaultLow; + [NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint]]; + } + [self setNeedsUpdateConstraints]; +} + +- (UIImageView *)imageView { + if (_imageView == nil) { + _imageView = [[ORKTintedImageView alloc] init]; + [_customViewContainer addSubview:_imageView]; + _imageView.contentMode = UIViewContentModeScaleAspectFit; + _imageView.userInteractionEnabled = YES; + [self setNeedsUpdateConstraints]; + } + return _imageView; +} + +- (void)setStepView:(ORKActiveStepCustomView *)customView { + [_stepView removeFromSuperview]; + _stepView = customView; + [_stepViewContainer addSubview:_stepView]; + [self setNeedsUpdateConstraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView_Internal.h new file mode 100755 index 0000000..64dc406 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVerticalContainerView_Internal.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerticalContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVerticalContainerView () + +- (void)updateConstraintConstantsForWindow:(UIWindow *)window; + +@property (nonatomic, assign) BOOL scrollContainerShouldCollapseNavbar; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.h new file mode 100755 index 0000000..f5c881f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.h @@ -0,0 +1,50 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVideoCaptureCameraPreviewView : UIView + +@property (nonatomic, weak, nullable) AVCaptureSession *session; +@property (nonatomic) AVCaptureVideoOrientation videoOrientation; +@property (nonatomic, weak, nullable) UIImage *templateImage; +@property (nonatomic) UIEdgeInsets templateImageInsets; +@property (nonatomic, getter=isTemplateImageHidden) BOOL templateImageHidden; +@property (nonatomic, weak, nullable) NSURL *videoFileURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.m new file mode 100755 index 0000000..6fddfdf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureCameraPreviewView.m @@ -0,0 +1,231 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoCaptureCameraPreviewView.h" +#import "ORKTintedImageView.h" +#import "ORKHelpers_Internal.h" +#import + + +@implementation ORKVideoCaptureCameraPreviewView { + AVCaptureVideoPreviewLayer *_previewLayer; + ORKTintedImageView *_templateImageView; + NSLayoutConstraint *_templateImageViewTopInsetConstraint; + NSLayoutConstraint *_templateImageViewLeftInsetConstraint; + NSLayoutConstraint *_templateImageViewBottomInsetConstraint; + NSLayoutConstraint *_templateImageViewRightInsetConstraint; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _previewLayer = [AVCaptureVideoPreviewLayer new]; + _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; + _previewLayer.needsDisplayOnBoundsChange = YES; + [self.layer addSublayer:_previewLayer]; + + _templateImageView = [ORKTintedImageView new]; + _templateImageView.contentMode = UIViewContentModeScaleAspectFit; + _templateImageView.shouldApplyTint = YES; + _templateImageView.hidden = YES; + _templateImageView.alpha = 0; + [self addSubview:_templateImageView]; + + [self setUpConstraints]; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + _templateImageView.translatesAutoresizingMaskIntoConstraints = NO; + + // Make the insets for the template image view changeable later + _templateImageViewTopInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewTopInsetConstraint]; + + _templateImageViewLeftInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewLeftInsetConstraint]; + + _templateImageViewBottomInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewBottomInsetConstraint]; + + _templateImageViewRightInsetConstraint = [NSLayoutConstraint constraintWithItem:_templateImageView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0]; + [constraints addObject:_templateImageViewRightInsetConstraint]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (AVCaptureSession *)session { + return _previewLayer.session; +} + +- (void)setSession:(AVCaptureSession *)session { + _previewLayer.session = session; +} + +- (UIImage *)templateImage { + return _templateImageView.image; +} + +- (void)setTemplateImage:(UIImage *)templateImage { + _templateImageView.image = templateImage; +} + +- (void)setTemplateImageHidden:(BOOL)templateImageHidden { + if (!templateImageHidden) { + _templateImageView.hidden = NO; + } + + [UIView animateWithDuration:0.15 + animations:^{ + _templateImageView.alpha = templateImageHidden ? 0 : 1; + } completion:^(BOOL finished) { + _templateImageView.hidden = templateImageHidden; + }]; + +} + +- (BOOL)isTemplateImageHidden { + return _templateImageView.hidden; +} + +- (void)setVideoFileURL:(NSURL *)videoFileURL { + _videoFileURL = videoFileURL; + _previewLayer.hidden = videoFileURL!=nil; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + // Ensure that the preview layer takes up all the space + _previewLayer.frame = self.frame; + + // Update the insets for the template image view. + [self updateInsets]; +} + +- (void)updateInsets { + // Update the layoutMargins to match those being used by the preview layer content, if needed + UIEdgeInsets previewLayerContentFrameInsets = [self getPreviewLayerContentFrameInsets]; + if (!UIEdgeInsetsEqualToEdgeInsets(previewLayerContentFrameInsets, self.layoutMargins)) { + self.layoutMargins = previewLayerContentFrameInsets; + } + + // Update the insets on the template image view, if needed + CGRect previewLayerContentFrame = UIEdgeInsetsInsetRect(_previewLayer.frame, previewLayerContentFrameInsets); + UIEdgeInsets insets = UIEdgeInsetsMake(round(self.templateImageInsets.top * previewLayerContentFrame.size.height), + round(self.templateImageInsets.left * previewLayerContentFrame.size.width), + round(self.templateImageInsets.bottom * previewLayerContentFrame.size.height), + round(self.templateImageInsets.right * previewLayerContentFrame.size.width)); + + if (_templateImageViewTopInsetConstraint.constant != insets.top) { + _templateImageViewTopInsetConstraint.constant = insets.top; + } + if (_templateImageViewLeftInsetConstraint.constant != insets.left) { + _templateImageViewLeftInsetConstraint.constant = insets.left; + } + if (_templateImageViewBottomInsetConstraint.constant != -insets.bottom) { + _templateImageViewBottomInsetConstraint.constant = -insets.bottom; + } + if (_templateImageViewRightInsetConstraint.constant != -insets.right) { + _templateImageViewRightInsetConstraint.constant = -insets.right; + } +} + +- (UIEdgeInsets)getPreviewLayerContentFrameInsets { + // Determine the insets on the preview layer frame that correspond to the actual video content + // when using a videoGravity of AVLayerVideoGravityResizeAspect; + NSArray *inputs = _previewLayer.session.inputs; + if (!inputs || inputs.count == 0) + return UIEdgeInsetsZero; + AVCaptureDeviceInput* input = (AVCaptureDeviceInput*)inputs[0]; + CMVideoDimensions cmd = CMVideoFormatDescriptionGetDimensions(input.device.activeFormat.formatDescription); + AVCaptureVideoOrientation avcvo = _previewLayer.connection.videoOrientation; + BOOL landscape = avcvo == AVCaptureVideoOrientationLandscapeLeft || avcvo == AVCaptureVideoOrientationLandscapeRight; + + CGRect contentFrame = AVMakeRectWithAspectRatioInsideRect(CGSizeMake(landscape ? cmd.width : cmd.height, landscape ? cmd.height : cmd.width), _previewLayer.frame); + CGRect overallFrame = _previewLayer.frame; + return UIEdgeInsetsMake(contentFrame.origin.y - overallFrame.origin.y, + contentFrame.origin.x - overallFrame.origin.x, + (overallFrame.origin.y + overallFrame.size.height) - (contentFrame.origin.y + contentFrame.size.height), + (overallFrame.origin.x + overallFrame.size.width) - (contentFrame.origin.x + contentFrame.size.width)); +} + +- (AVCaptureVideoOrientation)videoOrientation { + return _previewLayer.connection.videoOrientation; +} + +- (void)setVideoOrientation:(AVCaptureVideoOrientation)videoOrientation { + _previewLayer.connection.videoOrientation = videoOrientation; +} + +#pragma mark - Accessibility + +- (BOOL)isAccessibilityElement { + return self.videoFileURL == nil; +} + +- (NSString *)accessibilityLabel { + return ORKLocalizedString(@"AX_VIDEO_CAPTURE_LABEL", nil); +} + +- (UIAccessibilityTraits)accessibilityTraits { + return [super accessibilityTraits] | UIAccessibilityTraitStartsMediaSession; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.h new file mode 100755 index 0000000..c3d2bf3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKVideoCaptureStep` class represents a step that captures a video through the device + camera. A template image can optionally be laid over the camera preview to assist in properly + capturing the video. + + To use the video capture step, optionally set the `templateImage` and `templateImageInsets` + properties, incorporate the step into a task, and present the task with a task view controller. + + If implementing a video capture task like this one, remember that people will + take your instructions literally. So be cautious. Make sure your template image + is high contrast and very visible against a variety of backgrounds. + + The recording length can be a max of 20 minutes. It defaults to 2 minutes. + */ +ORK_CLASS_AVAILABLE +@interface ORKVideoCaptureStep : ORKStep + +/** + An image to be displayed over the camera preview. + + The image is stretched to fit the available space while retaining its aspect ratio. + When choosing a size for this asset, be sure to take into account the variations in device + form factors. + */ +@property (nonatomic, strong) UIImage *templateImage; + +/** + Insets to be used in positioning and sizing the `templateImage`. + + The insets are interpreted as percentages relative to the preview frame size. The left + and right insets are relative to the width of the preview frame. The top and bottom + insets are relative to the height of the preview frame. + */ +@property (nonatomic) UIEdgeInsets templateImageInsets; + +/** + The duration, in seconds, for the recording. + + The maximum that this can be set to is 20.0 minutes (60*20 seconds). + The minimum that this can be set to is 0.01 minutes (1 second). + + The default value is 2.0 minutes (60*2 seconds). + */ +@property (nonatomic) NSNumber *duration; + +/** + A Boolean indicating whether the audio is recorded or not. + + The default value is NO. + */ +@property (nonatomic, getter=isAudioMute) BOOL audioMute; + +/** + Constants indicating the desired torch mode to use + + The default value is `AVCaptureTorchModeAuto` (see `AVCaptureTorchMode`). + */ +@property (nonatomic) AVCaptureTorchMode torchMode; + +/** + Constants indicating the physical position of an AVCaptureDevice's hardware on the system. + + The default value is `AVCaptureDevicePositionBack` (see `AVCaptureDevicePosition`). + If `AVCaptureDevicePositionUnspecified` is set, then it defaults to `AVCaptureDevicePositionBack`. + */ +@property (nonatomic) AVCaptureDevicePosition devicePosition; + +/** + An accessibility hint of the capture preview. + + This property can be used to specify accessible instructions for capturing the video. The + use of this property can assist when the `templateImage` may not be visible + to the user. + + For example, if you want to capture a video of the user's right hand, you may use a template + image that displays the outline of the right hand. You may also want to set this property + to a string such as @"Extend your right hand, palm side down, one foot from your device. + Tap the Capture Video button, or two finger tap on the preview, to capture a video of your + extended right hand." + */ +@property (nonatomic, copy) NSString *accessibilityInstructions; + +/** + An accessibility hint of the capture button. + */ +@property (nonatomic, copy) NSString *accessibilityHint; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.m new file mode 100755 index 0000000..67b39d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStep.m @@ -0,0 +1,119 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoCaptureStep.h" +#import "ORKHelpers_Internal.h" +#import "ORKStep_Private.h" +#import "ORKVideoCaptureStepViewController.h" + + +@implementation ORKVideoCaptureStep + ++ (Class)stepViewControllerClass { + return [ORKVideoCaptureStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.optional = YES; + self.duration = @120; + self.audioMute = NO; + self.torchMode = AVCaptureTorchModeAuto; + self.devicePosition = AVCaptureDevicePositionBack; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_IMAGE(aDecoder, templateImage); + ORK_DECODE_UIEDGEINSETS(aDecoder, templateImageInsets); + ORK_DECODE_OBJ(aDecoder, duration); + ORK_DECODE_BOOL(aDecoder, audioMute); + ORK_DECODE_ENUM(aDecoder, torchMode); + ORK_DECODE_ENUM(aDecoder, devicePosition); + ORK_DECODE_OBJ(aDecoder, accessibilityHint); + ORK_DECODE_OBJ(aDecoder, accessibilityInstructions); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_IMAGE(aCoder, templateImage); + ORK_ENCODE_UIEDGEINSETS(aCoder, templateImageInsets); + ORK_ENCODE_OBJ(aCoder, duration); + ORK_ENCODE_BOOL(aCoder, audioMute); + ORK_ENCODE_ENUM(aCoder, torchMode); + ORK_ENCODE_ENUM(aCoder, devicePosition); + ORK_ENCODE_OBJ(aCoder, accessibilityHint); + ORK_ENCODE_OBJ(aCoder, accessibilityInstructions); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKVideoCaptureStep *step = [super copyWithZone:zone]; + step.templateImage = self.templateImage; + step.templateImageInsets = self.templateImageInsets; + step.duration = self.duration; + step.audioMute = self.audioMute; + step.torchMode = self.torchMode; + step.devicePosition = self.devicePosition; + step.accessibilityHint = self.accessibilityHint; + step.accessibilityInstructions = self.accessibilityInstructions; + return step; +} + +- (NSUInteger)hash { + return super.hash ^ self.templateImage.hash ^ self.duration.hash ^ self.audioMute ^ self.torchMode ^ self.devicePosition ^ self.accessibilityHint.hash ^ self.accessibilityInstructions.hash; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && + ORKEqualObjects(self.templateImage, castObject.templateImage) && + UIEdgeInsetsEqualToEdgeInsets(self.templateImageInsets, castObject.templateImageInsets) && + ORKEqualObjects(self.duration, castObject.duration) && + (self.audioMute == castObject.audioMute) && + (self.torchMode == castObject.torchMode) && + (self.devicePosition == castObject.devicePosition) && + ORKEqualObjects(self.accessibilityHint, castObject.accessibilityHint) && + ORKEqualObjects(self.accessibilityInstructions, castObject.accessibilityInstructions); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.h new file mode 100755 index 0000000..e9afe0e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +/** + The `ORKVideoCaptureStepViewController` class represents the step view controller that + corresponds to an `ORKVideoCaptureStep` class. + + It is not usually necessary to instantiate this view controller directly. + Instead, add a video capture step to a task, and present the task in a task + view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKVideoCaptureStepViewController : ORKStepViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.m new file mode 100755 index 0000000..3971133 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureStepViewController.m @@ -0,0 +1,401 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKStepViewController_Internal.h" +#import "ORKVideoCaptureStepViewController.h" +#import "ORKVideoCaptureView.h" +#import "ORKVideoCaptureStep.h" +#import "ORKHelpers_Internal.h" + +#import + + +@interface ORKVideoCaptureStepViewController () + +@end + + +@implementation ORKVideoCaptureStepViewController { + ORKVideoCaptureView *_videoCaptureView; + ORKVideoCaptureStep *_videoCaptureStep; + dispatch_queue_t _sessionQueue; + AVCaptureSession *_captureSession; + AVCaptureMovieFileOutput *_movieFileOutput; + NSURL *_fileURL; + BOOL _recording; +} + +- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result { + self = [self initWithStep:step]; + if (self) { + ORKStepResult *stepResult = (ORKStepResult *)result; + if (stepResult && [stepResult results].count > 0) { + + ORKFileResult *fileResult = ORKDynamicCast([stepResult results].firstObject, ORKFileResult); + + if (fileResult.fileURL) { + self.fileURL = fileResult.fileURL; + } + } + } + return self; +} + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + self.fileURL = nil; + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + _videoCaptureView.translatesAutoresizingMaskIntoConstraints = NO; + + UIView *iPadContentView = [self viewForiPadLayoutConstraints]; + [constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_videoCaptureView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_videoCaptureView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_videoCaptureView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_videoCaptureView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:iPadContentView ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _videoCaptureView.continueButtonItem = continueButtonItem; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + _videoCaptureView.skipButtonItem = skipButtonItem; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + [super setCancelButtonItem:cancelButtonItem]; + _videoCaptureView.cancelButtonItem = cancelButtonItem; +} + +- (void)stepDidChange { + [super stepDidChange]; + + if (self.step && [self isViewLoaded]) { + [_videoCaptureView removeFromSuperview]; + _videoCaptureView = nil; + _movieFileOutput = nil; + + _videoCaptureView = [[ORKVideoCaptureView alloc] initWithFrame:CGRectZero]; + _videoCaptureView.videoCaptureStep = (ORKVideoCaptureStep *)self.step; + _videoCaptureView.delegate = self; + _videoCaptureView.cancelButtonItem = self.cancelButtonItem; + [self.view addSubview:_videoCaptureView]; + + + _videoCaptureStep = (ORKVideoCaptureStep *)self.step; + _movieFileOutput = [AVCaptureMovieFileOutput new]; + + [self setUpConstraints]; + + + // Capture actions should be performed off the main queue to keep the UI responsive + _sessionQueue = dispatch_queue_create("session queue", DISPATCH_QUEUE_SERIAL); + + // Setup the capture session + dispatch_async(_sessionQueue, ^{ + [self queue_SetupCaptureSession]; + }); + } +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // If we don't already have a captured image, then start running the capture session. + if (!_fileURL) { + dispatch_async(_sessionQueue, ^{ + [_captureSession startRunning]; + }); + } +} + +- (void)viewWillDisappear:(BOOL)animated { + // If the capture session is running, stop it + if (_captureSession.isRunning) { + dispatch_async(_sessionQueue, ^{ + [_captureSession stopRunning]; + }); + } + + [_videoCaptureView.playerViewController.player pause]; + + [super viewWillDisappear:animated]; +} + +- (void)queue_SetupCaptureSession { + // Create the session + _captureSession = [AVCaptureSession new]; + [_captureSession beginConfiguration]; + + // Get the camera + AVCaptureDevice *device; + + AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:_videoCaptureStep.devicePosition ? : AVCaptureDevicePositionBack]; + + if (discoverySession.devices.count > 0) { + device = discoverySession.devices[0]; + } + + if (device) { + // Check if the device has the requested torchMode + if([device isTorchModeSupported:_videoCaptureStep.torchMode]){ + [device lockForConfiguration:nil]; + device.torchMode = _videoCaptureStep.torchMode; + [device unlockForConfiguration]; + } + + // Configure the input and output + AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil]; + + AVCaptureMovieFileOutput *movieFileOutput = [AVCaptureMovieFileOutput new]; + movieFileOutput.maxRecordedDuration = CMTimeMakeWithSeconds(_videoCaptureStep.duration.floatValue, 30.0); + + if ([_captureSession canAddInput:input] && [_captureSession canAddOutput:movieFileOutput]) { + [_captureSession addInput:input]; + [_captureSession addOutput:movieFileOutput]; + + if (!_videoCaptureStep.audioMute) { + AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; + AVCaptureDeviceInput * audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:nil]; + if ([_captureSession canAddInput:audioInput]) { + [_captureSession addInput:audioInput]; + } + } + _movieFileOutput = movieFileOutput; + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_NO_PERMISSIONS", nil)}]]; + }); + _captureSession = nil; + } + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + [self handleError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_CAMERA_NOT_FOUND", nil)}]]; + }); + _captureSession = nil; + } + + + [_captureSession commitConfiguration]; + + _videoCaptureView.session = _captureSession; +} + +- (void)handleError:(NSError *)error { + // Shut down the session, if running + if (_captureSession.isRunning) { + ORKStrongTypeOf(_captureSession) strongCaptureSession = _captureSession; + dispatch_async(_sessionQueue, ^{ + [strongCaptureSession stopRunning]; + }); + } + + // Reset the state to before the capture session was setup. Order here is important + _captureSession = nil; + _movieFileOutput = nil; + _videoCaptureView.session = nil; + _videoCaptureView.videoFileURL = nil; + _fileURL = nil; + + // Show the error in the image capture view + _videoCaptureView.error = error; +} + +- (void)setFileURL:(NSURL *)fileURL { + _fileURL = fileURL; + _videoCaptureView.videoFileURL = fileURL; + + [self notifyDelegateOnResultChange]; +} + +- (void)setRecording:(BOOL)recording { + _recording = recording; + _videoCaptureView.recording = recording; +} + +- (ORKStepResult *)result { + ORKStepResult *stepResult = [super result]; + NSDate *now = stepResult.endDate; + + NSMutableArray *results = [NSMutableArray arrayWithArray:stepResult.results]; + ORKFileResult *fileResult = [[ORKFileResult alloc] initWithIdentifier:self.step.identifier]; + fileResult.startDate = stepResult.startDate; + fileResult.endDate = now; + fileResult.contentType = @"video/mp4"; + fileResult.fileURL = _fileURL; + [results addObject:fileResult]; + stepResult.results = [results copy]; + return stepResult; +} + + +#pragma mark - ORKVideoCaptureViewDelegate + +- (void)retakePressed:(void (^)(void))handler { + dispatch_async(_sessionQueue, ^{ + [_captureSession startRunning]; + dispatch_async(dispatch_get_main_queue(), ^{ + self.fileURL = nil; + if (handler) { + handler(); + } + }); + }); +} + +- (void)capturePressed:(void (^)(void))handler { + // Capture the video via the output + dispatch_async(_sessionQueue, ^{ + _fileURL = [self.outputDirectory URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4",self.step.identifier]]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:_fileURL.path]) { + [fileManager removeItemAtURL:_fileURL error:nil]; + } + AVCaptureConnection *connection = [_movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; + if (connection.isActive) { + [_movieFileOutput startRecordingToOutputFileURL:_fileURL + recordingDelegate:self]; + + // Use the main queue, as UI components may need to be updated + dispatch_async(dispatch_get_main_queue(), ^{ + if (handler) { + handler(); + } + }); + } + else { + ORK_Log_Info("Connection not ready"); + // Use the main queue, as UI components may need to be updated + dispatch_async(dispatch_get_main_queue(), ^{ + if (handler) { + handler(); + } + [self handleError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSFeatureUnsupportedError userInfo:@{NSLocalizedDescriptionKey:ORKLocalizedString(@"CAPTURE_ERROR_NO_PERMISSIONS", nil)}]]; + + }); + } + }); +} + +- (void)stopCapturePressed:(void (^)(void))handler { + if (_movieFileOutput.recording) { + dispatch_async(_sessionQueue, ^{ + [_movieFileOutput stopRecording]; + + // Use the main queue, as UI components may need to be updated + dispatch_async(dispatch_get_main_queue(), ^{ + if (handler) { + handler(); + } + }); + }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + if (handler) { + handler(); + } + }); + } +} + +- (void)videoOrientationDidChange:(AVCaptureVideoOrientation)videoOrientation { + // Keep the output orientation in sync with the input orientation + NSArray *connections = _movieFileOutput.connections; + if (connections.count > 0) { + connections[0].videoOrientation = videoOrientation; + } +} + + +#pragma mark - AVCaptureFileOutputRecordingDelegate + +- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections { + self.recording = YES; +} + +- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { + if (error && !error.userInfo[AVErrorRecordingSuccessfullyFinishedKey]) { + _videoCaptureView.error = error; + return; + } + + self.recording = NO; + self.fileURL = outputFileURL; + + if (UIAccessibilityIsVoiceOverRunning()) { + UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, ORKLocalizedString(@"AX_VIDEO_CAPTURE_COMPLETE", nil)); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.h new file mode 100755 index 0000000..ccd1636 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import +#import "ORKVideoCaptureStep.h" +#import "ORKVideoCaptureCameraPreviewView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@protocol ORKVideoCaptureViewDelegate + +- (void)capturePressed:(void (^ _Nullable)(void))handler; +- (void)stopCapturePressed:(void (^ _Nullable)(void))handler; +- (void)retakePressed:(void (^ _Nullable)(void))handler; +- (void)videoOrientationDidChange:(AVCaptureVideoOrientation)videoOrientation; + +@end + + +@interface ORKVideoCaptureView : UIView + +@property (nonatomic, strong, nullable) ORKVideoCaptureStep *videoCaptureStep; +@property (nonatomic, weak, nullable) id delegate; +@property (nonatomic, weak, nullable) AVCaptureSession *session; +@property (nonatomic, strong, nullable) UIBarButtonItem *continueButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *skipButtonItem; +@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem; +@property (nonatomic, strong, nullable) NSURL *videoFileURL; +@property (nonatomic, strong, nullable) NSError *error; +@property (nonatomic) BOOL recording; +@property (nonatomic, strong, nullable) ORKVideoCaptureCameraPreviewView *previewView; +@property (nonatomic, strong, readonly) AVPlayerViewController *playerViewController; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.m new file mode 100755 index 0000000..8b93402 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoCaptureView.m @@ -0,0 +1,491 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoCaptureView.h" +#import "ORKVideoCaptureCameraPreviewView.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKHelpers_Private.h" +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import "ORKStepHeaderView_Internal.h" + + +@implementation ORKVideoCaptureView { + ORKStepHeaderView *_headerView; + ORKNavigationContainerView *_navigationFooterView; + UIBarButtonItem *_captureButtonItem; + UIBarButtonItem *_stopButtonItem; + UIBarButtonItem *_recordingButtonItem; + UIBarButtonItem *_recaptureButtonItem; + NSMutableArray *_variableConstraints; + NSTimer *_timer; + CGFloat _recordTime; + NSDateComponentsFormatter *_dateComponentsFormatter; + + BOOL _capturePressesIgnored; + BOOL _stopCapturePressesIgnored; + BOOL _retakePressesIgnored; + BOOL _showSkipButtonItem; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _previewView = [ORKVideoCaptureCameraPreviewView new]; + [self addSubview:_previewView]; + + _playerViewController = [AVPlayerViewController new]; + _playerViewController.videoGravity = AVLayerVideoGravityResizeAspectFill; + _playerViewController.allowsPictureInPicturePlayback = NO; + [self addSubview:_playerViewController.view]; + + _headerView = [ORKStepHeaderView new]; + _headerView.instructionLabel.text = @" "; + [self addSubview:_headerView]; + + _captureButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"CAPTURE_BUTTON_CAPTURE_VIDEO", nil) + style:UIBarButtonItemStylePlain + target:self + action:@selector(capturePressed)]; + + _stopButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO", nil) + style:UIBarButtonItemStylePlain + target:self + action:@selector(stopCapturePressed)]; + + _recordingButtonItem = [[UIBarButtonItem alloc] initWithTitle:nil + style:UIBarButtonItemStylePlain + target:self + action:nil]; + + _recaptureButtonItem = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"CAPTURE_BUTTON_RECAPTURE_VIDEO", nil) + style:UIBarButtonItemStylePlain + target:self + action:@selector(retakePressed)]; + + _navigationFooterView = [ORKNavigationContainerView new]; + _navigationFooterView.continueEnabled = YES; + _navigationFooterView.optional = YES; + _navigationFooterView.footnoteLabel.textAlignment = NSTextAlignmentCenter; + _navigationFooterView.footnoteLabel.text = @" "; + _navigationFooterView.backgroundColor = ORKColor(ORKNavigationContainerColorKey); + [_navigationFooterView setAlpha:0.8]; + [self addSubview:_navigationFooterView]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queue_sessionRunning) name:AVCaptureSessionDidStartRunningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionWasInterrupted:) name:AVCaptureSessionWasInterruptedNotification object:self.session]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionInterruptionEnded:) name:AVCaptureSessionInterruptionEndedNotification object:self.session]; + + [self updateAppearance]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)queue_sessionRunning { + dispatch_async(dispatch_get_main_queue(), ^{ + _previewView.templateImageHidden = NO; + }); +} + +- (void)orientationDidChange { + dispatch_async(dispatch_get_main_queue(), ^{ + AVCaptureVideoOrientation orientation = AVCaptureVideoOrientationPortrait; + switch ([[UIApplication sharedApplication] statusBarOrientation]) { + case UIInterfaceOrientationLandscapeRight: + orientation = AVCaptureVideoOrientationLandscapeRight; + break; + case UIInterfaceOrientationLandscapeLeft: + orientation = AVCaptureVideoOrientationLandscapeLeft; + break; + case UIInterfaceOrientationPortraitUpsideDown: + orientation = AVCaptureVideoOrientationPortraitUpsideDown; + break; + case UIInterfaceOrientationPortrait: + orientation = AVCaptureVideoOrientationPortrait; + break; + case UIInterfaceOrientationUnknown: + // Do nothing in these cases, since we don't need to change display orientation. + return; + } + + [_previewView setVideoOrientation:orientation]; + [self.delegate videoOrientationDidChange:orientation]; + [self setNeedsUpdateConstraints]; + }); +} + +- (void)setVideoCaptureStep:(ORKVideoCaptureStep *)videoCaptureStep { + _videoCaptureStep = videoCaptureStep; + + _previewView.templateImage = _videoCaptureStep.templateImage; + _previewView.templateImageInsets = _videoCaptureStep.templateImageInsets; + + _captureButtonItem.accessibilityHint = _videoCaptureStep.accessibilityHint; + + _showSkipButtonItem = _videoCaptureStep.optional; + + [self updateAppearance]; +} + +- (void)updateAppearance { + + _headerView.alpha = (self.error) ? 1 : 0; + _previewView.alpha = (self.error) ? 0 : 1; + + if (self.error) { + // Display the error instruction. + _headerView.instructionLabel.text = [self.error.userInfo valueForKey:NSLocalizedDescriptionKey]; + + // Hide the template image if there is an error + _previewView.templateImageHidden = YES; + _previewView.accessibilityHint = nil; + _playerViewController.view.hidden = YES; + + // Show skip, if available, and hide the template and continue/capture button + _navigationFooterView.continueButtonItem = nil; + _navigationFooterView.skipButtonItem = _skipButtonItem; + _navigationFooterView.skipEnabled = YES; + } else if (self.videoFileURL) { + // Hide the template image after capturing + _previewView.templateImageHidden = YES; + _previewView.accessibilityHint = nil; + _playerViewController.view.hidden = NO; + + // Set the continue button to the one we've saved and configure the skip button as a recapture button + _navigationFooterView.continueButtonItem = _continueButtonItem; + _navigationFooterView.skipButtonItem = _recaptureButtonItem; + _navigationFooterView.skipEnabled = YES; + } else if (self.recording) { + // Show the template image during capturing + _previewView.templateImageHidden = NO; + _previewView.accessibilityHint = _videoCaptureStep.accessibilityInstructions; + _playerViewController.view.hidden = YES; + + // Change the continue button back to capture. + _navigationFooterView.continueButtonItem = _stopButtonItem; + + // Start a timer to show recording progress. + _navigationFooterView.footnoteLabel.text = [self formattedTimeFromSeconds:_videoCaptureStep.duration.floatValue]; + _navigationFooterView.skipEnabled = NO; + _recordTime = 0.0; + _timer = [NSTimer scheduledTimerWithTimeInterval:0.1 + target:self + selector:@selector(updateRecordTime:) + userInfo:nil + repeats:YES]; + } else { + // Show the template image during capturing + _previewView.templateImageHidden = NO; + _previewView.accessibilityHint = _videoCaptureStep.accessibilityInstructions; + _playerViewController.view.hidden = YES; + + // Change the continue button back to capture, and change the recapture button back to skip (if available) + _navigationFooterView.continueButtonItem = _captureButtonItem; + _navigationFooterView.skipButtonItem = _skipButtonItem; + _navigationFooterView.skipEnabled = YES; + } +} + +- (void)setVideoFileURL:(NSURL *)videoFileURL { + _videoFileURL = videoFileURL; + _previewView.videoFileURL = videoFileURL; + + if (_videoFileURL != nil) { + AVPlayerItem *item = [[AVPlayerItem alloc] initWithURL:_videoFileURL]; + _playerViewController.player = [[AVPlayer alloc] initWithPlayerItem:item]; + } + + [self updateAppearance]; +} + +- (void)setRecording:(BOOL)recording { + _recording = recording; + [self updateAppearance]; +} + +- (void)setError:(NSError *)error { + _error = error; + [self updateAppearance]; +} + +- (void)updateConstraints { + + if (_variableConstraints) { + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + } + + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + + UIView *playerView = _playerViewController.view; + _headerView.translatesAutoresizingMaskIntoConstraints = NO; + self.translatesAutoresizingMaskIntoConstraints = NO; + _previewView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + playerView.translatesAutoresizingMaskIntoConstraints = NO; + + [_variableConstraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_headerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_headerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_headerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:playerView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:playerView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:playerView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:playerView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_previewView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:playerView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_previewView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:playerView + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_previewView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:playerView + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_previewView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:playerView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + + + ]]; + + [NSLayoutConstraint activateConstraints:_variableConstraints]; + [super updateConstraints]; +} + +- (AVCaptureSession *)session { + return _previewView.session; +} + +- (void)setSession:(AVCaptureSession *)session { + _previewView.session = session; + // Set up the proper videoOrientation from the start + [self orientationDidChange]; +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + if (_showSkipButtonItem) { + _skipButtonItem = skipButtonItem; + [self updateAppearance]; + } +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + _continueButtonItem = continueButtonItem; + [self updateAppearance]; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + _cancelButtonItem = cancelButtonItem; + [self updateAppearance]; +} + +- (void)capturePressed { + // If we are still waiting for the delegate to complete, ignore futher presses + if (_capturePressesIgnored) + return; + + // Ignore futher presses until the delegate completes + _capturePressesIgnored = YES; + + // Capture the video via the delegate + [self.delegate capturePressed:^ { + // Stop ignoring presses + _capturePressesIgnored = NO; + }]; +} + +- (void)stopCapturePressed { + // If we are still waiting for the delegate to complete, ignore futher presses + if (_stopCapturePressesIgnored) + return; + + // Ignore futher presses until the delegate completes + _stopCapturePressesIgnored = YES; + + // Invalidate timer. + [_timer invalidate]; + + // Stop the video capture via the delegate + [self.delegate stopCapturePressed:^ { + // Stop ignoring presses + _stopCapturePressesIgnored = NO; + }]; + +} + +- (void)retakePressed { + // If we are still waiting for the delegate to complete, ignore futher presses + if (_retakePressesIgnored) + return; + + // Ignore futher presses until the delegate completes + _retakePressesIgnored = YES; + + // Tell the delegate to start capturing again + [self.delegate retakePressed:^{ + // Stop ignoring presses + _retakePressesIgnored = NO; + }]; +} + +- (void)updateRecordTime:(NSTimer *)timer { + _recordTime += timer.timeInterval; + + if (_recordTime >= _videoCaptureStep.duration.floatValue || !self.recording) { + [_timer invalidate]; + [self updateAppearance]; + } else { + CGFloat remainingTime = _videoCaptureStep.duration.floatValue - _recordTime; + _navigationFooterView.footnoteLabel.text = [self formattedTimeFromSeconds:remainingTime]; + } +} + +- (NSString *)formattedTimeFromSeconds:(CGFloat)seconds { + if (!_dateComponentsFormatter) { + _dateComponentsFormatter = [NSDateComponentsFormatter new]; + _dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorPad; + _dateComponentsFormatter.allowedUnits = NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitNanosecond; + } + return [_dateComponentsFormatter stringFromTimeInterval:seconds]; +} + +- (void)sessionWasInterrupted:(NSNotification *)notification { + AVCaptureSessionInterruptionReason reason = [notification.userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]; + if (reason == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps) { + [self setError:[[NSError alloc] initWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey : ORKLocalizedString(@"CAMERA_UNAVAILABLE_MESSAGE", nil)}]]; + } + [_previewView.session stopRunning]; +} + +- (void)sessionInterruptionEnded:(NSNotification *)notification { + [self setError:nil]; +} + +- (BOOL)accessibilityPerformMagicTap { + if (self.error) { + return NO; + } + if (self.videoFileURL) { + [self retakePressed]; + } else { + [self capturePressed]; + } + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.h new file mode 100755 index 0000000..03d1c32 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.h @@ -0,0 +1,65 @@ +/* +Copyright (c) 2017, Oliver Schaefer. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + An `ORKVideoInstructionStep` object gives the participant video-based instructions for a task. + + You can use video instruction steps to present video content during a task. + + */ +ORK_CLASS_AVAILABLE +@interface ORKVideoInstructionStep : ORKInstructionStep + +/** + The URL of the video to play (local or remote) + */ +@property (nonatomic, copy, nullable) NSURL *videoURL; + +/** + The time (in seconds) at which the thumbnail image is created. + + When presented, the step view controller will display a preview image of the video to play. + This property tells the step view controller at what time of the video this thumbnail image + should be created. + + Default is 0, negative values will be ignored. + */ +@property (nonatomic) NSUInteger thumbnailTime; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.m new file mode 100755 index 0000000..dc71865 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStep.m @@ -0,0 +1,93 @@ +/* + Copyright (c) 2017, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoInstructionStep.h" +#import "ORKVideoInstructionStepViewController.h" +#import "ORKHelpers_Internal.h" +#import + + +@implementation ORKVideoInstructionStep + ++ (Class)stepViewControllerClass { + return [ORKVideoInstructionStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + _thumbnailTime = 0; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_URL(aDecoder, videoURL); + ORK_DECODE_INTEGER(aDecoder, thumbnailTime); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_URL(aCoder, videoURL); + ORK_ENCODE_INTEGER(aCoder, thumbnailTime); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKVideoInstructionStep *step = [super copyWithZone:zone]; + step.videoURL = self.videoURL; + step.thumbnailTime = self.thumbnailTime; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + __typeof(self) castObject = object; + return isParentSame && ORKEqualObjects(castObject.videoURL, self.videoURL) && + castObject.thumbnailTime == self.thumbnailTime; +} + +- (NSUInteger)hash { + return super.hash ^ self.videoURL.hash; +} + +- (void)setThumbnailTime:(NSUInteger)thumbnailTime { + _thumbnailTime = thumbnailTime; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.h new file mode 100755 index 0000000..ff9ce65 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2016, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKVideoInstructionStepResult` class represents the result of a video insruction step (`ORKVideoInstructionStep`). + + A video instruction result is produced by the task view controller when it presents a video instruction step. + + */ +ORK_CLASS_AVAILABLE +@interface ORKVideoInstructionStepResult : ORKResult + +/** + The time (in seconds) after video playback stopped, or NaN if the video was never played. + */ +@property (nonatomic) Float64 playbackStoppedTime; + +/** + Returns 'YES' if the video was watched until the end, or 'NO' if video playback was stopped half way. + */ +@property (nonatomic) BOOL playbackCompleted; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.m new file mode 100755 index 0000000..743155c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepResult.m @@ -0,0 +1,80 @@ +/* + Copyright (c) 2016, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoInstructionStepResult.h" + +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKVideoInstructionStepResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + [aCoder encodeFloat:self.playbackStoppedTime forKey:@"playbackStoppedTime"]; + ORK_ENCODE_BOOL(aCoder, playbackCompleted); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + self.playbackStoppedTime = [aDecoder decodeFloatForKey:@"playbackStoppedTime"]; + ORK_DECODE_BOOL(aDecoder, playbackCompleted); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + NSNumber *playbackStoppedTime = [NSNumber numberWithFloat:self.playbackStoppedTime]; + return super.hash ^ [playbackStoppedTime hash] ^ self.playbackCompleted; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.playbackStoppedTime == castObject.playbackStoppedTime && + self.playbackCompleted == castObject.playbackCompleted); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKVideoInstructionStepResult *result = [super copyWithZone:zone]; + result->_playbackStoppedTime = self.playbackStoppedTime; + result->_playbackCompleted = self.playbackCompleted; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.h new file mode 100755 index 0000000..26922dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2017, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +/** + An `ORKVideoInstructionStepViewController` object is the view controller for an `ORKVideoInstructionStep` object. + + In general, you don't need to instantiate an video instruction step view controller directly. + Instead, add an video instruction step to a task and present the task using a + task view controller. When appropriate, the task view controller instantiates the step + view controller for the step. + */ +ORK_CLASS_AVAILABLE +@interface ORKVideoInstructionStepViewController : ORKInstructionStepViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.m new file mode 100755 index 0000000..5b1f64e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKVideoInstructionStepViewController.m @@ -0,0 +1,160 @@ +/* + Copyright (c) 2017, Oliver Schaefer. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVideoInstructionStepViewController.h" +#import "ORKInstructionStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKInstructionStepView.h" +#import "ORKVideoInstructionStepResult.h" +#import "AVFoundation/AVFoundation.h" +#import +#import "ORKHelpers_Internal.h" + + +@interface ORKRateObservedPlayer : AVPlayer + +@end + + +@implementation ORKRateObservedPlayer { + id _observer; +} + +- (instancetype)initWithPlayerItem:(AVPlayerItem *)item andObserver:(id)observer { + self = [super initWithPlayerItem:item]; + if (self) { + _observer = observer; + [self addObserver:_observer forKeyPath:@"rate" options:NSKeyValueObservingOptionNew context:nil]; + } + return self; +} + +- (void)dealloc { + [self removeObserver:_observer forKeyPath:@"rate"]; +} + +@end + + +@implementation ORKVideoInstructionStepViewController { + Float64 _playbackStoppedTime; + BOOL _playbackCompleted; +} + +- (ORKVideoInstructionStep *)videoInstructionStep { + NSAssert(self.step == nil || [self.step isKindOfClass:[ORKVideoInstructionStep class]], @"View controller is only valid with a ORKVideoInstructionStep step class."); + return (ORKVideoInstructionStep *)self.step; +} + +- (void)stepDidChange { + [self setThumbnailImageFromAsset]; + [super stepDidChange]; + _playbackStoppedTime = NAN; + _playbackCompleted = NO; + //FIXME: video instruction step needs to adopt ORKInstructionStepContainerView +// if (self.step && [self isViewLoaded] && [self videoInstructionStep].image) { +// UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] init]; +// [tapRecognizer addTarget:self action:@selector(play)]; +// [self.stepView.instructionImageView addGestureRecognizer:tapRecognizer]; +// +// if (self.stepView.instructionImageView.image) { +// UIImageView *playImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"play" inBundle:ORKBundle() compatibleWithTraitCollection:nil]]; +// self.stepView.instructionImageView.userInteractionEnabled = YES; +// [self.stepView.instructionImageView addSubview:playImageView]; +// +// playImageView.translatesAutoresizingMaskIntoConstraints = NO; +// +// NSLayoutConstraint* xConstraint = [NSLayoutConstraint constraintWithItem:self.stepView.instructionImageView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:playImageView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]; +// NSLayoutConstraint* yConstraint = [NSLayoutConstraint constraintWithItem:self.stepView.instructionImageView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:playImageView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; +// +// [self.stepView.instructionImageView addConstraints:@[xConstraint, yConstraint]]; +// } +// } +} + +- (void)setThumbnailImageFromAsset { + if ([self videoInstructionStep].image) { + return; + } + if (![self videoInstructionStep].videoURL) { + self.videoInstructionStep.image = nil; + return; + } + AVAsset* asset = [AVAsset assetWithURL:[self videoInstructionStep].videoURL]; + CMTime duration = [asset duration]; + duration.value = MIN([self videoInstructionStep].thumbnailTime, duration.value / duration.timescale) * duration.timescale; + AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; + CGImageRef thumbnailImageRef = [imageGenerator copyCGImageAtTime:duration actualTime:NULL error:NULL]; + UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnailImageRef]; + CGImageRelease(thumbnailImageRef); + [self videoInstructionStep].image = thumbnailImage; +} + +- (void)play { + AVAsset* asset = [AVAsset assetWithURL:[self videoInstructionStep].videoURL]; + AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:asset]; + ORKRateObservedPlayer* player = [[ORKRateObservedPlayer alloc] initWithPlayerItem:playerItem andObserver:self]; + player.actionAtItemEnd = AVPlayerActionAtItemEndPause; + AVPlayerViewController *playerViewController = [[AVPlayerViewController alloc] init]; + playerViewController.player = player; + + [self presentViewController:playerViewController animated:true completion:^{ + if (playerViewController.player.status == AVPlayerStatusReadyToPlay) { + [playerViewController.player play]; + } + }]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + if ([keyPath isEqual: @"rate"]) { + AVPlayer *player = (AVPlayer*)object; + if (player.rate == 0) { + _playbackStoppedTime = CMTimeGetSeconds([player.currentItem currentTime]); + if (CMTimeGetSeconds(player.currentItem.duration) == _playbackStoppedTime) { + _playbackCompleted = YES; + } + } + } +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + if (parentResult) { + ORKVideoInstructionStepResult *childResult = [[ORKVideoInstructionStepResult alloc] + initWithIdentifier:self.step.identifier]; + childResult.playbackStoppedTime = _playbackStoppedTime; + childResult.playbackCompleted = _playbackCompleted; + parentResult.results = [self.addedResults arrayByAddingObject:childResult] ? : @[childResult]; + } + return parentResult; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.h new file mode 100755 index 0000000..a96b82f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.h @@ -0,0 +1,71 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKWaitStep` class represents a step that displays a label and an activity + indicator mask. + + This task can be used to indicate to a user that a process is occuring that does + not need their input, and possibly indicate the progress that process has made. + To update the progress on screen, use the methods provided on the + `ORKWaitStepViewController` this step represents. Once the processing is complete, + `goForward` must be called on the `ORKWaitStepViewController` in order for the user to + be able to continue. + */ +ORK_CLASS_AVAILABLE +@interface ORKWaitStep : ORKStep + +/** + This property specifies the type of progress bar that will be displayed. + + ORKProgressIndicatorTypeIndeterminate (default) is for indeterminate duration operations + ORKProgressIndicatorTypeProgressBar is for determinate duration operations + */ +@property (nonatomic) ORKProgressIndicatorType indicatorType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.m new file mode 100755 index 0000000..89b5361 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStep.m @@ -0,0 +1,97 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWaitStep.h" + +#import "ORKWaitStepViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKWaitStep + ++ (Class)stepViewControllerClass { + return [ORKWaitStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + self.indicatorType = ORKProgressIndicatorTypeIndeterminate; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_ENUM(aDecoder, indicatorType); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_ENUM(aCoder, indicatorType); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)allowsBackNavigation { + return NO; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKWaitStep *step = [super copyWithZone:zone]; + step.indicatorType = self.indicatorType; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + self.indicatorType == castObject.indicatorType); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.h new file mode 100755 index 0000000..0092bbc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKStepContainerView.h" +#import "ORKTypes.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKWaitStepView : ORKStepContainerView + +- (instancetype)initWithIndicatorType:(ORKProgressIndicatorType)type; + +@property (nonatomic, readonly) UIProgressView *progressView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.m new file mode 100755 index 0000000..36146df --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepView.m @@ -0,0 +1,85 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWaitStepView.h" +#import "ORKStepContainerView_Private.h" +#import "ORKStepView_Private.h" +#import "ORKStepContentView_Private.h" +#import "ORKNavigationContainerView.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKAccessibility.h" +#import "ORKSkin.h" + + +@implementation ORKWaitStepView { + NSArray *_customConstraints; + ORKProgressIndicatorType _indicatorType; + UIActivityIndicatorView *_activityIndicatorView; + NSNumberFormatter *_percentFormatter; +} + +- (instancetype)initWithIndicatorType:(ORKProgressIndicatorType)type { + self = [super init]; + if (self) { + + _indicatorType = type; + + self.customContentView = [UIView new]; + switch (_indicatorType) { + case ORKProgressIndicatorTypeProgressBar: + _progressView = [UIProgressView new]; + self.customContentView = _progressView; + break; + case ORKProgressIndicatorTypeIndeterminate: + if (@available(iOS 13.0, *)) { + _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium]; + } else { + _activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + } + [_activityIndicatorView startAnimating]; + self.customContentView = _activityIndicatorView; + break; + } + self.stepContentView.textLabel.textAlignment = NSTextAlignmentCenter; + } + return self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.h new file mode 100755 index 0000000..7d43d3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.h @@ -0,0 +1,74 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKWaitStepViewController` class represents the step view controller that corresponds to an `ORKWaitStep`. + + It is not usually necessary to instantiate this view controller directly. + Instead, add a wait step to a task, and present the task in a task + view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKWaitStepViewController: ORKStepViewController + +/** + Updates the amount of progress displayed in the progress bar if the current indicator mask is set to progress bar. + + @param progress The fraction of work completed on the range of zero to one. + @param animated If true, the update is animated. + */ +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated; + +/** + Updates the text on the step with the process that is occuring. + + @param text The description of the process that is occuring. + */ +- (void)updateText:(NSString *)text; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.m new file mode 100755 index 0000000..0e9193d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWaitStepViewController.m @@ -0,0 +1,155 @@ +/* + Copyright (c) 2015, Alejandro Martinez, Quintiles Inc. + Copyright (c) 2015, Brian Kelly, Quintiles Inc. + Copyright (c) 2015, Bryan Strothmann, Quintiles Inc. + Copyright (c) 2015, Greg Yip, Quintiles Inc. + Copyright (c) 2015, John Reites, Quintiles Inc. + Copyright (c) 2015, Pavel Kanzelsberger, Quintiles Inc. + Copyright (c) 2015, Richard Thomas, Quintiles Inc. + Copyright (c) 2015, Shelby Brooks, Quintiles Inc. + Copyright (c) 2015, Steve Cadwallader, Quintiles Inc. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWaitStepViewController.h" + +#import "ORKStepHeaderView_Internal.h" +#import "ORKWaitStepView.h" +#import "ORKStepView.h" +#import "ORKStepViewController_Internal.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKWaitStep.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKWaitStepViewController { + ORKWaitStepView *_waitStepView; + ORKProgressIndicatorType _indicatorType; + NSString *_updatedText; + NSArray *_constraints; +} + +- (ORKWaitStep *)waitStep { + return (ORKWaitStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + + [_waitStepView removeFromSuperview]; + + if (self.step && [self isViewLoaded]) { + if (!_waitStepView) { + // Collect the text content from step during the when _waitStepView hasn't been initialized. + _updatedText = [self waitStep].text; + } + + _waitStepView = [[ORKWaitStepView alloc] initWithIndicatorType:[self waitStep].indicatorType]; + _waitStepView.frame = self.view.bounds; + _waitStepView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + [self.view addSubview:_waitStepView]; + [self setupNavigationFooterView]; + [self setupConstraints]; + _waitStepView.stepTopContentImage = self.step.image; + _waitStepView.titleIconImage = self.step.iconImage; + _waitStepView.stepTitle = self.step.title; + _waitStepView.stepText = _updatedText; + _waitStepView.stepDetailText = self.step.detailText; + _waitStepView.stepHeaderTextAlignment = self.step.headerTextAlignment; + _waitStepView.bodyItems = self.step.bodyItems; + _waitStepView.stepTopContentImageContentMode = self.step.imageContentMode; + } +} + +- (void)setupNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = _waitStepView.navigationFooterView; + _navigationFooterView.neverHasContinueButton = YES; + } +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _constraints = nil; + _waitStepView.translatesAutoresizingMaskIntoConstraints = NO; + + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_waitStepView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_waitStepView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_waitStepView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_waitStepView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; +} + +- (void)setProgress:(CGFloat)progress animated:(BOOL)animated { + [_waitStepView.progressView setProgress:progress animated:animated]; +} + +- (void)updateText:(NSString *)text { + _updatedText = text; + [self stepDidChange]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.h new file mode 100755 index 0000000..ddf4a66 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.h @@ -0,0 +1,73 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKWebViewStep` class represents a step that displays an embedded webview. + + This may be useful in cases where extreme custom styling is necessary, or an instrument + with specific requirements does not yet have a native implementation. + + In order to proceed to the next step from inside the webviewstep, you must execute this + line of javascript when the user should proceed: + + window.webkit.messageHandlers.ResearchKit.postMessage(answer); + + Where "answer" is the string answer that will be captured in the WebViewStepResult. + A string answer is required or the user will be unable to proceed. + */ +ORK_CLASS_AVAILABLE +@interface ORKWebViewStep : ORKStep + +/** + Returns a new web view step that includes the specified identifier and will display the specified html. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param html The html to be displayed in the webview. + */ ++ (instancetype)webViewStepWithIdentifier:(NSString *)identifier + html:(NSString *)html; + +/** + Embedded html used for displaying the webview. + */ +@property (nonatomic, copy, nullable) NSString *html; + +@property (nonatomic, copy, nullable) NSString *customCSS; + +@property (nonatomic) BOOL showSignatureAfterContent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.m new file mode 100755 index 0000000..95d4bae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStep.m @@ -0,0 +1,97 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKWebViewStep.h" +#import "ORKWebViewStepViewController.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKWebViewStep + ++ (Class)stepViewControllerClass { + return [ORKWebViewStepViewController class]; +} + ++ (instancetype)webViewStepWithIdentifier:(NSString *)identifier + html:(NSString *)html { + ORKWebViewStep *step = [[ORKWebViewStep alloc] initWithIdentifier:identifier]; + step.html = html; + return step; +} + +- (void)validateParameters { + [super validateParameters]; + + if (self.html == nil) { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:@"WebViewStep requires html property." + userInfo:nil]; + } +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, html, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, customCSS, NSString); + ORK_DECODE_BOOL(aDecoder, showSignatureAfterContent); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, html); + ORK_ENCODE_OBJ(aCoder, customCSS); + ORK_ENCODE_BOOL(aCoder, showSignatureAfterContent); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKWebViewStep *step = [super copyWithZone:zone]; + step.html = self.html; + step.customCSS = self.customCSS; + step.showSignatureAfterContent = self.showSignatureAfterContent; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + [self.html isEqual:castObject.html] && + [self.customCSS isEqual:castObject.customCSS] && + (self.showSignatureAfterContent == castObject.showSignatureAfterContent)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.h new file mode 100755 index 0000000..1dea4c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +/** + The `ORKWebViewStepResult` class represents the result of a web view step (`ORKWebViewStep`). + + A web view result is produced by the task view controller when it presents a web view step. + + */ +ORK_CLASS_AVAILABLE +@interface ORKWebViewStepResult : ORKResult + +/** + The answer produced by the webview. + */ +@property (nonatomic, nullable) NSString* result; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.m new file mode 100755 index 0000000..126c398 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepResult.m @@ -0,0 +1,72 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKWebViewStepResult.h" +#import "ORKResult_Private.h" +#import "ORKHelpers_Internal.h" + +@implementation ORKWebViewStepResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, result); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, result, NSString); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (NSUInteger)hash { + return super.hash ^ [self.result hash]; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + [self.result isEqualToString:castObject.result]); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKWebViewStepResult *result = [super copyWithZone:zone]; + result->_result = self.result; + return result; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.h new file mode 100755 index 0000000..2d99139 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import UIKit; +@import WebKit; +#import "ORKStepViewController.h" +#import "ORKSignatureView.h" + +NS_ASSUME_NONNULL_BEGIN + +@class ORKWebViewStepViewController; + +@protocol ORKWebViewStepDelegate + +- (WKNavigationActionPolicy)handleLinkNavigationWithURL:(NSURL *)url; +- (void)didFinishLoadingWebStepViewController:(ORKWebViewStepViewController *)webStepViewController; + +@end + +/** + The `ORKWebViewStepViewController` class is a step view controller subclass + used to manage a web view step (`ORKWebViewStep`). + + You should not need to instantiate a web view step view controller directly. Instead, include + a web view step in a task, and present a task view controller for that task. + */ + +ORK_CLASS_AVAILABLE +@interface ORKWebViewStepViewController : ORKStepViewController + +@property (nonatomic, weak, nullable) id webViewDelegate; + +- (void)startPreload; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.m new file mode 100755 index 0000000..4c2c786 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWebViewStepViewController.m @@ -0,0 +1,489 @@ +/* + Copyright (c) 2017, CareEvolution, Inc. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "ORKWebViewStepViewController.h" +#import "ORKStepViewController_Internal.h" +#import "ORKWebViewStep.h" + +#import "ORKResult_Private.h" +#import "ORKCollectionResult_Private.h" +#import "ORKWebViewStepResult.h" +#import "ORKNavigationContainerView_Internal.h" +#import "ORKSkin.h" +#import "ORKHelpers_Internal.h" +#import "ORKSignatureResult_Private.h" + +static const CGFloat ORKSignatureTopPadding = 37.0; +static const CGFloat ORKSignatureToClearPadding = 15.0; + +@implementation ORKWebViewStepViewController { + UIScrollView *_scrollView; + WKWebView *_webView; + NSString *_result; + NSMutableArray *_constraints; + + ORKSignatureView *_signatureView; + UIButton *_clearButton; + + CGFloat _leftRightPadding; +} + +- (ORKWebViewStep *)webViewStep { + return (ORKWebViewStep *)self.step; +} + +- (void)stepDidChange { + + _result = nil; + [_webView removeFromSuperview]; + _webView = nil; + + [_scrollView removeFromSuperview]; + _scrollView = nil; + + if (self.step && [self isViewLoaded]) { + + _scrollView = [[UIScrollView alloc] init]; + _scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + [_scrollView setDelegate:self]; + [self.view addSubview:_scrollView]; + + if ([self webViewStep].showSignatureAfterContent) { + _signatureView = [[ORKSignatureView alloc] initWithoutDefaultWidth]; + _signatureView.delegate = self; + [_scrollView addSubview:_signatureView]; + + _clearButton = [[ORKTextButton alloc] init]; + [_clearButton.titleLabel setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]]; + [_clearButton setTitle:ORKLocalizedString(@"BUTTON_CLEAR_SIGNATURE", nil) forState:UIControlStateNormal]; + [_clearButton addTarget:self action:@selector(clearSignature) forControlEvents:UIControlEventTouchUpInside]; + [_scrollView addSubview:_clearButton]; + } + + WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; + config.allowsInlineMediaPlayback = true; + if ([config respondsToSelector:@selector(mediaTypesRequiringUserActionForPlayback)]) { + config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; + } + + WKUserContentController *controller = [[WKUserContentController alloc] init]; + [controller addScriptMessageHandler:self name:@"ResearchKit"]; + config.userContentController = controller; + + _leftRightPadding = self.step.useExtendedPadding ? ORKStepContainerExtendedLeftRightPaddingForWindow(self.view.window) : ORKStepContainerLeftRightPaddingForWindow(self.view.window); + + UIColor *backgroundColor; + UIColor *textColor; + if (@available(iOS 13.0, *)) { + backgroundColor = [UIColor systemBackgroundColor]; + textColor = [UIColor labelColor]; + } else { + backgroundColor = [UIColor whiteColor]; + textColor = [UIColor blackColor]; + } + + NSString *backgroundColorString = [self hexStringForColor:backgroundColor]; + NSString *textColorString = [self hexStringForColor:textColor]; + + NSString *css = [NSString stringWithFormat:@"body { margin: 0px; font-size: 17px; font-family: \"-apple-system\"; padding-left: %fpx; padding-right: %fpx; background-color: %@; color: %@; }", + _leftRightPadding, + _leftRightPadding, + backgroundColorString, + textColorString]; + + if ([self webViewStep].customCSS != nil) { + css = [self webViewStep].customCSS; + } + + NSString *js = @"var style = document.createElement('style'); style.innerHTML = '%@'; document.head.appendChild(style);"; + NSString *formattedString = [NSString stringWithFormat:js, css]; + WKUserScript *userScript = [[WKUserScript alloc] initWithSource:formattedString injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:true]; + [controller addUserScript:userScript]; + + _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; + _webView.autoresizingMask = UIViewAutoresizingFlexibleHeight; + _webView.navigationDelegate = self; + _webView.scrollView.scrollEnabled = NO; + _webView.scrollView.delegate = self; + + [_scrollView addSubview:_webView]; + [self setupNavigationFooterView]; + [self setupConstraints]; + [_webView loadHTMLString:[self webViewStep].html baseURL:nil]; + } +} + +- (void)setupNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = [ORKNavigationContainerView new]; + [_navigationFooterView removeStyling]; + } + + _navigationFooterView.continueButtonItem = self.continueButtonItem; + _navigationFooterView.continueEnabled = YES; + [_navigationFooterView updateContinueAndSkipEnabled]; + [_navigationFooterView setUseExtendedPadding:[self.step useExtendedPadding]]; + + if ([self webViewStep].showSignatureAfterContent) { + _navigationFooterView.continueEnabled = NO; + } + + if ([self webViewStep].showSignatureAfterContent) { + [_scrollView addSubview:_navigationFooterView]; + } else { + [self.view addSubview:_navigationFooterView]; + } +} + +- (void)setupConstraints { + + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + + UIView *viewForiPad = [self viewForiPadLayoutConstraints]; + + _constraints = nil; + _webView.translatesAutoresizingMaskIntoConstraints = NO; + _navigationFooterView.translatesAutoresizingMaskIntoConstraints = NO; + _scrollView.translatesAutoresizingMaskIntoConstraints = NO; + _signatureView.translatesAutoresizingMaskIntoConstraints = NO; + _clearButton.translatesAutoresizingMaskIntoConstraints = NO; + + _constraints = [[NSMutableArray alloc] initWithArray:@[ + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_scrollView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + + [NSLayoutConstraint constraintWithItem:_webView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_webView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_webView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0] + ]]; + + if ([self webViewStep].showSignatureAfterContent) { + [_constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_signatureView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_webView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:ORKSignatureTopPadding], + [NSLayoutConstraint constraintWithItem:_signatureView + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_signatureView + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_clearButton + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_signatureView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:ORKSignatureToClearPadding], + [NSLayoutConstraint constraintWithItem:_clearButton + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeading + multiplier:1.0 + constant:_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_clearButton + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTrailing + multiplier:1.0 + constant:-_leftRightPadding], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_clearButton + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:ORKSignatureTopPadding], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_scrollView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + ]]; + } else { + [_constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_webView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:_scrollView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_navigationFooterView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:viewForiPad ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + ]]; + } + + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; +} + +- (void)scrollViewDidZoom:(UIScrollView *)scrollView { + _webView.scrollView.contentOffset = CGPointZero; +} + +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view { + // To prevent zooming + scrollView.pinchGestureRecognizer.enabled = NO; +} + +- (void)viewDidLayoutSubviews { + [super viewDidLayoutSubviews]; + + if (![self webViewStep].showSignatureAfterContent) { + [_scrollView setContentInset:UIEdgeInsetsMake(0, 0, _navigationFooterView.frame.size.height, 0)]; + } else { + [_scrollView setContentInset:UIEdgeInsetsZero]; + } +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)startPreload { + [self.view layoutSubviews]; + [self stepDidChange]; +} + +- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message +{ + if ([message.body isKindOfClass:[NSString class]]){ + _result = (NSString *)message.body; + [self goForward]; + } +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + + if (parentResult) { + ORKWebViewStepResult *childResult = [[ORKWebViewStepResult alloc] initWithIdentifier:self.step.identifier]; + childResult.result = _result; + childResult.endDate = parentResult.endDate; + childResult.userInfo = @{@"html": [self webViewStep].html}; + parentResult.results = [parentResult.results arrayByAddingObject:childResult] ? : @[childResult]; + + if ([self webViewStep].showSignatureAfterContent && _signatureView.signatureExists) { + ORKSignatureResult *signatureResult = [[ORKSignatureResult alloc] initWithSignatureImage:_signatureView.signatureImage signaturePath:_signatureView.signaturePath]; + parentResult.results = [parentResult.results arrayByAddingObject:signatureResult] ? : @[signatureResult]; + } + } + return parentResult; +} + +// MARK: WKWebViewDelegate + +- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation { + [UIApplication sharedApplication].networkActivityIndicatorVisible = true; +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation { + [webView evaluateJavaScript:@"document.readyState" completionHandler:^(id complete, NSError *readyError) { + if (complete != nil) { + [webView evaluateJavaScript:@"document.body.scrollHeight" completionHandler:^(id result, NSError *error) { + if (result != nil) { + NSString *resultString = [NSString stringWithFormat:@"%@", result]; + CGFloat height = [resultString floatValue]; + [_webView.heightAnchor constraintEqualToConstant:height].active = YES; + } + + if (_webViewDelegate != nil && [_webViewDelegate respondsToSelector:@selector(didFinishLoadingWebStepViewController:)]) { + [_webViewDelegate didFinishLoadingWebStepViewController:self]; + } + }]; + } else { + if (_webViewDelegate != nil && [_webViewDelegate respondsToSelector:@selector(didFinishLoadingWebStepViewController:)]) { + [_webViewDelegate didFinishLoadingWebStepViewController:self]; + } + } + }]; + + [UIApplication sharedApplication].networkActivityIndicatorVisible = false; +} + +- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (navigationAction.navigationType == WKNavigationTypeLinkActivated) { + if (_webViewDelegate != nil && [_webViewDelegate respondsToSelector:@selector(handleLinkNavigationWithURL:)]) { + decisionHandler([_webViewDelegate handleLinkNavigationWithURL:[navigationAction.request mainDocumentURL]]); + return; + } + } + + decisionHandler(WKNavigationActionPolicyAllow); +} + +// MARK: UIScrollViewDelegate + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + BOOL enabled = [self shouldEnableSignatureView] && scrollView.isDecelerating; + [_signatureView setEnabled:enabled]; + + if ([_scrollView.panGestureRecognizer translationInView:_scrollView.superview].y > 0) { + // Scrolling upward + [_signatureView cancelAutoScrollTimer]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + [_signatureView setEnabled:[self shouldEnableSignatureView]]; +} + +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { + [_signatureView setEnabled:[self shouldEnableSignatureView]]; +} + +- (BOOL)shouldEnableSignatureView { + CGFloat bottomOfSignature = _signatureView.frame.size.height + _signatureView.frame.origin.y; + CGFloat signaturePosition = _scrollView.contentOffset.y + _scrollView.frame.size.height; + return (bottomOfSignature <= signaturePosition); +} + +// MARK: Signature + +- (void)clearSignature { + [_signatureView clear]; + _navigationFooterView.continueEnabled = NO; +} + +- (void)signatureViewDidEditImage:(nonnull ORKSignatureView *)signatureView { + _navigationFooterView.continueEnabled = YES; +} + +- (void)signatureViewDidEndEditingWithTimeInterval { + CGPoint bottom = CGPointMake(0, _scrollView.contentSize.height - _scrollView.bounds.size.height + _scrollView.contentInset.bottom); + [_scrollView setContentOffset:bottom animated:YES]; +} + +// MARK: Color + +- (NSString *)hexStringForColor:(UIColor *)color { + const CGFloat *components = CGColorGetComponents(color.CGColor); + size_t count = CGColorGetNumberOfComponents(color.CGColor); + + CGFloat r = components[0]; + + if (count == 2) { + return [NSString stringWithFormat:@"#%02lX%02lX%02lX", lroundf(r * 255), lroundf(r * 255), lroundf(r * 255)]; + } + + CGFloat g = components[1]; + CGFloat b = components[2]; + + return [NSString stringWithFormat:@"#%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255)]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.h new file mode 100755 index 0000000..ac7264c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.h @@ -0,0 +1,42 @@ +/* + Copyright (c) 2017, Nino Guba. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKWeightPicker : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.m new file mode 100755 index 0000000..ec8ad55 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/ORKWeightPicker.m @@ -0,0 +1,382 @@ +/* + Copyright (c) 2017, Nino Guba. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKWeightPicker.h" +#import "ORKResult_Private.h" +#import "ORKAnswerFormat_Internal.h" +#import "ORKAccessibilityFunctions.h" + + +@interface ORKWeightPicker () + +@end + +static const CGFloat PickerSpacerHeight = 15.0; +static const CGFloat PickerMinimumHeight = 34.0; + +@implementation ORKWeightPicker { + UIPickerView *_pickerView; + ORKWeightAnswerFormat *_answerFormat; + id _answer; + __weak id _pickerDelegate; + NSArray *_majorValues; + NSArray *_minorValues; + double _canonicalMaximumValue; + double _canonicalMinimumValue; +} + +@synthesize pickerDelegate = _pickerDelegate; + +- (instancetype)initWithAnswerFormat:(ORKWeightAnswerFormat *)answerFormat answer:(id)answer pickerDelegate:(id)delegate { + self = [super init]; + if (self) { + NSAssert([answerFormat isKindOfClass:[ORKWeightAnswerFormat class]], @"answerFormat should be ORKWeightAnswerFormat"); + + // Take into account locale changes so unit string can be updated + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(currentLocaleDidChange:) + name:NSCurrentLocaleDidChangeNotification object:nil]; + + _answerFormat = answerFormat; + _pickerDelegate = delegate; + self.answer = answer; + + _canonicalMaximumValue = ORKDoubleDefaultValue; + _canonicalMinimumValue = ORKDoubleDefaultValue; + + if (_answerFormat.useMetricSystem) { + _majorValues = [self kilogramValues]; + } else { + _majorValues = [self poundValues]; + } + + if (_answerFormat.numericPrecision == ORKNumericPrecisionHigh) { + _minorValues = [self _minorValues]; + } + } + return self; +} + +- (UIView *)pickerView { + if (_pickerView == nil) { + _pickerView = [[UIPickerView alloc] init]; + _pickerView.dataSource = self; + _pickerView.delegate = self; + [self setAnswer:_answer]; + } + return _pickerView; +} + +- (void)setAnswer:(id)answer { + _answer = answer; + + if (ORKIsAnswerEmpty(answer)) { + answer = [self defaultAnswerValue]; + } + + if (_answerFormat.useMetricSystem) { + if (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) { + NSUInteger index = [_majorValues indexOfObject:@((NSInteger)((NSNumber *)answer).doubleValue)]; + if (index == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:index inComponent:0 animated:NO]; + } else { + double whole, fraction; + ORKKilogramsToWholeAndFraction(((NSNumber *)answer).doubleValue, &whole, &fraction); + NSUInteger wholeIndex = [_majorValues indexOfObject:@((NSInteger)whole)]; + NSUInteger fractionIndex = [_minorValues indexOfObject:@((NSInteger)fraction)]; + if (wholeIndex == NSNotFound || fractionIndex == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:wholeIndex inComponent:0 animated:NO]; + [_pickerView selectRow:fractionIndex inComponent:1 animated:NO]; + [_pickerView selectRow:0 inComponent:2 animated:NO]; + } + } else { + if (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) { + double pounds = ORKKilogramsToPounds(((NSNumber *)answer).doubleValue); + NSUInteger poundsIndex = [_majorValues indexOfObject:@((NSInteger)pounds)]; + if (poundsIndex == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:poundsIndex inComponent:0 animated:NO]; + } else { + double pounds, ounces; + ORKKilogramsToPoundsAndOunces(((NSNumber *)answer).doubleValue, £s, &ounces); + NSUInteger poundsIndex = [_majorValues indexOfObject:@((NSInteger)pounds)]; + NSUInteger ouncesIndex = [_minorValues indexOfObject:@((NSInteger)ounces)]; + if (poundsIndex == NSNotFound || ouncesIndex == NSNotFound) { + [self setAnswer:[self defaultAnswerValue]]; + return; + } + [_pickerView selectRow:poundsIndex inComponent:0 animated:NO]; + [_pickerView selectRow:ouncesIndex inComponent:1 animated:NO]; + } + } +} + +- (id)answer { + return _answer; +} + +- (NSNumber *)defaultAnswerValue { + double defaultValue = ORKDoubleDefaultValue; + if (_answerFormat.defaultValue == ORKDoubleDefaultValue) { + if (_answerFormat.useMetricSystem) { + defaultValue = 60.00; // Default metric weight: 60 kg + } else { + defaultValue = 60.33; // Default USC weight: 133 lbs + } + } else { + if (_answerFormat.useMetricSystem) { + defaultValue = _answerFormat.defaultValue; + } else { + defaultValue = ORKPoundsToKilograms(_answerFormat.defaultValue); // Convert to kg + } + } + // Ensure default value is within bounds + if ((_canonicalMinimumValue != ORKDoubleDefaultValue) && (defaultValue < _canonicalMinimumValue)) { + defaultValue = _canonicalMinimumValue; + } else if ((_canonicalMaximumValue != ORKDoubleDefaultValue) && (defaultValue > _canonicalMaximumValue)) { + defaultValue = _canonicalMaximumValue; + } + + return @(defaultValue); +} + +- (NSNumber *)selectedAnswerValue { + NSNumber *answer = nil; + if (_answerFormat.useMetricSystem) { + NSInteger wholeRow = [_pickerView selectedRowInComponent:0]; + NSNumber *whole = _majorValues[wholeRow]; + if (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) { + answer = @( whole.doubleValue ); + } else { + NSInteger fractionRow = [_pickerView selectedRowInComponent:1]; + NSNumber *fraction = _minorValues[fractionRow]; + answer = @( ORKWholeAndFractionToKilograms(whole.doubleValue, fraction.doubleValue) ); + } + } else { + NSInteger poundsRow = [_pickerView selectedRowInComponent:0]; + NSNumber *pounds = _majorValues[poundsRow]; + if (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) { + answer = @( ORKPoundsToKilograms(pounds.doubleValue) ); + } else { + NSInteger ouncesRow = [_pickerView selectedRowInComponent:1]; + NSNumber *ounces = _minorValues[ouncesRow]; + answer = @( ORKPoundsAndOuncesToKilograms(pounds.doubleValue, ounces.doubleValue) ); + } + } + + return answer; +} + +- (NSString *)selectedLabelText { + return [_answerFormat stringForAnswer:_answer]; +} + +- (void)pickerWillAppear { + // Report current value, since ORKWeightPicker always has a value + [self pickerView]; + [self valueDidChange:self]; + [self accessibilityFocusOnPickerElement]; +} + +- (void)valueDidChange:(id)sender { + _answer = [self selectedAnswerValue]; + if ([self.pickerDelegate respondsToSelector:@selector(picker:answerDidChangeTo:)]) { + [self.pickerDelegate picker:self answerDidChangeTo:_answer]; + } +} + +#pragma mark - Accessibility + +- (void)accessibilityFocusOnPickerElement { + if (UIAccessibilityIsVoiceOverRunning()) { + ORKAccessibilityPerformBlockAfterDelay(0.75, ^{ + NSArray *axElements = [self.pickerView accessibilityElements]; + if ([axElements count] > 0) { + UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, [axElements objectAtIndex:0]); + } + }); + } +} + +#pragma mark - UIPickerViewDataSource + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) ? 1 : (_answerFormat.useMetricSystem ? 3 : 2); +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + NSInteger numberOfRows = 0; + if (component == 0) { + numberOfRows = _majorValues.count; + } else if (component == 1) { + numberOfRows = _minorValues.count; + } else { + numberOfRows = 1; + } + return numberOfRows; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + NSString *title = nil; + if (_answerFormat.useMetricSystem) { + if (component == 0) { + if (_answerFormat.numericPrecision != ORKNumericPrecisionHigh) { + title = [NSString stringWithFormat:@"%@ %@", _majorValues[row], ORKLocalizedString(@"MEASURING_UNIT_KG", nil)]; + } else { + title = [NSString stringWithFormat:@"%@", _majorValues[row]]; + } + } else if (component == 1) { + NSNumberFormatter *formatter = ORKDecimalNumberFormatter(); + formatter.minimumIntegerDigits = 2; + formatter.maximumFractionDigits = 0; + title = [NSString stringWithFormat:@".%@", [formatter stringFromNumber:_minorValues[row]]]; + } else if (component == 2) { + title = ORKLocalizedString(@"MEASURING_UNIT_KG", nil); + } + } else { + if (component == 0) { + title = [NSString stringWithFormat:@"%@ %@", _majorValues[row], ORKLocalizedString(@"MEASURING_UNIT_LB", nil)]; + } else { + title = [NSString stringWithFormat:@"%@ %@", _minorValues[row], ORKLocalizedString(@"MEASURING_UNIT_OZ", nil)]; + } + } + return title; +} + +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view +{ + UILabel* valueLabel = (UILabel*)view; + if (!valueLabel) + { + valueLabel = [[UILabel alloc] init]; + [valueLabel setFont:[self defaultFont]]; + [valueLabel setTextAlignment:NSTextAlignmentCenter]; + } + valueLabel.text = [self pickerView:pickerView titleForRow:row forComponent:component]; + return valueLabel; +} + +- (UIFont *)defaultFont { + UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody]; + return [UIFont systemFontOfSize:((NSNumber *)[descriptor objectForKey:UIFontDescriptorSizeAttribute]).doubleValue + 2.0]; +} + +- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component { + UIFont *font = [self defaultFont]; + CGFloat height = font.pointSize + PickerSpacerHeight; + return (height < PickerMinimumHeight ? PickerMinimumHeight : height); +} + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + [self valueDidChange:self]; +} + +- (NSArray *)kilogramValues { + NSArray *wholeValues = nil; + NSMutableArray *mutableWholeValues = [[NSMutableArray alloc] init]; + + double minimumValue = 0; + double maximumValue = 657; + if ((_answerFormat.minimumValue != ORKDoubleDefaultValue) && (_answerFormat.minimumValue <= maximumValue)) { + minimumValue = _answerFormat.minimumValue; + } + if ((_answerFormat.maximumValue != ORKDoubleDefaultValue) && (_answerFormat.maximumValue >= minimumValue)) { + maximumValue = _answerFormat.maximumValue; + } + _canonicalMinimumValue = minimumValue; + _canonicalMaximumValue = maximumValue; + + for (NSInteger i = minimumValue; i <= maximumValue; i++) { + [mutableWholeValues addObject:@(i)]; + if (_answerFormat.numericPrecision == ORKNumericPrecisionDefault) { + double preciseValue = i + 0.5; + [mutableWholeValues addObject:@(preciseValue)]; + } + } + wholeValues = [mutableWholeValues copy]; + return wholeValues; +} + +- (NSArray *)poundValues { + NSArray *wholeValues = nil; + NSMutableArray *mutableWholeValues = [[NSMutableArray alloc] init]; + + double minimumValue = 0; + double maximumValue = 1450; + if ((_answerFormat.minimumValue != ORKDoubleDefaultValue) && (_answerFormat.minimumValue <= maximumValue)) { + minimumValue = _answerFormat.minimumValue; + } + if ((_answerFormat.maximumValue != ORKDoubleDefaultValue) && (_answerFormat.maximumValue >= minimumValue)) { + maximumValue = _answerFormat.maximumValue; + } + _canonicalMinimumValue = ORKPoundsToKilograms(minimumValue); // Convert to kg + _canonicalMaximumValue = ORKPoundsToKilograms(maximumValue); // Convert to kg + + for (NSInteger i = minimumValue; i <= maximumValue; i++) { + [mutableWholeValues addObject:[NSNumber numberWithInteger:i]]; + } + wholeValues = [mutableWholeValues copy]; + return wholeValues; +} + +- (NSArray *)_minorValues { + NSArray *wholeValues = nil; + NSMutableArray *mutableWholeValues = [[NSMutableArray alloc] init]; + + NSInteger maximumValue = 99; + if (!_answerFormat.useMetricSystem) { + maximumValue = 15; + } + for (NSInteger i = 0; i <= maximumValue; i++) { + [mutableWholeValues addObject:@(i)]; + } + wholeValues = [mutableWholeValues copy]; + return wholeValues; +} + +- (void)currentLocaleDidChange:(NSNotification *)notification { + [_pickerView reloadAllComponents]; + [self setAnswer:[self defaultAnswerValue]]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.h new file mode 100755 index 0000000..2e44e86 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface UIBarButtonItem (ORKBarButtonItem) + ++ (instancetype)ork_backBarButtonItemWithTarget:(nullable id)target action:(nullable SEL)selector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.m new file mode 100755 index 0000000..3b8658b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIBarButtonItem+ORKBarButtonItem.m @@ -0,0 +1,78 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "UIBarButtonItem+ORKBarButtonItem.h" + +#import "ORKHelpers_Internal.h" + + +@implementation UIBarButtonItem (ORKBarButtonItem) + ++ (UIBarButtonItem *)ork_backBarButtonItemWithTarget:(id)target action:(SEL)selector { + + // Use SFSymbols for the back button on iOS 13+ + if (@available(iOS 13.0, *)) { + NSString *imageName = @"chevron.left"; + if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft ) { + imageName = @"chevron.right"; + } + + UIImage *image = [UIImage systemImageNamed:imageName]; + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:image + landscapeImagePhone:image + style:UIBarButtonItemStyleDone + target:target + action:selector]; + item.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + return item; + } + + // Use assets catalog below iOS 13 + NSString *regularImageName = @"arrowLeft"; + NSString *landscapeImageName = @"arrowLeftLandscape"; + + if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft ) { + regularImageName = @"arrowRight"; + landscapeImageName = @"arrowRightLandscape"; + } + + UIImage *image = [UIImage imageNamed:regularImageName inBundle:ORKBundle() compatibleWithTraitCollection:nil]; + UIImage *landscapeImage = [UIImage imageNamed:landscapeImageName inBundle:ORKBundle() compatibleWithTraitCollection:nil]; + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:image + landscapeImagePhone:landscapeImage + style:UIBarButtonItemStyleDone + target:target + action:selector]; + item.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + return item; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.h new file mode 100755 index 0000000..d499f4d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2015, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +@interface UIImage (ResearchKit) + +- (UIImage *)ork_flippedImage:(UIImageOrientation)orientation; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.m new file mode 100755 index 0000000..9f5d1e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIImage+ResearchKit.m @@ -0,0 +1,119 @@ +/* + Copyright (c) 2015, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "UIImage+ResearchKit.h" + + +@implementation UIImage (ResearchKit) + +- (UIImage *)ork_flippedImage:(UIImageOrientation)orientation { + + if (self.images.count > 0) { + NSMutableArray *images = [self.images mutableCopy]; + [images enumerateObjectsUsingBlock:^(UIImage * _Nonnull image, NSUInteger idx, BOOL * _Nonnull stop __unused) { + [images replaceObjectAtIndex:idx + withObject:[image ork_flippedImage:orientation]]; + }]; + return [UIImage animatedImageWithImages:images duration:self.duration]; + } else { + // [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:orientation] doesn't seem + // to work with images that are vector PDF rather than PNG, so... + CGRect bounds = CGRectMake(0., 0., self.size.width, self.size.height); + CGAffineTransform transform = CGAffineTransformIdentity; + switch(orientation) { + case UIImageOrientationUp: { + transform = CGAffineTransformIdentity; + } break; + + case UIImageOrientationUpMirrored: { + transform = CGAffineTransformMakeTranslation(self.size.width, 0.); + transform = CGAffineTransformScale(transform, -1.0f, 1.0f); + } break; + + case UIImageOrientationDown: { + transform = CGAffineTransformMakeTranslation(self.size.width, self.size.height); + transform = CGAffineTransformRotate(transform, M_PI); + } break; + + case UIImageOrientationDownMirrored: { + transform = CGAffineTransformMakeTranslation (0., self.size.height); + transform = CGAffineTransformScale(transform, 1.0f, -1.0f); + } break; + + case UIImageOrientationLeftMirrored: { + CGFloat boundHeight = bounds.size.height; + bounds.size.height = bounds.size.width; + bounds.size.width = boundHeight; + transform = CGAffineTransformMakeTranslation (self.size.height, self.size.width); + transform = CGAffineTransformScale(transform, -1.0f, 1.0f); + transform = CGAffineTransformRotate(transform, 3.0f * M_PI/ 2.0f); + } break; + + case UIImageOrientationLeft: { + CGFloat boundHeight = bounds.size.height; + bounds.size.height = bounds.size.width; + bounds.size.width = boundHeight; + transform = CGAffineTransformMakeTranslation (0.0f, self.size.width); + transform = CGAffineTransformRotate(transform, 3.0f * M_PI / 2.0f); + } break; + + case UIImageOrientationRightMirrored: { + CGFloat boundHeight = bounds.size.height; + bounds.size.height = bounds.size.width; + bounds.size.width = boundHeight; + transform = CGAffineTransformMakeScale(-1.0f, 1.0f); + transform = CGAffineTransformRotate(transform, M_PI / 2.0f); + } break; + + case UIImageOrientationRight: { + CGFloat boundHeight = bounds.size.height; + bounds.size.height = bounds.size.width; + bounds.size.width = boundHeight; + transform = CGAffineTransformMakeTranslation(self.size.height, 0.0f); + transform = CGAffineTransformRotate(transform, M_PI / 2.0f); + } break; + } + + UIGraphicsBeginImageContext(self.size); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextConcatCTM(context, transform); + + [self drawInRect:CGRectMake(0.f, 0.f, self.size.width, self.size.height)]; + + UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return newImage; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.h new file mode 100755 index 0000000..1e17c38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface UIResponder (ORKFirstResponderAdditions) + +- (void)ork_updateCurrentFirstResponder:(nullable NSMutableArray *)sender; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.m new file mode 100755 index 0000000..1a4e5bd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Common/UIResponder+ResearchKit.m @@ -0,0 +1,42 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "UIResponder+ResearchKit.h" + + +@implementation UIResponder (ORKFirstResponderAdditions) + +- (void)ork_updateCurrentFirstResponder:(NSMutableArray *)sender { + + [sender addObject:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.fsh b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.fsh new file mode 100755 index 0000000..9cb63f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.fsh @@ -0,0 +1,52 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +varying highp vec2 texCoordVarying; +precision mediump float; + +uniform sampler2D SamplerY; +uniform sampler2D SamplerUV; +uniform mat3 colorConversionMatrix; +uniform lowp vec3 tintColor; + +void main() { + mediump vec3 yuv; + lowp vec3 rgb; + + // Subtract constants to map the video range start at 0 + yuv.x = (texture2D(SamplerY, texCoordVarying).r - (16.0 / 255.0)); + yuv.yz = (texture2D(SamplerUV, texCoordVarying).rg - vec2(0.5, 0.5)); + + rgb = colorConversionMatrix * yuv; + rgb = vec3(1, 1, 1) - ((vec3(1, 1, 1) - rgb) * (vec3(1, 1, 1) - tintColor)); + + gl_FragColor = vec4(rgb, 1); +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.vsh b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.vsh new file mode 100755 index 0000000..bff3c62 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/MovieTintShader.vsh @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +attribute vec4 position; +attribute vec2 texCoord; +uniform float preferredRotation; + +varying vec2 texCoordVarying; + +void main() { + mat4 rotationMatrix = mat4( cos(preferredRotation), -sin(preferredRotation), 0.0, 0.0, + sin(preferredRotation), cos(preferredRotation), 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0); + gl_Position = position * rotationMatrix; + texCoordVarying = texCoord; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.h new file mode 100755 index 0000000..f980216 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.h @@ -0,0 +1,176 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + +@class ORKHTMLPDFPageRenderer; + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentSection; +@class ORKConsentSectionFormatter; +@class ORKConsentSignature; +@class ORKConsentSignatureFormatter; +@class ORKHTMLPDFWriter; + +/** + The `ORKConsentDocument` class represents the content of an informed consent + document, which is a document that's used to obtain informed consent from participants + in a medical or other research study. The ResearchKit framework uses an `ORKConsentDocument` object + to provide content for visual consent steps (`ORKVisualConsentStep`) and for consent review steps (`ORKConsentReviewStep`). + + The `sections` of an `ORKConsentDocument` object are instances of `ORKConsentSection`. + When an `ORKConsentDocument` object is attached to an visual consent step, these + sections provide the content for the visual consent screens, and for the + Learn More pages that are accessible from them. When attached to an consent review step, + the sections can provide the content for the consent document to + be reviewed. + + If the consent document is simple, each section may be able to map to a visual consent screen. And in some cases, the formatting of the consent document may + be sufficiently simple that it can be presented using only section headers and + simple formatting. If your consent document uses simple formatting, you might be able to generate a document to sign by specifying the sections and the signatures. + In a case like this, you don't need to provide a value for the `htmlReviewContent` property, + and when the consent review step is completed, the signatures can be + placed into a copy of the document and a PDF can be generated. + + In more complex cases, the visual consent sections may bear little + relation to the formal consent document. In a situation like this, place the formal consent + document content in the `htmlReviewContent` property. Doing this overrides all content that would otherwise be generated from the consent + sections. + + The document should be in the user's language, and all the content of + the document should be appropriately localized. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentDocument : NSObject + +/// @name Properties + +/** + The document's title in a localized string. + + The title appears only in the generated PDF for review; it is not used in the + visual consent process. + */ +@property (nonatomic, copy, nullable) NSString *title; + +/// @name Visual consent sections + +/** + The sections to be in printed in the PDF file and or presented in the + visual consent sequence. + + All sections appear in the animated process, except for those sections of the + type `ORKConsentSectionTypeOnlyInDocument`. + + If the `htmlReviewContent` property is not set, this content is also used to + populate the document for review in the consent review step. + + The PDF file contains all sections. + */ +@property (nonatomic, copy, nullable) NSArray *sections; + +/// @name Signatures for consent review + +/** + The title to be rendered on the signature page of the generated PDF in a localized string. + + The title is ignored for visual consent. The title is also ignored if you supply a value for the `htmlReviewContent` property. + */ +@property (nonatomic, copy, nullable) NSString *signaturePageTitle; + +/** + The content to be rendered below the title on the signature page of the generated PDF in a localized string. + + The content is ignored for visual consent. The content is also ignored if you supply a value for the `htmlReviewContent` property. + */ +@property (nonatomic, copy, nullable) NSString *signaturePageContent; + +/** + The set of signatures that are required or prepopulated in the document. + + To add a signature to the document after consent review, the `signatures` array + needs to be modified to incorporate the new signature content prior to PDF + generation. For more information, see `[ORKConsentSignatureResult applyToDocument:]`. + */ +@property (nonatomic, copy, nullable) NSArray *signatures; + +/** + Adds a signature to the array of signatures. + + @param signature The signature object to add to the document. + */ +- (void)addSignature:(ORKConsentSignature *)signature; + +/// @name Alternative content provision + +/** + Override HTML content for review. + + Typically, the review content is generated from the values of the `sections` and `signatures` + properties. + + When this property is set, the review content is reproduced exactly as provided in the property + in the consent review step, and the `sections` and `signatures` properties + are ignored. + */ +@property (nonatomic, copy, nullable) NSString *htmlReviewContent; + +/// @name PDF generation + +/** + Writes the document's content into a PDF file. + + The PDF is generated in a form suitable for printing. This is done asynchronously, + so the PDF data is returned through a completion block. + + @param handler The handler block for generated PDF data. When successful, the returned + data represents a complete PDF document that represents the consent. + */ +- (void)makePDFWithCompletionHandler:(void (^)(NSData * _Nullable PDFData, NSError * _Nullable error))handler; + +/** + Writes the document's content into a PDF file using the specified renderer. + + The PDF is generated in a form suitable for printing. This is done asynchronously, + so the PDF data is returned through a completion block. + + @param renderer The PDF renderer. + @param handler The handler block for generated PDF data. When successful, the returned + data represents a complete PDF document that represents the consent. + */ +- (void)makeCustomPDFWithRenderer:(ORKHTMLPDFPageRenderer *)renderer + completionHandler:(void (^)(NSData * _Nullable PDFData, NSError * _Nullable error))handler; +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.m new file mode 100755 index 0000000..a636c4a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument.m @@ -0,0 +1,294 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Alex Basson. All rights reserved. + Copyright (c) 2017, Medable Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentDocument_Internal.h" + +#import "ORKBodyLabel.h" +#import "ORKHeadlineLabel.h" +#import "ORKSubheadlineLabel.h" + +#import "ORKConsentSection_Private.h" +#import "ORKConsentSectionFormatter.h" +#import "ORKConsentSignature.h" +#import "ORKConsentSignatureFormatter.h" +#import "ORKHTMLPDFWriter.h" + +#import "ORKHelpers_Internal.h" +#import "ORKErrors.h" + + +@implementation ORKConsentDocument { + NSMutableArray *_signatures; +} + +#pragma mark - Initializers + +- (instancetype)init { + return [self initWithHTMLPDFWriter:[[ORKHTMLPDFWriter alloc] init] + consentSectionFormatter:[[ORKConsentSectionFormatter alloc] init] + consentSignatureFormatter:[[ORKConsentSignatureFormatter alloc] init]]; +} + +- (instancetype)initWithHTMLPDFWriter:(ORKHTMLPDFWriter *)writer + consentSectionFormatter:(ORKConsentSectionFormatter *)sectionFormatter + consentSignatureFormatter:(ORKConsentSignatureFormatter *)signatureFormatter{ + if (self = [super init]) { + _writer = writer; + _sectionFormatter = sectionFormatter; + _signatureFormatter = signatureFormatter; + } + return self; +} + +#pragma mark - Accessors + +- (void)setSignatures:(NSArray *)signatures { + _signatures = [signatures mutableCopy]; +} + +- (NSArray *)signatures { + return [_signatures copy]; +} + +#pragma mark - Public + +- (void)addSignature:(ORKConsentSignature *)signature { + if (!_signatures) { + _signatures = [NSMutableArray array]; + } + [_signatures addObject:signature]; +} + +- (void)makePDFWithCompletionHandler:(void (^)(NSData *data, NSError *error))completionBlock { + [_writer writePDFFromHTML:[self htmlForMobile:NO title:nil detail:nil] + completionBlock:^(NSData *data, NSError *error) { + if (error) { + // Pass the webview error straight through. This is a pretty exceptional + // condition (can only happen if they pass us really invalid content). + completionBlock(nil, error); + } else { + completionBlock(data, nil); + } + }]; +} + +- (void)makeCustomPDFWithRenderer:(ORKHTMLPDFPageRenderer *)renderer completionHandler:(void (^)(NSData * _Nullable, NSError * _Nullable))completionBlock { + _writer.printRenderer = renderer; + return [_writer writePDFFromHTML:[self htmlForMobile:NO title:nil detail:nil] completionBlock:^(NSData *data, NSError *error) { + if (error) { + // Pass the webview error straight through. This is a pretty exceptional + // condition (can only happen if they pass us really invalid content). + completionBlock(nil, error); + } else { + completionBlock(data, nil); + } + _writer.printRenderer = nil; + }]; + +} + +#pragma mark - Private + +- (NSString *)mobileHTMLWithTitle:(NSString *)title detail:(NSString *)detail { + return [self htmlForMobile:YES title:title detail:detail]; +} + ++ (NSString *)cssStyleSheet:(BOOL)mobile { + NSMutableString *css = [@"@media print { .pagebreak { page-break-before: always; } }\n" mutableCopy]; + if (mobile) { + [css appendString:@".header { margin-top: 36px ; margin-bottom: 30px; text-align: center; }\n"]; + [css appendString:@"body { margin-left: 0px; margin-right: 0px; }\n"]; + + + CGFloat adjustment = [[ORKSubheadlineLabel defaultFont] pointSize] - 17.0; + NSArray *hPointSizes = @[ @([[ORKHeadlineLabel defaultFont] pointSize]), + @(24.0 + adjustment), + @(19.0 + adjustment), + @(17.0 + adjustment), + @(13.0 + adjustment), + @(11.0 + adjustment) ]; + + [css appendString:[NSString stringWithFormat:@"h1 { font-family: -apple-system-font ; font-weight: 300; font-size: %.0lf; }\n", + ((NSNumber *)hPointSizes[0]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"h2 { font-family: -apple-system-font ; font-weight: 300; font-size: %.0lf; text-align: left; margin-top: 2em; }\n", + ((NSNumber *)hPointSizes[1]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"h3 { font-family: -apple-system-font ; font-size: %.0lf; margin-top: 2em; }\n", + ((NSNumber *)hPointSizes[2]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"h4 { font-family: -apple-system-font ; font-size: %.0lf; margin-top: 2em; }\n", + ((NSNumber *)hPointSizes[3]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"h5 { font-family: -apple-system-font ; font-size: %.0lf; margin-top: 2em; }\n", + ((NSNumber *)hPointSizes[4]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"h6 { font-family: -apple-system-font ; font-size: %.0lf; margin-top: 2em; }\n", + ((NSNumber *)hPointSizes[5]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"body { font-family: -apple-system-font; font-size: %.0lf; }\n", + ((NSNumber *)hPointSizes[3]).floatValue]]; + [css appendString:[NSString stringWithFormat:@"p, blockquote, ul, fieldset, form, ol, dl, dir, { font-family: -apple-system-font; font-size: %.0lf; margin-top: -.5em; }\n", + ((NSNumber *)hPointSizes[3]).floatValue]]; + } else { + [css appendString:@"h1, h2 { text-align: center; }\n"]; + [css appendString:@"h2, h3 { margin-top: 3em; }\n"]; + [css appendString:@"body, p, h1, h2, h3 { font-family: Helvetica; }\n"]; + } + + [css appendFormat:@".col-1-3 { width: %@; float: left; padding-right: 20px; margin-top: 100px;}\n", mobile ? @"66.6%" : @"33.3%"]; + [css appendString:@".sigbox { position: relative; height: 100px; max-height:100px; display: inline-block; bottom: 10px }\n"]; + [css appendString:@".inbox { position: absolute; bottom:10px; top: 100%%; transform: translateY(-100%%); -webkit-transform: translateY(-100%%); }\n"]; + [css appendString:@".inboxImage { position: relative; bottom:60px; top: 100%%; transform: translateY(-100%%); -webkit-transform: translateY(-100%%); }\n"]; + [css appendString:@".grid:after { content: \"\"; display: table; clear: both; }\n"]; + [css appendString:@".border { -webkit-box-sizing: border-box; box-sizing: border-box; }\n"]; + + return css; +} + ++ (NSString *)wrapHTMLBody:(NSString *)body mobile:(BOOL)mobile { + NSMutableString *html = [NSMutableString string]; + + [html appendString:@""]; + [html appendString:body]; + [html appendString:@""]; + + return [html copy]; +} + +- (NSString *)htmlForMobile:(BOOL)mobile title:(NSString *)title detail:(NSString *)detail { + NSMutableString *body = [NSMutableString new]; + + // header + [body appendFormat:@"
"]; + if (title) { + [body appendFormat:@"

%@

", title]; + } + + if (detail) { + [body appendFormat:@"

%@

", detail]; + } + [body appendFormat:@"
"]; + + if (_htmlReviewContent) { + [body appendString:_htmlReviewContent]; + } else { + + // title + [body appendFormat:@"

%@

", _title ? : @""]; + + // scenes + for (ORKConsentSection *section in _sections) { + if (!section.omitFromDocument) { + [body appendFormat:@"%@", [_sectionFormatter HTMLForSection:section]]; + } + } + } + + if (!mobile) { + // page break + [body appendFormat:@"

%@

", _signaturePageTitle ? : @""]; + [body appendFormat:@"

%@

", _signaturePageContent ? : @""]; + + for (ORKConsentSignature *signature in self.signatures) { + [body appendFormat:@"%@", [_signatureFormatter HTMLForSignature:signature]]; + } + } + + return [[self class] wrapHTMLBody:body mobile:mobile]; +} + +#pragma mark - + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, title, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, signaturePageTitle, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, signaturePageContent, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, htmlReviewContent, NSString); + NSArray *signatures = (NSArray *)[aDecoder decodeObjectOfClass:[NSArray class] forKey:@"signatures"]; + _signatures = [signatures mutableCopy]; + ORK_DECODE_OBJ_ARRAY(aDecoder, sections, ORKConsentSection); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, title); + ORK_ENCODE_OBJ(aCoder, signaturePageTitle); + ORK_ENCODE_OBJ(aCoder, signaturePageContent); + ORK_ENCODE_OBJ(aCoder, signatures); + ORK_ENCODE_OBJ(aCoder, htmlReviewContent); + ORK_ENCODE_OBJ(aCoder, sections); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +#pragma mark - + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentDocument *doc = [[[self class] allocWithZone:zone] init]; + doc.title = _title; + doc.signaturePageTitle = _signaturePageTitle; + doc.signaturePageContent = _signaturePageContent; + doc.htmlReviewContent = _htmlReviewContent; + + // Deep copy the signatures + doc.signatures = ORKArrayCopyObjects(_signatures); + + // Deep copy the sections + doc.sections = ORKArrayCopyObjects(_sections); + + return doc; +} + +#pragma mark - + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.title, castObject.title) + && ORKEqualObjects(self.signaturePageTitle, castObject.signaturePageTitle) + && ORKEqualObjects(self.signaturePageContent, castObject.signaturePageContent) + && ORKEqualObjects(self.htmlReviewContent, castObject.htmlReviewContent) + && ORKEqualObjects(self.signatures, castObject.signatures) + && ORKEqualObjects(self.sections, castObject.sections)); +} + +- (NSUInteger)hash { + return _title.hash ^ _sections.hash; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Internal.h new file mode 100755 index 0000000..d2fc57f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Internal.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentDocument_Private.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKHTMLPDFWriter; +@class ORKConsentSectionFormatter; +@class ORKConsentSignatureFormatter; + +@interface ORKConsentDocument () + +@property (nonatomic, strong, nullable) ORKHTMLPDFWriter *writer; +@property (nonatomic, strong, nullable) ORKConsentSectionFormatter *sectionFormatter; +@property (nonatomic, strong, nullable) ORKConsentSignatureFormatter *signatureFormatter; + ++ (NSString *)wrapHTMLBody:(NSString *)body mobile:(BOOL)mobile; + +- (NSString *)mobileHTMLWithTitle:(nullable NSString *)title detail:(nullable NSString *)detail; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Private.h new file mode 100755 index 0000000..91eda1d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentDocument_Private.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKHTMLPDFWriter; +@class ORKConsentSectionFormatter; +@class ORKConsentSignatureFormatter; + +@interface ORKConsentDocument () + +/** + Initializer with ORKHTMLPDFWriter parameter. Allows for injecting mock dependency for the + purposes of isolated unit testing. + + @param writer The instance of the ORKHTMLPDFWriter upon which the class depends. + @param sectionFormatter An instance of ORKConsentSectionFormatter + @param signatureFormatter An instance of ORKConsentSignatureFormatter + */ +- (instancetype)initWithHTMLPDFWriter:(ORKHTMLPDFWriter *)writer + consentSectionFormatter:(ORKConsentSectionFormatter *)sectionFormatter + consentSignatureFormatter:(ORKConsentSignatureFormatter *)signatureFormatter; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.h new file mode 100755 index 0000000..6129c43 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKConsentLearnMoreViewController : UIViewController + +- (instancetype)initWithHTMLContent:(NSString *)content; +- (instancetype)initWithContentURL:(NSURL *)contentURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.m new file mode 100755 index 0000000..347fd31 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentLearnMoreViewController.m @@ -0,0 +1,134 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentLearnMoreViewController.h" + +#import "ORKConsentDocument_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" +#import + + +@interface ORKConsentLearnMoreViewController () + +@property (nonatomic, strong) WKWebView *webView; +@property (nonatomic, copy) NSString *content; +@property (nonatomic, copy) NSURL *contentURL; + +@end + + +@implementation ORKConsentLearnMoreViewController + +- (instancetype)initWithHTMLContent:(NSString *)content { + self = [super init]; + if (self) { + self.content = [ORKConsentDocument wrapHTMLBody:content mobile:YES]; + } + return self; +} + +- (instancetype)initWithContentURL:(NSURL *)contentURL { + self = [super init]; + if (self) { + self.contentURL = contentURL; + } + return self; +} + + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.view.backgroundColor = ORKColor(ORKBackgroundColorKey); + + WKWebViewConfiguration *webViewConfiguration = [WKWebViewConfiguration new]; + _webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:webViewConfiguration]; + + const CGFloat horizMargin = ORKStandardLeftMarginForTableViewCell(self.view); + _webView.backgroundColor = ORKColor(ORKBackgroundColorKey); + _webView.scrollView.backgroundColor = ORKColor(ORKBackgroundColorKey); + + _webView.clipsToBounds = NO; + _webView.scrollView.clipsToBounds = NO; + _webView.scrollView.scrollIndicatorInsets = (UIEdgeInsets){.left = -horizMargin, .right = -horizMargin}; + _webView.opaque = NO; // If opaque is set to YES, _webView shows a black right margin during transition when modally presented. This is an artifact due to disabling clipsToBounds to be able to show the scroll indicator outside the view. + + + _webView.navigationDelegate = self; + + if (_contentURL) { + [_webView loadRequest:[NSURLRequest requestWithURL:_contentURL]]; + } else { + [_webView loadHTMLString:self.content baseURL:ORKCreateRandomBaseURL()]; + } + + [self.view addSubview:_webView]; + + _webView.translatesAutoresizingMaskIntoConstraints = NO; + [self setUpConstraints]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)]; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_webView); + const CGFloat horizMargin = ORKStandardLeftMarginForTableViewCell(self.view); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-horizMargin-[_webView]-horizMargin-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"horizMargin": @(horizMargin) } + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_webView]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (IBAction)done:(id)sender { + [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)webView:(WKWebView *) __unused webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (navigationAction.navigationType != WKNavigationTypeOther) { + [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:^(BOOL __unused success) { + decisionHandler(WKNavigationActionPolicyCancel); + }]; + } else { + decisionHandler(WKNavigationActionPolicyAllow); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.h new file mode 100755 index 0000000..deadb54 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import WebKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentReviewController; + +@protocol ORKConsentReviewControllerDelegate + +- (void)consentReviewControllerDidAcknowledge:(ORKConsentReviewController *)consentReviewController; +- (void)consentReviewControllerDidCancel:(ORKConsentReviewController *)consentReviewController; + +@end + + +@interface ORKConsentReviewController : UIViewController + +- (instancetype)initWithHTML:(NSString *)html delegate:(id)delegate requiresScrollToBottom:(BOOL)requiresScrollToBottom; + +@property (nonatomic, strong, nullable) WKWebView *webView; + +@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem; + +@property (nonatomic, weak, nullable) id delegate; + +@property (nonatomic, strong, nullable) NSString *localizedReasonForConsent; + +- (void)setTextForiPadStepTitleLabel:(NSString *)text; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.m new file mode 100755 index 0000000..08fa6b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewController.m @@ -0,0 +1,253 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentReviewController.h" + +#import "ORKSignatureView.h" +#import "ORKVerticalContainerView_Internal.h" + +#import "ORKConsentDocument_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +static const CGFloat iPadStepTitleLabelFontSize = 50.0; +@interface ORKConsentReviewController () + +@end + + +@implementation ORKConsentReviewController { + UIToolbar *_toolbar; + NSString *_htmlString; + NSMutableArray *_variableConstraints; + UILabel *_iPadStepTitleLabel; + NSString *_iPadStepTitle; + UIBarButtonItem *_agreeButton; +} + +- (instancetype)initWithHTML:(NSString *)html delegate:(id)delegate requiresScrollToBottom:(BOOL)requiresScrollToBottom { + self = [super init]; + if (self) { + _htmlString = html; + _delegate = delegate; + + _agreeButton = [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_AGREE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(ack)]; + _agreeButton.enabled = !requiresScrollToBottom; + + self.toolbarItems = @[ + [[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"BUTTON_DISAGREE", nil) style:UIBarButtonItemStylePlain target:self action:@selector(cancel)], + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], + _agreeButton]; + } + return self; +} + +- (void)setTextForiPadStepTitleLabel:(NSString *)text { + _iPadStepTitle = text; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _toolbar = [[UIToolbar alloc] init]; + + _toolbar.items = self.toolbarItems; + + self.view.backgroundColor = ORKColor(ORKConsentBackgroundColorKey); + if (self.navigationController.navigationBar) { + [self.navigationController.navigationBar setBarTintColor:self.view.backgroundColor]; + } + + WKWebViewConfiguration *webViewConfiguration = [WKWebViewConfiguration new]; + _webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfiguration]; + [_webView loadHTMLString:_htmlString baseURL:ORKCreateRandomBaseURL()]; + _webView.backgroundColor = ORKColor(ORKConsentBackgroundColorKey); + _webView.scrollView.backgroundColor = ORKColor(ORKConsentBackgroundColorKey); + if (!_agreeButton.isEnabled) { + _webView.scrollView.delegate = self; + } + _webView.navigationDelegate = self; + [_webView setClipsToBounds:YES]; + _webView.translatesAutoresizingMaskIntoConstraints = NO; + _toolbar.translatesAutoresizingMaskIntoConstraints = NO; + _toolbar.translucent = YES; + + _webView.clipsToBounds = NO; + _webView.scrollView.clipsToBounds = NO; + [self updateLayoutMargins]; + + [self setupiPadStepTitleLabel]; + [self.view addSubview:_webView]; + [self.view addSubview:_toolbar]; + + [self setUpStaticConstraints]; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + if (!_cancelButtonItem) { + _cancelButtonItem = cancelButtonItem; + } +} + +- (void)setupiPadStepTitleLabel { + if (!_iPadStepTitleLabel) { + _iPadStepTitleLabel = [UILabel new]; + } + _iPadStepTitleLabel.numberOfLines = 0; + _iPadStepTitleLabel.textAlignment = NSTextAlignmentNatural; + [_iPadStepTitleLabel setFont:[UIFont systemFontOfSize:iPadStepTitleLabelFontSize weight:UIFontWeightBold]]; + _iPadStepTitleLabel.translatesAutoresizingMaskIntoConstraints = NO; + [_iPadStepTitleLabel setAdjustsFontSizeToFitWidth:YES]; + [_iPadStepTitleLabel setText:_iPadStepTitle]; + [self.view addSubview:_iPadStepTitleLabel]; +} + +- (void)updateLayoutMargins { + const CGFloat margin = ORKStandardHorizontalMarginForView(self.view); + _webView.scrollView.scrollIndicatorInsets = (UIEdgeInsets){.left = -margin, .right = -margin}; +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; + [self updateLayoutMargins]; +} + +- (void)setUpStaticConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_webView, _toolbar, _iPadStepTitleLabel); + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_toolbar]|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_iPadStepTitleLabel]-[_webView][_toolbar]-|" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:views]]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_toolbar + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute:NSLayoutAttributeNotAnAttribute + multiplier:1.0 + constant:ORKGetMetricForWindow(ORKScreenMetricToolbarHeight, self.view.window)]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)updateViewConstraints { + [super updateViewConstraints]; + if (!_variableConstraints) { + _variableConstraints = [NSMutableArray new]; + } + [NSLayoutConstraint deactivateConstraints:_variableConstraints]; + [_variableConstraints removeAllObjects]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_webView, _toolbar, _iPadStepTitleLabel); + const CGFloat horizontalMargin = ORKNeedWideScreenDesign(self.view) ? ORKiPadBackgroundViewLeftRightPadding : ORKStandardHorizontalMarginForView(self.view); + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-horizMargin-[_webView]-horizMargin-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"horizMargin": @(horizontalMargin) } + views:views]]; + [_variableConstraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-horizMargin-[_iPadStepTitleLabel]-horizMargin-|" + options:(NSLayoutFormatOptions)0 + metrics:@{ @"horizMargin": @(horizontalMargin) } + views:views]]; + [NSLayoutConstraint activateConstraints:_variableConstraints]; +} + +- (IBAction)cancel { + if (self.delegate && [self.delegate respondsToSelector:@selector(consentReviewControllerDidCancel:)]) { + [self.delegate consentReviewControllerDidCancel:self]; + } +} + +- (void)doAck { + if (self.delegate && [self.delegate respondsToSelector:@selector(consentReviewControllerDidAcknowledge:)]) { + [self.delegate consentReviewControllerDidAcknowledge:self]; + } +} + +- (IBAction)ack { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:ORKLocalizedString(@"CONSENT_REVIEW_ALERT_TITLE", nil) + message:self.localizedReasonForConsent + preferredStyle:UIAlertControllerStyleAlert]; + + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_CANCEL", nil) style:UIAlertActionStyleDefault handler:nil]]; + [alert addAction:[UIAlertAction actionWithTitle:ORKLocalizedString(@"BUTTON_AGREE", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + // Have to dispatch, so following transition animation works + dispatch_async(dispatch_get_main_queue(), ^{ + [self doAck]; + }); + }]]; + + [self presentViewController:alert animated:YES completion:nil]; +} + +- (void)webView:(WKWebView *) __unused webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { + if (navigationAction.navigationType != WKNavigationTypeOther) { + [[UIApplication sharedApplication] openURL:navigationAction.request.URL options:@{} completionHandler:^(BOOL __unused success) { + decisionHandler(WKNavigationActionPolicyCancel); + }]; + } else { + decisionHandler(WKNavigationActionPolicyAllow); + } +} + +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *) __unused navigation { + //need a delay here because of a race condition where the webview may not have fully rendered by the time this is called in which case scrolledToBottom returns YES because everything == 0 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (!_agreeButton.isEnabled && [self scrolledToBottom:_webView.scrollView]) { + [_agreeButton setEnabled:YES]; + } + }); +} + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (!_agreeButton.isEnabled && [self scrolledToBottom:scrollView]) { + _agreeButton.enabled = YES; + } + }); +} + +- (BOOL)scrolledToBottom:(UIScrollView *)scrollView { + CGPoint offset = scrollView.contentOffset; + CGRect bounds = scrollView.bounds; + UIEdgeInsets inset = scrollView.contentInset; + CGFloat currentOffset = offset.y + bounds.size.height - inset.bottom; + return (currentOffset - scrollView.contentSize.height >= 0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.h new file mode 100755 index 0000000..ec3aafa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.h @@ -0,0 +1,113 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentDocument; +@class ORKConsentSignature; + +/** + The `ORKConsentReviewStep` class is used to represent the consent review process. + Typically, the consent review process consists of three main parts: + + 1. Consent document review. In this part, you display the consent document for review. Users + must explicitly agree to the consent document before they can proceed. + + 2. Name entry (optional). Users are asked to enter their first and last name. To + request name entry in your app, set the step's `signature` property, and ensure that the signature's + `requiresName` property is set to `YES`. + + 3. Signature (optional). Users are asked to draw their signature on the device screen. + To request signature entry in your app, set the step's `signature` property, and ensure that the signature's + `requiresName` property is set to `YES`. + + The content for the consent document review comes from a consent document (`ORKConsentDocument`) + provided during initialization. + + To use a consent review step, configure it and include it in a task. Then + present the task in a task view controller. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentReviewStep : ORKStep + +/// @name Initialization. + +/** + Returns an initialized consent review step using the specified identifier, signature, and consent document. + + @param identifier The identifier for the step. + @param signature The signature to be collected, if any. + @param consentDocument The consent document to be reviewed. + + @return An initialized consent review step. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + signature:(nullable ORKConsentSignature *)signature + inDocument:(ORKConsentDocument *)consentDocument; + +/// @name Properties + +/** + The consent document to be reviewed by the user during the consent review process. (read-only) + */ +@property (nonatomic, strong, readonly) ORKConsentDocument *consentDocument; + +/** + The signature object from the document that should be collected. (read-only) + + When the value of `signature` is `nil`, neither the name nor the finger scrawl are collected. + When the value of `signature` is not `nil`, the `requiresName` and `requiresSignatureImage` properties of + `signature` determine the screens that get presented. + + The identifier of the signature is expected to match one of the signature objects in + the consent document. + */ +@property (nonatomic, strong, readonly, nullable) ORKConsentSignature *signature; + +/** + When set to YES, the consent document must be scrolled to the bottom to enable the `Agree` button. + */ +@property (nonatomic) BOOL requiresScrollToBottom; + +/** + A user-visible description of the reason for agreeing to consent in a localized string. + + The reason for consent is presented in the confirmation dialog that users see when giving their consent. + */ +@property (nonatomic, copy, nullable) NSString *reasonForConsent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.m new file mode 100755 index 0000000..bedbf2c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStep.m @@ -0,0 +1,108 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentReviewStep.h" + +#import "ORKConsentReviewStepViewController.h" + +#import "ORKConsentDocument_Internal.h" +#import "ORKConsentSection_Private.h" +#import "ORKConsentSignature.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentReviewStep + ++ (Class)stepViewControllerClass { + return [ORKConsentReviewStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier signature:(ORKConsentSignature *)signature inDocument:(ORKConsentDocument *)consentDocument { + self = [super initWithIdentifier:identifier]; + if (self) { + _consentDocument = consentDocument; + _signature = signature; + _requiresScrollToBottom = NO; + self.showsProgress = NO; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentReviewStep *step = [super copyWithZone:zone]; + step->_consentDocument = self.consentDocument; + step->_signature = self.signature; + step->_reasonForConsent = self.reasonForConsent; + step->_requiresScrollToBottom = self.requiresScrollToBottom; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, consentDocument, ORKConsentDocument); + ORK_DECODE_OBJ_CLASS(aDecoder, signature, ORKConsentSignature); + ORK_DECODE_OBJ_CLASS(aDecoder, reasonForConsent, NSString); + ORK_DECODE_BOOL(aDecoder, requiresScrollToBottom); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, consentDocument); + ORK_ENCODE_OBJ(aCoder, signature); + ORK_ENCODE_OBJ(aCoder, reasonForConsent); + ORK_ENCODE_BOOL(aCoder, requiresScrollToBottom); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.consentDocument, castObject.consentDocument) && + ORKEqualObjects(self.signature, castObject.signature) && + ORKEqualObjects(self.reasonForConsent, castObject.reasonForConsent)) && + (self.requiresScrollToBottom == castObject.requiresScrollToBottom); +} + +- (NSUInteger)hash { + return super.hash ^ self.consentDocument.hash ^ self.signature.hash ^ self.reasonForConsent.hash ^ (_requiresScrollToBottom ? 0xf : 0x0); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.h new file mode 100755 index 0000000..4e6d0c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.h @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentReviewStep; +@class ORKConsentSignatureResult; + +/** + The `ORKConsentReviewStepViewController` class is a step view controller subclass + used to manage a consent review step (`ORKConsentReviewStep`). + + You should not need to instantiate a consent review step view controller directly. Instead, include + a consent review step in a task, and present a task view controller for that + task. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentReviewStepViewController : ORKStepViewController + +/** + Returns an initialized consent review step view controller using the specified review step and result. + + @param consentReviewStep The configured review step. + @param result The initial or previous results for the review step, as appropriate. + */ +- (instancetype)initWithConsentReviewStep:(ORKConsentReviewStep *)consentReviewStep + result:(nullable ORKConsentSignatureResult *)result; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.m new file mode 100755 index 0000000..612afd8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentReviewStepViewController.m @@ -0,0 +1,513 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentReviewStepViewController.h" + +#import "ORKConsentReviewController.h" +#import "ORKFormStepViewController.h" +#import "ORKSignatureStepViewController.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" + +#import "ORKAnswerFormat_Internal.h" +#import "ORKCollectionResult_Private.h" +#import "ORKConsentDocument_Internal.h" +#import "ORKConsentReviewStep.h" +#import "ORKConsentSignature.h" +#import "ORKConsentSignatureResult.h" +#import "ORKFormStep.h" +#import "ORKQuestionResult_Private.h" +#import "ORKResult.h" +#import "ORKSignatureResult_Private.h" +#import "ORKSignatureStep.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" +#import "UIBarButtonItem+ORKBarButtonItem.h" +#import "ORKSkin.h" + + +typedef NS_ENUM(NSInteger, ORKConsentReviewPhase) { + ORKConsentReviewPhaseName, + ORKConsentReviewPhaseReviewDocument, + ORKConsentReviewPhaseSignature +}; + +@interface ORKConsentReviewStepViewController () { + ORKConsentSignature *_currentSignature; + UIPageViewController *_pageViewController; + + NSMutableArray *_pageIndices; + + NSString *_signatureFirst; + NSString *_signatureLast; + UIImage *_signatureImage; + BOOL _documentReviewed; + + NSUInteger _currentPageIndex; +} + +@end + + +@implementation ORKConsentReviewStepViewController + +- (instancetype)initWithConsentReviewStep:(ORKConsentReviewStep *)step result:(ORKConsentSignatureResult *)result { + self = [super initWithStep:step]; + if (self) { + _signatureFirst = [result.signature givenName]; + _signatureLast = [result.signature familyName]; + _signatureImage = [result.signature signatureImage]; + _documentReviewed = NO; + + _currentSignature = [result.signature copy]; + + _currentPageIndex = NSNotFound; + } + return self; +} + +- (void)stepDidChange { + if (![self isViewLoaded]) { + return; + } + + _currentPageIndex = NSNotFound; + ORKConsentReviewStep *step = [self consentReviewStep]; + NSMutableArray *indices = [NSMutableArray array]; + if (step.consentDocument) { + [indices addObject:@(ORKConsentReviewPhaseReviewDocument)]; + } + if (step.signature.requiresName) { + [indices addObject:@(ORKConsentReviewPhaseName)]; + } + if (step.signature.requiresSignatureImage) { + [indices addObject:@(ORKConsentReviewPhaseSignature)]; + } + + _pageIndices = indices; + + [self goToPage:0 animated:NO]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Prepare pageViewController + _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll + navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal + options:nil]; + _pageViewController.delegate = self; + + if ([_pageViewController respondsToSelector:@selector(edgesForExtendedLayout)]) { + _pageViewController.edgesForExtendedLayout = UIRectEdgeNone; + } + + _pageViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; + _pageViewController.view.frame = self.view.bounds; + [self.view addSubview:_pageViewController.view]; + [self addChildViewController:_pageViewController]; + [_pageViewController didMoveToParentViewController:self]; + + [self stepDidChange]; +} + +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + if ([_pageViewController.viewControllers[0] isKindOfClass:[ORKConsentReviewController class]]) { + ORKConsentReviewController *consentReviewController = _pageViewController.viewControllers[0]; + [self.taskViewController setRegisteredScrollView:consentReviewController.webView.scrollView]; + } else { + NSAssert(NO, @"The first view controller in a consent review step should be of type ORKConsentReviewController"); + } +} + +- (UIBarButtonItem *)goToPreviousPageButtonItem { + UIBarButtonItem *button = [UIBarButtonItem ork_backBarButtonItemWithTarget:self action:@selector(goToPreviousPage)]; + button.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + return button; +} + +- (void)updateBarButtonItems { + if (_currentPageIndex == 0) { + [super updateBarButtonItems]; + } else { + self.navigationItem.leftBarButtonItem = [self goToPreviousPageButtonItem]; + } +} + +- (void)updateBackButton { + if (_currentPageIndex == NSNotFound) { + return; + } + + [self updateBarButtonItems]; +} + +static NSString *const _NameFormIdentifier = @"nameForm"; +static NSString *const _GivenNameIdentifier = @"given"; +static NSString *const _FamilyNameIdentifier = @"family"; + +- (ORKFormStepViewController *)makeNameFormViewController { + ORKFormStep *formStep = [[ORKFormStep alloc] initWithIdentifier:_NameFormIdentifier + title:self.step.title ? : ORKLocalizedString(@"CONSENT_NAME_TITLE", nil) + text:self.step.text]; + formStep.useSurveyMode = NO; + + ORKTextAnswerFormat *givenNameAnswerFormat = [ORKTextAnswerFormat textAnswerFormat]; + givenNameAnswerFormat.multipleLines = NO; + givenNameAnswerFormat.autocapitalizationType = UITextAutocapitalizationTypeWords; + givenNameAnswerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + givenNameAnswerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + givenNameAnswerFormat.textContentType = UITextContentTypeGivenName; + ORKFormItem *givenNameFormItem = [[ORKFormItem alloc] initWithIdentifier:_GivenNameIdentifier + text:ORKLocalizedString(@"CONSENT_NAME_GIVEN", nil) + answerFormat:givenNameAnswerFormat]; + givenNameFormItem.placeholder = ORKLocalizedString(@"CONSENT_NAME_PLACEHOLDER", nil); + + ORKTextAnswerFormat *familyNameAnswerFormat = [ORKTextAnswerFormat textAnswerFormat]; + familyNameAnswerFormat.multipleLines = NO; + familyNameAnswerFormat.autocapitalizationType = UITextAutocapitalizationTypeWords; + familyNameAnswerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + familyNameAnswerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + familyNameAnswerFormat.textContentType = UITextContentTypeFamilyName; + ORKFormItem *familyNameFormItem = [[ORKFormItem alloc] initWithIdentifier:_FamilyNameIdentifier + text:ORKLocalizedString(@"CONSENT_NAME_FAMILY", nil) + answerFormat:familyNameAnswerFormat]; + familyNameFormItem.placeholder = ORKLocalizedString(@"CONSENT_NAME_PLACEHOLDER", nil); + + givenNameFormItem.optional = NO; + familyNameFormItem.optional = NO; + + NSArray *formItems = @[givenNameFormItem, familyNameFormItem]; + if (ORKCurrentLocalePresentsFamilyNameFirst()) { + formItems = @[familyNameFormItem, givenNameFormItem]; + } + + [formStep setFormItems:formItems]; + + formStep.optional = NO; + + ORKTextQuestionResult *givenNameDefault = [[ORKTextQuestionResult alloc] initWithIdentifier:_GivenNameIdentifier]; + givenNameDefault.textAnswer = _signatureFirst; + ORKTextQuestionResult *familyNameDefault = [[ORKTextQuestionResult alloc] initWithIdentifier:_FamilyNameIdentifier]; + familyNameDefault.textAnswer = _signatureLast; + ORKStepResult *defaults = [[ORKStepResult alloc] initWithStepIdentifier:_NameFormIdentifier results:@[givenNameDefault, familyNameDefault]]; + + ORKFormStepViewController *viewController = [[ORKFormStepViewController alloc] initWithStep:formStep result:defaults]; + viewController.delegate = self; + + return viewController; +} + +- (ORKConsentReviewController *)makeDocumentReviewViewController { + ORKConsentSignature *originalSignature = [self.consentReviewStep signature]; + ORKConsentDocument *origninalDocument = self.consentReviewStep.consentDocument; + + NSUInteger index = [origninalDocument.signatures indexOfObject:originalSignature]; + + // Deep copy + ORKConsentDocument *document = [origninalDocument copy]; + + if (index != NSNotFound) { + ORKConsentSignature *signature = document.signatures[index]; + + if (signature.requiresName) { + signature.givenName = _signatureFirst; + signature.familyName = _signatureLast; + } + } + + NSString *html = [document mobileHTMLWithTitle:ORKLocalizedString(@"CONSENT_REVIEW_TITLE", nil) + detail:ORKLocalizedString(@"CONSENT_REVIEW_INSTRUCTION", nil)]; + + ORKConsentReviewController *reviewViewController = [[ORKConsentReviewController alloc] initWithHTML:html delegate:self requiresScrollToBottom:[[self consentReviewStep] requiresScrollToBottom]]; + if (ORKNeedWideScreenDesign(self.view)) { + [reviewViewController setTextForiPadStepTitleLabel:self.title]; + } + reviewViewController.localizedReasonForConsent = [[self consentReviewStep] reasonForConsent]; + reviewViewController.cancelButtonItem = self.cancelButtonItem; + return reviewViewController; +} + +static NSString *const _SignatureStepIdentifier = @"signatureStep"; + +- (ORKSignatureStepViewController *)makeSignatureViewController { + ORKSignatureStep *step = [[ORKSignatureStep alloc] initWithIdentifier:_SignatureStepIdentifier]; + step.optional = NO; + ORKSignatureStepViewController *signatureController = [[ORKSignatureStepViewController alloc] initWithStep:step]; + signatureController.delegate = self; + return signatureController; +} + +- (void)goToPreviousPage { + [self navigateDelta:-1]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (UIViewController *)viewControllerForIndex:(NSUInteger)index { + if (index >= _pageIndices.count) { + return nil; + } + + ORKConsentReviewPhase phase = ((NSNumber *)_pageIndices[index]).integerValue; + + UIViewController *viewController = nil; + switch (phase) { + case ORKConsentReviewPhaseName: { + // A form step VC with a form step with a first name and a last name + ORKFormStepViewController *formViewController = [self makeNameFormViewController]; + formViewController.cancelButtonItem = self.cancelButtonItem; + viewController = formViewController; + break; + } + case ORKConsentReviewPhaseReviewDocument: { + // Document review VC + ORKConsentReviewController *reviewViewController = [self makeDocumentReviewViewController]; + viewController = reviewViewController; + break; + } + case ORKConsentReviewPhaseSignature: { + // Signature VC + ORKSignatureStepViewController *signatureViewController = [self makeSignatureViewController]; + signatureViewController.cancelButtonItem = self.cancelButtonItem; + viewController = signatureViewController; + break; + } + } + return viewController; +} + +- (ORKStepResult *)result { + ORKStepResult *parentResult = [super result]; + if (!_currentSignature) { + _currentSignature = [[self.consentReviewStep signature] copy]; + + if (_currentSignature.requiresName) { + _currentSignature.givenName = _signatureFirst; + _currentSignature.familyName = _signatureLast; + } + if (_currentSignature.requiresSignatureImage) { + _currentSignature.signatureImage = _signatureImage; + } + + if (_currentSignature.signatureDateFormatString.length > 0) { + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setDateFormat:_currentSignature.signatureDateFormatString]; + _currentSignature.signatureDate = [dateFormatter stringFromDate:[NSDate date]]; + } else { + _currentSignature.signatureDate = ORKSignatureStringFromDate([NSDate date]); + } + } + + ORKConsentSignatureResult *result = [[ORKConsentSignatureResult alloc] init]; + result.signature = _currentSignature; + result.identifier = _currentSignature.identifier; + result.consented = _documentReviewed; + result.startDate = parentResult.startDate; + result.endDate = parentResult.endDate; + + // Add the result + parentResult.results = [self.addedResults arrayByAddingObject:result] ? : @[result]; + + return parentResult; +} + +- (ORKConsentReviewStep *)consentReviewStep { + assert(self.step == nil || [self.step isKindOfClass:[ORKConsentReviewStep class]]); + return (ORKConsentReviewStep *)self.step; +} + +- (void)notifyDelegateOnResultChange { + _currentSignature = nil; + [super notifyDelegateOnResultChange]; +} + +#pragma mark ORKStepViewControllerDelegate + +- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction { + if (_currentPageIndex == NSNotFound) { + return; + } + + NSInteger delta = (direction == ORKStepViewControllerNavigationDirectionForward) ? 1 : -1; + [self navigateDelta:delta]; +} + +- (void)navigateDelta:(NSInteger)delta { + // Entry point for forward/back navigation. + NSUInteger pageCount = _pageIndices.count; + + if (_currentPageIndex == 0 && delta < 0) { + // Navigate back in our parent task VC. + [self goBackward]; + } else if (_currentPageIndex >= (pageCount - 1) && delta > 0) { + // Navigate forward in our parent task VC. + [self goForward]; + } else { + // Navigate within our managed steps + [self goToPage:(_currentPageIndex + delta) animated:YES]; + } +} + +- (void)goToPage:(NSInteger)page animated:(BOOL)animated { + UIViewController *viewController = [self viewControllerForIndex:page]; + + if (!viewController) { + ORK_Log_Debug("No view controller!"); + return; + } + + NSUInteger currentIndex = _currentPageIndex; + if (currentIndex == NSNotFound) { + animated = NO; + } + + UIPageViewControllerNavigationDirection direction = (!animated || page > currentIndex) ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse; + + ORKAdjustPageViewControllerNavigationDirectionForRTL(&direction); + + _currentPageIndex = page; + ORKWeakTypeOf(self) weakSelf = self; + + //unregister ScrollView to clear hairline + [self.taskViewController setRegisteredScrollView:nil]; + + [_pageViewController setViewControllers:@[viewController] direction:direction animated:animated completion:^(BOOL finished) { + if (finished) { + ORKStrongTypeOf(weakSelf) strongSelf = weakSelf; + [strongSelf updateBackButton]; + + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); + } + }]; +} + +- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController { + if ([stepViewController.step.identifier isEqualToString:_NameFormIdentifier]) { + // If this is the form step then update the values from the form + ORKStepResult *result = [stepViewController result]; + ORKTextQuestionResult *fnr = (ORKTextQuestionResult *)[result resultForIdentifier:_GivenNameIdentifier]; + _signatureFirst = (NSString *)fnr.textAnswer; + ORKTextQuestionResult *lnr = (ORKTextQuestionResult *)[result resultForIdentifier:_FamilyNameIdentifier]; + _signatureLast = (NSString *)lnr.textAnswer; + [self notifyDelegateOnResultChange]; + + } else if ([stepViewController.step.identifier isEqualToString:_SignatureStepIdentifier]) { + // If this is the signature step then update the image from the signature + ORKStepResult *result = [stepViewController result]; + [result.results enumerateObjectsUsingBlock:^(ORKResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[ORKSignatureResult class]]) { + _signatureImage = ((ORKSignatureResult *)obj).signatureImage; + *stop = YES; + } + }]; + [self notifyDelegateOnResultChange]; + } +} + +- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(NSError *)error { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(stepViewControllerDidFail:withError:)]) { + [strongDelegate stepViewControllerDidFail:self withError:error]; + } +} + +- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController { + if (_currentPageIndex < (_pageIndices.count - 1)) { + return YES; + } + return [self hasNextStep]; +} + +- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController { + return [self hasPreviousStep]; +} + +- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + ORKStrongTypeOf(self.delegate) strongDelegate = self.delegate; + if ([strongDelegate respondsToSelector:@selector(stepViewController:recorder:didFailWithError:)]) { + [strongDelegate stepViewController:self recorder:recorder didFailWithError:error]; + } +} + +#pragma mark ORKConsentReviewControllerDelegate + +- (void)consentReviewControllerDidAcknowledge:(ORKConsentReviewController *)consentReviewController { + _documentReviewed = YES; + [self notifyDelegateOnResultChange]; + [self navigateDelta:1]; +} + +- (void)consentReviewControllerDidCancel:(ORKConsentReviewController *)consentReviewController { + _signatureFirst = nil; + _signatureLast = nil; + _signatureImage = nil; + _documentReviewed = NO; + [self notifyDelegateOnResultChange]; + + [self goForward]; +} + +static NSString *const _ORKCurrentSignatureRestoreKey = @"currentSignature"; +static NSString *const _ORKSignatureFirstRestoreKey = @"signatureFirst"; +static NSString *const _ORKSignatureLastRestoreKey = @"signatureLast"; +static NSString *const _ORKSignatureImageRestoreKey = @"signatureImage"; +static NSString *const _ORKDocumentReviewedRestoreKey = @"documentReviewed"; +static NSString *const _ORKCurrentPageIndexRestoreKey = @"currentPageIndex"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_currentSignature forKey:_ORKCurrentSignatureRestoreKey]; + [coder encodeObject:_signatureFirst forKey:_ORKSignatureFirstRestoreKey]; + [coder encodeObject:_signatureLast forKey:_ORKSignatureLastRestoreKey]; + [coder encodeObject:_signatureImage forKey:_ORKSignatureImageRestoreKey]; + [coder encodeBool:_documentReviewed forKey:_ORKDocumentReviewedRestoreKey]; + [coder encodeInteger:_currentPageIndex forKey:_ORKCurrentPageIndexRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + _currentSignature = [coder decodeObjectOfClass:[ORKConsentSignature class] + forKey:_ORKCurrentSignatureRestoreKey]; + + _signatureFirst = [coder decodeObjectOfClass:[NSString class] forKey:_ORKSignatureFirstRestoreKey]; + _signatureLast = [coder decodeObjectOfClass:[NSString class] forKey:_ORKSignatureLastRestoreKey]; + _signatureImage = [coder decodeObjectOfClass:[NSString class] forKey:_ORKSignatureImageRestoreKey]; + _documentReviewed = [coder decodeBoolForKey:_ORKDocumentReviewedRestoreKey]; + _currentPageIndex = [coder decodeIntegerForKey:_ORKCurrentPageIndexRestoreKey]; + + [self goToPage:_currentPageIndex animated:NO]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.h new file mode 100755 index 0000000..484dd7a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.h @@ -0,0 +1,55 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentSection; + +@interface ORKConsentSceneViewController : UIViewController + +- (instancetype)initWithSection:(ORKConsentSection *)section; + +@property (nonatomic, readonly, nullable) ORKConsentSection *section; + +@property (nonatomic, strong, nullable) UIBarButtonItem *continueButtonItem; + +@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem; + +@property (nonatomic, strong, nullable) NSString *learnMoreButtonTitle; + +@property (nonatomic, assign) BOOL imageHidden; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.m new file mode 100755 index 0000000..1c157ba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController.m @@ -0,0 +1,233 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSceneViewController.h" +#import "ORKConsentSceneViewController_Internal.h" + +#import "ORKNavigationContainerView_Internal.h" +#import "ORKStepHeaderView_Internal.h" +#import "ORKTintedImageView.h" +#import "ORKStepView_Private.h" +#import "ORKStepContentView_Private.h" +#import "ORKConsentLearnMoreViewController.h" + +#import "ORKConsentDocument_Internal.h" +#import "ORKConsentSection_Private.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@interface ORKConsentSceneView () + +@property (nonatomic, strong) ORKConsentSection *consentSection; + +@end + +@implementation ORKConsentSceneView + +- (void)setConsentSection:(ORKConsentSection *)consentSection { + _consentSection = consentSection; + + self.stepTopContentImage = consentSection.image; + self.stepText = [consentSection summary]; + +} + +@end + + +static NSString *localizedLearnMoreForType(ORKConsentSectionType sectionType) { + NSString *str = ORKLocalizedString(@"BUTTON_LEARN_MORE", nil); + switch (sectionType) { + case ORKConsentSectionTypeOverview: + str = ORKLocalizedString(@"LEARN_MORE_WELCOME", nil); + break; + case ORKConsentSectionTypeDataGathering: + str = ORKLocalizedString(@"LEARN_MORE_DATA_GATHERING", nil); + break; + case ORKConsentSectionTypePrivacy: + str = ORKLocalizedString(@"LEARN_MORE_PRIVACY", nil); + break; + case ORKConsentSectionTypeDataUse: + str = ORKLocalizedString(@"LEARN_MORE_DATA_USE", nil); + break; + case ORKConsentSectionTypeTimeCommitment: + str = ORKLocalizedString(@"LEARN_MORE_TIME_COMMITMENT", nil); + break; + case ORKConsentSectionTypeStudySurvey: + str = ORKLocalizedString(@"LEARN_MORE_STUDY_SURVEY", nil); + break; + case ORKConsentSectionTypeStudyTasks: + str = ORKLocalizedString(@"LEARN_MORE_TASKS", nil); + break; + case ORKConsentSectionTypeWithdrawing: + str = ORKLocalizedString(@"LEARN_MORE_WITHDRAWING", nil); + break; + case ORKConsentSectionTypeOnlyInDocument: + assert(0); // assert and fall through to custom + case ORKConsentSectionTypeCustom: + break; + } + return str; +} + + +@implementation ORKConsentSceneViewController { + ORKNavigationContainerView *_navigationFooterView; + NSArray *_constraints; + +} + +- (instancetype)initWithSection:(ORKConsentSection *)section { + self = [super init]; + if (self) { + _section = section; + self.title = section.title; + self.learnMoreButtonTitle = _section.customLearnMoreButtonTitle; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + _sceneView = [ORKConsentSceneView new]; + _sceneView.consentSection = _section; + _sceneView.stepTitle = _section.title; + [self.view addSubview:_sceneView]; + + if (_section.content.length||_section.htmlContent.length || _section.contentURL) { + ORK_Log_Info("%@", localizedLearnMoreForType(_section.type)); + } + [self setupNavigationFooterView]; + [self setupConstraints]; +} + +- (void)setupNavigationFooterView { + if (!_navigationFooterView) { + _navigationFooterView = _sceneView.navigationFooterView ; + } + _navigationFooterView.continueButtonItem = _continueButtonItem; + _navigationFooterView.continueEnabled = YES; + [_navigationFooterView updateContinueAndSkipEnabled]; +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _constraints = nil; + _sceneView.translatesAutoresizingMaskIntoConstraints = NO; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_sceneView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_sceneView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_sceneView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_sceneView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + _continueButtonItem = continueButtonItem; + _navigationFooterView.continueButtonItem = continueButtonItem; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + _cancelButtonItem = cancelButtonItem; +} + +- (UIScrollView *)scrollView { + return (UIScrollView *)self.view; +} + +- (void)scrollToTopAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion { + ORKConsentSceneView *consentSceneView = (ORKConsentSceneView *)self.view; + CGRect targetBounds = consentSceneView.bounds; + targetBounds.origin.y = 0; + if (animated) { + [UIView animateWithDuration:ORKScrollToTopAnimationDuration animations:^{ + consentSceneView.bounds = targetBounds; + } completion:completion]; + } else { + consentSceneView.bounds = targetBounds; + if (completion) { + completion(YES); + } + } +} + +#pragma mark - Action + +- (IBAction)showContent:(id)sender { + ORKConsentLearnMoreViewController *viewController = nil; + + if (_section.contentURL) { + viewController = [[ORKConsentLearnMoreViewController alloc] initWithContentURL:_section.contentURL]; + } else { + viewController = [[ORKConsentLearnMoreViewController alloc] initWithHTMLContent:((_section.htmlContent.length > 0) ? _section.htmlContent : _section.escapedContent)]; + } + viewController.title = _section.title ?: ORKLocalizedString(@"CONSENT_LEARN_MORE_TITLE", nil); + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + navigationController.modalPresentationStyle = UIModalPresentationFormSheet; + [self presentViewController:navigationController animated:YES completion:nil]; +} + +- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller { + return UIModalPresentationOverFullScreen; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController_Internal.h new file mode 100755 index 0000000..845ae37 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSceneViewController_Internal.h @@ -0,0 +1,53 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSceneViewController.h" +#import "ORKStepContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKConsentSceneView : ORKStepContainerView + +@end + + +@interface ORKConsentSceneViewController () + +@property (nonatomic, readonly) ORKConsentSceneView *sceneView; + +@property (nonatomic, readonly) UIScrollView *scrollView; + +- (void)scrollToTopAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.h new file mode 100755 index 0000000..219e224 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.h @@ -0,0 +1,259 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + `ORKConsentSectionType` enumerates the predefined visual consent sections + available in the ResearchKit framework. + + Although the visuals are predefined, and default localized titles and Learn + More button titles are provided, you need to provide in `ORKConsentSection` the summary strapline on each visual consent + page and the actual Learn More content, because these items are specific to each individual + study. + + Not every section is applicable to every study, and most studies + are likely to require additional sections. + */ +typedef NS_ENUM(NSInteger, ORKConsentSectionType) { + /** + Overview of the informed consent process. + + This content can inform the user of what to expect during the process, + and provide general background information on the purpose of the study. + */ + ORKConsentSectionTypeOverview, + + /** + A section informing the user that sensor data will be collected. + + This content can identify which sensors will be used, for how long, + and for what purpose. + */ + ORKConsentSectionTypeDataGathering, + + /** + A section describing the privacy policies for the study. + + This content can describe how data is protected, the processes used + to sanitize the collected data or make it anonymous, and address the risks + involved. + */ + ORKConsentSectionTypePrivacy, + + /** + A section describing how the collected data will be used. + + This content can include details about those who will have access to the data, the types of + analysis that will be performed, and the degree of control the participant + may have over the data after it is collected. + */ + ORKConsentSectionTypeDataUse, + + /** + A section describing how much time is required for the study. + + This content can help users understand what to expect as they participate in the study. + */ + ORKConsentSectionTypeTimeCommitment, + + /** + A section describing survey use in the study. + + This content can explain how survey data will be collected, for what purpose, + and make it clear to what extent participation is optional. + */ + ORKConsentSectionTypeStudySurvey, + + /** + A section describing active task use in the study. + + This content can describe what types of tasks need to be performed, how + often, and for what purpose. Any risks that are involved can + also be communicated in this section. + */ + ORKConsentSectionTypeStudyTasks, + + /** + A section describing how to withdraw from the study. + + This section can describe the policies + that govern the collected data if the user decides to withdraw. + */ + ORKConsentSectionTypeWithdrawing, + + /** + A custom section. + + Custom sections don't have a predefined title, summary, content, image, + or animation. A consent document may have as many or as few custom sections + as needed. + */ + ORKConsentSectionTypeCustom, + + /** + Document-only sections. + + Document-only sections are ignored for a visual consent step and are only + displayed in a consent review step (assuming no value is provided for the `htmlReviewContent` property). + */ + ORKConsentSectionTypeOnlyInDocument +} ORK_ENUM_AVAILABLE; + +/** + The `ORKConsentSection` class represents one section in a consent document. Each + `ORKConsentSection` object (apart from those of type `ORKConsentSectionTypeOnlyInDocument`) + corresponds to a page in a visual consent step, or a section in the document + reviewed in consent review step. + + If you initialize a consent section with one of the defined section types, you get a prepopulated title, a default image, and animation (when appropriate). You can override these properties or you can use the `ORKConsentSectionTypeCustom` type to + avoid any prepopulation. + + If you provide content for the `ORKConsentSection` object, be sure to use localized content. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentSection : NSObject + +/** + Returns an initialized consent section using the specified type. + + This method populates the title and summary for all types except for + `ORKConsentSectionTypeCustom` and `ORKConsentSectionTypeOnlyInDocument`. + + @param type The consent section type. + */ +- (instancetype)initWithType:(ORKConsentSectionType)type; + +/** + The type of section. (read-only) + + The value of this property indicates whether a predefined image, title, and animation are present. + */ +@property (nonatomic, readonly) ORKConsentSectionType type; + +/** + The title of the consent section in a localized string. + + The title is displayed as a scene title in the animated consent sequence and is also included in the PDF file, but it can be overridden by setting `formalTitle`. + The title is prefilled unless the type is `ORKConsentSectionTypeCustom` or `ORKConsentSectionTypeOnlyInDocument`. + */ +@property (nonatomic, copy, nullable) NSString *title; + +/** + The formal title of the section in a localized string, for use in the legal document. + + If the value of this property is `nil`, the value of `title` is used in the legal document instead. + */ +@property (nonatomic, copy, nullable) NSString *formalTitle; + +/** + A short summary of the content in a localized string. + + The summary is displayed as description text in the animated consent sequence. + The summary should be limited in length, so that the consent can be reliably + displayed on smaller screens. + */ +@property (nonatomic, copy, nullable) NSString *summary; + +/** + The content of the section in a localized string. + + In a consent review step or in PDF file generation, the string is printed as the section's + content. The string is also displayed as Learn More content in a visual consent step. + + This property is never prepopulated based on the value of `type`. If both `content` and `htmlContent` are non-nil, the value of the `htmlContent` property is used. + */ +@property (nonatomic, copy, nullable) NSString *content; + +/** + The HTML content used to override the `content` property if additional formatting is needed. The content should be localized. + + In cases where plain text content is not sufficient to convey important details + during the consent process, you can provide HTML content in this property. When you do this, the `htmlContent` property takes precedence over the `content` property. + + In a consent review step or in PDF file generation, the value of this property is printed as the section's + content; in a visual consent step, the content is displayed as Learn More content. + */ +@property (nonatomic, copy, nullable) NSString *htmlContent; + +/** + The NSURL used to override the 'htmlContent' and 'consent' property if a document should be required. + + This property is used to display a document when required by an authortity. + + */ +@property (nonatomic, copy, nullable) NSURL *contentURL; + +/** + When set to YES, the section is omitted in a consent review step or in PDF file generation. This property is NO by default. + */ +@property (nonatomic) BOOL omitFromDocument; + +/** + A custom illustration for the consent. + + The custom image can override the image associated with any of the predefined + section types for an `ORKVisualConsentStep` object. It is ignored for a consent review step and + for PDF generation. + + The image is used in template rendering mode, and is tinted using the tint color. + */ +@property (nonatomic, copy, nullable) UIImage *customImage; + +/** + A custom Learn More button title in a localized string. + + The predefined section types have localized descriptive Learn More button + titles for a visual consent step. When this property is not `nil`, it overrides that + default text. + */ +@property (nonatomic, copy, nullable) NSString *customLearnMoreButtonTitle; + +/** + A file URL that specifies a custom transition animation video. + + Animations of the illustration between one screen and the next are provided + by default for transitions between consecutive section `type` codes. Custom + sections and out-of-order transitions may require custom animations. + + The animation loaded from the file URL is played aspect fill in the + illustration area for forward transitions only. The video is rendered in + template mode, with white treated as if it were transparent. + */ +@property (nonatomic, copy, nullable) NSURL *customAnimationURL; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.m new file mode 100755 index 0000000..4a318b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection.m @@ -0,0 +1,275 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSection.h" + +#import "ORKHelpers_Internal.h" + +#import "ORKConsentSection_Private.h" + + +static NSString *movieNameForType(ORKConsentSectionType type, CGFloat scale) { + NSString *fullMovieName = [NSString stringWithFormat:@"consent_%02ld", (long)type + 1]; + fullMovieName = [NSString stringWithFormat:@"%@@%dx", fullMovieName, (int)scale]; + return fullMovieName; +} + +NSURL *ORKMovieURLForConsentSectionType(ORKConsentSectionType type) { + CGFloat scale = [UIScreen mainScreen].scale; + + // For iPad, use the movie for the next scale up + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && scale < 3) { + scale++; + } + + NSURL *url = [ORKAssetsBundle() URLForResource:movieNameForType(type, scale) withExtension:@"m4v"]; + if (url == nil) { + // This can fail on 3x devices when the display is set to zoomed. Try an asset at 2x instead. + url = [ORKAssetsBundle() URLForResource:movieNameForType(type, 2.0) withExtension:@"m4v"]; + } + return url; +} + +static UIImage *ORKImageForConsentSectionType(ORKConsentSectionType type) { + NSString *imageName = [NSString stringWithFormat:@"consent_%02ld", (long)type]; + return [UIImage imageNamed:imageName inBundle:ORKBundle() compatibleWithTraitCollection:nil]; +} + +// Copied from CFXMLParser.c in http://www.opensource.apple.com/source/CF/CF-550.13/CFXMLParser.c +/* + At the very least we need to do <, >, &, ", and '. In addition, we'll have to do everything else in the string. + We should also be handling items that are up over certain values correctly. + */ +static CFStringRef CFXMLCreateStringByEscapingEntities(CFAllocatorRef allocator, CFStringRef string, CFDictionaryRef entitiesDictionary) { + //CFAssert1(string != NULL, __kCFLogAssertion, "%s(): NULL string not permitted.", __PRETTY_FUNCTION__); + CFMutableStringRef newString = CFStringCreateMutable(allocator, 0); // unbounded mutable string + CFMutableCharacterSetRef startChars = CFCharacterSetCreateMutable(allocator); + + CFStringInlineBuffer inlineBuf; + CFIndex idx = 0; + CFIndex mark = idx; + CFIndex stringLength = CFStringGetLength(string); + UniChar uc; + + CFCharacterSetAddCharactersInString(startChars, CFSTR("&<>'\"")); + + CFStringInitInlineBuffer(string, &inlineBuf, CFRangeMake(0, stringLength)); + for(idx = 0; idx < stringLength; idx++) { + uc = CFStringGetCharacterFromInlineBuffer(&inlineBuf, idx); + if (CFCharacterSetIsCharacterMember(startChars, uc)) { + CFStringRef previousSubstring = CFStringCreateWithSubstring(allocator, string, CFRangeMake(mark, idx - mark)); + CFStringAppend(newString, previousSubstring); + CFRelease(previousSubstring); + switch(uc) { + case '&': + CFStringAppend(newString, CFSTR("&")); + break; + case '<': + CFStringAppend(newString, CFSTR("<")); + break; + case '>': + CFStringAppend(newString, CFSTR(">")); + break; + case '\'': + CFStringAppend(newString, CFSTR("'")); + break; + case '"': + CFStringAppend(newString, CFSTR(""")); + break; + } + mark = idx + 1; + } + } + // Copy the remainder to the output string before returning. + CFStringRef remainder = CFStringCreateWithSubstring(allocator, string, CFRangeMake(mark, idx - mark)); + if (NULL != remainder) { + CFStringAppend(newString, remainder); + CFRelease(remainder); + } + CFRelease(startChars); + return newString; +} + + +@implementation ORKConsentSection { + NSString *_escapedContent; +} + +static NSString *localizedTitleForConsentSectionType(ORKConsentSectionType sectionType) { + NSString *str = nil; + switch (sectionType) { + case ORKConsentSectionTypeOverview: + str = ORKLocalizedString(@"CONSENT_SECTION_WELCOME", nil); + break; + case ORKConsentSectionTypeDataGathering: + str = ORKLocalizedString(@"CONSENT_SECTION_DATA_GATHERING", nil); + break; + case ORKConsentSectionTypePrivacy: + str = ORKLocalizedString(@"CONSENT_SECTION_PRIVACY", nil); + break; + case ORKConsentSectionTypeDataUse: + str = ORKLocalizedString(@"CONSENT_SECTION_DATA_USE", nil); + break; + case ORKConsentSectionTypeTimeCommitment: + str = ORKLocalizedString(@"CONSENT_SECTION_TIME_COMMITMENT", nil); + break; + case ORKConsentSectionTypeStudySurvey: + str = ORKLocalizedString(@"CONSENT_SECTION_STUDY_SURVEY", nil); + break; + case ORKConsentSectionTypeStudyTasks: + str = ORKLocalizedString(@"CONSENT_SECTION_STUDY_TASKS", nil); + break; + case ORKConsentSectionTypeWithdrawing: + str = ORKLocalizedString(@"CONSENT_SECTION_WITHDRAWING", nil); + break; + case ORKConsentSectionTypeOnlyInDocument: + case ORKConsentSectionTypeCustom: + break; + } + return str; +} + +- (instancetype)initWithType:(ORKConsentSectionType)type { + self = [super init]; + if (self) { + _type = type; + _title = localizedTitleForConsentSectionType(type); + _summary = nil; + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (void)setContent:(NSString *)content { + _content = content; + _escapedContent = nil; +} + +- (NSString *)escapedContent { + if (_content == nil || _content.length == 0) { + return _content; + } + + if (_escapedContent == nil) { + _escapedContent = (__bridge NSString *)(CFXMLCreateStringByEscapingEntities(NULL, (__bridge CFStringRef)(_content), NULL)); + + // Use
to replace "\n" + _escapedContent = [_escapedContent stringByReplacingOccurrencesOfString:@"\n" withString:@"
"]; + } + return _escapedContent; +} + +- (UIImage *)image { + UIImage *image = nil; + if (_type == ORKConsentSectionTypeCustom) { + image = _customImage; + } else { + image = ORKImageForConsentSectionType(_type); + } + return image; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_ENUM(aDecoder, type); + ORK_DECODE_OBJ_CLASS(aDecoder, title, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, summary, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, content, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, htmlContent, NSString); + ORK_DECODE_URL(aDecoder, contentURL); + ORK_DECODE_BOOL(aDecoder, omitFromDocument); + ORK_DECODE_OBJ_CLASS(aDecoder, formalTitle, NSString); + ORK_DECODE_IMAGE(aDecoder, customImage); + ORK_DECODE_URL(aDecoder, customAnimationURL); + ORK_DECODE_OBJ_CLASS(aDecoder, customLearnMoreButtonTitle, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_ENUM(aCoder, type); + ORK_ENCODE_OBJ(aCoder, title); + ORK_ENCODE_OBJ(aCoder, formalTitle); + ORK_ENCODE_OBJ(aCoder, summary); + ORK_ENCODE_OBJ(aCoder, content); + ORK_ENCODE_OBJ(aCoder, htmlContent); + ORK_ENCODE_URL(aCoder, contentURL); + ORK_ENCODE_BOOL(aCoder, omitFromDocument); + ORK_ENCODE_IMAGE(aCoder, customImage); + ORK_ENCODE_URL(aCoder, customAnimationURL); + ORK_ENCODE_OBJ(aCoder, customLearnMoreButtonTitle); +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.title, castObject.title) + && ORKEqualObjects(self.formalTitle, castObject.formalTitle) + && ORKEqualObjects(self.summary, castObject.summary) + && ORKEqualObjects(self.content, castObject.content) + && ORKEqualObjects(self.htmlContent, castObject.htmlContent) + && ORKEqualFileURLs(self.contentURL, castObject.contentURL) + && (self.omitFromDocument == castObject.omitFromDocument) + && ORKEqualObjects(self.customImage, castObject.customImage) + && ORKEqualObjects(self.customLearnMoreButtonTitle, castObject.customLearnMoreButtonTitle) + && ORKEqualFileURLs(self.customAnimationURL, castObject.customAnimationURL) && + (self.type == castObject.type)); +} + +- (NSUInteger)hash { + return _title.hash ^ _type; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentSection *sec = [[[self class] allocWithZone:zone] init]; + sec.title = _title; + sec.formalTitle = _formalTitle; + sec.summary = _summary; + sec.content = _content; + sec.htmlContent = _htmlContent; + sec.contentURL = _contentURL; + sec.omitFromDocument = _omitFromDocument; + sec.customImage = _customImage; + sec->_type = _type; + sec.customAnimationURL = _customAnimationURL; + sec.customLearnMoreButtonTitle = _customLearnMoreButtonTitle; + + return sec; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.h new file mode 100755 index 0000000..fb03bab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentSection; + +@interface ORKConsentSectionFormatter : NSObject + +- (NSString *)HTMLForSection:(ORKConsentSection *)section; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.m new file mode 100755 index 0000000..9ef4841 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSectionFormatter.m @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSectionFormatter.h" + +#import "ORKConsentSection_Private.h" + + +@implementation ORKConsentSectionFormatter + +- (NSString *)HTMLForSection:(ORKConsentSection *)section { + NSString *title = section.formalTitle ?: (section.title ?: @""); + NSString *content = section.htmlContent ?: (section.escapedContent ?: @""); + return [NSString stringWithFormat:@"

%@

%@

", title, content]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection_Private.h new file mode 100755 index 0000000..0fb6388 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSection_Private.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +NSURL *ORKMovieURLForConsentSectionType(ORKConsentSectionType type); + +@interface ORKConsentSection () + +@property (nonatomic, readonly, nullable) NSString *escapedContent; + +@property (nonatomic, readonly, nullable) UIImage *image; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.h new file mode 100755 index 0000000..f95ab34 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.h @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKConsentSharingStep` class represents a question step that includes prepopulated content that asks users about how much they're willing to allow + data to be shared after collection. + + To use the consent sharing step, include it in a task and present that task + with a task view controller. It's easy to incorporate a consent sharing step into the review flow, because it provides default content for its title, text, and answer format. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentSharingStep : ORKQuestionStep + +/** + Returns an initialized consent sharing step using the specified title, text, and answer format. + + @param identifier The identifier of the step. + @param investigatorShortDescription A short description of the investigator in a localized string. For example, "Stanford Medicine" or "American Heart Association." + @param investigatorLongDescription An extended description of the investigator and partners in a localized string. For example, "Stanford and its partners." + @param localizedLearnMoreHTMLContent The HTML content to display when the user + taps the Learn More button. + + @return An initialized consent sharing step. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + investigatorShortDescription:(NSString *)investigatorShortDescription + investigatorLongDescription:(NSString *)investigatorLongDescription + localizedLearnMoreHTMLContent:(NSString *)localizedLearnMoreHTMLContent; + +/// Localized HTML content to present in the Learn More section for the step. +@property (nonatomic, copy) NSString *localizedLearnMoreHTMLContent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.m new file mode 100755 index 0000000..e51131f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStep.m @@ -0,0 +1,114 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSharingStep.h" + +#import "ORKConsentSharingStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKAnswerFormat.h" +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentSharingStep + ++ (Class)stepViewControllerClass { + return [ORKConsentSharingStepViewController class]; +} + +- (BOOL)useSurveyMode { + return NO; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + investigatorShortDescription:(NSString *)investigatorShortDescription + investigatorLongDescription:(NSString *)investigatorLongDescription + localizedLearnMoreHTMLContent:(NSString *)localizedLearnMoreHTMLContent { + self = [super initWithIdentifier:identifier]; + if (self) { + if ( investigatorShortDescription.length == 0 ) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"investigatorShortDescription should not be empty." userInfo:nil]; + } + if ( investigatorLongDescription.length == 0 ) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"investigatorLongDescription should not be empty." userInfo:nil]; + } + if ( localizedLearnMoreHTMLContent.length == 0 ) { + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"localizedLearnMoreHTMLContent should not be empty." userInfo:nil]; + } + + self.answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices: + @[[ORKTextChoice choiceWithText:[NSString localizedStringWithFormat:ORKLocalizedString(@"CONSENT_SHARE_WIDELY_%@", nil), investigatorShortDescription] value:@(YES)], + [ORKTextChoice choiceWithText:[NSString localizedStringWithFormat:ORKLocalizedString(@"CONSENT_SHARE_ONLY_%@", nil), investigatorLongDescription] value:@(NO)], + ]]; + self.optional = NO; + self.useSurveyMode = NO; + self.title = ORKLocalizedString(@"CONSENT_SHARING_TITLE", nil); + self.text = [NSString localizedStringWithFormat:ORKLocalizedString(@"CONSENT_SHARING_DESCRIPTION_%@", nil), investigatorLongDescription]; + self.showsProgress = NO; + self.localizedLearnMoreHTMLContent = localizedLearnMoreHTMLContent; + } + return self; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return isParentSame && + ORKEqualObjects(self.localizedLearnMoreHTMLContent, castObject.localizedLearnMoreHTMLContent); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentSharingStep *step = [super copyWithZone:zone]; + step.localizedLearnMoreHTMLContent = self.localizedLearnMoreHTMLContent; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, localizedLearnMoreHTMLContent, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + ORK_ENCODE_OBJ(aCoder, localizedLearnMoreHTMLContent); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.h new file mode 100755 index 0000000..4447ea6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKConsentSharingStepViewController` class is a view controller subclass + used to manage a consent sharing step (`ORKConsentSharingStep`). + + You should not need to instantiate a consent sharing step view controller directly. Instead, include + a consent sharing step in a task, and present a task view controller for that + task. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentSharingStepViewController : ORKQuestionStepViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.m new file mode 100755 index 0000000..7ff68c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSharingStepViewController.m @@ -0,0 +1,67 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSharingStepViewController.h" + +#import "ORKConsentLearnMoreViewController.h" + +#import "ORKConsentSharingStep.h" +#import "ORKStepViewController_Internal.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentSharingStepViewController + +- (instancetype)initWithStep:(ORKStep *)step { + self = [super initWithStep:step]; + if (self) { + [super setLearnMoreButtonItem:[[UIBarButtonItem alloc] initWithTitle:ORKLocalizedString(@"LEARN_MORE_CONSENT_SHARING", nil) style:UIBarButtonItemStylePlain target:self action:@selector(consentLearnMoreAction:)]]; + } + return self; +} + +- (void)setLearnMoreButtonItem:(UIBarButtonItem *)learnMoreButtonItem { + // Override to ignore, so we keep our "private" learn more button item + return; +} + +- (void)consentLearnMoreAction:(id)sender { + ORKConsentSharingStep *step = (ORKConsentSharingStep *)self.step; + + ORKConsentLearnMoreViewController *viewController = [[ORKConsentLearnMoreViewController alloc] initWithHTMLContent:step.localizedLearnMoreHTMLContent]; + viewController.title = ORKLocalizedString(@"CONSENT_LEARN_MORE_TITLE", nil); + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + navigationController.modalPresentationStyle = UIModalPresentationFormSheet; + [self presentViewController:navigationController animated:YES completion:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.h new file mode 100755 index 0000000..5b30f1b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.h @@ -0,0 +1,149 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKConsentSignature` class represents a signature in as `ORKConsentDocument` object. + The signature can be that of an investigator, possibly prefilled with + an image, date, and first and last name; or you might need to collect the details of a signature. + + Signatures can be collected in a consent review step (`ORKConsentReviewStep`). After a signature has + been obtained (which produces an `ORKConsentSignatureResult` object), the resulting signature + can be substituted into a copy of the document, and used when generating a PDF. + + Alternatively, the details of a signature can be uploaded to a server + for PDF generation elsewhere or simply as a record of having obtained consent. + + The signature object has no concept of a cryptographic signature -- it is merely + a record of any input the user made during a consent review step. Also, an `ORKConsentSignature` object + does not verify or vouch for user identity. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentSignature : NSObject + +/// @name Factory methods + +/** + Returns a fully populated signature. + + Use this factory method when you need to prepopulate the investigator's signature in a generated consent document. + + @param title The title of the signatory. + @param dateFormatString The format string to use when formatting the date of signature. + @param identifier The identifier of the signature, unique within this document. + @param givenName The given name of the signatory. + @param familyName The family name of the signatory. + @param signatureImage An image of the signature. + @param signatureDate The date on which the signature was obtained, represented as a string. + */ ++ (ORKConsentSignature *)signatureForPersonWithTitle:(nullable NSString *)title + dateFormatString:(nullable NSString *)dateFormatString + identifier:(NSString *)identifier + givenName:(nullable NSString *)givenName + familyName:(nullable NSString *)familyName + signatureImage:(nullable UIImage *)signatureImage + dateString:(nullable NSString *)signatureDate; + +/** + Returns a signature to be collected. + + Use this factory method when representing a request to collect a signature for a consent review step. + + @param title The title of the signatory. + @param dateFormatString The format string to use when formatting the date of signature. + @param identifier The identifier of the signature, unique within this document. + */ ++ (ORKConsentSignature *)signatureForPersonWithTitle:(nullable NSString *)title + dateFormatString:(nullable NSString *)dateFormatString + identifier:(NSString *)identifier; + +/// @name Consent review configuration + +/** + A Boolean value indicating whether the user needs to enter their name during consent review. + + The default value of this property is `YES`. In a consent review step, the name entry screen is not displayed when the value of this property is `NO`. + */ +@property (nonatomic, assign) BOOL requiresName; + +/** + A Boolean value indicating whether the user needs to draw a signature during consent review. + + The default value of this property is `YES`. In a consent review step, the signature entry + screen is not shown when this property is `NO`. + */ +@property (nonatomic, assign) BOOL requiresSignatureImage; + +/// @name Identifying signatories + +/** + The identifier for this signature. + + The identifier should be unique in the document. It can be used to find or + replace a specific signature in an `ORKConsentDocument` object. The identifier is also reproduced in + the `ORKConsentSignatureResult` object produced by an `ORKConsentReviewStep` object. + */ +@property (nonatomic, copy) NSString *identifier; + +/// @name Personal information. + +/// The title of the signatory. +@property (nonatomic, copy, nullable) NSString *title; + +/// The given name (first name in Western languages) +@property (nonatomic, copy, nullable) NSString *givenName; + +/// The family name (last name in Western languages) +@property (nonatomic, copy, nullable) NSString *familyName; + +/// The image of the signature, if any. +@property (nonatomic, copy, nullable) UIImage *signatureImage; + +/// The date associated with the signature. +@property (nonatomic, copy, nullable) NSString *signatureDate; + +/** + The date format string to be used when producing a date string for the PDF + or consent review. + + For example, @"yyyy-MM-dd 'at' HH:mm". When the value of this property is `nil`, + the current date and time for the current locale is used. + */ +@property (nonatomic, copy, nullable) NSString *signatureDateFormatString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.m new file mode 100755 index 0000000..7420c35 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignature.m @@ -0,0 +1,148 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSignature.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentSignature + ++ (ORKConsentSignature *)signatureForPersonWithTitle:(NSString *)title + dateFormatString:(NSString *)dateFormatString + identifier:(NSString *)identifier + givenName:(NSString *)givenName + familyName:(NSString *)familyName + signatureImage:(UIImage *)signatureImage + dateString:(NSString *)signatureDate { + ORKConsentSignature *sig = [ORKConsentSignature new]; + sig.title = title; + sig.givenName = givenName; + sig.familyName = familyName; + sig.signatureImage = signatureImage; + sig.signatureDate = signatureDate; + sig.identifier = identifier; + sig.signatureDateFormatString = dateFormatString; + + return sig; +} + ++ (ORKConsentSignature *)signatureForPersonWithTitle:(NSString *)title + dateFormatString:(NSString *)dateFormatString + identifier:(NSString *)identifier { + ORKConsentSignature *sig = [ORKConsentSignature signatureForPersonWithTitle:title dateFormatString:dateFormatString identifier:identifier givenName:nil familyName:nil signatureImage:nil dateString:nil ]; + return sig; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _requiresName = YES; + _requiresSignatureImage = YES; + self.identifier = [NSUUID UUID].UUIDString; + } + return self; +} + +- (void)setIdentifier:(NSString *)identifier { + ORKThrowInvalidArgumentExceptionIfNil(identifier); + + _identifier = identifier; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super init]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, identifier, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, title, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, givenName, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, familyName, NSString); + ORK_DECODE_OBJ_CLASS(aDecoder, signatureDate, NSString); + ORK_DECODE_BOOL(aDecoder, requiresName); + ORK_DECODE_BOOL(aDecoder, requiresSignatureImage); + ORK_DECODE_IMAGE(aDecoder, signatureImage); + ORK_DECODE_OBJ_CLASS(aDecoder, signatureDateFormatString, NSString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + ORK_ENCODE_OBJ(aCoder, identifier); + ORK_ENCODE_OBJ(aCoder, title); + ORK_ENCODE_OBJ(aCoder, givenName); + ORK_ENCODE_OBJ(aCoder, familyName); + ORK_ENCODE_OBJ(aCoder, signatureDate); + ORK_ENCODE_BOOL(aCoder, requiresName); + ORK_ENCODE_BOOL(aCoder, requiresSignatureImage); + ORK_ENCODE_IMAGE(aCoder, signatureImage); + ORK_ENCODE_OBJ(aCoder, signatureDateFormatString); +} + +- (BOOL)isEqual:(id)object { + if ([self class] != [object class]) { + return NO; + } + + __typeof(self) castObject = object; + return (ORKEqualObjects(self.identifier, castObject.identifier) + && ORKEqualObjects(self.title, castObject.title) + && ORKEqualObjects(self.givenName, castObject.givenName) + && ORKEqualObjects(self.familyName, castObject.familyName) + && ORKEqualObjects(self.signatureDate, castObject.signatureDate) + && ORKEqualObjects(self.signatureImage, castObject.signatureImage) + && ORKEqualObjects(self.signatureDateFormatString, castObject.signatureDateFormatString) + && (self.requiresName == castObject.requiresName) + && (self.requiresSignatureImage == castObject.requiresSignatureImage)); +} + +- (NSUInteger)hash { + return _identifier.hash ^ _title.hash ^ _givenName.hash ^ _familyName.hash ^ _signatureDate.hash; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentSignature *sig = [[[self class] allocWithZone:zone] init]; + sig.identifier = [_identifier copy]; + sig.title = [_title copy]; + sig.givenName = [_givenName copy]; + sig.familyName = [_familyName copy]; + sig->_requiresName = _requiresName; + sig->_requiresSignatureImage = _requiresSignatureImage; + sig.signatureImage = _signatureImage; + sig.signatureDateFormatString = [_signatureDateFormatString copy]; + sig.signatureDate = [_signatureDate copy]; + return sig; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.h new file mode 100755 index 0000000..53c2288 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.h @@ -0,0 +1,46 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import "ORKDefines.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentSignature; + +@interface ORKConsentSignatureFormatter : NSObject + +- (NSString *)HTMLForSignature:(ORKConsentSignature *)signature; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.m new file mode 100755 index 0000000..5c117be --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureFormatter.m @@ -0,0 +1,112 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSignatureFormatter.h" + +#import "ORKConsentSignature.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentSignatureFormatter + +- (NSString *)HTMLForSignature:(ORKConsentSignature *)signature { + NSMutableString *body = [NSMutableString new]; + + NSString *hr = @"
"; + + NSString *signatureElementWrapper = @"


%@
%@%@

"; + NSString *signatureImageWrapper = @"


%@
%@%@

"; + + BOOL addedSig = NO; + + NSMutableArray *signatureElements = [NSMutableArray array]; + + if (signature.title == nil) { + @throw [NSException exceptionWithName:NSObjectNotAvailableException reason:@"Signature title is missing" userInfo:nil]; + } + + // Signature + + if (signature.requiresSignatureImage || signature.signatureImage) { + addedSig = YES; + NSString *imageTag = nil; + + if (signature.signatureImage) { + NSString *base64 = [UIImagePNGRepresentation(signature.signatureImage) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; + imageTag = [NSString stringWithFormat:@"star", base64]; + } else { + [body appendString:@"
"]; + } + + [signatureElements addObject:[NSString stringWithFormat:signatureImageWrapper, imageTag ? : @" ", hr, ORKLocalizedString(@"CONSENT_DOC_LINE_SIGNATURE", nil)]]; + } + + if (signature.requiresName || signature.familyName || signature.givenName) { + addedSig = YES; + NSString *nameStr = @" "; + if (signature.familyName || signature.givenName) { + NSMutableArray *names = [NSMutableArray array]; + if (signature.givenName) { + [names addObject:signature.givenName]; + } + if (signature.familyName) { + [names addObject:signature.familyName]; + } + if (ORKCurrentLocalePresentsFamilyNameFirst()) { + names = [[[names reverseObjectEnumerator] allObjects] mutableCopy]; + } + nameStr = [names componentsJoinedByString:@" "]; + } + + [signatureElements addObject:[NSString stringWithFormat:signatureElementWrapper, nameStr, hr, ORKLocalizedString(@"CONSENT_DOC_LINE_PRINTED_NAME", nil)]]; + } + + if (addedSig) { + [signatureElements addObject:[NSString stringWithFormat:signatureElementWrapper, signature.signatureDate ? : @" ", hr, ORKLocalizedString(@"CONSENT_DOC_LINE_DATE", nil)]]; + } + + NSInteger numElements = signatureElements.count; + if (numElements > 1) { + [body appendString:[NSString stringWithFormat:@"
"]]; + for (NSString *element in signatureElements) { + [body appendString:[NSString stringWithFormat:@"
%@
",element]]; + } + + [body appendString:@"
"]; + } else if (numElements == 1) { + [body appendString:[NSString stringWithFormat:@"
%@
",signatureElements.lastObject]]; + } + return body; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.h new file mode 100755 index 0000000..bc38d0d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentSignature; +@class ORKConsentDocument; + +/** + The `ORKConsentSignatureResult` class represents a signature obtained during + a consent review step (`ORKConsentReviewStep`). The consent signature result is usually found as a child result of the + `ORKStepResult` object for the consent review step. + + You can apply the result to a document to facilitate the generation of a + PDF including the signature, or for presentation in a follow-on + consent review. + + A consent signature result is typically generated by the framework as the task proceeds. When the task + completes, it may be appropriate to serialize it for transmission to a server, + or to immediately perform analysis on it. + */ +ORK_CLASS_AVAILABLE +@interface ORKConsentSignatureResult : ORKResult + +/** + A copy of the signature obtained. + + The signature is a copy of the `signature` property in the originating + `ORKConsentReviewStep` object, but also includes any name or signature image collected during + the consent review step. + */ +@property (nonatomic, copy, nullable) ORKConsentSignature *signature; + +/** + A boolean value indicating whether the participant consented. + + `YES` if the user confirmed consent to the contents of the consent review. Note + that the signature could still be invalid if the name or signature image is + empty; this indicates only that the user gave a positive acknowledgement of the + document. + */ +@property (nonatomic, assign) BOOL consented; + +/** + Applies the signature to the consent document. + + This method uses the identifier to look up the matching signature placeholder + in the consent document and replaces it with this signature. It may throw an exception if + the document does not contain a signature with a matching identifier. + + @param document The document to which to apply the signature. + */ +- (void)applyToDocument:(ORKConsentDocument *)document; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.m new file mode 100755 index 0000000..754bcaf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKConsentSignatureResult.m @@ -0,0 +1,105 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKConsentSignatureResult.h" + +#import "ORKConsentDocument.h" +#import "ORKConsentSignature.h" + +#import "ORKResult_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKConsentSignatureResult + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, signature); + ORK_ENCODE_BOOL(aCoder, consented); +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, signature, ORKConsentSignature); + ORK_DECODE_BOOL(aDecoder, consented); + } + return self; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKConsentSignatureResult *result = [super copyWithZone:zone]; + result.signature = _signature; + result.consented = _consented; + return result; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.signature, castObject.signature) && + (self.consented == castObject.consented)); +} + +- (NSUInteger)hash { + return super.hash ^ self.signature.hash; +} + +- (void)applyToDocument:(ORKConsentDocument *)document { + __block NSUInteger indexToBeReplaced = NSNotFound; + [[document signatures] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKConsentSignature *signature = obj; + if ([signature.identifier isEqualToString:self.signature.identifier]) { + indexToBeReplaced = idx; + *stop = YES; + } + }]; + + if (indexToBeReplaced != NSNotFound) { + NSMutableArray *signatures = [[document signatures] mutableCopy]; + signatures[indexToBeReplaced] = [_signature copy]; + document.signatures = signatures; + } +} + +- (NSString *)descriptionWithNumberOfPaddingSpaces:(NSUInteger)numberOfPaddingSpaces { + return [NSString stringWithFormat:@"%@; signature: %@; consented: %d%@", [self descriptionPrefixWithNumberOfPaddingSpaces:numberOfPaddingSpaces], self.signature, self.consented, self.descriptionSuffix]; +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.h new file mode 100755 index 0000000..edec810 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.h @@ -0,0 +1,47 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKEAGLMoviePlayerView : UIView + +@property (nonatomic) CGSize presentationSize; + +- (void)setupGL; +- (BOOL)consumePixelBuffer:(CVPixelBufferRef)pixelBuffer; +- (void)render; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.m new file mode 100755 index 0000000..fa2f526 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKEAGLMoviePlayerView.m @@ -0,0 +1,734 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKEAGLMoviePlayerView.h" + +#import "ORKHelpers_Internal.h" + +@import AVFoundation; +@import OpenGLES; +@import QuartzCore; + + +// Uniform index. +enum { + UNIFORM_Y, + UNIFORM_UV, + UNIFORM_ROTATION_ANGLE, + UNIFORM_COLOR_CONVERSION_MATRIX, + UNIFORM_TINT_COLOR, + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum { + ATTRIB_VERTEX, + ATTRIB_TEXCOORD, + NUM_ATTRIBUTES +}; + +// Color Conversion Constants (YUV to RGB) including adjustment from 16-235/16-240 (video range) + +// BT.601, which is the standard for SDTV. +static const GLfloat ColorConversion601[] = { + 1.164, 1.164, 1.164, + 0.0, -0.392, 2.017, + 1.596, -0.813, 0.0, +}; + +// BT.709, which is the standard for HDTV. +static const GLfloat ColorConversion709[] = { + 1.164, 1.164, 1.164, + 0.0, -0.213, 2.112, + 1.793, -0.533, 0.0, +}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#if defined(DEBUG) + static void ORKCheckForGLError() + { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + { + ORK_Log_Error("glError: 0x%04X", error); + } + } +#else + #define ORKCheckForGLError(...) +#endif +#pragma GCC diagnostic pop + +#define ORKEAGLLog(...) + +@interface ORKEAGLMoviePlayerView () { + // The pixel dimensions of the CAEAGLLayer. + GLint _backingWidth; + GLint _backingHeight; + + EAGLContext *_context; + NSMutableArray *_contextStack; + CVOpenGLESTextureRef _lumaTexture; + CVOpenGLESTextureRef _chromaTexture; + CVOpenGLESTextureCacheRef _videoTextureCache; + + GLuint _programHandle; + GLuint _vertexArrayHandle; + GLuint _vertexBufferHandle; + GLuint _frameBufferHandle; + GLuint _colorBufferHandle; + + BOOL _glIsSetup; +} + +@property (nonatomic) const GLfloat *preferredConversion; + +- (void)setupBuffers; +- (void)cleanUpTextures; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type URL:(NSURL *)URL; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; + +@end + + +@implementation ORKEAGLMoviePlayerView + +const GLfloat DefaultPreferredRotation = 0; + ++ (Class)layerClass { + return [CAEAGLLayer class]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + // Use 2x scale factor on Retina displays. + self.contentScaleFactor = [UIScreen mainScreen].scale; + + self.backgroundColor = [UIColor whiteColor]; + + // Get and configure the layer. + CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; + + eaglLayer.opaque = YES; + eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking : @YES, + kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8}; + + // Set the context into which the frames will be drawn. + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!_context || ![self loadShaders]) { + return nil; + } + + _preferredConversion = NULL; + } + return self; +} + +# pragma mark - OpenGL setup + +- (void)setupGL { + if (_glIsSetup) { + return; + } + _glIsSetup = YES; + + [self saveGLContext]; + + glDisable(GL_DEPTH_TEST); + [self setupBuffers]; + + glUseProgram(_programHandle); + + // 0 and 1 are the texture IDs of _lumaTexture and _chromaTexture respectively. + glUniform1i(uniforms[UNIFORM_Y], 0); + glUniform1i(uniforms[UNIFORM_UV], 1); + [self updateTintColorUniform]; + glUniform1f(uniforms[UNIFORM_ROTATION_ANGLE], DefaultPreferredRotation); + // Set the default conversion to BT.709, which is the standard for HDTV. + _preferredConversion = ColorConversion709; + [self updatePreferredConversionUniform]; + glUniformMatrix3fv(uniforms[UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion); + + // Create CVOpenGLESTextureCacheRef for optimal CVPixelBufferRef to GLES texture conversion. + if (!_videoTextureCache) { + CVReturn error = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _context, NULL, &_videoTextureCache); + if (error != noErr) { + ORK_Log_Error("Error at CVOpenGLESTextureCacheCreate %d", error); + return; + } + } + + glGenVertexArraysOES(1, &_vertexArrayHandle); + glGenBuffers(1, &_vertexBufferHandle); + + [self restoreGLContext]; + ORKEAGLLog(@""); +} + +#pragma mark - Utilities + +- (void)setupBuffers { + if (!_glIsSetup) { + return; + } + + [self saveGLContext]; + + [self deleteBuffers]; + + glGenFramebuffers(1, &_frameBufferHandle); + glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle); + + glGenRenderbuffers(1, &_colorBufferHandle); + glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle); + + [_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer]; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorBufferHandle); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + ORK_Log_Error("Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); + } + + // Set the view port to the entire view. + glViewport(0, 0, _backingWidth, _backingHeight); + + [self restoreGLContext]; + ORKEAGLLog(@""); +} + +- (void)deleteBuffers { + [self saveGLContext]; + + if (_frameBufferHandle) { + glDeleteFramebuffers(1, &_frameBufferHandle); + _frameBufferHandle = 0; + } + if (_colorBufferHandle) { + glDeleteRenderbuffers(1, &_colorBufferHandle); + _colorBufferHandle = 0; + } + + [self restoreGLContext]; +} + +- (void)cleanUpTextures { + [self saveGLContext]; + + if (_lumaTexture) { + CFRelease(_lumaTexture); + _lumaTexture = NULL; + } + + if (_chromaTexture) { + CFRelease(_chromaTexture); + _chromaTexture = NULL; + } + + // Periodic texture cache flush every frame + CVOpenGLESTextureCacheFlush(_videoTextureCache, 0); + + [self restoreGLContext]; +} + +- (BOOL)saveGLContext { + BOOL success = YES; + + if (_contextStack == nil) { + _contextStack = [NSMutableArray new]; + } + + EAGLContext *currentContext = [EAGLContext currentContext]; + + // Switch context only when necessary + if (_context != currentContext) { + glFlush(); + success = [EAGLContext setCurrentContext:_context]; + } + + // Always push + [_contextStack addObject:currentContext ? : [NSNull null]]; + + return success; +} + +- (BOOL)restoreGLContext { + BOOL success = YES; + + id lastObject = [_contextStack lastObject]; + + if (lastObject) { + EAGLContext *contextToBeRestored = (lastObject != [NSNull null]) ? lastObject : nil; + + // Switch context only when necessary + if (_context != contextToBeRestored) { + glFlush(); + success = [EAGLContext setCurrentContext:contextToBeRestored]; + } + } + + // Always pop + [_contextStack removeLastObject]; + + return success; +} + +- (void)dealloc { + ORKEAGLLog(@""); + + [self saveGLContext]; + + [self cleanUpTextures]; + + if (_videoTextureCache) { + CFRelease(_videoTextureCache); + } + [self deleteBuffers]; + if (_programHandle) { + glDeleteProgram(_programHandle); + _programHandle = 0; + } + + [self restoreGLContext]; +} + +- (void)setPresentationSize:(CGSize)presentationSize { + _presentationSize = presentationSize; + [self updateVertexAndTextureData]; +} + +- (void)setTintColor:(UIColor *)tintColor { + [super setTintColor:tintColor]; + [self updateTintColorUniform]; +} + +- (void)setPreferredConversion:(const GLfloat *)preferredConversion { + if (_preferredConversion != preferredConversion) { + _preferredConversion = preferredConversion; + [self updatePreferredConversionUniform]; + } +} + +- (void)layoutSubviews { + [super layoutSubviews]; + [self setupBuffers]; + [self updateVertexAndTextureData]; +} + +#pragma mark - OpenGLES drawing + +- (BOOL)consumePixelBuffer:(CVPixelBufferRef)pixelBuffer { + if (!_glIsSetup) { + return NO; + } + + CVReturn error; + if (pixelBuffer != NULL) { + ORKEAGLLog(@"Have buffer"); + + if (!_videoTextureCache) { + ORK_Log_Error("No video texture cache"); + return NO; + } + + [self saveGLContext]; + + [self cleanUpTextures]; + + /* + Use the color attachment of the pixel buffer to determine the appropriate color conversion matrix. + */ + CFTypeRef colorAttachments = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL); + + if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_601_4) { + self.preferredConversion = ColorConversion601; + } else { + self.preferredConversion = ColorConversion709; + } + + /* + CVOpenGLESTextureCacheCreateTextureFromImage will create GLES texture optimally from CVPixelBufferRef. + */ + + /* + Create Y and UV textures from the pixel buffer. These textures will be drawn on the frame buffer Y-plane. + */ + error = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + _videoTextureCache, + pixelBuffer, + NULL, + GL_TEXTURE_2D, + GL_RED_EXT, + (GLint)CVPixelBufferGetWidthOfPlane(pixelBuffer, 0), + (GLint)CVPixelBufferGetHeightOfPlane(pixelBuffer, 0), + GL_RED_EXT, + GL_UNSIGNED_BYTE, + 0, + &_lumaTexture); + if (0 == error) { + + glActiveTexture(GL_TEXTURE0); + glBindTexture(CVOpenGLESTextureGetTarget(_lumaTexture), CVOpenGLESTextureGetName(_lumaTexture)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // UV-plane. + error = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + _videoTextureCache, + pixelBuffer, + NULL, + GL_TEXTURE_2D, + GL_RG_EXT, + (GLint)CVPixelBufferGetWidthOfPlane(pixelBuffer, 1), + (GLint)CVPixelBufferGetHeightOfPlane(pixelBuffer, 1), + GL_RG_EXT, + GL_UNSIGNED_BYTE, + 1, + &_chromaTexture); + + if (0 == error) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(CVOpenGLESTextureGetTarget(_chromaTexture), CVOpenGLESTextureGetName(_chromaTexture)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + } + + [self restoreGLContext]; + + if (error) { + ORK_Log_Error("Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", error); + return NO; + } + + return YES; + } + return NO; +} + +- (void)updateVertexAndTextureData { + if (!_glIsSetup) { + return; + } + + // Set up the quad vertices with respect to the orientation and aspect ratio of the video. + CGRect vertexSamplingRect = AVMakeRectWithAspectRatioInsideRect(_presentationSize, self.layer.bounds); + ORKEAGLLog(@"%@", NSStringFromCGRect(vertexSamplingRect)); + + // Compute normalized quad coordinates to draw the frame into. + CGSize normalizedSamplingSize = CGSizeMake(0.0, 0.0); + CGSize cropScaleAmount = CGSizeMake(vertexSamplingRect.size.width/self.layer.bounds.size.width, vertexSamplingRect.size.height/self.layer.bounds.size.height); + + // Normalize the quad vertices. + if (cropScaleAmount.width > cropScaleAmount.height) { + normalizedSamplingSize.width = 1.0; + normalizedSamplingSize.height = cropScaleAmount.height/cropScaleAmount.width; + } else { + normalizedSamplingSize.height = 1.0; + normalizedSamplingSize.width = cropScaleAmount.width/cropScaleAmount.height; + } + + /* + The quad vertex data defines the region of 2D plane onto which we draw our pixel buffers. + Vertex data formed using (-1,-1) and (1,1) as the bottom left and top right coordinates respectively, covers the entire screen. + + The texture vertices are set up such that we flip the texture vertically. This is so that our top left origin buffers match OpenGL's bottom left texture coordinate system. + */ + CGRect textureSamplingRect = CGRectMake(0, 0, 1, 1); + + GLfloat quadVertexAndTextureData[] = { + // Vertex + -1 * normalizedSamplingSize.width, -1 * normalizedSamplingSize.height, + normalizedSamplingSize.width, -1 * normalizedSamplingSize.height, + -1 * normalizedSamplingSize.width, normalizedSamplingSize.height, + normalizedSamplingSize.width, normalizedSamplingSize.height, + // Texture + CGRectGetMinX(textureSamplingRect), CGRectGetMaxY(textureSamplingRect), + CGRectGetMaxX(textureSamplingRect), CGRectGetMaxY(textureSamplingRect), + CGRectGetMinX(textureSamplingRect), CGRectGetMinY(textureSamplingRect), + CGRectGetMaxX(textureSamplingRect), CGRectGetMinY(textureSamplingRect) + }; + + [self saveGLContext]; + + glBindVertexArrayOES(_vertexArrayHandle); + + glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferHandle); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertexAndTextureData), quadVertexAndTextureData, GL_STATIC_DRAW); + + // Set the position + glEnableVertexAttribArray(ATTRIB_VERTEX); + glEnableVertexAttribArray(ATTRIB_TEXCOORD); + glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0); + glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (void *)(8 * sizeof(GLfloat))); + + [self restoreGLContext]; +} + +- (void)updateTintColorUniform { + if (!_glIsSetup) { + return; + } + + [self saveGLContext]; + + CGFloat tintColorCG[4]; + [self.tintColor getRed:&tintColorCG[0] green:&tintColorCG[1] blue:&tintColorCG[2] alpha:&tintColorCG[3]]; + glUniform3f(uniforms[UNIFORM_TINT_COLOR], tintColorCG[0], tintColorCG[1], tintColorCG[2]); + + [self restoreGLContext]; +} + +- (void)updatePreferredConversionUniform { + if (!_glIsSetup) { + return; + } + [self saveGLContext]; + glUniformMatrix3fv(uniforms[UNIFORM_COLOR_CONVERSION_MATRIX], 1, GL_FALSE, _preferredConversion); + [self restoreGLContext]; +} + +- (void)render { + if (!_glIsSetup) { + return; + } + + [self saveGLContext]; + + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glBindFramebuffer(GL_FRAMEBUFFER, _frameBufferHandle); + + // Use the shader program and bin the VAO. + glUseProgram(_programHandle); + glBindVertexArrayOES(_vertexArrayHandle); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glBindRenderbuffer(GL_RENDERBUFFER, _colorBufferHandle); + if (![_context presentRenderbuffer:GL_RENDERBUFFER]) { + ORK_Log_Error("presentRenderBuffer failed"); + } + + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindVertexArrayOES(0); + glUseProgram(0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + [self restoreGLContext]; +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders { + + [self saveGLContext]; + + GLuint vertShader, fragShader; + NSURL *vertShaderURL, *fragShaderURL; + + // Create the shader program. + _programHandle = glCreateProgram(); + + [self restoreGLContext]; + + // Create and compile the vertex shader. + vertShaderURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MovieTintShader" withExtension:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER URL:vertShaderURL]) { + ORK_Log_Error("Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"MovieTintShader" withExtension:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER URL:fragShaderURL]) { + ORK_Log_Error("Failed to compile fragment shader"); + return NO; + } + + [self saveGLContext]; + + // Attach vertex shader to program. + glAttachShader(_programHandle, vertShader); + + // Attach fragment shader to program. + glAttachShader(_programHandle, fragShader); + + // Bind attribute locations. This needs to be done prior to linking. + glBindAttribLocation(_programHandle, ATTRIB_VERTEX, "position"); + glBindAttribLocation(_programHandle, ATTRIB_TEXCOORD, "texCoord"); + + // Link the program. + if (![self linkProgram:_programHandle]) { + ORK_Log_Error("Failed to link program: %d", _programHandle); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_programHandle) { + glDeleteProgram(_programHandle); + _programHandle = 0; + } + [self restoreGLContext]; + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_Y] = glGetUniformLocation(_programHandle, "SamplerY"); + uniforms[UNIFORM_UV] = glGetUniformLocation(_programHandle, "SamplerUV"); + uniforms[UNIFORM_ROTATION_ANGLE] = glGetUniformLocation(_programHandle, "preferredRotation"); + uniforms[UNIFORM_COLOR_CONVERSION_MATRIX] = glGetUniformLocation(_programHandle, "colorConversionMatrix"); + uniforms[UNIFORM_TINT_COLOR] = glGetUniformLocation(_programHandle, "tintColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_programHandle, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_programHandle, fragShader); + glDeleteShader(fragShader); + } + + [self restoreGLContext]; + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type URL:(NSURL *)URL { + NSError *error; + NSString *sourceString = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error]; + if (sourceString == nil) { + ORK_Log_Error("Failed to load vertex shader: %@", [error localizedDescription]); + return NO; + } + + [self saveGLContext]; + + GLint status; + const GLchar *source; + source = (GLchar *)[sourceString UTF8String]; + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + ORK_Log_Debug("Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + [self restoreGLContext]; + glDeleteShader(*shader); + return NO; + } + + [self restoreGLContext]; + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog { + [self saveGLContext]; + + GLint status; + glLinkProgram(prog); + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + ORK_Log_Debug("Program link log:\n%s", log); + free(log); + } +#endif + + [self restoreGLContext]; + + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog { + [self saveGLContext]; + + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + ORK_Log_Debug("Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + + [self restoreGLContext]; + + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.h new file mode 100755 index 0000000..f14c3af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.h @@ -0,0 +1,73 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKConsentDocument; + +/** + The `ORKVisualConsentStep` class represents a step in the visual consent sequence. + + To use a visual consent step, first create a consent document with at least one + section (at least one section must not be of type `ORKConsentSectionTypeOnlyInDocument`) and attach the document to a visual consent step. Put the visual consent step + into a ResearchKit task, and present it with a task view controller. + + In the ResearchKit framework, an `ORKVisualConsentStep` object is used to present a series of simple + graphics to help study participants understand the content of an informed + consent document. The default graphics include animated transitions. + The textual content you need to provide in the `consentDocument` property should relate to the specific study being run and should be localized. + + An `ORKVisualConsentStep` object produces an `ORKStepResult` object, in which the dates indicate the total amount of time participants have spent in the consent process, and the route by which they can exit the consent process. + */ +ORK_CLASS_AVAILABLE +@interface ORKVisualConsentStep : ORKStep + +/** + Returns an initialized visual consent step using the specified identifier and consent document. + + @param identifier The identifier of the visual consent step, unique within the document. + @param consentDocument The informed consent document. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier document:(nullable ORKConsentDocument *)consentDocument; + +/** + The consent document whose sections determine the order and appearance of scenes + in the visual consent step. + */ +@property (nonatomic, strong, nullable) ORKConsentDocument *consentDocument; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.m new file mode 100755 index 0000000..416c84d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStep.m @@ -0,0 +1,92 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVisualConsentStep.h" + +#import "ORKVisualConsentStepViewController.h" + +#import "ORKConsentDocument_Internal.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKVisualConsentStep + ++ (Class)stepViewControllerClass { + return [ORKVisualConsentStepViewController class]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier document:(ORKConsentDocument *)consentDocument { + self = [super initWithIdentifier:identifier]; + if (self) { + self.consentDocument = consentDocument; + self.showsProgress = NO; + } + return self; +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKVisualConsentStep *step = [super copyWithZone:zone]; + step.consentDocument = self.consentDocument; + return step; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ_CLASS(aDecoder, consentDocument, ORKConsentDocument); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, consentDocument); +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.consentDocument, castObject.consentDocument)); +} + +- (NSUInteger)hash { + return super.hash ^ self.consentDocument.hash; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.h new file mode 100755 index 0000000..efdb48f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKVisualConsentStepViewController` class is a view controller subclass + used to manage a visual consent step (`ORKVisualConsentStep`). + + You should not need to instantiate a visual consent step view controller directly. Instead, include + a visual consent step in a task, and present a task view controller for that + task. + */ +ORK_CLASS_AVAILABLE +@interface ORKVisualConsentStepViewController : ORKStepViewController + +/** + The view in which animations are displayed. + */ +@property (nonatomic, strong, nullable) UIView *animationView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.m new file mode 100755 index 0000000..d64225a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController.m @@ -0,0 +1,720 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVisualConsentStepViewController.h" + +#import "ORKContinueButton.h" +#import "ORKEAGLMoviePlayerView.h" +#import "ORKSignatureView.h" +#import "ORKTintedImageView_Internal.h" + +#import "ORKConsentSceneViewController_Internal.h" +#import "ORKVisualConsentTransitionAnimator.h" + +#import "ORKConsentDocument.h" +#import "ORKConsentSection_Private.h" +#import "ORKResult.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController_Internal.h" +#import "ORKVisualConsentStep.h" + +#import "ORKAccessibility.h" +#import "ORKHelpers_Internal.h" +#import "ORKObserver.h" +#import "ORKSkin.h" +#import "UIBarButtonItem+ORKBarButtonItem.h" + +#import +#import + + +@interface ORKVisualConsentStepViewController () { + BOOL _hasAppeared; + ORKStepViewControllerNavigationDirection _navigationDirection; + + ORKVisualConsentTransitionAnimator *_animator; + + NSArray *_visualSections; + + ORKScrollViewObserver *_scrollViewObserver; +} + +@property (nonatomic, strong) UIPageViewController *pageViewController; + +@property (nonatomic, strong) NSMutableDictionary *viewControllers; + +@property (nonatomic, strong) UIScrollView *scrollView; + +@property (nonatomic) NSUInteger currentPage; + +@property (nonatomic, strong) ORKContinueButton *continueActionButton; + +@property (nonatomic, strong) ORKBorderedButton *cancelActionButton; + +- (ORKConsentSceneViewController *)viewControllerForIndex:(NSUInteger)index; +- (NSUInteger)currentIndex; +- (NSUInteger)indexOfViewController:(UIViewController *)viewController; + +@end + + +@interface ORKAnimationPlaceholderView : UIView + +@property (nonatomic, strong) ORKEAGLMoviePlayerView *playerView; + +- (void)scrollToTopAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion; + +@end + + +@implementation ORKAnimationPlaceholderView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + _playerView = [ORKEAGLMoviePlayerView new]; + _playerView.hidden = YES; + [self addSubview:_playerView]; + } + return self; +} + +- (void)willMoveToWindow:(UIWindow *)newWindow { + [super willMoveToWindow:newWindow]; + + CGRect frame = self.frame; + frame.size.height = ORKGetMetricForWindow(ORKScreenMetricIllustrationHeight, newWindow); + self.frame = frame; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + + _playerView.frame = self.bounds; +} + +- (CGPoint)defaultFrameOrigin { + return (CGPoint){0, ORKGetMetricForWindow(ORKScreenMetricTopToIllustration, self.superview.window)}; +} + +- (void)scrollToTopAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion { + CGRect targetFrame = self.frame; + targetFrame.origin = [self defaultFrameOrigin]; + if (animated) { + [UIView animateWithDuration:ORKScrollToTopAnimationDuration + animations:^{ + self.frame = targetFrame; + } completion:completion]; + } else { + self.frame = targetFrame; + if (completion) { + completion(YES); + } + } +} + +@end + + +@implementation ORKVisualConsentStepViewController { + UIColor *_backgroundColor; +} + +- (void)dealloc { + [[ORKTintedImageCache sharedCache] removeAllObjects]; +} + +- (void)stepDidChange { + [super stepDidChange]; + _backgroundColor = [UIColor whiteColor]; + { + NSMutableArray *visualSections = [NSMutableArray new]; + + NSArray *sections = self.visualConsentStep.consentDocument.sections; + for (ORKConsentSection *scene in sections) { + if (scene.type != ORKConsentSectionTypeOnlyInDocument) { + [visualSections addObject:scene]; + } + } + _visualSections = [visualSections copy]; + } + + if (self.step && [self pageCount] == 0) { + @throw [NSException exceptionWithName:NSGenericException reason:@"Visual consent step has no visible scenes" userInfo:nil]; + } + + _viewControllers = nil; + + [self showViewController:[self viewControllerForIndex:0] forward:YES animated:NO]; +} + +- (ORKEAGLMoviePlayerView *)animationPlayerView { + return [(ORKAnimationPlaceholderView *)_animationView playerView]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Prepare pageViewController + _pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll + navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal + options:nil]; + //_pageViewController.dataSource = self; + _pageViewController.delegate = self; + + [self scrollView].bounces = NO; + + if ([_pageViewController respondsToSelector:@selector(edgesForExtendedLayout)]) { + _pageViewController.edgesForExtendedLayout = UIRectEdgeNone; + } + [self.view addSubview:_pageViewController.view]; + + [self addChildViewController:_pageViewController]; + [_pageViewController didMoveToParentViewController:self]; + + if (self.taskViewController.navigationBar) { + [self.taskViewController.navigationBar setBarTintColor:self.view.backgroundColor]; + } + _animationView.userInteractionEnabled = NO; + + [self updatePageIndex]; +} + +- (ORKVisualConsentStep *)visualConsentStep { + assert(!self.step || [self.step isKindOfClass:[ORKVisualConsentStep class]]); + return (ORKVisualConsentStep *)self.step; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + if (_pageViewController.viewControllers.count == 0) { + + _hasAppeared = YES; + + // Add first viewController + NSUInteger idx = 0; + if (_navigationDirection == ORKStepViewControllerNavigationDirectionReverse) { + idx = [self pageCount]-1; + } + + [self showViewController:[self viewControllerForIndex:idx] forward:YES animated:NO]; + } + [self updatePageIndex]; +} + +- (void)willNavigateDirection:(ORKStepViewControllerNavigationDirection)direction { + _navigationDirection = direction; +} + +- (UIBarButtonItem *)goToPreviousPageButton { + UIBarButtonItem *button = [UIBarButtonItem ork_backBarButtonItemWithTarget:self action:@selector(goToPreviousPage)]; + button.accessibilityLabel = ORKLocalizedString(@"AX_BUTTON_BACK", nil); + return button; +} + +- (void)updateBarButtonItems { + if ([self currentIndex] == 0) { + [super updateBarButtonItems]; + } else { + self.navigationItem.leftBarButtonItem = [self goToPreviousPageButton]; + } +} + +- (void)updateBackButton { + if (!_hasAppeared) { + return; + } + + [self updateBarButtonItems]; +} + +#pragma mark - actions + +- (IBAction)goToPreviousPage { + [self showViewController:[self viewControllerForIndex:[self currentIndex]-1] forward:NO animated:YES preloadNextConsentSectionImage:NO]; + UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil); +} + +- (IBAction)next { + ORKConsentSceneViewController *currentConsentSceneViewController = [self viewControllerForIndex:[self currentIndex]]; + [(ORKAnimationPlaceholderView *)_animationView scrollToTopAnimated:YES completion:nil]; + [currentConsentSceneViewController scrollToTopAnimated:YES completion:^(BOOL finished) { + if (finished) { + [self showNextViewController]; + } + }]; +} + +- (void)showNextViewController { + CGRect animationViewFrame = _animationView.frame; + animationViewFrame.origin = [ORKDynamicCast(_animationView, ORKAnimationPlaceholderView) defaultFrameOrigin]; + _animationView.frame = animationViewFrame; + ORKConsentSceneViewController *nextConsentSceneViewController = [self viewControllerForIndex:[self currentIndex] + 1]; + [(ORKAnimationPlaceholderView *)_animationView scrollToTopAnimated:NO completion:nil]; + [nextConsentSceneViewController scrollToTopAnimated:NO completion:^(BOOL finished) { + // 'finished' is always YES when not animated + [self showViewController:nextConsentSceneViewController forward:YES animated:YES]; + ORKAccessibilityPostNotificationAfterDelay(UIAccessibilityScreenChangedNotification, nil, 0.5); + }]; +} + +#pragma mark - internal + +- (UIScrollView *)scrollView { + if (_scrollView == nil) { + for (UIView *view in self.pageViewController.view.subviews) { + if ([view isKindOfClass:[UIScrollView class]]) { + _scrollView = (UIScrollView *)view; + break; + } + } + } + return _scrollView; +} + +- (void)updatePageIndex { + NSUInteger currentIndex = [self currentIndex]; + if (currentIndex == NSNotFound) { + return; + } + + _currentPage = currentIndex; + + [self updateBackButton]; + + ORKConsentSection *currentSection = (ORKConsentSection *)_visualSections[currentIndex]; + if (currentSection.type == ORKConsentSectionTypeOverview) { + _animationView.isAccessibilityElement = NO; + } else { + _animationView.isAccessibilityElement = YES; + _animationView.accessibilityLabel = [NSString stringWithFormat:ORKLocalizedString(@"AX_IMAGE_ILLUSTRATION", nil), currentSection.title]; + _animationView.accessibilityTraits |= UIAccessibilityTraitImage; + } +} + +- (void)setScrollEnabled:(BOOL)enabled { + [[self scrollView] setScrollEnabled:enabled]; +} + +- (NSArray *)visualSections { + return _visualSections; +} + +- (NSUInteger)pageCount { + return _visualSections.count; +} + +- (UIImageView *)findHairlineImageViewUnder:(UIView *)view { + if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) { + return (UIImageView *)view; + } + for (UIView *subview in view.subviews) { + UIImageView *imageView = [self findHairlineImageViewUnder:subview]; + if (imageView) { + return imageView; + } + } + return nil; +} + +- (void)doShowViewController:(ORKConsentSceneViewController *)viewController + direction:(UIPageViewControllerNavigationDirection)direction + animated:(BOOL)animated + completion:(void (^)(BOOL finished))completion { + UIView *pageViewControllerView = self.pageViewController.view; + pageViewControllerView.userInteractionEnabled = NO; + + if (!viewController || !self.pageViewController) { + if (completion) { + completion(NO); + } + return; + } + + ORKWeakTypeOf(self) weakSelf = self; + [self.pageViewController setViewControllers:@[viewController] direction:direction animated:animated completion:^(BOOL finished) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + pageViewControllerView.userInteractionEnabled = YES; + [strongSelf updatePageIndex]; + + if (completion != NULL) { + completion(finished); + } + }]; +} + +- (void)doAnimateFromViewController:(ORKConsentSceneViewController *)fromViewController + toController:(ORKConsentSceneViewController *)toViewController + direction:(UIPageViewControllerNavigationDirection)direction + url:(NSURL *)url + animateBeforeTransition:(BOOL)animateBeforeTransition + transitionBeforeAnimate:(BOOL)transitionBeforeAnimate + completion:(void (^)(BOOL finished))completion { + + NSAssert(url, @"url cannot be nil"); + NSAssert(!(animateBeforeTransition && transitionBeforeAnimate), @"Both flags cannot be set"); + + ORKWeakTypeOf(self) weakSelf = self; + void (^finishAndNilAnimator)(ORKVisualConsentTransitionAnimator *animator) = ^(ORKVisualConsentTransitionAnimator *animator) { + ORKStrongTypeOf(self) strongSelf = weakSelf; + [animator finish]; + if (strongSelf && strongSelf->_animator == animator) { + // Do not show images and hide animationPlayerView if it's not the current animator + fromViewController.imageHidden = NO; + toViewController.imageHidden = NO; + [strongSelf animationPlayerView].hidden = YES; + strongSelf->_animator = nil; + } + }; + + ORKVisualConsentTransitionAnimator *animator = [[ORKVisualConsentTransitionAnimator alloc] initWithVisualConsentStepViewController:self movieURL:url]; + _animator = animator; + + __block BOOL transitionFinished = NO; + __block BOOL animatorFinished = NO; + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + // The semaphore waits for both 'animateTransitionWithDirection:loadHandler:completionHandler:' and + // 'doShowViewController:direction:animated:completion:' methods to complete (both of these methods + // signal the semaphore on completion). It doesn't matter which of the two finishes first. + // Defensive 5-second timeout in case the animator doesn't complete. + BOOL semaphoreATimedOut = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5)); + BOOL semaphoreBTimedOut = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5)); + + if (semaphoreATimedOut || semaphoreBTimedOut) { + ORK_Log_Debug("[Semaphore timed out] semaphoreATimedOut: %d, semaphoreBTimedOut: %d, transitionFinished: %d, animatorFinished: %d", semaphoreATimedOut, semaphoreBTimedOut, transitionFinished, animatorFinished); + } + + dispatch_async(dispatch_get_main_queue(), ^{ + BOOL animationAndTransitionFinished = (transitionFinished && animatorFinished); + + if (!animatorFinished) { + finishAndNilAnimator(animator); + } + + if (completion) { + completion(animationAndTransitionFinished); + } + }); + }); + + if (!animateBeforeTransition && !transitionBeforeAnimate) { + [_animator animateTransitionWithDirection:direction + loadHandler:^(ORKVisualConsentTransitionAnimator *loadAnimator, UIPageViewControllerNavigationDirection loadDirection) { + + fromViewController.imageHidden = YES; + toViewController.imageHidden = YES; + + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf doShowViewController:toViewController + direction:loadDirection + animated:YES + completion:^(BOOL finished) { + + transitionFinished = finished; + dispatch_semaphore_signal(semaphore); + }]; + } + completionHandler:^(ORKVisualConsentTransitionAnimator *completedAnimator, UIPageViewControllerNavigationDirection completedDirection) { + + animatorFinished = YES; + finishAndNilAnimator(completedAnimator); + dispatch_semaphore_signal(semaphore); + }]; + + } else if (animateBeforeTransition && !transitionBeforeAnimate) { + [_animator animateTransitionWithDirection:direction + loadHandler:^(ORKVisualConsentTransitionAnimator *loadAnimator, UIPageViewControllerNavigationDirection loadDirection) { + + fromViewController.imageHidden = YES; + } + completionHandler:^(ORKVisualConsentTransitionAnimator *completedAnimator, UIPageViewControllerNavigationDirection completedDirection) { + + animatorFinished = YES; + finishAndNilAnimator(completedAnimator); + + ORKStrongTypeOf(self) strongSelf = weakSelf; + [strongSelf doShowViewController:toViewController + direction:completedDirection + animated:YES + completion:^(BOOL finished) { + + transitionFinished = finished; + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_signal(semaphore); + }]; + + } else if (!animateBeforeTransition && transitionBeforeAnimate) { + toViewController.imageHidden = YES; + [self doShowViewController:toViewController + direction:direction + animated:YES + completion:^(BOOL finished) { + + transitionFinished = finished; + + [_animator animateTransitionWithDirection:direction + loadHandler:nil + completionHandler:^(ORKVisualConsentTransitionAnimator *completedAnimator, UIPageViewControllerNavigationDirection completedDirection) { + + animatorFinished = YES; + finishAndNilAnimator(completedAnimator); + dispatch_semaphore_signal(semaphore); + }]; + + dispatch_semaphore_signal(semaphore); + }]; + } +} + +- (void)observedScrollViewDidScroll:(UIScrollView *)scrollView { + if (scrollView == _scrollViewObserver.target) { + CGRect animationViewFrame = _animationView.frame; + CGPoint scrollViewBoundsOrigin = scrollView.bounds.origin; + CGPoint defaultFrameOrigin = [ORKDynamicCast(_animationView, ORKAnimationPlaceholderView) defaultFrameOrigin]; + animationViewFrame.origin = (CGPoint){defaultFrameOrigin.x - scrollViewBoundsOrigin.x, defaultFrameOrigin.y - scrollViewBoundsOrigin.y}; + _animationView.frame = animationViewFrame; + } +} + +- (ORKConsentSection *)consentSectionForIndex:(NSUInteger)index { + ORKConsentSection *consentSection = nil; + NSArray *visualSections = [self visualSections]; + if (index < visualSections.count) { + consentSection = visualSections[index]; + } + return consentSection; +} + +- (void)showViewController:(ORKConsentSceneViewController *)viewController forward:(BOOL)forward animated:(BOOL)animated { + [self showViewController:viewController forward:forward animated:animated preloadNextConsentSectionImage:YES]; +} + +- (void)showViewController:(ORKConsentSceneViewController *)viewController forward:(BOOL)forward animated:(BOOL)animated preloadNextConsentSectionImage:(BOOL)preloadNextViewController { + [self showViewController:viewController + forward:forward + animated:animated + completion:^(BOOL finished) { + }]; +} + +- (void)showViewController:(ORKConsentSceneViewController *)viewController + forward:(BOOL)forward + animated:(BOOL)animated + completion:(void (^)(BOOL finished))completion { + if (!viewController) { + if (completion) { + completion(NO); + } + return; + } + // Stop old hairline scroll view observer and start new one + _scrollViewObserver = [[ORKScrollViewObserver alloc] initWithTargetView:viewController.scrollView delegate:self]; + + ORKConsentSceneViewController *fromViewController = nil; + NSUInteger currentIndex = [self currentIndex]; + if (currentIndex == NSNotFound) { + animated = NO; + } else { + fromViewController = _viewControllers[@(currentIndex)]; + } + + // Cancel any previous video animation + fromViewController.imageHidden = NO; + viewController.imageHidden = NO; + if (_animator) { + [self animationPlayerView].hidden = YES; + [_animator finish]; + _animator = nil; + } + + UIPageViewControllerNavigationDirection direction = forward ? UIPageViewControllerNavigationDirectionForward : UIPageViewControllerNavigationDirectionReverse; + + ORKAdjustPageViewControllerNavigationDirectionForRTL(&direction); + + if (!animated) { + // No animation at all + viewController.imageHidden = NO; + [self doShowViewController:viewController direction:direction animated:animated completion:completion]; + } else { + NSUInteger toIndex = [self indexOfViewController:viewController]; + + NSURL *url = nil; + BOOL animateBeforeTransition = NO; + BOOL transitionBeforeAnimate = NO; + + ORKConsentSectionType currentSection = [(ORKConsentSection *)_visualSections[currentIndex] type]; + ORKConsentSectionType destinationSection = (toIndex != NSNotFound) ? [(ORKConsentSection *)_visualSections[toIndex] type] : ORKConsentSectionTypeCustom; + + // Only use video animation when going forward + if (toIndex > currentIndex) { + + // Use the custom animation URL, if there is one for the destination index. + if (toIndex != NSNotFound && toIndex < _visualSections.count) { + url = [ORKDynamicCast(_visualSections[toIndex], ORKConsentSection) customAnimationURL]; + } + BOOL isCustomURL = (url != nil); + + // If there's no custom URL, use an animation only if transitioning in the expected order. + // Exception for datagathering, which does an arrival animation AFTER. + if (!isCustomURL) { + if (destinationSection == ORKConsentSectionTypeDataGathering) { + transitionBeforeAnimate = YES; + url = ORKMovieURLForConsentSectionType(ORKConsentSectionTypeOverview); + } else if ((destinationSection - currentSection) == 1) { + url = ORKMovieURLForConsentSectionType(currentSection); + } + } + } + + if (!url) { + // No video animation URL, just a regular push transition animation. + [self doShowViewController:viewController direction:direction animated:animated completion:completion]; + } else { + [self doAnimateFromViewController:fromViewController + toController:viewController + direction:direction + url:url + animateBeforeTransition:animateBeforeTransition + transitionBeforeAnimate:transitionBeforeAnimate + completion:completion]; + } + } +} + +- (ORKConsentSceneViewController *)viewControllerForIndex:(NSUInteger)index { + if (_viewControllers == nil) { + _viewControllers = [NSMutableDictionary new]; + } + + ORKConsentSceneViewController *consentViewController = nil; + + if (_viewControllers[@(index)]) { + consentViewController = _viewControllers[@(index)]; + } else if (index >= [self pageCount]) { + consentViewController = nil; + } else { + ORKConsentSceneViewController *sceneViewController = [[ORKConsentSceneViewController alloc] initWithSection:[self visualSections][index]]; + consentViewController = sceneViewController; + + if (index == [self pageCount]-1) { + sceneViewController.continueButtonItem = self.continueButtonItem; + } else { + NSString *buttonTitle = ORKLocalizedString(@"BUTTON_NEXT", nil); + if (sceneViewController.section.type == ORKConsentSectionTypeOverview) { + buttonTitle = ORKLocalizedString(@"BUTTON_GET_STARTED", nil); + } + + sceneViewController.continueButtonItem = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStylePlain target:self action:@selector(next)]; + } + } + + if (consentViewController) { + _viewControllers[@(index)] = consentViewController; + } + + consentViewController.cancelButtonItem = self.cancelButtonItem; + return consentViewController; +} + +- (NSUInteger)indexOfViewController:(UIViewController *)viewController { + if (!viewController) { + return NSNotFound; + } + + NSUInteger index = NSNotFound; + for (NSNumber *key in _viewControllers) { + if (_viewControllers[key] == viewController) { + index = key.unsignedIntegerValue; + break; + } + } + return index; +} + +- (NSUInteger)currentIndex { + return [self indexOfViewController:_pageViewController.viewControllers.firstObject]; +} + +#pragma mark - UIPageViewControllerDataSource + +- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { + NSUInteger index = [self indexOfViewController:viewController]; + if (index == NSNotFound) { + return nil; + } + + return [self viewControllerForIndex:index - 1]; +} + +- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { + NSUInteger index = [self indexOfViewController:viewController]; + if (index == NSNotFound) { + return nil; + } + + return [self viewControllerForIndex:index + 1]; +} + +#pragma mark - UIPageViewControllerDelegate + +- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished + previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { + if (finished && completed) { + [self updatePageIndex]; + } +} + +static NSString *const _ORKCurrentPageRestoreKey = @"currentPage"; +static NSString *const _ORKHasAppearedRestoreKey = @"hasAppeared"; +static NSString *const _ORKInitialBackButtonRestoreKey = @"initialBackButton"; + +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeInteger:_currentPage forKey:_ORKCurrentPageRestoreKey]; + [coder encodeBool:_hasAppeared forKey:_ORKHasAppearedRestoreKey]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + self.currentPage = [coder decodeIntegerForKey:_ORKCurrentPageRestoreKey]; + _hasAppeared = [coder decodeBoolForKey:_ORKHasAppearedRestoreKey]; + + _viewControllers = nil; + [self showViewController:[self viewControllerForIndex:_currentPage] forward:YES animated:NO]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController_Internal.h new file mode 100755 index 0000000..7ba0159 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentStepViewController_Internal.h @@ -0,0 +1,45 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVisualConsentStepViewController.h" + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKEAGLMoviePlayerView; + +@interface ORKVisualConsentStepViewController () + +- (nullable ORKEAGLMoviePlayerView *)animationPlayerView; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.h new file mode 100755 index 0000000..b03a458 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@class ORKVisualConsentStepViewController; +@class ORKVisualConsentTransitionAnimator; +@protocol ORKVisualConsentTransitionAnimatorDelegate; + +typedef void (^ORKVisualConsentAnimationCompletionHandler)(ORKVisualConsentTransitionAnimator *animator, UIPageViewControllerNavigationDirection direction); + +@interface ORKVisualConsentTransitionAnimator : NSObject + +- (instancetype)initWithVisualConsentStepViewController:(ORKVisualConsentStepViewController *)stepViewController + movieURL:(NSURL *)movieURL; + +@property (nonatomic, readonly, copy) NSURL *movieURL; + +- (void)animateTransitionWithDirection:(UIPageViewControllerNavigationDirection)direction + loadHandler:(nullable ORKVisualConsentAnimationCompletionHandler)loadHandler + completionHandler:(nullable ORKVisualConsentAnimationCompletionHandler)handler; + +// Call to invalidate display link and remove any observations. +- (void)finish; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.m new file mode 100755 index 0000000..3dfeab0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Consent/ORKVisualConsentTransitionAnimator.m @@ -0,0 +1,311 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import AVFoundation; + +#import "ORKEAGLMoviePlayerView.h" + +#import "ORKVisualConsentStepViewController_Internal.h" +#import "ORKVisualConsentTransitionAnimator.h" + +#import "ORKHelpers_Internal.h" + + +// Internal object to hold the direction we're animating, the phase of the animation, and the animation completion handler. +@interface ORKVisualConsentAnimationContext : NSObject + +@property (nonatomic, assign) UIPageViewControllerNavigationDirection direction; + +@property (nonatomic, assign) BOOL hasCalledLoadHandler; + +@property (nonatomic, copy) ORKVisualConsentAnimationCompletionHandler handler; + +@property (nonatomic, copy) ORKVisualConsentAnimationCompletionHandler loadHandler; + +@property (nonatomic, strong) NSValue *startTime; + +// Establish a retain cycle by setting this to ourselves, to lengthen lifetime +@property (nonatomic, strong) id selfReference; + +@end + + +@implementation ORKVisualConsentAnimationContext + +@end + + +@interface ORKVisualConsentTransitionAnimator () + +@end + + +@implementation ORKVisualConsentTransitionAnimator { + __weak ORKVisualConsentStepViewController *_stepViewController; + NSURL *_movieURL; + AVPlayer *_moviePlayer; + AVPlayerItem *_playerItem; + + BOOL _observingPlayerStatusKey; + BOOL _observingPlayerItemDurationKey; + + CADisplayLink *_displayLink; + AVPlayerItemVideoOutput *_videoOutput; + dispatch_queue_t _videoOutputQueue; + NSInteger _frameCounter; + ORKVisualConsentAnimationContext *_pendingContext; +} + +- (instancetype)initWithVisualConsentStepViewController:(ORKVisualConsentStepViewController *)stepViewController + movieURL:(NSURL *)movieURL { + self = [super init]; + if (self) { + NSParameterAssert(stepViewController != nil); + NSParameterAssert(movieURL != nil); + + _stepViewController = stepViewController; + _movieURL = [movieURL copy]; + + _moviePlayer = [[AVPlayer alloc] init]; + _moviePlayer.actionAtItemEnd = AVPlayerActionAtItemEndPause; + + // Setup CADisplayLink which will callback displayPixelBuffer: at every vsync. + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkCallback:)]; + [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; + [_displayLink setPaused:YES]; + + // Setup AVPlayerItemVideoOutput with the required pixelbuffer attributes. + NSDictionary *pixelBufferAttributes = @{(id)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)}; + _videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:pixelBufferAttributes]; + _videoOutputQueue = dispatch_queue_create("_ork_animationVideoQueue", DISPATCH_QUEUE_SERIAL); + [_videoOutput setDelegate:self queue:_videoOutputQueue]; + } + return self; +} + +- (NSURL *)movieURL { + return _movieURL; +} + +- (void)animateTransitionWithDirection:(UIPageViewControllerNavigationDirection)direction + loadHandler:(ORKVisualConsentAnimationCompletionHandler)loadHandler + completionHandler:(ORKVisualConsentAnimationCompletionHandler)handler { + ORKVisualConsentAnimationContext *context = [ORKVisualConsentAnimationContext new]; + context.handler = handler; + context.direction = direction; + context.loadHandler = loadHandler; + + _playerItem = [AVPlayerItem playerItemWithURL:_movieURL]; + + [_playerItem addOutput:_videoOutput]; + [_moviePlayer replaceCurrentItemWithPlayerItem:_playerItem]; + [_videoOutput requestNotificationOfMediaDataChangeWithAdvanceInterval:0.015]; + + context.startTime = [NSValue valueWithCMTime:CMTimeMake(0, NSEC_PER_SEC)]; + + [self attemptAnimationWithContext:context]; +} + +- (void)attemptAnimationWithContext:(ORKVisualConsentAnimationContext *)context { + BOOL playerIsReady = [_moviePlayer status] == AVPlayerStatusReadyToPlay; + BOOL playerItemIsReady = CMTimeGetSeconds([_playerItem duration]) > 0; + + // Observe the properties for which we still need to wait + if (!playerIsReady && !_observingPlayerStatusKey) { + [_moviePlayer addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:(void *)context]; + _observingPlayerStatusKey = YES; + context.selfReference = context; + } + if (!playerItemIsReady && !_observingPlayerItemDurationKey) { + [_playerItem addObserver:self forKeyPath:@"duration" options:NSKeyValueObservingOptionNew context:(void *)context]; + _observingPlayerItemDurationKey = YES; + context.selfReference = context; + } + + // Stop observing properties that have now changed to a ready state + if (playerIsReady && _observingPlayerStatusKey) { + [_moviePlayer removeObserver:self forKeyPath:@"status"]; + _observingPlayerStatusKey = NO; + } + if (playerItemIsReady && _observingPlayerItemDurationKey) { + [_playerItem removeObserver:self forKeyPath:@"duration"]; + _observingPlayerItemDurationKey = NO; + } + + if (playerIsReady && playerItemIsReady) { + context.selfReference = nil; + [self performAnimationWithContext:context]; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + ORKVisualConsentAnimationContext *animationContext = (__bridge ORKVisualConsentAnimationContext *)context; + + dispatch_async(dispatch_get_main_queue(), ^{ + if (([keyPath isEqualToString:@"status"] && object == _moviePlayer) || + ([keyPath isEqualToString:@"duration"] && object == _playerItem)) { + if (_moviePlayer.error) { + ORK_Log_Error("%@", _moviePlayer.error); + } + + [self attemptAnimationWithContext:animationContext]; + } + }); +} + +- (void)playbackDidFinish:(NSNotification *)notification { + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:notification.object]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemFailedToPlayToEndTimeNotification object:notification.object]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemPlaybackStalledNotification object:notification.object]; + + [_moviePlayer pause]; + + [self finishAnimationWithContext:_pendingContext]; +} + +- (void)performAnimationWithContext:(ORKVisualConsentAnimationContext *)context { + + _pendingContext = context; + + [[_stepViewController animationPlayerView] setupGL]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:[_moviePlayer currentItem]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish:) name:AVPlayerItemFailedToPlayToEndTimeNotification object:[_moviePlayer currentItem]]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish:) name:AVPlayerItemPlaybackStalledNotification object:[_moviePlayer currentItem]]; + + __weak AVPlayer *weakPlayer = _moviePlayer; + [_moviePlayer seekToTime:context.startTime.CMTimeValue + toleranceBefore:CMTimeMake(NSEC_PER_SEC * (1.0 / 60.0), NSEC_PER_SEC) toleranceAfter:CMTimeMake(NSEC_PER_SEC * (1.0 / 60.0), NSEC_PER_SEC) completionHandler:^(BOOL finished) { + AVPlayer *localPlayer = weakPlayer; + [localPlayer play]; + }]; +} + +- (void)finishAnimationWithContext:(ORKVisualConsentAnimationContext *)context { + if (context == _pendingContext) { + _pendingContext = nil; + } + + if (context.handler) { + context.handler(self, context.direction); + } + + // Clear the handler so it is not called twice + context.handler = nil; + // Make sure the context is released + context.selfReference = nil; +} + +#pragma mark - CADisplayLink Callback + +- (void)initialFrameDidDisplay { + // Once our initial frame has definitely been drawn, we make ourselves visible + // and signal the caller that the animation has started. + ORKEAGLMoviePlayerView *playerView = [_stepViewController animationPlayerView]; + playerView.hidden = NO; + + if (_pendingContext && !_pendingContext.hasCalledLoadHandler) { + if (_pendingContext.loadHandler) { + _pendingContext.loadHandler(self, _pendingContext.direction); + } + _pendingContext.hasCalledLoadHandler = YES; + } +} + +- (void)displayLinkCallback:(CADisplayLink *)sender { + /* + The callback gets called once every Vsync. + Using the display link's timestamp and duration we can compute the next time the screen will be refreshed, and copy the pixel buffer for that time + This pixel buffer can then be processed and later rendered on screen. + */ + CMTime outputItemTime = kCMTimeInvalid; + + // Calculate the nextVsync time which is when the screen will be refreshed next. + CFTimeInterval nextVSync = ([sender timestamp] + [sender duration]); + + outputItemTime = [_videoOutput itemTimeForHostTime:nextVSync]; + + if ([_videoOutput hasNewPixelBufferForItemTime:outputItemTime]) { + CVPixelBufferRef pixelBuffer = NULL; + pixelBuffer = [_videoOutput copyPixelBufferForItemTime:outputItemTime itemTimeForDisplay:NULL]; + + ORKEAGLMoviePlayerView *playerView = [_stepViewController animationPlayerView]; + CGSize playerItemPresentationSize = _playerItem.presentationSize; + if (!CGSizeEqualToSize(playerView.presentationSize, playerItemPresentationSize)) { + playerView.presentationSize = playerItemPresentationSize; + } + BOOL canDisplay = [playerView consumePixelBuffer:pixelBuffer]; + if (pixelBuffer != NULL) { + CFRelease(pixelBuffer); + pixelBuffer = NULL; + } + if (canDisplay) { + [playerView render]; + } + + if (_frameCounter == 1) { + [self initialFrameDidDisplay]; + } + _frameCounter ++; + } +} + +#pragma mark - AVPlayerItemOutputPullDelegate + +- (void)outputMediaDataWillChange:(AVPlayerItemOutput *)sender { + // Restart display link. + [_displayLink setPaused:NO]; + _frameCounter = 0; +} + +- (void)finish { + [_moviePlayer pause]; + [_displayLink invalidate]; // This makes animator single-use + + if (_observingPlayerStatusKey) { + [_moviePlayer removeObserver:self forKeyPath:@"status"]; + _observingPlayerStatusKey = NO; + } + if (_observingPlayerItemDurationKey) { + [_playerItem removeObserver:self forKeyPath:@"duration"]; + _observingPlayerItemDurationKey = NO; + } + + _videoOutputQueue = nil; + _moviePlayer = nil; + _displayLink = nil; + _pendingContext = nil; + _videoOutput = nil; + _videoOutputQueue = nil; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Info.plist new file mode 100755 index 0000000..55587b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 2.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ResearchKit.stringsdict new file mode 100755 index 0000000..edd4158 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errors) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.strings new file mode 100755 index 0000000..83230c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "موافقة"; +"CONSENT_NAME_GIVEN" = "الاسم الأول"; +"CONSENT_NAME_FAMILY" = "اسم العائلة"; +"CONSENT_NAME_PLACEHOLDER" = "مطلوب"; +"CONSENT_REVIEW_TITLE" = "مراجعة"; +"CONSENT_REVIEW_INSTRUCTION" = "راجع النموذج أدناه، واضغط على موافقة إذا كنت مستعدًا للمتابعة."; +"CONSENT_REVIEW_ALERT_TITLE" = "مراجعة"; +"CONSENT_SIGNATURE_TITLE" = "التوقيع"; +"CONSENT_SIGNATURE_INSTRUCTION" = "الرجاء التوقيع باستخدام إصبعك في المربع أدناه."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "التوقيع هنا"; +"CONSENT_PAGE_NUMBER_FORMAT" = "صفحة %1$ld من %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "مرحبًا"; +"CONSENT_SECTION_DATA_GATHERING" = "جمع البيانات"; +"CONSENT_SECTION_PRIVACY" = "الخصوصية"; +"CONSENT_SECTION_DATA_USE" = "استخدام البيانات"; +"CONSENT_SECTION_STUDY_SURVEY" = "استطلاع الدراسة"; +"CONSENT_SECTION_STUDY_TASKS" = "مهام الدراسة"; +"CONSENT_SECTION_TIME_COMMITMENT" = "التزام الوقت"; +"CONSENT_SECTION_WITHDRAWING" = "الانسحاب"; +"CONSENT_LEARN_MORE_TITLE" = "معرفة المزيد"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "معرفة المزيد عن كيفية جمع البيانات"; +"LEARN_MORE_DATA_USE" = "معرفة المزيد عن كيفية استخدام البيانات"; +"LEARN_MORE_PRIVACY" = "معرفة المزيد عن كيفية حماية خصوصيتك وهويتك"; +"LEARN_MORE_WELCOME" = "معرفة المزيد عن الدراسة أولاً"; +"LEARN_MORE_STUDY_SURVEY" = "معرفة المزيد عن استطلاع الدراسة"; +"LEARN_MORE_TIME_COMMITMENT" = "معرفة المزيد عن أثر الدراسة على وقتك"; +"LEARN_MORE_TASKS" = "معرفة المزيد عن المهام المتضمنة"; +"LEARN_MORE_WITHDRAWING" = "معرفة المزيد عن الانسحاب"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "خيارات المشاركة"; +"CONSENT_SHARE_WIDELY_%@" = "مشاركة بياناتي مع %@ والباحثين المؤهلين حول العالم"; +"CONSENT_SHARE_ONLY_%@" = "مشاركة بياناتي مع %@ فقط"; +"CONSENT_SHARING_DESCRIPTION_%@" = "سيحصل %@ على بيانات الدراسة الخاصة بك من خلال مشاركتك في هذه الدراسة.\n\nقد يستفيد هذا البحث والبحث المستقبلي من مشاركتك لبيانات الدراسة المشفرة الخاصة بك على نحو أوسع (دون مشاركة معلومات مثل اسمك)."; +"LEARN_MORE_CONSENT_SHARING" = "معرفة المزيد عن مشاركة البيانات"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "الاسم بخط اليد"; +"CONSENT_DOC_LINE_SIGNATURE" = "التوقيع"; +"CONSENT_DOC_LINE_DATE" = "التاريخ"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ من %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "السؤال %1$@ من %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "تم التخطي"; +"REVIEW_EDIT_ANSWER" = "تحرير"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "القيمة غير صالحة"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "‏%1$@ تتخطى القيمة القصوى المسموح بها (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "‏%1$@ أقل من القيمة الدنيا المسموح بها (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "‏%@ قيمة غير صالحة."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "عنوان البريد الإلكتروني غير صالح: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "أدخل عنوان"; +"LOCATION_ERROR_TITLE" = "تعذر العثور على العنوان المحدد"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "غير قادر على حل موقعك الحالي. يرجى كتابة العنوان أو الانتقال إلى موقع فيه إشارة GPS أفضل إن وجد."; +"LOCATION_ERROR_MESSAGE_DENIED" = "تم رفض الوصول إلى خدمات الموقع. يرجي منح هذا التطبيق الإذن لاستخدام خدمات الموقع في الإعدادات."; +"LOCATION_ERROR_GEOCODE" = "تعذر العثور على نتيجة للعنوان الذي تم إدخاله. يرجى التأكد من أن العنوان صالح."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "إما أنك غير متصل بالإنترنت أو أنك تجاوزت الحد الأقصى من طلبات البحث عن العنوان. إذا لم تكن متصلًا بالإنترنت، يرجى تشغيل الـ Wi-Fi للإجابة على هذا السؤال، قم بتخطي هذا السؤال إذا كان زر التخطي متاحاً، أو العودة للاستبيان عندما تكون متصلًا بالإنترنت. خلاف ذلك، يرجى المحاولة مرة أخرى خلال بضع دقائق."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "المحتوى النصي يتجاوز الحد الأقصى للطول: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "الكاميرا غير متوفرة في العرض المقسم."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "البريد الإلكتروني"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "كلمة السر"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "أدخل كلمة السر"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "تأكيد"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "أدخل كلمة السر مرة أخرى"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "كلمتا السر غير متطابقتين."; +"ADDITIONAL_INFO_SECTION_TITLE" = "معلومات إضافية"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "باسل"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "أسعد"; +"GENDER_FORM_ITEM_TITLE" = "الجنس"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "اختيار الجنس"; +"DOB_FORM_ITEM_TITLE" = "تاريخ الميلاد"; +"DOB_FORM_ITEM_PLACEHOLDER" = "اختيار تاريخ"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "رقم الهاتف"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "‪+1 (555) 555 5555‬"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "التحقق"; +"VERIFICATION_STEP_TITLE" = "التحقق من البريد الإلكتروني"; +"RESEND_EMAIL_LABEL_MESSAGE" = "اضغط على الرابط أدناه إذا كنت لم تستلم بريد التحقق، وترغب بإرساله لك مرة أخرى."; +"RESEND_EMAIL_BUTTON_TITLE" = "إعادة إرسال بريد التحقق"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "تسجيل الدخول"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "هل نسيت كلمة السر؟"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "أدخل رمز الدخول"; +"PASSCODE_CONFIRM_MESSAGE" = "تأكيد رمز الدخول"; +"PASSCODE_SAVED_MESSAGE" = "تم حفظ رمز الدخول"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "رمز الدخول غير مصدّق"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "أدخل رمز الدخول القديم"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "أدخل رمز الدخول الجديد"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "تأكيد رمز الدخول الجديد"; +"PASSCODE_INVALID_ALERT_TITLE" = "رمز الدخول غير صحيح"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "رمزي الدخول غير متطابقين. حاول مجدداً."; +"PASSCODE_TOUCH_ID_MESSAGE" = "الرجاء المصادقة باستخدام Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "خطأ في Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "فقط الأرقام مسموح بها."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "مؤشر تقدم إدخال رمز الدخول"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "تم إدخال %1$@ من %2$@ من الأرقام"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "هل نسيت رمز الدخول؟"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "تعذر إضافة عنصر سلسلة المفاتيح."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "تعذر تحديث عنصر سلسلة المفاتيح."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "تعذر حذف عنصر سلسلة المفاتيح."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "تعذر العثور على عنصر سلسلة المفاتيح."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "‎A+"; +"BLOOD_TYPE_A-" = "‎A-"; +"BLOOD_TYPE_AB+" = "‎AB+"; +"BLOOD_TYPE_AB-" = "‎AB-"; +"BLOOD_TYPE_B+" = "‎B+"; +"BLOOD_TYPE_B-" = "‎B-"; +"BLOOD_TYPE_O+" = "‎O+"; +"BLOOD_TYPE_O-" = "‎O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "النوع ١"; +"FITZPATRICK_SKIN_TYPE_II" = "النوع ٢"; +"FITZPATRICK_SKIN_TYPE_III" = "النوع ٣"; +"FITZPATRICK_SKIN_TYPE_IV" = "النوع ٤"; +"FITZPATRICK_SKIN_TYPE_V" = "النوع ٥"; +"FITZPATRICK_SKIN_TYPE_VI" = "النوع ٦"; + +/* Gender values. */ +"GENDER_FEMALE" = "أنثى"; +"GENDER_MALE" = "ذكر"; +"GENDER_OTHER" = "غير ذلك"; + +/* Boolean answer strings */ +"BOOL_NO" = "لا"; +"BOOL_YES" = "نعم"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "سم"; +"MEASURING_UNIT_FT" = "قدم"; +"MEASURING_UNIT_IN" = "بوصة"; +"MEASURING_UNIT_KG" = "كغم"; +"MEASURING_UNIT_LB" = "رطل"; +"MEASURING_UNIT_OZ" = "أونصة"; + +/* Limb values. */ +"LIMB_LEFT" = "الأيسر"; +"LIMB_RIGHT" = "الأيمن"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "اضغط للإجابة"; +"NULL_ANSWER" = "قم بتحديد إجابة"; +"PLACEHOLDER_IMAGE_CHOICES" = "اضغط للتحديد"; +"PLACEHOLDER_LONG_TEXT" = "اضغط للكتابة"; + +/* Button titles */ +"BUTTON_AGREE" = "موافقة"; +"BUTTON_CANCEL" = "إلغاء"; +"BUTTON_OK" = "موافق"; +"BUTTON_CLEAR" = "مسح"; +"BUTTON_CLEAR_SIGNATURE" = "مسح التوقيع"; +"BUTTON_APPLY" = "تطبيق"; +"BUTTON_DISAGREE" = "عدم الموافقة"; +"BUTTON_DONE" = "تم"; +"BUTTON_GET_STARTED" = "البدء"; +"BUTTON_LEARN_MORE" = "معرفة المزيد"; +"BUTTON_NEXT" = "التالي"; +"BUTTON_SKIP" = "تخطي"; +"BUTTON_SKIP_QUESTION" = "تخطي هذا السؤال"; +"BUTTON_START_TIMER" = "بدء تشغيل المؤقت"; +"BUTTON_OPTION_SAVE" = "حفظ لما بعد"; +"BUTTON_OPTION_DISCARD" = "تجاهل النتائج"; +"BUTTON_OPTION_STOP_TASK" = "إنهاء المهمة"; +"BUTTON_SAVE" = "حفظ"; +"BUTTON_CLEAR_ANSWER" = "مسح الإجابة"; +"BUTTON_READ_ONLY_MODE" = "لا يمكن تعديل هذه الإجابة."; +"BUTTON_COPYRIGHT" = "حقوق النشر"; +"BUTTON_CLOSE" = "إغلاق"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "بدء النشاط خلال"; +"TASK_COMPLETE_TITLE" = "اكتمل النشاط"; +"TASK_COMPLETE_TEXT" = "سيتم تحليل بياناتك وسيتم إعلامك عندما تصبح النتائج جاهزة."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "متبقٍ: %@."; +"TOUCH_ANYWHERE_LABEL" = "المس أي مكان للمتابعة"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "التقاط صورة"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "إعادة التقاط الصورة"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "لم يتم العثور على كاميرا. لا يمكن إكمال هذه الخطوة."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "لإكمال هذه الخطوة، اسمح لهذا التطبيق بالوصول إلى الكاميرا في الإعدادات."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "لم يتم تحديد دليل إخراج للصور الملتقطة."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "لا يمكن حفظ الصورة الملتقطة."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "بدء التسجيل"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "إيقاف التسجيل"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "إعادة التقاط الفيديو"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "اللياقة"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "المسافة ‏(%@)"; +"FITNESS_HEARTRATE_TITLE" = "معدل نبض القلب (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "خذ استراحة لمدة %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "قم بالمشي بأقصى سرعة لديك لمدة %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "يعمل هذا النشاط على مراقبة معدل نبض القلب لديك وقياس المسافة التي يمكنك أن تمشيها خلال %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "امشِ في الخارج بأقصى سرعة ممكنة لديك لمدة %1$@. عندما تنتهي، اجلس وخذ استراحة لمدة %2$@. للبدء، اضغط على البدء."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "سرعة المشي والتوازن"; +"WALK_INTRO_TEXT" = "يقيس هذا النشاط سرعة مشيتك وتوازنك أثناء المشي والوقوف ثابتًا. لا تقم بالمتابعة إذا لم تكن قادرًا على المشي دون مساعدة."; +"WALK_INTRO_2_TEXT_%ld" = "اعثر على مكان يمكنك المشي فيه بصورة آمنة دون مساعدة لمسافة %ld من الخطوات تقريبًا في خط مستقيم."; +"WALK_INTRO_2_DETAIL" = "ضع جهازك في حافظة أو حقيبة واتبع الإرشادات الصوتية."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "الآن قف ثابتًا لمدة %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "قف ثابتًا لمدة %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "قم بالدوران والمشي رجوعًا إلى نقطة بدايتك."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "قم بمشي حوالي %ld خطوة في خط مستقيم."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "اذهب إلى مكان يمكنك السير فيه بأمان ذهابًا وإيابًا في خط مستقيم. حاول السير بشكل متواصل عن طريق الانعطاف عند طرفي مسارك وكأنك تسير حول قمع.\n\nسيتم توجيهك بعد ذلك للاستدارة في دائرة كاملة، ثم الوقوف ويداك على جانبيك والمسافة بين قدميك تساوي عرض كتفك تقريبًا."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "اضغط على \“البدء\” عندما تكون مستعدًا للبدء.\nبعد ذلك ضع جهازك في حافظة أو حقيبة واتبع الإرشادات الصوتية."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "قم بالمشي ذهابًا وإيابًا في خط مستقيم %@. قم بالمشي كما تفعل عادةً."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "استدر بمقدار دائرة كاملة ثم قف ثابتًا لمدة %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "لقد أكملت النشاط."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "سرعة الضغط"; +"TAPPING_TASK_TITLE_RIGHT" = "اليد اليمنى"; +"TAPPING_TASK_TITLE_LEFT" = "اليد اليسرى"; +"TAPPING_INTRO_TEXT" = "يقيس هذا النشاط سرعتك في الضغط."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "ضع جهازك على سطح مستوٍ."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "استخدم إصبعين من نفس اليد للضغط بالتبادل على الزرين على الشاشة."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "استخدم إصبعين من يدك اليمنى للضغط بالتبادل على الزرين على الشاشة."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "استخدم إصبعين من يدك اليسرى للضغط بالتبادل على الزرين على الشاشة."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "الآن، كرر نفس الاختبار باستخدام يدك اليمنى."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "الآن، كرر نفس الاختبار باستخدام يدك اليسرى."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "اضغط بإصبع، ثم بالإصبع الآخر. حاول ضبط وقت ضغطاتك ليكون متساويًا قدر الإمكان. واستمر في الضغط لمدة %@."; +"TAPPING_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"TAPPING_CALL_TO_ACTION_NEXT" = "اضغط على التالي للبدء."; +"TAP_BUTTON_TITLE" = "الضغط"; +"TOTAL_TAPS_LABEL" = "إجمالي الضغطات"; +"TAPPING_INSTRUCTION" = "اضغط على الزرين بتوافق قدر الإمكان باستخدام إصبعين."; +"TAPPING_INSTRUCTION_RIGHT" = "اضغط على الزرين باستخدام يدك اليمنى."; +"TAPPING_INSTRUCTION_LEFT" = "اضغط على الزرين باستخدام يدك اليسرى."; +"TAPPING_SKIP_TITLE" = "تخطي هذه اليد"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "شبكة أمسلر"; +"AMSLER_GRID_INTRO_TEXT" = "يساعد هذا النشاط على اكتشاف المشاكل في رؤية المستخدم."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "أمسك بالجهاز على بعد ١٢ بوصة من وجهك وعلى مستوى عينيك طوال مدة الاختبار."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "أغلق %@ وحدّق في النقطة الموجودة في مركز الشبكة المربعة.\n\nاستخدم إصبعك أو القلم لتمييز أي تحرّفات تراها مثل الخطوط الضبابية أو المتموجة.\n\nعند الانتهاء، حرّك لليمين في أي مكان خارج الشبكة."; +"AMSLER_GRID_LEFT_EYE" = "العين اليسرى"; +"AMSLER_GRID_RIGHT_EYE" = "العين اليمنى"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "الصوت"; +"AUDIO_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"AUDIO_INSTRUCTION" = "انطق \“آااااه\” في الميكروفون لأطول فترة ممكنة بالنسبة إليك."; +"AUDIO_INTRO_TEXT" = "خذ نفسًا عميقًا وانطق \“آااااه\” في الميكروفون لأطول فترة ممكنة بالنسبة إليك. حافظ على ثبات مستوى صوتك حتى تظل أشرطة الصوت باللون الأزرق."; +"AUDIO_INTENDED_USE" = "يقيّم هذا النشاط صوتك عن طريق تسجيله باستخدام الميكروفون في أسفل الجهاز."; +"AUDIO_TOO_LOUD_LABEL" = "عالٍ جدًا"; +"AUDIO_GENERIC_ERROR_LABEL" = "غير قادر على تسجيل الصوت"; +"AUDIO_LEVEL_CHECK_LABEL" = "الرجاء الانتظار حتى يتم التحقق من مستوى الضوضاء في الخلفية."; +"AUDIO_TOO_LOUD_MESSAGE" = "مستوى الضوضاء المحيطة عالٍ جدًا بحيث لا يمكن تسجيل صوتك. الرجاء الانتقال إلى مكان أكثر هدوءًا والمحاولة مرة أخرى."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "اضغط على التالي عندما تكون مستعدًا."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "قياس سمع النغمة"; +"TONE_AUDIOMETRY_INTENDED_USE" = "يقيس هذا النشاط قدرتك على سماع الأصوات المختلفة."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "قبل البدء، قم بتوصيل سماعات الرأس وارتدائها.\n\nسيكون الصوت رقيقًا جدًا ولا يشبه نغمة التنبيه العادية.  سيبدأ الصوت ناعمًا ثم سيزداد مستوى الصوت ببطء.  الرجاء الانتباه والضغط على الزر الأيمن أو الأيسر للإشارة إلى الأذن التي تسمع الصوت فيها."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"TONE_AUDIOMETRY_PREP_TEXT" = "من المفترض أن تسمع نغمة الآن. اضبط مستوى الصوت باستخدام عناصر التحكم على جانب الجهاز.\n\nاضغط على أي زر عندما تكون مستعدًا للبدء."; +"TONE_AUDIOMETRY_INSTRUCTION" = "في كل مرة تسمع صوتًا، اضغط على الزر الأيمن أو الأيسر للإشارة إلى الأذن التي تسمع الصوت فيها."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "الأذن اليسرى"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "الأذن اليمنى"; +"TONE_LABEL_%@_LEFT" = "‏%@ هرتز، يسار"; +"TONE_LABEL_%@_RIGHT" = "‏%@ هرتز، يمين"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "قياس سمع النغمة"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "اضغط عندما تسمع نغمة."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "النغمة ومستوى الصوت"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "ستسمع سلسلة نغمات."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "عندما تسمع نغمة، اضغط على الزر."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "خلال هذا الاختبار، سيتم تعيين مستوى الصوت إلى ٥٠ بالمائة."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "يستغرق هذا الاختبار حوالي ١٠ دقائق."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "شغّل عدم الإزعاج لتجنب المقاطعة."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "سيتم تشغيل النغمات في أذنك اليمنى أولاً."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "الآن سيتم تشغيل النغمات في أذنك اليسرى."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "يحدد هذا النشاط مستويات الحد الأقصى للسمع للفرد بمقياس مستوى السمع بالديسيبل (dB HL)."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "تأكد من تعيين مستوى صوت الجهاز على الحد الأقصى.\n\nأثناء هذه المهمة، سيتم تشغيل نغمة رقيقة في الأذن اليسرى أو اليمنى.\n\nاستمع بعناية واضغط على الزر في كل مرة تسمع فيها النغمة."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "يحدد هذا الاختبار مستوى علوّ الصوت الذي تحتاجه حتى تسمع."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "استطلاع الالتحاق."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "حدد تفضيلك بخصوص \“الأذن الأفضل\”، إذا كانت هناك أذن أفضل من الأخرى."; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "يسار"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "يمين"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "بلا تفضيل"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "تم إلغاء الاختبار"; +"dBHL_ALERT_TITLE_START_OVER" = "بدء مرة أخرى"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "إلغاء الاختبار"; +"dBHL_ALERT_TEXT" = "أعِد توصيل الـ AirPods أو EarPods لإجراء هذا الاختبار."; +"dBHL_PROGRESS_COMPLETION_%@" = "اكتمل %@"; + +/* Headphones. */ +"AIRPODS" = "‏AirPods"; +"EARPODS" = "‏EarPods"; +"HEADPHONES" = "سماعات الرأس"; +"HEADPHONES_UNKNOWN" = "غير معروف"; +"HEADPHONES_NONE" = "لا شيء"; +"CONNECTED" = "متصلة"; +"NOT_CONNECTED" = "غير متصل"; +"HEADPHONE_CONNECTED_%@" = "متصلة - %@"; +"HEADPHONE_DETECT_TITLE" = "وصّل سماعات الرأس"; +"HEADPHONE_DETECT_TEXT" = "يتطلب هذا الاختبار Apple AirPods أو Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "الذاكرة المكانية"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "يقيس هذا النشاط ذاكرتك المكانية قصيرة المدى من خلال مطالبتك بتكرار نفس ترتيب إضاءة %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "زهور"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "زهور"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "ستضيء بعض ال%@ كلٌ على حدة. اضغط على هذه ال%@ بنفس ترتيب إضاءتها."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "ستضيء بعض ال%@ كلٌ على حدة. اضغط على هذه ال%@ بعكس ترتيب إضاءتها."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "للبدء، اضغط على البدء ثم قم بالمشاهدة عن قُرب."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "النتيجة"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "شاهد %@ تتم إضاءتها"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "اضغط على ال%@ حسب ترتيب إضاءتها"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "اضغط على %@ بترتيب عكسي"; +"MEMORY_GAME_COMPLETE_TITLE" = "اكتمل التتابع"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "للمتابعة اضغط على التالي."; +"MEMORY_GAME_FAILED_TITLE" = "المحاولة مرة أخرى"; +"MEMORY_GAME_FAILED_MESSAGE" = "لم يحالفك التوفيق تلك المرة. اضغط على التالي للمتابعة."; +"MEMORY_GAME_TIMEOUT_TITLE" = "انتهاء الوقت"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "نفد وقتك.\nاضغط على التالي للمتابعة."; +"MEMORY_GAME_COMPLETE" = "اكتملت اللعبة"; +"MEMORY_GAME_PAUSED_TITLE" = "تم الإيقاف مؤقتاً"; +"MEMORY_GAME_PAUSED_MESSAGE" = "للمتابعة اضغط على التالي."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "تم تطوير نشاط الذاكرة بمساعدة من د. كاثرين بوسين ود. جويل كرامر، دكتوراه من جامعة كاليفورنيا، سان فرانسيسكو."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "زمن رد الفعل"; +"REACTION_TIME_TASK_INTENDED_USE" = "يعمل هذا النشاط على تقييم الوقت الذي تستغرقه في الاستجابة للتلميح البصري."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "قم بهز الجهاز في أي اتجاه فور ظهور النقطة الزرقاء على الشاشة. سيُطلب منك فعل ذلك %D من المرات."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "المحاولة %@ من %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "قم بهز الجهاز سريعًا عندما تظهر الدائرة الزرقاء"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "ستروب"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "في كل مرة تظهر فيها كلمة، حدد الحرف الثاني من اسم اللون الذي يظهر."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "عندما تكون مستعدًا لبدء نشاط ستروب اضغط على البدء."; +"STROOP_TASK_STEP_TEXT" = "حدد الحرف الثاني من اسم اللون الذي يظهر."; +"STROOP_COLOR_RED" = "أحمر"; +"STROOP_COLOR_GREEN" = "أخضر"; +"STROOP_COLOR_BLUE" = "أزرق"; +"STROOP_COLOR_YELLOW" = "أصفر"; +"STROOP_COLOR_RED_INITIAL" = "ح"; +"STROOP_COLOR_GREEN_INITIAL" = "خ"; +"STROOP_COLOR_BLUE_INITIAL" = "ز"; +"STROOP_COLOR_YELLOW_INITIAL" = "ص"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "برج هانوي"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "يقيّم هذا النشاط مهاراتك في حل الألغاز."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "انقل الكومة بالكامل إلى المنصة المميزة في أقل عدد ممكن من الحركات."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "حل اللغز"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "عدد الحركات: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "لا أستطيع حل هذا اللغز"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "نطاق الحركة"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "يجب أن يكون limbOption الأيمن أو الأيسر"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "نطاق حركة الركبة اليسرى"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "نطاق حركة الركبة اليمنى"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "يقيس هذا النشاط إلى أي مدى يمكنك تمديد ركبتك اليسرى."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "يقيس هذا النشاط إلى أي مدى يمكنك تمديد ركبتك اليمنى."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "اجلس على حافة كرسي. عند البدء ستضع جهازك على ركبتك اليسرى لإجراء قياس. الرجاء تشغيل الصوت على جهازك حتى تتمكن من سماع التعليمات."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "اجلس على حافة كرسي. عند البدء ستضع جهازك على ركبتك اليمنى لإجراء قياس. الرجاء تشغيل الصوت على جهازك حتى تتمكن من سماع التعليمات."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "ضع جهازك على ركبتك اليسرى بحيث تكون الشاشة موجهة للخارج، كما هو موضح في الصورة."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "ضع جهازك على ركبتك اليمنى بحيث تكون الشاشة موجهة للخارج، كما هو موضح في الصورة."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "عندما تكون مستعدًا، اضغط على الشاشة للبدء ومُد ركبتك اليسرى قدر استطاعتك. ارجع إلى وضع البداية واضغط مرة أخرى عندما تنتهي."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "عندما تكون مستعدًا، اضغط على الشاشة للبدء ومُد ركبتك اليمنى قدر استطاعتك. ارجع إلى وضع البداية واضغط مرة أخرى عندما تنتهي."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "ضع جهازك على ركبتك اليسرى. اضغط على الشاشة ومُد ركبتك اليسرى قدر استطاعتك."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "ضع جهازك على ركبتك اليمنى. اضغط على الشاشة ومُد ركبتك اليمنى قدر استطاعتك."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "عندما تنتهي، أرجع ركبتك اليسرى إلى وضع البداية، ثم اضغط في أي مكان."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "عندما تنتهي، أرجع ركبتك اليمنى إلى وضع البداية، ثم اضغط في أي مكان."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "نطاق حركة الكتف الأيسر"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "نطاق حركة الكتف الأيمن"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "يقيس هذا النشاط إلى أي مدى يمكنك تمديد كتفك الأيسر."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "يقيس هذا النشاط إلى أي مدى يمكنك تمديد كتفك الأيمن."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "عند البدء ستضع جهازك على كتفك الأيسر لإجراء قياس. الرجاء تشغيل الصوت على جهازك حتى تتمكن من سماع التعليمات."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "عند البدء ستضع جهازك على كتفك الأيمن لإجراء قياس. الرجاء تشغيل الصوت على جهازك حتى تتمكن من سماع التعليمات."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "ضع جهازك على كتفك الأيسر بحيث تكون الشاشة موجهة للخارج، كما هو موضح في الصورة."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "ضع جهازك على كتفك الأيمن بحيث تكون الشاشة موجهة للخارج، كما هو موضح في الصورة."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "عندما تكون مستعدًا، اضغط على الشاشة للبدء وارفع ذراعك اليسرى قدر استطاعتك. ارجع إلى وضع البداية واضغط مرة أخرى عندما تنتهي."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "عندما تكون مستعدًا، اضغط على الشاشة للبدء وارفع ذراعك اليمنى قدر استطاعتك. ارجع إلى وضع البداية واضغط مرة أخرى عندما تنتهي."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "ضع جهازك على كتفك الأيسر. اضغط على الشاشة وارفع ذراعك اليسرى للأمام قدر المستطاع."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "ضع جهازك على كتفك الأيمن. اضغط على الشاشة وارفع ذراعك اليمنى للأمام قدر المستطاع."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "عندما تنتهي، أرجع ذراعك اليسرى إلى وضع البداية، ثم اضغط في أي مكان."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "عندما تنتهي، أرجع ذراعك اليمنى إلى وضع البداية، ثم اضغط في أي مكان."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "المشي المحدد بوقت"; +"TIMED_WALK_INTRO_DETAIL" = "يقيس هذا النشاط وظيفة الطرف السفلي لديك."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "ابحث عن مكان، ويفضل أن يكون بالخارج، يمكنك المشي فيه لمدة %@ تقريبًا في خط مستقيم بأقصى سرعة ممكنة، لكن بأمان. لا تبطئ من سرعتك إلى أن تجتاز خط النهاية."; +"TIMED_WALK_INTRO_2_DETAIL" = "اضغط على التالي للبدء."; +"TIMED_WALK_FORM_TITLE" = "الجهاز المساعد"; +"TIMED_WALK_FORM_TEXT" = "استخدم نفس الجهاز المساعد لكل اختبار."; +"TIMED_WALK_QUESTION_TEXT" = "هل ترتدي مقوام قدم وكاحل؟"; +"TIMED_WALK_QUESTION_2_TITLE" = "هل تستخدم جهازًا مساعدًا؟"; +"TIMED_WALK_QUESTION_2_TEXT" = "اضغط هنا لتحديد إجابة."; +"TIMED_WALK_QUESTION_2_CHOICE" = "لا شيء"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "عصا أحادية"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "عكاز أحادي"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "عصا ثنائية"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "عكاز ثنائي"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "مشاية"; +"TIMED_WALK_INSTRUCTION_%@" = "قم بالمشي حتى %@ في خط مستقيم."; +"TIMED_WALK_INSTRUCTION_TURN" = "قم بالدوران."; +"TIMED_WALK_INSTRUCTION_2" = "قم بالمشي رجوعًا إلى المكان الذي بدأت منه."; +"TIMED_WALK_INSTRUCTION_TEXT" = "اضغط على \“التالي\” عند الانتهاء."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "يقيس اختبار الجمع المتوالى السمعى المتواتر سرعة معالجة المعلومات السمعية والقدرة الحسابية."; +"PVSAT_INTRO_TEXT" = "يقيس اختبار الجمع المتوالى البصري المتواتر سرعة معالجة المعلومات المرئية والقدرة الحسابية."; +"PAVSAT_INTRO_TEXT" = "يقيس اختبار الجمع المتوالى السمعى البصري المتواتر سرعة معالجة المعلومات السمعية والمرئية والقدرة الحسابية."; +"PSAT_INTRO_TEXT_2_%@" = "يتم عرض أرقام فردية كل %@.\nيجب إضافة كل رقم جديد إلى الرقم الذي يسبقه مباشرةً.\nانتبه، لا يجب حساب مجموع مستمر، لكن فقط مجموع آخر رقمين."; +"PSAT_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"PSAT_INITIAL_INSTRUCTION" = "تذكر هذا العدد الأول."; +"PSAT_INSTRUCTION" = "اجمع هذا العدد الجديد على العدد السابق."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "‏%@-فحص السدادة والفتحة"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "هذا النشاط يقيس وظيفة الطرف العلوي من خلال مطالبتك بوضع السدادة في فتحة. سيُطلب منك أن تفعل هذا %@ مرات."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "سيتم اختبار كلتا يديك اليسرى واليمنى.\nيجب التقاط السدادة بأسرع ما يمكن ووضعها في الفتحة، وبمجرد فعل ذلك %@ مرات، قم بإزالتها مجددًا %@ مرات."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "سيتم اختبار كلتا يديك اليمنى واليسرى.\nيجب التقاط السدادة بأسرع ما يمكن ووضعها في الفتحة، وبمجرد فعل ذلك %@ مرات، قم بإزالتها مجددًا %@ مرات."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "ضع السدادة في الفتحة باليد اليسرى."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "ضع السدادة في الفتحة باليد اليمنى."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "ضع السدادة خلف السطر باليد اليسرى."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "ضع السدادة خلف السطر باليد اليمنى."; +"HOLE_PEG_TEST_TEXT" = "ارفع السدادة بإصبعين."; +"HOLE_PEG_TEST_TEXT_2" = "ارفع الأصابع لإسقاط السدادة."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "نشاط الرُعاش"; +"TREMOR_TEST_INTRO_1_DETAIL" = "يقيس هذا النشاط مقدار رُعاش يديك بمختلف الأوضاع. ابحث عن مكان يمكنك الجلوس فيه بشكل مريح أثناء مدة هذا النشاط."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "أمسك الهاتف في يدك الأكثر تأثرًا كما يظهر في الصورة أدناه."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "أمسك الهاتف في يدك اليمنى كما يظهر في الصورة أدناه."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "أمسك الهاتف في يدك اليسرى كما يظهر في الصورة أدناه."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "سيُطلب منك تنفيذ %@ أثناء الجلوس مع الإمساك بالهاتف في يديك."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "مهمة واحدة"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "مهمتان"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "ثلاث مهام"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "أربع مهام"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "خمس مهام"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "اضغط على التالي للمتابعة."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "استعد لإمساك هاتفك في حِجرك."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "استعد لإمساك هاتفك في حِجرك بيدك اليسرى."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "استعد لإمساك هاتفك في حِجرك بيدك اليمنى."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "استمر في إمساك هاتفك في حِجرك لمدة %ld من الثواني."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "الآن، أمسك هاتفك ويدك ممدودة في مستوى الكتف."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "الآن، أمسك هاتفك ويدك اليسرى ممدودة في مستوى الكتف."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "الآن، أمسك هاتفك ويدك اليمنى ممدودة في مستوى الكتف."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "استمر في إمساك هاتفك ويدك ممدودة لمدة %ld من الثواني."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "الآن، أمسك هاتفك في مستوى الكتف مع ثني مرفقك."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "الآن، أمسك هاتفك ويدك اليسرى في مستوى الكتف مع ثني مرفقك."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "الآن، أمسك هاتفك ويدك اليمنى في مستوى الكتف مع ثني مرفقك."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "استمر في إمساك هاتفك مع ثني مرفقك لمدة %ld من الثواني"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "الآن، مع الاستمرار في ثني مرفقك، المس الهاتف بأنفك بشكل متكرر."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "الآن، مع الاستمرار في ثني مرفقك والإمساك بالهاتف في يدك اليسرى، المس الهاتف بأنفك بشكل متكرر."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "الآن، مع الاستمرار في ثني مرفقك والإمساك بالهاتف في يدك اليمنى، المس الهاتف بأنفك بشكل متكرر."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "استمر في لمس الهاتف بأنفك لمدة %ld من الثواني"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "استعد للتلويح كالملوك (التلويح عن طريق تدوير معصمك)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "استعد للتلويح كالملوك مع إمساك هاتفك في يدك اليسرى (التلويح عن طريق تدوير معصمك)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "استعد للتلويح كالملوك مع إمساك هاتفك في يدك اليمنى (التلويح عن طريق تدوير معصمك)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "استمر في التلويح كالملوك لمدة %ld من الثواني."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "الآن، انقل الهاتف إلى يدك اليسرى وتابع إلى المهمة التالية."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "الآن، انقل الهاتف إلى يدك اليمنى وتابع إلى المهمة التالية."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "تابع إلى المهمة التالية."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "اكتمل النشاط."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "سيُطلب منك تنفيذ %@ أثناء الجلوس مع الإمساك بالهاتف في إحدى يديك، ثم تكرار ذلك باليد الأخرى."; +"TREMOR_SKIP_LEFT_HAND" = "لا يمكنني القيام بهذا النشاط بيدي اليسرى."; +"TREMOR_SKIP_RIGHT_HAND" = "لا يمكنني القيام بهذا النشاط بيدي اليمنى."; +"TREMOR_SKIP_NEITHER" = "يمكنني القيام بهذا النشاط بكلتا يدي."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "اختبار إجراء التعقب"; +"TRAILMAKING_INTENDED_USE" = "يعمل هذا النشاط على تقييم انتباهك البصري وتبديل المهام لديك عن طريق تسجيل الوقت اللازم للضغط على سلسلة من النقاط بالترتيب."; +"TRAILMAKING_INTENDED_USE2_A" = "بعد العد التنازلي، اضغط على النقاط بالتبادل بين الأرقام والحروف. ابدأ بالضغط على أول رقم \“١\” متبوعًا بالأرقام \“٢\”، \“٣\”، \“٤\”… حتى تصل إلى رقم \“٧\”."; +"TRAILMAKING_INTENDED_USE2_B" = "بعد العد التنازلي، اضغط على النقاط بالتبادل بين الأرقام والحروف. ابدأ بالضغط على أول رقم \“١\” ثم اضغط على أول حرف \“ا\”، ثم \“٢\”، \“ب\”، \“٣\”، \“ت\”… حتى تصل إلى رقم \“٧\”."; +"TRAILMAKING_INTRO_TEXT" = "افعل ذلك بأسرع ما يمكنك دون الوقوع في أخطاء. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"TRAILMAKING_LETTER_A" = "‎أ"; +"TRAILMAKING_LETTER_B" = "ب"; +"TRAILMAKING_LETTER_C" = "ت"; +"TRAILMAKING_LETTER_D" = "ث"; +"TRAILMAKING_LETTER_E" = "ج"; +"TRAILMAKING_LETTER_F" = "ح"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "التعرف على الكلام"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "يسجل هذا النشاط كلامك باستخدام الميكروفون في أسفل الجهاز، ويترجمه إلى نص."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "اضغط على البدء لكي تبدأ."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "اضغط على الزر لبدء التسجيل قبل النطق."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "بدء التسجيل"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "إيقاف التسجيل"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "تحرير النسخة المكتوبة"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "قم بتحرير نص النسخة المكتوبة لتصحيح أي خطأ في تفسير الكلام."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "النسخة المكتوبة ستظهر هنا."; +"SPEECH_RECOGNITION_FAILED" = "فشل التعرف على الكلام."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "فشلت تهيئة التعرّف على الكلام."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "تشغيل الصوت"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "إيقاف الصوت"; +"SPEECH_IN_NOISE_TITLE" = "التحدث في ضوضاء"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "يقيس هذا النشاط مدى وضوح الكلام عند نطقه في بيئات ضوضائية."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "كجزء من هذا الاختبار، ستفعل ما يلي:\n\nالاستماع إلى جملة.\n\nتكرار ما سمعته بوضوح أو التخطي لكتابة ما سمعته باستخدام لوحة المفاتيح.\n\nفي حالة تكرار ما سمعته، سيكون لديك الخيار لتعديل النسخة المكتوبة التي أنشأها محرك التعرّف على الكلام."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "معايرة مستوى الصوت"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "اضغط على \“تشغيل الصوت\”، اضبط مستوى الصوت على مستوى مريح لك ثم اضغط على \“إيقاف الصوت\” للمتابعة."; +"SPEECH_IN_NOISE_STEP_TITLE" = "استماع"; +"SPEECH_IN_NOISE_STEP_TEXT" = "سيتم تشغيل جملة لمرة واحدة، وهي جملة مختلطة بضوضاء في الخلفية بقيمة عشوائية لمعدل الإشارة إلى الضوضاء (SNR)."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "تحدث"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "كرر ما سمعته."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "تعذر إنشاء الملف"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "تعذر إزالة ملفات السجل الكافية للوصول إلى الحد"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "حدث خطأ في تعيين السمة"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "لم يتم تمييز الملف كمحذوف (لم يتم التمييز كـ \“تم التحميل\”)"; +"ERROR_DATALOGGER_MULTIPLE" = "حدثت عدة أخطاء أثناء إزالة السجلات"; +"ERROR_RECORDER_NO_DATA" = "لم يتم العثور على أي بيانات تم جمعها."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "لم يتم تحديد دليل إخراج"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "مقياس مستوى ضغط الصوت"; +"ENVIRONMENTSPL_INTRO_TEXT" = "يقيس هذا النشاط مستوى ضغط الصوت في البيئة المحيطة. إذا كانت مستويات الضوضاء عالية جدًا، فلن تتمكن من المتابعة. الرجاء الانتقال إلى موقع أهدأ لإكمال هذه المهمة أو إعادة هذا النشاط في وقت لاحق."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "جاري الحساب"; +"ENVIRONMENTSPL_THRESHOLD" = "الحد الأقصى: %@ dBA"; +"ENVIRONMENTSPL_OK" = "مستوى الضوضاء في الخلفية مقبول"; +"ENVIRONMENTSPL_NOISE" = "مستوى الضوضاء في الخلفية مرتفع جدًا"; +"ENVIRONMENTSPL_TITLE_2" = "ابحث عن مكان هادئ"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "لضمان الدقة، يجب إجراء هذا الاختبار في بيئة هادئة."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "بدء مهمة"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "لا توجد بيانات"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "حرّك شريط التمرير لإدخال قيمة"; +"SLIDER_I_DONT_KNOW" = "لا أعلم"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "صفحة"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "السابق"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "إظهار الصورة المصغرة للـ PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "إخفاء الصورة المصغرة للـ PDF"; +"AX_BUTTON_ANNOTATE" = "تعليق توضيحي"; +"AX_BUTTON_SHOW_SEARCH" = "إظهار شريط البحث"; +"AX_BUTTON_HIDE_SEARCH" = "إخفاء شريط البحث"; +"AX_BUTTON_SHARE" = "مشاركة"; + + +"AX_COMPLETION_ILLUSTRATION" = "رسم توضيحي لعلامة صح في دائرة زرقاء تشير إلى النجاح"; + +"AX_SIGNVIEW_LABEL" = "حقل التوقيع المخصص"; +"AX_SIGNVIEW_HINT" = "قم بلمس الشاشة وتحريك إصبعك للتوقيع"; +"AX_SIGNVIEW_SIGNED" = "موقّع"; +"AX_SIGNVIEW_UNSIGNED" = "غير موقّع"; + +"AX_SELECTED" = "محددة"; +"AX_UNSELECTED" = "غير محددة"; +"AX_SELECT_ALL_THAT_APPLY" = "تحديد كل الإجابات الصحيحة"; + +"AX_SLIDER_LABEL" = "شريط تمرير الاستجابة. النطاق من %@ إلى %@"; +"AX_UNLABELED_IMAGE" = "صورة بلا تسمية"; + +"AX_ANNOUNCE_BEGIN_TASK" = "بدء المهمة"; + +"AX.MEMORY.TILE.ACTIVE" = "نشط"; +"AX.MEMORY.TILE.CORRECT" = "صحيحة"; +"AX.MEMORY.TILE.INCORRECT" = "غير صحيحة"; +"AX.MEMORY.TILE.QUIESCENT" = "هادئ"; +"AX.MEMORY.TILE.LABEL" = "عنوان لعبة الذاكرة"; + +"AX_IMAGE_CAPTURE_LABEL" = "معاينة الالتقاط"; +"AX_IMAGE_CAPTURED_LABEL" = "تم التقاط الصورة"; + +"AX_VIDEO_CAPTURE_LABEL" = "معاينة التقاط الفيديو"; +"AX_VIDEO_CAPTURE_COMPLETE" = "اكتمال التقاط الفيديو"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "غير قادر على وضع القرص بحجم %@ على القرص بحجم %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "الهدف"; +"AX_TOWER_OF_HANOI_TOWER" = "برج"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "اضغط مرتين لوضع القرص"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "اضغط مرتين لتحديد أعلى قرص"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "يحتوي على أقراص بأحجام %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "فارغ"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "استبعاد لوحة المفاتيح"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "يتراوح من %@ إلى %@"; +"AX_GRAPH_STACK_PREFIX" = "مجموعة تتكون من"; +"AX_GRAPH_AND_SEPARATOR" = " و "; +"AX_GRAPH_POINT_%@" = "النقطة: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "شكل موجة الكلام"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "عندما يبدأ التسجيل، قم بالتنشيط مرة ثانية لإيقاف التسجيل."; + +"AX_AUDIO_BAR_GRAPH" = "الرسم البياني لشريط الصوت"; + +"AX_AMSLER_GRID_LABEL" = "شبكة أمسلر"; +"AX_AMSLER_GRID_HINT" = "استخدم إصبعك أو القلم لوضع العلامة في الشبكة مباشرةً، أو حرّك لليمين خارج الشبكة للإنهاء."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "أزرار قابلة للضغط"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "اضغط للأذن اليسرى"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "قم بالتنشيط لبدء الاختبار. عندما يبدأ الاختبار، اضغط مباشرة على هذا الزر عندما تسمع صوتًا في أذنك اليسرى."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "اضغط للأذن اليمنى"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "قم بالتنشيط لبدء الاختبار. عندما يبدأ الاختبار، اضغط مباشرة على هذا الزر عندما تسمع صوتًا في أذنك اليمنى."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "‏%@ باستخدام VoiceOver، استكشف الشاشة من خلال اللمس لتعرف أين توجد الأزرار الخاصة بكل أذن. عندما يبدأ الاختبار، ستكون الأزرار قابلة للضغط مباشرة. %@"; +"AX_TAP_BUTTON_1_LABEL" = "اضغط لإصبع واحد"; +"AX_TAP_BUTTON_2_LABEL" = "اضغط لإصبع آخر"; +"AX_TAP_BUTTON_HINT" = "قم بالتنشيط لتصبح الأزرار قابلة للضغط مباشرة."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "‏%@ باستخدام VoiceOver، استكشف الشاشة من خلال اللمس لتعرف أين توجد الأزرار. قم بتنشيط أحد الأزرار لتصبح الأزرار قابلة للضغط مباشرة."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "الأزرار الآن قابلة للضغط مباشرة."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "‏%@ باستخدام VoiceOver، سيكون الزر قابلاً للضغط مباشرة، وسيكون موجودُا بالقرب من منتصف الشاشة."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "‏%@ باستخدام VoiceOver، سيكون الزر قابلاً للضغط مباشرة."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "لا يمكن فك ترميز restoreData للتهيئة"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..1df1388 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ar.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (خطأ واحد) + other + (%d خطأ) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.strings new file mode 100755 index 0000000..9e6ec96 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentiment"; +"CONSENT_NAME_GIVEN" = "Nom"; +"CONSENT_NAME_FAMILY" = "Cognoms"; +"CONSENT_NAME_PLACEHOLDER" = "Obligatori"; +"CONSENT_REVIEW_TITLE" = "Revisió"; +"CONSENT_REVIEW_INSTRUCTION" = "Repassa el formulari de sota i toca Acceptar si estàs a punt per continuar."; +"CONSENT_REVIEW_ALERT_TITLE" = "Revisió"; +"CONSENT_SIGNATURE_TITLE" = "Signatura"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Signa amb el dit al requadre de sota."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Signa aquí"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Pàgina %1$ld de %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Benvingut"; +"CONSENT_SECTION_DATA_GATHERING" = "Recopilació de dades"; +"CONSENT_SECTION_PRIVACY" = "Privacitat"; +"CONSENT_SECTION_DATA_USE" = "Ús de dades"; +"CONSENT_SECTION_STUDY_SURVEY" = "Avaluació de l’estudi"; +"CONSENT_SECTION_STUDY_TASKS" = "Tasques d’estudi"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Temps necessari"; +"CONSENT_SECTION_WITHDRAWING" = "Abandonar"; +"CONSENT_LEARN_MORE_TITLE" = "Més informació"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Més informació sobre com es recopilen les dades"; +"LEARN_MORE_DATA_USE" = "Més informació sobre com s’utilitzen les dades"; +"LEARN_MORE_PRIVACY" = "Més informació sobre com es protegeix la privacitat i la identitat"; +"LEARN_MORE_WELCOME" = "Més informació sobre el primer estudi"; +"LEARN_MORE_STUDY_SURVEY" = "Més informació sobre l’avaluació de l’estudi"; +"LEARN_MORE_TIME_COMMITMENT" = "Més informació sobre com afecta l’estudi al teu temps"; +"LEARN_MORE_TASKS" = "Més informació sobre les tasques de l’estudi"; +"LEARN_MORE_WITHDRAWING" = "Més informació sobre l’abandonament"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opcions de compartir"; +"CONSENT_SHARE_WIDELY_%@" = "Compartir les meves dades amb %@ i investigadors qualificats de tot el món"; +"CONSENT_SHARE_ONLY_%@" = "Compartir només les meves dades amb %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ rebrà les teves dades de participació en aquest estudi.\n\nCompartir les dades codificades d’una manera més àmplia (sense informació com el nom) pot ser d’ajut en aquesta investigació i d’altres de futures."; +"LEARN_MORE_CONSENT_SHARING" = "Més informació sobre com compartir dades"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nom en majúscules"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signatura"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pregunta %1$@ de %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Omesa"; +"REVIEW_EDIT_ANSWER" = "Editar"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valor no vàlid"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ supera el valor màxim permès (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ és menys que el valor mínim permès (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ no és un valor vàlid."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Adreça electrònica no vàlida: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Escriu una adreça"; +"LOCATION_ERROR_TITLE" = "No s’ha trobat l‘adreça especificada"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "No s’ha pogut determinar la ubicació actual. Escriu una adreça o vés a un lloc que tingui un senyal de GPS més bo, si pot ser."; +"LOCATION_ERROR_MESSAGE_DENIED" = "S’ha denegat l’accés als serveis de localització. Dóna permís perquè l’app utilitzi els serveis de localització des de Configuració."; +"LOCATION_ERROR_GEOCODE" = "No s’ha trobat cap resultat per a l’adreça especificada. Comprova que sigui vàlida."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "O no tens connexió a internet o has superat el nombre màxim de peticions de cerca d’adreces. Si no tens connexió a internet, activa la Wi-Fi per contestar aquesta pregunta, passa aquesta pregunta si hi ha disponible un botó d’omissió o recupera l’enquesta quan et puguis connectar a internet. També pots tornar-ho a provar d’aquí a una mica."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "El contingut del text supera la llargada màxima: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "La càmera no està disponible amb la pantalla dividida."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Correu electrònic"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jmartorell@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Contrasenya"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Escriu la contrasenya"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmar"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Torna a escriure la contrasenya"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Les contrasenyes no coincideixen."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Més informació"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Jordi"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Martorell"; +"GENDER_FORM_ITEM_TITLE" = "Sexe"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Selecciona un sexe"; +"DOB_FORM_ITEM_TITLE" = "Data de naixement"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Selecciona una data"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Número de telèfon"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificació"; +"VERIFICATION_STEP_TITLE" = "Verifica el teu correu electrònic"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Prem l’enllaç de sota si no has rebut cap correu de verificació i vols que se’t torni a enviar."; +"RESEND_EMAIL_BUTTON_TITLE" = "Reenviar correu de verificació"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Iniciar sessió"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Contrasenya oblidada?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Escriu el codi"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirma el codi"; +"PASSCODE_SAVED_MESSAGE" = "Codi desat"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Codi autenticat"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Escriu el codi antic"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Escriu el codi nou"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirma el nou codi"; +"PASSCODE_INVALID_ALERT_TITLE" = "Codi incorrecte"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Els codis no coincideixen. Torna-ho a provar."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Identifica’t amb el Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Error de Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Només es permeten caràcters numèrics."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicador de progrés d’ingrés del codi"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ de %@ dígits introduïts"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Has oblidat el codi?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "No s’ha pogut afegir l’ítem del clauer."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "No s’ha pogut actualitzar l’ítem del clauer."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "No s’ha pogut eliminar l’ítem del clauer."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "No s’ha trobat l’ítem del clauer."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipus I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipus II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipus III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipus IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipus V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipus VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Dona"; +"GENDER_MALE" = "Home"; +"GENDER_OTHER" = "Altres"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Sí"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "esquerra"; +"LIMB_RIGHT" = "dreta"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toca per contestar"; +"NULL_ANSWER" = "Seleccionar una resposta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Prem per seleccionar"; +"PLACEHOLDER_LONG_TEXT" = "Prem per escriure"; + +/* Button titles */ +"BUTTON_AGREE" = "Acceptar"; +"BUTTON_CANCEL" = "Cancel·lar"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Esborrar"; +"BUTTON_CLEAR_SIGNATURE" = "Esborrar signatura"; +"BUTTON_APPLY" = "Aplicar"; +"BUTTON_DISAGREE" = "No acceptar"; +"BUTTON_DONE" = "Fet"; +"BUTTON_GET_STARTED" = "Començar"; +"BUTTON_LEARN_MORE" = "Més informació"; +"BUTTON_NEXT" = "Següent"; +"BUTTON_SKIP" = "Ometre"; +"BUTTON_SKIP_QUESTION" = "Ometre aquesta pregunta"; +"BUTTON_START_TIMER" = "Iniciar el temporitzador"; +"BUTTON_OPTION_SAVE" = "Desar per després"; +"BUTTON_OPTION_DISCARD" = "Descartar resultats"; +"BUTTON_OPTION_STOP_TASK" = "Finalitzar tasca"; +"BUTTON_SAVE" = "Desar"; +"BUTTON_CLEAR_ANSWER" = "Esborrar la resposta"; +"BUTTON_READ_ONLY_MODE" = "Aquesta resposta no es pot modificar."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Tancar"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Iniciant l’activitat en"; +"TASK_COMPLETE_TITLE" = "Activitat completada"; +"TASK_COMPLETE_TEXT" = "S’analitzaran les dades i rebràs una notificació quan tinguis els resultats a punt."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Queden %@."; +"TOUCH_ANYWHERE_LABEL" = "Toca a qualsevol lloc per continuar"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturar la imatge"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Tornar a capturar la imatge"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No s’ha trobat cap càmera. Aquest pas no es pot completar."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Per completar aquest pas, permet que aquesta app tingui accés a la càmera a Configuració."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No s’ha especificat cap directori de sortida per a les imatges capturades."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "No s’ha pogut desar la imatge capturada."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Iniciar la gravació"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Aturar la gravació"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Tornar a capturar el vídeo"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Activitat física"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distància (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Ritme cardíac (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Seu còmodament %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Camina tan ràpid com puguis durant %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Aquesta activitat controla la freqüència cardíaca i mesura la distància que pots caminar en %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Camina a l’aire lliure al ritme més alt que puguis durant %1$@. Transcorregut aquest temps, seu i descansa còmodament %2$@. Quan estiguis a punt, prem Començar."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Marxa i equilibri"; +"WALK_INTRO_TEXT" = "Aquesta activitat valora la marxa i l’equilibri quan camines i quan estàs quiet. No continuïs si no pots caminar sol de manera segura."; +"WALK_INTRO_2_TEXT_%ld" = "Busca un lloc on puguis caminar sense assistència de manera seguida uns %ld passos en línia recta."; +"WALK_INTRO_2_DETAIL" = "Posa’t el dispositiu a la butxaca o a la bossa i segueix les instruccions d’àudio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Ara estigues quiet %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Estigues quiet %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Fes mitja volta i torna allà on has començat."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Camina fins a %ld passos en línia recta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Busca un lloc on puguis anar i tornar caminant en línia recta de forma segura. Camina sense parar i gira al final del camí com si estiguessis vorejant un con.\n\nA continuació, se’t demanarà que giris fent un cercle complet i que et quedis quiet amb els braços als costats i els peus separats més o menys per la mateixa distància que hi ha entre espatlla i espatlla."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Quan estiguis a punt, toca Començar.\nLlavors, posa’t el dispositiu a la butxaca o a la bossa i segueix les instruccions d’àudio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Vés i torna caminant en línia recta durant %@. Camina naturalment."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Gira fent un cercle complet i llavors queda’t quiet durant %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Has completat l’activitat."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocitat de toc"; +"TAPPING_TASK_TITLE_RIGHT" = "Mà dreta"; +"TAPPING_TASK_TITLE_LEFT" = "Mà esquerra"; +"TAPPING_INTRO_TEXT" = "Aquesta activitat mesura la velocitat de toc."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Deixa el dispositiu sobre una superfície plana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Prem els botons de la pantalla alternant dos dits de la mateixa mà."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Prem els botons de la pantalla alternant dos dits de la mà dreta."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Prem els botons de la pantalla alternant dos dits de la mà esquerra."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Ara repeteix la mateixa operació amb la mà dreta."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Ara repeteix la mateixa operació amb la mà esquerra."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Toca amb un dit, i després amb l’altre. Intenta que el ritme de toc sigui constant. Toca durant %@."; +"TAPPING_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Prem Següent per continuar."; +"TAP_BUTTON_TITLE" = "Prem"; +"TOTAL_TAPS_LABEL" = "Tocs totals"; +"TAPPING_INSTRUCTION" = "Prem els botons amb dos dits al ritme més constant que puguis."; +"TAPPING_INSTRUCTION_RIGHT" = "Prem els botons amb la mà DRETA."; +"TAPPING_INSTRUCTION_LEFT" = "Prem els botons amb la mà ESQUERRA."; +"TAPPING_SKIP_TITLE" = "Ometre aquesta mà"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Reixeta d’Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Aquesta activitat ajuda a detectar problemes de visió de l’usuari."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Mantén el dispositiu a una distància de 30 a 40 centímetres de la teva cara, a l’alçada dels ulls, durant tota la prova."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Tanca l’%@ i mira fixament el punt central de la quadrícula.\n\nAmb el dit o el llapis tàctil, marca les distorsions que vegis, com ara línies borroses o ondulades.\n\nQuan hagis acabat, llisca cap a l’esquerra a qualsevol lloc de l’exterior de la reixeta."; +"AMSLER_GRID_LEFT_EYE" = "ull esquerre"; +"AMSLER_GRID_RIGHT_EYE" = "ull dret"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Veu"; +"AUDIO_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"AUDIO_INSTRUCTION" = "Fes un “Aaaaah” tan llarg com puguis al micròfon."; +"AUDIO_INTRO_TEXT" = "Inspira profundament i fes un “Aaaaah” tan llarg com puguis al micròfon. Mantingues un volum de veu estable fent que les barres d’àudio es mantinguin en blau."; +"AUDIO_INTENDED_USE" = "Aquesta activitat avalua la teva veu tot gravant‑la amb el micròfon de la part inferior del dispositiu."; +"AUDIO_TOO_LOUD_LABEL" = "Massa alt"; +"AUDIO_GENERIC_ERROR_LABEL" = "No s’ha pogut gravar l’àudio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Espera mentre es calcula el nivell de soroll de fons."; +"AUDIO_TOO_LOUD_MESSAGE" = "El soroll ambiental és massa fort per gravar la teva veu. Vés a un lloc més silenciós i torna‑ho a provar."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Prem Següent quan estiguis a punt."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonal"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Aquesta activitat mesura la capacitat de sentir diversos sons."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Abans de començar, connecta els auriculars i posa‑te’ls.\n\nEl so serà molt subtil, diferent d’un so d’avís normal. El so començarà baix i anirà pujant de volum. Presta atenció i toca el botó esquerre o el dret per indicar l’orella per on sents el so."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ara hauries d’escoltar un so. Ajusta el volum amb els controls de la part lateral del dispositiu.\n\nToca qualsevol botó quan estiguis a punt per començar."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Cada cop que comencis a sentir un so, toca el botó esquerre o el dret per indicar per quina orella el sents."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Orella esquerra"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Orella dreta"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, esquerra"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, dreta"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonal"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Toca quan sentis un so."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "So i volum"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Sentiràs una seqüència de sons."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Cada vegada que sentis un so, toca el botó."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Per fer aquesta prova, s’ajustarà el volum al 50 per cent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Aquesta prova dura uns 10 minuts."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activa “No molestar” per evitar interrupcions."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Ara els sons es reproduiran primer a l’orella dreta."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Ara els sons es reproduiran a l’orella esquerra."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Aquesta activitat identifica els nivells llindar d’audició d’una persona en l’escala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Comprova que el volum del dispositiu estigui al nivell màxim.\n\nDurant aquesta tasca, es reproduirà un so subtil a l’orella esquerra o dreta.\n\nEscolta atentament i toca el botó cada vegada que sentis un so."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Aquesta prova identifica com de fort ha de ser un so perquè el sentis."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Qüestionari inicial."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecciona la teva preferència de “millor orella”, si cal"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "esquerra"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "dreta"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "cap preferència"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Prova cancel·lada"; +"dBHL_ALERT_TITLE_START_OVER" = "Tornar a començar"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancel·lar la prova"; +"dBHL_ALERT_TEXT" = "Torna a connectar els AirPods o els EarPods per fer la prova."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ completat"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Auriculars"; +"HEADPHONES_UNKNOWN" = "Desconegut"; +"HEADPHONES_NONE" = "Cap"; +"CONNECTED" = "Connectat"; +"NOT_CONNECTED" = "Sense connexió"; +"HEADPHONE_CONNECTED_%@" = "Connectat - %@"; +"HEADPHONE_DETECT_TITLE" = "Connecta els auriculars"; +"HEADPHONE_DETECT_TEXT" = "Per fer aquesta prova necessitaràs uns AirPods o uns EarPods d’Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memòria espacial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Aquesta activitat mesura la memòria espacial a curt termini demanant-te que repeteixis l’ordre en què s’il·luminen les %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flors"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flors"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Algunes de les %@ s’il·luminaran d’una en una. Prem les %@ en qüestió en l’ordre en què s’hagin il·luminat."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Algunes de les %@ s’il·luminaran d’una en una. Prem les %@ en qüestió en l’ordre invers en què s’hagin il·luminat."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Per començar, prem Començar i mira atentament."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Puntuació"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Mira com s’il·luminen les imatges de %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Prem les %@ en l’ordre en què s’han il·luminat"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Prem les %@ en ordre invers"; +"MEMORY_GAME_COMPLETE_TITLE" = "Seqüència completa"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Per continuar, prem Següent"; +"MEMORY_GAME_FAILED_TITLE" = "Reintentar"; +"MEMORY_GAME_FAILED_MESSAGE" = "No ho has aconseguit aquesta vegada. Prem Següent per continuar."; +"MEMORY_GAME_TIMEOUT_TITLE" = "S’ha acabat el temps"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "T’has quedat sense temps.\nToca Següent per continuar."; +"MEMORY_GAME_COMPLETE" = "Joc completat"; +"MEMORY_GAME_PAUSED_TITLE" = "En pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Per continuar, prem Següent"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "L’activitat de memòria s’ha desenvolupat amb l’ajuda de la Dra. Katherine Possin i el Dr. Joel Kramer, de la Universitat de Califòrnia, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Temps de reacció"; +"REACTION_TIME_TASK_INTENDED_USE" = "Aquesta activitat avalua el temps que trigues a respondre a un senyal visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Agita el dispositiu en qualsevol direcció de seguida que aparegui el punt blau a la pantalla. Se’t demanarà que facis això %D vegades."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Intent %@ de %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Agita ràpidament el dispositiu quan aparegui el cercle blau"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Colors i paraules"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Cada cop que aparegui una paraula, selecciona la primera lletra del nom del COLOR que es mostra."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Quan estiguis a punt per començar l’activitat “Colors i paraules”, prem Començar."; +"STROOP_TASK_STEP_TEXT" = "Selecciona la primera lletra del nom del COLOR que es mostra."; +"STROOP_COLOR_RED" = "ROIG"; +"STROOP_COLOR_GREEN" = "VERD"; +"STROOP_COLOR_BLUE" = "BLAU"; +"STROOP_COLOR_YELLOW" = "GROC"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "G"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre de Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Aquesta activitat valora la teva capacitat de resoldre trencaclosques."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Trasllada tota la pila a la plataforma ressaltada en el mínim de moviments possibles."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Resol el joc"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Nombre de moviments: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "No puc resoldre aquest joc"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Amplitud de moviment"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption ha de ser dreta o esquerra"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rang de moviment del genoll esquerre"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rang de moviment del genoll dret"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aquesta activitat mesura el grau d’extensió del teu genoll esquerre."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aquesta activitat mesura el grau d’extensió del teu genoll dret."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Seu a la punta d’una cadira. Quan comencis, et posaràs el dispositiu a sobre del genoll esquerre per prendre una mesura. Activa el so del dispositiu per poder sentir les instruccions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Seu a la punta d’una cadira. Quan comencis, et posaràs el dispositiu a sobre del genoll dret per prendre una mesura. Activa el so del dispositiu per poder sentir les instruccions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posa’t el dispositiu a sobre del genoll esquerre amb la pantalla cap enfora, tal com es mostra."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posa’t el dispositiu a sobre del genoll dret amb la pantalla cap enfora, tal com es mostra."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quan estiguis preparat, toca la pantalla per començar i estira el genoll esquerre tant com puguis. Torna a la posició inicial i toca la pantalla un altre cop quan hagis acabat."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quan estiguis preparat, toca la pantalla per començar i estira el genoll dret tant com puguis. Torna a la posició inicial i toca la pantalla un altre cop quan hagis acabat."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Posa’t el dispositiu a sobre del genoll esquerre. Toca la pantalla i estira el genoll esquerre tant com puguis."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Posa’t el dispositiu a sobre del genoll dret. Toca la pantalla i estira el genoll dret tant com puguis."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quan hagis acabat, torna a posar el genoll esquerre en la posició inicial. Aleshores, toca qualsevol punt de la pantalla."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quan hagis acabat, torna a posar el genoll dret en la posició inicial. Aleshores, toca qualsevol punt de la pantalla."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rang de moviment de l’espatlla esquerra"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rang de moviment de l’espatlla dreta"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aquesta activitat mesura el grau d’extensió de la teva espatlla esquerra."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aquesta activitat mesura el grau d’extensió de la teva espatlla dreta."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Quan comencis, et posaràs el dispositiu a sobre de l’espatlla esquerra per prendre una mesura. Activa el so del dispositiu per poder sentir les instruccions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Quan comencis, et posaràs el dispositiu a sobre de l’espatlla dreta per prendre una mesura. Activa el so del dispositiu per poder sentir les instruccions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posa’t el dispositiu a sobre de l’espatlla esquerra amb la pantalla cap enfora, tal com es mostra."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posa’t el dispositiu a sobre de l’espatlla dreta amb la pantalla cap enfora, tal com es mostra."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quan estiguis preparat, toca la pantalla per començar i aixeca el braç esquerre tant com puguis. Torna a la posició inicial i toca la pantalla un altre cop quan hagis acabat."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quan estiguis preparat, toca la pantalla per començar i aixeca el braç dret tant com puguis. Torna a la posició inicial i toca la pantalla un altre cop quan hagis acabat."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Posa’t el dispositiu a sobre de l’espatlla esquerra. Toca la pantalla i aixeca el braç esquerre cap endavant tant com puguis."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Posa’t el dispositiu a sobre de l’espatlla dreta. Toca la pantalla i aixeca el braç dret cap endavant tant com puguis."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quan hagis acabat, torna a posar el braç esquerre en la posició inicial. Aleshores, toca qualsevol punt de la pantalla."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quan hagis acabat, torna a posar el braç dret en la posició inicial. Aleshores, toca qualsevol punt de la pantalla."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Caminada cronometrada"; +"TIMED_WALK_INTRO_DETAIL" = "Aquesta activitat mesura la funcionalitat de les teves extremitats inferiors."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Busca un lloc, preferiblement a l’aire lliure, on puguis caminar aproximadament %@ en línia recta tan ràpid com puguis, amb total seguretat. No abaixis el ritme fins que no hagis passat la línia d’arribada."; +"TIMED_WALK_INTRO_2_DETAIL" = "Prem Següent per continuar."; +"TIMED_WALK_FORM_TITLE" = "Tipus d’assistència"; +"TIMED_WALK_FORM_TEXT" = "Utilitza el mateix tipus d’assistència per a cada prova."; +"TIMED_WALK_QUESTION_TEXT" = "Portes una ortesi al peu i turmell?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Fas servir algun tipus d’assistència?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Prem aquí per respondre."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Cap"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Un bastó"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Una crossa"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dos bastons"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dues crosses"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Caminador"; +"TIMED_WALK_INSTRUCTION_%@" = "Camina fins a %@ en línia recta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Canvia de sentit."; +"TIMED_WALK_INSTRUCTION_2" = "Torna allà on has començat."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Prem Següent quan hagis acabat."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "El PAST (test auditiu de suma en sèrie a ritme) mesura la teva velocitat de processament d’informació auditiva i la teva habilitat de càlcul."; +"PVSAT_INTRO_TEXT" = "El PAVT (test visual de suma en sèrie a ritme) mesura la teva velocitat de processament d’informació visual i la teva habilitat de càlcul."; +"PAVSAT_INTRO_TEXT" = "El PAVSAT (test visual i auditiu de suma en sèrie per passos) mesura la teva velocitat de processament d’informació auditiva i visual i la teva habilitat de càlcul."; +"PSAT_INTRO_TEXT_2_%@" = "Es presenten números solts cada %@ segons.\nHas de sumar cada nou número al número immediatament anterior.\nAtenció: No has d’anar calculant la suma total, sinó només la suma dels dos últims números."; +"PSAT_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"PSAT_INITIAL_INSTRUCTION" = "Recorda aquest primer dígit."; +"PSAT_INSTRUCTION" = "Suma aquest número a l’anterior."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test de les %@ clavilles"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Aquesta activitat mesura la funcionalitat de les teves extremitats superiors demanant-te que fiquis una clavilla dins d’un forat. Ho hauràs de fer %@ cops."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "S’avaluaran la mà esquerra i la dreta.\nHas d’agafar la clavilla tan ràpid com puguis, posar‑la al forat i, un cop fet %@ cops, tornar‑la a treure %@ cops."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "S’avaluaran la mà dreta i l’esquerra.\nHas d’agafar la clavilla tan ràpid com puguis, posar‑la al forat i, un cop fet %@ cops, tornar‑la a treure %@ cops."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Posa la clavilla al forat amb la mà esquerra."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Posa la clavilla al forat amb la mà dreta."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Posa la clavilla darrere de la línia amb la mà esquerra."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Posa la clavilla darrere de la línia amb la mà dreta."; +"HOLE_PEG_TEST_TEXT" = "Agafa la clavilla fent servir dos dits."; +"HOLE_PEG_TEST_TEXT_2" = "Aixeca els dits per deixar caure la clavilla."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Activitat de tremolor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Aquesta activitat mesura la tremolor de les mans en diferents posicions. Busca un lloc on puguis seure còmodament per fer aquesta activitat."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Agafa el mòbil amb la mà més afectada, tal com es mostra a la imatge de sota."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Agafa el mòbil amb la mà DRETA, tal com es mostra a la imatge de sota."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Agafa el mòbil amb la mà ESQUERRA, tal com es mostra a la imatge de sota."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Quan estiguis assegut i amb el mòbil a la mà, se’t demanarà que completis %@."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "una tasca"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dues tasques"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tres tasques"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quatre tasques"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinc tasques"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Prem Següent per començar."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepara’t per agafar el mòbil i recolzar la mà sobre la falda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepara’t per agafar el mòbil amb la mà ESQUERRA i recolzar aquesta mà sobre la falda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepara’t per agafar el mòbil amb la mà DRETA i recolzar aquesta mà sobre la falda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Agafa el mòbil i recolza la mà sobre la falda durant %ld segons."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Ara agafa el mòbil i mantén el braç estirat cap enfora a l’altura de l’espatlla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Ara agafa el mòbil amb la mà ESQUERRA i mantén el braç esquerre estirat cap enfora a l’altura de l’espatlla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Ara agafa el mòbil amb la mà DRETA i mantén el braç dret estirat cap enfora a l’altura de l’espatlla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Agafa el mòbil i mantén el braç estirat cap enfora durant %ld segons."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Ara agafa el mòbil i mantén la mà a l’altura de l’espatlla amb el colze doblegat."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Ara agafa el mòbil i mantén la mà ESQUERRA a l’altura de l’espatlla amb el colze doblegat."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Ara agafa el mòbil i mantén la mà DRETA a l’altura de l’espatlla amb el colze doblegat."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Agafa el mòbil i mantén el colze doblegat durant %ld segons."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Ara, amb el colze doblegat, toca el mòbil amb el nas repetidament."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Ara, amb el colze doblegat i el mòbil a la mà ESQUERRA, toca el mòbil amb el nas repetidament."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Ara, amb el colze doblegat i el mòbil a la mà DRETA, toca el mòbil amb el nas repetidament."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Toca el mòbil amb el nas durant %ld segons."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepara’t per fer una salutació reial fent girar el canell amb el mòbil a la mà."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepara’t per fer una salutació reial fent girar el canell amb el mòbil a la mà ESQUERRA."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepara’t per fer una salutació reial fent girar el canell amb el mòbil a la mà DRETA."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Fes una salutació reial durant %ld segons."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Ara agafa el mòbil amb la mà ESQUERRA i avança a la tasca següent."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Ara agafa el mòbil amb la mà DRETA i avança a la tasca següent."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Avança a la tasca següent."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activitat completada."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Quan estiguis assegut i amb el mòbil a la mà, se’t demanarà que completis %@, primer amb una mà i després amb l’altra."; +"TREMOR_SKIP_LEFT_HAND" = "No puc completar l’activitat amb la mà ESQUERRA."; +"TREMOR_SKIP_RIGHT_HAND" = "No puc completar l’activitat amb la mà DRETA."; +"TREMOR_SKIP_NEITHER" = "Puc completar l’activitat amb les dues mans."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Unir els punts"; +"TRAILMAKING_INTENDED_USE" = "Aquesta activitat avalua la teva atenció visual i la teva capacitat de canvi de tasques comptant el temps que necessites per tocar una sèrie de punts en ordre."; +"TRAILMAKING_INTENDED_USE2_A" = "Després del compte enrere, vés tocant punts alternant l’ordre entre nombres i lletres. Comença tocant el primer número, 1, i després els números 2, 3, 4…, fins que arribis al número 7."; +"TRAILMAKING_INTENDED_USE2_B" = "Després del compte enrere, ves tocant punts alternant l’ordre entre nombres i lletres. Comença tocant el primer número, 1, i després la primera lletra, A, i tot seguit, 2, B, 3, C, fins que arribis al número 7."; +"TRAILMAKING_INTRO_TEXT" = "Fes‑ho tant ràpid com puguis sense equivocar‑te. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconeixement de veu"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Aquesta activitat grava el que dius amb el micròfon de la part inferior del dispositiu i després ho converteix a text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Per iniciar, toca Començar."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Abans de parlar, prem el botó per començar a gravar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Iniciar la gravació"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Aturar la gravació"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edita la transcripció"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edita la transcripció per corregir les malinterpretacions del text parlat."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "La transcripció apareixerà aquí."; +"SPEECH_RECOGNITION_FAILED" = "El reconeixement de veu ha fallat."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "No s’ha pogut iniciar el reconeixement de veu."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproduir l’àudio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Aturar l’àudio"; +"SPEECH_IN_NOISE_TITLE" = "Parlat amb soroll"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Aquesta activitat mesura la intel·ligibilitat del text parlat quan hi ha soroll de fons."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Com a part d’aquesta prova, hauràs de fer el següent:\n\nEscoltar una frase.\n\nRepetir amb claredat el que hagis sentit o escriure directament el que hagis sentit amb el teclat.\n\nSi repeteixes el que has sentit, podràs modificar la transcripció generada per l’eina de reconeixement de veu."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibratge del volum"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Toca “Reproduir l’àudio”, ajusta el volum a un nivell agradable i després toca “Aturar l’àudio” per continuar."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Escolta"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Es reproduirà només una vegada una frase amb soroll de fons en una relació senyal‑soroll (SNR) aleatòria."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Parla"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repeteix el que hagis sentit."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "No s’ha pogut crear l’arxiu"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "No s’han pogut eliminar prou arxius de registre per assolir el llindar"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error al configurar atribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Arxiu no marcat eliminat (no marcat carregat)"; +"ERROR_DATALOGGER_MULTIPLE" = "Diversos errors a l’eliminar registres"; +"ERROR_RECORDER_NO_DATA" = "No s’han trobat dades recollides."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "No s’ha especificat cap directori de sortida"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Sonòmetre"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Aquesta activitat mesura el nivell de pressió sonora de l’entorn. Si els nivells de soroll són molt alts, no la podràs fer. Vés a un lloc més tranquil per realitzar aquesta tasca o reprèn l’activitat més tard."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculant"; +"ENVIRONMENTSPL_THRESHOLD" = "Llindar: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Soroll de fons acceptable"; +"ENVIRONMENTSPL_NOISE" = "Hi ha massa soroll de fons"; +"ENVIRONMENTSPL_TITLE_2" = "Busca un lloc tranquil"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Perquè el resultat de la prova sigui precís, has d’estar en un entorn tranquil."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Iniciar tasca"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Sense dades"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Mou el regulador per fixar un valor"; +"SLIDER_I_DONT_KNOW" = "No ho sé"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Pàgina"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Enrere"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostrar la miniatura del PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ocultar la miniatura del PDF"; +"AX_BUTTON_ANNOTATE" = "Anotar"; +"AX_BUTTON_SHOW_SEARCH" = "Mostrar la barra de cerca"; +"AX_BUTTON_HIDE_SEARCH" = "Ocultar la barra de cerca"; +"AX_BUTTON_SHARE" = "Compartir"; + + +"AX_COMPLETION_ILLUSTRATION" = "Il·lustració d’una marca de verificació dins d’un cercle blau que significa que l’activitat s’ha completat amb èxit"; + +"AX_SIGNVIEW_LABEL" = "Camp designat de signatura"; +"AX_SIGNVIEW_HINT" = "Toca la pantalla i mou el dit per signar"; +"AX_SIGNVIEW_SIGNED" = "Signat"; +"AX_SIGNVIEW_UNSIGNED" = "Sense signar"; + +"AX_SELECTED" = "Seleccionat"; +"AX_UNSELECTED" = "No seleccionat"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECCIONA TOT ALLÒ QUE CORRESPONGUI"; + +"AX_SLIDER_LABEL" = "Regulador de resposta. Interval de %@ a %@"; +"AX_UNLABELED_IMAGE" = "Imatge sense etiquetar"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Començar tasca"; + +"AX.MEMORY.TILE.ACTIVE" = "actiu"; +"AX.MEMORY.TILE.CORRECT" = "correcte"; +"AX.MEMORY.TILE.INCORRECT" = "incorrecte"; +"AX.MEMORY.TILE.QUIESCENT" = "inactiu"; +"AX.MEMORY.TILE.LABEL" = "Joc de memòria"; + +"AX_IMAGE_CAPTURE_LABEL" = "Previsualització de la captura"; +"AX_IMAGE_CAPTURED_LABEL" = "Imatge capturada"; + +"AX_VIDEO_CAPTURE_LABEL" = "Previsualització de la captura de vídeo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captura de vídeo completa"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "No s’ha pogut situar el disc de mida %@ sobre el disc de mida %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Objectiu"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Prem dos cops per situar el disc"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Prem dos cops per seleccionar el disc superior"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Té disc amb mides %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Buidar"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Tancar teclat"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Interval de %@ a %@"; +"AX_GRAPH_STACK_PREFIX" = "Pila composta per"; +"AX_GRAPH_AND_SEPARATOR" = " i "; +"AX_GRAPH_POINT_%@" = "Punt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Ona de veu"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Quan hagi començat la gravació, torna a activar per aturar‑la."; + +"AX_AUDIO_BAR_GRAPH" = "Gràfic de barres d’àudio"; + +"AX_AMSLER_GRID_LABEL" = "Reixeta d’Amsler"; +"AX_AMSLER_GRID_HINT" = "Fes servir el dit o el llapis tàctil per marcar la reixeta directament o llisca cap a l’esquerra a l’exterior de la reixeta per acabar."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Botons que es poden tocar"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tocar per a l’orella esquerra"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activa’l per començar la prova. Quan comenci, toca directament aquest botó quan sentis un so a l’orella esquerra."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tocar per a l’orella dreta"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activa’l per començar la prova. Quan comenci, toca directament aquest botó quan sentis un so a l’orella dreta."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Amb el VoiceOver, explora la pantalla tocant-la per descobrir on són els botons per a cada orella. Quan comenci la prova, podràs tocar els botons directament. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tocar per a un dit"; +"AX_TAP_BUTTON_2_LABEL" = "Tocar per a un altre dit"; +"AX_TAP_BUTTON_HINT" = "Activa’l per poder tocar els botons directament."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Amb el VoiceOver, explora la pantalla tocant-la per descobrir on són els botons. Activa un dels botons per fer que es puguin tocar directament."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Ara pots tocar els botons directament."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Amb el VoiceOver, podràs tocar el botó directament. Estarà ubicat a prop del centre de la pantalla."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Amb el VoiceOver, podràs tocar els botons de la prova directament."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "No es pot descodificar restoreData per inicialitzar"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..edd4158 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ca.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errors) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.strings new file mode 100755 index 0000000..c7cb464 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Souhlas"; +"CONSENT_NAME_GIVEN" = "Jméno"; +"CONSENT_NAME_FAMILY" = "Příjmení"; +"CONSENT_NAME_PLACEHOLDER" = "Požadováno"; +"CONSENT_REVIEW_TITLE" = "Kontrola"; +"CONSENT_REVIEW_INSTRUCTION" = "Projděte si formulář níže, a až budete připraveni pokračovat, klepněte na Souhlasím."; +"CONSENT_REVIEW_ALERT_TITLE" = "Kontrola"; +"CONSENT_SIGNATURE_TITLE" = "Podpis"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Podepište se prstem do rámečku níže."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Zde se podepište"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Stránka %1$ld z %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Vítejte"; +"CONSENT_SECTION_DATA_GATHERING" = "Shromažďování dat"; +"CONSENT_SECTION_PRIVACY" = "Soukromí"; +"CONSENT_SECTION_DATA_USE" = "Využití dat"; +"CONSENT_SECTION_STUDY_SURVEY" = "Studijní průzkum"; +"CONSENT_SECTION_STUDY_TASKS" = "Studijní úkoly"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Věnovaný čas"; +"CONSENT_SECTION_WITHDRAWING" = "Odstoupení"; +"CONSENT_LEARN_MORE_TITLE" = "Další informace"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Informace o shromažďování dat"; +"LEARN_MORE_DATA_USE" = "Informace o způsobech využití dat"; +"LEARN_MORE_PRIVACY" = "Informace o ochraně soukromí a identity"; +"LEARN_MORE_WELCOME" = "Úvodní informace o studii"; +"LEARN_MORE_STUDY_SURVEY" = "Informace o realizaci průzkumu"; +"LEARN_MORE_TIME_COMMITMENT" = "Informace o dopadu studie na váš čas"; +"LEARN_MORE_TASKS" = "Informace o úkolech obsažených ve studii"; +"LEARN_MORE_WITHDRAWING" = "Informace o odstoupení od studie"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Volby sdílení"; +"CONSENT_SHARE_WIDELY_%@" = "Sdílet data se společností %@ a kvalifikovanými výzkumnými pracovišti na celém světě"; +"CONSENT_SHARE_ONLY_%@" = "Sdílet data pouze se společností %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "Data z vaší účasti v této studii obdrží %@.\n\nŠirší sdílení vašich dat v zakódované formě (a bez údajů, jako je vaše jméno) může být prospěšné pro současný i budoucí výzkum."; +"LEARN_MORE_CONSENT_SHARING" = "Další informace o sdílení dat"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Jméno hůlkovým písmem"; +"CONSENT_DOC_LINE_SIGNATURE" = "Podpis"; +"CONSENT_DOC_LINE_DATE" = "Datum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ z %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Otázka %1$@ z %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Přeskočeno"; +"REVIEW_EDIT_ANSWER" = "Upravit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Neplatná hodnota"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ přesahuje maximální povolenou hodnotu (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ nedosahuje minimální povolené hodnoty (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ není platná hodnota."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Neplatná e‑mailová adresa: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Zadejte adresu"; +"LOCATION_ERROR_TITLE" = "Zadanou adresu se nepodařilo najít"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Vaši aktuální polohu nelze zjistit. Zadejte adresu nebo se přesuňte na místo s lepším GPS signálem, je‑li to možné."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Přístup k polohovým službám byl odepřen. Přejděte do Nastavení a udělte této aplikaci oprávnění k používání polohových služeb."; +"LOCATION_ERROR_GEOCODE" = "Pro zadanou adresu se nepodařilo najít výsledek. Ověřte správnost adresy."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Nejste připojeni k internetu nebo jste překročili maximální počet žádostí o vyhledání adresy. Pokud nejste připojeni k internetu a chcete tuto otázku zodpovědět, zapněte Wi‑Fi. Je‑li k dispozici tlačítko přeskočit, můžete otázku přeskočit nebo se můžete k průzkumu vrátit, až bude internet dostupný. Případně to můžete zkusit za několik minut znovu."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Text překračuje maximální délku: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Fotoaparát není na rozdělené obrazovce k dispozici."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E‑mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jnovak@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Heslo"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Zadejte heslo"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Potvrzení"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Zadejte heslo ještě jednou"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Hesla se neshodují."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Doplňující informace"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Jan"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Novák"; +"GENDER_FORM_ITEM_TITLE" = "Pohlaví"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Vyberte pohlaví"; +"DOB_FORM_ITEM_TITLE" = "Datum narození"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Vyberte datum"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonní číslo"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Ověření"; +"VERIFICATION_STEP_TITLE" = "Ověřte svůj e-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Pokud jste neobdrželi ověřovací e‑mail a chcete, abychom vám ho zaslali znovu, klepněte na odkaz níže."; +"RESEND_EMAIL_BUTTON_TITLE" = "Znovu odeslat ověřovací e‑mail"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Přihlásit se"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Zapomenuté heslo?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Zadejte kód"; +"PASSCODE_CONFIRM_MESSAGE" = "Potvrďte kód"; +"PASSCODE_SAVED_MESSAGE" = "Kód byl uložen"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kód byl ověřen"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Zadejte starý kód"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Zadejte nový kód"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Potvrďte nový kód"; +"PASSCODE_INVALID_ALERT_TITLE" = "Nesprávný kód"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Kódy se neshodují. Zkuste to znovu."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Použijte ověření pomocí Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Chyba Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Jsou povoleny jen číselné znaky."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indikátor průběhu zadávání kódu"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Zadané číslice: %@ z %@"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Zapomenutý kód?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nepodařilo se přidat položku do svazku klíčů."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nepodařilo se aktualizovat položku ve svazku klíčů."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nepodařilo se smazat položku ze svazku klíčů."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Nepodařilo se najít položku ve svazku klíčů."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Typ I"; +"FITZPATRICK_SKIN_TYPE_II" = "Typ II"; +"FITZPATRICK_SKIN_TYPE_III" = "Typ III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Typ IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Typ V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Typ VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Žena"; +"GENDER_MALE" = "Muž"; +"GENDER_OTHER" = "Jiné"; + +/* Boolean answer strings */ +"BOOL_NO" = "Ne"; +"BOOL_YES" = "Ano"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "vlevo"; +"LIMB_RIGHT" = "vpravo"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Odpověď"; +"NULL_ANSWER" = "Vyberte odpověď"; +"PLACEHOLDER_IMAGE_CHOICES" = "Chcete‑li vybrat, klepněte"; +"PLACEHOLDER_LONG_TEXT" = "Chcete-li psát, klepněte"; + +/* Button titles */ +"BUTTON_AGREE" = "Souhlasím"; +"BUTTON_CANCEL" = "Zrušit"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Smazat"; +"BUTTON_CLEAR_SIGNATURE" = "Smazat podpis"; +"BUTTON_APPLY" = "Použít"; +"BUTTON_DISAGREE" = "Nesouhlasím"; +"BUTTON_DONE" = "Hotovo"; +"BUTTON_GET_STARTED" = "Začít"; +"BUTTON_LEARN_MORE" = "Další informace"; +"BUTTON_NEXT" = "Další"; +"BUTTON_SKIP" = "Přeskočit"; +"BUTTON_SKIP_QUESTION" = "Tuto otázku přeskočit"; +"BUTTON_START_TIMER" = "Spustit odpočet"; +"BUTTON_OPTION_SAVE" = "Nechat na později"; +"BUTTON_OPTION_DISCARD" = "Zahodit výsledky"; +"BUTTON_OPTION_STOP_TASK" = "Konec úlohy"; +"BUTTON_SAVE" = "Uložit"; +"BUTTON_CLEAR_ANSWER" = "Smazat odpověď"; +"BUTTON_READ_ONLY_MODE" = "Tuto odpověď nelze změnit."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Zavřít"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Aktivita se spustí za"; +"TASK_COMPLETE_TITLE" = "Aktivita byla dokončena"; +"TASK_COMPLETE_TEXT" = "Data budou analyzována a jakmile budou k dispozici výsledky, obdržíte oznámení."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Zbývá %@."; +"TOUCH_ANYWHERE_LABEL" = "Pokračujte dotykem kdekoli na displeji."; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Pořídit obrázek"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Pořídit obrázek znovu"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Fotoaparát nebyl nalezen. Tento krok nelze dokončit."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Před dokončením tohoto kroku musíte v Nastavení povolit této aplikaci přístup k fotoaparátu."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Nebyl určen žádný výstupní adresář pro pořízené obrázky."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Pořízený obrázek se nepodařilo uložit."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Začít nahrávat"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Zastavit nahrávání"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Znovu nahrát video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kondice"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Vzdálenost (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Srdeční tep (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Po %@ pohodlně seďte."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Po %@ co nejrychleji kráčejte."; +"FITNESS_INTRO_TEXT_FORMAT" = "Tato aktivita změří váš srdeční tep a vzdálenost, kterou ujdete za %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Po %1$@ se procházejte venku nejvyšším možným tempem. Poté po %2$@ v pohodlné pozici odpočívejte. Chcete‑li začít, klepněte na Začít."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Chůze a rovnováha"; +"WALK_INTRO_TEXT" = "Tato aktivita změří váš krok a rovnováhu při chůzi a stání. Pokud nedokážete bezpečně chodit bez pomoci, v tomto testu nepokračujte."; +"WALK_INTRO_2_TEXT_%ld" = "Najděte si místo, kde můžete bezpečně bez asistence ujít přibližně %ld kroků v přímém směru."; +"WALK_INTRO_2_DETAIL" = "Uložte zařízení do kapsy nebo tašky a postupujte podle zvukových pokynů."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Nyní po %@ klidně stůjte."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Po %@ klidně stůjte."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Obraťte se a jděte zpátky na začátek."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Ujděte až %ld kroků v přímém směru."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Najděte si místo, kde můžete bezpečně chodit tam a zpět v přímém směru. Pokuste se o chůzi, kterou nebude přerušovat obracení na koncích. Obraťte se, jako kdybyste obcházeli kužel.\n\nPotom budete požádáni, abyste se otočili kolem dokola a zůstali stát s rukama podél těla a nohama rozkročenýma na šířku ramen."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Až budete připraveni, klepněte na Začít.\nPak uložte zařízení do kapsy nebo tašky a postupujte podle zvukových pokynů."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Po %@ se procházejte sem a tam po přímé linii. Jděte normálním krokem."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Otočte se kolem své osy a pak po %@ klidně stůjte."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Dokončili jste aktivitu."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Rychlost klepání"; +"TAPPING_TASK_TITLE_RIGHT" = "Pravá ruka"; +"TAPPING_TASK_TITLE_LEFT" = "Levá ruka"; +"TAPPING_INTRO_TEXT" = "Tato aktivita změří vaši rychlost klepání."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Položte zařízení na rovný povrch."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Dvěma prsty jedné ruky střídavě klepejte na tlačítka na obrazovce."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Dvěma prsty pravé ruky střídavě klepejte na tlačítka na obrazovce."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Dvěma prsty levé ruky střídavě klepejte na tlačítka na obrazovce."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Nyní test zopakujte pravou rukou."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Nyní test zopakujte levou rukou."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Klepněte jedním prstem a potom druhým. Zkuste klepat co nejvíc rovnoměrně. Pokračujte v klepání po %@."; +"TAPPING_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Začněte klepnutím na Další."; +"TAP_BUTTON_TITLE" = "Klepněte"; +"TOTAL_TAPS_LABEL" = "Počet klepnutí"; +"TAPPING_INSTRUCTION" = "Dvěma prsty co nejrovnoměrněji klepejte na tlačítka."; +"TAPPING_INSTRUCTION_RIGHT" = "Klepejte na tlačítka PRAVOU rukou."; +"TAPPING_INSTRUCTION_LEFT" = "Klepejte na tlačítka LEVOU rukou."; +"TAPPING_SKIP_TITLE" = "Tuto ruku vynechat"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amslerova mřížka"; +"AMSLER_GRID_INTRO_TEXT" = "Tato aktivita vám pomůže detekovat problémy se zrakem."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Během testu držte zařízení v úrovni očí a ve vzdálenosti 30 centimetrů."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Zavřete %@ a soustředěně pozorujte bod uprostřed čtvercové mřížky.\n\nPrstem nebo stylusem označte zpozorované nepravidelnosti, například rozostřené nebo zvlněné čáry.\n\nAž budete hotovi, přejeďte kamkoli doleva mimo mřížku."; +"AMSLER_GRID_LEFT_EYE" = "levé oko"; +"AMSLER_GRID_RIGHT_EYE" = "pravé oko"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Hlas"; +"AUDIO_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"AUDIO_INSTRUCTION" = "Řekněte \“Ááááá\” do mikrofonu a vydržte co nejdéle."; +"AUDIO_INTRO_TEXT" = "Hluboce se nadechněte a při výdechu hlasitě a co nejdéle do mikrofonu vyslovujte \“Ááááá\”. Udržujte konstantní úroveň hlasitosti, při které budou proužky zbarvené modře."; +"AUDIO_INTENDED_USE" = "Tato aktivita nahraje váš hlas pomocí mikrofonu u dolního okraje zařízení a vyhodnotí ho."; +"AUDIO_TOO_LOUD_LABEL" = "Příliš nahlas"; +"AUDIO_GENERIC_ERROR_LABEL" = "Nelze zaznamenávat zvuk"; +"AUDIO_LEVEL_CHECK_LABEL" = "Počkejte, než otestujeme úroveň okolního hluku."; +"AUDIO_TOO_LOUD_MESSAGE" = "Úroveň okolního hluku je pro nahrání vašeho hlasu příliš vysoká. Přesuňte se na klidnější místo a zkuste to znovu."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Až budete připraveni, klepněte na Další."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tónová audiometrie"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Tato aktivita změří vaši schopnost slyšet různé zvuky."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Než začnete, zapojte sluchátka a nasaďte si je.\n\nZvuk bude velmi jemný. Nebude stejný jako zvuk běžných upozornění. Zpočátku bude slabý a pomalu bude nabírat na hlasitosti. Pozorně naslouchejte a klepnutím na levé nebo pravé tlačítko označte, ve kterém uchu zvuk slyšíte."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Měli byste slyšet tón. Jeho hlasitost upravte ovládacími prvky na boku zařízení.\n\nAž budete připraveni začít, klepněte na kterékoli tlačítko."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Vždy, když uslyšíte zvuk, signalizujte stisknutím levého nebo pravého tlačítka, ve kterém uchu ho slyšíte."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Levé ucho"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Pravé ucho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, vlevo"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, vpravo"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tónová audiometrie"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Když uslyšíte tón, klepněte."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tón a hlasitost"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Uslyšíte sérii tónů."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Když uslyšíte tón, klepněte na tlačítko."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "V tomto testu bude nastavena hlasitost na 50 procent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Tento test zabere přibližně 10 minut."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Zapněte funkci Nerušit, abyste se mohli soustředit."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Nejprve uslyšíte zvuky v pravém uchu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Nyní uslyšíte zvuky v levém uchu."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Tato aktivita identifikuje úrovně prahu slyšení na decibelové stupnici."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Ujistěte se, že je hlasitost zařízení nastavena na nejvyšší úroveň.\n\nBěhem této úlohy vám v levém nebo pravém uchu bude znít jemný zvuk.\n\nPozorně naslouchejte a pokaždé, když uslyšíte zvuk, klepněte na tlačítko."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Tento test určí hlasitost zvuku, která je pro vás slyšitelná."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Úvodní dotazník."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Vyberte ucho, na které slyšíte lépe (pokud na jedno ucho slyšíte lépe)"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "levé"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "pravé"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "bez preference"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test byl zrušen"; +"dBHL_ALERT_TITLE_START_OVER" = "Začít znovu"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Zrušit test"; +"dBHL_ALERT_TEXT" = "Před provedením testu znovu připojte AirPody nebo EarPody."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ dokončeno"; + +/* Headphones. */ +"AIRPODS" = "AirPody"; +"EARPODS" = "EarPody"; +"HEADPHONES" = "Sluchátka"; +"HEADPHONES_UNKNOWN" = "Neznámá"; +"HEADPHONES_NONE" = "Žádná"; +"CONNECTED" = "Připojeno"; +"NOT_CONNECTED" = "Nepřipojeno"; +"HEADPHONE_CONNECTED_%@" = "Připojeno – %@"; +"HEADPHONE_DETECT_TITLE" = "Připojte sluchátka"; +"HEADPHONE_DETECT_TEXT" = "Tento test vyžaduje AirPody nebo EarPody značky Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Prostorová paměť"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Tato aktivita změří vaši krátkodobou prostorovou paměť. Budete požádáni o zopakování pořadí, ve kterém se budou rozsvěcovat %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "květiny"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "květiny"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Některé %@ se postupně rozsvítí. Klepejte na %@ v pořadí, ve kterém se rozsvěcovaly."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Některé %@ se postupně rozsvítí. Klepejte na %@ v obráceném pořadí rozsvěcování."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Chcete-li začít, klepněte na Začít a pozorně se dívejte."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Skóre"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Sledujte, jak se %@ rozsvítí"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Klepejte na %@ v pořadí, ve kterém se rozsvítily"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Klepejte na %@ v obráceném pořadí"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sekvence byla dokončena"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Pokračujte klepnutím na Další."; +"MEMORY_GAME_FAILED_TITLE" = "Zkusit znovu"; +"MEMORY_GAME_FAILED_MESSAGE" = "Úplně se vám to tentokrát nepodařilo. Pokračujte klepnutím na Další."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Je na čase"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Čas vypršel.\nPokračujte klepnutím na Další."; +"MEMORY_GAME_COMPLETE" = "Hra byla dokončena"; +"MEMORY_GAME_PAUSED_TITLE" = "Pozastaveno"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Pokračujte klepnutím na Další."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Paměťovou aktivitu pomohli vyvinout Katherine Possin, PhD a Joel Kramer, PhD z University of California v San Franciscu."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reakční doba"; +"REACTION_TIME_TASK_INTENDED_USE" = "Tato aktivita zjišťuje, jak dlouho vám trvá, než zareagujete na vizuální podnět."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Jakmile se na displeji objeví modrá tečka, zatřeste zařízením v libovolném směru. Budete k tomu vyzváni celkem %Dx."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Pokus %@ z %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Jakmile se objeví modrý kroužek, krátce zařízením zatřeste"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroopův test"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Vždy, když se objeví slovo, vyberte první písmeno BARVY, kterou je slovo napsáno."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Jakmile budete připraveni začít se Stroopovým testem, klepněte na Začít."; +"STROOP_TASK_STEP_TEXT" = "Vyberte první písmeno BARVY, kterou je slovo napsáno."; +"STROOP_COLOR_RED" = "ČERVENÁ"; +"STROOP_COLOR_GREEN" = "ZELENÁ"; +"STROOP_COLOR_BLUE" = "MODRÁ"; +"STROOP_COLOR_YELLOW" = "ŽLUTÁ"; +"STROOP_COLOR_RED_INITIAL" = "Č"; +"STROOP_COLOR_GREEN_INITIAL" = "Z"; +"STROOP_COLOR_BLUE_INITIAL" = "M"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ž"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanojské věže"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Tato aktivita vyhodnotí vaši schopnost řešit hlavolamy."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Přesuňte celou sadu na zvýrazněnou podložku s využitím co nejmenšího počtu kroků."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Vyřešte hlavolam"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Počet pohybů: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Tento hlavolam nedokážu vyřešit"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Rozsah pohybu"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Volba končetiny musí být vlevo nebo vpravo"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rozsah pohybu levého kolene"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rozsah pohybu pravého kolene"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Tato aktivita změří schopnost narovnat nohu v levém koleni."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Tato aktivita změří schopnost narovnat nohu v pravém koleni."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sedněte si na kraj židle. V dalším kroku budete vyzváni, abyste svoje zařízení přiložili k levému kolenu kvůli měření. Zapněte na zařízení zvuk, abyste slyšeli pokyny."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sedněte si na kraj židle. V dalším kroku budete vyzváni, abyste svoje zařízení přiložili k pravému kolenu kvůli měření. Zapněte na zařízení zvuk, abyste slyšeli pokyny."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Přiložte zařízení k levému kolenu displejem od sebe, jak vidíte na obrázku."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Přiložte zařízení k pravému kolenu displejem od sebe, jak vidíte na obrázku."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Až budete připraveni, spusťte test klepnutím na displej a co nejvíc napřimte levé koleno. Potom se vraťte do výchozí polohy a znovu klepněte na displej."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Až budete připraveni, spusťte test klepnutím na displej a co nejvíc napřimte pravé koleno. Potom se vraťte do výchozí polohy a znovu klepněte na displej."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Přiložte si zařízení k levému koleni. Klepněte na displej a pak levé koleno co nejvíc napřimte."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Přiložte si zařízení k pravému koleni. Klepněte na displej a pak pravé koleno co nejvíc napřimte."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Až budete hotovi, vraťte levé koleno do výchozí polohy. Potom klepněte na libovolné místo."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Až budete hotovi, vraťte pravé koleno do výchozí polohy. Potom klepněte na libovolné místo."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rozsah pohybu levého ramene"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rozsah pohybu pravého ramene"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Tato aktivita změří schopnost zvednout ruku v levém rameni."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Tato aktivita změří schopnost zvednout ruku v pravém rameni."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "V dalším kroku budete vyzváni, abyste svoje zařízení přiložili k levému rameni kvůli měření. Zapněte na zařízení zvuk, abyste slyšeli pokyny."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "V dalším kroku budete vyzváni, abyste svoje zařízení přiložili k pravému rameni kvůli měření. Zapněte na zařízení zvuk, abyste slyšeli pokyny."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Přiložte zařízení k levému rameni displejem od sebe, jak vidíte na obrázku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Přiložte zařízení k pravému rameni displejem od sebe, jak vidíte na obrázku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Až budete připraveni, spusťte test klepnutím na displej a zvedněte levou paži co nejvýš. Potom se vraťte do původní polohy a znovu klepněte na displej."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Až budete připraveni, spusťte test klepnutím na displej a zvedněte pravou paži co nejvýš. Potom se vraťte do původní polohy a znovu klepněte na displej."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Přiložte si zařízení k levému rameni. Klepněte na displej a pak zvedněte levou paži předním obloukem, kam až to půjde."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Přiložte si zařízení k pravému rameni. Klepněte na displej a pak zvedněte levou paži předním obloukem, kam až to půjde."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Až budete hotovi, vraťte levou paži do výchozí polohy. Potom klepněte na libovolné místo."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Až budete hotovi, vraťte pravou paži do výchozí polohy. Potom klepněte na libovolné místo."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Chůze na čas"; +"TIMED_WALK_INTRO_DETAIL" = "Tato aktivita změří funkci vašich dolních končetin."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Najděte si místo (nejlépe venku), kde můžete co nejrychleji a bezpečně jít přibližně %@ v přímém směru. Nezpomalujte, dokud nepřekročíte cílovou čáru."; +"TIMED_WALK_INTRO_2_DETAIL" = "Začněte klepnutím na Další."; +"TIMED_WALK_FORM_TITLE" = "Asistenční zařízení"; +"TIMED_WALK_FORM_TEXT" = "Při všech testech používejte při chůzi tutéž oporu."; +"TIMED_WALK_QUESTION_TEXT" = "Používáte kotníkovou ortézu?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Používáte při chůzi oporu?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Klepněte a vyberte odpověď."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ne"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Jedna hůl"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Jedna berla"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dvě hole"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dvě berle"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Chodítko"; +"TIMED_WALK_INSTRUCTION_%@" = "Ujděte až %@ v přímém směru."; +"TIMED_WALK_INSTRUCTION_TURN" = "Obraťte se."; +"TIMED_WALK_INSTRUCTION_2" = "Jděte zpátky na začátek."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Až budete hotoví, klepněte na Další."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Paced Auditory a Serial Addition Test měří vaši rychlost a počtářské dovednosti při zpracovávání sluchových informací."; +"PVSAT_INTRO_TEXT" = "Paced Visual Serial Addition Test měří vaši rychlost a počtářské dovednosti při zpracovávání zrakových informací."; +"PAVSAT_INTRO_TEXT" = "Paced Auditory a Visual Serial Addition Test měří vaši rychlost a počtářské dovednosti při zpracovávání sluchových a zrakových informací."; +"PSAT_INTRO_TEXT_2_%@" = "Vždy za %@ se zobrazí číslice.\nPřičtěte ji k bezprostředně předchozí číslici.\nNesčítejte všechny číslice. Sečtěte jen poslední dvě."; +"PSAT_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"PSAT_INITIAL_INSTRUCTION" = "Zapamatujte si toto první číslo."; +"PSAT_INSTRUCTION" = "Přičtěte toto číslo k předchozímu."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@kolíkový test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Tato aktivita otestuje motoriku vašich horních končetin. Požádáme vás o zasunutí kolíku do otvoru. Budete k tomu vyzváni celkem %@×."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Bude proveden test levé i pravé ruky.\nCo nejrychleji uchopte kolík a zasuňte ho do otvoru. Tuto akci proveďte %@× a potom ho opět %@× vyndejte."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Bude proveden test pravé i levé ruky.\nCo nejrychleji uchopte kolík a zasuňte ho do otvoru. Tuto akci proveďte %@× a potom ho opět %@× vyndejte."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Zasuňte kolík do otvoru levou rukou."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Zasuňte kolík do otvoru pravou rukou."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Umístěte kolík za čáru levou rukou."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Umístěte kolík za čáru pravou rukou."; +"HOLE_PEG_TEST_TEXT" = "Uchopte kolík dvěma prsty."; +"HOLE_PEG_TEST_TEXT_2" = "Zvednutím prstů kolík pusťte."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Třes rukou"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Tato aktivita změří třas rukou v různých polohách. Najděte si místo, na kterém budete moct po celou dobu aktivity pohodlně sedět."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Podržte telefon ve více postižené ruce tak, jak vidíte na obrázku."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Podržte telefon v PRAVÉ ruce tak, jak vidíte na obrázku."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Podržte telefon v LEVÉ ruce tak, jak vidíte na obrázku."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Budete požádáni o %@ při sezení s telefonem v ruce."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "úkol"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dva úkoly"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tři úkoly"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "čtyři úkoly"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "pět úkolů"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Pokračujte klepnutím na Další."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Připravte se držet telefon na klíně."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Připravte se držet telefon LEVOU rukou na klíně."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Připravte se držet telefon PRAVOU rukou na klíně."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "%ld sekund držte telefon na klíně."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Nyní držte telefon rukou nataženou ve výši ramen."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Nyní držte telefon LEVOU rukou nataženou ve výši ramen."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Nyní držte telefon PRAVOU rukou nataženou ve výši ramen."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "%ld sekund držte telefon v natažené ruce."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Nyní ohněte ruku v lokti a držte telefon ve výši ramen."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Nyní držte telefon ve výši ramen LEVOU rukou ohnutou v lokti."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Nyní držte telefon ve výši ramen PRAVOU rukou ohnutou v lokti."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "%ld sekund držte telefon s rukou ohnutou v lokti."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Nyní se s rukou ohnutou v lokti opakovaně dotýkejte telefonem nosu."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Nyní držte telefon ve výši ramen LEVOU rukou ohnutou v lokti a dotýkejte se jím opakovaně nosu."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Nyní držte telefon ve výši ramen PRAVOU rukou ohnutou v lokti a dotýkejte se jím opakovaně nosu."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "%ld sekund se telefonem dotýkejte nosu."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Připravte se zamávat otáčením zápěstí."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Připravte se zamávat otáčením zápěstí s telefonem v LEVÉ ruce."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Připravte se zamávat otáčením zápěstí s telefonem v PRAVÉ ruce."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "%ld sekund mávejte otáčením zápěstí."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Nyní vezměte telefon do LEVÉ ruky a pokračujte dalším úkolem."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Nyní vezměte telefon do PRAVÉ ruky a pokračujte dalším úkolem."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Pokračujte další úlohou."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivita byla dokončena."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Budete požádáni o %@ při sezení s telefonem nejprve v jedné a pak v druhé ruce."; +"TREMOR_SKIP_LEFT_HAND" = "Tuto aktivitu nemůžu provádět LEVOU rukou."; +"TREMOR_SKIP_RIGHT_HAND" = "Tuto aktivitu nemůžu provádět PRAVOU rukou."; +"TREMOR_SKIP_NEITHER" = "Tuto aktivitu můžu provádět oběma rukama."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test cesty"; +"TRAILMAKING_INTENDED_USE" = "Tato aktivita vyhodnotí vaši vizuální pozornost a schopnost přecházet mezi úlohami. Zaznamená čas, který budete potřebovat ke klepání na řadu bodů v určeném pořadí."; +"TRAILMAKING_INTENDED_USE2_A" = "Po skončení odpočtu střídavě klepejte na body u číslic a písmen. Začněte klepnutím na číslo „1“, potom na čísla „2“ – „3“ – „4“… až do čísla „7“."; +"TRAILMAKING_INTENDED_USE2_B" = "Po skončení odpočtu střídavě klepejte na body u číslic a písmen. Začněte klepnutím na číslo „1“, potom na písmeno „A“ a pak na „2“ – „B“ – „3“ – „C“… až do čísla „7“."; +"TRAILMAKING_INTRO_TEXT" = "Udělejte to co nejrychleji, aniž byste dělali chyby. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Rozpoznávání řeči"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Tato aktivita nahraje vaši řeč pomocí mikrofonu u dolního okraje zařízení a pak ji převede na text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Začněte klepnutím na Začít."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Než začnete mluvit, nejprve spusťte nahrávání stisknutím tlačítka."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Začít nahrávat"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Zastavit nahrávání"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Upravit přepis"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Pokud jsou v textu chyby v interpretaci řeči, opravte je."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Zde se objeví přepis vaší řeči."; +"SPEECH_RECOGNITION_FAILED" = "Rozpoznávání řeči selhalo."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Inicializace rozpoznávání řeči selhala."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Spustit přehrávání"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Zastavit přehrávání"; +"SPEECH_IN_NOISE_TITLE" = "Řeč v hluku"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Tato aktivita změří srozumitelnost řeči v hlučných prostředích."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "V rámci tohoto testu provedete následující:\n\nPoslechnete si větu.\n\nZřetelně zopakujete, co jste slyšeli, nebo tento krok přeskočíte a text, který jste slyšeli, zadáte pomocí klávesnice.\n\nPo zopakování toho, co jste slyšeli, budete mít možnost upravit přepis vygenerovaný funkcí pro rozpoznávání řeči."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Kalibrace hlasitosti"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Klepněte na Spustit přehrávání, upravte hlasitost na příjemnou úroveň a potom pokračujte klepnutím na Zastavit přehrávání."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Poslouchat"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Věta smíchaná s hlukem na pozadí při náhodném poměru signál-šum (SNR) bude přehrána jen jednou."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Mluvit"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Zopakujte, co jste slyšeli."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Soubor nelze vytvořit"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nepodařilo se odstranit dostatečné množství protokolů pro dosažení prahové hodnoty"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Chyba nastavení atributu"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Soubor není označen jako smazaný (není označen jako odeslaný)"; +"ERROR_DATALOGGER_MULTIPLE" = "Při odstraňování protokolů došlo k více chybám"; +"ERROR_RECORDER_NO_DATA" = "Nebyla nalezena žádná shromážděná data."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Nebyl určen výstupní adresář"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Měřič akustického tlaku"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Tato aktivita změří úroveň akustického tlaku v prostředí. Pokud bude úroveň hluku příliš vysoká, nebudete moct pokračovat. V tom případě proveďte úlohu v tišším prostředí nebo se k aktivitě vraťte později."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Výpočet"; +"ENVIRONMENTSPL_THRESHOLD" = "Práh: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Akceptovatelný hluk na pozadí"; +"ENVIRONMENTSPL_NOISE" = "Příliš silný hluk na pozadí"; +"ENVIRONMENTSPL_TITLE_2" = "Najděte si tiché místo"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Tento test podstupte v tichém prostředí, aby byly jeho výsledky přesné."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Zahájit úlohu"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Žádná data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Pohybem jezdce nastavte hodnotu"; +"SLIDER_I_DONT_KNOW" = "Nevím"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Stránka"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Zpět"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Zobrazit miniaturu PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Skrýt miniaturu PDF"; +"AX_BUTTON_ANNOTATE" = "Anotace"; +"AX_BUTTON_SHOW_SEARCH" = "Zobrazit panel hledání"; +"AX_BUTTON_HIDE_SEARCH" = "Skrýt panel hledání"; +"AX_BUTTON_SHARE" = "Sdílet"; + + +"AX_COMPLETION_ILLUSTRATION" = "Obrázek zaškrtávací značky v modrém kroužku značící úspěch"; + +"AX_SIGNVIEW_LABEL" = "Vyhrazené pole pro podpis"; +"AX_SIGNVIEW_HINT" = "Chcete-li se podepsat, dotkněte se obrazovky a pohybujte prstem"; +"AX_SIGNVIEW_SIGNED" = "Podepsáno"; +"AX_SIGNVIEW_UNSIGNED" = "Nepodepsáno"; + +"AX_SELECTED" = "Vybráno"; +"AX_UNSELECTED" = "Nevybráno"; +"AX_SELECT_ALL_THAT_APPLY" = "VYBERTE VŠE RELEVANTNÍ"; + +"AX_SLIDER_LABEL" = "Jezdec odpovědi. Rozsah od %@ do %@"; +"AX_UNLABELED_IMAGE" = "Obrázek bez štítku"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Spustit úlohu"; + +"AX.MEMORY.TILE.ACTIVE" = "aktivní"; +"AX.MEMORY.TILE.CORRECT" = "správně"; +"AX.MEMORY.TILE.INCORRECT" = "nesprávně"; +"AX.MEMORY.TILE.QUIESCENT" = "klid"; +"AX.MEMORY.TILE.LABEL" = "Kostka paměťové hry"; + +"AX_IMAGE_CAPTURE_LABEL" = "Náhled"; +"AX_IMAGE_CAPTURED_LABEL" = "Pořízený obrázek"; + +"AX_VIDEO_CAPTURE_LABEL" = "Náhled nahraného videa"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video je nahrané"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Disk o velikosti %@ nelze umístit na disk o velikosti %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cíl"; +"AX_TOWER_OF_HANOI_TOWER" = "Věž"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Poklepáním umístíte disk"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Poklepáním vyberte vrchní disk"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Obsahuje disky o velikosti %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Prázdné"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Zavřít klávesnici"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Rozmezí od %@ do %@"; +"AX_GRAPH_STACK_PREFIX" = "Sada se skládá z"; +"AX_GRAPH_AND_SEPARATOR" = " a "; +"AX_GRAPH_POINT_%@" = "Bod: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Vlnový průběh řeči"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Po zahájení nahrávání můžete druhou aktivací nahrávání ukončit."; + +"AX_AUDIO_BAR_GRAPH" = "Pruhový graf zvuku"; + +"AX_AMSLER_GRID_LABEL" = "Amslerova mřížka"; +"AX_AMSLER_GRID_HINT" = "Prstem nebo stylusem přidejte značky na mřížku nebo přejetím doleva mimo mřížku ukončete test."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Možnost klepnutí na tlačítka"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Klepněte při zvuku v levém uchu"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktivací spustíte test. Po spuštění testu klepněte přímo na toto tlačítko, jakmile uslyšíte zvuk v levém uchu."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Klepněte při zvuku v pravém uchu"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktivací spustíte test. Po spuštění testu klepněte přímo na toto tlačítko, jakmile uslyšíte zvuk v pravém uchu."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Při použití VoiceOveru můžete dotykem prozkoumat obrazovku a zjistit, kde se nacházejí tlačítka pro levé a pravé ucho. Po spuštění testu bude možné na tato tlačítka klepnout přímo. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Klepnutím nastavíte jeden prst"; +"AX_TAP_BUTTON_2_LABEL" = "Klepnutím nastavíte druhý prst"; +"AX_TAP_BUTTON_HINT" = "Aktivujte, chcete‑li umožnit přímé klepnutí na tlačítka."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Při použití VoiceOveru můžete dotykem prozkoumat obrazovku a zjistit, kde se nacházejí jednotlivá tlačítka. Aktivací libovolného tlačítka umožníte přímé klepnutí na tlačítka."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Na tlačítka teď lze přímo klepnout."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Při použití VoiceOveru bude možné na tlačítko přímo klepnout. Bude se nacházet poblíž středu obrazovky."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Při použití VoiceOveru bude možné na tlačítka v testu přímo klepnout."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Nelze dekódovat hodnotu restoreData pro inicializaci"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..5a8a654 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/cs.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d chyba) + other + (%d chyb) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.strings new file mode 100755 index 0000000..cb8a6bb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Tilladelse"; +"CONSENT_NAME_GIVEN" = "Fornavn"; +"CONSENT_NAME_FAMILY" = "Efternavn"; +"CONSENT_NAME_PLACEHOLDER" = "Nødvendig"; +"CONSENT_REVIEW_TITLE" = "Gennemse"; +"CONSENT_REVIEW_INSTRUCTION" = "Gennemse nedenstående formular, og tryk på Enig, hvis du er klar til at fortsætte."; +"CONSENT_REVIEW_ALERT_TITLE" = "Gennemse"; +"CONSENT_SIGNATURE_TITLE" = "Underskrift"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Brug din finger til at underskrive i feltet nedenfor."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Skriv under her"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Side %1$ld af %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Velkommen"; +"CONSENT_SECTION_DATA_GATHERING" = "Dataindsamling"; +"CONSENT_SECTION_PRIVACY" = "Anonymitet"; +"CONSENT_SECTION_DATA_USE" = "Databrug"; +"CONSENT_SECTION_STUDY_SURVEY" = "Undersøgelse"; +"CONSENT_SECTION_STUDY_TASKS" = "Opgaver"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tidsforbrug"; +"CONSENT_SECTION_WITHDRAWING" = "Tilbagetrækning"; +"CONSENT_LEARN_MORE_TITLE" = "Læs mere"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Læs mere om, hvordan data indsamles"; +"LEARN_MORE_DATA_USE" = "Læs mere om, hvordan data bruges"; +"LEARN_MORE_PRIVACY" = "Læs mere om, hvordan din anonymitet og identitet er beskyttet"; +"LEARN_MORE_WELCOME" = "Læs mere om undersøgelsen først"; +"LEARN_MORE_STUDY_SURVEY" = "Læs mere om undersøgelsen"; +"LEARN_MORE_TIME_COMMITMENT" = "Læs mere om undersøgelsens indflydelse på din tid"; +"LEARN_MORE_TASKS" = "Læs mere om de involverede opgaver"; +"LEARN_MORE_WITHDRAWING" = "Læs mere om tilbagetrækning"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Valg til deling"; +"CONSENT_SHARE_WIDELY_%@" = "Del mine data med %@ og kvalificerede forskere i hele verden"; +"CONSENT_SHARE_ONLY_%@" = "Del kun mine data med %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ modtager dine data fra din deltagelse i dette studie.\n\nHvis du deler dine kodede data fra studiet (uden oplysninger som f.eks. dit navn), kan det være til gavn for dette studie og fremtidig forskning."; +"LEARN_MORE_CONSENT_SHARING" = "Læs mere om deling af data"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Navn med blokbogstaver"; +"CONSENT_DOC_LINE_SIGNATURE" = "Underskrift"; +"CONSENT_DOC_LINE_DATE" = "Dato"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ af %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Spørgsmål %1$@ af %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Sprunget over"; +"REVIEW_EDIT_ANSWER" = "Rediger"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Ugyldig værdi"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ overskrider den maks. tilladte værdi (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ er mindre end den min. tilladte værdi (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ er ikke en gyldig værdi."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Ugyldig e-mailadresse: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Indtast en adresse"; +"LOCATION_ERROR_TITLE" = "Den angivne adresse blev ikke fundet"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Din aktuelle lokalitet blev ikke fundet. Skriv en adresse, eller flyt til en lokalitet med bedre GPS-signal, hvis relevant."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Der er nægtet adgang til lokalitetstjenester. Giv denne app tilladelse til at bruge lokalitetstjenester vha. Indstillinger."; +"LOCATION_ERROR_GEOCODE" = "Den indtastede adresse blev ikke fundet. Kontroller, at adressen er gyldig."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Enten har du ikke oprettet forbindelse til internettet, eller også har du overskredet det maksimale antal anmodninger om adresseopslag. Hvis du ikke har oprettet forbindelse til internettet, skal du slå Wi-Fi til for at besvare dette spørgsmål, springe dette spørgsmål over, hvis knappen spring over er tilgængelig, eller vende tilbage til denne undersøgelse, når du har oprettet forbindelse til internettet. Ellers prøv igen om nogle minutter."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Tekstindhold overskrider maks. længde: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera ikke tilgængeligt på delt skærm."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "cfriis@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Adgangskode"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Skriv adgangskode"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Bekræft"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Skriv adgangskoden igen"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Adgangskoder er forskellige."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Yderligere oplysninger"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Clara"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Friis"; +"GENDER_FORM_ITEM_TITLE" = "Køn"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Vælg køn"; +"DOB_FORM_ITEM_TITLE" = "Fødselsdato"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Vælg en dato"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonnummer"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Bekræftelse"; +"VERIFICATION_STEP_TITLE" = "Bekræft din e-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tryk på linket nedenfor, hvis du ikke modtog en e-mail med bekræftelse og gerne vil have den sendt igen."; +"RESEND_EMAIL_BUTTON_TITLE" = "Send e-mail med bekræftelse igen"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Log ind"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Glemt adgangskode?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Skriv adgangskode"; +"PASSCODE_CONFIRM_MESSAGE" = "Bekræft adgangskode"; +"PASSCODE_SAVED_MESSAGE" = "Adgangskode arkiveret"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Adgangskode godkendt"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Skriv den gamle adgangskode"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Skriv den nye adgangskode"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Bekræft den nye adgangskode"; +"PASSCODE_INVALID_ALERT_TITLE" = "Forkert adgangskode"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Adgangskoderne stemte ikke overens. Prøv igen."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Godkend med Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-fejl"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Kun numeriske tegn er tilladt."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Statusindikator for indtastning af adgangskode"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ af %@ cifre indtastet"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Glemt adgangskoden?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nøgleringsemne kunne ikke tilføjes."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nøgleringsemne kunne ikke opdateres."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nøgleringsemne kunne ikke slettes."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Nøgleringsemne blev ikke fundet."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Kvinde"; +"GENDER_MALE" = "Mand"; +"GENDER_OTHER" = "Andet"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nej"; +"BOOL_YES" = "Ja"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "fod"; +"MEASURING_UNIT_IN" = "\\\“"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "venstre"; +"LIMB_RIGHT" = "højre"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tryk for at svare"; +"NULL_ANSWER" = "Vælg et svar"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tryk for at vælge"; +"PLACEHOLDER_LONG_TEXT" = "Tryk for at skrive"; + +/* Button titles */ +"BUTTON_AGREE" = "Enig"; +"BUTTON_CANCEL" = "Annuller"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Ryd"; +"BUTTON_CLEAR_SIGNATURE" = "Ryd underskrift"; +"BUTTON_APPLY" = "Anvend"; +"BUTTON_DISAGREE" = "Uenig"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Gå i gang"; +"BUTTON_LEARN_MORE" = "Læs mere"; +"BUTTON_NEXT" = "Næste"; +"BUTTON_SKIP" = "Spring over"; +"BUTTON_SKIP_QUESTION" = "Spring dette spørgsmål over"; +"BUTTON_START_TIMER" = "Start stopur"; +"BUTTON_OPTION_SAVE" = "Arkiver til senere"; +"BUTTON_OPTION_DISCARD" = "Slet resultater"; +"BUTTON_OPTION_STOP_TASK" = "Slut opgave"; +"BUTTON_SAVE" = "Arkiver"; +"BUTTON_CLEAR_ANSWER" = "Ryd svar"; +"BUTTON_READ_ONLY_MODE" = "Dette svar kan ikke ændres."; +"BUTTON_COPYRIGHT" = "Ophavsret"; +"BUTTON_CLOSE" = "Luk"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Starter aktivitet om"; +"TASK_COMPLETE_TITLE" = "Aktivitet færdig"; +"TASK_COMPLETE_TEXT" = "Dine data vil blive analyseret, og du får besked, når resultaterne er klar."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ tilbage."; +"TOUCH_ANYWHERE_LABEL" = "Rør et tilfældigt sted for at fortsætte"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Tag billede"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Tag billede igen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Intet kamera fundet. Dette trin kan ikke gennemføres."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "For at kunne gennemføre dette trin skal du give denne app adgang til kameraet i Indstillinger."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Der blev ikke anført noget resultatbibliotek til billederne."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Billedet kunne ikke arkiveres."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start optagelse"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stop optagelse"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Optag video igen"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Puls (spm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sid behageligt i %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Gå så hurtigt, du kan, i %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Denne aktivitet overvåger din puls og måler, hvor langt du kan gå på %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Gå så hurtigt, du kan, udendørs i %1$@. Når du er færdig, skal du sætte dig ned og hvile i %2$@. Tryk på Gå i gang for at starte."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gang og balance"; +"WALK_INTRO_TEXT" = "Denne aktivitet måler din gang og balance, mens du går og står stille. Fortsæt ikke, hvis du ikke kan gå sikkert uden hjælp."; +"WALK_INTRO_2_TEXT_%ld" = "Find et sted, hvor du kan gå omkring %ld trin sikkert uden hjælp i en lige linje."; +"WALK_INTRO_2_DETAIL" = "Læg din enhed i en lomme eller taske, og følg lydinstruktionerne."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Stå nu stille i %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stå stille i %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Vend om, og gå tilbage til det sted, hvor du startede."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Gå op til %ld trin i en lige linje."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Find et sted, hvor du kan gå sikkert frem og tilbage i en lige linje. Forsøg at gå uden stop ved at vende i slutningen af din rute, som om du går omkring en kegle.\n\nDu vil derefter blive bedt om at dreje 360 grader omkring og derefter stå stille med dine arme ned langs siderne og med en skulderbreddes afstand mellem fødderne."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tryk på Gå i gang, når du er klar til at begynde.\nAnbring derefter enheden i en lomme eller taske, og følg lydinstruktionerne."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Gå frem og tilbage i en lige linje i %@. Gå, som du plejer."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Drej 360 grader rundt, og stå derefter stille i %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Du har færdiggjort aktiviteten."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Hastighed på tryk"; +"TAPPING_TASK_TITLE_RIGHT" = "Højre hånd"; +"TAPPING_TASK_TITLE_LEFT" = "Venstre hånd"; +"TAPPING_INTRO_TEXT" = "Denne aktivitet måler din trykhastighed."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Anbring din enhed på en plan overflade."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Tryk skiftevis på knapperne på skærmen med to fingre på den samme hånd."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Tryk skiftevis på knapperne på skærmen med to fingre på den højre hånd."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Tryk skiftevis på knapperne på skærmen med to fingre på den venstre hånd."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Gentag nu den samme test med din højre hånd."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Gentag nu den samme test med din venstre hånd."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tryk med en finger og derefter med den anden. Forsøg at holde tiden mellem tryk så ensartet som muligt. Fortsæt med at trykke i %@."; +"TAPPING_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tryk på Næste for at starte."; +"TAP_BUTTON_TITLE" = "Tryk"; +"TOTAL_TAPS_LABEL" = "Tryk i alt"; +"TAPPING_INSTRUCTION" = "Tryk på knapperne så ensartet, som du kan vha. to fingre."; +"TAPPING_INSTRUCTION_RIGHT" = "Tryk på knapperne med din HØJRE hånd."; +"TAPPING_INSTRUCTION_LEFT" = "Tryk på knapperne med din VENSTRE hånd."; +"TAPPING_SKIP_TITLE" = "Spring denne hånd over"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler-gitter"; +"AMSLER_GRID_INTRO_TEXT" = "Denne aktivitet hjælper med at registrere problemer med brugerens syn."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Hold enheden 30 cm fra ansigtet og i øjenhøjde under hele testen."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Luk %@, og fokuser på prikken i midten af det firkantede gitter.\n\nBrug en finger eller pen til at markere alle forvrængninger, du ser, f.eks. slørede eller bølgede streger.\n\nSkub til venstre uden for gitteret, når du er færdig."; +"AMSLER_GRID_LEFT_EYE" = "Venstre øje"; +"AMSLER_GRID_RIGHT_EYE" = "Højre øje"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Stemme"; +"AUDIO_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"AUDIO_INSTRUCTION" = "Sig “Aaaaah” ind i mikrofonen i så lang tid, som du kan."; +"AUDIO_INTRO_TEXT" = "Tag en dyb indånding, og sig “Aaaaah” ind i mikrofonen i så lang tid, som du kan. Hold den samme styrke, så lydmålerne bliver ved med at være blå."; +"AUDIO_INTENDED_USE" = "Denne aktivitet vurderer din stemme ved at optage den med mikrofonen nederst i enheden."; +"AUDIO_TOO_LOUD_LABEL" = "For højt"; +"AUDIO_GENERIC_ERROR_LABEL" = "Kan ikke optage lyd"; +"AUDIO_LEVEL_CHECK_LABEL" = "Vent, mens støjniveauet i baggrunden kontrolles."; +"AUDIO_TOO_LOUD_MESSAGE" = "Det omgivende støjniveau er for højt til at optage din stemme. Gå et sted hen, hvor der er mere stille, og prøv igen."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tryk på Næste, når du er klar."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Toneaudiometri"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Denne aktivitet måler din evne til at høre forskellige lyde."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Før du starter, skal du tilslutte dine hovedtelefoner og tage dem på.\n\nLyden vil være meget diskret og lyder ikke som en almindelig advarselstone. Lyden vil være dæmpet i begyndelsen, men lydstyrken øges langsomt. Lyt opmærksomt, og tryk på den venstre eller højre knap for at angive, hvilket øre du hører den i."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Du skulle nu høre en tone. Juster lydstyrken med knapperne på siden af din enhed.\n\nTryk på en knap, når du er klar til at starte."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Hver gang du hører en lyd, skal du trykke på den venstre eller højre knap for at vise, hvilket øre du hører lyden i."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Venstre øre"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Højre øre"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, venstre"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, højre"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Toneaudiometri"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tryk, når du hører en tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tone og lydstyrke"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Du vil høre en række toner."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Tryk på knappen, når du hører en tone."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Lydstyrken er indstillet til 50 procent i denne test."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Denne test tager omkring 10 minutter."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Slå Forstyr ikke til for at undgå afbrydelser."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Først afspilles der toner i dit højre øre."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Nu afspilles der toner i dit venstre øre."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Denne aktivitet identificerer grænseniveauer for en persons hørelse i skalaen dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Sørg for, at enhedens lydstyrke er skruet helt op.\n\nUnder denne opgave afspilles en diskret tone i enten venstre eller højre øre.\n\nLyt godt efter, og tryk på knappen, hver gang du hører en tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Denne test identificerer, hvor høj en tone skal være, for at du kan høre den."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Indledende spørgeskema."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Vælg evt. din indstilling for “bedre øre”"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "venstre"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "højre"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ingen præference"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test annulleret"; +"dBHL_ALERT_TITLE_START_OVER" = "Start igen"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Annuller test"; +"dBHL_ALERT_TEXT" = "Tilslut dine AirPods eller EarPods igen for at udføre testen."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ færdig"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Hovedtelefoner"; +"HEADPHONES_UNKNOWN" = "Ukendt"; +"HEADPHONES_NONE" = "Ingen"; +"CONNECTED" = "Tilsluttet"; +"NOT_CONNECTED" = "Ikke tilsluttet"; +"HEADPHONE_CONNECTED_%@" = "Tilsluttet – %@"; +"HEADPHONE_DETECT_TITLE" = "Tilslut dine hovedtelefoner"; +"HEADPHONE_DETECT_TEXT" = "Denne test kræver Apple AirPods eller Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Rumlig hukommelse"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Denne aktivitet måler din rumlige korttidshukommelse ved at bede dig om at gentage den rækkefølge, som de enkelte %@ blinker i."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "blomster"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "blomster"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Nogle af %@ne vil blinke en ad gangen. Tryk på %@ne i den samme rækkefølge, som de blinker i."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Nogle af %@ne vil blinke en ad gangen. Tryk på disse %@ i modsat rækkefølge af, hvordan de blinkede."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Du starter ved at trykke på Gå i gang og følge nøje med."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Point"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Se, hvordan de enkelte %@ blinker"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tryk på de enkelte %@ i den rækkefølge, de tændes"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tryk på de enkelte %@ i omvendt rækkefølge"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sekvens færdig"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Tryk på Næste for at fortsætte"; +"MEMORY_GAME_FAILED_TITLE" = "Prøv igen"; +"MEMORY_GAME_FAILED_MESSAGE" = "Du klarede det ikke helt på den tildelte tid. Tryk på Næste for at fortsætte."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Tiden er gået"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Tiden løb ud.\nTryk på Næste for at fortsætte."; +"MEMORY_GAME_COMPLETE" = "Spil udført"; +"MEMORY_GAME_PAUSED_TITLE" = "På pause"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Tryk på Næste for at fortsætte"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Hukommelsesaktiviteten er udviklet med hjælp fra Katherine Possin, PhD, og Joel Kramer, PhD, fra University of California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaktionstid"; +"REACTION_TIME_TASK_INTENDED_USE" = "Denne aktivitet vurderer, hvor lang tid du er om at reagere på et visuelt tegn."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Ryst enheden i tilfældig retning, lige så snart den blå prik vises på skærmen. Du vil blive bedt om at gøre det %D gange."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Forsøg %@ af %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Ryst hurtigt enheden, når den blå cirkel vises"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Hver gang der vises et ord, skal du vælge de(t) første bogstav(er) i navnet på den viste FARVE."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Tryk på Gå i gang, når du er klar til at starte Stroop-aktiviteten."; +"STROOP_TASK_STEP_TEXT" = "Vælg de(t) første bogstav(er) i navnet på den viste FARVE."; +"STROOP_COLOR_RED" = "RØD"; +"STROOP_COLOR_GREEN" = "GRØN"; +"STROOP_COLOR_BLUE" = "BLÅ"; +"STROOP_COLOR_YELLOW" = "GUL"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "GR"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "GU"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tårnet i Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Denne aktivitet vurderer din evne til at løse opgaver."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Flyt hele stakken til den markerede platform med så få træk som muligt."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Løs opgaven"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Antal træk: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Jeg kan ikke løse opgaven"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Bevægelsesområde"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption skal være venstre eller højre"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Bevægelighed af venstre knæ"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Bevægelighed af højre knæ"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Denne aktivitet måler, hvor langt du kan strække dit venstre knæ ud."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Denne aktivitet måler, hvor langt du kan strække dit højre knæ ud."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sæt dig på kanten af en stol. Når du starter, anbringer du din enhed på dit venstre knæ for at tage et mål. Slå lyden til på din enhed, så du kan høre instruktioner."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sæt dig på kanten af en stol. Når du starter, anbringer du din enhed på dit højre knæ for at tage et mål. Slå lyden til på din enhed, så du kan høre instruktioner."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Anbring din enhed på dit venstre knæ med skærmen udad som vist på billedet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Anbring din enhed på dit højre knæ med skærmen udad som vist på billedet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Når du er klar, skal du trykke på skærmen for at begynde og strække dit venstre ben så meget, som du kan. Vend tilbage til startpositionen, og tryk igen, når du er færdig."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Når du er klar, skal du trykke på skærmen for at begynde og strække dit højre ben så meget, som du kan. Vend tilbage til startpositionen, og tryk igen, når du er færdig."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Anbring enheden på dit venstre knæ. Tryk på skærmen, og stræk dit venstre ben så meget, som du kan."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Anbring enheden på dit højre knæ. Tryk på skærmen, og stræk dit højre ben så meget, som du kan."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Når du er færdig, skal du føre dit venstre knæ tilbage til startpositionen. Tryk derefter et vilkårligt sted."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Når du er færdig, skal du føre dit højre knæ tilbage til startpositionen. Tryk derefter et vilkårligt sted."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Bevægelighed af venstre skulder"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Bevægelighed af højre skulder"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Denne aktivitet måler, hvor langt du kan strække din venstre skulder ud."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Denne aktivitet måler, hvor langt du kan strække din højre skulder ud."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Når du starter, anbringer du din enhed på din venstre skulder for at tage et mål. Slå lyden til på din enhed, så du kan høre instruktioner."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Når du starter, anbringer du din enhed på din højre skulder for at tage et mål. Slå lyden til på din enhed, så du kan høre instruktioner."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Anbring din enhed på din venstre skulder med skærmen udad som vist på billedet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Anbring din enhed på din højre skulder med skærmen udad som vist på billedet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Når du er klar, skal du trykke på skærmen for at begynde og løfte din venstre arm så højt, som du kan. Vend tilbage til startpositionen, og tryk igen, når du er færdig."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Når du er klar, skal du trykke på skærmen for at begynde og løfte din højre arm så højt, som du kan. Vend tilbage til startpositionen, og tryk igen, når du er færdig."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Anbring enheden på din venstre skulder. Tryk på skærmen, og løft din venstre arm fremad så højt, som du kan."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Anbring enheden på din højre skulder. Tryk på skærmen, og løft din højre arm fremad så højt, som du kan."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Når du er færdig, skal du føre din venstre arm tilbage til startpositionen. Tryk derefter et vilkårligt sted."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Når du er færdig, skal du føre din højre arm tilbage til startpositionen. Tryk derefter et vilkårligt sted."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Gå på tid"; +"TIMED_WALK_INTRO_DETAIL" = "Denne aktivitet måler funktionen i dine ben."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Find et sted, helst udenfor, hvor du trygt kan gå omkring %@ i en lige linje så hurtigt som muligt. Sænk ikke farten, før du har passeret mållinjen."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tryk på Næste for at starte."; +"TIMED_WALK_FORM_TITLE" = "Hjælpemiddelenhed"; +"TIMED_WALK_FORM_TEXT" = "Brug den samme hjælpemiddelenhed til hver test."; +"TIMED_WALK_QUESTION_TEXT" = "Bruger du en ankel-fodortose?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Bruger du hjælpemiddelenheder?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tryk her for at vælge et svar."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ingen"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Enkeltsidig stok"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Enkeltsidig krykke"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Tosidig stok"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Tosidig krykke"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Gangstativ/rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Gå op til %@ i en lige linje."; +"TIMED_WALK_INSTRUCTION_TURN" = "Vend om."; +"TIMED_WALK_INSTRUCTION_2" = "Gå tilbage til det sted, hvor du startede."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tryk på Næste, når du er færdig."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT-testen måler, hvor hurtigt du behandler lydoplysninger og din evne til at foretage udregninger."; +"PVSAT_INTRO_TEXT" = "PVSAT-testen måler, hvor hurtigt du behandler synsoplysninger og din evne til at foretage udregninger."; +"PAVSAT_INTRO_TEXT" = "PAVSAT-testen (Paced Auditory and Visual Serial Addition Test) måler, hvor hurtigt du behandler lyd- og synsoplysninger og din evne til at foretage udregninger."; +"PSAT_INTRO_TEXT_2_%@" = "Der vises enkelte tal med %@s interval.\nDu skal lægge hvert nye tal sammen med det forrige tal.\nBemærk: Du skal ikke lægge alle tallene sammen, men kun de to sidste tal."; +"PSAT_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"PSAT_INITIAL_INSTRUCTION" = "Husk dette første tal."; +"PSAT_INSTRUCTION" = "Læg dette nye tal sammen med det forrige."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-huls pindetest"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Denne aktivitet måler funktionen i dine hænder ved at bede dig om at anbringe en pind i et hul. Du bliver bedt om at gøre dette %@ gange."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Både din venstre og højre hånd testes.\nDu skal samle cirklen op så hurtigt som muligt, anbringe den i hullet, og når det er gjort %@ gange, skal du fjerne den igen %@ gange."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Både din højre og venstre hånd testes.\nDu skal samle cirklen op så hurtigt som muligt, anbringe den i hullet, og når det er gjort %@ gange, skal du fjerne den igen %@ gange."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Anbring cirklen i hullet vha. din venstre hånd."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Anbring cirklen i hullet vha. din højre hånd."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Anbring cirklen bag ved stregen vha. din venstre hånd."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Anbring cirklen bag ved stregen vha. din højre hånd."; +"HOLE_PEG_TEST_TEXT" = "Saml cirklen op vha. to fingre."; +"HOLE_PEG_TEST_TEXT_2" = "Løft fingrene for at slippe cirklen."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Aktivitet med rysten"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Denne aktivitet måler dine hænders rysten i forskellige positioner. Find et sted, hvor du kan sidde behageligt under hele aktiviteten."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Hold telefonen i den hånd, der er mest påvirket, som vist på billedet nedenfor."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Hold telefonen i din HØJRE hånd som vist på billedet nedenfor."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Hold telefonen i din VENSTRE hånd som vist på billedet nedenfor."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Du vil blive bedt om at udføre %@, mens du sidder med telefonen i hånden."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "en opgave"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "to opgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tre opgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "fire opgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "fem opgaver"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tryk på næste for at fortsætte."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Gør dig klar til at holde telefonen i skødet."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Gør dig klar til at holde telefonen i skødet med din VENSTRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Gør dig klar til at holde telefonen i skødet med din HØJRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Bliv ved med at holde din telefon i skødet i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Hold nu din telefon i skulderhøjde med udstrakt arm."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Hold nu din telefon i skulderhøjde med VENSTRE arm udstrakt."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Hold nu din telefon i skulderhøjde med HØJRE arm udstrakt."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Bliv ved med at holde din telefon med udstrakt hånd i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Hold nu din telefon i skulderhøjde med bøjet albue."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Hold nu din telefon med din VENSTRE hånd i skulderhøjde med bøjet albue."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Hold nu din telefon med din HØJRE hånd i skulderhøjde med bøjet albue."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Bliv ved med at holde din telefon med bøjet albue i %ld sekunder"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Hold nu din telefon med bøjet albue, mens du bliver ved med at røre din næse med telefonen."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Hold nu din telefon med bøjet albue i VENSTRE hånd, mens du bliver ved med at røre din næse med telefonen."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Hold nu din telefon med bøjet albue i HØJRE hånd, mens du bliver ved med at røre din næse med telefonen."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Bliv ved med at røre din næse med telefonen i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Gør dig klar til at udføre et dronningevink (vink ved at dreje dit håndled)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Gør dig klar til at udføre et dronningevink (vink ved at dreje dit håndled) med telefonen i VENSTRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Gør dig klar til at udføre et dronningevink (vink ved at dreje dit håndled) med telefonen i HØJRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Bliv ved med at udføre et dronningevink i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Flyt nu telefonen til din VENSTRE hånd, og fortsæt til næste opgave."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Flyt nu telefonen til din HØJRE hånd, og fortsæt til næste opgave."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Fortsæt til den næste opgave."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivitet færdig."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Du vil blive bedt om at udføre %@, mens du sidder med telefonen først i den ene hånd og derefter igen med telefonen i den anden hånd."; +"TREMOR_SKIP_LEFT_HAND" = "Jeg kan ikke udføre denne aktivitet med min VENSTRE hånd."; +"TREMOR_SKIP_RIGHT_HAND" = "Jeg kan ikke udføre denne aktivitet med min HØJRE hånd."; +"TREMOR_SKIP_NEITHER" = "Jeg kan udføre denne aktivitet med begge hænder."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Sportest"; +"TRAILMAKING_INTENDED_USE" = "Denne aktivitet evaluerer din visuelle opmærksomhed og evne til at skifte mellem opgaver ved at registrere, hvor lang tid det tager at trykke på en række prikker i rækkefølge."; +"TRAILMAKING_INTENDED_USE2_A" = "Efter nedtællingen skal du trykke på prikker i skiftende rækkefølge mellem tal og bogstaver. Start med at trykke på det første tal “1” efterfulgt af tallene “2” – “3” – “4”…, indtil du når tallet “7”."; +"TRAILMAKING_INTENDED_USE2_B" = "Efter nedtællingen skal du trykke på prikker i skiftende rækkefølge mellem tal og bogstaver. Start med at trykke på det første tal “1”, derefter på det første bogstav “A”, så “2” – “B” – “3” – “C”…, indtil du når tallet “7”."; +"TRAILMAKING_INTRO_TEXT" = "Gør det så hurtigt, som du kan, uden at lave fejl. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Talegenkendelse"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Denne aktivitet optager din tale med mikrofonen i bunden af enheden og oversætter den til tekst."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tryk på Gå i gang for at starte."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Tryk på knappen for at starte optagelsen, før du taler."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start optagelse"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stop optagelse"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Rediger transskription"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Rediger tekst i transskriptionen for at rette talemisforståelser."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Din transskription vises her."; +"SPEECH_RECOGNITION_FAILED" = "Talegenkendelse mislykkedes."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Kunne ikke initialisere talegenkendelse."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Afspil lyd"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stop lyd"; +"SPEECH_IN_NOISE_TITLE" = "Tale med støj"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Denne aktivitet måler forståeligheden af talen i omgivelser med meget støj."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Som en del af denne test vil du:\n\nLytte til en sætning.\n\nGentag tydeligt, hvad du hørte, eller spring over for at bruge tastaturet til at skrive, hvad du hørte. \n\nHvis du gentager, hvad du hørte, har du mulighed for at redigere transskriptionen, der genereres af programmet til talegenkendelse."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Lydkalibrering"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tryk på “Afspil lyd” for at justere lydstyrken til et behageligt niveau, og tryk derefter på “Stop lyd” for at fortsætte."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Lyt"; +"SPEECH_IN_NOISE_STEP_TEXT" = "En sætning, der er blandet med baggrundsstøj i et tilfældigt signal-støj-forhold (SNR) afspilles kun en gang."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Tal"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Gentag, hvad du hørte."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Kunne ikke oprette arkiv"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Kunne ikke fjerne tilstrækkeligt med logarkiver til at nå grænsen"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Fejl under indstilling af egenskab"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Arkiv ikke mærket som slettet (ikke mærket som overført)"; +"ERROR_DATALOGGER_MULTIPLE" = "Flere fejl under fjernelse af logarkiver"; +"ERROR_RECORDER_NO_DATA" = "Der blev ikke fundet nogen indsamlede data."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Intet resultatbibliotek anført"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Støjniveaumåler"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Denne aktivitet måler omgivelsernes støjniveau. Hvis støjniveauet er for højt, kan du ikke fortsætte. Gå et sted hen, der er mere stille, for at gennemføre opgaven, eller udfør aktiviteten igen senere."; +"ENVIRONMENTSPL_UNIT" = "dB(A)"; +"ENVIRONMENTSPL_CALCULATING" = "Beregner"; +"ENVIRONMENTSPL_THRESHOLD" = "Grænse: %@ dB(A)"; +"ENVIRONMENTSPL_OK" = "Baggrundsstøj er OK"; +"ENVIRONMENTSPL_NOISE" = "For meget baggrundsstøj"; +"ENVIRONMENTSPL_TITLE_2" = "Find et stille område"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Denne test bør udføres på et stille sted for at opnå størst nøjagtighed."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start opgave"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Ingen data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Flyt mærket for at anføre en værdi"; +"SLIDER_I_DONT_KNOW" = "Jeg ved det ikke"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Side"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Tilbage"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Vis PDF-miniature"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Skjul PDF-miniaturer"; +"AX_BUTTON_ANNOTATE" = "Tilføj kommentar"; +"AX_BUTTON_SHOW_SEARCH" = "Vis søgelinje"; +"AX_BUTTON_HIDE_SEARCH" = "Skjul søgelinje"; +"AX_BUTTON_SHARE" = "Del"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration af et flueben i en blå cirkel angiver, at det lykkedes"; + +"AX_SIGNVIEW_LABEL" = "Valgt felt til signatur"; +"AX_SIGNVIEW_HINT" = "Rør ved skærmen, og bevæg din finger for at underskrive"; +"AX_SIGNVIEW_SIGNED" = "Underskrevet"; +"AX_SIGNVIEW_UNSIGNED" = "Ikke underskrevet"; + +"AX_SELECTED" = "Valgt"; +"AX_UNSELECTED" = "Ikke valgt"; +"AX_SELECT_ALL_THAT_APPLY" = "VÆLG ALLE RELEVANTE"; + +"AX_SLIDER_LABEL" = "Svarmærke. Udsnit fra %@ til %@"; +"AX_UNLABELED_IMAGE" = "Billede uden mærke"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Start opgave"; + +"AX.MEMORY.TILE.ACTIVE" = "aktiv"; +"AX.MEMORY.TILE.CORRECT" = "rigtigt"; +"AX.MEMORY.TILE.INCORRECT" = "forkert"; +"AX.MEMORY.TILE.QUIESCENT" = "passiv"; +"AX.MEMORY.TILE.LABEL" = "Brik i memoryspil"; + +"AX_IMAGE_CAPTURE_LABEL" = "Tag billede af eksempel"; +"AX_IMAGE_CAPTURED_LABEL" = "Taget billede"; + +"AX_VIDEO_CAPTURE_LABEL" = "Eksempel på videooptagelse"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Videooptagelse færdig"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Kan ikke anbringe ring i størrelse %@ på ring i størrelse %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Mål"; +"AX_TOWER_OF_HANOI_TOWER" = "Tårn"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Tryk to gange for at anbringe ring"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Tryk to gange for at vælge den øverste ring"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Har ringe med størrelserne %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Tom"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Luk tastatur"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Udsnit fra %@ til %@"; +"AX_GRAPH_STACK_PREFIX" = "Stak består af"; +"AX_GRAPH_AND_SEPARATOR" = " og "; +"AX_GRAPH_POINT_%@" = "Punkt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Talebølgeform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Når optagelsen starter, skal du aktivere en gang mere for at standse optagelsen."; + +"AX_AUDIO_BAR_GRAPH" = "Lydsøjlegraf"; + +"AX_AMSLER_GRID_LABEL" = "Amsler-gitter"; +"AX_AMSLER_GRID_HINT" = "Brug din finger eller pen til at markere gitteret, eller skub til venstre uden for gitteret for at fortsætte."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Knapper, der kan trykkes på"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tryk for venstre øre"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktiver for at starte testen. Når testen starter, skal du trykke direkte på denne knap, når du hører en lyd i dit venstre øre."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tryk for højre øre"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktiver for at starte testen. Når testen starter, skal du trykke direkte på denne knap, når du hører en lyd i dit højre øre."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Med VoiceOver kan du udforske skærmen ved at berøre den, så du kan finde ud af, hvor knapperne for hvert øre er placeret. Når testen starter, kan du trykke direkte på knapperne. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tryk med en finger"; +"AX_TAP_BUTTON_2_LABEL" = "Tryk med en anden finger"; +"AX_TAP_BUTTON_HINT" = "Aktiver for at kunne trykke direkte på knapperne."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Med VoiceOver kan du udforske skærmen ved at berøre den, så du kan finde ud af, hvor knapperne er placeret. Aktiver knapperne for at kunne trykke direkte på dem."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Nu kan du trykke direkte på knapperne."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Med VoiceOver kan du trykke direkte på knappen. Den bliver placeret omkring midten af skærmen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Med VoiceOver kan du trykke direkte på knapperne i testen."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Kan ikke afkode restoreData til initialisering"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..d7ca311 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/da.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d fejl) + other + (%d fejl) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.strings new file mode 100755 index 0000000..7217065 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Zustimmung"; +"CONSENT_NAME_GIVEN" = "Vorname"; +"CONSENT_NAME_FAMILY" = "Nachname"; +"CONSENT_NAME_PLACEHOLDER" = "Erforderlich"; +"CONSENT_REVIEW_TITLE" = "Überprüfen"; +"CONSENT_REVIEW_INSTRUCTION" = "Lies das Formular unten nochmals durch und tippe auf „Akzeptieren“, wenn du bereit zum Fortfahren bist."; +"CONSENT_REVIEW_ALERT_TITLE" = "Überprüfen"; +"CONSENT_SIGNATURE_TITLE" = "Unterschrift"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Unterzeichne mit deinem Finger in dem Feld unten."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Hier unterschreiben"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Seite %1$ld von %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Willkommen"; +"CONSENT_SECTION_DATA_GATHERING" = "Datenerfassung"; +"CONSENT_SECTION_PRIVACY" = "Datenschutz"; +"CONSENT_SECTION_DATA_USE" = "Datennutzung"; +"CONSENT_SECTION_STUDY_SURVEY" = "Studienumfrage"; +"CONSENT_SECTION_STUDY_TASKS" = "Studienaufgaben"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Zeitaufwand"; +"CONSENT_SECTION_WITHDRAWING" = "Zurücktreten"; +"CONSENT_LEARN_MORE_TITLE" = "Weitere Infos"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Weitere Infos über die Erfassung der Daten"; +"LEARN_MORE_DATA_USE" = "Weitere Infos über die Verwendung der Daten"; +"LEARN_MORE_PRIVACY" = "Weitere Infos über den Schutz deiner Daten und Identität"; +"LEARN_MORE_WELCOME" = "Zunächst weitere Infos über diese Studie"; +"LEARN_MORE_STUDY_SURVEY" = "Weitere Infos über die Studienumfrage"; +"LEARN_MORE_TIME_COMMITMENT" = "Weitere Infos über den für diese Studie benötigten Zeitaufwand"; +"LEARN_MORE_TASKS" = "Weitere Infos über die Aufgaben in der Studie"; +"LEARN_MORE_WITHDRAWING" = "Weitere Infos zum Zurücktreten"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Freigabe-Optionen"; +"CONSENT_SHARE_WIDELY_%@" = "Meine Daten mit %@ und qualifizierten Forschern auf der ganzen Welt teilen"; +"CONSENT_SHARE_ONLY_%@" = "Meine Daten nur mit „%@“ teilen"; +"CONSENT_SHARING_DESCRIPTION_%@" = "Die Studiendaten deiner Teilnahme an dieser Studie werden an %@ gesendet.\n\nDurch Teilen deiner codierten Studiendaten (ohne Informationen wie deinem Namen) mit einer breiteren Basis können diese und künftige Studien profitieren."; +"LEARN_MORE_CONSENT_SHARING" = "Weitere Infos zur Datenfreigabe"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Gedruckter Name"; +"CONSENT_DOC_LINE_SIGNATURE" = "Unterschrift"; +"CONSENT_DOC_LINE_DATE" = "Datum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ von %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Frage %1$@ von %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Übersprungen"; +"REVIEW_EDIT_ANSWER" = "Bearbeiten"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Ungültiger Wert"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ liegt über dem erlaubten Höchstwert (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ liegt unter dem erlaubten Mindestwert (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ ist kein gültiger Wert."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Ungültige E-Mail-Adresse: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Eine Adresse eingeben"; +"LOCATION_ERROR_TITLE" = "Angegebene Adresse konnte nicht gefunden werden"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Der aktuelle Standort konnte nicht ermittelt werden. Gib eine Adresse ein oder begib dich ggf. an einen Ort mit einem besseren GPS-Signal."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Diese App hat keinen Zugriff auf die Ortungsdienste. Erlaube ihr in den Einstellungen das Verwenden der Ortungsdienste."; +"LOCATION_ERROR_GEOCODE" = "Die eingegebene Adresse konnte nicht gefunden werden. Überprüfe, dass es sich um eine gültige Adresse handelt."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Es besteht entweder keine Internetverbindung oder du hast die höchstmögliche Anzahl an Adresssuchen erreicht. Wenn du nicht mit dem Internet verbunden bist, aktiviere WLAN, um diese Frage zu beantworten, oder überspringe sie, wenn die Taste „Überspringen“ angezeigt wird. Du kannst auch zur Umfrage zurückkehren, wenn eine Internetverbindung hergestellt wurde. Versuche es andernfalls zu einem späteren Zeitpunkt erneut."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Textinhalt überschreitet die Maximallänge: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera in der geteilten Darstellung nicht verfügbar."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-Mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "max@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Passwort"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Passwort eingeben"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Bestätigen"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Erneut versuchen"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Die Passwörter stimmen nicht überein."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Zusätzliche Infos"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Max"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Bauer"; +"GENDER_FORM_ITEM_TITLE" = "Geschlecht"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Geschlecht wählen"; +"DOB_FORM_ITEM_TITLE" = "Geburtsdatum"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Datum wählen"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonnummer"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Überprüfung"; +"VERIFICATION_STEP_TITLE" = "E‑Mail überprüfen"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Wenn du keine E-Mail zur Überprüfung erhalten hast, klicke auf den Link unten, um sie dir erneut senden zu lassen."; +"RESEND_EMAIL_BUTTON_TITLE" = "Bestätigungs-E‑Mail erneut senden"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Anmeldung"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Passwort vergessen?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Code eingeben"; +"PASSCODE_CONFIRM_MESSAGE" = "Code bestätigen"; +"PASSCODE_SAVED_MESSAGE" = "Code gesichert"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Code authentifiziert"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Alten Code eingeben"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Neuen Code eingeben"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Neuen Code bestätigen"; +"PASSCODE_INVALID_ALERT_TITLE" = "Code nicht korrekt"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Code stimmte nicht überein. Versuche es erneut."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Mit Touch ID authentifizieren"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-Fehler"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Es sind nur numerische Zeichen zulässig."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Statusanzeige für Codeeingabe"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ von %@ Stellen eingegeben"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Code vergessen?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Schlüsselbundobjekt konnte nicht hinzugefügt werden"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Schlüsselbundobjekt konnte nicht aktualisiert werden"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Schlüsselbundobjekt konnte nicht entfernt werden"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Schlüsselbundobjekt konnte nicht gefunden werden"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Typ I"; +"FITZPATRICK_SKIN_TYPE_II" = "Typ II"; +"FITZPATRICK_SKIN_TYPE_III" = "Typ III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Typ IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Typ V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Typ VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Weiblich"; +"GENDER_MALE" = "Männlich"; +"GENDER_OTHER" = "Divers"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nein"; +"BOOL_YES" = "Ja"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "links"; +"LIMB_RIGHT" = "rechts"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Zum Antworten tippen"; +"NULL_ANSWER" = "Antwort wählen"; +"PLACEHOLDER_IMAGE_CHOICES" = "Zur Auswahl tippen"; +"PLACEHOLDER_LONG_TEXT" = "Zum Schreiben tippen"; + +/* Button titles */ +"BUTTON_AGREE" = "Akzeptieren"; +"BUTTON_CANCEL" = "Abbrechen"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Löschen"; +"BUTTON_CLEAR_SIGNATURE" = "Unterschrift löschen"; +"BUTTON_APPLY" = "Anwenden"; +"BUTTON_DISAGREE" = "Ablehnen"; +"BUTTON_DONE" = "Fertig"; +"BUTTON_GET_STARTED" = "Los geht’s"; +"BUTTON_LEARN_MORE" = "Weitere Infos"; +"BUTTON_NEXT" = "Weiter"; +"BUTTON_SKIP" = "Überspringen"; +"BUTTON_SKIP_QUESTION" = "Frage überspringen"; +"BUTTON_START_TIMER" = "Timer starten"; +"BUTTON_OPTION_SAVE" = "Für später sichern"; +"BUTTON_OPTION_DISCARD" = "Ergebnisse löschen"; +"BUTTON_OPTION_STOP_TASK" = "Aufgabe beenden"; +"BUTTON_SAVE" = "Sichern"; +"BUTTON_CLEAR_ANSWER" = "Antwort löschen"; +"BUTTON_READ_ONLY_MODE" = "Diese Antwort kann nicht geändert werden."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Schließen"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Aktivität beginnt in"; +"TASK_COMPLETE_TITLE" = "Aktivität abgeschlossen"; +"TASK_COMPLETE_TEXT" = "Deine Daten werden analysiert und du wirst benachrichtigt, wenn deine Ergebnisse bereitstehen."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Noch %@."; +"TOUCH_ANYWHERE_LABEL" = "Tippe auf den Bildschirm, um fortzufahren."; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Bild aufnehmen"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Bild erneut aufnehmen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Keine Kamera gefunden. Dieser Schritt kann nicht abgeschlossen werden."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Erlaube der App in den Einstellungen Zugriff auf die Kamera, um diesen Schritt abzuschließen."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Es wurde kein Ausgabeverzeichnis für aufgenommene Bilder festgelegt."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Das aufgenommene Bild konnte nicht gesichert werden."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Aufnahme starten"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Aufnahme stoppen"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Video erneut aufnehmen"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Strecke (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Herzfrequenz (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Setze dich %@ bequem hin."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Gehe %@ lang so schnell wie möglich."; +"FITNESS_INTRO_TEXT_FORMAT" = "Mit dieser Aktivität wird deine Herzfrequenz kontrolliert und gemessen, wie weit du in %1$@ laufen kannst."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Gehe draußen %1$@ lang so schnell wie möglich. Setze dich anschließend %2$@ bequem hin und ruhe dich aus. Tippe zum Starten auf „Los geht’s“."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gang und Gleichgewicht"; +"WALK_INTRO_TEXT" = "Mit dieser Aktivität wird dein Gang und Gleichgewichtsinn beim Gehen und Stillstehen getestet. Fahre nur fort, wenn du ohne Hilfe sicher gehen kannst."; +"WALK_INTRO_2_TEXT_%ld" = "Finde eine Stelle, an der du sicher und ohne Hilfe etwa %ld Schritte in einer geraden Linie gehen kannst."; +"WALK_INTRO_2_DETAIL" = "Stecke dein Gerät in eine Hosentasche oder andere Tasche und folge den Audioanleitungen."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Stehe jetzt %@ still."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stehe %@ still."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Drehe dich um und gehe zum Ausgangspunkt zurück."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Gehe bis zu %ld Schritte in einer geraden Linie."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Suche eine Stelle, an der du auf einer geraden Linie sicher vor- und zurückgehen kannst. Versuche, gleichmäßig zu gehen, indem du am Ende des Weges so umkehrst, als würdest du um einen Kegel herumgehen.\n\nAls Nächstes wirst du aufgefordert, dich um die eigene Achse zu drehen und dann stehenzubleiben, wobei du die Arme an den Seiten hältst und deine Füße schulterbreit aufstellst."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tippe auf „Los geht’s!“, um anzufangen.\nStecke dein Gerät dann in eine Hosentasche oder eine andere Tasche und folge den Audioanleitungen."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Gehe in einer geraden Linie %@ weit vor und zurück. Gehe so, wie du normal gehst."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Drehe dich einmal im Kreis und bewege dich dann %@ lang nicht."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Du hast diese Aktivität abgeschlossen."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tipptempo"; +"TAPPING_TASK_TITLE_RIGHT" = "Rechte Hand"; +"TAPPING_TASK_TITLE_LEFT" = "Linke Hand"; +"TAPPING_INTRO_TEXT" = "Diese Aktivität misst dein Tipptempo."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Lege dein Gerät auf eine flache Oberfläche."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Verwende zwei Finger derselben Hand, um abwechselnd auf die Tasten auf dem Bildschirm zu tippen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Verwende zwei Finger deiner rechten Hand, um abwechselnd auf die Tasten auf dem Bildschirm zu tippen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Verwende zwei Finger deiner linken Hand, um abwechselnd auf die Tasten auf dem Bildschirm zu tippen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Wiederhole den Test nun mit deiner rechten Hand."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Wiederhole den Test nun mit deiner linken Hand."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tippe erst mit einem Finger und dann mit dem anderen. Versuche in möglichst gleichmäßigen Abständen zu tippen. Tippe %@ lang."; +"TAPPING_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tippe auf „Weiter“, um anzufangen."; +"TAP_BUTTON_TITLE" = "Tippen"; +"TOTAL_TAPS_LABEL" = "Tippanzahl"; +"TAPPING_INSTRUCTION" = "Tippe mit zwei Fingern so gleichmäßig wie möglich auf die Tasten."; +"TAPPING_INSTRUCTION_RIGHT" = "Tippe mit deiner RECHTEN Hand auf die Tasten."; +"TAPPING_INSTRUCTION_LEFT" = "Tippe mit deiner LINKEN Hand auf die Tasten."; +"TAPPING_SKIP_TITLE" = "Diese Hand überspringen"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler-Gitter"; +"AMSLER_GRID_INTRO_TEXT" = "Diese Aktivität hilft dabei, Probleme beim Sehvermögen des Benutzers festzustellen."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Halte das Gerät während des Tests etwa 30 cm weit von deinem Gesicht entfernt auf Augenhöhe."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Schließe dein %@ und fixiere den Punkt in der Mitte des quadratischen Gitters.\n\nVerwende deinen Finger oder den Stylus und markiere alle Störungen, die du als unscharfe oder gewellte Linien siehst.\n\nStreiche abschließend links an einer beliebigen Stelle außerhalb des Gitters."; +"AMSLER_GRID_LEFT_EYE" = "Linkes Auge"; +"AMSLER_GRID_RIGHT_EYE" = "Rechtes Auge"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Stimme"; +"AUDIO_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"AUDIO_INSTRUCTION" = "Sage solange wie möglich „Aaaaah“ in das Mikrofon."; +"AUDIO_INTRO_TEXT" = "Hole tief Luft und sage solange wie möglich und mit gleichbleibender Lautstärke „Aaaaah“ in das Mikrofon, sodass die Audiobalken blau bleiben."; +"AUDIO_INTENDED_USE" = "Diese Aktivität prüft deine Stimme, indem sie mit dem Mikrofon an der Unterseite deines Geräts aufgenommen wird."; +"AUDIO_TOO_LOUD_LABEL" = "Zu laut"; +"AUDIO_GENERIC_ERROR_LABEL" = "Aufnahme von Audiomaterial nicht möglich"; +"AUDIO_LEVEL_CHECK_LABEL" = "Bitte warte, während der Hintergrundgeräuschpegel überprüft wird."; +"AUDIO_TOO_LOUD_MESSAGE" = "Der Hintergrundgeräuschpegel ist zu hoch, um deine Stimme aufzunehmen. Bitte gehe an einen leiseren Ort und versuche es erneut."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tippe auf „Weiter“, wenn du bereit bist."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tonaudiometrie"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Diese Aktivität misst deine Fähigkeit, unterschiedliche Töne zu hören."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Schließe zunächst die Kopfhörer an und setze sie auf.\n\nDer Klang wird sehr leise sein und ähnelt keinem üblichen Hinweiston.  Der Ton beginnt leise und wird allmählich lauter.  Bitte pass genau auf und tippe auf die linke oder rechte Taste, um zu zeigen, mit welchem Ohr du den Ton hörst."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Du solltest jetzt einen Ton hören. Passe die Lautstärke mit den Steuerelementen an der Seite deines Geräts an.\n\nTippe auf eine Taste, wenn du beginnen möchtest."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Tippe jedes Mal, wenn du einen Ton hörst, auf die linke oder rechte Taste, um anzuzeigen, auf welchem Ohr du den Ton hörst."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Linkes Ohr"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Rechtes Ohr"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Links"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Rechts"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tonaudiometrie"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tippe, wenn du einen Ton hörst."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ton & Lautstärke"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Du wirst eine Serie von Tönen hören."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Wenn du einen Ton hörst, tippe auf die Taste."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Für diesen Test wird die Lautstärke auf 50 Prozent gestellt."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Dieser Test dauert etwa 10 Minuten."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Aktiviere „Nicht stören“, um Unterbrechungen zu vermeiden."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Es werden erst in deinem rechten Ohr Töne wiedergegeben."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Es werden jetzt in deinem linken Ohr Töne wiedergegeben."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Diese Aktivität identifiziert die Hörschwellenpegel eines Individuums in db auf einer HL-Skala."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Vergewissere dich, dass die Gerätelautstärke auf den höchsten Pegel eingestellt ist.\n\nWährend dieser Aufgabe wird ein leiser Ton im linken oder rechten Ohr abgespielt.\n\nHöre genau zu und tippe jedes Mal auf die Taste, wenn du einen Ton hörst."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Dieser Test identifiziert, wie laut ein Ton sein muss, damit du ihn hörst."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Eingangsfragebogen."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Wähle das „bessere Ohr“ als deine Vorliebe, falls nötig"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "links"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "rechts"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "keine Vorliebe"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test abgebrochen"; +"dBHL_ALERT_TITLE_START_OVER" = "Erneut starten"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Test abbrechen"; +"dBHL_ALERT_TEXT" = "Schließe deine AirPods oder EarPods erneut an, um diesen Test zu machen."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ vollständig"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Kopfhörer"; +"HEADPHONES_UNKNOWN" = "Unbekannt"; +"HEADPHONES_NONE" = "Keine"; +"CONNECTED" = "Verbunden"; +"NOT_CONNECTED" = "Nicht verbunden"; +"HEADPHONE_CONNECTED_%@" = "Verbunden - %@"; +"HEADPHONE_DETECT_TITLE" = "Kopfhörer anschließen"; +"HEADPHONE_DETECT_TEXT" = "Für diesen Test sind Apple AirPods oder Apple EarPods erforderlich"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Räumliches Gedächtnis"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Mit dieser Aktivität wird dein räumliches Kurzzeitgedächtnis gemessen, indem du aufgefordert wirst, die Reihenfolge, in der die %@ aufleuchten, zu wiederholen."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "Blumen"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "Blumen"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Einige der %@ werden der Reihe nach aufleuchten. Tippe in derselben Reihenfolge auf diese %@."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Einige der %@ werden der Reihe nach aufleuchten. Tippe in umgekehrter Reihenfolge auf diese %@."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“ und schaue dann genau hin."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Ergebnis"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Auf das Aufleuchten der %@ achten"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tippe auf die %@ in der Reihenfolge, in der sie aufleuchten"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tippe in umgekehrter Reihenfolge auf die %@"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequenz abgeschlossen"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Zum Fortfahren tippst du auf „Weiter“"; +"MEMORY_GAME_FAILED_TITLE" = "Erneut versuchen"; +"MEMORY_GAME_FAILED_MESSAGE" = "Du hast es diesmal nicht ganz geschafft. Zum Fortfahren tippe auf „Weiter“."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Zeit ist abgelaufen"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Deine Zeit ist vorbei.\nTippe auf „Weiter“, um fortzufahren."; +"MEMORY_GAME_COMPLETE" = "Spiel abgeschlossen"; +"MEMORY_GAME_PAUSED_TITLE" = "Angehalten"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Zum Fortfahren tippst du auf „Weiter“"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Die Gedächtnisaktivität wurde in Zusammenarbeit mit Katherine Possin, PhD, und Joel Kramer, PhD, der University of California, San Francisco entwickelt."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaktionszeit"; +"REACTION_TIME_TASK_INTENDED_USE" = "Mit dieser Aktivität wird bewertet, wie lange du brauchst, um auf optische Reize zu reagieren."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Schüttle das Gerät, sobald der blaue Punkt auf dem Bildschirm angezeigt wird. Du wirst %D-mal dazu aufgefordert."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Versuch %@ von %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Wenn der blaue Kreis angezeigt wird, schüttle das Gerät schnell"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Wähle jedes Mal, wenn ein Wort erscheint, den ersten Buchstaben der FARBE aus, die angezeigt wird."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Wenn du bereit bist, mit der Stroop-Aktivität zu beginnen, tippe auf „Los geht’s“."; +"STROOP_TASK_STEP_TEXT" = "Wähle den ersten Buchstaben der FARBE aus, die angezeigt wird."; +"STROOP_COLOR_RED" = "ROT"; +"STROOP_COLOR_GREEN" = "GRÜN"; +"STROOP_COLOR_BLUE" = "BLAU"; +"STROOP_COLOR_YELLOW" = "GELB"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "Gr"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ge"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Türme von Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Diese Aktivität misst deine Fähigkeit, Rätsel zu lösen."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Bewege den gesamten Stapel in so wenigen Zügen wie möglich auf den markierten Turm."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Löse das Rätsel"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Anzahl der Bewegungen: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Ich kann dieses Rätsel nicht lösen"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Bewegungsbereich"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption muss „links“ oder „rechts“ sein"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Linkes Knie Bewegungsumfang"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rechtes Knie Bewegungsumfang"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Diese Aktivität misst, wie weit du dein linkes Knie strecken kannst."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Diese Aktivität misst, wie weit du dein rechtes Knie strecken kannst."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Setze dich an den Rand eines Stuhls. Wenn es losgeht, legst du dein Gerät zur Messung auf dein linkes Knie. Bitte schalte bei deinem Gerät den Ton an, damit du die Anweisungen hören kannst."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Setze dich an den Rand eines Stuhls. Wenn es losgeht, legst du dein Gerät zur Messung auf dein rechtes Knie. Bitte schalte bei deinem Gerät den Ton an, damit du die Anweisungen hören kannst."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Lege dein Gerät wie abgebildet auf dein linkes Knie mit dem Bildschirm nach außen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Lege dein Gerät wie abgebildet auf dein rechtes Knie mit dem Bildschirm nach außen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Wenn du bereit bist, tippe zum Starten auf den Bildschirm und strecke dein linkes Knie so weit wie möglich durch. Kehre zur Startposition zurück und tippe erneut, wenn du fertig bist."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Wenn du bereit bist, tippe zum Starten auf den Bildschirm und strecke dein rechtes Knie so weit wie möglich durch. Kehre zur Startposition zurück und tippe erneut, wenn du fertig bist."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Lege dein Gerät auf dein linkes Knie. Tippe auf den Bildschirm und strecke dein linkes Knie so weit wie möglich durch."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Lege dein Gerät auf dein rechtes Knie. Tippe auf den Bildschirm und strecke dein rechtes Knie so weit wie möglich durch."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Wenn du fertig bist, bringe dein linkes Knie wieder in die Startposition und tippe dann auf den Bildschirm."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Wenn du fertig bist, bringe dein rechtes Knie wieder in die Startposition und tippe dann auf den Bildschirm."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Linke Schulter Bewegungsumfang"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rechte Schulter Bewegungsumfang"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Diese Aktivität misst, wie weit du deine linke Schulter strecken kannst."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Diese Aktivität misst, wie weit du deine rechte Schulter strecken kannst."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Wenn es losgeht, legst du dein Gerät zur Messung auf deine linke Schulter. Bitte schalte bei deinem Gerät den Ton an, damit du die Anweisungen hören kannst."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Wenn es losgeht, legst du dein Gerät zur Messung auf deine rechte Schulter. Bitte schalte bei deinem Gerät den Ton an, damit du die Anweisungen hören kannst."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Lege dein Gerät wie abgebildet auf deine linke Schulter mit dem Bildschirm nach außen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Lege dein Gerät wie abgebildet auf deine rechte Schulter mit dem Bildschirm nach außen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Wenn du bereit bist, tippe zum Starten auf den Bildschirm und hebe den linken Arm so weit wie möglich an. Kehre zur Startposition zurück und tippe erneut, wenn du fertig bist."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Wenn du bereit bist, tippe zum Starten auf den Bildschirm und hebe den rechten Arm so weit wie möglich an. Kehre zur Startposition zurück und tippe erneut, wenn du fertig bist."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Lege dein Gerät auf deine linke Schulter. Tippe auf den Bildschirm und strecke den linken Arm so weit wie möglich nach vorne aus."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Lege dein Gerät auf deine rechte Schulter. Tippe auf den Bildschirm und strecke den rechten Arm so weit wie möglich nach vorne aus."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Wenn du fertig bist, bringe deinen linken Arm wieder in die Startposition und tippe dann auf den Bildschirm."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Wenn du fertig bist, bringe deinen rechten Arm wieder in die Startposition und tippe dann auf den Bildschirm."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Gehen mit Zeitmessung"; +"TIMED_WALK_INTRO_DETAIL" = "Diese Aktivität misst die Funktion deiner unteren Extremitäten"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Finde einen Ort, am besten draußen, an dem du sicher ca. %@ so schnell wie möglich in einer geraden Linie gehen kannst. Werde erst langsamer, wenn du das Ziel erreicht hast."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tippe auf „Weiter“, um anzufangen."; +"TIMED_WALK_FORM_TITLE" = "Gehhilfe"; +"TIMED_WALK_FORM_TEXT" = "Verwende für jeden Test dieselbe Gehhilfe."; +"TIMED_WALK_QUESTION_TEXT" = "Verwendest du eine Unterschenkelorthese?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Verwendest du Gehhilfen?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tippen, um eine Antwort auszuwählen."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ohne"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Gehstock, eine Seite"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Krücke, eine Seite"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Gehstock, beide Seiten"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Krücken, beide Seiten"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Gehe bis zu %@ in einer geraden Linie."; +"TIMED_WALK_INSTRUCTION_TURN" = "Drehe dich um."; +"TIMED_WALK_INSTRUCTION_2" = "Gehe zum Ausgangspunkt zurück."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tippe danach auf „Weiter“."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Der akustische Serienaddiertest mit Zeitlimit (PASAT, Paced Auditory Serial Addition Test) misst, wie schnell du akustische Informationen verarbeiten und rechnen kannst."; +"PVSAT_INTRO_TEXT" = "Der visuelle Serienaddiertest mit Zeitlimit (PASAT, Paced Visual Serial Addition Test) misst, wie schnell du optische Informationen verarbeiten und rechnen kannst."; +"PAVSAT_INTRO_TEXT" = "Der audiovisuelle Serienaddiertest mit Zeitlimit (PAVSAT, Paced Auditory and Visual Serial Addition Test) misst, wie schnell du akustische und optische Informationen verarbeiten und rechnen kannst."; +"PSAT_INTRO_TEXT_2_%@" = "Alle %@ werden einzelne Zahlen präsentiert.\nDu musst jede neue Zahl zu der unmittelbar vorhergehenden addieren.\nAchtung, du sollst nicht die Gesamtsumme bilden, sondern nur die Summe der beiden letzten Zahlen."; +"PSAT_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"PSAT_INITIAL_INSTRUCTION" = "Merke dir die erste Zahl."; +"PSAT_INSTRUCTION" = "Addiere diese Zahl zur vorherigen."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-Hole-Peg-Test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Mit dieser Aktivität wird die Reaktionsfähigkeit deiner oberen Extremitäten gemessen, indem du aufgefordert wirst, einen Kreis auf einem Loch zu platzieren. Das Ganze wird %@-mal wiederholt."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Sowohl deine linke als auch die rechte Hand werden getestet.\nDu musst den Stift so schnell wie möglich greifen, in das Loch stecken und nach einer %@-maligen Wiederholung wieder %@-mal entfernen."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Sowohl deine rechte als auch die linke Hand werden getestet.\nDu musst den Stift so schnell wie möglich greifen, in das Loch stecken und nach einer %@-maligen Wiederholung wieder %@-mal entfernen."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Bewege den Kreis mit der linken Hand in das Loch."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Bewege den Kreis mit der rechten Hand in das Loch."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Bewege den Kreis mit der linken Hand hinter die Linie."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Bewege den Kreis mit der rechten Hand hinter die Linie."; +"HOLE_PEG_TEST_TEXT" = "Bewege den Kreis mit zwei Fingern."; +"HOLE_PEG_TEST_TEXT_2" = "Hebe den Finger, um den Kreis auf die Zielposition zu setzen."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Zitteraktivität"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Mit dieser Aktivität wird gemessen, wie sehr deine Hände in unterschiedlichen Haltungen zittern. Führe diese Aktivität an einem Ort durch, an dem du währenddessen bequem sitzen kannst."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Halte dein Telefon in der stärker betroffenen Hand, wie unten im Bild zu sehen."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Halte dein Telefon in der RECHTEN Hand, wie unten im Bild zu sehen."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Halte dein Telefon in der LINKEN Hand, wie unten im Bild zu sehen."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Du wirst aufgefordert %@ durchzuführen, während du sitzend dein Telefon in der Hand hältst."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "eine Aufgabe"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "zwei Aufgaben"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "drei Aufgaben"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "vier Aufgaben"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "fünf Aufgaben"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tippe auf „Weiter“, um fortzufahren."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Bereite dich darauf vor, dein Telefon im Schoß zu halten."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Bereite dich darauf vor, dein Telefon mit der LINKEN Hand im Schoß zu halten."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Bereite dich darauf vor, dein Telefon mit der RECHTEN Hand im Schoß zu halten."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Halte %ld Sekunden lang dein Telefon in deinem Schoß."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Halte dein Telefon nun mit ausgestreckter Hand in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Halte dein Telefon nun mit ausgestreckter LINKER Hand in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Halte dein Telefon nun mit ausgestreckter RECHTER Hand in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Halte mit ausgestreckter Hand %ld Sekunden lang dein Telefon."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Halte dein Telefon nun mit angewinkeltem Ellenbogen in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Halte dein Telefon nun in deiner LINKEN Hand mit angewinkeltem Ellenbogen in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Halte dein Telefon nun in deiner RECHTEN Hand mit angewinkeltem Ellenbogen in Schulterhöhe."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Halte mit angewinkeltem Ellenbogen %ld Sekunden lang dein Telefon"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Winkle nun deinen Ellenbogen an und berühre wiederholt mit deinem Telefon deine Nase."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Winkle nun deinen Ellenbogen an, halte dein Telefon in der LINKEN Hand und berühre wiederholt mit deinem Telefon deine Nase."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Winkle nun deinen Ellenbogen an, halte dein Telefon in der RECHTEN Hand und berühre wiederholt mit deinem Telefon deine Nase."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Halte dein Telefon %ld Sekunden lang an deine Nase"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Bereite dich darauf vor, zu winken, indem du dein Handgelenk drehst."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Bereite dich darauf vor, mit dem Telefon in deiner LINKEN Hand zu winken, indem du dein Handgelenk drehst."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Bereite dich darauf vor, mit dem Telefon in deiner RECHTEN Hand zu winken, indem du dein Handgelenk drehst."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Winke %ld Sekunden lang."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Wechsle nun zu deiner LINKEN Hand und fahre mit der nächsten Aufgabe fort."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Wechsle nun zu deiner RECHTEN Hand und fahre mit der nächsten Aufgabe fort."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Weiter zur nächsten Aufgabe."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivität abgeschlossen."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Du wirst aufgefordert %@ durchzuführen, während du sitzend dein Telefon zuerst in der einen, dann in der anderen Hand hältst."; +"TREMOR_SKIP_LEFT_HAND" = "Ich kann diese Aktivität mit meiner LINKEN Hand nicht durchführen."; +"TREMOR_SKIP_RIGHT_HAND" = "Ich kann diese Aktivität mit meiner RECHTEN Hand nicht durchführen."; +"TREMOR_SKIP_NEITHER" = "Ich kann diese Aktivität mit beiden Händen durchführen."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trail Making Test"; +"TRAILMAKING_INTENDED_USE" = "Mit dieser Aktivität werden deine visuelle Aufmerksamkeit und der Aufgabenwechsel geprüft, indem die Zeit gemessen wird, die du benötigst, um in der richtigen Reihenfolge auf eine Reihe von Punkten zu tippen."; +"TRAILMAKING_INTENDED_USE2_A" = "Tippe nach dem Countdown abwechselnd auf die Punkte mit Zahlen und Buchstaben. Beginne damit, auf die erste Zahl („1“) zu tippen und dann weiter auf „2“ – „3“ – „4“ … bis du zur Zahl „7“ gelangst."; +"TRAILMAKING_INTENDED_USE2_B" = "Tippe nach dem Countdown abwechselnd auf die Punkte mit Zahlen und Buchstaben. Beginne damit, auf die erste Zahl („1“) zu tippen, danach auf den ersten Buchstaben „A“ und dann weiter auf „2“ – „B“ – „3“ – „C“ bis du zur Zahl „7“ gelangst."; +"TRAILMAKING_INTRO_TEXT" = "Führe dies so schnell aus, wie du kannst, ohne Fehler zu machen. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Spracherkennung"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Diese Aktivität zeichnet deine Stimme mit dem Mikrofon an der Unterseite des Geräts auf und setzt das Gesprochene in Text um."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tippe zum Starten auf „Los geht’s“."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Drücke bereits vor dem Sprechen auf die Taste, um die Aufnahme zu starten."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Aufnahme starten"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Aufnahme stoppen"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Transkript ändern"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Bearbeite den transkribierten Text, um alle Fehlinterpretationen der Sprache zu korrigieren."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Deine Transkription wird hier angezeigt."; +"SPEECH_RECOGNITION_FAILED" = "Spracherkennung fehlgeschlagen."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Die Spracherkennung konnte nicht initialisiert werden."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Audio wiedergeben"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Audio stoppen"; +"SPEECH_IN_NOISE_TITLE" = "Sprechen bei Geräuschkulisse"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Diese Aktivität misst, wie verständlich die Sprache ist, wenn sie in lauten Umgebungen zu hören ist."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Als Teil dieses Tests wirst du Folgendes tun:\n\nHöre einen Satz an.\n\nWiederhole deutlich, was du gehört hast, oder fahre fort, um das Gehörte mit der Tastatur einzugeben. \n\nWenn du das Gehörte wiederholst, hast du die Möglichkeit, das von der Spracherkennungs-Engine generierte Transkript zu ändern."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Lautstärkekalibrierung"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tippe auf „Audio wiedergeben“, um die Lautstärke auf einen angenehmen Pegel einzustellen, und tippe dann auf „Audio stoppen“, um fortzufahren."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Hören"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Ein Satz, der bei einer zufälligen SNR-Rate (Signal-to-Noise-Ratio) mit Hintergrundgeräuschen gemischt wurde, wird einmal abgespielt."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Sprechen"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Wiederhole das Gehörte."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Fehler beim Erstellen der Datei"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Es konnten nicht genügend Protokolldateien gelöscht werden, um den Schwellenwert zu erreichen."; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Fehler beim Einstellen des Attributs"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Datei nicht als gelöscht markiert (nicht als geladen markiert)"; +"ERROR_DATALOGGER_MULTIPLE" = "Mehrere Fehler beim Entfernen von Protokollen"; +"ERROR_RECORDER_NO_DATA" = "Es wurden keine erfassten Daten gefunden."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Kein Ausgabeverzeichnis angegeben"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Schallpegelmesser"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Diese Aktivität misst den Schalldruckpegel der Umgebung. Wenn die Geräuschpegel zu hoch sind, kannst du nicht fortfahren. Bitte schließe diese Aufgabe dann in einer ruhigeren Umgebung ab oder führe diese Aktivität zu einem späteren Zeitpunkt durch."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Rechnen"; +"ENVIRONMENTSPL_THRESHOLD" = "Schwellenwert: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Hintergrundgeräusch OK"; +"ENVIRONMENTSPL_NOISE" = "Zu viel Hintergrundgeräusch"; +"ENVIRONMENTSPL_TITLE_2" = "Einen ruhigen Ort finden"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Um sicherzustellen, dass erfasste Daten akkurat sind, sollte dieser Test in einer ruhigen Umgebung erfolgen."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Aufgabe starten"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Keine Daten"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Bewege den Schieberegler zur Werteingabe"; +"SLIDER_I_DONT_KNOW" = "Ich weiß nicht"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Seite"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Zurück"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDF-Miniatur einblenden"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDF-Miniatur ausblenden"; +"AX_BUTTON_ANNOTATE" = "Anmerken"; +"AX_BUTTON_SHOW_SEARCH" = "Suchleiste einblenden"; +"AX_BUTTON_HIDE_SEARCH" = "Suchleiste ausblenden"; +"AX_BUTTON_SHARE" = "Teilen"; + + +"AX_COMPLETION_ILLUSTRATION" = "Die Abbildung eines Häkchens in einem blauen Kreis, das auf Erfolg hinweist"; + +"AX_SIGNVIEW_LABEL" = "Vorgesehenes Unterschriftsfeld"; +"AX_SIGNVIEW_HINT" = "Bildschirm berühren und mit dem Finger unterschreiben"; +"AX_SIGNVIEW_SIGNED" = "Unterschrieben"; +"AX_SIGNVIEW_UNSIGNED" = "Keine Unterschrift"; + +"AX_SELECTED" = "Ausgewählt"; +"AX_UNSELECTED" = "Nicht ausgewählt"; +"AX_SELECT_ALL_THAT_APPLY" = "ALLE ZUTREFFENDEN OPTIONEN AUSWÄHLEN"; + +"AX_SLIDER_LABEL" = "Antwortregler. Bereich von %@ bis %@"; +"AX_UNLABELED_IMAGE" = "Nicht markiertes Bild"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Aufgabe starten"; + +"AX.MEMORY.TILE.ACTIVE" = "aktiv"; +"AX.MEMORY.TILE.CORRECT" = "richtig"; +"AX.MEMORY.TILE.INCORRECT" = "falsch"; +"AX.MEMORY.TILE.QUIESCENT" = "inaktiv"; +"AX.MEMORY.TILE.LABEL" = "Gedächtnisspielkarten"; + +"AX_IMAGE_CAPTURE_LABEL" = "Vorschau aufnehmen"; +"AX_IMAGE_CAPTURED_LABEL" = "Aufgenommenes Bild"; + +"AX_VIDEO_CAPTURE_LABEL" = "Videoaufnahmenvorschau"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Videoaufnahme abgeschlossen"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Die Scheibe der Größe %@ kann nicht auf die Scheibe der Größe %@ gelegt werden"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Ziel"; +"AX_TOWER_OF_HANOI_TOWER" = "Turm"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Zum Ablegen der Scheibe doppeltippen"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Zum Auswählen der obersten Scheibe doppeltippen"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Mit Scheiben in den Größen %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Leer"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Tastatur schließen"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Bereich von %@ bis %@"; +"AX_GRAPH_STACK_PREFIX" = "Stapel besteht aus"; +"AX_GRAPH_AND_SEPARATOR" = " und "; +"AX_GRAPH_POINT_%@" = "Punkt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Sprachwellenform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Wenn die Aufnahme startet, aktiviere sie ein zweites Mal, um die Aufnahme zu stoppen."; + +"AX_AUDIO_BAR_GRAPH" = "Audio-Balkendiagramm"; + +"AX_AMSLER_GRID_LABEL" = "Amsler-Gitter"; +"AX_AMSLER_GRID_HINT" = "Markiere das Gitter direkt mit deinem Finger oder dem Stylus oder streiche links an einer beliebigen Stelle außerhalb des Gitters, um die Aufgabe zu beenden."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Antippbare Tasten"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Für das linke Ohr tippen"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Zum Starten des Tests aktivieren. Wenn der Test startet, tippe direkt auf diese Taste, wenn du im linken Ohr einen Ton hörst."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Für das rechte Ohr tippen"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Zum Starten des Tests aktivieren. Wenn der Test startet, tippe direkt auf diese Taste, wenn du im rechten Ohr einen Ton hörst."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Verwende VoiceOver und erkunde den Bildschirm mit deinen Fingern, um zu lernen, wo sich die Tasten für jedes Ohr befinden. Wenn der Test startet, können die Tasten direkt angetippt werden. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Für einen Finger tippen"; +"AX_TAP_BUTTON_2_LABEL" = "Für den anderen Finger tippen"; +"AX_TAP_BUTTON_HINT" = "Aktivieren, damit die Tasten antippbar werden."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Verwende VoiceOver und erkunde den Bildschirm mit deinen Fingern, um zu lernen, wo sich die Tasten befinden. Aktiviere eine der beiden Tasten, damit sie direkt angetippt werden können."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Tasten können jetzt direkt angetippt werden."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Beim Verwenden von VoiceOver kann die Taste direkt angetippt werden. Sie befindet sich in der Nähe der Bildschirmmitte."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Beim Verwenden von VoiceOver können die Tasten im Test direkt angetippt werden."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "restoreData kann nicht für Initialisierung decodiert werden"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..2adac05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/de.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d Fehler) + other + (%d Fehler) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.strings new file mode 100755 index 0000000..45ed767 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Συναίνεση"; +"CONSENT_NAME_GIVEN" = "Όνομα"; +"CONSENT_NAME_FAMILY" = "Επώνυμο"; +"CONSENT_NAME_PLACEHOLDER" = "Απαιτείται"; +"CONSENT_REVIEW_TITLE" = "Έλεγχος"; +"CONSENT_REVIEW_INSTRUCTION" = "Διαβάστε την παρακάτω φόρμα και αγγίξτε «Αποδοχή» αν είστε έτοιμοι να συνεχίσετε."; +"CONSENT_REVIEW_ALERT_TITLE" = "Έλεγχος"; +"CONSENT_SIGNATURE_TITLE" = "Υπογραφή"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Υπογράψτε με το δάχτυλό σας στο παρακάτω πλαίσιο."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Υπογράψτε εδώ"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Σελίδα %1$ld από %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Καλώς ορίσατε"; +"CONSENT_SECTION_DATA_GATHERING" = "Συλλογή δεδομένων"; +"CONSENT_SECTION_PRIVACY" = "Απόρρητο"; +"CONSENT_SECTION_DATA_USE" = "Χρήση δεδομένων"; +"CONSENT_SECTION_STUDY_SURVEY" = "Έρευνα μελέτης"; +"CONSENT_SECTION_STUDY_TASKS" = "Εργασίες μελέτης"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Απαιτούμενος χρόνος"; +"CONSENT_SECTION_WITHDRAWING" = "Αποχώρηση"; +"CONSENT_LEARN_MORE_TITLE" = "Μάθετε περισσότερα"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Μάθετε περισσότερα για τη συλλογή δεδομένων"; +"LEARN_MORE_DATA_USE" = "Μάθετε περισσότερα για τον τρόπο χρήσης των δεδομένων"; +"LEARN_MORE_PRIVACY" = "Μάθετε περισσότερα για τον τρόπο προστασίας του απορρήτου και της ταυτότητάς σας"; +"LEARN_MORE_WELCOME" = "Μάθετε περισσότερα για τη μελέτη πρώτα"; +"LEARN_MORE_STUDY_SURVEY" = "Μάθετε περισσότερα για την έρευνα μελέτης"; +"LEARN_MORE_TIME_COMMITMENT" = "Μάθετε περισσότερα για τον χρόνο που θα χρειαστείτε για να ολοκληρώσετε τη μελέτη"; +"LEARN_MORE_TASKS" = "Μάθετε περισσότερα για τις σχετιζόμενες εργασίες"; +"LEARN_MORE_WITHDRAWING" = "Μάθετε περισσότερα για την αποχώρηση από την έρευνα"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Επιλογές κοινοποίησης"; +"CONSENT_SHARE_WIDELY_%@" = "Κοινοποίηση των δεδομένων μου στο %@ και πιστοποιημένους ερευνητές ανά τον κόσμο"; +"CONSENT_SHARE_ONLY_%@" = "Κοινοποίηση των δεδομένων μου μόνο σε: %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "Η %@ θα λάβει τα δεδομένα που θα προκύψουν από τη συμμετοχή σας σε αυτήν τη μελέτη.\n\nΗ πιο ευρεία κοινοποίηση των κωδικοποιημένων δεδομένων μελέτης σας (χωρίς πληροφορίες όπως π.χ. το όνομά σας) μπορεί να ωφελήσουν αυτήν και τυχόν μελλοντικές μελέτες."; +"LEARN_MORE_CONSENT_SHARING" = "Μάθετε περισσότερα για την κοινοποίηση δεδομένων"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Ονοματεπώνυμο (ολογράφως)"; +"CONSENT_DOC_LINE_SIGNATURE" = "Υπογραφή"; +"CONSENT_DOC_LINE_DATE" = "Ημερομηνία"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ από %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Ερώτηση %1$@ από %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Παραλείφθηκε"; +"REVIEW_EDIT_ANSWER" = "Επεξεργασία"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Μη έγκυρη τιμή"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "Η τιμή «%1$@» υπερβαίνει τη μέγιστη επιτρεπόμενη τιμή (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "Η τιμή «%1$@» είναι χαμηλότερη από την ελάχιστη επιτρεπόμενη τιμή (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "Το «%@» δεν είναι έγκυρη τιμή."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Μη έγκυρη διεύθυνση email: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Εισαγάγετε διεύθυνση"; +"LOCATION_ERROR_TITLE" = "Δεν βρέθηκε η καθορισμένη διεύθυνση"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Δεν είναι δυνατή η επίλυση της τρέχουσας τοποθεσίας σας. Πληκτρολογήστε μια διεύθυνση ή μετακινηθείτε σε μια τοποθεσία με καλύτερο σήμα GPS, αν είναι δυνατόν."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Δεν επιτράπηκε η πρόσβαση στις υπηρεσίες τοποθεσίας. Παραχωρήστε άδεια σε αυτήν την εφαρμογή για χρήση των υπηρεσιών τοποθεσίας μέσω των Ρυθμίσεων."; +"LOCATION_ERROR_GEOCODE" = "Δεν βρέθηκε αποτέλεσμα για την εισαγμένη διεύθυνση. Βεβαιωθείτε ότι η διεύθυνση είναι έγκυρη."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Είτε δεν είστε συνδεδεμένοι στο Διαδίκτυο είτε έχετε υπερβεί το μέγιστο πλήθος αιτήσεων αναζήτησης διευθύνσεων. Αν δεν είστε συνδεδεμένοι στο Διαδίκτυο, ενεργοποιήστε το Wi-Fi για να απαντήσετε σε αυτήν την ερώτηση, παραλείψτε την ερώτηση αν είναι διαθέσιμο το κουμπί παράλειψης, ή επιστρέψτε στο ερωτηματολόγιο όταν συνδεθείτε στο Διαδίκτυο. Διαφορετικά, δοκιμάστε ξανά σε λίγα λεπτά."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Το περιεχόμενο κειμένου υπερβαίνει το επιτρεπόμενο όριο χαρακτήρων: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Η κάμερα δεν διατίθεται στην Προβολή διαίρεσης."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "gmilosporos@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Συνθηματικό"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Εισαγωγή"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Επιβεβαίωση"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Εισαγωγή πάλι"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Τα συνθηματικά δεν ταιριάζουν."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Πρόσθετες πληροφορίες"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Γιάννης"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Μηλοσπόρος"; +"GENDER_FORM_ITEM_TITLE" = "Φύλο"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Επιλογή"; +"DOB_FORM_ITEM_TITLE" = "Ημερομηνία γέννησης"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Επιλογή"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Αριθμός τηλεφώνου"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Επαλήθευση"; +"VERIFICATION_STEP_TITLE" = "Επαληθεύστε το email σας"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Αν δεν έχετε λάβει email επαλήθευσης, αγγίξτε τον παρακάτω σύνδεσμο για να σταλεί ξανά."; +"RESEND_EMAIL_BUTTON_TITLE" = "Νέα αποστολή email επιβεβαίωσης"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Είσοδος"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Ξεχάσατε το συνθηματικό;"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Εισαγωγή κωδικού"; +"PASSCODE_CONFIRM_MESSAGE" = "Επιβεβαίωση κωδικού"; +"PASSCODE_SAVED_MESSAGE" = "Ο κωδικός αποθηκεύτηκε"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Έγινε έλεγχος ταυτότητας κωδικού"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Εισαγάγετε τον παλιό κωδικό"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Εισαγάγετε τον νέο κωδικό"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Επιβεβαίωση νέου κωδικού"; +"PASSCODE_INVALID_ALERT_TITLE" = "Λανθασμένος κωδικός"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Ασυμφωνία κωδικών. Δοκιμάστε ξανά."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Πραγματοποιήστε έλεγχο ταυτότητας με Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Σφάλμα Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Επιτρέπονται μόνο αριθμητικοί χαρακτήρες."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Ένδειξη προόδου εισαγωγής κωδικού"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Εισάχθηκαν %@ από %@ ψηφία"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Ξεχάσατε τον κωδικό;"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Δεν ήταν δυνατή η προσθήκη στοιχείου της Κλειδοθήκης."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Δεν ήταν δυνατή η ενημέρωση στοιχείου της Κλειδοθήκης."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Δεν ήταν δυνατή η διαγραφή στοιχείου της Κλειδοθήκης."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Δεν ήταν δυνατή η εύρεση στοιχείου της Κλειδοθήκης."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "Α-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Τύπου I"; +"FITZPATRICK_SKIN_TYPE_II" = "Τύπου II"; +"FITZPATRICK_SKIN_TYPE_III" = "Τύπου III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Τύπου IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Τύπου V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Τύπου VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Γυναίκα"; +"GENDER_MALE" = "Άντρας"; +"GENDER_OTHER" = "Άλλο"; + +/* Boolean answer strings */ +"BOOL_NO" = "Όχι"; +"BOOL_YES" = "Ναι"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "εκ."; +"MEASURING_UNIT_FT" = "πδ"; +"MEASURING_UNIT_IN" = "ίντσ."; +"MEASURING_UNIT_KG" = "κ."; +"MEASURING_UNIT_LB" = "λβ"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "αριστερό"; +"LIMB_RIGHT" = "δεξί"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Αγγίξτε για απάντηση"; +"NULL_ANSWER" = "Επιλέξτε μια απάντηση"; +"PLACEHOLDER_IMAGE_CHOICES" = "Αγγίξτε για επιλογή"; +"PLACEHOLDER_LONG_TEXT" = "Αγγίξτε για γραφή"; + +/* Button titles */ +"BUTTON_AGREE" = "Αποδοχή"; +"BUTTON_CANCEL" = "Ακύρωση"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Εκκαθάριση"; +"BUTTON_CLEAR_SIGNATURE" = "Εκκαθάριση υπογραφής"; +"BUTTON_APPLY" = "Εφαρμογή"; +"BUTTON_DISAGREE" = "Απόρριψη"; +"BUTTON_DONE" = "Τέλος"; +"BUTTON_GET_STARTED" = "Έναρξη"; +"BUTTON_LEARN_MORE" = "Μάθετε περισσότερα"; +"BUTTON_NEXT" = "Επόμενο"; +"BUTTON_SKIP" = "Παράλειψη"; +"BUTTON_SKIP_QUESTION" = "Παράλειψη αυτής της ερώτησης"; +"BUTTON_START_TIMER" = "Έναρξη χρονοδιακόπτη"; +"BUTTON_OPTION_SAVE" = "Αποθήκευση για αργότερα"; +"BUTTON_OPTION_DISCARD" = "Απόρριψη αποτελεσμάτων"; +"BUTTON_OPTION_STOP_TASK" = "Τέλος εργασίας"; +"BUTTON_SAVE" = "Αποθήκευση"; +"BUTTON_CLEAR_ANSWER" = "Εκκαθάριση απάντησης"; +"BUTTON_READ_ONLY_MODE" = "Δεν είναι δυνατή η τροποποίηση αυτής της απάντησης."; +"BUTTON_COPYRIGHT" = "Πνευματικά δικαιώματα"; +"BUTTON_CLOSE" = "Κλείσιμο"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Έναρξη δραστηριότητας σε"; +"TASK_COMPLETE_TITLE" = "Η δραστηριότητα ολοκληρώθηκε"; +"TASK_COMPLETE_TEXT" = "Τα δεδομένα σας θα αναλυθούν και θα ειδοποιηθείτε όταν είναι έτοιμα τα αποτελέσματα."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Απομένουν %@."; +"TOUCH_ANYWHERE_LABEL" = "Αγγίξτε οπουδήποτε για να συνεχίσετε"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Καταγραφή εικόνας"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Επανάληψη καταγραφής εικόνας"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Δεν βρέθηκε κάμερα. Δεν είναι δυνατή η ολοκλήρωση αυτού του βήματος."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Για να ολοκληρώσετε αυτό το βήμα, επιτρέψτε σε αυτήν την εφαρμογή να προσπελάζει την κάμερα στις Ρυθμίσεις."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Δεν καθορίστηκε κατάλογος εξόδου για καταγραμμένες εικόνες."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Δεν ήταν δυνατή η αποθήκευση της καταγραμμένης εικόνας."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Έναρξη εγγραφής"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Διακοπή εγγραφής"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Εκ νέου καταγραφή βίντεο"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Φυσική κατάσταση"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Απόσταση (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Καρδιακοί παλμοί (π.α.λ.)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Καθίστε κάπου άνετα για %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Περπατήστε όσο πιο γρήγορα μπορείτε για %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Αυτή η δραστηριότητα αξιολογεί τους καρδιακούς παλμούς σας και μετρά πόσο μακριά μπορείτε να περπατήσετε σε %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Περπατήστε σε εξωτερικό χώρο όσο πιο γρήγορα μπορείτε για %1$@. Όταν τελειώσετε, καθίστε κάπου άνετα και ξεκουραστείτε για %2$@. Για να αρχίσετε, αγγίξτε «Έναρξη»."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Βάδισμα και ισορροπία"; +"WALK_INTRO_TEXT" = "Αυτή η δραστηριότητα αξιολογεί το βάδισμα και την ισορροπία σας καθώς περπατάτε και στέκεστε όρθιοι. Μην πραγματοποιήσετε τη δραστηριότητα αν δεν μπορείτε να περπατήσετε με ασφάλεια χωρίς βοήθεια."; +"WALK_INTRO_2_TEXT_%ld" = "Βρείτε έναν χώρο όπου μπορείτε να περπατήσετε με ασφάλεια χωρίς βοήθεια και κάντε περίπου %ld βήματα σε ευθεία γραμμή."; +"WALK_INTRO_2_DETAIL" = "Τοποθετήστε τη συσκευή σας στην τσέπη ή στην τσάντα σας και μετά ακολουθήστε τις ηχητικές οδηγίες."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Τώρα μείνετε ακίνητοι για %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Μείνετε ακίνητοι για %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Γυρίστε πίσω και περπατήστε μέχρι το σημείο από όπου αρχίσατε."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Περπατήστε έως %ld βήματα σε ευθεία γραμμή."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Βρείτε έναν χώρο όπου μπορείτε να περπατήσετε με ασφάλεια μπρος-πίσω σε ευθεία γραμμή. Προσπαθήστε να περπατήσετε συνεχόμενα στρίβοντας στα άκρα της διαδρομής, σαν να περπατάτε γύρω από έναν κώνο.\n\nΣτη συνέχεια, θα σας δοθούν οδηγίες να στρίψετε σε πλήρη κύκλο και μετά πρέπει να σταθείτε ακίνητοι με τα χέρια στα πλάγιά σας και τα πόδια σας ανοιχτά περίπου στην ευθεία του πλάτους των ώμων."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Αγγίξτε «Έναρξη» όταν είστε έτοιμοι να ξεκινήσετε.\nΤοποθετήστε τη συσκευή σας στην τσέπη ή στην τσάντα σας και μετά ακολουθήστε τις ηχητικές οδηγίες."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Περπατήστε μπρος-πίσω σε ευθεία γραμμή για %@ στον συνηθισμένο σας ρυθμό."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Κάντε μια πλήρη στροφή γύρω από τον εαυτό σας και μετά μείνετε ακίνητοι για %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Ολοκληρώσατε τη δραστηριότητα."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Ταχύτητα αγγίγματος"; +"TAPPING_TASK_TITLE_RIGHT" = "Δεξιό χέρι"; +"TAPPING_TASK_TITLE_LEFT" = "Αριστερό χέρι"; +"TAPPING_INTRO_TEXT" = "Αυτή η δραστηριότητα αξιολογεί την ταχύτητα αγγιγμάτων σας."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Τοποθετήστε τη συσκευή σας πάνω σε επίπεδη επιφάνεια."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Χρησιμοποιήστε δύο δάχτυλα του ίδιου χεριού για εναλλάξ άγγιγμα των κουμπιών στην οθόνη."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Χρησιμοποιήστε δύο δάχτυλα του δεξιού χεριού για εναλλάξ άγγιγμα των κουμπιών στην οθόνη."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Χρησιμοποιήστε δύο δάχτυλα του αριστερού χεριού για εναλλάξ άγγιγμα των κουμπιών στην οθόνη."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Τώρα επαναλάβετε το ίδιο τεστ με το δεξιό σας χέρι."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Τώρα επαναλάβετε το ίδιο τεστ με το αριστερό σας χέρι."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Αγγίξτε με το ένα δάχτυλο και μετά με το άλλο. Προσπαθήστε ώστε ο χρόνος μεταξύ των αγγιγμάτων να είναι όσο το δυνατόν ίδιος. Συνεχίστε τα αγγίγματα για %@."; +"TAPPING_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Αγγίξτε «Επόμενο» για να ξεκινήσετε."; +"TAP_BUTTON_TITLE" = "Αγγίξτε"; +"TOTAL_TAPS_LABEL" = "Συνολικά αγγίγματα"; +"TAPPING_INSTRUCTION" = "Αγγίξτε τα κουμπιά χρησιμοποιώντας δύο δάχτυλα και φροντίστε ο χρόνος μεταξύ των αγγιγμάτων να είναι όσο το δυνατόν ίδιος."; +"TAPPING_INSTRUCTION_RIGHT" = "Αγγίξτε τα κουμπιά χρησιμοποιώντας το ΔΕΞΙΟ σας χέρι."; +"TAPPING_INSTRUCTION_LEFT" = "Αγγίξτε τα κουμπιά χρησιμοποιώντας το ΑΡΙΣΤΕΡΟ σας χέρι."; +"TAPPING_SKIP_TITLE" = "Παράλειψη αυτού του χεριού"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Πλέγμα Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Αυτή η δραστηριότητα βοηθά στον εντοπισμό προβλημάτων στην όραση του χρήστη."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Κρατήστε τη συσκευή σε απόσταση 30 εκατοστών από το πρόσωπό σας στο ύψος των ματιών σας κατά τη διάρκεια του τεστ."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Κλείστε το %@ σας και κοιτάξτε την κουκκίδα στο κέντρο του τετράγωνου πλέγματος.\n\nΧρησιμοποιώντας το δάχτυλό σας ή τη γραφίδα, σημειώστε τυχόν παραμορφώσεις που βλέπετε, όπως π.χ. θαμπές ή κυματιστές γραμμές.\n\nΌταν τελειώσετε, σαρώστε προς τα αριστερά οπουδήποτε έξω από το πλέγμα."; +"AMSLER_GRID_LEFT_EYE" = "αριστερό μάτι"; +"AMSLER_GRID_RIGHT_EYE" = "δεξιό μάτι"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Φωνή"; +"AUDIO_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"AUDIO_INSTRUCTION" = "Πείτε «Ααααα» στο μικρόφωνο για όση περισσότερη ώρα μπορέσετε."; +"AUDIO_INTRO_TEXT" = "Πάρτε μια βαθιά ανάσα και πείτε «Ααααα» στο μικρόφωνο για όση περισσότερη ώρα μπορέσετε. Κρατήστε σταθερή την ένταση ήχου της φωνής σας για να παραμείνουν μπλε οι γραμμές ήχου."; +"AUDIO_INTENDED_USE" = "Αυτή η δραστηριότητα αξιολογεί τη φωνή σας μέσω της εγγραφής με το μικρόφωνο στο κάτω μέρος της συσκευής σας."; +"AUDIO_TOO_LOUD_LABEL" = "Πολύ δυνατά"; +"AUDIO_GENERIC_ERROR_LABEL" = "Δεν είναι δυνατή η εγγραφή ήχου"; +"AUDIO_LEVEL_CHECK_LABEL" = "Περιμένετε μέχρι να ελεγχθεί το επίπεδο θορύβου παρασκηνίου."; +"AUDIO_TOO_LOUD_MESSAGE" = "Το επίπεδο περιβαλλοντικού θορύβου είναι πολύ υψηλό για εγγραφή της φωνής σας. Πηγαίνετε σε έναν χώρο με λιγότερο θόρυβο και προσπαθήστε πάλι."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Αγγίξτε «Επόμενο» όταν είστε έτοιμοι."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Τονική ακοομετρία"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Αυτή η δραστηριότητα μετρά την ικανότητά σας να ακούτε διαφορετικούς ήχους."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Προτού ξεκινήσετε, συνδέστε και φορέστε τα ακουστικά κεφαλής.\n\nΟ ήχος θα είναι πολύ απαλός και δεν μοιάζει με τυπικό τόνο ειδοποίησης.  Η ένταση του ήχου θα ξεκινήσει σε χαμηλό επίπεδο και θα αυξάνεται αργά.  Δώστε προσοχή και αγγίξτε το αριστερό ή το δεξιό κουμπί για να υποδείξετε σε ποιο αυτί ακούτε τον ήχο."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Τώρα θα ακούσετε έναν τόνο. Προσαρμόστε την ένταση ήχου με τα χειριστήρια που βρίσκονται στην πλαϊνή πλευρά της συσκευής σας.\n\nΑγγίξτε οποιοδήποτε κουμπί όταν είστε έτοιμοι να ξεκινήσετε."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Κάθε φορά που ακούτε έναν ήχο, αγγίξτε το αριστερό ή το δεξιό κουμπί για να υποδείξετε σε ποιο αυτί ακούτε τον ήχο."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Αριστερό αυτί"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Δεξιό αυτί"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, αριστερά"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, δεξιά"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Τονική ακοομετρία"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Αγγίξτε όταν ακούσετε έναν τόνο."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Τόνος και ένταση ήχου"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Θα ακούσετε μια σειρά τόνων."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Όταν ακούσετε έναν τόνο, αγγίξτε το κουμπί."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Για αυτό το τεστ, η ένταση ήχου θα οριστεί στο 50 τοις εκατό."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Αυτό το τεστ διαρκεί περίπου 10 λεπτά."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Ενεργοποιήστε τη ρύθμιση «Μην ενοχλείτε» για να μη σας διακόψουν."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Πρώτα θα αναπαραχθούν τόνοι στο δεξιό αυτί σας."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Τώρα θα αναπαραχθούν τόνοι στο αριστερό αυτί σας."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Αυτή η δραστηριότητα εντοπίζει τα επίπεδα κατωφλίου ακοής ενός ατόμου σε κλίμακα επιπέδου ακοής dB."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Βεβαιωθείτε ότι η ένταση ήχου της συσκευής είναι στο μέγιστο επίπεδο.\n\nΚατά τη διάρκεια αυτής της δραστηριότητας, θα αναπαραχθεί ένας απαλός ήχος είτε στο αριστερό είτε στο δεξιό αυτί.\n\nΑκούστε προσεκτικά και αγγίξτε το κουμπί κάθε φορά που ακούτε έναν τόνο."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Αυτό το τεστ προσδιορίζει πόσο δυνατός πρέπει να είναι ένας ήχος για να τον ακούσετε."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Ερωτηματολόγιο συμμετοχής."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Επιλέξτε την προτίμηση σας για «καλύτερο αυτί», αν ισχύει"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "αριστερό"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "δεξιό"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "καμία προτίμηση"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Το τεστ ακυρώθηκε"; +"dBHL_ALERT_TITLE_START_OVER" = "Έναρξη εκ νέου"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Ακύρωση τεστ"; +"dBHL_ALERT_TEXT" = "Επανασυνδέστε τα AirPods ή EarPods για εκτέλεση αυτού του τεστ."; +"dBHL_PROGRESS_COMPLETION_%@" = "Έχει ολοκληρωθεί το %@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Ακουστικά"; +"HEADPHONES_UNKNOWN" = "Άγνωστο"; +"HEADPHONES_NONE" = "Κανένα"; +"CONNECTED" = "Συνδεδεμένο"; +"NOT_CONNECTED" = "Μη συνδεδεμένο"; +"HEADPHONE_CONNECTED_%@" = "Συνδέθηκε - %@"; +"HEADPHONE_DETECT_TITLE" = "Συνδέστε τα ακουστικά σας"; +"HEADPHONE_DETECT_TEXT" = "Για αυτό το τεστ, χρειάζεστε Apple AirPods ή Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Χωρική μνήμη"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Αυτή η δραστηριότητα αξιολογεί τη χωρική μνήμη σας ζητώντας σας να επαναλάβετε τη σειρά με την οποία φωτίζονται οι %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "εικόνες"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "εικόνες"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Κάποιες από τις %@ θα φωτίζονται μία-μία. Αγγίξτε αυτές τις %@ με την ίδια σειρά με αυτήν που φωτίστηκαν."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Κάποιες από τις %@ θα φωτίζονται μία-μία. Αγγίξτε αυτές τις %@ με σειρά αντίστροφη από αυτήν που φωτίστηκαν."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Για να αρχίσετε, αγγίξτε «Έναρξη» και μετά παρακολουθήστε προσεκτικά."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Βαθμολογία"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Δείτε τις %@ να φωτίζονται"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Αγγίξτε τις %@ με τη σειρά που επισημάνθηκαν"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Αγγίξτε τις %@ σε αντίστροφη σειρά"; +"MEMORY_GAME_COMPLETE_TITLE" = "Η ακολουθία ολοκληρώθηκε"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Για να συνεχίσετε, αγγίξτε «Επόμενο»"; +"MEMORY_GAME_FAILED_TITLE" = "Νέα δοκιμή"; +"MEMORY_GAME_FAILED_MESSAGE" = "Δεν τα καταφέρατε αυτήν τη φορά. Αγγίξτε «Επόμενο» για να συνεχίσετε."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Τέλος χρόνου"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Τελείωσε ο χρόνος.\nΑγγίξτε «Επόμενο» για να συνεχίσετε."; +"MEMORY_GAME_COMPLETE" = "Το παιχνίδι ολοκληρώθηκε"; +"MEMORY_GAME_PAUSED_TITLE" = "Σε παύση"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Για να συνεχίσετε, αγγίξτε «Επόμενο»"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Η δραστηριότητα μνήμης αναπτύχθηκε με τη βοήθεια της Katherine Possin, PhD και του Joel Kramer, PhD από το Πανεπιστήμιο της Καλιφόρνια, στο Σαν Φρανσίσκο."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Χρόνος αντίδρασης"; +"REACTION_TIME_TASK_INTENDED_USE" = "Αυτή η δραστηριότητα υπολογίζει τον χρόνο που χρειάζεστε για να αποκριθείτε σε μια οπτική ένδειξη."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Ανακινήστε τη συσκευή προς οποιαδήποτε κατεύθυνση αμέσως μόλις εμφανιστεί η μπλε κουκκίδα στην οθόνη. Θα σας ζητηθεί να το κάνετε αυτό %D φορές."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Απόπειρα %@ από %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Ανακινήστε γρήγορα τη συσκευή όταν εμφανιστεί ο μπλε κύκλος"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Κάθε φορά που εμφανίζεται μια λέξη, επιλέξτε τα πρώτα δύο γράμματα του ονόματος του ΧΡΩΜΑΤΟΣ που εμφανίζεται."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Όταν είστε έτοιμοι να ξεκινήσετε τη δραστηριότητα Stroop, αγγίξτε «Έναρξη»."; +"STROOP_TASK_STEP_TEXT" = "Επιλέξτε τα πρώτα δύο γράμματα του ονόματος του ΧΡΩΜΑΤΟΣ που εμφανίζεται."; +"STROOP_COLOR_RED" = "ΚΟΚΚΙΝΟ"; +"STROOP_COLOR_GREEN" = "ΠΡΑΣΙΝΟ"; +"STROOP_COLOR_BLUE" = "ΜΠΛΕ"; +"STROOP_COLOR_YELLOW" = "ΚΙΤΡΙΝΟ"; +"STROOP_COLOR_RED_INITIAL" = "ΚΟ"; +"STROOP_COLOR_GREEN_INITIAL" = "ΠΡ"; +"STROOP_COLOR_BLUE_INITIAL" = "ΜΠ"; +"STROOP_COLOR_YELLOW_INITIAL" = "ΚΙ"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Πύργος του Ανόι"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Αυτή η δραστηριότητα αξιολογεί τις ικανότητές σας ως προς την επίλυση παζλ."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Μετακινήστε ολόκληρη τη στοίβα στην επισημασμένη πλατφόρμα με όσο το δυνατό λιγότερες κινήσεις."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Επιλύστε το παζλ"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Αριθμός κινήσεων: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Δεν μπορώ να λύσω αυτό το παζλ"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Εύρος κίνησης"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Η ρύθμιση limbOption πρέπει να είναι αριστερό ή δεξιό"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Εύρος κίνησης αριστερού γόνατου"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Εύρος κίνησης δεξιού γόνατου"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Αυτή η δραστηριότητα μετρά πόσο πολύ μπορείτε να τεντώσετε το αριστερό σας γόνατο."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Αυτή η δραστηριότητα μετρά πόσο πολύ μπορείτε να τεντώσετε το δεξιό σας γόνατο."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Καθίστε στην άκρη μιας καρέκλας. Όταν ξεκινήσετε, θα τοποθετήσετε τη συσκευή στο αριστερό σας γόνατο για τη μέτρηση. Αυξήστε την ένταση ήχου στη συσκευή για να ακούσετε τις οδηγίες."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Καθίστε στην άκρη μιας καρέκλας. Όταν ξεκινήσετε, θα τοποθετήσετε τη συσκευή στο δεξιό σας γόνατο για τη μέτρηση. Αυξήστε την ένταση ήχου στη συσκευή για να ακούσετε τις οδηγίες."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Τοποθετήστε τη συσκευή στο αριστερό σας γόνατο με την οθόνη να κοιτά προς τα έξω, όπως φαίνεται στην εικόνα."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Τοποθετήστε τη συσκευή στο δεξιό σας γόνατο με την οθόνη να κοιτά προς τα έξω, όπως φαίνεται στην εικόνα."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Όταν είστε έτοιμοι, αγγίξτε την οθόνη για να ξεκινήσετε και εκτείνετε το αριστερό σας γόνατο όσο μπορείτε. Επιστρέψτε στην αρχική θέση και αγγίξτε πάλι όταν τελειώσετε."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Όταν είστε έτοιμοι, αγγίξτε την οθόνη για να ξεκινήσετε και εκτείνετε το δεξιό σας γόνατο όσο μπορείτε. Επιστρέψτε στην αρχική θέση και αγγίξτε πάλι όταν τελειώσετε."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Τοποθετήστε τη συσκευή στο αριστερό σας γόνατο. Αγγίξτε την οθόνη και εκτείνετε όσο μπορείτε το αριστερό σας γόνατο."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Τοποθετήστε τη συσκευή στο δεξιό σας γόνατο. Αγγίξτε την οθόνη και εκτείνετε όσο μπορείτε το δεξιό σας γόνατο."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Όταν τελειώσετε, επαναφέρετε το αριστερό σας γόνατο στην αρχική θέση. Μετά, αγγίξτε οπουδήποτε."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Όταν τελειώσετε, επαναφέρετε το δεξιό σας γόνατο στην αρχική θέση. Μετά, αγγίξτε οπουδήποτε."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Εύρος κίνησης αριστερού ώμου"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Εύρος κίνησης δεξιού ώμου"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Αυτή η δραστηριότητα μετρά πόσο πολύ μπορείτε να τεντώσετε τον αριστερό σας ώμο."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Αυτή η δραστηριότητα μετρά πόσο πολύ μπορείτε να τεντώσετε τον δεξιό σας ώμο."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Όταν ξεκινήσετε, θα τοποθετήσετε τη συσκευή στον αριστερό σας ώμο για τη μέτρηση. Αυξήστε την ένταση ήχου στη συσκευή για να ακούσετε τις οδηγίες."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Όταν ξεκινήσετε, θα τοποθετήσετε τη συσκευή στον δεξιό σας ώμο για τη μέτρηση. Αυξήστε την ένταση ήχου στη συσκευή για να ακούσετε τις οδηγίες."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Τοποθετήστε τη συσκευή στον αριστερό σας ώμο με την οθόνη να κοιτά προς τα έξω, όπως φαίνεται στην εικόνα."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Τοποθετήστε τη συσκευή στον δεξιό σας ώμο με την οθόνη να κοιτά προς τα έξω, όπως φαίνεται στην εικόνα."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Όταν είστε έτοιμοι, αγγίξτε την οθόνη για να ξεκινήσετε και σηκώστε το αριστερό χέρι σας όσο μπορείτε. Επιστρέψτε στην αρχική θέση και αγγίξτε πάλι όταν τελειώσετε."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Όταν είστε έτοιμοι, αγγίξτε την οθόνη για να ξεκινήσετε και σηκώστε το δεξιό χέρι σας όσο μπορείτε. Επιστρέψτε στην αρχική θέση και αγγίξτε πάλι όταν τελειώσετε."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Τοποθετήστε τη συσκευή στον αριστερό σας ώμο. Αγγίξτε την οθόνη και σηκώστε όσο μπορείτε το αριστερό χέρι σας προς τα εμπρός."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Τοποθετήστε τη συσκευή στον δεξιό σας ώμο. Αγγίξτε την οθόνη και σηκώστε όσο μπορείτε το δεξιό χέρι σας προς τα εμπρός."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Όταν τελειώσετε, επαναφέρετε το αριστερό χέρι σας στην αρχική θέση. Μετά, αγγίξτε οπουδήποτε."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Όταν τελειώσετε, επαναφέρετε το δεξιό χέρι σας στην αρχική θέση. Μετά, αγγίξτε οπουδήποτε."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Χρονισμένο περπάτημα"; +"TIMED_WALK_INTRO_DETAIL" = "Αυτή η δραστηριότητα αξιολογεί τη λειτουργία των κάτω άκρων σας."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Βρείτε ένα μέρος, κατά προτίμηση σε εξωτερικό χώρο, όπου μπορείτε να περπατήσετε για περίπου %@ σε ευθεία γραμμή όσο το δυνατόν πιο γρήγορα αλλά με ασφάλεια. Μη μειώσετε την ταχύτητά σας προτού περάσετε τη γραμμή τερματισμού."; +"TIMED_WALK_INTRO_2_DETAIL" = "Αγγίξτε «Επόμενο» για να ξεκινήσετε."; +"TIMED_WALK_FORM_TITLE" = "Βοηθητική συσκευή"; +"TIMED_WALK_FORM_TEXT" = "Χρησιμοποιήστε την ίδια βοηθητική συσκευή για κάθε τεστ."; +"TIMED_WALK_QUESTION_TEXT" = "Φοράτε νάρθηκα ποδοκνημικής;"; +"TIMED_WALK_QUESTION_2_TITLE" = "Χρησιμοποιείτε βοηθητική συσκευή;"; +"TIMED_WALK_QUESTION_2_TEXT" = "Αγγίξτε εδώ για επιλογή απάντησης"; +"TIMED_WALK_QUESTION_2_CHOICE" = "Όχι"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Μονόπλευρο μπαστούνι"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Μονόπλευρη πατερίτσα"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Δίπλευρο μπαστούνι"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Δίπλευρη πατερίτσα"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Περιπατητήρας"; +"TIMED_WALK_INSTRUCTION_%@" = "Περπατήστε έως %@ σε ευθεία γραμμή."; +"TIMED_WALK_INSTRUCTION_TURN" = "Κάντε αναστροφή."; +"TIMED_WALK_INSTRUCTION_2" = "Επιστρέψτε περπατώντας στο σημείο από όπου αρχίσατε."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Αγγίξτε «Επόμενο» όταν τελειώσετε."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Το τεστ PASAT (Βηματική ακουστική πρόσθεση αριθμών σε σειρά) αξιολογεί την ταχύτητα ακουστικής επεξεργασίας πληροφοριών και την ικανότητα υπολογισμών."; +"PVSAT_INTRO_TEXT" = "Το τεστ PVSAT (Βηματική οπτική πρόσθεση αριθμών σε σειρά) αξιολογεί την ταχύτητα οπτικής επεξεργασίας πληροφοριών και την ικανότητα υπολογισμών."; +"PAVSAT_INTRO_TEXT" = "Το τεστ PAVSAT (Βηματική ακουστική και οπτική πρόσθεση αριθμών σε σειρά) αξιολογεί την ταχύτητα ακουστικής και οπτικής επεξεργασίας πληροφοριών και την ικανότητα υπολογισμών."; +"PSAT_INTRO_TEXT_2_%@" = "Τα μονά ψηφία εμφανίζονται κάθε %@.\nΠρέπει να προσθέτετε κάθε νέο ψηφίο με το ακριβώς προηγούμενό του.\nΠροσοχή: Δεν πρέπει να υπολογίζετε το ολικό σύνολο, αλλά μόνο το σύνολο των τελευταίων δύο αριθμών."; +"PSAT_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"PSAT_INITIAL_INSTRUCTION" = "Θυμηθείτε αυτό το πρώτο ψηφίο."; +"PSAT_INSTRUCTION" = "Προσθέστε αυτό το νέο ψηφίο στο προηγούμενο ψηφίο."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Τεστ %@-HPT"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Αυτή η δραστηριότητα μετρά την επιδεξιότητα των άνω άκρων σας ζητώντας σας να τοποθετήσετε έναν κύκλο σε μια οπή. Αυτό θα σας ζητηθεί να το κάνετε %@ φορές."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Θα ελεγχθούν και το αριστερό και το δεξιό σας χέρι.\nΠρέπει να πιάσετε τον κύκλο όσο το δυνατόν πιο γρήγορα, να τον τοποθετήσετε στην οπή και, όταν το κάνετε αυτό %@ φορές, να τον αφαιρέσετε από την οπή %@ φορές."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Θα ελεγχθούν και το δεξιό και το αριστερό σας χέρι.\nΠρέπει να πιάσετε τον κύκλο όσο το δυνατόν πιο γρήγορα, να τον τοποθετήσετε στην οπή και, όταν το κάνετε αυτό %@ φορές, να τον αφαιρέσετε από την οπή %@ φορές."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Τοποθετήστε τον κύκλο στην οπή με το αριστερό χέρι σας."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Τοποθετήστε τον κύκλο στην οπή με το δεξιό χέρι σας."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Τοποθετήστε τον κύκλο πίσω από τη γραμμή με το αριστερό χέρι σας."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Τοποθετήστε τον κύκλο πίσω από τη γραμμή με το δεξιό χέρι σας."; +"HOLE_PEG_TEST_TEXT" = "Σηκώστε τον κύκλο με δύο δάχτυλα."; +"HOLE_PEG_TEST_TEXT_2" = "Σηκώστε τα δάχτυλα για να αφήσετε τον κύκλο."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Δραστηριότητα τρέμουλου"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Αυτή η δραστηριότητα μετρά το τρέμουλο των χεριών σας σε διάφορες θέσεις. Βρείτε ένα σημείο όπου μπορείτε να κάθεστε άνετα καθ' όλη τη διάρκεια της δραστηριότητας."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Κρατήστε το τηλέφωνο στο πιο επηρεαζόμενο χέρι σας όπως φαίνεται στην παρακάτω εικόνα."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Κρατήστε το τηλέφωνο στο ΔΕΞΙΟ χέρι σας όπως φαίνεται στην παρακάτω εικόνα."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Κρατήστε το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι σας όπως φαίνεται στην παρακάτω εικόνα."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Θα σας ζητηθεί να εκτελέσετε %@ σε θέση καθίσματος με το τηλέφωνο στο χέρι σας."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "μια εργασία"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "δύο εργασίες"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "τρεις εργασίες"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "τέσσερις εργασίες"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "πέντε εργασίες"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Αγγίξτε «Επόμενο» για να συνεχίσετε."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Προετοιμαστείτε να κρατήσετε το τηλέφωνο πάνω στα πόδια σας."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Προετοιμαστείτε να κρατήσετε το τηλέφωνο πάνω στα πόδια σας με το ΑΡΙΣΤΕΡΟ χέρι."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Προετοιμαστείτε να κρατήσετε το τηλέφωνο πάνω στα πόδια σας με το ΔΕΞΙΟ χέρι."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Συνεχίστε να κρατάτε το τηλέφωνο πάνω στα πόδια σας για %ld δευτερόλεπτα."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Τώρα κρατήστε το τηλέφωνο στο χέρι σας τεντωμένο στο ύψος του ώμου."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Τώρα κρατήστε το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι τεντωμένο στο ύψος του ώμου."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Τώρα κρατήστε το τηλέφωνο στο ΔΕΞΙΟ χέρι τεντωμένο στο ύψος του ώμου."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Συνεχίστε να κρατάτε το τηλέφωνο με το τεντωμένο χέρι σας για %ld δευτερόλεπτα."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Τώρα κρατήστε το τηλέφωνο στο ύψος του ώμου με τον αγκώνα λυγισμένο."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Τώρα κρατήστε το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι τεντωμένο στο ύψος του ώμου με τον αγκώνα λυγισμένο."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Τώρα κρατήστε το τηλέφωνο στο ΔΕΞΙΟ χέρι τεντωμένο στο ύψος του ώμου με τον αγκώνα λυγισμένο."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Συνεχίστε να κρατάτε το τηλέφωνο με λυγισμένο τον αγκώνα για %ld δευτερόλεπτα."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Κρατώντας τον αγκώνα σας λυγισμένο, αγγίξτε τη μύτη σας με το τηλέφωνο επανειλημμένα."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Κρατώντας τον αγκώνα σας λυγισμένο με το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι σας, αγγίξτε τη μύτη σας με το τηλέφωνο επανειλημμένα."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Κρατώντας τον αγκώνα σας λυγισμένο με το τηλέφωνο στο ΔΕΞΙΟ χέρι σας, αγγίξτε τη μύτη σας με το τηλέφωνο επανειλημμένα."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Συνεχίστε να ακουμπάτε τη μύτη σας με το τηλέφωνο για %ld δευτερόλεπτα."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Προετοιμαστείτε να κάνετε έναν βασιλικό χαιρετισμό (κουνώντας τον καρπό)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Προετοιμαστείτε να κάνετε έναν βασιλικό χαιρετισμό (κουνώντας τον καρπό) με το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι σας."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Προετοιμαστείτε να κάνετε έναν βασιλικό χαιρετισμό (κουνώντας τον καρπό) με το τηλέφωνο στο ΔΕΞΙΟ χέρι σας."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Συνεχίστε να χαιρετάτε με αυτόν τον τρόπο για %ld δευτερόλεπτα."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Τώρα κρατήστε το τηλέφωνο στο ΑΡΙΣΤΕΡΟ χέρι σας και συνεχίστε στην επόμενη εργασία."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Τώρα κρατήστε το τηλέφωνο στο ΔΕΞΙΟ χέρι σας και συνεχίστε στην επόμενη εργασία."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Συνεχίστε στην επόμενη εργασία."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Η δραστηριότητα ολοκληρώθηκε."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Θα σας ζητηθεί να εκτελέσετε %@ σε θέση καθίσματος με το τηλέφωνο πρώτα στο ένα χέρι και μετά στο άλλο."; +"TREMOR_SKIP_LEFT_HAND" = "Δεν μπορώ να εκτελέσω αυτήν τη δραστηριότητα με το ΑΡΙΣΤΕΡΟ χέρι μου."; +"TREMOR_SKIP_RIGHT_HAND" = "Δεν μπορώ να εκτελέσω αυτήν τη δραστηριότητα με το ΔΕΞΙΟ χέρι μου."; +"TREMOR_SKIP_NEITHER" = "Μπορώ να εκτελέσω αυτήν τη δραστηριότητα και με τα δύο χέρια."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Τεστ δημιουργίας διαδρομής"; +"TRAILMAKING_INTENDED_USE" = "Αυτή η δραστηριότητα αξιολογεί την οπτική προσοχή σας και την ικανότητα αλλαγής εργασιών, εγγράφοντας τον χρόνο που χρειάζεστε για να αγγίξετε κάποιες κουκκίδες στη σειρά."; +"TRAILMAKING_INTENDED_USE2_A" = "Μετά την αντίστροφη μέτρηση, αγγίξτε κουκκίδες σε εναλλάξ σειρά μεταξύ αριθμών και γραμμάτων. Ξεκινήστε αγγίζοντας τον πρώτο αριθμό «1» και μετά τους αριθμούς «2» – «3» – «4»… μέχρι να φτάσετε στον αριθμό «7»."; +"TRAILMAKING_INTENDED_USE2_B" = "Μετά την αντίστροφη μέτρηση, αγγίξτε κουκκίδες σε εναλλάξ σειρά μεταξύ αριθμών και γραμμάτων. Ξεκινήστε αγγίζοντας τον πρώτο αριθμό «1», μετά το πρώτο γράμμα «Α», και στη συνέχεια «2» – «Β» – «3» – «Γ»… μέχρι να φτάσετε στον αριθμό «7»."; +"TRAILMAKING_INTRO_TEXT" = "Κάντε αυτήν τη δραστηριότητα όσο πιο γρήγορα μπορείτε χωρίς να κάνετε λάθη. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"TRAILMAKING_LETTER_A" = "Α"; +"TRAILMAKING_LETTER_B" = "Β"; +"TRAILMAKING_LETTER_C" = "Γ"; +"TRAILMAKING_LETTER_D" = "Δ"; +"TRAILMAKING_LETTER_E" = "Ε"; +"TRAILMAKING_LETTER_F" = "Ζ"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Αναγνώριση ομιλίας"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Αυτή η δραστηριότητα εγγράφει την ομιλία σας με το μικρόφωνο στο κάτω μέρος της συσκευής και μετά τη μετατρέπει σε κείμενο."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Αγγίξτε «Έναρξη» για να αρχίσετε."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Πατήστε το κουμπί για έναρξη της εγγραφής προτού μιλήσετε."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Έναρξη εγγραφής"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Διακοπή εγγραφής"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Επεξεργασία κειμένου απομαγνητοφώνησης"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Επεξεργαστείτε το κείμενο απομαγνητοφώνησης για να διορθώσετε τυχόν εσφαλμένες ερμηνείες της ομιλίας."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Το κείμενο απομαγνητοφώνησης θα εμφανιστεί εδώ."; +"SPEECH_RECOGNITION_FAILED" = "Απέτυχε η αναγνώριση ομιλίας."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Απέτυχε η αρχικοποίηση της αναγνώρισης ομιλίας."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Αναπαραγωγή ήχου"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Διακοπή ήχου"; +"SPEECH_IN_NOISE_TITLE" = "Ομιλία σε θόρυβο"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Αυτή η δραστηριότητα μετρά την αντιληπτότητα της ομιλίας σε θορυβώδη περιβάλλοντα."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Ως μέρος αυτού του τεστ, θα κάνετε τα εξής:\n\nΘα ακούσετε μια πρόταση.\n\nΘα επαναλάβετε ξεκάθαρα τι ακούσατε ή θα μεταβείτε παρακάτω ώστε να πληκτρολογήσετε τι ακούσατε με το πληκτρολόγιο. \n\nΑν επαναλάβετε αυτό που ακούσατε, θα έχετε την επιλογή να τροποποιήσετε το κείμενο απομαγνητοφώνησης που θα δημιουργήσει η μηχανή αναγνώρισης ομιλίας."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Διακρίβωση έντασης ήχου"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Αγγίξτε «Αναπαραγωγή ήχου», προσαρμόστε τον ήχο σε άνετο επίπεδο και μετά αγγίξτε «Διακοπή ήχου» για να συνεχίσετε."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Ακρόαση"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Θα αναπαραχθεί μόνο μία φορά μια πρόταση μαζί με θόρυβο στο παρασκήνιο σε τυχαιοποιημένο SNR (λόγος σήματος προς θόρυβο)."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Ομιλία"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Επαναλάβετε αυτά που ακούσατε"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Δεν ήταν δυνατή η δημιουργία αρχείου"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Δεν ήταν δυνατή η αφαίρεση επαρκών αρχείων καταγραφής για την επίτευξη ορίου"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Σφάλμα κατά τον καθορισμό χαρακτηριστικού"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Το αρχείο δεν έχει σημανθεί ως διαγραμμένο (δεν έχει σημανθεί ως απεσταλμένο)"; +"ERROR_DATALOGGER_MULTIPLE" = "Πολλαπλά σφάλματα κατά την αφαίρεση αρχείων καταγραφής"; +"ERROR_RECORDER_NO_DATA" = "Δεν βρέθηκαν συλλεγμένα δεδομένα."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Δεν έχει καθοριστεί κατάλογος εξόδου"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Μετρητής επιπέδου πίεσης ήχου (SPL)"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Αυτή η δραστηριότητα μετρά το επίπεδο πίεσης του περιβαλλοντικού θορύβου. Αν τα επίπεδα θορύβου είναι πολύ υψηλά, δεν θα είναι δυνατό να συνεχίσετε. Πηγαίνετε σε πιο ήσυχη τοποθεσία για να ολοκληρώσετε αυτήν τη δραστηριότητα ή πραγματοποιήστε την εκ νέου αργότερα."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Υπολογισμός…"; +"ENVIRONMENTSPL_THRESHOLD" = "Όριο: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Θόρυβος παρασκηνίου ΟΚ"; +"ENVIRONMENTSPL_NOISE" = "Υπερβολικός θόρυβος παρασκηνίου"; +"ENVIRONMENTSPL_TITLE_2" = "Βρείτε ένα ήσυχο μέρος"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Για διασφάλιση της ακρίβειας, αυτό το τεστ πρέπει να διεξαχθεί σε ήσυχο περιβάλλον."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Έναρξη εργασίας"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Δεν υπάρχουν δεδομένα"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Μετακινήστε το ρυθμιστικό για εισαγωγή τιμής"; +"SLIDER_I_DONT_KNOW" = "Δεν γνωρίζω"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Σελίδα"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Πίσω"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Εμφάνιση μικρογραφίας PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Απόκρυψη μικρογραφίας PDF"; +"AX_BUTTON_ANNOTATE" = "Σχολιασμός"; +"AX_BUTTON_SHOW_SEARCH" = "Εμφάνιση γραμμής αναζήτησης"; +"AX_BUTTON_HIDE_SEARCH" = "Απόκρυψη γραμμής αναζήτησης"; +"AX_BUTTON_SHARE" = "Κοινή χρήση"; + + +"AX_COMPLETION_ILLUSTRATION" = "Εικόνα σημαδιού επιλογής σε ένα μπλε κύκλο που υποδεικνύει επιτυχία"; + +"AX_SIGNVIEW_LABEL" = "Καθορισμένο πεδίο υπογραφής"; +"AX_SIGNVIEW_HINT" = "Αγγίξτε την οθόνη και μετακινήστε το δάχτυλό σας για υπογραφή"; +"AX_SIGNVIEW_SIGNED" = "Υπογεγραμμένο"; +"AX_SIGNVIEW_UNSIGNED" = "Ανυπόγραφο"; + +"AX_SELECTED" = "Επιλεγμένο"; +"AX_UNSELECTED" = "Μη επιλεγμένο"; +"AX_SELECT_ALL_THAT_APPLY" = "ΕΠΙΛΕΞΤΕ ΟΛΑ ΟΣΑ ΙΣΧΥΟΥΝ"; + +"AX_SLIDER_LABEL" = "Ρυθμιστικό απάντησης. Εύρος από %@ έως %@"; +"AX_UNLABELED_IMAGE" = "Εικόνα χωρίς ετικέτα"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Έναρξη εργασίας"; + +"AX.MEMORY.TILE.ACTIVE" = "ενεργό"; +"AX.MEMORY.TILE.CORRECT" = "σωστό"; +"AX.MEMORY.TILE.INCORRECT" = "λάθος"; +"AX.MEMORY.TILE.QUIESCENT" = "αδρανές"; +"AX.MEMORY.TILE.LABEL" = "Πλακίδιο παιχνιδιού μνήμης"; + +"AX_IMAGE_CAPTURE_LABEL" = "Προεπισκόπηση καταγραφής"; +"AX_IMAGE_CAPTURED_LABEL" = "Καταγραμμένη εικόνα"; + +"AX_VIDEO_CAPTURE_LABEL" = "Προεπισκόπηση καταγραφής βίντεο"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Ολοκληρώθηκε η καταγραφή βίντεο"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Δεν είναι δυνατή η τοποθέτηση δίσκου μεγέθους %@ πάνω σε δίσκο μεγέθους %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Στόχος"; +"AX_TOWER_OF_HANOI_TOWER" = "Πύργος"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Αγγίξτε δύο φορές για τοποθέτηση του δίσκου"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Αγγίξτε δύο φορές για επιλογή του ανώτερου δίσκου"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Έχει δίσκο με μεγέθη %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Κενός"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Απόρριψη πληκτρολογίου"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Εύρος από %@ έως %@"; +"AX_GRAPH_STACK_PREFIX" = "Η στοίβα αποτελείται από"; +"AX_GRAPH_AND_SEPARATOR" = " και "; +"AX_GRAPH_POINT_%@" = "Σημείο: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Κυματομορφή ομιλίας"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Όταν ξεκινήσει η εγγραφή, ενεργοποιήστε πάλι για διακοπή της εγγραφής."; + +"AX_AUDIO_BAR_GRAPH" = "Γράφημα ράβδων ήχου"; + +"AX_AMSLER_GRID_LABEL" = "Πλέγμα Amsler"; +"AX_AMSLER_GRID_HINT" = "Χρησιμοποιήστε το δάχτυλό σας ή τη γραφίδα για να σημειώσετε απευθείας πάνω στο πλέγμα, ή σαρώστε προς τα αριστερά έξω από το πλέγμα για ολοκλήρωση."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Κουμπιά με δυνατότητα αγγίγματος"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Αγγίξτε για αριστερό αυτί"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Ενεργοποιήστε για έναρξη του τεστ. Όταν ξεκινήσει το τεστ, αγγίξτε απευθείας αυτό το κουμπί όταν ακούσετε έναν ήχο στο αριστερό αυτί σας."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Αγγίξτε για δεξιό αυτί"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Ενεργοποιήστε για έναρξη του τεστ. Όταν ξεκινήσει το τεστ, αγγίξτε απευθείας αυτό το κουμπί όταν ακούσετε έναν ήχο στο δεξιό αυτί σας."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Χρησιμοποιώντας το VoiceOver, εξερευνήστε την οθόνη με αφή για να μάθετε πού βρίσκονται τα κουμπιά για κάθε αυτί. Όταν ξεκινήσει το τεστ, θα είναι δυνατό το απευθείας άγγιγμα στα κουμπιά. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Αγγίξτε για ένα δάχτυλο"; +"AX_TAP_BUTTON_2_LABEL" = "Αγγίξτε για άλλο δάχτυλο"; +"AX_TAP_BUTTON_HINT" = "Ενεργοποιήστε για να είναι δυνατό το απευθείας άγγιγμα στα κουμπιά."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Χρησιμοποιώντας το VoiceOver, εξερευνήστε την οθόνη με αφή για να μάθετε πού βρίσκονται τα κουμπιά για κάθε αυτί. Ενεργοποιήστε οποιοδήποτε κουμπί ώστε να είναι δυνατό το απευθείας άγγιγμα στα κουμπιά."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Μπορείτε πλέον να αγγίζετε τα κουμπιά απευθείας."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Με χρήση του VoiceOver, θα είναι δυνατό το απευθείας άγγιγμα στο κουμπί, το οποίο θα βρίσκεται κοντά στο κέντρο της οθόνης."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Με τη χρήση του VoiceOver, θα είναι δυνατό το απευθείας άγγιγμα στα κουμπιά του τεστ."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Δεν είναι δυνατή η αποκωδικοποίηση του restoreData για αρχικοποίηση"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7f0c9a1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/el.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d σφάλμα) + other + (%d σφάλματα) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.strings new file mode 100755 index 0000000..f69b78f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.strings @@ -0,0 +1,719 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consent"; +"CONSENT_NAME_GIVEN" = "First Name"; +"CONSENT_NAME_FAMILY" = "Last Name"; +"CONSENT_NAME_PLACEHOLDER" = "Required"; +"CONSENT_REVIEW_TITLE" = "Review"; +"CONSENT_REVIEW_INSTRUCTION" = "Review the form below, and tap Agree if you’re ready to continue."; +"CONSENT_REVIEW_ALERT_TITLE" = "Review"; +"CONSENT_SIGNATURE_TITLE" = "Signature"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Please sign using your finger in the box below."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Sign Here"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Page %1$ld of %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Welcome"; +"CONSENT_SECTION_DATA_GATHERING" = "Data Gathering"; +"CONSENT_SECTION_PRIVACY" = "Privacy"; +"CONSENT_SECTION_DATA_USE" = "Data Use"; +"CONSENT_SECTION_STUDY_SURVEY" = "Study Survey"; +"CONSENT_SECTION_STUDY_TASKS" = "Study Tasks"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Time Commitment"; +"CONSENT_SECTION_WITHDRAWING" = "Withdrawing"; +"CONSENT_LEARN_MORE_TITLE" = "Learn More"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Learn more about how data is gathered"; +"LEARN_MORE_DATA_USE" = "Learn more about how data is used"; +"LEARN_MORE_PRIVACY" = "Learn more about how your privacy and identity are protected"; +"LEARN_MORE_WELCOME" = "Learn more about the study first"; +"LEARN_MORE_STUDY_SURVEY" = "Learn more about the study survey"; +"LEARN_MORE_TIME_COMMITMENT" = "Learn more about the study’s impact on your time"; +"LEARN_MORE_TASKS" = "Learn more about the tasks involved"; +"LEARN_MORE_WITHDRAWING" = "Learn more about withdrawing"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Sharing Options"; +"CONSENT_SHARE_WIDELY_%@" = "Share my data with %@ and qualified researchers worldwide"; +"CONSENT_SHARE_ONLY_%@" = "Only share my data with %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ will receive your study data from your participation in this study.\n\nSharing your coded study data more broadly (without information such as your name) may benefit this and future research."; +"LEARN_MORE_CONSENT_SHARING" = "Learn more about data sharing"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Printed Name"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signature"; +"CONSENT_DOC_LINE_DATE" = "Date"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ of %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Question %1$@ of %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Skipped"; +"REVIEW_EDIT_ANSWER" = "Edit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Invalid value"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ exceeds the maximum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ is less than the minimum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ is not a valid value."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Invalid email address: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Enter an address"; +"LOCATION_ERROR_TITLE" = "Could not Find Specified Address"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Unable to resolve your current location. Please type in an address or move to a location with better GPS signal if applicable."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Access to location services has been denied. Please grant this app permission to use location services through Settings."; +"LOCATION_ERROR_GEOCODE" = "Unable to find a result for the entered address. Please make sure the address is valid."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Either you are not connected to the internet or you have exceeded the maximum amount of address lookup requests. If you are not connected to the internet, please turn on your Wi-Fi to answer this question, skip this question if skip button is available, or come back to the survey when you are connected to the internet. Otherwise, please try again in a few minutes."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Text content exceeding maximum length: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera not available in split screen."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Password"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirm"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password again"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Passwords do not match."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Additional Information"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Gender"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Pick a gender"; +"DOB_FORM_ITEM_TITLE" = "Date of Birth"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Pick a date"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Phone Number"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verification"; +"VERIFICATION_STEP_TITLE" = "Verify your Email"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tap on the link below if you did not receive a verification email and would like it sent again."; +"RESEND_EMAIL_BUTTON_TITLE" = "Resend Verification Email"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Login"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Forgot password?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Enter passcode"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirm passcode"; +"PASSCODE_SAVED_MESSAGE" = "Passcode saved"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Passcode authenticated"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Enter your old passcode"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Enter your new passcode"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirm your new passcode"; +"PASSCODE_INVALID_ALERT_TITLE" = "Passcode Incorrect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Passcodes did not match. Try again."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Please authenticate with Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID error"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Only numeric characters allowed."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Passcode entry progress indicator"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ of %@ digits entered"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Forgot Passcode?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Could not add Keychain item."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Could not update Keychain item."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Could not delete Keychain item."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Could not find Keychain item."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Female"; +"GENDER_MALE" = "Male"; +"GENDER_OTHER" = "Other"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Yes"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "left"; +"LIMB_RIGHT" = "right"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tap to answer"; +"NULL_ANSWER" = "Select an answer"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tap to select"; +"PLACEHOLDER_LONG_TEXT" = "Tap to write"; + +/* Button titles */ +"BUTTON_AGREE" = "Agree"; +"BUTTON_CANCEL" = "Cancel"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Clear"; +"BUTTON_CLEAR_SIGNATURE" = "Clear Signature"; +"BUTTON_APPLY" = "Apply"; +"BUTTON_DISAGREE" = "Disagree"; +"BUTTON_DONE" = "Done"; +"BUTTON_GET_STARTED" = "Get Started"; +"BUTTON_LEARN_MORE" = "Learn more"; +"BUTTON_NEXT" = "Next"; +"BUTTON_SKIP" = "Skip"; +"BUTTON_SKIP_QUESTION" = "Skip this question"; +"BUTTON_START_TIMER" = "Start Timer"; +"BUTTON_OPTION_SAVE" = "Save for Later"; +"BUTTON_OPTION_DISCARD" = "Discard Results"; +"BUTTON_OPTION_STOP_TASK" = "End Task"; +"BUTTON_SAVE" = "Save"; +"BUTTON_CLEAR_ANSWER" = "Clear answer"; +"BUTTON_READ_ONLY_MODE" = "This answer cannot be modified."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Close"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Starting activity in"; +"TASK_COMPLETE_TITLE" = "Activity Complete"; +"TASK_COMPLETE_TEXT" = "Your data will be analyzed and you will be notified when your results are ready."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ remaining."; +"TOUCH_ANYWHERE_LABEL" = "Touch anywhere to continue"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capture Image"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapture Image"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No camera found. This step cannot be completed."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "In order to complete this step, allow this app access to the camera in Settings."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No output directory was specified for captured images."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "The captured image could not be saved."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start Recording"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stop Recording"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapture Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Heart Rate (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sit comfortably for %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Walk as fast as you can for %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "This activity monitors your heart rate and measures how far you can walk in %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Walk outdoors at your fastest possible pace for %1$@. When you’re done, sit and rest comfortably for %2$@. To begin, tap Get Started."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gait and Balance"; +"WALK_INTRO_TEXT" = "This activity measures your gait and balance as you walk and stand still. Do not continue if you cannot safely walk unassisted."; +"WALK_INTRO_2_TEXT_%ld" = "Find a place where you can safely walk unassisted for about %ld steps in a straight line."; +"WALK_INTRO_2_DETAIL" = "Put your device in a pocket or bag and follow the audio instructions."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Now stand still for %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stand still for %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Turn around, and walk back to where you started."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Walk up to %ld steps in a straight line."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Find a place where you can safely walk back and forth in a straight line. Try to walk continuously by turning at the ends of your path, as if you are walking around a cone.\n\nNext you will be instructed to turn around in a full circle, then stand still with your arms at your sides and your feet about shoulder-width apart."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tap Get Started when you are ready to begin.\nThen place your device in a pocket or bag and follow the audio instructions."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Walk back and forth in a straight line for %@. Walk as you would normally."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Turn in a full circle and then stand still for %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "You have completed the activity."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tapping Speed"; +"TAPPING_TASK_TITLE_RIGHT" = "Right Hand"; +"TAPPING_TASK_TITLE_LEFT" = "Left Hand"; +"TAPPING_INTRO_TEXT" = "This activity measures your tapping speed."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Put your device on a flat surface."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Use two fingers on the same hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Use two fingers on your right hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Use two fingers on your left hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Now repeat the same test using your right hand."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Now repeat the same test using your left hand."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for %@."; +"TAPPING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tap Next to begin."; +"TAP_BUTTON_TITLE" = "Tap"; +"TOTAL_TAPS_LABEL" = "Total Taps"; +"TAPPING_INSTRUCTION" = "Tap the buttons as consistently as you can using two fingers."; +"TAPPING_INSTRUCTION_RIGHT" = "Tap the buttons using your RIGHT hand."; +"TAPPING_INSTRUCTION_LEFT" = "Tap the buttons using your LEFT hand."; +"TAPPING_SKIP_TITLE" = "Skip this hand"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler Grid"; +"AMSLER_GRID_INTRO_TEXT" = "This activity helps in detecting problems in user’s vision."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Hold the device 12 inches from your face and at eye level throughout the test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Close your %@ and stare at the dot in the center of the square grid.\n\nUsing your finger or stylus, mark any distortions you see such as blurred or wavy lines.\n\nWhen you are done, swipe left anywhere outside the grid."; +"AMSLER_GRID_LEFT_EYE" = "Left Eye"; +"AMSLER_GRID_RIGHT_EYE" = "Right Eye"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voice"; +"AUDIO_CALL_TO_ACTION" = "Tap Get Started to begin."; +"AUDIO_INSTRUCTION" = "Say “Aaaaah” into the microphone for as long as you can."; +"AUDIO_INTRO_TEXT" = "Take a deep breath and say “Aaaaah” into the microphone for as long as you can. Keep a steady vocal volume so the audio bars remain blue."; +"AUDIO_INTENDED_USE" = "This activity evaluates your voice by recording it with the microphone at the bottom of your device."; +"AUDIO_TOO_LOUD_LABEL" = "Too Loud"; +"AUDIO_GENERIC_ERROR_LABEL" = "Unable to record audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Please wait while we check the background noise level."; +"AUDIO_TOO_LOUD_MESSAGE" = "The ambient noise level is too loud to record your voice. Please move somewhere quieter and try again."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tap Next when ready."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"TONE_AUDIOMETRY_INTENDED_USE" = "This activity measures your ability to hear different sounds."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Before you begin, plug in and put your headphones on.\n\nThe sound will be very subtle and is unlike a regular alert tone.  The sound will begin soft and then slowly increase in volume.  Please pay attention and tap the left or right button to indicate which ear you hear it in."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TONE_AUDIOMETRY_PREP_TEXT" = "You should now hear a tone. Adjust the volume using the controls on the side of your device.\n\nTap any button when you are ready to begin."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Every time you start hearing a sound, tap the left or right button to indicate which ear you hear the sound in."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Left Ear"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Right Ear"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Left"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Right"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tap when you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tone & Volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "You will hear a series of tones."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "When you hear a tone, tap on the button."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "For this test, volume will be set to 50 percent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "This test takes about 10 minutes."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Turn on Do Not Disturb to avoid interruptions."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Tones will play in your right ear first."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Tones will now play in your left ear."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "This activity identifies hearing threshold levels of an individual in dB HL scale."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Make sure the device volume is set to the maximum level.\n\nDuring this task, a subtle tone will play in either the left or right ear.\n\nListen carefully and tap the button every time you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "This test identifies how loud a sound needs to be in order for you to hear it."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Onboarding questionnaire."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Select your preference for ‘better ear’, if any"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "left"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "right"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "no preference"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test Cancelled"; +"dBHL_ALERT_TITLE_START_OVER" = "Start Again"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancel Test"; +"dBHL_ALERT_TEXT" = "Reconnect your AirPods or EarPods to take this test."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Complete"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Headphones"; +"HEADPHONES_UNKNOWN" = "Unknown"; +"HEADPHONES_NONE" = "None"; +"CONNECTED" = "Connected"; +"NOT_CONNECTED" = "Not Connected"; +"HEADPHONE_CONNECTED_%@" = "Connected - %@"; +"HEADPHONE_DETECT_TITLE" = "Connect your Headphones"; +"HEADPHONE_DETECT_TEXT" = "This test requires Apple AirPods or Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Spatial Memory"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "This activity measures your short-term spatial memory by asking you to repeat the order in which %@ light up."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flowers"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flowers"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the same order they lit up."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the reverse of the order they lit up."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "To begin, tap Get Started, then watch closely."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Score"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Watch the %@ light up"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tap the %@ in the order they lit up"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tap the %@ in reverse order"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequence Complete"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_FAILED_TITLE" = "Try Again"; +"MEMORY_GAME_FAILED_MESSAGE" = "You didn’t quite make it through that time. Tap Next to continue."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Time’s Up"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "You ran out of time.\nTap Next to continue."; +"MEMORY_GAME_COMPLETE" = "Game Complete"; +"MEMORY_GAME_PAUSED_TITLE" = "Paused"; +"MEMORY_GAME_PAUSED_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "The memory activity was developed with assistance from Katherine Possin, PhD and Joel Kramer, PhD from University of California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaction Time"; +"REACTION_TIME_TASK_INTENDED_USE" = "This activity evaluates the time it takes for you to respond to a visual cue."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Shake the device in any direction as soon as the blue dot appears on screen. You will be asked to do this %D times."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Attempt %@ of %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Quickly shake the device when the blue circle appears"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Every time a word appears, select the first letter of the name of the COLOR that is shown."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "When you are ready to begin the Stroop activity tap Get Started."; +"STROOP_TASK_STEP_TEXT" = "Select the first letter of the name of the COLOR that is shown."; +"STROOP_COLOR_RED" = "RED"; +"STROOP_COLOR_GREEN" = "GREEN"; +"STROOP_COLOR_BLUE" = "BLUE"; +"STROOP_COLOR_YELLOW" = "YELLOW"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "G"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Y"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tower of Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "This activity evaluates your puzzle solving skills."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Move the entire stack to the highlighted platform in as few moves as possible."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Solve the Puzzle"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Number of Moves: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "I cannot solve this puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Range of Motion"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption must be left or right"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Left Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sit down on the edge of a chair. When you begin you will put your device on your left knee for a measurement. Please turn the sound on your device on so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sit down on the edge of a chair. When you begin you will put your device on your right knee for a measurement. Please turn the sound on your device on so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and extend your left knee as far as you can. Return to the start position and tap again when you are done."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and extend your right knee as far as you can. Return to the start position and tap again when you are done."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left knee. Tap the screen and extend your left knee as far as you can."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right knee. Tap the screen and extend your right knee as far as you can."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you are done, return your left knee to the start position. Then tap anywhere."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you are done, return your right knee to the start position. Then tap anywhere."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Left Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "When you begin you will put your device on your left shoulder for a measurement. Please turn the sound on your device on so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "When you begin you will put your device on your right shoulder for a measurement. Please turn the sound on your device on so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and raise your left arm as far as you can. Return to the start position and tap again when you are done."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and raise your right arm as far as you can. Return to the start position and tap again when you are done."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left shoulder. Tap the screen and raise your left arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right shoulder. Tap the screen and raise your right arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you are done, return your left arm to the start position. Then tap anywhere."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you are done, return your right arm to the start position. Then tap anywhere."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Timed Walk"; +"TIMED_WALK_INTRO_DETAIL" = "This activity measures your lower extremity function."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Find a place, preferably outside, where you can walk for about %@ in a straight line as quickly as possible, but safely. Do not slow down until after you’ve passed the finish line."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tap Next to begin."; +"TIMED_WALK_FORM_TITLE" = "Assistive device"; +"TIMED_WALK_FORM_TEXT" = "Use the same assistive device for each test."; +"TIMED_WALK_QUESTION_TEXT" = "Do you wear an ankle foot orthosis?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Do you use assistive device?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tap here to select an answer."; +"TIMED_WALK_QUESTION_2_CHOICE" = "None"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Unilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Unilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Bilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Walker/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Walk up to %@ in a straight line."; +"TIMED_WALK_INSTRUCTION_TURN" = "Turn around."; +"TIMED_WALK_INSTRUCTION_2" = "Walk back to where you started."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tap Next when complete."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "The Paced Auditory Serial Addition Test measures your auditory information processing speed and calculation ability."; +"PVSAT_INTRO_TEXT" = "The Paced Visual Serial Addition Test measures your visual information processing speed and calculation ability."; +"PAVSAT_INTRO_TEXT" = "The Paced Auditory and Visual Serial Addition Test measures your auditory and visual information processing speed and calculation ability."; +"PSAT_INTRO_TEXT_2_%@" = "Single digits are presented every %@.\nYou must add each new digit to the one immediately prior to it.\nAttention, you mustn’t calculate a running total, but only the sum of the last two numbers."; +"PSAT_CALL_TO_ACTION" = "Tap Get Started to begin."; +"PSAT_INITIAL_INSTRUCTION" = "Remember this first digit."; +"PSAT_INSTRUCTION" = "Add this new digit to the previous one."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-Hole Peg Test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "This activity measures your upper extremity function by asking you to place a peg in a hole. You will be asked to do this %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Both your left and right hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole, and, once done %@ times, remove it again %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Both your right and left hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole, and, once done %@ times, remove it again %@ times."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tap Get Started to begin."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Put the peg in the hole using your left hand."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Put the peg in the hole using your right hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Put the peg behind the line using your left hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Put the peg behind the line using your right hand."; +"HOLE_PEG_TEST_TEXT" = "Pick up the peg using two fingers."; +"HOLE_PEG_TEST_TEXT_2" = "Lift fingers to drop the peg."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor Activity"; +"TREMOR_TEST_INTRO_1_DETAIL" = "This activity measures the tremor of your hands in various positions. Find a place where you can sit comfortably for the duration of this activity."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Hold the phone in your more affected hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Hold the phone in your RIGHT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Hold the phone in your LEFT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "You will be asked to perform %@ while sitting with the phone in your hand."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "a task"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "two tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "three tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "four tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "five tasks"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tap next to proceed."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepare to hold your phone in your lap."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepare to hold your phone in your lap with your LEFT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepare to hold your phone in your lap with your RIGHT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Keep holding your phone in your lap for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Now hold your phone with your hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your hand extended for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Now hold your phone at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your elbow bent for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Now keeping your elbow bent, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Now keeping your elbow bent with your phone in your LEFT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Now keeping your elbow bent with your phone in your RIGHT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Keep touching your phone to your nose for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepare to do a queen wave (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepare to do a queen wave with your phone in your LEFT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepare to do a queen wave with your phone in your RIGHT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Keep performing a queen wave for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Now switch the phone to your LEFT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Now switch the phone to your RIGHT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continue to the next task."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activity completed."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "You will be asked to perform %@ while sitting with the phone first in one hand, then again with the other hand."; +"TREMOR_SKIP_LEFT_HAND" = "I cannot perform this activity with my LEFT hand."; +"TREMOR_SKIP_RIGHT_HAND" = "I cannot perform this activity with my RIGHT hand."; +"TREMOR_SKIP_NEITHER" = "I can perform this activity with both hands."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trail Making Test"; +"TRAILMAKING_INTENDED_USE" = "This activity evaluates your visual attention and task switching by recording the time required to tap a series of dots in order."; +"TRAILMAKING_INTENDED_USE2_A" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number ‘1’ followed by the numbers ‘2’ – ‘3’ – ‘4’… until you reach the number ‘7’."; +"TRAILMAKING_INTENDED_USE2_B" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number ‘1’ followed by tapping the first letter ‘A’, and then ‘2’ – ‘B’ – ‘3’ – ‘C’… until you reach the number ‘7’."; +"TRAILMAKING_INTRO_TEXT" = "Do this as quickly as you can without making mistakes. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Speech Recognition"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "This activity records your speech with the microphone at the bottom of the device, and translates it to text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tap Get Started to begin."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Press the button to start recording before speaking."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start Recording"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stop Recording"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edit Transcript"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edit transcript text to correct any misinterpretation of the speech."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Your transcription will appear here."; +"SPEECH_RECOGNITION_FAILED" = "Speech recognition failed."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Failed to initialize speech recognition."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Play Audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stop Audio"; +"SPEECH_IN_NOISE_TITLE" = "Speech in Noise"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "This activity measures intelligibility of speech when presented in noisy environments."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "As part of this test, you will:\n\nListen to a sentence.\n\nRepeat clearly what you heard or skip ahead to type in what you heard using the keyboard. \n\nIf you repeat what you heard, you will have the option to modify the transcript generated by the speech recognition engine."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volume Calibration"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tap ‘Play Audio’, adjust your volume to a comfortable level and then tap ‘Stop Audio’ to proceed."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Listen"; +"SPEECH_IN_NOISE_STEP_TEXT" = "A sentence mixed with background noise at a randomized Signal to Noise Ratio (SNR) will be played only once."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Speak"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repeat what you heard."; + +/* Touch Ability active task. */ +"TOUCH_ABILITY_INSTRUCTION_TITLE" = "Touch Ability Activity"; +"TOUCH_ABILITY_INSTRUCTION_DETAIL" = "This activity will measure your touch screen usability. Please locate a comfortable spot to proceed with this activity."; +"TOUCH_ABILITY_TAP_TITLE" = "Tap Ability"; +"TOUCH_ABILITY_TAP_TEXT" = "Please click on the squares appear on the screen. Square will disappear upon clicking. Please await for next square to appear before next click."; +"TOUCH_ABILITY_LONG_PRESS_TITLE" = "Long Press Ability"; +"TOUCH_ABILITY_LONG_PRESS_TEXT" = "Please long press on the squares appear on the screen for at least one second before lift up from screen. Once finger lift up, square will disappear despite whether it is long pressed for one second or not. Please await for next square to appear before next press."; +"TOUCH_ABILITY_SWIPE_TITLE" = "Swipe Ability"; +"TOUCH_ABILITY_SWIPE_TEXT" = "Please swipe in direction of the arrow on the screen. arrow will disappear upon swiping completion. Please await for next arrow to appear before next swipe."; +"TOUCH_ABILITY_VERTICAL_SCROLL_TITLE" = "Vertical Scroll Ability"; +"TOUCH_ABILITY_VERTICAL_SCROLL_TEXT" = "This test will require you to scroll through a list of number, and drag the item labeled by the color into a dotted line box. Once hand is lifted up from the list and stop scrolling for one second, list and box will disappear. Please await for next list to appear before next test."; +"TOUCH_ABILITY_HORIZONTAL_SCROLL_TITLE" = "Horizontal Scroll Ability"; +"TOUCH_ABILITY_HORIZONTAL_SCROLL_TEXT" = "This test will require you to scroll through a horizontal list of number, and drag the item labeled by the color into a dotted line box. Once hand is lifted up from the list and stop scrolling for one second, list and box will disappear. Please await for next list to appear before next trial."; +"TOUCH_ABILITY_PINCH_TITLE" = "Pinch Ability"; +"TOUCH_ABILITY_PINCH_TEXT" = "Please use two finger pinching gesture to readjust the size of cube similar the dash line box. Once completing and lifting up your fingers, cube and box will disappear. Please await for cube and box to appear before next trial."; +"TOUCH_ABILITY_ROTATION_TITLE" = "Rotation Ability"; +"TOUCH_ABILITY_ROTATION_TEXT" = "Please use two finger rotating gesture to readjust the arrow to align with dashed arrow. Once completing and lifting up your fingers, arrow will disappear. Please await for cube and box to appear before next trial."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Could not create file"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Could not remove sufficient log files to reach threshold"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error setting attribute"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "File not marked deleted (not marked uploaded)"; +"ERROR_DATALOGGER_MULTIPLE" = "Multiple errors removing logs"; +"ERROR_RECORDER_NO_DATA" = "No collected data was found."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "No output directory specified"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL Meter"; +"ENVIRONMENTSPL_INTRO_TEXT" = "This activity measures the environment sound pressure level. If the noise levels are too high, you will be unable to proceed. Please move to a quieter location to complete this task or retake this activity at a later time."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculating"; +"ENVIRONMENTSPL_THRESHOLD" = "Threshold: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Background Noise OK"; +"ENVIRONMENTSPL_NOISE" = "Too Much Background Noise"; +"ENVIRONMENTSPL_TITLE_2" = "Find a quiet place"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "To ensure accuracy, this test should be taken in a quiet environment."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start Task"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "No Data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Move slider to enter value"; +"SLIDER_I_DONT_KNOW" = "I Don’t Know"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Page"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Back"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Show PDF Thumbnail"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Hide PDF Thumbnail"; +"AX_BUTTON_ANNOTATE" = "Annotate"; +"AX_BUTTON_SHOW_SEARCH" = "Show Search Bar"; +"AX_BUTTON_HIDE_SEARCH" = "Hide Search Bar"; +"AX_BUTTON_SHARE" = "Share"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration of a check mark in a blue circle conveying success"; + +"AX_SIGNVIEW_LABEL" = "Designated signature field"; +"AX_SIGNVIEW_HINT" = "Touch the screen and move your finger to sign"; +"AX_SIGNVIEW_SIGNED" = "Signed"; +"AX_SIGNVIEW_UNSIGNED" = "Unsigned"; + +"AX_SELECTED" = "Selected"; +"AX_UNSELECTED" = "Un-selected"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECT ALL THAT APPLY"; + +"AX_SLIDER_LABEL" = "Response slider. Range from %@ to %@"; +"AX_UNLABELED_IMAGE" = "Unlabeled image"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Begin task"; + +"AX.MEMORY.TILE.ACTIVE" = "active"; +"AX.MEMORY.TILE.CORRECT" = "correct"; +"AX.MEMORY.TILE.INCORRECT" = "incorrect"; +"AX.MEMORY.TILE.QUIESCENT" = "quiescent"; +"AX.MEMORY.TILE.LABEL" = "Memory game tile"; + +"AX_IMAGE_CAPTURE_LABEL" = "Capture preview"; +"AX_IMAGE_CAPTURED_LABEL" = "Captured image"; + +"AX_VIDEO_CAPTURE_LABEL" = "Video capture preview"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video capture complete"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Unable to place disk with size %@ on disk with size %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Target"; +"AX_TOWER_OF_HANOI_TOWER" = "Tower"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Double-tap to place disk"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Double-tap to select top-most disk"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Has disk with sizes %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Empty"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Dismiss keyboard"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Range from %@ to %@"; +"AX_GRAPH_STACK_PREFIX" = "Stack composed of"; +"AX_GRAPH_AND_SEPARATOR" = " and "; +"AX_GRAPH_POINT_%@" = "Point: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Speech Waveform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "When recording starts, activate a second time to stop recording."; + +"AX_AUDIO_BAR_GRAPH" = "Audio Bar Graph"; + +"AX_AMSLER_GRID_LABEL" = "Amsler Grid"; +"AX_AMSLER_GRID_HINT" = "Use your finger or stylus to mark the grid directly, or swipe left outside the grid to finish."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tappable Buttons"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tap for Left Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your left ear."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tap for Right Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your right ear."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons for each ear are located. When the test starts, the buttons will be directly tappable. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tap for one finger"; +"AX_TAP_BUTTON_2_LABEL" = "Tap for other finger"; +"AX_TAP_BUTTON_HINT" = "Activate to make the buttons directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons are located. Activate either button to make the buttons directly tappable."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Buttons are now directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Using VoiceOver, the button will be directly tappable. It will be located near the center of the screen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Using VoiceOver, the buttons in the test will be directly tappable."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Cannot decode restoreData for initialization"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..edd4158 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errors) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.strings new file mode 100755 index 0000000..e0844aa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consent"; +"CONSENT_NAME_GIVEN" = "First Name"; +"CONSENT_NAME_FAMILY" = "Last Name"; +"CONSENT_NAME_PLACEHOLDER" = "Required"; +"CONSENT_REVIEW_TITLE" = "Review"; +"CONSENT_REVIEW_INSTRUCTION" = "Review the form below and tap Agree if you’re ready to continue."; +"CONSENT_REVIEW_ALERT_TITLE" = "Review"; +"CONSENT_SIGNATURE_TITLE" = "Signature"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Please sign using your finger in the box below."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Sign Here"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Page %1$ld of %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Welcome"; +"CONSENT_SECTION_DATA_GATHERING" = "Data Gathering"; +"CONSENT_SECTION_PRIVACY" = "Privacy"; +"CONSENT_SECTION_DATA_USE" = "Data Use"; +"CONSENT_SECTION_STUDY_SURVEY" = "Study Survey"; +"CONSENT_SECTION_STUDY_TASKS" = "Study Tasks"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Time Commitment"; +"CONSENT_SECTION_WITHDRAWING" = "Withdrawing"; +"CONSENT_LEARN_MORE_TITLE" = "Learn More"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Learn more about how data is gathered"; +"LEARN_MORE_DATA_USE" = "Learn more about how data is used"; +"LEARN_MORE_PRIVACY" = "Learn more about how your privacy and identity are protected"; +"LEARN_MORE_WELCOME" = "Learn more about the study first"; +"LEARN_MORE_STUDY_SURVEY" = "Learn more about the study survey"; +"LEARN_MORE_TIME_COMMITMENT" = "Learn more about the study’s impact on your time"; +"LEARN_MORE_TASKS" = "Learn more about the tasks involved"; +"LEARN_MORE_WITHDRAWING" = "Learn more about withdrawing"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Sharing Options"; +"CONSENT_SHARE_WIDELY_%@" = "Share my data with %@ and qualified researchers worldwide"; +"CONSENT_SHARE_ONLY_%@" = "Only share my data with %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ will receive your study data from your participation in this study.\n\nSharing your coded study data more broadly (without information such as your name), may benefit this and future research."; +"LEARN_MORE_CONSENT_SHARING" = "Learn more about data sharing"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Printed Name"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signature"; +"CONSENT_DOC_LINE_DATE" = "Date"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ of %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Question %1$@ of %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Skipped"; +"REVIEW_EDIT_ANSWER" = "Edit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Invalid value"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ exceeds the maximum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ is less than the minimum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ is not a valid value."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Invalid email address: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Enter an address"; +"LOCATION_ERROR_TITLE" = "Could not Find Specified Address"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Unable to resolve your current location. Please type in an address or move to a location with better GPS signal if applicable."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Access to location services has been denied. Please grant this app permission to use location services through Settings."; +"LOCATION_ERROR_GEOCODE" = "Unable to find a result for the entered address. Please make sure the address is valid."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Either you are not connected to the Internet or you have exceeded the maximum amount of address lookup requests. If you are not connected to the Internet, please turn on your Wi-Fi to answer this question, skip this question if skip button is available, or come back to the survey when you are connected to the Internet. Otherwise, please try again in a few minutes."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Text content exceeding maximum length: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera not available in split screen."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Password"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirm"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password again"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Passwords do not match."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Additional Information"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Gender"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Pick a gender"; +"DOB_FORM_ITEM_TITLE" = "Birthdate"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Pick a date"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Phone Number"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verification"; +"VERIFICATION_STEP_TITLE" = "Verify your Email"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tap on the link below if you did not receive a verification email and would like it sent again."; +"RESEND_EMAIL_BUTTON_TITLE" = "Resend Verification Email"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Login"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Forgot password?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Enter passcode"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirm passcode"; +"PASSCODE_SAVED_MESSAGE" = "Passcode saved"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Passcode authenticated"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Enter your old passcode"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Enter your new passcode"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirm your new passcode"; +"PASSCODE_INVALID_ALERT_TITLE" = "Passcode Incorrect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Passcodes did not match. Try again."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Please authenticate with Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID error"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Only numeric characters allowed."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Passcode entry progress indicator"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ of %@ digits entered"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Forgot Passcode?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Could not add Keychain item."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Could not update Keychain item."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Could not delete Keychain item."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Could not find Keychain item."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Female"; +"GENDER_MALE" = "Male"; +"GENDER_OTHER" = "Other"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Yes"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "left"; +"LIMB_RIGHT" = "right"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tap to answer"; +"NULL_ANSWER" = "Select an answer"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tap to select"; +"PLACEHOLDER_LONG_TEXT" = "Tap to write"; + +/* Button titles */ +"BUTTON_AGREE" = "Agree"; +"BUTTON_CANCEL" = "Cancel"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Clear"; +"BUTTON_CLEAR_SIGNATURE" = "Clear Signature"; +"BUTTON_APPLY" = "Apply"; +"BUTTON_DISAGREE" = "Disagree"; +"BUTTON_DONE" = "Done"; +"BUTTON_GET_STARTED" = "Get Started"; +"BUTTON_LEARN_MORE" = "Learn more"; +"BUTTON_NEXT" = "Next"; +"BUTTON_SKIP" = "Skip"; +"BUTTON_SKIP_QUESTION" = "Skip this question"; +"BUTTON_START_TIMER" = "Start Timer"; +"BUTTON_OPTION_SAVE" = "Save for Later"; +"BUTTON_OPTION_DISCARD" = "Discard Results"; +"BUTTON_OPTION_STOP_TASK" = "End Task"; +"BUTTON_SAVE" = "Save"; +"BUTTON_CLEAR_ANSWER" = "Clear answer"; +"BUTTON_READ_ONLY_MODE" = "This answer cannot be modified."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Close"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Starting activity in"; +"TASK_COMPLETE_TITLE" = "Activity Complete"; +"TASK_COMPLETE_TEXT" = "Your data will be analysed and you will be notified when your results are ready."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ remaining."; +"TOUCH_ANYWHERE_LABEL" = "Touch anywhere to continue"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capture Image"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapture Image"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No camera found. This step cannot be completed."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "In order to complete this step, allow this app access to the camera in Settings."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No output directory was specified for captured images."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "The captured image could not be saved."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start Recording"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stop Recording"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapture Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Heart Rate (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sit comfortably for %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Walk as fast as you can for %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "This activity monitors your heart rate and measures how far you can walk in %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Walk outdoors at your fastest possible pace for %1$@. When you’re done, sit and rest comfortably for %2$@. To begin, tap Get Started."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gait and Balance"; +"WALK_INTRO_TEXT" = "This activity measures your gait and balance as you walk and stand still. Do not continue if you cannot safely walk unassisted."; +"WALK_INTRO_2_TEXT_%ld" = "Find a place where you can safely walk unassisted for about %ld steps in a straight line."; +"WALK_INTRO_2_DETAIL" = "Put your device in a pocket or bag and follow the audio instructions."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Now stand still for %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stand still for %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Turn around and walk back to where you started."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Walk up to %ld steps in a straight line."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Find a place where you can safely walk back and forth in a straight line. Try to walk continuously by turning at the end of your path, as if you were walking around a cone.\n\nNext, you will be instructed to turn in a full circle, then stand still with your arms at your sides and your feet about shoulder-width apart."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tap Get Started when you are ready to begin.\nThen place your device in a pocket or bag and follow the audio instructions."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Walk back and forth in a straight line for %@. Walk as you would normally."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Turn in a full circle and then stand still for %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "You have completed the activity."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tapping Speed"; +"TAPPING_TASK_TITLE_RIGHT" = "Right Hand"; +"TAPPING_TASK_TITLE_LEFT" = "Left Hand"; +"TAPPING_INTRO_TEXT" = "This activity measures your tapping speed."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Put your device on a flat surface."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Use two fingers on the same hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Use two fingers on your right hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Use two fingers on your left hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Now repeat the same test using your right hand."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Now repeat the same test using your left hand."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for %@."; +"TAPPING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tap Next to begin."; +"TAP_BUTTON_TITLE" = "Tap"; +"TOTAL_TAPS_LABEL" = "Total Taps"; +"TAPPING_INSTRUCTION" = "Tap the buttons as consistently as you can using two fingers."; +"TAPPING_INSTRUCTION_RIGHT" = "Tap the buttons using your RIGHT hand."; +"TAPPING_INSTRUCTION_LEFT" = "Tap the buttons using your LEFT hand."; +"TAPPING_SKIP_TITLE" = "Skip this hand"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler Grid"; +"AMSLER_GRID_INTRO_TEXT" = "This activity helps in detecting problems in user’s vision."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Hold the device 30 centimetres from your face and at eye level throughout the test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Close your %@ and stare at the dot in the centre of the square grid.\n\nUsing your finger or stylus, mark any distortions you see, such as blurred or wavy lines.\n\nWhen you are done, swipe left anywhere outside the grid."; +"AMSLER_GRID_LEFT_EYE" = "Left Eye"; +"AMSLER_GRID_RIGHT_EYE" = "Right Eye"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voice"; +"AUDIO_CALL_TO_ACTION" = "Tap Get Started to begin."; +"AUDIO_INSTRUCTION" = "Say “Aaaaah” into the microphone for as long as you can."; +"AUDIO_INTRO_TEXT" = "Take a deep breath and say “Aaaaah” into the microphone for as long as you can. Keep a steady vocal volume so the audio bars remain blue."; +"AUDIO_INTENDED_USE" = "This activity evaluates your voice by recording it with the microphone at the bottom of your device."; +"AUDIO_TOO_LOUD_LABEL" = "Too Loud"; +"AUDIO_GENERIC_ERROR_LABEL" = "Unable to record audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Please wait while we check the background noise level."; +"AUDIO_TOO_LOUD_MESSAGE" = "The ambient noise level is too loud to record your voice. Please move somewhere quieter and try again."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tap Next when ready."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"TONE_AUDIOMETRY_INTENDED_USE" = "This activity measures your ability to hear different sounds."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Before you begin, plug in and put your headphones on.\n\nThe sound will be very subtle and is unlike a regular alert tone. The sound will begin softly, then slowly increase in volume. Please pay attention and tap the left or right button to indicate which ear you hear it in."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TONE_AUDIOMETRY_PREP_TEXT" = "You should now hear a tone. Adjust the volume using the controls on the side of your device.\n\nTap any button when you are ready to begin."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Every time you start hearing a sound, tap the left or right button to indicate which ear you hear the sound in."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Left Ear"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Right Ear"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Left"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Right"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tap when you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tone & Volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "You will hear a series of tones."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "When you hear a tone, tap on the button."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "For this test, volume will be set to 50 per cent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "This test takes about 10 minutes."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Turn on Do Not Disturb to avoid interruptions."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Tones will play in your right ear first."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Tones will now play in your left ear."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "This activity identifies hearing threshold levels of an individual in dB HL scale."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Make sure the device volume is set to the maximum level.\n\nDuring this task, a subtle tone will play in either the left or right ear.\n\nListen carefully and tap the button every time you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "This test identifies how loud a sound needs to be in order for you to hear it."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Onboarding questionnaire."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Select your preference for 'better ear', if any"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "left"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "right"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "no preference"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test Cancelled"; +"dBHL_ALERT_TITLE_START_OVER" = "Start Again"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancel Test"; +"dBHL_ALERT_TEXT" = "Reconnect your AirPods or EarPods to take this test."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Complete"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Headphones"; +"HEADPHONES_UNKNOWN" = "Unknown"; +"HEADPHONES_NONE" = "None"; +"CONNECTED" = "Connected"; +"NOT_CONNECTED" = "Not Connected"; +"HEADPHONE_CONNECTED_%@" = "Connected - %@"; +"HEADPHONE_DETECT_TITLE" = "Connect your Headphones"; +"HEADPHONE_DETECT_TEXT" = "This test requires Apple AirPods or Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Spatial Memory"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "This activity measures your short-term spatial memory by asking you to repeat the order in which %@ light up."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flowers"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flowers"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the same order they lit up."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the reverse of the order they lit up."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "To begin, tap Get Started, then watch closely."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Score"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Watch the %@ light up"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tap the %@ in the order they lit up"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tap the %@ in reverse order"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequence Complete"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_FAILED_TITLE" = "Try Again"; +"MEMORY_GAME_FAILED_MESSAGE" = "You didn’t quite make it through that time. Tap Next to continue."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Time’s Up"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "You ran out of time.\nTap Next to continue."; +"MEMORY_GAME_COMPLETE" = "Game Complete"; +"MEMORY_GAME_PAUSED_TITLE" = "Paused"; +"MEMORY_GAME_PAUSED_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "The memory activity was developed with assistance from Katherine Possin, PhD and Joel Kramer, PhD from University of California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaction Time"; +"REACTION_TIME_TASK_INTENDED_USE" = "This activity evaluates the time it takes for you to respond to a visual cue."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Shake the device in any direction as soon as the blue dot appears on screen. You will be asked to do this %D times."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Attempt %@ of %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Quickly shake the device when the blue circle appears"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Every time a word appears, select the first letter of the name of the COLOUR that is shown."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "When you are ready to begin the Stroop activity tap Get Started."; +"STROOP_TASK_STEP_TEXT" = "Select the first letter of the name of the COLOUR that is shown."; +"STROOP_COLOR_RED" = "RED"; +"STROOP_COLOR_GREEN" = "GREEN"; +"STROOP_COLOR_BLUE" = "BLUE"; +"STROOP_COLOR_YELLOW" = "YELLOW"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "G"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Y"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tower of Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "This activity evaluates your puzzle solving skills."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Move the entire stack to the highlighted platform in as few moves as possible."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Solve the Puzzle"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Number of Moves: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "I cannot solve this puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Range of Motion"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption must be left or right"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Left Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sit down on the edge of a chair. When you begin you will put your device on your left knee for a measurement. Please turn the sound on your device on so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sit down on the edge of a chair. When you begin you will put your device on your right knee for a measurement. Please turn the sound on your device on so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and extend your left knee as far as you can. Return to the start position and tap again when you are done."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and extend your right knee as far as you can. Return to the start position and tap again when you are done."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left knee. Tap the screen and extend your left knee as far as you can."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right knee. Tap the screen and extend your right knee as far as you can."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you are done, return your left knee to the start position. Then tap anywhere."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you are done, return your right knee to the start position. Then tap anywhere."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Left Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "When you begin you will put your device on your left shoulder for a measurement. Please turn the sound on your device on so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "When you begin you will put your device on your right shoulder for a measurement. Please turn the sound on your device on so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and raise your left arm as far as you can. Return to the start position and tap again when you are done."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and raise your right arm as far as you can. Return to the start position and tap again when you are done."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left shoulder. Tap the screen and raise your left arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right shoulder. Tap the screen and raise your right arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you are done, return your left arm to the start position. Then tap anywhere."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you are done, return your right arm to the start position. Then tap anywhere."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Timed Walk"; +"TIMED_WALK_INTRO_DETAIL" = "This activity measures your lower extremity function."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Find a place, preferably outside, where you can walk for about %@ in a straight line as quickly as possible, but safely. Do not slow down until after you’ve passed the finish line."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tap Next to begin."; +"TIMED_WALK_FORM_TITLE" = "Assistive device"; +"TIMED_WALK_FORM_TEXT" = "Use the same assistive device for each test."; +"TIMED_WALK_QUESTION_TEXT" = "Do you wear an ankle foot orthosis?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Do you use assistive device?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tap here to select an answer."; +"TIMED_WALK_QUESTION_2_CHOICE" = "None"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Unilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Unilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Bilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Walker/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Walk up to %@ in a straight line."; +"TIMED_WALK_INSTRUCTION_TURN" = "Turn around."; +"TIMED_WALK_INSTRUCTION_2" = "Walk back to where you started."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tap Next when complete."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "The Paced Auditory Serial Addition Test measures your auditory information processing speed and calculation ability."; +"PVSAT_INTRO_TEXT" = "The Paced Visual Serial Addition Test measures your visual information processing speed and calculation ability."; +"PAVSAT_INTRO_TEXT" = "The Paced Auditory and Visual Serial Addition Test measures your auditory and visual information processing speed and calculation ability."; +"PSAT_INTRO_TEXT_2_%@" = "Single digits are presented every %@ \nYou must add each new digit to the one immediately prior to it.\nAttention, you mustn’t calculate a running total, but only the sum of the last two numbers."; +"PSAT_CALL_TO_ACTION" = "Tap Get Started to begin."; +"PSAT_INITIAL_INSTRUCTION" = "Remember this first digit."; +"PSAT_INSTRUCTION" = "Add this new digit to the previous one."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-Hole Peg Test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "This activity measures your upper extremity function by asking you to place a peg in a hole. You will be asked to do this %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Both your left and right hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole and, once done %@ times, remove it again %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Both your right and left hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole and, once done %@ times, remove it again %@ times."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tap Get Started to begin."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Put the peg in the hole using your left hand."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Put the peg in the hole using your right hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Put the peg behind the line using your left hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Put the peg behind the line using your right hand."; +"HOLE_PEG_TEST_TEXT" = "Pick up the peg using two fingers."; +"HOLE_PEG_TEST_TEXT_2" = "Lift fingers to drop the peg."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor Activity"; +"TREMOR_TEST_INTRO_1_DETAIL" = "This activity measures the tremor of your hands in various positions. Find a place where you can sit comfortably for the duration of this activity."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Hold the phone in your more affected hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Hold the phone in your RIGHT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Hold the phone in your LEFT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "You will be asked to perform %@ while sitting with the phone in your hand."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "a task"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "two tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "three tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "four tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "five tasks"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tap next to proceed."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepare to hold your phone in your lap."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepare to hold your phone in your lap with your LEFT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepare to hold your phone in your lap with your RIGHT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Keep holding your phone in your lap for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Now hold your phone with your hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your hand extended for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Now hold your phone at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your elbow bent for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Now keeping your elbow bent, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Now keeping your elbow bent with your phone in your LEFT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Now keeping your elbow bent with your phone in your RIGHT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Keep touching your phone to your nose for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepare to do a queen wave (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepare to do a queen wave with your phone in your LEFT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepare to do a queen wave with your phone in your RIGHT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Keep performing a queen wave for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Now switch the phone to your LEFT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Now switch the phone to your RIGHT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continue to the next task."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activity completed."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "You will be asked to perform %@ while sitting with the phone first in one hand, then again with the other hand."; +"TREMOR_SKIP_LEFT_HAND" = "I cannot perform this activity with my LEFT hand."; +"TREMOR_SKIP_RIGHT_HAND" = "I cannot perform this activity with my RIGHT hand."; +"TREMOR_SKIP_NEITHER" = "I can perform this activity with both hands."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trail Making Test"; +"TRAILMAKING_INTENDED_USE" = "This activity evaluates your visual attention and task switching by recording the time required to tap a series of dots in order."; +"TRAILMAKING_INTENDED_USE2_A" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number '1' followed by the numbers '2' – '3' – '4'… until you reach the number '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number '1' followed by tapping the first letter 'A' and then '2' – 'B' – '3' – 'C'… until you reach the number '7'."; +"TRAILMAKING_INTRO_TEXT" = "Do this as quickly as you can without making mistakes. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Speech Recognition"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "This activity records your speech with the microphone at the bottom of the device and translates it to text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tap Get Started to begin."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Press the button to start recording before speaking."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start Recording"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stop Recording"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edit Transcript"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edit transcript text to correct any misinterpretation of the speech."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Your transcription will appear here."; +"SPEECH_RECOGNITION_FAILED" = "Speech recognition failed."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Failed to initialise speech recognition."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Play Audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stop Audio"; +"SPEECH_IN_NOISE_TITLE" = "Speech in Noise"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "This activity measures intelligibility of speech when presented in noisy environments."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "As part of this test, you will:\n\nListen to a sentence.\n\nRepeat clearly what you heard or skip ahead to type what you heard using the keyboard. \n\nIf you repeat what you heard, you will have the option to modify the transcript generated by the speech recognition engine."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volume Calibration"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tap 'Play Audio', adjust your volume to a comfortable level and then tap 'Stop Audio' to proceed."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Listen"; +"SPEECH_IN_NOISE_STEP_TEXT" = "A sentence mixed with background noise at a randomised Signal to Noise Ratio (SNR) will be played only once."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Speak"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repeat what you heard."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Could not create file"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Could not remove sufficient log files to reach threshold"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error setting attribute"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "File not marked deleted (not marked uploaded)"; +"ERROR_DATALOGGER_MULTIPLE" = "Multiple errors removing logs"; +"ERROR_RECORDER_NO_DATA" = "No collected data was found."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "No output directory specified"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL Meter"; +"ENVIRONMENTSPL_INTRO_TEXT" = "This activity measures the environment sound pressure level. If the noise levels are too high, you will be unable to proceed. Please move to a quieter location to complete this task or retake this activity at a later time."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculating"; +"ENVIRONMENTSPL_THRESHOLD" = "Threshold: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Background Noise OK"; +"ENVIRONMENTSPL_NOISE" = "Too Much Background Noise"; +"ENVIRONMENTSPL_TITLE_2" = "Find a quiet place"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "To ensure accuracy, this test should be taken in a quiet environment."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start Task"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "No Data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Move slider to enter value"; +"SLIDER_I_DONT_KNOW" = "I don’t know"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Page"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Back"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Show PDF Thumbnail"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Hide PDF Thumbnail"; +"AX_BUTTON_ANNOTATE" = "Annotate"; +"AX_BUTTON_SHOW_SEARCH" = "Show Search Bar"; +"AX_BUTTON_HIDE_SEARCH" = "Hide Search Bar"; +"AX_BUTTON_SHARE" = "Share"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration of a tick in a blue circle conveying success"; + +"AX_SIGNVIEW_LABEL" = "Designated signature field"; +"AX_SIGNVIEW_HINT" = "Touch the screen and move your finger to sign"; +"AX_SIGNVIEW_SIGNED" = "Signed"; +"AX_SIGNVIEW_UNSIGNED" = "Unsigned"; + +"AX_SELECTED" = "Selected"; +"AX_UNSELECTED" = "Un-selected"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECT ALL THAT APPLY"; + +"AX_SLIDER_LABEL" = "Response slider. Range from %@ to %@"; +"AX_UNLABELED_IMAGE" = "Unlabelled image"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Begin task"; + +"AX.MEMORY.TILE.ACTIVE" = "active"; +"AX.MEMORY.TILE.CORRECT" = "correct"; +"AX.MEMORY.TILE.INCORRECT" = "incorrect"; +"AX.MEMORY.TILE.QUIESCENT" = "quiescent"; +"AX.MEMORY.TILE.LABEL" = "Memory game tile"; + +"AX_IMAGE_CAPTURE_LABEL" = "Capture preview"; +"AX_IMAGE_CAPTURED_LABEL" = "Captured image"; + +"AX_VIDEO_CAPTURE_LABEL" = "Video capture preview"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video capture complete"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Unable to place disk with size %@ on disk with size %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Target"; +"AX_TOWER_OF_HANOI_TOWER" = "Tower"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Double-tap to place disk"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Double-tap to select top-most disk"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Has disk with sizes %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Empty"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Dismiss keyboard"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Range from %@ to %@"; +"AX_GRAPH_STACK_PREFIX" = "Stack composed of"; +"AX_GRAPH_AND_SEPARATOR" = " and "; +"AX_GRAPH_POINT_%@" = "Point: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Speech Waveform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "When recording starts, activate a second time to stop recording."; + +"AX_AUDIO_BAR_GRAPH" = "Audio Bar Graph"; + +"AX_AMSLER_GRID_LABEL" = "Amsler Grid"; +"AX_AMSLER_GRID_HINT" = "Use your finger or stylus to mark the grid directly, or swipe left outside the grid to finish."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tappable Buttons"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tap for Left Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your left ear."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tap for Right Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your right ear."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons for each ear are located. When the test starts, the buttons will be directly tappable. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tap for one finger"; +"AX_TAP_BUTTON_2_LABEL" = "Tap for other finger"; +"AX_TAP_BUTTON_HINT" = "Activate to make the buttons directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons are located. Activate either button to make the buttons directly tappable."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Buttons are now directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Using VoiceOver, the button will be directly tappable. It will be located near the centre of the screen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Using VoiceOver, the buttons in the test will be directly tappable."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Cannot decode restoreData for initialisation"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..edd4158 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_AU.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errors) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.strings new file mode 100755 index 0000000..937db64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consent"; +"CONSENT_NAME_GIVEN" = "First Name"; +"CONSENT_NAME_FAMILY" = "Last Name"; +"CONSENT_NAME_PLACEHOLDER" = "Required"; +"CONSENT_REVIEW_TITLE" = "Review"; +"CONSENT_REVIEW_INSTRUCTION" = "Review the form below and tap Agree if you’re ready to continue."; +"CONSENT_REVIEW_ALERT_TITLE" = "Review"; +"CONSENT_SIGNATURE_TITLE" = "Signature"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Please sign using your finger in the box below."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Sign Here"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Page %1$ld of %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Welcome"; +"CONSENT_SECTION_DATA_GATHERING" = "Data Gathering"; +"CONSENT_SECTION_PRIVACY" = "Privacy"; +"CONSENT_SECTION_DATA_USE" = "Data Use"; +"CONSENT_SECTION_STUDY_SURVEY" = "Study Survey"; +"CONSENT_SECTION_STUDY_TASKS" = "Study Tasks"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Time Commitment"; +"CONSENT_SECTION_WITHDRAWING" = "Withdrawing"; +"CONSENT_LEARN_MORE_TITLE" = "Learn More"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Learn more about how data is gathered"; +"LEARN_MORE_DATA_USE" = "Learn more about how data is used"; +"LEARN_MORE_PRIVACY" = "Learn more about how your privacy and identity are protected"; +"LEARN_MORE_WELCOME" = "Learn more about the study first"; +"LEARN_MORE_STUDY_SURVEY" = "Learn more about the study survey"; +"LEARN_MORE_TIME_COMMITMENT" = "Learn more about the study’s impact on your time"; +"LEARN_MORE_TASKS" = "Learn more about the tasks involved"; +"LEARN_MORE_WITHDRAWING" = "Learn more about withdrawing"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Sharing Options"; +"CONSENT_SHARE_WIDELY_%@" = "Share my data with %@ and qualified researchers worldwide"; +"CONSENT_SHARE_ONLY_%@" = "Only share my data with %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ will receive your study data from your participation in this study.\n\nSharing your coded study data more widely (without information such as your name) may benefit this and future research."; +"LEARN_MORE_CONSENT_SHARING" = "Learn more about data sharing"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Printed Name"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signature"; +"CONSENT_DOC_LINE_DATE" = "Date"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ of %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Question %1$@ of %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Skipped"; +"REVIEW_EDIT_ANSWER" = "Edit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Invalid value"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ exceeds the maximum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ is less than the minimum allowed value (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ is not a valid value."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Invalid email address: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Enter an address"; +"LOCATION_ERROR_TITLE" = "Could Not Find Specified Address"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Unable to resolve your current location. Please type in an address or move to a location with better GPS signal if applicable."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Access to Location Services has been denied. Please grant this app permission to use Location Services through Settings."; +"LOCATION_ERROR_GEOCODE" = "Unable to find a result for the entered address. Please make sure the address is valid."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Either you are not connected to the Internet or you have exceeded the maximum amount of address lookup requests. If you are not connected to the Internet, please turn on your Wi-Fi to answer this question, skip this question if the skip button is available, or come back to the survey when you are connected to the Internet. Otherwise, please try again in a few minutes."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Text content exceeding maximum length: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera not available in split screen."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Password"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirm"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Enter password again"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Passwords do not match."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Additional Information"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Gender"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Pick a gender"; +"DOB_FORM_ITEM_TITLE" = "Date of Birth"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Pick a date"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Phone Number"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verification"; +"VERIFICATION_STEP_TITLE" = "Verify your Email"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tap the link below if you did not receive a verification email and would like it sent again."; +"RESEND_EMAIL_BUTTON_TITLE" = "Resend Verification Email"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Login"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Forgot password?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Enter passcode"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirm passcode"; +"PASSCODE_SAVED_MESSAGE" = "Passcode saved"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Passcode authenticated"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Enter your old passcode"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Enter your new passcode"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirm your new passcode"; +"PASSCODE_INVALID_ALERT_TITLE" = "Passcode Incorrect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Passcodes did not match. Try again."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Please authenticate with Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID error"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Only numeric characters allowed."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Passcode entry progress indicator"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ of %@ digits entered"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Forgot Passcode?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Could not add Keychain item."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Could not update Keychain item."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Could not delete Keychain item."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Could not find Keychain item."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Female"; +"GENDER_MALE" = "Male"; +"GENDER_OTHER" = "Other"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Yes"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "left"; +"LIMB_RIGHT" = "right"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tap to answer"; +"NULL_ANSWER" = "Select an answer"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tap to select"; +"PLACEHOLDER_LONG_TEXT" = "Tap to write"; + +/* Button titles */ +"BUTTON_AGREE" = "Agree"; +"BUTTON_CANCEL" = "Cancel"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Clear"; +"BUTTON_CLEAR_SIGNATURE" = "Clear Signature"; +"BUTTON_APPLY" = "Apply"; +"BUTTON_DISAGREE" = "Disagree"; +"BUTTON_DONE" = "Done"; +"BUTTON_GET_STARTED" = "Get Started"; +"BUTTON_LEARN_MORE" = "Learn more"; +"BUTTON_NEXT" = "Next"; +"BUTTON_SKIP" = "Skip"; +"BUTTON_SKIP_QUESTION" = "Skip this question"; +"BUTTON_START_TIMER" = "Start Timer"; +"BUTTON_OPTION_SAVE" = "Save for Later"; +"BUTTON_OPTION_DISCARD" = "Discard Results"; +"BUTTON_OPTION_STOP_TASK" = "End Task"; +"BUTTON_SAVE" = "Save"; +"BUTTON_CLEAR_ANSWER" = "Clear answer"; +"BUTTON_READ_ONLY_MODE" = "This answer cannot be modified."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Close"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Starting activity in"; +"TASK_COMPLETE_TITLE" = "Activity Complete"; +"TASK_COMPLETE_TEXT" = "Your data will be analysed and you will be notified when your results are ready."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ remaining."; +"TOUCH_ANYWHERE_LABEL" = "Touch anywhere to continue"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capture Image"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapture Image"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No camera found. This step cannot be completed."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "In order to complete this step, allow this app access to the camera in Settings."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No output directory was specified for captured images."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "The captured image could not be saved."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start Recording"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stop Recording"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapture Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Heart Rate (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sit comfortably for %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Walk as fast as you can for %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "This activity monitors your heart rate and measures how far you can walk in %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Walk outdoors at your fastest possible pace for %1$@. When you’ve finished, sit and rest comfortably for %2$@. To begin, tap Get Started."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gait and Balance"; +"WALK_INTRO_TEXT" = "This activity measures your gait and balance as you walk and stand still. Do not continue if you cannot safely walk unassisted."; +"WALK_INTRO_2_TEXT_%ld" = "Find a place where you can safely walk unassisted for about %ld steps in a straight line."; +"WALK_INTRO_2_DETAIL" = "Put your device in a pocket or bag and follow the audio instructions."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Now stand still for %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stand still for %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Turn round and walk back to where you started."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Walk up to %ld steps in a straight line."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Find a place where you can safely walk back and forth in a straight line. Try to walk continuously by turning at the ends of your path, as if you are walking around a cone.\n\nNext you will be instructed to turn round in a full circle, then stand still with your arms at your sides and your feet about a shoulder-width apart."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tap Get Started when you are ready to begin.\nThen place your device in a pocket or bag and follow the audio instructions."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Walk back and forth in a straight line for %@. Walk as you would normally."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Turn in a full circle and then stand still for %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "You have completed the activity."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tapping Speed"; +"TAPPING_TASK_TITLE_RIGHT" = "Right Hand"; +"TAPPING_TASK_TITLE_LEFT" = "Left Hand"; +"TAPPING_INTRO_TEXT" = "This activity measures your tapping speed."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Put your device on a flat surface."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Use two fingers on the same hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Use two fingers on your right hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Use two fingers on your left hand to alternately tap the buttons on the screen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Now repeat the same test using your right hand."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Now repeat the same test using your left hand."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for %@."; +"TAPPING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tap Next to begin."; +"TAP_BUTTON_TITLE" = "Tap"; +"TOTAL_TAPS_LABEL" = "Total Taps"; +"TAPPING_INSTRUCTION" = "Tap the buttons as consistently as you can using two fingers."; +"TAPPING_INSTRUCTION_RIGHT" = "Tap the buttons using your RIGHT hand."; +"TAPPING_INSTRUCTION_LEFT" = "Tap the buttons using your LEFT hand."; +"TAPPING_SKIP_TITLE" = "Skip this hand"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler Grid"; +"AMSLER_GRID_INTRO_TEXT" = "This activity helps in detecting problems in user’s vision."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Hold the device 30 centimetres (12 inches) from your face and at eye level throughout the test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Close your %@ and stare at the dot in the centre of the square grid.\n\nUsing your finger or stylus, mark any distortions you see such as blurred or wavy lines.\n\nWhen you’ve finished, swipe left anywhere outside the grid."; +"AMSLER_GRID_LEFT_EYE" = "Left Eye"; +"AMSLER_GRID_RIGHT_EYE" = "Right Eye"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voice"; +"AUDIO_CALL_TO_ACTION" = "Tap Get Started to begin."; +"AUDIO_INSTRUCTION" = "Say “Aaaaah” into the microphone for as long as you can."; +"AUDIO_INTRO_TEXT" = "Take a deep breath and say “Aaaaah” into the microphone for as long as you can. Keep a steady vocal volume so the audio bars remain blue."; +"AUDIO_INTENDED_USE" = "This activity evaluates your voice by recording it with the microphone at the bottom of your device."; +"AUDIO_TOO_LOUD_LABEL" = "Too Loud"; +"AUDIO_GENERIC_ERROR_LABEL" = "Unable to record audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Please wait while we check the background noise level."; +"AUDIO_TOO_LOUD_MESSAGE" = "The ambient noise level is too loud to record your voice. Please move somewhere quieter and try again."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tap Next when ready."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"TONE_AUDIOMETRY_INTENDED_USE" = "This activity measures your ability to hear different sounds."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Before you begin, plug in and put your headphones on.\n\nThe sound will be very subtle and is unlike a standard alert tone.  The sound will begin softly and then slowly increase in volume.  Please pay attention and tap the left or right button to indicate which ear you hear it in."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TONE_AUDIOMETRY_PREP_TEXT" = "You should now hear a tone. Adjust the volume using the controls on the side of your device.\n\nTap any button when you are ready to begin."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Every time you start hearing a sound, tap the left or right button to indicate which ear you hear the sound in."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Left Ear"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Right Ear"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Left"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Right"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tone Audiometry"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tap when you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tone & Volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "You will hear a series of tones."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "When you hear a tone, tap on the button."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "For this test, volume will be set to 50 per cent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "This test takes about 10 minutes."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Turn on Do Not Disturb to avoid interruptions."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Tones will play in your right ear first."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Tones will now play in your left ear."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "This activity identifies hearing threshold levels of an individual in dB HL scale."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Make sure the device volume is set to the maximum level.\n\nDuring this task, a subtle tone will play in either the left or right ear.\n\nListen carefully and tap the button every time you hear a tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "This test identifies how loud a sound needs to be in order for you to hear it."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Onboarding questionnaire."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Select your preference for 'better ear', if any"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "left"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "right"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "no preference"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test Cancelled"; +"dBHL_ALERT_TITLE_START_OVER" = "Start Again"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancel Test"; +"dBHL_ALERT_TEXT" = "Reconnect your AirPods or EarPods to take this test."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Complete"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Headphones"; +"HEADPHONES_UNKNOWN" = "Unknown"; +"HEADPHONES_NONE" = "None"; +"CONNECTED" = "Connected"; +"NOT_CONNECTED" = "Not Connected"; +"HEADPHONE_CONNECTED_%@" = "Connected - %@"; +"HEADPHONE_DETECT_TITLE" = "Connect your Headphones"; +"HEADPHONE_DETECT_TEXT" = "This test requires Apple AirPods or Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Spatial Memory"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "This activity measures your short-term spatial memory by asking you to repeat the order in which %@ light up."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flowers"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flowers"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the same order they lit up."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Some of the %@ will light up one at a time. Tap those %@ in the reverse of the order they lit up."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "To begin, tap Get Started, then watch closely."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Score"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Watch the %@ light up"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tap the %@ in the order they lit up"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tap the %@ in reverse order"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequence Complete"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_FAILED_TITLE" = "Try Again"; +"MEMORY_GAME_FAILED_MESSAGE" = "You didn’t quite make it through that time. Tap Next to continue."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Time’s Up"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "You ran out of time.\nTap Next to continue."; +"MEMORY_GAME_COMPLETE" = "Game Complete"; +"MEMORY_GAME_PAUSED_TITLE" = "Paused"; +"MEMORY_GAME_PAUSED_MESSAGE" = "To continue, tap Next"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "The memory activity was developed with assistance from Katherine Possin, PhD and Joel Kramer, PhD from University of California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaction Time"; +"REACTION_TIME_TASK_INTENDED_USE" = "This activity evaluates the time it takes for you to respond to a visual cue."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Shake the device in any direction as soon as the blue dot appears on screen. You will be asked to do this %D times."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Attempt %@ of %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Quickly shake the device when the blue circle appears"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Every time a word appears, select the first letter of the name of the COLOUR that is shown."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "When you are ready to begin the Stroop activity, tap Get Started."; +"STROOP_TASK_STEP_TEXT" = "Select the first letter of the name of the COLOUR that is shown."; +"STROOP_COLOR_RED" = "RED"; +"STROOP_COLOR_GREEN" = "GREEN"; +"STROOP_COLOR_BLUE" = "BLUE"; +"STROOP_COLOR_YELLOW" = "YELLOW"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "G"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Y"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tower of Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "This activity evaluates your puzzle-solving skills."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Move the entire stack to the highlighted platform in as few moves as possible."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Solve the Puzzle"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Number of Moves: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "I cannot solve this puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Range of Motion"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption must be left or right"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Left Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Knee Range of Motion"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right knee."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sit down on the edge of a chair. When you begin, you will put your device on your left knee for a measurement. Please turn on the sound on your device so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sit down on the edge of a chair. When you begin, you will put your device on your right knee for a measurement. Please turn on the sound on your device so you can hear instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right knee with the screen facing out, as pictured."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and extend your left knee as far as you can. Return to the start position and tap again when you have finished."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and extend your right knee as far as you can. Return to the start position and tap again when you have finished."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left knee. Tap the screen and extend your left knee as far as you can."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right knee. Tap the screen and extend your right knee as far as you can."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you have finished, return your left knee to the start position. Then tap anywhere."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you have finished, return your right knee to the start position. Then tap anywhere."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Left Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Right Shoulder Range of Motion"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "This activity measures how far you can extend your left shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "This activity measures how far you can extend your right shoulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "When you begin, you will put your device on your left shoulder for a measurement. Please turn on the sound on your device so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "When you begin, you will put your device on your right shoulder for a measurement. Please turn on the sound on your device so you can hear instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Place your device on your left shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Place your device on your right shoulder with the screen facing out, as pictured."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "When ready, tap the screen to begin and raise your left arm as far as you can. Return to the start position and tap again when you have finished."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "When ready, tap the screen to begin and raise your right arm as far as you can. Return to the start position and tap again when you have finished."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Place your device on your left shoulder. Tap the screen and raise your left arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Place your device on your right shoulder. Tap the screen and raise your right arm to the front as far as you can."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "When you have finished, return your left arm to the start position. Then tap anywhere."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "When you have finished, return your right arm to the start position. Then tap anywhere."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Timed Walk"; +"TIMED_WALK_INTRO_DETAIL" = "This activity measures your lower extremity function."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Find a place, preferably outside, where you can walk for about %@ in a straight line as quickly as possible, but safely. Do not slow down until after you’ve passed the finish line."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tap Next to begin."; +"TIMED_WALK_FORM_TITLE" = "Assistive device"; +"TIMED_WALK_FORM_TEXT" = "Use the same assistive device for each test."; +"TIMED_WALK_QUESTION_TEXT" = "Do you wear an ankle-foot orthosis?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Do you use assistive device?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tap here to select an answer."; +"TIMED_WALK_QUESTION_2_CHOICE" = "None"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Unilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Unilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bilateral Cane"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Bilateral Crutch"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Zimmer/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Walk up to %@ in a straight line."; +"TIMED_WALK_INSTRUCTION_TURN" = "Turn round."; +"TIMED_WALK_INSTRUCTION_2" = "Walk back to where you started."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tap Next when complete."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "The Paced Auditory Serial Addition Test measures your auditory information processing speed and calculation ability."; +"PVSAT_INTRO_TEXT" = "The Paced Visual Serial Addition Test measures your visual information processing speed and calculation ability."; +"PAVSAT_INTRO_TEXT" = "The Paced Auditory and Visual Serial Addition Test measures your auditory and visual information processing speed and calculation ability."; +"PSAT_INTRO_TEXT_2_%@" = "Single digits are presented every %@.\nYou must add each new digit to the one immediately prior to it.\nAttention: you mustn’t calculate a running total, just the sum of the last two numbers."; +"PSAT_CALL_TO_ACTION" = "Tap Get Started to begin."; +"PSAT_INITIAL_INSTRUCTION" = "Remember this first digit."; +"PSAT_INSTRUCTION" = "Add this new digit to the previous one."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-Hole Peg Test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "This activity measures your upper extremity function by asking you to place a peg in a hole. You will be asked to do this %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Both your left and right hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole and, once done %@ times, remove it again %@ times."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Both your right and left hands will be tested.\nYou must pick up the peg as quickly as possible, put it in the hole and, once done %@ times, remove it again %@ times."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tap Get Started to begin."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Put the peg in the hole using your left hand."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Put the peg in the hole using your right hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Put the peg behind the line using your left hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Put the peg behind the line using your right hand."; +"HOLE_PEG_TEST_TEXT" = "Pick up the peg using two fingers."; +"HOLE_PEG_TEST_TEXT_2" = "Lift fingers to drop the peg."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor Activity"; +"TREMOR_TEST_INTRO_1_DETAIL" = "This activity measures the tremor of your hands in various positions. Find a place where you can sit comfortably for the duration of this activity."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Hold the phone in your more affected hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Hold the phone in your RIGHT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Hold the phone in your LEFT hand as shown in the image below."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "You will be asked to perform %@ while sitting with the phone in your hand."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "a task"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "two tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "three tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "four tasks"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "five tasks"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tap next to proceed."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepare to hold your phone in your lap."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepare to hold your phone in your lap with your LEFT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepare to hold your phone in your lap with your RIGHT hand."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Keep holding your phone in your lap for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Now hold your phone with your hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand extended out at shoulder height."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your hand extended for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Now hold your phone at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Now hold your phone with your LEFT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Now hold your phone with your RIGHT hand at shoulder height with your elbow bent."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Keep holding your phone with your elbow bent for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Now keeping your elbow bent, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Now keeping your elbow bent with your phone in your LEFT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Now keeping your elbow bent with your phone in your RIGHT hand, touch your phone to your nose repeatedly."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Keep touching your phone to your nose for %ld seconds"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepare to do a queen wave (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepare to do a queen wave with your phone in your LEFT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepare to do a queen wave with your phone in your RIGHT hand (wave by turning your wrist)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Keep performing a queen wave for %ld seconds."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Now switch the phone to your LEFT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Now switch the phone to your RIGHT hand and continue to the next task."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continue to the next task."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activity completed."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "You will be asked to perform %@ while sitting with the phone first in one hand, then again with the other hand."; +"TREMOR_SKIP_LEFT_HAND" = "I cannot perform this activity with my LEFT hand."; +"TREMOR_SKIP_RIGHT_HAND" = "I cannot perform this activity with my RIGHT hand."; +"TREMOR_SKIP_NEITHER" = "I can perform this activity with both hands."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trail Making Test"; +"TRAILMAKING_INTENDED_USE" = "This activity evaluates your visual attention and task switching by recording the time required to tap a series of dots in order."; +"TRAILMAKING_INTENDED_USE2_A" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number '1' followed by the numbers '2' – '3' – '4'… until you reach the number '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "After the countdown, tap dots in alternating order between numbers and letters. Begin by tapping the first number '1' followed by tapping the first letter 'A', and then '2' – 'B' – '3' – 'C'… until you reach the number '7'."; +"TRAILMAKING_INTRO_TEXT" = "Do this as quickly as you can without making mistakes. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tap Get Started to begin."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Speech Recognition"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "This activity records your speech with the microphone at the bottom of the device and translates it to text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tap Get Started to begin."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Press the button to start recording before speaking."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start Recording"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stop Recording"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edit Transcript"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edit transcript text to correct any misinterpretation of the speech."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Your transcription will appear here."; +"SPEECH_RECOGNITION_FAILED" = "Speech recognition failed."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Failed to initialise speech recognition."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Play Audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stop Audio"; +"SPEECH_IN_NOISE_TITLE" = "Speech in Noise"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "This activity measures intelligibility of speech when presented in noisy environments."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "As part of this test, you will:\n\nListen to a sentence.\n\nRepeat clearly what you heard or skip ahead to type in what you heard using the keyboard. \n\nIf you repeat what you heard, you will have the option to modify the transcript generated by the speech recognition engine."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volume Calibration"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tap Play Audio, adjust your volume to a comfortable level, and then tap Stop Audio to proceed."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Listen"; +"SPEECH_IN_NOISE_STEP_TEXT" = "A sentence mixed with background noise at a randomised Signal to Noise Ratio (SNR) will be played only once."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Speak"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repeat what you heard."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Could not create file"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Could not remove sufficient log files to reach threshold"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error setting attribute"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "File not marked deleted (not marked uploaded)"; +"ERROR_DATALOGGER_MULTIPLE" = "Multiple errors removing logs"; +"ERROR_RECORDER_NO_DATA" = "No collected data was found."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "No output directory specified"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL Meter"; +"ENVIRONMENTSPL_INTRO_TEXT" = "This activity measures the environment sound pressure level. If the noise levels are too high, you will be unable to proceed. Please move to a quieter location to complete this task or retake this activity at a later time."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculating"; +"ENVIRONMENTSPL_THRESHOLD" = "Threshold: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Background Noise OK"; +"ENVIRONMENTSPL_NOISE" = "Too Much Background Noise"; +"ENVIRONMENTSPL_TITLE_2" = "Find a quiet place"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "To ensure accuracy, this test should be taken in a quiet environment."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start Task"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "No Data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Move slider to enter value"; +"SLIDER_I_DONT_KNOW" = "I Don’t Know"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Page"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Back"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Show PDF Thumbnail"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Hide PDF Thumbnail"; +"AX_BUTTON_ANNOTATE" = "Annotate"; +"AX_BUTTON_SHOW_SEARCH" = "Show Search Bar"; +"AX_BUTTON_HIDE_SEARCH" = "Hide Search Bar"; +"AX_BUTTON_SHARE" = "Share"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration of a tick in a blue circle conveying success"; + +"AX_SIGNVIEW_LABEL" = "Designated signature field"; +"AX_SIGNVIEW_HINT" = "Touch the screen and move your finger to sign"; +"AX_SIGNVIEW_SIGNED" = "Signed"; +"AX_SIGNVIEW_UNSIGNED" = "Unsigned"; + +"AX_SELECTED" = "Selected"; +"AX_UNSELECTED" = "Unselected"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECT ALL THAT APPLY"; + +"AX_SLIDER_LABEL" = "Response slider. Range from %@ to %@"; +"AX_UNLABELED_IMAGE" = "Unlabelled image"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Begin task"; + +"AX.MEMORY.TILE.ACTIVE" = "active"; +"AX.MEMORY.TILE.CORRECT" = "correct"; +"AX.MEMORY.TILE.INCORRECT" = "incorrect"; +"AX.MEMORY.TILE.QUIESCENT" = "quiescent"; +"AX.MEMORY.TILE.LABEL" = "Memory game tile"; + +"AX_IMAGE_CAPTURE_LABEL" = "Capture preview"; +"AX_IMAGE_CAPTURED_LABEL" = "Captured image"; + +"AX_VIDEO_CAPTURE_LABEL" = "Video capture preview"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video capture complete"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Unable to place disk with size %@ on disk with size %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Target"; +"AX_TOWER_OF_HANOI_TOWER" = "Tower"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Double-tap to place disk"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Double-tap to select top-most disk"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Has disk with sizes %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Empty"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Dismiss keyboard"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Range from %@ to %@"; +"AX_GRAPH_STACK_PREFIX" = "Stack composed of"; +"AX_GRAPH_AND_SEPARATOR" = " and "; +"AX_GRAPH_POINT_%@" = "Point: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Speech Waveform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "When recording starts, activate a second time to stop recording."; + +"AX_AUDIO_BAR_GRAPH" = "Audio Bar Graph"; + +"AX_AMSLER_GRID_LABEL" = "Amsler Grid"; +"AX_AMSLER_GRID_HINT" = "Use your finger or stylus to mark the grid directly, or swipe left outside the grid to finish."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tappable Buttons"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tap for Left Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your left ear."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tap for Right Ear"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activate to start the test. When the test starts, tap directly on this button when you hear a sound in your right ear."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons for each ear are located. When the test starts, the buttons will be directly tappable. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tap for one finger"; +"AX_TAP_BUTTON_2_LABEL" = "Tap for other finger"; +"AX_TAP_BUTTON_HINT" = "Activate to make the buttons directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Using VoiceOver, explore the screen by touch to learn where the buttons are located. Activate either button to make the buttons directly tappable."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Buttons are now directly tappable."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Using VoiceOver, the button will be directly tappable. It will be located near the centre of the screen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Using VoiceOver, the buttons in the test will be directly tappable."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Cannot decode restoreData for initialisation"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..edd4158 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/en_GB.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errors) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.strings new file mode 100755 index 0000000..c21c468 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentimiento"; +"CONSENT_NAME_GIVEN" = "Nombre"; +"CONSENT_NAME_FAMILY" = "Apellidos"; +"CONSENT_NAME_PLACEHOLDER" = "Obligatorio"; +"CONSENT_REVIEW_TITLE" = "Revisar"; +"CONSENT_REVIEW_INSTRUCTION" = "Revisa el siguiente formulario y pulsa Acepto para continuar."; +"CONSENT_REVIEW_ALERT_TITLE" = "Revisar"; +"CONSENT_SIGNATURE_TITLE" = "Firma"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Firma con el dedo en el recuadro siguiente."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Firma aquí"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Página %1$ld de %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bienvenido"; +"CONSENT_SECTION_DATA_GATHERING" = "Recopilación de datos"; +"CONSENT_SECTION_PRIVACY" = "Privacidad"; +"CONSENT_SECTION_DATA_USE" = "Utilización de datos"; +"CONSENT_SECTION_STUDY_SURVEY" = "Evaluación del estudio"; +"CONSENT_SECTION_STUDY_TASKS" = "Tareas del estudio"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tiempo dedicado"; +"CONSENT_SECTION_WITHDRAWING" = "Salida del estudio"; +"CONSENT_LEARN_MORE_TITLE" = "Más información"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Más información sobre la recopilación de los datos"; +"LEARN_MORE_DATA_USE" = "Más información sobre la utilización de los datos"; +"LEARN_MORE_PRIVACY" = "Más información sobre la protección de la privacidad y la identidad"; +"LEARN_MORE_WELCOME" = "Más información sobre el estudio"; +"LEARN_MORE_STUDY_SURVEY" = "Más información sobre la evaluación del estudio"; +"LEARN_MORE_TIME_COMMITMENT" = "Más información sobre cómo afecta el estudio a tu tiempo"; +"LEARN_MORE_TASKS" = "Más información sobre las tareas del estudio"; +"LEARN_MORE_WITHDRAWING" = "Más información sobre cómo salir del estudio"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opciones para compartir"; +"CONSENT_SHARE_WIDELY_%@" = "Compartir mis datos con %@ y con investigadores cualificados de todo el mundo"; +"CONSENT_SHARE_ONLY_%@" = "Solo compartir mis datos con %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ recibirá los datos obtenidos de tu participación en este estudio.\n\nSi compartes los datos codificados del estudio de forma más amplia (sin incluir información personal como tu nombre), beneficiarás tanto esta investigación como las que se realicen en el futuro."; +"LEARN_MORE_CONSENT_SHARING" = "Más información sobre cómo se comparten los datos"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nombre impreso"; +"CONSENT_DOC_LINE_SIGNATURE" = "Firma"; +"CONSENT_DOC_LINE_DATE" = "Fecha"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ de %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pregunta %1$@ de %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Omitida"; +"REVIEW_EDIT_ANSWER" = "Editar"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valor no válido"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ es superior al valor máximo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ es inferior al valor mínimo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ no es un valor válido."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Dirección de correo electrónico no válida: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Introduce una dirección"; +"LOCATION_ERROR_TITLE" = "No se ha encontrado la dirección especificada"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "No se ha podido determinar tu ubicación actual. Escribe una dirección o dirígete a una ubicación donde la señal GPS sea mejor."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Se ha denegado el acceso a los servicios de localización. Ve a Ajustes para conceder a esta app permiso para utilizar los servicios de localización."; +"LOCATION_ERROR_GEOCODE" = "No se ha encontrado ningún resultado para la dirección introducida. Asegúrate de que la dirección es válida."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "O bien no estás conectado a Internet o bien has excedido el número máximo de búsquedas de direcciones. Si no estás conectado a Internet, activa la conexión Wi-Fi para responder a esta pregunta, omítela si el botón de omisión está disponible, o vuelve al estudio cuando dispongas de conexión a Internet. Si no es posible, inténtalo de nuevo dentro de unos minutos."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "El texto supera la longitud máxima: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Cámara no disponible en pantalla dividida."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Correo electrónico"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "juan@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Contraseña"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Introduce la contraseña"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmar"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Introduce de nuevo la contraseña"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Las contraseñas no coinciden."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Información adicional"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Juan"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "López"; +"GENDER_FORM_ITEM_TITLE" = "Sexo"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Selecciona tu sexo"; +"DOB_FORM_ITEM_TITLE" = "Fecha de nacimiento"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Selecciona una fecha"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Número de teléfono"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificación"; +"VERIFICATION_STEP_TITLE" = "Verifica tu correo electrónico"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Pulsa en el enlace siguiente si no has recibido un correo de verificación y quieres que se te vuelva a enviar."; +"RESEND_EMAIL_BUTTON_TITLE" = "Reenviar correo de verificación"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Iniciar sesión"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "¿Has olvidado tu contraseña?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Introduce el código"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmar código"; +"PASSCODE_SAVED_MESSAGE" = "Código guardado"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Autenticado por código"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Introduce el código antiguo"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Introduce el código nuevo"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirma el nuevo código"; +"PASSCODE_INVALID_ALERT_TITLE" = "Código incorrecto"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Los códigos no coinciden. Inténtalo de nuevo."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentícate con Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Error de Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Solo se admiten caracteres numéricos."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicador de progreso de introducción de código"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ de %@ dígitos introducidos"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "¿Has olvidado el código?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "No se ha podido añadir el ítem del llavero."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "No se ha podido actualizar el ítem del llavero."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "No se ha podido eliminar el ítem del llavero."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "No se ha podido encontrar el ítem del llavero."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipo I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipo II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipo III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipo IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipo V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipo VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Mujer"; +"GENDER_MALE" = "Hombre"; +"GENDER_OTHER" = "Otro"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Sí"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "izquierda"; +"LIMB_RIGHT" = "la derecha"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Pulsa para contestar"; +"NULL_ANSWER" = "Selecciona una respuesta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Pulsa para seleccionar"; +"PLACEHOLDER_LONG_TEXT" = "Pulsa para escribir"; + +/* Button titles */ +"BUTTON_AGREE" = "Acepto"; +"BUTTON_CANCEL" = "Cancelar"; +"BUTTON_OK" = "Aceptar"; +"BUTTON_CLEAR" = "Borrar"; +"BUTTON_CLEAR_SIGNATURE" = "Borrar firma"; +"BUTTON_APPLY" = "Aplicar"; +"BUTTON_DISAGREE" = "No acepto"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Empezar"; +"BUTTON_LEARN_MORE" = "Más información"; +"BUTTON_NEXT" = "Siguiente"; +"BUTTON_SKIP" = "Omitir"; +"BUTTON_SKIP_QUESTION" = "Omitir esta pregunta"; +"BUTTON_START_TIMER" = "Activar temporizador"; +"BUTTON_OPTION_SAVE" = "Guardar para luego"; +"BUTTON_OPTION_DISCARD" = "Descartar resultados"; +"BUTTON_OPTION_STOP_TASK" = "Finalizar tarea"; +"BUTTON_SAVE" = "Guardar"; +"BUTTON_CLEAR_ANSWER" = "Borrar respuesta"; +"BUTTON_READ_ONLY_MODE" = "Esta respuesta no puede modificarse."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Cerrar"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Iniciando actividad en"; +"TASK_COMPLETE_TITLE" = "Act. completada"; +"TASK_COMPLETE_TEXT" = "Se analizarán tus datos y recibirás los resultados cuando estén listos."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Quedan %@."; +"TOUCH_ANYWHERE_LABEL" = "Pulsa cualquier punto de la pantalla para continuar"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturar imagen"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Volver a capturar imagen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No se ha encontrado ninguna cámara. Este paso no se puede completar."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Para completar este paso, ve a Ajustes para conceder a la app acceso a la cámara."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No se ha especificado ningún directorio de salida para las imágenes capturadas."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "No se ha podido guardar la imagen capturada."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Iniciar grabación"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Detener grabación"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Volver a capturar vídeo"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Forma física"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distancia (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Frecuencia cardíaca (ppm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Siéntate cómodamente durante %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Camina lo más rápido que puedas durante %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Esta actividad controla tu frecuencia cardíaca y mide la distancia que puedes recorrer andando en %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Camina al aire libre lo más rápido que puedas durante %1$@. Transcurrido este tiempo, siéntate y descansa durante %2$@. Para comenzar, pulsa Empezar."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Marcha y equilibrio"; +"WALK_INTRO_TEXT" = "Esta actividad mide tu forma de andar, tu equilibrio al caminar y al permanecer quieto de pie. No sigas adelante si no puedes caminar de forma segura sin ayuda."; +"WALK_INTRO_2_TEXT_%ld" = "Busca un lugar en el que puedas dar unos %ld pasos en línea recta de forma segura sin ayuda."; +"WALK_INTRO_2_DETAIL" = "Guárdate el dispositivo en un bolsillo o un bolso y sigue las instrucciones de audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Ahora permanece quieto de pie durante %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Permanece quieto de pie durante %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Da la vuelta y camina hasta el punto de partida."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Da unos %ld pasos en línea recta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Busca un lugar en el que puedas caminar de un lado a otro en línea recta de forma segura. Camina sin parar y da la vuelta al final del recorrido, como si rodearas un cono.\n\nA continuación, se te indicará que gires sobre ti mismo dando una vuelta completa y que te quedes quieto, con los brazos relajados a los lados del cuerpo y los pies separados de forma que estén alineados con los hombros."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Pulsa Empezar cuando estés preparado para comenzar.\nA continuación, guarda el teléfono en un bolsillo o en una bolsa y sigue las instrucciones de audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Camina en línea recta de un lado a otro durante %@. Camina como lo harías normalmente."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Gira sobre ti mismo dando una vuelta completa y quédate quieto durante %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Has acabado la actividad."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocidad de pulsación"; +"TAPPING_TASK_TITLE_RIGHT" = "Mano derecha"; +"TAPPING_TASK_TITLE_LEFT" = "Mano izquierda"; +"TAPPING_INTRO_TEXT" = "Esta actividad mide tu velocidad de pulsación."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Coloca el dispositivo sobre una superficie plana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Utiliza dos dedos de la misma mano para pulsar de forma alternativa los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Utiliza dos dedos de la mano derecha para pulsar de forma alternativa los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Utiliza dos dedos de la mano izquierda para pulsar de forma alternativa los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Ahora repite la prueba, pero con la mano derecha."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Ahora repite la prueba, pero con la mano izquierda."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Pulsa con un dedo y luego con el otro. Intenta calcular el tiempo entre pulsación y pulsación para que sea lo más regular posible. Sigue pulsando durante %@."; +"TAPPING_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Pulsa Siguiente para empezar."; +"TAP_BUTTON_TITLE" = "Pulsar"; +"TOTAL_TAPS_LABEL" = "N.º total de pulsaciones"; +"TAPPING_INSTRUCTION" = "Pulsa los botones a un ritmo que sea lo más constante posible utilizando dos dedos."; +"TAPPING_INSTRUCTION_RIGHT" = "Pulsa los botones con la mano derecha."; +"TAPPING_INSTRUCTION_LEFT" = "Pulsa los botones con la mano izquierda."; +"TAPPING_SKIP_TITLE" = "Omitir esta mano"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Rejilla de Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Esta actividad ayuda a detectar los problemas de visión del usuario."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Sostén el dispositivo a 30 cm de distancia de la cara y a la altura de los ojos durante toda la prueba."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Cierra el %@ y mira fijamente al punto central de la rejilla.\n\nCon el dedo o un lápiz táctil, marca todas las distorsiones que veas (por ejemplo, líneas borrosas u onduladas).\n\nCuando hayas terminado, desliza el dedo hacia la izquierda fuera de la rejilla."; +"AMSLER_GRID_LEFT_EYE" = "ojo izquierdo"; +"AMSLER_GRID_RIGHT_EYE" = "ojo derecho"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voz"; +"AUDIO_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"AUDIO_INSTRUCTION" = "Di “aaaaaa” hacia el micrófono durante el máximo tiempo posible."; +"AUDIO_INTRO_TEXT" = "Inspira profundamente y di “aaaaaa” hacia el micrófono durante el máximo tiempo posible. Mantén un volumen constante para que las barras de audio permanezcan en color azul."; +"AUDIO_INTENDED_USE" = "Esta actividad valora tu voz grabándola con el micrófono que hay en la parte inferior de tu dispositivo."; +"AUDIO_TOO_LOUD_LABEL" = "Demasiado alto"; +"AUDIO_GENERIC_ERROR_LABEL" = "No se puede grabar el audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Espera mientras se comprueba el nivel de ruido de fondo."; +"AUDIO_TOO_LOUD_MESSAGE" = "Hay demasiado ruido ambiental para grabar tu voz. Ve a un lugar más tranquilo y vuelve a intentarlo."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Pulsa Siguiente cuando estés preparado."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometría tonal"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Esta actividad mide tu capacidad para oír diferentes sonidos."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Antes de empezar, conecta los auriculares y póntelos.\n\nEl sonido será muy sutil y no es el típico tono de aviso. El sonido empezará a oírse a un volumen muy bajito que irá aumentando de forma gradual. Presta atención y pulsa el botón izquierdo o derecho para indicar por qué oído lo estás oyendo."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ahora deberías oír un tono. Ajusta el volumen con los controles laterales del dispositivo.\n\nPulsa cualquier botón cuando estés listo para empezar."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Cada vez que empieces a oír un sonido, pulsa el botón izquierdo o derecho para indicar por qué oído lo estás oyendo."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Oído izquierdo"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Oído derecho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, izquierdo"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, derecho"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometría tonal"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Pulsa cuando oigas un tono."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tono y volumen"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Oirás una serie de tonos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Cuando oigas un tono, pulsa el botón."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Para esta prueba, el volumen se configurará al 50 %."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Esta prueba tarda unos 10 minutos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activa el modo “No molestar” para evitar interrupciones."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Los tonos se reproducirán primero en el oído derecho."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Ahora los tonos se reproducirán en el oído izquierdo."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Esta actividad identifica los umbrales de audición de un individuo en la escala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Comprueba que el volumen del dispositivo está al máximo nivel.\n\nDurante esta tarea, se reproducirá un tono sutil en el oído izquierdo o derecho.\n\nEscucha con atención y pulsa el botón cada vez que oigas un tono."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Esta prueba identifica cómo de alto debe estar un sonido para que puedas oírlo."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Cuestionario de introducción."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecciona tu preferencia para “oído bueno”, si la tienes"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "izquierdo"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "derecho"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "sin preferencia"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Se ha cancelado la prueba"; +"dBHL_ALERT_TITLE_START_OVER" = "Volver a empezar"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancelar la prueba"; +"dBHL_ALERT_TEXT" = "Vuelve a conectar tus AirPods o EarPods para realizar esta prueba."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ completado"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Auriculares"; +"HEADPHONES_UNKNOWN" = "Desconocidos"; +"HEADPHONES_NONE" = "Ninguno"; +"CONNECTED" = "Conectados"; +"NOT_CONNECTED" = "Sin conexión"; +"HEADPHONE_CONNECTED_%@" = "Conectados: %@"; +"HEADPHONE_DETECT_TITLE" = "Conecta tus auriculares"; +"HEADPHONE_DETECT_TEXT" = "Esta prueba requiere disponer de los AirPods o EarPods de Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memoria espacial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Esta actividad mide tu memoria espacial a corto plazo haciendo que repitas el orden en que se iluminan las %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flores"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flores"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Las %@ se irán iluminando de una en una. Pulsa las %@ en el mismo orden en el que se han iluminado."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Las %@ se irán iluminando de una en una. Pulsa las %@ en orden inverso al que se han iluminado."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Para comenzar, pulsa Empezar y observa con atención."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Puntuación"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Observa las %@ que se iluminan"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Pulsa las %@ en el orden en el que se han iluminado"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Pulsa las %@ en orden inverso"; +"MEMORY_GAME_COMPLETE_TITLE" = "Secuencia completada"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Para continuar, pulsa Siguiente"; +"MEMORY_GAME_FAILED_TITLE" = "Reintentar"; +"MEMORY_GAME_FAILED_MESSAGE" = "Esta vez no lo has conseguido. Pulsa Siguiente para continuar."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Se acabó el tiempo"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Se ha acabado el tiempo.\nPulsa Siguiente para continuar."; +"MEMORY_GAME_COMPLETE" = "Juego completado"; +"MEMORY_GAME_PAUSED_TITLE" = "En pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Para continuar, pulsa Siguiente"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "El ejercicio de memoria se ha desarrollado con la ayuda de la doctora Katherine Possin y del doctor Joel Kramer, de la Universidad de California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tiempo de reacción"; +"REACTION_TIME_TASK_INTENDED_USE" = "Esta actividad evalúa el tiempo que tardas en responder a un estímulo visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Agita el dispositivo en cualquier dirección en cuanto el punto azul aparezca en pantalla. Se te pedirá que lo hagas %D veces."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Intento %@ de %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Cuando aparezca el círculo azul, agita rápidamente el dispositivo"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Colores y palabras"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Cada vez que aparezca una palabra, selecciona la primera letra del nombre del COLOR que se muestra."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Cuando estés preparado para empezar el ejercicio de colores y palabras, pulsa Empezar."; +"STROOP_TASK_STEP_TEXT" = "Selecciona la primera letra del nombre del COLOR que se muestra."; +"STROOP_COLOR_RED" = "ROJO"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "AZUL"; +"STROOP_COLOR_YELLOW" = "AMARILLO"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "Az"; +"STROOP_COLOR_YELLOW_INITIAL" = "Am"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre de Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Esta actividad evalúa tu habilidad para solucionar rompecabezas."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Mueve toda la pila a la plataforma resaltada en el mínimo número de movimientos posible."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Soluciona el rompecabezas"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Número de movimientos: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "No sé resolver este rompecabezas"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Movimiento articular"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Tienes que elegir entre la extremidad izquierda o la derecha"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rango de movimiento de la rodilla izquierda"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rango de movimiento de la rodilla derecha"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Este ejercicio mide tu capacidad para estirar la rodilla izquierda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Este ejercicio mide tu capacidad para estirar la rodilla derecha."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Siéntate en el borde de una silla. Cuando estés preparado, colócate el dispositivo en la rodilla izquierda para empezar a medir. Activa el sonido del dispositivo para oír las instrucciones."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Siéntate en el borde de una silla. Cuando estés preparado, colócate el dispositivo en la rodilla derecha para empezar a medir. Activa el sonido del dispositivo para oír las instrucciones."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Colócate el dispositivo en la rodilla izquierda con la pantalla hacia delante, tal y como se ve en la imagen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Colócate el dispositivo en la rodilla derecha con la pantalla hacia delante, tal y como se ve en la imagen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Para empezar, pulsa la pantalla y eleva la rodilla izquierda todo lo que puedas. Cuando termines, vuelve a la posición inicial y pulsa la pantalla de nuevo."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Para empezar, pulsa la pantalla y eleva la rodilla derecha todo lo que puedas. Cuando termines, vuelve a la posición inicial y pulsa la pantalla de nuevo."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Colócate el dispositivo en la rodilla izquierda. Pulsa la pantalla y extiende la rodilla izquierda todo lo que puedas."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Colócate el dispositivo en la rodilla derecha. Pulsa la pantalla y extiende la rodilla derecha todo lo que puedas."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Cuando termines, coloca la rodilla izquierda en la posición inicial. Después, pulsa cualquier parte de la pantalla."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Cuando termines, coloca la rodilla derecha en la posición inicial. Después, pulsa cualquier parte de la pantalla."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rango de movimiento del hombro izquierdo"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rango de movimiento del hombro derecho"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Este ejercicio mide tu capacidad para estirar el hombro izquierdo."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Este ejercicio mide tu capacidad para estirar el hombro derecho."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Siéntate en el borde de una silla. Cuando estés preparado, colócate el dispositivo en el hombro izquierdo para empezar a medir. Activa el sonido del dispositivo para oír las instrucciones."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Siéntate en el borde de una silla. Cuando estés preparado, colócate el dispositivo en el hombro derecho para empezar a medir. Activa el sonido del dispositivo para oír las instrucciones."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Colócate el dispositivo en el hombro izquierdo con la pantalla hacia delante, tal y como se ve en la imagen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Colócate el dispositivo en el hombro derecho con la pantalla hacia delante, tal y como se ve en la imagen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Para empezar, pulsa la pantalla y eleva el brazo izquierdo todo lo que puedas. Cuando termines, vuelve a la posición inicial y pulsa la pantalla de nuevo."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Para empezar, pulsa la pantalla y eleva el brazo derecho todo lo que puedas. Cuando termines, vuelve a la posición inicial y pulsa la pantalla de nuevo."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Colócate el dispositivo en el hombro izquierdo. Pulsa la pantalla y eleva el brazo izquierdo hacia adelante todo lo que puedas."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Colócate el dispositivo en el hombro derecho. Pulsa la pantalla y eleva el brazo derecho hacia adelante todo lo que puedas."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Cuando termines, coloca el brazo izquierdo en la posición inicial. Después, pulsa cualquier parte de la pantalla."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Cuando termines, coloca el brazo derecho en la posición inicial. Después, pulsa cualquier parte de la pantalla."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Paseo cronometrado"; +"TIMED_WALK_INTRO_DETAIL" = "Esta actividad mide la funcionalidad de tus extremidades inferiores."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Busca un lugar, preferiblemente al aire libre, donde puedas caminar unos %@ en línea recta lo más rápido posible, pero de forma segura. No disminuyas la velocidad hasta que hayas llegado al final del recorrido."; +"TIMED_WALK_INTRO_2_DETAIL" = "Pulsa Siguiente para empezar."; +"TIMED_WALK_FORM_TITLE" = "Dispositivo de ayuda"; +"TIMED_WALK_FORM_TEXT" = "Utiliza el mismo dispositivo de ayuda en cada prueba."; +"TIMED_WALK_QUESTION_TEXT" = "¿Utilizas una ortesis de pie y tobillo?"; +"TIMED_WALK_QUESTION_2_TITLE" = "¿Utilizas algún dispositivo de ayuda?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Pulsa aquí para responder."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ninguno"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Un bastón"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Una muleta"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dos bastones"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dos muletas"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Andador (con o sin ruedas)"; +"TIMED_WALK_INSTRUCTION_%@" = "Camina %@ en línea recta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Date la vuelta."; +"TIMED_WALK_INSTRUCTION_2" = "Vuelve al punto de partida."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Pulsa Siguiente cuando hayas acabado."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "La prueba de suma seriada auditiva por pasos mide tu velocidad de procesamiento de información auditiva y tu capacidad de cálculo."; +"PVSAT_INTRO_TEXT" = "La prueba de suma seriada visual por pasos mide tu velocidad de procesamiento de información visual y tu capacidad de cálculo."; +"PAVSAT_INTRO_TEXT" = "La prueba de suma seriada auditiva y visual por pasos (PAVSAT) mide tu velocidad de procesamiento de información auditiva y visual y tu capacidad de cálculo."; +"PSAT_INTRO_TEXT_2_%@" = "Cada %@ se muestra un dígito.\nDebes sumar cada dígito nuevo al anterior.\nAtención: no debes calcular la suma total de todos los dígitos, solo sumar los dos últimos números."; +"PSAT_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"PSAT_INITIAL_INSTRUCTION" = "Recuerda este primer dígito."; +"PSAT_INSTRUCTION" = "Suma este otro dígito al anterior."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Prueba de los %@ círculos"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Esta actividad mide la capacidad funcional de tus extremidades superiores, para lo cual se te pedirá que introduzcas un círculo azul en un círculo vacío %@ veces."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "La prueba debe realizarse tanto con la mano izquierda como con la derecha.\nHay que arrastrar el círculo azul y colocarlo en el círculo vacío lo más rápido posible y, una vez que lo hayas hecho %@ veces, volver a extraerlo %@ veces."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "La prueba debe realizarse tanto con la mano derecha como con la izquierda.\nHay que arrastrar el círculo azul y colocarlo en el círculo vacío lo más rápido posible y, una vez que lo hayas hecho %@ veces, volver a extraerlo %@ veces."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Introduce el círculo azul en el círculo vacío con la mano izquierda."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Introduce el círculo azul en el círculo vacío con la mano derecha."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Coloca el círculo azul detrás de la línea con la mano izquierda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Coloca el círculo azul detrás de la línea con la mano derecha."; +"HOLE_PEG_TEST_TEXT" = "Arrastra el círculo azul con dos dedos."; +"HOLE_PEG_TEST_TEXT_2" = "Levanta los dedos para soltar el círculo azul."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Actividad para medir el temblor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Esta actividad mide el temblor de las manos en diferentes posiciones. Busca un lugar en el que puedas estar sentado cómodamente durante el tiempo que dure esta actividad."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Aguanta el teléfono en la mano más afectada como se muestra en la imagen siguiente."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Aguanta el teléfono en la mano derecha como se muestra en la imagen siguiente."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Aguanta el teléfono en la mano izquierda como se muestra en la imagen siguiente."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Se te solicitará que realices %@ mientras estás sentado con el teléfono en la mano."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "una tarea"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dos tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tres tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "cuatro tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinco tareas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Pulsa Siguiente para continuar."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepárate para aguantar el teléfono en el regazo."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepárate para aguantar el teléfono en la mano izquierda apoyada en el regazo."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepárate para aguantar el teléfono en la mano derecha apoyada en el regazo."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Sigue aguantando el teléfono en el regazo durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Ahora aguanta el teléfono con la mano extendida hacia arriba a la altura del hombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Ahora aguanta el teléfono con la mano izquierda extendida hacia arriba a la altura del hombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Ahora aguanta el teléfono con la mano derecha extendida hacia arriba a la altura del hombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Sigue aguantando el teléfono con la mano extendida durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Ahora aguanta el teléfono a la altura del hombro con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Ahora, aguanta el teléfono con la mano izquierda a la altura del hombro con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Ahora, aguanta el teléfono con la mano derecha a la altura del hombro con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Sigue aguantando el teléfono con el codo doblado durante %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Ahora, sin dejar de tener el codo doblado, toca el móvil con la nariz acercándotelo a la cara repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Ahora, sin dejar de tener el codo doblado y con el teléfono en la mano izquierda, toca el móvil con la nariz acercándotelo a la cara repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Ahora, sin dejar de tener el codo doblado y con el teléfono en la mano derecha, toca el móvil con la nariz acercándotelo a la cara repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Sigue tocando el móvil con la nariz acercándotelo a la cara durante %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepárate para girar la muñeca a modo de saludo."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepárate para girar la muñeca a modo de saludo con el teléfono en la mano izquierda."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepárate para girar la muñeca a modo de saludo con el teléfono en la mano derecha."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Sigue girando la muñeca durante %ld segundos a modo de saludo."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Ahora cambia el teléfono a la mano izquierda y continúa con la tarea siguiente."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Ahora cambia el teléfono a la mano derecha y continúa con la tarea siguiente."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continúa con la tarea siguiente."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Actividad completada."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Se te solicitará que realices %@ mientras estás sentado, primero con el teléfono en una mano y luego en la otra."; +"TREMOR_SKIP_LEFT_HAND" = "No puedo realizar esta actividad con la mano izquierda."; +"TREMOR_SKIP_RIGHT_HAND" = "No puedo realizar esta actividad con la mano derecha."; +"TREMOR_SKIP_NEITHER" = "Puedo realizar esta actividad con las dos manos."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Prueba del trazo"; +"TRAILMAKING_INTENDED_USE" = "Este ejercicio evalúa tu capacidad de atención visual y para cambiar de tarea grabando el tiempo que necesitas para pulsar una serie de puntos por orden."; +"TRAILMAKING_INTENDED_USE2_A" = "Cuando empiece la cuenta atrás, pulsa los puntos alternando números y letras. Empieza por el primer número “1” seguido de los números “2”, “3”, “4”… hasta llegar al número “7”."; +"TRAILMAKING_INTENDED_USE2_B" = "Cuando empiece la cuenta atrás, pulsa los puntos alternando números y letras. Empieza por el primer número “1” seguido de la primera letra “A” y, después, “2”, “B”, “3”, “C”… hasta llegar al número “7”."; +"TRAILMAKING_INTRO_TEXT" = "Realiza esta actividad lo más rápido posible procurando no cometer errores. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconocimiento de voz"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Esta actividad graba lo que dices con el micrófono que hay en la parte inferior del dispositivo, y lo convierte a texto."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Pulsa Empezar para comenzar."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Pulsa el botón para empezar a grabar antes de hablar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Iniciar grabación"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Detener grabación"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Editar transcripción"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edita el texto transcrito para corregir cualquier imprecisión."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Tu transcripción aparecerá aquí."; +"SPEECH_RECOGNITION_FAILED" = "Error del reconocimiento de voz."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "No se ha podido inicializar el reconocimiento de voz."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproducir audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Detener audio"; +"SPEECH_IN_NOISE_TITLE" = "Habla en ruido"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Esta actividad mide el grado de inteligibilidad del habla cuando se presenta en ambientes ruidosos."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Esta prueba consiste en:\n\nEscuchar una frase.\n\nRepetir vocalizando lo que has oído o introducirlo directamente utilizando el teclado. \n\nSi repites lo que has oído, tendrás la opción de modificar la transcripción generada por el motor de reconocimiento de voz."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibración del volumen"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Pulsa “Reproducir audio”, ajusta el volumen a un nivel cómodo y pulsa “Detener audio” para continuar."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Escuchar"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Se reproducirá una frase mezclada con ruido de fondo a una relación señal/ruido (S/R) aleatorizada."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Hablar"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repite lo que oyes."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "No se ha podido crear el archivo"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "No se han podido eliminar los archivos de registro suficientes para alcanzar el umbral"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error al establecer el atributo"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Archivo no marcado como eliminado (no marcado como cargado)"; +"ERROR_DATALOGGER_MULTIPLE" = "Varios errores al eliminar los registros"; +"ERROR_RECORDER_NO_DATA" = "No se han encontrado datos recopilados."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "No se ha especificado ningún directorio de salida"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Sonómetro"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Esta actividad mide el nivel de presión acústica ambiental. Si hay demasiado ruido, no podrás continuar. Vete a un lugar más silencioso para completar esta tarea o retómala en otro momento."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculando"; +"ENVIRONMENTSPL_THRESHOLD" = "Umbral: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Ruido de fondo aceptable"; +"ENVIRONMENTSPL_NOISE" = "Demasiado ruido de fondo"; +"ENVIRONMENTSPL_TITLE_2" = "Encuentra un sitio tranquilo"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Para garantizar la precisión, esta prueba debe realizarse en un entorno silencioso."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Iniciar tarea"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "No hay datos"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Desplaza el regulador para introducir un valor"; +"SLIDER_I_DONT_KNOW" = "No lo sé"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Página"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Atrás"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostrar la miniatura del PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ocultar la miniatura del PDF"; +"AX_BUTTON_ANNOTATE" = "Anotar"; +"AX_BUTTON_SHOW_SEARCH" = "Mostrar la barra de búsqueda"; +"AX_BUTTON_HIDE_SEARCH" = "Ocultar la barra de búsqueda"; +"AX_BUTTON_SHARE" = "Compartir"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustración de una marca de verificación en un círculo azul para indicar que se ha hecho correctamente"; + +"AX_SIGNVIEW_LABEL" = "Campo para la firma"; +"AX_SIGNVIEW_HINT" = "Toca la pantalla y firma con el dedo"; +"AX_SIGNVIEW_SIGNED" = "Firmado"; +"AX_SIGNVIEW_UNSIGNED" = "Sin firmar"; + +"AX_SELECTED" = "Seleccionado"; +"AX_UNSELECTED" = "No seleccionado"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECCIONA TODO LO QUE CORRESPONDA"; + +"AX_SLIDER_LABEL" = "Regulador de respuesta que va del %@ al %@."; +"AX_UNLABELED_IMAGE" = "Imagen sin etiqueta"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Iniciar tarea"; + +"AX.MEMORY.TILE.ACTIVE" = "activo"; +"AX.MEMORY.TILE.CORRECT" = "correcto"; +"AX.MEMORY.TILE.INCORRECT" = "incorrecto"; +"AX.MEMORY.TILE.QUIESCENT" = "inactivo"; +"AX.MEMORY.TILE.LABEL" = "Juego de memoria"; + +"AX_IMAGE_CAPTURE_LABEL" = "Previsualización de la captura"; +"AX_IMAGE_CAPTURED_LABEL" = "Imagen capturada"; + +"AX_VIDEO_CAPTURE_LABEL" = "Previsualización de la captura de vídeo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captura de vídeo completada"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "No se puede colocar un disco de tamaño %@ en un disco de tamaño %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Objetivo"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Pulsa dos veces para colocar el disco"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Pulsa dos veces para seleccionar el disco situado más arriba"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Tiene discos de tamaño %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vacía"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Descartar teclado"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Rango de valores de %@ a %@"; +"AX_GRAPH_STACK_PREFIX" = "Grupo compuesto por"; +"AX_GRAPH_AND_SEPARATOR" = " y "; +"AX_GRAPH_POINT_%@" = "Punto: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forma de onda de habla"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Cuando comience la grabación, actívalo una segunda vez para detener la grabación."; + +"AX_AUDIO_BAR_GRAPH" = "Gráfico de barras de audio"; + +"AX_AMSLER_GRID_LABEL" = "Rejilla de Amsler"; +"AX_AMSLER_GRID_HINT" = "Utiliza el dedo o un lápiz táctil para marcar la rejilla directamente o desliza el dedo hacia la izquierda fuera de la rejilla para terminar la actividad."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Botones que puedes pulsar"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Pulsa para el oído izquierdo"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activa este botón para iniciar la prueba. Cuando empiece, púlsalo directamente al oír un sonido en el oído izquierdo."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Pulsa para el oído derecho"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activa esta opción para iniciar la prueba. Cuando empiece, pulsa este botón directamente al oír un sonido en el oído derecho."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Con VoiceOver, explora la pantalla al tacto para aprender dónde están los botones para cada oído. Cuando empiece la prueba, podrás tocar los botones directamente. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Pulsa para indicar un dedo"; +"AX_TAP_BUTTON_2_LABEL" = "Pulsa para indicar otro dedo"; +"AX_TAP_BUTTON_HINT" = "Activa esta opción para poder pulsar los botones directamente."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Con VoiceOver, explora la pantalla al tacto para aprender dónde están los botones para cada oído. Activa cualquiera de los botones para poder tocarlos directamente."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Ahora puedes pulsar los botones directamente."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Con VoiceOver, podrás pulsar directamente el botón. Estará situado cerca del centro de la pantalla."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Con VoiceOver, podrás pulsar directamente los botones de la prueba."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "No se puede descodificar restoreData para inicializar"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7713777 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errores) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.strings new file mode 100755 index 0000000..28b8bf2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentimiento"; +"CONSENT_NAME_GIVEN" = "Nombre"; +"CONSENT_NAME_FAMILY" = "Apellidos"; +"CONSENT_NAME_PLACEHOLDER" = "Campo obligatorio"; +"CONSENT_REVIEW_TITLE" = "Revisar"; +"CONSENT_REVIEW_INSTRUCTION" = "Revisa el formulario siguiente y toca Acepto para continuar."; +"CONSENT_REVIEW_ALERT_TITLE" = "Revisar"; +"CONSENT_SIGNATURE_TITLE" = "Firma"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Firma con tu dedo en el siguiente cuadro."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Firma aquí"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Página %1$ld de %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bienvenido"; +"CONSENT_SECTION_DATA_GATHERING" = "Recopilación de datos"; +"CONSENT_SECTION_PRIVACY" = "Privacidad"; +"CONSENT_SECTION_DATA_USE" = "Uso de datos"; +"CONSENT_SECTION_STUDY_SURVEY" = "Encuesta del estudio"; +"CONSENT_SECTION_STUDY_TASKS" = "Tareas del estudio"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Compromiso de tiempo"; +"CONSENT_SECTION_WITHDRAWING" = "Darse de baja"; +"CONSENT_LEARN_MORE_TITLE" = "Más información"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Más información sobre cómo se recopilan los datos"; +"LEARN_MORE_DATA_USE" = "Más información sobre cómo se usan los datos"; +"LEARN_MORE_PRIVACY" = "Más información sobre cómo se protege tu privacidad e identidad"; +"LEARN_MORE_WELCOME" = "Obtén primero más información sobre el estudio"; +"LEARN_MORE_STUDY_SURVEY" = "Más información sobre la encuesta del estudio"; +"LEARN_MORE_TIME_COMMITMENT" = "Conoce más acerca del impacto del estudio en tu tiempo"; +"LEARN_MORE_TASKS" = "Más información sobre las tareas relacionadas"; +"LEARN_MORE_WITHDRAWING" = "Más información"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opciones al compartir"; +"CONSENT_SHARE_WIDELY_%@" = "Compartir mis datos con %@ y otros investigadores calificados a nivel mundial"; +"CONSENT_SHARE_ONLY_%@" = "Sólo compartir mis datos con %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ recibirá los datos de tu participación en este estudio.\n\nAl compartir tus datos de estudio codificados de manera general (sin información personal, como tu nombre) se beneficia esta y las investigaciones futuras."; +"LEARN_MORE_CONSENT_SHARING" = "Más información sobre compartir datos"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nombre"; +"CONSENT_DOC_LINE_SIGNATURE" = "Firma"; +"CONSENT_DOC_LINE_DATE" = "Fecha"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ de %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pregunta %1$@ de %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Se omitió"; +"REVIEW_EDIT_ANSWER" = "Editar"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valor no válido"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ excede el número máximo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ es menor al número mínimo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ no es un valor válido."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Correo electrónico no válido: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Ingresa una dirección"; +"LOCATION_ERROR_TITLE" = "No se encontró la dirección especificada"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "No se pudo determinar tu ubicación actual. Ingresa una dirección o ve a una ubicación con mejor recepción de señal GPS, si aplica."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Se rechazó el acceso a los servicios de localización. Otorga a esta app permiso para usar los servicios de localización desde Configuración."; +"LOCATION_ERROR_GEOCODE" = "No fue posible encontrar coincidencias con la dirección ingresada. Asegúrate de que la dirección es válida."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "No estás conectado a Internet o excediste la cantidad máxima de solicitudes de búsqueda de direcciones. Si no estás conectado a Internet, activa tu red Wi-Fi para contestar esta pregunta. También puedes omitirla (si el botón de omitir está disponible) o regresar a la encuesta cuando estés conectado a Internet. De lo contrario, vuelve a intentar en unos minutos."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "El texto sobrepasa la longitud máxima: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "No se puede usar la cámara con la pantalla dividida."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Correo"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "juanlopez@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Contraseña"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Ingresar contraseña"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmar"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Reingresar contraseña"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Las contraseñas no coinciden."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Información adicional"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Juan"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "López"; +"GENDER_FORM_ITEM_TITLE" = "Sexo"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Seleccionar"; +"DOB_FORM_ITEM_TITLE" = "Fecha de nacimiento"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Seleccionar"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Teléfono"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificación"; +"VERIFICATION_STEP_TITLE" = "Verifica tu correo electrónico"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Toca el siguiente enlace si no recibiste un correo de verificación y quieres que se vuelva a enviar."; +"RESEND_EMAIL_BUTTON_TITLE" = "Reenviar correo de verificación"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Inicio de sesión"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "¿Olvidaste tu contraseña?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Ingresa el código"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmar código"; +"PASSCODE_SAVED_MESSAGE" = "Código guardado"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Código autenticado"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Ingresa el código anterior"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Ingresa el nuevo código"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirma el nuevo código"; +"PASSCODE_INVALID_ALERT_TITLE" = "Código incorrecto"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Los códigos no coinciden. Intenta de nuevo."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentica con Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Error de Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Solo se permiten caracteres numéricos."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicador del progreso de ingreso de código"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ de %@ dígitos ingresados"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "¿Olvidaste el código?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "No se pudo agregar el elemento de Llavero."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "No se pudo actualizar el elemento de Llavero."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "No se pudo eliminar el elemento de Llavero."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "No se pudo encontrar el elemento de Llavero."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipo I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipo II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipo III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipo IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipo V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipo VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Mujer"; +"GENDER_MALE" = "Hombre"; +"GENDER_OTHER" = "Otro"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Sí"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "pie(s)"; +"MEASURING_UNIT_IN" = "pulg."; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "izquierda"; +"LIMB_RIGHT" = "derecha"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toca para contestar"; +"NULL_ANSWER" = "Seleccionar una respuesta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Toca para seleccionar"; +"PLACEHOLDER_LONG_TEXT" = "Toca para escribir"; + +/* Button titles */ +"BUTTON_AGREE" = "Acepto"; +"BUTTON_CANCEL" = "Cancelar"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Borrar"; +"BUTTON_CLEAR_SIGNATURE" = "Borrar firma"; +"BUTTON_APPLY" = "Aplicar"; +"BUTTON_DISAGREE" = "No acepto"; +"BUTTON_DONE" = "Aceptar"; +"BUTTON_GET_STARTED" = "Empezar"; +"BUTTON_LEARN_MORE" = "Más información"; +"BUTTON_NEXT" = "Siguiente"; +"BUTTON_SKIP" = "Omitir"; +"BUTTON_SKIP_QUESTION" = "Omitir esta pregunta"; +"BUTTON_START_TIMER" = "Activar temporizador"; +"BUTTON_OPTION_SAVE" = "Guardar para después"; +"BUTTON_OPTION_DISCARD" = "Descartar resultados"; +"BUTTON_OPTION_STOP_TASK" = "Finalizar tarea"; +"BUTTON_SAVE" = "Guardar"; +"BUTTON_CLEAR_ANSWER" = "Borrar respuesta"; +"BUTTON_READ_ONLY_MODE" = "No se puede modificar esta respuesta."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Cerrar"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Comenzar la actividad en"; +"TASK_COMPLETE_TITLE" = "Actividad completada"; +"TASK_COMPLETE_TEXT" = "Se analizarán tus datos y se te avisará cuando tus resultados estén listos."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ más."; +"TOUCH_ANYWHERE_LABEL" = "Toca para continuar"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturar imagen"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapturar imagen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "No se encontraron cámaras. Este paso no se puede finalizar."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Para finalizar este paso, permite el acceso de la app a la cámara en Configuración."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "No se especificó un directorio de salida para las imágenes capturadas."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "No se pudo guardar la imagen capturada."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Iniciar grabación"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Detener grabación"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapturar video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Condición física"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distancia (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Frecuencia cardiaca (lpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Siéntate cómodamente durante %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Camina tan rápido como sea posible durante %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Esta actividad revisa tu frecuencia cardiaca y mide cuánto puedes caminar en el transcurso de %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Camina en exteriores al paso más apresurado que puedas durante %1$@. Cuando termines, siéntate y descansa cómodamente durante %2$@. Para comenzar, toca Empezar."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Pasos y equilibrio"; +"WALK_INTRO_TEXT" = "Esta actividad mide tus pasos así como tu equilibrio al caminar y al permanecer de pie. No continúes si no puedes caminar sin ayuda."; +"WALK_INTRO_2_TEXT_%ld" = "Encuentra un lugar donde puedas dar %ld pasos en línea recta sin ayuda."; +"WALK_INTRO_2_DETAIL" = "Coloca tu dispositivo en un bolsillo o bolsa y sigue las instrucciones sonoras."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Ahora, no te muevas durante %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "No te muevas durante %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Da vuelta y regresa al punto de inicio."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Da hasta %ld pasos en línea recta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Encuentra un lugar donde puedas avanzar y retroceder en línea recta de manera segura. Camina sin detenerte y, cuando llegues al final, da una media vuelta amplia.\n\nA continuación, se te pedirá que des una vuelta completa, que te pares con los brazos extendidos a los costados y los pies separados a lo ancho de los hombros."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Toca Empezar cuando quieras comenzar.\nLuego coloca tu dispositivo en tu bolsillo o bolsa y sigue las instrucciones sonoras."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Camina de un lado a otro en una línea recta por %@. Camina como lo harías normalmente."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Da una vuelta completa sobre tu eje y quédate quieto por %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Completaste la actividad."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocidad al tocar"; +"TAPPING_TASK_TITLE_RIGHT" = "Mano derecha"; +"TAPPING_TASK_TITLE_LEFT" = "Mano izquierda"; +"TAPPING_INTRO_TEXT" = "Esta actividad mide tu velocidad al tocar."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Coloca tu dispositivo sobre una superficie plana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Usa dos dedos de la misma mano para tocar alternativamente los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Usa dos dedos de la mano derecha para tocar alternativamente los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Usa dos dedos de la mano izquierda para tocar alternativamente los botones de la pantalla."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Ahora repite la prueba con la mano derecha."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Ahora repite la prueba con la mano izquierda."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Toca con un dedo y luego con el otro. Intenta calcular el tiempo entre cada toque para que sea lo más constante posible. Sigue tocando por %@."; +"TAPPING_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Toca Siguiente para comenzar."; +"TAP_BUTTON_TITLE" = "Tocar"; +"TOTAL_TAPS_LABEL" = "Toques en total"; +"TAPPING_INSTRUCTION" = "Toca los botones lo más constante que puedas usando dos dedos."; +"TAPPING_INSTRUCTION_RIGHT" = "Toca los botones usando tu mano derecha."; +"TAPPING_INSTRUCTION_LEFT" = "Toca los botones usando tu mano izquierda."; +"TAPPING_SKIP_TITLE" = "Omitir esta mano"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Cuadrícula de Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Esta actividad ayuda a detectar problemas de visión del usuario."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Durante toda la prueba, mantén el dispositivo a 30 cm de tu cara, al nivel de los ojos."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Cierra tu %@ y mira el punto en el centro de la cuadrícula.\n\nCon tu dedo o lápiz óptico, marca todas las distorsiones que detectes,\ntales como líneas borrosas u onduladas.\n\nAl terminar, desliza a la izquierda sobre cualquier área afuera de la cuadrícula."; +"AMSLER_GRID_LEFT_EYE" = "Ojo izquierdo"; +"AMSLER_GRID_RIGHT_EYE" = "Ojo derecho"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voz"; +"AUDIO_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"AUDIO_INSTRUCTION" = "Di “Aaah” en el micrófono durante todo tiempo que puedas."; +"AUDIO_INTRO_TEXT" = "Inhala profundamente y di “Aaah” en el micrófono durante todo tiempo que puedas. Mantén la misma intensidad de volumen de manera que las barras de audio permanezcan azules."; +"AUDIO_INTENDED_USE" = "Esta actividad evalúa tu voz al grabarla con el micrófono ubicado en la parte inferior de tu dispositivo."; +"AUDIO_TOO_LOUD_LABEL" = "Demasiado fuerte"; +"AUDIO_GENERIC_ERROR_LABEL" = "No se pudo grabar audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Espera mientras revisamos el nivel de ruido de fondo."; +"AUDIO_TOO_LOUD_MESSAGE" = "Hay mucho ruido ambiental como para grabar tu voz. Ve a un lugar más tranquilo y reintenta."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Toca Siguiente cuando estés listo."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometría tonal"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Esta actividad mide tu capacidad para escuchar sonidos distintos."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Antes de empezar, conecta y ponte los audífonos.\n\nEscucharás un sonido muy sutil, diferente a una alerta de tono regular.  El volumen del sonido aumentará gradualmente.  Escucha atentamente y toca el botón de la izquierda o de la derecha, dependiendo del lado en que escuches el sonido."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ahora deberías estar escuchando un tono. Ajusta el volumen utilizando los controles a un lado de tu dispositivo.\n\nToca cualquier botón cuando estés listo para iniciar."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Cada que escuches un sonido, toca el botón de la izquierda o la derecha para indicar el oído con el cual escuchas el sonido."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Oído izquierdo"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Oído derecho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, izquierda"; +"TONE_LABEL_%@_RIGHT" = "%@ HZ, derecha"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometría tonal"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Toca cuando escuches un tono."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tono y volumen"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Escucharás una serie de tonos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Cuando escuches un tono, toca el botón."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Para esta prueba, el volumen se configurará en 50%."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Esta prueba toma unos 10 minutos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activa \"No molestar\" para evitar interrupciones."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Los tonos se reproducirán primero en tu oído derecho."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Los tonos se reproducirán ahora en tu oído izquierdo."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Esta actividad identifica los niveles de audición de una persona utilizando una escala decibélica HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Asegúrate de que el volumen del dispositivo esté al nivel máximo.\n\nDurante esta tarea, se reproducirá un tono sutil en uno de los dos oídos.\n\nEscucha atentamente y toca el botón cada que oigas un tono."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Esta prueba identifica lo alto que debe ser el volumen del sonido para que lo escuches."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Cuestionario de integración."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecciona tus preferencias del \"mejor oído\", si aplica"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "izquierdo"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "derecho"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "sin preferencia"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Prueba cancelada"; +"dBHL_ALERT_TITLE_START_OVER" = "Volver a empezar"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancelar prueba"; +"dBHL_ALERT_TEXT" = "Vuelve a conectar tus AirPods o EarPods para realizar esta prueba."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ completado"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Audífonos"; +"HEADPHONES_UNKNOWN" = "Desconocidos"; +"HEADPHONES_NONE" = "Ninguno"; +"CONNECTED" = "Conectados"; +"NOT_CONNECTED" = "Sin conectar"; +"HEADPHONE_CONNECTED_%@" = "Conectados: %@"; +"HEADPHONE_DETECT_TITLE" = "Conecta tus audífonos"; +"HEADPHONE_DETECT_TEXT" = "Este estudio requiere usar Apple AirPods o Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memoria espacial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Esta actividad mide tu memoria espacial a corto plazo al pedirte repetir el orden en que se encienden las imágenes de %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flores"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flores"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Algunas imágenes de %@ se encenderán una a la vez. Toca las imágenes de %@ en el mismo orden en que se encendieron."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Algunas imágenes de %@ se encenderán una a la vez. Toca las imágenes de %@ en orden inverso al que se encendieron."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Para comenzar, toca Empezar y luego observa cuidadosamente."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Puntuación"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Observa cuando se encienda las imágenes de %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Toca las imágenes de %@ según se encienden"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Toca las imágenes de %@ en orden contrario"; +"MEMORY_GAME_COMPLETE_TITLE" = "Secuencia completada"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Para continuar, toca Siguiente"; +"MEMORY_GAME_FAILED_TITLE" = "Reintentar"; +"MEMORY_GAME_FAILED_MESSAGE" = "Tuviste dificultades esa vez. Toca Siguiente para continuar."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Se acabó el tiempo"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Se agotó el tiempo.\nToca Siguiente para continuar."; +"MEMORY_GAME_COMPLETE" = "Juego completado"; +"MEMORY_GAME_PAUSED_TITLE" = "En pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Para continuar, toca Siguiente"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "La actividad de memoria fue desarrollada en colaboración con la Dra. Katherine Possin y el Dr. Joel Kramer de la Universidad de California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tiempo de reacción"; +"REACTION_TIME_TASK_INTENDED_USE" = "Esta actividad evalúa el tiempo que te toma responder a una indicación visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Sacude el dispositivo en cualquier dirección en cuanto el punto azul se muestre en la pantalla. Se te pedirá esto %D veces."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Intento %@ de %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Sacude rápidamente el dispositivo cuando se muestre el círculo azul"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Cada que aparezca la palabra, selecciona la primera letra del nombre del COLOR que se muestra."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Cuando estés listo para comenzar la actividad de Stroop, toca Empezar."; +"STROOP_TASK_STEP_TEXT" = "Selecciona la primera letra del nombre del COLOR que se muestra."; +"STROOP_COLOR_RED" = "ROJO"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "AZUL"; +"STROOP_COLOR_YELLOW" = "AMARILLO"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "A"; +"STROOP_COLOR_YELLOW_INITIAL" = "A"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre de Hanói"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Esta actividad evalúa tu capacidad para resolver acertijos."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Mueve toda la pila a la plataforma iluminada usando un número mínimo de movimientos."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Resuelve el acertijo"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Número de movimientos: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "No puedo resolver este acertijo"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Rango de movimiento"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption debe ser izquierda o derecha"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rango de movimiento de la rodilla izquierda"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rango de movimiento de la rodilla derecha"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Esta actividad mide cuánto puedes extender tu rodilla izquierda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Esta actividad mide cuánto puedes extender tu rodilla derecha."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Siéntate en el borde de una silla. Al iniciar deberás colocar el dispositivo sobre tu rodilla izquierda para realizar una medición. Activa el sonido en el dispositivo para escuchar las instrucciones."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Siéntate en el borde de una silla. Al iniciar deberás colocar el dispositivo sobre tu rodilla derecha para realizar una medición. Activa el sonido en el dispositivo para escuchar las instrucciones."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Coloca el dispositivo sobre tu rodilla izquierda con la pantalla expuesta, como se indica en la imagen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Coloca el dispositivo sobre tu rodilla derecha con la pantalla expuesta, como se indica en la imagen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Toca la pantalla cuando te hayas preparado para comenzar y estira tu rodilla izquierda tanto como puedas. Vuelve a la posición inicial y toca de nuevo cuando hayas terminado."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Toca la pantalla cuando te hayas preparado para comenzar y estira tu rodilla derecha tanto como puedas. Vuelve a la posición inicial y toca de nuevo cuando hayas terminado."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloca el dispositivo sobre tu rodilla izquierda. Toca la pantalla y estira la rodilla tanto como puedas."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloca el dispositivo sobre tu rodilla derecha. Toca la pantalla y estira la rodilla tanto como puedas."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Al terminar, vuelve a dejar tu rodilla izquierda en la posición inicial. Luego, toca en cualquier parte."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Al terminar, vuelve a dejar tu rodilla derecha en la posición inicial. Luego, toca en cualquier parte."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rango de movimiento del hombro izquierdo"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rango de movimiento del hombro derecho"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Esta actividad mide cuánto puedes extender tu hombro izquierdo."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Esta actividad mide cuánto puedes extender tu hombro derecho."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Al iniciar deberás colocar el dispositivo sobre tu hombro izquierdo para realizar una medición. Activa el sonido en el dispositivo para escuchar las instrucciones."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Al iniciar deberás colocar el dispositivo sobre tu hombro derecho para realizar una medición. Activa el sonido en el dispositivo para escuchar las instrucciones."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Coloca el dispositivo sobre tu hombro izquierdo con la pantalla expuesta, como se indica en la imagen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Coloca el dispositivo sobre tu hombro derecho con la pantalla expuesta, como se indica en la imagen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Toca la pantalla cuando te hayas preparado para comenzar y levanta tu brazo izquierdo tanto como puedas. Vuelve a la posición inicial y toca de nuevo cuando hayas terminado."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Toca la pantalla cuando te hayas preparado para comenzar y levanta tu brazo derecho tanto como puedas. Vuelve a la posición inicial y toca de nuevo cuando hayas terminado."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloca el dispositivo sobre tu hombro izquierdo. Toca la pantalla y levanta el brazo izquierdo hacia el frente tanto como puedas."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloca el dispositivo sobre tu hombro derecho. Toca la pantalla y levanta el brazo derecho hacia el frente tanto como puedas."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Al terminar, vuelve a dejar tu brazo izquierdo en la posición inicial. Luego, toca en cualquier parte."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Al terminar, vuelve a dejar tu brazo derecho en la posición inicial. Luego, toca en cualquier parte."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Caminata cronometrada"; +"TIMED_WALK_INTRO_DETAIL" = "Esta actividad mide la función de tus extremidades inferiores."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Encuentra un lugar, de preferencia al aire libre, donde puedas caminar alrededor de %@ en línea recta tan rápido como sea posible pero de forma segura. No te detengas sino hasta cruzar la meta."; +"TIMED_WALK_INTRO_2_DETAIL" = "Toca Siguiente para comenzar."; +"TIMED_WALK_FORM_TITLE" = "Dispositivo de ayuda"; +"TIMED_WALK_FORM_TEXT" = "Usa el mismo dispositivo de ayuda para cada prueba."; +"TIMED_WALK_QUESTION_TEXT" = "¿Usas una órtesis para pie y tobillo?"; +"TIMED_WALK_QUESTION_2_TITLE" = "¿Usas un dispositivo de ayuda?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Toca aquí para elegir la respuesta."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ninguno"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Bastón unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Muleta unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bastón bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Muleta bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Andador (con o sin ruedas)"; +"TIMED_WALK_INSTRUCTION_%@" = "Camina hasta %@ en línea recta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Da vuelta."; +"TIMED_WALK_INSTRUCTION_2" = "Camina al punto de inicio."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Toca Siguiente al terminar."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "La prueba de la adición auditiva consecutiva ritmada (PASAT) mide tu capacidad de cálculo y velocidad de procesamiento de información auditiva."; +"PVSAT_INTRO_TEXT" = "La prueba de la adición visual consecutiva ritmada (PVSAT) mide tu capacidad de cálculo y velocidad de procesamiento de información visual."; +"PAVSAT_INTRO_TEXT" = "La prueba de la adición audiovisual consecutiva ritmada (PAVSAT) mide tu capacidad de cálculo y velocidad de procesamiento de información auditiva y visual."; +"PSAT_INTRO_TEXT_2_%@" = "Los números individuales se presentan cada %@.\nDebes agregar uno nuevo al que sea inmediatamente anterior.\nEs importante señalar que no debes calcular un total al correr; sólo la suma de los últimos dos números."; +"PSAT_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"PSAT_INITIAL_INSTRUCTION" = "Recuerda este primer dígito."; +"PSAT_INSTRUCTION" = "Agrega este nuevo dígito al anterior."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Prueba de las %@ estacas"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Esta actividad mide la funcionalidad de tus extremidades superiores pidiéndote que coloques una estaca en un hoyo. Se te pedirá que hagas esto %@ veces."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Se evaluarán tus dos manos.\nDebes recoger la estaca lo más rápido posible, colocarla en el hoyo y, después de repetirlo %@ veces, volver a sacarla %@ veces."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Se evaluarán tus dos manos.\nDebes recoger la estaca lo más rápido posible, colocarla en el hoyo y, después de repetirlo %@ veces, volver a sacarla %@ veces."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Coloca la estaca en el hoyo usando tu mano izquierda."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Coloca la estaca en el hoyo usando tu mano derecha."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Coloca la estaca detrás de la línea usando tu mano izquierda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Coloca la estaca detrás de la línea usando tu mano derecha."; +"HOLE_PEG_TEST_TEXT" = "Recoge la estaca con dos dedos."; +"HOLE_PEG_TEST_TEXT_2" = "Levanta los dedos para soltar la estaca."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Medición de temblor de manos"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Esta actividad mide cuánto tiemblan tus manos en varias posiciones. Busca un lugar en donde te puedas sentar cómodamente durante esta actividad."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Agarra el teléfono con tu mano más afectada como se muestra en la imagen."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Agarra el teléfono con tu mano derecha como se muestra en la imagen."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Agarra el teléfono con tu mano izquierda como se muestra en la imagen."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Se te pedirá que realices %@ mientras estás sentado con el teléfono en la mano."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "una tarea"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dos tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tres tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "cuatro tareas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinco tareas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Toca Siguiente para continuar."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepárate para sostener el teléfono sobre tu pierna."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepárate para sostener el teléfono sobre tu pierna con tu mano izquierda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepárate para sostener el teléfono sobre tu pierna con tu mano derecha."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Sigue sosteniendo el teléfono sobre tu pierna por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Ahora agarra el teléfono con la mano extendida a la altura de los hombros."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Ahora agarra el teléfono con tu mano izquierda extendida a la altura de los hombros."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Ahora agarra el teléfono con tu mano derecha extendida a la altura de los hombros."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Sigue sosteniendo el teléfono con tu mano extendida por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Ahora agarra el teléfono a la altura de los hombros con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Ahora agarra el teléfono con tu mano izquierda a la altura de los hombros con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Ahora agarra el teléfono con tu mano derecha a la altura de los hombros con el codo doblado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Sigue sosteniendo el teléfono con tu codo doblado por %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Ahora, aún con el codo doblado, acerca y toca el teléfono con tu nariz varias veces."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Ahora, aún con el codo doblado y sosteniendo el teléfono con tu mano izquierda, acerca y toca el teléfono con tu nariz varias veces."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Ahora, aún con el codo doblado y sosteniendo el teléfono con tu mano derecha, acerca y toca el teléfono con tu nariz varias veces."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Sigue acercando y tocando el teléfono con tu nariz por %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepárate para hacer un gesto de saludo (girando la muñeca)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepárate para hacer un gesto de saludo (girando la muñeca) con tu teléfono en la mano izquierda."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepárate para hacer un gesto de saludo (girando la muñeca) con tu teléfono en la mano derecha."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Sigue haciendo un gesto de saludo por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Ahora cambia el teléfono a tu mano izquierda y pasa a la siguiente tarea."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Ahora cambia el teléfono a tu mano derecha y pasa a la siguiente tarea."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Pasa a la siguiente tarea."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Actividad completada."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Se te pedirá que realices %@ mientras estás sentado, primero con el teléfono en una mano y luego en la otra."; +"TREMOR_SKIP_LEFT_HAND" = "No puedo realizar esta actividad con mi mano izquierda."; +"TREMOR_SKIP_RIGHT_HAND" = "No puedo realizar esta actividad con mi mano derecha."; +"TREMOR_SKIP_NEITHER" = "Puedo realizar esta actividad con las dos manos."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Prueba de seguimiento"; +"TRAILMAKING_INTENDED_USE" = "Esta actividad evalúa la capacidad de atención visual y de cambio de tareas al registrar el tiempo necesario para tocar una serie de puntos en orden."; +"TRAILMAKING_INTENDED_USE2_A" = "Cuando termine la cuenta regresiva, toca los puntos alternando entre los números y las letras. Empieza con el primer número '1' seguido de los números 2', ’3’, ’4’, etc. hasta llegar a '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "Cuando termine la cuenta regresiva, toca los puntos alternando entre los números y las letras. Empieza con el primer número '1' seguido de la primera letra 'A', luego '2' y ’B’, después ’3’ y ’C’, y así sucesivamente hasta llegar a '7'."; +"TRAILMAKING_INTRO_TEXT" = "Hazlo lo más rápido que puedas sin equivocarte. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconocimiento de voz"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Esta actividad graba tu voz con el micrófono ubicado en la parte inferior de tu dispositivo y luego la transcribe."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Toca Empezar para comenzar."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Presiona el botón para empezar a grabar antes de hablar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Iniciar grabación"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Detener grabación"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Editar transcripción"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Corrige la transcripción si hay errores."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Tu transcripción aparecerá aquí."; +"SPEECH_RECOGNITION_FAILED" = "Error de reconocimiento de voz."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Error al iniciar el reconocimiento de voz."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproducir audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Detener audio"; +"SPEECH_IN_NOISE_TITLE" = "Voz con ruido"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Esta actividad mide la inteligibilidad de la voz en entornos ruidosos."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "En esta prueba:\n\nEscucharás una oración.\n\nRepite claramente lo que escuchaste o escríbelo utilizando el teclado. \n\nSi lo repites, podrás modificar la transcripción generada por el sistema de reconocimiento de voz."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibración del volumen"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Toca \"Reproducir audio\", ajusta el volumen a un nivel cómodo y luego toca \"Detener audio\" para continuar."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Escuchar"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Se reproducirá sólo una vez una oración con ruido de fondo con una relación señal/ruido (SNR) aleatoria."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Habla"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repite lo que escuchaste."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "No se pudo crear el archivo"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "No se pudo eliminar suficientes registros para alcanzar el umbral"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Error al definir el atributo"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "El archivo no se marcó como eliminado (no se marcó como cargado)"; +"ERROR_DATALOGGER_MULTIPLE" = "Varios errores al eliminar registros"; +"ERROR_RECORDER_NO_DATA" = "Datos recopilados no encontrados."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Directorio de salida no especificado"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Sonómetro"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Esta actividad mide el nivel de presión sonora ambiental. No podrás continuar si los niveles de ruido son demasiado altos. Ve a un lugar más callado para completar esta tarea, o reanuda esta actividad más tarde."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculando"; +"ENVIRONMENTSPL_THRESHOLD" = "Umbral: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Ruido ambiental aceptable"; +"ENVIRONMENTSPL_NOISE" = "Hay demasiado ruido ambiental"; +"ENVIRONMENTSPL_TITLE_2" = "Encuentra un lugar silencioso"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Para asegurar la precisión, este estudio se debe tomar en un entorno silencioso."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Comenzar tarea"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Sin datos"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Desliza el interruptor para ingresar el valor"; +"SLIDER_I_DONT_KNOW" = "No sé"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Página"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Atrás"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostrar miniatura de PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ocultar miniatura de PDF"; +"AX_BUTTON_ANNOTATE" = "Anotar"; +"AX_BUTTON_SHOW_SEARCH" = "Mostrar barra de búsqueda"; +"AX_BUTTON_HIDE_SEARCH" = "Ocultar barra de búsqueda"; +"AX_BUTTON_SHARE" = "Compartir"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustración de una marca de verificación en un círculo azul que representa el éxito"; + +"AX_SIGNVIEW_LABEL" = "Campo para firma"; +"AX_SIGNVIEW_HINT" = "Usa tu dedo para firmar la pantalla"; +"AX_SIGNVIEW_SIGNED" = "Firmado"; +"AX_SIGNVIEW_UNSIGNED" = "Sin firmar"; + +"AX_SELECTED" = "Elemento seleccionado"; +"AX_UNSELECTED" = "No seleccionado"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECCIONA TODO LO QUE APLIQUE"; + +"AX_SLIDER_LABEL" = "Regulador de respuesta. Rango de %@ a %@"; +"AX_UNLABELED_IMAGE" = "Imagen sin etiqueta"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Comenzar tarea"; + +"AX.MEMORY.TILE.ACTIVE" = "activa"; +"AX.MEMORY.TILE.CORRECT" = "correcto"; +"AX.MEMORY.TILE.INCORRECT" = "incorrecto"; +"AX.MEMORY.TILE.QUIESCENT" = "sin actividad"; +"AX.MEMORY.TILE.LABEL" = "Cuadro del juego de memoria"; + +"AX_IMAGE_CAPTURE_LABEL" = "Previsualización de captura"; +"AX_IMAGE_CAPTURED_LABEL" = "Imagen capturada"; + +"AX_VIDEO_CAPTURE_LABEL" = "Previsualización de captura de video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captura de video completada"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "No se puede colocar un disco de tamaño %@ sobre otro de tamaño %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Destino"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Toca dos veces para colocar el disco"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Toca dos veces para seleccionar el disco de hasta arriba."; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Tiene discos de tamaño %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vacía"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Ocultar teclado"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Rango de %@ a %@"; +"AX_GRAPH_STACK_PREFIX" = "Pila compuesta de"; +"AX_GRAPH_AND_SEPARATOR" = " y "; +"AX_GRAPH_POINT_%@" = "Punto: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Onda de voz"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Cuando inicie la grabación, actívalo otra vez para detener la grabación."; + +"AX_AUDIO_BAR_GRAPH" = "Gráfica de barras de audio"; + +"AX_AMSLER_GRID_LABEL" = "Cuadrícula de Amsler"; +"AX_AMSLER_GRID_HINT" = "Usa tu dedo o lápiz óptico para marcar la cuadrícula, o desliza a la izquierda afuera de la cuadrícula para finalizar."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Botones para tocar"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Toca para el oído izquierdo"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activa para comenzar la prueba. Tras comenzarla, toca directamente este botón cuando escuches un sonido en tu oído izquierdo."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Toca para el oído derecho"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activa para comenzar la prueba. Tras comenzarla, toca directamente este botón cuando escuches un sonido en tu oído derecho."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Usando VoiceOver, explora la pantalla al tocar dónde se ubican los botones para cada oído. Cuando la prueba inicie, los botones se podrán tocar directamente.%@"; +"AX_TAP_BUTTON_1_LABEL" = "Toque para un dedo"; +"AX_TAP_BUTTON_2_LABEL" = "Toca para otro dedo"; +"AX_TAP_BUTTON_HINT" = "Activa para que los botones se puedan tocar directamente."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Usando VoiceOver, explora la pantalla al tocar dónde se ubican los botones. Activa cualquier botón para que se puedan tocar directamente."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Los botones ahora se pueden tocar directamente."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Usando VoiceOver, se podrá tocar el botón y estará ubicado cerca del centro de la pantalla."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Usando VoiceOver, los botones de la prueba se podrán tocar directamente."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "No se puede decodificar restoreData para la inicialización"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7713777 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/es_419.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d errores) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.strings new file mode 100755 index 0000000..555fff7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Suostumus"; +"CONSENT_NAME_GIVEN" = "Etunimi"; +"CONSENT_NAME_FAMILY" = "Sukunimi"; +"CONSENT_NAME_PLACEHOLDER" = "Vaaditaan"; +"CONSENT_REVIEW_TITLE" = "Tarkasta"; +"CONSENT_REVIEW_INSTRUCTION" = "Tarkasta alla oleva lomake ja napauta ”Hyväksy”, jos olet valmis jatkamaan."; +"CONSENT_REVIEW_ALERT_TITLE" = "Tarkasta"; +"CONSENT_SIGNATURE_TITLE" = "Allekirjoitus"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Allekirjoita sormellasi alla olevaan laatikkoon."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Allekirjoitus tähän"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Sivu %1$ld / %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Tervetuloa"; +"CONSENT_SECTION_DATA_GATHERING" = "Tietojen kerääminen"; +"CONSENT_SECTION_PRIVACY" = "Tietosuoja"; +"CONSENT_SECTION_DATA_USE" = "Tietojen käyttö"; +"CONSENT_SECTION_STUDY_SURVEY" = "Tutkimuskysely"; +"CONSENT_SECTION_STUDY_TASKS" = "Tutkimustehtävät"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Ajankäyttö"; +"CONSENT_SECTION_WITHDRAWING" = "Peruuttaminen"; +"CONSENT_LEARN_MORE_TITLE" = "Lisätietoja"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Lisätietoja tietojen keräämisestä"; +"LEARN_MORE_DATA_USE" = "Lisätietoja tietojen käytöstä"; +"LEARN_MORE_PRIVACY" = "Lisätietoja siitä, kuinka yksityisyyttäsi ja identiteettiäsi suojataan."; +"LEARN_MORE_WELCOME" = "Lisätietoja tutkimuksesta"; +"LEARN_MORE_STUDY_SURVEY" = "Lisätietoja tutkimuskyselystä"; +"LEARN_MORE_TIME_COMMITMENT" = "Lisätietoja tutkimuksen vaatimasta ajasta"; +"LEARN_MORE_TASKS" = "Lisätietoja tutkimukseen liittyvistä tehtävistä"; +"LEARN_MORE_WITHDRAWING" = "Lisätietoja peruuttamisesta"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Jakovalinnat"; +"CONSENT_SHARE_WIDELY_%@" = "Jaa datani kohteen %@ ja hyväksyttyjen tutkijoiden kanssa maailmanlaajuisesti"; +"CONSENT_SHARE_ONLY_%@" = "Jaa datani vain kohteen %@ kanssa"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ vastaanottaa tutkimusdatasi tästä tutkimuksesta.\n\nKoodatun tutkimusdatan jakaminen laajemmalle käyttäjäkunnalle (ilman nimeä ym. tietoja) voi edesauttaa tätä ja tulevia tutkimuksia."; +"LEARN_MORE_CONSENT_SHARING" = "Lisätietoja datajaosta"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nimi painokirjaimin"; +"CONSENT_DOC_LINE_SIGNATURE" = "Allekirjoitus"; +"CONSENT_DOC_LINE_DATE" = "Päivämäärä"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ / %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Kysymys %1$@/%2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Ohitettu"; +"REVIEW_EDIT_ANSWER" = "Muokkaa"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Virheellinen arvo"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ ylittää sallitun enimmäisarvon (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ on alle sallitun vähimmäisarvon (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ ei ole kelvollinen arvo."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Virheellinen sähköpostiosoite: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Syötä osoite"; +"LOCATION_ERROR_TITLE" = "Määritettyä osoitetta ei löydy"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Nykyistä sijaintiasi ei voida määrittää. Kirjoita osoite tai, jos mahdollista, siirry paikkaan, jossa GPS-signaali on parempi."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Sijaintipalveluiden käyttö on kielletty. Anna Asetuksissa tälle ohjelmalle oikeus käyttää Sijaintipalveluita."; +"LOCATION_ERROR_GEOCODE" = "Syötetyllä osoitteella ei löydy tuloksia. Varmista, että osoite on oikein."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Joko et ole yhteydessä internetiin tai olet ylittänyt osoitehakupyyntöjen enimmäismäärän. Jos et ole yhteydessä internetiin, laita Wi-Fi päälle vastataksesi tähän kysymykseen, ohita tämä kysymys (jos ohituspainike on käytettävissä), tai palaa kyselyyn, kun olet internet-yhteydessä. Muussa tapauksessa yritä muutaman minuutin päästä uudelleen."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Tekstisisältö ylittää maksimipituuden: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera ei ole käytettävissä jaetulla näytöllä."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Sähköposti"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Salasana"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Syötä salasana"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Vahvista"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Syötä salasana uudelleen"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Salasanat eivät täsmää."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Lisätietoja"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Sukupuoli"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Valitse sukupuoli"; +"DOB_FORM_ITEM_TITLE" = "Syntymäaika"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Valitse päiväys"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Puhelinnumero"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Vahvistus"; +"VERIFICATION_STEP_TITLE" = "Vahvista sähköpostisi"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Napauta alla olevaa linkkiä, jos et saanut vahvistussähköpostia ja haluat, että se lähetetään uudelleen."; +"RESEND_EMAIL_BUTTON_TITLE" = "Lähetä uusi vahvistussähköposti"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Kirjaudu sisään"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Unohditko salasanan?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Syötä pääsykoodi"; +"PASSCODE_CONFIRM_MESSAGE" = "Vahvista pääsykoodi"; +"PASSCODE_SAVED_MESSAGE" = "Pääsykoodi tallennettu"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Pääsykoodi todennettu"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Syötä vanha pääsykoodi"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Syötä uusi pääsykoodi"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Vahvista uusi pääsykoodi"; +"PASSCODE_INVALID_ALERT_TITLE" = "Virheellinen pääsykoodi"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Pääsykoodit eivät täsmää. Yritä uudelleen."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Tunnistaudu Touch ID:llä"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID -virhe"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Vain numerot ovat sallittuja."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Pääsykoodin syötön edistymisen osoitin"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ merkkiä yhteensä %@ merkistä syötetty"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Unohditko pääsykoodin?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Avainnipun kohdetta ei voitu lisätä."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Avainnipun kohdetta ei voitu päivittää."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Avainnipun kohdetta ei voitu poistaa."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Avainnipun kohdetta ei löydy."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tyyppi I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tyyppi II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tyyppi III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tyyppi IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tyyppi V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tyyppi VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Nainen"; +"GENDER_MALE" = "Mies"; +"GENDER_OTHER" = "Muu"; + +/* Boolean answer strings */ +"BOOL_NO" = "Ei"; +"BOOL_YES" = "Kyllä"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "vasen"; +"LIMB_RIGHT" = "oikea"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Vastaa napauttamalla"; +"NULL_ANSWER" = "Valitse vastaus"; +"PLACEHOLDER_IMAGE_CHOICES" = "Valitse napauttamalla"; +"PLACEHOLDER_LONG_TEXT" = "Kirjoita napauttamalla"; + +/* Button titles */ +"BUTTON_AGREE" = "Hyväksy"; +"BUTTON_CANCEL" = "Kumoa"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Tyhjennä"; +"BUTTON_CLEAR_SIGNATURE" = "Poista allekirjoitus"; +"BUTTON_APPLY" = "Käytä"; +"BUTTON_DISAGREE" = "Hylkää"; +"BUTTON_DONE" = "Valmis"; +"BUTTON_GET_STARTED" = "Aloita"; +"BUTTON_LEARN_MORE" = "Lisätietoja"; +"BUTTON_NEXT" = "Seuraava"; +"BUTTON_SKIP" = "Ohita"; +"BUTTON_SKIP_QUESTION" = "Ohita tämä kysymys"; +"BUTTON_START_TIMER" = "Käynnistä ajastin"; +"BUTTON_OPTION_SAVE" = "Jatka tästä myöhemmin"; +"BUTTON_OPTION_DISCARD" = "Hylkää tulokset"; +"BUTTON_OPTION_STOP_TASK" = "Lopeta tehtävä"; +"BUTTON_SAVE" = "Tallenna"; +"BUTTON_CLEAR_ANSWER" = "Tyhjennä vastaus"; +"BUTTON_READ_ONLY_MODE" = "Tätä vastausta ei voida muuttaa."; +"BUTTON_COPYRIGHT" = "Tekijänoikeudet"; +"BUTTON_CLOSE" = "Sulje"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Aktiviteetti alkaa"; +"TASK_COMPLETE_TITLE" = "Aktiviteetti valmis"; +"TASK_COMPLETE_TEXT" = "Datasi analysoidaan ja sinulle ilmoitetaan, kun tuloksesi ovat valmiina."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ jäljellä."; +"TOUCH_ANYWHERE_LABEL" = "Jatka koskettamalla mihin tahansa"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Kaappaa kuva"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Kaappaa kuva uudelleen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Kameraa ei löydy. Tätä vaihetta ei voida suorittaa."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Jotta tämä vaihe voidaan suorittaa, anna Asetuksissa tälle ohjelmalle käyttöoikeus kameraan."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Kaapatuille kuville ei ole määritetty kohdehakemistoa."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Kaapattua kuvaa ei voitu tallentaa."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Aloita tallentaminen"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Lopeta tallentaminen"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Kaappaa video uudelleen"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kuntoilu"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Matka (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Syke (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Istu %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Kävele niin nopeasti kuin voit %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Tämä aktiviteetti seuraa sykettäsi ja mittaa kuinka kauas voit kävellä, kun aikaa on %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Kävele ulkona kovinta mahdollista vauhtia %1$@. Kun olet valmis, istu ja lepää %2$@. Aloita napauttamalla Aloita."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Askeleet ja tasapaino"; +"WALK_INTRO_TEXT" = "Tämä aktiviteetti arvioi askellustasi ja tasapainoasi, kun kävelet tasaisesti ja seisot. Älä jatka, jos et pysty turvallisesti kävelemään avustamatta."; +"WALK_INTRO_2_TEXT_%ld" = "Etsi paikka, jossa voit turvallisesti kävellä avustamatta noin %ld askelta suoraan."; +"WALK_INTRO_2_DETAIL" = "Laita laite taskuun tai laukkuun ja seuraa ääniohjeita."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Seiso nyt paikoillaan %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Seiso paikoillaan %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Käänny ympäri ja kävele takaisin alkupisteeseen."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Kävele enintään %ld askelta suoraan."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Etsi paikka, jossa voit turvallisesti kävellä suoraa reittiä edestakaisin. Yritä kävellä jatkuvasti kääntyen reitin päissä ikään kuin kiertäisit liikenteenohjainta.\n\nSeuraavaksi sinua pyydetään kääntymään ympäri täysi kierros, ja sitten seisomaan paikallasi kädet sivuilla ja jalat noin hartianleveyden etäisyydellä toisistaan."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Kun olet valmis, napauta Aloita.\nLaita sitten laite taskuun tai laukkuun ja seuraa ääniohjeita."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Kävele suoraa reittiä edestakaisin %@. Kävele, kuten kävelisit tavallisesti."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Käänny kokonaan ympäri ja seiso paikallasi %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Aktiviteetti on suoritettu."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Napautusnopeus"; +"TAPPING_TASK_TITLE_RIGHT" = "Oikea käsi"; +"TAPPING_TASK_TITLE_LEFT" = "Vasen käsi"; +"TAPPING_INTRO_TEXT" = "Tämä aktiviteetti mittaa napautusnopeuttasi."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Laita laite tasaiselle alustalle."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Käytä saman käden kahta sormea näytön painikkeiden napauttamiseen vuorotellen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Käytä oikean käden kahta sormea näytön painikkeiden napauttamiseen vuorotellen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Käytä vasemman käden kahta sormea näytön painikkeiden napauttamiseen vuorotellen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Suorita nyt sama testi oikealla kädellä."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Suorita nyt sama testi vasemmalla kädellä."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Napauta yhtä sormea ja sitten toista. Yritä ajoittaa napautukset mahdollisimman tasaisesti. Napauttele %@."; +"TAPPING_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Aloita napauttamalla Seuraava."; +"TAP_BUTTON_TITLE" = "Napauta"; +"TOTAL_TAPS_LABEL" = "Napautuksia yhteensä"; +"TAPPING_INSTRUCTION" = "Napauta painikkeita niin tasaisesti kuin pystyt kahdella sormella."; +"TAPPING_INSTRUCTION_RIGHT" = "Napauta painikkeita OIKEALLA kädellä."; +"TAPPING_INSTRUCTION_LEFT" = "Napauta painikkeita VASEMMALLA kädellä."; +"TAPPING_SKIP_TITLE" = "Ohita tämä käsi"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amslerin ruudukko"; +"AMSLER_GRID_INTRO_TEXT" = "Tämä aktiviteetti auttaa havaitsemaan ongelmia käyttäjän näössä."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Pidä laitetta noin 30 cm päässä kasvoistasi ja silmän korkeudella koko testin ajan."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Sulje %@ ja tuijota neliöruudukon keskellä olevaa pistettä.\n\nMerkitse sormella tai kynällä kaikki näkemäsi vääristymät, esim. epäselvät tai aaltoilevat viivat.\n\nKun olet valmis, pyyhkäise vasemmalle ruudukon ulkopuolelta."; +"AMSLER_GRID_LEFT_EYE" = "vasen silmä"; +"AMSLER_GRID_RIGHT_EYE" = "oikea silmä"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Ääni"; +"AUDIO_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"AUDIO_INSTRUCTION" = "Sano ”aaa” mikrofoniin niin kauan kuin voit."; +"AUDIO_INTRO_TEXT" = "Hengitä syvään ja sano \”Aaaaa\” mikrofoniin niin pitkään kuin pystyt. Pidä äänenvoimakkuus tasaisena siten, että äänipalkit pysyvät sinisinä."; +"AUDIO_INTENDED_USE" = "Tämä aktiviteetti arvioi ääntäsi tallentamalla sitä laitteen alareunassa olevalla mikrofonilla."; +"AUDIO_TOO_LOUD_LABEL" = "Liian kovaa"; +"AUDIO_GENERIC_ERROR_LABEL" = "Ei voida äänittää"; +"AUDIO_LEVEL_CHECK_LABEL" = "Odota, taustamelun tasoa tarkistetaan."; +"AUDIO_TOO_LOUD_MESSAGE" = "Ympäristön melutaso on liian korkea, jotta ääntäsi voitaisiin tallentaa. Siirry hiljaisempaan paikkaan ja yritä uudelleen."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Napauta Seuraava, kun olet valmis."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Tämä aktiviteetti mittaa kykyäsi kuulla erilaisia ääniä."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Ennen kuin aloitat, liitä kuulokkeet ja laita ne päälle.\n\nÄäni on hyvin huomaamaton ja erilainen kuin tavalliset merkkiäänet. Ääni alkaa hiljaisena ja vahvistuu sitten. Ole tarkkaavainen ja napauta vasenta tai oikeaa painiketta riippuen siitä, kummalla korvalla kuulet äänen."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Sinun pitäisi nyt kuulla ääni. Säädä voimakkuutta laitteen sivussa olevilla säätimillä.\n\nNapauta jotakin painiketta kun olet valmis aloittamaan."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Kun kuulet äänen, napauta vasenta tai oikeaa painiketta riippuen siitä, kummalla korvalla kuulet äänen."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Vasen korva"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Oikea korva"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, vasen"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, oikea"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Napauta, kun kuulet äänen."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ääni ja äänenvoimakkuus"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Kuulet sarjan ääniä."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Kun kuulet äänen, napauta painiketta."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Tälle testille äänenvoimakkuus asetetaan 50 prosenttiin."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Tämä testi kestää noin 10 minuuttia."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Laita Älä häiritse -toiminto päälle keskeytysten välttämiseksi."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Äänet toistetaan ensin oikeaan korvaan."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Äänet toistetaan nyt vasempaan korvaan."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Tämä aktiviteetti mittaa henkilön kuulon kynnystasoja dB HL -asteikolla."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Varmista, että laitteen äänenvoimakkuus on asetettu suurimpaan arvoonsa.\n\nTämän tehtävän aikana hiljainen ääni toistetaan joko vasempaan tai oikeaan korvaan.\n\nKuuntele tarkasti ja napauta painiketta aina, kun kuulet äänen."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Tämä testi määrittää, kuinka kova äänen täytyy olla, jotta kuulet sen."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Aloituskysely."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Valitse ”parempi korva”, jos tarpeen"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "vasen"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "oikea"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ei asetusta"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Testi kumottu"; +"dBHL_ALERT_TITLE_START_OVER" = "Aloita alusta"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Kumoa testi"; +"dBHL_ALERT_TEXT" = "Liitä AirPods- tai EarPods-kuulokkeet testin suorittamista varten."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ suoritettu"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Kuulokkeet"; +"HEADPHONES_UNKNOWN" = "Tuntematon"; +"HEADPHONES_NONE" = "Ei mitään"; +"CONNECTED" = "Yhdistetty"; +"NOT_CONNECTED" = "Ei yhteydessä"; +"HEADPHONE_CONNECTED_%@" = "Yhdistetty – %@"; +"HEADPHONE_DETECT_TITLE" = "Liitä kuulokkeet"; +"HEADPHONE_DETECT_TEXT" = "Tämä testi vaatii Apple AirPods- tai Apple EarPods -kuulokkeet"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Avaruudellinen muisti"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Tämä aktiiviteetti mittaa lyhytaikaista avaruudellista muistiasi. Toista järjestys, jossa %@ syttyy."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "kukkia"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "kukkia"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Näet yksi kerrallaan syttyviä %@. Napauta %@ samassa järjestyksessä kuin ne syttyivät."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Näet yksi kerrallaan syttyviä %@. Napauta %@ käänteisessä syttymisjärjestyksessä."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Aloita napauttamalla Aloita ja katso tarkasti."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Tulos"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Katso %@, kun niihin syttyy valo."; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Napauta %@ siinä järjestyksessä, kun ne syttyivät"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Napauta %@ käänteisessä järjestyksessä"; +"MEMORY_GAME_COMPLETE_TITLE" = "Jakso valmis"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Jatka napauttamalla Seuraava"; +"MEMORY_GAME_FAILED_TITLE" = "Yritä uudelleen"; +"MEMORY_GAME_FAILED_MESSAGE" = "Et onnistunut tällä kertaa. Jatka napauttamalla Seuraava."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Aika loppui"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Aika loppui.\nJatka napauttamalla Seuraava."; +"MEMORY_GAME_COMPLETE" = "Peli päättyi"; +"MEMORY_GAME_PAUSED_TITLE" = "Keskeytetty"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Jatka napauttamalla Seuraava"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Muisti-aktiviteetti on kehitetty University of California, San Franciscon PhD Katherine Possinin ja PhD Joel Kramerin avustuksella."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaktioaika"; +"REACTION_TIME_TASK_INTENDED_USE" = "Tämä aktiviteetti mittaa aikaa, joka sinulta kuluu vastata visuaaliseen tapahtumaan."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Ravista laitetta mihin tahansa suuntaan heti, kun sininen piste tulee näkyviin. Sinua pyydetään tekemään tämä %D kertaa."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Yritys %@ / %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Kun sininen ympyrä tulee näkyviin, ravista nopeasti laitetta"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Kun sana tulee näkyviin, valitse näytettävän VÄRIN nimen ensimmäinen kirjain."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Kun olet valmis aloittamaan Stroop-aktiviteetin, napauta Aloita."; +"STROOP_TASK_STEP_TEXT" = "Valitse näytettävän VÄRIN nimen ensimmäinen kirjain."; +"STROOP_COLOR_RED" = "PUNAINEN"; +"STROOP_COLOR_GREEN" = "VIHREÄ"; +"STROOP_COLOR_BLUE" = "SININEN"; +"STROOP_COLOR_YELLOW" = "KELTAINEN"; +"STROOP_COLOR_RED_INITIAL" = "P"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "S"; +"STROOP_COLOR_YELLOW_INITIAL" = "K"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanoin torni"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Tämä aktiviteetti arvioi ongelmanratkaisukykyä."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Siirrä koko pino korostetulle alustalle mahdollisimman vähillä siirroilla."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Ratkaise tehtävä"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Siirtojen määrä: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "En osaa ratkaista tätä tehtävää"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Liikeulottuvuus"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption on oltava vasen tai oikea"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Vasemman polven liikealue"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Oikean polven liikealue"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Tämä aktiviteetti mittaa kuinka pitkälle voit ojentaa vasemman polvesi."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Tämä aktiviteetti mittaa kuinka pitkälle voit ojentaa oikean polvesi."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Istu tuolin reunalle. Aloitettaessa laite asetetaan mittausta varten vasemmalle polvelle. Laita laitteesi ääni päälle, jotta kuulet ohjeet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Istu tuolin reunalle. Aloitettaessa laite asetetaan mittausta varten oikealle polvelle. Laita laitteesi ääni päälle, jotta kuulet ohjeet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Aseta laite vasemmalle polvelle näyttö ulospäin, kuten kuvassa."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Aseta laite oikealle polvelle näyttö ulospäin, kuten kuvassa."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Kun olet valmis, aloita napauttamalla näyttöä ja nosta vasen polvi niin ylös kuin mahdollista. Palaa aloitusasentoon ja napauta uudelleen, kun olet valmis."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Kun olet valmis, aloita napauttamalla näyttöä ja nosta oikea polvi niin ylös kuin mahdollista. Palaa aloitusasentoon ja napauta uudelleen, kun olet valmis."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Aseta laite vasemmalle polvelle. Napauta näyttöä ja suorista vasenta polvea niin pitkälle kuin mahdollista."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Aseta laite oikealle polvelle. Napauta näyttöä ja suorista oikeaa polvea niin pitkälle kuin mahdollista."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Kun olet valmis, palauta vasen polvi lähtöasentoon. Napauta sitten missä tahansa."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Kun olet valmis, palauta oikea polvi aloitusasentoon. Napauta sitten missä tahansa."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Vasemman olkapään liikealue"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Oikean olkapään liikealue"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Tämä aktiviteetti mittaa kuinka pitkälle voit ojentaa vasemman olkapääsi."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Tämä aktiviteetti mittaa kuinka pitkälle voit ojentaa oikean olkapääsi."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Aloitettaessa laite asetetaan mittausta varten vasemmalle olkapäälle. Laita laitteesi ääni päälle, jotta kuulet ohjeet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Aloitettaessa laite asetetaan mittausta varten oikealle olkapäälle. Laita laitteesi ääni päälle, jotta kuulet ohjeet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Aseta laite vasemmalle olkapäälle näyttö ulospäin, kuten kuvassa."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Aseta laite oikealle olkapäälle näyttö ulospäin, kuten kuvassa."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Kun olet valmis, aloita napauttamalla näyttöä ja nosta vasen käsi niin ylös kuin mahdollista. Palaa aloitusasentoon ja napauta uudelleen, kun olet valmis."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Kun olet valmis, aloita napauttamalla näyttöä ja nosta oikea käsi niin ylös kuin mahdollista. Palaa aloitusasentoon ja napauta uudelleen, kun olet valmis."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Aseta laite vasemmalle olkapäälle. Napauta näyttöä ja nosta vasen käsi eteen niin kauas kuin mahdollista."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Aseta laite oikealle olkapäälle. Napauta näyttöä ja nosta oikea käsi eteen niin kauas kuin mahdollista."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Kun olet valmis, palauta vasen käsi lähtöasentoon. Napauta sitten missä tahansa."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Kun olet valmis, palauta oikea käsi lähtöasentoon. Napauta sitten missä tahansa."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Ajoitettu kävely"; +"TIMED_WALK_INTRO_DETAIL" = "Tämä aktiviteetti mittaa alaraajojen toimintaa."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Etsi mieluiten ulkoa paikka, jossa voit turvallisesti kävellä suoraan noin %@ niin nopeasti kuin mahdollista. Älä hidasta ennen kuin olet ylittänyt maaliviivan."; +"TIMED_WALK_INTRO_2_DETAIL" = "Aloita napauttamalla Seuraava."; +"TIMED_WALK_FORM_TITLE" = "Apuväline"; +"TIMED_WALK_FORM_TEXT" = "Käytä samaa apuvälinettä kaikissa testeissä."; +"TIMED_WALK_QUESTION_TEXT" = "Käytätkö nilkkatukea?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Käytätkö apuvälinettä?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Valitse vastaus napauttamalla tähän."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ei mitään"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Yksi kävelykeppi"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Yksi kainalosauva"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Kaksi kävelykeppiä"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Kaksi kainalosauvaa"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Kävelytuki/rollaattori"; +"TIMED_WALK_INSTRUCTION_%@" = "Kävele %@ suoraan."; +"TIMED_WALK_INSTRUCTION_TURN" = "Käänny ympäri."; +"TIMED_WALK_INSTRUCTION_2" = "Kävele takaisin alkupisteeseen."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Kun se on tehty, napauta Seuraava."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT-testi (Paced Auditory Serial Addition Test) mittaa kuullun informaation käsittelynopeuttasi ja laskutaitoasi."; +"PVSAT_INTRO_TEXT" = "PVSAT-testi (Paced Visual Serial Addition Test) mittaa nähdyn informaation käsittelynopeuttasi ja laskutaitoasi."; +"PAVSAT_INTRO_TEXT" = "PAVSAT-testi (Paced Auditory and Visual Serial Addition Test) mittaa kuullun ja nähdyn informaation käsittelynopeuttasi ja laskutaitoasi."; +"PSAT_INTRO_TEXT_2_%@" = "Yksittäisten numeroiden välillä kuluu %@.\nKukin uusi numero on lisättävä sitä edeltäneeseen.\nHuomaa, että ei ole tarkoitus laskea jatkuvaa summaa, vaan vain kahden viimeisen numeron summa."; +"PSAT_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"PSAT_INITIAL_INSTRUCTION" = "Muista tämä ensimmäinen numero."; +"PSAT_INSTRUCTION" = "Lisää tämä uusi numero edelliseen."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@ reiän palikkatesti"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Tämä aktiviteetti mittaa yläraajojen toimintaa pyytämällä sinua asettamaan palikan reikään. Tämä toistetaan %@ kertaa."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Sekä vasen että oikea käsi testataan.\nSinun on poimittava palikka mahdollisimman nopeasti, asetettava se reikään, ja tehtyäsi tämän %@ kertaa, poistettava se jälleen %@ kertaa."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Sekä oikea että vasen käsi testataan.\nSinun on poimittava palikka mahdollisimman nopeasti, asetettava se reikään, ja tehtyäsi tämän %@ kertaa, poistettava se jälleen %@ kertaa."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Laita palikka reikään vasemmalla kädellä."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Laita palikka reikään oikealla kädellä."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Laita palikka viivan taakse vasemmalla kädellä."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Laita palikka viivan taakse oikealla kädellä."; +"HOLE_PEG_TEST_TEXT" = "Poimi palikka kahdella sormella."; +"HOLE_PEG_TEST_TEXT_2" = "Pudota palikka nostamalla sormia."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Vapina-aktiviteetti"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Tämä aktiviteetti mittaa käsiesi vapinaa eri asennoissa. Etsi paikka, jossa voit istua mukavasti tämän aktiviteetin keston ajan."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Pidä puhelinta alla olevan kuvan mukaisesti kädessä, jossa vaikutus on voimakkaampi."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Pidä puhelinta alla olevan kuvan mukaisesti OIKEASSA kädessä."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Pidä puhelinta alla olevan kuvan mukaisesti VASEMMASSA kädessä."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Sinua pyydetään suorittamaan %@ puhelin kädessä istuen."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "tehtävä"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "kaksi tehtävää"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "kolme tehtävää"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "neljä tehtävää"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "viisi tehtävää"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Jatka napauttamalla Seuraava."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Valmistaudu pitämään puhelinta sylissäsi."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Valmistaudu pitämään puhelinta sylissäsi VASEMMALLA kädellä."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Valmistaudu pitämään puhelinta sylissäsi OIKEALLA kädellä."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Pidä puhelinta sylissäsi %ld sekuntia."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Pidä puhelinta nyt käsi suorana olkapään korkeudella."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Pidä puhelinta nyt VASEN käsi suorana olkapään korkeudella."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Pidä puhelinta nyt OIKEA käsi suorana olkapään korkeudella."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Pidä puhelinta käsi suorana %ld sekuntia."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Pidä puhelinta nyt olkapään korkeudella kyynärpää taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Pidä puhelinta nyt VASEMMALLA kädellä olkapään korkeudella kyynärpää taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Pidä puhelinta nyt OIKEALLA kädellä olkapään korkeudella kyynärpää taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Pidä puhelinta kyynärpää taivutettuna %ld sekuntia"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Kosketa nyt puhelimella nenääsi toistuvasti pitäen kyynärpäätä taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Kosketa nyt puhelimella nenääsi toistuvasti pitäen puhelinta VASEMMASSA kädessä ja kyynärpäätä taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Kosketa nyt puhelimella nenääsi toistuvasti pitäen puhelinta OIKEASSA kädessä ja kyynärpäätä taivutettuna."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Kosketa puhelimella nenääsi toistuvasti %ld sekuntia"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Valmistaudu vilkuttamaan kuninkaallisesti (vilkuttamaan rannetta pyörittämällä)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Valmistaudu puhelin VASEMMASSA kädessä vilkuttamaan kuninkaallisesti (vilkuttamaan rannetta pyörittämällä)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Valmistaudu puhelin OIKEASSA kädessä vilkuttamaan kuninkaallisesti (vilkuttamaan rannetta pyörittämällä)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Vilkuta kuninkaallisesti %ld sekuntia."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Vaihda puhelin nyt VASEMPAAN käteen ja jatka seuraavaan tehtävään."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Vaihda puhelin nyt OIKEAAN käteen ja jatka seuraavaan tehtävään."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Jatka seuraavaan tehtävään."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktiviteetti valmis."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Sinua pyydetään suorittamaan %@ istuen, ensin puhelin toisessa kädessä ja sitten toisessa."; +"TREMOR_SKIP_LEFT_HAND" = "En voi suorittaa tätä aktiviteettia VASEMMALLA kädellä."; +"TREMOR_SKIP_RIGHT_HAND" = "En voi suorittaa tätä aktiviteettia OIKEALLA kädellä."; +"TREMOR_SKIP_NEITHER" = "Voin suorittaa tämän aktiviteetin molemmilla käsillä."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Polkutesti"; +"TRAILMAKING_INTENDED_USE" = "Tämä aktiviteetti arvioi visuaalista tarkkaavaisuutta ja tehtävänvaihtoa mittaamalla aikaa, joka kuluu pisteiden napautteluun järjestyksessä."; +"TRAILMAKING_INTENDED_USE2_A" = "Lähtölaskennan jälkeen napauttele pisteitä numeroiden ja kirjainten vuorottelevassa järjestyksessä. Aloita napauttamalla numeroa 1, napauta sitten 2, 3, 4 jne., kunnes vastaan tulee numero 7."; +"TRAILMAKING_INTENDED_USE2_B" = "Lähtölaskennan jälkeen napauttele pisteitä numeroiden ja kirjainten vuorottelevassa järjestyksessä. Aloita napauttamalla numeroa 1, napauta sitten kirjainta A. Jatka tätä järjestyksessä 2 ja B, 3 ja C jne., kunnes vastaan tulee numero 7."; +"TRAILMAKING_INTRO_TEXT" = "Tee tämä niin nopeasti kuin kykenet tekemättä virheitä. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Puheentunnistus"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Tämä aktiviteetti tallentaa puhettasi laitteen alareunassa olevalla mikrofonilla ja muuntaa sen tekstiksi."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Aloita napauttamalla Aloita-painiketta."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Aloita äänitys painamalla painiketta ennen puhumista."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Aloita tallentaminen"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Lopeta tallentaminen"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Muokkaa tekstiä"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Korjaa mahdolliset väärintunnistetut kohdat muokkaamalla saneltua tekstiä."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Muunnettu teksti näkyy tässä."; +"SPEECH_RECOGNITION_FAILED" = "Puheentunnistus epäonnistui."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Puheentunnistuksen alustaminen epäonnistui."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Toista ääni"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Pysäytä ääni"; +"SPEECH_IN_NOISE_TITLE" = "Puhe kohinan seassa"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Tämä aktiviteetti mittaa puheen ymmärrettävyyttä meluisassa ympäristössä."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Tämän testin osana:\n\nKuuntele virke.\n\nToista kuulemasi selkeästi tai jatka eteenpäin ja kirjoita kuulemasi näppäimistöllä. \n\nJos toistit kuulemasi, voit tarvittaessa muokata puheen­tunnistus­järjestelmän tuottamaa tekstiä."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Äänenvoimakkuuden kalibrointi"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Napauta Toista ääni, säädä äänenvoimakkuus sopivalle tasolle ja jatka napauttamalla Pysäytä ääni."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Kuuntele"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Virke, johon on sekoitettu taustakohinaa satunnaisessa signaali-kohinasuhteessa (SNR), toistetaan vain kerran."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Puhu"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Toista kuulemasi."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Tiedostoa ei voitu luoda"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Ei voitu poistaa riittävästi lokitiedostoja raja-arvon saavuttamiseksi."; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Virhe asetettaessa attribuuttia"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Tiedostoa ei ole merkitty poistetuksi (ei merkitty lähetetyksi)"; +"ERROR_DATALOGGER_MULTIPLE" = "Useita virheitä poistettaessa lokeja"; +"ERROR_RECORDER_NO_DATA" = "Kerättyjä tietoja ei löytynyt."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Ei määritettyä tulostehakemistoa"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL-mittari"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Tämä aktiviteetti mittaa ympäristön äänenpaineen. Jos melutaso on liian korkea, et voi jatkaa. Siirry hiljaisempaan ympäristöön nyt tai suorita tämä tehtävä myöhemmin."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Lasketaan"; +"ENVIRONMENTSPL_THRESHOLD" = "Kynnys: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Taustamelu OK"; +"ENVIRONMENTSPL_NOISE" = "Liikaa taustahälyä"; +"ENVIRONMENTSPL_TITLE_2" = "Etsi hiljainen paikka"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Tarkkuuden varmistamiseksi tämä testi on suoritettava hiljaisessa paikassa."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Aloita tehtävä"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Ei dataa"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Syötä arvo siirtämällä liukusäädintä"; +"SLIDER_I_DONT_KNOW" = "En tiedä"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Sivu"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Takaisin"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Näytä PDF:n miniatyyri"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Kätke PDF:n miniatyyri"; +"AX_BUTTON_ANNOTATE" = "Merkitse"; +"AX_BUTTON_SHOW_SEARCH" = "Näytä hakupalkki"; +"AX_BUTTON_HIDE_SEARCH" = "Kätke hakupalkki"; +"AX_BUTTON_SHARE" = "Jaa"; + + +"AX_COMPLETION_ILLUSTRATION" = "Onnistumista tarkoittava kuva valintamerkistä sinisessä ympyrässä"; + +"AX_SIGNVIEW_LABEL" = "Määritetty allekirjoituskenttä"; +"AX_SIGNVIEW_HINT" = "Allekirjoita koskettamalla näyttöä ja liikuttamalla sormea"; +"AX_SIGNVIEW_SIGNED" = "Allekirjoitettu"; +"AX_SIGNVIEW_UNSIGNED" = "Ei allekirjoitettu"; + +"AX_SELECTED" = "Valittu"; +"AX_UNSELECTED" = "Valitsematon"; +"AX_SELECT_ALL_THAT_APPLY" = "VALITSE KAIKKI SOPIVAT KOHDAT"; + +"AX_SLIDER_LABEL" = "Vastausliukusäädin. Asteikko %@–%@"; +"AX_UNLABELED_IMAGE" = "Merkitsemätön kuva"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Aloita tehtävä"; + +"AX.MEMORY.TILE.ACTIVE" = "aktiivinen"; +"AX.MEMORY.TILE.CORRECT" = "oikein"; +"AX.MEMORY.TILE.INCORRECT" = "väärin"; +"AX.MEMORY.TILE.QUIESCENT" = "lepotilassa"; +"AX.MEMORY.TILE.LABEL" = "Muistipelin ruutu"; + +"AX_IMAGE_CAPTURE_LABEL" = "Kaappauksen esikatselu"; +"AX_IMAGE_CAPTURED_LABEL" = "Kaapattu kuva"; + +"AX_VIDEO_CAPTURE_LABEL" = "Videokaappauksen esikatselu"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Videon tallennus on valmis"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Koon %@ levyä ei voida laittaa koon %@ levyn päälle"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Kohde"; +"AX_TOWER_OF_HANOI_TOWER" = "Torni"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Aseta levy kaksoisnapauttamalla"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Valitse päällimmäinen levy kaksoisnapauttamalla"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Sisältää levyjä, joiden koko on %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Tyhjä"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Sulje näppäimistö"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Alue välillä %@–%@"; +"AX_GRAPH_STACK_PREFIX" = "Pino, joka koostuu arvoista"; +"AX_GRAPH_AND_SEPARATOR" = " ja "; +"AX_GRAPH_POINT_%@" = "Piste: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Puheen aaltomuoto"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Kun äänitys alkaa, aktivoi toiseen kertaan sen lopettamiseksi."; + +"AX_AUDIO_BAR_GRAPH" = "Äänipalkin graafi"; + +"AX_AMSLER_GRID_LABEL" = "Amslerin ruudukko"; +"AX_AMSLER_GRID_HINT" = "Merkitse suoraan ruudukkoon sormellasi tai kynällä, tai lopeta pyyhkäisemällä ruudukon ulkopuolella."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Napautettavissa olevat painikkeet"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Napauta vasemmalle korvalle"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aloita testi napauttamalla. Kun testi alkaa, napauta tätä painiketta suoraan, kun kuulet äänen vasemmassa korvassasi."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Napauta oikealle korvalle"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aloita testi napauttamalla. Kun testi alkaa, napauta tätä painiketta suoraan, kun kuulet äänen oikeassa korvassasi."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Käytettäessä VoiceOveria paikanna kunkin korvan painikkeet koskettelemalla näyttöä. Painikkeet ovat suoraan painettavissa testin alettua.%@"; +"AX_TAP_BUTTON_1_LABEL" = "Napauta yhdelle sormelle"; +"AX_TAP_BUTTON_2_LABEL" = "Napauta toiselle sormelle"; +"AX_TAP_BUTTON_HINT" = "Laita päälle, jotta painikkeita voidaan napauttaa suoraan."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Käytettäessä VoiceOveria voit tutustua näyttöön ja painikkeiden sijaintiin koskettamalla näyttöä. Jos haluat voida napauttaa painikkeita suoraan, laita jompikumpi painike päälle."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Painikkeita voi nyt napauttaa suoraan."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ VoiceOveria käytettäessä painiketta voidaan napauttaa suoraan. Se sijaitsee lähellä näytön keskustaa."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Käytettäessä VoiceOveria testissä olevia painikkeita voidaan napauttaa suoraan."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "restoreDataa ei voida dekoodata alustusta varten"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..757aa8e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fi.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d virhe) + other + (%d virhettä) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.strings new file mode 100755 index 0000000..b17a243 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentement"; +"CONSENT_NAME_GIVEN" = "Prénom"; +"CONSENT_NAME_FAMILY" = "Nom"; +"CONSENT_NAME_PLACEHOLDER" = "Obligatoire"; +"CONSENT_REVIEW_TITLE" = "Vérification"; +"CONSENT_REVIEW_INSTRUCTION" = "Consultez le formulaire ci-dessous et touchez Accepter si vous êtes prêt à continuer."; +"CONSENT_REVIEW_ALERT_TITLE" = "Vérification"; +"CONSENT_SIGNATURE_TITLE" = "Signature"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Veuillez signer dans la zone ci-dessous à l’aide de votre doigt."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Signer ici"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Page %1$ld sur %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bienvenue"; +"CONSENT_SECTION_DATA_GATHERING" = "Collecte des données"; +"CONSENT_SECTION_PRIVACY" = "Confidentialité"; +"CONSENT_SECTION_DATA_USE" = "Utilisation des données"; +"CONSENT_SECTION_STUDY_SURVEY" = "Étude"; +"CONSENT_SECTION_STUDY_TASKS" = "Tâches de l’étude"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Temps consacré à l’étude"; +"CONSENT_SECTION_WITHDRAWING" = "Retrait de l’étude"; +"CONSENT_LEARN_MORE_TITLE" = "En savoir plus"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "En savoir plus sur la collecte des données"; +"LEARN_MORE_DATA_USE" = "En savoir plus sur l’utilisation des données"; +"LEARN_MORE_PRIVACY" = "En savoir plus sur la protection de la confidentialité et de votre identité"; +"LEARN_MORE_WELCOME" = "Commencer par en savoir plus sur l’étude"; +"LEARN_MORE_STUDY_SURVEY" = "En savoir plus sur l’étude"; +"LEARN_MORE_TIME_COMMITMENT" = "En savoir plus sur l’impact de l’étude sur votre emploi du temps"; +"LEARN_MORE_TASKS" = "En savoir plus sur les tâches impliquées"; +"LEARN_MORE_WITHDRAWING" = "En savoir plus sur le retrait de l’étude"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Options de partage"; +"CONSENT_SHARE_WIDELY_%@" = "Partager mes données avec %@ et des chercheurs du monde entier dans ce domaine"; +"CONSENT_SHARE_ONLY_%@" = "Ne partager mes données qu’avec %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ recevra les données issues de votre participation à cette étude.\n\nLe partage plus large de vos données d’étude chiffrées (sans renseignements tels que votre nom) peut être bénéfique à cette étude et aux suivantes."; +"LEARN_MORE_CONSENT_SHARING" = "En savoir plus sur le partage de données"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nom en majuscules"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signature"; +"CONSENT_DOC_LINE_DATE" = "Date"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ sur %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Question %1$@ sur %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Ignorée"; +"REVIEW_EDIT_ANSWER" = "Modifier"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valeur non valide"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ dépasse la valeur maximale autorisée (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ est inférieur à la valeur minimale autorisée (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ n’est pas une valeur valide."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Adresse e-mail non valide : %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Saisir une adresse"; +"LOCATION_ERROR_TITLE" = "Impossible de localiser l’adresse"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Impossible de vous localiser. Saisissez une adresse ou rendez-vous si possible dans un endroit avec un meilleur signal GPS."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Accès au service de localisation refusé. Permettez à cette app d’utiliser le service de localisation dans Réglages."; +"LOCATION_ERROR_GEOCODE" = "Impossible de trouver un résultat pour l’adresse saisie. Assurez-vous qu’elle est valide."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Vous n’êtes pas connecté à Internet ou vous avez atteint la limite de requêtes d’adresse. Si vous n’êtes pas connecté à Internet, activez votre Wi-Fi pour répondre à cette question, ignorez cette question si le bouton est disponible, ou reprenez l’enquête lorsque vous serez connecté à Internet. Sinon, veuillez attendre quelques minutes."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "La longueur du texte dépasse la limite : %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Appareil photo non disponible en plein écran."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Adresse e-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "gallain@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Mot de passe"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Saisir le mot de passe"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmer"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Saisir à nouveau le mot de passe"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Les mots de passe sont différents."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informations supplémentaires"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Gilles"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Allain"; +"GENDER_FORM_ITEM_TITLE" = "Sexe"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Choisir"; +"DOB_FORM_ITEM_TITLE" = "Date de naissance"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Définir la date"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Numéro de téléphone"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Vérification"; +"VERIFICATION_STEP_TITLE" = "Vérifier votre adresse e-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Touchez le lien ci-dessous si vous n’avez pas reçu d’e-mail de vérification et aimeriez le renvoyer."; +"RESEND_EMAIL_BUTTON_TITLE" = "Renvoyer l’e-mail de vérification"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Connexion"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Mot de passe oublié ?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Saisir le code"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmer le code"; +"PASSCODE_SAVED_MESSAGE" = "Code enregistré"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Authentification par code"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Saisir votre ancien code"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Saisir votre nouveau code"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirmer votre nouveau code"; +"PASSCODE_INVALID_ALERT_TITLE" = "Code incorrect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Les codes sont différents. Réessayez."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Authentification avec Touch ID requise"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Erreur Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Caractères numériques uniquement."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicateur de progression de la saisie du code"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ sur %@ chiffres saisis"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Code oublié ?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Impossible d’ajouter l’élément du trousseau."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Impossible de mettre à jour l’élément du trousseau."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Impossible de supprimer l’élément du trousseau."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Impossible de localiser l’élément du trousseau."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Femme"; +"GENDER_MALE" = "Homme"; +"GENDER_OTHER" = "Autre"; + +/* Boolean answer strings */ +"BOOL_NO" = "Non"; +"BOOL_YES" = "Oui"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "pi"; +"MEASURING_UNIT_IN" = "po"; +"MEASURING_UNIT_KG" = " kg"; +"MEASURING_UNIT_LB" = " lb"; +"MEASURING_UNIT_OZ" = "once"; + +/* Limb values. */ +"LIMB_LEFT" = "gauche"; +"LIMB_RIGHT" = "droit"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toucher pour répondre"; +"NULL_ANSWER" = "Sélectionner une réponse"; +"PLACEHOLDER_IMAGE_CHOICES" = "Toucher pour sélectionner"; +"PLACEHOLDER_LONG_TEXT" = "Toucher pour écrire"; + +/* Button titles */ +"BUTTON_AGREE" = "Accepter"; +"BUTTON_CANCEL" = "Annuler"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Effacer"; +"BUTTON_CLEAR_SIGNATURE" = "Effacer la signature"; +"BUTTON_APPLY" = "Appliquer"; +"BUTTON_DISAGREE" = "Refuser"; +"BUTTON_DONE" = "Terminé"; +"BUTTON_GET_STARTED" = "Démarrer"; +"BUTTON_LEARN_MORE" = "En savoir plus"; +"BUTTON_NEXT" = "Suivant"; +"BUTTON_SKIP" = "Ignorer"; +"BUTTON_SKIP_QUESTION" = "Ignorer cette question"; +"BUTTON_START_TIMER" = "Lancer le minuteur"; +"BUTTON_OPTION_SAVE" = "Enregistrer pour plus tard"; +"BUTTON_OPTION_DISCARD" = "Effacer les résultats"; +"BUTTON_OPTION_STOP_TASK" = "Interrompre la tâche"; +"BUTTON_SAVE" = "Enregistrer"; +"BUTTON_CLEAR_ANSWER" = "Effacer la réponse"; +"BUTTON_READ_ONLY_MODE" = "Cette réponse ne peut pas être modifiée."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Fermer"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Début de l’activité dans"; +"TASK_COMPLETE_TITLE" = "Activité terminée"; +"TASK_COMPLETE_TEXT" = "Les données vont être analysées, et vous recevrez une notification lorsque les résultats seront disponibles."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Reste %@."; +"TOUCH_ANYWHERE_LABEL" = "Touchez l’écran n’importe où pour continuer"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturer l’image"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapturer l’image"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Aucun appareil photo n’a été trouvé. Cette étape ne peut être effectuée."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Afin d’effectuer cette étape, autorisez cette app à accéder à l’appareil photo dans Réglages."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Aucun répertoire de sortie n’a été spécifié pour les images capturées."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "L’image capturée n’a pas pu être enregistrée."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Lancer l’enregistrement"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Arrêter l’enregistrement"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapturer la vidéo"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Fréquence cardiaque (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Asseyez-vous confortablement pendant %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Marchez le plus rapidement possible pendant %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Cette activité mesure votre fréquence cardiaque et la distance maximale que vous pouvez parcourir à pied en %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Marchez à l’extérieur le plus rapidement possible pendant %1$@. Asseyez-vous ensuite confortablement pendant %2$@. Touchez Démarrer pour commencer."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Marche et équilibre"; +"WALK_INTRO_TEXT" = "Cette activité observe votre allure et votre équilibre pendant que vous marchez et que vous vous tenez debout. Ne continuez pas si vous ne pouvez pas marcher en sécurité sans assistance."; +"WALK_INTRO_2_TEXT_%ld" = "Trouvez un endroit où vous pouvez effectuer environ %ld pas sur une ligne droite en sécurité et sans assistance."; +"WALK_INTRO_2_DETAIL" = "Placez votre appareil dans une poche ou dans un sac et suivez les instructions audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Maintenant, ne bougez plus pendant %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Ne bougez pas pendant %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Faites demi-tour et revenez à votre point de départ."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Faites jusqu’à %ld pas sur une ligne droite."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Trouvez un endroit vous permettant d’avancer et de reculer en ligne droite en toute sécurité. Essayez de marcher de façon continue en tournant à la fin de votre chemin, comme si vous contourniez un cône.\n\nOn vous invitera ensuite à faire demi-tour en décrivant un cercle complet, puis à vous tenir immobile avec vos bras le long du corps et vos pieds placés de façon à être alignés avec vos épaules."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Touchez Démarrer une fois que vous êtes prêt à démarrer.\nPlacez ensuite votre appareil dans une poche ou un sac et suivez les instructions audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Faites des allers-retours en ligne droite pendant %@. Marchez normalement."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Effectuez un cercle complet en marchant, puis restez immobile pendant %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Vous avez terminé cette activité."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Vitesse de saisie"; +"TAPPING_TASK_TITLE_RIGHT" = "Main droite"; +"TAPPING_TASK_TITLE_LEFT" = "Main gauche"; +"TAPPING_INTRO_TEXT" = "Cette activité mesure votre vitesse de saisie."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Placez votre appareil sur une surface plane."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Avec deux doigts de la même main et en les alternant, touchez les boutons à l’écran."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Avec deux doigts de la main droite et en les alternant, touchez les boutons à l’écran."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Avec deux doigts de la main gauche et en les alternant, touchez les boutons à l’écran."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Répétez à présent ce test avec la main droite."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Répétez à présent ce test avec la main gauche."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Touchez l’écran avec un doigt, puis avec l’autre, pendant %@. Essayez de respecter le même intervalle de temps entre chaque toucher pour être aussi régulier que possible."; +"TAPPING_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Touchez Suivant pour commencer."; +"TAP_BUTTON_TITLE" = "Toucher"; +"TOTAL_TAPS_LABEL" = "Total de touchers"; +"TAPPING_INSTRUCTION" = "Touchez les boutons de façon aussi régulière que possible avec deux doigts."; +"TAPPING_INSTRUCTION_RIGHT" = "Touchez les boutons de la main DROITE."; +"TAPPING_INSTRUCTION_LEFT" = "Touchez les boutons de la main GAUCHE."; +"TAPPING_SKIP_TITLE" = "Ne pas faire avec cette main"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Grille d'Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Cette activité permet de détecter les problèmes de vision de l’utilisateur."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Tenez l’appareil à 12 pouces (environ 30 centimètres) de votre visage et au niveau de votre œil pendant toute la durée du test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Fermez votre %@ et fixez le point au centre de la grille carrée.\n\nAvec votre doigt ou votre stylet, marquez toute distorsion que vous percevez, comme des lignes ondulées ou floues.\n\nUne fois que vous avez terminé, balayez vers la gauche depuis n’importe quel endroit extérieur à la grille."; +"AMSLER_GRID_LEFT_EYE" = "Œil de gauche"; +"AMSLER_GRID_RIGHT_EYE" = "Œil droit"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voix"; +"AUDIO_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"AUDIO_INSTRUCTION" = "Dites « Aaaaah » dans le micro le plus longtemps possible."; +"AUDIO_INTRO_TEXT" = "Inspirez profondément et dites « Aaaaah » dans le micro le plus longtemps possible. Les barres audio doivent rester bleues : gardez le même volume."; +"AUDIO_INTENDED_USE" = "Cette activité permet d’évaluer votre voix en l’enregistrant avec le micro situé en bas de votre appareil."; +"AUDIO_TOO_LOUD_LABEL" = "Trop fort"; +"AUDIO_GENERIC_ERROR_LABEL" = "Enregistrement audio impossible"; +"AUDIO_LEVEL_CHECK_LABEL" = "Veuillez patienter pendant que nous étudions le volume du fond sonore."; +"AUDIO_TOO_LOUD_MESSAGE" = "Le volume ambiant est trop fort pour enregistrer votre voix. Rendez-vous dans un endroit plus calme et réessayez."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Touchez Suivant lorsque vous êtes prêt."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiométrie tonale"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Cette activité mesure votre capacité à entendre différents sons."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Avant de commencer, branchez votre casque d’écoute et placez-le sur vos oreilles.\n\nLe son sera très subtil et ne ressemblera pas à un son d’alerte standard.  Le son sera tout d’abord faible, puis gagnera doucement en volume. Veuillez rester concentré et toucher le bouton de gauche ou de droite en fonction de l’oreille dans laquelle vous entendez le son."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Vous devriez maintenant entendre un son. Réglez le volume à l’aide des commandes situées sur le côté de l’appareil.\n\nTouchez n’importe quel bouton quand vous êtes prêt à commencer."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Dès que vous entendez un son, touchez le bouton gauche ou droit pour indiquer dans quelle oreille vous l’entendez."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Oreille gauche"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Oreille droite"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, à gauche"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, à droite"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiométrie tonale"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Touchez lorsque vous entendez un son."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Son et volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Vous entendrez une série de sons."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Lorsque vous entendez un son, touchez le bouton."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Pour ce test, le volume sera réglé sur 50 pour cent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Ce test dure 10 minutes environ."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activez Ne pas déranger pour éviter toute interruption."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Des sons seront d’abord émis dans votre oreille droite."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Des sons seront émis dans votre oreille gauche."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Cette activité permet d’identifier les niveaux de seuil d’audition d’un individu à une échelle dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Assurez-vous que le volume de l’appareil est au maximum.\n\nPendant cette tâche, un son subtil sera joué dans votre oreille de gauche ou de droite.\n\nÉcoutez avec attention et touchez le bouton chaque fois que vous entendez un son."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ce test permet d’identifier le volume qu’un son doit atteindre pour que vous puissiez l’entendre."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Questionnaire de départ."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Sélectionnez votre « meilleure oreille », si vous en avez une"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "gauche"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "droite"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "aucune préférence"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test annulé"; +"dBHL_ALERT_TITLE_START_OVER" = "Recommencer"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Annuler le test"; +"dBHL_ALERT_TEXT" = "Reconnectez vos AirPods ou EarPods pour passer ce test."; +"dBHL_PROGRESS_COMPLETION_%@" = "Progression : %@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Écouteurs"; +"HEADPHONES_UNKNOWN" = "Inconnu"; +"HEADPHONES_NONE" = "Aucun"; +"CONNECTED" = "Connecté"; +"NOT_CONNECTED" = "Non connecté"; +"HEADPHONE_CONNECTED_%@" = "Connecté - %@"; +"HEADPHONE_DETECT_TITLE" = "Connectez vos écouteurs"; +"HEADPHONE_DETECT_TEXT" = "Ce test requiert des AirPods ou des EarPods Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Mémoire spatiale"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Cette activité évalue votre mémoire spatiale à court terme en vous demandant de répéter l’ordre dans lequel les images de %@ s’éclairent."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "fleurs"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "fleurs"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Certaines des images de %@ s’allumeront une par une. Touchez ces images de %@ dans l’ordre dans lequel elles s’allument."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Certaines des images de %@ s’allumeront une par une. Touchez ces images de %@ dans l’ordre inverse dans lequel elles s’allument."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Pour commencer, touchez Démarrer puis regardez avec attention."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Résultat"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Regarder les %@ s’éclairer"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Toucher les images de %@ dans l’ordre d’éclairage"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Toucher les images de %@ dans l’ordre inverse"; +"MEMORY_GAME_COMPLETE_TITLE" = "Séquence terminée"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Pour continuer, touchez Suivant."; +"MEMORY_GAME_FAILED_TITLE" = "Réessayer"; +"MEMORY_GAME_FAILED_MESSAGE" = "Vous n’avez pas totalement réussi cette fois-ci. Touchez Suivant pour continuer."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Temps écoulé"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Votre temps est écoulé.\nTouchez Suivant pour continuer."; +"MEMORY_GAME_COMPLETE" = "Jeu terminé"; +"MEMORY_GAME_PAUSED_TITLE" = "En pause"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Pour continuer, touchez Suivant."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "L’activité de mémoire a été développée avec l’aide des docteurs en psychologie Katherine Possin et Joel Kramer de l’université de Californie, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Temps de réaction"; +"REACTION_TIME_TASK_INTENDED_USE" = "Cette activité évalue le temps qu’il vous faut pour réagir à un signal visuel."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Secouez l’appareil dans n’importe quelle direction dès que le point bleu apparaît à l’écran. Il vous sera demandé de le faire %D fois."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Tentative %@ sur %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Secouer rapidement l’appareil lorsque le cercle bleu apparaît"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Chaque fois qu’un mot apparaît, sélectionnez la première lettre du nom de la COULEUR affichée."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Lorsque vous êtes prêt à commencer l’activité Stroop, touchez Démarrer."; +"STROOP_TASK_STEP_TEXT" = "Sélectionnez la première lettre du nom de la COULEUR affichée."; +"STROOP_COLOR_RED" = "ROUGE"; +"STROOP_COLOR_GREEN" = "VERT"; +"STROOP_COLOR_BLUE" = "BLEU"; +"STROOP_COLOR_YELLOW" = "JAUNE"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "J"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tour de Hanoï"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Cette activité évalue votre capacité à terminer un jeu de réflexion."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Déplacez toute la pile de disques sur la plateforme en surbrillance en un minimum de déplacements."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Jeu de réflexion"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Nombre de déplacements : %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Je ne parviens pas à faire ce jeu"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Amplitude de mouvement"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Vous devez préciser le membre concerné : gauche ou droit"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Plage de mouvement du genou gauche"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Plage de mouvement du genou droit"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Cette activité mesure l’extension maximale de votre genou gauche."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Cette activité mesure l’extension maximale de votre genou droit."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Asseyez-vous sur le bord d’une chaise. Commencez par placer votre appareil sur le genou gauche pour prendre une mesure. Veillez à activer le son pour entendre les instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Asseyez-vous sur le bord d’une chaise. Commencez par placer votre appareil sur le genou droit pour prendre une mesure. Veillez à activer le son pour entendre les instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placez votre appareil sur le genou gauche avec l’écran orienté vers le haut, comme illustré."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placez votre appareil sur le genou droit avec l’écran orienté vers le haut, comme illustré."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre genou gauche aussi loin que vous pouvez. Revenez à la position de départ et touchez l’écran de nouveau lorsque vous avez terminé."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre genou droit aussi loin que vous pouvez. Revenez à la position de départ et touchez l’écran de nouveau lorsque vous avez terminé."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placez votre appareil sur votre genou gauche. Touchez l’écran et étendez votre genou gauche aussi loin que vous pouvez."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placez votre appareil sur votre genou droit. Touchez l’écran et étendez votre genou droit aussi loin que vous pouvez."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Lorsque vous avez terminé, remettez votre genou gauche dans sa position de départ. Puis, touchez n’importe quel endroit de l’écran."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Lorsque vous avez terminé, remettez votre genou droit dans sa position de départ. Puis, touchez n’importe quel endroit de l’écran."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Plage de mouvement de l’épaule gauche"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Plage de mouvement de l’épaule droite"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Cette activité mesure l’extension maximale de votre épaule gauche."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Cette activité mesure l’extension maximale de votre épaule droite."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Commencez par placer votre appareil sur l’épaule gauche pour prendre une mesure. Veillez à activer le son pour entendre les instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Commencez par placer votre appareil sur l’épaule droite pour prendre une mesure. Veillez à activer le son pour entendre les instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placez votre appareil sur l’épaule gauche avec l’écran orienté vers le haut, comme illustré."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placez votre appareil sur l’épaule droite avec l’écran orienté vers le haut, comme illustré."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre bras gauche aussi loin que vous pouvez. Revenez à la position de départ et touchez l’écran de nouveau lorsque vous avez terminé."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre bras droit aussi loin que vous pouvez. Revenez à la position de départ et touchez l’écran de nouveau lorsque vous avez terminé."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placez votre appareil sur l’épaule gauche. Touchez l’écran et étendez votre bras gauche vers l’avant aussi loin que vous pouvez."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placez votre appareil sur l’épaule droite. Touchez l’écran et étendez votre bras droit vers l’avant aussi loin que vous pouvez."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Lorsque vous avez terminé, remettez votre bras gauche dans sa position de départ. Puis, touchez n’importe quel endroit de l’écran."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Lorsque vous avez terminé, remettez votre bras droit dans sa position de départ. Puis, touchez n’importe quel endroit de l’écran."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Marche chronométrée"; +"TIMED_WALK_INTRO_DETAIL" = "Cette activité évalue le fonctionnement de vos extrémités inférieures."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Trouvez un endroit, de préférence en extérieur, où vous pouvez marcher environ %@ en ligne droite aussi vite que possible, mais sans vous mettre en danger. Ne ralentissez pas avant d’avoir passé la ligne d’arrivée."; +"TIMED_WALK_INTRO_2_DETAIL" = "Touchez Suivant pour commencer."; +"TIMED_WALK_FORM_TITLE" = "Appareil d’assistance"; +"TIMED_WALK_FORM_TEXT" = "Utilisez le même appareil d’assistance pour chaque test."; +"TIMED_WALK_QUESTION_TEXT" = "Portez-vous un releveur de pied ?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Utilisez-vous un appareil d’assistance ?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Touchez ici pour répondre."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Non"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Une canne"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Une béquille"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Deux cannes"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Deux béquilles"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Un déambulateur/rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Marchez %@ en ligne droite."; +"TIMED_WALK_INSTRUCTION_TURN" = "Faites demi-tour."; +"TIMED_WALK_INSTRUCTION_2" = "Revenez à votre point de départ."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Touchez Suivant lorsque vous avez terminé."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Le test PASAT (Paced Auditory Serial Addition Test) mesure votre vitesse de traitement des informations audio et votre capacité à calculer."; +"PVSAT_INTRO_TEXT" = "Le test PVSAT (Paced Visual Serial Addition Test) mesure votre vitesse de traitement des informations visuelles et votre capacité à calculer."; +"PAVSAT_INTRO_TEXT" = "Le test PAVSAT (Paced Auditory and Visual Serial Addition Test) mesure votre vitesse de traitement des informations audio et visuelles et votre capacité à calculer."; +"PSAT_INTRO_TEXT_2_%@" = "Des chiffres uniques s’affichent toutes les %@.\nVous devez ajouter chaque nouveau chiffre à celui qui l’a précédé.\nAttention, vous ne devez pas calculer de total, mais simplement la somme des deux derniers chiffres."; +"PSAT_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"PSAT_INITIAL_INSTRUCTION" = "Souvenez-vous de ce chiffre."; +"PSAT_INSTRUCTION" = "Ajoutez ce chiffre au précédent."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test des %@ chevilles"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Cette activité évalue le fonctionnement de vos extrémités supérieures. Vous devez placer un rond dans un trou et répéter cette opération %@ fois."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Votre main gauche et droite seront toutes les deux testées.\nVous devez récupérer l’élément aussi rapidement que possible, le placer dans le trou et, une fois l’opération répétée %@ fois, le retirer de nouveau %@ fois."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Votre main droite et gauche seront toutes les deux testées.\nVous devez récupérer l’élément aussi rapidement que possible, le placer dans le trou et, une fois l’opération répétée %@ fois, le retirer de nouveau %@ fois."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Placez le rond dans le trou avec votre main gauche."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Placez le rond dans le trou avec votre main droite."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Placez le rond derrière la ligne avec votre main gauche."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Placez le rond derrière la ligne avec votre main droite."; +"HOLE_PEG_TEST_TEXT" = "Ramassez le rond avec deux doigts."; +"HOLE_PEG_TEST_TEXT_2" = "Levez les doigts pour faire tomber le rond."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremblements"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Cette activité mesure les tremblements de vos mains dans différentes positions. Trouvez une position assise confortable, que vous garderez pendant toute la durée de ce test."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Tenez votre téléphone dans la main la plus affectée, comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Tenez votre téléphone dans la main DROITE, comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Tenez votre téléphone dans la main GAUCHE, comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Vous serez invité à réaliser %@ en positon assise, le téléphone dans votre main."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "une tâche"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "deux tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "trois tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quatre tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinq tâches"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Touchez Suivant pour continuer."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Préparez-vous à tenir votre téléphone sur vos genoux."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Préparez-vous à tenir votre téléphone sur vos genoux avec votre main GAUCHE."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Préparez-vous à tenir votre téléphone sur vos genoux avec votre main DROITE."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Tenez votre téléphone sur vos genoux pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Maintenant, tenez votre téléphone à hauteur d’épaule, la main tendue."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Maintenant, tenez votre téléphone avec votre main GAUCHE, à hauteur d’épaule, la main tendue."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Maintenant, tenez votre téléphone avec votre main DROITE, à hauteur d’épaule, la main tendue."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Tenez votre téléphone, la main tendue, pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Maintenant, tenez votre téléphone à hauteur d’épaule, le coude plié."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Maintenant, tenez votre téléphone avec votre main GAUCHE, à hauteur d’épaule, le coude plié."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Maintenant, tenez votre téléphone avec votre main DROITE, à hauteur d’épaule, le coude plié."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Tenez votre téléphone, le coude plié, pendant %ld secondes"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Maintenant, avec le coude plié, portez votre téléphone à votre nez, plusieurs fois."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Maintenant, avec le coude plié et le téléphone dans votre main GAUCHE, portez votre téléphone à votre nez, plusieurs fois."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Maintenant, avec le coude plié et le téléphone dans votre main DROITE, portez votre téléphone à votre nez, plusieurs fois."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Portez votre téléphone à votre nez, plusieurs fois, pendant %ld secondes"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Préparez-vous à saluer de la main, les doigts serrés les uns contre les autres."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Préparez-vous à saluer de la main GAUCHE, le téléphone en main, les doigts serrés les uns contre les autres."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Préparez-vous à saluer de la main DROITE, le téléphone en main, les doigts serrés les uns contre les autres."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Saluez de la main, les doigts serrés les uns contre les autres, pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Placez maintenant le téléphone dans votre main GAUCHE et passez à la tâche suivante."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Placez maintenant le téléphone dans votre main DROITE et passez à la tâche suivante."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Passez à la tâche suivante."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activité terminée."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Vous serez invité à réaliser %@ en positon assise, le téléphone dans une main, puis dans l’autre."; +"TREMOR_SKIP_LEFT_HAND" = "Je ne peux pas effectuer cette activité avec ma main GAUCHE."; +"TREMOR_SKIP_RIGHT_HAND" = "Je ne peux pas effectuer cette activité avec ma main DROITE."; +"TREMOR_SKIP_NEITHER" = "Je peux effectuer cette activité des deux mains."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test des tracés (TMT)"; +"TRAILMAKING_INTENDED_USE" = "Cette activité évalue votre attention visuelle et votre capacité à passer d’une tâche à une autre en enregistrant le temps qu’il vous faut pour toucher une série de points dans l’ordre."; +"TRAILMAKING_INTENDED_USE2_A" = "Après le compte à rebours, touchez les points en alternant entre les chiffres et les lettres. Commencez par toucher le premier chiffre « 1 », puis « 2 » – « 3 » – « 4 »… jusqu’à atteindre le chiffre 7."; +"TRAILMAKING_INTENDED_USE2_B" = "Après le compte à rebours, touchez les points en alternant entre les chiffres et les lettres. Commencez par le premier chiffre « 1 » suivi de la première lettre « A », puis touchez « 2 » – « B » – « 3 » – « C »… jusqu’à atteindre le chiffre 7."; +"TRAILMAKING_INTRO_TEXT" = "Allez aussi vite que possible sans faire de faute. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconnaissance vocale"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Cette activité permet d’enregistrer votre énonciation avec le micro situé en bas de votre appareil, puis de le retranscrire en texte."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Appuyez sur le bouton pour commencer l’enregistrement avant d’énoncer."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Enregistrer"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Terminer"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Modification"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Modifiez la transcription pour corriger toute mauvaise interprétation du texte énoncé."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Votre transcription s’affichera ici."; +"SPEECH_RECOGNITION_FAILED" = "Échec de la reconnaissance vocale."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Impossible d’initialiser la reconnaissance vocale."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Écouter"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Arrêter l’audio"; +"SPEECH_IN_NOISE_TITLE" = "Parole dans le bruit"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Cette activité permet de mesurer l’intelligibilité de l’énonciation en cas d’environnement bruyant."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Dans le cadre de ce test, vous :\n\nÉcouterez une phrase.\n\nRépéterez clairement ce que vous avez entendu ou avancerez pour saisir au clavier ce que vous avez entendu. \n\nSi vous répétez ce que vous avez entendu, vous pouvez modifier la transcription générée par le moteur de reconnaissance vocale."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Étalonnage du volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Touchez « Écouter », réglez votre volume à un niveau qui vous convient, puis touchez « Arrêter l’audio » pour continuer."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Écouter"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Une phrase avec du bruit de fond sera lue une seule fois, à un rapport signal sur bruit aléatoire."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Énoncer"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Répétez ce que vous avez entendu."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Création du fichier impossible"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Impossible de supprimer assez de fichiers journaux pour atteindre le seuil"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Erreur de définition de l’attribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Fichier non marqué comme supprimé (non marqué comme chargé)"; +"ERROR_DATALOGGER_MULTIPLE" = "Plusieurs erreurs lors de la suppression des journaux"; +"ERROR_RECORDER_NO_DATA" = "Aucune donnée collectée n’a été détectée."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Aucun répertoire de sortie spécifié"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Calculateur de pression acoustique"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Cette activité permet de mesurer le niveau de pression acoustique de l’environnement. Si les niveaux de bruit sont trop élevés, vous ne pourrez pas continuer. Veuillez vous déplacer vers un endroit plus calme pour effectuer cette tâche ou reprendre cette activité plus tard."; +"ENVIRONMENTSPL_UNIT" = "dB (A)"; +"ENVIRONMENTSPL_CALCULATING" = "Calcul en cours"; +"ENVIRONMENTSPL_THRESHOLD" = "Seuil : %@ dB (A)"; +"ENVIRONMENTSPL_OK" = "Bruit de fond OK"; +"ENVIRONMENTSPL_NOISE" = "Bruit de fond excessif"; +"ENVIRONMENTSPL_TITLE_2" = "Trouvez un lieu calme"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Pour obtenir des résultats précis, il est recommandé d’effectuer ce test dans un environnement calme."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Commencer la tâche"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Aucune donnée"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Déplacer le curseur pour saisir une valeur"; +"SLIDER_I_DONT_KNOW" = "Je ne sais pas"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Page"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Retour"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Afficher la vignette PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Masquer les vignettes PDF"; +"AX_BUTTON_ANNOTATE" = "Annoter"; +"AX_BUTTON_SHOW_SEARCH" = "Afficher la barre de recherche"; +"AX_BUTTON_HIDE_SEARCH" = "Masquer la barre de recherche"; +"AX_BUTTON_SHARE" = "Partager"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration d’une coche dans un cercle bleu indiquant une réussite"; + +"AX_SIGNVIEW_LABEL" = "Champ de signature indiqué"; +"AX_SIGNVIEW_HINT" = "Signer avec votre doigt sur l’écran"; +"AX_SIGNVIEW_SIGNED" = "Signé"; +"AX_SIGNVIEW_UNSIGNED" = "Non signé"; + +"AX_SELECTED" = "Sélectionné"; +"AX_UNSELECTED" = "Désélectionné"; +"AX_SELECT_ALL_THAT_APPLY" = "COCHEZ LES RÉPONSES"; + +"AX_SLIDER_LABEL" = "Curseur de réponses. De %@ à %@"; +"AX_UNLABELED_IMAGE" = "Image sans étiquette"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Commencer la tâche"; + +"AX.MEMORY.TILE.ACTIVE" = "actif"; +"AX.MEMORY.TILE.CORRECT" = "correct"; +"AX.MEMORY.TILE.INCORRECT" = "incorrect"; +"AX.MEMORY.TILE.QUIESCENT" = "latent"; +"AX.MEMORY.TILE.LABEL" = "Jeu de mémoire"; + +"AX_IMAGE_CAPTURE_LABEL" = "Aperçu de la capture"; +"AX_IMAGE_CAPTURED_LABEL" = "Image capturée"; + +"AX_VIDEO_CAPTURE_LABEL" = "Aperçu de la capture vidéo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Capture vidéo terminée"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Impossible de placer un disque de taille %@ sur un disque de taille %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cible"; +"AX_TOWER_OF_HANOI_TOWER" = "Tour"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Toucher deux fois pour placer le disque"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Toucher deux fois pour sélectionner le disque supérieur"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Possède un disque de tailles %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vide"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Fermer le clavier"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "De %@ à %@"; +"AX_GRAPH_STACK_PREFIX" = "Pile composée de"; +"AX_GRAPH_AND_SEPARATOR" = " et "; +"AX_GRAPH_POINT_%@" = "Point : %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forme d’ondes de l’énonciation"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Lorsque vous lancez l’enregistrement, effectuez une deuxième activation pour l’arrêter."; + +"AX_AUDIO_BAR_GRAPH" = "Graphique à barres audio"; + +"AX_AMSLER_GRID_LABEL" = "Grille d'Amsler"; +"AX_AMSLER_GRID_HINT" = "Avec votre doigt ou votre stylet, marquez directement la grille ou balayez vers la gauche depuis n’importe où à l’extérieur de la grille pour terminer."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Boutons touchables"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Toucher pour l’oreille gauche"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activez cette option pour démarrer le test. Lorsque le test commence, touchez directement ce bouton lorsque vous entendez un son dans votre oreille gauche."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Toucher pour l’oreille droite"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activez cette option pour démarrer le test. Lorsque le test commence, touchez directement ce bouton lorsque vous entendez un son dans votre oreille droite."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ À l’aide de VoiceOver, explorez l’écran au toucher pour apprendre où se situent les boutons pour chaque oreille. Lorsque le test commence, les boutons seront directement touchables. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Toucher avec un doigt"; +"AX_TAP_BUTTON_2_LABEL" = "Toucher avec un autre doigt"; +"AX_TAP_BUTTON_HINT" = "Activez cette option pour rendre les boutons directement touchables."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ À l’aide de VoiceOver, explorez l’écran au toucher pour apprendre où se situent les boutons. Activez l’un ou l’autre des boutons pour le rendre directement touchable."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Les boutons sont désormais directement touchables."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ À l’aide de VoiceOver, le bouton sera directement touchable. Il se trouvera près du centre de l’écran."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ À l’aide de VoiceOver, les boutons utilisés dans le test seront directement touchables."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Impossible de décoder restoreData pour l’initialisation"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..6430399 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d erreur) + other + (%d erreurs) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.strings new file mode 100755 index 0000000..4c6f139 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentement"; +"CONSENT_NAME_GIVEN" = "Prénom"; +"CONSENT_NAME_FAMILY" = "Nom de famille"; +"CONSENT_NAME_PLACEHOLDER" = "Requis"; +"CONSENT_REVIEW_TITLE" = "Révision"; +"CONSENT_REVIEW_INSTRUCTION" = "Consultez le formulaire ci-dessous et touchez Accepter si vous êtes prêt à continuer."; +"CONSENT_REVIEW_ALERT_TITLE" = "Révision"; +"CONSENT_SIGNATURE_TITLE" = "Signature"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Signez avec votre doigt dans la boîte ci-dessous."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Signez ici"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Page %1$ld sur %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bienvenue"; +"CONSENT_SECTION_DATA_GATHERING" = "Collecte de données"; +"CONSENT_SECTION_PRIVACY" = "Confidentialité"; +"CONSENT_SECTION_DATA_USE" = "Utilisation des données"; +"CONSENT_SECTION_STUDY_SURVEY" = "Enquête de l’étude"; +"CONSENT_SECTION_STUDY_TASKS" = "Tâches de l’étude"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Durée de l'engagement"; +"CONSENT_SECTION_WITHDRAWING" = "Abandonner"; +"CONSENT_LEARN_MORE_TITLE" = "En savoir plus"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "En savoir plus sur la façon dont les données sont recueillies"; +"LEARN_MORE_DATA_USE" = "En savoir plus sur la façon dont les données sont utilisées"; +"LEARN_MORE_PRIVACY" = "En savoir plus sur notre façon de protéger votre confidentialité et votre identité"; +"LEARN_MORE_WELCOME" = "Tout d’abord, en savoir plus sur l’étude"; +"LEARN_MORE_STUDY_SURVEY" = "En savoir plus sur l’enquête de l’étude"; +"LEARN_MORE_TIME_COMMITMENT" = "En savoir plus sur l’impact de l’étude sur votre agenda"; +"LEARN_MORE_TASKS" = "En savoir plus sur les tâches concernées"; +"LEARN_MORE_WITHDRAWING" = "En savoir plus sur l’abandon"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Options de partage"; +"CONSENT_SHARE_WIDELY_%@" = "Partager mes données avec %@ et les chercheurs qualifiés de par le monde"; +"CONSENT_SHARE_ONLY_%@" = "Ne partager mes données qu’avec %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ recevra les données de votre participation à cette étude.\n\nLe partage de vos données codées relatives à l’étude (hormis les informations, telles que votre nom) pourrait permettre de faire avancer cette recherche et les recherches futures."; +"LEARN_MORE_CONSENT_SHARING" = "Plus d’info sur le partage des données"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nom en caractère d’imprimerie"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signature"; +"CONSENT_DOC_LINE_DATE" = "Date"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ sur %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Question %1$@ sur %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Ignoré"; +"REVIEW_EDIT_ANSWER" = "Modifier"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valeur non valide"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ dépasse la valeur maximale autorisée (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ est inférieur à la valeur minimale autorisée (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ n’est pas une valeur valide."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Adresse courriel non valide : %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Entrer une adresse"; +"LOCATION_ERROR_TITLE" = "Adresse indiquée introuvable"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Impossible de déterminer votre position actuelle. Tapez une adresse ou déplacez-vous vers un endroit où le signal GPS est meilleur, si possible."; +"LOCATION_ERROR_MESSAGE_DENIED" = "L’accès au service de localisation a été refusé. Veuillez autoriser cette app à utiliser le service de localisation dans Réglages."; +"LOCATION_ERROR_GEOCODE" = "Impossible de trouver un résultat pour l’adresse indiquée. Assurez-vous que celle-ci est valide."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Soit vous n’êtes pas connecté à Internet ou vous avez atteint la limite de demandes de recherche d’adresses. Si vous n’êtes pas connecté à Internet, activez le Wi-Fi pour répondre à cette question, ignorez cette question si le bouton ignorer est disponible, ou revenez au questionnaire lorsque vous êtes connecté à Internet. Sinon, réessayez dans quelques minutes."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "La longueur du texte dépasse le maximum autorisé : %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Caméra indisponible en écran scindé."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Courriel"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "gallain@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Mot de passe"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Entrer le mot de passe"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmer"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Entrer à nouveau le mot de passe"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Les mots de passe sont différents."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informations supplémentaires"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Gilles"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Allain"; +"GENDER_FORM_ITEM_TITLE" = "Sexe"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Choisir un sexe"; +"DOB_FORM_ITEM_TITLE" = "Date de naissance"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Choisir une date"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Numéro de téléphone"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Vérification"; +"VERIFICATION_STEP_TITLE" = "Vérifiez votre courriel"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Touchez le lien ci-dessous si vous n’avez pas reçu de courriel de confirmation et que vous souhaitez qu’il vous soit envoyé à nouveau."; +"RESEND_EMAIL_BUTTON_TITLE" = "Renvoyer le courriel de vérification"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Connexion"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Mot de passe oublié?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Entrez le code."; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmez le code."; +"PASSCODE_SAVED_MESSAGE" = "Code enregistré"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Code authentifié"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Entrez votre ancien code."; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Entrez votre nouveau code."; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirmez votre nouveau code."; +"PASSCODE_INVALID_ALERT_TITLE" = "Code incorrect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Les codes sont différents. Réessayez."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Authentifiez-vous avec Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Erreur de Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Seuls les caractères numériques sont autorisés."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicateur de progression de saisie du code"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ sur %@ chiffres entrés"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Code oublié?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Impossible d’ajouter l’élément du trousseau."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Impossible de mettre à jour l’élément du trousseau."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Impossible de supprimer l’élément du trousseau."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Impossible de trouver l’élément du trousseau."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Femme"; +"GENDER_MALE" = "Homme"; +"GENDER_OTHER" = "Autre"; + +/* Boolean answer strings */ +"BOOL_NO" = "Non"; +"BOOL_YES" = "Oui"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "pi"; +"MEASURING_UNIT_IN" = "po"; +"MEASURING_UNIT_KG" = " kg"; +"MEASURING_UNIT_LB" = " lb"; +"MEASURING_UNIT_OZ" = " oz"; + +/* Limb values. */ +"LIMB_LEFT" = "gauche"; +"LIMB_RIGHT" = "droite"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toucher pour répondre"; +"NULL_ANSWER" = "Sélectionner une réponse"; +"PLACEHOLDER_IMAGE_CHOICES" = "Toucher pour sélectionner"; +"PLACEHOLDER_LONG_TEXT" = "Toucher pour écrire"; + +/* Button titles */ +"BUTTON_AGREE" = "Accepter"; +"BUTTON_CANCEL" = "Annuler"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Effacer"; +"BUTTON_CLEAR_SIGNATURE" = "Effacer la signature"; +"BUTTON_APPLY" = "Appliquer"; +"BUTTON_DISAGREE" = "Refuser"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Démarrer"; +"BUTTON_LEARN_MORE" = "En savoir plus"; +"BUTTON_NEXT" = "Suivant"; +"BUTTON_SKIP" = "Ignorer"; +"BUTTON_SKIP_QUESTION" = "Ignorer cette question"; +"BUTTON_START_TIMER" = "Démarrer le minuteur"; +"BUTTON_OPTION_SAVE" = "Enregistrer pour plus tard"; +"BUTTON_OPTION_DISCARD" = "Supprimer les résultats"; +"BUTTON_OPTION_STOP_TASK" = "Terminer la tâche"; +"BUTTON_SAVE" = "Enregistrer"; +"BUTTON_CLEAR_ANSWER" = "Effacer la réponse"; +"BUTTON_READ_ONLY_MODE" = "Impossible de modifier cette réponse."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Fermer"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "L’activité commence dans"; +"TASK_COMPLETE_TITLE" = "Activité terminée"; +"TASK_COMPLETE_TEXT" = "Les données vont être analysées, et vous recevrez une notification lorsque les résultats seront disponibles."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ restantes."; +"TOUCH_ANYWHERE_LABEL" = "Touchez n’importe où pour continuer."; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturer l’image"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapturer l’image"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Caméra introuvable. Cette étape n’a pas pu être achevée."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Afin de conclure cette étape, autorisez cette app à accéder à la caméra dans Réglages."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Aucun répertoire de sortie n’a été spécifié pour les images capturées."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "L’image capturée n’a pas pu être enregistrée."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Lancer l’enregistrement"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Arrêter l’enregistrement"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapturer la vidéo"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Forme"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distance (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Rythme cardiaque (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Assoyez-vous confortablement pendant %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Marchez aussi vite que possible pendant %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Cette activité mesure votre rythme cardiaque, ainsi que la distance que vous pouvez parcourir à pied en %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Marchez aussi vite que possible pendant %1$@ en plein air. Ensuite, assoyez-vous et reposez-vous confortablement pendant %2$@. Pour commencer, touchez Démarrer."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Démarche et équilibre"; +"WALK_INTRO_TEXT" = "Cette activité mesure votre démarche et votre équilibre lorsque vous marchez et lorsque vous êtes immobile. Ne poursuivez pas cette activité si vous ne pouvez pas marcher sans assistance."; +"WALK_INTRO_2_TEXT_%ld" = "Trouvez un endroit adéquat pour parcourir %ld pas en ligne droite, en sécurité et sans assistance."; +"WALK_INTRO_2_DETAIL" = "Placez votre appareil dans une poche ou un sac, et suivez les instructions audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Ne bougez plus pendant %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Ne bougez pas pendant %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Retournez-vous, puis marchez vers votre point de départ."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Parcourez %ld pas en ligne droite."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Identifiez un endroit où vous pouvez faire des allers-retours en ligne droite de façon sécuritaire. Essayez de marcher sans vous arrêter, en faisant demi-tour en fin de ligne droite, comme si vous contourniez un cône.\n\nIl vous sera ensuite demandé de vous retourner en effectuant un cercle complet, puis de rester immobile, les bras le long du corps et les pieds dans l’alignement des épaules."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Touchez Démarrer lorsque vous êtes prêt.\nPlacez ensuite votre appareil dans une poche ou un sac, puis suivez les instructions audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Faites des allers-retours en ligne droite pendant %@. Marchez de façon habituelle."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Effectuez un cercle complet, puis restez immobile pendant %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Vous avez terminé l’activité."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Vitesse de frappe"; +"TAPPING_TASK_TITLE_RIGHT" = "Main droite"; +"TAPPING_TASK_TITLE_LEFT" = "Main gauche"; +"TAPPING_INTRO_TEXT" = "Cette activité mesure votre vitesse de frappe."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Placez votre appareil sur une surface plane."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Utilisez deux doigts d’une même main pour toucher tour à tour les boutons affichés à l’écran."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Utilisez deux doigts de la main droite pour toucher tour à tour les boutons affichés à l’écran."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Utilisez deux doigts de la main gauche pour toucher tour à tour les boutons affichés à l’écran."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Maintenant, répétez le test avec la main droite."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Maintenant, répétez le test avec la main gauche."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Touchez l’écran avec un doigt, puis avec l’autre. Faites en sorte que les contacts soient aussi réguliers que possible. Continuez pendant %@."; +"TAPPING_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Touchez Suivant pour commencer."; +"TAP_BUTTON_TITLE" = "Toucher"; +"TOTAL_TAPS_LABEL" = "Total de contacts"; +"TAPPING_INSTRUCTION" = "Touchez les boutons aussi régulièrement que possible avec deux doigts."; +"TAPPING_INSTRUCTION_RIGHT" = "Touchez les boutons avec la main DROITE."; +"TAPPING_INSTRUCTION_LEFT" = "Touchez les boutons avec la main GAUCHE."; +"TAPPING_SKIP_TITLE" = "Ignorer cette main"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Grille d’Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Cette activité contribue à détecter les problèmes de vision de l’utilisateur."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Tenez l’appareil à 30 cm de votre visage et à hauteur des yeux pendant toute la durée du test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Fermez votre %@ et fixez le point au centre de la grille.\n\nUtilisez votre doigt ou le stylet et indiquez toutes les distortions que vous voyez, par exemple des lignes floues ou ondulées.\n\nLorsque vous avez terminé, balayez vers la gauche sur un point à l’extérieur de la grille."; +"AMSLER_GRID_LEFT_EYE" = "œil gauche"; +"AMSLER_GRID_RIGHT_EYE" = "œil droit"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voix"; +"AUDIO_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"AUDIO_INSTRUCTION" = "Dites « Aaaaa » dans le micro le plus longtemps possible."; +"AUDIO_INTRO_TEXT" = "Respirez profondément et dites « Aaaaa » dans le micro le plus longtemps possible. Produisez un volume vocal stable de façon à ce que les barres audio restent bleues."; +"AUDIO_INTENDED_USE" = "Cette activité évalue votre voix en l’enregistrant grâce au micro situé au bas de votre appareil."; +"AUDIO_TOO_LOUD_LABEL" = "Trop fort"; +"AUDIO_GENERIC_ERROR_LABEL" = "Impossible d’enregistrer le son"; +"AUDIO_LEVEL_CHECK_LABEL" = "Veuillez patienter pendant que nous vérifions le niveau de bruit de fond."; +"AUDIO_TOO_LOUD_MESSAGE" = "Le niveau de bruit ambiant est trop élevé pour enregistrer votre voix. Choisissez un endroit plus silencieux, puis réessayez."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Touchez Suivant lorsque vous êtes prêt."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiométrie tonale"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Cette activité mesure votre aptitude à entendre différents sons."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Avant de commencer, branchez et mettez vos écouteurs.\n\nLe son sera très subtil, contrairement à un son d’alerte. Il sera d’abord très doux, puis il s’intensifiera peu à peu. Soyez attentif et touchez le bouton gauche ou droit pour indiquer quelle oreille perçoit le son."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Vous devriez maintenant entendre un son. Réglez le volume en utilisant les boutons latéraux de votre appareil.\n\nTouchez n’importe quel bouton lorsque vous êtes prêt."; +"TONE_AUDIOMETRY_INSTRUCTION" = "À chaque fois que vous commencez à entendre un son, touchez le bouton gauche ou droit pour indiquer quelle oreille perçoit le son."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Oreille gauche"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Oreille droite"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, gauche"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, droite"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiométrie tonale"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Touchez dès que vous entendez une tonalité."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tonalité et volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Vous entendrez une série de tonalités."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Touchez le bouton dès que vous entendez une tonalité."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Pour ce test, le volume sera réglé à 50 pour cent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Ce test prend environ dix minutes."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activez Ne pas déranger pour éviter les interruptions."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Les tonalités seront d’abord émises dans votre oreille droite."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Les tonalités seront maintenant émises dans votre oreille gauche."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Cette activité identifie les niveaux de seuil d’audition d’une personne en fonction de l’échelle dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Assurez-vous que le volume de l’appareil soit réglé au niveau le plus élevé.\n\nPendant cette tâche, une tonalité subtile se fera entendre soit dans l’oreille droite ou la gauche.\n\nÉcoutez avec attention et touchez le bouton chaque fois que vous entendez une tonalité."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ce test mesure le volume minimum que vous êtes en mesure d’entendre."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Questionnaire d’accueil"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Sélectionnez votre préférence pour la « meilleure oreille » si vous en avez une."; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "gauche"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "droite"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "aucune préférence"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test annulé"; +"dBHL_ALERT_TITLE_START_OVER" = "Recommencer"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Annuler le test"; +"dBHL_ALERT_TEXT" = "Reconnectez vos AirPods ou vos EarPods pour effectuer ce test."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ terminé"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Écouteurs"; +"HEADPHONES_UNKNOWN" = "Inconnu"; +"HEADPHONES_NONE" = "Aucun"; +"CONNECTED" = "Connecté"; +"NOT_CONNECTED" = "Non connectés"; +"HEADPHONE_CONNECTED_%@" = "Connecté - %@"; +"HEADPHONE_DETECT_TITLE" = "Connectez vos écouteurs"; +"HEADPHONE_DETECT_TEXT" = "Ce test requiert l’utilisation d’AirPods ou d’EarPods d’Apple."; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Mémoire spatiale"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Cette activité mesure votre mémoire spatiale à court terme en vous demandant de reproduire l’ordre dans lequel les %@ se sont allumées."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "fleurs"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "fleurs"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Certaines %@ s’allumeront une par une. Touchez ces %@ dans l’ordre duquel elles se sont allumées."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Certaines %@ s’allumeront une par une. Touchez ces %@ dans l’ordre inverse duquel elles se sont allumées."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Pour commencer, touchez Démarrer et soyez attentif."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Score"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Observez les %@ s’allumer"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Touchez les %@ dans l’ordre d’affichage."; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Touchez les %@ dans l’ordre inverse."; +"MEMORY_GAME_COMPLETE_TITLE" = "Séquence terminée"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Pour continuer, touchez Suivant"; +"MEMORY_GAME_FAILED_TITLE" = "Réessayer"; +"MEMORY_GAME_FAILED_MESSAGE" = "Vous n’y êtes pas arrivé cette fois-ci. Touchez Suivant pour continuer."; +"MEMORY_GAME_TIMEOUT_TITLE" = "C’est l’heure"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Le temps s’est écoulé.\nTouchez Suivant pour continuer."; +"MEMORY_GAME_COMPLETE" = "Jeu terminé"; +"MEMORY_GAME_PAUSED_TITLE" = "En pause"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Pour continuer, touchez Suivant"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "L’activité de mémoire a été développée avec l’aide de Dre Katherine Possin et de Dr Joel Kramer de l’université de Californie à San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Temps de réaction"; +"REACTION_TIME_TASK_INTENDED_USE" = "Cette activité évalue votre temps de réaction pour répondre à un signal visuel."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Secouez l’appareil dans n’importe quel sens dès que le point bleu apparaît à l’écran. Vous serez invité à effectuer cette action %D fois."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Tentative %@ sur %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Secouez rapidement l’appareil lorsque le cercle bleu apparaît."; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "À chaque fois qu’un mot apparaît, sélectionnez la première lettre du nom de la COULEUR affichée."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Touchez Démarrer lorsque vous êtes prêt à commencer l’activité Stroop."; +"STROOP_TASK_STEP_TEXT" = "Sélectionnez la première lettre du nom de la COULEUR affichée."; +"STROOP_COLOR_RED" = "ROUGE"; +"STROOP_COLOR_GREEN" = "VERT"; +"STROOP_COLOR_BLUE" = "BLEU"; +"STROOP_COLOR_YELLOW" = "JAUNE"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "J"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tours de Hanoï"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Cette activité évalue votre capacité à résoudre un casse-tête."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Déplacez toute la pile vers la plateforme surlignée en effectuant un minimum de mouvements."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Résoudre le casse-tête"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Nombre de mouvements : %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Je n’arrive pas à résoudre ce casse-tête"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Amplitude de mouvement"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption : gauche ou droit."; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitude articulaire du genou gauche"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitude articulaire du genou droit"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Cette activité mesure l’extension de votre genou gauche."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Cette activité mesure l’extension de votre genou droit."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Assoyez-vous sur le bord d’une chaise. Vous débuterez l’activité en plaçant votre appareil sur le genou gauche pour effectuer une mesure. Activez le son de votre appareil pour écouter les instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Assoyez-vous sur le bord d’une chaise. Vous débuterez l’activité en plaçant votre appareil sur le genou droit pour effectuer une mesure. Activez le son de votre appareil pour écouter les instructions."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placez votre appareil sur votre genou gauche avec l’écran vers le haut, comme illustré ici."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placez votre appareil sur votre genou droit avec l’écran vers le haut, comme illustré ici."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre genou gauche le plus loin possible. Revenez en position de départ et touchez à nouveau quand vous avez terminé."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre genou droit le plus loin possible. Revenez en position de départ et touchez à nouveau quand vous avez terminé."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placez votre appareil sur votre genou gauche. Touchez l’écran et étendez votre genou gauche le plus loin possible."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placez votre appareil sur votre genou droit. Touchez l’écran et étendez votre genou droit le plus loin possible."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Lorsque vous avez terminé, remettez votre genou gauche en position de départ. Puis, touchez n’importe où."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Lorsque vous avez terminé, remettez votre genou droit en position de départ. Puis, touchez n’importe où."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitude articulaire de l’épaule gauche"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitude articulaire de l’épaule droite"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Cette activité mesure l’extension de votre épaule gauche."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Cette activité mesure l’extension de votre épaule droite."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Vous débuterez l’activité en plaçant votre appareil sur l’épaule gauche pour effectuer une mesure. Activez le son de votre appareil pour écouter les instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Vous débuterez l’activité en plaçant votre appareil sur l’épaule droite pour effectuer une mesure. Activez le son de votre appareil pour écouter les instructions."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placez votre appareil sur votre épaule gauche avec l’écran vers le haut, comme illustré ici."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placez votre appareil sur votre épaule droite avec l’écran vers le haut, comme illustré ici."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre bras gauche le plus loin possible. Revenez en position de départ et touchez à nouveau quand vous avez terminé."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Lorsque vous êtes prêt, touchez l’écran pour commencer et étendez votre bras droit le plus loin possible. Revenez en position de départ et touchez à nouveau quand vous avez terminé."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placez votre appareil sur votre épaule gauche. Touchez l’écran et étendez votre bras gauche le plus loin possible vers l’avant."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placez votre appareil sur votre épaule droite. Touchez l’écran et étendez votre bras droit le plus loin possible vers l’avant."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Lorsque vous avez terminé, remettez votre bras gauche en position de départ. Puis, touchez n’importe où."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Lorsque vous avez terminé, remettez votre bras droit en position de départ. Puis, touchez n’importe où."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Marche chronométrée"; +"TIMED_WALK_INTRO_DETAIL" = "Cette activité évalue la fonction des membres inférieurs."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Identifiez un endroit, de préférence à l’extérieur, où vous pouvez marcher sur %@ en ligne droite, le plus vite possible, mais en toute sécurité. Ne ralentissez pas tant que vous n’avez pas franchi la ligne d’arrivée."; +"TIMED_WALK_INTRO_2_DETAIL" = "Touchez Suivant pour commencer."; +"TIMED_WALK_FORM_TITLE" = "Appareil d’assistance"; +"TIMED_WALK_FORM_TEXT" = "Utilisez le même appareil d’assistance pour chaque test."; +"TIMED_WALK_QUESTION_TEXT" = "Portez-vous une orthèse de cheville et de pied?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Utilisez-vous un appareil d’assistance?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Sélectionnez une réponse."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Aucun"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Une canne"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Une béquille"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Deux cannes"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Deux béquilles"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Cadre de marche / ambulateur"; +"TIMED_WALK_INSTRUCTION_%@" = "Parcourez %@ en ligne droite."; +"TIMED_WALK_INSTRUCTION_TURN" = "Faites demi-tour."; +"TIMED_WALK_INSTRUCTION_2" = "Marchez vers votre point de départ."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Touchez Suivant lorsque vous avez terminé."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Le test rythmé d’addition en série auditive (PASAT) mesure la vitesse de traitement d’informations auditives, ainsi que la capacité de calcul."; +"PVSAT_INTRO_TEXT" = "Le test rythmé d’addition en série visuelle (PAVAT) mesure la vitesse de traitement d’informations visuelles, ainsi que la capacité de calcul."; +"PAVSAT_INTRO_TEXT" = "Le test rythmé d’addition en série auditive et visuelle (PAVSAT) mesure la vitesse de traitement d’informations auditives et visuelles, ainsi que la capacité de calcul."; +"PSAT_INTRO_TEXT_2_%@" = "Les chiffres s’affichent toutes les %@.\nVous devez ajouter chaque nouveau chiffre au chiffre précédent.\nAttention, vous ne devez pas calculer la somme totale, mais bien la somme des deux derniers chiffres."; +"PSAT_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"PSAT_INITIAL_INSTRUCTION" = "Mémorisez ce premier chiffre."; +"PSAT_INSTRUCTION" = "Ajoutez ce nouveau chiffre au précédent."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test des %@ trous"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Cette activité mesure la dextérité de vos membres supérieurs en vous demandant de placer un cercle dans un trou. On vous demandera de le faire %@ fois."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Votre main gauche et votre main droite seront testées.\nVous devez saisir la cheville aussi rapidement que possible, la placer dans le trou et, après avoir fait cela %@ fois, la retirer à nouveau %@ fois."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Votre main droite et votre main gauche seront testées.\nVous devez saisir la cheville aussi rapidement que possible, la placer dans le trou et, après avoir fait cela %@ fois, la retirer à nouveau %@ fois."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Placez le cercle dans le trou en utilisant votre main gauche."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Placez le cercle dans le trou en utilisant votre main droite."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Placez le cercle derrière la ligne en utilisant votre main gauche."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Placez le cercle derrière la ligne en utilisant votre main droite."; +"HOLE_PEG_TEST_TEXT" = "Saisissez le cercle avec deux doigts."; +"HOLE_PEG_TEST_TEXT_2" = "Levez vos doigts pour relâcher le cercle."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremblements"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Cette activité mesure les tremblements de vos mains dans plusieurs positions. Choisissez un endroit où vous pouvez vous assoir confortablement pendant la durée de cette activité."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Tenez le téléphone dans la main la plus affectée comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Tenez le téléphone dans la main DROITE comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Tenez le téléphone dans la main GAUCHE comme indiqué dans l’image ci-dessous."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Il vous sera demandé d’effectuer %@ tout en étant assis avec le téléphone dans la main."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "une tâche"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "deux tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "trois tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quatre tâches"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinq tâches"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Touchez Suivant pour continuer."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Préparez-vous à tenir votre téléphone sur vos genoux."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Préparez-vous à tenir votre téléphone sur vos genoux avec votre main GAUCHE."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Préparez-vous à tenir votre téléphone sur vos genoux avec votre main DROITE."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Tenez votre téléphone sur vos genoux pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Maintenant, tenez votre téléphone en tendant votre bras à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Maintenant, tenez votre téléphone dans la main GAUCHE en tendant votre bras à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Maintenant, tenez votre téléphone dans la main DROITE en tendant votre bras à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Tenez votre téléphone avec la main tendue pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Maintenant, tenez votre téléphone et pliez le coude à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Maintenant, tenez votre téléphone dans la main GAUCHE et pliez le coude à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Maintenant, tenez votre téléphone dans la main DROITE et pliez le coude à la hauteur de votre épaule."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Tenez votre téléphone et pliez le coude pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Maintenant, pliez le coude et touchez votre nez avec le téléphone de façon répétée."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Maintenant, pliez le coude tout en tenant votre téléphone dans la main GAUCHE et touchez votre nez avec le téléphone de façon répétée."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Maintenant, pliez le coude tout en tenant votre téléphone dans la main DROITE et touchez votre nez avec le téléphone de façon répétée."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Touchez votre nez avec le téléphone à plusieurs reprises pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Préparez-vous à saluer en faisant pivoter le poignet."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Préparez-vous à saluer de la main GAUCHE en tenant le téléphone."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Préparez-vous à saluer de la main DROITE en tenant le téléphone."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Saluez de la main pendant %ld secondes."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Prenez le téléphone dans la main GAUCHE, puis passez à la tâche suivante."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Prenez le téléphone dans la main DROITE, puis passez à la tâche suivante."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Passez à la tâche suivante."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activité terminée."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Il vous sera demandé d’effectuer %@ tout en étant assis avec le téléphone dans une main, puis dans l’autre."; +"TREMOR_SKIP_LEFT_HAND" = "Je ne peux pas effectuer cette activité avec la main GAUCHE."; +"TREMOR_SKIP_RIGHT_HAND" = "Je ne peux pas effectuer cette activité avec la main DROITE."; +"TREMOR_SKIP_NEITHER" = "Je peux effectuer cette activité avec les deux mains."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test des tracés"; +"TRAILMAKING_INTENDED_USE" = "Cette activité évalue votre attention visuelle et votre capacité à alterner les tâches en enregistrant le temps requis pour toucher une série de points dans l’ordre."; +"TRAILMAKING_INTENDED_USE2_A" = "Après le compte à rebours, touchez les points dans l’ordre en alternant chiffres et lettres. Commencez par le premier chiffre « 1 », puis les chiffres « 2 » – « 3 » – « 4 »… jusqu’au chiffre « 7 »."; +"TRAILMAKING_INTENDED_USE2_B" = "Après le compte à rebours, touchez les points dans l’ordre en alternant chiffres et lettres. Commencez par le premier chiffre « 1 », puis touchez la première lettre « A », puis « 2 » – « B » – « 3 » – « C »… jusqu’au chiffre « 7 »."; +"TRAILMAKING_INTRO_TEXT" = "Soyez aussi rapide que possible sans faire d’erreurs. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconnaissance vocale"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Cette activité enregistre vos paroles grâce au micro situé au bas de votre appareil, puis les transcrit en texte."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Touchez Démarrer pour commencer."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Appuyez sur le bouton pour démarrer l’enregistrement avant de parler."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Enregistrer"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Arrêter"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Modifier"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Modifiez la transcription afin de corriger toute erreur d’interprétation de la parole."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Votre transcription s’affichera ici."; +"SPEECH_RECOGNITION_FAILED" = "Échec de la reconnaissance vocale."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "L’initialisation de la reconnaissance vocale a échoué."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Écouter"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Arrêter l’audio"; +"SPEECH_IN_NOISE_TITLE" = "Parole dans le bruit"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Cette activité mesure l’intelligibilité de la parole dans des environnements bruyants."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Pendant ce test, vous :\n\nécouterez une phrase;\n\nrépéterez clairement ce que vous avez entendu ou passerez cette étape pour saisir ce que vous avez entendu à l’aide du clavier. \n\nSi vous répétez ce que vous avez entendu, vous pourrez ensuite modifier la transcription générée par l’engin de reconnaissance vocale."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Étalonnage du volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Touchez « Écouter », réglez votre volume à un niveau qui est confortable, puis touchez « Arrêter l’audio » pour continuer."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Écouter"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Une phrase mélangée à du bruit de fond ayant un rapport signal/bruit (RSB) réparti au hasard ne se fera entendre qu’une seule fois."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Énoncer"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Répétez ce que vous avez entendu."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Impossible de créer le fichier"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Impossible de supprimer suffisamment de fichiers d’historique pour atteindre le seuil"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Erreur de réglage d’attribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Fichier non marqué comme supprimé (non marqué comme téléchargé)"; +"ERROR_DATALOGGER_MULTIPLE" = "Plusieurs erreurs se sont produites lors de la suppression des historiques"; +"ERROR_RECORDER_NO_DATA" = "Aucune donnée recueillie n’a été trouvée."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Aucun répertoire de sortie n’est spécifié"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Mesure du NPA"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Cette activité mesure le niveau de pression acoustique de l’environnement. Dans le cas où les niveaux de bruits seraient trop élévés, il vous sera impossible de continuer. Veuillez vous déplacer dans un lieu plus silencieux pour terminer cette tâche ou reprendre cette activité plus tard."; +"ENVIRONMENTSPL_UNIT" = "dB(A)"; +"ENVIRONMENTSPL_CALCULATING" = "Calcul en cours"; +"ENVIRONMENTSPL_THRESHOLD" = "Seuil : %@ dB(A)"; +"ENVIRONMENTSPL_OK" = "Bruit de fond OK"; +"ENVIRONMENTSPL_NOISE" = "Trop de bruit en arrière-plan"; +"ENVIRONMENTSPL_TITLE_2" = "Choisissez un endroit calme."; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Pour obtenir la précision nécessaire, ce test doit être effectué dans un endroit calme."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Commencer la tâche"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Aucune donnée"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Déplacer le curseur pour entrer une valeur"; +"SLIDER_I_DONT_KNOW" = "Je ne sais pas"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Page"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Retour"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Afficher la vignette de PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Masquer la vignette de PDF"; +"AX_BUTTON_ANNOTATE" = "Annoter"; +"AX_BUTTON_SHOW_SEARCH" = "Afficher la barre de recherche"; +"AX_BUTTON_HIDE_SEARCH" = "Masquer la barre de recherche"; +"AX_BUTTON_SHARE" = "Partager"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration d’un cercle bleu coché signifiant la réussite"; + +"AX_SIGNVIEW_LABEL" = "Champ de signature désigné"; +"AX_SIGNVIEW_HINT" = "Toucher l’écran et signer du doigt"; +"AX_SIGNVIEW_SIGNED" = "Signé"; +"AX_SIGNVIEW_UNSIGNED" = "Non signé"; + +"AX_SELECTED" = "Sélectionné"; +"AX_UNSELECTED" = "Désélectionné"; +"AX_SELECT_ALL_THAT_APPLY" = "COCHEZ LES RÉPONSES."; + +"AX_SLIDER_LABEL" = "Curseur de réponse. De %@ à %@"; +"AX_UNLABELED_IMAGE" = "Image sans étiquette"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Démarrer la tâche"; + +"AX.MEMORY.TILE.ACTIVE" = "active"; +"AX.MEMORY.TILE.CORRECT" = "correct"; +"AX.MEMORY.TILE.INCORRECT" = "incorrect"; +"AX.MEMORY.TILE.QUIESCENT" = "calme"; +"AX.MEMORY.TILE.LABEL" = "Fiche du jeu de mémoire"; + +"AX_IMAGE_CAPTURE_LABEL" = "Aperçu de l’image capturée"; +"AX_IMAGE_CAPTURED_LABEL" = "Image capturée"; + +"AX_VIDEO_CAPTURE_LABEL" = "Aperçu de la vidéo capturée"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Enregistrement de la vidéo terminé"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Impossible de placer un disque de taille %@ sur un disque de taille %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cible"; +"AX_TOWER_OF_HANOI_TOWER" = "Tour"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Touchez deux fois pour placer le disque."; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Touchez deux fois pour sélectionner le disque le plus haut."; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Comporte des disques de tailles %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vide"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Masquer le clavier"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "De %@ à %@"; +"AX_GRAPH_STACK_PREFIX" = "Pile composée de"; +"AX_GRAPH_AND_SEPARATOR" = " et "; +"AX_GRAPH_POINT_%@" = "Point : %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forme d’onde de parole"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Une fois l’enregistrement commencé, activez de nouveau pour cesser l’enregistrement."; + +"AX_AUDIO_BAR_GRAPH" = "Graphique audio à barres"; + +"AX_AMSLER_GRID_LABEL" = "Grille d’Amsler"; +"AX_AMSLER_GRID_HINT" = "Utilisez votre doigt ou le stylet pour marquer la grille directement, ou balayez vers la gauche à l’extérieur de la grille pour terminer."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Boutons touchables"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Toucher pour l’oreille gauche"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activez pour commencer le test. Une fois le test commencé, touchez directement ce bouton lorsque vous entendrez un son dans votre oreille gauche."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Toucher pour l’oreille droite"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activez pour commencer le test. Une fois le test commencé, touchez directement ce bouton lorsque vous entendrez un son dans votre oreille droite."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ À l’aide de VoiceOver, explorez l’écran en le touchant pour découvrir où les boutons sont situés pour chaque oreille. Lorsque le test commencera, les boutons pourront être touchés directement. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Toucher pour un doigt"; +"AX_TAP_BUTTON_2_LABEL" = "Toucher pour un autre doigt"; +"AX_TAP_BUTTON_HINT" = "Activez pour permettre aux boutons d’être touchés directement."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ À l’aide de VoiceOver, explorez l’écran en le touchant pour découvrir où les boutons sont situés. Activez l’un des boutons pour que tous les boutons puissent être touchés directement."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Les boutons peuvent maintenant être directement touchés."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Le bouton pourra être touché directement à l’aide de VoiceOver. Il sera situé près du centre de l’écran."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Les boutons du test pourront être touchés directement à l’aide de VoiceOver."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Impossible de décoder restoreData pour l’initialisation"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..6430399 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/fr_CA.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d erreur) + other + (%d erreurs) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.strings new file mode 100755 index 0000000..6af0925 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "הסכמה"; +"CONSENT_NAME_GIVEN" = "שם פרטי"; +"CONSENT_NAME_FAMILY" = "שם משפחה"; +"CONSENT_NAME_PLACEHOLDER" = "חובה"; +"CONSENT_REVIEW_TITLE" = "נא לקרוא בעיון"; +"CONSENT_REVIEW_INSTRUCTION" = "יש לעיין בטופס הבא ולהקיש על ״אני מסכים/ה״ כדי להמשיך."; +"CONSENT_REVIEW_ALERT_TITLE" = "נא לקרוא בעיון"; +"CONSENT_SIGNATURE_TITLE" = "חתימה"; +"CONSENT_SIGNATURE_INSTRUCTION" = "חתום/י עם האצבע בתיבה שלמטה."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "חתום/י כאן"; +"CONSENT_PAGE_NUMBER_FORMAT" = "עמוד %1$ld מתוך %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "ברוך/ה הבא/ה"; +"CONSENT_SECTION_DATA_GATHERING" = "איסוף נתונים"; +"CONSENT_SECTION_PRIVACY" = "פרטיות"; +"CONSENT_SECTION_DATA_USE" = "שימוש בנתונים"; +"CONSENT_SECTION_STUDY_SURVEY" = "סקר מחקר"; +"CONSENT_SECTION_STUDY_TASKS" = "משימות מחקר"; +"CONSENT_SECTION_TIME_COMMITMENT" = "התחייבות זמן"; +"CONSENT_SECTION_WITHDRAWING" = "ביטול השתתפות"; +"CONSENT_LEARN_MORE_TITLE" = "פרטים נוספים"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "קבל/י מידע נוסף על איסוף הנתונים"; +"LEARN_MORE_DATA_USE" = "קבל/י מידע נוסף על השימוש בנתונים"; +"LEARN_MORE_PRIVACY" = "קבל/י מידע נוסף בנושא ההגנה על הפרטיות והזהות שלך"; +"LEARN_MORE_WELCOME" = "קבל/י מידע נוסף תחילה בנושא המחקר"; +"LEARN_MORE_STUDY_SURVEY" = "קבל/י מידע נוסף בנושא סקר המחקר"; +"LEARN_MORE_TIME_COMMITMENT" = "קבל/י מידע נוסף בנושא השפעת המחקר על זמנך"; +"LEARN_MORE_TASKS" = "קבל/י מידע נוסף בנושא המשימות הכרוכות"; +"LEARN_MORE_WITHDRAWING" = "קבל/י מידע נוסף בנושא ביטול ההשתתפות"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "אפשרויות שיתוף"; +"CONSENT_SHARE_WIDELY_%@" = "שתף את הנתונים שלי עם %@ ועם חוקרים מוסמכים מכל העולם"; +"CONSENT_SHARE_ONLY_%@" = "שתף את הנתונים שלי רק עם %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "נתוני המחקר שבו השתתפת יישלחו אל %@.\n\nשיתוף נרחב יותר של נתונים מקודדים מהמחקר שלך (שאינם כוללים מידע אישי כמו השם שלך) עשוי לתרום למחקר זה ולמחקרים עתידיים."; +"LEARN_MORE_CONSENT_SHARING" = "קבל/י מידע נוסף בנושא שיתוף נתונים"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "שם מלא"; +"CONSENT_DOC_LINE_SIGNATURE" = "חתימה"; +"CONSENT_DOC_LINE_DATE" = "תאריך"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ מתוך %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "שאלה %1$@ מתוך %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "דילגת על פריט זה"; +"REVIEW_EDIT_ANSWER" = "עריכה"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "ערך שאינו תקין"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ חורג מהערך המרבי המותר (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ נמוך מהערך המינימלי המותר (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ הוא לא ערך תקין."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "כתובת דוא״ל לא תקינה: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "הקש/י כתובת"; +"LOCATION_ERROR_TITLE" = "לא ניתן למצוא את הכתובת שצוינה"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "לא ניתן לזהות את מיקומך הנוכחי. הקלד/י כתובת או עבור/י אל מיקום שבו קליטת ה-GPS טובה יותר, אם אפשר."; +"LOCATION_ERROR_MESSAGE_DENIED" = "הגישה אל שירותי המיקום נדחתה. הענק/י ליישום זה הרשאה להשתמש בשירותי המיקום דרך ״הגדרות״."; +"LOCATION_ERROR_GEOCODE" = "לא ניתן למצוא תוצאה עבור הכתובת שהוקשה. ודא/י שהכתובת תקינה."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "יתכן שאינך מחובר/ת לאינטרנט, או שחרגת מהמספר המרבי המותר של בקשות בדיקת כתובת. אם אינך מחובר/ת לאינטרנט, הפעל/י את הרשת האלחוטית בכדי לענות על שאלה זו, דלג/י על השאלה אם כפתור הדילוג זמין, או חזור/י ובצע/י שוב את הסקר כשתהיה/י מחובר/ת לאינטרנט. אחרת, נסה/י שוב בעוד כמה דקות."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "תוכן המלל חורג מהאורך המרבי: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "המצלמה אינה זמינה במסך מפוצל."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "שלח בדוא״ל"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "israelisraeli@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "סיסמה"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "הקש/י סיסמה"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "אשר/י"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "הקש/י את הסיסמה שוב"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "הסיסמאות לא היו זהות."; +"ADDITIONAL_INFO_SECTION_TITLE" = "מידע נוסף"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "ישראל"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "ישראלי"; +"GENDER_FORM_ITEM_TITLE" = "מין"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "בחר/י מין"; +"DOB_FORM_ITEM_TITLE" = "תאריך לידה"; +"DOB_FORM_ITEM_PLACEHOLDER" = "בחר/י תאריך"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "מספר טלפון"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "‏‎+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "אימות"; +"VERIFICATION_STEP_TITLE" = "אימות הדוא״ל שלך"; +"RESEND_EMAIL_LABEL_MESSAGE" = "הקש/י על הקישור שלמטה אם לא קיבלת דוא״ל אימות וברצונך שהוא יישלח שוב."; +"RESEND_EMAIL_BUTTON_TITLE" = "שלח הודעת דוא״ל לאימות מחדש"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "התחבר"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "שכחת את הסיסמה?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "הקש/י את קוד הגישה"; +"PASSCODE_CONFIRM_MESSAGE" = "אשר/י קוד גישה"; +"PASSCODE_SAVED_MESSAGE" = "קוד הגישה נשמר"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "קוד הגישה מאומת"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "הקש/י את קוד הגישה הישן"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "הקש/י את קוד הגישה החדש"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "אשר/י את קוד הגישה החדש"; +"PASSCODE_INVALID_ALERT_TITLE" = "קוד הגישה שגוי"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "קודי הגישה לא היו זהים. נסה/י שוב."; +"PASSCODE_TOUCH_ID_MESSAGE" = "בצע/י אימות באמצעות Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "שגיאת Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "ניתן להשתמש בתווי ספרות בלבד."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "מד התקדמות של הקשת קוד גישה"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "הוקשו %@ מתוך %@ ספרות"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "שכחת את קוד הגישה?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "לא ניתן היה להוסיף את פריט צרור המפתחות."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "לא ניתן היה לעדכן את פריט צרור המפתחות."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "לא ניתן היה למחוק את פריט צרור המפתחות."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "לא ניתן היה למצוא את פריט צרור המפתחות."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "‎A+‎"; +"BLOOD_TYPE_A-" = "‎A-‎"; +"BLOOD_TYPE_AB+" = "‎AB+‎"; +"BLOOD_TYPE_AB-" = "‎AB-‎"; +"BLOOD_TYPE_B+" = "‎B+‎"; +"BLOOD_TYPE_B-" = "‎B-‎"; +"BLOOD_TYPE_O+" = "‎O+‎"; +"BLOOD_TYPE_O-" = "‎O-‎"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "סוג עור 1"; +"FITZPATRICK_SKIN_TYPE_II" = "סוג עור 2"; +"FITZPATRICK_SKIN_TYPE_III" = "סוג עור 3"; +"FITZPATRICK_SKIN_TYPE_IV" = "סוג עור 4"; +"FITZPATRICK_SKIN_TYPE_V" = "סוג עור 5"; +"FITZPATRICK_SKIN_TYPE_VI" = "סוג עור 6"; + +/* Gender values. */ +"GENDER_FEMALE" = "נקבה"; +"GENDER_MALE" = "זכר"; +"GENDER_OTHER" = "אחר"; + +/* Boolean answer strings */ +"BOOL_NO" = "לא"; +"BOOL_YES" = "כן"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "ס״מ"; +"MEASURING_UNIT_FT" = "רגל"; +"MEASURING_UNIT_IN" = "אינץ׳"; +"MEASURING_UNIT_KG" = "ק״ג"; +"MEASURING_UNIT_LB" = "ליב׳"; +"MEASURING_UNIT_OZ" = "אונק׳"; + +/* Limb values. */ +"LIMB_LEFT" = "שמאל"; +"LIMB_RIGHT" = "ימין"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "הקש/י בכדי לענות"; +"NULL_ANSWER" = "בחר/י תשובה"; +"PLACEHOLDER_IMAGE_CHOICES" = "הקש/י לבחירה"; +"PLACEHOLDER_LONG_TEXT" = "הקש/י לכתיבה"; + +/* Button titles */ +"BUTTON_AGREE" = "אני מסכים/ה"; +"BUTTON_CANCEL" = "ביטול"; +"BUTTON_OK" = "אישור"; +"BUTTON_CLEAR" = "נקה"; +"BUTTON_CLEAR_SIGNATURE" = "נקה את החתימה"; +"BUTTON_APPLY" = "החל"; +"BUTTON_DISAGREE" = "איני מסכים/ה"; +"BUTTON_DONE" = "סיום"; +"BUTTON_GET_STARTED" = "התחלה"; +"BUTTON_LEARN_MORE" = "פרטים נוספים"; +"BUTTON_NEXT" = "הבא"; +"BUTTON_SKIP" = "דלג"; +"BUTTON_SKIP_QUESTION" = "דלג על שאלה זו"; +"BUTTON_START_TIMER" = "הפעל את שעון העצר"; +"BUTTON_OPTION_SAVE" = "שמור למועד מאוחר יותר"; +"BUTTON_OPTION_DISCARD" = "מחק את התוצאות"; +"BUTTON_OPTION_STOP_TASK" = "סיים את המשימה"; +"BUTTON_SAVE" = "שמור"; +"BUTTON_CLEAR_ANSWER" = "נקה את התשובה"; +"BUTTON_READ_ONLY_MODE" = "לא ניתן לשנות את התשובה הזאת."; +"BUTTON_COPYRIGHT" = "זכויות יוצרים"; +"BUTTON_CLOSE" = "סגור"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "מתחיל פעילות בעוד"; +"TASK_COMPLETE_TITLE" = "הפעילות הושלמה"; +"TASK_COMPLETE_TEXT" = "הנתונים שלך ינותחו וכאשר התוצאות יהיו מוכנות תקבל/י הודעה."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "נותרו %@."; +"TOUCH_ANYWHERE_LABEL" = "גע/י במסך כדי להמשיך"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "צלם תמונה"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "צלם תמונה שוב"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "לא נמצאה מצלמה. לא ניתן להשלים שלב זה."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "על-מנת לסיים שלב זה, אפשר/י ליישום זה לגשת למצלמה שלך ב״הגדרות״."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "לא צוינה ספריית פלט עבור התמונות שצולמו."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "לא ניתן היה לשמור את התמונה שצולמה."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "התחל הקלטה"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "הפסק הקלטה"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "צלם/י את הסרט מחדש"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "כושר"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "מרחק (%@)"; +"FITNESS_HEARTRATE_TITLE" = "קצב לב (פעימות לדקה)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "שב/י בצורה נוחה למשך %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "לך/י הכי מהר שתוכל/י למשך %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "פעילות זו בודקת את קצב הלב שלך ומודדת כמה רחוק תוכל/י ללכת תוך %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "לך/י בחוץ בקצב המהיר ביותר שלך למשך %1$@. לסיום, התיישב/י והרגע/י למשך %2$@. כדי להתחיל, הקש/י על ״התחלה״."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "הליכה ואיזון"; +"WALK_INTRO_TEXT" = "פעילות זו מודדת את ההליכה והאיזון שלך תוך כדי הליכה ועמידה במקום. אל תמשיך/י אם אינך יכול/ה ללכת בבטחה ללא סיוע."; +"WALK_INTRO_2_TEXT_%ld" = "מצא/י מקום שבו תוכל/י ללכת בבטחה וללא סיוע למרחק של %ld צעדים בקו ישר."; +"WALK_INTRO_2_DETAIL" = "הנח/י את המכשיר בכיס או בתיק ופעל/י על-פי הנחיות השמע."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "כעת עמוד/י ללא תזוזה למשך %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "עמוד/י ללא תזוזה למשך %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "הסתובב/י והתהלך/י חזרה למקום שבו התחלת."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "לך/י %ld צעדים לכל היותר בקו ישר."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "מצא/י מקום שבו ניתן ללכת בקו ישר הלוך וחזור בבטחה. נסה/י לצעוד באופן רציף ולבצע פניות בקצוות המסלול, כאילו תוך הקפת קונוס דמיוני המסמן את הקצה.\n\nלאחר מכן, תתבקש/י ללכת במסלול מעגלי שלם ואז לעצור ולעמוד כשהידיים לצידי הגוף והרגליים בפיסוק קל ברוחב הכתפיים."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "הקש/י על ״התחלה״ כשתהיה/י מוכן/ה.\nלאחר מכן, הנח/י את המכשיר בכיס או בתיק ובצע/י את ההוראות שיושמעו לך."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "לך/י הלוך ושוב בקו ישר במשך %@, באופן ההליכה הרגיל שלך."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "בצע/י סיבוב שלם ולאחר מכן עמוד/י למשך %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "השלמת את הפעילות."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "מהירות הקשה"; +"TAPPING_TASK_TITLE_RIGHT" = "יד ימין"; +"TAPPING_TASK_TITLE_LEFT" = "יד שמאל"; +"TAPPING_INTRO_TEXT" = "פעילות זו מודדת את מהירות ההקשה שלך."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "הנח/י את המכשיר על משטח ישר."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "הקש/י על הכפתורים שמופיעים על המסך עם שתי אצבעות של אותה היד המתחלפות ביניהן לסירוגין."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "הקש/י על הכפתורים שמופיעים על המסך בשתי אצבעות יד ימין המתחלפות ביניהן לסירוגין."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "הקש/י על הכפתורים שמופיעים על המסך בשתי אצבעות יד שמאל המתחלפות ביניהן לסירוגין."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "כעת חזור/י על אותה פעולה ביד ימין."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "כעת חזור/י על אותה פעולה ביד שמאל."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "הקש/י באצבע אחת, ולאחר מכן בשניה. נסה/י להקיש בקצב קבוע ככל שתוכל/י. המשך/י להקיש למשך %@."; +"TAPPING_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"TAPPING_CALL_TO_ACTION_NEXT" = "הקש/י על ״הבא״ כדי להתחיל."; +"TAP_BUTTON_TITLE" = "הקש/י"; +"TOTAL_TAPS_LABEL" = "סה״כ הקשות"; +"TAPPING_INSTRUCTION" = "הקש/י על הכפתורים בשתי אצבעות באופן עקבי ככל שניתן."; +"TAPPING_INSTRUCTION_RIGHT" = "הקש/י על הכפתורים ביד ימין."; +"TAPPING_INSTRUCTION_LEFT" = "הקש/י על הכפתורים ביד שמאל."; +"TAPPING_SKIP_TITLE" = "דלג/י על יד זו"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "בדיקת רשת אמסלר"; +"AMSLER_GRID_INTRO_TEXT" = "פעילות זו עוזרת לזהות בעיות ראיה."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "החזק/י את המכשיר במרחק של כ-30 ס״מ מפניך ובגובה העיניים לכל אורך המבחן."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "עצום/י את %@ ונעץ/י את מבטך בנקודה שבמרכז הרשת המרובעת.\n\nכעת, באמצעות האצבע או עט דיגיטלי, סמן/י עיוותים הנראים לעין, כמו טשטושים או קווים גליים.\n\nלסיום, החלק/י ימינה בכל מקום מחוץ לרשת."; +"AMSLER_GRID_LEFT_EYE" = "עין שמאל"; +"AMSLER_GRID_RIGHT_EYE" = "עין ימין"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "קול"; +"AUDIO_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"AUDIO_INSTRUCTION" = "אמור/י ״אהההה״ לתוך המיקרופון למשך זמן ארוך ככל שתוכל/י."; +"AUDIO_INTRO_TEXT" = "נשום/י נשימה עמוקה ואמור/י ״אהההה״ לתוך המיקרופון למשך זמן ארוך ככל שתוכל/י. נסה/י לשמור על עוצמת קול קבועה כך שפסי השמע יישארו כחולים."; +"AUDIO_INTENDED_USE" = "פעילות זו מעריכה את קולך על-ידי הקלטתו דרך המיקרופון שבתחתית המכשיר."; +"AUDIO_TOO_LOUD_LABEL" = "חזק מדי"; +"AUDIO_GENERIC_ERROR_LABEL" = "לא ניתן להקליט שמע"; +"AUDIO_LEVEL_CHECK_LABEL" = "המתן/י עד לסיום מדידת רעשי הרקע."; +"AUDIO_TOO_LOUD_MESSAGE" = "רעש הרקע חזק מדי ולא ניתן להקליט את קולך. עבור/י למקום שקט יותר ונסה/י שוב."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "כשתהיה/י מוכן/ה, הקש/י על ״הבא״."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "בדיקת שמיעה"; +"TONE_AUDIOMETRY_INTENDED_USE" = "פעילות זו מודדת את יכולתך לשמוע צלילים שונים."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "לפני שתתחיל/י, חבר/י והרכב/י את האזניות.\n\nהצליל יהיה עדין מאוד ושונה מצליל התראה רגיל.  הוא יתחיל בעוצמה נמוכה שתלך ותגבר בהדרגה.  עליך להאזין לצליל ולהקיש על הכפתור הימני או השמאלי כדי לציין באיזו אוזן שמעת את הצליל."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"TONE_AUDIOMETRY_PREP_TEXT" = "כעת מושמע צליל. התאם/י את עוצמת השמע לפי הצורך באמצעות כפתורי עוצמת השמע בצד המכשיר.\n\nהקש/י על כפתור כלשהו כדי להתחיל."; +"TONE_AUDIOMETRY_INSTRUCTION" = "בכל פעם שתתחיל/י לשמוע את הצליל, הקש/י על הכפתור הימני או השמאלי כדי לציין באיזו אוזן שמעת אותו."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "אוזן שמאל"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "אוזן ימין"; +"TONE_LABEL_%@_LEFT" = "‏%@ הרץ, שמאל"; +"TONE_LABEL_%@_RIGHT" = "‏%@ הרץ, ימין"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "בדיקת שמיעה"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "הקש/י כאשר תשמע/י את הצליל."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "צליל ועוצמת קול"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "כעת יישמעו כמה צלילים ברצף."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "כאשר תשמע/י צליל, עליך להקיש על הכפתור."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "במהלך בדיקה זו, עוצמת הקול תיקבע ל-50 אחוז."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "משך הבדיקה הוא כ-10 דקות."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "מומלץ להפעיל את ״נא לא להפריע״ כדי למנוע הפרעות במהלך הבדיקה."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "הצלילים יושמעו באוזן ימין שלך תחילה."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "הצלילים יושמעו באוזן שמאל שלך."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "פעילות זו מזהה רמות סף של שמיעה בטווח דציבלים גבוה/נמוך."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "ודא/י שעוצמת הקול של המכשיר הוגדרה לעוצמה המקסימלית.\n\nבמהלך משימה זו, יישמע צליל עדין באוזן שמאל או באוזן ימין.\n\nהאזן/י בקפידה והקש/י על הכפתור בכל פעם שהינך שומע/ת צליל."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "בדיקה זו מזהה את עוצמת הצליל הנמוכה ביותר שביכולתך לשמוע."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "שאלון הצטרפות."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "בחר/י את העדפתך לגבי האוזן ״הטובה יותר״, אם יש כזו"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "שמאל"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "ימין"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ללא העדפה"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "הבדיקה בוטלה"; +"dBHL_ALERT_TITLE_START_OVER" = "התחל מחדש"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "בטל את הבדיקה"; +"dBHL_ALERT_TEXT" = "יש לחבר מחדש את ה-AirPods או ה-EarPods כדי להתחיל בבדיקה."; +"dBHL_PROGRESS_COMPLETION_%@" = "‏%@ הושלם"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "אזניות"; +"HEADPHONES_UNKNOWN" = "לא ידוע"; +"HEADPHONES_NONE" = "ללא"; +"CONNECTED" = "מחובר"; +"NOT_CONNECTED" = "לא מחובר"; +"HEADPHONE_CONNECTED_%@" = "מחובר - %@"; +"HEADPHONE_DETECT_TITLE" = "כעת עליך לחבר אזניות"; +"HEADPHONE_DETECT_TEXT" = "בדיקה זו דורשת שימוש ב-Apple AirPods או Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "זכרון מרחבי"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "פעילות זו מודדת את הזכרון המרחבי שלך לטווח קצר על-ידי הנחיה לחזור על הסדר שבו נדלקו ה%@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "פרחים"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "פרחים"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "כמה מה%@ יידלקו זה אחר זה. הקש/י על ה%@ בסדר זהה לזה שבו הם נדלקו."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "כמה מה%@ יידלקו זה אחר זה. הקש/י על ה%@ בסדר הפוך מזה שבו הם נדלקו."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "כדי להתחיל, הקש/י על ״התחלה״ וצפה/י בתשומת לב."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "תוצאה"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "צפה/י ב%@ נדלקים"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "הקש/י על ה%@ לפי הסדר שבו הם נדלקים"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "הקש/י על ה%@ בסדר הפוך"; +"MEMORY_GAME_COMPLETE_TITLE" = "הרצף הושלם"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "להמשך, הקש/י על ״הבא״."; +"MEMORY_GAME_FAILED_TITLE" = "נסה/י שוב"; +"MEMORY_GAME_FAILED_MESSAGE" = "לא השלמת את המשימה הפעם. הקש/י על ״הבא״ להמשך."; +"MEMORY_GAME_TIMEOUT_TITLE" = "נגמר הזמן"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "אזל הזמן.\nהקש/י על ״הבא״ להמשך."; +"MEMORY_GAME_COMPLETE" = "המשחק הושלם"; +"MEMORY_GAME_PAUSED_TITLE" = "מושהה"; +"MEMORY_GAME_PAUSED_MESSAGE" = "להמשך, הקש/י על ״הבא״."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "בדיקת הזיכרון פותחה בעזרתם של ד״ר קתרין פוסין (Katherine Possin, PhD) וד״ר ג׳ואל קרמר (Joel Kramer, PhD) מאוניברסיטת קליפורניה בסן-פרנסיסקו."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "זמן תגובה"; +"REACTION_TIME_TASK_INTENDED_USE" = "פעילות זו מעריכה את משך הזמן שלוקח לך להגיב לרמז חזותי."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "נער/י את המכשיר בכיוון כלשהו ברגע שהנקודה הכחולה מופיעה על המסך. תתבקש/י לעשות זאת %D פעמים."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "נסיון %@ מתוך %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "נער/י את המכשיר במהירות כשמופיע העיגול הכחול"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "מבחן סטרופ"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "בכל פעם שתופיע מילה, בחר/י את האות הראשונה של שם הצבע שבו כתובה המילה."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "כשתרצה/י להתחיל את מבחן סטרופ, הקש/י על ״התחלה״."; +"STROOP_TASK_STEP_TEXT" = "בחר/י את האות הראשונה של שם ה*צבע* שבו כתובה המילה."; +"STROOP_COLOR_RED" = "אדום"; +"STROOP_COLOR_GREEN" = "ירוק"; +"STROOP_COLOR_BLUE" = "כחול"; +"STROOP_COLOR_YELLOW" = "צהוב"; +"STROOP_COLOR_RED_INITIAL" = "א"; +"STROOP_COLOR_GREEN_INITIAL" = "י"; +"STROOP_COLOR_BLUE_INITIAL" = "כ"; +"STROOP_COLOR_YELLOW_INITIAL" = "צ"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "מגדל האנוי"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "פעילות זו מעריכה את מיומנויות פתרון הפאזלים שלך."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "הזז/י את המערום כולו אל הפלטפורמה המסומנת בכמה שפחות מהלכים."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "פתור/י את הפאזל"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "מספר מהלכים: %@ \n%@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "איני מצליח/ה לפתור את הפאזל"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "טווח תנועה"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "‏limbOption חייב להיות שמאל או ימין"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "טווח התנועה של ברך שמאל"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "טווח התנועה של ברך ימין"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "פעילות זו מודדת את טווח התנועה של הברך השמאלית שלך."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "פעילות זו מודדת את טווח התנועה של הברך הימנית שלך."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "שב/י על חלקו הקדמי של הכיסא. בתחילת הפעילות, תצטרך/י להניח את המכשיר על ברך שמאל כדי לבצע מדידות. ודא/י שהצליל במכשיר מופעל כדי שתוכל/י לשמוע את ההנחיות."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "שב/י על חלקו הקדמי של הכיסא. בתחילת הפעילות, תצטרך/י להניח את המכשיר על ברך ימין כדי לבצע מדידות. ודא/י שהצליל במכשיר מופעל כדי שתוכל/י לשמוע את ההנחיות."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "הנח/י את המכשיר על ברך שמאל כשהמסך מופנה כלפי מעלה, כפי שנראה בתמונה."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "הנח/י את המכשיר על ברך ימין כשהמסך מופנה כלפי מעלה, כפי שנראה בתמונה."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "כדי להתחיל, הקש/י על המסך והרחק/י את ברך שמאל רחוק ככל האפשר. לאחר מכן, חזור/י לנקודת ההתחלה והקש/י שוב לסיום."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "כדי להתחיל, הקש/י על המסך והרחק/י את ברך ימין רחוק ככל האפשר. לאחר מכן, חזור/י לנקודת ההתחלה והקש/י שוב לסיום."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "הנח/י את המכשיר על ברך שמאל. הקש/י על המסך והרחק/י את ברך שמאל ככל האפשר."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "הנח/י את המכשיר על ברך ימין. הקש/י על המסך והרחק/י את ברך ימין ככל האפשר."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "לסיום, החזר/י את ברך שמאל לנקודת ההתחלה. לאחר מכן, הקש/י בכל מקום."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "לסיום, החזר/י את ברך ימין לנקודת ההתחלה. לאחר מכן, הקש/י בכל מקום."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "טווח התנועה של כתף שמאל"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "טווח התנועה של כתף ימין"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "פעילות זו מודדת את טווח התנועה של הכתף השמאלית שלך."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "פעילות זו מודדת את טווח התנועה של הכתף הימנית שלך."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "בתחילת הפעילות, תצטרך/י להניח את המכשיר על כתף שמאל כדי לבצע מדידות. ודא/י שהצליל במכשיר מופעל כדי שתוכל/י לשמוע את ההנחיות."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "בתחילת הפעילות, תצטרך/י להניח את המכשיר על כתף ימין כדי לבצע מדידות. ודא/י שהצליל במכשיר מופעל כדי שתוכל/י לשמוע את ההנחיות."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "הנח/י את המכשיר על כתף שמאל כשהמסך מופנה כלפי מעלה, כפי שנראה בתמונה."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "הנח/י את המכשיר על כתף ימין כשהמסך מופנה כלפי מעלה, כפי שנראה בתמונה."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "כדי להתחיל, הקש/י על המסך והרם/י את זרוע שמאל רחוק ככל האפשר. לאחר מכן, חזור/י לנקודת ההתחלה והקש/י שוב לסיום."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "כדי להתחיל, הקש/י על המסך והרם/י את זרוע ימין רחוק ככל האפשר. לאחר מכן, חזור/י לנקודת ההתחלה והקש/י שוב לסיום."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "הנח/י את המכשיר על כתף שמאל. הקש/י על המסך והרם/י את זרוע שמאל קדימה ככל האפשר."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "הנח/י את המכשיר על כתף ימין. הקש/י על המסך והרם/י את זרוע ימין קדימה ככל האפשר."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "לסיום, החזר/י את זרוע שמאל לנקודת ההתחלה. לאחר מכן, הקש/י בכל מקום."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "לסיום, החזר/י את זרוע ימין לנקודת ההתחלה. לאחר מכן, הקש/י בכל מקום."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "הליכה מתוזמנת"; +"TIMED_WALK_INTRO_DETAIL" = "פעילות זו מודדת את תפקוד פלג הגוף התחתון שלך."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "מצא/י מקום, עדיף בחוץ, שבו תוכל/י ללכת במשך %@ בקו ישר במהירות המרבית שניתן, אך בבטחה. אל תאט/י עד שתעבור/י את קו הסיום."; +"TIMED_WALK_INTRO_2_DETAIL" = "הקש/י על ״הבא״ כדי להתחיל."; +"TIMED_WALK_FORM_TITLE" = "אמצעי עזר"; +"TIMED_WALK_FORM_TEXT" = "השתמש/י באותו אמצעי עזר בכל בדיקה."; +"TIMED_WALK_QUESTION_TEXT" = "האם הינך חובש/ת תומך לקרסול?"; +"TIMED_WALK_QUESTION_2_TITLE" = "האם הינך משתמש/ת באמצעי עזר?"; +"TIMED_WALK_QUESTION_2_TEXT" = "הקש/י כאן לבחירת תשובה."; +"TIMED_WALK_QUESTION_2_CHOICE" = "ללא"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "מקל הליכה ליד אחת"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "קב ליד אחת"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "מקל הליכה לשתי הידיים"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "קביים לשתי הידיים"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "הליכון"; +"TIMED_WALK_INSTRUCTION_%@" = "לך/י עד %@ בקו ישר."; +"TIMED_WALK_INSTRUCTION_TURN" = "הסתובב/י."; +"TIMED_WALK_INSTRUCTION_2" = "לך/י חזרה אל נקודת ההתחלה."; +"TIMED_WALK_INSTRUCTION_TEXT" = "בסיום, הקש/י על ״הבא״."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "הבדיקה ״חיבור סדרתי מתוזמן של שמע״ מודדת את מהירות עיבוד המידע ויכולת החישוב שלך בשמיעה."; +"PVSAT_INTRO_TEXT" = "הבדיקה ״חיבור סדרתי מתוזמן של ראיה״ מודדת את מהירות עיבוד המידע ויכולת החישוב שלך בראיה."; +"PAVSAT_INTRO_TEXT" = "הבדיקה ״חיבור סדרתי מתוזמן של שמע וראיה״ מודדת את מהירות עיבוד המידע ויכולת החישוב שלך, הן בשמיעה והן בראייה."; +"PSAT_INTRO_TEXT_2_%@" = "ספרות בודדות מוצגות כל %@ שניות.\nעליך להוסיף ספרה חדשה אל זו שנמצאת ממש לפניה.\nלתשומת לבך, אין לחשב את הסה״כ המצטבר, אלא רק את סכום שני המספרים האחרונים."; +"PSAT_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"PSAT_INITIAL_INSTRUCTION" = "זכור/י ספרה ראשונה זו."; +"PSAT_INSTRUCTION" = "הוסף/י ספרה חדשה זו לספרה הקודמת."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "מבחן דיסקית של %@ חורים"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "פעילות זו מודדת את תפקוד פלג הגוף העליון בכך שהיא מבקשת ממך להניח דיסקית עגולה בתוך חור. את הפעולה הזו תתבקש/י לבצע %@ פעמים."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "כעת תתבצע בדיקה של היד השמאלית והימנית שלך.\nעליך להרים את הדיסקית במהירות המרבית ולהכניס אותה לחור. לאחר שתבצע/י זאת %@ פעמים, עליך להוציא אותה שוב %@ פעמים."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "כעת תתבצע בדיקה של היד הימנית והשמאלית שלך.\nעליך להרים את הדיסקית במהירות המרבית ולהכניס אותה לחור. לאחר שתבצע/י זאת %@ פעמים, עליך להוציא אותה שוב %@ פעמים."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "מקם/י את הדיסקית בתוך החור באמצעות ידך השמאלית."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "מקם/י את הדיסקית בתוך החור באמצעות ידך הימנית."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "מקם/י את הדיסקית מאחורי הקו באמצעות ידך השמאלית."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "מקם/י את הדיסקית מאחורי הקו באמצעות ידך הימנית."; +"HOLE_PEG_TEST_TEXT" = "הרם/י את הדיסקית בשתי אצבעות."; +"HOLE_PEG_TEST_TEXT_2" = "הרם/י את אצבעותיך כדי להפיל את הדיסקית."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "פעילות למדידת הרעד"; +"TREMOR_TEST_INTRO_1_DETAIL" = "פעילות זו מודדת את הרעד בידיים שלך בתנוחות שונות. מצא/י מקום שבו תוכל/י לשבת בנוחות במשך כל הפעילות."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "החזק/י את הטלפון ביד שבה הבעיה מורגשת יותר, כמתואר בתמונה למטה."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "החזק/י את הטלפון ביד ימין, כמתואר בתמונה למטה."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "החזק/י את הטלפון ביד שמאל, כמתואר בתמונה למטה."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "בהמשך תתבקש/י לבצע %@ בישיבה עם הטלפון ביד."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "משימה אחת"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "שתי משימות"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "שלוש משימות"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "ארבע משימות"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "חמש משימות"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "הקש/י על ״הבא״ בכדי להמשיך."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "התכונן/י להחזיק את הטלפון על הירכיים."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "התכונן/י להחזיק את הטלפון ביד שמאל כשזאת מונחת על הירכיים."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "התכונן/י להחזיק את הטלפון ביד ימין כשזאת מונחת על הירכיים."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "המשך/י להחזיק את הטלפון על הירכיים למשך %ld שניות."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "כעת החזק/י את הטלפון בגובה הכתפיים תוך יישור המרפק."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "כעת החזק/י את הטלפון ביד שמאל בגובה הכתפיים תוך יישור המרפק."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "כעת החזק/י את הטלפון ביד ימין בגובה הכתפיים תוך יישור המרפק."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "המשך/י להחזיק את הטלפון תוך יישור המרפק למשך %ld שניות."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "כעת החזק/י את הטלפון בגובה הכתפיים תוך כיפוף המרפק."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "כעת החזק/י את הטלפון ביד שמאל בגובה הכתפיים תוך כיפוף המרפק."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "כעת החזק/י את הטלפון ביד ימין בגובה הכתפיים תוך כיפוף המרפק."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "המשך/י להחזיק את הטלפון תוך כיפוף המרפק למשך %ld שניות"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "כעת, תוך שמירה על מרפק מכופף, גע/י עם הטלפון באף מספר פעמים ברצף."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "כעת, עם הטלפון ביד שמאל ותוך שמירה על מרפק מכופף, גע/י עם הטלפון באף מספר פעמים ברצף."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "כעת, עם הטלפון ביד ימין ותוך שמירה על מרפק מכופף, גע/י עם הטלפון באף מספר פעמים ברצף."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "המשך/י לגעת עם הטלפון באף למשך %ld שניות"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "התכונן/י לבצע ״נפנוף מלכותי״ (סיבוב מפרק כף היד על צירו)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "התכונן/י לביצוע ״נפנוף מלכותי״ תוך אחיזת הטלפון ביד שמאל (סיבוב מפרק כף היד על צירו)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "התכונן/י לביצוע ״נפנוף מלכותי״ תוך אחיזת הטלפון ביד ימין (סיבוב מפרק כף היד על צירו)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "המשך/י לבצע ״נפנוף מלכותי״ למשך %ld שניות."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "כעת העבר/י את הטלפון ליד שמאל והמשך/י למשימה הבאה."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "כעת העבר/י את הטלפון ליד ימין והמשך/י למשימה הבאה."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "המשך/י אל המשימה הבאה."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "הפעילות הושלמה."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "בהמשך תתבקש/י לבצע %@ בישיבה כשהטלפון נמצא תחילה ביד אחת, ולאחר מכן ביד השניה."; +"TREMOR_SKIP_LEFT_HAND" = "אני לא יכול/ה לבצע את הפעולה הזו ביד שמאל."; +"TREMOR_SKIP_RIGHT_HAND" = "אני לא יכול/ה לבצע את הפעולה הזו ביד ימין."; +"TREMOR_SKIP_NEITHER" = "אני יכול/ה לבצע את הפעולה הזו בשתי הידיים."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "מבחן TMT (חיבור נקודות)"; +"TRAILMAKING_INTENDED_USE" = "פעילות זו בודקת את הקשב החזותי שלך ואת היכולת שלך לדלג בין משימות, על-ידי רישום משך הזמן שדרוש לך כדי להקיש על סידרה של נקודות."; +"TRAILMAKING_INTENDED_USE2_A" = "לאחר הספירה לאחור, הקש/י על הנקודות בסדר מתחלף תוך מעבר בין מספרים ואותיות. התחל/י בהקשה על המספר ׳1׳ ולאחר מכן על המספרים ׳2׳ – ׳3׳ – ׳4׳, וכן הלאה, עד שתגיע/י למספר ׳7׳."; +"TRAILMAKING_INTENDED_USE2_B" = "לאחר הספירה לאחור, הקש/י על הנקודות בסדר מתחלף תוך מעבר בין מספרים ואותיות. התחל/י בהקשה על המספר ׳1׳ ולאחר מכן על האות הראשונה ׳א׳, והמשך/י כך עם ׳2׳ – ׳ב׳ – ׳3׳ – ׳ג׳ וכן הלאה, עד שתגיע/י למספר ׳7׳."; +"TRAILMAKING_INTRO_TEXT" = "בצע/י את הבדיקה מהר ככל שתוכל/י מבלי לטעות.\n"; +"TRAILMAKING_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"TRAILMAKING_LETTER_A" = "א"; +"TRAILMAKING_LETTER_B" = "ב"; +"TRAILMAKING_LETTER_C" = "ג"; +"TRAILMAKING_LETTER_D" = "ד"; +"TRAILMAKING_LETTER_E" = "ה"; +"TRAILMAKING_LETTER_F" = "ו"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "זיהוי דיבור"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "פעילות זו מקליטה את הדיבור שלך באמצעות המיקרופון שבתחתית המכשיר, ומתרגמת את הדיבור למלל כתוב."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "הקש/י על ״התחלה״ כדי להתחיל."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "לחץ/י על הכפתור כדי להתחיל בהקלטה לפני שתדבר/י."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "התחל הקלטה"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "הפסק הקלטה"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "ערוך תמלול"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "ערוך/י את התמלול כדי לתקן טעויות בפירוש הטקסטואלי של הדיבור."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "התמלול יופיע כאן."; +"SPEECH_RECOGNITION_FAILED" = "זיהוי הדיבור נכשל."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "לא ניתן היה להתחיל את זיהוי הדיבור."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "הפעל שמע"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "עצור את השמע"; +"SPEECH_IN_NOISE_TITLE" = "דיבור ברעש"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "פעילות זו מודדת את מידת יכולת זיהוי הדיבור כאשר הדובר/ת נמצא/ת בסביבה רועשת."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "במהלך המבחן, תתבקש/י:\n\nלהאזין למשפט.\n\nלחזור בצורה ברורה על מה ששמעת או לדלג קדימה כדי להקליד את מה ששמעת באמצעות המקלדת.\n\nאם תחזור/י על מה ששמעת, תוכל/י לשנות את התמלול שנוצר על-ידי מנוע זיהוי הדיבור."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "כיול עוצמת קול"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "הקש/י על ״נגן שמע״, התאם/י את עוצמת הקול לרמה הנוחה לך ולאחר מכן הקש/י על ״הפסק שמע״ כדי להמשיך."; +"SPEECH_IN_NOISE_STEP_TITLE" = "האזן/י"; +"SPEECH_IN_NOISE_STEP_TEXT" = "משפט המשולב עם רעש רקע בעל יחס אות לרעש (SNR) אקראי יושמע פעם אחת בלבד."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "דבר/י"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "חזור/י על מה ששמעת."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "לא ניתן ליצור את הקובץ"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "לא ניתן היה להסיר מספיק קובצי רישום בכדי להגיע לסף"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "ארעה שגיאה בהגדרת המאפיין"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "הקובץ אינו מסומן כנמחק (אינו מסומן כקובץ שהועלה)"; +"ERROR_DATALOGGER_MULTIPLE" = "ארעו שגיאות מרובות במהלך הסרת קובצי הרישום"; +"ERROR_RECORDER_NO_DATA" = "לא נמצאו נתונים שנאספו."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "לא צוינה ספריית פלט"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "מד SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "פעילות זו מודדת את רמת לחץ הצליל בסביבה. אם רמות הרעש גבוהות מדי, לא תוכל/י להמשיך. עבור/י אל מיקום שקט יותר כדי להשלים משימה זו, או בצע/י שוב את המשימה בזמן אחר."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "מחשב"; +"ENVIRONMENTSPL_THRESHOLD" = "סף: ‎%@ dBA"; +"ENVIRONMENTSPL_OK" = "רעשי רקע תקינים"; +"ENVIRONMENTSPL_NOISE" = "יש יותר מדי רעשי רקע"; +"ENVIRONMENTSPL_TITLE_2" = "עליך למצוא מקום שקט"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "לשמירה על מידת הדיוק של הבדיקה, יש לבצעה באזור שקט."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "התחל משימה"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "אין נתונים"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "הזז/י את המחוון להזנת ערך"; +"SLIDER_I_DONT_KNOW" = "לא ממש ברור לי"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "עמוד"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "הקודם"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "הצג תמונה ממוזערת של PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "הסתר תמונות ממוזערות בפורמט PDF"; +"AX_BUTTON_ANNOTATE" = "הוסף הערות"; +"AX_BUTTON_SHOW_SEARCH" = "הצג את שורת החיפוש"; +"AX_BUTTON_HIDE_SEARCH" = "הסתר את שורת החיפוש"; +"AX_BUTTON_SHARE" = "שתף"; + + +"AX_COMPLETION_ILLUSTRATION" = "איור של סימן בחירה בתוך עיגול כחול המציין הצלחה"; + +"AX_SIGNVIEW_LABEL" = "שדה חתימה ייעודי"; +"AX_SIGNVIEW_HINT" = "גע/י במסך והזז/י את האצבע בכדי לחתום"; +"AX_SIGNVIEW_SIGNED" = "חתום"; +"AX_SIGNVIEW_UNSIGNED" = "לא חתום"; + +"AX_SELECTED" = "נבחרו"; +"AX_UNSELECTED" = "לא נבחר"; +"AX_SELECT_ALL_THAT_APPLY" = "נא לבחור את כל האפשרויות הרלוונטיות"; + +"AX_SLIDER_LABEL" = "מחוון תגובה. טווח שנע בין %@ ל-%@"; +"AX_UNLABELED_IMAGE" = "תמונה ללא תיוג"; + +"AX_ANNOUNCE_BEGIN_TASK" = "התחל משימה"; + +"AX.MEMORY.TILE.ACTIVE" = "פעיל"; +"AX.MEMORY.TILE.CORRECT" = "נכון"; +"AX.MEMORY.TILE.INCORRECT" = "לא נכון"; +"AX.MEMORY.TILE.QUIESCENT" = "ללא תנועה"; +"AX.MEMORY.TILE.LABEL" = "אריח משחק זכרון"; + +"AX_IMAGE_CAPTURE_LABEL" = "צלם תצוגה מקדימה"; +"AX_IMAGE_CAPTURED_LABEL" = "התמונה צולמה"; + +"AX_VIDEO_CAPTURE_LABEL" = "תצוגה מקדימה של הסרט שצולם"; +"AX_VIDEO_CAPTURE_COMPLETE" = "צילום הסרט הושלם"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "לא ניתן למקם דיסקית בגודל %@ על-גבי דיסקית בגודל %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "יעד"; +"AX_TOWER_OF_HANOI_TOWER" = "מגדל"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "הקש/י פעמיים למיקום הדיסקית"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "הקש/י פעמיים לבחירת הדיסקית הכי עליונה"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "כולל דיסק בגדלים %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "ריק"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "סגור את המקלדת"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "נע בין %@ ל-%@"; +"AX_GRAPH_STACK_PREFIX" = "הערימה מכילה"; +"AX_GRAPH_AND_SEPARATOR" = " וגם"; +"AX_GRAPH_POINT_%@" = "נקודה: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "צורת גל דיבור"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "עם תחילת ההקלטה, הפעל/י בפעם השניה כדי להפסיק את ההקלטה."; + +"AX_AUDIO_BAR_GRAPH" = "תצוגת עמודות (עוצמת שמע)"; + +"AX_AMSLER_GRID_LABEL" = "בדיקת רשת אמסלר"; +"AX_AMSLER_GRID_HINT" = "השתמש/י באצבע או בעט דיגיטלי כדי לסמן ישירות על הרשת, או החלק/י ימינה מחוץ לרשת לסיום."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "כפתורים שניתן להקיש עליהם"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "הקש/י עבור אוזן שמאל"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "הפעל/י כדי להתחיל בבדיקה. עם תחילת הבדיקה, הקש/י ישירות על כפתור זה כאשר תשמע/י צליל באזנך השמאלית."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "הקש/י עבור אוזן ימין"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "הפעל/י כדי להתחיל בבדיקה. עם תחילת הבדיקה, הקש/י ישירות על כפתור זה כאשר תשמע/י צליל באזנך הימנית."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ באמצעות VoiceOver, ניתן לנווט במסך כדי ללמוד היכן ממוקמים הכפתורים של כל אוזן. עם תחילת הבדיקה, ניתן יהיה להקיש ישירות על הכפתורים. %@"; +"AX_TAP_BUTTON_1_LABEL" = "הקש/י לאצבע אחת"; +"AX_TAP_BUTTON_2_LABEL" = "הקש/י לאצבע נוספת"; +"AX_TAP_BUTTON_HINT" = "הפעל/י כדי לאפשר הקשה ישירה על הכפתורים."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ באמצעות VoiceOver, ניתן לנווט במסך כדי ללמוד היכן ממוקמים הכפתורים השונים. ניתן להפעיל כל כפתור כדי לאפשר הקשה ישירה עליו."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "הקשה ישירה על הכפתורים זמינה כעת."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ באמצעות VoiceOver, ניתן יהיה להקיש באופן ישיר על הכפתור. הוא ימוקם בקרבת מרכז המסך."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ באמצעות VoiceOver, ניתן יהיה להקיש ישירות על הכפתורים בבדיקה."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "לא ניתן לפענח את הקוד של restoreData לצורך אתחול"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..0c0b815 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/he.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (שגיאה אחת) + other + (%d שגיאות) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.strings new file mode 100755 index 0000000..d1707a9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "सहमति"; +"CONSENT_NAME_GIVEN" = "प्रथम नाम"; +"CONSENT_NAME_FAMILY" = "उपनाम"; +"CONSENT_NAME_PLACEHOLDER" = "आवश्यक"; +"CONSENT_REVIEW_TITLE" = "समीक्षा"; +"CONSENT_REVIEW_INSTRUCTION" = "नीचे दिए गए फ़ॉर्म को देखें और जारी रखने के लिए “सहमत” पर टैप करें।"; +"CONSENT_REVIEW_ALERT_TITLE" = "समीक्षा"; +"CONSENT_SIGNATURE_TITLE" = "हस्ताक्षर"; +"CONSENT_SIGNATURE_INSTRUCTION" = "कृपया अपनी उँगली का उपयोग करके नीचे दिए गए बॉक्स में हस्ताक्षर करें।"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "यहाँ हस्ताक्षर करें"; +"CONSENT_PAGE_NUMBER_FORMAT" = "पृष्ठ %1$ld/%2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "स्वागत है"; +"CONSENT_SECTION_DATA_GATHERING" = "डेटा एकत्रीकरण"; +"CONSENT_SECTION_PRIVACY" = "गोपनीयता"; +"CONSENT_SECTION_DATA_USE" = "डेटा उपयोग"; +"CONSENT_SECTION_STUDY_SURVEY" = "सर्वेक्षण अध्ययन"; +"CONSENT_SECTION_STUDY_TASKS" = "अध्ययन कार्य"; +"CONSENT_SECTION_TIME_COMMITMENT" = "समय प्रतिबद्धता"; +"CONSENT_SECTION_WITHDRAWING" = "सहमति वापस लेना"; +"CONSENT_LEARN_MORE_TITLE" = "और अधिक जानें"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "डेटा एकत्रीकरण की प्रक्रिया के बारे में और अधिक जानें"; +"LEARN_MORE_DATA_USE" = "डेटा उपयोग करने की प्रक्रिया के बारे में और अधिक जानें"; +"LEARN_MORE_PRIVACY" = "आपकी गोपनीयता और पहचान की सुरक्षा के बारे में और अधिक जानें"; +"LEARN_MORE_WELCOME" = "अध्ययन से पहले उसके बारे में और अधिक जानें"; +"LEARN_MORE_STUDY_SURVEY" = "सर्वेक्षण अध्ययन के बारे में और अधिक जानें"; +"LEARN_MORE_TIME_COMMITMENT" = "अपने समय पर अध्ययन के प्रभाव के बारे में और अधिक जानें"; +"LEARN_MORE_TASKS" = "सम्मिलित कार्यों के बारे में और अधिक जानें"; +"LEARN_MORE_WITHDRAWING" = "सहमति वापस लेने के बारे में और अधिक जानें"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "शेयर विकल्प"; +"CONSENT_SHARE_WIDELY_%@" = "मेरे डेटा को %@ और दुनिया भर के योग्य शोधकर्ताओं के साथ शेयर करें"; +"CONSENT_SHARE_ONLY_%@" = "मेरा डेटा केवल %@ के साथ शेयर करें"; +"CONSENT_SHARING_DESCRIPTION_%@" = "इस अध्ययन में आपकी सहभागिता से %@ को आपका अध्ययन डेटा प्राप्त होगा।\n\nकोड किए हुए अध्ययन डेटा का विस्तृत रूप से (आपका नाम दिए बिना) शेयर, इस शोध और भविष्य में होने वाले शोधों के लिए उपयोगी हो सकता है।"; +"LEARN_MORE_CONSENT_SHARING" = "डेटा शेयर के बारे में अधिक जानें"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "प्रिंट किया गया नाम"; +"CONSENT_DOC_LINE_SIGNATURE" = "हस्ताक्षर"; +"CONSENT_DOC_LINE_DATE" = "तिथि"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "%1$@/%2$@ प्रश्न"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "स्किप किया गया"; +"REVIEW_EDIT_ANSWER" = "संपादित करें"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "अमान्य मान"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ अधिकतम अनुमत मान (%2$@) से अधिक है।"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ न्यूनतम अनुमत मान (%2$@) से कम है।"; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ मान्य मान नहीं है।"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "अमान्य ईमेल पता : %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "पता दर्ज करें"; +"LOCATION_ERROR_TITLE" = "निर्दिष्ट पता ढूँढा नहीं जा सका"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "आपके वर्तमान स्थान का पता लगाने में असमर्थ। कृपया कोई पता टाइप करें या लागू होने पर किसी ऐसे स्थान पर जाएँ जहाँ बेहतर GPS सिग्नल हों।"; +"LOCATION_ERROR_MESSAGE_DENIED" = "स्थान सेवा में ऐक्सेस को अस्वीकृत किया गया। कृपया सेटिंग्ज़ में जाकर इस ऐप को स्थान सेवा का उपयोग करने की अनुमति दें।"; +"LOCATION_ERROR_GEOCODE" = "दर्ज किए गए पते के लिए कोई परिणाम नहीं मिले। कृपया सुनिश्चित करें कि यह पता मान्य है।"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "या तो आप इंटरनेट से कनेक्टेड नहीं हैं या आपने पता देखने हेतु अधिकतम अनुमत अनुरोध कर लिए हैं। यदि आप इंटरनेट से कनेक्टेड नहीं हैं, तो इस प्रश्न का जवाब देने के लिए अपने वाई-फ़ाई को चालू करें, यदि स्किप बटन उपलब्ध हो, तो इस प्रश्न को स्किप करें या फिर इंटरनेट से कनेक्ट होने पर इस सर्वेक्षण पर वापस आएँ।"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "टेक्स्ट कॉन्टेंट अधिकतम अनुमत सीमा से अधिक है : %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "स्प्लिट स्क्रीन में कैमरा उपलब्ध नहीं है।"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "ईमेल"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "पासवर्ड"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "पासवर्ड दर्ज करें"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "पुष्टि करें"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "पासवर्ड फिर दर्ज करें"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "पासवर्ड मेल नहीं खा रहे हैं।"; +"ADDITIONAL_INFO_SECTION_TITLE" = "अतिरिक्त जानकारी"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "साहिल"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "मलिक"; +"GENDER_FORM_ITEM_TITLE" = "लिंग"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "लिंग चुनें"; +"DOB_FORM_ITEM_TITLE" = "जन्मतिथि"; +"DOB_FORM_ITEM_PLACEHOLDER" = "तिथि चुनें"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "फ़ोन नंबर"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "सत्यापन"; +"VERIFICATION_STEP_TITLE" = "अपना ईमेल सत्यापित करें"; +"RESEND_EMAIL_LABEL_MESSAGE" = "यदि आपको सत्यापन ईमेल प्राप्त नहीं हुआ है और आप चाहते हैं कि उसे फिर प्रेषित किया जाए, तो नीचे दिए गए लिंक पर टैप करें।"; +"RESEND_EMAIL_BUTTON_TITLE" = "सत्यापन ईमेल फिर से भेजें"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "लॉगइन करें"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "पासवर्ड भूल गए?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "पासकोड दर्ज करें"; +"PASSCODE_CONFIRM_MESSAGE" = "पासकोड की पुष्टि करें"; +"PASSCODE_SAVED_MESSAGE" = "पासकोड सहेजा गया"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "पासकोड प्रमाणित किया गया"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "अपना पुराना पासकोड दर्ज करें"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "अपना नया पासकोड दर्ज करें"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "अपने नए पासकोड की पुष्टि करें"; +"PASSCODE_INVALID_ALERT_TITLE" = "ग़लत पासकोड"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "पासकोड एक समान नहीं हैं। फिर कोशिश करें।"; +"PASSCODE_TOUCH_ID_MESSAGE" = "कृपया Touch ID से प्रमाणित करें।"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID त्रुटि"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "केवल न्यूमैरिक वर्णों की अनुमति है।"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "पासकोड दर्ज करने की प्रक्रिया का संकेतक"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%1$@/%2$@ मान दर्ज किए गए"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "पासकोड भूल गए?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "कीचेन आइटम को जोड़ा नहीं जा सका।"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "कीचेन आइटम को अपडेट नहीं किया जा सका।"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "कीचेन आइटम को डिलीट नहीं किया जा सका।"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "कीचेन आइटम को खोजा नहीं जा सका।"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "प्रकार I"; +"FITZPATRICK_SKIN_TYPE_II" = "प्रकार II"; +"FITZPATRICK_SKIN_TYPE_III" = "प्रकार III"; +"FITZPATRICK_SKIN_TYPE_IV" = "प्रकार IV"; +"FITZPATRICK_SKIN_TYPE_V" = "प्रकार V"; +"FITZPATRICK_SKIN_TYPE_VI" = "प्रकार VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "महिला"; +"GENDER_MALE" = "पुरूष"; +"GENDER_OTHER" = "अन्य"; + +/* Boolean answer strings */ +"BOOL_NO" = "नहीं"; +"BOOL_YES" = "हाँ"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "सें॰मी॰"; +"MEASURING_UNIT_FT" = "फ़ीट"; +"MEASURING_UNIT_IN" = "इंच"; +"MEASURING_UNIT_KG" = "कि॰ग्रा॰"; +"MEASURING_UNIT_LB" = "पाउंड"; +"MEASURING_UNIT_OZ" = "औंस"; + +/* Limb values. */ +"LIMB_LEFT" = "बायाँ"; +"LIMB_RIGHT" = "दायाँ"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "उत्तर देने के लिए टैप करें"; +"NULL_ANSWER" = "उत्तर का चयन करें"; +"PLACEHOLDER_IMAGE_CHOICES" = "चयन करने के लिए टैप करें"; +"PLACEHOLDER_LONG_TEXT" = "लिखने के लिए टैप करें"; + +/* Button titles */ +"BUTTON_AGREE" = "सहमत"; +"BUTTON_CANCEL" = "रद्द करें"; +"BUTTON_OK" = "ठीक"; +"BUTTON_CLEAR" = "साफ़ करें"; +"BUTTON_CLEAR_SIGNATURE" = "सिग्नेचर साफ़ करें"; +"BUTTON_APPLY" = "लागू करें"; +"BUTTON_DISAGREE" = "असहमत"; +"BUTTON_DONE" = "पूर्ण"; +"BUTTON_GET_STARTED" = "आरंभ करें"; +"BUTTON_LEARN_MORE" = "और अधिक जानें"; +"BUTTON_NEXT" = "अगला"; +"BUTTON_SKIP" = "स्किप करें"; +"BUTTON_SKIP_QUESTION" = "यह प्रश्न स्किप करें"; +"BUTTON_START_TIMER" = "टाइमर प्रारंभ करें"; +"BUTTON_OPTION_SAVE" = "बाद के लिए सहेजें"; +"BUTTON_OPTION_DISCARD" = "परिणाम ख़ारिज करें"; +"BUTTON_OPTION_STOP_TASK" = "कार्य समाप्त करें"; +"BUTTON_SAVE" = "सहेजें"; +"BUTTON_CLEAR_ANSWER" = "उत्तर साफ़ करें"; +"BUTTON_READ_ONLY_MODE" = "इस उत्तर को संशोधित नहीं किया जा सकता है।"; +"BUTTON_COPYRIGHT" = "कॉपीराइट"; +"BUTTON_CLOSE" = "बंद करें"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "गतिविधि शुरू होने में शेष समय"; +"TASK_COMPLETE_TITLE" = "गतिविधि पूरी हुई"; +"TASK_COMPLETE_TEXT" = "आपके डेटा का विश्लेषण किया जाएगा और परिणाम के तैयार होते ही आपको सूचित किया जाएगा।"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ शेष।"; +"TOUCH_ANYWHERE_LABEL" = "जारी रखने के लिए कहीं भी स्पर्श करें"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "इमेज कैप्चर करें"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "इमेज फिर कैप्चर करें"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "कोई कैमरा नहीं मिला। यह चरण पूरा नहीं किया जा सकता है।"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "इस चरण को पूरा करने के लिए “सेटिंग्ज़” में इस ऐप को कैमरे का ऐक्सेस प्रदान करें।"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "कैप्चर की गई इमेज के लिए कोई आउटपुट डायरेक्टरी निर्दिष्ट नहीं की गई थी।"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "कैप्चर की गई इमेज सहेजी नहीं जा सकी।"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "रिकॉर्डिंग शुरू करें"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "रिकॉर्डिंग रोकें"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "वीडियो फिर कैप्चर करें"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "तंदुरुस्ती"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "दूरी (%@)"; +"FITNESS_HEARTRATE_TITLE" = "हृदय गति (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "%@ तक आराम से बैठें।"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "%@ तक जितना तेज़ हो सके, चलें।"; +"FITNESS_INTRO_TEXT_FORMAT" = "इस गतिविधि द्वारा आपकी हृदय गति का निरीक्षण किया जाता है और यह मापित किया जाता है कि %1$@ में आप कितनी दूर पैदल चल सकते हैं।"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "बाहर %1$@ तक जितनी तेज़ गति से संभव हो, चलें। उसके बाद बैठें और आराम से %2$@ तक सुस्ताएँ। आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "चाल और संतुलन"; +"WALK_INTRO_TEXT" = "इस गतिविधि द्वारा आपके पैदल चलने या खड़े रहने पर आपकी चाल और संतुलन का मापन किया जाता है। यदि आप बिना किसी सहायता के सुरक्षित पैदल नहीं चल सकते हैं, तो इसे जारी न रखें।"; +"WALK_INTRO_2_TEXT_%ld" = "ऐसी जगह ढूँढें जहाँ आप बिना किसी सहायता के लगभग %ld क़दम सीधी रेखा में चल सकें।"; +"WALK_INTRO_2_DETAIL" = "अपने डिवाइस को जेब या बैग में रखें और ऑडियो निर्देशों का अनुसरण करें।"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "अब %@ तक स्थिर खड़े रहें।"; +"WALK_STAND_INSTRUCTION_FORMAT" = "%@ तक स्थिर खड़े रहें।"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "पीछे मुड़ें और जहाँ से आपने शुरूआत की थी, वहाँ वापस चलकर जाएँ।"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "लगभग %ld क़दम सीधी रेखा में चलें।"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "ऐसी जगह ढूँढें, जहाँ आप एक ओर व दूसरी ओर सुरक्षित रूप से सीधी रेखा में चल सकें। मार्ग की समाप्ति पर मुड़ें और लगातार चलते रहने का प्रयास करें, जैसे कि आप किसी शंकु के इर्द-गिर्द चल रहे हों।\n\nइसके बाद आपको पूर्ण वृत्त में मुड़ने के लिए, फिर अपनी भुजाओं को फैलाकर और अपने पैरों को लगभग कंधे की चौड़ाई तक फैलाकर स्थिर खड़े रहने के लिए कहा जाएगा।"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "जब आप शुरू करने के लिए तैयार हों, “आरंभ करें” पर टैप करें।\nफिर अपने डिवाइस को जेब या बैग में रखें और ऑडियो निर्देशों का पालन करें।"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "%@ तक पीछे और आगे सीधी रेखा में चलें। अपनी सामान्य चाल से चलें।"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "पूर्ण वृत्त में मुड़ें फिर %@ तक स्थिर खड़े रहें।"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "आपने गतिविधि पूरी कर ली है।"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "टैप करने की गति"; +"TAPPING_TASK_TITLE_RIGHT" = "दायॉं हाथ"; +"TAPPING_TASK_TITLE_LEFT" = "बायाँ हाथ"; +"TAPPING_INTRO_TEXT" = "इस गतिविधि द्वारा आपकी टैप करने की गति का मापन किया जाता है।"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "अपना डिवाइस समतल सतह पर रखें।"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "स्क्रीन पर बटनों पर एक के बाद एक टैप करने के लिए एक ही हाथ की दो उँगलियों का उपयोग करें।"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "स्क्रीन पर बटनों पर एक के बाद एक टैप करने के लिए दाएँ हाथ की दो उँगलियों का उपयोग करें।"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "स्क्रीन पर बटनों पर एक के बाद एक टैप करने के लिए बाएँ हाथ की दो उँगलियों का उपयोग करें।"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "अब अपने दाएँ हाथ का उपयोग करके यही परीक्षण दोहराएँ।"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "अब अपने बाएँ हाथ का उपयोग करके यही परीक्षण दोहराएँ।"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "एक उँगली से फिर दूसरी उँगली से टैप करें। अपने टैप का समय जितना संभव हो, एक समान रखने का प्रयास करें। %@ तक टैप करते रहें।"; +"TAPPING_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"TAPPING_CALL_TO_ACTION_NEXT" = "आरंभ करने के लिए “अगला” पर टैप करें।"; +"TAP_BUTTON_TITLE" = "टैप करें"; +"TOTAL_TAPS_LABEL" = "कुल टैप"; +"TAPPING_INSTRUCTION" = "बटनों को दो उँगलियों से जितना हो सके, उतने समान समयांतराल पर टैप करें।"; +"TAPPING_INSTRUCTION_RIGHT" = "अपने दाएँ हाथ से बटनों पर टैप करें।"; +"TAPPING_INSTRUCTION_LEFT" = "अपने बाएँ हाथ से बटनों पर टैप करें।"; +"TAPPING_SKIP_TITLE" = "इस हाथ को स्किप करें"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler ग्रिड"; +"AMSLER_GRID_INTRO_TEXT" = "इस गतिविधि से यूज़र की दृष्टि से संबंधित समस्याओं का पता लगाने में मदद मिलती है।"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "पूरे परीक्षण के दौरान डिवाइस को अपने चेहरे से 12 इंच दूर और अपनी आँखों के बराबर की ऊँचाई पर पकड़कर रखें।"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "अपनी %@ बंद करें और वर्गाकार ग्रिड के मध्य में स्थित डॉट की तरफ़ देखते रहें।\n\nअपनी उँगली या स्टाइलस का उपयोग करके आपको दिखने वाली धुँधली या हिलती हुई रेखाओं जैसे किसी भी व्यवधान को चिह्नित करें।\n\nइसे पूर्ण करने पर ग्रिड के बाहर कहीं भी बाईं ओर स्वाइप करें।"; +"AMSLER_GRID_LEFT_EYE" = "बाईं आँख"; +"AMSLER_GRID_RIGHT_EYE" = "दाईं आँख"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "वॉइस"; +"AUDIO_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"AUDIO_INSTRUCTION" = "जितनी देर तक बोल सकें, माइक्रोफ़ोन में “आह” बोलिए।"; +"AUDIO_INTRO_TEXT" = "गहरी साँस लें और जितनी देर तक बोल सकें, माइक्रोफ़ोन में “आह” बोलें। अपनी बोलने की गति और आवाज़ स्थिर रखें ताकि ऑडियो बारों का रंग नीला बना रहे।"; +"AUDIO_INTENDED_USE" = "इस गतिविधि द्वारा आपके डिवाइस के नीचे लगे माइक्रोफ़ोन से आपकी आवाज़ को रिकॉर्ड करके उसका मूल्यांकन किया जाता है।"; +"AUDIO_TOO_LOUD_LABEL" = "बहुत तेज़"; +"AUDIO_GENERIC_ERROR_LABEL" = "ऑडियो रिकॉर्ड करने में असमर्थ"; +"AUDIO_LEVEL_CHECK_LABEL" = "पृष्ठभूमि नॉइज़ स्तर की जाँच होने तक कृपया प्रतीक्षा करें।"; +"AUDIO_TOO_LOUD_MESSAGE" = "आस-पास नॉइज़ का स्तर बहुत अधिक होने के कारण आपकी आवाज़ रिकॉर्ड नहीं की जा सकती। कृपया किसी शांत जगह पर जाएँ और फिर कोशिश करें।"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "तैयार होने पर “अगला” पर टैप करें।"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "टोन ऑडियोमेट्री"; +"TONE_AUDIOMETRY_INTENDED_USE" = "इस गतिविधि द्वारा अलग-अलग प्रकार की ध्वनियाँ सुनने की आपकी क्षमता का आकलन किया जाता है।"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "आरंभ करने से पहले अपने हेडफ़ोन को प्लग इन करें और कानों पर लगाएँ।\n\nध्वनि बहुत हल्की होगी और वह नियमित अलर्ट टोन से अलग होती है। ध्वनि मंद होना शुरू होगी और धीरे-धीरे वॉल्यूम बढ़ेगा।  कृपया ध्यान दें कि आपको किस कान में ध्वनि सुनाई देती है और उसे दाएँ या बाएँ बटन पर टैप करके बताएँ।"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"TONE_AUDIOMETRY_PREP_TEXT" = "अब आपको एक टोन सुनाई देनी चाहिए। अपने डिवाइस के किनारे दिए गए नियंत्रणों का उपयोग करके वॉल्यूम ऐडजस्ट करें।\n\nजब आप आरंभ करने के लिए तैयार हो जाएँ, तो किसी भी बटन पर टैप करें।"; +"TONE_AUDIOMETRY_INSTRUCTION" = "हर बार ध्वनि सुनाई देना शुरू होने पर बाएँ या दाएँ बटन पर टैप करके यह बताएँ कि आपको किस कान में ध्वनि सुनाई देती है।"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "बायाँ कान"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "दायाँ कान"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, बाएँ"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, दाएँ"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "टोन ऑडियोमेट्री"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "जब आप कोई टोन सुनें, तो टैप करें।"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "टोन और वॉल्यूम"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "आपको टोन की शृंखलाएँ सुनाई देंगी।"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "जब आप कोई टोन सुनें, तो बटन पर टैप करें।"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "इस परीक्षण के लिए वॉल्यूम को 50 प्रतिशत पर सेट किया जाएगा।"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "इस परीक्षण में क़रीब 10 मिनट लगते हैं।"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "व्यवधान से बचने के लिए विश्राम मोड चालू करें।"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "आपके दाएँ कान में पहले टोन बजाए जाएँगे।"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "अब आपके बाएँ कान में टोन बजाए जाएँगे।"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "इस गतिविधि से किसी व्यक्ति के सुनने की सीमा के स्तरों की पहचान dB HL स्केल में की जाती है।"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "सुनिश्चित करें कि डिवाइस का वॉल्यूम अधिकतम स्तर पर सेट है।\n\nइस परीक्षण के दौरान या तो बाएँ या दाएँ कान में हल्की टोन बजाई जाएगी।\n\nध्यान से सुनें और हर बार टोन सुनाई देने पर बटन पर टैप करें।"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "यह परीक्षण पहचान करती है कि किसी भी आवाज़ को सुनाई देने के लिए उसे कितना तेज़ होना चाहिए।"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "ऑनबोर्डिंग प्रश्न।"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "‘बेहतर कान' के लिए अपनी प्राथमिकता चुनें, यदि कोई हो"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "बायाँ"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "दायाँ"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "कोई प्राथमिकता नहीं है"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "परीक्षण रद्द किया गया"; +"dBHL_ALERT_TITLE_START_OVER" = "फिर शुरू करें"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "परीक्षण रद्द करें"; +"dBHL_ALERT_TEXT" = "यह परीक्षण करने के लिए अपने AirPods या EarPods को फिर से कनेक्ट करें।"; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ पूर्ण"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "हेडफ़ोन"; +"HEADPHONES_UNKNOWN" = "अज्ञात"; +"HEADPHONES_NONE" = "कोई नहीं"; +"CONNECTED" = "कनेक्टेड"; +"NOT_CONNECTED" = "कनेक्टेड नहीं है"; +"HEADPHONE_CONNECTED_%@" = "कनेक्टेड - %@"; +"HEADPHONE_DETECT_TITLE" = "अपने हेडफ़ोन को कनेक्ट करें"; +"HEADPHONE_DETECT_TEXT" = "इस परीक्षण के लिए Apple AirPods या Apple EarPods आवश्यक हैं"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "स्थानिक याददाश्त"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "%@ के चमकने के क्रम को दोहराने के लिए कहकर इस गतिविधि द्वारा आपकी अल्पावधि स्थानिक याददाश्त का मापन किया जाता है।"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "फूलों"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "फूल"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "%1$@ में से कुछ एक-एक करके चमकेंगे। उन %2$@ पर उनके चमकने के क्रम में टैप करें।"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "%1$@ में से कुछ एक-एक करके चमकेंगे। उन %2$@ पर उनके चमकने के विपरीत क्रम में टैप करें।"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें और फिर ध्यान से देखें।"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "स्कोर"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "%@ को चमकते हुए देखें"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "%@ को उनके चमकने के क्रम में टैप करें"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "%@ को विपरीत क्रम में टैप करें"; +"MEMORY_GAME_COMPLETE_TITLE" = "अनुक्रम पूरा हुआ"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "जारी रखने के लिए “अगला” पर टैप करें"; +"MEMORY_GAME_FAILED_TITLE" = "फिर कोशिश करें"; +"MEMORY_GAME_FAILED_MESSAGE" = "आप निर्धारित समय में इसे पूरा नहीं कर पाए। जारी रखने के लिए “अगला” पर टैप करें।"; +"MEMORY_GAME_TIMEOUT_TITLE" = "समय-समाप्त"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "आप निर्धारित समय में इसे पूरा नहीं कर पाए।\nजारी रखने के लिए “अगला” पर टैप करें।"; +"MEMORY_GAME_COMPLETE" = "गेम पूरा हुआ"; +"MEMORY_GAME_PAUSED_TITLE" = "ठहरा हुआ"; +"MEMORY_GAME_PAUSED_MESSAGE" = "जारी रखने के लिए “अगला” पर टैप करें"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "मेमोरी गतिविधि को कैलिफ़ोर्निया विश्वविद्यालय, सैन फ़्रैंसिस्को से पीएचडी केथरीन पॉसिन और जोल क्रामेर के सहयोग से विकसित किया गया है।"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "प्रतिक्रिया समय"; +"REACTION_TIME_TASK_INTENDED_USE" = "इस गतिविधि द्वारा किसी दृश्यात्मक संकेत की प्रतिक्रिया देने में आपके द्वारा लिए जाने वाले समय का मूल्यांकन किया जाता है।"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "स्क्रीन पर नीले रंग का बिंदु दिखाई देते ही डिवाइस को किसी भी दिशा में हिलाएँ। आपसे %D बार ऐसा करने का अनुरोध किया जाएगा।"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "प्रयास %1$@/%2$@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "नीले रंग का वृत्त दिखाई देने पर शीघ्रता से डिवाइस को हिलाएँ"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "स्ट्रूप"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "हर बार जब शब्द दिखाया जाता है, दिखाए गए रंग के नाम के पहले अक्षर का चयन करें।"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "स्ट्रूप गतिविधि आरंभ करने के लिए तैयार होने पर “आरंभ करें” पर टैप करें।"; +"STROOP_TASK_STEP_TEXT" = "दिखाए गए रंग के नाम के पहले अक्षर का चयन करें।"; +"STROOP_COLOR_RED" = "लाल"; +"STROOP_COLOR_GREEN" = "हरा"; +"STROOP_COLOR_BLUE" = "नीला"; +"STROOP_COLOR_YELLOW" = "पीला"; +"STROOP_COLOR_RED_INITIAL" = "ला॰"; +"STROOP_COLOR_GREEN_INITIAL" = "ह॰"; +"STROOP_COLOR_BLUE_INITIAL" = "नी॰"; +"STROOP_COLOR_YELLOW_INITIAL" = "पी॰"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "हनोई का टॉवर"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "इस गतिविधि के द्वारा पहेली को हल करने की आपकी क्षमता का मूल्यांकन किया जाएगा।"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "पूरे स्टैक को चिह्नांकित प्लेटफ़ॉर्म पर कम से कम प्रयासों में स्थानांतरित करें।"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "पहेली हल करें"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "प्रयासों की संख्या : %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "यह पहेली मेरे द्वारा हल नहीं की जा सकती है"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "गति की सीमा"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption बाएँ या दाएँ होना चाहिए"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "बाएँ घुटने की गति सीमा"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "दाएँ घुटने की गति सीमा"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "इस गतिविधि द्वारा मापा जाता है कि आप अपना बायाँ घुटना कितना आगे ले जा सकते हैं।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "इस गतिविधि द्वारा मापा जाता है कि आप अपना दायाँ घुटना कितना आगे ले जा सकते हैं।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "कुर्सी के किनारे पर बैठें। शुरुआत में माप करने के लिए डिवाइस को अपने बाएँ घुटने पर रखें। कृपया अपने डिवाइस पर ध्वनि चालू करें जिससे आप निर्देश सुन सकें।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "कुर्सी के किनारे पर बैठें। शुरुआत में माप करने के लिए डिवाइस को अपने बाएँ घुटने पर रखें। कृपया अपने डिवाइस पर ध्वनि चालू करें जिससे आप निर्देश सुन सकें।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "स्क्रीन को बाहर की ओर करके अपना डिवाइस अपने बाएँ घुटने पर रखें, जैसा तस्वीर में दिखाया गया है।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "स्क्रीन को बाहर की ओर करके अपना डिवाइस अपने दाएँ घुटने पर रखें, जैसा तस्वीर में दिखाया गया है।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "जब आप तैयार हों तो शुरू करने के लिए स्क्रीन पर टैप करें और अपने बाएँ घुटने को यथासंभव फैलाएँ। आरंभिक स्थिति में वापस लौटें और अंत में फिर टैप करें।"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "जब आप तैयार हों तो शुरू करने के लिए स्क्रीन पर टैप करें और अपने दाएँ घुटने को यथासंभव फैलाएँ। आरंभिक स्थिति में वापस लौटें और अंत में फिर टैप करें।"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "अपने बाएँ घुटने पर अपना डिवाइस रखें। स्क्रीन पर टैप करें और अपने बाएँ घुटने को यथासंभव फैलाएँ।"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "अपने दाएँ घुटने पर अपना डिवाइस रखें। स्क्रीन पर टैप करें और अपने दाएँ घुटने को यथासंभव फैलाएँ।"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "जब आप पूरा कर लें, तो अपने बाएँ घुटने पर आरंभिक स्थिति में लौटें। उसके बाद कहीं भी टैप करें।"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "जब आप पूरा कर लें, तो अपने दाएँ घुटने पर आरंभिक स्थिति में लौटें। उसके बाद कहीं भी टैप करें।"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "बाएँ कंधे की गति सीमा"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "दाएँ कंधे की गति सीमा"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "इस गतिविधि द्वारा मापा जाता है कि आप अपना बायाँ कंधा कितना आगे ले जा सकते हैं।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "इस गतिविधि द्वारा मापा जाता है कि आप अपना दायाँ कंधा कितना आगे ले जा सकते हैं।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "आरंभ करने पर आपको माप के लिए अपने बाएँ कंधे पर अपना डिवाइस रखना होगा। कृपया अपने डिवाइस पर ध्वनि चालू करें जिससे आप निर्देश सुन सकें।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "आरंभ करने पर आपको माप के लिए अपने दाएँ कंधे पर अपना डिवाइस रखना होगा। कृपया अपने डिवाइस पर ध्वनि चालू करें जिससे आप निर्देश सुन सकें।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "स्क्रीन को बाहर की ओर करके अपना डिवाइस अपने बाएँ कंधे पर रखें, जैसा तस्वीर में दिखाया गया है।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "स्क्रीन को बाहर की ओर करके अपना डिवाइस अपने दाएँ कंधे पर रखें, जैसा तस्वीर में दिखाया गया है।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "जब आप तैयार हों तो शुरू करने के लिए स्क्रीन पर टैप करें और अपनी बाईं भुजा को यथासंभव उठाएँ। आरंभिक स्थिति में वापस लौटें और अंत में फिर टैप करें।"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "जब आप तैयार हों तो शुरू करने के लिए स्क्रीन पर टैप करें और अपनी दाईं भुजा को यथासंभव उठाएँ। आरंभिक स्थिति में वापस लौटें और अंत में फिर टैप करें।"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "अपने बाएँ कंधे पर अपना डिवाइस रखें। स्क्रीन टैप करें और अपनी बाईं भुजा को यथासंभव सामने की ओर उठाएँ।"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "अपने दाएँ कंधे पर अपना डिवाइस रखें। स्क्रीन टैप करें और अपनी दाईं भुजा को यथासंभव सामने की ओर उठाएँ।"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "जब आप पूरा कर लें, तो अपनी बाईं भुजा को वापस आरंभिक स्थिति में ले जाएँ। उसके बाद कहीं भी टैप करें।"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "जब आप पूरा कर लें, तो अपनी दाईं भुजा को वापस आरंभिक स्थिति में ले जाएँ। उसके बाद कहीं भी टैप करें।"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "समयबद्ध चाल"; +"TIMED_WALK_INTRO_DETAIL" = "इस गतिविधि के द्वारा शरीर के निचले हिस्से के कार्य करने की क्षमता को मापा जाता है।"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "ऐसी जगह ढूँढें, यदि संभव हो तो घर के बाहर, जहाँ पर आप लगभग %@ तक जितना संभव हो, उतनी तेज़ी से लेकिन सुरक्षित रूप से सीधी रेखा में चल सकें। समाप्ति रेखा तक पहुँचने तक गति कम न करें।"; +"TIMED_WALK_INTRO_2_DETAIL" = "आरंभ करने के लिए “अगला” पर टैप करें।"; +"TIMED_WALK_FORM_TITLE" = "सहायक डिवाइस"; +"TIMED_WALK_FORM_TEXT" = "प्रत्येक परीक्षण हेतु एक ही सहायक डिवाइस का उपयोग करें।"; +"TIMED_WALK_QUESTION_TEXT" = "क्या आप टखनों और पैरों को सहारा देने वाला उपकरण पहनते हैं?"; +"TIMED_WALK_QUESTION_2_TITLE" = "क्या आप सहायक डिवाइस का उपयोग करते हैं?"; +"TIMED_WALK_QUESTION_2_TEXT" = "उत्तर का चयन करने के लिए यहाँ टैप करें।"; +"TIMED_WALK_QUESTION_2_CHOICE" = "कुछ नहीं"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "एक हाथ के लिए बेंत"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "एक हाथ के लिए बैसाखी"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "दोनों हाथों के लिए बेंत"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "दोनों हाथों के लिए बैसाखी"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "वॉकर/रोलेटर"; +"TIMED_WALK_INSTRUCTION_%@" = "सीधी रेखा में लगभग %@ चलें।"; +"TIMED_WALK_INSTRUCTION_TURN" = "पीछे मुड़ें।"; +"TIMED_WALK_INSTRUCTION_2" = "जहाँ से आपने शुरुआत की थी, वहाँ वापस चलकर जाएँ।"; +"TIMED_WALK_INSTRUCTION_TEXT" = "पूरा हो जाने पर “अगला” पर टैप करें।"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "पेस्ड ऑडिटरी सीरियल ऐडीशन टेस्ट के द्वारा सुनकर जानकारी संसाधित करने की आपकी गति और परिकलन क्षमता को मापा जाता है।"; +"PVSAT_INTRO_TEXT" = "पेस्ड विजुअल सीरियल ऐडीशन टेस्ट के द्वारा देखकर जानकारी संसाधित करने की आपकी गति और परिकलन क्षमता को मापा जाता है।"; +"PAVSAT_INTRO_TEXT" = "पेस्ड ऑडिटरी एंड विजुअल सीरियल ऐडीशन टेस्ट के द्वारा देख और सुनकर जानकारी संसाधित करने की आपकी गति और परिकलन क्षमता को मापा जाता है।"; +"PSAT_INTRO_TEXT_2_%@" = "हर %@ पर एक अंक दिखाया जाएगा।\nप्रत्येक नए अंक को उससे ठीक पहले वाले अंक में जोड़ें।\nध्यान रखें, आपको कुल योग की गणना नहीं करनी है बल्कि केवल अंतिम दो अंकों का योग करना है।"; +"PSAT_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"PSAT_INITIAL_INSTRUCTION" = "इस पहले अंक को याद रखें।"; +"PSAT_INSTRUCTION" = "इस नए अंक का पिछले अंक में योग करें।"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-होल पेग परीक्षण"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "छिद्र में पेग को डालने के लिए कहकर इस गतिविधि द्वारा आपके अपर एक्सट्रेमिटी फ़ंक्शन का मापन किया जाता है। आपसे %@ बार ऐसा करने का अनुरोध किया जाएगा।"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "आपके बाएँ और दाएँ, दोनों हाथों का परीक्षण किया जाएगा।\nआपको जितनी जल्दी हो सके, पेग को लेकर छिद्र में डालना होगा और %1$@ बार करने के बाद %2$@ बार फिर उसे वहाँ से हटाना होगा।"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "आपके दाएँ और बाएँ, दोनों हाथों का परीक्षण किया जाएगा।\nआपको जितनी जल्दी हो सके, पेग को लेकर छिद्र में डालना होगा और %1$@ बार करने के बाद %2$@ बार फिर उसे वहाँ से हटाना होगा।"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "अपने बाएँ हाथ से पेग को छिद्र में डालें।"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "अपने दाएँ हाथ से पेग को छिद्र में डालें।"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "अपने बाएँ हाथ से पेग को रेखा के पीछे करें।"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "अपने दाएँ हाथ से पेग को रेखा के पीछे करें।"; +"HOLE_PEG_TEST_TEXT" = "दो उँगलियों से पेग को उठाएँ।"; +"HOLE_PEG_TEST_TEXT_2" = "पेग को डालने के लिए उँगलियों को उठाएँ।"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "कंपन गतिविधि"; +"TREMOR_TEST_INTRO_1_DETAIL" = "इस गतिविधि से विभिन्न स्थितियों में आपके हाथों के कंपन को मापा जाता है। ऐसी जगह ढूँढें जहाँ आप इस गतिविधि की अवधि के दौरान आराम से बैठ सकें।"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "नीचे दी गई इमेज में दिखाए अनुसार फ़ोन को अपने अधिक प्रभावित हाथ में पकड़ें।"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "नीचे दी गई इमेज में दिखाए अनुसार फ़ोन को अपने दाएँ हाथ में पकड़ें।"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "नीचे दी गई इमेज में दिखाए अनुसार फ़ोन को अपने बाएँ हाथ में पकड़ें।"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "बैठे रहकर फ़ोन को अपने हाथ में पकड़कर आपसे %@ करने के लिए कहा जाएगा।"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "कार्य"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "दो कार्य"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "तीन कार्य"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "चार कार्य"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "पाँच कार्य"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "अागे बढ़ने के लिए “अगला” पर टैप करें।"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "अपने फ़ोन को अपनी गोद में पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "बाएँ हाथ से अपने फ़ोन को अपनी गोद में पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "दाएँ हाथ से अपने फ़ोन को अपनी गोद में पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "अपने फ़ोन को अपनी गोद में %ld सेकंड तक पकड़े रखें।"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "अब अपने हाथ को कंधे की ऊँचाई तक फैलाकर अपने फ़ोन को पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "अब अपने बाएँ हाथ को कंधे की ऊँचाई तक फैलाकर अपने फ़ोन को पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "अब अपने दाएँ हाथ को कंधे की ऊँचाई तक फैलाकर अपने फ़ोन को पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "हाथ फैलाकर अपने फ़ोन को %ld सेकंड तक पकड़े रखें।"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "अब अपनी कोहनी मोड़कर अपने फ़ोन को कंधे की ऊंचाई पर पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "अब अपने बाएँ हाथ की कोहनी मोड़कर कंधे की ऊँचाई पर अपने फ़ोन को पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "अब अपने दाएँ हाथ की कोहनी मोड़कर कंधे की ऊँचाई पर अपने फ़ोन को पकड़ें।"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "अपनी कोहनी मोड़कर अपने फ़ोन को %ld सेकंड तक पकड़े रखें"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "अब अपनी कोहनी मुड़ी हुई रखकर अपने फ़ोन को बार-बार अपनी नाक से स्पर्श करें।"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "अब अपने बाएँ हाथ में फ़ोन पकड़कर और कोहनी मुड़ी हुई रखकर अपने फ़ोन को बार-बार अपनी नाक से स्पर्श करें।"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "अब अपने दाएँ हाथ में फ़ोन पकड़कर और कोहनी मुड़ी हुई रखकर अपने फ़ोन को बार-बार अपनी नाक से स्पर्श करें।"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "अपने फ़ोन को अपनी नाक से %ld सेकंड तक स्पर्श करते रहें"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "रानी की तरह हाथ हिलाने (अपनी कलाई को मोड़कर हाथ हिलाना) की तैयारी करें।"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "अपने फ़ोन को अपने बाएँ हाथ में रखकर रानी की तरह हाथ हिलाने (अपनी कलाई को मोड़कर हाथ हिलाना) की तैयारी करें।"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "अपने फ़ोन को अपने दाएँ हाथ में रखकर रानी की तरह हाथ हिलाने (अपनी कलाई को मोड़कर हाथ हिलाना) की तैयारी करें।"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "%ld सेकंड तक रानी की तरह हाथ हिलाते रहें।"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "अब अपने फ़ोन को अपने बाएँ हाथ में लें और अगला कार्य जारी रखें।"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "अब अपने फ़ोन को अपने दाएँ हाथ में लें और अगला कार्य जारी रखें।"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "अगला कार्य जारी रखें।"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "गतिविधि पूरी हुई।"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "बैठे रहकर फ़ोन को पहले एक हाथ में फिर दूसरे हाथ में पकड़कर आपसे %@ करने के लिए कहा जाएगा।"; +"TREMOR_SKIP_LEFT_HAND" = "इस गतिविधि को मेरे बाएँ हाथ से नहीं किया जा सकता है।"; +"TREMOR_SKIP_RIGHT_HAND" = "इस गतिविधि को मेरे दाएँ हाथ से नहीं किया जा सकता है।"; +"TREMOR_SKIP_NEITHER" = "इस गतिविधि को मेरे दोनों हाथों से किया जा सकता है।"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "ट्रेल निर्माण परीक्षण"; +"TRAILMAKING_INTENDED_USE" = "इस गतिविधि द्वारा क्रमानुसार बिंदुओं की शृंखला को टैप करने में लगने वाले आवश्यक समय को रिकॉर्ड करके आपकी विज़ुअल एकाग्रता का और कार्य स्विचिंग का मूल्यांकन किया जाता है।"; +"TRAILMAKING_INTENDED_USE2_A" = "उल्टी गिनती के बाद संख्याओं और अक्षरों के बीच वैकल्पिक क्रम में डॉट पर टैप करें। पहली संख्या ‘1’ पर टैप करके उसके बाद संख्या ‘2’ – ‘3’ – ‘4’ पर तब तक टैप करते जाएँ… जब तक आप संख्या ‘7’ तक नहीं पहुँच जाते।"; +"TRAILMAKING_INTENDED_USE2_B" = "उल्टी गिनती के बाद, संख्याओं और अक्षरों के बीच वैकल्पिक क्रम में डॉट पर टैप करें। पहली संख्या ‘1’ पर टैप करके उसके बाद पहले अक्षर ‘क’ पर टैप करके आरंभ करें फिर ‘2’ – ‘ख’ – ‘3’ – ‘ग’ पर तब तक टैप करते जाएँ… जब तक आप संख्या ‘7’ तक नहीं पहुँच जाते।"; +"TRAILMAKING_INTRO_TEXT" = "जितना जल्दी संभव हो बिना ग़लती किए यह करें। \n "; +"TRAILMAKING_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"TRAILMAKING_LETTER_A" = "क"; +"TRAILMAKING_LETTER_B" = "ख"; +"TRAILMAKING_LETTER_C" = "ग"; +"TRAILMAKING_LETTER_D" = "घ"; +"TRAILMAKING_LETTER_E" = "ड़"; +"TRAILMAKING_LETTER_F" = "च"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "बोली पहचान"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "इस गतिविधि से आपकी बोली को डिवाइस के नीचे लगे माइक्रोफ़ोन से रिकॉर्ड किया जाता है और उसे टेक्स्ट में अनुवादित किया जाता है।"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "आरंभ करने के लिए “आरंभ करें” पर टैप करें।"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "रिकॉर्डिंग शुरू करने के लिए बोलने से पहले बटन दबाएँ।"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "रिकॉर्डिंग शुरू करें"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "रिकॉर्डिंग रोकें"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "अनुलेखन संपादित करें"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "बोली के किसी ग़लत इंटरप्रिटेशन को सुधारने के लिए अनुलेखन टेक्स्ट संपादित करें।"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "आपका अनुलेखन यहाँ दिखाई देगा।"; +"SPEECH_RECOGNITION_FAILED" = "बोली पहचान विफल।"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "बोली पहचान शुरू करने में विफल।"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "ऑडियो चलाएँ"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "ऑडियो रोकें"; +"SPEECH_IN_NOISE_TITLE" = "नॉइज़ में बोली"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "इस गतिविधि से शोर से भरे माहौल में प्रस्तुत की गई बोली की स्पष्टता मापी जाती है।"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "इस परीक्षण के भाग के रूप में आपको यह करना होगा :\n\nवाक्य को सुनें।\n\nआपने जो सुना उसे स्पष्ट रूप से दोहराएँ या आपने जो सुना उसे कीबोर्ड का उपयोग करके टाइप करने के लिए आगे स्किप करें। \n\nयदि आप सुना हुआ दोहराते हैं, तो आपके पास बोली पहचान इंजन के द्वारा जनरेट किए गए अनुलेखन को संशोधित करने का विकल्प होगा।"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "वॉल्यूम अंशांकन"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "‘ऑडियो चलाएँ' पर टैप करें, आरामदेय स्तर पर अपना वॉल्यूम समायोजित करें और फिर जारी रखने के लिए ‘ऑडियो रोकें' पर टैप करें।"; +"SPEECH_IN_NOISE_STEP_TITLE" = "सुनें"; +"SPEECH_IN_NOISE_STEP_TEXT" = "पृष्ठभूमि के नॉइज़ के साथ अनियमित नॉइज़ अनुपात सिग्नल (SNR) पर मिश्रित वाक्य को केवल एक बार चलाया जाएगा।"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "बोलें"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "सुने हुए को दोहराएँ।"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "फ़ाइल नहीं बन सकी"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "अधिकतम संग्रहण सीमा तक पहुँचने के लिए आवश्यक लॉग फ़ाइलें नहीं हटाई जा सकीं"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "विशेषता सेट करने में त्रुटि"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "फ़ाइल डिलीट की गई (अपलोड की गई) के रूप में चिन्हित नहीं है"; +"ERROR_DATALOGGER_MULTIPLE" = "लॉग हटाने में कई त्रुटियाँ"; +"ERROR_RECORDER_NO_DATA" = "कोई संग्रहित डेटा नहीं मिला।"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "कोई आउटपुट निर्देशिका निर्दिष्ट नहीं"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL मीटर"; +"ENVIRONMENTSPL_INTRO_TEXT" = "इस ऐक्टिविटी से वातावरण के ध्वनि दबाव स्तर मापा जाता है। यदि नॉइज़ का स्तर अधिक उच्च हो, तो आप जारी नहीं रख पाएँगे। कृपया इस कार्य को पूरा करने के लिए किसी शांत स्थान पर जाएँ या इस ऐक्टिविटी को बाद में फिर करें।"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "गणना जारी है"; +"ENVIRONMENTSPL_THRESHOLD" = "सीमा : %@ dBA"; +"ENVIRONMENTSPL_OK" = "पृष्ठभूमि नॉइज़ ठीक"; +"ENVIRONMENTSPL_NOISE" = "बहुत अधिक पृष्ठभूमि नॉइज़"; +"ENVIRONMENTSPL_TITLE_2" = "कोई शांत जगह ढूँढें"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "सटीकता सुनिश्चित करने के लिए इस परीक्षण को शांत वातावरण में किया जाना चाहिए।"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "कार्य शुरू करें"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "कोई डेटा नहीं"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "मान दर्ज करने के लिए स्लाइडर सरकाएँ"; +"SLIDER_I_DONT_KNOW" = "मुझे नहीं पता"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "पृष्ठ"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "वापस"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDF थंबनेल दिखाएँ"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDF थंबनेल छिपाएँ"; +"AX_BUTTON_ANNOTATE" = "ऐनोटेट करें"; +"AX_BUTTON_SHOW_SEARCH" = "खोज बार दिखाएँ"; +"AX_BUTTON_HIDE_SEARCH" = "खोज बार छिपाएँ"; +"AX_BUTTON_SHARE" = "शेयर करें"; + + +"AX_COMPLETION_ILLUSTRATION" = "नीले रंग के वृत्त में चेक मार्क का चित्रण सफलता को बताता है"; + +"AX_SIGNVIEW_LABEL" = "निर्दिष्ट हस्ताक्षर फ़ील्ड"; +"AX_SIGNVIEW_HINT" = "हस्ताक्षर करने के लिए स्क्रीन को स्पर्श करें और अपनी उँगली हिलाएँ"; +"AX_SIGNVIEW_SIGNED" = "हस्ताक्षरित"; +"AX_SIGNVIEW_UNSIGNED" = "अहस्ताक्षरित"; + +"AX_SELECTED" = "चयनित"; +"AX_UNSELECTED" = "अचयनित"; +"AX_SELECT_ALL_THAT_APPLY" = "लागू होने वाले सभी चुनें"; + +"AX_SLIDER_LABEL" = "प्रतिक्रिया स्लाइडर। %1$@ से %2$@ तक सीमा"; +"AX_UNLABELED_IMAGE" = "बिना लेबल की इमेज"; + +"AX_ANNOUNCE_BEGIN_TASK" = "कार्य आरंभ करें"; + +"AX.MEMORY.TILE.ACTIVE" = "सक्रिय"; +"AX.MEMORY.TILE.CORRECT" = "सही"; +"AX.MEMORY.TILE.INCORRECT" = "ग़लत"; +"AX.MEMORY.TILE.QUIESCENT" = "निष्क्रिय"; +"AX.MEMORY.TILE.LABEL" = "मेमोरी गेम टाइटल"; + +"AX_IMAGE_CAPTURE_LABEL" = "प्रीव्यू को कैप्चर करें"; +"AX_IMAGE_CAPTURED_LABEL" = "कैप्चर की हुई इमेज"; + +"AX_VIDEO_CAPTURE_LABEL" = "वीडियो कैप्चर प्रीव्यू"; +"AX_VIDEO_CAPTURE_COMPLETE" = "वीडियो कैप्चर पूरा हुआ"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "%2$@ आकार के डिस्क पर %1$@ आकार के डिस्क को रखने में असमर्थ"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "लक्ष्य"; +"AX_TOWER_OF_HANOI_TOWER" = "टॉवर"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "डिस्क रखने के लिए डबल टैप करें"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "सबसे ऊपर के डिस्क का चयन करने के लिए डबल टैप करें"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "इसमें %@ आकारों के डिस्क हैं"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "ख़ाली"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "कीबोर्ड ख़ारिज करें"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "%1$@ से %2$@ तक श्रेणी"; +"AX_GRAPH_STACK_PREFIX" = "निम्नलिखित का संग्रह"; +"AX_GRAPH_AND_SEPARATOR" = " और "; +"AX_GRAPH_POINT_%@" = "पॉइंट : %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "स्पीच वेवफ़ॉर्म"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "रिकॉर्डिंग शुरू होने पर रिकॉर्डिंग रोकने के लिए दूसरी बार सक्रिय करें।"; + +"AX_AUDIO_BAR_GRAPH" = "ऑडियो बार ग्राफ़"; + +"AX_AMSLER_GRID_LABEL" = "Amsler ग्रिड"; +"AX_AMSLER_GRID_HINT" = "ग्रिड को सीधे चिह्नित करने के लिए अपनी उँगली या स्टाइलस का उपयोग करें या पूरा करने के लिए ग्रिड के बाहर बाएँ स्वाइप करें।"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "टैप करने योग्य बटन"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "बाएँ कान के लिए टैप करें"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "परीक्षण शुरू करने के लिए सक्रिय करें। परीक्षण शुरू होने पर इस बटन पर सीधे तब टैप करें जब आपको अपने बाएँ कान में ध्वनि सुनाई दे।"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "दाएँ कान के लिए टैप करें"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "परीक्षण शुरू करने के लिए सक्रिय करें। परीक्षण शुरू होने पर इस बटन पर सीधे तब टैप करें जब आपको अपने दाएँ कान में ध्वनि सुनाई दे।"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ VoiceOver के उपयोग से प्रत्येक कान के लिए बटन की स्थिति जानने के लिए स्क्रीन को स्पर्श करके एक्सप्लोर करें। परीक्षण शुरू होने पर बटन सीधे टैप करने योग्य हो जाएँगे।%@"; +"AX_TAP_BUTTON_1_LABEL" = "एक उँगली के लिए टैप करें"; +"AX_TAP_BUTTON_2_LABEL" = "अन्य उँगली के लिए टैप करें"; +"AX_TAP_BUTTON_HINT" = "बटन को सीधे टैप करने योग्य बनाने के लिए सक्रिय करें।"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ VoiceOver के उपयोग से बटन की स्थिति जानने के लिए स्क्रीन को स्पर्श करके एक्सप्लोर करें। बटन सीधे टैप करने योग्य बनाने के लिए किसी एक बटन को सक्रिय करें।"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "बटन अब सीधे टैप करने योग्य हैं।"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ VoiceOver के उपयोग से बटन सीधे टैप करने योग्य हो जाएगा। यह स्क्रीन के केंद्र के नज़दीक स्थित होगा।"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ VoiceOver के उपयोग से परीक्षण में बटन सीधे टैप करने योग्य हो जाएँगे।"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "शुरू करने के लिए restoreData को डिकोड नहीं किया जा सकता"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..380a8e4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hi.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d त्रुटि) + other + (%d त्रुटियाँ) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.strings new file mode 100755 index 0000000..64f298a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Pristanak"; +"CONSENT_NAME_GIVEN" = "Ime"; +"CONSENT_NAME_FAMILY" = "Prezime"; +"CONSENT_NAME_PLACEHOLDER" = "Potrebno"; +"CONSENT_REVIEW_TITLE" = "Pregled informacija"; +"CONSENT_REVIEW_INSTRUCTION" = "Pregledajte obrazac u nastavku te dodirnite Slažem se ako ste spremni nastaviti."; +"CONSENT_REVIEW_ALERT_TITLE" = "Pregled informacija"; +"CONSENT_SIGNATURE_TITLE" = "Potpis"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Prijavite se koristeći prst u donjem okviru."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Potpišite se ovdje"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Stranica %1$ld od %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Dobrodošli"; +"CONSENT_SECTION_DATA_GATHERING" = "Prikupljanje podataka"; +"CONSENT_SECTION_PRIVACY" = "Privatnost"; +"CONSENT_SECTION_DATA_USE" = "Uporaba podataka"; +"CONSENT_SECTION_STUDY_SURVEY" = "Istraživačka anketa"; +"CONSENT_SECTION_STUDY_TASKS" = "Zadaci istraživanja"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Potrebno vrijeme"; +"CONSENT_SECTION_WITHDRAWING" = "Povlačenje pristanka"; +"CONSENT_LEARN_MORE_TITLE" = "Saznajte više"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Saznajte više o načinu prikupljanja podataka"; +"LEARN_MORE_DATA_USE" = "Saznajte više o načinu uporabe podataka"; +"LEARN_MORE_PRIVACY" = "Saznajte više o načinu zaštite vaše privatnosti i identiteta"; +"LEARN_MORE_WELCOME" = "Saznajte više o istraživanju"; +"LEARN_MORE_STUDY_SURVEY" = "Saznajte više o istraživačkoj anketi"; +"LEARN_MORE_TIME_COMMITMENT" = "Saznajte kako će istraživanje utjecati na vaše vrijeme"; +"LEARN_MORE_TASKS" = "Saznajte više o zadacima"; +"LEARN_MORE_WITHDRAWING" = "Saznajte više o povlačenju pristanka"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opcije dijeljenja"; +"CONSENT_SHARE_WIDELY_%@" = "Dijeli moje podatke sa sveučilištem %@ i kvalificiranim istraživačima diljem svijeta"; +"CONSENT_SHARE_ONLY_%@" = "Dijeli moje podatke samo sa sveučilištem %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ će primiti vaše podatke o studiji iz vašeg sudjelovanja u ovoj studiji.\n\nŠire dijeljenje vaše kodirane studije (bez informacija kao što je vaše ime) može doprinijeti ovom i budućem istraživanju."; +"LEARN_MORE_CONSENT_SHARING" = "Saznajte više o dijeljenju podataka"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Ime"; +"CONSENT_DOC_LINE_SIGNATURE" = "Potpis"; +"CONSENT_DOC_LINE_DATE" = "Datum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ od %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pitanje %1$@ od %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Preskočeno"; +"REVIEW_EDIT_ANSWER" = "Uredi"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Nevažeća vrijednost"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ prekoračuje maksimalnu dozvoljenu vrijednost (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ je manje od minimalne dozvoljene vrijednosti (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ nije važeća vrijednost."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Nevažeća e-mail adresa: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Unesite adresu"; +"LOCATION_ERROR_TITLE" = "Navedena adresa nije pronađena"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Nije moguće utvrditi vašu trenutnu lokaciju. Molimo unesite adresu ili se premjestite na lokaciju s boljim GPS signalom, ako je primjenjivo."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Odbijen je pristup lokacijskim uslugama. Molimo dajte ovoj aplikaciji dopuštenje da koristi lokacijske usluge putem Postavki."; +"LOCATION_ERROR_GEOCODE" = "Nije moguće naći rezultat za unesenu adresu. Molimo provjerite je li adresa valjana."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Niste spojeni na internet ili ste prekoračili maksimalan broj zahtjeva za traženje adresa. Ako niste spojeni na internet, uključite Wi-Fi kako biste odgovorili na ovo pitanje, preskočite pitanje ako je dostupna tipka za preskakanje ili se vratite na anketu kad ste spojeni na internet. U suprotnom, probajte ponovno za nekoliko minuta."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Tekstualni sadržaj prekoračuje maksimalnu duljinu: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera nije dostupna u razdvojenom zaslonu."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Pošaljite e-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "ihorvat@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Lozinka"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Unesite lozinku"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Potvrdi"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Ponovno unesite lozinku"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Lozinke nisu iste."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Dodatne informacije"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Ivan"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Horvat"; +"GENDER_FORM_ITEM_TITLE" = "Spol"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Izaberite rod"; +"DOB_FORM_ITEM_TITLE" = "Datum rođenja"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Izaberite datum"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Broj telefona"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Potvrda"; +"VERIFICATION_STEP_TITLE" = "Potvrdite vaš e-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Ako niste primili e-mail za potvrdu i želite da bude ponovno poslan, dodirnite link ispod."; +"RESEND_EMAIL_BUTTON_TITLE" = "Ponovno pošalji e-mail za provjeru"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Prijava"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Zaboravili ste lozinku?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Unesite šifru"; +"PASSCODE_CONFIRM_MESSAGE" = "Potvrdite šifru"; +"PASSCODE_SAVED_MESSAGE" = "Šifra je spremljena"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Šifra je autorizirana"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Unesite staru šifru"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Unesite novu šifru"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Potvrdite vašu novu šifru"; +"PASSCODE_INVALID_ALERT_TITLE" = "Netočna šifra"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Šifre nisu iste. Pokušajte ponovno."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Molimo autorizirajte pomoću Touch ID-a"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Greška Touch ID-a"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Dopušteni su samo numerički znakovi."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indikator napretka unošenja šifre"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ od %@ unesenih znamenki"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Zaboravili ste šifru?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nije moguće dodati stavku privjeska ključeva."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nije moguće ažurirati stavku privjeska ključeva."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nije moguće obrisati stavku privjeska ključeva."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Nije moguće pronaći stavku privjeska ključeva."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tip I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tip II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tip III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tip IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tip V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tip VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Žensko"; +"GENDER_MALE" = "Muško"; +"GENDER_OTHER" = "Ostalo"; + +/* Boolean answer strings */ +"BOOL_NO" = "Ne"; +"BOOL_YES" = "Da"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "u"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "lijevo"; +"LIMB_RIGHT" = "desno"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Dodirnite za odgovaranje"; +"NULL_ANSWER" = "Odaberite odgovor"; +"PLACEHOLDER_IMAGE_CHOICES" = "Dodirnite za odabir"; +"PLACEHOLDER_LONG_TEXT" = "Dodirnite za pisanje"; + +/* Button titles */ +"BUTTON_AGREE" = "Slažem se"; +"BUTTON_CANCEL" = "Poništi"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Očisti"; +"BUTTON_CLEAR_SIGNATURE" = "Očisti potpis"; +"BUTTON_APPLY" = "Primijeni"; +"BUTTON_DISAGREE" = "Ne slažem se"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Pokreni"; +"BUTTON_LEARN_MORE" = "Saznajte više"; +"BUTTON_NEXT" = "Sljedeće"; +"BUTTON_SKIP" = "Preskoči"; +"BUTTON_SKIP_QUESTION" = "Preskoči ovo pitanje"; +"BUTTON_START_TIMER" = "Pokreni brojač"; +"BUTTON_OPTION_SAVE" = "Spremi za kasnije"; +"BUTTON_OPTION_DISCARD" = "Odbaci rezultate"; +"BUTTON_OPTION_STOP_TASK" = "Zaustavi zadatak"; +"BUTTON_SAVE" = "Spremi"; +"BUTTON_CLEAR_ANSWER" = "Očisti odgovor"; +"BUTTON_READ_ONLY_MODE" = "Ovaj odgovor se ne može promijeniti."; +"BUTTON_COPYRIGHT" = "Autorsko pravo"; +"BUTTON_CLOSE" = "Zatvori"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Započinjanje aktivnosti za"; +"TASK_COMPLETE_TITLE" = "Aktivnost dovršena"; +"TASK_COMPLETE_TEXT" = "Vaši podaci će se analizirati i bit ćete obaviješteni kad rezultati budu spremni."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Preostalo: %@."; +"TOUCH_ANYWHERE_LABEL" = "Dodirnite bilo gdje za nastavak"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Snimi sliku"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Ponovno snimi sliku"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Kamera nije pronađena. Korak se ne može dovršiti."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Za dovršetak ovog koraka, u Postavkama dopustite aplikaciji pristup kameri."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Nije naveden izlazni direktorij za snimljene slike."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Snimljena slika ne može se spremiti."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Započni snimati"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Zaustavi snimanje"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Ponovno snimi video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kondicija"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Udaljenost (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Puls u minuti"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sjedite udobno %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Hodajte što brže možete %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Ova aktivnost prati vašu brzinu otkucaja srca i mjeri koliko možete prehodati unutar %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Hodajte na otvorenom najbrže što možete %1$@. Kad završite, sjednite i odmarajte %2$@. Za početak dodirnite Pokreni."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Položaj i ravnoteža"; +"WALK_INTRO_TEXT" = "Ova aktivnost mjeri vaš položaj tijela i ravnotežu dok hodate i stojite mirno. Nemojte nastavljati ako ne možete sigurno hodati bez pomoći."; +"WALK_INTRO_2_TEXT_%ld" = "Pronađite mjesto na kojem možete sigurno hodati približno %ld koraka u ravnoj liniji."; +"WALK_INTRO_2_DETAIL" = "Stavite svoj uređaj u džep ili torbu i slijedite audio upute."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Sada stojte mirno %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stojte mirno %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Okrenite se i hodajte natrag do mjesta od kojeg ste krenuli."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Hodajte najviše %ld koraka u ravnoj liniji."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Pronađite mjesto gdje možete sigurno i pravocrtno hodati naprijed i natrag. Pokušajte hodati u kontinuitetu okrećući se na krajevima svoje staze, kao da hodate oko čunja.\n\nZatim ćete dobiti upute da se okrenete oko sebe, te da stanete mirno s rukama uz bokove i stopalima u širini ramena."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Dodirnite Pokreni kad ste spremni započeti.\nZatim svoj uređaj stavite u džep ili torbu i slijedite audio upute."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Hodajte naprijed-natrag u ravnoj liniji %@. Hodajte kao i inače."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Okrenite se punim krugom i zatim budite mirni %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Dovršili ste aktivnost."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Brzina dodirivanja"; +"TAPPING_TASK_TITLE_RIGHT" = "Desna ruka"; +"TAPPING_TASK_TITLE_LEFT" = "Lijeva ruka"; +"TAPPING_INTRO_TEXT" = "Ova aktivnost mjeri vašu brzinu dodirivanja."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Stavite svoj uređaj na ravnu površinu."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Koristeći dva prsta iste ruke, naizmjence dodirujte tipke na zaslonu."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Koristeći dva prsta desne ruke, naizmjence dodirujte tipke na zaslonu."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Koristeći dva prsta lijeve ruke, naizmjence dodirujte tipke na zaslonu."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Sad ponovite isti test desnom rukom."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Sad ponovite isti test lijevom rukom."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Dodirnite jednim prstom, zatim drugim. Pokušajte tempirati dodire kako bi bili ujednačeni. Nastavite dodirivati %@."; +"TAPPING_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Dodirnite Sljedeće za početak."; +"TAP_BUTTON_TITLE" = "Dodirnite"; +"TOTAL_TAPS_LABEL" = "Ukupan broj dodira"; +"TAPPING_INSTRUCTION" = "Dodirujte tipke što ujednačenije možete koristeći dva prsta."; +"TAPPING_INSTRUCTION_RIGHT" = "Dodirujte tipke koristeći DESNU ruku."; +"TAPPING_INSTRUCTION_LEFT" = "Dodirujte tipke koristeći LIJEVU ruku."; +"TAPPING_SKIP_TITLE" = "Preskoči ovu ruku"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amslerova mreža"; +"AMSLER_GRID_INTRO_TEXT" = "Ovom se aktivnošću pomažu detektirati problemi s vidom korisnika."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Tijekom cijelog testa uređaj držite na udaljenosti od 30 centimetara od svog lica i u razini očiju."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Zatvorite svoje %@ i gledajte točku u središtu četvrtaste mreže.\n\nPrstima ili olovkom označite sva izobličenja koja vidite poput zamagljenih ili valovitih linija.\n\nKad završite, povucite lijevo bilo gdje izvan rešetke."; +"AMSLER_GRID_LEFT_EYE" = "Lijevo oko"; +"AMSLER_GRID_RIGHT_EYE" = "Desno oko"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Glas"; +"AUDIO_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"AUDIO_INSTRUCTION" = "Izgovarajte \"Aaaaaa\" u mikrofon što dulje možete."; +"AUDIO_INTRO_TEXT" = "Duboko udahnite i izgovorite \"Aaaaaa\" u mikrofon što dulje možete. Održavajte ujednačenu glasnoću glasa tako da audio stupci ostanu plavi."; +"AUDIO_INTENDED_USE" = "Ovom se aktivnošću procjenjuje vaš glas snimanjem mikrofonom koji se nalazi na dnu uređaja."; +"AUDIO_TOO_LOUD_LABEL" = "Preglasno"; +"AUDIO_GENERIC_ERROR_LABEL" = "Zvuk se ne može snimati"; +"AUDIO_LEVEL_CHECK_LABEL" = "Molimo, pričekajte da provjerimo razinu pozadinske buke."; +"AUDIO_TOO_LOUD_MESSAGE" = "Razina buke u okruženju je previsoka za snimanje vašeg glasa. Molimo, premjestite se negdje gdje je tiše i pokušajte ponovno."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Dodirnite Sljedeće kad budete spremni."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tonalna audiometrija"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Ovom se aktivnošću mjeri vaša sposobnost da čujete različite zvukove."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Prije nego započnete, uključite slušalice i stavite ih.\n\nZvuk će biti jako suptilan i neće biti nalik redovitom tonu upozorenja.  Zvuk će započeti tiho, zatim će mu se polako povećavati glasnoća.  Obratite pažnju i dodirnite lijevu ili desnu tipku kako biste označili u kojem uhu čujete zvuk."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Sad biste trebali začuti ton. Kontrolama s bočne strane svog uređaja podesite glasnoću.\n\nKad ste spremni započeti dodirnite bilo koju tipku."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Svaki put kad začujete zvuk, dodirnite lijevu ili desnu tipku ovisno o uhu u kojem čujete zvuk."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Lijevo uho"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Desno uho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, lijevo"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, desno"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tonalna audiom."; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Dodirnite kad čujete ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ton i glasnoća"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Čut ćete niz tonova."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Kad čujete ton, dodirnite tipku."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Za ovaj test glasnoća će biti podešena na 50 %."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Ovaj test traje približno 10 minuta."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Uključite Zabranu ometanja kako biste izbjegli prekidanje."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Tonovi će se reproducirati prvo u vašem desnom uhu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Tonovi će se sad reproducirati u vašem lijevom uhu."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Ovom se aktivnošću identificiraju pragovi čujnosti pojedinca na dB HL skali."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Provjerite je li glasnoća uređaja podešena na maksimalnu razinu.\n\nTijekom ovog zadatka u lijevom ili desnom uhu reproducirat će se suptilan ton.\n\nSlušajte pažljivo i dodirnite tipku svaki put kad začujete ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ovaj test služi određivanju koliko glasan zvuk treba biti da biste ga čuli."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Upitnik o dodavanju novog korisnika."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Odaberite svoju postavku za 'bolje uho', ako ga ima"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "lijevo"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "desno"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "bez postavke"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test je poništen"; +"dBHL_ALERT_TITLE_START_OVER" = "Ponovno pokreni"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Poništi test"; +"dBHL_ALERT_TEXT" = "Ponovno spojite svoje AirPods ili EarPods slušalice za provođenje ovog testa."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ dovršeno"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Slušalice"; +"HEADPHONES_UNKNOWN" = "Nepoznato"; +"HEADPHONES_NONE" = "Bez"; +"CONNECTED" = "Spojeno"; +"NOT_CONNECTED" = "Nije spojeno"; +"HEADPHONE_CONNECTED_%@" = "Spojeno - %@"; +"HEADPHONE_DETECT_TITLE" = "Spojite slušalice"; +"HEADPHONE_DETECT_TEXT" = "Ovaj test zahtijeva Apple AirPods ili Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Prostorna memorija"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Ova aktivnost mjeri vašu kratkotrajnu prostornu memoriju dok dodirujete %@ redoslijedom kojim su zasvijetlili."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "cvjetove"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "cvjetovi"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Gledajte %@ kako će zasvijetliti jedan za drugim. Dodirnite te %@ istim redoslijedom kojim su zasvijetlili."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Gledajte %@ kako će zasvijetliti jedan za drugim. Dodirnite te %@ obrnutim redoslijedom od onog kojim su zasvijetlili."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Za početak dodirnite Pokreni i zatim gledajte pažljivo."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Rezultat"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Gledajte %@ kako svijetle"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Dodirnite %@ redoslijedom kojim su zasvijetlili"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Dodirnite %@ obrnutim redoslijedom"; +"MEMORY_GAME_COMPLETE_TITLE" = "Niz je dovršen"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Za nastavak dodirnite Sljedeće"; +"MEMORY_GAME_FAILED_TITLE" = "Pokušaj ponovno"; +"MEMORY_GAME_FAILED_MESSAGE" = "Ovaj put niste uspjeli. Dodirnite Sljedeće za nastavak."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Isteklo vrijeme"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Isteklo vam je vrijeme.\nZa nastavak kliknite Dalje."; +"MEMORY_GAME_COMPLETE" = "Igra je dovršena"; +"MEMORY_GAME_PAUSED_TITLE" = "Pauzirano"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Za nastavak dodirnite Sljedeće"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Memorijska aktivnost razvijena je uz pomoć dr. Katherine Possin i dr. Joela Kramera s Kalifornijskog sveučilišta u San Franciscu."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Vrijeme reakcije"; +"REACTION_TIME_TASK_INTENDED_USE" = "Ovom se aktivnošću procjenjuje koliko vam je vremena potrebno za reakciju na vizualni znak."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Protresite uređaj u bilo kojem smjeru čim se na zaslonu pojavi plava točka. Od vas će se zatražiti da to učinite %D puta."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Pokušaj %@ od %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Kada se pojavi plavi krug, brzo protresite uređaj"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroopov efekt"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Svaki put kad se pojavi riječ, odaberite prvo slovo naziva BOJE koja je prikazana."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Kad budete spremni za pokretanje Stroopovog testa, dodirnite Pokreni."; +"STROOP_TASK_STEP_TEXT" = "Odaberite prvo slovo naziva BOJE koja je prikazana."; +"STROOP_COLOR_RED" = "CRVENA"; +"STROOP_COLOR_GREEN" = "ZELENA"; +"STROOP_COLOR_BLUE" = "PLAVA"; +"STROOP_COLOR_YELLOW" = "ŽUTA"; +"STROOP_COLOR_RED_INITIAL" = "C"; +"STROOP_COLOR_GREEN_INITIAL" = "Z"; +"STROOP_COLOR_BLUE_INITIAL" = "P"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ž"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanojski toranj"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Ova aktivnost procjenjuje vaše vještine rješavanja slagalica."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Premjestite cijeli stog na označenu platformu u što je moguće manje poteza."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Riješite slagalicu"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Broj pokreta: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Ne mogu riješiti ovu slagalicu"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Raspon kretanja"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption treba biti lijevo ili desno"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Raspon kretanja lijevog koljena"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Raspon kretanja desnog koljena"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Ova aktivnost mjeri koliko možete ispružiti lijevo koljeno."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Ova aktivnost mjeri koliko možete ispružiti desno koljeno."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sjednite na rub stolice. Kad započnete, trebat ćete staviti uređaj na lijevo koljeno radi mjerenja. Molimo, uključite zvuk na uređaju kako biste čuli upute."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sjednite na rub stolice. Kad započnete, trebat ćete staviti uređaj na desno koljeno radi mjerenja. Molimo, uključite zvuk na uređaju kako biste čuli upute."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Stavite uređaj na lijevo koljeno, sa zaslonom okrenutim prema van, kako je prikazano na slici."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Stavite uređaj na desno koljeno, sa zaslonom okrenutim prema van, kako je prikazano na slici."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Kad budete spremni, dodirnite zaslon za početak i ispružite svoje lijevo koljeno koliko god možete. Vratite se na početni položaj i dodirnite ponovno kad ste gotovi."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Kad budete spremni, dodirnite zaslon za početak i ispružite svoje desno koljeno koliko god možete. Vratite se na početni položaj i dodirnite ponovno kad ste gotovi."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Postavite uređaj na svoje lijevo koljeno. Dodirnite zaslon i ispružite lijevo koljeno koliko god možete."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Postavite uređaj na svoje desno koljeno. Dodirnite zaslon i ispružite desno koljeno koliko god možete."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Kad ste gotovi, vratite svoje lijevo koljeno na početni položaj. Zatim dodirnite bilo gdje."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Kad ste gotovi, vratite svoje desno koljeno na početni položaj. Zatim dodirnite bilo gdje."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Raspon kretanja lijevog ramena"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Raspon kretanja desnog ramena"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Ova aktivnost mjeri koliko možete ispružiti lijevo rame."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Ova aktivnost mjeri koliko možete ispružiti desno rame."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Kad započnete, trebat ćete staviti uređaj na lijevo rame radi mjerenja. Molimo, uključite zvuk na uređaju kako biste čuli upute."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Kad započnete, trebat ćete staviti uređaj na desno rame radi mjerenja. Molimo, uključite zvuk na uređaju kako biste čuli upute."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Stavite uređaj na lijevo rame, sa zaslonom okrenutim prema van, kako je prikazano na slici."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Stavite uređaj na desno rame, sa zaslonom okrenutim prema van, kako je prikazano na slici."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Kad budete spremni, dodirnite zaslon za početak i podignite svoju lijevu ruku koliko god možete. Vratite se na početni položaj i dodirnite ponovno kad ste gotovi."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Kad budete spremni, dodirnite zaslon za početak i podignite svoju desnu ruku koliko god možete. Vratite se na početni položaj i dodirnite ponovno kad ste gotovi."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Postavite uređaj na svoje lijevo rame. Dodirnite zaslon i podignite lijevu ruku ispred sebe koliko god možete."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Postavite uređaj na svoje desno rame. Dodirnite zaslon i podignite desnu ruku ispred sebe koliko god možete."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Kad ste gotovi, vratite svoju lijevu ruku na početni položaj. Zatim dodirnite bilo gdje."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Kad ste gotovi, vratite svoju desnu ruku na početni položaj. Zatim dodirnite bilo gdje."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Tempirana šetnja"; +"TIMED_WALK_INTRO_DETAIL" = "Ova aktivnost mjeri funkcionalnost vaših donjih ekstremiteta."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Pronađite mjesto, po mogućnosti vani, gdje možete hodati približno %@ u ravnoj liniji što je brže moguće, ali na siguran način. Nemojte usporavati sve dok ne prođete završnu liniju."; +"TIMED_WALK_INTRO_2_DETAIL" = "Dodirnite Sljedeće za početak."; +"TIMED_WALK_FORM_TITLE" = "Pomagalo"; +"TIMED_WALK_FORM_TEXT" = "Koristite isto pomagalo za svaki test."; +"TIMED_WALK_QUESTION_TEXT" = "Nosite li ortozu za gležanj i stopalo?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Koristite li pomagalo?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Dodirnite ovdje za odabir odgovora."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nijedno"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Jedan štap za hodanje"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Jedna štaka"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dva štapa za hodanje"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dvije štake"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Hodalica/Guralica"; +"TIMED_WALK_INSTRUCTION_%@" = "Hodajte najviše %@ u ravnoj liniji."; +"TIMED_WALK_INSTRUCTION_TURN" = "Okrenite se."; +"TIMED_WALK_INSTRUCTION_2" = "Hodajte natrag do mjesta od kojeg ste krenuli."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Po završetku dodirnite Sljedeće."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Auditivni test tempiranog serijskog zbrajanja (PASAT) mjeri brzinu vaše obrade auditivnih podataka te sposobnost računanja."; +"PVSAT_INTRO_TEXT" = "Vizualni test tempiranog serijskog zbrajanja mjeri (PVSAT) brzinu vaše obrade vizualnih podataka te sposobnost računanja."; +"PAVSAT_INTRO_TEXT" = "Auditivni i vizualni test tempiranog serijskog zbrajanja (PAVSAT) mjeri brzinu vaše obrade auditivnih i vizualnih podataka te sposobnost računanja."; +"PSAT_INTRO_TEXT_2_%@" = "Jednoznamenkaste brojke prikazuju se svake %@.\nMorate pribrojiti svaku novu znamenku onoj koja joj neposredno prethodi.\nPozor, ne smijete računati ukupni iznos, nego samo zbroj posljednja dva broja."; +"PSAT_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"PSAT_INITIAL_INSTRUCTION" = "Zapamtite prvu znamenku."; +"PSAT_INSTRUCTION" = "Zbrojite ovu novu znamenku s prethodnom."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test s %@ rupa i klinovima"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Ova aktivnost mjeri funkciju vaših gornjih ekstremiteta dok stavljate klin u rupu. Ovu radnju morat ćete ponoviti %@ puta."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Testirat će se vaša lijeva i desna ruka.\nMorate što je brže moguće podići klin, staviti ga u otvor i, čim to napravite %@ puta, morate ga ponovno ukloniti %@ puta."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Testirat će se vaša desna i lijeva ruka.\nMorate što je brže moguće podići klin, staviti ga u otvor i, čim to napravite %@ puta, morate ga ponovno ukloniti %@ puta."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Stavite klin u rupu koristeći se lijevom rukom."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Stavite klin u rupu koristeći se desnom rukom."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Stavite klin iza crte koristeći se lijevom rukom."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Stavite klin iza crte koristeći se desnom rukom."; +"HOLE_PEG_TEST_TEXT" = "Podignite klin s dva prsta."; +"HOLE_PEG_TEST_TEXT_2" = "Podignite prste da biste ispustili klin."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Aktivnost drhtanja"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Ova aktivnost mjeri drhtanje vaših ruku u različitim položajima. Pronađite mjesto na kojem možete udobno sjediti tijekom trajanja ove aktivnosti."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Držite telefon u ruci koja vam je više zahvaćena, kako je prikazano na slici ispod."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Držite telefon u DESNOJ ruci kako je prikazano na slici ispod."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Držite telefon u LIJEVOJ ruci kako je prikazano na slici ispod."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Od vas će se zatražiti da napravite %@ dok sjedite s telefonom u ruci."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "zadatak"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dva zadatka"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tri zadatka"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "četiri zadatka"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "pet zadataka"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Dodirnite Sljedeće za nastavak."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Pripremite se na držanje telefona u krilu."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Pripremite se na držanje telefona u krilu LIJEVOM rukom."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Pripremite se na držanje telefona u krilu DESNOM rukom."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Nastavite držati telefon u krilu %ld s."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Sad držite telefon s ispruženom rukom u visini ramena."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Sad držite telefon u LIJEVOJ šaci s rukom ispruženom u visini ramena."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Sad držite telefon u DESNOJ šaci s rukom ispruženom u visini ramena."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Nastavite držati telefon s ispruženom rukom %ld s."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Sad držite telefon u visini ramena sa savijenim laktom."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Sad držite telefon LIJEVOM rukom u visini ramena sa savijenim laktom."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Sad držite telefon DESNOM rukom u visini ramena sa savijenim laktom."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Nastavite držati telefon sa savijenim laktom %ld s"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Sad držite lakat savijen i neprekidno dodirujte nos telefonom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Sad držite lakat savijen s telefonom u LIJEVOJ ruci i neprekidno dodirujte nos telefonom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Sad držite lakat savijen s telefonom u DESNOJ ruci i neprekidno dodirujte nos telefonom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Nastavite dodirivati nos telefonom %ld s"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Pripremite se za mahanje rotiranjem šake u zapešću (kao što maše engleska kraljica)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Pripremite se za mahanje rotiranjem šake, s telefonom u LIJEVOJ ruci (kao što maše engleska kraljica)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Pripremite se za mahanje rotiranjem šake, s telefonom u DESNOJ ruci (kao što maše engleska kraljica)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Nastavite mahati rotiranjem šake %ld s."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Sad uzmite telefon u LIJEVU ruku i nastavite na sljedeći zadatak."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Sad uzmite telefon u DESNU ruku i nastavite na sljedeći zadatak."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Nastavite na sljedeći zadatak."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivnost dovršena."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Od vas će se zatražiti da napravite %@ dok sjedite s telefonom prvo u jednoj ruci, zatim ponovno u drugoj ruci."; +"TREMOR_SKIP_LEFT_HAND" = "Ne mogu obaviti ovaj zadatak LIJEVOM rukom."; +"TREMOR_SKIP_RIGHT_HAND" = "Ne mogu obaviti ovaj zadatak DESNOM rukom."; +"TREMOR_SKIP_NEITHER" = "Mogu obaviti ovaj zadatak s obje ruke."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test praćenja linije"; +"TRAILMAKING_INTENDED_USE" = "Ovom se aktivnošću procjenjuje vaša vizualna pažnja i mogućnost promjene zadataka tako što se bilježi vrijeme potrebno za redoslijedno dodirivanje niza točaka."; +"TRAILMAKING_INTENDED_USE2_A" = "Nakon odbrojavanja, naizmjence dodirujte točke između brojeva i slova. Započnite dodirivanjem prvog broja “1”, zatim dodirnite brojeve “2” – “3” – “4”… sve dok ne dosegnete broj “7”."; +"TRAILMAKING_INTENDED_USE2_B" = "Nakon odbrojavanja, naizmjence dodirujte točke između brojeva i slova. Započnite dodirivanjem prvog broja “1”, zatim dodirnite prvo slovo “A”, a zatim “2” – “B” – “3” – “C”… sve dok ne dosegnete broj “7”."; +"TRAILMAKING_INTRO_TEXT" = "Napravite ovo što brže možete bez grešaka. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Prepozn. govora"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Ovom se aktivnošću snima vaš govor s mikrofonom na dnu uređaja, te se prevodi u tekst."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Dodirnite Pokreni za početak."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Prije nego što započnete govoriti pritisnite tipku za početak snimanja."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Započni snimati"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Zaustavi snimanje"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Uredi transkript"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Uredite tekst transkripta kako biste ispravili bilo koje krivo tumačenje govora."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Ovdje će se pojaviti vaš transkript."; +"SPEECH_RECOGNITION_FAILED" = "Prepoznavanje govora nije uspjelo."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Neuspjelo pokretanje prepoznavanja govora."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproduciraj zvuk"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Zaustavi audio zapis"; +"SPEECH_IN_NOISE_TITLE" = "Govor u buci"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Ovom se aktivnošću mjeri razumljivost govora u bučnim okruženjima."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Kao dio ovog testa, učinit ćete sljedeće:\n\nPoslušati rečenicu.\n\nJasno ponoviti što ste čuli ili preskočiti prema naprijed kako biste tipkovnicom natipkali ono što ste čuli. \n\nAko ponovite što ste čuli, moći ćete izmijeniti transkript koji je generirao uređaj za prepoznavanje govora."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Kalibracija glasnoće"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Dodirnite 'Reproduciraj zvuk', podesite svoju glasnoću na ugodnu razinu i zatim dodirnite 'Zaustavi audio zapis' za nastavak."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Slušaj"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Rečenica pomiješana s pozadinskom bukom po nasumično odabranom Omjeru signala i šuma (SNR) reproducirat će se samo jednom."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Govori"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Ponovite što ste čuli."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Datoteka se ne može izraditi"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nije se moglo ukloniti dovoljno log datoteka za dosezanje praga"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Greška prilikom podešavanja atributa"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Datoteka nije označena kao obrisana (nije označena kao postavljena)"; +"ERROR_DATALOGGER_MULTIPLE" = "Više grešaka prilikom uklanjanja log zapisa"; +"ERROR_RECORDER_NO_DATA" = "Nisu pronađeni prikupljeni podaci."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Izlazni direktorij nije naveden"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL mjerač"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Ovom se aktivnošću mjeri razina tlaka zvuka u okruženju. Ako su razine buke previsoke, nećete moći nastaviti. Premjestite se na tiše mjesto kako biste dovršili ovaj zadatak ili ponovite ovu aktivnost kasnije."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Izračunavanje"; +"ENVIRONMENTSPL_THRESHOLD" = "Prag: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Pozadinska je buka u redu"; +"ENVIRONMENTSPL_NOISE" = "Previše pozadinske buke"; +"ENVIRONMENTSPL_TITLE_2" = "Pronađite tiho mjesto"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Kako bi se osigurala točnost, ovaj test treba provoditi u tihom okruženju."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Započni zadatak"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Bez podataka"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Pomaknite kliznik za unos vrijednosti"; +"SLIDER_I_DONT_KNOW" = "Ne znam"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Stranica"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Natrag"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Prikaži minijaturu PDF-a"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Sakrij minijaturu PDF-a"; +"AX_BUTTON_ANNOTATE" = "Zabilježi"; +"AX_BUTTON_SHOW_SEARCH" = "Prikaži traku za pretraživanje"; +"AX_BUTTON_HIDE_SEARCH" = "Sakrij traku za pretraživanje"; +"AX_BUTTON_SHARE" = "Dijeli"; + + +"AX_COMPLETION_ILLUSTRATION" = "Prikaz kvačice u plavom krugu što označava uspjeh"; + +"AX_SIGNVIEW_LABEL" = "Polje za potpis"; +"AX_SIGNVIEW_HINT" = "Dodirnite zaslon i pomičite prst za potpisivanje"; +"AX_SIGNVIEW_SIGNED" = "Potpisano"; +"AX_SIGNVIEW_UNSIGNED" = "Nepotpisano"; + +"AX_SELECTED" = "Odabrano"; +"AX_UNSELECTED" = "Nije odabrano"; +"AX_SELECT_ALL_THAT_APPLY" = "NAVEDITE SVOJE SIMPTOME"; + +"AX_SLIDER_LABEL" = "Kliznik odgovora. Raspon od %@ do %@"; +"AX_UNLABELED_IMAGE" = "Neoznačena slika"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Započni zadatak"; + +"AX.MEMORY.TILE.ACTIVE" = "aktivno"; +"AX.MEMORY.TILE.CORRECT" = "točno"; +"AX.MEMORY.TILE.INCORRECT" = "netočno"; +"AX.MEMORY.TILE.QUIESCENT" = "neaktivno"; +"AX.MEMORY.TILE.LABEL" = "Igra memorije s pločicama"; + +"AX_IMAGE_CAPTURE_LABEL" = "Snimi pregled"; +"AX_IMAGE_CAPTURED_LABEL" = "Snimljena slika"; + +"AX_VIDEO_CAPTURE_LABEL" = "Pregled snimanja videa"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Snimanje videa je dovršeno"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Pločica veličine %@ ne može se staviti na pločicu veličine %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cilj"; +"AX_TOWER_OF_HANOI_TOWER" = "Toranj"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Dodirnite dvaput za stavljanje pločice"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Dodirnite dvaput za odabir najviše pločice"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Ima pločicu veličine %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Isprazni"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Odbaci tipkovnicu"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Raspon od %@ do %@."; +"AX_GRAPH_STACK_PREFIX" = "Stog sastavljen od"; +"AX_GRAPH_AND_SEPARATOR" = " i "; +"AX_GRAPH_POINT_%@" = "Točka: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Oblik vala govora"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Kad snimanje započne, aktivirajte drugi put za zaustavljanje snimanja."; + +"AX_AUDIO_BAR_GRAPH" = "Stupčasti grafikon audio zapisa"; + +"AX_AMSLER_GRID_LABEL" = "Amslerova mreža"; +"AX_AMSLER_GRID_HINT" = "Prstom ili olovkom izravno označite rešetku ili za završetak povucite lijevo izvan rešetke."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tipke koje se mogu dodirivati"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Dodirnite za lijevo uho"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktivirajte za početak testa. Kad test započne, dodirnite izravno na ovu tipku kad začujete zvuk u lijevom uhu."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Dodirnite za desno uho"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktivirajte za početak testa. Kad test započne, dodirnite izravno na ovu tipku kad začujete zvuk u desnom uhu."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Koristeći VoiceOver, istražite zaslon dodirom kako biste saznali gdje se nalaze tipke za svako uho. Kad test započne, tipke će se moći izravno dodirivati. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Dodirnite za jedan prst"; +"AX_TAP_BUTTON_2_LABEL" = "Dodirnite za drugi prst"; +"AX_TAP_BUTTON_HINT" = "Aktivirajte kako bi se tipke mogle izravno dodirivati."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Koristeći VoiceOver, istražite zaslon dodirom kako biste saznali gdje se nalaze tipke. Aktivirajte bilo koju tipku kako bi se tipke mogle izravno dodirivati."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Tipke se sada mogu izravno dodirivati."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Koristeći VoiceOver, tipka će se moći izravno dodirnuti. Nalazit će se blizu sredine zaslona."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Koristeći VoiceOver, tipke u testu moći će se izravno dodirivati."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Nije moguće dekodirati restoreData za inicijalizaciju"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..48ce8b4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hr.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d greška) + other + (%d grešaka) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.strings new file mode 100755 index 0000000..c20b5f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Beleegyezés"; +"CONSENT_NAME_GIVEN" = "Utónév"; +"CONSENT_NAME_FAMILY" = "Családi név"; +"CONSENT_NAME_PLACEHOLDER" = "Szükséges"; +"CONSENT_REVIEW_TITLE" = "Áttekintés"; +"CONSENT_REVIEW_INSTRUCTION" = "Tekintse át az alábbi űrlapot, majd koppintson az Elfogadom gombra, ha készen áll a folytatásra."; +"CONSENT_REVIEW_ALERT_TITLE" = "Áttekintés"; +"CONSENT_SIGNATURE_TITLE" = "Aláírás"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Kérjük, írja alá az ujjával az alábbi mezőben."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Itt írja alá"; +"CONSENT_PAGE_NUMBER_FORMAT" = "%2$ld/%1$ld oldal"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Üdvözöljük"; +"CONSENT_SECTION_DATA_GATHERING" = "Adatgyűjtés"; +"CONSENT_SECTION_PRIVACY" = "Adatvédelem"; +"CONSENT_SECTION_DATA_USE" = "Adathasználat"; +"CONSENT_SECTION_STUDY_SURVEY" = "Kérdőív"; +"CONSENT_SECTION_STUDY_TASKS" = "A vizsgálat feladatai"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Szükséges idő"; +"CONSENT_SECTION_WITHDRAWING" = "Visszavonás"; +"CONSENT_LEARN_MORE_TITLE" = "További infók"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "További információk az adatok gyűjtésének módjáról"; +"LEARN_MORE_DATA_USE" = "További információk az adatok felhasználásának módjáról"; +"LEARN_MORE_PRIVACY" = "További információk az adatok és személyes információk védelmének módjáról"; +"LEARN_MORE_WELCOME" = "További információk a vizsgálatról"; +"LEARN_MORE_STUDY_SURVEY" = "További információk a kérdőívről"; +"LEARN_MORE_TIME_COMMITMENT" = "További információk arról, hogy mennyi időt vesz igénybe a tanulmány"; +"LEARN_MORE_TASKS" = "További információk a bennfoglalt feladatokról"; +"LEARN_MORE_WITHDRAWING" = "További információk a visszavonásról"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Megosztási beállítások"; +"CONSENT_SHARE_WIDELY_%@" = "Az adataim megosztása a következővel és világszerte szakképzett kutatókkal: %@"; +"CONSENT_SHARE_ONLY_%@" = "Az adataim megosztása csak a következővel: %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "A(z) %@ meg fogja kapni az Ön vizsgálati adatait az Ön vizsgálatban való részvételéről.\n\nA kódolt vizsgálati adatok szélesebb körű megosztása (az olyan információk nélkül, mint az Ön neve) segítheti ezt és a jövőbeli kutatásokat."; +"LEARN_MORE_CONSENT_SHARING" = "További infó az adatok megosztásáról"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nyomtatott név"; +"CONSENT_DOC_LINE_SIGNATURE" = "Aláírás"; +"CONSENT_DOC_LINE_DATE" = "Dátum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%2$@/%1$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "%2$@/%1$@. kérdés"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Átugorva"; +"REVIEW_EDIT_ANSWER" = "Szerkesztés"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Érvénytelen érték"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "A(z) %1$@ túllépi a maximálisan engedélyezett értéket (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "A(z) %1$@ kisebb a minimálisan engedélyezett értéknél (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "A(z) %@ nem érvényes érték."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Érvénytelen e-mail cím: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Adjon meg egy címet"; +"LOCATION_ERROR_TITLE" = "A megadott cím nem található"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Az aktuális hely feloldása nem sikerült. Írjon be egy címet, vagy menjen olyan helyre, ahol a GPS-jelerősség kedvezőbb."; +"LOCATION_ERROR_MESSAGE_DENIED" = "A helymeghatározáshoz való hozzáférés le van tiltva. Engedélyezze az alkalmazás számára a helymeghatározás funkció használatát a Beállításokban."; +"LOCATION_ERROR_GEOCODE" = "A megadott címhez nem található eredmény. Győződjön meg arról, hogy a cím érvényes."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Ön nem csatlakozik az internethez, vagy túllépte a címkeresési kérelmek maximálisan engedélyezett számát. Ha nem csatlakozik az internethez, akkor kapcsolja be a Wi-Fi-t és válaszoljon erre a kérdésre, ha a kihagyás gomb megjelenik, akkor hagyja ki ezt a kérdést, vagy térjen vissza a kérdőívre, amikor már csatlakozik az internethez. Ellenkező esetben próbálkozzon újra néhány perc múlva."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "A szöveg túllépi a maximális hosszt: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "A kamera nem érhető el osztott képernyős nézetben."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "nagyede@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Jelszó"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Jelszó megadása"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Megerősítés"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Jelszó ismételt megadása"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "A jelszavak nem egyeznek meg."; +"ADDITIONAL_INFO_SECTION_TITLE" = "További információk"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Ede"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Nagy"; +"GENDER_FORM_ITEM_TITLE" = "Nem"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Nem kiválasztása"; +"DOB_FORM_ITEM_TITLE" = "Születési dátum"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Dátum kiválasztása"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonszám"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Ellenőrzés"; +"VERIFICATION_STEP_TITLE" = "E-mail ellenőrzése"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Koppintson az alábbi linkre, ha nem kapott ellenőrző e-mailt, és azt szeretné, ha újra elküldenénk."; +"RESEND_EMAIL_BUTTON_TITLE" = "Ellenőrző e-mail újraküldése"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Bejelentkezés"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Elfelejtette a jelszót?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Adja meg a jelkódot"; +"PASSCODE_CONFIRM_MESSAGE" = "Erősítse meg a jelkódját"; +"PASSCODE_SAVED_MESSAGE" = "A jelkód mentve"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "A jelkód hitelesítve van"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Adja meg a régi jelkódját"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Adja meg az új jelkódját"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Erősítse meg az új jelkódját"; +"PASSCODE_INVALID_ALERT_TITLE" = "A jelkód helytelen"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "A jelkódok nem egyeznek meg. Próbálja újra."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Kérjük, végezzen hitelesítést a Touch ID-val"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-val kapcsolatos hiba"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Kizárólag számkarakterek engedélyezettek."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Jelkóddal történő belépés folyamatjelzője"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@/%@ számjegy megadva"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Elfelejtette a jelkódot?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nem lehetett hozzáadni a Kulcskarika-elemet."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nem lehetett frissíteni a Kulcskarika-elemet."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nem lehetett törölni a Kulcskarika-elemet."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "A Kulcskarika-elem nem található."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "I. típus"; +"FITZPATRICK_SKIN_TYPE_II" = "II. típus"; +"FITZPATRICK_SKIN_TYPE_III" = "III. típus"; +"FITZPATRICK_SKIN_TYPE_IV" = "IV. típus"; +"FITZPATRICK_SKIN_TYPE_V" = "V. típus"; +"FITZPATRICK_SKIN_TYPE_VI" = "VI. típus"; + +/* Gender values. */ +"GENDER_FEMALE" = "Nő"; +"GENDER_MALE" = "Férfi"; +"GENDER_OTHER" = "Egyéb"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nem"; +"BOOL_YES" = "Igen"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "font"; +"MEASURING_UNIT_OZ" = "uncia"; + +/* Limb values. */ +"LIMB_LEFT" = "bal"; +"LIMB_RIGHT" = "jobb"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Koppintson a válaszhoz"; +"NULL_ANSWER" = "Válasz kiválasztása"; +"PLACEHOLDER_IMAGE_CHOICES" = "Koppintson a kijelöléshez"; +"PLACEHOLDER_LONG_TEXT" = "Koppintson az íráshoz."; + +/* Button titles */ +"BUTTON_AGREE" = "Elfogadom"; +"BUTTON_CANCEL" = "Mégsem"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Törlés"; +"BUTTON_CLEAR_SIGNATURE" = "Aláírás törlése"; +"BUTTON_APPLY" = "Alkalmazás"; +"BUTTON_DISAGREE" = "Nem fogadom el"; +"BUTTON_DONE" = "Kész"; +"BUTTON_GET_STARTED" = "Kezdés"; +"BUTTON_LEARN_MORE" = "További infók"; +"BUTTON_NEXT" = "Következő"; +"BUTTON_SKIP" = "Kihagyás"; +"BUTTON_SKIP_QUESTION" = "A kérdés kihagyása"; +"BUTTON_START_TIMER" = "Időzítő indítása"; +"BUTTON_OPTION_SAVE" = "Mentés későbbre"; +"BUTTON_OPTION_DISCARD" = "Eredmények elvetése"; +"BUTTON_OPTION_STOP_TASK" = "Feladat abbahagyása"; +"BUTTON_SAVE" = "Mentés"; +"BUTTON_CLEAR_ANSWER" = "Válasz törlése"; +"BUTTON_READ_ONLY_MODE" = "Ez a válasz nem módosítható."; +"BUTTON_COPYRIGHT" = "Szerzői jog"; +"BUTTON_CLOSE" = "Bezárás"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Tevékenység indítása:"; +"TASK_COMPLETE_TITLE" = "Tevékenység befejezve"; +"TASK_COMPLETE_TEXT" = "Az adatok ki lesznek elemezve, és értesítést fog kapni, ha az eredmény elkészült."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ maradt."; +"TOUCH_ANYWHERE_LABEL" = "A folytatáshoz érintse meg a képernyőt"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Kép készítése"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Kép készítése újra"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nem található kamera. Ezt a lépést nem lehet végrehajtani."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "A lépés végrehajtásához a Beállításokban engedélyezze az alkalmazás számára, hogy hozzáférjen a kamerához."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Az elkészített képekhez nem lett megadva kimeneti könyvtár."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Az elkészített képet nem sikerült menteni."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Felvétel indítása"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Felvétel leállítása"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Videó ismételt rögzítése"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitnesz"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Távolság (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Pulzusszám (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Üljön kényelmesen %@ időtartamig."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Gyalogoljon olyan gyorsan, amilyen gyorsan tud %@ időtartam alatt."; +"FITNESS_INTRO_TEXT_FORMAT" = "Ez a tevékenység a pulzusát figyeli, és megméri, milyen messzire tud gyalogolni %1$@ időtartam alatt."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Kültéren gyalogoljon olyan gyorsan, ahogy csak tud %1$@ időtartamig. Amikor befejezte, üljön le, és pihenjen kényelmesen %2$@ időtartamig. A kezdéshez koppintson a Kezdés elemre."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Testtartás és egyensúly"; +"WALK_INTRO_TEXT" = "Ez a tevékenység a testtartását és egyensúlyát méri járás és állás közben. Ne folytassa, ha segítség nélkül nem tud biztonságosan gyalogolni."; +"WALK_INTRO_2_TEXT_%ld" = "Keressen olyan helyet, ahol segítség nélkül gyalogolhat egyenesen körülbelül %ld lépést."; +"WALK_INTRO_2_DETAIL" = "Tegye az eszközt a zsebébe vagy a táskájába, és kövesse a hangutasításokat."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Most álljon mozdulatlanul %@ időtartamig."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Álljon mozdulatlanul %@ időtartamig."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Forduljon meg, és menjen vissza a kiindulási ponthoz."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Tegyen meg legalább %ld lépést egyenesen."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Keressen egy olyan helyet, ahol egyenes vonalban tud oda-vissza gyalogolni. Próbáljon meg folyamatosan gyalogolni, és a végeken úgy forduljon meg, mintha egy útjelző bóját kerülne meg.\n\nEzután utasítást fog kapni, hogy fogduljon meg egy teljes kört megtéve, majd álljon meg, engedje le a törzse mellett karjait, és álljon vállszélességű terpeszben."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Koppintson a Kezdés elemre, amikor készen áll.\n\nEzután tegye az eszközt a zsebébe vagy a táskájába, és kövesse a hangutasításokat."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Gyalogoljon oda-vissza egy egyenes vonal mentén ennyi ideig: %@. A szokásos tempójában gyalogoljon."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Forduljon meg egy teljes kör mentén, és álljon mozdulatlanul ennyi ideig: %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Befejezte a tevékenységet."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Koppintási sebesség"; +"TAPPING_TASK_TITLE_RIGHT" = "Jobb kéz"; +"TAPPING_TASK_TITLE_LEFT" = "Bal kéz"; +"TAPPING_INTRO_TEXT" = "Ez a tevékenység megméri a koppintási sebességét."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Tegye az eszközt vízszintes felületre."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Ugyanannak a kezének két ujjával felváltva koppintson a gombokra a kijelzőn."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "A jobb kezének két ujjával felváltva koppintson a gombokra a kijelzőn."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "A bal kezének két ujjával felváltva koppintson a gombokra a kijelzőn."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Most ismételje meg ugyanezt a tesztet jobb kézzel."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Most ismételje meg ugyanezt a tesztet bal kézzel."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Koppintson az egyik, majd a másik ujjával. Próbáljon meg egyenletes időközönként koppintani. Folytassa a koppintásokat ennyi ideig: %@."; +"TAPPING_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Koppintson\na Következő elemre\na kezdéshez."; +"TAP_BUTTON_TITLE" = "Koppintás"; +"TOTAL_TAPS_LABEL" = "Összes koppintás"; +"TAPPING_INSTRUCTION" = "Két ujjal koppintson a gombokra olyan egyenletesen, ahogy csak tud."; +"TAPPING_INSTRUCTION_RIGHT" = "Koppintson a gombokra JOBB kézzel."; +"TAPPING_INSTRUCTION_LEFT" = "Koppintson a gombokra BAL kézzel."; +"TAPPING_SKIP_TITLE" = "Kéz kihagyása"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler-rács"; +"AMSLER_GRID_INTRO_TEXT" = "Ez a tevékenység segít észlelni a felhasználó látásával kapcsolatos problémákat."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "A vizsgálat alatt tartsa 30 cm-re az eszközt az arcától, szemmagasságban."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Csukja be a %@, és nézze a négyzetrács közepén lévő pontot.\n\nAz ujja vagy egy érintőceruza segítségével jelölje meg az összes torzítva megjelenő elemet, például elmosott vagy hullámos vonalakat.\n\nHa elkészült, legyintsen balra bárhol, a rácson kívül."; +"AMSLER_GRID_LEFT_EYE" = "bal szemét"; +"AMSLER_GRID_RIGHT_EYE" = "jobb szemét"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Hang"; +"AUDIO_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"AUDIO_INSTRUCTION" = "Amilyen hosszan csak tudja, mondja, hogy „Áááááá” a mikrofonba."; +"AUDIO_INTRO_TEXT" = "Vegyen mély levegőt, és amilyen hosszan csak tudja, mondja a mikrofonba, hogy „Áááááá”. Próbáljon egyenletes hangerőt tartani, hogy a hangsávok kékek maradjanak."; +"AUDIO_INTENDED_USE" = "Ez a tevékenység kiértékeli a hangját, rögzítve, ahogy az eszköz alján lévő mikrofonba beszél."; +"AUDIO_TOO_LOUD_LABEL" = "Túl hangos"; +"AUDIO_GENERIC_ERROR_LABEL" = "Nem sikerült hangot felvenni"; +"AUDIO_LEVEL_CHECK_LABEL" = "Kérjük, várjon, amíg ellenőrizzük a háttérzaj szintjét."; +"AUDIO_TOO_LOUD_MESSAGE" = "A környezeti zaj szinte túl magas a hangja felvételéhez. Kérjük, menjen csendesebb helyre, és próbálkozzon újra."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Koppintson a Következő elemre, amikor készen áll."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Hangaudiometria"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Ez a tevékenység azt méri fel, hogyan hallja Ön a különböző hangokat."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "A kezdés előtt dugja be, és vegye fel a fejhallgatót.\n\nA hang nagyon halk lesz, és nem fog hasonlítani a szokásos jelzéshangra. A hang halkan kezdődik, majd felerősödik. Kérjük, figyeljen, és koppintson a bal vagy jobb gombra, attól függően, melyik fülében hallja a hangot."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ön most valószínűleg hall egy hangot. Állítsa be a hangerőt az eszköz oldalán található vezérlőkkel.\n\nKoppintson egy gombra, amikor készen áll a kezdésre."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Amikor hangot hall, koppintson a bal vagy a jobb gombra attól függően, hogy melyik fülében hallja a hangot."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Bal fül"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Jobb fül"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, bal"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, jobb"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Hangaudiometria"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Koppintson, amikor hangot hall."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Hang és hangerő"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Egy hangsorozatot fog hallani."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Amikor hangot hall, koppintson a gombra."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "A hangerő 50 százalékra lesz állítva ehhez a teszthez."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Ez a vizsgálat 10 percig tart."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "A zavaró körülmények kizárásához kapcsolja be a Ne zavarjanak funkciót."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "A hangok először a jobb fülében lesznek lejátszva."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "A hangok most a bal fülében lesznek lejátszva."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Ez a tevékenység megméri egy személy hallási küszöbének szintjét a dB HL skálán."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Győződjön meg róla, hogy az eszköz hangereje a maximális szintre van állítva.\n\nA feladat alatt egy halk hang lesz lejátszva a bal vagy jobb fülében.\n\nHallgasson figyelmesen, és minden alkalommal koppintson a gombra, amikor hangot hall."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ez a vizsgálat megállapítja, hogy milyen hangosnak kell lennie egy hangnak, hogy Ön azt meghallja."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Belépési kérdőív."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Ha az egyik fülére jobban hall, válassza ki itt."; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "bal"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "jobb"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "nincs beállítás"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Teszt megszakítva"; +"dBHL_ALERT_TITLE_START_OVER" = "Újrakezdés"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Teszt megszakítása"; +"dBHL_ALERT_TEXT" = "Csatlakoztassa újra az AirPods vagy EarPods fülhallgatóját a teszt elvégzéséhez."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ teljesítve"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Fejhallgató"; +"HEADPHONES_UNKNOWN" = "Ismeretlen"; +"HEADPHONES_NONE" = "Nincs"; +"CONNECTED" = "Csatlakoztatva"; +"NOT_CONNECTED" = "Nem kapcsolódik"; +"HEADPHONE_CONNECTED_%@" = "Csatlakoztatva – %@"; +"HEADPHONE_DETECT_TITLE" = "Fejhallgató csatlakoztatása"; +"HEADPHONE_DETECT_TEXT" = "Ehhez a vizsgálathoz Apple AirPodsra vagy Apple EarPodsra van szükség"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Térbeli memória"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Ez a tevékenység a rövidtávú térbeli memóriát vizsgálja. Ehhez ismételje meg a felvillanó %@ képeinek sorrendjét."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "virágok"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "virágok"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "A(z) %@ egymás után fel fognak villanni. Koppintson a(z) %@ képeire a megjelenésükkel azonos sorrendben."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "A(z) %@ egymás után fel fognak villanni. Koppintson a(z) %@ képeire a megjelenésük fordított sorrendjében."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre, majd figyeljen."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Eredmény"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Figyelje, ahogy a(z) %@ felvillannak"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Koppintson a(z) %@ képeire olyan sorrendben, ahogy felvillantak"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Koppintson a(z) %@ képeire fordított sorrendben"; +"MEMORY_GAME_COMPLETE_TITLE" = "A sorozat befejeződött"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "A folytatáshoz koppintson a Következő gombra"; +"MEMORY_GAME_FAILED_TITLE" = "Újrapróbálkozás"; +"MEMORY_GAME_FAILED_MESSAGE" = "Ez alkalommal nem sikerült. A folytatáshoz koppintson a Következő gombra."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Letelt az idő"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Elfogyott az idő.\nA folytatáshoz koppintson a Következő gombra."; +"MEMORY_GAME_COMPLETE" = "Játék befejezve"; +"MEMORY_GAME_PAUSED_TITLE" = "Szüneteltetve"; +"MEMORY_GAME_PAUSED_MESSAGE" = "A folytatáshoz koppintson a Következő gombra"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "A memóriát vizsgáló feladat elkészítéséhez Katherine Possin PhD és Joel Kramer PhD, a San Franciscó-i Kaliforniai Egyetem munkatársai nyújtottak segítséget."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reakcióidő"; +"REACTION_TIME_TASK_INTENDED_USE" = "Ez a tevékenység felméri, hogy mennyi ideig tart Önnek válaszolni egy vizuális jelzésre."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Rázza meg a készüléket tetszőleges irányban, amint megjelenik a képernyőn a kék pont. A készülék %D alkalommal fogja megkérni erre."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "%@/%@. kísérlet"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Gyorsan rázza meg a készüléket, amikor megjelenik a kék kör"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop-hatás"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Amikor megjelenik egy szó, válassza ki a látott SZÍN nevének első betűjét."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Ha készen áll a Stroop-feladat elkezdésére, koppintson a Kezdés gombra."; +"STROOP_TASK_STEP_TEXT" = "Válassza ki a látott SZÍN nevének első betűjét."; +"STROOP_COLOR_RED" = "PIROS"; +"STROOP_COLOR_GREEN" = "ZÖLD"; +"STROOP_COLOR_BLUE" = "KÉK"; +"STROOP_COLOR_YELLOW" = "SÁRGA"; +"STROOP_COLOR_RED_INITIAL" = "P"; +"STROOP_COLOR_GREEN_INITIAL" = "Z"; +"STROOP_COLOR_BLUE_INITIAL" = "K"; +"STROOP_COLOR_YELLOW_INITIAL" = "S"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanoi tornyai"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Ez a tevékenység kiértékeli az Ön kirakómegoldási képességeit."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Helyezze át a teljes köteget a kijelölt oszlopra a lehető legkevesebb lépésben."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "A kirakós megoldása"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Lépések száma: %@\n%@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Nem tudom megoldani ezt a kirakót"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Mozgástartomány"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "A limbOption beállításaként a bal vagy a jobb értéket kell megadni"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Bal térd mozgástartománya"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Jobb térd mozgástartománya"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Ez a feladat azt méri, hogy mennyire tudja kinyújtani a bal térdét."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Ez a feladat azt méri, hogy mennyire tudja kinyújtani a jobb térdét."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Üljön le egy szék szélére. Első lépésként tegye az eszközét a bal térdére egy mérés elvégzéséhez. Kapcsolja be a hangot az eszközén, hogy hallja az utasításokat."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Üljön le egy szék szélére. Első lépésként tegye az eszközét a jobb térdére egy mérés elvégzéséhez. Kapcsolja be a hangot az eszközén, hogy hallja az utasításokat."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Tegye az eszközét a bal térdére úgy, hogy a kijelző kifelé nézzen, ahogy ez a képen is látható."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Tegye az eszközét a jobb térdére úgy, hogy a kijelző kifelé nézzen, ahogy ez a képen is látható."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Ha készen áll, a kezdéshez koppintson a képernyőre, és nyújtsa ki a bal térdét, amennyire csak tudja. Térjen vissza a kiinduló helyzetbe, és koppintson ismét, ha elkészült."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Ha készen áll, a kezdéshez koppintson a képernyőre, és nyújtsa ki a jobb térdét, amennyire csak tudja. Térjen vissza a kiinduló helyzetbe, és koppintson ismét, ha elkészült."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Tegye eszközét a bal térdére. Koppintson a képernyőre, és nyújtsa ki bal térdét, amennyire csak tudja."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Tegye eszközét a jobb térdére. Koppintson a képernyőre, és nyújtsa ki jobb térdét, amennyire csak tudja."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Ha elkészült, engedje vissza bal térdét a kiinduló helyzetbe. Majd koppintson bárhova."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Ha elkészült, engedje vissza jobb térdét a kiinduló helyzetbe. Majd koppintson bárhova."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Bal váll mozgástartománya"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Jobb váll mozgástartománya"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Ez a feladat azt méri, hogy mennyire tudja kinyújtani a bal vállát."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Ez a feladat azt méri, hogy mennyire tudja kinyújtani a jobb vállát."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Első lépésként tegye az eszközét a bal vállára egy mérés elvégzéséhez. Kapcsolja be a hangot az eszközén, hogy hallja az utasításokat."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Első lépésként tegye az eszközét a jobb vállára egy mérés elvégzéséhez. Kapcsolja be a hangot az eszközén, hogy hallja az utasításokat."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Tegye az eszközét a bal vállára úgy, hogy a kijelző kifelé nézzen, ahogy ez a képen is látható."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Tegye az eszközét a jobb vállára úgy, hogy a kijelző kifelé nézzen, ahogy ez a képen is látható."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Ha készen áll, a kezdéshez koppintson a képernyőre, és emelje fel a bal karját, amennyire csak tudja. Térjen vissza a kiinduló helyzetbe, és koppintson ismét, ha elkészült."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Ha készen áll, a kezdéshez koppintson a képernyőre, és emelje fel a jobb karját, amennyire csak tudja. Térjen vissza a kiinduló helyzetbe, és koppintson ismét, ha elkészült."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Tegye eszközét a bal vállára. Koppintson a képernyőre, és emelje fel bal karját előre, amennyire csak tudja."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Tegye eszközét a jobb vállára. Koppintson a képernyőre, és emelje fel jobb karját előre, amennyire csak tudja."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Ha elkészült, engedje vissza bal karját a kiinduló helyzetbe. Majd koppintson bárhova."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Ha elkészült, engedje vissza jobb karját a kiinduló helyzetbe. Majd koppintson bárhova."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Időre mért gyaloglás"; +"TIMED_WALK_INTRO_DETAIL" = "Ez a tevékenység az alsó végtagok működését méri."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Keressen olyan helyet, lehetőleg kültéren, ahol %@ távolságot egyenesen tud gyalogolni olyan gyorsan, ahogy csak tud, de biztonságosan. Ne lassítson le, amíg el nem hagyta a célvonalat."; +"TIMED_WALK_INTRO_2_DETAIL" = "Koppintson a Következő gombra a kezdéshez."; +"TIMED_WALK_FORM_TITLE" = "Segítőeszköz"; +"TIMED_WALK_FORM_TEXT" = "Ugyanazt a segítőeszközt használja minden teszthez."; +"TIMED_WALK_QUESTION_TEXT" = "Használ boka-járáskönnyítőt?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Használ segítőeszközt?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Válasz kijelöléséhez koppintson ide."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nincs"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Egyoldali bot"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Egyoldali mankó"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Kétoldali bot"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Kétoldali mankó"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Járókeret/rollátor"; +"TIMED_WALK_INSTRUCTION_%@" = "Gyalogoljon legalább %@ távolságra egyenesen."; +"TIMED_WALK_INSTRUCTION_TURN" = "Forduljon meg."; +"TIMED_WALK_INSTRUCTION_2" = "Gyalogoljon vissza oda, ahonnan elindult."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Koppintson a Következő lehetőségre, ha elkészült."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Az Ütemes hallási sorozatösszeadási teszt a hallási információfeldolgozási sebességet és számítási képességet méri."; +"PVSAT_INTRO_TEXT" = "Az Ütemes vizuális sorozatösszeadási teszt a vizuális információfeldolgozási sebességet és számítási képességet méri."; +"PAVSAT_INTRO_TEXT" = "Az Ütemes hallási és vizuális sorozatösszeadási teszt a hallási és vizuális információfeldolgozási sebességet és számítási képességet méri."; +"PSAT_INTRO_TEXT_2_%@" = "Egyszámjegyű számok jelennek meg %@ időközönként.\nMinden új számjegyet adjon hozzá az előtte lévőhöz.\nFigyelem: Ne a teljes sorozat összegét számítsa ki, csak az utolsó két számjegyét."; +"PSAT_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"PSAT_INITIAL_INSTRUCTION" = "Jegyezze meg ezt az első számjegyet."; +"PSAT_INSTRUCTION" = "Adja hozzá ezt az új számjegyet az előzőhöz."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@ lyukú körillesztő teszt"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Ez a tevékenység a felső végtagok mozgását vizsgálja, amelynek során a rendszer megkéri Önt, hogy illesszen bele egy kört egy lyukba. Ezt %@ alkalommal kell megtennie."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "A bal és a jobb keze egyaránt tesztelve lesz.\nMinél gyorsabban vegye fel a kört, és illessze be a lyukba, és miután ezt %@ alkalommal megtette, távolítsa el %@ alkalommal."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "A jobb és a bal keze egyaránt tesztelve lesz.\nMinél gyorsabban vegye fel a kört, és illessze be a lyukba, és miután ezt %@ alkalommal megtette, távolítsa el %@ alkalommal."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Tegye a kört a lyukba a bal kezével."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Tegye a kört a lyukba a jobb kezével."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Tegye a kört a vonal mögé a bal kezével."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Tegye a kört a vonal mögé a jobb kezével."; +"HOLE_PEG_TEST_TEXT" = "Fogja meg a kört két ujjal."; +"HOLE_PEG_TEST_TEXT_2" = "Emelje fel az ujjait a kör elhelyezéséhez."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Remegési tevékenység"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Ez a tevékenység a keze remegését méri különböző helyzetekben. Keressen egy olyan helyet, ahol kényelmesen le tud ülni a tevékenység idejére."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Tartsa a telefont a gyakrabban használt kezében, a képen látható módon."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Tartsa a telefont a JOBB kezében, a képen látható módon."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Tartsa a telefont a BAL kezében, a képen látható módon."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "A rendszer fel fogja kérni %@ végrehajtására, miközben ül a telefonnal a kezében."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "egy feladat"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "két feladat"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "három feladat"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "négy feladat"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "öt feladat"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Koppintson a Következő elemre a folytatáshoz."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Készüljön fel arra, hogy a telefont az ölében tartsa."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Készüljön fel arra, hogy a telefont a BAL kezével az ölében tartsa."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Készüljön fel arra, hogy a telefont a JOBB kezével az ölében tartsa."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Tartsa az ölében a telefont %ld másodpercig."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Most tartsa a telefont kinyújtott karral vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Most tartsa a telefont kinyújtott karral, BAL kézzel vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Most tartsa a telefont kinyújtott karral, JOBB kézzel vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Tartsa a telefont kinyújtott karral %ld másodpercig."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Most tartsa a telefont behajlított könyökkel vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Most tartsa a telefont behajlított könyökkel, BAL kézzel vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Most tartsa a telefont behajlított könyökkel, JOBB kézzel vállmagasságban."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Tartsa a telefont behajlított könyökkel %ld másodpercig."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Most a könyökét behajlítva érintse többször az orrához a telefont."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Most tartsa a telefont BAL kézzel, a könyökét behajlítva, és érintse többször az orrához a telefont."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Most tartsa a telefont JOBB kézzel, a könyökét behajlítva, és érintse többször az orrához a telefont."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Érintse többször az orrához a telefont %ld másodpercen keresztül"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Forgassa a felemelt csuklóját (mintha integetne)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Forgassa a felemelt BAL csuklóját a telefonnal a kezében (mintha integetne)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Forgassa a felemelt JOBB csuklóját a telefonnal a kezében (mintha integetne)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Forgassa a felemelt csuklóját %ld másodpercig."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Most tegye át a telefont a BAL kezébe, és folytassa a következő feladattal."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Most tegye át a telefont a JOBB kezébe, és folytassa a következő feladattal."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Folytatás a következő feladattal."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Tevékenység befejezve."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "A rendszer fel fogja kérni %@ végrehajtására, miközben ül a telefonnal az egyik kezében, majd a másik kezében."; +"TREMOR_SKIP_LEFT_HAND" = "A BAL kezemmel nem tudom elvégezni ezt a feladatot."; +"TREMOR_SKIP_RIGHT_HAND" = "A JOBB kezemmel nem tudom elvégezni ezt a feladatot."; +"TREMOR_SKIP_NEITHER" = "Mindkét kézzel el tudom végezni ezt a feladatot."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Összekötési teszt"; +"TRAILMAKING_INTENDED_USE" = "Ez a feladat a vizuális figyelmét és feladatváltási képességét értékeli ki, amelynek során leméri, mennyi időre van szüksége ahhoz, hogy egy pontokból álló sorozatra koppintson a megfelelő sorrendben."; +"TRAILMAKING_INTENDED_USE2_A" = "A visszaszámlálás után koppintson felváltva a számokat és betűket jelölő pontokra a megfelelő sorrendben. Először koppintson az 1-re, majd a 2-re, a 3-ra, a 4-re stb., amíg eléri a 7-es számot."; +"TRAILMAKING_INTENDED_USE2_B" = "A visszaszámlálás után koppintson felváltva a számokat és betűket jelölő pontokra a megfelelő sorrendben. Először koppintson az 1-re, majd az A-ra, a 2-re, a B-re, a 3-ra, a C-re és így tovább, amíg eléri a 7-es számot."; +"TRAILMAKING_INTRO_TEXT" = "Olyan gyorsan végezze el hibátlanul, ahogy csak tudja. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Beszédfelismerés"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Ez a tevékenység rögzíti a beszédhangját az eszköz alján található mikrofon használatával, és szöveggé alakítja."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "A kezdéshez koppintson a Kezdés elemre."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "A beszéd előtt nyomja meg a gombot a felvétel megkezdéséhez."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Felvétel indítása"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Felvétel leállítása"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Átirat szerkesztése"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "A szöveges átirat szerkesztésével korrigálhatja az esetlegesen félreértett beszédet."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Az átírt szöveg itt fog megjelenni."; +"SPEECH_RECOGNITION_FAILED" = "A beszédfelismerés sikertelen volt."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Nem sikerült elindítani a beszédfelismerést."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Hang lejátszása"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Hang leállítása"; +"SPEECH_IN_NOISE_TITLE" = "Beszéd zajban"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Ez a tevékenység megméri a beszédértést zajos környezetben."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "A vizsgálat részeként:\n\nHallani fog egy mondatot.\n\nIsmételje meg érthetően a hallott szöveget, vagy lépjen tovább, és írja be a billentyűzettel, amit hallott. \n\nHa megismétli, amit hallott, akkor lehetősége lesz módosítani a beszédfelismerési motor által létrehozott szöveges átiratot."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Hangerő kalibrálása"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Koppintson a „Hang lejátszása” gombra, állítsa kellemes szintre a hangerőt, majd koppintson a „Hang leállítása” gombra a folytatáshoz."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Hallgatás"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Egy véletlenszerű jel-zaj arányú (SNR) háttérzajjal kevert mondat lesz egyetlen alkalommal lejátszva."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Beszéd"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Ismételje meg, amit hallott."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "A fájl nem hozható létre"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nem sikerült elég naplófájlt eltávolítani a küszöb eléréséhez"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Hiba történt az attribútum beállításakor"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "A fájl nincs töröltként megjelölve (nincs feltöltöttként megjelölve)"; +"ERROR_DATALOGGER_MULTIPLE" = "Több hiba történt a naplók eltávolításakor"; +"ERROR_RECORDER_NO_DATA" = "Nem található összegyűjtött adat."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Nincs megadva kimeneti könyvtár"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL-mérő"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Ez a tevékenység megméri a környezeti hangnyomást. Ha a zaj szintje túl magas, nem fogja tudni folytatni. Kérjük, menjen csendesebb helyre a feladat befejezéséhez, vagy ismételje meg később a tevékenységet."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Számítás"; +"ENVIRONMENTSPL_THRESHOLD" = "Küszöb: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Elfogadható mértékű háttérzaj"; +"ENVIRONMENTSPL_NOISE" = "Túl erős háttérzaj"; +"ENVIRONMENTSPL_TITLE_2" = "Keressen egy csendes helyet"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "A pontos eredményhez ezt a vizsgálatot halk környezetben kell elvégezni."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Feladat elkezdése"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Nincs adat"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Értékbeállítás a csúszka mozgatásával"; +"SLIDER_I_DONT_KNOW" = "Nem tudom"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Oldal"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Vissza"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDF-bélyegkép megjelenítése"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDF-bélyegképek elrejtése"; +"AX_BUTTON_ANNOTATE" = "Annotáció"; +"AX_BUTTON_SHOW_SEARCH" = "Keresési sáv megjelenítése"; +"AX_BUTTON_HIDE_SEARCH" = "Keresési sáv elrejtése"; +"AX_BUTTON_SHARE" = "Megosztás"; + + +"AX_COMPLETION_ILLUSTRATION" = "Egy kék körben lévő pipa, amelynek jelentése siker"; + +"AX_SIGNVIEW_LABEL" = "Külön aláírásmező"; +"AX_SIGNVIEW_HINT" = "Érintse meg a képernyőt, és mozgassa az ujját az aláíráshoz"; +"AX_SIGNVIEW_SIGNED" = "Aláírva"; +"AX_SIGNVIEW_UNSIGNED" = "Aláírás nélküli"; + +"AX_SELECTED" = "Kiválasztva"; +"AX_UNSELECTED" = "Nincs kijelölve"; +"AX_SELECT_ALL_THAT_APPLY" = "JELÖLJE MEG AZ ÖSSZES VONATKOZÓ ELEMET"; + +"AX_SLIDER_LABEL" = "Válaszcsúszka. Tartomány: %@ - %@"; +"AX_UNLABELED_IMAGE" = "Címke nélküli kép"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Feladat megkezdése"; + +"AX.MEMORY.TILE.ACTIVE" = "aktív"; +"AX.MEMORY.TILE.CORRECT" = "helyes"; +"AX.MEMORY.TILE.INCORRECT" = "helytelen"; +"AX.MEMORY.TILE.QUIESCENT" = "nyugodt"; +"AX.MEMORY.TILE.LABEL" = "Memóriajáték címe"; + +"AX_IMAGE_CAPTURE_LABEL" = "Előnézet rögzítése"; +"AX_IMAGE_CAPTURED_LABEL" = "Készített kép"; + +"AX_VIDEO_CAPTURE_LABEL" = "Videorögzítés előnézete"; +"AX_VIDEO_CAPTURE_COMPLETE" = "A videó rögzítése befejeződött"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Nem helyezhető %@ méretű korong %@ méretű korongra"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cél"; +"AX_TOWER_OF_HANOI_TOWER" = "Torony"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Koppintson duplán a korong elhelyezéséhez"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Koppintson duplán a legfelső korong kijelöléséhez"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "A következő méretű korongokat tárolja: %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Üres"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Billentyűzet bezárása"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Tartomány ettől: %@ eddig: %@"; +"AX_GRAPH_STACK_PREFIX" = "Halom a következőkből:"; +"AX_GRAPH_AND_SEPARATOR" = " és "; +"AX_GRAPH_POINT_%@" = "Pont: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Beszéd hullámformája"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Amikor elkezdődik a felvétel, aktiválja másodszor a felvétel leállításához."; + +"AX_AUDIO_BAR_GRAPH" = "Hangsávdiagram"; + +"AX_AMSLER_GRID_LABEL" = "Amsler-rács"; +"AX_AMSLER_GRID_HINT" = "Az ujja vagy egy érintőceruza segítségével jelölje meg közvetlenül a rácsot, vagy legyintsen balra a rácson kívül a befejezéshez."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Koppintható gombok"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Koppintás a bal fülhöz"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktiválja a teszt megkezdéséhez. Ha a teszt elkezdődött, koppintson közvetlenül a gombra, amikor egy hangot hall a bal fülében."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Koppintás a jobb fülhöz"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktiválja a teszt megkezdéséhez. Ha a teszt elkezdődött, koppintson közvetlenül a gombra, amikor egy hangot hall a jobb fülében."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ A VoiceOver használatával tapintással felfedezheti a képernyőt, és megtanulhatja az egyes fülekhez tartozó gombok helyét. Ha a teszt elindul a gombok közvetlenül koppinthatóak lesznek. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Koppintás egy ujjhoz"; +"AX_TAP_BUTTON_2_LABEL" = "Koppintás másik ujjhoz"; +"AX_TAP_BUTTON_HINT" = "Aktiválja, hogy közvetlenül koppinthatóvá tegye a gombokat."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ A VoiceOver használatával tapintással felfedezheti a képernyőt, és megtanulhatja a gombok helyét. Aktiválja bármelyik gombot, hogy közvetlenül koppinthatóvá tegye a gombokat."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "A gombokra immár közvetlenül rá lehet koppintani."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ VoiceOver használata esetén a gombra közvetlenül rá lehet koppintani. A gomb a képernyő közepének közelében lesz."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ VoiceOver használata esetén a gombok a tesztben közvetlenül koppinthatók lesznek."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Nem lehet dekódolni a restoreData paramétert az inicializáláshoz"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..5f5029e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/hu.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d hiba) + other + (%d hiba) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.strings new file mode 100755 index 0000000..7d4454e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Persetujuan"; +"CONSENT_NAME_GIVEN" = "Nama Depan"; +"CONSENT_NAME_FAMILY" = "Nama Belakang"; +"CONSENT_NAME_PLACEHOLDER" = "Diperlukan"; +"CONSENT_REVIEW_TITLE" = "Tinjauan"; +"CONSENT_REVIEW_INSTRUCTION" = "Tinjau formulir di bawah dan ketuk Setuju jika Anda siap melanjutkan."; +"CONSENT_REVIEW_ALERT_TITLE" = "Tinjauan"; +"CONSENT_SIGNATURE_TITLE" = "Tanda Tangan"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Tanda tangani menggunakan jari Anda di kotak di bawah."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Tanda Tangan di Sini"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Halaman %1$ld dari %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Selamat Datang"; +"CONSENT_SECTION_DATA_GATHERING" = "Pengumpulan Data"; +"CONSENT_SECTION_PRIVACY" = "Privasi"; +"CONSENT_SECTION_DATA_USE" = "Penggunaan Data"; +"CONSENT_SECTION_STUDY_SURVEY" = "Survei Kajian"; +"CONSENT_SECTION_STUDY_TASKS" = "Tugas Kajian"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Komitmen Waktu"; +"CONSENT_SECTION_WITHDRAWING" = "Penarikan Diri"; +"CONSENT_LEARN_MORE_TITLE" = "Lebih Lanjut"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Lebih lanjut mengenai cara data dikumpulkan"; +"LEARN_MORE_DATA_USE" = "Lebih lanjut mengenai cara data digunakan"; +"LEARN_MORE_PRIVACY" = "Lebih lanjut mengenai cara privasi dan identitas Anda dilindungi"; +"LEARN_MORE_WELCOME" = "Pelajari lebih lanjut mengenai kajian terlebih dahulu"; +"LEARN_MORE_STUDY_SURVEY" = "Lebih lanjut mengenai survei kajian"; +"LEARN_MORE_TIME_COMMITMENT" = "Lebih lanjut mengenai dampak kajian terhadap waktu Anda"; +"LEARN_MORE_TASKS" = "Lebih lanjut mengenai tugas yang bersangkutan"; +"LEARN_MORE_WITHDRAWING" = "Lebih lanjut mengenai penarikan diri"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Pilihan Berbagi"; +"CONSENT_SHARE_WIDELY_%@" = "Bagikan data saya dengan %@ dan peneliti berkualifikasi di seluruh dunia"; +"CONSENT_SHARE_ONLY_%@" = "Hanya bagikan data saya dengan %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ akan menerima data kajian Anda dari partisipasi Anda dalam kajian ini.\n\nBerbagi data kajian yang dikodekan secara lebih luas (tanpa informasi seperti nama Anda) dapat bermanfaat bagi penelitian ini dan mendatang."; +"LEARN_MORE_CONSENT_SHARING" = "Lebih lanjut mengenai berbagi data"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nama Tercetak"; +"CONSENT_DOC_LINE_SIGNATURE" = "Tanda Tangan"; +"CONSENT_DOC_LINE_DATE" = "Tanggal"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ dari %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pertanyaan %1$@ dari %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Dilewati"; +"REVIEW_EDIT_ANSWER" = "Edit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Nilai tidak sah"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ melebihi nilai maksimum yang diizinkan (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ kurang dari nilai minimum yang diizinkan (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ bukan nilai yang sah."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Alamat email tidak sah: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Masukkan alamat"; +"LOCATION_ERROR_TITLE" = "Tidak Dapat Menemukan Alamat yang Ditetapkan"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Tidak dapat menemukan lokasi Anda saat ini. Ketikkan alamat atau pindah ke lokasi dengan sinyal GPS yang lebih baik jika memungkinkan."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Akses ke layanan lokasi telah ditolak. Izinkan app ini untuk menggunakan layanan lokasi melalui Pengaturan."; +"LOCATION_ERROR_GEOCODE" = "Tidak dapat menemukan hasil untuk alamat yang dimasukkan. Pastikan bahwa alamat sah."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Anda tidak terhubung ke internet atau telah melampaui jumlah maksimum permintaan pencarian alamat. Jika Anda tidak terhubung ke internet, nyalakan Wi-Fi untuk menjawab pertanyaan ini, lewati pertanyaan ini jika tombol lewati tersedia, atau kembali ke survey setelah Anda terhubung ke internet. Jika tidak, coba lagi dalam beberapa menit."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Konten teks melebihi panjang maksimum: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera tidak tersedia dalam layar terpisah."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Kata Sandi"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Masukkan kata sandi"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Konfirmasi"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Masukkan kata sandi lagi"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Kata sandi tidak cocok."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informasi Tambahan"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Jenis Kelamin"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Pilih jenis kelamin"; +"DOB_FORM_ITEM_TITLE" = "Tanggal Lahir"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Pilih tanggal"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Nomor Telepon"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verifikasi"; +"VERIFICATION_STEP_TITLE" = "Verifikasi Email Anda"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Ketuk tautan di bawah jika Anda tidak menerima email verifikasi dan ingin email dikirimkan lagi."; +"RESEND_EMAIL_BUTTON_TITLE" = "Kirim Ulang Email Verifikasi"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Masuk"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Lupa kata sandi?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Masukkan kode sandi"; +"PASSCODE_CONFIRM_MESSAGE" = "Konfirmasi kode sandi"; +"PASSCODE_SAVED_MESSAGE" = "Kode sandi disimpan"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kode sandi disahkan"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Masukkan kode sandi Anda yang lama"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Masukkan kode sandi Anda yang baru"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Konfirmasi kode sandi baru Anda"; +"PASSCODE_INVALID_ALERT_TITLE" = "Kode Sandi Salah"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Kode sandi tidak cocok. Coba lagi."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Sahkan dengan Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Kesalahan Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Hanya karakter numerik yang diizinkan."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indikator kemajuan entri kode sandi"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ dari %@ digit dimasukkan"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Lupa Kode Sandi?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Tidak dapat menambah item Rantai Kunci."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Tidak dapat memperbarui item Rantai Kunci."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Tidak dapat menghapus item Rantai Kunci."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Tidak dapat menemukan item Rantai Kunci."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipe I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipe II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipe III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipe IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipe V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipe VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Wanita"; +"GENDER_MALE" = "Pria"; +"GENDER_OTHER" = "Lainnya"; + +/* Boolean answer strings */ +"BOOL_NO" = "Tidak"; +"BOOL_YES" = "Ya"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "kaki"; +"MEASURING_UNIT_IN" = "inci"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "kiri"; +"LIMB_RIGHT" = "kanan"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Ketuk untuk menjawab"; +"NULL_ANSWER" = "Pilih jawaban"; +"PLACEHOLDER_IMAGE_CHOICES" = "Ketuk untuk memilih"; +"PLACEHOLDER_LONG_TEXT" = "Ketuk untuk menulis"; + +/* Button titles */ +"BUTTON_AGREE" = "Setuju"; +"BUTTON_CANCEL" = "Batalkan"; +"BUTTON_OK" = "OKE"; +"BUTTON_CLEAR" = "Bersihkan"; +"BUTTON_CLEAR_SIGNATURE" = "Bersihkan Tanda Tangan"; +"BUTTON_APPLY" = "Terapkan"; +"BUTTON_DISAGREE" = "Tidak Setuju"; +"BUTTON_DONE" = "Selesai"; +"BUTTON_GET_STARTED" = "Mulai"; +"BUTTON_LEARN_MORE" = "Lebih lanjut"; +"BUTTON_NEXT" = "Berikutnya"; +"BUTTON_SKIP" = "Lewati"; +"BUTTON_SKIP_QUESTION" = "Lewati pertanyaan ini"; +"BUTTON_START_TIMER" = "Mulai Timer"; +"BUTTON_OPTION_SAVE" = "Simpan untuk Nanti"; +"BUTTON_OPTION_DISCARD" = "Hapus Hasil"; +"BUTTON_OPTION_STOP_TASK" = "Akhiri Tugas"; +"BUTTON_SAVE" = "Simpan"; +"BUTTON_CLEAR_ANSWER" = "Bersihkan jawaban"; +"BUTTON_READ_ONLY_MODE" = "Jawaban ini tidak dapat dimodifikasi."; +"BUTTON_COPYRIGHT" = "Hak Cipta"; +"BUTTON_CLOSE" = "Tutup"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Memulai aktivitas dalam"; +"TASK_COMPLETE_TITLE" = "Aktivitas Selesai"; +"TASK_COMPLETE_TEXT" = "Data Anda akan dianalisis dan Anda akan diberi tahu setelah hasil Anda siap."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Tersisa %@."; +"TOUCH_ANYWHERE_LABEL" = "Sentuh di mana saja untuk melanjutkan"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Ambil Gambar"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Ambil Ulang Gambar"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Kamera tidak ditemukan. Langkah ini tidak dapat diselesaikan."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Untuk menyelesaikan langkah ini, izinkan app ini untuk mengakses kamera di Pengaturan."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Tidak ada direktori output yang ditentukan untuk gambar yang diambil."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Gambar yang diambil tidak dapat disimpan."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Mulai Merekam"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Berhenti Merekam"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Ambil Ulang Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kebugaran"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Jarak (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Detak Jantung (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Duduk dengan nyaman selama %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Jalan secepat mungkin selama %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Aktivitas ini memonitor detak jantung Anda dan mengukur seberapa jauh Anda dapat berjalan dalam %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Berjalan kaki di luar ruangan dengan laju secepat mungkin selama %1$@. Setelah selesai, duduk dan istirahat dengan nyaman selama %2$@. Untuk memulai, ketuk Mulai."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gaya dan Keseimbangan"; +"WALK_INTRO_TEXT" = "Aktivitas ini mengukur gaya dan keseimbangan Anda saat Anda berjalan dan berdiri. Jangan lanjutkan jika Anda tidak dapat berjalan dengan aman tanpa bantuan."; +"WALK_INTRO_2_TEXT_%ld" = "Temukan tempat yang memungkinkan Anda untuk berjalan kaki dengan aman tanpa bantuan sejauh sekitar %ld langkah dalam garis lurus."; +"WALK_INTRO_2_DETAIL" = "Simpan perangkat Anda di saku atau tas dan ikuti instruksi audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Sekarang berdiri selama %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Berdiri selama %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Putar balik, dan kembali ke tempat Anda memulai."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Berjalan kaki hingga %ld langkah dalam garis lurus."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Cari tempat yang memungkinkan Anda untuk berjalan maju mundur dalam garis lurus dengan aman. Coba terus berjalan dengan memutar balik di ujung jalur Anda, seakan-akan Anda memutari kerucut lalu lintas.\n\nBerikutnya, Anda akan diinstruksikan untuk memutar dalam lingkaran penuh, kemudian diam berdiri dengan tangan di samping Anda dan kaki Anda direnggangkan selebar bahu."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Ketuk Mulai setelah Anda siap memulai.\nKemudian, letakkan perangkat Anda di saku atau tas dan ikuti instruksi audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Jalan bolak-balik di jalur lurus selama %@. Jalan dengan normal."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Berputar dalam lingkaran penuh lalu tetap berdiri selama %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Anda telah menyelesaikan aktivitas."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Kecepatan Mengetuk"; +"TAPPING_TASK_TITLE_RIGHT" = "Tangan Kanan"; +"TAPPING_TASK_TITLE_LEFT" = "Tangan Kiri"; +"TAPPING_INTRO_TEXT" = "Aktivitas ini mengukur kecepatan mengetuk Anda."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Letakkan perangkat Anda di permukaan datar."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Gunakan dua jari pada tangan yang sama untuk mengetuk tombol di layar secara bergantian."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Gunakan dua jari pada tangan kanan Anda untuk mengetuk tombol di layar secara bergantian."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Gunakan dua jari pada tangan kiri Anda untuk mengetuk tombol di layar secara bergantian."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Sekarang ulangi tes yang sama menggunakan tangan kanan."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Sekarang ulangi tes yang sama menggunakan tangan kiri."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Ketuk dengan satu jari, lalu jari lainnya. Sebisa mungkin, coba atur ketukan Anda agar seimbang. Terus mengetuk selama %@."; +"TAPPING_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Ketuk Berikutnya untuk memulai."; +"TAP_BUTTON_TITLE" = "Ketuk"; +"TOTAL_TAPS_LABEL" = "Total Ketukan"; +"TAPPING_INSTRUCTION" = "Ketuk tombol sekonsisten mungkin menggunakan dua jari."; +"TAPPING_INSTRUCTION_RIGHT" = "Ketuk tombol menggunakan tangan KANAN Anda."; +"TAPPING_INSTRUCTION_LEFT" = "Ketuk tombol menggunakan tangan KIRI Anda."; +"TAPPING_SKIP_TITLE" = "Lewati tangan Ini"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Grid Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Aktivitas ini membantu mendeteksi masalah pada penglihatan pengguna."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Pegang perangkat sejauh 30 cm dari wajah Anda dan sejajar dengan mata selama tes."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Tutup %@ Anda dan lihat ke arah titik di pusat grid persegi.\n\nDengan menggunakan jari atau stylus Anda, tandai semua distorsi yang Anda lihat seperti garis kabur atau bergelombang.\n\nSetelah selesai, gesek ke kiri di mana pun di luar grid."; +"AMSLER_GRID_LEFT_EYE" = "Mata Kiri"; +"AMSLER_GRID_RIGHT_EYE" = "Mata Kanan"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Suara"; +"AUDIO_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"AUDIO_INSTRUCTION" = "Katakan “Aaaaah” di mikrofon selama mungkin."; +"AUDIO_INTRO_TEXT" = "Tarik nafas dalam-dalam dan katakan “Aaaaah” ke mikrofon selama Anda bisa. Pertahankan volume suara sehingga bar audio tetap berwarna biru."; +"AUDIO_INTENDED_USE" = "Aktivitas ini mengevaluasi suara Anda dengan merekamnya menggunakan mikrofon di bagian bawah perangkat Anda."; +"AUDIO_TOO_LOUD_LABEL" = "Terlalu Keras"; +"AUDIO_GENERIC_ERROR_LABEL" = "Tidak dapat merekam audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Harap tunggu saat kami memeriksa level kebisingan latar belakang."; +"AUDIO_TOO_LOUD_MESSAGE" = "Level kebisingan di sekitar terlalu kencang untuk merekam suara Anda. Pindah ke tempat lain yang lebih hening dan coba lagi."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Ketuk Berikutnya saat sudah siap."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometri Nada"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Aktivitas ini mengukur kemampuan Anda untuk mendengar bunyi yang berbeda."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Sebelum memulai, sambungkan dan kenakan headphone Anda.\n\nBunyi akan terdengar sangat halus dan berbeda dengan nada peringatan biasa.  Bunyi akan terdengar lembut pada awalnya, namun volumenya perlahan-lahan akan bertambah.  Perhatikan dan ketuk tombol kiri atau kanan untuk menunjukkan di telinga mana Anda mendengarnya."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Seharusnya Anda telah mendengar nada sekarang. Sesuaikan volume menggunakan kontrol di sisi perangkat Anda.\n\nKetuk tombol mana pun setelah Anda siap memulai."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Setiap kali Anda mulai mendengar bunyi, ketuk tombol kiri atau kanan untuk menunjukkan di telinga mana Anda mendengar bunyi tersebut."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Telinga Kiri"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Telinga Kanan"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Kiri"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Kanan"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometri Nada"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Ketuk saat mendengar nada."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Nada & Volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Anda akan mendengar rangkaian nada."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Saat mendengar nada, ketuk tombol."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Untuk tes ini, volume akan diatur ke 50 persen."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Tes ini memerlukan waktu sekitar 10 menit."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Nyalakan Jangan Ganggu untuk menghindari gangguan."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Nada akan diputar di telinga kanan Anda terlebih dahulu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Sekarang nada akan diputar di telinga kiri Anda."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Aktivitas ini mengidentifikasi level ambang pendengaran seseorang dalam skala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Pastikan volume perangkat diatur ke level maksimum.\n\nSelama tugas ini, nada halus akan diputar di telinga kiri atau kanan.\n\nDengarkan dengan seksama dan ketuk tombol setiap kali Anda mendengar nada."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Tes ini mengidentifikasi level bunyi yang diperlukan agar Anda dapat mendengarnya."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Daftar pertanyaan orientasi."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Pilih preferensi Anda untuk 'telinga yang lebih baik', jika ada"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "kiri"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "kanan"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "tidak ada preferensi"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Tes Dibatalkan"; +"dBHL_ALERT_TITLE_START_OVER" = "Mulai Lagi"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Batalkan Tes"; +"dBHL_ALERT_TEXT" = "Hubungkan ulang AirPods atau EarPods Anda untuk mengikuti tes ini."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Selesai"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Headphone"; +"HEADPHONES_UNKNOWN" = "Tidak Diketahui"; +"HEADPHONES_NONE" = "Tidak Ada"; +"CONNECTED" = "Terhubung"; +"NOT_CONNECTED" = "Tidak Terhubung"; +"HEADPHONE_CONNECTED_%@" = "Terhubung - %@"; +"HEADPHONE_DETECT_TITLE" = "Hubungkan Headphone Anda"; +"HEADPHONE_DETECT_TEXT" = "Tes ini memerlukan Apple AirPods atau Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memori Spasial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Aktivitas ini mengukur memori spasial jangka pendek dengan meminta Anda untuk mengulangi urutan menyalanya %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "bunga"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "bunga"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Beberapa %@ akan menyala satu per satu. Ketuk %@ tersebut sesuai urutan menyalanya."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Beberapa %@ akan menyala satu per satu. Ketuk %@ tersebut berkebalikan dengan urutan menyalanya."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Untuk memulai, ketuk Mulai, lalu perhatikan dengan saksama."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Skor"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Lihat %@ menyala"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Ketuk %@ sesuai urutan menyalanya"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Ketuk %@ dalam urutan terbalik"; +"MEMORY_GAME_COMPLETE_TITLE" = "Urutan Selesai"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Untuk melanjutkan, ketuk Berikutnya"; +"MEMORY_GAME_FAILED_TITLE" = "Coba Lagi"; +"MEMORY_GAME_FAILED_MESSAGE" = "Sebelumnya Anda tidak berhasil. Ketuk Berikutnya untuk melanjutkan."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Waktu Habis"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Anda kehabisan waktu.\nKetuk Berikutnya untuk melanjutkan."; +"MEMORY_GAME_COMPLETE" = "Permainan Selesai"; +"MEMORY_GAME_PAUSED_TITLE" = "Dijeda"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Untuk melanjutkan, ketuk Berikutnya"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Aktivitas ingatan dikembangkan dengan bantuan dari Katherine Possin, PhD dan Joel Kramer, PhD dari University of California, San Fransisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Waktu Reaksi"; +"REACTION_TIME_TASK_INTENDED_USE" = "Aktivitas ini mengevaluasi waktu yang Anda butuhkan untuk merespons isyarat visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Goyangkan perangkat ke arah mana pun segera setelah titik biru muncul di layar. Anda akan diminta untuk melakukannya sebanyak %D kali."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Percobaan %@ dari %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Goyangkan perangkat dengan cepat saat lingkaran biru muncul"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Setiap kali suatu kata muncul, pilih huruf pertama dari nama WARNA yang ditampilkan."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Setelah Anda siap untuk memulai aktivitas Stroop, ketuk Mulai."; +"STROOP_TASK_STEP_TEXT" = "Pilih huruf pertama dari nama WARNA yang ditampilkan."; +"STROOP_COLOR_RED" = "MERAH"; +"STROOP_COLOR_GREEN" = "HIJAU"; +"STROOP_COLOR_BLUE" = "BIRU"; +"STROOP_COLOR_YELLOW" = "KUNING"; +"STROOP_COLOR_RED_INITIAL" = "M"; +"STROOP_COLOR_GREEN_INITIAL" = "H"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "K"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Menara Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Aktivitas ini mengevaluasi kemampuan Anda dalam menyelesaikan teka-teki."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Pindahkan seluruh tumpukan ke platform yang disorot, semakin sedikit gerakan maka semakin baik."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Selesaikan Teka-Teki"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Jumlah Gerakan: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Saya tidak dapat menyelesaikan teka-teki ini"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Cakupan Gerakan"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption harus berupa kiri atau kanan"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Jangkauan Gerakan Lutut Kiri"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Jangkauan Gerakan Lutut Kanan"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aktivitas ini mengukur seberapa jauh Anda dapat meregangkan lutut kiri Anda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aktivitas ini mengukur seberapa jauh Anda dapat meregangkan lutut kanan Anda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Duduk di tepi kursi. Saat Anda memulai, taruh perangkat di lutut kiri Anda untuk pengukuran. Nyalakan bunyi pada perangkat sehingga Anda dapat mendengar instruksi."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Duduk di tepi kursi. Saat Anda memulai, taruh perangkat di lutut kanan Anda untuk pengukuran. Nyalakan bunyi pada perangkat sehingga Anda dapat mendengar instruksi."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Letakkan perangkat di lutut kiri Anda dengan layar menghadap keluar, sebagaimana yang terlihat di gambar."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Letakkan perangkat di lutut kanan Anda dengan layar menghadap keluar, sebagaimana yang terlihat di gambar."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Setelah siap, ketuk layar untuk memulai dan regangkan lutut kiri Anda sejauh mungkin. Kembali ke posisi semula dan ketuk lagi setelah Anda selesai."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Setelah siap, ketuk layar untuk memulai dan regangkan lutut kanan Anda sejauh mungkin. Kembali ke posisi semula dan ketuk lagi setelah Anda selesai."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Letakkan perangkat di lutut kiri Anda. Ketuk layar dan regangkan lutut kiri Anda sejauh mungkin."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Letakkan perangkat di lutut kanan Anda. Ketuk layar dan regangkan lutut kanan Anda sejauh mungkin."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Setelah selesai, kembalikan lutut kiri Anda ke posisi semula, lalu ketuk di mana pun."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Setelah selesai, kembalikan lutut kanan Anda ke posisi semula, lalu ketuk di mana pun."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Jangkauan Gerakan Bahu Kiri"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Jangkauan Gerakan Bahu Kanan"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aktivitas ini mengukur seberapa jauh Anda dapat meregangkan bahu kiri Anda."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aktivitas ini mengukur seberapa jauh Anda dapat meregangkan bahu kanan Anda."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Saat Anda memulai, taruh perangkat di bahu kiri Anda untuk pengukuran. Nyalakan bunyi pada perangkat sehingga Anda dapat mendengar instruksi."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Saat Anda memulai, taruh perangkat di bahu kanan Anda untuk pengukuran. Nyalakan bunyi pada perangkat sehingga Anda dapat mendengar instruksi."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Letakkan perangkat di bahu kiri Anda dengan layar menghadap keluar, sebagaimana yang terlihat di gambar."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Letakkan perangkat di bahu kanan Anda dengan layar menghadap keluar, sebagaimana yang terlihat di gambar."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Setelah siap, ketuk layar untuk memulai dan angkat lengan kiri Anda sejauh mungkin. Kembali ke posisi semula dan ketuk lagi setelah Anda selesai."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Setelah siap, ketuk layar untuk memulai dan angkat lengan kanan Anda sejauh mungkin. Kembali ke posisi semula dan ketuk lagi setelah Anda selesai."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Letakkan perangkat di bahu kiri Anda. Ketuk layar dan angkat lengan kiri Anda ke depan sejauh mungkin."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Letakkan perangkat di bahu kanan Anda. Ketuk layar dan angkat lengan kanan Anda ke depan sejauh mungkin."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Setelah selesai, kembalikan lengan kiri Anda ke posisi semula, lalu ketuk di mana pun."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Setelah selesai, kembalikan lengan kanan Anda ke posisi semula, lalu ketuk di mana pun."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Berjalan Kaki dibatasi Waktu"; +"TIMED_WALK_INTRO_DETAIL" = "Aktivitas ini mengukur fungsi ekstrem rendah Anda."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Cari tempat (usahakan di luar ruangan) yang memungkinkan Anda untuk berjalan lurus sekitar selama %@ secepat mungkin dengan aman. Jangan kurangi kecepatan hingga Anda melewat garis akhir."; +"TIMED_WALK_INTRO_2_DETAIL" = "Ketuk Berikutnya untuk memulai."; +"TIMED_WALK_FORM_TITLE" = "Perangkat bantuan"; +"TIMED_WALK_FORM_TEXT" = "Gunakan perangkat bantuan yang sama untuk tiap pengujian."; +"TIMED_WALK_QUESTION_TEXT" = "Apakah Anda mengenakan ortosis gelang kaki?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Apakah Anda menggunakan perangkat bantuan?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Ketuk di sini untuk memilih jawaban."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Tidak"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Tongkat Unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Kruk Unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Tongkat Bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Kruk Bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Walker/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Berjalan kaki hingga %@ dalam garis lurus."; +"TIMED_WALK_INSTRUCTION_TURN" = "Putar balik."; +"TIMED_WALK_INSTRUCTION_2" = "Kembali ke tempat Anda memulai."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Ketuk Berikutnya setelah selesai."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Pengujian Paced Auditory Serial Addition mengukur kecepatan pemrosesan informasi dan kemampuan menghitung auditori Anda."; +"PVSAT_INTRO_TEXT" = "Pengujian Paced Visual Serial Addition mengukur kecepatan pemrosesan informasi dan kemampuan menghitung visual Anda."; +"PAVSAT_INTRO_TEXT" = "Pengujian Paced Auditory dan Visual Serial Addition mengukur kecepatan pemrosesan informasi dan kemampuan menghitung auditori dan visual Anda."; +"PSAT_INTRO_TEXT_2_%@" = "Digit tunggal dimunculkan setiap %@.\nAnda harus menambahkan setiap digit baru ke digit sebelumnya.\nIngat, jangan menghitung jumlah total, tapi hanya jumlah dua angka terakhir."; +"PSAT_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"PSAT_INITIAL_INSTRUCTION" = "Ingat digit pertama ini."; +"PSAT_INSTRUCTION" = "Tambahkan digit baru ini ke digit sebelumnya."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Uji Sumbat %@ Lubang"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Aktivitas ini mengukur fungsi bagian teratas dengan meminta Anda untuk meletakkan sumbat di lubang. Anda akan diminta untuk melakukan ini %@ kali."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Tangan kiri dan kanan Anda akan dites.\nAnda harus mengambil pasak secepat mungkin, memasukkannya ke lubang, dan, setelah selesai %@ kali, mencabutnya lagi %@ kali."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Tangan kanan dan kiri Anda akan dites.\nAnda harus mengambil pasak secepat mungkin, memasukkannya ke lubang, dan, setelah selesai %@ kali, mencabutnya lagi %@ kali."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Letakkan sumbat di lubang menggunakan tangan kiri Anda."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Letakkan sumbat di lubang menggunakan tangan kanan Anda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Letakkan sumbat di belakang garis menggunakan tangan kiri Anda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Letakkan sumbat di belakang garis menggunakan tangan kanan Anda."; +"HOLE_PEG_TEST_TEXT" = "Ambil sumbat dengan dua jari."; +"HOLE_PEG_TEST_TEXT_2" = "Angkat jari untuk menjatuhkan sumbat."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Aktivitas Tremor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Aktivitas ini mengukur tremor tangan Anda dalam berbagai posisi. Cari tempat yang dapat Anda gunakan untuk duduk dengan nyaman selama durasi aktivitas ini."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Genggam telepon di tangan yang terkena dampak lebih besar seperti yang ditampilkan dalam gambar di bawah."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Genggam telepon Anda di tangan KANAN seperti yang ditampilkan dalam gambar di bawah."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Genggam telepon Anda di tangan KIRI seperti yang ditampilkan dalam gambar di bawah."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Anda akan diminta untuk melakukan %@ saat duduk dengan telepon di tangan Anda."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "sebuah tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dua tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tiga tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "empat tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "lima tugas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Ketuk berikutnya untuk melanjutkan."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Bersiap untuk menggenggam telepon di pangkuan."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Bersiap untuk menggenggam telepon di pangkuan dengan tangan KIRI."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Bersiap untuk menggenggam telepon di pangkuan dengan tangan KANAN."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Terus genggam telepon Anda di pangkuan selama %ld detik."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Sekarang genggam telepon Anda dengan tangan terentang setinggi bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Sekarang genggam telepon Anda dengan tangan KIRI terentang setinggi bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Sekarang genggam telepon Anda dengan tangan KANAN terentang setinggi bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Terus genggam telepon Anda dengan tangan terentang selama %ld detik."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Sekarang genggam telepon Anda setinggi bahu dengan siku ditekuk."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Sekarang genggam telepon Anda dengan tangan KIRI setinggi bahu dengan siku ditekuk."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Sekarang genggam telepon Anda dengan tangan KANAN setinggi bahu dengan siku ditekuk."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Terus genggam telepon dengan siku ditekuk selama %ld detik"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Sekarang siku tetap ditekuk, sentuhkan telepon ke hidung Anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Sekarang siku tetap ditekuk dengan telepon di tangan KIRI, sentuhkan telepon ke hidung Anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Sekarang siku tetap ditekuk dengan telepon di tangan KANAN, sentuhkan telepon ke hidung Anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Terus sentuhkan telepon ke hidung Anda selama %ld detik"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Bersiap untuk melakukan lambaian tangan ratu (melambai dengan memutar pergelangan tangan)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Bersiap untuk melakukan lambaian tangan ratu dengan telepon di tangan KIRI Anda (melambai dengan memutar pergelangan tangan)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Bersiap untuk melakukan lambaian tangan ratu dengan telepon di tangan KANAN Anda (melambai dengan memutar pergelangan tangan)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Terus lakukan lambaian tangan ratu selama %ld detik."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Sekarang pindahkan telepon ke tangan KIRI dan lanjutkan ke tugas berikutnya."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Sekarang pindahkan telepon ke tangan KANAN dan lanjutkan ke tugas berikutnya."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Lanjutkan ke tugas berikutnya."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivitas selesai."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Anda akan diminta untuk melakukan %@ saat duduk dengan telepon di satu tangan lebih dahulu, lalu melakukan lagi dengan tangan lainnya."; +"TREMOR_SKIP_LEFT_HAND" = "Saya tidak dapat melakukan aktivitas ini dengan tangan KIRI."; +"TREMOR_SKIP_RIGHT_HAND" = "Saya tidak dapat melakukan aktivitas ini dengan tangan KANAN."; +"TREMOR_SKIP_NEITHER" = "Saya dapat melakukan aktivitas ini dengan kedua tangan."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Tes Membuat Jejak"; +"TRAILMAKING_INTENDED_USE" = "Aktivitas ini mengevaluasi perhatian visual dan peralihan tugas Anda dengan merekam waktu yang diperlukan untuk mengetuk rangkaian lingkaran sesuai urutan."; +"TRAILMAKING_INTENDED_USE2_A" = "Setelah hitungan mundur, ketuk lingkaran dengan urutan selang-seling antara angka dan huruf. Mulai dengan mengetuk angka pertama '1' diikuti dengan angka '2' – '3' – '4'… hingga Anda mencapai angka '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "Setelah hitungan mundur, ketuk lingkaran dengan urutan selang-seling antara angka dan huruf. Mulai dengan mengetuk angka pertama '1' diikuti dengan mengetuk huruf 'A', lalu '2' – 'B' – '3' – 'C'… hingga Anda mencapai angka '7'."; +"TRAILMAKING_INTRO_TEXT" = "Lakukan ini secepat mungkin tanpa melakukan kesalahan. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Pengenalan Ucapan"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Aktivitas ini merekam ucapan Anda dengan mikrofon di bagian bawah perangkat, dan menerjemahkannya ke teks."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Ketuk Mulai untuk memulai."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Tekan tombol untuk memulai rekaman sebelum bicara."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Mulai Merekam"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Berhenti Merekam"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edit Transkrip"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edit teks transkrip untuk mengoreksi misinterpretasi ucapan."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Transkripsi Anda akan muncul di sini."; +"SPEECH_RECOGNITION_FAILED" = "Pengenalan ucapan gagal."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Gagal memulai pengenalan ucapan."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Putar Audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Hentikan Audio"; +"SPEECH_IN_NOISE_TITLE" = "Ucapan dalam Kebisingan"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Aktivitas ini mengukur seberapa baik ucapan dapat dipahami saat dihadirkan di lingkungan yang bising."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Sebagai bagian dari tes ini, Anda akan:\n\nMendengarkan suatu kalimat.\n\nUlangi dengan jelas apa yang Anda dengar atau lewati untuk mengetik apa yang Anda dengar menggunakan papan ketik.\n\nJika Anda mengulangi apa yang Anda dengar, Anda akan memiliki pilihan untuk memodifikasi transkrip yang dibuat oleh mesin pengenalan ucapan."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Kalibrasi Volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Ketuk 'Putar Audio', sesuaikan volume Anda hingga terdengar nyaman, lalu ketuk 'Hentikan Audio' untuk melanjutkan."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Dengarkan"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Kalimat yang dicampur dengan kebisingan latar belakang pada Rasio Sinyal terhadap Kebisingan (SNR) yang acak hanya akan diputar sekali."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Bicara"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Ulangi apa yang Anda dengar."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Tidak dapat membuat file"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Tidak dapat menghapus cukup file log untuk mencapai ambang"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Kesalahan saat mengatur atribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "File tidak ditandai sebagai dihapus (tidak ditandai sebagai diunggah)"; +"ERROR_DATALOGGER_MULTIPLE" = "Beberapa kesalahan saat menghapus log"; +"ERROR_RECORDER_NO_DATA" = "Tidak ada data terkumpul yang ditemukan."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Tidak ada direktori output yang ditentukan"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Pengukur SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Aktivitas ini mengukur level tekanan bunyi lingkungan. Jika level kebisingan terlalu tinggi, Anda tidak akan dapat melanjutkan. Pindah ke lokasi yang lebih hening untuk menyelesaikan tugas ini atau mengulangi aktivitas ini di lain waktu."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Menghitung"; +"ENVIRONMENTSPL_THRESHOLD" = "Ambang: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Kebisingan Latar Belakang OKE"; +"ENVIRONMENTSPL_NOISE" = "Suara Latar Belakang Terlalu Bising"; +"ENVIRONMENTSPL_TITLE_2" = "Cari tempat yang sunyi"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Untuk memastikan akurasi, tes ini harus diambil di tempat yang sunyi."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Mulai Tugas"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Tidak Ada Data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Pindahkan penggeser untuk memasukkan nilai"; +"SLIDER_I_DONT_KNOW" = "Saya Tidak Tahu"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Halaman"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Kembali"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Tampilkan Gambar Mini PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Sembunyikan Gambar Mini PDF"; +"AX_BUTTON_ANNOTATE" = "Anotasi"; +"AX_BUTTON_SHOW_SEARCH" = "Tampilkan Bar Pencarian"; +"AX_BUTTON_HIDE_SEARCH" = "Sembunyikan Bar Pencarian"; +"AX_BUTTON_SHARE" = "Bagikan"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustrasi tanda centang dalam lingkaran biru menandakan keberhasilan"; + +"AX_SIGNVIEW_LABEL" = "Bidang tanda tangan yang ditetapkan"; +"AX_SIGNVIEW_HINT" = "Sentuh layar dan gerakkan jari Anda untuk menandatangani"; +"AX_SIGNVIEW_SIGNED" = "Ditandatangani"; +"AX_SIGNVIEW_UNSIGNED" = "Tidak ditandatangani"; + +"AX_SELECTED" = "Dipilih"; +"AX_UNSELECTED" = "Tidak dipilih"; +"AX_SELECT_ALL_THAT_APPLY" = "PILIH SEMUA YANG SESUAI"; + +"AX_SLIDER_LABEL" = "Penggeser respons. Berkisar dari %@ hingga %@"; +"AX_UNLABELED_IMAGE" = "Gambar tidak dilabeli"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Mulai tugas"; + +"AX.MEMORY.TILE.ACTIVE" = "aktif"; +"AX.MEMORY.TILE.CORRECT" = "benar"; +"AX.MEMORY.TILE.INCORRECT" = "salah"; +"AX.MEMORY.TILE.QUIESCENT" = "diam"; +"AX.MEMORY.TILE.LABEL" = "Ubin permainan memori"; + +"AX_IMAGE_CAPTURE_LABEL" = "Pratinjau gambar"; +"AX_IMAGE_CAPTURED_LABEL" = "Gambar terambil"; + +"AX_VIDEO_CAPTURE_LABEL" = "Pratinjau pengambilan video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Pengambilan video selesai"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Tidak dapat meletakkan disk dengan ukuran %@ pada disk dengan ukuran %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Target"; +"AX_TOWER_OF_HANOI_TOWER" = "Menara"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Ketuk dua kali untuk meletakkan disk"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Ketuk dua kali untuk memilih disk teratas"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Memiliki disk dengan ukuran %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Kosong"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Tutup papan ketik"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Berkisar dari %@ hingga %@"; +"AX_GRAPH_STACK_PREFIX" = "Tumpukan terdiri dari"; +"AX_GRAPH_AND_SEPARATOR" = " dan "; +"AX_GRAPH_POINT_%@" = "Poin: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Bentuk Gelombang Ucapan"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Setelah perekaman dimulai, aktifkan sekali lagi untuk menghentikan perekaman."; + +"AX_AUDIO_BAR_GRAPH" = "Grafik Bar Audio"; + +"AX_AMSLER_GRID_LABEL" = "Grid Amsler"; +"AX_AMSLER_GRID_HINT" = "Gunakan jari atau stylus Anda untuk menandai grid secara langsung, atau gesek ke kiri di luar grid untuk menyelesaikan."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tombol yang Dapat Diketuk"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Ketuk untuk Telinga Kiri"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktifkan untuk memulai tes. Setelah tes dimulai, ketuk tombol ini secara langsung setelah Anda mendengar bunyi di telinga kiri Anda."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Ketuk untuk Telinga Kanan"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktifkan untuk memulai tes. Setelah tes dimulai, ketuk tombol ini secara langsung setelah Anda mendengar bunyi di telinga kanan Anda."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Menggunakan VoiceOver, jelajahi layar dengan sentuhan untuk mempelajari lokasi tombol untuk setiap telinga. Setelah tes dimulai, tombol akan dapat diketuk secara langsung. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Ketuk untuk satu jari"; +"AX_TAP_BUTTON_2_LABEL" = "Ketuk untuk jari lainnya"; +"AX_TAP_BUTTON_HINT" = "Aktifkan agar tombol dapat diketuk secara langsung."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Menggunakan VoiceOver, jelajahi layar untuk mempelajari lokasi tombol. Aktifkan tombol mana pun agar dapat diketuk secara langsung."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Tombol sudah dapat diketuk secara langsung."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Menggunakan VoiceOver, tombol akan dapat diketuk secara langsung. Tombol akan berada di dekat bagian pusat layar."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Menggunakan VoiceOver, tombol dalam tes akan dapat diketuk secara langsung."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Tidak dapat memulihkan restoreData untuk memulai"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..3c8170c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/id.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d kesalahan) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.strings new file mode 100755 index 0000000..e5b30b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consenso"; +"CONSENT_NAME_GIVEN" = "Nome"; +"CONSENT_NAME_FAMILY" = "Cognome"; +"CONSENT_NAME_PLACEHOLDER" = "Obbligatorio"; +"CONSENT_REVIEW_TITLE" = "Verifica"; +"CONSENT_REVIEW_INSTRUCTION" = "Leggi il modulo di seguito e scegli Accetto per continuare."; +"CONSENT_REVIEW_ALERT_TITLE" = "Verifica"; +"CONSENT_SIGNATURE_TITLE" = "Firma"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Firma con il dito nel riquadro sottostante."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Firma qui"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Pagina %1$ld di %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Ciao"; +"CONSENT_SECTION_DATA_GATHERING" = "Raccolta dati"; +"CONSENT_SECTION_PRIVACY" = "Privacy"; +"CONSENT_SECTION_DATA_USE" = "Utilizzo dati"; +"CONSENT_SECTION_STUDY_SURVEY" = "Indagine studio scientifico"; +"CONSENT_SECTION_STUDY_TASKS" = "Attività studio"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tempo richiesto"; +"CONSENT_SECTION_WITHDRAWING" = "Non partecipare più allo studio"; +"CONSENT_LEARN_MORE_TITLE" = "Scopri di più"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Scopri di più sulla raccolta di dati"; +"LEARN_MORE_DATA_USE" = "Scopri di più sull'utilizzo dei dati"; +"LEARN_MORE_PRIVACY" = "Scopri di più sulla tutela dei dati relativi alla privacy e alla tua identità"; +"LEARN_MORE_WELCOME" = "Prima di iniziare, scopri di più sullo studio"; +"LEARN_MORE_STUDY_SURVEY" = "Scopri di più sullo studio"; +"LEARN_MORE_TIME_COMMITMENT" = "Scopri di più sull'impatto che lo studio avrà sul tuo tempo"; +"LEARN_MORE_TASKS" = "Scopri di più sulle attività previste"; +"LEARN_MORE_WITHDRAWING" = "Scopri di più sulla possibilità di annullare la partecipazione allo studio"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opzioni di condivisione"; +"CONSENT_SHARE_WIDELY_%@" = "Condividi i miei dati con %@ e con ricercatori qualificati a livello mondiale"; +"CONSENT_SHARE_ONLY_%@" = "Condividi i miei dati solo con %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "Partecipando allo studio, invierai a %@ i dati raccolti.\n\nUna condivisione più ampia di questi dati codificati (senza rivelare informazioni sensibili come il tuo nome) può aiutare questo studio ed eventuali ricerche future."; +"LEARN_MORE_CONSENT_SHARING" = "Scopri di più sulla condivisione dei dati"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nome in stampatello"; +"CONSENT_DOC_LINE_SIGNATURE" = "Firma"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ di %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Domanda %1$@ di %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Ignorata"; +"REVIEW_EDIT_ANSWER" = "Modifica"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valore non valido"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ supera il valore massimo consentito (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ è inferiore al valore minimo consentito (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ non è un valore valido."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Indirizzo e-mail non valido: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Inserisci un indirizzo"; +"LOCATION_ERROR_TITLE" = "Impossibile trovare l'indirizzo specificato"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Impossibile individuare la tua posizione attuale. Inserisci l'indirizzo o spostati in una zona con una migliore copertura GPS."; +"LOCATION_ERROR_MESSAGE_DENIED" = "L'accesso ai servizi di localizzazione è stato negato. Vai in Impostazioni e autorizza l'applicazione a utilizzare i servizi di localizzazione."; +"LOCATION_ERROR_GEOCODE" = "Impossibile trovare risultati per l'indirizzo inserito, assicurati che sia valido."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "La connessione a internet non è attiva oppure hai superato il numero massimo di tentativi di ricerca dell'indirizzo. Se la connessione a internet non è attiva, per rispondere a questa domanda attiva la rete Wi-Fi, ignora il passaggio se è disponibile il pulsante Ignora o torna all'indagine conoscitiva una volta ristabilita la connessione. In alternativa, riprova tra qualche minuto."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Il testo supera la lunghezza massima: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Fotocamera non disponibile in modalità “Vista suddivisa”."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "gmela@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Password"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Inserisci password"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Conferma"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Reinserisci password"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Le password non coincidono."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Ulteriori informazioni"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Giovanni"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Mela"; +"GENDER_FORM_ITEM_TITLE" = "Sesso"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Scegli il sesso"; +"DOB_FORM_ITEM_TITLE" = "Data di nascita"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Scegli una data"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Numero di telefono"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verifica"; +"VERIFICATION_STEP_TITLE" = "Verifica il tuo indirizzo e-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Seleziona il link se non hai ricevuto l'e-mail di conferma e desideri che venga inviata nuovamente."; +"RESEND_EMAIL_BUTTON_TITLE" = "Invia di nuovo e-mail di verifica"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Accedi"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Hai dimenticato la password?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Inserisci codice"; +"PASSCODE_CONFIRM_MESSAGE" = "Conferma codice"; +"PASSCODE_SAVED_MESSAGE" = "Codice salvato"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Codice autenticato"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Inserisci il vecchio codice"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Inserisci il nuovo codice"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Conferma il nuovo codice"; +"PASSCODE_INVALID_ALERT_TITLE" = "Codice non corretto"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "I codici non corrispondono, riprova."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Effettua l'autenticazione con Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Errore Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Sono consentiti solo caratteri numerici."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicatore progresso inserimento codice"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ di %@ cifre inserite"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Hai dimenticato il codice?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Impossibile aggiungere l'elemento del portachiavi."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Impossibile aggiornare l'elemento del portachiavi."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Impossibile eliminare l'elemento del portachiavi."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Impossibile trovare l'elemento del portachiavi."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipo I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipo II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipo III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipo IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipo V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipo VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Donna"; +"GENDER_MALE" = "Uomo"; +"GENDER_OTHER" = "Altro"; + +/* Boolean answer strings */ +"BOOL_NO" = "No"; +"BOOL_YES" = "Sì"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "piedi"; +"MEASURING_UNIT_IN" = "pollici"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "sinistro"; +"LIMB_RIGHT" = "destro"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tocca per rispondere"; +"NULL_ANSWER" = "Seleziona una risposta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tocca per selezionare"; +"PLACEHOLDER_LONG_TEXT" = "Tocca per scrivere"; + +/* Button titles */ +"BUTTON_AGREE" = "Accetto"; +"BUTTON_CANCEL" = "Annulla"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Cancella"; +"BUTTON_CLEAR_SIGNATURE" = "Cancella firma"; +"BUTTON_APPLY" = "Applica"; +"BUTTON_DISAGREE" = "Rifiuto"; +"BUTTON_DONE" = "Fine"; +"BUTTON_GET_STARTED" = "Inizia"; +"BUTTON_LEARN_MORE" = "Scopri di più"; +"BUTTON_NEXT" = "Avanti"; +"BUTTON_SKIP" = "Ignora"; +"BUTTON_SKIP_QUESTION" = "Ignora la domanda"; +"BUTTON_START_TIMER" = "Avvia il timer"; +"BUTTON_OPTION_SAVE" = "Salva e continua dopo"; +"BUTTON_OPTION_DISCARD" = "Elimina i risultati"; +"BUTTON_OPTION_STOP_TASK" = "Concludi attività"; +"BUTTON_SAVE" = "Salva"; +"BUTTON_CLEAR_ANSWER" = "Cancella risposta"; +"BUTTON_READ_ONLY_MODE" = "La risposta non può essere modificata."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Chiudi"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Inizio attività tra"; +"TASK_COMPLETE_TITLE" = "Attività completata"; +"TASK_COMPLETE_TEXT" = "I dati verranno analizzati, riceverai una notifica quando i risultati saranno pronti."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ rimanenti."; +"TOUCH_ANYWHERE_LABEL" = "Tocca un punto qualsiasi per continuare"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Scatta foto"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Scatta altra foto"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Fotocamera non trovata. Non è possibile completare l'operazione."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Per completare l'operazione, consenti a questa app di accedere alla fotocamera in Impostazioni."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Non è stata specificata nessuna directory di output per le immagini acquisite."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "L'immagine acquisita non può essere salvata."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Avvia registrazione"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Interrompi registrazione"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Riacquisisci video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Forma fisica"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distanza (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Battito cardiaco (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Siediti comodamente per %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Cammina il più velocemente possibile per %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "L'attività monitora la tua frequenza cardiaca e valuta la distanza massima che puoi raggiungere in %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Cammina all'aperto tenendo l'andatura più veloce che riesci a sostenere per %1$@. Al termine, siediti e riposati per %2$@. Tocca Inizia per cominciare."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Deambulazione ed equilibrio"; +"WALK_INTRO_TEXT" = "L'attività valuta la capacità di deambulazione e di equilibrio mentre cammini e rimani fermo. Non continuare se non sei in grado di spostarti in modo sicuro e autonomo."; +"WALK_INTRO_2_TEXT_%ld" = "Trova un luogo in cui puoi fare autonomamente circa %ld passi in linea retta in modo sicuro."; +"WALK_INTRO_2_DETAIL" = "Metti il dispositivo in tasca o in borsa e segui le istruzioni audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Rimani in piedi per %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Rimani in piedi per %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Girati e torna verso il punto in cui hai cominciato a camminare."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Fai fino a %ld passi in linea retta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Trova un luogo dove puoi camminare in sicurezza avanti e indietro in linea retta. Cerca di camminare senza interruzioni girandoti alla fine del percorso come se camminassi attorno a un cono.\n\nSuccessivamente ti verrà chiesto di girare in un cerchio completo, quindi di fermarti con le braccia lungo il corpo e i piedi circa alla larghezza delle spalle."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tocca Inizia per cominciare.\nQuindi posiziona il dispositivo in tasca o in borsa e segui le istruzioni audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Cammina avanti e indietro in linea retta per %@. Cammina come faresti normalmente."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Gira effettuando un cerchio completo, quindi fermati per %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Hai completato l'attività."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocità tocco"; +"TAPPING_TASK_TITLE_RIGHT" = "Mano destra"; +"TAPPING_TASK_TITLE_LEFT" = "Mano sinistra"; +"TAPPING_INTRO_TEXT" = "L'attività misura la velocità dei tocchi che esegui."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Posiziona il dispositivo su una superficie piana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Utilizza due dita della stessa mano per toccare alternativamente i pulsanti sullo schermo."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Utilizza due dita della mano destra per toccare alternativamente i pulsanti sullo schermo."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Utilizza due dita della mano sinistra per toccare alternativamente i pulsanti sullo schermo."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Ora ripeti lo stesso test con la mano destra."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Ora ripeti lo stesso test con la mano sinistra."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tocca con un dito, quindi con l'altro. Cerca di effettuare i tocchi con un ritmo più regolare possibile. Continua a toccare per %@."; +"TAPPING_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tocca Avanti per iniziare."; +"TAP_BUTTON_TITLE" = "Tocca"; +"TOTAL_TAPS_LABEL" = "Totale tocchi"; +"TAPPING_INSTRUCTION" = "Tocca i pulsanti il più regolarmente possibile usando due dita."; +"TAPPING_INSTRUCTION_RIGHT" = "Tocca i pulsanti usando la mano DESTRA."; +"TAPPING_INSTRUCTION_LEFT" = "Tocca i pulsanti usando la mano SINISTRA."; +"TAPPING_SKIP_TITLE" = "Non esaminare questa mano"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Griglia di Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "L'attività aiuta a rilevare problemi alla vista dell'utente."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Tieni il dispositivo a 30 centimetri dal viso e all'altezza degli occhi per tutto il test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Chiudi il tuo %@ e fissa il punto al centro della griglia quadrata.\n\nUtilizzando il dito o lo stilo, segna eventuali distorsioni, come linee sfocate o ondulate.\n\nQuando hai finito, scorri verso sinistra da qualsiasi punto fuori dalla griglia."; +"AMSLER_GRID_LEFT_EYE" = "occhio sinistro"; +"AMSLER_GRID_RIGHT_EYE" = "occhio destro"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voce"; +"AUDIO_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"AUDIO_INSTRUCTION" = "Di' “Aaaaa” nel microfono il più a lungo possibile."; +"AUDIO_INTRO_TEXT" = "Fai un respiro profondo e di' “Aaaaa” nel microfono il più a lungo possibile. Mantieni un volume uniforme in modo tale che le barre dell'audio rimangano di colore blu."; +"AUDIO_INTENDED_USE" = "L'attività valuta la tua voce registrandola tramite il microfono del dispositivo."; +"AUDIO_TOO_LOUD_LABEL" = "Volume troppo alto"; +"AUDIO_GENERIC_ERROR_LABEL" = "Impossibile registrare l'audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Attendi la verifica del livello di rumore di sottofondo."; +"AUDIO_TOO_LOUD_MESSAGE" = "Il livello di rumore ambientale è troppo alto per registrare la tua voce. Spostati in un luogo più silenzioso e riprova."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tocca Avanti per iniziare."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonale"; +"TONE_AUDIOMETRY_INTENDED_USE" = "L'attività valuta la tua capacità di sentire suoni differenti."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Prima di iniziare, collega e indossa le cuffie.\n\nIl suono sarà molto tenue e diverso da un normale avviso acustico. Il suono inizierà basso e successivamente aumenterà di volume. Presta attenzione e tocca il pulsante sinistro o destro per indicare in quale orecchio lo senti."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ora sentirai un segnale acustico, regola il volume mediante i tasti laterali del tuo dispositivo.\n\nTocca un pulsante per iniziare."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Ogni volta che inizi a sentire un suono tocca il pulsante sinistro o destro per indicare in quale orecchio lo senti."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Orecchio sinistro"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Orecchio destro"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, a sinistra"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, a destra"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonale"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tocca quando senti un suono."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tono e volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Sentirai una serie di suoni."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Quando senti un suono, tocca il pulsante."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Per questo test, il volume sarà impostato al 50 per cento."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Questo test dura circa 10 minuti."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Attiva “Non disturbare” per evitare interruzioni."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "I suoni verranno riprodotti nell'orecchio destro."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "I suoni verranno riprodotti nell'orecchio sinistro."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "L'attività identifica i livelli soglia dell'udito di un individuo in scala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Assicurati che il volume del dispositivo sia impostato sul livello massimo.\n\nDurante l'attività, verrà riprodotto un tenue segnale acustico nell'orecchio sinistro o nell'orecchio destro.\n\nAscolta con attenzione e tocca il pulsante ogni volta che senti un segnale acustico."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Questo test identifica il volume necessario perché tu senta un suono."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Questionario introduttivo."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Seleziona l'orecchio migliore, se presente"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "sinistro"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "destro"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "nessuna preferenza"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test annullato"; +"dBHL_ALERT_TITLE_START_OVER" = "Ricomincia"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Annulla test"; +"dBHL_ALERT_TEXT" = "Per eseguire questo test, riconnetti i tuoi auricolari AirPods o EarPods."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ completato"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Cuffie"; +"HEADPHONES_UNKNOWN" = "Sconosciute"; +"HEADPHONES_NONE" = "Nessuna"; +"CONNECTED" = "Connessi"; +"NOT_CONNECTED" = "Non connessi"; +"HEADPHONE_CONNECTED_%@" = "Connesso - %@"; +"HEADPHONE_DETECT_TITLE" = "Connetti le cuffie"; +"HEADPHONE_DETECT_TEXT" = "Questo test richiede auricolari AirPods o Earpods di Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memoria spaziale"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "L'attività valuta la tua memoria spaziale a breve termine. Ripeti l'ordine di accensione dei simboli a forma di %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "fiore"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "fiori"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "I simboli a forma di %@ si accenderanno uno alla volta. Toccali seguendo l'ordine di accensione."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "I simboli a forma di %@ si accenderanno uno alla volta. Toccali in ordine inverso rispetto alla sequenza iniziale."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Per cominciare, tocca Inizia e osserva con attenzione."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Punteggio"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Osserva quando il simbolo a forma di %@ si accende"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tocca i simboli a forma di %@ seguendo l'ordine con cui si sono accesi"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tocca i simboli a forma di %@ in ordine inverso"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequenza completa"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Per continuare, tocca Avanti"; +"MEMORY_GAME_FAILED_TITLE" = "Riprova"; +"MEMORY_GAME_FAILED_MESSAGE" = "Non hai completato l'attività in tempo. Tocca Avanti per continuare."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Tempo scaduto"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Tempo scaduto.\nTocca Avanti per continuare."; +"MEMORY_GAME_COMPLETE" = "Fine"; +"MEMORY_GAME_PAUSED_TITLE" = "In pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Per continuare, tocca Avanti"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "L'attività sulla memoria è stata sviluppata con l’assistenza della dottoressa Katherine Possin e del dottor Joel Kramer dell’Università della California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tempo di reazione"; +"REACTION_TIME_TASK_INTENDED_USE" = "L'attività valuta il tuo tempo di risposta quando ricevi un'indicazione visiva."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Quando vedi comparire il cerchio di colore blu sullo schermo, agita il dispositivo in qualsiasi direzione. Dovrai ripetere l'operazione %D volte."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Tentativo %@ di %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Agita velocemente il dispositivo quando compare il cerchio di colore blu"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Test di Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Ogni volta che appare una parola, seleziona la prima lettera del nome del COLORE che viene mostrato."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Per cominciare l’attività Stroop, tocca Inizia."; +"STROOP_TASK_STEP_TEXT" = "Seleziona la prima lettera del nome del COLORE che viene mostrato."; +"STROOP_COLOR_RED" = "ROSSO"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "BLU"; +"STROOP_COLOR_YELLOW" = "GIALLO"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "G"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre di Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Questa attività valuta le tue capacità di risolvere rompicapi."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Sposta l'intera pila sul piano evidenziato con il minor numero di mosse possibili."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Risolvi il rompicapo"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Numero di mosse: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Non riesco a risolvere il rompicapo"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Capacità di movimento"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption deve essere sinistra o destra"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Ampiezza del movimento del ginocchio sinistro"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Ampiezza del movimento del ginocchio destro"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Questa attività misura quanto riesci a estendere il ginocchio sinistro."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Questa attività misura quanto riesci a estendere il ginocchio destro."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Siediti sul bordo di una sedia. All’inizio posizionerai il dispositivo sul ginocchio sinistro per una misurazione. Attiva i suoni del dispositivo per poter sentire le istruzioni."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Siediti sul bordo di una sedia. All’inizio posizionerai il dispositivo sul ginocchio destro per una misurazione. Attiva i suoni del dispositivo per poter sentire le istruzioni."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posiziona il dispositivo sul ginocchio sinistro con lo schermo rivolto all’esterno, come illustrato."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posiziona il dispositivo sul ginocchio destro con lo schermo rivolto all’esterno, come illustrato."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quando vuoi, tocca lo schermo per iniziare ed estendi il più possibile il ginocchio sinistro. Torna alla posizione iniziale e tocca di nuovo quando hai finito."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quando vuoi, tocca lo schermo per iniziare ed estendi il più possibile il ginocchio destro. Torna alla posizione iniziale e tocca di nuovo quando hai finito."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Posiziona il dispositivo sul ginocchio sinistro. Tocca lo schermo ed estendi il più possibile il ginocchio sinistro."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Posiziona il dispositivo sul ginocchio destro. Tocca lo schermo ed estendi il più possibile il ginocchio destro."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando hai finito, riporta il ginocchio sinistro nella posizione iniziale e tocca qualunque punto."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando hai finito, riporta il ginocchio destro nella posizione iniziale e tocca qualunque punto."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Ampiezza del movimento della spalla sinistra"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Ampiezza del movimento della spalla destra"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Questa attività misura quanto riesci a estendere la spalla sinistra."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Questa attività misura quanto riesci a estendere la spalla destra."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "All’inizio posizionerai il dispositivo sulla spalla sinistra per una misurazione. Attiva i suoni del dispositivo per poter sentire le istruzioni."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "All’inizio posizionerai il dispositivo sulla spalla destra per una misurazione. Attiva i suoni del dispositivo per poter sentire le istruzioni."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posiziona il dispositivo sulla spalla sinistra con lo schermo rivolto all’esterno, come illustrato."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posiziona il dispositivo sulla spalla destra con lo schermo rivolto all’esterno, come illustrato."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quando vuoi, tocca lo schermo per iniziare e alza il più possibile il braccio sinistro. Torna alla posizione iniziale e tocca di nuovo quando hai finito."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quando vuoi, tocca lo schermo per iniziare e alza il più possibile il braccio destro. Torna alla posizione iniziale e tocca di nuovo quando hai finito."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Posiziona il dispositivo sulla spalla sinistra. Tocca lo schermo e alza il più possibile in avanti il braccio sinistro."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Posiziona il dispositivo sulla spalla destra. Tocca lo schermo e alza il più possibile in avanti il braccio destro."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando hai finito, riporta il braccio sinistro nella posizione iniziale e tocca qualunque punto."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando hai finito, riporta il braccio destro nella posizione iniziale e tocca qualunque punto."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Camminata a tempo"; +"TIMED_WALK_INTRO_DETAIL" = "Questa attività misura la funzionalità dei tuoi arti inferiori."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Trova un luogo, preferibilmente all'aperto, dove puoi camminare per circa %@ in linea retta il più velocemente possibile, ma in sicurezza. Non rallentare finché non hai superato il traguardo."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tocca Avanti per iniziare."; +"TIMED_WALK_FORM_TITLE" = "Ausilio ortopedico"; +"TIMED_WALK_FORM_TEXT" = "Utilizza lo stesso ausilio ortopedico per ciascun test."; +"TIMED_WALK_QUESTION_TEXT" = "Indossi un'ortesi caviglia-piede?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Utilizzi ausili ortopedici? "; +"TIMED_WALK_QUESTION_2_TEXT" = "Tocca per selezionare una risposta."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nessuno"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Bastone unilaterale"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Stampella unilaterale"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bastoni bilaterali"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Stampelle bilaterali"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Deambulatore/Rollatore"; +"TIMED_WALK_INSTRUCTION_%@" = "Cammina per %@ in linea retta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Girati."; +"TIMED_WALK_INSTRUCTION_2" = "Torna verso il punto in cui hai cominciato a camminare."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Al termine, tocca Avanti."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Il Paced Auditory Serial Addition Test (PASAT) misura la velocità di elaborazione delle informazioni uditive e la capacità di calcolo."; +"PVSAT_INTRO_TEXT" = "Il Paced Visual Serial Addition Test (PVSAT) misura la velocità di elaborazione delle informazioni visive e la capacità di calcolo."; +"PAVSAT_INTRO_TEXT" = "Il Paced Auditory and Visual Serial Addition Test (PAVSAT) misura la velocità di elaborazione delle informazioni uditive e visive e la capacità di calcolo."; +"PSAT_INTRO_TEXT_2_%@" = "Le singole cifre vengono mostrate ogni %@.\nDevi sommare ogni nuova cifra a quella immediatamente precedente.\nAttenzione: non devi calcolare un totale collettivo, ma solo la somma degli ultimi due numeri."; +"PSAT_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"PSAT_INITIAL_INSTRUCTION" = "Ricorda questa prima cifra."; +"PSAT_INSTRUCTION" = "Somma questa nuova cifra alla precedente."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test dei %@ pioli"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Questo test valuta la funzionalità dei tuoi arti superiori. Dovrai posizionare l'icona colorata nella sagoma vuota %@ volte."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Verranno esaminate entrambe le mani.\nDovrai afferrare l'icona colorata il più velocemente possibile e inserirla nell'apposita sagoma vuota. Una volta completata l'operazione %@ volte, dovrai rimuovere l'icona altre %@ volte."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Verranno esaminate entrambe le mani.\nDovrai afferrare l'icona colorata il più velocemente possibile e inserirla nell'apposita sagoma vuota. Una volta completata l'operazione %@ volte, dovrai rimuovere l'icona altre %@ volte."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Sposta l'icona colorata nella sagoma vuota usando la mano sinistra."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Sposta l'icona colorata nella sagoma vuota usando la mano destra."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Sposta l'icona colorata dietro la linea usando la mano sinistra."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Sposta l'icona colorata dietro la linea usando la mano destra."; +"HOLE_PEG_TEST_TEXT" = "Afferra l'icona colorata utilizzando due dita."; +"HOLE_PEG_TEST_TEXT_2" = "Solleva le dita per rilasciare l'icona colorata."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Attività tremore"; +"TREMOR_TEST_INTRO_1_DETAIL" = "L'attività misura il tremore delle mani in varie posizioni. Trova un luogo dove puoi sederti comodamente per la durata dell'attività."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Tieni il telefono nella mano maggiormente interessata come mostrato nell'immagine sotto."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Tieni il telefono nella mano DESTRA come mostrato nell'immagine sotto."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Tieni il telefono nella mano SINISTRA come mostrato nell'immagine sotto."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Ti verrà richiesto di eseguire %@ in posizione seduta con il telefono in mano."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "un'attività"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "due attività"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tre attività"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quattro attività"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinque attività"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tocca Avanti per procedere."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Preparati a tenere il telefono vicino alle ginocchia."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Preparati a tenere il telefono vicino alle ginocchia con la mano SINISTRA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Preparati a tenere il telefono vicino alle ginocchia con la mano DESTRA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Continua a tenere il telefono vicino alle ginocchia per %ld secondi."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Ora tieni il telefono con la mano distesa all'altezza della spalla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Ora tieni il telefono con la mano SINISTRA distesa all'altezza della spalla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Ora tieni il telefono con la mano DESTRA distesa all'altezza della spalla."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Continua a tenere il telefono con la mano distesa per %ld secondi."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Ora tieni il telefono all'altezza della spalla con il gomito piegato."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Ora tieni il telefono con la mano SINISTRA all'altezza della spalla con il gomito piegato."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Ora tieni il telefono con la mano DESTRA all'altezza della spalla con il gomito piegato."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Continua a tenere il telefono con il gomito piegato per %ld secondi"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Ora, tenendo il gomito piegato, tocca ripetutamente il naso con il telefono."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Ora, tenendo il gomito piegato con il telefono nella mano SINISTRA, tocca ripetutamente il naso con il telefono."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Ora, tenendo il gomito piegato con il telefono nella mano DESTRA, tocca ripetutamente il naso con il telefono."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Continua a toccare il naso con il telefono per %ld secondi"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Preparati a ruotare ripetutamente il polso a destra e a sinistra."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Preparati a ruotare ripetutamente il polso a destra e a sinistra con la mano SINISTRA."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Preparati a ruotare ripetutamente il polso a destra e a sinistra con la mano DESTRA."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Continua a ruotare il polso a destra e a sinistra per %ld secondi."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Ora passa il telefono alla mano SINISTRA e continua con l'attività successiva."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Ora passa il telefono alla mano DESTRA e continua con l'attività successiva."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continua con l'attività successiva."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Attività completata."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Ti verrà richiesto di eseguire %@ in posizione seduta con il telefono prima in una mano, poi di nuovo nell'altra."; +"TREMOR_SKIP_LEFT_HAND" = "Non posso eseguire l'attività con la mano SINISTRA."; +"TREMOR_SKIP_RIGHT_HAND" = "Non posso eseguire l'attività con la mano DESTRA."; +"TREMOR_SKIP_NEITHER" = "Posso eseguire l'attività con entrambe le mani."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test di trail-making"; +"TRAILMAKING_INTENDED_USE" = "L'attività valuta la tua attenzione visiva e il passaggio da un compito all’altro registrando il tempo richiesto per toccare una serie di punti in ordine."; +"TRAILMAKING_INTENDED_USE2_A" = "Dopo il conto alla rovescia, tocca i punti in ordine alternato tra numeri e lettere. Inizia toccando il primo numero “1” seguito dai numeri “2” – “3” – “4”… fino a raggiungere il numero “7”."; +"TRAILMAKING_INTENDED_USE2_B" = "Dopo il conto alla rovescia, tocca i punti in ordine alternato tra numeri e lettere. Inizia toccando il primo numero “1” seguito dalla prima lettera “A”, quindi “2” – “B” – “3” – “C”… fino a raggiungere il numero “7”."; +"TRAILMAKING_INTRO_TEXT" = "Fallo più velocemente che puoi senza commettere errori. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Riconoscimento vocale"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "L'attività registra la tua voce con il microfono del dispositivo e lo converte in testo."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tocca Inizia per cominciare."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Premi il pulsante per avviare la registrazione prima di parlare."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Avvia registrazione"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Interrompi registrazione"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Modifica trascrizione"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Modifica la trascrizione per correggere eventuali errori nel riconoscimento vocale."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "La trascrizione verrà mostrata qui."; +"SPEECH_RECOGNITION_FAILED" = "Riconoscimento vocale non riuscito."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Impossibile inizializzare il riconoscimento vocale."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Riproduci audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Interrompi audio"; +"SPEECH_IN_NOISE_TITLE" = "Voce con rumore"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "L'attività misura la capacità di comprendere il parlato quando avviene in ambienti rumorosi."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Il test è composto dai seguenti passaggi:\n\nAscolta una frase.\n\nRipeti chiaramente cosa hai sentito o salta il passaggio per inserire cosa hai sentito utilizzando la tastiera. \n\nSe ripeti cosa hai sentito, ti verrà data l'opzione di modificare il testo generato dal sistema di riconoscimento vocale."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibrazione volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tocca “Riproduci audio”, regola il volume a un livello confortevole, quindi tocca “Interrompi audio” per procedere."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Ascolta"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Verrà riprodotta una frase con rumore di fondo con un rapporto segnale/rumore casuale una sola volta."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Parla"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Ripeti quello che hai sentito."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Impossibile creare file"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Impossibile rimuovere file di log sufficienti per raggiungere la soglia"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Errore di impostazione dell'attributo"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "File non contrassegnati eliminati (non contrassegnati caricati)"; +"ERROR_DATALOGGER_MULTIPLE" = "Errori multipli durante la rimozione dei log"; +"ERROR_RECORDER_NO_DATA" = "Non ci sono dati disponibili."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Non è stata specificata nessuna directory di output"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Fonometro"; +"ENVIRONMENTSPL_INTRO_TEXT" = "L'attività misura il livello di pressione sonora dell'ambiente. Se i livelli di rumore sono troppo alti, non potrai procedere. Raggiungi un luogo più silenzioso per completare l'attività oppure eseguila di nuovo in un secondo momento."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calcolo"; +"ENVIRONMENTSPL_THRESHOLD" = "Soglia: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Rumore di sottofondo OK"; +"ENVIRONMENTSPL_NOISE" = "Troppo rumore in sottofondo"; +"ENVIRONMENTSPL_TITLE_2" = "Trova un luogo silenzioso"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Per garantire la precisione necessaria, il test dovrebbe essere realizzato in un ambiente silenzioso."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Avvia attività"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Nessun dato"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Sposta il cursore per inserire un valore"; +"SLIDER_I_DONT_KNOW" = "Non saprei"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Pagina"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Indietro"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostra miniatura PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Nascondi miniature PDF"; +"AX_BUTTON_ANNOTATE" = "Annota"; +"AX_BUTTON_SHOW_SEARCH" = "Mostra barra di ricerca"; +"AX_BUTTON_HIDE_SEARCH" = "Nascondi barra di ricerca"; +"AX_BUTTON_SHARE" = "Condividi"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustrazione di un segno di spunta in un cerchio blu che indica successo"; + +"AX_SIGNVIEW_LABEL" = "Campo firma"; +"AX_SIGNVIEW_HINT" = "Tocca lo schermo e sposta il dito per firmare"; +"AX_SIGNVIEW_SIGNED" = "Firmato"; +"AX_SIGNVIEW_UNSIGNED" = "Senza firma"; + +"AX_SELECTED" = "Selezionato"; +"AX_UNSELECTED" = "Non selezionato"; +"AX_SELECT_ALL_THAT_APPLY" = "SELEZIONA TUTTE LE OPZIONI VALIDE"; + +"AX_SLIDER_LABEL" = "Slider risposta. Da %@ a %@"; +"AX_UNLABELED_IMAGE" = "Immagine senza etichetta"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Inizia"; + +"AX.MEMORY.TILE.ACTIVE" = "attivo"; +"AX.MEMORY.TILE.CORRECT" = "corretto"; +"AX.MEMORY.TILE.INCORRECT" = "non corretto"; +"AX.MEMORY.TILE.QUIESCENT" = "inattivo"; +"AX.MEMORY.TILE.LABEL" = "Tassello gioco mnemonico"; + +"AX_IMAGE_CAPTURE_LABEL" = "Anteprima immagine"; +"AX_IMAGE_CAPTURED_LABEL" = "Immagine scattata"; + +"AX_VIDEO_CAPTURE_LABEL" = "Anteprima acquisizione video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Acquisizione video completata"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Impossibile posizionare il disco di dimensione %@ sul disco di dimensione %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Destinazione"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Tocca due volte per posizionare il disco"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Tocca due volte per selezionare il disco superiore"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Dimensioni dischi: %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vuota"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Chiudi tastiera"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Intervallo da %@ a %@"; +"AX_GRAPH_STACK_PREFIX" = "Pila composta da"; +"AX_GRAPH_AND_SEPARATOR" = " e "; +"AX_GRAPH_POINT_%@" = "Punto: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forma d'onda della voce"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Quando la registrazione inizia, attiva una seconda volta per interromperla."; + +"AX_AUDIO_BAR_GRAPH" = "Grafico barra audio"; + +"AX_AMSLER_GRID_LABEL" = "Griglia di Amsler"; +"AX_AMSLER_GRID_HINT" = "Utilizza il dito o lo stilo per segnare direttamente sulla griglia oppure scorri verso sinistra da un punto fuori dalla griglia per finire."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Pulsanti attivabili tramite tocco"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tocca per orecchio sinistro"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Attiva per avviare il test. Dopo che è iniziato, tocca direttamente il pulsante quando senti un suono nell'orecchio sinistro."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tocca per orecchio destro"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Attiva per avviare il test. Dopo che è iniziato, tocca direttamente il pulsante quando senti un suono nell'orecchio destro."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Usando VoiceOver, tocca lo schermo per sapere dove sono posizionati i pulsanti per ogni orecchio. Quando inizia il test, i pulsanti saranno attivabili direttamente tramite tocco. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tocca per un dito"; +"AX_TAP_BUTTON_2_LABEL" = "Tocca per un altro dito"; +"AX_TAP_BUTTON_HINT" = "Abilita quest'opzione per rendere i pulsanti attivabili direttamente tramite tocco."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Usando VoiceOver, esplora lo schermo toccando per sapere dove sono posizionati i pulsanti. Abilita uno dei pulsanti per renderli attivabili direttamente tramite tocco."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "I pulsanti adesso sono attivabili direttamente tramite tocco."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Usando VoiceOver, il pulsante potrà essere attivato direttamente tramite tocco. Sarà posizionato approssimativamente al centro dello schermo."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Usando VoiceOver, i pulsanti del test saranno attivabili direttamente tramite tocco."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Impossibile decodificare restoreData per l'inizializzazione"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..3eb1d3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/it.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d errore) + other + (%d errori) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.strings new file mode 100755 index 0000000..53e63e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "同意"; +"CONSENT_NAME_GIVEN" = "名"; +"CONSENT_NAME_FAMILY" = "姓"; +"CONSENT_NAME_PLACEHOLDER" = "必須"; +"CONSENT_REVIEW_TITLE" = "確認"; +"CONSENT_REVIEW_INSTRUCTION" = "下記のフォームを確認して、続ける場合は“同意する”をタップしてください。"; +"CONSENT_REVIEW_ALERT_TITLE" = "確認"; +"CONSENT_SIGNATURE_TITLE" = "署名"; +"CONSENT_SIGNATURE_INSTRUCTION" = "下の枠内に指で署名してください。"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "ここに署名"; +"CONSENT_PAGE_NUMBER_FORMAT" = "ページ%1$ld/%2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "ようこそ"; +"CONSENT_SECTION_DATA_GATHERING" = "データの収集"; +"CONSENT_SECTION_PRIVACY" = "プライバシー"; +"CONSENT_SECTION_DATA_USE" = "データの使用方法"; +"CONSENT_SECTION_STUDY_SURVEY" = "調査アンケート"; +"CONSENT_SECTION_STUDY_TASKS" = "調査タスク"; +"CONSENT_SECTION_TIME_COMMITMENT" = "所要時間"; +"CONSENT_SECTION_WITHDRAWING" = "同意の撤回"; +"CONSENT_LEARN_MORE_TITLE" = "詳しい情報"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "データの収集方法についての詳しい情報を表示します"; +"LEARN_MORE_DATA_USE" = "データの使用方法についての詳しい情報を表示します"; +"LEARN_MORE_PRIVACY" = "プライバシーおよび個人を特定する情報の保護方法についての詳しい情報を表示します"; +"LEARN_MORE_WELCOME" = "まず調査についての詳しい情報を表示します"; +"LEARN_MORE_STUDY_SURVEY" = "調査アンケートについての詳しい情報を表示します"; +"LEARN_MORE_TIME_COMMITMENT" = "調査にかかる時間についての詳しい情報を表示します"; +"LEARN_MORE_TASKS" = "必要なタスクについての詳しい情報を表示します"; +"LEARN_MORE_WITHDRAWING" = "同意の撤回についての詳しい情報を表示します"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "共有オプション"; +"CONSENT_SHARE_WIDELY_%@" = "自分のデータを%@および資格を持つ世界中の研究者と共有します"; +"CONSENT_SHARE_ONLY_%@" = "自分のデータを%@とのみ共有します"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@は、この調査に参加したあなたの調査データを受信します。\n\n名前などの情報を含まない、大まかにコード化された調査データを共有すると、今回と将来の調査に役立てることができます。"; +"LEARN_MORE_CONSENT_SHARING" = "データ共有についての詳しい情報を表示します"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "氏名(活字体)"; +"CONSENT_DOC_LINE_SIGNATURE" = "署名"; +"CONSENT_DOC_LINE_DATE" = "日付"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "質問: %1$@ / %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "スキップしました"; +"REVIEW_EDIT_ANSWER" = "編集"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "値が無効です"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@は許容される最大値(%2$@)を超えています。"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@は許容される最小値(%2$@)より小さいです。"; +"RANGE_ALERT_MESSAGE_OTHER" = "%@は無効な値です。"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "メールアドレスが無効です: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "住所を入力"; +"LOCATION_ERROR_TITLE" = "指定した住所が見つかりませんでした"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "現在地を確認できません。住所を入力するか、GPS信号の受信状況が良好な場所に移動してください。"; +"LOCATION_ERROR_MESSAGE_DENIED" = "位置情報サービスへのアクセスが拒否されました。“設定”でこのAppに位置情報サービスの使用を許可してください。"; +"LOCATION_ERROR_GEOCODE" = "入力した住所の結果が見つかりません。住所が正しいことを確認してください。"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "インターネットに接続されていないか、住所検索要求の最大数に達しました。インターネットに接続されていない場合は、Wi-Fiをオンにしてこの質問に回答するか、この質問をスキップするか(スキップボタンが表示されている場合)、またはインターネットに接続されているときにアンケートをやり直してください。インターネットに接続されている場合は、数分待ってからやり直してください。"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "文字数が最大許容数を超えています: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "分割画面ではカメラを使用できません。"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "メール"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "hiro_sato@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "パスワード"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "パスワードを入力"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "確認"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "パスワードを再入力"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "パスワードが一致しません。"; +"ADDITIONAL_INFO_SECTION_TITLE" = "追加情報"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "性別"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "性別を選択"; +"DOB_FORM_ITEM_TITLE" = "生年月日"; +"DOB_FORM_ITEM_PLACEHOLDER" = "日付を選択"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "電話番号"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "確認"; +"VERIFICATION_STEP_TITLE" = "メールを確認"; +"RESEND_EMAIL_LABEL_MESSAGE" = "確認メールが届いておらず、送信し直したい場合は、下のリンクをタップしてください。"; +"RESEND_EMAIL_BUTTON_TITLE" = "確認メールを再送信"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "ログイン"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "パスワードをお忘れですか?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "パスコードを入力してください"; +"PASSCODE_CONFIRM_MESSAGE" = "パスコードを確認してください"; +"PASSCODE_SAVED_MESSAGE" = "パスコードが保存されました"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "パスコードが認証されました"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "古いパスコードを入力してください"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "新しいパスコードを入力してください"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "新しいパスコードを確認してください"; +"PASSCODE_INVALID_ALERT_TITLE" = "パスコードが正しくありません"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "パスコードが一致しません。もう一度入力してください。"; +"PASSCODE_TOUCH_ID_MESSAGE" = "Touch IDで認証してください"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch IDエラー"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "入力できるのは数字のみです。"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "パスコード入力の進行状況インジケータ"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@/%@桁を入力しました"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "パスコードをお忘れですか?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "キーチェーン項目を追加できませんでした。"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "キーチェーン項目をアップデートできませんでした。"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "キーチェーン項目を削除できませんでした。"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "キーチェーン項目が見つかりませんでした。"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "タイプI"; +"FITZPATRICK_SKIN_TYPE_II" = "タイプII"; +"FITZPATRICK_SKIN_TYPE_III" = "タイプIII"; +"FITZPATRICK_SKIN_TYPE_IV" = "タイプIV"; +"FITZPATRICK_SKIN_TYPE_V" = "タイプV"; +"FITZPATRICK_SKIN_TYPE_VI" = "タイプVI"; + +/* Gender values. */ +"GENDER_FEMALE" = "女性"; +"GENDER_MALE" = "男性"; +"GENDER_OTHER" = "その他"; + +/* Boolean answer strings */ +"BOOL_NO" = "いいえ"; +"BOOL_YES" = "はい"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "左"; +"LIMB_RIGHT" = "右"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "タップで回答"; +"NULL_ANSWER" = "答えを選択してください"; +"PLACEHOLDER_IMAGE_CHOICES" = "タップで選択"; +"PLACEHOLDER_LONG_TEXT" = "タップで書き込む"; + +/* Button titles */ +"BUTTON_AGREE" = "同意する"; +"BUTTON_CANCEL" = "キャンセル"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "消去"; +"BUTTON_CLEAR_SIGNATURE" = "署名を消去"; +"BUTTON_APPLY" = "適用"; +"BUTTON_DISAGREE" = "同意しない"; +"BUTTON_DONE" = "完了"; +"BUTTON_GET_STARTED" = "開始"; +"BUTTON_LEARN_MORE" = "詳しい情報"; +"BUTTON_NEXT" = "次へ"; +"BUTTON_SKIP" = "スキップ"; +"BUTTON_SKIP_QUESTION" = "この質問をスキップ"; +"BUTTON_START_TIMER" = "タイマーを開始"; +"BUTTON_OPTION_SAVE" = "後で使用するために保存"; +"BUTTON_OPTION_DISCARD" = "結果を破棄"; +"BUTTON_OPTION_STOP_TASK" = "タスクを終了"; +"BUTTON_SAVE" = "保存"; +"BUTTON_CLEAR_ANSWER" = "答えを消去"; +"BUTTON_READ_ONLY_MODE" = "この答えは変更できません。"; +"BUTTON_COPYRIGHT" = "著作権"; +"BUTTON_CLOSE" = "閉じる"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "アクティビティ開始まで"; +"TASK_COMPLETE_TITLE" = "アクティビティ完了"; +"TASK_COMPLETE_TEXT" = "データは分析され、結果が準備できたら通知されます。"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "残り%@です。"; +"TOUCH_ANYWHERE_LABEL" = "続けるにはどこかをタッチしてください"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "イメージを取り込む"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "再度イメージを取り込む"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "カメラが見つからないため、この手順を完了できません。"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "この手順を完了するには、“設定”でこのAppがカメラにアクセスすることを許可してください。"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "取り込んだイメージの出力ディレクトリが指定されていません。"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "取り込んだイメージを保存できませんでした。"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "収録を開始"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "収録を停止"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "再度ビデオを取り込む"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "体力"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "距離(%@)"; +"FITNESS_HEARTRATE_TITLE" = "心拍数(bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "%@間楽な姿勢で座ってください。"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "できるだけ速く%@間歩いてください。"; +"FITNESS_INTRO_TEXT_FORMAT" = "このアクティビティでは、心拍数をモニタし、%1$@で歩ける距離を測定します。"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "屋外でできるだけ速いペースで%1$@間歩いてください。終わったら座って、%2$@間楽にしてください。始めるには、“開始”をタップしてください。"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "歩行/バランス"; +"WALK_INTRO_TEXT" = "このアクティビティでは、歩行中とじっと立っているときの歩行/バランスを測定します。介助なしで安全に歩行できない場合は、続行しないでください。"; +"WALK_INTRO_2_TEXT_%ld" = "介助なしで安全に、まっすぐに%ld歩程度歩ける場所を見つけてください。"; +"WALK_INTRO_2_DETAIL" = "デバイスをポケットまたはバッグに入れて、音声による指示に従ってください。"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "ここで%@間じっと立っていてください。"; +"WALK_STAND_INSTRUCTION_FORMAT" = "%@間じっと立っていてください。"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "後ろを向いて、元の場所まで歩いて戻ってください。"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "まっすぐに%ld歩まで歩いてください。"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "安全にまっすぐ行ったり来たり歩ける場所を見つけてください。進路の終わりまで来たら、コーンを回るように折り返して歩き続けます。\n\n次に、完全な円を描いて回るように指示されます。その後、両腕を脇につけ、足を肩幅くらいに開いてじっと立ってください。"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "開始の準備ができたら、“開始”をタップしてください。\n次に、デバイスをポケットまたはバッグに入れて、音声による指示に従ってください。"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "まっすぐ行ったり来たりして%@間歩きます。いつもと同じように歩いてください。"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "完全な円を描いて歩いてから、%@間じっと立ってください。"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "アクティビティが完了しました。"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "タップの速度"; +"TAPPING_TASK_TITLE_RIGHT" = "右手"; +"TAPPING_TASK_TITLE_LEFT" = "左手"; +"TAPPING_INTRO_TEXT" = "このアクティビティでは、タップの速度を測定します。"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "デバイスを平らな面に置いてください。"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "同じ手の2本の指を使って、画面上のボタンを交互にタップします。"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "右手の2本の指を使って、画面上のボタンを交互にタップしてください。"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "左手の2本の指を使って、画面上のボタンを交互にタップしてください。"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "次に、右手で同じテストを繰り返します。"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "次に、左手で同じテストを繰り返します。"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "一方の指でタップしてから、他方の指でタップします。できるだけ一定の時間間隔でタップしてください。%@間タップし続けます。"; +"TAPPING_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"TAPPING_CALL_TO_ACTION_NEXT" = "始めるには、“次へ”をタップしてください。"; +"TAP_BUTTON_TITLE" = "タップ"; +"TOTAL_TAPS_LABEL" = "合計タップ回数"; +"TAPPING_INSTRUCTION" = "2本の指を使って、できるだけ一定の速度でボタンをタップしてください。"; +"TAPPING_INSTRUCTION_RIGHT" = "右手を使ってボタンをタップしてください。"; +"TAPPING_INSTRUCTION_LEFT" = "左手を使ってボタンをタップしてください。"; +"TAPPING_SKIP_TITLE" = "この手をスキップ"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "アムスラーグリッド"; +"AMSLER_GRID_INTRO_TEXT" = "このアクティビティは、ユーザの視力の問題を検出するときに役立てることができます。"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "テストの間、デバイスを目の高さで、顔から30センチメートルほど離して持ってください。"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "%@を閉じて、四角形のグリッドの中央にあるドットを見つめます。\n\n指かスタイラスペンで、不鮮明な線や破線などの歪みをマークします。\n\n終わったら、グリッドの外を左へスワイプします。"; +"AMSLER_GRID_LEFT_EYE" = "左目"; +"AMSLER_GRID_RIGHT_EYE" = "右目"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "声"; +"AUDIO_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"AUDIO_INSTRUCTION" = "マイクに向かってできるだけ長く「あーーーー」と声を出してください。"; +"AUDIO_INTRO_TEXT" = "大きく息を吸ってから、マイクに向かってできるだけ長く「あーーーー」と声を出してください。声の大きさを一定に保って、オーディオバーを青色のままにしてください。"; +"AUDIO_INTENDED_USE" = "このアクティビティでは、デバイスの下部にあるマイクで録音することで、あなたの声を評価します。"; +"AUDIO_TOO_LOUD_LABEL" = "大きすぎる"; +"AUDIO_GENERIC_ERROR_LABEL" = "声を録音できません"; +"AUDIO_LEVEL_CHECK_LABEL" = "背景ノイズのレベルを確認中です。しばらくお待ちください。"; +"AUDIO_TOO_LOUD_MESSAGE" = "周囲のノイズが大きすぎるため、声を録音できません。静かな場所に移動してやり直してください。"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "準備ができたら“次へ”をタップしてください。"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "聴力検査"; +"TONE_AUDIOMETRY_INTENDED_USE" = "このアクティビティでは、さまざまな音がどのように聞こえるかが測定されます。"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "始める前に、ヘッドフォンを接続して装着してください。\n\n普通の通知音ではなく、非常にかすかな音が聞こえます。最初は弱い音で、徐々に大きくなっていきます。よく聞いて、どちらの耳で聞こえたかを左ボタンか右ボタンをタップして示してください。"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"TONE_AUDIOMETRY_PREP_TEXT" = "音が聞こえてくるのでデバイスの横にあるコントロールで音量を調整してください。\n\n始める準備ができたらボタンをタップしてください。"; +"TONE_AUDIOMETRY_INSTRUCTION" = "音が聞こえ始めるたびに、どちらの耳で聞こえたかを左ボタンか右ボタンをタップして示してください。"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "左耳"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "右耳"; +"TONE_LABEL_%@_LEFT" = "%@ Hz、左"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz、右"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "聴力検査"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "トーン音が聞こえたらタップしてください。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "トーンおよび音量"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "一連のトーン音が聞こえます。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "トーン音が聞こえたら、ボタンをタップしてください。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "このテストでは、音量は50パーセントに設定されます。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "テストの所要時間は約10分です。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "テストの中断を避けるために、“おやすみモード”をオンにしてください。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "トーンは最初に右の耳で再生されます。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "トーンは次に左の耳で再生されます。"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "このアクティビティでは、個人の聴覚閾値レベルをdBHL単位で識別します。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "デバイスの音量が最大レベルまで設定されていることを確認してください。\n\nこのタスクの間に、かすかな音が左耳か右耳のどちらかに流れます。\n\n耳を澄ませて、音が聞こえるたびにボタンをタップしてください。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "このテストは、音が聞こえるにはどれぐらいの音量が必要かを確認します。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "開始時の質問。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "聴きやすいほうの耳があれば選択します"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "左"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "右"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "設定なし"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "テストはキャンセルされました"; +"dBHL_ALERT_TITLE_START_OVER" = "もう一度開始"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "テストをキャンセル"; +"dBHL_ALERT_TEXT" = "このテストを実行するには、AirPodsかEarPodsを再接続してください。"; +"dBHL_PROGRESS_COMPLETION_%@" = "%@完了"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "ヘッドフォン"; +"HEADPHONES_UNKNOWN" = "不明"; +"HEADPHONES_NONE" = "なし"; +"CONNECTED" = "接続済み"; +"NOT_CONNECTED" = "未接続"; +"HEADPHONE_CONNECTED_%@" = "接続済み - %@"; +"HEADPHONE_DETECT_TITLE" = "ヘッドフォンを接続"; +"HEADPHONE_DETECT_TEXT" = "このテストにはApple製品のAirPodsまたはEarPodsが必要です"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "空間記憶"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "このアクティビティでは、%@が明るく表示される順番を再現することで、短期空間記憶を測定します。"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "花"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "花"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "%@のいくつかが1つずつ明るく表示されます。それらの%@を明るく表示された順番と同じ順番でタップしてください。"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "%@のいくつかが1つずつ明るく表示されます。それらの%@を明るく表示された順番と逆の順番でタップしてください。"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "始めるには、“開始”をタップしてから、じっと見てください。"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "スコア"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "明るく表示される%@に注意してください"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "明るく表示された順番で%@をタップしてください"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "逆の順番で%@をタップしてください"; +"MEMORY_GAME_COMPLETE_TITLE" = "シーケンス完了"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "続けるには、“次へ”をタップしてください"; +"MEMORY_GAME_FAILED_TITLE" = "やり直す"; +"MEMORY_GAME_FAILED_MESSAGE" = "うまくできませんでした。\\n続けるには、“次へ”をタップしてください。"; +"MEMORY_GAME_TIMEOUT_TITLE" = "タイムアップ"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "時間がなくなりました。\n続けるには、“次へ”をタップしてください。"; +"MEMORY_GAME_COMPLETE" = "ゲーム完了"; +"MEMORY_GAME_PAUSED_TITLE" = "一時停止"; +"MEMORY_GAME_PAUSED_MESSAGE" = "続けるには、“次へ”をタップしてください"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "記憶アクティビティは、カリフォルニア大学サンフランシスコ校のKatherine Possin博士およびJoel Kramer博士の支援を受けて開発されました。"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "反応時間"; +"REACTION_TIME_TASK_INTENDED_USE" = "このアクティビティでは、視覚的な合図に反応するまでの時間が測定されます。"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "画面に青い点が表示されたらすぐにデバイスを振ってください。測定は%D回行います。"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "%@/%@回"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "青い円が表示されたら、すぐにデバイスを振ってください"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "ストループ"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "文字が表示されるたびに、表示される色を選択してください。"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "ストループアクティビティを始める準備ができたら、“開始”をタップしてください。"; +"STROOP_TASK_STEP_TEXT" = "表示される色を選択してください。"; +"STROOP_COLOR_RED" = "あか"; +"STROOP_COLOR_GREEN" = "みどり"; +"STROOP_COLOR_BLUE" = "あお"; +"STROOP_COLOR_YELLOW" = "きいろ"; +"STROOP_COLOR_RED_INITIAL" = "あか"; +"STROOP_COLOR_GREEN_INITIAL" = "みどり"; +"STROOP_COLOR_BLUE_INITIAL" = "あお"; +"STROOP_COLOR_YELLOW_INITIAL" = "きいろ"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "ハノイの塔"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "このアクティビティでは、パズルの解決力を評価します。"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "塔全体を色の付いた台にできるだけ少ない回数で移動してください。"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "パズルを解く"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "移動回数: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "降参"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "可動域"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOptionは左または右にする必要があります"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "左膝の可動域"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "右膝の可動域"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "このアクティビティでは、左膝をどこまで伸ばせるかを測定します。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "このアクティビティでは、右膝をどこまで伸ばせるかを測定します。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "椅子の端に座ってください。始めるときは、測定のためにデバイスを左膝の上に置きます。指示が聞こえるように、デバイスのサウンドをオンにしてください。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "椅子の端に座ってください。始めるときは、測定のためにデバイスを右膝の上に置きます。指示が聞こえるように、デバイスのサウンドをオンにしてください。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "写真のように、画面を外側に向けてデバイスを左膝の上に置きます。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "写真のように、画面を外側に向けてデバイスを右膝の上に置きます。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "準備ができたら、画面をタップして開始し、左膝をできるだけ伸ばしてください。終わったら、最初の位置に戻りもう一度タップしてください。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "準備ができたら、画面をタップして開始し、右膝をできるだけ伸ばしてください。終わったら、最初の位置に戻りもう一度タップしてください。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "デバイスを左膝の上に置きます。画面をタップして、左膝をできるだけ伸ばしてください。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "デバイスを右膝の上に置きます。画面をタップして、右膝をできるだけ伸ばしてください。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "終わったら、左膝を最初の位置に戻してください。次にどこかをタップしてください。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "終わったら、右膝を最初の位置に戻してください。次にどこかをタップしてください。"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "左肩の可動域"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "右肩の可動域"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "このアクティビティでは、左肩をどこまで伸ばせるかを測定します。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "このアクティビティでは、右肩をどこまで伸ばせるかを測定します。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "始めるときは、測定のためにデバイスを左肩の上に置きます。指示が聞こえるように、デバイスのサウンドをオンにしてください。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "始めるときは、測定のためにデバイスを右肩の上に置きます。指示が聞こえるように、デバイスのサウンドをオンにしてください。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "写真のように、画面を外側に向けてデバイスを左肩の上に置きます。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "写真のように、画面を外側に向けてデバイスを右肩の上に置きます。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "準備ができたら、画面をタップして開始し、左腕をできるだけ高く上げてください。終わったら、最初の位置に戻りもう一度タップしてください。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "準備ができたら、画面をタップして開始し、右腕をできるだけ高く上げてください。終わったら、最初の位置に戻りもう一度タップしてください。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "デバイスを左肩の上に置きます。画面をタップして、左腕をできるだけ前に上げてください。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "デバイスを右肩の上に置きます。画面をタップして、右腕をできるだけ前に上げてください。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "終わったら、左腕を最初の位置に戻してください。次にどこかをタップしてください。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "終わったら、右腕を最初の位置に戻してください。次にどこかをタップしてください。"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "歩行時間"; +"TIMED_WALK_INTRO_DETAIL" = "このアクティビティでは、下肢の機能を測定します。"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "約%@の距離をできるだけ速く安全にまっすぐに歩ける場所(可能であれば屋外で)を見つけてください。ゴールを通過するまで速度を落とさないでください。"; +"TIMED_WALK_INTRO_2_DETAIL" = "始めるには、“次へ”をタップしてください。"; +"TIMED_WALK_FORM_TITLE" = "補助器具"; +"TIMED_WALK_FORM_TEXT" = "すべてのテストで同じ補助器具を使用してください。"; +"TIMED_WALK_QUESTION_TEXT" = "短下肢装具をお付けになりますか?"; +"TIMED_WALK_QUESTION_2_TITLE" = "補助器具をお使いになりますか?"; +"TIMED_WALK_QUESTION_2_TEXT" = "ここをタップして答えを選択。"; +"TIMED_WALK_QUESTION_2_CHOICE" = "なし"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "片側ケイン"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "片側クラッチ"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "両側ケイン"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "両側クラッチ"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "歩行器"; +"TIMED_WALK_INSTRUCTION_%@" = "まっすぐ%@歩いてください。"; +"TIMED_WALK_INSTRUCTION_TURN" = "後ろを向いてください。"; +"TIMED_WALK_INSTRUCTION_2" = "元の場所まで歩いて戻ってください。"; +"TIMED_WALK_INSTRUCTION_TEXT" = "完了したら、“次へ”をタップしてください。"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT(定速聴覚的連続加算)では、聴覚による情報処理速度と計算能力を測定します。"; +"PVSAT_INTRO_TEXT" = "PVSAT(定速視覚的連続加算)では、視覚による情報処理速度と計算能力を測定します。"; +"PAVSAT_INTRO_TEXT" = "PAVSAT(定速聴覚および視覚的連続加算)では、聴覚および視覚による情報処理速度と計算能力を測定します。"; +"PSAT_INTRO_TEXT_2_%@" = "%@秒ごとに1つの数字が表示されます。\n表示された数字を、直前に表示された数字と足してください。\nすべての数字を足すのではありません。常に、表示された数字とその直前の数字の2つだけを足してください。"; +"PSAT_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"PSAT_INITIAL_INSTRUCTION" = "この最初の数字を覚えておいてください。"; +"PSAT_INSTRUCTION" = "この数字を直前の数字と足してください。"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@ホールペグテスト"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "このアクティビティでは、円を穴に入れる動作で上肢機能を測定します。測定は%@回行います。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "左手と右手の両方をテストします。\n円をできるだけすばやくつかんでください。穴に入れる動作を%@回繰り返したら、今度は穴から円を取り出す動作を%@回繰り返します。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "右手と左手の両方をテストします。\n円をできるだけすばやくつかんでください。穴に入れる動作を%@回繰り返したら、今度は穴から円を取り出す動作を%@回繰り返します。"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "左手で円を穴に置いてください。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "右手で円を穴に置いてください。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "左手で円を線の向こう側に置いてください。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "右手で円を線の向こう側に置いてください。"; +"HOLE_PEG_TEST_TEXT" = "2本の指で円をつまんでください。"; +"HOLE_PEG_TEST_TEXT_2" = "指で円を持ち上げて移動させ落としてください。"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "震え測定アクティビティ"; +"TREMOR_TEST_INTRO_1_DETAIL" = "このアクティビティでは、さまざまな位置で手の震えを測定します。このアクティビティが終わるまで楽な姿勢で座っていられる場所を見つけてください。"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "下の図のように、震えの大きい方の手で電話を持ってください。"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "下の図のように、右手で電話を持ってください。"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "下の図のように、左手で電話を持ってください。"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "電話を手に持って座ったまま、%@を行うように求められます。"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "1つのタスク"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "2つのタスク"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "3つのタスク"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "4つのタスク"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "5つのタスク"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "続けるには、“次へ”をタップします。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "電話を膝の上で持つ準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "左手を使って電話を膝の上で持つ準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "右手を使って電話を膝の上で持つ準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "電話を膝の上で%ld秒間持ち続けてください。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "次に、手を伸ばして電話を肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "次に、左手を伸ばして電話を肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "次に、右手を伸ばして電話を肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "手を伸ばして、%ld秒間電話を持ち続けてください。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "肘を曲げて、電話を肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "肘を曲げて、電話を左手で肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "肘を曲げて、電話を右手で肩の高さに持ってください。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "肘を曲げて%ld秒間電話を持ち続けてください。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "次に、肘を曲げて電話で繰り返し鼻に触れてください。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "次に、電話を左手に持って肘を曲げたまま、電話で繰り返し鼻に触れてください。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "次に、電話を右手に持って肘を曲げたまま、電話で繰り返し鼻に触れてください。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "電話で%ld秒間鼻に触れ続けてください。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "手首を回すように手を振る準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "電話を左手に持って手首を回すように手を振る準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "電話を右手に持って手首を回すように手を振る準備をしてください。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "%ld秒間、手を振り続けてください。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "電話を左手に持ち替えて、次のタスクに進んでください。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "電話を右手に持ち替えて、次のタスクに進んでください。"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "次のタスクに進んでください。"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "アクティビティが完了しました。"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "最初に一方の手、次に他方の手で電話を持って座ったまま、%@を行うように求められます。"; +"TREMOR_SKIP_LEFT_HAND" = "左手ではこのアクティビティができません。"; +"TREMOR_SKIP_RIGHT_HAND" = "右手ではこのアクティビティができません。"; +"TREMOR_SKIP_NEITHER" = "どちらの手でもこのアクティビティができます。"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "トレイルメイキングテスト"; +"TRAILMAKING_INTENDED_USE" = "このアクティビティでは、一連の円を順番にタップするために必要な時間を記録することで、あなたの視覚的注意力と切り替え能力を評価します。"; +"TRAILMAKING_INTENDED_USE2_A" = "カウントダウンの後、数字と文字を交互にタップしてください。最初に数字“1”をタップしてから、“2”–“3”–“4”の順にタップし、数字“7”まで続けます。"; +"TRAILMAKING_INTENDED_USE2_B" = "カウントダウンの後、数字と文字を交互にタップしてください。最初に数字“1”をタップして、文字“A”をタップしてから、“2”–“B”–“3”–“C”の順にタップし、数字“7”まで続けます。"; +"TRAILMAKING_INTRO_TEXT" = "間違えずにできるだけ速くこれを行ってください。\n "; +"TRAILMAKING_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "音声認識"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "このアクティビティは、あなたが話す音声をデバイスの下部にあるマイクで記録して、テキストに書き起こします。"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "始めるには、“開始”をタップしてください。"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "ボタンを押して、収録を開始してから、話します。"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "収録を開始"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "収録を停止"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "発音表記を編集"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "発音表記のテキストを修正して、発声内容の聞き間違いを訂正します。"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "発音表記はここに表示されます。"; +"SPEECH_RECOGNITION_FAILED" = "音声認識できませんでした。"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "音声認識を初期化できませんでした。"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "オーディオを再生"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "オーディオを停止"; +"SPEECH_IN_NOISE_TITLE" = "ノイズの中で発声"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "このアクティビティでは、雑音環境下での発声の明瞭度を測定します。"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "このテストの一環として、次のことを行います:\n\n文章を聴きます。\n\n聞こえた内容をはっきりと繰り返すか、スキップしてキーボードを使って入力します。\n\n聞こえた内容を繰り返す場合、音声認識エンジンから生成される発音表記を修正するオプションがあります。"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "音量の調整"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "“オーディオを再生”をタップして、音量を快適なレベルへ調整してから、“オーディオを停止”をタップして次に進みます。"; +"SPEECH_IN_NOISE_STEP_TITLE" = "聴く"; +"SPEECH_IN_NOISE_STEP_TEXT" = "ランダムなSN比(SNR)で背景ノイズと混ざった文章が一度だけ再生されます。"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "話す"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "聞こえた内容を繰り返します。"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "ファイルを作成できませんでした"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "しきい値に達するのに十分なログファイルを削除できませんでした"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "属性の設定中にエラーが起きました"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "ファイルが削除済みとマークされていません(アップロード済みとマークされていません)"; +"ERROR_DATALOGGER_MULTIPLE" = "ログ削除時に複数のエラー"; +"ERROR_RECORDER_NO_DATA" = "収集したデータが見つかりませんでした。"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "出力ディレクトリが指定されていません"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "騒音計"; +"ENVIRONMENTSPL_INTRO_TEXT" = "このアクティビティでは、環境の音圧レベルを測定します。ノイズレベルが高すぎる場合、アクティビティを続けることはできません。静かな場所に移動してこのタスクを完了するか、後でこのアクティビティを行ってください。"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "計算中"; +"ENVIRONMENTSPL_THRESHOLD" = "閾値: %@ dBA"; +"ENVIRONMENTSPL_OK" = "背景ノイズOK"; +"ENVIRONMENTSPL_NOISE" = "背景の雑音が多すぎます"; +"ENVIRONMENTSPL_TITLE_2" = "静かな環境を見つけてください"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "正確性を確保するため、このテストは静かな環境で実施する必要があります。"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "タスクを開始"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "データなし"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "スライダを動かして値を入力します"; +"SLIDER_I_DONT_KNOW" = "知りません"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "ページ"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "戻る"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDFサムネールを表示"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDFサムネールを非表示"; +"AX_BUTTON_ANNOTATE" = "注釈"; +"AX_BUTTON_SHOW_SEARCH" = "検索バーを表示"; +"AX_BUTTON_HIDE_SEARCH" = "検索バーを非表示"; +"AX_BUTTON_SHARE" = "共有"; + + +"AX_COMPLETION_ILLUSTRATION" = "成功を示すために青い丸の中にチェックマークがある図"; + +"AX_SIGNVIEW_LABEL" = "指定された署名フィールド"; +"AX_SIGNVIEW_HINT" = "画面をタッチしながら指を動かして署名します"; +"AX_SIGNVIEW_SIGNED" = "署名済み"; +"AX_SIGNVIEW_UNSIGNED" = "未署名"; + +"AX_SELECTED" = "選択"; +"AX_UNSELECTED" = "選択解除"; +"AX_SELECT_ALL_THAT_APPLY" = "該当するものすべてを選択してください"; + +"AX_SLIDER_LABEL" = "応答スライダ。範囲は%@から%@です"; +"AX_UNLABELED_IMAGE" = "ラベルなしイメージ"; + +"AX_ANNOUNCE_BEGIN_TASK" = "タスクを開始します"; + +"AX.MEMORY.TILE.ACTIVE" = "動いている"; +"AX.MEMORY.TILE.CORRECT" = "正解"; +"AX.MEMORY.TILE.INCORRECT" = "不正解"; +"AX.MEMORY.TILE.QUIESCENT" = "止まっている"; +"AX.MEMORY.TILE.LABEL" = "記憶ゲームタイル"; + +"AX_IMAGE_CAPTURE_LABEL" = "プレビューを取り込む"; +"AX_IMAGE_CAPTURED_LABEL" = "取り込んだイメージ"; + +"AX_VIDEO_CAPTURE_LABEL" = "ビデオ取り込みのプレビュー"; +"AX_VIDEO_CAPTURE_COMPLETE" = "ビデオの取り込みが完了しました"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "サイズ%@の円盤をサイズ%@の円盤の上に置くことはできません"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "ターゲット"; +"AX_TOWER_OF_HANOI_TOWER" = "塔"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "ダブルタップして円盤を置く"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "ダブルタップして一番上の円盤を選択"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "%@のサイズの円盤があります"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "空"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "キーボードを閉じる"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "範囲%@〜%@"; +"AX_GRAPH_STACK_PREFIX" = "次の内容のスタック:"; +"AX_GRAPH_AND_SEPARATOR" = "と"; +"AX_GRAPH_POINT_%@" = "ポイント: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "音声波形"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "録音の開始後に再度アクティベートすると録音が停止します。"; + +"AX_AUDIO_BAR_GRAPH" = "オーディオバーグラフ"; + +"AX_AMSLER_GRID_LABEL" = "アムスラーグリッド"; +"AX_AMSLER_GRID_HINT" = "指かスタイラスペンでグリッドに直接マークするか、グリッドの外を左にスワイプして終了します。"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "直接タップ可能ボタン"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "左耳用タップ"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "アクティベートしてテストを開始します。テストが始まったら、左耳で音が聞こえたらこのボタンを直接タップしてください。"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "右耳用タップ"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "アクティベートしてテストを開始します。テストが始まったら、右耳で音が聞こえたらこのボタンを直接タップしてください。"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@VoiceOverを使用して画面をタッチして、それぞれの耳用のボタンの位置を確認してください。テストが始まると、ボタンを直接タップできるようになります。%@"; +"AX_TAP_BUTTON_1_LABEL" = "1本指用タップ"; +"AX_TAP_BUTTON_2_LABEL" = "その他の指用タップ"; +"AX_TAP_BUTTON_HINT" = "このボタンを直接タップできるようにするには、アクティベートします。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@VoiceOverを使用して画面をタッチして、ボタンの位置を確認してください。ボタンを直接タップできるようにするには、いずれかのボタンをアクティブにします。"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "ボタンを直接タップできるようになりました。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@VoiceOverを使用して、ボタンを直接タップできるようになります。ボタンは画面の中央付近にあります。"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@VoiceOverを使用して、ボタンを直接タップできるようになります。"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "初期化のためのrestoreDataのデコードができません"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..1bd2fbc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ja.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d件のエラー) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.strings new file mode 100755 index 0000000..a2c002f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "동의"; +"CONSENT_NAME_GIVEN" = "이름"; +"CONSENT_NAME_FAMILY" = "성"; +"CONSENT_NAME_PLACEHOLDER" = "필요함"; +"CONSENT_REVIEW_TITLE" = "검토"; +"CONSENT_REVIEW_INSTRUCTION" = "아래 양식을 검토하고 계속할 준비가 되었으면 동의를 탭하십시오."; +"CONSENT_REVIEW_ALERT_TITLE" = "검토"; +"CONSENT_SIGNATURE_TITLE" = "서명"; +"CONSENT_SIGNATURE_INSTRUCTION" = "손가락을 사용하여 아래에 있는 상자에 서명하십시오."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "여기에 서명하기"; +"CONSENT_PAGE_NUMBER_FORMAT" = "%1$ld/%2$ld페이지"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "환영합니다."; +"CONSENT_SECTION_DATA_GATHERING" = "데이터 수집"; +"CONSENT_SECTION_PRIVACY" = "개인 정보 보호"; +"CONSENT_SECTION_DATA_USE" = "데이터 사용"; +"CONSENT_SECTION_STUDY_SURVEY" = "연구 설문"; +"CONSENT_SECTION_STUDY_TASKS" = "연구 과제"; +"CONSENT_SECTION_TIME_COMMITMENT" = "소요 시간"; +"CONSENT_SECTION_WITHDRAWING" = "철회하기"; +"CONSENT_LEARN_MORE_TITLE" = "더 알아보기"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "데이터 수집 방법에 관하여 더 알아보기"; +"LEARN_MORE_DATA_USE" = "데이터 사용 방법에 관하여 더 알아보기"; +"LEARN_MORE_PRIVACY" = "사용자의 개인 정보 및 신원 보호 방법에 관하여 더 알아보기"; +"LEARN_MORE_WELCOME" = "연구에 관하여 더 알아보기"; +"LEARN_MORE_STUDY_SURVEY" = "연구 설문에 관하여 더 알아보기"; +"LEARN_MORE_TIME_COMMITMENT" = "이 연구가 사용자의 시간에 미치는 영향에 관하여 더 알아보기"; +"LEARN_MORE_TASKS" = "관련된 과제에 관하여 더 알아보기"; +"LEARN_MORE_WITHDRAWING" = "철회하기에 관하여 더 알아보기"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "공유 옵션"; +"CONSENT_SHARE_WIDELY_%@" = "나의 데이터를 %@ 및 전세계의 인증된 연구원에게 공유"; +"CONSENT_SHARE_ONLY_%@" = "나의 데이터를 %@에게만 공유"; +"CONSENT_SHARING_DESCRIPTION_%@" = "사용자가 참여한 이 연구 조사의 데이터가 %@(으)로 보내집니다.\n\n코드화된 사용자의 연구 데이터를 더 광범위하게 공유할수록(사용자 이름 등의 정보는 제외) 현재 및 향후 실시될 연구에 도움이 됩니다."; +"LEARN_MORE_CONSENT_SHARING" = "데이터 공유에 관하여 더 알아보기"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "프린트된 이름"; +"CONSENT_DOC_LINE_SIGNATURE" = "서명"; +"CONSENT_DOC_LINE_DATE" = "날짜"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "질문 %1$@/%2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "건너뜀"; +"REVIEW_EDIT_ANSWER" = "편집"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "유효하지 않은 값"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@은(는) 최대 허용 값을 초과합니다(%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@은(는) 최소 허용 값보다 작습니다(%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@은(는) 유효한 값이 아닙니다."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "이메일 주소가 유효하지 않음: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "주소 입력"; +"LOCATION_ERROR_TITLE" = "지정된 주소를 찾을 수 없음"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "사용자의 현재 위치를 확인할 수 없습니다. 주소를 입력하거나, 가능한 경우 GPS 신호가 좋은 곳으로 위치를 이동하십시오."; +"LOCATION_ERROR_MESSAGE_DENIED" = "위치 서비스에 대한 접근이 거부되었습니다. 설정에서 위치 서비스를 사용할 수 있는 권한을 이 App에 허용하십시오."; +"LOCATION_ERROR_GEOCODE" = "입력한 주소에 대한 결과를 찾을 수 없습니다. 주소가 유효한지 확인하십시오."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "인터넷에 연결되어 있지 않거나 주소 검색을 요청할 수 있는 최대치를 초과하였습니다. 인터넷에 연결되어 있지 않으면 Wi-Fi를 켜고 질문에 답하십시오. 건너뛰기 버튼을 사용할 수 있는 경우 질문을 건너뛸 수 있습니다. 그렇지 않으면 인터넷에 연결되어 있을 때 다시 설문 조사를 재개하거나 몇 분 후에 다시 시도해 보십시오."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "텍스트 내용이 최대 길이를 초과함: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "분할된 화면에서는 카메라를 사용할 수 없습니다."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "이메일"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "암호"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "암호 입력"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "확인"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "암호 다시 입력"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "암호가 일치하지 않습니다."; +"ADDITIONAL_INFO_SECTION_TITLE" = "추가 정보"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "길동"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "홍"; +"GENDER_FORM_ITEM_TITLE" = "성별"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "성별 선택"; +"DOB_FORM_ITEM_TITLE" = "생년월일"; +"DOB_FORM_ITEM_PLACEHOLDER" = "날짜 선택"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "전화번호"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "확인"; +"VERIFICATION_STEP_TITLE" = "이메일 확인"; +"RESEND_EMAIL_LABEL_MESSAGE" = "확인 이메일을 받지 못했다면 아래 링크를 탭하여 다시 보낼 수 있습니다."; +"RESEND_EMAIL_BUTTON_TITLE" = "확인 이메일 다시 보내기"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "로그인"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "암호를 잊어버렸습니까?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "암호 입력"; +"PASSCODE_CONFIRM_MESSAGE" = "암호 확인"; +"PASSCODE_SAVED_MESSAGE" = "암호가 저장됨"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "암호가 인증됨"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "이전 암호 입력"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "새로운 암호 입력"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "새로운 암호 확인"; +"PASSCODE_INVALID_ALERT_TITLE" = "올바르지 않은 암호"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "암호가 일치하지 않습니다. 다시 시도하십시오."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Touch ID를 사용하여 인증하십시오."; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID 오류"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "숫자만 허용됩니다."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "암호 입력 진행 과정 표시기"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%2$@개 중 %1$@개의 숫자가 입력됨"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "암호를 잊어버렸습니까?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "키체인 항목을 추가할 수 없습니다."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "키체인 항목을 업데이트할 수 없습니다."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "키체인 항목을 삭제할 수 없습니다."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "키체인 항목을 찾을 수 없습니다."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "타입 I"; +"FITZPATRICK_SKIN_TYPE_II" = "타입 II"; +"FITZPATRICK_SKIN_TYPE_III" = "타입 III"; +"FITZPATRICK_SKIN_TYPE_IV" = "타입 IV"; +"FITZPATRICK_SKIN_TYPE_V" = "타입 V"; +"FITZPATRICK_SKIN_TYPE_VI" = "타입 VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "여성"; +"GENDER_MALE" = "남성"; +"GENDER_OTHER" = "기타"; + +/* Boolean answer strings */ +"BOOL_NO" = "아니요"; +"BOOL_YES" = "예"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "왼쪽"; +"LIMB_RIGHT" = "오른쪽"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "탭하여 대답하기"; +"NULL_ANSWER" = "대답 선택하기"; +"PLACEHOLDER_IMAGE_CHOICES" = "탭하여 선택하기"; +"PLACEHOLDER_LONG_TEXT" = "탭하여 쓰기"; + +/* Button titles */ +"BUTTON_AGREE" = "동의"; +"BUTTON_CANCEL" = "취소"; +"BUTTON_OK" = "확인"; +"BUTTON_CLEAR" = "지우기"; +"BUTTON_CLEAR_SIGNATURE" = "서명 지우기"; +"BUTTON_APPLY" = "적용"; +"BUTTON_DISAGREE" = "동의 안 함"; +"BUTTON_DONE" = "완료"; +"BUTTON_GET_STARTED" = "시작하기"; +"BUTTON_LEARN_MORE" = "더 알아보기"; +"BUTTON_NEXT" = "다음"; +"BUTTON_SKIP" = "건너뛰기"; +"BUTTON_SKIP_QUESTION" = "이 질문 건너뛰기"; +"BUTTON_START_TIMER" = "타이머 시작"; +"BUTTON_OPTION_SAVE" = "나중을 위해 저장"; +"BUTTON_OPTION_DISCARD" = "결과 삭제"; +"BUTTON_OPTION_STOP_TASK" = "과제 종료"; +"BUTTON_SAVE" = "저장"; +"BUTTON_CLEAR_ANSWER" = "대답 지우기"; +"BUTTON_READ_ONLY_MODE" = "이 대답을 수정할 수 없습니다."; +"BUTTON_COPYRIGHT" = "저작권"; +"BUTTON_CLOSE" = "닫기"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "실험 시작까지"; +"TASK_COMPLETE_TITLE" = "실험 완료"; +"TASK_COMPLETE_TEXT" = "데이터를 분석하여 결과가 준비되면 통보합니다."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ 남았습니다."; +"TOUCH_ANYWHERE_LABEL" = "계속하려면 아무 곳이나 터치하십시오."; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "이미지 캡처"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "이미지 다시 캡처"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "카메라를 찾을 수 없습니다. 이 단계를 완료할 수 없습니다."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "이 단계를 완료하려면 설정에서 이 App이 카메라에 접근할 수 있도록 허용하십시오."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "캡처한 이미지를 위한 출력 디렉토리가 지정되지 않았습니다."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "캡처한 이미지를 저장할 수 없습니다."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "녹화 시작"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "녹화 중단"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "비디오 다시 캡처"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "피트니스"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "거리(%@)"; +"FITNESS_HEARTRATE_TITLE" = "심박수(bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "%@ 동안 편하게 앉아 있으십시오."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "%@ 동안 최대한 빨리 걸으십시오."; +"FITNESS_INTRO_TEXT_FORMAT" = "이 실험은 사용자의 심박수를 모니터하고 %1$@ 동안 얼마나 멀리 걸을 수 있는지를 측정합니다."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "실외에서 최대한 빠른 페이스로 %1$@ 동안 걸으십시오. 걷기가 끝나면 편하게 앉아서 %2$@ 동안 휴식하십시오. 시작하려면 시작하기를 탭하십시오."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "보행 및 균형"; +"WALK_INTRO_TEXT" = "이 실험은 사용자가 걸을 때와 가만히 서 있을 때의 보행 및 균형 능력을 측정합니다. 도움 없이 안전하게 걸을 수 있는 상황이 아닌 경우 이 실험을 중단하십시오."; +"WALK_INTRO_2_TEXT_%ld" = "다른 도움 없이 일직선으로 안전하게 약 %ld보를 걸을 수 있는 장소를 찾으십시오."; +"WALK_INTRO_2_DETAIL" = "기기를 주머니 또는 가방에 넣고 오디오 지침을 따르십시오."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "이제 %@ 동안 가만히 서 있으십시오."; +"WALK_STAND_INSTRUCTION_FORMAT" = "%@ 동안 가만히 서 있으십시오."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "뒤로 돌아서 시작한 지점으로 되돌아가십시오."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "일직선으로 최대 %ld보를 걸으십시오."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "일직선으로 안전하게 왔다 갔다 할 수 있는 공간을 찾으십시오. 계속 걷다가 반환점에서 마치 원뿔형 도로 표지가 있는 것처럼 주변을 돌아서 되돌아갑니다.\n\n그런 다음, 제자리에서 한 바퀴 돌고난 후 양팔을 옆구리에 붙이고 발은 어깨너비만큼 벌린 채 서 있으십시오."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "시작할 준비가 되면 시작하기를 탭하십시오.\n그런 다음 기기를 주머니나 가방에 넣고 오디오 지침을 따르십시오."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "%@ 동안 일직선으로 왔다 갔다 걸으십시오. 평상시 걷는 것처럼 걸으면 됩니다."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "원을 그리며 돌아선 다음 %@ 동안 가만히 서 있으십시오."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "이 실험을 완료했습니다."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "탭하기 속도"; +"TAPPING_TASK_TITLE_RIGHT" = "오른손"; +"TAPPING_TASK_TITLE_LEFT" = "왼손"; +"TAPPING_INTRO_TEXT" = "이 실험은 사용자의 탭하기 속도를 측정합니다."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "기기를 평평한 표면에 두십시오."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "동일한 손의 두 손가락으로 화면의 버튼을 번갈아 탭하십시오."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "오른손의 두 손가락으로 화면의 버튼을 번갈아 탭하십시오."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "왼손의 두 손가락으로 화면의 버튼을 번갈아 탭하십시오."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "이제 오른손으로 동일한 테스트를 반복하십시오."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "이제 왼손으로 동일한 테스트를 반복하십시오."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "한 손가락을 탭하고 다른 손가락을 탭하십시오. 탭 간격이 거의 없도록 연속으로 탭하십시오. %@를 계속 탭하십시오."; +"TAPPING_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"TAPPING_CALL_TO_ACTION_NEXT" = "시작하려면 다음을 탭하십시오."; +"TAP_BUTTON_TITLE" = "탭"; +"TOTAL_TAPS_LABEL" = "탭한 총 횟수"; +"TAPPING_INSTRUCTION" = "두 손가락으로 버튼을 빠르게 연속으로 탭하십시오."; +"TAPPING_INSTRUCTION_RIGHT" = "오른손으로 버튼을 탭하십시오."; +"TAPPING_INSTRUCTION_LEFT" = "왼손으로 버튼을 탭하십시오."; +"TAPPING_SKIP_TITLE" = "이 손 건너뛰기"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "암슬러 격자"; +"AMSLER_GRID_INTRO_TEXT" = "이 실험은 사용자의 시각에 문제가 있는지 감지할 수 있습니다."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "실험하는 동안 기기를 얼굴에서 약 30cm 정도 떨어진 거리에서 눈높이에 맞춰 유지하십시오."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "%@을(를) 감고 정사각형 격자 가운데 있는 점을 응시합니다.\n\n손가락이나 스타일러스를 사용하여 흐릿한 선이나 물결선 같은 왜곡된 부분을 모두 표시하십시오.\n\n모두 완료하면 격자 바깥을 왼쪽으로 쓸어 넘기십시오."; +"AMSLER_GRID_LEFT_EYE" = "왼쪽 눈"; +"AMSLER_GRID_RIGHT_EYE" = "오른쪽 눈"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "음성"; +"AUDIO_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"AUDIO_INSTRUCTION" = "마이크에 대고 최대한 길게 ‘아’하고 말하십시오."; +"AUDIO_INTRO_TEXT" = "숨을 크게 들이쉰 다음 마이크에 대고 최대한 길게 ‘아’하고 말하십시오. 오디오 막대가 파란색으로 지속되도록 발성 음량을 꾸준하게 유지하십시오."; +"AUDIO_INTENDED_USE" = "이 실험은 기기 하단에 있는 마이크로 목소리를 녹음하여 사용자의 음성을 평가합니다."; +"AUDIO_TOO_LOUD_LABEL" = "소리가 너무 큼"; +"AUDIO_GENERIC_ERROR_LABEL" = "오디오를 녹음할 수 없습니다."; +"AUDIO_LEVEL_CHECK_LABEL" = "주변 소음 단계를 측정하는 동안 기다리십시오."; +"AUDIO_TOO_LOUD_MESSAGE" = "음성을 녹음하기에 주변 소음이 너무 큽니다. 좀 더 조용한 장소로 이동한 다음 다시 시도하십시오."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "준비되면 다음을 탭하십시오."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "순음 청력 검사"; +"TONE_AUDIOMETRY_INTENDED_USE" = "이 실험은 소리를 구별할 수 있는 사용자의 능력을 측정합니다."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "시작하기 전에 헤드폰을 연결하고 착용하십시오.\n\n일반적인 알림 소리와 달리 소리가 매우 미묘합니다. 부드러운 소리로 시작해서 점차 볼륨이 커집니다. 주의를 기울이고 소리가 들리는 쪽에 맞춰 왼쪽 또는 오른쪽 버튼을 탭하십시오."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"TONE_AUDIOMETRY_PREP_TEXT" = "이제 소리가 들립니다. 기기 측면에 있는 제어기를 사용하여 음량을 조절하십시오.\n\n시작할 준비가 되었으면 아무 버튼이나 탭하십시오."; +"TONE_AUDIOMETRY_INSTRUCTION" = "소리가 들리면, 소리가 들리는 쪽에 맞춰 왼쪽 또는 오른쪽 버튼을 탭하십시오"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "왼쪽 귀"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "오른쪽 귀"; +"TONE_LABEL_%@_LEFT" = "%@Hz, 왼쪽"; +"TONE_LABEL_%@_RIGHT" = "%@Hz, 오른쪽"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "순음 청력 검사"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "소리가 들리면 탭하십시오."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "소리 및 음량"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "일련의 소리를 듣게 됩니다."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "소리가 들리면 버튼을 탭하십시오."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "이 테스트에서는 음량이 50퍼센트로 설정됩니다."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "이 테스트는 10분 정도 소요됩니다."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "테스트가 중단되는 것을 방지하기 위해 방해금지 모드를 켜십시오."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "먼저 오른쪽 귀에서 소리를 재생합니다."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "이제 왼쪽 귀에서 소리를 재생합니다."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "이 실험은 개인의 청각 임계 기준을 dB HL 등급으로 확인합니다."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "기기 음량을 최대로 설정했는지 확인하십시오.\n\n이 실험을 진행하는 동안 감지하기 힘든 소리가 왼쪽 귀나 오른쪽 귀에 각각 재생됩니다.\n\n잘 듣고 소리가 들릴 때마다 버튼을 탭하십시오."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "이 테스트에서는 사용자가 소리를 듣기 위해 필요한 음량을 파악합니다."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "사전 설문 사항."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "'더 잘 들리는 귀'가 있는 경우 선호하는 귀를 선택하십시오."; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "왼쪽"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "오른쪽"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "선호하는 쪽 없음"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "테스트가 취소됨"; +"dBHL_ALERT_TITLE_START_OVER" = "다시 시작"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "테스트 취소"; +"dBHL_ALERT_TEXT" = "이 테스트를 실시하려면 AirPods 또는 EarPods를 다시 연결하십시오."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ 완료"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "헤드폰"; +"HEADPHONES_UNKNOWN" = "알 수 없음"; +"HEADPHONES_NONE" = "없음"; +"CONNECTED" = "연결됨"; +"NOT_CONNECTED" = "연결 안 됨"; +"HEADPHONE_CONNECTED_%@" = "연결됨 - %@"; +"HEADPHONE_DETECT_TITLE" = "헤드폰에 연결"; +"HEADPHONE_DETECT_TEXT" = "이 테스트는 Apple AirPods 또는 Apple EarPods이 필요합니다."; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "공간 기억"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "이 실험은 %@에 불이 들어오는 순서를 반복하도록 하여 사용자의 단기 공간 기억 능력을 측정합니다."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "꽃"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "꽃"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "일부 %@에 한 번에 하나씩 불이 들어옵니다. 이 %@을(를) 불이 들어온 순서와 같은 순서로 탭하십시오."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "일부 %@에 한 번에 하나씩 불이 들어옵니다. 이 %@을(를) 불이 들어온 순서와 반대로 탭하십시오."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "시작하려면 시작하기를 탭한 다음 주의깊게 보십시오."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "점수"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "%@에 불이 들어오는 것을 잘 보십시오."; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "%@을(를) 불이 들어온 순서대로 탭하십시오"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "%@을(를) 반대 순서대로 탭하십시오."; +"MEMORY_GAME_COMPLETE_TITLE" = "순서 완료"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "계속하려면 다음을 탭하십시오."; +"MEMORY_GAME_FAILED_TITLE" = "다시 시도"; +"MEMORY_GAME_FAILED_MESSAGE" = "이번에는 성공적으로 완료하지 못했습니다. 계속하려면 다음을 탭하십시오."; +"MEMORY_GAME_TIMEOUT_TITLE" = "제한 시간 도달"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "시간이 초과되었습니다.\n계속하려면 다음을 탭하십시오."; +"MEMORY_GAME_COMPLETE" = "게임 종료"; +"MEMORY_GAME_PAUSED_TITLE" = "일시 정지됨"; +"MEMORY_GAME_PAUSED_MESSAGE" = "계속하려면 다음을 탭하십시오."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "기억 실험은 캘리포니아 대학교 샌프란시스코의 Katherine Possin 박사와 Joel Kramer 박사의 도움으로 개발되었습니다."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "반응 시간"; +"REACTION_TIME_TASK_INTENDED_USE" = "이 실험은 시각 신호에 대한 사용자의 반응 시간을 평가합니다."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "파란 점이 화면에 나타나면 방향에 상관없이 즉시 기기를 흔드십시오. 이 동작을 %D번 해야 합니다."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "%@/%@ 시도"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "파란 원이 나타나면 재빨리 기기를 흔드십시오."; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "스트루프"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "단어가 나타나면, 단어에 칠해진 색상 이름의 첫 번째 글자를 선택하십시오."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "스트루프 실험을 시작할 준비가 되면 시작하기를 탭하십시오."; +"STROOP_TASK_STEP_TEXT" = "표시된 색상을 뜻하는 단어의 첫 번째 글자를 선택하십시오."; +"STROOP_COLOR_RED" = "빨강"; +"STROOP_COLOR_GREEN" = "초록"; +"STROOP_COLOR_BLUE" = "파랑"; +"STROOP_COLOR_YELLOW" = "노랑"; +"STROOP_COLOR_RED_INITIAL" = "빨"; +"STROOP_COLOR_GREEN_INITIAL" = "초"; +"STROOP_COLOR_BLUE_INITIAL" = "파"; +"STROOP_COLOR_YELLOW_INITIAL" = "노"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "하노이의 탑"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "이 실험은 사용자의 퍼즐 푸는 능력을 평가합니다."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "아래 스택 전체를 최대한 적게 이동하여 하이라이트된 플랫폼으로 옮기십시오."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "퍼즐을 푸십시오."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "이동 횟수: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "이 퍼즐을 풀 수 없습니다."; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "가동 범위"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption은 왼쪽 또는 오른쪽이어야 합니다."; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "왼쪽 무릎 관절 가동 범위"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "오른쪽 무릎 관절 가동 범위"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "이 실험에서는 사용자가 왼쪽 무릎을 얼마나 펼 수 있는지 측정합니다."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "이 실험에서는 사용자가 오른쪽 무릎을 얼마나 펼 수 있는지 측정합니다."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "의자 가장자리에 앉으십시오. 실험을 시작하면 측정을 위해 기기를 왼쪽 무릎에 놓아두게 됩니다. 지침을 들을 수 있도록 기기 사운드를 켜두십시오."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "의자 가장자리에 앉으십시오. 실험을 시작하면 측정을 위해 기기를 오른쪽 무릎에 놓아두게 됩니다. 지침을 들을 수 있도록 기기 사운드를 켜두십시오."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "그림에 표시된 대로 화면을 위로 향하게 한 채로 기기를 왼쪽 무릎 위에 놓으십시오."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "그림에 표시된 대로 화면을 위로 향하게 한 채로 기기를 오른쪽 무릎 위에 놓으십시오."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "준비가 되면 화면을 탭하여 시작한 다음 왼쪽 무릎을 최대한 많이 폅니다. 완료하면 시작 위치로 되돌리고 다시 탭하십시오."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "준비가 되면 화면을 탭하여 시작한 다음 오른쪽 무릎을 최대한 많이 폅니다. 완료하면 시작 위치로 되돌린 다음 다시 탭하십시오."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "기기를 왼쪽 무릎 위에 놓으십시오. 화면을 탭하고 왼쪽 무릎을 최대한 많이 폅니다."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "기기를 오른쪽 무릎 위에 놓으십시오. 화면을 탭하고 오른쪽 무릎을 최대한 많이 폅니다."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "완료하면 왼쪽 무릎을 시작했던 위치로 되돌린 다음 아무 곳이나 탭하십시오."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "완료하면 오른쪽 무릎을 시작했던 위치로 되돌린 다음 아무 곳이나 탭하십시오."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "왼쪽 어깨 관절 가동 범위"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "오른쪽 어깨 관절 가동 범위"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "이 실험에서는 사용자가 왼쪽 어깨를 얼마나 펼 수 있는지 측정합니다."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "이 실험에서는 사용자가 오른쪽 어깨를 얼마나 펼 수 있는지 측정합니다."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "실험을 시작하면 측정을 위해 기기를 왼쪽 어깨에 놓아두게 됩니다. 지침을 들을 수 있도록 기기 사운드를 켜두십시오."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "실험을 시작하면 측정을 위해 기기를 오른쪽 어깨에 놓아두게 됩니다. 지침을 들을 수 있도록 기기 사운드를 켜두십시오."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "그림에 표시된 대로 화면을 위로 향하게 한 채로 기기를 왼쪽 어깨 위에 놓으십시오."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "그림에 표시된 대로 화면을 위로 향하게 한 채로 기기를 오른쪽 어깨 위에 놓으십시오."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "준비가 되면 화면을 탭하여 시작한 다음 왼쪽 팔을 최대한 많이 들어 올립니다. 완료하면 시작 위치로 되돌리고 다시 탭하십시오."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "준비가 되면 화면을 탭하여 시작한 다음 오른쪽 팔을 최대한 많이 들어 올립니다. 완료하면 시작 위치로 되돌리고 다시 탭하십시오."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "기기를 왼쪽 어깨 위에 놓으십시오. 화면을 탭하고 왼쪽 팔을 최대한 앞으로 들어 올립니다."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "기기를 오른쪽 어깨 위에 놓으십시오. 화면을 탭하고 오른쪽 팔을 최대한 앞으로 들어 올립니다."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "완료하면 왼쪽 팔을 시작했던 위치로 되돌린 다음 아무 곳이나 탭하십시오."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "완료하면 오른쪽 팔을 시작했던 위치로 되돌린 다음 아무 곳이나 탭하십시오."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "보행 테스트"; +"TIMED_WALK_INTRO_DETAIL" = "이 실험은 사용자의 하지 기능을 측정합니다."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "되도록 실외로 장소를 골라서 안전하면서도 최대한 빨리 일직선으로 약 %@를 걸으십시오. 결승선을 지나기 전에는 속도를 늦추지 마십시오."; +"TIMED_WALK_INTRO_2_DETAIL" = "시작하려면 다음을 탭하십시오."; +"TIMED_WALK_FORM_TITLE" = "보조 기구"; +"TIMED_WALK_FORM_TEXT" = "매 테스트에 동일한 보조 기구를 사용하십시오."; +"TIMED_WALK_QUESTION_TEXT" = "단하지 보조기를 착용하십니까?"; +"TIMED_WALK_QUESTION_2_TITLE" = "보조 기구를 사용하십니까?"; +"TIMED_WALK_QUESTION_2_TEXT" = "여기를 탭하여 대답을 선택하십시오."; +"TIMED_WALK_QUESTION_2_CHOICE" = "없음"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "편측 지팡이"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "편측 목발"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "양측 지팡이"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "양측 목발"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "워커/롤레이터"; +"TIMED_WALK_INSTRUCTION_%@" = "일직선으로 %@까지 걸으십시오."; +"TIMED_WALK_INSTRUCTION_TURN" = "뒤로 도십시오."; +"TIMED_WALK_INSTRUCTION_2" = "시작 지점으로 돌아가십시오."; +"TIMED_WALK_INSTRUCTION_TEXT" = "완료하면 다음을 탭하십시오."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT 테스트(Paced Auditory Serial Addition Test)는 사용자의 청각 정보 처리 속도 및 계산 능력을 측정합니다."; +"PVSAT_INTRO_TEXT" = "PVSAT 테스트(Paced Visual Serial Addition Test)는 사용자의 시각 정보 처리 속도 및 계산 능력을 측정합니다."; +"PAVSAT_INTRO_TEXT" = "PAVSAT 테스트(Paced Auditory and Visual Serial Addition Test)는 사용자의 청각 및 시각 정보 처리 속도 및 계산 능력을 측정합니다."; +"PSAT_INTRO_TEXT_2_%@" = "한 자릿수의 숫자가 %@마다 제시됩니다.\n새로운 숫자가 제시될 때마다 직전에 제시된 숫자에 더하십시오.\n총 누계를 계산하지 않도록 주의하십시오. 직전에 제시된 두 개의 숫자만 더하십시오."; +"PSAT_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"PSAT_INITIAL_INSTRUCTION" = "아래 첫 번째 숫자를 기억하십시오."; +"PSAT_INSTRUCTION" = "아래 새로운 숫자를 이전 숫자에 더하십시오."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-홀 페그 테스트"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "이 실험은 페그를 구멍에 넣는 동작을 통해 사용자의 상지 기능을 측정합니다. 이 동작을 %@번 해야 합니다."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "왼손과 오른손을 모두 테스트합니다.\n페그를 최대한 빨리 집어서 구멍에 넣으십시오. 이 동작을 %@번 완료하면, 페그를 제거하는 동작을 다시 %@번 하십시오."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "오른손과 왼손을 모두 테스트합니다.\n페그를 최대한 빨리 집어서 구멍에 넣으십시오. 이 동작을 %@번 완료하면, 페그를 제거하는 동작을 다시 %@번 하십시오."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "왼손을 사용하여 페그를 구멍에 넣으십시오."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "오른손을 사용하여 페그를 구멍에 넣으십시오."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "왼손을 사용하여 페그를 선 뒤에 놓으십시오."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "오른손을 사용하여 페그를 선 뒤에 놓으십시오."; +"HOLE_PEG_TEST_TEXT" = "두 손가락을 사용하여 페그를 집으십시오."; +"HOLE_PEG_TEST_TEXT_2" = "손가락을 떼어서 페그를 내려놓으십시오."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "손떨림 실험"; +"TREMOR_TEST_INTRO_1_DETAIL" = "이 실험은 여러 가지 상황에서 손떨림 정도를 측정합니다. 이 실험을 위해 편안하게 앉아있을 수 있는 장소로 이동하십시오."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "아래 그림처럼 전화기를 더 자주 사용하는 손에 들고 있으십시오."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "아래 그림처럼 전화기를 오른손에 들고 있으십시오."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "아래 그림처럼 전화기를 왼손에 들고 있으십시오."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "전화를 손에 든 채로 앉아있는 동안 %@를 수행해야 합니다."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "한 건의 과제"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "두 건의 과제"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "세 건의 과제"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "네 건의 과제"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "다섯 건의 과제"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "다음을 탭하여 계속합니다."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "전화기를 무릎에 두는 동작을 준비하십시오."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "왼손으로 전화기를 쥐고 무릎에 두는 동작을 준비하십시오."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "오른손으로 전화기를 쥐고 무릎에 두는 동작을 준비하십시오."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "전화기를 %ld초 동안 무릎에 두십시오."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "이제 전화기를 어깨 높이로 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "이제 전화기를 왼손에 어깨 높이로 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "이제 전화기를 오른손에 어깨 높이로 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "%ld초 동안 손을 내민 채로 전화기를 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "이제 팔꿈치를 굽히고 전화기를 어깨 높이에 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "이제 왼쪽 팔꿈치를 굽히고 왼손으로 전화기를 어깨 높이에 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "이제 오른쪽 팔꿈치를 굽히고 오른손으로 전화기를 어깨 높이에 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "%ld초 동안 팔꿈치를 굽힌 채로 전화기를 들고 있으십시오."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "이제 팔꿈치를 굽히고 전화기를 코에 반복적으로 대십시오."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "이제 왼쪽 팔꿈치를 굽히고 왼손으로 전화기를 든 다음 전화기를 코에 반복적으로 대십시오."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "이제 오른쪽 팔꿈치를 굽히고 오른손으로 전화기를 든 다음 전화기를 코에 반복적으로 대십시오."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "전화기를 %ld초 동안 코에 반복적으로 대십시오."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "반짝반짝 율동을 취할 준비를 하십시오."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "왼손으로 전화기를 들고 반짝반짝 율동을 취할 준비를 하십시오."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "오른손으로 전화기를 들고 반짝반짝 율동을 취할 준비를 하십시오."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "%ld초 동안 반짝반짝 율동을 수행하십시오."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "이제 전화기를 왼손으로 바꿔 들고 다음 과제를 진행하십시오."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "이제 전화기를 오른손으로 바꿔 들고 다음 과제를 진행하십시오."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "다음 과제를 진행합니다."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "실험이 완료되었습니다."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "전화를 한 손에 먼저 들었다가 다른 손으로 들면서 %@를 수행해야 합니다."; +"TREMOR_SKIP_LEFT_HAND" = "저는 이 과제를 왼손으로 수행할 수 없습니다."; +"TREMOR_SKIP_RIGHT_HAND" = "저는 이 과제를 오른손으로 수행할 수 없습니다."; +"TREMOR_SKIP_NEITHER" = "저는 이 과제를 양손으로 수행할 수 있습니다."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "선로 잇기 검사"; +"TRAILMAKING_INTENDED_USE" = "이 실험은 여러 개의 점을 순서대로 탭하는 데 들인 시간을 기록하여 사용자의 시각적 주의력과 과제 전환 능력을 평가합니다."; +"TRAILMAKING_INTENDED_USE2_A" = "카운트다운이 지나면 숫자와 한글 자음을 순서대로 연결하십시오. 숫자 1을 먼저 탭하여 시작합니다. 그런 다음 숫자 7에 도달할 때까지 2 – 3 – 4의 순서대로 탭하십시오."; +"TRAILMAKING_INTENDED_USE2_B" = "카운트다운이 지나면 숫자와 한글 자음을 순서대로 연결하십시오. 먼저 숫자 1을 탭하여 시작한 다음, 자음 ㄱ을 탭합니다. 그런 다음 숫자 7에 도달할 때까지 2 – ㄴ – 3 – ㄷ의 순서대로 탭하십시오."; +"TRAILMAKING_INTRO_TEXT" = "실수 없이 최대한 빠르게 해보십시오. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"TRAILMAKING_LETTER_A" = "ㄱ"; +"TRAILMAKING_LETTER_B" = "ㄴ"; +"TRAILMAKING_LETTER_C" = "ㄷ"; +"TRAILMAKING_LETTER_D" = "ㄹ"; +"TRAILMAKING_LETTER_E" = "ㅁ"; +"TRAILMAKING_LETTER_F" = "ㅂ"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "음성 인식"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "이 실험은 기기 하단에 있는 마이크로 사용자의 음성을 녹음하여 텍스트로 변환합니다."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "시작하려면 시작하기를 탭하십시오."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "말하기 전에 녹음 시작을 위해 버튼을 누르십시오."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "녹음 시작"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "녹음 중단"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "음성 기록 편집"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "음성이 제대로 변환되지 않은 텍스트를 올바르게 수정하십시오."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "음성 기록이 여기에 나타납니다."; +"SPEECH_RECOGNITION_FAILED" = "음성 인식에 실패했습니다."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "음성 인식 초기화에 실패했습니다."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "오디오 재생"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "오디오 중단"; +"SPEECH_IN_NOISE_TITLE" = "시끄러운 환경에서 말하기"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "이 실험은 시끄러운 환경에서 음성의 명확성을 측정합니다."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "이 테스트의 일환으로 다음 단계를 진행하게 됩니다.\n\n문장을 듣습니다.\n\n들은 문장을 분명하게 따라 말하거나 건너 뛰고 키보드로 들은 문장을 입력합니다. \n\n문장을 따라 말한 경우 음성 인식 엔진에 의해 생성된 기록을 수정할 수 있습니다."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "음량 보정"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "'오디오 재생'을 탭하고 편안하게 들릴 때까지 음량을 조절한 다음 '오디오 중단'을 탭하여 진행하십시오."; +"SPEECH_IN_NOISE_STEP_TITLE" = "듣기"; +"SPEECH_IN_NOISE_STEP_TEXT" = "무작위의 SNR(신호 대 잡음비)로 주변의 소음이 혼합된 문장이 한 번만 재생됩니다."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "말하기"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "들은 대로 따라 말하십시오."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "파일을 생성할 수 없습니다."; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "임계값에 이르기 위한 충분한 수의 로그 파일을 제거하는 데 실패했습니다."; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "속성 설정 오류"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "삭제로 표시되지 않은 파일(업로드됨으로 표시되지 않음)"; +"ERROR_DATALOGGER_MULTIPLE" = "로그 제거 중에 여러 개의 오류 발생"; +"ERROR_RECORDER_NO_DATA" = "수집된 데이터를 찾을 수 없습니다."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "지정된 출력 디렉토리 없음"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL 측정기"; +"ENVIRONMENTSPL_INTRO_TEXT" = "이 실험은 주변 환경의 음압 레벨을 측정합니다. 주변의 소음이 너무 큰 경우 진행할 수 없습니다. 좀 더 조용한 장소로 이동하여 이 실험을 완료하거나 나중에 이 실험을 다시 진행하십시오."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "계산 중"; +"ENVIRONMENTSPL_THRESHOLD" = "임계값: %@dBA"; +"ENVIRONMENTSPL_OK" = "주변 소음 양호함"; +"ENVIRONMENTSPL_NOISE" = "주변 소음이 너무 큼"; +"ENVIRONMENTSPL_TITLE_2" = "조용한 장소 찾기"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "이 테스트는 정확성을 높이기 위해 조용한 환경에서 진행해야 합니다."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "과제 시작"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "데이터 없음"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "슬라이더를 이동하여 값 입력"; +"SLIDER_I_DONT_KNOW" = "모르겠음"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "페이지"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "뒤로"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDF 축소판 보기"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDF 축소판 가리기"; +"AX_BUTTON_ANNOTATE" = "주석"; +"AX_BUTTON_SHOW_SEARCH" = "검색 막대 보기"; +"AX_BUTTON_HIDE_SEARCH" = "검색 막대 가리기"; +"AX_BUTTON_SHARE" = "공유"; + + +"AX_COMPLETION_ILLUSTRATION" = "전송 성공을 나타내는 파란색 원 안의 체크표시 그림"; + +"AX_SIGNVIEW_LABEL" = "지정된 서명 필드"; +"AX_SIGNVIEW_HINT" = "화면을 터치하고 손가락을 움직여서 서명하십시오."; +"AX_SIGNVIEW_SIGNED" = "서명됨"; +"AX_SIGNVIEW_UNSIGNED" = "서명 안 됨"; + +"AX_SELECTED" = "선택됨"; +"AX_UNSELECTED" = "선택 안 됨"; +"AX_SELECT_ALL_THAT_APPLY" = "해당되는 사항은 모두 선택하십시오."; + +"AX_SLIDER_LABEL" = "응답 슬라이더. %@에서 %@까지의 범위"; +"AX_UNLABELED_IMAGE" = "꼬리표 없는 이미지"; + +"AX_ANNOUNCE_BEGIN_TASK" = "과제 시작"; + +"AX.MEMORY.TILE.ACTIVE" = "활동"; +"AX.MEMORY.TILE.CORRECT" = "맞음"; +"AX.MEMORY.TILE.INCORRECT" = "틀림"; +"AX.MEMORY.TILE.QUIESCENT" = "대기"; +"AX.MEMORY.TILE.LABEL" = "메모리 게임 타일"; + +"AX_IMAGE_CAPTURE_LABEL" = "캡처 미리보기"; +"AX_IMAGE_CAPTURED_LABEL" = "캡처된 이미지"; + +"AX_VIDEO_CAPTURE_LABEL" = "비디오 캡처 미리보기"; +"AX_VIDEO_CAPTURE_COMPLETE" = "비디오 캡처 완료"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "크기가 %@인 디스크를 크기가 %@인 디스크 위에 놓을 수 없습니다."; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "대상"; +"AX_TOWER_OF_HANOI_TOWER" = "탑"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "디스크를 놓으려면 이중 탭하십시오."; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "가장 위에 있는 디스크를 선택하려면 이중 탭하십시오."; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "%@ 크기의 디스크가 있음"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "비어 있음"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "키보드 닫기"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "%@에서 %@까지의 범위"; +"AX_GRAPH_STACK_PREFIX" = "다음으로 구성된 스택"; +"AX_GRAPH_AND_SEPARATOR" = " 및 "; +"AX_GRAPH_POINT_%@" = "포인트: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "음성 파형"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "녹음을 시작한 후 다시 활성화하면 녹음이 중단됩니다."; + +"AX_AUDIO_BAR_GRAPH" = "오디오 막대 그래프"; + +"AX_AMSLER_GRID_LABEL" = "암슬러 격자"; +"AX_AMSLER_GRID_HINT" = "격자에 직접 표시하려면 손가락이나 스타일러스를 사용하고, 완료하려면 격자 바깥을 왼쪽으로 쓸어 넘기십시오."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "탭할 수 있는 버튼"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "왼쪽 귀를 위한 탭"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "테스트를 시작하려면 활성화하십시오. 테스트가 시작되면 왼쪽 귀에 소리가 들리는 경우 이 버튼을 직접 탭하십시오."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "오른쪽 귀를 위한 탭"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "테스트를 시작하려면 활성화하십시오. 테스트가 시작되면 오른쪽 귀에 소리가 들리는 경우 이 버튼을 직접 탭하십시오."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ VoiceOver를 사용하여 화면을 터치하고 탐색하여 양쪽 귀와 연결된 각각의 버튼이 어디에 있는지 파악합니다. 테스트가 시작되면 버튼을 직접 탭할 수 있습니다. %@"; +"AX_TAP_BUTTON_1_LABEL" = "한 손가락으로 탭하기"; +"AX_TAP_BUTTON_2_LABEL" = "다른 손가락으로 탭하기"; +"AX_TAP_BUTTON_HINT" = "버튼을 직접 탭할 수 있도록 하려면 활성화하십시오."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ VoiceOver를 사용하여 화면을 터치하고 탐색하여 버튼이 어디에 있는지 파악합니다. 버튼을 직접 탭할 수 있도록 하려면 버튼을 각각 활성화하십시오."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "이제 버튼을 직접 탭할 수 있습니다."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ VoiceOver를 사용하여 버튼을 직접 탭할 수 있으며, 탭은 화면의 중앙 근처에 위치합니다."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ VoiceOver를 사용하여 테스트 중에 버튼을 직접 탭할 수 있습니다."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "초기화를 위한 restoreData 디코딩을 할 수 없음"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..f98de92 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ko.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d개의 오류) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.strings new file mode 100755 index 0000000..b9aac9a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Keizinan"; +"CONSENT_NAME_GIVEN" = "Nama Pertama"; +"CONSENT_NAME_FAMILY" = "Nama Akhir"; +"CONSENT_NAME_PLACEHOLDER" = "Diperlukan"; +"CONSENT_REVIEW_TITLE" = "Semak"; +"CONSENT_REVIEW_INSTRUCTION" = "Semak borang di bawah dan ketik Setuju jika anda bersedia untuk meneruskan."; +"CONSENT_REVIEW_ALERT_TITLE" = "Semak"; +"CONSENT_SIGNATURE_TITLE" = "Tandatangan"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Sila tandatangan menggunakan jari anda dalam kotak di bawah."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Tandatangan Di Sini"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Halaman %1$ld daripada %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Selamat Datang"; +"CONSENT_SECTION_DATA_GATHERING" = "Pengumpulan Data"; +"CONSENT_SECTION_PRIVACY" = "Privasi"; +"CONSENT_SECTION_DATA_USE" = "Penggunaan Data"; +"CONSENT_SECTION_STUDY_SURVEY" = "Tinjauan Kajian"; +"CONSENT_SECTION_STUDY_TASKS" = "Tugas Kajian"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Komitmen Masa"; +"CONSENT_SECTION_WITHDRAWING" = "Menarik Diri"; +"CONSENT_LEARN_MORE_TITLE" = "Ketahui Lebih Lanjut"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Ketahui lebih lanjut tentang cara data dikumpulkan"; +"LEARN_MORE_DATA_USE" = "Ketahui lebih lanjut tentang cara data digunakan"; +"LEARN_MORE_PRIVACY" = "Ketahui lebih lanjut tentang cara privasi dan identiti anda dilindungi"; +"LEARN_MORE_WELCOME" = "Ketahui lebih lanjut tentang kajian terlebih dahulu"; +"LEARN_MORE_STUDY_SURVEY" = "Ketahui lebih lanjut tentang tinjauan kajian"; +"LEARN_MORE_TIME_COMMITMENT" = "Ketahui lebih lanjut tentang impak kajian pada masa anda"; +"LEARN_MORE_TASKS" = "Ketahui lebih lanjut tentang tugas yang terlibat"; +"LEARN_MORE_WITHDRAWING" = "Ketahui lebih lanjut tentang menarik diri"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Pilihan Perkongsian"; +"CONSENT_SHARE_WIDELY_%@" = "Kongsi data saya dengan %@ dan penyelidik yang layak di seluruh dunia"; +"CONSENT_SHARE_ONLY_%@" = "Kongsi data saya dengan %@ sahaja"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ akan menerima data kajian anda daripada penyertaan anda dalam kajian ini.\n\nBerkongsi data kajian berkod anda dengan lebih luas (tanpa maklumat seperti nama anda) mungkin memberi manfaat kepada penyelidikan ini dan penyelidikan masa hadapan."; +"LEARN_MORE_CONSENT_SHARING" = "Ketahui lebih lanjut tentang perkongsian data"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nama Bercetak"; +"CONSENT_DOC_LINE_SIGNATURE" = "Tandatangan"; +"CONSENT_DOC_LINE_DATE" = "Tarikh"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ daripada %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Soalan %1$@ daripada %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Dilangkau"; +"REVIEW_EDIT_ANSWER" = "Edit"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Nilai tidak sah"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ melebihi nilai maksimum yang dibenarkan (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ kurang daripada nilai minimum yang dibenarkan (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ bukan nilai yang sah."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Alamat e-mel tidak sah: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Masukkan alamat"; +"LOCATION_ERROR_TITLE" = "Tidak Menemui Alamat yang Ditentukan"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Gagal menentukan lokasi semasa anda. Sila taipkan alamat atau pergi ke lokasi dengan isyarat GPS yang lebih baik jika berkenaan."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Akses kepada perkhidmatan lokasi telah ditolak. Sila berikan app ini keizinan untuk menggunakan perkhidmatan lokasi menerusi Seting."; +"LOCATION_ERROR_GEOCODE" = "Gagal mencari hasil untuk alamat yang dimasukkan. Sila pastikan alamat adalah sah."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Sama ada anda tidak disambungkan ke internet atau anda telah melebihi bilangan maksimum permintaan carian alamat. Jika anda tidak disambungkan ke internet, sila aktifkan Wi-Fi anda untuk menjawab soalan ini, langkau soalan ini jika butang langkau tersedia, atau kembali ke tinjauan apabila anda disambungkan ke internet. Sebaliknya, sila cuba lagi dalam masa beberapa minit."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Kandungan teks melebihi panjang maksimum: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera tidak tersedia dalam skrin terpisah."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mel"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Kata Laluan"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Masukkan kata laluan"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Sahkan"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Masukkan kata laluan sekali lagi"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Kata laluan tidak sepadan."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Maklumat Tambahan"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Jantina"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Pilih jantina"; +"DOB_FORM_ITEM_TITLE" = "Tarikh Lahir"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Pilih tarikh"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Nombor Telefon"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Pengesahan"; +"VERIFICATION_STEP_TITLE" = "Sahkan E-mel anda"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Ketik pautan di bawah jika anda tidak menerima e-mel pengesahan dan mahu e-mel tersebut dihantar sekali lagi."; +"RESEND_EMAIL_BUTTON_TITLE" = "Hantar Semula E-mel Pengesahan"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Log Masuk"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Terlupa kata laluan?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Masukkan kod laluan"; +"PASSCODE_CONFIRM_MESSAGE" = "Sahkan kod laluan"; +"PASSCODE_SAVED_MESSAGE" = "Kod laluan disimpan"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kod laluan disahkan"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Masukkan kod laluan lama anda"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Masukkan kod laluan baru anda"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Sahkan kod laluan baru anda"; +"PASSCODE_INVALID_ALERT_TITLE" = "Kod Laluan Salah"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Kod laluan tidak sepadan. Cuba lagi."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Sila sahkan menggunakan Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Ralat Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Hanya aksara angka dibenarkan."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Penunjuk kemajuan entri kod laluan"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ daripada %@ digit dimasukkan"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Terlupa Kod Laluan?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Tidak dapat menambah item Rantai Kunci."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Tidak dapat mengemas kini item Rantai Kunci."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Tidak dapat memadamkan item Rantai Kunci."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Tidak dapat mencari item Rantai Kunci."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Jenis I"; +"FITZPATRICK_SKIN_TYPE_II" = "Jenis II"; +"FITZPATRICK_SKIN_TYPE_III" = "Jenis III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Jenis IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Jenis V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Jenis VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Wanita"; +"GENDER_MALE" = "Lelaki"; +"GENDER_OTHER" = "Lain"; + +/* Boolean answer strings */ +"BOOL_NO" = "Tidak"; +"BOOL_YES" = "Ya"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ka"; +"MEASURING_UNIT_IN" = "inci"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "kiri"; +"LIMB_RIGHT" = "kanan"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Ketik untuk jawab"; +"NULL_ANSWER" = "Pilih jawapan"; +"PLACEHOLDER_IMAGE_CHOICES" = "Ketik untuk pilih"; +"PLACEHOLDER_LONG_TEXT" = "Ketik untuk tulis"; + +/* Button titles */ +"BUTTON_AGREE" = "Setuju"; +"BUTTON_CANCEL" = "Batal"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Kosongkan"; +"BUTTON_CLEAR_SIGNATURE" = "Kosongkan Tandatangan"; +"BUTTON_APPLY" = "Guna"; +"BUTTON_DISAGREE" = "Tidak Setuju"; +"BUTTON_DONE" = "Selesai"; +"BUTTON_GET_STARTED" = "Mulakan"; +"BUTTON_LEARN_MORE" = "Ketahui lebih lanjut"; +"BUTTON_NEXT" = "Seterusnya"; +"BUTTON_SKIP" = "Langkau"; +"BUTTON_SKIP_QUESTION" = "Langkau soalan ini"; +"BUTTON_START_TIMER" = "Mulakan Pemasa"; +"BUTTON_OPTION_SAVE" = "Simpan untuk Kemudian"; +"BUTTON_OPTION_DISCARD" = "Buang Hasil"; +"BUTTON_OPTION_STOP_TASK" = "Tamatkan Tugas"; +"BUTTON_SAVE" = "Simpan"; +"BUTTON_CLEAR_ANSWER" = "Kosongkan jawapan"; +"BUTTON_READ_ONLY_MODE" = "Jawapan ini tidak boleh diubah suai."; +"BUTTON_COPYRIGHT" = "Hak Cipta"; +"BUTTON_CLOSE" = "Tutup"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Memulakan aktiviti dalam"; +"TASK_COMPLETE_TITLE" = "Aktiviti Selesai"; +"TASK_COMPLETE_TEXT" = "Data anda akan dianalisis dan anda akan dimaklumkan apabila keputusan anda tersedia."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Tinggal %@."; +"TOUCH_ANYWHERE_LABEL" = "Sentuh di mana-mana untuk teruskan"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Tangkap Imej"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Tangkap Semula Imej"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Tiada kamera ditemui. Langkah ini tidak boleh dilengkapkan."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Untuk melengkapkan langkah ini, benarkan app ini mengakses kamera dalam Seting."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Tiada direktori output ditentukan untuk imej yang ditangkap."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Imej yang ditangkap tidak dapat disimpan."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Mula Merakam"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Henti Merakam"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Rakam Semula Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kecergasan"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Jarak (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Kadar Jantung (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Duduk dengan selesa selama %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Jalan secepat mungkin selama %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Aktiviti ini memantau kadar jantung anda dan mengukur jarak anda boleh berjalan dalam masa %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Jalan di luar bangunan pada kadar paling laju yang anda boleh selama %1$@. Apabila anda selesai, duduk dan berehat dengan selesa selama %2$@. Untuk bermula, ketik Mulakan."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gaya Jalan dan Imbangan"; +"WALK_INTRO_TEXT" = "Aktiviti ini mengukur gaya jalan dan keseimbangan anda semasa anda berjalan dan berdiri pegun. Jangan teruskan jika anda tidak boleh berjalan dengan selamat tanpa bantuan."; +"WALK_INTRO_2_TEXT_%ld" = "Cari tempat yang boleh anda berjalan dengan selamat tanpa bantuan sejauh lebih kurang %ld langkah dalam garis lurus."; +"WALK_INTRO_2_DETAIL" = "Masukkan peranti anda ke dalam saku atau beg dan ikuti arahan audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Sekarang berdiri pegun selama %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Berdiri pegun selama %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Pusing dan berjalan balik ke tempat anda bermula."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Jalan sehingga %ld langkah dalam garis lurus."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Cari tempat yang anda boleh berjalan mundar-mandir dalam garis lurus dengan selamat. Cuba berjalan berterusan dengan berpusing di penghujung laluan anda, seperti anda berjalan mengelilingi kon.\n\nSeterusnya anda akan diarahkan untuk berpusing dalam bulatan penuh, kemudian berdiri tegak dengan tangan anda di sisi anda dan kaki anda dibuka lebih kurang selebar bahu."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Ketik Mulakan apabila anda bersedia untuk bermula.\nKemudian letakkan peranti anda ke dalam saku atau beg dan ikuti arahan audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Berjalan mundar-mandir dalam garis lurus selama %@. Jalan seperti biasa anda lakukan."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Buat pusingan penuh dan kemudian berdiri tegak selama %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Anda telah melengkapkan aktiviti."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Kelajuan Ketikan"; +"TAPPING_TASK_TITLE_RIGHT" = "Tangan Kanan"; +"TAPPING_TASK_TITLE_LEFT" = "Tangan Kiri"; +"TAPPING_INTRO_TEXT" = "Aktiviti ini mengukur kelajuan mengetik anda."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Letakkan peranti anda di atas permukaan rata."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Gunakan dua jari pada tangan yang sama untuk mengetik butang pada skrin secara berselang-seli."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Gunakan dua jari pada tangan kanan anda untuk mengetik butang pada skrin secara berselang-seli."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Gunakan dua jari pada tangan kiri anda untuk mengetik butang pada skrin secara berselang-seli."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Sekarang ulang ujian yang sama menggunakan tangan kanan anda."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Sekarang ulang ujian yang sama menggunakan tangan kiri anda."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Ketik satu jari, kemudian ketik yang lain. Cuba mengetik dengan kadar yang sekata mungkin. Teruskan mengetik selama %@."; +"TAPPING_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Ketik Seterusnya untuk bermula."; +"TAP_BUTTON_TITLE" = "Ketik"; +"TOTAL_TAPS_LABEL" = "Jumlah Ketikan"; +"TAPPING_INSTRUCTION" = "Ketik butang sekonsisten yang anda boleh menggunakan dua jari."; +"TAPPING_INSTRUCTION_RIGHT" = "Ketik butang menggunakan tangan KANAN anda."; +"TAPPING_INSTRUCTION_LEFT" = "Ketik butang menggunakan tangan KIRI anda."; +"TAPPING_SKIP_TITLE" = "Langkau tangan ini"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Kekisi Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Aktiviti ini membantu mengesan masalah dalam penglihatan pengguna."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Pegang peranti 12 inci dari muka anda dan pada paras mata sepanjang ujian."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Tutup %@ anda dan tenung pada titik di tengah grid segi empat.\n\nMenggunakan jari atau stilus anda, tandakan sebarang herotan yang anda lihat seperti garis kabur atau beralun.\n\nApabila anda selesai, leret ke kiri di mana-mana kawasan luar grid."; +"AMSLER_GRID_LEFT_EYE" = "Mata Kiri"; +"AMSLER_GRID_RIGHT_EYE" = "Mata Kanan"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Suara"; +"AUDIO_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"AUDIO_INSTRUCTION" = "Sebut “Aaaaah” ke dalam mikrofon selama yang anda boleh."; +"AUDIO_INTRO_TEXT" = "Tarik nafas panjang dan sebut “Aaaaah” ke dalam mikrofon selama yang anda boleh. Kekalkan kelantangan suara yang tetap agar bar audio kekal biru."; +"AUDIO_INTENDED_USE" = "Aktiviti ini menilai suara anda dengan merakamnya menggunakan mikrofon di bahagian bawah peranti anda."; +"AUDIO_TOO_LOUD_LABEL" = "Terlalu Kuat"; +"AUDIO_GENERIC_ERROR_LABEL" = "Gagal merakam audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Sila tunggu sementara kami memeriksa paras bunyi latar belakang."; +"AUDIO_TOO_LOUD_MESSAGE" = "Paras bunyi sekitar terlalu kuat untuk merakamkan suara anda. Sila pergi ke tempat yang lebih senyap dan cuba lagi."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Ketik Seterusnya apabila bersedia."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometri Nada"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Aktiviti ini mengukur keupayaan anda untuk mendengar bunyi berlainan."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Sebelum anda bermula, pasangkan dan pakai fon kepala anda.\n\nBunyinya sangat tidak ketara dan tidak seperti nada isyarat biasa.  Bunyi akan bermula dengan perlahan kemudian meningkat kelantangannya perlahan-lahan.  Sila beri perhatian dan ketik butang kiri atau kanan untuk menandakan telinga mana anda mendengarnya."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Anda sepatutnya mendengar nada sekarang. Laraskan kelantangan menggunakan kawalan di sisi peranti anda.\n\nKetik sebarang butang apabila anda bersedia untuk bermula."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Setiap kali anda mendengar bunyi, ketik butang kiri atau kanan untuk menandakan telinga yang anda mendengarnya."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Telinga Kiri"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Telinga Kanan"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Kiri"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Kanan"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometri Nada"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Ketik apabila anda mendengar nada."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Nada & Kelantangan"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Anda akan mendengar satu siri nada."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Apabila anda mendengar nada, ketik butang."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Untuk ujian ini, kelantangan akan disetkan kepada 50 peratus."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Ujian ini mengambil masa lebih kurang 10 minit."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Aktifkan Jangan Ganggu untuk mengelakkan gangguan."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Nada akan dimainkan dalam telinga kanan anda dahulu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Nada kini akan dimainkan dalam telinga kiri anda."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Aktiviti ini mengenal pasti paras ambang pendengaran untuk individu dalam skala HL dB."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Pastikan kelantangan peranti disetkan ke paras maksimum.\n\nSemasa tugas ini, nada lembut akan dimainkan dalam telinga kiri atau kanan.\n\nDengar dengan teliti dan ketik butang setiap kali anda mendengar nada."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ujian ini mengenal pasti kekuatan bunyi yang diperlukan untuk membolehkan anda mendengarnya."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Soal selidik persediaan."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Pilih keutamaan anda untuk ‘telinga yang lebih baik’, jika ada"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "kiri"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "kanan"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "tiada keutamaan"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Ujian Dibatalkan"; +"dBHL_ALERT_TITLE_START_OVER" = "Mula Semula"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Batalkan Ujian"; +"dBHL_ALERT_TEXT" = "Sambungkan semula AirPods atau EarPods anda untuk melakukan ujian ini."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Selesai"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Fon Kepala"; +"HEADPHONES_UNKNOWN" = "Tidak Diketahui"; +"HEADPHONES_NONE" = "Tiada"; +"CONNECTED" = "Disambung"; +"NOT_CONNECTED" = "Tidak Disambung"; +"HEADPHONE_CONNECTED_%@" = "Disambung - %@"; +"HEADPHONE_DETECT_TITLE" = "Sambung Fon Kepala anda"; +"HEADPHONE_DETECT_TEXT" = "Ujian ini memerlukan Apple AirPods atau Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memori Ruang"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Aktiviti ini mengukur memori ruang jangka pendek anda dengan meminta anda mengulangi tertib %@ bernyala."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "bunga"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "bunga"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Sesetengah %@ akan bernyala satu demi satu. Ketik %@ tersebut dalam urutan yang sama ia menyala."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Sesetengah %@ akan bernyala satu demi satu. Ketik %@ tersebut dalam urutan terbalik ia menyala."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Untuk memulakan, ketik Mulakan, kemudian lihat dengan teliti."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Skor"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Lihat %@ bernyala"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Ketik %@ dalam tertib ia bernyala"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Ketik %@ dalam tertib terbalik"; +"MEMORY_GAME_COMPLETE_TITLE" = "Jujukan Selesai"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Untuk meneruskan, ketik Seterusnya"; +"MEMORY_GAME_FAILED_TITLE" = "Cuba Lagi"; +"MEMORY_GAME_FAILED_MESSAGE" = "Anda tidak berjaya dalam pusingan tersebut. Ketik Seterusnya untuk meneruskan."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Habis Masa"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Anda kehabisan masa.\nKetik Seterusnya untuk meneruskan."; +"MEMORY_GAME_COMPLETE" = "Permainan Selesai"; +"MEMORY_GAME_PAUSED_TITLE" = "Dijedakan"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Untuk meneruskan, ketik Seterusnya"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Aktiviti memori dibangunkan dengan bantuan Katherine Possin, PhD dan Joel Kramer, PhD dari University of California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Masa Reaksi"; +"REACTION_TIME_TASK_INTENDED_USE" = "Aktiviti ini menilai masa yang diambil untuk anda membalas kepada isyarat visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Goncang peranti dalam sebarang arah sebaik sahaja titik biru muncul pada skrin. Anda akan diminta untuk melakukan ini sebanyak %D kali."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Percubaan %@ daripada %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Goncang peranti dengan cepat apabila bulatan biru muncul"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Setiap kali perkataan muncul, pilih huruf pertama nama WARNA yang ditunjukkan."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Apabila anda bersedia untuk memulakan aktiviti Stroop ketik Mulakan."; +"STROOP_TASK_STEP_TEXT" = "Pilih huruf pertama nama WARNA yang ditunjukkan."; +"STROOP_COLOR_RED" = "MERAH"; +"STROOP_COLOR_GREEN" = "HIJAU"; +"STROOP_COLOR_BLUE" = "BIRU"; +"STROOP_COLOR_YELLOW" = "KUNING"; +"STROOP_COLOR_RED_INITIAL" = "M"; +"STROOP_COLOR_GREEN_INITIAL" = "H"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "K"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Menara Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Aktiviti ini menilai keupayaan penyelesaian teka-teki anda."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Alihkan keseluruhan tindanan ke platform yang diserlahkan dalam paling kurang pergerakan yang mungkin."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Selesaikan Teka-Teki"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Bilangan Pergerakan: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Saya tidak boleh menyelesaikan teka-teki ini"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Julat Pergerakan"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption mesti kiri atau kanan"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Julat Pergerakan Lutut Kiri"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Julat Pergerakan Lutut Kanan"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aktiviti ini mengukur sejauh mana anda boleh meluruskan lutut kiri anda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aktiviti ini mengukur sejauh mana anda boleh meluruskan lutut kanan anda."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Duduk di pinggir kerusi. Apabila anda bermula anda akan meletakkan peranti anda di atas lutut kiri anda untuk ukuran. Sila aktifkan bunyi pada peranti anda supaya anda boleh mendengar arahan."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Duduk di pinggir kerusi. Apabila anda bermula anda akan meletakkan peranti anda di atas lutut kanan anda untuk ukuran. Sila aktifkan bunyi pada peranti anda supaya anda boleh mendengar arahan."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Letakkan peranti anda di atas lutut kiri anda dengan skrin menghadap ke luar, seperti dalam gambar."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Letakkan peranti anda di atas lutut kanan anda dengan skrin menghadap ke luar, seperti dalam gambar."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Apabila bersedia, ketik skrin untuk bermula dan luruskan lutut kiri anda sejauh yang anda boleh. Kembali ke kedudukan permulaan dan ketik lagi apabila anda selesai."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Apabila bersedia, ketik skrin untuk bermula dan luruskan lutut kanan anda sejauh yang anda boleh. Kembali ke kedudukan permulaan dan ketik lagi apabila anda selesai."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Letakkan peranti anda di atas lutut kiri anda. Ketik skrin dan luruskan lutut kiri anda sejauh yang anda boleh."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Letakkan peranti anda di atas lutut kanan anda. Ketik skrin dan luruskan lutut kanan anda sejauh yang anda boleh."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Apabila anda selesai, kembalikan lutut kiri anda ke kedudukan permulaan. Kemudian ketik di mana-mana sahaja."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Apabila anda selesai, kembalikan lutut kanan anda ke kedudukan permulaan. Kemudian ketik di mana-mana sahaja."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Julat Pergerakan Bahu Kiri"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Julat Pergerakan Bahu Kanan"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Aktiviti ini mengukur sejauh mana anda boleh meluruskan bahu kiri anda."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Aktiviti ini mengukur sejauh mana anda boleh meluruskan bahu kanan anda."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Apabila anda bermula anda akan meletakkan peranti anda di atas bahu kiri anda untuk ukuran. Sila aktifkan bunyi pada peranti anda supaya anda boleh dengar arahan."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Apabila anda bermula anda akan meletakkan peranti anda di atas bahu kanan anda untuk ukuran. Sila aktifkan bunyi pada peranti anda supaya anda boleh dengar arahan."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Letakkan peranti anda di atas bahu kiri anda dengan skrin menghadap ke luar, seperti dalam gambar."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Letakkan peranti anda di atas bahu kanan anda dengan skrin menghadap ke luar, seperti dalam gambar."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Apabila bersedia, ketik skrin untuk bermula dan angkat lengan kiri anda sejauh yang anda boleh. Kembali ke kedudukan permulaan dan ketik lagi apabila anda selesai."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Apabila bersedia, ketik skrin untuk bermula dan angkat lengan kanan anda sejauh yang anda boleh. Kembali ke kedudukan permulaan dan ketik lagi apabila anda selesai."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Letakkan peranti anda di atas bahu kiri anda. Ketik skrin dan angkat lengan kiri anda ke hadapan sejauh yang anda boleh."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Letakkan peranti anda di atas bahu kanan anda. Ketik skrin dan angkat lengan kanan anda ke hadapan sejauh yang anda boleh."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Apabila anda selesai, kembalikan lengan kiri anda ke kedudukan permulaan. Kemudian ketik di mana-mana sahaja."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Apabila anda selesai, kembalikan lengan kanan anda ke kedudukan permulaan. Kemudian ketik di mana-mana sahaja."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Jalan Bermasa"; +"TIMED_WALK_INTRO_DETAIL" = "Aktiviti ini mengukur fungsi anggota badan bawah anda."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Cari sesuatu tempat, lebih baik jika di luar bangunan, yang boleh anda berjalan sejauh lebih kurang %@ dalam garis lurus secepat mungkin, namun dengan selamat. Jangan perlahankan diri sehingga anda melepasi garisan penamat."; +"TIMED_WALK_INTRO_2_DETAIL" = "Ketik Seterusnya untuk bermula."; +"TIMED_WALK_FORM_TITLE" = "Peranti bantu"; +"TIMED_WALK_FORM_TEXT" = "Gunakan peranti bantu yang sama untuk setiap ujian."; +"TIMED_WALK_QUESTION_TEXT" = "Adakah anda memakai ortosis buku lali kaki?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Adakah anda menggunakan peranti bantu?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Ketik di sini untuk memilih jawapan."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Tiada"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Tongkat Satu Tangan"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Topang Satu Tangan"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Tongkat Dua Tangan"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Topang Dua Tangan"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Pejalan/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Jalan sehingga %@ dalam garis lurus."; +"TIMED_WALK_INSTRUCTION_TURN" = "Pusing."; +"TIMED_WALK_INSTRUCTION_2" = "Berjalan balik ke tempat anda bermula."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Ketik Seterusnya apabila selesai."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Ujian Penambahan Bersiri Pendengaran Berkadar mengukur kelajuan pemprosesan maklumat pendengaran dan keupayaan pengiraan anda."; +"PVSAT_INTRO_TEXT" = "Ujian Penambahan Bersiri Visual Berkadar mengukur kelajuan pemprosesan maklumat visual dan keupayaan pengiraan anda."; +"PAVSAT_INTRO_TEXT" = "Ujian Penambahan Bersiri Pendengaran dan Visual Berkadar mengukur kelajuan pemprosesan maklumat pendengaran dan visual serta keupayaan pengiraan anda."; +"PSAT_INTRO_TEXT_2_%@" = "Digit tunggal dipaparkan setiap %@.\nAnda mesti menambahkan setiap digit baru dengan digit sebelumnya.\nHarap maklum, anda tidak perlu mengira jumlah keseluruhan, tetapi jumlah dua nombor terakhir sahaja."; +"PSAT_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"PSAT_INITIAL_INSTRUCTION" = "Ingati digit pertama ini."; +"PSAT_INSTRUCTION" = "Tambah digit baru ini pada yang sebelumnya."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Ujian Pancang %@ Lubang"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Aktiviti ini mengukur fungsi anggota badan atas anda dengan meminta anda meletakkan pancang ke dalam lubang. Anda akan diminta melakukan ini sebanyak %@ kali."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Tangan kiri dan kanan anda akan diuji.\nAnda mesti mengutip pancang secepat mungkin, masukkannya ke dalam lubang dan setelah dilakukan sebanyak %@ kali, keluarkannya lagi sebanyak %@ kali."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Tangan kanan dan kiri anda akan diuji.\nAnda mesti mengutip pancang secepat mungkin, masukkannya ke dalam lubang dan setelah dilakukan sebanyak %@ kali, keluarkannya lagi sebanyak %@ kali."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Letakkan pancang ke dalam lubang menggunakan tangan kiri anda."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Letakkan pancang ke dalam lubang menggunakan tangan kanan anda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Letakkan pancang di belakang garis menggunakan tangan kiri anda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Letakkan pancang di belakang garis menggunakan tangan kanan anda."; +"HOLE_PEG_TEST_TEXT" = "Kutip pancang menggunakan dua jari."; +"HOLE_PEG_TEST_TEXT_2" = "Angkat jari untuk melepaskan pancang."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Aktiviti Getaran"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Aktiviti ini mengukur getaran tangan anda dalam pelbagai posisi. Cari tempat yang anda boleh duduk dengan selesa sepanjang tempoh aktiviti ini."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Pegang telefon di tangan anda yang lebih terjejas seperti yang ditunjukkan dalam imej di bawah."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Pegang telefon di tangan KANAN anda seperti yang ditunjukkan dalam imej di bawah."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Pegang telefon di tangan KIRI anda seperti yang ditunjukkan dalam imej di bawah."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Anda akan diminta untuk melakukan %@ sambil duduk dengan telefon di tangan anda."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "satu tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dua tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tiga tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "empat tugas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "lima tugas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Ketik seterusnya untuk teruskan."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Bersedia untuk memegang telefon anda di riba anda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Bersedia untuk memegang telefon anda di riba anda dengan tangan KIRI anda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Bersedia untuk memegang telefon anda di riba anda dengan tangan KANAN anda."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Teruskan memegang telefon anda di riba anda selama %ld saat."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Sekarang pegang telefon anda dengan tangan anda diluruskan pada ketinggian bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Sekarang pegang telefon anda dengan tangan KIRI anda diluruskan pada ketinggian bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Sekarang pegang telefon anda dengan tangan KANAN anda diluruskan pada ketinggian bahu."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Teruskan memegang telefon anda dengan tangan anda diluruskan selama %ld saat."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Sekarang pegang telefon anda pada ketinggian bahu dengan siku anda dibengkokkan."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Sekarang pegang telefon anda dengan tangan KIRI anda pada ketinggian bahu dengan siku anda dibengkokkan."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Sekarang pegang telefon anda dengan tangan KANAN anda pada ketinggian bahu dengan siku anda dibengkokkan."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Teruskan memegang telefon anda dengan siku anda dibengkokkan selama %ld saat"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Terus bengkokkan siku anda, sentuh telefon anda ke hidung anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Terus bengkokkan siku anda dengan telefon anda di tangan KIRI anda, sentuh telefon anda ke hidung anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Terus bengkokkan siku anda dengan telefon anda di tangan KANAN anda, sentuh telefon anda ke hidung anda berulang kali."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Teruskan menyentuh telefon anda ke hidung anda selama %ld saat"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Bersedia untuk melakukan lambaian ratu (lambai dengan memusingkan pergelangan tangan anda)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Bersedia untuk melakukan lambaian ratu dengan telefon anda di tangan KIRI anda (lambai dengan memusingkan pergelangan tangan anda)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Bersedia untuk melakukan lambaian ratu dengan telefon anda di tangan KANAN anda (lambai dengan memusingkan pergelangan tangan anda)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Teruskan melakukan lambaian ratu selama %ld saat."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Sekarang tukar telefon ke tangan KIRI anda dan teruskan ke tugas seterusnya."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Sekarang tukar telefon ke tangan KANAN anda dan teruskan ke tugas seterusnya."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Teruskan ke tugas seterusnya."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktiviti selesai."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Anda akan diminta untuk melakukan %@ sambil duduk dengan telefon di sebelah tangan dahulu, kemudian sekali lagi dengan tangan yang lain."; +"TREMOR_SKIP_LEFT_HAND" = "Saya tidak boleh melakukan aktiviti ini menggunakan tangan KIRI saya."; +"TREMOR_SKIP_RIGHT_HAND" = "Saya tidak boleh melakukan aktiviti ini menggunakan tangan KANAN saya."; +"TREMOR_SKIP_NEITHER" = "Saya boleh melakukan aktiviti ini menggunakan kedua-dua tangan."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Ujian Pembuatan Jejak"; +"TRAILMAKING_INTENDED_USE" = "Aktiviti ini menilai perhatian visual dan penukaran tugas anda dengan merekod masa yang diperlukan untuk mengetik siri bulatan dalam tertib."; +"TRAILMAKING_INTENDED_USE2_A" = "Selepas kira detik, ketik bulatan dalam tertib berselang-seli antara nombor dan huruf. Mulakan dengan mengetik nombor pertama ‘1’ diikuti dengan nombor ‘2’ – ‘3’ – ‘4’… sehingga anda mencapai nombor ‘7’."; +"TRAILMAKING_INTENDED_USE2_B" = "Selepas kira detik, ketik bulatan dalam tertib berselang-seli antara nombor dan huruf. Mulakan dengan mengetik nombor pertama ‘1’ diikuti dengan mengetik huruf pertama ‘A’ dan kemudian ‘2’ – ‘B’ – ‘3’ – ‘C’… sehingga anda mencapai nombor ‘7’."; +"TRAILMAKING_INTRO_TEXT" = "Lakukan ini secepat mungkin tanpa melakukan kesilapan. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Pengecaman Pertuturan"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Aktiviti ini merakam pertuturan anda dengan mikrofon di bahagian bawah peranti dan menterjemahkannya kepada teks."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Ketik Mulakan untuk memulakan."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Tekan butang untuk mula merakam sebelum bercakap."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Mula Merakam"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Henti Merakam"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edit Transkrip"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edit teks transkrip untuk membetulkan sebarang salah tafsir pertuturan."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Transkripsi anda akan muncul di sini."; +"SPEECH_RECOGNITION_FAILED" = "Pengecaman pertuturan gagal."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Gagal memulakan pengecaman pertuturan."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Mainkan Audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Hentikan Audio"; +"SPEECH_IN_NOISE_TITLE" = "Pertuturan dalam Bunyi"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Aktiviti ini mengukur kebolehfahaman pertuturan apabila dilakukan dalam persekitaran yang bising."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Sebagai sebahagian daripada ujian ini, anda akan:\n\nDengar ayat.\n\nUlang perkara yang anda dengar dengan jelas atau langkau ke hadapan untuk menaip perkara yang anda dengar menggunakan papan kekunci. \n\nJika anda mengulang perkara yang anda dengar, anda akan mempunyai pilihan untuk mengubah suai transkrip yang dijana oleh enjin pengecaman pertuturan."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Penentukuran Kelantangan"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Ketik ‘Mainkan Audio’, laraskan kelantangan anda kepada paras yang selesa dan kemudian ketik ‘Hentikan Audio’ untuk meneruskan."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Dengar"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Ayat bercampur dengan bunyi latar belakang pada Nisbah Isyarat kepada Hingar (SNR) yang dirawakkan akan dimainkan hanya sekali."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Sebut"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Ulang perkara yang anda dengar."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Tidak dapat mencipta fail"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Tidak dapat mengeluarkan fail log yang mencukupi untuk mencapai ambang"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Ralat mengeset atribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Fail tidak ditandakan sebagai dipadamkan (tidak ditandakan sebagai dimuat naik)"; +"ERROR_DATALOGGER_MULTIPLE" = "Berbilang ralat semasa mengeluarkan log"; +"ERROR_RECORDER_NO_DATA" = "Tiada data yang dikumpulkan ditemui."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Tiada direktori output ditentukan"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Meter SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Aktiviti ini mengukur paras tekanan bunyi persekitaran. Jika paras bunyi terlalu tinggi, anda tidak boleh meneruskan. Sila pergi ke lokasi yang lebih senyap untuk menyelesaikan tugas ini atau lakukan semula aktiviti ini kemudian."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Mengira"; +"ENVIRONMENTSPL_THRESHOLD" = "Ambang: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Bunyi Latar Belakang OK"; +"ENVIRONMENTSPL_NOISE" = "Bunyi Latar Belakang Terlalu Kuat"; +"ENVIRONMENTSPL_TITLE_2" = "Cari tempat yang senyap"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Untuk memastikan ketepatan, ujian ini patut dilakukan dalam persekitaran yang senyap."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Mulakan Tugas"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Tiada Data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Gerakkan gelangsar untuk memasukkan nilai"; +"SLIDER_I_DONT_KNOW" = "Saya Tidak Tahu"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Halaman"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Balik"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Tunjukkan Imej Kecil PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Sembunyikan Imej Kecil PDF"; +"AX_BUTTON_ANNOTATE" = "Anotasi"; +"AX_BUTTON_SHOW_SEARCH" = "Tunjukkan Bar Carian"; +"AX_BUTTON_HIDE_SEARCH" = "Sembunyikan Bar Carian"; +"AX_BUTTON_SHARE" = "Kongsi"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustrasi tanda semak dalam bulatan biru menunjukkan ia berjaya"; + +"AX_SIGNVIEW_LABEL" = "Medan tandatangan yang ditetapkan"; +"AX_SIGNVIEW_HINT" = "Sentuh skrin dan gerakkan jari anda untuk menandatangan"; +"AX_SIGNVIEW_SIGNED" = "Ditandatangani"; +"AX_SIGNVIEW_UNSIGNED" = "Tidak Ditandatangani"; + +"AX_SELECTED" = "Dipilih"; +"AX_UNSELECTED" = "Dinyahpilih"; +"AX_SELECT_ALL_THAT_APPLY" = "PILIH SEMUA YANG BERKENAAN"; + +"AX_SLIDER_LABEL" = "Gelangsar respons. Julat dari %@ hingga %@"; +"AX_UNLABELED_IMAGE" = "Imej tanpa label"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Mulakan tugas"; + +"AX.MEMORY.TILE.ACTIVE" = "aktif"; +"AX.MEMORY.TILE.CORRECT" = "betul"; +"AX.MEMORY.TILE.INCORRECT" = "salah"; +"AX.MEMORY.TILE.QUIESCENT" = "kuisen"; +"AX.MEMORY.TILE.LABEL" = "Jubin permainan memori"; + +"AX_IMAGE_CAPTURE_LABEL" = "Pratonton tangkapan"; +"AX_IMAGE_CAPTURED_LABEL" = "Imej ditangkap"; + +"AX_VIDEO_CAPTURE_LABEL" = "Pratonton rakaman video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Rakaman video selesai"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Gagal menempatkan cakera bersaiz %@ pada cakera bersaiz %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Sasaran"; +"AX_TOWER_OF_HANOI_TOWER" = "Menara"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Dwiketik untuk menempatkan cakera"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Dwiketik untuk memilih cakera teratas"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Mempunyai cakera bersaiz %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Kosong"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Tutup papan kekunci"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Julat daripada %@ hingga %@"; +"AX_GRAPH_STACK_PREFIX" = "Tindanan terdiri daripada"; +"AX_GRAPH_AND_SEPARATOR" = " dan "; +"AX_GRAPH_POINT_%@" = "Titik: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Bentuk Gelombang Pertuturan"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Apabila rakaman bermula, aktifkan buat kali kedua untuk menghentikan rakaman."; + +"AX_AUDIO_BAR_GRAPH" = "Graf Bar Audio"; + +"AX_AMSLER_GRID_LABEL" = "Kekisi Amsler"; +"AX_AMSLER_GRID_HINT" = "Gunakan jari atau stilus anda untuk terus menandakan grid, atau leret ke kiri di luar grid untuk menghabiskan."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Butang Boleh Diketik"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Ketik untuk Telinga Kiri"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktifkan untuk memulakan ujian. Apabila ujian bermula, ketik terus pada butang ini apabila anda mendengar bunyi dalam telinga kiri anda."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Ketik untuk Telinga Kanan"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktifkan untuk memulakan ujian. Apabila ujian bermula, ketik terus pada butang ini apabila anda mendengar bunyi dalam telinga kanan anda."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Menggunakan VoiceOver, terokai skrin dengan sentuhan untuk mengetahui lokasi butang untuk setiap telinga. Apabila ujian bermula, butang akan dapat diketik terus. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Ketik dengan satu jari"; +"AX_TAP_BUTTON_2_LABEL" = "Ketik dengan jari lain"; +"AX_TAP_BUTTON_HINT" = "Aktifkan untuk menjadikan butang dapat diketik terus."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Menggunakan VoiceOver, terokai skrin dengan sentuhan untuk mengetahui lokasi butang. Aktifkan salah satu butang untuk menjadikan butang dapat diketik terus."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Butang kini dapat diketik terus."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Menggunakan VoiceOver, butang akan dapat diketik terus. Ia akan berada berdekatan bahagian tengah skrin."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Menggunakan VoiceOver, butang dalam ujian akan dapat diketik terus."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Tidak boleh menyahkod restoreData untuk pengawalan"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..4258fa9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ms.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d ralat) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.strings new file mode 100755 index 0000000..a60c7b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Toestemming"; +"CONSENT_NAME_GIVEN" = "Voornaam"; +"CONSENT_NAME_FAMILY" = "Achternaam"; +"CONSENT_NAME_PLACEHOLDER" = "Vereist"; +"CONSENT_REVIEW_TITLE" = "Bekijk"; +"CONSENT_REVIEW_INSTRUCTION" = "Lees het formulier hieronder door en tik op 'Akkoord' als je klaar bent om verder te gaan."; +"CONSENT_REVIEW_ALERT_TITLE" = "Bekijk"; +"CONSENT_SIGNATURE_TITLE" = "Handtekening"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Onderteken met je vinger in het onderstaande vak."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Zet hier je handtekening"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Pagina %1$ld van %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Welkom"; +"CONSENT_SECTION_DATA_GATHERING" = "Gegevens verzamelen"; +"CONSENT_SECTION_PRIVACY" = "Privacy"; +"CONSENT_SECTION_DATA_USE" = "Gegevensgebruik"; +"CONSENT_SECTION_STUDY_SURVEY" = "Onderzoeksenquête"; +"CONSENT_SECTION_STUDY_TASKS" = "Onderzoekstaken"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Benodigde tijd"; +"CONSENT_SECTION_WITHDRAWING" = "Afzien van deelname"; +"CONSENT_LEARN_MORE_TITLE" = "Meer informatie"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Meer informatie over het verzamelen van gegevens"; +"LEARN_MORE_DATA_USE" = "Meer informatie over het gebruik van gegevens"; +"LEARN_MORE_PRIVACY" = "Meer informatie over de bescherming van je privacy en identiteit"; +"LEARN_MORE_WELCOME" = "Meer informatie over het onderzoek"; +"LEARN_MORE_STUDY_SURVEY" = "Meer informatie over de onderzoeksenquête"; +"LEARN_MORE_TIME_COMMITMENT" = "Meer informatie over hoelang het onderzoek duurt"; +"LEARN_MORE_TASKS" = "Meer informatie over wat je moet doen"; +"LEARN_MORE_WITHDRAWING" = "Meer informatie over afzien van deelname"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opties voor delen"; +"CONSENT_SHARE_WIDELY_%@" = "Deel mijn gegevens met %@ en gekwalificeerde onderzoekers wereldwijd"; +"CONSENT_SHARE_ONLY_%@" = "Deel mijn gegevens alleen met %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "De resultaten van je deelname aan dit onderzoek worden naar %@ gestuurd.\n\nDoor de gecodeerde onderzoeksgegevens met anderen te delen (zonder persoonlijke gegevens zoals je naam) kun je helpen om dit en toekomstig onderzoek te verbeteren."; +"LEARN_MORE_CONSENT_SHARING" = "Meer informatie over het delen van gegevens"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Naam in hoofdletters"; +"CONSENT_DOC_LINE_SIGNATURE" = "Handtekening"; +"CONSENT_DOC_LINE_DATE" = "Datum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ van %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Vraag %1$@ van %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Overgeslagen"; +"REVIEW_EDIT_ANSWER" = "Wijzig"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Ongeldige waarde"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ is hoger dan de maximaal toegestane waarde (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ is lager dan de minimaal toegestane waarde (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ is geen geldige waarde."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Ongeldig e‑mailadres: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Voer een adres in"; +"LOCATION_ERROR_TITLE" = "Opgegeven adres niet gevonden"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "De huidige locatie kan niet worden bepaald. Typ een adres of ga indien nodig naar een plek met een beter gps-signaal."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Toegang tot 'Locatievoorzieningen' is geweigerd. Ga naar Instellingen en geef deze app toestemming om 'Locatievoorzieningen' te gebruiken."; +"LOCATION_ERROR_GEOCODE" = "Het ingevoerde adres is niet gevonden. Zorg dat je een geldig adres invoert."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Je bent niet verbonden met het internet of je hebt te vaak naar een adres gezocht. Zet om deze vraag te beantwoorden wifi aan als je niet verbonden bent met het internet. Je kunt deze vraag ook overslaan als er een knop 'Sla over' is of verdergaan met deze vragenlijst als de internetverbinding actief is. Of je kunt het over een paar minuten opnieuw proberen."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Tekst overschrijdt maximale lengte: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera niet beschikbaar in gedeeld scherm."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E‑mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Wachtwoord"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Voer wachtwoord in"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Herhaal"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Herhaal wachtwoord"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "De wachtwoorden komen niet overeen."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Aanvullende informatie"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Geslacht"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Kies een geslacht"; +"DOB_FORM_ITEM_TITLE" = "Geboortedatum"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Kies een datum"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefoonnummer"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificatie"; +"VERIFICATION_STEP_TITLE" = "Verifieer je e-mailadres"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tik op de koppeling hieronder als je geen verificatiemail hebt ontvangen en je deze opnieuw wilt laten versturen."; +"RESEND_EMAIL_BUTTON_TITLE" = "Stuur controlemail opnieuw"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Inloggen"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Wachtwoord vergeten?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Voer toegangscode in"; +"PASSCODE_CONFIRM_MESSAGE" = "Herhaal toegangscode"; +"PASSCODE_SAVED_MESSAGE" = "Toegangscode bewaard"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Toegangscode geverifieerd"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Voer je oude toegangscode in"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Voer je nieuwe toegangscode in"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Herhaal je nieuwe wachtwoord"; +"PASSCODE_INVALID_ALERT_TITLE" = "Toegangscode onjuist"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "De codes komen niet overeen. Probeer het opnieuw."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Log in met Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-fout"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Alleen cijfertekens toegestaan."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Voortgangsindicator toegangscode-invoer"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ van %@ cijfers ingevoerd"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Toegangscode vergeten?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Sleutelhangeronderdeel kan niet worden toegevoegd."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Sleutelhangeronderdeel kan niet worden bijgewerkt."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Sleutelhangeronderdeel kan niet worden verwijderd."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Sleutelhangeronderdeel is onvindbaar."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type I"; +"FITZPATRICK_SKIN_TYPE_II" = "Type II"; +"FITZPATRICK_SKIN_TYPE_III" = "Type III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Type V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Vrouw"; +"GENDER_MALE" = "Man"; +"GENDER_OTHER" = "Anders"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nee"; +"BOOL_YES" = "Ja"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "vt"; +"MEASURING_UNIT_IN" = "inch"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "links"; +"LIMB_RIGHT" = "rechts"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tik om te antwoorden"; +"NULL_ANSWER" = "Kies een antwoord"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tik om te selecteren"; +"PLACEHOLDER_LONG_TEXT" = "Tik om te schrijven"; + +/* Button titles */ +"BUTTON_AGREE" = "Akkoord"; +"BUTTON_CANCEL" = "Annuleer"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Wis"; +"BUTTON_CLEAR_SIGNATURE" = "Wis handtekening"; +"BUTTON_APPLY" = "Pas toe"; +"BUTTON_DISAGREE" = "Niet akkoord"; +"BUTTON_DONE" = "Gereed"; +"BUTTON_GET_STARTED" = "Start"; +"BUTTON_LEARN_MORE" = "Meer informatie"; +"BUTTON_NEXT" = "Volgende"; +"BUTTON_SKIP" = "Sla over"; +"BUTTON_SKIP_QUESTION" = "Sla deze vraag over"; +"BUTTON_START_TIMER" = "Start timer"; +"BUTTON_OPTION_SAVE" = "Bewaar voor later"; +"BUTTON_OPTION_DISCARD" = "Wis resultaten"; +"BUTTON_OPTION_STOP_TASK" = "Stop met taak"; +"BUTTON_SAVE" = "Bewaar"; +"BUTTON_CLEAR_ANSWER" = "Wis antwoord"; +"BUTTON_READ_ONLY_MODE" = "Dit antwoord kan niet worden gewijzigd."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Sluit"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Activiteit begint over"; +"TASK_COMPLETE_TITLE" = "Activiteit voltooid"; +"TASK_COMPLETE_TEXT" = "Je gegevens worden geanalyseerd. Je ontvangt bericht als de resultaten gereed zijn."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Nog %@."; +"TOUCH_ANYWHERE_LABEL" = "Tik om verder te gaan"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Leg afbeelding vast"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Leg afbeelding opnieuw vast"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Geen camera gevonden. Deze stap kan niet worden voltooid."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Om deze stap te voltooien, moet je in Instellingen deze app toegang tot de camera geven."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Er is geen uitvoermap voor vastgelegde afbeeldingen opgegeven."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "De vastgelegde afbeelding kan niet worden bewaard."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start opname"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stop opname"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Leg video opnieuw vast"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Conditie"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Afstand (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Hartslag (spm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Ga %@ gemakkelijk zitten."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Loop %@ zo snel als je kunt."; +"FITNESS_INTRO_TEXT_FORMAT" = "Tijdens deze activiteit wordt je hartslag gemeten en wordt gekeken hoe ver je in %1$@ kunt lopen."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Loop buiten %1$@ zo snel als je kunt. Ga daarna gemakkelijk zitten en rust %2$@ uit. Tik op 'Start' om te beginnen."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Tred en balans"; +"WALK_INTRO_TEXT" = "Tijdens deze activiteit worden je tred en balans gemeten terwijl je loopt en stilstaat. Ga niet verder als je niet veilig zelfstandig kunt lopen."; +"WALK_INTRO_2_TEXT_%ld" = "Zoek een plek waar je veilig en zelfstandig ongeveer %ld stappen in een rechte lijn kunt zetten."; +"WALK_INTRO_2_DETAIL" = "Stop je apparaat in je zak of tas en volg de audio-instructies."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Sta nu %@ lang stil."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Sta %@ stil."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Draai om en loop terug naar het beginpunt."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Zet maximaal %ld stappen in een rechte lijn."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Zoek een plek waar je veilig in een rechte lijn heen en weer kunt lopen. Maak aan de einden van de looproute een bocht (alsof je om een pylon heenloopt) zodat je niet hoeft te stoppen.\n\nDaarna wordt je gevraagd om één keer om je as te draaien en vervolgens om stil te staan met je armen langs je lichaam en je voeten uit elkaar op schouderbreedte."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tik op 'Start' als je klaar bent om te beginnen.\nStop het apparaat vervolgens in je zak of tas en volg de audio-instructies."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Loop %@ in een rechte lijn heen en weer. Loop zoals je altijd loopt."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Draai één keer om je as en sta vervolgens %@ stil."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Je hebt de activiteit voltooid."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tiksnelheid"; +"TAPPING_TASK_TITLE_RIGHT" = "Rechterhand"; +"TAPPING_TASK_TITLE_LEFT" = "Linkerhand"; +"TAPPING_INTRO_TEXT" = "Tijdens deze activiteit wordt de snelheid waarmee je tikt gemeten."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Plaats je apparaat op een egaal oppervlak."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Tik met twee vingers van dezelfde hand beurtelings op de knoppen op het scherm."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Tik met twee vingers van je rechterhand beurtelings op de knoppen op het scherm."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Tik met twee vingers van je linkerhand beurtelings op de knoppen op het scherm."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Voer nu dezelfde test uit met je rechterhand."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Voer nu dezelfde test uit met je linkerhand."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tik eerst met de ene vinger en dan met de andere. Probeer zo gelijkmatig mogelijk te tikken. Ga %@ door met tikken."; +"TAPPING_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tik op 'Volgende' om te beginnen."; +"TAP_BUTTON_TITLE" = "Tik"; +"TOTAL_TAPS_LABEL" = "Totaal aantal tikken"; +"TAPPING_INSTRUCTION" = "Tik met twee vingers zo gelijkmatig mogelijk op de knoppen."; +"TAPPING_INSTRUCTION_RIGHT" = "Tik op de knoppen met de vingers van je RECHTERHAND."; +"TAPPING_INSTRUCTION_LEFT" = "Tik op de knoppen met de vingers van je LINKERHAND."; +"TAPPING_SKIP_TITLE" = "Sla deze hand over"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amslerrooster"; +"AMSLER_GRID_INTRO_TEXT" = "Met deze activiteit kun je problemen met het gezichtsvermogen van de gebruiker beter detecteren."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Houd het apparaat gedurende de test 30 centimeter van je gezicht en op ooghoogte."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Sluit je %@ en staar naar de stip in het midden van het vierkante rooster.\n\nGebruik je vinger of stylus en markeer eventuele vervormingen die je ziet, zoals vervaagde of golvende lijnen.\n\nVeeg wanneer je klaar bent naar links buiten het rooster."; +"AMSLER_GRID_LEFT_EYE" = "linkeroog"; +"AMSLER_GRID_RIGHT_EYE" = "rechteroog"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Stem"; +"AUDIO_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"AUDIO_INSTRUCTION" = "Zeg zo lang mogelijk 'aaaaah' in de microfoon."; +"AUDIO_INTRO_TEXT" = "Haal diep adem en zeg zo lang mogelijk 'aaaaah' in de microfoon. Houd daarbij dezelfde geluidssterkte aan zodat de audiobalken blauw blijven."; +"AUDIO_INTENDED_USE" = "Tijdens deze activiteit wordt je stemgeluid gemeten door dit op te nemen met de microfoon aan de onderkant van je apparaat."; +"AUDIO_TOO_LOUD_LABEL" = "Te hard"; +"AUDIO_GENERIC_ERROR_LABEL" = "Geluid opnemen niet mogelijk"; +"AUDIO_LEVEL_CHECK_LABEL" = "Even geduld. Het achtergrondgeluid wordt gecontroleerd."; +"AUDIO_TOO_LOUD_MESSAGE" = "Er is te veel omgevingsgeluid om je stem op te nemen. Ga naar een stillere plek en probeer het opnieuw."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tik op 'Volgende' als je klaar bent."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Toonaudiometrie"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Met deze activiteit wordt gemeten of je verschillende geluiden kunt horen."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Voordat je begint, sluit je je koptelefoon aan en zet je deze op.\n\nHet geluid is erg subtiel en lijkt niet op een normaal waarschuwingssignaal. Het geluid begint zacht en wordt langzaam steeds luider. Luister aandachtig en tik op de linker- of rechterknop om aan te geven in welk oor je het geluid hoorde."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Je moet nu een toon horen. Pas het volume aan met de knoppen aan de zijkant van je apparaat.\n\nTik op een willekeurige knop wanneer je klaar bent om te beginnen."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Telkens wanneer je een geluid hoort, tik je op de linker- of rechterknop om aan te geven in welk oor je het geluid hoorde."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Linkeroor"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Rechteroor"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, links"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, rechts"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Toonaudiometrie"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tik wanneer je een toon hoort."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Toon en volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Je hoort een reeks tonen."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Wanneer je een toon hoort, tik je op de knop."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Voor deze test wordt het volume ingesteld op 50 procent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Deze test duurt ongeveer 10 minuten."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Schakel 'Niet storen' in om onderbrekingen te voorkomen."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Er worden eerst tonen in je rechteroor afgespeeld."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Er worden nu tonen in je linkeroor afgespeeld."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Met deze activiteit bepaal je de gehoordrempelwaarden van een individu op de dB HL-schaal."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Zorg ervoor dat het volume van het apparaat op het hoogste niveau is ingesteld.\n\nTijdens deze taak wordt er een subtiele toon afgespeeld in het linker- of rechteroor.\n\nLuister aandachtig en tik telkens wanneer je een toon hoort op de knop."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Deze test stelt vast hoe hard een geluid moet zijn, zodat jij het kunt horen."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Intakevragenlijst."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecteer je voorkeur voor \“beter oor\”, indien van toepassing"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "links"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "rechts"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "geen voorkeur"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test geannuleerd"; +"dBHL_ALERT_TITLE_START_OVER" = "Begin opnieuw"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Annuleer test"; +"dBHL_ALERT_TEXT" = "Verbind je AirPods of EarPods opnieuw om deze test uit te voeren."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ voltooid"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Koptelefoon"; +"HEADPHONES_UNKNOWN" = "Onbekend"; +"HEADPHONES_NONE" = "Geen"; +"CONNECTED" = "Verbonden"; +"NOT_CONNECTED" = "Geen verbinding"; +"HEADPHONE_CONNECTED_%@" = "Verbonden - %@"; +"HEADPHONE_DETECT_TITLE" = "Sluit je koptelefoon aan"; +"HEADPHONE_DETECT_TEXT" = "Voor deze test zijn Apple AirPods of Apple EarPods vereist"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Ruimtelijk geheugen"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Tijdens deze activiteit wordt je ruimtelijk kortetermijngeheugen gemeten door je de volgorde waarin %@ oplichten te laten herhalen."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "bloemen"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "bloemen"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Een aantal van de %@ licht een voor een op. Tik op die %@ in dezelfde volgorde als waarin ze oplichtten."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Een aantal van de %@ licht een voor een op. Tik op die %@ in de omgekeerde volgorde als waarin ze oplichtten."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen en kijk goed."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Score"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Kijk hoe de %@ oplichten"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tik op de %@ in de volgorde waarin ze oplichtten"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tik in omgekeerde volgorde op de %@"; +"MEMORY_GAME_COMPLETE_TITLE" = "Volgorde voltooid"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Tik op 'Ga door' om verder te gaan"; +"MEMORY_GAME_FAILED_TITLE" = "Probeer het opnieuw"; +"MEMORY_GAME_FAILED_MESSAGE" = "Het is niet helemaal gelukt dit keer. Tik op 'Volgende' om verder te gaan."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Tijd is om"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Je hebt het niet binnen de tijd gehaald.\nTik op 'Volgende' om verder te gaan."; +"MEMORY_GAME_COMPLETE" = "Spel voltooid"; +"MEMORY_GAME_PAUSED_TITLE" = "Pauze"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Tik op 'Ga door' om verder te gaan"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "De geheugenactiviteit is ontwikkeld met hulp van Katherine Possin, PhD en Joel Kramer, PhD van de University of California in San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reactietijd"; +"REACTION_TIME_TASK_INTENDED_USE" = "Met deze activiteit wordt gekeken hoe snel je op een visuele aanwijzing reageert."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Schud het apparaat in een willekeurige richting zodra de blauwe stip op het scherm verschijnt. Je wordt gevraagd om dit %D keer te doen."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Poging %@ van %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Schud het apparaat snel heen en weer als de blauwe cirkel verschijnt"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop-taak"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Telkens wanneer er een woord verschijnt, selecteer je de eerste letter(s) van de naam van de KLEUR die wordt weergegeven."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Tik op 'Start' wanneer je klaar bent om de Stroop-taak te starten."; +"STROOP_TASK_STEP_TEXT" = "Selecteer de eerste letter(s) van de naam van de KLEUR die wordt weergegeven."; +"STROOP_COLOR_RED" = "ROOD"; +"STROOP_COLOR_GREEN" = "GROEN"; +"STROOP_COLOR_BLUE" = "BLAUW"; +"STROOP_COLOR_YELLOW" = "GEEL"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "Gr"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ge"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torens van Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Met deze activiteit wordt gekeken hoe goed je puzzels kunt oplossen."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Verplaats de hele stapel in zo min mogelijk stappen naar het gemarkeerde platform."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Los de puzzel op"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Aantal stappen: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Ik kan deze puzzel niet oplossen"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Bewegingsbereik"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption moet links of rechts zijn"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Beweeglijkheid linkerknie"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Beweeglijkheid rechterknie"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Met deze activiteit wordt gemeten hoe ver je je linkerknie kunt strekken."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Met deze activiteit wordt gemeten hoe ver je je rechterknie kunt strekken."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Ga op de rand van een stoel zitten. Wanneer je begint, plaats je je apparaat op je linkerknie voor een meting. Schakel het geluid van je apparaat in zodat je instructies kunt horen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Ga op de rand van een stoel zitten. Wanneer je begint, plaats je je apparaat op je rechterknie voor een meting. Schakel het geluid van je apparaat in zodat je instructies kunt horen."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Plaats je apparaat op je linkerknie met het scherm naar boven en de leesrichting van je af, zoals in de afbeelding."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Plaats je apparaat op je rechterknie met het scherm naar boven en de leesrichting van je af, zoals in de afbeelding."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Wanneer je klaar bent, tik je op het scherm om te beginnen en strek je je linkerknie zo ver mogelijk uit. Breng je knie terug naar het beginpunt en tik opnieuw wanneer je klaar bent."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Wanneer je klaar bent, tik je op het scherm om te beginnen en strek je je rechterknie zo ver mogelijk. Breng je knie terug naar het beginpunt en tik opnieuw wanneer je klaar bent."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Plaats je apparaat op je linkerknie. Tik op het scherm en strek je linkerknie zo ver mogelijk."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Plaats je apparaat op je rechterknie. Tik op het scherm en strek je rechterknie zo ver mogelijk."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Wanneer je klaar bent, breng je je linkerknie terug naar het beginpunt. Tik vervolgens op een willekeurige plaats."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Wanneer je klaar bent, breng je je rechterknie terug naar het beginpunt. Tik vervolgens op een willekeurige plaats."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Beweeglijkheid linkerschouder"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Beweeglijkheid rechterschouder"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Met deze activiteit wordt gemeten hoe ver je je linkerschouder kunt strekken."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Met deze activiteit wordt gemeten hoe ver je je rechterschouder kunt strekken."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Wanneer je begint, plaats je je apparaat op je linkerschouder voor een meting. Schakel het geluid van je apparaat in zodat je instructies kunt horen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Wanneer je begint, plaats je je apparaat op je rechterschouder voor een meting. Schakel het geluid van je apparaat in zodat je instructies kunt horen."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Plaats je apparaat op je linkerschouder met het scherm naar boven en de leesrichting van je af, zoals in de afbeelding."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Plaats je apparaat op je rechterschouder met het scherm naar boven en de leesrichting van je af, zoals in de afbeelding."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Wanneer je klaar bent, tik je op het scherm om te beginnen en til je je linkerarm zo ver mogelijk op. Breng je arm terug naar het beginpunt en tik opnieuw wanneer je klaar bent."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Wanneer je klaar bent, tik je op het scherm om te beginnen en til je je rechterarm zo ver mogelijk op. Breng je arm terug naar het beginpunt en tik opnieuw wanneer je klaar bent."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Plaats je apparaat op je rechterschouder. Tik op het scherm en strek je linkerarm zo ver mogelijk naar voren."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Plaats je apparaat op je rechterschouder. Tik op het scherm en strek je rechterarm zo ver mogelijk naar voren."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Wanneer je klaar bent, breng je je linkerarm terug naar het beginpunt. Tik vervolgens op een willekeurige plaats."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Wanneer je klaar bent, breng je je rechterarm terug naar het beginpunt. Tik vervolgens op een willekeurige plaats."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Looptest"; +"TIMED_WALK_INTRO_DETAIL" = "Met deze activiteit wordt het functioneren van je onderlichaam gemeten."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Zoek een plek, bij voorkeur buiten, waar je veilig zo snel mogelijk ongeveer %@ in een rechte lijn kunt lopen. Vertraag je tempo niet totdat je voorbij de eindstreep bent."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tik op 'Volgende' om te beginnen."; +"TIMED_WALK_FORM_TITLE" = "Loophulpmiddel"; +"TIMED_WALK_FORM_TEXT" = "Gebruik hetzelfde hulpmiddel voor elke test."; +"TIMED_WALK_QUESTION_TEXT" = "Draag je een enkel-voetorthese?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Gebruik je een loophulpmiddel?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tik hier om een antwoord te kiezen."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Geen"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Eén wandelstok"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Eén kruk"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Twee wandelstokken"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Twee krukken"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Looprek/Rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Loop max. %@ in een rechte lijn."; +"TIMED_WALK_INSTRUCTION_TURN" = "Keer om."; +"TIMED_WALK_INSTRUCTION_2" = "Loop terug naar het beginpunt."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tik op 'Volgende' als je klaar bent."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Met de PASAT (een stapsgewijze auditieve seriële opteltest) wordt gemeten hoe snel je hoorbare informatie verwerkt en hoe goed je kunt rekenen."; +"PVSAT_INTRO_TEXT" = "Met de PVSAT (een stapsgewijze visuele seriële opteltest) wordt gemeten hoe snel je zichtbare informatie verwerkt en hoe goed je kunt rekenen."; +"PAVSAT_INTRO_TEXT" = "Met de PAVSAT (een stapsgewijze auditieve en visuele seriële opteltest) wordt gemeten hoe snel je hoorbare en zichtbare informatie verwerkt en hoe goed je kunt rekenen."; +"PSAT_INTRO_TEXT_2_%@" = "Elke %@ zie en/of hoor je een cijfer.\nJe moet elk nieuw cijfer optellen bij het vorige cijfer.\nLet op: je moet niet het totaal van alle cijfers berekenen, maar alleen de som van de laatste twee cijfers."; +"PSAT_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"PSAT_INITIAL_INSTRUCTION" = "Onthoud dit eerste cijfer."; +"PSAT_INSTRUCTION" = "Tel dit nieuwe cijfer op bij het vorige."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-schijventest"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Tijdens deze activiteit meet je het functioneren van je bovenste ledematen door een schijfje in een cirkel te plaatsen. Dit moet je %@ keer doen."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Zowel je linker- als rechterhand wordt getest.\nJe moet het schijfje zo snel mogelijk oppakken en in de cirkel plaatsen. Nadat je dit %@ keer hebt gedaan, moet je het schijfje %@ keer weer weghalen."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Zowel je rechter- als linkerhand wordt getest.\nJe moet het schijfje zo snel mogelijk oppakken en in de cirkel plaatsen. Nadat je dit %@ keer hebt gedaan, moet je het schijfje %@ keer weer weghalen."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Plaats met je linkerhand het schijfje in de cirkel."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Plaats met je rechterhand het schijfje in de cirkel."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Plaats met je linkerhand het schijfje achter de lijn."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Plaats met je rechterhand het schijfje achter de lijn."; +"HOLE_PEG_TEST_TEXT" = "Pak het schijfje op met twee vingers."; +"HOLE_PEG_TEST_TEXT_2" = "Til je vingers op om het schijfje los te laten."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Trillingsactiviteit"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Met deze activiteit wordt gemeten hoe sterk je handen trillen in verschillende posities. Ga naar een plek waar je comfortabel kunt zitten gedurende deze activiteit."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Houd de telefoon in de hand waarvan je de meeste last hebt, zoals hieronder afgebeeld."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Houd de telefoon in je RECHTERHAND, zoals hieronder afgebeeld."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Houd de telefoon in je LINKERHAND, zoals hieronder afgebeeld."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Je wordt gevraagd om %@ zittend uit te voeren met de telefoon in je hand."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "een taak"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "twee taken"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "drie taken"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "vier taken"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "vijf taken"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tik op 'Volgende' om door te gaan."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Bereid je voor om de telefoon in je schoot te houden."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Bereid je voor om de telefoon in je schoot te houden met je LINKERHAND."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Bereid je voor om de telefoon in je schoot te houden met je RECHTERHAND."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Houd de telefoon %ld seconden vast in je schoot."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Houd nu de telefoon op schouderhoogte in je uitgestoken hand."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Houd nu de telefoon op schouderhoogte in je uitgestoken LINKERHAND."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Houd nu de telefoon op schouderhoogte in je uitgestoken RECHTERHAND."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Houd de telefoon %ld seconden vast in je uitgestoken hand."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Houd nu de telefoon op schouderhoogte terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Houd nu de telefoon op schouderhoogte in je LINKERHAND terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Houd nu de telefoon op schouderhoogte in je RECHTERHAND terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Houd de telefoon %ld seconden vast terwijl je je elleboog gebogen houdt"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Raak nu je neus herhaaldelijk aan met de telefoon terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Houd nu de telefoon in je LINKERHAND en raak je neus herhaaldelijk aan met de telefoon terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Houd nu de telefoon in je RECHTERHAND en raak je neus herhaaldelijk aan met de telefoon terwijl je je elleboog gebogen houdt."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Raak %ld seconden je neus aan met de telefoon"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Bereid je voor om te wuiven vanuit de pols."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Bereid je voor om te wuiven vanuit de pols met de telefoon in je LINKERHAND."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Bereid je voor om te wuiven vanuit de pols met de telefoon in je RECHTERHAND."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Wuif %ld seconden vanuit de pols."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Neem de telefoon nu in je LINKERHAND en ga door met de volgende taak."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Neem de telefoon nu in je RECHTERHAND en ga door met de volgende taak."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Ga door naar de volgende taak."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activiteit voltooid."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Je wordt gevraagd om %@ zittend uit te voeren met de telefoon in de ene hand en daarna opnieuw met de telefoon in de andere hand."; +"TREMOR_SKIP_LEFT_HAND" = "Ik kan deze activiteit niet met mijn LINKERHAND uitvoeren."; +"TREMOR_SKIP_RIGHT_HAND" = "Ik kan deze activiteit niet met mijn RECHTERHAND uitvoeren."; +"TREMOR_SKIP_NEITHER" = "Ik kan deze activiteit met beide handen uitvoeren."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test 'Spoor maken'"; +"TRAILMAKING_INTENDED_USE" = "Met deze activiteit wordt je visuele aandacht en je vermogen om tussen taken te schakelen gemeten door de tijd vast te leggen die je nodig hebt om in de juiste volgorde op een reeks stippen te tikken."; +"TRAILMAKING_INTENDED_USE2_A" = "Tik na het aftellen op stippen, waarbij je afwisselend op cijfers en letters tikt. Begin door op het eerste cijfer '1' te tikken, gevolgd door de cijfers '2' – '3' – '4'… totdat je het cijfer '7' bereikt."; +"TRAILMAKING_INTENDED_USE2_B" = "Tik na het aftellen op stippen, waarbij je afwisselend op cijfers en letters tikt. Begin door op het eerste cijfer '1' te tikken, gevolgd door een tik op de eerste letter 'A', en dan '2' – 'B' – '3' – 'C'… totdat je het cijfer '7' bereikt."; +"TRAILMAKING_INTRO_TEXT" = "Doe dit zo snel als je kunt zonder fouten te maken. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Spraakherkenning"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Met deze activiteit neem je spraak op met de microfoon aan de onderzijde van het apparaat, waarna dit naar tekst wordt omgezet."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tik op 'Start' om te beginnen."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Druk op de knop om de opname te starten voordat je begint met praten."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start opname"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stop opname"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Wijzig transcriptie"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Wijzig de tekst van de transcriptie om eventuele fouten te corrigeren."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Je transcriptie verschijnt hier."; +"SPEECH_RECOGNITION_FAILED" = "Spraakherkenning mislukt."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Initialiseren van spraakherkenning is mislukt."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Speel audio af"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stop audio"; +"SPEECH_IN_NOISE_TITLE" = "Achtergrondgeluid"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Met deze activiteit meet je de verstaanbaarheid van spraak in omgevingen met veel geluid."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Als onderdeel van deze test ga je het volgende doen:\n\nLuister naar een zin.\n\nHerhaal duidelijk wat je hebt gehoord of ga door naar de volgende stap en typ wat je hebt gehoord met het toetsenbord. \n\nAls je herhaalt wat je hebt gehoord, heb je de mogelijkheid om de transcriptie die door de spraakherkenning is gegenereerd, te wijzigen."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volumekalibratie"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tik op 'Speel audio af', zet het volume op een prettig niveau en tik vervolgens op 'Stop audio' om verder te gaan."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Luister"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Er wordt slechts eenmaal een zin afgespeeld, waarbij achtergrondgeluid met een willekeurige signaal-ruisverhouding hoorbaar is."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Spreek"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Herhaal wat je hebt gehoord."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Bestand aanmaken mislukt"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Er kunnen niet genoeg logbestanden worden verwijderd om de drempel te halen"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Fout bij kenmerk instellen"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Bestand niet gemarkeerd als verwijderd (niet gemarkeerd als geüpload)"; +"ERROR_DATALOGGER_MULTIPLE" = "Meerdere fouten bij logbestanden verwijderen"; +"ERROR_RECORDER_NO_DATA" = "Geen verzamelde gegevens gevonden."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Geen uitvoerdirectory opgegeven"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL-meter"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Met deze activiteit meet je het niveau van de druk van het omgevingsgeluid. Als het ruisniveau te hoog is, kun je niet verdergaan. Ga naar een stillere locatie om deze taak uit te voeren of voer deze taak op een later tijdstip uit."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Berekenen"; +"ENVIRONMENTSPL_THRESHOLD" = "Drempelwaarde: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Achtergrondgeluid OK"; +"ENVIRONMENTSPL_NOISE" = "Te veel geluid op de achtergrond"; +"ENVIRONMENTSPL_TITLE_2" = "Zoek een rustige plek op"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Voor een grotere nauwkeurigheid moet deze test in een rustige omgeving worden uitgevoerd."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start taak"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Geen gegevens"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Versleep schuifknop om waarde in te voeren"; +"SLIDER_I_DONT_KNOW" = "Weet ik niet"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Pagina"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Terug"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Toon pdf-miniatuur"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Verberg pdf-miniatuur"; +"AX_BUTTON_ANNOTATE" = "Annoteer"; +"AX_BUTTON_SHOW_SEARCH" = "Toon zoekbalk"; +"AX_BUTTON_HIDE_SEARCH" = "Verberg zoekbalk"; +"AX_BUTTON_SHARE" = "Deel"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustratie van een vinkje in een blauwe cirkel ten teken van een geslaagde afronding"; + +"AX_SIGNVIEW_LABEL" = "Veld voor handtekening"; +"AX_SIGNVIEW_HINT" = "Beweeg je vinger over het scherm om je handtekening te zetten"; +"AX_SIGNVIEW_SIGNED" = "Ondertekend"; +"AX_SIGNVIEW_UNSIGNED" = "Niet ondertekend"; + +"AX_SELECTED" = "Geselecteerd"; +"AX_UNSELECTED" = "Selectie opgeheven"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECTEER ALLES WAT VAN TOEPASSING IS"; + +"AX_SLIDER_LABEL" = "Antwoordschuifknop. Bereik van %@ tot %@"; +"AX_UNLABELED_IMAGE" = "Naamloze afbeelding"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Begin met taak"; + +"AX.MEMORY.TILE.ACTIVE" = "actief"; +"AX.MEMORY.TILE.CORRECT" = "goed"; +"AX.MEMORY.TILE.INCORRECT" = "fout"; +"AX.MEMORY.TILE.QUIESCENT" = "inactief"; +"AX.MEMORY.TILE.LABEL" = "Tegel in geheugenspel"; + +"AX_IMAGE_CAPTURE_LABEL" = "Voorvertoning opname"; +"AX_IMAGE_CAPTURED_LABEL" = "Vastgelegde afbeelding"; + +"AX_VIDEO_CAPTURE_LABEL" = "Voorvertoning video-opname"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video vastleggen voltooid"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "De schijf met grootte %@ kan niet op de schijf met grootte %@ worden geplaatst."; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Doel"; +"AX_TOWER_OF_HANOI_TOWER" = "Toren"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Tik dubbel om de schijf te plaatsen"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Tik dubbel om de bovenste schijf te selecteren"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Heeft schijf met groottes %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Leeg"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Sluit toetsenbord"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Bereik van %@ tot %@"; +"AX_GRAPH_STACK_PREFIX" = "Stack bestaat uit"; +"AX_GRAPH_AND_SEPARATOR" = " en "; +"AX_GRAPH_POINT_%@" = "Punt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Spraakgolfvorm"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Activeer na het starten van de opname de regelaar een tweede keer om de opname te stoppen."; + +"AX_AUDIO_BAR_GRAPH" = "Audiostaafdiagram"; + +"AX_AMSLER_GRID_LABEL" = "Amslerrooster"; +"AX_AMSLER_GRID_HINT" = "Gebruik je vinger of stylus om rechtstreeks markeringen aan te brengen op het rooster of veeg naar links buiten het rooster om te stoppen."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tikbare knoppen"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tik voor linkeroor"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activeer om de test te starten. Wanneer de test start, tik je direct op deze knop wanneer je een geluid in je linkeroor hoort."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tik voor rechteroor"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activeer om de test te starten. Wanneer de test start, tik je direct op deze knop wanneer je een geluid in je rechteroor hoort."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Als je VoiceOver gebruikt, verken je het scherm door middel van aanraken om de locatie van de knoppen voor elk oor vast te stellen. Wanneer de test start, zijn de knoppen direct tikbaar. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tik voor één vinger"; +"AX_TAP_BUTTON_2_LABEL" = "Tik voor andere vinger"; +"AX_TAP_BUTTON_HINT" = "Activeer om knoppen direct tikbaar te maken."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Als je VoiceOver gebruikt, verken je het scherm door middel van aanraken om de locatie van de knoppen voor elk oor vast te stellen. Activeer de knoppen om ze direct tikbaar te maken."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Er kan nu direct op knoppen worden getikt."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Als je VoiceOver gebruikt, is de knop direct tikbaar. De knop bevindt zich midden op het scherm."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Als je VoiceOver gebruikt, zijn de knoppen in de test direct tikbaar."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Decoderen van restoreData voor initialisatie niet mogelijk"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..c9c20ed --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/nl.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d fout) + other + (%d fouten) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.strings new file mode 100755 index 0000000..c1d3dc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Samtykke"; +"CONSENT_NAME_GIVEN" = "Fornavn"; +"CONSENT_NAME_FAMILY" = "Etternavn"; +"CONSENT_NAME_PLACEHOLDER" = "Kreves"; +"CONSENT_REVIEW_TITLE" = "Se gjennom"; +"CONSENT_REVIEW_INSTRUCTION" = "Se gjennom skjemaet nedenfor, og trykk på Enig hvis du er klar til å fortsette."; +"CONSENT_REVIEW_ALERT_TITLE" = "Se gjennom"; +"CONSENT_SIGNATURE_TITLE" = "Signatur"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Signer med fingeren i ruten nedenfor."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Signer her"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Side %1$ld av %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Velkommen"; +"CONSENT_SECTION_DATA_GATHERING" = "Datainnsamling"; +"CONSENT_SECTION_PRIVACY" = "Personvern"; +"CONSENT_SECTION_DATA_USE" = "Databruk"; +"CONSENT_SECTION_STUDY_SURVEY" = "Undersøkelse"; +"CONSENT_SECTION_STUDY_TASKS" = "Oppgaver"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tidsbruk"; +"CONSENT_SECTION_WITHDRAWING" = "Avslutte studien"; +"CONSENT_LEARN_MORE_TITLE" = "Finn ut mer"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Finn ut mer om hvordan data samles inn"; +"LEARN_MORE_DATA_USE" = "Finn ut mer om hvordan dataene brukes"; +"LEARN_MORE_PRIVACY" = "Finn ut mer om hvordan personvernet og identiteten din beskyttes"; +"LEARN_MORE_WELCOME" = "Finn ut mer om studien"; +"LEARN_MORE_STUDY_SURVEY" = "Finn ut mer om undersøkelsen"; +"LEARN_MORE_TIME_COMMITMENT" = "Finn ut mer om hvor mye tid studien krever"; +"LEARN_MORE_TASKS" = "Finn ut mer om oppgavene i studien"; +"LEARN_MORE_WITHDRAWING" = "Finn ut mer om å avslutte studien"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Delingsvalg"; +"CONSENT_SHARE_WIDELY_%@" = "Del dataene dine med %@ og erfarne forskere over hele verden"; +"CONSENT_SHARE_ONLY_%@" = "Del data kun med %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ vil motta data fra undersøkelsen du deltar i.\n\nEn videre deling av dine kodede opplysninger (navn og lignende fjernes) kan komme til nytte både i denne og framtidige undersøkelser."; +"LEARN_MORE_CONSENT_SHARING" = "Finn ut mer om datadeling"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Navn (i blokkbokstaver)"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signatur"; +"CONSENT_DOC_LINE_DATE" = "Dato"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ av %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Spørsmål %1$@ av %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Hoppet over"; +"REVIEW_EDIT_ANSWER" = "Rediger"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Ugyldig verdi"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ overstiger høyest tillatte verdi (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ er mindre enn lavest tillatte verdi (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ er ikke en gyldig verdi."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Ugyldig e-postadresse: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Skriv inn en adresse"; +"LOCATION_ERROR_TITLE" = "Fant ikke angitt adresse"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Finner ikke din nåværende posisjon. Skriv inn adressen, eller gå om mulig til et sted med bedre GPS-signal."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Du har ikke gitt appen tilgang til stedstjenester. Du kan endre tilgangen til stedstjenester i Innstillinger."; +"LOCATION_ERROR_GEOCODE" = "Fant ingen treff for angitt adresse. Kontroller at adressen er riktig og prøv igjen."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Du er enten ikke koblet til internett, eller du har oversteget grensen for antall adressesøk. Hvis du ikke er koblet til internett, må du slå på Wi-Fi for å svare på spørsmålet. Du kan hoppe over spørsmålet hvis hopp over-knappen er tilgjengelig, eller komme tilbake til undersøkelsen når du er koblet til internett. Prøv ellers igjen om noen minutter."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Teksten overstiger makslengden: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kameraet er ikke tilgjengelig på delt skjerm."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-post"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Passord"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Oppgi passord"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Bekreft"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Oppgi passordet igjen"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Passordene er ikke like."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Tilleggsinformasjon"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Kjønn"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Angi kjønn"; +"DOB_FORM_ITEM_TITLE" = "Fødselsdato"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Angi dato"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonnummer"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+47 20 00 00 00"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verifisering"; +"VERIFICATION_STEP_TITLE" = "Verifiser e-postadressen"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Trykk på lenken nedenfor hvis du ikke mottok verifiseringsmeldingen på e-post og vil sende den på nytt."; +"RESEND_EMAIL_BUTTON_TITLE" = "Send verifiseringsmelding på nytt"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Logg på"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Glemt passordet?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Oppgi kode"; +"PASSCODE_CONFIRM_MESSAGE" = "Bekreft kode"; +"PASSCODE_SAVED_MESSAGE" = "Kode arkivert"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kode godkjent"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Oppgi den gamle koden"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Angi den nye koden"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Bekreft den nye koden"; +"PASSCODE_INVALID_ALERT_TITLE" = "Koden er feil"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Kodene er ikke like. Prøv igjen."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentiser med Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-feil"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Kun numeriske tegn er tillatt."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Framdriftsindikator for inntasting av kode"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ av %@ sifre oppgitt"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Glemt koden?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Kunne ikke legge til nøkkelringobjekt."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Kunne ikke oppdatere nøkkelringobjekt."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Kunne ikke slette nøkkelringobjekt."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Fant ikke nøkkelringobjekt."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Type 1"; +"FITZPATRICK_SKIN_TYPE_II" = "Type 2"; +"FITZPATRICK_SKIN_TYPE_III" = "Type 3"; +"FITZPATRICK_SKIN_TYPE_IV" = "Type 4"; +"FITZPATRICK_SKIN_TYPE_V" = "Type 5"; +"FITZPATRICK_SKIN_TYPE_VI" = "Type 6"; + +/* Gender values. */ +"GENDER_FEMALE" = "Kvinne"; +"GENDER_MALE" = "Mann"; +"GENDER_OTHER" = "Annet"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nei"; +"BOOL_YES" = "Ja"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "fot"; +"MEASURING_UNIT_IN" = "to"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "pund"; +"MEASURING_UNIT_OZ" = "unse(r)"; + +/* Limb values. */ +"LIMB_LEFT" = "venstre"; +"LIMB_RIGHT" = "høyre"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Trykk for å svare"; +"NULL_ANSWER" = "Velg et svar"; +"PLACEHOLDER_IMAGE_CHOICES" = "Trykk for å velge"; +"PLACEHOLDER_LONG_TEXT" = "Trykk for å skrive"; + +/* Button titles */ +"BUTTON_AGREE" = "Enig"; +"BUTTON_CANCEL" = "Avbryt"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Fjern"; +"BUTTON_CLEAR_SIGNATURE" = "Fjern signatur"; +"BUTTON_APPLY" = "Bruk"; +"BUTTON_DISAGREE" = "Uenig"; +"BUTTON_DONE" = "Ferdig"; +"BUTTON_GET_STARTED" = "Start"; +"BUTTON_LEARN_MORE" = "Finn ut mer"; +"BUTTON_NEXT" = "Neste"; +"BUTTON_SKIP" = "Hopp over"; +"BUTTON_SKIP_QUESTION" = "Hopp over spørsmålet"; +"BUTTON_START_TIMER" = "Start tidtaker"; +"BUTTON_OPTION_SAVE" = "Spar til senere"; +"BUTTON_OPTION_DISCARD" = "Forkast resultater"; +"BUTTON_OPTION_STOP_TASK" = "Avslutt oppgave"; +"BUTTON_SAVE" = "Arkiver"; +"BUTTON_CLEAR_ANSWER" = "Fjern svar"; +"BUTTON_READ_ONLY_MODE" = "Dette svaret kan ikke endres."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Lukk"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Starter aktivitet om"; +"TASK_COMPLETE_TITLE" = "Aktivitet fullført"; +"TASK_COMPLETE_TEXT" = "Dataene vil bli analysert, og du blir varslet når resultatene er klare."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ gjenstår."; +"TOUCH_ANYWHERE_LABEL" = "Berør hvor som helst for å fortsette"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Ta bilde"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Ta nytt bilde"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Finner ikke kamera. Trinnet kunne ikke fullføres."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "For å fullføre trinnet må du først gi appen tilgang til kameraet i Innstillinger."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Du har ikke angitt en katalog for bildene du tar."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Bildet kunne ikke arkiveres."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Start opptak"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stopp opptak"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Spill inn video på nytt"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kondisjon"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Strekning (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Puls (slag/min)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sitt komfortabelt i %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Gå så fort du kan i %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Denne aktiviteten leser av pulsen din og måler hvor langt du kan gå på %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Gå utendørs så fort du kan i %1$@. Når du er ferdig, setter du deg og hviler komfortabelt i %2$@. Trykk på Start for å begynne."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Balanse og gange"; +"WALK_INTRO_TEXT" = "Denne aktiviteten måler balansen og gangen din mens du går og står i ro. Ikke fortsett hvis du ikke kan gå trygt uten hjelp."; +"WALK_INTRO_2_TEXT_%ld" = "Finn et sted der du trygt og uten hjelp kan gå omtrent %ld skritt i rett linje."; +"WALK_INTRO_2_DETAIL" = "Legg enheten i lommen eller en veske, og følg lydinstruksjonene."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Stå stille i %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stå stille i %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Snu og gå tilbake der du startet."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Gå opptil %ld skritt i rett linje."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Finn et sted hvor du trygt kan gå fram og tilbake i en rett linje. Prøv å gå kontinuerlig når du skal snu, som om du skal gå rundt en kjegle.\n\nDu vil bli bedt om å snu deg helt rundt og deretter stå helt stille med armene ned langs siden og føttene med en skulderbreddes avstand."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Trykk på Kom i gang når du er klar til å starte.\nLegg deretter enheten i en lomme eller veske, og følg lydinstruksjonene."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Gå fram og tilbake i en rett linje i %@. Gå så normalt så mulig."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Snu deg helt rundt og stå stille i %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Du har fullført aktiviteten."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Trykkhastighet"; +"TAPPING_TASK_TITLE_RIGHT" = "Høyre hånd"; +"TAPPING_TASK_TITLE_LEFT" = "Venstre hånd"; +"TAPPING_INTRO_TEXT" = "Denne aktiviteten måler trykkhastigheten din."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Plasser enheten på et flatt underlag."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Bruk to fingre på samme hånd til å trykke vekselvis på knappene på skjermen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Bruk to fingre på høyre hånd til å trykke vekselvis på knappene på skjermen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Bruk to fingre på venstre hånd til å trykke vekselvis på knappene på skjermen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Gjør den samme testen med høyre hånd."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Gjør den samme testen med venstre hånd."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Trykk med én finger, og deretter den andre. Veksle mellom knappene i jevne intervaller. Fortsett å trykke i %@."; +"TAPPING_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Trykk på Neste for å begynne."; +"TAP_BUTTON_TITLE" = "Trykk"; +"TOTAL_TAPS_LABEL" = "Trykk totalt"; +"TAPPING_INSTRUCTION" = "Trykk på knappene så jevnt som du klarer, med to fingre."; +"TAPPING_INSTRUCTION_RIGHT" = "Trykk på knappene med din HØYRE hånd."; +"TAPPING_INSTRUCTION_LEFT" = "Trykk på knappene med din VENSTRE hånd."; +"TAPPING_SKIP_TITLE" = "Utelat denne hånden"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler-rutenett"; +"AMSLER_GRID_INTRO_TEXT" = "Denne aktiviteten kan bidra til å avdekke en persons synsproblemer."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Hold enheten 30 cm fra ansiktet og i øyehøyde gjennom hele testen."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Lukk %@ og se på prikken i midten av rutenettet.\n\nBruk fingeren eller en stylus til å markere alle forstyrrelser i form av uskarpe eller bølgende linjer.\n\nSveip mot venstre hvor som helst utenfor rutenettet når du er ferdig."; +"AMSLER_GRID_LEFT_EYE" = "venstre øye"; +"AMSLER_GRID_RIGHT_EYE" = "høyre øye"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Stemme"; +"AUDIO_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"AUDIO_INSTRUCTION" = "Si «aaa» inn i mikrofonen så lenge du klarer."; +"AUDIO_INTRO_TEXT" = "Trekk pusten dypt inn og si «aaa» inn i mikrofonen så lenge du klarer. Hold et jevnt volum slik at lydstolpene forblir blå."; +"AUDIO_INTENDED_USE" = "Denne aktiviteten vil evaluere stemmen din ved å ta den opp i mikrofonen i nedre kant av enheten."; +"AUDIO_TOO_LOUD_LABEL" = "For høyt"; +"AUDIO_GENERIC_ERROR_LABEL" = "Kan ikke ta opp lyd"; +"AUDIO_LEVEL_CHECK_LABEL" = "Vent mens vi kontrollerer støynivået i bakgrunnen."; +"AUDIO_TOO_LOUD_MESSAGE" = "Støynivået fra omgivelsene er for høyt til å gjøre opptak av stemmen din. Gå til et sted mindre støy, og prøv igjen."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Trykk på Neste når du er klar."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Toneaudiometri"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Aktiviteten måler hvor godt du hører ulike lyder."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Før du starter, må du plugge i hodetelefonene og ta dem på.\n\nLyden er svært svak og ulik vanlige varseltoner. Lyden begynner svakt og øker gradvis i volum. Konsentrer deg og trykk på venstre eller høyre knapp for å indikere hvilket øre du hører lyden i."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Du bør nå høre en tone. Juster volumet med kontrollene på siden av enheten.\n\nTrykk på en hvilken som helst knapp når du er klar til å begynne."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Hver gang du hører en lyd, må du trykke på venstre eller høyre knapp for å indikere hvilket øre du hører lyden i."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Venstre øre"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Høyre øre"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, venstre"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, høyre"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Toneaudiometri"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Trykk når du hører en tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tone og volum"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Du vil høre en rekke med toner."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Trykk på knappen når du hører en tone."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "I denne testen settes volumet til 50 prosent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Testen tar ca. 10 minutter."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Slå på Ikke forstyrr for å unngå forstyrrelser."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Toner spilles først av i det høyre øret ditt."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Toner spilles nå av i det venstre øret ditt."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Denne aktiviteten identifiserer en persons hørselsterskel målt i dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Sjekk at volumet på enheten er skrudd helt opp.\n\nUnder denne oppgaven vil du høre en svak tone i enten venstre eller høyre øre.\n\nHør nøye etter og trykk på knappen hver gang du hører en tone."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Denne testen måler hvor høy en lyd må være før du hører den."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Introduksjonsskjema."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Angi eventuelt hvilket øre du hører best på"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "venstre"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "høyre"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ingen preferanse"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test avbrutt"; +"dBHL_ALERT_TITLE_START_OVER" = "Start på nytt"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Avbryt test"; +"dBHL_ALERT_TEXT" = "For å ta denne testen koble til AirPods eller EarPods på nytt."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ fullført"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Hodetelefoner"; +"HEADPHONES_UNKNOWN" = "Ukjent"; +"HEADPHONES_NONE" = "Ingen"; +"CONNECTED" = "Tilkoblet"; +"NOT_CONNECTED" = "Ikke tilkoblet"; +"HEADPHONE_CONNECTED_%@" = "Tilkoblet – %@"; +"HEADPHONE_DETECT_TITLE" = "Koble til hodetelefonene dine"; +"HEADPHONE_DETECT_TEXT" = "Denne testen krever Apple AirPods eller Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Visuell hukommelse"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Denne aktiviteten måler den visuelle korttidshukommelsen din ved å be deg gjenta i hvilken rekkefølge %@ lyser."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "blomstene"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "blomstene"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Noen av %@ vil lyse én om gangen. Trykk på disse %@ i samme rekkefølge som de lyser opp."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Noen av %@ vil lyse én om gangen. Trykk på disse %@ i omvendt rekkefølge av hvordan de lyser opp."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Begynn ved å trykke på Start, og følg så nøye med."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Poeng"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Se %@ lyse opp"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Trykk på %@ i samme rekkefølge som de lyste"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Trykk på %@ i omvendt rekkefølge"; +"MEMORY_GAME_COMPLETE_TITLE" = "Mønster fullført"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Trykk på Neste for å fortsette"; +"MEMORY_GAME_FAILED_TITLE" = "Prøv igjen"; +"MEMORY_GAME_FAILED_MESSAGE" = "Testbesvarelsen var ikke helt riktig. Trykk på Neste for å fortsette."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Tiden er ute"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Du gikk over tiden.\nTrykk på Neste for å fortsette."; +"MEMORY_GAME_COMPLETE" = "Spill ferdig"; +"MEMORY_GAME_PAUSED_TITLE" = "Pause"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Trykk på Neste for å fortsette"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Hukommelsesaktiviteten er utviklet i samarbeid med Katherine Possin, PhD og Joel Kramer, PhD fra University of California i San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaksjonstid"; +"REACTION_TIME_TASK_INTENDED_USE" = "Aktiviteten måler hvor lang tid det tar før du reagerer på visuelle signaler."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Rist enheten så snart du ser den blå prikken vises på skjermen. Du vil bli bedt om å gjøre dette %D ganger."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Forsøk %@ av %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Rist enheten fort når den blå sirkelen vises"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Hver gang et ord vises, må du velge de to første bokstavene i navnet på FARGEN som vises."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Trykk på Start når du er klar til å starte Stroop-aktiviteten."; +"STROOP_TASK_STEP_TEXT" = "Velg de to første bokstavene i navnet på FARGEN som vises."; +"STROOP_COLOR_RED" = "RØD"; +"STROOP_COLOR_GREEN" = "GRØNN"; +"STROOP_COLOR_BLUE" = "BLÅ"; +"STROOP_COLOR_YELLOW" = "GUL"; +"STROOP_COLOR_RED_INITIAL" = "Rø"; +"STROOP_COLOR_GREEN_INITIAL" = "Gr"; +"STROOP_COLOR_BLUE_INITIAL" = "Bl"; +"STROOP_COLOR_YELLOW_INITIAL" = "Gu"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tårnet i Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Denne aktiviteten vurderer evnen din til å løse oppgaver."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Flytt hele stabelen til den markerte plattformen med så få trekk som mulig."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Løs oppgaven"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Antall trekk: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Jeg klarer ikke å løse oppgaven"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Bevegelsesområde"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption må være venstre eller høyre"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Bevegelsesområde for venstre kne"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Bevegelsesområde for høyre kne"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Denne aktiviteten måler hvor mye bevegelighet du har i venstre kne."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Denne aktiviteten måler hvor mye bevegelighet du har i høyre kne."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sett deg på kanten av stolen. Når du starter, må du legge enheten på venstre kne for en måling. Slå på lyden på enheten så du kan høre instruksjonene."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sett deg på kanten av stolen. Når du starter, må du legge enheten på høyre kne for en måling. Slå på lyden på enheten så du kan høre instruksjonene."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Legg enheten på venstre kne med skjermen vendt utover, som illustrert på bildet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Legg enheten på høyre kne med skjermen vendt utover, som illustrert på bildet."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Trykk på skjermen for å begynne, og strekk ut venstre bein slå langt du klarer. Flytt tilbake til startposisjonen og trykk en gang til når du er ferdig."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Trykk på skjermen for å begynne, og strekk ut høyre bein slå langt du klarer. Flytt tilbake til startposisjonen og trykk en gang til når du er ferdig."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Plasser enheten din på venstre kne. Trykk på skjermen og strekk ut venstre bein så langt du kan."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Plasser enheten din på høyre kne. Trykk på skjermen og strekk ut høyre bein så langt du kan."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Før venstre bein tilbake til startposisjonen når du er ferdig. Trykk så hvor som helst på skjermen."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Før høyre bein tilbake til startposisjonen når du er ferdig. Trykk så hvor som helst på skjermen."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Bevegelsesområde for venstre skulder"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Bevegelsesområde for høyre skulder"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Denne aktiviteten måler hvor mye bevegelighet du har i venstre skulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Denne aktiviteten måler hvor mye bevegelighet du har i høyre skulder."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Når du starter, må du legge enheten på venstre skulder for en måling. Slå på lyden på enheten så du kan høre instruksjonene."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Når du starter, må du legge enheten på høyre skulder for en måling. Slå på lyden på enheten så du kan høre instruksjonene."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Legg enheten på venstre skulder med skjermen vendt utover, som illustrert på bildet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Legg enheten på høyre skulder med skjermen vendt utover, som illustrert på bildet."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Trykk på skjermen for å begynne, og hev venstre arm slå langt du klarer. Flytt tilbake til startposisjonen og trykk en gang til når du er ferdig."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Trykk på skjermen for å begynne, og hev høyre arm slå langt du klarer. Flytt tilbake til startposisjonen og trykk en gang til når du er ferdig."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Plasser enheten din på venstre skulder. Trykk på skjermen og hev venstre arm så langt fram du klarer."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Plasser enheten din på høyre skulder. Trykk på skjermen og hev høyre arm så langt fram du klarer."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Før venstre arm tilbake til startposisjonen når du er ferdig. Trykk så hvor som helst på skjermen."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Før høyre arm tilbake til startposisjonen når du er ferdig. Trykk så hvor som helst på skjermen."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Gå på tid"; +"TIMED_WALK_INTRO_DETAIL" = "Denne aktiviteten måler funksjonen i nedre kroppshalvdel."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Finn et sted, helst utendørs, der du trygt kan gå omtrent %@ i rett linje, så raskt som mulig. Ikke senk farten før etter at du har passert mållinjen."; +"TIMED_WALK_INTRO_2_DETAIL" = "Trykk på Neste for å begynne."; +"TIMED_WALK_FORM_TITLE" = "Hjelpemiddel"; +"TIMED_WALK_FORM_TEXT" = "Bruk samme hjelpemiddel i hver test."; +"TIMED_WALK_QUESTION_TEXT" = "Bruker du en ankelortose?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Bruker du et hjelpemiddel?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Trykk her for å velge et svar."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Ingen"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Én stokk"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Én krykke"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "To stokker"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "To krykker"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Gåstol/rullator"; +"TIMED_WALK_INSTRUCTION_%@" = "Gå opptil %@ i rett linje."; +"TIMED_WALK_INSTRUCTION_TURN" = "Snu."; +"TIMED_WALK_INSTRUCTION_2" = "Gå tilbake der du startet."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Trykk på Neste når du har fullført oppgaven."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT-testen (Paced Auditory Serial Addition Test) måler hvor raskt du behandler lydinformasjon og evnen din til å gjøre utregninger."; +"PVSAT_INTRO_TEXT" = "PVSAT-testen (Paced Visual Serial Addition Test) måler hvor raskt du behandler synsinformasjon og evnen din til å gjøre utregninger."; +"PAVSAT_INTRO_TEXT" = "PAVSAT-testen (Paced Auditory and Visual Serial Addition Test) måler hvor raskt du behandler lyd- og synsinformasjon og evnen din til å gjøre utregninger."; +"PSAT_INTRO_TEXT_2_%@" = "Enkeltsifre vises i %@s intervaller.\nDu må legge det nye sifferet sammen med det som ble vist rett før.\nMerk at du ikke skal summere alle tallene, bare de to som ble vist sist."; +"PSAT_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"PSAT_INITIAL_INSTRUCTION" = "Husk dette første sifferet."; +"PSAT_INSTRUCTION" = "Legg dette nye sifferet til det forrige."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-hulls pluggtest"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "I denne aktiviteten skal du plassere en plugg i et hull for å måle funksjonen i armene dine. Du vil bli bedt om å gjøre det %@ ganger."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Både venstre og høyre hånd vil bli testet.\nDu må plukke opp pluggen så fort som mulig og legge den i hullet. Gjør dette %@ ganger, og fjern den så igjen %@ ganger."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Både høyre og venstre hånd vil bli testet.\nDu må plukke opp pluggen så fort som mulig og legge den i hullet. Gjør dette %@ ganger, og fjern den så igjen %@ ganger."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Plasser pluggen i hullet med venstre hånd."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Plasser pluggen i hullet med høyre hånd."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Plasser pluggen bak streken med venstre hånd."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Plasser pluggen bak streken med høyre hånd."; +"HOLE_PEG_TEST_TEXT" = "Bruk to fingre til å løfte opp pluggen."; +"HOLE_PEG_TEST_TEXT_2" = "Løft fingrene for å slippe pluggen."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Skjelving"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Denne aktiviteten måler skjelving i hendene dine i forskjellige posisjoner. Finn et sted hvor du kan sitte i ro i løpet av denne aktiviteten."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Hold telefonen i hånden som er hardest rammet, som vist i bildet nedenfor."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Hold telefonen i din HØYRE hånd som vist i bildet nedenfor."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Hold telefonen i din VENSTRE hånd som vist i bildet nedenfor."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Du vil bli bedt om å utføre %@ mens du sitter med telefonen i den ene hånden."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "en oppgave"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "to oppgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tre oppgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "fire oppgaver"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "fem oppgaver"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Trykk på Neste for å gå videre."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Forbered deg på å holde telefonen i fanget."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Forbered deg på å holde telefonen i fanget med VENSTRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Forbered deg på å holde telefonen i fanget med HØYRE hånd."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Hold telefonen i fanget i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Hold telefonen med utstrakt hånd i skulderhøyde."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Hold telefonen med VENSTRE hånd utstrakt i skulderhøyde."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Hold telefonen med HØYRE hånd utstrakt i skulderhøyde."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Hold telefonen med utstrakt hånd i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Hold telefonen i skulderhøyde med albuen bøyd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Hold telefonen med VENSTRE hånd i skulderhøyde med albuen bøyd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Hold telefonen med HØYRE hånd i skulderhøyde med albuen bøyd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Hold telefonen med albuen bøyd i %ld sekunder"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Hold albuen bøyd, og trykk telefonen mot nesen gjentatte ganger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Hold albuen bøyd med telefonen i VENSTRE hånd, og trykk telefonen mot nesen gjentatte ganger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Hold albuen bøyd med telefonen i HØYRE hånd, og trykk telefonen mot nesen gjentatte ganger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Hold telefonen mot nesen i %ld sekunder"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Forbered deg på å vinke som en dronning (vink ved å vri på håndleddet)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Forbered deg på å vinke som en dronning med telefonen i VENSTRE hånd (vink ved å vri på håndleddet)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Forbered deg på å vinke som en dronning med telefonen i HØYRE hånd (vink ved å vri på håndleddet)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Vink som en dronning i %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Flytt telefonen til VENSTRE hånd, og fortsett oppgaven."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Flytt telefonen til HØYRE hånd, og fortsett oppgaven."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Fortsett til neste oppgave."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivitet fullført."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Du vil bli bedt om å utføre %@ mens du sitter med telefonen i den ene hånden, og deretter igjen med den andre hånden."; +"TREMOR_SKIP_LEFT_HAND" = "Jeg kan ikke utføre denne aktiviteten med min VENSTRE hånd."; +"TREMOR_SKIP_RIGHT_HAND" = "Jeg kan ikke utføre denne aktiviteten med min HØYRE hånd."; +"TREMOR_SKIP_NEITHER" = "Jeg kan utføre denne aktiviteten med begge hender."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Oppmerksomhetstest"; +"TRAILMAKING_INTENDED_USE" = "Aktiviteten måler visuell reaksjonsevne og evne til å bytte oppgave ved at den måler tiden det tar å trykke på en rekke prikker i en bestemt rekkefølge."; +"TRAILMAKING_INTENDED_USE2_A" = "Etter nedtellingen trykker du vekselvis på prikker med tall og bokstaver. Begynn med å trykke på det første tallet, '1', etterfulgt av tallene '2' – '3' – '4'… til du kommer til tallet '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "Etter nedtellingen trykker du vekselvis på prikker med tall og bokstaver. Begynn med å trykke på det første tallet, '1', og deretter trykke på den første bokstaven, ‘A’. Deretter trykker du på '2' – 'B' – '3' – 'C'… til du kommer til tallet '7'."; +"TRAILMAKING_INTRO_TEXT" = "Gjør dette så fort du klarer uten å gjøre feil. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Talegjenkjenning"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Denne aktiviteten tar opp tale med mikrofonen i nedre kant av enheten og oversetter tale til tekst."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Trykk på Start for å begynne."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Trykk på knappen for å starte opptaket før du begynner å snakke."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Start opptak"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stopp opptak"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Rediger avskrift"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Rediger avskriftteksten for å rette opp eventuelle misoppfatninger av tale."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Avskriften din vises her."; +"SPEECH_RECOGNITION_FAILED" = "Talegjenkjenning mislyktes."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Kunne ikke initialisere talegjenkjenning."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Spill av lyd"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stopp lyd"; +"SPEECH_IN_NOISE_TITLE" = "Tale og støy"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Denne aktiviteten måler hvor godt du hører tale i støyende omgivelser."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Som del av denne testen skal du:\n\nLytte til en setning.\n\nGjenta tydelig det du hørte, eller bruke tastaturet til å skrive inn det du hørte. \n\nHvis du gjentar det du hørte, vil du ha muligheten til å endre avskriften som genereres av talegjenkjenningsmotoren."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volumkalibrering"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Trykk på «Spill av lyd», juster volumet til et behagelig nivå, og trykk deretter på «Stopp lyd» for å fortsette."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Lytt"; +"SPEECH_IN_NOISE_STEP_TEXT" = "En setning blandet med bakgrunnsstøy vil bli spilt av én gang med et tilfeldig signal-til-støy-forhold (SNR)."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Les opp"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Gjenta det du hørte."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Kunne ikke opprette fil"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Kunne ikke fjerne nok loggfiler til å nå grensen"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Feil ved angivelse av attributt"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Fil er ikke merket som slettet (ikke merket som opplastet)"; +"ERROR_DATALOGGER_MULTIPLE" = "Flere feil ved fjerning av logger"; +"ERROR_RECORDER_NO_DATA" = "Fant ingen innsamlede data."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Ingen katalog angitt"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Desibelmåler"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Denne aktiviteten måler lydtrykksnivået i miljøet. Det er ikke mulig å fortsette hvis støynivået er for høyt. Flytt til et sted med mindre støy for å fullføre denne oppgaven, eller utfør denne aktiviteten på et senere tidspunkt."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Beregner"; +"ENVIRONMENTSPL_THRESHOLD" = "Terskel: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Omgivelsesstøy OK"; +"ENVIRONMENTSPL_NOISE" = "For mye bakgrunnsstøy"; +"ENVIRONMENTSPL_TITLE_2" = "Finn et rolig sted"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Testen bør tas i stille omgivelser for å sikre et nøyaktig resultat."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Start oppgave"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Ingen data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Flytt skyveknappen for å oppgi en verdi"; +"SLIDER_I_DONT_KNOW" = "Jeg vet ikke"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Side"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Tilbake"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Vis PDF-miniatyrbilde"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Skjul PDF-miniatyrbilde"; +"AX_BUTTON_ANNOTATE" = "Merknad"; +"AX_BUTTON_SHOW_SEARCH" = "Vis søkelinje"; +"AX_BUTTON_HIDE_SEARCH" = "Skjul søkelinje"; +"AX_BUTTON_SHARE" = "Del"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustrasjon av et hakemerke i en blå sirkel som viser at det er fullført"; + +"AX_SIGNVIEW_LABEL" = "Eget signaturfelt"; +"AX_SIGNVIEW_HINT" = "Berør skjermen og flytt fingeren for å signere"; +"AX_SIGNVIEW_SIGNED" = "Signert"; +"AX_SIGNVIEW_UNSIGNED" = "Ikke signert"; + +"AX_SELECTED" = "Markert"; +"AX_UNSELECTED" = "Ikke markert"; +"AX_SELECT_ALL_THAT_APPLY" = "MERK AV ALT SOM GJELDER"; + +"AX_SLIDER_LABEL" = "Svarskyveknapp fra %@ til %@"; +"AX_UNLABELED_IMAGE" = "Bilde uten etikett"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Start oppgave"; + +"AX.MEMORY.TILE.ACTIVE" = "aktiv"; +"AX.MEMORY.TILE.CORRECT" = "riktig"; +"AX.MEMORY.TILE.INCORRECT" = "feil"; +"AX.MEMORY.TILE.QUIESCENT" = "inaktiv"; +"AX.MEMORY.TILE.LABEL" = "Brikke i bildelottospill"; + +"AX_IMAGE_CAPTURE_LABEL" = "Forhåndsvisning av bilde"; +"AX_IMAGE_CAPTURED_LABEL" = "Tatt bilde"; + +"AX_VIDEO_CAPTURE_LABEL" = "Forhåndsvisning av videoopptak"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Videoopptak fullført"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Kan ikke plassere skive med størrelse %@ på skive med størrelse %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Mål"; +"AX_TOWER_OF_HANOI_TOWER" = "Tårn"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Dobbelttrykk for å plassere skiven"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Dobbelttrykk for å velge øverste skive"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Har skive med størrelse %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Tom"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Lukk tastatur"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Område fra %@ til %@"; +"AX_GRAPH_STACK_PREFIX" = "Stabel bestående av"; +"AX_GRAPH_AND_SEPARATOR" = " og "; +"AX_GRAPH_POINT_%@" = "Punkt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Talebølgeform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Når opptaket starter, må du aktivere det en gang til for å stoppe opptaket."; + +"AX_AUDIO_BAR_GRAPH" = "Lydgraf"; + +"AX_AMSLER_GRID_LABEL" = "Amsler-rutenett"; +"AX_AMSLER_GRID_HINT" = "Bruk fingeren eller en stylus til å merke rett i rutenettet, eller sveip til venstre utenfor rutenettet for å avslutte."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Trykkbare knapper"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Trykk for venstre øre"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktiver for å starte testen. Når testen har startet, trykker du på denne knappen når du hører en lyd i venstre øre."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Trykk for høyre øre"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktiver for å starte testen. Når testen har startet, trykker du på denne knappen når du hører en lyd i høyre øre."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Bruk berøring for å utforske hvor hver knapp er på skjermen når du bruker VoiceOver. Når testen starter, kan du trykke på knappene direkte. %@ "; +"AX_TAP_BUTTON_1_LABEL" = "Trykk med én finger"; +"AX_TAP_BUTTON_2_LABEL" = "Trykk med en annen finger"; +"AX_TAP_BUTTON_HINT" = "Aktiver for å kunne trykke på knappene direkte."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Bruk berøring for å utforske hvor knappene er på skjermen når du bruker VoiceOver. Aktiver en av knappene så du kan trykke på dem direkte."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Knappene kan nå trykkes på direkte."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Denne knappen kan trykkes på direkte når du bruker VoiceOver. Den vil være plassert nær midten av skjermen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Knappene i testen kan trykkes på direkte også når du bruker VoiceOver."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Kan ikke dekode restoreData for initialisering"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..1965c49 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/no.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d feil) + other + (%d feil) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.strings new file mode 100755 index 0000000..7604fed --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Zgoda"; +"CONSENT_NAME_GIVEN" = "Imię"; +"CONSENT_NAME_FAMILY" = "Nazwisko"; +"CONSENT_NAME_PLACEHOLDER" = "Wymagane"; +"CONSENT_REVIEW_TITLE" = "Przejrzyj"; +"CONSENT_REVIEW_INSTRUCTION" = "Przejrzyj poniższy formularz i stuknij w Akceptuję, aby kontynuować."; +"CONSENT_REVIEW_ALERT_TITLE" = "Przejrzyj"; +"CONSENT_SIGNATURE_TITLE" = "Podpis"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Podpisz palcem w polu poniżej."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Podpisz tutaj"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Strona %1$ld z %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Witamy"; +"CONSENT_SECTION_DATA_GATHERING" = "Gromadzenie danych"; +"CONSENT_SECTION_PRIVACY" = "Prywatność"; +"CONSENT_SECTION_DATA_USE" = "Użycie danych"; +"CONSENT_SECTION_STUDY_SURVEY" = "Ankieta badawcza"; +"CONSENT_SECTION_STUDY_TASKS" = "Zadania badawcze"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Zobowiązanie czasowe"; +"CONSENT_SECTION_WITHDRAWING" = "Wycofywanie zgody"; +"CONSENT_LEARN_MORE_TITLE" = "Więcej informacji"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Więcej informacji o gromadzeniu danych"; +"LEARN_MORE_DATA_USE" = "Więcej informacji o wykorzystywaniu danych"; +"LEARN_MORE_PRIVACY" = "Więcej informacji o ochronie prywatności i tożsamości"; +"LEARN_MORE_WELCOME" = "Na początek: więcej informacji o badaniu"; +"LEARN_MORE_STUDY_SURVEY" = "Więcej informacji o ankiecie"; +"LEARN_MORE_TIME_COMMITMENT" = "Więcej informacji o wymogach czasowych badania"; +"LEARN_MORE_TASKS" = "Więcej informacji o zadaniach"; +"LEARN_MORE_WITHDRAWING" = "Więcej informacji o wycofywaniu się z badania"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opcje udostępniania"; +"CONSENT_SHARE_WIDELY_%@" = "%@ i wykwalifikowani badacze z całego świata mogą uzyskać moje dane"; +"CONSENT_SHARE_ONLY_%@" = "Tylko %@ może uzyskać moje dane"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ otrzyma wyniki badań w zakresie wynikającym z Twojego udziału w tym badaniu.\n\nUdostępnianie zakodowanych wyników badań szerszej grupie odbiorców (bez informacji takich jak imię i nazwisko) może przynieść korzyści z tych i przyszłych badań."; +"LEARN_MORE_CONSENT_SHARING" = "Więcej informacji o udostępnianiu danych"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Imię i nazwisko"; +"CONSENT_DOC_LINE_SIGNATURE" = "Podpis"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ z %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pytanie %1$@ z %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Pominięta"; +"REVIEW_EDIT_ANSWER" = "Edycja"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Nieprawidłowa wartość"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ przekracza maksymalną dozwoloną wartość (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ nie przekracza minimalnej dozwolonej wartości (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ nie jest poprawną wartością."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Nieprawidłowy adres email: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Podaj adres"; +"LOCATION_ERROR_TITLE" = "Nie można było znaleźć określonego adresu"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Nie można określić Twojego bieżącego położenia. Podaj adres lub przenieś się w miejsce z lepszym sygnałem GPS."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Nastąpiła odmowa dostępu do usług lokalizacji. Przejdź do Ustawień i pozwól tej aplikacji używać usług lokalizacji."; +"LOCATION_ERROR_GEOCODE" = "Nie można znaleźć wyniku dla podanego adresu. Upewnij się, że adres jest prawidłowy."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Nie masz połączenia z Internetem lub przekroczona została maksymalna liczba żądań wyszukiwania adresu. Jeśli nie masz połączenia z Internetem, włącz sieć Wi-Fi, aby odpowiedzieć na to pytanie, pomiń pytanie (jeśli dostępny jest przycisk pomijania) lub powróć do ankiety po nawiązaniu połączenia z Internetem. W przeciwnym przypadku spróbuj ponownie za kilka minut."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Przekroczony limit długości tekstu: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera niedostępna na ekranie podzielonym."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jjablonka@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Hasło"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Podaj hasło"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Potwierdź"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Powtórz hasło"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Hasła są niezgodne."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informacje dodatkowe"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Jan"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Jabłonka"; +"GENDER_FORM_ITEM_TITLE" = "Płeć"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Wybierz płeć"; +"DOB_FORM_ITEM_TITLE" = "Data urodzenia"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Wybierz datę"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Numer telefonu"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Weryfikacja"; +"VERIFICATION_STEP_TITLE" = "Zweryfikuj adres email"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Jeśli email weryfikacji nie dotarł na Twoje konto, stuknij w łącze poniżej, aby wysłać go ponownie."; +"RESEND_EMAIL_BUTTON_TITLE" = "Wyślij ponownie email z weryfikacją"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Logowanie"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Nie pamiętasz hasła?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Podaj kod"; +"PASSCODE_CONFIRM_MESSAGE" = "Potwierdź kod"; +"PASSCODE_SAVED_MESSAGE" = "Kod został zachowany"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kod został uwierzytelniony"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Podaj stary kod"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Podaj nowy kod"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Potwierdź nowy kod"; +"PASSCODE_INVALID_ALERT_TITLE" = "Nieprawidłowy kod"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Niezgodne kody. Spróbuj ponownie."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Uwierzytelnij przy użyciu Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Błąd Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Dozwolone są tylko znaki numeryczne."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Wskaźnik postępu podawania kodu"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Liczba wprowadzonych cyfr: %@ z %@"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Nie pamiętasz kodu?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nie można było dodać rzeczy pęku kluczy."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nie można było uaktualnić rzeczy pęku kluczy."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nie można było usunąć rzeczy pęku kluczy."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Nie można było znaleźć rzeczy pęku kluczy."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Typ I"; +"FITZPATRICK_SKIN_TYPE_II" = "Typ II"; +"FITZPATRICK_SKIN_TYPE_III" = "Typ III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Typ IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Typ V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Typ VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Kobieta"; +"GENDER_MALE" = "Mężczyzna"; +"GENDER_OTHER" = "Inna"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nie"; +"BOOL_YES" = "Tak"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "cale"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "lewa"; +"LIMB_RIGHT" = "prawa"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Stuknij, aby odpowiedzieć"; +"NULL_ANSWER" = "Wybierz odpowiedź"; +"PLACEHOLDER_IMAGE_CHOICES" = "Stuknij, aby wybrać"; +"PLACEHOLDER_LONG_TEXT" = "Stuknij, aby wpisać"; + +/* Button titles */ +"BUTTON_AGREE" = "Akceptuję"; +"BUTTON_CANCEL" = "Anuluj"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Wymaż"; +"BUTTON_CLEAR_SIGNATURE" = "Wymaż podpis"; +"BUTTON_APPLY" = "Zastosuj"; +"BUTTON_DISAGREE" = "Nie akceptuję"; +"BUTTON_DONE" = "Gotowe"; +"BUTTON_GET_STARTED" = "Start"; +"BUTTON_LEARN_MORE" = "Więcej informacji"; +"BUTTON_NEXT" = "Dalej"; +"BUTTON_SKIP" = "Pomiń"; +"BUTTON_SKIP_QUESTION" = "Pomiń to pytanie"; +"BUTTON_START_TIMER" = "Włącz stoper"; +"BUTTON_OPTION_SAVE" = "Zachowaj na później"; +"BUTTON_OPTION_DISCARD" = "Odrzuć wyniki"; +"BUTTON_OPTION_STOP_TASK" = "Zakończ zadanie"; +"BUTTON_SAVE" = "Zachowaj"; +"BUTTON_CLEAR_ANSWER" = "Wymaż odpowiedź"; +"BUTTON_READ_ONLY_MODE" = "Nie można modyfikować tej odpowiedzi."; +"BUTTON_COPYRIGHT" = "Prawa autorskie"; +"BUTTON_CLOSE" = "Zamknij"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Początek ćwiczenia za:"; +"TASK_COMPLETE_TITLE" = "Koniec ćwiczenia"; +"TASK_COMPLETE_TEXT" = "Twoje dane zostaną przeanalizowane i otrzymasz powiadomienie o wynikach."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Pozostało %@."; +"TOUCH_ANYWHERE_LABEL" = "Aby kontynuować, dotknij w dowolnym miejscu"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Zarejestruj obraz"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Zarejestruj obraz ponownie"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nie znaleziono aparatu. Nie można wykonać kroku."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Aby wykonać ten krok, przejdź do Ustawień i daj tej aplikacji dostęp do aparatu."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Nie wskazano katalogu wyjściowego dla zarejestrowanych obrazów."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Nie można było zachować zarejestrowanego obrazu."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Rozpocznij nagrywanie"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Zatrzymaj nagrywanie"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Zarejestruj wideo ponownie"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Sprawność"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Dystans (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Tętno (ud./min)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Siedź wygodnie przez %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Idź najszybciej jak potrafisz przez %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "To ćwiczenie monitoruje Twoje tętno i mierzy dystans, jaki potrafisz przejść przez %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Wyjdź na zewnątrz i idź najszybciej jak potrafisz przez %1$@. Gdy skończysz, usiądź wygodnie i odpoczywaj przez %2$@. Aby rozpocząć, stuknij w Start."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Chód i równowaga"; +"WALK_INTRO_TEXT" = "To ćwiczenie mierzy Twój chód i równowagę w ruchu i bezruchu. Jeśli nie możesz bezpiecznie chodzić bez pomocy innych, nie wykonuj go."; +"WALK_INTRO_2_TEXT_%ld" = "Znajdź miejsce, w którym możesz bezpiecznie i bez pomocy innych iść prosto i zatrzymać się po około %ld krokach."; +"WALK_INTRO_2_DETAIL" = "Włóż urządzenie do kieszeni lub torby i postępuj zgodnie z instrukcjami audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Teraz stój w bezruchu przez %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stój w bezruchu przez %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Odwróć się i przejdź do miejsca startu."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Idź prosto i zatrzymaj się po maksymalnie %ld krokach."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Znajdź miejsce, gdzie bez przeszkód możesz chodzić po linii prostej tam i z powrotem. Staraj się iść nieprzerwanie, obracając się na końcach ścieżki, tak jakby chód odbywał się dookoła stożka.\n\nNastępnie poprosimy Cię o obrócenie się, a następnie spokojne stanie z rękami po bokach i stopami rozstawionymi na szerokość ramion."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Gdy już możesz zacząć, stuknij w Start.\nNastępnie umieść urządzenie w kieszeni lub w torbie i postępuj zgodnie z instrukcjami audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Chodź zwykłym krokiem w tę i z powrotem w linii prostej przez %@."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Wykonaj pełny obrót i stój bez ruchu przez %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Ćwiczenie zostało ukończone."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Szybkość stukania"; +"TAPPING_TASK_TITLE_RIGHT" = "Prawa ręka"; +"TAPPING_TASK_TITLE_LEFT" = "Lewa ręka"; +"TAPPING_INTRO_TEXT" = "To ćwiczenie mierzy Twoją szybkość stukania."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Umieść urządzenie na płaskiej powierzchni."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Naprzemiennie stukaj w przyciski na ekranie dwoma palcami tej samej ręki."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Naprzemiennie stukaj w przyciski na ekranie dwoma palcami prawej ręki."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Naprzemiennie stukaj w przyciski na ekranie dwoma palcami lewej ręki."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Teraz wykonaj to ćwiczenie prawą ręką."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Teraz wykonaj to ćwiczenie lewą ręką."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Stukaj na zmianę jednym i drugim palcem. Próbuj stukać możliwie miarowo. Stukaj przez %@."; +"TAPPING_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Aby rozpocząć, stuknij w Dalej."; +"TAP_BUTTON_TITLE" = "Stuknij"; +"TOTAL_TAPS_LABEL" = "Liczba stuknięć"; +"TAPPING_INSTRUCTION" = "Stukaj w przyciski dwoma palcami możliwie miarowo."; +"TAPPING_INSTRUCTION_RIGHT" = "Stukaj w przyciski PRAWĄ ręką."; +"TAPPING_INSTRUCTION_LEFT" = "Stukaj w przyciski LEWĄ ręką."; +"TAPPING_SKIP_TITLE" = "Pomiń tę rękę"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Siatka Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "To ćwiczenie pomaga wykrywać problemy ze wzrokiem użytkownika."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Trzymaj to urządzenie 30 centymetrów od twarzy na poziomie oczu przez cały test."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Zamknij %@ i zacznij wpatrywać się w kropkę na środku kwadratowej siatki.\n\nPalcem lub stylusem zaznacz zniekształcenia, jakie zobaczysz, takie jak nieostre lub faliste linie.\n\nGdy skończysz, przesuń palcem w lewo poza siatkę."; +"AMSLER_GRID_LEFT_EYE" = "lewe oko"; +"AMSLER_GRID_RIGHT_EYE" = "prawe oko"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Głos"; +"AUDIO_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"AUDIO_INSTRUCTION" = "Mów „Aaaaa” do mikrofonu najdłużej jak potrafisz."; +"AUDIO_INTRO_TEXT" = "Weź głęboki oddech i mów „Aaaaa” do mikrofonu najdłużej jak potrafisz. Utrzymuj stały poziom głośności, aby paski dźwięku były przez cały czas niebieskie."; +"AUDIO_INTENDED_USE" = "Ta czynność ocenia Twój głos, nagrywając go za pomocą mikrofonu umieszczonego na dole urządzenia."; +"AUDIO_TOO_LOUD_LABEL" = "Zbyt głośno"; +"AUDIO_GENERIC_ERROR_LABEL" = "Nie można nagrać dźwięku"; +"AUDIO_LEVEL_CHECK_LABEL" = "Czekaj, sprawdzamy poziom szumu tła."; +"AUDIO_TOO_LOUD_MESSAGE" = "Szum otoczenia jest zbyt głośny, aby nagrać Twój głos. Przenieś się w cichsze miejsce i spróbuj ponownie."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Aby rozpocząć, stuknij w Dalej."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonalna"; +"TONE_AUDIOMETRY_INTENDED_USE" = "To ćwiczenie mierzy Twoją zdolność słyszenia różnych dźwięków."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Zanim zaczniesz, podłącz i załóż słuchawki.\n\nDźwięk będzie bardzo subtelny i nie będzie przypominał regularnego dźwięku alertu.  Na początku będzie cichy, a potem jego głośność będzie stopniowo zwiększana.  Słuchaj uważnie i stukaj w lewy lub prawy przycisk, aby wskazać, w którym uchu go słyszysz."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Teraz usłyszysz dźwięk. Ustaw głośność urządzenia używając przycisków bocznych.\n\nAby rozpocząć, naciśnij dowolny klawisz."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Za każdym razem, gdy usłyszysz dźwięk, stuknij w lewy lub prawy przycisk, aby wskazać, w którym uchu go słyszysz."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Lewe ucho"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Prawe ucho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, lewy"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, prawy"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria tonalna"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Stuknij, gdy usłyszysz dźwięk."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Dźwięk i głośność"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Urządzenie odtworzy serię dźwięków."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Gdy usłyszysz dźwięk, stuknij w przycisk."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Na potrzeby tego testu głośność zostanie ustawiona na 50 procent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Test trwa około 10 minut."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Aby skupić się na teście, włącz tryb Nie przeszkadzać."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Dźwięki będą najpierw odtwarzane w prawym uchu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Dźwięki będą teraz odtwarzane w lewym uchu."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Ta czynność identyfikuje poziomy progu słuchu osoby w skali dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Ustaw głośność urządzenia na maksymalny poziom.\n\nPodczas tego zadania w lewym lub prawym uchu będzie odtwarzany delikatny dźwięk.\n\nSłuchaj uważnie i za każdym razem, gdy usłyszysz ten dźwięk, stuknij w przycisk."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Ten test określa, jak głośny musi być dźwięk, aby był słyszalny dla Ciebie."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Kwestionariusz wprowadzający."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Zaznacz preferencje „sprawniejszego ucha”, jeśli to konieczne"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "lewe"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "prawe"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "bez preferencji"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test anulowany"; +"dBHL_ALERT_TITLE_START_OVER" = "Zacznij od nowa"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Anuluj test"; +"dBHL_ALERT_TEXT" = "Aby przeprowadzić ten test, połącz ponownie ze słuchawkami AirPods lub EarPods."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ wykonane"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Słuchawki"; +"HEADPHONES_UNKNOWN" = "Nieznane"; +"HEADPHONES_NONE" = "Brak"; +"CONNECTED" = "Połączono"; +"NOT_CONNECTED" = "Niepołączone"; +"HEADPHONE_CONNECTED_%@" = "Połączono – %@"; +"HEADPHONE_DETECT_TITLE" = "Połącz ze słuchawkami"; +"HEADPHONE_DETECT_TEXT" = "Ten test wymaga słuchawek AirPods lub EarPods firmy Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Pamięć przestrzenna"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "To ćwiczenie mierzy Twoją krótkotrwałą pamięć przestrzenną: podświetla %@ w określonej sekwencji i prosi o jej powtórzenie."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "kwiaty"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "kwiaty"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Widoczne na ekranie %@ będą kolejno podświetlane. Stuknij w te %@ w takie samej kolejności."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Widoczne na ekranie %@ będą kolejno podświetlane. Stuknij w te %@ w odwrotnej kolejności."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start, a następnie obserwuj ekran."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Wynik"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Obserwuj podświetlane %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Stuknij w %@ w kolejności, w jakiej były podświetlane"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Stuknij w %@ w odwrotnej kolejności"; +"MEMORY_GAME_COMPLETE_TITLE" = "Koniec sekwencji"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Aby kontynuować, stuknij w Dalej"; +"MEMORY_GAME_FAILED_TITLE" = "Spróbuj ponownie"; +"MEMORY_GAME_FAILED_MESSAGE" = "Tym razem nie udało Ci się. Stuknij w Dalej, aby kontynuować."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Czas minął"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Skończył Ci się czas.\nAby kontynuować, stuknij w Dalej."; +"MEMORY_GAME_COMPLETE" = "Gra zakończona"; +"MEMORY_GAME_PAUSED_TITLE" = "Wstrzymana"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Aby kontynuować, stuknij w Dalej"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Ćwiczenie pamięci zostało opracowane przy pomocy dr Katherine Possin, dr Joel Kramer, z Uniwersytetu Kalifornijskiego w San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Czas reakcji"; +"REACTION_TIME_TASK_INTENDED_USE" = "To ćwiczenie ocenia Twój czas odpowiedzi na bodziec wzrokowy."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Potrząśnij urządzeniem w dowolnym kierunku, gdy tylko zobaczysz na ekranie niebieską kropkę. Test zostanie powtórzony %D razy."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Próba %@ z %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Gdy pojawi się niebieskie kółko, szybko potrząśnij urządzeniem"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Efekt Stroopa"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Za każdym razem, gdy pojawi się słowo, wybierz pierwszą literę nazwy KOLORU, jaki jest wyświetlony."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "W dogodnym momencie stuknij w Start, aby rozpocząć ćwiczenie Stroopa."; +"STROOP_TASK_STEP_TEXT" = "Zaznacz pierwszą literę nazwy KOLORU, jaki jest wyświetlony."; +"STROOP_COLOR_RED" = "CZERWONY"; +"STROOP_COLOR_GREEN" = "ZIELONY"; +"STROOP_COLOR_BLUE" = "NIEBIESKI"; +"STROOP_COLOR_YELLOW" = "ŻÓŁTY"; +"STROOP_COLOR_RED_INITIAL" = "C"; +"STROOP_COLOR_GREEN_INITIAL" = "Z"; +"STROOP_COLOR_BLUE_INITIAL" = "N"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ż"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Wieże Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "To ćwiczenie ocenia Twoją zdolność rozwiązywania łamigłówek."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Przenieś cały zestaw krążków na wyróżnioną podstawę, wykonując jak najmniej ruchów."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Rozwiąż łamigłówkę"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Liczba ruchów: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Nie potrafię rozwiązać tej łamigłówki"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Zakres ruchu"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Wartość dla limbOption musi być lewa lub prawa"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Zasięg ruchu lewego kolana"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Zasięg ruchu prawego kolana"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "To ćwiczenie mierzy, jak bardzo możesz wyprostować lewą nogę w kolanie."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "To ćwiczenie mierzy, jak bardzo możesz wyprostować prawą nogę w kolanie."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Usiądź na krawędzi krzesła. Na początek umieścisz urządzenie na lewym kolanie w celu pomiaru. Włącz dźwięk w urządzeniu, aby słyszeć instrukcje."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Usiądź na krawędzi krzesła. Na początek umieścisz urządzenie na prawym kolanie w celu pomiaru. Włącz dźwięk w urządzeniu, aby słyszeć instrukcje."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Umieść urządzenie na lewym kolanie, a ekran skieruj na zewnątrz, tak jak na ilustracji."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Umieść urządzenie na prawym kolanie, a ekran skieruj na zewnątrz, tak jak na ilustracji."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Przygotuj się, stuknij w ekran i wyprostuj maksymalnie lewą nogę w kolanie. Następnie wróć do pozycji początkowej. Gdy skończysz, stuknij ponownie w ekran."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Przygotuj się, stuknij w ekran i wyprostuj maksymalnie prawą nogę w kolanie. Następnie wróć do pozycji początkowej. Gdy skończysz, stuknij ponownie w ekran."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Umieść urządzenie na lewym kolanie. Stuknij w ekran i wyprostuj maksymalnie lewą nogę w kolanie."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Umieść urządzenie na prawym kolanie. Stuknij w ekran i wyprostuj maksymalnie prawą nogę w kolanie."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Gdy skończysz, ustaw lewe kolano w pozycji początkowej i stuknij w ekran."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Gdy skończysz, ustaw prawe kolano w pozycji początkowej i stuknij w ekran."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Zasięg ruchu lewego ramienia"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Zasięg ruchu prawego ramienia"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "To ćwiczenie mierzy, jak mocno możesz rozciągnąć lewe ramię."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "To ćwiczenie mierzy, jak mocno możesz rozciągnąć prawe ramię."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Na początek umieścisz urządzenie na lewym ramieniu w celu pomiaru. Włącz dźwięk w urządzeniu, aby słyszeć instrukcje."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Na początek umieścisz urządzenie na prawym ramieniu w celu pomiaru. Włącz dźwięk w urządzeniu, aby słyszeć instrukcje."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Umieść urządzenie na lewym ramieniu, a ekran skieruj na zewnątrz, tak jak na ilustracji."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Umieść urządzenie na prawym ramieniu, a ekran skieruj na zewnątrz, tak jak na ilustracji."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Przygotuj się, stuknij w ekran i unieś lewe ramię jak najwyżej. Następnie ustaw je w pozycji początkowej. Gdy skończysz, stuknij ponownie w ekran."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Przygotuj się, stuknij w ekran i unieś prawe ramię jak najwyżej. Następnie ustaw je w pozycji początkowej. Gdy skończysz, stuknij ponownie w ekran."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Umieść urządzenie na lewym barku. Stuknij w ekran i unieś lewe ramię jak najwyżej do przodu."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Umieść urządzenie na prawym barku. Stuknij w ekran i unieś prawe ramię jak najwyżej do przodu."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Gdy skończysz, ustaw lewe ramię w pozycji początkowej i stuknij w ekran."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Gdy skończysz, ustaw prawe ramię w pozycji początkowej i stuknij w ekran."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Chód na czas"; +"TIMED_WALK_INTRO_DETAIL" = "To ćwiczenie mierzy sprawność dolnej partii ciała."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Znajdź miejsce, najlepiej na zewnątrz, gdzie możesz iść w linii prostej przez ok. %@ możliwie najszybciej, ale bezpiecznie. Nie zwalniaj, dopóki nie przekroczysz linii końcowej."; +"TIMED_WALK_INTRO_2_DETAIL" = "Aby rozpocząć, stuknij w Dalej."; +"TIMED_WALK_FORM_TITLE" = "Urządzenie wspomagające"; +"TIMED_WALK_FORM_TEXT" = "Użyj tego samego urządzenia wspomagającego w każdym teście."; +"TIMED_WALK_QUESTION_TEXT" = "Czy nosisz ortezę stawu skokowego?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Czy używasz urządzenia wspomagającego?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Stuknij tutaj, aby odpowiedzieć."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Brak"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Jedna laska"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Jedna kula"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dwie laski"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dwie kule"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Chodzik/balkonik"; +"TIMED_WALK_INSTRUCTION_%@" = "Idź maks. %@ w linii prostej."; +"TIMED_WALK_INSTRUCTION_TURN" = "Zawróć."; +"TIMED_WALK_INSTRUCTION_2" = "Wróć do miejsca początkowego."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Gdy skończysz, stuknij w Dalej."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Test PASAT mierzy szybkość przetwarzania danych audialnych i umiejętność liczenia."; +"PVSAT_INTRO_TEXT" = "Test PVSAT mierzy szybkość przetwarzania danych wizualnych i umiejętność liczenia."; +"PAVSAT_INTRO_TEXT" = "Test PAVSAT mierzy szybkość przetwarzania danych audiowizualnych i umiejętność liczenia."; +"PSAT_INTRO_TEXT_2_%@" = "Zaprezentujemy liczby jednocyfrowe zmieniające się po %@.\nKażdą nową liczbę musisz dodać do poprzedniej.\nUwaga: Nie obliczaj łącznej sumy, tylko sumę dwóch ostatnich liczb."; +"PSAT_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"PSAT_INITIAL_INSTRUCTION" = "Zapamiętaj tę pierwszą cyfrę."; +"PSAT_INSTRUCTION" = "Dodaj tę cyfrę do poprzedniej."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Test %@-HPT (otwory i kołki)"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "To ćwiczenie mierzy sprawność górnej partii ciała: umieszczasz kołek (pełne kółko) w otworze (puste kółko). Do wykonania %@ razy."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Testowane będą zarówno lewa, jak i prawa ręka.\nMusisz podnieść kołek tak szybko, jak to możliwe, umieścić go w otworze, oraz po %@ razach, wyjąć go %@ razy."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Testowane będą zarówno prawa, jak i lewa ręka.\nMusisz podnieść kołek tak szybko, jak to możliwe, umieścić go w otworze, oraz po %@ razach, wyjąć go %@ razy."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Umieść kołek w otworze, używając lewej ręki."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Umieść kołek w otworze, używając prawej ręki."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Umieść kołek za linią, używając lewej ręki."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Umieść kołek za linią, używając prawej ręki."; +"HOLE_PEG_TEST_TEXT" = "Podnieś kołek dwoma palcami."; +"HOLE_PEG_TEST_TEXT_2" = "Unieś palce, aby upuścić kołek."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Ćwiczenie mierzące drżenie rąk"; +"TREMOR_TEST_INTRO_1_DETAIL" = "To ćwiczenie mierzy drżenie rąk w różnych pozycjach. Na czas tego ćwiczenia znajdź miejsce, w którym możesz wygodnie siedzieć."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Trzymaj telefon w bardziej drżącej ręce, tak jak na obrazku poniżej."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Trzymaj telefon w PRAWEJ ręce, tak jak na obrazku poniżej."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Trzymaj telefon w LEWEJ ręce, tak jak na obrazku poniżej."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Wykonasz %@ w pozycji siedzącej, trzymając telefon w ręce."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "zadanie"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dwa zadania"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "trzy zadania"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "cztery zadania"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "pięć zadań"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Aby kontynuować, stuknij w Dalej."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Przygotuj się do trzymania telefonu na kolanach."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Przygotuj się do trzymania telefonu na kolanach LEWĄ ręką."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Przygotuj się do trzymania telefonu na kolanach PRAWĄ ręką."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Trzymaj telefon na kolanach przez %ld s."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Teraz trzymaj telefon w wyciągniętej ręce na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Teraz trzymaj telefon w wyciągniętej LEWEJ ręce na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Teraz trzymaj telefon w wyciągniętej PRAWEJ ręce na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Trzymaj telefon w wyciągniętej ręce przez %ld s."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Teraz trzymaj telefon w ręce ugiętej w łokciu na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Teraz trzymaj telefon w LEWEJ ręce ugiętej w łokciu na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Teraz trzymaj telefon w PRAWEJ ręce ugiętej w łokciu na wysokości barku."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Trzymaj telefon w ręce zgiętej w łokciu przez %ld s"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Teraz, trzymając telefon w ręce zgiętej w łokciu, dotknij nim nosa i powtarzaj tę czynność."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Teraz, trzymając telefon w LEWEJ ręce zgiętej w łokciu, dotknij nim nosa i powtarzaj tę czynność."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Teraz, trzymając telefon w PRAWEJ ręce zgiętej w łokciu, dotknij nim nosa i powtarzaj tę czynność."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Dotykaj telefonem nosa przez %ld s"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Przygotuj się do machania dłonią, zginając rękę w nadgarstku."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Przygotuj się do machania LEWĄ dłonią, zginając rękę w nadgarstku."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Przygotuj się do machania PRAWĄ dłonią, zginając rękę w nadgarstku."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Unieś rękę i machaj dłonią, zginając rękę w nadgarstku, przez %ld s."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Teraz przełóż telefon do LEWEJ ręki i przejdź do następnego zadania."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Teraz przełóż telefon do PRAWEJ ręki i przejdź do następnego zadania."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Przejdź do następnego zadania."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Ćwiczenie ukończone."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Wykonasz %@ w pozycji siedzącej z telefonem w jednej ręce, a następnie w drugiej."; +"TREMOR_SKIP_LEFT_HAND" = "Nie mogę wykonywać tego ćwiczenia LEWĄ ręką."; +"TREMOR_SKIP_RIGHT_HAND" = "Nie mogę wykonywać tego ćwiczenia PRAWĄ ręką."; +"TREMOR_SKIP_NEITHER" = "Mogę wykonywać to ćwiczenie obiema rękami."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test łączenia punktów"; +"TRAILMAKING_INTENDED_USE" = "To ćwiczenie ocenia Twoje zdolności skupienia się na obrazie oraz przełączania zadań przez pomiar czasu potrzebnego do stuknięcia w serię kropek w odpowiedniej kolejności."; +"TRAILMAKING_INTENDED_USE2_A" = "Po odliczeniu, stukaj naprzemiennie w kropki oznaczające cyfry i litery. Zacznij stukając w pierwszą cyfrę ‚1’, a po niej w kolejne cyfry ‚2’ – ‚3’ – ‚4’…, aż do cyfry ‚7’."; +"TRAILMAKING_INTENDED_USE2_B" = "Po odliczeniu, stukaj naprzemiennie w kropki oznaczające cyfry i litery. Zacznij stukając w pierwszą cyfrę ‚1’, a po niej w pierwszą literę ‚A’, następnie ‚2’ – ‚B’ – ‚3’ – ‚C’…, aż do cyfry ‚7’."; +"TRAILMAKING_INTRO_TEXT" = "Rób to tak szybko, jak potrafisz, nie popełniając błędów. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Rozpoznanie mowy"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Ta czynność nagrywa Twoją mowę za pomocą mikrofonu umieszczonego na dole urządzenia i transponuje ją na tekst."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Aby rozpocząć, stuknij w Start."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Naciśnij przycisk, aby rozpocząć nagrywanie zanim zaczniesz mówić."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Rozpocznij nagrywanie"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Zatrzymaj nagrywanie"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Edycja zapisu"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edytuj tekst zapisu, aby poprawić wszelkie błędne interpretacje mowy."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Twój zapis tekstu pojawi się tutaj."; +"SPEECH_RECOGNITION_FAILED" = "Rozpoznawanie mowy nie powiodło się."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Nie udało się zainicjować rozpoznawania mowy."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Odtwarzaj dźwięk"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Zatrzymaj dźwięk"; +"SPEECH_IN_NOISE_TITLE" = "Szum podczas mówienia"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Ta czynność mierzy rozpoznawalność mowy w hałaśliwym otoczeniu."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Zadaniem tego testu będzie:\n\nOdsłuchanie zdania.\n\nWyraźne powtórzenie usłyszanej treści lub pominięcie i wpisanie tej treści na klawiaturze. \n\nJeśli powtórzysz usłyszaną treść, damy Ci możliwość modyfikowania zapisu treści wygenerowanego przez mechanizm rozpoznawania mowy."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Kalibracja głośności"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Stuknij w Odtwarzaj dźwięk, dostosuj głośność do odpowiedniego poziomu, a potem stuknij w Zatrzymaj dźwięk, aby kontynuować."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Słuchaj"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Zdanie z szumem w tle z losowym stosunkiem sygnału do szumu (SNR) zostanie odczytane tylko raz."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Powiedz"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Powtórz usłyszaną treść."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Nie można było utworzyć pliku"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nie można było usunąć liczby plików dzienników pozwalającej na osiągnięcie progu"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Błąd ustawiania atrybutu"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Plik nie oznaczony jako usunięty (nie oznaczony jako wysłany)"; +"ERROR_DATALOGGER_MULTIPLE" = "Wiele błędów usuwania dzienników"; +"ERROR_RECORDER_NO_DATA" = "Nie znaleziono zgromadzonych danych."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Nie wskazano katalogu wyjściowego"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Wskaźnik SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Ta czynność mierzy poziom ciśnienia akustycznego otoczenia. Jeśli poziomy hałasu będą za wysokie, nie możesz kontynuować. Przesuń się do cichszego miejsca, aby zakończyć to zadanie lub powtórz tę czynność później."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Obliczam"; +"ENVIRONMENTSPL_THRESHOLD" = "Próg: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Głośność otoczenia OK"; +"ENVIRONMENTSPL_NOISE" = "Zbyt głośne otoczenie"; +"ENVIRONMENTSPL_TITLE_2" = "Znajdź ciche miejsce"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Aby zapewnić dokładność testu, przeprowadź go w cichym miejscu."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Rozpocznij"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Brak danych"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Aby wprowadzić wartość, przesuń suwak"; +"SLIDER_I_DONT_KNOW" = "Nie wiem"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Strona"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Wróć"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Pokaż miniaturkę PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ukryj miniaturkę PDF"; +"AX_BUTTON_ANNOTATE" = "Adnotacja"; +"AX_BUTTON_SHOW_SEARCH" = "Pokaż pasek wyszukiwania"; +"AX_BUTTON_HIDE_SEARCH" = "Ukryj pasek wyszukiwania"; +"AX_BUTTON_SHARE" = "Udostępnij"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustracja znaku zaznaczenia w niebieskim okręgu oznacza sukces"; + +"AX_SIGNVIEW_LABEL" = "Wyznaczone pole podpisu"; +"AX_SIGNVIEW_HINT" = "Dotknij ekranu i przesuwaj palec, aby podpisać"; +"AX_SIGNVIEW_SIGNED" = "Podpisane"; +"AX_SIGNVIEW_UNSIGNED" = "Niepodpisane"; + +"AX_SELECTED" = "Zaznaczone"; +"AX_UNSELECTED" = "Nie zaznaczone"; +"AX_SELECT_ALL_THAT_APPLY" = "ZAZNACZ WSZYSTKIE PASUJĄCE ODPOWIEDZI"; + +"AX_SLIDER_LABEL" = "Suwak odpowiedzi. Zakres od %@ do %@"; +"AX_UNLABELED_IMAGE" = "Obrazek bez etykiety"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Rozpocznij zadanie"; + +"AX.MEMORY.TILE.ACTIVE" = "aktywna"; +"AX.MEMORY.TILE.CORRECT" = "prawidłowa"; +"AX.MEMORY.TILE.INCORRECT" = "nieprawidłowa"; +"AX.MEMORY.TILE.QUIESCENT" = "nieaktywna"; +"AX.MEMORY.TILE.LABEL" = "Płytka gry pamięciowej"; + +"AX_IMAGE_CAPTURE_LABEL" = "Zarejestruj podgląd"; +"AX_IMAGE_CAPTURED_LABEL" = "Zarejestrowany obraz"; + +"AX_VIDEO_CAPTURE_LABEL" = "Podgląd rejestracji wideo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Przechwytywanie wideo zakończone"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Nie można umieścić dysku o rozmiarze %@ na dysku o rozmiarze %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Krążek docelowy"; +"AX_TOWER_OF_HANOI_TOWER" = "Wieża"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Stuknij dwukrotnie, aby umieścić krążek"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Stuknij dwukrotnie, aby wybrać krążek znajdujący się na górze"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Zawiera krążki o rozmiarach %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Pusta"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Zamknij klawiaturę"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Zakres %@–%@"; +"AX_GRAPH_STACK_PREFIX" = "Stos złożony z"; +"AX_GRAPH_AND_SEPARATOR" = " i "; +"AX_GRAPH_POINT_%@" = "Punkt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Kształt fali mowy"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Po rozpoczęciu nagrywania aktywuj drugi raz, aby zakończyć nagrywanie."; + +"AX_AUDIO_BAR_GRAPH" = "Wykres paskowy audio"; + +"AX_AMSLER_GRID_LABEL" = "Siatka Amsler"; +"AX_AMSLER_GRID_HINT" = "Palcem lub stylusem oznaczaj bezpośrednio na siatce, lub przesuń palcem w lewo poza siatkę, aby zakończyć."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Aktywne przyciski"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Stuknij (lewe ucho)"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktywuj, aby rozpocząć test. Podczas testu stuknij bezpośrednio w ten przycisk, gdy usłyszysz dźwięk w lewym uchu."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Stuknij (prawo ucho)"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktywuj, aby rozpocząć test. Podczas testu stuknij bezpośrednio w ten przycisk, gdy usłyszysz dźwięk w prawym uchu."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Jeśli korzystasz z VoiceOver, możesz nawigować po ekranie, używając dotyku, i dowiedzieć się, gdzie znajdują się przyciski każdego z uszu. Po rozpoczęciu testu możesz stukać w te przyciski bezpośrednio. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Stuknij (1 palec)"; +"AX_TAP_BUTTON_2_LABEL" = "Stuknij (inny palec)"; +"AX_TAP_BUTTON_HINT" = "Aktywuj, jeśli chcesz móc stukać w przyciski bezpośrednio."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Jeśli korzystasz z VoiceOver, możesz nawigować po ekranie, używając dotyku, i dowiedzieć się, gdzie znajdują się przyciski. Aktywuj dowolny z nich, aby móc stukać w przyciski bezpośrednio."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Możesz teraz stukać w przyciski bezpośrednio."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Jeśli korzystasz z VoiceOver, będziesz mieć możliwość stukania w ten przycisk bezpośrednio (w środkowej części ekranu)."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Jeśli korzystasz z VoiceOver, możesz stukać bezpośrednio w przyciski wyświetlane przez test."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Nie można odkodować restoreData na potrzeby inicjalizacji"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..b0a4f0c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pl.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d błąd) + other + (%d błędu) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.strings new file mode 100755 index 0000000..1bbcb2b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consentimento"; +"CONSENT_NAME_GIVEN" = "Nome"; +"CONSENT_NAME_FAMILY" = "Sobrenome"; +"CONSENT_NAME_PLACEHOLDER" = "Obrigatório"; +"CONSENT_REVIEW_TITLE" = "Revisar"; +"CONSENT_REVIEW_INSTRUCTION" = "Analise o formulário abaixo e toque em Concordar se estiver pronto para continuar."; +"CONSENT_REVIEW_ALERT_TITLE" = "Revisar"; +"CONSENT_SIGNATURE_TITLE" = "Assinatura"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Assine com o seu dedo na caixa abaixo."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Assine Aqui"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Página %1$ld de %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bem-vindo(a)"; +"CONSENT_SECTION_DATA_GATHERING" = "Coleta de Dados"; +"CONSENT_SECTION_PRIVACY" = "Privacidade"; +"CONSENT_SECTION_DATA_USE" = "Uso dos Dados"; +"CONSENT_SECTION_STUDY_SURVEY" = "Opinião do Estudo"; +"CONSENT_SECTION_STUDY_TASKS" = "Tarefas do Estudo"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Compromisso de Tempo"; +"CONSENT_SECTION_WITHDRAWING" = "Desistência"; +"CONSENT_LEARN_MORE_TITLE" = "Saiba Mais"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Saiba mais sobre como os dados são coletados"; +"LEARN_MORE_DATA_USE" = "Saiba mais sobre como os dados são usados"; +"LEARN_MORE_PRIVACY" = "Saiba mais sobre como sua privacidade e sua identidade são protegidas"; +"LEARN_MORE_WELCOME" = "Antes, saiba mais sobre o estudo"; +"LEARN_MORE_STUDY_SURVEY" = "Saiba mais sobre a pesquisa de opinião"; +"LEARN_MORE_TIME_COMMITMENT" = "Saiba mais sobre o impacto do estudo sobre o seu tempo"; +"LEARN_MORE_TASKS" = "Saiba mais sobre as tarefas envolvidas"; +"LEARN_MORE_WITHDRAWING" = "Saiba mais sobre a desistência"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opções de Compartilhamento"; +"CONSENT_SHARE_WIDELY_%@" = "Compartilhar meus dados com %@ e pesquisadores qualificados mundialmente"; +"CONSENT_SHARE_ONLY_%@" = "Compartilhar meus dados somente com %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ receberá os seus dados de estudo conforme a sua participação neste estudo.\n\nO compartilhamento dos seus dados de estudo codificados de forma mais ampla (sem conter informações como o seu nome) poderá beneficiar esta pesquisa e pesquisas futuras."; +"LEARN_MORE_CONSENT_SHARING" = "Saiba mais sobre o compartilhamento de dados"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nome Impresso"; +"CONSENT_DOC_LINE_SIGNATURE" = "Assinatura"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ de %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pergunta %1$@ de %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Pulada"; +"REVIEW_EDIT_ANSWER" = "Editar"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valor inválido"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ excede o valor máximo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ é menor que o valor mínimo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ não é um valor válido."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Endereço de e-mail inválido: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Digite um endereço"; +"LOCATION_ERROR_TITLE" = "Não Foi Possível Encontrar o Endereço Especificado"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Não foi possível determinar sua localização atual. Digite um endereço ou vá para um local com melhor sinal GPS, se aplicável."; +"LOCATION_ERROR_MESSAGE_DENIED" = "O acesso aos Serviços de Localização foi negado. Permita que este aplicativo use os Serviços de Localização nos Ajustes."; +"LOCATION_ERROR_GEOCODE" = "Não foi possível encontrar um resultado para o endereço inserido. Certifique-se de que o endereço é válido."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Você não esta conectado à internet ou o número máximo de solicitações de busca de endereço foi atingido. Se você não está conectado à internet, ative a conexão Wi-Fi para responder a esta pergunta, pule esta pergunta se houver um botão que permita esta ação ou volte para a busca quando estiver conectado à Internet. Caso contrário, tente novamente em alguns minutos."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Conteúdo de texto excedendo duração máxima: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "A câmera não está disponível na tela dividia."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jaime@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Senha"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Digite a senha"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmar"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Digite a senha novamente"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "As senhas não coincidem."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informações Adicionais"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Jaime"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Silveira"; +"GENDER_FORM_ITEM_TITLE" = "Sexo"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Escolha um sexo"; +"DOB_FORM_ITEM_TITLE" = "Data de Nascimento"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Escolha uma data"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Número de Telefone"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificação"; +"VERIFICATION_STEP_TITLE" = "Verifique seu E-mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Caso não tenha recebido um e-mail de verificação e gostaria que ele fosse enviado novamente, toque no link abaixo."; +"RESEND_EMAIL_BUTTON_TITLE" = "Reenviar e-mail de verificação"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Início de Sessão"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Esqueceu a senha?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Digite o código"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmar código"; +"PASSCODE_SAVED_MESSAGE" = "Código salvo"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Código autenticado"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Digite o seu código anterior"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Digite seu novo código"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirme o seu novo código"; +"PASSCODE_INVALID_ALERT_TITLE" = "Código Incorreto"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Os códigos não coincidem. Tente de novo."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Realize a autenticação com Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Erro do Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Apenas caracteres numéricos são permitidos."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicador de progresso de inserção de código"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Você digitou %@ de %@ dígitos"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Esqueceu o Código?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Não foi possível adicionar a chave."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Não foi possível atualizar a chave."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Não foi possível apagar a chave."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Não foi possível encontrar a chave."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipo I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipo II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipo III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipo IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipo V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipo VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Feminino"; +"GENDER_MALE" = "Masculino"; +"GENDER_OTHER" = "Outro"; + +/* Boolean answer strings */ +"BOOL_NO" = "Não"; +"BOOL_YES" = "Sim"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "pés"; +"MEASURING_UNIT_IN" = "pol"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "esquerda"; +"LIMB_RIGHT" = "direito"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toque para responder"; +"NULL_ANSWER" = "Selecione uma resposta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Toque para selecionar"; +"PLACEHOLDER_LONG_TEXT" = "Toque para escrever"; + +/* Button titles */ +"BUTTON_AGREE" = "Concordar"; +"BUTTON_CANCEL" = "Cancelar"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Limpar"; +"BUTTON_CLEAR_SIGNATURE" = "Limpar Assinatura"; +"BUTTON_APPLY" = "Aplicar"; +"BUTTON_DISAGREE" = "Discordar"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Iniciar"; +"BUTTON_LEARN_MORE" = "Saiba mais"; +"BUTTON_NEXT" = "Seguinte"; +"BUTTON_SKIP" = "Ignorar"; +"BUTTON_SKIP_QUESTION" = "Ignorar esta pergunta"; +"BUTTON_START_TIMER" = "Iniciar Timer"; +"BUTTON_OPTION_SAVE" = "Salvar para Mais Tarde"; +"BUTTON_OPTION_DISCARD" = "Descartar Resultados"; +"BUTTON_OPTION_STOP_TASK" = "Finalizar Tarefa"; +"BUTTON_SAVE" = "Salvar"; +"BUTTON_CLEAR_ANSWER" = "Limpar resposta"; +"BUTTON_READ_ONLY_MODE" = "Esta resposta não pode ser modificada."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Fechar"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Iniciando atividade em"; +"TASK_COMPLETE_TITLE" = "Concluído"; +"TASK_COMPLETE_TEXT" = "Seus dados serão analisados e você será notificado quando os resultados estiverem prontos."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Resta %@."; +"TOUCH_ANYWHERE_LABEL" = "Toque em qualquer lugar para continuar"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturar Imagem"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapturar Imagem"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nenhuma câmera encontrada. Não foi possível concluir esta etapa."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Para concluir esta etapa, permita que este aplicativo acesse a câmera, em Ajustes."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Não foi especificado um diretório de saída para imagens capturadas."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "A imagem capturada não pôde ser salva."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Iniciar Gravação"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Parar Gravação"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapturar Vídeo"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Condicionamento Físico"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distância (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Frequência Cardíaca (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sente confortavelmente por %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Ande o mais rápido que conseguir por %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Esta atividade monitora a sua pulsação e mede o quão longe você consegue andar em %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Ande ao ar livre o mais rápido que conseguir por %1$@. Ao terminar, sente e descanse confortavelmente por %2$@. Para começar, toque em Iniciar."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Caminhada e Equilíbrio"; +"WALK_INTRO_TEXT" = "Esta atividade mede a sua caminhada e o seu equilíbrio ao andar e ficar de pé. Não prossiga caso não possa andar seguramente sem ajuda."; +"WALK_INTRO_2_TEXT_%ld" = "Encontre um local onde você possa andar seguramente sem ajuda para dar %ld passos em linha reta."; +"WALK_INTRO_2_DETAIL" = "Coloque o dispositivo em um bolso ou bolsa e siga as instruções do áudio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Agora pare e fique de pé por %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Pare e fique de pé por %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Vire-se e volte para o local onde você começou."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Dê até %ld passos em linha reta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Encontre um local onde você possa andar para a frente e para trás em linha reta com segurança. Tente andar continuamente, virando ao final do caminho, como se estivesse dando a volta em um cone.\n\nA seguir, você será instruído a virar em um círculo completo e ficar parado com os braços ao lado do corpo e os pés separados pela distância entre os ombros."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Toque em Iniciar quando estiver pronto.\nColoque o dispositivo em um bolso ou bolsa e siga as instruções do áudio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Ande para a frente e para trás em linha reta por %@. Ande normalmente."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Vire em um círculo completo e fique parado por %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Você concluiu a atividade."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocidade de Toque"; +"TAPPING_TASK_TITLE_RIGHT" = "Mão Direita"; +"TAPPING_TASK_TITLE_LEFT" = "Mão Esquerda"; +"TAPPING_INTRO_TEXT" = "Esta atividade mede a sua velocidade de toque."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Coloque o dispositivo em uma superfície plana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Use dois dedos da mesma mão para tocar nos botões da tela alternadamente."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Use dois dedos da mão direita para tocar nos botões da tela alternadamente."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Use dois dedos da mão esquerda para tocar nos botões da tela alternadamente."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Agora repita o mesmo teste com a mão direita."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Agora repita o mesmo teste com a mão esquerda."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Toque um dedo e depois o outro. Tente manter o ritmo dos toques o mais constante possível. Continue tocando por %@."; +"TAPPING_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Toque em Seguinte para começar."; +"TAP_BUTTON_TITLE" = "Toque"; +"TOTAL_TAPS_LABEL" = "Total de Toques"; +"TAPPING_INSTRUCTION" = "Toque nos botões com o máximo de consistência que puder usando dois dedos."; +"TAPPING_INSTRUCTION_RIGHT" = "Toque nos botões usando a mão DIREITA."; +"TAPPING_INSTRUCTION_LEFT" = "Toque nos botões usando a mão ESQUERDA."; +"TAPPING_SKIP_TITLE" = "Ignorar esta mão"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Tela de Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Esta atividade ajuda a detectar problemas na visão do usuário."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Mantenha o dispositivo a 30 centímetros do seu rosto, no nível dos olhos, durante todo o teste."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Feche o %@ e olhe fixamente para o ponto no centro da grade quadrada.\n\nCom o dedo ou uma caneta stylus, marque quaisquer distorções que você vê, como linhas desfocadas ou onduladas.\n\nQuando terminar, deslize para a esquerda em qualquer lugar fora da grade."; +"AMSLER_GRID_LEFT_EYE" = "Olho Esquerdo"; +"AMSLER_GRID_RIGHT_EYE" = "Olho Direito"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voz"; +"AUDIO_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"AUDIO_INSTRUCTION" = "Diga “Aaaaah” no microfone por quanto tempo conseguir."; +"AUDIO_INTRO_TEXT" = "Tome fôlego e diga “Aaaaah” no microfone por quanto tempo conseguir. Mantenha o volume vocal estável para que as barras de áudio permaneçam azuis."; +"AUDIO_INTENDED_USE" = "Esta atividade avalia a sua voz, gravando-a com o microfone na parte inferior do dispositivo."; +"AUDIO_TOO_LOUD_LABEL" = "Alto Demais"; +"AUDIO_GENERIC_ERROR_LABEL" = "Não foi possível gravar áudio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Aguarde a verificação do nível de ruído de fundo."; +"AUDIO_TOO_LOUD_MESSAGE" = "O nível de ruído ambiente está muito alto para gravar a sua voz. Vá até um local mais silencioso e tente novamente."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Toque em Seguinte quando pronto."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria Tonal"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Esta atividade mede a sua capacidade de ouvir sons diferentes."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Antes de começar, conecte e coloque seus fones de ouvido.\n\nO som será muito sutil e diferente de um tom de alerta.  O som iniciará suave e, lentamente, aumentará o volume.  Preste atenção e toque no botão esquerdo ou direito para indicar em qual ouvido você o escuta."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Agora você deverá ouvir um tom. Ajuste o volume usando os controles na lateral do seu dispositivo.\n\nToque em qualquer botão quando você estiver pronto para começar."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Sempre que começar a ouvir um som, toque no botão esquerdo ou direito para indicar em qual ouvido você escuta o som."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Ouvido Esquerdo"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Ouvido Direito"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Esquerdo"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Direito"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria Tonal"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Toque quando ouvir um tom."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tom e Volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Você ouvirá uma série de tons."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Quando ouvir um tom, toque no botão."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Para este teste, o volume será de 50 por cento."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Este teste leva cerca de 10 minutos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Ative o recurso Não Perturbe para evitar interrupções."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Os tons serão reproduzidos no ouvido direito primeiro."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Os tons serão reproduzidos no ouvido esquerdo."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Esta atividade identifica os níveis limiares auditivos de uma pessoa na escala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Verifique se o volume do dispositivo está ajustado ao máximo.\n\nDurante esta tarefa, será reproduzido um som sutil no ouvido esquerdo ou direito.\n\nOuça com atenção e toque no botão sempre que ouvir um som."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Este teste identifica quão alto um som precisa ser para que você o ouça."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Questionário de integração."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecione sua preferência de “ouvido melhor”, se aplicável"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "esquerdo"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "direito"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "sem preferência"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Teste Cancelado"; +"dBHL_ALERT_TITLE_START_OVER" = "Iniciar Novamente"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancelar Teste"; +"dBHL_ALERT_TEXT" = "Reconecte os AirPods ou EarPods para realizar este teste."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Concluído"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Fones de Ouvido"; +"HEADPHONES_UNKNOWN" = "Desconhecido"; +"HEADPHONES_NONE" = "Nenhum"; +"CONNECTED" = "Conectados"; +"NOT_CONNECTED" = "Não Conectados"; +"HEADPHONE_CONNECTED_%@" = "Conectado - %@"; +"HEADPHONE_DETECT_TITLE" = "Conecte seus Fones de Ouvido"; +"HEADPHONE_DETECT_TEXT" = "Este teste requer AirPods ou EarPods da Apple"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memória Espacial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Esta atividade mede a sua memória espacial de curto prazo ao pedir que você repita a ordem em que as %@ se acendem."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flores"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flores"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Algumas das %@ serão acesas uma por vez. Toque nas %@ na mesma ordem em que se acenderam."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Algumas das %@ serão acesas uma por vez. Toque nas %@ na ordem reversa em que se acenderam."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Para começar, toque em Iniciar e observe com atenção."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Pontuação"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Observe as imagens de %@ se acenderem"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Toque nas imagens de %@ na ordem em que se acenderem"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Toque nas imagens de %@ em ordem reversa"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequência Concluída"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Para continuar, toque em Seguinte"; +"MEMORY_GAME_FAILED_TITLE" = "Tentar Novamente"; +"MEMORY_GAME_FAILED_MESSAGE" = "Não foi desta vez. Toque em Seguinte para continuar."; +"MEMORY_GAME_TIMEOUT_TITLE" = "O Tempo Acabou"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "O tempo acabou.\nToque em Seguinte para continuar."; +"MEMORY_GAME_COMPLETE" = "Jogo Concluído"; +"MEMORY_GAME_PAUSED_TITLE" = "Em pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Para continuar, toque em Seguinte"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "A atividade de memória foi desenvolvida com o auxílio de Katherine Possin, PhD e Joel Kramer, PhD da Universidade da Califórnia, São Francisco, EUA."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tempo de Reação"; +"REACTION_TIME_TASK_INTENDED_USE" = "Esta atividade avalia quanto tempo você leva para responder a um sinal visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Agite o dispositivo em qualquer direção assim que o ponto azul aparecer na tela. Você será solicitado a fazer isso %D vezes."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Tentativa %@ de %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Agite o dispositivo rapidamente quando o círculo azul aparecer"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Sempre que uma palavra aparecer, selecione a abreviação do nome da COR mostrada."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Quando estiver pronto para começar a atividade Stroop, toque em Iniciar."; +"STROOP_TASK_STEP_TEXT" = "Selecione a abreviação do nome da COR mostrada."; +"STROOP_COLOR_RED" = "VERMELHO"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "AZUL"; +"STROOP_COLOR_YELLOW" = "AMARELO"; +"STROOP_COLOR_RED_INITIAL" = "Vm"; +"STROOP_COLOR_GREEN_INITIAL" = "Vd"; +"STROOP_COLOR_BLUE_INITIAL" = "Az"; +"STROOP_COLOR_YELLOW_INITIAL" = "Am"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre de Hanói"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Esta atividade avalia a sua capacidade para resolver puzzles."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Mova toda a pilha para a plataforma em destaque usando o menor número de movimentos possíveis."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Solucione o Puzzle"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Número de Movimentos: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Não consigo solucionar este puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Amplitude de Movimento"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption deve ser esquerdo ou direito"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Alcance de Movimento do Joelho Esquerdo"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Alcance de Movimento do Joelho Direito"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Esta atividade mede o quanto você consegue esticar o seu joelho esquerdo."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Esta atividade mede o quanto você consegue esticar o seu joelho direito."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sente na beirada de uma cadeira. Ao começar, você colocará o dispositivo no seu joelho esquerdo para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sente na beirada de uma cadeira. Ao começar, você colocará o dispositivo no seu joelho direito para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posicione o dispositivo no seu joelho esquerdo com a tela voltada para fora, conforme a imagem."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posicione o dispositivo no seu joelho direito com a tela voltada para fora, conforme a imagem."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quando estiver pronto, toque na tela para começar e estenda o joelho esquerdo o máximo que conseguir. Retorne à posição inicial e toque novamente quando tiver terminado."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quando estiver pronto, toque na tela para começar e estenda o joelho direito o máximo que conseguir. Retorne à posição inicial e toque novamente quando tiver terminado."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloque o dispositivo no joelho esquerdo. Toque na tela e estenda o joelho esquerdo o máximo que conseguir."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloque o dispositivo no joelho direito. Toque na tela e estenda o joelho direito o máximo que conseguir."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando tiver terminado, retorne o joelho esquerdo à posição inicial. Depois toque em qualquer lugar."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando tiver terminado, retorne o joelho direito à posição inicial. Depois toque em qualquer lugar."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Alcance de Movimento do Ombro Esquerdo"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Alcance de Movimento do Ombro Direito"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Esta atividade mede o quanto você consegue esticar o seu ombro esquerdo."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Esta atividade mede o quanto você consegue esticar o seu ombro direito."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Ao começar, você colocará o dispositivo no seu ombro esquerdo para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Ao começar, você colocará o dispositivo no seu ombro direito para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Posicione o dispositivo no seu ombro esquerdo com a tela voltada para fora, conforme a imagem."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Posicione o dispositivo no seu ombro direito com a tela voltada para fora, conforme a imagem."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Quando estiver pronto, toque na tela para começar e levante o braço esquerdo o máximo que conseguir. Retorne à posição inicial e toque novamente quando tiver terminado."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Quando estiver pronto, toque na tela para começar e levante o braço direito o máximo que conseguir. Retorne à posição inicial e toque novamente quando tiver terminado."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloque o dispositivo no ombro esquerdo. Toque na tela e levante o braço esquerdo à frente o máximo que conseguir."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloque o dispositivo no ombro direito. Toque na tela e levante o braço direito à frente o máximo que conseguir."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando tiver terminado, retorne o braço esquerdo à posição inicial. Depois toque em qualquer lugar."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando tiver terminado, retorne o braço direito à posição inicial. Depois toque em qualquer lugar."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Caminhada Cronometrada"; +"TIMED_WALK_INTRO_DETAIL" = "Esta atividade mede o funcionamento das suas extremidades inferiores."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Encontre um local, de preferência ao ar livre, onde você possa andar por %@ em linha reta o mais rápido que puder com segurança. Não desacelere até ultrapassar a linha de chegada."; +"TIMED_WALK_INTRO_2_DETAIL" = "Toque em Seguinte para começar."; +"TIMED_WALK_FORM_TITLE" = "Dispositivo assistivo"; +"TIMED_WALK_FORM_TEXT" = "Use o mesmo dispositivo assistivo para cada teste."; +"TIMED_WALK_QUESTION_TEXT" = "Você usa uma órtese no tornozelo?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Você usa um dispositivo assistivo?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Toque para selecionar resposta."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nenhum"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Bengala Unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Muleta Unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bengala Bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Muleta Bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Andador/Rodador"; +"TIMED_WALK_INSTRUCTION_%@" = "Ande por até %@ em linha reta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Dê meia-volta."; +"TIMED_WALK_INSTRUCTION_2" = "Caminhe de volta ao local onde você começou."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Toque em Seguinte ao concluir."; + +/* PSAT active task. */ +"PASAT_TITLE" = "TASAM"; +"PVSAT_TITLE" = "TASVM"; +"PAVSAT_TITLE" = "TASAV"; +"PASAT_INTRO_TEXT" = "O Teste de Adição Sequencial de Audição Medida processa a velocidade e capacidade de calcular para medir suas informações auditivas."; +"PVSAT_INTRO_TEXT" = "O Teste de Adição Sequencial de Visão Medida processa a velocidade e capacidade de calcular para medir suas informações visuais."; +"PAVSAT_INTRO_TEXT" = "O Teste de Adição Sequencial de Audição e Visão mede suas informações auditivas e visuais processando a velocidade e a capacidade de calcular."; +"PSAT_INTRO_TEXT_2_%@" = "Dígitos únicos são apresentados a cada %@.\nVocê deve adicionar cada novo dígito ao dígito anterior.\nAtenção, não calcule um total cumulativo, apenas a soma dos últimos dois números."; +"PSAT_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"PSAT_INITIAL_INSTRUCTION" = "Memorize este primeiro dígito."; +"PSAT_INSTRUCTION" = "Adicione esse novo dígito ao anterior."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Teste dos %@ Pinos nos Buracos"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Esta atividade determinará a capacidade das suas extremidades superiores, solicitando que você coloque um círculo dentro de um buraco. Você precisará fazer isso %@ vezes."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Tanto a sua mão esquerda como a direita serão testadas.\nVocê deve pegar o círculo o mais rapidamente possível, colocá-lo no buraco e, após repetir %@ vezes, removê-lo novamente %@ vezes."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Tanto a sua mão direita como a esquerda serão testadas.\nVocê deve pegar o círculo o mais rapidamente possível, colocá-lo no buraco e, após repetir %@ vezes, removê-lo novamente %@ vezes."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Coloque o círculo no buraco com sua mão esquerda."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Coloque o círculo no buraco com sua mão direita."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Coloque o círculo atrás da linha com sua mão esquerda."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Coloque o círculo atrás da linha com sua mão direita."; +"HOLE_PEG_TEST_TEXT" = "Pegue o círculo usando dois dedos."; +"HOLE_PEG_TEST_TEXT_2" = "Tire o dedo da tela para largar o círculo."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Esta atividade mede o tremor das mãos em várias posições. Encontre um local onde você possa se sentar confortavelmente durante esta atividade."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Segure o telefone na mão mais afetada, conforme mostrado na imagem abaixo."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Segure o telefone na mão DIREITA, conforme mostrado na imagem abaixo."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Segure o telefone na mão ESQUERDA, conforme mostrado na imagem abaixo."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Você será solicitado a realizar %@ sentado com o telefone na mão."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "uma tarefa"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "duas tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "três tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quatro tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinco tarefas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Toque em Seguinte para prosseguir."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepare-se para segurar o telefone na perna."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepare-se para segurar o telefone na perna com a mão ESQUERDA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepare-se para segurar o telefone na perna com a mão DIREITA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Continue segurando o telefone na perna por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Agora segure o telefone com a mão estendida na altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Agora segure o telefone com a mão ESQUERDA estendida na altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Agora segure o telefone com a mão DIREITA estendida na altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Continue segurando o telefone com a mão estendida por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Agora segure o telefone na altura do ombro com o cotovelo dobrado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Agora segure o telefone com a mão ESQUERDA na altura do ombro com o cotovelo dobrado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Agora segure o telefone com a mão DIREITA na altura do ombro com o cotovelo dobrado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Continue segurando o telefone com o cotovelo dobrado por %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Agora, mantendo o cotovelo dobrado, toque o telefone no nariz repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Agora, mantendo o cotovelo dobrado e com o telefone na mão ESQUERDA, toque o telefone no nariz repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Agora, mantendo o cotovelo dobrado e com o telefone na mão DIREITA, toque o telefone no nariz repetidamente."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Continue tocando o telefone no nariz por %ld segundos"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepare-se para fazer um aceno como o da rainha (acene virando o pulso)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepare-se para fazer um aceno como o da rainha com o telefone na mão ESQUERDA (acene virando o pulso)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepare-se para fazer um aceno como o da rainha com o telefone na mão DIREITA (acene virando o pulso)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Continue fazendo um aceno como da rainha por %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Agora passe o telefone para a mão ESQUERDA e continue para a tarefa seguinte."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Agora passe o telefone para a mão DIREITA e continue para a tarefa seguinte."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continue para a tarefa seguinte."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Atividade concluída."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Você será solicitado a realizar %@ sentado com o telefone em uma das mãos e, depois, na outra."; +"TREMOR_SKIP_LEFT_HAND" = "Não posso realizar esta atividade com a mão ESQUERDA."; +"TREMOR_SKIP_RIGHT_HAND" = "Não posso realizar esta atividade com a mão DIREITA."; +"TREMOR_SKIP_NEITHER" = "Posso realizar esta atividade com ambas as mãos."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Teste de Sequência"; +"TRAILMAKING_INTENDED_USE" = "Esta atividade avalia a sua atenção visual e alternância de tarefas, por meio da gravação do tempo necessário para tocar em uma série de pontos ordenados."; +"TRAILMAKING_INTENDED_USE2_A" = "Após a contagem regressiva, toque nos pontos alternando entre números e letras. Comece tocando no primeiro número ‘1’, depois nos números '2' – '3' – '4'… até alcançar o número '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "Após a contagem regressiva, toque nos pontos alternando entre números e letras. Comece tocando no primeiro número ‘1’, em seguida toque na primeira letra ‘A’, depois em '2' – 'B' – '3' – 'C'… até alcançar o número '7'."; +"TRAILMAKING_INTRO_TEXT" = "Faça isso o mais rápido que conseguir sem cometer erros. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconhecimento de Fala"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Esta atividade grava a sua fala com o microfone na parte inferior do dispositivo e a traduz em texto."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Toque em Iniciar para começar."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Pressione o botão para iniciar a gravação antes de falar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Iniciar Gravação"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Parar Gravação"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Editar Transcrição"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edite o texto transcrito para corrigir possíveis interpretações incorretas da fala."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "A sua transcrição aparecerá aqui."; +"SPEECH_RECOGNITION_FAILED" = "O reconhecimento de fala falhou."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Falha ao inicializar o reconhecimento de fala."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproduzir Áudio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Parar Áudio"; +"SPEECH_IN_NOISE_TITLE" = "Fala com Ruído"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Esta atividade mede a inteligibilidade da fala quando apresentada em ambientes ruidosos."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Como parte deste teste, você vai:\n\nOuvir uma frase;\n\nRepetir claramente o que você ouviu ou avançar para digitar o que você ouviu, usando o teclado. \n\nSe você repetir o que ouviu, terá a opção de modificar a transcrição gerada pelo mecanismo de reconhecimento de fala."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibração do Volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Toque em “Reproduzir Áudio”, ajuste o volume para um nível confortável e toque em “Parar Áudio” para prosseguir."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Ouvir"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Uma frase mesclada com ruído de fundo em Razão Sinal-Ruído (RSR) será reproduzida somente uma vez."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Falar"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repita o que você ouviu."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Não foi possível criar o arquivo"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Não foi possível remover arquivos de registro suficientes para alcançar o limite"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Erro ao definir atributo"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Arquivo não marcado como apagado (não marcado como enviado)"; +"ERROR_DATALOGGER_MULTIPLE" = "Múltiplos erros ao remover os registros"; +"ERROR_RECORDER_NO_DATA" = "Nenhum dado coletado foi encontrado."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Um diretório de saída não foi especificado"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Decibelímetro"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Esta atividade mede o nível de pressão do som do ambiente. Se os níveis de ruído estiverem altos demais, você não poderá prosseguir. Desloque-se para um local mais silencioso para concluir esta tarefa ou refaça-a mais tarde."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculando"; +"ENVIRONMENTSPL_THRESHOLD" = "Limiar: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Ruído ao Fundo OK"; +"ENVIRONMENTSPL_NOISE" = "Excesso de Ruído de Fundo"; +"ENVIRONMENTSPL_TITLE_2" = "Encontre um lugar silencioso"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Para garantir a precisão, este teste deve ser realizado em um ambiente silencioso."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Iniciar Tarefa"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Nenhum Dado"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Mova o controle deslizante para inserir o valor"; +"SLIDER_I_DONT_KNOW" = "Não Sei"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Página"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Voltar"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostrar Miniatura de PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ocultar Miniatura de PDF"; +"AX_BUTTON_ANNOTATE" = "Anotar"; +"AX_BUTTON_SHOW_SEARCH" = "Mostrar Barra de Busca"; +"AX_BUTTON_HIDE_SEARCH" = "Ocultar Barra de Busca"; +"AX_BUTTON_SHARE" = "Compartilhar"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustração de um tique em um círculo azul simbolizando sucesso"; + +"AX_SIGNVIEW_LABEL" = "Campo de assinatura designada"; +"AX_SIGNVIEW_HINT" = "Toque na tela e mova o dedo para assinar"; +"AX_SIGNVIEW_SIGNED" = "Assinado"; +"AX_SIGNVIEW_UNSIGNED" = "Não assinado"; + +"AX_SELECTED" = "Selecionado"; +"AX_UNSELECTED" = "Não selecionado"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECIONE TUDO QUE FOR APLICÁVEL"; + +"AX_SLIDER_LABEL" = "Controle de resposta. Os valores vão de %@ a %@"; +"AX_UNLABELED_IMAGE" = "Imagem sem rótulo"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Iniciar tarefa"; + +"AX.MEMORY.TILE.ACTIVE" = "ativo"; +"AX.MEMORY.TILE.CORRECT" = "correto"; +"AX.MEMORY.TILE.INCORRECT" = "incorreto"; +"AX.MEMORY.TILE.QUIESCENT" = "em repouso"; +"AX.MEMORY.TILE.LABEL" = "Peça do jogo de memória"; + +"AX_IMAGE_CAPTURE_LABEL" = "Pré-visualização da captura"; +"AX_IMAGE_CAPTURED_LABEL" = "Imagem capturada"; + +"AX_VIDEO_CAPTURE_LABEL" = "Pré-visualização da captura de vídeo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captura de vídeo completa"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Não pôde colocar o disco com %@ de tamanho no disco com %@ de tamanho"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Destino"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Toque duas vezes para posicionar o disco"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Toque duas vezes para selecionar o disco mais acima"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Tem disco com tamanhos %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Esvaziar"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Descartar teclado"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Varia entre %@ e %@"; +"AX_GRAPH_STACK_PREFIX" = "Pilha composta de"; +"AX_GRAPH_AND_SEPARATOR" = " e "; +"AX_GRAPH_POINT_%@" = "Ponto: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forma de Onda da Fala"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Quando a gravação começar, ative pela segunda vez para interromper a gravação."; + +"AX_AUDIO_BAR_GRAPH" = "Gráfico de Barras de Áudio"; + +"AX_AMSLER_GRID_LABEL" = "Tela de Amsler"; +"AX_AMSLER_GRID_HINT" = "Use o dedo ou uma caneta stylus para marcar diretamente na grade ou deslize para a esquerda fora da grade para concluir."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Botões Tocáveis"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Toque para Ouvido Esquerdo"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Ative para iniciar o teste. Quando o teste começar, toque diretamente neste botões quando ouvir um som no ouvido esquerdo."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Toque para Ouvido Direito"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Ative para iniciar o teste. Quando o teste começar, toque diretamente neste botões quando ouvir um som no ouvido direito."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Usando o VoiceOver, explore a tela por toques para aprender onde os botões estão localizados. Quando o teste começar, os botões serão diretamente tocáveis.%@"; +"AX_TAP_BUTTON_1_LABEL" = "Toque com um dedo"; +"AX_TAP_BUTTON_2_LABEL" = "Toque com outro dedo"; +"AX_TAP_BUTTON_HINT" = "Ative para tornar os botões diretamente tocáveis."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Usando o VoiceOver, explore a tela por toques para aprender onde os botões estão localizados. Ative um dos botões para torná-los diretamente tocáveis."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Agora você pode tocar diretamente nos botões."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Usando o VoiceOver, você poderá tocar diretamente no botão. Ele estará localizado perto do centro da tela."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Usando o VoiceOver, os botões no teste serão diretamente tocáveis."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Não foi possível decodificar restoreData para inicialização"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..c3cb38c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_BR.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d erro) + other + (%d erros) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.strings new file mode 100755 index 0000000..d2600c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Autorização"; +"CONSENT_NAME_GIVEN" = "Nome"; +"CONSENT_NAME_FAMILY" = "Apelido"; +"CONSENT_NAME_PLACEHOLDER" = "necessário"; +"CONSENT_REVIEW_TITLE" = "Leia com atenção"; +"CONSENT_REVIEW_INSTRUCTION" = "Leia com atenção o texto abaixo e toque em Concordo se pretende continuar."; +"CONSENT_REVIEW_ALERT_TITLE" = "Leia com atenção"; +"CONSENT_SIGNATURE_TITLE" = "Assinatura"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Assine com o dedo na caixa abaixo."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Assine aqui"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Página %1$ld de %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Damos‑lhe as boas‑vindas!"; +"CONSENT_SECTION_DATA_GATHERING" = "Recolha de dados"; +"CONSENT_SECTION_PRIVACY" = "Privacidade"; +"CONSENT_SECTION_DATA_USE" = "Utilização de dados"; +"CONSENT_SECTION_STUDY_SURVEY" = "Inquérito"; +"CONSENT_SECTION_STUDY_TASKS" = "Tarefas"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tempo dedicado"; +"CONSENT_SECTION_WITHDRAWING" = "Desistência"; +"CONSENT_LEARN_MORE_TITLE" = "Saiba mais"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Saiba mais acerca de como os dados são recolhidos."; +"LEARN_MORE_DATA_USE" = "Saiba mais acerca de como os dados são utilizados."; +"LEARN_MORE_PRIVACY" = "Saiba mais acerca de como a sua privacidade e identidade são protegidas."; +"LEARN_MORE_WELCOME" = "Saiba mais acerca deste inquérito antes de começar."; +"LEARN_MORE_STUDY_SURVEY" = "Saiba mais acerca deste inquérito."; +"LEARN_MORE_TIME_COMMITMENT" = "Saiba mais acerca da duração do estudo."; +"LEARN_MORE_TASKS" = "Saiba mais acerca das tarefas incluídas."; +"LEARN_MORE_WITHDRAWING" = "Saiba mais acerca de como desistir do inquérito."; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opções de partilha"; +"CONSENT_SHARE_WIDELY_%@" = "Partilhar dados com %@ e investigadores qualificados em todo o mundo"; +"CONSENT_SHARE_ONLY_%@" = "Partilhar dados só com %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ receberá os dados relativos à sua participação neste estudo.\n\nPartilhar os seus dados codificados com mais entidades (excluindo informação como o seu nome, por exemplo) beneficiará estudos futuros."; +"LEARN_MORE_CONSENT_SHARING" = "Saiba mais acerca da partilha de dados"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nome (maiúsculas)"; +"CONSENT_DOC_LINE_SIGNATURE" = "Assinatura"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ de %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Pergunta %1$@ de %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Ignorada"; +"REVIEW_EDIT_ANSWER" = "Editar"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valor inválido"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ ultrapassa o valor máximo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ é inferior ao valor mínimo permitido (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ não é um valor válido."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Endereço de e‑mail inválido: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Digite um endereço"; +"LOCATION_ERROR_TITLE" = "Não foi possível encontrar o endereço indicado."; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Não foi possível encontrar a localização atual. Digite um endereço ou desloque‑se para um local com sinal GPS mais forte."; +"LOCATION_ERROR_MESSAGE_DENIED" = "O acesso aos serviços de localização foi recusado. Permita a esta aplicação aceder a estes serviços nas Definições."; +"LOCATION_ERROR_GEOCODE" = "Não foi encontrado nenhum resultado. Certifique‑se de que o endereço indicado é válido."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Ou não dispõe de ligação à Internet ou excedeu o número limite de consultas. Caso não tenha ligação estabelecida à Internet, ative a rede Wi‑Fi para responder a esta pergunta ou para a ignorar (se esta opção estiver disponível). Também pode optar por voltar ao questionário quando tiver estabelecido ligação à Internet ou por voltar a tentar dentro de alguns minutos."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Conteúdo de texto que excede o comprimento máximo: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "A câmara não está disponível em ecrã dividido."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E‑mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "mmacieira@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Palavra‑passe"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Digite"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmar"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Volte a digitar"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "As palavras‑passe não coincidem."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informação adicional"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Manuel"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Macieira"; +"GENDER_FORM_ITEM_TITLE" = "Sexo"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Escolha o sexo"; +"DOB_FORM_ITEM_TITLE" = "Data de nascimento"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Data"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Número de telefone"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Confirmação"; +"VERIFICATION_STEP_TITLE" = "Confirme o e‑mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Caso não tenha recebido um e‑mail de confirmação, toque na hiperligação abaixo; o e‑mail voltará a ser enviado."; +"RESEND_EMAIL_BUTTON_TITLE" = "Reenviar e‑mail de confirmação"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Iniciar sessão"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Não se lembra da palavra‑passe?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Digite o código"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmar código"; +"PASSCODE_SAVED_MESSAGE" = "Código guardado"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Código autenticado"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Digite o código antigo"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Digite o novo código"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirme o novo código"; +"PASSCODE_INVALID_ALERT_TITLE" = "Código incorreto"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Introduziu códigos diferentes. Volte a tentar."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Efetue autenticação com o Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Erro do Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Só são permitidos caracteres numéricos."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicador de progresso de introdução do código"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ de %@ dígitos introduzidos"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Não se lembra do código?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Não foi possível adicionar elemento do Porta‑chaves."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Não foi possível atualizar elemento do Porta‑chaves."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Não foi possível apagar elemento do Porta‑chaves."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Não foi possível encontrar elemento do Porta‑chaves."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tipo I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tipo II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tipo III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tipo IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tipo V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tipo VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Feminino"; +"GENDER_MALE" = "Masculino"; +"GENDER_OTHER" = "Outro"; + +/* Boolean answer strings */ +"BOOL_NO" = "Não"; +"BOOL_YES" = "Sim"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "pés"; +"MEASURING_UNIT_IN" = "pol."; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "esquerdo"; +"LIMB_RIGHT" = "direito"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Toque para responder"; +"NULL_ANSWER" = "Selecione uma resposta"; +"PLACEHOLDER_IMAGE_CHOICES" = "Toque para selecionar"; +"PLACEHOLDER_LONG_TEXT" = "Toque para escrever"; + +/* Button titles */ +"BUTTON_AGREE" = "Concordo"; +"BUTTON_CANCEL" = "Cancelar"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Limpar"; +"BUTTON_CLEAR_SIGNATURE" = "Limpar assinatura"; +"BUTTON_APPLY" = "Aplicar"; +"BUTTON_DISAGREE" = "Não concordo"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Começar"; +"BUTTON_LEARN_MORE" = "Saiba mais"; +"BUTTON_NEXT" = "Seguinte"; +"BUTTON_SKIP" = "Ignorar"; +"BUTTON_SKIP_QUESTION" = "Passar à pergunta seguinte"; +"BUTTON_START_TIMER" = "Iniciar relógio"; +"BUTTON_OPTION_SAVE" = "Guardar para depois"; +"BUTTON_OPTION_DISCARD" = "Não usar os resultados"; +"BUTTON_OPTION_STOP_TASK" = "Terminar tarefa"; +"BUTTON_SAVE" = "Guardar"; +"BUTTON_CLEAR_ANSWER" = "Limpar resposta"; +"BUTTON_READ_ONLY_MODE" = "Esta resposta não pode ser alterada."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Fechar"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "A iniciar exercício daqui a"; +"TASK_COMPLETE_TITLE" = "Exercício concluído"; +"TASK_COMPLETE_TEXT" = "Os seus dados serão analisados e receberá um aviso quando os resultados estiverem disponíveis."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Falta: %@."; +"TOUCH_ANYWHERE_LABEL" = "Toque em qualquer lugar para continuar"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturar imagem"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Voltar a capturar imagem"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nenhuma câmara encontrada. Não foi possível concluir este passo."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Para completar este passo, permita que esta aplicação aceda à câmara nas Definições."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Não foi especificado nenhum diretório de saída para as imagens capturadas."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Não foi possível guardar a imagem capturada."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Iniciar gravação"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Parar gravação"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Voltar a filmar"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distância (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Ritmo cardíaco (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sente‑se confortavelmente durante %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Ande o mais depressa que puder durante %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Este exercício mede o seu ritmo cardíaco e a distância que consegue percorrer a pé em %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Durante %1$@, ande na rua o mais depressa que puder. No fim, sente‑se confortavelmente e descanse durante %2$@. Para dar início ao teste, toque em Começar."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Equilíbrio e modo de andar"; +"WALK_INTRO_TEXT" = "Este exercício mede o seu equilíbrio e modo de andar. Se não tem condições para andar em segurança sem ajuda, não continue."; +"WALK_INTRO_2_TEXT_%ld" = "Encontre um sítio onde possa andar em linha reta, em segurança e sem ajuda, durante aproximadamente %ld passos."; +"WALK_INTRO_2_DETAIL" = "Ponha o dispositivo no bolso ou dentro da mala e siga as instruções via áudio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Agora, pare e mantenha-se de pé durante %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Pare e mantenha-se de pé durante %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Dê meia‑volta e volte ao ponto de partida."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Dê até %ld passos em linha reta."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Escolha um sítio onde possa andar em segurança, para trás e para frente em linha reta. Tente andar sem parar, dando a volta no final do percurso como se estivesse a andar à volta de um cone.\n\nDepois, ser‑lhe‑á pedido que se vire, dando uma volta completa, e que permaneça imóvel, com os braços ao logo do corpo e os pés afastados à largura dos ombros."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Quando estiver pronto(a), toque em Começar.\nDepois, coloque o dispositivo no bolso ou na carteira e siga as instruções via áudio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Ande em linha reta, para trás e para frente, durante %@. Ande normalmente."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Rode dando uma volta completa e, depois, permaneça imóvel durante %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Concluiu este exercício."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Velocidade de toque"; +"TAPPING_TASK_TITLE_RIGHT" = "Mão direita"; +"TAPPING_TASK_TITLE_LEFT" = "Mão esquerda"; +"TAPPING_INTRO_TEXT" = "Este exercício mede a sua velocidade de toque."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Coloque o dispositivo numa superfície plana."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Com dois dedos da mesma mão, toque alternadamente nos botões no ecrã."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Com dois dedos da mão direita, toque alternadamente nos botões no ecrã."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Com dois dedos da mão esquerda, toque alternadamente nos botões no ecrã."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Agora repita o mesmo teste com a mão direita."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Agora repita o mesmo teste com a mão esquerda."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Toque com um dedo e depois com o outro. Tente fazer com que os toques sejam o mais regulares possível. Continue a tocar durante %@."; +"TAPPING_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Toque em Seguinte para começar."; +"TAP_BUTTON_TITLE" = "Toque"; +"TOTAL_TAPS_LABEL" = "Total de toques"; +"TAPPING_INSTRUCTION" = "Com dois dedos, toque nos botões o mais regularmente que puder."; +"TAPPING_INSTRUCTION_RIGHT" = "Com a mão DIREITA, toque nos botões."; +"TAPPING_INSTRUCTION_LEFT" = "Com a mão ESQUERDA, toque nos botões."; +"TAPPING_SKIP_TITLE" = "Não testar esta mão"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Grelha de Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Este exercício ajuda a detetar problemas na visão do utilizador."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Mantenha o dispositivo a uma distância de 30 centímetros do seu rosto, ao nível dos olhos, durante o teste."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Feche o %@ e olhe atentamente para o ponto no centro da grelha.\n\nCom o dedo ou o estilete, marque as distorções que vê, tais como linhas desfocadas ou onduladas.\n\nQuando terminar, passe o dedo para a esquerda em qualquer local fora da grelha."; +"AMSLER_GRID_LEFT_EYE" = "olho esquerdo"; +"AMSLER_GRID_RIGHT_EYE" = "olho direito"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voz"; +"AUDIO_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"AUDIO_INSTRUCTION" = "Diga “Aaaaah” ao microfone durante o máximo de tempo possível."; +"AUDIO_INTRO_TEXT" = "Respire fundo e diga “Aaaaah” ao microfone durante o máximo de tempo possível. Mantenha um nível vocal estável - as barras de áudio devem permanecer azuis."; +"AUDIO_INTENDED_USE" = "Este exercício avalia a sua voz, gravando‑a através do microfone na parte inferior do dispositivo."; +"AUDIO_TOO_LOUD_LABEL" = "Demasiado alto"; +"AUDIO_GENERIC_ERROR_LABEL" = "Não é possível gravar áudio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Aguarde enquanto verificamos o nível de ruído de fundo."; +"AUDIO_TOO_LOUD_MESSAGE" = "O nível de ruído ambiente é demasiado elevado para gravar a sua voz. Desloque‑se para um local menos ruidoso e volte a tentar."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Quando estiver pronto(a), toque em Seguinte."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria de tom"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Este exercício mede a sua capacidade de ouvir sons diferentes."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Antes de começar, ligue os auscultadores e coloque‑os na cabeça.\n\nO som será muito subtil e não é como um som de aviso normal. O som começará suave e, lentamente, aumentará de volume. Preste atenção e toque no botão da esquerda ou da direita para indicar em que ouvido está a escutar o som."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Deverá ouvir um som agora. Ajuste o volume usando os controlos na parte lateral do dispositivo.\n\nToque em qualquer botão quando estiver pronto(a) para começar."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Sempre que começar a ouvir um som, toque no botão esquerdo ou direito para indicar o ouvido em que está a ouvir o som."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Ouvido esquerdo"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Ouvido direito"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, esquerda"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, direita"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometria de tom"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Toque quando ouvir um som."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Som e volume"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Ouvirá uma série de sons."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Quando ouvir um som, toque no botão."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Para este teste, o volume será definido a 50 por cento."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Este teste demora cerca de 10 minutos."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Ative a funcionalidade Não incomodar para evitar interrupções."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Ouvirá primeiro os sons no ouvido direito."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Agora ouvirá os sons no ouvido esquerdo."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Este exercício identifica os limiares de audição de uma pessoa na escala dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Certifique‑se de que o volume do dispositivo está no máximo.\n\nDurante esta tarefa, um som subtil será reproduzido no ouvido esquerdo ou direito.\n\nOuça atentamente e toque no botão sempre que ouvir um som."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Este teste identifica quão alto um som tem de ser para que o consiga ouvir."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Questionário de preparação."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selecione a sua preferência de “melhor ouvido”, se for o caso"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "esquerdo"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "direito"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "sem preferência"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Teste cancelado"; +"dBHL_ALERT_TITLE_START_OVER" = "Recomeçar"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Cancelar teste"; +"dBHL_ALERT_TEXT" = "Volte a ligar os AirPods ou EarPods para fazer este teste."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ concluído"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Auscultadores"; +"HEADPHONES_UNKNOWN" = "Desconhecidos"; +"HEADPHONES_NONE" = "Nenhuns"; +"CONNECTED" = "Ligação estabelecida"; +"NOT_CONNECTED" = "Ligação não estabelecida"; +"HEADPHONE_CONNECTED_%@" = "Ligação estabelecida – %@"; +"HEADPHONE_DETECT_TITLE" = "Ligue os auscultadores"; +"HEADPHONE_DETECT_TEXT" = "Este teste requer Apple AirPods ou Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memória espacial"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Este exercício mede a sua memória espacial de curto termo, pedindo‑lhe que repita a ordem pela qual os elementos (%@) se tornam mais destacados."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flores"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flores"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Um de cada vez, alguns dos elementos (%@) vão ficar mais destacados que os outros. Toque nos elementos (%@) na ordem pela qual se destacam."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Um de cada vez, alguns dos elementos (%@) vão ficar mais destacados que os outros. Toque nos elementos (%@) na ordem inversa à qual se destacam."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Para dar início ao teste, toque em Começar e observe com atenção."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Resultado"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Note como os elementos (%@) ficam mais destacados."; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Toque nos elementos (%@) na ordem em que se destacam."; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Toque nos elementos (%@) em ordem contrária."; +"MEMORY_GAME_COMPLETE_TITLE" = "Sequência completa"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Para continuar, toque em Seguinte"; +"MEMORY_GAME_FAILED_TITLE" = "Voltar a tentar"; +"MEMORY_GAME_FAILED_MESSAGE" = "Desta vez, não correu muito bem. Toque em Seguinte para continuar."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Fim do tempo"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Acabou o tempo.\nToque em Seguinte para continuar."; +"MEMORY_GAME_COMPLETE" = "Jogo terminado"; +"MEMORY_GAME_PAUSED_TITLE" = "Em pausa"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Para continuar, toque em Seguinte"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "O exercício de memória foi desenvolvido com o apoio de Katherine Possin, PhD, e Joel Kramer, PhD, da Universidade da Califórnia, São Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tempo de reação"; +"REACTION_TIME_TASK_INTENDED_USE" = "Este exercício avalia o seu tempo de resposta a uma pista visual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Agite o dispositivo em qualquer direção assim que o ponto azul aparecer no ecrã. Ser-lhe-á pedido para fazer isto %D vezes."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Tentativa %@ de %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Agite rapidamente o dispositivo quando o círculo azul aparecer"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Sempre que aparecer uma palavra, selecione a quarta letra do nome da COR mostrada."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Quando estiver pronto(a) para começar o exercício Stroop, toque em Começar."; +"STROOP_TASK_STEP_TEXT" = "Selecione a quarta letra do nome da COR mostrada."; +"STROOP_COLOR_RED" = "VERMELHO"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "AZUL"; +"STROOP_COLOR_YELLOW" = "AMARELO"; +"STROOP_COLOR_RED_INITIAL" = "M"; +"STROOP_COLOR_GREEN_INITIAL" = "D"; +"STROOP_COLOR_BLUE_INITIAL" = "L"; +"STROOP_COLOR_YELLOW_INITIAL" = "R"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Torre de Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Este exercício avalia a sua capacidade de resolver puzzles."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Mova a pilha inteira para a plataforma destacada no menor número de movimentos possível."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Resolver o puzzle"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Número de movimentos: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Não consigo resolver este puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Intervalo de movimento"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption tem de ser direito ou esquerdo"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitude de movimento do joelho esquerdo"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitude de movimento do joelho direito"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Este exercício mede a amplitude de movimento do seu joelho esquerdo."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Este exercício mede a amplitude de movimento do seu joelho direito."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sente‑se na extremidade de uma cadeira. Ao iniciar, coloque o dispositivo sobre o seu joelho esquerdo para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sente‑se na extremidade de uma cadeira. Ao iniciar, coloque o dispositivo sobre o seu joelho direito para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Coloque o dispositivo sobre o seu joelho esquerdo com o ecrã virado para fora, como na imagem."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Coloque o dispositivo sobre o seu joelho direito com o ecrã virado para fora, como na imagem."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Toque no ecrã para começar. Estenda o joelho esquerdo o mais que puder e, depois, volte à posição inicial. Quando terminar, toque novamente no ecrã."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Toque no ecrã para começar. Estenda o joelho direito o mais que puder e, depois, volte à posição inicial. Quando terminar, toque novamente no ecrã."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloque o dispositivo sobre o joelho esquerdo. Toque no ecrã e estenda o joelho esquerdo o mais que puder."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloque o dispositivo sobre o joelho direito. Toque no ecrã e estenda o joelho direito o mais que puder."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando terminar, coloque o joelho esquerdo na posição inicial. Depois, toque em qualquer parte do ecrã."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando terminar, coloque o joelho direito na posição inicial. Depois, toque em qualquer parte do ecrã."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitude de movimento do ombro esquerdo"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitude de movimento do ombro direito"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Este exercício mede a amplitude de movimento do seu ombro esquerdo."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Este exercício mede a amplitude de movimento do seu ombro direito."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Ao iniciar, coloque o dispositivo sobre o seu ombro esquerdo para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Ao iniciar, coloque o dispositivo sobre o seu ombro direito para uma medição. Ative o som do dispositivo para poder ouvir as instruções."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Coloque o dispositivo sobre o seu ombro esquerdo com o ecrã virado para fora, como na imagem."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Coloque o dispositivo sobre o seu ombro direito com o ecrã virado para fora, como na imagem."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Toque no ecrã para começar. Levante o braço esquerdo o mais que puder e, depois, volte à posição inicial. Quando terminar, toque novamente no ecrã."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Toque no ecrã para começar. Levante o braço direito o mais que puder e, depois, volte à posição inicial. Quando terminar, toque novamente no ecrã."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Coloque o dispositivo sobre o ombro esquerdo. Toque no ecrã e levante o braço esquerdo o mais que puder."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Coloque o dispositivo sobre o ombro direito. Toque no ecrã e levante o braço direito o mais que puder."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Quando terminar, coloque o braço esquerdo na posição inicial. Depois, toque em qualquer parte do ecrã."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Quando terminar, coloque o braço direito na posição inicial. Depois, toque em qualquer parte do ecrã."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Caminhada temporizada"; +"TIMED_WALK_INTRO_DETAIL" = "Este exercício mede a função das suas extremidades inferiores."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Encontre um lugar, de preferência no exterior, onde possa caminhar durante cerca de %@ em linha reta o mais rapidamente possível, mas em segurança. Não abrande até passar a meta."; +"TIMED_WALK_INTRO_2_DETAIL" = "Toque em Seguinte para começar."; +"TIMED_WALK_FORM_TITLE" = "Dispositivo auxiliar"; +"TIMED_WALK_FORM_TEXT" = "Use o mesmo dispositivo auxiliar para cada teste."; +"TIMED_WALK_QUESTION_TEXT" = "Utiliza uma órtotese tornozelo-pé?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Usa dispositivo auxiliar?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Toque aqui para responder."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nenhum"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Bengala unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Muleta unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bengala bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Muleta bilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Andarilho"; +"TIMED_WALK_INSTRUCTION_%@" = "Caminhe até %@ em linha reta."; +"TIMED_WALK_INSTRUCTION_TURN" = "Dê meia‑volta."; +"TIMED_WALK_INSTRUCTION_2" = "Volte ao ponto de partida."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Toque em Seguinte quando terminar."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "O teste PASAT (Paced Auditory Serial Addition Test) mede a velocidade de processamento de informação auditiva e a capacidade de cálculo."; +"PVSAT_INTRO_TEXT" = "O teste PVSAT (Paced Auditory Serial Addition Test) mede a velocidade de processamento de informação visual e a capacidade de cálculo."; +"PAVSAT_INTRO_TEXT" = "O teste PAVSAT (Paced Auditory and Visual Serial Addition Test) mede a velocidade de processamento de informação auditiva e visual e a capacidade de cálculo."; +"PSAT_INTRO_TEXT_2_%@" = "É apresentado um dígito a cada %@.\nTem de adicionar cada novo dígito ao dígito imediatamente anterior.\nAtenção: não deve calcular o valor total, mas apenas a soma dos últimos dois dígitos."; +"PSAT_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"PSAT_INITIAL_INSTRUCTION" = "Lembre-se deste primeiro dígito."; +"PSAT_INSTRUCTION" = "Adicione este novo dígito ao anterior."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Teste dos %@ buracos e pinos"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Esta exercício mede as funções das extremidades superiores pedindo‑lhe que coloque um círculo dentro de um buraco. Ser-lhe-à pedido que repita %@ vezes."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "As duas mãos serão testadas.\nTem de pegar no círculo o mais depressa possível e arrastá‑lo para o buraco. Depois de o fazer %@ vezes, faça o movimento contrário e remova o círculo do buraco %@ vezes."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "As duas mãos serão testadas.\nTem de pegar no círculo o mais depressa possível e arrastá‑lo para o buraco. Depois de o fazer %@ vezes, faça o movimento contrário e remova o círculo do buraco %@ vezes."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Com a mão esquerda, ponha o círculo dentro do buraco."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Com a mão direita, ponha o círculo dentro do buraco."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Com a mão esquerda, ponha o círculo do outro lado da linha."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Com a mão direita, ponha o círculo do outro lado da linha."; +"HOLE_PEG_TEST_TEXT" = "Apanhe o círculo com dois dedos."; +"HOLE_PEG_TEST_TEXT_2" = "Levante os dedos para largar o círculo."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Este exercício mede o tremor das mãos em várias posições. Durante todo o exercício, é importante manter‑se confortavelmente sentado(a)."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Segure no telefone (como mostra a imagem abaixo) com a mão mais afetada."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Segure no telefone (como mostra a imagem abaixo) com a mão DIREITA."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Segure no telefone (como mostra a imagem abaixo) com a mão ESQUERDA."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Ser‑lhe‑à pedido que efetue %@, na posição sentada, com o telefone na mão."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "uma tarefa"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "duas tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "três tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "quatro tarefas"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinco tarefas"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Toque em Seguinte para continuar."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Prepare‑se para segurar no telefone no colo."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Prepare‑se para segurar no telefone no colo, com a mão ESQUERDA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Prepare‑se para segurar no telefone no colo, com a mão DIREITA."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Continue com o telefone no colo durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Agora segure no telefone com o braço estendido à altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Agora segure no telefone com a mão ESQUERDA, com o braço estendido à altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Agora segure no telefone com a mão DIREITA, com o braço estendido à altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Continue a segurar no telefone com o braço estendido durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Agora segure no telefone à altura do ombro, com o cotovelo dobrado."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Agora, segure no telefone com a mão ESQUERDA e, com o cotovelo dobrado, levante o braço à altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Agora, segure no telefone com a mão DIREITA e, com o cotovelo dobrado, levante o braço à altura do ombro."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Continue a segurar no telefone com o cotovelo dobrado durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Agora, mantendo o cotovelo dobrado, toque repetidamente no nariz com o telefone."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Agora, com a mão ESQUERDA e mantendo o cotovelo dobrado, toque repetidamente no nariz com o telefone."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Agora, com a mão DIREITA e mantendo o cotovelo dobrado, toque repetidamente no nariz com o telefone."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Continue a tocar com o telefone no nariz durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Prepare‑se para acenar (rodando o pulso com a mão levantada)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Prepare‑se para acenar com o telefone na mão ESQUERDA (rodando o pulso com a mão levantada)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Prepare‑se para acenar com o telefone na mão DIREITA (rodando o pulso com a mão levantada)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Continue a acenar com a mão durante %ld segundos."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Agora mude o telefone para a mão ESQUERDA e passe à tarefa seguinte."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Agora mude o telefone para a mão DIREITA e passe à tarefa seguinte."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Passar à tarefa seguinte."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Exercício concluído."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Ser‑lhe‑à pedido que efetue %@, na posição sentada, primeiro com o telefone numa mão e, depois, na outra."; +"TREMOR_SKIP_LEFT_HAND" = "Não consigo fazer este exercício com a mão ESQUERDA."; +"TREMOR_SKIP_RIGHT_HAND" = "Não consigo fazer este exercício com a mão DIREITA."; +"TREMOR_SKIP_NEITHER" = "Consigo fazer este exercício com ambas as mãos."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Teste de sequência"; +"TRAILMAKING_INTENDED_USE" = "Este exercício avalia a sua atenção visual e troca de tarefas ao registar o tempo necessário para tocar numa série de pontos por ordem."; +"TRAILMAKING_INTENDED_USE2_A" = "Após a contagem decrescente, toque nos pontos alternando entre números e letras. Comece por tocar no primeiro número “1”, em seguida toque nos números “2” – “3” – “4”… até chegar ao número “7”."; +"TRAILMAKING_INTENDED_USE2_B" = "Após a contagem decrescente, toque nos pontos alternando entre números e letras. Comece por tocar no primeiro número “1”, em seguida toque na primeira letra “A” e depois “2” – “B” – “3” – “C”… até chegar ao número “7”."; +"TRAILMAKING_INTRO_TEXT" = "Faça este exercício o mais depressa possível sem cometer erros. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Reconhecimento da fala"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Este exercício grava a sua fala através do microfone na parte inferior do dispositivo e converte‑a em texto."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Para iniciar, toque em Começar."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Prima o botão para iniciar a gravação antes de falar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Iniciar gravação"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Parar gravação"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Editar transcrição"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Edite o texto transcrito para corrigir qualquer interpretação incorreta da fala."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "A transcrição aparecerá aqui."; +"SPEECH_RECOGNITION_FAILED" = "Falha no reconhecimento da fala."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Não foi possível inicializar o reconhecimento de fala."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Reproduzir áudio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Parar áudio"; +"SPEECH_IN_NOISE_TITLE" = "Fala com ruído"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Este exercício mede a inteligibilidade da fala em ambientes ruidosos."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "No âmbito deste teste, irá:\n\nOuvir uma frase.\n\nRepetir claramente o que ouviu ou passar à frente e digitar o que ouviu com o teclado. \n\nSe optar por repetir o que ouviu, poderá modificar a transcrição gerada pelo motor de reconhecimento de fala."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibragem de volume"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Toque em “Reproduzir áudio” para ajustar o volume para um nível confortável e, depois, toque em “Parar áudio” para avançar."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Ouvir"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Uma frase misturada com ruído de fundo será reproduzida, apenas uma vez, com um rácio sinal/ruído (SNR) aleatório."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Falar"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repita o que ouviu."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Não foi possível criar ficheiro"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Não foi possível remover ficheiros de registo suficientes para atingir o limite."; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Erro ao definir atributo."; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Ficheiro não marcado como pagado (não marcado como enviado)."; +"ERROR_DATALOGGER_MULTIPLE" = "Vários erros ao remover registos."; +"ERROR_RECORDER_NO_DATA" = "Os dados recolhidos não foram encontrados."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Não foi especificado nenhum diretório de saída."; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Nível de SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Este exercício mede o nível de pressão do som ambiente. Se os níveis de ruído forem demasiado elevados, não poderá continuar. Vá para um local mais tranquilo para completar este exercício ou repita‑o mais tarde."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "A calcular…"; +"ENVIRONMENTSPL_THRESHOLD" = "Limiar: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Ruído de fundo aceitável"; +"ENVIRONMENTSPL_NOISE" = "Demasiado ruído de fundo"; +"ENVIRONMENTSPL_TITLE_2" = "Procure um lugar tranquilo"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Para assegurar a precisão do teste, este deverá ser realizado num ambiente tranquilo."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Iniciar tarefa"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Sem dados"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Especifique o valor abaixo"; +"SLIDER_I_DONT_KNOW" = "Não sei"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Página"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Voltar"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Mostrar miniatura do PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ocultar miniatura do PDF"; +"AX_BUTTON_ANNOTATE" = "Anotar"; +"AX_BUTTON_SHOW_SEARCH" = "Mostrar barra de pesquisa"; +"AX_BUTTON_HIDE_SEARCH" = "Ocultar barra de pesquisa"; +"AX_BUTTON_SHARE" = "Partilhar"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustração de uma marca de seleção dentro de um círculo azul a indicar êxito"; + +"AX_SIGNVIEW_LABEL" = "Campo de assinatura"; +"AX_SIGNVIEW_HINT" = "Para assinar, toque no ecrã e escreva com o dedo."; +"AX_SIGNVIEW_SIGNED" = "Assinado"; +"AX_SIGNVIEW_UNSIGNED" = "Por assinar"; + +"AX_SELECTED" = "Selecionado"; +"AX_UNSELECTED" = "Não selecionado"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECIONE O QUE FOR RELEVANTE"; + +"AX_SLIDER_LABEL" = "Nivelador de resposta. De %@ a %@"; +"AX_UNLABELED_IMAGE" = "Imagem sem etiqueta"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Iniciar tarefa"; + +"AX.MEMORY.TILE.ACTIVE" = "ativa"; +"AX.MEMORY.TILE.CORRECT" = "correto"; +"AX.MEMORY.TILE.INCORRECT" = "incorreto"; +"AX.MEMORY.TILE.QUIESCENT" = "quiescente"; +"AX.MEMORY.TILE.LABEL" = "Mosaico do jogo de memória"; + +"AX_IMAGE_CAPTURE_LABEL" = "Pré‑visualização da captura"; +"AX_IMAGE_CAPTURED_LABEL" = "Imagem capturada"; + +"AX_VIDEO_CAPTURE_LABEL" = "Pré‑visualização de vídeo"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captura de vídeo concluída"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Impossível colocar o disco com tamanho %@ no disco com tamanho %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Destino"; +"AX_TOWER_OF_HANOI_TOWER" = "Torre"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Dê dois toques para colocar o disco"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Dê dois toques para selecionar o primeiro disco"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Tem disco com tamanhos %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Vazio"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Fechar teclado"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Intervalo de %@ a %@"; +"AX_GRAPH_STACK_PREFIX" = "Pilha composta por"; +"AX_GRAPH_AND_SEPARATOR" = " e "; +"AX_GRAPH_POINT_%@" = "Ponto: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Forma de onda da fala"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Quando a gravação começar, ative uma segunda vez para parar de gravar."; + +"AX_AUDIO_BAR_GRAPH" = "Gráfico de barras de áudio"; + +"AX_AMSLER_GRID_LABEL" = "Grelha de Amsler"; +"AX_AMSLER_GRID_HINT" = "Use o dedo ou o estilete para assinalar diretamente na grelha ou passe o dedo para a esquerda fora da grelha para terminar."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Botões tocáveis"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Toque para o ouvido esquerdo"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Ative para dar início ao teste. Quando o teste começar, toque diretamente neste botão assim que ouvir um som no ouvido esquerdo."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Toque para o ouvido direito"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Ative para dar início ao teste. Quando o teste começar, toque diretamente neste botão assim que ouvir um som no ouvido direito."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Ao usar o VoiceOver, explore o ecrã através do toque para saber onde se encontram os botões para cada ouvido. Quando o teste começar, poderá tocar diretamente nos botões. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Toque com um dedo"; +"AX_TAP_BUTTON_2_LABEL" = "Toque com outro dedo"; +"AX_TAP_BUTTON_HINT" = "Ative para poder tocar diretamente nos botões."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Ao usar o VoiceOver, explore o ecrã através do toque para saber onde se encontram os botões. Ative um dos botões para poder tocar diretamente nos botões."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Pode agora tocar diretamente nos botões."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Ao usar o VoiceOver, poderá tocar diretamente no botão, quando este aparecer perto do centro do ecrã."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Ao usar o VoiceOver, poderá tocar diretamente nos botões indicados durante o teste."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Não é possível descodificar restoreData para a inicialização"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..c3cb38c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/pt_PT.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d erro) + other + (%d erros) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.strings new file mode 100755 index 0000000..e5de53f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Consimțământ"; +"CONSENT_NAME_GIVEN" = "Prenume"; +"CONSENT_NAME_FAMILY" = "Nume de familie"; +"CONSENT_NAME_PLACEHOLDER" = "Obligatoriu"; +"CONSENT_REVIEW_TITLE" = "Revizuire"; +"CONSENT_REVIEW_INSTRUCTION" = "Revizuiți formularul de mai jos și apăsați pe “De acord” dacă sunteți gata să continuați."; +"CONSENT_REVIEW_ALERT_TITLE" = "Revizuiți"; +"CONSENT_SIGNATURE_TITLE" = "Semnătura"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Semnați folosind degetul în caseta de mai jos."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Semnați aici"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Pagina %1$ld din %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Bun venit"; +"CONSENT_SECTION_DATA_GATHERING" = "Colectarea datelor"; +"CONSENT_SECTION_PRIVACY" = "Intimitate"; +"CONSENT_SECTION_DATA_USE" = "Utilizarea datelor"; +"CONSENT_SECTION_STUDY_SURVEY" = "Chestionar studiu"; +"CONSENT_SECTION_STUDY_TASKS" = "Sarcini studiu"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Alocarea timpului"; +"CONSENT_SECTION_WITHDRAWING" = "Retragere"; +"CONSENT_LEARN_MORE_TITLE" = "Aflați mai multe"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Aflați mai multe despre colectarea datelor"; +"LEARN_MORE_DATA_USE" = "Aflați mai multe despre utilizarea datelor"; +"LEARN_MORE_PRIVACY" = "Aflați mai multe despre protejarea intimității și identității dvs."; +"LEARN_MORE_WELCOME" = "Mai întâi, aflați mai multe despre studiu"; +"LEARN_MORE_STUDY_SURVEY" = "Aflați mai multe despre chestionarul studiului"; +"LEARN_MORE_TIME_COMMITMENT" = "Aflați mai multe despre impactul studiului asupra timpului dvs."; +"LEARN_MORE_TASKS" = "Aflați mai multe despre sarcinile implicate"; +"LEARN_MORE_WITHDRAWING" = "Aflați mai multe despre retragere"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Opțiuni de partajare"; +"CONSENT_SHARE_WIDELY_%@" = "Partajați datele dvs. cu %@ și cercetători calificați din întreaga lume"; +"CONSENT_SHARE_ONLY_%@" = "Partajați datele dvs. doar cu %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ va primi datele referitoare la participarea dvs. la acest studiu.\n\nPartajarea mai extinsă a datelor codificate privind studiul (fără informații precum numele dvs.) poate contribui la această cercetare și la cele viitoare."; +"LEARN_MORE_CONSENT_SHARING" = "Mai multe despre partajarea datelor"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Nume tipărit"; +"CONSENT_DOC_LINE_SIGNATURE" = "Semnătură"; +"CONSENT_DOC_LINE_DATE" = "Data"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ din %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Întrebarea %1$@ din %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Omis"; +"REVIEW_EDIT_ANSWER" = "Editați"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Valoare nevalidă"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "Valoarea “%1$@” depășește maximul permis (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "Valoarea “%1$@” este mai mică decât minimul permis (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ nu este o valoare validă."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Adresă de e-mail nevalidă: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Introduceți o adresă"; +"LOCATION_ERROR_TITLE" = "Adresa specificată nu a putut fi găsită"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Imposibil de rezolvat localizarea dvs. actuală. Introduceți o adresă sau mergeți într-un loc cu semnal GPS mai bun dacă este cazul."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Accesul la serviciile de localizare a fost refuzat. Acordați acestei aplicații permisiunea de a utiliza serviciile de localizare din Configurări."; +"LOCATION_ERROR_GEOCODE" = "Imposibil de găsit un rezultat pentru adresa introdusă. Asigurați-vă că adresa este validă."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Nu dispuneți de o conexiune la internet sau ați depășit numărul maxim al solicitărilor de identificare a adreselor. Dacă nu dispuneți de conexiune la internet, activați Wi-Fi pentru a răspunde la această întrebare, omiteți întrebarea dacă butonul de omitere este disponibil sau reveniți la chestionar după ce vă conectați la internet. În caz contrar, reîncercați peste câteva minute."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Conținutul de text depășește lungimea maximă: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera nu este disponibilă în ecranul divizat."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "ioanapopa@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Parolă"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Introduceți parola"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Confirmați"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Introduceți din nou parola"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Parolele nu coincid."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Informații suplimentare"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Ioana"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Popescu"; +"GENDER_FORM_ITEM_TITLE" = "Sex"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Alegeți o opțiune"; +"DOB_FORM_ITEM_TITLE" = "Data nașterii"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Alegeți o dată"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefon"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verificare"; +"VERIFICATION_STEP_TITLE" = "Verificați-vă e‑mailul"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Apăsați pe linkul de mai jos dacă nu ați primit un e‑mail de verificare și ați dori retrimiterea acestuia."; +"RESEND_EMAIL_BUTTON_TITLE" = "Retrimiteți e‑mailul de verificare"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Login"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Ați uitat parola?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Introduceți codul"; +"PASSCODE_CONFIRM_MESSAGE" = "Confirmare cod"; +"PASSCODE_SAVED_MESSAGE" = "Cod salvat"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Cod autentificat"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Introduceți codul vechi"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Introduceți codul nou"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Confirmați noul cod"; +"PASSCODE_INVALID_ALERT_TITLE" = "Cod incorect"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Codurile nu coincid. Reîncercați."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentificați-vă cu Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Eroare Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Sunt permise doar caractere numerice."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indicator de progres pentru introducerea codului"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ din %@ cifre introduse"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Ați uitat codul de acces?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Imposibil de adăugat articolul din portchei."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Imposibil de actualizat articolul din portchei."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Imposibil de șters articolul din portchei."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Imposibil de găsit articolul din portchei."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tip I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tip II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tip III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tip IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tip V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tip VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Feminin"; +"GENDER_MALE" = "Masculin"; +"GENDER_OTHER" = "Altul"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nu"; +"BOOL_YES" = "Da"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "livre"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "stânga"; +"LIMB_RIGHT" = "dreapta"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Apăsați pentru a răspunde"; +"NULL_ANSWER" = "Selectați un răspuns"; +"PLACEHOLDER_IMAGE_CHOICES" = "Apăsați pentru a selecta"; +"PLACEHOLDER_LONG_TEXT" = "Apăsați pentru a scrie"; + +/* Button titles */ +"BUTTON_AGREE" = "De acord"; +"BUTTON_CANCEL" = "Anulați"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Degajați"; +"BUTTON_CLEAR_SIGNATURE" = "Degajați semnătura"; +"BUTTON_APPLY" = "Aplicați"; +"BUTTON_DISAGREE" = "Nu sunt de acord"; +"BUTTON_DONE" = "OK"; +"BUTTON_GET_STARTED" = "Start"; +"BUTTON_LEARN_MORE" = "Aflați mai multe"; +"BUTTON_NEXT" = "Înainte"; +"BUTTON_SKIP" = "Omiteți"; +"BUTTON_SKIP_QUESTION" = "Omiteți această întrebare"; +"BUTTON_START_TIMER" = "Porniți temporizatorul"; +"BUTTON_OPTION_SAVE" = "Salvați pentru mai târziu"; +"BUTTON_OPTION_DISCARD" = "Abandonați rezultatele"; +"BUTTON_OPTION_STOP_TASK" = "Încheiați sarcina"; +"BUTTON_SAVE" = "Salvați"; +"BUTTON_CLEAR_ANSWER" = "Degajați răspunsul"; +"BUTTON_READ_ONLY_MODE" = "Acest răspuns nu poate fi modificat."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Închideți"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Activitatea începe în"; +"TASK_COMPLETE_TITLE" = "Activitate finalizată"; +"TASK_COMPLETE_TEXT" = "Datele dvs. vor fi analizate și veți primi o notificare atunci când rezultatele vor fi disponibile."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ rămase."; +"TOUCH_ANYWHERE_LABEL" = "Apăsați oriunde pentru a continua"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Capturați imaginea"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Recapturați imaginea"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nicio cameră găsită. Această etapă nu poate fi finalizată."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Pentru a finaliza această etapă, acordați acestei aplicații acces la cameră în Configurări."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Nu a fost specificat un director de ieșire pentru imaginile capturate."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Imaginea capturată nu a putut fi salvată."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Porniți înregistrarea"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Opriți înregistrarea"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Recapturați clipul video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distanță (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Ritm cardiac (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Așezați-vă confortabil timp de %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Mergeți cât de repede puteți timp de %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Această activitate vă monitorizează ritmul cardiac și măsoară cât de mult puteți merge în %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Mergeți în aer liber, în cel mai rapid ritm posibil, timp de %1$@. Când sunteți gata, așezați‑vă și stați confortabil timp de %2$@. Pentru a începe, apăsați pe “Start”."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Mers și echilibru"; +"WALK_INTRO_TEXT" = "Această activitate vă măsoară mersul și echilibrul în timp ce mergeți și stați în repaus. Nu continuați dacă nu puteți merge în siguranță, fără a necesita asistență."; +"WALK_INTRO_2_TEXT_%ld" = "Găsiți un loc unde să puteți merge în siguranță, fără a necesita asistență, aproximativ %ld pași în linie dreaptă."; +"WALK_INTRO_2_DETAIL" = "Puneți dispozitivul într-un buzunar sau într-o geantă și urmați instrucțiunile audio."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Acum nu vă mișcați timp de %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Nu vă mișcați timp de %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Întorceți-vă și mergeți înapoi la locul de pornire."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Mergeți până la %ld pași în linie dreaptă."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Găsiți un loc unde puteți să mergeți în siguranță înainte și înapoi în linie dreaptă. Încercați să mergeți continuu întorcându-vă la capătul traseului ca și cum ați merge în jurul unui con.\n\nÎn continuare, vi se va solicita să vă întoarceți descriind un cerc complet, apoi să stați cu brațele pe lângă corp și cu picioarele depărtate la lățimea umerilor, fără să vă mișcați."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Apăsați “Start” când sunteți gata să începeți.\nApoi puneți dispozitivul într-un buzunar sau într-o geantă și urmați instrucțiunile audio."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Mergeți înainte și înapoi în linie dreaptă timp de %@. Mergeți așa cum o ați face‑o în mod normal."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Întoarceți‑vă descriind un cerc complet, apoi stați în repaus timp de %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Ați finalizat activitatea."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Viteză de apăsare"; +"TAPPING_TASK_TITLE_RIGHT" = "Mâna dreaptă"; +"TAPPING_TASK_TITLE_LEFT" = "Mâna stângă"; +"TAPPING_INTRO_TEXT" = "Această activitate vă măsoară viteza de apăsare cu degetele."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Puneți dispozitivul pe o suprafață plată."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Folosiți două degete de la aceeași mână pentru a apăsa alternativ butoanele de pe ecran."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Folosiți două degete de la mâna dreaptă pentru a apăsa alternativ butoanele de pe ecran."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Folosiți două degete de la mâna stângă pentru a apăsa alternativ butoanele de pe ecran."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Acum, repetați același test folosind mâna dreaptă."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Acum, repetați același test folosind mâna stângă."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Apăsați cu un deget, apoi cu celălalt. Încercați ca apăsările să se succeadă cât de regulat cu putință. Continuați să apăsați timp de %@."; +"TAPPING_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Apăsați “Înainte” pentru a începe."; +"TAP_BUTTON_TITLE" = "Apăsați"; +"TOTAL_TAPS_LABEL" = "Total apăsări"; +"TAPPING_INSTRUCTION" = "Apăsați butoanele cât de consecvent puteți folosind două degete."; +"TAPPING_INSTRUCTION_RIGHT" = "Apăsați butoanele folosind mâna DREAPTĂ."; +"TAPPING_INSTRUCTION_LEFT" = "Apăsați butoanele folosind mâna STÂNGĂ."; +"TAPPING_SKIP_TITLE" = "Omiteți această mână"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Grilă Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Această activitate contribuie la detectarea problemelor de vedere ale utilizatorului."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Țineți dispozitivul la o distanță de 30 cm de față și la nivelul ochilor pe toată durata testului."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Închideți %@ și uitați-vă la punctul din centrul grilei de pătrate.\n\nFolosind degetul sau un stilou, marcați orice distorsiune vedeți, cum ar fi linii estompate sau ondulate.\n\nCând ați terminat, glisați spre stânga oriunde în exteriorul grilei."; +"AMSLER_GRID_LEFT_EYE" = "ochiul stâng"; +"AMSLER_GRID_RIGHT_EYE" = "ochiul drept"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Voce"; +"AUDIO_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"AUDIO_INSTRUCTION" = "Spuneți “Aaaaah” în microfon cât de mult timp puteți."; +"AUDIO_INTRO_TEXT" = "Inspirați adânc și spuneți “Aaaaah” în microfon cât de mult timp puteți. Mențineți un volum vocal constant, astfel încât barele audio să rămână albastre."; +"AUDIO_INTENDED_USE" = "Această activitate vă evaluează vocea prin înregistrarea acesteia cu microfonul din partea de jos a dispozitivului."; +"AUDIO_TOO_LOUD_LABEL" = "Prea tare"; +"AUDIO_GENERIC_ERROR_LABEL" = "Imposibil de înregistrat audio"; +"AUDIO_LEVEL_CHECK_LABEL" = "Așteptați să se verifice nivelul zgomotului de fundal."; +"AUDIO_TOO_LOUD_MESSAGE" = "Nivelul zgomotului ambiental este prea puternic pentru a vă înregistra vocea. Mutați‑vă într‑un loc mai liniștit și reîncercați."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Apăsați “Înainte” când sunteți gata."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Audiometrie tonală"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Această activitate vă măsoară capacitatea de a auzi diferite sunete."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Înainte de a începe, conectați căștile și puneți-le la urechi.\n\nSunetul va fi foarte subtil și diferit de un ton de alertă obișnuit.  La început, sunetul va fi slab, apoi va crește lent în volum.  Fiți atent și apăsați butonul din stânga sau din dreapta pentru a indica urechea în care auziți sunetul."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Ar trebui să auziți acum un ton. Ajustați volumul folosind comenzile de pe lateralul dispozitivului.\n\nApăsați orice buton când sunteți gata de a începe."; +"TONE_AUDIOMETRY_INSTRUCTION" = "De fiecare dată când auziți un sunet, apăsați butonul din stânga sau din dreapta pentru a indica urechea în care auziți sunetul."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Urechea stângă"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Urechea dreaptă"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, stânga"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, dreapta"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Audiometrie tonală"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Apăsați când auziți un ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ton și volum"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Veți auzi o serie de tonuri."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Când auziți un ton, apăsați pe buton."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Pentru acest test, volumul va fi fixat la 50 la sută."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Acest test durează aproximatv 10 minute."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Activați opțiunea “Nu deranjați” pentru a evita întreruperile."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Vor fi redate mai întâi tonuri în urechea dvs. dreaptă."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Acum vor fi redate tonuri în urechea dvs. stângă."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Această activitate identifică nivelul pragului auditiv al unei persoane în scala HL dB."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Asigurați-vă că volumul dispozitivului este la nivel maxim.\n\nPe durata sarcinii va fi redat un ton subtil în urechea stângă sau dreaptă.\n\nAscultați cu atenție și apăsați butonul de fiecare dată când auziți un ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Acest test determină cât de puternic trebuie să fie un sunet pentru a‑l putea auzi."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Chestionar de orientare."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Selectați preferința dvs. pentru urechea cu care auziți mai bine, dacă este cazul"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "stânga"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "dreapta"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "nicio preferință"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test anulat"; +"dBHL_ALERT_TITLE_START_OVER" = "Reîncepeți"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Anulați testul"; +"dBHL_ALERT_TEXT" = "Reconectați‑vă căștile AirPods sau EarPods pentru a face acest test."; +"dBHL_PROGRESS_COMPLETION_%@" = "Finalizat în proporție de %@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Căști audio"; +"HEADPHONES_UNKNOWN" = "Necunoscut"; +"HEADPHONES_NONE" = "Nimic"; +"CONNECTED" = "Conectate"; +"NOT_CONNECTED" = "Neconectate"; +"HEADPHONE_CONNECTED_%@" = "Conectate - %@"; +"HEADPHONE_DETECT_TITLE" = "Conectați‑vă căștile audio"; +"HEADPHONE_DETECT_TEXT" = "Acest test necesită Apple AirPods sau Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Memorie spațială"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Această activitate vă măsoară memoria spațială pe termen scurt, solicitându-vă să repetați ordinea în care se aprind simbolurile reprezentând %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "flori"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "flori"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Unele dintre simbolurile de %@ se vor aprinde pe rând. Apăsați pe %@ în ordinea în care s‑au aprins."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Unele dintre simbolurile de %@ se vor aprinde pe rând. Apăsați pe %@ în ordinea inversă aprinderii lor."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Pentru a începe, apăsați “Start”, apoi priviți cu atenție."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Scor"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Priviți cum se aprind simbolurile de %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Apăsați pe %@ în ordinea în care s‑au aprins"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Apăsați pe %@ în ordine inversă"; +"MEMORY_GAME_COMPLETE_TITLE" = "Secvență finalizată"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Pentru a continua, apăsați “Înainte”"; +"MEMORY_GAME_FAILED_TITLE" = "Reîncercați"; +"MEMORY_GAME_FAILED_MESSAGE" = "Nu ați reușit să vă încadrați în timpul alocat. Apăsați “Înainte” pentru a continua."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Timpul a expirat"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Ați epuizat timpul.\nApăsați “Înainte” pentru a continua."; +"MEMORY_GAME_COMPLETE" = "Joc finalizat"; +"MEMORY_GAME_PAUSED_TITLE" = "Suspendat"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Pentru a continua, apăsați “Înainte”"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Activitatea pentru memorie a fost dezvoltată cu ajutorul dr. Katherine Possin și al dr. Joel Kramer de la Universitatea din California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Timp de reacție"; +"REACTION_TIME_TASK_INTENDED_USE" = "Această activitate evaluează timpul de care aveți nevoie pentru a răspunde la un stimul vizual."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Agitați dispozitivul în orice direcție imediat ce apare cercul albastru pe ecran. Va trebui să repetați acțiunea de %D ori."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Încercarea %@ din %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Agitați rapid dispozitivul atunci când apare cercul albastru"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "De fiecare dată când apare un cuvânt, selectați prima literă a numelui CULORII afișate."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Când sunteți gata să începeți activitatea Stroop, apăsați pe Start."; +"STROOP_TASK_STEP_TEXT" = "Selectați prima literă a numelui CULORII afișate."; +"STROOP_COLOR_RED" = "ROȘU"; +"STROOP_COLOR_GREEN" = "VERDE"; +"STROOP_COLOR_BLUE" = "ALBASTRU"; +"STROOP_COLOR_YELLOW" = "GALBEN"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "V"; +"STROOP_COLOR_BLUE_INITIAL" = "A"; +"STROOP_COLOR_YELLOW_INITIAL" = "G"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Turnul din Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Această activitate evaluează aptitudinile dvs. de rezolvare a puzzle‑urilor"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Mutați toată stiva pe platforma evidențiată din cât mai puține mișcări posibil."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Rezolvați puzzle‑ul"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Număr de mișcări: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Nu pot rezolva acest puzzle"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Amplitudinea mișcării"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption trebuie să fie stânga sau dreapta"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitudinea mișcării genunchiului stâng"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitudinea mișcării genunchiului drept"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Această activitate măsoară cât de mult vă puteți întinde genunchiul stâng."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Această activitate măsoară cât de mult vă puteți întinde genunchiul drept."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Așezați-vă pe marginea unui scaun. Când începeți, puneți-vă dispozitivul pe genunchiul stâng pentru măsurătoare. Activați sunetul pe dispozitivul dvs. pentru a auzi instrucțiunile."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Așezați-vă pe marginea unui scaun. Când începeți, puneți-vă dispozitivul pe genunchiul drept pentru măsurătoare. Activați sunetul pe dispozitivul dvs. pentru a auzi instrucțiunile."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Așezați dispozitivul pe genunchiul stâng cu ecranul în sus, ca în imagine."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Așezați dispozitivul pe genunchiul drept cu ecranul în sus, ca în imagine."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Când sunteți gata, apăsați ecranul pentru a începe și întindeți genunchiul stâng cât de mult puteți. Reveniți la poziția inițială și apăsați din nou când ați terminat."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Când sunteți gata, apăsați ecranul pentru a începe și întindeți genunchiul drept cât de mult puteți. Reveniți la poziția inițială și apăsați din nou când ați terminat."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Așezați dispozitivul pe genunchiul stâng. Apăsați ecranul și întindeți genunchiul stâng cât de mult puteți."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Așezați dispozitivul pe genunchiul drept. Apăsați ecranul și întindeți genunchiul drept cât de mult puteți."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Când sunteți gata, readuceți genunchiul stâng în poziția inițială, apoi apăsați oriunde."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Când sunteți gata, readuceți genunchiul drept în poziția inițială, apoi apăsați oriunde."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Amplitudinea mișcării umărului stâng"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Amplitudinea mișcării umărului drept"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Această activitate măsoară cât de mult vă puteți întinde umărul stâng."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Această activitate măsoară cât de mult vă puteți întinde umărul drept."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Când începeți, puneți-vă dispozitivul pe umărul stâng pentru măsurătoare. Activați sunetul pe dispozitivul dvs. pentru a auzi instrucțiunile."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Când începeți, puneți-vă dispozitivul pe umărul drept pentru măsurătoare. Activați sunetul pe dispozitivul dvs. pentru a auzi instrucțiunile."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Așezați dispozitivul pe umărul stâng cu ecranul în sus, ca în imagine."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Așezați dispozitivul pe umărul drept cu ecranul în sus, ca în imagine."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Când sunteți gata, apăsați ecranul pentru a începe și ridicați brațul stâng cât de mult puteți. Reveniți la poziția inițială și apăsați din nou când ați terminat."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Când sunteți gata, apăsați ecranul pentru a începe și ridicați brațul drept cât de mult puteți. Reveniți la poziția inițială și apăsați din nou când ați terminat."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Așezați dispozitivul pe umărul stâng. Apăsați ecranul și ridicați brațul stâng în față cât de mult puteți."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Așezați dispozitivul pe umărul drept. Apăsați ecranul și ridicați brațul drept în față cât de mult puteți."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Când sunteți gata, readuceți brațul stâng în poziția inițială, apoi apăsați oriunde."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Când sunteți gata, readuceți brațul drept în poziția inițială, apoi apăsați oriunde."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Mers cronometrat"; +"TIMED_WALK_INTRO_DETAIL" = "Această activitate măsoară funcționarea extremităților dvs. inferioare."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Găsiți un loc, preferabil afară, unde să puteți merge aproximativ %@ în linie dreaptă cât de repede posibil, dar în siguranță. Nu încetiniți decât după ce treceți linia de sosire."; +"TIMED_WALK_INTRO_2_DETAIL" = "Apăsați “Înainte” pentru a începe."; +"TIMED_WALK_FORM_TITLE" = "Dispozitiv asistiv"; +"TIMED_WALK_FORM_TEXT" = "Utilizați același dispozitiv asistiv pentru fiecare test."; +"TIMED_WALK_QUESTION_TEXT" = "Purtați o orteză de gleznă?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Utilizați un dispozitiv asistiv?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Apăsați aici pentru un răspuns."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nu"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Baston unilateral"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Cârjă unilaterală"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Bastoane bilaterale"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Cârje bilaterale"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Cadru de mers/cu rotile"; +"TIMED_WALK_INSTRUCTION_%@" = "Mergeți până la %@ în linie dreaptă."; +"TIMED_WALK_INSTRUCTION_TURN" = "Întoarceți-vă."; +"TIMED_WALK_INSTRUCTION_2" = "Mergeți înapoi la locul de pornire."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Apăsați “Înainte” când terminați."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Testul PAVSAT (testul auditiv pe etape de adunare în serie) măsoară aptitudinile dvs. de calcul și viteza de procesare a informațiilor auditive."; +"PVSAT_INTRO_TEXT" = "Testul PAVSAT (testul vizual pe etape de adunare în serie) măsoară aptitudinile dvs. de calcul și viteza de procesare a informațiilor vizuale."; +"PAVSAT_INTRO_TEXT" = "Testul PAVSAT (testul auditiv și vizual pe etape de adunare în serie) măsoară aptitudinile dvs. de calcul și viteza de procesare a informațiilor auditive și vizuale."; +"PSAT_INTRO_TEXT_2_%@" = "Cifrele apar la fiecare %@.\nTrebuie să adunați fiecare cifră nouă cu cea imediat precedentă.\nAtenție, nu trebuie să calculați suma totală, ci doar suma ultimelor două cifre."; +"PSAT_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"PSAT_INITIAL_INSTRUCTION" = "Rețineți această primă cifră."; +"PSAT_INSTRUCTION" = "Adăugați această nouă cifră la cea anterioară."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Testul cu %@ cercuri"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Această activitate vă măsoară funcționalitatea extremităților superioare, solicitându‑vă să plasați un cerc într‑un orificiu. Va trebui să repetați acțiunea de %@ ori."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Va fi testată atât mâna stângă, cât și mâna dreaptă.\nTrebuie să ridicați cercul cât mai rapid posibil, să-l plasați în orificiu și, după ce repetați acțiunea de %@ ori, să-l scoateți din nou de %@ ori."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Va fi testată atât mâna dreaptă, cât și mâna stângă.\nTrebuie să ridicați cercul cât mai rapid posibil, să-l plasați în orificiu și, după ce repetați acțiunea de %@ ori, să-l scoateți din nou de %@ ori."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Puneți cercul în orificiu folosind mâna stângă."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Puneți cercul în orificiu folosind mâna dreaptă."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Puneți cercul după linie folosind mâna stângă."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Puneți cercul după linie folosind mâna dreaptă."; +"HOLE_PEG_TEST_TEXT" = "Ridicați cercul folosind două degete."; +"HOLE_PEG_TEST_TEXT_2" = "Ridicați degetele pentru a elibera cercul."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Activitate referitoare la tremor"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Această activitate vă măsoară tremorul mâinilor în diverse poziții. Găsiți un loc unde să puteți sta confortabil pe durata activității."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Țineți telefonul în mâna mai afectată, ca în imaginea de mai jos."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Țineți telefonul în mâna DREAPTĂ, ca în imaginea de mai jos."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Țineți telefonul în mâna STÂNGĂ, ca în imaginea de mai jos."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Vi se va solicita să efectuați %@ stând cu telefonul în mână."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "o sarcină"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "două sarcini"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "trei sarcini"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "patru sarcini"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "cinci sarcini"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Apăsați “Înainte” pentru a continua."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Pregătiți‑vă să țineți telefonul pe genunchi."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Pregătiți‑vă să țineți telefonul pe genunchi cu mâna STÂNGĂ."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Pregătiți‑vă să țineți telefonul pe genunchi cu mâna DREAPTĂ."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Continuați să țineți telefonul pe genunchi timp de %ld secunde."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Acum, țineți telefonul cu mâna întinsă la înălțimea umărului."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Acum, țineți telefonul cu mâna STÂNGĂ întinsă la înălțimea umărului."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Acum, țineți telefonul cu mâna DREAPTĂ întinsă la înălțimea umărului."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Continuați să țineți telefonul cu mâna întinsă timp de %ld secunde."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Acum, țineți telefonul la înălțimea umărului, cu cotul îndoit."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Acum, țineți telefonul cu mâna STÂNGĂ la înălțimea umărului, cu cotul îndoit."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Acum, țineți telefonul cu mâna DREAPTĂ la înălțimea umărului, cu cotul îndoit."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Continuați să țineți telefonul cu cotul îndoit timp de %ld secunde."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Acum, ținându‑vă cotul îndoit, atingeți‑vă nasul cu telefonul în mod repetat."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Acum, ținându‑vă telefonul în mâna STÂNGĂ cu cotul îndoit, atingeți‑vă nasul cu telefonul în mod repetat."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Acum, ținându‑vă telefonul în mâna DREAPTĂ cu cotul îndoit, atingeți‑vă nasul cu telefonul în mod repetat."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Continuați să vă atingeți nasul cu telefonul timp de %ld secunde."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Pregătiți‑vă să fluturați mâna, răsucind din încheietură."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Pregătiți‑vă să fluturați mâna STÂNGĂ, ținând telefonul în aceasta și răsucind din încheietură."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Pregătiți‑vă să fluturați mâna DREAPTĂ, ținând telefonul în aceasta și răsucind din încheietură."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Continuați să fluturați mâna timp de %ld secunde."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Acum, treceți telefonul în mâna STÂNGĂ și continuați cu sarcina următoare."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Acum, treceți telefonul în mâna DREAPTĂ și continuați cu sarcina următoare."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Continuați cu sarcina următoare."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Activitate finalizată."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Vi se va solicita să efectuați %@ stând mai întâi cu telefonul într‑o mână, apoi în cealaltă."; +"TREMOR_SKIP_LEFT_HAND" = "Nu pot efectua această activitate cu mâna STÂNGĂ."; +"TREMOR_SKIP_RIGHT_HAND" = "Nu pot efectua această activitate cu mâna DREAPTĂ."; +"TREMOR_SKIP_NEITHER" = "Pot efectua această activitate cu ambele mâini."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test de trasare a liniilor"; +"TRAILMAKING_INTENDED_USE" = "Această activitate vă evaluează atenția vizuală și comutarea între sarcini prin înregistrarea timpului necesar pentru a apăsa o serie de puncte în ordine."; +"TRAILMAKING_INTENDED_USE2_A" = "După numărătoarea inversă, apăsați punctele în ordine alternativă între numere și litere. Începeți prin apăsarea primului număr, ‘1’, apoi continuați cu numerele '2' – '3' – '4'… până când ajungeți la numărul ’7’."; +"TRAILMAKING_INTENDED_USE2_B" = "După numărătoarea inversă, apăsați punctele în ordine alternativă între numere și litere. Începeți prin apăsarea primului număr, ‘1’, apoi apăsați prima literă, 'A' și continuați cu '2' – 'B' – '3' – 'C'… până când ajungeți la numărul ’7’."; +"TRAILMAKING_INTRO_TEXT" = "Faceți acest lucru cât de rapid puteți fără să faceți greșeli. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Recunoaștere vocală"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Această activitate vă înregistrează vocea folosind microfonul din partea de jos a dispozitivului și o transformă în text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Apăsați “Start” pentru a începe."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Apăsați butonul pentru a începe înregistrarea înainte de a vorbi."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Porniți înregistrarea"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Opriți înregistrarea"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Editați transcrierea"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Editați textul transcrierii pentru a corecta eventualele interpretări greșite ale enunțării."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Transcrierea dvs. va apărea aici."; +"SPEECH_RECOGNITION_FAILED" = "Recunoașterea vocală a eșuat."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Recunoașterea vocală nu a putut fi inițializată."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Redare audio"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Oprire audio"; +"SPEECH_IN_NOISE_TITLE" = "Enunțare în zgomot"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Această activitate măsoară inteligibilitatea vorbirii atunci când are loc în medii cu zgomot."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "În cadrul acestui test, veți:\n\nAsculta o propoziție.\n\nRepeta în mod clar ce ați auzit sau veți face un salt înainte pentru a tasta ce ați auzit folosind tastatura.\n\nDacă repetați ce ați auzit, veți avea opțiunea de a modifica transcrierea generată de motorul de recunoaștere vocală."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Calibrare volum"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Apăsați “Redare audio”, ajustați volumul la un nivel confortabil și apoi apăsați “Oprire audio” pentru a continua."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Ascultați"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Va fi redată o singură dată o propoziție combinată cu zgomot de fundal la un raport semnal/zgomot (SNR) randomizat."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Vorbiți"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Repetați ce ați auzit."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Fișierul nu a putut fi creat"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nu au putut fi eliminate suficiente fișiere jurnal pentru atingerea pragului admis"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Eroare la definirea atributului"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Fișierul nu a fost marcat drept șters (nu a fost marcat drept încărcat)"; +"ERROR_DATALOGGER_MULTIPLE" = "Mai multe erori la eliminarea jurnalelor"; +"ERROR_RECORDER_NO_DATA" = "Nu au fost găsite date colectate."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Nu a fost specificat un director de ieșire"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Contor nivel de presiune sonoră"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Această activitate măsoară nivelul presiunii sonore din mediu. Dacă nivelul zgomotului este prea mare, nu veți putea continua. Mergeți într-un loc mai liniștit pentru a termina această sarcină sau reluați ulterior această activitate."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Calculare"; +"ENVIRONMENTSPL_THRESHOLD" = "Prag: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Zgomot de fundal OK"; +"ENVIRONMENTSPL_NOISE" = "Zgomot de fundal excesiv"; +"ENVIRONMENTSPL_TITLE_2" = "Găsiți un loc liniștit"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Pentru asigurarea preciziei, acest test trebuie efectuat într‑un loc liniștit."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Începeți sarcina"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Nu există date"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Deplasați glisorul pentru a introduce o valoare"; +"SLIDER_I_DONT_KNOW" = "Nu știu"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Pagina"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Înapoi"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Afișați miniatura PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ascundeți miniatura PDF"; +"AX_BUTTON_ANNOTATE" = "Adnotare"; +"AX_BUTTON_SHOW_SEARCH" = "Afișați bara de căutare"; +"AX_BUTTON_HIDE_SEARCH" = "Ascundeți bara de căutare"; +"AX_BUTTON_SHARE" = "Partajați"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustrație a unei bife într-un cerc albastru însemnând succes"; + +"AX_SIGNVIEW_LABEL" = "Câmp de semnătură desemnat"; +"AX_SIGNVIEW_HINT" = "Atingeți ecranul și deplasați-vă degetul pentru a semna"; +"AX_SIGNVIEW_SIGNED" = "Semnat"; +"AX_SIGNVIEW_UNSIGNED" = "Nesemnat"; + +"AX_SELECTED" = "Selectat"; +"AX_UNSELECTED" = "Neselectat"; +"AX_SELECT_ALL_THAT_APPLY" = "SELECTAȚI TOATE OPȚIUNILE APLICABILE"; + +"AX_SLIDER_LABEL" = "Glisor de răspuns. Variază de la %@ la %@"; +"AX_UNLABELED_IMAGE" = "Imagine neetichetată"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Începeți sarcina"; + +"AX.MEMORY.TILE.ACTIVE" = "activ"; +"AX.MEMORY.TILE.CORRECT" = "corect"; +"AX.MEMORY.TILE.INCORRECT" = "incorect"; +"AX.MEMORY.TILE.QUIESCENT" = "pasiv"; +"AX.MEMORY.TILE.LABEL" = "Piesă joc memorie"; + +"AX_IMAGE_CAPTURE_LABEL" = "Previzualizare captură"; +"AX_IMAGE_CAPTURED_LABEL" = "Imagine capturată"; + +"AX_VIDEO_CAPTURE_LABEL" = "Previzualizare captură video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Captură video completă"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Nu se poate plasa un disc de mărimea %@ pe un disc de mărimea %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Țintă"; +"AX_TOWER_OF_HANOI_TOWER" = "Turn"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Apăsați dublu pentru a plasa discul"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Apăsați dublu pentru a selecta discul cel mai de sus"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Are disc de mărime %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Gol"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Închideți tastatura"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Interval de la %@ la %@"; +"AX_GRAPH_STACK_PREFIX" = "Stiva compusă din"; +"AX_GRAPH_AND_SEPARATOR" = " și "; +"AX_GRAPH_POINT_%@" = "Punctul: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Formă de undă enunțare"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Când începe înregistrarea, activați din nou pentru a opri înregistrarea."; + +"AX_AUDIO_BAR_GRAPH" = "Grafic bară audio"; + +"AX_AMSLER_GRID_LABEL" = "Grilă Amsler"; +"AX_AMSLER_GRID_HINT" = "Utilizați degetul sau un stilou pentru a marca grila direct sau glisați spre stânga în exteriorul grilei pentru a termina."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Butoane pe care puteți apăsa"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Apăsați pentru urechea stângă"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Activați pentru a începe testul. Când începe testul, apăsați direct pe acest buton atunci când auziți un sunet în urechea stângă."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Apăsați pentru urechea dreaptă"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Activați pentru a începe testul. Când începe testul, apăsați direct pe acest buton atunci când auziți un sunet în urechea dreaptă."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Folosind VoiceOver, explorați tactil ecranul pentru a afla unde se află butoanele pentru fiecare ureche. Când începe testul, veți putea apăsa direct pe butoane. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Apăsați pentru un deget"; +"AX_TAP_BUTTON_2_LABEL" = "Apăsați pentru alt deget"; +"AX_TAP_BUTTON_HINT" = "Activați pentru a putea apăsa direct pe butoane."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Folosind VoiceOver, explorați tactil ecranul pentru a afla unde se află butoanele. Activați oricare dintre butoane pentru a putea să le apăsați direct."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Acum puteți apăsa direct pe butoane."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Folosind VoiceOver, veți putea apăsa direct pe buton. Acesta va fi amplasat aproape de centrul ecranului."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Folosind VoiceOver, veți putea apăsa direct pe butoanele din test."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Datele restoreData nu pot fi decodate pentru inițializare"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7ec9c3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ro.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d eroare) + other + (%d de erori) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.strings new file mode 100755 index 0000000..dc36e7e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Согласие"; +"CONSENT_NAME_GIVEN" = "Имя"; +"CONSENT_NAME_FAMILY" = "Фамилия"; +"CONSENT_NAME_PLACEHOLDER" = "Обязательно"; +"CONSENT_REVIEW_TITLE" = "Проверка"; +"CONSENT_REVIEW_INSTRUCTION" = "Проверьте приведенную ниже форму и коснитесь «Принимаю», если Вы готовы продолжить."; +"CONSENT_REVIEW_ALERT_TITLE" = "Проверка"; +"CONSENT_SIGNATURE_TITLE" = "Подпись"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Распишитесь пальцем в поле ниже."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Место для подписи"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Стр. %1$ld из %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Добро пожаловать!"; +"CONSENT_SECTION_DATA_GATHERING" = "Сбор данных"; +"CONSENT_SECTION_PRIVACY" = "Личные данные"; +"CONSENT_SECTION_DATA_USE" = "Использование данных"; +"CONSENT_SECTION_STUDY_SURVEY" = "Опрос"; +"CONSENT_SECTION_STUDY_TASKS" = "Задачи"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Соглашение о времени"; +"CONSENT_SECTION_WITHDRAWING" = "Отказ от участия"; +"CONSENT_LEARN_MORE_TITLE" = "Подробнее"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Подробнее о сборе данных"; +"LEARN_MORE_DATA_USE" = "Подробнее об использовании данных"; +"LEARN_MORE_PRIVACY" = "Подробнее о конфиденциальности и защите личной информации"; +"LEARN_MORE_WELCOME" = "Подробнее об исследовании"; +"LEARN_MORE_STUDY_SURVEY" = "Подробнее об опросе"; +"LEARN_MORE_TIME_COMMITMENT" = "Подробнее о том, сколько времени занимает исследование"; +"LEARN_MORE_TASKS" = "Подробнее о задачах, включенных в исследование"; +"LEARN_MORE_WITHDRAWING" = "Подробнее об отказе от участия"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Параметры предоставления данных"; +"CONSENT_SHARE_WIDELY_%@" = "Предоставлять мои данные %@ и мировому научному сообществу."; +"CONSENT_SHARE_ONLY_%@" = "Предоставлять мои данные только %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ получат данные о Вашем участии в этом исследовании.\n\nПредоставление этих данных (без Вашей личной информации) научному сообществу может помочь этому и будущим исследованиям."; +"LEARN_MORE_CONSENT_SHARING" = "Подробнее о предоставлении данных"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Имя и фамилия печатными буквами"; +"CONSENT_DOC_LINE_SIGNATURE" = "Подпись"; +"CONSENT_DOC_LINE_DATE" = "Дата"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ из %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Вопрос %1$@ из %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Пропущено"; +"REVIEW_EDIT_ANSWER" = "Изменить"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Недопустимое значение"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ превышает максимально допустимое значение (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ меньше минимально допустимого значения (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "Недопустимое значение: %@."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Недействительный адрес e-mail: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Введите адрес"; +"LOCATION_ERROR_TITLE" = "Указанный адрес не найден"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Не удается устранить проблему с текущей геопозицией. Введите адрес или переместитесь в геопозицию с лучшим GPS‑сигналом, если возможно."; +"LOCATION_ERROR_MESSAGE_DENIED" = "В доступе к службам геолокации отказано. Разрешите этой программе использовать службы геолокации в Настройках."; +"LOCATION_ERROR_GEOCODE" = "Не удается найти результат по введенному адресу. Убедитесь, что адрес действителен."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Вы не подключены к Интернету или превысили максимальное количество запросов на поиск адресов. Если Вы не подключены к Интернету, включите Wi‑Fi, чтобы ответить на это вопрос; пропустите этот вопрос, если кнопка «Пропустить» доступна; или вернитесь к опросу после подключения к Интернету. В противном случае, повторите попытку через несколько минут."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Превышены максимальная длина текста: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Камера недоступна в разделенном экране."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Е‑mail"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Пароль"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Введите пароль"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Подтверждение"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Введите пароль снова"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Пароли не совпадают."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Дополнительная информация"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Иван"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Арсентьев"; +"GENDER_FORM_ITEM_TITLE" = "Пол"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Выберите пол"; +"DOB_FORM_ITEM_TITLE" = "Дата рождения"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Выберите дату"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Номер телефона"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Проверка"; +"VERIFICATION_STEP_TITLE" = "Проверка e‑mail"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Нажмите ссылку ниже, если Вы не получили e‑mail с подтверждением и хотите, чтобы он был отправлен повторно."; +"RESEND_EMAIL_BUTTON_TITLE" = "Повторно отправить e‑mail"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Вход"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Забыли пароль?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Введите код‑пароль"; +"PASSCODE_CONFIRM_MESSAGE" = "Подтвердите код‑пароль"; +"PASSCODE_SAVED_MESSAGE" = "Код‑пароль сохранен"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Код‑пароль аутентифицирован"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Введите старый код‑пароль"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Введите новый код‑пароль"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Подтвердите новый код-пароль"; +"PASSCODE_INVALID_ALERT_TITLE" = "Неверный код‑пароль"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Код‑пароли не совпали. Повторите попытку."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Выполните аутентификацию с Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Ошибка Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Можно использовать только цифры."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Индикатор хода ввода код‑пароля"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Введено цифр: %@ из %@"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Забыли код‑пароль?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Не удалось добавить объект связки ключей."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Не удалось обновить объект связки ключей."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Не удалось удалить объект связки ключей."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Не удалось найти объект связки ключей."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A(II)Rh+"; +"BLOOD_TYPE_A-" = "A(II)Rh‑"; +"BLOOD_TYPE_AB+" = "AB(IV)Rh+"; +"BLOOD_TYPE_AB-" = "AB(IV)Rh‑"; +"BLOOD_TYPE_B+" = "B(III)Rh+"; +"BLOOD_TYPE_B-" = "B(III)Rh‑"; +"BLOOD_TYPE_O+" = "0(I)Rh+"; +"BLOOD_TYPE_O-" = "0(I)Rh‑"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Тип I"; +"FITZPATRICK_SKIN_TYPE_II" = "Тип II"; +"FITZPATRICK_SKIN_TYPE_III" = "Тип III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Тип IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Тип V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Тип VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Женский"; +"GENDER_MALE" = "Мужской"; +"GENDER_OTHER" = "Другой"; + +/* Boolean answer strings */ +"BOOL_NO" = "Нет"; +"BOOL_YES" = "Да"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "см"; +"MEASURING_UNIT_FT" = "фт"; +"MEASURING_UNIT_IN" = "дюйм."; +"MEASURING_UNIT_KG" = "кг"; +"MEASURING_UNIT_LB" = "фнт"; +"MEASURING_UNIT_OZ" = "унц"; + +/* Limb values. */ +"LIMB_LEFT" = "левая"; +"LIMB_RIGHT" = "правая"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Коснитесь, чтобы ответить"; +"NULL_ANSWER" = "Выберите ответ"; +"PLACEHOLDER_IMAGE_CHOICES" = "Коснитесь, чтобы выбрать"; +"PLACEHOLDER_LONG_TEXT" = "Коснитесь, чтобы написать"; + +/* Button titles */ +"BUTTON_AGREE" = "Принимаю"; +"BUTTON_CANCEL" = "Отменить"; +"BUTTON_OK" = "ОК"; +"BUTTON_CLEAR" = "Очистить"; +"BUTTON_CLEAR_SIGNATURE" = "Очистить подпись"; +"BUTTON_APPLY" = "Применить"; +"BUTTON_DISAGREE" = "Не принимаю"; +"BUTTON_DONE" = "Готово"; +"BUTTON_GET_STARTED" = "Начать"; +"BUTTON_LEARN_MORE" = "Подробнее"; +"BUTTON_NEXT" = "Далее"; +"BUTTON_SKIP" = "Пропустить"; +"BUTTON_SKIP_QUESTION" = "Пропустить этот вопрос"; +"BUTTON_START_TIMER" = "Запустить таймер"; +"BUTTON_OPTION_SAVE" = "Сохранить на потом"; +"BUTTON_OPTION_DISCARD" = "Сбросить результаты"; +"BUTTON_OPTION_STOP_TASK" = "Завершить"; +"BUTTON_SAVE" = "Сохранить"; +"BUTTON_CLEAR_ANSWER" = "Очистить ответ"; +"BUTTON_READ_ONLY_MODE" = "Этот ответ нельзя изменить."; +"BUTTON_COPYRIGHT" = "Авторские права"; +"BUTTON_CLOSE" = "Закрыть"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Задание начинается через"; +"TASK_COMPLETE_TITLE" = "Задание выполнено"; +"TASK_COMPLETE_TEXT" = "Данные будут проанализированы. Вы получите уведомление, когда результаты будут готовы."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Осталось %@."; +"TOUCH_ANYWHERE_LABEL" = "Коснитесь экрана в любом месте, чтобы продолжить"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Захват изображения"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Повторный захват изображения"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Камера не найдена. Невозможно завершить этот шаг."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Для выполнения этого шага необходимо в Настройках разрешить этой программе доступ к камере."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Не указана папка для сохранения полученных изображений."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Не удается сохранить полученное изображение."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Начать запись"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Остановить запись"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Снять видео еще раз"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Выносливость"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Расстояние (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Пульс (уд/мин)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Сядьте поудобнее и сидите %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Идите %@ с максимальной скоростью."; +"FITNESS_INTRO_TEXT_FORMAT" = "Во время выполнения этого задания программа следит за частотой Вашего пульса и измеряет расстояние, которое Вы пройдете за %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Пройдите %1$@ по улице с максимальной скоростью. После этого удобно сядьте и отдыхайте %2$@. Коснитесь «Начать», чтобы приступить."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Координация"; +"WALK_INTRO_TEXT" = "Во время выполнения этого задания оценивается координация движений при ходьбе и в положении стоя. Не выполняйте это задание, если Вы не можете передвигаться без посторонней помощи."; +"WALK_INTRO_2_TEXT_%ld" = "Найдите место, где Вы можете безопасно пройти %ld шагов по прямой линии без посторонней помощи."; +"WALK_INTRO_2_DETAIL" = "Поместите устройство в карман или сумку и следуйте звуковым указаниям."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Теперь стойте спокойно %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Стойте спокойно %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Развернитесь и пройдите на исходное место."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Пройдите прямо %ld шагов."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Найдите место, где бы Вы могли ходить по прямой линии вперед и назад. Постарайтесь идти не останавливаясь. Разворачивайтесь в конце пути так, будто обходите острый угол.\n\nЗатем Вы получите указание развернуться на 360 градусов и просто стоять, опустив руки вдоль тела и расставив ноги на ширине плеч."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Коснитесь «Начать», когда будете готовы приступить к выполнению задания.\nЗатем положите устройство в карман или сумку и следуйте звуковым указаниям."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Походите по прямой вперед и назад в течение %@. Идите нормальной походкой."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Развернитесь на 360 градусов и стойте спокойно %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Вы выполнили задание."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Скорость касания"; +"TAPPING_TASK_TITLE_RIGHT" = "Правая рука"; +"TAPPING_TASK_TITLE_LEFT" = "Левая рука"; +"TAPPING_INTRO_TEXT" = "Во время выполнения этого задания оценивается скорость касания пальцами."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Положите устройство на ровную поверхность."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Двумя пальцами одной руки попеременно касайтесь появляющихся кнопок на экране."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Двумя пальцами правой руки попеременно касайтесь появляющихся кнопок на экране."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Двумя пальцами левой руки попеременно касайтесь появляющихся кнопок на экране."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Теперь повторите это упражнение правой рукой."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Теперь повторите это упражнение левой рукой."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Коснитесь одним пальцем, затем другим. Старайтесь, чтобы касания были максимально регулярными. Продолжайте в течение %@."; +"TAPPING_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Чтобы начать, коснитесь «Далее»."; +"TAP_BUTTON_TITLE" = "Коснитесь"; +"TOTAL_TAPS_LABEL" = "Всего касаний"; +"TAPPING_INSTRUCTION" = "Касайтесь кнопок двумя пальцами с одинаковой скоростью."; +"TAPPING_INSTRUCTION_RIGHT" = "Касайтесь кнопок пальцами ПРАВОЙ руки."; +"TAPPING_INSTRUCTION_LEFT" = "Касайтесь кнопок пальцами ЛЕВОЙ руки."; +"TAPPING_SKIP_TITLE" = "Пропустить эту руку"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Сетка Амслера"; +"AMSLER_GRID_INTRO_TEXT" = "Это задание позволяет установить наличие проблем со зрением."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Во время теста держите устройство на уровне глаз и в 30 сантиметрах от лица."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Закройте %@ и смотрите на точку в центре сетки.\n\nИспользуя стилус или палец, отметьте любые дефекты сетки, которые заметите, например, волны или искривления линий сетки.\n\nКогда будете готовы, смахните влево в любом месте, где нет сетки."; +"AMSLER_GRID_LEFT_EYE" = "левый глаз"; +"AMSLER_GRID_RIGHT_EYE" = "правый глаз"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Голос"; +"AUDIO_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"AUDIO_INSTRUCTION" = "Произносите «Ааааа» в микрофон как можно дольше."; +"AUDIO_INTRO_TEXT" = "Сделайте глубокий вдох и произнесите «Ааааа» в микрофон как можно дольше. Сохраняйте такую громкость голоса, чтобы полоски звука на диаграмме оставались синими."; +"AUDIO_INTENDED_USE" = "Во время выполнения этого задания оцениваются характеристики Вашего голоса, который записывается микрофоном, расположенным в нижней части устройства."; +"AUDIO_TOO_LOUD_LABEL" = "Слишком громко"; +"AUDIO_GENERIC_ERROR_LABEL" = "Не удается записать аудио."; +"AUDIO_LEVEL_CHECK_LABEL" = "Подождите, пока устройство измерит уровень фонового шума."; +"AUDIO_TOO_LOUD_MESSAGE" = "Уровень фонового шума слишком большой и не позволяет записать Ваш голос. Найдите более тихое место и повторите попытку."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Коснитесь «Далее», когда будете готовы."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Аудиометрия"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Во время выполнения этого задания оценивается способность слышать различные звуки."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Сначала подключите наушники к устройству, а затем наденьте их.\n\nЗвук будет очень слабым, не похожим на обычный сигнал предупреждения.  Сначала звук будет тихим, а затем громкость будет постепенно нарастать.  Сосредоточьтесь и касайтесь левой или правой кнопки в зависимости от того, каким ухом Вы слышите сигнал."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Сейчас Вы должны слышать сигнал. Отрегулируйте громкость при помощи боковых кнопок устройства.\n\nКоснитесь любой кнопки, когда будете готовы начать."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Каждый раз, когда слышите звук, определяйте, каким ухом Вы слышите его, и с учетом этого касайтесь левой или правой кнопки."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Левое ухо"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Правое ухо"; +"TONE_LABEL_%@_LEFT" = "%@ Гц, левый"; +"TONE_LABEL_%@_RIGHT" = "%@ Гц, правый"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Аудиометрия"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Касайтесь, когда услышите звук."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Звук и громкость"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Вы услышите последовательность звуков."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Нажимайте кнопку, когда услышите звук."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Для этого теста громкость будет установлена на 50 процентов."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Этот тест займет около 10 минут."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Включите режим «Не беспокоить», чтобы не прерываться."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Звуки сначала будут воспроизводиться для правого уха."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Звуки теперь будут воспроизводиться для левого уха."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Это задание позволяет определить порог слышимости (ПС) по шкале дБ ПС."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Убедитесь, что установлена максимальная громкость устройства.\n\nВо время выполнения задания Вы услышите слабый звук с правой или левой стороны.\n\nСлушайте внимательно и касайтесь кнопки каждый раз, когда слышите звук."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Этот тест определяет, насколько громким должен быть звук, чтобы Вы могли его услышать."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Вводный опрос."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Каким ухом Вы слышите лучше? (Если замечаете разницу)"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "левым"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "правым"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "не замечаю разницы"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Тест отменен"; +"dBHL_ALERT_TITLE_START_OVER" = "Начать снова"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Отменить тест"; +"dBHL_ALERT_TEXT" = "Чтобы пройти тест, переподключите свои наушники AirPods или EarPods."; +"dBHL_PROGRESS_COMPLETION_%@" = "Выполнено %@"; + +/* Headphones. */ +"AIRPODS" = "Наушники AirPods"; +"EARPODS" = "Наушники EarPods"; +"HEADPHONES" = "Наушники"; +"HEADPHONES_UNKNOWN" = "Неизвестно"; +"HEADPHONES_NONE" = "Нет"; +"CONNECTED" = "Подключены"; +"NOT_CONNECTED" = "Не подключены"; +"HEADPHONE_CONNECTED_%@" = "Подключено — %@"; +"HEADPHONE_DETECT_TITLE" = "Подключите наушники"; +"HEADPHONE_DETECT_TEXT" = "Для этого теста нужны наушники Apple AirPods или Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Пространственная память"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Во время выполнения этого задания оцениваются возможности Вашей кратковременной пространственной памяти. Программа попросит Вас повторить последовательность, в которой подсвечиваются %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "цветов"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "цветов"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Некоторые из %@ будут подсвечиваться поочередно в определенном порядке. Касайтесь %@ в том же порядке."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Некоторые из %@ будут подсвечиваться поочередно в определенном порядке. Касайтесь %@ в обратном порядке."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать» и внимательно смотрите на экран."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Счет"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Следите за тем, как подсвечиваются %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Коснитесь изображений (%@) в том порядке, в котором они подсвечивались"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Коснитесь изображений (%@) в обратном порядке"; +"MEMORY_GAME_COMPLETE_TITLE" = "Задание выполнено"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Нажмите «Далее», чтобы продолжить"; +"MEMORY_GAME_FAILED_TITLE" = "Повторить"; +"MEMORY_GAME_FAILED_MESSAGE" = "В этот раз Вы не совсем справились с заданием. Коснитесь «Далее», чтобы продолжить."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Время истекло"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Время истекло.\nНажмите «Далее», чтобы продолжить."; +"MEMORY_GAME_COMPLETE" = "Игра завершена"; +"MEMORY_GAME_PAUSED_TITLE" = "Пауза"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Нажмите «Далее», чтобы продолжить"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Задание для оценки памяти было подготовлено при участии доктора философских наук Кэтрин Поссин и доктора философских наук Джоэла Крамера из Калифорнийского университета в Сан-Франциско."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Время реакции"; +"REACTION_TIME_TASK_INTENDED_USE" = "Во время выполнения этого задания измеряется время реакции на визуальный сигнал."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Как только на экране появится синяя точка, встряхните устройство в любом направлении. Количество повторений этого задания: %D."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Попытка %@ из %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "При появлении синего круга быстро встряхните устройство"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Тест Струпа"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Каждый раз, когда появляется слово, выбирайте первую букву названия ЦВЕТА, который Вы видите на экране."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Когда будете готовы приступить к тесту Струпа, коснитесь «Начать»."; +"STROOP_TASK_STEP_TEXT" = "Выберите первую букву названия того ЦВЕТА, который видите на экране."; +"STROOP_COLOR_RED" = "КРАСНЫЙ"; +"STROOP_COLOR_GREEN" = "ЗЕЛЕНЫЙ"; +"STROOP_COLOR_BLUE" = "СИНИЙ"; +"STROOP_COLOR_YELLOW" = "ЖЕЛТЫЙ"; +"STROOP_COLOR_RED_INITIAL" = "К"; +"STROOP_COLOR_GREEN_INITIAL" = "З"; +"STROOP_COLOR_BLUE_INITIAL" = "С"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ж"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Ханойская башня"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Во время выполнения этого задания проверяется способность решать головоломки."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Переместите всю стопку на отмеченное цветом место за наименьшее число ходов."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Решить задачу"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Число ходов: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Я не могу решить эту задачу"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Подвижность"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Необходимо указать, оценка какой конечности выполняется — левой или правой"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Амплитуда движений левого коленного сустава"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Амплитуда движений правого коленного сустава"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Во время выполнения этого задания оценивается подвижность левого коленного сустава."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Во время выполнения этого задания оценивается подвижность правого коленного сустава."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Сядьте на край стула. Сперва положите устройство на левую ногу, ближе к колену: это необходимо для оценивания. Включите звук на устройстве для прослушивания инструкций."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Сядьте на край стула. Сперва положите устройство на правую ногу, ближе к колену: это необходимо для оценивания. Включите звук на устройстве для прослушивания инструкций."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Положите устройство экраном вверх на левую ногу, ближе к колену, как показано на картинке."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Положите устройство экраном вверх на правую ногу, ближе к колену, как показано на картинке."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Когда будете готовы, коснитесь экрана, чтобы начать, и максимально разогните левое колено. Вернитесь в начальное положение и коснитесь экрана снова, когда будете готовы."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Когда будете готовы, коснитесь экрана, чтобы начать, и максимально разогните правое колено. Вернитесь в начальное положение и коснитесь экрана снова, когда будете готовы."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Положите устройство на левое колено. Коснитесь экрана и максимально разогните левое колено."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Положите устройство на правое колено. Коснитесь экрана и максимально разогните правое колено."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Когда будете готовы, верните левое колено в начальное положение. Затем коснитесь экрана."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Когда будете готовы, верните правое колено в начальное положение. Затем коснитесь экрана."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Амплитуда движений левого плечевого сустава"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Амплитуда движений правого плечевого сустава"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Во время выполнения этого задания оценивается подвижность левого плечевого сустава."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Во время выполнения этого задания оценивается подвижность правого плечевого сустава."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Сперва положите устройство на левое надплечье, ближе к плечу: это необходимо для оценивания. Включите звук на устройстве для прослушивания инструкций."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Сперва положите устройство на правое надплечье, ближе к плечу: это необходимо для оценивания. Включите звук на устройстве для прослушивания инструкций."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Положите устройство экраном вверх на левое плечо, как показано на картинке."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Положите устройство экраном вверх на правое плечо, как показано на картинке."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Когда будете готовы, коснитесь экрана, чтобы начать, и поднимите левую руку как можно выше. Вернитесь в начальное положение и коснитесь экрана снова, когда будете готовы."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Когда будете готовы, коснитесь экрана, чтобы начать, и поднимите правую руку как можно выше. Вернитесь в начальное положение и коснитесь экрана снова, когда будете готовы."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Положите устройство на левое плечо. Коснитесь экрана и поднимите левую руку как можно выше."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Положите устройство на правое плечо. Коснитесь экрана и поднимите правую руку как можно выше."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Когда будете готовы, верните левую руку в начальное положение. Затем коснитесь экрана."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Когда будете готовы, верните правую руку в начальное положение. Затем коснитесь экрана."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Ходьба на время"; +"TIMED_WALK_INTRO_DETAIL" = "Во время выполнения этого задания оценивается работоспособность нижних конечностей."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Найдите место, предпочтительно на улице, где Вы смогли бы безопасно идти %@ по прямой линии с максимальной скоростью. Не замедляйте шаг, пока не дойдете до финиша."; +"TIMED_WALK_INTRO_2_DETAIL" = "Чтобы начать, коснитесь «Далее»."; +"TIMED_WALK_FORM_TITLE" = "Вспомогательные приспособления"; +"TIMED_WALK_FORM_TEXT" = "Используйте одно и тоже вспомогательное приспособление для всех упражнений."; +"TIMED_WALK_QUESTION_TEXT" = "Вы носите голеностопный ортез?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Вы пользуетесь вспомогательными приспособлениями?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Коснитесь, чтобы выбрать ответ."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Нет"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Одна трость"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Один костыль"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Трости"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Костыли"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Ходунки/ролятор"; +"TIMED_WALK_INSTRUCTION_%@" = "Пройдите прямо %@."; +"TIMED_WALK_INSTRUCTION_TURN" = "Развернитесь."; +"TIMED_WALK_INSTRUCTION_2" = "Вернитесь на исходное место."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Коснитесь «Далее» после завершения."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "В слуховом тесте на сложение с заданным темпом измеряются способность обрабатывать аудиальную информацию, а также способность к вычислениям."; +"PVSAT_INTRO_TEXT" = "В визуальном тесте на сложение с заданным темпом измеряются способность обрабатывать визуальную информацию, а также способность к вычислениям."; +"PAVSAT_INTRO_TEXT" = "В слуховом и визуальном тестах на сложение с заданным темпом измеряются способности обрабатывать аудиальную и визуальную информацию, а также способность к вычислениям."; +"PSAT_INTRO_TEXT_2_%@" = "С частотой в %@ будет появляться однозначное число.\nПрибавляйте каждое новое число к предыдущему.\nВнимание! Вычислять общую сумму не нужно — просто складывайте два последних числа."; +"PSAT_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"PSAT_INITIAL_INSTRUCTION" = "Запомните эту первую цифру."; +"PSAT_INSTRUCTION" = "Прибавьте это новое число к предыдущему."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Тест «Вставляем %@ колышков»"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Во время выполнения этого задания оценивается работоспособность верхних конечностей. Вам предложат поместить колышек в лунку %@ раз(а)."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Проверены будут обе руки: левая и правая.\nВам потребуется поднять колышек как можно быстрее, поместить его в лунку, а затем, повторив упражнение %@ раз(а), удалить его снова %@ раз(а)."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Проверены будут обе руки: правая и левая.\nВам потребуется поднять колышек как можно быстрее, поместить его в лунку, а затем, повторив упражнение %@ раз(а), удалить его снова %@ раз(а)."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Поместите колышек в лунку левой рукой."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Поместите колышек в лунку правой рукой."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Поместите колышек за линию левой рукой."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Поместите колышек за линию правой рукой."; +"HOLE_PEG_TEST_TEXT" = "Поднимите колышек двумя пальцами."; +"HOLE_PEG_TEST_TEXT_2" = "Приподнимите пальцы, чтобы бросить колышек."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Измерение дрожания рук"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Во время выполнения этого задания оценивается дрожание рук в различных положениях. Найдите удобное место, где бы Вы могли сидеть во время выполнения задания."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Держите телефон, как показано на изображении ниже, той рукой, дрожь которой сильнее."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Держите телефон ПРАВОЙ рукой, как показано на изображении ниже."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Держите телефон ЛЕВОЙ рукой, как показано на изображении ниже."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Вам нужно будет выполнить %@ в сидячем положении, держа телефон в руке."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "одно задание"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "два задания"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "три задания"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "четыре задания"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "пять заданий"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Коснитесь «Далее», чтобы продолжить."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Приготовьтесь держать телефон на коленях."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Приготовьтесь держать телефон на коленях в ЛЕВОЙ руке."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Приготовьтесь держать телефон на коленях в ПРАВОЙ руке."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Держите телефон на коленях в течение %ld с."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Теперь держите телефон в вытянутой руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Теперь держите телефон в вытянутой ЛЕВОЙ руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Теперь держите телефон в вытянутой ПРАВОЙ руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Удерживайте телефон в вытянутой руке в течение %ld с."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Теперь держите телефон в согнутой в локте руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Теперь держите телефон в согнутой в локте ЛЕВОЙ руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Теперь держите телефон в согнутой в локте ПРАВОЙ руке на уровне плеч."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Удерживайте телефон в руке, согнутой в локте, в течение %ld с."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Теперь держите телефон в согнутой в локте руке и несколько раз коснитесь им своего носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Теперь держите телефон в согнутой в локте ЛЕВОЙ руке и несколько раз коснитесь им своего носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Теперь держите телефон в согнутой в локте ПРАВОЙ руке и несколько раз коснитесь им своего носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Касайтесь телефоном своего носа в течение %ld с."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Подготовьтесь выполнить махание рукой (сгибая руку в запястье)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Подготовьтесь выполнить махание ЛЕВОЙ рукой, держа в ней телефон (сгибая руку в запястье)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Подготовьтесь выполнить махание ПРАВОЙ рукой, держа в ней телефон (сгибая руку в запястье)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Продолжайте махать рукой в течение %ld с."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Теперь возьмите телефон ЛЕВОЙ рукой и перейдите к следующему заданию."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Теперь возьмите телефон ПРАВОЙ рукой и перейдите к следующему заданию."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Перейдите к следующему заданию."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Задание выполнено."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Вам нужно будет выполнить %@ в сидячем положении, держа телефон сначала в одной руке, затем в другой."; +"TREMOR_SKIP_LEFT_HAND" = "Я не могу выполнить это задание ЛЕВОЙ рукой."; +"TREMOR_SKIP_RIGHT_HAND" = "Я не могу выполнить это задание ПРАВОЙ рукой."; +"TREMOR_SKIP_NEITHER" = "Я могу выполнить это задание обеими руками."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Соедините точки"; +"TRAILMAKING_INTENDED_USE" = "Во время выполнения этого задания оцениваются зрительное сосредоточение и способность переключаться с одной задачи на другую. Основанием для оценки служит время, затраченное на то, чтобы коснуться всех точек по порядку."; +"TRAILMAKING_INTENDED_USE2_A" = "Когда закончится обратный отсчет, нужно будет попеременно касаться то цифр, то букв. Сначала коснитесь цифры 1, затем 2, 3, 4 и так далее, пока не дойдете до цифры 7."; +"TRAILMAKING_INTENDED_USE2_B" = "Когда закончится обратный отсчет, нужно будет попеременно касаться то цифр, то букв. Сначала коснитесь цифры 1, затем — буквы А, а потом — цифры 2, буквы Б, цифры 3, буквы В и так далее, пока не дойдете до цифры 7."; +"TRAILMAKING_INTRO_TEXT" = "Это нужно делать быстро, но правильно. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"TRAILMAKING_LETTER_A" = "А"; +"TRAILMAKING_LETTER_B" = "Б"; +"TRAILMAKING_LETTER_C" = "В"; +"TRAILMAKING_LETTER_D" = "Г"; +"TRAILMAKING_LETTER_E" = "Д"; +"TRAILMAKING_LETTER_F" = "Е"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Распознавание речи"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Во время выполнения этого задания Ваша речь записывается микрофоном, расположенным в нижней части устройства, и переводится в текст."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Чтобы приступить, коснитесь «Начать»."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Нажмите кнопку, чтобы начать запись до проговаривания."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Начать запись"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Остановить запись"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Правка"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Если Вы произносили не то, что написано в расшифровке, исправьте ее."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Расшифровка отобразится здесь."; +"SPEECH_RECOGNITION_FAILED" = "Не удалось выполнить распознавание речи."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Не удалось начать распознавание речи."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Воспроизвести аудио"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Остановить аудио"; +"SPEECH_IN_NOISE_TITLE" = "Проговаривание на фоне шума"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Во время выполнения этого задания оценивается четкость и ясность речи в шумном окружении."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Во время этого теста от Вас потребуется:\n\nПрослушать предложение.\n\nЧетко и ясно повторить то, что услышали, или пропустить эту часть и ввести услышанный текст с помощью клавиатуры. \n\nЕсли Вы произнесете то, что услышали, Вы сможете внести изменения в расшифровку, созданную системой распознавания речи."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Калибровка громкости"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Коснитесь «Воспроизвести аудио», отрегулируйте громкость до нужного уровня, а затем коснитесь «Остановить аудио», чтобы продолжить."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Прослушивание"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Предложение, записанное на фоне шума и с измененным отношением сигнала к шуму, будет воспроизведено один раз."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Проговаривание"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Повторите то, что услышали."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Не удалось создать файл"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Не удалось удалить файлы журналов, чтобы освободить достаточно места"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Ошибка при установке атрибута"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Файл не помечен как удаленный (выгруженный)"; +"ERROR_DATALOGGER_MULTIPLE" = "Несколько ошибок при удалении журналов"; +"ERROR_RECORDER_NO_DATA" = "Собранные данные не найдены."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Не указан каталог для выходных данных"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Шумомер"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Это задание направлено на измерение звукового давления окружающей среды. Если уровень шума слишком высокий, выполнить задание не удастся. Потребуется пройти в тихое место или выполнить это задание в другое время."; +"ENVIRONMENTSPL_UNIT" = "дБА"; +"ENVIRONMENTSPL_CALCULATING" = "Вычисление"; +"ENVIRONMENTSPL_THRESHOLD" = "Порог: %@ дБА"; +"ENVIRONMENTSPL_OK" = "Приемлемый уровень фонового шума"; +"ENVIRONMENTSPL_NOISE" = "Вокруг слишком шумно"; +"ENVIRONMENTSPL_TITLE_2" = "Найдите тихое место"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Для получения достоверного результата этот тест необходимо проводить в тихом месте."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Начать задание"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Нет данных"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Чтобы ввести значение, передвиньте бегунок."; +"SLIDER_I_DONT_KNOW" = "Я не знаю"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Страница"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Назад"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Показать миниатюру PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Скрыть миниатюру PDF"; +"AX_BUTTON_ANNOTATE" = "Добавить пометку"; +"AX_BUTTON_SHOW_SEARCH" = "Показать строку поиска"; +"AX_BUTTON_HIDE_SEARCH" = "Скрыть строку поиска"; +"AX_BUTTON_SHARE" = "Поделиться"; + + +"AX_COMPLETION_ILLUSTRATION" = "Обозначение в виде галочки в синем кружке, означающее успешное выполнение"; + +"AX_SIGNVIEW_LABEL" = "Место для подписи"; +"AX_SIGNVIEW_HINT" = "Прикоснитесь к экрану и проведите по нему пальцем, чтобы оставить подпись"; +"AX_SIGNVIEW_SIGNED" = "Подписано"; +"AX_SIGNVIEW_UNSIGNED" = "Не подписано"; + +"AX_SELECTED" = "Выбрано"; +"AX_UNSELECTED" = "Не выбрано"; +"AX_SELECT_ALL_THAT_APPLY" = "ВЫБЕРИТЕ ВСЕ ПОДХОДЯЩИЕ ВАРИАНТЫ"; + +"AX_SLIDER_LABEL" = "Бегунок ответа. Диапазон от %@ до %@"; +"AX_UNLABELED_IMAGE" = "Изображение без подписи"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Приступить"; + +"AX.MEMORY.TILE.ACTIVE" = "активно"; +"AX.MEMORY.TILE.CORRECT" = "верно"; +"AX.MEMORY.TILE.INCORRECT" = "неверно"; +"AX.MEMORY.TILE.QUIESCENT" = "неподвижно"; +"AX.MEMORY.TILE.LABEL" = "Игра на проверку памяти"; + +"AX_IMAGE_CAPTURE_LABEL" = "Просмотр изображения"; +"AX_IMAGE_CAPTURED_LABEL" = "Отснятое изображение"; + +"AX_VIDEO_CAPTURE_LABEL" = "Просмотр записанного видео"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Запись видео завершена"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Нельзя положить кольцо размера %@ на кольцо размера %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Цель"; +"AX_TOWER_OF_HANOI_TOWER" = "Башня"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Коснитесь дважды, чтобы положить кольцо"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Коснитесь дважды, чтобы выбрать самое верхнее кольцо"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Содержит кольцо размеров: %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Пусто"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Скрыть клавиатуру"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Диапазон от %@ до %@"; +"AX_GRAPH_STACK_PREFIX" = "Стопка из"; +"AX_GRAPH_AND_SEPARATOR" = " и "; +"AX_GRAPH_POINT_%@" = "Точка: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Речь в виде формы волны"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "После того как запись начнется, для ее остановки нажмите кнопку записи еще раз."; + +"AX_AUDIO_BAR_GRAPH" = "Столбчатый график звука"; + +"AX_AMSLER_GRID_LABEL" = "Сетка Амслера"; +"AX_AMSLER_GRID_HINT" = "Отметьте участки сетки стилусом или пальцем или смахните влево в любом месте, где нет сетки, чтобы закончить тест."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Поддержка касания для кнопок"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Коснитесь для левого уха"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Активируйте, чтобы начать тест. После запуска теста просто касайтесь этой кнопки, когда Вы слышите звук в левом наушнике."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Коснитесь для правого уха"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Активируйте, чтобы начать тест. После запуска теста просто касайтесь этой кнопки, когда Вы слышите звук в правом наушнике."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ При использовании VoiceOver исследуйте экран касаниями, чтобы запомнить, где расположены кнопки для каждого уха. После начала теста кнопок можно будет просто касаться. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Коснитесь для одного пальца"; +"AX_TAP_BUTTON_2_LABEL" = "Коснитесь для другого пальца"; +"AX_TAP_BUTTON_HINT" = "Активируйте, чтобы кнопок можно было просто касаться."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ При использовании VoiceOver исследуйте экран касаниями, чтобы запомнить, где расположены кнопки. Активируйте одну из кнопок, чтобы кнопок можно было просто касаться."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Теперь кнопок можно просто касаться."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ При использовании VoiceOver этой кнопки можно будет просто касаться. Она будет расположена в центре экрана."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ При использовании VoiceOver кнопок во время теста можно просто касаться."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Не удалось декодировать данные restoreData для инициализации"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..2cfaae0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/ru.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d ошибка) + other + (%d ошибки) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.strings new file mode 100755 index 0000000..4998ebf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Súhlas"; +"CONSENT_NAME_GIVEN" = "Meno"; +"CONSENT_NAME_FAMILY" = "Priezvisko"; +"CONSENT_NAME_PLACEHOLDER" = "Povinné"; +"CONSENT_REVIEW_TITLE" = "Revízia"; +"CONSENT_REVIEW_INSTRUCTION" = "Skontrolujte formulár nižšie, a ak ste pripravení pokračovať, klepnite na Súhlasím."; +"CONSENT_REVIEW_ALERT_TITLE" = "Skontrolovať"; +"CONSENT_SIGNATURE_TITLE" = "Podpis"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Pomocou prsta sa podpíšte do rámčeka nižšie."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Sem sa podpíšte"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Strana %1$ld z %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Vitajte"; +"CONSENT_SECTION_DATA_GATHERING" = "Zber dát"; +"CONSENT_SECTION_PRIVACY" = "Súkromie"; +"CONSENT_SECTION_DATA_USE" = "Využitie dát"; +"CONSENT_SECTION_STUDY_SURVEY" = "Študijný prieskum"; +"CONSENT_SECTION_STUDY_TASKS" = "Študijné úlohy"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Časová náročnosť"; +"CONSENT_SECTION_WITHDRAWING" = "Odstúpenie"; +"CONSENT_LEARN_MORE_TITLE" = "Viac informácií"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Viac informácií o zbere dát"; +"LEARN_MORE_DATA_USE" = "Viac informácií o využívaní dát"; +"LEARN_MORE_PRIVACY" = "Viac informácií o ochrane súkromia a identity"; +"LEARN_MORE_WELCOME" = "Viac informácií o štúdii"; +"LEARN_MORE_STUDY_SURVEY" = "Viac informácií o prieskume štúdie"; +"LEARN_MORE_TIME_COMMITMENT" = "Viac informácií o vplyve štúdie na váš čas"; +"LEARN_MORE_TASKS" = "Viac informácií o úlohách"; +"LEARN_MORE_WITHDRAWING" = "Viac informácií o odstúpení"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Možnosti zdieľania"; +"CONSENT_SHARE_WIDELY_%@" = "Zdieľať dáta s inštitúciou %@ a ďalšími kvalifikovanými výskumníkmi."; +"CONSENT_SHARE_ONLY_%@" = "Zdieľať dáta len s inštitúciou %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "Vaše dáta z účasti v tejto štúdii budú doručené inštitúcii %@.\n\nŠiršie zdieľanie zakódovaných dát štúdie (bez informácií, ako je vaše meno) môže byť užitočné pre tento a budúci výskum."; +"LEARN_MORE_CONSENT_SHARING" = "Viac informácií o zdieľaní dát"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Meno tlačeným písmom"; +"CONSENT_DOC_LINE_SIGNATURE" = "Podpis"; +"CONSENT_DOC_LINE_DATE" = "Dátum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ z %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Otázka %1$@ z %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Preskočená"; +"REVIEW_EDIT_ANSWER" = "Upraviť"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Neplatná hodnota"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ prekračuje maximálnu povolenú hodnotu (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ nedosahuje minimálnu povolenú hodnotu (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ nie je platná hodnota."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Neplatná emailová adresa: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Zadajte adresu"; +"LOCATION_ERROR_TITLE" = "Špecifikovaná adresa sa nenašla"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Nepodarilo sa identifikovať aktuálnu polohu. Zadajte adresu alebo prejdite na miesto s lepším signálom GPS."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Prístup k lokalizačným službám bol zamietnutý. Udeľte tejto aplikácii povolenie na používanie lokalizačných služieb v Nastaveniach."; +"LOCATION_ERROR_GEOCODE" = "Nenašiel sa žiadny výsledok zodpovedajúci zadanej adrese. Skontrolujte, či je adresa platná."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Buď nemáte pripojenie na internet, alebo ste prekročili maximálny počet žiadostí o vyhľadanie adresy. Ak nemáte pripojenie na internet a chcete odpovedať na túto otázku, zapnite Wi-Fi. Ak je dostupné tlačidlo Preskočiť, môžete otázku preskočiť, prípadne sa vrátiť späť po pripojení na internet. Ináč to skúste znovu o niekoľko minút."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Textový obsah prekračuje maximálnu dĺžku: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera nie je dostupná v režime rozdelenej obrazovky."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jankohrasko@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Heslo"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Zadajte heslo"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Potvrdiť"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Znovu zadajte heslo"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Heslá sa nezhodujú."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Ďalšie informácie"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Janko"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Hraško"; +"GENDER_FORM_ITEM_TITLE" = "Pohlavie"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Vyberte pohlavie"; +"DOB_FORM_ITEM_TITLE" = "Dátum narodenia"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Vyberte dátum"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefónne číslo"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Overenie"; +"VERIFICATION_STEP_TITLE" = "Overte svoj email"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Ak vám nebol doručený overovací email a chcete ho znovu odoslať, klepnite na odkaz nižšie."; +"RESEND_EMAIL_BUTTON_TITLE" = "Znovu odoslať overovací email"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Prihlásenie"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Zabudli ste heslo?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Zadajte kód"; +"PASSCODE_CONFIRM_MESSAGE" = "Potvrďte kód"; +"PASSCODE_SAVED_MESSAGE" = "Kód uložený"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Kód autentifikovaný"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Zadajte starý kód"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Zadajte nový kód"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Potvrďte nový kód"; +"PASSCODE_INVALID_ALERT_TITLE" = "Nesprávny kód"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Kódy sa nezhodujú. Skúste to znovu."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentifikujte sa pomocou Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Chyba Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Povolené sú len číselné znaky."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Indikátor priebehu zadávania kódu"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Zadané číslice: %@ z %@"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Zabudli ste kód?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Nepodarilo sa pridať položku kľúčenky."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Nepodarilo sa aktualizovať položku kľúčenky."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Nepodarilo sa vymazať položku kľúčenky."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Položka kľúčenky sa nenašla."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Typ I"; +"FITZPATRICK_SKIN_TYPE_II" = "Typ II"; +"FITZPATRICK_SKIN_TYPE_III" = "Typ III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Typ IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Typ V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Typ VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Žena"; +"GENDER_MALE" = "Muž"; +"GENDER_OTHER" = "Iné"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nie"; +"BOOL_YES" = "Áno"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "ľavá"; +"LIMB_RIGHT" = "pravá"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Klepnutím odpovedajte"; +"NULL_ANSWER" = "Vyberte odpoveď"; +"PLACEHOLDER_IMAGE_CHOICES" = "Klepnutím vyberte"; +"PLACEHOLDER_LONG_TEXT" = "Klepnutím píšte"; + +/* Button titles */ +"BUTTON_AGREE" = "Súhlasím"; +"BUTTON_CANCEL" = "Zrušiť"; +"BUTTON_OK" = "Potvrdiť"; +"BUTTON_CLEAR" = "Vyčistiť"; +"BUTTON_CLEAR_SIGNATURE" = "Vymazať podpis"; +"BUTTON_APPLY" = "Použiť"; +"BUTTON_DISAGREE" = "Nesúhlasím"; +"BUTTON_DONE" = "Hotovo"; +"BUTTON_GET_STARTED" = "Začať"; +"BUTTON_LEARN_MORE" = "Viac informácií"; +"BUTTON_NEXT" = "Ďalej"; +"BUTTON_SKIP" = "Preskočiť"; +"BUTTON_SKIP_QUESTION" = "Preskočiť túto otázku"; +"BUTTON_START_TIMER" = "Spustiť časovač"; +"BUTTON_OPTION_SAVE" = "Uložiť na neskôr"; +"BUTTON_OPTION_DISCARD" = "Zahodiť výsledky"; +"BUTTON_OPTION_STOP_TASK" = "Ukončiť úlohu"; +"BUTTON_SAVE" = "Uložiť"; +"BUTTON_CLEAR_ANSWER" = "Vyčistiť odpoveď"; +"BUTTON_READ_ONLY_MODE" = "Túto odpoveď nie je možné upraviť."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Zatvoriť"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Aktivita sa spustí o"; +"TASK_COMPLETE_TITLE" = "Aktivita dokončená"; +"TASK_COMPLETE_TEXT" = "Vaše dáta budú analyzované a na výsledky budete upozornení po ich vyhodnotení."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Zostáva: %@."; +"TOUCH_ANYWHERE_LABEL" = "Pokračujte klepnutím na obrazovku."; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Zachytiť obrázok"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Znovu zachytiť obrázok"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Nenašla sa žiadna kamera. Tento krok nebude možné dokončiť."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Ak chcete dokončiť tento krok, v Nastaveniach povoľte tejto aplikácii prístup ku kamere."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Pre zachytené obrázky nebol uvedený žiadny cieľový priečinok."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Zachytený obrázok sa nepodarilo uložiť."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Spustiť nahrávanie"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Zastaviť nahrávanie"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Znovu zachytiť video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Kondícia"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Vzdialenosť (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Srdcová frekvencia (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Pohodlne sa posaďte na %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Kráčajte čo najrýchlejšie %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Táto aktivita monitoruje vašu srdcovú frekvenciu a zmeria vzdialenosť, ktorú prejdete za %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Prechádzajte sa vonku %1$@ čo najrýchlejšou chôdzou. Po skončení sa pohodlne posaďte na %2$@. Začnite klepnutím na Začať."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Držanie tela a rovnováha"; +"WALK_INTRO_TEXT" = "Táto aktivita zmeria vaše držanie tela a rovnováhu počas chôdze a státia. Ak nemôžete bezpečne chodiť bez cudzej pomoci, nepokračujte."; +"WALK_INTRO_2_TEXT_%ld" = "Nájdite si miesto, kde môžete bez cudzej pomoci bezpečne prejsť rovno %ld krokov."; +"WALK_INTRO_2_DETAIL" = "Vložte si zariadenie do vrecka alebo tašky a postupujte podľa zvukových pokynov."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Teraz %@ nehybne stojte."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Nehybne stojte %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Otočte sa a choďte späť na miesto, kde ste začali."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Prejdite rovno %ld krokov"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Nájdite si miesto, kde môžete bezpečne chodiť po priamke tam a naspäť. Skúste kráčať plynule a na konci sa otočiť, ako keby ste obchádzali kužeľ.\n\nV ďalšom kroku budete požiadaní o otočenie na mieste o 360 stupňov a následné státie v pokoji s pripaženými rukami a chodidlami na šírku ramien."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Keď budete pripravení, klepnite na Začať.\nPotom si vložte zariadenie do vrecka alebo tašky a postupujte podľa zvukových pokynov."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Kráčajte tam a naspäť po priamke %@. Chôdza by mala byť prirodzená."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Otočte sa o 360 stupňov a na %@ ostaňte nehybne stáť."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Dokončili ste aktivitu."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Rýchlosť klepania"; +"TAPPING_TASK_TITLE_RIGHT" = "Pravá ruka"; +"TAPPING_TASK_TITLE_LEFT" = "Ľavá ruka"; +"TAPPING_INTRO_TEXT" = "Táto aktivita zmeria vašu rýchlosť klepania."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Položte zariadenie na vodorovnú plochu."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Pomocou dvoch prstov rovnakej ruky striedavo klepte na tlačidlá na obrazovke."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Pomocou dvoch prstov pravej ruky striedavo klepte na tlačidlá na obrazovke."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Pomocou dvoch prstov ľavej ruky striedavo klepte na tlačidlá na obrazovke."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Zopakujte tento test pomocou pravej ruky."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Zopakujte tento test pomocou ľavej ruky."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Klepnite najprv jedným prstom a potom druhým prstom. Skúste klepnutia načasovať tak, aby boli čo najviac pravidelné. Klepte %@."; +"TAPPING_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Začnite klepnutím na Ďalej."; +"TAP_BUTTON_TITLE" = "Klepnite"; +"TOTAL_TAPS_LABEL" = "Počet klepnutí"; +"TAPPING_INSTRUCTION" = "Pravidelne klepte na tlačidlá dvomi prstami."; +"TAPPING_INSTRUCTION_RIGHT" = "Klepte na tlačidlá pomocou PRAVEJ ruky."; +"TAPPING_INSTRUCTION_LEFT" = "Klepte na tlačidlá pomocou ĽAVEJ ruky."; +"TAPPING_SKIP_TITLE" = "Preskočiť túto ruku"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amslerova mriežka"; +"AMSLER_GRID_INTRO_TEXT" = "Táto aktivita pomáha zistiť problémy so zrakom."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Počas celého testu držte zariadenie pred tvárou na úrovni očí vo vzdialenosti 30 cm."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Zatvorte %@ a pozerajte sa na bodku v strede štvorcovej mriežky.\n\nPomocou prsta alebo dotykového pera označte skreslené miesta, ako sú napríklad rozmazané alebo nerovné čiary.\n\nPo skončení potiahnite doľava na ľubovoľnom mieste mimo mriežky."; +"AMSLER_GRID_LEFT_EYE" = "ľavé oko"; +"AMSLER_GRID_RIGHT_EYE" = "pravé oko"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Hlas"; +"AUDIO_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"AUDIO_INSTRUCTION" = "Po čo najdlhšiu dobu vravte do mikrofónu „Aaaaaaaaaa“."; +"AUDIO_INTRO_TEXT" = "Zhlboka sa nadýchnite a čo najdlhšie hovorte do mikrofónu „Aaaaaaaaaa“. Snažte sa udržať stabilnú hlasitosť, aby paličky zvuku zostali modré."; +"AUDIO_INTENDED_USE" = "Táto aktivita vyhodnotí váš hlas, ktorý nahráte pomocou mikrofónu v dolnej časti zariadenia."; +"AUDIO_TOO_LOUD_LABEL" = "Príliš nahlas"; +"AUDIO_GENERIC_ERROR_LABEL" = "Nie je možné nahrať zvuk"; +"AUDIO_LEVEL_CHECK_LABEL" = "Počkajte na dokončenie merania úrovne hluku pozadia."; +"AUDIO_TOO_LOUD_MESSAGE" = "Úroveň hluku okolitého prostredia je príliš vysoká na nahrávanie hlasu. Presuňte sa na tichšie miesto a skúste to znovu."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Keď budete pripravení, klepnite na Ďalej."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tónová audiometria"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Táto aktivita meria vašu schopnosť počuť rôzne zvuky."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Skôr ako začnete, pripojte slúchadlá a nasaďte si ich.\n\nZvuk bude veľmi slabý a nepodobá sa na bežné zvonenie. Zvuk bude sprvu tichý a jeho hlasitosť bude postupne narastať. Pozorne počúvajte a klepnutím na ľavé alebo pravé tlačidlo vyberte ucho, v ktorom ste ho začuli."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Teraz by ste mali počuť tón. Nastavte hlasitosť pomocou ovládacích prvkov na bočnej strane zariadenia.\n\nKeď budete pripravení začať, klepnite na ľubovoľné tlačidlo."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Akonáhle začujete zvuk, klepnutím na ľavé alebo pravé tlačidlo vyberte ucho, v ktorom ste ho počuli."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Ľavé ucho"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Pravé ucho"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, naľavo"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, napravo"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tónová audiometria"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Keď začujete tón, klepnite."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Tóny a hlasitosť"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Budete počuť sériu tónov."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Keď začujete tón, klepnite na tlačidlo."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Pri tomto teste bude hlasitosť nastavená na úroveň 50 percent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Tento test trvá približne 10 minút."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Zapnite si režim Nerušiť, aby vás nikto nevyrušoval."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Najskôr budú tóny znieť vo vašom pravom uchu."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Teraz budú tóny znieť vo vašom ľavom uchu."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Táto aktivita identifikuje prahové úrovne sluchu osoby na mierke v dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Uistite sa, že hlasitosť zariadenia je nastavená na maximum.\n\nPočas tejto úlohy budete v ľavom alebo pravom uchu počuť slabý tón.\n\nPočúvajte pozorne a vždy, keď začujete tón, klepnite na tlačidlo."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Tento test určuje, nakoľko hlasný musí byť zvuk, aby ste ho počuli."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Úvodný dotazník."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "V prípade potreby vyberte ucho, ktorým lepšie počujete."; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "ľavé"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "pravé"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "bez predvoľby"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Test bol zrušený"; +"dBHL_ALERT_TITLE_START_OVER" = "Spustiť znovu"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Zrušiť test"; +"dBHL_ALERT_TEXT" = "Ak chcete absolvovať tento test, znovu pripojte AirPody alebo EarPody."; +"dBHL_PROGRESS_COMPLETION_%@" = "Dokončené na %@"; + +/* Headphones. */ +"AIRPODS" = "AirPody"; +"EARPODS" = "EarPody"; +"HEADPHONES" = "Slúchadlá"; +"HEADPHONES_UNKNOWN" = "Neznáme"; +"HEADPHONES_NONE" = "Žiadne"; +"CONNECTED" = "Pripojené"; +"NOT_CONNECTED" = "Nepripojené"; +"HEADPHONE_CONNECTED_%@" = "Pripojené – %@"; +"HEADPHONE_DETECT_TITLE" = "Pripojte slúchadlá"; +"HEADPHONE_DETECT_TEXT" = "Na tento test budete potrebovať Apple AirPody alebo Apple EarPody"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Priestorová pamäť"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Táto aktivita zmeria vašu krátkodobú pamäť zobrazením sekvencie obrázkov (%@), ktorú budete musieť zopakovať."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "kvety"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "kvety"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Obrázky (%@) sa budú postupne rozsvecovať. Klepnite na obrázky (%@) v rovnakom poradí, v akom sa rozsvietili."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Obrázky (%@) sa budú postupne rozsvecovať. Klepnite na obrázky (%@) v opačnom poradí, v akom sa rozsvietili."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Klepnutím na Začať spustite test a pozorne sa dívajte."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Skóre"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Pozorujte rozsvecovanie obrázkov (%@)"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Klepnite na obrázky (%@) v poradí, v akom sa rozsvietili"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Klepnite na obrázky (%@) v opačnom poradí"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sekvencia dokončená"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Pokračujte klepnutím na Ďalej."; +"MEMORY_GAME_FAILED_TITLE" = "Skúste to znovu"; +"MEMORY_GAME_FAILED_MESSAGE" = "Tentokrát sa vám to nepodarilo. Pokračujte klepnutím na Ďalej."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Čas vypršal"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Vypršal vám čas.\nPokračujte klepnutím na Ďalej."; +"MEMORY_GAME_COMPLETE" = "Hra dokončená"; +"MEMORY_GAME_PAUSED_TITLE" = "Pozastavené"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Pokračujte klepnutím na Ďalej."; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Na vývoji tejto aktivity sa podieľali Katherine Possin, PhD a Joel Kramer, PhD z Kalifornskej univerzity v San Franciscu."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Čas reakcie"; +"REACTION_TIME_TASK_INTENDED_USE" = "Táto aktivita hodnotí, ako rýchlo reagujete na vizuálny podnet."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Hneď ako sa na obrazovke objaví modrý bod, potraste zariadením v ľubovoľnom smere. Budete vyzvaní, aby ste to urobili %D-krát."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Pokus %@ z %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Keď sa zobrazí modrý kruh, rýchlo potraste zariadením."; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroopov test"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Keď sa na obrazovke zobrazí slovo, vyberte prvé písmeno názvu zobrazenej FARBY."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Ak ste pripravení na Stroopov test, klepnite na Začať."; +"STROOP_TASK_STEP_TEXT" = "Vyberte prvé písmeno názvu zobrazenej FARBY."; +"STROOP_COLOR_RED" = "ČERVENÁ"; +"STROOP_COLOR_GREEN" = "ZELENÁ"; +"STROOP_COLOR_BLUE" = "MODRÁ"; +"STROOP_COLOR_YELLOW" = "ŽLTÁ"; +"STROOP_COLOR_RED_INITIAL" = "Č"; +"STROOP_COLOR_GREEN_INITIAL" = "Z"; +"STROOP_COLOR_BLUE_INITIAL" = "M"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ž"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanojská veža"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Táto aktivita vyhodnotí vašu schopnosť riešiť rébusy."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Presuňte celú pyramídu na zvýraznenú podložku čo najmenším počtom ťahov."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Vyriešte rébus"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Počet ťahov: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Tento rébus nedokážem vyriešiť"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Rozsah pohybu"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption musí byť ľavé alebo pravé"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rozsah pohybu ľavého kolena"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rozsah pohybu pravého kolena"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Táto aktivita meria, do akej miery dokážete vystrieť ľavé koleno."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Táto aktivita meria, do akej miery dokážete vystrieť pravé koleno."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Na zariadení zapnite zvuk, aby ste počuli pokyny. Sadnite si na okraj stoličky. Po spustení aktivity si na účely merania pridržte zariadenie na ľavom kolene."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Na zariadení zapnite zvuk, aby ste počuli pokyny. Sadnite si na okraj stoličky. Po spustení aktivity si na účely merania pridržte zariadenie na pravom kolene."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Položte zariadenie na ľavé koleno obrazovkou nahor, ako je to znázornené na obrázku."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Pridržte si zariadenie na pravom kolene obrazovkou nahor, ako je to znázornené na obrázku."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Keď budete pripravení, klepnite na obrazovku a čo najviac vystrite ľavé koleno. Potom ho vráťte do počiatočnej polohy a znova klepnite na obrazovku."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Keď budete pripravení, klepnite na obrazovku a čo najviac vystrite pravé koleno. Potom ho vráťte do počiatočnej polohy a znova klepnite na obrazovku."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Položte si zariadenie na ľavé koleno. Klepnite na obrazovku a ľavé koleno čo najviac vystrite."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Položte si zariadenie na pravé koleno. Klepnite na obrazovku a pravé koleno čo najviac vystrite."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Keď skončíte, vráťte ľavé koleno do počiatočnej polohy. Potom klepnite na ľubovoľné miesto."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Keď skončíte, vráťte pravé koleno do počiatočnej polohy. Potom klepnite na ľubovoľné miesto."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rozsah pohybu ľavého ramena"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rozsah pohybu pravého ramena"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Táto aktivita meria, do akej miery dokážete zdvihnúť ľavú ruku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Táto aktivita meria, do akej miery dokážete zdvihnúť pravú ruku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Na zariadení zapnite zvuk, aby ste počuli pokyny. Po spustení aktivity si na účely merania pridržte zariadenie na ľavom ramene."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Na zariadení zapnite zvuk, aby ste počuli pokyny. Po spustení aktivity si na účely merania pridržte zariadenie na pravom ramene."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Pridržte si zariadenie na ľavom ramene obrazovkou nahor, ako je to znázornené na obrázku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Pridržte si zariadenie na pravom ramene obrazovkou nahor, ako je to znázornené na obrázku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Keď budete pripravení, klepnite na obrazovku a zdvihnite ľavú ruku čo najvyššie. Potom ju vráťte do počiatočnej polohy a znova klepnite na obrazovku."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Keď budete pripravení, klepnite na obrazovku a zdvihnite pravú ruku čo najvyššie. Potom ju vráťte do počiatočnej polohy a znova klepnite na obrazovku."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Položte si zariadenie na ľavé plece. Klepnite na obrazovku a ľavú ruku čo najviac predpažte."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Položte si zariadenie na pravé plece. Klepnite na obrazovku a pravú ruku čo najviac predpažte."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Keď skončíte, vráťte ľavú ruku do počiatočnej polohy. Potom klepnite na ľubovoľné miesto."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Keď skončíte, vráťte pravú ruku do počiatočnej polohy. Potom klepnite na ľubovoľné miesto."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Chôdza na čas"; +"TIMED_WALK_INTRO_DETAIL" = "Táto aktivita meria funkčnosť vašich dolných končatín."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Nájdite si miesto, najlepšie vonku, kde môžete čo najrýchlejšie bezpečne prejsť v priamom smere približne %@. Nespomaľujte, kým neprejdete cieľom."; +"TIMED_WALK_INTRO_2_DETAIL" = "Začnite klepnutím na Ďalej."; +"TIMED_WALK_FORM_TITLE" = "Zdravotná pomôcka"; +"TIMED_WALK_FORM_TEXT" = "Pre každý test použite rovnakú zdravotnú pomôcku."; +"TIMED_WALK_QUESTION_TEXT" = "Nosíte ortézu na členku?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Používate zdravotnú pomôcku?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Klepnutím sem vyberte odpoveď."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Nie"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Jedna palica"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Jedna barla"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dve palice"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dve barly"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Chodítko"; +"TIMED_WALK_INSTRUCTION_%@" = "Prejdite %@ v priamom smere."; +"TIMED_WALK_INSTRUCTION_TURN" = "Otočte sa naspäť."; +"TIMED_WALK_INSTRUCTION_2" = "Choďte späť na miesto, kde ste začali."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Po skončení klepnite na Ďalej."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Paced Auditory Serial Addition Test meria rýchlosť, akou dokážete spracovať a spočítať informácie prijaté prostredníctvom sluchu."; +"PVSAT_INTRO_TEXT" = "Paced Visual Serial Addition Test meria rýchlosť, akou dokážete spracovať a spočítať informácie prijaté prostredníctvom zraku."; +"PAVSAT_INTRO_TEXT" = "Paced Auditory a Visual Serial Addition Test meria rýchlosť, akou dokážete spracovať a spočítať informácie prijaté prostredníctvom sluchu a zraku."; +"PSAT_INTRO_TEXT_2_%@" = "Každé %@ sa zobrazí nové číslo.\nKaždé nové číslo musíte pripočítať k číslu zobrazenému pred ním.\nPozor, nesmiete počítať celkový súčet všetkých čísel, ale len súčet dvoch posledných čísel."; +"PSAT_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"PSAT_INITIAL_INSTRUCTION" = "Zapamätajte si toto prvé číslo."; +"PSAT_INSTRUCTION" = "Pripočítajte nové číslo k predošlému číslu."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-kolíkový test"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Táto aktivita slúži na otestovanie motoriky horných končatín. Počas testu budete umiestňovať kolíky do otvorov. Test budete opakovať %@-krát."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Otestovaná bude vaša ľavá aj pravá ruka.\nČo najrýchlejšie vezmite kolík, umiestnite do otvoru %@-krát a potom ho vytiahnite taktiež %@-krát."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Otestovaná bude vaša pravá aj ľavá ruka.\nČo najrýchlejšie vezmite kolík, umiestnite do otvoru %@-krát a potom ho vytiahnite taktiež %@-krát."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Umiestnite kolík do otvoru pomocou ľavej ruky."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Umiestnite kolík do otvoru pomocou pravej ruky."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Položte kolík za čiaru pomocou ľavej ruky."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Položte kolík za čiaru pomocou pravej ruky."; +"HOLE_PEG_TEST_TEXT" = "Zdvihnite kolík dvomi prstami."; +"HOLE_PEG_TEST_TEXT_2" = "Nadvihnutím prstov pustite kolík."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Trasenie rúk"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Táto aktivita zmeria trasenie rúk v rôznych polohách. Po celý čas by ste mali pohodlne sedieť."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Držte telefón v ruke, ktorá je viac postihnutá, ako na obrázku nižšie."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Držte telefón v PRAVEJ ruke, ako na obrázku nižšie."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Držte telefón v ĽAVEJ ruke, ako na obrázku nižšie."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Budete požiadaní o vykonanie %@. Po celý čas budete sedieť s telefónom v ruke."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "jednej úlohy"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "dvoch úloh"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "troch úloh"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "štyroch úloh"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "piatich úloh"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Ak chcete pokračovať, klepnite na Ďalej."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Pripravte sa na držanie telefónu v ruke."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Pripravte sa na držanie telefónu v ĽAVEJ ruke."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Pripravte sa na držanie telefónu v PRAVEJ ruke."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Držte telefón %ld sekúnd s rukou položenou na lone."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Držte telefón vo vystretej ruke vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Držte telefón vo vystretej ĽAVEJ ruke vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Držte telefón vo vystretej PRAVEJ ruke vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Držte telefón vo vystretej ruke %ld sekúnd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Držte telefón v ruke s pokrčeným lakťom vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Držte telefón v ĽAVEJ ruke s pokrčeným lakťom vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Držte telefón v PRAVEJ ruke s pokrčeným lakťom vo výške ramien."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Držte telefón v ruke s pokrčeným lakťom %ld sekúnd."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "S pokrčeným lakťom sa opakovane dotýkajte nosa telefónom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "S pokrčeným lakťom a telefónom v ĽAVEJ ruke sa opakovane dotýkajte nosa telefónom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "S pokrčeným lakťom a telefónom v PRAVEJ ruke sa opakovane dotýkajte nosa telefónom."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Na %ld sekúnd sa dotýkajte nosa telefónom."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Pripravte sa na mávanie otáčaním zápästia."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Pripravte sa na mávanie otáčaním zápästia s telefónom v ĽAVEJ ruke."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Pripravte sa na mávanie otáčaním zápästia s telefónom v PRAVEJ ruke."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Mávajte zápästím %ld sekúnd."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Uchopte telefón do ĽAVEJ ruky a pokračujte na ďalšiu úlohu."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Uchopte telefón do PRAVEJ ruky a pokračujte na ďalšiu úlohu."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Pokračujte na ďalšiu úlohu."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivita dokončená."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Budete požiadaní o vykonanie %@. Po celý čas budete sedieť s telefónom najprv v jednej a potom v druhej ruke."; +"TREMOR_SKIP_LEFT_HAND" = "Túto aktivitu nedokážem vykonať pomocou ĽAVEJ ruky."; +"TREMOR_SKIP_RIGHT_HAND" = "Túto aktivitu nedokážem vykonať pomocou PRAVEJ ruky."; +"TREMOR_SKIP_NEITHER" = "Túto aktivitu dokážem vykonať pomocou oboch rúk."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Test spájania bodov"; +"TRAILMAKING_INTENDED_USE" = "Táto aktivita vyhodnotí vašu vizuálnu pozornosť a schopnosť pracovať na viacerých úlohách tak, že zaznamená čas, ktorý potrebujete na klepnutie na sériu bodiek v určitom poradí."; +"TRAILMAKING_INTENDED_USE2_A" = "Po skončení odpočítavania striedavo klepajte na bodky s číslami a písmenami. Začnite klepnutím na prvé číslo „1“ a potom klepnite na čísla „2“ – „3“ – „4“…, až kým nedosiahnete číslo „7“."; +"TRAILMAKING_INTENDED_USE2_B" = "Po skončení odpočítavania striedavo klepajte na bodky s číslami a písmenami. Začnite klepnutím na prvé číslo „1“, potom klepnite na prvé písmeno „A“ a pokračujte klepnutím na „2“ – „B“ – „3“ – „C“…, až kým nedosiahnete číslo „7“."; +"TRAILMAKING_INTRO_TEXT" = "Spravte to čo najrýchlejšie a bez chýb. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Rozpoznávanie reči"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Táto aktivita zaznamená vašu reč pomocou mikrofónu v dolnej časti zariadenia a prevedie ju na text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Aktivitu spustíte klepnutím na Začať."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Stlačením tlačidla spustite nahrávanie a začnite hovoriť."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Spustiť nahrávanie"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Zastaviť nahrávanie"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Upraviť prepis"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Ak ste našli chyby v prepise reči, opravte ich."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Tu sa zobrazí prepis."; +"SPEECH_RECOGNITION_FAILED" = "Rozpoznávanie reči zlyhalo."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Nepodarilo sa spustiť rozpoznávanie reči."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Spustiť prehrávanie"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Zastaviť prehrávanie"; +"SPEECH_IN_NOISE_TITLE" = "Reč v hlučnom prostredí"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Táto aktivita meria zrozumiteľnosť reči v hlučnom prostredí."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Tento test pozostáva z nasledujúcich úloh:\n\nVypočujete si vetu.\n\nZreteľne zopakujete, čo ste počuli, prípadne to napíšete pomocou klávesnice. \n\nAk zopakujete, čo ste počuli, budete môcť upraviť prepis vygenerovaný funkciou na rozpoznávanie reči."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Kalibrácia hlasitosti"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Klepnite na Spustiť prehrávanie, upravte hlasitosť na primeranú úroveň a potom pokračujte klepnutím na Zastaviť prehrávanie."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Počúvanie"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Nahrávka vety skombinovanej so šumom na pozadí a náhodným pomerom signálu k šumu (SNR) bude prehraná len raz."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Rozprávanie"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Zopakujte, čo ste počuli."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Nepodarilo sa vytvoriť súbor"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Nepodarilo odstrániť dostatok súborov záznamov pre dosiahnutie prahovej hodnoty"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Chyba počas nastavovania vlastnosti"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Súbor neoznačený ako vymazaný (neoznačený ako odoslaný)"; +"ERROR_DATALOGGER_MULTIPLE" = "Viacero chýb pri odstraňovaní záznamov"; +"ERROR_RECORDER_NO_DATA" = "Nenašli sa žiadne zhromaždené dáta."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Nie je špecifikovaný výstupný adresár"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Indikátor hladiny akustického tlaku"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Táto aktivita meria úroveň akustického tlaku. Ak je úroveň hluku príliš vysoká, nebudete môcť pokračovať. Prejdite na tichšie miesto a dokončite túto úlohu, prípadne aktivitu absolvujte neskôr."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Vypočítavam"; +"ENVIRONMENTSPL_THRESHOLD" = "Prah: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Hlučnosť prostredia je vyhovujúca"; +"ENVIRONMENTSPL_NOISE" = "Príliš hlučné prostredie"; +"ENVIRONMENTSPL_TITLE_2" = "Nájdite si tiché miesto"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Na zaistenie čo najväčšej presnosti sa tento test musí vykonať v tichom prostredí."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Spustiť úlohu"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Žiadne dáta"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Nastavte hodnotu posuvníkom"; +"SLIDER_I_DONT_KNOW" = "Neviem"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Strana"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Späť"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Zobraziť PDF miniatúru"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Skryť PDF miniatúru"; +"AX_BUTTON_ANNOTATE" = "Anotovať"; +"AX_BUTTON_SHOW_SEARCH" = "Zobraziť vyhľadávaciu lištu"; +"AX_BUTTON_HIDE_SEARCH" = "Skryť vyhľadávaciu lištu"; +"AX_BUTTON_SHARE" = "Zdieľať"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ilustrácia symbolu zaškrtnutia v modrom kruhu označujúca úspech"; + +"AX_SIGNVIEW_LABEL" = "Pole pre podpis"; +"AX_SIGNVIEW_HINT" = "Pre podpísanie sa dotknite obrazovky a ťahajte prst"; +"AX_SIGNVIEW_SIGNED" = "Podpísané"; +"AX_SIGNVIEW_UNSIGNED" = "Nepodpísané"; + +"AX_SELECTED" = "Označené"; +"AX_UNSELECTED" = "Neoznačené"; +"AX_SELECT_ALL_THAT_APPLY" = "ZAŠKRTNITE VHODNÉ"; + +"AX_SLIDER_LABEL" = "Posuvník pre odpoveď. Rozsah je od %@ do %@"; +"AX_UNLABELED_IMAGE" = "Obrázok bez popisu"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Spustiť úlohu"; + +"AX.MEMORY.TILE.ACTIVE" = "aktívne"; +"AX.MEMORY.TILE.CORRECT" = "správne"; +"AX.MEMORY.TILE.INCORRECT" = "nesprávne"; +"AX.MEMORY.TILE.QUIESCENT" = "nehybné"; +"AX.MEMORY.TILE.LABEL" = "Dlaždica pamäťovej hry"; + +"AX_IMAGE_CAPTURE_LABEL" = "Náhľad"; +"AX_IMAGE_CAPTURED_LABEL" = "Zachytený obrázok"; + +"AX_VIDEO_CAPTURE_LABEL" = "Náhľad zachytávaného videa"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video je vytvorené"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Kotúč veľkosti %@ nie je možné umiestniť na kotúč veľkosti %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Cieľ"; +"AX_TOWER_OF_HANOI_TOWER" = "Veža"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Klepnutím dvakrát umiestnite kotúč"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Klepnutím dvakrát vyberte najvrchnejší kotúč"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Obsahuje kotúče o veľkostiach %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Prázdne"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Zrušiť klávesnicu"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Rozsah od %@ do %@"; +"AX_GRAPH_STACK_PREFIX" = "Pyramída pozostáva z"; +"AX_GRAPH_AND_SEPARATOR" = " a "; +"AX_GRAPH_POINT_%@" = "Bod: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Vlnový priebeh reči"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Keď sa spustí nahrávanie, ďalšou aktiváciou ho zastavíte."; + +"AX_AUDIO_BAR_GRAPH" = "Stĺpcový graf zvuku"; + +"AX_AMSLER_GRID_LABEL" = "Amslerova mriežka"; +"AX_AMSLER_GRID_HINT" = "Pomocou prsta alebo dotykového pera označte mriežku alebo potiahnutím doľava mimo mriežky dokončite úlohu."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Tlačidlá s možnosťou klepnutia"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Klepnite pre ľavé ucho"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktiváciou spustíte test. Keď budete po spustení testu počuť zvuk v ľavom uchu, klepnite priamo na toto tlačidlo."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Klepnite pre pravé ucho"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktiváciou spustíte test. Keď budete po spustení testu počuť zvuk v pravom uchu, klepnite priamo na toto tlačidlo."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Pri používaní VoiceOveru môžete dotykom na obrazovku zistiť, kde sa nachádzajú tlačidlá pre každé ucho. Po spustení testu bude možné na tlačidlá priamo klepnúť. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Klepnutím aktivujete používanie jedného prsta"; +"AX_TAP_BUTTON_2_LABEL" = "Klepnutím aktivujete používanie druhého prsta"; +"AX_TAP_BUTTON_HINT" = "Po aktivácii bude možné na tlačidlá priamo klepnúť."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Pri používaní VoiceOveru môžete dotykom na obrazovku zistiť, kde sa nachádzajú tlačidlá. Po aktivácii niektorého z tlačidiel bude možné na tlačidlá priamo klepnúť."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Na tlačidlá teraz možno priamo klepnúť."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Pri používaní VoiceOveru bude možné na tlačidlo priamo klepnúť. Tlačidlo bude umiestnené približne v strede obrazovky."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Pri používaní VoiceOveru bude možné na tlačidlá v teste priamo klepnúť."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Nie je možné dekódovať restoreData pre inicializáciu"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..9801388 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sk.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d chyba) + other + (%d chýb) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.strings new file mode 100755 index 0000000..76ed624 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Godkännande"; +"CONSENT_NAME_GIVEN" = "Förnamn"; +"CONSENT_NAME_FAMILY" = "Efternamn"; +"CONSENT_NAME_PLACEHOLDER" = "Krävs"; +"CONSENT_REVIEW_TITLE" = "Granska"; +"CONSENT_REVIEW_INSTRUCTION" = "Granska formuläret nedan och tryck på Godkänn om du vill fortsätta."; +"CONSENT_REVIEW_ALERT_TITLE" = "Granska"; +"CONSENT_SIGNATURE_TITLE" = "Signatur"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Signera med hjälp av fingret i rutan nedan."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Signera här"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Sidan %1$ld av %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Välkommen"; +"CONSENT_SECTION_DATA_GATHERING" = "Datainsamling"; +"CONSENT_SECTION_PRIVACY" = "Integritet"; +"CONSENT_SECTION_DATA_USE" = "Dataanvändning"; +"CONSENT_SECTION_STUDY_SURVEY" = "Studieenkät"; +"CONSENT_SECTION_STUDY_TASKS" = "Studieåtgärder"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Tidsåtgång"; +"CONSENT_SECTION_WITHDRAWING" = "Tillbakadragning"; +"CONSENT_LEARN_MORE_TITLE" = "Läs mer"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Läs mer om hur data samlas in"; +"LEARN_MORE_DATA_USE" = "Läs mer om hur data används"; +"LEARN_MORE_PRIVACY" = "Läs mer om hur din integritet och identitet skyddas"; +"LEARN_MORE_WELCOME" = "Läs mer om studien först"; +"LEARN_MORE_STUDY_SURVEY" = "Läs mer om studieenkäten"; +"LEARN_MORE_TIME_COMMITMENT" = "Läs mer om studiens påverkan på din tid"; +"LEARN_MORE_TASKS" = "Läs mer om de berörda åtgärderna"; +"LEARN_MORE_WITHDRAWING" = "Läs mer om tillbakadragning"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Delningsalternativ"; +"CONSENT_SHARE_WIDELY_%@" = "Dela mina data med %@ och kvalificerade forskare över hela världen"; +"CONSENT_SHARE_ONLY_%@" = "Dela mina data endast med %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ kommer att få dina studiedata från din medverkan i denna studie.\n\nVidare delning av dina kodade studiedata (utan ditt namn eller liknande information) kan vara till nytta för denna och framtida forskning."; +"LEARN_MORE_CONSENT_SHARING" = "Läs mer om datadelning"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Namnförtydligande"; +"CONSENT_DOC_LINE_SIGNATURE" = "Signatur"; +"CONSENT_DOC_LINE_DATE" = "Datum"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ av %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Fråga %1$@ av %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Överhoppad"; +"REVIEW_EDIT_ANSWER" = "Ändra"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Ogiltigt värde"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ överskrider det högsta tillåtna värdet (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ är mindre än det minsta tillåtna värdet (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ är inte ett giltigt värde."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Ogiltig e-postadress: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Ange en adress"; +"LOCATION_ERROR_TITLE" = "Kunde inte hitta den angivna adressen"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Kunde inte bestämma din aktuella plats. Ange en adress eller flytta dig till en plats med bättre GPS-signal om det är tillämpligt."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Åtkomst till platstjänster har nekats. Tillåt att den här appen använder platstjänster via Inställningar."; +"LOCATION_ERROR_GEOCODE" = "Det gick inte att hitta något resultat för den angivna adressen. Kontrollera att adressen är giltig."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Antingen är du inte ansluten till internet eller så har du överskridit det maximala antalet addressökbegäranden. Om du inte är ansluten till internet aktiverar du Wi-Fi så att du kan svara på frågan, hoppa över frågan om en sådan knapp är tillgänglig eller gå tillbaka till enkäten när du är ansluten till internet. I annat fall försöker du igen om några minuter."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Textinnehållet överskrider maximal längd: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Kamera inte tillgänglig i delad skärm."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-post"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Lösenord"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Ange lösenord"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Bekräfta"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Ange lösenordet igen"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Lösenorden stämmer inte överens."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Ytterligare information"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Kön"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Välj ett kön"; +"DOB_FORM_ITEM_TITLE" = "Födelsedatum"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Välj ett datum"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefonnummer"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Verifiering"; +"VERIFICATION_STEP_TITLE" = "Bekräfta din e-postadress"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Tryck på länken nedan om du inte fick något bekräftelsebrev och vill att det skickas på nytt."; +"RESEND_EMAIL_BUTTON_TITLE" = "Skicka bekräftelsebrev igen"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Inloggning"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Har du glömt lösenordet?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Ange lösenkod"; +"PASSCODE_CONFIRM_MESSAGE" = "Bekräfta lösenkod"; +"PASSCODE_SAVED_MESSAGE" = "Lösenkoden sparad"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Autentiserad med lösenkod"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Ange din gamla lösenkod"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Ange din nya lösenkod"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Bekräfta den nya lösenkoden"; +"PASSCODE_INVALID_ALERT_TITLE" = "Felaktig lösenkod"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Lösenkoderna stämde inte överens. Försök igen."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Autentisera med Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID-fel"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Endast numeriska tecken tillåts."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Förloppsindikator för angivande av lösenkod"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ av %@ siffror angivna"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Glömt lösenkoden?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Kunde inte lägga till nyckelringsobjekt."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Kunde inte uppdatera nyckelringsobjekt."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Kunde inte radera nyckelringsobjekt."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Kunde inte hitta nyckelringsobjekt."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Typ I"; +"FITZPATRICK_SKIN_TYPE_II" = "Typ II"; +"FITZPATRICK_SKIN_TYPE_III" = "Typ III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Typ IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Typ V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Typ VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Kvinna"; +"GENDER_MALE" = "Man"; +"GENDER_OTHER" = "Annat"; + +/* Boolean answer strings */ +"BOOL_NO" = "Nej"; +"BOOL_YES" = "Ja"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "fot"; +"MEASURING_UNIT_IN" = "tum"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "uns"; + +/* Limb values. */ +"LIMB_LEFT" = "vänster"; +"LIMB_RIGHT" = "höger"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Tryck för att svara"; +"NULL_ANSWER" = "Välj ett svar"; +"PLACEHOLDER_IMAGE_CHOICES" = "Tryck för att markera"; +"PLACEHOLDER_LONG_TEXT" = "Tryck för att skriva"; + +/* Button titles */ +"BUTTON_AGREE" = "Godkänn"; +"BUTTON_CANCEL" = "Avbryt"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Rensa"; +"BUTTON_CLEAR_SIGNATURE" = "Rensa signatur"; +"BUTTON_APPLY" = "Använd"; +"BUTTON_DISAGREE" = "Avböj"; +"BUTTON_DONE" = "Klar"; +"BUTTON_GET_STARTED" = "Kom igång"; +"BUTTON_LEARN_MORE" = "Läs mer"; +"BUTTON_NEXT" = "Nästa"; +"BUTTON_SKIP" = "Hoppa över"; +"BUTTON_SKIP_QUESTION" = "Hoppa över denna fråga"; +"BUTTON_START_TIMER" = "Starta timern"; +"BUTTON_OPTION_SAVE" = "Spara till senare"; +"BUTTON_OPTION_DISCARD" = "Bortse från träffar"; +"BUTTON_OPTION_STOP_TASK" = "Avsluta åtgärd"; +"BUTTON_SAVE" = "Spara"; +"BUTTON_CLEAR_ANSWER" = "Rensa svar"; +"BUTTON_READ_ONLY_MODE" = "Det här svaret kan inte ändras."; +"BUTTON_COPYRIGHT" = "Copyright"; +"BUTTON_CLOSE" = "Stäng"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Startar aktivitet om"; +"TASK_COMPLETE_TITLE" = "Aktiviteten är klar"; +"TASK_COMPLETE_TEXT" = "Dina data kommer att analyseras, och du blir meddelad när resultaten är klara."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ återstår."; +"TOUCH_ANYWHERE_LABEL" = "Fortsätt genom att trycka var som helst"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Spara bild"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Spara bild igen"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Ingen kamera hittades. Steget kan inte slutföras."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "För att slutföra det här steget måste du ge denna app tillgång till kameran i Inställningar."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Ingen utmatningskatalog har angetts för de sparade bilderna."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Bilden kunde inte sparas."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Starta inspelning"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Stoppa inspelning"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Spela in video igen"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Motion"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Distans (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Puls – slag/minut"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Sitt bekvämt under %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Gå så fort du kan under %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Den här aktiviteten registrerar din puls och mäter hur långt du kan gå på %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Gå utomhus i snabbast möjliga takt under %1$@. När du är klar sitter du och vilar bekvämt under %2$@. Tryck på Kom igång för att börja."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Gång och balans"; +"WALK_INTRO_TEXT" = "Den här aktiviteten mäter din gångstil och balans medan du går och står still. Fortsätt endast om du säkert kan gå utan hjälp."; +"WALK_INTRO_2_TEXT_%ld" = "Hitta en plats där du säkert kan gå ungefär %ld steg i en rak linje utan hjälp."; +"WALK_INTRO_2_DETAIL" = "Placera enheten i en ficka eller väska och följ de talade anvisningarna."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Stå nu stilla under %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Stå stilla under %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Vänd om och gå tillbaka till utgångsplatsen."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Gå upp till %ld steg i en rak linje."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Hitta en plats där du tryggt kan gå fram och tillbaka i en rät linje. Försök att gå kontinuerligt genom att vända dig om vid slutet av linjen, som om du gick runt en kon.\n\nDärefter blir du ombedd att vända dig ett helt varv och sedan stå stilla med armarna längs sidorna och fötterna i ungefär axelbredd."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Tryck på Kom igång när du är redo att börja.\nPlacera sedan enheten i en ficka eller väska och följ de talade anvisningarna."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Gå fram och tillbaka i en rät linje under %@. Gå som du vanligtvis gör."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Vänd dig ett helt varv och stå sedan stilla under %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Du har slutfört aktiviteten."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tryckhastighet"; +"TAPPING_TASK_TITLE_RIGHT" = "Höger hand"; +"TAPPING_TASK_TITLE_LEFT" = "Vänster hand"; +"TAPPING_INTRO_TEXT" = "Den här aktiviteten mäter din tryckhastighet."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Lägg enheten på en slät yta."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Använd två fingrar på samma hand till att omväxlande trycka på knapparna på skärmen."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Använd två fingrar på högra handen till att omväxlande trycka på knapparna på skärmen."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Använd två fingrar på vänstra handen till att omväxlande trycka på knapparna på skärmen."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Nu upprepar du samma test med högra handen."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Nu upprepar du samma test med vänstra handen."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tryck med ett finger och sedan det andra. Försök att trycka i en så jämn takt som möjligt. Fortsätt trycka under %@."; +"TAPPING_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Tryck på Nästa för att börja."; +"TAP_BUTTON_TITLE" = "Tryck"; +"TOTAL_TAPS_LABEL" = "Totalt antal tryckningar"; +"TAPPING_INSTRUCTION" = "Tryck på knapparna så konsekvent du kan med två fingrar."; +"TAPPING_INSTRUCTION_RIGHT" = "Tryck på knapparna med HÖGRA handen."; +"TAPPING_INSTRUCTION_LEFT" = "Tryck på knapparna med VÄNSTRA handen."; +"TAPPING_SKIP_TITLE" = "Hoppa över den här handen"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler-nät"; +"AMSLER_GRID_INTRO_TEXT" = "Den här aktiviteten kan upptäcka synproblem hos användaren."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Håll enheten 30 cm från ansiktet och i ögonhöjd under hela testet."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Blunda med %@ och fokusera på punkten i mitten av det kvadratiska rutnätet.\n\nOm du ser förvrängningar, exempelvis suddiga eller vågiga linjer, märker du ut dem med fingret eller en ritpenna.\n\nSvep åt vänster utanför rutnätet när du är klar."; +"AMSLER_GRID_LEFT_EYE" = "vänster öga"; +"AMSLER_GRID_RIGHT_EYE" = "höger öga"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Röst"; +"AUDIO_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"AUDIO_INSTRUCTION" = "Säg ”aaah” i mikrofonen så länge du kan."; +"AUDIO_INTRO_TEXT" = "Ta ett djupt andetag och säg ”aaah” i mikrofonen så länge du kan. Håll röststyrkan stadig så att ljudstaplarna förblir blå."; +"AUDIO_INTENDED_USE" = "Den här aktiviteten utvärderar din röst genom att spela in den med mikrofonen i nederkanten av enheten."; +"AUDIO_TOO_LOUD_LABEL" = "För högt"; +"AUDIO_GENERIC_ERROR_LABEL" = "Kan inte spela in ljud"; +"AUDIO_LEVEL_CHECK_LABEL" = "Vänta medan vi kontrollerar ljudnivån på bakgrundsbullret."; +"AUDIO_TOO_LOUD_MESSAGE" = "Bakgrundsbullret är för högt för att spela in din röst. Gå någonstans tystare och försök igen."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Tryck på Nästa när du är redo."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Tonaudiometri"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Den här aktiviteten mäter din förmåga att höra olika ljud."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Anslut och ta på dig hörlurarna innan du börjar.\n\nLjudet kommer att vara väldigt subtilt och liknar inte ett vanligt varningsljud. Ljudet är svagt i början och ökar sakta i ljudstyrka. Koncentrera dig på ljudet och tryck på höger- eller vänsterknappen för att registrera i vilket öra du hör ljudet."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Nu bör du höra en ton. Justera volymen med reglagen på sidan av enheten.\n\nTryck på någon av knapparna när du vill börja."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Varje gång du börjar höra ett ljud ska du trycka på vänster eller höger knapp för att visa vilket öra du hör ljudet i."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Vänster öra"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Höger öra"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, vänster"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, höger"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Tonaudiometri"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Tryck när du hör en ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ton och volym"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "En serie toner kommer att spelas upp."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Tryck på knappen när du hör en ton."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "I det här testet kommer volymen att ställas in på 50 procent."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Det här testet tar omkring 10 minuter."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Aktivera Stör ej så att du inte blir avbruten."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Först kommer toner att spelas upp i ditt högra öra."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Nu kommer toner att spelas upp i ditt vänstra öra."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Den här aktiviteten identifierar en persons hörseltröskvärden i dB HL-skala."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Se till att ljudet på enheten är inställt på högsta volym.\n\nUnder den här uppgiften kommer en subtil ton att spelas i antingen det högra eller vänstra örat.\n\nLyssna noga och tryck på knappen varje gång du hör en ton."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Det här testet mäter hur hög volymen måste vara för att du ska kunna höra ett ljud."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Förberedande frågeformulär."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Markera din inställning för ”bättre öra” (om du har ett)"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "vänster"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "höger"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ingen inställning"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Testet avbröts"; +"dBHL_ALERT_TITLE_START_OVER" = "Börja om"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Avbryt testet"; +"dBHL_ALERT_TEXT" = "Anslut AirPods eller EarPods på nytt om du vill utföra det här testet."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ klart"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Hörlurar"; +"HEADPHONES_UNKNOWN" = "Okända"; +"HEADPHONES_NONE" = "Inga"; +"CONNECTED" = "Ansluten"; +"NOT_CONNECTED" = "Ej ansluten"; +"HEADPHONE_CONNECTED_%@" = "Anslutna – %@"; +"HEADPHONE_DETECT_TITLE" = "Anslut dina hörlurar"; +"HEADPHONE_DETECT_TEXT" = "Det här testet kräver Apple AirPods eller Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Spatialt minne"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Den här aktiviteten mäter ditt spatiala korttidsminne genom att be dig upprepa den ordning i vilken %@ lyser upp."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "blommor"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "blommor"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "En del av %@na kommer att lysa upp en i taget. Tryck på de %@na i samma ordning som de lyser upp."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "En del av %@na kommer att lysa upp en i taget. Tryck på de %@na i omvänd ordning jämfört med hur de lyser upp."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Tryck på Kom igång för att börja och titta noggrant."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Poäng"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Se när %@ lyser upp"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Tryck på %@ i den ordning de lyser upp"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Tryck på %@ i omvänd ordning"; +"MEMORY_GAME_COMPLETE_TITLE" = "Sekvensen är klar"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Tryck på Nästa när du vill fortsätta"; +"MEMORY_GAME_FAILED_TITLE" = "Försök igen"; +"MEMORY_GAME_FAILED_MESSAGE" = "Du klarade dig inte riktigt igenom den gången. Tryck på Nästa för att fortsätta."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Tiden är slut"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Tiden tog slut.\nTryck på Nästa för att fortsätta."; +"MEMORY_GAME_COMPLETE" = "Spelet är klart"; +"MEMORY_GAME_PAUSED_TITLE" = "Pausat"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Tryck på Nästa när du vill fortsätta"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Minnesaktiviteten har tagits fram med hjälp av fil.dr Katherine Possin och fil.dr Joel Kramer från University of California i San Francisco i USA."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Reaktionstid"; +"REACTION_TIME_TASK_INTENDED_USE" = "Den här aktiviteten utvärderar den tid det tar för dig att reagera på visuella stimuli."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Skaka enheten i valfri riktning så fort den blå punkten visas på skärmen. Du blir ombedd att göra detta %D gånger."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Försök %@ av %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Skaka snabbt enheten när den blå cirkeln visas"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Varje gång ett ord visas ska du välja de första två bokstäverna i namnet på den FÄRG som visas."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Tryck på Kom igång när du vill börja med stroop-aktiviteten."; +"STROOP_TASK_STEP_TEXT" = "Välj de första två bokstäverna i namnet på den FÄRG som visas."; +"STROOP_COLOR_RED" = "RÖD"; +"STROOP_COLOR_GREEN" = "GRÖN"; +"STROOP_COLOR_BLUE" = "BLÅ"; +"STROOP_COLOR_YELLOW" = "GUL"; +"STROOP_COLOR_RED_INITIAL" = "Rö"; +"STROOP_COLOR_GREEN_INITIAL" = "Gr"; +"STROOP_COLOR_BLUE_INITIAL" = "Bl"; +"STROOP_COLOR_YELLOW_INITIAL" = "Gu"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tornen i Hanoi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Den här aktiviteten utvärderar din förmåga att lösa pussel."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Flytta hela traven till den markerade plattformen med så få drag som möjligt."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Lös pusslet"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Antal drag: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Jag kan inte lösa pusslet"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Rörlighet"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption måste vara vänster eller höger"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Rörlighet, vänster knä"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Rörlighet, höger knä"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Den här aktiviteten mäter hur långt du kan sträcka ditt vänstra knä."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Den här aktiviteten mäter hur långt du kan sträcka ditt högra knä."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Sätt dig längst ut på en stol. Du börjar med att lägga enheten på ditt vänstra knä så att det kan mätas. Slå på ljudet på enheten så att du kan höra anvisningarna."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Sätt dig längst ut på en stol. Du börjar med att lägga enheten på ditt högra knä så att det kan mätas. Slå på ljudet på enheten så att du kan höra anvisningarna."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placera enheten på ditt vänstra knä med skärmen utåt (se bild)."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placera enheten på ditt högra knä med skärmen utåt (se bild)."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "När du är klar trycker du på skärmen för att börja och rätar ut ditt vänstra knä så långt du kan. Återgå till startpositionen och tryck igen när du är klar."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "När du är klar trycker du på skärmen för att börja och rätar ut ditt högra knä så långt du kan. Återgå till startpositionen och tryck igen när du är klar."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placera enheten på ditt vänstra knä. Tryck på skärmen och räta ut ditt vänstra knä så mycket du kan."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placera enheten på ditt högra knä. Tryck på skärmen och räta ut ditt högra knä så mycket du kan."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "När du är klar återgår du till startpositionen för ditt vänstra knä. Tryck sedan var som helst på skärmen."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "När du är klar återgår du till startpositionen för ditt högra knä. Tryck sedan var som helst på skärmen."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Rörlighet, vänster axel"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Rörlighet, höger axel"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Den här aktiviteten mäter hur långt du kan sträcka din vänstra axel."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Den här aktiviteten mäter hur långt du kan sträcka din högra axel."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Du börjar med att lägga enheten på din vänstra axel så att den kan mätas. Slå på ljudet på enheten så att du kan höra anvisningarna."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Du börjar med att lägga enheten på din högra axel så att den kan mätas. Slå på ljudet på enheten så att du kan höra anvisningarna."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Placera enheten på din vänstra axel med skärmen utåt (se bild)."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Placera enheten på din högra axel med skärmen utåt (se bild)."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "När du är klar trycker du på skärmen för att börja och höjer din vänstra arm så högt du kan. Återgå till startpositionen och tryck igen när du är klar."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "När du är klar trycker du på skärmen för att börja och höjer din högra arm så högt du kan. Återgå till startpositionen och tryck igen när du är klar."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Placera enheten på din vänstra axel. Tryck på skärmen och lyft din vänstra arm framåt så långt du kan."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Placera enheten på din högra axel. Tryck på skärmen och lyft din högra arm framåt så långt du kan."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "När du är klar återgår du till startpositionen för din vänstra arm. Tryck sedan var som helst på skärmen."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "När du är klar återgår du till startpositionen för din högra arm. Tryck sedan var som helst på skärmen."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Gång med tidtagning"; +"TIMED_WALK_INTRO_DETAIL" = "Den här aktiviteten mäter benfunktionen."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Hitta en plats, helst utomhus, där du kan gå ungefär %@ i en rät linje så fort som möjligt (men fortfarande säkert). Sakta inte ned förrän du har passerat mållinjen."; +"TIMED_WALK_INTRO_2_DETAIL" = "Tryck på Nästa för att börja."; +"TIMED_WALK_FORM_TITLE" = "Hjälpmedel"; +"TIMED_WALK_FORM_TEXT" = "Använd samma hjälpmedel för alla test."; +"TIMED_WALK_QUESTION_TEXT" = "Bär du en ankel- och fotortos?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Använder du ett hjälpmedel?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Tryck här för att välja ett svar."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Inget"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Ensidig käpp"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Ensidig krycka"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Dubbelsidig käpp"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Dubbelsidig krycka"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Gåstativ/rollator"; +"TIMED_WALK_INSTRUCTION_%@" = "Gå upp till %@ i en rät linje."; +"TIMED_WALK_INSTRUCTION_TURN" = "Vänd om."; +"TIMED_WALK_INSTRUCTION_2" = "Gå tillbaka till utgångsplatsen."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tryck på Nästa när du är klar."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "PASAT (Paced Auditory Serial Addition Test) mäter din auditiva bearbetningshastighet och beräkningsförmåga."; +"PVSAT_INTRO_TEXT" = "PVSAT (Paced Visual Serial Addition Test) mäter din visuella bearbetningshastighet och beräkningsförmåga."; +"PAVSAT_INTRO_TEXT" = "PAVSAT (Paced Auditory and Visual Serial Addition Test) mäter din auditiva och visuella bearbetningshastighet och beräkningsförmåga."; +"PSAT_INTRO_TEXT_2_%@" = "Ensiffriga tal visas med intervall på %@.\nDu måste addera varje nytt tal till talet som visades omedelbart före det.\nObs! Du ska inte beräkna en löpande totalsumma, utan bara summan av de senaste två talen."; +"PSAT_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"PSAT_INITIAL_INSTRUCTION" = "Kom ihåg den första siffran."; +"PSAT_INSTRUCTION" = "Addera det nya talet till det föregående."; +"PSAT_NO_DIGIT" = "–"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@-håls pegtest"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Den här aktiviteten mäter funktionen för dina övre extremiteter genom att be dig placera en pinne i ett hål. Du uppmanas att göra detta %@ gånger."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Både den vänstra och högra handen kommer att testas.\nDu måste plocka upp pinnen så fort som möjligt och placera den i hålet. När du har gjort det %@ gånger tar du bort den igen %@ gånger."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Både den högra och vänstra handen kommer att testas.\nDu måste plocka upp pinnen så fort som möjligt och placera den i hålet. När du har gjort det %@ gånger tar du bort den igen %@ gånger."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Placera pinnen i hålet med hjälp av vänster hand."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Placera pinnen i hålet med hjälp av höger hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Placera pinnen bakom strecket med hjälp av vänster hand."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Placera pinnen bakom strecket med hjälp av höger hand."; +"HOLE_PEG_TEST_TEXT" = "Lyft upp pinnen med två fingrar."; +"HOLE_PEG_TEST_TEXT_2" = "Släpp pinnen genom att lyfta på fingrarna."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremoraktivitet"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Den här aktiviteten mäter darrningarna i dina händer i olika positioner. Hitta en plats där du kan sitta bekvämt under hela den här aktiviteten."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Håll telefonen i den mer påverkade handen enligt bilden nedan."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Håll telefonen i den HÖGRA handen enligt bilden nedan."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Håll telefonen i den VÄNSTRA handen enligt bilden nedan."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Du blir ombedd att utföra %@ medan du sitter med telefonen i handen."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "en åtgärd"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "två åtgärder"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "tre åtgärder"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "fyra åtgärder"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "fem åtgärder"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Tryck på nästa för att fortsätta."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Förbered dig på att hålla telefonen i knät."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Förbered dig på att hålla telefonen i knät med den VÄNSTRA handen."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Förbered dig på att hålla telefonen i knät med den HÖGRA handen."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Fortsätt hålla telefonen i knät under %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Håll nu telefonen med handen utsträckt i axelhöjd."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Håll nu telefonen med den VÄNSTRA handen utsträckt i axelhöjd."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Håll nu telefonen med den HÖGRA handen utsträckt i axelhöjd."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Fortsätt hålla telefonen med handen utsträckt under %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Håll nu telefonen i axelhöjd med armbågen böjd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Håll nu telefonen med den VÄNSTRA handen i axelhöjd med armbågen böjd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Håll nu telefonen med den HÖGRA handen i axelhöjd med armbågen böjd."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Fortsätt hålla telefonen med armbågen böjd under %ld sekunder"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Nu ska du hålla armbågen böjd och röra vid näsan med telefonen flera gånger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Nu ska du hålla armbågen böjd med telefonen i den VÄNSTRA handen och röra vid näsan med telefonen flera gånger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Nu ska du hålla armbågen böjd med telefonen i den HÖGRA handen och röra vid näsan med telefonen flera gånger."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Fortsätt röra vid näsan med telefonen under %ld sekunder"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Förbered dig på att vinka kungligt (vinka genom att vrida på handleden)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Förbered dig på att vinka kungligt med telefonen i den VÄNSTRA handen (vinka genom att vrida på handleden)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Förbered dig på att vinka kungligt med telefonen i den HÖGRA handen (vinka genom att vrida på handleden)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Fortsätt utföra en kunglig vinkning under %ld sekunder."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Flytta nu telefonen till den VÄNSTRA handen och fortsätt med nästa åtgärd."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Flytta nu telefonen till den HÖGRA handen och fortsätt med nästa åtgärd."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Fortsätt till nästa åtgärd."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktiviteten är klar."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Du blir ombedd att utföra %@ medan du sitter med telefonen i ena handen, och sedan en gång till med den andra handen."; +"TREMOR_SKIP_LEFT_HAND" = "Jag kan inte utföra den här aktiviteten med VÄNSTRA handen."; +"TREMOR_SKIP_RIGHT_HAND" = "Jag kan inte utföra den här aktiviteten med HÖGRA handen."; +"TREMOR_SKIP_NEITHER" = "Jag kan utföra den här aktiviteten med båda händerna."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trail making test"; +"TRAILMAKING_INTENDED_USE" = "Den här aktiviteten utvärderar hur uppmärksam du är visuellt och hur bra du är på att växla mellan uppgifter genom att registrera tiden som krävs för att trycka på en serie med prickar i följd."; +"TRAILMAKING_INTENDED_USE2_A" = "När nedräkningen är slut ska du trycka på prickar med varannan gång siffror och varannan gång bokstäver. Börja genom att trycka på den första siffran ”1” och sedan på siffrorna ”2” – ”3” – ”4” osv. tills du kommer till siffran ”7”."; +"TRAILMAKING_INTENDED_USE2_B" = "När nedräkningen är slut ska du trycka på prickar med varannan gång siffror och varannan gång bokstäver. Börja genom att trycka på den första siffran ”1” och tryck sedan på den första bokstaven ”A”. Sedan ska du trycka på ”2” – ”B” – ”3” – ”C” osv. tills du kommer till siffran ”7”."; +"TRAILMAKING_INTRO_TEXT" = "Gör det här så snabbt du kan utan att göra några misstag. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Röstigenkänning"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Den här aktiviteten spelar in ditt tal med mikrofonen i nederkanten av enheten och översätter den till text."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Tryck på Kom igång för att börja."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Tryck på knappen för att starta inspelningen innan du talar."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Starta inspelning"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Stoppa inspelning"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Redigera utskrift"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Redigera utskriftstexten för att rätta eventuella feltolkningar av talet."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Din utskrift visas här."; +"SPEECH_RECOGNITION_FAILED" = "Röstigenkänning misslyckades."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Kunde inte starta röstigenkänning."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Spela upp ljud"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Stoppa ljud"; +"SPEECH_IN_NOISE_TITLE" = "Tal i brus"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Den här aktiviteten mäter hörförståelsen i bullriga miljöer."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Som en del av det här testet ska du:\n\nLyssna på en mening.\n\nTydligt upprepa det du hörde eller gå vidare för att skriva in det du hörde med tangentbordet. \n\nOm du upprepar det du hörde har du möjlighet att ändra utskriften som görs av röstigenkänningsmotorn."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Volymkalibrering"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Tryck på Spela upp ljud, justera volymen till en behaglig nivå och fortsätt sedan genom att trycka på Stoppa ljud."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Lyssna"; +"SPEECH_IN_NOISE_STEP_TEXT" = "En mening som är uppblandad med bakgrundsbrus med ett slumpmässigt signal-brusförhållande (SNR) kommer bara att spelas upp en gång."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Tal"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Upprepa det du hörde."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Kunde inte skapa fil"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Kunde inte ta bort tillräckligt många loggfiler för att nå tröskelvärdet"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Fel vid angivning av attribut"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Filen är inte markerad som raderad (ej markerad som öveförd)"; +"ERROR_DATALOGGER_MULTIPLE" = "Flera fel vid borttagning av loggar"; +"ERROR_RECORDER_NO_DATA" = "Inga insamlade data hittades."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Ingen utmatningskatalog har angetts"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Ljudtrycksmätare"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Den här aktiviteten mäter miljöns ljudtrycksnivå. Om bullernivåerna är för höga kan du inte fortsätta. Flytta till en tystare plats där du kan slutföra uppgiften eller gör om den här aktiviteten senare."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Beräknar"; +"ENVIRONMENTSPL_THRESHOLD" = "Tröskel: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Bakgrundsbrus OK"; +"ENVIRONMENTSPL_NOISE" = "För mycket bakgrundsljud"; +"ENVIRONMENTSPL_TITLE_2" = "Hitta en tyst plats"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "För att det här testet ska bli så exakt som möjligt bör det utföras i en tyst miljö."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Starta uppgiften"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Inga data"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Ange ett värde genom att flytta skjutreglaget"; +"SLIDER_I_DONT_KNOW" = "Jag vet inte"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Sida"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Tillbaka"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Visa PDF-miniatyr"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Göm PDF-miniatyr"; +"AX_BUTTON_ANNOTATE" = "Anteckna"; +"AX_BUTTON_SHOW_SEARCH" = "Visa sökfält"; +"AX_BUTTON_HIDE_SEARCH" = "Göm sökfält"; +"AX_BUTTON_SHARE" = "Dela"; + + +"AX_COMPLETION_ILLUSTRATION" = "Illustration av en bockmarkering i en blå cirkel som förmedlar ett lyckat resultat"; + +"AX_SIGNVIEW_LABEL" = "Tilldelat signaturfält"; +"AX_SIGNVIEW_HINT" = "Rör vid skärmen och signera genom att röra fingret"; +"AX_SIGNVIEW_SIGNED" = "Signerat"; +"AX_SIGNVIEW_UNSIGNED" = "Osignerat"; + +"AX_SELECTED" = "Markerat"; +"AX_UNSELECTED" = "Avmarkerat"; +"AX_SELECT_ALL_THAT_APPLY" = "MARKERA ALLT SOM GÄLLER"; + +"AX_SLIDER_LABEL" = "Svarsreglage. Intervall från %@ till %@"; +"AX_UNLABELED_IMAGE" = "Omärkt bild"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Påbörja åtgärd"; + +"AX.MEMORY.TILE.ACTIVE" = "aktiv"; +"AX.MEMORY.TILE.CORRECT" = "rätt"; +"AX.MEMORY.TILE.INCORRECT" = "fel"; +"AX.MEMORY.TILE.QUIESCENT" = "inaktiv"; +"AX.MEMORY.TILE.LABEL" = "Minnesspelbricka"; + +"AX_IMAGE_CAPTURE_LABEL" = "Spara förhandsvisning"; +"AX_IMAGE_CAPTURED_LABEL" = "Sparad bild"; + +"AX_VIDEO_CAPTURE_LABEL" = "Förhandsvisning av videoinspelning"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Videoinspelning klar"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Ka inte placera skivan med storleken %@ på skivan med storleken %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Mål"; +"AX_TOWER_OF_HANOI_TOWER" = "Torn"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Tryck snabbt två gånger för att placera skivan"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Tryck snabbt två gånger för att markera den översta skivan"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Har skivor med storlekarna %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Tomt"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Stäng tangentbord"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Intervall från %@ till %@"; +"AX_GRAPH_STACK_PREFIX" = "Trave som består av"; +"AX_GRAPH_AND_SEPARATOR" = " och "; +"AX_GRAPH_POINT_%@" = "Punkt: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Talvågform"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "När inspelningen börjar aktiverar du en andra tid för att stoppa inspelningen."; + +"AX_AUDIO_BAR_GRAPH" = "Ljudstapeldiagram"; + +"AX_AMSLER_GRID_LABEL" = "Amsler-nät"; +"AX_AMSLER_GRID_HINT" = "Använd fingret eller en ritpenna till att märka rutnätet, eller svep åt vänster utanför rutnätet för att avsluta."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Knappar som kan tryckas"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Tryck för vänster öra"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Aktivera när du vill starta testet. När testet startas trycker du direkt på den här knappen när du hör ett ljud i vänster öra."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Tryck för höger öra"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Aktivera när du vill starta testet. När testet startas trycker du direkt på den här knappen när du hör ett ljud i höger öra."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Rör vid skärmen för att utforska var knapparna för varje öra finns när du använder VoiceOver. När testet startas kan du trycka direkt på knapparna. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Tryck för ett finger"; +"AX_TAP_BUTTON_2_LABEL" = "Tryck för annat finger"; +"AX_TAP_BUTTON_HINT" = "Aktivera om du vill kunna trycka direkt på knapparna."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Rör vid skärmen för att utforska var knapparna finns när du använder VoiceOver. Aktivera en av knapparna så att du kan trycka på den direkt."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Nu kan du trycka direkt på knapparna."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Du kan trycka direkt på den här knappen när du använder VoiceOver. Den kommer att placeras nära mitten av skärmen."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Du kan trycka direkt på knapparna i testet när du använder VoiceOver."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Det går inte att avkoda restoreData för initiering"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..d20c3d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/sv.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d fel) + other + (%d fel) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.strings new file mode 100755 index 0000000..73a5165 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "ความยินยอม"; +"CONSENT_NAME_GIVEN" = "ชื่อ"; +"CONSENT_NAME_FAMILY" = "นามสกุล"; +"CONSENT_NAME_PLACEHOLDER" = "บังคับ"; +"CONSENT_REVIEW_TITLE" = "ตรวจทาน"; +"CONSENT_REVIEW_INSTRUCTION" = "ตรวจทานแบบฟอร์มด้านล่างแล้วแตะยอมรับหากคุณพร้อมดำเนินการต่อ"; +"CONSENT_REVIEW_ALERT_TITLE" = "ตรวจทาน"; +"CONSENT_SIGNATURE_TITLE" = "ลายเซ็น"; +"CONSENT_SIGNATURE_INSTRUCTION" = "โปรดเซ็นชื่อในช่องด้านล่างโดยใช้นิ้วของคุณ"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "เซ็นชื่อที่นี่"; +"CONSENT_PAGE_NUMBER_FORMAT" = "หน้า %1$ld จาก %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "ยินดีต้อนรับ"; +"CONSENT_SECTION_DATA_GATHERING" = "การรวบรวมข้อมูล"; +"CONSENT_SECTION_PRIVACY" = "ความเป็นส่วนตัว"; +"CONSENT_SECTION_DATA_USE" = "การใช้ข้อมูล"; +"CONSENT_SECTION_STUDY_SURVEY" = "การสำรวจการศึกษา"; +"CONSENT_SECTION_STUDY_TASKS" = "งานการศึกษา"; +"CONSENT_SECTION_TIME_COMMITMENT" = "เวลาดำเนินการ"; +"CONSENT_SECTION_WITHDRAWING" = "การถอนตัว"; +"CONSENT_LEARN_MORE_TITLE" = "เรียนรู้เพิ่มเติม"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "เรียนรู้เพิ่มเติมเกี่ยวกับวิธีรวบรวมข้อมูล"; +"LEARN_MORE_DATA_USE" = "เรียนรู้เพิ่มเติมเกี่ยวกับวิธีใช้ข้อมูล"; +"LEARN_MORE_PRIVACY" = "เรียนรู้เพิ่มเติมเกี่ยวกับวิธีการปกป้องความเป็นส่วนตัวและข้อมูลประจำตัวของคุณ"; +"LEARN_MORE_WELCOME" = "เรียนรู้เพิ่มเติมเกี่ยวกับการศึกษาก่อน"; +"LEARN_MORE_STUDY_SURVEY" = "เรียนรู้เพิ่มเติมเกี่ยวกับการสำรวจการศึกษา"; +"LEARN_MORE_TIME_COMMITMENT" = "เรียนรู้เพิ่มเติมเกี่ยวกับผลกระทบต่อเวลาของคุณของการศึกษา"; +"LEARN_MORE_TASKS" = "เรียนรู้เพิ่มเติมเกี่ยวกับงานที่เกี่ยวข้อง"; +"LEARN_MORE_WITHDRAWING" = "เรียนรู้เพิ่มเติมเกี่ยวกับการถอนตัว"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "ตัวเลือกการแชร์"; +"CONSENT_SHARE_WIDELY_%@" = "แบ่งปันข้อมูลกับ %@ และนักวิจัยที่ได้รับการรับรองทั่วโลก"; +"CONSENT_SHARE_ONLY_%@" = "แชร์ข้อมูลของฉันกับ %@ เท่านั้น"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ จะได้รับข้อมูลของคุณจากการเข้าร่วมการศึกษาข้อมูลของคุณในครั้งนี้\n\nการแชร์ข้อมูลจากการศึกษาของคุณกับคนอื่นที่ถูกเข้ารหัส (โดยไม่แชร์ข้อมูลอย่างเช่นชื่อของคุณ) อาจช่วยพัฒนาการวิจัยชิ้นนี้และชิ้นอื่นๆ ในอนาคตได้"; +"LEARN_MORE_CONSENT_SHARING" = "เรียนรู้เพิ่มเติมเกี่ยวกับการแชร์ข้อมูล"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "ชื่อเอกสาร"; +"CONSENT_DOC_LINE_SIGNATURE" = "ลายเซ็น"; +"CONSENT_DOC_LINE_DATE" = "วันที่"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ จาก %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "คำถามที่ %1$@ จาก %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "ข้ามไป"; +"REVIEW_EDIT_ANSWER" = "แก้ไข"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "ค่าไม่ถูกต้อง"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ เกินจำนวนค่าสูงสุดที่อนุญาต (%2$@)"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ น้อยกว่าค่าต่ำสุดที่อนุญาต (%2$@)"; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ ไม่ใช่ค่าที่ถูกต้อง"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "ที่อยู่อีเมลที่ไม่ถูกต้อง: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "ป้อนที่อยู่"; +"LOCATION_ERROR_TITLE" = "ไม่สามารถหาที่อยู่ที่ระบุได้"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "ไม่สามารถหาตำแหน่งที่ตั้งปัจจุบันของคุณได้ โปรดป้อนที่อยู่หรือไปอยู่ในที่ที่มีสัญญาณ GPS ที่ดีกว่านี้หากเป็นไปได้"; +"LOCATION_ERROR_MESSAGE_DENIED" = "การเข้าถึงบริการหาตำแหน่งที่ตั้งถูกปฏิเสธ โปรดอนุญาตให้แอพนี้ใช้บริการหาตำแหน่งที่ตั้งได้ผ่านทางการตั้งค่า"; +"LOCATION_ERROR_GEOCODE" = "ไม่มีผลการค้นหาสำหรับที่อยู่ที่ป้อน โปรดตรวจสอบให้แน่ใจว่าที่อยู่ถูกต้อง"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "คุณไม่ได้เชื่อมต่อกับอินเทอร์เน็ตหรือได้ค้นหาที่อยู่เกินจำนวนที่จำกัด ถ้าคุณไม่ได้เชื่อมต่อกับอินเทอร์เน็ต โปรดเปิด Wi-Fi ของคุณเพื่อตอบคำถามนี้ ถ้ามีปุ่มข้ามคุณจะสามารถข้ามคำถามนี้ได้ หรือกลับมาที่แบบสำรวจนี้เมื่อคุณเชื่อมต่อกับอินเทอร์เน็ต หรือโปรดรอสักครู่หนึ่งแล้วลองอีกครั้ง"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "เนื้อหาข้อความที่เกินจำนวนสูงสุด: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "ไม่สามารถใช้งานกล้องในหน้าจอแบบแยกได้"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "อีเมล"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "รหัสผ่าน"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "ป้อนรหัสผ่าน"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "ยืนยัน"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "ป้อนรหัสผ่านอีกครั้ง"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "รหัสผ่านไม่ตรงกัน"; +"ADDITIONAL_INFO_SECTION_TITLE" = "ข้อมูลเพิ่มเติม"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "เพศ"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "เลือกเพศ"; +"DOB_FORM_ITEM_TITLE" = "วันเกิด"; +"DOB_FORM_ITEM_PLACEHOLDER" = "เลือกวันที่"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "เบอร์โทรศัพท์"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "การยืนยัน"; +"VERIFICATION_STEP_TITLE" = "ยืนยันอีเมลของคุณ"; +"RESEND_EMAIL_LABEL_MESSAGE" = "แตะที่ลิงก์ข้างล่างหากคุณไม่ได้รับอีเมลสำหรับการยืนยันและต้องการที่จะให้ส่งอีเมลอีกครั้ง"; +"RESEND_EMAIL_BUTTON_TITLE" = "ส่งอีเมลการยืนยันอีกครั้ง"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "เข้าสู่ระบบ"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "ลืมรหัสผ่านหรือไม่"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "ป้อนรหัส"; +"PASSCODE_CONFIRM_MESSAGE" = "ยืนยันรหัส"; +"PASSCODE_SAVED_MESSAGE" = "บันทึกรหัสแล้ว"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "ตรวจสอบรหัสแล้ว"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "ป้อนรหัสเก่าของคุณ"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "ป้อนรหัสใหม่ของคุณ"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "ยืนยันรหัสใหม่ของคุณ"; +"PASSCODE_INVALID_ALERT_TITLE" = "รหัสไม่ถูกต้อง"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "รหัสไม่ตรงกัน ลองอีกครั้ง"; +"PASSCODE_TOUCH_ID_MESSAGE" = "โปรดใช้ Touch ID เพื่อตรวจสอบสิทธิ์"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID ผิดพลาด"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "เฉพาะตัวเลขเท่านั้น"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "สัญลักษณ์แสดงว่ากำลังป้อนรหัสอยู่"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "ตัวเลขที่ป้อนหลักที่ %@ จาก %@ หลัก"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "ลืมรหัสหรือไม่"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "ไม่สามารถเพิ่มรายการในพวงกุญแจได้"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "ไม่สามารถอัพเดทรายการในพวงกุญแจได้"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "ไม่สามารถลบรายการในพวงกุญแจได้"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "ไม่สามารถค้นหารายการในพวงกุญแจได้"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "ประเภท I"; +"FITZPATRICK_SKIN_TYPE_II" = "ประเภท II"; +"FITZPATRICK_SKIN_TYPE_III" = "ประเภท III"; +"FITZPATRICK_SKIN_TYPE_IV" = "ประเภท IV"; +"FITZPATRICK_SKIN_TYPE_V" = "ประเภท V"; +"FITZPATRICK_SKIN_TYPE_VI" = "ประเภท VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "หญิง"; +"GENDER_MALE" = "ชาย"; +"GENDER_OTHER" = "อื่นๆ"; + +/* Boolean answer strings */ +"BOOL_NO" = "ไม่"; +"BOOL_YES" = "ใช่"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "ซม."; +"MEASURING_UNIT_FT" = "ฟุต"; +"MEASURING_UNIT_IN" = "นิ้ว"; +"MEASURING_UNIT_KG" = "กก."; +"MEASURING_UNIT_LB" = "ปอนด์"; +"MEASURING_UNIT_OZ" = "ออนซ์"; + +/* Limb values. */ +"LIMB_LEFT" = "ซ้าย"; +"LIMB_RIGHT" = "ขวา"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "แตะเพื่อตอบ"; +"NULL_ANSWER" = "เลือกคำตอบ"; +"PLACEHOLDER_IMAGE_CHOICES" = "แตะเพื่อเลือก"; +"PLACEHOLDER_LONG_TEXT" = "แตะเพื่อเขียน"; + +/* Button titles */ +"BUTTON_AGREE" = "ยอมรับ"; +"BUTTON_CANCEL" = "ยกเลิก"; +"BUTTON_OK" = "ตกลง"; +"BUTTON_CLEAR" = "ล้าง"; +"BUTTON_CLEAR_SIGNATURE" = "ล้างลายเซ็น"; +"BUTTON_APPLY" = "ปรับใช้"; +"BUTTON_DISAGREE" = "ไม่ยอมรับ"; +"BUTTON_DONE" = "เสร็จ"; +"BUTTON_GET_STARTED" = "เริ่มต้นใช้งาน"; +"BUTTON_LEARN_MORE" = "เรียนรู้เพิ่มเติม"; +"BUTTON_NEXT" = "ถัดไป"; +"BUTTON_SKIP" = "ข้าม"; +"BUTTON_SKIP_QUESTION" = "ข้ามคำถามนี้"; +"BUTTON_START_TIMER" = "เริ่มจับเวลา"; +"BUTTON_OPTION_SAVE" = "บันทึกไว้ใช้ภายหลัง"; +"BUTTON_OPTION_DISCARD" = "ทิ้งผลลัพธ์"; +"BUTTON_OPTION_STOP_TASK" = "สิ้นสุดงาน"; +"BUTTON_SAVE" = "บันทึก"; +"BUTTON_CLEAR_ANSWER" = "ล้างคำตอบ"; +"BUTTON_READ_ONLY_MODE" = "ไม่สามารถแก้ไขคำตอบนี้ได้"; +"BUTTON_COPYRIGHT" = "ลิขสิทธิ์"; +"BUTTON_CLOSE" = "ปิด"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "กำลังจะเริ่มกิจกรรมใน"; +"TASK_COMPLETE_TITLE" = "กิจกรรมสำเร็จ"; +"TASK_COMPLETE_TEXT" = "ข้อมูลของคุณจะได้รับการวินิจฉัยและคุณจะได้รับแจ้งเมื่อได้ผลลัพธ์ของคุณแล้ว"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "เหลือ %@"; +"TOUCH_ANYWHERE_LABEL" = "แตะที่ใดก็ได้เพื่อดำเนินการต่อ"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "จับภาพ"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "จับภาพอีกครั้ง"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "ไม่พบกล้อง ไม่สามารถทำขั้นตอนนี้ได้"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "ในการทำขั้นตอนนี้ อนุญาตให้แอพนี้เข้าถึงกล้องได้ในการตั้งค่า"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "ไม่ได้ระบุไดเรกทอรีสำหรับรูปภาพที่จับภาพ"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "ไม่สามารถบันทึกรูปภาพที่จับภาพได้"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "เริ่มบันทึกเสียง"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "หยุดบันทึกเสียง"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "ถ่ายวิดีโออีกครั้ง"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "ฟิตเนส"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "ระยะทาง (%@)"; +"FITNESS_HEARTRATE_TITLE" = "อัตราการเต้นของหัวใจ (bpm)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "นั่งสบายๆ นาน %@"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "เดินให้เร็วที่สุดเท่าที่คุณทำได้นาน %@"; +"FITNESS_INTRO_TEXT_FORMAT" = "กิจกรรมนี้จะตรวจสอบอัตราการเต้นของหัวใจของคุณและวัดระยะทางที่คุณสามารถเดินได้ภายใน %1$@"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "เดินกลางแจ้งด้วยอัตราการเดินที่เร็วที่สุดที่คุณทำได้นาน %1$@ เมื่อคุณเดินเสร็จแล้ว ให้นั่งพักสบายๆ นาน %2$@ ในการเริ่มต้น ให้แตะเริ่มต้นใช้งาน"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "ท่าเดินและความสมดุล"; +"WALK_INTRO_TEXT" = "กิจกรรมนี้จะวัดการเดินรวมทั้งความสมดุลของคุณในขณะเดินและยืนนิ่งๆ อย่าดำเนินการต่อหากคุณไม่สามารถเดินได้อย่างปลอดภัยโดยที่ไม่มีตัวช่วยแล้ว"; +"WALK_INTRO_2_TEXT_%ld" = "ค้นหาที่ที่คุณสามารถเดินเป็นเส้นตรงได้ไกลประมาณ %ld ก้าวได้อย่างปลอดภัยโดยไม่ต้องมีสิ่งช่วยเหลือ"; +"WALK_INTRO_2_DETAIL" = "ใส่อุปกรณ์ไว้ในกระเป๋ากางเกงหรือกระเป๋าแล้วทำตามคำแนะนำด้วยเสียง"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "ตอนนี้ให้ยืนนิ่งๆ นาน %@"; +"WALK_STAND_INSTRUCTION_FORMAT" = "ยืนนิ่งๆ นาน %@"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "หันหลัง แล้วเดินกลับไปจุดเริ่มต้น"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "เดินตรงขึ้นไป %ld ก้าว"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "หาสถานที่ที่คุณสามารถเดินไปมาเป็นเส้นตรงได้อย่างปลอดภัย ให้ลองเดินไปเรื่อยๆ จนสุดทางแล้วเดินกลับ เสมือนคุณเดินวนรอบกรวย\n\nจากนั้นระบบจะแนะนำให้คุณกลับหลังหัน แล้วยืนนิ่งๆ โดยแนบแขนไว้ข้างลำตัวและวางเท้าให้ห่างกันเท่ากับความกว้างของหัวไหล่"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "แตะเริ่มต้นกันเมื่อคุณพร้อมที่จะเริ่ม\nจากนั้นใส่อุปกรณ์ของคุณไว้ในกระเป๋ากางเกงหรือกระเป๋าแล้วทำตามคำแนะนำด้วยเสียง"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "เดินไปมาเป็นเส้นตรงนาน %@ โดยให้คุณเดินตามปกติ"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "กลับหลังหันแล้วยืนนิ่งๆ นาน %@"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "คุณทำกิจกรรมสำเร็จแล้ว"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "ความเร็วของการแตะ"; +"TAPPING_TASK_TITLE_RIGHT" = "มือขวา"; +"TAPPING_TASK_TITLE_LEFT" = "มือซ้าย"; +"TAPPING_INTRO_TEXT" = "กิจกรรมนี้จะวัดความเร็วในการแตะของคุณ"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "วางอุปกรณ์ของคุณไว้บนพื้นผิวที่ราบเรียบ"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "ใช้นิ้วมือข้างเดียวกันสองนิ้วแตะสลับกันที่ปุ่มบนหน้าจอ"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "ใช้นิ้วมือข้างขวาสองนิ้วแตะสลับกันที่ปุ่มบนหน้าจอ"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "ใช้นิ้วมือข้างซ้ายสองนิ้วแตะสลับกันที่ปุ่มบนหน้าจอ"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "ตอนนี้ให้ทดสอบแบบเดียวกันซ้ำอีกครั้งโดยใช้มือขวา"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "ตอนนี้ให้ทดสอบแบบเดียวกันซ้ำอีกครั้งโดยใช้มือซ้าย"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "แตะหนึ่งนิ้ว แล้วตามด้วยอีกนิ้ว ลองจับเวลาการแตะของคุณโดยให้มีจังหวะเท่ากันมากที่สุด แตะต่อไปเรื่อยๆ เป็นเวลา %@"; +"TAPPING_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"TAPPING_CALL_TO_ACTION_NEXT" = "แตะถัดไปเพื่อเริ่ม"; +"TAP_BUTTON_TITLE" = "แตะ"; +"TOTAL_TAPS_LABEL" = "การแตะทั้งหมด"; +"TAPPING_INSTRUCTION" = "ใช้สองนิ้วแตะปุ่มโดยลงน้ำหนักให้สม่ำเสมอที่สุดเท่าที่จะทำได้"; +"TAPPING_INSTRUCTION_RIGHT" = "ใช้มือขวาแตะปุ่ม"; +"TAPPING_INSTRUCTION_LEFT" = "ใช้มือซ้ายแตะปุ่ม"; +"TAPPING_SKIP_TITLE" = "ข้ามมือข้างนี้"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "ตาราง Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "กิจกรรมนี้ช่วยตรวจหาปัญหาสายตาของผู้ใช้"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "ถืออุปกรณ์ให้ห่างจากใบหน้าของคุณเป็นระยะ 12 นิ้วในระดับสายตาตลอดการทดสอบ"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "ปิด %@ ของคุณแล้วจ้องที่จุดตรงกึ่งกลางของตารางสี่เหลี่ยมจัตุรัส\n\nใช้นิ้วหรือปากกาสไตลัสทำเครื่องหมายบนตำแหน่งใดๆ ที่คุณเห็นว่าบิดเบี้ยว เช่น เส้นที่พร่ามัวหรือเส้นหยัก\n\nเมื่อเสร็จแล้ว ให้ปัดไปทางซ้ายที่ตำแหน่งใดก็ได้นอกตาราง"; +"AMSLER_GRID_LEFT_EYE" = "ตาข้างซ้าย"; +"AMSLER_GRID_RIGHT_EYE" = "ตาข้างขวา"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "เสียง"; +"AUDIO_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"AUDIO_INSTRUCTION" = "พูด “อาาาาา” ใส่ไมโครโฟนให้นานที่สุดเท่าที่คุณจะทำได้"; +"AUDIO_INTRO_TEXT" = "สูดลมหายใจเข้าลึกๆ แล้วพูด “อาาาาา” ใส่ไมโครโฟนให้นานที่สุดเท่าที่คุณจะทำได้ ให้ออกเสียงด้วยความดังที่คงที่เพื่อให้แถบเสียงคงสีฟ้าไว้"; +"AUDIO_INTENDED_USE" = "กิจกรรมนี้จะประเมินเสียงของคุณโดยใช้ไมโครโฟนที่อยู่ด้านล่างสุดของอุปกรณ์ของคุณบันทึกเสียง"; +"AUDIO_TOO_LOUD_LABEL" = "ดังเกินไป"; +"AUDIO_GENERIC_ERROR_LABEL" = "ไม่สามารถบันทึกเสียงได้"; +"AUDIO_LEVEL_CHECK_LABEL" = "โปรดรอในระหว่างที่เราตรวจสอบระดับเสียงรบกวนรอบข้าง"; +"AUDIO_TOO_LOUD_MESSAGE" = "ระดับเสียงแวดล้อมดังเกินกว่าที่จะบันทึกเสียงของคุณได้ โปรดย้ายไปอยู่บริเวณที่มีเสียงเบากว่านี้แล้วลองอีกครั้ง"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "แตะถัดไปเมื่อพร้อม"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "ตรวจวัดการได้ยิน"; +"TONE_AUDIOMETRY_INTENDED_USE" = "กิจกรรมนี้จะวัดความสามารถของคุณในการฟังเสียงต่างๆ"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "ก่อนที่คุณจะเริ่มต้น ให้เสียบสายและสวมหูฟังของคุณ\n\nเสียงจะเบามากและไม่เหมือนกับเสียงเตือนทั่วไป  เสียงจะเริ่มต้นอย่างเบาๆ และจะเพิ่มความดังขึ้นอย่างช้าๆ  โปรดตั้งใจฟังแล้วแตะปุ่มซ้ายหรือปุ่มขวาเพื่อระบุหูข้างที่คุณได้ยินเสียง"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"TONE_AUDIOMETRY_PREP_TEXT" = "ตอนนี้คุณควรจะได้ยินเสียงเตือน ให้ปรับความดังเสียงโดยใช้ตัวควบคุมที่อยู่ด้านข้างอุปกรณ์ของคุณ\n\nแตะปุ่มใดก็ได้เมื่อคุณพร้อมที่จะเริ่มต้นแล้ว"; +"TONE_AUDIOMETRY_INSTRUCTION" = "ทุกๆ ครั้งที่คุณเริ่มได้ยินเสียง ให้แตะปุ่มซ้ายหรือปุ่มขวาเพื่อระบุหูข้างที่คุณได้ยินเสียง"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "หูข้างซ้าย"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "หูข้างขวา"; +"TONE_LABEL_%@_LEFT" = "%@ Hz ซ้าย"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz ขวา"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "ตรวจวัดการได้ยิน"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "แตะเมื่อคุณได้ยินเสียง"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "เสียงและระดับเสียง"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "คุณจะได้ยินเสียงต่อเนื่องกันหลายเสียง"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "เมื่อคุณได้ยินเสียง ให้แตะบนปุ่ม"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "สำหรับการทดสอบนี้ ระดับความดังจะถูกตั้งอยู่ที่ 50 เปอร์เซ็นต์"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "การทดสอบนี้ใช้เวลาประมาณ 10 นาที"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "เปิดใช้ห้ามรบกวนเพื่อหลีกเลี่ยงการขัดจังหวะ"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "เสียงจะดังครั้งแรกในหูข้างขวาของคุณ"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "เสียงจะดังในหูข้างซ้ายของคุณ"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "กิจกรรมนี้จะระบุระดับเกณฑ์การได้ยินของบุคคลเป็น dB HL"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "ตรวจสอบให้แน่ใจว่าระดับเสียงของอุปกรณ์ตั้งอยู่ที่ระดับสูงสุด\n\nในระหว่างงานนี้ จะมีเสียงเบาๆ เล่นในหูข้างซ้ายหรือข้างขวา\n\nตั้งใจฟังให้ดี แล้วแตะปุ่มทุกครั้งที่คุณได้ยินเสียง"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "การทดสอบนี้ตรวจสอบว่าควรมีระดับความดังของเสียงเท่าไหร่ที่คุณสามารถได้ยิน"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "คำแนะนำแบบสอบถาม"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "ถ้ามี ‘หูข้างที่ถนัด’ ให้เลือกหูข้างนั้น"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "ซ้าย"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "ขวา"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "ไม่มีข้างที่ถนัด"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "การทดสอบถูกยกเลิก"; +"dBHL_ALERT_TITLE_START_OVER" = "เริ่มอีกครั้ง"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "ยกเลิกการทดสอบ"; +"dBHL_ALERT_TEXT" = "เชื่อมต่อกับ AirPods หรือ EarPods ของคุณอีกครั้งเพื่อทำการทดสอบนี้"; +"dBHL_PROGRESS_COMPLETION_%@" = "สำเร็จ %@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "หูฟัง"; +"HEADPHONES_UNKNOWN" = "ไม่ทราบชื่อ"; +"HEADPHONES_NONE" = "ไม่มี"; +"CONNECTED" = "เชื่อมต่ออยู่"; +"NOT_CONNECTED" = "ไม่ได้เชื่อมต่อ"; +"HEADPHONE_CONNECTED_%@" = "%@ - เชื่อมต่ออยู่"; +"HEADPHONE_DETECT_TITLE" = "เชื่อมต่อกับหูฟังของคุณ"; +"HEADPHONE_DETECT_TEXT" = "การทดสอบนี้ต้องใช้ Apple AirPods หรือ Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "ความจำเชิงพื้นที่"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "กิจกรรมนี้จะวัดความจำเชิงพื้นที่ระยะสั้นของคุณโดยจะขอให้คุณทวนลำดับการสว่างขึ้นของ%@"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "ดอกไม้"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "ดอกไม้"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "%@บางตัวจะสว่างขึ้นครั้งละหนึ่งตัว ให้แตะ%@เหล่านั้นแบบตามลำดับการสว่าง"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "%@บางตัวจะสว่างขึ้นครั้งละหนึ่งตัว ให้แตะ%@เหล่านั้นแบบย้อนลำดับการสว่าง"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "ในการเริ่มต้น ให้แตะเริ่มต้นใช้งาน แล้วจับตาดูอย่างใกล้ชิด"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "คะแนน"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "ดู%@สว่างขึ้น"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "แตะ%@ตามลำดับการสว่างขึ้น"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "แตะ%@แบบย้อนกลับลำดับ"; +"MEMORY_GAME_COMPLETE_TITLE" = "ลำดับสำเร็จ"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "ในการดำเนินการต่อ ให้แตะถัดไป"; +"MEMORY_GAME_FAILED_TITLE" = "ลองอีกครั้ง"; +"MEMORY_GAME_FAILED_MESSAGE" = "คุณทำได้ไม่ค่อยดีนักในครั้งที่ผ่านมา ให้แตะถัดไปเพื่อดำเนินการต่อ"; +"MEMORY_GAME_TIMEOUT_TITLE" = "หมดเวลา"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "หมดเวลาแล้ว\nให้แตะถัดไปเพื่อดำเนินการต่อ"; +"MEMORY_GAME_COMPLETE" = "เกมสำเร็จ"; +"MEMORY_GAME_PAUSED_TITLE" = "พักอยู่"; +"MEMORY_GAME_PAUSED_MESSAGE" = "ในการดำเนินการต่อ ให้แตะถัดไป"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "กิจกรรมด้านความจำได้รับการพัฒนาโดยอาศัยความช่วยเหลือจาก ศ. Katherine Possin และ ศ. Joel Kramer จาก University of California, ซานฟรานซิสโก"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "เวลาตอบสนอง"; +"REACTION_TIME_TASK_INTENDED_USE" = "กิจกรรมนี้จะประเมินเวลาที่คุณใช้ในการตอบสนองต่อการมองเห็น"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "เขย่าอุปกรณ์ในทิศทางใดก็ได้ทันทีที่มีจุดสีน้ำเงินปรากฏขึ้นมาบนหน้าจอ ระบบจะขอให้คุณทำสิ่งนี้ %D ครั้ง"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "ความพยายาม %@ จาก %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "เขย่าอุปกรณ์อย่างรวดเร็วเมื่อมีวงกลมสีนำ้เงินปรากฏขึ้น"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "ทุกๆ ครั้งที่มีคำปรากฏขึ้นมา ให้เลือกตัวอักษรตัวแรกของชื่อสีที่ปรากฏ"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "เมื่อคุณพร้อมที่จะเริ่มต้นกิจกรรม Stroop แล้ว ให้แตะเริ่มต้นใช้งาน"; +"STROOP_TASK_STEP_TEXT" = "เลือกตัวอักษรแรกของชื่อสีที่ปรากฏขึ้น"; +"STROOP_COLOR_RED" = "RED"; +"STROOP_COLOR_GREEN" = "GREEN"; +"STROOP_COLOR_BLUE" = "BLUE"; +"STROOP_COLOR_YELLOW" = "YELLOW"; +"STROOP_COLOR_RED_INITIAL" = "R"; +"STROOP_COLOR_GREEN_INITIAL" = "G"; +"STROOP_COLOR_BLUE_INITIAL" = "B"; +"STROOP_COLOR_YELLOW_INITIAL" = "Y"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "หอคอยแห่งฮานอย"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "กิจกรรมนี้จะประเมินทักษะในการไขปริศนาของคุณ"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "ย้ายทั้งกองไปที่แท่นวางที่ไฮไลท์ไว้โดยเคลื่อนย้ายให้น้อยที่สุดเท่าที่จะทำได้"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "ไขปริศนา"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "จำนวนการเคลื่อนย้าย: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "ฉันไขปริศนานี้ไม่ได้"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "พิสัยการเคลื่อนไหว"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption จะต้องเป็นข้างซ้ายหรือข้างขวา"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "พิสัยการเคลื่อนไหวของเข่าข้างซ้าย"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "พิสัยการเคลื่อนไหวของเข่าข้างขวา"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "กิจกรรมนี้จะวัดว่าคุณสามารถเหยียดเข่าข้างซ้ายของคุณได้มากสุดเท่าใด"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "กิจกรรมนี้จะวัดว่าคุณสามารถเหยียดเข่าข้างขวาของคุณได้มากสุดเท่าใด"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "นั่งตรงขอบของเก้าอี้ เมื่อคุณเริ่มต้นคุณจะต้องวางอุปกรณ์ไว้บนเข่าข้างซ้ายของคุณสำหรับการวัด โปรดเปิดเสียงบนอุปกรณ์ของคุณเพื่อให้คุณสามารถฟังขั้นตอนได้"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "นั่งตรงขอบของเก้าอี้ เมื่อคุณเริ่มต้นคุณจะต้องวางอุปกรณ์ไว้บนเข่าข้างขวาของคุณสำหรับการวัด โปรดเปิดเสียงบนอุปกรณ์ของคุณเพื่อให้คุณสามารถฟังขั้นตอนได้"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "วางอุปกรณ์ไว้บนเข่าข้างซ้ายของคุณพร้อมกับหงายหน้าจอขึ้น ดังภาพ"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "วางอุปกรณ์ไว้บนเข่าข้างขวาของคุณพร้อมกับหงายหน้าจอขึ้น ดังภาพ"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "เมื่อคุณพร้อม ให้แตะหน้าจอเพื่อเริ่มต้น แล้วเหยียดเข่าข้างซ้ายของคุณให้มากที่สุดเท่าที่คุณทำได้ จากนั้นนำกลับมาที่ตำแหน่งเริ่มต้นแล้วแตะอีกครั้งเมื่อคุณทำเสร็จ"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "เมื่อคุณพร้อม ให้แตะหน้าจอเพื่อเริ่มต้น แล้วเหยียดเข่าข้างขวาของคุณให้มากที่สุดเท่าที่คุณทำได้ จากนั้นนำกลับมาที่ตำแหน่งเริ่มต้นแล้วแตะอีกครั้งเมื่อคุณทำเสร็จ"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "วางอุปกรณ์ไว้บนเข่าข้างซ้ายของคุณ แตะหน้าจอแล้วเหยียดเข่าข้างซ้ายของคุณให้มากที่สุดเท่าที่คุณทำได้"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "วางอุปกรณ์ไว้บนเข่าข้างขวาของคุณ แตะหน้าจอแล้วเหยียดเข่าข้างขวาของคุณให้มากที่สุดเท่าที่คุณทำได้"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "เมื่อคุณทำเสร็จ นำเข่าข้างซ้ายของคุณกลับมาที่ตำแหน่งเริ่มต้น จากนั้นแตะที่ใดก็ได้"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "เมื่อคุณทำเสร็จ นำเข่าข้างขวาของคุณกลับมาที่ตำแหน่งเริ่มต้น จากนั้นแตะที่ใดก็ได้"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "พิสัยการเคลื่อนไหวของไหล่ข้างซ้าย"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "พิสัยการเคลื่อนไหวของไหล่ข้างขวา"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "กิจกรรมนี้จะวัดว่าคุณสามารถยืดไหล่ข้างซ้ายของคุณได้มากสุดเท่าใด"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "กิจกรรมนี้จะวัดว่าคุณสามารถยืดไหล่ข้างขวาของคุณได้มากสุดเท่าใด"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "เมื่อคุณเริ่มต้น คุณจะต้องวางอุปกรณ์ของคุณบนไหล่ข้างซ้ายของคุณเพื่อการวัด โปรดเปิดเสียงบนอุปกรณ์ของคุณเพื่อให้คุณสามารถฟังขั้นตอนได้"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "เมื่อคุณเริ่มต้น คุณจะต้องวางอุปกรณ์ของคุณบนไหล่ข้างขวาของคุณเพื่อการวัด โปรดเปิดเสียงบนอุปกรณ์ของคุณเพื่อให้คุณสามารถฟังขั้นตอนได้"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "วางอุปกรณ์ไว้บนไหล่ข้างซ้ายของคุณพร้อมกับหงายหน้าจอขึ้น ดังภาพ"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "วางอุปกรณ์ไว้บนไหล่ข้างขวาของคุณพร้อมกับหงายหน้าจอขึ้น ดังภาพ"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "เมื่อคุณพร้อม ให้แตะหน้าจอเพื่อเริ่มต้น แล้วยกแขนข้างซ้ายของคุณให้สูงที่สุดเท่าที่คุณทำได้ จากนั้นนำกลับมาที่ตำแหน่งเริ่มต้นแล้วแตะอีกครั้งเมื่อคุณทำเสร็จ"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "เมื่อคุณพร้อม ให้แตะหน้าจอเพื่อเริ่มต้น แล้วยกแขนข้างขวาของคุณให้สูงที่สุดเท่าที่คุณทำได้ จากนั้นนำกลับมาที่ตำแหน่งเริ่มต้นแล้วแตะอีกครั้งเมื่อคุณทำเสร็จ"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "วางอุปกรณ์ไว้บนไหล่ข้างซ้ายของคุณ แตะหน้าจอแล้วยกแขนซ้ายของคุณไปข้างหน้าให้ไกลมากที่สุดเท่าที่คุณทำได้"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "วางอุปกรณ์ไว้บนไหล่ข้างขวาของคุณ แตะหน้าจอแล้วยกแขนขวาของคุณไปข้างหน้าให้ไกลมากที่สุดเท่าที่คุณทำได้"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "เมื่อคุณทำเสร็จ นำแขนข้างซ้ายของคุณกลับมาที่ตำแหน่งเริ่มต้น จากนั้นแตะที่ใดก็ได้"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "เมื่อคุณทำเสร็จ นำแขนข้างขวาของคุณกลับมาที่ตำแหน่งเริ่มต้น จากนั้นแตะที่ใดก็ได้"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "การเดินแบบจับเวลา"; +"TIMED_WALK_INTRO_DETAIL" = "กิจกรรมนี้จะประเมินการทำหน้าที่ของรยางค์ล่างของคุณ"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "ค้นหาสถานที่ โดยเฉพาะบริเวณกลางแจ้ง ซึ่งคุณสามารถเดินเป็นเส้นตรงในระยะทางประมาณ %@ ได้เร็วที่สุดเท่าที่จะทำได้อย่างปลอดภัย อย่าลดความเร็วลงจนกว่าคุณจะเดินผ่านจุดสิ้นสุด"; +"TIMED_WALK_INTRO_2_DETAIL" = "แตะถัดไปเพื่อเริ่ม"; +"TIMED_WALK_FORM_TITLE" = "อุปกรณ์ช่วยเหลือ"; +"TIMED_WALK_FORM_TEXT" = "ใช้อุปกรณ์ช่วยเหลืออันเดียวกันสำหรับการทดสอบแต่ละครั้ง"; +"TIMED_WALK_QUESTION_TEXT" = "คุณสวมอุปกรณ์เสริมสำหรับเท้าและข้อเท้าหรือไม่"; +"TIMED_WALK_QUESTION_2_TITLE" = "คุณใช้อุปกรณ์ช่วยเหลือหรือไม่"; +"TIMED_WALK_QUESTION_2_TEXT" = "แตะที่นี่เพื่อเลือกคำตอบ"; +"TIMED_WALK_QUESTION_2_CHOICE" = "ไม่มี"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "ไม้เท้าแบบข้างเดียว"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "ไม้ค้ำยันแบบข้างเดียว"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "ไม้เท้าแบบสองข้าง"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "ไม้ค้ำยันแบบสองข้าง"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "วอล์กเกอร์/รถเข็นหัดเดิน"; +"TIMED_WALK_INSTRUCTION_%@" = "เดินเป็นเส้นตรงให้ได้ระยะทาง %@"; +"TIMED_WALK_INSTRUCTION_TURN" = "หันหลังกลับ"; +"TIMED_WALK_INSTRUCTION_2" = "เดินกลับไปที่จุดเริ่มต้น"; +"TIMED_WALK_INSTRUCTION_TEXT" = "แตะถัดไปเมื่อสำเร็จ"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "การทดสอบความสามารถผ่านการบวกเลขตามความเร็วที่ได้ยินจะประเมินข้อมูลด้านการได้ยินของคุณโดยการประมวลผลความเร็วและความสามารถด้านการคิดคำนวณ"; +"PVSAT_INTRO_TEXT" = "การทดสอบความสามารถผ่านการบวกเลขตามความเร็วที่มองเห็นจะประเมินข้อมูลด้านการมองเห็นของคุณโดยการประมวลผลความเร็วและความสามารถด้านการคิดคำนวณ"; +"PAVSAT_INTRO_TEXT" = "การทดสอบความสามารถผ่านการบวกเลขตามความเร็วที่ได้ยินและมองเห็นจะประเมินข้อมูลด้านการได้ยินและการมองเห็นของคุณโดยการประมวลผลความเร็วและความสามารถด้านการคิดคำนวณ"; +"PSAT_INTRO_TEXT_2_%@" = "ตัวเลขแต่ละตัวจะแสดงทุก %@\nคุณต้องเพิ่มตัวเลขใหม่หนึ่งตัวต่อท้ายตัวเลขก่อนหน้านี้โดยทันที\nโปรดทราบว่าคุณต้องไม่คำนวณผลรวมของตัวเลขที่เรียงต่อกันทั้งหมด แต่คำนวณเฉพาะผลรวมของตัวเลขสองจำนวนสุดท้ายเท่านั้น"; +"PSAT_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"PSAT_INITIAL_INSTRUCTION" = "จดจำตัวเลขตัวแรกนี้"; +"PSAT_INSTRUCTION" = "เพิ่มตัวเลขตัวใหม่นี้ไปที่ตัวเลขก่อนหน้า"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "การทดสอบวางหมุด %@ ครั้ง"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "การกระทำนี้จะวัดความสามารถของการใช้นิ้วมือของคุณโดยที่คุณจะต้องวางหมุดลงในช่อง คุณจะต้องทำการวางหมุด %@ ครั้ง"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "ทั้งมือซ้ายและมือขวาของคุณจะถูกทดสอบ\nคุณจะต้องหยิบหมุดให้ไวที่สุดเท่าที่จะทำได้ แล้ววางหมุดลงในช่อง ทำซ้ำ %@ ครั้ง จากนั้นให้หยิบหมุดออกจากช่อง %@ ครั้ง"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "ทั้งมือขวาและมือซ้ายของคุณจะถูกทดสอบ\nคุณต้องหยิบหมุดให้ไวที่สุดเท่าที่จะทำได้ แล้ววางหมุดลงในช่อง ทำซ้ำ %@ ครั้ง จากนั้นให้หยิบหมุดออกจากช่อง %@ ครั้ง"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "ใช้มือซ้ายหยิบหมุดวางลงในช่อง"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "ใช้มือขวาหยิบหมุดวางลงในช่อง"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "ใช้มือซ้ายหยิบหมุดวางไว้ข้างหลังเส้น"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "ใช้มือขวาหยิบหมุดวางไว้ข้างหลังเส้น"; +"HOLE_PEG_TEST_TEXT" = "ใช้นิ้วสองนิ้วหยิบหมุด"; +"HOLE_PEG_TEST_TEXT_2" = "ปล่อยนิ้วเพื่อปล่อยหมุด"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "กิจกรรมวัดอาการสั่น"; +"TREMOR_TEST_INTRO_1_DETAIL" = "กิจกรรมนี้เป็นตัววัดอาการสั่นของมือคุณในอิริยาบทต่างๆ โปรดหาสถานที่ที่คุณสามารถนั่งได้อย่างสบายๆ ในระหว่างที่ทำกิจกรรมนี้"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "ถือโทรศัพท์ไว้ในมือข้างที่มีอาการสั่นมากกว่าตามที่แสดงในรูปภาพด้านล่าง"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "ถือโทรศัพท์ไว้ในมือขวาตามที่แสดงในรูปภาพด้านล่าง"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "ถือโทรศัพท์ไว้ในมือซ้ายตามที่แสดงในรูปภาพด้านล่าง"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "ระบบจะขอให้คุณทำ%@ในระหว่างที่นั่งถือโทรศัพท์ไว้ในมือ"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "หนึ่งงาน"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "สองงาน"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "สามงาน"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "สี่งาน"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "ห้างาน"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "แตะถัดไปเพื่อทำต่อ"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "เตรียมถือโทรศัพท์ของคุณไว้บนตัก"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "เตรียมถือโทรศัพท์ของคุณไว้บนตักโดยใช้มือซ้าย"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "เตรียมถือโทรศัพท์ของคุณไว้บนตักโดยใช้มือขวา"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "ถือโทรศัพท์ของคุณไว้นิ่งๆ บนตักนาน %ld วินาที"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "ตอนนี้ให้วางโทรศัพท์ของคุณบนฝ่ามือแล้วถือไว้นิ่งๆ ที่ความสูงระดับไหล่"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "ตอนนี้ให้วางโทรศัพท์ของคุณบนฝ่ามือข้างซ้ายแล้วถือไว้นิ่งๆ ที่ความสูงระดับไหล่"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "ตอนนี้ให้วางโทรศัพท์ของคุณบนฝ่ามือข้างขวาแล้วถือไว้นิ่งๆ ที่ความสูงระดับไหล่"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "วางโทรศัพท์ของคุณบนฝ่ามือแล้วถือไว้นิ่งๆ นาน %ld วินาที"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "ตอนนี้ให้ถือโทรศัพท์ที่ความสูงระดับไหล่โดยงอข้อศอกของคุณไว้"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "ตอนนี้ให้ใช้มือซ้ายถือโทรศัพท์ที่ความสูงระดับไหล่โดยงอข้อศอกของคุณไว้"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "ตอนนี้ให้ใช้มือขวาถือโทรศัพท์ที่ความสูงระดับไหล่โดยงอข้อศอกของคุณไว้"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "ถือโทรศัพท์ของคุณไว้นิ่งๆ โดยงอข้อศอกนาน %ld วินาที"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "ตอนนี้ให้งอข้อศอกของคุณไว้นิ่งๆ แล้วเอาโทรศัพท์มาแตะที่จมูกแบบสลับไปมาซ้ำๆ"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "ตอนนี้ให้ใช้มือซ้ายถือโทรศัพท์และงอข้อศอกของคุณไว้นิ่งๆ แล้วเอาโทรศัพท์มาแตะที่จมูกแบบสลับไปมาซ้ำๆ"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "ตอนนี้ให้ใช้มือขวาถือโทรศัพท์และงอข้อศอกของคุณไว้นิ่งๆ แล้วเอาโทรศัพท์มาแตะที่จมูกแบบสลับไปมาซ้ำๆ"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "เอาโทรศัพท์ของคุณมาแตะที่จมูกแบบสลับไปมานาน %ld วินาที"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "เตรียมทำท่าโบกมือเบาๆ (โบกมือโดยขยับแค่ข้อมือ)"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "เตรียมทำท่าโบกมือเบาๆ โดยใช้มือซ้ายที่ถือโทรศัพท์ไว้ (โบกมือโดยขยับแค่ข้อมือ)"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "เตรียมทำท่าโบกมือเบาๆ โดยใช้มือขวาที่ถือโทรศัพท์ไว้ (โบกมือโดยขยับแค่ข้อมือ)"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "ทำท่าโบกมือเบาๆ นาน %ld วินาที"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "ตอนนี้ให้สลับไปใช้มือซ้ายถือโทรศัพท์แล้วทำงานถัดไปต่อ"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "ตอนนี้ให้สลับไปใช้มือขวาถือโทรศัพท์แล้วทำงานถัดไปต่อ"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "ทำงานถัดไปต่อ"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "กิจกรรมสำเร็จแล้ว"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "ระบบจะขอให้คุณทำ%@ในระหว่างที่นั่งถือโทรศัพท์ไว้ในมือข้างหนึ่ง แล้วเปลี่ยนไปถือในมืออีกข้างหนึ่ง"; +"TREMOR_SKIP_LEFT_HAND" = "ฉันไม่สามารถทำกิจกรรมนี้ได้โดยใช้มือซ้าย"; +"TREMOR_SKIP_RIGHT_HAND" = "ฉันไม่สามารถทำกิจกรรมนี้ได้โดยใช้มือขวา"; +"TREMOR_SKIP_NEITHER" = "ฉันสามารถทำกิจกรรมนี้ได้โดยใช้มือทั้งสองข้าง"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "การทดสอบการต่อจุด"; +"TRAILMAKING_INTENDED_USE" = "กิจกรรมนี้จะประเมินสมาธิในการมองเห็นและทักษะการสลับการทำงานของคุณโดยบันทึกเวลาที่ใช้ในการแตะชุดของวงกลมตามลำดับ"; +"TRAILMAKING_INTENDED_USE2_A" = "หลังจากการนับถอยหลัง ให้แตะวงกลมที่มีตัวเลขและตัวอักษรในลำดับที่สลับกัน โดยเริ่มต้นด้วยการแตะตัวเลขแรก '1' แล้วตามด้วยตัวเลข '2' – '3' – '4'… จนกว่าจะถึงตัวเลข '7'"; +"TRAILMAKING_INTENDED_USE2_B" = "หลังจากการนับถอยหลัง ให้แตะวงกลมที่มีตัวเลขและตัวอักษรในลำดับที่สลับกัน โดยเริ่มต้นด้วยการแตะตัวเลขแรก '1' แล้วแตะตัวอักษรแรก 'A' จากนั้นแตะ '2' – 'B' – '3' – 'C'… จนกว่าจะถึงตัวเลข '7'"; +"TRAILMAKING_INTRO_TEXT" = "ทำเช่นนี้ให้เร็วที่สุดเท่าที่จะทำได้โดยไม่ทำผิด \n"; +"TRAILMAKING_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "การรู้จำเสียงพูด"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "กิจกรรมนี้จะบันทึกเสียงพูดของคุณด้วยไมโครโฟนที่อยู่ด้านล่างสุดของอุปกรณ์และแปลงเสียงพูดเป็นข้อความ"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "แตะเริ่มต้นใช้งานเพื่อเริ่ม"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "กดปุ่มเพื่อเริ่มบันทึกเสียงก่อนที่จะพูด"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "เริ่มบันทึกเสียง"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "หยุดบันทึกเสียง"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "แก้ไขการถอดข้อความ"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "แก้ไขข้อความในการถอดข้อความเพื่อปรับปรุงส่วนใดๆ ของเสียงพูดที่ตีความผิดพลาดให้ถูกต้อง"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "การถอดข้อความของคุณจะแสดงขึ้นที่นี่"; +"SPEECH_RECOGNITION_FAILED" = "การรู้จำเสียงพูดไม่สำเร็จ"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "เริ่มต้นการรู้จำเสียงพูดไม่สำเร็จ"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "เล่นเสียง"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "หยุดเสียง"; +"SPEECH_IN_NOISE_TITLE" = "เสียงพูดมีเสียงรบกวน"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "กิจกรรมนี้จะวัดความเข้าใจเสียงพูดเมื่ออยู่ในสภาพแวดล้อมที่มีเสียงรบกวน"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "ในส่วนหนึ่งของการทดสอบนี้ คุณจะได้:\n\nฟังประโยค\n\nพูดซ้ำสิ่งที่ได้ยินให้ชัดเจนหรือข้ามไปข้างหน้าเพื่อป้อนสิ่งที่คุณได้ยินโดยใช้แป้นพิมพ์ \n\nถ้าคุณพูดซ้ำสิ่งที่ได้ยิน คุณจะได้รับตัวเลือกในการแก้ไขการถอดข้อความที่สร้างโดยเครื่องมือรู้จำเสียงพูด"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "การปรับเทียบความดัง"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "แตะ 'เล่นเสียง' แล้วปรับความดังของคุณให้อยู่ในระดับที่พอดี จากนั้นแตะ 'หยุดเสียง' เพื่อดำเนินการต่อ"; +"SPEECH_IN_NOISE_STEP_TITLE" = "ฟัง"; +"SPEECH_IN_NOISE_STEP_TEXT" = "ประโยคที่มีเสียงรบกวนรอบข้างปะปน โดยมีอัตราสัญญาณเสียงต่อคลื่นรบกวน (SNR) แบบสุ่ม จะเล่นเพียงครั้งเดียว"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "พูด"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "พูดซ้ำสิ่งที่คุณได้ยิน"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "ไม่สามารถสร้างไฟล์ได้"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "ไม่สามารถเอาไฟล์บันทึกการใช้งานออกได้เพียงพอกับค่าที่กำหนด"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "ข้อผิดพลาดในการตั้งค่าคุณลักษณะ"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "ไฟล์ไม่ได้ทำเครื่องหมายว่าถูกลบ (ไม่ทำเครื่องหมายว่าอัพโหลดแล้ว)"; +"ERROR_DATALOGGER_MULTIPLE" = "ข้อผิดพลาดหลายอย่างเกี่ยวกับการเอาบันทึกการใช้งานออก"; +"ERROR_RECORDER_NO_DATA" = "ไม่พบข้อมูลที่เก็บรวบรวม"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "ไม่ได้ระบุไดเรกทอรีสำหรับการบันทึก"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "มิเตอร์ SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "กิจกรรมนี้จะวัดระดับความดันเสียงรอบข้าง ถ้าระดับเสียงรบกวนสูงเกินไป คุณจะไม่สามารถดำเนินการต่อได้ โปรดย้ายไปยังสถานที่ที่เงียบกว่านี้เพื่อทำงานนี้ให้สำเร็จ หรือทำกิจกรรมนี้อีกครั้งในภายหลัง"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "กำลังคำนวณ"; +"ENVIRONMENTSPL_THRESHOLD" = "เกณฑ์: %@ dBA"; +"ENVIRONMENTSPL_OK" = "มีเสียงรบกวนอยู่เบื้องหลังในระดับโอเค"; +"ENVIRONMENTSPL_NOISE" = "มีเสียงรบกวนอยู่เบื้องหลังมากเกินไป"; +"ENVIRONMENTSPL_TITLE_2" = "ค้นหาสถานที่เงียบ"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "เพื่อความแม่นยำที่ถูกต้อง ควรทำการทดสอบนี้ในสภาพแวดล้อมที่เงียบสงบ"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "เริ่มงาน"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "ไม่มีข้อมูล"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "เลื่อนแถบเลื่อนเพื่อป้อนค่า"; +"SLIDER_I_DONT_KNOW" = "ฉันไม่รู้"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "หน้า"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "ย้อนกลับ"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "แสดงรูปย่อ PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "ซ่อนรูปย่อ PDF"; +"AX_BUTTON_ANNOTATE" = "อธิบายประกอบ"; +"AX_BUTTON_SHOW_SEARCH" = "แสดงแถบค้นหา"; +"AX_BUTTON_HIDE_SEARCH" = "ซ่อนแถบค้นหา"; +"AX_BUTTON_SHARE" = "แชร์"; + + +"AX_COMPLETION_ILLUSTRATION" = "ภาพประกอบที่แสดงเครื่องหมายถูกในวงกลมสีน้ำเงินหมายถึงความสำเร็จ"; + +"AX_SIGNVIEW_LABEL" = "ช่องสำหรับลายเซ็นที่กำหนด"; +"AX_SIGNVIEW_HINT" = "แตะหน้าจอแล้วเลื่อนนิ้วของคุณเพื่อเซ็นชื่อ"; +"AX_SIGNVIEW_SIGNED" = "เซ็นชื่อแล้ว"; +"AX_SIGNVIEW_UNSIGNED" = "ไม่ได้เซ็นชื่อ"; + +"AX_SELECTED" = "เลือกอยู่"; +"AX_UNSELECTED" = "ไม่ได้เลือก"; +"AX_SELECT_ALL_THAT_APPLY" = "เลือกทั้งหมดที่เกี่ยวข้อง"; + +"AX_SLIDER_LABEL" = "แถบเลื่อนการตอบสนอง ช่วงตั้งแต่ %@ ถึง %@"; +"AX_UNLABELED_IMAGE" = "รูปภาพที่ไม่มีคำอธิบาย"; + +"AX_ANNOUNCE_BEGIN_TASK" = "เริ่มงาน"; + +"AX.MEMORY.TILE.ACTIVE" = "ใช้งานอยู่"; +"AX.MEMORY.TILE.CORRECT" = "ถูกต้อง"; +"AX.MEMORY.TILE.INCORRECT" = "ไม่ถูกต้อง"; +"AX.MEMORY.TILE.QUIESCENT" = "ไม่ได้ใช้งาน"; +"AX.MEMORY.TILE.LABEL" = "เกมเปิดป้ายจับคู่"; + +"AX_IMAGE_CAPTURE_LABEL" = "แสดงตัวอย่างการเก็บภาพ"; +"AX_IMAGE_CAPTURED_LABEL" = "รูปภาพที่จับภาพ"; + +"AX_VIDEO_CAPTURE_LABEL" = "แสดงตัวอย่างภาพถ่ายวิดีโอ"; +"AX_VIDEO_CAPTURE_COMPLETE" = "จับภาพวิดีโอสำเร็จ"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "ไม่สามารถวางจานที่มีขนาด %@ บนจานที่มีขนาด %@ ได้"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "เป้าหมาย"; +"AX_TOWER_OF_HANOI_TOWER" = "หอคอย"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "แตะสองครั้งเพื่อวางจาน"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "แตะสองครั้งเพื่อเลือกจานที่อยู่ด้านบนสุด"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "มีจานที่มีขนาด %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "ว่างเปล่า"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "ปิดทิ้งแป้นพิมพ์"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "ช่วงตั้งแต่ %@ ถึง %@"; +"AX_GRAPH_STACK_PREFIX" = "สแต็คประกอบด้วย"; +"AX_GRAPH_AND_SEPARATOR" = " และ "; +"AX_GRAPH_POINT_%@" = "จุด: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "รูปคลื่นเสียงของเสียงพูด"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "เมื่อเริ่มบันทึกเสียง ให้เปิดใช้งานอีกครั้งเพื่อหยุดบันทึกเสียง"; + +"AX_AUDIO_BAR_GRAPH" = "กราฟแท่งเสียง"; + +"AX_AMSLER_GRID_LABEL" = "ตาราง Amsler"; +"AX_AMSLER_GRID_HINT" = "ใช้นิ้วหรือปากกาสไตลัสของคุณเพื่อทำเครื่องหมายลงบนตารางโดยตรง หรือปัดไปทางซ้ายด้านนอกตารางเพื่อสิ้นสุด"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "ปุ่มที่สามารถถูกแตะได้"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "แตะสำหรับหูข้างซ้าย"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "เปิดใช้งานเพื่อเริ่มการทดสอบ เมื่อเริ่มการทดสอบ แตะโดยตรงบนปุ่มนี้เมื่อคุณได้ยินเสียงในหูข้างซ้ายของคุณ"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "แตะสำหรับหูข้างขวา"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "เปิดใช้งานเพื่อเริ่มการทดสอบ เมื่อเริ่มการทดสอบ แตะโดยตรงบนปุ่มนี้เมื่อคุณได้ยินเสียงในหูข้างขวาของคุณ"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ โดยการใช้ VoiceOver ให้สำรวจหน้าจอโดยการแตะเพื่อหาตำแหน่งของปุ่มต่างๆ สำหรับหูแต่ละข้าง เมื่อเริ่มการทดสอบ ปุ่มจะสามารถถูกแตะโดยตรงได้ %@"; +"AX_TAP_BUTTON_1_LABEL" = "ใช้หนึ่งนิ้วแตะ"; +"AX_TAP_BUTTON_2_LABEL" = "ใช้นิ้วอื่นแตะ"; +"AX_TAP_BUTTON_HINT" = "เปิดใช้งานเป็นปุ่มที่สามารถถูกแตะโดยตรงได้"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ โดยการใช้ VoiceOver ให้สำรวจหน้าจอโดยการแตะเพื่อรับทราบตำแหน่งของปุ่มต่างๆ ให้เปิดใช้งานปุ่มหนึ่งเป็นปุ่มที่สามารถถูกแตะโดยตรงได้"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "ปุ่มสามารถถูกแตะโดยตรงได้แล้ว"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ โดยการใช้ VoiceOver ปุ่มจะสามารถถูกแตะโดยตรงได้ ปุ่มจะอยู่ใกล้กับจุดกึ่งกลางของหน้าจอ"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ โดยการใช้ VoiceOver ปุ่มในการทดสอบจะสามารถถูกแตะโดยตรงได้"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "ไม่สามารถถอดรหัส restoreData สำหรับการจัดเตรียมได้"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..4116233 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/th.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d ข้อผิดพลาด) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.strings new file mode 100755 index 0000000..fdab8b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "İzin"; +"CONSENT_NAME_GIVEN" = "Ad"; +"CONSENT_NAME_FAMILY" = "Soyad"; +"CONSENT_NAME_PLACEHOLDER" = "Gerekli"; +"CONSENT_REVIEW_TITLE" = "Gözden Geçir"; +"CONSENT_REVIEW_INSTRUCTION" = "Aşağıdaki formu gözden geçirin, sürdürmeye hazırsanız Kabul Ediyorum’a dokunun."; +"CONSENT_REVIEW_ALERT_TITLE" = "Gözden Geçir"; +"CONSENT_SIGNATURE_TITLE" = "İmza"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Lütfen aşağıdaki kutuyu parmağınızı kullanarak imzalayın."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Burayı İmzalayın"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Sayfa %1$ld / %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Hoş Geldiniz"; +"CONSENT_SECTION_DATA_GATHERING" = "Veri Toplama"; +"CONSENT_SECTION_PRIVACY" = "Gizlilik"; +"CONSENT_SECTION_DATA_USE" = "Veri Kullanımı"; +"CONSENT_SECTION_STUDY_SURVEY" = "Çalışma Anketi"; +"CONSENT_SECTION_STUDY_TASKS" = "Çalışma Görevleri"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Zaman Ayırma"; +"CONSENT_SECTION_WITHDRAWING" = "Ayrılma"; +"CONSENT_LEARN_MORE_TITLE" = "Daha Fazla Bilgi"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Verilerin toplanması hakkında daha fazla bilgi"; +"LEARN_MORE_DATA_USE" = "Verilerin kullanılması hakkında daha fazla bilgi"; +"LEARN_MORE_PRIVACY" = "Gizliliğinizin ve kimliğinizin korunması hakkında daha fazla bilgi"; +"LEARN_MORE_WELCOME" = "Çalışma hakkında daha fazla bilgi"; +"LEARN_MORE_STUDY_SURVEY" = "Çalışma anketi hakkında daha fazla bilgi"; +"LEARN_MORE_TIME_COMMITMENT" = "Çalışmanın zamanınıza etkisi hakkında daha fazla bilgi"; +"LEARN_MORE_TASKS" = "İlişkili görevler hakkında daha fazla bilgi"; +"LEARN_MORE_WITHDRAWING" = "Ayrılma hakkında daha fazla bilgi"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Paylaşma Seçenekleri"; +"CONSENT_SHARE_WIDELY_%@" = "Verilerimi %@ ve dünya çapında nitelikli araştırmacılarla paylaş"; +"CONSENT_SHARE_ONLY_%@" = "Verilerimi yalnızca %@ ile paylaş"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@, bu çalışmaya katılımınızdan elde ettiğiniz çalışma verilerinizi alacak.\n\nKodlanmış çalışma verilerinizi daha geniş bir biçimde (adınız gibi bilgiler olmadan) paylaşmanız, bu araştırma ve gelecekteki araştırmalar için yararlı olabilir."; +"LEARN_MORE_CONSENT_SHARING" = "Veri paylaşımı hakkında daha fazla bilgi"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Yazılı Ad"; +"CONSENT_DOC_LINE_SIGNATURE" = "İmza"; +"CONSENT_DOC_LINE_DATE" = "Tarih"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ / %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Soru %1$@ / %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Atlandı"; +"REVIEW_EDIT_ANSWER" = "Düzenle"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Geçersiz değer"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@, izin verilen maksimum değeri (%2$@) aşıyor."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@, izin verilen minimum değerden (%2$@) küçük."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ geçerli bir değer değil."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Geçersiz e-posta adresi: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Adres girin"; +"LOCATION_ERROR_TITLE" = "Belirtilen Adres Bulunamadı"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Şu anki konumunuz çözülemedi. Lütfen bir adres girin veya uygunsa daha iyi GPS sinyalı olan bir konuma gidin."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Konum servislerine erişim reddedildi. Lütfen konum servislerini kullanmak için Ayarlar'da bu uygulamaya izin verin."; +"LOCATION_ERROR_GEOCODE" = "Girilen adres için bir sonuç bulunmadı. Lütfen adresin geçerli olduğundan emin olun."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "İnternete bağlı değilsiniz veya en fazla adres arama isteği miktarını aştınız. İnternete bağlı değilseniz lütfen bu soruya yanıt vermek için Wi-Fi'yi açın, atlama düğmesi varsa bu soruyu atlayın ya da internete bağlı olduğunuzda anket için yeniden sayfayı ziyaret edin. Aksi takdirde, birkaç dakika sonra yeniden deneyin."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Metin içeriği maksimum uzunluğu aşıyor: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Bölünmüş ekranda Kamera kullanılamıyor."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "E-posta"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "ad@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Parola"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Parola girin"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Doğrula"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Parolayı yeniden girin"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Parolalar eşleşmiyor."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Ek Bilgi"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Ali"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Utku"; +"GENDER_FORM_ITEM_TITLE" = "Cinsiyet"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Bir cinsiyet seçin"; +"DOB_FORM_ITEM_TITLE" = "Doğum Tarihi"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Bir tarih seçin"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Telefon Numarası"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Doğrulama"; +"VERIFICATION_STEP_TITLE" = "E-postanızı doğrulayın"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Doğrulama e-postası almadıysanız ve yeniden gönderilmesini istiyorsanız, lütfen aşağıdaki bağlantıya dokunun."; +"RESEND_EMAIL_BUTTON_TITLE" = "Doğrulamayı Yeniden E-postala"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Oturum Aç"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Parolayı mı unuttunuz?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Parola girin"; +"PASSCODE_CONFIRM_MESSAGE" = "Parolayı doğrulayın"; +"PASSCODE_SAVED_MESSAGE" = "Parola kaydedildi"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Parola doğrulandı"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Eski parolanızı girin"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Yeni parolanızı girin"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Yeni parolanızı doğrulayın"; +"PASSCODE_INVALID_ALERT_TITLE" = "Parola Doğru Değil"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Parolalar eşleşmedi. Yeniden deneyin."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Lütfen Touch ID ile kimlik doğrulayın"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID hatası"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Yalnızca sayısal karakterlere izin veriliyor."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Parola giriş ilerleme göstergesi"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "%@ / %@ basamak girildi"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Parolayı mı Unuttunuz?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Anahtar zinciri öğesi eklenemedi."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Anahtar zinciri öğesi güncellenemedi."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Anahtar zinciri öğesi silinemedi."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Anahtar zinciri öğesi bulunamadı."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "0+"; +"BLOOD_TYPE_O-" = "0-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Tip I"; +"FITZPATRICK_SKIN_TYPE_II" = "Tip II"; +"FITZPATRICK_SKIN_TYPE_III" = "Tip III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Tip IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Tip V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Tip VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Kadın"; +"GENDER_MALE" = "Erkek"; +"GENDER_OTHER" = "Diğer"; + +/* Boolean answer strings */ +"BOOL_NO" = "Hayır"; +"BOOL_YES" = "Evet"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "fit"; +"MEASURING_UNIT_IN" = "inç"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "lb"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "sol"; +"LIMB_RIGHT" = "sağ"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Yanıtlamak için dokunun"; +"NULL_ANSWER" = "Bir yanıt seçin"; +"PLACEHOLDER_IMAGE_CHOICES" = "Seçmek için dokunun"; +"PLACEHOLDER_LONG_TEXT" = "Yazmak için dokunun"; + +/* Button titles */ +"BUTTON_AGREE" = "Kabul Ediyorum"; +"BUTTON_CANCEL" = "Vazgeç"; +"BUTTON_OK" = "Tamam"; +"BUTTON_CLEAR" = "Sil"; +"BUTTON_CLEAR_SIGNATURE" = "İmzayı Sil"; +"BUTTON_APPLY" = "Uygula"; +"BUTTON_DISAGREE" = "Kabul Etmiyorum"; +"BUTTON_DONE" = "Bitti"; +"BUTTON_GET_STARTED" = "Başla"; +"BUTTON_LEARN_MORE" = "Daha fazla bilgi"; +"BUTTON_NEXT" = "İleri"; +"BUTTON_SKIP" = "Atla"; +"BUTTON_SKIP_QUESTION" = "Bu soruyu atla"; +"BUTTON_START_TIMER" = "Sayacı Başlat"; +"BUTTON_OPTION_SAVE" = "Sonrası İçin Kaydet"; +"BUTTON_OPTION_DISCARD" = "Sonuçları Sil"; +"BUTTON_OPTION_STOP_TASK" = "Görevi Bitir"; +"BUTTON_SAVE" = "Kaydet"; +"BUTTON_CLEAR_ANSWER" = "Yanıtı sil"; +"BUTTON_READ_ONLY_MODE" = "Bu yanıt değiştirilemiyor."; +"BUTTON_COPYRIGHT" = "Telif Hakkı"; +"BUTTON_CLOSE" = "Kapat"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Aktivite başlatılıyor"; +"TASK_COMPLETE_TITLE" = "Tamamlandı"; +"TASK_COMPLETE_TEXT" = "Verileriniz incelenecek ve sonuçlarınız hazır olduğunda size haber verilecektir."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "%@ kaldı."; +"TOUCH_ANYWHERE_LABEL" = "Sürdürmek için herhangi bir yere dokunun"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Görüntü Yakala"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Görüntüyü Yeniden Yakala"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Kamera bulunamadı. Bu adım tamamlanamıyor."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Bu adımı tamamlamak için Ayarlar'da bu uygulamanın kameraya erişimine izin verin."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Yakalanan görüntülerin kaydedileceği bir dizin belirtilmemiş."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Yakalanan görüntü kaydedilemedi."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Kaydı Başlat"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Kaydı Durdur"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Videoyu Yeniden Yakala"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Fitness"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Mesafe (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Kalp Atış Hızı (vuruş/dk)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Rahat bir şekilde %@ oturun."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Yürüyebildiğiniz kadar hızlı %@ yürüyün."; +"FITNESS_INTRO_TEXT_FORMAT" = "Bu aktivite, kalp atış hızınızı izler ve %1$@ içinde ne kadar mesafe yürüyebileceğinizi ölçer."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Açık havada yürüyebildiğiniz en yüksek hızda %1$@ yürüyün. Bitirdiğinizde, oturun ve %2$@ rahat bir şekilde dinlenin. Başlamak için Başla’ya dokunun."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Yürüyüş Tarzı ve Denge"; +"WALK_INTRO_TEXT" = "Bu aktivite, yürürken ve ayakta dururken yürüyüş tarzınızı ve dengenizi ölçer. Yardımsız, güvenli bir şekilde yürüyemiyorsanız devam etmeyin."; +"WALK_INTRO_2_TEXT_%ld" = "Düz bir çizgide yaklaşık %ld adım yardımsız, güvenli bir şekilde yürüyebileceğiniz bir yer bulun."; +"WALK_INTRO_2_DETAIL" = "Aygıtınızı cebinize veya çantanıza koyun ve sesli yönergeleri takip edin."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Şimdi %@ süresince hareketsiz durun."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Hareketsiz bir şekilde %@ durun."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Geriye dönün ve başladığınız yere yürüyün."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Düz bir çizgide en fazla %ld adım yürüyün."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Düz bir çizgide güvenli bir şekilde ileri ve geri yürüyebileceğiniz bir yer bulun. Tıpkı bir koninin etrafında yürüyor gibi, yolunuzun sonundan dönerek sürekli yürümeyi deneyin.\n\nArdından, tam daire çevresinde dönmeniz, kollarınız iki yanınızda ve ayaklarınız omuz genişliğinde açık olacak şekilde ayakta sabit durmanız istenecektir."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Başlamaya hazır olduğunuzda Başla’ya dokunun.\nArdından aygıtınızı cebinize veya çantanıza yerleştirin ve sesli yönergeleri takip edin."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Düz bir çizgide ileri geri %@ yürüyün. Normal bir şekilde yürüyün."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Tam daire şeklinde dönün ve sonra %@ süresince hareketsiz durun."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Bu aktiviteyi tamamladınız."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Dokunma Hızı"; +"TAPPING_TASK_TITLE_RIGHT" = "Sağ El"; +"TAPPING_TASK_TITLE_LEFT" = "Sol El"; +"TAPPING_INTRO_TEXT" = "Bu aktivite, dokunma hızınızı ölçer."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Aygıtı düz bir zemine koyun."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Ekrandaki düğmelere dönüşümlü olarak dokunmak için aynı elinizin iki parmağını kullanın."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Ekrandaki düğmelere dönüşümlü olarak dokunmak için sağ elinizin iki parmağını kullanın."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Ekrandaki düğmelere dönüşümlü olarak dokunmak için sol elinizin iki parmağını kullanın."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Şimdi aynı testi sağ elinizi kullanarak tekrarlayın."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Şimdi aynı testi sol elinizi kullanarak tekrarlayın."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Tek parmağınızla, sonra diğeriyle dokunun. Mümkün olduğunca eşit zaman aralıklarıyla dokunmaya çalışın. %@ süresince dokunmaya devam edin."; +"TAPPING_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Başlamak için İleri’ye dokunun."; +"TAP_BUTTON_TITLE" = "Dokun"; +"TOTAL_TAPS_LABEL" = "Toplam Dokunma"; +"TAPPING_INSTRUCTION" = "İki parmağınızı kullanarak düğmelere dokunabildiğiniz kadar tutarlı dokunun."; +"TAPPING_INSTRUCTION_RIGHT" = "Düğmelere SAĞ elinizi kullanarak dokunun."; +"TAPPING_INSTRUCTION_LEFT" = "Düğmelere SOL elinizi kullanarak dokunun."; +"TAPPING_SKIP_TITLE" = "Bu eli atla"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Amsler Izgarası"; +"AMSLER_GRID_INTRO_TEXT" = "Bu aktivite, kullanıcının görüşündeki sorunları algılamaya yardımcı olur."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Aygıtı test boyunca yüzünüzden 30 cm uzakta ve göz seviyenizde tutun."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "%@ünüzü kapatın ve kare ızgaranın ortasındaki noktaya bakın.\n\nParmağınızı veya ekran kalemini kullanarak gördüğünüz bozulmaları işaretleyin (örneğin bulanık veya dalgalı çizgiler).\n\nİşiniz bittiğinde, ızgaranın dışında herhangi bir yere doğru sola kaydırın."; +"AMSLER_GRID_LEFT_EYE" = "Sol Göz"; +"AMSLER_GRID_RIGHT_EYE" = "Sağ Göz"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Ses"; +"AUDIO_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"AUDIO_INSTRUCTION" = "Mikrofona, söyleyebildiğiniz kadar uzun “Aaaaa” deyin."; +"AUDIO_INTRO_TEXT" = "Derin bir nefes alın ve mikrofona, söyleyebildiğiniz kadar uzun “Aaaaa” deyin. Ses çubukları mavi kalacak şekilde ses yüksekliğini sabit tutmaya çalışın."; +"AUDIO_INTENDED_USE" = "Bu aktivite, sesinizi aygıtınızın en altındaki mikrofonla kaydederek değerlendirir."; +"AUDIO_TOO_LOUD_LABEL" = "Çok Yüksek"; +"AUDIO_GENERIC_ERROR_LABEL" = "Ses kaydı yapılamıyor"; +"AUDIO_LEVEL_CHECK_LABEL" = "Arka plan gürültü düzeyi denetlenirken lütfen bekleyin."; +"AUDIO_TOO_LOUD_MESSAGE" = "Ortam gürültü düzeyi sesinizi kaydedemeyecek kadar yüksek. Lütfen daha sessiz bir yere gidip yeniden deneyin."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Hazır olduğunuzda İleri’ye dokunun."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Ses Tonu Odyometrisi"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Bu aktivite, farklı sesleri duyabilme becerinizi ölçer."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Başlamadan önce, kulaklıklarınızı bağlayın ve takın.\n\nSes çok hafif ve normal uyarı tonundan farklı olacaktır.  Ses yumuşak bir şekilde başlayacak ve ses düzeyi yavaşça artacaktır.  Lütfen dikkatinizi verin ve hangi kulakta duyduğunuzu belirtmek için sol veya sağ düğmeye dokunun."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Şimdi bir ses duymalısınız. Aygıtınızın yan tarafındaki denetimleri kullanarak ses düzeyini ayarlayın.\n\nBaşlamaya hazır olduğunuzda herhangi bir düğmeye dokunun."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Sesi her duyduğunuzda, sesi hangi kulağınızdan duyduğunuzu belirtmek üzere sol veya sağ düğmeye dokunun."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Sol Kulak"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Sağ Kulak"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Sol"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Sağ"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Ses Tonu Odyometrisi"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Bir ses tonu duyduğunuzda dokunun."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Ses Tonu ve Ses Yüksekliği"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Bir dizi ses tonu duyacaksınız."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Bir ses tonu duyduğunuzda düğmeye dokunun."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Bu test için ses düzeyi yüzde 50 olarak ayarlanır."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Bu test yaklaşık 10 dakika sürer."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Kesintilerden kaçınmak için Rahatsız Etme'yi açın."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Tonlar ilk önce sağ kulağınızda çalacak."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Tonlar şimdi sol kulağınızda çalacak."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Bu aktivite, bir bireyin duyma eşiği düzeylerini dB HL ölçeğinde belirler."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Aygıt sesinin en yüksek düzeye ayarlandığından emin olun.\n\nBu görev sırasında, sol veya sağ kulakta hafif bir ses çalacaktır.\n\nDikkatli bir şekilde dinleyin ve sesi her duyduğunuzda düğmeye dokunun."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Bu test, bir sesi duyabilmeniz için sesin ne kadar yüksek olması gerektiğini belirler."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "İşe alım anketi."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Bir kulağınız “daha iyi duyuyorsa” onu seçin"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "sol"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "sağ"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "tercih yok"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Testten Vazgeçildi"; +"dBHL_ALERT_TITLE_START_OVER" = "Baştan Başla"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Testten Vazgeç"; +"dBHL_ALERT_TEXT" = "Bu test için AirPods veya EarPods bağlayın."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ Tamamlandı"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Kulaklık"; +"HEADPHONES_UNKNOWN" = "Bilinmeyen"; +"HEADPHONES_NONE" = "Yok"; +"CONNECTED" = "Bağlı"; +"NOT_CONNECTED" = "Bağlı Değil"; +"HEADPHONE_CONNECTED_%@" = "Bağlı - %@"; +"HEADPHONE_DETECT_TITLE" = "Kulaklığınızı bağlayın"; +"HEADPHONE_DETECT_TEXT" = "Bu test Apple AirPods veya Apple EarPods gerektiriyor"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Konumsal Bellek"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Bu aktivite, %@ görüntülerinin sırasını yinelemenizi isteyerek kısa süreli konumsal belleğinizi ölçer."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "çiçek"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "çiçek"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Bu %@ görüntülerinin bazıları teker teker yanacaktır. Bu %@ görüntülerine yandıkları sırada dokunun."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Bu %@ görüntülerinin bazıları teker teker yanacaktır. Bu %@ görüntülerine yandıkları sıranın tersinde dokunun."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Başlamak için Başla'ya dokunun, sonra dikkatlice izleyin."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Puan"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Bu %@ görüntülerinin yanmasını izleyin"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Bu %@ görüntülerine yandıkları sırada dokunun"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Bu %@ görüntülerine ters sırada dokunun"; +"MEMORY_GAME_COMPLETE_TITLE" = "Dizi Tamamlandı"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Devam etmek için İleri’ye dokunun"; +"MEMORY_GAME_FAILED_TITLE" = "Yeniden Deneyin"; +"MEMORY_GAME_FAILED_MESSAGE" = "Bu sefer pek iyi yapamadınız. Devam etmek için İleri’ye dokunun."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Süre Doldu"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Süreniz doldu.\nSürdürmek için Sonraki’ye dokunun."; +"MEMORY_GAME_COMPLETE" = "Oyun Tamamlandı"; +"MEMORY_GAME_PAUSED_TITLE" = "Duraklatıldı"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Devam etmek için İleri’ye dokunun"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Bellek aktivitesi, San Francisco’daki Kaliforniya Üniversitesi’nden Katherine Possin (PhD) ile Joel Kramer’in (PhD) yardımlarıyla geliştirilmiştir."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Tepki Süresi"; +"REACTION_TIME_TASK_INTENDED_USE" = "Bu aktivite, görünen bir ipucuna yanıt verebildiğiniz süreyi hesaplar."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Ekranda mavi nokta görünür görünmez aygıtı herhangi bir yönde hızlıca sallayın. Bunu %D kez yapmanız istenecek."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "%@ / %@ Girişim"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Mavi daire göründüğünde aygıtı hızlıca sallayın"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Her sözcük göründüğünde, gösterilen RENGİN adının ilk harfini seçin."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Stroop aktivitesine başlamaya hazır olduğunuzda Başla’ya dokunun."; +"STROOP_TASK_STEP_TEXT" = "Gösterilen RENGİN adının ilk harfini seçin."; +"STROOP_COLOR_RED" = "KIRMIZI"; +"STROOP_COLOR_GREEN" = "YEŞİL"; +"STROOP_COLOR_BLUE" = "MAVİ"; +"STROOP_COLOR_YELLOW" = "SARI"; +"STROOP_COLOR_RED_INITIAL" = "K"; +"STROOP_COLOR_GREEN_INITIAL" = "Y"; +"STROOP_COLOR_BLUE_INITIAL" = "M"; +"STROOP_COLOR_YELLOW_INITIAL" = "S"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Hanoi Kulesi"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Bu aktivite, bulmaca çözme becerilerinizi ölçer."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Tüm yığını, vurgulanan platforma mümkün olan en az hamlede taşıyın."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Bulmacayı Çöz"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Hareket Sayısı: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Bu bulmacayı çözemedim"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Hareket Aralığı"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption sol veya sağ olmalı"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Sol Diz Hareket Alanı"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Sağ Diz Hareket Alanı"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Bu aktivite, sol dizinizi ne kadar uzatabileceğinizi ölçer."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Bu aktivite, sağ dizinizi ne kadar uzatabileceğinizi ölçer."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Bir sandalyenin kenarına oturun. Başladığınızda, aygıtınızı ölçüm için sol dizinize koyacaksınız. Yönergeleri duyabilmeniz için lütfen aygıtınızın sesini açın."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Bir sandalyenin kenarına oturun. Başladığınızda, aygıtınızı ölçüm için sağ dizinize koyacaksınız. Yönergeleri duyabilmeniz için lütfen aygıtınızın sesini açın."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Aygıtınızı, resimde gösterildiği gibi ekran dışa bakacak şekilde sol dizinize yerleştirin."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Aygıtınızı, resimde gösterildiği gibi ekran dışa bakacak şekilde sağ dizinize yerleştirin."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Hazır olduğunuzda başlamak için ekrana dokunun ve sol dizinizi uzatabildiğiniz kadar uzatın. Başlangıç noktasına dönün ve bitirdiğinizde yeniden dokunun."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Hazır olduğunuzda başlamak için ekrana dokunun ve sağ dizinizi uzatabildiğiniz kadar uzatın. Başlangıç noktasına dönün ve bitirdiğinizde yeniden dokunun."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Aygıtınızı sol dizinize yerleştirin. Ekrana dokunun ve sol dizinizi uzatabildiğiniz kadar uzatın."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Aygıtınızı sağ dizinize yerleştirin. Ekrana dokunun ve sağ dizinizi uzatabildiğiniz kadar uzatın."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Bitirdiğinizde sol dizinizi başlangıç noktasına getirin. Sonra herhangi bir yere dokunun."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Bitirdiğinizde sağ dizinizi başlangıç noktasına getirin. Sonra herhangi bir yere dokunun."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Sol Omuz Hareket Alanı"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Sağ Omuz Hareket Alanı"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Bu aktivite, sol omzunuzu ne kadar uzatabileceğinizi ölçer."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Bu aktivite, sağ omzunuzu ne kadar uzatabileceğinizi ölçer."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Başladığınızda, aygıtınızı ölçüm için sol omzunuza koyacaksınız. Yönergeleri duyabilmeniz için lütfen aygıtınızın sesini açın."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Başladığınızda, aygıtınızı ölçüm için sağ omzunuza koyacaksınız. Yönergeleri duyabilmeniz için lütfen aygıtınızın sesini açın."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Aygıtınızı, resimde gösterildiği gibi ekran dışa bakacak şekilde sol omzunuza yerleştirin."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Aygıtınızı, resimde gösterildiği gibi ekran dışa bakacak şekilde sağ omzunuza yerleştirin."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Hazır olduğunuzda başlamak için ekrana dokunun ve sol kolunuzu kaldırabildiğiniz kadar kaldırın. Başlangıç noktasına dönün ve bitirdiğinizde yeniden dokunun."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Hazır olduğunuzda başlamak için ekrana dokunun ve sağ kolunuzu kaldırabildiğiniz kadar kaldırın. Başlangıç noktasına dönün ve bitirdiğinizde yeniden dokunun."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Aygıtınızı sol omzunuza yerleştirin. Ekrana dokunun ve sol kolunuzu uzatabildiğiniz kadar öne uzatın."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Aygıtınızı sağ omzunuza yerleştirin. Ekrana dokunun ve sağ kolunuzu uzatabildiğiniz kadar öne uzatın."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Bitirdiğinizde sol kolunuzu başlangıç noktasına getirin. Sonra herhangi bir yere dokunun."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Bitirdiğinizde sağ kolunuzu başlangıç noktasına getirin. Sonra herhangi bir yere dokunun."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Süreli Yürüme"; +"TIMED_WALK_INTRO_DETAIL" = "Bu aktivite, alt ekstremite fonksiyonlarınızı ölçer."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Düz bir çizgide mümkün olduğunca hızlı ama güvenli bir şekilde %@ yürüyebileceğiniz bir yer (tercihen dışarıda) bulun. Bitirme çizgisini geçene dek yavaşlamayın."; +"TIMED_WALK_INTRO_2_DETAIL" = "Başlamak için İleri’ye dokunun."; +"TIMED_WALK_FORM_TITLE" = "Yardımcı aygıt"; +"TIMED_WALK_FORM_TEXT" = "Her test için aynı yardımcı aygıtı kullanın."; +"TIMED_WALK_QUESTION_TEXT" = "Ayak bileği ortezi takıyor musunuz?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Yardımcı aygıt kullanıyor musunuz?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Bir yanıt seçmek için dokunun."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Hiçbiri"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Tek Taraflı Baston"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Tek Taraflı Koltuk Değneği"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Çift Taraflı Baston"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Çift Taraflı Koltuk Değneği"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Yürüteç/Yürüme Desteği"; +"TIMED_WALK_INSTRUCTION_%@" = "Düz bir çizgide en fazla %@ yürüyün."; +"TIMED_WALK_INSTRUCTION_TURN" = "Geriye dönün."; +"TIMED_WALK_INSTRUCTION_2" = "Başladığınız yere yürüyün."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Tamamlandığında İleri’ye dokunun."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Tempolu İşitsel Toplama Testi, işitsel bilgi işleme hızınızı ve hesaplama becerinizi ölçer."; +"PVSAT_INTRO_TEXT" = "Tempolu Görsel Toplama Testi, görsel bilgi işleme hızınızı ve hesaplama becerinizi ölçer."; +"PAVSAT_INTRO_TEXT" = "Tempolu İşitsel ve Görsel Toplama Testi, işitsel ve görsel bilgi işleme hızınızı ve hesaplama becerinizi ölçer."; +"PSAT_INTRO_TEXT_2_%@" = "Tek basamaklar her %@ saniyede bir gösterilir.\nHer bir yeni basamağı hemen öncesindeki basamağa eklemelisiniz.\nDikkat edin, toplamı değil, yalnızca son iki sayının toplamını hesaplamalısınız."; +"PSAT_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"PSAT_INITIAL_INSTRUCTION" = "Bu ilk rakamı aklınızda tutun."; +"PSAT_INSTRUCTION" = "Bu yeni rakamı bir öncekine ekleyin."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@ Delikli Daire Testi"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Bu aktivite, bir daireyi deliğe yerleştirmenizi isteyerek üst uzuvlarınızın işlevini ölçer. Bunu %@ kez yapmanız istenecektir."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Hem sol hem de sağ eliniz test edilecektir.\nDaireyi mümkün olduğu kadar hızlı bir şekilde almalı, onu deliğe koymalı ve bunu %@ kez yaptıktan sonra yeniden %@ kez kaldırmalısınız."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Hem sağ hem de sol eliniz test edilecektir.\nDaireyi mümkün olduğu kadar hızlı bir şekilde almalı, onu deliğe koymalı ve bunu %@ kez yaptıktan sonra yeniden %@ kez kaldırmalısınız."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Sol elinizi kullanarak daireyi deliğin içine koyun."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Sağ elinizi kullanarak daireyi deliğin içine koyun."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Sol elinizi kullanarak daireyi çizginin arkasına koyun."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Sağ elinizi kullanarak daireyi çizginin arkasına koyun."; +"HOLE_PEG_TEST_TEXT" = "İki parmağınızla daireyi alın."; +"HOLE_PEG_TEST_TEXT_2" = "Daireyi bırakmak için parmakları kaldırın."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Tremor Aktivitesi"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Bu aktivite, çeşitli pozisyonlarda ellerinizdeki tremor düzeyini ölçer. Bu aktivite süresince rahat bir şekilde oturabileceğiniz bir yer bulun."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Telefonu aşağıdaki görüntüde gösterildiği gibi daha çok etkilenen elinizde tutun."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Telefonu aşağıdaki görüntüde gösterildiği gibi SAĞ elinizde tutun."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Telefonu aşağıdaki görüntüde gösterildiği gibi SOL elinizde tutun."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Telefonunuz elinizde otururken %@ gerçekleştirmeniz istenecektir."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "bir görev"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "iki görev"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "üç görev"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "dört görev"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "beş görev"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Devam etmek için İleri’ye dokunun."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Telefonunuzu kucağınızda tutmaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Telefonunuzu SOL elinizle kucağınızda tutmaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Telefonunuzu SAĞ elinizle kucağınızda tutmaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Telefonunuzu %ld saniye kucağınızda tutmaya devam edin."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Şimdi telefonunuzu eliniz uzatılmış olarak omuz yüksekliğinde tutun."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Şimdi telefonunuzu SOL eliniz uzatılmış olarak omuz yüksekliğinde tutun."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Şimdi telefonunuzu SAĞ eliniz uzatılmış olarak omuz yüksekliğinde tutun."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Telefonunuzu eliniz uzatılmış olarak %ld saniye tutmaya devam edin."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Şimdi telefonunuzu dirseğiniz kıvrık olarak omuz yüksekliğinde tutun."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Şimdi telefonunuzu dirseğiniz kıvrık olarak omuz yüksekliğinde SOL elinizle tutun."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Şimdi telefonunuzu dirseğiniz kıvrık olarak omuz yüksekliğinde SAĞ elinizle tutun."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Telefonunuzu dirseğiniz kıvrık olarak %ld saniye tutmaya devam edin"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Şimdi dirseğinizi kıvrık tutarak telefonunuzu burnunuza tekrar tekrar dokundurun."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Şimdi telefonunuz SOL elinizde olacak şekilde dirseğinizi kıvrık tutarak telefonunuzu burnunuza tekrar tekrar dokundurun."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Şimdi telefonunuz SAĞ elinizde olacak şekilde dirseğinizi kıvrık tutarak telefonunuzu burnunuza tekrar tekrar dokundurun."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Telefonunuzu burnunuza değdirmeye %ld saniye devam edin"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Bileğinizi çevirerek el sallamaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Telefonunuz SOL elinizde olacak şekilde bileğinizi çevirerek el sallamaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Telefonunuz SAĞ elinizde olacak şekilde bileğinizi çevirerek el sallamaya hazırlanın."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Bileğinizi çevirerek el sallamaya %ld saniye devam edin."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Şimdi telefonunuzu SOL elinize alıp bir sonraki göreve geçin."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Şimdi telefonunuzu SAĞ elinize alıp bir sonraki göreve geçin."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Bir sonraki göreve geçin."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Aktivite tamamlandı."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Telefonunuz önce bir elinizde, sonra diğer elinizde otururken %@ gerçekleştirmeniz istenecektir."; +"TREMOR_SKIP_LEFT_HAND" = "Bu aktiviteyi SOL elimle gerçekleştiremem."; +"TREMOR_SKIP_RIGHT_HAND" = "Bu aktiviteyi SAĞ elimle gerçekleştiremem."; +"TREMOR_SKIP_NEITHER" = "Bu aktiviteyi her iki elimle gerçekleştirebilirim."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "İz Sürme Testi"; +"TRAILMAKING_INTENDED_USE" = "Bu aktivite, bir dizi noktaya sırayla dokunmanız için gereken süreyi kaydederek görsel dikkatinizi ve görev geçişinizi değerlendirir."; +"TRAILMAKING_INTENDED_USE2_A" = "Geri sayımdan sonra rakamlar ve harfler arasında dönüşümlü olarak noktalara dokunun. Önce “1” rakamına dokunarak başlayın, ardından “2” – “3” – “4”… rakamlarına dokunarak “7” rakamına ulaşın."; +"TRAILMAKING_INTENDED_USE2_B" = "Geri sayımdan sonra rakamlar ve harfler arasında dönüşümlü olarak noktalara dokunun. Önce “1” rakamına dokunarak başlayın, ardından ilk harf olan “A”ya sonra “2” – “B” – “3” – “C”… noktalarına dokunarak “7” rakamına ulaşın."; +"TRAILMAKING_INTRO_TEXT" = "Bunu hata yapmadan olabildiğince hızlı yapın. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Konuşma Tanıma"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Bu aktivite, konuşmanızı aygıtın en altındaki mikrofonla kaydeder ve metne çevirir."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Başlamak için Başla’ya dokunun."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Konuşmaya başlamadan önce kaydı başlatmak için düğmeye basın."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Kaydı Başlat"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Kaydı Durdur"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Dökümü Düzenle"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Konuşmadaki yanlış anlaşılmaları düzeltmek için döküm metnini düzenleyin."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Dökümünüz burada görünecektir."; +"SPEECH_RECOGNITION_FAILED" = "Konuşma tanıma başarısız oldu."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Konuşma tanıma sıfırlanamadı."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Sesi Çal"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Sesi Durdur"; +"SPEECH_IN_NOISE_TITLE" = "Gürültüde Konuşma"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Bu aktivite, gürültülü ortamlarda sunulduğunda konuşmanın anlaşılabilirliğini ölçer."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Bu testin bir parçası olarak şunları yapacaksınız:\n\nBir cümle dinleyin.\n\nDuyduğunuzu açıkça tekrar edin ya da bu kısmı atlayıp klavyeyi kullanarak duyduğunuzu yazın. \n\nDuyduğunuzu tekrar ederseniz, konuşma tanıma motoru tarafından oluşturulan dökümü değiştirme seçeneğiniz olacaktır."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Ses Düzeyi Ayarlama"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "“Sesi Çal”a dokunun, ses yüksekliğini sizi rahatsız etmeyecek bir düzeye ayarlayın ve ardından “Sesi Durdur”a dokunarak ilerleyin."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Dinle"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Rasgele Sinyal - Gürültü Oranı’nda (SNR) arka plan gürültüsü ile karışık bir cümle yalnızca bir sefer oynatılacaktır."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Seslendir"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Duyduğunuzu tekrar edin."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Dosya yaratılamadı"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Eşiğe ulaşmaya yetecek kadar günlük dosyası silinemedi"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Özelliği ayarlama hatası"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Dosya silinmiş (karşıya yüklenmiş) olarak işaretlenemedi"; +"ERROR_DATALOGGER_MULTIPLE" = "Günlükleri silmeyle ilgili birden fazla hata"; +"ERROR_RECORDER_NO_DATA" = "Toplanmış bir veri bulunamadı."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Çıkış dizini belirtilmemiş"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL Metre"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Bu aktivite, ortam ses baskısı düzeyini ölçer. Gürültü düzeyleri çok yüksekse, ilerleyemezsiniz. Lütfen bu görevi tamamlamak için daha sessiz bir konuma geçin ya da bu aktiviteyi daha sonra tekrar yapın."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Hesaplanıyor"; +"ENVIRONMENTSPL_THRESHOLD" = "Eşik: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Arka Plan Gürültüsü İyi"; +"ENVIRONMENTSPL_NOISE" = "Arka Plan Gürültüsü Çok Fazla"; +"ENVIRONMENTSPL_TITLE_2" = "Sessiz bir yer bulun"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Doğruluğu sağlamak için bu test sessiz bir ortamda yapılmalıdır."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Görevi Başlat"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Veri Yok"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Değeri girmek için sürgüyü hareket ettirin"; +"SLIDER_I_DONT_KNOW" = "Bilmiyorum"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Sayfa"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Geri"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "PDF Küçük Resmini Göster"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "PDF Küçük Resmini Gizle"; +"AX_BUTTON_ANNOTATE" = "Açıklama Ekle"; +"AX_BUTTON_SHOW_SEARCH" = "Arama Çubuğunu Göster"; +"AX_BUTTON_HIDE_SEARCH" = "Arama Çubuğunu Gizle"; +"AX_BUTTON_SHARE" = "Paylaş"; + + +"AX_COMPLETION_ILLUSTRATION" = "Mavi daire içinde onay işareti çizimi başarıyı gösterir"; + +"AX_SIGNVIEW_LABEL" = "Belirtilen imza alanı"; +"AX_SIGNVIEW_HINT" = "İmzalamak için ekrana dokunup parmağınızı hareket ettirin"; +"AX_SIGNVIEW_SIGNED" = "İmzalanmış"; +"AX_SIGNVIEW_UNSIGNED" = "İmzalanmamış"; + +"AX_SELECTED" = "Seçili"; +"AX_UNSELECTED" = "Seçili değil"; +"AX_SELECT_ALL_THAT_APPLY" = "UYGUN OLANLARIN TÜMÜNÜ SEÇİN"; + +"AX_SLIDER_LABEL" = "Yanıt sürgüsü. %@ ile %@ aralığında"; +"AX_UNLABELED_IMAGE" = "Etiketsiz görüntü"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Göreve başla"; + +"AX.MEMORY.TILE.ACTIVE" = "etkin"; +"AX.MEMORY.TILE.CORRECT" = "doğru"; +"AX.MEMORY.TILE.INCORRECT" = "yanlış"; +"AX.MEMORY.TILE.QUIESCENT" = "hareketsiz"; +"AX.MEMORY.TILE.LABEL" = "Bellek oyunu taşı"; + +"AX_IMAGE_CAPTURE_LABEL" = "Yakalanan görüntü önizlemesi"; +"AX_IMAGE_CAPTURED_LABEL" = "Yakalanmış görüntü"; + +"AX_VIDEO_CAPTURE_LABEL" = "Video yakalama önizlemesi"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Video çekimi tamamlandı"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "%@ büyüklüğündeki disk, %@ büyüklüğündeki diskin üzerine yerleştirilemez"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Hedef"; +"AX_TOWER_OF_HANOI_TOWER" = "Kule"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Diski yerleştirmek için çift dokunun"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "En üstteki diski seçmek için çift dokunun"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "%@ büyüklüklerinde disk içeriyor"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Boş"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Klavyeyi kapat"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "%@ - %@ aralığında"; +"AX_GRAPH_STACK_PREFIX" = "Yığın içeriği:"; +"AX_GRAPH_AND_SEPARATOR" = " ve "; +"AX_GRAPH_POINT_%@" = "Nokta: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Konuşma Dalga Biçimi"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Kayıt başlatıldığında, kaydı durdurmak için ikinci kez etkinleştirin."; + +"AX_AUDIO_BAR_GRAPH" = "Ses Çubuğu Grafiği"; + +"AX_AMSLER_GRID_LABEL" = "Amsler Izgarası"; +"AX_AMSLER_GRID_HINT" = "Doğrudan ızgarayı işaretlemek için parmağınızı veya ekran kalemini kullanın ya da bitirmek için ızgaranın dışına doğru sola kaydırın."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Dokunulabilir Düğmeler"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Sol Kulak İçin Dokun"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Teste başlamak için etkinleştirin. Test başladıktan sonra sol kulağınızda bir ses duyduğunuzda doğrudan bu düğmeye basın."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Sağ Kulak İçin Dokun"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Teste başlamak için etkinleştirin. Test başladıktan sonra sağ kulağınızda bir ses duyduğunuzda doğrudan bu düğmeye basın."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Düğmelerin nerede olduğunu öğrenmek için ekranı dokunarak VoiceOver ile keşfedin. Test başladığında düğmeler doğrudan dokunulabilir olur. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Bir Parmak İçin Dokun"; +"AX_TAP_BUTTON_2_LABEL" = "Diğer Parmak İçin Dokun"; +"AX_TAP_BUTTON_HINT" = "Düğmeleri doğrudan dokunulabilir yapmak için etkinleştirin."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Düğmelerin nerede olduğunu öğrenmek için ekranı dokunarak VoiceOver ile keşfedin. Düğmeleri doğrudan dokunulabilir yapmak için düğmelerden birini etkinleştirin."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Düğmeler artık doğrudan dokunulabilir."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ VoiceOver ile düğme doğrudan dokunulabilir olur ve ekranın merkezine yakın bir noktada konumlanır."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ VoiceOver ile test edilen düğmeler doğrudan dokunulabilir olur."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "restoreData kodu başlangıç için çözülemiyor"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..91f3b34 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/tr.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d hata) + other + (%d hata) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.strings new file mode 100755 index 0000000..4b56f08 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Згода"; +"CONSENT_NAME_GIVEN" = "Ім’я"; +"CONSENT_NAME_FAMILY" = "Прізвище"; +"CONSENT_NAME_PLACEHOLDER" = "Обов’язково"; +"CONSENT_REVIEW_TITLE" = "Огляд"; +"CONSENT_REVIEW_INSTRUCTION" = "Перегляньте подану нижче форму і торкніть «Погоджуюсь», якщо ви готові продовжити."; +"CONSENT_REVIEW_ALERT_TITLE" = "Огляд"; +"CONSENT_SIGNATURE_TITLE" = "Підпис"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Будь ласка, підпишіть пальцем у полі нижче."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Розпишіться тут"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Сторінка %1$ld із %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Ласкаво просимо"; +"CONSENT_SECTION_DATA_GATHERING" = "Збір даних"; +"CONSENT_SECTION_PRIVACY" = "Приватність"; +"CONSENT_SECTION_DATA_USE" = "Використання даних"; +"CONSENT_SECTION_STUDY_SURVEY" = "Дослідне опитування"; +"CONSENT_SECTION_STUDY_TASKS" = "Дослідні завдання"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Часове навантаження"; +"CONSENT_SECTION_WITHDRAWING" = "Відкликання"; +"CONSENT_LEARN_MORE_TITLE" = "Докладніше"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Докладніше про збір даних"; +"LEARN_MORE_DATA_USE" = "Докладніше про використання даних"; +"LEARN_MORE_PRIVACY" = "Докладніше про захист вашої приватності і особистих даних"; +"LEARN_MORE_WELCOME" = "Докладніше про дослідження"; +"LEARN_MORE_STUDY_SURVEY" = "Докладніше про дослідне опитування"; +"LEARN_MORE_TIME_COMMITMENT" = "Докладніше про те, скільки вашого часу треба на цей дослід"; +"LEARN_MORE_TASKS" = "Докладніше про залучені завдання"; +"LEARN_MORE_WITHDRAWING" = "Докладніше про відкликання"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Опції доступу"; +"CONSENT_SHARE_WIDELY_%@" = "Оприлюднити мої дані для %@ і кваліфікованих вчених в усьому світі"; +"CONSENT_SHARE_ONLY_%@" = "Оприлюднювати тільки для %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ отримає ваші дослідні дані завдяки вашій участі в цьому дослідженні.\n\nШирше оприлюднення ваших кодованих дослідних даних (без такої інформації, як ваше імʼя) може сприяти цьому і майбутнім дослідженням."; +"LEARN_MORE_CONSENT_SHARING" = "Докладніше про оприлюднення даних"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Імʼя друкованими літерами"; +"CONSENT_DOC_LINE_SIGNATURE" = "Підпис"; +"CONSENT_DOC_LINE_DATE" = "Дата"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ із %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Запитання %1$@ із %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Пропущено"; +"REVIEW_EDIT_ANSWER" = "Змінити"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Неправильне значення"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ перевищує максимально дозволене значення (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ є меншим мінімально дозволеного значення (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ не є правильним значенням."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Хибна адреса е-пошти: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Введіть адресу"; +"LOCATION_ERROR_TITLE" = "Не вдалося знайти вказану адресу"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Не вдається відстежити ваше поточне місце. Введіть адресу або перейдіть у місце з кращим сигналом GPS, якщо це можливо."; +"LOCATION_ERROR_MESSAGE_DENIED" = "У доступі до Служби локації відмовлено. Надайте цій програмі дозвіл на використання Служби локації у Параметрах."; +"LOCATION_ERROR_GEOCODE" = "Не вдається знайти збіги для введеної адреси. Перевірте правильність адреси."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Ви або не маєте інтернет-зʼєднання, або перевищили ліміт запитів пошуку адреси. Якщо ви не маєте інтернет-зʼєднання, увімкніть Wi-Fi, щоб відповісти на це запитання, пропустити це запитання, якщо кнопка пропуску доступна, або повертайтесь до опитування, коли матимете інтернет-зʼєднання. Інакше спробуйте ще раз за кілька хвилин."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Текстовий вміст перевищує ліміт: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "На розділеному екрані Камера недоступна."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Е-пошта"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "syabluchko@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Пароль"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Введіть пароль"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Підтвердити"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Введіть пароль ще раз"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Паролі не збігаються."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Додаткова інформація"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "Степан"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Яблучко"; +"GENDER_FORM_ITEM_TITLE" = "Стать"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Виберіть стать"; +"DOB_FORM_ITEM_TITLE" = "Дата народження"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Виберіть дату"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Номер телефону"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Перевірка"; +"VERIFICATION_STEP_TITLE" = "Перевірка е-пошти"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Торкніть наведене нижче посилання, якщо ви не отримали лист перевірки і хочете, щоб його надіслали повторно."; +"RESEND_EMAIL_BUTTON_TITLE" = "Надіслати лист перевірки ще раз"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Ім’я"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Забули пароль?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Введіть код допуску"; +"PASSCODE_CONFIRM_MESSAGE" = "Підтвердьте код"; +"PASSCODE_SAVED_MESSAGE" = "Код допуску збережено"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Код допуску прийнято"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Введіть старий код допуску"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Введіть новий код допуску"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Підтвердьте свій новий код"; +"PASSCODE_INVALID_ALERT_TITLE" = "Неправильний код допуску"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Незбіг кодів. Спробуйте ще раз."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Будь ласка, засвідчіть своїм Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Помилка Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Дозволено тільки цифри."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Індикатор перебігу вводу коду допуску"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Введено: %@ із %@"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Забули код допуску?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Не вдалося додати елемент до В'язки."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Не вдалося оновити елемент В'язки."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Не вдалося видалити елемент із В'язки."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Не вдалося знайти елемент В'язки."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A(II)+"; +"BLOOD_TYPE_A-" = "A(II)-"; +"BLOOD_TYPE_AB+" = "AB(IV)+"; +"BLOOD_TYPE_AB-" = "AB(IV)-"; +"BLOOD_TYPE_B+" = "B(III)+"; +"BLOOD_TYPE_B-" = "B(III)-"; +"BLOOD_TYPE_O+" = "O(I)+"; +"BLOOD_TYPE_O-" = "O(I)-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Тип I"; +"FITZPATRICK_SKIN_TYPE_II" = "Тип II"; +"FITZPATRICK_SKIN_TYPE_III" = "Тип III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Тип IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Тип V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Тип VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Жіноча"; +"GENDER_MALE" = "Чоловіча"; +"GENDER_OTHER" = "Інше"; + +/* Boolean answer strings */ +"BOOL_NO" = "Ні"; +"BOOL_YES" = "Так"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "см"; +"MEASURING_UNIT_FT" = "фт"; +"MEASURING_UNIT_IN" = "дм"; +"MEASURING_UNIT_KG" = "кг"; +"MEASURING_UNIT_LB" = "фнт"; +"MEASURING_UNIT_OZ" = "унц"; + +/* Limb values. */ +"LIMB_LEFT" = "ліва"; +"LIMB_RIGHT" = "права"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Торкніть, щоб відповісти"; +"NULL_ANSWER" = "Вибрати відповідь"; +"PLACEHOLDER_IMAGE_CHOICES" = "Торкніть, щоб вибрати"; +"PLACEHOLDER_LONG_TEXT" = "Торкніть, щоб написати"; + +/* Button titles */ +"BUTTON_AGREE" = "Погоджуюсь"; +"BUTTON_CANCEL" = "Скасувати"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Очистити"; +"BUTTON_CLEAR_SIGNATURE" = "Очистити підпис"; +"BUTTON_APPLY" = "Застосувати"; +"BUTTON_DISAGREE" = "Не погоджуюсь"; +"BUTTON_DONE" = "Готово"; +"BUTTON_GET_STARTED" = "Розпочати"; +"BUTTON_LEARN_MORE" = "Докладніше"; +"BUTTON_NEXT" = "Далі"; +"BUTTON_SKIP" = "Пропустити"; +"BUTTON_SKIP_QUESTION" = "Пропустити питання"; +"BUTTON_START_TIMER" = "Запустити таймер"; +"BUTTON_OPTION_SAVE" = "Пізніше"; +"BUTTON_OPTION_DISCARD" = "Відхилити результати"; +"BUTTON_OPTION_STOP_TASK" = "Завершити завдання"; +"BUTTON_SAVE" = "Зберегти"; +"BUTTON_CLEAR_ANSWER" = "Стерти відповідь"; +"BUTTON_READ_ONLY_MODE" = "Цю відповідь неможливо змінити."; +"BUTTON_COPYRIGHT" = "Авторське право"; +"BUTTON_CLOSE" = "Закрити"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Початок тесту через"; +"TASK_COMPLETE_TITLE" = "Дію виконано"; +"TASK_COMPLETE_TEXT" = "Ваші дані буде проаналізовано, і ви отримаєте сповіщення, коли будуть готові результати."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Ще %@."; +"TOUCH_ANYWHERE_LABEL" = "Торкніть будь-де, щоб продовжити"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Зробити знімок"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Зробити знімок ще раз"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Камери не знайдено. Неможливо виконати цей крок."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Щоб виконати цей крок, надайте цій програмі доступ до камери в Параметрах."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Для зроблених знімків не вказано вихідного каталогу."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Не вдається зберегти зроблений знімок."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Почати запис"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Зупинити запис"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Зняти відео ще раз"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Фітнес"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Відстань (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Пульс (уд./хв)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Сидіть зручно %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Ідіть якомога швидше %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Цей тест оцінює ваш серцевий ритм і обчислює, скільки ви можете пройти за %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Простуйте надворі своєю якнайшвидшою ходою %1$@. Упоравшись із завданням, присядьте і, зручно влаштувавшись, відпочиньте протягом %2$@. Щоб почати, торкніть «Розпочати»."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Хода і рівновага"; +"WALK_INTRO_TEXT" = "Цей тест оцінює вашу ходу і рівновагу під час ходіння і стояння. Не продовжуйте, якщо ви не можете безпечно ходити без допомоги."; +"WALK_INTRO_2_TEXT_%ld" = "Знайдіть місце, де ви можете безпечно зробити %ld кроків по прямій без допомоги."; +"WALK_INTRO_2_DETAIL" = "Покладіть свій пристрій у кишеню чи сумку і виконуйте аудіовказівки."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Тепер не рухайтесь %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Не рухайтесь %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Розверніться і йдіть туди, де ви почали."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Зробіть до %ld кроків по прямій."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Знайдіть місце, де ви можете безпечно пройтися туди й назад по прямій. Намагайтеся не зупинятися, розвертаючись у кінцях шляху, а ніби обходити дорожній конус.\n\nДалі вам накажуть обернутися повним колом і завмерти з руками по боках і ногами на ширині плечей."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Торкніть «Розпочати», коли ви готові починати.\nПотім покладіть свій пристрій у кишеню чи сумку і виконайте аудіовказівки."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Ідіть по прямій уперед і назад %@. Ідіть, як ви ходите зазвичай."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Пройдіть повну відстань по колу, потім зупиніться і не рухайтесь %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Ви виконали дію."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Темп торкання"; +"TAPPING_TASK_TITLE_RIGHT" = "Права рука"; +"TAPPING_TASK_TITLE_LEFT" = "Ліва рука"; +"TAPPING_INTRO_TEXT" = "Цей тест оцінює вашу швидкість торкання."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Покладіть свій пристрій на пласку поверхню."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Двома пальцями однієї руки по черзі торкайте кнопки на екрані."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Двома пальцями правої руки по черзі торкайте кнопки на екрані."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Двома пальцями лівої руки по черзі торкайте кнопки на екрані."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Тепер повторіть цей самий тест для правої руки."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Тепер повторіть цей самий тест для лівої руки."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Торкніть одним пальцем, потім іншим. Намагайтеся торкатися з якомога рівнішим інтервалом. Торкайте далі %@."; +"TAPPING_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Торкніть «Далі», щоб почати."; +"TAP_BUTTON_TITLE" = "Торкнути"; +"TOTAL_TAPS_LABEL" = "Всього дотиків"; +"TAPPING_INSTRUCTION" = "Торкайте кнопки двома пальцями якомога послідовніше."; +"TAPPING_INSTRUCTION_RIGHT" = "Торкайте кнопки ПРАВОЮ рукою."; +"TAPPING_INSTRUCTION_LEFT" = "Торкайте кнопки ЛІВОЮ рукою."; +"TAPPING_SKIP_TITLE" = "Минути цю руку"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Сітка Амслера"; +"AMSLER_GRID_INTRO_TEXT" = "Ця вправа допомагає виявляти проблеми із зором користувача."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Тримайте пристрій на рівні очей на відстані 30 см (12 дюймів) від обличчя під час усього тесту."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Закрийте своє %@ і пильно дивіться на крапку в центрі квадратної сітки.\n\nПальцем чи стилусом позначте всі видимі спотворення, як-от розмиті або хвилясті лінії.\n\nКоли завершите, посуньте вліво поза сіткою."; +"AMSLER_GRID_LEFT_EYE" = "Ліве око"; +"AMSLER_GRID_RIGHT_EYE" = "Праве око"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Голос"; +"AUDIO_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"AUDIO_INSTRUCTION" = "Вимовляйте «А-а-а-а» у мікрофон якомога довше."; +"AUDIO_INTRO_TEXT" = "Зробіть глибокий подих і вимовляйте «А-а-а-а» у мікрофон якомога довше. Тримайте однакову гучність голосу, щоб смуги звуку залишалися синіми."; +"AUDIO_INTENDED_USE" = "Цей тест оцінює ваш голос, записуючи його за допомогою мікрофона внизу вашого пристрою."; +"AUDIO_TOO_LOUD_LABEL" = "Надто гучно"; +"AUDIO_GENERIC_ERROR_LABEL" = "Не вдається записати аудіо"; +"AUDIO_LEVEL_CHECK_LABEL" = "Будь ласка, зачекайте, поки ми перевіряємо рівень фонового шуму."; +"AUDIO_TOO_LOUD_MESSAGE" = "Рівень навколишнього шуму зависокий для записування голосу. Будь ласка, повторіть спробу у тихішому місці."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Торкніть «Далі», коли ви готові."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Аудіометрія"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Цей тест вимірює вашу здатність чути різні звуки."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Переш ніж починати, приєднайте навушники до пристрою й одягніть їх.\n\nЗвук буде ледь чутним, на відміну від звуку звичайних оповіщень.  Гучність звуку поволі наростатиме.  Будь ласка, будьте уважні й вказуйте, в якому вусі ви почули звук, торкаючи ліву чи праву кнопку."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Зараз ви маєте почути тональний сигнал. Регулюйте гучність кнопками на боці свого пристрою.\n\nТоркніть будь-яку кнопку на екрані, щоб розпочати."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Щоразу почувши звук, торкайте ліву чи праву кнопку, щоб вказати, яким вухом ви чули цей звук."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Ліве вухо"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Праве вухо"; +"TONE_LABEL_%@_LEFT" = "%@ Гц, зліва"; +"TONE_LABEL_%@_RIGHT" = "%@ Гц, справа"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Аудіометрія"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Торкніть, коли почуєте тональний сигнал."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Тон і Гучність"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Ви почуєте серію тональних сигналів."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Почувши тональний сигнал, торкніть цю кнопку."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Для цього тесту буде задано гучність на рівні 50 відсотків."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Цей тест триває приблизно 10 хвилин."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Увімкніть «Не турбувати», щоб запобігти втручанням."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Тональні сигнали спочатку відтворюватимуться у вашому правому вусі."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Тональні сигнали тепер відтворюватимуться у вашому лівому вусі."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Цей тест визначає порогові рівні слуху особи за шкалою dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Упевніться, що задано максимальний рівень гучності.\n\nПід час цього завдання в ліве або праве вухо буде відтворюватися ледь чутний сигнал.\n\nУважно слухайте і торкайте кнопку, щоразу як чуєте сигнал."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Цей тест виявляє, наскільки гучним має бути звук, аби ви його почули."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Реєстраційна анкета."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Виберіть вухо, яким ви чуєте краще, якщо таке є"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "ліве"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "праве"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "немає"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Тест скасовано"; +"dBHL_ALERT_TITLE_START_OVER" = "З початку"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Скасувати тест"; +"dBHL_ALERT_TEXT" = "Перепідʼєднайте свої AirPods або EarPods, щоб виконати цей тест."; +"dBHL_PROGRESS_COMPLETION_%@" = "%@ виконано"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Навушники"; +"HEADPHONES_UNKNOWN" = "Невідомі"; +"HEADPHONES_NONE" = "Немає"; +"CONNECTED" = "Зʼєднано"; +"NOT_CONNECTED" = "Не зʼєднано"; +"HEADPHONE_CONNECTED_%@" = "Зʼєднано - %@"; +"HEADPHONE_DETECT_TITLE" = "Підʼєднайте свої навушники"; +"HEADPHONE_DETECT_TEXT" = "Для цього тесту необхідні Apple AirPods або Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Просторова пам’ять"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Цей тест оцінює вашу короткострокову пам’ять, коли вам потрібно повторити порядок загоряння %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "квітки"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "квітки"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Деякі %@ будуть загорятися по черзі. Торкайте ці %@ у такому самому порядку загоряння."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Деякі %@ будуть загорятися по черзі. Торкайте %@ у зворотному порядку їх загоряння."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Щоб почати, торкніть «Розпочати», потім уважно слідкуйте."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Рахунок"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Слідкуйте, як загоряються %@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Торкайте %@ у порядку, у якому вони загоряються"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Торкайте %@ у зворотному порядку"; +"MEMORY_GAME_COMPLETE_TITLE" = "Послідовність виконано"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Щоб продовжити, торкніть «Далі»"; +"MEMORY_GAME_FAILED_TITLE" = "Повторити спробу"; +"MEMORY_GAME_FAILED_MESSAGE" = "Вам трохи не вдалося вкластися в цей час. Торкніть «Далі», щоб продовжити."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Час завершився"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Ваш час минув.\nТоркніть «Далі», щоб продовжити."; +"MEMORY_GAME_COMPLETE" = "Гру виконано"; +"MEMORY_GAME_PAUSED_TITLE" = "Припинено"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Щоб продовжити, торкніть «Далі»"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Тест на памʼять було розроблено за сприяння Кетрін Поссін, Ph.D і Джоель Крамер, Ph.D з Університету Каліфорнії в Сан-Франціско."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Час реакції"; +"REACTION_TIME_TASK_INTENDED_USE" = "Цей тест оцінює час, потрібний вам, щоб зреагувати на візуальну команду."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Трясніть пристроєм в будь-який бік, щойно на екрані з’явиться синя точка. Вас попросять зробити це кілька разів: %D."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Спроба %@ із %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Швидко трусніть пристроєм, коли з’явиться синє коло"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Тест Струпа"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Щоразу коли зʼявляється слово, вибирайте першу букву назви показаного КОЛЬОРУ."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "За готовності починати тест Струпа торкніть «Розпочати»."; +"STROOP_TASK_STEP_TEXT" = "Вибирайте першу букву назви показаного КОЛЬОРУ."; +"STROOP_COLOR_RED" = "ЧЕРВОНИЙ"; +"STROOP_COLOR_GREEN" = "ЗЕЛЕНИЙ"; +"STROOP_COLOR_BLUE" = "СИНІЙ"; +"STROOP_COLOR_YELLOW" = "ЖОВТИЙ"; +"STROOP_COLOR_RED_INITIAL" = "Ч"; +"STROOP_COLOR_GREEN_INITIAL" = "З"; +"STROOP_COLOR_BLUE_INITIAL" = "С"; +"STROOP_COLOR_YELLOW_INITIAL" = "Ж"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Ханойська вежа"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Цей тест оцінює вашу здібність до розв’язання головоломок."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Перенесіть весь стос на виділену платформу мінімальною кількістю ходів."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Розв’яжіть головоломку"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Кількість ходів: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Я не можу розв’язати цю головоломку"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Діапазон руху"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "Опція кінцівки має бути «ліва» чи «права»"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Межі руху лівого коліна"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Межі руху правого коліна"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Цей тест оцінює, наскільки ви можете вирівняти ногу в лівому коліні."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Цей тест оцінює, наскільки ви можете вирівняти ногу в правому коліні."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Сідайте на край стільця. Почніть, поклавши свій пристрій на ліве коліно для вимірювання. Будь ласка, увімкніть звук на своєму пристрою, щоб чути вказівки."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Сідайте на край стільця. Почніть, поклавши свій пристрій на праве коліно для вимірювання. Будь ласка, увімкніть звук на своєму пристрою, щоб чути вказівки."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Покладіть свій пристрій на ліве коліно екраном назовні, як показано."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Покладіть свій пристрій на праве коліно екраном назовні, як показано."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Коли будете готові, торкніть екран, щоб почати, і випряміть свою ліву ногу в коліні якомога далі. Поверніться у вихідну позицію і торкніть ще раз, коли закінчите."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Коли будете готові, торкніть екран, щоб почати, і випряміть свою праву ногу в коліні якомога далі. Поверніться у вихідну позицію і торкніть ще раз, коли закінчите."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Покладіть свій пристрій на ліве коліно. Торкніть екран і випряміть свою ліву ногу в коліні якомога далі."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Покладіть свій пристрій на праве коліно. Торкніть екран і випряміть свою праву ногу в коліні якомога далі."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Виконавши, поверніть своє ліве коліно у вихідне положення. Потім торкніть будь-де."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Виконавши, поверніть своє праве коліно у вихідне положення. Потім торкніть будь-де."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Межі руху лівого плеча"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Межі руху правого плеча"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Цей тест оцінює, наскільки ви можете вирівняти руку в лівому плечі."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Цей тест оцінює, наскільки ви можете вирівняти руку в правому плечі."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Почніть, поклавши свій пристрій на ліве плече для вимірювання. Будь ласка, увімкніть звук на своєму пристрою, щоб чути вказівки."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Почніть, поклавши свій пристрій на праве плече для вимірювання. Будь ласка, увімкніть звук на своєму пристрою, щоб чути вказівки."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Покладіть свій пристрій на ліве плече екраном назовні, як показано."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Покладіть свій пристрій на праве плече екраном назовні, як показано."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Коли будете готові, торкніть екран, щоб почати, і підніміть свою ліву руку якомога вище. Поверніться у вихідну позицію і торкніть ще раз, коли закінчите."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Коли будете готові, торкніть екран, щоб почати, і підніміть свою праву руку якомога вище. Поверніться у вихідну позицію і торкніть ще раз, коли закінчите."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Покладіть свій пристрій на ліве плече. Торкніть екран і підніміть свою ліву руку якомога вище."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Покладіть свій пристрій на праве плече. Торкніть екран і підніміть свою праву руку якомога вище."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Виконавши, поверніть свою ліву руку у вихідне положення. Потім торкніть будь-де."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Виконавши, поверніть свою праву руку у вихідне положення. Потім торкніть будь-де."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Ходіння за часом"; +"TIMED_WALK_INTRO_DETAIL" = "Цей тест оцінює роботу ваших нижніх кінцівок."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Знайдіть місце, бажано просто неба, де ви без ризику можете якнайшвидше пройти приблизно %@ по прямій. Не сповільнюйте темп, доки не перетнете фінішну лінію."; +"TIMED_WALK_INTRO_2_DETAIL" = "Торкніть «Далі», щоб почати."; +"TIMED_WALK_FORM_TITLE" = "Допоміжний засіб"; +"TIMED_WALK_FORM_TEXT" = "Вживайте однаковий допоміжний засіб для всіх тестів."; +"TIMED_WALK_QUESTION_TEXT" = "Ви носите гомілкостопний біопротез?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Ви користуєтесь допоміжними засобами?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Торкніть тут і виберіть відповідь."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Жодним"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Однобічна тростина"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Однобічна милиця"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Двобічна тростина"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Двобічна милиця"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Ходунки/ролятор"; +"TIMED_WALK_INSTRUCTION_%@" = "Пройдіть до %@ по прямій."; +"TIMED_WALK_INSTRUCTION_TURN" = "Розверніться."; +"TIMED_WALK_INSTRUCTION_2" = "Поверніться туди, де ви почали."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Торкніть «Далі», коли виконаєте."; + +/* PSAT active task. */ +"PASAT_TITLE" = "СТСЗТ"; +"PVSAT_TITLE" = "ВТСЗТ"; +"PAVSAT_TITLE" = "ВСТСЗТ"; +"PASAT_INTRO_TEXT" = "Слуховий тест на складання у заданому темпі вимірює швидкість обробки вами слухової інформації та вашу здібність до обчислення."; +"PVSAT_INTRO_TEXT" = "Візуальний тест на складання у заданому темпі вимірює швидкість обробки вами візуальної інформації та вашу здібність до обчислення."; +"PAVSAT_INTRO_TEXT" = "Слуховий і візуальний тест на складання у заданому темпі вимірює швидкість обробки вами слухової і візуальної інформації та вашу здібність до обчислення."; +"PSAT_INTRO_TEXT_2_%@" = "Однорозрядні числа показуються з інтервалом %@.\nВи маєте додавати кожну нову цифру до цифри, що їй передує.\nМайте на увазі, що вам слід підраховувати не проміжний підсумок, а лише суму двох останніх чисел."; +"PSAT_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"PSAT_INITIAL_INSTRUCTION" = "Запам’ятайте цю першу цифру."; +"PSAT_INSTRUCTION" = "Додайте це нове число до попереднього."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Кілковий тест на %@ отворів"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Цей тест оцінює функцію ваших верхніх кінцівок, коли вам потрібно покласти кілок в отвір. Вас попросять зробити це %@ разів."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Тестуванню підлягають ваша ліва і права рука.\nВи маєте взяти кілок якомога швидше, поставити в отвір, і зробивши це %@ разів, вилучити його знов %@ разів."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Тестуванню підлягають ваша права і ліва рука.\nВи маєте взяти кілок якомога швидше, поставити в отвір, і зробивши це %@ разів, вилучити його знов %@ разів."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Покладіть кілок в отвір лівою рукою."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Покладіть кілок в отвір правою рукою."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Покладіть кілок за лінію лівою рукою."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Покладіть кілок за лінію правою рукою."; +"HOLE_PEG_TEST_TEXT" = "Візьміть кілок двома пальцями."; +"HOLE_PEG_TEST_TEXT_2" = "Підніміть пальці, щоб опустити кілок."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Тест на тремтіння"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Цей тест вимірює рівень тремтіння рук у різних положеннях. Знайдіть місце, де можна зручно сидіти протягом виконання цього тесту."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Тримайте телефон у найбільш ураженій руці, як це показано на зображенні нижче."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Тримайте телефон у ПРАВІЙ руці, як це показано на зображенні нижче."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Тримайте телефон у ЛІВІЙ руці, як це показано на зображенні нижче."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Вам буде запропоновано виконати %@, сидячи з телефоном у руці."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "завдання"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "два завдання"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "три завдання"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "чотири завдання"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "пʼять завдань"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Торкніть «Далі», щоб продовжити."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Готуйтеся тримати телефон на колінах."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Готуйтеся тримати телефон на колінах ЛІВОЮ рукою."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Готуйтеся тримати телефон на колінах ПРАВОЮ рукою."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Тримайте телефон далі на колінах протягом %ld секунд."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Тепер тримайте телефон рукою, протягнутою на рівні плечей."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Тепер тримайте телефон у ЛІВІЙ руці із зігнутим ліктем, протягнутою на рівні плечей."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Тепер тримайте телефон у ПРАВІЙ руці із зігнутим ліктем, протягнутою на рівні плечей."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Тримайте телефон далі простягнутою рукою протягом %ld секунд."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Тепер тримайте телефон на висоті плечей у руці із зігнутим ліктем."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Тепер тримайте телефон у ЛІВІЙ руці із зігнутим ліктем на рівні плечей."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Тепер тримайте телефон у ПРАВІЙ руці із зігнутим ліктем на рівні плечей."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Тримайте телефон далі в руці з зігнутим ліктем протягом %ld секунд"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Тепер, не розгинаючи ліктя, торкайтеся неодноразово телефоном свого носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Тепер, тримаючи телефон у ЛІВІЙ руці із зігнутим ліктем, торкайтеся неодноразово телефоном свого носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Тепер, тримаючи телефон у ПРАВІЙ руці із зігнутим ліктем, торкайтеся неодноразово телефоном свого носа."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Торкайтеся далі телефоном свого носа протягом %ld секунд"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Готуйтеся махати, як це робить королева (вертячи запʼястком)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Готуйтеся махати телефоном у ЛІВІЙ руці, як це робить королева (вертячи запʼястком)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Готуйтеся махати телефоном у ПРАВІЙ руці, як це робить королева (вертячи запʼястком)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Виконуйте махання королеви далі протягом %ld секунд."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Тепер перекладіть телефон у ЛІВУ руку, і перейдіть до наступного завдання."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Тепер перекладіть телефон у ПРАВУ руку, і перейдіть до наступного завдання."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Перейдіть до наступного завдання."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Дію виконано."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Вам буде запропоновано виконати %@, сидячи з телефоном спочатку в одній руці, потім ще раз в іншій руці."; +"TREMOR_SKIP_LEFT_HAND" = "Я не можу виконати цю дію ЛІВОЮ рукою."; +"TREMOR_SKIP_RIGHT_HAND" = "Я не можу виконати цю дію ПРАВОЮ рукою."; +"TREMOR_SKIP_NEITHER" = "Я можу виконати цю дію обома руками."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Побудова сліду"; +"TRAILMAKING_INTENDED_USE" = "Цей тест оцінює рівень вашої зорової уважності та здатність перемикатися між завданнями, фіксуючи, скільки потрібно часу, щоб торкнути серію крапок по черзі."; +"TRAILMAKING_INTENDED_USE2_A" = "Після вступного відліку торкайте крапки, змінюючи черговість між цифрами і буквами. Почніть торканням першої цифри «1», потім торкайте цифри «2» – «3» – «4»…, доки не дійдете до цифри «7»."; +"TRAILMAKING_INTENDED_USE2_B" = "Після вступного відліку торкайте крапки, змінюючи черговість між цифрами і буквами. Почніть торканням першої цифри «1», потім торкніть першу букву «А», а після неї «2» – «Б» – «3» − «В»…, доки не дійдете до цифри «7»."; +"TRAILMAKING_INTRO_TEXT" = "Зробіть це якомога швидше, не припускаючись помилок. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"TRAILMAKING_LETTER_A" = "А"; +"TRAILMAKING_LETTER_B" = "Б"; +"TRAILMAKING_LETTER_C" = "В"; +"TRAILMAKING_LETTER_D" = "Г"; +"TRAILMAKING_LETTER_E" = "Ґ"; +"TRAILMAKING_LETTER_F" = "Д"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Розпізнання мови"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Цей тест записує ваше мовлення за допомогою мікрофона внизу пристрою і перекладає його на текст."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Торкніть «Розпочати», щоб почати."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Тисніть кнопку, щоб почати записування перед мовленням."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Почати запис"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Зупинити запис"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Зміна транскрипції"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Редагуйте транскрипцію для усунення всіх хибних тлумачень вашого мовлення."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Ваша транскрипція зʼявлятиметься тут."; +"SPEECH_RECOGNITION_FAILED" = "Збій розпізнання мовлення."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Збій ініціалізації розпізнання мовлення."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Відтворити аудіо"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Припинити аудіо"; +"SPEECH_IN_NOISE_TITLE" = "Мовлення в шумі"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Цей тест вимірює розбірність мовлення в умовах шумного середовища."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "У рамках цього тесту ви маєте:\n\nПрослухати речення.\n\nЧітко повторити те, що почули, або перейти одразу до введення того, що ви почули, на клавіатурі. \n\nЯкщо ви повторите те, що почули, то матимете можливість редагувати транскрипцію, яку згенерувала система розпізнання мовлення."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Калібрування гучності"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Торкніть «Відтворити аудіо», установіть комфортний рівень гучності і потім торкніть «Зупинити аудіо», щоб продовжити."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Слухати"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Речення, змішане з фоновим шумом при довільному відношенні сигнал/шум (ВСШ), буде відтворено лише раз."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Промовити"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Повторіть, що почули."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Не вдалося створити файл"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Не вдалося вилучити достатньо файлів журналів, щоб досягти порогу"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Помилка задання атрибуту"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Файл не позначено як видалений (не позначено як відвантажений)"; +"ERROR_DATALOGGER_MULTIPLE" = "Кілька помилок під час вилучення журналів"; +"ERROR_RECORDER_NO_DATA" = "Не знайдено жодних зібраних даних."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Не задано вихідний каталог"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Покажчик РЗТ"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Цей тест вимірює рівень звукового тиску. Якщо рівні шуму зависокі, ви не зможете продовжити. Будь ласка, перейдіть у тихіше місце для виконання цього завдання або пройдіть цей тест ще раз згодом."; +"ENVIRONMENTSPL_UNIT" = "дБ"; +"ENVIRONMENTSPL_CALCULATING" = "Обчислювання"; +"ENVIRONMENTSPL_THRESHOLD" = "Поріг: %@ дБ"; +"ENVIRONMENTSPL_OK" = "Фоновий шум у нормі"; +"ENVIRONMENTSPL_NOISE" = "Забагато фонового шуму"; +"ENVIRONMENTSPL_TITLE_2" = "Знайдіть тихе місце"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Щоб гарантувати точність, цей тест слід проводити в тихому середовищі."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Почати завдання"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Немає даних"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Рухайте повзунок для вводу значення"; +"SLIDER_I_DONT_KNOW" = "Я не знаю"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Сторінка"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Назад"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Показати PDF-мініатюри"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Сховати PDF-мініатюри"; +"AX_BUTTON_ANNOTATE" = "Анотувати"; +"AX_BUTTON_SHOW_SEARCH" = "Показати смугу пошуку"; +"AX_BUTTON_HIDE_SEARCH" = "Сховати смугу пошуку"; +"AX_BUTTON_SHARE" = "Оприлюднити"; + + +"AX_COMPLETION_ILLUSTRATION" = "Ілюстрація галочки в синьому колі на позначення успіху"; + +"AX_SIGNVIEW_LABEL" = "Спеціальне поле для підпису"; +"AX_SIGNVIEW_HINT" = "Торкніть екран і рухайте пальцем, щоб поставити підпис"; +"AX_SIGNVIEW_SIGNED" = "Підписано"; +"AX_SIGNVIEW_UNSIGNED" = "Без підпису"; + +"AX_SELECTED" = "Вибрано"; +"AX_UNSELECTED" = "Вибір скасовано"; +"AX_SELECT_ALL_THAT_APPLY" = "ВИБЕРІТЬ УСІ ДОРЕЧНІ"; + +"AX_SLIDER_LABEL" = "Повзунок відповіді. Діапазон від %@ до %@"; +"AX_UNLABELED_IMAGE" = "Зображення без мітки"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Почати завдання"; + +"AX.MEMORY.TILE.ACTIVE" = "активна"; +"AX.MEMORY.TILE.CORRECT" = "правильно"; +"AX.MEMORY.TILE.INCORRECT" = "неправильно"; +"AX.MEMORY.TILE.QUIESCENT" = "неактивний"; +"AX.MEMORY.TILE.LABEL" = "Клітинка тесту на пам’ять"; + +"AX_IMAGE_CAPTURE_LABEL" = "Перегляд знімку"; +"AX_IMAGE_CAPTURED_LABEL" = "Зроблений знімок"; + +"AX_VIDEO_CAPTURE_LABEL" = "Перегляд знятого відео"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Запис відео виконано"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Неможливо розмістити диск розміру %@ на диск розміру %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Ціль"; +"AX_TOWER_OF_HANOI_TOWER" = "Вежа"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Торкніть двічі, щоб розмістити диск"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Торкніть двічі, щоб вибрати верхній диск"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Має диски з розмірами %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Пусто"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Прибрати клавіатуру"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Діапазон від %@ до %@"; +"AX_GRAPH_STACK_PREFIX" = "Стос, створений із"; +"AX_GRAPH_AND_SEPARATOR" = " і "; +"AX_GRAPH_POINT_%@" = "Точка: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Форма хвилі мовлення"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Коли почнеться записування, активуйте вдруге, щоб припинити записування."; + +"AX_AUDIO_BAR_GRAPH" = "Аудіографік"; + +"AX_AMSLER_GRID_LABEL" = "Сітка Амслера"; +"AX_AMSLER_GRID_HINT" = "Пальцем або стилусом робіть позначки прямо на сітці або посуньте вліво поза сіткою, щоб завершити."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Прямолінійні кнопки"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Торкніть для лівого вуха"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Активуйте, щоб розпочати тест. Коли тест розпочнеться, просто торкайте цю кнопку, почувши будь-який звук своїм лівим вухом."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Торкніть для правого вуха"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Активуйте, щоб розпочати тест. Коли тест розпочнеться, просто торкайте цю кнопку, почувши будь-який звук своїм правим вухом."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ За допомогою VoiceOver досліджуйте екран дотиком, аби вивчити, де розташовано кнопки для кожного вуха. Коли тест розпочнеться, цих кнопок можна буде просто торкатися. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Торкніть для одного пальця"; +"AX_TAP_BUTTON_2_LABEL" = "Торкніть для іншого пальця"; +"AX_TAP_BUTTON_HINT" = "Активуйте, щоб кнопок можна було просто торкатися."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ За допомогою VoiceOver досліджуйте екран дотиком, аби вивчити де розташовано кнопки. Активуйте будь-яку з кнопок, щоб кнопок можна було просто торкатися."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Кнопок відтепер можна просто торкатися."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ За допомогою VoiceOver цієї кнопки можна буде просто торкатися. Її буде розташовано біля центру екрана."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ За допомогою VoiceOver цих кнопок у тесті можна буде просто торкатися."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Не вдається декодувати restoreData для ініціалізації"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..46b65cf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/uk.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d помилка) + other + (%d помилки) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.strings new file mode 100755 index 0000000..7150550 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "Đồng ý"; +"CONSENT_NAME_GIVEN" = "Tên"; +"CONSENT_NAME_FAMILY" = "Họ"; +"CONSENT_NAME_PLACEHOLDER" = "Bắt buộc"; +"CONSENT_REVIEW_TITLE" = "Xem lại"; +"CONSENT_REVIEW_INSTRUCTION" = "Hãy xem xét biểu mẫu bên dưới và chạm vào Đồng ý nếu bạn sẵn sàng tiếp tục."; +"CONSENT_REVIEW_ALERT_TITLE" = "Xem lại"; +"CONSENT_SIGNATURE_TITLE" = "Chữ ký"; +"CONSENT_SIGNATURE_INSTRUCTION" = "Vui lòng ký tên bằng ngón tay của bạn trong hộp bên dưới."; +"CONSENT_SIGNATURE_PLACEHOLDER" = "Ký vào đây"; +"CONSENT_PAGE_NUMBER_FORMAT" = "Trang %1$ld / %2$ld"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "Chào mừng"; +"CONSENT_SECTION_DATA_GATHERING" = "Thu thập Dữ liệu"; +"CONSENT_SECTION_PRIVACY" = "Quyền riêng tư"; +"CONSENT_SECTION_DATA_USE" = "Sử dụng Dữ liệu"; +"CONSENT_SECTION_STUDY_SURVEY" = "Khảo sát Nghiên cứu"; +"CONSENT_SECTION_STUDY_TASKS" = "Nhiệm vụ Nghiên cứu"; +"CONSENT_SECTION_TIME_COMMITMENT" = "Cam kết Thời gian"; +"CONSENT_SECTION_WITHDRAWING" = "Rút lui"; +"CONSENT_LEARN_MORE_TITLE" = "Tìm hiểu Thêm"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "Tìm hiểu thêm về cách thu thập dữ liệu"; +"LEARN_MORE_DATA_USE" = "Tìm hiểu thêm về cách sử dụng dữ liệu"; +"LEARN_MORE_PRIVACY" = "Tìm hiểu thêm về cách bảo vệ quyền riêng tư và nhận dạng của bạn"; +"LEARN_MORE_WELCOME" = "Trước tiên, tìm hiểu thêm về nghiên cứu"; +"LEARN_MORE_STUDY_SURVEY" = "Tìm hiểu thêm về khảo sát nghiên cứu"; +"LEARN_MORE_TIME_COMMITMENT" = "Tìm hiểu thêm về tác động của nghiên cứu đối với thời gian của bạn"; +"LEARN_MORE_TASKS" = "Tìm hiểu thêm về các nhiệm vụ liên quan"; +"LEARN_MORE_WITHDRAWING" = "Tìm hiểu thêm về việc rút lui"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "Tùy chọn Chia sẻ"; +"CONSENT_SHARE_WIDELY_%@" = "Chia sẻ dữ liệu của tôi với %@ và các nhà nghiên cứu đủ chuyên môn trên thế giới"; +"CONSENT_SHARE_ONLY_%@" = "Chỉ chia sẻ dữ liệu của tôi với %@"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@ sẽ nhận được dữ liệu nghiên cứu của bạn từ quá trình bạn tham gia nghiên cứu này.\n\nViệc chia sẻ rộng rãi hơn dữ liệu nghiên cứu được mã hóa của bạn (không có thông tin như tên của bạn) có thể giúp ích cho nghiên cứu này và các công trình trong tương lai."; +"LEARN_MORE_CONSENT_SHARING" = "Tìm hiểu thêm về chia sẻ dữ liệu"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "Tên viết hoa"; +"CONSENT_DOC_LINE_SIGNATURE" = "Chữ ký"; +"CONSENT_DOC_LINE_DATE" = "Ngày"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@ / %2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "Câu hỏi %1$@ / %2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "Đã bỏ qua"; +"REVIEW_EDIT_ANSWER" = "Sửa"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "Giá trị không hợp lệ"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@ vượt quá giá trị tối đa được phép (%2$@)."; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@ nhỏ hơn giá trị tối thiểu được phép (%2$@)."; +"RANGE_ALERT_MESSAGE_OTHER" = "%@ không phải giá trị hợp lệ."; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "Địa chỉ email không hợp lệ: %@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "Nhập một địa chỉ"; +"LOCATION_ERROR_TITLE" = "Không thể Tìm thấy Địa chỉ Được chỉ định"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "Không thể xử lý vị trí hiện tại của bạn. Vui lòng nhập địa chỉ hoặc di chuyển đến một vị trí có tín hiệu GPS tốt hơn nếu có thể."; +"LOCATION_ERROR_MESSAGE_DENIED" = "Truy cập vào dịch vụ định vị này đã bị từ chối. Vui lòng cấp quyền cho ứng dụng này sử dụng dịch vụ định vị qua phần Cài đặt."; +"LOCATION_ERROR_GEOCODE" = "Không thể tìm thấy kết quả cho địa chỉ đã nhập. Vui lòng đảm bảo địa chỉ này hợp lệ."; +"LOCATION_ERROR_GEOCODE_NETWORK" = "Bạn không được kết nối vào internet hoặc bạn đã vượt quá số lượng yêu cầu tra cứu địa chỉ tối đa. Nếu bạn không được kết nối vào internet, vui lòng bật Wi-Fi để trả lời câu hỏi này, bỏ qua câu hỏi này nếu có nút bỏ qua hoặc quay trở lại bản khảo sát khi bạn được kết nối vào internet. Nếu không, vui lòng thử lại sau một vài phút nữa."; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "Nội dung văn bản vượt quá độ dài tối đa: %@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "Camera không có sẵn trong chế độ màn hình tách rời."; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "Email"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "Mật khẩu"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "Nhập mật khẩu"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "Xác nhận"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "Nhập lại mật khẩu"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "Các mật khẩu không khớp."; +"ADDITIONAL_INFO_SECTION_TITLE" = "Thông tin Bổ sung"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "Giới tính"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "Chọn giới tính"; +"DOB_FORM_ITEM_TITLE" = "Ngày sinh"; +"DOB_FORM_ITEM_PLACEHOLDER" = "Chọn một ngày"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "Số điện thoại"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "Xác minh"; +"VERIFICATION_STEP_TITLE" = "Xác minh Email của bạn"; +"RESEND_EMAIL_LABEL_MESSAGE" = "Chạm vào liên kết bên dưới nếu bạn không nhận được email xác minh và muốn được gửi lại."; +"RESEND_EMAIL_BUTTON_TITLE" = "Gửi lại Email Xác minh"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "Đăng nhập"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "Quên mật khẩu?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "Nhập mật mã"; +"PASSCODE_CONFIRM_MESSAGE" = "Xác nhận mật mã"; +"PASSCODE_SAVED_MESSAGE" = "Đã lưu mật mã"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "Đã xác thực mật mã"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "Nhập mật mã cũ của bạn"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "Nhập mật mã mới của bạn"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "Xác nhận mật mã mới của bạn"; +"PASSCODE_INVALID_ALERT_TITLE" = "Mật mã không đúng"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "Các mật mã không khớp. Thử lại."; +"PASSCODE_TOUCH_ID_MESSAGE" = "Vui lòng xác thực bằng Touch ID"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Lỗi Touch ID"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "Chỉ cho phép các ký tự số."; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "Chỉ báo tiến trình nhập mật mã"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "Đã nhập %@ / %@ số"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "Bạn quên mật mã?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "Không thể thêm mục Chuỗi khóa."; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "Không thể cập nhật mục Chuỗi khóa."; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "Không thể xóa mục Chuỗi khóa."; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "Không thể tìm mục Chuỗi khóa."; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "Loại I"; +"FITZPATRICK_SKIN_TYPE_II" = "Loại II"; +"FITZPATRICK_SKIN_TYPE_III" = "Loại III"; +"FITZPATRICK_SKIN_TYPE_IV" = "Loại IV"; +"FITZPATRICK_SKIN_TYPE_V" = "Loại V"; +"FITZPATRICK_SKIN_TYPE_VI" = "Loại VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "Nữ"; +"GENDER_MALE" = "Nam"; +"GENDER_OTHER" = "Khác"; + +/* Boolean answer strings */ +"BOOL_NO" = "Không"; +"BOOL_YES" = "Có"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "cm"; +"MEASURING_UNIT_FT" = "ft"; +"MEASURING_UNIT_IN" = "in"; +"MEASURING_UNIT_KG" = "kg"; +"MEASURING_UNIT_LB" = "pao"; +"MEASURING_UNIT_OZ" = "oz"; + +/* Limb values. */ +"LIMB_LEFT" = "trái"; +"LIMB_RIGHT" = "phải"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "Chạm để trả lời"; +"NULL_ANSWER" = "Chọn một câu trả lời"; +"PLACEHOLDER_IMAGE_CHOICES" = "Chạm để chọn"; +"PLACEHOLDER_LONG_TEXT" = "Chạm để viết"; + +/* Button titles */ +"BUTTON_AGREE" = "Đồng ý"; +"BUTTON_CANCEL" = "Hủy"; +"BUTTON_OK" = "OK"; +"BUTTON_CLEAR" = "Xóa"; +"BUTTON_CLEAR_SIGNATURE" = "Xóa chữ ký"; +"BUTTON_APPLY" = "Áp dụng"; +"BUTTON_DISAGREE" = "Không đồng ý"; +"BUTTON_DONE" = "Xong"; +"BUTTON_GET_STARTED" = "Bắt đầu"; +"BUTTON_LEARN_MORE" = "Tìm hiểu thêm"; +"BUTTON_NEXT" = "Tiếp"; +"BUTTON_SKIP" = "Bỏ qua"; +"BUTTON_SKIP_QUESTION" = "Bỏ qua câu hỏi này"; +"BUTTON_START_TIMER" = "Bắt đầu Hẹn giờ"; +"BUTTON_OPTION_SAVE" = "Lưu để Sau này"; +"BUTTON_OPTION_DISCARD" = "Hủy bỏ Kết quả"; +"BUTTON_OPTION_STOP_TASK" = "Kết thúc Nhiệm vụ"; +"BUTTON_SAVE" = "Lưu"; +"BUTTON_CLEAR_ANSWER" = "Xóa câu trả lời"; +"BUTTON_READ_ONLY_MODE" = "Không thể sửa đổi câu trả lời này."; +"BUTTON_COPYRIGHT" = "Bản quyền"; +"BUTTON_CLOSE" = "Đóng"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "Bắt đầu hoạt động sau"; +"TASK_COMPLETE_TITLE" = "Hoạt động hoàn tất"; +"TASK_COMPLETE_TEXT" = "Dữ liệu của bạn sẽ được phân tích và bạn sẽ được thông báo khi có kết quả."; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "Còn lại %@."; +"TOUCH_ANYWHERE_LABEL" = "Chạm vào bất kỳ đâu để tiếp tục"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "Chụp Ảnh"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "Chụp lại Ảnh"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "Không tìm thấy camera nào. Không thể hoàn thành bước này."; +"CAPTURE_ERROR_NO_PERMISSIONS" = "Để hoàn thành bước này, hãy cho phép ứng dụng này truy cập camera trong Cài đặt."; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "Không có thư mục đầu ra nào được chỉ định cho hình ảnh được chụp."; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "Không thể lưu hình ảnh đã chụp."; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "Bắt đầu Ghi"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "Dừng Ghi"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "Quay lại Video"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "Thể dục"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "Quãng đường (%@)"; +"FITNESS_HEARTRATE_TITLE" = "Nhịp tim (nhịp/phút)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "Ngồi thoải mái trong %@."; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "Đi bộ với tốc độ nhanh nhất có thể trong %@."; +"FITNESS_INTRO_TEXT_FORMAT" = "Hoạt động này sẽ theo dõi nhịp tim của bạn và tính quãng đường bạn có thể đi bộ trong %1$@."; +"FITNESS_INTRO_2_TEXT_FORMAT" = "Đi bộ ngoài trời với tốc độ cao nhất có thể của bạn trong %1$@. Khi bạn hoàn tất, hãy ngồi và nghỉ ngơi thoải mái trong %2$@. Để bắt đầu, chạm Bắt đầu."; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "Dáng đi & thăng bằng"; +"WALK_INTRO_TEXT" = "Hoạt động này sẽ đo khả năng thăng bằng và dáng đi của bạn khi bạn đi bộ và đứng yên. Không tiếp tục hoạt động nếu bạn không thể đi bộ an toàn mà không có sự hỗ trợ."; +"WALK_INTRO_2_TEXT_%ld" = "Tìm một nơi mà bạn có thể đi bộ an toàn, không cần có sự hỗ trợ, trong khoảng %ld bước theo đường thẳng."; +"WALK_INTRO_2_DETAIL" = "Cho thiết bị của bạn vào trong túi hoặc vào giỏ và làm theo âm thanh hướng dẫn."; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "Bây giờ, đứng yên trong %@."; +"WALK_STAND_INSTRUCTION_FORMAT" = "Đứng yên trong %@."; +"WALK_RETURN_INSTRUCTION_FORMAT" = "Quay đầu lại và đi bộ về nơi bạn bắt đầu."; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "Đi bộ tối đa %ld bước theo đường thẳng."; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "Tìm một nơi mà bạn có thể đi tới đi lui an toàn theo đường thẳng. Cố gắng đi bộ liên tục bằng cách rẽ cuối đường, như thể bạn đang đi bộ quanh một hình nón.\n\nTiếp theo, bạn sẽ được hướng dẫn xoay một vòng tròn, sau đó đứng yên với hai cánh tay ở bên sườn và hai chân mở rộng bằng vai."; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "Chạm vào Bắt đầu khi bạn đã sẵn sàng.\nSau đó, đặt thiết bị của bạn vào trong túi hoặc vào giỏ và làm theo âm thanh hướng dẫn."; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "Đi tới đi lui theo đường thẳng trong %@. Đi bộ bình thường."; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "Xoay một vòng tròn rồi đứng yên trong %@."; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "Bạn đã hoàn thành hoạt động."; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "Tốc độ Chạm"; +"TAPPING_TASK_TITLE_RIGHT" = "Tay Phải"; +"TAPPING_TASK_TITLE_LEFT" = "Tay Trái"; +"TAPPING_INTRO_TEXT" = "Hoạt động này sẽ đo tốc độ chạm của bạn."; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "Đặt thiết bị của bạn trên một bề mặt phẳng."; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "Sử dụng hai ngón tay trên cùng bàn tay bạn để luân phiên chạm vào các nút trên màn hình."; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "Sử dụng hai ngón tay trên bàn tay phải bạn để luân phiên chạm vào các nút trên màn hình."; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "Sử dụng hai ngón tay trên bàn tay trái bạn để luân phiên chạm vào các nút trên màn hình."; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "Bây giờ, hãy lặp lại bài kiểm tra tương tự bằng tay phải của bạn."; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "Bây giờ, hãy lặp lại bài kiểm tra tương tự bằng tay trái của bạn."; +"TAPPING_INTRO_TEXT_2_FORMAT" = "Chạm một ngón tay, sau đó chạm ngón còn lại. Cố gắng tính thời gian số lần chạm chẵn nhất có thể. Tiếp tục chạm trong %@."; +"TAPPING_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"TAPPING_CALL_TO_ACTION_NEXT" = "Chạm Tiếp để bắt đầu."; +"TAP_BUTTON_TITLE" = "Chạm"; +"TOTAL_TAPS_LABEL" = "Tổng Lần chạm"; +"TAPPING_INSTRUCTION" = "Chạm vào các nút bằng hai ngón tay liên tục nhất có thể."; +"TAPPING_INSTRUCTION_RIGHT" = "Chạm nút bằng tay PHẢI của bạn."; +"TAPPING_INSTRUCTION_LEFT" = "Chạm nút bằng tay TRÁI của bạn."; +"TAPPING_SKIP_TITLE" = "Bỏ qua tay này"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "Lưới Amsler"; +"AMSLER_GRID_INTRO_TEXT" = "Hoạt động này giúp phát hiện các vấn đề về thị lực của người dùng."; +"AMSLER_GRID_INSTRUCTION_TEXT" = "Giữ thiết bị cách mặt bạn 30 cm (12 inch) và ở ngang tầm mắt trong suốt bài kiểm tra."; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "Nhắm %@ của bạn và nhìn chăm chú vào dấu chấm ở giữa lưới hình vuông.\n\nSử dụng ngón tay của bạn hoặc bút cảm ứng, đánh dấu bất kỳ sự biến dạng nào mà bạn thấy như đường kẻ bị mờ hoặc lượn sóng.\n\nKhi bạn hoàn tất, hãy vuốt sang trái ở bất kỳ đâu bên ngoài lưới."; +"AMSLER_GRID_LEFT_EYE" = "Mắt trái"; +"AMSLER_GRID_RIGHT_EYE" = "Mắt phải"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "Giọng nói"; +"AUDIO_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"AUDIO_INSTRUCTION" = "Nói “Aaaaah” vào micrô với thời gian dài nhất mà bạn có thể."; +"AUDIO_INTRO_TEXT" = "Hít một hơi thật sâu và nói “Aaaaah” lâu hết mức có thể vào micrô. Giữ thật đều giọng nói để các thanh tiếng vẫn ở trong vùng màu xanh dương."; +"AUDIO_INTENDED_USE" = "Hoạt động này sẽ đánh giá giọng nói của bạn bằng cách ghi âm bằng micrô ở cạnh dưới của thiết bị."; +"AUDIO_TOO_LOUD_LABEL" = "Quá To"; +"AUDIO_GENERIC_ERROR_LABEL" = "Không thể ghi âm"; +"AUDIO_LEVEL_CHECK_LABEL" = "Vui lòng đợi trong khi chúng tôi kiểm tra độ ồn trong nền."; +"AUDIO_TOO_LOUD_MESSAGE" = "Độ ồn xung quanh quá lớn để ghi âm giọng nói của bạn. Vui lòng di chuyển đến nơi nào đó yên tĩnh hơn và thử lại."; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "Chạm Tiếp khi sẵn sàng."; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "Trắc thính Âm báo"; +"TONE_AUDIOMETRY_INTENDED_USE" = "Hoạt động này giúp đánh giá khả năng nghe các âm thanh khác nhau của bạn."; +"TONE_AUDIOMETRY_INTRO_TEXT" = "Trước khi bạn bắt đầu, hãy cắm và đeo tai nghe của bạn.\n\nÂm thanh sẽ rất nhỏ và khác với âm báo thông thường. Âm thanh sẽ bắt đầu nhỏ và sau đó âm lượng sẽ tăng từ từ. Vui lòng tập trung và chạm vào nút bên trái hoặc phải để cho biết bạn nghe thấy âm thanh ở bên tai nào."; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"TONE_AUDIOMETRY_PREP_TEXT" = "Bây giờ bạn sẽ nghe thấy một âm báo. Điều chỉnh âm lượng bằng cách điều khiển ở sườn của thiết bị.\n\nChạm vào bất kỳ nút nào khi bạn đã sẵn sàng bắt đầu."; +"TONE_AUDIOMETRY_INSTRUCTION" = "Mỗi lần bạn bắt đầu nghe âm thanh, hãy chạm vào nút bên trái hoặc phải để cho biết bạn nghe âm thanh ở bên tai nào."; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "Tai trái"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "Tai phải"; +"TONE_LABEL_%@_LEFT" = "%@ Hz, Trái"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz, Phải"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "Trắc thính Âm báo"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "Chạm khi bạn nghe thấy một âm báo."; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "Âm báo & Âm lượng"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "Bạn sẽ nghe thấy một chuỗi âm báo."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "Khi bạn nghe thấy một âm báo, hãy chạm vào nút."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "Đối với kiểm tra này, âm lượng sẽ được đặt thành 50%."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "Kiểm tra này kéo dài khoảng 10 phút."; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "Bật Không làm phiền để tránh gián đoạn."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "Âm báo sẽ phát trong tai phải của bạn trước tiên."; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "Bây giờ, âm báo sẽ phát trong tai trái của bạn."; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "Hoạt động này xác định các mức ngưỡng thính giác của một cá nhân theo thang dB HL."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "Đảm bảo rằng âm lượng của thiết bị được đặt ở mức tối đa.\n\nTrong phần này, một âm báo nhỏ sẽ phát ở tai bên trái hoặc bên phải.\n\nNghe cẩn thận và chạm vào nút mỗi lần bạn nghe thấy một âm báo."; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "Kiểm tra này xác định độ lớn cần thiết của một âm thanh để bạn nghe thấy."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "Bảng câu hỏi tích hợp."; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "Chọn ưu tiên của bạn cho 'tai tốt hơn', nếu có"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "trái"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "phải"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "không có ưu tiên"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "Đã hủy kiểm tra"; +"dBHL_ALERT_TITLE_START_OVER" = "Bắt đầu lại"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "Hủy kiểm tra"; +"dBHL_ALERT_TEXT" = "Kết nối lại AirPods hoặc EarPods của bạn để thực hiện bài kiểm tra này."; +"dBHL_PROGRESS_COMPLETION_%@" = "Hoàn tất %@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "Tai nghe"; +"HEADPHONES_UNKNOWN" = "Không xác định"; +"HEADPHONES_NONE" = "Không có"; +"CONNECTED" = "Đã kết nối"; +"NOT_CONNECTED" = "Không được kết nối"; +"HEADPHONE_CONNECTED_%@" = "Đã kết nối - %@"; +"HEADPHONE_DETECT_TITLE" = "Kết nối tai nghe của bạn"; +"HEADPHONE_DETECT_TEXT" = "Kiểm tra này yêu cầu Apple AirPods hoặc Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "Trí nhớ Không gian"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "Hoạt động này sẽ đánh giá trí nhớ không gian ngắn hạn của bạn bằng cách yêu cầu bạn lặp lại thứ tự sáng lên của %@."; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "những bông hoa"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "những bông hoa"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "Một số %@ sẽ sáng lên lần lượt. Hãy chạm vào các %@ này theo thứ tự sáng lên của chúng."; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "Một số %@ sẽ sáng lên lần lượt. Hãy chạm vào các %@ này theo thứ tự ngược với thứ tự sáng lên của chúng."; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "Để bắt đầu, chạm Bắt đầu, sau đó theo dõi chặt chẽ."; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "Điểm"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "Theo dõi %@ sáng lên"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "Chạm vào %@ theo thứ tự chúng sáng lên"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "Chạm vào %@ theo thứ tự ngược lại"; +"MEMORY_GAME_COMPLETE_TITLE" = "Chuỗi Hoàn thành"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "Để tiếp tục, hãy chạm vào Tiếp"; +"MEMORY_GAME_FAILED_TITLE" = "Thử lại"; +"MEMORY_GAME_FAILED_MESSAGE" = "Lần trước bạn chưa thực sự thành công. Hãy chạm vào Tiếp để tiếp tục."; +"MEMORY_GAME_TIMEOUT_TITLE" = "Hết thời gian"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "Bạn đã hết thời gian.\nHãy chạm vào Tiếp để tiếp tục."; +"MEMORY_GAME_COMPLETE" = "Hoàn tất Trò chơi"; +"MEMORY_GAME_PAUSED_TITLE" = "Đã tạm dừng"; +"MEMORY_GAME_PAUSED_MESSAGE" = "Để tiếp tục, hãy chạm vào Tiếp"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "Hoạt động trí nhớ được phát triển với sự hỗ trợ từ Tiến sĩ Katherine Possin và Tiến sĩ Joel Kramer từ Trường đại học California, San Francisco."; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "Thời gian Phản ứng"; +"REACTION_TIME_TASK_INTENDED_USE" = "Hoạt động này giúp đánh giá thời gian bạn phản ứng trước gợi ý bằng hình ảnh."; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "Lắc thiết bị theo bất kỳ hướng nào ngay khi chấm màu xanh dương xuất hiện trên màn hình. Bạn sẽ được yêu cầu làm việc này %D lần."; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "Lần thử %@ / %@"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "Lắc nhanh thiết bị khi vòng tròn màu xanh dương xuất hiện"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "Stroop"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "Mỗi lần một từ xuất hiện, hãy chọn chữ cái đầu tiên của tên MÀU được hiển thị."; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "Khi bạn đã sẵn sàng bắt đầu hoạt động Stroop, hãy chạm vào Bắt đầu."; +"STROOP_TASK_STEP_TEXT" = "Chọn chữ cái đầu tiên của tên MÀU được hiển thị."; +"STROOP_COLOR_RED" = "ĐỎ"; +"STROOP_COLOR_GREEN" = "XANH LỤC"; +"STROOP_COLOR_BLUE" = "XANH DƯƠNG"; +"STROOP_COLOR_YELLOW" = "VÀNG"; +"STROOP_COLOR_RED_INITIAL" = "Đ"; +"STROOP_COLOR_GREEN_INITIAL" = "L"; +"STROOP_COLOR_BLUE_INITIAL" = "D"; +"STROOP_COLOR_YELLOW_INITIAL" = "V"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "Tháp Hà Nội"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "Hoạt động này đánh giá các kỹ năng giải đố của bạn."; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "Di chuyển toàn bộ chồng đĩa đến bục được tô sáng với số lần di chuyển ít nhất có thể."; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "Giải đố"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "Số lần di chuyển: %@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "Tôi không thể giải câu đố này"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "Phạm vi chuyển động"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption phải là trái hoặc phải"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "Phạm vi chuyển động của đầu gối chân trái"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "Phạm vi chuyển động của đầu gối chân phải"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Hoạt động này đo khoảng cách mà bạn có thể duỗi đầu gối chân trái."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Hoạt động này đo khoảng cách mà bạn có thể duỗi đầu gối chân phải."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Ngồi xuống trên mép ghế. Khi bạn bắt đầu, bạn sẽ đặt thiết bị trên đầu gối chân trái để lấy số đo. Vui lòng bật âm thanh của thiết bị để bạn có thể nghe thấy các hướng dẫn."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Ngồi xuống trên mép ghế. Khi bạn bắt đầu, bạn sẽ đặt thiết bị trên đầu gối chân phải để lấy số đo. Vui lòng bật âm thanh của thiết bị để bạn có thể nghe thấy các hướng dẫn."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Đặt thiết bị trên đầu gối chân trái của bạn với màn hình hướng ra ngoài, giống như trong hình."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Đặt thiết bị trên đầu gối chân phải của bạn với màn hình hướng ra ngoài, giống như trong hình."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Khi sẵn sàng, chạm vào màn hình để bắt đầu và duỗi đầu gối trái của bạn ra xa nhất có thể. Trở lại vị trí bắt đầu và chạm lại khi bạn thực hiện xong."; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Khi sẵn sàng, chạm vào màn hình để bắt đầu và duỗi đầu gối phải của bạn ra xa nhất có thể. Trở lại vị trí bắt đầu và chạm lại khi bạn thực hiện xong."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Đặt thiết bị trên đầu gối trái của bạn. Chạm vào màn hình và duỗi đầu gối trái của bạn ra xa nhất có thể."; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Đặt thiết bị trên đầu gối phải của bạn. Chạm vào màn hình và duỗi đầu gối phải của bạn ra xa nhất có thể."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Khi bạn thực hiện xong, hãy đưa đầu gối trái về vị trí bắt đầu. Sau đó, chạm vào bất kỳ đâu."; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Khi bạn thực hiện xong, hãy đưa đầu gối phải về vị trí bắt đầu. Sau đó, chạm vào bất kỳ đâu."; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "Phạm vi chuyển động của vai trái"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "Phạm vi chuyển động của vai phải"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "Hoạt động này đo khoảng cách mà bạn có thể duỗi vai trái."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "Hoạt động này đo khoảng cách mà bạn có thể duỗi vai phải."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "Khi bạn bắt đầu, bạn sẽ đặt thiết bị trên vai trái để lấy số đo. Vui lòng bật âm thanh của thiết bị để bạn có thể nghe thấy các hướng dẫn."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "Khi bạn bắt đầu, bạn sẽ đặt thiết bị trên vai phải để lấy số đo. Vui lòng bật âm thanh của thiết bị để bạn có thể nghe thấy các hướng dẫn."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "Đặt thiết bị trên vai trái của bạn với màn hình hướng ra ngoài, giống như trong hình."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "Đặt thiết bị trên vai phải của bạn với màn hình hướng ra ngoài, giống như trong hình."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "Khi sẵn sàng, chạm vào màn hình để bắt đầu và đưa cánh tay trái của bạn lên xa nhất có thể. Trở lại vị trí bắt đầu và chạm lại khi bạn thực hiện xong."; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "Khi sẵn sàng, chạm vào màn hình để bắt đầu và đưa cánh tay phải của bạn lên xa nhất có thể. Trở lại vị trí bắt đầu và chạm lại khi bạn thực hiện xong."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "Đặt thiết bị trên vai trái của bạn. Chạm vào màn hình và đưa cánh tay trái của bạn ra phía trước xa nhất có thể."; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "Đặt thiết bị trên vai phải của bạn. Chạm vào màn hình và đưa cánh tay phải của bạn ra phía trước xa nhất có thể."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "Khi bạn thực hiện xong, hãy đưa cánh tay trái về vị trí bắt đầu. Sau đó, chạm vào bất kỳ đâu."; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "Khi bạn thực hiện xong, hãy đưa cánh tay phải về vị trí bắt đầu. Sau đó, chạm vào bất kỳ đâu."; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "Đi bộ Tính giờ"; +"TIMED_WALK_INTRO_DETAIL" = "Hoạt động này đo lường chức năng chi dưới của bạn."; +"TIMED_WALK_INTRO_2_TEXT_%@" = "Tìm một địa điểm, tốt nhất là ngoài trời, mà bạn có thể đi bộ trong khoảng %@ theo đường thẳng nhanh nhất có thể, nhưng an toàn. Không giảm tốc độ cho tới khi bạn đã vượt qua vạch đích."; +"TIMED_WALK_INTRO_2_DETAIL" = "Chạm Tiếp để bắt đầu."; +"TIMED_WALK_FORM_TITLE" = "Thiết bị hỗ trợ"; +"TIMED_WALK_FORM_TEXT" = "Sử dụng cùng thiết bị hỗ trợ cho từng bài kiểm tra."; +"TIMED_WALK_QUESTION_TEXT" = "Bạn có đeo thiết bị chỉnh hình mắt cá chân không?"; +"TIMED_WALK_QUESTION_2_TITLE" = "Bạn có sử dụng thiết bị hỗ trợ không?"; +"TIMED_WALK_QUESTION_2_TEXT" = "Chạm vào đây để chọn một câu trả lời."; +"TIMED_WALK_QUESTION_2_CHOICE" = "Không có"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "Gậy chống Đơn"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "Nạng Đơn"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "Gậy chống Đôi"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "Nạng Đôi"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "Khung tập đi/Xe lăn"; +"TIMED_WALK_INSTRUCTION_%@" = "Đi bộ tối đa %@ theo đường thẳng."; +"TIMED_WALK_INSTRUCTION_TURN" = "Quay lại."; +"TIMED_WALK_INSTRUCTION_2" = "Đi bộ trở về nơi bạn đã bắt đầu."; +"TIMED_WALK_INSTRUCTION_TEXT" = "Chạm Tiếp khi hoàn tất."; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "Bài Kiểm tra Tính tổng Tuần tự bằng Âm thanh Theo tốc độ đo lường tốc độ xử lý thông tin âm thanh cùng với khả năng tính toán của bạn."; +"PVSAT_INTRO_TEXT" = "Bài Kiểm tra Tính tổng Tuần tự bằng Hình ảnh Theo tốc độ đo lường tốc độ xử lý thông tin hình ảnh cùng với khả năng tính toán của bạn."; +"PAVSAT_INTRO_TEXT" = "Bài Kiểm tra Tính tổng Tuần tự bằng Âm thanh và Hình ảnh Theo tốc độ đo lường tốc độ xử lý thông tin âm thanh và hình ảnh cùng với khả năng tính toán của bạn."; +"PSAT_INTRO_TEXT_2_%@" = "Các số duy nhất được đưa ra sau mỗi %@.\nBạn phải cộng từng số mới với số ngay trước nó.\nLưu ý: bạn không được tính tổng liên tục mà chỉ được tính tổng của hai số sau cùng."; +"PSAT_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"PSAT_INITIAL_INSTRUCTION" = "Ghi nhớ số đầu tiên này."; +"PSAT_INSTRUCTION" = "Cộng số mới này với số trước đó."; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "Kiểm tra Bảng %@ Lỗ"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "Hoạt động này đánh giá chức năng phần thân trên của bạn bằng cách yêu cầu bạn đặt một miếng gỗ vào trong lỗ. Bạn sẽ được yêu cầu thực hiện việc này %@ lần."; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "Cả tay trái và phải của bạn sẽ được kiểm tra.\nBạn phải nhặt miếng gỗ nhanh nhất có thể, đặt vào trong lỗ, và khi đã thực hiện xong %@ lần, hãy lấy ra %@ lần nữa."; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "Cả tay phải và trái của bạn sẽ được kiểm tra.\nBạn phải nhặt miếng gỗ nhanh nhất có thể, đặt vào trong lỗ, và khi đã thực hiện xong %@ lần, hãy lấy ra %@ lần nữa."; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "Đặt miếng gỗ vào trong lỗ bằng tay trái của bạn."; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "Đặt miếng gỗ vào trong lỗ bằng tay phải của bạn."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "Đặt miếng gỗ phía sau dòng kẻ bằng tay trái của bạn."; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "Đặt miếng gỗ phía sau dòng kẻ bằng tay phải của bạn."; +"HOLE_PEG_TEST_TEXT" = "Nhặt miếng gỗ bằng hai ngón tay."; +"HOLE_PEG_TEST_TEXT_2" = "Nhấc các ngón tay để thả rơi miếng gỗ."; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "Hoạt động Rung"; +"TREMOR_TEST_INTRO_1_DETAIL" = "Hoạt động này sẽ đo độ rung của các tay bạn ở những vị trí khác nhau. Tìm một địa điểm nơi bạn có thể ngồi thoải mái trong suốt hoạt động này."; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "Cầm điện thoại bằng tay thuận hơn như được hiển thị trong hình bên dưới."; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "Cầm điện thoại bằng tay PHẢI như được hiển thị trong hình bên dưới."; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "Cầm điện thoại bằng tay TRÁI như được hiển thị trong hình bên dưới."; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "Bạn sẽ được yêu cầu thực hiện %@ trong khi ngồi với điện thoại trên tay của mình."; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "một nhiệm vụ"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "hai nhiệm vụ"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "ba nhiệm vụ"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "bốn nhiệm vụ"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "năm nhiệm vụ"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "Chạm tiếp để tiếp tục."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "Chuẩn bị giữ điện thoại trên đùi của bạn."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "Chuẩn bị giữ điện thoại trên đùi bằng tay TRÁI của bạn."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "Chuẩn bị giữ điện thoại trên đùi bằng tay PHẢI của bạn."; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "Tiếp tục giữ điện thoại trên đùi của bạn trong %ld giây."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "Bây giờ, hãy cầm điện thoại với tay của bạn duỗi ngang vai."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "Bây giờ, hãy cầm điện thoại với tay TRÁI của bạn duỗi ngang vai."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "Bây giờ, hãy cầm điện thoại với tay PHẢI của bạn duỗi ngang vai."; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "Tiếp tục cầm điện thoại với tay của bạn duỗi thẳng trong %ld giây."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "Bây giờ, hãy cầm điện thoại cao bằng vai cùng khủy tay bị gập."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "Bây giờ, hãy cầm điện thoại với tay TRÁI của bạn cao bằng vai cùng khủy tay bị gập."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "Bây giờ, hãy cầm điện thoại với tay PHẢI của bạn cao bằng vai cùng khủy tay bị gập."; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "Tiếp tục cầm điện thoại với khuỷu tay của bạn bị gập trong %ld giây"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "Bây giờ, hãy gập khuỷu tay bạn, chạm điện thoại vào mũi nhiều lần."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "Bây giờ, hãy giữ khuỷu tay bạn gập với điện thoại ở tay TRÁI, chạm điện thoại vào mũi nhiều lần."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "Bây giờ, hãy gập khuỷu tay bạn với điện thoại ở tay PHẢI, chạm điện thoại vào mũi nhiều lần."; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "Tiếp tục chạm điện thoại vào mũi bạn trong %ld giây"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "Chuẩn bị vẫy tay (vẫy bằng cách xoay cổ tay của bạn)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "Chuẩn bị vẫy tay với điện thoại ở tay TRÁI (vẫy bằng cách xoay cổ tay của bạn)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "Chuẩn bị vẫy tay với điện thoại ở tay PHẢI (vẫy bằng cách xoay cổ tay của bạn)."; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "Tiếp tục thực hiện vẫy tay trong %ld giây."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "Bây giờ, hãy chuyển điện thoại sang tay TRÁI và tiếp tục nhiệm vụ tiếp theo."; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "Bây giờ, hãy chuyển điện thoại sang tay PHẢI và tiếp tục nhiệm vụ tiếp theo."; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "Tiếp tục đến nhiệm vụ tiếp theo."; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "Hoạt động đã hoàn tất."; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "Bạn sẽ được yêu cầu thực hiện %@ trong khi ngồi với điện thoại trên một tay trước tiên, sau đó đặt lại lên tay còn lại."; +"TREMOR_SKIP_LEFT_HAND" = "Tôi không thể thực hiện hoạt động này bằng tay TRÁI."; +"TREMOR_SKIP_RIGHT_HAND" = "Tôi không thể thực hiện hoạt động này bằng tay PHẢI."; +"TREMOR_SKIP_NEITHER" = "Tôi có thể thực hiện hoạt động này bằng hai tay."; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "Trắc nghiệm nối chuỗi"; +"TRAILMAKING_INTENDED_USE" = "Hoạt động này đánh giá khả năng tập trung thị giác và chuyển đổi nhiệm vụ bằng cách ghi lại thời gian cần thiết để chạm vào một chuỗi các dấu chấm theo thứ tự."; +"TRAILMAKING_INTENDED_USE2_A" = "Sau thời gian đếm ngược, chạm vào các dấu chấm theo thứ tự luân phiên giữa các số và chữ cái. Bắt đầu bằng cách chạm vào số đầu tiên '1', tiếp theo là các số '2' – '3' – '4'… cho tới khi bạn đến số '7'."; +"TRAILMAKING_INTENDED_USE2_B" = "Sau thời gian đếm ngược, chạm vào các dấu chấm theo thứ tự luân phiên giữa các số và chữ cái. Bắt đầu bằng cách chạm vào số đầu tiên '1', tiếp theo là chạm vào chữ cái đầu tiên 'A' và sau đó là '2' – 'B' – '3' – 'C'… cho tới khi bạn đến số '7'."; +"TRAILMAKING_INTRO_TEXT" = "Thực hiện việc này nhanh nhất có thể mà không mắc lỗi. \n "; +"TRAILMAKING_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "Nhận dạng lời nói"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "Hoạt động này ghi lại lời nói của bạn bằng micrô ở cạnh dưới của thiết bị và diễn giải thành văn bản."; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "Chạm vào Bắt đầu để bắt đầu."; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "Nhấn nút để bắt đầu ghi âm trước khi nói."; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "Bắt đầu Ghi"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "Dừng Ghi"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "Sửa bản chép lại"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "Sửa nội dung bản chép lại để hiệu chỉnh bất kỳ phần nào diễn giải sai lời nói."; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "Bản chép lại của bạn sẽ xuất hiện tại đây."; +"SPEECH_RECOGNITION_FAILED" = "Không thể nhận dạng lời nói."; +"SPEECH_RECOGNITION_INIT_FAILURE" = "Không thể bắt đầu nhận dạng lời nói."; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "Phát âm thanh"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "Dừng âm thanh"; +"SPEECH_IN_NOISE_TITLE" = "Lời nói trong tiếng ồn"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "Hoạt động này đánh giá mức độ rõ ràng của lời nói khi được trình bày trong môi trường nhiều tiếng ồn."; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "Trong kiểm tra này, bạn sẽ:\n\nNghe một câu.\n\nLặp lại rõ ràng những gì bạn đã nghe hoặc bỏ qua đến phần sau để nhập những gì bạn đã nghe bằng bàn phím. \n\nNếu bạn lặp lại những gì đã nghe, bạn sẽ có tùy chọn sửa đổi bản chép lại do công cụ nhận dạng lời nói tạo ra."; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "Hiệu chỉnh âm lượng"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "Chạm vào 'Phát âm thanh', điều chỉnh âm lượng đến mức phù hợp và sau đó chạm vào 'Dừng âm thanh' để tiếp tục."; +"SPEECH_IN_NOISE_STEP_TITLE" = "Nghe"; +"SPEECH_IN_NOISE_STEP_TEXT" = "Một câu trộn lẫn trong môi trường tiếng ồn theo Tỷ số tín hiệu/nhiễu (SNR) được ngẫu nhiên hóa sẽ chỉ được phát một lần."; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "Nói"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "Lặp lại những gì bạn nghe được."; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "Không thể tạo tệp"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "Không thể xóa đủ số tệp bản ghi để đạt tới ngưỡng"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "Lỗi khi đặt thuộc tính"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "Đã xóa tệp không được đánh dấu (không được đánh dấu là đã tải lên)"; +"ERROR_DATALOGGER_MULTIPLE" = "Nhiều lỗi trong khi xóa bản ghi"; +"ERROR_RECORDER_NO_DATA" = "Không tìm thấy dữ liệu được thu thập."; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "Không có thư mục đầu ra nào được chỉ định"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "Công cụ đo SPL"; +"ENVIRONMENTSPL_INTRO_TEXT" = "Hoạt động này đánh giá mức độ áp lực âm thanh môi trường. Nếu mức tiếng ồn quá cao, bạn sẽ không thể tiếp tục. Vui lòng di chuyển đến một vị trí yên tĩnh hơn để hoàn thành phần này hoặc thực hiện lại hoạt động này vào một thời điểm khác."; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "Đang tính"; +"ENVIRONMENTSPL_THRESHOLD" = "Ngưỡng: %@ dBA"; +"ENVIRONMENTSPL_OK" = "Tiếng ồn trong nền bình thường"; +"ENVIRONMENTSPL_NOISE" = "Quá nhiều tiếng ồn trong nền"; +"ENVIRONMENTSPL_TITLE_2" = "Tìm một địa điểm yên tĩnh"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "Để đảm bảo độ chính xác, bạn nên thực hiện kiểm tra này trong một môi trường yên tĩnh."; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "Bắt đầu tác vụ"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "Không có Dữ liệu"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "Di chuyển thanh trượt để nhập giá trị"; +"SLIDER_I_DONT_KNOW" = "Tôi không biết"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "Trang"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "Quay lại"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "Hiển thị hình thu nhỏ PDF"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "Ẩn hình thu nhỏ PDF"; +"AX_BUTTON_ANNOTATE" = "Chú thích"; +"AX_BUTTON_SHOW_SEARCH" = "Hiển thị thanh tìm kiếm"; +"AX_BUTTON_HIDE_SEARCH" = "Ẩn thanh tìm kiếm"; +"AX_BUTTON_SHARE" = "Chia sẻ"; + + +"AX_COMPLETION_ILLUSTRATION" = "Hình minh họa dấu chọn trong vòng tròn màu lam biểu thị thành công"; + +"AX_SIGNVIEW_LABEL" = "Trường chữ ký được chỉ định"; +"AX_SIGNVIEW_HINT" = "Chạm vào màn hình và di chuyển ngón tay của bạn để ký"; +"AX_SIGNVIEW_SIGNED" = "Đã ký"; +"AX_SIGNVIEW_UNSIGNED" = "Chưa ký"; + +"AX_SELECTED" = "Đã chọn"; +"AX_UNSELECTED" = "Đã bỏ chọn"; +"AX_SELECT_ALL_THAT_APPLY" = "CHỌN TẤT CẢ CÁC MỤC PHÙ HỢP"; + +"AX_SLIDER_LABEL" = "Thanh trượt phản hồi. Phạm vi từ %@ đến %@"; +"AX_UNLABELED_IMAGE" = "Hình ảnh không có nhãn"; + +"AX_ANNOUNCE_BEGIN_TASK" = "Bắt đầu nhiệm vụ"; + +"AX.MEMORY.TILE.ACTIVE" = "hoạt động"; +"AX.MEMORY.TILE.CORRECT" = "đúng"; +"AX.MEMORY.TILE.INCORRECT" = "sai"; +"AX.MEMORY.TILE.QUIESCENT" = "yên lặng"; +"AX.MEMORY.TILE.LABEL" = "Ô trò chơi ghi nhớ"; + +"AX_IMAGE_CAPTURE_LABEL" = "Chụp bản xem trước"; +"AX_IMAGE_CAPTURED_LABEL" = "Ảnh được chụp"; + +"AX_VIDEO_CAPTURE_LABEL" = "Xem trước quay video"; +"AX_VIDEO_CAPTURE_COMPLETE" = "Hoàn tất quay video"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "Không thể đặt đĩa có kích cỡ %@ lên trên đĩa có kích cỡ %@"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "Đích"; +"AX_TOWER_OF_HANOI_TOWER" = "Tháp"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "Chạm hai lần để đặt đĩa"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "Chạm hai lần để chọn đĩa trên cùng"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "Có đĩa có kích cỡ %@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "Trống"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "Ẩn bàn phím"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "Trong khoảng từ %@ đến %@"; +"AX_GRAPH_STACK_PREFIX" = "Ngăn xếp bao gồm"; +"AX_GRAPH_AND_SEPARATOR" = " và "; +"AX_GRAPH_POINT_%@" = "Điểm: %@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "Dạng sóng lời nói"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "Khi quá trình ghi âm bắt đầu, kích hoạt lần thứ hai để dừng ghi âm."; + +"AX_AUDIO_BAR_GRAPH" = "Biểu đồ thanh âm thanh"; + +"AX_AMSLER_GRID_LABEL" = "Lưới Amsler"; +"AX_AMSLER_GRID_HINT" = "Sử dụng ngón tay của bạn hoặc bút cảm ứng để đánh dấu trực tiếp trên lưới hoặc vuốt sang trái ở bên ngoài lưới để hoàn tất."; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "Nút có thể chạm"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "Chạm cho tai trái"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "Kích hoạt để bắt đầu kiểm tra. Khi kiểm tra bắt đầu, hãy chạm trực tiếp vào nút này khi bạn nghe thấy âm thanh trong tai trái của mình."; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "Chạm cho tai phải"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "Kích hoạt để bắt đầu kiểm tra. Khi kiểm tra bắt đầu, hãy chạm trực tiếp vào nút này khi bạn nghe thấy âm thanh trong tai phải của mình."; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@ Sử dụng VoiceOver, khám phá màn hình bằng cách chạm để tìm hiểu vị trí đặt các nút cho từng tai. Khi kiểm tra bắt đầu, bạn sẽ có thể chạm trực tiếp vào các nút. %@"; +"AX_TAP_BUTTON_1_LABEL" = "Chạm bằng một ngón tay"; +"AX_TAP_BUTTON_2_LABEL" = "Chạm bằng ngón tay khác"; +"AX_TAP_BUTTON_HINT" = "Kích hoạt để làm cho các nút có thể chạm trực tiếp."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@ Sử dụng VoiceOver, khám phá màn hình bằng cách chạm để tìm hiểu vị trí đặt các nút. Kích hoạt một trong hai nút để làm cho các nút có thể chạm trực tiếp."; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "Bây giờ có thể chạm trực tiếp vào các nút."; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@ Sử dụng VoiceOver, bạn sẽ có thể chạm trực tiếp vào nút. Nút này sẽ nằm ở gần giữa màn hình."; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@ Sử dụng VoiceOver, bạn sẽ có thể chạm trực tiếp vào các nút trong kiểm tra."; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "Không thể giải mã restoreData để khởi chạy"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..cbfb3e8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/vi.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d lỗi) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.strings new file mode 100755 index 0000000..9dd977f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "同意书"; +"CONSENT_NAME_GIVEN" = "名"; +"CONSENT_NAME_FAMILY" = "姓"; +"CONSENT_NAME_PLACEHOLDER" = "必填"; +"CONSENT_REVIEW_TITLE" = "检查"; +"CONSENT_REVIEW_INSTRUCTION" = "请检查下方的表单,准备好继续后请轻点“同意”。"; +"CONSENT_REVIEW_ALERT_TITLE" = "检查"; +"CONSENT_SIGNATURE_TITLE" = "签名"; +"CONSENT_SIGNATURE_INSTRUCTION" = "请用手指在下方的方框中签名。"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "在此签名"; +"CONSENT_PAGE_NUMBER_FORMAT" = "第%1$ld/%2$ld页"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "欢迎使用"; +"CONSENT_SECTION_DATA_GATHERING" = "数据收集"; +"CONSENT_SECTION_PRIVACY" = "隐私权"; +"CONSENT_SECTION_DATA_USE" = "数据使用"; +"CONSENT_SECTION_STUDY_SURVEY" = "研究调查"; +"CONSENT_SECTION_STUDY_TASKS" = "研究任务"; +"CONSENT_SECTION_TIME_COMMITMENT" = "时间保证"; +"CONSENT_SECTION_WITHDRAWING" = "退出研究"; +"CONSENT_LEARN_MORE_TITLE" = "了解更多"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "了解有关数据收集方式的更多信息"; +"LEARN_MORE_DATA_USE" = "了解有关数据使用方式的更多信息"; +"LEARN_MORE_PRIVACY" = "了解有关隐私和身份保护方式的更多信息"; +"LEARN_MORE_WELCOME" = "首先了解有关研究的更多信息"; +"LEARN_MORE_STUDY_SURVEY" = "了解有关研究调查的更多信息"; +"LEARN_MORE_TIME_COMMITMENT" = "了解有关研究所占用时间的更多信息"; +"LEARN_MORE_TASKS" = "了解有关所涉及任务的更多信息"; +"LEARN_MORE_WITHDRAWING" = "了解有关退出研究的更多信息"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "共享选项"; +"CONSENT_SHARE_WIDELY_%@" = "与%@及全世界符合资格的研究者共享我的数据"; +"CONSENT_SHARE_ONLY_%@" = "仅与%@共享我的数据"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@将从您参与的此研究中接收研究数据。\n\n更广泛地共享经加密的研究数据(不包含诸如姓名的信息)可能有助于本次以及未来的研究。"; +"LEARN_MORE_CONSENT_SHARING" = "了解有关数据共享的更多信息"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "正楷签名"; +"CONSENT_DOC_LINE_SIGNATURE" = "签名"; +"CONSENT_DOC_LINE_DATE" = "日期"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "问题%1$@/%2$@"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "已跳过"; +"REVIEW_EDIT_ANSWER" = "编辑"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "无效值"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@超出了允许的最大值(%2$@)。"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@低于允许的最小值(%2$@)。"; +"RANGE_ALERT_MESSAGE_OTHER" = "%@不是有效值。"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "无效的电子邮件地址:%@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "输入地址"; +"LOCATION_ERROR_TITLE" = "无法找到指定地址"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "未能解析您的当前位置。请键入地址或转移到GPS信号较好的位置(若条件允许)。"; +"LOCATION_ERROR_MESSAGE_DENIED" = "访问位置服务已被拒绝。请通过“设置”来授权此App使用位置服务。"; +"LOCATION_ERROR_GEOCODE" = "未能找到所输入地址的相关结果。请确定该地址是否有效。"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "您未连接到互联网,或已超出地址查询请求的次数上限。如果未连接到互联网,请打开您的Wi-Fi以回答此问题,跳过按钮可用时可跳过此问题,或在连接到互联网后继续参与该调查。如果超出请求次数上限,请等待几分钟后再次尝试。"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "文本内容超过最大长度:%@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "相机在拆分屏幕中不可用。"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "电子邮件"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "密码"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "输入密码"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "确认"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "再次输入密码"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "密码不匹配。"; +"ADDITIONAL_INFO_SECTION_TITLE" = "其他信息"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "性别"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "选择性别"; +"DOB_FORM_ITEM_TITLE" = "出生日期"; +"DOB_FORM_ITEM_PLACEHOLDER" = "选择日期"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "电话号码"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "验证"; +"VERIFICATION_STEP_TITLE" = "验证您的电子邮件"; +"RESEND_EMAIL_LABEL_MESSAGE" = "如果您未收到验证电子邮件并希望再收一次,请轻点下方的链接。"; +"RESEND_EMAIL_BUTTON_TITLE" = "重新发送验证电子邮件"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "登录"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "忘记了密码?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "输入口令"; +"PASSCODE_CONFIRM_MESSAGE" = "确认口令"; +"PASSCODE_SAVED_MESSAGE" = "口令已存储"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "口令已认证"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "输入旧口令"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "输入新口令"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "确认新口令"; +"PASSCODE_INVALID_ALERT_TITLE" = "口令不正确"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "口令不匹配。请再试一次。"; +"PASSCODE_TOUCH_ID_MESSAGE" = "请使用触控ID进行认证"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "触控ID错误"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "仅允许数字字符。"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "口令输入进度指示器"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "已输入%@/%@位"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "忘记了密码?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "无法添加钥匙串项。"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "无法更新钥匙串项。"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "无法删除钥匙串项。"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "无法找到钥匙串项。"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "类型I"; +"FITZPATRICK_SKIN_TYPE_II" = "类型II"; +"FITZPATRICK_SKIN_TYPE_III" = "类型III"; +"FITZPATRICK_SKIN_TYPE_IV" = "类型IV"; +"FITZPATRICK_SKIN_TYPE_V" = "类型V"; +"FITZPATRICK_SKIN_TYPE_VI" = "类型VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "女"; +"GENDER_MALE" = "男"; +"GENDER_OTHER" = "其他"; + +/* Boolean answer strings */ +"BOOL_NO" = "否"; +"BOOL_YES" = "是"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "厘米"; +"MEASURING_UNIT_FT" = "英尺"; +"MEASURING_UNIT_IN" = "英寸"; +"MEASURING_UNIT_KG" = "公斤"; +"MEASURING_UNIT_LB" = "磅"; +"MEASURING_UNIT_OZ" = "盎司"; + +/* Limb values. */ +"LIMB_LEFT" = "左"; +"LIMB_RIGHT" = "右"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "轻点来回答"; +"NULL_ANSWER" = "选择一个答案"; +"PLACEHOLDER_IMAGE_CHOICES" = "轻点来选择"; +"PLACEHOLDER_LONG_TEXT" = "轻点来书写"; + +/* Button titles */ +"BUTTON_AGREE" = "同意"; +"BUTTON_CANCEL" = "取消"; +"BUTTON_OK" = "好"; +"BUTTON_CLEAR" = "清除"; +"BUTTON_CLEAR_SIGNATURE" = "清除签名"; +"BUTTON_APPLY" = "应用"; +"BUTTON_DISAGREE" = "不同意"; +"BUTTON_DONE" = "完成"; +"BUTTON_GET_STARTED" = "开始"; +"BUTTON_LEARN_MORE" = "了解更多"; +"BUTTON_NEXT" = "下一步"; +"BUTTON_SKIP" = "跳过"; +"BUTTON_SKIP_QUESTION" = "跳过此问题"; +"BUTTON_START_TIMER" = "启动定时器"; +"BUTTON_OPTION_SAVE" = "存储以稍后查看"; +"BUTTON_OPTION_DISCARD" = "放弃结果"; +"BUTTON_OPTION_STOP_TASK" = "结束任务"; +"BUTTON_SAVE" = "存储"; +"BUTTON_CLEAR_ANSWER" = "清除答案"; +"BUTTON_READ_ONLY_MODE" = "此答案无法修改。"; +"BUTTON_COPYRIGHT" = "版权"; +"BUTTON_CLOSE" = "关闭"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "即将开始活动"; +"TASK_COMPLETE_TITLE" = "活动完成"; +"TASK_COMPLETE_TEXT" = "将对您的数据进行分析并在结果可用时通知您。"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "还剩%@。"; +"TOUCH_ANYWHERE_LABEL" = "触碰任意位置以继续"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "捕捉图像"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "重新捕捉图像"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "未找到相机。此步骤无法完成。"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "为了完成此步骤,请在“设置”中允许此App访问相机。"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "未指定捕捉图像的输出目录。"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "无法存储捕捉的图像。"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "开始录制"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "停止录制"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "重新采集视频"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "健身"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "距离(%@)"; +"FITNESS_HEARTRATE_TITLE" = "心率(次/分)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "请静坐%@。"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "以最快速度步行%@。"; +"FITNESS_INTRO_TEXT_FORMAT" = "本活动监控您的心率并测量%1$@内的步行距离。"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "请在室外以最快的速度步行%1$@。步行完成后,请静坐%2$@。若要开始,请轻点“开始”。"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "步态和平衡"; +"WALK_INTRO_TEXT" = "本活动测量您在步行和站立时的步态和平衡。请仅在步行安全区域(无外力辅助条件下)进行。"; +"WALK_INTRO_2_TEXT_%ld" = "请在步行安全区域(无外力辅助条件下)直线行走大约%ld步。"; +"WALK_INTRO_2_DETAIL" = "请将设备放入口袋或背包中,然后跟随音频指示操作。"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "现在请站立%@。"; +"WALK_STAND_INSTRUCTION_FORMAT" = "请站立%@。"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "转身并走回起点。"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "请直线步行最多%ld步。"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "找到一处您可以沿直线安全往返的地方。在路尽头转弯,不要停下来,就好像绕着圆锥体转圈一样。\n\n接下来会要求您转一圈,然后站立不动,双手放在两侧,双脚张开,与肩同宽。"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "准备就绪后,轻点“开始”。\n将设备放入口袋或背包中,然后跟随音频指示操作。"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "沿直线往返%@。尽可能跟平时一样走动。"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "走完一圈后站立不动,坚持%@。"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "您已经完成了本活动。"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "轻点速度"; +"TAPPING_TASK_TITLE_RIGHT" = "右手"; +"TAPPING_TASK_TITLE_LEFT" = "左手"; +"TAPPING_INTRO_TEXT" = "本活动测量您的轻点速度。"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "把设备放在平面上。"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "用同一只手上的两根手指来轮流轻点屏幕上的按钮。"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "用右手上的两根手指来轮流轻点屏幕上的按钮。"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "用左手上的两根手指来轮流轻点屏幕上的按钮。"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "现在用右手重复相同的测试。"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "现在用左手重复相同的测试。"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "用一根手指轻点,然后用另一根手指轻点。尽量保持均匀的轻点间隔。持续轻点%@。"; +"TAPPING_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"TAPPING_CALL_TO_ACTION_NEXT" = "轻点“下一步”来开始。"; +"TAP_BUTTON_TITLE" = "轻点"; +"TOTAL_TAPS_LABEL" = "轻点总次数"; +"TAPPING_INSTRUCTION" = "用两根手指尽可能以均匀的速度轻点按钮。"; +"TAPPING_INSTRUCTION_RIGHT" = "使用右手轻点按钮。"; +"TAPPING_INSTRUCTION_LEFT" = "使用左手轻点按钮。"; +"TAPPING_SKIP_TITLE" = "跳过这只手"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "阿姆斯勒方格表"; +"AMSLER_GRID_INTRO_TEXT" = "本活动帮助检测用户视力方面的问题。"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "在整个测试中,将设备置于靠近距您脸部12英寸(约30厘米)的位置,与眼睛同高。"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "闭上您的%@并盯着正方形网格中间的圆点。\n\n用您的手指或触控笔标记出您所看到的任何变形,如模糊的线或波浪线。\n\n完成后,在网格外的任意位置向左轻扫。"; +"AMSLER_GRID_LEFT_EYE" = "左眼"; +"AMSLER_GRID_RIGHT_EYE" = "右眼"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "嗓音"; +"AUDIO_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"AUDIO_INSTRUCTION" = "请对着麦克风说“啊啊啊”,时间越长越好。"; +"AUDIO_INTRO_TEXT" = "请深呼吸并对着麦克风说“啊啊啊”,时间越长越好。保持平稳的声音大小以使音频条保持蓝色。"; +"AUDIO_INTENDED_USE" = "本活动通过设备底部的麦克风来录制嗓音从而对其进行评估。"; +"AUDIO_TOO_LOUD_LABEL" = "太大声"; +"AUDIO_GENERIC_ERROR_LABEL" = "无法录音"; +"AUDIO_LEVEL_CHECK_LABEL" = "请耐心等待,我们正在检查背景噪声级。"; +"AUDIO_TOO_LOUD_MESSAGE" = "环境噪声级太高,无法录制您的声音。请移至较为安静的地方,然后再试一次。"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "就绪后,轻点“下一步”。"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "纯音测听"; +"TONE_AUDIOMETRY_INTENDED_USE" = "本活动测量您是否可听见不同的声音。"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "开始之前,请先插入并戴上耳机。\n\n这种声音十分微弱,与普通的提醒铃声有所不同。起初声音十分柔和,之后音量会慢慢增大。请注意听,然后轻点左边或右边的按钮来表示哪只耳朵听到了声音。"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"TONE_AUDIOMETRY_PREP_TEXT" = "现在您应该听到一个音调。使用设备一侧的控制来调整音量。\n\n请在准备好后,轻点任意按钮来开始测试。"; +"TONE_AUDIOMETRY_INSTRUCTION" = "每次一听到声音,就轻点左边或右边的按钮来表示哪只耳朵听到了声音。"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "左耳"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "右耳"; +"TONE_LABEL_%@_LEFT" = "%@ Hz,左"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz,右"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "纯音测听"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "听到音调时轻点。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "音调与音量"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "您将听到一连串的音调。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "听到一声音调后,轻点按钮。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "此测试的音量将设为50%。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "此测试需要大约10分钟。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "打开“勿扰模式”以防止打断。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "音调将先在您的右耳播放。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "现在音调将在您的左耳播放。"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "本活动识别个人的听力阈值水平,以dB HL为度量。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "确保设备的音量已设为最高。\n\n在本任务过程中,将在左耳或右耳播放柔和的音调。\n\n请仔细听并在每次听到音调时轻点按钮。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "此测试确定声音需要多大才能被您听见。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "参与问卷调查。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "针对“听力较好的耳朵”选择您的偏好(如果有)"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "左"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "右"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "无偏好"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "测试已取消"; +"dBHL_ALERT_TITLE_START_OVER" = "重新开始"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "取消测试"; +"dBHL_ALERT_TEXT" = "若要进行此测试,请重新连接您的AirPods或EarPods。"; +"dBHL_PROGRESS_COMPLETION_%@" = "已完成%@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "耳机"; +"HEADPHONES_UNKNOWN" = "未知"; +"HEADPHONES_NONE" = "无"; +"CONNECTED" = "已连接"; +"NOT_CONNECTED" = "未连接"; +"HEADPHONE_CONNECTED_%@" = "已连接 - %@"; +"HEADPHONE_DETECT_TITLE" = "连接耳机"; +"HEADPHONE_DETECT_TEXT" = "此测试要求Apple AirPods或Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "空间记忆"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "本活动通过重现%@亮起的顺序来测量您的短期空间记忆能力。"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "花朵"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "花朵"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "部分%@一次只亮起一个。请以亮起的顺序轻点这些%@。"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "部分%@一次只亮起一个。请以与亮起相反的顺序轻点这些%@。"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "若要开始,请轻点“开始”,然后留心观察。"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "得分"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "观察亮起的%@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "请以%@亮起的顺序轻点它们"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "请以相反的顺序轻点%@"; +"MEMORY_GAME_COMPLETE_TITLE" = "顺序完成"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "轻点“下一步”来继续"; +"MEMORY_GAME_FAILED_TITLE" = "再试一次"; +"MEMORY_GAME_FAILED_MESSAGE" = "您好像记错了顺序。轻点“下一步”来继续。"; +"MEMORY_GAME_TIMEOUT_TITLE" = "计时结束"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "时间已到。\n轻点“下一步”来继续。"; +"MEMORY_GAME_COMPLETE" = "游戏完成"; +"MEMORY_GAME_PAUSED_TITLE" = "暂停"; +"MEMORY_GAME_PAUSED_MESSAGE" = "轻点“下一步”来继续"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "本记忆活动的开发得到了旧金山加利福尼亚大学Katherine Possin博士和Joel Kramer博士的大力协助。"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "反应时间"; +"REACTION_TIME_TASK_INTENDED_USE" = "本活动评估您对视觉提示的反应时间。"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "屏幕出现蓝色圆点时立刻朝任意方向摇动设备。您将需要完成此操作%D次。"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "第%@/%@次尝试"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "蓝色圆圈出现时快速摇动设备"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "斯特鲁普"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "每次颜色名称出现的时候,选择所显示颜色名称的第一个字。"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "准备好进行“斯特鲁普”活动后,轻点“开始”。"; +"STROOP_TASK_STEP_TEXT" = "选择所显示颜色名称的第一个字。"; +"STROOP_COLOR_RED" = "红色"; +"STROOP_COLOR_GREEN" = "绿色"; +"STROOP_COLOR_BLUE" = "蓝色"; +"STROOP_COLOR_YELLOW" = "黄色"; +"STROOP_COLOR_RED_INITIAL" = "红"; +"STROOP_COLOR_GREEN_INITIAL" = "绿"; +"STROOP_COLOR_BLUE_INITIAL" = "蓝"; +"STROOP_COLOR_YELLOW_INITIAL" = "黄"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "汉诺塔"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "本活动评估您的解谜能力。"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "将整个圆盘堆以尽可能少的步数移到高亮显示的平台。"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "解谜"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "移动次数:%@\n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "我解不开这个谜"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "运动范围"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption必须为左或者右"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "左膝运动范围"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "右膝运动范围"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "本活动测试您左膝伸展的距离。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "本活动测试您右膝伸展的距离。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "坐在椅子的边缘上。开始前,将设备放在左膝上进行测试。请打开设备的声音,方便您听到指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "坐在椅子的边缘上。开始前,将设备放在右膝上进行测试。请打开设备的声音,方便您听到指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "将设备放在您的左膝上,屏幕朝外,如图所示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "将设备放在您的右膝上,屏幕朝外,如图所示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "就绪后,轻点屏幕以开始,并将左膝尽可能地伸展。完成后,将左膝归位并再次轻点。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "就绪后,轻点屏幕以开始,并将右膝尽可能地伸展。完成后,将右膝归位并再次轻点。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "将设备放在您的左膝上。轻点屏幕并将左膝尽可能地伸展。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "将设备放在您的右膝上。轻点屏幕并将右膝尽可能地伸展。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成后,将左膝归位。然后轻点任意位置。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成后,将右膝归位。然后轻点任意位置。"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "左肩运动范围"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "右肩运动范围"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "本活动测试您左肩伸展的距离。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "本活动测试您右肩伸展的距离。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "开始前,将设备放在左肩上进行测试。请打开设备的声音,方便您听到指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "开始前,将设备放在右肩上进行测试。请打开设备的声音,方便您听到指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "将设备放在您的左肩上,屏幕朝外,如图所示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "将设备放在您的右肩上,屏幕朝外,如图所示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "就绪后,轻点屏幕以开始,并将左手手臂尽可能地向前伸。完成后,将手臂归位并再次轻点。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "就绪后,轻点屏幕以开始,并将右手手臂尽可能地向前伸。完成后,将手臂归位并再次轻点。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "将设备放在您的左肩上。轻点屏幕并将左手手臂尽可能地向前伸。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "将设备放在您的右肩上。轻点屏幕并将右手手臂尽可能地向前伸。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成后,将左手手臂归位。然后轻点任意位置。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成后,将右手手臂归位。然后轻点任意位置。"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "计时步行"; +"TIMED_WALK_INTRO_DETAIL" = "本活动测量您的下肢功能。"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "找到一处地点,最好是户外,能够安全地以最快速度直线步行约%@。请不要放慢脚步,直到跨过终点线。"; +"TIMED_WALK_INTRO_2_DETAIL" = "轻点“下一步”来开始。"; +"TIMED_WALK_FORM_TITLE" = "辅助设备"; +"TIMED_WALK_FORM_TEXT" = "在每次测试中使用相同的辅助设备。"; +"TIMED_WALK_QUESTION_TEXT" = "您是否穿戴了踝足矫形器?"; +"TIMED_WALK_QUESTION_2_TITLE" = "您是否使用了辅助设备?"; +"TIMED_WALK_QUESTION_2_TEXT" = "轻点此处来选择答案。"; +"TIMED_WALK_QUESTION_2_CHOICE" = "无"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "单杖"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "单拐"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "双杖"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "双拐"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "轮椅/助行车"; +"TIMED_WALK_INSTRUCTION_%@" = "直线步行最多%@。"; +"TIMED_WALK_INSTRUCTION_TURN" = "转身。"; +"TIMED_WALK_INSTRUCTION_2" = "走回起点。"; +"TIMED_WALK_INSTRUCTION_TEXT" = "完成后,轻点“下一步”。"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "“步进式听觉累加实验”测量您的听觉信息处理速度和计算能力。"; +"PVSAT_INTRO_TEXT" = "“步进式视觉累加实验”测量您的视觉信息处理速度和计算能力。"; +"PAVSAT_INTRO_TEXT" = "“步进式听觉和视觉累加实验”测量您的听觉和视觉信息处理速度和计算能力。"; +"PSAT_INTRO_TEXT_2_%@" = "每隔%@会显示一个一位数。\n您必须将每个新数字与前一个数字相加。\n注意,您不用计算累加值,只需计算最后两个数字之和。"; +"PSAT_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"PSAT_INITIAL_INSTRUCTION" = "记住这第一个数字。"; +"PSAT_INSTRUCTION" = "将这个新数字与前一个数字相加。"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@孔插棒测试"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "本活动通过将圆饼放入圆孔来测量您的上肢功能。您将需要完成此操作%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "您的左手和右手都需要进行测试。\n您必须以最快速度拿起圆饼,将其放入圆孔中,完成%@次后,再将其移除%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "您的右手和左手都需要进行测试。\n您必须以最快速度拿起圆饼,将其放入圆孔中,完成%@次后,再将其移除%@次。"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "用您的左手将圆饼放入圆孔中。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "用您的右手将圆饼放入圆孔中。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "用您的左手将圆饼放在线条后方。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "用您的右手将圆饼放在线条后方。"; +"HOLE_PEG_TEST_TEXT" = "用两根手指拿起圆饼。"; +"HOLE_PEG_TEST_TEXT_2" = "抬起手指以放下圆饼。"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "颤抖活动"; +"TREMOR_TEST_INTRO_1_DETAIL" = "本活动测试在不同姿势下,您双手的颤抖情况。请找到一处舒适的地方坐下并完成此活动。"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "如下图所示,用更易受到影响的手握住手机。"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "如下图所示,用右手握住手机。"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "如下图所示,用左手握住手机。"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "请坐下并用手握住手机,然后完成%@。"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "一个任务"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "两个任务"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "三个任务"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "四个任务"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "五个任务"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "轻点下一步来继续。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "准备握住手机并放在膝盖上。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "准备用左手握住手机并放在膝盖上。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "准备用右手握住手机并放在膝盖上。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "握住手机并放在膝盖上,坚持%ld秒钟。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "现在伸直手臂并将手机举至肩高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "现在伸直左手臂并将手机举至肩高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "现在伸直右手臂并将手机举至肩高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "握住手机并伸直手臂,坚持%ld秒钟。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "现在把手机举至肩高并弯曲手肘。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "现在用左手握住手机,举至肩高并弯曲手肘。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "现在用右手握住手机,举至肩高并弯曲手肘。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "握住手机并弯曲手肘,坚持%ld秒钟"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "现在弯曲手肘,重复用手机接触您的鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "现在弯曲手肘并用左手握住手机,重复用手机接触您的鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "现在弯曲手肘并用右手握住手机,重复用手机接触您的鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "用手机接触鼻子,坚持%ld秒钟"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "准备挥手(通过转动手腕来挥手)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "用左手握住手机并准备挥手(通过转动手腕来挥手)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "用右手握住手机并准备挥手(通过转动手腕来挥手)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "持续挥手,坚持%ld秒钟。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "现在换左手握住手机并继续下一个任务。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "现在换右手握住手机并继续下一个任务。"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "继续下一个任务。"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "活动已完成。"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "请坐下并用一只手握住手机,然后完成%@,接着换另一只手再完成一次。"; +"TREMOR_SKIP_LEFT_HAND" = "我不能用左手完成本活动。"; +"TREMOR_SKIP_RIGHT_HAND" = "我不能用右手完成本活动。"; +"TREMOR_SKIP_NEITHER" = "我能用两只手完成本活动。"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "连线测试"; +"TRAILMAKING_INTENDED_USE" = "本活动通过记录按顺序轻点一系列圆点所需的时间,来评估您的视觉注意力和任务切换能力。"; +"TRAILMAKING_INTENDED_USE2_A" = "倒计时开始后,轮流轻点包含数字和字母的圆点。首先,轻点第一个数字“1”,然后轻点数字“2”–“3”–“4”…直到数字“7”。"; +"TRAILMAKING_INTENDED_USE2_B" = "倒计时开始后,轮流轻点包含数字和字母的圆点。首先,轻点第一个数字“1”,然后轻点第一个字母“A”,以此类推,依次轻点“2”–“B”–“3”–“C”…直到数字“7”。"; +"TRAILMAKING_INTRO_TEXT" = "以最快的速度完成而不出错。\n "; +"TRAILMAKING_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "语音识别"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "本活动使用设备底部的麦克风录制您的语音,并将它翻译成文本。"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "轻点“开始”来进行测试。"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "按下按钮以在说话前开始录音。"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "开始录制"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "停止录制"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "编辑文本记录"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "编辑文本记录以改正任何错误的语音解析。"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "您的文本记录将显示在此处。"; +"SPEECH_RECOGNITION_FAILED" = "语音识别失败。"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "初始化语音识别失败。"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "播放音频"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "停止播放音频"; +"SPEECH_IN_NOISE_TITLE" = "在噪声中说话"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "本活动测量噪声环境中语音的清晰度。"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "作为本测试的一部分,您将:\n\n听一个句子。\n\n清楚地复述您所听到的内容,或跳过以使用键盘键入您听到的内容。\n\n如果复述听到的内容,您可以选择修改由语音识别引擎生成的文本记录。"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "音量校准"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "轻点“播放音频”,将音量调整至舒适的程度,然后轻点“停止播放音频”以进行下一步。"; +"SPEECH_IN_NOISE_STEP_TITLE" = "听"; +"SPEECH_IN_NOISE_STEP_TEXT" = "混有背景噪声的句子会以随机信噪比(SNR)只播放一次。"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "说话"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "复述您所听到的内容。"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "无法创建文件"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "无法移除足够的日志文件来达到阈值"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "设定属性时出错"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "文件未标记为删除(未标记为上传)"; +"ERROR_DATALOGGER_MULTIPLE" = "移除日志时出现多个错误"; +"ERROR_RECORDER_NO_DATA" = "未找到任何已收集的数据。"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "未指定输出目录"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "SPL指示器"; +"ENVIRONMENTSPL_INTRO_TEXT" = "本活动测量环境声压级。如果噪声级过高,您将无法进行下一步。请转移到更安静的地方以完成本任务或稍后再重新进行本活动。"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "正在计算"; +"ENVIRONMENTSPL_THRESHOLD" = "阈值:%@ dBA"; +"ENVIRONMENTSPL_OK" = "背景噪声通过"; +"ENVIRONMENTSPL_NOISE" = "背景噪声过杂"; +"ENVIRONMENTSPL_TITLE_2" = "找一处安静的地方"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "为确保准确性,此测试应当在安静的环境中进行。"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "开始任务"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "无数据"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "移动滑块输入值"; +"SLIDER_I_DONT_KNOW" = "不知道"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "页面"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "上一步"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "显示PDF缩略图"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "隐藏PDF缩略图"; +"AX_BUTTON_ANNOTATE" = "注解"; +"AX_BUTTON_SHOW_SEARCH" = "显示搜索栏"; +"AX_BUTTON_HIDE_SEARCH" = "隐藏搜索栏"; +"AX_BUTTON_SHARE" = "共享"; + + +"AX_COMPLETION_ILLUSTRATION" = "蓝色圆圈中带有勾号的图示,表示成功"; + +"AX_SIGNVIEW_LABEL" = "指定签名栏"; +"AX_SIGNVIEW_HINT" = "触摸屏幕并移动手指来签名"; +"AX_SIGNVIEW_SIGNED" = "已签名"; +"AX_SIGNVIEW_UNSIGNED" = "未签名"; + +"AX_SELECTED" = "已选择"; +"AX_UNSELECTED" = "未选择"; +"AX_SELECT_ALL_THAT_APPLY" = "选择所有适用项"; + +"AX_SLIDER_LABEL" = "响应滑块。范围:%@ ~ %@"; +"AX_UNLABELED_IMAGE" = "无标签图像"; + +"AX_ANNOUNCE_BEGIN_TASK" = "开始任务"; + +"AX.MEMORY.TILE.ACTIVE" = "活跃"; +"AX.MEMORY.TILE.CORRECT" = "正确"; +"AX.MEMORY.TILE.INCORRECT" = "不正确"; +"AX.MEMORY.TILE.QUIESCENT" = "不活跃"; +"AX.MEMORY.TILE.LABEL" = "记忆游戏拼贴"; + +"AX_IMAGE_CAPTURE_LABEL" = "捕捉预览"; +"AX_IMAGE_CAPTURED_LABEL" = "捕捉的图像"; + +"AX_VIDEO_CAPTURE_LABEL" = "视频采集预览"; +"AX_VIDEO_CAPTURE_COMPLETE" = "视频采集完成"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "无法将大小为%@的圆盘放在大小为%@的圆盘上"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "目标圆盘"; +"AX_TOWER_OF_HANOI_TOWER" = "塔"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "轻点两下来放置圆盘"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "轻点两下来选择最顶端的圆盘"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "包含圆盘,大小为%@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "空"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "关闭键盘"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "范围:%@ ~ %@"; +"AX_GRAPH_STACK_PREFIX" = "圆盘堆组成:"; +"AX_GRAPH_AND_SEPARATOR" = "、"; +"AX_GRAPH_POINT_%@" = "分数:%@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "语音波形"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "录音开始后,再次激活以停止录音。"; + +"AX_AUDIO_BAR_GRAPH" = "音频条图形"; + +"AX_AMSLER_GRID_LABEL" = "阿姆斯勒方格表"; +"AX_AMSLER_GRID_HINT" = "用手指或触控笔直接标记网格,或在网格外向左轻扫以结束。"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "可轻点的按钮"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "轻点表示左耳"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "激活以开始测试。测试开始后,当您左耳听到声音时直接轻点此按钮。"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "轻点表示右耳"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "激活以开始测试。测试开始后,当您右耳听到声音时直接轻点此按钮。"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@使用旁白时,通过触碰学习表示每只耳朵的按钮位置来探索屏幕。测试开始时,按钮将变为可直接轻点。%@"; +"AX_TAP_BUTTON_1_LABEL" = "用一根手指轻点"; +"AX_TAP_BUTTON_2_LABEL" = "用另一根手指轻点"; +"AX_TAP_BUTTON_HINT" = "激活以使按钮变为可直接轻点。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@使用旁白时,通过触碰学习按钮位置来探索屏幕。激活任一按钮,使按钮变为可直接轻点。"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "按钮现可直接轻点。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@使用旁白时,该按钮将位于屏幕的中央附近,可直接轻点。"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@使用旁白时,测试中的按钮将变为可直接轻点。"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "无法解码restoreData以进行初始化"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..c9c5326 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_CN.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d个错误) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.strings new file mode 100755 index 0000000..375805b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.strings @@ -0,0 +1,701 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "同意書"; +"CONSENT_NAME_GIVEN" = "名字"; +"CONSENT_NAME_FAMILY" = "姓氏"; +"CONSENT_NAME_PLACEHOLDER" = "必填"; +"CONSENT_REVIEW_TITLE" = "同意書檢閱"; +"CONSENT_REVIEW_INSTRUCTION" = "請檢視以下表格,如你準備好繼續,請點一下「同意」。"; +"CONSENT_REVIEW_ALERT_TITLE" = "同意書檢閱"; +"CONSENT_SIGNATURE_TITLE" = "簽名"; +"CONSENT_SIGNATURE_INSTRUCTION" = "請用手指在以下方格內簽名。"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "在此簽名"; +"CONSENT_PAGE_NUMBER_FORMAT" = "第%1$ld頁(共%2$ld頁)"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "歡迎"; +"CONSENT_SECTION_DATA_GATHERING" = "數據收集"; +"CONSENT_SECTION_PRIVACY" = "私隱"; +"CONSENT_SECTION_DATA_USE" = "數據使用"; +"CONSENT_SECTION_STUDY_SURVEY" = "研究問卷"; +"CONSENT_SECTION_STUDY_TASKS" = "研究任務"; +"CONSENT_SECTION_TIME_COMMITMENT" = "所需時間"; +"CONSENT_SECTION_WITHDRAWING" = "退出研究"; +"CONSENT_LEARN_MORE_TITLE" = "了解更多"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "進一步了解數據的收集方法"; +"LEARN_MORE_DATA_USE" = "進一步了解數據的使用方法"; +"LEARN_MORE_PRIVACY" = "進一步了解你的私隱及個人身份如何得到保護"; +"LEARN_MORE_WELCOME" = "開始前先了解此研究"; +"LEARN_MORE_STUDY_SURVEY" = "進一步了解研究的問卷"; +"LEARN_MORE_TIME_COMMITMENT" = "進一步了解研究所花費的時間"; +"LEARN_MORE_TASKS" = "進一步了解相關的任務"; +"LEARN_MORE_WITHDRAWING" = "進一步了解退出研究"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "分享選項"; +"CONSENT_SHARE_WIDELY_%@" = "與「%@」及全世界合資格的研究者分享我的數據"; +"CONSENT_SHARE_ONLY_%@" = "只與「%@」分享我的數據"; +"CONSENT_SHARING_DESCRIPTION_%@" = "%@會收到你參與這個研究的研究數據。\n\n更廣泛地分享你的已編碼研究數據(不含你的姓名等資料)可能對此研究和未來的調查有益處。"; +"LEARN_MORE_CONSENT_SHARING" = "進一步了解數據共享"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "正楷名稱"; +"CONSENT_DOC_LINE_SIGNATURE" = "簽名"; +"CONSENT_DOC_LINE_DATE" = "日期"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "問題%1$@(共%2$@個)"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "已略過"; +"REVIEW_EDIT_ANSWER" = "編輯"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "無效值"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@超過了上限(%2$@)。"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@低於下限(%2$@)。"; +"RANGE_ALERT_MESSAGE_OTHER" = "%@不是有效的數值。"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "無效的電郵地址:%@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "輸入地址"; +"LOCATION_ERROR_TITLE" = "找不到指定的地址"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "無法找出現時位置,請輸入地址或移動至GPS訊號較佳的位置(如適用)。"; +"LOCATION_ERROR_MESSAGE_DENIED" = "定位服務存取遭拒,請前往「設定」以授權此App使用定位服務。"; +"LOCATION_ERROR_GEOCODE" = "找不到輸入的地址,請確定地址是否正確。"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "你可能未連接互聯網,或地址查詢請求的次數已超出上限。如果你未連接互聯網,請開啟Wi-Fi以回答此問題(如果顯示「略過」按鈕,則可略過此問題),或在連接互聯網後返回此問卷。否則,請在幾分鐘後再試一次。"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "文字內容超出長度上限:%@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "分割螢幕無法使用相機。"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "電郵"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "密碼"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "輸入密碼"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "確認"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "請再次輸入密碼"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "密碼不符。"; +"ADDITIONAL_INFO_SECTION_TITLE" = "其他資料"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "大明"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "王"; +"GENDER_FORM_ITEM_TITLE" = "性別"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "選擇性別"; +"DOB_FORM_ITEM_TITLE" = "出生日期"; +"DOB_FORM_ITEM_PLACEHOLDER" = "選擇日期"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "電話號碼"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+852 1111 1111"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "驗證"; +"VERIFICATION_STEP_TITLE" = "驗證你的電郵"; +"RESEND_EMAIL_LABEL_MESSAGE" = "如果你未收到驗證電郵,並希望系統再傳送一次,請點一下下方的連結。"; +"RESEND_EMAIL_BUTTON_TITLE" = "重新傳送驗證電郵"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "登入"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "忘記密碼?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "輸入密碼"; +"PASSCODE_CONFIRM_MESSAGE" = "確認密碼"; +"PASSCODE_SAVED_MESSAGE" = "密碼已儲存"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "已認證密碼"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "輸入舊密碼"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "輸入新密碼"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "確認新密碼"; +"PASSCODE_INVALID_ALERT_TITLE" = "密碼不正確"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "密碼不符,請再試一次。"; +"PASSCODE_TOUCH_ID_MESSAGE" = "請使用Touch ID認證"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID錯誤"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "只允許輸入數字。"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "密碼輸入進度指示器"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "已輸入%@個數字(共%@個)"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "忘記密碼?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "無法加入「鑰匙圈」項目。"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "無法更新「鑰匙圈」項目。"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "無法刪除「鑰匙圈」項目。"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "找不到「鑰匙圈」項目。"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "類型I"; +"FITZPATRICK_SKIN_TYPE_II" = "類型II"; +"FITZPATRICK_SKIN_TYPE_III" = "類型III"; +"FITZPATRICK_SKIN_TYPE_IV" = "類型IV"; +"FITZPATRICK_SKIN_TYPE_V" = "類型V"; +"FITZPATRICK_SKIN_TYPE_VI" = "類型VI"; + +/* Gender values. */ +"GENDER_FEMALE" = "女性"; +"GENDER_MALE" = "男性"; +"GENDER_OTHER" = "其他"; + +/* Boolean answer strings */ +"BOOL_NO" = "不是"; +"BOOL_YES" = "是"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "厘米"; +"MEASURING_UNIT_FT" = "呎"; +"MEASURING_UNIT_IN" = "吋"; +"MEASURING_UNIT_KG" = "公斤"; +"MEASURING_UNIT_LB" = "磅"; +"MEASURING_UNIT_OZ" = "安士"; + +/* Limb values. */ +"LIMB_LEFT" = "左"; +"LIMB_RIGHT" = "右"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "點一下回答"; +"NULL_ANSWER" = "選擇答案"; +"PLACEHOLDER_IMAGE_CHOICES" = "點一下選擇"; +"PLACEHOLDER_LONG_TEXT" = "點一下編寫"; + +/* Button titles */ +"BUTTON_AGREE" = "同意"; +"BUTTON_CANCEL" = "取消"; +"BUTTON_OK" = "好"; +"BUTTON_CLEAR" = "清除"; +"BUTTON_CLEAR_SIGNATURE" = "清除簽名"; +"BUTTON_APPLY" = "套用"; +"BUTTON_DISAGREE" = "不同意"; +"BUTTON_DONE" = "完成"; +"BUTTON_GET_STARTED" = "開始"; +"BUTTON_LEARN_MORE" = "了解更多"; +"BUTTON_NEXT" = "下一步"; +"BUTTON_SKIP" = "略過"; +"BUTTON_SKIP_QUESTION" = "略過此問題"; +"BUTTON_START_TIMER" = "開始計時器"; +"BUTTON_OPTION_SAVE" = "儲存作日後之用"; +"BUTTON_OPTION_DISCARD" = "放棄測試結果"; +"BUTTON_OPTION_STOP_TASK" = "結束測試任務"; +"BUTTON_SAVE" = "儲存"; +"BUTTON_CLEAR_ANSWER" = "清除答案"; +"BUTTON_READ_ONLY_MODE" = "無法修改此答案。"; +"BUTTON_COPYRIGHT" = "版權"; +"BUTTON_CLOSE" = "關閉"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "測試活動倒數"; +"TASK_COMPLETE_TITLE" = "測試活動已完成"; +"TASK_COMPLETE_TEXT" = "測試活動將會進行分析。當得到結果時,你將會收到通知。"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "剩餘%@。"; +"TOUCH_ANYWHERE_LABEL" = "點一下任何一處以繼續"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "截取圖案"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "重新截取圖案"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "找不到相機,無法完成此步驟。"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "如要完成此步驟,請前往「設定」以允許此App使用相機。"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "未指定截取圖案的輸出目錄。"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "無法儲存截取的圖案。"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "開始錄製"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "停止錄影"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "重新截取影片"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "體能"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "距離(%@)"; +"FITNESS_HEARTRATE_TITLE" = "心跳率(每分鐘次數)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "安坐%@。"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "用最快的速度步行%@。"; +"FITNESS_INTRO_TEXT_FORMAT" = "此測試活動能監測你的心跳率,並量度你在%1$@內能步行的最遠距離。"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "在室外以最快的配速步行%1$@。完成後,安坐並休息%2$@。點一下「開始」以進行測試。"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "步態及平衡"; +"WALK_INTRO_TEXT" = "此測試活動可測量你步行及站立時的步態及平衡。如果你行動不便或行走時需要輔助,請勿繼續進行。"; +"WALK_INTRO_2_TEXT_%ld" = "找一個安全的地方,讓你可以不靠輔助地直線步行大約%ld步。"; +"WALK_INTRO_2_DETAIL" = "將你的裝置放入口袋或手袋中,並跟隨音訊指示。"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "現在站立%@。"; +"WALK_STAND_INSTRUCTION_FORMAT" = "站立%@。"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "掉頭,然後步行回到起點。"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "直線步行最多%ld步。"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "找一個你可以安全地來回走直線的地方。請在路徑的盡頭調頭以持續行走,就像繞過錐形路標走路。\n然後你會收到指示360度自轉一次,並以雙手放在身側,雙腳稍微分開至肩膀距離的姿勢站立不動。"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "當你準備好開始時,點一下「開始」。\n然後將你的裝置放入口袋或手袋中,並跟隨音訊指示。"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "以平常姿態,直線來回步行%@。"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "轉一個圈,然後站立%@。"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "你已完成測試活動。"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "點按速度"; +"TAPPING_TASK_TITLE_RIGHT" = "右手"; +"TAPPING_TASK_TITLE_LEFT" = "左手"; +"TAPPING_INTRO_TEXT" = "此測試活動能評估你的點按速度。"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "將裝置放在一個平面上。"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "請用同一隻手的兩指梅花間竹地點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "請用右手的兩指梅花間竹地點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "請用左手的兩指梅花間竹地點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "現在用右手進行相同的測試。"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "現在用左手進行相同的測試。"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "先用一指點按,然後用另一指點按。請嘗試以最平穩的速度,持續點按%@。"; +"TAPPING_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"TAPPING_CALL_TO_ACTION_NEXT" = "點一下「下一步」開始。"; +"TAP_BUTTON_TITLE" = "點按"; +"TOTAL_TAPS_LABEL" = "點按總次數"; +"TAPPING_INSTRUCTION" = "用兩指以最平穩的速度點按這些按鈕。"; +"TAPPING_INSTRUCTION_RIGHT" = "用你的右手點按這些按鈕。"; +"TAPPING_INSTRUCTION_LEFT" = "用你的左手點按這些按鈕。"; +"TAPPING_SKIP_TITLE" = "略過這隻手"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "阿姆斯勒⽅格"; +"AMSLER_GRID_INTRO_TEXT" = "此活動有助偵測用户的視力問題。"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "在整個測試期間,將裝置放在面孔前方與視線成水平,距離約30厘米。"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "閉上你的%@並注視方格中央的點。\n\n使用手指或觸控筆,標記你看到的任何變形地方,例如模糊或波浪線條。\n\n完成後,在方格外任何位置向左掃。"; +"AMSLER_GRID_LEFT_EYE" = "左眼"; +"AMSLER_GRID_RIGHT_EYE" = "右眼"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "語音"; +"AUDIO_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"AUDIO_INSTRUCTION" = "對着咪高風發出「呀─」的聲音,時間愈長愈好。"; +"AUDIO_INTRO_TEXT" = "深呼吸,然後對着咪高風發出「呀─」的聲音,時間愈長愈好。請保持穩定的音量,以使音量棒圖維持藍色。"; +"AUDIO_INTENDED_USE" = "此測試活動會以裝置底部的咪高風錄下你的聲音並進行評估。"; +"AUDIO_TOO_LOUD_LABEL" = "太大聲"; +"AUDIO_GENERIC_ERROR_LABEL" = "無法錄音"; +"AUDIO_LEVEL_CHECK_LABEL" = "正在檢查背景雜音音量,請稍候。"; +"AUDIO_TOO_LOUD_MESSAGE" = "環境雜音太大聲,無法錄取你的聲音。請前往較靜的地方,然後再試一次。"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "準備好後,請點一下「下一步」。"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "純音聽力檢查"; +"TONE_AUDIOMETRY_INTENDED_USE" = "此測試活動能評估你聆聽不同聲音的能力。"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "開始測試前,請連接並戴上耳筒。\n\n聲音會很微細並與一般警示聲音不同。  該聲音開始會很弱並慢慢變大聲。  請注意並點一下左或右按鈕來顯示哪一隻耳朵聽到聲音。"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"TONE_AUDIOMETRY_PREP_TEXT" = "你現在會聽到一個聲調。使用裝置側邊的控制項目來調整音量。\n\n當你準備好開始時,請按一下任何按鈕。"; +"TONE_AUDIOMETRY_INSTRUCTION" = "每次當你開始聽到聲音時,請點一下左或右按鈕以指出哪一邊耳朵聽見聲音。"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "左耳"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "右耳"; +"TONE_LABEL_%@_LEFT" = "%@ Hz,左"; +"TONE_LABEL_%@_RIGHT" = "%@ Hz,右"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "純音聽力檢查"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "當你聽到聲音時,請點一下。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "聲音與音量"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "你將會聽到一連串聲音。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "當你聽到聲音時,請點一下按鈕。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "就是次測試,音量將會設定為50%。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "此測試需時大約10分鐘。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "開啟「請勿打擾」以避免打擾。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "會先在你的右耳播放聲音。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "現在會在你的左耳播放聲音。"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "此測試活動以分貝聽力級別為單位辨識個別人士的聽力臨界值。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "請確定裝置音量已設定為最大聲。\n\n在此測試活動中,會在左耳或右耳播放一個微細的音調。\n\n細心聆聽並在每次聽到音調時點一下按鈕。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "此測試識別聲音需要多大你才能聽得到。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "測試前問卷調查。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "選擇「聽力較好」偏好設定(如有)"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "左"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "右"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "沒有偏好"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "測試已取消"; +"dBHL_ALERT_TITLE_START_OVER" = "重新開始"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "取消測試"; +"dBHL_ALERT_TEXT" = "重新連接AirPods或EarPods以進行測試。"; +"dBHL_PROGRESS_COMPLETION_%@" = "已完成%@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "耳筒"; +"HEADPHONES_UNKNOWN" = "未知"; +"HEADPHONES_NONE" = "無"; +"CONNECTED" = "已連接"; +"NOT_CONNECTED" = "未連接"; +"HEADPHONE_CONNECTED_%@" = "已連接 - %@"; +"HEADPHONE_DETECT_TITLE" = "連接你的耳筒"; +"HEADPHONE_DETECT_TEXT" = "此測試需要Apple AirPods或Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "空間記憶"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "此測試活動需要你重覆%@圖案亮起的次序,以測量你的短期空間記憶。"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "花朵"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "花朵"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "部分%@圖案會逐個亮起。請以亮起的次序點按這些%@圖案。"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "部分%@圖案會逐個亮起。請以亮起的相反次序點按這些%@圖案。"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "點一下「開始」以進行測試,然後細心觀看。"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "分數"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "看亮起的%@"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "以剛才亮起的順序點按%@圖案"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "按相反次序點按%@圖案"; +"MEMORY_GAME_COMPLETE_TITLE" = "已完成順序"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "如要繼續,點一下「下一步」"; +"MEMORY_GAME_FAILED_TITLE" = "再試一次"; +"MEMORY_GAME_FAILED_MESSAGE" = "你似乎記錯了順序。點一下「下一步」繼續。"; +"MEMORY_GAME_TIMEOUT_TITLE" = "時間到了"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "時限已經到了。\n按一下「下一步」來繼續。"; +"MEMORY_GAME_COMPLETE" = "遊戲結束"; +"MEMORY_GAME_PAUSED_TITLE" = "已暫停"; +"MEMORY_GAME_PAUSED_MESSAGE" = "如要繼續,點一下「下一步」"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "此記憶測試活動由三藩市加利福尼亞大學之Katherine Possin, PhD及Joel Kramer, PhD輔助開發。"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "反應時間"; +"REACTION_TIME_TASK_INTENDED_USE" = "此測試活動會評估你對視覺提示作出反應所需的時間。"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "當螢幕顯示藍色圓點時,請立刻以任何方向搖動裝置。你將需要執行此操作%D次。"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "第%@/%@次嘗試"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "當藍色圓圈出現時,請快速搖動裝置"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "斯特魯普"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "每次當字詞出現時,請選擇所顯示之「顏色」的首字。"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "當你準備好開始進行「斯特魯普」測試活動時,請點一下「開始」。"; +"STROOP_TASK_STEP_TEXT" = "請選擇所顯示之「顏色」的首字。"; +"STROOP_COLOR_RED" = "紅色"; +"STROOP_COLOR_GREEN" = "綠色"; +"STROOP_COLOR_BLUE" = "藍色"; +"STROOP_COLOR_YELLOW" = "黃色"; +"STROOP_COLOR_RED_INITIAL" = "紅"; +"STROOP_COLOR_GREEN_INITIAL" = "綠"; +"STROOP_COLOR_BLUE_INITIAL" = "藍"; +"STROOP_COLOR_YELLOW_INITIAL" = "黃"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "河內塔"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "此測試活動會評估你的解題能力。"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "用最少的次數將所有圓盤移到有顏色標示的平台。"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "解開謎題"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "移動次數:%@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "我無法解開此謎題"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "動作範圍"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption 必須為左或右"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "左膝動作範圍"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "右膝動作範圍"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "此測試活動可測量你左膝的伸展幅度。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "此測試活動可測量你右膝的伸展幅度。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "請坐在椅子的邊緣。當你開始時,你須將裝置放在左膝上以進行測量。請開啟裝置的聲音,讓你可以聽取指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "請坐在椅子的邊緣。當你開始時,你須將裝置放在右膝上以進行測量。請開啟裝置的聲音,讓你可以聽取指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "請將裝置放在左膝上,螢幕向外(如圖)。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "請將裝置放在右膝上,螢幕向外(如圖)。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "準備好時,點一下螢幕即可開始,將你的左膝盡量伸展到最遠的距離。完成後,將你的左膝還原至開始時的位置,並且再點一下。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "準備好時,點一下螢幕即可開始,將你的右膝盡量伸展到最遠的距離。完成後,將你的右膝還原至開始時的位置,並且再點一下。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "將裝置放在你的左膝上。點一下螢幕並將左膝盡量伸展到最遠的距離。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "將裝置放在你的右膝上。點一下螢幕並將右膝盡量伸展到最遠的距離。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成後,請將你的左膝還原至開始時的位置。然後點一下任何位置。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成後,請將你的右膝還原至開始時的位置。然後點一下任何位置。"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "左肩動作範圍"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "右肩動作範圍"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "此測試活動可測量你左肩的伸展幅度。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "此測試活動可測量你右肩的伸展幅度。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "當你開始時,你須將裝置放在左肩上以進行測量。請開啟裝置的聲音,讓你可以聽取指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "當你開始時,你須將裝置放在右肩上以進行測量。請開啟裝置的聲音,讓你可以聽取指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "請將裝置放在左肩上,螢幕向外(如圖)。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "請將裝置放在右肩上,螢幕向外(如圖)。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "當準備好,點一下螢幕即可開始,舉起你的左臂,盡量向上方伸展。完成後,將左臂還原至開始時的位置,並且再點一下。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "當準備好,點一下螢幕即可開始,舉起你的右臂,盡量向上方伸展。完成後,將右臂還原至開始時的位置,並且再點一下。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "將裝置放在你的左肩上。點一下螢幕,舉起你的左臂,盡量向前方伸展。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "將裝置放在你的右肩上。點一下螢幕,舉起你的右臂,盡量向前方伸展。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成後,請將你的左臂還原至開始時的位置。然後點一下任何位置。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成後,請將你的右臂還原至開始時的位置。然後點一下任何位置。"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "定時步行"; +"TIMED_WALK_INTRO_DETAIL" = "此測試活動可測量你的下肢功能。"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "找一個地方(最好在室外),讓你可以用最快的速度直線步行大約%@。通過終點線前請勿放慢速度。"; +"TIMED_WALK_INTRO_2_DETAIL" = "點一下「下一步」開始。"; +"TIMED_WALK_FORM_TITLE" = "輔助器材"; +"TIMED_WALK_FORM_TEXT" = "每次測試時請使用相同的輔助器材。"; +"TIMED_WALK_QUESTION_TEXT" = "你是否穿戴足踝矯形器?"; +"TIMED_WALK_QUESTION_2_TITLE" = "你是否使用輔助器材?"; +"TIMED_WALK_QUESTION_2_TEXT" = "點一下此處以選擇答案。"; +"TIMED_WALK_QUESTION_2_CHOICE" = "無"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "單邊手杖"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "單邊拐杖"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "雙邊手杖"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "雙邊拐杖"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "助行架或四輪助行架"; +"TIMED_WALK_INSTRUCTION_%@" = "直線步行最多%@。"; +"TIMED_WALK_INSTRUCTION_TURN" = "掉頭。"; +"TIMED_WALK_INSTRUCTION_2" = "步行回到起點。"; +"TIMED_WALK_INSTRUCTION_TEXT" = "完成後,請點一下「下一步」。"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "定時聽覺連續加法測試(PASAT)可測量你的聽覺資料處理速度及計算能力。"; +"PVSAT_INTRO_TEXT" = "定時視覺連續加法測試(PVSAT)可測量你的視覺資料處理速度及計算能力。"; +"PAVSAT_INTRO_TEXT" = "定時聽覺及視覺連續加法測試(PAVSAT)可測量你的聽覺及視覺資料處理速度及計算能力。"; +"PSAT_INTRO_TEXT_2_%@" = "每%@秒會顯示一個個位數字。\n你必須將每個新數字和前一個數字相加。\n請注意,你不能計算所有數字的總和,只需算最後兩個數字的總和。"; +"PSAT_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"PSAT_INITIAL_INSTRUCTION" = "記住第一個數字。"; +"PSAT_INSTRUCTION" = "將這個新的數字與前一個數字相加。"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@孔柱測試"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "此測試活動需要你將圓柱放進洞內,以測量你的上肢功能。你將需要執行此操作%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "你的左右手都會被測試。\n你必須盡快拿起釘子放入洞中,並在完成%@次後,再拿出來%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "你的左右手都會被測試。\n你必須盡快拿起釘子放入洞中,並在完成%@次後,再拿出來%@次。"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "請用左手將圓柱放進洞中。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "請用右手將圓柱放進洞中。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "請用左手將圓柱放進線後。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "請用右手將圓柱放進線後。"; +"HOLE_PEG_TEST_TEXT" = "用兩指拿起圓柱。"; +"HOLE_PEG_TEST_TEXT_2" = "放開手指以放下圓柱。"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "顫抖測試活動"; +"TREMOR_TEST_INTRO_1_DETAIL" = "此測試活動可測量你雙手不同位置的顫抖情況。請找一個地方,讓你可以在此測試活動期間舒適坐下。"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "請用較受影響的手拿着電話,如下圖所示。"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "請用右手拿着電話,如下圖所示。"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "請用左手拿着電話,如下圖所示。"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "你將需要坐着,並拿着電話進行%@。"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "一個任務"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "兩個任務"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "三個任務"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "四個任務"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "五個任務"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "點一下「下一步」繼續。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "請準備將手放在大腿上,然後拿着電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "請準備將左手放在大腿上,然後拿着電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "請準備將右手放在大腿上,然後拿着電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "將手放在大腿上,然後拿着電話%ld秒。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "現在伸直手臂,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "現在伸直左手手臂,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "現在伸直右手手臂,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "伸直手臂,然後拿着電話%ld秒。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "現在彎曲手肘,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "現在彎曲左手手肘,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "現在彎曲右手手肘,並將電話拿到肩膊的高度。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "彎曲手肘,然後拿着電話%ld秒"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "現在繼續彎曲手肘,並用電話重複觸碰鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "現在繼續彎曲左手手肘,並拿着電話重複觸碰鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "現在繼續彎曲右手手肘,並拿着電話重複觸碰鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "拿着電話觸碰鼻子%ld秒"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "請準備進行揮手動作(只揮動手腕)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "請準備用左手拿着電話,進行揮手動作(只揮動手腕)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "請準備用右手拿着電話,進行揮手動作(只揮動手腕)。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "繼續進行揮手動作%ld秒。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "現在用左手拿着電話,並繼續進行下一個任務。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "現在用右手拿着電話,並繼續進行下一個任務。"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "繼續進行下一個任務。"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "測試活動已完成。"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "你將需要坐着,先用一隻手拿着電話進行%@,然後再用另一隻手進行。"; +"TREMOR_SKIP_LEFT_HAND" = "我無法用左手進行此測試活動。"; +"TREMOR_SKIP_RIGHT_HAND" = "我無法用右手進行此測試活動。"; +"TREMOR_SKIP_NEITHER" = "我可以用雙手進行此測試活動。"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "連線測試"; +"TRAILMAKING_INTENDED_USE" = "此測試活動會記錄你順序點按一系列圓點所需的時間,以評估你的視覺注意力及工作切換的能力。"; +"TRAILMAKING_INTENDED_USE2_A" = "倒數之後,請梅花間竹地點按數字及字母的圓點。首先點一下第一個數字「1」,然後數字「2」、「3」、「4」⋯直到數字「7」。"; +"TRAILMAKING_INTENDED_USE2_B" = "倒數之後,請梅花間竹地點按數字及字母的圓點。首先點一下第一個數字「1」,然後點一下第一個字母「A」,然後「2」、「B」、「3」、「C」⋯直到數字「7」。"; +"TRAILMAKING_INTRO_TEXT" = "在不犯錯的情況下盡快完成。 \n "; +"TRAILMAKING_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "語音辨識"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "此測試活動會以裝置底部的咪高風錄下你的語音,並將語音翻譯為文字。"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "點一下「開始」以進行測試。"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "開始說話前,請按下按鈕來開始錄音。"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "開始錄音"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "停止錄音"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "編輯文字記錄"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "編輯文字記錄以改正任何對語音的誤譯。"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "你的文字記錄會在此顯示。"; +"SPEECH_RECOGNITION_FAILED" = "語音辨識失敗。"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "初始化語音辨識失敗。"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "播放音訊"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "停止音訊"; +"SPEECH_IN_NOISE_TITLE" = "在噪音中說話"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "此測試活動能評估在噪音環境中的語音清晰度。"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "作為此測試的一部份,你會:\n\n聆聽一句句子。\n\n清晰地重複你聽到的內容,或跳過此程序,以鍵盤輸入你聽到的內容。\n\n如你重複你聽到的內容,你可以選擇修改由語音辨識引擎產生的文字記錄。"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "音量校正"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "按一下「播放音訊」,將音量調整至一個舒適的水平,然後按一下「停止音訊」以繼續。"; +"SPEECH_IN_NOISE_STEP_TITLE" = "聆聽"; +"SPEECH_IN_NOISE_STEP_TEXT" = "只會播放一次以隨機訊噪比(SNR)混合背景噪音的句子。"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "朗讀"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "重複你聽到的內容。"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "無法製作檔案"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "無法移除足夠的記錄檔案以達到臨界值"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "設定屬性錯誤"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "檔案未標示為已刪除(未標示為已上載)"; +"ERROR_DATALOGGER_MULTIPLE" = "移除記錄檔時發生多個錯誤"; +"ERROR_RECORDER_NO_DATA" = "找不到已收集的數據。"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "未指定輸出目錄"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "聲壓計"; +"ENVIRONMENTSPL_INTRO_TEXT" = "此測試活動可測量環境聲壓水平。如果噪音水平太高,你將無法進行。請移至一個比較安靜的位置來完成此測試活動,或在稍後重新進行。"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "正在計算"; +"ENVIRONMENTSPL_THRESHOLD" = "臨界值:%@dBA"; +"ENVIRONMENTSPL_OK" = "背景噪音正常"; +"ENVIRONMENTSPL_NOISE" = "太多背景噪音"; +"ENVIRONMENTSPL_TITLE_2" = "找一個安靜的地方"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "為確保準確性,此測試應該在一個安靜的環境中進行。"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "開始任務"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "沒有數據"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "移動滑桿以輸入數值"; +"SLIDER_I_DONT_KNOW" = "我不知道"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "頁面"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "上一步"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "顯示PDF縮圖"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "隱藏PDF縮圖"; +"AX_BUTTON_ANNOTATE" = "註解"; +"AX_BUTTON_SHOW_SEARCH" = "顯示搜尋列"; +"AX_BUTTON_HIDE_SEARCH" = "隱藏搜尋列"; +"AX_BUTTON_SHARE" = "分享"; + + +"AX_COMPLETION_ILLUSTRATION" = "藍色圓圈內的剔號圖示表示成功"; + +"AX_SIGNVIEW_LABEL" = "指定簽名欄位"; +"AX_SIGNVIEW_HINT" = "觸碰螢幕並移動手指簽名"; +"AX_SIGNVIEW_SIGNED" = "已簽名"; +"AX_SIGNVIEW_UNSIGNED" = "未簽名"; + +"AX_SELECTED" = "已選擇"; +"AX_UNSELECTED" = "未選擇"; +"AX_SELECT_ALL_THAT_APPLY" = "選擇所有適用的選項"; + +"AX_SLIDER_LABEL" = "回應滑桿。範圍由%@至%@"; +"AX_UNLABELED_IMAGE" = "未標記的圖案"; + +"AX_ANNOUNCE_BEGIN_TASK" = "開始任務"; + +"AX.MEMORY.TILE.ACTIVE" = "動態"; +"AX.MEMORY.TILE.CORRECT" = "正確"; +"AX.MEMORY.TILE.INCORRECT" = "不正確"; +"AX.MEMORY.TILE.QUIESCENT" = "靜態"; +"AX.MEMORY.TILE.LABEL" = "記憶遊戲圖樣"; + +"AX_IMAGE_CAPTURE_LABEL" = "截取預覽"; +"AX_IMAGE_CAPTURED_LABEL" = "截取的圖案"; + +"AX_VIDEO_CAPTURE_LABEL" = "截取影片預覽"; +"AX_VIDEO_CAPTURE_COMPLETE" = "完成截取影片"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "無法將%@號的圓盤放在%@號的圓盤上"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "目標"; +"AX_TOWER_OF_HANOI_TOWER" = "塔座"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "點兩下放置圓盤"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "點兩下選擇最上方的圓盤"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "其中的圓盤大小是%@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "空白"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "關閉鍵盤"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "範圍介乎%@至%@"; +"AX_GRAPH_STACK_PREFIX" = "圓盤柱的組成方式:"; +"AX_GRAPH_AND_SEPARATOR" = " 與 "; +"AX_GRAPH_POINT_%@" = "點數:%@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "語音波形"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "當錄音開始時,再啟動一次來停止錄音。"; + +"AX_AUDIO_BAR_GRAPH" = "音量棒圖表"; + +"AX_AMSLER_GRID_LABEL" = "阿姆斯勒⽅格"; +"AX_AMSLER_GRID_HINT" = "用你的手指或觸控筆直接標記該方格,或在方格外向左掃來完成。"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "可輕點的按鈕"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "點一下表示左耳"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "啟用以開始測試。測試開始後,當你的左耳聽到聲音時,請直接點一下此按鈕。"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "點一下表示右耳"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "啟用以開始測試。測試開始後,當你的右耳聽到聲音時,請直接點一下此按鈕。"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@使用「旁白」時,透過觸碰來學習每隻耳朵的按鈕之所在位置以探索螢幕。測試開始時,按鈕將變為可以直接輕點。%@"; +"AX_TAP_BUTTON_1_LABEL" = "用一隻手指點一下"; +"AX_TAP_BUTTON_2_LABEL" = "用另一隻手指點一下"; +"AX_TAP_BUTTON_HINT" = "啟用以令按鈕變為可以直接輕點。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@使用「旁白」後,透過觸碰來學習按鈕所在位置以探索螢幕。啟用任何一個按鈕,令按鈕變為可以直接輕點。"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "按鈕現已可以直接輕點。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@使用「旁白」時,按鈕將可以直接輕點。按鈕位置將位於螢幕中心附近·。"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@使用「旁白」時,測試中的按鈕將可以直接輕點。"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "無法解碼restoreData以進行初始化"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7832e16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_HK.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d個錯誤) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.strings b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.strings new file mode 100755 index 0000000..4ffe939 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.strings @@ -0,0 +1,719 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Informed consent process. */ +"CONSENT_NAME_TITLE" = "許可"; +"CONSENT_NAME_GIVEN" = "名字"; +"CONSENT_NAME_FAMILY" = "姓氏"; +"CONSENT_NAME_PLACEHOLDER" = "必填"; +"CONSENT_REVIEW_TITLE" = "檢視"; +"CONSENT_REVIEW_INSTRUCTION" = "檢視下方的表單,準備好繼續時請點一下「同意」。"; +"CONSENT_REVIEW_ALERT_TITLE" = "檢視"; +"CONSENT_SIGNATURE_TITLE" = "簽名"; +"CONSENT_SIGNATURE_INSTRUCTION" = "請使用手指在下方的方框內簽名。"; +"CONSENT_SIGNATURE_PLACEHOLDER" = "在此處簽名"; +"CONSENT_PAGE_NUMBER_FORMAT" = "第%1$ld頁(共%2$ld頁)"; + +/* Consent section titles. */ +"CONSENT_SECTION_WELCOME" = "歡迎"; +"CONSENT_SECTION_DATA_GATHERING" = "收集資料"; +"CONSENT_SECTION_PRIVACY" = "隱私權"; +"CONSENT_SECTION_DATA_USE" = "使用資料"; +"CONSENT_SECTION_STUDY_SURVEY" = "研究問卷"; +"CONSENT_SECTION_STUDY_TASKS" = "研究任務"; +"CONSENT_SECTION_TIME_COMMITMENT" = "花費時間"; +"CONSENT_SECTION_WITHDRAWING" = "退出"; +"CONSENT_LEARN_MORE_TITLE" = "更多內容"; + +/* Consent section learn more */ +"LEARN_MORE_DATA_GATHERING" = "進一步瞭解資料如何被收集"; +"LEARN_MORE_DATA_USE" = "進一步瞭解資料如何被使用"; +"LEARN_MORE_PRIVACY" = "進一步瞭解隱私權和識別身分如何被保護"; +"LEARN_MORE_WELCOME" = "開始前先瞭解研究內容"; +"LEARN_MORE_STUDY_SURVEY" = "進一步瞭解研究問卷"; +"LEARN_MORE_TIME_COMMITMENT" = "進一步瞭解研究需花費的時間"; +"LEARN_MORE_TASKS" = "進一步瞭解相關的任務"; +"LEARN_MORE_WITHDRAWING" = "進一步瞭解如何退出"; + +/* Consent sharing step */ +"CONSENT_SHARING_TITLE" = "分享選項"; +"CONSENT_SHARE_WIDELY_%@" = "與%@和全世界合格的研究學者分享我的資料"; +"CONSENT_SHARE_ONLY_%@" = "只與%@分享資料"; +"CONSENT_SHARING_DESCRIPTION_%@" = "由於您參與了本項研究,因此%@會收到您的研究資料。\n\n更廣泛地分享您經過加密的資料(不包括姓名等資訊)將有助於此研究和未來研究的發展。"; +"LEARN_MORE_CONSENT_SHARING" = "進一步瞭解資料分享"; + +/* Lines beneath typewritten signatures on documents.*/ +"CONSENT_DOC_LINE_PRINTED_NAME" = "工整書寫姓名"; +"CONSENT_DOC_LINE_SIGNATURE" = "簽名"; +"CONSENT_DOC_LINE_DATE" = "日期"; + +/* Progress indication (in navigation bar). */ +"STEP_PROGRESS_FORMAT" = "%1$@/%2$@"; + +/* Progress indication (in formItem section header). */ +"FORM_ITEM_PROGRESS" = "問題%1$@(共%2$@個)"; + +/* ORKTaskReviewViewController */ +"REVIEW_SKIPPED_ANSWER" = "已略過"; +"REVIEW_EDIT_ANSWER" = "編輯"; + +/* Alert for out of range values. */ +"RANGE_ALERT_TITLE" = "無效值"; +"RANGE_ALERT_MESSAGE_ABOVE_MAXIMUM" = "%1$@超過最大的允許值 (%2$@)。"; +"RANGE_ALERT_MESSAGE_BELOW_MAXIMUM" = "%1$@低於最小的允許值 (%2$@)。"; +"RANGE_ALERT_MESSAGE_OTHER" = "「%@」不是有效值。"; + +/* Alert for invalid email address value */ +"INVALID_EMAIL_ALERT_MESSAGE" = "無效的電子郵件地址:%@"; + +/* Alerts for invalid location coordinates */ +"LOCATION_QUESTION_PLACEHOLDER" = "輸入地址"; +"LOCATION_ERROR_TITLE" = "找不到指定的地址"; +"LOCATION_ERROR_MESSAGE_LOCATION_UNKNOWN" = "無法解析您的目前位置。請輸入地址,或者如果可以,請移至GPS訊號較佳的位置。"; +"LOCATION_ERROR_MESSAGE_DENIED" = "拒絕取用定位服務。請透過「設定」來許可此項App權限使用定位服務。"; +"LOCATION_ERROR_GEOCODE" = "無法找到輸入地址的結果。請確定地址有效。"; +"LOCATION_ERROR_GEOCODE_NETWORK" = "您可能無法連接Internet或是您已超出地址查詢要求的最大數量。若您未連接Internet,請開啟Wi-Fi來回答此問題(如果顯示「略過」按鈕,則略過此問題),或是在您連接Internet之後再返回問卷。否則,請在幾分鐘後重試一次。"; + +/* Alert for exceeding length limit in text answer */ +"TEXT_ANSWER_EXCEEDING_MAX_LENGTH_ALERT_MESSAGE" = "文字內容超過最大長度:%@"; + +/* Camera not available during multitasking */ +"CAMERA_UNAVAILABLE_MESSAGE" = "分割螢幕無法使用相機。"; + +/* Registration step */ +"EMAIL_FORM_ITEM_TITLE" = "電子郵件"; +"EMAIL_FORM_ITEM_PLACEHOLDER" = "jappleseed@example.com"; +"PASSWORD_FORM_ITEM_TITLE" = "密碼"; +"PASSWORD_FORM_ITEM_PLACEHOLDER" = "輸入密碼"; +"CONFIRM_PASSWORD_FORM_ITEM_TITLE" = "確認"; +"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER" = "再次輸入密碼"; +"CONFIRM_PASSWORD_ERROR_MESSAGE" = "密碼不符。"; +"ADDITIONAL_INFO_SECTION_TITLE" = "其他資訊"; +"GIVEN_NAME_ITEM_PLACEHOLDER" = "John"; +"FAMILY_NAME_ITEM_PLACEHOLDER" = "Appleseed"; +"GENDER_FORM_ITEM_TITLE" = "性別"; +"GENDER_FORM_ITEM_PLACEHOLDER" = "選擇性別"; +"DOB_FORM_ITEM_TITLE" = "出生日期"; +"DOB_FORM_ITEM_PLACEHOLDER" = "選擇日期"; +"PHONE_NUMBER_FORM_ITEM_TITLE" = "電話號碼"; +"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER" = "+1 (555) 555 5555"; + +/* Verification step */ +"VERIFICATION_NAV_TITLE" = "驗證"; +"VERIFICATION_STEP_TITLE" = "驗證您的電子郵件"; +"RESEND_EMAIL_LABEL_MESSAGE" = "如果您未收到驗證電子郵件並希望系統再寄送一次,請點下方連結。"; +"RESEND_EMAIL_BUTTON_TITLE" = "重新傳送驗證電子郵件"; + +/* Login step */ +"LOGIN_CONTINUE_BUTTON_TITLE" = "登入"; +"FORGOT_PASSWORD_BUTTON_TITLE" = "忘記密碼?"; + +/* Passcode step */ +"PASSCODE_PROMPT_MESSAGE" = "輸入密碼"; +"PASSCODE_CONFIRM_MESSAGE" = "確認密碼"; +"PASSCODE_SAVED_MESSAGE" = "已儲存密碼"; +"PASSCODE_AUTHENTICATED_MESSAGE" = "已認證密碼"; +"PASSCODE_OLD_ENTRY_MESSAGE" = "輸入舊密碼"; +"PASSCODE_NEW_ENTRY_MESSAGE" = "輸入新密碼"; +"PASSCODE_CONFIRM_NEW_ENTRY_MESSAGE" = "確認您的新密碼"; +"PASSCODE_INVALID_ALERT_TITLE" = "密碼不正確"; +"PASSCODE_INVALID_ALERT_MESSAGE" = "密碼不符。請再試一次。"; +"PASSCODE_TOUCH_ID_MESSAGE" = "請使用Touch ID認證"; +"PASSCODE_TOUCH_ID_ERROR_ALERT_TITLE" = "Touch ID錯誤"; +"PASSCODE_TEXTFIELD_INVALID_INPUT_MESSAGE" = "僅允許數字字元。"; +"PASSCODE_TEXTFIELD_ACCESSIBILITY_LABEL" = "密碼輸入進度指示器"; +"PASSCODE_TEXTFIELD_ACCESSIBILTIY_VALUE" = "已輸入%1$@位數字(共%2$@位)"; +"PASSCODE_FORGOT_BUTTON_TITLE" = "忘記密碼?"; + +/* Keychain wrapper */ +"KEYCHAIN_ADD_ERROR_MESSAGE" = "無法加入鑰匙圈項目。"; +"KEYCHAIN_UPDATE_ERROR_MESSAGE" = "無法升級鑰匙圈項目。"; +"KEYCHAIN_DELETE_ERROR_MESSAGE" = "無法刪除鑰匙圈項目。"; +"KEYCHAIN_FIND_ERROR_MESSAGE" = "無法找到鑰匙圈項目。"; + +/* Blood types */ +"BLOOD_TYPE_A+" = "A+"; +"BLOOD_TYPE_A-" = "A-"; +"BLOOD_TYPE_AB+" = "AB+"; +"BLOOD_TYPE_AB-" = "AB-"; +"BLOOD_TYPE_B+" = "B+"; +"BLOOD_TYPE_B-" = "B-"; +"BLOOD_TYPE_O+" = "O+"; +"BLOOD_TYPE_O-" = "O-"; + +/* Fitzpatrick Skin types */ +"FITZPATRICK_SKIN_TYPE_I" = "類型1"; +"FITZPATRICK_SKIN_TYPE_II" = "類型2"; +"FITZPATRICK_SKIN_TYPE_III" = "類型3"; +"FITZPATRICK_SKIN_TYPE_IV" = "類型4"; +"FITZPATRICK_SKIN_TYPE_V" = "類型5"; +"FITZPATRICK_SKIN_TYPE_VI" = "類型6"; + +/* Gender values. */ +"GENDER_FEMALE" = "女性"; +"GENDER_MALE" = "男性"; +"GENDER_OTHER" = "其他"; + +/* Boolean answer strings */ +"BOOL_NO" = "否"; +"BOOL_YES" = "是"; + +/* Measuring unit abbreviations */ +"MEASURING_UNIT_CM" = "公分"; +"MEASURING_UNIT_FT" = "英尺"; +"MEASURING_UNIT_IN" = "英寸"; +"MEASURING_UNIT_KG" = "公斤"; +"MEASURING_UNIT_LB" = "磅"; +"MEASURING_UNIT_OZ" = "盎司"; + +/* Limb values. */ +"LIMB_LEFT" = "左側"; +"LIMB_RIGHT" = "右側"; + +/* Default placeholders to request answers in a questionnaire. */ +"PLACEHOLDER_TEXT_OR_NUMBER" = "點一下來回答"; +"NULL_ANSWER" = "選取答案"; +"PLACEHOLDER_IMAGE_CHOICES" = "點一下來選取"; +"PLACEHOLDER_LONG_TEXT" = "點一下來寫入"; + +/* Button titles */ +"BUTTON_AGREE" = "同意"; +"BUTTON_CANCEL" = "取消"; +"BUTTON_OK" = "好"; +"BUTTON_CLEAR" = "清除"; +"BUTTON_CLEAR_SIGNATURE" = "清除簽名"; +"BUTTON_APPLY" = "套用"; +"BUTTON_DISAGREE" = "不同意"; +"BUTTON_DONE" = "完成"; +"BUTTON_GET_STARTED" = "開始測試"; +"BUTTON_LEARN_MORE" = "更多內容"; +"BUTTON_NEXT" = "下一步"; +"BUTTON_SKIP" = "略過"; +"BUTTON_SKIP_QUESTION" = "略過此問題"; +"BUTTON_START_TIMER" = "啟動計時器"; +"BUTTON_OPTION_SAVE" = "稍後再試"; +"BUTTON_OPTION_DISCARD" = "捨棄結果"; +"BUTTON_OPTION_STOP_TASK" = "結束任務"; +"BUTTON_SAVE" = "儲存"; +"BUTTON_CLEAR_ANSWER" = "清除答案"; +"BUTTON_READ_ONLY_MODE" = "這個答案無法修改。"; +"BUTTON_COPYRIGHT" = "版權"; +"BUTTON_CLOSE" = "關閉"; + +/* General active tasks. */ +"COUNTDOWN_LABEL" = "準備開始活動:"; +"TASK_COMPLETE_TITLE" = "活動完成"; +"TASK_COMPLETE_TEXT" = "您的資料會經過分析,收到結果時會通知您。"; +"COUNTDOWN_SPOKEN_REMAINING_%@" = "剩餘%@。"; +"TOUCH_ANYWHERE_LABEL" = "觸碰任一處來繼續"; + +/* Image capture step. */ +"CAPTURE_BUTTON_CAPTURE_IMAGE" = "擷取影像"; +"CAPTURE_BUTTON_RECAPTURE_IMAGE" = "重新擷取影像"; +"CAPTURE_ERROR_CAMERA_NOT_FOUND" = "找不到相機。無法完成此步驟。"; +"CAPTURE_ERROR_NO_PERMISSIONS" = "為了完成此步驟,請在「設定」中允許此App取用相機。"; +"CAPTURE_ERROR_NO_OUTPUT_DIRECTORY" = "尚未指定擷取影像的輸出目錄。"; +"CAPTURE_ERROR_CANNOT_WRITE_FILE" = "無法儲存擷取的影像。"; + +/* Video capture step. */ +"CAPTURE_BUTTON_CAPTURE_VIDEO" = "開始錄影"; +"CAPTURE_BUTTON_STOP_CAPTURE_VIDEO" = "停止錄影"; +"CAPTURE_BUTTON_RECAPTURE_VIDEO" = "重新擷取影像"; + +/* Fitness active task. */ +"FITNESS_TASK_TITLE" = "健身"; +"FITNESS_DISTANCE_TITLE_FORMAT" = "距離(%@)"; +"FITNESS_HEARTRATE_TITLE" = "心率(下/分鐘)"; +"FITNESS_SIT_INSTRUCTION_FORMAT" = "輕鬆坐著%@。"; +"FITNESS_WALK_INSTRUCTION_FORMAT" = "以最快的速度步行%@。"; +"FITNESS_INTRO_TEXT_FORMAT" = "此活動會監控您的心率並測量您在%1$@內最快的步行速度。"; +"FITNESS_INTRO_2_TEXT_FORMAT" = "以最快的配速在室外步行%1$@。完成後,請輕鬆坐下並休息%2$@。若要開始,請點一下「開始測試」。"; + +/* Short walk active task. */ +"WALK_TASK_TITLE" = "步態和平衡"; +"WALK_INTRO_TEXT" = "此活動會在您步行和靜止站立時測量您的步態和平衡。若無法獨立地安全步行,請勿繼續。"; +"WALK_INTRO_2_TEXT_%ld" = "請找到一個地方可讓您獨立安全地直線步行%ld步。"; +"WALK_INTRO_2_DETAIL" = "將您的裝置放在口袋或包包並依照語音指示來操作。"; +"WALK_STAND_VOICE_INSTRUCTION_FORMAT" = "現在站著不動%@。"; +"WALK_STAND_INSTRUCTION_FORMAT" = "站著不動%@。"; +"WALK_RETURN_INSTRUCTION_FORMAT" = "請掉頭並走回您的起點。"; +"WALK_OUTBOUND_INSTRUCTION_FORMAT" = "直線步行到最多%ld步。"; + +/* Short walk back and forth. */ +"WALK_INTRO_2_TEXT_BACK_AND_FORTH_INSTRUCTION" = "找一個您可以安全地以直線來回步行的地點。請試著持續走到盡頭再折返,如同繞過交通錐折返。\n\n接著會指示您轉一圈,然後站著不動,雙手自然放鬆,並且雙腳張開與肩同寬。"; +"WALK_INTRO_2_DETAIL_BACK_AND_FORTH_INSTRUCTION" = "當您準備好時,請點一下「開始測試」。\n然後將裝置放在口袋或包包裡面,並依照語音指示執行。"; +"WALK_BACK_AND_FORTH_INSTRUCTION_FORMAT" = "直線來回步行到%@。請以您一般的步調行走。"; +"WALK_BACK_AND_FORTH_STAND_INSTRUCTION_FORMAT" = "旋轉一整圈,然後站著不動%@。"; +"WALK_BACK_AND_FORTH_FINISHED_VOICE" = "您已完成活動。"; + +/* Tapping active task. */ +"TAPPING_TASK_TITLE" = "點按速度"; +"TAPPING_TASK_TITLE_RIGHT" = "右手"; +"TAPPING_TASK_TITLE_LEFT" = "左手"; +"TAPPING_INTRO_TEXT" = "此活動會測量您的點按速度。"; +"TAPPING_INTRO_TEXT_2_REST_PHONE" = "將您的裝置置於平坦的表面上。"; +"TAPPING_INTRO_TEXT_2_MOST_AFFECTED" = "用同一隻手的兩指來交互點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_RIGHT_FIRST" = "用右手的兩指來交互點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_LEFT_FIRST" = "用左手的兩指來交互點按螢幕上的按鈕。"; +"TAPPING_INTRO_TEXT_2_RIGHT_SECOND" = "現在請用右手重複執行相同的測試。"; +"TAPPING_INTRO_TEXT_2_LEFT_SECOND" = "現在請用左手重複執行相同的測試。"; +"TAPPING_INTRO_TEXT_2_FORMAT" = "先用一隻手指點按,再用另一隻手指。請試著讓兩指以平均的速率點按。持續點按%@。"; +"TAPPING_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"TAPPING_CALL_TO_ACTION_NEXT" = "點「下一步」來開始。"; +"TAP_BUTTON_TITLE" = "點一下"; +"TOTAL_TAPS_LABEL" = "總計點按數量"; +"TAPPING_INSTRUCTION" = "用兩指儘可能地以相同的節奏點按按鈕。"; +"TAPPING_INSTRUCTION_RIGHT" = "用「右手」點按按鈕。"; +"TAPPING_INSTRUCTION_LEFT" = "用「左手」點按按鈕。"; +"TAPPING_SKIP_TITLE" = "略過這隻手"; + +/* Amsler Grid Task.*/ +"AMSLER_GRID_TITLE" = "阿姆斯勒方格表"; +"AMSLER_GRID_INTRO_TEXT" = "此活動有助於偵測使用者的視力問題。"; +"AMSLER_GRID_INSTRUCTION_TEXT" = "測試期間,請將裝置放在離臉約30公分遠的距離,且需平視。"; +"AMSLER_GRID_INSTRUCTION_DETAIL_TEXT" = "關閉您的%@並注視方格中央的圓點。\n\n使用手指或筆標出您所看見扭曲的地方,例如模糊或波浪線條。\n\n完成時,請在方格外任意位置向左滑動。"; +"AMSLER_GRID_LEFT_EYE" = "左眼"; +"AMSLER_GRID_RIGHT_EYE" = "右眼"; + +/* Audio active task. */ +"AUDIO_TASK_TITLE" = "聲音"; +"AUDIO_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"AUDIO_INSTRUCTION" = "對著麥克風說「啊」,時間越久越好。"; +"AUDIO_INTRO_TEXT" = "請深呼吸,然後對著麥克風說「啊」,時間越久越好。請保持穩定的音量,讓音訊條顯示為藍色。"; +"AUDIO_INTENDED_USE" = "此活動會用裝置底部的麥克風錄下您的聲音以進行評估。"; +"AUDIO_TOO_LOUD_LABEL" = "太大聲了"; +"AUDIO_GENERIC_ERROR_LABEL" = "無法錄音"; +"AUDIO_LEVEL_CHECK_LABEL" = "我們檢查背景噪音量,請稍候。"; +"AUDIO_TOO_LOUD_MESSAGE" = "周圍的噪音量過高,無法錄下您的聲音。請到較為安靜的位置,並再試一次。"; +"AUDIO_TOO_LOUD_ACTION_NEXT" = "準備好時,請點「下一步」。"; + +/* Tone audiometry active task. */ +"TONE_AUDIOMETRY_TASK_TITLE" = "純音聽力檢查"; +"TONE_AUDIOMETRY_INTENDED_USE" = "此活動會測量您是否能聽到不同種的測試音。"; +"TONE_AUDIOMETRY_INTRO_TEXT" = "在您開始前,請插入並開啟耳機。\n\n聲音十分微細且不像一般的提示聲。開始會發出柔和的聲音,然後慢慢加大音量。請注意聆聽,並且點一下左側或右側的按鈕來表示聽見聲音的那只耳朵。"; +"TONE_AUDIOMETRY_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"TONE_AUDIOMETRY_PREP_TEXT" = "您現在應該可聽到測試音。請使用裝置側邊的控制按鈕來調整音量。\n\n當您準備好開始時,請點任一個按鈕。"; +"TONE_AUDIOMETRY_INSTRUCTION" = "您每次開始聽取聲音時,請點一下左側或右側按鈕來指示聽見聲音的那只耳朵。"; +"TONE_AUDIOMETRY_LABEL_LEFT_EAR" = "左耳"; +"TONE_AUDIOMETRY_LABEL_RIGHT_EAR" = "右耳"; +"TONE_LABEL_%@_LEFT" = "左側,%@赫茲"; +"TONE_LABEL_%@_RIGHT" = "右側,%@赫茲"; + +/* dBHL Tone audiometry active task. */ +"dBHL_TONE_AUDIOMETRY_TASK_TITLE" = "純音聽力檢查"; +"dBHL_TONE_AUDIOMETRY_TASK_TITLE_2" = "聽到聲音時請點一下。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TITLE" = "聲音與音量"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_1" = "您將會聽到一連串的聲音。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_2" = "聽到聲音時,請點一下按鈕。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_3" = "音量在本測試中會設為百分之五十。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_4" = "本測試會花上大約10分鐘的時間。"; +"dBHL_TONE_AUDIOMETRY_BODY_ITEM_TEXT_5" = "開啟「勿擾模式」來避免干擾。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_RIGHT_EAR" = "現在會在您的右耳播放聲音。"; +"dBHL_TONE_AUDIOMETRY_STEP_TITLE_LEFT_EAR" = "現在會在您的左耳播放聲音。"; +"dBHL_TONE_AUDIOMETRY_INTENDED_USE" = "此活動會識別每個人的聽閾線,單位為dB HL量程。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "確定裝置音量已設到最大聲。\n\n此任務期間,會在左耳或右耳播放微弱的音調。\n\n請仔細聆聽,並在每次聽到音調時點一下按鈕。"; +"dBHL_TONE_AUDIOMETRY_INTRO_TEXT_2" = "本測試會辨識音量需要多大才能讓您聽到。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING" = "新手問卷調查。"; +"dBHL_TONE_AUDIOMETRY_ONBOARDING_QUESTION" = "如有需要,請選擇「聽力較好的耳朵」偏好設定"; +"dBHL_TONE_AUDIOMETRY_OPTION_LEFT" = "左側"; +"dBHL_TONE_AUDIOMETRY_OPTION_RIGHT" = "右側"; +"dBHL_TONE_AUDIOMETRY_OPTION_NO_PREFERENCE" = "無偏好"; +"dBHL_ALERT_TITLE_TEST_INTERRUPTED" = "測試已取消"; +"dBHL_ALERT_TITLE_START_OVER" = "重新開始"; +"dBHL_ALERT_TITLE_CANCEL_TEST" = "取消測試"; +"dBHL_ALERT_TEXT" = "重新連接AirPods或EarPods來進行測試。"; +"dBHL_PROGRESS_COMPLETION_%@" = "已完成%@"; + +/* Headphones. */ +"AIRPODS" = "AirPods"; +"EARPODS" = "EarPods"; +"HEADPHONES" = "耳機"; +"HEADPHONES_UNKNOWN" = "未知"; +"HEADPHONES_NONE" = "無"; +"CONNECTED" = "已連線"; +"NOT_CONNECTED" = "未連線"; +"HEADPHONE_CONNECTED_%@" = "已連線 - %@"; +"HEADPHONE_DETECT_TITLE" = "連接您的耳機"; +"HEADPHONE_DETECT_TEXT" = "此測試需要Apple AirPods或Apple EarPods"; + +/* Spatial span memory active task. */ +"SPATIAL_SPAN_MEMORY_TITLE" = "空間記憶"; +"SPATIAL_SPAN_MEMORY_INTRO_TEXT_%@" = "此活動會讓您重複%@亮起來的順序以測量您的短期空間記憶。"; +"SPATIAL_SPAN_MEMORY_TARGET_PLURAL" = "花朵"; +"SPATIAL_SPAN_MEMORY_TARGET_STANDALONE" = "花朵"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_%@" = "部分的%@會一次點亮一個。按照相同的點亮順序點一下這些%@。"; +"SPATIAL_SPAN_MEMORY_INTRO_2_TEXT_REVERSE_%@" = "部分的%@會一次點亮一個。按照相反的點亮順序點一下這些%@。"; +"SPATIAL_SPAN_MEMORY_CALL_TO_ACTION" = "若要開始,請點一下「開始測試」,然後仔細觀看螢幕。"; +"MEMORY_GAME_ITEM_COUNT_TITLE_%@" = "%@"; +"MEMORY_GAME_SCORE_TITLE" = "分數"; +"MEMORY_GAME_PLAYBACK_TITLE_%@" = "觀看%@亮起來"; +"MEMORY_GAME_GAMEPLAY_TITLE_%@" = "以圖片亮起來的順序點一下%@"; +"MEMORY_GAME_GAMEPLAY_REVERSE_TITLE_%@" = "以相反的順序點一下%@"; +"MEMORY_GAME_COMPLETE_TITLE" = "完成順序"; +"MEMORY_GAME_COMPLETE_MESSAGE" = "若要繼續,請點「下一步」"; +"MEMORY_GAME_FAILED_TITLE" = "再試一次"; +"MEMORY_GAME_FAILED_MESSAGE" = "您這次未成功。點「下一步」來繼續。"; +"MEMORY_GAME_TIMEOUT_TITLE" = "時間到了"; +"MEMORY_GAME_TIMEOUT_MESSAGE" = "您的時間用完了。\n點「下一步」來繼續。"; +"MEMORY_GAME_COMPLETE" = "遊戲完成"; +"MEMORY_GAME_PAUSED_TITLE" = "已暫停"; +"MEMORY_GAME_PAUSED_MESSAGE" = "若要繼續,請點「下一步」"; +"MEMORY_GAME_COPYRIGHT_TEXT" = "記憶活動是在加州舊金山大學的Katherine Possin博士和Joel Kramer博士的協助下進行開發。"; + +/* Reaction time active task. */ +"REACTION_TIME_TASK_TITLE" = "反應時間"; +"REACTION_TIME_TASK_INTENDED_USE" = "此活動會評估您對於視覺提示的回應時間。"; +"REACTION_TIME_TASK_INTRO_TEXT_FORMAT" = "看到螢幕上顯示藍色圓點後,請立即往任意方向晃動裝置。您將被要求進行%D次晃動操作。"; +"REACTION_TIME_TASK_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"REACTION_TIME_TASK_ATTEMPTS_FORMAT" = "第%@次(共%@次)"; +"REACTION_TIME_TASK_ACTIVE_STEP_TITLE" = "顯示藍色圓圈時快速晃動裝置"; + +/* Stroop active task.*/ +"STROOP_TASK_TITLE" = "斯特魯普"; +"STROOP_TASK_INTRO1_DETAIL_TEXT" = "每次顯示一組文字時,請選取所顯示的「顏色」名稱的第一個字。"; +"STROOP_TASK_INTRO2_DETAIL_TEXT" = "當您準備好開始「斯特魯普」活動時,請點一下「開始測試」。"; +"STROOP_TASK_STEP_TEXT" = "選取所顯示的「顏色」名稱的第一個字。"; +"STROOP_COLOR_RED" = "紅色"; +"STROOP_COLOR_GREEN" = "綠色"; +"STROOP_COLOR_BLUE" = "藍色"; +"STROOP_COLOR_YELLOW" = "黃色"; +"STROOP_COLOR_RED_INITIAL" = "紅"; +"STROOP_COLOR_GREEN_INITIAL" = "綠"; +"STROOP_COLOR_BLUE_INITIAL" = "藍"; +"STROOP_COLOR_YELLOW_INITIAL" = "黃"; + +/* Tower of Hanoi active task */ +"TOWER_OF_HANOI_TASK_TITLE" = "河內塔"; +"TOWER_OF_HANOI_TASK_INTENDED_USE" = "此活動會評估您的解題能力。"; +"TOWER_OF_HANOI_TASK_INTRO_TEXT" = "以最少的次數將所有圓盤移到有顏色標示的平台。"; +"TOWER_OF_HANOI_TASK_TASK_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_INTRO_TEXT" = "解開謎題"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_PROGRESS_TEXT" = "移動次數:%@ \n %@"; +"TOWER_OF_HANOI_TASK_ACTIVE_STEP_SKIP_BUTTON_TITLE" = "我無法解開此謎題"; + +/* Range of Motion active task */ +"RANGE_OF_MOTION_TITLE" = "活動範圍"; +"LIMB_OPTION_LEFT_OR_RIGHT_ERROR" = "limbOption必須是左側或右側"; + +/* Knee Range of Motion active task */ +"KNEE_RANGE_OF_MOTION_TITLE_LEFT" = "左膝活動範圍"; +"KNEE_RANGE_OF_MOTION_TITLE_RIGHT" = "右膝活動範圍"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "此活動會測量您的左膝伸展程度。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "此活動會測量您的右膝伸展程度。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "坐在椅子邊緣上。開始時,請將裝置放在左膝上來進行測量。請開啟裝置的聲音以便聽取指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "坐在椅子邊緣上。開始時,請將裝置放在右膝上來進行測量。請開啟裝置的聲音以便聽取指示。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "將裝置放在您的左膝上,螢幕朝上(如圖所示)。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "將裝置放在您的右膝上,螢幕朝上(如圖所示)。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "準備好時,點一下螢幕來開始,將您的左膝伸展到最遠的距離。接著返回原本位置並在完成後點一下。"; +"KNEE_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "準備好時,點一下螢幕來開始,將您的右膝伸展到最遠的距離。接著返回原本位置並在完成後點一下。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "將裝置放在您的左膝上。點一下螢幕並將左膝伸展到最遠的距離。"; +"KNEE_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "將裝置放在您的右膝上。點一下螢幕並將右膝伸展到最遠的距離。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成後請將您的左膝放回原本位置。然後點一下任一處。"; +"KNEE_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成後請將您的右膝放回原本位置。然後點一下任一處。"; + +/* Shoulder Range of Motion active task */ +"SHOULDER_RANGE_OF_MOTION_TITLE_LEFT" = "左肩活動範圍"; +"SHOULDER_RANGE_OF_MOTION_TITLE_RIGHT" = "右肩活動範圍"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_LEFT" = "此活動會測量您的左肩伸展程度。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_0_RIGHT" = "此活動會測量您的右肩伸展程度。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_LEFT" = "開始時,請將裝置放在左肩上來進行測量。請開啟裝置的聲音以便聽取指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_1_RIGHT" = "開始時,請將裝置放在右肩上來進行測量。請開啟裝置的聲音以便聽取指示。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_LEFT" = "將裝置放在您的左肩上,螢幕朝上(如圖所示)。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_2_RIGHT" = "將裝置放在您的右肩上,螢幕朝上(如圖所示)。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_LEFT" = "準備好時,點一下螢幕來開始,將您的左手臂伸展到最遠的距離。接著返回原本位置並在完成後點一下。"; +"SHOULDER_RANGE_OF_MOTION_TEXT_INSTRUCTION_3_RIGHT" = "準備好時,點一下螢幕來開始,將您的右手臂伸展到最遠的距離。接著返回原本位置並在完成後點一下。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_LEFT" = "將裝置放在您的左肩上。點一下螢幕並將左手臂伸展到最遠的距離。"; +"SHOULDER_RANGE_OF_MOTION_TOUCH_ANYWHERE_STEP_INSTRUCTION_RIGHT" = "將裝置放在您的右肩上。點一下螢幕並將右手臂伸展到最遠的距離。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_LEFT" = "完成後請將您的左手放回原本位置。然後點一下任一處。"; +"SHOULDER_RANGE_OF_MOTION_SPOKEN_INSTRUCTION_RIGHT" = "完成後請將您的右手放回原本位置。然後點一下任一處。"; + +/* Timed walk active task. */ +"TIMED_WALK_TITLE" = "定時步行"; +"TIMED_WALK_INTRO_DETAIL" = "此活動會測量您的下肢功能。"; +"TIMED_WALK_INTRO_2_TEXT_%@" = "請找到一個地方(最好在室外)可讓您快速安全地直線步行約%@。通過終點線前請勿放慢速度。"; +"TIMED_WALK_INTRO_2_DETAIL" = "點「下一步」來開始。"; +"TIMED_WALK_FORM_TITLE" = "輔具"; +"TIMED_WALK_FORM_TEXT" = "每次測試時請使用相同的輔具。"; +"TIMED_WALK_QUESTION_TEXT" = "您是否穿戴足踝輔具?"; +"TIMED_WALK_QUESTION_2_TITLE" = "您是否使用輔具?"; +"TIMED_WALK_QUESTION_2_TEXT" = "點一下此處來選取答案。"; +"TIMED_WALK_QUESTION_2_CHOICE" = "無"; +"TIMED_WALK_QUESTION_2_CHOICE_2" = "單邊手杖"; +"TIMED_WALK_QUESTION_2_CHOICE_3" = "單邊拐杖"; +"TIMED_WALK_QUESTION_2_CHOICE_4" = "雙邊手杖"; +"TIMED_WALK_QUESTION_2_CHOICE_5" = "雙邊拐杖"; +"TIMED_WALK_QUESTION_2_CHOICE_6" = "助行器/四輪助行器"; +"TIMED_WALK_INSTRUCTION_%@" = "直線步行到最多%@。"; +"TIMED_WALK_INSTRUCTION_TURN" = "轉身。"; +"TIMED_WALK_INSTRUCTION_2" = "請走回您的起點。"; +"TIMED_WALK_INSTRUCTION_TEXT" = "完成時,請點「下一步」。"; + +/* PSAT active task. */ +"PASAT_TITLE" = "PASAT"; +"PVSAT_TITLE" = "PVSAT"; +"PAVSAT_TITLE" = "PAVSAT"; +"PASAT_INTRO_TEXT" = "連續聽覺序列附加測試(PASAT)會測量您的聽覺資訊處理速度和計算能力。"; +"PVSAT_INTRO_TEXT" = "連續視覺序列附加測試(PVSAT)會測量您的視覺資訊處理速度和計算能力。"; +"PAVSAT_INTRO_TEXT" = "連續聽覺序列附加測試(PAVSAT)會測量您的視聽覺資訊處理速度和計算能力。"; +"PSAT_INTRO_TEXT_2_%@" = "每%@秒會顯示單一數字。\n您必須將新的數字與前一個數字相加。\n注意:您不能計算所有的數字總和,只需計算前兩個數字的總和。"; +"PSAT_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"PSAT_INITIAL_INSTRUCTION" = "記住第一個數字。"; +"PSAT_INSTRUCTION" = "將新的數字與前一個數字相加。"; +"PSAT_NO_DIGIT" = "-"; + +/* Hole peg test active task. */ +"HOLE_PEG_TEST_TITLE_%@" = "%@孔圓柱測試"; +"HOLE_PEG_TEST_INTRO_TEXT_%@" = "此活動會要求您將圓柱放入孔中,藉此測量您的上肢功能。將會要求您執行%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_LEFT_HAND_FIRST_%@" = "將會測試您的左手和右手。\n您必須儘快拿起圓柱,將其放入孔中,完成%@次之後,再將圓柱從孔中取出%@次。"; +"HOLE_PEG_TEST_INTRO_TEXT_2_RIGHT_HAND_FIRST_%@" = "將會測試您的右手和左手。\n您必須儘快拿起圓柱,將其放入孔中,完成%@次之後,再將圓柱從孔中取出%@次。"; + +"HOLE_PEG_TEST_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_LEFT_HAND" = "用您的左手將圓柱放入孔中。"; +"HOLE_PEG_TEST_PLACE_INSTRUCTION_RIGHT_HAND" = "用您的右手將圓柱放入孔中。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_LEFT_HAND" = "用您的左手將圓柱放在線的後方。"; +"HOLE_PEG_TEST_REMOVE_INSTRUCTION_RIGHT_HAND" = "用您右手將圓柱放在線的後方。"; +"HOLE_PEG_TEST_TEXT" = "用兩指拿起圓柱。"; +"HOLE_PEG_TEST_TEXT_2" = "抬起手指來放下圓柱。"; + +/* Tremor test active task. */ +"TREMOR_TEST_TITLE" = "顫抖測試活動"; +"TREMOR_TEST_INTRO_1_DETAIL" = "這項活動是測量在不同的姿勢下,您雙手顫抖的情況。請找一個可以讓您舒適坐下的位置,來完成這個活動。"; +"TREMOR_TEST_INTRO_2_DEFAULT_TEXT" = "將電話拿在較受影響的那隻手上,如下方影像所示。"; +"TREMOR_TEST_INTRO_2_RIGHT_HAND_TEXT" = "將電話拿在「右手」,如下方影像所示。"; +"TREMOR_TEST_INTRO_2_LEFT_HAND_TEXT" = "將電話拿在「左手」,如下方影像所示。"; +"TREMOR_TEST_INTRO_2_DETAIL_DEFAULT_%@" = "將會要求您在坐下時用手拿著電話執行%@。"; +"TREMOR_TEST_INTRO_2_DETAIL_1_TASK" = "一項任務"; +"TREMOR_TEST_INTRO_2_DETAIL_2_TASK" = "兩項任務"; +"TREMOR_TEST_INTRO_2_DETAIL_3_TASK" = "三項任務"; +"TREMOR_TEST_INTRO_2_DETAIL_4_TASK" = "四項任務"; +"TREMOR_TEST_INTRO_2_DETAIL_5_TASK" = "五項任務"; +"TREMOR_TEST_ACTIVE_STEP_INTRO_TEXT" = "點「下一步」來繼續。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO" = "請準備將手放在大腿上並拿著電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_LEFT" = "請準備將「左手」放在大腿上並拿著電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INTRO_RIGHT" = "請準備將「右手」放在大腿上並拿著電話。"; +"TREMOR_TEST_ACTIVE_STEP_IN_LAP_INSTRUCTION_%ld" = "請拿著電話並放在大腿上持續%ld秒鐘。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO" = "現在請用手拿著電話,手伸直至與肩同高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_LEFT" = "現在請用「左手」拿著電話,手伸直至與肩同高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INTRO_RIGHT" = "現在請用「右手」拿著電話,手伸直至與肩同高。"; +"TREMOR_TEST_ACTIVE_STEP_EXTEND_ARM_INSTRUCTION_%ld" = "將手伸直,並拿著電話持續%ld秒鐘。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO" = "現在請用手拿著電話,舉至與肩同高時手肘彎曲。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_LEFT" = "現在請用「左手」拿著電話,舉至與肩同高時手肘彎曲。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INTRO_RIGHT" = "現在請用「右手」拿著電話,舉至與肩同高時手肘彎曲。"; +"TREMOR_TEST_ACTIVE_STEP_BEND_ARM_INSTRUCTION_%ld" = "繼續用手拿著電話,手肘彎曲,持續%ld秒鐘"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO" = "現在請將手肘保持彎曲,並重複用電話碰觸鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_LEFT" = "現在請用「左手」拿著電話,手肘保持彎曲,並重複用電話碰觸鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INTRO_RIGHT" = "現在請用「右手」拿著電話,手肘保持彎曲,並重複用電話碰觸鼻子。"; +"TREMOR_TEST_ACTIVE_STEP_TOUCH_NOSE_INSTRUCTION_%ld" = "重複用電話碰觸鼻子持續%ld秒鐘"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO" = "準備執行手腕轉動。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_LEFT" = "準備用「左手」拿著電話執行手腕轉動。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INTRO_RIGHT" = "準備用「右手」拿著電話執行手腕轉動。"; +"TREMOR_TEST_ACTIVE_STEP_TURN_WRIST_INSTRUCTION_%ld" = "繼續執行手腕轉動%ld秒鐘。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_LEFT_INSTRUCTION" = "現在請將電話換到「左手」來繼續下一項任務。"; +"TREMOR_TEST_ACTIVE_STEP_SWITCH_HANDS_RIGHT_INSTRUCTION" = "現在請將電話換到「右手」來繼續下一項任務。"; +"TREMOR_TEST_ACTIVE_STEP_FINISHED_INSTRUCTION" = "繼續下一項任務。"; +"TREMOR_TEST_COMPLETED_INSTRUCTION" = "活動已完成。"; +"TREMOR_TEST_SKIP_QUESTION_BOTH_HANDS_%@" = "將會要求您在坐下時先用一隻手拿著電話執行%@,然後再用另一隻手執行。"; +"TREMOR_SKIP_LEFT_HAND" = "我無法用「左手」執行這項活動。"; +"TREMOR_SKIP_RIGHT_HAND" = "我無法用「右手」執行這項活動。"; +"TREMOR_SKIP_NEITHER" = "我可以用兩隻手執行這項活動。"; + +/* Trail making task. */ +"TRAILMAKING_TASK_TITLE" = "路徑描繪測驗"; +"TRAILMAKING_INTENDED_USE" = "此活動會讓您依序點按一系列的圓點,並記錄您花費的時間,以評估您的視覺注意力和任務切換。"; +"TRAILMAKING_INTENDED_USE2_A" = "倒數之後,以交互順序點一下數字和字母之間的圓點。開始先點第一個數字「1」,接著點數字「2」–「3」–「4」⋯直到數字「7」。"; +"TRAILMAKING_INTENDED_USE2_B" = "倒數之後,以交互順序點一下數字和字母之間的圓點。開始先點第一個數字「1」,再點第一個字母「A」,然後點「2」–「B」–「3」–「C」⋯直到數字「7」。"; +"TRAILMAKING_INTRO_TEXT" = "請用最快的速度完成,不要出錯。"; +"TRAILMAKING_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"TRAILMAKING_LETTER_A" = "A"; +"TRAILMAKING_LETTER_B" = "B"; +"TRAILMAKING_LETTER_C" = "C"; +"TRAILMAKING_LETTER_D" = "D"; +"TRAILMAKING_LETTER_E" = "E"; +"TRAILMAKING_LETTER_F" = "F"; + +/* Touch Ability active task. */ +"TOUCH_ABILITY_INSTRUCTION_TITLE" = "觸控能力測試活動"; +"TOUCH_ABILITY_INSTRUCTION_DETAIL" = "此項活動會測量您的觸控螢幕使用能力。請找一個可以讓您舒適使用本裝置的位置,來完成此項活動。"; +"TOUCH_ABILITY_TAP_TITLE" = "點按能力測驗"; +"TOUCH_ABILITY_TAP_TEXT" = "請點按畫面中出現的方塊,點按後方塊即會消失,請待方塊再次出現再進行下一次點按。"; +"TOUCH_ABILITY_LONG_PRESS_TITLE" = "長按能力測驗"; +"TOUCH_ABILITY_LONG_PRESS_TEXT" = "請長按畫面中出現的方塊,持續至少一秒鐘再抬起。無論是否確實長按至少一秒鐘,當您將手抬起後方塊即會消失,請待方塊再次出現再進行下一次長按。"; +"TOUCH_ABILITY_SWIPE_TITLE" = "掃動能力測驗"; +"TOUCH_ABILITY_SWIPE_TEXT" = "請依畫面中箭頭的方向掃動。當您完成掃動手勢後,箭頭即會消失,請待箭頭再次出現再進行下一次掃動。"; +"TOUCH_ABILITY_VERTICAL_SCROLL_TITLE" = "垂直滾動測驗"; +"TOUCH_ABILITY_VERTICAL_SCROLL_TEXT" = "此項測驗將要求您滾動一個數字列表,請將其中被色彩標記的項目移至虛線方框內。當您將手抬起並且列表停止滾動一秒鐘後,列表和方框即會消失,請待列表再次出現再進行下一次測驗。"; +"TOUCH_ABILITY_HORIZONTAL_SCROLL_TITLE" = "水平滾動測驗"; +"TOUCH_ABILITY_HORIZONTAL_SCROLL_TEXT" = "此項測驗將要求您滾動一個水平的數字列表,請將其中被色彩標記的項目移至虛線方框內。當您將手抬起並且列表停止滾動一秒鐘後,列表和方框即會消失,請待列表再次出現再進行下一次測驗。"; +"TOUCH_ABILITY_PINCH_TITLE" = "兩指縮放測驗"; +"TOUCH_ABILITY_PINCH_TEXT" = "請透過兩指縮放手勢將畫面中的方塊調整至與虛線方框相同大小。當您完成並將手指全數抬起後,方塊和方框即會消失,請待它們重新出現後再進行下一次測驗。"; +"TOUCH_ABILITY_ROTATION_TITLE" = "兩指旋轉測驗"; +"TOUCH_ABILITY_ROTATION_TEXT" = "請透過兩指旋轉手勢將畫面中的箭頭調整至對齊虛線箭頭。當您完成並將手指全數抬起後,箭頭即會消失,請待它們重新出現後再進行下一次測驗。"; + +/* Speech Recognition active task. */ +"SPEECH_TASK_TITLE" = "語音辨識"; +"SPEECH_RECOGNITION_INTRO_TEXT" = "此活動會用裝置底部的麥克風錄下您的語音,並聽寫成文字。"; +"SPEECH_RECOGNITION_CALL_TO_ACTION" = "點一下「開始測試」來開始。"; +"SPEECH_RECOGNITION_INTRO_2_TEXT" = "按下按鈕來開始錄音。"; +"SPEECH_RECOGNITION_START_RECORD_LABEL" = "開始錄音"; +"SPEECH_RECOGNITION_STOP_RECORD_LABEL" = "停止錄音"; +"SPEECH_RECOGNITION_QUESTION_TITLE" = "編輯聽寫記錄"; +"SPEECH_RECOGNITION_QUESTION_TEXT" = "編輯聽寫文字來更正聽寫內容的任何誤解。"; +"SPEECH_RECOGNITION_TRANSCRIPTION_LABEL" = "您的聽寫記錄將顯示於此處。"; +"SPEECH_RECOGNITION_FAILED" = "語音辨識失敗。"; +"SPEECH_RECOGNITION_INIT_FAILURE" = "無法初始化語音辨識。"; + +/* Speech In Noise active task. */ +"SPEECH_IN_NOISE_START_AUDIO_LABEL" = "播放音訊"; +"SPEECH_IN_NOISE_STOP_AUDIO_LABEL" = "停止音訊"; +"SPEECH_IN_NOISE_TITLE" = "噪音中的語音"; +"SPEECH_IN_NOISE_INTRO_TEXT" = "此活動會測量在嘈雜環境中的語音清晰度。"; +"SPEECH_IN_NOISE_DETAIL_TEXT" = "此為本測試的一部分,您將會:\n\n聆聽一句話。\n\n清楚複述一遍您聽到的內容,或是略過到下一頁使用鍵盤輸入您聽到的內容。\n\n若您複述您聽到的內容,將可以選擇修改由語音辨識引擎產生的聽寫記錄。"; +"SPEECH_IN_NOISE_CALIBRATION_TITLE" = "音量校正"; +"SPEECH_IN_NOISE_CALIBRATION_TEXT" = "點一下「播放音訊」,調整至舒適音量,然後點一下「停止音訊」以繼續。"; +"SPEECH_IN_NOISE_STEP_TITLE" = "聆聽"; +"SPEECH_IN_NOISE_STEP_TEXT" = "混有背景雜音的句子會以隨機訊號雜訊比(SNR)只播放一次。"; +"SPEECH_IN_NOISE_SPEAK_TITLE" = "說話"; +"SPEECH_IN_NOISE_SPEAK_TEXT" = "復述您聽到的內容。"; + +/* Potentially user visible error messages. */ +"ERROR_DATALOGGER_CREATE_FILE" = "無法製作檔案"; +"ERROR_DATALOGGER_COULD_NOT_FREE_SPACE" = "無法移除足夠的記錄檔來達到臨界值"; +"ERROR_DATALOGGER_SET_ATTRIBUTE" = "設定屬性時發生錯誤"; +"ERROR_DATALOGGER_COULD_NOT_MAORK" = "檔案未被標示為刪除(或上傳)"; +"ERROR_DATALOGGER_MULTIPLE" = "移除記錄時發生多個錯誤"; +"ERROR_RECORDER_NO_DATA" = "找不到收集的資料。"; +"ERROR_RECORDER_NO_OUTPUT_DIRECTORY" = "尚未指定輸出的目錄"; + +/* Environment SPL*/ +"ENVIRONMENTSPL_TITLE" = "音壓計"; +"ENVIRONMENTSPL_INTRO_TEXT" = "此活動是測量環境音壓位準。如果噪音位準過高便無法繼續。請前往較安靜的地點完成本任務,或稍後重做此活動。"; +"ENVIRONMENTSPL_UNIT" = "dBA"; +"ENVIRONMENTSPL_CALCULATING" = "正在計算"; +"ENVIRONMENTSPL_THRESHOLD" = "閾值:%@ dBA"; +"ENVIRONMENTSPL_OK" = "背景噪音正常"; +"ENVIRONMENTSPL_NOISE" = "太多背景噪音"; +"ENVIRONMENTSPL_TITLE_2" = "尋找一個安靜的地方"; +"ENVIRONMENTSPL_INTRO_TEXT_2" = "為了確保結果準確,此測試必須在安靜的環境下進行。"; + +/* Secondary Task Step*/ +"SECONDARY_TASK_START_BUTTON" = "開始任務"; + +/* Charts */ +"CHART_NO_DATA_TEXT" = "沒有資料"; + +/* Slider */ +"SLIDER_MOVE_SLIDER_FOR_VALUE" = "移動滑桿來輸入數值"; +"SLIDER_I_DONT_KNOW" = "不知道"; + +/* Review Step */ +"REVIEW_STEP_PAGE" = "頁面"; + +/* Accessibility */ +"AX_BUTTON_BACK" = "返回"; +"AX_BUTTON_SHOW_PDF_THUMBNAIL" = "顯示PDF縮覽圖"; +"AX_BUTTON_HIDE_PDF_THUMBNAIL" = "隱藏PDF縮覽圖"; +"AX_BUTTON_ANNOTATE" = "註解"; +"AX_BUTTON_SHOW_SEARCH" = "顯示搜尋列"; +"AX_BUTTON_HIDE_SEARCH" = "隱藏搜尋列"; +"AX_BUTTON_SHARE" = "分享"; + + +"AX_COMPLETION_ILLUSTRATION" = "藍色圓圈中包含勾號的插圖表示成功"; + +"AX_SIGNVIEW_LABEL" = "指定簽名欄位"; +"AX_SIGNVIEW_HINT" = "觸碰螢幕並移動手指來簽名"; +"AX_SIGNVIEW_SIGNED" = "已簽名"; +"AX_SIGNVIEW_UNSIGNED" = "未簽名"; + +"AX_SELECTED" = "已選取"; +"AX_UNSELECTED" = "未選取"; +"AX_SELECT_ALL_THAT_APPLY" = "勾選所有適用的欄位"; + +"AX_SLIDER_LABEL" = "回應滑桿。範圍在%@到%@之間"; +"AX_UNLABELED_IMAGE" = "未標示的影像"; + +"AX_ANNOUNCE_BEGIN_TASK" = "開始任務"; + +"AX.MEMORY.TILE.ACTIVE" = "動態"; +"AX.MEMORY.TILE.CORRECT" = "正確"; +"AX.MEMORY.TILE.INCORRECT" = "不正確"; +"AX.MEMORY.TILE.QUIESCENT" = "靜態"; +"AX.MEMORY.TILE.LABEL" = "記憶遊戲圖塊"; + +"AX_IMAGE_CAPTURE_LABEL" = "擷取預覽"; +"AX_IMAGE_CAPTURED_LABEL" = "擷取的影像"; + +"AX_VIDEO_CAPTURE_LABEL" = "擷取影像預覽"; +"AX_VIDEO_CAPTURE_COMPLETE" = "影片擷取完畢"; + +"AX_TOWER_OF_HANOI_INVALID_MOVE_FORMAT" = "無法將%@號的圓盤放在%@號的圓盤上"; +"AX_TOWER_OF_HANOI_TARGET_DISK" = "目標"; +"AX_TOWER_OF_HANOI_TOWER" = "塔座"; +"AX_TOWER_OF_HANOI_PLACE_DISK" = "點兩下來放置圓盤"; +"AX_TOWER_OF_HANOI_SELECT_DISK" = "點兩下來選取最上方的圓盤"; +"AX_TOWER_OF_HANOI_TOWER_CONTAINS" = "圓盤大小是%@"; +"AX_TOWER_OF_HANOI_TOWER_EMPTY" = "空白"; + +"AX_DISMISS_KEYBOARD_CUSTOM_ACTION" = "關閉鍵盤"; + +"AX_GRAPH_RANGE_FORMAT_%@_%@" = "範圍在%@到%@之間"; +"AX_GRAPH_STACK_PREFIX" = "圓盤組成:"; +"AX_GRAPH_AND_SEPARATOR" = " 和 "; +"AX_GRAPH_POINT_%@" = "點:%@"; + +"AX_SPEECH_RECOGNITION_WAVEFORM" = "語音波形"; +"AX_SPEECH_RECOGNITION_START_RECORDING_HINT" = "錄音開始時,啟用第二次以停止錄音。"; + +"AX_AUDIO_BAR_GRAPH" = "音訊條圖形"; + +"AX_AMSLER_GRID_LABEL" = "阿姆斯勒方格表"; +"AX_AMSLER_GRID_HINT" = "使用手指或筆直接標出格線,或在外側向左滑動以完成。"; + +"AX_TAP_BUTTON_DIRECT_TOUCH_AREA" = "可以點選的按鈕"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_LABEL" = "為左耳點一下"; +"AX_TONE_AUDIOMETRY_BUTTON_LEFT_EAR_HINT" = "啟用來開始測試。測試開始後,若左耳聽到聲音,請直接點一下此按鈕。"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_LABEL" = "為右耳點一下"; +"AX_TONE_AUDIOMETRY_BUTTON_RIGHT_EAR_HINT" = "啟用來開始測試。測試開始後,若右耳聽到聲音,請直接點一下此按鈕。"; +/* This contains the visual text, followed by a VoiceOver-specific description, followed by the visual text on the following page (since VoiceOver users may not have a chance to hear the visual text before needing to perform the actions). */ +"AX_TONE_AUDIOMETRY_PREP_TEXT_VOICEOVER" = "%@使用「旁白」後,透過觸碰並學習雙耳按鈕的所在位置來探索螢幕。測試開始後,按鈕將可以直接點選。%@"; +"AX_TAP_BUTTON_1_LABEL" = "用一根手指點一下"; +"AX_TAP_BUTTON_2_LABEL" = "用另一根手指點一下"; +"AX_TAP_BUTTON_HINT" = "啟用來讓按鈕可以直接點選。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TAPPING_INSTRUCTION_VOICEOVER" = "%@使用「旁白」後,透過觸碰並學習按鈕所在位置來探索螢幕。啟用按鈕或讓按鈕可以直接點選。"; +"AX_TAP_BUTTON_DIRECT_TOUCH_ANNOUNCEMENT" = "按鈕現在可以直接點選。"; +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_dBHL_TONE_AUDIOMETRY_INTRO_TEXT" = "%@使用「旁白」後,按鈕將可以直接點選,其位置將靠近螢幕中心。"; + +/* This contains the visual text, followed by a VoiceOver-specific description. */ +"AX_TRAILMAKING_CALL_TO_ACTION_VOICEOVER" = "%@使用「旁白」後,測試中的按鈕將可以直接點選。"; + +/* Restore error */ +"RESTORE_ERROR_CANNOT_DECODE" = "無法為初始化解碼restoreData"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.stringsdict b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.stringsdict new file mode 100755 index 0000000..7832e16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Localized/zh_TW.lproj/ResearchKit.stringsdict @@ -0,0 +1,22 @@ + + + + + TRAILMAKING_ERROR_FORMAT + + NSStringLocalizedFormatKey + %#@_errors@ + _errors + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + (%d error) + other + (%d個錯誤) + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.h new file mode 100755 index 0000000..5cb4069 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.h @@ -0,0 +1,73 @@ +/* + Copyright (c) 2017, Ricardo Sanchez-Saez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKAnswerFormat.h" +#import "ORKOrderedTask.h" +#import "ORKRegistrationStep.h" +#import "ORKQuestionStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +/** + Deprecated in v2.0 (scheduled for removal). + */ + +@interface ORKQuestionStep (Deprecated) + +/** + Returns a new question step that includes the specified identifier, title, question, and answer format. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param title A localized string that represents the question. + @param answerFormat The format in which the answer is expected. + */ ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + answer:(nullable ORKAnswerFormat *)answerFormat __attribute__((deprecated("Use '-questionStepWithIdentifier:title:question:answer:' instead.","questionStepWithIdentifier"))); + +/** + Returns a new question step that includes the specified identifier, title, question, and answer format. + + @param identifier The identifier of the step (a step identifier should be unique within the task). + @param title A localized string that represents the question. + @param text The primary text shown below the title string. + @param answerFormat The format in which the answer is expected. + */ ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + answer:(nullable ORKAnswerFormat *)answerFormat __attribute__((deprecated("Use '-questionStepWithIdentifier:title:question:answer:' instead.", + "questionStepWithIdentifier"))); + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.m new file mode 100755 index 0000000..d9b8da5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ORKDeprecated.m @@ -0,0 +1,61 @@ +/* + Copyright (c) 2017, Ricardo Sanchez-Saez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKDeprecated.h" + +#import "ORKRegistrationStep_Internal.h" + + +@implementation ORKQuestionStep (Deprecated) + ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(NSString *)title + answer:(ORKAnswerFormat *)answer { + + ORKQuestionStep *step = [[ORKQuestionStep alloc] initWithIdentifier:identifier]; + step.question = title; + step.answerFormat = answer; + return step; +} + ++ (instancetype)questionStepWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + answer:(nullable ORKAnswerFormat *)answerFormat { + + ORKQuestionStep *step = [[ORKQuestionStep alloc] initWithIdentifier:identifier]; + step.question = title; + step.text = text; + step.answerFormat = answerFormat; + return step; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.h new file mode 100755 index 0000000..deffb78 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.h @@ -0,0 +1,86 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + Constants for the form items included in the login step. + These allow for convenient retrieval of user's inputted data from the result. + */ +ORK_EXTERN NSString *const ORKLoginFormItemIdentifierEmail ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKLoginFormItemIdentifierPassword ORK_AVAILABLE_DECL; + + +/** + The `ORKLoginStep` class represents a form step that provides fields commonly used + for account login. + + The login step contains email and password fields. + */ +ORK_CLASS_AVAILABLE +@interface ORKLoginStep : ORKFormStep + +- (instancetype)initWithIdentifier:(NSString *)identifier NS_UNAVAILABLE; + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text NS_UNAVAILABLE; + +/** + Returns an initialized login step using the specified identifier, title, text, and options. + + @param identifier The string that identifies the step (see `ORKStep`). + @param title The title of the form (see `ORKStep`). + @param text The text shown immediately below the title (see `ORKStep`). + @param loginViewControllerClass The subclassed login step view controller class. + + @return An initialized login step object. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + loginViewControllerClass:(Class)loginViewControllerClass; + +/** + The view controller subclass used for the step. + + The subclass allows you to override button actions in order to provide navigation logic + for the button items on the step. + */ +@property (nonatomic, readonly) Class loginViewControllerClass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.m new file mode 100755 index 0000000..b0cbd50 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep.m @@ -0,0 +1,165 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLoginStep.h" +#import "ORKLoginStep_Internal.h" + +#import "ORKLoginStepViewController.h" + +#import "ORKAnswerFormat.h" +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +NSString *const ORKLoginFormItemIdentifierEmail = @"ORKLoginFormItemEmail"; +NSString *const ORKLoginFormItemIdentifierPassword = @"ORKLoginFormItemPassword"; + +@implementation ORKLoginStep + +- (Class)stepViewControllerClass { + return self.loginViewControllerClass; +} + +// Don't throw on -initWithIdentifier: because it's internally used by -copyWithZone: + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text { + ORKThrowMethodUnavailableException(); +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(NSString *)title + text:(NSString *)text + loginViewControllerClass:(Class)loginViewControllerClass { + + NSParameterAssert([loginViewControllerClass isSubclassOfClass:[ORKLoginStepViewController class]]); + + self = [super initWithIdentifier:identifier title:title text:text]; + if (self) { + _loginViewControllerString = NSStringFromClass(loginViewControllerClass); + self.formItems = [self loginFormItems]; + self.showsProgress = NO; + + [self validateParameters]; + } + return self; +} + +- (NSArray *)loginFormItems { + NSMutableArray *formItems = [NSMutableArray new]; + + { + ORKEmailAnswerFormat *answerFormat = [ORKAnswerFormat emailAnswerFormat]; + answerFormat.usernameField = YES; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKLoginFormItemIdentifierEmail + text:ORKLocalizedString(@"EMAIL_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"EMAIL_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.secureTextEntry = YES; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + answerFormat.textContentType = UITextContentTypePassword; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKLoginFormItemIdentifierPassword + text:ORKLocalizedString(@"PASSWORD_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"PASSWORD_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + return formItems; +} + +- (Class)loginViewControllerClass { + return NSClassFromString(_loginViewControllerString); +} + +- (void)validateParameters { + [super validateParameters]; + + if (!_loginViewControllerString || !NSClassFromString(_loginViewControllerString)) { + @throw [NSException exceptionWithName:NSGenericException + reason:@"Unable to find ORKLoginStepViewController subclass." + userInfo:nil]; + } +} + +- (BOOL)isOptional { + // This is necessary because the skip button is used as a `Forgot password?` button. + return YES; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, loginViewControllerString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, loginViewControllerString); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKLoginStep *step = [super copyWithZone:zone]; + step->_loginViewControllerString = [self.loginViewControllerString copy]; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.loginViewControllerString, castObject.loginViewControllerString)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.h new file mode 100755 index 0000000..eb35117 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.h @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKLoginStepViewController` class is the concrete `ORKStepViewController` + implementation for `ORKLoginStep`. + + You should subclass a login step view controller and override the button action + methods to provide your navigation logic. All override methods are required. + */ +ORK_CLASS_AVAILABLE +@interface ORKLoginStepViewController : ORKFormStepViewController + +/** + Action method for the forgot password button. + + The forgot password button is shown in place of the skip button. + Override this method to provide custom logic for the button action. + */ +- (void)forgotPasswordButtonTapped; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.m new file mode 100755 index 0000000..82edc1d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStepViewController.m @@ -0,0 +1,81 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLoginStepViewController.h" + +#import "ORKFormStepViewController_Internal.h" +#import "ORKStepViewController_Internal.h" +#import "ORKTaskViewController.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKLoginStepViewController + +- (void)setContinueButtonItem:(UIBarButtonItem *)continueButtonItem { + [super setContinueButtonItem:continueButtonItem]; + continueButtonItem.title = ORKLocalizedString(@"LOGIN_CONTINUE_BUTTON_TITLE", nil); +} + +- (void)setSkipButtonItem:(UIBarButtonItem *)skipButtonItem { + [super setSkipButtonItem:skipButtonItem]; + + [skipButtonItem setTitle:ORKLocalizedString(@"FORGOT_PASSWORD_BUTTON_TITLE", nil)]; + [skipButtonItem setTarget:self]; + [skipButtonItem setAction:@selector(forgotPasswordButtonHandler:)]; +} + +- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem { + [super setCancelButtonItem:cancelButtonItem]; + [cancelButtonItem setTarget:self]; + [cancelButtonItem setAction:@selector(cancelButtonHandler:)]; +} + +- (void)cancelButtonHandler:(id)sender { + ORKStrongTypeOf(self.taskViewController.delegate) strongDelegate = self.taskViewController.delegate; + if ([strongDelegate respondsToSelector:@selector(taskViewController:didFinishWithReason:error:)]) { + [strongDelegate taskViewController:self.taskViewController didFinishWithReason:ORKTaskViewControllerFinishReasonDiscarded error:nil]; + } +} + +- (void)forgotPasswordButtonHandler:(id)sender{ + [self forgotPasswordButtonTapped]; +} + +#pragma mark Override methods + +- (void)forgotPasswordButtonTapped { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] + userInfo:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep_Internal.h new file mode 100755 index 0000000..ff4b390 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKLoginStep_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKLoginStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKLoginStep () + +@property (nonatomic, copy, readonly) NSString *loginViewControllerString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.h new file mode 100755 index 0000000..c839888 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.h @@ -0,0 +1,176 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKRegistrationStepOption` flags let you include particular fields in addition + to the default fields (email and password) in the registration step. + */ +typedef NS_OPTIONS(NSUInteger, ORKRegistrationStepOption) { + /// Default behavior. + ORKRegistrationStepDefault = 0, + + /// Include the given name field. + ORKRegistrationStepIncludeGivenName = (1 << 1), + + /// Include the family name field. + ORKRegistrationStepIncludeFamilyName = (1 << 2), + + /// Include the gender field. + ORKRegistrationStepIncludeGender = (1 << 3), + + /// Include the date of birth field. + ORKRegistrationStepIncludeDOB = (1 << 4), + + /// Include the user phone number. + ORKRegistrationStepIncludePhoneNumber = (1 << 5) +} ORK_ENUM_AVAILABLE; + + +/** + Constants for the form items included in the registration step. + These allow for convenient retrieval of user's inputted data from the result. + */ +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierEmail ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierPassword ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierGivenName ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierFamilyName ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierGender ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierDOB ORK_AVAILABLE_DECL; +ORK_EXTERN NSString *const ORKRegistrationFormItemIdentifierPhoneNumber ORK_AVAILABLE_DECL; + + +/** + The `ORKRegistrationStep` class represents a form step that provides fields commonly used + for account registration. + + The registration step contains email and password fields by default. Optionally, any + of the additional fields can be included based on context and requirements. + */ +ORK_CLASS_AVAILABLE +@interface ORKRegistrationStep : ORKFormStep + +/** + Returns an initialized registration step using the specified identifier, + title, text, options, passcodeValidationRegularExpression, and passcodeInvalidMessage. + + @param identifier The string that identifies the step (see `ORKStep`). + @param title The title of the form (see `ORKStep`). + @param text The text shown immediately below the title (see `ORKStep`). + @param passcodeValidationRegularExpression The regular expression used to validate the passcode form item (see `ORKTextAnswerFormat`). + @param passcodeInvalidMessage The invalid message displayed for invalid input (see `ORKTextAnswerFormat`). + @param options The options used for the step (see `ORKRegistrationStepOption`). + + @return An initialized registration step object. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text +passcodeValidationRegularExpression:(nullable NSRegularExpression *)passcodeValidationRegularExpression + passcodeInvalidMessage:(nullable NSString *)passcodeInvalidMessage + options:(ORKRegistrationStepOption)options; + +/** + Returns an initialized registration step using the specified identifier, + title, text, and options. + + @param identifier The string that identifies the step (see `ORKStep`). + @param title The title of the form (see `ORKStep`). + @param text The text shown immediately below the title (see `ORKStep`). + @param options The options used for the step (see `ORKRegistrationStepOption`). + + @return An initialized registration step object. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(nullable NSString *)title + text:(nullable NSString *)text + options:(ORKRegistrationStepOption)options; + +/** + The options used for the step. + + These options allow one or more fields to be included in the registration step. + */ +@property (nonatomic, readonly) ORKRegistrationStepOption options; + +/** + The regular expression used to validate the passcode form item. + This is a transparent property pointing to its definition in `ORKTextAnswerFormat`. + + The passcode invalid message property must also be set along with this property. + By default, there is no validation on the passcode. + */ +@property (nonatomic, copy, nullable) NSRegularExpression *passcodeValidationRegularExpression; + +/** + The invalid message displayed if the passcode does not match the validation regular expression. + This is a transparent property pointing to its definition in `ORKTextAnswerFormat`. + + The passcode validation regular expression property must also be set along with this property. + By default, there is no invalid message. + */ +@property (nonatomic, copy, nullable) NSString *passcodeInvalidMessage; + +/** + The password generation rules to use for Automatic Secure Passwords. + + If specified, overrides the default passsword generation rules for fields with secureTextEntry. + The `passcodeRules` should match the `passcodeValidationRegularExpression` or else a passcode + may be generated that fails validation. + */ +@property (nonatomic, nullable) UITextInputPasswordRules *passcodeRules API_AVAILABLE(ios(12.0)); + +/** + The regular expression used to validate the phone number form item. + This is a transparent property pointing to its definition in `ORKTextAnswerFormat`. + + The phone number invalid message property must also be set along with this property. + By default, there is no validation on the phone number. + */ +@property (nonatomic, copy, nullable) NSRegularExpression *phoneNumberValidationRegularExpression; + +/** + The invalid message displayed if the phone number does not match the validation regular expression. + This is a transparent property pointing to its definition in `ORKTextAnswerFormat`. + + The phone number validation regular expression property must also be set along with this property. + By default, there is no invalid message. + */ +@property (nonatomic, copy, nullable) NSString *phoneNumberInvalidMessage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.m new file mode 100755 index 0000000..40423ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep.m @@ -0,0 +1,372 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRegistrationStep.h" + +#import "ORKAnswerFormat_Private.h" + +#import "ORKHelpers_Internal.h" + + +NSString *const ORKRegistrationFormItemIdentifierEmail = @"ORKRegistrationFormItemEmail"; +NSString *const ORKRegistrationFormItemIdentifierPassword = @"ORKRegistrationFormItemPassword"; +NSString *const ORKRegistrationFormItemIdentifierConfirmPassword = @"ORKRegistrationFormItemConfirmPassword"; +NSString *const ORKRegistrationFormItemIdentifierGivenName = @"ORKRegistrationFormItemGivenName"; +NSString *const ORKRegistrationFormItemIdentifierFamilyName = @"ORKRegistrationFormItemFamilyName"; +NSString *const ORKRegistrationFormItemIdentifierGender = @"ORKRegistrationFormItemGender"; +NSString *const ORKRegistrationFormItemIdentifierDOB = @"ORKRegistrationFormItemDOB"; +NSString *const ORKRegistrationFormItemIdentifierPhoneNumber = @"ORKRegistrationFormItemPhoneNumber"; + +static _Nullable id ORKFindInArrayByFormItemId(NSArray *array, NSString *formItemIdentifier) { + return ORKFindInArrayByKey(array, @"identifier", formItemIdentifier); +} + +static NSArray *ORKRegistrationFormItems(ORKRegistrationStepOption options) { + NSMutableArray *formItems = [NSMutableArray new]; + + { + ORKEmailAnswerFormat *answerFormat = [ORKAnswerFormat emailAnswerFormat]; + answerFormat.usernameField = YES; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierEmail + text:ORKLocalizedString(@"EMAIL_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"EMAIL_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + ORKFormItem *passwordFormItem; + { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.secureTextEntry = YES; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + + if (@available(iOS 12.0, *)) { + answerFormat.textContentType = UITextContentTypeNewPassword; + } else { + answerFormat.textContentType = UITextContentTypePassword; + } + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierPassword + text:ORKLocalizedString(@"PASSWORD_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"PASSWORD_FORM_ITEM_PLACEHOLDER", nil); + passwordFormItem = item; + + [formItems addObject:item]; + } + + { + ORKFormItem *item = [passwordFormItem confirmationAnswerFormItemWithIdentifier:ORKRegistrationFormItemIdentifierConfirmPassword + text:ORKLocalizedString(@"CONFIRM_PASSWORD_FORM_ITEM_TITLE", nil) + errorMessage:ORKLocalizedString(@"CONFIRM_PASSWORD_ERROR_MESSAGE", nil)]; + item.placeholder = ORKLocalizedString(@"CONFIRM_PASSWORD_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + if (options & (ORKRegistrationStepIncludeFamilyName | ORKRegistrationStepIncludeGivenName | ORKRegistrationStepIncludeDOB | ORKRegistrationStepIncludeGender | ORKRegistrationStepIncludePhoneNumber)) { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:ORKLocalizedString(@"ADDITIONAL_INFO_SECTION_TITLE", nil)]; + + [formItems addObject:item]; + } + + if (options & ORKRegistrationStepIncludeGivenName) { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.textContentType = UITextContentTypeGivenName; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierGivenName + text:ORKLocalizedString(@"CONSENT_NAME_GIVEN", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"GIVEN_NAME_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + if (options & ORKRegistrationStepIncludeFamilyName) { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.textContentType = UITextContentTypeFamilyName; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierFamilyName + text:ORKLocalizedString(@"CONSENT_NAME_FAMILY", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"FAMILY_NAME_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + // Adjust order of given name and family name form item cells based on current locale. + if ((options & ORKRegistrationStepIncludeGivenName) && (options & ORKRegistrationStepIncludeFamilyName)) { + if (ORKCurrentLocalePresentsFamilyNameFirst()) { + ORKFormItem *givenNameFormItem = ORKFindInArrayByFormItemId(formItems, ORKRegistrationFormItemIdentifierGivenName); + ORKFormItem *familyNameFormItem = ORKFindInArrayByFormItemId(formItems, ORKRegistrationFormItemIdentifierFamilyName); + [formItems exchangeObjectAtIndex:[formItems indexOfObject:givenNameFormItem] + withObjectAtIndex:[formItems indexOfObject:familyNameFormItem]]; + } + } + + if (options & ORKRegistrationStepIncludeGender) { + NSArray *textChoices = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_FEMALE", nil) value:@"female"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_MALE", nil) value:@"male"], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_OTHER", nil) value:@"other"]]; + ORKValuePickerAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierGender + text:ORKLocalizedString(@"GENDER_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"GENDER_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + if (options & ORKRegistrationStepIncludeDOB) { + // Calculate default date (20 years from now). + NSDate *defaultDate = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] dateByAddingUnit:NSCalendarUnitYear + value:-20 + toDate:[NSDate date] + options:(NSCalendarOptions)0]; + + ORKDateAnswerFormat *answerFormat = [ORKAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate + minimumDate:nil + maximumDate:[NSDate date] + calendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]]; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierDOB + text:ORKLocalizedString(@"DOB_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"DOB_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + if (options & ORKRegistrationStepIncludePhoneNumber) { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + answerFormat.keyboardType = UIKeyboardTypeNumbersAndPunctuation; + answerFormat.textContentType = UITextContentTypeTelephoneNumber; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierPhoneNumber + text:ORKLocalizedString(@"PHONE_NUMBER_FORM_ITEM_TITLE", nil) + answerFormat:answerFormat + optional:NO]; + item.placeholder = ORKLocalizedString(@"PHONE_NUMBER_FORM_ITEM_PLACEHOLDER", nil); + + [formItems addObject:item]; + } + + return formItems; +} + + +@implementation ORKRegistrationStep + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(NSString *)title + text:(NSString *)text +passcodeValidationRegularExpression:(NSRegularExpression *)passcodeValidationRegularExpression + passcodeInvalidMessage:(NSString *)passcodeInvalidMessage + options:(ORKRegistrationStepOption)options { + self = [super initWithIdentifier:identifier title:title text:text]; + if (self) { + _options = options; + self.passcodeValidationRegularExpression = passcodeValidationRegularExpression; + self.passcodeInvalidMessage = passcodeInvalidMessage; + self.optional = NO; + } + return self; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(NSString *)title + text:(NSString *)text + options:(ORKRegistrationStepOption)options { + return [self initWithIdentifier:identifier + title:title + text:text +passcodeValidationRegularExpression:nil + passcodeInvalidMessage:nil + options:options]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier + title:(NSString *)title + text:(NSString *)text { + return [self initWithIdentifier:identifier + title:title + text:text + options:ORKRegistrationStepDefault]; +} + +- (instancetype)initWithIdentifier:(NSString *)identifier { + return [self initWithIdentifier:identifier + title:nil + text:nil]; +} + +- (ORKTextAnswerFormat *)passwordAnswerFormat { + ORKFormItem *passwordFormItem = ORKFindInArrayByFormItemId(self.formItems, ORKRegistrationFormItemIdentifierPassword); + ORKTextAnswerFormat *passwordAnswerFormat = (ORKTextAnswerFormat *)passwordFormItem.answerFormat; + return passwordAnswerFormat; +} + +- (ORKTextAnswerFormat *)phoneNumberAnswerFormat { + ORKFormItem *phoneNumberFormItem = ORKFindInArrayByFormItemId(self.formItems, ORKRegistrationFormItemIdentifierPhoneNumber); + ORKTextAnswerFormat *phoneNumberAnswerFormat = (ORKTextAnswerFormat *)phoneNumberFormItem.answerFormat; + return phoneNumberAnswerFormat; +} + +- (NSArray *)formItems { + if (![super formItems]) { + self.formItems = ORKRegistrationFormItems(_options); + } + + ORKFormItem *dobFormItem = ORKFindInArrayByFormItemId([super formItems], ORKRegistrationFormItemIdentifierDOB); + ORKDateAnswerFormat *originalAnswerFormat = (ORKDateAnswerFormat *)dobFormItem.answerFormat; + ORKDateAnswerFormat *modifiedAnswerFormat = [ORKAnswerFormat dateAnswerFormatWithDefaultDate:originalAnswerFormat.defaultDate + minimumDate:originalAnswerFormat.minimumDate + maximumDate:[NSDate date] + calendar:originalAnswerFormat.calendar]; + + dobFormItem = [[ORKFormItem alloc] initWithIdentifier:ORKRegistrationFormItemIdentifierDOB + text:ORKLocalizedString(@"DOB_FORM_ITEM_TITLE", nil) + answerFormat:modifiedAnswerFormat + optional:NO]; + dobFormItem.placeholder = ORKLocalizedString(@"DOB_FORM_ITEM_PLACEHOLDER", nil); + + return [super formItems]; +} + +- (NSRegularExpression *)passcodeValidationRegularExpression { + return [self passwordAnswerFormat].validationRegularExpression; +} + +- (void)setPasscodeValidationRegularExpression:(NSRegularExpression *)passcodeValidationRegularExpression { + [self passwordAnswerFormat].validationRegularExpression = passcodeValidationRegularExpression; +} + +- (NSString *)passcodeInvalidMessage { + return [self passwordAnswerFormat].invalidMessage; +} + +- (void)setPasscodeInvalidMessage:(NSString *)passcodeInvalidMessage { + [self passwordAnswerFormat].invalidMessage = passcodeInvalidMessage; +} + +- (UITextInputPasswordRules *)passcodeRules { + return [self passwordAnswerFormat].passwordRules; +} + +- (void)setPasscodeRules:(UITextInputPasswordRules *)passcodeRules { + [self passwordAnswerFormat].passwordRules = passcodeRules; +} + +- (NSRegularExpression *)phoneNumberValidationRegularExpression { + return [self phoneNumberAnswerFormat].validationRegularExpression; +} + +- (void)setPhoneNumberValidationRegularExpression:(NSRegularExpression *)phoneNumberValidationRegularExpression { + [self phoneNumberAnswerFormat].validationRegularExpression = phoneNumberValidationRegularExpression; +} + +- (NSString *)phoneNumberInvalidMessage { + return [self phoneNumberAnswerFormat].invalidMessage; +} + +- (void)setPhoneNumberInvalidMessage:(NSString *)phoneNumberInvalidMessage { + [self phoneNumberAnswerFormat].invalidMessage = phoneNumberInvalidMessage; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + + // `passcodeValidationRegularExpression`, `passcodeInvalidMessage`, + // `phoneNumberValidationRegularExpression`, and `phoneNumberInvalidMessage` are transparent + // properties. The corresponding decoding for these properties takes place in the answer + // format's `-initWithCode:` method, invoked from super's (ORKFormStep) implementation. + ORK_DECODE_INTEGER(aDecoder, options); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + + // `passcodeValidationRegularExpression`, `passcodeInvalidMessage`, + // `phoneNumberValidationRegularExpression`, and `phoneNumberInvalidMessage` are transparent + // properties. The corresponding encoding for these properties takes place in the answer format's + // `-encodeWithCoder:` method, invoked from super's (ORKFormStep) implementation. + ORK_ENCODE_INTEGER(aCoder, options); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKRegistrationStep *step = [super copyWithZone:zone]; + + // `passcodeValidationRegularExpression`, `passcodeInvalidMessage`, + // `phoneNumberValidationRegularExpression`, and `phoneNumberInvalidMessage` are transparent + // properties. The corresponding copying of these properties happens in the answer format + // `-copyWithZone:` method, invoked from the super's (ORKFormStep) implementation. + step->_options = self.options; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + // `passcodeValidationRegularExpression`, `passcodeInvalidMessage`, + // `phoneNumberValidationRegularExpression`, and `phoneNumberInvalidMessage` are transparent + // properties. The corresponding equality test for these properties takes place in the answer + // format's `-isEqual:` method, invoked from super's (ORKFormStep) implementation. + __typeof(self) castObject = object; + return (isParentSame && + self.options == castObject.options); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep_Internal.h new file mode 100755 index 0000000..544de16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKRegistrationStep_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKRegistrationStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKRegistrationStep () + +- (ORKTextAnswerFormat *)passwordAnswerFormat; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.h new file mode 100755 index 0000000..455f0f4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.h @@ -0,0 +1,78 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKVerificationStep` class represents a step that serves as placeholder + step to use while the user attempts to verify their account. + + The verification step contains a text field and a resend email button. The button + actions must be overriden inside a subclassed verification view controller to provide + navigation logic. + + The developer should redirect user back to the app once the verification is done + and move forward automatically. + */ +ORK_CLASS_AVAILABLE +@interface ORKVerificationStep : ORKStep + +- (instancetype)initWithIdentifier:(NSString *)identifier NS_UNAVAILABLE; + +/** + Returns an initialized verification step using the specified identifier, + title, text, and class. + + @param identifier The string that identifies the step (see `ORKStep`). + @param text The text shown immediately below the title (see `ORKStep`). + @param verificationViewControllerClass The subclassed verification view controller class. + + @return An initialized verification step object. + */ +- (instancetype)initWithIdentifier:(NSString *)identifier + text:(nullable NSString *)text + verificationViewControllerClass:(Class)verificationViewControllerClass; + +/** + The view controller subclass used for the step. + + The subclass allows you to override button actions in order to provide navigation logic + for the button items on the step. + */ +@property (nonatomic, readonly) Class verificationViewControllerClass; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.m new file mode 100755 index 0000000..444571d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep.m @@ -0,0 +1,117 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerificationStep.h" +#import "ORKVerificationStep_Internal.h" + +#import "ORKVerificationStepViewController.h" + +#import "ORKStep_Private.h" + +#import "ORKHelpers_Internal.h" + + +@implementation ORKVerificationStep + +- (Class)stepViewControllerClass { + return self.verificationViewControllerClass; +} + +// Don't throw on -initWithIdentifier: because it's internally used by -copyWithZone: + +- (instancetype)initWithIdentifier:(NSString *)identifier + text:(NSString *)text + verificationViewControllerClass:(Class)verificationViewControllerClass { + + NSParameterAssert([verificationViewControllerClass isSubclassOfClass:[ORKVerificationStepViewController class]]); + + self = [super initWithIdentifier:identifier]; + if (self) { + self.title = ORKLocalizedString(@"VERIFICATION_STEP_TITLE", nil); + self.text = text; + self.showsProgress = NO; + _verificationViewControllerString = NSStringFromClass(verificationViewControllerClass); + + [self validateParameters]; + } + return self; +} + +- (Class)verificationViewControllerClass { + return NSClassFromString(_verificationViewControllerString); +} + +- (void)validateParameters { + [super validateParameters]; + + if (!_verificationViewControllerString || !NSClassFromString(_verificationViewControllerString)) { + @throw [NSException exceptionWithName:NSGenericException + reason:@"Unable to find ORKVerificationStepViewController subclass." + userInfo:nil]; + } +} + +- (BOOL)allowsBackNavigation { + return NO; +} + ++ (BOOL)supportsSecureCoding { + return YES; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + ORK_DECODE_OBJ(aDecoder, verificationViewControllerString); + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + ORK_ENCODE_OBJ(aCoder, verificationViewControllerString); +} + +- (instancetype)copyWithZone:(NSZone *)zone { + ORKVerificationStep *step = [super copyWithZone:zone]; + step->_verificationViewControllerString = [self.verificationViewControllerString copy]; + return step; +} + +- (BOOL)isEqual:(id)object { + BOOL isParentSame = [super isEqual:object]; + + __typeof(self) castObject = object; + return (isParentSame && + ORKEqualObjects(self.verificationViewControllerString, castObject.verificationViewControllerString)); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.h new file mode 100755 index 0000000..33a1904 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import "ORKVerticalContainerView.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVerificationStepView : ORKVerticalContainerView + +@property (nonatomic, strong, readonly) UIButton *resendEmailButton; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.m new file mode 100755 index 0000000..5e941d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepView.m @@ -0,0 +1,102 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerificationStepView.h" + +#import "ORKStepHeaderView_Internal.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + + +@implementation ORKVerificationStepView + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + + self.stepView = [UIView new]; + self.stepView.translatesAutoresizingMaskIntoConstraints = NO; + + _resendEmailButton = [UIButton new]; + [_resendEmailButton setTitle:ORKLocalizedString(@"RESEND_EMAIL_BUTTON_TITLE", nil) forState:UIControlStateNormal]; + [_resendEmailButton setTitleColor:self.tintColor forState:UIControlStateNormal]; + [self.stepView addSubview:_resendEmailButton]; + + [self setUpConstraints]; + + } + return self; +} + +- (void)setUpConstraints { + NSMutableArray *constraints = [NSMutableArray new]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_resendEmailButton); + ORKEnableAutoLayoutForViews(views.allValues); + const CGFloat textBaselineToResendButtonBaselineMetric = ORKGetMetricForWindow(ORKScreenMetricVerificationTextBaselineToResendButtonBaseline, self.window); + + [constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_resendEmailButton + attribute:NSLayoutAttributeFirstBaseline + relatedBy:NSLayoutRelationEqual + toItem:self.headerView.instructionLabel + attribute:NSLayoutAttributeLastBaseline + multiplier:1.0 + constant:textBaselineToResendButtonBaselineMetric], + [NSLayoutConstraint constraintWithItem:_resendEmailButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.stepView + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0] + ]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_resendEmailButton]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_resendEmailButton]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +- (void)tintColorDidChange { + [super tintColorDidChange]; + [_resendEmailButton setTitleColor:self.tintColor forState:UIControlStateNormal]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.h new file mode 100755 index 0000000..e3f1948 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.h @@ -0,0 +1,57 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +#import + + +NS_ASSUME_NONNULL_BEGIN + +/** + The `ORKVerificationStepViewController` class is the concrete `ORKStepViewController` + implementation for `ORKVerificationStep`. + + You should subclass a verification step view controller and override the button action + methods to provide your navigation logic. All override methods are required. + */ +ORK_CLASS_AVAILABLE +@interface ORKVerificationStepViewController : ORKStepViewController + +/** + Action method for the resend email button. + + Override this method to provide custom logic for the button action. + */ +- (void)resendEmailButtonTapped; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.m new file mode 100755 index 0000000..29e35fd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStepViewController.m @@ -0,0 +1,134 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerificationStepViewController.h" + +#import "ORKStepHeaderView_Internal.h" +#import "ORKVerificationStepView.h" + +#import "ORKStepViewController_Internal.h" + +#import "ORKVerificationStep.h" + +#import "ORKHelpers_Internal.h" +#import "ORKSkin.h" + +@implementation ORKVerificationStepViewController { + ORKVerificationStepView *_verificationStepView; + NSArray *_constraints; + UIView *_iPadContentView; +} + +- (ORKVerificationStep *)verificationStep { + return (ORKVerificationStep *)self.step; +} + +- (void)stepDidChange { + [super stepDidChange]; + + if (self.step && [self isViewLoaded]) { + self.navigationItem.title = ORKLocalizedString(@"VERIFICATION_NAV_TITLE", nil); + + _verificationStepView = [ORKVerificationStepView new]; + _verificationStepView.headerView.instructionLabel.text = [[self verificationStep].text stringByAppendingString:[NSString stringWithFormat:@"\n\n%@", ORKLocalizedString(@"RESEND_EMAIL_LABEL_MESSAGE", nil)]]; + + _iPadContentView = [self viewForiPadLayoutConstraints]; + if (_iPadContentView) { + [_iPadContentView addSubview:_verificationStepView]; + } + else { + [self.view addSubview:_verificationStepView]; + } + + [_verificationStepView.resendEmailButton addTarget:self + action:@selector(resendEmailButtonHandler:) + forControlEvents:UIControlEventTouchUpInside]; + } +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + } + _verificationStepView.translatesAutoresizingMaskIntoConstraints = NO; + + _constraints = @[ + [NSLayoutConstraint constraintWithItem:_verificationStepView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:_iPadContentView ? : self.view + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_verificationStepView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:_iPadContentView ? : self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_verificationStepView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:_iPadContentView ? : self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_verificationStepView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:_iPadContentView ? : self.view + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + ]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self stepDidChange]; + [self setupConstraints]; +} + +- (void)resendEmailButtonHandler:(id)sender { + [self resendEmailButtonTapped]; +} + +#pragma mark Override methods + +- (void)resendEmailButtonTapped { + @throw [NSException exceptionWithName:NSInvalidArgumentException + reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] + userInfo:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep_Internal.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep_Internal.h new file mode 100755 index 0000000..bb70852 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/Onboarding/ORKVerificationStep_Internal.h @@ -0,0 +1,43 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKVerificationStep.h" + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKVerificationStep () + +@property (nonatomic, copy, readonly) NSString *verificationViewControllerString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.h new file mode 100755 index 0000000..4bf2f05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.h @@ -0,0 +1,139 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import + +#import +#import +#import + +#import + +#import +#import +#import +#import +#import + +#import +#import + +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.modulemap b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.modulemap new file mode 100755 index 0000000..8818f1c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit.modulemap @@ -0,0 +1,11 @@ +framework module ResearchKit { + umbrella header "ResearchKit.h" + + module Private { + umbrella header "ResearchKit_Private.h" + export * + } + + export * + module * { export * } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit_Private.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit_Private.h new file mode 100755 index 0000000..bbbe055 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKit/ResearchKit_Private.h @@ -0,0 +1,179 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import + +#import +#import + +// Active step support +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import + +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +// For custom steps +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import +#import +#import +#import + +#import +#import +#import +#import +#import + +#import +#import diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/Info.plist new file mode 100755 index 0000000..ba72822 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAccessibilityTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAccessibilityTests.m new file mode 100755 index 0000000..b8128c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAccessibilityTests.m @@ -0,0 +1,60 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +#import "ORKAccessibilityFunctions.h" + + +@interface ORKAccessibilityTests : XCTestCase + +@end + + +@implementation ORKAccessibilityTests + +- (void)testAccessibilityString { + { + NSString *result = ORKAccessibilityStringForVariables(@"a", @"b", nil); + XCTAssert([result isEqualToString:@"a, b"]); + } + + { + NSString *result = ORKAccessibilityStringForVariables(@"a", nil, @"b"); + XCTAssert([result isEqualToString:@"a, b"]); + } + + { + NSString *result = ORKAccessibilityStringForVariables(@"a"); + XCTAssert([result isEqualToString:@"a"]); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveStepTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveStepTests.swift new file mode 100755 index 0000000..b5154f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveStepTests.swift @@ -0,0 +1,118 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import XCTest +@testable import ResearchKit + +class ORKActiveStepTests: XCTestCase { + + var activeStepTest: ORKActiveStep! + + override func setUp() { + super.setUp() + activeStepTest = ORKActiveStep(identifier: "Test") + } + + func testIdentifier() { + XCTAssert(activeStepTest.identifier == "Test") + } + + func testStartsFinished() { + activeStepTest.stepDuration = -1 + XCTAssertFalse(activeStepTest.startsFinished()) + + activeStepTest.stepDuration = 2 + XCTAssertFalse(activeStepTest.startsFinished()) + + activeStepTest.stepDuration = 0 + XCTAssert(activeStepTest.startsFinished()) + } + + func testHasCountdown() { + // stepDuration > 0 && shouldShowDefaultTimer = true -> true + activeStepTest.shouldShowDefaultTimer = true + activeStepTest.stepDuration = -1 + XCTAssertFalse(activeStepTest.hasCountDown()) + + activeStepTest.stepDuration = 0 + XCTAssertFalse(activeStepTest.hasCountDown()) + + activeStepTest.stepDuration = 1 + activeStepTest.shouldShowDefaultTimer = false + XCTAssertFalse(activeStepTest.hasCountDown()) + + activeStepTest.shouldShowDefaultTimer = true + XCTAssert(activeStepTest.hasCountDown()) + } + + func testHasTitle() { + activeStepTest.title = "" + XCTAssertFalse(activeStepTest.hasTitle()) + + activeStepTest.title = nil + XCTAssertFalse(activeStepTest.hasTitle()) + + activeStepTest.title = "This should work" + XCTAssert(activeStepTest.hasTitle()) + } + + func testHasText() { + activeStepTest.text = "" + XCTAssertFalse(activeStepTest.hasText()) + + activeStepTest.text = nil + XCTAssertFalse(activeStepTest.hasText()) + + activeStepTest.text = "THIS SHOULD WORK" + XCTAssert(activeStepTest.hasText()) + } + + func testHasVoice() { + + activeStepTest.spokenInstruction = nil + XCTAssertFalse(activeStepTest.hasVoice()) + + activeStepTest.spokenInstruction = "" + XCTAssertFalse(activeStepTest.hasVoice()) + + activeStepTest.spokenInstruction = "Do jumping jacks" + activeStepTest.finishedSpokenInstruction = nil + XCTAssert(activeStepTest.hasVoice()) + + activeStepTest.spokenInstruction = nil + activeStepTest.finishedSpokenInstruction = "" + XCTAssertFalse(activeStepTest.hasVoice()) + + activeStepTest.finishedSpokenInstruction = "Good job" + XCTAssert(activeStepTest.hasVoice()) + + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveTaskResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveTaskResultTests.swift new file mode 100755 index 0000000..b620089 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKActiveTaskResultTests.swift @@ -0,0 +1,640 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +@testable import ResearchKit + +class ORKAmslerGridResultTests: XCTestCase { + var result: ORKAmslerGridResult! + var identifier: String! + var image: UIImage! + var path: UIBezierPath! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + let bundle = Bundle(identifier: "org.researchkit.ResearchKit") + image = UIImage(named: "amslerGrid", in: bundle, compatibleWith: nil) + path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 50, height: 50)) + result = ORKAmslerGridResult(identifier: identifier, image: image, path: [path], eyeSide: .left) + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.image, image) + XCTAssertEqual(result.path, [path]) + XCTAssertEqual(result.eyeSide, ORKAmslerGridEyeSide.left) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKAmslerGridResult(identifier: identifier, image: image, path: [path], eyeSide: .left) + newResult.startDate = date + newResult.endDate = date + XCTAssert(result.isEqual(newResult)) + } +} + + +class ORKHolePegTestResultTests: XCTestCase { + var result: ORKHolePegTestResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKHolePegTestResult(identifier: identifier) + + result.movingDirection = ORKBodySagittal(rawValue: 2)! + result.isDominantHandTested = true + result.numberOfPegs = 2 + result.threshold = 2.0 + result.isRotated = false + result.totalSuccesses = 10 + result.totalFailures = 5 + result.totalTime = 5.0 + result.totalDistance = 10.0 + result.samples = [2, 4] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.movingDirection, ORKBodySagittal(rawValue: 2)) + XCTAssertEqual(result.isDominantHandTested, true) + XCTAssertEqual(result.numberOfPegs, 2) + XCTAssertEqual(result.threshold, 2.0) + XCTAssertEqual(result.isRotated, false) + XCTAssertEqual(result.totalSuccesses, 10) + XCTAssertEqual(result.totalFailures, 5) + XCTAssertEqual(result.totalTime, 5.0) + XCTAssertEqual(result.totalDistance, 10.0) + guard let samples = result.samples as? [Int] else { + XCTFail("unable to cast samples array to array of int") + return + } + XCTAssertEqual(samples, [2, 4]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKHolePegTestResult(identifier: identifier) + newResult.movingDirection = .left + newResult.isDominantHandTested = true + newResult.numberOfPegs = 5 + newResult.movingDirection = ORKBodySagittal(rawValue: 2)! + newResult.isDominantHandTested = true + newResult.numberOfPegs = 2 + newResult.threshold = 2.0 + newResult.isRotated = false + newResult.totalSuccesses = 10 + newResult.totalFailures = 5 + newResult.totalTime = 5.0 + newResult.totalDistance = 10.0 + newResult.samples = [2, 4] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKPSATResultTests: XCTestCase { + var result: ORKPSATResult! + var identifier: String! + var sample: ORKPSATSample! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "TESTS" + result = ORKPSATResult(identifier: identifier) + + result.presentationMode = .auditory + result.interStimulusInterval = 2 + result.stimulusDuration = 3 + result.length = 4 + result.totalCorrect = 5 + result.totalDyad = 2 + result.totalTime = 20 + result.initialDigit = 20 + sample = ORKPSATSample() + sample.answer = 20 + result.samples = [sample] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.presentationMode, ORKPSATPresentationMode.auditory) + XCTAssertEqual(result.interStimulusInterval, 2) + XCTAssertEqual(result.stimulusDuration, 3) + XCTAssertEqual(result.length, 4) + XCTAssertEqual(result.totalCorrect, 5) + XCTAssertEqual(result.totalDyad, 2) + XCTAssertEqual(result.totalTime, 20) + XCTAssertEqual(result.initialDigit, 20) + XCTAssertEqual(result.samples, [sample]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKPSATResult(identifier: identifier) + newResult.presentationMode = .auditory + newResult.interStimulusInterval = 2 + newResult.stimulusDuration = 3 + newResult.length = 4 + newResult.totalCorrect = 5 + newResult.totalDyad = 2 + newResult.totalTime = 20 + newResult.initialDigit = 20 + newResult.samples = [sample] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKRangeOfMotionResultTests: XCTestCase { + var result: ORKRangeOfMotionResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKRangeOfMotionResult(identifier: identifier) + + result.start = 0 + result.finish = 50 + result.minimum = 10 + result.maximum = 50 + result.range = 10 + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.start, 0) + XCTAssertEqual(result.finish, 50) + XCTAssertEqual(result.minimum, 10) + XCTAssertEqual(result.maximum, 50) + XCTAssertEqual(result.range, 10) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKRangeOfMotionResult(identifier: identifier) + newResult.start = 0 + newResult.finish = 50 + newResult.minimum = 10 + newResult.maximum = 50 + newResult.range = 10 + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKReactionTimeResultTests: XCTestCase { + var result: ORKReactionTimeResult! + var identifier: String! + var fileResult: ORKFileResult! + var url: URL! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKReactionTimeResult(identifier: identifier) + + result.timestamp = 10 + fileResult = ORKFileResult() + url = URL(fileURLWithPath: "FILEURL") + fileResult.fileURL = url + result.fileResult = fileResult + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.timestamp, 10) + XCTAssertEqual(result.fileResult, fileResult) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKReactionTimeResult(identifier: identifier) + newResult.timestamp = 10 + newResult.fileResult = fileResult + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKSpatialSpanMemoryResultTests: XCTestCase { + var result: ORKSpatialSpanMemoryResult! + var identifier: String! + var gameRecord: ORKSpatialSpanMemoryGameRecord! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKSpatialSpanMemoryResult(identifier: identifier) + + result.score = 0 + result.numberOfGames = 20 + result.numberOfFailures = 20 + gameRecord = ORKSpatialSpanMemoryGameRecord() + gameRecord.score = 10 + result.gameRecords = [gameRecord] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.score, 0) + XCTAssertEqual(result.numberOfGames, 20) + XCTAssertEqual(result.numberOfFailures, 20) + XCTAssertEqual(result.gameRecords, [gameRecord]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKSpatialSpanMemoryResult(identifier: identifier) + newResult.score = 0 + newResult.numberOfGames = 20 + newResult.numberOfFailures = 20 + newResult.gameRecords = [gameRecord] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKSpeechRecognitionResultTests: XCTestCase { + var result: ORKSpeechRecognitionResult! + var identifier: String! + var transcription: SFTranscription! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "Result" + result = ORKSpeechRecognitionResult(identifier: identifier) + + transcription = SFTranscription() + result.transcription = transcription + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.transcription, transcription) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKSpeechRecognitionResult(identifier: identifier) + newResult.transcription = transcription + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKStroopResultTests: XCTestCase { + var result: ORKStroopResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKStroopResult(identifier: identifier) + + result.startTime = 0 + result.endTime = 100 + result.color = "BLUE" + result.text = "TEXT" + result.colorSelected = "RED" + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.startTime, 0) + XCTAssertEqual(result.endTime, 100) + XCTAssertEqual(result.color, "BLUE") + XCTAssertEqual(result.text, "TEXT") + XCTAssertEqual(result.colorSelected, "RED") + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKStroopResult(identifier: identifier) + newResult.startTime = 0 + newResult.endTime = 100 + newResult.color = "BLUE" + newResult.text = "TEXT" + newResult.colorSelected = "RED" + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKTappingIntervalResultTests: XCTestCase { + var result: ORKTappingIntervalResult! + var identifier: String! + var sample: ORKTappingSample! + var stepViewSize: CGSize! + var buttonRect1: CGRect! + var buttonRect2: CGRect! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKTappingIntervalResult(identifier: identifier) + + sample = ORKTappingSample() + sample.duration = 20 + stepViewSize = CGSize(width: 50, height: 50) + buttonRect1 = CGRect(x: 0, y: 0, width: 50, height: 50) + buttonRect2 = CGRect(x: 100, y: 100, width: 50, height: 50) + result.samples = [sample] + result.stepViewSize = stepViewSize + result.buttonRect1 = buttonRect1 + result.buttonRect2 = buttonRect2 + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.samples, [sample]) + XCTAssertEqual(result.stepViewSize, stepViewSize) + XCTAssertEqual(result.buttonRect1, buttonRect1) + XCTAssertEqual(result.buttonRect2, buttonRect2) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKTappingIntervalResult(identifier: identifier) + newResult.samples = [sample] + newResult.stepViewSize = stepViewSize + newResult.buttonRect1 = buttonRect1 + newResult.buttonRect2 = buttonRect2 + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKTimedWalkResultTests: XCTestCase { + var result: ORKTimedWalkResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKTimedWalkResult(identifier: identifier) + + result.distanceInMeters = 100 + result.timeLimit = 100 + result.duration = 20 + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.distanceInMeters, 100) + XCTAssertEqual(result.timeLimit, 100) + XCTAssertEqual(result.duration, 20) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKTimedWalkResult(identifier: identifier) + newResult.distanceInMeters = 100 + newResult.timeLimit = 100 + newResult.duration = 20 + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKToneAudiometryResultTests: XCTestCase { + var result: ORKToneAudiometryResult! + var identifier: String! + var sample: ORKToneAudiometrySample! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKToneAudiometryResult(identifier: identifier) + + result.outputVolume = 100 + sample = ORKToneAudiometrySample() + sample.amplitude = 100 + sample.frequency = 100 + result.samples = [sample] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.outputVolume, 100) + XCTAssertEqual(result.samples, [sample]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKToneAudiometryResult(identifier: identifier) + newResult.outputVolume = 100 + newResult.samples = [sample] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKdBHLToneAudiometryResultTests: XCTestCase { + var result: ORKdBHLToneAudiometryResult! + var identifier: String! + var sample: ORKdBHLToneAudiometryFrequencySample! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKdBHLToneAudiometryResult(identifier: identifier) + + result.outputVolume = 100 + result.tonePlaybackDuration = 360 + result.postStimulusDelay = 10 + result.headphoneType = ORKHeadphoneTypeIdentifier.airPods + sample = ORKdBHLToneAudiometryFrequencySample() + sample.frequency = 100 + result.samples = [sample] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.outputVolume, 100) + XCTAssertEqual(result.tonePlaybackDuration, 360) + XCTAssertEqual(result.postStimulusDelay, 10) + XCTAssertEqual(result.headphoneType, ORKHeadphoneTypeIdentifier.airPods) + XCTAssertEqual(result.samples, [sample]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKdBHLToneAudiometryResult(identifier: identifier) + newResult.outputVolume = 100 + newResult.tonePlaybackDuration = 360 + newResult.postStimulusDelay = 10 + newResult.headphoneType = ORKHeadphoneTypeIdentifier.airPods + newResult.samples = [sample] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKTowerOfHanoiResultTests: XCTestCase { + var result: ORKTowerOfHanoiResult! + var identifier: String! + var moveOne: ORKTowerOfHanoiMove! + var moveTwo: ORKTowerOfHanoiMove! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKTowerOfHanoiResult(identifier: identifier) + + result.puzzleWasSolved = false + moveOne = ORKTowerOfHanoiMove() + moveOne.donorTowerIndex = 0 + moveOne.recipientTowerIndex = 1 + moveTwo = ORKTowerOfHanoiMove() + moveTwo.donorTowerIndex = 4 + moveTwo.recipientTowerIndex = 2 + result.moves = [moveOne, moveTwo] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.puzzleWasSolved, false) + XCTAssertEqual(result.moves, [moveOne, moveTwo]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKTowerOfHanoiResult(identifier: identifier) + newResult.startDate = date + newResult.endDate = date + newResult.puzzleWasSolved = false + newResult.moves = [moveOne, moveTwo] + XCTAssert(result.isEqual(newResult)) + } +} + +class ORKTrailmakingResultTests: XCTestCase { + + var result: ORKTrailmakingResult! + var identifier: String! + var tap: ORKTrailmakingTap! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKTrailmakingResult(identifier: identifier) + + tap = ORKTrailmakingTap() + tap.incorrect = false + result.taps = [tap] + result.numberOfErrors = 1 + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.taps, [tap]) + XCTAssertEqual(result.numberOfErrors, 1) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKTrailmakingResult(identifier: identifier) + newResult.startDate = date + newResult.endDate = date + newResult.taps = [tap] + newResult.numberOfErrors = 1 + + XCTAssert(result.isEqual(newResult)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAnswerFormatTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAnswerFormatTests.m new file mode 100755 index 0000000..1808555 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKAnswerFormatTests.m @@ -0,0 +1,737 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKAnswerFormatTests : XCTestCase + +@end + +@protocol ORKComfirmAnswerFormat_Private + +@property (nonatomic, copy, readonly) NSString *originalItemIdentifier; +@property (nonatomic, copy, readonly) NSString *errorMessage; + +@end + + +@implementation ORKAnswerFormatTests + +- (void)testValidEmailAnswerFormat { + // Test email regular expression validation with correct input. + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone@researchkit.org"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some.one@researchkit.org"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone@researchkit.org.uk"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some_one@researchkit.org"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"some-one@researchkit.org"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"someone1@researchkit.org"]); + XCTAssert([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"Someone1@ResearchKit.org"]); +} + +- (void)testInvalidEmailAnswerFormat { + // Test email regular expression validation with incorrect input. + XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest"]); + XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@"]); + XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@researchkit"]); + XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"emailtest@.org"]); + XCTAssertFalse([[ORKEmailAnswerFormat emailAnswerFormat] isAnswerValidWithString:@"12345"]); +} + +- (void)testInvalidRegularExpressionAnswerFormat { + + // Setup an answer format + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.keyboardType = UIKeyboardTypeASCIICapable; + NSRegularExpression *validationRegularExpression = + [NSRegularExpression regularExpressionWithPattern:@"^[A-F,0-9]+$" + options:(NSRegularExpressionOptions)0 + error:nil]; + answerFormat.validationRegularExpression = validationRegularExpression; + answerFormat.invalidMessage = @"Only hexidecimal values in uppercase letters are accepted."; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters; + XCTAssertFalse([answerFormat isAnswerValidWithString:@"Q2"]); + XCTAssertFalse([answerFormat isAnswerValidWithString:@"abcd"]); + XCTAssertTrue([answerFormat isAnswerValidWithString:@"ABCD1234FFED0987654321"]); +} + +- (void)testConfirmAnswerFormat { + + // Setup an answer format + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.secureTextEntry = YES; + answerFormat.keyboardType = UIKeyboardTypeASCIICapable; + if (@available(iOS 12.0, *)) { + answerFormat.textContentType = UITextContentTypeNewPassword; + } else { + answerFormat.textContentType = UITextContentTypePassword; + } + answerFormat.maximumLength = 12; + NSRegularExpression *validationRegularExpression = + [NSRegularExpression regularExpressionWithPattern:@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[$@$!%*?&])[A-Za-z\\d$@$!%*?&]{10,}" + options:(NSRegularExpressionOptions)0 + error:nil]; + answerFormat.validationRegularExpression = validationRegularExpression; + answerFormat.invalidMessage = @"Invalid password"; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters; + + // Note: setting these up incorrectly for a password to test that the values are *not* copied. + // DO NOT setup a real password field with these options. + answerFormat.autocorrectionType = UITextAutocorrectionTypeDefault; + answerFormat.spellCheckingType = UITextSpellCheckingTypeDefault; + + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:NO]; + + // -- method under test + ORKFormItem *confirmItem = [item confirmationAnswerFormItemWithIdentifier:@"bar" + text:@"enter again" + errorMessage:@"doesn't match"]; + + XCTAssertEqualObjects(confirmItem.identifier, @"bar"); + XCTAssertEqualObjects(confirmItem.text, @"enter again"); + XCTAssertFalse(confirmItem.optional); + + // Inspect the answer format + ORKAnswerFormat *confirmFormat = confirmItem.answerFormat; + + // ORKAnswerFormat that is returned should be a subclass of ORKTextAnswerFormat. + // The actual subclass that is returned is private to the API and should not be accessed directly. + XCTAssertNotNil(confirmFormat); + XCTAssertTrue([confirmFormat isKindOfClass:[ORKTextAnswerFormat class]]); + if (![confirmFormat isKindOfClass:[ORKTextAnswerFormat class]]) { return; } + + ORKTextAnswerFormat *confirmAnswer = (ORKTextAnswerFormat*)confirmFormat; + + // These properties should match the original format + XCTAssertFalse(confirmAnswer.multipleLines); + XCTAssertTrue(confirmAnswer.secureTextEntry); + XCTAssertEqual(confirmAnswer.keyboardType, UIKeyboardTypeASCIICapable); + if (@available(iOS 12.0, *)) { + XCTAssertEqual(confirmAnswer.textContentType, UITextContentTypeNewPassword); + } else { + XCTAssertEqual(confirmAnswer.textContentType, UITextContentTypePassword); + } + XCTAssertEqual(confirmAnswer.maximumLength, 12); + + // This property should match the input answer format so that cases that + // require all-upper or all-lower (for whatever reason) can be met. + XCTAssertEqual(confirmAnswer.autocapitalizationType, UITextAutocapitalizationTypeAllCharacters); + + // These properties should always be set to not autocorrect + XCTAssertEqual(confirmAnswer.autocorrectionType, UITextAutocorrectionTypeNo); + XCTAssertEqual(confirmAnswer.spellCheckingType, UITextSpellCheckingTypeNo); + + // These properties should be nil + XCTAssertNil(confirmAnswer.validationRegularExpression); + XCTAssertNil(confirmAnswer.invalidMessage); + + // Check that the confirmation answer format responds to the internal methods + XCTAssertTrue([confirmFormat respondsToSelector:@selector(originalItemIdentifier)]); + XCTAssertTrue([confirmFormat respondsToSelector:@selector(errorMessage)]); + if (![confirmFormat respondsToSelector:@selector(originalItemIdentifier)] || + ![confirmFormat respondsToSelector:@selector(errorMessage)]) { + return; + } + + NSString *originalItemIdentifier = [(id)confirmFormat originalItemIdentifier]; + XCTAssertEqualObjects(originalItemIdentifier, @"foo"); + + NSString *errorMessage = [(id)confirmFormat errorMessage]; + XCTAssertEqualObjects(errorMessage, @"doesn't match"); + +} + +- (void)testConfirmAnswerFormat_Optional_YES { + + // Setup an answer format + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:YES]; + + // -- method under test + ORKFormItem *confirmItem = [item confirmationAnswerFormItemWithIdentifier:@"bar" + text:@"enter again" + errorMessage:@"doesn't match"]; + + // Check that the confirm item optional value matches the input item + XCTAssertTrue(confirmItem.optional); + +} + +- (void)testConfirmAnswerFormat_MultipleLines_YES { + + // Setup an answer format + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = YES; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"foo" text:@"enter value" answerFormat:answerFormat optional:YES]; + + // -- method under test + XCTAssertThrows([item confirmationAnswerFormItemWithIdentifier:@"bar" + text:@"enter again" + errorMessage:@"doesn't match"]); + +} + +- (void)testContinuousScaleAnswerFormat { + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:100 + defaultValue:10 + maximumFractionDigits:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max < min"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10001 + minimumValue:100 + defaultValue:10 + maximumFractionDigits:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max > effectiveUpperBound"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:100 + minimumValue:-10001 + defaultValue:10 + maximumFractionDigits:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since min < effectiveLowerBound"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:100 + defaultValue:10 + maximumFractionDigits:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], NSException, NSInvalidArgumentException, @"Shoud throw NSInvalidArgumentException since max < min"); + + + ORKContinuousScaleAnswerFormat *answerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:1 + minimumValue:0 + defaultValue:10 + maximumFractionDigits:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL]; + + XCTAssertEqual([answerFormat maximum], 1); + XCTAssertEqual([answerFormat minimum], 0); + XCTAssertEqual([answerFormat defaultValue], 10); + XCTAssertEqual([answerFormat maximumFractionDigits], 4, @"Should return 4 since the maximumFractionDigits needs to 0 <= maximumFractionDigits <= 4"); + XCTAssertEqual([answerFormat isVertical], YES); + XCTAssertEqual([answerFormat maximumValueDescription], NULL); + XCTAssertEqual([answerFormat minimumValueDescription], NULL); + + ORKContinuousScaleAnswerFormat *answerFormatTwo = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:1 + minimumValue:0 + defaultValue:10 + maximumFractionDigits:-1 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL]; + + XCTAssertEqual([answerFormatTwo maximumFractionDigits], 0, @"Should return 0 since the maximumFractionDigits needs to 0 <= maximumFractionDigits <= 4"); + +} + +- (void)testScaleAnswerFormat { + + ORKScaleAnswerFormat *answerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100 + minimumValue:0 + defaultValue:10 + step:10 + vertical:YES + maximumValueDescription:@"MAX" + minimumValueDescription:@"MIN"]; + + XCTAssertEqual([answerFormat maximum], 100); + XCTAssertEqual([answerFormat minimum], 0); + XCTAssertEqual([answerFormat defaultValue], 10); + XCTAssertEqual([answerFormat step], 10); + XCTAssertEqual([answerFormat isVertical], YES); + XCTAssertEqual([answerFormat maximumValueDescription], @"MAX"); + XCTAssertEqual([answerFormat minimumValueDescription], @"MIN"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:25 + minimumValue:50 + defaultValue:10 + step:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since max < min"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100 + minimumValue:10 + defaultValue:200 + step:0 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step < 1"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100 + minimumValue:0 + defaultValue:10 + step:3 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step is not divisible by the difference of max and min"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:25 + minimumValue:-20000 + defaultValue:10 + step:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since min < -10000"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:20000 + minimumValue:0 + defaultValue:10 + step:10 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since max > 10000"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100 + minimumValue:0 + defaultValue:10 + step:1 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step count > 13"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat scaleAnswerFormatWithMaximumValue:100 + minimumValue:100 + defaultValue:10 + step:1 + vertical:YES + maximumValueDescription:NULL + minimumValueDescription:NULL], + NSException, NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step count < 1"); + +} + +- (void)testTextScaleAnswerFormat { + + ORKTextChoice *choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value:[NSNumber numberWithInteger:1]]; + ORKTextChoice *choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value:[NSNumber numberWithInteger:2]]; + NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil]; + ORKTextScaleAnswerFormat *answerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:choices defaultIndex:0 vertical:YES]; + + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] value],[NSNumber numberWithInteger:1]); + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value],[NSNumber numberWithInteger:2]); + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] text], @"Choice One"); + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] text], @"Choice Two"); + XCTAssertEqual([answerFormat defaultIndex], 0); + XCTAssertEqual([answerFormat isVertical], YES); + +} + +- (void)testTimeOfDayAnswerFormat { + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.month = 01; + dateComponents.day = 24; + dateComponents.year = 1984; + + ORKTimeOfDayAnswerFormat *answerFormat = [ORKAnswerFormat timeOfDayAnswerFormatWithDefaultComponents:dateComponents]; + + XCTAssertEqual([[answerFormat defaultComponents] month], 01); + XCTAssertEqual([[answerFormat defaultComponents] day], 24); + XCTAssertEqual([[answerFormat defaultComponents] year], 1984); +} + +- (void)testNumericAnswerFormat { + + ORKNumericAnswerFormat *answerFormatWithIntegerStyle = [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger + unit:@"Units" + minimum:[NSNumber numberWithInteger:0] + maximum:[NSNumber numberWithInteger:100] + maximumFractionDigits:@(0)]; + + XCTAssertEqual([answerFormatWithIntegerStyle style], ORKNumericAnswerStyleInteger); + XCTAssertEqual([answerFormatWithIntegerStyle unit], @"Units"); + XCTAssertEqual([answerFormatWithIntegerStyle minimum], [NSNumber numberWithInteger:0]); + XCTAssertEqual([answerFormatWithIntegerStyle maximum], [NSNumber numberWithInteger:100]); + XCTAssertEqual([answerFormatWithIntegerStyle maximumFractionDigits], @(0)); + + + ORKNumericAnswerFormat *answerFormatWithDecimalStyle = [[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal]; + XCTAssertEqual([answerFormatWithDecimalStyle style ], ORKNumericAnswerStyleDecimal); + + XCTAssertThrowsSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger + unit:@"Integers" + minimum:[NSNumber numberWithInteger:100] + maximum:[NSNumber numberWithInteger:0]], NSException, NSInvalidArgumentException, @"Should throw NSInvalidArgumentException since max < min"); + + + XCTAssertThrowsSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleDecimal + unit:@"Doubles" + minimum:[NSNumber numberWithDouble:10.2] + maximum:[NSNumber numberWithDouble:10]], NSException, NSInvalidArgumentException, @"Should throw NSInvalidArgumentException since max < min"); + + XCTAssertNoThrowSpecificNamed([[ORKNumericAnswerFormat alloc] initWithStyle:ORKNumericAnswerStyleInteger + unit:@"Integers" + minimum:NULL + maximum:NULL], + NSException, NSInvalidArgumentException, + @"Should not throw exception for null values"); +} + +- (void)testBooleanAnswerFormat { + ORKBooleanAnswerFormat *answerFormat = [ORKAnswerFormat booleanAnswerFormatWithYesString:@"YES" noString:@"NO"]; + XCTAssertEqual([answerFormat yes], @"YES"); + XCTAssertEqual([answerFormat no], @"NO"); +} + +- (void)testHeightAnswerFormat { + ORKHeightAnswerFormat *answerFormat = [ORKAnswerFormat heightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric]; + XCTAssert([answerFormat measurementSystem] == ORKMeasurementSystemMetric); +} + +- (void)testTimeIntervalAnswerFormat { + NSTimeInterval defaultTimeInterval = 40; + + ORKTimeIntervalAnswerFormat *answerFormat = [ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval + step:1]; + + XCTAssertEqual([answerFormat defaultInterval], defaultTimeInterval); + XCTAssertEqual([answerFormat step], 1); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval step:-1], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step is lower than the recommended minimuim: 0"); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:defaultTimeInterval step:31], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since step is lower than the recommended maximum: 30"); +} +- (void)testImageChoiceAnswerFormat { + + NSBundle *bundle = [NSBundle bundleWithIdentifier:@"org.researchkit.ResearchKit"]; + + UIImage *imageOne = [UIImage imageNamed:@"heart-fitness" inBundle:bundle compatibleWithTraitCollection:nil]; + UIImage *imageTwo = [UIImage imageNamed:@"phoneshake" inBundle:bundle compatibleWithTraitCollection:nil]; + + ORKImageChoice *choiceOne = [ORKImageChoice choiceWithNormalImage:imageOne selectedImage:imageOne text:@"Heart" value:@"ImageTwo"]; + ORKImageChoice *choiceTwo = [ORKImageChoice choiceWithNormalImage:imageTwo selectedImage:imageTwo text:@"Phone Shake" value:@"ImageOne"]; + + NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil]; + ORKImageChoiceAnswerFormat *answerChoice = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:choices]; + + XCTAssertEqual([[answerChoice imageChoices] objectAtIndex:0], choiceOne); + XCTAssertEqual([[answerChoice imageChoices] objectAtIndex:1], choiceTwo); + + NSArray *wrongChoices = [NSArray arrayWithObjects:@"Wrong Choice One", @"Wrong Choice Two", nil]; + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat choiceAnswerFormatWithImageChoices:wrongChoices], NSException, NSInvalidArgumentException, "Should throw NSInvalidArgumentException since choices were not ORKImageChoice objects"); +} + +- (void)testTextAnswerFormat { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormatWithMaximumLength:10]; + + XCTAssertEqual([answerFormat questionType], ORKQuestionTypeText); + XCTAssertEqual(answerFormat.maximumLength, 10); + XCTAssertEqual([answerFormat isAnswerValidWithString:@"CORRECT"], YES, @"Should return YES since the string length is less than max"); + XCTAssertEqual([answerFormat isAnswerValidWithString:@"REALLY LONG STRING! I THINK?"], NO, @"Should return NO since the string length is more than max"); + XCTAssert([answerFormat isEqual:answerFormat], @"Should be equal"); + + ORKTextAnswerFormat *noMaxAnswerFormat = [ORKAnswerFormat textAnswerFormat]; + XCTAssertEqual(noMaxAnswerFormat.maximumLength, 0); + + NSString *pattern = @"^[2-9]\\d{2}-\\d{3}-\\d{4}$"; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:NULL]; + ORKTextAnswerFormat *regexAnswerFormat = [ORKAnswerFormat textAnswerFormatWithValidationRegularExpression:regex invalidMessage:@"NOT A PHONENUMBER!"]; + + XCTAssertEqual(regexAnswerFormat.validationRegularExpression, regex); + XCTAssertEqual(regexAnswerFormat.invalidMessage, @"NOT A PHONENUMBER!"); + + NSString *correctPhoneNumber = @"333-444-5555"; + NSString *incorrectPhoneNumber = @"123-456-7890"; + + XCTAssertEqual([regexAnswerFormat isAnswerValidWithString:correctPhoneNumber], YES, @"Should return YES since it is in the correct format"); + XCTAssertEqual([regexAnswerFormat isAnswerValidWithString:incorrectPhoneNumber], NO, @"Should return NO since it is not in the correct format"); +} + +- (void)testLocationAnswerFormat { + ORKLocationAnswerFormat *answerFormat = [ORKAnswerFormat locationAnswerFormat]; + [answerFormat setUseCurrentLocation:YES]; + XCTAssertEqual(answerFormat.useCurrentLocation, YES); +} + +- (void)testWeightAnswerFormat { + ORKWeightAnswerFormat *answerFormat = [ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric + numericPrecision:ORKNumericPrecisionHigh + minimumValue:0 + maximumValue:300 + defaultValue: 150]; + + XCTAssertEqual(answerFormat.measurementSystem, ORKMeasurementSystemMetric); + XCTAssertEqual(answerFormat.numericPrecision, ORKNumericPrecisionHigh); + XCTAssertEqual(answerFormat.minimumValue, 0); + XCTAssertEqual(answerFormat.maximumValue, 300); + XCTAssertEqual(answerFormat.defaultValue, 150); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric + numericPrecision:ORKNumericPrecisionHigh + minimumValue:100 + maximumValue:50 + defaultValue:25], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since min > max"); + +} + +- (void)testMultipleValuePickerAnswerFormat { + ORKTextChoice *choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value: [NSNumber numberWithInteger:1]]; + ORKTextChoice *choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:2]]; + ORKTextChoice *choiceThree = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:3]]; + ORKTextChoice *choiceFour = [ORKTextChoice choiceWithText:@"Choice Two" value: [NSNumber numberWithInteger:4]]; + + NSArray *firstChoices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil]; + NSArray *secondChoices = [NSArray arrayWithObjects:choiceThree, choiceFour, nil]; + + ORKValuePickerAnswerFormat *valuePickerOne = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:firstChoices]; + ORKValuePickerAnswerFormat *valuePickerTwo = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:secondChoices]; + + NSArray *valuePickerFormats = [NSArray arrayWithObjects:valuePickerOne, valuePickerTwo, nil]; + ORKMultipleValuePickerAnswerFormat *multiplePickerAnswerFormat = [[ORKMultipleValuePickerAnswerFormat alloc] initWithValuePickers:valuePickerFormats separator:@"S"]; + + XCTAssertEqualObjects(multiplePickerAnswerFormat.valuePickers, valuePickerFormats); + XCTAssert([multiplePickerAnswerFormat.separator isEqualToString:@"S"]); +} + +- (void)testValuePickerAnswerFormat { + + ORKTextChoice *choiceOne, *choiceTwo; + + choiceOne = [ORKTextChoice choiceWithText:@"Choice One" value:[NSNumber numberWithInteger:1]]; + choiceTwo = [ORKTextChoice choiceWithText:@"Choice Two" value:[NSNumber numberWithInteger:2]]; + + NSArray *choices = [NSArray arrayWithObjects:choiceOne, choiceTwo, nil]; + ORKValuePickerAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:choices]; + + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:0] value], [NSNumber numberWithInteger:1]); + XCTAssertEqual([[[answerFormat textChoices] objectAtIndex:1] value], [NSNumber numberWithInteger:2]); +} + +- (void)testHealthKitCharacteristicTypeAnswerFormat { + + HKCharacteristicType *biologicalSex = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]; + ORKHealthKitCharacteristicTypeAnswerFormat *answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:biologicalSex]; + NSArray *options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_FEMALE", nil) value: ORKBiologicalSexIdentifierFemale], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_MALE", nil) value:ORKBiologicalSexIdentifierMale], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"GENDER_OTHER", nil) value:ORKBiologicalSexIdentifierOther] + ]; + ORKAnswerFormat *expectedFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:options]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + + HKCharacteristicType *bloodType = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]; + answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:bloodType]; + options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A+", nil) value:ORKBloodTypeIdentifierAPositive], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_A-", nil) value:ORKBloodTypeIdentifierANegative], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B+", nil) value:ORKBloodTypeIdentifierBPositive], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_B-", nil) value:ORKBloodTypeIdentifierBNegative], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB+", nil) value:ORKBloodTypeIdentifierABPositive], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_AB-", nil) value:ORKBloodTypeIdentifierABNegative], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O+", nil) value:ORKBloodTypeIdentifierOPositive], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"BLOOD_TYPE_O-", nil) value:ORKBloodTypeIdentifierONegative] + ]; + expectedFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + + HKCharacteristicType *dateOfBirth = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth]; + answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:dateOfBirth]; + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDate *defaultDate = [NSDate date]; + NSDate *minimumDate = [NSDate dateWithTimeIntervalSinceNow:-1000]; + NSDate *maximumDate = [NSDate dateWithTimeIntervalSinceNow:1000]; + answerFormat.defaultDate = defaultDate; + answerFormat.minimumDate = minimumDate; + answerFormat.maximumDate = maximumDate; + expectedFormat = [ORKDateAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate + minimumDate:minimumDate + maximumDate:maximumDate + calendar:calendar]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + + HKCharacteristicType *fitzpatrickSkin = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType]; + answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:fitzpatrickSkin]; + options = @[[ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_I", nil) value:@(HKFitzpatrickSkinTypeI)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_II", nil) value:@(HKFitzpatrickSkinTypeII)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_III", nil) value:@(HKFitzpatrickSkinTypeIII)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_IV", nil) value:@(HKFitzpatrickSkinTypeIV)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_V", nil) value:@(HKFitzpatrickSkinTypeV)], + [ORKTextChoice choiceWithText:ORKLocalizedString(@"FITZPATRICK_SKIN_TYPE_VI", nil) value:@(HKFitzpatrickSkinTypeVI)], + ]; + expectedFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:options]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + + HKCharacteristicType *wheelchairUse = [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierWheelchairUse]; + answerFormat = [ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:wheelchairUse]; + expectedFormat = [ORKAnswerFormat booleanAnswerFormat]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], [expectedFormat impliedAnswerFormat]); + XCTAssertEqual([answerFormat questionType], ORKQuestionTypeSingleChoice); + XCTAssert([answerFormat isEqual:answerFormat]); +} + +- (void)testHealthKitQuantityTypeAnswerFormat { + + HKQuantityType *height = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; + ORKHealthKitQuantityTypeAnswerFormat *answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:height unit:NULL style:ORKNumericAnswerStyleInteger]; + ORKAnswerFormat *expectedFormat = [ORKHeightAnswerFormat heightAnswerFormat]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + XCTAssertEqual([answerFormat unit], [HKUnit meterUnitWithMetricPrefix:(HKMetricPrefixCenti)]); + + HKQuantityType *weight = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; + answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:weight unit:NULL style:ORKNumericAnswerStyleInteger]; + expectedFormat = [ORKWeightAnswerFormat weightAnswerFormat]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + XCTAssertEqual([answerFormat unit], [HKUnit gramUnitWithMetricPrefix:(HKMetricPrefixKilo)]); + + HKUnit *unit = [HKUnit unitFromEnergyFormatterUnit:(NSEnergyFormatterUnitCalorie)]; + HKQuantityType *calories = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned]; + answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:calories unit:unit style:ORKNumericAnswerStyleDecimal]; + expectedFormat = [ORKNumericAnswerFormat decimalAnswerFormatWithUnit:[unit localizedUnitString]]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + + answerFormat = [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:calories unit:unit style:ORKNumericAnswerStyleInteger]; + expectedFormat = [ORKNumericAnswerFormat integerAnswerFormatWithUnit:[unit localizedUnitString]]; + XCTAssertEqualObjects([answerFormat impliedAnswerFormat], expectedFormat); + XCTAssertEqual([answerFormat unit], unit); + XCTAssertEqual([answerFormat numericAnswerStyle], ORKNumericAnswerStyleInteger); + XCTAssertEqual([answerFormat quantityType], calories); +} + +- (void)testDateAnswerFormat { + + NSDateComponents *earlierDateComponents = [[NSDateComponents alloc] init]; + [earlierDateComponents setDay: 24]; + [earlierDateComponents setMonth: 1]; + [earlierDateComponents setYear: 1984]; + NSDate *earlierDate = [[NSCalendar currentCalendar] dateFromComponents: earlierDateComponents]; + + NSDate *middleDate = [NSDate date]; + + NSDateComponents *laterDateComponents = [[NSDateComponents alloc] init]; + [laterDateComponents setDay: 01]; + [laterDateComponents setMonth: 01]; + [laterDateComponents setYear: 3000]; + NSDate *laterDate = [[NSCalendar currentCalendar] dateFromComponents: laterDateComponents]; + + NSCalendar *calendar = [NSCalendar currentCalendar]; + + ORKDateAnswerFormat *answerFormat = [ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate + minimumDate:earlierDate + maximumDate:laterDate + calendar:calendar]; + + XCTAssertEqual([answerFormat minimumDate], earlierDate); + XCTAssertEqual([answerFormat defaultDate], middleDate); + XCTAssertEqual([answerFormat maximumDate], laterDate); + XCTAssertEqual([answerFormat questionType], ORKQuestionTypeDate); + XCTAssert([answerFormat isAnswerValidWithString:NULL]); + + answerFormat = [ORKAnswerFormat dateTimeAnswerFormat]; + XCTAssertEqual([answerFormat questionType], ORKQuestionTypeDateAndTime); + + XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate + minimumDate:laterDate + maximumDate:earlierDate + calendar:calendar], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since maximum date is less than minimum date"); + XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:laterDate + minimumDate:earlierDate + maximumDate:middleDate + calendar:calendar], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since default date is more than maximum date"); + XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:earlierDate + minimumDate:middleDate + maximumDate:laterDate + calendar:calendar], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since default date is less than minimum date"); + XCTAssertThrowsSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:nil + minimumDate:laterDate + maximumDate:earlierDate + calendar:calendar], + NSException, + NSInvalidArgumentException, + @"Should throw NSInvalidArgumentException since minimum date is later than maximum date"); + XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:nil + minimumDate:earlierDate + maximumDate:laterDate + calendar:calendar], + NSException, + NSInvalidArgumentException); + XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate + minimumDate:nil + maximumDate:laterDate + calendar:calendar], + NSException, + NSInvalidArgumentException); + XCTAssertNoThrowSpecificNamed([ORKAnswerFormat dateAnswerFormatWithDefaultDate:middleDate + minimumDate:earlierDate + maximumDate:nil + calendar:calendar], + NSException, + NSInvalidArgumentException); + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKBorderedButtonTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKBorderedButtonTests.swift new file mode 100755 index 0000000..2ec9edb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKBorderedButtonTests.swift @@ -0,0 +1,53 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +@testable import ResearchKit + +class ORKBorderedButtonTests: XCTestCase { + + let button = ORKBorderedButton(type: .custom) + + override func setUp() { + super.setUp() + button.normalTintColor = UIColor.black + button.normalHighlightOrSelectTintColor = UIColor.red + button.disableTintColor = UIColor.blue + button.fadeDelay = 20.0 + } + + func testProperties() { + XCTAssertEqual(button.buttonType, UIButton.ButtonType.custom) + XCTAssertEqual(button.normalTintColor, UIColor.black) + XCTAssertEqual(button.normalHighlightOrSelectTintColor, UIColor.red) + XCTAssertEqual(button.disableTintColor, UIColor.blue) + XCTAssertEqual(button.fadeDelay, 20.0) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKChoiceAnswerFormatHelperTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKChoiceAnswerFormatHelperTests.m new file mode 100755 index 0000000..6725592 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKChoiceAnswerFormatHelperTests.m @@ -0,0 +1,352 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKChoiceAnswerFormatHelper.h" + + +@interface ORKChoiceAnswerFormatHelperTests : XCTestCase + +@end + + +@implementation ORKChoiceAnswerFormatHelperTests + +- (NSArray *)textChoices { + + static NSArray *choices = nil; + + if (choices == nil) { + choices = @[[ORKTextChoice choiceWithText:@"choice 01" value:@"c1"], + [ORKTextChoice choiceWithText:@"choice 02" value:@"c2"], + [ORKTextChoice choiceWithText:@"choice 03" value:@"c3"], + [ORKTextChoice choiceWithText:@"choice 04" value:@"c4"]]; + } + + return choices; +} + +- (NSArray *)imageChoices { + + static NSArray *choices = nil; + + if (choices == nil) { + choices = @[[ORKImageChoice choiceWithNormalImage:nil selectedImage:nil text:@"choice 01" value:@"c1"], + [ORKImageChoice choiceWithNormalImage:nil selectedImage:nil text:@"choice 02" value:@"c2"], + [ORKImageChoice choiceWithNormalImage:nil selectedImage:nil text:@"choice 03" value:@"c3"]]; + } + + return choices; +} + +- (void)testCount { + + { + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:[self textChoices]]; + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + XCTAssertEqual(formatHelper.choiceCount, [self textChoices].count, @""); + } + + { + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:[self imageChoices]]; + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + XCTAssertEqual(formatHelper.choiceCount, [self imageChoices].count, @""); + } + + { + ORKAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:[self textChoices]]; + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + XCTAssertEqual(formatHelper.choiceCount, [self textChoices].count+1, @""); + } +} + +- (void)testTextChoice { + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [textChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKTextChoice *tc = obj; + ORKTextChoice *tc2 = [formatHelper textChoiceAtIndex:idx]; + XCTAssertEqual(tc, tc2, @""); + XCTAssertNil([formatHelper imageChoiceAtIndex:idx],@""); + }]; + } + + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]; + + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [textChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKTextChoice *tc = obj; + ORKTextChoice *tc2 = [formatHelper textChoiceAtIndex:idx+1]; + XCTAssertEqual(tc, tc2, @""); + XCTAssertNil([formatHelper imageChoiceAtIndex:idx],@""); + }]; + } +} + +- (void)testImageChoice { + { + NSArray *imageChoices = [self imageChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:imageChoices]; + + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [imageChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKImageChoice *tc = obj; + ORKImageChoice *tc2 = [formatHelper imageChoiceAtIndex:idx]; + XCTAssertEqual(tc, tc2, @""); + XCTAssertNil([formatHelper textChoiceAtIndex:idx],@""); + }]; + } +} + +- (void)verifyAnswerForSelectedIndexes:(ORKChoiceAnswerFormatHelper *)formatHelper choices:(NSArray *)choices { + NSMutableArray *indexArray = [NSMutableArray new]; + + [choices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + + id answer = [formatHelper answerForSelectedIndex:idx]; + + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + + id value = ((ORKTextChoice *)choices[idx]).value; + + if (value == nil) { + value = @(idx); + } + + XCTAssert(answerArray.count == 1 && [answerArray.firstObject isEqual:value], @"%@", answerArray); + + answer = [formatHelper answerForSelectedIndexes:@[@(idx)]]; + XCTAssert([answer isKindOfClass:[NSArray class]]); + answerArray = answer; + + XCTAssert(answerArray.count == 1 && [answerArray.firstObject isEqual:value], @"%@", answerArray); + + [indexArray addObject:@(idx)]; + + answer = [formatHelper answerForSelectedIndexes:indexArray]; + XCTAssert([answer isKindOfClass:[NSArray class]]); + answerArray = answer; + + XCTAssertEqual(answerArray.count, idx + 1, @"%@", answerArray); + + }]; +} + +- (void)testAnswerForSelectedIndexes { + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + id answer = [formatHelper answerForSelectedIndexes:@[@(0)]]; + + XCTAssert(answer == ORKNullAnswerValue(), @"%@", answer); + + answer = [formatHelper answerForSelectedIndex:0]; + + XCTAssert(answer == ORKNullAnswerValue(), @"%@", answer); + + [textChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + + id answer = [formatHelper answerForSelectedIndex:idx+1]; + + id value = ((ORKTextChoice *)textChoices[idx]).value; + + if (value == nil) { + value = @(idx); + } + + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssert(answerArray.count == 1 && [answerArray.firstObject isEqual:value], @"%@", answer); + + answer = [formatHelper answerForSelectedIndexes:@[@(idx+1)]]; + XCTAssert([answer isKindOfClass:[NSArray class]]); + answerArray = answer; + + XCTAssert(answerArray.count == 1 && [answerArray.firstObject isEqual:value], @"%@", answer); + }]; + + } + + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + + [self verifyAnswerForSelectedIndexes:formatHelper choices:textChoices]; + } + + { + NSArray *imageChoices = [self imageChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:imageChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [self verifyAnswerForSelectedIndexes:formatHelper choices:imageChoices]; + } +} + +- (void)verifySelectedIndexesForAnswer:(ORKChoiceAnswerFormatHelper *)formatHelper choices:(NSArray *)choices { + + NSArray *indexes = [formatHelper selectedIndexesForAnswer:nil]; + + XCTAssertEqual(indexes.count, 0, @"%@", indexes); + + indexes = [formatHelper selectedIndexesForAnswer:ORKNullAnswerValue()]; + + XCTAssertEqual(indexes.count, 0, @"%@", indexes); + + NSNumber *indexNumber = [formatHelper selectedIndexForAnswer:nil]; + + XCTAssertNil(indexNumber, @"%@", indexNumber); + + indexNumber = [formatHelper selectedIndexForAnswer:ORKNullAnswerValue()]; + + XCTAssertNil(indexNumber, @"%@", indexNumber); + + [choices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + + id value = ((ORKTextChoice *)obj).value; + + if (value == nil) { + value = @(idx); + } + + NSNumber *indexNumber = [formatHelper selectedIndexForAnswer:@[value]]; + + XCTAssertEqualObjects(indexNumber, @(idx), @"%@ vs %@", indexNumber, @(idx)); + + NSArray *indexArray = [formatHelper selectedIndexesForAnswer:@[value]]; + + XCTAssertEqualObjects( indexArray.firstObject, @(idx), @"%@ vs %@", indexArray[0], @(idx)); + + }]; +} + +- (void)testSelectedIndexesForAnswer { + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + NSArray *indexes = [formatHelper selectedIndexesForAnswer:nil]; + + XCTAssertEqualObjects(indexes.firstObject, @(0), @"%@", indexes); + + indexes = [formatHelper selectedIndexesForAnswer:ORKNullAnswerValue()]; + + XCTAssertEqualObjects(indexes.firstObject, @(0), @"%@", indexes); + + NSNumber *indexNumber = [formatHelper selectedIndexForAnswer:nil]; + + XCTAssert([indexNumber isKindOfClass:[NSNumber class]] && indexNumber.unsignedIntegerValue == 0, @"%@", indexNumber); + + indexNumber = [formatHelper selectedIndexForAnswer:ORKNullAnswerValue()]; + + XCTAssert([indexNumber isKindOfClass:[NSNumber class]] && indexNumber.unsignedIntegerValue == 0, @"%@", indexNumber); + + [textChoices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + + id value = ((ORKTextChoice *)obj).value; + + if (value == nil) { + value = @(idx); + } + + NSNumber *indexNumber = [formatHelper selectedIndexForAnswer:@[value]]; + + XCTAssertEqualObjects(indexNumber, @(idx+1), @"%@ vs %@", indexNumber, @(idx+1)); + + NSArray *indexArray = [formatHelper selectedIndexesForAnswer:@[value]]; + + XCTAssertEqualObjects(indexArray.firstObject, @(idx+1), @"%@ vs %@", indexArray[0], @(idx+1)); + + }]; + + } + + { + NSArray *textChoices = [self textChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [self verifySelectedIndexesForAnswer:formatHelper choices:textChoices]; + + } + + { + NSArray *imageChoices = [self imageChoices]; + + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithImageChoices:imageChoices]; + + ORKChoiceAnswerFormatHelper *formatHelper = [[ORKChoiceAnswerFormatHelper alloc] initWithAnswerFormat:answerFormat]; + + [self verifySelectedIndexesForAnswer:formatHelper choices:imageChoices]; + + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKCompletionStepViewControllerTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKCompletionStepViewControllerTests.swift new file mode 100755 index 0000000..a52b1d4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKCompletionStepViewControllerTests.swift @@ -0,0 +1,60 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +import ResearchKit.Private + +class ORKCompletionStepViewControllerTests: XCTestCase { + var completionController: ORKCompletionStepViewController! + var step: ORKStep! + var result: ORKResult! + var utilities: TopLevelUIUtilities! + + override func setUp() { + super.setUp() + step = ORKInstructionStep(identifier: "STEP") + result = ORKResult(identifier: "RESULT") + completionController = ORKCompletionStepViewController(step: step, result: result) + completionController.shouldShowContinueButton = true + completionController.checkmarkColor = .blue + utilities = TopLevelUIUtilities() + utilities.setupTopLevelUI(withViewController: completionController) + } + + override func tearDown() { + super.tearDown() + utilities.tearDownTopLevelUI() + } + + func testProperties() { + XCTAssertEqual(completionController.shouldShowContinueButton, true) + XCTAssertEqual(completionController.checkmarkColor, UIColor.blue) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentDocumentTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentDocumentTests.m new file mode 100755 index 0000000..a224225 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentDocumentTests.m @@ -0,0 +1,194 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKConsentSectionFormatter.h" +#import "ORKConsentSignatureFormatter.h" +#import "ORKHTMLPDFWriter.h" + + +@interface ORKMockHTMLPDFWriter : ORKHTMLPDFWriter + +@property (nonatomic, copy) NSString *html; +@property (nonatomic, copy) void (^completionBlock)(NSData *, NSError *); + +@end + + +@implementation ORKMockHTMLPDFWriter + +- (void)writePDFFromHTML:(NSString *)html completionBlock:(void (^)(NSData *, NSError *))completionBlock { + self.html = html; + self.completionBlock = completionBlock; +} + +@end + + +@interface ORKMockConsentSectionFormatter : ORKConsentSectionFormatter + +@end + + +@implementation ORKMockConsentSectionFormatter + +- (NSString *)HTMLForSection:(ORKConsentSection *)section { + return @"html for section"; +} + +@end + + +@interface ORKMockConsentSignatureFormatter : ORKConsentSignatureFormatter + +@end + + +@implementation ORKMockConsentSignatureFormatter + +- (NSString *)HTMLForSignature:(ORKConsentSignature *)signature { + return @"html for signature"; +} + +@end + + +@interface ORKConsentDocumentTests : XCTestCase + +@property (nonatomic, strong) ORKConsentDocument *document; +@property (nonatomic, strong) ORKMockHTMLPDFWriter *mockWriter; + +@end + + +@implementation ORKConsentDocumentTests + +- (void)setUp { + [super setUp]; + + self.mockWriter = [[ORKMockHTMLPDFWriter alloc] init]; + + self.document = [[ORKConsentDocument alloc] initWithHTMLPDFWriter:self.mockWriter + consentSectionFormatter:[[ORKMockConsentSectionFormatter alloc] init] + consentSignatureFormatter:[[ORKMockConsentSignatureFormatter alloc] init]]; +} + +- (void)tearDown { + self.document = nil; + [super tearDown]; +} + +- (NSString *)htmlWithContent:(NSString *)content mobile:(BOOL)mobile { + NSString *boilerplateHeader = +@"
"; + NSMutableString *boilerplateFooter = [NSMutableString new]; + if (mobile) { + [boilerplateFooter appendString:@"

"]; + } + [boilerplateFooter appendString:@""]; + + return [NSString stringWithFormat:@"%@%@%@", boilerplateHeader, content, boilerplateFooter]; +} + +- (void)testMakePDFWithCompletionHandler_withHTMLReviewContent_callsWriterWithCorrectHTML { + self.document.htmlReviewContent = @"some content"; + [self.document makePDFWithCompletionHandler:^(NSData *data, NSError *error) {}]; + XCTAssertEqualObjects(self.mockWriter.html, [self htmlWithContent:@"some content" mobile:YES]); +} + +- (void)testMakePDFWithCompletionHandler_withoutHTMLReviewContent_callsWriterWithCorrectHTML { + self.document.title = @"A Title"; + self.document.sections = @[ + [[ORKConsentSection alloc] init], + [[ORKConsentSection alloc] init] + ]; + self.document.signaturePageTitle = @"Signature Page Title"; + self.document.signaturePageContent = @"signature page content"; + self.document.signatures = @[ + [[ORKConsentSignature alloc] init], + [[ORKConsentSignature alloc] init] + ]; + + NSString *content = @"

A Title

" + @"html for section" + @"html for section" + @"

Signature Page Title

" + @"

signature page content

" + @"html for signature" + @"html for signature"; + + [self.document makePDFWithCompletionHandler:^(NSData *data, NSError *error) {}]; + XCTAssertEqualObjects(self.mockWriter.html, [self htmlWithContent:content mobile:NO]); +} + +- (void)testMakePDFWithCompletionHandler_whenWriterReturnsData_callsCompletionBlockWithData { + __block NSData *passedData; + __block NSError *passedError; + [self.document makePDFWithCompletionHandler:^(NSData *data, NSError *error) { + passedData = data; + passedError = error; + }]; + + NSData *data = [NSData data]; + self.mockWriter.completionBlock(data, nil); + + XCTAssertEqualObjects(passedData, data); + XCTAssertEqualObjects(passedError, nil); +} + +- (void)testMakePDFWithCompletionHandler_whenWriterReturnsError_callsCompletionBlockWithError { + __block NSData *passedData; + __block NSError *passedError; + [self.document makePDFWithCompletionHandler:^(NSData *data, NSError *error) { + passedData = data; + passedError = error; + }]; + + NSError *error = [NSError errorWithDomain:@"some error domain" code:123 userInfo:@{}]; + self.mockWriter.completionBlock(nil, error); + + XCTAssertEqualObjects(passedData, nil); + XCTAssertEqualObjects(passedError, error); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSectionFormatterTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSectionFormatterTests.m new file mode 100755 index 0000000..6f4476e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSectionFormatterTests.m @@ -0,0 +1,82 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKConsentSectionFormatter.h" + + +@interface ORKConsentSectionFormatterTests : XCTestCase + +@property (nonatomic, strong) ORKConsentSectionFormatter *formatter; +@property (nonatomic, strong) ORKConsentSection *section; + +@end + + +@implementation ORKConsentSectionFormatterTests + +- (void)setUp { + [super setUp]; + self.formatter = [[ORKConsentSectionFormatter alloc] init]; + self.section = [[ORKConsentSection alloc] init]; +} + +- (void)tearDown { + self.formatter = nil; + self.section = nil; + [super tearDown]; +} + +- (void)testHTMLForSection_whenSectionHasFormalTitle_formatsFormalTitle { + self.section.formalTitle = @"Formal Title"; + self.section.title = @"Informal Title"; + XCTAssertEqualObjects([self.formatter HTMLForSection:self.section], @"

Formal Title

"); +} + +- (void)testHTMLForSection_whenSectionHasNoFormalTitle_formatsFormalTitle { + self.section.title = @"Informal Title"; + XCTAssertEqualObjects([self.formatter HTMLForSection:self.section], @"

Informal Title

"); +} + +- (void)testHTMLForSection_whenSectionHasHTMLContent_formatsHTMLContent { + self.section.htmlContent = @"html content"; + self.section.content = @"other content"; + XCTAssertEqualObjects([self.formatter HTMLForSection:self.section], @"

html content

"); +} + +- (void)testHTMLForSection_whenSectionHasNoHTMLContent_formatsEscapedContent { + self.section.content = @"unescaped content\nwith special characters such as < >"; + XCTAssertEqualObjects([self.formatter HTMLForSection:self.section], @"

unescaped content
with special characters such as < >

"); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSignatureFormatterTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSignatureFormatterTests.m new file mode 100755 index 0000000..675c669 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentSignatureFormatterTests.m @@ -0,0 +1,185 @@ +/* + Copyright (c) 2015, Alex Basson. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKConsentSignatureFormatter.h" + + +@interface ORKConsentSignatureFormatterTests : XCTestCase + +@property (nonatomic, strong) ORKConsentSignatureFormatter *formatter; +@property (nonatomic, strong) ORKConsentSignature *signature; + +@end + + +@implementation ORKConsentSignatureFormatterTests + +- (void)setUp { + [super setUp]; + + self.formatter = [[ORKConsentSignatureFormatter alloc] init]; + self.signature = [[ORKConsentSignature alloc] init]; + self.signature.title = @"User"; +} + +- (void)tearDown { + self.formatter = nil; + self.signature = nil; + + [super tearDown]; +} + +- (void)testHTMLForSignature_withNameNotRequired_formatsNames { + self.signature.requiresName = NO; + NSString *html; + html = @"


" + @"

 
" + @"
" + @"Signature

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); +} + +- (void)testHTMLForSignature_withNameRequired_formatsNames { + self.signature.requiresName = YES; + NSString *html; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
 
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); + + self.signature.familyName = @"Family"; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
Family
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); + + self.signature.givenName = @"Given"; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
Given Family
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); +} + +- (void)testHTMLForSignature_withSignatureImageNotRequired_formatsImage { + self.signature.requiresSignatureImage = NO; + NSString *html; + html = @"


" + @"
 
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); +} + +- (void)testHTMLForSignature_withSignatureImageRequired_formatsImage { + self.signature.requiresSignatureImage = YES; + NSString *html; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
 
" + @"
" + @"Printed Name

" + @"


 
" + @"
Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); + +} + +- (void)testHTMLForSignature_withSignatureImage_formatsImage { + self.signature.signatureImage = [UIImage imageNamed:@"arrowLeft"]; + NSString *html; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
 
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); +} + +- (void)testHTMLForSignature_withNameAndImage_formatsSignature { + self.signature.requiresName = YES; + self.signature.familyName = @"Family"; + self.signature.givenName = @"Given"; + + self.signature.requiresSignatureImage = YES; + self.signature.signatureImage = [UIImage imageNamed:@"arrowLeft"]; + + NSString *html; + html = @"


 
" + @"
" + @"Signature

" + @"


" + @"
Given Family
" + @"
" + @"Printed Name

" + @"


 
" + @"
" + @"Date

"; + XCTAssertEqualObjects([self.formatter HTMLForSignature:self.signature], html); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentTests.m new file mode 100755 index 0000000..d1cf6a4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKConsentTests.m @@ -0,0 +1,54 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKConsentTests : XCTestCase + +@end + + +@implementation ORKConsentTests + +- (void)testContentEscaping { + NSString *content = @"

this is content


"; + + ORKConsentSection *section = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOverview]; + + section.content = content; + + XCTAssert([section.escapedContent isEqualToString:@"<img><p>this is content</p><br><div/>"]); + +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKContinueButtonTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKContinueButtonTests.swift new file mode 100755 index 0000000..1933317 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKContinueButtonTests.swift @@ -0,0 +1,47 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +import UIKit + +class ORKContinueButtonTests: XCTestCase { + + var button: ORKContinueButton! + + override func setUp() { + super.setUp() + button = ORKContinueButton(title: "BUTTON", isDoneButton: true) + } + + func testAttributes() { + XCTAssertEqual(button.titleLabel?.text, "BUTTON") + XCTAssertEqual(button.isDoneButton, true) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerManagerTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerManagerTests.m new file mode 100755 index 0000000..95987ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerManagerTests.m @@ -0,0 +1,259 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKDataLoggerManagerTests : XCTestCase { + NSURL *_directory; + ORKDataLoggerManager *_manager; + + NSInteger _pendingUploadBytesReachedCounter; + unsigned long long _lastPendingUploadBytes; + NSInteger _totalBytesReachedCounter; + unsigned long long _lastTotalBytes; +} + +@end + + +@implementation ORKDataLoggerManagerTests + +- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLogger pendingUploadBytesReachedThreshold:(unsigned long long)pendingUploadBytes { + _pendingUploadBytesReachedCounter ++; + _lastPendingUploadBytes = pendingUploadBytes; +} + +- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLogger totalBytesReachedThreshold:(unsigned long long)totalBytes { + _totalBytesReachedCounter ++; + _lastTotalBytes = totalBytes; +} + +- (void)setUp { + [super setUp]; + + _directory = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString] isDirectory:YES]; + + BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_directory withIntermediateDirectories:YES attributes:nil error:nil]; + XCTAssertTrue(success, @"Create log directory"); + _pendingUploadBytesReachedCounter = 0; + _totalBytesReachedCounter = 0; + _lastPendingUploadBytes = 0; + _lastTotalBytes = 0; + _manager = [[ORKDataLoggerManager alloc] initWithDirectory:_directory delegate:self]; + XCTAssertNotNil(_manager); +} + +- (void)tearDown { + [super tearDown]; + _manager.delegate = nil; + _manager = nil; + _pendingUploadBytesReachedCounter = 0; + _totalBytesReachedCounter = 0; + + BOOL success = [[NSFileManager defaultManager] removeItemAtURL:_directory error:nil]; + XCTAssertTrue(success, @"Remove log directory"); + _directory = nil; + +} + +- (void)addLoggers123 { + [_manager addJSONDataLoggerForLogName:@"test1"]; + [_manager addJSONDataLoggerForLogName:@"test2"]; + [_manager addJSONDataLoggerForLogName:@"test3"]; + + XCTAssertEqual([_manager logNames].count, 3); +} + +- (void)testPreservesParameters { + _manager.totalBytesThreshold = 10; + _manager.pendingUploadBytesThreshold = 12; + _manager.delegate = nil; + _manager = nil; + + _manager = [[ORKDataLoggerManager alloc] initWithDirectory:_directory delegate:self]; + XCTAssertNotNil(_manager); + + XCTAssertEqual(_manager.totalBytesThreshold, 10); + XCTAssertEqual(_manager.pendingUploadBytesThreshold, 12); + +} + +- (void)testAddingLoggers { + [self addLoggers123]; + XCTAssertEqualObjects([_manager dataLoggerForLogName:@"test1"].logName, @"test1"); + XCTAssertEqualObjects([_manager dataLoggerForLogName:@"test2"].logName, @"test2"); + XCTAssertEqualObjects([_manager dataLoggerForLogName:@"test3"].logName, @"test3"); +} + +- (void)testEnumerationSortOrder { + [self addLoggers123]; + + ORKDataLogger *dm3 = [_manager dataLoggerForLogName:@"test3"]; + ORKDataLogger *dm2 = [_manager dataLoggerForLogName:@"test2"]; + ORKDataLogger *dm1 = [_manager dataLoggerForLogName:@"test1"]; + + NSDictionary *jsonObject = @{@"test": @"1234"}; + + NSError *error = nil; + XCTAssertTrue([dm3 append:jsonObject error:&error]); + XCTAssertNil(error); + [dm3 finishCurrentLog]; + + XCTAssertTrue([dm3 append:jsonObject error:&error]); + XCTAssertNil(error); + [dm3 finishCurrentLog]; + // Always wait 1.1 seconds, because the string we sort on only changes with time after 1 sec + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.1]]; + + XCTAssertTrue([dm1 append:jsonObject error:&error]); + XCTAssertNil(error); + [dm1 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.1]]; + + XCTAssertTrue([dm2 append:jsonObject error:&error]); + XCTAssertNil(error); + [dm2 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.1]]; + + XCTAssertTrue([dm1 append:jsonObject error:&error]); + XCTAssertNil(error); + [dm1 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.1]]; + + NSMutableArray *dataLoggers = [NSMutableArray array]; + BOOL success = [_manager enumerateLogsNeedingUpload:^(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop) { + [dataLoggers addObject:dataLogger]; + } error:&error]; + + XCTAssertTrue(success); + XCTAssertNil(error); + + NSArray *a = @[dm3, dm3, dm1, dm2, dm1]; + // Data loggers should be referenced in the order that their files were added (with repeats where appropriate) + XCTAssertEqualObjects(dataLoggers, a); + +} + +- (void)testRemoveOldLogs { + [self addLoggers123]; + + _manager.totalBytesThreshold = 10; + + const NSTimeInterval filesystemSettleTime = 0.5; + + ORKDataLogger *dm3 = [_manager dataLoggerForLogName:@"test3"]; + ORKDataLogger *dm2 = [_manager dataLoggerForLogName:@"test2"]; + ORKDataLogger *dm1 = [_manager dataLoggerForLogName:@"test1"]; + + XCTAssertTrue([dm3 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm2 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm1 append:@{@"test":@"blah"} error:nil]); + [dm3 finishCurrentLog]; + [dm2 finishCurrentLog]; + [dm1 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:filesystemSettleTime]]; + + unsigned long long bytes = _manager.totalBytes; + + // Check we got the delegate callback appropriately + XCTAssertGreaterThan(bytes, _manager.totalBytesThreshold); + XCTAssertEqual(_totalBytesReachedCounter, 1); + XCTAssertEqual(_pendingUploadBytesReachedCounter, 0); + + NSError *error = nil; + XCTAssertTrue([_manager removeOldAndUploadedLogsToThreshold:9 error:&error]); + XCTAssertNil(error); + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:filesystemSettleTime]]; + XCTAssertTrue(_manager.totalBytes <= 10); + + XCTAssertTrue([dm3 append:@{@"test":@"blah"} error:nil]); + [dm3 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:filesystemSettleTime]]; + + bytes = _manager.totalBytes; + XCTAssertGreaterThan(bytes, _manager.totalBytesThreshold); + XCTAssertTrue(bytes > _manager.totalBytesThreshold); + XCTAssertEqual(_totalBytesReachedCounter, 2); + XCTAssertEqual(_pendingUploadBytesReachedCounter, 0); +} + +- (void)testDelegateThresholds { + [self addLoggers123]; + + _manager.pendingUploadBytesThreshold = 10; + + ORKDataLogger *dm3 = [_manager dataLoggerForLogName:@"test3"]; + ORKDataLogger *dm2 = [_manager dataLoggerForLogName:@"test2"]; + ORKDataLogger *dm1 = [_manager dataLoggerForLogName:@"test1"]; + + XCTAssertTrue([dm3 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm2 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm1 append:@{@"test":@"blah"} error:nil]); + [dm3 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + [dm2 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + [dm1 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + + unsigned long long bytes = _manager.pendingUploadBytes; + XCTAssertTrue(bytes > _manager.pendingUploadBytesThreshold); + XCTAssertEqual(_totalBytesReachedCounter, 0); + XCTAssertEqual(_pendingUploadBytesReachedCounter, 1); + + // Mark all the files uploaded, then create some more files. Check we get another delegate call + BOOL success = [_manager enumerateLogsNeedingUpload:^(ORKDataLogger *dataLogger, NSURL *logFileUrl, BOOL *stop) { + XCTAssertTrue([dataLogger markFileUploaded:YES atURL:logFileUrl error:nil]); + } error:nil]; + XCTAssertTrue(success); + + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + + bytes = _manager.pendingUploadBytes; + XCTAssertTrue(bytes < _manager.pendingUploadBytesThreshold); + + XCTAssertTrue([dm3 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm2 append:@{@"test":@"blah"} error:nil]); + XCTAssertTrue([dm1 append:@{@"test":@"blah"} error:nil]); + [dm3 finishCurrentLog]; + [dm2 finishCurrentLog]; + [dm1 finishCurrentLog]; + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]]; + + bytes = _manager.pendingUploadBytes; + XCTAssertTrue(bytes > _manager.pendingUploadBytesThreshold); + XCTAssertEqual(_totalBytesReachedCounter, 0); + XCTAssertEqual(_pendingUploadBytesReachedCounter, 2); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerTests.m new file mode 100755 index 0000000..853b1f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKDataLoggerTests.m @@ -0,0 +1,391 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKHelpers_Internal.h" + +@interface ORKDataLoggerTests : XCTestCase { + NSURL *_directory; + NSString *_logName; + ORKDataLogger *_dataLogger; + + NSMutableArray *_finishedLogFiles; +} + +@end + + +@implementation ORKDataLoggerTests + +- (void)setUp { + [super setUp]; + NSURL *baseURL = [NSURL fileURLWithPath:NSHomeDirectory()]; + NSURL *standardizedBaseURL = [baseURL URLByStandardizingPath]; + + _directory = [NSURL fileURLWithPath:[NSUUID UUID].UUIDString isDirectory:YES relativeToURL:standardizedBaseURL]; + + BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:_directory withIntermediateDirectories:YES attributes:nil error:nil]; + XCTAssertTrue(success, @"Create log directory"); + + _logName = @"test"; + + _finishedLogFiles = [NSMutableArray array]; + _dataLogger = [ORKDataLogger JSONDataLoggerWithDirectory:_directory logName:_logName delegate:self]; +} + +- (void)tearDown { + [super tearDown]; + + [_dataLogger finishCurrentLog]; + _dataLogger.delegate = nil; + [_finishedLogFiles removeAllObjects]; + + BOOL success = [[NSFileManager defaultManager] removeItemAtURL:_directory error:nil]; + XCTAssertTrue(success, @"Remove log directory"); + _directory = nil; + _logName = nil; +} + +- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl { + XCTAssertEqual(_dataLogger, dataLogger, @"Should be the same"); + [_finishedLogFiles addObject:fileUrl]; +} + +- (void)testDoNothing { + NSURL *url = [_dataLogger currentLogFileURL]; + XCTAssertTrue([[url URLByDeletingLastPathComponent] isEqual:_directory], @"current log file should be in _directory"); + + XCTAssertFalse([[NSFileManager defaultManager] fileExistsAtPath:[url path]], @"File should not be created if we log nothing"); +} + +- (void)logJsonObject:(NSDictionary *)jsonObject { + NSError *error = nil; + BOOL success = [_dataLogger append:jsonObject error:&error]; + XCTAssertTrue(success); + XCTAssertNil(error); +} + +- (void)wait { + // Let the runloop run once so we get our delegate callback + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; +} + +- (void)logJsonObjectAndRolloverAndWaitOnce:(NSDictionary *)jsonObject { + [self logJsonObject:jsonObject]; + + NSURL *url = [_dataLogger currentLogFileURL]; + XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:[url path]]); + + [_dataLogger finishCurrentLog]; + + [self wait]; +} + +- (void)testJSONFormatting { + NSDictionary *jsonObject = @{@"test": @[@"a", @"b"], @"blah": @(1) }; + + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + + XCTAssertEqual(_finishedLogFiles.count, 1); + + NSError *error = nil; + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:_finishedLogFiles[0]] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(jsonOut[@"items"][0], jsonObject); +} + +- (void)testContinuesExistingLog { + // Test that if you create a logger, and then kill it and create a new logger, the new one + // continues from the right place without forcing a roll-over + XCTAssertTrue([_dataLogger append:@{@"val":@(1)} error:nil]); + + _dataLogger.delegate = nil; + + _dataLogger = [ORKDataLogger JSONDataLoggerWithDirectory:_directory logName:_logName delegate:self]; + + XCTAssertTrue([_dataLogger append:@{@"val":@(2)} error:nil]); + + [_dataLogger finishCurrentLog]; + + [self wait]; + + __block int count = 0; + [_dataLogger enumerateLogsNeedingUpload:^(NSURL *logFileUrl, BOOL *stop) { + count ++; + } error:nil]; + XCTAssertEqual(count, 1); + + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:_finishedLogFiles.lastObject] options:(NSJSONReadingOptions)0 error:nil]; + XCTAssertEqualObjects(jsonOut[@"items"][0][@"val"], @(1)); + XCTAssertEqualObjects(jsonOut[@"items"][1][@"val"], @(2)); +} + +- (void)testRemoveAllFiles { + NSDictionary *jsonObject = @{@"test": @(1) }; + NSDictionary *jsonObject2 = @{@"test": @(2) }; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject2]; + + XCTAssertEqual(_finishedLogFiles.count, 2); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + XCTAssertTrue([fileManager fileExistsAtPath:[(NSURL *)_finishedLogFiles[0] path]]); + XCTAssertTrue([fileManager fileExistsAtPath:[(NSURL *)_finishedLogFiles[1] path]]); + + NSError *error = nil; + XCTAssertTrue([_dataLogger removeAllFilesWithError:&error]); + XCTAssertNil(error); + + XCTAssertFalse([fileManager fileExistsAtPath:[(NSURL *)_finishedLogFiles[0] path]]); + XCTAssertFalse([fileManager fileExistsAtPath:[(NSURL *)_finishedLogFiles[1] path]]); + + NSArray *logs = [self allLogsWithError:&error]; + XCTAssertNil(error); + XCTAssertEqual(logs.count, 0); +} + +- (void)testMarkFileUploaded { + NSDictionary *jsonObject = @{@"test": @(1) }; + NSDictionary *jsonObject2 = @{@"test": @(2) }; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject2]; + + XCTAssertFalse([_dataLogger isFileUploadedAtURL:_finishedLogFiles[0]]); + + // Test direct attribute set/unset using underlying category + XCTAssertFalse([_finishedLogFiles[0] ork_isUploaded]); + XCTAssertTrue([_finishedLogFiles[0] ork_setUploaded:YES error:nil]); + XCTAssertTrue([_finishedLogFiles[0] ork_isUploaded]); + XCTAssertTrue([_dataLogger isFileUploadedAtURL:_finishedLogFiles[0]]); + XCTAssertTrue([_finishedLogFiles[0] ork_setUploaded:NO error:nil]); + XCTAssertFalse([_finishedLogFiles[0] ork_isUploaded]); + + XCTAssertFalse([_dataLogger isFileUploadedAtURL:_finishedLogFiles[0]]); + + // Test setting uploaded through the data logger + NSError *error = nil; + XCTAssertTrue([_dataLogger markFileUploaded:YES atURL:_finishedLogFiles[0] error:&error]); + XCTAssertNil(error); + + XCTAssertTrue([_dataLogger isFileUploadedAtURL:_finishedLogFiles[0]]); + XCTAssertFalse([_dataLogger isFileUploadedAtURL:_finishedLogFiles[1]]); +} + +- (NSArray *)allLogsWithError:(NSError **)errorOut { + NSMutableArray *logs = [NSMutableArray array]; + [_dataLogger enumerateLogs:^(NSURL *logFileUrl, BOOL *stop) { + [logs addObject:logFileUrl]; + } error:errorOut]; + return logs; +} + +- (NSArray *)logsUploaded:(BOOL)uploaded withError:(NSError **)errorOut { + NSMutableArray *logs = [NSMutableArray array]; + if (uploaded) { + [_dataLogger enumerateLogsAlreadyUploaded:^(NSURL *logFileUrl, BOOL *stop) { + [logs addObject:logFileUrl]; + } error:errorOut]; + } else { + [_dataLogger enumerateLogsNeedingUpload:^(NSURL *logFileUrl, BOOL *stop) { + [logs addObject:logFileUrl]; + } error:errorOut]; + } + return logs; +} + +- (void)testFileEnumerators { + NSDictionary *jsonObject = @{@"test": @(1) }; + NSDictionary *jsonObject2 = @{@"test": @(2) }; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject2]; + + XCTAssertEqual(_finishedLogFiles.count, 2); + { + NSError *error = nil; + NSArray *uploaded = [self logsUploaded:YES withError:&error]; + XCTAssertNil(error); + XCTAssertEqual(uploaded.count, 0); + + NSArray *needUpload = [self logsUploaded:NO withError:&error]; + XCTAssertNil(error); + XCTAssertEqual(needUpload.count, 2); + } + + { + NSError *error = nil; + XCTAssertTrue([_dataLogger markFileUploaded:YES atURL:_finishedLogFiles[0] error:&error]); + XCTAssertNil(error); + + NSArray *uploaded = [self logsUploaded:YES withError:&error]; + XCTAssertNil(error); + XCTAssertEqual(uploaded.count, 1); + + NSURL *uploadedURL = [uploaded objectAtIndex:0]; + NSString *uploadedFileName = [[uploadedURL lastPathComponent] stringByDeletingPathExtension]; + + NSURL *finishedURL = [_finishedLogFiles objectAtIndex:0]; + NSString *finishedFileName = [[finishedURL lastPathComponent] stringByDeletingPathExtension]; + + XCTAssert([uploadedFileName isEqualToString: finishedFileName]); + + NSArray *needUpload = [self logsUploaded:NO withError:&error]; + XCTAssertNil(error); + + NSURL *needUploadedURL = [needUpload objectAtIndex:0]; + NSString *needUploadedFileName = [[needUploadedURL lastPathComponent] stringByDeletingPathExtension]; + + NSURL *notFinishedURL = [_finishedLogFiles objectAtIndex:1]; + NSString *notFinishedFileName = [[notFinishedURL lastPathComponent] stringByDeletingPathExtension]; + + XCTAssert([needUploadedFileName isEqualToString:notFinishedFileName]); + } +} + +- (void)testDataProtection { + _dataLogger.fileProtectionMode = ORKFileProtectionComplete; + + NSDictionary *jsonObject = @{@"test": @(1) }; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + NSError *error = nil; + XCTAssertTrue([_dataLogger append:jsonObject error:&error]); + XCTAssertNil(error); + + NSArray *logs= [self allLogsWithError:&error]; + XCTAssertNil(error); + XCTAssertEqual(logs.count, 1); + + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:logs[0]] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(jsonOut[@"items"][0], jsonObject); + +#if !TARGET_IPHONE_SIMULATOR + { + NSDictionary *attribs = [[NSFileManager defaultManager] attributesOfItemAtPath:[[_dataLogger currentLogFileURL] path] error:&error]; + XCTAssertNil(error); + XCTAssertTrue([attribs[NSFileProtectionKey] isEqualToString:ORKFileProtectionFromMode(_dataLogger.fileProtectionMode)]); + } + { + NSDictionary *attribs = [[NSFileManager defaultManager] attributesOfItemAtPath:[(NSURL *)logs[0] path] error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(attribs[NSFileProtectionKey], ORKFileProtectionFromMode(_dataLogger.fileProtectionMode)); + } +#endif +} + +- (void)testFileSizeLimitTriggersRollover { + _dataLogger.maximumCurrentLogFileSize = 50; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + NSDictionary *jsonObject = @{@"x": @"1234567890"}; + [self logJsonObject:jsonObject]; + [self logJsonObject:jsonObject]; + + [self wait]; + + XCTAssertTrue([[fileManager attributesOfItemAtPath:[[_dataLogger currentLogFileURL] path] error:nil] fileSize] < 50); + XCTAssertEqual(_finishedLogFiles.count, 0); + + [self logJsonObject:jsonObject]; + [self wait]; + XCTAssertTrue([[fileManager attributesOfItemAtPath:[[_dataLogger currentLogFileURL] path] error:nil] fileSize] < 50); + XCTAssertEqual(_finishedLogFiles.count, 1); + + XCTAssertTrue([[fileManager attributesOfItemAtPath:[(NSURL *)_finishedLogFiles[0] path] error:nil] fileSize] >= 50); + XCTAssertTrue([[fileManager attributesOfItemAtPath:[[_dataLogger currentLogFileURL] path] error:nil] fileSize] < 50); +} + +- (void)testFirstWriteOpensFilehandle { + XCTAssertNil([_dataLogger fileHandle]); + NSDictionary *jsonObject = @{@"x": @"1234567890"}; + [self logJsonObject:jsonObject]; + XCTAssertNotNil([_dataLogger fileHandle]); +} + +- (void)testExplicitRolloverBeforeHandleOpened { + XCTAssertNil([_dataLogger fileHandle]); + [_dataLogger finishCurrentLog]; + XCTAssertNil([_dataLogger fileHandle]); + [self wait]; + XCTAssertEqual(_finishedLogFiles.count, 0); +} + +- (void)testExplicitRolloverWithZeroLengthFile { + XCTAssertNil([_dataLogger fileHandle]); + NSDictionary *jsonObject = @{}; + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + XCTAssertNil([_dataLogger fileHandle]); + XCTAssertEqual(_finishedLogFiles.count, 1); + [self logJsonObjectAndRolloverAndWaitOnce:jsonObject]; + XCTAssertEqual(_finishedLogFiles.count, 2); +} + +- (void)testCurrentLogFileAlwaysHasValidJson { + NSDictionary *jsonObject = @{@"x": @"1234567890"}; + [self logJsonObject:jsonObject]; + { + NSError *error = nil; + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[_dataLogger currentLogFileURL]] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(jsonOut[@"items"][0], jsonObject); + } + [self logJsonObject:jsonObject]; + { + NSError *error = nil; + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[_dataLogger currentLogFileURL]] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(jsonOut[@"items"][1], jsonObject); + } +} + +- (void)testArrayWrite { + NSMutableArray *a = [NSMutableArray array]; + for (int i = 0; i < 100; i++) { + [a addObject:@{@"val": @(i)}]; + } + + NSError *error = nil; + BOOL success = [_dataLogger appendObjects:a error:&error]; + XCTAssertTrue(success); + XCTAssertNil(error); + + { + NSError *error = nil; + NSDictionary *jsonOut = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[_dataLogger currentLogFileURL]] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error); + for (int i = 0; i < 100; i++) { + XCTAssertEqualObjects(jsonOut[@"items"][i], @{@"val": @(i)}); + } + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKEnvironmentSPLMeterResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKEnvironmentSPLMeterResultTests.swift new file mode 100755 index 0000000..e59ca99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKEnvironmentSPLMeterResultTests.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest + +class ORKEnvironmentSPLMeterResultTests: XCTestCase { + + var result: ORKEnvironmentSPLMeterResult! + var identifer: String! + let date = Date() + + override func setUp() { + super.setUp() + identifer = "RESULT" + result = ORKEnvironmentSPLMeterResult(identifier: identifer) + result.sensitivityOffset = 40 + result.recordedSPLMeterSamples = [2] + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifer) + XCTAssertEqual(result.sensitivityOffset, 40) + XCTAssertEqual(result.recordedSPLMeterSamples, [2]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKEnvironmentSPLMeterResult(identifier: identifer) + newResult.sensitivityOffset = 40 + newResult.recordedSPLMeterSamples = [2] + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKHKSampleTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKHKSampleTests.m new file mode 100755 index 0000000..40b9331 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKHKSampleTests.m @@ -0,0 +1,111 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "HKSample+ORKJSONDictionary.h" + + +@interface ORKHKSampleTests : XCTestCase + +@end + + +@implementation ORKHKSampleTests + +- (void)testHKSampleSerialization { + NSDate *d1 = [NSDate dateWithTimeIntervalSinceReferenceDate:0]; + NSDate *d2 = [NSDate dateWithTimeInterval:10 sinceDate:d1]; + + NSString *identifier = HKQuantityTypeIdentifierStepCount; + HKQuantitySample *quantitySample = [HKQuantitySample quantitySampleWithType:[HKQuantityType quantityTypeForIdentifier:identifier] quantity:[HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:5] startDate:d1 endDate:d2]; + + NSDictionary *dict = [quantitySample ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) unit:[HKUnit countUnit]]; + + XCTAssertEqualObjects(dict[@"uuid"], [quantitySample UUID].UUIDString, @""); + XCTAssertEqualObjects(dict[@"type"], identifier, @""); + XCTAssertEqualObjects(dict[@"startDate"], ORKStringFromDateISO8601(d1), @""); + XCTAssertEqualObjects(dict[@"endDate"], ORKStringFromDateISO8601(d2), @""); + XCTAssertEqualObjects(dict[@"value"], @(5), @""); + XCTAssertNil(dict[@"sourceBundleIdentifier"], @""); + XCTAssertNil(dict[@"sourceName"], @""); + XCTAssertNil(dict[@"metadata"], @""); +} + +- (void)testHKMetadataSerialization { + NSDate *d1 = [NSDate dateWithTimeIntervalSinceReferenceDate:0]; + NSDate *d2 = [NSDate dateWithTimeInterval:10 sinceDate:d1]; + + NSDictionary *testMeta = @{@"k1": @"v1"}; + + NSString *identifier = HKQuantityTypeIdentifierStepCount; + HKQuantitySample *quantitySample = [HKQuantitySample quantitySampleWithType:[HKQuantityType quantityTypeForIdentifier:identifier] quantity:[HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:5] startDate:d1 endDate:d2 metadata:testMeta ]; + + // No metadata if not requested + NSDictionary *dict = [quantitySample ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeSource) unit:[HKUnit countUnit]]; + XCTAssertNil(dict[@"metadata"], @""); + + // Verify metadata appears when requested + dict = [quantitySample ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) unit:[HKUnit countUnit]]; + XCTAssertEqualObjects(testMeta, dict[@"metadata"], @""); +} + +- (void)testHKCorrelationSerialization { + NSDate *d1 = [NSDate dateWithTimeIntervalSinceReferenceDate:0]; + NSDate *d2 = [NSDate dateWithTimeInterval:10 sinceDate:d1]; + + NSString *identifier = HKCorrelationTypeIdentifierBloodPressure; + HKUnit *unit = [HKUnit unitFromString:@"mmHg"]; + HKQuantityType *diastolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic]; + HKQuantityType *systolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]; + HKQuantitySample *dPressure = [HKQuantitySample quantitySampleWithType:diastolicType quantity:[HKQuantity quantityWithUnit:unit doubleValue:70] startDate:d1 endDate:d2]; + HKQuantitySample *sPressure = [HKQuantitySample quantitySampleWithType:systolicType quantity:[HKQuantity quantityWithUnit:unit doubleValue:110] startDate:d1 endDate:d2]; + + HKCorrelation *correlation = [HKCorrelation correlationWithType:[HKCorrelationType correlationTypeForIdentifier:identifier] startDate:d1 endDate:d2 objects:[NSSet setWithObjects:dPressure, sPressure, nil]]; + + NSDictionary *dict = [correlation ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) sampleTypes:@[diastolicType,systolicType] units:@[unit, unit]]; + + NSDictionary *dd = [dPressure ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) unit:unit]; + NSDictionary *ds = [sPressure ork_JSONDictionaryWithOptions:(ORKSampleJSONOptions)(ORKSampleIncludeMetadata|ORKSampleIncludeSource|ORKSampleIncludeUUID) unit:unit]; + + XCTAssertEqualObjects(dict[@"uuid"], [correlation UUID].UUIDString, @""); + XCTAssertEqualObjects(dict[@"type"], identifier, @""); + XCTAssertEqualObjects(dict[@"startDate"], ORKStringFromDateISO8601(d1), @""); + XCTAssertEqualObjects(dict[@"endDate"], ORKStringFromDateISO8601(d2), @""); + XCTAssertNil(dict[@"sourceBundleIdentifier"], @""); + XCTAssertNil(dict[@"sourceName"], @""); + XCTAssertNil(dict[@"metadata"], @""); + XCTAssertTrue([dict[@"objects"] containsObject:dd], @""); + XCTAssertTrue([dict[@"objects"] containsObject:ds], @""); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKLoggingTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKLoggingTests.m new file mode 100755 index 0000000..bd7ff55 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKLoggingTests.m @@ -0,0 +1,91 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import XCTest; +#import + +@interface ORKLoggingTests : XCTestCase + +@end + +@implementation ORKLoggingTests + +- (void)setUp { +} + +- (void)tearDown { +} + +- (void)testDisablingLogging { + int stderrCopy = dup(STDERR_FILENO); + int pipefd[2]; + + pipe(pipefd); + dup2(pipefd[1], STDERR_FILENO); + close(pipefd[1]); + + NSFileHandle *stderrReader = [[NSFileHandle alloc] initWithFileDescriptor:pipefd[0]]; + + for (int i = 0; i < 2; ++i) { + ORK_Log("[$$OK_DEFAULT$$], self: %@, aThing: %d", self, 42); + ORK_Log_Info("[$$OK_INFO$$], self: %@, aThing: %d", self, 42); +// ORK_Log_Debug("[$$OK_DEBUG$$], self: %@, aThing: %d", self, 42); + ORK_Log_Error("[$$OK_ERROR$$], self: %@, aThing: %d", self, 42); + ORK_Log_Fault("[$$OK_FAULT$$], self: %@, aThing: %d", self, 42); + ORKLoggingEnabled = NO; + ORK_Log("[$$NOTOK_DEFAULT$$], self: %@, aThing: %d", self, 42); + ORK_Log_Info("[$$NOTOK_INFO$$], self: %@, aThing: %d", self, 42); + ORK_Log_Debug("[$$NOTOK_DEBUG$$], self: %@, aThing: %d", self, 42); + ORK_Log_Error("[$$NOTOK_ERROR$$], self: %@, aThing: %d", self, 42); + ORK_Log_Fault("[$$NOTOK_FAULT$$], self: %@, aThing: %d", self, 42); + + NSData *data = [stderrReader availableData]; + NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + XCTAssertTrue([output containsString:@"[$$OK_DEFAULT$$]"]); + XCTAssertTrue([output containsString:@"[$$OK_INFO$$]"]); +// XCTAssertTrue([output containsString:@"[$$OK_DEBUG$$]"]); + XCTAssertTrue([output containsString:@"[$$OK_ERROR$$]"]); + XCTAssertTrue([output containsString:@"[$$OK_FAULT$$]"]); + XCTAssertFalse([output containsString:@"[$$NOTOK_DEFAULT$$]"]); + XCTAssertFalse([output containsString:@"[$$NOTOK_INFO$$]"]); + XCTAssertFalse([output containsString:@"[$$NOTOK_DEBUG$$]"]); + XCTAssertFalse([output containsString:@"[$$NOTOK_ERROR$$]"]); + XCTAssertFalse([output containsString:@"[$$NOTOK_FAULT$$]"]); + + ORKLoggingEnabled = YES; + } + + close(pipefd[0]); + [stderrReader closeFile]; + dup2(stderrCopy, STDERR_FILENO); +} + + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeResultTests.swift new file mode 100755 index 0000000..96ba8b4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeResultTests.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +@testable import ResearchKit + +class ORKPasscodeResultTests: XCTestCase { + var result: ORKPasscodeResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKPasscodeResult(identifier: identifier) + result.isPasscodeSaved = true + result.isTouchIdEnabled = false + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.isPasscodeSaved, true) + XCTAssertEqual(result.isTouchIdEnabled, false) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKPasscodeResult(identifier: identifier) + newResult.isPasscodeSaved = true + newResult.isTouchIdEnabled = false + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(result)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeViewControllerTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeViewControllerTests.swift new file mode 100755 index 0000000..fe049f0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKPasscodeViewControllerTests.swift @@ -0,0 +1,159 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +@testable import ResearchKit +import ResearchKit.Private + +class ORKPasscodeViewControllerTests: XCTestCase { + + var testController: ORKPasscodeViewController! + var resultController: ORKPasscodeStepViewController? + var asyncExpectation: XCTestExpectation? + + func testPasscodeAuthenticationView() { + testController = ORKPasscodeViewController.passcodeAuthenticationViewController(withText: "TEST", delegate: self) + XCTAssertEqual(testController.navigationBar.isTranslucent, false) + XCTAssert(testController.navigationBar.shadowImage != nil) + + + guard let stepViewController = testController.viewControllers.first as? ORKPasscodeStepViewController, + let step = stepViewController.step as? ORKPasscodeStep else { + XCTFail("failed to cast step as ORKPascodeStep") + return + } + + XCTAssertEqual(step.identifier, "passcode_step") + XCTAssertEqual(step.passcodeFlow, ORKPasscodeFlow.authenticate) + XCTAssertEqual(step.passcodeType, ORKPasscodeType.type4Digit) + XCTAssertEqual(step.text, "TEST") + } + + func testPasscodeEditView() { + testController = ORKPasscodeViewController.passcodeEditingViewController(withText: "TEST", delegate: self, passcodeType: .type6Digit) + + guard let stepViewController = testController.viewControllers.first as? ORKPasscodeStepViewController, + let step = stepViewController.step as? ORKPasscodeStep else { + XCTFail("failed to cast step as ORKPascodeStep") + return + } + + XCTAssertEqual(step.passcodeFlow, ORKPasscodeFlow.edit) + XCTAssertEqual(step.passcodeType, ORKPasscodeType.type6Digit) + } + + func testPasscodeViewControllerDelegateCalls() { + testController = ORKPasscodeViewController.passcodeEditingViewController(withText: "TEST", delegate: self, passcodeType: .type4Digit) + + guard let stepController = testController.viewControllers.first as? ORKPasscodeStepViewController else { + XCTFail("unable to cast view controller as ORKPasscodeStepViewController") + return + } + + var testExpectation = expectation(description: "ORKPasscodeViewController calls the delegate as the result of the user authenticating or finishing editing") + self.asyncExpectation = testExpectation + + stepController.passcodeDelegate?.passcodeViewControllerDidFinish(withSuccess: stepController) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationWithTimeout error: \(error)") + } + } + + testExpectation = expectation(description: "ORKPasscodeViewController calls the delegate as the result of the user cancelling") + self.asyncExpectation = testExpectation + + stepController.passcodeDelegate?.passcodeViewControllerDidCancel?(stepController) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationWithTimeout error: \(error)") + } + } + + testExpectation = expectation(description: "ORKPasscodeViewController calls the delegate as the result of failed authentication") + self.asyncExpectation = testExpectation + + stepController.passcodeDelegate?.passcodeViewControllerDidFailAuthentication(stepController) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationWithTimeout error: \(error)") + } + } + + + testExpectation = expectation(description: "ORKPasscodeViewController calls the delegate as the result of user forgetting passcode") + self.asyncExpectation = testExpectation + + stepController.passcodeDelegate?.passcodeViewControllerForgotPasscodeTapped?(stepController) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationWithTimeout error: \(error)") + } + } + } +} + +extension ORKPasscodeViewControllerTests: ORKPasscodeDelegate { + func passcodeViewControllerDidFinish(withSuccess viewController: UIViewController) { + guard let expectation = asyncExpectation else { + XCTFail("Delegate was not setup correctly. Missing XCTExpectation reference") + return + } + expectation.fulfill() + } + + func passcodeViewControllerDidFailAuthentication(_ viewController: UIViewController) { + guard let expectation = asyncExpectation else { + XCTFail("Delegate was not setup correctly. Missing XCTExpectation reference") + return + } + expectation.fulfill() + } + + func passcodeViewControllerDidCancel(_ viewController: UIViewController) { + guard let expectation = asyncExpectation else { + XCTFail("Delegate was not setup correctly. Missing XCTExpectation reference") + return + } + expectation.fulfill() + } + + func passcodeViewControllerForgotPasscodeTapped(_ viewController: UIViewController) { + guard let expectation = asyncExpectation else { + XCTFail("Delegate was not setup correctly. Missing XCTExpectation reference") + return + } + expectation.fulfill() + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKRecorderTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKRecorderTests.m new file mode 100755 index 0000000..f7d3ffe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKRecorderTests.m @@ -0,0 +1,634 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +@import CoreLocation; +@import CoreMotion; + + +@interface ORKMockLocationManager : CLLocationManager + +@end + + +@implementation ORKMockLocationManager + +- (void)setPausesLocationUpdatesAutomatically:(BOOL)pausesLocationUpdatesAutomatically { + +} + +@end + + +@interface ORKMockLocationRecorder : ORKLocationRecorder + +@end + + +@implementation ORKMockLocationRecorder + +- (CLLocationManager *)createLocationManager { + return [[ORKMockLocationManager alloc] init]; +} + +@end + + +@interface ORKMockTouch : UITouch + +@end + + +@implementation ORKMockTouch + +- (CGPoint)locationInView:(UIView *)view { + return CGPointMake(11.0, 12.0); +} + +- (NSTimeInterval)timestamp { + return 3000.0; +} + +- (UITouchPhase)phase { + return UITouchPhaseMoved; +} + +@end + + +@interface ORKMockMotionManager : CMMotionManager + +- (void)injectMotion:(CMDeviceMotion *)motion; + +- (void)injectAccelerometerData:(CMAccelerometerData *)accelerometerData; + +@end + + +@implementation ORKMockMotionManager { + CMDeviceMotionHandler _motionHandler; + CMAccelerometerHandler _accelerometerHandler; +} + +- (void)startAccelerometerUpdates { + // override implementation and do nothing, fake data will be added via the inject method +} + +- (void)stopAccelerometerUpdates { + // override implementation and do nothing +} + +- (void)injectMotion:(CMDeviceMotion *)motion { + _motionHandler(motion, nil); +} + +- (void)injectAccelerometerData:(CMAccelerometerData *)accelerometerData { + _accelerometerHandler(accelerometerData, nil); +} + +- (void)startDeviceMotionUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMDeviceMotionHandler)handler { + _motionHandler = handler; +} + +- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler { + _accelerometerHandler = handler; +} + +- (BOOL)isAccelerometerAvailable { + return YES; +} + +- (BOOL)isDeviceMotionAvailable { + return YES; +} + +@end + + +@interface ORKMockPedometer : CMPedometer + +- (void)injectData:(CMPedometerData *)data; + +@end + + +@implementation ORKMockPedometer { + CMPedometerHandler _handler; +} + +- (void)injectData:(CMPedometerData *)data { + _handler(data, nil); +} + +- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler { + _handler = handler; +} + ++ (BOOL)isStepCountingAvailable { + return YES; +} + +@end + + +@interface ORKMockAccelerometerRecorder : ORKAccelerometerRecorder + +@property (nonatomic, strong) ORKMockMotionManager* mockManager; + +@end + + +@implementation ORKMockAccelerometerRecorder + +- (CMMotionManager *)createMotionManager { + return _mockManager; +} + +@end + + +@interface ORKMockAccelerometerData : CMAccelerometerData + +@end + + +@implementation ORKMockAccelerometerData + +- (CMAcceleration)acceleration { + return (CMAcceleration){.x=0.1, .y=0.12, .z=0.123}; +} + +- (NSTimeInterval)timestamp { + return 1000.0; +} + +@end + + +@interface ORKMockPedometerRecorder : ORKPedometerRecorder + +@property (nonatomic, strong) ORKMockPedometer* mockPedometer; + +@end + + +@implementation ORKMockPedometerRecorder + +- (CMPedometer *)createPedometer { + return _mockPedometer; +} + +@end + + +@interface ORKMockPedometerData : CMPedometerData + +@end + + +@implementation ORKMockPedometerData + +- (NSDate *)startDate { + return [NSDate dateWithTimeIntervalSinceReferenceDate:1000.0]; +} + +- (NSDate *)endDate { + return [NSDate dateWithTimeIntervalSinceReferenceDate:1001.0]; +} + +- (NSNumber *)numberOfSteps { + return @(2); +} + +- (NSNumber *)distance { + return @(1.2); +} + +- (NSNumber *)floorsAscended { + return @(0.1); +} + +- (NSNumber *)floorsDescended { + return @(0); +} + +@end + + +@interface ORKMockDeviceMotionRecorder : ORKDeviceMotionRecorder + +@property (nonatomic, strong) ORKMockMotionManager* mockManager; + +@end + + +@implementation ORKMockDeviceMotionRecorder + +- (CMMotionManager *)createMotionManager { + return _mockManager; +} + +@end + + +@interface ORKMockAttitude : CMAttitude + +@end + + +@implementation ORKMockAttitude + +- (CMQuaternion)quaternion { + return (CMQuaternion){.x=0.1, .y=0.12, .z=0.123, .w=0.1234}; +} + +@end + + +@interface ORKMockDeviceMotion : CMDeviceMotion + +@end + + +@implementation ORKMockDeviceMotion + +- (NSTimeInterval)timestamp { + return 1000.0; +} + +- (CMAttitude *)attitude { + return [ORKMockAttitude new]; +} + +- (CMRotationRate)rotationRate { + return (CMRotationRate){.x=0.1, .y=0.12, .z=0.123}; +} + +- (CMAcceleration)gravity { + return (CMAcceleration){.x=0.2, .y=0.23, .z=0.234}; +} + +- (CMAcceleration)userAcceleration { + return (CMAcceleration){.x=0.3, .y=0.34, .z=0.345}; +} + +- (CMCalibratedMagneticField)magneticField { + return (CMCalibratedMagneticField){.field=(CMMagneticField){.x=0.4, .y=0.45, .z=0.456}, .accuracy=CMMagneticFieldCalibrationAccuracyHigh}; +} + +@end + + +static BOOL ork_doubleEqual(double x, double y) { + static double K = 2; + return (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN); +} + +#pragma mark - ORKRecorderTests +#pragma mark - + +@interface ORKRecorderTests : XCTestCase + +@end + + +@implementation ORKRecorderTests { + NSString *_outputPath; + ORKRecorder *_recorder; + ORKResult *_result; + NSArray *_items; +} + +static const NSInteger kNumberOfSamples = 5; + +- (void)setUp { + [super setUp]; + + if (_outputPath == nil) { + + _outputPath = [NSBundle bundleForClass:[self class]].bundlePath; + _outputPath = [_outputPath stringByAppendingPathExtension:@"testdir"]; + NSError *error; + [[NSFileManager defaultManager] createDirectoryAtPath:_outputPath withIntermediateDirectories:YES attributes:nil error:&error]; + + if (error) { + ORK_Log_Error("Failed to create directory %@", error); + } + } + + _recorder = nil; + _result = nil; + _items = nil; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(ORKResult *)result { + ORK_Log_Debug("didCompleteWithResult: %@", result); + _recorder = recorder; + _result = result; +} + +- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error { + ORK_Log_Error("didFailWithError: %@", error); + _recorder = nil; + _result = nil; +} + +- (ORKRecorder *)createRecorder:(ORKRecorderConfiguration *)recorderConfiguration { + ORKRecorder *recorder = [recorderConfiguration recorderForStep:[[ORKStep alloc] initWithIdentifier:@"step"] + outputDirectory:[NSURL fileURLWithPath:_outputPath]]; + XCTAssert([recorder.identifier isEqualToString:recorderConfiguration.identifier], @""); + recorder.delegate = self; + return recorder; +} + +- (void)checkResult { + + XCTAssertNotNil(_result, @""); + XCTAssert([_result isKindOfClass:[ORKFileResult class]], @""); + XCTAssert([_recorder.identifier isEqualToString:_result.identifier], @""); + + ORKFileResult *fileResult = (ORKFileResult *)_result; + + NSError *error; + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:fileResult.fileURL ] options:(NSJSONReadingOptions)0 error:&error]; + XCTAssertNil(error, @""); + XCTAssertNotNil(dict, @""); + + NSArray *items = dict[@"items"]; + XCTAssertEqual(items.count, kNumberOfSamples, @""); + + _items = items; +} + +- (void)testLocationRecorder { + + ORKLocationRecorder *recorder = (ORKLocationRecorder *)[self createRecorder:[[ORKLocationRecorderConfiguration alloc] initWithIdentifier:@"location"]]; + XCTAssertTrue([recorder isKindOfClass:[ORKLocationRecorder class]], @""); + + recorder = [[ORKMockLocationRecorder alloc] initWithIdentifier:@"location" + step:recorder.step + outputDirectory:recorder.outputDirectory]; + recorder.delegate = self; + [recorder start]; + + id clDelegate = (id)recorder; + + double latitude = 37.31317; + double longitude = -122.07238159997; + double altitude = 11.0; + double horizontalAccuracy = 12.0; + double verticalAccuracy = 13.0; + double course = 14.0; + double speed = 15.0; + NSDate *timestamp = [NSDate date]; + + CLLocationManager *currentLocationManager = [recorder locationManager]; + + for (NSInteger i = 0; i < kNumberOfSamples; i++) { + CLLocation *location = [[CLLocation alloc] initWithCoordinate:CLLocationCoordinate2DMake(latitude, longitude) + altitude:altitude + horizontalAccuracy:horizontalAccuracy + verticalAccuracy:verticalAccuracy + course:course + speed:speed + timestamp:timestamp]; + + [clDelegate locationManager:currentLocationManager didUpdateLocations:@[location]]; + } + + [recorder stop]; + [self checkResult]; + + for (NSDictionary *sample in _items) { + + XCTAssertTrue(ork_doubleEqual(altitude, ((NSNumber *)sample[@"altitude"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(horizontalAccuracy, ((NSNumber *)sample[@"horizontalAccuracy"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(verticalAccuracy, ((NSNumber *)sample[@"verticalAccuracy"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(course, ((NSNumber *)sample[@"course"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(speed, ((NSNumber *)sample[@"speed"]).doubleValue), @""); + XCTAssertEqualObjects(ORKStringFromDateISO8601(timestamp), sample[@"timestamp"], @""); + XCTAssertTrue(ork_doubleEqual(latitude, ((NSNumber *)sample[@"coordinate"][@"latitude"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(longitude, ((NSNumber *)sample[@"coordinate"][@"longitude"]).doubleValue), @""); + } +} + +- (void)testAccelerometerRecorder { + + ORKAccelerometerRecorderConfiguration *recorderConfiguration = [[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"accelerometer" frequency:60.0]; + Class recorderClass = [ORKAccelerometerRecorder class]; + ORKAccelerometerRecorder *recorder = (ORKAccelerometerRecorder *)[self createRecorder:recorderConfiguration]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); + XCTAssertTrue([recorder.identifier isEqualToString:recorderConfiguration.identifier], @""); + + ORKMockAccelerometerRecorder *newRecorder = [[ORKMockAccelerometerRecorder alloc] initWithIdentifier:@"accelerometer" frequency:recorder.frequency step:recorder.step outputDirectory:recorder.outputDirectory]; + + newRecorder.delegate = self; + ORKMockMotionManager *manager = [ORKMockMotionManager new]; + [newRecorder setMockManager:manager]; + + ORKMockAccelerometerData *data = [ORKMockAccelerometerData new]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"Dummy expectation"]; + + [newRecorder start]; + + for (NSInteger i = 0; i < kNumberOfSamples; i++) { + [manager injectAccelerometerData:data]; + } + + [newRecorder stop]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + XCTAssert(self->_result!=nil, @"Data source has populated array after initializing"); + [expectation fulfill]; + }); + + + [self waitForExpectationsWithTimeout:20.0 handler:nil]; + [self checkResult]; + + for (NSDictionary *sample in _items) { + XCTAssertTrue(ork_doubleEqual(data.timestamp, ((NSNumber *)sample[@"timestamp"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(data.acceleration.x, ((NSNumber *)sample[@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(data.acceleration.y, ((NSNumber *)sample[@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(data.acceleration.z, ((NSNumber *)sample[@"z"]).doubleValue), @""); + } +} + +- (void)testDeviceMotionRecorder { + + ORKDeviceMotionRecorderConfiguration *recorderConfiguration = [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"deviceMotion" frequency:60.0]; + Class recorderClass = [ORKDeviceMotionRecorder class]; + ORKDeviceMotionRecorder *recorder = (ORKDeviceMotionRecorder *)[self createRecorder:recorderConfiguration]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); + + recorder = [[ORKMockDeviceMotionRecorder alloc] initWithIdentifier:@"deviceMotion" frequency:recorder.frequency step:recorder.step outputDirectory:recorder.outputDirectory]; + recorder.delegate = self; + ORKMockMotionManager *manager = [ORKMockMotionManager new]; + [(ORKMockAccelerometerRecorder*)recorder setMockManager:manager]; + + [recorder start]; + + ORKMockDeviceMotion *motion = [ORKMockDeviceMotion new]; + for (NSInteger i = 0; i < kNumberOfSamples; i++) { + [manager injectMotion:motion]; + } + + [recorder stop]; + [self checkResult]; + + for (NSDictionary *sample in _items) { + XCTAssertTrue(ork_doubleEqual(motion.timestamp, ((NSNumber *)sample[@"timestamp"]).doubleValue), @""); + + XCTAssertTrue(ork_doubleEqual(motion.attitude.quaternion.x, ((NSNumber *)sample[@"attitude"][@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.attitude.quaternion.y, ((NSNumber *)sample[@"attitude"][@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.attitude.quaternion.z, ((NSNumber *)sample[@"attitude"][@"z"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.attitude.quaternion.w, ((NSNumber *)sample[@"attitude"][@"w"]).doubleValue), @""); + + XCTAssertTrue(ork_doubleEqual(motion.gravity.x, ((NSNumber *)sample[@"gravity"][@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.gravity.y, ((NSNumber *)sample[@"gravity"][@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.gravity.z, ((NSNumber *)sample[@"gravity"][@"z"]).doubleValue), @""); + + XCTAssertTrue(ork_doubleEqual(motion.magneticField.accuracy, ((NSNumber *)sample[@"magneticField"][@"accuracy"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.magneticField.field.x, ((NSNumber *)sample[@"magneticField"][@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.magneticField.field.y, ((NSNumber *)sample[@"magneticField"][@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.magneticField.field.z, ((NSNumber *)sample[@"magneticField"][@"z"]).doubleValue), @""); + + XCTAssertTrue(ork_doubleEqual(motion.rotationRate.x, ((NSNumber *)sample[@"rotationRate"][@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.rotationRate.y, ((NSNumber *)sample[@"rotationRate"][@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.rotationRate.z, ((NSNumber *)sample[@"rotationRate"][@"z"]).doubleValue), @""); + + XCTAssertTrue(ork_doubleEqual(motion.userAcceleration.x, ((NSNumber *)sample[@"userAcceleration"][@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.userAcceleration.y, ((NSNumber *)sample[@"userAcceleration"][@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(motion.userAcceleration.z, ((NSNumber *)sample[@"userAcceleration"][@"z"]).doubleValue), @""); + } +} + +- (void)testPedometerRecorder { + + Class recorderClass = [ORKPedometerRecorder class]; + ORKPedometerRecorder *recorder = (ORKPedometerRecorder *)[self createRecorder:[[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:@"pedometer"]]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); + + recorder = [[ORKMockPedometerRecorder alloc] initWithIdentifier:@"pedometer" step:recorder.step outputDirectory:recorder.outputDirectory]; + recorder.delegate = self; + ORKMockPedometer *pedometer = [ORKMockPedometer new]; + [(ORKMockPedometerRecorder*)recorder setMockPedometer:pedometer]; + + [recorder start]; + + ORKMockPedometerData *data = [ORKMockPedometerData new]; + for (NSInteger i = 0; i < kNumberOfSamples; i++) { + [pedometer injectData:data]; + } + + [recorder stop]; + [self checkResult]; + + for (NSDictionary *sample in _items) { + + XCTAssertEqualObjects(ORKStringFromDateISO8601(data.startDate), sample[@"startDate"], @""); + XCTAssertEqualObjects(ORKStringFromDateISO8601(data.endDate), sample[@"endDate"], @""); + + XCTAssertTrue(ork_doubleEqual(data.distance.doubleValue, ((NSNumber *)sample[@"distance"]).doubleValue), @""); + XCTAssertEqual(data.numberOfSteps.integerValue, ((NSNumber *)sample[@"numberOfSteps"]).integerValue, @""); + XCTAssertTrue(ork_doubleEqual(data.floorsAscended.doubleValue, ((NSNumber *)sample[@"floorsAscended"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual(data.floorsDescended.doubleValue, ((NSNumber *)sample[@"floorsDescended"]).doubleValue), @""); + } +} + +- (void)testTouchRecorder { + + Class recorderClass = [ORKTouchRecorder class]; + ORKTouchRecorder *recorder = (ORKTouchRecorder *)[self createRecorder:[[ORKTouchRecorderConfiguration alloc] initWithIdentifier:@"touch"]]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); + + UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)]; + [recorder viewController:[UIViewController new] willStartStepWithView:view]; + [recorder start]; + + ORKMockTouch *touch = [ORKMockTouch new]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + + for (NSInteger i = 0; i < kNumberOfSamples; i++) { + [recorder performSelector:@selector(view:didDetectTouch:) withObject:view withObject:touch]; + } + +#pragma clang diagnostic pop + + [recorder stop]; + [self checkResult]; + + for (NSDictionary *sample in _items) { + + XCTAssertTrue(ork_doubleEqual([touch locationInView:nil].x, ((NSNumber *)sample[@"x"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual([touch locationInView:nil].y, ((NSNumber *)sample[@"y"]).doubleValue), @""); + XCTAssertTrue(ork_doubleEqual([touch timestamp], ((NSNumber *)sample[@"timestamp"]).doubleValue), @""); + XCTAssertEqual(view.bounds.size.width, ((NSNumber *)sample[@"width"]).floatValue, @""); + XCTAssertEqual(view.bounds.size.height, ((NSNumber *)sample[@"height"]).floatValue, @""); + XCTAssertEqual(0, ((NSNumber *)sample[@"index"]).integerValue, @""); + XCTAssertEqual([touch phase], ((NSNumber *)sample[@"phase"]).integerValue, @""); + } +} + +- (void)testAudioRecorder { + + ORKAudioRecorderConfiguration *recorderConfiguration = [[ORKAudioRecorderConfiguration alloc] initWithIdentifier:@"audio" recorderSettings:@{}]; + Class recorderClass = [ORKAudioRecorder class]; + ORKAudioRecorder *recorder = (ORKAudioRecorder *)[self createRecorder:recorderConfiguration]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); +} + +- (void)testHealthQuantityTypeRecorder { + + HKUnit *bpmUnit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]; + HKQuantityType *hbQuantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; + ORKHealthQuantityTypeRecorderConfiguration *recorderConfiguration = [[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:@"healtQuantityTypeRecorder" healthQuantityType:hbQuantityType unit:bpmUnit]; + Class recorderClass = [ORKHealthQuantityTypeRecorder class]; + ORKHealthQuantityTypeRecorder *recorder = (ORKHealthQuantityTypeRecorder *)[self createRecorder:recorderConfiguration]; + + XCTAssertTrue([recorder isKindOfClass:recorderClass], @""); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultPredicateTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultPredicateTests.swift new file mode 100755 index 0000000..99e298b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultPredicateTests.swift @@ -0,0 +1,152 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest + +class ORKResultPredicateTests: XCTestCase { + + var selector: ORKResultSelector! + var identifier: String! + + override func setUp() { + super.setUp() + identifier = "TESTING" + selector = ORKResultSelector(resultIdentifier: identifier) + } + + func testPredicateForBooleanQuestion() { + let predicate = ORKResultPredicate.predicateForBooleanQuestionResult(with: selector, expectedAnswer: true) + let predicateString = TestPredicateFormat.boolean + let expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForNilQuestion() { + let predicate = ORKResultPredicate.predicateForNilQuestionResult(with: selector) + let predicateString = TestPredicateFormat.nilPredicate + let expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicatedForConsent() { + let predicate = ORKResultPredicate.predicateForConsent(with: selector, didConsent: true) + let predicateString = TestPredicateFormat.consent + let expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForTextQuestion() { + let expectedString = "EXPECTED" + let predicate = ORKResultPredicate.predicateForTextQuestionResult(with: selector, expectedString: expectedString) + let predicateString = TestPredicateFormat.text + let expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier, expectedString) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForScaleQuestion() { + var predicate = ORKResultPredicate.predicateForScaleQuestionResult(with: selector, expectedAnswer: 5) + var predicateString = TestPredicateFormat.scale + var expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForScaleQuestionResult(with: selector, maximumExpectedAnswerValue: 20) + predicateString = TestPredicateFormat.scaleMax + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForScaleQuestionResult(with: selector, minimumExpectedAnswerValue: 10) + predicateString = TestPredicateFormat.scaleMin + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForChoiceQuestion() { + let pattern = "PATTERN" + var predicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: selector, matchingPattern: pattern) + var predicateString = TestPredicateFormat.choice + var expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier, pattern) + XCTAssert(predicate.isEqual(expectedPredicate)) + + let resultOne = ORKChoiceQuestionResult(identifier: "RESULT_ONE") + let resultTwo = ORKChoiceQuestionResult(identifier: "RESULT_TWO") + let results = [resultOne, resultTwo] + + predicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: selector, expectedAnswerValue: resultOne) + predicateString = TestPredicateFormat.choiceObject + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier, resultOne) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: selector, expectedAnswerValues: results) + predicateString = TestPredicateFormat.choiceObjects + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier, resultOne, resultTwo) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForNumericQuestion() { + var predicate = ORKResultPredicate.predicateForNumericQuestionResult(with: selector, expectedAnswer: 25) + var predicateString = TestPredicateFormat.numeric + var expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForNumericQuestionResult(with: selector, maximumExpectedAnswerValue: 50) + predicateString = TestPredicateFormat.numericMax + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForNumericQuestionResult(with: selector, minimumExpectedAnswerValue: 0) + predicateString = TestPredicateFormat.numericMin + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForTimeIntervalQuestion() { + var predicate = ORKResultPredicate.predicateForTimeIntervalQuestionResult(with: selector, maximumExpectedAnswerValue: 100) + var predicateString = TestPredicateFormat.timeMax + var expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForTimeIntervalQuestionResult(with: selector, minimumExpectedAnswerValue: 16) + predicateString = TestPredicateFormat.timeMin + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + + predicate = ORKResultPredicate.predicateForTimeIntervalQuestionResult(with: selector, minimumExpectedAnswerValue: 10, maximumExpectedAnswerValue: 1000) + predicateString = TestPredicateFormat.timeMinAndMax + expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } + + func testPredicateForTimeOfDayQuestion() { + let predicate = ORKResultPredicate.predicateForTimeOfDayQuestionResult(with: selector, minimumExpectedHour: 2, minimumExpectedMinute: 30, maximumExpectedHour: 10, maximumExpectedMinute: 10) + let predicateString = TestPredicateFormat.timeOfDay + let expectedPredicate = NSPredicate(format: predicateString.rawValue, identifier, identifier) + XCTAssert(predicate.isEqual(expectedPredicate)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultTests.m new file mode 100755 index 0000000..2393c0f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKResultTests.m @@ -0,0 +1,198 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKResultTests : XCTestCase + +@end + + +@implementation ORKResultTests + +- (ORKTaskResult *)createTaskResultTree { + // Construction + ORKFileResult *fileResult1 = [[ORKFileResult alloc] init]; + + NSURL *baseURL = [NSURL fileURLWithPath:NSHomeDirectory()]; + NSURL *standardizedBaseURL = [baseURL URLByStandardizingPath]; + fileResult1.fileURL = [NSURL fileURLWithPath:@"ResultFile" relativeToURL:standardizedBaseURL]; + fileResult1.contentType = @"file"; + + ORKTextQuestionResult *questionResult1 = [[ORKTextQuestionResult alloc] init]; + questionResult1.identifier = @"qid"; + questionResult1.answer = @"answer"; + questionResult1.questionType = ORKQuestionTypeText; + + ORKConsentSignatureResult *consentResult1 = [[ORKConsentSignatureResult alloc] init]; + consentResult1.signature = [[ORKConsentSignature alloc] init]; + + ORKStepResult *stepResult1 = [[ORKStepResult alloc] initWithStepIdentifier:@"StepIdentifier" results:@[fileResult1, questionResult1, consentResult1]]; + + ORKTaskResult *taskResult1 = [[ORKTaskResult alloc] initWithTaskIdentifier:@"TaskIdentifier" + taskRunUUID:[NSUUID UUID] + outputDirectory: [NSURL fileURLWithPath:@"OutputFile" relativeToURL:standardizedBaseURL]]; + taskResult1.results = @[stepResult1]; + return taskResult1; +} + +- (void)compareTaskResult1:(ORKTaskResult *)taskResult1 andTaskResult2:(ORKTaskResult *)taskResult2 { + // Compare + XCTAssert([taskResult1.taskRunUUID isEqual:taskResult2.taskRunUUID], @""); + XCTAssert([taskResult1.outputDirectory.absoluteString isEqualToString:taskResult2.outputDirectory.absoluteString], @""); + XCTAssert([taskResult1.identifier isEqualToString:taskResult2.identifier], @""); + + XCTAssert(taskResult1 != taskResult2, @""); + + [taskResult1.results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKResult *result1 = obj; + ORKResult *result2 = taskResult2.results[idx]; + XCTAssertNotNil(result2, @""); + XCTAssert(result1.class == result2.class); + XCTAssert(result2.class == ORKStepResult.class); + ORKStepResult *stepResult1 = (ORKStepResult *)result1; + ORKStepResult *stepResult2 = (ORKStepResult *)result2; + + XCTAssert(stepResult1 != stepResult2, @""); + + [stepResult1.results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + ORKResult *result1 = obj; + ORKResult *result2 = stepResult2.results[idx]; + XCTAssertNotNil(result2, @""); + XCTAssert(result1.class == result2.class); + XCTAssert([result1.startDate isEqualToDate: result2.startDate], @""); + XCTAssert([result1.endDate isEqualToDate: result2.endDate], @""); + + XCTAssert(result1 != result2, @""); + + if ([result1 isKindOfClass:[ORKQuestionResult class]]) { + ORKQuestionResult *q1 = (ORKQuestionResult *)result1; + ORKQuestionResult *q2 = (ORKQuestionResult *)result2; + + XCTAssert(q1.questionType == q2.questionType, @""); + if (![q1.answer isEqual:q2.answer]) { + XCTAssert([q1.answer isEqual:q2.answer], @""); + } + XCTAssert([q1.identifier isEqualToString:q2.identifier], @"%@ and %@", q1.identifier, q2.identifier); + } else if ([result1 isKindOfClass:[ORKFileResult class]]) { + ORKFileResult *f1 = (ORKFileResult *)result1; + ORKFileResult *f2 = (ORKFileResult *)result2; + + XCTAssert( [f1.fileURL.absoluteString isEqual:f2.fileURL.absoluteString], @""); + XCTAssert( [f1.contentType isEqualToString:f2.contentType], @""); + } else if ([result1 isKindOfClass:[ORKConsentSignatureResult class]]) { + ORKConsentSignatureResult *c1 = (ORKConsentSignatureResult *)result1; + ORKConsentSignatureResult *c2 = (ORKConsentSignatureResult *)result2; + + XCTAssert(c1.signature != c2.signature, @""); + } + }]; + }]; +} + +- (void)testResultSerialization { + ORKTaskResult *taskResult1 = [self createTaskResultTree]; + + // Archive + id data = [NSKeyedArchiver archivedDataWithRootObject:taskResult1]; + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; + unarchiver.requiresSecureCoding = YES; + ORKTaskResult *taskResult2 = [unarchiver decodeObjectOfClass:[ORKTaskResult class] forKey:NSKeyedArchiveRootObjectKey]; + + [self compareTaskResult1:taskResult1 andTaskResult2:taskResult2]; + XCTAssertEqualObjects(taskResult1, taskResult2); +} + +- (void)testResultCopy { + ORKTaskResult *taskResult1 = [self createTaskResultTree]; + + ORKTaskResult *taskResult2 = [taskResult1 copy]; + + [self compareTaskResult1:taskResult1 andTaskResult2:taskResult2]; + + XCTAssertEqualObjects(taskResult1, taskResult2); +} + +- (void)testCollectionResult { + ORKCollectionResult *result = [[ORKCollectionResult alloc] initWithIdentifier:@"001"]; + [result setResults:@[ [[ORKResult alloc]initWithIdentifier: @"101"], [[ORKResult alloc]initWithIdentifier: @"007"] ]]; + + ORKResult *childResult = [result resultForIdentifier:@"005"]; + XCTAssertNil(childResult, @"%@", childResult.identifier); + + childResult = [result resultForIdentifier:@"007"]; + XCTAssertEqual(childResult.identifier, @"007", @"%@", childResult.identifier); + + childResult = [result resultForIdentifier: @"101"]; + XCTAssertEqual(childResult.identifier, @"101", @"%@", childResult.identifier); +} + +- (void)testPageResult { + + NSArray *steps = @[[[ORKStep alloc] initWithIdentifier:@"step1"], + [[ORKStep alloc] initWithIdentifier:@"step2"], + [[ORKStep alloc] initWithIdentifier:@"step3"], + ]; + ORKPageStep *pageStep = [[ORKPageStep alloc] initWithIdentifier:@"pageStep" steps:steps]; + + ORKChoiceQuestionResult *step1Result1 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step1.result1"]; + step1Result1.choiceAnswers = @[ @(1) ]; + ORKChoiceQuestionResult *step1Result2 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step1.result2"]; + step1Result2.choiceAnswers = @[ @(2) ]; + ORKChoiceQuestionResult *step2Result1 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step2.result1"]; + step2Result1.choiceAnswers = @[ @(3) ]; + + ORKStepResult *inputResult = [[ORKStepResult alloc] initWithStepIdentifier:@"pageStep" + results:@[step1Result1, step1Result2, step2Result1]]; + + // Test that the page result creates ORKStepResults for each result that matches the prefix test + ORKPageResult *pageResult = [[ORKPageResult alloc] initWithPageStep:pageStep stepResult:inputResult]; + XCTAssertEqual(pageResult.results.count, 2); + + ORKStepResult *stepResult1 = [pageResult stepResultForStepIdentifier:@"step1"]; + XCTAssertNotNil(stepResult1); + XCTAssertEqual(stepResult1.results.count, 2); + + ORKStepResult *stepResult2 = [pageResult stepResultForStepIdentifier:@"step2"]; + XCTAssertNotNil(stepResult2); + XCTAssertEqual(stepResult2.results.count, 1); + + ORKStepResult *stepResult3 = [pageResult stepResultForStepIdentifier:@"step3"]; + XCTAssertNil(stepResult3); + + // Check that the flattened results match the input results + NSArray *flattedResults = [pageResult flattenResults]; + XCTAssertEqualObjects(inputResult.results, flattedResults); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSignatureResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSignatureResultTests.swift new file mode 100755 index 0000000..86cf395 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSignatureResultTests.swift @@ -0,0 +1,62 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest + +class ORKSignatureResultTests: XCTestCase { + var result: ORKSignatureResult! + var image: UIImage! + var path: UIBezierPath! + let date = Date() + + override func setUp() { + super.setUp() + let bundle = Bundle(identifier: "org.researchkit.ResearchKit") + image = UIImage(named: "heartbeat", in: bundle, compatibleWith: .none) + path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 50, height: 50)) + result = ORKSignatureResult(signatureImage: image, signaturePath: [path]) + } + + func testProperties() { + XCTAssertEqual(result.signatureImage, image) + XCTAssertEqual(result.signaturePath, [path]) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKSignatureResult(signatureImage: image, signaturePath: [path]) + newResult.startDate = date + newResult.endDate = date + + XCTAssert(result.isEqual(newResult)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepContainerViewTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepContainerViewTests.m new file mode 100755 index 0000000..4906feb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepContainerViewTests.m @@ -0,0 +1,216 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +@import ResearchKit; + + +static const NSString *LearnMoreStepIdentifierPrefix = @"ORKLearnMoreStepIdentifier"; + +@interface ORKStepContainerViewTests : XCTestCase + +@end + +@implementation ORKStepContainerViewTests { + int identifierNumber; + ORKLearnMoreItem *learnMoreItem; +} + +- (NSString *)generateLearnMoreStepIdentifier { + if (!identifierNumber) { + identifierNumber = 0; + } + identifierNumber = identifierNumber + 1; + return [LearnMoreStepIdentifierPrefix stringByAppendingString:[NSString stringWithFormat:@"%d",identifierNumber]]; +} + +- (NSArray *)bodyItemsWithAllAttributes { + learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:nil learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] initWithIdentifier:[self generateLearnMoreStepIdentifier]]]; + + return @[ + [[ORKBodyItem alloc] initWithText:@"Text1" + detailText:@"DetailText1" + image:[UIImage new] + learnMoreItem:[ORKLearnMoreItem learnMoreItemWithText:@"LearnMore" + learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] + initWithIdentifier:[self generateLearnMoreStepIdentifier]]] + bodyItemStyle:ORKBodyItemStyleText], + [[ORKBodyItem alloc] initWithText:@"Text2" + detailText:@"DetailText2" + image:[UIImage new] + learnMoreItem:learnMoreItem + bodyItemStyle:ORKBodyItemStyleBulletPoint] + ]; +} + +- (NSArray *)bodyItemsWithoutText { + learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:nil learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] initWithIdentifier:[self generateLearnMoreStepIdentifier]]]; + return @[ + [[ORKBodyItem alloc] initWithText:nil + detailText:@"DetailText1" + image:[UIImage new] + learnMoreItem:[ORKLearnMoreItem learnMoreItemWithText:@"LearnMore" + learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] + initWithIdentifier:[self generateLearnMoreStepIdentifier]]] + bodyItemStyle:ORKBodyItemStyleBulletPoint], + [[ORKBodyItem alloc] initWithText:nil + detailText:@"DetailText2" + image:[UIImage new] + learnMoreItem:learnMoreItem + bodyItemStyle:ORKBodyItemStyleImage] + ]; +} + +- (NSArray *)bodyItemsWithoutDetailText { + learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:nil learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] initWithIdentifier:[self generateLearnMoreStepIdentifier]]]; + return @[ + [[ORKBodyItem alloc] initWithText:@"Text1" + detailText:nil + image:[UIImage new] + learnMoreItem:[ORKLearnMoreItem learnMoreItemWithText:@"LearnMore" + learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] + initWithIdentifier:[self generateLearnMoreStepIdentifier]]] + bodyItemStyle:ORKBodyItemStyleImage], + [[ORKBodyItem alloc] initWithText:@"Text2" + detailText:nil + image:[UIImage new] + learnMoreItem:learnMoreItem + bodyItemStyle:ORKBodyItemStyleText] + ]; +} + +- (NSArray *)bodyItemsWithoutImages { + learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:nil learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] initWithIdentifier:[self generateLearnMoreStepIdentifier]]]; + return @[ + [[ORKBodyItem alloc] initWithText:@"Text1" + detailText:@"DetailText1" + image:nil + learnMoreItem:[ORKLearnMoreItem learnMoreItemWithText:@"LearnMore" + learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] + initWithIdentifier:[self generateLearnMoreStepIdentifier]]] + bodyItemStyle:ORKBodyItemStyleImage], + [[ORKBodyItem alloc] initWithText:@"Text2" + detailText:@"DetailText2" + image:nil + learnMoreItem:learnMoreItem + bodyItemStyle:ORKBodyItemStyleBulletPoint] + ]; +} + +- (NSArray *)bodyItemsWithoutLearnMoreItems { + return @[ + [[ORKBodyItem alloc] initWithText:@"Text1" + detailText:@"DetailText1" + image:[UIImage new] + learnMoreItem:nil + bodyItemStyle:ORKBodyItemStyleText], + [[ORKBodyItem alloc] initWithText:@"Text2" + detailText:@"DetailText2" + image:[UIImage new] + learnMoreItem:nil + bodyItemStyle:ORKBodyItemStyleText] + ]; +} + +- (void)testBodyItems { + + NSArray *bodyItems = [self bodyItemsWithoutText]; + for (ORKBodyItem *item in bodyItems) { + XCTAssertNil(item.text); + XCTAssertNotNil(item.detailText); + XCTAssertNotNil(item.image); + XCTAssertNotNil(item.learnMoreItem); + + XCTAssertLessThanOrEqual(item.bodyItemStyle, 2); + + } + XCTAssertEqual(bodyItems[0].detailText, @"DetailText1"); + XCTAssertEqual(bodyItems[1].detailText, @"DetailText2"); + XCTAssertEqual(bodyItems[0].learnMoreItem.text, @"LearnMore"); + XCTAssertNil(bodyItems[1].learnMoreItem.text); + + + bodyItems = [self bodyItemsWithoutDetailText]; + for (ORKBodyItem *item in bodyItems) { + XCTAssertNotNil(item.text); + XCTAssertNil(item.detailText); + XCTAssertNotNil(item.image); + XCTAssertNotNil(item.learnMoreItem); + + XCTAssertLessThanOrEqual(item.bodyItemStyle, 2); + } + XCTAssertEqual(bodyItems[0].text, @"Text1"); + XCTAssertEqual(bodyItems[1].text, @"Text2"); + XCTAssertEqual(bodyItems[0].learnMoreItem.text, @"LearnMore"); + XCTAssertNil(bodyItems[1].learnMoreItem.text); + + bodyItems = [self bodyItemsWithoutImages]; + for (ORKBodyItem *item in bodyItems) { + XCTAssertNotNil(item.text); + XCTAssertNotNil(item.detailText); + XCTAssertNil(item.image); + XCTAssertNotNil(item.learnMoreItem); + + XCTAssertLessThanOrEqual(item.bodyItemStyle, 2); + } + XCTAssertEqual(bodyItems[0].text, @"Text1"); + XCTAssertEqual(bodyItems[1].text, @"Text2"); + XCTAssertEqual(bodyItems[0].detailText, @"DetailText1"); + XCTAssertEqual(bodyItems[1].detailText, @"DetailText2"); + XCTAssertEqual(bodyItems[0].learnMoreItem.text, @"LearnMore"); + XCTAssertNil(bodyItems[1].learnMoreItem.text); + + bodyItems = [self bodyItemsWithoutLearnMoreItems]; + for (ORKBodyItem *item in bodyItems) { + XCTAssertNotNil(item.text); + XCTAssertNotNil(item.detailText); + XCTAssertNotNil(item.image); + XCTAssertNil(item.learnMoreItem); + } + + bodyItems = [self bodyItemsWithAllAttributes]; + for (ORKBodyItem *item in bodyItems) { + XCTAssertNotNil(item.text); + XCTAssertNotNil(item.detailText); + XCTAssertNotNil(item.image); + XCTAssertNotNil(item.learnMoreItem); + + XCTAssertLessThanOrEqual(item.bodyItemStyle, 2); + } + XCTAssertEqual(bodyItems[0].text, @"Text1"); + XCTAssertEqual(bodyItems[1].text, @"Text2"); + XCTAssertEqual(bodyItems[0].detailText, @"DetailText1"); + XCTAssertEqual(bodyItems[1].detailText, @"DetailText2"); + XCTAssertEqual(bodyItems[0].learnMoreItem.text, @"LearnMore"); + XCTAssertNil(bodyItems[1].learnMoreItem.text); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepTests.m new file mode 100755 index 0000000..2046a21 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepTests.m @@ -0,0 +1,539 @@ +/* + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit; +@import ResearchKit.Private; +@import UIKit; + +@interface ORKStepTests : XCTestCase + +@end + +@implementation ORKStepTests + +- (void)testAttributes { + ORKStep *step = [[ORKStep alloc] initWithIdentifier:@"STEP"]; + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"TASK" steps:NULL]; + ORKResult *result = [[ORKResult alloc] initWithIdentifier:@"RESULT"]; + + [step setTitle:@"Title"]; + [step setText:@"Text"]; + [step setTask:task]; + step.showsProgress = NO; + [step setDetailText:@"DETAIL"]; + [step setFootnote:@"FOOTNOTE"]; + + NSBundle *bundle = [NSBundle bundleWithIdentifier:@"org.researchkit.ResearchKit"]; + UIImage *imageOne = [UIImage imageNamed:@"heart-fitness" inBundle:bundle compatibleWithTraitCollection:nil]; + UIImage *imageTwo = [UIImage imageNamed:@"phoneshake" inBundle:bundle compatibleWithTraitCollection:nil]; + UIImage *imageThree = [UIImage imageNamed:@"heartbeat" inBundle:bundle compatibleWithTraitCollection:nil]; + [step setImage:imageOne]; + [step setAuxiliaryImage:imageTwo]; + [step setIconImage:imageThree]; + + ORKStepViewController *controller = [step instantiateStepViewControllerWithResult:result]; + + XCTAssertEqual([step title], @"Title"); + XCTAssertEqual([step text], @"Text"); + XCTAssertEqual([step task], task); + XCTAssertEqual([controller restorationIdentifier], [step identifier]); + XCTAssertEqual([controller restorationClass], [step stepViewControllerClass]); + XCTAssertEqual([controller step], step); + XCTAssertEqual([step stepViewControllerClass], [ORKStepViewController class]); + XCTAssertEqual([step isRestorable], YES); + XCTAssertEqual([step showsProgress], NO); + XCTAssert([step.identifier isEqualToString:@"STEP"]); + XCTAssert([step isEqual:step]); + XCTAssertFalse([step isEqual:@"TEST"]); + XCTAssertEqual([step requestedPermissions], ORKPermissionNone); + XCTAssertEqualObjects([step requestedHealthKitTypesForReading], nil); +} + +- (void)testCopyWithIdentifier { + NSString *firstIdentifier = @"STEP"; + ORKStep *step = [[ORKStep alloc] initWithIdentifier:firstIdentifier]; + step.title = @"TITLE"; + step.text = @"TEXT"; + + XCTAssertEqual(step.identifier, firstIdentifier); + + NSString *newIdentifier = @"NEW STEP"; + ORKStep *newStep = [step copyWithIdentifier:newIdentifier]; + + XCTAssertEqual(newStep.identifier, newIdentifier); + XCTAssertEqual(newStep.title, @"TITLE"); + XCTAssertEqual(newStep.text, @"TEXT"); +} + +- (void) testCopyWithZone { + ORKStep *step = [[ORKStep alloc] initWithIdentifier:@"STEP"]; + ORKStep *newStep = [step copyWithZone:nil]; + XCTAssert([newStep isEqual:step]); +} + +@end + +@interface ORKInstructionStepTests : XCTestCase + +@end + +@implementation ORKInstructionStepTests + +- (void)testAttributes { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step"]; + + [step setDetailText:@"DETAILS"]; + NSAttributedString *attributeString = [[NSAttributedString alloc] initWithString:@"ATTRIBUTE"]; + [step setAttributedDetailText:attributeString]; + [step setFootnote:@"FOOTNOTE"]; + + NSBundle *bundle = [NSBundle bundleWithIdentifier:@"org.researchkit.ResearchKit"]; + UIImage *image = [UIImage imageNamed:@"heartbeat" inBundle:bundle compatibleWithTraitCollection:nil]; + [step setImage:image]; + [step setAuxiliaryImage:image]; + [step setIconImage:image]; + + XCTAssert([step.detailText isEqualToString:@"DETAILS"]); + XCTAssertEqual(step.attributedDetailText, attributeString); + XCTAssert([step.footnote isEqualToString:@"FOOTNOTE"]); + XCTAssertEqual([step image], image); + XCTAssertEqual([step auxiliaryImage], image); + XCTAssertEqual([step iconImage], image); +} + +@end + + +@interface ORKFormStepTests : XCTestCase + +@end + +@implementation ORKFormStepTests + +- (void)testAttributes { + // Test duplicate form step identifier validation + ORKFormStep *formStep = [[ORKFormStep alloc] initWithIdentifier:@"form" title:@"Form" text:@"Form test"]; + NSMutableArray *items = [NSMutableArray new]; + + ORKFormItem *item = nil; + item = [[ORKFormItem alloc] initWithIdentifier:@"formItem1" + text:@"formItem1" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + [items addObject:item]; + + item = [[ORKFormItem alloc] initWithIdentifier:@"formItem2" + text:@"formItem2" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + [items addObject:item]; + + [formStep setFormItems:items]; + XCTAssertNoThrow([formStep validateParameters]); + + item = [[ORKFormItem alloc] initWithIdentifier:@"formItem2" + text:@"formItem2" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + [items addObject:item]; + + item = [[ORKFormItem alloc] initWithSectionTitle:@"formItem3" + detailText:@"formItem3" + learnMoreItem:[ORKLearnMoreItem learnMoreItemWithText:@"learnMoreItemText" learnMoreInstructionStep:[[ORKLearnMoreInstructionStep alloc] initWithIdentifier:@"instructionStepIdentifier"]] + showsProgress:YES]; + [items addObject:item]; + + XCTAssertEqual(item.text, @"formItem3"); + XCTAssertEqual(item.detailText, @"formItem3"); + XCTAssertNotNil(item.detailText); + XCTAssertNotNil(item.learnMoreItem); + XCTAssertTrue(item.showsProgress); + + item = [[ORKFormItem alloc] initWithSectionTitle:nil + detailText:nil + learnMoreItem:nil + showsProgress:NO]; + [items addObject:item]; + + XCTAssertNil(item.text); + XCTAssertNil(item.detailText); + XCTAssertNil(item.learnMoreItem); + XCTAssertFalse(item.showsProgress); + + [formStep setFormItems:items]; + XCTAssertThrows([formStep validateParameters]); +} + +@end + +@interface ORKReactionTimeStepTests : XCTestCase + +@end + +@implementation ORKReactionTimeStepTests + +- (void)testAttributes { + ORKReactionTimeStep *validReactionTimeStep = [[ORKReactionTimeStep alloc] initWithIdentifier:@"ReactionTimeStep"]; + + validReactionTimeStep.maximumStimulusInterval = 8; + validReactionTimeStep.minimumStimulusInterval = 4; + validReactionTimeStep.thresholdAcceleration = 0.5; + validReactionTimeStep.numberOfAttempts = 3; + validReactionTimeStep.timeout = 10; + + XCTAssertNoThrow([validReactionTimeStep validateParameters]); + + ORKReactionTimeStep *reactionTimeStep = [validReactionTimeStep copy]; + XCTAssertEqualObjects(reactionTimeStep, validReactionTimeStep); + + // minimumStimulusInterval cannot be zero or less + reactionTimeStep = [validReactionTimeStep copy]; + validReactionTimeStep.minimumStimulusInterval = 0; + XCTAssertThrows([validReactionTimeStep validateParameters]); + + // minimumStimulusInterval cannot be higher than maximumStimulusInterval + reactionTimeStep = [validReactionTimeStep copy]; + validReactionTimeStep.maximumStimulusInterval = 8; + validReactionTimeStep.minimumStimulusInterval = 10; + XCTAssertThrows([validReactionTimeStep validateParameters]); + + // thresholdAcceleration cannot be zero or less + reactionTimeStep = [validReactionTimeStep copy]; + validReactionTimeStep.thresholdAcceleration = 0; + XCTAssertThrows([validReactionTimeStep validateParameters]); + + // timeout cannot be zero or less + reactionTimeStep = [validReactionTimeStep copy]; + validReactionTimeStep.timeout = 0; + XCTAssertThrows([validReactionTimeStep validateParameters]); + + // numberOfAttempts cannot be zero or less + reactionTimeStep = [validReactionTimeStep copy]; + validReactionTimeStep.numberOfAttempts = 0; + XCTAssertThrows([validReactionTimeStep validateParameters]); +} + +@end + +@interface ORKPageStepTests : XCTestCase + +@end + +@implementation ORKPageStepTests + +- (void)testAttributes { + + NSArray *steps = @[[[ORKStep alloc] initWithIdentifier:@"step1"], + [[ORKStep alloc] initWithIdentifier:@"step2"], + [[ORKStep alloc] initWithIdentifier:@"step3"], + ]; + ORKPageStep *pageStep = [[ORKPageStep alloc] initWithIdentifier:@"pageStep" steps:steps]; + + ORKChoiceQuestionResult *step1Result1 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step1.result1"]; + step1Result1.choiceAnswers = @[ @(1) ]; + ORKChoiceQuestionResult *step1Result2 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step1.result2"]; + step1Result2.choiceAnswers = @[ @(2) ]; + ORKChoiceQuestionResult *step2Result1 = [[ORKChoiceQuestionResult alloc] initWithIdentifier:@"step2.result1"]; + step2Result1.choiceAnswers = @[ @(3) ]; + + ORKStepResult *inputResult = [[ORKStepResult alloc] initWithStepIdentifier:@"pageStep" + results:@[step1Result1, step1Result2, step2Result1]]; + + ORKPageResult *pageResult = [[ORKPageResult alloc] initWithPageStep:pageStep stepResult:inputResult]; + + // Check steps going forward + ORKStep *step1 = [pageStep stepAfterStepWithIdentifier:nil withResult:pageResult]; + XCTAssertNotNil(step1); + XCTAssertEqualObjects(step1.identifier, @"step1"); + + ORKStep *step2 = [pageStep stepAfterStepWithIdentifier:@"step1" withResult:pageResult]; + XCTAssertNotNil(step2); + XCTAssertEqualObjects(step2.identifier, @"step2"); + + ORKStep *step3 = [pageStep stepAfterStepWithIdentifier:@"step2" withResult:pageResult]; + XCTAssertNotNil(step3); + XCTAssertEqualObjects(step3.identifier, @"step3"); + + ORKStep *step4 = [pageStep stepAfterStepWithIdentifier:@"step3" withResult:pageResult]; + XCTAssertNil(step4); + + // Check steps going backward + ORKStep *backStep2 = [pageStep stepBeforeStepWithIdentifier:@"step3" withResult:pageResult]; + XCTAssertEqualObjects(backStep2, step2); + + ORKStep *backStep1 = [pageStep stepBeforeStepWithIdentifier:@"step2" withResult:pageResult]; + XCTAssertEqualObjects(backStep1, step1); + + ORKStep *backStepNil = [pageStep stepBeforeStepWithIdentifier:@"step1" withResult:pageResult]; + XCTAssertNil(backStepNil); + + // Check identifier + XCTAssertEqualObjects([pageStep stepWithIdentifier:@"step1"], step1); + XCTAssertEqualObjects([pageStep stepWithIdentifier:@"step2"], step2); + XCTAssertEqualObjects([pageStep stepWithIdentifier:@"step3"], step3); +} +@end + +@interface ORKNavigablePageStepTests : XCTestCase + +@end + +@implementation ORKNavigablePageStepTests + +- (void)testAttributes { + ORKQuestionStep *stepOne = [ORKQuestionStep questionStepWithIdentifier:@"stepOne" + title:@"QUESTION" + question:@"Which step do we go to?" + answer:[ORKAnswerFormat booleanAnswerFormat]]; + + ORKStep *stepTwo = [[ORKStep alloc] initWithIdentifier:@"stepTwo"]; + ORKStep *stepThree = [[ORKStep alloc] initWithIdentifier:@"stepThree"]; + ORKStep *stepFour = [[ORKStep alloc] initWithIdentifier:@"stepFour"]; + + NSArray *steps = [NSArray arrayWithObjects:stepOne, stepTwo, stepThree, stepFour, nil]; + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:@"task" steps:steps]; + + ORKBooleanQuestionResult *result = [[ORKBooleanQuestionResult alloc] initWithIdentifier:@"stepOne.result"]; + result.booleanAnswer = @(YES); + + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"stepOne" results:@[result]]; + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithIdentifier:@"task"]; + taskResult.results = @[stepResult]; + + // Creating predicates + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"stepOne" resultIdentifier:@"stepOne.result"]; + NSPredicate *stepOneYes = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:YES]; + NSPredicate *stepOneNo = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:NO]; + + // Creating navigation rule and setting it to task + ORKStepNavigationRule *navigationRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[stepOneYes, stepOneNo] + destinationStepIdentifiers:@[@"stepTwo", @"stepThree"] + defaultStepIdentifier:@"stepFour"]; + [task setNavigationRule:navigationRule forTriggerStepIdentifier:@"stepOne"]; + ORKNavigablePageStep *pageStep = [[ORKNavigablePageStep alloc] initWithIdentifier:@"pageStep" pageTask:task]; + + // Check step if answer is YES + ORKStep *nextStep = [pageStep stepAfterStepWithIdentifier:@"stepOne" withResult:taskResult]; + XCTAssert([nextStep.identifier isEqualToString:@"stepTwo"]); + + // Check step if answer is NO + result.booleanAnswer = @(NO); + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"stepOne" results:@[result]]; + taskResult.results = @[stepResult]; + nextStep = [pageStep stepAfterStepWithIdentifier:@"stepOne" withResult:taskResult]; + XCTAssert([nextStep.identifier isEqualToString:@"stepThree"]); + + // Check step if answer is NULL + result.booleanAnswer = NULL; + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"stepOne" results:@[result]]; + taskResult.results = @[stepResult]; + nextStep = [pageStep stepAfterStepWithIdentifier:@"stepOne" withResult:taskResult]; + XCTAssert([nextStep.identifier isEqualToString:@"stepFour"]); + +} + +@end + +@interface ORKPasscodeStepTests : XCTestCase + +@end + +@implementation ORKPasscodeStepTests + +- (void)testAttributes { + + ORKPasscodeStep *step = [ORKPasscodeStep passcodeStepWithIdentifier:@"STEP" passcodeFlow:ORKPasscodeFlowAuthenticate]; + XCTAssert([step.identifier isEqualToString:@"STEP"]); + XCTAssertEqual(step.passcodeFlow, ORKPasscodeFlowAuthenticate); + XCTAssertEqual(step.passcodeType, ORKPasscodeType4Digit); +} + +@end + +@interface ORKQuestionStepTests : XCTestCase + +@end + +@implementation ORKQuestionStepTests + +- (void)testAttributes { + NSString *identifier = @"Identifier"; + NSString *title = @"Title"; + NSString *question = @"How are you?"; + NSString *errorMessage = @"ERROR"; + NSString *placeHolder = @"PLACEHOLDER"; + + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormatWithMaximumLength:100]; + ORKConfirmTextAnswerFormat *incorrectAnswerFormat = [[ORKConfirmTextAnswerFormat alloc] initWithOriginalItemIdentifier:identifier errorMessage:errorMessage]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:identifier title:title question:question answer:answerFormat]; + [step setPlaceholder:placeHolder]; + [step setUseSurveyMode: NO]; + [step setUseCardView: NO]; + [step setOptional:NO]; + + XCTAssertEqual([step identifier], identifier); + XCTAssertEqual([step title], title); + XCTAssertEqual([step question], question); + XCTAssertEqual([step placeholder], placeHolder); + XCTAssertEqual([step useSurveyMode], NO); + XCTAssertEqual([step useCardView], NO); + XCTAssertEqual([step isOptional], NO); + XCTAssertNoThrowSpecificNamed([step validateParameters], NSException, NSInvalidArgumentException, @"Should not throw exception"); + XCTAssertEqual([step requestedHealthKitTypesForReading], nil); + XCTAssertEqual([step stepViewControllerClass], [ORKQuestionStepViewController class], @"Should return ORKQuestionStepViewController"); + XCTAssert([step isEqual:step]); + XCTAssertEqual([step questionType], ORKQuestionTypeText, @"Should return ORKQuestionTypeText"); + + ORKQuestionStep *incorrectStep = [ORKQuestionStep questionStepWithIdentifier:identifier title:title question:question answer:incorrectAnswerFormat]; + XCTAssertThrowsSpecificNamed([incorrectStep validateParameters], NSException, NSInvalidArgumentException); +} + +@end + +@interface ORKPDFViewerStepTests : XCTestCase + +@end + +@implementation ORKPDFViewerStepTests + +- (void)testAttributes { + NSString *identifier = @"STEP"; + NSURL *url = [NSURL URLWithString:@"TESTINGURL"]; + + ORKPDFViewerStep *step = [[ORKPDFViewerStep alloc] initWithIdentifier:identifier pdfURL:url]; + step.actionBarOption = ORKPDFViewerActionBarOptionExcludeShare; + + XCTAssertEqual([step identifier], identifier); + XCTAssertEqual([step pdfURL], url); + XCTAssertEqual([step actionBarOption], ORKPDFViewerActionBarOptionExcludeShare); +} + +@end + +@interface ORKRegistrationStepTests : XCTestCase + +@end + +@implementation ORKRegistrationStepTests + +- (void)testAttributes { + NSString *identifier = @"STEP"; + NSString *title = @"TITLE"; + NSString *text = @"TEXT"; + + NSString *pattern = @"^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{4,8}$"; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:nil]; + + ORKRegistrationStep *step = [[ORKRegistrationStep alloc] initWithIdentifier:identifier title:title text:text passcodeValidationRegularExpression:regex passcodeInvalidMessage:@"Invalid Password" options:ORKRegistrationStepIncludePhoneNumber]; + step.phoneNumberValidationRegularExpression = regex; + step.phoneNumberInvalidMessage = @"Invalid Number"; + + XCTAssertEqual([step identifier], identifier); + XCTAssertEqual([step title], title); + XCTAssertEqual([step text], text); + XCTAssertEqual([step options], ORKRegistrationStepIncludePhoneNumber); + XCTAssertEqual([step passcodeValidationRegularExpression], regex); + XCTAssertEqual([step passcodeInvalidMessage], @"Invalid Password"); + XCTAssertEqual([step phoneNumberValidationRegularExpression], regex); + XCTAssertEqual([step phoneNumberInvalidMessage], @"Invalid Number"); + XCTAssert([[[[step formItems] objectAtIndex:0] identifier] isEqualToString:@"ORKRegistrationFormItemEmail"]); + XCTAssert([[[[step formItems] objectAtIndex:1] identifier] isEqualToString:@"ORKRegistrationFormItemPassword"]); + XCTAssert([[[[step formItems] objectAtIndex:2] identifier] isEqualToString:@"ORKRegistrationFormItemConfirmPassword"]); +} + +@end + +@interface ORKWebViewStepTests: XCTestCase + +@end + +@implementation ORKWebViewStepTests + +- (void)testAttributes { + NSString *identifier = @"STEP"; + NSString *html = @"HTML"; + ORKWebViewStep *step = [ORKWebViewStep webViewStepWithIdentifier:identifier html:html]; + step.customCSS = @"body { font-size: 12px; }"; + + XCTAssertEqual([step identifier], identifier); + XCTAssertEqual([step html], html); + XCTAssertEqual([step stepViewControllerClass], [ORKWebViewStepViewController class]); + XCTAssert([step isEqual:step]); + + [step setHtml:nil]; + XCTAssertThrowsSpecificNamed([step validateParameters], NSException, NSInvalidArgumentException); +} + +@end + +@interface ORKLearnMoreInstructionStepTests : XCTestCase + +@end + +@implementation ORKLearnMoreInstructionStepTests + +- (void)testAttributes { + NSString *identifier = @"STEP"; + ORKLearnMoreInstructionStep *step = [[ORKLearnMoreInstructionStep alloc] initWithIdentifier:identifier]; + XCTAssertEqual([step identifier], identifier); +} + +@end + +@interface ORKEnvironmentSPLMeterStepTests : XCTestCase + +@end + +@implementation ORKEnvironmentSPLMeterStepTests + +- (void)testAttributes { + NSString *identifier = @"STEP"; + ORKEnvironmentSPLMeterStep *step = [[ORKEnvironmentSPLMeterStep alloc] initWithIdentifier:identifier]; + + XCTAssertEqual([step identifier], identifier); + XCTAssertNoThrow([step validateParameters]); + XCTAssertEqual([step thresholdValue], 35.0); + XCTAssertEqual([step samplingInterval], 1.0); + XCTAssertEqual([step requiredContiguousSamples], 5); + + [step setThresholdValue:-1]; + XCTAssertThrowsSpecificNamed([step validateParameters], NSException, NSInvalidArgumentException); + + [step setSamplingInterval:-1]; + [step setThresholdValue:0]; + XCTAssertThrowsSpecificNamed([step validateParameters], NSException, NSInvalidArgumentException); + + [step setRequiredContiguousSamples:0]; + [step setThresholdValue:2]; + XCTAssertThrowsSpecificNamed([step validateParameters], NSException, NSInvalidArgumentException); + + XCTAssert([step isEqual:step]); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerHelpers.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerHelpers.swift new file mode 100755 index 0000000..a6a2032 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerHelpers.swift @@ -0,0 +1,59 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +import UIKit + +class TopLevelUIUtilities { + + private var rootWindow: UIWindow! + + func setupTopLevelUI(withViewController viewController: T) { + rootWindow = UIWindow(frame: UIScreen.main.bounds) + rootWindow.isHidden = false + rootWindow.rootViewController = viewController + _ = viewController.view + viewController.viewWillAppear(false) + viewController.viewDidAppear(false) + } + + func tearDownTopLevelUI() { + guard let rootWindow = rootWindow, + let rootViewController = rootWindow.rootViewController as? T else { + XCTFail("tearDownTopLevelUI() was called without setupTopLevelUI() being called first") + return + } + rootViewController.viewWillDisappear(false) + rootViewController.viewDidDisappear(false) + rootWindow.rootViewController = nil + rootWindow.isHidden = true + self.rootWindow = nil + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerTests.swift new file mode 100755 index 0000000..44eb500 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKStepViewControllerTests.swift @@ -0,0 +1,279 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest +import ResearchKit + +class ORKStepViewControllerTests: XCTestCase { + + var testController: ORKStepViewController! + var step: ORKStep! + var result: ORKResult! + var negativeTest: Bool! + var forwardExpectation: XCTestExpectation! + var reverseExpectation: XCTestExpectation! + var testExpectation: XCTestExpectation! + var appearExpectation: XCTestExpectation! + var failExpectation: XCTestExpectation! + var recorderExpectation: XCTestExpectation! + var testingWillExpectation: Bool! + var utilities: TopLevelUIUtilities! + + override func setUp() { + super.setUp() + negativeTest = false + testingWillExpectation = false + + step = ORKStep(identifier: "STEP") + result = ORKResult(identifier: "RESULT") + testController = ORKStepViewController(step: step, result: result) + testController.delegate = self + + utilities = TopLevelUIUtilities() + utilities.setupTopLevelUI(withViewController: testController) + } + + func testAttributes() { + let backButton = UIBarButtonItem(title: "BACK", style: .plain, target: nil, action: nil) + let cancelButton = UIBarButtonItem(title: "CANCEL", style: .plain, target: nil, action: nil) + let countinueString = "COUNTINUE" + let learnMoreString = "LEARN MORE" + let skipString = "SKIP" + + testController.continueButtonTitle = countinueString + testController.learnMoreButtonTitle = learnMoreString + testController.skipButtonTitle = skipString + testController.backButtonItem = backButton + testController.cancelButtonItem = cancelButton + XCTAssertEqual(testController.continueButtonTitle, countinueString) + XCTAssertEqual(testController.skipButtonTitle, skipString) + XCTAssertEqual(testController.backButtonItem, backButton) + XCTAssertEqual(testController.cancelButtonItem, cancelButton) + } + + func testiPhoneViewDidLoad() { + let step = ORKStep(identifier: "STEP") + testController = ORKStepViewController(step: step) + testController.viewDidLoad() + XCTAssertEqual(testController.view.backgroundColor?.cgColor, ORKColor(ORKBackgroundColorKey).cgColor) + } + + func testViewWillAppear() { + testingWillExpectation = true + appearExpectation = expectation(description: "ORKStepViewController notifies delegate its status(Will Appear)") + + testController.viewWillAppear(false) + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + + XCTAssertEqual(testController.continueButtonItem, testController.internalContinueButtonItem) + XCTAssertEqual(testController.backButtonItem, nil) + + testController.delegate = nil + testController.viewWillAppear(false) + + XCTAssertEqual(testController.continueButtonItem, testController.internalDoneButtonItem) + XCTAssertEqual(testController.backButtonItem, nil) + XCTAssertEqual(testController.hasBeenPresented, true) + XCTAssert(testController.presentedDate != nil) + XCTAssertNil(testController.dismissedDate) + } + + + func testShowValidityAlertWithTitle() { + + var completed = testController.showValidityAlert(withMessage: "HELLO") + XCTAssert(completed, "Alert should display") + + completed = testController.showValidityAlert(withTitle: "", message: "") + XCTAssertFalse(completed, "Alert should not display") + + _ = testController.showValidityAlert(withMessage: "HELLO") + completed = testController.showValidityAlert(withMessage: "HELLO") + XCTAssertFalse(completed, "Alert should not display") + + testController.viewDidDisappear(true) + completed = testController.showValidityAlert(withMessage: "HELLO") + XCTAssertFalse(completed, "Alert should not display") + } + + func testNavigation() { + negativeTest = false + XCTAssertEqual(testController.hasPreviousStep(), true) + XCTAssertEqual(testController.hasNextStep(), true) + + negativeTest = true + XCTAssertEqual(testController.hasPreviousStep(), false) + XCTAssertEqual(testController.hasNextStep(), false) + } + + func testAddResult() { + let resultOne = ORKResult(identifier: "RESULT ONE") + testController.addResult(resultOne) + + XCTAssertEqual(testController.result?.results, [resultOne]) + + let resultTwo = ORKResult(identifier: "RESULT TWO") + testController.addResult(resultTwo) + XCTAssertEqual(testController.result?.results, [resultOne, resultTwo]) + + testController.addResult(resultOne) + XCTAssertEqual(testController.result?.results, [resultOne, resultOne, resultTwo]) + } + + func testGoForward() { + forwardExpectation = expectation(description: "ORKStepViewController notifies delegate with Forward Direction") + testController.goForward() + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + } + + func testGoBackward() { + reverseExpectation = expectation(description: "ORKStepViewController notifies delegate with Reverse Direction") + testController.goBackward() + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + } + + + func testResultDidChangeDelegate() { + testExpectation = expectation(description: "ORKStepViewController notifies delegate that results changed") + testController.notifyDelegateOnResultChange() + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + } + + + func testSkip() { + + forwardExpectation = expectation(description: "ORKStepViewController notifies delegate with Forward Direction") + + guard let skipButton = testController.skipButtonItem else { + XCTFail("failed to unwrap the skipButtonItem") + return + } + + _ = skipButton.target?.perform(skipButton.action, with: testController.view) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + + let reviewStep = ORKReviewStep(identifier: "REVIEW STEP") + testController.parentReviewStep = reviewStep + _ = skipButton.target?.perform(skipButton.action, with: testController.view) + + guard (testController.presentedViewController as? UIAlertController) != nil else { + XCTFail("alert was not presented") + return + } + } + + func testViewDelegates() { + failExpectation = expectation(description: "ORKStepViewController notifies delegate it did fail") + testController.delegate?.stepViewControllerDidFail(testController, withError: nil) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + + recorderExpectation = expectation(description: "ORKStepViewController notifies delegate that it's recorder failed") + let recorder = ORKRecorder(identifier: "RECORDER", step: nil, outputDirectory: nil) + testController!.delegate!.stepViewController(testController, recorder: recorder, didFailWithError: TestError.recorderError) + + waitForExpectations(timeout: 10) { (error) in + if let error = error { + XCTFail("waitForExpectationsWithTimeout errored: \(error)") + } + } + + } +} + +extension ORKStepViewControllerTests: ORKStepViewControllerDelegate { + func stepViewController(_ stepViewController: ORKStepViewController, didFinishWith direction: ORKStepViewControllerNavigationDirection) { + if direction == .forward { + forwardExpectation.fulfill() + } else { + reverseExpectation.fulfill() + } + } + + func stepViewControllerWillAppear(_ stepViewController: ORKStepViewController) { + if testingWillExpectation { + appearExpectation.fulfill() + } + } + + func stepViewControllerResultDidChange(_ stepViewController: ORKStepViewController) { + testExpectation.fulfill() + } + + func stepViewControllerDidFail(_ stepViewController: ORKStepViewController, withError error: Error?) { + failExpectation.fulfill() + } + + func stepViewController(_ stepViewController: ORKStepViewController, recorder: ORKRecorder, didFailWithError error: Error) { + recorderExpectation.fulfill() + } + + func stepViewControllerHasNextStep(_ stepViewController: ORKStepViewController) -> Bool { + if negativeTest { return false } + return true + } + + func stepViewControllerHasPreviousStep(_ stepViewController: ORKStepViewController) -> Bool { + if negativeTest { return false } + return true + } +} + +enum TestError: Error { + case recorderError +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSwiftStroopTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSwiftStroopTests.swift new file mode 100755 index 0000000..7a7f397 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKSwiftStroopTests.swift @@ -0,0 +1,81 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import XCTest +@testable import ResearchKit +import Foundation + +class ORKSwiftStroopStepTests: XCTestCase { + + var stroopStep: ORKSwiftStroopStep! + let identifier = "stroopStep" + let numberOfAttempts = 20 + + override func setUp() { + super.setUp() + stroopStep = ORKSwiftStroopStep(identifier: identifier) + stroopStep.numberOfAttempts = numberOfAttempts + } + + func testIdentifier() { + XCTAssertEqual(stroopStep.identifier, identifier) + } + + func testProperties() { + XCTAssertEqual(stroopStep.numberOfAttempts, numberOfAttempts) + } + + func testMethods() { + + XCTAssertTrue(stroopStep.stepViewControllerClass() === ORKSwiftStroopStepViewController.self) + } +} + +class ORKSStroopStepViewControllerTests: XCTestCase { + + var stroopStep: ORKSwiftStroopStep! + var stroopStepViewController: ORKSwiftStroopStepViewController! + let identifier = "stroopStep" + let numberOfAttempts = 20 + + override func setUp() { + super.setUp() + stroopStep = ORKSwiftStroopStep(identifier: identifier) + stroopStep.numberOfAttempts = numberOfAttempts + stroopStepViewController = ORKSwiftStroopStepViewController(step: stroopStep) + stroopStepViewController.viewDidLoad() + stroopStepViewController.start() + } + + func testProperties() { + XCTAssertEqual(stroopStepViewController.step, stroopStep) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTaskTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTaskTests.m new file mode 100755 index 0000000..38d37c7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTaskTests.m @@ -0,0 +1,1798 @@ +/* + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKTaskTests : XCTestCase + +@end + +@interface MethodObject : NSObject +@property (nonatomic) NSString *selectorName; +@property (nonatomic) NSArray *arguments; +@end + +@interface TestTaskViewControllerDelegate : NSObject +@property (nonatomic) NSMutableArray *methodCalled; +@end + +@interface MockTaskViewController : ORKTaskViewController +@property (nonatomic) NSMutableArray *methodCalled; +@end + + +@implementation ORKTaskTests { + NSArray *_orderedTaskStepIdentifiers; + NSArray *_orderedTaskSteps; + ORKOrderedTask *_orderedTask; + + NSArray *_navigableOrderedTaskStepIdentifiers; + NSArray *_navigableOrderedTaskSteps; + NSMutableDictionary *_stepNavigationRules; + ORKNavigableOrderedTask *_navigableOrderedTask; +} + +ORKDefineStringKey(HeadacheChoiceValue); +ORKDefineStringKey(DizzinessChoiceValue); +ORKDefineStringKey(NauseaChoiceValue); + +ORKDefineStringKey(SymptomStepIdentifier); +ORKDefineStringKey(SeverityStepIdentifier); +ORKDefineStringKey(BlankStepIdentifier); +ORKDefineStringKey(SevereHeadacheStepIdentifier); +ORKDefineStringKey(LightHeadacheStepIdentifier); +ORKDefineStringKey(OtherSymptomStepIdentifier); +ORKDefineStringKey(EndStepIdentifier); +ORKDefineStringKey(BlankBStepIdentifier); + +ORKDefineStringKey(OrderedTaskIdentifier); +ORKDefineStringKey(NavigableOrderedTaskIdentifier); + +- (void)generateTaskSteps:(out NSArray **)outSteps stepIdentifiers:(out NSArray **)outStepIdentifiers { + if (outSteps == NULL || outStepIdentifiers == NULL) { + return; + } + + NSMutableArray *stepIdentifiers = [NSMutableArray new]; + NSMutableArray *steps = [NSMutableArray new]; + + ORKAnswerFormat *answerFormat = nil; + NSString *stepIdentifier = nil; + ORKStep *step = nil; + + NSArray *textChoices = + @[ + [ORKTextChoice choiceWithText:@"Headache" value:HeadacheChoiceValue], + [ORKTextChoice choiceWithText:@"Dizziness" value:DizzinessChoiceValue], + [ORKTextChoice choiceWithText:@"Nausea" value:NauseaChoiceValue] + ]; + + answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + stepIdentifier = SymptomStepIdentifier; + step = [ORKQuestionStep questionStepWithIdentifier:stepIdentifier title:@"Survey" question:@"What is your symptom?" answer:answerFormat]; + step.optional = NO; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + answerFormat = [ORKAnswerFormat booleanAnswerFormat]; + stepIdentifier = SeverityStepIdentifier; + step = [ORKQuestionStep questionStepWithIdentifier:stepIdentifier title:@"Survey" question:@"Does your symptom interferes with your daily life?" answer:answerFormat]; + step.optional = NO; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = BlankStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"This step is intentionally left blank (you should not see it)"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = SevereHeadacheStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"You have a severe headache"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = LightHeadacheStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"You have a light headache"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = OtherSymptomStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"You have other symptom"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = EndStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"You have finished the task"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + stepIdentifier = BlankBStepIdentifier; + step = [[ORKInstructionStep alloc] initWithIdentifier:stepIdentifier]; + step.title = @"This step is intentionally left blank (you should not see it)"; + [stepIdentifiers addObject:stepIdentifier]; + [steps addObject:step]; + + *outSteps = steps; + *outStepIdentifiers = stepIdentifiers; +} + +- (void)setUpOrderedTask { + NSArray *orderedTaskSteps = nil; + NSArray *orderedTaskStepIdentifiers = nil; + [self generateTaskSteps:&orderedTaskSteps stepIdentifiers:&orderedTaskStepIdentifiers]; + _orderedTaskSteps = orderedTaskSteps; + _orderedTaskStepIdentifiers = orderedTaskStepIdentifiers; + + _orderedTask = [[ORKOrderedTask alloc] initWithIdentifier:OrderedTaskIdentifier + steps:ORKArrayCopyObjects(_orderedTaskSteps)]; // deep copy to test step copying and equality +} + +- (void)setUpNavigableOrderedTask { + ORKResultSelector *resultSelector = nil; + NSArray *navigableOrderedTaskSteps = nil; + NSArray *navigableOrderedTaskStepIdentifiers = nil; + [self generateTaskSteps:&navigableOrderedTaskSteps stepIdentifiers:&navigableOrderedTaskStepIdentifiers]; + _navigableOrderedTaskSteps = navigableOrderedTaskSteps; + _navigableOrderedTaskStepIdentifiers = navigableOrderedTaskStepIdentifiers; + + _navigableOrderedTask = [[ORKNavigableOrderedTask alloc] initWithIdentifier:NavigableOrderedTaskIdentifier + steps:ORKArrayCopyObjects(_navigableOrderedTaskSteps)]; // deep copy to test step copying and equality + + // Build navigation rules + _stepNavigationRules = [NSMutableDictionary new]; + // Individual predicates + + // User chose headache at the symptom step + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:SymptomStepIdentifier]; + NSPredicate *predicateHeadache = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:HeadacheChoiceValue]; + // Equivalent to: + // [NSPredicate predicateWithFormat: + // @"SUBQUERY(SELF, $x, $x.identifier like 'symptom' \ + // AND SUBQUERY($x.answer, $y, $y like 'headache').@count > 0).@count > 0"]; + + // User didn't chose headache at the symptom step + NSPredicate *predicateNotHeadache = [NSCompoundPredicate notPredicateWithSubpredicate:predicateHeadache]; + + // User chose YES at the severity step + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:SeverityStepIdentifier]; + NSPredicate *predicateSevereYes = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:YES]; + // Equivalent to: + // [NSPredicate predicateWithFormat: + // @"SUBQUERY(SELF, $x, $x.identifier like 'severity' AND $x.answer == YES).@count > 0"]; + + // User chose NO at the severity step + NSPredicate *predicateSevereNo = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:NO]; + + + // From the "symptom" step, go to "other_symptom" is user didn't chose headache. + // Otherwise, default to going to next step (when the defaultStepIdentifier argument is omitted, + // the regular ORKOrderedTask order applies). + NSMutableArray *resultPredicates = [NSMutableArray new]; + NSMutableArray *destinationStepIdentifiers = [NSMutableArray new]; + + [resultPredicates addObject:predicateNotHeadache]; + [destinationStepIdentifiers addObject:OtherSymptomStepIdentifier]; + + ORKPredicateStepNavigationRule *predicateRule = + [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers]; + + [_navigableOrderedTask setNavigationRule:predicateRule forTriggerStepIdentifier:SymptomStepIdentifier]; + _stepNavigationRules[SymptomStepIdentifier] = [predicateRule copy]; + + // From the "severity" step, go to "severe_headache" or "light_headache" depending on the user answer + resultPredicates = [NSMutableArray new]; + destinationStepIdentifiers = [NSMutableArray new]; + + NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateHeadache, predicateSevereYes]]; + [resultPredicates addObject:predicate]; + [destinationStepIdentifiers addObject:SevereHeadacheStepIdentifier]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateHeadache, predicateSevereNo]]; + [resultPredicates addObject:predicate]; + [destinationStepIdentifiers addObject:LightHeadacheStepIdentifier]; + + predicateRule = + [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers + defaultStepIdentifier:OtherSymptomStepIdentifier]; + + [_navigableOrderedTask setNavigationRule:predicateRule forTriggerStepIdentifier:SeverityStepIdentifier]; + _stepNavigationRules[SeverityStepIdentifier] = [predicateRule copy]; + + + // Add end direct rules to skip unneeded steps + ORKDirectStepNavigationRule *directRule = nil; + + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:EndStepIdentifier]; + + [_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:SevereHeadacheStepIdentifier]; + [_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:LightHeadacheStepIdentifier]; + [_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:OtherSymptomStepIdentifier]; + + _stepNavigationRules[SevereHeadacheStepIdentifier] = [directRule copy]; + _stepNavigationRules[LightHeadacheStepIdentifier] = [directRule copy]; + _stepNavigationRules[OtherSymptomStepIdentifier] = [directRule copy]; + + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKNullStepIdentifier]; + [_navigableOrderedTask setNavigationRule:directRule forTriggerStepIdentifier:EndStepIdentifier]; + _stepNavigationRules[EndStepIdentifier] = [directRule copy]; +} + +typedef NS_OPTIONS(NSUInteger, TestsTaskResultOptions) { + TestsTaskResultOptionSymptomHeadache = 1 << 0, + TestsTaskResultOptionSymptomDizziness = 1 << 1, + TestsTaskResultOptionSymptomNausea = 1 << 2, + + TestsTaskResultOptionSeverityYes = 1 << 3, + TestsTaskResultOptionSeverityNo = 1 << 4 +}; + +- (ORKTaskResult *)getResultTreeWithTaskIdentifier:(NSString *)taskIdentifier resultOptions:(TestsTaskResultOptions)resultOptions { + if ( ((resultOptions & TestsTaskResultOptionSymptomDizziness) || (resultOptions & TestsTaskResultOptionSymptomNausea)) && ((resultOptions & TestsTaskResultOptionSeverityYes) || (resultOptions & TestsTaskResultOptionSeverityNo)) ) { + @throw [NSException exceptionWithName:NSGenericException reason:@"You can only add a severity result for the headache symptom" userInfo:nil]; + } + + NSMutableArray *stepResults = [NSMutableArray new]; + + ORKQuestionResult *questionResult = nil; + ORKStepResult *stepResult = nil; + NSString *stepIdentifier = nil; + + if (resultOptions & (TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSymptomDizziness | TestsTaskResultOptionSymptomNausea)) { + stepIdentifier = SymptomStepIdentifier; + questionResult = [[ORKChoiceQuestionResult alloc] init]; + questionResult.identifier = stepIdentifier; + if (resultOptions & TestsTaskResultOptionSymptomHeadache) { + questionResult.answer = @[HeadacheChoiceValue]; + } else if (resultOptions & TestsTaskResultOptionSymptomDizziness) { + questionResult.answer = @[DizzinessChoiceValue]; + } else if (resultOptions & TestsTaskResultOptionSymptomNausea) { + questionResult.answer = @[NauseaChoiceValue]; + } + questionResult.questionType = ORKQuestionTypeSingleChoice; + + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]]; + [stepResults addObject:stepResult]; + + if (resultOptions & (TestsTaskResultOptionSymptomDizziness | TestsTaskResultOptionSymptomNausea)) { + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:OtherSymptomStepIdentifier results:nil]; + [stepResults addObject:stepResult]; + } + } + + if (resultOptions & (TestsTaskResultOptionSeverityYes | TestsTaskResultOptionSeverityNo)) { + stepIdentifier = SeverityStepIdentifier; + questionResult = [[ORKBooleanQuestionResult alloc] init]; + questionResult.identifier = stepIdentifier; + if (resultOptions & TestsTaskResultOptionSeverityYes) { + questionResult.answer = @(YES); + } else if (resultOptions & TestsTaskResultOptionSeverityNo) { + questionResult.answer = @(NO); + } + questionResult.questionType = ORKQuestionTypeSingleChoice; + + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]]; + [stepResults addObject:stepResult]; + + + if (resultOptions & TestsTaskResultOptionSeverityYes) { + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:SevereHeadacheStepIdentifier results:nil]; + [stepResults addObject:stepResult]; + } else if (resultOptions & TestsTaskResultOptionSeverityNo) { + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:LightHeadacheStepIdentifier results:nil]; + [stepResults addObject:stepResult]; + } + } + + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:EndStepIdentifier results:nil]; + [stepResults addObject:stepResult]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:taskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + +- (void)setUp { + [super setUp]; + [self setUpOrderedTask]; + [self setUpNavigableOrderedTask]; +} + +- (void)testOrderedTask { + ORKTaskResult *mockTaskResult = [[ORKTaskResult alloc] init]; + + XCTAssertEqualObjects(_orderedTask.identifier, OrderedTaskIdentifier); + XCTAssertEqualObjects(_orderedTask.steps, _orderedTaskSteps); + + NSUInteger expectedTotalProgress = _orderedTaskSteps.count; + + for (ORKStep *step in _orderedTaskSteps) { + ORKTaskProgress currentProgress = [_orderedTask progressOfCurrentStep:step withResult:mockTaskResult]; + if (!currentProgress.shouldBePresented) { + expectedTotalProgress -= 1; + } + } + + for (NSUInteger stepIndex = 0; stepIndex < _orderedTaskStepIdentifiers.count; stepIndex++) { + ORKStep *currentStep = _orderedTaskSteps[stepIndex]; + XCTAssertEqualObjects(currentStep, [_orderedTask stepWithIdentifier:_orderedTaskStepIdentifiers[stepIndex]]); + + ORKTaskProgress currentProgress = [_orderedTask progressOfCurrentStep:currentStep withResult:mockTaskResult]; + + if (currentProgress.shouldBePresented) { + const NSUInteger expectedCurrentProgress = stepIndex; + XCTAssertEqual(currentProgress.total, expectedTotalProgress); + XCTAssertEqual(currentProgress.current, expectedCurrentProgress); + } + + NSString *expectedPreviousStep = (stepIndex != 0) ? _orderedTaskSteps[stepIndex - 1] : nil; + NSString *expectedNextStep = (stepIndex < _orderedTaskStepIdentifiers.count - 1) ? _orderedTaskSteps[stepIndex + 1] : nil; + XCTAssertEqualObjects(expectedPreviousStep, [_orderedTask stepBeforeStep:currentStep withResult:mockTaskResult]); + XCTAssertEqualObjects(expectedNextStep, [_orderedTask stepAfterStep:currentStep withResult:mockTaskResult]); + } + + // Test duplicate step identifier validation + XCTAssertNoThrow([_orderedTask validateParameters]); + + NSMutableArray *steps = [[NSMutableArray alloc] initWithArray:ORKArrayCopyObjects(_orderedTaskSteps)]; + ORKStep *step = [[ORKInstructionStep alloc] initWithIdentifier:BlankStepIdentifier]; + [steps addObject:step]; + + XCTAssertThrows([[ORKOrderedTask alloc] initWithIdentifier:OrderedTaskIdentifier + steps:steps]); +} + +#define getIndividualNavigableOrderedTaskSteps() \ +__unused ORKStep *symptomStep = _navigableOrderedTaskSteps[0];\ +__unused ORKStep *severityStep = _navigableOrderedTaskSteps[1];\ +__unused ORKStep *blankStep = _navigableOrderedTaskSteps[2];\ +__unused ORKStep *severeHeadacheStep = _navigableOrderedTaskSteps[3];\ +__unused ORKStep *lightHeadacheStep = _navigableOrderedTaskSteps[4];\ +__unused ORKStep *otherSymptomStep = _navigableOrderedTaskSteps[5];\ +__unused ORKStep *endStep = _navigableOrderedTaskSteps[6]; + +BOOL (^testStepAfterStep)(ORKNavigableOrderedTask *, ORKTaskResult *, ORKStep *, ORKStep *) = ^BOOL(ORKNavigableOrderedTask *task, ORKTaskResult *taskResult, ORKStep *fromStep, ORKStep *expectedStep) { + ORKStep *testedStep = [task stepAfterStep:fromStep withResult:taskResult]; + return (testedStep == nil && expectedStep == nil) || [testedStep isEqual:expectedStep]; +}; + +BOOL (^testStepBeforeStep)(ORKNavigableOrderedTask *, ORKTaskResult *, ORKStep *, ORKStep *) = ^BOOL(ORKNavigableOrderedTask *task, ORKTaskResult *taskResult, ORKStep *fromStep, ORKStep *expectedStep) { + ORKStep *testedStep = [task stepBeforeStep:fromStep withResult:taskResult]; + return (testedStep == nil && expectedStep == nil) || [testedStep isEqual:expectedStep]; +}; + +- (void)testNavigableOrderedTask { + XCTAssertEqualObjects(_navigableOrderedTask.identifier, NavigableOrderedTaskIdentifier); + XCTAssertEqualObjects(_navigableOrderedTask.steps, _navigableOrderedTaskSteps); + XCTAssertEqualObjects(_navigableOrderedTask.stepNavigationRules, _stepNavigationRules); + + for (NSString *triggerStepIdentifier in [_stepNavigationRules allKeys]) { + XCTAssertEqualObjects(_stepNavigationRules[triggerStepIdentifier], [_navigableOrderedTask navigationRuleForTriggerStepIdentifier:triggerStepIdentifier]); + } + + ORKDefineStringKey(MockTriggerStepIdentifier); + ORKDefineStringKey(MockDestinationStepIdentifier); + + // Test adding and removing a step navigation rule + XCTAssertNil([_navigableOrderedTask navigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier]); + + ORKDirectStepNavigationRule *mockNavigationRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:MockDestinationStepIdentifier]; + [_navigableOrderedTask setNavigationRule:mockNavigationRule forTriggerStepIdentifier:MockTriggerStepIdentifier]; + + XCTAssertEqualObjects([_navigableOrderedTask navigationRuleForTriggerStepIdentifier:MockTriggerStepIdentifier], [mockNavigationRule copy]); + + ORKPredicateSkipStepNavigationRule *mockSkipNavigationRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:[NSPredicate predicateWithFormat:@"1 == 1"]]; + [_navigableOrderedTask setSkipNavigationRule:mockSkipNavigationRule forStepIdentifier:MockTriggerStepIdentifier]; + + XCTAssertEqualObjects([_navigableOrderedTask skipNavigationRuleForStepIdentifier:MockTriggerStepIdentifier], [mockSkipNavigationRule copy]); + + [_navigableOrderedTask removeSkipNavigationRuleForStepIdentifier:MockTriggerStepIdentifier]; + XCTAssertNil([_navigableOrderedTask skipNavigationRuleForStepIdentifier:MockTriggerStepIdentifier]); +} + +- (void)testNavigableOrderedTaskEmpty { + getIndividualNavigableOrderedTaskSteps(); + + // + // Empty task result + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:0]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, otherSymptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, otherSymptomStep, endStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil)); + + // Test absent backward navigation + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, nil)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, nil)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); + + // Test unreachable nodes + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, otherSymptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, blankStep, severeHeadacheStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severeHeadacheStep, endStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severeHeadacheStep, nil)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, lightHeadacheStep, endStep)); + +} + +- (void)testNavigableOrderedTaskHeadache { + getIndividualNavigableOrderedTaskSteps(); + + // + // Only headache symptom question step answered + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityYes]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, severeHeadacheStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severeHeadacheStep, endStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil)); + + // Test backward navigation + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, severeHeadacheStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severeHeadacheStep, severityStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); +} + +- (void)testNavigableOrderedTaskDizziness { + getIndividualNavigableOrderedTaskSteps(); + + // + // Only dizziness symptom question answered + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomDizziness]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, otherSymptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, otherSymptomStep, endStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil)); + + // Test backward navigation + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, otherSymptomStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, otherSymptomStep, symptomStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); +} + +- (void)testNavigableOrderedTaskSevereHeadache { + getIndividualNavigableOrderedTaskSteps(); + + // + // Severe headache sequence + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityYes]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, severeHeadacheStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severeHeadacheStep, endStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil)); + + // Test backward navigation + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, severeHeadacheStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severeHeadacheStep, severityStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); +} + +- (void)testNavigableOrderedTaskLightHeadache { + getIndividualNavigableOrderedTaskSteps(); + + // + // Light headache sequence + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityNo]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, severityStep, lightHeadacheStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, lightHeadacheStep, endStep)); + XCTAssertTrue(testStepAfterStep(_navigableOrderedTask, taskResult, endStep, nil)); + + // Test backward navigation + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, endStep, lightHeadacheStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, lightHeadacheStep, severityStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, severityStep, symptomStep)); + XCTAssertTrue(testStepBeforeStep(_navigableOrderedTask, taskResult, symptomStep, nil)); +} + +- (void)testNavigableOrderedTaskSkip { + ORKNavigableOrderedTask *skipTask = [_navigableOrderedTask copy]; + + getIndividualNavigableOrderedTaskSteps(); + + // + // Light headache sequence + // + ORKTaskResult *taskResult = [self getResultTreeWithTaskIdentifier:NavigableOrderedTaskIdentifier resultOptions:TestsTaskResultOptionSymptomHeadache | TestsTaskResultOptionSeverityNo]; + + // User chose headache at the symptom step + ORKResultSelector *resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:SymptomStepIdentifier]; + NSPredicate *predicateHeadache = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:HeadacheChoiceValue]; + ORKPredicateSkipStepNavigationRule *skipRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicateHeadache]; + + // Skip endStep + [skipTask setSkipNavigationRule:skipRule forStepIdentifier:EndStepIdentifier]; + + // Test forward navigation + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, severityStep, lightHeadacheStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, lightHeadacheStep, nil)); + + + // Skip lightHeadacheStep + [skipTask removeSkipNavigationRuleForStepIdentifier:EndStepIdentifier]; + [skipTask setSkipNavigationRule:skipRule forStepIdentifier:LightHeadacheStepIdentifier]; + + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, severityStep, endStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, endStep, nil)); + + + // Skip lightHeadache and endStep + [skipTask setSkipNavigationRule:skipRule forStepIdentifier:EndStepIdentifier]; + + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, nil, symptomStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, symptomStep, severityStep)); + XCTAssertTrue(testStepAfterStep(skipTask, taskResult, severityStep, nil)); +} + +ORKDefineStringKey(SignConsentStepIdentifier); +ORKDefineStringKey(SignatureIdentifier); + +ORKDefineStringKey(ScaleStepIdentifier); +ORKDefineStringKey(ContinuousScaleStepIdentifier); +static const NSInteger IntegerValue = 6; +static const float FloatValue = 6.5; + +ORKDefineStringKey(SingleChoiceStepIdentifier); +ORKDefineStringKey(MultipleChoiceStepIdentifier); +ORKDefineStringKey(MixedMultipleChoiceStepIdentifier); +ORKDefineStringKey(SingleChoiceValue); +ORKDefineStringKey(MultipleChoiceValue1); +ORKDefineStringKey(MultipleChoiceValue2); +static const NSInteger MultipleChoiceValue3 = 7; + +ORKDefineStringKey(BooleanStepIdentifier); +static const BOOL BooleanValue = YES; + +ORKDefineStringKey(TextStepIdentifier); +ORKDefineStringKey(TextValue); +ORKDefineStringKey(OtherTextValue); + +ORKDefineStringKey(IntegerNumericStepIdentifier); +ORKDefineStringKey(FloatNumericStepIdentifier); + +ORKDefineStringKey(TimeOfDayStepIdentifier); +ORKDefineStringKey(TimeIntervalStepIdentifier); +ORKDefineStringKey(DateStepIdentifier); + +ORKDefineStringKey(FormStepIdentifier); + +ORKDefineStringKey(TextFormItemIdentifier); +ORKDefineStringKey(NumericFormItemIdentifier); + +ORKDefineStringKey(NilTextStepIdentifier); + +ORKDefineStringKey(AdditionalTaskIdentifier); +ORKDefineStringKey(AdditionalFormStepIdentifier); +ORKDefineStringKey(AdditionalTextFormItemIdentifier); +ORKDefineStringKey(AdditionalNumericFormItemIdentifier); + +ORKDefineStringKey(AdditionalTextStepIdentifier); +ORKDefineStringKey(AdditionalTextValue); + +ORKDefineStringKey(MatchedDestinationStepIdentifier); +ORKDefineStringKey(DefaultDestinationStepIdentifier); + +static const NSInteger AdditionalIntegerValue = 42; + +static NSDate *(^Date)(void) = ^NSDate *{ return [NSDate dateWithTimeIntervalSince1970:60*60*24]; }; +static NSDateComponents *(^DateComponents)(void) = ^NSDateComponents *{ + NSDateComponents *dateComponents = [NSDateComponents new]; + dateComponents.hour = 6; + dateComponents.minute = 6; + return dateComponents; +}; + +static ORKQuestionResult *(^getQuestionResult)(NSString *, Class, ORKQuestionType, id) = ^ORKQuestionResult *(NSString *questionResultIdentifier, Class questionResultClass, ORKQuestionType questionType, id answer) { + ORKQuestionResult *questionResult = [[questionResultClass alloc] init]; + questionResult.identifier = questionResultIdentifier; + questionResult.answer = answer; + questionResult.questionType = questionType; + return questionResult; +}; + +static ORKStepResult *(^getStepResult)(NSString *, Class, ORKQuestionType, id) = ^ORKStepResult *(NSString *stepIdentifier, Class questionResultClass, ORKQuestionType questionType, id answer) { + ORKQuestionResult *questionResult = getQuestionResult(stepIdentifier, questionResultClass, questionType, answer); + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[questionResult]]; + return stepResult; +}; + +static ORKStepResult *(^getConsentStepResult)(NSString *, NSString *, BOOL) = ^ORKStepResult *(NSString *stepIdentifier, NSString *signatureIdentifier, BOOL consented) { + ORKConsentSignatureResult *consentSignatureResult = [[ORKConsentSignatureResult alloc] initWithIdentifier:signatureIdentifier]; + consentSignatureResult.consented = consented; + return [[ORKStepResult alloc] initWithStepIdentifier:stepIdentifier results:@[consentSignatureResult]]; +}; + +- (ORKTaskResult *)getGeneralTaskResultTree { + NSMutableArray *stepResults = [NSMutableArray new]; + + [stepResults addObject:getStepResult(ScaleStepIdentifier, [ORKScaleQuestionResult class], ORKQuestionTypeScale, @(IntegerValue))]; + [stepResults addObject:getStepResult(ContinuousScaleStepIdentifier, [ORKScaleQuestionResult class], ORKQuestionTypeScale, @(FloatValue))]; + + [stepResults addObject:getStepResult(SingleChoiceStepIdentifier, [ORKChoiceQuestionResult class], ORKQuestionTypeSingleChoice, @[SingleChoiceValue])]; + [stepResults addObject:getStepResult(MultipleChoiceStepIdentifier, [ORKChoiceQuestionResult class], ORKQuestionTypeMultipleChoice, @[MultipleChoiceValue1, MultipleChoiceValue2])]; + [stepResults addObject:getStepResult(MixedMultipleChoiceStepIdentifier, [ORKChoiceQuestionResult class], ORKQuestionTypeMultipleChoice, @[MultipleChoiceValue1, MultipleChoiceValue2, @(MultipleChoiceValue3)])]; + + [stepResults addObject:getStepResult(BooleanStepIdentifier, [ORKBooleanQuestionResult class], ORKQuestionTypeBoolean, @(BooleanValue))]; + + [stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)]; + + [stepResults addObject:getStepResult(IntegerNumericStepIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeInteger, @(IntegerValue))]; + [stepResults addObject:getStepResult(FloatNumericStepIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeDecimal, @(FloatValue))]; + + [stepResults addObject:getStepResult(DateStepIdentifier, [ORKDateQuestionResult class], ORKQuestionTypeDate, Date())]; + + [stepResults addObject:getStepResult(TimeIntervalStepIdentifier, [ORKTimeIntervalQuestionResult class], ORKQuestionTypeTimeInterval, @(IntegerValue))]; + + [stepResults addObject:getStepResult(TimeOfDayStepIdentifier, [ORKTimeOfDayQuestionResult class], ORKQuestionTypeTimeOfDay, DateComponents())]; + + // Nil result (simulate skipped step) + [stepResults addObject:getStepResult(NilTextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, nil)]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + +- (ORKTaskResult *)getTaskResultTreeWithConsent:(BOOL)consented { + NSMutableArray *stepResults = [NSMutableArray new]; + + [stepResults addObject:getConsentStepResult(SignConsentStepIdentifier, SignatureIdentifier, consented)]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + +- (ORKTaskResult *)getSmallTaskResultTreeWithIsAdditionalTask:(BOOL)isAdditionalTask { + NSMutableArray *stepResults = [NSMutableArray new]; + + if (!isAdditionalTask) { + [stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)]; + } else { + [stepResults addObject:getStepResult(AdditionalTextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, AdditionalTextValue)]; + } + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:!isAdditionalTask ? OrderedTaskIdentifier : AdditionalTaskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + +- (ORKTaskResult *)getSmallFormTaskResultTreeWithIsAdditionalTask:(BOOL)isAdditionalTask { + NSMutableArray *formItemResults = [NSMutableArray new]; + + if (!isAdditionalTask) { + [formItemResults addObject:getQuestionResult(TextFormItemIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)]; + [formItemResults addObject:getQuestionResult(NumericFormItemIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeInteger, @(IntegerValue))]; + } else { + [formItemResults addObject:getQuestionResult(AdditionalTextFormItemIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, AdditionalTextValue)]; + [formItemResults addObject:getQuestionResult(AdditionalNumericFormItemIdentifier, [ORKNumericQuestionResult class], ORKQuestionTypeInteger, @(AdditionalIntegerValue))]; + } + + ORKStepResult *formStepResult = [[ORKStepResult alloc] initWithStepIdentifier:(!isAdditionalTask ? FormStepIdentifier : AdditionalFormStepIdentifier) results:formItemResults]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:(!isAdditionalTask ? OrderedTaskIdentifier : AdditionalTaskIdentifier) + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = @[formStepResult]; + + return taskResult; +} + +- (ORKTaskResult *)getSmallTaskResultTreeWithDuplicateStepIdentifiers { + NSMutableArray *stepResults = [NSMutableArray new]; + + [stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)]; + [stepResults addObject:getStepResult(TextStepIdentifier, [ORKTextQuestionResult class], ORKQuestionTypeText, TextValue)]; + + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithTaskIdentifier:OrderedTaskIdentifier + taskRunUUID:[NSUUID UUID] + outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + taskResult.results = stepResults; + + return taskResult; +} + +- (void)testPredicateStepNavigationRule { + NSPredicate *predicate = nil; + NSPredicate *predicateA = nil; + NSPredicate *predicateB = nil; + ORKPredicateStepNavigationRule *predicateRule = nil; + ORKTaskResult *taskResult = nil; + ORKTaskResult *additionalTaskResult = nil; + + NSArray *resultPredicates = nil; + NSArray *destinationStepIdentifiers = nil; + NSString *defaultStepIdentifier = nil; + + ORKResultSelector *resultSelector = nil; + + { + // Test predicate step navigation rule initializers + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + resultPredicates = @[ predicate ]; + destinationStepIdentifiers = @[ MatchedDestinationStepIdentifier ]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers]; + + XCTAssertEqualObjects(predicateRule.resultPredicates, ORKArrayCopyObjects(resultPredicates)); + XCTAssertEqualObjects(predicateRule.destinationStepIdentifiers, ORKArrayCopyObjects(destinationStepIdentifiers)); + XCTAssertNil(predicateRule.defaultStepIdentifier); + + defaultStepIdentifier = DefaultDestinationStepIdentifier; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:resultPredicates + destinationStepIdentifiers:destinationStepIdentifiers + defaultStepIdentifier:defaultStepIdentifier]; + + XCTAssertEqualObjects(predicateRule.resultPredicates, ORKArrayCopyObjects(resultPredicates)); + XCTAssertEqualObjects(predicateRule.destinationStepIdentifiers, ORKArrayCopyObjects(destinationStepIdentifiers)); + XCTAssertEqualObjects(predicateRule.defaultStepIdentifier, defaultStepIdentifier); + } + + { + // Predicate matching, no additional task results, matching + taskResult = [ORKTaskResult new]; + taskResult.identifier = OrderedTaskIdentifier; + + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier); + } + + { + // Predicate matching, no additional task results, non matching + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:OtherTextValue]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + } + + { + NSPredicate *currentPredicate = nil; + NSPredicate *additionalPredicate = nil; + + // Predicate matching, additional task results + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + currentPredicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + resultIdentifier:AdditionalTextStepIdentifier]; + additionalPredicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:AdditionalTextValue]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[currentPredicate, additionalPredicate]]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + + taskResult = [ORKTaskResult new]; + taskResult.identifier = OrderedTaskIdentifier; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + + additionalTaskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:YES]; + predicateRule.additionalTaskResults = @[ additionalTaskResult ]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier); + } + + { + // Test duplicate task identifiers check + predicateRule.additionalTaskResults = @[ taskResult ]; + XCTAssertThrows([predicateRule identifierForDestinationStepWithTaskResult:taskResult]); + + // Test duplicate question result identifiers check + XCTAssertThrows(predicateRule.additionalTaskResults = @[ [self getSmallTaskResultTreeWithDuplicateStepIdentifiers] ]); + } + + { + // Form predicate matching, no additional task results, matching + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:NumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier); + } + + { + // Form predicate matching, no additional task results, non matching + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:OtherTextValue]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + } + + { + NSPredicate *currentPredicate = nil; + NSPredicate *additionalPredicate = nil; + + // Form predicate matching, additional task results + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:NumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue]; + + currentPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + stepIdentifier:AdditionalFormStepIdentifier + resultIdentifier:AdditionalTextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:AdditionalTextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + stepIdentifier:AdditionalFormStepIdentifier + resultIdentifier:AdditionalNumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:AdditionalIntegerValue]; + + additionalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[currentPredicate, additionalPredicate]]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicate ] + destinationStepIdentifiers:@[ MatchedDestinationStepIdentifier ] + defaultStepIdentifier:DefaultDestinationStepIdentifier]; + + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], DefaultDestinationStepIdentifier); + + additionalTaskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:YES]; + predicateRule.additionalTaskResults = @[ additionalTaskResult ]; + XCTAssertEqualObjects([predicateRule identifierForDestinationStepWithTaskResult:taskResult], MatchedDestinationStepIdentifier); + } +} + +- (void)testPredicateSkipStepNavigationRule { + NSPredicate *predicate = nil; + NSPredicate *predicateA = nil; + NSPredicate *predicateB = nil; + ORKPredicateSkipStepNavigationRule *predicateRule = nil; + ORKTaskResult *taskResult = nil; + ORKTaskResult *additionalTaskResult = nil; + + ORKResultSelector *resultSelector = nil; + + { + // Test predicate step navigation rule initializers + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + XCTAssertEqualObjects(predicateRule.resultPredicate, predicate); + } + + { + // Predicate matching, no additional task results, matching + taskResult = [ORKTaskResult new]; + taskResult.identifier = OrderedTaskIdentifier; + + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertTrue([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } + + { + // Predicate matching, no additional task results, non matching + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:OtherTextValue]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } + + { + NSPredicate *currentPredicate = nil; + NSPredicate *additionalPredicate = nil; + + // Predicate matching, additional task results + resultSelector = [[ORKResultSelector alloc] initWithResultIdentifier:TextStepIdentifier]; + currentPredicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + resultIdentifier:AdditionalTextStepIdentifier]; + additionalPredicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:AdditionalTextValue]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[currentPredicate, additionalPredicate]]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + + taskResult = [ORKTaskResult new]; + taskResult.identifier = OrderedTaskIdentifier; + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + + taskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + + additionalTaskResult = [self getSmallTaskResultTreeWithIsAdditionalTask:YES]; + predicateRule.additionalTaskResults = @[ additionalTaskResult ]; + XCTAssertTrue([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } + + { + // Test duplicate task identifiers check + predicateRule.additionalTaskResults = @[ taskResult ]; + XCTAssertThrows([predicateRule stepShouldSkipWithTaskResult:taskResult]); + + // Test duplicate question result identifiers check + XCTAssertThrows(predicateRule.additionalTaskResults = @[ [self getSmallTaskResultTreeWithDuplicateStepIdentifiers] ]); + } + + { + // Form predicate matching, no additional task results, matching + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:NumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertTrue([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } + + { + // Form predicate matching, no additional task results, non matching + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicate = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:OtherTextValue]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } + + { + NSPredicate *currentPredicate = nil; + NSPredicate *additionalPredicate = nil; + + // Form predicate matching, additional task results + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:TextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithStepIdentifier:FormStepIdentifier + resultIdentifier:NumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue]; + + currentPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + stepIdentifier:AdditionalFormStepIdentifier + resultIdentifier:AdditionalTextFormItemIdentifier]; + predicateA = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:AdditionalTextValue]; + + resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:AdditionalTaskIdentifier + stepIdentifier:AdditionalFormStepIdentifier + resultIdentifier:AdditionalNumericFormItemIdentifier]; + predicateB = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:AdditionalIntegerValue]; + + additionalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateA, predicateB]]; + + predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[currentPredicate, additionalPredicate]]; + predicateRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicate]; + + taskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:NO]; + XCTAssertFalse([predicateRule stepShouldSkipWithTaskResult:taskResult]); + + additionalTaskResult = [self getSmallFormTaskResultTreeWithIsAdditionalTask:YES]; + predicateRule.additionalTaskResults = @[ additionalTaskResult ]; + XCTAssertTrue([predicateRule stepShouldSkipWithTaskResult:taskResult]); + } +} + +- (void)testDirectStepNavigationRule { + ORKDirectStepNavigationRule *directRule = nil; + ORKTaskResult *mockTaskResult = [ORKTaskResult new]; + + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:MatchedDestinationStepIdentifier]; + XCTAssertEqualObjects(directRule.destinationStepIdentifier, [MatchedDestinationStepIdentifier copy] ); + XCTAssertEqualObjects([directRule identifierForDestinationStepWithTaskResult:mockTaskResult], [MatchedDestinationStepIdentifier copy]); + + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKNullStepIdentifier]; + XCTAssertEqualObjects(directRule.destinationStepIdentifier, [ORKNullStepIdentifier copy]); + XCTAssertEqualObjects([directRule identifierForDestinationStepWithTaskResult:mockTaskResult], [ORKNullStepIdentifier copy]); +} + +- (void)testResultPredicatesWithTaskIdentifier:(NSString *)taskIdentifier + substitutionVariables:(NSDictionary *)substitutionVariables + taskResults:(NSArray *)taskResults { + // ORKScaleQuestionResult + ORKResultSelector *resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:taskIdentifier + resultIdentifier:@""]; + + resultSelector.resultIdentifier = ScaleStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue + 1] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = ContinuousScaleStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01 + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.05 + maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKChoiceQuestionResult (strings) + resultSelector.resultIdentifier = SingleChoiceStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:SingleChoiceValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:OtherTextValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = MultipleChoiceStepIdentifier; + NSArray *expectedAnswers = nil; + expectedAnswers = @[MultipleChoiceValue1]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2, OtherTextValue]; + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2, @(MultipleChoiceValue3)]; + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = MixedMultipleChoiceStepIdentifier; + expectedAnswers = @[MultipleChoiceValue1]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[@(MultipleChoiceValue3)]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2, @(MultipleChoiceValue3)]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[MultipleChoiceValue1, MultipleChoiceValue2, OtherTextValue]; + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValues:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKChoiceQuestionResult (regular expressions) + resultSelector.resultIdentifier = SingleChoiceStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + matchingPattern:@"...gleChoiceValue"] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:@"...SingleChoiceValue"] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = MultipleChoiceStepIdentifier; + expectedAnswers = @[@"...tipleChoiceValue1", @"...tipleChoiceValue2"]; + XCTAssertTrue([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + matchingPatterns:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedAnswers = @[@"...MultipleChoiceValue1", @"...MultipleChoiceValue2", @"...OtherTextValue"]; + XCTAssertFalse([[ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + matchingPatterns:expectedAnswers] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKBooleanQuestionResult + resultSelector.resultIdentifier = BooleanStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:BooleanValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:!BooleanValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKTextQuestionResult (strings) + resultSelector.resultIdentifier = TextStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:TextValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + expectedString:OtherTextValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKTextQuestionResult (regular expressions) + XCTAssertTrue([[ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + matchingPattern:@"...tValue"] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector + matchingPattern:@"...TextValue"] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKNumericQuestionResult + resultSelector.resultIdentifier = IntegerNumericStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + expectedAnswer:IntegerValue + 1] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = FloatNumericStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:ORKIgnoreDoubleValue + maximumExpectedAnswerValue:ORKIgnoreDoubleValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01 + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.05 + maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01 + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.05 + maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKTimeOfDayQuestionResult + resultSelector.resultIdentifier = TimeOfDayStepIdentifier; + NSDateComponents *expectedDateComponentsMinimum = DateComponents(); + NSDateComponents *expectedDateComponentsMaximum = DateComponents(); + XCTAssertTrue([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithResultSelector:resultSelector + minimumExpectedHour:expectedDateComponentsMinimum.hour + minimumExpectedMinute:expectedDateComponentsMinimum.minute + maximumExpectedHour:expectedDateComponentsMaximum.hour + maximumExpectedMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + expectedDateComponentsMinimum.minute -= 2; + expectedDateComponentsMaximum.minute += 2; + XCTAssertTrue([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithResultSelector:resultSelector + minimumExpectedHour:expectedDateComponentsMinimum.hour + minimumExpectedMinute:expectedDateComponentsMinimum.minute + maximumExpectedHour:expectedDateComponentsMaximum.hour + maximumExpectedMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + expectedDateComponentsMinimum.minute += 3; + XCTAssertFalse([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithResultSelector:resultSelector + minimumExpectedHour:expectedDateComponentsMinimum.hour + minimumExpectedMinute:expectedDateComponentsMinimum.minute + maximumExpectedHour:expectedDateComponentsMaximum.hour + maximumExpectedMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + expectedDateComponentsMinimum.minute -= 3; + expectedDateComponentsMinimum.hour += 1; + expectedDateComponentsMaximum.hour += 2; + XCTAssertFalse([[ORKResultPredicate predicateForTimeOfDayQuestionResultWithResultSelector:resultSelector + minimumExpectedHour:expectedDateComponentsMinimum.hour + minimumExpectedMinute:expectedDateComponentsMinimum.minute + maximumExpectedHour:expectedDateComponentsMaximum.hour + maximumExpectedMinute:expectedDateComponentsMaximum.minute] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKTimeIntervalQuestionResult + resultSelector.resultIdentifier = FloatNumericStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:ORKIgnoreTimeIntervalValue + maximumExpectedAnswerValue:ORKIgnoreTimeIntervalValue] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01 + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.05 + maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01 + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.05 + maximumExpectedAnswerValue:FloatValue + 0.06] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue + 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForTimeIntervalQuestionResultWithResultSelector:resultSelector + maximumExpectedAnswerValue:FloatValue - 0.01] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // ORKDateQuestionResult + resultSelector.resultIdentifier = DateStepIdentifier; + NSDate *expectedDate = Date(); + XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-60] + maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60]] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60] + maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+120]] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-60] + maximumExpectedAnswerDate:nil] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+1] + maximumExpectedAnswerDate:nil] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:nil + maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:+60]] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + XCTAssertFalse([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:nil + maximumExpectedAnswerDate:[expectedDate dateByAddingTimeInterval:-1]] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + XCTAssertTrue([[ORKResultPredicate predicateForDateQuestionResultWithResultSelector:resultSelector + minimumExpectedAnswerDate:nil + maximumExpectedAnswerDate:nil] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + // Result with nil value + resultSelector.resultIdentifier = NilTextStepIdentifier; + XCTAssertTrue([[ORKResultPredicate predicateForNilQuestionResultWithResultSelector:resultSelector] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); + + resultSelector.resultIdentifier = TextStepIdentifier; + XCTAssertFalse([[ORKResultPredicate predicateForNilQuestionResultWithResultSelector:resultSelector] evaluateWithObject:taskResults substitutionVariables:substitutionVariables]); +} + +- (void)testConsentPredicate { + ORKResultSelector *resultSelector = [[ORKResultSelector alloc] initWithTaskIdentifier:OrderedTaskIdentifier + stepIdentifier:SignConsentStepIdentifier + resultIdentifier:SignatureIdentifier]; + { + ORKTaskResult *consentedTaskResult = [self getTaskResultTreeWithConsent:YES]; + XCTAssertTrue([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:YES] evaluateWithObject:@[consentedTaskResult] substitutionVariables:nil]); + XCTAssertFalse([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:NO] evaluateWithObject:@[consentedTaskResult] substitutionVariables:nil]); + } + + { + ORKTaskResult *didNotConsentTaskResult = [self getTaskResultTreeWithConsent:NO]; + + XCTAssertTrue([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:NO] evaluateWithObject:@[didNotConsentTaskResult] substitutionVariables:nil]); + XCTAssertFalse([[ORKResultPredicate predicateForConsentWithResultSelector:resultSelector + didConsent:YES] evaluateWithObject:@[didNotConsentTaskResult] substitutionVariables:nil]); + } +} + +- (void)testResultPredicates { + ORKTaskResult *taskResult = [self getGeneralTaskResultTree]; + NSArray *taskResults = @[ taskResult ]; + + // The following two calls are equivalent since 'substitutionVariables' are ignored when you provide a non-nil task identifier + [self testResultPredicatesWithTaskIdentifier:OrderedTaskIdentifier + substitutionVariables:nil + taskResults:taskResults]; + [self testResultPredicatesWithTaskIdentifier:OrderedTaskIdentifier + substitutionVariables:@{ORKResultPredicateTaskIdentifierVariableName: OrderedTaskIdentifier} + taskResults:taskResults]; + // Test nil task identifier variable substitution + [self testResultPredicatesWithTaskIdentifier:nil + substitutionVariables:@{ORKResultPredicateTaskIdentifierVariableName: OrderedTaskIdentifier} + taskResults:taskResults]; +} + +- (void)testStepViewControllerWillDisappear { + TestTaskViewControllerDelegate *delegate = [[TestTaskViewControllerDelegate alloc] init]; + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"test" intendedUseDescription:nil duration:30 handOptions:0 options:0]; + ORKTaskViewController *taskViewController = [[MockTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + taskViewController.delegate = delegate; + ORKInstructionStepViewController *stepViewController = [[ORKInstructionStepViewController alloc] initWithStep:task.steps.firstObject]; + + //-- call method under test + [taskViewController stepViewController:stepViewController didFinishWithNavigationDirection:ORKStepViewControllerNavigationDirectionForward]; + + // Check that the expected methods were called + XCTAssertEqual(delegate.methodCalled.count, 1); + XCTAssertEqualObjects(delegate.methodCalled.firstObject.selectorName, @"taskViewController:stepViewControllerWillDisappear:navigationDirection:"); + NSArray *expectedArgs = @[taskViewController, stepViewController, @(ORKStepViewControllerNavigationDirectionForward)]; + XCTAssertEqualObjects(delegate.methodCalled.firstObject.arguments, expectedArgs); + +} + +- (void)testIndexOfStep { + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"tapping" intendedUseDescription:nil duration:30 handOptions:0 options:0]; + + // get the first step + ORKStep *step0 = [task.steps firstObject]; + XCTAssertNotNil(step0); + XCTAssertEqual([task indexOfStep:step0], 0); + + // get the second step + ORKStep *step1 = [task stepWithIdentifier:ORKInstruction1StepIdentifier]; + XCTAssertNotNil(step1); + XCTAssertEqual([task indexOfStep:step1], 1); + + // get the last step + ORKStep *stepLast = [task.steps lastObject]; + XCTAssertNotNil(stepLast); + XCTAssertEqual([task indexOfStep:stepLast], task.steps.count - 1); + + // Look for not found + ORKStep *stepNF = [[ORKStep alloc] initWithIdentifier:@"foo"]; + XCTAssertEqual([task indexOfStep:stepNF], NSNotFound); + +} + +- (void)testAudioTask_WithSoundCheck { + ORKNavigableOrderedTask *task = [ORKOrderedTask audioTaskWithIdentifier:@"audio" intendedUseDescription:nil speechInstruction:nil shortSpeechInstruction:nil duration:20 recordingSettings:nil checkAudioLevel:YES options:0]; + + NSArray *expectedStepIdentifiers = @[ORKInstruction0StepIdentifier, + ORKInstruction1StepIdentifier, + ORKCountdownStepIdentifier, + ORKAudioTooLoudStepIdentifier, + ORKAudioStepIdentifier, + ORKConclusionStepIdentifier]; + NSArray *stepIdentifiers = [task.steps valueForKey:@"identifier"]; + XCTAssertEqual(stepIdentifiers.count, expectedStepIdentifiers.count); + XCTAssertEqualObjects(stepIdentifiers, expectedStepIdentifiers); + + XCTAssertNotNil([task navigationRuleForTriggerStepIdentifier:ORKCountdownStepIdentifier]); + XCTAssertNotNil([task navigationRuleForTriggerStepIdentifier:ORKAudioTooLoudStepIdentifier]); +} + +- (void)testAudioTask_NoSoundCheck { + + ORKNavigableOrderedTask *task = [ORKOrderedTask audioTaskWithIdentifier:@"audio" intendedUseDescription:nil speechInstruction:nil shortSpeechInstruction:nil duration:20 recordingSettings:nil checkAudioLevel:NO options:0]; + + NSArray *expectedStepIdentifiers = @[ORKInstruction0StepIdentifier, + ORKInstruction1StepIdentifier, + ORKCountdownStepIdentifier, + ORKAudioStepIdentifier, + ORKConclusionStepIdentifier]; + NSArray *stepIdentifiers = [task.steps valueForKey:@"identifier"]; + XCTAssertEqual(stepIdentifiers.count, expectedStepIdentifiers.count); + XCTAssertEqualObjects(stepIdentifiers, expectedStepIdentifiers); + XCTAssertEqual(task.stepNavigationRules.count, 0); +} + +- (void)testWalkBackAndForthTask_30SecondDuration { + + // Create the task + ORKOrderedTask *task = [ORKOrderedTask walkBackAndForthTaskWithIdentifier:@"walking" intendedUseDescription:nil walkDuration:30 restDuration:30 options:0]; + + // Check that the steps match the expected - If these change, it will affect the results and + // could adversely impact existing studies that are expecting this step order. + NSArray *expectedStepIdentifiers = @[ORKInstruction0StepIdentifier, + ORKInstruction1StepIdentifier, + ORKCountdownStepIdentifier, + ORKShortWalkOutboundStepIdentifier, + ORKShortWalkRestStepIdentifier, + ORKConclusionStepIdentifier]; + XCTAssertEqual(task.steps.count, expectedStepIdentifiers.count); + NSArray *stepIdentifiers = [task.steps valueForKey:@"identifier"]; + XCTAssertEqualObjects(stepIdentifiers, expectedStepIdentifiers); + + // Check that the active steps include speaking the halfway point + ORKActiveStep *walkingStep = (ORKActiveStep *)[task stepWithIdentifier:ORKShortWalkOutboundStepIdentifier]; + XCTAssertTrue(walkingStep.shouldSpeakRemainingTimeAtHalfway); + ORKActiveStep *restStep = (ORKActiveStep *)[task stepWithIdentifier:ORKShortWalkRestStepIdentifier]; + XCTAssertTrue(restStep.shouldSpeakRemainingTimeAtHalfway); + +} + +- (void)testWalkBackAndForthTask_15SecondDuration_NoRest { + + // Create the task + ORKOrderedTask *task = [ORKOrderedTask walkBackAndForthTaskWithIdentifier:@"walking" intendedUseDescription:nil walkDuration:15 restDuration:0 options:0]; + + // Check that the steps match the expected - If these change, it will affect the results and + // could adversely impact existing studies that are expecting this step order. + NSArray *expectedStepIdentifiers = @[ORKInstruction0StepIdentifier, + ORKInstruction1StepIdentifier, + ORKCountdownStepIdentifier, + ORKShortWalkOutboundStepIdentifier, + ORKConclusionStepIdentifier]; + XCTAssertEqual(task.steps.count, expectedStepIdentifiers.count); + NSArray *stepIdentifiers = [task.steps valueForKey:@"identifier"]; + XCTAssertEqualObjects(stepIdentifiers, expectedStepIdentifiers); + + // Check that the active steps include speaking the halfway point + ORKActiveStep *walkingStep = (ORKActiveStep *)[task stepWithIdentifier:ORKShortWalkOutboundStepIdentifier]; + XCTAssertFalse(walkingStep.shouldSpeakRemainingTimeAtHalfway); + +} + +#pragma mark - two-finger tapping with both hands + +- (void)testTwoFingerTappingIntervalTaskWithIdentifier_TapHandOptionUndefined { + + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"test" + intendedUseDescription:nil + duration:10 + handOptions:0 + options:0]; + NSArray *expectedStepIdentifiers = @[ORKInstruction0StepIdentifier, + ORKInstruction1StepIdentifier, + ORKTappingStepIdentifier, + ORKConclusionStepIdentifier]; + NSArray *stepIdentifiers = [task.steps valueForKey:@"identifier"]; + XCTAssertEqual(stepIdentifiers.count, expectedStepIdentifiers.count); + XCTAssertEqualObjects(stepIdentifiers, expectedStepIdentifiers); + + ORKStep *tappingStep = [task stepWithIdentifier:ORKTappingStepIdentifier]; + XCTAssertFalse(tappingStep.optional); + +} + +- (void)testTwoFingerTappingIntervalTaskWithIdentifier_TapHandOptionLeft { + + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"test" + intendedUseDescription:nil + duration:10 + handOptions:ORKPredefinedTaskHandOptionLeft + options:0]; + // Check assumption around how many steps + XCTAssertEqual(task.steps.count, 4); + + // Check that none of the language or identifiers contain the word "right" + for (ORKStep *step in task.steps) { + XCTAssertFalse([step.identifier.lowercaseString hasSuffix:@"right"]); + XCTAssertFalse([step.title.lowercaseString containsString:@"right"]); + XCTAssertFalse([step.text.lowercaseString containsString:@"right"]); + } + + NSArray * (^filteredSteps)(NSString*, NSString*) = ^(NSString *part1, NSString *part2) { + NSString *keyValue = [NSString stringWithFormat:@"%@.%@", part1, part2]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", NSStringFromSelector(@selector(identifier)), keyValue]; + return [task.steps filteredArrayUsingPredicate:predicate]; + }; + + // Look for instruction step + NSArray *instructions = filteredSteps(@"instruction1", @"left"); + XCTAssertEqual(instructions.count, 1); + ORKStep *instructionStep = [instructions firstObject]; + XCTAssertEqualObjects(instructionStep.title, @"Left Hand"); + XCTAssertEqualObjects(instructionStep.text, @"Put your device on a flat surface. Use two fingers on your left hand to alternately tap the buttons on the screen. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + + // Look for the activity step + NSArray *tappings = filteredSteps(@"tapping", @"left"); + XCTAssertEqual(tappings.count, 1); + ORKStep *tappingStep = [tappings firstObject]; + XCTAssertEqualObjects(tappingStep.text, @"Tap the buttons using your LEFT hand."); + XCTAssertFalse(tappingStep.optional); + +} + +- (void)testTwoFingerTappingIntervalTaskWithIdentifier_TapHandOptionRight { + + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"test" + intendedUseDescription:nil + duration:10 + handOptions:ORKPredefinedTaskHandOptionRight + options:0]; + // Check assumption around how many steps + XCTAssertEqual(task.steps.count, 4); + + // Check that none of the language or identifiers contain the word "right" + for (ORKStep *step in task.steps) { + XCTAssertFalse([step.identifier.lowercaseString hasSuffix:@"left"]); + XCTAssertFalse([step.title.lowercaseString containsString:@"left"]); + XCTAssertFalse([step.text.lowercaseString containsString:@"left"]); + } + + NSArray * (^filteredSteps)(NSString*, NSString*) = ^(NSString *part1, NSString *part2) { + NSString *keyValue = [NSString stringWithFormat:@"%@.%@", part1, part2]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", NSStringFromSelector(@selector(identifier)), keyValue]; + return [task.steps filteredArrayUsingPredicate:predicate]; + }; + + // Look for instruction step + NSArray *instructions = filteredSteps(@"instruction1", @"right"); + XCTAssertEqual(instructions.count, 1); + ORKStep *instructionStep = [instructions firstObject]; + XCTAssertEqualObjects(instructionStep.title, @"Right Hand"); + XCTAssertEqualObjects(instructionStep.text, @"Put your device on a flat surface. Use two fingers on your right hand to alternately tap the buttons on the screen. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + + // Look for the activity step + NSArray *tappings = filteredSteps(@"tapping", @"right"); + XCTAssertEqual(tappings.count, 1); + ORKStep *tappingStep = [tappings firstObject]; + XCTAssertEqualObjects(tappingStep.text, @"Tap the buttons using your RIGHT hand."); + XCTAssertFalse(tappingStep.optional); + +} + +- (void)testTwoFingerTappingIntervalTaskWithIdentifier_TapHandOptionBoth { + NSUInteger leftCount = 0; + NSUInteger rightCount = 0; + NSUInteger totalCount = 100; + NSUInteger threshold = 30; + + for (int ii = 0; ii < totalCount; ii++) { + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:@"test" + intendedUseDescription:nil + duration:10 + handOptions:ORKPredefinedTaskHandOptionBoth + options:0]; + ORKStep * (^filteredSteps)(NSString*, NSString*) = ^(NSString *part1, NSString *part2) { + NSString *keyValue = [NSString stringWithFormat:@"%@.%@", part1, part2]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", NSStringFromSelector(@selector(identifier)), keyValue]; + return [[task.steps filteredArrayUsingPredicate:predicate] firstObject]; + }; + + // Look for instruction steps + ORKStep *rightInstructionStep = filteredSteps(@"instruction1", @"right"); + XCTAssertNotNil(rightInstructionStep); + ORKStep *leftInstructionStep = filteredSteps(@"instruction1", @"left"); + XCTAssertNotNil(leftInstructionStep); + + // Depending upon the seed (clock time) this will be either the right or left hand + // Without using OCMock, cannot easily verify that both will display. + BOOL isRightFirst = [task.steps indexOfObject:rightInstructionStep] < [task.steps indexOfObject:leftInstructionStep]; + if (isRightFirst) { + rightCount++; + } else { + leftCount++; + } + + if ((isRightFirst && rightCount == 1) || (!isRightFirst && leftCount == 1)) { + + // Look for instruction steps + XCTAssertEqualObjects(rightInstructionStep.title, @"Right Hand"); + XCTAssertEqualObjects(leftInstructionStep.title, @"Left Hand"); + + // Depending upon the seed (clock time) this will be either the right or left hand + // Without using OCMock, cannot easily verify that both will display. + if (isRightFirst) { + XCTAssertEqualObjects(rightInstructionStep.text, @"Put your device on a flat surface. Use two fingers on your right hand to alternately tap the buttons on the screen. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + XCTAssertEqualObjects(leftInstructionStep.text, @"Put your device on a flat surface. Now repeat the same test using your left hand. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + } else { + XCTAssertEqualObjects(leftInstructionStep.text, @"Put your device on a flat surface. Use two fingers on your left hand to alternately tap the buttons on the screen. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + XCTAssertEqualObjects(rightInstructionStep.text, @"Put your device on a flat surface. Now repeat the same test using your right hand. Tap one finger, then the other. Try to time your taps to be as even as possible. Keep tapping for 10 seconds."); + } + + // Look for tapping steps + ORKStep *rightTapStep = filteredSteps(@"tapping", @"right"); + XCTAssertNotNil(rightTapStep); + XCTAssertEqualObjects(rightTapStep.text, @"Tap the buttons using your RIGHT hand."); + XCTAssertTrue(rightTapStep.optional); + + ORKStep *leftTapStep = filteredSteps(@"tapping", @"left"); + XCTAssertNotNil(leftTapStep); + XCTAssertEqualObjects(leftTapStep.text, @"Tap the buttons using your LEFT hand."); + XCTAssertTrue(leftTapStep.optional); + } + } + + XCTAssertGreaterThan(leftCount, threshold); + XCTAssertGreaterThan(rightCount, threshold); +} + + +#pragma mark - Test Tremor Task navigation + +- (void)testKeyValueStepModifier { + + // Setup the task + ORKStep *boolStep = [ORKQuestionStep questionStepWithIdentifier:@"question" + title:@"Question" + question:@"Yes or No" + answer:[ORKAnswerFormat booleanAnswerFormat]]; + + ORKStep *nextStep = [[ORKInstructionStep alloc] initWithIdentifier:@"nextStep"]; + nextStep.title = @"Yes"; + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:NavigableOrderedTaskIdentifier + steps:@[boolStep, nextStep]]; + + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"question" + resultIdentifier:@"question"]; + NSPredicate *predicate = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:NO]; + ORKStepModifier *stepModifier = [[ORKKeyValueStepModifier alloc] initWithResultPredicate:predicate + keyValueMap:@{ @"title" : @"No" }]; + + [task setStepModifier:stepModifier forStepIdentifier:@"nextStep"]; + + // -- Check the title if the answer is YES + ORKBooleanQuestionResult *result = [[ORKBooleanQuestionResult alloc] initWithIdentifier:@"question"]; + result.booleanAnswer = @(YES); + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"question" results:@[result]]; + ORKTaskResult *taskResult = [[ORKTaskResult alloc] initWithIdentifier:NavigableOrderedTaskIdentifier]; + taskResult.results = @[stepResult]; + + // For the case where the answer is YES, then the title should be "Yes" (unmodified) + ORKStep *yesStep = [task stepAfterStep:boolStep withResult:taskResult]; + XCTAssertEqualObjects(yesStep.title, @"Yes"); + + // -- Check the title if the answer is NO + result.booleanAnswer = @(NO); + stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"question" results:@[result]]; + taskResult.results = @[stepResult]; + + // For the case where the answer is NO, then the title should be modified to be "No" + ORKStep *noStep = [task stepAfterStep:boolStep withResult:taskResult]; + XCTAssertEqualObjects(noStep.title, @"No"); +} + + +@end + + +@implementation MethodObject +@end + +@implementation TestTaskViewControllerDelegate + +- (instancetype)init +{ + self = [super init]; + if (self) { + _methodCalled = [NSMutableArray new]; + } + return self; +} + +- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error { + + // Add results of method call + MethodObject *obj = [[MethodObject alloc] init]; + obj.selectorName = NSStringFromSelector(@selector(taskViewController:didFinishWithReason:error:)); + obj.arguments = @[taskViewController ?: [NSNull null], + @(reason), + error ?: [NSNull null]]; + [self.methodCalled addObject:obj]; +} + +- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillDisappear:(ORKStepViewController *)stepViewController navigationDirection:(ORKStepViewControllerNavigationDirection)direction { + // Add results of method call + MethodObject *obj = [[MethodObject alloc] init]; + obj.selectorName = NSStringFromSelector(@selector(taskViewController:stepViewControllerWillDisappear:navigationDirection:)); + obj.arguments = @[taskViewController ?: [NSNull null], + stepViewController ?: [NSNull null], + @(direction)]; + [self.methodCalled addObject:obj]; +} + +@end + +@implementation MockTaskViewController + +- (void)flipToNextPageFrom:(ORKStepViewController *)fromController { + // Add results of method call + MethodObject *obj = [[MethodObject alloc] init]; + obj.selectorName = NSStringFromSelector(@selector(flipToNextPageFrom:)); + obj.arguments = @[fromController ?: [NSNull null]]; + [self.methodCalled addObject:obj]; +} + +- (void)flipToPreviousPageFrom:(ORKStepViewController *)fromController { + // Add results of method call + MethodObject *obj = [[MethodObject alloc] init]; + obj.selectorName = NSStringFromSelector(@selector(flipToPreviousPageFrom:)); + obj.arguments = @[fromController ?: [NSNull null]]; + [self.methodCalled addObject:obj]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTestResultPredicateType.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTestResultPredicateType.swift new file mode 100755 index 0000000..32841e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTestResultPredicateType.swift @@ -0,0 +1,50 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +import Foundation + +enum TestPredicateFormat: String { + case consent = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.consented == 1).@count > 0).@count > 0).@count > 0" + case text = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer == %@).@count > 0).@count > 0).@count > 0" + case choice = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND SUBQUERY($z.answer, $w, $w MATCHES %@).@count > 0).@count > 0).@count > 0).@count > 0" + case choiceObject = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND SUBQUERY($z.answer, $w, $w == %@).@count > 0).@count > 0).@count > 0).@count > 0" + case choiceObjects = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND SUBQUERY($z.answer, $w, $w == %@).@count > 0 AND SUBQUERY($z.answer, $w, $w == %@).@count > 0).@count > 0).@count > 0).@count > 0" + case scale = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer == 5).@count > 0).@count > 0).@count > 0" + case scaleMax = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer <= 20).@count > 0).@count > 0).@count > 0" + case scaleMin = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer >= 10).@count > 0).@count > 0).@count > 0" + case numeric = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer == 25).@count > 0).@count > 0).@count > 0" + case numericMax = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer <= 50).@count > 0).@count > 0).@count > 0" + case numericMin = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer >= 0).@count > 0).@count > 0).@count > 0" + case timeMax = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer <= 100).@count > 0).@count > 0).@count > 0" + case timeMin = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer >= 16).@count > 0).@count > 0).@count > 0" + case timeMinAndMax = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer >= 10 AND $z.answer <= 1000).@count > 0).@count > 0).@count > 0" + case timeOfDay = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer.hour >= 2 AND $z.answer.minute >= 30 AND $z.answer.hour <= 10 AND $z.answer.minute <= 10).@count > 0).@count > 0).@count > 0" + case boolean = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer == 1).@count > 0).@count > 0).@count > 0" + case nilPredicate = "SUBQUERY(SELF, $x, $x.identifier == $ORK_TASK_IDENTIFIER AND SUBQUERY($x.results, $y, $y.identifier == %@ AND $y.isPreviousResult == 0 AND SUBQUERY($y.results, $z, $z.identifier == %@ AND $z.answer == nil).@count > 0).@count > 0).@count > 0" +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTextChoiceCellGroupTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTextChoiceCellGroupTests.m new file mode 100755 index 0000000..262921c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKTextChoiceCellGroupTests.m @@ -0,0 +1,655 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKChoiceViewCell.h" +#import "ORKTextChoiceCellGroup.h" +#import "ORKAnswerTextView.h" + +@interface ORKTextChoiceCellGroupTests : XCTestCase + +@end + + +@implementation ORKTextChoiceCellGroupTests + +- (NSArray *)textChoices { + static NSArray *choices = nil; + + if (choices == nil) { + choices = @[[ORKTextChoice choiceWithText:@"choice 01" value:@"c1"], + [ORKTextChoice choiceWithText:@"choice 02" value:@"c2"], + [ORKTextChoice choiceWithText:@"choice 03" value:@"c3"], + [ORKTextChoice choiceWithText:@"choice 04" value:@"c4"]]; + } + + return choices; +} + +- (NSArray *)textChoicesOther { + ORKTextChoiceOther *textChoiceOtherOne = [[ORKTextChoiceOther alloc] initWithText:@"Text Choice Other One" primaryTextAttributedString:nil detailText:nil detailTextAttributedString:nil value:@"one" exclusive:true textViewPlaceholderText:@"Please describe." textViewInputOptional:YES textViewStartsHidden:YES]; + ORKTextChoiceOther *textChoiceOtherTwo = [[ORKTextChoiceOther alloc] initWithText:@"Text Choice Other Two" primaryTextAttributedString:nil detailText:nil detailTextAttributedString:nil value:@"two" exclusive:true textViewPlaceholderText:@"" textViewInputOptional:YES textViewStartsHidden:NO]; + ORKTextChoiceOther *textChoiceOtherThree = [[ORKTextChoiceOther alloc] initWithText:@"Text Choice Other Three" primaryTextAttributedString:nil detailText:nil detailTextAttributedString:nil value:@"three" exclusive:true textViewPlaceholderText:@"Please describe." textViewInputOptional:NO textViewStartsHidden:YES]; + ORKTextChoiceOther *textChoiceOtherFour = [[ORKTextChoiceOther alloc] initWithText:nil primaryTextAttributedString:nil detailText:@"Text Choice Other Four" detailTextAttributedString:nil value:@"four" exclusive:true textViewPlaceholderText:@"Please describe." textViewInputOptional:NO textViewStartsHidden:NO]; + + static NSArray *choicesOther = nil; + if (choicesOther == nil) { + choicesOther = @[textChoiceOtherOne, textChoiceOtherTwo, textChoiceOtherThree, textChoiceOtherFour]; + } + return choicesOther; +} + +- (NSArray *)textChoicesWithOneExclusive { + static NSArray *choicesWithOneExclusive = nil; + + if (choicesWithOneExclusive == nil) { + choicesWithOneExclusive = @[[ORKTextChoice choiceWithText:@"choice 01" value:@"c1"], + [ORKTextChoice choiceWithText:@"choice 02" detailText:nil value:@"c2" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 03" value:@"c3"], + [ORKTextChoice choiceWithText:@"choice 04" value:@"c4"]]; + } + + return choicesWithOneExclusive; +} + +- (NSArray *)textChoicesWithTwoExclusives { + static NSArray *choicesWithTwoExclusives = nil; + + if (choicesWithTwoExclusives == nil) { + choicesWithTwoExclusives = @[[ORKTextChoice choiceWithText:@"choice 01" value:@"c1"], + [ORKTextChoice choiceWithText:@"choice 02" detailText:nil value:@"c2" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 03" detailText:nil value:@"c3" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 04" value:@"c4"]]; + } + + return choicesWithTwoExclusives; +} + +- (NSArray *)textChoicesWithAllExclusives { + static NSArray *choicesWithAllExclusives = nil; + + if (choicesWithAllExclusives == nil) { + choicesWithAllExclusives = @[[ORKTextChoice choiceWithText:@"choice 01" detailText:nil value:@"c1" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 02" detailText:nil value:@"c2" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 03" detailText:nil value:@"c3" exclusive:YES], + [ORKTextChoice choiceWithText:@"choice 04" detailText:nil value:@"c4" exclusive:YES]]; + } + + return choicesWithAllExclusives; +} + +- (void)testSingleChoice { + NSArray *choices = [self textChoices]; + ORKTextChoiceAnswerFormat *answerFormat = [ORKTextChoiceAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:choices]; + [self testSingleChoice:answerFormat choices:choices]; +} + +- (void)testSingleChoice:(ORKTextChoiceAnswerFormat *)answerFormat choices:(NSArray *)choices { + + ORKTextChoiceCellGroup *group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:YES]; + + // Basic check + XCTAssertEqual(group.size, choices.count, @""); + XCTAssertEqualObjects(group.answer, nil, @""); + XCTAssertEqualObjects(group.answerForBoolean, nil, @""); + + // Test containsIndexPath + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]], @""); + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:choices.count inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:choices.count-1 inSection:0]], @""); + + // Test cell generation + NSUInteger index = 0; + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNotNil(cell, @""); + XCTAssertEqualObjects(cell.reuseIdentifier, @"abc", @""); + XCTAssertEqual(cell.immediateNavigation, YES, @""); + } + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNil(cell, @""); + + // Regenerate cell group + group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:YES]; + + // Test cell selection + for ( index = 0 ; index < group.size; index++) { + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, 1); + + ORKTextChoice *choice = choices[index]; + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + XCTAssertEqualObjects(answerArray.firstObject, value, @"%@ vs %@", answerArray.firstObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, YES); + } + + // Test cell deselection (ORKChoiceAnswerStyleSingleChoice: selected cell should not deselect if chosen again) + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:group.size-1 inSection:0]]; + + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, 1); + + // Test set nil/null answer + [group setAnswer:nil]; + answer = group.answer; + XCTAssertNil(answer); + answerArray = answer; + XCTAssertEqual(answerArray.count, 0); + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(cell.isCellSelected, NO); + } + [group setAnswer:ORKNullAnswerValue()]; + XCTAssertEqual(answerArray.count, 0); + + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, NO); + } + + // Test set answer + for ( index = 0 ; index < group.size; index++) { + ORKTextChoice *choice = choices[index]; + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + [group setAnswer:@[value]]; + + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, 1); + + XCTAssertEqualObjects(answerArray.firstObject, value, @"%@ vs %@", answerArray.firstObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertTrue( cell.isCellSelected ); + } +} + +- (void)testMultiChoice { + ORKTextChoiceAnswerFormat *answerFormat = [ORKTextChoiceAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices:[self textChoices]]; + + ORKTextChoiceCellGroup *group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:NO]; + + // Test basics + XCTAssertEqual(group.size, [self textChoices].count, @""); + XCTAssertEqualObjects(group.answer, nil, @""); + XCTAssertEqualObjects(group.answerForBoolean, nil, @""); + + // Test containsIndexPath + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]], @""); + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:[self textChoices].count inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:[self textChoices].count-1 inSection:0]], @""); + + // Test cell generation + NSUInteger index = 0; + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNotNil(cell, @""); + XCTAssertEqualObjects(cell.reuseIdentifier, @"abc", @""); + XCTAssertEqual( cell.immediateNavigation, NO, @""); + } + + // Test cell generation with invalid indexPath + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNil(cell, @""); + + // Regenerate cellGroup + group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:NO]; + + // Test cell selection + for ( index = 0 ; index < group.size; index++) { + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, index+1); + + ORKTextChoice *choice = [self textChoices][index]; + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + XCTAssertEqualObjects(answerArray.lastObject, value, @"%@ vs %@", answerArray.lastObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, YES); + } + + // Test cell deselection + for ( index = 0 ; index < group.size; index++) { + + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + if (index < group.size - 1) { + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, group.size - index -1); + } else { + // Answer becomes NSNull when all cells are deselected + XCTAssert(answer == ORKNullAnswerValue()); + } + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, NO); + } + + XCTAssert(group.answer == ORKNullAnswerValue()); + + // Select all cells again + for ( index = 0 ; index < group.size; index++) { + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + } + + NSArray *answerArray = group.answer; + XCTAssertEqual(answerArray.count, group.size); + + // Test set nil/null answer + [group setAnswer:nil]; + XCTAssertNil(group.answer); + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssert( cell.cellSelected == NO); + } + + // Select all cells again + for ( index = 0 ; index < group.size; index++) { + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + } + + answerArray = group.answer; + XCTAssertEqual(answerArray.count, group.size); + + [group setAnswer:ORKNullAnswerValue()]; + XCTAssert(group.answer == ORKNullAnswerValue()); + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(cell.isCellSelected, NO); + } + + // Test set answers + NSMutableArray *answers = [NSMutableArray new]; + for ( index = 0 ; index < group.size; index++) { + ORKTextChoice *choice = [self textChoices][index]; + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + [answers addObject:value]; + + [group setAnswer:answers]; + + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, index + 1); + + XCTAssertEqualObjects(answerArray.lastObject, value, @"%@ vs %@", answerArray.lastObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertTrue( cell.isCellSelected ); + } +} + +- (void)testMultiChoiceWithOneExclusive { + [self testMultiChoiceWithExclusives:[self textChoicesWithOneExclusive]]; +} + +- (void)testMultiChoiceWithTwoExclusives { + [self testMultiChoiceWithExclusives:[self textChoicesWithTwoExclusives]]; +} + +- (void)testMultiChoiceWithExclusives:(NSArray *)choices { + ORKTextChoiceAnswerFormat *answerFormat = [ORKTextChoiceAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices:choices]; + + ORKTextChoiceCellGroup *group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:NO]; + + // Test basics + XCTAssertEqual(group.size, choices.count, @""); + XCTAssertEqualObjects(group.answer, nil, @""); + XCTAssertEqualObjects(group.answerForBoolean, nil, @""); + + // Test containsIndexPath + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]], @""); + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:choices.count inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:choices.count-1 inSection:0]], @""); + + // Test cell generation + NSUInteger index = 0; + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNotNil(cell, @""); + XCTAssertEqualObjects(cell.reuseIdentifier, @"abc", @""); + XCTAssertEqual( cell.immediateNavigation, NO, @""); + } + + // Test cell generation with invalid indexPath + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNil(cell, @""); + + // Regenerate cellGroup + group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:NO]; + + // Get the indexes of the exclusive and non-exclusive choices + NSMutableArray *exclusiveIndexes = [[NSMutableArray alloc] init]; + NSMutableArray *nonExclusiveIndexes = [[NSMutableArray alloc] init]; + for (index = 0 ; index < group.size; index++) { + ORKTextChoice *choice = choices[index]; + if (choice.exclusive) { + [exclusiveIndexes addObject:@(index)]; + } else { + [nonExclusiveIndexes addObject:@(index)]; + } + } + + // Test cell selection. First select all the non-exclusive choices, then do one exclusive + NSUInteger exclusiveIndexI = 0; + for (exclusiveIndexI = 0 ; exclusiveIndexI < exclusiveIndexes.count; exclusiveIndexI++) { + NSUInteger exclusiveIndex = ((NSNumber *)exclusiveIndexes[exclusiveIndexI]).unsignedIntegerValue; + + // Select all the non-exclusive choices, confirming the answer is including them all + NSUInteger nonExclusiveIndexI = 0; + for ( nonExclusiveIndexI = 0 ; nonExclusiveIndexI < nonExclusiveIndexes.count; nonExclusiveIndexI++) { + NSUInteger index = ((NSNumber *)nonExclusiveIndexes[nonExclusiveIndexI]).unsignedIntegerValue; + ORKTextChoice *choice = choices[index]; + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, nonExclusiveIndexI+1); + + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + XCTAssertEqualObjects(answerArray.lastObject, value, @"%@ vs %@", answerArray.lastObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, YES); + } + // Now, Select the exclusive choice, which should unselect all the non-exclusive choices chosen + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0]]; + id exclusiveAnswer = group.answer; + XCTAssert([exclusiveAnswer isKindOfClass:[NSArray class]]); + NSArray *exclusiveAnswerArray = exclusiveAnswer; + XCTAssertEqual(exclusiveAnswerArray.count, 1); + ORKChoiceViewCell *exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, YES); + + // Test cell deselection. First deselect the exclusive, and confirm no choices are selected + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0]]; + exclusiveAnswer = group.answer; + XCTAssert(exclusiveAnswer == ORKNullAnswerValue()); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, NO); + + // Now, select the exclusive choice again, and then select a non-exclusive choice, which + // should deselect the exclusive choice + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0]]; + exclusiveAnswer = group.answer; + XCTAssert([exclusiveAnswer isKindOfClass:[NSArray class]]); + exclusiveAnswerArray = exclusiveAnswer; + XCTAssertEqual(exclusiveAnswerArray.count, 1); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, YES); + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:((NSNumber *)nonExclusiveIndexes[0]).unsignedIntegerValue inSection:0]]; + exclusiveAnswer = group.answer; + XCTAssert([exclusiveAnswer isKindOfClass:[NSArray class]]); + exclusiveAnswerArray = exclusiveAnswer; + XCTAssertEqual(exclusiveAnswerArray.count, 1); + ORKChoiceViewCell *nonExclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:((NSNumber *)nonExclusiveIndexes[0]).unsignedIntegerValue inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(nonExclusiveCell.isCellSelected, YES); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, NO); + + // Deselect the non-exclusive to reset for the next test + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:((NSNumber *)nonExclusiveIndexes[0]).unsignedIntegerValue inSection:0]]; + + // If there are more than one exclusive choice, try selecting the current exclusive choice, and then + // selecting another exclusive choice, which should deselect the first + if (exclusiveIndexes.count > 1) { + NSUInteger otherExclusiveIndex = ((NSNumber *)exclusiveIndexes[(exclusiveIndexI+1)%exclusiveIndexes.count]).unsignedIntegerValue; + + // Select the current exclusive choice and confirm its selected + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0]]; + exclusiveAnswer = group.answer; + XCTAssert([exclusiveAnswer isKindOfClass:[NSArray class]]); + exclusiveAnswerArray = exclusiveAnswer; + XCTAssertEqual(exclusiveAnswerArray.count, 1); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, YES); + + // Select the other exclusive choice and confirm its selected, and the previously selected exclusive + // choice is no longer selected + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:otherExclusiveIndex inSection:0]]; + exclusiveAnswer = group.answer; + XCTAssert([exclusiveAnswer isKindOfClass:[NSArray class]]); + exclusiveAnswerArray = exclusiveAnswer; + XCTAssertEqual(exclusiveAnswerArray.count, 1); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:otherExclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, YES); + exclusiveCell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:exclusiveIndex inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(exclusiveCell.isCellSelected, NO); + + // Deselect the other exclusive choice to reset for the next test + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:otherExclusiveIndex inSection:0]]; + } + + // Now select all the non-exclusive choices + for (nonExclusiveIndexI = 0 ; nonExclusiveIndexI < nonExclusiveIndexes.count; nonExclusiveIndexI++) { + NSUInteger index = ((NSNumber *)nonExclusiveIndexes[nonExclusiveIndexI]).unsignedIntegerValue; + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, YES); + } + XCTAssertEqual(((NSArray *)group.answer).count, nonExclusiveIndexes.count); + + // Now, deselect all the non-exclusive choices one at a time + for (nonExclusiveIndexI = 0 ; nonExclusiveIndexI < nonExclusiveIndexes.count; nonExclusiveIndexI++) { + NSUInteger index = ((NSNumber *)nonExclusiveIndexes[nonExclusiveIndexI]).unsignedIntegerValue; + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + if (nonExclusiveIndexI < nonExclusiveIndexes.count - 1) { + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, nonExclusiveIndexes.count - nonExclusiveIndexI - 1); + } else { + // Answer becomes NSNull when there are no selected cells + XCTAssert(answer == ORKNullAnswerValue()); + } + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual( cell.isCellSelected, NO); + } + + id answer = group.answer; + XCTAssert(answer == ORKNullAnswerValue()); + } + + // Test set nil/null answer + [group setAnswer:nil]; + id answer = group.answer; + XCTAssertNil(answer); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, 0); + for ( index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssert(cell.cellSelected == NO); + } + [group setAnswer:ORKNullAnswerValue()]; + XCTAssertEqual(answerArray.count, 0); + + for (index = 0 ; index < group.size; index++) { + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertEqual(cell.isCellSelected, NO); + } + + // Test set answers + NSMutableArray *answers = [NSMutableArray new]; + for (index = 0 ; index < group.size; index++) { + ORKTextChoice *choice = choices[index]; + id value = choice.value; + + if (value == nil) { + value = @(index); + } + + [answers addObject:value]; + + [group setAnswer:answers]; + + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, index + 1); + + + XCTAssertEqualObjects(answerArray.lastObject, value, @"%@ vs %@", answerArray.lastObject, value ); + + ORKChoiceViewCell *cell = [group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertTrue(cell.isCellSelected ); + } +} + +- (void)testMultiChoiceWithAllExclusives { + // All exclusives should behave exactly like single choice mode, so use that test method + NSArray *choices = [self textChoicesWithAllExclusives]; + ORKTextChoiceAnswerFormat *answerFormat = [ORKTextChoiceAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:choices]; + [self testSingleChoice:answerFormat choices:choices]; +} + +- (void)testTextChoiceOthers { + NSArray *choices = [self textChoicesOther]; + ORKTextChoiceAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:choices]; + ORKTextChoiceCellGroup *group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:YES]; + + // Test basics + XCTAssertEqual(group.size, [self textChoices].count, @""); + XCTAssertEqualObjects(group.answer, nil, @""); + XCTAssertEqualObjects(group.answerForBoolean, nil, @""); + + // Test containsIndexPath + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]], @""); + XCTAssertFalse([group containsIndexPath:[NSIndexPath indexPathForRow:[self textChoices].count inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]], @""); + XCTAssertTrue([group containsIndexPath:[NSIndexPath indexPathForRow:[self textChoices].count-1 inSection:0]], @""); + + // Test cell generation + NSUInteger index = 0; + for ( index = 0 ; index < group.size; index++) { + ORKChoiceOtherViewCell *cell = (ORKChoiceOtherViewCell *)[group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + ORKTextChoiceOther *choice = choices[index]; + XCTAssertNotNil(cell, @""); + XCTAssertEqualObjects(cell.reuseIdentifier, @"abc", @""); + XCTAssertEqual(cell.immediateNavigation, YES, @""); + + if (choice.textViewStartsHidden) { + XCTAssertTrue(cell.textView.isHidden); + } + else { + XCTAssertFalse(cell.textView.isHidden); + } + XCTAssertEqual(choice.textViewPlaceholderText, cell.textView.placeholder); + } + + ORKChoiceOtherViewCell *cell = (ORKChoiceOtherViewCell *)[group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + XCTAssertNil(cell, @""); + + // Regenerate cell group + group = [[ORKTextChoiceCellGroup alloc] initWithTextChoiceAnswerFormat:answerFormat + answer:nil + beginningIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] + immediateNavigation:YES]; + + // Test cell selection + for ( index = 0 ; index < group.size; index++) { + ORKChoiceOtherViewCell *cell = (ORKChoiceOtherViewCell *)[group cellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] withReuseIdentifier:@"abc"]; + ORKTextChoiceOther *choice = choices[index]; + [group didSelectCellAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; + id answer = group.answer; + XCTAssert([answer isKindOfClass:[NSArray class]]); + NSArray *answerArray = answer; + XCTAssertEqual(answerArray.count, 1); + XCTAssertEqual(cell.isCellSelected, (choice.textViewInputOptional || cell.textView.text.length > 0)); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKUIViewAccessibilityTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKUIViewAccessibilityTests.m new file mode 100755 index 0000000..1e28739 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKUIViewAccessibilityTests.m @@ -0,0 +1,70 @@ +/* + Copyright (c) 2015, Denis Lebedev. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "UIView+ORKAccessibility.h" + + +@interface ORKUIViewAccessibilityTests : XCTestCase + +@end + + +@implementation ORKUIViewAccessibilityTests + +- (void)testSuperViewOfTypeReturnsNilWhenClassIsNil { + UIView *view = [[UIView alloc] init]; + + UIView *result = [view ork_superviewOfType:nil]; + XCTAssertNil(result); +} + +- (void)testReturnsNilWhenViewHasNoSuperView { + UIView *view = [[UIView alloc] init]; + + UIView *result = [view ork_superviewOfType:[UIView class]]; + XCTAssertNil(result); +} + +- (void)testReturnsSuperViewOfSpecifiedClass { + UIButton *button = [[UIButton alloc] init]; + UIView *view = [[UIView alloc] init]; + UIView *anotherView = [[UIView alloc] init]; + [button addSubview:view]; + [view addSubview:anotherView]; + + UIView *result = [anotherView ork_superviewOfType:[UIButton class]]; + XCTAssertEqualObjects(result, button); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVideoInstructionStepResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVideoInstructionStepResultTests.swift new file mode 100755 index 0000000..aee1ff5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVideoInstructionStepResultTests.swift @@ -0,0 +1,65 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest + +class ORKVideoInstructionStepResultTests: XCTestCase { + + var result: ORKVideoInstructionStepResult! + var identifier: String! + let date = Date() + + override func setUp() { + super.setUp() + identifier = "RESULT" + result = ORKVideoInstructionStepResult(identifier: identifier) + result.playbackCompleted = true + result.playbackStoppedTime = 20.00 + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifier) + XCTAssertEqual(result.playbackCompleted, true) + XCTAssertEqual(result.playbackStoppedTime, 20.00) + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKVideoInstructionStepResult(identifier: identifier) + newResult.startDate = date + newResult.endDate = date + newResult.playbackCompleted = true + newResult.playbackStoppedTime = 20.00 + + XCTAssert(result.isEqual(newResult)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVoiceEngineTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVoiceEngineTests.m new file mode 100755 index 0000000..e990076 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKVoiceEngineTests.m @@ -0,0 +1,151 @@ +/* + Copyright (c) 2015, Denis Lebedev. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKVoiceEngine_Internal.h" + + +@interface ORKMockSpeechSynthesizer : AVSpeechSynthesizer + +@property (nonatomic, readonly) BOOL didStopSpeaking; +@property (nonatomic, readonly) BOOL didSpeakText; +@property (nonatomic, readonly) NSString *speech; +@property (nonatomic, readonly) AVSpeechBoundary stopBoundary; +@property (nonatomic) BOOL mockSpeaking; + +@end + + +@implementation ORKMockSpeechSynthesizer + +- (BOOL)isSpeaking { + return self.mockSpeaking; +} + +- (BOOL)stopSpeakingAtBoundary:(AVSpeechBoundary)boundary { + _didStopSpeaking = YES; + _stopBoundary = boundary; + return YES; +} + +- (void)speakUtterance:(AVSpeechUtterance *)utterance { + _didSpeakText = YES; + _speech = utterance.speechString; +} + +@end + + +@interface ORKTestVoiceEngine : ORKVoiceEngine + +@end + + +@implementation ORKTestVoiceEngine { + ORKMockSpeechSynthesizer *_speechSynthesizer; +} + +- (AVSpeechSynthesizer *)speechSynthesizer { + if (!_speechSynthesizer) { + _speechSynthesizer = [[ORKMockSpeechSynthesizer alloc] init]; + } + return _speechSynthesizer; +} + +@end + + +@interface ORKVoiceEngineTests : XCTestCase + +@end + + +@implementation ORKVoiceEngineTests { + ORKVoiceEngine *_voiceEngine; + ORKMockSpeechSynthesizer *_mockSpeechSynthesizer; +} + +- (void)setUp { + [super setUp]; + _voiceEngine = [[ORKTestVoiceEngine alloc] init]; + _mockSpeechSynthesizer = (ORKMockSpeechSynthesizer *)_voiceEngine.speechSynthesizer; +} + +- (void)testSharedInstance { + XCTAssertEqualObjects([ORKVoiceEngine sharedVoiceEngine], [ORKVoiceEngine sharedVoiceEngine]); +} + +- (void)testSpeakText { + [_voiceEngine speakText:@"foo"]; + + XCTAssertTrue(_mockSpeechSynthesizer.didSpeakText); + XCTAssertEqualObjects(@"foo", _mockSpeechSynthesizer.speech); +} + +- (void)testSpeakTextWhenVoiceEngineIsAlreadySpeaking { + _mockSpeechSynthesizer.mockSpeaking = YES; + + [_voiceEngine speakText:@"foo"]; + + XCTAssertTrue(_mockSpeechSynthesizer.didStopSpeaking); + XCTAssertTrue(_mockSpeechSynthesizer.didSpeakText); + XCTAssertEqualObjects(@"foo", _mockSpeechSynthesizer.speech); +} + +- (void)testSpeakInt { + [_voiceEngine speakInt:42]; + + XCTAssertTrue(_mockSpeechSynthesizer.didSpeakText); + XCTAssertEqualObjects(@"42", _mockSpeechSynthesizer.speech); +} + +- (void)testStopTalking { + [_voiceEngine stopTalking]; + + XCTAssertTrue(_mockSpeechSynthesizer.didStopSpeaking); + XCTAssertEqual(_mockSpeechSynthesizer.stopBoundary, AVSpeechBoundaryWord); +} + +- (void)testIsSpeaking { + { + _mockSpeechSynthesizer.mockSpeaking = NO; + XCTAssertFalse(_voiceEngine.isSpeaking); + } + + { + _mockSpeechSynthesizer.mockSpeaking = YES; + XCTAssertTrue(_voiceEngine.isSpeaking); + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKWebViewStepResultTests.swift b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKWebViewStepResultTests.swift new file mode 100755 index 0000000..35ba0d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ORKWebViewStepResultTests.swift @@ -0,0 +1,61 @@ +/* + Copyright (c) 2019, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import XCTest + +class ORKWebViewStepResultTests: XCTestCase { + var result: ORKWebViewStepResult! + var identifer: String! + let date = Date() + + override func setUp() { + super.setUp() + identifer = "RESULT" + result = ORKWebViewStepResult(identifier: identifer) + result.result = "RESULTTORESULT" + } + + func testProperties() { + XCTAssertEqual(result.identifier, identifer) + XCTAssertEqual(result.result, "RESULTTORESULT") + } + + func testIsEqual() { + result.startDate = date + result.endDate = date + + let newResult = ORKWebViewStepResult(identifier: identifer) + newResult.startDate = date + newResult.endDate = date + newResult.result = "RESULTTORESULT" + + XCTAssert(result.isEqual(newResult)) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ResearchKitTests-Bridging-Header.h b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ResearchKitTests-Bridging-Header.h new file mode 100755 index 0000000..4ab1462 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/ResearchKitTests/ResearchKitTests-Bridging-Header.h @@ -0,0 +1,6 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ResearchKit.h" +#import "ResearchKit_Private.h" diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.pbxproj new file mode 100755 index 0000000..f15f0c6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.pbxproj @@ -0,0 +1,864 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 24D002781BA2268D001BF82F /* ORKKeychainWrapperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 24D002771BA2268D001BF82F /* ORKKeychainWrapperTests.m */; }; + 335418E91B118EAD00A38F5E /* SAMPLE_PDF_TEST.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 335418E81B118EAD00A38F5E /* SAMPLE_PDF_TEST.pdf */; }; + 712977A922B0917A0049213B /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 712977A622B091500049213B /* ResearchKit.framework */; }; + 712977AA22B0917A0049213B /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 712977A622B091500049213B /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 866DA52E1D63D1EE00C9AF3F /* ORKDataCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 866DA52D1D63D1EE00C9AF3F /* ORKDataCollectionTests.m */; }; + 86717A901AC0C0FE00AC2A23 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 86717A8F1AC0C0FE00AC2A23 /* main.m */; }; + 86717A931AC0C0FE00AC2A23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 86717A921AC0C0FE00AC2A23 /* AppDelegate.m */; }; + 86717A9B1AC0C0FE00AC2A23 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 86717A9A1AC0C0FE00AC2A23 /* Images.xcassets */; }; + 86717A9E1AC0C0FE00AC2A23 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 86717A9C1AC0C0FE00AC2A23 /* LaunchScreen.xib */; }; + 86717AE51AC0C53800AC2A23 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 86717AD71AC0C53800AC2A23 /* MainViewController.m */; }; + 86717AEA1AC0C53800AC2A23 /* image_example.png in Resources */ = {isa = PBXBuildFile; fileRef = 86717AE01AC0C53800AC2A23 /* image_example.png */; }; + 86717AED1AC0C53800AC2A23 /* signature.png in Resources */ = {isa = PBXBuildFile; fileRef = 86717AE31AC0C53800AC2A23 /* signature.png */; }; + 86717AFD1AC0C86000AC2A23 /* ORKJSONSerializationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 86717AFC1AC0C86000AC2A23 /* ORKJSONSerializationTests.m */; }; + 86717AFE1AC0C8BC00AC2A23 /* ORKESerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 86717AD81AC0C53800AC2A23 /* ORKESerialization.m */; }; + 86717B071AC0CC0400AC2A23 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 86717B091AC0CC0400AC2A23 /* Localizable.strings */; }; + 86D347FA1AC0E1B4006DB02B /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 86D347F91AC0E1B4006DB02B /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + B119F055229BD4B6001402F9 /* samples.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B119F054229BD4B6001402F9 /* samples.bundle */; }; + BCEDC7D71E8A45DE00C5405F /* ChartDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7D31E8A45DE00C5405F /* ChartDataSources.swift */; }; + BCEDC7D81E8A45DE00C5405F /* ChartListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7D41E8A45DE00C5405F /* ChartListViewController.swift */; }; + BCEDC7D91E8A45DE00C5405F /* Charts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BCEDC7D51E8A45DE00C5405F /* Charts.storyboard */; }; + BCEDC7DA1E8A45DE00C5405F /* ChartTableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7D61E8A45DE00C5405F /* ChartTableViewCells.swift */; }; + BCEDC7E41E8A45EE00C5405F /* ContinueButtonExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7DD1E8A45EE00C5405F /* ContinueButtonExampleViewController.m */; }; + BCEDC7E51E8A45EE00C5405F /* DragonPokerStep.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7DF1E8A45EE00C5405F /* DragonPokerStep.m */; }; + BCEDC7E61E8A45EE00C5405F /* DynamicTask.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7E11E8A45EE00C5405F /* DynamicTask.m */; }; + BCEDC7E71E8A45EE00C5405F /* FooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7E31E8A45EE00C5405F /* FooterView.m */; }; + BCEDC7FC1E8A469D00C5405F /* TaskFactory+ActiveTasks.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7EA1E8A469D00C5405F /* TaskFactory+ActiveTasks.m */; }; + BCEDC7FD1E8A469D00C5405F /* TaskFactory+Forms.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7EC1E8A469D00C5405F /* TaskFactory+Forms.m */; }; + BCEDC7FE1E8A469D00C5405F /* TaskFactory+Onboarding.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7EE1E8A469D00C5405F /* TaskFactory+Onboarding.m */; }; + BCEDC7FF1E8A469D00C5405F /* TaskFactory+PasscodeManagement.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7F01E8A469D00C5405F /* TaskFactory+PasscodeManagement.m */; }; + BCEDC8001E8A469D00C5405F /* TaskFactory+QuestionSteps.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7F21E8A469D00C5405F /* TaskFactory+QuestionSteps.m */; }; + BCEDC8011E8A469D00C5405F /* TaskFactory+TaskCustomization.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7F41E8A469D00C5405F /* TaskFactory+TaskCustomization.m */; }; + BCEDC8021E8A469D00C5405F /* TaskFactory+TaskReview.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7F61E8A469D00C5405F /* TaskFactory+TaskReview.m */; }; + BCEDC8031E8A469D00C5405F /* TaskFactory+UtilitySteps.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7F81E8A469D00C5405F /* TaskFactory+UtilitySteps.m */; }; + BCEDC8041E8A469D00C5405F /* TaskFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7FA1E8A469D00C5405F /* TaskFactory.m */; }; + BCEDC8051E8A469D00C5405F /* TaskFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCEDC7FB1E8A469D00C5405F /* TaskFactory.swift */; }; + CAF31DCF1BC6AEA200041163 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CAF31DCE1BC6AEA200041163 /* MapKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + FFF010751D21F2030054B430 /* ContinueButtonExample.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FFF010741D21F2030054B430 /* ContinueButtonExample.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 712977A522B091500049213B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7129779F22B091500049213B /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = B183A5951A8535D100C76870; + remoteInfo = ResearchKit; + }; + 712977A722B091500049213B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 7129779F22B091500049213B /* ResearchKit.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 86CC8E9A1AC09332001CCD89; + remoteInfo = ResearchKitTests; + }; + 86717AA41AC0C0FE00AC2A23 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 86717A821AC0C0FE00AC2A23 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 86717A891AC0C0FE00AC2A23; + remoteInfo = ORKTest; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + BC2A3CE31C58F1EE00DA64B7 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 712977AA22B0917A0049213B /* ResearchKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 24D002771BA2268D001BF82F /* ORKKeychainWrapperTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKKeychainWrapperTests.m; sourceTree = ""; }; + 335418E81B118EAD00A38F5E /* SAMPLE_PDF_TEST.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = SAMPLE_PDF_TEST.pdf; sourceTree = ""; }; + 7129779F22B091500049213B /* ResearchKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ResearchKit.xcodeproj; path = ../../ResearchKit.xcodeproj; sourceTree = ""; }; + 866DA52D1D63D1EE00C9AF3F /* ORKDataCollectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKDataCollectionTests.m; sourceTree = ""; }; + 86717A8A1AC0C0FE00AC2A23 /* ORKTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 86717A8E1AC0C0FE00AC2A23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 86717A8F1AC0C0FE00AC2A23 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 86717A911AC0C0FE00AC2A23 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 86717A921AC0C0FE00AC2A23 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 86717A9A1AC0C0FE00AC2A23 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 86717A9D1AC0C0FE00AC2A23 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 86717AA31AC0C0FE00AC2A23 /* ORKTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ORKTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 86717AA81AC0C0FE00AC2A23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 86717AD71AC0C53800AC2A23 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; + 86717AD81AC0C53800AC2A23 /* ORKESerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKESerialization.m; sourceTree = ""; }; + 86717ADE1AC0C53800AC2A23 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; + 86717AE01AC0C53800AC2A23 /* image_example.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = image_example.png; sourceTree = ""; }; + 86717AE31AC0C53800AC2A23 /* signature.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = signature.png; sourceTree = ""; }; + 86717AFC1AC0C86000AC2A23 /* ORKJSONSerializationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ORKJSONSerializationTests.m; sourceTree = ""; }; + 86717AFF1AC0C93E00AC2A23 /* ORKESerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ORKESerialization.h; sourceTree = ""; }; + 86717B081AC0CC0400AC2A23 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 86717B0A1AC0CC1A00AC2A23 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 86717B0B1AC0CC1C00AC2A23 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + 86717B0C1AC0CC1D00AC2A23 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + 86717B0F1AC0CC2500AC2A23 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + 86717B101AC0CC2700AC2A23 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 86717B121AC0CC2A00AC2A23 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 86717B131AC0CC2A00AC2A23 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; + 86717B141AC0CC2C00AC2A23 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + 86717B151AC0CC2D00AC2A23 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = ""; }; + 86717B171AC0CC2F00AC2A23 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; + 86717B181AC0CC3000AC2A23 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; + 86717B191AC0CC3100AC2A23 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + 86717B1B1AC0CC3300AC2A23 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + 86717B1C1AC0CC3400AC2A23 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + 86717B1D1AC0CC3500AC2A23 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + 86717B1E1AC0CC3700AC2A23 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; + 86717B1F1AC0CC3A00AC2A23 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = ""; }; + 86717B201AC0CC3B00AC2A23 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; + 86717B211AC0CC3E00AC2A23 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; + 86717B221AC0CC3F00AC2A23 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = ""; }; + 86717B231AC0CC4000AC2A23 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; + 86717B241AC0CC4100AC2A23 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; + 86717B251AC0CC4200AC2A23 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; + 86717B261AC0CC4300AC2A23 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; + 86717B271AC0CC4400AC2A23 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; + 86717B281AC0CC4600AC2A23 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; + 86717B291AC0CC4700AC2A23 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; + 86717B2A1AC0CC4800AC2A23 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; + 86717B2B1AC0CC4A00AC2A23 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + 86D347F91AC0E1B4006DB02B /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; + 86D347FB1AC0E1B4006DB02B /* ORKTest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = ORKTest.entitlements; sourceTree = ""; }; + B119F054229BD4B6001402F9 /* samples.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = samples.bundle; sourceTree = ""; }; + B1337BA01B1E709B0098AA54 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-CA"; path = "fr-CA.lproj/Localizable.strings"; sourceTree = ""; }; + B1337BA11B1E709C0098AA54 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + B1337BA21B1E70A00098AA54 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "zh-HK.lproj/Localizable.strings"; sourceTree = ""; }; + B1337BA31B1E70A10098AA54 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = ""; }; + B1337BA41B1E70A20098AA54 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Localizable.strings"; sourceTree = ""; }; + B1337BA51B1E70AA0098AA54 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = ""; }; + B1337BA61B1E70AB0098AA54 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; + B1337BA71B1E70AC0098AA54 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = ""; }; + B15636901B1F8A0700B28200 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Localizable.strings"; sourceTree = ""; }; + B15636931B1F8A0800B28200 /* en-AU */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-AU"; path = "en-AU.lproj/Localizable.strings"; sourceTree = ""; }; + BC2A3CA01C58E85D00DA64B7 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + BCEDC7D31E8A45DE00C5405F /* ChartDataSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartDataSources.swift; sourceTree = ""; }; + BCEDC7D41E8A45DE00C5405F /* ChartListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartListViewController.swift; sourceTree = ""; }; + BCEDC7D51E8A45DE00C5405F /* Charts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Charts.storyboard; sourceTree = ""; }; + BCEDC7D61E8A45DE00C5405F /* ChartTableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChartTableViewCells.swift; sourceTree = ""; }; + BCEDC7DC1E8A45EE00C5405F /* ContinueButtonExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContinueButtonExampleViewController.h; sourceTree = ""; }; + BCEDC7DD1E8A45EE00C5405F /* ContinueButtonExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContinueButtonExampleViewController.m; sourceTree = ""; }; + BCEDC7DE1E8A45EE00C5405F /* DragonPokerStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DragonPokerStep.h; sourceTree = ""; }; + BCEDC7DF1E8A45EE00C5405F /* DragonPokerStep.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DragonPokerStep.m; sourceTree = ""; }; + BCEDC7E01E8A45EE00C5405F /* DynamicTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicTask.h; sourceTree = ""; }; + BCEDC7E11E8A45EE00C5405F /* DynamicTask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DynamicTask.m; sourceTree = ""; }; + BCEDC7E21E8A45EE00C5405F /* FooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FooterView.h; sourceTree = ""; }; + BCEDC7E31E8A45EE00C5405F /* FooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FooterView.m; sourceTree = ""; }; + BCEDC7E91E8A469D00C5405F /* TaskFactory+ActiveTasks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+ActiveTasks.h"; sourceTree = ""; }; + BCEDC7EA1E8A469D00C5405F /* TaskFactory+ActiveTasks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+ActiveTasks.m"; sourceTree = ""; }; + BCEDC7EB1E8A469D00C5405F /* TaskFactory+Forms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+Forms.h"; sourceTree = ""; }; + BCEDC7EC1E8A469D00C5405F /* TaskFactory+Forms.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+Forms.m"; sourceTree = ""; }; + BCEDC7ED1E8A469D00C5405F /* TaskFactory+Onboarding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+Onboarding.h"; sourceTree = ""; }; + BCEDC7EE1E8A469D00C5405F /* TaskFactory+Onboarding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+Onboarding.m"; sourceTree = ""; }; + BCEDC7EF1E8A469D00C5405F /* TaskFactory+PasscodeManagement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+PasscodeManagement.h"; sourceTree = ""; }; + BCEDC7F01E8A469D00C5405F /* TaskFactory+PasscodeManagement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+PasscodeManagement.m"; sourceTree = ""; }; + BCEDC7F11E8A469D00C5405F /* TaskFactory+QuestionSteps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+QuestionSteps.h"; sourceTree = ""; }; + BCEDC7F21E8A469D00C5405F /* TaskFactory+QuestionSteps.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+QuestionSteps.m"; sourceTree = ""; }; + BCEDC7F31E8A469D00C5405F /* TaskFactory+TaskCustomization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+TaskCustomization.h"; sourceTree = ""; }; + BCEDC7F41E8A469D00C5405F /* TaskFactory+TaskCustomization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+TaskCustomization.m"; sourceTree = ""; }; + BCEDC7F51E8A469D00C5405F /* TaskFactory+TaskReview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+TaskReview.h"; sourceTree = ""; }; + BCEDC7F61E8A469D00C5405F /* TaskFactory+TaskReview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+TaskReview.m"; sourceTree = ""; }; + BCEDC7F71E8A469D00C5405F /* TaskFactory+UtilitySteps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TaskFactory+UtilitySteps.h"; sourceTree = ""; }; + BCEDC7F81E8A469D00C5405F /* TaskFactory+UtilitySteps.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TaskFactory+UtilitySteps.m"; sourceTree = ""; }; + BCEDC7F91E8A469D00C5405F /* TaskFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TaskFactory.h; sourceTree = ""; }; + BCEDC7FA1E8A469D00C5405F /* TaskFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TaskFactory.m; sourceTree = ""; }; + BCEDC7FB1E8A469D00C5405F /* TaskFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskFactory.swift; sourceTree = ""; }; + CAF31DCE1BC6AEA200041163 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; + FFF010741D21F2030054B430 /* ContinueButtonExample.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = ContinueButtonExample.storyboard; path = "ORKTest/Supporting Files/ContinueButtonExample.storyboard"; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 86717A871AC0C0FE00AC2A23 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CAF31DCF1BC6AEA200041163 /* MapKit.framework in Frameworks */, + 86D347FA1AC0E1B4006DB02B /* HealthKit.framework in Frameworks */, + 712977A922B0917A0049213B /* ResearchKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86717AA01AC0C0FE00AC2A23 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 712977A022B091500049213B /* Products */ = { + isa = PBXGroup; + children = ( + 712977A622B091500049213B /* ResearchKit.framework */, + 712977A822B091500049213B /* ResearchKitTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 86717A811AC0C0FE00AC2A23 = { + isa = PBXGroup; + children = ( + 7129779F22B091500049213B /* ResearchKit.xcodeproj */, + BC2A3CA01C58E85D00DA64B7 /* README.md */, + BC2A3C9F1C58E83B00DA64B7 /* Frameworks */, + 86717A8C1AC0C0FE00AC2A23 /* ORKTest */, + 86717AA61AC0C0FE00AC2A23 /* ORKTestTests */, + 86717A8B1AC0C0FE00AC2A23 /* Products */, + ); + sourceTree = ""; + }; + 86717A8B1AC0C0FE00AC2A23 /* Products */ = { + isa = PBXGroup; + children = ( + 86717A8A1AC0C0FE00AC2A23 /* ORKTest.app */, + 86717AA31AC0C0FE00AC2A23 /* ORKTestTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 86717A8C1AC0C0FE00AC2A23 /* ORKTest */ = { + isa = PBXGroup; + children = ( + BCEDC7DB1E8A45EE00C5405F /* Customization */, + BC9A27111B81732200BDA84D /* Charts */, + BCEDC7E81E8A469D00C5405F /* Tasks */, + 86717B011AC0C9D400AC2A23 /* Resources */, + 86717A8D1AC0C0FE00AC2A23 /* Supporting Files */, + 86717A911AC0C0FE00AC2A23 /* AppDelegate.h */, + 86717A921AC0C0FE00AC2A23 /* AppDelegate.m */, + 86717ADE1AC0C53800AC2A23 /* MainViewController.h */, + 86717AD71AC0C53800AC2A23 /* MainViewController.m */, + ); + path = ORKTest; + sourceTree = ""; + }; + 86717A8D1AC0C0FE00AC2A23 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 86D347FB1AC0E1B4006DB02B /* ORKTest.entitlements */, + 86717A8E1AC0C0FE00AC2A23 /* Info.plist */, + 86717A8F1AC0C0FE00AC2A23 /* main.m */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + 86717AA61AC0C0FE00AC2A23 /* ORKTestTests */ = { + isa = PBXGroup; + children = ( + B119F054229BD4B6001402F9 /* samples.bundle */, + 866DA52D1D63D1EE00C9AF3F /* ORKDataCollectionTests.m */, + 86717AFF1AC0C93E00AC2A23 /* ORKESerialization.h */, + 86717AD81AC0C53800AC2A23 /* ORKESerialization.m */, + 86717AFC1AC0C86000AC2A23 /* ORKJSONSerializationTests.m */, + 24D002771BA2268D001BF82F /* ORKKeychainWrapperTests.m */, + 86717AA71AC0C0FE00AC2A23 /* Supporting Files */, + ); + path = ORKTestTests; + sourceTree = ""; + }; + 86717AA71AC0C0FE00AC2A23 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 86717AA81AC0C0FE00AC2A23 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 86717B011AC0C9D400AC2A23 /* Resources */ = { + isa = PBXGroup; + children = ( + FFF010741D21F2030054B430 /* ContinueButtonExample.storyboard */, + 335418E81B118EAD00A38F5E /* SAMPLE_PDF_TEST.pdf */, + 86717AE01AC0C53800AC2A23 /* image_example.png */, + 86717AE31AC0C53800AC2A23 /* signature.png */, + 86717A9A1AC0C0FE00AC2A23 /* Images.xcassets */, + 86717A9C1AC0C0FE00AC2A23 /* LaunchScreen.xib */, + 86717B091AC0CC0400AC2A23 /* Localizable.strings */, + ); + path = Resources; + sourceTree = ""; + }; + BC2A3C9F1C58E83B00DA64B7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CAF31DCE1BC6AEA200041163 /* MapKit.framework */, + 86D347F91AC0E1B4006DB02B /* HealthKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + BC9A27111B81732200BDA84D /* Charts */ = { + isa = PBXGroup; + children = ( + BCEDC7D31E8A45DE00C5405F /* ChartDataSources.swift */, + BCEDC7D41E8A45DE00C5405F /* ChartListViewController.swift */, + BCEDC7D51E8A45DE00C5405F /* Charts.storyboard */, + BCEDC7D61E8A45DE00C5405F /* ChartTableViewCells.swift */, + ); + path = Charts; + sourceTree = ""; + }; + BCEDC7DB1E8A45EE00C5405F /* Customization */ = { + isa = PBXGroup; + children = ( + BCEDC7DC1E8A45EE00C5405F /* ContinueButtonExampleViewController.h */, + BCEDC7DD1E8A45EE00C5405F /* ContinueButtonExampleViewController.m */, + BCEDC7DE1E8A45EE00C5405F /* DragonPokerStep.h */, + BCEDC7DF1E8A45EE00C5405F /* DragonPokerStep.m */, + BCEDC7E01E8A45EE00C5405F /* DynamicTask.h */, + BCEDC7E11E8A45EE00C5405F /* DynamicTask.m */, + BCEDC7E21E8A45EE00C5405F /* FooterView.h */, + BCEDC7E31E8A45EE00C5405F /* FooterView.m */, + ); + path = Customization; + sourceTree = ""; + }; + BCEDC7E81E8A469D00C5405F /* Tasks */ = { + isa = PBXGroup; + children = ( + BCEDC7E91E8A469D00C5405F /* TaskFactory+ActiveTasks.h */, + BCEDC7EA1E8A469D00C5405F /* TaskFactory+ActiveTasks.m */, + BCEDC7EB1E8A469D00C5405F /* TaskFactory+Forms.h */, + BCEDC7EC1E8A469D00C5405F /* TaskFactory+Forms.m */, + BCEDC7ED1E8A469D00C5405F /* TaskFactory+Onboarding.h */, + BCEDC7EE1E8A469D00C5405F /* TaskFactory+Onboarding.m */, + BCEDC7EF1E8A469D00C5405F /* TaskFactory+PasscodeManagement.h */, + BCEDC7F01E8A469D00C5405F /* TaskFactory+PasscodeManagement.m */, + BCEDC7F11E8A469D00C5405F /* TaskFactory+QuestionSteps.h */, + BCEDC7F21E8A469D00C5405F /* TaskFactory+QuestionSteps.m */, + BCEDC7F31E8A469D00C5405F /* TaskFactory+TaskCustomization.h */, + BCEDC7F41E8A469D00C5405F /* TaskFactory+TaskCustomization.m */, + BCEDC7F51E8A469D00C5405F /* TaskFactory+TaskReview.h */, + BCEDC7F61E8A469D00C5405F /* TaskFactory+TaskReview.m */, + BCEDC7F71E8A469D00C5405F /* TaskFactory+UtilitySteps.h */, + BCEDC7F81E8A469D00C5405F /* TaskFactory+UtilitySteps.m */, + BCEDC7F91E8A469D00C5405F /* TaskFactory.h */, + BCEDC7FA1E8A469D00C5405F /* TaskFactory.m */, + BCEDC7FB1E8A469D00C5405F /* TaskFactory.swift */, + ); + path = Tasks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 86717A891AC0C0FE00AC2A23 /* ORKTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 86717AAD1AC0C0FE00AC2A23 /* Build configuration list for PBXNativeTarget "ORKTest" */; + buildPhases = ( + 86717A861AC0C0FE00AC2A23 /* Sources */, + 86717A871AC0C0FE00AC2A23 /* Frameworks */, + 86717A881AC0C0FE00AC2A23 /* Resources */, + BC2A3CE31C58F1EE00DA64B7 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ORKTest; + productName = ORKTest; + productReference = 86717A8A1AC0C0FE00AC2A23 /* ORKTest.app */; + productType = "com.apple.product-type.application"; + }; + 86717AA21AC0C0FE00AC2A23 /* ORKTestTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 86717AB01AC0C0FE00AC2A23 /* Build configuration list for PBXNativeTarget "ORKTestTests" */; + buildPhases = ( + 86717A9F1AC0C0FE00AC2A23 /* Sources */, + 86717AA01AC0C0FE00AC2A23 /* Frameworks */, + 86717AA11AC0C0FE00AC2A23 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 86717AA51AC0C0FE00AC2A23 /* PBXTargetDependency */, + ); + name = ORKTestTests; + productName = ORKTestTests; + productReference = 86717AA31AC0C0FE00AC2A23 /* ORKTestTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 86717A821AC0C0FE00AC2A23 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 1000; + ORGANIZATIONNAME = ResearchKit; + TargetAttributes = { + 86717A891AC0C0FE00AC2A23 = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 1020; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.BackgroundModes = { + enabled = 1; + }; + com.apple.HealthKit = { + enabled = 1; + }; + }; + }; + 86717AA21AC0C0FE00AC2A23 = { + CreatedOnToolsVersion = 6.2; + ProvisioningStyle = Manual; + TestTargetID = 86717A891AC0C0FE00AC2A23; + }; + }; + }; + buildConfigurationList = 86717A851AC0C0FE00AC2A23 /* Build configuration list for PBXProject "ORKTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + fr, + fr_CA, + de, + zh_CN, + zh_HK, + zh_TW, + ja, + es, + es_MX, + hi, + no, + it, + ko, + nl, + pt, + pt_PT, + da, + fi, + sv, + ru, + pl, + tr, + ar, + th, + cs, + vi, + ms, + id, + uk, + sk, + ro, + he, + hr, + ca, + el, + hu, + "fr-CA", + "zh-Hans", + "zh-HK", + "zh-Hant", + "es-MX", + nb, + "pt-PT", + "en-GB", + "en-AU", + ); + mainGroup = 86717A811AC0C0FE00AC2A23; + productRefGroup = 86717A8B1AC0C0FE00AC2A23 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 712977A022B091500049213B /* Products */; + ProjectRef = 7129779F22B091500049213B /* ResearchKit.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 86717A891AC0C0FE00AC2A23 /* ORKTest */, + 86717AA21AC0C0FE00AC2A23 /* ORKTestTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 712977A622B091500049213B /* ResearchKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ResearchKit.framework; + remoteRef = 712977A522B091500049213B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 712977A822B091500049213B /* ResearchKitTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ResearchKitTests.xctest; + remoteRef = 712977A722B091500049213B /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 86717A881AC0C0FE00AC2A23 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FFF010751D21F2030054B430 /* ContinueButtonExample.storyboard in Resources */, + 86717A9E1AC0C0FE00AC2A23 /* LaunchScreen.xib in Resources */, + 335418E91B118EAD00A38F5E /* SAMPLE_PDF_TEST.pdf in Resources */, + 86717AED1AC0C53800AC2A23 /* signature.png in Resources */, + 86717AEA1AC0C53800AC2A23 /* image_example.png in Resources */, + BCEDC7D91E8A45DE00C5405F /* Charts.storyboard in Resources */, + 86717B071AC0CC0400AC2A23 /* Localizable.strings in Resources */, + 86717A9B1AC0C0FE00AC2A23 /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86717AA11AC0C0FE00AC2A23 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B119F055229BD4B6001402F9 /* samples.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 86717A861AC0C0FE00AC2A23 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BCEDC7DA1E8A45DE00C5405F /* ChartTableViewCells.swift in Sources */, + BCEDC7E41E8A45EE00C5405F /* ContinueButtonExampleViewController.m in Sources */, + 86717A931AC0C0FE00AC2A23 /* AppDelegate.m in Sources */, + BCEDC7FD1E8A469D00C5405F /* TaskFactory+Forms.m in Sources */, + BCEDC7D81E8A45DE00C5405F /* ChartListViewController.swift in Sources */, + BCEDC8021E8A469D00C5405F /* TaskFactory+TaskReview.m in Sources */, + BCEDC7E51E8A45EE00C5405F /* DragonPokerStep.m in Sources */, + BCEDC8051E8A469D00C5405F /* TaskFactory.swift in Sources */, + BCEDC7E71E8A45EE00C5405F /* FooterView.m in Sources */, + BCEDC7D71E8A45DE00C5405F /* ChartDataSources.swift in Sources */, + BCEDC7E61E8A45EE00C5405F /* DynamicTask.m in Sources */, + BCEDC8031E8A469D00C5405F /* TaskFactory+UtilitySteps.m in Sources */, + BCEDC7FC1E8A469D00C5405F /* TaskFactory+ActiveTasks.m in Sources */, + BCEDC7FF1E8A469D00C5405F /* TaskFactory+PasscodeManagement.m in Sources */, + 86717AE51AC0C53800AC2A23 /* MainViewController.m in Sources */, + BCEDC8011E8A469D00C5405F /* TaskFactory+TaskCustomization.m in Sources */, + 86717A901AC0C0FE00AC2A23 /* main.m in Sources */, + BCEDC8001E8A469D00C5405F /* TaskFactory+QuestionSteps.m in Sources */, + BCEDC7FE1E8A469D00C5405F /* TaskFactory+Onboarding.m in Sources */, + BCEDC8041E8A469D00C5405F /* TaskFactory.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 86717A9F1AC0C0FE00AC2A23 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 86717AFD1AC0C86000AC2A23 /* ORKJSONSerializationTests.m in Sources */, + 866DA52E1D63D1EE00C9AF3F /* ORKDataCollectionTests.m in Sources */, + 86717AFE1AC0C8BC00AC2A23 /* ORKESerialization.m in Sources */, + 24D002781BA2268D001BF82F /* ORKKeychainWrapperTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 86717AA51AC0C0FE00AC2A23 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 86717A891AC0C0FE00AC2A23 /* ORKTest */; + targetProxy = 86717AA41AC0C0FE00AC2A23 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 86717A9C1AC0C0FE00AC2A23 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 86717A9D1AC0C0FE00AC2A23 /* Base */, + ); + name = LaunchScreen.xib; + path = Localized; + sourceTree = ""; + }; + 86717B091AC0CC0400AC2A23 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 86717B081AC0CC0400AC2A23 /* Base */, + 86717B0A1AC0CC1A00AC2A23 /* en */, + 86717B0B1AC0CC1C00AC2A23 /* fr */, + 86717B0C1AC0CC1D00AC2A23 /* de */, + 86717B0F1AC0CC2500AC2A23 /* ja */, + 86717B101AC0CC2700AC2A23 /* es */, + 86717B121AC0CC2A00AC2A23 /* it */, + 86717B131AC0CC2A00AC2A23 /* ko */, + 86717B141AC0CC2C00AC2A23 /* nl */, + 86717B151AC0CC2D00AC2A23 /* pt */, + 86717B171AC0CC2F00AC2A23 /* da */, + 86717B181AC0CC3000AC2A23 /* fi */, + 86717B191AC0CC3100AC2A23 /* sv */, + 86717B1B1AC0CC3300AC2A23 /* ru */, + 86717B1C1AC0CC3400AC2A23 /* pl */, + 86717B1D1AC0CC3500AC2A23 /* tr */, + 86717B1E1AC0CC3700AC2A23 /* ar */, + 86717B1F1AC0CC3A00AC2A23 /* th */, + 86717B201AC0CC3B00AC2A23 /* cs */, + 86717B211AC0CC3E00AC2A23 /* vi */, + 86717B221AC0CC3F00AC2A23 /* ms */, + 86717B231AC0CC4000AC2A23 /* id */, + 86717B241AC0CC4100AC2A23 /* uk */, + 86717B251AC0CC4200AC2A23 /* sk */, + 86717B261AC0CC4300AC2A23 /* ro */, + 86717B271AC0CC4400AC2A23 /* he */, + 86717B281AC0CC4600AC2A23 /* hr */, + 86717B291AC0CC4700AC2A23 /* ca */, + 86717B2A1AC0CC4800AC2A23 /* el */, + 86717B2B1AC0CC4A00AC2A23 /* hu */, + B1337BA01B1E709B0098AA54 /* fr-CA */, + B1337BA11B1E709C0098AA54 /* zh-Hans */, + B1337BA21B1E70A00098AA54 /* zh-HK */, + B1337BA31B1E70A10098AA54 /* zh-Hant */, + B1337BA41B1E70A20098AA54 /* es-MX */, + B1337BA51B1E70AA0098AA54 /* hi */, + B1337BA61B1E70AB0098AA54 /* nb */, + B1337BA71B1E70AC0098AA54 /* pt-PT */, + B15636901B1F8A0700B28200 /* en-GB */, + B15636931B1F8A0800B28200 /* en-AU */, + ); + name = Localizable.strings; + path = Localized; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 86717AAB1AC0C0FE00AC2A23 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 86717AAC1AC0C0FE00AC2A23 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 86717AAE1AC0C0FE00AC2A23 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "ORKTest/Supporting Files/ORKTest.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKTest/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "ORKTest/Supporting Files/ORKTest-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 86717AAF1AC0C0FE00AC2A23 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "ORKTest/Supporting Files/ORKTest.entitlements"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKTest/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKTest"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "ORKTest/Supporting Files/ORKTest-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; + 86717AB11AC0C0FE00AC2A23 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = ORKTestTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ORKTest.app/ORKTest"; + }; + name = Debug; + }; + 86717AB21AC0C0FE00AC2A23 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = ORKTestTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ORKTest.app/ORKTest"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 86717A851AC0C0FE00AC2A23 /* Build configuration list for PBXProject "ORKTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 86717AAB1AC0C0FE00AC2A23 /* Debug */, + 86717AAC1AC0C0FE00AC2A23 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 86717AAD1AC0C0FE00AC2A23 /* Build configuration list for PBXNativeTarget "ORKTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 86717AAE1AC0C0FE00AC2A23 /* Debug */, + 86717AAF1AC0C0FE00AC2A23 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 86717AB01AC0C0FE00AC2A23 /* Build configuration list for PBXNativeTarget "ORKTestTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 86717AB11AC0C0FE00AC2A23 /* Debug */, + 86717AB21AC0C0FE00AC2A23 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 86717A821AC0C0FE00AC2A23 /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..c22a64d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/xcshareddata/xcschemes/ORKTest.xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/xcshareddata/xcschemes/ORKTest.xcscheme new file mode 100755 index 0000000..94740bb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest.xcodeproj/xcshareddata/xcschemes/ORKTest.xcscheme @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.h new file mode 100755 index 0000000..ccb2aae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.m new file mode 100755 index 0000000..b971a89 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/AppDelegate.m @@ -0,0 +1,69 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "AppDelegate.h" +#import "MainViewController.h" + + +@implementation AppDelegate + +/* + For UI state restoration, we must configure the app and make the window key + in willFinishLaunchingWithOptions:. Otherwise, the restored task view controller + will animate in. + */ +- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + self.window.backgroundColor = [UIColor blackColor]; + self.window.rootViewController = [MainViewController new]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + return YES; +} + +#pragma mark UI state restoration + +/* + These methods are needed in order to enable UI state restoration. + */ + +- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder { + return YES; +} + +- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder { + return YES; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartDataSources.swift b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartDataSources.swift new file mode 100755 index 0000000..543be94 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartDataSources.swift @@ -0,0 +1,465 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. +Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +func randomColorArray(_ number: Int) -> [UIColor] { + + func random() -> CGFloat { + return CGFloat(Float(arc4random()) / Float(UINT32_MAX)) + } + + var colors: [UIColor] = [] + for _ in 0 ..< number { + colors.append(UIColor(red: random(), green: random(), blue: random(), alpha: 1)) + } + return colors + } + +let numberOfPieChartSegments = 13 + +class ColorlessPieChartDataSource: NSObject, ORKPieChartViewDataSource { + + func numberOfSegments(in pieChartView: ORKPieChartView ) -> Int { + return numberOfPieChartSegments + } + + func pieChartView(_ pieChartView: ORKPieChartView, valueForSegmentAt index: Int) -> CGFloat { + return CGFloat(index + 1) + } + + func pieChartView(_ pieChartView: ORKPieChartView, titleForSegmentAt index: Int) -> String? { + return "Title \(index + 1)" + } +} + +class RandomColorPieChartDataSource: ColorlessPieChartDataSource { + + lazy var backingStore: [UIColor] = { + return randomColorArray(numberOfPieChartSegments) + }() + + func pieChartView(_ pieChartView: ORKPieChartView, colorForSegmentAtIndex index: Int) -> UIColor { + return backingStore[index] + } +} + +class BaseFloatRangeGraphChartDataSource: NSObject, ORKValueRangeGraphChartViewDataSource { + var plotPoints: [[ORKValueRange]] = [[]] + + internal func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueRange { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } +} + +class BaseFloatStackGraphChartDataSource: NSObject, ORKValueStackGraphChartViewDataSource { + + var plotPoints: [[ORKValueStack]] = [[]] + + public func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueStack { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } +} + +class LineGraphChartDataSource: BaseFloatRangeGraphChartDataSource { + + override init() { + super.init() + plotPoints = + [ + [ + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange() + ], + [ + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 50), + ORKValueRange(value: 64) + ], + [ + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange() + ] + ] + } + + func maximumValueForGraphChartView(_ graphChartView: ORKGraphChartView) -> Double { + return 70 + } + + func minimumValueForGraphChartView(_ graphChartView: ORKGraphChartView) -> Double { + return 0 + } + + func numberOfDivisionsInXAxisForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 10 + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return (pointIndex % 2 == 0) ? nil : "\(pointIndex + 1)" + } + + func graphChartView(_ graphChartView: ORKGraphChartView, drawsVerticalReferenceLineAtPointIndex pointIndex: Int) -> Bool { + return (pointIndex % 2 == 1) ? false : true + } + + func scrubbingPlotIndexForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 2 + } +} + +class ColoredLineGraphChartDataSource: LineGraphChartDataSource { + func graphChartView(_ graphChartView: ORKGraphChartView, colorForPlotIndex plotIndex: Int) -> UIColor { + let color: UIColor + switch plotIndex { + case 0: + color = UIColor.cyan + case 1: + color = UIColor.magenta + case 2: + color = UIColor.yellow + default: + color = UIColor.red + } + return color + } + + func graphChartView(graphChartView: ORKGraphChartView, fillColorForPlotIndex plotIndex: Int) -> UIColor { + let color: UIColor + switch plotIndex { + case 0: + color = UIColor.blue.withAlphaComponent(0.6) + case 1: + color = UIColor.red.withAlphaComponent(0.6) + case 2: + color = UIColor.green.withAlphaComponent(0.6) + default: + color = UIColor.cyan.withAlphaComponent(0.6) + } + return color + } +} + +class DiscreteGraphChartDataSource: BaseFloatRangeGraphChartDataSource { + + override init() { + super.init() + plotPoints = + [ + [ + ORKValueRange(), + ORKValueRange(minimumValue: 0, maximumValue: 2), + ORKValueRange(minimumValue: 1, maximumValue: 3), + ORKValueRange(minimumValue: 2, maximumValue: 6), + ORKValueRange(minimumValue: 3, maximumValue: 9), + ORKValueRange(minimumValue: 4, maximumValue: 13) + ], + [ + ORKValueRange(value: 1), + ORKValueRange(minimumValue: 2, maximumValue: 4), + ORKValueRange(minimumValue: 3, maximumValue: 8), + ORKValueRange(minimumValue: 5, maximumValue: 11), + ORKValueRange(minimumValue: 7, maximumValue: 13), + ORKValueRange(minimumValue: 10, maximumValue: 13), + ORKValueRange(minimumValue: 12, maximumValue: 15) + ], + [ + ORKValueRange(), + ORKValueRange(minimumValue: 5, maximumValue: 6), + ORKValueRange(), + ORKValueRange(minimumValue: 2, maximumValue: 15), + ORKValueRange(minimumValue: 4, maximumValue: 11) + ] + ] + } + + func numberOfDivisionsInXAxisForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 8 + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String { + return "\(pointIndex + 1)" + } + + func scrubbingPlotIndexForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 2 + } +} + +class ColoredDiscreteGraphChartDataSource: DiscreteGraphChartDataSource { + func graphChartView(graphChartView: ORKGraphChartView, colorForPlotIndex plotIndex: Int) -> UIColor { + let color: UIColor + switch plotIndex { + case 0: + color = UIColor.cyan + case 1: + color = UIColor.magenta + case 2: + color = UIColor.yellow + default: + color = UIColor.red + } + return color + } +} + +class BarGraphChartDataSource: BaseFloatStackGraphChartDataSource { + + override init() { + super.init() + plotPoints = + [ + [ + ORKValueStack(), + ORKValueStack(stackedValues: [0, 2, 5]), + ORKValueStack(stackedValues: [1, 3, 2]), + ORKValueStack(stackedValues: [2, 6, 1]), + ORKValueStack(stackedValues: [3, 9, 4]), + ORKValueStack(stackedValues: [4, 13, 2]) + ], + [ + ORKValueStack(stackedValues: [1]), + ORKValueStack(stackedValues: [2, 4]), + ORKValueStack(stackedValues: [3, 8]), + ORKValueStack(stackedValues: [5, 11]), + ORKValueStack(stackedValues: [7, 13]), + ORKValueStack(stackedValues: [10, 13]), + ORKValueStack(stackedValues: [12, 15]) + ], + [ + ORKValueStack(), + ORKValueStack(stackedValues: [5, 6]), + ORKValueStack(stackedValues: [2, 15]), + ORKValueStack(stackedValues: [4, 11]), + ORKValueStack(), + ORKValueStack(stackedValues: [6, 16]) + ] + ] + } + + func numberOfDivisionsInXAxisForGraphChartView(graphChartView: ORKGraphChartView) -> Int { + return 8 + } + + func graphChartView(graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String { + return "\(pointIndex + 1)" + } + + func scrubbingPlotIndexForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 2 + } +} + +class ColoredBarGraphChartDataSource: BarGraphChartDataSource { + + func graphChartView(graphChartView: ORKGraphChartView, colorForPlotIndex plotIndex: Int) -> UIColor { + let color: UIColor + switch plotIndex { + case 0: + color = UIColor.cyan + case 1: + color = UIColor.magenta + case 2: + color = UIColor.yellow + default: + color = UIColor.red + } + return color + } + + override func scrubbingPlotIndexForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 1 + } +} + +class PerformanceLineGraphChartDataSource: BaseFloatRangeGraphChartDataSource { + + override init() { + super.init() + plotPoints = + [ + [ + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange() + ], + [ + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 50), + ORKValueRange(value: 64), + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 50), + ORKValueRange(value: 64), + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 50), + ORKValueRange(value: 64), + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 50), + ORKValueRange(value: 64) + ], + [ + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40), + ORKValueRange() + ] + ] + } + + func maximumValueForGraphChartView(_ graphChartView: ORKGraphChartView) -> Double { + return 70 + } + + func minimumValueForGraphChartView(_ graphChartView: ORKGraphChartView) -> Double { + return 0 + } + + func numberOfDivisionsInXAxisForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 10 + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return (pointIndex % 2 == 0) ? nil : "\(pointIndex + 1)" + } + + func graphChartView(_ graphChartView: ORKGraphChartView, drawsVerticalReferenceLineAtPointIndex pointIndex: Int) -> Bool { + return (pointIndex % 2 == 1) ? false : true + } + + func scrubbingPlotIndexForGraphChartView(_ graphChartView: ORKGraphChartView) -> Int { + return 2 + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartListViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartListViewController.swift new file mode 100755 index 0000000..18a43b3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartListViewController.swift @@ -0,0 +1,315 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. +Copyright (c) 2015, Ricardo Sánchez-Sáez. +Copyright (c) 2018, Brian Ganninger. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +func executeAfterDelay(_ delay: Double, closure: @escaping () -> Void) { + let delayTime = DispatchTime.now() + delay + let dispatchWorkItem = DispatchWorkItem(block: closure) + DispatchQueue.main.asyncAfter( + deadline: delayTime, execute: dispatchWorkItem) +} + +class ChartListViewController: UIViewController, UITableViewDataSource { + + @IBOutlet var tableView: UITableView! + + let colorlessPieChartDataSource = ColorlessPieChartDataSource() + let randomColorPieChartDataSource = RandomColorPieChartDataSource() + + let lineGraphChartDataSource = LineGraphChartDataSource() + let coloredLineGraphChartDataSource = ColoredLineGraphChartDataSource() + + let discreteGraphChartDataSource = DiscreteGraphChartDataSource() + let coloredDiscreteGraphChartDataSource = ColoredDiscreteGraphChartDataSource() + + let barGraphChartDataSource = BarGraphChartDataSource() + let coloredBarGraphChartDataSource = ColoredBarGraphChartDataSource() + + let pieChartIdentifier = "PieChartCell" + let lineGraphChartIdentifier = "LineGraphChartCell" + let discreteGraphChartIdentifier = "DiscreteGraphChartCell" + let barGraphChartIdentifier = "BarGraphChartCell" + + var pieChartTableViewCell: PieChartTableViewCell! + var lineGraphChartTableViewCell: LineGraphChartTableViewCell! + var discreteGraphChartTableViewCell: DiscreteGraphChartTableViewCell! + var barGraphChartTableViewCell: BarGraphChartTableViewCell! + var chartTableViewCells: [UITableViewCell]! + + @IBAction func dimiss(_ sender: AnyObject) { + self.dismiss(animated: true, completion: nil) + } + + override func viewDidLoad() { + super.viewDidLoad() + self.tableView.dataSource = self + + // ORKPieChartView + pieChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: pieChartIdentifier) as? PieChartTableViewCell + let pieChartView = pieChartTableViewCell.pieChartView + pieChartView?.dataSource = randomColorPieChartDataSource + // Optional custom configuration + pieChartView?.title = "TITLE" + pieChartView?.text = "TEXT" + pieChartView?.lineWidth = 1000 + pieChartView?.showsTitleAboveChart = true + pieChartView?.showsPercentageLabels = false + pieChartView?.drawsClockwise = false + pieChartView?.titleFont = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.bold) + pieChartView?.subtitleFont = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.thin) + pieChartView?.noDataFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.black) + pieChartView?.percentageLabelFont = UIFont.systemFont(ofSize: 12, weight: UIFont.Weight.light) + pieChartView?.legendFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.heavy) + executeAfterDelay(2.5) { + pieChartView?.showsTitleAboveChart = false + pieChartView?.lineWidth = 12 + pieChartView?.title = "UPDATED" + pieChartView?.text = "UPDATED TEXT" + pieChartView?.titleColor = UIColor.red + pieChartView?.textColor = UIColor.orange + pieChartView?.titleFont = nil + pieChartView?.subtitleFont = nil + pieChartView?.noDataFont = nil + pieChartView?.percentageLabelFont = nil + pieChartView?.legendFont = nil + } + executeAfterDelay(3.5) { + pieChartView?.drawsClockwise = true + pieChartView?.dataSource = self.colorlessPieChartDataSource + } + executeAfterDelay(4.5) { + pieChartView?.showsPercentageLabels = true + pieChartView?.tintColor = UIColor.purple + pieChartView?.percentageLabelFont = UIFont.systemFont(ofSize: 12, weight: UIFont.Weight.light) + pieChartView?.legendFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.heavy) + } + executeAfterDelay(5.5) { + pieChartView?.titleColor = nil + pieChartView?.textColor = nil + pieChartView?.percentageLabelFont = nil + pieChartView?.legendFont = nil + } + + // ORKBarGraphChartView + barGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: barGraphChartIdentifier) as? BarGraphChartTableViewCell + let barGraphChartView = barGraphChartTableViewCell.graphChartView as! ORKBarGraphChartView + barGraphChartView.dataSource = barGraphChartDataSource + executeAfterDelay(1.5) { + barGraphChartView.tintColor = UIColor.purple + barGraphChartView.showsHorizontalReferenceLines = true + barGraphChartView.showsVerticalReferenceLines = true + } + executeAfterDelay(2.5) { + barGraphChartView.axisColor = UIColor.red + barGraphChartView.verticalAxisTitleColor = UIColor.red + barGraphChartView.referenceLineColor = UIColor.orange + barGraphChartView.scrubberLineColor = UIColor.blue + barGraphChartView.scrubberThumbColor = UIColor.green + barGraphChartView.xAxisFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.light) + barGraphChartView.yAxisFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.light) + barGraphChartView.noDataFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.heavy) + barGraphChartView.scrubberFont = UIFont.systemFont(ofSize: 10, weight: UIFont.Weight.medium) + } + executeAfterDelay(3.5) { + barGraphChartView.axisColor = nil + barGraphChartView.verticalAxisTitleColor = nil + barGraphChartView.referenceLineColor = nil + barGraphChartView.scrubberLineColor = nil + barGraphChartView.scrubberThumbColor = nil + barGraphChartView.xAxisFont = nil + barGraphChartView.yAxisFont = nil + barGraphChartView.noDataFont = nil + barGraphChartView.scrubberFont = nil + } + executeAfterDelay(4.5) { + barGraphChartView.dataSource = self.coloredBarGraphChartDataSource + } + executeAfterDelay(5.5) { + let maximumValueImage = UIImage(named: "GraphMaximumValueTest")! + let minimumValueImage = UIImage(named: "GraphMinimumValueTest")! + barGraphChartView.maximumValueImage = maximumValueImage + barGraphChartView.minimumValueImage = minimumValueImage + } + + // ORKLineGraphChartView + lineGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: lineGraphChartIdentifier) as? LineGraphChartTableViewCell + let lineGraphChartView = lineGraphChartTableViewCell.graphChartView as! ORKLineGraphChartView + lineGraphChartView.dataSource = lineGraphChartDataSource + // Optional custom configuration + executeAfterDelay(1.5) { + lineGraphChartView.tintColor = UIColor.purple + lineGraphChartView.showsHorizontalReferenceLines = true + lineGraphChartView.showsVerticalReferenceLines = true + } + executeAfterDelay(2.5) { + lineGraphChartView.axisColor = UIColor.red + lineGraphChartView.verticalAxisTitleColor = UIColor.red + lineGraphChartView.referenceLineColor = UIColor.orange + lineGraphChartView.scrubberLineColor = UIColor.blue + lineGraphChartView.scrubberThumbColor = UIColor.green + lineGraphChartView.xAxisFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.light) + lineGraphChartView.yAxisFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.light) + lineGraphChartView.noDataFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.heavy) + lineGraphChartView.scrubberFont = UIFont.systemFont(ofSize: 10, weight: UIFont.Weight.medium) + } + executeAfterDelay(3.5) { + lineGraphChartView.axisColor = nil + lineGraphChartView.verticalAxisTitleColor = nil + lineGraphChartView.referenceLineColor = nil + lineGraphChartView.scrubberLineColor = nil + lineGraphChartView.scrubberThumbColor = nil + } + executeAfterDelay(4.5) { + lineGraphChartView.dataSource = self.coloredLineGraphChartDataSource + lineGraphChartView.xAxisFont = nil + lineGraphChartView.yAxisFont = nil + lineGraphChartView.noDataFont = nil + lineGraphChartView.scrubberFont = nil + } + executeAfterDelay(5.5) { + let maximumValueImage = UIImage(named: "GraphMaximumValueTest")! + let minimumValueImage = UIImage(named: "GraphMinimumValueTest")! + lineGraphChartView.maximumValueImage = maximumValueImage + lineGraphChartView.minimumValueImage = minimumValueImage + } + + // ORKDiscreteGraphChartView + discreteGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: discreteGraphChartIdentifier) as? DiscreteGraphChartTableViewCell + let discreteGraphChartView = discreteGraphChartTableViewCell.graphChartView as! ORKDiscreteGraphChartView + discreteGraphChartView.dataSource = discreteGraphChartDataSource + // Optional custom configuration + discreteGraphChartView.showsHorizontalReferenceLines = true + discreteGraphChartView.showsVerticalReferenceLines = true + discreteGraphChartView.drawsConnectedRanges = true + discreteGraphChartView.xAxisFont = UIFont.systemFont(ofSize: 9, weight: UIFont.Weight.thin) + discreteGraphChartView.yAxisFont = UIFont.systemFont(ofSize: 8, weight: UIFont.Weight.light) + discreteGraphChartView.noDataFont = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.heavy) + discreteGraphChartView.scrubberFont = UIFont.systemFont(ofSize: 10, weight: UIFont.Weight.medium) + executeAfterDelay(2.5) { + discreteGraphChartView.tintColor = UIColor.purple + } + executeAfterDelay(3.5) { + discreteGraphChartView.drawsConnectedRanges = false + } + executeAfterDelay(4.5) { + discreteGraphChartView.dataSource = self.coloredDiscreteGraphChartDataSource + discreteGraphChartView.xAxisFont = nil + discreteGraphChartView.yAxisFont = nil + discreteGraphChartView.noDataFont = nil + discreteGraphChartView.scrubberFont = nil + } + executeAfterDelay(5.5) { + discreteGraphChartView.drawsConnectedRanges = true + } + + chartTableViewCells = [pieChartTableViewCell, barGraphChartTableViewCell, lineGraphChartTableViewCell, discreteGraphChartTableViewCell] + + tableView.tableFooterView = UIView(frame: CGRect.zero) + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return chartTableViewCells.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = chartTableViewCells[(indexPath as NSIndexPath).row] + return cell + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.view.layoutIfNeeded() + pieChartTableViewCell.pieChartView.animate(withDuration: 0.5) + lineGraphChartTableViewCell.graphChartView.animate(withDuration: 0.5) + discreteGraphChartTableViewCell.graphChartView.animate(withDuration: 0.5) + discreteGraphChartTableViewCell.graphChartView.animate(withDuration: 2.5) + } +} + +class ChartPerformanceListViewController: UIViewController, UITableViewDataSource { + + @IBOutlet var tableView: UITableView! + + let lineGraphChartIdentifier = "LineGraphChartCell" + let discreteGraphChartIdentifier = "DiscreteGraphChartCell" + let graphChartDataSource = PerformanceLineGraphChartDataSource() + var lineGraphChartTableViewCell: LineGraphChartTableViewCell! + let discreteGraphChartDataSource = DiscreteGraphChartDataSource() + var discreteGraphChartTableViewCell: DiscreteGraphChartTableViewCell! + var chartTableViewCells: [UITableViewCell]! + + @IBAction func dimiss(_ sender: AnyObject) { + self.dismiss(animated: true, completion: nil) + } + + override func viewDidLoad() { + super.viewDidLoad() + self.tableView.dataSource = self + + // ORKLineGraphChartView + lineGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: lineGraphChartIdentifier) as? LineGraphChartTableViewCell + let lineGraphChartView = lineGraphChartTableViewCell.graphChartView as! ORKLineGraphChartView + lineGraphChartView.dataSource = graphChartDataSource + // Optional custom configuration + lineGraphChartView.showsHorizontalReferenceLines = true + lineGraphChartView.showsVerticalReferenceLines = true + + // ORKDiscreteGraphChartView + discreteGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: discreteGraphChartIdentifier) as? DiscreteGraphChartTableViewCell + let discreteGraphChartView = discreteGraphChartTableViewCell.graphChartView as! ORKDiscreteGraphChartView + discreteGraphChartView.dataSource = graphChartDataSource + // Optional custom configuration + discreteGraphChartView.showsHorizontalReferenceLines = true + discreteGraphChartView.showsVerticalReferenceLines = true + discreteGraphChartView.drawsConnectedRanges = true + + chartTableViewCells = [lineGraphChartTableViewCell, discreteGraphChartTableViewCell] + + tableView.tableFooterView = UIView(frame: CGRect.zero) + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return chartTableViewCells.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = chartTableViewCells[(indexPath as NSIndexPath).row] + return cell + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + lineGraphChartTableViewCell.graphChartView.animate(withDuration: 0.5) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartTableViewCells.swift b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartTableViewCells.swift new file mode 100755 index 0000000..4817beb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/ChartTableViewCells.swift @@ -0,0 +1,46 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class PieChartTableViewCell: UITableViewCell { + @IBOutlet weak var pieChartView: ORKPieChartView! +} + +class GraphChartTableViewCell: UITableViewCell { + @IBOutlet weak var graphChartView: ORKGraphChartView! +} + +class DiscreteGraphChartTableViewCell: GraphChartTableViewCell { } + +class LineGraphChartTableViewCell: GraphChartTableViewCell { } + +class BarGraphChartTableViewCell: GraphChartTableViewCell { } diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/Charts.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/Charts.storyboard new file mode 100755 index 0000000..5fb4d6b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Charts/Charts.storyboard @@ -0,0 +1,386 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.h new file mode 100755 index 0000000..be83945 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ContinueButtonExampleViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.m new file mode 100755 index 0000000..c7be07e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/ContinueButtonExampleViewController.m @@ -0,0 +1,56 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ContinueButtonExampleViewController.h" +#import "FooterView.h" + + +@interface ContinueButtonExampleViewController () + +@property (weak, nonatomic) IBOutlet FooterView *footerView; + +@end + + +@implementation ContinueButtonExampleViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. + + [self.footerView.continueButton addTarget:self action:@selector(continueButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; +} + +- (IBAction)continueButtonTapped:(id)sender { + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.h new file mode 100755 index 0000000..8f4df58 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.h @@ -0,0 +1,41 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import ResearchKit; + +/// Example implementation of an override of the class method -instantiateStepViewControllerWithResult: +/// In this example, only show the cancel button on Tuesdays + +@interface DragonPokerStep : ORKFormStep + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.m new file mode 100755 index 0000000..578f7df --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DragonPokerStep.m @@ -0,0 +1,89 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "DragonPokerStep.h" + + +@interface DragonPokerStep () + +@property (nonatomic) NSDate *playDate; + +@end + + +@interface DragonPokerStepViewController : ORKFormStepViewController + +@property (nonatomic) BOOL shouldShowCancelButton; + +@end + + +@implementation DragonPokerStep + +- (instancetype)initWithIdentifier:(NSString *)identifier { + self = [super initWithIdentifier:identifier]; + if (self) { + ORKFormItem *formItem = [[ORKFormItem alloc] initWithIdentifier:@"question1" text:@"Are you tall?" answerFormat:[ORKAnswerFormat booleanAnswerFormat]]; + self.formItems = @[formItem]; + } + return self; +} + +- (NSDate *)playDate { + if (_playDate == nil) { + _playDate = [NSDate date]; + } + return _playDate; + } + +- (ORKStepViewController *)instantiateStepViewControllerWithResult:(ORKResult *)result { + + DragonPokerStepViewController *viewController = [[DragonPokerStepViewController alloc] initWithStep:self result:result]; + NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitWeekday fromDate:self.playDate]; + viewController.shouldShowCancelButton = components.weekday == 2; + + return viewController; +} + +@end + +@implementation DragonPokerStepViewController + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + // Hide the cancel button if it should not be shown. + if (!self.shouldShowCancelButton) { + self.cancelButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[[UIView alloc] initWithFrame:CGRectZero]]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.h new file mode 100755 index 0000000..45ccdae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import ResearchKit; + + +/* + This custom task is used to verify correct behavior of `ORKTaskViewController` + when it is used on a task that is not an `ORKOrderedTask` subclass. + + This also tests turning off navigation-bar progress indication for a task. + */ +@interface DynamicTask : NSObject + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.m new file mode 100755 index 0000000..0b17698 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/DynamicTask.m @@ -0,0 +1,177 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "DynamicTask.h" + +@import ResearchKit.Private; + + +@interface DynamicTask () + +@property (nonatomic, strong) ORKInstructionStep *step1; +@property (nonatomic, strong) ORKQuestionStep *step2; +@property (nonatomic, strong) ORKQuestionStep *step3a; +@property (nonatomic, strong) ORKQuestionStep *step3b; +@property (nonatomic, strong) ORKActiveStep *step4; + +@end + + +@implementation DynamicTask + +- (instancetype)init { + self = [super init]; + if (self) { + + } + return self; +} + +- (NSString *)identifier { + return @"DynamicTask01"; +} + +/* + A custom implementation of `ORKTask` must implement `stepAfterStep:withResult:` + and `stepBeforeStep:withResult:` so that they are internally consistent. This + can be a little tricky. In most cases we recommend subclassing `ORKOrderedTask` + and overriding it in the specific situations where you need to customize + behavior. + */ +- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(id)result { + NSString *identifier = step.identifier; + if (step == nil) { + return self.step1; + } else if ([identifier isEqualToString:self.step1.identifier]) { + return self.step2; + } else if ([identifier isEqualToString:self.step2.identifier]) { + ORKStepResult *stepResult = [result stepResultForStepIdentifier:step.identifier]; + ORKQuestionResult *result = (ORKQuestionResult *)(stepResult.results.count > 0 ? stepResult.results.firstObject : nil); + if (result.answer != nil) { + if ([((NSArray *)result.answer).firstObject isEqualToString:@"route1"]) + { + return self.step3a; + } else { + return self.step3b; + } + } + } else if ([identifier isEqualToString:self.step3a.identifier] || [identifier isEqualToString:self.step3b.identifier]) { + ORKStepResult *stepResult = [result stepResultForStepIdentifier:step.identifier]; + ORKQuestionResult *result = (ORKQuestionResult *)[stepResult firstResult]; + if (result.answer != nil) { + if (((NSNumber *)result.answer).boolValue) { + return self.step4; + } + } + } + return nil; +} + +- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result { + NSString *identifier = step.identifier; + if (identifier == nil || [identifier isEqualToString:self.step1.identifier]) { + return nil; + } else if ([identifier isEqualToString:self.step2.identifier]) { + return self.step1; + } else if ([identifier isEqualToString:self.step3a.identifier] || [identifier isEqualToString:self.step3b.identifier]) { + return self.step2; + } else if ([identifier isEqualToString:self.step4.identifier] ) { + ORKQuestionResult *questionResult = (ORKQuestionResult *)[[result stepResultForStepIdentifier:self.step3a.identifier] firstResult]; + + if (questionResult != nil) { + return self.step3a; + } else { + return self.step3b; + } + } + + return nil; +} + +// Explicitly hide progress indication for all steps in this dynamic task. +- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResultProvider:(NSArray *)surveyResults { + return (ORKTaskProgress){.total = 0, .current = 0}; +} + +- (ORKInstructionStep *)step1 { + if (_step1 == nil) { + _step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + _step1.title = @"Dynamic Task"; + _step1.text = @"This is an example of a dynamic task providing a custom implementation of ORKTask."; + } + return _step1; +} + +- (ORKQuestionStep *)step2 { + if (_step2 == nil) { + _step2 = [[ORKQuestionStep alloc] initWithIdentifier:@"step2"]; + _step2.title = @"Dynamic Task"; + _step2.text = @"Please choose a route from the options below:"; + ORKTextChoice *route1 = [ORKTextChoice choiceWithText:@"route1" value:@"route1"]; + ORKTextChoice *route2 = [ORKTextChoice choiceWithText:@"route2" value:@"route2"]; + _step2.answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:@[route1, route2]]; + _step2.optional = NO; + } + return _step2; +} + +- (ORKQuestionStep *)step3a { + if (_step3a == nil) { + _step3a = [[ORKQuestionStep alloc] initWithIdentifier:@"step3a"]; + _step3a.title = @"Dynamic Task"; + _step3a.text = @"You chose route1. Was this correct?"; + _step3a.answerFormat = [ORKBooleanAnswerFormat new]; + _step3a.optional = NO; + } + return _step3a; +} + +- (ORKQuestionStep *)step3b { + if (_step3b == nil) { + _step3b = [[ORKQuestionStep alloc] initWithIdentifier:@"step3b"]; + _step3b.title = @"Dynamic Task"; + _step3b.text = @"You chose route2. Was this correct?"; + _step3b.answerFormat = [ORKBooleanAnswerFormat new]; + _step3b.optional = NO; + } + return _step3b; +} + +- (ORKActiveStep *)step4 { + if (_step4 == nil) { + _step4 = [[ORKActiveStep alloc] initWithIdentifier:@"step4"]; + _step4.title = @"Thank you."; + _step4.spokenInstruction = @"Thank you."; + } + return _step4; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.h new file mode 100755 index 0000000..987ffbd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.h @@ -0,0 +1,39 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +@interface FooterView : UIView + +@property (nonatomic, readonly) UIButton *continueButton; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.m new file mode 100755 index 0000000..cdf717e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Customization/FooterView.m @@ -0,0 +1,89 @@ +/* + Copyright (c) 2016, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "FooterView.h" + +@import ResearchKit; + + +@implementation FooterView + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + [self commonInit]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if ((self = [super initWithCoder:aDecoder])) { + [self commonInit]; + } + return self; +} + +- (void)commonInit { + + // Add continue button and constraints + _continueButton = [[ORKContinueButton alloc] initWithTitle:NSLocalizedString(@"Done", @"") isDoneButton:NO]; + _continueButton.exclusiveTouch = YES; + _continueButton.translatesAutoresizingMaskIntoConstraints = NO; + + [self addSubview:_continueButton]; + + NSMutableArray *constraints = [NSMutableArray new]; + + [constraints addObject:[NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeCenterX + multiplier:1.0 + constant:0.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:-20.0]]; + [constraints addObject:[NSLayoutConstraint constraintWithItem:_continueButton + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationLessThanOrEqual + toItem:self + attribute:NSLayoutAttributeWidth + multiplier:1.0 + constant:0.0]]; + + [NSLayoutConstraint activateConstraints:constraints]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.h new file mode 100755 index 0000000..49823b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; + + +/* + The main view controller provides a list of all the tasks that are available. + */ +@interface MainViewController : UIViewController + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.m new file mode 100755 index 0000000..6d19c8e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/MainViewController.m @@ -0,0 +1,930 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015 - 2016, Ricardo Sanchez-Saez. + Copyright (c) 2016, Sage Bionetworks. + Copyright (c) 2017, Macro Yau. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "MainViewController.h" + +#import "AppDelegate.h" +#import "DynamicTask.h" +#import "TaskFactory.h" + +#import "ORKTest-Swift.h" + +@import ResearchKit; + +@import AVFoundation; + + +NSArray *> *> *TestButtonTable() +{ + return @[ + @{ @"Active Tasks": + @[ + @"Active Step", + @"Audio", + @"Fitness", + @"GAIT", + @"Hand Tremor", + @"Hand (Right) Tremor", + @"Hole Peg Test", + @"Memory Game", + @"PSAT", + @"Reaction Time", + @"Stroop", + @"Timed Walk", + @"Tone Audiometry", + @"Tower Of Hanoi", + @"Trail Making", + @"Two Finger Tapping", + @"Walk And Turn", + ]}, + @{ @"Forms": + @[ + @"Confirmation Form Item", + @"Mini Form", + @"Optional Form", + ]}, + @{ @"Onboarding": + @[ + @"Consent", + @"Consent Review", + @"Eligibility Form", + @"Eligibility Survey", + @"Login", + @"Registration", + @"Verification", + ]}, + @{ @"Passcode Management": + @[ + @"Authenticate Passcode", + @"Create Passcode", + @"Edit Passcode", + @"Remove Passcode", + ]}, + @{ @"Question Steps": + @[ + @"Date Pickers", + @"Image Capture", + @"Image Choice", + @"Location", + @"Scale", + @"Scale (Color Gradient)", + @"Selection Survey", + @"Video Capture", + ]}, + @{ @"Task Customization": + @[ + @"Custom View Controller", + @"Dynamic", + @"Interruptible", + @"Navigable Ordered", + @"Navigable Ordered Loop", + @"Step Will Appear", + @"Step Will Disappear", + ]}, + @{ @"Task Review": + @[ + @"Embedded Review", + @"Standalone Review", + ]}, + @{ @"Utility Steps": + @[ + @"Auxiliary Image Step", + @"Completion Step", + @"Footnote Step", + @"Icon Image Step", + @"Page Step", + @"Predicate Tests", + @"Signature Step", + @"Table Step", + @"Video Instruction Step", + @"Wait Step", + @"Web View Step" + ]}, + @{ @"Miscellaneous": + @[ + @"Continue Button", + @"Test Charts", + @"Test Charts Performance", + @"Toggle Tint Color", + ]}, + ]; +} + + +@interface SectionHeader: UICollectionReusableView + +- (void)configureHeaderWithTitle:(NSString *)title; + +@end + + +@implementation SectionHeader { + UILabel *_title; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + if (self = [super initWithCoder:aDecoder]) { + [self sharedInit]; + } + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + [self sharedInit]; + } + return self; +} + +static UIColor *HeaderColor() { + return [UIColor colorWithWhite:0.97 alpha:1.0]; +} + +static const CGFloat HeaderSideLayoutMargin = 16.0; + +- (void)sharedInit { + self.layoutMargins = UIEdgeInsetsMake(0, HeaderSideLayoutMargin, 0, HeaderSideLayoutMargin); + self.backgroundColor = HeaderColor(); + _title = [UILabel new]; + _title.font = [UIFont systemFontOfSize:17.0 weight:UIFontWeightSemibold]; // Table view header font + [self addSubview:_title]; + + _title.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *views = @{@"title": _title}; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[title]-|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[title]|" + options:0 + metrics:nil + views:views]]; +} + +- (void)configureHeaderWithTitle:(NSString *)title { + _title.text = title; +} + +@end + + +@interface ButtonCell: UICollectionViewCell + +- (void)configureButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector; + +@end + + +@implementation ButtonCell { + UIButton *_button; +} + +- (void)setUpButton { + [_button removeFromSuperview]; + _button = [UIButton buttonWithType:UIButtonTypeSystem]; + _button.titleLabel.adjustsFontSizeToFitWidth = YES; + _button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; + _button.contentEdgeInsets = UIEdgeInsetsMake(0.0, HeaderSideLayoutMargin, 0.0, 0.0); + [self.contentView addSubview:_button]; + + _button.translatesAutoresizingMaskIntoConstraints = NO; + + [NSLayoutConstraint activateConstraints:@[ + [NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.contentView + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.contentView.safeAreaLayoutGuide + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_button + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.contentView.safeAreaLayoutGuide + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0] + ]]; +} + +- (void)configureButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector { + [self setUpButton]; + [_button setTitle:title forState:UIControlStateNormal]; + [_button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside]; +} + +@end + + +#define ORKTDefineStringKey(x) static NSString *const x = @#x + +ORKTDefineStringKey(CollectionViewHeaderReuseIdentifier); +ORKTDefineStringKey(CollectionViewCellReuseIdentifier); + +@interface MainViewController () + +@end + + +@implementation MainViewController { + ORKTaskViewController *_taskViewController; + id _lastRouteResult; + + NSMutableDictionary *_savedViewControllers; // Maps task identifiers to task view controller restoration data + + UICollectionView *_collectionView; + NSArray *> *> *_buttonSections; + NSMutableArray *_constraints; + UIView *_statusBarBackground; + ORKTaskResult * _miniFormTaskResult; +} + + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + self.restorationIdentifier = @"main"; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _savedViewControllers = [NSMutableDictionary new]; + + UICollectionViewFlowLayout *flowLayout = [UICollectionViewFlowLayout new]; + _collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout]; + _collectionView.backgroundColor = [UIColor whiteColor]; + [self.view addSubview:_collectionView]; + + _collectionView.dataSource = self; + _collectionView.delegate = self; + [_collectionView registerClass:[SectionHeader class] + forSupplementaryViewOfKind:UICollectionElementKindSectionHeader + withReuseIdentifier:CollectionViewHeaderReuseIdentifier]; + [_collectionView registerClass:[ButtonCell class] + forCellWithReuseIdentifier:CollectionViewCellReuseIdentifier]; + + _statusBarBackground = [UIView new]; + _statusBarBackground.backgroundColor = HeaderColor(); + [self.view addSubview:_statusBarBackground]; + + [self setupConstraints]; + + _buttonSections = TestButtonTable(); +} + +- (void)setupConstraints { + if (_constraints) { + [NSLayoutConstraint deactivateConstraints:_constraints]; + _constraints = nil; + } + + _collectionView.translatesAutoresizingMaskIntoConstraints = NO; + _statusBarBackground.translatesAutoresizingMaskIntoConstraints = NO; + NSDictionary *views = @{@"collectionView": _collectionView, + @"statusBarBackground": _statusBarBackground}; + + _constraints = [[NSMutableArray alloc] init]; + [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[statusBarBackground]|" + options:NSLayoutFormatDirectionLeadingToTrailing + metrics:nil + views:views]]; + [_constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[statusBarBackground]" + options:0 + metrics:nil + views:views]]; + [_constraints addObject:[NSLayoutConstraint constraintWithItem:_statusBarBackground + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0]]; + [_constraints addObjectsFromArray:@[ + [NSLayoutConstraint constraintWithItem:_collectionView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_collectionView + attribute:NSLayoutAttributeLeft + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeLeft + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_collectionView + attribute:NSLayoutAttributeRight + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeRight + multiplier:1.0 + constant:0.0], + [NSLayoutConstraint constraintWithItem:_collectionView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:self.view.safeAreaLayoutGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0 + constant:0.0] + ]]; + [NSLayoutConstraint activateConstraints:_constraints]; +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + [_collectionView reloadData]; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { + return CGSizeMake(self.view.bounds.size.width, 22.0); // Table view header height +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + CGFloat viewWidth = self.view.bounds.size.width; + NSUInteger numberOfColums = 2; + if (viewWidth >= 667.0) { + numberOfColums = 3; + } + CGFloat width = viewWidth / numberOfColums; + return CGSizeMake(width, 44.0); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 0.0; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 0.0; +} + +- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { + return _buttonSections.count; +} + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return _buttonSections[section].allValues[0].count; +} + +- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { + SectionHeader *sectionHeader = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:CollectionViewHeaderReuseIdentifier forIndexPath:indexPath]; + NSString *title = _buttonSections[indexPath.section].allKeys[0]; + [sectionHeader configureHeaderWithTitle:title]; + return sectionHeader; +} + +NSString *RemoveParenthesisAndCapitalizeString(NSString *string) { + // "THIS (FOO) baR title" is converted to the "This Foo Bar Title" + NSMutableString *mutableString = [string mutableCopy]; + [mutableString replaceOccurrencesOfString:@"(" withString:@"" options:0 range:NSMakeRange(0, mutableString.length)]; + [mutableString replaceOccurrencesOfString:@")" withString:@"" options:0 range:NSMakeRange(0, mutableString.length)]; + return mutableString.capitalizedString; +} + +- (SEL)selectorFromButtonTitle:(NSString *)buttonTitle { + // "THIS (FOO) baR title" is converted to the "thisFooBarTitleButtonTapped:" selector + buttonTitle = RemoveParenthesisAndCapitalizeString(buttonTitle); + NSMutableArray *titleTokens = [[buttonTitle componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] mutableCopy]; + titleTokens[0] = ((NSString *)titleTokens[0]).lowercaseString; + NSString *selectorString = [NSString stringWithFormat:@"%@ButtonTapped:", [titleTokens componentsJoinedByString:@""]]; + return NSSelectorFromString(selectorString); +} + +- (NSString *)taskIdentifierFromButtonTitle:(NSString *)buttonTitle { + // "THIS (FOO) baR title" is converted to the "ThisFooBarTitleTaskIdentifier" selector + buttonTitle = RemoveParenthesisAndCapitalizeString(buttonTitle); + NSMutableArray *titleTokens = [[buttonTitle componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] mutableCopy]; + NSString *taskIdentifier = [NSString stringWithFormat:@"%@TaskIdentifier", [titleTokens componentsJoinedByString:@""]]; + return taskIdentifier; +} + +- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + ButtonCell *buttonCell = [collectionView dequeueReusableCellWithReuseIdentifier:CollectionViewCellReuseIdentifier forIndexPath:indexPath]; + NSString *buttonTitle = _buttonSections[indexPath.section].allValues[0][indexPath.row]; + [buttonCell configureButtonWithTitle:buttonTitle target:self selector:@selector(buttonTapped:)]; + return buttonCell; +} + +- (void)buttonTapped:(UIButton *)button { + NSString *buttonTitle = button.titleLabel.text; + SEL buttonSelector = [self selectorFromButtonTitle:buttonTitle]; + if ([self respondsToSelector:buttonSelector]) { + // Equivalent to [self peformSelector:buttonSelector], but ARC safe + IMP imp = [self methodForSelector:buttonSelector]; + void (*func)(id, SEL, UIButton *button) = (void *)imp; + func(self, buttonSelector, button); + } else { + [self beginTaskWithIdentifier:[self taskIdentifierFromButtonTitle:buttonTitle]]; + } +} + +/* + Creates a task and presents it with a task view controller. + */ +- (void)beginTaskWithIdentifier:(NSString *)identifier { + /* + This is our implementation of restoration after saving during a task. + If the user saved their work on a previous run of a task with the same + identifier, we attempt to restore the view controller here. + + Since unarchiving can throw an exception, in a real application we would + need to attempt to catch that exception here. + */ + + id task = [[TaskFactory sharedInstance] makeTaskWithIdentifier:identifier]; + NSParameterAssert(task != nil); + NSError *error; + + if (_savedViewControllers[identifier]) { + NSData *data = _savedViewControllers[identifier]; + _taskViewController = [[ORKTaskViewController alloc] initWithTask:task restorationData:data delegate:self error: &error]; + } else { + // No saved data, just create the task and the corresponding task view controller. + _taskViewController = [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:[NSUUID UUID]]; + } + + // If we have stored data then data will contain the stored data. + // If we don't, data will be nil (and the task will be opened up as a 'new' task. + NSData *data = _savedViewControllers[identifier]; + _taskViewController = [[ORKTaskViewController alloc] initWithTask:task restorationData:data delegate:self error: &error]; + + [self beginTask]; +} + +/* + Actually presents the task view controller. + */ +- (void)beginTask { + NSObject *task = _taskViewController.task; + _taskViewController.delegate = self; + + if (_taskViewController.outputDirectory == nil) { + // Sets an output directory in Documents, using the `taskRunUUID` in the path. + NSURL *documents = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + NSURL *outputDir = [documents URLByAppendingPathComponent:_taskViewController.taskRunUUID.UUIDString]; + [[NSFileManager defaultManager] createDirectoryAtURL:outputDir withIntermediateDirectories:YES attributes:nil error:nil]; + _taskViewController.outputDirectory = outputDir; + } + + /* + For the dynamic task, we remember the last result and use it as a source + of default values for any optional questions. + */ + if ([task isKindOfClass:[DynamicTask class]]) { + _taskViewController.defaultResultSource = _lastRouteResult; + } + + if ([_taskViewController.task.identifier isEqualToString: @"MiniFormTaskIdentifier"] && _miniFormTaskResult) { + _taskViewController.defaultResultSource = _miniFormTaskResult; + _taskViewController.reviewMode = ORKTaskViewControllerReviewModeStandalone; + } + + /* + We set a restoration identifier so that UI state restoration is enabled + for the task view controller. We don't need to do anything else to prepare + for state restoration of a ResearchKit framework task VC. + */ + _taskViewController.restorationIdentifier = task.identifier; + + [self presentViewController:_taskViewController animated:YES completion:nil]; +} + +#pragma mark - Custom Button Actions + +// Passcode management +- (void)authenticatePasscodeButtonTapped:(id)sender { + if ([ORKPasscodeViewController isPasscodeStoredInKeychain]) { + ORKPasscodeViewController *viewController = [ORKPasscodeViewController + passcodeAuthenticationViewControllerWithText:@"Authenticate your passcode in order to proceed." + delegate:self]; + [self presentViewController:viewController animated:YES completion:nil]; + } else { + [self showAlertWithTitle:@"Error" message:@"A passcode must be created before you can authenticate it."]; + } +} + +- (void)editPasscodeButtonTapped:(id)sender { + if ([ORKPasscodeViewController isPasscodeStoredInKeychain]) { + ORKPasscodeViewController *viewController = [ORKPasscodeViewController passcodeEditingViewControllerWithText:nil + delegate:self + passcodeType:ORKPasscodeType6Digit]; + [self presentViewController:viewController animated:YES completion:nil]; + } else { + [self showAlertWithTitle:@"Error" message:@"A passcode must be created before you can edit it."]; + } +} + +- (void)removePasscodeButtonTapped:(id)sender { + if ([ORKPasscodeViewController isPasscodeStoredInKeychain]) { + if ([ORKPasscodeViewController removePasscodeFromKeychain]) { + [self showAlertWithTitle:@"Success" message:@"Passcode removed."]; + } else { + [self showAlertWithTitle:@"Error" message:@"Passcode could not be removed."]; + } + } else { + [self showAlertWithTitle:@"Error" message:@"There is no passcode stored in the keychain."]; + } +} + +// Task Review +- (IBAction)standaloneReviewButtonTapped:(UIButton *)button { + if ([TaskFactory sharedInstance].embeddedReviewTaskResult != nil) { + NSString *buttonTitle = button.titleLabel.text; + [self beginTaskWithIdentifier:[self taskIdentifierFromButtonTitle:buttonTitle]]; + } else { + [self showAlertWithTitle:@"Alert" message:@"Please run embedded review task first"]; + } +} + +// Miscellaneous +- (IBAction)continueButtonButtonTapped:(UIButton *)button { + UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"ContinueButtonExample" bundle:nil]; + UIViewController *viewcController = [storyboard instantiateInitialViewController]; + [self presentViewController:viewcController animated:YES completion:nil]; +} + +- (void)toggleTintColorButtonTapped:(UIButton *)button { + static UIColor *defaultTintColor = nil; + if (!defaultTintColor) { + defaultTintColor = self.view.tintColor; + } + if ([[UIView appearance].tintColor isEqual:[UIColor redColor]]) { + [UIView appearance].tintColor = defaultTintColor; + } else { + [UIView appearance].tintColor = [UIColor redColor]; + } + // Update appearance + UIView *superview = self.view.superview; + [self.view removeFromSuperview]; + [superview addSubview:self.view]; +} + +#pragma mark - Passcode delegate + +- (void)passcodeViewControllerDidFailAuthentication:(UIViewController *)viewController { + NSLog(@"Passcode authentication failed."); + [self showAlertWithTitle:@"Error" message:@"Passcode authentication failed"]; +} + +- (void)passcodeViewControllerDidFinishWithSuccess:(UIViewController *)viewController { + NSLog(@"New passcode saved."); + [viewController dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)passcodeViewControllerDidCancel:(UIViewController *)viewController { + NSLog(@"User tapped the cancel button."); + [viewController dismissViewControllerAnimated:YES completion:nil]; +} + +- (void)passcodeViewControllerForgotPasscodeTapped:(UIViewController *)viewController { + NSLog(@"Forgot Passcode tapped."); + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Forgot Passcode" + message:@"Forgot Passcode tapped." + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [viewController presentViewController:alert animated:YES completion:nil]; +} + +- (void)testChartsButtonTapped:(id)sender { + UIStoryboard *chartStoryboard = [UIStoryboard storyboardWithName:@"Charts" bundle:nil]; + UIViewController *chartListViewController = [chartStoryboard instantiateViewControllerWithIdentifier:@"ChartListViewController"]; + [self presentViewController:chartListViewController animated:YES completion:nil]; +} + +- (void)testChartsPerformanceButtonTapped:(id)sender { + UIStoryboard *chartStoryboard = [UIStoryboard storyboardWithName:@"Charts" bundle:nil]; + UIViewController *chartListViewController = [chartStoryboard instantiateViewControllerWithIdentifier:@"ChartPerformanceListViewController"]; + [self presentViewController:chartListViewController animated:YES completion:nil]; +} + +#pragma mark - Helpers + +/* + Shows an alert. + + Used to display an alert with the provided title and message. + + @param title The title text for the alert. + @param message The message text for the alert. + */ +- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +#pragma mark - Managing the task view controller + +/* + Dismisses the task view controller. + */ +- (void)dismissTaskViewController:(ORKTaskViewController *)taskViewController removeOutputDirectory:(BOOL)removeOutputDirectory { + [TaskFactory sharedInstance].currentConsentDocument = nil; + + NSURL *outputDirectoryURL = taskViewController.outputDirectory; + [self dismissViewControllerAnimated:YES completion:^{ + if (outputDirectoryURL && removeOutputDirectory) + { + /* + We attempt to clean up the output directory. + + This is only useful for a test app, where we don't care about the + data after the test is complete. In a real application, only + delete your data when you've processed it or sent it to a server. + */ + NSError *error = nil; + if (![[NSFileManager defaultManager] removeItemAtURL:outputDirectoryURL error:&error]) { + NSLog(@"Error removing %@: %@", outputDirectoryURL, error); + } + } + }]; +} + +#pragma mark - ORKTaskViewControllerDelegate + +/* + Any step can have "Learn More" content. + + For testing, we return YES only for instruction steps, except on the active + tasks. + */ +- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController hasLearnMoreForStep:(ORKStep *)step { + NSObject *task = taskViewController.task; + + return ([step isKindOfClass:[ORKInstructionStep class]] + && !task.hidesLearnMoreButtonOnInstructionStep); +} + +/* + When the user taps on "Learn More" on a step, respond on this delegate callback. + In this test app, we just print to the console. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreForStep:(ORKStepViewController *)stepViewController { + NSLog(@"Learn more tapped for step %@", stepViewController.step.identifier); +} + +- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController shouldPresentStep:(ORKStep *)step { + BOOL shouldPresentStep = YES; + if (step.shouldPresentStepBlock) { + shouldPresentStep = step.shouldPresentStepBlock(taskViewController, step); + } + return shouldPresentStep; +} + +/* + In `stepViewControllerWillAppear:`, it is possible to significantly customize + the behavior of the step view controller. In this test app, we do a few funny + things to push the limits of this customization. + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController +stepViewControllerWillAppear:(ORKStepViewController *)stepViewController { + ORKStep *step = stepViewController.step; + if (step.stepViewControllerWillAppearBlock) { + step.stepViewControllerWillAppearBlock(taskViewController, stepViewController); + } +} + +- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillDisappear:(ORKStepViewController *)stepViewController navigationDirection:(ORKStepViewControllerNavigationDirection)direction { + ORKStep *step = stepViewController.step; + if (step.stepViewControllerWillDisappearBlock) { + step.stepViewControllerWillDisappearBlock(taskViewController, stepViewController, direction); + } +} + +/* + We support save and restore on all of the tasks in this test app. + + In a real app, not all tasks necessarily ought to support saving -- for example, + active tasks that can't usefully be restarted after a significant time gap + should not support save at all. + */ +- (BOOL)taskViewControllerSupportsSaveAndRestore:(ORKTaskViewController *)taskViewController { + return YES; +} + +/* + In almost all cases, we want to dismiss the task view controller. + + In this test app, we don't dismiss on a fail (we just log it). + */ +- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error { + switch (reason) { + case ORKTaskViewControllerFinishReasonCompleted: + { + NSObject *task = taskViewController.task; + if (task.isEmbeddedReviewTask) { + [TaskFactory sharedInstance].embeddedReviewTaskResult = taskViewController.result; + } + if ([task.identifier isEqualToString: @"MiniFormTaskIdentifier"]) { + _miniFormTaskResult = taskViewController.result; + } + [self taskViewControllerDidComplete:taskViewController]; + } + break; + case ORKTaskViewControllerFinishReasonFailed: + { + NSLog(@"Error on step %@: %@", taskViewController.currentStepViewController.step, error); + } + break; + case ORKTaskViewControllerFinishReasonDiscarded: + { + NSObject *task = taskViewController.task; + if (task.isEmbeddedReviewTask) { + [TaskFactory sharedInstance].embeddedReviewTaskResult = nil; + } + [self dismissTaskViewController:taskViewController removeOutputDirectory:YES]; + } + break; + case ORKTaskViewControllerFinishReasonSaved: + { + NSObject *task = taskViewController.task; + if (task.isEmbeddedReviewTask) { + [TaskFactory sharedInstance].embeddedReviewTaskResult = taskViewController.result; + } + /* + Save the restoration data, dismiss the task VC, and do an early return + so we don't clear the restoration data. + */ + _savedViewControllers[task.identifier] = taskViewController.restorationData; + [self dismissTaskViewController:taskViewController removeOutputDirectory:NO]; + return; + } + break; + + default: + break; + } + + [_savedViewControllers removeObjectForKey:taskViewController.task.identifier]; + _taskViewController = nil; +} + +/* + When a task completes, we pretty-print the result to the console. + + This is ok for testing, but if what you want to do is see the results of a task, + the `ORKCatalog` Swift sample app might be a better choice, since it lets + you navigate through the result structure. + */ +- (void)taskViewControllerDidComplete:(ORKTaskViewController *)taskViewController { + + NSLog(@"[ORKTest] task results: %@", taskViewController.result); + + // Validate the results + NSArray *results = taskViewController.result.results; + if (results) { + NSSet *uniqueResults = [NSSet setWithArray:results]; + BOOL allResultsUnique = (results.count == uniqueResults.count); + NSAssert(allResultsUnique, @"The returned results have duplicates of the same object."); + } + + if ([TaskFactory sharedInstance].currentConsentDocument) { + /* + This demonstrates how to take a signature result, apply it to a document, + and then generate a PDF From the document that includes the signature. + */ + + // Search for the review step. + NSArray *steps = [(ORKOrderedTask *)taskViewController.task steps]; + NSPredicate *predicate = [NSPredicate predicateWithFormat: @"self isKindOfClass: %@", [ORKConsentReviewStep class]]; + ORKStep *reviewStep = [[steps filteredArrayUsingPredicate:predicate] firstObject]; + ORKConsentSignatureResult *signatureResult = (ORKConsentSignatureResult *)[[[taskViewController result] stepResultForStepIdentifier:reviewStep.identifier] firstResult]; + + [signatureResult applyToDocument:[TaskFactory sharedInstance].currentConsentDocument]; + + [[TaskFactory sharedInstance].currentConsentDocument makePDFWithCompletionHandler:^(NSData *pdfData, NSError *error) { + NSLog(@"Created PDF of size %lu (error = %@)", (unsigned long)pdfData.length, error); + + if (!error) { + NSURL *documents = [NSURL fileURLWithPath:NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject]; + NSURL *outputUrl = [documents URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", taskViewController.taskRunUUID.UUIDString]]; + + [pdfData writeToURL:outputUrl atomically:YES]; + NSLog(@"Wrote PDF to %@", [outputUrl path]); + } + }]; + + [TaskFactory sharedInstance].currentConsentDocument = nil; + } + + NSURL *dir = taskViewController.outputDirectory; + [self dismissViewControllerAnimated:YES completion:^{ + if (dir) + { + NSError *error = nil; + if (![[NSFileManager defaultManager] removeItemAtURL:dir error:&error]) { + NSLog(@"Error removing %@: %@", dir, error); + } + } + }]; +} + +/** + When a task has completed it calls this method to post the result of the task to the delegate. +*/ +- (void)taskViewController:(ORKTaskViewController *)taskViewController didChangeResult:(ORKTaskResult *)result { + /* + Upon creation of a Passcode by a user, the results of their creation + are returned by getting it from ORKPasscodeResult in this delegate call. + This is triggered upon completion/failure/or cancel + */ + ORKStepResult *stepResult = (ORKStepResult *)[[result results] firstObject]; + if ([[[stepResult results] firstObject] isKindOfClass:[ORKPasscodeResult class]]) { + ORKPasscodeResult *passcodeResult = (ORKPasscodeResult *)[[stepResult results] firstObject]; + NSLog(@"passcode saved: %d , Touch ID Enabled: %d", passcodeResult.passcodeSaved, passcodeResult.touchIdEnabled); + + } +} + +#pragma mark - UI state restoration + +/* + UI state restoration code for the MainViewController. + + The MainViewController needs to be able to re-create the exact task that + was being done, in order for the task view controller to restore correctly. + + In a real app implementation, this might mean that you would also need to save + and restore the actual task; here, since we know the tasks don't change during + testing, we just re-create the task. + */ +- (void)encodeRestorableStateWithCoder:(NSCoder *)coder { + [super encodeRestorableStateWithCoder:coder]; + + [coder encodeObject:_taskViewController forKey:@"taskVC"]; + [coder encodeObject:_lastRouteResult forKey:@"lastRouteResult"]; + [coder encodeObject:[TaskFactory sharedInstance].embeddedReviewTaskResult forKey:@"embeddedReviewTaskResult"]; +} + +- (void)decodeRestorableStateWithCoder:(NSCoder *)coder { + [super decodeRestorableStateWithCoder:coder]; + + _taskViewController = [coder decodeObjectOfClass:[UIViewController class] forKey:@"taskVC"]; + _lastRouteResult = [coder decodeObjectForKey:@"lastRouteResult"]; + + // Need to give the task VC back a copy of its task, so it can restore itself. + + // Could save and restore the task's identifier separately, but the VC's + // restoration identifier defaults to the task's identifier. + id taskForTaskViewController = [[TaskFactory sharedInstance] makeTaskWithIdentifier:_taskViewController.restorationIdentifier]; + + _taskViewController.task = taskForTaskViewController; + if ([_taskViewController.restorationIdentifier isEqualToString:@"DynamicTask01"]) + { + _taskViewController.defaultResultSource = _lastRouteResult; + } + _taskViewController.delegate = self; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..c69af42 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,106 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon_small_40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon_small_40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_60@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon_small_40.png", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon_83.5@2x.png", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@2x.png new file mode 100755 index 0000000..0b93283 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@3x.png new file mode 100755 index 0000000..f01e1cc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_60@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76.png new file mode 100755 index 0000000..954ebd8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76@2x.png new file mode 100755 index 0000000..669c9e8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_76@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_83.5@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_83.5@2x.png new file mode 100755 index 0000000..b541745 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_83.5@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40.png new file mode 100755 index 0000000..aec9ca7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@2x.png new file mode 100755 index 0000000..abc6b72 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@3x.png new file mode 100755 index 0000000..0b93283 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/AppIcon.appiconset/icon_small_40@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/Contents.json new file mode 100755 index 0000000..c22b539 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "GraphMaximumValueTest.pdf" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/GraphMaximumValueTest.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/GraphMaximumValueTest.pdf new file mode 100755 index 0000000..c2ae731 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMaximumValueTest.imageset/GraphMaximumValueTest.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/Contents.json new file mode 100755 index 0000000..d4e2907 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "GraphMinimumValueTest.pdf" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/GraphMinimumValueTest.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/GraphMinimumValueTest.pdf new file mode 100755 index 0000000..8b61bf3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/GraphMinimumValueTest.imageset/GraphMinimumValueTest.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Contents.json new file mode 100755 index 0000000..8ce48c3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "Poppies.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Poppies.jpg b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Poppies.jpg new file mode 100755 index 0000000..e9569b8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/Poppies.imageset/Poppies.jpg differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/Contents.json new file mode 100755 index 0000000..81e5148 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "hands_solid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "hands_solid@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "hands_solid@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x.png new file mode 100755 index 0000000..6bc1aac Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x~ipad.png new file mode 100755 index 0000000..262d9ca Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@3x.png new file mode 100755 index 0000000..262d9ca Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/hands_solid.imageset/hands_solid@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/Contents.json new file mode 100755 index 0000000..c45f431 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_outline@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_outline@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "left_hand_outline@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x.png new file mode 100755 index 0000000..75eb05d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x~ipad.png new file mode 100755 index 0000000..582c913 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@3x.png new file mode 100755 index 0000000..fcae3be Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline.imageset/left_hand_outline@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/Contents.json new file mode 100755 index 0000000..8d57a33 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_outline_big@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_outline_big@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "left_hand_outline_big@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x.png new file mode 100755 index 0000000..218d1e4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x~ipad.png new file mode 100755 index 0000000..537789a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@3x.png new file mode 100755 index 0000000..537789a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_outline_big.imageset/left_hand_outline_big@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/Contents.json new file mode 100755 index 0000000..72a5693 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_solid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "left_hand_solid@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "left_hand_solid@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x.png new file mode 100755 index 0000000..c66f8e9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x~ipad.png new file mode 100755 index 0000000..26810ee Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@3x.png new file mode 100755 index 0000000..26810ee Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/left_hand_solid.imageset/left_hand_solid@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/Contents.json new file mode 100755 index 0000000..811a34f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "right_hand_outline@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x.png new file mode 100755 index 0000000..b12a7cd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x~ipad.png new file mode 100755 index 0000000..1f049ea Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@3x.png new file mode 100755 index 0000000..a7c3db1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline.imageset/right_hand_outline@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/Contents.json new file mode 100755 index 0000000..de2ffc3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline_big@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline_big@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "right_hand_outline_big@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x.png new file mode 100755 index 0000000..f4647fc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png new file mode 100755 index 0000000..4d9d639 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@3x.png new file mode 100755 index 0000000..4d9d639 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_outline_big.imageset/right_hand_outline_big@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/Contents.json new file mode 100755 index 0000000..d0c4869 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_solid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_solid@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "right_hand_solid@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x.png new file mode 100755 index 0000000..6872ebb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x~ipad.png new file mode 100755 index 0000000..fe50bd5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@3x.png new file mode 100755 index 0000000..fdd76f2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Images.xcassets/right_hand_solid.imageset/right_hand_solid@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/LaunchScreen.xib b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/LaunchScreen.xib new file mode 100755 index 0000000..c918d0f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/LaunchScreen.xib @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/Base.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ar.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ar.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ar.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ca.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ca.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ca.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/cs.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/cs.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/cs.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/da.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/da.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/da.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/de.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/de.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/de.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/el.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/el.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/el.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-AU.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-AU.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-AU.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-GB.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-GB.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en-GB.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/en.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es-MX.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es-MX.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es-MX.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/es.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fi.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fi.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr-CA.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr-CA.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr-CA.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/fr.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/he.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/he.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/he.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hi.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hi.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hr.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hr.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hu.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hu.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/hu.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/id.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/id.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/id.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/it.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/it.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/it.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ja.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ja.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ja.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ko.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ko.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ko.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ms.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ms.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ms.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nb.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nb.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nb.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nl.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nl.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/nl.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pl.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pl.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pl.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt-PT.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt-PT.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt-PT.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/pt.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ro.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ro.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ro.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ru.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ru.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/ru.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sk.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sk.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sk.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sv.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sv.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/sv.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/th.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/th.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/th.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/tr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/tr.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/tr.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/uk.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/uk.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/uk.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/vi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/vi.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/vi.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-HK.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-HK.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-HK.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hans.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hans.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hans.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hant.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hant.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh-Hant.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh_TW.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh_TW.lproj/Localizable.strings new file mode 100755 index 0000000..8b13789 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/Localized/zh_TW.lproj/Localizable.strings @@ -0,0 +1 @@ + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/SAMPLE_PDF_TEST.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/SAMPLE_PDF_TEST.pdf new file mode 100755 index 0000000..47dafc2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/SAMPLE_PDF_TEST.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/image_example.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/image_example.png new file mode 100755 index 0000000..cab7fd9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/image_example.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/signature.png b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/signature.png new file mode 100755 index 0000000..b486d74 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Resources/signature.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ContinueButtonExample.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ContinueButtonExample.storyboard new file mode 100755 index 0000000..7896b79 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ContinueButtonExample.storyboard @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/Info.plist new file mode 100755 index 0000000..3fd3854 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.3 + CFBundleSignature + ???? + CFBundleVersion + 1.3 + LSRequiresIPhoneOS + + NSCameraUsageDescription + Test Camera related features. + NSFaceIDUsageDescription + This app uses Face ID. + NSHealthShareUsageDescription + Test HK releated features. + NSHealthUpdateUsageDescription + Test HK releated features. + NSLocationWhenInUseUsageDescription + This app records your location during certian tasks. + NSMicrophoneUsageDescription + Test audio recording features. + NSMotionUsageDescription + Use motion sensors + UIBackgroundModes + + audio + location + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest-Bridging-Header.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest-Bridging-Header.h new file mode 100755 index 0000000..ceecb9d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "TaskFactory.h" diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest.entitlements b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest.entitlements new file mode 100755 index 0000000..e10f430 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/ORKTest.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.healthkit + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/main.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/main.m new file mode 100755 index 0000000..286148c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Supporting Files/main.m @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +@import UIKit; +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.h new file mode 100755 index 0000000..7ac6b4d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (ActiveTasks) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.m new file mode 100755 index 0000000..86572e4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+ActiveTasks.m @@ -0,0 +1,326 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+ActiveTasks.h" + +@import ResearchKit; + + +@implementation TaskFactory (ActiveTasks) + +/* + This task demonstrates direct use of active steps, which is not particularly + well-supported by the framework. The intended use of `ORKActiveStep` is as a + base class for creating new types of active step, with matching view + controllers appropriate to the particular task that uses them. + + Nonetheless, this functions as a test-bed for basic active task functonality. + */ +- (id)makeActiveStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + /* + Example of a fully-fledged instruction step. + The text of this step is not appropriate to the rest of the task, but + is helpful for verifying layout. + */ + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step.title = @"Demo Study"; + step.text = @"This 12-step walkthrough will explain the study and the impact it will have on your life."; + step.detailText = @"You must complete the walkthough to participate in the study."; + [steps addObject:step]; + } + + { + /* + Audio-recording active step, configured directly using `ORKActiveStep`. + + Not a recommended way of doing audio recording with the ResearchKit framework. + */ + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:@"step2"]; + step.title = @"Audio"; + step.stepDuration = 10.0; + step.text = @"An active test recording audio"; + step.recorderConfigurations = @[[[ORKAudioRecorderConfiguration alloc] initWithIdentifier:@"aid_001d.audio" recorderSettings:@{}]]; + step.shouldUseNextAsSkipButton = YES; + [steps addObject:step]; + } + + { + /* + Audio-recording active step with lossless audio, configured directly + using `ORKActiveStep`. + + Not a recommended way of doing audio recording with the ResearchKit framework. + */ + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:@"step3"]; + step.title = @"Audio"; + step.stepDuration = 10.0; + step.text = @"An active test recording lossless audio"; + step.shouldUseNextAsSkipButton = YES; + step.recorderConfigurations = @[[[ORKAudioRecorderConfiguration alloc] + initWithIdentifier:@"aid_001e.audio" recorderSettings:@{AVFormatIDKey : @(kAudioFormatAppleLossless), + AVNumberOfChannelsKey : @(2), + AVSampleRateKey: @(44100.0) + }]]; + [steps addObject:step]; + } + + { + /* + Touch recorder active step. This should record touches on the primary + view for a 30 second period. + + Not a recommended way of collecting touch data with the ResearchKit framework. + */ + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:@"step4"]; + step.title = @"Touch"; + step.text = @"An active test, touch collection"; + step.shouldStartTimerAutomatically = NO; + step.stepDuration = 30.0; + step.spokenInstruction = @"An active test, touch collection"; + step.shouldUseNextAsSkipButton = YES; + step.recorderConfigurations = @[[[ORKTouchRecorderConfiguration alloc] initWithIdentifier:@"aid_001a.touch"]]; + [steps addObject:step]; + } + + { + /* + Test for device motion recorder directly on an active step. + + Not a recommended way of customizing active steps with the ResearchKit framework. + */ + ORKActiveStep *step = [[ORKActiveStep alloc] initWithIdentifier:@"step5"]; + step.title = @"Motion"; + step.text = @"An active test collecting device motion data"; + step.shouldUseNextAsSkipButton = YES; + step.recorderConfigurations = @[[[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:@"aid_001c.deviceMotion" frequency:100.0]]; + + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeAudioTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask audioTaskWithIdentifier:identifier + intendedUseDescription:nil + speechInstruction:nil + shortSpeechInstruction:nil + duration:10 + recordingSettings:nil + checkAudioLevel:YES + options:(ORKPredefinedTaskOption)0]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeFitnessTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask fitnessCheckTaskWithIdentifier:identifier + intendedUseDescription:nil + walkDuration:360 + restDuration:180 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeGaitTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask shortWalkTaskWithIdentifier:identifier + intendedUseDescription:nil + numberOfStepsPerLeg:20 + restDuration:30 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeHandTremorTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask tremorTestTaskWithIdentifier:identifier + intendedUseDescription:nil + activeStepDuration:10 + activeTaskOptions: + ORKTremorActiveTaskOptionExcludeHandAtShoulderHeight | + ORKTremorActiveTaskOptionExcludeHandAtShoulderHeightElbowBent | + ORKTremorActiveTaskOptionExcludeHandToNose + handOptions:ORKPredefinedTaskHandOptionBoth + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeHandRightTremorTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask tremorTestTaskWithIdentifier:identifier + intendedUseDescription:nil + activeStepDuration:10 + activeTaskOptions:0 + handOptions:ORKPredefinedTaskHandOptionRight + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeHolePegTestTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKNavigableOrderedTask holePegTestTaskWithIdentifier:identifier + intendedUseDescription:nil + dominantHand:ORKBodySagittalRight + numberOfPegs:9 + threshold:0.2 + rotated:NO + timeLimit:300.0 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + + +- (id)makeMemoryGameTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask spatialSpanMemoryTaskWithIdentifier:identifier + intendedUseDescription:nil + initialSpan:3 + minimumSpan:2 + maximumSpan:15 + playSpeed:1 + maximumTests:5 + maximumConsecutiveFailures:3 + customTargetImage:nil + customTargetPluralName:nil + requireReversal:NO + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makePsatTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask PSATTaskWithIdentifier:identifier + intendedUseDescription:nil + presentationMode:(ORKPSATPresentationModeAuditory | ORKPSATPresentationModeVisual) + interStimulusInterval:3.0 + stimulusDuration:1.0 + seriesLength:60 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeReactionTimeTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask reactionTimeTaskWithIdentifier:identifier + intendedUseDescription:nil + maximumStimulusInterval:8 + minimumStimulusInterval:4 + thresholdAcceleration:0.5 + numberOfAttempts:3 + timeout:10 + successSound:0 + timeoutSound:0 + failureSound:0 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeStroopTaskWithIdentifier:(NSString *)identifier { + return [ORKOrderedTask stroopTaskWithIdentifier:identifier + intendedUseDescription:nil + numberOfAttempts:15 + options:0]; +} + +- (id)makeTimedWalkTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask timedWalkTaskWithIdentifier:identifier + intendedUseDescription:nil + distanceInMeters:100 + timeLimit:180 + turnAroundTimeLimit:60 + includeAssistiveDeviceForm:YES + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeToneAudiometryTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask toneAudiometryTaskWithIdentifier:identifier + intendedUseDescription:nil + speechInstruction:nil + shortSpeechInstruction:nil + toneDuration:20 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeTowerOfHanoiTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask towerOfHanoiTaskWithIdentifier:identifier + intendedUseDescription:nil + numberOfDisks:5 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + + +- (id)makeTrailMakingTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask trailmakingTaskWithIdentifier:identifier + intendedUseDescription:nil + trailmakingInstruction:nil + trailType:ORKTrailMakingTypeIdentifierA + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeTwoFingerTappingTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:identifier + intendedUseDescription:nil + duration:20.0 + handOptions:ORKPredefinedTaskHandOptionBoth + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +- (id)makeWalkAndTurnTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = [ORKOrderedTask walkBackAndForthTaskWithIdentifier:identifier + intendedUseDescription:nil + walkDuration:30 + restDuration:30 + options:ORKPredefinedTaskOptionNone]; + task.hidesLearnMoreButtonOnInstructionStep = YES; + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.h new file mode 100755 index 0000000..c668850 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (Forms) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.m new file mode 100755 index 0000000..3882878 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Forms.m @@ -0,0 +1,943 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+Forms.h" + +@import ResearchKit; + + +@implementation TaskFactory (Forms) + +- (id)makeConfirmationFormItemTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Confirmation Form"; + step1.text = @"Proceed to register a new account."; + [steps addObject:step1]; + + // Create a step for entering password with confirmation + ORKFormStep *step2 = [[ORKFormStep alloc] initWithIdentifier:@"step2" title:@"Password" text:@"Register a new password"]; + [steps addObject:step2]; + + { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.secureTextEntry = YES; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeNone; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + if (@available(iOS 12.0, *)) { + answerFormat.textContentType = UITextContentTypeNewPassword; + } else { + answerFormat.textContentType = UITextContentTypePassword; + } + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"password" + text:@"Password" + answerFormat:answerFormat + optional:NO]; + item.placeholder = @"Enter password"; + + ORKFormItem *confirmationItem = [item confirmationAnswerFormItemWithIdentifier:@"password.confirmation" + text:@"Confirm" + errorMessage:@"Passwords do not match"]; + confirmationItem.placeholder = @"Enter password again"; + + step2.formItems = @[item, confirmationItem]; + } + + // Create a step for entering participant id + ORKFormStep *step3 = [[ORKFormStep alloc] initWithIdentifier:@"step3" title:@"Participant ID" text:@"Register a new participant ID"]; + [steps addObject:step3]; + + { + ORKTextAnswerFormat *answerFormat = [ORKAnswerFormat textAnswerFormat]; + answerFormat.multipleLines = NO; + answerFormat.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters; + answerFormat.autocorrectionType = UITextAutocorrectionTypeNo; + answerFormat.spellCheckingType = UITextSpellCheckingTypeNo; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"participantID" + text:@"Participant ID" + answerFormat:answerFormat + optional:YES]; + item.placeholder = @"Enter Participant ID"; + + ORKFormItem *confirmationItem = [item confirmationAnswerFormItemWithIdentifier:@"participantID.confirmation" + text:@"Confirm" + errorMessage:@"IDs do not match"]; + confirmationItem.placeholder = @"Enter ID again"; + + step3.formItems = @[item, confirmationItem]; + } + + ORKCompletionStep *step4 = [[ORKCompletionStep alloc] initWithIdentifier:@"confirmationForm.lastStep"]; + step4.title = @"Survey Complete"; + step4.text = @"Thank you for registering."; + [steps addObject:step4]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +/* + The mini form task is used to test survey forms functionality (`ORKFormStep`). + */ +- (id)makeMiniFormTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step.title = @"Mini Form"; + [steps addObject:step]; + } + + { + /* + A short form for testing behavior when loading multiple HealthKit + default values on the same form. + */ + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step2" + title:@"Mini Form" + text:@"Mini form groups multi-entry in one page"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"weight1" + text:@"Weight" + answerFormat: + [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] + unit:[HKUnit unitFromMassFormatterUnit:NSMassFormatterUnitPound] + style:ORKNumericAnswerStyleDecimal]]; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"weight2" + text:@"Weight" + answerFormat: + [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] + unit:[HKUnit unitFromMassFormatterUnit:NSMassFormatterUnitPound] + style:ORKNumericAnswerStyleDecimal]]; + item.placeholder = @"Add weight"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"weight3" + text:@"Weight" + answerFormat: + [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] + unit:[HKUnit unitFromMassFormatterUnit:NSMassFormatterUnitPound] + style:ORKNumericAnswerStyleDecimal]]; + item.placeholder = @"Input your body weight here. Really long text."; + [items addObject:item]; + } + + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"weight4" + text:@"Weight" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + item.placeholder = @"Input your body weight here"; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + /* + A long "kitchen-sink" form with all the different types of supported + answer formats. + */ + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step3" title:@"Mini Form" text:@"Mini form groups multi-entry in one page"]; + NSMutableArray *items = [NSMutableArray new]; + + { + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"biologicalSex" text:@"Gender" answerFormat:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]]]; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Basic Information"]; + [items addObject:item]; + } + + { + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"bloodType" text:@"Blood Type" answerFormat:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]]]; + item.placeholder = @"Choose a type"; + [items addObject:item]; + } + + { + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"dateOfBirth" text:@"Date of Birth" answerFormat:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth]]]; + item.placeholder = @"DOB"; + [items addObject:item]; + } + + { + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"weight" + text:@"Weight" + answerFormat: + [ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] + unit:nil + style:ORKNumericAnswerStyleDecimal]]; + item.placeholder = @"Add weight"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"headacheQuestion" text:@"Do you have a headache?" answerFormat:[ORKBooleanAnswerFormat new]]; + [items addObject:item]; + } + + { + ORKTextChoice *apple = [ORKTextChoice choiceWithText:@"Apple" value:@"Apple"]; + ORKTextChoice *orange = [ORKTextChoice choiceWithText:@"Orange" value:@"Orange"]; + ORKTextChoice *banana = [ORKTextChoice choiceWithText:@"Banana" value:@"Banana"]; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_002" + text:@"Which fruit do you like most? Please pick one from below." + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:@[apple, orange, banana]]]; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"message1" text:@"Message" + answerFormat:[ORKAnswerFormat textAnswerFormat]]; + item.placeholder = @"Your message"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"bpDiastolic" text:@"BP Diastolic" + answerFormat:[ORKAnswerFormat integerAnswerFormatWithUnit:@"mm Hg"]]; + item.placeholder = @"Enter value"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"bpSystolic" text:@"BP Systolic" + answerFormat:[ORKAnswerFormat integerAnswerFormatWithUnit:@"mm Hg"]]; + item.placeholder = @"Enter value"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"email" text:@"Email" + answerFormat:[ORKAnswerFormat emailAnswerFormat]]; + item.placeholder = @"Enter Email"; + [items addObject:item]; + } + + { + + NSRegularExpression *validationRegularExpression = + [NSRegularExpression regularExpressionWithPattern:@"^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" + options:(NSRegularExpressionOptions)0 + error:nil]; + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithValidationRegularExpression:validationRegularExpression + invalidMessage:@"Invalid URL: %@"]; + format.multipleLines = NO; + format.keyboardType = UIKeyboardTypeURL; + format.autocapitalizationType = UITextAutocapitalizationTypeNone; + format.autocorrectionType = UITextAutocorrectionTypeNo; + format.spellCheckingType = UITextSpellCheckingTypeNo; + format.textContentType = UITextContentTypeURL; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"url" text:@"URL" + answerFormat:format]; + item.placeholder = @"Enter URL"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"message2" text:@"Message" + answerFormat:[ORKAnswerFormat textAnswerFormatWithMaximumLength:20]]; + item.placeholder = @"Your message (limit 20 characters)."; + [items addObject:item]; + } + + { + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.secureTextEntry = YES; + format.multipleLines = NO; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"passcode" text:@"Passcode" + answerFormat:format]; + item.placeholder = @"Enter Passcode"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"height1" text:@"Height" + answerFormat:[ORKAnswerFormat heightAnswerFormat]]; + item.placeholder = @"Pick a height (local system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"height2" text:@"Height" + answerFormat:[ORKAnswerFormat heightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric]]; + item.placeholder = @"Pick a height (metric system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"height3" text:@"Height" + answerFormat:[ORKAnswerFormat heightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemUSC]]; + item.placeholder = @"Pick a height (imperial system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_001" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormat]]; + item.placeholder = @"Pick a weight (local system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_002" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric]]; + item.placeholder = @"Pick a weight (metric system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_003" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemUSC]]; + item.placeholder = @"Pick a weight (USC system)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_004" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric + numericPrecision:ORKNumericPrecisionLow + minimumValue:10 + maximumValue:20 + defaultValue:11.5]]; + item.placeholder = @"Pick a weight (metric system, low precision)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_005" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemUSC + numericPrecision:ORKNumericPrecisionLow + minimumValue:10 + maximumValue:20 + defaultValue:11.5]]; + item.placeholder = @"Pick a weight (USC system, low precision)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_006" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemMetric + numericPrecision:ORKNumericPrecisionHigh + minimumValue:10 + maximumValue:20 + defaultValue:11.5]]; + item.placeholder = @"Pick a weight (metric system, high precision)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_weight_007" text:@"Weight" + answerFormat:[ORKAnswerFormat weightAnswerFormatWithMeasurementSystem:ORKMeasurementSystemUSC + numericPrecision:ORKNumericPrecisionHigh + minimumValue:10 + maximumValue:20 + defaultValue:11.5]]; + item.placeholder = @"Pick a weight (USC system, high precision)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"birthdate1" text:@"Birthdate" + answerFormat:[ORKAnswerFormat dateAnswerFormat]]; + item.placeholder = @"Pick a date"; + [items addObject:item]; + } + + { + NSDate *defaultDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitYear value:-30 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *minDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitYear value:-150 toDate:[NSDate date] options:(NSCalendarOptions)0]; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"birthdate2" text:@"Birthdate" + answerFormat:[ORKAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate + minimumDate:minDate + maximumDate:[NSDate date] + calendar:nil]]; + item.placeholder = @"Pick a date (with default)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"timeOfDay1" text:@"Today sunset time?" + answerFormat:[ORKAnswerFormat timeOfDayAnswerFormat]]; + item.placeholder = @"No default time"; + [items addObject:item]; + } + + { + NSDateComponents *defaultDC = [[NSDateComponents alloc] init]; + defaultDC.hour = 14; + defaultDC.minute = 23; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"timeOfDay2" text:@"Today sunset time?" + answerFormat:[ORKAnswerFormat timeOfDayAnswerFormatWithDefaultComponents:defaultDC]]; + item.placeholder = @"Default time 14:23"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"dateTime1" text:@"Next eclipse visible in Cupertino?" + answerFormat:[ORKAnswerFormat dateTimeAnswerFormat]]; + + item.placeholder = @"No default date and range"; + [items addObject:item]; + } + + { + + NSDate *defaultDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:3 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *minDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:0 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *maxDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:10 toDate:[NSDate date] options:(NSCalendarOptions)0]; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"dateTime2" + text:@"Next eclipse visible in Cupertino?" + answerFormat:[ORKAnswerFormat dateTimeAnswerFormatWithDefaultDate:defaultDate + minimumDate:minDate + maximumDate:maxDate + calendar:nil]]; + + item.placeholder = @"Default date in 3 days and range(0, 10)"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"timeInterval1" text:@"Wake up interval" + answerFormat:[ORKAnswerFormat timeIntervalAnswerFormat]]; + item.placeholder = @"No default Interval and step size"; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"timeInterval2" text:@"Wake up interval" + answerFormat:[ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:300 step:3]]; + item.placeholder = @"Default Interval 300 and step size 3"; + [items addObject:item]; + } + + { + /* + Testbed for image choice. + + In a real application, you would use real images rather than square + colored boxes. + */ + ORKImageChoice *option1 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor redColor] size:CGSizeMake(360, 360) border:NO] + selectedImage:[self imageWithColor:[UIColor redColor] size:CGSizeMake(360, 360) border:YES] + text:@"Red" value:@"red"]; + ORKImageChoice *option2 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor orangeColor] size:CGSizeMake(360, 360) border:NO] + selectedImage:[self imageWithColor:[UIColor orangeColor] size:CGSizeMake(360, 360) border:YES] + text:nil value:@"orange"]; + ORKImageChoice *option3 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor yellowColor] size:CGSizeMake(360, 360) border:NO] + selectedImage:[self imageWithColor:[UIColor yellowColor] size:CGSizeMake(360, 360) border:YES] + text:@"Yellow" value:@"yellow"]; + + ORKFormItem *item3 = [[ORKFormItem alloc] initWithIdentifier:@"favoriteColor" text:@"What is your favorite color?" + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2, option3]]]; + [items addObject:item3]; + } + + { + // Discrete scale + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale1" text:@"Pick an integer" answerFormat:[[ORKScaleAnswerFormat alloc] initWithMaximumValue:100 minimumValue:0 defaultValue:NSIntegerMax step:10]]; + [items addObject:item]; + } + + { + // Discrete scale, with default value + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale2" text:@"Pick an integer" answerFormat:[[ORKScaleAnswerFormat alloc] initWithMaximumValue:100 minimumValue:0 defaultValue:20 step:10]]; + [items addObject:item]; + } + + { + // Continuous scale + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale3" text:@"Pick a decimal" answerFormat:[[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:100 minimumValue:0 defaultValue:NSIntegerMax maximumFractionDigits:2]]; + [items addObject:item]; + } + + { + // Continuous scale, with default value + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale4" text:@"Pick a decimal" answerFormat:[[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:100 minimumValue:0 defaultValue:87.34 maximumFractionDigits:2]]; + [items addObject:item]; + } + + { + // Vertical Discrete scale, with default value + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale5" text:@"Pick an integer" answerFormat:[[ORKScaleAnswerFormat alloc] initWithMaximumValue:100 minimumValue:0 defaultValue:90 step:10 vertical:YES]]; + [items addObject:item]; + } + + { + // Vertical Continuous scale, with default value + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale6" text:@"Pick a decimal" answerFormat:[[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue: 100 minimumValue: 0 defaultValue:12.75 maximumFractionDigits:2 vertical:YES]]; + [items addObject:item]; + } + + { + ORKTextChoice *textChoice1 = [ORKTextChoice choiceWithText:@"Poor" value:@(1)]; + ORKTextChoice *textChoice2 = [ORKTextChoice choiceWithText:@"Fair" value:@(2)]; + ORKTextChoice *textChoice3 = [ORKTextChoice choiceWithText:@"Good" value:@(3)]; + ORKTextChoice *textChoice4 = [ORKTextChoice choiceWithText:@"Above Average" value:@(4)]; + ORKTextChoice *textChoice5 = [ORKTextChoice choiceWithText:@"Excellent" value:@(5)]; + + NSArray *textChoices = @[textChoice1, textChoice2, textChoice3, textChoice4, textChoice5]; + + ORKTextScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices + defaultIndex:NSIntegerMax + vertical:NO]; + scaleAnswerFormat.hideSelectedValue = YES; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale7" + text:@"How are you feeling today?" + answerFormat:scaleAnswerFormat]; + [items addObject:item]; + } + + { + ORKTextChoice *textChoice1 = [ORKTextChoice choiceWithText:@"Poor" value:@(1)]; + ORKTextChoice *textChoice2 = [ORKTextChoice choiceWithText:@"Fair" value:@(2)]; + ORKTextChoice *textChoice3 = [ORKTextChoice choiceWithText:@"Good" value:@(3)]; + ORKTextChoice *textChoice4 = [ORKTextChoice choiceWithText:@"Above Average" value:@(4)]; + ORKTextChoice *textChoice5 = [ORKTextChoice choiceWithText:@"Excellent" value:@(5)]; + + NSArray *textChoices = @[textChoice1, textChoice2, textChoice3, textChoice4, textChoice5]; + + ORKTextScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices + defaultIndex:NSIntegerMax + vertical:YES]; + scaleAnswerFormat.hideSelectedValue = YES; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale8" + text:@"How are you feeling today?" + answerFormat:scaleAnswerFormat]; + [items addObject:item]; + } + + { + //Location + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"location" text:@"Pick a location" answerFormat:[ORKAnswerFormat locationAnswerFormat]]; + [items addObject:item]; + } + + [step setFormItems:items]; + [steps addObject:step]; + } + + { + + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step4" title:@"Required form step" text:nil]; + ORKTextChoice *one = [ORKTextChoice choiceWithText:@"1" value:@"1"]; + ORKTextChoice *two = [ORKTextChoice choiceWithText:@"2" value:@"2"]; + ORKTextChoice *three = [ORKTextChoice choiceWithText:@"3" value:@"3"]; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"fqid_001" + text:@"Value" + answerFormat:[ORKNumericAnswerFormat valuePickerAnswerFormatWithTextChoices:@[one, two, three]]]; + item.placeholder = @"Pick a value"; + [step setFormItems:@[item]]; + step.optional = NO; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step5"]; + step.title = @"Thanks"; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +/* + The optional form task is used to test form items' optional functionality (`ORKFormStep`, `ORKFormItem`). + */ +- (id)makeOptionalFormTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step1" + title:@"Optional Form Items" + text:@"Optional form with a required scale item with a default value"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKScaleAnswerFormat *format = [ORKScaleAnswerFormat scaleAnswerFormatWithMaximumValue:10 minimumValue:1 defaultValue:4 step:1 vertical:YES maximumValueDescription:nil minimumValueDescription:nil]; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"scale" + text:@"Optional scale" + answerFormat:format]; + item.optional = NO; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step2" title:@"Optional Form Items" text:@"Optional form with no required items"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Optional"]; + [items addObject:item]; + } + + { + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text" + text:@"Text" + answerFormat:format]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step3" title:@"Optional Form Items" text:@"Optional form with some required items"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Optional"]; + [items addObject:item]; + } + + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text1" + text:@"Text A" + answerFormat:format]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text2" + text:@"Text B" + answerFormat:format]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Required"]; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text3" + text:@"Text C" + answerFormat:format + optional:NO]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil] + optional:NO]; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step4" title:@"Optional Form Items" text:@"Optional form with all items required"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Required"]; + [items addObject:item]; + } + + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text1" + text:@"Text A" + answerFormat:format + optional:NO]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text2" + text:@"Text B" + answerFormat:format + optional:NO]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text3" + text:@"Text C" + answerFormat:format + optional:NO]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil] + optional:NO]; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step5" title:@"Optional Form Items" text:@"Optional form with custom validation"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Optional"]; + [items addObject:item]; + } + + { + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text" + text:@"Text" + answerFormat:format]; + item.placeholder = @"Input the value \"Valid\" to proceed."; + item.optional = NO; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step6" title:@"Optional Form Items" text:@"Required form with no required items"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Optional"]; + [items addObject:item]; + } + + { + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:6]; + format.multipleLines = NO; + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text" + text:@"Text" + answerFormat:format]; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + step.optional = NO; + + step.shouldPresentStepBlock = ^BOOL(ORKTaskViewController *taskViewController, ORKStep *step) { + ORKTextQuestionResult *textResult = (ORKTextQuestionResult *)[[taskViewController.result stepResultForStepIdentifier:@"step5"] resultForIdentifier:@"text"]; + BOOL isValid = [textResult.answer isEqualToString:@"Valid"]; + if (!isValid) { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil + message:@"Invalid text field value." + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [taskViewController presentViewController:alert animated:YES completion:nil]; + } + return isValid; + }; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step7" title:@"Optional Form Items" text:@"Required form with some required items"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Optional"]; + [items addObject:item]; + } + + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text1" + text:@"Text A" + answerFormat:format]; + item.placeholder = @"Input your text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text2" + text:@"Text B" + answerFormat:format]; + item.placeholder = @"Input your text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Required"]; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text3" + text:@"Text C" + answerFormat:format]; + item.optional = NO; + item.placeholder = @"Input your text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + item.optional = NO; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + step.optional = NO; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"step8" title:@"Optional Form Items" text:@"Required form with all items required"]; + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithSectionTitle:@"Required"]; + [items addObject:item]; + } + + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:12]; + format.multipleLines = NO; + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text1" + text:@"Text A" + answerFormat:format]; + item.optional = NO; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text2" + text:@"Text B" + answerFormat:format]; + item.optional = NO; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"text3" + text:@"Text C" + answerFormat:format]; + item.optional = NO; + item.placeholder = @"Input any text here."; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"number" + text:@"Number" + answerFormat:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:nil]]; + item.optional = NO; + item.placeholder = @"Input any number here."; + [items addObject:item]; + } + + [step setFormItems:items]; + step.optional = NO; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.h new file mode 100755 index 0000000..fd7e817 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (Onboarding) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.m new file mode 100755 index 0000000..022b9ab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+Onboarding.m @@ -0,0 +1,375 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+Onboarding.h" + +@import ResearchKit; + + +/** + A subclass is required for the login step. + + The implementation below demonstrates how to subclass and override button actions. + */ +@interface LoginViewController : ORKLoginStepViewController + +@end + + +@implementation LoginViewController + +- (void)forgotPasswordButtonTapped { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Forgot password?" + message:@"Button tapped" + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +@end + + +/** + A subclass is required for the verification step. + + The implementation below demonstrates how to subclass and override button actions. + */ +@interface VerificationViewController : ORKVerificationStepViewController + +@end + + +@implementation VerificationViewController + +- (void)resendEmailButtonTapped { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Resend Verification Email" + message:@"Button tapped" + preferredStyle:UIAlertControllerStyleAlert]; + [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +@end + + +@implementation TaskFactory (Onboarding) + +#pragma mark - Consent review task + +/* + This consent task demonstrates visual consent, followed by a consent review step. + + In a real consent process, you would substitute the text of your consent document + for the various placeholders. + */ +- (id)makeConsentTaskWithIdentifier:(NSString *)identifier { + /* + Most of the configuration of what pages will appear in the visual consent step, + and what content will be displayed in the consent review step, it in the + consent document itself. + */ + ORKConsentDocument *consentDocument = [self buildConsentDocument]; + self.currentConsentDocument = [consentDocument copy]; + + ORKVisualConsentStep *step = [[ORKVisualConsentStep alloc] initWithIdentifier:@"visualConsent" document:consentDocument]; + step.title = @"Consent Document"; + ORKConsentReviewStep *reviewStep = [[ORKConsentReviewStep alloc] initWithIdentifier:@"consentReview" signature:consentDocument.signatures[0] inDocument:consentDocument]; + reviewStep.title = @"Consent Review"; + reviewStep.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + reviewStep.reasonForConsent = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step, reviewStep]]; + + return task; +} + +/* + The consent review task is used to quickly verify the layout of the consent + sharing step and the consent review step. + + In a real consent process, you would substitute the text of your consent document + for the various placeholders. + */ +- (id)makeConsentReviewTaskWithIdentifier:(NSString *)identifier { + /* + Tests layout of the consent sharing step. + + This step is used when you want to obtain permission to share the data + collected with other researchers for uses beyond the present study. + */ + ORKConsentSharingStep *sharingStep = + [[ORKConsentSharingStep alloc] initWithIdentifier:@"consentSharing" + investigatorShortDescription:@"MyInstitution" + investigatorLongDescription:@"MyInstitution and its partners" + localizedLearnMoreHTMLContent:@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."]; + + /* + Tests layout of the consent review step. + + In the consent review step, the user reviews the consent document and + optionally enters their name and/or draws a signature. + */ + ORKConsentDocument *consentDocument = [self buildConsentDocument]; + ORKConsentSignature *participantSig = consentDocument.signatures[0]; + [participantSig setSignatureDateFormatString:@"yyyy-MM-dd 'at' HH:mm"]; + self.currentConsentDocument = [consentDocument copy]; + ORKConsentReviewStep *reviewStep = [[ORKConsentReviewStep alloc] initWithIdentifier:@"consentReview" signature:participantSig inDocument:consentDocument]; + reviewStep.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + reviewStep.reasonForConsent = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[sharingStep,reviewStep]]; + return task; +} + +/* + The eligibility form task is used to demonstrate an eligibility form (`ORKFormStep`, `ORKFormItem`). + */ +- (id)makeEligibilityFormTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"introStep"]; + step.title = @"Eligibility Form"; + [steps addObject:step]; + } + + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:@"formStep"]; + step.optional = NO; + step.title = @"Eligibility Form"; + step.text = @"Please answer the questions below."; + + NSMutableArray *items = [NSMutableArray new]; + [steps addObject:step]; + + { + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"formItem1" + text:@"Are you over 18 years of age?" + answerFormat:[ORKAnswerFormat booleanAnswerFormat]]; + item.optional = NO; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"formItem2" + text:@"Have you been diagnosed with pre-diabetes or type 2 diabetes?" + answerFormat:[ORKAnswerFormat booleanAnswerFormat]]; + item.optional = NO; + [items addObject:item]; + } + + { + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"formItem3" + text:@"Can you not read and understand English in order to provide informed consent and follow the instructions?" + answerFormat:[ORKAnswerFormat booleanAnswerFormat]]; + item.optional = NO; + [items addObject:item]; + } + + { + NSArray *textChoices = @[[ORKTextChoice choiceWithText:@"Yes" value:@1], + [ORKTextChoice choiceWithText:@"No" value:@0], + [ORKTextChoice choiceWithText:@"N/A" value:@2]]; + ORKTextChoiceAnswerFormat *answerFormat = (ORKTextChoiceAnswerFormat *)[ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + ORKFormItem *item = [[ORKFormItem alloc] initWithIdentifier:@"formItem4" + text:@"Are you pregnant?" + answerFormat:answerFormat]; + item.optional = NO; + [items addObject:item]; + } + + [step setFormItems:items]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"ineligibleStep"]; + step.title = @"Eligibility Form"; + step.text = @"You are ineligible to join the study."; + [steps addObject:step]; + } + + { + ORKCompletionStep *step = [[ORKCompletionStep alloc] initWithIdentifier:@"eligibleStep"]; + step.title = @"Eligibility Form"; + step.text = @"You are eligible to join the study."; + [steps addObject:step]; + } + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + // Build navigation rules. + ORKPredicateStepNavigationRule *predicateRule = nil; + ORKResultSelector *resultSelector = nil; + + resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"formStep" resultIdentifier:@"formItem1"]; + NSPredicate *predicateFormItem1 = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:YES]; + + resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"formStep" resultIdentifier:@"formItem2"]; + NSPredicate *predicateFormItem2 = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:YES]; + + resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"formStep" resultIdentifier:@"formItem3"]; + NSPredicate *predicateFormItem3 = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:NO]; + + resultSelector = [ORKResultSelector selectorWithStepIdentifier:@"formStep" resultIdentifier:@"formItem4"]; + NSPredicate *predicateFormItem4a = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValue:@0]; + NSPredicate *predicateFormItem4b = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValue:@2]; + + NSPredicate *predicateEligible1 = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateFormItem1,predicateFormItem2, predicateFormItem3, predicateFormItem4a]]; + NSPredicate *predicateEligible2 = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicateFormItem1,predicateFormItem2, predicateFormItem3, predicateFormItem4b]]; + + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateEligible1, predicateEligible2] + destinationStepIdentifiers:@[@"eligibleStep", @"eligibleStep"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"formStep"]; + + // Add end direct rules to skip unneeded steps + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKNullStepIdentifier]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"ineligibleStep"]; + + return task; +} + +/* + The eligibility survey task is used to demonstrate an eligibility survey. + */ +- (id)makeEligibilitySurveyTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"introStep"]; + step.title = @"Eligibility Survey"; + [steps addObject:step]; + } + + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question1" + title:@"Eligibility Survey" + question:@"Are you over 18 years of age?" + answer:[ORKAnswerFormat booleanAnswerFormat]]; + step.optional = NO; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"ineligibleStep"]; + step.title = @"Eligibility Survey"; + step.text = @"You are ineligible to join the study."; + [steps addObject:step]; + } + + { + ORKCompletionStep *step = [[ORKCompletionStep alloc] initWithIdentifier:@"eligibleStep"]; + step.title = @"Eligibility Survey"; + step.text = @"You are eligible to join the study."; + [steps addObject:step]; + } + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + // Build navigation rules. + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question1"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:YES]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"eligibleStep"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question1"]; + + // Add end direct rules to skip unneeded steps + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:ORKNullStepIdentifier]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"ineligibleStep"]; + + return task; +} + +/* + The login task is used to demonstrate a login step. + */ + +- (id)makeLoginTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKLoginStep *step = [[ORKLoginStep alloc] initWithIdentifier:@"loginStep" + title:@"Login" + text:@"Enter your credentials" + loginViewControllerClass:[LoginViewController class]]; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +/* + The registration task is used to demonstrate a registration step. + */ +- (id)makeRegistrationTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKRegistrationStepOption options = (ORKRegistrationStepIncludeFamilyName | + ORKRegistrationStepIncludeGivenName | + ORKRegistrationStepIncludeDOB | + ORKRegistrationStepIncludeGender); + ORKRegistrationStep *step = [[ORKRegistrationStep alloc] initWithIdentifier:@"registrationStep" + title:@"Registration" + text:@"Fill out the form below" + options:options]; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +/* + The verification task is used to demonstrate a verification step. + */ +- (id)makeVerificationTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKVerificationStep *step = [[ORKVerificationStep alloc] initWithIdentifier:@"verificationStep" text:@"Check your email and click on the link to verify your email address and start using the app." + verificationViewControllerClass:[VerificationViewController class]]; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.h new file mode 100755 index 0000000..f44b601 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (PasscodeManagement) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.m new file mode 100755 index 0000000..9d4483f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+PasscodeManagement.m @@ -0,0 +1,58 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+PasscodeManagement.h" + +@import ResearchKit; + + +@implementation TaskFactory (PasscodeManagement) + +/* + Tests various uses of passcode step and view controllers. + + Passcode authentication and passcode editing are presented in + the examples. Passcode creation would ideally be as part of + the consent process. + */ + +- (id)makeCreatePasscodeTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + ORKPasscodeStep *passcodeStep = [[ORKPasscodeStep alloc] initWithIdentifier:@"createPasscode"]; + passcodeStep.text = @"This passcode protects your privacy and ensures that the user giving consent is the one completing the tasks."; + [steps addObject: passcodeStep]; + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.h new file mode 100755 index 0000000..11de8bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (QuestionSteps) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.m new file mode 100755 index 0000000..3cf8fc8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+QuestionSteps.m @@ -0,0 +1,1255 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+QuestionSteps.h" + +@import ResearchKit; + + +@implementation TaskFactory (QuestionSteps) + +/* + This task presents several questions which exercise functionality based on + `UIDatePicker`. + */ +- (id)makeDatePickersTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"instruction"]; + step.title = @"Date Survey"; + step.detailText = @"date pickers"; + [steps addObject:step]; + } + + /* + A time interval question with no default set. + */ + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"timeInterval1" + title:@"Date Survey" + question:@"How long did it take to fall asleep last night?" + answer:[ORKAnswerFormat timeIntervalAnswerFormat]]; + [steps addObject:step]; + } + + /* + A time interval question specifying a default and a step size. + */ + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"timeInterval2" + title:@"Date Survey" + question:@"How long did it take to fall asleep last night?" + answer:[ORKAnswerFormat timeIntervalAnswerFormatWithDefaultInterval:300 step:5]]; + [steps addObject:step]; + } + + /* + A date answer format question, specifying a specific calendar. + If no calendar were specified, the user's preferred calendar would be used. + */ + { + ORKDateAnswerFormat *dateAnswer = [ORKDateAnswerFormat dateAnswerFormatWithDefaultDate:nil minimumDate:nil maximumDate:nil calendar: [NSCalendar calendarWithIdentifier:NSCalendarIdentifierHebrew]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"date1" + title:@"Date Survey" + question:@"When is your birthday?" + answer:dateAnswer]; + [steps addObject:step]; + } + + /* + A date question with a minimum, maximum, and default. + Also specifically requires the Gregorian calendar. + */ + { + NSDate *defaultDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:10 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *minDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:8 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *maxDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:12 toDate:[NSDate date] options:(NSCalendarOptions)0]; + ORKDateAnswerFormat *dateAnswer = [ORKDateAnswerFormat dateAnswerFormatWithDefaultDate:defaultDate + minimumDate:minDate + maximumDate:maxDate + calendar: [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"date2" + title:@"Date Survey" + question:@"What day are you available?" + answer:dateAnswer]; + [steps addObject:step]; + } + + /* + A time of day question with no default. + */ + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"timeOfDay1" + title:@"Date Survey" + question:@"What time do you get up?" + answer:[ORKTimeOfDayAnswerFormat timeOfDayAnswerFormat]]; + [steps addObject:step]; + } + + /* + A time of day question with a default of 8:15 AM. + */ + { + + NSDateComponents *dateComponents = [[NSDateComponents alloc] init]; + dateComponents.hour = 8; + dateComponents.minute = 15; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"timeOfDay2" + title:@"Date Survey" + question:@"What time do you get up?" + answer:[ORKTimeOfDayAnswerFormat timeOfDayAnswerFormatWithDefaultComponents:dateComponents]]; + [steps addObject:step]; + } + + /* + A date-time question with default parameters (no min, no max, default to now). + */ + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"dateTime1" + title:@"Date Survey" + question:@"When is your next meeting?" + answer:[ORKDateAnswerFormat dateTimeAnswerFormat]]; + [steps addObject:step]; + } + + /* + A date-time question with specified min, max, default date, and calendar. + */ + { + NSDate *defaultDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:10 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *minDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:8 toDate:[NSDate date] options:(NSCalendarOptions)0]; + NSDate *maxDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:12 toDate:[NSDate date] options:(NSCalendarOptions)0]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"dateTime2" + title:@"Date Survey" + question:@"When is your next meeting?" + answer:[ORKDateAnswerFormat dateTimeAnswerFormatWithDefaultDate:defaultDate minimumDate:minDate maximumDate:maxDate calendar:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]]]; + [steps addObject:step]; + + } + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +- (id)makeImageCaptureTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + /* + If implementing an image capture task like this one, remember that people will + take your instructions literally. So, be cautious. Make sure your template image + is high contrast and very visible against a variety of backgrounds. + */ + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"begin"]; + step.title = @"Hands"; + step.image = [[UIImage imageNamed:@"hands_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"In this step we will capture images of both of your hands"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"right1"]; + step.title = @"Right Hand"; + step.image = [[UIImage imageNamed:@"right_hand_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Let's start by capturing an image of your right hand"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"right2"]; + step.title = @"Right Hand"; + step.image = [[UIImage imageNamed:@"right_hand_outline"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Align your right hand with the on-screen outline and capture the image. Be sure to place your hand over a contrasting background. You can re-capture the image as many times as you need."; + [steps addObject:step]; + } + + { + ORKImageCaptureStep *step = [[ORKImageCaptureStep alloc] initWithIdentifier:@"right3"]; + step.templateImage = [UIImage imageNamed:@"right_hand_outline_big"]; + step.templateImageInsets = UIEdgeInsetsMake(0.05, 0.05, 0.05, 0.05); + step.accessibilityInstructions = @"Extend your right hand, palm side down, one foot in front of your device. Tap the Capture Image button, or two-finger double tap the preview to capture the image"; + step.accessibilityHint = @"Captures the image visible in the preview"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"left1"]; + step.title = @"Left Hand"; + step.image = [[UIImage imageNamed:@"left_hand_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Now let's capture an image of your left hand"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"left2"]; + step.title = @"Left Hand"; + step.image = [[UIImage imageNamed:@"left_hand_outline"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Align your left hand with the on-screen outline and capture the image. Be sure to place your hand over a contrasting background. You can re-capture the image as many times as you need."; + [steps addObject:step]; + } + + { + ORKImageCaptureStep *step = [[ORKImageCaptureStep alloc] initWithIdentifier:@"left3"]; + step.templateImage = [UIImage imageNamed:@"left_hand_outline_big"]; + step.templateImageInsets = UIEdgeInsetsMake(0.05, 0.05, 0.05, 0.05); + step.accessibilityInstructions = @"Extend your left hand, palm side down, one foot in front of your device. Tap the Capture Image button, or two-finger double tap the preview to capture the image"; + step.accessibilityHint = @"Captures the image visible in the preview"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"end"]; + step.title = @"Complete"; + step.detailText = @"Hand image capture complete"; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +/* + Tests various uses of image choices. + + All these tests use square colored images to test layout correctness. In a real + application you would use images to convey an image scale. + + Tests image choices both in form items, and in question steps. + */ +- (id)makeImageChoiceTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + for (NSValue *ratio in @[[NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)], [NSValue valueWithCGPoint:CGPointMake(2.0, 1.0)], [NSValue valueWithCGPoint:CGPointMake(1.0, 2.0)]]) + { + ORKFormStep *step = [[ORKFormStep alloc] initWithIdentifier:[NSString stringWithFormat:@"formStep%@",NSStringFromCGPoint(ratio.CGPointValue)] title:@"Image Choice" text:@"Testing image choices in a form layout."]; + + NSMutableArray *items = [NSMutableArray new]; + + for (NSNumber *dimension in @[@(360), @(60)]) + { + CGSize size1 = CGSizeMake(dimension.floatValue * ratio.CGPointValue.x, dimension.floatValue * ratio.CGPointValue.y); + CGSize size2 = CGSizeMake(dimension.floatValue * ratio.CGPointValue.y, dimension.floatValue * ratio.CGPointValue.x); + + ORKImageChoice *option1 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor redColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor redColor] size:size1 border:YES] + text:@"Red" value:@"red"]; + ORKImageChoice *option2 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor orangeColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor orangeColor] size:size1 border:YES] + text:nil value:@"orange"]; + ORKImageChoice *option3 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor yellowColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor yellowColor] size:size1 border:YES] + text:@"Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow" value:@"yellow"]; + ORKImageChoice *option4 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor greenColor] size:size2 border:NO] + selectedImage:[self imageWithColor:[UIColor greenColor] size:size2 border:YES] + text:@"Green" value:@"green"]; + ORKImageChoice *option5 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor blueColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor blueColor] size:size1 border:YES] + text:nil value:@"blue"]; + ORKImageChoice *option6 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor cyanColor] size:size2 border:NO] + selectedImage:[self imageWithColor:[UIColor cyanColor] size:size2 border:YES] + text:@"Cyan" value:@"cyanColor"]; + + + ORKFormItem *item1 = [[ORKFormItem alloc] initWithIdentifier:[@"item1" stringByAppendingFormat:@"%@",dimension] text:@"Pick a color" + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1] ]]; + [items addObject:item1]; + + ORKFormItem *item2 = [[ORKFormItem alloc] initWithIdentifier:[@"item2" stringByAppendingFormat:@"%@",dimension] text:@"Pick a color" + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2] ]]; + [items addObject:item2]; + + ORKFormItem *item3 = [[ORKFormItem alloc] initWithIdentifier:[@"item3" stringByAppendingFormat:@"%@",dimension] text:@"Pick a color" + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2, option3] ]]; + [items addObject:item3]; + + ORKFormItem *item6 = [[ORKFormItem alloc] initWithIdentifier:[@"item4" stringByAppendingFormat:@"%@",dimension] text:@"Pick a color" + answerFormat:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2, option3, option4, option5, option6] ]]; + [items addObject:item6]; + } + + [step setFormItems:items]; + [steps addObject:step]; + + for (NSNumber *dimension in @[@(360), @(60), @(20)]) { + CGSize size1 = CGSizeMake(dimension.floatValue * ratio.CGPointValue.x, dimension.floatValue * ratio.CGPointValue.y); + CGSize size2 = CGSizeMake(dimension.floatValue * ratio.CGPointValue.y, dimension.floatValue * ratio.CGPointValue.x); + + ORKImageChoice *option1 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor redColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor redColor] size:size1 border:YES] + text:@"Red\nRed\nRed\nRed" value:@"red"]; + ORKImageChoice *option2 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor orangeColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor orangeColor] size:size1 border:YES] + text:@"Orange" value:@"orange"]; + ORKImageChoice *option3 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor yellowColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor yellowColor] size:size1 border:YES] + text:@"Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow Yellow" value:@"yellow"]; + ORKImageChoice *option4 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor greenColor] size:size2 border:NO] + selectedImage:[self imageWithColor:[UIColor greenColor] size:size2 border:YES] + text:@"Green" value:@"green"]; + ORKImageChoice *option5 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor blueColor] size:size1 border:NO] + selectedImage:[self imageWithColor:[UIColor blueColor] size:size1 border:YES] + text:@"Blue" value:@"blue"]; + ORKImageChoice *option6 = [ORKImageChoice choiceWithNormalImage:[self imageWithColor:[UIColor cyanColor] size:size2 border:NO] + selectedImage:[self imageWithColor:[UIColor cyanColor] size:size2 border:YES] + text:@"Cyan" value:@"cyanColor"]; + + ORKQuestionStep *step1 = [ORKQuestionStep questionStepWithIdentifier:[NSString stringWithFormat:@"qid_color1_%@_%@", NSStringFromCGPoint(ratio.CGPointValue), dimension] + title:@"Image Choice" + question:@"Pick a color" + answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1] ]]; + [steps addObject:step1]; + + ORKQuestionStep *step2 = [ORKQuestionStep questionStepWithIdentifier:[NSString stringWithFormat:@"qid_color2_%@_%@", NSStringFromCGPoint(ratio.CGPointValue), dimension] + title:@"Image Choice" + question:@"Pick a color" + answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2] ]]; + [steps addObject:step2]; + + ORKQuestionStep *step3 = [ORKQuestionStep questionStepWithIdentifier:[NSString stringWithFormat:@"qid_color3_%@_%@", NSStringFromCGPoint(ratio.CGPointValue), dimension] + title:@"Image Choice" + question:@"Pick a color" + answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2, option3] ]]; + [steps addObject:step3]; + + ORKQuestionStep *step6 = [ORKQuestionStep questionStepWithIdentifier:[NSString stringWithFormat:@"qid_color6_%@_%@", NSStringFromCGPoint(ratio.CGPointValue), dimension] + title:@"Image Choice" + question:@"Pick a color" + answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:@[option1, option2, option3, option4, option5, option6]]]; + [steps addObject:step6]; + } + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"end"]; + step.title = @"Image Choices End"; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +- (id)makeLocationTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Location Survey"; + [steps addObject:step1]; + + // Location question with current location observing on + ORKQuestionStep *step2 = [[ORKQuestionStep alloc] initWithIdentifier:@"step2"]; + step2.title = @"Location Survey"; + step2.text = @"Where are you right now?"; + step2.answerFormat = [[ORKLocationAnswerFormat alloc] init]; + [steps addObject:step2]; + + // Location question with current location observing off + ORKQuestionStep *step3 = [[ORKQuestionStep alloc] initWithIdentifier:@"step3"]; + step3.title = @"Location Survey"; + step3.text = @"Where is your home?"; + ORKLocationAnswerFormat *locationAnswerFormat = [[ORKLocationAnswerFormat alloc] init]; + locationAnswerFormat.useCurrentLocation= NO; + step3.answerFormat = locationAnswerFormat; + [steps addObject:step3]; + + ORKCompletionStep *step4 = [[ORKCompletionStep alloc] initWithIdentifier:@"step4"]; + step4.title = @"Location Survey"; + step4.text = @"Survey Complete"; + [steps addObject:step4]; + + ORKOrderedTask *locationTask = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return locationTask; +} + +/* + This task is used to test various uses of discrete and continuous, horizontal and vertical valued sliders. + */ +- (id)makeScaleTaskWithIdentifier:(NSString *)identifier { + + NSMutableArray *steps = [NSMutableArray array]; + + { + /* + Continuous scale with two decimal places. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + maximumFractionDigits:2 + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale1" + title:@"Scale" + question:@"On a scale of 1 to 10, how much pain do you feel?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Discrete scale, no default. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:300 + minimumValue:100 + defaultValue:NSIntegerMax + step:50 + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale2" + title:@"Scale" + question:@"How much money do you need?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Discrete scale, with a default. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:5 + step:1 + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale3" + title:@"Scale" + question:@"On a scale of 1 to 10, how much pain do you feel?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Discrete scale, with a default that is not on a step boundary. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:300 + minimumValue:100 + defaultValue:174 + step:50 + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale4" + title:@"Scale" + question:@"How much money do you need?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical continuous scale with three decimal places and a default. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:8.725 + maximumFractionDigits:3 + vertical:YES + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale5" + title:@"Scale" + question:@"On a scale of 1 to 10, what is your mood?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical discrete scale, with a default on a step boundary. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:5 + step:1 + vertical:YES + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale6" + title:@"Scale" + question:@"How was your mood yesterday?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical discrete scale, with min and max labels. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + step:1 + vertical:YES + maximumValueDescription:@"A lot" + minimumValueDescription:@"Not at all"]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale7" + title:@"Scale" + question:@"On a scale of 1 to 10, what is your mood?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical continuous scale, with min and max labels. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:99 + maximumFractionDigits:2 + vertical:YES + maximumValueDescription:@"High value" + minimumValueDescription:@"Low value"]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale8" + title:@"Scale" + question:@"How would you measure your mood improvement?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical discrete scale, with min and max labels. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + step:1 + vertical:NO + maximumValueDescription:@"A lot" + minimumValueDescription:@"Not at all"]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale9" + title:@"Scale" + question:@"On a scale of 1 to 10, what is your mood?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical continuous scale, with min and max labels. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:99 + maximumFractionDigits:2 + vertical:NO + maximumValueDescription:@"High value" + minimumValueDescription:@"Low value"]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale10" + title:@"Scale" + question:@"How would you measure your mood improvement?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Vertical continuous scale with three decimal places, a default, and a format style. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:1.0 + minimumValue:0.0 + defaultValue:0.8725 + maximumFractionDigits:0 + vertical:YES + maximumValueDescription:nil + minimumValueDescription:nil]; + + scaleAnswerFormat.numberStyle = ORKNumberFormattingStylePercent; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale11" + title:@"Scale" + question:@"How much has your mood improved?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Continuous scale with images. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + maximumFractionDigits:2 + vertical:YES + maximumValueDescription:@"Hot" + minimumValueDescription:@"Warm"]; + + scaleAnswerFormat.hideSelectedValue = YES; + scaleAnswerFormat.minimumImage = [self imageWithColor:[UIColor yellowColor] size:CGSizeMake(30, 30) border:NO]; + scaleAnswerFormat.maximumImage = [self imageWithColor:[UIColor redColor] size:CGSizeMake(30, 30) border:NO]; + scaleAnswerFormat.minimumImage.accessibilityHint = @"A yellow colored square to represent warmness."; + scaleAnswerFormat.maximumImage.accessibilityHint = @"A red colored square to represent hot."; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale12" + title:@"Scale" + question:@"How warm do you feel?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Discrete scale with images. + */ + ORKScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + step:1 + vertical:NO + maximumValueDescription:nil + minimumValueDescription:nil]; + + scaleAnswerFormat.hideSelectedValue = YES; + scaleAnswerFormat.minimumImage = [self imageWithColor:[UIColor yellowColor] size:CGSizeMake(30, 30) border:NO]; + scaleAnswerFormat.maximumImage = [self imageWithColor:[UIColor redColor] size:CGSizeMake(30, 30) border:NO]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale13" + title:@"Scale" + question:@"How warm do you feel?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + /* + Horizontal text choice scale with visible selected value. + */ + ORKTextChoice *textChoice1 = [ORKTextChoice choiceWithText:@"Poor" value:@(1)]; + ORKTextChoice *textChoice2 = [ORKTextChoice choiceWithText:@"Fair" value:@(2)]; + ORKTextChoice *textChoice3 = [ORKTextChoice choiceWithText:@"Good" value:@(3)]; + ORKTextChoice *textChoice4 = [ORKTextChoice choiceWithText:@"Above Average" value:@(4)]; + ORKTextChoice *textChoice5 = [ORKTextChoice choiceWithText:@"Excellent" value:@(5)]; + + NSArray *textChoices = @[textChoice1, textChoice2, textChoice3, textChoice4, textChoice5]; + + ORKTextScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices + defaultIndex:3 + vertical:NO]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale14" + title:@"Scale" + question:@"How are you feeling today?" + answer:scaleAnswerFormat]; + + [steps addObject:step]; + } + + { + /* + Horizontal text choice scale with hidden selected value. + */ + ORKTextChoice *textChoice1 = [ORKTextChoice choiceWithText:@"Poor" value:@(1)]; + ORKTextChoice *textChoice2 = [ORKTextChoice choiceWithText:@"Fair" value:@(2)]; + ORKTextChoice *textChoice3 = [ORKTextChoice choiceWithText:@"Good" value:@(3)]; + ORKTextChoice *textChoice4 = [ORKTextChoice choiceWithText:@"Above Average" value:@(4)]; + ORKTextChoice *textChoice5 = [ORKTextChoice choiceWithText:@"Excellent" value:@(5)]; + + NSArray *textChoices = @[textChoice1, textChoice2, textChoice3, textChoice4, textChoice5]; + + ORKTextScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices + defaultIndex:3 + vertical:NO]; + + scaleAnswerFormat.hideSelectedValue = YES; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale15" + title:@"Scale" + question:@"How are you feeling today?" + answer:scaleAnswerFormat]; + + [steps addObject:step]; + } + + { + /* + Vertical text choice scale. Selected value isn't shown for type. + */ + ORKTextChoice *textChoice1 = [ORKTextChoice choiceWithText:@"Poor" value:@(1)]; + ORKTextChoice *textChoice2 = [ORKTextChoice choiceWithText:@"Fair" value:@(2)]; + ORKTextChoice *textChoice3 = [ORKTextChoice choiceWithText:@"Good" value:@(3)]; + ORKTextChoice *textChoice4 = [ORKTextChoice choiceWithText:@"Above Average" value:@(4)]; + ORKTextChoice *textChoice5 = [ORKTextChoice choiceWithText:@"Excellent" value:@(5)]; + + NSArray *textChoices = @[textChoice1, textChoice2, textChoice3, textChoice4, textChoice5]; + + ORKTextScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices + defaultIndex:NSIntegerMax + vertical:YES]; + + scaleAnswerFormat.hideSelectedValue = YES; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"scale16" + title:@"Scale" + question:@"How are you feeling today?" + answer:scaleAnswerFormat]; + + [steps addObject:step]; + } + + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; + +} + +- (id)makeScaleColorGradientTaskWithIdentifier:(NSString *)identifier { + ORKOrderedTask *task = (ORKOrderedTask *)[self makeScaleTaskWithIdentifier:identifier]; + + for (ORKQuestionStep *step in task.steps) { + if ([step isKindOfClass:[ORKQuestionStep class]]) { + ORKAnswerFormat *answerFormat = step.answerFormat; + if ([answerFormat respondsToSelector:@selector(setGradientColors:)]) { + [answerFormat performSelector:@selector(setGradientColors:) withObject:@[[UIColor redColor], + [UIColor greenColor], + [UIColor greenColor], + [UIColor yellowColor], + [UIColor yellowColor]]]; + [answerFormat performSelector:@selector(setGradientLocations:) withObject:@[@0.2, @0.2, @0.7, @0.7, @0.8]]; + } + } + } + return task; +} + +/* + The selection survey task is just a collection of various styles of survey questions. + */ +- (id)makeSelectionSurveyTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step.title = @"Selection Survey"; + [steps addObject:step]; + } + + { + /* + A numeric question requiring integer answers in a fixed range, with no default. + */ + ORKNumericAnswerFormat *format = [ORKNumericAnswerFormat integerAnswerFormatWithUnit:@"years"]; + format.minimum = @(0); + format.maximum = @(199); + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step2" + title:@"Selection Survey" + question:@"How old are you?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A boolean question. + */ + ORKBooleanAnswerFormat *format = [ORKBooleanAnswerFormat new]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step3" + title:@"Selection Survey" + question:@"Do you consent to a background check?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A custom boolean question. + */ + ORKBooleanAnswerFormat *format = [ORKAnswerFormat booleanAnswerFormatWithYesString:@"Agree" noString:@"Disagree"]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step4" + title:@"Selection Survey" + question:@"Do you agree to proceed to the background check questions?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A single-choice question presented in the tableview format. + */ + ORKTextChoiceAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices: + @[ + [ORKTextChoice choiceWithText:@"Less than seven" + value:@(7)], + [ORKTextChoice choiceWithText:@"Between seven and eight" + value:@(8)], + [ORKTextChoice choiceWithText:@"More than eight" + value:@(9)] + ]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step5" + title:@"Selection Survey" + question:@"How many hours did you sleep last night?" + answer:answerFormat]; + + step.optional = NO; + [steps addObject:step]; + } + + { + /* + A multiple-choice question presented in the tableview format. + */ + ORKTextChoiceAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices: + @[ + [ORKTextChoice choiceWithText:@"Cough" + value:@"cough"], + [ORKTextChoice choiceWithText:@"Fever" + value:@"fever"], + [ORKTextChoice choiceWithText:@"Headaches" + value:@"headache"], + [ORKTextChoice choiceWithText:@"None of the above" + detailText:nil + value:@"none" + exclusive:YES] + ]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step6" + title:@"Selection Survey" + question:@"Which symptoms do you have?" + answer:answerFormat]; + [steps addObject:step]; + } + + { + /* + A multiple-choice question with text choices that have detail text. + */ + ORKTextChoiceAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices: + @[ + [ORKTextChoice choiceWithText:@"Cough" + detailText:@"A cough and/or sore throat" + value:@"cough" + exclusive:NO], + [ORKTextChoice choiceWithText:@"Fever" + detailText:@"A 100F or higher fever or feeling feverish" + value:@"fever" + exclusive:NO], + [ORKTextChoice choiceWithText:@"Headaches" + detailText:@"Headaches and/or body aches" + value:@"headache" + exclusive:NO] + ]]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step7" + title:@"Selection Survey" + question:@"Which symptoms do you have?" + answer:answerFormat]; + + [steps addObject:step]; + } + + { + /* + A text question with the default multiple-line text entry. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step8" + title:@"Selection Survey" + question:@"How did you feel last night?" + answer:[ORKAnswerFormat textAnswerFormat]]; + [steps addObject:step]; + } + + { + /* + A text question with single-line text entry, with autocapitalization on + for words, and autocorrection, and spellchecking turned off. + */ + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormat]; + format.multipleLines = NO; + format.autocapitalizationType = UITextAutocapitalizationTypeWords; + format.autocorrectionType = UITextAutocorrectionTypeNo; + format.spellCheckingType = UITextSpellCheckingTypeNo; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step9" + title:@"Selection Survey" + question:@"What is your name?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A text question with a length limit. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step10" + title:@"Selection Survey" + question:@"How did you feel last night?" + answer:[ORKTextAnswerFormat textAnswerFormatWithMaximumLength:20]]; + [steps addObject:step]; + } + + { + /* + An email question with single-line text entry. + */ + ORKEmailAnswerFormat *format = [ORKAnswerFormat emailAnswerFormat]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step11" + title:@"Selection Survey" + question:@"What is your email?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A text question demos secureTextEntry feature + */ + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:10]; + format.secureTextEntry = YES; + format.multipleLines = NO; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step12" + title:@"Selection Survey" + question:@"What is your passcode?" + answer:format]; + step.placeholder = @"Tap your passcode here"; + [steps addObject:step]; + } + + { + /* + A text question with single-line text entry and a length limit. + */ + ORKTextAnswerFormat *format = [ORKAnswerFormat textAnswerFormatWithMaximumLength:20]; + format.multipleLines = NO; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step13" + title:@"Selection Survey" + question:@"What is your name?" + answer:format]; + [steps addObject:step]; + } + + { + /* + A single-select value-picker question. Rather than seeing the items in a tableview, + the user sees them in a picker wheel. This is suitable where the list + of items can be long, and the text describing the options can be kept short. + */ + ORKValuePickerAnswerFormat *answerFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices: + @[ + [ORKTextChoice choiceWithText:@"Cough" + value:@"cough"], + [ORKTextChoice choiceWithText:@"Fever" + value:@"fever"], + [ORKTextChoice choiceWithText:@"Headaches" + value:@"headache"] + ]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step14" + title:@"Selection Survey" + question:@"Select a symptom" + answer:answerFormat]; + + [steps addObject:step]; + } + + { + /* + A multiple component value-picker question. + */ + ORKValuePickerAnswerFormat *colorFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices: + @[ + [ORKTextChoice choiceWithText:@"Red" + value:@"red"], + [ORKTextChoice choiceWithText:@"Blue" + value:@"blue"], + [ORKTextChoice choiceWithText:@"Green" + value:@"green"] + ]]; + + ORKValuePickerAnswerFormat *animalFormat = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices: + @[ + [ORKTextChoice choiceWithText:@"Cat" + value:@"cat"], + [ORKTextChoice choiceWithText:@"Dog" + value:@"dog"], + [ORKTextChoice choiceWithText:@"Turtle" + value:@"turtle"] + ]]; + + ORKMultipleValuePickerAnswerFormat *answerFormat = [ORKAnswerFormat multipleValuePickerAnswerFormatWithValuePickers: + @[colorFormat, animalFormat]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step15" + title:@"Selection Survey" + question:@"Select a pet:" + answer:answerFormat]; + + [steps addObject:step]; + } + + + { + /* + A multiple component value-picker question. + */ + ORKValuePickerAnswerFormat *f1 = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices: + @[ + [ORKTextChoice choiceWithText:@"A" + value:@"A"], + [ORKTextChoice choiceWithText:@"B" + value:@"B"], + [ORKTextChoice choiceWithText:@"C" + value:@"C"] + ]]; + + ORKValuePickerAnswerFormat *f2 = [ORKAnswerFormat valuePickerAnswerFormatWithTextChoices: + @[ + [ORKTextChoice choiceWithText:@"0" + value:@0], + [ORKTextChoice choiceWithText:@"1" + value:@1], + [ORKTextChoice choiceWithText:@"2" + value:@2] + ]]; + + ORKMultipleValuePickerAnswerFormat *answerFormat = [[ORKMultipleValuePickerAnswerFormat alloc] initWithValuePickers:@[f1, f2] separator:@"-"]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step16" + title:@"Selection Survey" + question:@"Select a letter and number code:" + answer:answerFormat]; + + [steps addObject:step]; + } + + { + /* + A continuous slider question. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step17" + title:@"Selection Survey" + question:@"On a scale of 1 to 10, how much pain do you feel?" + answer:[[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:10 minimumValue:1 defaultValue:NSIntegerMax maximumFractionDigits:1]]; + [steps addObject:step]; + } + + { + /* + The same as the previous question, but now using a discrete slider. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step18" + title:@"Selection Survey" + question:@"On a scale of 1 to 10, how much pain do you feel?" + answer:[ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:NSIntegerMax + step:1 + vertical:NO + maximumValueDescription:@"High value" + minimumValueDescription:@"Low value"]]; + [steps addObject:step]; + } + + { + /* + A HealthKit answer format question for gender. + The default value is read from HealthKit when the step is being presented, + but the user's answer is not written back to HealthKit. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step19" + title:@"Selection Survey" + question:@"What is your gender" + answer:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]]]; + [steps addObject:step]; + } + + { + /* + A HealthKit answer format question for blood type. + The default value is read from HealthKit when the step is being presented, + but the user's answer is not written back to HealthKit. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step20" + title:@"Selection Survey" + question:@"What is your blood type?" + answer:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]]]; + [steps addObject:step]; + } + + { + /* + A HealthKit answer format question for date of birth. + The default value is read from HealthKit when the step is being presented, + but the user's answer is not written back to HealthKit. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step21" + title:@"Selection Survey" + question:@"What is your date of birth?" + answer:[ORKHealthKitCharacteristicTypeAnswerFormat answerFormatWithCharacteristicType:[HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth]]]; + [steps addObject:step]; + } + + { + /* + A HealthKit answer format question for weight. + The default value is read from HealthKit when the step is being presented, + but the user's answer is not written back to HealthKit. + */ + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step22" + title:@"Selection Survey" + question:@"How much do you weigh?" + answer:[ORKHealthKitQuantityTypeAnswerFormat answerFormatWithQuantityType:[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass] + unit:nil + style:ORKNumericAnswerStyleDecimal]]; + [steps addObject:step]; + } + + { + /* + A multiple choice question where the items are mis-formatted. + This question is used for verifying correct layout of the table view + cells when the content is mixed or very long. + */ + ORKTextChoiceAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices: + @[ + [ORKTextChoice choiceWithText:@"Cough, A cough and/or sore throat, A cough and/or sore throat" + detailText:@"A cough and/or sore throat, A cough and/or sore throat, A cough and/or sore throat" + value:@"cough" + exclusive:NO], + [ORKTextChoice choiceWithText:@"Fever, A 100F or higher fever or feeling feverish" + detailText:nil + value:@"fever" + exclusive:NO], + [ORKTextChoice choiceWithText:@"" + detailText:@"Headaches, Headaches and/or body aches" + value:@"headache" + exclusive:NO] + ]]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step23" + title:@"Selection Survey" + question:@"(Misused) Which symptoms do you have?" + answer:answerFormat]; + [steps addObject:step]; + } + + { + ORKCompletionStep *step = [[ORKCompletionStep alloc] initWithIdentifier:@"completion"]; + step.title = @"Survey Complete"; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +- (id)makeVideoCaptureTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + /* + If implementing an video capture task like this one, remember that people will + take your instructions literally. So, be cautious. Make sure your template image + is high contrast and very visible against a variety of backgrounds. + */ + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"begin"]; + step.title = @"Hands"; + step.image = [[UIImage imageNamed:@"hands_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"In this step we will capture 5 second videos of both of your hands"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"right1"]; + step.title = @"Right Hand"; + step.image = [[UIImage imageNamed:@"right_hand_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Let's start by capturing a video of your right hand"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"right2"]; + step.title = @"Right Hand"; + step.image = [[UIImage imageNamed:@"right_hand_outline"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Align your right hand with the on-screen outline and record the video. Be sure to place your hand over a contrasting background. You can re-capture the video as many times as you need."; + [steps addObject:step]; + } + + { + ORKVideoCaptureStep *step = [[ORKVideoCaptureStep alloc] initWithIdentifier:@"right3"]; + step.templateImage = [UIImage imageNamed:@"right_hand_outline_big"]; + step.templateImageInsets = UIEdgeInsetsMake(0.05, 0.05, 0.05, 0.05); + step.duration = @5.0; + step.accessibilityInstructions = @"Extend your right hand, palm side down, one foot in front of your device. Tap the Start Recording button, or two-finger double tap the preview to capture the video"; + step.accessibilityHint = @"Records the video visible in the preview"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"left1"]; + step.title = @"Left Hand"; + step.image = [[UIImage imageNamed:@"left_hand_solid"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Now let's capture a video of your left hand"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"left2"]; + step.title = @"Left Hand"; + step.image = [[UIImage imageNamed:@"left_hand_outline"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + step.detailText = @"Align your left hand with the on-screen outline and record the video. Be sure to place your hand over a contrasting background. You can re-capture the video as many times as you need."; + [steps addObject:step]; + } + + { + ORKVideoCaptureStep *step = [[ORKVideoCaptureStep alloc] initWithIdentifier:@"left3"]; + step.templateImage = [UIImage imageNamed:@"left_hand_outline_big"]; + step.templateImageInsets = UIEdgeInsetsMake(0.05, 0.05, 0.05, 0.05); + step.duration = @5.0; + step.accessibilityInstructions = @"Extend your left hand, palm side down, one foot in front of your device. Tap the Start Recording button, or two-finger double tap the preview to capture the video"; + step.accessibilityHint = @"Records the video visible in the preview"; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"end"]; + step.title = @"Complete"; + step.detailText = @"Hand video capture complete"; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.h new file mode 100755 index 0000000..c2de574 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (TaskCustomization) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.m new file mode 100755 index 0000000..d18995a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskCustomization.m @@ -0,0 +1,392 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+TaskCustomization.h" + +#import "DragonPokerStep.h" +#import "DynamicTask.h" + +@import ResearchKit; + + +@implementation TaskFactory (TaskCustomization) + +- (id)makeCustomViewControllerTaskWithIdentifier:(NSString *)identifier { + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Custom VC"; + step1.text = @"The next step uses a custom subclass of an ORKFormStepViewController."; + + DragonPokerStep *dragonStep = [[DragonPokerStep alloc] initWithIdentifier:@"dragonStep"]; + dragonStep.title = @"Custom VC"; + + ORKStep *lastStep = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + lastStep.title = @"Complete"; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step1, dragonStep, lastStep]]; +} + +- (id)makeDynamicTaskWithIdentifier:(NSString *)identifier { + return [DynamicTask new]; +} + +/* + This demonstrates a task where if the user enters a value that is too low for + the first question (say, under 18), the task view controller delegate API can + be used to reject the answer and prevent forward navigation. + + See the implementation of the task view controller delegate methods for specific + handling of this task. + */ +- (id)makeInterruptibleTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKNumericAnswerFormat *format = [ORKNumericAnswerFormat integerAnswerFormatWithUnit:@"years"]; + format.minimum = @(5); + format.maximum = @(90); + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step1" + title:@"Interruptible" + question:@"How old are you?" + answer:format]; + [steps addObject:step]; + } + + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"step2" + title:@"Interruptible" + question:@"How much did you pay for your car?" + answer:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:@"USD"]]; + /* + Test interrupting navigation from the task view controller delegate. + + This is an example of preventing a user from proceeding if they don't + enter a valid answer. + */ + step.shouldPresentStepBlock = ^BOOL(ORKTaskViewController *taskViewController, ORKStep *step) { + BOOL shouldPresentStep = YES; + ORKQuestionResult *questionResult = (ORKQuestionResult *)[[[taskViewController result] stepResultForStepIdentifier:@"step1"] firstResult]; + if (questionResult == nil || [(NSNumber *)questionResult.answer integerValue] < 18) { + UIAlertController *alertViewController = + [UIAlertController alertControllerWithTitle:@"Warning" + message:@"You can't participate if you are under 18." + preferredStyle:UIAlertControllerStyleAlert]; + + + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"OK" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + [alertViewController dismissViewControllerAnimated:YES completion:nil]; + }]; + [alertViewController addAction:okAction]; + + [taskViewController presentViewController:alertViewController animated:NO completion:nil]; + shouldPresentStep = NO; + } + return shouldPresentStep; + }; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step3"]; + step.title = @"Thank you for completing this task."; + [steps addObject:step]; + } + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return task; +} + +- (id)makeNavigableOrderedLoopTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + ORKAnswerFormat *answerFormat = nil; + ORKStep *step = nil; + NSArray *textChoices = nil; + ORKQuestionStep *questionStep = nil; + + // Intro step + step = [[ORKInstructionStep alloc] initWithIdentifier:@"introStep"]; + step.title = @"Ordered Loop"; + step.text = @"This task demonstrates an skippable step and an optional loop within a navigable ordered task"; + [steps addObject:step]; + + // Skippable step + answerFormat = [ORKAnswerFormat booleanAnswerFormat]; + questionStep = [ORKQuestionStep questionStepWithIdentifier:@"skipNextStep" title:@"Ordered Loop" question:@"Do you want to skip the next step?" answer:answerFormat]; + questionStep.optional = NO; + [steps addObject:questionStep]; + + step = [[ORKInstructionStep alloc] initWithIdentifier:@"skippableStep"]; + step.title = @"Optional Skip"; + step.text = @"You should only see this step if you answered the previous question with 'No'"; + [steps addObject:step]; + + // Loop target step + step = [[ORKInstructionStep alloc] initWithIdentifier:@"loopAStep"]; + step.title = @"Optional return"; + step.text = @"You'll optionally return to this step"; + [steps addObject:step]; + + // Branching paths + textChoices = + @[ + [ORKTextChoice choiceWithText:@"Scale" value:@"scale"], + [ORKTextChoice choiceWithText:@"Text Choice" value:@"textchoice"] + ]; + + answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + questionStep = [ORKQuestionStep questionStepWithIdentifier:@"branchingStep" title:@"Ordered Loop" question:@"Which kind of question do you prefer?" answer:answerFormat]; + questionStep.optional = NO; + [steps addObject:questionStep]; + + // Scale question step + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:8.725 + maximumFractionDigits:3 + vertical:YES + maximumValueDescription:nil + minimumValueDescription:nil]; + + step = [ORKQuestionStep questionStepWithIdentifier:@"scaleStep" + title:@"Ordered Loop" + question:@"On a scale of 1 to 10, what is your mood?" + answer:scaleAnswerFormat]; + [steps addObject:step]; + + // Text choice question step + textChoices = + @[ + [ORKTextChoice choiceWithText:@"Good" value:@"good"], + [ORKTextChoice choiceWithText:@"Bad" value:@"bad"] + ]; + + answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice + textChoices:textChoices]; + + questionStep = [ORKQuestionStep questionStepWithIdentifier:@"textChoiceStep" title:@"Ordered Loop" question:@"How is your mood?" answer:answerFormat]; + questionStep.optional = NO; + [steps addObject:questionStep]; + + // Loop conditional step + answerFormat = [ORKAnswerFormat booleanAnswerFormat]; + step = [ORKQuestionStep questionStepWithIdentifier:@"loopBStep" title:@"Ordered Loop" question:@"Do you want to repeat the survey?" answer:answerFormat]; + step.optional = NO; + [steps addObject:step]; + + step = [[ORKInstructionStep alloc] initWithIdentifier:@"endStep"]; + step.title = @"Complete"; + step.text = @"You have finished the task"; + [steps addObject:step]; + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier + steps:steps]; + + // Build navigation rules + ORKResultSelector *resultSelector = nil; + ORKPredicateStepNavigationRule *predicateRule = nil; + ORKDirectStepNavigationRule *directRule = nil; + ORKPredicateSkipStepNavigationRule *predicateSkipRule = nil; + + // skippable step + resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"skipNextStep"]; + NSPredicate *predicateSkipStep = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:YES]; + predicateSkipRule = [[ORKPredicateSkipStepNavigationRule alloc] initWithResultPredicate:predicateSkipStep]; + [task setSkipNavigationRule:predicateSkipRule forStepIdentifier:@"skippableStep"]; + + // From the branching step, go to either scaleStep or textChoiceStep + resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"branchingStep"]; + NSPredicate *predicateAnswerTypeScale = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector + expectedAnswerValue:@"scale"]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicateAnswerTypeScale ] + destinationStepIdentifiers:@[ @"scaleStep" ] + defaultStepIdentifier:@"textChoiceStep"]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"branchingStep"]; + + // From the loopB step, return to loopA if user chooses so + resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"loopBStep"]; + NSPredicate *predicateLoopYes = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector + expectedAnswer:YES]; + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicateLoopYes ] + destinationStepIdentifiers:@[ @"loopAStep" ] ]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"loopBStep"]; + + // scaleStep to loopB direct navigation rule + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"loopBStep"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"scaleStep"]; + + return task; +} + +- (id)makeStepWillAppearTaskWithIdentifier:(NSString *)identifier { + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Will Appear"; + step1.text = @"This task will test several usages of the delegate's 'taskViewController:stepViewControllerWillAppear:\' method."; + + /* + Test adding a custom view to a view controller for an active step, without + subclassing. + + This is possible, but not recommended. A better choice would be to create + a custom active step subclass and a matching active step view controller + subclass, so you completely own the view controller and its appearance. + */ + ORKActiveStep *step2 = [[ORKActiveStep alloc] initWithIdentifier:@"step2"]; + step2.title = @"Will Appear"; + step2.text = @"Custom View On Active Step"; + step2.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + UIView *customView = [UIView new]; + customView.backgroundColor = [UIColor cyanColor]; + + // Have the custom view request the space it needs. + // A little tricky because we need to let it size to fit if there's not enough space. + customView.translatesAutoresizingMaskIntoConstraints = NO; + NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[c(==160)]" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"c":customView}]; + for (NSLayoutConstraint *constraint in verticalConstraints) { + constraint.priority = UILayoutPriorityFittingSizeLevel; + } + [NSLayoutConstraint activateConstraints:verticalConstraints]; + [NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[c(==280)]" + options:(NSLayoutFormatOptions)0 + metrics:nil + views:@{@"c":customView}]]; + + [(ORKActiveStepViewController *)stepViewController setCustomView:customView]; + + // Set custom button on navigation bar + stepViewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Custom button" + style:UIBarButtonItemStylePlain + target:nil + action:nil]; + }; + + /* + Customize the continue and learn more buttons. + */ + ORKInstructionStep *step3 = [[ORKInstructionStep alloc] initWithIdentifier:@"step3"]; + step3.title = @"Will Appear"; + step3.text = @"Custom Next and Learn More Buttons"; + step3.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + stepViewController.continueButtonTitle = @"Next Customized Step"; + stepViewController.learnMoreButtonTitle = @"Learn more about this customized task"; + }; + + /* + Customize the back and cancel buttons. + */ + ORKInstructionStep *step4 = [[ORKInstructionStep alloc] initWithIdentifier:@"step4"]; + step4.title = @"Will Appear"; + step4.text = @"Custom Back and Cancel Buttons"; + step4.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + stepViewController.backButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Backwards" + style:UIBarButtonItemStylePlain + target:stepViewController.backButtonItem.target + action:stepViewController.backButtonItem.action]; + stepViewController.cancelButtonItem.title = @"Abort"; + }; + + /* + Customize the navigation item title. + */ + ORKInstructionStep *step5 = [[ORKInstructionStep alloc] initWithIdentifier:@"step5"]; + step5.title = @"Will Appear"; + step5.text = @"Custom Navigation Item Title"; + step5.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + taskViewController.showsProgressInNavigationBar = NO; + stepViewController.navigationItem.title = @"Custom title"; + }; + step5.stepViewControllerWillDisappearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController, + ORKStepViewControllerNavigationDirection navigationDirection) { + taskViewController.showsProgressInNavigationBar = YES; + }; + + /* + Customize the navigation item title view. + */ + ORKInstructionStep *step6 = [[ORKInstructionStep alloc] initWithIdentifier:@"step6"]; + step6.title = @"Will Appear"; + step6.text = @"Custom Navigation Item Title View"; + step6.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + taskViewController.showsProgressInNavigationBar = NO; + NSMutableArray *items = [[NSMutableArray alloc] init]; + [items addObject:@"Item1"]; + [items addObject:@"Item2"]; + [items addObject:@"Item3"]; + stepViewController.navigationItem.titleView = [[UISegmentedControl alloc] initWithItems:items]; + }; + step6.stepViewControllerWillDisappearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController, + ORKStepViewControllerNavigationDirection navigationDirection) { + taskViewController.showsProgressInNavigationBar = YES; + }; + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier + steps:@[step1, step2, step3, step4, step5, step6]]; + return task; +} + +- (id)makeStepWillDisappearTaskWithIdentifier:(NSString *)identifier { + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Will Disappear"; + step1.text = @"The tint color of the task view controller will be changed to magenta in the delegate's 'taskViewController:stepViewControllerWillDisappear:navigationDirection:' method after this step."; + + step1.stepViewControllerWillDisappearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController, + ORKStepViewControllerNavigationDirection navigationDirection) { + taskViewController.view.tintColor = [UIColor magentaColor]; + }; + + ORKCompletionStep *step2 = [[ORKCompletionStep alloc] initWithIdentifier:@"step2"]; + step2.title = @"Survey Complete"; + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step1, step2]]; + return task; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.h new file mode 100755 index 0000000..4999d64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (TaskReview) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.m new file mode 100755 index 0000000..402439e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+TaskReview.m @@ -0,0 +1,137 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+TaskReview.h" + +@import ResearchKit; + + +@implementation TaskFactory (TaskReview) + +- (NSArray *)stepsForReviewTasks { + // ORKInstructionStep + ORKInstructionStep *instructionStep = [[ORKInstructionStep alloc] initWithIdentifier:@"instructionStep"]; + instructionStep.title = @"Review Task"; + instructionStep.text = @"The task demonstrates the usage of ORKReviewStep within a task"; + + NSMutableArray *textChoices = [[NSMutableArray alloc] init]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Good" detailText:@"" value:[NSNumber numberWithInt:0] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Average" detailText:@"" value:[NSNumber numberWithInt:1] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Poor" detailText:@"" value:[NSNumber numberWithInt:2] exclusive:NO]]; + ORKQuestionStep *step1 = [ORKQuestionStep questionStepWithIdentifier:@"step1" title:@"Review Task" question:@"How do you feel today?" answer:[ORKAnswerFormat valuePickerAnswerFormatWithTextChoices:textChoices]]; + + // ORKImageChoiceAnswerFormat + NSMutableArray *imageChoices = [[NSMutableArray alloc] init]; + [imageChoices addObject:[[ORKImageChoice alloc] initWithNormalImage:[UIImage imageNamed:@"left_hand_outline"] selectedImage:[UIImage imageNamed:@"left_hand_solid"] text:@"Left hand" value:[NSNumber numberWithInt:1]]]; + [imageChoices addObject:[[ORKImageChoice alloc] initWithNormalImage:[UIImage imageNamed:@"right_hand_outline"] selectedImage:[UIImage imageNamed:@"right_hand_solid"] text:@"Right hand" value:[NSNumber numberWithInt:0]]]; + ORKQuestionStep *step2 = [ORKQuestionStep questionStepWithIdentifier:@"step2" title:@"Review Task" question: @"Which hand was injured?" answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:imageChoices]]; + + // ORKTextChoiceAnswerFormat + ORKQuestionStep *step3 = [ORKQuestionStep questionStepWithIdentifier:@"step3" title:@"Review Task" question: @"How do you feel today?" answer:[ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:textChoices]]; + + // ORKBooleanAnswerFormat + ORKQuestionStep *step4 = [ORKQuestionStep questionStepWithIdentifier:@"step4" title:@"Review Task" question:@"Are you at least 18 years old?" answer:[ORKAnswerFormat booleanAnswerFormat]]; + + // ORKTimeOfDayAnswerFormat + ORKQuestionStep *step5 = [ORKQuestionStep questionStepWithIdentifier:@"step5" title:@"Review Task" question:@"When did you wake up today?" answer:[ORKAnswerFormat timeOfDayAnswerFormat]]; + + // ORKDateAnswerFormat + ORKQuestionStep *step6 = [ORKQuestionStep questionStepWithIdentifier:@"step6" title:@"Review Task" question:@"When is your birthday?" answer:[ORKAnswerFormat dateAnswerFormat]]; + + // ORKFormStep + ORKFormStep *formStep = [[ORKFormStep alloc] initWithIdentifier:@"formStep" title:@"Survey" text:@"Please answer the following set of questions"]; + ORKFormItem *formItem1 = [[ORKFormItem alloc] initWithIdentifier:@"formItem1" text:@"How do you feel today?" answerFormat:[ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:textChoices]]; + ORKFormItem *formItem2 = [[ORKFormItem alloc] initWithIdentifier:@"formItem2" text:@"Are you pregnant?" answerFormat:[ORKAnswerFormat booleanAnswerFormat]]; + formStep.formItems = @[formItem1, formItem2]; + + // ORKReviewStep + ORKReviewStep *reviewStep = [ORKReviewStep embeddedReviewStepWithIdentifier:@"embeddedReviewStep"]; + reviewStep.title = @"Review"; + reviewStep.text = @"Review your answers"; + + // ORKNumericAnswerFormat + ORKQuestionStep *step7 = [ORKQuestionStep questionStepWithIdentifier:@"step7" title:@"Review Task" question:@"How many children do you have?" answer:[ORKAnswerFormat integerAnswerFormatWithUnit:@"children"]]; + + // ORKScaleAnswerFormat + ORKQuestionStep *step8 = [ORKQuestionStep questionStepWithIdentifier:@"step8" title:@"Review Task" question:@"On a scale from 1 to 10: How do you feel today?" answer:[ORKAnswerFormat scaleAnswerFormatWithMaximumValue:10 minimumValue:1 defaultValue:6 step:1 vertical:NO maximumValueDescription:@"Excellent" minimumValueDescription:@"Poor"]]; + + // ORKContinousScaleAnswerFormat + ORKQuestionStep *step9 = [ORKQuestionStep questionStepWithIdentifier:@"step9" title:@"Review Task" question:@"On a scale from 1 to 10: How do you feel today?" answer:[ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 minimumValue:1 defaultValue:6 maximumFractionDigits:2 vertical:NO maximumValueDescription:@"Excellent" minimumValueDescription:@"Poor"]]; + + // ORKTextScaleAnswerFormat + ORKQuestionStep *step10 = [ORKQuestionStep questionStepWithIdentifier:@"step10" title:@"Review Task" question:@"How do you feel today?" answer:[ORKAnswerFormat textScaleAnswerFormatWithTextChoices:textChoices defaultIndex:0 vertical:NO]]; + + // ORKTextAnswerFormat + ORKQuestionStep *step11 = [ORKQuestionStep questionStepWithIdentifier:@"step11" title:@"Review Task" question:@"What books do you like best?" answer:[ORKAnswerFormat textAnswerFormat]]; + + // ORKEmailAnswerFormat + ORKQuestionStep *step12 = [ORKQuestionStep questionStepWithIdentifier:@"step12" title:@"Review Task" question:@"What is your e-mail address?" answer:[ORKAnswerFormat emailAnswerFormat]]; + + // ORKTimeIntervalAnswerFormat + ORKQuestionStep *step13 = [ORKQuestionStep questionStepWithIdentifier:@"step13" title:@"Review Task" question:@"How many hours did you sleep last night?" answer:[ORKAnswerFormat timeIntervalAnswerFormat]]; + + // ORKHeightAnswerFormat + ORKQuestionStep *step14 = [ORKQuestionStep questionStepWithIdentifier:@"step14" title:@"Review Task" question:@"What is your height?" answer:[ORKAnswerFormat heightAnswerFormat]]; + + // ORKWeightAnswerFormat + ORKQuestionStep *step15 = [ORKQuestionStep questionStepWithIdentifier:@"step15" title:@"Review Task" question:@"What is your weight?" answer:[ORKAnswerFormat weightAnswerFormat]]; + + // ORKLocationAnswerFormat + ORKQuestionStep *step16 = [ORKQuestionStep questionStepWithIdentifier:@"step16" title:@"Review Task" question:@"Where do you live?" answer:[ORKAnswerFormat locationAnswerFormat]]; + + return @[instructionStep, step1, step2, step3, step4, step5, step6, formStep, reviewStep, step7, step8, step9, step10, step11, step12, step13, step14, step15, step16]; +} + +- (id)makeEmbeddedReviewTaskWithIdentifier:(NSString *)identifier { + // ORKValuePickerAnswerFormat + NSMutableArray *steps = [[NSMutableArray alloc] initWithArray:[self stepsForReviewTasks]]; + ORKReviewStep *reviewStep = [ORKReviewStep embeddedReviewStepWithIdentifier:@"reviewStep"]; + reviewStep.title = @"Review"; + reviewStep.text = @"Review your answers"; + [steps addObject:reviewStep]; + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + task.isEmbeddedReviewTask = YES; + return task; +} + +- (id)makeStandaloneReviewTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] initWithArray:[self stepsForReviewTasks]]; + ORKReviewStep *reviewStep = [ORKReviewStep standaloneReviewStepWithIdentifier:@"reviewStep" steps:steps resultSource:self.embeddedReviewTaskResult]; + reviewStep.title = @"Review"; + reviewStep.text = @"Review your answers from your last survey"; + reviewStep.excludeInstructionSteps = YES; + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[reviewStep]]; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.h new file mode 100755 index 0000000..6e629a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.h @@ -0,0 +1,40 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + + +@interface TaskFactory (UtilitySteps) + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.m new file mode 100755 index 0000000..9839a33 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory+UtilitySteps.m @@ -0,0 +1,703 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory+UtilitySteps.h" + +@import ResearchKit; + + +@implementation TaskFactory (UtilitySteps) + +- (id)makeAuxiliaryImageStepTaskWithIdentifier:(NSString *)identifier { + + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"step"]; + step.title = @"Title"; + step.text = @"This is description text."; + step.detailText = @"This is detail text."; + step.image = [UIImage imageNamed:@"tremortest3a" inBundle:[NSBundle bundleForClass:[ORKOrderedTask class]] compatibleWithTraitCollection:nil]; + step.auxiliaryImage = [UIImage imageNamed:@"tremortest3b" inBundle:[NSBundle bundleForClass:[ORKOrderedTask class]] compatibleWithTraitCollection:nil]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step]]; +} + +- (id)makeCompletionStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKCompletionStep *step1 = [[ORKCompletionStep alloc] initWithIdentifier:@"completionStepWithDoneButton"]; + step1.title = @"Completion Step"; + step1.text = @"Example of a step view controller with the continue button in the standard location below the checkmark."; + step1.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + ((ORKCompletionStepViewController*)stepViewController).shouldShowContinueButton = YES; + }; + [steps addObject:step1]; + + ORKCompletionStep *stepLast = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + stepLast.title = @"Completion Step"; + stepLast.text = @"Example of an step view controller with the continue button in the upper right."; + [steps addObject:stepLast]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +- (id)makeFootnoteStepTaskWithIdentifier:(NSString *)identifier { + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Footnote example"; + step1.text = @"This is an instruction step with a footnote."; + step1.footnote = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dignissim tortor eget orci placerat, eu congue diam tempor. In hac."; + + ORKInstructionStep *step2 = [[ORKInstructionStep alloc] initWithIdentifier:@"step2"]; + step2.title = @"No Footnote"; + step2.text = @"This is an instruction step with an image and NO footnote."; + step2.image = [UIImage imageNamed:@"image_example"]; + + ORKInstructionStep *step3 = [[ORKInstructionStep alloc] initWithIdentifier:@"step3"]; + step3.title = @"Image and Footnote"; + step3.text = @"This is an instruction step with an image and a footnote."; + step3.image = [UIImage imageNamed:@"image_example"]; + step3.footnote = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dignissim tortor eget orci placerat, eu congue diam tempor. In hac."; + + ORKFormStep *step4 = [[ORKFormStep alloc] initWithIdentifier:@"step4" title:@"Form Step" text:@"This is a form step with a skip button."]; + step4.formItems = @[[[ORKFormItem alloc] initWithIdentifier:@"formItem1" + text:@"Are you over 18 years of age?" + answerFormat:[ORKAnswerFormat booleanAnswerFormat]]]; + step4.optional = YES; + + ORKFormStep *step5 = [[ORKFormStep alloc] initWithIdentifier:@"step5" title:@"Footnote example" text:@"This is a form step with a skip button and footnote."]; + step5.formItems = @[[[ORKFormItem alloc] initWithIdentifier:@"formItem1" + text:@"Are you over 18 years of age?" + answerFormat:[ORKAnswerFormat booleanAnswerFormat]]]; + step5.optional = YES; + step5.footnote = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dignissim tortor eget orci placerat, eu congue diam tempor. In hac."; + + ORKCompletionStep *lastStep = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + lastStep.title = @"Last step."; + lastStep.text = @"This is a completion step with a footnote."; + lastStep.footnote = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce dignissim tortor eget orci placerat, eu congue diam tempor. In hac."; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step1, step2, step3, step4, step5, lastStep]]; +} + +- (id)makeIconImageStepTaskWithIdentifier:(NSString *)identifier { + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Title"; + step1.text = @"This is an example of a step with an icon image."; + + NSDictionary *infoPlist = [[NSBundle mainBundle] infoDictionary]; + NSString *icon = [[infoPlist valueForKeyPath:@"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles"] lastObject]; + step1.iconImage = [UIImage imageNamed:icon]; + + ORKInstructionStep *step2 = [[ORKInstructionStep alloc] initWithIdentifier:@"step2"]; + step2.text = @"This is an example of a step with an icon image and no title."; + step2.iconImage = [UIImage imageNamed:icon]; + + ORKInstructionStep *step3 = [[ORKInstructionStep alloc] initWithIdentifier:@"step3"]; + step3.title = @"Title"; + step3.text = @"This is an example of a step with an icon image that is very big."; + step3.iconImage = [UIImage imageNamed:@"Poppies"]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:@[step1, step2, step3]]; +} + + +- (id)makePageStepTaskWithIdentifier:(NSString *)identifier { + + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Page Step"; + step1.text = @"Example of an ORKPageStep"; + [steps addObject:step1]; + + NSMutableArray *textChoices = [[NSMutableArray alloc] init]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Good" detailText:@"" value:[NSNumber numberWithInt:0] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Average" detailText:@"" value:[NSNumber numberWithInt:1] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Poor" detailText:@"" value:[NSNumber numberWithInt:2] exclusive:NO]]; + ORKAnswerFormat *answerFormat = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:textChoices]; + ORKFormItem *formItem = [[ORKFormItem alloc] initWithIdentifier:@"choice" text:nil answerFormat:answerFormat]; + ORKFormStep *groupStep1 = [[ORKFormStep alloc] initWithIdentifier:@"step1" title:nil text:@"How do you feel today?"]; + groupStep1.formItems = @[formItem]; + + NSMutableArray *imageChoices = [[NSMutableArray alloc] init]; + [imageChoices addObject:[[ORKImageChoice alloc] initWithNormalImage:[UIImage imageNamed:@"left_hand_outline"] selectedImage:[UIImage imageNamed:@"left_hand_solid"] text:@"Left hand" value:[NSNumber numberWithInt:1]]]; + [imageChoices addObject:[[ORKImageChoice alloc] initWithNormalImage:[UIImage imageNamed:@"right_hand_outline"] selectedImage:[UIImage imageNamed:@"right_hand_solid"] text:@"Right hand" value:[NSNumber numberWithInt:0]]]; + ORKQuestionStep *groupStep2 = [ORKQuestionStep questionStepWithIdentifier:@"step2" title:nil question:@"Which hand was injured?" answer:[ORKAnswerFormat choiceAnswerFormatWithImageChoices:imageChoices]]; + + ORKSignatureStep *groupStep3 = [[ORKSignatureStep alloc] initWithIdentifier:@"step3"]; + + ORKStep *groupStep4 = [[ORKConsentReviewStep alloc] initWithIdentifier:@"groupStep4" signature:nil inDocument:[self buildConsentDocument]]; + + ORKPageStep *pageStep = [[ORKPageStep alloc] initWithIdentifier:@"pageStep" steps:@[groupStep1, groupStep2, groupStep3, groupStep4]]; + pageStep.title = @"Page Step"; + [steps addObject:pageStep]; + + ORKOrderedTask *audioTask = [ORKOrderedTask audioTaskWithIdentifier:@"audioTask" + intendedUseDescription:nil + speechInstruction:nil + shortSpeechInstruction:nil + duration:10 + recordingSettings:nil + checkAudioLevel:YES + options: + ORKPredefinedTaskOptionExcludeInstructions | + ORKPredefinedTaskOptionExcludeConclusion]; + ORKPageStep *audioStep = [[ORKNavigablePageStep alloc] initWithIdentifier:@"audioStep" pageTask:audioTask]; + audioStep.title = @"Page Step"; + [steps addObject:audioStep]; + + ORKCompletionStep *stepLast = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + stepLast.title = @"Task Complete"; + [steps addObject:stepLast]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +/* + This is intended to test the predicate functions and APIs + */ +- (id)makePredicateTestsTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [NSMutableArray new]; + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"introStep"]; + step.title = @"Predicate Tests"; + [steps addObject:step]; + } + + // Test Expected Boolean value + { + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question1" title:@"Predicate Tests" question:@"Pass the Boolean question?" answer:[ORKAnswerFormat booleanAnswerFormat]]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question1Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You failed the Boolean question."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question1Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You passed the Boolean question."; + [steps addObject:step]; + } + + // Test expected Single Choice + { + NSMutableArray *textChoices = [[NSMutableArray alloc] init]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Choose Yes" detailText:@"" value:[NSNumber numberWithInt:0] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Choose No" detailText:@"" value:[NSNumber numberWithInt:1] exclusive:NO]]; + ORKAnswerFormat *answer = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:textChoices]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question2" title:@"Predicate Tests" question:@"Pass the single choice question?" answer:answer]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question2Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You failed the single choice question."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question2Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You passed the single choice question."; + [steps addObject:step]; + } + + // Test expected multiple choices + { + NSMutableArray *textChoices = [[NSMutableArray alloc] init]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Cat" detailText:@"" value:[NSNumber numberWithInt:0] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Dog" detailText:@"" value:[NSNumber numberWithInt:1] exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Rock" detailText:@"" value:[NSNumber numberWithInt:2] exclusive:NO]]; + ORKAnswerFormat *answer = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices:textChoices]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question3" title:@"Predicate Tests" question:@"Select all the animals" answer:answer]; + + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question3Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You failed the multiple choice animals question."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question3Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You passed the multiple choice animals question."; + [steps addObject:step]; + } + + // Test expected multiple choices + { + NSMutableArray *textChoices = [[NSMutableArray alloc] init]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Cat" detailText:@"" value:@"Cat" exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Catheter" detailText:@"" value:@"Catheter" exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Cathedral" detailText:@"" value:@"Cathedral" exclusive:NO]]; + [textChoices addObject:[[ORKTextChoice alloc] initWithText:@"Dog" detailText:@"" value:@"Dog" exclusive:NO]]; + ORKAnswerFormat *answer = [ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleSingleChoice textChoices:textChoices]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question4" title:@"Predicate Tests" question:@"Choose any word containing the word 'Cat'" answer:answer]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question4Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You failed the 'Cat' pattern match question."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question4Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You passed the 'Cat' pattern match question."; + [steps addObject:step]; + } + + // Test expected text + { + ORKAnswerFormat *answer = [ORKAnswerFormat textAnswerFormat]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question5" title:@"Predicate Tests" question:@"Write the word 'Dog'" answer:answer]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question5Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You didn't write 'Dog'."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question5Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You wrote 'Dog'."; + [steps addObject:step]; + } + + // Test matching text + { + ORKAnswerFormat *answer = [ORKAnswerFormat textAnswerFormat]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question6" title:@"Predicate Tests" question:@"Write a word matching '*og'" answer:answer]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question6Fail"]; + step.title = @"Predicate Tests"; + step.text = @"You didn't write a word matching '*og'."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question6Pass"]; + step.title = @"Predicate Tests"; + step.text = @"You wrote a word matching '*og'."; + [steps addObject:step]; + } + + // Numeric test - any number over 10 + { + ORKAnswerFormat *answer = [ORKAnswerFormat integerAnswerFormatWithUnit:nil]; + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question7" title:@"Predicate Tests" question:@"Enter a number over 10" answer:answer]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question7Fail"]; + step.title = @"Predicate Tests"; + step.text = @"Your number was less then 10."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question7Pass"]; + step.title = @"Predicate Tests"; + step.text = @"Your number was over 10."; + [steps addObject:step]; + } + + { + /* + Vertical continuous scale with three decimal places and a default. + */ + ORKContinuousScaleAnswerFormat *scaleAnswerFormat = [ORKAnswerFormat continuousScaleAnswerFormatWithMaximumValue:10 + minimumValue:1 + defaultValue:8.725 + maximumFractionDigits:3 + vertical:YES + maximumValueDescription:nil + minimumValueDescription:nil]; + + ORKQuestionStep *step = [ORKQuestionStep questionStepWithIdentifier:@"question8" title:@"Predciate Tests" question:@"Choose a value under 5" answer:scaleAnswerFormat]; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question8Fail"]; + step.title = @"Predicate Tests"; + step.text = @"Your number was more than 5."; + [steps addObject:step]; + } + + { + ORKInstructionStep *step = [[ORKInstructionStep alloc] initWithIdentifier:@"question8Pass"]; + step.title = @"Predicate Tests"; + step.text = @"Your number was less than 5."; + [steps addObject:step]; + } + + + { + ORKCompletionStep *step = [[ORKCompletionStep alloc] initWithIdentifier:@"allPassed"]; + step.title = @"Predicate Tests"; + step.text = @"All validation tests now completed."; + [steps addObject:step]; + } + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + + // Build navigation rules. + { + // If we answer 'Yes' to Question 1, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question1"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:resultSelector expectedAnswer:YES]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question1Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question1"]; + } + + { + // If we arrived at question_01_fail then fall through to question 2 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question2"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question1Fail"]; + } + + { + // If we answer 'Yes' to Question 2, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question2"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValue:@"Choose Yes"]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question2Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question2"]; + } + + { + // If we arrived at question_02_fail then fall through to question 3 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question3"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question2Fail"]; + } + + { + // If we answer 'Yes' to Question 3, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question3"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector expectedAnswerValues:[NSArray arrayWithObjects: @"Cat", @"Dog", nil]]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question3Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question3"]; + } + + { + // If we arrived at question_03_fail then fall through to question 4 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question4"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question3Fail"]; + } + + { + // If we answer 'Yes' to Question 4, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question4"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForChoiceQuestionResultWithResultSelector:resultSelector matchingPattern:@"Cat.*"]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question4Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question4"]; + } + + { + // If we arrived at question_04_fail then fall through to question 5 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question5"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question4Fail"]; + } + + { + // If we answer 'Dog' to Question 5, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question5"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector expectedString:@"Dog"]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question5Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question5"]; + } + + { + // If we arrived at question_05_fail then fall through to question 6 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question6"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question5Fail"]; + } + + + { + // If we answer '*og' to Question 6, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question6"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForTextQuestionResultWithResultSelector:resultSelector matchingPattern:@".*og"]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question6Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question6"]; + } + + { + // If we arrived at question_06_fail then fall through to question 7 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question7"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question6Fail"]; + } + + { + // If we answer '*og' to Question 7, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question7"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForNumericQuestionResultWithResultSelector:resultSelector minimumExpectedAnswerValue:10]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question7Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question7"]; + } + + { + // If we arrived at question_05_fail then fall through to question 6 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"question8"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question7Fail"]; + } + + { + // If we answer '*og' to Question 7, then proceed to the pass screen + ORKResultSelector *resultSelector = [ORKResultSelector selectorWithResultIdentifier:@"question8"]; + NSPredicate *predicateQuestion = [ORKResultPredicate predicateForScaleQuestionResultWithResultSelector:resultSelector maximumExpectedAnswerValue:5]; + + ORKPredicateStepNavigationRule *predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[predicateQuestion] + destinationStepIdentifiers:@[@"question8Pass"]]; + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"question8"]; + } + + { + // If we arrived at question_05_fail then fall through to question 6 + ORKDirectStepNavigationRule *directRule = nil; + directRule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:@"allPassed"]; + [task setNavigationRule:directRule forTriggerStepIdentifier:@"question8Fail"]; + } + + return task; +} + +- (id)makeSignatureStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Signature Step"; + step1.text = @"Example of an ORKSignatureStep"; + [steps addObject:step1]; + + ORKSignatureStep *signatureStep = [[ORKSignatureStep alloc] initWithIdentifier:@"signatureStep"]; + signatureStep.title = @"Signature Step"; + [steps addObject:signatureStep]; + + ORKCompletionStep *stepLast = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + stepLast.title = @"Task Complete"; + [steps addObject:stepLast]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +- (id)makeTableStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Table Step"; + step1.text = @"Example of an ORKTableStepViewController"; + [steps addObject:step1]; + + ORKTableStep *tableStep = [[ORKTableStep alloc] initWithIdentifier:@"tableStep"]; + tableStep.title = @"Table Step"; + tableStep.items = @[@"Item 1", @"Item 2", @"Item 3"]; + tableStep.bulletType = ORKBulletTypeNumber; + [steps addObject:tableStep]; + + ORKCompletionStep *stepLast = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + stepLast.title = @"Task Complete"; + [steps addObject:stepLast]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +- (id)makeVideoInstructionStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *firstStep = [[ORKInstructionStep alloc] initWithIdentifier:@"firstStep"]; + firstStep.title = @"Video Instruction"; + firstStep.text = @"Example of an ORKVideoInstructionStep"; + [steps addObject:firstStep]; + + ORKVideoInstructionStep *videoInstructionStep = [[ORKVideoInstructionStep alloc] initWithIdentifier:@"videoInstructionStep"]; + videoInstructionStep.title = @"Video Instruction"; + videoInstructionStep.videoURL = [[NSURL alloc] initWithString:@"https://www.apple.com/media/us/researchkit/2016/a63aa7d4_e6fd_483f_a59d_d962016c8093/films/carekit/researchkit-carekit-cc-us-20160321_r848-9dwc.mov"]; + + [steps addObject:videoInstructionStep]; + + ORKCompletionStep *lastStep = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + lastStep.title = @"Task Complete"; + [steps addObject:lastStep]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +- (id)makeWaitStepTaskWithIdentifier:(NSString *)identifier { + + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + /* + To properly use the wait steps, one needs to implement the "" method of ORKTaskViewControllerDelegate to start their background action when the wait task begins, and then call the "finish" method on the ORKWaitTaskViewController when the background task has been completed. + */ + ORKInstructionStep *step1 = [[ORKInstructionStep alloc] initWithIdentifier:@"step1"]; + step1.title = @"Setup"; + step1.detailText = @"ORKTest needs to set up some things before you begin, once the setup is complete you will be able to continue."; + [steps addObject:step1]; + + // Interterminate wait step. + ORKWaitStep *step2 = [[ORKWaitStep alloc] initWithIdentifier:@"step2"]; + step2.title = @"Getting Ready"; + step2.text = @"Please wait while the setup completes."; + step2.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + [((ORKWaitStepViewController *)stepViewController) performSelector:@selector(updateText:) withObject:@"Updated text" afterDelay:2.0]; + [((ORKWaitStepViewController *)stepViewController) performSelector:@selector(goForward) withObject:nil afterDelay:5.0]; + }; + [steps addObject:step2]; + + ORKInstructionStep *step3 = [[ORKInstructionStep alloc] initWithIdentifier:@"step3"]; + step3.title = @"Account Setup"; + step3.detailText = @"The information you entered will be sent to the secure server to complete your account setup."; + [steps addObject:step3]; + + // Determinate wait step. + ORKWaitStep *step4 = [[ORKWaitStep alloc] initWithIdentifier:@"step4"]; + step4.title = @"Syncing Account"; + step4.text = @"Please wait while the data is uploaded."; + step4.indicatorType = ORKProgressIndicatorTypeProgressBar; + step4.stepViewControllerWillAppearBlock = ^(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController) { + [self updateProgress:0.0 waitStepViewController:((ORKWaitStepViewController *)stepViewController)]; + }; + [steps addObject:step4]; + + ORKCompletionStep *step5 = [[ORKCompletionStep alloc] initWithIdentifier:@"step5"]; + step5.title = @"Setup Complete"; + [steps addObject:step5]; + + ORKOrderedTask *waitTask = [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; + return waitTask; +} + +- (id)makeWebViewStepTaskWithIdentifier:(NSString *)identifier { + NSMutableArray *steps = [[NSMutableArray alloc] init]; + + ORKInstructionStep *firstStep = [[ORKInstructionStep alloc] initWithIdentifier:@"firstStep"]; + firstStep.title = @"Web View"; + firstStep.text = @"Example of an ORKWebViewStep"; + [steps addObject:firstStep]; + + NSString * html = @"" + "" + "" + "" + "" + "" + "" + "
" + "" + "" + "
" + "" + ""; + + ORKWebViewStep *webViewStep = [ORKWebViewStep webViewStepWithIdentifier:@"webViewStep" html:html]; + webViewStep.title = @"Web View"; + [steps addObject:webViewStep]; + + ORKCompletionStep *lastStep = [[ORKCompletionStep alloc] initWithIdentifier:@"lastStep"]; + lastStep.title = @"Task Complete"; + [steps addObject:lastStep]; + + return [[ORKOrderedTask alloc] initWithIdentifier:identifier steps:steps]; +} + +// Update progress on the Wait Task +- (void)updateProgress:(CGFloat)progress waitStepViewController:(ORKWaitStepViewController *)waitStepviewController { + if (progress <= 1.0) { + [waitStepviewController setProgress:progress animated:true]; + double delayInSeconds = 0.1; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void) { + [self updateProgress:(progress + 0.01) waitStepViewController:waitStepviewController]; + if (progress > 0.495 && progress < 0.505) { + NSString *newText = @"Please wait while the data is downloaded."; + [waitStepviewController updateText:newText]; + } + }); + } else { + [waitStepviewController goForward]; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.h new file mode 100755 index 0000000..4086c53 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.h @@ -0,0 +1,88 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import UIKit; +@import ResearchKit; + + +/* NOTE: The task creation utility methods are alphabetically sorted within their + * their own category file. Make sure you insert your code in the appropriate place + * so all the methods in each categoty files remain alphabetically sorted. + */ + +@protocol ORKTask; +@class ORKConsentDocument; +@class ORKStepViewController; +@class ORKTaskResult; +@class ORKTaskViewController; + +// Helper properties to communicate task and step intent to MainViewController +@interface NSObject (TaskFactory) + +// ORKTask associated properties +@property (nonatomic, assign) BOOL hidesLearnMoreButtonOnInstructionStep; +@property (nonatomic, assign) BOOL isEmbeddedReviewTask; + +// ORKStep associated properties +typedef void (^StepViewControllerWillAppearBlockType)(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController); +@property (nonatomic, copy) StepViewControllerWillAppearBlockType stepViewControllerWillAppearBlock; + +typedef void (^StepViewControllerWillDisappearBlockType)(ORKTaskViewController *taskViewController, + ORKStepViewController *stepViewController, + ORKStepViewControllerNavigationDirection navigationDirection); +@property (nonatomic, copy) StepViewControllerWillDisappearBlockType stepViewControllerWillDisappearBlock; + +typedef BOOL (^ShouldPresentStepBlockType)(ORKTaskViewController *taskViewController, + ORKStep *step); +@property (nonatomic, copy) ShouldPresentStepBlockType shouldPresentStepBlock; + +@end + + +@interface TaskFactory : NSObject + ++ (instancetype)sharedInstance; + +- (id)makeTaskWithIdentifier:(NSString *)identifier; + +- (ORKConsentDocument *)buildConsentDocument; + +- (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size border:(BOOL)border; + +@property (nonatomic, copy) ORKConsentDocument *currentConsentDocument; + +@property (nonatomic, strong) ORKTaskResult *embeddedReviewTaskResult; + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.m new file mode 100755 index 0000000..e4d105c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.m @@ -0,0 +1,307 @@ +/* + Copyright (c) 2015-2017, Apple Inc. All rights reserved. + Copyright (c) 2015, Bruce Duncan. + Copyright (c) 2015-2017, Ricardo Sanchez-Saez. + Copyright (c) 2016-2017, Sage Bionetworks + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "TaskFactory.h" + +#import "ORKTest-Swift.h" + +#import + + +// This macro generates a default implementation for CType properties declared inside a class extension. +// +// Example: +// +// ORKTypeExtensionProperty_Implementation(myBoolProperty, +// MyBoolProperty, +// BOOL, +// NO); +// +#define ORKTPasteTokens(A,B) A ## B + +#define ORKTCTypeExtensionProperty_Implementation(_propertyName, \ + _capitalizedPropertyName, \ + _propertyType, \ + _propertyDefaultValue) \ + \ +- (void) ORKTPasteTokens(set, _capitalizedPropertyName) :(_propertyType)propertyValue \ +{ \ + NSValue *value = [NSValue valueWithBytes:&propertyValue objCType:@encode(_propertyType)]; \ + objc_setAssociatedObject(self, @selector(_propertyName), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); \ +} \ + \ +- ( _propertyType ) _propertyName \ +{ \ + NSValue *value = objc_getAssociatedObject(self, @selector(_propertyName) ); \ + if (value) \ + { \ + _propertyType propertyValue; [value getValue:&propertyValue]; return propertyValue; \ + } \ + else \ + { \ + return _propertyDefaultValue ; \ + } \ +} \ + +#define ORKTCopyExtensionProperty_Implementation(_propertyName, \ + _capitalizedPropertyName, \ + _propertyType) \ + \ +- (void) ORKTPasteTokens(set, _capitalizedPropertyName) :(_propertyType)propertyValue \ +{ \ + objc_setAssociatedObject(self, \ + @selector(_propertyName), \ + propertyValue, \ + OBJC_ASSOCIATION_COPY_NONATOMIC); \ +} \ + \ +- ( _propertyType ) _propertyName \ +{ \ + return objc_getAssociatedObject(self, @selector(_propertyName)); \ +} \ + + +@implementation NSObject (TaskFactory) + +ORKTCTypeExtensionProperty_Implementation(hidesLearnMoreButtonOnInstructionStep, + HidesLearnMoreButtonOnInstructionStep, + BOOL, + NO); + +ORKTCTypeExtensionProperty_Implementation(hidesProgressInNavigationBar, + HidesProgressInNavigationBar, + BOOL, + NO); + +ORKTCTypeExtensionProperty_Implementation(isEmbeddedReviewTask, + IsEmbeddedReviewTask, + BOOL, + NO); + +ORKTCTypeExtensionProperty_Implementation(triggersStepWillDisappearAction, + TriggersStepWillDisappearAction, + BOOL, + NO); + +ORKTCopyExtensionProperty_Implementation(stepViewControllerWillAppearBlock, + StepViewControllerWillAppearBlock, + StepViewControllerWillAppearBlockType); + +ORKTCopyExtensionProperty_Implementation(stepViewControllerWillDisappearBlock, + StepViewControllerWillDisappearBlock, + StepViewControllerWillDisappearBlockType); + +ORKTCopyExtensionProperty_Implementation(shouldPresentStepBlock, + ShouldPresentStepBlock, + ShouldPresentStepBlockType); + +@end + + +@implementation TaskFactory + ++ (instancetype)sharedInstance +{ + static dispatch_once_t onceToken; + static id sharedInstance = nil; + dispatch_once(&onceToken, ^{ + sharedInstance = [[[self class] alloc] init]; + }); + return sharedInstance; +} + +#pragma mark - Mapping identifiers to tasks + +- (id)makeTaskWithIdentifier:(NSString *)identifier { + id task = nil; + // convert @"SampleTaskIdentifier" into @"makeSampleTaskWithIdentifier:" + NSString *makeTaskSelectorName = [NSString stringWithFormat:@"make%@WithIdentifier:", + [identifier substringToIndex:identifier.length - 10]]; + SEL makeTaskSelector = NSSelectorFromString(makeTaskSelectorName); + if ([self respondsToSelector:makeTaskSelector]) { + // Equivalent to [self peformSelector:buttonSelector], but ARC safe + IMP imp = [self methodForSelector:makeTaskSelector]; + id (*func)(id, SEL, NSString *) = (void *)imp; + task = func(self, makeTaskSelector, identifier); + } + return task; +} + +/* + Builds a test consent document. + */ +- (ORKConsentDocument *)buildConsentDocument { + ORKConsentDocument *consent = [[ORKConsentDocument alloc] init]; + + /* + If you have HTML review content, you can substitute it for the + concatenation of sections by doing something like this: + consent.htmlReviewContent = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:XXX ofType:@"html"] encoding:NSUTF8StringEncoding error:nil]; + */ + + /* + Title that will be shown in the generated document. + */ + consent.title = @"Demo Consent"; + + + /* + Signature page content, used in the generated document above the signatures. + */ + consent.signaturePageTitle = @"Consent"; + consent.signaturePageContent = @"I agree to participate in this research Study."; + + /* + The empty signature that the user will fill in. + */ + ORKConsentSignature *participantSig = [ORKConsentSignature signatureForPersonWithTitle:@"Participant" dateFormatString:nil identifier:@"participantSig"]; + [consent addSignature:participantSig]; + + /* + Pre-populated investigator's signature. + */ + ORKConsentSignature *investigatorSig = [ORKConsentSignature signatureForPersonWithTitle:@"Investigator" dateFormatString:nil identifier:@"investigatorSig" givenName:@"Jake" familyName:@"Clemson" signatureImage:[UIImage imageNamed:@"signature"] dateString:@"9/2/14" ]; + [consent addSignature:investigatorSig]; + + /* + These are the set of consent sections that have pre-defined animations and + images. + + We will create a section for each of the section types, and then add a custom + section on the end. + */ + NSArray *scenes = @[@(ORKConsentSectionTypeOverview), + @(ORKConsentSectionTypeDataGathering), + @(ORKConsentSectionTypePrivacy), + @(ORKConsentSectionTypeDataUse), + @(ORKConsentSectionTypeTimeCommitment), + @(ORKConsentSectionTypeStudySurvey), + @(ORKConsentSectionTypeStudyTasks), + @(ORKConsentSectionTypeWithdrawing)]; + + NSMutableArray *sections = [NSMutableArray new]; + for (NSNumber *type in scenes) { + NSString *summary = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo? Et doming eirmod delicata cum. Vel fabellas scribentur neglegentur cu, pro te iudicabit explicari. His alia idque scriptorem ei, quo no nominavi noluisse."; + ORKConsentSection *consentSection = [[ORKConsentSection alloc] initWithType:type.integerValue]; + consentSection.summary = summary; + + if (type.integerValue == ORKConsentSectionTypeOverview) { + /* + Tests HTML content instead of text for Learn More. + */ + consentSection.htmlContent = @"
  • Lorem
  • ipsum
  • dolor

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?

\ +

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?

研究"; + } else if (type.integerValue == ORKConsentSectionTypeDataGathering) { + /* + Tests PDF content instead of text, HTML for Learn More. + */ + NSString *path = [[NSBundle mainBundle] pathForResource:@"SAMPLE_PDF_TEST" ofType:@"pdf"]; + consentSection.contentURL = [NSURL URLWithString:path]; + + } else { + /* + Tests text Learn More content. + */ + consentSection.content = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?\ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?\ + An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo? Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?\ + An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo? Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?\ + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?\ + An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?"; + } + + [sections addObject:consentSection]; + } + + { + /* + A custom consent scene. This doesn't demo it but you can also set a custom + animation. + */ + ORKConsentSection *consentSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeCustom]; + consentSection.summary = @"Custom Scene summary"; + consentSection.title = @"Custom Scene"; + consentSection.customImage = [UIImage imageNamed:@"image_example.png"]; + consentSection.customLearnMoreButtonTitle = @"Learn more about customizing ResearchKit"; + consentSection.content = @"You can customize ResearchKit a lot!"; + [sections addObject:consentSection]; + } + + { + /* + An "only in document" scene. This is ignored for visual consent, but included in + the concatenated document for review. + */ + ORKConsentSection *consentSection = [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeOnlyInDocument]; + consentSection.summary = @"OnlyInDocument Scene summary"; + consentSection.title = @"OnlyInDocument Scene"; + consentSection.content = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?"; + [sections addObject:consentSection]; + } + + consent.sections = [sections copy]; + return consent; +} + +/* + A helper for creating square colored images, which can optionally have a border. + + Used for testing the image choices answer format. + + @param color Color to use for the image. + @param size Size of image. + @param border Boolean value indicating whether to add a black border around the image. + + @return An image. + */ +- (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size border:(BOOL)border { + + UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)]; + + view.backgroundColor = color; + + if (border) { + view.layer.borderColor = [[UIColor blackColor] CGColor]; + view.layer.borderWidth = 5.0; + } + + UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0); + [view.layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.swift b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.swift new file mode 100755 index 0000000..25e95d2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTest/Tasks/TaskFactory.swift @@ -0,0 +1,174 @@ +/* +Copyright (c) 2015, Ricardo Sánchez-Sáez. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import Foundation +import ResearchKit + +public extension TaskFactory { + + @objc + class func makeNavigableOrderedTask(_ taskIdentifier: String) -> ORKNavigableOrderedTask { + var steps: [ORKStep] = [] + var answerFormat: ORKAnswerFormat + var step: ORKStep + var textChoices: [ORKTextChoice] + + // Intro step + step = ORKInstructionStep(identifier: "introStep") + step.title = "This task demonstrates rule-based navigation within tasks" + steps.append(step) + + // Form step + textChoices = [ + ORKTextChoice(text: "Good", value: "good" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Bad", value: "bad" as NSCoding & NSCopying & NSObjectProtocol) + ] + answerFormat = ORKAnswerFormat.choiceAnswerFormat(with: ORKChoiceAnswerStyle.singleChoice, textChoices: textChoices) + let formItemFeeling: ORKFormItem = ORKFormItem(identifier: "formFeeling", text: "How do you feel", answerFormat: answerFormat) + let formItemMood: ORKFormItem = ORKFormItem(identifier: "formMood", text: "How is your mood", answerFormat: answerFormat) + let formStep: ORKFormStep = ORKFormStep(identifier: "introForm") + formStep.isOptional = false + formStep.formItems = [formItemFeeling, formItemMood] + steps.append(formStep) + + // Question steps + textChoices = [ + ORKTextChoice(text: "Headache", value: "headache" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Dizziness", value: "dizziness" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Nausea", value: "nausea" as NSCoding & NSCopying & NSObjectProtocol) + ] + answerFormat = ORKTextChoiceAnswerFormat(style: ORKChoiceAnswerStyle.singleChoice, textChoices: textChoices) + step = ORKQuestionStep(identifier: "symptom", title: "Symptoms", question: "Which is your most severe symptom?", answer: answerFormat) + step.isOptional = false + steps.append(step) + + answerFormat = ORKAnswerFormat.booleanAnswerFormat() + step = ORKQuestionStep(identifier: "severity", title: "Symptoms", question: "Does your symptom interfere with your daily life?", answer: answerFormat) + step.isOptional = false + steps.append(step) + + // Instruction steps + step = ORKInstructionStep(identifier: "blank") + step.title = "This step is intentionally left blank (you should not see it)" + steps.append(step) + + step = ORKInstructionStep(identifier: "severeHeadache") + step.title = "You have a severe headache" + steps.append(step) + + step = ORKInstructionStep(identifier: "lightHeadache") + step.title = "You have a light headache" + steps.append(step) + + step = ORKInstructionStep(identifier: "otherSymptom") + step.title = "Your symptom is not a headache" + steps.append(step) + + step = ORKInstructionStep(identifier: "surveySkipped") + step.title = "Please come back to this survey when you don't feel good or your mood is low." + steps.append(step) + + step = ORKInstructionStep(identifier: "end") + step.title = "You have finished the task" + steps.append(step) + + step = ORKInstructionStep(identifier: "blankB") + step.title = "This step is intentionally left blank (you should not see it)" + steps.append(step) + + let task: ORKNavigableOrderedTask = ORKNavigableOrderedTask(identifier: taskIdentifier, steps: steps) + + // Navigation rules + var predicateRule: ORKPredicateStepNavigationRule + + // From the feel/mood form step, skip the survey if the user is feeling okay and has a good mood + var resultSelector = ORKResultSelector(stepIdentifier: "introForm", resultIdentifier: "formFeeling") + let predicateGoodFeeling: NSPredicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "good" as NSCoding & NSCopying & NSObjectProtocol) + resultSelector = ORKResultSelector(stepIdentifier: "introForm", resultIdentifier: "formMood") + let predicateGoodMood: NSPredicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "good" as NSCoding & NSCopying & NSObjectProtocol) + let predicateGoodMoodAndFeeling: NSCompoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateGoodFeeling, predicateGoodMood]) + predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: + [ (predicateGoodMoodAndFeeling, "surveySkipped") ]) + task.setNavigationRule(predicateRule, forTriggerStepIdentifier: "introForm") + + // From the "symptom" step, go to "otherSymptom" is user didn't chose headache. + // Otherwise, default to going to next step (the regular ORKOrderedTask order applies + // when the defaultStepIdentifier argument is omitted). + + // User chose headache at the symptom step + // Equivalent to: + // [NSPredicate predicateWithFormat: + // @"SUBQUERY(SELF, $x, $x.identifier like 'symptom' \ + // AND SUBQUERY($x.answer, $y, $y like 'headache').@count > 0).@count > 0"]; + resultSelector = ORKResultSelector(resultIdentifier: "symptom") + let predicateHeadache: NSPredicate = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "headache" as NSCoding & NSCopying & NSObjectProtocol) + + // User didn't chose headache at the symptom step + let predicateNotHeadache: NSCompoundPredicate = NSCompoundPredicate(notPredicateWithSubpredicate: predicateHeadache) + + predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: + [ (predicateNotHeadache, "otherSymptom") ]) + task.setNavigationRule(predicateRule, forTriggerStepIdentifier: "symptom") + + // From the "severity" step, go to "severeHeadache" or "lightHeadache" depending on the user answer + + // User chose YES at the severity step + // Equivalent to: + // [NSPredicate predicateWithFormat: + // @"SUBQUERY(SELF, $x, $x.identifier like 'severity' AND $x.answer == YES).@count > 0"]; + resultSelector = ORKResultSelector(resultIdentifier: "severity") + let predicateSevereYes: NSPredicate = ORKResultPredicate.predicateForBooleanQuestionResult(with: resultSelector, expectedAnswer: true) + + // User chose NO at the severity step + resultSelector = ORKResultSelector(resultIdentifier: "severity") + let predicateSevereNo: NSPredicate = ORKResultPredicate.predicateForBooleanQuestionResult(with: resultSelector, expectedAnswer: false) + + let predicateSevereHeadache: NSCompoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateHeadache, predicateSevereYes]) + let predicateLightHeadache: NSCompoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateHeadache, predicateSevereNo]) + + predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: + [ (predicateSevereHeadache, "severeHeadache"), (predicateLightHeadache, "lightHeadache") ]) + task.setNavigationRule(predicateRule, forTriggerStepIdentifier: "severity") + + // Direct rules to skip unneeded steps + var directRule: ORKDirectStepNavigationRule + + directRule = ORKDirectStepNavigationRule(destinationStepIdentifier: "end") + task.setNavigationRule(directRule, forTriggerStepIdentifier: "severeHeadache") + task.setNavigationRule(directRule, forTriggerStepIdentifier: "lightHeadache") + task.setNavigationRule(directRule, forTriggerStepIdentifier: "otherSymptom") + task.setNavigationRule(directRule, forTriggerStepIdentifier: "surveySkipped") + + directRule = ORKDirectStepNavigationRule(destinationStepIdentifier: ORKNullStepIdentifier) + task.setNavigationRule(directRule, forTriggerStepIdentifier: "end") + + return task + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/Info.plist new file mode 100755 index 0000000..c782c79 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/Info.plist @@ -0,0 +1,28 @@ + + + + + NSHealthShareUsageDescription + Test HK releated features. + NSHealthUpdateUsageDescription + Test HK related features. + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKDataCollectionTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKDataCollectionTests.m new file mode 100755 index 0000000..26df415 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKDataCollectionTests.m @@ -0,0 +1,433 @@ +/* + Copyright (c) 2016, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import +#import + + +@interface ORKDataCollectionTests : XCTestCase + +@end + + +@implementation ORKDataCollectionTests { + XCTestExpectation *_completionExpectation; + XCTestExpectation *_healthCollectionExpectation; + XCTestExpectation *_correlationCollectionExpectation; + HKHealthStore *_healthStore; + BOOL _acceptDelivery; + NSInteger _errorCount; +} + +- (BOOL)fileExistAt:(NSString *)path { + return [[NSFileManager defaultManager] fileExistsAtPath:path]; +} + +- (NSString *)documentPath { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + return ([paths count] > 0) ? [paths objectAtIndex:0] : nil; +} + +- (NSString *)sourcePath { + NSString *sourcePath = [[self documentPath] stringByAppendingPathComponent:@"source"]; + [[NSFileManager defaultManager] createDirectoryAtPath:sourcePath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + return sourcePath; +} + +- (NSString *)basePath { + NSString *testPath = [[self documentPath] stringByAppendingPathComponent:@"test"]; + [[NSFileManager defaultManager] createDirectoryAtPath:testPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + return testPath; +} + +- (NSString *)storePath { + NSString *basePath = [self basePath]; + NSString *storePath = [basePath stringByAppendingPathComponent:@"managedDataCollectionStore"]; + return storePath; +} + +- (NSString *)cleanStorePath { + NSString *storePath = [self storePath]; + [[NSFileManager defaultManager] removeItemAtPath:storePath error:nil]; + return storePath; +} + +static ORKDataCollectionManager *createManagerWithCollectors(NSURL *url, + NSDate *startDate, + ORKMotionActivityCollector **motionCollector, + ORKHealthCollector **healthCollector, + ORKHealthCorrelationCollector **healthCorrelationCollector, + NSError **error) { + + ORKDataCollectionManager *manager = [[ORKDataCollectionManager alloc] initWithPersistenceDirectoryURL:url]; + + ORKMotionActivityCollector *mac = [manager addMotionActivityCollectorWithStartDate:startDate error:error]; + if (motionCollector) { + *motionCollector = mac; + } + + if (error && *error) { + return nil; + } + + HKQuantityType *type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; + HKUnit *unit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]; + ORKHealthCollector *hc = [manager addHealthCollectorWithSampleType:type + unit:unit + startDate:startDate + error:error]; + + if (healthCollector) { + *healthCollector = hc; + } + + if (error && *error) { + return nil; + } + + HKCorrelationType *correlationType = [HKCorrelationType correlationTypeForIdentifier:HKCorrelationTypeIdentifierBloodPressure]; + NSArray *sampleTypes = @[[HKObjectType quantityTypeForIdentifier: HKQuantityTypeIdentifierBloodPressureDiastolic], + [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]]; + NSArray *units = @[[HKUnit unitFromString:@"mmHg"], [HKUnit unitFromString:@"mmHg"]]; + + ORKHealthCorrelationCollector *hcc = [manager addHealthCorrelationCollectorWithCorrelationType:correlationType + sampleTypes:sampleTypes + units:units + startDate:startDate + error:error]; + + if (healthCorrelationCollector) { + *healthCorrelationCollector = hcc; + } + + if (error && *error) { + return nil; + } + + return manager; +} + +- (void)setUp { + HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; + HKQuantityType *diastolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic]; + HKQuantityType *systolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]; + + NSSet *types = [NSSet setWithObjects:heartRateType, diastolicType, systolicType, nil]; + XCTestExpectation *expectation = [self expectationWithDescription:@"Wait for grant permissions"]; + [[HKHealthStore new] requestAuthorizationToShareTypes:types readTypes:types + completion:^(BOOL success, NSError * _Nullable error) { + [expectation fulfill]; + }]; + + _acceptDelivery = YES; + + [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { + XCTAssertNil(error); + }]; +} + +- (void)testBasicOperations { + + ORKMotionActivityCollector *motionCollector; + ORKHealthCollector *healthCollector; + ORKHealthCorrelationCollector *healthCorrelationCollector; + NSError *error; + // Create + ORKDataCollectionManager *manager = createManagerWithCollectors([NSURL fileURLWithPath:[self cleanStorePath]], + [NSDate date], + &motionCollector, + &healthCollector, + &healthCorrelationCollector, + &error); + + XCTAssertNil(error); + XCTAssertEqual(manager.collectors.count, 3); + + // Re-init + manager = [[ORKDataCollectionManager alloc] initWithPersistenceDirectoryURL:[NSURL fileURLWithPath:[self storePath]]]; + XCTAssertEqual(manager.collectors.count, 3); + + // Remove Collector + [manager removeCollector:motionCollector error:&error]; + XCTAssertNil(error); + XCTAssertEqual(manager.collectors.count, 2); + + [manager removeCollector:healthCollector error:&error]; + XCTAssertNil(error); + XCTAssertEqual(manager.collectors.count, 1); + + [manager removeCollector:healthCorrelationCollector error:&error]; + XCTAssertNil(error); + XCTAssertEqual(manager.collectors.count, 0); + +} + + +typedef NS_OPTIONS (NSInteger, SampleDataType) { + SampleDataTypeHR = 1 << 0, + SampleDataTypeBP = 1 << 1, + SampleDataTypeALL= SampleDataTypeHR|SampleDataTypeBP +}; + + +- (BOOL)insertSampleDataWithType:(SampleDataType)sampleDataType + startDate:(NSDate *)startDate + endDate:(NSDate *)endDate { + _healthStore = [[HKHealthStore alloc] init]; + + HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; + HKQuantityType *diastolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic]; + HKQuantityType *systolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic]; + + HKAuthorizationStatus heartRateTypeStatus = [_healthStore authorizationStatusForType:heartRateType]; + HKAuthorizationStatus diastolicTypeStatus = [_healthStore authorizationStatusForType:diastolicType]; + HKAuthorizationStatus systolicTypeStatus = [_healthStore authorizationStatusForType:systolicType]; + + BOOL authorized = (heartRateTypeStatus == HKAuthorizationStatusSharingAuthorized + && diastolicTypeStatus == HKAuthorizationStatusSharingAuthorized + && systolicTypeStatus == HKAuthorizationStatusSharingAuthorized); + + if (authorized) { + +#if TARGET_OS_SIMULATOR + + // Heart Rate + HKUnit *hrUnit = [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]]; + HKQuantity* quantity = [HKQuantity quantityWithUnit:hrUnit doubleValue:(NSInteger)([NSDate date].timeIntervalSinceReferenceDate)%100]; + HKQuantitySample *heartRateSample = [HKQuantitySample quantitySampleWithType:heartRateType quantity:quantity startDate:startDate endDate:endDate]; + + NSString *identifier = HKCorrelationTypeIdentifierBloodPressure; + HKUnit *bpUnit = [HKUnit unitFromString:@"mmHg"]; + + // Blood Presure + HKQuantitySample *diastolicPressure = [HKQuantitySample quantitySampleWithType:diastolicType quantity:[HKQuantity quantityWithUnit:bpUnit doubleValue:70] startDate:startDate endDate:endDate]; + HKQuantitySample *systolicPressure = [HKQuantitySample quantitySampleWithType:systolicType quantity:[HKQuantity quantityWithUnit:bpUnit doubleValue:110] startDate:startDate endDate:endDate]; + + HKCorrelation *bloodPressureCorrelation = [HKCorrelation correlationWithType:[HKCorrelationType correlationTypeForIdentifier:identifier] startDate:startDate endDate:endDate objects:[NSSet setWithObjects:diastolicPressure, systolicPressure, nil]]; + + NSMutableArray *objects = [NSMutableArray new]; + if (sampleDataType & SampleDataTypeHR) { + [objects addObject:heartRateSample]; + } + if (sampleDataType & SampleDataTypeBP) { + [objects addObject:bloodPressureCorrelation]; + } + + [_healthStore saveObjects:objects withCompletion:^(BOOL success, NSError * _Nullable error) { + NSLog(@"HK sample saving = %@, error = %@", success ? @"success" : @"failed", error); + }]; + +#endif + } else { + NSLog(@"HKHealthStore access has not been authorized."); + } + + return authorized; +} + +- (void)testDataCollection { + + ORKMotionActivityCollector *motionCollector; + ORKHealthCollector *healthCollector; + ORKHealthCorrelationCollector *healthCorrelationCollector; + __block NSError *error; + ORKDataCollectionManager *manager = createManagerWithCollectors([NSURL fileURLWithPath:[self cleanStorePath]], + [NSDate dateWithTimeIntervalSinceNow:-10], + &motionCollector, + &healthCollector, + &healthCorrelationCollector, + &error); + + manager.delegate = self; + + // First round collection + _completionExpectation = [self expectationWithDescription:@"Expectation for collection completion"]; + +#if TARGET_OS_SIMULATOR + if ([self insertSampleDataWithType:SampleDataTypeALL + startDate:[NSDate dateWithTimeIntervalSinceNow:-9] + endDate:[NSDate dateWithTimeIntervalSinceNow:-8]]) { + _healthCollectionExpectation = [self expectationWithDescription:@"Expectation for health sample collection completion"]; + _correlationCollectionExpectation = [self expectationWithDescription:@"Expectation for correlation collection completion"]; + } +#endif + + [manager startCollection]; + + // Test removing collector during collection + BOOL result = [manager removeCollector:healthCollector error:&error]; + XCTAssertFalse(result); + XCTAssertNotNil(error); + XCTAssertEqual(manager.collectors.count, 3); + + [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { + XCTAssertNil(error); + }]; + + // Test removing collector after collection + result = [manager removeCollector:healthCollector error:&error]; + XCTAssertTrue(result); + XCTAssertNil(error); + XCTAssertEqual(manager.collectors.count, 2); + + // Second round collection + _completionExpectation = [self expectationWithDescription:@"Expectation for collection completion"]; + +#if TARGET_OS_SIMULATOR + if ([self insertSampleDataWithType:SampleDataTypeBP + startDate:[NSDate dateWithTimeIntervalSinceNow:-9] + endDate:[NSDate dateWithTimeIntervalSinceNow:-8]]) { + // Health Collector was removed + _healthCollectionExpectation = nil; + _correlationCollectionExpectation = [self expectationWithDescription:@"Expectation for correlation collection completion"]; + } +#endif + + [manager startCollection]; + + [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { + XCTAssertNil(error); + }]; + +} + +- (void)testDataCollectionWithoutCollectors { + + ORKMotionActivityCollector *motionCollector; + ORKHealthCollector *healthCollector; + ORKHealthCorrelationCollector *healthCorrelationCollector; + __block NSError *error; + ORKDataCollectionManager *manager = createManagerWithCollectors([NSURL fileURLWithPath:[self cleanStorePath]], + [NSDate date], + &motionCollector, + &healthCollector, + &healthCorrelationCollector, + &error); + + manager.delegate = self; + + [manager removeCollector:motionCollector error:&error]; + [manager removeCollector:healthCollector error:&error]; + [manager removeCollector:healthCorrelationCollector error:&error]; + + _completionExpectation = [self expectationWithDescription:@"Expectation for collection completion"]; + + [manager startCollection]; + + [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { + XCTAssertNil(error); + }]; +} + +- (void)testDataCollectionDelegateDeliveryRejection { + _acceptDelivery = NO; + _errorCount = 0; + + ORKMotionActivityCollector *motionCollector; + ORKHealthCollector *healthCollector; + ORKHealthCorrelationCollector *healthCorrelationCollector; + __block NSError *error; + + // Make sure the startDate isn't earlier that the dates + // of the samples added on '-testDataCollection'. + // Othersie, you'll get the samples from that test too. + ORKDataCollectionManager *manager = createManagerWithCollectors([NSURL fileURLWithPath:[self cleanStorePath]], + [NSDate dateWithTimeIntervalSinceNow:-5], + &motionCollector, + &healthCollector, + &healthCorrelationCollector, + &error); + + manager.delegate = self; + + _completionExpectation = [self expectationWithDescription:@"Expectation for collection completion"]; + +#if TARGET_OS_SIMULATOR + if ([self insertSampleDataWithType:SampleDataTypeALL + startDate:[NSDate dateWithTimeIntervalSinceNow:-4] + endDate:[NSDate dateWithTimeIntervalSinceNow:-3]]) { + _healthCollectionExpectation = [self expectationWithDescription:@"Expectation for health sample collection completion"]; + _correlationCollectionExpectation = [self expectationWithDescription:@"Expectation for correlation collection completion"]; + } +#endif + + [manager startCollection]; + [self waitForExpectationsWithTimeout:10.0 handler:^(NSError *error) { + XCTAssertNil(error); + }]; + XCTAssertEqual(_errorCount, 2); +} + +#pragma mark - delegate + +- (BOOL)healthCollector:(ORKHealthCollector *)collector + didCollectSamples:(NSArray *)samples { + XCTAssertEqual(samples.count, 1); + [_healthCollectionExpectation fulfill]; + NSLog(@"Did collect health samples"); + return _acceptDelivery; +} + +- (BOOL)healthCorrelationCollector:(ORKHealthCorrelationCollector *)collector + didCollectCorrelations:(NSArray *)correlations { + XCTAssertEqual(correlations.count, 1); + [_correlationCollectionExpectation fulfill]; + NSLog(@"Did collect correlation samples"); + return _acceptDelivery; +} + +- (BOOL)motionActivityCollector:(ORKMotionActivityCollector *)collector + didCollectMotionActivities:(NSArray *)motionActivities { + XCTAssertGreaterThan(motionActivities.count, 0); + NSLog(@"Did collect CMMotionActivity samples"); + return _acceptDelivery; +} + +- (void)dataCollectionManagerDidCompleteCollection:(ORKDataCollectionManager *)manager { + NSLog(@"dataCollectionManagerDidCompleteCollection %@", @(_acceptDelivery)); + [_completionExpectation fulfill]; +} + +- (void)collector:(ORKCollector *)collector didDetectError:(NSError *)error { + NSLog(@"didDetectError %@", error); + if (_acceptDelivery) { + XCTAssertNil(error); + } + _errorCount++; +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.h b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.h new file mode 100755 index 0000000..ff91d3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.h @@ -0,0 +1,118 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import Foundation; +@import UIKit; + + +NS_ASSUME_NONNULL_BEGIN + +@interface ORKESerializationLocalizer : NSObject + +- (instancetype)initWithBundle:(NSBundle *)bundle tableName:(NSString *)tableName; + +@property (nonatomic, strong) NSBundle *bundle; +@property (nonatomic, strong) NSString *tableName; + +@end + +@protocol ORKESerializationImageProvider + +- (UIImage *)imageForReference:(NSDictionary *)reference; +- (nullable NSDictionary *)referenceBySavingImage:(UIImage *)image; + +@end + +@interface ORKESerializationContext : NSObject + +- (instancetype)initWithLocalizer:(nullable ORKESerializationLocalizer *)localizer + imageProvider:(nullable id)imageProvider; + +@property (nonatomic, strong, nullable) ORKESerializationLocalizer *localizer; +@property (nonatomic, strong, nullable) id imageProvider; + +@end + +typedef _Nullable id (^ORKESerializationPropertyGetter)(NSDictionary *dict, NSString *property); +typedef _Nullable id (^ORKESerializationInitBlock)(NSDictionary *dict, ORKESerializationPropertyGetter getter); +typedef _Nullable id (^ORKESerializationObjectToJSONBlock)(id object, ORKESerializationContext *context); +typedef _Nullable id (^ORKESerializationJSONToObjectBlock)(id jsonObject, ORKESerializationContext *context); + + + + +@interface ORKESerializationBundleImageProvider : NSObject + +- (instancetype)initWithBundle:(NSBundle *)bundle; + +@property (nonatomic, strong, readonly) NSBundle *bundle; + +@end + +@interface ORKESerializer : NSObject + ++ (nullable NSDictionary *)JSONObjectForObject:(id)object error:(NSError **)error; + ++ (nullable NSData *)JSONDataForObject:(id)object error:(NSError **)error; + ++ (nullable id)objectFromJSONObject:(NSDictionary *)object error:(NSError **)error; + ++ (nullable id)objectFromJSONObject:(NSDictionary *)object context:(ORKESerializationContext *)context error:(NSError **)error; + ++ (NSDictionary *)JSONObjectForObject:(id)object context:(ORKESerializationContext *)context error:(__unused NSError **)error; + ++ (nullable id)objectFromJSONData:(NSData *)data error:(NSError **)error; + ++ (NSArray *)serializableClasses; + ++ (NSArray *)serializedPropertiesForClass:(Class)c; + +@end + + +@interface ORKESerializer (Registration) + ++ (void)registerSerializableClass:(Class)serializableClass + initBlock:(nullable ORKESerializationInitBlock)initBlock; + ++ (void)registerSerializableClassPropertyName:(NSString *)propertyName + forClass:(Class)serializableClass + valueClass:(Class)valueClass + containerClass:(nullable Class)containerClass + writeAfterInit:(BOOL)writeAfterInit + objectToJSONBlock:(nullable ORKESerializationObjectToJSONBlock)objectToJSON + jsonToObjectBlock:(nullable ORKESerializationJSONToObjectBlock)jsonToObjectBlock; + +@end + + +NS_ASSUME_NONNULL_END + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.m new file mode 100755 index 0000000..2a8d322 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKESerialization.m @@ -0,0 +1,2389 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import "ORKESerialization.h" + +@import ResearchKit; +@import ResearchKit.Private; + +@import MapKit; +@import Speech; + +static NSString *noAnswerPrefix = @"noAnswer_"; + +static NSString *ORKEStringFromDateISO8601(NSDate *date) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; + [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + }); + return [formatter stringFromDate:date]; +} + +static NSDate *ORKEDateFromStringISO8601(NSString *string) { + static NSDateFormatter *formatter = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; + [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]]; + }); + return [formatter dateFromString:string]; +} + +static NSArray *ORKNumericAnswerStyleTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"decimal", @"integer"]; + }); + return table; +} + +static NSArray *ORKImageChoiceAnswerStyleTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"singleChoice", @"multipleChoice"]; + }); + return table; +} + +static NSArray *ORKMeasurementSystemTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"local", @"metric", @"USC"]; + }); + return table; +} + +static id tableMapForward(NSInteger index, NSArray *table) { + return table[(NSUInteger)index]; +} + +static NSInteger tableMapReverse(id value, NSArray *table) { + NSUInteger idx = [table indexOfObject:value]; + if (idx == NSNotFound) + { + idx = 0; + } + return (NSInteger)idx; +} + +static NSDictionary *dictionaryFromCGPoint(CGPoint p) { + return @{ @"x": @(p.x), @"y": @(p.y) }; +} + +static NSDictionary *dictionaryFromNSRange(NSRange r) { + return @{ @"location": @(r.location) , @"length": @(r.length) }; +} + +static NSDictionary *dictionaryFromSFAcousticFeature(SFAcousticFeature *acousticFeature) { + if (acousticFeature == nil) { return @{}; } + return @{ @"acousticFeatureValuePerFrame" : acousticFeature.acousticFeatureValuePerFrame, + @"frameDuration" : @(acousticFeature.frameDuration) + }; +} + +static NSDictionary *dictionaryFromSFVoiceAnalytics(SFVoiceAnalytics *voiceAnalytics) { + if (voiceAnalytics == nil) { return @{}; } + return @{ + @"jitter" : dictionaryFromSFAcousticFeature(voiceAnalytics.jitter), + @"shimmer" : dictionaryFromSFAcousticFeature(voiceAnalytics.shimmer), + @"pitch" : dictionaryFromSFAcousticFeature(voiceAnalytics.pitch), + @"voicing" : dictionaryFromSFAcousticFeature(voiceAnalytics.voicing) + }; +} + +static NSDictionary *dictionaryFromSFTranscriptionSegment(SFTranscriptionSegment *segment) { + if (segment == nil) { return @{}; } + return @{ + @"substring" : segment.substring, + @"substringRange" : dictionaryFromNSRange(segment.substringRange), + @"timestamp" : @(segment.timestamp), + @"duration" : @(segment.duration), + @"confidence" : @(segment.confidence), + @"alternativeSubstrings" : segment.alternativeSubstrings.copy, + @"voiceAnalytics" : dictionaryFromSFVoiceAnalytics(segment.voiceAnalytics) + }; +} + +typedef id (*mapFunction)(id); +static NSArray *mapArray(NSArray *input, mapFunction function) { + NSMutableArray *result = [NSMutableArray arrayWithCapacity:[input count]]; + for (id value in input) { + [result addObject:function(value)]; + } + return result; +} + +static NSDictionary *dictionaryFromSFTranscription(SFTranscription *transcription) { + if (transcription == nil) { return @{}; }; + return @{ + @"formattedString": transcription.formattedString, + @"speakingRate" : @(transcription.speakingRate), + @"averagePauseDuration" : @(transcription.averagePauseDuration), + @"segments" : mapArray(transcription.segments, dictionaryFromSFTranscriptionSegment) + }; +} + +static NSDictionary *dictionaryFromCGSize(CGSize s) { + return @{ @"h": @(s.height), @"w": @(s.width) }; +} + +static NSDictionary *dictionaryFromCGRect(CGRect r) { + return @{ @"origin": dictionaryFromCGPoint(r.origin), @"size": dictionaryFromCGSize(r.size) }; +} + +static NSDictionary *dictionaryFromUIEdgeInsets(UIEdgeInsets i) { + return @{ @"top": @(i.top), @"left": @(i.left), @"bottom": @(i.bottom), @"right": @(i.right) }; +} + +static CGSize sizeFromDictionary(NSDictionary *dict) { + return (CGSize){.width = ((NSNumber *)dict[@"w"]).doubleValue, .height = ((NSNumber *)dict[@"h"]).doubleValue }; +} + +static CGPoint pointFromDictionary(NSDictionary *dict) { + return (CGPoint){.x = ((NSNumber *)dict[@"x"]).doubleValue, .y = ((NSNumber *)dict[@"y"]).doubleValue}; +} + +static CGRect rectFromDictionary(NSDictionary *dict) { + return (CGRect){.origin = pointFromDictionary(dict[@"origin"]), .size = sizeFromDictionary(dict[@"size"])}; +} + +static UIEdgeInsets edgeInsetsFromDictionary(NSDictionary *dict) { + return (UIEdgeInsets){.top = ((NSNumber *)dict[@"top"]).doubleValue, .left = ((NSNumber *)dict[@"left"]).doubleValue, .bottom = ((NSNumber *)dict[@"bottom"]).doubleValue, .right = ((NSNumber *)dict[@"right"]).doubleValue}; +} + +static NSDictionary *dictionaryFromCoordinate (CLLocationCoordinate2D coordinate) { + return @{ @"latitude": @(coordinate.latitude), @"longitude": @(coordinate.longitude) }; +} + +static CLLocationCoordinate2D coordinateFromDictionary(NSDictionary *dict) { + return (CLLocationCoordinate2D){.latitude = ((NSNumber *)dict[@"latitude"]).doubleValue, .longitude = ((NSNumber *)dict[@"longitude"]).doubleValue }; +} + +static ORKNumericAnswerStyle ORKNumericAnswerStyleFromString(NSString *s) { + return tableMapReverse(s, ORKNumericAnswerStyleTable()); +} + +static NSString *ORKNumericAnswerStyleToString(ORKNumericAnswerStyle style) { + return tableMapForward(style, ORKNumericAnswerStyleTable()); +} + +static ORKNumericAnswerStyle ORKImageChoiceAnswerStyleFromString(NSString *s) { + return tableMapReverse(s, ORKImageChoiceAnswerStyleTable()); +} + +static NSString *ORKImageChoiceAnswerStyleToString(ORKNumericAnswerStyle style) { + return tableMapForward(style, ORKImageChoiceAnswerStyleTable()); +} + +static ORKMeasurementSystem ORKMeasurementSystemFromString(NSString *s) { + return tableMapReverse(s, ORKMeasurementSystemTable()); +} + +static NSString *ORKMeasurementSystemToString(ORKMeasurementSystem measurementSystem) { + return tableMapForward(measurementSystem, ORKMeasurementSystemTable()); +} + +static NSDictionary *dictionaryFromCircularRegion(CLCircularRegion *region) { + NSDictionary *dictionary = region ? + @{ + @"coordinate": dictionaryFromCoordinate(region.center), + @"radius": @(region.radius), + @"identifier": region.identifier + } : + @{}; + return dictionary; +} + +static NSDictionary *dictionaryFromPostalAddress(CNPostalAddress *address) { + return @{ @"city": address.city, @"street": address.street }; +} + +static NSString *identifierFromClinicalType(HKClinicalType *type) { + return type.identifier; +} + +static NSString *dontKnowFakePropertyName(NSString *propertyName) { + return [noAnswerPrefix stringByAppendingString:propertyName]; +} + +static CLCircularRegion *circularRegionFromDictionary(NSDictionary *dict) { + CLCircularRegion *circularRegion; + if (dict.count == 3) { + circularRegion = [[CLCircularRegion alloc] initWithCenter:coordinateFromDictionary(dict[@"coordinate"]) + radius:((NSNumber *)dict[@"radius"]).doubleValue + identifier:dict[@"identifier"]]; + } + return circularRegion; +} + +static NSArray *arrayFromRegularExpressionOptions(NSRegularExpressionOptions regularExpressionOptions) { + NSMutableArray *optionsArray = [NSMutableArray new]; + if (regularExpressionOptions & NSRegularExpressionCaseInsensitive) { + [optionsArray addObject:@"NSRegularExpressionCaseInsensitive"]; + } + if (regularExpressionOptions & NSRegularExpressionAllowCommentsAndWhitespace) { + [optionsArray addObject:@"NSRegularExpressionAllowCommentsAndWhitespace"]; + } + if (regularExpressionOptions & NSRegularExpressionIgnoreMetacharacters) { + [optionsArray addObject:@"NSRegularExpressionIgnoreMetacharacters"]; + } + if (regularExpressionOptions & NSRegularExpressionDotMatchesLineSeparators) { + [optionsArray addObject:@"NSRegularExpressionDotMatchesLineSeparators"]; + } + if (regularExpressionOptions & NSRegularExpressionAnchorsMatchLines) { + [optionsArray addObject:@"NSRegularExpressionAnchorsMatchLines"]; + } + if (regularExpressionOptions & NSRegularExpressionUseUnixLineSeparators) { + [optionsArray addObject:@"NSRegularExpressionUseUnixLineSeparators"]; + } + if (regularExpressionOptions & NSRegularExpressionUseUnicodeWordBoundaries) { + [optionsArray addObject:@"NSRegularExpressionUseUnicodeWordBoundaries"]; + } + return [optionsArray copy]; +} + +static NSRegularExpressionOptions regularExpressionOptionsFromArray(NSArray *array) { + NSRegularExpressionOptions regularExpressionOptions = 0; + for (NSString *optionString in array) { + if ([optionString isEqualToString:@"NSRegularExpressionCaseInsensitive"]) { + regularExpressionOptions |= NSRegularExpressionCaseInsensitive; + } + else if ([optionString isEqualToString:@"NSRegularExpressionAllowCommentsAndWhitespace"]) { + regularExpressionOptions |= NSRegularExpressionAllowCommentsAndWhitespace; + } + else if ([optionString isEqualToString:@"NSRegularExpressionIgnoreMetacharacters"]) { + regularExpressionOptions |= NSRegularExpressionIgnoreMetacharacters; + } + else if ([optionString isEqualToString:@"NSRegularExpressionDotMatchesLineSeparators"]) { + regularExpressionOptions |= NSRegularExpressionDotMatchesLineSeparators; + } + else if ([optionString isEqualToString:@"NSRegularExpressionAnchorsMatchLines"]) { + regularExpressionOptions |= NSRegularExpressionAnchorsMatchLines; + } + else if ([optionString isEqualToString:@"NSRegularExpressionUseUnixLineSeparators"]) { + regularExpressionOptions |= NSRegularExpressionUseUnixLineSeparators; + } + else if ([optionString isEqualToString:@"NSRegularExpressionUseUnicodeWordBoundaries"]) { + regularExpressionOptions |= NSRegularExpressionUseUnicodeWordBoundaries; + } + } + return regularExpressionOptions; +} + +static NSDictionary *dictionaryFromRegularExpression(NSRegularExpression *regularExpression) { + NSDictionary *dictionary = regularExpression ? + @{ + @"pattern": regularExpression.pattern ?: @"", + @"options": arrayFromRegularExpressionOptions(regularExpression.options) + } : + @{}; + return dictionary; +} + +static NSRegularExpression *regularExpressionsFromDictionary(NSDictionary *dict) { + NSRegularExpression *regularExpression; + if (dict.count == 2) { + regularExpression = [NSRegularExpression regularExpressionWithPattern:dict[@"pattern"] + options:regularExpressionOptionsFromArray(dict[@"options"]) + error:nil]; + } + return regularExpression; +} + +static NSDictionary *dictionaryFromPasswordRules(UITextInputPasswordRules *passwordRules) { + NSDictionary *dictionary = passwordRules ? + @{ + @"rules": passwordRules.passwordRulesDescriptor ?: @"" + } : + @{}; + return dictionary; +} + +static UITextInputPasswordRules *passwordRulesFromDictionary(NSDictionary *dict) { + UITextInputPasswordRules *passwordRules; + if (dict.count == 1) { + passwordRules = [UITextInputPasswordRules passwordRulesWithDescriptor:dict[@"rules"]]; + } + return passwordRules; +} + +static CNPostalAddress *postalAddressFromDictionary(NSDictionary *dict) { + CNMutablePostalAddress *postalAddress = [[CNMutablePostalAddress alloc] init]; + postalAddress.city = dict[@"city"]; + postalAddress.street = dict[@"street"]; + return [postalAddress copy]; +} + +static HKClinicalType *typeFromIdentifier(NSString *identifier) { + return [HKClinicalType clinicalTypeForIdentifier:identifier]; +} + +static NSMutableDictionary *ORKESerializationEncodingTable(void); +static id propFromDict(NSDictionary *dict, NSString *propName, ORKESerializationContext *context); +static NSArray *classEncodingsForClass(Class c) ; +static id objectForJsonObject(id input, Class expectedClass, ORKESerializationJSONToObjectBlock converterBlock, ORKESerializationContext *context); + +__unused static NSInteger const SerializationVersion = 1; // Will be used moving forward as we get additional versions + +#define ESTRINGIFY2( x) #x +#define ESTRINGIFY(x) ESTRINGIFY2(x) + +#define ENTRY(entryName, bb, props) @ESTRINGIFY(entryName) : [[ORKESerializableTableEntry alloc] initWithClass:[entryName class] initBlock:bb properties: props] + +#define PROPERTY(x, vc, cc, ww, jb, ob) @ESTRINGIFY(x) : ([[ORKESerializableProperty alloc] initWithPropertyName:@ESTRINGIFY(x) valueClass:[vc class] containerClass:[cc class] writeAfterInit:ww objectToJSONBlock:jb jsonToObjectBlock:ob ]) + +#define IMAGEPROPERTY(x, cc, ww) @ESTRINGIFY(x) : imagePropertyObject(@ESTRINGIFY(x), [cc class], ww) + +#define DYNAMICCAST(x, c) ((c *) ([x isKindOfClass:[c class]] ? x : nil)) + + +@interface ORKESerializableTableEntry : NSObject + +- (instancetype)initWithClass:(Class)class + initBlock:(ORKESerializationInitBlock)initBlock + properties:(NSDictionary *)properties; + +@property (nonatomic) Class class; +@property (nonatomic, copy) ORKESerializationInitBlock initBlock; +@property (nonatomic, strong) NSMutableDictionary *properties; + +@end + +static NSString * const _SerializedBundleImageNameKey = @"imageName"; + +@implementation ORKESerializationBundleImageProvider { + NSBundle *_bundle; +} + +- (instancetype)initWithBundle:(NSBundle *)bundle { + self = [super init]; + if (self) { + _bundle = bundle; + } + return self; +} + +- (NSBundle *)bundle { + return _bundle; +} + +- (UIImage *)imageForReference:(NSDictionary *)reference { + NSString *imageName = [reference objectForKey:_SerializedBundleImageNameKey]; + + /* + * Serialization should support the use of SFSymbols as a provided imageName. + * If the imageName can be converted to an SFSymbol, the symbol will be used, + * otherwise it will attempt to find the image name in the specified bundle. + */ + UIImage *symbolImage = [UIImage systemImageNamed:imageName]; + if (symbolImage != nil) { + return symbolImage; + } + + return [UIImage imageNamed:imageName inBundle:_bundle compatibleWithTraitCollection:[UITraitCollection traitCollectionWithUserInterfaceIdiom:[UIDevice currentDevice].userInterfaceIdiom]]; +} + +// Writing to bundle is not supported: supply a placeholder +- (nullable NSDictionary *)referenceBySavingImage:(UIImage __unused *)image { + return @{_SerializedBundleImageNameKey : @""}; +} + +@end + +@interface ORKESerializableProperty : NSObject + +- (instancetype)initWithPropertyName:(NSString *)propertyName + valueClass:(Class)valueClass + containerClass:(Class)containerClass + writeAfterInit:(BOOL)writeAfterInit + objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON + jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock; + +@property (nonatomic, copy) NSString *propertyName; +@property (nonatomic) Class valueClass; +@property (nonatomic) Class containerClass; +@property (nonatomic) BOOL writeAfterInit; +@property (nonatomic, copy) ORKESerializationObjectToJSONBlock objectToJSONBlock; +@property (nonatomic, copy) ORKESerializationJSONToObjectBlock jsonToObjectBlock; + +@end + +static ORKESerializableProperty *imagePropertyObject(NSString *propertyName, + Class containerClass, + BOOL writeAfterInit) { + return [[ORKESerializableProperty alloc] initWithPropertyName:propertyName + valueClass:[UIImage class] + containerClass:containerClass + writeAfterInit:writeAfterInit + objectToJSONBlock:^id _Nullable(id object, ORKESerializationContext *context) + { + return [context.imageProvider referenceBySavingImage:object]; + } jsonToObjectBlock:^id _Nullable(id jsonObject, ORKESerializationContext *context) { + return [context.imageProvider imageForReference:jsonObject]; + }]; +} + +@implementation ORKESerializableTableEntry + +- (instancetype)initWithClass:(Class)class + initBlock:(ORKESerializationInitBlock)initBlock + properties:(NSDictionary *)properties { + self = [super init]; + if (self) { + _class = class; + self.initBlock = initBlock; + self.properties = [properties mutableCopy]; + } + return self; +} + +@end + + +@implementation ORKESerializableProperty + +- (instancetype)initWithPropertyName:(NSString *)propertyName + valueClass:(Class)valueClass + containerClass:(Class)containerClass + writeAfterInit:(BOOL)writeAfterInit + objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON + jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock { + self = [super init]; + if (self) { + self.propertyName = propertyName; + self.valueClass = valueClass; + self.containerClass = containerClass; + self.writeAfterInit = writeAfterInit; + self.objectToJSONBlock = objectToJSON; + self.jsonToObjectBlock = jsonToObjectBlock; + } + return self; +} + +@end + +@implementation ORKESerializationContext + +- (instancetype)initWithLocalizer:(nullable ORKESerializationLocalizer *)localizer + imageProvider:(nullable id)imageProvider { + self = [super init]; + if (self) { + _localizer = localizer; + _imageProvider = imageProvider; + } + return self; +} + +@end + + +static NSString *_ClassKey = @"_class"; + +static id propFromDict(NSDictionary *dict, NSString *propName, ORKESerializationContext *context) { + NSArray *classEncodings = classEncodingsForClass(NSClassFromString(dict[_ClassKey])); + ORKESerializableProperty *propertyEntry = nil; + for (ORKESerializableTableEntry *classEncoding in classEncodings) { + + NSDictionary *propertyEncoding = classEncoding.properties; + propertyEntry = propertyEncoding[propName]; + if (propertyEntry != nil) { + break; + } + } + NSCAssert(propertyEntry != nil, @"Unexpected property %@ for class %@", propName, dict[_ClassKey]); + + Class containerClass = propertyEntry.containerClass; + Class propertyClass = propertyEntry.valueClass; + ORKESerializationJSONToObjectBlock converterBlock = propertyEntry.jsonToObjectBlock; + + id input = dict[propName]; + if (input == nil) { + input = dict[dontKnowFakePropertyName(propName)]; + propertyClass = [ORKDontKnowAnswer class]; + converterBlock = nil; + } + id output = nil; + if (input != nil) { + if ([containerClass isSubclassOfClass:[NSArray class]]) { + NSMutableArray *outputArray = [NSMutableArray array]; + for (id value in DYNAMICCAST(input, NSArray)) { + id convertedValue = objectForJsonObject(value, propertyClass, converterBlock, context); + NSCAssert(convertedValue != nil, @"Could not convert to object of class %@", propertyClass); + [outputArray addObject:convertedValue]; + } + output = outputArray; + } else if ([containerClass isSubclassOfClass:[NSDictionary class]]) { + NSMutableDictionary *outputDictionary = [NSMutableDictionary dictionary]; + for (NSString *key in [DYNAMICCAST(input, NSDictionary) allKeys]) { + id convertedValue = objectForJsonObject(DYNAMICCAST(input, NSDictionary)[key], propertyClass, converterBlock, nil); + NSCAssert(convertedValue != nil, @"Could not convert to object of class %@", propertyClass); + outputDictionary[key] = convertedValue; + } + output = outputDictionary; + } else { + NSCAssert(containerClass == [NSObject class], @"Unexpected container class %@", containerClass); + + output = objectForJsonObject(input, propertyClass, converterBlock, context); + } + } + return output; +} + +@implementation ORKESerializationLocalizer + +- (instancetype)initWithBundle:(NSBundle *)bundle tableName:(NSString *)tableName { + self = [super init]; + if (self) { + self.bundle = bundle; + self.tableName = tableName; + } + return self; +} + +@end + + +#define NUMTOSTRINGBLOCK(table) ^id(id num, __unused ORKESerializationContext *context) { return table[((NSNumber *)num).unsignedIntegerValue]; } +#define STRINGTONUMBLOCK(table) ^id(id string, __unused ORKESerializationContext *context) { NSUInteger index = [table indexOfObject:string]; \ +NSCAssert(index != NSNotFound, @"Expected valid entry from table %@", table); \ +return @(index); \ +} + +@implementation ORKESerializer + +static NSArray *ORKChoiceAnswerStyleTable() { + static NSArray *table; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"singleChoice", @"multipleChoice"]; + }); + + return table; +} + +static NSArray *ORKDateAnswerStyleTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"dateTime", @"date"]; + }); + return table; +} + +static NSArray *buttonIdentifierTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"none", @"left", @"right"]; + }); + return table; +} + +static NSArray *memoryGameStatusTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"unknown", @"success", @"failure", @"timeout"]; + }); + return table; +} + +static NSArray *numberFormattingStyleTable() { + static NSArray *table = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + table = @[@"default", @"percent"]; + }); + return table; +} + +#define GETPROP(d,x) getter(d, @ESTRINGIFY(x)) +static NSMutableDictionary *ORKESerializationEncodingTable() { + static dispatch_once_t onceToken; + static NSMutableDictionary *internalEncodingTable = nil; + dispatch_once(&onceToken, ^{ + internalEncodingTable = + [@{ + ENTRY(ORKResultSelector, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKResultSelector *selector = [[ORKResultSelector alloc] initWithTaskIdentifier:GETPROP(dict, taskIdentifier) + stepIdentifier:GETPROP(dict, stepIdentifier) + resultIdentifier:GETPROP(dict, resultIdentifier)]; + return selector; + },(@{ + PROPERTY(taskIdentifier, NSString, NSObject, YES, nil, nil), + PROPERTY(stepIdentifier, NSString, NSObject, YES, nil, nil), + PROPERTY(resultIdentifier, NSString, NSObject, YES, nil, nil), + })), + ENTRY(ORKPredicateStepNavigationRule, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKPredicateStepNavigationRule *rule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:GETPROP(dict, resultPredicates) + destinationStepIdentifiers:GETPROP(dict, destinationStepIdentifiers) + defaultStepIdentifier:GETPROP(dict, defaultStepIdentifier) + validateArrays:NO]; + return rule; + },(@{ + PROPERTY(resultPredicates, NSPredicate, NSArray, NO, nil, nil), + PROPERTY(destinationStepIdentifiers, NSString, NSArray, NO, nil, nil), + PROPERTY(defaultStepIdentifier, NSString, NSObject, NO, nil, nil), + PROPERTY(additionalTaskResults, ORKTaskResult, NSArray, YES, nil, nil) + })), + ENTRY(ORKDirectStepNavigationRule, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKDirectStepNavigationRule *rule = [[ORKDirectStepNavigationRule alloc] initWithDestinationStepIdentifier:GETPROP(dict, destinationStepIdentifier)]; + return rule; + },(@{ + PROPERTY(destinationStepIdentifier, NSString, NSObject, NO, nil, nil), + })), + ENTRY(ORKAudioLevelNavigationRule, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKAudioLevelNavigationRule *rule = [[ORKAudioLevelNavigationRule alloc] initWithAudioLevelStepIdentifier:GETPROP(dict, audioLevelStepIdentifier) destinationStepIdentifier:GETPROP(dict, destinationStepIdentifier) + recordingSettings:GETPROP(dict, recordingSettings)]; + return rule; + },(@{ + PROPERTY(audioLevelStepIdentifier, NSString, NSObject, NO, nil, nil), + PROPERTY(destinationStepIdentifier, NSString, NSObject, NO, nil, nil), + PROPERTY(recordingSettings, NSDictionary, NSObject, NO, nil, nil), + })), + ENTRY(ORKOrderedTask, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:GETPROP(dict, identifier) + steps:GETPROP(dict, steps)]; + return task; + },(@{ + PROPERTY(identifier, NSString, NSObject, NO, nil, nil), + PROPERTY(steps, ORKStep, NSArray, NO, nil, nil) + })), + ENTRY(ORKNavigableOrderedTask, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:GETPROP(dict, identifier) + steps:GETPROP(dict, steps)]; + return task; + },(@{ + PROPERTY(stepNavigationRules, ORKStepNavigationRule, NSMutableDictionary, YES, nil, nil), + PROPERTY(skipStepNavigationRules, ORKSkipStepNavigationRule, NSMutableDictionary, YES, nil, nil), + PROPERTY(stepModifiers, ORKStepModifier, NSMutableDictionary, YES, nil, nil), + PROPERTY(shouldReportProgress, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKStep *step = [[ORKStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + return step; + }, + (@{ + PROPERTY(identifier, NSString, NSObject, NO, nil, nil), + PROPERTY(optional, NSNumber, NSObject, YES, nil, nil), + PROPERTY(title, NSString, NSObject, YES, nil, nil), + PROPERTY(text, NSString, NSObject, YES, nil, nil), + PROPERTY(detailText, NSString, NSObject, YES, nil, nil), + PROPERTY(headerTextAlignment, NSNumber, NSObject, YES, nil, nil), + PROPERTY(footnote, NSString, NSObject, YES, nil, nil), + PROPERTY(shouldTintImages, NSNumber, NSObject, YES, nil, nil), + PROPERTY(useSurveyMode, NSNumber, NSObject, YES, nil, nil), + PROPERTY(bodyItems, ORKBodyItem, NSArray, YES, nil, nil), + PROPERTY(imageContentMode, NSNumber, NSObject, YES, nil, nil), + IMAGEPROPERTY(iconImage, NSObject, YES), + IMAGEPROPERTY(auxiliaryImage, NSObject, YES), + IMAGEPROPERTY(image, NSObject, YES), + PROPERTY(bodyItemTextAlignment, NSNumber, NSObject, YES, nil, nil), + PROPERTY(buildInBodyItems, NSNumber, NSObject, YES, nil, nil), + PROPERTY(useExtendedPadding, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKBodyItem, + ^id(__unused NSDictionary *dict, __unused ORKESerializationPropertyGetter getter) { + ORKBodyItem *bodyItem = [[ORKBodyItem alloc] initWithText:GETPROP(dict, text) + detailText:GETPROP(dict, detailText) + image:nil + learnMoreItem:GETPROP(dict, learnMoreItem) + bodyItemStyle:[GETPROP(dict, bodyItemStyle) intValue] + useCardStyle:GETPROP(dict, useCardStyle)]; + return bodyItem; + }, + (@{ + PROPERTY(text, NSString, NSObject, NO, nil, nil), + PROPERTY(detailText, NSString, NSObject, NO, nil, nil), + PROPERTY(bodyItemStyle, NSNumber, NSObject, NO, nil, nil), + IMAGEPROPERTY(image, NSObject, YES), + PROPERTY(learnMoreItem, ORKLearnMoreItem, NSObject, YES, nil, nil), + PROPERTY(useCardStyle, NSNumber, NSObject, YES, nil, nil), + PROPERTY(useSecondaryColor, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKLearnMoreItem, + ^id(__unused NSDictionary *dict, __unused ORKESerializationPropertyGetter getter) { + ORKLearnMoreItem *learnMoreItem = [[ORKLearnMoreItem alloc] initWithText:GETPROP(dict, text) learnMoreInstructionStep:GETPROP(dict, learnMoreInstructionStep)]; + return learnMoreItem; + }, + (@{ + PROPERTY(text, NSString, NSObject, YES, nil, nil), + PROPERTY(learnMoreInstructionStep, ORKLearnMoreInstructionStep, NSObject, YES, nil, nil), + })), + ENTRY(ORKReviewStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKReviewStep *reviewStep = [ORKReviewStep standaloneReviewStepWithIdentifier:GETPROP(dict, identifier) + steps:GETPROP(dict, steps) + resultSource:GETPROP(dict, resultSource)]; + return reviewStep; + }, + (@{ + PROPERTY(steps, ORKStep, NSArray, NO, nil, nil), + PROPERTY(resultSource, ORKTaskResult, NSObject, NO, nil, nil), + PROPERTY(excludeInstructionSteps, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKVisualConsentStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKVisualConsentStep alloc] initWithIdentifier:GETPROP(dict, identifier) + document:GETPROP(dict, consentDocument)]; + }, + @{ + PROPERTY(consentDocument, ORKConsentDocument, NSObject, NO, nil, nil) + }), + ENTRY(ORKPDFViewerStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKPDFViewerStep alloc] initWithIdentifier:GETPROP(dict, identifier) + pdfURL:GETPROP(dict, pdfURL)]; + }, + (@{ + PROPERTY(pdfURL, NSURL, NSObject, YES, + ^id(id url, __unused ORKESerializationContext *context) { return [(NSURL *)url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }), + PROPERTY(actionBarOption, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKPasscodeStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKPasscodeStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(passcodeType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(useBiometrics, NSNumber, NSObject, YES, nil, nil), + PROPERTY(passcodeFlow, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKWaitStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKWaitStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(indicatorType, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKRecorderConfiguration *recorderConfiguration = [[ORKRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier)]; + return recorderConfiguration; + }, + (@{ + PROPERTY(identifier, NSString, NSObject, NO, nil, nil), + })), + ENTRY(ORKQuestionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKQuestionStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(answerFormat, ORKAnswerFormat, NSObject, YES, nil, nil), + PROPERTY(placeholder, NSString, NSObject, YES, nil, nil), + PROPERTY(question, NSString, NSObject, YES, nil, nil), + PROPERTY(useCardView, NSNumber, NSObject, YES, nil, nil), + PROPERTY(learnMoreItem, ORKLearnMoreItem, NSObject, YES, nil, nil), + PROPERTY(tagText, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKInstructionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKInstructionStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(detailText, NSString, NSObject, YES, nil, nil), + PROPERTY(footnote, NSString, NSObject, YES, nil, nil), + PROPERTY(centerImageVertically, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKLearnMoreInstructionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKLearnMoreInstructionStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKLearnMoreItem, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKLearnMoreItem alloc] initWithText:GETPROP(dict, text) learnMoreInstructionStep:GETPROP(dict, learnMoreInstructionStep)]; + }, + (@{ + PROPERTY(text, NSString, NSObject, YES, nil, nil), + PROPERTY(learnMoreInstructionStep, ORKLearnMoreInstructionStep, NSObject, YES, nil, nil) + })), + ENTRY(ORKSecondaryTaskStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKSecondaryTaskStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(secondaryTask, ORKOrderedTask, NSObject, YES, nil, nil), + PROPERTY(secondaryTaskButtonTitle, NSString, NSObject, YES, nil, nil), + PROPERTY(nextButtonTitle, NSString, NSObject, YES, nil, nil), + PROPERTY(requiredAttempts, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKVideoInstructionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKVideoInstructionStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(videoURL, NSURL, NSObject, YES, + ^id(id url, __unused ORKESerializationContext *context) { return [(NSURL *)url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }), + PROPERTY(thumbnailTime, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKCompletionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKCompletionStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKCountdownStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKCountdownStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKTouchAnywhereStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTouchAnywhereStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKWebViewStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKWebViewStep *step = [[ORKWebViewStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + return step; + }, + (@{ + PROPERTY(html, NSString, NSObject, YES, nil, nil), + PROPERTY(customCSS, NSString, NSObject, YES, nil, nil), + PROPERTY(showSignatureAfterContent, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKWebViewStepResult, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKWebViewStepResult *result = [[ORKWebViewStepResult alloc] initWithIdentifier:GETPROP(dict, identifier)]; + return result; + }, + (@{ + PROPERTY(result, NSString, NSObject, YES, nil, nil), + })), + ENTRY(ORKHealthQuantityTypeRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHealthQuantityTypeRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) healthQuantityType:GETPROP(dict, quantityType) unit:GETPROP(dict, unit)]; + }, + (@{ + PROPERTY(quantityType, HKQuantityType, NSObject, NO, + ^id(id type, __unused ORKESerializationContext *context) { return [(HKQuantityType *)type identifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [HKQuantityType quantityTypeForIdentifier:string]; }), + PROPERTY(unit, HKUnit, NSObject, NO, + ^id(id unit, __unused ORKESerializationContext *context) { return [(HKUnit *)unit unitString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [HKUnit unitFromString:string]; }), + })), + ENTRY(ORKActiveStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKActiveStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(stepDuration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldShowDefaultTimer, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldSpeakCountDown, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldSpeakRemainingTimeAtHalfway, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldStartTimerAutomatically, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldPlaySoundOnStart, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldPlaySoundOnFinish, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldVibrateOnStart, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldVibrateOnFinish, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldUseNextAsSkipButton, NSNumber, NSObject, YES, nil, nil), + PROPERTY(shouldContinueOnFinish, NSNumber, NSObject, YES, nil, nil), + PROPERTY(spokenInstruction, NSString, NSObject, YES, nil, nil), + PROPERTY(finishedSpokenInstruction, NSString, NSObject, YES, nil, nil), + PROPERTY(recorderConfigurations, ORKRecorderConfiguration, NSArray, YES, nil, nil), + })), + ENTRY(ORKAudioStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKAudioStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKToneAudiometryStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKToneAudiometryStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + ((@{ + PROPERTY(toneDuration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(practiceStep, NSNumber, NSObject, YES, nil, nil), + }))), + ENTRY(ORKdBHLToneAudiometryStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKdBHLToneAudiometryStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(toneDuration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(maxRandomPreStimulusDelay, NSNumber, NSObject, YES, nil, nil), + PROPERTY(postStimulusDelay, NSNumber, NSObject, YES, nil, nil), + PROPERTY(maxNumberOfTransitionsPerFrequency, NSNumber, NSObject, YES, nil, nil), + PROPERTY(initialdBHLValue, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLStepUpSize, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLStepUpSizeFirstMiss, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLStepUpSizeSecondMiss, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLStepUpSizeThirdMiss, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLStepDownSize, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dBHLMinimumThreshold, NSNumber, NSObject, YES, nil, nil), + PROPERTY(headphoneType, NSString, NSObject, YES, nil, nil), + PROPERTY(earPreference, NSNumber, NSObject, YES, nil, nil), + PROPERTY(frequencyList, NSArray, NSObject, YES, nil, nil) + })), + ENTRY(ORKHolePegTestPlaceStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHolePegTestPlaceStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(movingDirection, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dominantHandTested, NSNumber, NSObject, YES, nil, nil), + PROPERTY(numberOfPegs, NSNumber, NSObject, YES, nil, nil), + PROPERTY(threshold, NSNumber, NSObject, YES, nil, nil), + PROPERTY(rotated, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKHolePegTestRemoveStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHolePegTestRemoveStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(movingDirection, NSNumber, NSObject, YES, nil, nil), + PROPERTY(dominantHandTested, NSNumber, NSObject, YES, nil, nil), + PROPERTY(numberOfPegs, NSNumber, NSObject, YES, nil, nil), + PROPERTY(threshold, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKImageCaptureStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKImageCaptureStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(templateImageInsets, NSValue, NSObject, YES, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromUIEdgeInsets(((NSValue *)value).UIEdgeInsetsValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithUIEdgeInsets:edgeInsetsFromDictionary(dict)]; }), + PROPERTY(accessibilityHint, NSString, NSObject, YES, nil, nil), + PROPERTY(accessibilityInstructions, NSString, NSObject, YES, nil, nil), + PROPERTY(captureRaw, NSNumber, NSObject, YES, nil, nil), + IMAGEPROPERTY(templateImage, NSObject, YES), + })), + ENTRY(ORKVideoCaptureStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKVideoCaptureStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(templateImageInsets, NSValue, NSObject, YES, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromUIEdgeInsets(((NSValue *)value).UIEdgeInsetsValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithUIEdgeInsets:edgeInsetsFromDictionary(dict)]; }), + PROPERTY(duration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(audioMute, NSNumber, NSObject, YES, nil, nil), + PROPERTY(torchMode, NSNumber, NSObject, YES, nil, nil), + PROPERTY(devicePosition, NSNumber, NSObject, YES, nil, nil), + PROPERTY(accessibilityHint, NSString, NSObject, YES, nil, nil), + PROPERTY(accessibilityInstructions, NSString, NSObject, YES, nil, nil), + IMAGEPROPERTY(templateImage, NSObject, YES), + })), + ENTRY(ORKSignatureStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKSignatureStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKSpatialSpanMemoryStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKSpatialSpanMemoryStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(initialSpan, NSNumber, NSObject, YES, nil, nil), + PROPERTY(minimumSpan, NSNumber, NSObject, YES, nil, nil), + PROPERTY(maximumSpan, NSNumber, NSObject, YES, nil, nil), + PROPERTY(playSpeed, NSNumber, NSObject, YES, nil, nil), + PROPERTY(maximumTests, NSNumber, NSObject, YES, nil, nil), + PROPERTY(maximumConsecutiveFailures, NSNumber, NSObject, YES, nil, nil), + PROPERTY(requireReversal, NSNumber, NSObject, YES, nil, nil), + PROPERTY(customTargetPluralName, NSString, NSObject, YES, nil, nil), + IMAGEPROPERTY(customTargetImage, NSObject, YES), + })), + ENTRY(ORKWalkingTaskStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKWalkingTaskStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(numberOfStepsPerLeg, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKTableStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTableStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + ((@{ + PROPERTY(items, NSObject, NSArray, YES, nil, nil), + PROPERTY(isBulleted, NSNumber, NSObject, YES, nil, nil), + PROPERTY(bulletIconNames, NSString, NSArray, YES, nil, nil), + PROPERTY(allowsSelection, NSNumber, NSObject, YES, nil, nil), + PROPERTY(bulletType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(pinNavigationContainer, NSNumber, NSObject, YES, nil, nil) + }))), + ENTRY(ORKTimedWalkStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTimedWalkStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(distanceInMeters, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKPSATStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKPSATStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(presentationMode, NSNumber, NSObject, YES, nil, nil), + PROPERTY(interStimulusInterval, NSNumber, NSObject, YES, nil, nil), + PROPERTY(stimulusDuration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(seriesLength, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKRangeOfMotionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKRangeOfMotionStep alloc] initWithIdentifier:GETPROP(dict, identifier) limbOption:(NSUInteger)[GETPROP(dict, identifier) integerValue]]; + }, + (@{ + PROPERTY(limbOption, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKReactionTimeStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKReactionTimeStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(maximumStimulusInterval, NSNumber, NSObject, YES, nil, nil), + PROPERTY(minimumStimulusInterval, NSNumber, NSObject, YES, nil, nil), + PROPERTY(timeout, NSNumber, NSObject, YES, nil, nil), + PROPERTY(numberOfAttempts, NSNumber, NSObject, YES, nil, nil), + PROPERTY(thresholdAcceleration, NSNumber, NSObject, YES, nil, nil), + PROPERTY(successSound, NSNumber, NSObject, YES, nil, nil), + PROPERTY(timeoutSound, NSNumber, NSObject, YES, nil, nil), + PROPERTY(failureSound, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKStroopStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKStroopStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(numberOfAttempts, NSNumber, NSObject, YES, nil, nil)})), + ENTRY(ORKTappingIntervalStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTappingIntervalStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKTrailmakingStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTrailmakingStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(trailType, NSString, NSObject, YES, nil, nil), + })), + ENTRY(ORKTowerOfHanoiStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTowerOfHanoiStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(numberOfDisks, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKSpeechInNoiseStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKSpeechInNoiseStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + ((@{ + PROPERTY(speechFileNameWithExtension, NSString, NSObject, YES, nil, nil), + PROPERTY(noiseFileNameWithExtension, NSString, NSObject, YES, nil, nil), + PROPERTY(filterFileNameWithExtension, NSString, NSObject, YES, nil, nil), + PROPERTY(gainAppliedToNoise, NSNumber, NSObject, YES, nil, nil), + PROPERTY(willAudioLoop, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideGraphView, NSNumber, NSObject, YES, nil, nil), + }))), + ENTRY(ORKSpeechRecognitionStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKSpeechRecognitionStep alloc] initWithIdentifier:GETPROP(dict, identifier) image:nil text:GETPROP(dict, speechRecognitionText)]; + }, + (@{ + PROPERTY(shouldHideTranscript, NSNumber, NSObject, YES, nil, nil), + PROPERTY(speechRecognitionText, NSString, NSObject, NO, nil, nil), + PROPERTY(speechRecognizerLocale, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKEnvironmentSPLMeterStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKEnvironmentSPLMeterStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(thresholdValue, NSNumber, NSObject, YES, nil, nil), + PROPERTY(samplingInterval, NSNumber, NSObject, YES, nil, nil), + PROPERTY(requiredContiguousSamples, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKEnvironmentSPLMeterResult, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKEnvironmentSPLMeterResult alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(sensitivityOffset, NSNumber, NSObject, YES, nil, nil), + PROPERTY(recordedSPLMeterSamples, NSNumber, NSArray, YES, nil, nil) + })), + ENTRY(ORKStreamingAudioRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKStreamingAudioRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKAccelerometerRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) frequency:((NSNumber *)GETPROP(dict, frequency)).doubleValue]; + }, + (@{ + PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKAudioRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKAudioRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) recorderSettings:GETPROP(dict, recorderSettings)]; + }, + (@{ + PROPERTY(recorderSettings, NSDictionary, NSObject, NO, nil, nil), + })), + ENTRY(ORKAmslerGridStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKAmslerGridStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(eyeSide, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKAmslerGridResult, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKAmslerGridResult alloc] initWithIdentifier:GETPROP(dict, identifier)image:[UIImage new] path:GETPROP(dict, path) eyeSide:(ORKAmslerGridEyeSide)[GETPROP(dict, eyeSide) integerValue]]; + }, + (@{ + PROPERTY(eyeSide, NSNumber, NSObject, NO, nil, nil), + PROPERTY(path, UIBezierPath, NSArray, NO, nil, nil), + IMAGEPROPERTY(image, NSObject, YES), + })), + ENTRY(ORKConsentDocument, + nil, + (@{ + PROPERTY(title, NSString, NSObject, NO, nil, nil), + PROPERTY(sections, ORKConsentSection, NSArray, NO, nil, nil), + PROPERTY(signaturePageTitle, NSString, NSObject, NO, nil, nil), + PROPERTY(signaturePageContent, NSString, NSObject, NO, nil, nil), + PROPERTY(signatures, ORKConsentSignature, NSArray, NO, nil, nil), + PROPERTY(htmlReviewContent, NSString, NSObject, NO, nil, nil), + })), + ENTRY(ORKConsentSharingStep, + ^(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKConsentSharingStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(localizedLearnMoreHTMLContent, NSString, NSObject, YES, nil, nil), + })), + ENTRY(ORKConsentReviewStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKConsentReviewStep alloc] initWithIdentifier:GETPROP(dict, identifier) signature:GETPROP(dict, signature) inDocument:GETPROP(dict,consentDocument)]; + }, + (@{ + PROPERTY(consentDocument, ORKConsentDocument, NSObject, NO, nil, nil), + PROPERTY(reasonForConsent, NSString, NSObject, YES, nil, nil), + PROPERTY(signature, ORKConsentSignature, NSObject, NO, nil, nil), + PROPERTY(requiresScrollToBottom, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKFitnessStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKFitnessStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + })), + ENTRY(ORKConsentSection, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKConsentSection alloc] initWithType:((NSNumber *)GETPROP(dict, type)).integerValue]; + }, + (@{ + PROPERTY(type, NSNumber, NSObject, NO, nil, nil), + PROPERTY(title, NSString, NSObject, YES, nil, nil), + PROPERTY(formalTitle, NSString, NSObject, YES, nil, nil), + PROPERTY(summary, NSString, NSObject, YES, nil, nil), + PROPERTY(content, NSString, NSObject, YES, nil, nil), + PROPERTY(htmlContent, NSString, NSObject, YES, nil, nil), + PROPERTY(contentURL, NSURL, NSObject, YES, + ^id(id url, __unused ORKESerializationContext *context) { return [(NSURL *)url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }), + PROPERTY(customLearnMoreButtonTitle, NSString, NSObject, YES, nil, nil), + PROPERTY(customAnimationURL, NSURL, NSObject, YES, + ^id(id url, __unused ORKESerializationContext *context) { return [(NSURL *)url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }), + PROPERTY(omitFromDocument, NSNumber, NSObject, YES, nil, nil), + IMAGEPROPERTY(customImage, NSObject, YES), + })), + ENTRY(ORKConsentSignature, + nil, + (@{ + PROPERTY(identifier, NSString, NSObject, YES, nil, nil), + PROPERTY(title, NSString, NSObject, YES, nil, nil), + PROPERTY(givenName, NSString, NSObject, YES, nil, nil), + PROPERTY(familyName, NSString, NSObject, YES, nil, nil), + PROPERTY(signatureDate, NSString, NSObject, YES, nil, nil), + PROPERTY(requiresName, NSNumber, NSObject, YES, nil, nil), + PROPERTY(requiresSignatureImage, NSNumber, NSObject, YES, nil, nil), + PROPERTY(signatureDateFormatString, NSString, NSObject, YES, nil, nil), + IMAGEPROPERTY(signatureImage, NSObject, YES), + })), + ENTRY(ORKRegistrationStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKRegistrationStep alloc] initWithIdentifier:GETPROP(dict, identifier) title:GETPROP(dict, title) text:GETPROP(dict, text) options:(NSUInteger)((NSNumber *)GETPROP(dict, options)).integerValue]; + }, + (@{ + PROPERTY(options, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKVerificationStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKVerificationStep alloc] initWithIdentifier:GETPROP(dict, identifier) text:GETPROP(dict, text) verificationViewControllerClass:NSClassFromString(GETPROP(dict, verificationViewControllerString))]; + }, + (@{ + PROPERTY(verificationViewControllerString, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKLoginStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKLoginStep alloc] initWithIdentifier:GETPROP(dict, identifier) title:GETPROP(dict, title) text:GETPROP(dict, text) loginViewControllerClass:NSClassFromString(GETPROP(dict, loginViewControllerString))]; + }, + (@{ + PROPERTY(loginViewControllerString, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKDeviceMotionRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKDeviceMotionRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) frequency:((NSNumber *)GETPROP(dict, frequency)).doubleValue]; + }, + (@{ + PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKdBHLToneAudiometryOnboardingStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKdBHLToneAudiometryOnboardingStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(useCardView, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKFormStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKFormStep alloc] initWithIdentifier:GETPROP(dict, identifier)]; + }, + (@{ + PROPERTY(formItems, ORKFormItem, NSArray, YES, nil, nil), + PROPERTY(footnote, NSString, NSObject, YES, nil, nil), + PROPERTY(useCardView, NSNumber, NSObject, YES, nil, nil), + PROPERTY(footerText, NSString, NSObject, YES, nil, nil), + PROPERTY(cardViewStyle, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKFormItem, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKFormItem alloc] initWithIdentifier:GETPROP(dict, identifier) text:GETPROP(dict, text) answerFormat:GETPROP(dict, answerFormat)]; + }, + (@{ + PROPERTY(identifier, NSString, NSObject, NO, nil, nil), + PROPERTY(optional, NSNumber, NSObject, YES, nil, nil), + PROPERTY(showsProgress, NSNumber, NSObject, YES, nil, nil), + PROPERTY(text, NSString, NSObject, NO, nil, nil), + PROPERTY(detailText, NSString, NSObject, YES, nil, nil), + PROPERTY(placeholder, NSString, NSObject, YES, nil, nil), + PROPERTY(answerFormat, ORKAnswerFormat, NSObject, NO, nil, nil), + PROPERTY(learnMoreItem, ORKLearnMoreItem, NSObject, YES, nil, nil), + PROPERTY(tagText, NSString, NSObject, YES, nil, nil), + })), + ENTRY(ORKPageStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKPageStep *step = [[ORKPageStep alloc] initWithIdentifier:GETPROP(dict, identifier) pageTask:GETPROP(dict, pageTask)]; + return step; + }, + (@{ + PROPERTY(pageTask, ORKOrderedTask, NSObject, NO, nil, nil), + })), + ENTRY(ORKNavigablePageStep, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKNavigablePageStep *step = [[ORKNavigablePageStep alloc] initWithIdentifier:GETPROP(dict, identifier) pageTask:GETPROP(dict, pageTask)]; + return step; + }, + (@{ + PROPERTY(pageTask, ORKOrderedTask, NSObject, NO, nil, nil), + })), + ENTRY(ORKHealthKitCharacteristicTypeAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHealthKitCharacteristicTypeAnswerFormat alloc] initWithCharacteristicType:GETPROP(dict, characteristicType)]; + }, + (@{ + PROPERTY(characteristicType, HKCharacteristicType, NSObject, NO, + ^id(id type, __unused ORKESerializationContext *context) { return [(HKCharacteristicType *)type identifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [HKCharacteristicType characteristicTypeForIdentifier:string]; }), + PROPERTY(defaultDate, NSDate, NSObject, YES, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(minimumDate, NSDate, NSObject, YES, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(maximumDate, NSDate, NSObject, YES, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(calendar, NSCalendar, NSObject, YES, + ^id(id calendar, __unused ORKESerializationContext *context) { return [(NSCalendar *)calendar calendarIdentifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSCalendar calendarWithIdentifier:string]; }), + PROPERTY(shouldRequestAuthorization, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKHealthKitQuantityTypeAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHealthKitQuantityTypeAnswerFormat alloc] initWithQuantityType:GETPROP(dict, quantityType) unit:GETPROP(dict, unit) style:((NSNumber *)GETPROP(dict, numericAnswerStyle)).integerValue]; + }, + (@{ + PROPERTY(unit, HKUnit, NSObject, NO, + ^id(id unit, __unused ORKESerializationContext *context) { return [(HKUnit *)unit unitString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [HKUnit unitFromString:string]; }), + PROPERTY(quantityType, HKQuantityType, NSObject, NO, + ^id(id type, __unused ORKESerializationContext *context) { return [(HKQuantityType *)type identifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [HKQuantityType quantityTypeForIdentifier:string]; }), + PROPERTY(numericAnswerStyle, NSNumber, NSObject, NO, + ^id(id num, __unused ORKESerializationContext *context) { return ORKNumericAnswerStyleToString(((NSNumber *)num).integerValue); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(ORKNumericAnswerStyleFromString(string)); }), + PROPERTY(shouldRequestAuthorization, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKAnswerFormat, + nil, + (@{ + PROPERTY(showDontKnowButton, NSNumber, NSObject, YES, nil, nil), + PROPERTY(customDontKnowButtonText, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKDontKnowAnswer, + nil, + (@{ + })), + ENTRY(ORKValuePickerAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKValuePickerAnswerFormat alloc] initWithTextChoices:GETPROP(dict, textChoices)]; + }, + (@{ + PROPERTY(textChoices, ORKTextChoice, NSArray, NO, nil, nil), + })), + ENTRY(ORKMultipleValuePickerAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKMultipleValuePickerAnswerFormat alloc] initWithValuePickers:GETPROP(dict, valuePickers) separator:GETPROP(dict, separator)]; + }, + (@{ + PROPERTY(valuePickers, ORKValuePickerAnswerFormat, NSArray, NO, nil, nil), + PROPERTY(separator, NSString, NSObject, NO, nil, nil), + })), + ENTRY(ORKImageChoiceAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKImageChoiceAnswerFormat alloc] initWithImageChoices:GETPROP(dict, imageChoices) style:((NSNumber *)GETPROP(dict, style)).integerValue vertical:((NSNumber *)GETPROP(dict, vertical)).boolValue]; + }, + (@{ + PROPERTY(imageChoices, ORKImageChoice, NSArray, NO, nil, nil), + PROPERTY(style, NSNumber, NSObject, NO, + ^id(id number, __unused ORKESerializationContext *context) { return ORKImageChoiceAnswerStyleToString(((NSNumber *)number).integerValue); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(ORKImageChoiceAnswerStyleFromString(string)); }), + PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKTextChoiceAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTextChoiceAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue textChoices:GETPROP(dict, textChoices)]; + }, + (@{ + PROPERTY(style, NSNumber, NSObject, NO, NUMTOSTRINGBLOCK(ORKChoiceAnswerStyleTable()), STRINGTONUMBLOCK(ORKChoiceAnswerStyleTable())), + PROPERTY(textChoices, ORKTextChoice, NSArray, NO, nil, nil), + })), + ENTRY(ORKTextChoice, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTextChoice alloc] initWithText:GETPROP(dict, text) detailText:GETPROP(dict, detailText) value:GETPROP(dict, value) exclusive:((NSNumber *)GETPROP(dict, exclusive)).boolValue]; + }, + (@{ + PROPERTY(text, NSString, NSObject, NO, nil, nil), + PROPERTY(value, NSObject, NSObject, NO, nil, nil), + PROPERTY(detailText, NSString, NSObject, NO, nil, nil), + PROPERTY(exclusive, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKTextChoiceOther, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTextChoiceOther alloc] initWithText:GETPROP(dict, text) primaryTextAttributedString:nil detailText:GETPROP(dict, detailText) detailTextAttributedString:nil value:GETPROP(dict, value) exclusive:((NSNumber *)GETPROP(dict, exclusive)).boolValue textViewPlaceholderText:GETPROP(dict, textViewPlaceholderText) textViewInputOptional:((NSNumber *)GETPROP(dict, textViewInputOptional)).boolValue textViewStartsHidden:((NSNumber *)GETPROP(dict, textViewStartsHidden)).boolValue]; + }, + (@{ + PROPERTY(textViewPlaceholderText, NSString, NSObject, NO, nil, nil), + PROPERTY(textViewInputOptional, NSNumber, NSObject, NO, nil, nil), + PROPERTY(textViewStartsHidden, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKImageChoice, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKImageChoice alloc] initWithNormalImage:nil selectedImage:nil text:GETPROP(dict, text) value:GETPROP(dict, value)]; + }, + (@{ + PROPERTY(text, NSString, NSObject, NO, nil, nil), + PROPERTY(value, NSObject, NSObject, NO, nil, nil), + IMAGEPROPERTY(normalStateImage, NSObject, YES), + IMAGEPROPERTY(selectedStateImage, NSObject, YES), + })), + ENTRY(ORKTimeOfDayAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTimeOfDayAnswerFormat alloc] initWithDefaultComponents:GETPROP(dict, defaultComponents)]; + }, + (@{ + PROPERTY(defaultComponents, NSDateComponents, NSObject, NO, + ^id(id components, __unused ORKESerializationContext *context) { return ORKTimeOfDayStringFromComponents(components); }, + ^id(id string, __unused ORKESerializationContext *context) { return ORKTimeOfDayComponentsFromString(string); }), + PROPERTY(minuteInterval, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKDateAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKDateAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue defaultDate:GETPROP(dict, defaultDate) minimumDate:GETPROP(dict, minimumDate) maximumDate:GETPROP(dict, maximumDate) calendar:GETPROP(dict, calendar)]; + }, + (@{ + PROPERTY(style, NSNumber, NSObject, NO, + NUMTOSTRINGBLOCK(ORKDateAnswerStyleTable()), + STRINGTONUMBLOCK(ORKDateAnswerStyleTable())), + PROPERTY(calendar, NSCalendar, NSObject, NO, + ^id(id calendar, __unused ORKESerializationContext *context) { return [(NSCalendar *)calendar calendarIdentifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSCalendar calendarWithIdentifier:string]; }), + PROPERTY(minimumDate, NSDate, NSObject, NO, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(maximumDate, NSDate, NSObject, NO, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(defaultDate, NSDate, NSObject, NO, + ^id(id date, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() stringFromDate:date]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [ORKResultDateTimeFormatter() dateFromString:string]; }), + PROPERTY(minuteInterval, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKNumericAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + ORKNumericAnswerFormat *format = [[ORKNumericAnswerFormat alloc] initWithStyle:((NSNumber *)GETPROP(dict, style)).integerValue + unit:GETPROP(dict, unit) + minimum:GETPROP(dict, minimum) + maximum:GETPROP(dict, maximum) + maximumFractionDigits:GETPROP(dict, maximumFractionDigits)]; + format.defaultNumericAnswer = GETPROP(dict, defaultNumericAnswer); + return format; + }, + (@{ + PROPERTY(style, NSNumber, NSObject, NO, + ^id(id num, __unused ORKESerializationContext *context) { return ORKNumericAnswerStyleToString(((NSNumber *)num).integerValue); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(ORKNumericAnswerStyleFromString(string)); }), + PROPERTY(unit, NSString, NSObject, NO, nil, nil), + PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximumFractionDigits, NSNumber, NSObject, NO, nil, nil), + PROPERTY(defaultNumericAnswer, NSNumber, NSObject, NO, nil, nil), + PROPERTY(hideUnitWhenAnswerIsEmpty, NSNumber, NSObject, YES, nil, nil), + PROPERTY(placeholder, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKScaleAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + NSNumber *defaultValue = (NSNumber *)GETPROP(dict, defaultValue); + // FIXME:- We are adding this for scenarios where the payload does not have the "defaultValue" key + if (defaultValue == nil) { + defaultValue = [[NSNumber alloc] initWithInt:INT_MAX]; + } + return [[ORKScaleAnswerFormat alloc] initWithMaximumValue:((NSNumber *)GETPROP(dict, maximum)).integerValue + minimumValue:((NSNumber *)GETPROP(dict, minimum)).integerValue + defaultValue:defaultValue.integerValue + step:((NSNumber *)GETPROP(dict, step)).integerValue + vertical:((NSNumber *)GETPROP(dict, vertical)).boolValue + maximumValueDescription:GETPROP(dict, maximumValueDescription) + minimumValueDescription:GETPROP(dict, minimumValueDescription)]; + }, + (@{ + PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(defaultValue, NSNumber, NSObject, NO, nil, nil), + PROPERTY(step, NSNumber, NSObject, NO, nil, nil), + PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximumValueDescription, NSString, NSObject, NO, nil, nil), + PROPERTY(minimumValueDescription, NSString, NSObject, NO, nil, nil), + PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil), + PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil), + PROPERTY(hideSelectedValue, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideRanges, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideLabels, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideValueMarkers, NSNumber, NSObject, YES, nil, nil), + IMAGEPROPERTY(minimumImage, NSObject, YES), + IMAGEPROPERTY(maximumImage, NSObject, YES), + })), + ENTRY(ORKContinuousScaleAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + NSNumber *defaultValue = (NSNumber *)GETPROP(dict, defaultValue); + // FIXME:- We are adding this for scenarios where the payload does not have the "defaultValue" key + if (defaultValue == nil) { + defaultValue = [[NSNumber alloc] initWithDouble:DBL_MAX]; + } + return [[ORKContinuousScaleAnswerFormat alloc] initWithMaximumValue:((NSNumber *)GETPROP(dict, maximum)).doubleValue + minimumValue:((NSNumber *)GETPROP(dict, minimum)).doubleValue + defaultValue:defaultValue.doubleValue + maximumFractionDigits:((NSNumber *)GETPROP(dict, maximumFractionDigits)).integerValue + vertical:((NSNumber *)GETPROP(dict, vertical)).boolValue + maximumValueDescription:GETPROP(dict, maximumValueDescription) + minimumValueDescription:GETPROP(dict, minimumValueDescription)]; + }, + (@{ + PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(defaultValue, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximumFractionDigits, NSNumber, NSObject, NO, nil, nil), + PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil), + PROPERTY(numberStyle, NSNumber, NSObject, YES, + ^id(id numeric, __unused ORKESerializationContext *context) { return tableMapForward(((NSNumber *)numeric).integerValue, numberFormattingStyleTable()); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(tableMapReverse(string, numberFormattingStyleTable())); }), + PROPERTY(maximumValueDescription, NSString, NSObject, NO, nil, nil), + PROPERTY(minimumValueDescription, NSString, NSObject, NO, nil, nil), + PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil), + PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil), + PROPERTY(hideSelectedValue, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideRanges, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideLabels, NSNumber, NSObject, YES, nil, nil), + IMAGEPROPERTY(minimumImage, NSObject, YES), + IMAGEPROPERTY(maximumImage, NSObject, YES), + })), + ENTRY(ORKTextScaleAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTextScaleAnswerFormat alloc] initWithTextChoices:GETPROP(dict, textChoices) defaultIndex:(NSInteger)[GETPROP(dict, defaultIndex) doubleValue] vertical:[GETPROP(dict, vertical) boolValue]]; + }, + (@{ + PROPERTY(textChoices, ORKTextChoice, NSArray, NO, nil, nil), + PROPERTY(defaultIndex, NSNumber, NSObject, NO, nil, nil), + PROPERTY(vertical, NSNumber, NSObject, NO, nil, nil), + PROPERTY(gradientColors, UIColor, NSArray, YES, nil, nil), + PROPERTY(gradientLocations, NSNumber, NSArray, YES, nil, nil), + PROPERTY(hideSelectedValue, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideRanges, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideLabels, NSNumber, NSObject, YES, nil, nil), + PROPERTY(hideValueMarkers, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKTextAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTextAnswerFormat alloc] initWithMaximumLength:((NSNumber *)GETPROP(dict, maximumLength)).integerValue]; + }, + (@{ + PROPERTY(maximumLength, NSNumber, NSObject, NO, nil, nil), + PROPERTY(validationRegularExpression, NSRegularExpression, NSObject, YES, + ^id(id value, __unused ORKESerializationContext *context) { return dictionaryFromRegularExpression((NSRegularExpression *)value); }, + ^id(id dict, __unused ORKESerializationContext *context) { return regularExpressionsFromDictionary(dict); } ), + PROPERTY(invalidMessage, NSString, NSObject, YES, nil, nil), + PROPERTY(defaultTextAnswer, NSString, NSObject, YES, nil, nil), + PROPERTY(autocapitalizationType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(autocorrectionType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(spellCheckingType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(keyboardType, NSNumber, NSObject, YES, nil, nil), + PROPERTY(multipleLines, NSNumber, NSObject, YES, nil, nil), + PROPERTY(secureTextEntry, NSNumber, NSObject, YES, nil, nil), + PROPERTY(textContentType, NSString, NSObject, YES, nil, nil), + PROPERTY(passwordRules, UITextInputPasswordRules, NSObject, YES, + ^id(id value, __unused ORKESerializationContext *context) { return dictionaryFromPasswordRules((UITextInputPasswordRules *)value); }, + ^id(id dict, __unused ORKESerializationContext *context) { return passwordRulesFromDictionary(dict); } ), + PROPERTY(placeholder, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKEmailAnswerFormat, + nil, + (@{ + PROPERTY(usernameField, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKConfirmTextAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKConfirmTextAnswerFormat alloc] initWithOriginalItemIdentifier:GETPROP(dict, originalItemIdentifier) errorMessage:GETPROP(dict, errorMessage)]; + }, + (@{ + PROPERTY(originalItemIdentifier, NSString, NSObject, NO, nil, nil), + PROPERTY(errorMessage, NSString, NSObject, NO, nil, nil), + PROPERTY(maximumLength, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKTimeIntervalAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTimeIntervalAnswerFormat alloc] initWithDefaultInterval:((NSNumber *)GETPROP(dict, defaultInterval)).doubleValue step:((NSNumber *)GETPROP(dict, step)).integerValue]; + }, + (@{ + PROPERTY(defaultInterval, NSNumber, NSObject, NO, nil, nil), + PROPERTY(step, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKBooleanAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKBooleanAnswerFormat alloc] initWithYesString:((NSString *)GETPROP(dict, yes)) noString:((NSString *)GETPROP(dict, no))]; + }, + (@{ + PROPERTY(yes, NSString, NSObject, NO, nil, nil), + PROPERTY(no, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKHeightAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHeightAnswerFormat alloc] initWithMeasurementSystem:((NSNumber *)GETPROP(dict, measurementSystem)).integerValue]; + }, + (@{ + PROPERTY(measurementSystem, NSNumber, NSObject, NO, + ^id(id number, __unused ORKESerializationContext *context) { return ORKMeasurementSystemToString(((NSNumber *)number).integerValue); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(ORKMeasurementSystemFromString(string)); }), + })), + ENTRY(ORKWeightAnswerFormat, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKWeightAnswerFormat alloc] initWithMeasurementSystem:((NSNumber *)GETPROP(dict, measurementSystem)).integerValue + numericPrecision:((NSNumber *)GETPROP(dict, numericPrecision)).integerValue + minimumValue:((NSNumber *)GETPROP(dict, minimumValue)).doubleValue + maximumValue:((NSNumber *)GETPROP(dict, maximumValue)).doubleValue + defaultValue:((NSNumber *)GETPROP(dict, defaultValue)).doubleValue]; + }, + (@{ + PROPERTY(measurementSystem, NSNumber, NSObject, NO, + ^id(id number, __unused ORKESerializationContext *context) { return ORKMeasurementSystemToString(((NSNumber *)number).integerValue); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(ORKMeasurementSystemFromString(string)); }), + PROPERTY(numericPrecision, NSNumber, NSObject, NO, nil, nil), + PROPERTY(minimumValue, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximumValue, NSNumber, NSObject, NO, nil, nil), + PROPERTY(defaultValue, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKLocationAnswerFormat, + ^id(__unused NSDictionary *dict, __unused ORKESerializationPropertyGetter getter) { + return [[ORKLocationAnswerFormat alloc] init]; + }, + (@{ + PROPERTY(useCurrentLocation, NSNumber, NSObject, YES, nil, nil), + PROPERTY(placeholder, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKSESAnswerFormat, + ^id(__unused NSDictionary *dict, __unused ORKESerializationPropertyGetter getter) { + return [[ORKSESAnswerFormat alloc] init]; + }, + (@{ + PROPERTY(topRungText, NSString, NSObject, YES, nil, nil), + PROPERTY(bottomRungText, NSString, NSObject, YES, nil, nil) + })), + ENTRY(ORKLocationRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKLocationRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)]; + }, + (@{ + })), + ENTRY(ORKPedometerRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKPedometerRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)]; + }, + (@{ + })), + ENTRY(ORKTouchRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTouchRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict,identifier)]; + }, + (@{ + })), + ENTRY(ORKResult, + nil, + (@{ + PROPERTY(identifier, NSString, NSObject, NO, nil, nil), + PROPERTY(startDate, NSDate, NSObject, YES, + ^id(id date, __unused ORKESerializationContext *context) { return ORKEStringFromDateISO8601(date); }, + ^id(id string, __unused ORKESerializationContext *context) { return ORKEDateFromStringISO8601(string); }), + PROPERTY(endDate, NSDate, NSObject, YES, + ^id(id date, __unused ORKESerializationContext *context) { return ORKEStringFromDateISO8601(date); }, + ^id(id string, __unused ORKESerializationContext *context) { return ORKEDateFromStringISO8601(string); }), + PROPERTY(userInfo, NSDictionary, NSObject, YES, nil, nil) + })), + ENTRY(ORKTappingSample, + nil, + (@{ + PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(duration, NSNumber, NSObject, NO, nil, nil), + PROPERTY(buttonIdentifier, NSNumber, NSObject, NO, + ^id(id numeric, __unused ORKESerializationContext *context) { return tableMapForward(((NSNumber *)numeric).integerValue, buttonIdentifierTable()); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(tableMapReverse(string, buttonIdentifierTable())); }), + PROPERTY(location, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGPoint(((NSValue *)value).CGPointValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGPoint:pointFromDictionary(dict)]; }) + })), + ENTRY(ORKTappingIntervalResult, + nil, + (@{ + PROPERTY(samples, ORKTappingSample, NSArray, NO, nil, nil), + PROPERTY(stepViewSize, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGSize(((NSValue *)value).CGSizeValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGSize:sizeFromDictionary(dict)]; }), + PROPERTY(buttonRect1, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; }), + PROPERTY(buttonRect2, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; }) + })), + ENTRY(ORKTrailmakingTap, + nil, + (@{ + PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(index, NSNumber, NSObject, NO, nil, nil), + PROPERTY(incorrect, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKTrailmakingResult, + nil, + (@{ + PROPERTY(taps, ORKTrailmakingTap, NSArray, NO, nil, nil), + PROPERTY(numberOfErrors, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKSpatialSpanMemoryGameTouchSample, + nil, + (@{ + PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(targetIndex, NSNumber, NSObject, NO, nil, nil), + PROPERTY(correct, NSNumber, NSObject, NO, nil, nil), + PROPERTY(location, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGPoint(((NSValue *)value).CGPointValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGPoint:pointFromDictionary(dict)]; }) + })), + ENTRY(ORKSpatialSpanMemoryGameRecord, + nil, + (@{ + PROPERTY(seed, NSNumber, NSObject, NO, nil, nil), + PROPERTY(sequence, NSNumber, NSArray, NO, nil, nil), + PROPERTY(gameSize, NSNumber, NSObject, NO, nil, nil), + PROPERTY(gameStatus, NSNumber, NSObject, NO, nil, nil), + PROPERTY(score, NSNumber, NSObject, NO, nil, nil), + PROPERTY(touchSamples, ORKSpatialSpanMemoryGameTouchSample, NSArray, NO, + ^id(id numeric, __unused ORKESerializationContext *context) { return tableMapForward(((NSNumber *)numeric).integerValue, memoryGameStatusTable()); }, + ^id(id string, __unused ORKESerializationContext *context) { return @(tableMapReverse(string, memoryGameStatusTable())); }), + PROPERTY(targetRects, NSValue, NSArray, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value?dictionaryFromCGRect(((NSValue *)value).CGRectValue):nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithCGRect:rectFromDictionary(dict)]; }) + })), + ENTRY(ORKSpatialSpanMemoryResult, + nil, + (@{ + PROPERTY(score, NSNumber, NSObject, NO, nil, nil), + PROPERTY(numberOfGames, NSNumber, NSObject, NO, nil, nil), + PROPERTY(numberOfFailures, NSNumber, NSObject, NO, nil, nil), + PROPERTY(gameRecords, ORKSpatialSpanMemoryGameRecord, NSArray, NO, nil, nil) + })), + ENTRY(ORKFileResult, + nil, + (@{ + PROPERTY(contentType, NSString, NSObject, NO, nil, nil), + PROPERTY(fileURL, NSURL, NSObject, NO, + ^id(id url, __unused ORKESerializationContext *context) { return [url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }) + })), + ENTRY(ORKToneAudiometrySample, + nil, + (@{ + PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil), + PROPERTY(channel, NSNumber, NSObject, NO, nil, nil), + PROPERTY(amplitude, NSNumber, NSObject, NO, nil, nil), + PROPERTY(channelSelected, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKToneAudiometryResult, + nil, + (@{ + PROPERTY(outputVolume, NSNumber, NSObject, NO, nil, nil), + PROPERTY(samples, ORKToneAudiometrySample, NSArray, NO, nil, nil), + })), + ENTRY(ORKdBHLToneAudiometryUnit, + nil, + (@{ + PROPERTY(dBHLValue, NSNumber, NSObject, NO, nil, nil), + PROPERTY(startOfUnitTimeStamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(preStimulusDelay, NSNumber, NSObject, NO, nil, nil), + PROPERTY(userTapTimeStamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(timeoutTimeStamp, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKdBHLToneAudiometryFrequencySample, + nil, + (@{ + PROPERTY(frequency, NSNumber, NSObject, NO, nil, nil), + PROPERTY(calculatedThreshold, NSNumber, NSObject, NO, nil, nil), + PROPERTY(channel, NSNumber, NSObject, NO, nil, nil), + PROPERTY(units, ORKdBHLToneAudiometryUnit, NSArray, NO, nil, nil) + })), + ENTRY(ORKdBHLToneAudiometryResult, + nil, + (@{ + PROPERTY(outputVolume, NSNumber, NSObject, NO, nil, nil), + PROPERTY(tonePlaybackDuration, NSNumber, NSObject, NO, nil, nil), + PROPERTY(postStimulusDelay, NSNumber, NSObject, NO, nil, nil), + PROPERTY(headphoneType, NSString, NSObject, NO, nil, nil), + PROPERTY(samples, ORKdBHLToneAudiometryFrequencySample, NSArray, NO, nil, nil), + })), + ENTRY(ORKReactionTimeResult, + nil, + (@{ + PROPERTY(timestamp, NSNumber, NSObject, NO, nil, nil), + PROPERTY(fileResult, ORKResult, NSObject, NO, nil, nil) + })), + ENTRY(ORKSpeechRecognitionResult, + nil, + (@{ + PROPERTY(transcription, SFTranscription, NSObject, NO, + (^id(id transcription, __unused ORKESerializationContext *context) { return dictionaryFromSFTranscription(transcription); }), + // Decode not supported: SFTranscription is immmutable + (^id(id __unused transcriptionDict, __unused ORKESerializationContext *context) { return nil; })), + })), + ENTRY(ORKStroopResult, + nil, + (@{ + PROPERTY(startTime, NSNumber, NSObject, NO, nil, nil), + PROPERTY(endTime, NSNumber, NSObject, NO, nil, nil), + PROPERTY(color, NSString, NSObject, NO, nil, nil), + PROPERTY(text, NSString, NSObject, NO, nil, nil), + PROPERTY(colorSelected, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKTimedWalkResult, + nil, + (@{ + PROPERTY(distanceInMeters, NSNumber, NSObject, NO, nil, nil), + PROPERTY(timeLimit, NSNumber, NSObject, NO, nil, nil), + PROPERTY(duration, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKPSATSample, + nil, + (@{ + PROPERTY(correct, NSNumber, NSObject, NO, nil, nil), + PROPERTY(digit, NSNumber, NSObject, NO, nil, nil), + PROPERTY(answer, NSNumber, NSObject, NO, nil, nil), + PROPERTY(time, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKPSATResult, + nil, + (@{ + PROPERTY(presentationMode, NSNumber, NSObject, NO, nil, nil), + PROPERTY(interStimulusInterval, NSNumber, NSObject, NO, nil, nil), + PROPERTY(stimulusDuration, NSNumber, NSObject, NO, nil, nil), + PROPERTY(length, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalCorrect, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalDyad, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalTime, NSNumber, NSObject, NO, nil, nil), + PROPERTY(initialDigit, NSNumber, NSObject, NO, nil, nil), + PROPERTY(samples, ORKPSATSample, NSArray, NO, nil, nil), + })), + ENTRY(ORKRangeOfMotionResult, + nil, + (@{ + PROPERTY(start, NSNumber, NSObject, NO, nil, nil), + PROPERTY(finish, NSNumber, NSObject, NO, nil, nil), + PROPERTY(minimum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(maximum, NSNumber, NSObject, NO, nil, nil), + PROPERTY(range, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKTowerOfHanoiResult, + nil, + (@{ + PROPERTY(puzzleWasSolved, NSNumber, NSObject, YES, nil, nil), + PROPERTY(moves, ORKTowerOfHanoiMove, NSArray, YES, nil, nil), + })), + ENTRY(ORKTowerOfHanoiMove, + nil, + (@{ + PROPERTY(timestamp, NSNumber, NSObject, YES, nil, nil), + PROPERTY(donorTowerIndex, NSNumber, NSObject, YES, nil, nil), + PROPERTY(recipientTowerIndex, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKHolePegTestSample, + nil, + (@{ + PROPERTY(time, NSNumber, NSObject, NO, nil, nil), + PROPERTY(distance, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKHolePegTestResult, + nil, + (@{ + PROPERTY(movingDirection, NSNumber, NSObject, NO, nil, nil), + PROPERTY(dominantHandTested, NSNumber, NSObject, NO, nil, nil), + PROPERTY(numberOfPegs, NSNumber, NSObject, NO, nil, nil), + PROPERTY(threshold, NSNumber, NSObject, NO, nil, nil), + PROPERTY(rotated, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalSuccesses, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalFailures, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalTime, NSNumber, NSObject, NO, nil, nil), + PROPERTY(totalDistance, NSNumber, NSObject, NO, nil, nil), + PROPERTY(samples, ORKHolePegTestSample, NSArray, NO, nil, nil), + })), + ENTRY(ORKPasscodeResult, + nil, + (@{ + PROPERTY(passcodeSaved, NSNumber, NSObject, YES, nil, nil), + PROPERTY(touchIdEnabled, NSNumber, NSObject, YES, nil, nil) + })), + ENTRY(ORKQuestionResult, + nil, + (@{ + PROPERTY(questionType, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKScaleQuestionResult, + nil, + (@{ + PROPERTY(scaleAnswer, NSNumber, NSObject, NO, nil, nil), + })), + ENTRY(ORKChoiceQuestionResult, + nil, + (@{ + PROPERTY(choiceAnswers, NSObject, NSObject, NO, nil, nil) + })), + ENTRY(ORKMultipleComponentQuestionResult, + nil, + (@{ + PROPERTY(componentsAnswer, NSObject, NSObject, NO, nil, nil), + PROPERTY(separator, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKBooleanQuestionResult, + nil, + (@{ + PROPERTY(booleanAnswer, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKTextQuestionResult, + nil, + (@{ + PROPERTY(textAnswer, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKNumericQuestionResult, + nil, + (@{ + PROPERTY(numericAnswer, NSNumber, NSObject, NO, nil, nil), + PROPERTY(unit, NSString, NSObject, NO, nil, nil) + })), + ENTRY(ORKTimeOfDayQuestionResult, + nil, + (@{ + PROPERTY(dateComponentsAnswer, NSDateComponents, NSObject, NO, + ^id(id dateComponents, __unused ORKESerializationContext *context) { return ORKTimeOfDayStringFromComponents(dateComponents); }, + ^id(id string, __unused ORKESerializationContext *context) { return ORKTimeOfDayComponentsFromString(string); }) + })), + ENTRY(ORKTimeIntervalQuestionResult, + nil, + (@{ + PROPERTY(intervalAnswer, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKDateQuestionResult, + nil, + (@{ + PROPERTY(dateAnswer, NSDate, NSObject, NO, + ^id(id date, __unused ORKESerializationContext *context) { return ORKEStringFromDateISO8601(date); }, + ^id(id string, __unused ORKESerializationContext *context) { return ORKEDateFromStringISO8601(string); }), + PROPERTY(calendar, NSCalendar, NSObject, NO, + ^id(id calendar, __unused ORKESerializationContext *context) { return [(NSCalendar *)calendar calendarIdentifier]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSCalendar calendarWithIdentifier:string]; }), + PROPERTY(timeZone, NSTimeZone, NSObject, NO, + ^id(id timeZone, __unused ORKESerializationContext *context) { return @([timeZone secondsFromGMT]); }, + ^id(id number, __unused ORKESerializationContext *context) { return [NSTimeZone timeZoneForSecondsFromGMT:(NSInteger)((NSNumber *)number).doubleValue]; }) + })), + ENTRY(ORKLocation, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + CLLocationCoordinate2D coordinate = coordinateFromDictionary(dict[@ESTRINGIFY(coordinate)]); + return [[ORKLocation alloc] initWithCoordinate:coordinate + region:GETPROP(dict, region) + userInput:GETPROP(dict, userInput) + postalAddress:GETPROP(dict, postalAddress)]; + }, + (@{ + PROPERTY(userInput, NSString, NSObject, NO, nil, nil), + PROPERTY(postalAddress, CNPostalAddress, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return dictionaryFromPostalAddress(value); }, + ^id(id dict, __unused ORKESerializationContext *context) { return postalAddressFromDictionary(dict); }), + PROPERTY(coordinate, NSValue, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return value ? dictionaryFromCoordinate(((NSValue *)value).MKCoordinateValue) : nil; }, + ^id(id dict, __unused ORKESerializationContext *context) { return [NSValue valueWithMKCoordinate:coordinateFromDictionary(dict)]; }), + PROPERTY(region, CLCircularRegion, NSObject, NO, + ^id(id value, __unused ORKESerializationContext *context) { return dictionaryFromCircularRegion((CLCircularRegion *)value); }, + ^id(id dict, __unused ORKESerializationContext *context) { return circularRegionFromDictionary(dict); }), + })), + ENTRY(ORKLocationQuestionResult, + nil, + (@{ + PROPERTY(locationAnswer, ORKLocation, NSObject, NO, nil, nil) + })), + ENTRY(ORKSESQuestionResult, + nil, + (@{ + PROPERTY(rungPicked, NSNumber, NSObject, NO, nil, nil) + })), + ENTRY(ORKConsentSignatureResult, + nil, + (@{ + PROPERTY(signature, ORKConsentSignature, NSObject, YES, nil, nil), + PROPERTY(consented, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKSignatureResult, + nil, + (@{ + })), + ENTRY(ORKCollectionResult, + nil, + (@{ + PROPERTY(results, ORKResult, NSArray, YES, nil, nil) + })), + ENTRY(ORKTaskResult, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKTaskResult alloc] initWithTaskIdentifier:GETPROP(dict, identifier) taskRunUUID:GETPROP(dict, taskRunUUID) outputDirectory:GETPROP(dict, outputDirectory)]; + }, + (@{ + PROPERTY(taskRunUUID, NSUUID, NSObject, NO, + ^id(id uuid, __unused ORKESerializationContext *context) { return [uuid UUIDString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [[NSUUID alloc] initWithUUIDString:string]; }), + PROPERTY(outputDirectory, NSURL, NSObject, NO, + ^id(id url, __unused ORKESerializationContext *context) { return [url absoluteString]; }, + ^id(id string, __unused ORKESerializationContext *context) { return [NSURL URLWithString:string]; }) + })), + ENTRY(ORKStepResult, + nil, + (@{ + PROPERTY(enabledAssistiveTechnology, NSString, NSObject, YES, nil, nil), + PROPERTY(isPreviousResult, NSNumber, NSObject, YES, nil, nil), + })), + ENTRY(ORKPageResult, + nil, + (@{ + })), + ENTRY(ORKVideoInstructionStepResult, + nil, + (@{ + PROPERTY(playbackStoppedTime, NSNumber, NSObject, YES, nil, nil), + PROPERTY(playbackCompleted, NSNumber, NSObject, YES, nil, nil), + })), + + } mutableCopy]; + if (@available(iOS 12.0, *)) { + [internalEncodingTable addEntriesFromDictionary:@{ ENTRY(ORKHealthClinicalTypeRecorderConfiguration, + ^id(NSDictionary *dict, ORKESerializationPropertyGetter getter) { + return [[ORKHealthClinicalTypeRecorderConfiguration alloc] initWithIdentifier:GETPROP(dict, identifier) healthClinicalType:GETPROP(dict, healthClinicalType) healthFHIRResourceType:GETPROP(dict, healthFHIRResourceType)]; + }, + (@{ + PROPERTY(healthClinicalType, HKClinicalType, NSObject, NO, + ^id(id type, __unused ORKESerializationContext *context) { return identifierFromClinicalType(type); }, + ^id(id identifier, __unused ORKESerializationContext *context) { return typeFromIdentifier(identifier); }), + PROPERTY(healthFHIRResourceType, NSString, NSObject, NO, nil, nil), + })) }]; + } + }); + return internalEncodingTable; +} +#undef GETPROP + +static NSArray *classEncodingsForClass(Class c) { + NSDictionary *encodingTable = ORKESerializationEncodingTable(); + + NSMutableArray *classEncodings = [NSMutableArray array]; + Class sc = c; + while (sc != nil) { + NSString *className = NSStringFromClass(sc); + ORKESerializableTableEntry *classEncoding = encodingTable[className]; + if (classEncoding) { + [classEncodings addObject:classEncoding]; + } + sc = [sc superclass]; + } + return classEncodings; +} + +static id objectForJsonObject(id input, Class expectedClass, ORKESerializationJSONToObjectBlock converterBlock, ORKESerializationContext *context) { + id output = nil; + + if (converterBlock != nil) { + input = converterBlock(input, context); + if (input == nil) { + // Object converted to nothing + return nil; + } + } + + ORKESerializationLocalizer *localizer = context.localizer; + if (expectedClass != nil && [input isKindOfClass:expectedClass]) { + // Input is already of the expected class, do nothing + + // Edge case for ORKAnswerFormat options. Certain formats (e.g. ORKTextChoiceAnswerFormat) contain + // text strings (e.g. 'Yes', 'No') that need to be localized but are already of the expected type. + if ([input isKindOfClass:[NSString class]] && localizer != nil) { + NSString *localizedValue = NSLocalizedStringFromTableInBundle((NSString *)input, localizer.tableName, localizer.bundle, nil); + output = localizedValue; + } else { + output = input; + } + } else if ([input isKindOfClass:[NSDictionary class]]) { + NSDictionary *dict = (NSDictionary *)input; + NSString *className = input[_ClassKey]; + if (expectedClass != nil) { + NSCAssert([NSClassFromString(className) isSubclassOfClass:expectedClass], @"Expected subclass of %@ but got %@", expectedClass, className); + } + NSArray *classEncodings = classEncodingsForClass(NSClassFromString(className)); + NSCAssert([classEncodings count] > 0, @"Expected serializable class but got %@", className); + + ORKESerializableTableEntry *leafClassEncoding = classEncodings.firstObject; + ORKESerializationInitBlock initBlock = leafClassEncoding.initBlock; + BOOL writeAllProperties = YES; + if (initBlock != nil) { + output = initBlock(dict, + ^id(NSDictionary *propDict, NSString *param) { + return propFromDict(propDict, param, context); }); + writeAllProperties = NO; + } else { + Class class = NSClassFromString(className); + if (class == [ORKDontKnowAnswer class]) { + output = [ORKDontKnowAnswer answer]; + } else { + output = [[class alloc] init]; + } + } + + for (__strong NSString *key in [dict allKeys]) { + if ([key isEqualToString:_ClassKey]) { + continue; + } + if ([key hasPrefix:noAnswerPrefix]) { + key = [key substringFromIndex:[noAnswerPrefix length]]; + } + + BOOL haveSetProp = NO; + for (ORKESerializableTableEntry *encoding in classEncodings) { + NSDictionary *propertyTable = encoding.properties; + ORKESerializableProperty *propertyEntry = propertyTable[key]; + if (propertyEntry != nil) { + // Only write the property if it has not already been set during init + if (writeAllProperties || propertyEntry.writeAfterInit) { + id property = propFromDict(dict, key, context); + if ((localizer != nil) && ([property isKindOfClass: [NSString class]])) { + // Keys that exist in the localization table will be localized. + // + // If the key is not found in the table the provided key string will be returned as is, + // supporting the expected functionality for inputs that contain both strings to be + // localized as well as strings to be displayed as is. + NSString *localizedValue = NSLocalizedStringFromTableInBundle((NSString *)property, localizer.tableName, localizer.bundle, nil); + [output setValue:localizedValue forKey:key]; + } else { + [output setValue:property forKey:key]; + } + } + haveSetProp = YES; + break; + } + } + NSCAssert(haveSetProp, @"Unexpected property on %@: %@", className, key); + } + + } else { + NSCAssert(0, @"Unexpected input of class %@ for %@", [input class], expectedClass); + } + return output; +} + +static BOOL isValid(id object) { + return [NSJSONSerialization isValidJSONObject:object] || [object isKindOfClass:[NSNumber class]] || [object isKindOfClass:[NSString class]] || [object isKindOfClass:[NSNull class]] || [object isKindOfClass:[ORKDontKnowAnswer class]]; +} + +static id jsonObjectForObject(id object, ORKESerializationContext *context) { + if (object == nil) { + // Leaf: nil + return nil; + } + + id jsonOutput = nil; + Class c = [object class]; + + NSArray *classEncodings = classEncodingsForClass(c); + + if ([classEncodings count]) { + NSMutableDictionary *encodedDict = [NSMutableDictionary dictionary]; + encodedDict[_ClassKey] = NSStringFromClass(c); + + for (ORKESerializableTableEntry *encoding in classEncodings) { + NSDictionary *propertyTable = encoding.properties; + for (NSString *propertyName in [propertyTable allKeys]) { + ORKESerializableProperty *propertyEntry = propertyTable[propertyName]; + ORKESerializationObjectToJSONBlock converter = propertyEntry.objectToJSONBlock; + Class containerClass = propertyEntry.containerClass; + id valueForKey = [object valueForKey:propertyName]; + BOOL valueIsDontKnowAnswer = [valueForKey isKindOfClass:[ORKDontKnowAnswer class]]; + if (valueIsDontKnowAnswer) { + converter = nil; + } + if (valueForKey != nil) { + if ([containerClass isSubclassOfClass:[NSArray class]]) { + NSMutableArray *a = [NSMutableArray array]; + for (id valueItem in valueForKey) { + id outputItem; + if (converter != nil) { + outputItem = converter(valueItem, context); + NSCAssert(isValid(valueItem), @"Expected valid JSON object"); + } else { + // Recurse for each property + outputItem = jsonObjectForObject(valueItem, context); + } + [a addObject:outputItem]; + } + valueForKey = a; + } else { + if (converter != nil) { + valueForKey = converter(valueForKey, context); + NSCAssert((valueForKey == nil) || isValid(valueForKey), @"Expected valid JSON object"); + } else { + // Recurse for each property + valueForKey = jsonObjectForObject(valueForKey, context); + } + } + } + + if (valueForKey != nil) { + if (valueIsDontKnowAnswer) { + encodedDict[dontKnowFakePropertyName(propertyName)] = valueForKey; + } else { + encodedDict[propertyName] = valueForKey; + } + } + } + } + + jsonOutput = encodedDict; + } else if ([c isSubclassOfClass:[NSArray class]]) { + NSArray *inputArray = (NSArray *)object; + NSMutableArray *encodedArray = [NSMutableArray arrayWithCapacity:[inputArray count]]; + for (id input in inputArray) { + // Recurse for each array element + [encodedArray addObject:jsonObjectForObject(input, context)]; + } + jsonOutput = encodedArray; + } else if ([c isSubclassOfClass:[NSDictionary class]]) { + NSDictionary *inputDict = (NSDictionary *)object; + NSMutableDictionary *encodedDictionary = [NSMutableDictionary dictionaryWithCapacity:[inputDict count]]; + for (NSString *key in [inputDict allKeys] ) { + // Recurse for each dictionary value + encodedDictionary[key] = jsonObjectForObject(inputDict[key], context); + } + jsonOutput = encodedDictionary; + } else if (![c isSubclassOfClass:[NSPredicate class]]) { // Ignore NSPredicate which cannot be easily serialized for now + NSCAssert(isValid(object), @"Expected valid JSON object"); + // Leaf: native JSON object + jsonOutput = object; + } + + return jsonOutput; +} + ++ (NSDictionary *)JSONObjectForObject:(id)object error:(__unused NSError * __autoreleasing *)error { + return [self JSONObjectForObject:object context:[[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:nil] error:error]; +} + ++ (NSDictionary *)JSONObjectForObject:(id)object context:(ORKESerializationContext *)context error:(__unused NSError * __autoreleasing *)error { + id json = jsonObjectForObject(object, context); + return json; +} + ++ (id)objectFromJSONObject:(NSDictionary *)object error:(__unused NSError * __autoreleasing *)error { + return objectForJsonObject(object, nil, nil, [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:nil]); +} + ++ (id)objectFromJSONObject:(NSDictionary *)object context:(ORKESerializationContext *)context error:(__unused NSError * __autoreleasing *)error { + return objectForJsonObject(object, nil, nil, context); +} + ++ (NSData *)JSONDataForObject:(id)object error:(NSError * __autoreleasing *)error { + id json = jsonObjectForObject(object, [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:nil]); + return [NSJSONSerialization dataWithJSONObject:json options:(NSJSONWritingOptions)0 error:error]; +} + ++ (id)objectFromJSONData:(NSData *)data error:(NSError * __autoreleasing *)error { + id json = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingOptions)0 error:error]; + id ret = nil; + if (json != nil) { + ret = objectForJsonObject(json, nil, nil, [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:nil]); + } + return ret; +} + ++ (NSArray *)serializableClasses { + NSMutableArray *a = [NSMutableArray array]; + NSDictionary *table = ORKESerializationEncodingTable(); + for (NSString *key in [table allKeys]) { + if ([key containsString:@"SwiftStroop"]) { + continue; + } + [a addObject:NSClassFromString(key)]; + } + return a; +} + + ++ (NSArray *)serializedPropertiesForClass:(Class)c { + NSArray *entries = classEncodingsForClass(c); + NSMutableArray *properties = [NSMutableArray array]; + for (ORKESerializableTableEntry *entry in entries) { + [properties addObjectsFromArray:[entry.properties allKeys]]; + } + return properties; +} + +@end + + +@implementation ORKESerializer(Registration) + ++ (void)registerSerializableClass:(Class)serializableClass + initBlock:(ORKESerializationInitBlock)initBlock { + NSMutableDictionary *encodingTable = ORKESerializationEncodingTable(); + + ORKESerializableTableEntry *entry = encodingTable[NSStringFromClass(serializableClass)]; + if (entry) { + entry.class = serializableClass; + entry.initBlock = initBlock; + } else { + entry = [[ORKESerializableTableEntry alloc] initWithClass:serializableClass initBlock:initBlock properties:@{}]; + encodingTable[NSStringFromClass(serializableClass)] = entry; + } +} + ++ (void)registerSerializableClassPropertyName:(NSString *)propertyName + forClass:(Class)serializableClass + valueClass:(Class)valueClass + containerClass:(Class)containerClass + writeAfterInit:(BOOL)writeAfterInit + objectToJSONBlock:(ORKESerializationObjectToJSONBlock)objectToJSON + jsonToObjectBlock:(ORKESerializationJSONToObjectBlock)jsonToObjectBlock { + NSMutableDictionary *encodingTable = ORKESerializationEncodingTable(); + + ORKESerializableTableEntry *entry = encodingTable[NSStringFromClass(serializableClass)]; + if (!entry) { + entry = [[ORKESerializableTableEntry alloc] initWithClass:serializableClass initBlock:nil properties:@{}]; + encodingTable[NSStringFromClass(serializableClass)] = entry; + } + + ORKESerializableProperty *property = entry.properties[propertyName]; + if (property == nil) { + property = [[ORKESerializableProperty alloc] initWithPropertyName:propertyName + valueClass:valueClass + containerClass:containerClass + writeAfterInit:writeAfterInit + objectToJSONBlock:objectToJSON + jsonToObjectBlock:jsonToObjectBlock]; + entry.properties[propertyName] = property; + } else { + property.propertyName = propertyName; + property.valueClass = valueClass; + property.containerClass = containerClass; + property.writeAfterInit = writeAfterInit; + property.objectToJSONBlock = objectToJSON; + property.jsonToObjectBlock = jsonToObjectBlock; + } +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m new file mode 100755 index 0000000..8680e72 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKJSONSerializationTests.m @@ -0,0 +1,1453 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2018, Brian Ganninger. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + +#import "ORKESerialization.h" + +#import + + +@interface ClassProperty : NSObject + +@property (nonatomic, copy) NSString *propertyName; +@property (nonatomic, strong) Class propertyClass; +@property (nonatomic) BOOL isPrimitiveType; +@property (nonatomic) BOOL isBoolType; + +- (instancetype)initWithObjcProperty:(objc_property_t)property; + +@end + + +@implementation ClassProperty + +- (instancetype)initWithObjcProperty:(objc_property_t)property { + + self = [super init]; + if (self) { + const char *name = property_getName(property); + self.propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding]; + + const char *type = property_getAttributes(property); + NSString *typeString = [NSString stringWithUTF8String:type]; + NSArray *attributes = [typeString componentsSeparatedByString:@","]; + NSString *typeAttribute = attributes[0]; + + _isPrimitiveType = YES; + if ([typeAttribute hasPrefix:@"T@"]) { + _isPrimitiveType = NO; + Class typeClass = nil; + if (typeAttribute.length > 4) { + NSString *typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, typeAttribute.length-4)]; //turns @"NSDate" into NSDate + typeClass = NSClassFromString(typeClassName); + } else { + typeClass = [NSObject class]; + } + self.propertyClass = typeClass; + + } else if ([@[@"Ti", @"Tq", @"TI", @"TQ"] containsObject:typeAttribute]) { + self.propertyClass = [NSNumber class]; + } + else if ([typeAttribute isEqualToString:@"TB"]) { + self.propertyClass = [NSNumber class]; + _isBoolType = YES; + } + } + return self; +} + +@end + + +@interface MockCountingDictionary : NSObject + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary; + +- (void)startObserving; + +- (void)stopObserving; + +- (NSArray *)unTouchedKeys; + +@property (nonatomic, strong) NSMutableSet *touchedKeys; + +- (NSDictionary *)_containedDictionary; + +@end + + +@implementation MockCountingDictionary { + NSDictionary *_d; +} + +- (instancetype)initWithDictionary:(NSDictionary *)dictionary { + self = [super init]; + _d = dictionary; + return self; +} + +- (BOOL)isKindOfClass:(Class)aClass { + if ([aClass isSubclassOfClass:[NSDictionary class]]) { + return YES; + } + return [super isKindOfClass:aClass]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { + return [_d methodSignatureForSelector:aSelector]; +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation { + if ([_d respondsToSelector:[anInvocation selector]]) { + [anInvocation invokeWithTarget:_d]; + } else { + [super forwardInvocation:anInvocation]; + } +} + +- (void)startObserving { + self.touchedKeys = [NSMutableSet new]; +} + +- (void)stopObserving { + self.touchedKeys = nil; +} + +- (NSArray *)unTouchedKeys { + NSMutableArray *unTouchedKeys = [NSMutableArray new]; + NSArray *keys = [_d allKeys]; + for (NSString *key in keys) { + if ([self.touchedKeys containsObject:key] == NO) { + [unTouchedKeys addObject:key]; + } + } + return [unTouchedKeys copy]; +} + +- (id)objectForKey:(id)aKey { + if (aKey && self.touchedKeys) { + [self.touchedKeys addObject:aKey]; + } + return [_d objectForKey:aKey]; +} + +- (id)objectForKeyedSubscript:(id)key { + if (key && self.touchedKeys) { + [self.touchedKeys addObject:key]; + } + return [_d objectForKeyedSubscript:key]; +} + +- (NSDictionary *)_containedDictionary { + return [_d copy]; +} + +@end + +#define ORK_MAKE_TEST_INIT(class, block) \ +@interface class (ORKTest) \ +- (instancetype)orktest_init; \ +@end \ +\ +@implementation class (ORKTest) \ +- (instancetype)orktest_init { \ +return block(); \ +} \ +@end \ + +#define ORK_MAKE_TEST_INIT_ALT(class, block) \ +@interface class (ORKTest_Alt) \ +- (instancetype)orktest_init_alt; \ +@end \ +\ +@implementation class (ORKTest_Alt) \ +- (instancetype)orktest_init_alt { \ +return block(); \ +} \ +@end \ + + +/* + Add an orktest_init method to all the classes which make init unavailable. This + allows us to write very short code to instantiate valid objects during these tests. + */ +ORK_MAKE_TEST_INIT(ORKStepNavigationRule, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKSkipStepNavigationRule, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKStepModifier, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKKeyValueStepModifier, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKAnswerFormat, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKDontKnowAnswer, ^{return [ORKDontKnowAnswer answer];}); +ORK_MAKE_TEST_INIT(ORKLoginStep, ^{return [self initWithIdentifier:[NSUUID UUID].UUIDString title:@"title" text:@"text" loginViewControllerClass:NSClassFromString(@"ORKLoginStepViewController") ];}); +ORK_MAKE_TEST_INIT(ORKVerificationStep, ^{return [self initWithIdentifier:[NSUUID UUID].UUIDString text:@"text" verificationViewControllerClass:NSClassFromString(@"ORKVerificationStepViewController") ];}); +ORK_MAKE_TEST_INIT(ORKStep, ^{return [self initWithIdentifier:[NSUUID UUID].UUIDString];}); +ORK_MAKE_TEST_INIT(ORKReviewStep, ^{return [[self class] standaloneReviewStepWithIdentifier:[NSUUID UUID].UUIDString steps:@[] resultSource:[ORKTaskResult new]];}); +ORK_MAKE_TEST_INIT(ORKOrderedTask, ^{return [self initWithIdentifier:@"test1" steps:nil];}); +ORK_MAKE_TEST_INIT(ORKImageChoice, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKTextChoice, ^{return [super init];}); +ORK_MAKE_TEST_INIT(ORKTextChoiceOther, ^{return [self initWithText:@"test" primaryTextAttributedString:nil detailText:@"test1" detailTextAttributedString:nil value:@"value" exclusive:YES textViewPlaceholderText:@"test2" textViewInputOptional:NO textViewStartsHidden:YES];}); +ORK_MAKE_TEST_INIT(ORKPredicateStepNavigationRule, ^{return [self initWithResultPredicates:@[[ORKResultPredicate predicateForBooleanQuestionResultWithResultSelector:[ORKResultSelector selectorWithResultIdentifier:@"test"] expectedAnswer:YES]] destinationStepIdentifiers:@[@"test2"]];}); +ORK_MAKE_TEST_INIT(ORKResultSelector, ^{return [self initWithResultIdentifier:@"resultIdentifier"];}); +ORK_MAKE_TEST_INIT(ORKRecorderConfiguration, ^{return [self initWithIdentifier:@"testRecorder"];}); +ORK_MAKE_TEST_INIT(ORKAccelerometerRecorderConfiguration, ^{return [super initWithIdentifier:@"testRecorder"];}); +ORK_MAKE_TEST_INIT(ORKHealthQuantityTypeRecorderConfiguration, ^{ return [super initWithIdentifier:@"testRecorder"];}); +ORK_MAKE_TEST_INIT(ORKAudioRecorderConfiguration, ^{ return [super initWithIdentifier:@"testRecorder"];}); +ORK_MAKE_TEST_INIT(ORKDeviceMotionRecorderConfiguration, ^{ return [super initWithIdentifier:@"testRecorder"];}); +ORK_MAKE_TEST_INIT(ORKHealthClinicalTypeRecorderConfiguration, ^{return [self initWithIdentifier:@"testRecorder" healthClinicalType:[HKClinicalType clinicalTypeForIdentifier:HKClinicalTypeIdentifierAllergyRecord] healthFHIRResourceType:nil];}); +ORK_MAKE_TEST_INIT(CLCircularRegion, (^{ + return [self initWithCenter:CLLocationCoordinate2DMake(2.0, 3.0) radius:100.0 identifier:@"identifier"]; +})) +ORK_MAKE_TEST_INIT_ALT(CLCircularRegion, (^{ + return [self initWithCenter:CLLocationCoordinate2DMake(3.0, 4.0) radius:150.0 identifier:@"identifier"]; +})) +ORK_MAKE_TEST_INIT(ORKLocation, (^{ + CNMutablePostalAddress *postalAddress = [[CNMutablePostalAddress alloc] init]; + postalAddress.city = @"cityA"; + postalAddress.street = @"street"; + ORKLocation *location = [self initWithCoordinate:CLLocationCoordinate2DMake(2.0, 3.0) region:[[CLCircularRegion alloc] orktest_init] userInput:@"addressStringA" postalAddress:postalAddress]; + return location; +})); +ORK_MAKE_TEST_INIT_ALT(ORKLocation, (^{ + CNMutablePostalAddress *postalAddress = [[CNMutablePostalAddress alloc] init]; + postalAddress.city = @"cityB"; + postalAddress.street = @"street"; + ORKLocation *location = [self initWithCoordinate:CLLocationCoordinate2DMake(4.0, 5.0) region:[[CLCircularRegion alloc] orktest_init_alt] userInput:@"addressStringB" postalAddress:postalAddress]; + return location; +})); +ORK_MAKE_TEST_INIT(HKSampleType, (^{ + return [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; +})) +ORK_MAKE_TEST_INIT(HKQuantityType, (^{ + return [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; +})) +ORK_MAKE_TEST_INIT(HKCorrelationType, (^{ + return [HKCorrelationType correlationTypeForIdentifier:HKCorrelationTypeIdentifierBloodPressure]; +})) +ORK_MAKE_TEST_INIT(HKCharacteristicType, (^{ + return [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]; +})) +ORK_MAKE_TEST_INIT(HKClinicalType, (^{ + return [HKClinicalType clinicalTypeForIdentifier:HKClinicalTypeIdentifierAllergyRecord]; +})) + +ORK_MAKE_TEST_INIT(NSNumber, (^{ + return [self initWithInt:123]; +})) +ORK_MAKE_TEST_INIT(HKUnit, (^{ + return [HKUnit unitFromString:@"kg"]; +})) +ORK_MAKE_TEST_INIT(NSURL, (^{ + return [self initFileURLWithPath:@"/usr"]; +})) +ORK_MAKE_TEST_INIT(NSTimeZone, (^{ + return [NSTimeZone timeZoneForSecondsFromGMT:60*60]; +})) +ORK_MAKE_TEST_INIT(NSCalendar, (^{ + return [self initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; +})) +ORK_MAKE_TEST_INIT(NSRegularExpression, (^{ + return [self initWithPattern:@"." options:0 error:nil]; +})) + +@interface ORKJSONTestImageSerialization : NSObject + +@property (nonatomic, readonly) NSDictionary *imageTable; +@property (nonatomic) BOOL generateImages; + +- (void)reset; + +@end + +@implementation ORKJSONTestImageSerialization { + NSMutableDictionary *_imageTable; + NSMutableDictionary *_reverseImageTable; +} + +- (id)init { + self = [super init]; + if (self) { + _imageTable = [[NSMutableDictionary alloc] init]; + _reverseImageTable = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (NSDictionary *)imageTable { + return [_imageTable copy]; +} + +- (void)reset { + [_imageTable removeAllObjects]; + [_reverseImageTable removeAllObjects]; +} + +- (UIImage *)imageForReference:(NSDictionary *)reference { + NSString *s = reference[@"imageName"]; + if (_generateImages && ![_imageTable objectForKey:s]) { + UIImage *image = [UIImage new]; + NSValue *imagePointer = [NSValue valueWithPointer:(const void *)image]; + _imageTable[s] = image; + _reverseImageTable[imagePointer] = s; + } + return _imageTable[s]; +} + +- (nullable NSDictionary *)referenceBySavingImage:(UIImage *)image { + NSValue *imagePointer = [NSValue valueWithPointer:(const void *)image]; + NSString *path = _reverseImageTable[imagePointer]; + if (path == nil) { + path = [[NSUUID UUID] UUIDString]; + } + _imageTable[path] = image; + _reverseImageTable[imagePointer] = path; + + return @{@"imageName" : path}; +} + +@end + +@interface ORKJSONSerializationTestConfiguration : NSObject +@property (nonatomic, readonly) NSArray *classesWithORKSerialization; +@property (nonatomic, readonly) NSArray *classesWithSecureCoding; +@property (nonatomic, readonly) NSArray *classesExcludedForORKESerialization; +@property (nonatomic, readonly) NSArray *propertyExclusionList; +@property (nonatomic, readonly) NSArray *knownNotSerializedProperties; +@property (nonatomic, readonly) NSArray *allowedUnTouchedKeys; + ++ (NSArray *)_classesWithSecureCoding; + +@end + +@implementation ORKJSONSerializationTestConfiguration + +- (id)init { + self = [super init]; + if (self) { + _classesWithORKSerialization = [ORKESerializer serializableClasses]; + _classesWithSecureCoding = [[self class] _classesWithSecureCoding]; + _classesExcludedForORKESerialization = @[ + [ORKStepNavigationRule class], // abstract base class + [ORKSkipStepNavigationRule class], // abstract base class + [ORKStepModifier class], // abstract base class + [ORKPredicateSkipStepNavigationRule class], // NSPredicate doesn't yet support JSON serialization + [ORKKeyValueStepModifier class], // NSPredicate doesn't yet support JSON serialization + [ORKCollector class], // ORKCollector doesn't support JSON serialization + [ORKHealthCollector class], + [ORKHealthCorrelationCollector class], + [ORKMotionActivityCollector class], + [ORKShoulderRangeOfMotionStep class], + [ORKTouchAbilityTouch class], + [ORKTouchAbilityTrack class], + [ORKTouchAbilityTrial class], + [ORKTouchAbilityTapStep class], + [ORKTouchAbilityTapTrial class], + [ORKTouchAbilityPinchStep class], + [ORKTouchAbilitySwipeStep class], + [ORKTouchAbilityTapResult class], + [ORKTouchAbilityPinchTrial class], + [ORKTouchAbilityLongPressTrial class], + [ORKTouchAbilityScrollTrial class], + [ORKTouchAbilityRotationTrial class], + [ORKTouchAbilitySwipeTrial class], + [ORKTouchAbilityGestureRecoginzerEvent class], + [ORKTouchAbilityRotationGestureRecoginzerEvent class], + [ORKTouchAbilityPinchGestureRecoginzerEvent class], + [ORKTouchAbilitySwipeGestureRecoginzerEvent class], + [ORKTouchAbilityPanGestureRecoginzerEvent class], + [ORKTouchAbilityLongPressGestureRecoginzerEvent class], + [ORKTouchAbilityTapGestureRecoginzerEvent class], + [ORKCustomStep class], + [ORKTouchAbilityRotationStep class], + [ORKTouchAbilityLongPressStep class], + [ORKTouchAbilityScrollStep class], + [ORKTouchAbilityPinchResult class], + [ORKTouchAbilityRotationResult class], + [ORKTouchAbilityLongPressResult class], + [ORKTouchAbilitySwipeResult class], + [ORKTouchAbilityScrollResult class] + ]; + _propertyExclusionList = @[ + @"superclass", + @"description", + @"descriptionSuffix", + @"debugDescription", + @"hash", + @"requestedHealthKitTypesForReading", + @"requestedHealthKitTypesForWriting", + @"healthKitUnit", + @"answer", + @"firstResult", + @"ORKPageStep.steps", + @"ORKNavigablePageStep.steps", + @"ORKTextAnswerFormat.validationRegex", + @"ORKRegistrationStep.passcodeValidationRegex", + @"textViewText", + @"ORKConsentSection.image", + @"ORKSpeechRecognitionResult.transcription" + ]; + _knownNotSerializedProperties = @[ + @"ORKStep.task", + @"ORKStep.restorable", + @"ORKReviewStep.isStandalone", + @"ORKAnswerFormat.questionType", + @"ORKQuestionStep.questionType", + @"ORKConsentSection.escapedContent", + @"ORKConsentSignature.signatureImage", + @"ORKConsentDocument.writer", + @"ORKConsentDocument.signatureFormatter", + @"ORKConsentDocument.sectionFormatter", + @"ORKConsentDocument.sections", + @"ORKConsentDocument.signatures", + @"ORKContinuousScaleAnswerFormat.numberFormatter", + @"ORKFormItem.step", + @"ORKTimeIntervalAnswerFormat.maximumInterval", + @"ORKTimeIntervalAnswerFormat.defaultInterval", + @"ORKTimeIntervalAnswerFormat.step", + @"ORKTextAnswerFormat.maximumLength", + @"ORKTextAnswerFormat.autocapitalizationType", + @"ORKTextAnswerFormat.autocorrectionType", + @"ORKTextAnswerFormat.spellCheckingType", + @"ORKTextAnswerFormat.textContentType", + @"ORKTextAnswerFormat.passwordRules", + @"ORKStep.requestedPermissions", + @"ORKOrderedTask.providesBackgroundAudioPrompts", + @"ORKScaleAnswerFormat.numberFormatter", + @"ORKStep.allowsBackNavigation", + @"ORKAnswerFormat.healthKitUserUnit", + @"ORKOrderedTask.requestedPermissions", + @"ORKStep.showsProgress", + @"ORKResult.saveable", + @"ORKCollectionResult.firstResult", + @"ORKHeightAnswerFormat.useMetricSystem", + @"ORKWeightAnswerFormat.useMetricSystem", + @"ORKDataResult.data", + @"ORKVerificationStep.verificationViewControllerClass", + @"ORKLoginStep.loginViewControllerClass", + @"ORKRegistrationStep.passcodeValidationRegularExpression", + @"ORKRegistrationStep.passcodeInvalidMessage", + @"ORKRegistrationStep.phoneNumberValidationRegularExpression", + @"ORKRegistrationStep.phoneNumberInvalidMessage", + @"ORKSignatureResult.signatureImage", + @"ORKSignatureResult.signaturePath", + @"ORKPageStep.steps", + @"ORKNavigablePageStep.steps", + @"ORKNumericAnswerFormat.defaultNumericAnswer", + @"ORKInstructionStep.attributedDetailText", + @"ORKOrderedTask.progressLabelColor", + @"ORKRegistrationStep.passcodeRules", + @"ORKTextChoice.detailTextAttributedString", + @"ORKTextChoice.primaryTextAttributedString" + ]; + _allowedUnTouchedKeys = @[@"_class"]; + } + return self; +} + ++ (NSArray *)_classesWithSecureCoding { + NSArray *classesExcluded = @[]; // classes not intended to be serialized standalone + NSMutableArray *stringsForClassesExcluded = [NSMutableArray array]; + for (Class c in classesExcluded) { + [stringsForClassesExcluded addObject:NSStringFromClass(c)]; + } + + [stringsForClassesExcluded addObject:@"ORKFreehandDrawingGestureRecognizer"]; + [stringsForClassesExcluded addObject:@"ORKSignatureGestureRecognizer"]; + [stringsForClassesExcluded addObject:@"ORKTouchGestureRecognizer"]; + [stringsForClassesExcluded addObject:@"ORKHealthClinicalTypeRecorderConfiguration"]; + + // Find all classes that conform to NSSecureCoding + NSMutableArray *classesWithSecureCoding = [NSMutableArray new]; + int numClasses = objc_getClassList(NULL, 0); + Class classes[numClasses]; + numClasses = objc_getClassList(classes, numClasses); + for (int index = 0; index < numClasses; index++) { + Class aClass = classes[index]; + if ([stringsForClassesExcluded containsObject:NSStringFromClass(aClass)]) { + continue; + } + + if ([NSStringFromClass(aClass) hasPrefix:@"ORK"] && + [aClass conformsToProtocol:@protocol(NSSecureCoding)]) { + [classesWithSecureCoding addObject:aClass]; + } + } + + return [classesWithSecureCoding copy]; +} + +@end + + +@interface ORKJSONSerializationTests : XCTestCase + +@end + + +@implementation ORKJSONSerializationTests + +- (Class)unarchiver:(NSKeyedUnarchiver *) __unused unarchiver cannotDecodeObjectOfClassName:(NSString *)name originalClasses:(NSArray *)classNames { + ORK_Log_Info("Cannot decode object with class: %@ (original classes: %@)", name, classNames); + return nil; +} + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testTaskResult { + + //ORKTaskResult *result = [[ORKTaskResult alloc] initWithTaskIdentifier:@"a000012" taskRunUUID:[NSUUID UUID] outputDirectory:[NSURL fileURLWithPath:NSTemporaryDirectory()]]; + + ORKQuestionResult *qr = [[ORKQuestionResult alloc] init]; + qr.answer = @(1010); + qr.questionType = ORKQuestionTypeInteger; + qr.identifier = @"a000012.s05"; + + ORKStepResult *stepResult = [[ORKStepResult alloc] initWithStepIdentifier:@"stepIdentifier" results:@[qr]]; + stepResult.results = @[qr]; +} + +- (void)testTaskModel { + + ORKActiveStep *activeStep = [[ORKActiveStep alloc] initWithIdentifier:@"id"]; + activeStep.shouldPlaySoundOnStart = YES; + activeStep.shouldVibrateOnStart = YES; + activeStep.stepDuration = 100.0; + activeStep.recorderConfigurations = + @[[[ORKAccelerometerRecorderConfiguration alloc] initWithIdentifier:@"id.accelerometer" frequency:11.0], + [[ORKTouchRecorderConfiguration alloc] initWithIdentifier:@"id.touch"], + [[ORKAudioRecorderConfiguration alloc] initWithIdentifier:@"id.audio" recorderSettings:@{}]]; + + ORKQuestionStep *questionStep = [ORKQuestionStep questionStepWithIdentifier:@"id1" title:@"question" question:@"this is the question" answer:[ORKAnswerFormat choiceAnswerFormatWithStyle:ORKChoiceAnswerStyleMultipleChoice textChoices:@[[[ORKTextChoice alloc] initWithText:@"test1" detailText:nil value:@(1) exclusive:NO] ]]]; + + ORKQuestionStep *questionStep2 = [ORKQuestionStep questionStepWithIdentifier:@"id2" title:@"question" question:@"this is the question" answer:[ORKNumericAnswerFormat decimalAnswerFormatWithUnit:@"kg"]]; + + ORKQuestionStep *questionStep3 = [ORKQuestionStep questionStepWithIdentifier:@"id3" title:@"question" question:@"this is the question" answer:[ORKScaleAnswerFormat scaleAnswerFormatWithMaximumValue:10.0 minimumValue:1.0 defaultValue:5.0 step:1.0 vertical:YES maximumValueDescription:@"High value" minimumValueDescription:@"Low value"]]; + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"id" steps:@[activeStep, questionStep, questionStep2, questionStep3]]; + + NSDictionary *dict1 = [ORKESerializer JSONObjectForObject:task error:nil]; + + NSData *data = [NSJSONSerialization dataWithJSONObject:dict1 options:NSJSONWritingPrettyPrinted error:nil]; + NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSUUID UUID].UUIDString stringByAppendingPathExtension:@"json"]]; + [data writeToFile:tempPath atomically:YES]; + ORK_Log_Info("JSON file at %@", tempPath); + + ORKOrderedTask *task2 = [ORKESerializer objectFromJSONObject:dict1 error:nil]; + + NSDictionary *dict2 = [ORKESerializer JSONObjectForObject:task2 error:nil]; + + XCTAssertTrue([dict1 isEqualToDictionary:dict2], @"Should be equal"); + +} + +/* + Verify that all the known classes that can have dont know answers, serialize them as separate properties with + the prefix noAnswer_ + */ +- (void)testDontKnowSerialization { + + NSDictionary *examples = @{ + @"ORKBooleanQuestionResult" : @"booleanAnswer", + @"ORKDateQuestionResult": @"dateAnswer", + @"ORKNumericQuestionResult" : @"numericAnswer", + @"ORKScaleQuestionResult" : @"scaleAnswer" + }; + [examples enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull className, NSString * _Nonnull answerProp, __unused BOOL * _Nonnull stop) { + ORKQuestionResult *result = [(ORKQuestionResult *)[NSClassFromString(className) alloc] initWithIdentifier:[[NSUUID UUID] UUIDString]]; + [result setAnswer:[ORKDontKnowAnswer answer]]; + result.startDate = [NSDate date]; + result.endDate = [NSDate date]; + NSDictionary *dict = [ORKESerializer JSONObjectForObject:result error:nil]; + + // Do not expect the property name for the answer to have a value + XCTAssertNil([dict valueForKey:answerProp]); + + // Do expect the "dont know" version of the property name for the answer to have a value. + XCTAssertEqualObjects(@"ORKDontKnowAnswer", + [[dict valueForKey:[@"noAnswer_" stringByAppendingString:answerProp]] valueForKey:@"_class"]); + + }]; +} + +- (void)_verifyDontKnowExampleFromPath:(NSString *)path + answerPropertyName:(NSString *)propertyName + context:(ORKESerializationContext *)context { + + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:0 error:NULL]; + id instance = [ORKESerializer objectFromJSONObject:dict context:context error:NULL]; + XCTAssertNotNil(instance); + XCTAssertEqualObjects([instance valueForKey:propertyName], [ORKDontKnowAnswer answer]); +} + +/* + Verifies there is a sample for every JSON-serializable class. + Verifies all registered properties for each of those classes is present in the sample. + Verifies that all properties in the sample are registered. + Attempts a decode of the sample, twice: once with image decoding enabled and once with images mapped to nil. + Provides special handling for dont know answers, verifying that they deserialize as expected. + */ +- (void)testORKSampleDeserialization { + NSString *bundlePath = [[NSBundle bundleForClass:[ORKJSONSerializationTests class]] pathForResource:@"samples" ofType:@"bundle"]; + NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; + NSArray *paths = [bundle pathsForResourcesOfType:@"json" inDirectory:nil forLocalization:nil]; + + ORKJSONTestImageSerialization *testImageSerialization = [[ORKJSONTestImageSerialization alloc] init]; + testImageSerialization.generateImages = YES; + ORKESerializationContext *context = [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:testImageSerialization]; + + ORKJSONSerializationTestConfiguration *testConfiguration = [[ORKJSONSerializationTestConfiguration alloc] init]; + + NSArray *classesWithORKSerialization = testConfiguration.classesWithORKSerialization; + + for (Class c in classesWithORKSerialization) { + XCTAssertNotNil([bundle pathForResource:NSStringFromClass(c) ofType:@"json"], @"Missing JSON serialization example for %@", NSStringFromClass(c)); + } + + // Decode where images are "decoded" + for (NSString *path in paths) { + if ([[path lastPathComponent] hasPrefix:@"DontKnow"]) { + continue; + } + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:0 error:NULL]; + NSString *className = [[path lastPathComponent] stringByDeletingPathExtension]; + NSMutableArray *knownProperties = [[ORKESerializer serializedPropertiesForClass:NSClassFromString(className)] mutableCopy]; + NSMutableArray *loadedProperties = [[dict allKeys] mutableCopy]; + [loadedProperties removeObject:@"_class"]; + NSSet *knownPropSet = [NSSet setWithArray:knownProperties]; + NSSet *loadedPropSet = [NSSet setWithArray:loadedProperties]; + NSMutableSet *intersectionSet = [knownPropSet mutableCopy]; [intersectionSet intersectSet:loadedPropSet]; + NSMutableSet *extraKnownProps = [knownPropSet mutableCopy]; [extraKnownProps minusSet:intersectionSet]; + NSMutableSet *extraLoadedProps = [loadedPropSet mutableCopy]; [extraLoadedProps minusSet:intersectionSet]; + XCTAssertEqualObjects(extraKnownProps, [NSSet set], @"Extra properties registered but not in example for %@", className); + XCTAssertEqualObjects(extraLoadedProps, [NSSet set], @"Extra properties in sample but not registered for %@ on %@", className, path); + id instance = [ORKESerializer objectFromJSONObject:dict context:context error:NULL]; + XCTAssertNotNil(instance); + XCTAssertEqualObjects(NSStringFromClass([instance class]), className); + } + + context.imageProvider = nil; + + // Decode with image decoding failing and returning nil instead of an image: silently suppress the failure + for (NSString *path in paths) { + if ([[path lastPathComponent] hasPrefix:@"DontKnow"]) { + continue; + } + NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:path] options:0 error:NULL]; + NSString *className = [[path lastPathComponent] stringByDeletingPathExtension]; + id instance = [ORKESerializer objectFromJSONObject:dict context:context error:NULL]; + XCTAssertNotNil(instance); + XCTAssertEqualObjects(NSStringFromClass([instance class]), className); + } + + // Test the dont know examples + NSDictionary *examples = @{ + @"DontKnowBooleanResult" : @"booleanAnswer", + @"DontKnowDateResult": @"dateAnswer", + @"DontKnowNumericResult" : @"numericAnswer", + @"DontKnowScaleResult" : @"scaleAnswer" + }; + [examples enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull propName, __unused BOOL * _Nonnull stop) { + [self _verifyDontKnowExampleFromPath:[bundle pathForResource:key ofType:@"json"] + answerPropertyName:propName + context:context]; + }]; + + + +} + +#define GENERATE_SAMPLES 0 + +// JSON Serialization +- (void)testORKSerialization { + ORKJSONTestImageSerialization *testImageSerialization = [[ORKJSONTestImageSerialization alloc] init]; + ORKESerializationContext *context = [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:testImageSerialization]; + + ORKJSONSerializationTestConfiguration *testConfiguration = [[ORKJSONSerializationTestConfiguration alloc] init]; + // Find all classes that are serializable this way + NSArray *classesWithORKSerialization = testConfiguration.classesWithORKSerialization; + + // All classes that conform to NSSecureCoding should also support ORKESerialization + NSArray *classesWithSecureCoding = testConfiguration.classesWithSecureCoding; + + NSArray *classesExcludedForORKESerialization = testConfiguration.classesExcludedForORKESerialization; + + if ((classesExcludedForORKESerialization.count + classesWithORKSerialization.count) != classesWithSecureCoding.count) { + NSMutableArray *unregisteredList = [classesWithSecureCoding mutableCopy]; + [unregisteredList removeObjectsInArray:classesWithORKSerialization]; + [unregisteredList removeObjectsInArray:classesExcludedForORKESerialization]; + XCTAssertEqual(unregisteredList.count, 0, @"Classes didn't implement ORKSerialization %@", unregisteredList); + } + + // Predefined exception + NSArray *propertyExclusionList = testConfiguration.propertyExclusionList; + NSArray *knownNotSerializedProperties = testConfiguration.knownNotSerializedProperties; + NSArray *allowedUnTouchedKeys = testConfiguration.allowedUnTouchedKeys; + + // Test Each class + for (Class aClass in classesWithORKSerialization) { + + id instance = [self instanceForClass:aClass]; + + // Find all properties of this class + NSMutableArray *propertyNames = [NSMutableArray array]; + NSMutableDictionary *dottedPropertyNames = [NSMutableDictionary dictionary]; + unsigned int count; + + // Walk superclasses of this class, looking at all properties. + // Otherwise we don't catch failures to base-call in initWithDictionary (etc) + Class currentClass = aClass; + while ([classesWithORKSerialization containsObject:currentClass]) { + + objc_property_t *props = class_copyPropertyList(currentClass, &count); + for (uint i = 0; i < count; i++) { + objc_property_t property = props[i]; + ClassProperty *p = [[ClassProperty alloc] initWithObjcProperty:property]; + + NSString *dottedPropertyName = [NSString stringWithFormat:@"%@.%@",NSStringFromClass(currentClass),p.propertyName]; + if ([propertyExclusionList containsObject: p.propertyName] == NO && + [propertyExclusionList containsObject: dottedPropertyName] == NO) { + if (p.isPrimitiveType == NO) { + // Assign value to object type property + if (p.propertyClass == [NSObject class] && (aClass == [ORKTextChoice class] || aClass == [ORKImageChoice class])) + { + // Map NSObject to string, since it's used where either a string or a number is acceptable + [instance setValue:@"test" forKey:p.propertyName]; + } else { + id itemInstance = [self instanceForClass:p.propertyClass]; + [instance setValue:itemInstance forKey:p.propertyName]; + } + } + [propertyNames addObject:p.propertyName]; + dottedPropertyNames[p.propertyName] = dottedPropertyName; + } + } + currentClass = [currentClass superclass]; + + } + + if ([aClass isSubclassOfClass:[ORKTextScaleAnswerFormat class]]) { + [instance setValue:@[[ORKTextChoice choiceWithText:@"Poor" value:@1], [ORKTextChoice choiceWithText:@"Excellent" value:@2]] forKey:@"textChoices"]; + } + if ([aClass isSubclassOfClass:[ORKContinuousScaleAnswerFormat class]]) { + [instance setValue:@(100) forKey:@"maximum"]; + [instance setValue:@(ORKNumberFormattingStylePercent) forKey:@"numberStyle"]; + } else if ([aClass isSubclassOfClass:[ORKScaleAnswerFormat class]]) { + [instance setValue:@(0) forKey:@"minimum"]; + [instance setValue:@(100) forKey:@"maximum"]; + [instance setValue:@(10) forKey:@"step"]; + } else if ([aClass isSubclassOfClass:[ORKImageChoice class]] || [aClass isSubclassOfClass:[ORKTextChoice class]]) { + [instance setValue:@"blah" forKey:@"value"]; + } else if ([aClass isSubclassOfClass:[ORKConsentSection class]]) { + [instance setValue:[NSURL URLWithString:@"http://www.apple.com/"] forKey:@"customAnimationURL"]; + } else if ([aClass isSubclassOfClass:[ORKImageCaptureStep class]] || [aClass isSubclassOfClass:[ORKVideoCaptureStep class]]) { + [instance setValue:[NSValue valueWithUIEdgeInsets:(UIEdgeInsets){1,1,1,1}] forKey:@"templateImageInsets"]; + } else if ([aClass isSubclassOfClass:[ORKTimeIntervalAnswerFormat class]]) { + [instance setValue:@(1) forKey:@"step"]; + } else if ([aClass isSubclassOfClass:[ORKLoginStep class]]) { + [instance setValue:NSStringFromClass([ORKLoginStepViewController class]) forKey:@"loginViewControllerString"]; + } else if ([aClass isSubclassOfClass:[ORKVerificationStep class]]) { + [instance setValue:NSStringFromClass([ORKVerificationStepViewController class]) forKey:@"verificationViewControllerString"]; + } else if ([aClass isSubclassOfClass:[ORKReviewStep class]]) { + [instance setValue:[ORKTaskResult new] forKey:@"resultSource"]; // Manually add here because it's a protocol and hence property doesn't have a class + } + + // Serialization + id mockDictionary = [[MockCountingDictionary alloc] initWithDictionary:[ORKESerializer JSONObjectForObject:instance context:context error:NULL]]; + + // Must contain corrected _class field + XCTAssertTrue([NSStringFromClass(aClass) isEqualToString:mockDictionary[@"_class"]]); + + // All properties should have matching fields in dictionary (allow predefined exceptions) + for (NSString *pName in propertyNames) { + if (mockDictionary[pName] == nil) { + NSString *notSerializedProperty = dottedPropertyNames[pName]; + BOOL success = [knownNotSerializedProperties containsObject:notSerializedProperty]; + if (!success) { + XCTAssertTrue(success, "Unexpected notSerializedProperty = %@ (%@)", notSerializedProperty, NSStringFromClass(aClass)); + } + } + } + + [mockDictionary startObserving]; + + id instance2 = [ORKESerializer objectFromJSONObject:mockDictionary context:context error:NULL]; + + NSArray *unTouchedKeys = [mockDictionary unTouchedKeys]; + + // Make sure all keys are touched by initializer + for (NSString *key in unTouchedKeys) { + XCTAssertTrue([allowedUnTouchedKeys containsObject:key], @"untouched %@ in %@", key, aClass); + } + + [mockDictionary stopObserving]; + + // Serialize again, the output ought to be equal + NSDictionary *dictionary2 = [ORKESerializer JSONObjectForObject:instance2 context:context error:NULL]; + BOOL isMatch = [mockDictionary isEqualToDictionary:dictionary2]; + if (!isMatch) { + XCTAssertTrue(isMatch, @"Should be equal for class: %@", NSStringFromClass(aClass)); + } + +#if GENERATE_SAMPLES + [self writeDictionary:dictionary2 forClass:aClass]; +#endif + + [testImageSerialization reset]; + } + +} + +- (void)writeDictionary:(NSDictionary *)dictionary forClass:(Class)aClass { + NSURL *docsDir = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]]; + NSString *outputPath = [[docsDir path] stringByAppendingPathComponent:[NSStringFromClass(aClass) stringByAppendingString:@".json"]]; + NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:NULL]; + [data writeToFile:outputPath atomically:YES]; + ORK_Log_Info("%@", outputPath); +} + +- (BOOL)applySomeValueToClassProperty:(ClassProperty *)p forObject:(id)instance index:(NSInteger)index forEqualityCheck:(BOOL)equality { + // return YES if the index makes it distinct + + if (p.isPrimitiveType) { + if (p.propertyClass == [NSNumber class]) { + if (p.isBoolType) { + XCTAssertNoThrow([instance setValue:index?@YES:@NO forKey:p.propertyName]); + } else { + XCTAssertNoThrow([instance setValue:index?@(12):@(123) forKey:p.propertyName]); + } + return YES; + } else { + return NO; + } + } + + Class aClass = [instance class]; + // Assign value to object type property + if (p.propertyClass == [NSObject class] && (aClass == [ORKTextChoice class]|| aClass == [ORKImageChoice class] || (aClass == [ORKQuestionResult class]))) + { + // Map NSObject to string, since it's used where either a string or a number is acceptable + [instance setValue:index?@"blah":@"test" forKey:p.propertyName]; + } else if (p.propertyClass == [NSNumber class]) { + [instance setValue:index?@(12):@(123) forKey:p.propertyName]; + } else if (p.propertyClass == [NSURL class]) { + NSURL *url = [NSURL fileURLWithFileSystemRepresentation:[index?@"xxx":@"blah" UTF8String] isDirectory:NO relativeToURL:[NSURL fileURLWithPath:NSHomeDirectory()]]; + [instance setValue:url forKey:p.propertyName]; + [[NSFileManager defaultManager] createFileAtPath:[url path] contents:nil attributes:nil]; + } else if (p.propertyClass == [HKUnit class]) { + [instance setValue:[HKUnit unitFromString:index?@"g":@"kg"] forKey:p.propertyName]; + } else if (p.propertyClass == [HKQuantityType class]) { + [instance setValue:[HKQuantityType quantityTypeForIdentifier:index?HKQuantityTypeIdentifierActiveEnergyBurned : HKQuantityTypeIdentifierBodyMass] forKey:p.propertyName]; + } else if (p.propertyClass == [HKCharacteristicType class]) { + [instance setValue:[HKCharacteristicType characteristicTypeForIdentifier:index?HKCharacteristicTypeIdentifierBiologicalSex: HKCharacteristicTypeIdentifierBloodType] forKey:p.propertyName]; + } else if (p.propertyClass == [NSCalendar class]) { + [instance setValue:index?[NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese]:[NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian] forKey:p.propertyName]; + } else if (p.propertyClass == [NSTimeZone class]) { + [instance setValue:index?[NSTimeZone timeZoneWithName:[NSTimeZone knownTimeZoneNames][0]]:[NSTimeZone timeZoneForSecondsFromGMT:1000] forKey:p.propertyName]; + } else if (p.propertyClass == [ORKLocation class]) { + [instance setValue:(index ? [[ORKLocation alloc] orktest_init] : [[ORKLocation alloc] orktest_init_alt]) forKey:p.propertyName]; + } else if (p.propertyClass == [CLCircularRegion class]) { + [instance setValue:index?[[CLCircularRegion alloc] orktest_init_alt]:[[CLCircularRegion alloc] orktest_init] forKey:p.propertyName]; + } else if (p.propertyClass == [NSPredicate class]) { + [instance setValue:[NSPredicate predicateWithFormat:index?@"1 == 1":@"1 == 2"] forKey:p.propertyName]; + } else if (p.propertyClass == [NSRegularExpression class]) { + [instance setValue:[NSRegularExpression regularExpressionWithPattern:index ? @"." : @"[A-Z]" + options:index ? 0 : NSRegularExpressionCaseInsensitive + error:nil] forKey:p.propertyName]; + } else if (equality && (p.propertyClass == [UIImage class])) { + // do nothing - meaningless for the equality check + return NO; + } else if (aClass == [ORKReviewStep class] && [p.propertyName isEqualToString:@"resultSource"]) { + [instance setValue:[[ORKTaskResult alloc] initWithIdentifier:@"blah"] forKey:p.propertyName]; + return NO; + } else { + id instanceForChild = [self instanceForClass:p.propertyClass]; + [instance setValue:instanceForChild forKey:p.propertyName]; + return NO; + } + return YES; +} + +- (void)testSecureCoding { + ORKJSONSerializationTestConfiguration *testConfiguration = [[ORKJSONSerializationTestConfiguration alloc] init]; + NSArray *classesWithSecureCoding = testConfiguration.classesWithSecureCoding; + + // Predefined exception + NSArray *propertyExclusionList = @[@"superclass", + @"description", + @"descriptionSuffix", + @"debugDescription", + @"hash", + @"requestedHealthKitTypesForReading", + @"requestedHealthKitTypesForWriting", + @"healthKitUnit", + @"firstResult", + @"correlationType", + @"sampleType", + @"unit", + @"ORKPageStep.steps", + @"ORKNavigablePageStep.steps", + @"ORKTextAnswerFormat.validationRegex", + @"ORKRegistrationStep.passcodeValidationRegex", + @"textViewText" + ]; + NSArray *knownNotSerializedProperties = @[@"ORKConsentDocument.writer", // created on demand + @"ORKConsentDocument.signatureFormatter", // created on demand + @"ORKConsentDocument.sectionFormatter", // created on demand + @"ORKStep.task", // weak ref - object will be nil + @"ORKFormItem.step", // weak ref - object will be nil + + // id<> properties - these are actually serialized, but we can't fill them in properly for this test + @"ORKTextChoice.value", + @"ORKImageChoice.value", + @"ORKQuestionResult.answer", + @"ORKVerificationStep.verificationViewControllerClass", + @"ORKLoginStep.loginViewControllerClass", + + // Not serialized - computed property + @"ORKAnswerFormat.healthKitUnit", + @"ORKAnswerFormat.healthKitUserUnit", + @"ORKCollectionResult.firstResult", + + @"ORKCustomStep.contentView", // UIView is not able to be serialized + + // Images: ignored so we can do the equality test and pass + @"ORKImageChoice.normalStateImage", + @"ORKImageChoice.selectedStateImage", + @"ORKImageCaptureStep.templateImage", + @"ORKVideoCaptureStep.templateImage", + @"ORKConsentSignature.signatureImage", + @"ORKConsentSection.customImage", + @"ORKInstructionStep.image", + @"ORKInstructionStep.auxiliaryImage", + @"ORKInstructionStep.iconImage", + @"ORKActiveStep.image", + @"ORKStep.image", + @"ORKStep.iconImage", + @"ORKStep.auxiliaryImage", + @"ORKStep.image", + @"ORKStep.auxiliaryImage", + @"ORKStep.iconImage", + @"ORKSpatialSpanMemoryStep.customTargetImage", + @"ORKScaleAnswerFormat.minimumImage", + @"ORKScaleAnswerFormat.maximumImage", + @"ORKContinuousScaleAnswerFormat.minimumImage", + @"ORKContinuousScaleAnswerFormat.maximumImage", + @"ORKSignatureResult.signatureImage", + @"ORKSignatureResult.signaturePath", + @"ORKPageStep.steps", + + @"ORKRegistrationStep.phoneNumberValidationRegularExpression", + @"ORKRegistrationStep.phoneNumberInvalidMessage", + @"ORKTableStep.bulletIconNames", + @"ORKAmslerGridResult.image", + @"ORKHealthClinicalTypeRecorderConfiguration.healthClinicalType", + @"ORKHealthClinicalTypeRecorderConfiguration.healthFHIRResourceType", + @"ORKInstructionStep.attributedDetailText", + @"ORKOrderedTask.progressLabelColor", + @"ORKQuestionStep.question", + @"ORKConsentSection.image", + @"ORKBodyItem.image" + ]; + + // Test Each class + for (Class aClass in classesWithSecureCoding) { + id instance = [self instanceForClass:aClass]; + + // Find all properties of this class + NSMutableArray *propertyNames = [NSMutableArray array]; + unsigned int count; + objc_property_t *props = class_copyPropertyList(aClass, &count); + for (uint i = 0; i < count; i++) { + objc_property_t property = props[i]; + ClassProperty *p = [[ClassProperty alloc] initWithObjcProperty:property]; + + NSString *dottedPropertyName = [NSString stringWithFormat:@"%@.%@",NSStringFromClass(aClass),p.propertyName]; + if ([propertyExclusionList containsObject: p.propertyName] == NO && + [propertyExclusionList containsObject: dottedPropertyName] == NO) { + if (p.isPrimitiveType == NO) { + [self applySomeValueToClassProperty:p forObject:instance index:0 forEqualityCheck:YES]; + } + [propertyNames addObject:p.propertyName]; + } + } + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:instance requiringSecureCoding:YES error:nil]; + XCTAssertNotNil(data); + + NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:nil]; + unarchiver.requiresSecureCoding = YES; + unarchiver.delegate = self; + NSMutableSet *decodingClasses = [NSMutableSet setWithArray:classesWithSecureCoding]; + [decodingClasses addObject:[NSDate class]]; + [decodingClasses addObject:[HKQueryAnchor class]]; + + id newInstance = [unarchiver decodeObjectOfClasses:decodingClasses forKey:NSKeyedArchiveRootObjectKey]; + + // Set of classes we can check for equality. Would like to get rid of this once we implement + NSSet *checkableClasses = [NSSet setWithObjects:[NSNumber class], [NSString class], [NSDictionary class], [NSURL class], nil]; + // All properties should have matching fields in dictionary (allow predefined exceptions) + for (NSString *pName in propertyNames) { + id newValue = [newInstance valueForKey:pName]; + id oldValue = [instance valueForKey:pName]; + + if (newValue == nil) { + NSString *notSerializedProperty = [NSString stringWithFormat:@"%@.%@", NSStringFromClass(aClass), pName]; + BOOL success = [knownNotSerializedProperties containsObject:notSerializedProperty]; + if (!success) { + XCTAssertTrue(success, "Unexpected notSerializedProperty = %@", notSerializedProperty); + } + } + for (Class c in checkableClasses) { + if ([oldValue isKindOfClass:c]) { + if ([newValue isKindOfClass:[NSURL class]] || [oldValue isKindOfClass:[NSURL class]]) { + if (![[newValue absoluteString] isEqualToString:[oldValue absoluteString]]) { + XCTAssertTrue([[newValue absoluteString] isEqualToString:[oldValue absoluteString]]); + } + } else { + XCTAssertEqualObjects(newValue, oldValue); + } + break; + } + } + } + + // NSData and NSDateComponents in your properties mess up the following test. + // NSDateComponents - seems to be due to serializing and then deserializing introducing a leap month:no flag. + if (aClass == [NSDateComponents class] || + aClass == [ORKDateQuestionResult class] || + aClass == [ORKDateAnswerFormat class] || + [aClass superclass] == [UIGestureRecognizer class]) { + continue; + } + + NSData *data2 = [NSKeyedArchiver archivedDataWithRootObject:newInstance requiringSecureCoding:YES error:nil]; + + NSKeyedUnarchiver *unarchiver2 = [[NSKeyedUnarchiver alloc] initForReadingFromData:data2 error:nil]; + unarchiver2.requiresSecureCoding = YES; + unarchiver2.delegate = self; + id newInstance2 = [unarchiver2 decodeObjectOfClasses:decodingClasses forKey:NSKeyedArchiveRootObjectKey]; + NSData *data3 = [NSKeyedArchiver archivedDataWithRootObject:newInstance2 requiringSecureCoding:YES error:nil]; + + if (![data isEqualToData:data2]) { // allow breakpointing + if (![aClass isSubclassOfClass:[ORKConsentSection class]] + // ORKConsentSection mis-matches, but it is still "equal" because + // the net custom animation URL is a match. + && ![aClass isSubclassOfClass:[ORKNavigableOrderedTask class]] + // ORKNavigableOrderedTask contains ORKStepModifiers which is an abstract class + // with no encoded properties, but encoded/decoded objects are still equal. + && ![aClass isSubclassOfClass:[ORKKeyValueStepModifier class]] + // ORKKeyValueStepModifier si a subclass of ORKStepModifier which is an abstract class + // with no encoded properties, but encoded/decoded objects are still equal. + ) { + XCTAssertEqualObjects(data, data2, @"data mismatch for %@", NSStringFromClass(aClass)); + } + } + if (![data2 isEqualToData:data3]) { // allow breakpointing + XCTAssertEqualObjects(data2, data3, @"data mismatch for %@", NSStringFromClass(aClass)); + } + + if (![newInstance isEqual:instance]) { + XCTAssertEqualObjects(newInstance, instance, @"equality mismatch for %@", NSStringFromClass(aClass)); + } + if (![newInstance2 isEqual:instance]) { + XCTAssertEqualObjects(newInstance2, instance, @"equality mismatch for %@", NSStringFromClass(aClass)); + } + } +} + +- (id)instanceForClass:(Class)c { + id result = nil; + @try { + if ([c instancesRespondToSelector:@selector(orktest_init)]) + { + result = [[c alloc] orktest_init]; + } else { + result = [[c alloc] init]; + } + } @catch (NSException *exception) { + XCTAssert(NO, @"Exception throw in init for %@. Exception: %@", NSStringFromClass(c), exception); + } + return result; +} + +- (void)testEquality { + NSArray *classesExcluded = @[ + [ORKStepNavigationRule class], // abstract base class + [ORKSkipStepNavigationRule class], // abstract base class + [ORKStepModifier class], // abstract base class + [ORKVideoCaptureStep class], + [ORKImageCaptureStep class] + ]; + + + // Each time ORKRegistrationStep returns a new date in its answer fromat, cannot be tested. + NSMutableArray *stringsForClassesExcluded = [NSMutableArray arrayWithObjects:NSStringFromClass([ORKRegistrationStep class]), nil]; + for (Class c in classesExcluded) { + [stringsForClassesExcluded addObject:NSStringFromClass(c)]; + } + + // Find all classes that conform to NSSecureCoding + NSMutableArray *classesWithSecureCodingAndCopying = [NSMutableArray new]; + int numClasses = objc_getClassList(NULL, 0); + Class classes[numClasses]; + numClasses = objc_getClassList(classes, numClasses); + for (int index = 0; index < numClasses; index++) { + Class aClass = classes[index]; + if ([stringsForClassesExcluded containsObject:NSStringFromClass(aClass)]) { + continue; + } + + if ([NSStringFromClass(aClass) hasPrefix:@"ORK"] && + [aClass conformsToProtocol:@protocol(NSSecureCoding)] && + [aClass conformsToProtocol:@protocol(NSCopying)]) { + + [classesWithSecureCodingAndCopying addObject:aClass]; + } + } + + // Predefined exception + NSArray *propertyExclusionList = @[@"superclass", + @"description", + @"descriptionSuffix", + @"debugDescription", + @"hash", + + // ResearchKit specific + @"answer", + @"firstResult", + @"healthKitUnit", + @"providesBackgroundAudioPrompts", + @"questionType", + @"requestedHealthKitTypesForReading", + @"requestedHealthKitTypesForWriting", + @"requestedPermissions", + @"shouldReportProgress", + + // For a specific class + @"ORKHeightAnswerFormat.useMetricSystem", + @"ORKWeightAnswerFormat.useMetricSystem", + @"ORKNavigablePageStep.steps", + @"ORKPageStep.steps", + @"ORKResult.saveable", + @"ORKReviewStep.isStandalone", + @"ORKStep.allowsBackNavigation", + @"ORKStep.restorable", + @"ORKStep.showsProgress", + @"ORKStepResult.isPreviousResult", + @"ORKTextAnswerFormat.validationRegex", + @"ORKVideoCaptureStep.duration", + @"ORKQuestionStep.useCardView", + @"ORKFormStep.useCardView", + @"ORKSpeechRecognitionStep.shouldHideTranscript", + @"ORKTableStep.isBulleted", + @"ORKTableStep.allowsSelection", + @"ORKPDFViewerStep.actionBarOption" + ]; + + NSArray *hashExclusionList = @[ + @"ORKDateQuestionResult.calendar", + @"ORKDateQuestionResult.timeZone", + @"ORKToneAudiometryResult.outputVolume", + @"ORKToneAudiometryResult.channel", + @"ORKConsentSection.contentURL", + @"ORKConsentSection.customAnimationURL", + @"ORKNumericAnswerFormat.minimum", + @"ORKNumericAnswerFormat.maximum", + @"ORKNumericAnswerFormat.maximumFractionDigits", + @"ORKNumericAnswerFormat.defaultNumericAnswer", + @"ORKVideoCaptureStep.duration", + @"ORKTextAnswerFormat.validationRegularExpression", + @"ORKPDFViewerStep.pdfURL" + ]; + + // Test Each class + for (Class aClass in classesWithSecureCodingAndCopying) { + id instance = [self instanceForClass:aClass]; + + // Find all properties of this class + NSMutableArray *propertyNames = [NSMutableArray array]; + unsigned int count; + objc_property_t *props = class_copyPropertyList(aClass, &count); + for (uint i = 0; i < count; i++) { + objc_property_t property = props[i]; + ClassProperty *p = [[ClassProperty alloc] initWithObjcProperty:property]; + + NSString *dottedPropertyName = [NSString stringWithFormat:@"%@.%@",NSStringFromClass(aClass),p.propertyName]; + if ([propertyExclusionList containsObject: p.propertyName] == NO && + [propertyExclusionList containsObject: dottedPropertyName] == NO) { + if (p.isPrimitiveType || [instance valueForKey:p.propertyName] == nil) { + [self applySomeValueToClassProperty:p forObject:instance index:0 forEqualityCheck:YES]; + } + [propertyNames addObject:p.propertyName]; + } + } + + id copiedInstance = [instance copy]; + if (![copiedInstance isEqual:instance]) { + XCTAssertEqualObjects(copiedInstance, instance); + } + + for (uint i = 0; i < count; i++) { + objc_property_t property = props[i]; + ClassProperty *p = [[ClassProperty alloc] initWithObjcProperty:property]; + + NSString *dottedPropertyName = [NSString stringWithFormat:@"%@.%@",NSStringFromClass(aClass),p.propertyName]; + if ([propertyExclusionList containsObject: p.propertyName] == NO && + [propertyExclusionList containsObject: dottedPropertyName] == NO) { + copiedInstance = [instance copy]; + if (instance == copiedInstance) { + // Totally immutable object. + continue; + } + if ([self applySomeValueToClassProperty:p forObject:copiedInstance index:1 forEqualityCheck:YES]) + { + if ([copiedInstance isEqual:instance]) { + XCTAssertNotEqualObjects(copiedInstance, instance, @"%@", dottedPropertyName); + } + if (!p.isPrimitiveType && + ![hashExclusionList containsObject:p.propertyName] && + ![hashExclusionList containsObject:dottedPropertyName]) { + // Only check the hash for non-primitive type properties because often the + // hash into a table can be referenced using a subset of the properties used to test equality. + XCTAssertNotEqual([instance hash], [copiedInstance hash], @"(%@, %@) %@", [instance valueForKey:p.propertyName], [copiedInstance valueForKey:p.propertyName], dottedPropertyName); + } + + [self applySomeValueToClassProperty:p forObject:copiedInstance index:0 forEqualityCheck:YES]; + XCTAssertEqualObjects(copiedInstance, instance, @"%@", dottedPropertyName); + + if (p.isPrimitiveType == NO) { + [copiedInstance setValue:nil forKey:p.propertyName]; + XCTAssertNotEqualObjects(copiedInstance, instance); + } + } + } + } + } +} + +- (void)testDateComponentsSerialization { + + // Trying to get NSDateComponents to change when you serialize / deserialize twice. But the test passes here. + + NSDateComponents *a = [NSDateComponents new]; + NSData *d1 = [NSKeyedArchiver archivedDataWithRootObject:a requiringSecureCoding:YES error:nil]; + NSDateComponents *b = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSDateComponents class] fromData:d1 error:nil]; + NSData *d2 = [NSKeyedArchiver archivedDataWithRootObject:b requiringSecureCoding:YES error:nil]; + + XCTAssertEqualObjects(d1, d2); + XCTAssertEqualObjects(a, b); +} + +- (void)testAddResult { + + // Classes for which tests are not currently implemented + NSArray *excludedClassNames = @[ + @"ORKVisualConsentStepViewController", // Requires step with scenes + @"ORKImageCaptureStepViewController" + ]; + + // Classes that do not allow adding a result should throw an exception + NSArray *exceptionClassNames = @[ + @"ORKPasscodeStepViewController", + ]; + + NSDictionary *mapStepClassForViewController = @{ // classes that require custom step class + @"ORKActiveStepViewController" : @"ORKActiveStep", + @"ORKConsentReviewStepViewController" : @"ORKConsentReviewStep", + @"ORKFormStepViewController" : @"ORKFormStep", + @"ORKHolePegTestPlaceStepViewController" : @"ORKHolePegTestPlaceStep", + @"ORKHolePegTestRemoveStepViewController" : @"ORKHolePegTestRemoveStep", + @"ORKImageCaptureStepViewController" : @"ORKImageCaptureStep", + @"ORKPSATStepViewController" : @"ORKPSATStep", + @"ORKQuestionStepViewController" : @"ORKQuestionStep", + @"ORKSpatialSpanMemoryStepViewController" : @"ORKSpatialSpanMemoryStep", + @"ORKStroopStepViewController" : @"ORKStroopStep", + @"ORKTimedWalkStepViewController" : @"ORKTimedWalkStep", + @"ORKTowerOfHanoiViewController" : @"ORKTowerOfHanoiStep", + @"ORKVideoCaptureStepViewController" : @"ORKVideoCaptureStep", + @"ORKVideoInstructionStepViewController" : @"ORKVideoInstructionStep", + @"ORKVisualConsentStepViewController" : @"ORKVisualConsentStep", + @"ORKWalkingTaskStepViewController" : @"ORKWalkingTaskStep", + @"ORKTableStepViewController" : @"ORKTableStep", + @"ORKdBHLToneAudiometryStepViewController" : @"ORKdBHLToneAudiometryStep", + + @"ORKSecondaryTaskStepViewController" : @"ORKSecondaryTaskStep", + @"ORKHeadphoneDetectStepViewController" : @"ORKHeadphoneDetectStep", + @"ORKWebViewStepViewController": @"ORKWebViewStep", + }; + + NSDictionary *kvMapForStep = @{ // Steps that require modification to validate + @"ORKHolePegTestPlaceStep" : @{@"numberOfPegs" : @2, + @"stepDuration" : @2.0f }, + @"ORKHolePegTestRemoveStep" : @{@"numberOfPegs" : @2, + @"stepDuration" : @2.0f }, + @"ORKPSATStep" : @{@"interStimulusInterval" : @1.0, + @"seriesLength" : @10, + @"stepDuration" : @11.0f, + @"presentationMode" : @(ORKPSATPresentationModeAuditory)}, + @"ORKSpatialSpanMemoryStep" : @{@"initialSpan" : @2, + @"maximumSpan" : @5, + @"playSpeed" : @1.0, + @"maximumTests" : @3, + @"maximumConsecutiveFailures" : @1}, + @"ORKStroopStep" : @{@"numberOfAttempts" : @15}, + @"ORKTimedWalkStep" : @{@"distanceInMeters" : @30.0, + @"stepDuration" : @2.0}, + @"ORKWalkingTaskStep" : @{@"numberOfStepsPerLeg" : @2}, + @"ORKWebViewStep" : @{@"html": @""} + }; + + // Find all classes that subclass from ORKStepViewController + NSMutableArray *stepViewControllerClassses = [NSMutableArray new]; + int numClasses; + Class * classes = NULL; + classes = NULL; + numClasses = objc_getClassList(NULL, 0); + + if (numClasses > 0 ) { + classes = (Class *)realloc(classes, sizeof(Class) * (unsigned)numClasses); + numClasses = objc_getClassList(classes, numClasses); + Class aClass = nil; + for (int i = 0; i < numClasses; i++) { + aClass = classes[i]; + + if ([excludedClassNames containsObject:NSStringFromClass(aClass)]) { + continue; + } + + if ([NSStringFromClass(aClass) hasPrefix:@"ORK"] && + [aClass isSubclassOfClass:[ORKStepViewController class]]) { + + [stepViewControllerClassses addObject:aClass]; + } + } + + free(classes); + } + + // Test Each class + for (Class aClass in stepViewControllerClassses) { + + // Instantiate the step view controller + NSString *stepClassName = mapStepClassForViewController[NSStringFromClass(aClass)]; + if (stepClassName == nil) { + for (NSString *vcClassName in mapStepClassForViewController.allKeys) { + if ([aClass isSubclassOfClass:NSClassFromString(vcClassName)]) { + stepClassName = mapStepClassForViewController[vcClassName]; + } + } + } + Class stepClass = stepClassName ? NSClassFromString(stepClassName) : [ORKStep class]; + ORKStep *step = [self instanceForClass:stepClass]; + NSDictionary *kv = nil; + if (stepClassName && (kv = kvMapForStep[stepClassName])) { + [step setValuesForKeysWithDictionary:kv]; + } + ORKStepViewController *stepViewController = [[aClass alloc] initWithStep:step]; + + // Create a result + ORKBooleanQuestionResult *result = [[ORKBooleanQuestionResult alloc] initWithIdentifier:@"test"]; + result.booleanAnswer = @YES; + + // -- Call method under test + if ([exceptionClassNames containsObject:NSStringFromClass(aClass)]) { + XCTAssertThrows([stepViewController addResult:result]); + continue; + } else { + XCTAssertNoThrow([stepViewController addResult:result]); + } + + ORKStepResult *stepResult = stepViewController.result; + XCTAssertNotNil(stepResult, @"Step result is nil for %@", NSStringFromClass([stepViewController class])); + XCTAssertTrue([stepResult isKindOfClass:[ORKStepResult class]], @"Step result is not subclass of ORKStepResult for %@", NSStringFromClass([stepViewController class])); + if ([stepResult isKindOfClass:[ORKStepResult class]]) { + XCTAssertNotNil(stepResult.results, @"Step result.results is nil for %@", NSStringFromClass([stepViewController class])); + XCTAssertTrue([stepResult.results containsObject:result], @"Step result does not contain added result for %@", NSStringFromClass([stepViewController class])); + } + } +} + +- (void)testInvalidDBHLValue { + // Non ORKInvalidDBHLValue-containing sample + ORKdBHLToneAudiometryFrequencySample *sample = [[ORKdBHLToneAudiometryFrequencySample alloc] init]; + sample.channel = ORKAudioChannelLeft; + sample.frequency = 1000; + sample.calculatedThreshold = 0.5; + + NSDictionary *sampleDictionary = [ORKESerializer JSONObjectForObject:sample error:NULL]; + ORKdBHLToneAudiometryFrequencySample *deserializedSample = [ORKESerializer objectFromJSONObject:sampleDictionary error:NULL]; + + XCTAssertEqualObjects(sample, deserializedSample); + + NSData *sampleData = [ORKESerializer JSONDataForObject:sample error:NULL]; + deserializedSample = [ORKESerializer objectFromJSONData:sampleData error:NULL]; + + XCTAssertEqualObjects(sample, deserializedSample); + + // ORKInvalidDBHLValue-containing sample + sample.calculatedThreshold = ORKInvalidDBHLValue; + + sampleDictionary = [ORKESerializer JSONObjectForObject:sample error:NULL]; + deserializedSample = [ORKESerializer objectFromJSONObject:sampleDictionary error:NULL]; + + XCTAssertEqualObjects(sample, deserializedSample); + + sampleData = [ORKESerializer JSONDataForObject:sample error:NULL]; + deserializedSample = [ORKESerializer objectFromJSONData:sampleData error:NULL]; + + XCTAssertEqualObjects(sample, deserializedSample); +} + +- (void)testMissingDefaultValueKeyInScaleAnswerFormat { + ORKESerializationContext *context = [[ORKESerializationContext alloc] initWithLocalizer:nil imageProvider:nil]; + + NSDictionary *payloadForContinuousScale = @{@"minimumValueDescription":@"",@"maximum":@100,@"_class":@"ORKContinuousScaleAnswerFormat",@"vertical":@NO,@"minimum":@0,@"maximumFractionDigits":@0,@"hideSelectedValue":@NO,@"hideRanges":@NO,@"hideLabels":@NO,@"numberStyle":@"percent",@"maximumValueDescription":@"",@"showDontKnowButton":@NO,@"customDontKnowButtonText":@""}; + + ORKContinuousScaleAnswerFormat *continuousScaleAnswerFormat = (ORKContinuousScaleAnswerFormat *)[ORKESerializer objectFromJSONObject:payloadForContinuousScale context:context error:NULL]; + XCTAssertEqual(continuousScaleAnswerFormat.defaultValue, DBL_MAX); + + NSDictionary *payloadForScale = @{@"minimumValueDescription":@"",@"maximum":@100,@"_class":@"ORKScaleAnswerFormat",@"vertical":@NO,@"minimum":@0,@"hideSelectedValue":@NO,@"hideRanges":@NO,@"hideLabels":@NO,@"hideValueMarkers":@NO,@"step":@10,@"maximumValueDescription":@"",@"showDontKnowButton":@NO,@"customDontKnowButtonText":@""}; + ORKScaleAnswerFormat *scaleAnswerFormat = (ORKScaleAnswerFormat *)[ORKESerializer objectFromJSONObject:payloadForScale context:context error:NULL]; + XCTAssertEqual(scaleAnswerFormat.defaultValue, INT_MAX); +} + +@end + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKKeychainWrapperTests.m b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKKeychainWrapperTests.m new file mode 100755 index 0000000..4ddeac5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/ORKKeychainWrapperTests.m @@ -0,0 +1,133 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +@import XCTest; +@import ResearchKit.Private; + + +@interface ORKKeychainWrapperTests : XCTestCase + +@end + + +static NSString *const inObject = @"RK object"; +static NSString *const key = @"RK key"; +static NSString *const invalidKey = @"RK invalid key"; + +@implementation ORKKeychainWrapperTests + +- (void)testSetObjectInKeychain { + NSError *error; + + // Test that the object is set without error. + BOOL success = [ORKKeychainWrapper setObject:inObject + forKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Test that the object set is equal to the object retrieved. + NSString *outObject = (NSString *) [ORKKeychainWrapper objectForKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(inObject, outObject); + +} + +- (void)testGetObjectFromKeychain { + NSError *error; + + // Set an object in the keychain. + BOOL success = [ORKKeychainWrapper setObject:inObject + forKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Test that the object set is equal to the object retrieved. + NSString *outObject = (NSString *) [ORKKeychainWrapper objectForKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(inObject, outObject); + + // Test that there is an error for invalid key. + id object = [ORKKeychainWrapper objectForKey:invalidKey + error:&error]; + XCTAssertNotNil(error); + XCTAssertNil(object); +} + +- (void)testRemoveObjectFromKeychain { + NSError *error; + + // Set an object in the keychain. + BOOL success = [ORKKeychainWrapper setObject:inObject + forKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Remove the object from the keychain. + success = [ORKKeychainWrapper removeObjectForKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Test that there is no object for the key. + id object = [ORKKeychainWrapper objectForKey:key + error:&error]; + XCTAssertNotNil(error); + XCTAssertNil(object); +} + +- (void)testResetKeychain { + NSError *error; + + // Set an object in the keychain. + BOOL success = [ORKKeychainWrapper setObject:inObject + forKey:key + error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Reset the keychain. + success = [ORKKeychainWrapper resetKeychainWithError:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + // Test that there is no object for the key. + id object = [ORKKeychainWrapper objectForKey:key + error:&error]; + XCTAssertNotNil(error); + XCTAssertNil(object); +} + +@end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowBooleanResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowBooleanResult.json new file mode 100755 index 0000000..a420194 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowBooleanResult.json @@ -0,0 +1 @@ +{"_class":"ORKBooleanQuestionResult","noAnswer_booleanAnswer":{"_class":"ORKDontKnowAnswer"},"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"userInfo":{}} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowDateResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowDateResult.json new file mode 100755 index 0000000..2213d16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowDateResult.json @@ -0,0 +1 @@ +{"_class":"ORKDateQuestionResult","timeZone":3600,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","noAnswer_dateAnswer":{"_class":"ORKDontKnowAnswer"},"identifier":"","calendar":"gregorian","questionType":0,"userInfo":{}} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowNumericResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowNumericResult.json new file mode 100755 index 0000000..de35272 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowNumericResult.json @@ -0,0 +1 @@ +{"_class":"ORKNumericQuestionResult","unit":"","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","noAnswer_numericAnswer":{"_class":"ORKDontKnowAnswer"},"identifier":"","questionType":0,"userInfo":{}} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowScaleResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowScaleResult.json new file mode 100755 index 0000000..1dac3e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/DontKnowScaleResult.json @@ -0,0 +1,2 @@ +{"_class":"ORKScaleQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","noAnswer_scaleAnswer":{"_class":"ORKDontKnowAnswer"},"identifier":"","questionType":0,"userInfo":{}} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/Info.plist new file mode 100755 index 0000000..95afeb7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/Info.plist differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAccelerometerRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAccelerometerRecorderConfiguration.json new file mode 100755 index 0000000..01fa96f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAccelerometerRecorderConfiguration.json @@ -0,0 +1 @@ +{"identifier":"","_class":"ORKAccelerometerRecorderConfiguration","frequency":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKActiveStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKActiveStep.json new file mode 100755 index 0000000..f4c5153 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKActiveStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"50DE67FB-AE5A-4C1A-97E6-038BAB9A346F"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"23DBF489-731A-446A-A5ED-3D3E737C5E12"},"title":"","image":{"imageName":"A39F0D25-B88E-446C-BC34-614AE0405E73"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment":0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKActiveStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridResult.json new file mode 100755 index 0000000..1211e03 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridResult.json @@ -0,0 +1 @@ +{"_class":"ORKAmslerGridResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","eyeSide":0,"identifier":"","image":{"imageName":"F4FE0CA6-169B-4F8C-A902-A3328D686153"},"path":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridStep.json new file mode 100755 index 0000000..56624ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAmslerGridStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"DFC4815F-FB55-4365-9D10-FF2BA83879A1"},"auxiliaryImage":{"imageName":"3E076C04-09E0-4055-8FBE-5309DC4A5348"},"title":"","image":{"imageName":"0905D188-3CBD-4DEE-82C7-11165BA8352B"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","eyeSide":0,"optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":true,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAmslerGridStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAnswerFormat.json new file mode 100755 index 0000000..c5516ac --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKAnswerFormat","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioLevelNavigationRule.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioLevelNavigationRule.json new file mode 100755 index 0000000..7122c91 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioLevelNavigationRule.json @@ -0,0 +1 @@ +{"audioLevelStepIdentifier":"","destinationStepIdentifier":"","_class":"ORKAudioLevelNavigationRule","recordingSettings":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioRecorderConfiguration.json new file mode 100755 index 0000000..1bee123 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioRecorderConfiguration.json @@ -0,0 +1 @@ +{"identifier":"","_class":"ORKAudioRecorderConfiguration","recorderSettings":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioStep.json new file mode 100755 index 0000000..a4a9dc1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKAudioStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"244AD43E-7785-4BF5-829C-A3B5C771E9F2"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"A35CAC85-9557-4ED5-9807-DCFDAC04C81D"},"title":"","image":{"imageName":"5E598B50-21DC-400E-8D80-75BB26BDCD65"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKAudioStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBodyItem.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBodyItem.json new file mode 100755 index 0000000..2deaa98 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBodyItem.json @@ -0,0 +1 @@ +{"text":"","learnMoreItem":{"_class":"ORKLearnMoreItem"},"bodyItemStyle":0,"_class":"ORKBodyItem","detailText":"","image":{"imageName":"55324853-4B02-4BC2-B295-C42B8D9D814D"},"useCardStyle":0, "useSecondaryColor":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanAnswerFormat.json new file mode 100755 index 0000000..3e7f467 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanAnswerFormat.json @@ -0,0 +1 @@ +{"yes":"","_class":"ORKBooleanAnswerFormat","no":"","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanQuestionResult.json new file mode 100755 index 0000000..02a1a22 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKBooleanQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKBooleanQuestionResult","booleanAnswer":123,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKChoiceQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKChoiceQuestionResult.json new file mode 100755 index 0000000..53a85d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKChoiceQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKChoiceQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"choiceAnswers":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCollectionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCollectionResult.json new file mode 100755 index 0000000..82b2c42 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCollectionResult.json @@ -0,0 +1 @@ +{"userInfo":{},"results":[],"_class":"ORKCollectionResult","startDate":"2019-05-27T00:35:06-0700","identifier":"","endDate":"2019-05-27T00:35:06-0700"} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCompletionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCompletionStep.json new file mode 100755 index 0000000..91c83ac --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCompletionStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKCompletionStep","iconImage":{"imageName":"2A7001B3-FE8B-4628-B9A3-848BBEF58B1F"},"auxiliaryImage":{"imageName":"685A4968-7933-4BCE-A646-9EBE32A63514"},"title":"","identifier":"","image":{"imageName":"7469F374-6BCA-4716-8BF1-AFF1761E6DE2"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConfirmTextAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConfirmTextAnswerFormat.json new file mode 100755 index 0000000..6efdb2b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConfirmTextAnswerFormat.json @@ -0,0 +1 @@ +{"multipleLines":false,"secureTextEntry":false,"keyboardType":0,"validationRegularExpression":{"pattern":".","options":[]},"_class":"ORKConfirmTextAnswerFormat","spellCheckingType":0,"invalidMessage":"","errorMessage":"","maximumLength":0,"textContentType":"","passwordRules":{"rules":""},"originalItemIdentifier":"","autocorrectionType":0,"autocapitalizationType":0,"defaultTextAnswer":"","showDontKnowButton":false,"customDontKnowButtonText":"","placeholder":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentDocument.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentDocument.json new file mode 100755 index 0000000..5e087cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentDocument.json @@ -0,0 +1 @@ +{"_class":"ORKConsentDocument","sections":[],"signaturePageTitle":"","title":"","signatures":[],"htmlReviewContent":"","signaturePageContent":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentReviewStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentReviewStep.json new file mode 100755 index 0000000..d22e258 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentReviewStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "consentDocument":{"_class":"ORKConsentDocument"},"optional":false,"shouldTintImages":true,"requiresScrollToBottom":false,"_class":"ORKConsentReviewStep","useSurveyMode":false,"iconImage":{"imageName":"7259A545-C1AF-4696-B0A5-E4DADBB7172F"},"title":"","auxiliaryImage":{"imageName":"0336A673-281A-47C4-BB1E-2428BFBFA947"},"signature":{"requiresName":true,"requiresSignatureImage":true,"_class":"ORKConsentSignature","identifier":"5739826D-2DEA-4CB9-AB4E-10047140EC66"},"identifier":"","footnote":"","image":{"imageName":"76F181D1-005C-43C2-B429-AE931FE7371E"},"text":"","reasonForConsent":"","imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSection.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSection.json new file mode 100755 index 0000000..cfc74c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSection.json @@ -0,0 +1 @@ +{"_class":"ORKConsentSection","contentURL":"file:\/\/\/usr\/","type":0,"title":"","customLearnMoreButtonTitle":"","summary":"","formalTitle":"","htmlContent":"","customAnimationURL":"http:\/\/www.apple.com\/","customImage":{"imageName":"1EB08D4E-6613-41CC-9C6F-26427EB3D26F"},"omitFromDocument":false,"content":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSharingStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSharingStep.json new file mode 100755 index 0000000..60e4869 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSharingStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"answerFormat":{"_class":"ORKAnswerFormat"},"detailText":"", "headerTextAlignment": 0, "optional":true,"shouldTintImages":true,"useSurveyMode":false,"_class":"ORKConsentSharingStep","iconImage":{"imageName":"648F7701-58AE-4D8E-9BF4-7CEB2544CE26"},"auxiliaryImage":{"imageName":"47CCEC1A-365D-4A7B-AE45-381EDD7B1F32"},"title":"","identifier":"","footnote":"","image":{"imageName":"E0C3A64C-50AA-4499-8CF6-41EBEA752510"},"text":"","placeholder":"","question":"","localizedLearnMoreHTMLContent":"","useCardView":true,"imageContentMode": 0, "learnMoreItem":{"_class":"ORKLearnMoreItem"},"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0, "tagText": ""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignature.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignature.json new file mode 100755 index 0000000..7783118 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignature.json @@ -0,0 +1 @@ +{"_class":"ORKConsentSignature","signatureImage":{"imageName":"64513349-1CB7-4E8B-94D5-9D2A16069200"},"signatureDate":"","signatureDateFormatString":"","requiresName":true,"title":"","identifier":"","familyName":"","givenName":"","requiresSignatureImage":true} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignatureResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignatureResult.json new file mode 100755 index 0000000..c5ad182 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKConsentSignatureResult.json @@ -0,0 +1 @@ +{"_class":"ORKConsentSignatureResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","signature":{"requiresName":true,"requiresSignatureImage":true,"_class":"ORKConsentSignature","identifier":"1357B9FF-7D21-4880-B390-B3DBB252B876"},"identifier":"","userInfo":{},"consented":false} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKContinuousScaleAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKContinuousScaleAnswerFormat.json new file mode 100755 index 0000000..6ffcdd8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKContinuousScaleAnswerFormat.json @@ -0,0 +1 @@ +{"gradientColors":[],"minimumImage":{"imageName":"CF025EF9-EDF2-48DE-9DDB-19805DE3624B"},"minimumValueDescription":"","maximum":100,"_class":"ORKContinuousScaleAnswerFormat","vertical":false,"gradientLocations":[],"minimum":0,"defaultValue":0,"maximumFractionDigits":0,"hideSelectedValue":false,"hideRanges":false,"hideLabels":false,"numberStyle":"percent","maximumValueDescription":"","maximumImage":{"imageName":"FFEA709A-B3DD-42F5-8392-33E4FB4F85E1"},"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCountdownStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCountdownStep.json new file mode 100755 index 0000000..3feea91 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKCountdownStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"B6F92FB7-5395-4AE2-9360-066CA37A418E"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"C7C218A3-69F7-4C4E-9501-BAD38CC4260F"},"title":"","image":{"imageName":"55019522-82E5-4D89-86D3-0ACD6A220E9E"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0, "stepDuration":5,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKCountdownStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateAnswerFormat.json new file mode 100755 index 0000000..566e646 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKDateAnswerFormat","style":"dateTime","minuteInterval":0,"minimumDate":"2019-05-27T00:35:06-0700","calendar":"gregorian","defaultDate":"2019-05-27T00:35:06-0700","maximumDate":"2019-05-27T00:35:06-0700","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateQuestionResult.json new file mode 100755 index 0000000..c1066ba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDateQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKDateQuestionResult","timeZone":3600,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","dateAnswer":"2019-05-27T00:35:06-0700","identifier":"","calendar":"gregorian","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDeviceMotionRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDeviceMotionRecorderConfiguration.json new file mode 100755 index 0000000..7dfd3b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDeviceMotionRecorderConfiguration.json @@ -0,0 +1 @@ +{"identifier":"","_class":"ORKDeviceMotionRecorderConfiguration","frequency":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDirectStepNavigationRule.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDirectStepNavigationRule.json new file mode 100755 index 0000000..ccc491b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDirectStepNavigationRule.json @@ -0,0 +1 @@ +{"_class":"ORKDirectStepNavigationRule","destinationStepIdentifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDontKnowAnswer.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDontKnowAnswer.json new file mode 100755 index 0000000..771cfad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKDontKnowAnswer.json @@ -0,0 +1 @@ +{"_class":"ORKDontKnowAnswer"} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEmailAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEmailAnswerFormat.json new file mode 100755 index 0000000..f0d90c8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEmailAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKEmailAnswerFormat","usernameField":false,"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterResult.json new file mode 100755 index 0000000..a46d234 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterResult.json @@ -0,0 +1 @@ +{"_class":"ORKEnvironmentSPLMeterResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","sensitivityOffset":0,"identifier":"","recordedSPLMeterSamples":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterStep.json new file mode 100755 index 0000000..8cab221 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKEnvironmentSPLMeterStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"883D1208-F5D7-438F-96E2-BDCADF944A00"},"auxiliaryImage":{"imageName":"314A97C4-3FC7-42E3-BA7F-318B7584547E"},"thresholdValue":35,"title":"","shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"image":{"imageName":"B6828B3C-AE63-4DDC-A099-CA8898DBD6CA"},"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":true,"requiredContiguousSamples":5,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"samplingInterval":1,"finishedSpokenInstruction":"","_class":"ORKEnvironmentSPLMeterStep","text":"","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFileResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFileResult.json new file mode 100755 index 0000000..1dc9032 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFileResult.json @@ -0,0 +1 @@ +{"_class":"ORKFileResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","contentType":"","identifier":"","fileURL":"file:\/\/\/usr\/","userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFitnessStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFitnessStep.json new file mode 100755 index 0000000..cdafe9b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFitnessStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"3F5C9800-6A7A-4158-8ECF-0832B44DF6C1"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"988B687D-F50F-4B89-B6B7-20F11AE6AC8E"},"title":"","image":{"imageName":"B7400237-AD21-4AA3-8E4C-60F06E05EA39"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKFitnessStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormItem.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormItem.json new file mode 100755 index 0000000..55ad95c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormItem.json @@ -0,0 +1 @@ +{"placeholder":"","answerFormat":{"_class":"ORKAnswerFormat"},"_class":"ORKFormItem","optional":false,"learnMoreItem":{"_class":"ORKLearnMoreItem"},"text":"","identifier":"","detailText":"","showsProgress":false, "tagText": ""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormStep.json new file mode 100755 index 0000000..e02ef91 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKFormStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "optional":true,"useSurveyMode":true,"shouldTintImages":true,"_class":"ORKFormStep","auxiliaryImage":{"imageName":"747C6BFD-53E7-47EE-95B6-D4ABDC6270CF"},"iconImage":{"imageName":"A9782DB7-4168-4967-8E34-F75A62A7106E"},"title":"","identifier":"","footnote":"","image":{"imageName":"0BBE4F43-391F-4B33-9770-740363779CBD"},"text":"","formItems":[],"useCardView":true,"imageContentMode": 0,"footerText":"","bodyItemTextAlignment":0,"buildInBodyItems": 0,"cardViewStyle":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthClinicalTypeRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthClinicalTypeRecorderConfiguration.json new file mode 100755 index 0000000..ba71844 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthClinicalTypeRecorderConfiguration.json @@ -0,0 +1 @@ +{"healthClinicalType":"HKClinicalTypeIdentifierAllergyRecord","_class":"ORKHealthClinicalTypeRecorderConfiguration","healthFHIRResourceType":"","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitCharacteristicTypeAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitCharacteristicTypeAnswerFormat.json new file mode 100755 index 0000000..798f93f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitCharacteristicTypeAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKHealthKitCharacteristicTypeAnswerFormat","shouldRequestAuthorization":false,"characteristicType":"HKCharacteristicTypeIdentifierBloodType","minimumDate":"2019-05-27T00:35:06-0700","calendar":"gregorian","defaultDate":"2019-05-27T00:35:06-0700","maximumDate":"2019-05-27T00:35:06-0700","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitQuantityTypeAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitQuantityTypeAnswerFormat.json new file mode 100755 index 0000000..55c4d33 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthKitQuantityTypeAnswerFormat.json @@ -0,0 +1 @@ +{"unit":"kg","numericAnswerStyle":"decimal","_class":"ORKHealthKitQuantityTypeAnswerFormat","quantityType":"HKQuantityTypeIdentifierBodyMass","shouldRequestAuthorization":false,"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthQuantityTypeRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthQuantityTypeRecorderConfiguration.json new file mode 100755 index 0000000..59145b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHealthQuantityTypeRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKHealthQuantityTypeRecorderConfiguration","identifier":"","quantityType":"HKQuantityTypeIdentifierBodyMass","unit":"kg"} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHeightAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHeightAnswerFormat.json new file mode 100755 index 0000000..e8618af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHeightAnswerFormat.json @@ -0,0 +1 @@ +{"measurementSystem":"local","_class":"ORKHeightAnswerFormat","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestPlaceStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestPlaceStep.json new file mode 100755 index 0000000..c3a70e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestPlaceStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"C4304649-4220-45B0-95C8-07219157A460"},"auxiliaryImage":{"imageName":"CD0C6044-D7E4-4970-9E24-D4907A9CCF85"},"movingDirection":0,"title":"","shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"image":{"imageName":"48957C0F-22A8-419C-A372-9DB9B4CFE41B"},"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"dominantHandTested":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"numberOfPegs":0,"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"bodyItems":[],"text":"","finishedSpokenInstruction":"","_class":"ORKHolePegTestPlaceStep","rotated":false,"threshold":0,"shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestRemoveStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestRemoveStep.json new file mode 100755 index 0000000..9a5f783 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestRemoveStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"BE486BA2-4BF4-4B55-A13C-823460C271F9"},"auxiliaryImage":{"imageName":"CC4FA554-A433-46CB-948E-35F2B01177BB"},"movingDirection":0,"title":"","shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"image":{"imageName":"0D2B43F6-8030-40F3-B7D5-6D3848EAEB83"},"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"dominantHandTested":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"numberOfPegs":0,"shouldVibrateOnStart":false,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKHolePegTestRemoveStep","threshold":0,"shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestResult.json new file mode 100755 index 0000000..c0a6507 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestResult.json @@ -0,0 +1 @@ +{"totalFailures":0,"samples":[],"totalSuccesses":0,"_class":"ORKHolePegTestResult","totalTime":0,"totalDistance":0,"rotated":false,"identifier":"","endDate":"2019-05-27T00:35:06-0700","numberOfPegs":0,"dominantHandTested":false,"movingDirection":0,"startDate":"2019-05-27T00:35:06-0700","userInfo":{},"threshold":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestSample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestSample.json new file mode 100755 index 0000000..2aad4c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKHolePegTestSample.json @@ -0,0 +1 @@ +{"distance":0,"_class":"ORKHolePegTestSample","time":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageCaptureStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageCaptureStep.json new file mode 100755 index 0000000..57fae8b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageCaptureStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "optional":true,"useSurveyMode":false,"templateImageInsets":{"right":1,"top":1,"left":1,"bottom":1},"_class":"ORKImageCaptureStep","shouldTintImages":true,"iconImage":{"imageName":"B540C098-2AC8-47DC-AA92-C5D12711DE58"},"auxiliaryImage":{"imageName":"E8D4C452-E28D-4F04-9681-FCFE512B578D"},"captureRaw":false,"title":"","identifier":"","templateImage":{"imageName":"DFC768AB-9173-4574-A981-53298C0F9155"},"footnote":"","image":{"imageName":"D1E13489-E3D2-4248-9260-2F7A750DA1A3"},"text":"","accessibilityInstructions":"","accessibilityHint":"","imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoice.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoice.json new file mode 100755 index 0000000..336c02a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoice.json @@ -0,0 +1 @@ +{"value":"blah","selectedStateImage":{"imageName":"D3FF449C-11EF-49EB-82AA-CB12046AAA15"},"_class":"ORKImageChoice","normalStateImage":{"imageName":"8EC33FBD-2102-4577-87C0-587A0A37CB80"},"text":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoiceAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoiceAnswerFormat.json new file mode 100755 index 0000000..5dfb7cd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKImageChoiceAnswerFormat.json @@ -0,0 +1 @@ +{"vertical":false,"style":"singleChoice","_class":"ORKImageChoiceAnswerFormat","imageChoices":[],"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKInstructionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKInstructionStep.json new file mode 100755 index 0000000..121cc1a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKInstructionStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKInstructionStep","iconImage":{"imageName":"009AF45B-7E20-494E-A16C-88C6BDC15016"},"auxiliaryImage":{"imageName":"63D79505-966B-4AB6-BD80-0B4CADF45EAA"},"title":"","identifier":"","image":{"imageName":"97759B9C-39F2-4BE2-AD0A-FBCC3571DC5C"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreInstructionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreInstructionStep.json new file mode 100755 index 0000000..eaa0863 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreInstructionStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKLearnMoreInstructionStep","iconImage":{"imageName":"AA4B1340-91CA-43F8-8DFF-65D8072F47E0"},"auxiliaryImage":{"imageName":"51F527BE-5B1E-465A-9260-B79664443AC2"},"title":"","identifier":"","image":{"imageName":"EE23D70C-83EB-41CE-83FC-4D3D632322DE"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreItem.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreItem.json new file mode 100755 index 0000000..3105554 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLearnMoreItem.json @@ -0,0 +1 @@ +{"learnMoreInstructionStep":{"shouldTintImages":false,"useSurveyMode":false,"_class":"ORKLearnMoreInstructionStep","identifier":"71FBF954-4D34-4267-BE27-E7F46C92BFB5","optional":false},"_class":"ORKLearnMoreItem","text":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocation.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocation.json new file mode 100755 index 0000000..f517c16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocation.json @@ -0,0 +1 @@ +{"userInput":"","postalAddress":{"street":"","city":""},"_class":"ORKLocation","coordinate":{"longitude":3,"latitude":2},"region":{"identifier":"identifier","coordinate":{"longitude":3,"latitude":2},"radius":100}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationAnswerFormat.json new file mode 100755 index 0000000..d58313c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationAnswerFormat.json @@ -0,0 +1 @@ +{"useCurrentLocation":false,"_class":"ORKLocationAnswerFormat","showDontKnowButton":false,"customDontKnowButtonText":"","placeholder":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationQuestionResult.json new file mode 100755 index 0000000..9ff5837 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKLocationQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","locationAnswer":{"userInput":"addressStringA","postalAddress":{"street":"street","city":"cityA"},"_class":"ORKLocation","coordinate":{"longitude":3,"latitude":2},"region":{"identifier":"identifier","coordinate":{"longitude":3,"latitude":2},"radius":100}},"identifier":"","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationRecorderConfiguration.json new file mode 100755 index 0000000..2315bb9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLocationRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKLocationRecorderConfiguration","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLoginStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLoginStep.json new file mode 100755 index 0000000..af96fbb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKLoginStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "loginViewControllerString":"ORKLoginStepViewController","optional":true,"useSurveyMode":true,"shouldTintImages":true,"_class":"ORKLoginStep","iconImage":{"imageName":"65159B22-6011-4EB7-81BD-2E597B4AA29A"},"auxiliaryImage":{"imageName":"45AA55E2-9A86-4285-9FF7-A1E77856C480"},"title":"","identifier":"","footnote":"","image":{"imageName":"5B301CC2-521C-4403-BFBA-7597E0A93CFA"},"text":"","formItems":[],"useCardView":true,"imageContentMode": 0,"footerText":"","bodyItemTextAlignment":0,"buildInBodyItems": 0,"cardViewStyle":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleComponentQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleComponentQuestionResult.json new file mode 100755 index 0000000..0d7d88c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleComponentQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKMultipleComponentQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","separator":"","identifier":"","questionType":0,"componentsAnswer":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleValuePickerAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleValuePickerAnswerFormat.json new file mode 100755 index 0000000..7a88d4d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKMultipleValuePickerAnswerFormat.json @@ -0,0 +1 @@ +{"separator":"","_class":"ORKMultipleValuePickerAnswerFormat","valuePickers":[],"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigableOrderedTask.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigableOrderedTask.json new file mode 100755 index 0000000..e67c678 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigableOrderedTask.json @@ -0,0 +1 @@ +{"_class":"ORKNavigableOrderedTask","steps":[],"stepModifiers":{},"identifier":"","skipStepNavigationRules":{},"shouldReportProgress":false,"stepNavigationRules":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigablePageStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigablePageStep.json new file mode 100755 index 0000000..ea7bb73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNavigablePageStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"pageTask":{"_class":"ORKOrderedTask","identifier":"test1"},"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKNavigablePageStep","iconImage":{"imageName":"EA8D496D-A56D-4C7E-A4F0-78CE32EE034C"},"auxiliaryImage":{"imageName":"A17C26E6-AEE0-4F8A-97E5-96C2B925884F"},"title":"","identifier":"","image":{"imageName":"428F188A-57C5-44A2-8B53-1BA16F8F50E0"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericAnswerFormat.json new file mode 100755 index 0000000..d2a41b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKNumericAnswerFormat","style":"decimal","minimum":123,"maximum":123,"unit":"","defaultNumericAnswer":123,"maximumFractionDigits":123,"showDontKnowButton":false,"customDontKnowButtonText":"","placeholder":"","hideUnitWhenAnswerIsEmpty":true} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericQuestionResult.json new file mode 100755 index 0000000..1d35df1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKNumericQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKNumericQuestionResult","unit":"","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","numericAnswer":123,"identifier":"","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKOrderedTask.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKOrderedTask.json new file mode 100755 index 0000000..1b24f8d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKOrderedTask.json @@ -0,0 +1 @@ +{"steps":[],"_class":"ORKOrderedTask","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPDFViewerStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPDFViewerStep.json new file mode 100755 index 0000000..a22102b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPDFViewerStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"pdfURL":"file:\/\/\/usr\/","useSurveyMode":false,"_class":"ORKPDFViewerStep","shouldTintImages":true,"iconImage":{"imageName":"304906CA-FB5B-4147-AA16-1A087A78A324"},"title":"","identifier":"","footnote":"","auxiliaryImage":{"imageName":"2ED7211C-A4AB-4EB3-A59E-C99AA7884B2D"},"actionBarOption":0,"image":{"imageName":"E2F454DF-3E96-4974-8BBB-46E1FF556A0C"},"text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATResult.json new file mode 100755 index 0000000..414bd23 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATResult.json @@ -0,0 +1 @@ +{"stimulusDuration":0,"initialDigit":0,"samples":[],"_class":"ORKPSATResult","totalTime":0,"length":0,"totalCorrect":0,"identifier":"","endDate":"2019-05-27T00:35:06-0700","interStimulusInterval":0,"totalDyad":0,"startDate":"2019-05-27T00:35:06-0700","userInfo":{},"presentationMode":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATSample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATSample.json new file mode 100755 index 0000000..5372d01 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATSample.json @@ -0,0 +1 @@ +{"correct":false,"digit":0,"_class":"ORKPSATSample","answer":0,"time":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATStep.json new file mode 100755 index 0000000..a5d2033 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPSATStep.json @@ -0,0 +1 @@ +{"footnote":"","stimulusDuration":0,"recorderConfigurations":[],"shouldContinueOnFinish":true,"shouldSpeakCountDown":false,"interStimulusInterval":0,"shouldTintImages":true,"iconImage":{"imageName":"A0A7FA5A-91F9-4FC1-8D58-287F482B2074"},"auxiliaryImage":{"imageName":"A2ED4D38-98B4-46E2-A926-C226ED3415B0"},"shouldPlaySoundOnFinish":false,"seriesLength":0,"shouldPlaySoundOnStart":false,"title":"","image":{"imageName":"F7381130-E0E1-4B0E-A726-C0D0C6D0C8F0"},"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"presentationMode":0,"shouldVibrateOnStart":false,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKPSATStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageResult.json new file mode 100755 index 0000000..3cb7373 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageResult.json @@ -0,0 +1 @@ +{"_class":"ORKPageResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","outputDirectory":"file:\/\/\/usr\/","taskRunUUID":"637A93BE-FE56-4397-8D6B-D42378A6C977","identifier":"","results":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageStep.json new file mode 100755 index 0000000..1175973 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPageStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"pageTask":{"_class":"ORKOrderedTask","identifier":"test1"},"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKPageStep","iconImage":{"imageName":"AF540A3D-754B-4D3B-8800-3147F200E737"},"auxiliaryImage":{"imageName":"3F29D2C0-BFAD-47F5-BF04-46C669F92C27"},"title":"","identifier":"","image":{"imageName":"D83FAB77-1713-4C02-BAFD-4C0C0D831BCD"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeResult.json new file mode 100755 index 0000000..b27e6c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeResult.json @@ -0,0 +1 @@ +{"_class":"ORKPasscodeResult","passcodeSaved":false,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","userInfo":{},"touchIdEnabled":false} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeStep.json new file mode 100755 index 0000000..1ea93b5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPasscodeStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "passcodeType":0,"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKPasscodeStep","iconImage":{"imageName":"AD57BE82-B09F-4325-A9EA-DE82F7C29610"},"auxiliaryImage":{"imageName":"3B3736C1-BD56-4237-9875-5C65FFFD0A37"},"title":"","identifier":"","footnote":"","image":{"imageName":"3F144446-AAAE-4D83-9860-46E99BB08AE1"},"text":"","useBiometrics":true, "passcodeFlow":0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPedometerRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPedometerRecorderConfiguration.json new file mode 100755 index 0000000..f42a2bf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPedometerRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKPedometerRecorderConfiguration","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPredicateStepNavigationRule.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPredicateStepNavigationRule.json new file mode 100755 index 0000000..2bc3435 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKPredicateStepNavigationRule.json @@ -0,0 +1 @@ +{"defaultStepIdentifier":"","destinationStepIdentifiers":[],"additionalTaskResults":[],"_class":"ORKPredicateStepNavigationRule","resultPredicates":[]} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionResult.json new file mode 100755 index 0000000..650b460 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionResult.json @@ -0,0 +1 @@ +{"questionType":0,"userInfo":{},"startDate":"2019-05-27T00:35:06-0700","_class":"ORKQuestionResult","identifier":"","endDate":"2019-05-27T00:35:06-0700"} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionStep.json new file mode 100755 index 0000000..73335bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKQuestionStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"answerFormat":{"_class":"ORKAnswerFormat"},"detailText":"", "headerTextAlignment": 0, "optional":true,"shouldTintImages":true,"useSurveyMode":true,"_class":"ORKQuestionStep","iconImage":{"imageName":"08814579-346A-4783-8F5E-4BC2F61E9FE5"},"auxiliaryImage":{"imageName":"61DAEC67-9E43-4B89-A3F8-BE87C9F87C3B"},"title":"","identifier":"","footnote":"","image":{"imageName":"B2C3112F-8A16-4A7C-9CCF-743FBAF9B993"},"text":"","placeholder":"","question":"","useCardView":true,"imageContentMode": 0, "learnMoreItem":{"_class":"ORKLearnMoreItem"},"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"tagText": ""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionResult.json new file mode 100755 index 0000000..b203ca0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionResult.json @@ -0,0 +1 @@ +{"finish":0,"_class":"ORKRangeOfMotionResult","maximum":0,"startDate":"2019-05-27T00:35:06-0700","start":0,"endDate":"2019-05-27T00:35:06-0700","range":0,"identifier":"","userInfo":{},"minimum":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionStep.json new file mode 100755 index 0000000..44862e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRangeOfMotionStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"F3331959-D3B6-43BA-A279-E1502B81DE5E"},"auxiliaryImage":{"imageName":"2C398061-2D1F-45E6-BCCF-F470628D51D1"},"title":"","image":{"imageName":"E1CF0E97-5E1A-4860-AF2D-D36FC5C427E3"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"limbOption":0,"detailText":"", "headerTextAlignment": 0, "stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKRangeOfMotionStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeResult.json new file mode 100755 index 0000000..f1fc8fc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeResult.json @@ -0,0 +1 @@ +{"_class":"ORKReactionTimeResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","fileResult":{"endDate":"2019-05-27T00:35:06-0700","_class":"ORKFileResult","startDate":"2019-05-27T00:35:06-0700"},"timestamp":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeStep.json new file mode 100755 index 0000000..dacfb78 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReactionTimeStep.json @@ -0,0 +1 @@ +{"shouldVibrateOnStart":false,"spokenInstruction":"","shouldStartTimerAutomatically":false,"successSound":0,"stepDuration":0,"shouldShowDefaultTimer":true,"optional":false,"minimumStimulusInterval":0,"detailText":"", "headerTextAlignment": 0, "text":"","_class":"ORKReactionTimeStep","useSurveyMode":false,"numberOfAttempts":0,"maximumStimulusInterval":0,"thresholdAcceleration":0,"bodyItems":[],"shouldVibrateOnFinish":false,"image":{"imageName":"282B623C-C013-4FDD-8721-4D2EB755598F"},"iconImage":{"imageName":"904E22CF-C9ED-485D-B9C4-6B47D351C10A"},"shouldPlaySoundOnStart":false,"auxiliaryImage":{"imageName":"64424C2B-9897-4A78-A79E-B1948817505A"},"failureSound":0,"shouldContinueOnFinish":true,"identifier":"","shouldSpeakRemainingTimeAtHalfway":false,"footnote":"","shouldSpeakCountDown":false,"timeout":0,"title":"","finishedSpokenInstruction":"","shouldUseNextAsSkipButton":false,"shouldPlaySoundOnFinish":false,"shouldTintImages":true,"timeoutSound":0,"recorderConfigurations":[],"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRecorderConfiguration.json new file mode 100755 index 0000000..52c4fb6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKRecorderConfiguration","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRegistrationStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRegistrationStep.json new file mode 100755 index 0000000..195c89c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKRegistrationStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "options":0,"optional":false,"useSurveyMode":true,"shouldTintImages":true,"_class":"ORKRegistrationStep","auxiliaryImage":{"imageName":"AE8E0687-1A0C-42C1-964A-E8F89E789B1E"},"iconImage":{"imageName":"4C7914C4-0EA8-4D43-A7B0-ECB2E3DE0FAC"},"title":"","identifier":"","footnote":"","image":{"imageName":"0BB5BA89-09CC-4DB0-B941-6A2D51834EC6"},"text":"","formItems":[],"useCardView":true,"imageContentMode": 0,"footerText":"","bodyItemTextAlignment":0,"buildInBodyItems": 0,"cardViewStyle":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResult.json new file mode 100755 index 0000000..8ebcfcd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResult.json @@ -0,0 +1 @@ +{"userInfo":{},"_class":"ORKResult","identifier":"","startDate":"2019-05-27T00:35:06-0700","endDate":"2019-05-27T00:35:06-0700"} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResultSelector.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResultSelector.json new file mode 100755 index 0000000..cb33d1f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKResultSelector.json @@ -0,0 +1 @@ +{"stepIdentifier":"","_class":"ORKResultSelector","taskIdentifier":"","resultIdentifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReviewStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReviewStep.json new file mode 100755 index 0000000..1a77a11 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKReviewStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKReviewStep","iconImage":{"imageName":"FC6FA284-33CF-4207-A766-E4B53D63D1FA"},"auxiliaryImage":{"imageName":"DF5BB476-8890-4AA0-9F39-D15A16D5FDF7"},"title":"","identifier":"","footnote":"","image":{"imageName":"C71BC697-7306-4B7D-99B7-62E7C9D0CEB2"},"excludeInstructionSteps":false,"text":"","resultSource":{"results":[],"_class":"ORKTaskResult","startDate":"2019-05-27T00:35:06-0700","endDate":"2019-05-27T00:35:06-0700"},"steps":[],"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESAnswerFormat.json new file mode 100755 index 0000000..70bd90b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESAnswerFormat.json @@ -0,0 +1 @@ +{"topRungText":"","bottomRungText":"","_class":"ORKSESAnswerFormat","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESQuestionResult.json new file mode 100755 index 0000000..2a9119d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSESQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKSESQuestionResult","questionType":0,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","rungPicked":0,"userInfo":{}} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleAnswerFormat.json new file mode 100755 index 0000000..ec4fd64 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleAnswerFormat.json @@ -0,0 +1 @@ +{"gradientColors":[],"minimumImage":{"imageName":"E24DF267-22A9-46D9-9551-1AA464833DB5"},"minimumValueDescription":"","maximum":100,"_class":"ORKScaleAnswerFormat","vertical":false,"gradientLocations":[],"minimum":0,"defaultValue":0,"hideSelectedValue":false,"hideRanges":false,"hideLabels":false,"hideValueMarkers":false,"step":10,"maximumImage":{"imageName":"9F3968E8-9C77-47D5-A225-93F4D02234B0"},"maximumValueDescription":"","showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleQuestionResult.json new file mode 100755 index 0000000..a48f999 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKScaleQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKScaleQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","scaleAnswer":123,"identifier":"","questionType":0,"userInfo":{}} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSecondaryTaskStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSecondaryTaskStep.json new file mode 100755 index 0000000..aeb4fb1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSecondaryTaskStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKSecondaryTaskStep","iconImage":{"imageName":"AA4B1340-91CA-43F8-8DFF-65D8072F47E0"},"auxiliaryImage":{"imageName":"51F527BE-5B1E-465A-9260-B79664443AC2"},"title":"","identifier":"","image":{"imageName":"EE23D70C-83EB-41CE-83FC-4D3D632322DE"},"footnote":"","text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"secondaryTask":{"_class":"ORKOrderedTask","identifier":"test1"},"secondaryTaskButtonTitle":"","nextButtonTitle":"","requiredAttempts":0,"centerImageVertically":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureResult.json new file mode 100755 index 0000000..9edd991 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureResult.json @@ -0,0 +1 @@ +{"userInfo":{},"_class":"ORKSignatureResult","identifier":"","startDate":"2019-05-27T00:35:06-0700","endDate":"2019-05-27T00:35:06-0700"} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureStep.json new file mode 100755 index 0000000..d63f84c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSignatureStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKSignatureStep","iconImage":{"imageName":"37EEFD54-6752-4FE3-A7AD-ABC987E21266"},"auxiliaryImage":{"imageName":"3FF8D308-8975-4B50-B016-28BA3E62C095"},"title":"","identifier":"","footnote":"","image":{"imageName":"10358617-E4C2-473F-8B22-9C68B4B8A5D9"},"text":"","detailText":"", "headerTextAlignment": 0, "imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameRecord.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameRecord.json new file mode 100755 index 0000000..9558748 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameRecord.json @@ -0,0 +1 @@ +{"touchSamples":[],"score":0,"sequence":[],"_class":"ORKSpatialSpanMemoryGameRecord","gameStatus":0,"seed":0,"gameSize":0,"targetRects":[]} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameTouchSample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameTouchSample.json new file mode 100755 index 0000000..72a3ca2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryGameTouchSample.json @@ -0,0 +1 @@ +{"correct":false,"timestamp":0,"_class":"ORKSpatialSpanMemoryGameTouchSample","targetIndex":0,"location":{"x":0,"y":0}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryResult.json new file mode 100755 index 0000000..38874ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryResult.json @@ -0,0 +1 @@ +{"_class":"ORKSpatialSpanMemoryResult","score":0,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","numberOfGames":0,"identifier":"","gameRecords":[],"numberOfFailures":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryStep.json new file mode 100755 index 0000000..8c7e98a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpatialSpanMemoryStep.json @@ -0,0 +1 @@ +{"spokenInstruction":"","shouldStartTimerAutomatically":true,"stepDuration":0,"shouldShowDefaultTimer":true,"requireReversal":false,"maximumSpan":0,"optional":false,"initialSpan":0,"detailText":"", "headerTextAlignment": 0, "minimumSpan":0,"_class":"ORKSpatialSpanMemoryStep","text":"","useSurveyMode":false,"bodyItems":[],"customTargetPluralName":"","shouldVibrateOnFinish":false,"image":{"imageName":"A8AB293A-10C1-41BE-ACFE-7AE22DE83E8B"},"iconImage":{"imageName":"DCA06D4F-5800-4E11-AE9C-127854AE5393"},"shouldPlaySoundOnStart":false,"maximumTests":0,"auxiliaryImage":{"imageName":"68CF68A4-DED8-4EC1-8246-D11AAEBA99D8"},"customTargetImage":{"imageName":"7F102C61-3C9D-420A-8C29-ED016F6C4E45"},"shouldContinueOnFinish":true,"identifier":"","shouldSpeakRemainingTimeAtHalfway":false,"footnote":"","shouldSpeakCountDown":false,"playSpeed":0,"maximumConsecutiveFailures":0,"title":"","finishedSpokenInstruction":"","shouldUseNextAsSkipButton":false,"shouldPlaySoundOnFinish":false,"shouldTintImages":true,"shouldVibrateOnStart":false,"recorderConfigurations":[],"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechInNoiseStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechInNoiseStep.json new file mode 100755 index 0000000..f63119b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechInNoiseStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"3994049A-3699-4491-B71D-80A8A5E018F1"},"auxiliaryImage":{"imageName":"AD8C88C5-00F7-416C-BB20-809FC47C5269"},"title":"","image":{"imageName":"D338CF69-B8EA-4532-BC00-337B3DA86BC0"},"shouldPlaySoundOnFinish":false,"willAudioLoop":false, "hideGraphView":false, "shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":true,"filterFileNameWithExtension":"","shouldVibrateOnFinish":false,"noiseFileNameWithExtension":"","gainAppliedToNoise":0,"spokenInstruction":"","speechFileNameWithExtension":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"bodyItems":[],"text":"","finishedSpokenInstruction":"","_class":"ORKSpeechInNoiseStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionResult.json new file mode 100755 index 0000000..403410b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionResult.json @@ -0,0 +1,61 @@ +{"userInfo":{},"_class":"ORKSpeechRecognitionResult","identifier":"","startDate":"2019-05-27T00:35:06-0700","endDate":"2019-05-27T00:35:06-0700", + "transcription" : { + "formattedString": "complete string", + "speakingRate" : 1.5, + "averagePauseDuration" : 1.0, + "segments" : [ + { + "substring" : "complete", + "substringRange" : { "location" : 0, "length" : 8}, + "timestamp" : 0.0, + "duration" : 0.5, + "confidence" : 1.0, + "alternativeSubstrings" : [ "test1", "test2" ], + "voiceAnalytics" : { + "jitter" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "shimmer" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "pitch" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "voicing" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + } + } + }, + { + "substring" : "string", + "substringRange" : { "location" : 9, "length" : 6}, + "timestamp" : 0.0, + "duration" : 0.5, + "confidence" : 1.0, + "alternativeSubstrings" : [ "test1", "test2" ], + "voiceAnalytics" : { + "jitter" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "shimmer" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "pitch" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + }, + "voicing" : { + "acousticFeatureValuePerFrame" : [ 1, 2, 3], + "frameDuration" : 0.5 + } + } + } + ] + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionStep.json new file mode 100755 index 0000000..23edcc3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKSpeechRecognitionStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"A7F86173-D719-4A24-80B1-84307C0CAF6F"},"auxiliaryImage":{"imageName":"FE592459-9F5E-41AB-B051-7EFCD8F7ADA4"},"title":"","image":{"imageName":"97352EFE-D43D-498A-B780-DCAADFB923E9"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"speechRecognitionText":"test","detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"shouldHideTranscript":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","speechRecognizerLocale":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKSpeechRecognitionStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStep.json new file mode 100755 index 0000000..5becdc7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKStep","iconImage":{"imageName":"1425D9D4-DB67-4B5D-93B0-FE3125E67262"},"auxiliaryImage":{"imageName":"5DEF32D5-D23E-4E8F-8C05-4B1D24E6257D"},"title":"","identifier":"","footnote":"","image":{"imageName":"DB613E0C-4491-457B-B958-C7FBE6232101"},"text":"","detailText":"","headerTextAlignment": 0,"imageContentMode": 0, "headerTextAlignment": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStepResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStepResult.json new file mode 100755 index 0000000..fa58eb8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStepResult.json @@ -0,0 +1 @@ +{"_class":"ORKStepResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","enabledAssistiveTechnology":"","isPreviousResult":false,"results":[],"identifier":"","userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStreamingAudioRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStreamingAudioRecorderConfiguration.json new file mode 100755 index 0000000..5f29854 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStreamingAudioRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKStreamingAudioRecorderConfiguration","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopResult.json new file mode 100755 index 0000000..d0ccaea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopResult.json @@ -0,0 +1 @@ +{"_class":"ORKStroopResult","color":"","endDate":"2019-05-27T00:35:06-0700","endTime":0,"startDate":"2019-05-27T00:35:06-0700","text":"","identifier":"","startTime":0,"userInfo":{},"colorSelected":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopStep.json new file mode 100755 index 0000000..326a6b2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKStroopStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"62E9D4CF-3E7B-49B8-A295-7D2EB1ECC00B"},"auxiliaryImage":{"imageName":"8C25AB92-00C9-4E13-B55F-711658F53D48"},"title":"","image":{"imageName":"4930AC43-8AAA-4563-8C8F-6E7E25E550C3"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":9.2233720368547758e+18,"shouldShowDefaultTimer":false,"numberOfAttempts":0,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":true,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKStroopStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTableStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTableStep.json new file mode 100755 index 0000000..e2ad43d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTableStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"allowsSelection":false,"detailText":"","headerTextAlignment": 0,"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKTableStep","auxiliaryImage":{"imageName":"C594DE5C-AB0F-468C-956E-8347C5E14E08"},"iconImage":{"imageName":"A3C3C914-C4ED-4633-9852-67D8AB687094"},"isBulleted":false,"title":"","identifier":"","footnote":"","image":{"imageName":"FC4CCE13-5C8A-434F-979C-1E48ADDEBBE0"},"items":[],"text":"","bulletType":0,"bulletIconNames":[],"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"pinNavigationContainer":false,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalResult.json new file mode 100755 index 0000000..c4a7f1a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalResult.json @@ -0,0 +1 @@ +{"_class":"ORKTappingIntervalResult","endDate":"2019-05-27T00:35:06-0700","samples":[],"startDate":"2019-05-27T00:35:06-0700","buttonRect2":{"origin":{"x":0,"y":0},"size":{"h":0,"w":0}},"identifier":"","buttonRect1":{"origin":{"x":0,"y":0},"size":{"h":0,"w":0}},"stepViewSize":{"h":0,"w":0},"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalStep.json new file mode 100755 index 0000000..fe0825e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingIntervalStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"E99E1E45-69C1-4A8D-B93A-8A2C21F83BF8"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"8C6E1C04-F1B1-4EA7-93F4-415FBEB3C489"},"title":"","image":{"imageName":"1DA566D1-4BE7-48C9-849B-8E30C0EE613A"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKTappingIntervalStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingSample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingSample.json new file mode 100755 index 0000000..de16f1a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTappingSample.json @@ -0,0 +1 @@ +{"buttonIdentifier":"none","timestamp":0,"_class":"ORKTappingSample","location":{"x":0,"y":0},"duration":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTaskResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTaskResult.json new file mode 100755 index 0000000..5c4436a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTaskResult.json @@ -0,0 +1 @@ +{"_class":"ORKTaskResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","outputDirectory":"file:\/\/\/usr\/","taskRunUUID":"FDFCC3EC-01B6-43E7-8200-9B93E2744BB8","identifier":"","results":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextAnswerFormat.json new file mode 100755 index 0000000..a13be6f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextAnswerFormat.json @@ -0,0 +1 @@ +{"secureTextEntry":false,"keyboardType":0,"validationRegularExpression":{"pattern":".","options":[]},"_class":"ORKTextAnswerFormat","spellCheckingType":0,"invalidMessage":"","maximumLength":0,"textContentType":"","passwordRules":{"rules":""},"autocorrectionType":0,"autocapitalizationType":0,"defaultTextAnswer":"","multipleLines":false,"showDontKnowButton":false,"customDontKnowButtonText":"","placeholder":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoice.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoice.json new file mode 100755 index 0000000..4a64917 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoice.json @@ -0,0 +1 @@ +{"exclusive":false,"value":"blah","_class":"ORKTextChoice","detailText":"","text":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceAnswerFormat.json new file mode 100755 index 0000000..5b559a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceAnswerFormat.json @@ -0,0 +1 @@ +{"style":"singleChoice","_class":"ORKTextChoiceAnswerFormat","textChoices":[],"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceOther.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceOther.json new file mode 100755 index 0000000..32af5ae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextChoiceOther.json @@ -0,0 +1 @@ +{"_class":"ORKTextChoiceOther","textViewInputOptional":false,"textViewStartsHidden":true,"exclusive":true,"text":"","value":"blah","textViewPlaceholderText":"","detailText":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextQuestionResult.json new file mode 100755 index 0000000..83b1042 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKTextQuestionResult","textAnswer":"","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextScaleAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextScaleAnswerFormat.json new file mode 100755 index 0000000..f24d804 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTextScaleAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKTextScaleAnswerFormat","hideSelectedValue":false,"hideRanges":false,"hideLabels":false,"hideValueMarkers":false,"vertical":false,"defaultIndex":0,"gradientColors":[],"textChoices":[{"exclusive":false,"value":1,"_class":"ORKTextChoice","text":"Poor"},{"exclusive":false,"value":2,"_class":"ORKTextChoice","text":"Excellent"}],"gradientLocations":[],"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalAnswerFormat.json new file mode 100755 index 0000000..df3c81c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalAnswerFormat.json @@ -0,0 +1 @@ +{"step":1,"_class":"ORKTimeIntervalAnswerFormat","defaultInterval":0,"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalQuestionResult.json new file mode 100755 index 0000000..48b30ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeIntervalQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKTimeIntervalQuestionResult","endDate":"2019-05-27T00:35:06-0700","intervalAnswer":123,"startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayAnswerFormat.json new file mode 100755 index 0000000..0564278 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayAnswerFormat.json @@ -0,0 +1 @@ +{"defaultComponents":"00:00","_class":"ORKTimeOfDayAnswerFormat","minuteInterval":0,"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayQuestionResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayQuestionResult.json new file mode 100755 index 0000000..84c513d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimeOfDayQuestionResult.json @@ -0,0 +1 @@ +{"_class":"ORKTimeOfDayQuestionResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","questionType":0,"dateComponentsAnswer":"00:00","userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkResult.json new file mode 100755 index 0000000..3ce48cb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkResult.json @@ -0,0 +1 @@ +{"_class":"ORKTimedWalkResult","timeLimit":0,"endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","identifier":"","duration":0,"distanceInMeters":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkStep.json new file mode 100755 index 0000000..cd0f317 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTimedWalkStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"distanceInMeters":0,"iconImage":{"imageName":"392B209E-E4E0-458A-9CF3-0C7DF89F6626"},"auxiliaryImage":{"imageName":"0690C295-21F0-4FD8-926B-A4ECE1396745"},"title":"","shouldPlaySoundOnFinish":true,"shouldPlaySoundOnStart":true,"image":{"imageName":"2167A19B-9B1F-4010-812B-0F254CD98D00"},"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":true,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":true,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKTimedWalkStep","shouldStartTimerAutomatically":true,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryResult.json new file mode 100755 index 0000000..38fa6cb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryResult.json @@ -0,0 +1 @@ +{"_class":"ORKToneAudiometryResult","outputVolume":123,"samples":[],"startDate":"2019-05-27T00:35:06-0700","endDate":"2019-05-27T00:35:06-0700","identifier":"","userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometrySample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometrySample.json new file mode 100755 index 0000000..6daece1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometrySample.json @@ -0,0 +1 @@ +{"channelSelected":0,"amplitude":0,"_class":"ORKToneAudiometrySample","channel":0,"frequency":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryStep.json new file mode 100755 index 0000000..bb41dba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKToneAudiometryStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"80051064-3F2B-4675-AB0C-5C2C841B6BD8"},"auxiliaryImage":{"imageName":"E7C93E74-A1F3-4FA7-887C-64254B197612"},"title":"","image":{"imageName":"06DE4520-4A3F-4E48-A331-84FA1BC2F05D"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","practiceStep":false,"optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKToneAudiometryStep","toneDuration":0,"shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchAnywhereStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchAnywhereStep.json new file mode 100755 index 0000000..c1a1a3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchAnywhereStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"shouldTintImages":true,"shouldSpeakCountDown":false,"iconImage":{"imageName":"661D3E94-889E-406B-A010-63E1E382D649"},"recorderConfigurations":[],"auxiliaryImage":{"imageName":"2F9EF951-6F59-413F-AC9A-4005401B6430"},"title":"","image":{"imageName":"A1753FF0-DF94-4966-863F-47542F37D42E"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKTouchAnywhereStep","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchRecorderConfiguration.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchRecorderConfiguration.json new file mode 100755 index 0000000..f154626 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTouchRecorderConfiguration.json @@ -0,0 +1 @@ +{"_class":"ORKTouchRecorderConfiguration","identifier":""} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiMove.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiMove.json new file mode 100755 index 0000000..978ca9a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiMove.json @@ -0,0 +1 @@ +{"timestamp":0,"_class":"ORKTowerOfHanoiMove","donorTowerIndex":0,"recipientTowerIndex":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiResult.json new file mode 100755 index 0000000..a0405ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiResult.json @@ -0,0 +1 @@ +{"_class":"ORKTowerOfHanoiResult","endDate":"2019-05-27T00:35:06-0700","startDate":"2019-05-27T00:35:06-0700","moves":[],"identifier":"","puzzleWasSolved":false,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiStep.json new file mode 100755 index 0000000..825ce56 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTowerOfHanoiStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"CF6F5959-510B-4131-99B0-2B625446CCE7"},"auxiliaryImage":{"imageName":"CEC9CBE5-4978-473A-B597-3BFD19AA17FD"},"title":"","image":{"imageName":"30F1BD7F-633F-41EA-8144-0E06BCA8C457"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":true,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":true,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":false,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKTowerOfHanoiStep","numberOfDisks":3,"shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingResult.json new file mode 100755 index 0000000..beb5c66 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingResult.json @@ -0,0 +1 @@ +{"_class":"ORKTrailmakingResult","endDate":"2019-05-27T00:35:06-0700","numberOfErrors":0,"startDate":"2019-05-27T00:35:06-0700","identifier":"","taps":[],"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingStep.json new file mode 100755 index 0000000..633f5c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":true,"shouldTintImages":true,"shouldSpeakCountDown":false,"recorderConfigurations":[],"iconImage":{"imageName":"6C57DF6B-CBDE-4763-906B-82204530AD07"},"auxiliaryImage":{"imageName":"3ED81064-D8E6-4D26-A2F0-9302EFB1058F"},"title":"","image":{"imageName":"3F2A9599-FE48-41D2-9169-ABB8EFD777C6"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"detailText":"","headerTextAlignment": 0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"bodyItems":[],"shouldVibrateOnStart":false,"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKTrailmakingStep","trailType":"","shouldStartTimerAutomatically":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingTap.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingTap.json new file mode 100755 index 0000000..effb38c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKTrailmakingTap.json @@ -0,0 +1 @@ +{"incorrect":false,"timestamp":0,"_class":"ORKTrailmakingTap","index":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKValuePickerAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKValuePickerAnswerFormat.json new file mode 100755 index 0000000..0c43f1a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKValuePickerAnswerFormat.json @@ -0,0 +1 @@ +{"_class":"ORKValuePickerAnswerFormat","textChoices":[],"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVerificationStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVerificationStep.json new file mode 100755 index 0000000..208aafd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVerificationStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"","headerTextAlignment": 0,"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKVerificationStep","iconImage":{"imageName":"A3D51283-8457-474E-83F9-8624BA60C7D5"},"auxiliaryImage":{"imageName":"E9559DA0-9EE9-4365-A75E-5DA1A9A458F3"},"title":"","identifier":"","footnote":"","image":{"imageName":"39D4B5C9-17BA-40B1-8EA2-E78B3BDA896F"},"text":"","verificationViewControllerString":"ORKVerificationStepViewController","imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoCaptureStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoCaptureStep.json new file mode 100755 index 0000000..fc03250 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoCaptureStep.json @@ -0,0 +1 @@ +{"accessibilityHint":"","shouldTintImages":true,"templateImageInsets":{"right":1,"top":1,"left":1,"bottom":1},"iconImage":{"imageName":"3EBEBF88-86DD-4500-8B48-B7F61F75C7A6"},"title":"","devicePosition":1,"auxiliaryImage":{"imageName":"7832E6A2-DA40-4CFA-AB16-808717B2CA4E"},"duration":123,"templateImage":{"imageName":"0DCC3994-3FA0-4A05-97AC-A3C82777010B"},"image":{"imageName":"D2B3C2CB-10D5-4C97-B0FF-208C38971A0F"},"detailText":"","headerTextAlignment": 0,"optional":true,"audioMute":false,"useSurveyMode":false,"identifier":"","bodyItems":[],"text":"","accessibilityInstructions":"","_class":"ORKVideoCaptureStep","torchMode":2,"footnote":"","imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStep.json new file mode 100755 index 0000000..5dc730e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"videoURL":"file:\/\/\/usr\/","optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKVideoInstructionStep","auxiliaryImage":{"imageName":"8EB1EFFE-C9DE-48C5-BD63-7B3182834B09"},"iconImage":{"imageName":"3AF26F65-958B-4EFA-974A-184B40D35D7A"},"title":"","identifier":"","footnote":"","image":{"imageName":"7025FEF9-6715-4499-B7C3-1C1AA8DDB3E1"},"text":"","thumbnailTime":0,"detailText":"","headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"centerImageVertically":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStepResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStepResult.json new file mode 100755 index 0000000..52dd794 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVideoInstructionStepResult.json @@ -0,0 +1 @@ +{"_class":"ORKVideoInstructionStepResult","endDate":"2019-05-27T00:35:06-0700","playbackCompleted":false,"startDate":"2019-05-27T00:35:06-0700","playbackStoppedTime":0,"identifier":"","userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVisualConsentStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVisualConsentStep.json new file mode 100755 index 0000000..51fa2ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKVisualConsentStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"consentDocument":{"_class":"ORKConsentDocument"},"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKVisualConsentStep","iconImage":{"imageName":"AB4D9A59-5D77-433F-819F-D1E150BF2A6E"},"auxiliaryImage":{"imageName":"B5A2597F-DF74-40F4-A6EB-E1A812C68A14"},"title":"","identifier":"","footnote":"","image":{"imageName":"DABD65A8-FABD-4049-99B6-E67E53EE123C"},"text":"","detailText":"","headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWaitStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWaitStep.json new file mode 100755 index 0000000..e41eb10 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWaitStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKWaitStep","indicatorType":0,"iconImage":{"imageName":"8AB7019D-38A4-4969-8A3B-4132B98A4D43"},"title":"","identifier":"","footnote":"","image":{"imageName":"D9D9BA3C-8AE2-45F2-9439-7AF519EF2BFA"},"auxiliaryImage":{"imageName":"589E582A-6BE4-4956-9895-0C07DE2DE0E4"},"text":"","detailText":"","headerTextAlignment": 0,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWalkingTaskStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWalkingTaskStep.json new file mode 100755 index 0000000..c042ea2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWalkingTaskStep.json @@ -0,0 +1 @@ +{"footnote":"","shouldContinueOnFinish":false,"recorderConfigurations":[],"shouldSpeakCountDown":false,"shouldTintImages":true,"iconImage":{"imageName":"B2C5CEC9-067F-42C7-ADD5-F6BDCB1AEB72"},"auxiliaryImage":{"imageName":"01708EE8-CC14-408A-AB15-4C9E9806172E"},"title":"","image":{"imageName":"10F66CE1-AA9F-4F9C-B51A-5AEED1B73A27"},"shouldPlaySoundOnFinish":false,"shouldPlaySoundOnStart":false,"numberOfStepsPerLeg":0,"detailText":"","headerTextAlignment": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0,"stepDuration":0,"shouldShowDefaultTimer":false,"shouldVibrateOnFinish":false,"spokenInstruction":"","optional":false,"useSurveyMode":false,"identifier":"","shouldUseNextAsSkipButton":false,"shouldVibrateOnStart":false,"bodyItems":[],"shouldSpeakRemainingTimeAtHalfway":false,"text":"","finishedSpokenInstruction":"","_class":"ORKWalkingTaskStep","shouldStartTimerAutomatically":false,"imageContentMode": 0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStep.json new file mode 100755 index 0000000..7b394f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"","headerTextAlignment": 0,"optional":false,"useSurveyMode":false,"shouldTintImages":true,"_class":"ORKWebViewStep","iconImage":{"imageName":"369C0323-EB2C-4BD7-8B1F-90030C5A1B8F"},"auxiliaryImage":{"imageName":"C1A70CC9-EC88-4525-A166-5DE6BD2CFA1A"},"title":"","identifier":"","image":{"imageName":"4DAC99C9-1BC9-42EA-95E7-CD746641F78A"},"footnote":"","text":"","html":"","customCSS":"","showSignatureAfterContent":false,"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStepResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStepResult.json new file mode 100755 index 0000000..a8da2f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWebViewStepResult.json @@ -0,0 +1 @@ +{"result":"","userInfo":{},"_class":"ORKWebViewStepResult","startDate":"2019-05-27T00:35:06-0700","identifier":"","endDate":"2019-05-27T00:35:06-0700"} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWeightAnswerFormat.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWeightAnswerFormat.json new file mode 100755 index 0000000..bf3bff6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKWeightAnswerFormat.json @@ -0,0 +1 @@ +{"defaultValue":0,"measurementSystem":"local","numericPrecision":0,"_class":"ORKWeightAnswerFormat","minimumValue":0,"maximumValue":0,"showDontKnowButton":false,"customDontKnowButtonText":""} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryFrequencySample.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryFrequencySample.json new file mode 100755 index 0000000..cd513ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryFrequencySample.json @@ -0,0 +1 @@ +{"units":[],"_class":"ORKdBHLToneAudiometryFrequencySample","channel":0,"frequency":0,"calculatedThreshold":1.0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryOnboardingStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryOnboardingStep.json new file mode 100755 index 0000000..aa3e8f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryOnboardingStep.json @@ -0,0 +1 @@ +{"bodyItems":[],"detailText":"", "headerTextAlignment": 0, "optional":true,"useSurveyMode":true,"shouldTintImages":true,"_class":"ORKdBHLToneAudiometryOnboardingStep","auxiliaryImage":{"imageName":"0255CA0B-11EA-4502-926A-07DCA0599AEC"},"iconImage":{"imageName":"B10BDAB3-6380-4F75-A5D3-7E334CD94C7D"},"title":"","identifier":"","footnote":"","image":{"imageName":"E2856DA0-1728-4A16-A468-9A940C0E6F95"},"text":"","formItems":[],"useCardView":true,"imageContentMode": 0,"footerText":"","bodyItemTextAlignment":0,"buildInBodyItems": 0,"cardViewStyle":0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryResult.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryResult.json new file mode 100755 index 0000000..635f53c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryResult.json @@ -0,0 +1 @@ +{"_class":"ORKdBHLToneAudiometryResult","headphoneType":"","outputVolume":0,"startDate":"2019-05-27T00:35:06-0700","samples":[],"endDate":"2019-05-27T00:35:06-0700","postStimulusDelay":0,"identifier":"","tonePlaybackDuration":0,"userInfo":{}} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryStep.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryStep.json new file mode 100755 index 0000000..7045a2a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryStep.json @@ -0,0 +1 @@ +{"postStimulusDelay":1,"spokenInstruction":"","headphoneType":"","shouldStartTimerAutomatically":false,"stepDuration":0,"shouldShowDefaultTimer":true,"optional":false,"detailText":"", "headerTextAlignment": 0, "earPreference":0,"text":"","_class":"ORKdBHLToneAudiometryStep","useSurveyMode":false,"initialdBHLValue":30,"dBHLStepDownSize":10,"dBHLMinimumThreshold":-10,"bodyItems":[],"maxNumberOfTransitionsPerFrequency":15,"shouldVibrateOnFinish":false,"iconImage":{"imageName":"90BF43E2-61B4-493A-A818-55FF314B240D"},"shouldPlaySoundOnStart":false,"image":{"imageName":"A660ED46-8FFE-4AFA-A3AA-AC9E134A20F0"},"auxiliaryImage":{"imageName":"99B355E5-D322-4C26-BA80-5701151B3352"},"shouldContinueOnFinish":false,"identifier":"","shouldSpeakRemainingTimeAtHalfway":false,"footnote":"","dBHLStepUpSize":5,"dBHLStepUpSizeFirstMiss":20,"dBHLStepUpSizeSecondMiss":10,"dBHLStepUpSizeThirdMiss":10,"shouldSpeakCountDown":false,"toneDuration":1,"frequencyList":[],"maxRandomPreStimulusDelay":2,"title":"","finishedSpokenInstruction":"","shouldUseNextAsSkipButton":false,"shouldPlaySoundOnFinish":false,"shouldTintImages":true,"shouldVibrateOnStart":false,"recorderConfigurations":[],"imageContentMode": 0,"bodyItemTextAlignment":0,"buildInBodyItems": 0,"useExtendedPadding":0} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryUnit.json b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryUnit.json new file mode 100755 index 0000000..6408fce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/ORKTestTests/samples.bundle/ORKdBHLToneAudiometryUnit.json @@ -0,0 +1 @@ +{"preStimulusDelay":0,"userTapTimeStamp":0,"timeoutTimeStamp":0,"_class":"ORKdBHLToneAudiometryUnit","startOfUnitTimeStamp":0,"dBHLValue":0} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/README.md b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/README.md new file mode 100755 index 0000000..129f08f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/Testing/ORKTest/README.md @@ -0,0 +1,48 @@ +# ORKTest + +The `ORKTest` project is an Objective-C test-bed used by the ResearchKit™ framework +developers to test API features during development. When adding a new +feature to the ResearchKit framework, please either add a way to test it in this +`ORKTest` project, or consider creating a new project to use for +testing. We also use this project to check for regressions. + +This project is not intended as an example of best practice in use of +the ResearchKit framework. For that, see the samples directory or the documentation +instead. + +Instead, this project should give good coverage of the features in +the ResearchKit framework. For example, the project enables localization to all the +supported languages, even though the survey content is not itself +localized. This allows us to test the localized parts of the ResearchKit framework, +but is not something you should do in a real app. As another example, +rotation is enabled on the iPhone, even though in real use it would be +atypical to enable rotation for most steps. + +The `ORKTest` tests include a module called `ORKESerialization`, a +JSON serialization module for the ResearchKit framework. `ORKESerialization` can +serialize and deserialize all the ResearchKit framework model objects, and all +ResearchKit framework results, to and from JSON. + + +## Build Requirements + ++ Xcode 7.0 ++ iOS 9.0 SDK or later + + +## Runtime Requirements + ++ iOS 8.0 or later + + +## Using the App + +You can run `ORKTest` on a device or in the iOS Simulator. + +To run on device, you will need to use a provisioning profile that +includes the appropriate HealthKit entitlement. + +When launching `ORKTest`, you will see an array of buttons. Each +button corresponds to a task that can be used for testing. Information +on the results and progress of the task are logged to the console. + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/coding-style-guide.md b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/coding-style-guide.md new file mode 100755 index 0000000..3e392a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/coding-style-guide.md @@ -0,0 +1,445 @@ +## ResearchKit Coding Style Guide + +Always follow the [Coding Guidelines for Cocoa](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/CodingGuidelines.html) for naming variables, properties, methods, classes and functions. Do not use any abbreviations except the ones mentioned in [Acceptable Abbreviations and Acronyms](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html#//apple_ref/doc/uid/20001285-BCIHCGAE). + + +### 1. Visual Style + +#### 1.1. Whitespace + +##### Indent with Spaces + +Use groups of 4 spaces (instead of tabs) to denote different indentation levels. + +*Xcode* does this by default. Double-check your settings in: `Preferences -> Text Editing -> Indentation`. + +![Xcode indentation settings](https://cloud.githubusercontent.com/assets/444313/7571539/25cced36-f810-11e4-8568-b824838a7070.png) + +##### Spaces in Declarations + +Single spaces should be used in the cases detailed in this section. Don't use double spaces and don't add spaces elsewhere. + +--- + +In `@interface` declarations, there should be one space between: the subclass name; the colon symbol; the superclass name; the adopted protocols section; and any adopted protocols. + + // DO + @interface ORKProtocolAdoptingClass : NSObject + + // DON'T + @interface ORKProtocolAdoptingClass:NSObject + @interface ORKProtocolAdoptingClass : NSObject + @interface ORKProtocolAdoptingClass : NSObject + +--- + +In `@property` declarations, there should be one space between: the `@property` keyword; the property attributes section; any property attribute; the property type; and the pointer asterisk. + + // DO + @property (nonatomic, weak, nullable) id delegate; + + // DON'T + @property(nonatomic, weak, nullable) id delegate; + @property (nonatomic,weak,nullable) id delegate; + @property (nonatomic, weak, nullable) iddelegate; + +--- + +In *method* declarations, there should be one space between: the `-` or `+` character and the `(returnType)`; and any argument type and its pointer asterisk. + + // DO + - (void)doSomethingWithString:(NSString *)string number:(NSNumber *)number + + // DON'T + -(void)doSomethingWithString:(NSString *)string number:(NSNumber *)number + - (void)doSomethingWithString:(NSString*)string number:(NSNumber *)number + - (void)doSomethingWithString:(NSString *)string number:(NSNumber *)number + +--- + +In *variable* declarations, add one space between the type and the pointer asterisk, and omit it between the asterisk and the variable name. + +Similarly, omit the space between the asterisk and non-prefixed variable modifiers such as `const`. On the other hand, use one exactly one space before underscored annotations such as `_Nullable` or `_Nonnull`. + + // DO + ORKTask *task = [ORKTask new]; + static NSString *const ActivityUnknown = @"unknown"; + CGFloat ORKWidthForSignatureView(UIWindow * _Nullable window); + - (BOOL)recreateFileWithError:(NSError * _Nullable *)error; + + +##### Spaces between Operators + +Use spaces if the operator has two or more arguments: + + // DO + steps += 2 + calories = 5 + calories == caloryGoal + goalAchieved && notReminded + flightsClimbed > 4 + success ? YES : NO + +Omit the space when the operator takes only one argument: + + // DO + calories++ + &error + !success + + +##### Spaces in array and dictionary literals + +Add exactly one space before the first and after the last element in array and dictionary literals. Use exactly one space after each comma-separated element. Do not add any space between the key and the colon symbol on dictionary literals, but add exactly one space between the colon and the pointed object. + + // DO + @[ @"Abdomen", @"Chest", @"Back" ]; // Array literal + @{ @"red": redImage, @"blue": blueImage }; // Dictionary literal + + // DON'T + @[ @"Abdomen",@"Chest",@"Back" ]; + @{ @"red" : redImage, @"blue":blueImage }; + + +#### 1.2. Brackets + +Opening brackets should be on the same line as the statement they refer to. Closing brackets should be on their own line, except when followed by `else`. + + // DO + - (void)doSomethingWithString:(NSString *)string { + if (condition) { + ... + } else { + ... + } + } + + // DON'T + - (void)doSomethingWithString:(NSString *)string + { + if (condition) + { + ... + } + else + { + ... + } + } + +Always use brackets even when the conditional code is only one statement. + + // DO + if (condition) { + return; + } + + // DON'T + if (condition) + return; + + +#### 1.3. Line Wrapping + +Hard-wrap lines that exceed 140 characters. You can configure the column guide on *Xcode*: `Preferences -> Text Editing -> Page guide at column: 140`. + +When hard-wrapping method calls, give each parameter its own line. Align each parameter using the colon before the parameter (*Xcode* does this for you by default). + + // DO + - (void)doSomethingWithFoo:(Foo *)foo + bar:(Bar *)bar + interval:(NSTimeInterval)interval { + ... + +Method invocations should be formatted much like method declarations. Invocations should have all arguments on one line or have one argument per line, with colons aligned. + + // DO + [myObject doSomethingWithFoo:foo bar:bar interval:interval]; + + [myObject doSomethingWithFoo:foo + bar:bar + interval:interval]; + + // DON'T + [myObject doSomethingWithFoo:foo bar:bar + interval:interval]; + + [myObject doSomethingWithFoo:foo + bar:bar + interval:interval]; + +#### 1.4. Appledoc Header Comments + +*ResearchKit* uses [appledoc](http://appledoc.gentlebytes.com/appledoc/) to generate its documentation from specially marked comments in header files. + +Follow these guidelines when writing *appledoc comments*: + +- Multiline *appledoc comments* start with the `/**` character sequence. +- When documenting methods, use the `@param` and `@return` keywords to detail the parameters and return value. +- When you name classes or methods, enclose them in backticks so *appledoc* creates a reference (`` `ORKStep` is ...``). +- For multiline code examples, surround them with a triple backtick (```) for cross references within the code block not to be automatically generated. +- Don't use abbreviations such as *e.g.* or *i.e.* in the documentation. +- Hard-wrap comment lines at column 100. +- Read the latest *ResearchKit* documentation for inspiration and try to follow the same literary style. + +#### 1.5. Newlines + +Use exactly two empty lines to separate: + +- The `/* Copyright header */` and the `#import` section. +- The `#import` section and the class `@interface` or `@implementation` line (or its associated *forward declarations* or *appledoc comment*). +- Different `@interface` or `@implementation` sections within the same file. + +Do not use two or more empty lines in any other cases. + +Use exactly one empty line to separate: + +- The last *forward declaration* and the *`@interface` declaration*. +- The *`@interface` declaration* and the first *method* or *property declaration*. +- The last *method* or *property declaration* and the *`@end` keyword*. +- The *`@implementation` line* and the first *method definition*. +- The closing bracket of the last *method definition* and the *`@end` keyword*. +- The *`@param` section* and the *`@return` line* in an *appledoc comment*. + +*Header* and *implementation* files must have one, and only one, trailing empty line. + +Do not use empty lines to separate: + +- *Forward declarations* from other contiguous *forward declarations*. +- An *appledoc comment* from its related *class* or *method*. +- Contiguous *`@param` lines* within the same *appledoc comment*. +- Last statement in a method definition and its closing bracket. + +Note that *forward declarations* should appear before any *class appledoc comment*. + +You can optionally use one (and only one) blank like to separate: + +- Groups of related `#import` statements. +- Groups of related statements in a single method implementation. + + + +### 2. Code Style + +#### 2.1. Variable Declarations + +Declare one variable per line even if they have the same type. In general it's a good idea to initialize primitive type variables with a reasonable value. + + // DO + int floatVariable = -1; + double doubleVariable = 0.0; + int *cPointerVariable = NULL; + CGContextRef context = NULL; + +Strong, weak, and autoreleasing stack variables are [implicitly initialized with `nil`](https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW5) so you can either explicitly initialize them (with `nil` or any valid object) for visual homogeneity, or skip initializing them altogether. + + // DO + id object = nil; + NSString *string = nil; + UIView *view = nil; + // ALSO OK + id object; + NSString *string; + UIView *view; + +When declaring pointers, there should be a space between the asterisk and the variable type, but none between the asterisk and the variable. + + // DON'T + int* variablePointer2; + int* variablePointer, variable; + UIView* view; + + +#### 2.2. Forward Declarations + +Use one line for each forward declarations: + + // DO + @protocol ORKProtocol; + @protocol ORKAnotherProtocol; + @class ORKClass; + @class ORKAnotherClass; + @class ORKYetAnotherClass; + + // DON'T + @protocol ORKProtocol, ORKAnotherProtocol; + @class ORKClass, ORKAnotherClass, ORKYetAnotherClass; + + +#### 2.3. Constant Declarations + +If a constant is only used inside one method, declare it locally to that method. If a constant is used in several methods of a single class, declare it as a `static` constant in the class implementation file. If a constant is used from several files, declare it as an `extern` constant and prefix its name with a suitable `ORK*` prefix. + +Static or global constant names should start in uppercase. Constants should never start with the `k` prefix (that naming convention is deprecated). These rules also apply to `enum` value names. + + // Method-local constant + - (void)animateView { + const CGFloat animationDuration = 0.2; + ... + } + + + // Class-local constant + static const CGFloat DefaultLineWidth = 10.0; + - (void)init { + if (self = [super init]) { + _lineWidth = DefaultLineWidth + ... + } + return self; + } + + - (void)resetView { + _lineWidth = DefaultLineWidth + ... + } + + + // Global constant + + // ORKSkin.h + ORK_EXTERN NSString *const ORKToolBarTintColorKey; + ORK_EXTERN const CGFloat ORKScreenMetricMaxDimension; + + // ORKSkin.m + NSString *const ORKBackgroundColorKey = @"ORKBackgroundColorKey"; + const CGFloat ORKScreenMetricMaxDimension = 10000.0; + + + // Global enum + typedef NS_ENUM(NSInteger, ORKQuestionType) { + ORKQuestionTypeNone, + ORKQuestionTypeScale, + ... + } ORK_ENUM_AVAILABLE; + + + +#### 2.4. Dot Notation + +Dot notation (`object.property`) is a syntax for using properties in a convenient and compact way. Accessing or setting a property through dot notation is completely equivalent to calling the property accessor methods: + + - (PropertyType *)property + - (void)setProperty:(PropertyType *)property + + // DO + NSString *oldName = user.name; // Equivalent to 'NSString *oldName = [user name]' + user.name = @"John Appleseed"; // Equivalent to '[user setName:@"John Appleseed"]' + +Dot notation should be used when accessing proper properties, but should be avoided when invoking regular methods. Use the syntax corresponding to the official documentation or relevant header declaration. + + // DO + CGRect viewFrame = view.frame; // Declared as a property + NSUInteger numberOfItems = array.count; // Declared as a property since iOS 8 + NSUInteger stringLength = string.length; // Declared as a property since iOS 8 + [autoreleasePool drain]; // A method + NSArray *constraints = [view constraints]; // A method + + // DON'T + CGRect viewFrame = [view frame]; // 'frame' is not declared as a method + NSUInteger numberOfItems = [array count]; // 'count' is no longer declared as a method + NSUInteger stringLength = [string length]; // 'length' is no longer declared as a method + autoreleasePool.drain; // Not a property + NSArray *constraints = view.constraints; // Not a property + +#### 2.5. Nullability Annotations + +Always include [*nullability annotations*](https://developer.apple.com/swift/blog/?id=25) in header files. + +Generally, it's a good idea to make the entirety of headers as *audited for nullability*, which makes any simple pointer type to be assumed as `nonnull` by the compiler. You do this by wrapping the whole file with the `NS_ASSUME_NONNULL_BEGIN` and `NS_ASSUME_NONNULL_END` macros. You can then opt any property or argument declaration that can take `nil` values out by annotating it as `nullable`. + + // DO + + NS_ASSUME_NONNULL_BEGIN + + - (instancetype)initWithStep:(nullable ORKStep *)step; + @property (nonatomic, copy, nullable) NSString *aNullableProperty; + + NS_ASSUME_NONNULL_END + + +When annotating function or blocks, use the `_Nullable` keyword (available since Xcode 7), instead of the legacy `__nullable`. + + // DO + CGFloat ORKWidthForSignatureView(UIWindow * _Nullable window); + + // DON'T + CGFloat ORKWidthForSignatureView(UIWindow * __nullable window); + +Do not add *nullability annotations* to implementation files. + +See **Section 3** for a nullability-annotated *Header File Example*. + + +#### 2.6. Lightweight Generics + +Always use [*lightweight generic parametrization*](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-ID173) when declaring `NSArray`, `NSSet` and `NSDictionary` types. This tells the compiler which kind of objects these *Foundation collection classes* will contain. It improves type-safety and interoperability with *Swift*. + +Use the same whitespace rules as when declaring *protocol conformance*, but omit the space between the type and the opening bracket: + + // DO + @property NSArray *steps; + @property NSDictionary *stepNavigationRules; + @property NSSet *tasks; + + // DON'T + @property NSArray *steps; + @property NSDictionary *stepNavigationRules; + @property NSSet *tasks; + + +### 3. Header File Example + + /* + Copyright (c) 2015, John Appleseed. All rights reserved. + ... + */ + + + #import + #import + + + NS_ASSUME_NONNULL_BEGIN + + @protocol ORKTask; + @class ORKStep; + + /** + appledoc class comment. + */ + ORK_CLASS_AVAILABLE + @interface ORKMyClass : NSObject + + /** + appledoc method comment. + + @param parameterA The first parameter. + @param parameterB The second parameter. + + @return A new MyClass. + */ + - (instancetype)initWithParameterA:(NSString *)parameterA parameterB:(NSString *)parameterB NS_DESIGNATED_INITIALIZER; + + /** + appledoc property comment. + */ + @property (nonatomic, copy, readonly) NSString *aProperty; + + /** + appledoc property comment. + */ + @property (nonatomic, copy, nullable) NSString *aNullableProperty; + + @end + + + /** + appledoc class comment. + */ + ORK_CLASS_AVAILABLE + @interface ORKMyOtherClass : ORKMyClass + + @end + + NS_ASSUME_NONNULL_END diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/dependency-management.md b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/dependency-management.md new file mode 100755 index 0000000..a762c5e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/dependency-management.md @@ -0,0 +1,29 @@ +Dependency Management +=========== + +The ResearchKit framework can also be added to your app using CocoaPods or Carthage. + +Prerequisites +------------ + +* [Git](https://www.git-scm.com) 2.19 or later (`git --version`) +* [Git-LFS](https://git-lfs.github.com) 2.4.2 or later (`git-lfs --version`) +* [CocoaPods](https://cocoapods.org) 1.0 or later (`pod env --version`) +* [Carthage](https://github.com/Carthage/Carthage) 0.30 or later (`carthage version`) + + +Installation with CocoaPods +------------ +Add the following line to your [Podfile](http://guides.cocoapods.org/syntax/podfile.html) and run `pod install`: + +```ruby +pod 'ResearchKit', '~> 1.0' +``` + +Installation with Carthage +------------ +Add the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile) and run `carthage update`: + +``` +github "ResearchKit/ResearchKit" "stable" +``` diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/reviewing-guidelines.md b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/reviewing-guidelines.md new file mode 100755 index 0000000..1a618ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs-standalone/reviewing-guidelines.md @@ -0,0 +1,73 @@ +## ResearchKit Reviewing Guidelines + +Apple, from time to time, may grant write permissions to trusted external contributors so they can review and merge *Pull Requests*; and edit, label and close *Issues*. + +### Basic Guidelines + +These are the requisites that must be met before a Pull Request can be merged. + +*Pull Request* must have at least two *Approve GitHub* reviews before they can be merged. The reviews must be done by at least one reviewer from *Apple*, and one reviewer who is from a different institution than the *Pull Request* initiator (either from *Apple* or an external write-access contributor). + +An exception to this rule are *Pull Requests* which have been received one *Approve* review by a write-access contributor from a different organization than the initiator, and have remained inactive for five business days since the *Approval* was received (comments count as activity and invalidate this exception). + +If you start reviewing a *Pull Request*, please label it as `In Review` and comment on the *Pull Request* stating so, so other contributors are aware that you will be looking into it. + + +### Reviewing Pull Requests + +This section provides some guidance when reviewing Pull Requests from other contributors. + +#### 1. Be Thorough + +Reviewing contributions is an important task, so try to be thorough. + +Always be polite, but don't be afraid to be too nit-picking or to annoy contributors by requesting changes. The code base will benefit from simplicity, correctness and homogeneity in any new code. + +#### 2. Check the ResearchKit Coding Style Guide + +Make sure all Pull Requests follow the [*ResearchKit Coding Style Guide*](https://github.com/ResearchKit/ResearchKit/blob/master/docs-standalone/coding-style-guide.md). + +Verify that the code is coherent with the existing codebase. Make sure that new APIs follow *ResearchKit* and *UIKit* patterns and conventions. + +#### 3. Test new code + +Before approving a Pull Request, make sure to test the submitted code. + +If the *Pull Request* adds new functionality, try to test it as thoroughly as possible. Compare it to similar *ResearchKit* or *iOS* functionality, and try to think ways it could be more consistent or more simple. Request example tasks in `ORKCatalog` or `ORKTest` if you feel they do not cover all use cases. + +If the Pull Request fixes an issue, verify that the issue is no longer present. Think of edge cases. For visual issues, try to test it on as many screen sizes as possible using the *iPhone and iPad Simulators*. + +#### 4. A partial review is better than no review + +If you feel you have valuable feedback on any *Pull Request*, don't be afraid to share your comments. + +If you feel you can partially review a *Pull Request*, review what you can and request additional help. + +Apple doesn't want to discourage anybody from contributing to *ResearchKit*, no matter their experience level. + +Don't be discouraged by these guidelines! + + +### Editing Issues + +This section contains some light guidance for editing *Issues*. + +#### 1. Clarifying Issues + +If you see a new, unlabeled issue, try to label it appropriately. + +If you feel that you can clarify or provide more information on an *Issue*, please comment on it. + +#### 2. Linking Issues + +If you see an *Issue* which has a related *Pull Request* but they are not linked, comment on the *Issue* with a link to the *Pull Request* or vice versa so they're visibly linked. + +#### 3. Closing Issues + +If you feel that an *Issue* can be closed, verify that the problem is gone before doing so. + +Do not close unresolved issues solely due to inactivity. + +--- + +*Apple* and the whole *ResearchKit* community is grateful for your contributions. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Account-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Account-template.markdown new file mode 100755 index 0000000..eda100b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Account-template.markdown @@ -0,0 +1,97 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +# The Account Module +Registration is an important aspect of validating users of your ResearchKit app. The Account module provides all of the logic to perform this necessary functionality. + +The basic operations of the Account module include: + + * Registration, during which the user can enter an email address, password, and additional information such as first and last name, gender, and date of birth. + * Verification, when your app can vet new users. In order to properly vet new users, your app can opt to perform a verification step after registration. + * Login, which allows registered and verified users to access your app. After your user has registered and verified their registration, this operation allows them to log in to your app. + +##Register New Users +To register new users, use the `ORKRegistrationStep` class. The resulting view shows a title and helpful registration text. There, the user can type an email address and password, along with other optional information. + +The following example specifies a registration step that includes requesting the user's full name, gender, and birthday: + + ORKRegistrationStep *registrationStep = [[ORKRegistrationStep alloc] initWithIdentifier:@"identifier" + title:@"Account Registration" text:@"Please register at this point." + options:ORKRegistrationStepIncludeGivenName | ORKRegistrationStepIncludeFamilyName | ORKRegistrationStepIncludeGender |ORKRegistrationStepIncludeDOB]; + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"registrationTask" steps:@[registrationStep]]; + ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + taskViewController.delegate = self; + [self presentViewController:taskViewController animated:YES completion:^{}]; + + +Figure 1 shows the registration view. + +
+
+ +
Figure 1. Registration
+
+
+ +After all of the information has been properly set, the user can touch the Done button to proceed. Your app is responsible for sending the user-provided data to a server to perform the actual registration. + +##Verify Users +Email verification is a common way to validate proper registration for a user. After the user registers, your backend server can send an email to the provided email address. + +To enable email verification in your app, use a combination of the `ORKVerificationStep` class along with a subclass of the `ORKVerificationStepViewController`. Subclassing `ORKVerificationStepViewController` allows you to provide custom behavior when the user taps the Resend Email Verification button. Here's how to set up your subclass: + + @interface MyVerificationStepViewController : ORKVerificationStepViewController + @end + + @implmentation MyVerificationStepViewController + + - (void)resendEmailButtonTapped { + // perform custom logic here + } + + @end + +Next, create a verification step and pass in the subclass object: + + ORKVerificationStep *verificationStep = [[ORKVerificationStep alloc] initWithIdentifier:@"identifier" + text:@"Please verify." + verificationViewControllerClass:[MyVerificationStepViewController class]]; + +You can then insert the step into your `ORKOrderedTask` object. When the step is executed, it instantiates the view controller, as shown in Figure 2. + +
+
+ +
Figure 2. Verification
+
+
+ +##Allow Users to Login +After the user has registered and has been verified, you can provide them access to further functionality in your app by helping them log in. + +Logging in requires subclassing the `ORKLoginStepViewController` class, which is similar to what you did to implement the verification step. Override the following method in your subclass so that you can add custom logic to handle the situation when the user forgets their password: + + - (void)forgotPasswordButtonTapped; + + +Here's a code snippet that shows how to create a subclass of `ORKLoginStepViewController`: + + @interface MyLoginStepViewController : ORKLoginStepViewController + @end + + @implmentation MyLoginStepViewController + + - (void)forgotPasswordButtonTapped { + // perform custom logic here + } + + @end + +When the login step executes, the view shown in Figure 3 appears. + +
+
+ +
Figure 3. User login
+
+
diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Login.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Login.png new file mode 100755 index 0000000..bff6845 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Login.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Registration.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Registration.png new file mode 100755 index 0000000..e541452 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Registration.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Verification.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Verification.png new file mode 100755 index 0000000..b6184c9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Account/Verification.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ActiveTasks-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ActiveTasks-template.markdown new file mode 100755 index 0000000..b079ea4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ActiveTasks-template.markdown @@ -0,0 +1,601 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +# Active Tasks + +Active tasks invite users to perform activities under partially +controlled conditions while iPhone sensors are used to collect data. +For example, an active task for analyzing gait and balance might ask +the user to walk a short distance, while collecting accelerometer data on the device. + +## Predefined Active Tasks + +ResearchKit™ includes a number of predefined tasks, which fall into seven categories: motor activities, fitness, cognition, speech, hearing, hand dexterity, and vision. Table 1 summarizes each task and describes the data it generates. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table 1. Active tasks in ResearchKit
CATEGORYTASKSENSORDATA COLLECTED
Motor ActivitiesRange of MotionAccelerometer
+ Gyroscope
Device motion
Gait and BalanceAccelerometer
+ Gyroscope
Device motion
Pedometer
Tapping SpeedMulti-Touch display
+Accelerometer (optional) +
Touch activity
+
FitnessFitnessGPS
Gyroscope
Device motion
Pedometer
Location
Heart rate +
Timed WalkGPS
Gyroscope
Device motion
Pedometer
Location +
CognitionSpatial MemoryMulti-Touch display
+Accelerometer (optional)
+Touch activity
Correct answer
Actual sequences +
Stroop TestMulti-Touch displayActual color
Actual text
User selection
Completion time
Trail Making TestMulti-Touch displayCompletion time
Touch activity
Paced Serial Addition Test (PSAT)Multi-Touch displayAddition results from user
Tower of HanoiMulti-Touch display +Every move taken by the user +
Reaction TimeAccelerometer
Gyroscope +
Device motion +
SpeechSustained PhonationMicrophoneUncompressed audio
Speech RecognitionMicrophoneRaw audio recording
Transcription in the form of an SFTranscription object.
Edited transcript (if any, by the user)
Speech-in-NoiseMicrophoneRaw audio recording
Transcription in the form of an SFTranscription object
Edited transcript (if any, by the user). This can be used to calculate the Speech Reception Threshold (SRT) for a user.
HearingEnvironment SPLMicrophoneEnvironment sound pressure level in dBA
Tone AudiometryAirPods
+Headphones
Minimum amplitude for the user +to recognize the sound
dBHL Tone AudiometryAirPods
+Headphones
+Hearing threshold in dB HL scale
+User response timestamps +
Hand Dexterity9-Hole PegMulti-Touch displayCompletion time
Move distance +
VisionAmsler GridMulti-Touch displayTouch activity
Eye side
Areas of distortions as annotated by the user
+ +You can disable the instruction or completion steps that are automatically +included in the framework by passing appropriate options when you create an active task. See the +`ORKPredefinedTaskOption` constants for the available options. + +You can use options flags to exclude data collection for data types that are not needed for your study. For example, to perform the fitness task without recording heart rate data, use the `ORKPredefinedTaskOptionExcludeHeartRate` option. + +## Range of Motion +In the range of motion task, participants follow movement instructions while accelerometer and gyroscope data is captured to measure flexed and extended positions for the knee or shoulder. Range of motion steps for the knee are shown in Figure 1. + +

Instruction step introducing the task

+

Instruction step introducing the task

+

Specific instructions with an illustration

+

+

Further instructions with an illustration

+

A touch anywhere step

+

A further touch anywhere step

+

Confirms task completion

+

+
Figure 1. Range of motion steps for the right knee
+ +## Gait and Balance + +In the gait and balance task (see the method [ORKOrderedTask shortWalkTaskWithIdentifier:intendedUseDescription:numberOfStepsPerLeg:restDuration:options]([ORKOrderedTask shortWalkTaskWithIdentifier:intendedUseDescription:numberOfStepsPerLeg:restDuration:options:])), +the user walks for a short distance, which may be indoors. You might +use this semi-controlled task to collect objective measurements that +can be used to estimate stride length, smoothness, sway, and other +aspects of the participant's walking. + +Gait and balance steps are shown in Figure 2. + +

Welcome/introduction ScreenInstruction step introducing the task

+

Instruction step introducing the task

+

Count down a specified duration into the task

+

+

Asking user to walk

+

Asking user to walk

+

Asking user to rest

+

+

Confirms task completion

+

+
Figure 2. Gait and balance steps
+ +## Tapping Speed + +In the tapping task (see the method [ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:intendedUseDescription:duration:handOptions:options]([ORKOrderedTask twoFingerTappingIntervalTaskWithIdentifier:intendedUseDescription:duration:handOptions:options:])), the user rapidly alternates between tapping two +targets on the touch screen. The resulting touch data can be used to +assess basic motor capabilities such as speed, accuracy, and rhythm. + +Touch data, and optionally accelerometer data from CoreMotion in iOS, are +collected using public APIs. No analysis is performed by the ResearchKit framework on the data. + +Tapping speed steps are shown in Figure 3. + +

Instruction step introducing the taskInstruction step introducing the task

+

Providing instruction for the right hand task

+

The user rapidly taps on the targets using the right hand

+

+

Providing instruction for the left hand task

+

The user rapidly taps on the targets using the left hand

+

Confirms task completion

+

+
Figure 3. Tapping speed steps
+ +## Fitness + +In the fitness task (see the method [ORKOrderedTask fitnessCheckTaskWithIdentifier:intendedUseDescription:walkDuration:restDuration:options]([ORKOrderedTask fitnessCheckTaskWithIdentifier:intendedUseDescription:walkDuration:restDuration:options:])), the user walks for a specified duration (usually +several minutes). Sensor data is collected and returned through the +task view controller's delegate. Sensor data can include +accelerometer, device motion, pedometer, location, and heart rate data +where available. + +Toward the end of the walk, if heart rate data is available, the user +is asked to sit down and rest for a period. Data collection continues +during the rest period. + +Fitness steps are shown in Figure 4. + +

Instruction step introducing the task

+

Instruction step introducing the task

+

Count down a specified duration to begin the task

+

Displays distance and heart rate

+

The rest step, which can be skipped if heart rate data is unavailable

+

Confirms task completion

+

+
Figure 4. Fitness task
+ +All of the data is collected from public CoreMotion and HealthKit APIs on iOS, and serialized to JSON. No analysis is applied to the data by the ResearchKit framework. + +## Timed Walk + +In the timed walk task (see the method [ORKOrderedTask timedWalkTaskWithIdentifier:intendedUseDescription:distanceInMeters:timeLimit:turnAroundLimit:includeAssistiveDeviceForm:options:]([ORKOrderedTask timedWalkTaskWithIdentifier:intendedUseDescription:distanceInMeters:timeLimit:turnAroundLimit:includeAssistiveDeviceForm:options:])), the user is asked to walk quickly and safely for a specific distance. The task is immediately administered again by having the user walk the same distance in the opposite direction. The timed walk task differs from both the fitness and the short walk tasks in that the distance walked by the user is fixed. A timed walk task measures the user's lower-extremity function. + +The data collected by this task includes accelerometer, device motion, pedometer data, and location of the user. Note that the location is available only if the user agrees to share their location. +Data collected by the task is in the form of an `ORKTimedWalkResult` object. + +Timed walk steps are shown in Figure 5. + +

Welcome/introduction ScreenInstruction step introducing the task

+

Gather information about the user's assistive deviceGathers information about the user's assistive device

+

Instruction to perform the taskInstructions on how to perform the task

+

+

Count down a specified duration to begin the taskCount down a specified duration to begin the task

+

Actual task screenActual task screen

+

Instruct the user to turn aroundInstruct the user to turn around

+

+

Actual task screenActual task screen

+

Task Completion screenTask completion

+

+
Figure 5. Timed walk steps
+ +## Spatial Memory + +In the spatial memory task (see the method [ORKOrderedTask spatialSpanMemoryTaskWithIdentifier:intendedUseDescription:initialSpan:minimumSpan:maximumSpan:playSpeed:maximumTests:maximumConsecutiveFailures:customTargetImage:customTargetPluralName:requireReversal:options:]([ORKOrderedTask spatialSpanMemoryTaskWithIdentifier:intendedUseDescription:initialSpan:minimumSpan:maximumSpan:playSpeed:maximumTests:maximumConsecutiveFailures:customTargetImage:customTargetPluralName:requireReversal:options:])), +the user is asked to observe and then recall pattern sequences of +increasing length in a game-like environment. The task collects data that +can be used to assess visuospatial memory and executive function. + +The span (that is, the length of the pattern sequence) is automatically varied +during the task, increasing after successful completion of a sequence, +and decreasing after failures, in the range from `minimumSpan` to +`maximumSpan`. The `playSpeed` property lets you control the speed of sequence +playback, and the `customTargetImage` property lets you customize the shape of the tap target. The game finishes when either `maxTests` tests have been +completed, or the user has made `maxConsecutiveFailures` errors in a +row. + +The results collected are scores derived from the game, the details of +the game, and the touch inputs made by the user. + +Spatial memory test steps are shown in Figure 6. + +

Welcome/introduction ScreenInstruction step introducing the task

+

Instruction stepDescribes what the user must do

+

Initial sequence playback screenThe flowers light up in sequence

+

+

Recall sequence screenThe user must recall the sequence

+

Consecutive failure screenIf users make a mistake, they will be offered a new pattern

+

Welcome/introduction ScreenThe user is offered a shorter sequence

+

+

Task Completion screenConfirms task completion

+

+
Figure 6. Spatial memory steps
+ +## Stroop Test +In the Stroop test, the participant is shown a series of words that are displayed in color, and must select the first letter of the color's name. Stroop test steps are shown in Figure 7. + +

Instruction step introducing the task

+

Further instructions

+

Count down a specified duration to begin the activity

+

+

A typical Stroop test; the correct answer is "B" for blue

+

Confirms task completion

+

+
Figure 7. Stroop test steps
+ +## Trail Making Test +In the trail making test, the participant connects a series of labelled circles, in order. The time to complete the test is recorded. The circles can be labelled with sequential numbers (1, 2, 3, ...) or with alternating numbers and letters (1, a, 2, b, 3, c, ...). + +Trail making test steps are shown in Figure 8. + +

Instruction step introducing the task

+

Instruction step introducing the task

+

Further instructions

+

+

Count down a specified duration to begin the activity

+

The activity screen, shown mid-task

+

Confirms task completion

+

+
Figure 8. Trail making test steps
+ +## Paced Serial Addition Test (PSAT) + +The Paced Serial Addition Test (PSAT) task (see method [ORKOrderedTask PSATTaskWithIdentifier:intendedUseDescription:presentationMode:interStimulusInterval:stimulusDuration:seriesLength:options]([ORKOrderedTask PSATTaskWithIdentifier:intendedUseDescription:presentationMode:interStimulusInterval:stimulusDuration:seriesLength:options:])) measures the cognitive function that assesses auditory and/or visual information processing speed, flexibility, and the calculation ability of the user. + +Single digits are presented every two or three seconds and the user must add each new digit to the one immediately before. + +There are three variations of this test: + +1. PASAT: Paced Auditory Serial Addition Test - the device speaks the digit every two or three seconds. +2. PVSAT: Paced Visual Serial Addition Test - the device shows the digit on screen. +3. PAVSAT: Paced Auditory and Visual Serial Addition Test - the device speaks the digit and shows it onscreen every two to three seconds. + +The score for the PSAT task is the total number of correct answers out of the number of possible correct answers. Data collected by the task is in the form of an `ORKPSATResult` object. + +PVSAT steps are shown in Figure 9. + +Note that the visual and auditory components of the task are optional. You can choose to include either of them or both. + +

Welcome/introduction ScreenInstruction step introducing the task

+

Instruction stepDescribes what the user must do

+

Countdown screenCount down a specified duration into the task

+

+

The user must add each new digit on the screen to the one immediately prior to itThe user must add each new digit on the screen to the one immediately prior to it

+

Task completion screenConfirms task completion

+

+
Figure 9. PVSAT memory steps
+ +## Tower of Hanoi + +In the Tower of Hanoi task (see the method [ORKOrderedTask towerOfHanoiTaskWithIdentifier:intendedUseDescription:numberOfDisks:options:]([ORKOrderedTask towerOfHanoiTaskWithIdentifier:intendedUseDescription:numberOfDisks:options:])), the user is asked to solve the classic Tower of Hanoi puzzle in a minimum number of moves. To solve the puzzle, the user must move the entire stack to the highlighted platform in as few moves as possible. This task measures the user's problem solving skills. A Tower of Hanoi task finishes when the user completes the puzzle correctly or concedes that they cannot solve the puzzle. + +Data collected by this task is in the form of an `ORKTowerOfHanoiResult` object. It contains every move taken by the user and indicates whether the puzzle was successfully completed or not. + +Tower of Hanoi steps are shown in Figure 10. + +

Welcome/introduction ScreenInstruction step introducing the task

Instruction stepDescribes what the user must do

+

+

Actual task screenActual task

Task completion screenConfirms task completion

+

+
Figure 10. Tower of Hanoi steps
+ +## Reaction Time + +In the reaction time task, the user shakes the device in response to a visual clue on the device's screen. The task is divided into a number of attempts, which you determine. To complete an attempt in a task, the user must shake or move the device with an acceleration that exceeds a threshold value ( `thresholdAcceleration` property) within the given time. The task finishes when the user successfully completes all the attempts as instructed in the task. Use this task to evaluate a user's response to the stimulus and calculate their reaction time. (See the method [ORKOrderedTask reactionTimeTaskWithIdentifier:intendedUseDescription:maximumStimulusInterval:minimumStimulusInterval:thresholdAcceleration:numberOfAttempts:timeout:successSound:timeoutSound:failureSound:option]([ORKOrderedTask reactionTimeTaskWithIdentifier:intendedUseDescription:maximumStimulusInterval:minimumStimulusInterval:thresholdAcceleration:numberOfAttempts:timeout:successSound:timeoutSound:failureSound:options:])). + +Data collected by this task is in the form of `ORKReactionTimeResult` objects. Each of these objects contain a timestamp representing the delivery of the stimulus and an `ORKFileResult` object that references the motion data collected during an attempt. To present this task, use an `ORKTaskViewController` object. + +Reaction time steps are shown in Figure 11. + +

Welcome/introduction ScreenInstruction step introducing the task

+

Instruction stepDescribes what the user must do

+

+

Actual task screenActual task

Task completion screenConfirms task completion

+

+
Figure 11. Reaction time steps
+ +## Sustained Phonation + +In the sustained phonation task (see the method [ORKOrderedTask audioTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:duration:recordingSettings:checkAudioLevel:options]([ORKOrderedTask audioTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:duration:recordingSettings:checkAudioLevel:options:])), the user makes a sustained sound, and an audio +recording is made. Analysis of the audio data is not included in the +ResearchKit framework, but might naturally involve looking at the power spectrum +and how it relates to the ability to produce certain +sounds. The ResearchKit framework uses the AVFoundation framework to collect this +data and to present volume indication during recording. No data +analysis is done by ResearchKit; you can define your analysis on this +task according to your own requirements. +Audio steps are shown in Figure 12. + +

Welcome ScreenInstruction step introducing the task

+

Instruction ScreenInstruction step describes user action during the task

+

Task Completion ScreenCount down a specified duration to begin the task

+

+

Task ScreenDisplays a graph during audio playback (audio collection step)

+

Task Completion ScreenConfirms task completion

+

+
Figure 12. Audio steps
+ +## Speech Recognition + +Researchers and developers can use ResearchKit to record audio data and produce transcriptions generated by Apple’s speech recognition system. ResearchKit also provides word alignments, confidence scores, and alternative speech recognition hypotheses in the form of an n-best list. Medical researchers and developers can leverage this information to analyze speech and language features like speaking rate, word usage, and pause durations. + +The n-best list and the confidence measure detect uncertainty in the speech recognition system's hypothesis in certain cases of unintelligible speech or speech containing word fragments or meaningless words. These conditions are found to be a useful indicator of cognitive decline associated with Alzheimer's disease and related dementias (1, 2), as well as other mental health issues (3). Additionally, researchers and developers can use the raw audio data captured through ResearchKit to investigate and deploy speech indicators for research and system design. + +The `ORKSpeechRecognitionStep` class represents a single recording step. In this step, the user's speech is recorded from the microphone. + +Speech recognition steps showing capturing and displaying recorded text are in Figure 13. + +

Instruction step introducing the taskInstruction step introducing the task

+

Instruct the user to prepare for recordingInstruct the user to prepare for recording

+

Prompts the user to start the recordingPrompts the user to start the recording

+

+

Records the user's speechRecords the user's speech

+

Provides the transcription and allows editingProvides the transcription and allows editing

+

Task completionTask completion

+

+
Figure 13. Speech recognition steps
+ +Once a user completes the recording, they are given the option to edit the transcript generated by the speech recognition engine. The data collected by this task consists of three main components: +
    +
  1. The raw audio recording of what the user said.
  2. +
  3. The transcriptino generated by the speech recognition engine returned as an object of type `SFTranscript`.
  4. +
  5. The edited transcript, if any, by the user.
  6. +
+ +## Speech-in-Noise + + +Understanding speech in noisy environments depends on both the level of the background noise and the hearing health of the listener. A speech-in-noise test quantifies the difficulty of understanding speech in noisy environments. + +A speech-in-noise test consists of presenting spoken sentences at different noise levels and asking listeners to repeat what they heard. Based on the sentence and word recognition rate, a metric is calculated. The speech intelligibility metric used in this test is the Speech Reception Threshold (SRT). It represents the SNR at which 50% of the words are correctly repeated by the user. The SRT is calculated using the Tillman-Olsen formula (4). + +The `ORKSpeechInNoiseStep` class plays the speech from a file set by the `speechFileNameWithExtension` property mixed with noise from a file set by the `noiseFileNameWithExtension` property. The noise gain is set through the `gainAppliedToNoise` property. Use the `filterFileNameWithExtension` property to specify a ramp-up/ramp-down filter. + +Speech-in-noise steps are shown in Figure 14. + +

Instruction step introducing the taskInstruction step introducing the task

+

Instructs the user how to proceed with the taskInstructs the user how to proceed with the task

+

Prompts the user to play the spoken sentencePrompts the user to play the spoken sentence

+

+

Plays the spoken sentence with background noisePlays the spoken sentence with background noise

+

Prompts the user to record and repeat what they heardPrompts the user to record and repeat what they heard

+

Records the user's voiceRecords the user's voice

+

+

Task completionTask completion

+

Displays spoken text and provides transcript editingDisplays spoken text and provides transcript editing

+

+
Figure 14. Speech-in-noise steps
+ +## Environment SPL Meter + +The Environment SPL Meter is not a task, but a single step that detects the sound pressure level in the user's environment. Configure this step with the following properties: + +* `thresholdValue` is the maximum permissible value for the environment sound pressure level in dBA. +* `samplingInterval` is the rate at which the `AVAudioPCMBuffer` is queried and A-weighted filter is applied. +* `requiredContiguousSamples` is the number of consecutive samples less than threshold value required for the step to proceed. + +The environment SPL meter step is shown in Figure 15. + +
+ +
Figure 15. Environment SPL meter
+
+ +## Tone Audiometry + +In the tone audiometry task users listen through headphones to a series of tones, and tap left or right buttons on the screen when they hear each tone. These tones are of different audio frequencies, playing on different channels (left and right), with the volume being progressively increased until the user taps one of the buttons. A tone audiometry task measures different properties of a user's hearing ability, based on their reaction to a wide range of frequencies. (See the method [ORKOrderedTask toneAudiometryTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:toneDuration:options:]([ORKOrderedTask toneAudiometryTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:toneDuration:options:])). + +Data collected in this task consists of audio signal amplitude for specific frequencies and channels for each ear. + +Tone audiometry steps are shown in Figure 16. + +

Instruction step introducing the task

+

Instruction step introducing the task

+

Further instructions

+

+

Count down a specified duration to begin the activity

+

The tone test screen with buttons for left and right ears

+

Confirms task completion

+

+
Figure 16. Tone audiometry steps
+ +## dBHL Tone Audiometry + +The dBHL tone audiometry task implements the Hughson-Westlake method of determining hearing threshold. It is similar to the tone audiometry task, except that it utilizes a dB HL scale. (See the method [ORKOrderedTask dBHLToneAudiometryTaskWithIdentifier:intendedUseDescription:options:]([ORKOrderedTask dBHLToneAudiometryTaskWithIdentifier:intendedUseDescription:options:])). + +Data collected in this task consists of audio signal amplitude for specific frequencies and channels for each ear. + +dBHL tone audiometry steps are shown in Figure 17. + +

Instruction step introducing the task

+

Instruction step allowing the user to select an ear

+

Further instructions

+

+

Count down a specified duration to begin the activity

+

The tone test screen with buttons for the left ear

+

Count down a specified duration to begin the activity

+

+

The tone test screen with buttons for the right ear

+

Confirms task completion

+

+
Figure 17. dBHL tone audiometry steps
+ +## 9-Hole Peg Test + +The 9-hole peg test is a two-step test of hand dexterity to measure the MSFC score in Multiple Sclerosis, or signs of Parkinson's disease or stroke. This task is well documented in the scientific literature (see Earhart et al., 2011). + +The data collected by this task includes the number of pegs, an array of move samples, and the total duration that the user spent taking the test. Practically speaking, this task generates a two-step test in which the participant must put a variable number of pegs in a hole (the place step), and then remove them (the remove step). This task tests both hands. + +The `ORKHolePegTestPlaceStep` class represents the place step. In this step, the user uses two fingers to touch the peg and drag it into the hole using their left hand. The `ORKHolePegTestRemoveStep` class represents the remove step. Here, the user moves the peg over a line using two fingers on their right hand. + +9-Hole peg test steps are shown in Figure 18. + +

Instruction step introducing the task

+

Describes what the user must do

+

Instructs the user to perform the step with the right hand

+

+

Instructs the user to perform the step with the right hand

+

Instructs the user to perform the step with the right hand

+

Instructs the user to perform the step with the left hand

+

+

Task completion

+

+
Figure 18. 9-hole peg test steps
+ + +## Amsler Grid + +The Amsler Grid task is a tool used to detect the onset of vision problems such as macular degeneration. + +The `ORKAmslerGridStep` class represents a single measurement step. In this step, the user observes the grid while closing one eye for any anomalies and marks the areas that appear distorted, using their finger or a stylus. + +Data collected by this task is in the form of an `ORKAmslerGridResult` object for the eye. It contains the eye side (specified by `ORKAmslerGridEyeSide`) and the image of the grid, along with the user's annotations for the corresponding eye. + +Amsler grid steps for the left and right eyes are shown in Figure 19. + +

Instruction step introducing the taskInstruction step introducing the task

+

Instruct the user how to measure the left eyeInstruct the user how to measure the left eye

+

Perform the left eye testPerform the left eye test

+

+

Instruct the user how to measure the right eyeInstruct the user how to measure the right eye

+

Perform the right eye testPerform the right eye test

+

Task completionTask completion

+

+
Figure 19. Amsler grid steps
+ +## Collect the Data + +The data collected in active tasks is recorded in a hierarchy of `ORKResult` objects in memory. It is up to you to serialize this hierarchy for storage or transmission in a way that’s appropriate for your application. + +For high sample rate data, such as from the accelerometer, use the `ORKFileResult` in the hierarchy. This object references a file in the output directory (specified by the `outputDirectory` property of `ORKTaskViewController`) where the data is logged. + +The recommended approach for handling file-based output is to create a new directory per task and to remove it after you have processed the results of the task. + +Active steps support attaching recorder configurations +(`ORKRecorderConfiguration`). A recorder configuration defines a type of +data that should be collected for the duration of the step from a sensor or +a database on the device. For example: + +* The pedometer sensor returns a `CMPedometerData` object that provides step counts computed by the motion coprocessor on supported devices. +* The accelerometer sensor returns a `CMAccelerometerData` object that provides raw accelerometer samples indicating the forces on the device. +* A `CMDeviceMotion` object provides information about the orientation and movement of the device by combining data collected from the accelerometer, gyroscope, and magnetometer. +* HealthKit returns sample types, such as heart rate. +* CoreLocation returns location data (combined from GPS, Wi-Fi and cell tower information). + +The recorders used by ResearchKit's predefined active tasks always use +`NSFileProtectionCompleteUnlessOpen` while writing data to disk, and +then change the file protection level on any files generated to +`NSFileProtectionComplete` when recording is finished. + +### Access Health Data + +For HealthKit related data, there are two recorder configurations: + +* `ORKHealthQuantityTypeRecorderConfiguration` to access quantity data such as heart rate. +* `ORKHealthClinicalTypeRecorderConfiguration` to access health records data. + +Access to health quanity and records data requires explicit permission that the user must grant explicitly. More information about accessing health record data can be found here. + +## Create Custom Active Tasks + +You can build your own custom active tasks by creating custom subclasses of `ORKActiveStep` and +`ORKActiveStepViewController`. Follow the example of active steps in ResearchKit's predefined tasks. (A helpful tutorial on creating active tasks can be found here). + +Some steps used in the predefined tasks may be useful as guides for creating your own tasks. For example: + +* `ORKCountdownStep` displays a timer that counts down with animation for the step duration. +* `ORKCompletionStep` displays a confirmation that the task is completed. + +Figure 20 shows examples of custom tasks. + +

Countdown stepCountdown step

+

Task completion stepTask completion step

+

+
Figure 20. Custom task examples
+ +-- +### References + +1. [Yancheva et. al., 2015] M. Yancheva, K. C. Fraser and F. Rudzicz, “Using linguistic features longitudinally to predict clinical scores for Alzheimer's disease and related dementias,” Proceedings of SLPAT 2015: 6th Workshop on Speech and Language Processing for Assistive Technologies, 2015. + +2. [Konig et al., 2015] A. König, A. Satt, A. Sorin, R. Hoory, O. Toledo-Ronen, A. Derreumaux, V. Manera, F. Verhey, P. Aalten, P. H. Robert, and R. David. “Automatic speech analysis for the assessment of patients with predementia and Alzheimer's disease,” Alzheimers Dement (Amst). 2015 Mar; 1(1): 112–124. + +3. [Gong and Poellabauer’ 17] Y. Gong and C. Poellabauer, “Topic Modeling Based Multi-modal Depression Detection,” AVEC@ACM Multimedia, 2017. + +4. [T.W. Tillman and W.O. Olsen] "Speech audiometry, Modern Development in Audiology (2nd Edition)," 1972. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep1.png new file mode 100755 index 0000000..971a469 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep2.png new file mode 100755 index 0000000..46ba12b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep3.png new file mode 100755 index 0000000..bb947f0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep4.png new file mode 100755 index 0000000..4adffb4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep5.png new file mode 100755 index 0000000..9bc9244 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep6.png new file mode 100755 index 0000000..72744a2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AmslerGridImages/AmslerGridStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep1.png new file mode 100755 index 0000000..27d9c91 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep2.png new file mode 100755 index 0000000..8832c6b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep3.png new file mode 100755 index 0000000..84bc92c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep4.png new file mode 100755 index 0000000..8928024 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep5.png new file mode 100755 index 0000000..d9cf534 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/AudioTaskImages/AudioStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/EnvironmentSPLImages/EnvironmentSPL.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/EnvironmentSPLImages/EnvironmentSPL.png new file mode 100755 index 0000000..f9c483b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/EnvironmentSPLImages/EnvironmentSPL.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep1.png new file mode 100755 index 0000000..4b056e8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep2.png new file mode 100755 index 0000000..c6bd516 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep3.png new file mode 100755 index 0000000..96ac30d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep4.png new file mode 100755 index 0000000..7765f64 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep5.png new file mode 100755 index 0000000..ff85f21 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep6.png new file mode 100755 index 0000000..9547286 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/FitnessTaskImages/FitnessStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep1.png new file mode 100755 index 0000000..5e1f740 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep2.png new file mode 100755 index 0000000..470792b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep3.png new file mode 100755 index 0000000..c5baa92 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep4.png new file mode 100755 index 0000000..ad6325f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep5.png new file mode 100755 index 0000000..7d77d54 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep6.png new file mode 100755 index 0000000..4ec7e2f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep7.png new file mode 100755 index 0000000..514de40 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/HolePegTaskImages/HolePegStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep1.png new file mode 100755 index 0000000..c95b26b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep2.png new file mode 100755 index 0000000..0ed8687 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep3.png new file mode 100755 index 0000000..dc737b0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep4.png new file mode 100755 index 0000000..6864fa0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep5.png new file mode 100755 index 0000000..5727877 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep6.png new file mode 100755 index 0000000..a22c374 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep7.png new file mode 100755 index 0000000..a3a6a04 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/KneeRangeOfMotionTaskImages/KneeRangeOfMotionStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep1.png new file mode 100755 index 0000000..18513a8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep2.png new file mode 100755 index 0000000..e65ab02 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep3.png new file mode 100755 index 0000000..f1ff859 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep4.png new file mode 100755 index 0000000..d830e0f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep5.png new file mode 100755 index 0000000..8fcb439 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/PsatTaskImages/PSATStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep1.png new file mode 100755 index 0000000..e39bf77 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep2.png new file mode 100755 index 0000000..228ad13 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep3.png new file mode 100755 index 0000000..a793c9b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep4.png new file mode 100755 index 0000000..ca207df Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ReactionTimeTaskImages/ReactionTimeStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep1.png new file mode 100755 index 0000000..ed2bd04 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep2.png new file mode 100755 index 0000000..8b83910 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep3.png new file mode 100755 index 0000000..d3cbc0b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep4.png new file mode 100755 index 0000000..8580bf5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep5.png new file mode 100755 index 0000000..324f9be Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep6.png new file mode 100755 index 0000000..5ba5376 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep7.png new file mode 100755 index 0000000..bb372db Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ShortWalkTaskImages/ShortWalkStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep1.png new file mode 100755 index 0000000..8695179 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep2.png new file mode 100755 index 0000000..bee461b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep3.png new file mode 100755 index 0000000..e9442c3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep4.png new file mode 100755 index 0000000..6f7c523 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep5.png new file mode 100755 index 0000000..2c36a90 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep6.png new file mode 100755 index 0000000..770d463 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep7.png new file mode 100755 index 0000000..8397259 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpatialSpanMemoryTaskImages/SpatialSpanMemoryStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep1.png new file mode 100755 index 0000000..d24f305 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep2.png new file mode 100755 index 0000000..09bb4e1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep3.png new file mode 100755 index 0000000..fe82cb1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep4.png new file mode 100755 index 0000000..60eec29 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep5.png new file mode 100755 index 0000000..c5ca97f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep6.png new file mode 100755 index 0000000..1073b45 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep7.png new file mode 100755 index 0000000..3a1a286 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep8.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep8.png new file mode 100755 index 0000000..ca394fe Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechInNoiseImages/SpeechInNoiseStep8.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep1.png new file mode 100755 index 0000000..01d3865 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep2.png new file mode 100755 index 0000000..f14b513 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep3.png new file mode 100755 index 0000000..3a977da Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep4.png new file mode 100755 index 0000000..e79199a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep5.png new file mode 100755 index 0000000..ac352d4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep6.png new file mode 100755 index 0000000..416b5ba Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/SpeechRecognitionImages/SpeechRecognitionStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep1.png new file mode 100755 index 0000000..7710b12 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep2.png new file mode 100755 index 0000000..4c32257 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep3.png new file mode 100755 index 0000000..3deb2eb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep4.png new file mode 100755 index 0000000..fb26efd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep5.png new file mode 100755 index 0000000..1be8fdd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/StroopTaskImages/StroopStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep1.png new file mode 100755 index 0000000..bfa0a96 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep2.png new file mode 100755 index 0000000..a1c860c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep3.png new file mode 100755 index 0000000..7cc29a4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep4.png new file mode 100755 index 0000000..da06af1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TOHTaskImages/TOHStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep1.png new file mode 100755 index 0000000..19db5b1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep2.png new file mode 100755 index 0000000..33a7d14 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep3.png new file mode 100755 index 0000000..21b8c4e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep4.png new file mode 100755 index 0000000..6c8e6f0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep5.png new file mode 100755 index 0000000..55c217f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep6.png new file mode 100755 index 0000000..acf0f3d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep7.png new file mode 100755 index 0000000..4cdd575 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep8.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep8.png new file mode 100755 index 0000000..39a138f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TimedWalkTaskImages/TimedWalkStep8.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep1.png new file mode 100755 index 0000000..3a7be4f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep2.png new file mode 100755 index 0000000..8666918 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep3.png new file mode 100755 index 0000000..b7c5117 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep4.png new file mode 100755 index 0000000..77f161c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep5.png new file mode 100755 index 0000000..0009012 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep6.png new file mode 100755 index 0000000..c26dd9c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/ToneAudiometryTaskImages/ToneAudiometryStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep1.png new file mode 100755 index 0000000..d2e7a63 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep2.png new file mode 100755 index 0000000..aa89435 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep3.png new file mode 100755 index 0000000..7ec3360 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep4.png new file mode 100755 index 0000000..2a9fff7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep5.png new file mode 100755 index 0000000..4ee2e66 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep6.png new file mode 100755 index 0000000..b557bf6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TrailMakingTaskImages/TrailMakingStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep1.png new file mode 100755 index 0000000..471521e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep2.png new file mode 100755 index 0000000..bf51008 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep3.png new file mode 100755 index 0000000..f580368 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep4.png new file mode 100755 index 0000000..f5e7c86 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep5.png new file mode 100755 index 0000000..0f63ddb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep6.png new file mode 100755 index 0000000..076a438 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/TwoFingerTappingTaskImages/TwoFingerTappingStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep1.png new file mode 100755 index 0000000..cde1e0a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep2.png new file mode 100755 index 0000000..4410217 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep3.png new file mode 100755 index 0000000..6b70657 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep4.png new file mode 100755 index 0000000..81b35b6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep5.png new file mode 100755 index 0000000..bea9025 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep6.png new file mode 100755 index 0000000..8d6be59 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep7.png new file mode 100755 index 0000000..353916b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep8.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep8.png new file mode 100755 index 0000000..51d1996 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ActiveTasks/dBHLToneAudiometryTaskImages/dBHLToneAudiometryStep8.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/AppledocSettings.plist b/PediatricPancreas_Storyboard/ResearchKit-master/docs/AppledocSettings.plist new file mode 100755 index 0000000..3343b17 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/AppledocSettings.plist @@ -0,0 +1,43 @@ + + + + + --repeat-first-par + + --company-id + org.researchkit + --create-docset + + --create-html + + --ignore + + Internal + ORKDemo + ORKDemoTests + docs + + --index-desc + docs/index-template.md + --install-docset + + --keep-undocumented-objects + + --logformat + xcode + --project-company + ResearchKit + --project-name + ResearchKit + --verbose + 2 + --warn-empty-description + + --warn-undocumented-member + + --warn-undocumented-object + + --warn-unknown-directive + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsAndGraphs-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsAndGraphs-template.markdown new file mode 100755 index 0000000..730e250 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsAndGraphs-template.markdown @@ -0,0 +1,405 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. +# Charts and Graphs +The ResearchKit framework provides classes that display data in charts and graphs. Presenting information this way helps users understand your data better and provides key insights in a visual way. + +Use the ResearchKit classes to create five kinds of charts: + + * Pie chart (ORKPieChartView). A pie chart is a circular chart divided into segments, which is useful for showing the magnitude of a particular data point as it relates to the whole. For example, a task-based research app could use a pie chart to display how many of the user's daily activities are complete. + * Line graph (ORKLineGraphChartView). A line graph is a type of chart that displays information as a series of data points connected by a straight line. Use a line graph to display the number of steps taken by a user every day in a week. + * Multiple line graph. A multiple line graph is a type of line graph that's useful for comparing multiple data sets over time. + * Discrete graph (ORKDiscreteGraphChartView). A discrete graph displays information as a series of data points in which each series is evenly spaced across the axis according to a tier row index. A discrete graph chart is a good choice for displaying data within a range, such as the range of a user's heart rate over the past month. + * Discrete graph with multiple points. A discrete graph with multiple points groups together noncontinuous values, which is useful for showing relationships between different types of discrete values that occur at the same time (e.g. viewing a user's blood pressure and heart rate in a single discrete graph). + +Each of these charts is shown in Figure 1.  + +

Pie Chart

Line graph chart

Line graph chart with multiple lines

+

+

Discrete graph chart

Discrete graph chart with multiple points

+

+

Figure 1. Types of charts
+

+ +##Add a Chart to Your App +Chart objects adhere to the Model-View-Controller (MVC) paradigm. MVC emphasizes separation between the data (model), the presentation of that data (view), and the class required to coordinate the data and its view (controller). This design pattern is pervasive in iOS programming and is an integral part of the charts feature. + +In a research app, the chart object (view) must be connected to a data source object (model) which is responsible for supplying the data. The chart is then presented to a view controller object (controller) which establishes the necessary connections between the data source and the view. + +To add a chart or graph to your app, first create a data source class to supply the data. Next, create a chart or graph object (such as an `ORKPieChartView` object), connect it to the data source, customize the chart object as you want, and present it in a view controller. + +###Implement the Data Source Protocol +The data source provides the information that a chart object needs in order to construct a chart. This communication is enforced by a contractual obligation between objects known as a *protocol*. A protocol is composed of a name and a list of methods that the data source promises to implement. + +Two types of methods exist in a protocol: *required* and *optional* methods. You must implement the required methods in the data source while choosing which optional methods to implement. In the case of ResearchKit charts, one of the required methods of the protocol provides the number of points (or segments) and another required method provides the value of each point to the chart object. The optional methods of the protocol help in further configuring data, such as color of the x axis or segments. + +When providing the data to a chart, the data source must adopt one of two protocols: the `ORKGraphChartViewDataSource` protocol (for a graph chart) or the `ORKPieChartViewDataSource` protocol (for a pie chart). For specific examples of implementing these protocols, see [Adding a Line or Discrete Graph Chart to Your App](#header-add-line) and [Adding a Pie Chart to Your App](#header-add-pie). + +###Create a Chart Object and Adding It to a View Controller +To present data in a chart, create an instance of a ResearchKit chart object, such as `ORKPieChartView` or `ORKLineGraphChartView`. To do this, first create a UIView object in a UIViewController object and change the custom class of the view to the ResearchKit chart class you want to use. + +Next, use an IBOutlet to link the chart view to your code. This connection between your code and the view will allow you to update the contents of the chart on demand, as well as customize its look and feel. + +Then, connect the chart view with your data source so that the chart has access to the data. For example, to connect a pie chart object with a custom data source, you can use code similar to this: + + // Connect the pie chart-view object to a data source + pieChartView.dataSource = pieChartDataSource + +###Customize the Chart Object (Optional) +Although the default ResearchKit charts and graphs are ready to use with your data, it's easy to customize them to suit your app. Each chart object includes several properties that let you customize its look and feel. You can title the segments in a pie chart by implementing the `titleForSegmentAtIndex` method in a pie chart data source class, as shown here: + + func pieChartView(pieChartView: ORKPieChartView, titleForSegmentAtIndex index: Int) -> String { + switch index { + case 0: + return "Steps taken" + case 1: + return "Tasks completed" + case 2: + return "Surveys completed" + default: + return "task \(index + 1)" + } + } + +The code above displays the titles in the pie chart shown in Figure 2. + +

+
+ +
Figure 2. Pie chart with custom titles
+
+
+ + +To learn about the customizable properties of pie, line graph, and discrete graph chart objects, see `ORKPieChartView`, `ORKGraphChartView`, and `ORKDiscreteGraphChartView`. + +##Add a Pie Chart to Your App +The data source object that provides data to a pie chart adopts the `ORKPieChartViewDataSource` protocol. To construct a pie chart, you need to know the number of segments and the value of each segment. + +To specify the number of segments in a pie chart, implement the `numberOfSegmentsInPieChartView` method and return an integer that indicates the number of segments in the pie chart. This code specifies a pie chart that has three segments: + + func numberOfSegmentsInPieChartView(pieChartView: ORKPieChartView) -> Int { + return 3 + } + +Before you can draw the segments in a pie chart, you need to specify the value of each segment. To provide a value for each segment of the pie chart, implement the `valueForSegmentAtIndex` method. + +The values themselves are percentages whose sum should equal to 100.0. For example, the code below returns the values 50, 30, and 20 for segments at indexes 0, 1, and 2 in the pie chart: + + func pieChartView(pieChartView: ORKPieChartView, valueForSegmentAtIndex index: Int) -> CGFloat { + switch index { + case 0: + return 60.0 + case 1: + return 25.0 + case 2: + return 15.0 + } + } + +You can use the optional methods in the pie chart data source protocol to help you customize the look and feel of the data in the chart, including specifying a color and a title for each segment. (To learn more about using properties in the pie chart data source protocol to customize your chart, see `ORKPieChartViewDataSource`.) + +Here's an example of a pie chart data source class that includes both required and optional methods: + + class PieChartDataSource: NSObject, ORKPieChartViewDataSource { + // Specify three different colors. + let colors = [ + UIColor(red: 217/225, green: 217/255, blue: 217/225, alpha: 1), + UIColor(red: 142/255, green: 142/255, blue: 147/255, alpha: 1), + UIColor(red: 244/255, green: 200/255, blue: 74/255, alpha: 1) + ] + + // Values for each of the three segments. + let values = [60.0, 25.0, 15.0] + + // Required methods. + func numberOfSegmentsInPieChartView(pieChartView: ORKPieChartView ) -> Int { + return colors.count + } + + func pieChartView(pieChartView: ORKPieChartView, valueForSegmentAtIndex index: Int) -> CGFloat { + return CGFloat(values[index]) + } + + // Optional methods + // Give a color to each segment in the pie chart. + func pieChartView(pieChartView: ORKPieChartView, colorForSegmentAtIndex index: Int) -> UIColor { + return colors[index] + } + + // Give a title to each segment in the pie chart. + func pieChartView(pieChartView: ORKPieChartView, titleForSegmentAtIndex index: Int) -> String { + switch index { + case 0: + return "Steps taken" + case 1: + return "Tasks completed" + case 2: + return "Surveys completed" + default: + return "task \(index + 1)" + } + } + } + +After you create a pie chart data source class, create a pie chart object that presents the data it receives from the data source object. This code shows how to create a pie chart object, connect it to the data source, and customize some of its properties: + + // Create a pie chart object + @IBOutlet weak var pieChartView: ORKPieChartView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Connect the pie chart object to a data source + pieChartView.dataSource = pieChartDataSource + + // Optional custom configuration + pieChartView.showsTitleAboveChart = false + pieChartView.showsPercentageLabels = true + pieChartView.drawsClockwise = true + pieChartView.titleColor = UIColor.purpleColor() + pieChartView.textColor = UIColor.purpleColor() + pieChartView.title = "Weekly" + pieChartView.text = "Report" + pieChartView.lineWidth = 10 + pieChartView.showsPercentageLabels = true + } + +Figure 3 shows the pie chart created by the code in this section. + +
+
+Instruction step +
Figure 3. Pie chart
+
+
+ + +##Add a Line or Discrete Graph Chart to Your App +Adding data to line and discrete graph is a matter of implementing methods in the `ORKGraphChartViewDataSource` protocol. There are several methods that you must implement for correct behavior. + +Line and discrete graphs can display one or more plots. A plot is a graphical representation of a relationship between two variables. + +Start by implementing the `graphChartView:numberOfPointsForPlotIndex:` method. Here, you return the number of points for the specific plot index (a graph may have more than one plot associated with it). + +Next, implement the `graphChartView:pointForPointIndex:plotIndex:` method. In this method, return a `ORKValueRange` (which represents a ranged point used in a graph plot) for the given point index and plot index. + +An optional method that you can implement is `numberOfPlotsInGraphChartView:`. Here, return the number of plots for the passed graph. If you don't implement this method, one plot is assumed. + +Other optional methods provide titles as well as set minimum and maximum values for the y axis. + +Here's an example of a data source class for a line graph. This class returns five points for the two plots that will appear on the graph: + + class LineGraphDataSource: NSObject, ORKGraphChartViewDataSource { + + var plotPoints = + [ + [ + ORKValueRange(value: 200), + ORKValueRange(value: 450), + ORKValueRange(value: 500), + ORKValueRange(value: 250), + ORKValueRange(value: 300), + ORKValueRange(value: 600), + ORKValueRange(value: 300), + ], + [ + ORKValueRange(value: 100), + ORKValueRange(value: 350), + ORKValueRange(value: 400), + ORKValueRange(value: 150), + ORKValueRange(value: 200), + ORKValueRange(value: 500), + ORKValueRange(value: 400), + ] + ] + + // Required methods + + func graphChartView(graphChartView: ORKGraphChartView, pointForPointIndex dataPointForPointIndex: Int, plotIndex: Int) -> ORKValueRange { + + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + // Optional methods + + // Returns the number of points to the graph chart view + func numberOfPlotsInGraphChartView(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + // Sets the maximum value on the y axis + func maximumValueForGraphChartView(for graphChartView: ORKGraphChartView) -> CGFloat { + return 1000 + } + + // Sets the minimum value on the y axis + func minimumValueForGraphChartView(for graphChartView: ORKGraphChartView) -> CGFloat { + return 0 + } + + // Provides titles for x axis + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + switch pointIndex { + case 0: + return "Mon" + case 1: + return "Tue" + case 2: + return "Wed" + case 3: + return "Thu" + case 4: + return "Fri" + case 5: + return "Sat" + case 6: + return "Sun" + default: + return "Day \(pointIndex + 1)" + } + } + + // Returns the color for the given plot index + func graphChartView(graphChartView: ORKGraphChartView, colorForPlotIndex plotIndex: Int) -> UIColor { + if plotIndex == 0 { + return UIColor.purpleColor() + } + } + +Note: A discrete graph uses the same data source protocol as a line graph, so the data source class for a discrete graph tends to look similar to the line graph data source class shown above. + +After you create the data source class for a graph, create a graph chart object to present the data. This code creates a line graph chart object, connects it to the data source shown above, and customizes some of its properties: + + // Create a line graph view object + @IBOutlet weak var lineGraphView: ORKLineGraphChartView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Connect the line graph view object to a data source + lineGraphView.dataSource = lineGraphChartDataSource() + + // Optional custom configuration + lineGraphView.showsHorizontalReferenceLines = true + lineGraphView.showsVerticalReferenceLines = true + lineGraphView.axisColor = UIColor.whiteColor() + lineGraphView.verticalAxisTitleColor = UIColor.orangeColor() + lineGraphView.showsHorizontalReferenceLines = true + lineGraphView.showsVerticalReferenceLines = true + lineGraphView.scrubberLineColor = UIColor.redColor() + } + +Figure 4 shows the line graph created by the code in this section. + +
+
+Instruction step +
Figure 4. Line graph chart
+
+
+ +To display a discrete graph chart instead of a line graph chart, use code similar to the code below to create a discrete graph chart object, connect it to a data source, and customize some of its properties: + + // Creating discrete graph chart-view object + @IBOutlet weak var discreteGraphChart: ORKDiscreteGraphChartView! + + //Connecting discrete graph chart-view object to a data source + let discreteGraphChartDataSource = DiscreteGraphDataSource() + + override func viewDidLoad() { + super.viewDidLoad() + + // Connect the line graph view object to a data source + discreteGraphChart.dataSource = discreteGraphChartDataSource + + // Optional custom configuration + discreteGraphChart.showsVerticalReferenceLines = true + discreteGraphChart.drawsConnectedRanges = true + } + + +Figure 5 shows a discrete graph that uses the same data source class created for the line graph chart at the beginning of this section. + +
+
+ +
Figure 5. Discrete graph chart
+
+
+ + +###Draw Multiple Lines in a Graph +By default, the graph object assumes that it has a single plot to draw. To draw more than one plot on a graph, use the `numberOfPlotsInGraphChartView` method and specify the number of plots in the graph. This optional data source method is useful when drawing more than one plot on a graph chart. + +This code shows how a graph object can draw two plots: + + // Optional methods + func numberOfPlotsInGraphChartView(graphChartView: ORKGraphChartView) -> Int { + return 2 + } + +###Add Titles to a Graph Chart +To add titles along the x axis in a line or discrete graph, implement the `titleForXAxisAtPointIndex` method in the data source class and return the title to display adjacent to each division on the x axis. For the y axis, display maximum or minimum values using the `maximumValueForGraphChartView:` or `minimumValueForGraphChartView:` properties (to display images instead of values, use the `maximumValueImage` and `minimumValueImage` properties). + +The following code displays titles on the x axis of a discrete graph chart: + + func graphChartView(graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + switch pointIndex { + case 0: + return "Jan" + case 1: + return "Feb" + case 2: + return "Mar" + case 3: + return "Apr" + default: + return "Month \(pointIndex + 1)" + } + } + +The code above displays the titles you can see in the discrete graph shown in Figure 6. + +
+
+ +
Figure 6. Discrete graph chart with custom titles
+
+
+ +###Support the Pan Gesture +By default, the graph chart object implements the pan gesture for you. When the user drags a finger along the graph in a view, a label appears above the point that's closest to the user's finger, displaying the point's value. + +You can extend the default pan gesture behavior by implementing the `ORKGraphChartViewDelegate` protocol. The graph chart view delegate protocol forwards the pan gesture events occurring within the bounds of an `ORKGraphChartView` object. + +There are three optional methods that can be implemented: + +- `graphChartViewTouchesBegan:` alerts the object when the user has started touching the graph chart view. + +- `graphChartView:touchesMovedToXPosition:` provides the position on the x axis where the touch has moved. + +- `graphChartViewTouchesEnded:` alerts the object when the user has stopped touching the graph view. + +### Update the Data Source +In the examples above, the `plotPoints` are hard-coded. To update the data source, you may add functions that take in a new set of `plotPoints` to update the data. Call the `reloadData()` method after updating your data source in order to redraw the graph. + +If your graph is in a table view: + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + let dataSource = lineGraphChartView.dataSource as! yourDataSource + dataSource.updatePlotPoints(newPlotPoints: [ + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 64), + ] + hrLineGraphChartView.reloadData() + hrLineGraphChartView.animate(withDuration: 0.5) + } diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedChart.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedChart.png new file mode 100755 index 0000000..c519de7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedChart.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedLineGraph.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedLineGraph.png new file mode 100755 index 0000000..7716a16 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/CustomizedLineGraph.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart.png new file mode 100755 index 0000000..027e79a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart2.png new file mode 100755 index 0000000..570c3f4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/DiscreteGraphChart2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/LineChart/LineChart1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/LineChart/LineChart1.png new file mode 100755 index 0000000..1917201 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/LineChart/LineChart1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscereteGraphChartMultipleLinesOverview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscereteGraphChartMultipleLinesOverview.png new file mode 100755 index 0000000..dadf007 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscereteGraphChartMultipleLinesOverview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscreteGraphChartOverview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscreteGraphChartOverview.png new file mode 100755 index 0000000..e13ee95 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/DiscreteGraphChartOverview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartMultipleLinesOverview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartMultipleLinesOverview.png new file mode 100755 index 0000000..b7fcf0d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartMultipleLinesOverview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartOverview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartOverview.png new file mode 100755 index 0000000..61bae4f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/LineGraphChartOverview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/PieChartOverview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/PieChartOverview.png new file mode 100755 index 0000000..990c466 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/Overview/PieChartOverview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomTitlePieChart.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomTitlePieChart.png new file mode 100755 index 0000000..5380aa2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomTitlePieChart.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomizedChart.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomizedChart.png new file mode 100755 index 0000000..65b9000 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/CustomizedChart.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/chart1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/chart1.png new file mode 100755 index 0000000..aa10c2d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/ChartsAndGraphs/ChartsImages/PieChart/chart1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-ObjC.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-ObjC.markdown new file mode 100755 index 0000000..7aaa597 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-ObjC.markdown @@ -0,0 +1,229 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +# Obtaining Consent + +Research studies that involve human subjects typically require some form of ethics review. Depending on the country, this may be review by an institutional review board (IRB) or by an ethics committee (EC). For some studies, informed consent may be required to conduct a research study, which means that the researcher must ensure that each participant is fully informed about the nature of the study, and must obtain a signed consent from each participant. Additionally, consent may be required as a condition of app review. + +The ResearchKit™ framework makes it easy to display your consent document and to obtain a participant's signature. Note that the ResearchKit framework does not include digital signature support. If the signature needs to be verifiable and irrevocable, you are responsible for producing a digital signature or for generating a PDF that can be used to attest to the identity of the participant and the time at which the form was signed. + +To use the ResearchKit framework to obtain consent, start by creating a consent document model object (`ORKConsentDocument`) that represents the consent document. + +In the consent document model, encode each section of your consent document and the signatures that are needed. After you have the structure of your consent form in the document model, present a visual, animated sequence to help the participant understand it by adding the document to a visual consent step (`ORKVisualConsentStep`). To present the document for review and obtain a signature, add the document to a consent review step (`ORKConsentReviewStep`). To present the visual consent and consent review steps together, create a consent task that contains the steps and present them using an `ORKTaskViewController` object. + +You can also add other steps into your consent sequence. For example, a consent sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission to share the data your study is collecting with other researchers, if allowed by your IRB or EC. Or you can add instruction, form, or question steps to ask comprehension questions to verify that your prospective participants understand the nature of the study. + +## 1. Create the Consent Document Model + +To create a consent document model, first decide how you want to present your consent document. Categorize your content into sections based on what information you present to participants. After you have the structure for your consent document, you can replicate the same structure using the consent document model object (`ORKConsentDocument`). + +The ResearchKit framework comes with some predefined sections that are commonly included in consent documents: + +* Overview (`ORKConsentSectionTypeOverview`) +* Data gathering (`ORKConsentSectionTypeDataGathering`) +* Privacy (`ORKConsentSectionTypePrivacy`) +* Data use (`ORKConsentSectionTypeDataUse`) +* Time commitment (`ORKConsentSectionTypeTimeCommitment`) +* Surveys (`ORKConsentSectionTypeStudySurvey`) +* Tasks (`ORKConsentSectionTypeStudyTasks`) +* Withdrawal (`ORKConsentSectionTypeWithdrawing`) + +The predefined sections include appropriate images and localized titles. To use a predefined section, use the `content` or `htmlContent` properties of `ORKConsentSection` object to supply a short, one-line summary of the section and the content to display if the participant taps the Learn More button. + +If you use the predefined sections in the expected order, the ResearchKit framework animates the transitions between the sections, giving a more fluid participant experience. + +After you create a section, you create a step to present the section. + +```objective-c + ORKConsentDocument *document = [ORKConsentDocument new]; + ORKConsentSection *section1 = + [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeDataGathering]; + section1.title = @"The title of the section goes here ..."; + section1.summary = @"The summary about the section goes here ..."; + section1.content = @"The content to show in learn more ..."; + + // Create additional section objects for later sections + document.sections = @[section1, ...]; + + ORKVisualConsentStep *step = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsent document:document]; + + // And then create and present a task including this step. +``` + +If the predefined consent sections do not adequately cover the sections of your consent document, you can create your own custom sections. You can also create your own images and animations and add them to your consent section, to complete the experience. The animations you add should be H.264 videos; for best results, try to match the assets included with the ResearchKit framework. + +### Create a Visual Consent Step + +The visual consent step presents the sections of the consent document. +It is your responsibility to populate the visual consent step with +content; the `ORKVisualConsentStep` object doesn't contain any +default content. + +```objective-c + // Add consent sections for each page of visual consent; for example: + ORKConsentSection *section1 = + [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeDataGathering]; + document.sections = @[section1, ...]; + + // Add the document to a visual consent step and/or a review step: + ORKVisualConsentStep *visualConsent = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsentIdentifier document:document]; + + // Create and present a task including this step. +``` + +Visual step is presented as: + + + +> Consent overview screen (ORKConsentSectionTypeOverview object) + + + +> Data gathering (ORKConsentSectionTypeDataGathering object) + + + +> Privacy (ORKConsentSectionTypePrivacy object) + + + +> Data use disclosure (ORKConsentSectionTypeDataUse object) + + + +> Time commitment (ORKConsentSectionTypeTimeCommitment object) + + + +> Type of study survey (ORKConsentSectionTypeStudySurvey object)

+ + + +> Study tasks (ORKConsentSectionTypeStudyTasks object) + + + +> Consent withdrawal (ORKConsentSectionTypeWithdrawing object) + + + +> Custom consent section (ORKConsentSectionTypeCustom object) + +### Add a Review Step + +Participants review the consent review document in the consent review step (`ORKConsentReviewStep`). Depending on your signature requirements, participant can also be asked to enter their name and write a signature on the screen. + +The content for consent review can either be produced as a concatenation of all the consent sections in your document model, or you can provide entirely separate review content as HTML in the consent document's `htmlReviewContent` property. + +When the participant agrees to the content in the consent form, a confirmation dialog is shown. The text of this dialog is customizable using the `reasonForConsent` property of `ORKConsentReviewStep`. + +The name entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresName` property is YES. Similarly, the signature entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresSignature` property is YES. + +```objective-c + ORKConsentDocument *consent = [[ORKConsentDocument alloc] init]; + consent.title = @"Demo Consent"; + consent.signaturePageTitle = @"Consent"; + + ORKConsentReviewStep *reviewStep = + [[ORKConsentReviewStep alloc] initWithIdentifier:kConsentReviewIdentifier + signature:consent.signatures[0] + inDocument:consent]; + reviewStep.text = @"Lorem ipsum .."; + reviewStep.reasonForConsent = @"Lorem ipsum ..."; + + // Add the content to a task and present it. +``` + +Review step is presented as: + + + +> Consent review (ORKConsentReviewStep object) + + + +> Agreeing to the consent document (reasonForConsent property of ORKConsentReviewStep object) + + + +> Consent review name entry (signature property in ORKConsentReviewStep) + + + +> Consent review signature (signature property in ORKConsentReviewStep) + +### Consent Sharing Step + +The primary aim of apps which use the ResearchKit framework is to collect data for a +specific study. But if you want to ask participants to share their data with other +researchers, participants must be able to control this. + +A consent sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission +to share their data that you collect for your study with other researchers, if allowed by +your IRB or EC if applicable. To use a consent sharing step, include it in a task, perhaps +just before a consent review step. + +```objective-c + ORKConsentSharingStep *sharingStep = + [[ORKConsentSharingStep alloc] initWithIdentifier:kConsentSharingIdentifier + investigatorShortDescription:@"MyInstitution" + investigatorLongDescription:@"MyInstitution and its partners" + localizedLearnMoreHTMLContent:@"Lorem ipsum..."]; + + // Then include this step to a task and present with a task view controller. +``` + +The consent sharing step looks like this: + + + +> Example of a consent sharing step. + +## 2. Create the Consent Task + +After you create the step(s), create an `ORKOrderedTask` task and add them to it. To present the task, attach your task to a task view controller and present it. + +The following code snippet shows how to create a task with a visual consent step and a consent review step: + +```objective-c + ORKVisualConsentStep *visualStep = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsentIdentifier + document:consent]; + ORKConsentReviewStep *reviewStep = + [[ORKConsentReviewStep alloc] initWithIdentifier:kConsentReviewIdentifier + signature:consent.signatures[0] + inDocument:consent]; + // Configure the steps. + + // Create a task containing those steps. + ORKOrderedTask *task = + [[ORKOrderedTask alloc] initWithIdentifier:kConsentTaskIdentifier + steps:@[visualStep,reviewStep]]; + + ORKTaskViewController *taskViewController = + [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + + // And then present the task view controller. +``` + +## 3. Optionally, Generate a PDF + +The ResearchKit framework can help you generate a PDF of the signed consent form and provide it to the participant. For example, your app could generate the PDF locally, write it to disk, email it to the participant, display it in the app, or send it to a server. + +To do this, first take any signature results from the completed consent review, and apply the resulting signatures to a copy of your consent document. Then, call the `makePDFWithCompletionHandler:` method of `ORKConsentDocument` as shown here. + +```objective-c + ORKConsentDocument *documentCopy = [document copy]; + + ORKConsentSignatureResult *signatureResult = + (ORKConsentSignatureResult *)[[[taskViewController result] stepResultForStepIdentifier:kConsentReviewIdentifier] firstResult]; + [signatureResult applyToDocument:documentCopy]; + + [documentCopy makePDFWithCompletionHandler:^(NSData *pdfData, NSError *error) { + // Write the PDF data to disk, email it, display it, or send it to a server. + }]; +``` + +You can only apply a signature result to a new copy of a consent document. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-Swfit3.md b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-Swfit3.md new file mode 100755 index 0000000..acff2b1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template-Swfit3.md @@ -0,0 +1,208 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +# Obtaining Consent + +Research studies that involve human subjects typically require some form of ethics review. Depending on the country, this may be review by an institutional review board (IRB) or by an ethics committee (EC). For some studies, informed consent may be required to conduct a research study, which means that the researcher must ensure that each participant is fully informed about the nature of the study, and must obtain a signed consent from each participant. Additionally, consent may be required as a condition of app review. + +The ResearchKit™ framework makes it easy to display your consent document and to obtain a participant's signature. Note that the ResearchKit framework does not include digital signature support. If the signature needs to be verifiable and irrevocable, you are responsible for producing a digital signature or for generating a PDF that can be used to attest to the identity of the participant and the time at which the form was signed. + +To use the ResearchKit framework to obtain consent, start by creating a consent document model object (`ORKConsentDocument`) that represents the consent document. + +In the consent document model, encode each section of your consent document and the signatures that are needed. After you have the structure of your consent form in the document model, present a visual, animated sequence to help the user understand it by adding the document to a visual consent step (`ORKVisualConsentStep`). To present the document for review and obtain a signature, add the document to a consent review step (`ORKConsentReviewStep`). To present the visual consent and consent review steps together, create a consent task that contains the steps and present them using an `ORKTaskViewController` object. + +You can also add other steps into your consent sequence. For example, a consent sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission to share the data your study is collecting with other researchers, if allowed by your IRB or EC. Or you can add instruction, form, or question steps to ask comprehension questions to verify that your prospective participants understand the nature of the study. + +## 1. Create the Consent Document Model + +To create a consent document model, first decide how you want to present your consent document. Categorize your content into sections based on what information you present to participants. After you have the structure for your consent document, you can replicate the same structure using the consent document model object (`ORKConsentDocument`). + +The ResearchKit framework comes with some predefined sections that are commonly included in consent documents: + +* Overview (`ORKConsentSectionTypeOverview`) +* Data gathering (`ORKConsentSectionTypeDataGathering`) +* Privacy (`ORKConsentSectionTypePrivacy`) +* Data use (`ORKConsentSectionTypeDataUse`) +* Time commitment (`ORKConsentSectionTypeTimeCommitment`) +* Surveys (`ORKConsentSectionTypeStudySurvey`) +* Tasks (`ORKConsentSectionTypeStudyTasks`) +* Withdrawal (`ORKConsentSectionTypeWithdrawing`) + +The predefined sections include appropriate images and localized titles. To use a predefined section, use the `content` or `htmlContent` properties of `ORKConsentSection` object to supply a short, one-line summary of the section and the content to display if the participant taps the Learn More button. + +If you use the predefined sections in the expected order, the ResearchKit framework animates the transitions between the sections, giving a more fluid participant experience. + +After you create a section, you create a step to present the section. + +```swift +let document = ORKConsentDocument() + +let section1 = ORKConsentSection(type: .dataGathering) +section1.title = "The title of the section goes here ..." +section1.summary = "The summary about the section goes here ..." +section1.content = "The content to show in learn more ..." + +// Create additional section objects for later sections +document.sections = [section1, ...] + +let step = ORKVisualConsentStep(identifier: "VisualConsentStep", document: document) +// And then create and present a task including this step. +``` + +If the predefined consent sections do not adequately cover the sections of your consent document, you can create your own custom sections. You can also create your own images and animations and add them to your consent section, to complete the experience. The animations you add should be H.264 videos; for best results, try to match the assets included with the ResearchKit framework. + +### Create a Visual Consent Step + +The visual consent step presents the sections of the consent document. +It is your responsibility to populate the visual consent step with +content; the `ORKVisualConsentStep` object doesn't contain any +default content. + +```swift +// Add consent sections for each page of visual consent; for example: +let section1 = ORKConsentSection(type: .dataGathering) +document.sections = [section1, ...] + +// Add the document to a visual consent step and/or a review step: +let step = ORKVisualConsentStep(identifier: "VisualConsentStep", document: document) + +// Create and present a task including this step. +``` + +Visual step is presented as: + + + +> Consent overview screen (ORKConsentSectionTypeOverview object) + + + +> Data gathering (ORKConsentSectionTypeDataGathering object) + + + +> Privacy (ORKConsentSectionTypePrivacy object) + + + +> Data use disclosure (ORKConsentSectionTypeDataUse object) + + + +> Time commitment (ORKConsentSectionTypeTimeCommitment object) + + + +> Type of study survey (ORKConsentSectionTypeStudySurvey object)

+ + + +> Study tasks (ORKConsentSectionTypeStudyTasks object) + + + +> Consent withdrawal (ORKConsentSectionTypeWithdrawing object) + + + +> Custom consent section (ORKConsentSectionTypeCustom object)

+ +### Add a Review Step + +Participants review the consent review document in the consent review step (`ORKConsentReviewStep`). Depending on your signature requirements, a participant can also be asked to enter their name and write a signature on the screen. + +The content for consent review can either be produced as a concatenation of all the consent sections in your document model, or you can provide entirely separate review content as HTML in the consent document's `htmlReviewContent` property. + +When the participant agrees to the content in the consent form, a confirmation dialog is shown. The text of this dialog is customizable using the `reasonForConsent` property of `ORKConsentReviewStep`. + +The name entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresName` property is YES. Similarly, the signature entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresSignature` property is YES. + +```swift +let consent = ORKConsentDocument() +consent.title = "Demo Consent" +consent.signaturePageTitle = "Consent" + +let reviewStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: consent.signatures[0], in: consent) +reviewStep.text = "Lorem ipsum .." +reviewStep.reasonForConsent = "Lorem ipsum ..." + +// Add the content to a task and present it. +``` + +Review step is presented as: + + + +> Consent review (ORKConsentReviewStep object) + + + +> Agreeing to the consent document (reasonForConsent property of ORKConsentReviewStep object) + + + +> Consent review name entry (signature property in ORKConsentReviewStep) + + + +> Consent review signature (signature property in ORKConsentReviewStep) + +### Consent Sharing Step + +The primary aim of apps which use the ResearchKit framework is to collect data for a +specific study. But if you want to ask participants to share their data with other +researchers, participants must be able to control this. + +A consent sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission +to share their data that you collect for your study with other researchers, if allowed by +your IRB or EC if applicable. To use a consent sharing step, include it in a task, perhaps +just before a consent review step. + +```swift +let sharingStep = ORKConsentSharingStep(identifier: "ConsentSharingStep", investigatorShortDescription: "MyInstitution", investigatorLongDescription: "MyInstitution and its partners", localizedLearnMoreHTMLContent: "Lorem ipsum...") + +// Then include this step to a task and present with a task view controller. +``` + +The consent sharing step looks like this: + + + +> Example of a consent sharing step. + +## 2. Create the Consent Task + +After you create the step(s), create an `ORKOrderedTask` task and add them to it. To present the task, attach your task to a task view controller and present it. + +The following code snippet shows how to create a task with a visual consent step and a consent review step: + +```swift +let visualStep = ORKVisualConsentStep(identifier: "VisualConsentStep", document: document) +let reviewStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: consent.signatures[0], in: consent) +// Configure the steps. + +// Create a task containing those steps. +let task = ORKOrderedTask(identifier: "ConsentTask", steps: [visualStep, reviewStep]) + +let taskViewController = ORKTaskViewController(task: task, taskRun: nil) + +// And then present the task view controller. +``` + +## 3. Optionally, Generate a PDF + +The ResearchKit framework can help you generate a PDF of the signed consent form and provide it to the participant. For example, your app could generate the PDF locally, write it to disk, email it to the participant, display it in the app, or send it to a server. + +To do this, first take any signature results from the completed consent review, and apply the resulting signatures to a copy of your consent document. Then, call the `makePDFWithCompletionHandler:` method of `ORKConsentDocument` as shown here. + +```swift +let documentCopy = document.copy() as! ORKConsentDocument + +let signatureResult: ORKConsentSignatureResult = taskViewController.result.stepResult(forStepIdentifier: "ConsentReviewStep")?.firstResult as! ORKConsentSignatureResult + +documentCopy.makePDF{ (data, error) -> Void in + // Write the PDF data to disk, email it, display it, or send it to a server. +} +``` + +You can only apply a signature result to a new copy of a consent document. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template.markdown new file mode 100755 index 0000000..556bdc7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/InformedConsent-template.markdown @@ -0,0 +1,211 @@ + # +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +#Obtaining Consent + +Research studies that involve human subjects typically require some form of ethics review. Depending on the country, this may be review by an institutional review board (IRB), or by an ethics committee (EC). For some studies, consent may be required to conduct a research study, which means that the researcher must ensure that each participant is fully informed about the nature of the study, and must obtain a signed consent from each participant. Additionally, consent may be required as a condition of app review. + +The ResearchKit™ framework makes it easy to display your consent document and to obtain a participant's signature. Note that the ResearchKit framework does not include digital signature support. If the signature needs to be verifiable and irrevocable, you are responsible for producing a digital signature or for generating a PDF that can be used to attest to the identity of the participant and the time at which the form was signed. + +To use the ResearchKit framework to obtain consent, start by creating a consent document model object (`ORKConsentDocument`) that represents the consent document. +In the consent document model, encode each section of your consent document, and the signatures that are needed. After you have the structure of your consent form in the document model, present a visual, animated sequence to help the user understand it by adding the document to a visual consent step (`ORKVisualConsentStep`). To present the document for review and obtain a signature, add the document to a consent review step (`ORKConsentReviewStep`). To present the visual consent and consent review steps together, create an consent task that contains the steps, and present them using an `ORKTaskViewController` object. + +You can also add other steps into your consent sequence. For example, a consent-sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission to share the data your study is collecting with other researchers, if allowed by your IRB or EC. Or, add an instruction, form, or question steps to ask comprehension questions to verify that your prospective participants understand the nature of the study. + +##Create the Consent Document Model + +To create a consent document model, first decide how you want to present your consent document. Categorize your content into sections based on what information you present to users. After you have the structure for your consent document, you can replicate the same structure using the consent document model object (`ORKConsentDocument`). + +The ResearchKit framework comes with some predefined sections that are commonly included in consent documents: + +* Overview (`ORKConsentSectionTypeOverview`) +* Data gathering (`ORKConsentSectionTypeDataGathering`) +* Privacy (`ORKConsentSectionTypePrivacy`) +* Data use (`ORKConsentSectionTypeDataUse`) +* Time commitment (`ORKConsentSectionTypeTimeCommitment`) +* Surveys (`ORKConsentSectionTypeStudySurvey`) +* Tasks (`ORKConsentSectionTypeStudyTasks`) +* Withdrawal (`ORKConsentSectionTypeWithdrawing`) + +The predefined sections include appropriate images and localized titles. To use a predefined section, use the `content` or `htmlContent` properties of `ORKConsentSection` object to supply a short, one-line summary of the section and the content to display if the user taps the Learn More button. +You use the predefined sections in the expected order, and the ResearchKit framework animates the transitions between the sections, giving a more fluid user experience. + +After you create a section, you create a step to present the section. + + + ORKConsentDocument *document = [ORKConsentDocument new]; + ORKConsentSection *section1 = + [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeDataGathering]; + section1.title = @"The title of the section goes here ..."; + section1.summary = @"The summary about the section goes here ..."; + section1.content = @"The content to show in learn more ..."; + + // Create additional section objects for later sections + document.sections = @[section1, ...]; + + ORKVisualConsentStep *step = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsent document:document]; + + // And then create and present a task including this step. + +If the predefined consent sections do not adequately cover the sections of your consent document, you can create your own custom sections. You can also create your own images and animations and add them to your consent section, to complete the experience. The animations you add should be H.264 videos; for best results, try to match the assets included with the ResearchKit framework. + +### Create a Visual Consent Step + +The visual consent step presents the sections of the consent document. +It is your responsibility to populate the visual consent step with +content; the `ORKVisualConsentStep` object doesn't contain any +default content. + + // Add consent sections for each page of visual consent; for example: + ORKConsentSection *section1 = + [[ORKConsentSection alloc] initWithType:ORKConsentSectionTypeDataGathering]; + document.sections = @[section1, ...]; + + // Add the document to a visual consent step and/or a review step: + ORKVisualConsentStep *visualConsent = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsentIdentifier document:document]; + + // Create and present a task including this step. + + +The visual step is presented as shown in Figure 1. + +

Consent overview screen (ORKConsentSectionTypeOverview object)

Data gathering (ORKConsentSectionTypeDataGathering object)

Privacy (ORKConsentSectionTypePrivacy object)

+

+

Data use disclosure (ORKConsentSectionTypeDataUse object)

Time commitment (ORKConsentSectionTypeTimeCommitment object)

Type of study survey (ORKConsentSectionTypeStudySurvey object)

+

+

Study tasks (ORKConsentSectionTypeStudyTasks object)

+

Consent withdrawal (ORKConsentSectionTypeWithdrawing object)

+

+

Figure 1. Visual consent steps
+

+ + +### Add a Review Step + +Users review the consent review document in the consent review step (`ORKConsentReviewStep`). Depending on your signature requirements, users can also be asked to enter their name and write a signature on the screen. + +The content for consent review can either be produced as a concatenation of all the consent sections in your document model, or you can provide entirely separate review content as HTML in the consent document's `htmlReviewContent` property. + +When the user agrees to the content in the consent form, a confirmation dialog is shown. The text of this dialog is customizable using the `reasonForConsent` property of `ORKConsentReviewStep`. + +The name entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresName` property is YES. Similarly, the signature entry page is included in a consent review step if the step’s `signature` property contains a signature object in which the `requiresSignature` property is YES. + + + ORKConsentDocument *consent = [[ORKConsentDocument alloc] init]; + consent.title = @"Demo Consent"; + consent.signaturePageTitle = @"Consent"; + + ORKConsentReviewStep *reviewStep = + [[ORKConsentReviewStep alloc] initWithIdentifier:kConsentReviewIdentifier + signature:consent.signatures[0] + inDocument:consent]; + reviewStep.text = @"Lorem ipsum .."; + reviewStep.reasonForConsent = @"Lorem ipsum ..."; + + // Add the content to a task and present it. + + +The review step is presented as shown in Figure 2. + +

Custom consent section (ORKConsentSectionTypeCustom object)

+

Consent review (ORKConsentReviewStep object)

+

Agreeing to the consent document (reasonForConsent property of ORKConsentReviewStep object)

+

+

Consent review name entry (signature property in ORKConsentReviewStep)

+

+

Figure 2. Review consent steps
+

+ +### Consent-Sharing Step + +Apps that use the ResearchKit framework primarily collect data for a +specific study. But if you want to ask participants to share their data with other +researchers, participants must be able to control that decision. + +A consent-sharing step (`ORKConsentSharingStep`) can be used to explicitly obtain permission +to share participants' data that you have collected for your study with other researchers, if allowed by +your IRB or EC if applicable. To use a consent-sharing step, include it in a task, perhaps +just before a consent review step. + + + ORKConsentSharingStep *sharingStep = + [[ORKConsentSharingStep alloc] initWithIdentifier:kConsentSharingIdentifier + investigatorShortDescription:@"MyInstitution" + investigatorLongDescription:@"MyInstitution and its partners" + localizedLearnMoreHTMLContent:@"Lorem ipsum..."]; + + // Then include this step to a task and present with a task view controller. + + +The consent-sharing step is shown in Figure 3. + +

+
+Instruction step +
Figure 3. A consent-sharing step
+
+
+ +##Create the Consent Task + +After you create the step(s), create an `ORKOrderedTask` task and add them to it. To present the task, attach your task to a task view controller and present it. + +This code snippet shows how to create a task with a visual consent step and a consent review step: + + + ORKVisualConsentStep *visualStep = + [[ORKVisualConsentStep alloc] initWithIdentifier:kVisualConsentIdentifier + document:consent]; + ORKConsentReviewStep *reviewStep = + [[ORKConsentReviewStep alloc] initWithIdentifier:kConsentReviewIdentifier + signature:consent.signatures[0] + inDocument:consent]; + // Configure the steps. + + // Create a task containing those steps. + ORKOrderedTask *task = + [[ORKOrderedTask alloc] initWithIdentifier:kConsentTaskIdentifier + steps:@[visualStep,reviewStep]]; + + ORKTaskViewController *taskViewController = + [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + + // And then present the task view controller. + +##Generate a PDF + +The ResearchKit framework can help you generate a PDF of the signed consent form and provide it to the user. For example, your app could generate the PDF locally, write it to disk, email it to the participant, display it in the app, or send it to a server. + +To do this, first take any signature results from the completed consent review, and apply the resulting signatures to a copy of your consent document. Then, call the `makePDFWithCompletionHandler:` method of `ORKConsentDocument` as shown here. + + + ORKConsentDocument *documentCopy = [document copy]; + + ORKConsentSignatureResult *signatureResult = + (ORKConsentSignatureResult *)[[[taskViewController result] stepResultForStepIdentifier:kConsentReviewIdentifier] firstResult]; + [signatureResult applyToDocument:documentCopy]; + + [documentCopy makePDFWithCompletionHandler:^(NSData *pdfData, NSError *error) { + // Write the PDF data to disk, email it, display it, or send it to a server. + }]; + + +You can only apply a signature result to a new copy of a consent document. + +##Enhanced PDF Viewing + +Providing clear and concise material for the user to review is an important part of the data collection process. With `ORKPDFViewerStep`, the user can view a PDF in detail, perform text search, and mark up sections of the document. Other available features include viewing the pages of the PDF as thumbnails for quick perusal, printing, and saving the document. + +The various modes of this step are show in Figure 4. + +

Reviewing the document

+

Viewing the document in thumbnail mode

+

Marking up the document in markup mode

+

+

Searching the document for text

+

Sharing the document

+

+

Figure 4. PDF viewing modes
+ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_1.png new file mode 100755 index 0000000..fd4f4cf Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_2.png new file mode 100755 index 0000000..f673b8b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_3.png new file mode 100755 index 0000000..cfcb4c9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_4.png new file mode 100755 index 0000000..9a1420f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_5.png new file mode 100755 index 0000000..180cf2f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/PDFStep_5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/SharingConsentStep.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/SharingConsentStep.png new file mode 100755 index 0000000..7cd1a92 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/SharingConsentStep.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_1.png new file mode 100755 index 0000000..e94f10e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_10.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_10.png new file mode 100755 index 0000000..c628555 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_10.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_11.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_11.png new file mode 100755 index 0000000..a13bc8f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_11.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_12.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_12.png new file mode 100755 index 0000000..f1c8417 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_12.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_2.png new file mode 100755 index 0000000..5e8bbc6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_3.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_3.png new file mode 100755 index 0000000..57874fa Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_3.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_4.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_4.png new file mode 100755 index 0000000..7917e50 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_4.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_5.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_5.png new file mode 100755 index 0000000..88e24a2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_5.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_6.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_6.png new file mode 100755 index 0000000..bc5c646 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_6.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_7.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_7.png new file mode 100755 index 0000000..21c05f7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_7.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_8.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_8.png new file mode 100755 index 0000000..2726879 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_8.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_9.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_9.png new file mode 100755 index 0000000..4f52f59 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/InformedConsent/VisualStep_Images/VisualStep_9.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/GuideOverview-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/GuideOverview-template.markdown new file mode 100755 index 0000000..580a65d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/GuideOverview-template.markdown @@ -0,0 +1,95 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +#ResearchKit Framework Programming Guide + +The *ResearchKit™ framework* is an open source software framework that makes it easy for app +developers and researchers to create research apps. This new framework takes advantage of sensors +and capabilities of iPhone to track movement, take measurements, and record data. Users can perform +activities and generate data from anywhere. + +##Modules + +The *ResearchKit framework* provides three customizable modules that address some of the most +common elements of research: *surveys*, *consent*, and *active tasks*. You can use these modules as they +are, build on them, and even create completely new modules of your own. + +###Surveys + +The survey module's predefined user interface lets you quickly build surveys simply by specifying +the questions and types of answers. The survey module is already localized, so all you need to do is +to localize your questions. To learn more about surveys, see +[Creating Surveys](CreatingSurveys-template). + +###Consent + +Participants in research studies are often asked to share sensitive information as part of their +enrollment and involvement in the study. That’s why it’s critical to clarify exactly what +information will be collected from users and who will have access to their information. The +*ResearchKit framework* provides templates that you can customize to explain the details of your +study and to obtain the participant’s consent. To learn more about consent, see +[Creating a Consent Document](InformedConsent-template). + +### Active Tasks +Some studies may need more data than is provided by responses to survey questions or the data +collection capabilities of the *HealthKit* and *CoreMotion* APIs on *iOS*. Active tasks invite users +to perform activities under partially controlled conditions using iPhone sensors to actively collect +data. To learn more about active tasks, see [Active Tasks](ActiveTasks-template). + +##Tasks and Steps + +A task in the *ResearchKit framework* can be a simple ordered sequence of steps, or it can be +dynamic, with previous results informing what is presented. The task view controller supports saving +progress in the middle of a long task and restoring it later, as well as UI state restoration to +prevent data loss if the user switches out of your app in the middle of a task. + +Whether your app is giving instructions, presenting a form or survey, obtaining consent, or running +an active task, everything in the *ResearchKit framework* is a collection of steps +(`ORKStep` objects), which together form a task (an `ORKTask` object). To present a task, attach the +task to a task view controller object (`ORKTaskViewController`). When the user completes a step in a +task, the task view controller generates a step result object (`ORKStepResult`) that records the +start and end time for that step, and any results from the step. + +
ResearchKit framework Overview
+ +In a simple app, you can build up your tasks directly in code, collect the results, and serialize +them to disk for later manual collection and analysis. A large-scale deployment might dynamically +download predefined surveys from a server and deserialize them to produce a *ResearchKit framework* +object hierarchy. Similarly, results from tasks can be serialized and uploaded to a server for later +analysis. + +##Current Limitations + +The *ResearchKit framework* feature list will continue to grow as useful modules are contributed by +the community. Keep in mind that the *ResearchKit framework* currently doesn’t include: + +* Background sensor data collection. APIs like *HealthKit* and *CoreMotion* on *iOS* already support + this. +* Secure communication mechanisms between your app and your server; you will need to provide this. +* The ability to schedule surveys and active tasks for your participants. +* A defined data format for how the *ResearchKit framework* structured data is serialized. All the + *ResearchKit framework* objects conform to the `NSSecureCoding` protocol, and sample code exists + protocol, and sample code exists outside the framework for + serializing objects to JSON. + +You are responsible for complying with applicable law for each +territory in which the app is made available. + +## Logging Errors and Warnings + +The *ResearchKit framework* supports four log levels, controlled by four preprocessor macros and their corresponding *`NSLog()`-like* logging macros: +* `ORK_LOG_LEVEL_NONE` +* `ORK_LOG_LEVEL_DEBUG`, `ORK_Log_Debug()` +* `ORK_LOG_LEVEL_WARNING`, `ORK_Log_Warning()` +* `ORK_LOG_LEVEL_ERROR`, `ORK_Log_Error()` + +Setting the *ResearchKit framework* `ORK_LOG_LEVEL_NONE` macro to `1` completely silences all ResearchKit logs, overriding any other specified log level. Setting `ORK_LOG_LEVEL_DEBUG`, `ORK_LOG_LEVEL_WARNING`, or `ORK_LOG_LEVEL_ERROR` to `1` enables logging at that level and at those of higher seriousness. + +If you do not explicitly set a log level, `ORK_LOG_LEVEL_WARNING=1` is used by default. + +You have to set any of these preprocessor macros in your ResearchKit subproject, not in your main project. Within *Xcode*, you can do so by setting any of them in the `Preprocessor Macros` list on the `Build Settings` of your `ResearchKit` framework target. + +See these resources if you are using ResearchKit through CocoaPods and need to change the log level: [[1]](http://stackoverflow.com/a/30038120/269753) [[2]](http://www.mokacoding.com/blog/cocoapods-and-custom-build-configurations/). + +##Digital Object Identifier for ResearchKit +The ResearchKit repository has an assigned digital object identifier (DOI), which is a persistent identifier that can be used to reference ResearchKit in academic papers. The DOI is registered on zenodo.org. See https://doi.org/10.5281/zenodo.826964 . diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/overview.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/overview.png new file mode 100755 index 0000000..2c0c6fc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Overview/overview.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode-template.markdown new file mode 100755 index 0000000..d0830bb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode-template.markdown @@ -0,0 +1,140 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +# Passcode +ResearchKit apps often hold sensitive user data. In order to protect that data, your app can use Apple's Passcode technology from within ResearchKit. With Passcode, your users can provide a four or six-digit user-selected code for access or use their fingerprint via Touch ID on devices that provide that feature. + +Supporting Passcode in your app involves several operations: + + * Creation, during which the user enters their desired passcode twice—once to establish it and a second time to confirm it. + * Access, when the app requests the four-digit passcode or Touch ID after the passcode is created. + * Edit, in case the user wants to change the passcode. + * Remove, in case the user no longer wants a passcode. + +The user's keychain on the device stores the passcode. + +##Create a Passcode +The creation of a passcode starts with the creation of an `ORKPasscodeStep` object. The `ORKPasscodeStep` class inherits from the `ORKStep` class and provides step functionality that is common in ResearchKit. + +This code demonstrates how to create a passcode step using a four-digit passcode. + +First, create the step object: + + ORKPasscodeStep *passcodeStep = [[ORKPasscodeStep alloc] init]; + +Next, set the passcode type. Here, a four-digit passcode is used: + + passcodeStep.passcodeType = ORKPasscodeType4Digit; + +For additional security, consider using a six-digit passcode: + + passcodeStep.passcodeType = ORKPasscodeType6Digit; + +After the step is created, create an `ORKOrderedTask` object. Pass a string identifier as the first parameter, and the newly created passcode step (along with any additional steps for your app) into an array as the second parameter: + + ORKOrderedTask *task = [[ORKOrderedTask alloc] initWithIdentifier:@"passcodeTask" steps:@[passcodeStep]]; + +Pass the newly created task to an `ORKTaskViewController` object and set the view controller's delegate: + + ORKTaskViewController *taskViewController = [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + taskViewController.delegate = self + +Finally, present the task view controller: + + [self presentViewController:taskViewController animated:TRUE completion:nil]; + +The user is instructed to type in a passcode twice—once for the initial passcode, and again to confirm it. Figure 1 shows the initial view. + +
+Initial passcode view +
+
Figure 1. Initial passcode view
+

+ +If the confirmation fails, an alert appears indicating a mismatch. The user can then type the passcode again, as shown in Figure 2. + +

+Incorrect passcode with retry +
+
Figure 2. Incorrect passcode with retry
+

+ +Upon a successful match, the step alerts the user that it has saved the passcode. The device's keychain stores the passcode. + + +##Use the Passcode to Protect Content +With the passcode set, you can protect sensitive data in your app by enforcing user confirmation. The `ORKPasscodeViewController` class is responsible for displaying the view that requires the user to enter their passcode before proceeding. Note that a passcode *must* be set prior to enforcement, or an exception occurs. + +To enforce passcode entry, use the following class method: + + ORKPasscodeViewController * passcodeViewController; + + if ([ORKPasscodeViewController isPasscodeStoredInKeychain] == YES) { + self.passcodeViewController = [ORKPasscodeViewController passcodeAuthenticationViewControllerWithText:@"Upon success, you'll go to the next step." delegate:self]; + // present the view + } else { + } + +Your class must adhere to the `ORKPasscodeDelegate` protocol in order to know whether the passcode was entered correctly or not, or if the user canceled. + +When the view is presented, the user is prompted to enter their four or six-digit passcode, as shown in Figure 3. + +

+Passcode entry +
+
Figure 3. Passcode entry
+

+ + +The following method is called if the passcode was successfully entered: + + - (void)passcodeViewControllerDidFinishWithSuccess:(UIViewController *)viewController; + +You should perform any steps that would follow a successful authentication at this point. + +If the user does not input the passcode correctly, the following method is called: + + - (void)passcodeViewControllerDidFailAuthentication:(UIViewController *)viewController; + +The `passcodeViewControllerDidFailAuthentication` method gives your app the opportunity to attempt a reauthentication or rejection of additional steps going forward. + +If you want to provide a Cancel button so that the user has the option to back out of the authentication process, implement the following method: + + - (void)passcodeViewControllerDidCancel:(UIViewController *)viewController; + +The `passcodeViewControllerDidCancel` method is also called if the user taps the Cancel button. + +##Edit an Existing Passcode +Provide users the ability to conveniently edit their passcode by using the following code: + + ORKPasscodeViewController *passcodeViewController; + + if ([ORKPasscodeViewController isPasscodeStoredInKeychain] == YES) { + self.passcodeViewController = [ORKPasscodeViewController passcodeEditingViewControllerWithText:@"Choose something unique." delegate:self passcodeType:OKPasscodeType4Digit]; + // present the view + } else { + } + +When the editing view controller appears, the user is prompted to enter their old passcode, as shown in Figure 4. + +

+Old passcode entry +
+
Figure 4. Old passcode entry
+

+ +If it is entered correctly, the user has the opportunity to enter a new passcode of the specified type and should enter it again to verify it. + +Note that the passcode type (four or six-digit) is passed as the last parameter to the method, allowing the user's new passcode to be of a different type than their current one. + +##Remove an Existing Passcode +At times it is necessary to know if the user has already created a passcode. The following class method on the `ORKPasscodeViewController` class returns YES or NO to indicate whether or not a passcode exists: + + + (BOOL)isPasscodeStoredInKeychain; + +You can remove the user's passcode from the keychain with the following class method on the `ORKPasscodeViewController` class: + + + (BOOL)removePasscodeFromKeychain; + +The value YES is returned if the passcode was successfully removed from the keychain. + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode.png new file mode 100755 index 0000000..14977a1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_ask.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_ask.png new file mode 100755 index 0000000..6ca74d9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_ask.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_edit.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_edit.png new file mode 100755 index 0000000..a5b1dd0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_edit.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_retry.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_retry.png new file mode 100755 index 0000000..e854064 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Passcode/Passcode_retry.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/CreatingSurveys-template.markdown b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/CreatingSurveys-template.markdown new file mode 100755 index 0000000..4f096b6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/CreatingSurveys-template.markdown @@ -0,0 +1,397 @@ +# +These materials are for informational purposes only and do not constitute legal advice. You should contact an attorney to obtain advice with respect to the development of a research app and any applicable laws. + +#Creating Surveys + +A survey is a sequence of questions that you use to collect data from your users. In a ResearchKit app, a survey is composed of a survey task that has a collection of step objects (`ORKStep`). Each step object handles a specific question in the survey, such as "What medications are you taking?" or "How many hours did you sleep last night?". + +You can collect results for the individual steps or for the task as a whole. There are two types of survey tasks: an ordered task (`ORKOrderedTask`) and a navigable ordered task (`ORKNavigableOrderedTask`). + +In an ordered task, the order that the steps appear are always the same. +

+
+
An example of a survey that uses ordered tasks.
+
+
+ +In a navigable ordered task, the order of the tasks can change, or branch out, depending on how the user answered a question in a previous task. + +
+
+
An example of a survey that uses navigable ordered tasks.
+
+
+ +The steps for creating a task to present a survey are: + +1. Create one or more steps +2. Create a task +3. Collect results + +##1. Create Steps + +The survey module provides a single-question step (`ORKQuestionStep`) +and a form step that can contain more than one item +(`ORKFormStep`). You can also use an instruction step +(`ORKInstructionStep`) or a video instruction step (`ORKVideoInstructionStep`) to introduce the survey or provide instructions. + +Every step has its own step view controller that defines the UI +presentation for that type of step. A task view controller presents the steps, instantiating and presenting the right step view +controller for the step. You can optionally customize the details of +each step view controller, such as button titles and appearance, by +implementing task view controller delegate methods (see +`ORKTaskViewControllerDelegate`). + +### Instruction Step + +An instruction step explains the purpose of a task and provides +instructions for the user. An `ORKInstructionStep` object includes an +identifier, title, text, detail text, and an image. An +instruction step does not collect any data and yields an empty +`ORKStepResult` that nonetheless records how long the instruction was +on screen. + + + ORKInstructionStep *step = + [[ORKInstructionStep alloc] initWithIdentifier:@"identifier"]; + step.title = @"Selection Survey"; + step.text = @"This survey helps us understand your eligibility for the fitness study"; + + +Creating a step as shown in the code above, including it in a task, and presenting with a task view controller, yields something like this: + +
+
+Instruction step +
Example of an instruction step.
+
+
+ + +### Question Step + +A question step ([ORKQuestionStep](#)) presents a single question, +composed of a short [title]([ORKStep title]) and longer, more descriptive [text]([ORKStep text]). Configure the type of data the user can enter by setting the answer format. You can +also provide an option for the user to skip the question with the +step's [optional]([ORKStep optional]) property. + +For numeric and text answer formats, the question step's [placeholder]([ORKQuestionStep placeholder]) +property specifies a short hint that describes the expected value of +an input field. + +A question step yields a step result that, like the instruction step's +result, indicates how long the user had the question on screen. It +also has a child, an [ORKQuestionResult](#) subclass that reports the +user's answer. + +The following code configures a simple numeric question step: + + + ORKNumericAnswerFormat *format = + [ORKNumericAnswerFormat integerAnswerFormatWithUnit:@"years"]; + format.minimum = @(18); + format.maximum = @(90); + ORKQuestionStep *step = + [ORKQuestionStep questionStepWithIdentifier:kIdentifierAge + title:@"How old are you?" + answer:format]; + + +Adding this question step to a task and presenting the task produces a screen that looks like this: + +
+
+Question step +
Example of a question step.
+
+
+ +###Form Step + +When your survey has several related questions, you can use a form step ([ORKFormStep](#)) to present them all on one page. Form steps support all the same answer formats as question +steps, but can contain multiple items ([ORKFormItem](#)), each with its +own answer format. + +Forms can be organized into sections by incorporating "dummy" form +items that contain only a title. See the [ORKFormItem](#) reference documentation +for more details. + +The result of a form step is similar to the result of a question step, +except that it contains one question result for each form +item. The results are matched to their corresponding form items using +their identifiers (the [identifier]([ORKFormItem identifier]) property). + +For example, the following code shows how to create a form that requests some basic details, using default values extracted from HealthKit on iOS to accelerate data entry: + + + ORKFormStep *step = + [[ORKFormStep alloc] initWithIdentifier:kFormIdentifier + title:@"Form" + text:@"Form groups multi-entry in one page"]; + NSMutableArray *items = [NSMutableArray new]; + ORKAnswerFormat *genderFormat = + [ORKHealthKitCharacteristicTypeAnswerFormat + answerFormatWithCharacteristicType: + [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]]; + [items addObject: + [[ORKFormItem alloc] initWithIdentifier:kGenderItemIdentifier + text:@"Gender" + answerFormat:genderFormat]; + + // Include a section separator + [items addObject: + [[ORKFormItem alloc] initWithSectionTitle:@"Basic Information"]]; + + ORKAnswerFormat *bloodTypeFormat = + [ORKHealthKitCharacteristicTypeAnswerFormat + answerFormatWithCharacteristicType: + [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType]]; + [items addObject: + [[ORKFormItem alloc] initWithIdentifier:kBloodTypeItemIdentifier + text:@"Blood Type" + answerFormat:bloodTypeFormat]]; + + ORKAnswerFormat *dateOfBirthFormat = + [ORKHealthKitCharacteristicTypeAnswerFormat + answerFormatWithCharacteristicType: + [HKCharacteristicType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth]]; + ORKFormItem *dateOfBirthItem = + [[ORKFormItem alloc] initWithIdentifier:kDateOfBirthItemIdentifier + text:@"DOB" + answerFormat:dateOfBirthFormat]]; + dateOfBirthItem.placeholder = @"DOB"; + dateOfBirthItem.optional = YES; + [items addObject:dateOfBirthItem]; + + // ... And so on, adding additional items + step.formItems = items; + + +The code above creates this form step: +
+
+Form step +
Example of a form step.
+
+
+ +The [ORKFormItem](#) has a boolean property named `optional` which affects navigation to subsequent steps. It is set to NO by default, which requires the user to set that item before they can continue. If the property is set to YES, then the user can continue to the next step without setting the item. In the above code snippet, the `optional` property is for the `dateOfBirth` object is set to YES. This lets the user continue to the next step without entering their date of birth. + +### Answer Formats + +In the ResearchKit™ framework, an answer format defines how the user should be asked to +answer a question or an item in a form. For example, consider a +survey question such as "On a scale of 1 to 10, how much pain do you +feel?" The answer format for this question would naturally be a +discrete scale on that range, so you can use scale answer format ([ORKScaleAnswerFormat](#)), +and set its [minimum]([ORKScaleAnswerFormat minimum]) and [maximum]([ORKScaleAnswerFormat maximum]) +properties to reflect the desired range. + +The screenshots below show the standard answer formats that the ResearchKit framework provides. + +

Scale answer format

Boolean answer format

Value picker answer format

+

+

Image choice answer format

Text choice answer format (single text choice answer)

Text choice answer format (multiple text choice answer)

+

+

Numeric answer format

TimeOfTheDay answer format

Date answer format

+

+

Text answer format (unlimited text entry)

Text answer format (limited text entry)

+

Validated text answer format

+

+

Scale answer format (vertical)

+

Email answer format

+

Location answer format

+

+ +In addition to the preceding answer formats, the ResearchKit framework provides +special answer formats for asking questions about quantities or +characteristics that the user might already have stored in the Health +app. When a HealthKit answer format is used, the task view controller +automatically presents a Health data access request to the user (if +they have not already granted access to your app). The presentation +details are populated automatically, and, if the user has granted +access, the field defaults to the current value retrieved from their +Health database. + +## 2. Create a Survey Task + +Once you create one or more steps, create an `ORKOrderedTask` object to +contain the steps. The code below shows a Boolean step being added to a task. + + + // Create a Boolean step to include in the task. + ORKStep *booleanStep = + [[ORKQuestionStep alloc] initWithIdentifier:kNutritionIdentifier]; + booleanStep.title = @"Do you take nutritional supplements?"; + booleanStep.answerFormat = [ORKBooleanAnswerFormat new]; + booleanStep.optional = NO; + // Create a task wrapping the boolean step. + ORKOrderedTask *task = + [[ORKOrderedTask alloc] initWithIdentifier:kTaskIdentifier + steps:@[booleanStep]]; + + +You must assign a string identifier to each step. The step identifier must be unique within the task, because it is the key that connects a step in the task hierarchy with the step result in the result hierarchy. + +To present the task, attach it to a task view controller and present +it. The code below shows how to create a task view controller and present it modally. + + + // Create a task view controller using the task and set a delegate. + ORKTaskViewController *taskViewController = + [[ORKTaskViewController alloc] initWithTask:task taskRunUUID:nil]; + taskViewController.delegate = self; + + // Present the task view controller. + [self presentViewController:taskViewController animated:YES completion:nil]; + + +*Note: `ORKOrderedTask` assumes that you will always present all the questions, +and will never decide what question to show based on previous answers. +To introduce conditional logic, you must either subclass +`ORKOrderedTask` or implement the `ORKTask` protocol yourself.* + +##3. Collect Results + +The [result]([ORKTaskViewController result]) property of the task view controller gives you the results of the task. +Each step view controller that the user views produces a step result +([ORKStepResult](#)). The task view controller collates these results as +the user navigates through the task, in order to produce an +[ORKTaskResult](#). + +Both the task result and step result are collection results, in that +they can contain other result objects. For example, a task result +contains an array of step results. + +The results contained in a step result vary depending on the type of +step. For example, a question step produces a question result +([ORKQuestionResult](#)); a form step produces one question result for +every form item; and an active task with recorders generally produces +one result for each recorder. + +The hierarchy of results corresponds closely to the input +model hierarchy of task and steps, as you can see here: + +

+
+Completion step +
Example of a result hierarchy
+
+
+
+ +Among other properties, every result has an identifier. This +identifier is what connects the result to the model object (task, +step, form item, or recorder) that produced it. Every result also +includes start and end times, using the [startDate]([ORKResult startDate]) and [endDate]([ORKResult endDate]) +properties respectively. These properties can be used to infer how long the user +spent on the step. + +### Conditional Steps + +Sometimes it's important to know the result of a step before presenting the next step. For example, suppose a step asks "Do you have a fever?" If the user answers `Yes`, the next question the next question might be "What is your temperature now?"; otherwise it might be, "Do you have any additional health concerns?" + +To add custom conditional behavior in your task, use either ordered task (`ORKOrderedTask`) or navigable ordered task (`ORKNavigableOrderedTask`), and override particular `ORKTask` methods like `stepAfterStep:withResult`, and `stepBeforeStep:withResult:` and call `super` for all other methods. + +#### Ordered Tasks + +A sequential (static) task, such as a survey or an active task, can be represented as an ordered task. + +The following example demonstrates how to subclass +`ORKOrderedTask` to provide a different set of steps depending on the +user's answer to a Boolean question. Although the code shows the step-after-step method, a corresponding implementation of "step-before-step" +is usually necessary. + + + - (ORKStep *)stepAfterStep:(ORKStep *)step + withResult:(id)result { + NSString *identifier = step.identifier; + if ([identifier isEqualToString:self.qualificationStep.identifier]) + { + ORKStepResult *stepResult = [result stepResultForStepIdentifier:identifier]; + ORKQuestionResult *result = (ORKQuestionResult *)stepResult.firstResult; + if ([result isKindOfClass:[ORKBooleanQuestionResult class]]) + { + ORKBooleanQuestionResult *booleanResult = result; + NSNumber *booleanAnswer = booleanResult.booleanAnswer; + if (booleanAnswer) + { + return booleanAnswer.boolValue ? self.regularQuestionStep : self.terminationStep; + } + } + } + return [super stepAfterStep:step withResult:result]; + } + + +#### Navigable Ordered Task +The navigable ordered task (`ORKNavigableOrderedTask`) inherits its behavior from the ordered task (`ORKOrderedTask`) class. In addition to inheriting the behavior of ordered task it provides functionality to present different set of steps depending on the user's answer to a question. + +You can add a condition while the user navigates through the steps in a task by adding a conditional step navigation. For example, add a navigation rule to obtain a new destination step when the user goes forward from one step to another. You cannot add more than one navigation rule to the same step. If you do, then the most recent rule is executed. + +For example, to display a survey question only when the user answered Yes to a previous question you can use `ORKPredicateStepNavigationRule`; or if you want to define an arbitrary jump between two steps, you can use `ORKDirectStepNavigationRule`. + +The following example demonstrates how you can add a navigation rule to go to different step in the task depending on the user's selection to the symptom type. For example, from the "symptom" step, go to "other_symptom" step when the user didn't chose headache. Otherwise, default to going to next step (the regular ordered task ([ORKOrderedTask](#)) applies). + + + ORKNavigableOrderedTask *task = [[ORKNavigableOrderedTask alloc] initWithIdentifier:StepNavigationTaskIdentifier steps:steps]; + + + // Build a navigation rule + ORKPredicateStepNavigationRule *predicateRule = nil; + + NSPredicate *predicateHeadache = [ORKResultPredicate predicateForChoiceQuestionResultWithResultIdentifier:@"symptom" expectedString:@"headache"]; + + + // The user didn't choose headache at the symptom step + NSPredicate *predicateNotHeadache = [NSCompoundPredicate notPredicateWithSubpredicate:predicateHeadache]; + + predicateRule = [[ORKPredicateStepNavigationRule alloc] initWithResultPredicates:@[ predicateNotHeadache ] + destinationStepIdentifiers:@[ @"other_symptom" ] ]; + + [task setNavigationRule:predicateRule forTriggerStepIdentifier:@"symptom"]; + + +#### Saving Results on Task Completion + +After a task is completed, you can save or upload the results. This approach +will likely include serializing the result hierarchy in some form, +either using the built-in `NSSecureCoding` support, or another +format appropriate for your application. + +If your task can produce file output, the files are generally referenced by an `ORKFileResult` object and they are placed in the output directory that you set on the task view controller. After you complete a task, one implementation might be to serialize the result hierarchy into the output directory, zip up the entire output +directory, and share it. + +In the following example, the result is archived with +`NSKeyedArchiver` on successful completion. If you choose to support +saving and restoring tasks, the user may save the task, so this +example also demonstrates how to obtain the restoration data that +would later be needed to restore the task. + + - (void)taskViewController:(ORKTaskViewController *)taskViewController + didFinishWithReason:(ORKTaskViewControllerFinishReason)reason + error:(NSError *)error + { + switch (reason) { + case ORKTaskViewControllerFinishReasonCompleted: + // Archive the result object first + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:taskViewController.result]; + + // Save the data to disk with file protection + // or upload to a remote server securely. + + // If any file results are expected, also zip up the outputDirectory. + break; + case ORKTaskViewControllerFinishReasonFailed: + case ORKTaskViewControllerFinishReasonDiscarded: + // Generally, discard the result. + // Consider clearing the contents of the output directory. + break; + case ORKTaskViewControllerFinishReasonSaved: + NSData *data = [taskViewController restorationData]; + // Store the restoration data persistently for later use. + // Normally, keep the output directory for when you will restore. + break; + } + } + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/BooleanAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/BooleanAnswerFormat.png new file mode 100755 index 0000000..720ee66 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/BooleanAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/DateAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/DateAnswerFormat.png new file mode 100755 index 0000000..7c030d9 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/DateAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/EmailAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/EmailAnswerFormat.png new file mode 100755 index 0000000..bb098ae Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/EmailAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep.png new file mode 100755 index 0000000..46740d3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep_2.png new file mode 100755 index 0000000..a4bbe11 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/FormStep_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ImageChoiceAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ImageChoiceAnswerFormat.png new file mode 100755 index 0000000..00b7dfd Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ImageChoiceAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/InstructionStep.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/InstructionStep.png new file mode 100755 index 0000000..2fcaf2a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/InstructionStep.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/LocationAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/LocationAnswerFormat.png new file mode 100755 index 0000000..5481f2a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/LocationAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NavigableOrderedTasks.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NavigableOrderedTasks.png new file mode 100755 index 0000000..2d334fe Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NavigableOrderedTasks.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NumericAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NumericAnswerFormat.png new file mode 100755 index 0000000..1f67c19 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/NumericAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/OrderedTasks.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/OrderedTasks.png new file mode 100755 index 0000000..846d7f3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/OrderedTasks.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/QuestionStep.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/QuestionStep.png new file mode 100755 index 0000000..d8c5dd5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/QuestionStep.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ResultsHierarchy.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ResultsHierarchy.png new file mode 100755 index 0000000..7c0a582 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ResultsHierarchy.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ScaleAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ScaleAnswerFormat.png new file mode 100755 index 0000000..2fcaf2a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ScaleAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyExample.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyExample.png new file mode 100755 index 0000000..1d0ad48 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyExample.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_1.png new file mode 100755 index 0000000..a43edb4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_2.png new file mode 100755 index 0000000..1b7213e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/SurveyIntroduction_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_1.png new file mode 100755 index 0000000..35d2ea5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_2.png new file mode 100755 index 0000000..f4d0900 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextAnswerFormat_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_1.png new file mode 100755 index 0000000..33f4769 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_2.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_2.png new file mode 100755 index 0000000..93fa079 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TextChoiceAnswerFormat_2.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeIntervalAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeIntervalAnswerFormat.png new file mode 100755 index 0000000..26342c0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeIntervalAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeOfTheDayAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeOfTheDayAnswerFormat.png new file mode 100755 index 0000000..70f7c49 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/TimeOfTheDayAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValidatedTextAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValidatedTextAnswerFormat.png new file mode 100755 index 0000000..06be54f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValidatedTextAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValuePickerAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValuePickerAnswerFormat.png new file mode 100755 index 0000000..9c5888a Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/ValuePickerAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/VerticalSliderAnswerFormat.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/VerticalSliderAnswerFormat.png new file mode 100755 index 0000000..e737207 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/VerticalSliderAnswerFormat.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/video_1.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/video_1.png new file mode 100755 index 0000000..245fd1b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/Survey/SurveyImages/video_1.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/index-template.md b/PediatricPancreas_Storyboard/ResearchKit-master/docs/index-template.md new file mode 100755 index 0000000..3f9cd4a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/index-template.md @@ -0,0 +1,55 @@ +The ResearchKit™ framework is an open source framework that developers and researchers can use to create apps that let iOS users participate in medical research. + +This is the API documentation for the ResearchKit framework. For an overview of framework and a more general guide to using and extending the framework, see the [Programming Guide](GuideOverview). + + +Constructing Tasks +-------------------- + +ResearchKit tasks are actions to be performed by participants in a research study. Tasks are the building blocks for ResearchKit modules, which address the most common components of medical studies: surveys, consent documents, and active tasks. + +Tasks are constructed using a hierarchy of model objects. +At the root of the hierarchy is an ORKOrderedTask object (or another object that implements the ORKTask protocol). The task defines the order in which steps are presented, and how progress through the task is represented. + +A task consists of steps, which are subclasses of ORKStep. Most steps are designed for data presentation or data entry, but the ORKActiveStep subclasses can also enable data collection. +The ORKQuestionStep and ORKFormStep survey step classes describe a question to be asked. The format of the answer is modeled with subclasses of ORKAnswerFormat. + + +Presenting Tasks +-------------------- + +To present a task, you create an ORKTaskViewController object and give it the task. The task view controller manages the task and returns the result through delegate methods. + +For each step, ORKTaskViewController instantiates an appropriate subclass of ORKStepViewController to display the step. + + +Getting Results +-------------------- + +The `result` property of ORKTaskViewController provides the results of the task, both while the task is in progress, and upon completion of the task. + +Results are constructed with a hierarchy that’s similar to the task model hierarchy. In the hierarchy for a result, ORKTaskResult is the root and ORKStepResult objects form the immediate children. + +For survey question steps, the answers collected are reported as ORKQuestionResult objects, which are children of ORKStepResult. Active steps may include additional result objects as children, depending on the types of data that are recorded. To help you get data from various device features, such as the accelerometer or HealthKit, the ResearchKit framework provides the ORKRecorder and ORKRecorderConfiguration classes, which work together to collect and configure data into a serialized format during the duration of an active step. + + +Predefined Active Tasks +-------------------- + +An active task invites users to perform activities under semi-controlled conditions, while iPhone sensors actively collect data. A category on ORKOrderedTask provides factory methods for generating ORKOrderedTask instances that correspond to ResearchKit's predefined active tasks, such as the short walk or fitness task. + + +Consent +-------------------- + +The consent features in the ResearchKit framework are implemented using three special steps that can be added to tasks: + +* ORKVisualConsentStep. The visual consent step presents a series of simple graphics to help participants understand the content of an consent document. The default graphics have animated transitions. + +* ORKConsentSharingStep. The consent sharing step has predefined transitions that can be used to establish user preferences regarding how widely personal data can be shared. + +* ORKConsentReviewStep. The consent review step makes the consent document available for review, and provides facilities for collecting the user's name and signature. + +Creating the visual consent step and the consent review step requires a consent document model (that is, an ORKConsentDocument object). + +In addition to the consent steps, `ORKPDFViewerStep` displays a PDF document. The user can search, marked up, and share the PDF document from within the step. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Info.plist new file mode 100755 index 0000000..543fb43 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleIdentifier + org.researchkit.ResearchKit + CFBundleName + ResearchKit Documentation + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1.0 + + + + + DocSetFeedName + ResearchKit Documentation + + DocSetMinimumXcodeVersion + 3.0 + + DashDocSetFamily + appledoc + DocSetPublisherIdentifier + org.researchkit.documentation + DocSetPublisherName + ResearchKit + NSHumanReadableCopyright + Copyright © 2018 ResearchKit. All rights reserved. + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKActiveStepTimerHandler.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKActiveStepTimerHandler.html new file mode 100755 index 0000000..d4bb57e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKActiveStepTimerHandler.html @@ -0,0 +1,109 @@ + + + + + + ORKActiveStepTimerHandler Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKActiveStepTimerHandler Block Reference

+ + +
+ + + + +
Declared inORKActiveStepTimer.h
+ + + + + + + + + + +

Block Definition

+

ORKActiveStepTimerHandler

+ + +typedef void (^ORKActiveStepTimerHandler) (ORKActiveStepTimer *timer, BOOL finished) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKOperationBlock.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKOperationBlock.html new file mode 100755 index 0000000..a0c26ca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKOperationBlock.html @@ -0,0 +1,109 @@ + + + + + + ORKOperationBlock Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKOperationBlock Block Reference

+ + +
+ + + + +
Declared inORKOperation.h
+ + + + + + + + + + +

Block Definition

+

ORKOperationBlock

+ + +typedef void (^ORKOperationBlock) (ORKOperation *operation) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKVisualConsentAnimationCompletionHandler.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKVisualConsentAnimationCompletionHandler.html new file mode 100755 index 0000000..104dda9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ORKVisualConsentAnimationCompletionHandler.html @@ -0,0 +1,109 @@ + + + + + + ORKVisualConsentAnimationCompletionHandler Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVisualConsentAnimationCompletionHandler Block Reference

+ + +
+ + + + +
Declared inORKVisualConsentTransitionAnimator.h
+ + + + + + + + + + +

Block Definition

+

ORKVisualConsentAnimationCompletionHandler

+ + +typedef void (^ORKVisualConsentAnimationCompletionHandler) (ORKVisualConsentTransitionAnimator *animator, UIPageViewControllerNavigationDirection direction) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ShouldPresentStepBlockType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ShouldPresentStepBlockType.html new file mode 100755 index 0000000..ad61e06 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/ShouldPresentStepBlockType.html @@ -0,0 +1,109 @@ + + + + + + ShouldPresentStepBlockType Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ShouldPresentStepBlockType Block Reference

+ + +
+ + + + +
Declared inTaskFactory.h
+ + + + + + + + + + +

Block Definition

+

ShouldPresentStepBlockType

+ + +typedef BOOL (^ShouldPresentStepBlockType) (ORKTaskViewController *taskViewController, ORKStep *step) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillAppearBlockType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillAppearBlockType.html new file mode 100755 index 0000000..2007b7e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillAppearBlockType.html @@ -0,0 +1,109 @@ + + + + + + StepViewControllerWillAppearBlockType Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

StepViewControllerWillAppearBlockType Block Reference

+ + +
+ + + + +
Declared inTaskFactory.h
+ + + + + + + + + + +

Block Definition

+

StepViewControllerWillAppearBlockType

+ + +typedef void (^StepViewControllerWillAppearBlockType) (ORKTaskViewController *taskViewController, ORKStepViewController *stepViewController) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillDisappearBlockType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillDisappearBlockType.html new file mode 100755 index 0000000..936fa02 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/StepViewControllerWillDisappearBlockType.html @@ -0,0 +1,109 @@ + + + + + + StepViewControllerWillDisappearBlockType Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

StepViewControllerWillDisappearBlockType Block Reference

+ + +
+ + + + +
Declared inTaskFactory.h
+ + + + + + + + + + +

Block Definition

+

StepViewControllerWillDisappearBlockType

+ + +typedef void (^StepViewControllerWillDisappearBlockType) (ORKTaskViewController *taskViewController, ORKStepViewController *stepViewController, ORKStepViewControllerNavigationDirection navigationDirection) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKLocationAuthorizationRequestHandler.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKLocationAuthorizationRequestHandler.html new file mode 100755 index 0000000..4ff8fb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKLocationAuthorizationRequestHandler.html @@ -0,0 +1,109 @@ + + + + + + _ORKLocationAuthorizationRequestHandler Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

_ORKLocationAuthorizationRequestHandler Block Reference

+ + +
+ + + + +
Declared inORKTaskViewController.m
+ + + + + + + + + + +

Block Definition

+

_ORKLocationAuthorizationRequestHandler

+ + +typedef void (^_ORKLocationAuthorizationRequestHandler) (BOOL success) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKStateHandler.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKStateHandler.html new file mode 100755 index 0000000..36db8f7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Blocks/_ORKStateHandler.html @@ -0,0 +1,109 @@ + + + + + + _ORKStateHandler Block Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

_ORKStateHandler Block Reference

+ + +
+ + + + +
Declared inORKSpatialSpanMemoryStepViewController.m
+ + + + + + + + + + +

Block Definition

+

_ORKStateHandler

+ + +typedef void (^_ORKStateHandler) (ORKState *fromState, ORKState *_toState, id context) + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKAnchoredObjectQuery+iOS8.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKAnchoredObjectQuery+iOS8.html new file mode 100755 index 0000000..1a0394c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKAnchoredObjectQuery+iOS8.html @@ -0,0 +1,119 @@ + + + + + + HKAnchoredObjectQuery(iOS8) Category Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

HKAnchoredObjectQuery(iOS8) Category Reference

+ + +
+ + + + +
Declared inORKHealthQuantityTypeRecorder.m
+ + + + +
+ +

Overview

+

Add a protocol defining the initializer for iOS 8 apps. This signature was deprecated in iOS 9 +and deleted in iOS 10.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKCorrelation+ORKJSONDictionary.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKCorrelation+ORKJSONDictionary.html new file mode 100755 index 0000000..e9bb237 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKCorrelation+ORKJSONDictionary.html @@ -0,0 +1,118 @@ + + + + + + HKCorrelation(ORKJSONDictionary) Category Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

HKCorrelation(ORKJSONDictionary) Category Reference

+ + +
+ + + + +
Declared inHKSample+ORKJSONDictionary.h
HKSample+ORKJSONDictionary.m
+ + + + +
+ +

Overview

+

JSON serialization aid for HKCorrelation.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKSample+ORKJSONDictionary.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKSample+ORKJSONDictionary.html new file mode 100755 index 0000000..f08c552 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKSample+ORKJSONDictionary.html @@ -0,0 +1,118 @@ + + + + + + HKSample(ORKJSONDictionary) Category Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

HKSample(ORKJSONDictionary) Category Reference

+ + +
+ + + + +
Declared inHKSample+ORKJSONDictionary.h
HKSample+ORKJSONDictionary.m
+ + + + +
+ +

Overview

+

JSON serialization aid for HKSample.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKUnit+ORKLocalized.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKUnit+ORKLocalized.html new file mode 100755 index 0000000..f75dc52 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/HKUnit+ORKLocalized.html @@ -0,0 +1,170 @@ + + + + + + HKUnit(ORKLocalized) Category Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

HKUnit(ORKLocalized) Category Reference

+ + +
+ + + + +
Declared inORKHealthAnswerFormat.h
ORKHealthAnswerFormat.m
+ + + + + + +
+ + + + + + +
+
+ +

– localizedUnitString +

+ +
+
+ +
+ + +
+

Returns the localized string for the unit (if available)

+
+ + + +
- (NSString *)localizedUnitString
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/UIColor+ORKColor.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/UIColor+ORKColor.html new file mode 100755 index 0000000..f687180 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Categories/UIColor+ORKColor.html @@ -0,0 +1,118 @@ + + + + + + UIColor(ORKColor) Category Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

UIColor(ORKColor) Category Reference

+ + +
+ + + + +
Declared inORKSkin.h
ORKSkin.m
+ + + + +
+ +

Overview

+

Modify the color for a specified ORK…ColorKey. (for customization)

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DragonPokerStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DragonPokerStep.html new file mode 100755 index 0000000..3d28efb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DragonPokerStep.html @@ -0,0 +1,251 @@ + + + + + + DragonPokerStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

DragonPokerStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStep : ORKStep : NSObject
Declared inDragonPokerStep.h
DragonPokerStep.m
+ + + + +
+ +

Overview

+

Example implementation of an override of the class method instantiateStepViewControllerWithResult: +In this example, only show the cancel button on Tuesdays

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– instantiateStepViewControllerWithResult: +

+ +
+
+ +
+ + +
+

Instantiates a step view controller for this class.

+
+ + + +
- (ORKStepViewController *)instantiateStepViewControllerWithResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + +
result

The result associated with this step

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + +
+

Discussion

+

This method is called when a step is about to be presented. The default implementation returns +a view controller that is appropriate to this step by allocating an instance of ORKStepViewController +using the stepViewControllerClass method and initializing that instance by calling initWithIdentifier:result: +on the provided ORKStepViewController class instance.

+ +

Override this method if you need to customize the behavior before presenting the step or if +the view controller is presented using a nib or storyboard.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DynamicTask.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DynamicTask.html new file mode 100755 index 0000000..ede14eb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/DynamicTask.html @@ -0,0 +1,269 @@ + + + + + + DynamicTask Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

DynamicTask Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKTask
Declared inDynamicTask.h
DynamicTask.m
+ + + + + + +
+ + + + + + +
+
+ +

– identifier +

+ +
+
+ +
+ + +
+

The unique identifier for this task.

+
+ + + +
- (NSString *)identifier
+ + + + + + + + + +
+

Discussion

+

The identifier should be a short string that identifies the task. The identifier is copied +into the ORKTaskResult objects generated by the task view controller for this +task. You can use a human-readable string for the task identifier +or a UUID; the exact string you use depends on your app.

+ +

In the case of apps whose tasks come from a server, the unique +identifier for the task may be in an external database.

+ +

The task view controller uses the identifier when constructing the task result. +The identifier can also be used during UI state restoration to identify the +task that needs to be restored.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepAfterStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(id<ORKTaskResultSource>)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepBeforeStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/LoginViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/LoginViewController.html new file mode 100755 index 0000000..042c8be --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/LoginViewController.html @@ -0,0 +1,191 @@ + + + + + + LoginViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

LoginViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLoginStepViewController : ORKFormStepViewController : ORKStepViewController : UIViewController
Declared inTaskFactory+Onboarding.m
+ + + + +
+ +

Overview

+

A subclass is required for the login step.

+ +

The implementation below demonstrates how to subclass and override button actions.

+
+ + + + + +
+ + + + + + +
+
+ +

– forgotPasswordButtonTapped +

+ +
+
+ +
+ + +
+

Action method for the forgot password button.

+
+ + + +
- (void)forgotPasswordButtonTapped
+ + + + + + + + + +
+

Discussion

+

The forgot password button is shown in place of the skip button. +Override this method to provide custom logic for the button action.

+
+ + + + + + + +
+

Declared In

+

ORKLoginStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/MainViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/MainViewController.html new file mode 100755 index 0000000..f6cb984 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/MainViewController.html @@ -0,0 +1,173 @@ + + + + + + MainViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

MainViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromUIViewController
Declared inMainViewController.h
MainViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– taskViewController:didChangeResult: +

+ +
+
+ +
+ + +
+

When a task has completed it calls this method to post the result of the task to the delegate.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController didChangeResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

MainViewController.m

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorder.html new file mode 100755 index 0000000..517e0bb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorder.html @@ -0,0 +1,474 @@ + + + + + + ORKAccelerometerRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAccelerometerRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKAccelerometerRecorder.h
ORKAccelerometerRecorder.m
+ + + + +
+ +

Overview

+

The ORKAccelerometerRecorder class represents a recorder that requests and collects raw accelerometer data from CoreMotion at a fixed frequency.

+ +

The accelerometer recorder continues to record when the application enters the +background by using the background task support provided by UIApplication.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:frequency:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized accelerometer recorder using the specified frequency.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

frequency

The frequency of accelerometer data collected from CoreMotion, in hertz (Hz).

step

The step that requested this recorder.

outputDirectory

The directory in which the accelerometer data should be stored.

+
+ + + +
+

Return Value

+

An initialized accelerometer recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAccelerometerRecorder.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  frequency +

+ +
+
+ +
+ + +
+

The frequency of accelerometer data collected from CoreMotion, in hertz (Hz).

+
+ + + +
@property (nonatomic, readonly) double frequency
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAccelerometerRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorderConfiguration.html new file mode 100755 index 0000000..c1055cb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAccelerometerRecorderConfiguration.html @@ -0,0 +1,511 @@ + + + + + + ORKAccelerometerRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAccelerometerRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKAccelerometerRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKAccelerometerRecorderConfiguration subclass configures +the collection of accelerometer data during an active step.

+ +

Accelerometer data is serialized to JSON and returned as an ORKFileResult object. +For details on the format, see CMAccelerometerData+ORKJSONDictionary.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithIdentifier:frequency: +

+ +
+
+ +
+ + +
+

Returns an initialized accelerometer recorder configuration using the specified frequency.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier of the recorder configuration.

frequency

The frequency of accelerometer data collection in samples per second (Hz).

+
+ + + +
+

Return Value

+

An initialized accelerometer recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new accelerometer recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the accelerometer recorder configuration.

+
+ + + +
+

Return Value

+

A new accelerometer recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  frequency +

+ +
+
+ +
+ + +
+

The frequency of accelerometer data collection in samples per second (Hz).

+
+ + + +
@property (nonatomic, readonly) double frequency
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStep.html new file mode 100755 index 0000000..38cef9a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStep.html @@ -0,0 +1,1217 @@ + + + + + + ORKActiveStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKActiveStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKActiveStep.h
ORKActiveStep.m
+ + + + +
+ +

Overview

+

The ORKActiveStep class is the base class for steps in active tasks, which +are steps that collect sensor data in a semi-controlled environment, as opposed +to the purely passive data collection enabled by HealthKit, or the more subjective data +collected when users fill in surveys.

+ +

In addition to the behaviors of ORKStep, active steps have the concept of +life cycle, which includes a defined start and finish.

+ +

The ResearchKit framework provides built-in behaviors that allow active steps to play voice prompts, speak a count down, and have a +defined duration.

+ +

To present an active step in your app, it’s likely that you will subclass ORKActiveStep and +ORKActiveStepViewController to present custom UI and custom +prompts. For example subclasses, see ORKSpatialSpanMemoryStep or ORKFitnessStep. +Active steps may also need ORKResult subclasses to record their results +if these don’t come purely from recorders.

+ +

If you develop a new active step subclass, consider contributing your +code to the ResearchKit project so that it’s available for others to use in +their studies.

+ +

See also: ORKActiveStepViewController

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  stepDuration +

+ +
+
+ +
+ + +
+

The duration of the step in seconds.

+
+ + + +
@property (nonatomic) NSTimeInterval stepDuration
+ + + + + + + + + +
+

Discussion

+

If the step duration is greater than zero, a built-in timer starts when the +step starts. If shouldStartTimerAutomatically is set, the timer +starts when the step’s view appears. When the timer expires, a sound or +vibration may be played. If shouldContinueOnFinish is set, the step +automatically navigates forward when the timer expires.

+ +

The default value of this property is 0, which disables the built-in timer.

+ +

See also: ORKActiveStepViewController

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldShowDefaultTimer +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to show a view with a default timer.

+
+ + + +
@property (nonatomic) BOOL shouldShowDefaultTimer
+ + + + + + + + + +
+

Discussion

+

The default timer UI is not used in any of the current predefined tasks, +but it can be displayed in a simple active task that does not require custom +UI and needs only a count down timer on screen during data collection.

+ +

Note that this property is ignored if stepDuration is 0.

+ +

The default value of this property is YES.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldSpeakCountDown +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to speak the last few seconds in the count down of the +duration of a timed step.

+
+ + + +
@property (nonatomic) BOOL shouldSpeakCountDown
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, AVSpeechSynthesizer is used to synthesize the countdown. Note that this property is ignored if VoiceOver is enabled.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldSpeakRemainingTimeAtHalfway +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to speak the halfway point in the count down of the +duration of a timed step.

+
+ + + +
@property (nonatomic) BOOL shouldSpeakRemainingTimeAtHalfway
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, AVSpeechSynthesizer is used to synthesize the countdown. Note that this property is ignored if VoiceOver is enabled.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldStartTimerAutomatically +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to start the count down timer automatically when the step starts, or +require the user to take some explicit action to start the step, such as tapping a button.

+
+ + + +
@property (nonatomic) BOOL shouldStartTimerAutomatically
+ + + + + + + + + +
+

Discussion

+

Usually the explicit action needs to come from custom UI in an +ORKActiveStepViewController subclass.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldPlaySoundOnStart +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to play a default sound when the step starts.

+
+ + + +
@property (nonatomic) BOOL shouldPlaySoundOnStart
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldPlaySoundOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to play a default sound when the step finishes.

+
+ + + +
@property (nonatomic) BOOL shouldPlaySoundOnFinish
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldVibrateOnStart +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to vibrate when the step starts.

+
+ + + +
@property (nonatomic) BOOL shouldVibrateOnStart
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldVibrateOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to vibrate when the step finishes.

+
+ + + +
@property (nonatomic) BOOL shouldVibrateOnFinish
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldUseNextAsSkipButton +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the Next button should double as a skip action before +the step finishes.

+
+ + + +
@property (nonatomic) BOOL shouldUseNextAsSkipButton
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, the ResearchKit framework hides the skip button and makes the Next button function as a skip button when the step has not yet finished.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  shouldContinueOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to transition automatically when the step finishes.

+
+ + + +
@property (nonatomic) BOOL shouldContinueOnFinish
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, the active step view controller automatically performs the +continue action when the [ORKActiveStepViewController finish] method +is called.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  spokenInstruction +

+ +
+
+ +
+ + +
+

Localized text that represents an instructional voice prompt.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *spokenInstruction
+ + + + + + + + + +
+

Discussion

+

Instructional speech begins when the step starts. If VoiceOver is active, +the instruction is spoken by VoiceOver.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  finishedSpokenInstruction +

+ +
+
+ +
+ + +
+

Localized text that represents an instructional voice prompt for when the step finishes.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *finishedSpokenInstruction
+ + + + + + + + + +
+

Discussion

+

Instructional speech begins when the step finishes. If VoiceOver is active, +the instruction is spoken by VoiceOver.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  image +

+ +
+
+ +
+ + +
+

An image to be displayed below the instructions for the step.

+
+ + + +
@property (nonatomic, strong, nullable) UIImage *image
+ + + + + + + + + +
+

Discussion

+

The image can be stretched to fit the available space. When choosing a size +for this asset, be sure to take into account the variations in device form factors.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

  recorderConfigurations +

+ +
+
+ +
+ + +
+

An array of recorder configurations that define the parameters for recorders to be +run during a step to collect sensor or other data.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKRecorderConfiguration*> *recorderConfigurations
+ + + + + + + + + +
+

Discussion

+

If you want to collect data from sensors while the step is in progress, +add one or more recorder configurations to the array. The active step view +controller instantiates recorders and collates their results as children +of the step result.

+ +

The set of recorder configurations is scanned when populating the +requestedHealthKitTypesForReading and requestedPermissions properties.

+ +

See also: ORKRecorderConfiguration and ORKRecorder.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– isRestorable +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether a task can be restored to the step +during state restoration. (read-only)

+
+ + + +
- (BOOL)isRestorable
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is YES, but subclasses of ORKStep might use NO.

+ +

If a task cannot be restored to the step, the task is typically restored to the +last restorable step in the task, or to the first step, if +no restorable steps are available.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types the step requests for reading. (read-only)

+
+ + + +
- (NSSet<HKObjectType*> *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this set of types when constructing a list of +all the HealthKit types required by all the steps in a task, so that it can +present the HealthKit access dialog just once during that task.

+ +

By default, the property scans the recorders and collates the HealthKit +types the recorders require. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedPermissions +

+ +
+
+ +
+ + +
+

The set of access permissions required for the step. (read-only)

+
+ + + +
- (ORKPermissionMask)requestedPermissions
+ + + + + + + + + +
+

Discussion

+

The permission mask is used by the task view controller to determine the types of +access to request from users when they complete the initial instruction steps +in a task. If your step requires access to APIs that limit access, include +the permissions you require in this mask.

+ +

By default, the property scans the recorders and collates the permissions +required by the recorders. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStepViewController.html new file mode 100755 index 0000000..36566a3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKActiveStepViewController.html @@ -0,0 +1,1360 @@ + + + + + + ORKActiveStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKActiveStepViewController Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKStepViewController : UIViewController
Conforms toORKRecorderDelegate
Declared inORKActiveStepViewController.h
ORKActiveStepViewController.m
+ + + + +
+ +

Overview

+

The ORKActiveStepViewController class is the base class for displaying ORKActiveStep +subclasses. The predefined active tasks defined in ORKOrderedTask all make use +of subclasses of ORKActiveStep, paired with ORKActiveStepViewController +subclasses.

+ +

An active step view controller is typically instantiated by a task view controller +when it encounters an active step in a task. Active steps generally include some form of sensor-driven data collection, or involve some highly interactive content, such as a cognitive task or game.

+ +

Examples of active step view controller subclasses include ORKWalkingTaskStepViewController, +ORKCountdownStepViewController, ORKSpatialSpanMemoryStepViewController, +ORKFitnessStepViewController, and ORKAudioStepViewController.

+ +

The primary feature that active step view controllers enable is life cycle. After an active step is presented, it can be started to start a timer. When the timer expires, the +step is considered finished. Some steps may have the concept of suspend and resume, such as when +the app is put in the background, and during which data recording is temporarily paused. +These life cycle methods generally apply to any recorders being used to record +data from the device’s sensors, but they should also be applied to any UI +being displayed to clearly indicate when data is being collected +for the task.

+ +

When you develop a new active step, you should subclass ORKActiveStepViewController +and define your specific UI. When subclassing, pay special attention to the life cycle +methods, start, finish, suspend, and resume. Also, be sure to test for +the expected behavior when the user suspends and resumes the app, during task +save and restore, and during UIKit’s UI state restoration.

+ +

See also: ORKActiveStep.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– imageView +

+ +
+
+ +
+ + +
+

The image view for the active step. (read-only)

+
+ + + +
- (ORKTintedImageView *)imageView
+ + + + + + + + + +
+

Discussion

+

The image view is created on demand when this property is accessed, and is a +shortcut to display an image in the custom area of an active task (that is, instead of +using customView).

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– recordersDidChange +

+ +
+
+ +
+ + +
+

Tells the view controller that the set of recorders changed.

+
+ + + +
- (void)recordersDidChange
+ + + + + + + + + +
+

Discussion

+

This method is usually called by the active step view controller in response +to start or resume.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– recordersWillStart +

+ +
+
+ +
+ + +
+

Tells the view controller that the recorders are about to start.

+
+ + + +
- (void)recordersWillStart
+ + + + + + + + + +
+

Discussion

+

This method is called by the active step view controller after instantiating +the recorders, but before starting them.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– recordersWillStop +

+ +
+
+ +
+ + +
+

Tells the view controller that the recorders are about to stop.

+
+ + + +
- (void)recordersWillStop
+ + + + + + + + + +
+

Discussion

+

This method is called by the active step view controller before +stopping the recorders.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– prepareStep +

+ +
+
+ +
+ + +
+

Tells the view controller that the step has been loaded and is about to start.

+
+ + + +
- (void)prepareStep
+ + + + + + + + + +
+

Discussion

+

This method is called by the active step view controller just after the step +has been set. The base implementation instantiates the recorders and timer but +does not start them.

+ +

Subclasses may override this method, but must also call super.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– suspend +

+ +
+
+ +
+ + +
+

Suspends the active step.

+
+ + + +
- (void)suspend
+ + + + + + + + + +
+

Discussion

+

Call this method to suspend data recording and the step’s timer.

+ +

This method may called automatically when the app is suspended. +The view controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes the active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method when the step should be resumed. Calls to this method should +be paired with previous calls to suspend.

+ +

This method may be called automatically when the app is resumed. The view +controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

When the step is resumed, the UI should resume at the point where the user left off, +or, if that does not make sense for the particular step, to the most recent +suitable point.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– finish +

+ +
+
+ +
+ + +
+

Finishes the active step.

+
+ + + +
- (void)finish
+ + + + + + + + + +
+

Discussion

+

Call this method to finish the active step. If the active step is configured with +a timer, this method is called automatically when the timer expires.

+ +

Finishing the active step stops all data recording and stops any timers. In steps that have the +shouldContinueOnFinish property set, forward navigation to the next step +may ensue.

+ +

This method does nothing if the step has already finished.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– recorder:didCompleteWithResult: +

+ +
+
+ +
+ + +
+

Tells the delegate that the recorder has completed with the specified result.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

result

The generated result.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when recording is stopped.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorder:didFailWithError: +

+ +
+
+ +
+ + +
+

Tells the delegate that recording failed.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

error

The error that occurred.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when the error occurred.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ + + +

UI Customization

+ +
+
+ +

  customView +

+ +
+
+ +
+ + +
+

The custom view for the active step.

+
+ + + +
@property (nonatomic, strong, nullable) UIView *customView
+ + + + + + + + + +
+

Discussion

+

Attach a custom view here, and implement sizeThatFits: or +use intrinsicContentSize or provide constraints that request the size needed for +the custom view within the active step’s layout.

+ +

Custom views can be used for visual instructions with animation, +or for getting interactive input.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ + + +

Data collection

+ +
+
+ +

  recorders +

+ +
+
+ +
+ + +
+

The array of recorders currently in use by the active step. (read-only)

+
+ + + +
@property (nonatomic, strong, readonly, nullable) NSArray *recorders
+ + + + + + + + + +
+

Discussion

+

Recorders are generated when the step starts, based on the recorder +configurations of the step. Each recorder is an instance of ORKRecorder, and +is created by the active step view controller using the array of recorder +configurations in the step.

+ +

See also: ORKRecorderConfiguration and ORKActiveStep.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ + + +

Active step life cycle

+ +
+
+ +

  finished +

+ +
+
+ +
+ + +
+

A Boolean value that indicates whether the step has finished. (read-only)

+
+ + + +
@property (nonatomic, assign, readonly, getter=isFinished) BOOL finished
+ + + + + + + + + +
+

Discussion

+

If the step is considered finished, the Continue button is enabled and the Skip +button is hidden. When the step is not finished, the Continue button is disabled and the Skip +button is visible.

+ +

In addition, when a step is finished, all recorders are stopped.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

  started +

+ +
+
+ +
+ + +
+

A Boolean value that indicates whether the step has started. (read-only)

+
+ + + +
@property (nonatomic, assign, readonly, getter=isStarted) BOOL started
+ + + + + + + + + +
+

Discussion

+

If the step has not yet started, recorders are not yet running, and time +is not counted against the duration of the step.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

  suspendIfInactive +

+ +
+
+ +
+ + +
+

A Boolean value that indicates whether to suspend the step if the app is not +active or the screen is off.

+
+ + + +
@property (nonatomic, assign) BOOL suspendIfInactive
+ + + + + + + + + +
+

Discussion

+

Active steps that require the screen in order to work should suspend +recording when the app goes into the background. Other active steps require +the step to continue while the app is in the background. For example, the fitness check +active step continues to collect data while the screen is off, and continues +to give voice prompts.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  customViewContainer +

+ +
+
+ +
+ + +
+

The customViewContainer allows custom view to be its subview.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) UIView *customViewContainer
+ + + + + + + + + +
+

Discussion

+

Note: When ORKTouchRecorder is present, its gesture recognizer attaches to customViewContainer.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridResult.html new file mode 100755 index 0000000..758d99d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridResult.html @@ -0,0 +1,271 @@ + + + + + + ORKAmslerGridResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAmslerGridResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKAmslerGridResult.h
ORKAmslerGridResult.m
+ + + + +
+ +

Overview

+

The ORKAmslerGridResult class represents the result of a successful attempt of ORKAmslerGridStep.

+ +

An amsler grid result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  eyeSide +

+ +
+
+ +
+ + +
+

Eye side closed.

+
+ + + +
@property (nonatomic) ORKAmslerGridEyeSide eyeSide
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAmslerGridResult.h

+
+ + +
+
+
+ +

  image +

+ +
+
+ +
+ + +
+

The image for the step.

+
+ + + +
@property (nonatomic, nullable) UIImage *image
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAmslerGridResult.h

+
+ + +
+
+
+ +

  path +

+ +
+
+ +
+ + +
+

The path used to mark the area in the image.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<UIBezierPath*> *path
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAmslerGridResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStep.html new file mode 100755 index 0000000..4b89108 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStep.html @@ -0,0 +1,251 @@ + + + + + + ORKAmslerGridStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAmslerGridStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKAmslerGridStep.h
ORKAmslerGridStep.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStepViewController.html new file mode 100755 index 0000000..9222be8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAmslerGridStepViewController.html @@ -0,0 +1,305 @@ + + + + + + ORKAmslerGridStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAmslerGridStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKAmslerGridStepViewController.h
ORKAmslerGridStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerFormat.html new file mode 100755 index 0000000..c1296d8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerFormat.html @@ -0,0 +1,320 @@ + + + + + + ORKAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAnswerFormat Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKAnswerFormat class is the abstract base class for classes that describe the +format in which a survey question or form item should be answered. The ResearchKit framework uses +ORKQuestionStep and ORKFormItem to represent questions to ask the user. Each +question must have an associated answer format.

+ +

To use an answer format, instantiate the appropriate answer format subclass and +attach it to a question step or form item. Incorporate the resulting step +into a task, and present the task with a task view controller.

+ +

An answer format is validated when its owning step is validated.

+ +

Some answer formats are constructed of other answer formats. When this is the +case, the answer format can override the method impliedAnswerFormat to return +the answer format that is implied. For example, a Boolean answer format +is presented in the same way as a single-choice answer format with the +choices Yes and No mapping to @(YES) and @(NO), respectively.

+
+ + + + + +
+ + + + +

Properties

+ +
+
+ +

  questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
@property (readonly) ORKQuestionType questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Validation

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– impliedAnswerFormat +

+ +
+
+ +
+ + +
+

Some answer formats are constructed of other answer formats. This method allows +a subclass to return a different answer format for use in defining the UI/UX for +the answer format type. For example, a Boolean answer format is presented in the +same way as a single-choice answer format with the choices Yes and No mapping to +@(YES) and @(NO), respectively, so its impliedAnswerFormat is an +ORKTextChoiceAnswerFormat with those options.

+
+ + + +
- (ORKAnswerFormat *)impliedAnswerFormat
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextField.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextField.html new file mode 100755 index 0000000..8b9b0f2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextField.html @@ -0,0 +1,124 @@ + + + + + + ORKAnswerTextField Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAnswerTextField Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromUITextField
Conforms toORKDefaultFont
Declared inORKAnswerTextField.h
ORKAnswerTextField.m
+ + + + +
+ +

Overview

+

Answer’s text field.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextView.html new file mode 100755 index 0000000..1b91851 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAnswerTextView.html @@ -0,0 +1,124 @@ + + + + + + ORKAnswerTextView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAnswerTextView Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromUITextView
Conforms toORKDefaultFont
Declared inORKAnswerTextView.h
ORKAnswerTextView.m
+ + + + +
+ +

Overview

+

The ORKAnswerTextView class represents the text view of the answer.

Note: The answer text view is used in the answer page and the form page.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioGenerator.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioGenerator.html new file mode 100755 index 0000000..363ede3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioGenerator.html @@ -0,0 +1,410 @@ + + + + + + ORKAudioGenerator Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioGenerator Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKAudioGenerator.h
ORKAudioGenerator.m
+ + + + +
+ +

Overview

+

The ORKAudioGenerator class represents an audio tone generator.

+
+ + + + + +
+ + + + + + +
+
+ +

– volumeInDecibels +

+ +
+
+ +
+ + +
+

Returns the peak audio volume being currently played, in decibels (dB).

+
+ + + +
- (double)volumeInDecibels
+ + + + + +
+

Return Value

+

The current audio volume in decibels.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAudioGenerator.h

+
+ + +
+
+
+ +

– volumeAmplitude +

+ +
+
+ +
+ + +
+

Returns the peak audio volume amplitude being currently played (from 0 to 1).

+
+ + + +
- (double)volumeAmplitude
+ + + + + +
+

Return Value

+

The current audio volume amplitude.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAudioGenerator.h

+
+ + +
+
+
+ +

– playSoundAtFrequency: +

+ +
+
+ +
+ + +
+

Plays a tone at a specific frequency in stereo.

+
+ + + +
- (void)playSoundAtFrequency:(double)frequency
+ + + +
+

Parameters

+ + + + + + + +
frequency

The audio frequency in hertz.

+
+ + + + + + + +
+

Discussion

+

The sound is a “pure” sinusoid tone.

+
+ + + + + + + +
+

Declared In

+

ORKAudioGenerator.h

+
+ + +
+
+
+ +

– playSoundAtFrequency:onChannel:fadeInDuration: +

+ +
+
+ +
+ + +
+

Plays a tone at a specific frequency on a specific channel, with a fade-in effect.

+
+ + + +
- (void)playSoundAtFrequency:(double)frequency onChannel:(ORKAudioChannel)channel fadeInDuration:(NSTimeInterval)duration
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
frequency

The audio frequency in hertz.

channel

The audio channel (left or right).

duration

The fade-in duration.

+
+ + + + + + + +
+

Discussion

+

The sound is a “pure” sinusoid tone. +The fade-in effect is applied linearly for the peak amplitude, from a 0 to 1 factor.

+
+ + + + + + + +
+

Declared In

+

ORKAudioGenerator.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops the audio being played.

+
+ + + +
- (void)stop
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAudioGenerator.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioLevelNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioLevelNavigationRule.html new file mode 100755 index 0000000..3746d5b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioLevelNavigationRule.html @@ -0,0 +1,335 @@ + + + + + + ORKAudioLevelNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioLevelNavigationRule Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepNavigationRule : NSObject
Declared inORKAudioLevelNavigationRule.h
ORKAudioLevelNavigationRule.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithAudioLevelStepIdentifier:destinationStepIdentifier:recordingSettings: +

+ +
+
+ +
+ + +
+

Returns an initialized direct-step navigation rule using the specified destination step identifier.

+
+ + + +
- (instancetype)initWithAudioLevelStepIdentifier:(NSString *)audioLevelStepIdentifier destinationStepIdentifier:(NSString *)destinationStepIdentifier recordingSettings:(NSDictionary *)recordingSettings
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
audioLevelStepIdentifier

The identifier of the step with the audio file to check.

destinationStepIdentifier

The identifier of the destination step if audio test passes.

recordingSettings

Use key AVNumberOfChannelsKey to sepcify the number of recording channels.

+
+ + + +
+

Return Value

+

A audio level step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAudioLevelNavigationRule.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new direct-step navigation rule initialized from data in a given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the step navigation rule.

+
+ + + +
+

Return Value

+

A new direct-step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAudioLevelNavigationRule.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– identifierForDestinationStepWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns the target step identifier.

+
+ + + +
- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating the destination step.

+
+ + + +
+

Return Value

+

The identifier of the destination step.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate the next step based on the passed task result. +The ORKNullStepIdentifier constant can be returned to indicate that the ongoing task should end +after the step navigation rule is triggered.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorder.html new file mode 100755 index 0000000..3e64f81 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorder.html @@ -0,0 +1,583 @@ + + + + + + ORKAudioRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKAudioRecorder.h
ORKAudioRecorder.m
+ + + + +
+ +

Overview

+

The ORKAudioRecorder class represents a recorder that uses the app’s +AVAudioSession object to record audio.

+ +

To ensure audio recording continues when a task enters the background, +add the audio tag to UIBackgroundModes in your app’s Info.plist file.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ defaultRecorderSettings +

+ +
+
+ +
+ + +
+

The default audio format settings.

+
+ + + +
+ (NSDictionary *)defaultRecorderSettings
+ + + + + + + + + +
+

Discussion

+

If no settings are specified, the audio configuration is +MPEG4 AAC, 2 channels, 16 bit, 44.1 kHz, AVAudioQualityMin.

+
+ + + + + + + +
+

Declared In

+

ORKAudioRecorder.h

+
+ + +
+
+
+ +

– initWithIdentifier:recorderSettings:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized audio recorder using the specified settings, step, and output directory.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier recorderSettings:(NSDictionary *)recorderSettings step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

recorderSettings

The settings for the recording session.

step

The step that requested this recorder.

outputDirectory

The directory in which the audio output should be stored.

+
+ + + +
+

Return Value

+

An initialized audio recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAudioRecorder.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  recorderSettings +

+ +
+
+ +
+ + +
+

Audio format settings

+
+ + + +
@property (nonatomic, copy, readonly) NSDictionary *recorderSettings
+ + + + + + + + + +
+

Discussion

+

Settings for the recording session. +Passed to AVAudioRecorder's-initWithURL:settings:error:` +For information on the settings available for an audio recorder, see “AV Foundation Audio Settings Constants”.

+
+ + + + + + + +
+

Declared In

+

ORKAudioRecorder.h

+
+ + +
+
+
+ +

  audioRecorder +

+ +
+
+ +
+ + +
+

Reference to the audio recorder being used.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) AVAudioRecorder *audioRecorder
+ + + + + + + + + +
+

Discussion

+

The value of this property is used in the audio task in order to display recorded volume in real time during the task.

+
+ + + + + + + +
+

Declared In

+

ORKAudioRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorderConfiguration.html new file mode 100755 index 0000000..7131af4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioRecorderConfiguration.html @@ -0,0 +1,521 @@ + + + + + + ORKAudioRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKAudioRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKAudioRecorderConfiguration class represents a configuration that records +audio data during an active step.

+ +

An ORKAudioRecorderConfiguration generates an ORKAudioRecorder object.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithIdentifier:recorderSettings: +

+ +
+
+ +
+ + +
+

Returns an initialized audio recorder configuration using the specified settings.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier recorderSettings:(NSDictionary *)recorderSettings
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier of the recorder configuration.

recorderSettings

The settings for the recording session.

+
+ + + +
+

Return Value

+

An initialized audio recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+ +

For information on the settings available for an audio recorder, see “AV Foundation Audio Settings Constants”.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new audio recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the audio recorder configuration.

+
+ + + +
+

Return Value

+

A new audio recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  recorderSettings +

+ +
+
+ +
+ + +
+

The audio format settings for the recorder.

+
+ + + +
@property (nonatomic, readonly, nullable) NSDictionary *recorderSettings
+ + + + + + + + + +
+

Discussion

+

Pass the settings for the recording session to the AVAudioRecorder method initWithURL:settings:error:. +For information on the settings available for an audio recorder, see “AV Foundation Audio Settings Constants” in +the AVFoundation documentation.

+ +

The results are returned as an ORKFileResult object, which points to an audio file.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStep.html new file mode 100755 index 0000000..dbf0407 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStep.html @@ -0,0 +1,265 @@ + + + + + + ORKAudioStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKAudioStep.h
ORKAudioStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStepViewController.html new file mode 100755 index 0000000..6a1ae15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKAudioStepViewController.html @@ -0,0 +1,519 @@ + + + + + + ORKAudioStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKAudioStepViewController.h
ORKAudioStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– recordersDidChange +

+ +
+
+ +
+ + +
+

Tells the view controller that the set of recorders changed.

+
+ + + +
- (void)recordersDidChange
+ + + + + + + + + +
+

Discussion

+

This method is usually called by the active step view controller in response +to start or resume.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– suspend +

+ +
+
+ +
+ + +
+

Suspends the active step.

+
+ + + +
- (void)suspend
+ + + + + + + + + +
+

Discussion

+

Call this method to suspend data recording and the step’s timer.

+ +

This method may called automatically when the app is suspended. +The view controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes the active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method when the step should be resumed. Calls to this method should +be paired with previous calls to suspend.

+ +

This method may be called automatically when the app is resumed. The view +controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

When the step is resumed, the UI should resume at the point where the user left off, +or, if that does not make sense for the particular step, to the most recent +suitable point.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– finish +

+ +
+
+ +
+ + +
+

Finishes the active step.

+
+ + + +
- (void)finish
+ + + + + + + + + +
+

Discussion

+

Call this method to finish the active step. If the active step is configured with +a timer, this method is called automatically when the timer expires.

+ +

Finishing the active step stops all data recording and stops any timers. In steps that have the +shouldContinueOnFinish property set, forward navigation to the next step +may ensue.

+ +

This method does nothing if the step has already finished.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBarGraphChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBarGraphChartView.html new file mode 100755 index 0000000..110062d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBarGraphChartView.html @@ -0,0 +1,193 @@ + + + + + + ORKBarGraphChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKBarGraphChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromORKGraphChartView : UIView
Declared inORKBarGraphChartView.h
ORKBarGraphChartView.m
+ + + + +
+ +

Overview

+

The ORKBarGraphChartView class presents the data provided by an object conforming to the +ORKValueStackGraphChartViewDataSource protocol as a bar graph.

+ +

By default, the primary plot is colored by the tintColor, and any additional plots are colored +using the referenceLineColor property. You can customize the plot colors by implementing the +-graphChartView:colorForPlotIndex: method in the data source.

+
+ + + + + +
+ + + + + + +
+
+ +

  dataSource +

+ +
+
+ +
+ + +
+

The data source responsible for providing the data required to populate the graph chart view.

+
+ + + +
@property (nonatomic, weak) id<ORKValueStackGraphChartViewDataSource> dataSource
+ + + + + + + + + +
+

Discussion

+

See the ORKValueStackGraphChartViewDataSource protocol.

+
+ + + + + + + +
+

Declared In

+

ORKBarGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanAnswerFormat.html new file mode 100755 index 0000000..5d240f8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanAnswerFormat.html @@ -0,0 +1,406 @@ + + + + + + ORKBooleanAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKBooleanAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKBooleanAnswerFormat class behaves the same as the ORKTextChoiceAnswerFormat class, +except that it is preconfigured to use only Yes and No answers.

+ +

The Boolean answer format produces an ORKBooleanQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithYesString:noString: +

+ +
+
+ +
+ + +
+

Returns an initialized Boolean answer format using the specified strings for Yes and No answers.

+
+ + + +
- (instancetype)initWithYesString:(NSString *)yes noString:(NSString *)no
+ + + +
+

Parameters

+ + + + + + + + + + + + +
yes

A string that describes the Yes answer.

no

A string that describes the No answer.

+
+ + + +
+

Return Value

+

An initialized Boolean answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  yes +

+ +
+
+ +
+ + +
+

The string to describe the Yes answer. (read-only)

+
+ + + +
@property (copy, readonly) NSString *yes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  no +

+ +
+
+ +
+ + +
+

The string to describe the No answer. (read-only)

+
+ + + +
@property (copy, readonly) NSString *no
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– impliedAnswerFormat +

+ +
+
+ +
+ + +
+

Some answer formats are constructed of other answer formats. This method allows +a subclass to return a different answer format for use in defining the UI/UX for +the answer format type. For example, a Boolean answer format is presented in the +same way as a single-choice answer format with the choices Yes and No mapping to +@(YES) and @(NO), respectively, so its impliedAnswerFormat is an +ORKTextChoiceAnswerFormat with those options.

+
+ + + +
- (ORKAnswerFormat *)impliedAnswerFormat
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanQuestionResult.html new file mode 100755 index 0000000..194c2ad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBooleanQuestionResult.html @@ -0,0 +1,190 @@ + + + + + + ORKBooleanQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKBooleanQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKBooleanQuestionResult class represents the answer to a Yes/No question.

+ +

A Boolean question result is produced by the task view controller when it presents a question or form +item with a Boolean answer format (that is, ORKBooleanAnswerFormat).

+ +

A Boolean question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  booleanAnswer +

+ +
+
+ +
+ + +
+

The answer, or nil if the user skipped the question.

+
+ + + +
@property (nonatomic, copy, nullable) NSNumber *booleanAnswer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBorderedButton.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBorderedButton.html new file mode 100755 index 0000000..4749752 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKBorderedButton.html @@ -0,0 +1,302 @@ + + + + + + ORKBorderedButton Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKBorderedButton Class Reference

+ + +
+ + + + + + + +
Inherits fromORKTextButton : UIButton
Declared inORKBorderedButton.h
ORKBorderedButton.m
+ + + + + + +
+ + + + + + +
+
+ +

  normalTintColor +

+ +
+
+ +
+ + +
+

The tint color of the button for UIControlStateNormal

+
+ + + +
@property (nonatomic) UIColor *normalTintColor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKBorderedButton.h

+
+ + +
+
+
+ +

  normalHighlightOrSelectTintColor +

+ +
+
+ +
+ + +
+

The tint color of the button for UIControlStateSelected or UIControlStateHighlighted

+
+ + + +
@property (nonatomic) UIColor *normalHighlightOrSelectTintColor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKBorderedButton.h

+
+ + +
+
+
+ +

  disableTintColor +

+ +
+
+ +
+ + +
+

The tint color of the button for UIControlStateDisabled

+
+ + + +
@property (nonatomic) UIColor *disableTintColor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKBorderedButton.h

+
+ + +
+
+
+ +

  fadeDelay +

+ +
+
+ +
+ + +
+

The delay in fading animation

+
+ + + +
@property (nonatomic, assign) NSTimeInterval fadeDelay
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKBorderedButton.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCaption1Label.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCaption1Label.html new file mode 100755 index 0000000..3db19f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCaption1Label.html @@ -0,0 +1,121 @@ + + + + + + ORKCaption1Label Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCaption1Label Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKCaption1Label.h
ORKCaption1Label.m
+ + + + +
+ +

Overview

+

Intro step’s first piece details text.

Note: Used as cell’s caption text: in ORKConsentDocumentCell and ORKFormItemCell

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKChoiceQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKChoiceQuestionResult.html new file mode 100755 index 0000000..8feb2ad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKChoiceQuestionResult.html @@ -0,0 +1,197 @@ + + + + + + ORKChoiceQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKChoiceQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKChoiceQuestionResult class represents the single or multiple choice +answers from a choice-based answer format.

+ +

For example, an ORKTextChoiceAnswerFormat or an ORKImageChoiceAnswerFormat +format produces an ORKChoiceQuestionResult object.

+ +

A choice question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  choiceAnswers +

+ +
+
+ +
+ + +
+

An array of selected values, from the value property of an ORKTextChoice or ORKImageChoice object. +In the case of a single choice, the array has exactly one entry.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray *choiceAnswers
+ + + + + + + + + +
+

Discussion

+

If the user skipped the question, the value of the corresponding array member is nil.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollectionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollectionResult.html new file mode 100755 index 0000000..2c48fbf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollectionResult.html @@ -0,0 +1,307 @@ + + + + + + ORKCollectionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCollectionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKCollectionResult.h
ORKCollectionResult.m
+ + + + +
+ +

Overview

+

The ORKCollectionResult class represents a result that contains an array of +child results.

+ +

ORKCollectionResult is the superclass of ORKTaskResult and ORKStepResult.

+ +

Note that object of this class are not instantiated directly by the ResearchKit framework.

+
+ + + + + +
+ + + + + + +
+
+ +

  results +

+ +
+
+ +
+ + +
+

An array of ORKResult objects that are the children of the result.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKResult*> *results
+ + + + + + + + + +
+

Discussion

+

For ORKTaskResult, the array contains ORKStepResult objects. +For ORKStepResult the array contains concrete result objects such as ORKFileResult +and ORKQuestionResult.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

– resultForIdentifier: +

+ +
+
+ +
+ + +
+

Looks up the child result containing an identifier that matches the specified identifier.

+
+ + + +
- (nullable ORKResult *)resultForIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The identifier of the step for which to search.

+
+ + + +
+

Return Value

+

The matching result, or nil if none was found.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

  firstResult +

+ +
+
+ +
+ + +
+

The first result.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) ORKResult *firstResult
+ + + + + + + + + +
+

Discussion

+

This is the first result, or nil if there are no results.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollector.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollector.html new file mode 100755 index 0000000..7287b11 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCollector.html @@ -0,0 +1,308 @@ + + + + + + ORKCollector Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCollector Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKCollector.h
ORKCollector.m
+ + + + +
+ +

Overview

+

Abstract class of data collector.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– serializedDataForObjects: +

+ +
+
+ +
+ + +
+

Serialization helper that produces serialized output. +Subclasses should implement to provide a default serialization for upload.

+
+ + + +
- (NSData *)serializedDataForObjects:(NSArray *)objects
+ + + + + +
+

Return Value

+

Serialized data object.

+
+ + + + + +
+

Discussion

+

@params objects The objects to be serialized.

+
+ + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

– serializableObjectsForObjects: +

+ +
+
+ +
+ + +
+

Serialization helper that produces objects suitable for serialization to JSON.

+
+ + + +
- (NSArray *)serializableObjectsForObjects:(NSArray *)objects
+ + + + + +
+

Return Value

+

Serializable dictionary objects.

+
+ + + + + +
+

Discussion

+

Subclasses should implement to provide a default JSON serialization for upload. +Called by serializedDataForObjects:.

+ +

@params objects The objects to be serialized.

+
+ + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

Identifier of this collector.

+
+ + + +
@property (copy, readonly) NSString *identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStep.html new file mode 100755 index 0000000..2e1278b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStep.html @@ -0,0 +1,181 @@ + + + + + + ORKCompletionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCompletionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKInstructionStep : ORKStep : NSObject
Declared inORKCompletionStep.h
ORKCompletionStep.m
+ + + + +
+ +

Overview

+

The ORKCompletionStep class is a subclass of ORKInstructionStep which behaves like +an instruction step, but includes animated imagery that thanks the user +for participating in the task.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStepViewController.html new file mode 100755 index 0000000..dcebd6b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCompletionStepViewController.html @@ -0,0 +1,234 @@ + + + + + + ORKCompletionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCompletionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKInstructionStepViewController : ORKStepViewController : UIViewController
Declared inORKCompletionStepViewController.h
ORKCompletionStepViewController.m
+ + + + +
+ +

Overview

+

An ORKCompletionStepViewController object is the step view controller for an +ORKCompletionStep object.

+ +

Typically, you don’t need to instantiate a completion step view controller directly. +Instead, add a completion step to a task, and present the task with a +task view controller. The task view controller instantiates the step +view controller for the completion step.

+
+ + + + + +
+ + + + + + +
+
+ +

  shouldShowContinueButton +

+ +
+
+ +
+ + +
+

Optional property to allow showing the “Done/Next” button rather than moving this button +to the rightBarButtonItem.

+
+ + + +
@property (nonatomic) BOOL shouldShowContinueButton
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCompletionStepViewController.h

+
+ + +
+
+
+ +

  checkmarkColor +

+ +
+
+ +
+ + +
+

Optional property to set the color of the checkmark. This allows the checkmark to use a different +color from the tintColor of the parent view.

+
+ + + +
@property (nonatomic, copy, nullable) UIColor *checkmarkColor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCompletionStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConfirmTextAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConfirmTextAnswerFormat.html new file mode 100755 index 0000000..23d1d50 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConfirmTextAnswerFormat.html @@ -0,0 +1,434 @@ + + + + + + ORKConfirmTextAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConfirmTextAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKTextAnswerFormat : ORKAnswerFormat : NSObject
Declared inORKAnswerFormat.m
ORKAnswerFormat_Private.h
+ + + + +
+ +

Overview

+

The ORKConfirmTextAnswerFormat class represents the answer format for questions that collect a text +response from the user and validates it with another text answer format.

+ +

An ORKConfirmTextAnswerFormat object produces an ORKBooleanQuestionResult object.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithMaximumLength: +

+ +
+
+ +
+ + +
+

Returns an initialized text answer format using the specified maximum string length.

+
+ + + +
- (instancetype)initWithMaximumLength:(NSInteger)maximumLength
+ + + +
+

Parameters

+ + + + + + + +
maximumLength

The maximum number of characters to accept. When the value of this parameter + is 0, there is no maximum.

+
+ + + +
+

Return Value

+

An initialized text answer format.

+
+ + + + + +
+

Discussion

+

This method is one of the designated initializers.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithValidationRegularExpression:invalidMessage: +

+ +
+
+ +
+ + +
+

Returns an initialized text answer format using the regular expression.

+
+ + + +
- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression invalidMessage:(NSString *)invalidMessage
+ + + +
+

Parameters

+ + + + + + + + + + + + +
validationRegularExpression

The regular expression used to validate the text.

invalidMessage

The text presented to the user when invalid input is received.

+
+ + + +
+

Return Value

+

An initialized validated text answer format.

+
+ + + + + +
+

Discussion

+

This method is one of the designated initializers.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithOriginalItemIdentifier:errorMessage: +

+ +
+
+ +
+ + +
+

Returns an initialized text answer format using the original item identifier.

+
+ + + +
- (instancetype)initWithOriginalItemIdentifier:(NSString *)originalItemIdentifier errorMessage:(NSString *)errorMessage
+ + + +
+

Parameters

+ + + + + + + + + + + + +
originalItemIdentifier

The form item identifier against which this answer item is validated.

errorMessage

The error message displayed if validation fails.

+
+ + + +
+

Return Value

+

An initialized confirm text answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat_Private.h

+
+ + +
+
+
+ +

  originalItemIdentifier +

+ +
+
+ +
+ + +
+

The identifier for the form item that the current item will be validated against.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *originalItemIdentifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat_Private.h

+
+ + +
+
+
+ +

  errorMessage +

+ +
+
+ +
+ + +
+

The error message displayed if validation fails.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *errorMessage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentDocument.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentDocument.html new file mode 100755 index 0000000..56c9c19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentDocument.html @@ -0,0 +1,690 @@ + + + + + + ORKConsentDocument Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentDocument Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKConsentDocument.h
ORKConsentDocument.m
+ + + + +
+ +

Overview

+

The ORKConsentDocument class represents the content of an informed consent +document, which is a document that’s used to obtain informed consent from participants +in a medical or other research study. The ResearchKit framework uses an ORKConsentDocument object +to provide content for visual consent steps (ORKVisualConsentStep) and for consent review steps (ORKConsentReviewStep).

+ +

The sections of an ORKConsentDocument object are instances of ORKConsentSection. +When an ORKConsentDocument object is attached to an visual consent step, these +sections provide the content for the visual consent screens, and for the +Learn More pages that are accessible from them. When attached to an consent review step, +the sections can provide the content for the consent document to +be reviewed.

+ +

If the consent document is simple, each section may be able to map to a visual consent screen. And in some cases, the formatting of the consent document may +be sufficiently simple that it can be presented using only section headers and +simple formatting. If your consent document uses simple formatting, you might be able to generate a document to sign by specifying the sections and the signatures. +In a case like this, you don’t need to provide a value for the htmlReviewContent property, +and when the consent review step is completed, the signatures can be +placed into a copy of the document and a PDF can be generated.

+ +

In more complex cases, the visual consent sections may bear little +relation to the formal consent document. In a situation like this, place the formal consent +document content in the htmlReviewContent property. Doing this overrides all content that would otherwise be generated from the consent +sections.

+ +

The document should be in the user’s language, and all the content of +the document should be appropriately localized.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithHTMLPDFWriter:consentSectionFormatter:consentSignatureFormatter: +

+ +
+
+ +
+ + +
+

Initializer with ORKHTMLPDFWriter parameter. Allows for injecting mock dependency for the +purposes of isolated unit testing.

+
+ + + +
- (instancetype)initWithHTMLPDFWriter:(ORKHTMLPDFWriter *)writer consentSectionFormatter:(ORKConsentSectionFormatter *)sectionFormatter consentSignatureFormatter:(ORKConsentSignatureFormatter *)signatureFormatter
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
writer

The instance of the ORKHTMLPDFWriter upon which the class depends.

sectionFormatter

An instance of ORKConsentSectionFormatter

signatureFormatter

An instance of ORKConsentSignatureFormatter

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+ +

– signatures +

+ +
+
+ +
+ + +
+

The set of signatures that are required or prepopulated in the document.

+
+ + + +
- (NSArray<ORKConsentSignature*> *)signatures
+ + + + + + + + + +
+

Discussion

+

To add a signature to the document after consent review, the signatures array +needs to be modified to incorporate the new signature content prior to PDF +generation. For more information, see [ORKConsentSignatureResult applyToDocument:].

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+ +

– addSignature: +

+ +
+
+ +
+ + +
+

Adds a signature to the array of signatures.

+
+ + + +
- (void)addSignature:(ORKConsentSignature *)signature
+ + + +
+

Parameters

+ + + + + + + +
signature

The signature object to add to the document.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+ +

– makePDFWithCompletionHandler: +

+ +
+
+ +
+ + +
+

Writes the document’s content into a PDF file.

+
+ + + +
- (void)makePDFWithCompletionHandler:(void ( ^ ) ( NSData *data , NSError *error ))handler
+ + + +
+

Parameters

+ + + + + + + +
handler

The handler block for generated PDF data. When successful, the returned + data represents a complete PDF document that represents the consent.

+
+ + + + + + + +
+

Discussion

+

The PDF is generated in a form suitable for printing. This is done asynchronously, +so the PDF data is returned through a completion block.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+
+ + + +

Properties

+ +
+
+ +

  title +

+ +
+
+ +
+ + +
+

The document’s title in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *title
+ + + + + + + + + +
+

Discussion

+

The title appears only in the generated PDF for review; it is not used in the +visual consent process.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+
+ + + +

Visual consent sections

+ +
+
+ +

  sections +

+ +
+
+ +
+ + +
+

The sections to be in printed in the PDF file and or presented in the +visual consent sequence.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKConsentSection*> *sections
+ + + + + + + + + +
+

Discussion

+

All sections appear in the animated process, except for those sections of the +type ORKConsentSectionTypeOnlyInDocument.

+ +

If the htmlReviewContent property is not set, this content is also used to +populate the document for review in the consent review step.

+ +

The PDF file contains all sections.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+
+ + + +

Signatures for consent review

+ +
+
+ +

  signaturePageTitle +

+ +
+
+ +
+ + +
+

The title to be rendered on the signature page of the generated PDF in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *signaturePageTitle
+ + + + + + + + + +
+

Discussion

+

The title is ignored for visual consent. The title is also ignored if you supply a value for the htmlReviewContent property.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+ +

  signaturePageContent +

+ +
+
+ +
+ + +
+

The content to be rendered below the title on the signature page of the generated PDF in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *signaturePageContent
+ + + + + + + + + +
+

Discussion

+

The content is ignored for visual consent. The content is also ignored if you supply a value for the htmlReviewContent property.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+
+ + + +

Alternative content provision

+ +
+
+ +

  htmlReviewContent +

+ +
+
+ +
+ + +
+

Override HTML content for review.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *htmlReviewContent
+ + + + + + + + + +
+

Discussion

+

Typically, the review content is generated from the values of the sections and signatures +properties.

+ +

When this property is set, the review content is reproduced exactly as provided in the property +in the consent review step, and the sections and signatures properties +are ignored.

+
+ + + + + + + +
+

Declared In

+

ORKConsentDocument.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStep.html new file mode 100755 index 0000000..9537a5c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStep.html @@ -0,0 +1,467 @@ + + + + + + ORKConsentReviewStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentReviewStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKConsentReviewStep.h
ORKConsentReviewStep.m
+ + + + +
+ +

Overview

+

The ORKConsentReviewStep class is used to represent the consent review process. +Typically, the consent review process consists of three main parts:

+ +
    +
  1. Consent document review. In this part, you display the consent document for review. Users +must explicitly agree to the consent document before they can proceed.

  2. +
  3. Name entry (optional). Users are asked to enter their first and last name. To +request name entry in your app, set the step’s signature property, and ensure that the signature’s +requiresName property is set to YES.

  4. +
  5. Signature (optional). Users are asked to draw their signature on the device screen. +To request signature entry in your app, set the step’s signature property, and ensure that the signature’s +requiresName property is set to YES.

  6. +
+ + +

The content for the consent document review comes from a consent document (ORKConsentDocument) +provided during initialization.

+ +

To use a consent review step, configure it and include it in a task. Then +present the task in a task view controller.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:signature:inDocument: +

+ +
+
+ +
+ + +
+

Returns an initialized consent review step using the specified identifier, signature, and consent document.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier signature:(ORKConsentSignature *)signature inDocument:(ORKConsentDocument *)consentDocument
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The identifier for the step.

signature

The signature to be collected, if any.

consentDocument

The consent document to be reviewed.

+
+ + + +
+

Return Value

+

An initialized consent review step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKConsentReviewStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Properties

+ +
+
+ +

  consentDocument +

+ +
+
+ +
+ + +
+

The consent document to be reviewed by the user during the consent review process. (read-only)

+
+ + + +
@property (nonatomic, strong, readonly) ORKConsentDocument *consentDocument
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentReviewStep.h

+
+ + +
+
+
+ +

  signature +

+ +
+
+ +
+ + +
+

The signature object from the document that should be collected. (read-only)

+
+ + + +
@property (nonatomic, strong, readonly, nullable) ORKConsentSignature *signature
+ + + + + + + + + +
+

Discussion

+

When the value of signature is nil, neither the name nor the finger scrawl are collected. +When the value of signature is not nil, the requiresName and requiresSignatureImage properties of +signature determine the screens that get presented.

+ +

The identifier of the signature is expected to match one of the signature objects in +the consent document.

+
+ + + + + + + +
+

Declared In

+

ORKConsentReviewStep.h

+
+ + +
+
+
+ +

  reasonForConsent +

+ +
+
+ +
+ + +
+

A user-visible description of the reason for agreeing to consent in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *reasonForConsent
+ + + + + + + + + +
+

Discussion

+

The reason for consent is presented in the confirmation dialog that users see when giving their consent.

+
+ + + + + + + +
+

Declared In

+

ORKConsentReviewStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStepViewController.html new file mode 100755 index 0000000..5d91e16 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentReviewStepViewController.html @@ -0,0 +1,268 @@ + + + + + + ORKConsentReviewStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentReviewStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKConsentReviewStepViewController.h
ORKConsentReviewStepViewController.m
+ + + + +
+ +

Overview

+

The ORKConsentReviewStepViewController class is a step view controller subclass +used to manage a consent review step (ORKConsentReviewStep).

+ +

You should not need to instantiate a consent review step view controller directly. Instead, include +a consent review step in a task, and present a task view controller for that +task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithConsentReviewStep:result: +

+ +
+
+ +
+ + +
+

Returns an initialized consent review step view controller using the specified review step and result.

+
+ + + +
- (instancetype)initWithConsentReviewStep:(ORKConsentReviewStep *)consentReviewStep result:(ORKConsentSignatureResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
consentReviewStep

The configured review step.

result

The initial or previous results for the review step, as appropriate.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKConsentReviewStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSection.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSection.html new file mode 100755 index 0000000..4e562c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSection.html @@ -0,0 +1,761 @@ + + + + + + ORKConsentSection Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSection Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKConsentSection.h
ORKConsentSection.m
+ + + + +
+ +

Overview

+

The ORKConsentSection class represents one section in a consent document. Each +ORKConsentSection object (apart from those of type ORKConsentSectionTypeOnlyInDocument) +corresponds to a page in a visual consent step, or a section in the document +reviewed in consent review step.

+ +

If you initialize a consent section with one of the defined section types, you get a prepopulated title, a default image, and animation (when appropriate). You can override these properties or you can use the ORKConsentSectionTypeCustom type to +avoid any prepopulation.

+ +

If you provide content for the ORKConsentSection object, be sure to use localized content.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithType: +

+ +
+
+ +
+ + +
+

Returns an initialized consent section using the specified type.

+
+ + + +
- (instancetype)initWithType:(ORKConsentSectionType)type
+ + + +
+

Parameters

+ + + + + + + +
type

The consent section type.

+
+ + + + + + + +
+

Discussion

+

This method populates the title and summary for all types except for +ORKConsentSectionTypeCustom and ORKConsentSectionTypeOnlyInDocument.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  type +

+ +
+
+ +
+ + +
+

The type of section. (read-only)

+
+ + + +
@property (nonatomic, readonly) ORKConsentSectionType type
+ + + + + + + + + +
+

Discussion

+

The value of this property indicates whether a predefined image, title, and animation are present.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  title +

+ +
+
+ +
+ + +
+

The title of the consent section in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *title
+ + + + + + + + + +
+

Discussion

+

The title is displayed as a scene title in the animated consent sequence and is also included in the PDF file, but it can be overridden by setting formalTitle. +The title is prefilled unless the type is ORKConsentSectionTypeCustom or ORKConsentSectionTypeOnlyInDocument.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  formalTitle +

+ +
+
+ +
+ + +
+

The formal title of the section in a localized string, for use in the legal document.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *formalTitle
+ + + + + + + + + +
+

Discussion

+

If the value of this property is nil, the value of title is used in the legal document instead.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  summary +

+ +
+
+ +
+ + +
+

A short summary of the content in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *summary
+ + + + + + + + + +
+

Discussion

+

The summary is displayed as description text in the animated consent sequence. +The summary should be limited in length, so that the consent can be reliably +displayed on smaller screens.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  content +

+ +
+
+ +
+ + +
+

The content of the section in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *content
+ + + + + + + + + +
+

Discussion

+

In a consent review step or in PDF file generation, the string is printed as the section’s +content. The string is also displayed as Learn More content in a visual consent step.

+ +

This property is never prepopulated based on the value of type. If both content and htmlContent are non-nil, the value of the htmlContent property is used.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  htmlContent +

+ +
+
+ +
+ + +
+

The HTML content used to override the content property if additional formatting is needed. The content should be localized.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *htmlContent
+ + + + + + + + + +
+

Discussion

+

In cases where plain text content is not sufficient to convey important details +during the consent process, you can provide HTML content in this property. When you do this, the htmlContent property takes precedence over the content property.

+ +

In a consent review step or in PDF file generation, the value of this property is printed as the section’s +content; in a visual consent step, the content is displayed as Learn More content.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  contentURL +

+ +
+
+ +
+ + +
+

The NSURL used to override the ‘htmlContent’ and ‘consent’ property if a document should be required.

+
+ + + +
@property (nonatomic, copy, nullable) NSURL *contentURL
+ + + + + + + + + +
+

Discussion

+

This property is used to display a document when required by an authortity.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  omitFromDocument +

+ +
+
+ +
+ + +
+

When set to YES, the section is omitted in a consent review step or in PDF file generation. This property is NO by default.

+
+ + + +
@property (nonatomic) BOOL omitFromDocument
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  customImage +

+ +
+
+ +
+ + +
+

A custom illustration for the consent.

+
+ + + +
@property (nonatomic, copy, nullable) UIImage *customImage
+ + + + + + + + + +
+

Discussion

+

The custom image can override the image associated with any of the predefined +section types for an ORKVisualConsentStep object. It is ignored for a consent review step and +for PDF generation.

+ +

The image is used in template rendering mode, and is tinted using the tint color.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  customLearnMoreButtonTitle +

+ +
+
+ +
+ + +
+

A custom Learn More button title in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *customLearnMoreButtonTitle
+ + + + + + + + + +
+

Discussion

+

The predefined section types have localized descriptive Learn More button +titles for a visual consent step. When this property is not nil, it overrides that +default text.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+ +

  customAnimationURL +

+ +
+
+ +
+ + +
+

A file URL that specifies a custom transition animation video.

+
+ + + +
@property (nonatomic, copy, nullable) NSURL *customAnimationURL
+ + + + + + + + + +
+

Discussion

+

Animations of the illustration between one screen and the next are provided +by default for transitions between consecutive section type codes. Custom +sections and out-of-order transitions may require custom animations.

+ +

The animation loaded from the file URL is played aspect fill in the +illustration area for forward transitions only. The video is rendered in +template mode, with white treated as if it were transparent.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStep.html new file mode 100755 index 0000000..c7e1e2f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStep.html @@ -0,0 +1,357 @@ + + + + + + ORKConsentSharingStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSharingStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionStep : ORKStep : NSObject
Declared inORKConsentSharingStep.h
ORKConsentSharingStep.m
+ + + + +
+ +

Overview

+

The ORKConsentSharingStep class represents a question step that includes prepopulated content that asks users about how much they’re willing to allow +data to be shared after collection.

+ +

To use the consent sharing step, include it in a task and present that task +with a task view controller. It’s easy to incorporate a consent sharing step into the review flow, because it provides default content for its title, text, and answer format.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:investigatorShortDescription:investigatorLongDescription:localizedLearnMoreHTMLContent: +

+ +
+
+ +
+ + +
+

Returns an initialized consent sharing step using the specified title, text, and answer format.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier investigatorShortDescription:(NSString *)investigatorShortDescription investigatorLongDescription:(NSString *)investigatorLongDescription localizedLearnMoreHTMLContent:(NSString *)localizedLearnMoreHTMLContent
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The identifier of the step.

investigatorShortDescription

A short description of the investigator in a localized string. For example, “Stanford Medicine” or “American Heart Association.”

investigatorLongDescription

An extended description of the investigator and partners in a localized string. For example, “Stanford and its partners.”

localizedLearnMoreHTMLContent

The HTML content to display when the user + taps the Learn More button.

+
+ + + +
+

Return Value

+

An initialized consent sharing step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKConsentSharingStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  localizedLearnMoreHTMLContent +

+ +
+
+ +
+ + +
+

Localized HTML content to present in the Learn More section for the step.

+
+ + + +
@property (nonatomic, copy) NSString *localizedLearnMoreHTMLContent
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSharingStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStepViewController.html new file mode 100755 index 0000000..ef6a9c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSharingStepViewController.html @@ -0,0 +1,205 @@ + + + + + + ORKConsentSharingStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSharingStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionStepViewController : ORKStepViewController : UIViewController
Declared inORKConsentSharingStepViewController.h
ORKConsentSharingStepViewController.m
+ + + + +
+ +

Overview

+

The ORKConsentSharingStepViewController class is a view controller subclass +used to manage a consent sharing step (ORKConsentSharingStep).

+ +

You should not need to instantiate a consent sharing step view controller directly. Instead, include +a consent sharing step in a task, and present a task view controller for that +task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignature.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignature.html new file mode 100755 index 0000000..6f078d5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignature.html @@ -0,0 +1,756 @@ + + + + + + ORKConsentSignature Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSignature Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKConsentSignature.h
ORKConsentSignature.m
+ + + + +
+ +

Overview

+

The ORKConsentSignature class represents a signature in as ORKConsentDocument object. +The signature can be that of an investigator, possibly prefilled with +an image, date, and first and last name; or you might need to collect the details of a signature.

+ +

Signatures can be collected in a consent review step (ORKConsentReviewStep). After a signature has +been obtained (which produces an ORKConsentSignatureResult object), the resulting signature +can be substituted into a copy of the document, and used when generating a PDF.

+ +

Alternatively, the details of a signature can be uploaded to a server +for PDF generation elsewhere or simply as a record of having obtained consent.

+ +

The signature object has no concept of a cryptographic signature – it is merely +a record of any input the user made during a consent review step. Also, an ORKConsentSignature object +does not verify or vouch for user identity.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ signatureForPersonWithTitle:dateFormatString:identifier:givenName:familyName:signatureImage:dateString: +

+ +
+
+ +
+ + +
+

Returns a fully populated signature.

+
+ + + +
+ (ORKConsentSignature *)signatureForPersonWithTitle:(NSString *)title dateFormatString:(NSString *)dateFormatString identifier:(NSString *)identifier givenName:(NSString *)givenName familyName:(NSString *)familyName signatureImage:(UIImage *)signatureImage dateString:(NSString *)signatureDate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
title

The title of the signatory.

dateFormatString

The format string to use when formatting the date of signature.

identifier

The identifier of the signature, unique within this document.

givenName

The given name of the signatory.

familyName

The family name of the signatory.

signatureImage

An image of the signature.

signatureDate

The date on which the signature was obtained, represented as a string.

+
+ + + + + + + +
+

Discussion

+

Use this factory method when you need to prepopulate the investigator’s signature in a generated consent document.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

+ signatureForPersonWithTitle:dateFormatString:identifier: +

+ +
+
+ +
+ + +
+

Returns a signature to be collected.

+
+ + + +
+ (ORKConsentSignature *)signatureForPersonWithTitle:(NSString *)title dateFormatString:(NSString *)dateFormatString identifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
title

The title of the signatory.

dateFormatString

The format string to use when formatting the date of signature.

identifier

The identifier of the signature, unique within this document.

+
+ + + + + + + +
+

Discussion

+

Use this factory method when representing a request to collect a signature for a consent review step.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+
+ + + +

Consent review configuration

+ +
+
+ +

  requiresName +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the user needs to enter their name during consent review.

+
+ + + +
@property (nonatomic, assign) BOOL requiresName
+ + + + + + + + + +
+

Discussion

+

The default value of this property is YES. In a consent review step, the name entry screen is not displayed when the value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  requiresSignatureImage +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the user needs to draw a signature during consent review.

+
+ + + +
@property (nonatomic, assign) BOOL requiresSignatureImage
+ + + + + + + + + +
+

Discussion

+

The default value of this property is YES. In a consent review step, the signature entry +screen is not shown when this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+
+ + + +

Identifying signatories

+ +
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

The identifier for this signature.

+
+ + + +
@property (nonatomic, copy) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier should be unique in the document. It can be used to find or +replace a specific signature in an ORKConsentDocument object. The identifier is also reproduced in +the ORKConsentSignatureResult object produced by an ORKConsentReviewStep object.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+
+ + + +

Personal information.

+ +
+
+ +

  title +

+ +
+
+ +
+ + +
+

The title of the signatory.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *title
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  givenName +

+ +
+
+ +
+ + +
+

The given name (first name in Western languages)

+
+ + + +
@property (nonatomic, copy, nullable) NSString *givenName
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  familyName +

+ +
+
+ +
+ + +
+

The family name (last name in Western languages)

+
+ + + +
@property (nonatomic, copy, nullable) NSString *familyName
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  signatureImage +

+ +
+
+ +
+ + +
+

The image of the signature, if any.

+
+ + + +
@property (nonatomic, copy, nullable) UIImage *signatureImage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  signatureDate +

+ +
+
+ +
+ + +
+

The date associated with the signature.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *signatureDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+ +

  signatureDateFormatString +

+ +
+
+ +
+ + +
+

The date format string to be used when producing a date string for the PDF +or consent review.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *signatureDateFormatString
+ + + + + + + + + +
+

Discussion

+

For example, @“yyyy-MM-dd ‘at’ HH:mm”. When the value of this property is nil, +the current date and time for the current locale is used.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignature.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignatureResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignatureResult.html new file mode 100755 index 0000000..f2dfdbd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKConsentSignatureResult.html @@ -0,0 +1,325 @@ + + + + + + ORKConsentSignatureResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSignatureResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKConsentSignatureResult.h
ORKConsentSignatureResult.m
+ + + + +
+ +

Overview

+

The ORKConsentSignatureResult class represents a signature obtained during +a consent review step (ORKConsentReviewStep). The consent signature result is usually found as a child result of the +ORKStepResult object for the consent review step.

+ +

You can apply the result to a document to facilitate the generation of a +PDF including the signature, or for presentation in a follow-on +consent review.

+ +

A consent signature result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– applyToDocument: +

+ +
+
+ +
+ + +
+

Applies the signature to the consent document.

+
+ + + +
- (void)applyToDocument:(ORKConsentDocument *)document
+ + + +
+

Parameters

+ + + + + + + +
document

The document to which to apply the signature.

+
+ + + + + + + +
+

Discussion

+

This method uses the identifier to look up the matching signature placeholder +in the consent document and replaces it with this signature. It may throw an exception if +the document does not contain a signature with a matching identifier.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignatureResult.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  signature +

+ +
+
+ +
+ + +
+

A copy of the signature obtained.

+
+ + + +
@property (nonatomic, copy, nullable) ORKConsentSignature *signature
+ + + + + + + + + +
+

Discussion

+

The signature is a copy of the signature property in the originating +ORKConsentReviewStep object, but also includes any name or signature image collected during +the consent review step.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignatureResult.h

+
+ + +
+
+
+ +

  consented +

+ +
+
+ +
+ + +
+

A boolean value indicating whether the participant consented.

+
+ + + +
@property (nonatomic, assign) BOOL consented
+ + + + + + + + + +
+

Discussion

+

YES if the user confirmed consent to the contents of the consent review. Note +that the signature could still be invalid if the name or signature image is +empty; this indicates only that the user gave a positive acknowledgement of the +document.

+
+ + + + + + + +
+

Declared In

+

ORKConsentSignatureResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKContinuousScaleAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKContinuousScaleAnswerFormat.html new file mode 100755 index 0000000..d9b1fde --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKContinuousScaleAnswerFormat.html @@ -0,0 +1,1112 @@ + + + + + + ORKContinuousScaleAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKContinuousScaleAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKContinuousScaleAnswerFormat class represents an answer format that lets participants +select a value on a continuous scale.

+ +

The continuous scale answer format produces an ORKScaleQuestionResult object that has a +real-number value.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:maximumFractionDigits:vertical:maximumValueDescription:minimumValueDescription: +

+ +
+
+ +
+ + +
+

Returns an initialized continuous scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(double)maximumValue minimumValue:(double)minimumValue defaultValue:(double)defaultValue maximumFractionDigits:(NSInteger)maximumFractionDigits vertical:(BOOL)vertical maximumValueDescription:(nullable NSString *)maximumValueDescription minimumValueDescription:(nullable NSString *)minimumValueDescription
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, + the slider is displayed without a default value.

maximumFractionDigits

The maximum number of fractional digits to display.

vertical

Pass YES to use a vertical scale; for the default horizontal + scale, pass NO.

maximumValueDescription

A localized label to describe the maximum value of the scale. + For none, pass nil.

minimumValueDescription

A localized label to describe the minimum value of the scale. + For none, pass nil.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:maximumFractionDigits:vertical: +

+ +
+
+ +
+ + +
+

Returns an initialized continuous scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(double)maximumValue minimumValue:(double)minimumValue defaultValue:(double)defaultValue maximumFractionDigits:(NSInteger)maximumFractionDigits vertical:(BOOL)vertical
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, the + slider is displayed without a default value.

maximumFractionDigits

The maximum number of fractional digits to display.

vertical

Pass YES to use a vertical scale; for the default horizontal scale, + pass NO.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:maximumFractionDigits: +

+ +
+
+ +
+ + +
+

Returns an initialized horizontal continous scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(double)maximumValue minimumValue:(double)minimumValue defaultValue:(double)defaultValue maximumFractionDigits:(NSInteger)maximumFractionDigits
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, the + slider is displayed without a default value.

maximumFractionDigits

The maximum number of fractional digits to display.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximum +

+ +
+
+ +
+ + +
+

The upper bound of the scale. (read-only)

+
+ + + +
@property (readonly) double maximum
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimum +

+ +
+
+ +
+ + +
+

The lower bound of the scale. (read-only)

+
+ + + +
@property (readonly) double minimum
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultValue +

+ +
+
+ +
+ + +
+

The default value for the slider. (read-only)

+
+ + + +
@property (readonly) double defaultValue
+ + + + + + + + + +
+

Discussion

+

If the value of this property is less than minimum or greater than maximum, the slider has no +default value.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumFractionDigits +

+ +
+
+ +
+ + +
+

The maximum number of fractional digits to display. (read-only)

+
+ + + +
@property (readonly) NSInteger maximumFractionDigits
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  vertical +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the scale is oriented vertically. (read-only)

+
+ + + +
@property (readonly, getter=isVertical) BOOL vertical
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  numberStyle +

+ +
+
+ +
+ + +
+

A formatting style applied to the minimum, maximum, and slider values.

+
+ + + +
@property ORKNumberFormattingStyle numberStyle
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  numberFormatter +

+ +
+
+ +
+ + +
+

A number formatter applied to the minimum, maximum, and slider values. Can be overridden by +subclasses.

+
+ + + +
@property (readonly) NSNumberFormatter *numberFormatter
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumValueDescription +

+ +
+
+ +
+ + +
+

A localized label to describe the maximum value of the scale. (read-only)

+
+ + + +
@property (readonly, nullable) NSString *maximumValueDescription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumValueDescription +

+ +
+
+ +
+ + +
+

A localized label to describe the minimum value of the scale. (read-only)

+
+ + + +
@property (readonly, nullable) NSString *minimumValueDescription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumImage +

+ +
+
+ +
+ + +
+

An image for the upper bound of the slider.

+
+ + + +
@property (strong, nullable) UIImage *maximumImage
+ + + + + + + + + +
+

Discussion

+

The recommended image size is 30 x 30 points. The maximum range label will not be visible.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumImage +

+ +
+
+ +
+ + +
+

An image for the lower bound of the slider.

+
+ + + +
@property (strong, nullable) UIImage *minimumImage
+ + + + + + + + + +
+

Discussion

+

The recommended image size is 30 x 30 points. The minimum range label will not be visible.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientColors +

+ +
+
+ +
+ + +
+

The colors to use when drawing a color gradient above the slider. Colors are drawn such that +lower indexes correspond to the minimum side of the scale, while colors at higher indexes in +the array corresond to the maximum side of the scale.

+
+ + + +
@property (copy, nullable) NSArray<UIColor*> *gradientColors
+ + + + + + + + + +
+

Discussion

+

Setting this value to nil results in no gradient being drawn. Defaults to nil.

+ +

An example usage would set an array of red and green to visually indicate a scale from bad to good.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientLocations +

+ +
+
+ +
+ + +
+

Indicates the position of gradient stops for the colors specified in gradientColors. +Gradient stops are specified as values between 0 and 1. The values must be monotonically +increasing.

+
+ + + +
@property (copy, nullable) NSArray<NSNumber*> *gradientLocations
+ + + + + + + + + +
+

Discussion

+

If nil, the stops are spread uniformly across the range. Defaults to nil.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownLabel.html new file mode 100755 index 0000000..9e82f85 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKCountdownLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCountdownLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKCountdownLabel.h
ORKCountdownLabel.m
+ + + + +
+ +

Overview

+

Coundown label in active steps

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStep.html new file mode 100755 index 0000000..49f2952 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStep.html @@ -0,0 +1,281 @@ + + + + + + ORKCountdownStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCountdownStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKCountdownStep.h
ORKCountdownStep.m
+ + + + +
+ +

Overview

+

The ORKCountdownStep class represents a step that displays a label and a +countdown for a time equal to its duration.

+ +

To use the countdown step, set the duration property, incorporate it into a +task, and present the task with a task view controller.

+ +

The countdown step is used in most of ResearchKit’s predefined active tasks.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStepViewController.html new file mode 100755 index 0000000..d0aabe5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKCountdownStepViewController.html @@ -0,0 +1,260 @@ + + + + + + ORKCountdownStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKCountdownStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKCountdownStepViewController.h
ORKCountdownStepViewController.m
+ + + + +
+ +

Overview

+

The ORKCountdownStepViewController class represents the step view controller that corresponds to an ORKCountdownStep.

+ +

It is not usually necessary to instantiate this view controller directly. +Instead, add a countdown step to a task, and present the task in a task +view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setStep: +

+ +
+
+ +
+ + +
+

The step presented by the step view controller.

+
+ + + +
- (void)setStep:(ORKStep *)step
+ + + + + + + + + +
+

Discussion

+

If you use a storyboard to initialize the step view controller, initWithStep: isn’t called, +so you need to set the step property directly before the step view controller is presented.

+ +

Setting the value of step after the controller has been presented is an error that +generates an exception. +Modifying the value of step after the controller has been presented is an error that +has undefined results.

+ +

Subclasses that override the setter of this property must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionManager.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionManager.html new file mode 100755 index 0000000..7239758 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionManager.html @@ -0,0 +1,676 @@ + + + + + + ORKDataCollectionManager Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataCollectionManager Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKDataCollectionManager.h
ORKDataCollectionManager.m
+ + + + +
+ +

Overview

+

The data collection manager is used to collect HealthKit data and CoreMotion data.

+ +

It uses collectors to track data types to be collected. +Anchors are used to track progress of each types of data to avoid duplications. +Collected data samples are returned in the delegation methods, return YES to confirm the samples has been accepted.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithPersistenceDirectoryURL: +

+ +
+
+ +
+ + +
+

Initiate the manager with a persistence directory. +The directory is used to store the configurations and progress of the collectors.

+
+ + + +
- (instancetype)initWithPersistenceDirectoryURL:(NSURL *)directoryURL
+ + + +
+

Parameters

+ + + + + + + +
directoryURL

URL path for the directory.

+
+ + + +
+

Return Value

+

Initiated ORKDataCollectionManager instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

  collectors +

+ +
+
+ +
+ + +
+

An array of collectors.

+
+ + + +
@property (copy, readonly) NSArray<ORKCollector*> *collectors
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

Implement the delegate to receive collected data objects.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKDataCollectionManagerDelegate> delegate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– addHealthCollectorWithSampleType:unit:startDate:error: +

+ +
+
+ +
+ + +
+

Add a collector for HealthKit quantity and category samples.

+
+ + + +
- (ORKHealthCollector *)addHealthCollectorWithSampleType:(HKSampleType *)sampleType unit:(HKUnit *)unit startDate:(NSDate *)startDate error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
sampleType

HealthKit sample type.

unit

HealthKit unit into which data should be collected.

startDate

Samples should be collected starting at this date.

error

Any error detected during this operation.

+
+ + + +
+

Return Value

+

Initiated health collector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– addHealthCorrelationCollectorWithCorrelationType:sampleTypes:units:startDate:error: +

+ +
+
+ +
+ + +
+

Add a collector for HealthKit correlations.

+
+ + + +
- (ORKHealthCorrelationCollector *)addHealthCorrelationCollectorWithCorrelationType:(HKCorrelationType *)correlationType sampleTypes:(NSArray<HKSampleType*> *)sampleTypes units:(NSArray<HKUnit*> *)units startDate:(NSDate *)startDate error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
correlationType

HealthKit correlation type.

sampleTypes

Array of HKSampleType expected in the correlation.

units

Array of HKUnit to use when serializing the samples collected (should be same size as sampleTypes).

startDate

Samples should be collected starting at this date.

error

Any error detected during this operation.

+
+ + + +
+

Return Value

+

Initiated health correlation collector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– addMotionActivityCollectorWithStartDate:error: +

+ +
+
+ +
+ + +
+

Add a collector for motion activity.

+
+ + + +
- (ORKMotionActivityCollector *)addMotionActivityCollectorWithStartDate:(NSDate *)startDate error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
startDate

When data collection should start.

error

Error during this operation.

+
+ + + +
+

Return Value

+

Initiated motion activity collector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– removeCollector:error: +

+ +
+
+ +
+ + +
+

Remove a collector.

+
+ + + +
- (BOOL)removeCollector:(ORKCollector *)collector error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The collector to be removed.

error

Error during this operation.

+
+ + + +
+

Return Value

+

If this operation is successful.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– startCollection +

+ +
+
+ +
+ + +
+

Start data collection. +This method triggers running all the RKCollector collections associated with the present manager. +When the collection is completed, delegate recieves a method call dataCollectionManagerDidCompleteCollection:.

+
+ + + +
- (void)startCollection
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  lastCollectionDate +

+ +
+
+ +
+ + +
+

Last collection date.

+
+ + + +
@property (nonatomic, strong) NSDate *lastCollectionDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionTests.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionTests.html new file mode 100755 index 0000000..d9523d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataCollectionTests.html @@ -0,0 +1,449 @@ + + + + + + ORKDataCollectionTests Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataCollectionTests Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromXCTestCase
Conforms toORKDataCollectionManagerDelegate
Declared inORKDataCollectionTests.m
+ + + + + + +
+ + + + + + +
+
+ +

– healthCollector:didCollectSamples: +

+ +
+
+ +
+ + +
+

Method for delivering the collected health data samples.

+
+ + + +
- (BOOL)healthCollector:(ORKHealthCollector *)collector didCollectSamples:(NSArray<HKSample*> *)samples
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

samples

Collected health data samples.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– healthCorrelationCollector:didCollectCorrelations: +

+ +
+
+ +
+ + +
+

Method for delivering the collected health correlations.

+
+ + + +
- (BOOL)healthCorrelationCollector:(ORKHealthCorrelationCollector *)collector didCollectCorrelations:(NSArray<HKCorrelation*> *)correlations
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

correlations

Collected health correlation samples.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– motionActivityCollector:didCollectMotionActivities: +

+ +
+
+ +
+ + +
+

Method for delivering the collected motion activities.

+
+ + + +
- (BOOL)motionActivityCollector:(ORKMotionActivityCollector *)collector didCollectMotionActivities:(NSArray<CMMotionActivity*> *)motionActivities
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

motionActivities

Collected motion activities.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– dataCollectionManagerDidCompleteCollection: +

+ +
+
+ +
+ + +
+

Indicating the collection is completed for all the collectors.

+
+ + + +
- (void)dataCollectionManagerDidCompleteCollection:(ORKDataCollectionManager *)manager
+ + + +
+

Parameters

+ + + + + + + +
manager

The data collection manager.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– collector:didDetectError: +

+ +
+
+ +
+ + +
+

Method for reporting the deteted error during collection.

+
+ + + +
- (void)collector:(ORKCollector *)collector didDetectError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

error

The error object.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLogger.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLogger.html new file mode 100755 index 0000000..dc72ebb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLogger.html @@ -0,0 +1,1433 @@ + + + + + + ORKDataLogger Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLogger Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKDataLogger.h
ORKDataLogger.m
+ + + + +
+ +

Overview

+

The ORKDataLogger class is an internal component used by some ORKRecorder +subclasses for writing data to disk during tasks. An ORKDataLogger object manages one log as a set of files in a directory.

+ +

The current log file is at directory/logName. +Historic log files are at directory/logName-(timestamp)-(count) +where timestamp is of the form YYYYMMddHHmmss (Zulu) and indicates the time +the log finished (that is, was rolled over). If more than one rollover occurs within +one second, additional log files may be created with increasing count.

+ +

The user is responsible for managing the historic log files, but the ORKDataLogger class +provides tools for enumerating them (in sorted order).

+ +

The data logger contains a concept of whether a file has been uploaded, which +is tracked using file attributes. This feature can facilitate a workflow in which +log files are archived and queued for upload before actually sending them to +a server. When archived and ready for upload, the files could be marked uploaded +by the ORKDataLogger. When the upload is complete and the data has been handed +off downstream, the files can then be deleted. If the upload fails, the uploaded +files can have that flag cleared, to indicate that they should be included +in the next archiving attempt.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ JSONDataLoggerWithDirectory:logName:delegate: +

+ +
+
+ +
+ + +
+

Returns a data logger with an ORKJSONLogFormatter.

+
+ + + +
+ (ORKDataLogger *)JSONDataLoggerWithDirectory:(NSURL *)url logName:(NSString *)logName delegate:(id<ORKDataLoggerDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
url

The URL of the directory in which to place log files.

logName

The prefix on the log file name in an ASCII string. Note that the string must not contain the hyphen character (“-”), because a hyphen is used as a separator in the log naming scheme.

delegate

The initial delegate. May be nil.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– initWithDirectory:logName:formatter:delegate: +

+ +
+
+ +
+ + +
+

Returns an initialized data logger using the specified URL, log name, formatter, and delegate.

+
+ + + +
- (instancetype)initWithDirectory:(NSURL *)url logName:(NSString *)logName formatter:(ORKLogFormatter *)formatter delegate:(id<ORKDataLoggerDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
url

The URL of the directory in which to place log files

logName

The prefix on the log file name in an ASCII string. Note that +the string must not contain the hyphen character (“-”), because a hyphen is used as a separator in the log naming scheme.

formatter

The type of formatter to use for the log, such as ORKJSONLogFormatter.

delegate

The initial delegate. May be nil.

+
+ + + +
+

Return Value

+

An initialized data logger.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– finishCurrentLog +

+ +
+
+ +
+ + +
+

Forces a roll-over now.

+
+ + + +
- (void)finishCurrentLog
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– currentLogFileURL +

+ +
+
+ +
+ + +
+

The current log file’s location.

+
+ + + +
- (NSURL *)currentLogFileURL
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– fileHandle +

+ +
+
+ +
+ + +
+

The file handle to which to write

+
+ + + +
- (NSFileHandle *)fileHandle
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– enumerateLogs:error: +

+ +
+
+ +
+ + +
+

Enumerates the URLs of completed log files, sorted to put the oldest first.

+
+ + + +
- (BOOL)enumerateLogs:(void ( ^ ) ( NSURL *logFileUrl , BOOL *stop ))block error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
block

The block to call during enumeration.

error

Any error detected during the enumeration.

+
+ + + +
+

Return Value

+

YES if the enumeration was successful; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Takes a snapshot of the current directory’s relevant files, sorts them, +and enumerates them. Errors can occur if changes are being made to the filesystem other +than through this object.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– enumerateLogsNeedingUpload:error: +

+ +
+
+ +
+ + +
+

Enumerates the URLs of completed log files not yet marked uploaded, +sorted to put the oldest first.

+
+ + + +
- (BOOL)enumerateLogsNeedingUpload:(void ( ^ ) ( NSURL *logFileUrl , BOOL *stop ))block error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
block

The block to call during enumeration.

error

Any error detected during the enumeration.

+
+ + + +
+

Return Value

+

YES if the enumeration was successful; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method takes a snapshot of the current directory’s completed nonuploaded log files, sorts them, +and then enumerates them. Errors can occur if changes are being made to the filesystem other +than through this object.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– enumerateLogsAlreadyUploaded:error: +

+ +
+
+ +
+ + +
+

Enumerates the URLs of completed log files not already marked uploaded, +sorted to put the oldest first.

+
+ + + +
- (BOOL)enumerateLogsAlreadyUploaded:(void ( ^ ) ( NSURL *logFileUrl , BOOL *stop ))block error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
block

The block to call during enumeration.

error

Any error detected during the enumeration.

+
+ + + +
+

Return Value

+

YES if the enumeration was successful; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Takes a snapshot of the current directory’s completed uploaded log files, sorts them, +and then enumerates them. Errors can occur if changes are being made to the filesystem other +than through this object.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– append:error: +

+ +
+
+ +
+ + +
+

Appends an object to the log file, which is formatted with logFormatter.

+
+ + + +
- (BOOL)append:(id)object error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
object

Should be an object of a class that is accepted by the logFormatter.

error

Error output, if the append fails.

+
+ + + +
+

Return Value

+

YES if appending succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

The default log formatter expects NSData; call canAcceptLogObjectOfClass: on logFormatter to determine if it will accept this object.

+ +

Note that the current log file is created and opened lazily when a request to +log data is made. If an attempt is made to log data and there is no access due +to file protection, the log is immediately rolled over and a new file created.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– appendObjects:error: +

+ +
+
+ +
+ + +
+

Appends multiple objects to the log file.

+
+ + + +
- (BOOL)appendObjects:(NSArray *)objects error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
objects

An array of objects of a class that is accepted by the logFormatter.

error

Error output, if the append fails.

+
+ + + +
+

Return Value

+

YES if appending succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method formats and appends all the objects at once. Using this method may have efficiency +and atomicity gains for error handling, compared to making multiple calls to append:error.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– markFileUploaded:atURL:error: +

+ +
+
+ +
+ + +
+

Marks or unmarks a file as uploaded.

+
+ + + +
- (BOOL)markFileUploaded:(BOOL)uploaded atURL:(NSURL *)url error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
uploaded

A Boolean value that indicates whether to mark the file uploaded or not uploaded.

url

The URL to mark.

error

The error that occurred, if the operation fails.

+
+ + + +
+

Return Value

+

YES if adding or removing the attribute succeeded; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method uses an extended attribute on the filesystem to mark a file as uploaded. +This is intended for book-keeping use only and to track which files have already +been attached to a pending upload. When the upload is sufficiently complete, +the file should be removed.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– removeUploadedFiles:withError: +

+ +
+
+ +
+ + +
+

Removes files if they are marked uploaded.

+
+ + + +
- (BOOL)removeUploadedFiles:(NSArray<NSURL*> *)fileURLs withError:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileURLs

The array of files that should be removed.

error

The error that occurred, if the operation fails.

+
+ + + +
+

Return Value

+

YES if removing the files succeeded; otherwise, NO.

+
+ + + + + +
+

Discussion

+

If a file is in the list, but is no longer marked uploaded, this method does not remove the file. This workflow lets you unmark files selectively if they could not be added +to the archive, and later call removeUploadedFiles:withError: to remove only +the files that are still marked uploaded.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– removeAllFilesWithError: +

+ +
+
+ +
+ + +
+

Removes all files managed by this logger (files that have the logName prefix).

+
+ + + +
- (BOOL)removeAllFilesWithError:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + +
error

The error that occurred, if operation fails.

+
+ + + +
+

Return Value

+

YES if removing the files succeeded.; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– isFileUploadedAtURL: +

+ +
+
+ +
+ + +
+

Checks whether a file has been marked as uploaded.

+
+ + + +
- (BOOL)isFileUploadedAtURL:(NSURL *)url
+ + + +
+

Parameters

+ + + + + + + +
url

The URL to check.

+
+ + + +
+

Return Value

+

YES if the uploaded attribute has been set on the file and the file exists; otherwise, + NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate to be notified when file sizes change or the log rolls over.

+
+ + + +
@property (weak, nullable) id<ORKDataLoggerDelegate> delegate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  logFormatter +

+ +
+
+ +
+ + +
+

The log formatter being used.

+
+ + + +
@property (strong, readonly) ORKLogFormatter *logFormatter
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  maximumCurrentLogFileSize +

+ +
+
+ +
+ + +
+

The maximum current log file size.

+
+ + + +
@property size_t maximumCurrentLogFileSize
+ + + + + + + + + +
+

Discussion

+

When the current log reaches this size, it is automatically rolled over.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  maximumCurrentLogFileLifetime +

+ +
+
+ +
+ + +
+

The maximum current log file lifetime.

+
+ + + +
@property NSTimeInterval maximumCurrentLogFileLifetime
+ + + + + + + + + +
+

Discussion

+

When the current log file has been active this long, it is rolled over.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  pendingBytes +

+ +
+
+ +
+ + +
+

The number of bytes of log data that are not marked uploaded, excluding the current file. This value is lazily updated.

+
+ + + +
@property unsigned long long pendingBytes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  uploadedBytes +

+ +
+
+ +
+ + +
+

The number of bytes of log data that are marked uploaded. This value is lazily updated.

+
+ + + +
@property unsigned long long uploadedBytes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  fileProtectionMode +

+ +
+
+ +
+ + +
+

The file protection mode to use for newly created files.

+
+ + + +
@property (assign) ORKFileProtectionMode fileProtectionMode
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  logName +

+ +
+
+ +
+ + +
+

The prefix on the log file names.

+
+ + + +
@property (copy, readonly) NSString *logName
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManager.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManager.html new file mode 100755 index 0000000..08628c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManager.html @@ -0,0 +1,1159 @@ + + + + + + ORKDataLoggerManager Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerManager Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKDataLoggerDelegate
Declared inORKDataLogger.h
ORKDataLogger.m
+ + + + +
+ +

Overview

+

The ORKDataLoggerManager class represents a manager for multiple ORKDataLogger instances, +which tracks the total size of log files produced and can notify its delegate +when file sizes reach configurable thresholds.

+ +

The ORKDataLoggerManager class is an internal component used by some ORKRecorder +subclasses for writing data to disk during tasks.

+ +

This manager can be used to organize the ORKDataLogger logs in a directory, +and keep track of the total number of bytes stored on disk by each logger. The +delegate can be informed if either the number of bytes pending upload, or the total +number of bytes, exceeds configurable thresholds.

+ +

The configuration of the loggers and their thresholds is persisted in a +configuration file in the log directory.

+ +

If the number of bytes pending upload exceeds the threshold, the natural action is to +upload them. A block-based enumeration is provided for enumerating all the logs +pending upload. Use enumerateLogsNeedingUpload:error:, and when a log has been +processed for upload, use the logger to mark it uploaded.

+ +

When the upload succeeds (or at least is successfully queued), the uploaded files +can be removed across all the loggers by calling removeUploadedFiles:error:

+ +

If the total number of bytes exceeds the threshold, the natural action is to remove log +files that have been marked uploaded, and then remove old log files until the +threshold is no longer exceeded. You can do this by calling removeOldAndUploadedLogsToThreshold:error:

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithDirectory:delegate: +

+ +
+
+ +
+ + +
+

Returns an initialized data logger manager using the specified directory and delegate.

+
+ + + +
- (instancetype)initWithDirectory:(NSURL *)directory delegate:(id<ORKDataLoggerManagerDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + +
directory

The file URL of the directory where the data loggers should coexist.

delegate

The delegate to receive notifications.

+
+ + + +
+

Return Value

+

An initialized data logger manager.

+
+ + + + + +
+

Discussion

+

Designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– addJSONDataLoggerForLogName: +

+ +
+
+ +
+ + +
+

Adds a data logger with a JSON log format to the directory.

+
+ + + +
- (ORKDataLogger *)addJSONDataLoggerForLogName:(NSString *)logName
+ + + +
+

Parameters

+ + + + + + + +
logName

The log name prefix for the data logger.

+
+ + + +
+

Return Value

+

The ORKDataLogger object that was added.

+
+ + + + + +
+

Discussion

+

This method throws an exception if a logger already exists with the specified log name.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– addDataLoggerForLogName:formatter: +

+ +
+
+ +
+ + +
+

Adds a data logger with a particular formatter to the directory.

+
+ + + +
- (ORKDataLogger *)addDataLoggerForLogName:(NSString *)logName formatter:(ORKLogFormatter *)formatter
+ + + +
+

Parameters

+ + + + + + + + + + + + +
logName

The log name prefix for the data logger.

formatter

The log formatter instance to use for this logger.

+
+ + + +
+

Return Value

+

The ORKDataLogger object that was added, or the existing one if one already existed for +that log name.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– removeDataLogger: +

+ +
+
+ +
+ + +
+

Removes a data logger.

+
+ + + +
- (void)removeDataLogger:(ORKDataLogger *)logger
+ + + +
+

Parameters

+ + + + + + + +
logger

The logger to remove.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLoggerForLogName: +

+ +
+
+ +
+ + +
+

Retrieves the already existing data logger for a log name.

+
+ + + +
- (ORKDataLogger *)dataLoggerForLogName:(NSString *)logName
+ + + +
+

Parameters

+ + + + + + + +
logName

The log name prefix for the data logger.

+
+ + + +
+

Return Value

+

The ORKDataLogger object that was retrieved, or nil if one already existed for that log name.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– logNames +

+ +
+
+ +
+ + +
+

Returns the set of log names of the data loggers managed by this object.

+
+ + + +
- (NSArray<NSString*> *)logNames
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– enumerateLogsNeedingUpload:error: +

+ +
+
+ +
+ + +
+

Enumerates all the logs that need upload across all data loggers, sorted from oldest to first.

+
+ + + +
- (BOOL)enumerateLogsNeedingUpload:(void ( ^ ) ( ORKDataLogger *dataLogger , NSURL *logFileUrl , BOOL *stop ))block error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
block

The block to call during enumeration.

error

The error, on failure.

+
+ + + +
+

Return Value

+

YES if the enumeration succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Before sorting the logs, this method fetches all the data loggers' logs that need upload.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– removeUploadedFiles:error: +

+ +
+
+ +
+ + +
+

Removes a set of uploaded files.

+
+ + + +
- (BOOL)removeUploadedFiles:(NSArray<NSURL*> *)fileURLs error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileURLs

The array of file URLs that should be removed.

error

The error, on failure.

+
+ + + +
+

Return Value

+

YES if the operation succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method is analogous to a similar method in ORKDataLogger, but it accepts an array of files +that may relate to any of the data loggers. It is an error to pass a URL which would not +belong to one of the loggers managed by this manager.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– unmarkUploadedFiles:error: +

+ +
+
+ +
+ + +
+

Unmarks the set of uploaded files.

+
+ + + +
- (BOOL)unmarkUploadedFiles:(NSArray<NSURL*> *)fileURLs error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileURLs

The array of file URLs that should no longer be marked uploaded.

error

The error, on failure.

+
+ + + +
+

Return Value

+

YES if the operation succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Use this method to indicate that the specified files should no longer be marked uploaded (for example, because +the upload did not succeed).

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– removeOldAndUploadedLogsToThreshold:error: +

+ +
+
+ +
+ + +
+

Removes old and uploaded logs to bring total bytes down to a threshold.

+
+ + + +
- (BOOL)removeOldAndUploadedLogsToThreshold:(unsigned long long)bytes error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
bytes

The threshold down to which to remove old log files. File removal stops when the total bytes managed by all the data loggers reaches this threshold.

error

The error, on failure.

+
+ + + +
+

Return Value

+

YES if the operation succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method removes uploaded logs first, followed by the oldest log files across +all of the data loggers, until the total usage falls below a threshold.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLogger:finishedLogFile: +

+ +
+
+ +
+ + +
+

Tells the delegate when a log file rollover occurs.

+
+ + + +
- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLogger

The data logger providing the notification.

fileUrl

The URL of the newly renamed log file.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLoggerByteCountsDidChange: +

+ +
+
+ +
+ + +
+

Tells the delegate if the number of bytes in completed logs changes.

+
+ + + +
- (void)dataLoggerByteCountsDidChange:(ORKDataLogger *)dataLogger
+ + + +
+

Parameters

+ + + + + + + +
dataLogger

The data logger providing the notification.

+
+ + + + + + + +
+

Discussion

+

When files are removed or added, or marked as uploaded or unmarked, this delegate method is called a short time later. Multiple directory changes +are rolled up into a single delegate callback.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate of the data logger manager.

+
+ + + +
@property (weak, nullable) id<ORKDataLoggerManagerDelegate> delegate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  pendingUploadBytesThreshold +

+ +
+
+ +
+ + +
+

The threshold for delegate callback for total bytes not marked uploaded.

+
+ + + +
@property unsigned long long pendingUploadBytesThreshold
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  totalBytesThreshold +

+ +
+
+ +
+ + +
+

The threshold for delegate callback for total bytes of completed logs.

+
+ + + +
@property unsigned long long totalBytesThreshold
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  pendingUploadBytes +

+ +
+
+ +
+ + +
+

The total number of bytes of files not marked as pending upload.

+
+ + + +
@property unsigned long long pendingUploadBytes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

  totalBytes +

+ +
+
+ +
+ + +
+

The total number of bytes for all the loggers.

+
+ + + +
@property unsigned long long totalBytes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManagerTests.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManagerTests.html new file mode 100755 index 0000000..9821084 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerManagerTests.html @@ -0,0 +1,256 @@ + + + + + + ORKDataLoggerManagerTests Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerManagerTests Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromXCTestCase
Conforms toORKDataLoggerManagerDelegate
Declared inORKDataLoggerManagerTests.m
+ + + + + + +
+ + + + + + +
+
+ +

– dataLoggerManager:pendingUploadBytesReachedThreshold: +

+ +
+
+ +
+ + +
+

Called by the data logger manager when the total size of files +that are not marked uploaded has reached a threshold.

+
+ + + +
- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLogger pendingUploadBytesReachedThreshold:(unsigned long long)pendingUploadBytes
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLoggerManager

The manager that produced the notification.

pendingUploadBytes

The number of bytes managed by all the loggers, which + have not yet been marked uploaded.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLoggerManager:totalBytesReachedThreshold: +

+ +
+
+ +
+ + +
+

Called by the data logger manager when the total size of files +managed by any of the loggers has reached a threshold.

+
+ + + +
- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLogger totalBytesReachedThreshold:(unsigned long long)totalBytes
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLoggerManager

The manager that produced the notification.

totalBytes

The total number of bytes of all files managed.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerTests.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerTests.html new file mode 100755 index 0000000..01b9e02 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDataLoggerTests.html @@ -0,0 +1,193 @@ + + + + + + ORKDataLoggerTests Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerTests Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromXCTestCase
Conforms toORKDataLoggerDelegate
Declared inORKDataLoggerTests.m
+ + + + + + +
+ + + + + + +
+
+ +

– dataLogger:finishedLogFile: +

+ +
+
+ +
+ + +
+

Tells the delegate when a log file rollover occurs.

+
+ + + +
- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLogger

The data logger providing the notification.

fileUrl

The URL of the newly renamed log file.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateAnswerFormat.html new file mode 100755 index 0000000..6157bd4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateAnswerFormat.html @@ -0,0 +1,593 @@ + + + + + + ORKDateAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDateAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKDateAnswerFormat class represents the answer format for questions that require users +to enter a date, or a date and time.

+ +

A date answer format produces an ORKDateQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithStyle: +

+ +
+
+ +
+ + +
+

Returns an initialized date answer format using the specified date style.

+
+ + + +
- (instancetype)initWithStyle:(ORKDateAnswerStyle)style
+ + + +
+

Parameters

+ + + + + + + +
style

The style of date answer, such as date, or date and time.

+
+ + + +
+

Return Value

+

An initialized date answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithStyle:defaultDate:minimumDate:maximumDate:calendar: +

+ +
+
+ +
+ + +
+

Returns an initialized date answer format using the specified answer style and default date values.

+
+ + + +
- (instancetype)initWithStyle:(ORKDateAnswerStyle)style defaultDate:(nullable NSDate *)defaultDate minimumDate:(nullable NSDate *)minimumDate maximumDate:(nullable NSDate *)maximumDate calendar:(nullable NSCalendar *)calendar
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
style

The style of date answer, such as date, or date and time.

defaultDate

The default date to display. When the value of this parameter is nil, the + picker displays the current time.

minimumDate

The minimum date that is accessible in the picker. If the value of this + parameter is nil, there is no minimum.

maximumDate

The maximum date that is accessible in the picker. If the value of this + parameter is nil, there is no maximum.

calendar

The calendar to use. If the value of this parameter is nil, the picker + uses the default calendar for the current locale.

+
+ + + +
+

Return Value

+

An initialized date answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  style +

+ +
+
+ +
+ + +
+

The style of date entry.

+
+ + + +
@property (readonly) ORKDateAnswerStyle style
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultDate +

+ +
+
+ +
+ + +
+

The date to use as the default.

+
+ + + +
@property (copy, readonly, nullable) NSDate *defaultDate
+ + + + + + + + + +
+

Discussion

+

The date is displayed in the user’s time zone. +When the value of this property is nil, the current time is used as the default.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumDate +

+ +
+
+ +
+ + +
+

The minimum allowed date.

+
+ + + +
@property (copy, readonly, nullable) NSDate *minimumDate
+ + + + + + + + + +
+

Discussion

+

When the value of this property is nil, there is no minimum.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumDate +

+ +
+
+ +
+ + +
+

The maximum allowed date.

+
+ + + +
@property (copy, readonly, nullable) NSDate *maximumDate
+ + + + + + + + + +
+

Discussion

+

When the value of this property is nil, there is no maximum.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  calendar +

+ +
+
+ +
+ + +
+

The calendar to use in the picker.

+
+ + + +
@property (copy, readonly, nullable) NSCalendar *calendar
+ + + + + + + + + +
+

Discussion

+

When the value of this property is nil, the picker uses the default calendar for the current +locale.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateQuestionResult.html new file mode 100755 index 0000000..73bbff4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDateQuestionResult.html @@ -0,0 +1,280 @@ + + + + + + ORKDateQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDateQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKDateQuestionResult class represents the result of a question or form item that asks for a date (ORKDateAnswerFormat).

+ +

The calendar and time zone are recorded in addition to the answer itself, +to give the answer context. Usually, this data corresponds to the current calendar +and time zone at the time of the activity, but it can be overridden by setting +these properties explicitly in the ORKDateAnswerFormat object.

+
+ + + + + +
+ + + + + + +
+
+ +

  dateAnswer +

+ +
+
+ +
+ + +
+

The date that the user entered, or nil if the user skipped the question.

+
+ + + +
@property (nonatomic, copy, nullable) NSDate *dateAnswer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  calendar +

+ +
+
+ +
+ + +
+

The calendar used when selecting date and time.

+
+ + + +
@property (nonatomic, copy, nullable) NSCalendar *calendar
+ + + + + + + + + +
+

Discussion

+

If the calendar in the ORKDateAnswerFormat object is nil, this calendar is the system +calendar at the time of data entry.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  timeZone +

+ +
+
+ +
+ + +
+

The time zone that was current when selecting the date and time.

+
+ + + +
@property (nonatomic, copy, nullable) NSTimeZone *timeZone
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorder.html new file mode 100755 index 0000000..5f49bc6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorder.html @@ -0,0 +1,474 @@ + + + + + + ORKDeviceMotionRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDeviceMotionRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKDeviceMotionRecorder.h
ORKDeviceMotionRecorder.m
+ + + + +
+ +

Overview

+

The ORKDeviceMotionRecorder class represents a recorder that requests and collects device motion data from CoreMotion at a fixed frequency.

+ +

To ensure that the motion recorder continues to record when the app enters the +background, use the background task support provided by UIApplication.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  frequency +

+ +
+
+ +
+ + +
+

The frequency of motion data collection from CoreMotion in hertz (Hz).

+
+ + + +
@property (nonatomic, readonly) double frequency
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKDeviceMotionRecorder.h

+
+ + +
+
+
+ +

– initWithIdentifier:frequency:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized device motion recorder using the specified frequency.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency step:(nullable ORKStep *)step outputDirectory:(nullable NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

frequency

The frequency of motion data collection from CoreMotion in hertz (Hz).

step

The step that requested this recorder.

outputDirectory

The directory in which the device motion data should be stored.

+
+ + + +
+

Return Value

+

An initialized motion data recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDeviceMotionRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorderConfiguration.html new file mode 100755 index 0000000..71c59b2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDeviceMotionRecorderConfiguration.html @@ -0,0 +1,515 @@ + + + + + + ORKDeviceMotionRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDeviceMotionRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKDeviceMotionRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKDeviceMotionRecorderConfiguration class represents a configuration +that records device motion data during an active step.

+ +

Device motion data is the processed motion data provided by CoreMotion and obtained +from a CMMotionManager object. The data can include measures of the overall device orientation +obtained from combining accelerometer, magnetometer, and gyroscope data.

+ +

Device motion data is serialized to JSON and returned as an ORKFileResult object. +For details on the format, see CMDeviceMotion+ORKJSONDictionary.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithIdentifier:frequency: +

+ +
+
+ +
+ + +
+

Returns an initialized device motion recorder configuration using the specified frequency.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier frequency:(double)frequency
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier of the recorder configuration.

frequency

Motion data collection frequency in samples per second (Hz).

+
+ + + +
+

Return Value

+

An initialized device motion recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new device motion recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the device motion recorder configuration.

+
+ + + +
+

Return Value

+

A new device motion recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  frequency +

+ +
+
+ +
+ + +
+

The frequency of motion data collection in samples per second (Hz).

+
+ + + +
@property (nonatomic, readonly) double frequency
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDirectStepNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDirectStepNavigationRule.html new file mode 100755 index 0000000..bfd6490 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDirectStepNavigationRule.html @@ -0,0 +1,386 @@ + + + + + + ORKDirectStepNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDirectStepNavigationRule Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepNavigationRule : NSObject
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKDirectStepNavigationRule class can be used to unconditionally jump to a destination step +specified by its identifier or to finish the task early.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithDestinationStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized direct-step navigation rule using the specified destination step identifier.

+
+ + + +
- (instancetype)initWithDestinationStepIdentifier:(NSString *)destinationStepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
destinationStepIdentifier

The identifier of the destination step. Pass the + ORKNullStepIdentifier constant if you want to finish the + ongoing task when the direct-step navigation rule is + triggered.

+
+ + + +
+

Return Value

+

A direct-step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new direct-step navigation rule initialized from data in a given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the step navigation rule.

+
+ + + +
+

Return Value

+

A new direct-step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  destinationStepIdentifier +

+ +
+
+ +
+ + +
+

The identifier of the destination step.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *destinationStepIdentifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– identifierForDestinationStepWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns the target step identifier.

+
+ + + +
- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)ORKTaskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating the destination step.

+
+ + + +
+

Return Value

+

The identifier of the destination step.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate the next step based on the passed task result. +The ORKNullStepIdentifier constant can be returned to indicate that the ongoing task should end +after the step navigation rule is triggered.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDiscreteGraphChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDiscreteGraphChartView.html new file mode 100755 index 0000000..880ab0a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKDiscreteGraphChartView.html @@ -0,0 +1,196 @@ + + + + + + ORKDiscreteGraphChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDiscreteGraphChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromORKValueRangeGraphChartView : ORKGraphChartView : UIView
Declared inORKDiscreteGraphChartView.h
ORKDiscreteGraphChartView.m
+ + + + +
+ +

Overview

+

The ORKDiscreteGraphChartView class presents data provided by an object conforming to the +ORKValueRangeGraphChartViewDataSource protocol as a discrete graph of ranged points.

+ +

You can optionally display a line connecting each ranged point pair.

+ +

By default, the primary plot is colored by the tintColor, and any additional plots are colored +using the referenceLineColor property. You can customize the plot colors by implementing the +-graphChartView:colorForPlotIndex: method in the data source.

+
+ + + + + +
+ + + + + + +
+
+ +

  drawsConnectedRanges +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to draw a line connecting the minimum value and maximum value of +each ranged point represented by the graph view.

+
+ + + +
@property (nonatomic) IBInspectable BOOL drawsConnectedRanges
+ + + + + + + + + +
+

Discussion

+

The default value for this property is YES.

+
+ + + + + + + +
+

Declared In

+

ORKDiscreteGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEmailAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEmailAnswerFormat.html new file mode 100755 index 0000000..68e56d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEmailAnswerFormat.html @@ -0,0 +1,243 @@ + + + + + + ORKEmailAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKEmailAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKEmailAnswerFormat class represents the answer format for questions that collect an email +response from the user.

+ +

An ORKEmailAnswerFormat object produces an ORKTextQuestionResult object.

+
+ + + + + +
+ + + + + + +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– impliedAnswerFormat +

+ +
+
+ +
+ + +
+

Some answer formats are constructed of other answer formats. This method allows +a subclass to return a different answer format for use in defining the UI/UX for +the answer format type. For example, a Boolean answer format is presented in the +same way as a single-choice answer format with the choices Yes and No mapping to +@(YES) and @(NO), respectively, so its impliedAnswerFormat is an +ORKTextChoiceAnswerFormat with those options.

+
+ + + +
- (ORKAnswerFormat *)impliedAnswerFormat
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStep.html new file mode 100755 index 0000000..af6a49b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStep.html @@ -0,0 +1,445 @@ + + + + + + ORKEnvironmentSPLMeterStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKEnvironmentSPLMeterStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKEnvironmentSPLMeterStep.h
ORKEnvironmentSPLMeterStep.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  thresholdValue +

+ +
+
+ +
+ + +
+

The maximum permissible value for the environment sound pressure level in dBA.

+
+ + + +
@property (nonatomic, assign) double thresholdValue
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKEnvironmentSPLMeterStep.h

+
+ + +
+
+
+ +

  samplingInterval +

+ +
+
+ +
+ + +
+

The rate at which the AVAudioPCMBuffer is queried and A-weighted filter is applied.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval samplingInterval
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKEnvironmentSPLMeterStep.h

+
+ + +
+
+
+ +

  requiredContiguousSamples +

+ +
+
+ +
+ + +
+

The number of consecutive samples less than threshold value required for the step to proceed.

+
+ + + +
@property (nonatomic, assign) NSInteger requiredContiguousSamples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKEnvironmentSPLMeterStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStepViewController.html new file mode 100755 index 0000000..3b4f0b0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKEnvironmentSPLMeterStepViewController.html @@ -0,0 +1,361 @@ + + + + + + ORKEnvironmentSPLMeterStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKEnvironmentSPLMeterStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKEnvironmentSPLMeterStepViewController.h
ORKEnvironmentSPLMeterStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFileResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFileResult.html new file mode 100755 index 0000000..5037f22 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFileResult.html @@ -0,0 +1,325 @@ + + + + + + ORKFileResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFileResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKFileResult.h
ORKFileResult.m
+ + + + +
+ +

Overview

+

The ORKFileResult class is a result that references the location of a file produced +during a task.

+ +

A file result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize the linked file for transmission +to the server.

+ +

Active steps typically produce file results when CoreMotion or HealthKit are +serialized to disk using a data logger (ORKDataLogger). Audio recording also produces a file +result.

+ +

When you write a custom step, use files to report results only when the data +is likely to be too big to hold in memory for the duration of the task. For +example, fitness tasks that use sensors can be quite long and can generate +a large number of samples. To compensate for the length of the task, you can stream the samples to disk during +the task, and return an ORKFileResult object in the result hierarchy, usually as a +child of an ORKStepResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  contentType +

+ +
+
+ +
+ + +
+

The MIME content type of the result.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *contentType
+ + + + + + + + + +
+

Discussion

+

For example, @"application/json".

+
+ + + + + + + +
+

Declared In

+

ORKFileResult.h

+
+ + +
+
+
+ +

  fileURL +

+ +
+
+ +
+ + +
+

The URL of the file produced.

+
+ + + +
@property (nonatomic, copy, nullable) NSURL *fileURL
+ + + + + + + + + +
+

Discussion

+

It is the responsibility of the receiver of the result object to delete +the file when it is no longer needed.

+ +

The file is typically written to the output directory of the +task view controller, so it is common to manage the archiving or cleanup +of these files by archiving or deleting the entire output directory.

+
+ + + + + + + +
+

Declared In

+

ORKFileResult.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– isSaveable +

+ +
+
+ +
+ + +
+

A boolean value indicating whether this result can be saved in a save and +restore procedure.

+
+ + + +
- (BOOL)isSaveable
+ + + + + + + + + +
+

Discussion

+

This is currently considered a private method, but overriding the getter in a result +is the correct way to prevent this result being considered as saveable for +the purpose of deciding whether to offer a “Save” option when the user +cancels a task in progress.

+ +

ORKResult subclasses should return YES if they have data that the user +might want to be able to restore if the task were interrupted and later +resumed from the current state.

+
+ + + + + + + +
+

Declared In

+

ORKResult_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStep.html new file mode 100755 index 0000000..cd30cc2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStep.html @@ -0,0 +1,280 @@ + + + + + + ORKFitnessStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFitnessStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKFitnessStep.h
ORKFitnessStep.m
+ + + + +
+ +

Overview

+

Fitness step.

+ +

Displays usual header, a counting-up timer, read outs for distance and/or +heart rate if corresponding recorders are attached.

+ +

Also displays an image during the task.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStepViewController.html new file mode 100755 index 0000000..24b2a89 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFitnessStepViewController.html @@ -0,0 +1,254 @@ + + + + + + ORKFitnessStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFitnessStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKFitnessStepViewController.h
ORKFitnessStepViewController.m
+ + + + +
+ +

Overview

+

Step view controller corresponding to ORKFitnessStep.

+ +

Observes countdown timer, heart rate, and distance, and relays these to the +screen during the task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– recordersDidChange +

+ +
+
+ +
+ + +
+

Tells the view controller that the set of recorders changed.

+
+ + + +
- (void)recordersDidChange
+ + + + + + + + + +
+

Discussion

+

This method is usually called by the active step view controller in response +to start or resume.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFootnoteLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFootnoteLabel.html new file mode 100755 index 0000000..338df67 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFootnoteLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKFootnoteLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFootnoteLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKFootnoteLabel.h
ORKFootnoteLabel.m
+ + + + +
+ +

Overview

+

Step’s details text under title.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormItem.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormItem.html new file mode 100755 index 0000000..fe6748e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormItem.html @@ -0,0 +1,703 @@ + + + + + + ORKFormItem Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFormItem Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKFormStep.h
ORKFormStep.m
+ + + + +
+ +

Overview

+

The ORKFormItem class represents a single item in a form step (ORKFormStep), and typically +represents a question.

+ +

To use ORKFormItem, instantiate the object, fill in its properties, and incorporate +it in an ORKFormStep object.

+ +

Usually, a form item corresponds to either a row or a section header in a form, but +if the answer format is a choice answer format, it may correspond to an entire +section.

+ +

Each form item generates one question result (ORKQuestionResult), which becomes a child of its step’s +result (ORKStepResult).

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:text:answerFormat: +

+ +
+
+ +
+ + +
+

Returns an initialized form item using the specified identifier, title, and answer format.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier text:(NSString *)text answerFormat:(ORKAnswerFormat *)answerFormat
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The string that identifies the form item, which should be unique within the form step.

text

The text displayed as a prompt for the form item’s question.

answerFormat

The answer format for the form item.

+
+ + + +
+

Return Value

+

An initialized form item.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:text:answerFormat:optional: +

+ +
+
+ +
+ + +
+

Returns an initialized form item using the specified identifier, title, optionality and answer format.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier text:(NSString *)text answerFormat:(ORKAnswerFormat *)answerFormat optional:(BOOL)optional
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The string that identifies the form item, which should be unique within the form step.

text

The text displayed as a prompt for the form item’s question.

answerFormat

The answer format for the form item.

optional

A Boolean that determines whether the item is optional

+
+ + + +
+

Return Value

+

An initialized form item.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– initWithSectionTitle: +

+ +
+
+ +
+ + +
+

Returns an initialized form item using the specified section title.

+
+ + + +
- (instancetype)initWithSectionTitle:(NSString *)sectionTitle
+ + + +
+

Parameters

+ + + + + + + +
sectionTitle

The title of the section.

+
+ + + +
+

Return Value

+

An initialized form item for use as a section header in a form.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– confirmationAnswerFormItemWithIdentifier:text:errorMessage: +

+ +
+
+ +
+ + +
+

Returns an form item that can be used for confirming a text entry.

+
+ + + +
- (ORKFormItem *)confirmationAnswerFormItemWithIdentifier:(NSString *)identifier text:(nullable NSString *)text errorMessage:(NSString *)errorMessage
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The identifier for the ORKFormItem that is returned.

text

The text for the ORKFormItem that is returned.

errorMessage

The error message to display if the fields do not match

+
+ + + +
+

Return Value

+

An ORKFormItem with the indicated identifier and text and an ORKAnswerFormat + that is appropriate for confirming the input form item.

+
+ + + + + +
+

Discussion

+

This form item is intended to be used with an ORKFormStep in order to confirm a previous +formItem input. Example usage includes a password or participant identifier that is used to +anonymously identify a study participant.

+ +

Currently, only ORKTextAnswerFormat is supported. Unsupported ORKAnswerFormat types will +throw an exception.

+ +

The answer format for this item produces an ORKBooleanQuestionResult object.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

A string that identifies the form item.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier should be unique within the form step that contains the form +item. The identifier is reproduced in the question result object (ORKQuestionResult) +generated for the item.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  optional +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the form item is optional.

+
+ + + +
@property (nonatomic, getter=isOptional) BOOL optional
+ + + + + + + + + +
+

Discussion

+

The default value of this property is YES. When the value is YES, this form item doesn’t need +to be answered for the Continue button of a step form to be enabled.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

A localized string that describes the form item.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSString *text
+ + + + + + + + + +
+

Discussion

+

If the descriptive text is sufficiently short, you can display it as a prompt next to the item. +If it is too long to display next to the item, you can display it above the item.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  placeholder +

+ +
+
+ +
+ + +
+

A localized string that displays placeholder information for the form item.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *placeholder
+ + + + + + + + + +
+

Discussion

+

You can display placeholder text in a text field or text area to help users understand how to answer the +item’s question. A placeholder string is not appropriate for choice-based answer formats.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  answerFormat +

+ +
+
+ +
+ + +
+

The format of the expected answer for the item.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) ORKAnswerFormat *answerFormat
+ + + + + + + + + +
+

Discussion

+

The answer format specifies the type of answer that is expected, in addition to any +constraints on valid answers.

+ +

By default, the answer format is nil. The answer format for a form item that represents a section +header is always nil, because no answer is expected.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStep.html new file mode 100755 index 0000000..cc618f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStep.html @@ -0,0 +1,610 @@ + + + + + + ORKFormStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFormStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKFormStep.h
ORKFormStep.m
+ + + + +
+ +

Overview

+

The ORKFormStep class is a concrete subclass of ORKStep, used for presenting multiple questions +on a single scrollable page.

+ +

To use ORKFormStep, instantiate the object, fill in its properties, and include it +in a task. Next, create a task view controller for the task and present it. +When the task completes, the user’s answers are encoded in the result hierarchy +in the task view controller.

+ +

Each question in the form is represented by an ORKFormItem object. The form items have an +optional property that defaults to YES. All required questions need to be answered for the +Continue button to be enabled. If all the form items are optional, at least one question needs to +be answered for the Continue button to be enabled. You can allow the user to completely skip a +form step using the Skip button, even if it has required form items, by setting the form step +optional property to yes.

+ +

The form can be broken into sections by using an ORKFormItem object that includes only a section +title.

+ +

The result of a form step is an ORKStepResult object that includes a child ORKQuestionResult +object for each form item.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:title:text: +

+ +
+
+ +
+ + +
+

Returns an initialized form step using the specified identifier, title, and text.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title text:(NSString *)text
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

+
+ + + +
+

Return Value

+

As initialized form step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types the step requests for reading. (read-only)

+
+ + + +
- (NSSet<HKObjectType*> *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this set of types when constructing a list of +all the HealthKit types required by all the steps in a task, so that it can +present the HealthKit access dialog just once during that task.

+ +

By default, the property scans the recorders and collates the HealthKit +types the recorders require. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  footnote +

+ +
+
+ +
+ + +
+

Additional text to display for the step in a localized string at the bottom of the view.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *footnote
+ + + + + + + + + +
+

Discussion

+

The footnote is displayed in a smaller font below the continue button. It is intended to be used +in order to include disclaimer, copyright, etc. that is important to display in the step but +should not distract from the main purpose of the step.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  formItems +

+ +
+
+ +
+ + +
+

The array of items in the form.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKFormItem*> *formItems
+ + + + + + + + + +
+

Discussion

+

A form step that contains no items is considered invalid and an exception will be thrown +when it is presented.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

  useCardView +

+ +
+
+ +
+ + +
+

The property to present the form with all the items in a card view. Default to YES;

+
+ + + +
@property (nonatomic) BOOL useCardView
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStepViewController.html new file mode 100755 index 0000000..13e836f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormStepViewController.html @@ -0,0 +1,488 @@ + + + + + + ORKFormStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFormStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKFormStepViewController.h
ORKFormStepViewController.m
+ + + + +
+ +

Overview

+

The ORKFormStepViewController class is the concrete ORKStepViewController +implementation for ORKFormStep.

+ +

You should not need to instantiate a form step view controller +directly. Instead, create an ORKFormStep object and include it in a task for an +ORKTaskViewController object, and present the task view controller. The task view +controller automatically instantiates the form step view controller +when it encounters a form step and needs to present it.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– skipForward +

+ +
+
+ +
+ + +
+

This method is called when the user taps the skip button. By default, it calls goForward.

+
+ + + +
- (void)skipForward
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– goBackward +

+ +
+
+ +
+ + +
+

Navigates backward to the previous step.

+
+ + + +
- (void)goBackward
+ + + + + + + + + +
+

Discussion

+

When a user taps the Back button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormTextView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormTextView.html new file mode 100755 index 0000000..61ebee4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFormTextView.html @@ -0,0 +1,121 @@ + + + + + + ORKFormTextView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFormTextView Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerTextView : UITextView
Declared inORKFormTextView.h
ORKFormTextView.m
+ + + + +
+ +

Overview

+

Text view for use in forms

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFreehandDrawingView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFreehandDrawingView.html new file mode 100755 index 0000000..2193348 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKFreehandDrawingView.html @@ -0,0 +1,183 @@ + + + + + + ORKFreehandDrawingView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFreehandDrawingView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKFreehandDrawingView.h
ORKFreehandDrawingView.m
+ + + + + + +
+ + + + + + +
+
+ +

  lineWidthVariation +

+ +
+
+ +
+ + +
+

lineWidthVariation defines the max amount by which the line +width can vary (default 3pts).

+
+ + + +
@property (nonatomic) CGFloat lineWidthVariation
+ + + + + + + + + +
+

Discussion

+

The exact amount of the variation is determined by the amount +of force applied on 3D touch capable devices or by the speed +of the stroke if 3D touch is not available.

+ +

If the user is signing with an Apple Pencil, its force will be used.

+
+ + + + + + + +
+

Declared In

+

ORKFreehandDrawingView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKGraphChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKGraphChartView.html new file mode 100755 index 0000000..ed548c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKGraphChartView.html @@ -0,0 +1,1134 @@ + + + + + + ORKGraphChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKGraphChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKGraphChartView.h
ORKGraphChartView.m
+ + + + +
+ +

Overview

+

The ORKGraphChartView class is an abstract class which holds properties and methods common to +concrete subclasseses.

+ +

You should not instantiate this class directly; use one of the subclasses instead. The concrete +subclasses are ORKLineGraphChartView, ORKDiscreteGraphChartView, and ORKBarGraphChartView.

+
+ + + + + +
+ + + + + + +
+
+ +

  minimumValue +

+ +
+
+ +
+ + +
+

The minimum value of the y-axis.

+
+ + + +
@property (nonatomic, readonly) double minimumValue
+ + + + + + + + + +
+

Discussion

+

You can provide this value to an instance of ORKGraphChartView by implementing the optional +minimumValueForGraphChartView: method of the ORKGraphChartViewDataSource protocol.

+ +

If minimumValueForGraphChartView: is not implemented, the minimum value is assigned to the +smallest value of the minimumValue property of all ORKValueRange instances returned by the +graph chart view data source.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  maximumValue +

+ +
+
+ +
+ + +
+

The maximum value of the y-axis.

+
+ + + +
@property (nonatomic, readonly) double maximumValue
+ + + + + + + + + +
+

Discussion

+

You can provide this value instance of ORKGraphChartView by implementing the +optional maximumValueForGraphChartView: method of the ORKGraphChartViewDataSource protocol.

+ +

If maximumValueForGraphChartView: is not implemented, the maximum value is assigned to the +largest value of the maximumValue property of all ORKValueRange instances returned by the +graph chart view data source.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  showsHorizontalReferenceLines +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the graph chart view should draw horizontal reference lines.

+
+ + + +
@property (nonatomic) IBInspectable BOOL showsHorizontalReferenceLines
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  showsVerticalReferenceLines +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the graph chart view should draw vertical reference lines.

+
+ + + +
@property (nonatomic) IBInspectable BOOL showsVerticalReferenceLines
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate is notified of pan gesture events occuring within the bounds of the graph chart +view.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKGraphChartViewDelegate> delegate
+ + + + + + + + + +
+

Discussion

+

See the ORKGraphChartViewDelegate protocol.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  dataSource +

+ +
+
+ +
+ + +
+

The data source responsible for providing the data required to populate the graph chart view.

+
+ + + +
@property (nonatomic, weak) id<ORKGraphChartViewDataSource> dataSource
+ + + + + + + + + +
+

Discussion

+

See the ORKGraphChartViewDataSource protocol.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  axisColor +

+ +
+
+ +
+ + +
+

The color of the axes drawn by the graph chart view.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *axisColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a light gray color. Setting this property to nil +resets it to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  verticalAxisTitleColor +

+ +
+
+ +
+ + +
+

The color of the vertical axis titles.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *verticalAxisTitleColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a light gray color. Setting this property to nil resets it +to its default value.

Note: The horizontal axis titles use the current tintColor.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  referenceLineColor +

+ +
+
+ +
+ + +
+

The color of the reference lines.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *referenceLineColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a light gray color. Setting this property to nil resets it +to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  scrubberThumbColor +

+ +
+
+ +
+ + +
+

The background color of the thumb on the scrubber line.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *scrubberThumbColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a white color. Setting this property to nil resets it to +its default value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  scrubberLineColor +

+ +
+
+ +
+ + +
+

The color of the scrubber line.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *scrubberLineColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a gray color. Setting this property to nil resets it to +its default value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  noDataText +

+ +
+
+ +
+ + +
+

The string that is displayed if no data points are provided by the data source.

+
+ + + +
@property (nonatomic, copy, null_resettable) IBInspectable NSString *noDataText
+ + + + + + + + + +
+

Discussion

+

The default value for this property is an appropriate message string. Setting this property to +nil resets it to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  maximumValueImage +

+ +
+
+ +
+ + +
+

An image to be optionally displayed in place of the maximum value label on the y-axis.

+
+ + + +
@property (nonatomic, strong, nullable) IBInspectable UIImage *maximumValueImage
+ + + + + + + + + +
+

Discussion

+

The default value for this property is nil.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  minimumValueImage +

+ +
+
+ +
+ + +
+

An image to be optionally displayed in place of the minimum value label on the y-axis.

+
+ + + +
@property (nonatomic, strong, nullable) IBInspectable UIImage *minimumValueImage
+ + + + + + + + + +
+

Discussion

+

The default value for this property is nil.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  longPressGestureRecognizer +

+ +
+
+ +
+ + +
+

The long press gesture recognizer that is used for scrubbing by the graph chart view. You can use +this property to prioritize your own gesture recognizers.

+
+ + + +
@property (nonatomic, strong, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer
+ + + + + + + + + +
+

Discussion

+

This object is instatiated and added to the view when it is created.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  panGestureRecognizer +

+ +
+
+ +
+ + +
+

The gesture recognizer that is used for scrubbing by the graph chart view.

+
+ + + +
@property (nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer
+ + + + + + + + + +
+

Discussion

+

This object is instatiated and added to the view when it is created.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  decimalPlaces +

+ +
+
+ +
+ + +
+

The number of decimal places that is used on the y-axis and scrubber value labels.

+
+ + + +
@property (nonatomic) NSUInteger decimalPlaces
+ + + + + + + + + +
+

Discussion

+

The default value of this property is 0.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

  yAxisLabelFactors +

+ +
+
+ +
+ + +
+

An array of factors for adding Y-Axis labels

+
+ + + +
@property (nonatomic) NSArray<NSNumber*> *yAxisLabelFactors
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– animateWithDuration: +

+ +
+
+ +
+ + +
+

Animates the graph when it first displays on the screen.

+
+ + + +
- (void)animateWithDuration:(NSTimeInterval)animationDuration
+ + + +
+

Parameters

+ + + + + + + +
animationDuration

The duration of the appearing animation.

+
+ + + + + + + +
+

Discussion

+

You can optionally call this method from the viewWillAppear: implementation of the view +controller that owns the graph chart view.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– reloadData +

+ +
+
+ +
+ + +
+

Reloads the plotted data.

+
+ + + +
- (void)reloadData
+ + + + + + + + + +
+

Discussion

+

Call this method to reload the data and re-plot the graph. You should call it if the data provided by the dataSource changes.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeadlineLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeadlineLabel.html new file mode 100755 index 0000000..33503e0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeadlineLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKHeadlineLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHeadlineLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKHeadlineLabel.h
ORKHeadlineLabel.m
+ + + + +
+ +

Overview

+

Primary title for any step view controller.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorder.html new file mode 100755 index 0000000..c133d0b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorder.html @@ -0,0 +1,422 @@ + + + + + + ORKHealthClinicalTypeRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthClinicalTypeRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKHealthClinicalTypeRecorder.h
ORKHealthClinicalTypeRecorder.m
+ + + + +
+ +

Overview

+

The ORKHealthClinicalTypeRecorder class represents a recorder for collecting health records data from HealthKit during +an active task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier:healthClinicalType:healthFHIRResourceType:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized health clinical type recorder using the specified HKClinicalType and HKFHIRResourceType.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier healthClinicalType:(HKClinicalType *)healthClinicalType healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

healthClinicalType

The HKClinicalType data that should be collected during the active task.

healthFHIRResourceType

The HKFHIRResourceType for the predicate used to query the HKClinicalType.

step

The step that requested this recorder.

outputDirectory

The directory in which the health records data queried from HealthKit should be stored.

+
+ + + +
+

Return Value

+

An initialized health quantity type recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKHealthClinicalTypeRecorder.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorderConfiguration.html new file mode 100755 index 0000000..173de78 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthClinicalTypeRecorderConfiguration.html @@ -0,0 +1,547 @@ + + + + + + ORKHealthClinicalTypeRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthClinicalTypeRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKHealthClinicalTypeRecorder.m
ORKRecorder.h
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithIdentifier:healthClinicalType:healthFHIRResourceType: +

+ +
+
+ +
+ + +
+

Returns an initialized health clinical type recorder configuration using the specified clinical type.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier healthClinicalType:(HKClinicalType *)healthClinicalType healthFHIRResourceType:(nullable HKFHIRResourceType)healthFHIRResourceType
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder configuration.

healthClinicalType

The HKClinicalType that should be collected during the active task.

healthFHIRResourceType

The HKFHIRResourceType that should be used as predicate while querying for the healthClinicalType. Providing a HKFHIRResourceType that does not correspond to a HKClinicalType will NOT generate any result.

+
+ + + +
+

Return Value

+

An initialized health clinical type recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new health clinical type recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the health clinical type recorder configuration.

+
+ + + +
+

Return Value

+

A new health clinical type recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

Returns the HealthKit types for which this recorder requires read access in a set of HKSampleType objects.

+
+ + + +
- (NSSet *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

Typically, the task view controller automatically collects +and collates the types of HealthKit data requested by each of the active steps in a task, +and requests access to them at the end of the initial instruction +steps in the task.

+ +

If your recorder requires or would benefit from read access to HealthKit at +runtime during the task, return the appropriate set of HKSampleType objects.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  healthClinicalType +

+ +
+
+ +
+ + +
+

The HKClinicalType to be collected from HealthKit. (read-only)

+
+ + + +
@property (nonatomic, readonly, copy) HKClinicalType *healthClinicalType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

  healthFHIRResourceType +

+ +
+
+ +
+ + +
+

The HKFHIRResourceType to used as predicate for HKQuery. (read-only)

+
+ + + +
@property (nonatomic, readonly, copy) HKFHIRResourceType healthFHIRResourceType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCollector.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCollector.html new file mode 100755 index 0000000..cd3bffe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCollector.html @@ -0,0 +1,383 @@ + + + + + + ORKHealthCollector Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthCollector Class Reference

+ + +
+ + + + + + + +
Inherits fromORKCollector : NSObject
Declared inORKCollector.h
ORKCollector.m
+ + + + +
+ +

Overview

+

ORKHealthCollector collects HKSample.

+ +

It cannot be initiated directly. +Use addHealthCollectorWithSampleType:to add one to a ORKDataCollectionManager.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– serializableObjectsForObjects: +

+ +
+
+ +
+ + +
+

Serialization helper that produces objects suitable for serialization to JSON.

+
+ + + +
- (NSArray *)serializableObjectsForObjects:(NSArray<HKSample*> *)objects
+ + + + + +
+

Return Value

+

Serializable dictionary objects.

+
+ + + + + +
+

Discussion

+

Subclasses should implement to provide a default JSON serialization for upload. +Called by serializedDataForObjects:.

+ +

@params objects The objects to be serialized.

+
+ + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  sampleType +

+ +
+
+ +
+ + +
+

HealthKit sample type.

+
+ + + +
@property (copy, readonly) HKSampleType *sampleType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  unit +

+ +
+
+ +
+ + +
+

HealthKit unit into which data should be collected.

+
+ + + +
@property (copy, readonly) HKUnit *unit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  startDate +

+ +
+
+ +
+ + +
+

Samples should be collected starting at this date.

+
+ + + +
@property (copy, readonly) NSDate *startDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  lastAnchor +

+ +
+
+ +
+ + +
+

Last anchor already seen.

+
+ + + +
@property (copy, readonly) HKQueryAnchor *lastAnchor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCorrelationCollector.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCorrelationCollector.html new file mode 100755 index 0000000..41e7749 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthCorrelationCollector.html @@ -0,0 +1,426 @@ + + + + + + ORKHealthCorrelationCollector Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthCorrelationCollector Class Reference

+ + +
+ + + + + + + +
Inherits fromORKCollector : NSObject
Declared inORKCollector.h
ORKCollector.m
+ + + + +
+ +

Overview

+

ORKHealthCollector collects HKCorrelation.

+ +

It cannot be initiated directly. +Use addHealthCorrelationCollectorWithCorrelationType:to add one to a ORKDataCollectionManager.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– serializableObjectsForObjects: +

+ +
+
+ +
+ + +
+

Serialization helper that produces objects suitable for serialization to JSON.

+
+ + + +
- (NSArray *)serializableObjectsForObjects:(NSArray<HKCorrelation*> *)objects
+ + + + + +
+

Return Value

+

Serializable dictionary objects.

+
+ + + + + +
+

Discussion

+

Subclasses should implement to provide a default JSON serialization for upload. +Called by serializedDataForObjects:.

+ +

@params objects The objects to be serialized.

+
+ + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  correlationType +

+ +
+
+ +
+ + +
+

HealthKit correlation type.

+
+ + + +
@property (copy, readonly) HKCorrelationType *correlationType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  sampleTypes +

+ +
+
+ +
+ + +
+

Array of HKSampleType expected in the correlation.

+
+ + + +
@property (copy, readonly) NSArray<HKSampleType*> *sampleTypes
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  units +

+ +
+
+ +
+ + +
+

Array of HKUnit to use when serializing the samples collected (should be same size as sampleTypes).

+
+ + + +
@property (copy, readonly) NSArray<HKUnit*> *units
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  startDate +

+ +
+
+ +
+ + +
+

Samples should be collected starting at this date.

+
+ + + +
@property (copy, readonly) NSDate *startDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  lastAnchor +

+ +
+
+ +
+ + +
+

Last anchor already seen.

+
+ + + +
@property (copy, readonly) HKQueryAnchor *lastAnchor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitCharacteristicTypeAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitCharacteristicTypeAnswerFormat.html new file mode 100755 index 0000000..89d5295 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitCharacteristicTypeAnswerFormat.html @@ -0,0 +1,673 @@ + + + + + + ORKHealthKitCharacteristicTypeAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthKitCharacteristicTypeAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKHealthAnswerFormat.h
ORKHealthAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKHealthKitCharacteristicTypeAnswerFormat class represents an answer format that lets participants enter values that correspond to a HealthKit characteristic type.

+ +

The actual UI used for collecting data with this answer format depends on the HealthKit type being collected. +The default value displayed in the UI is the most recent value received from HealthKit, if such a value exists. +When a step or item is presented using this answer format, authorization is requested unless the property +shouldRequestAuthorization is set to NO.

+ +

You can use the HealthKit characteristic answer format to let users autofill information, such as their blood type or date of birth.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

+ answerFormatWithCharacteristicType: +

+ +
+
+ +
+ + +
+

Returns a new answer format for the specified HealthKit characteristic type.

+
+ + + +
+ (instancetype)answerFormatWithCharacteristicType:(HKCharacteristicType *)characteristicType
+ + + +
+

Parameters

+ + + + + + + +
characteristicType

The characteristic type to collect.

+
+ + + +
+

Return Value

+

A new HealthKit characteristic type answer format instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

– initWithCharacteristicType: +

+ +
+
+ +
+ + +
+

Returns an initialized HealthKit characteristic type answer format using the specified characteristic type.

+
+ + + +
- (instancetype)initWithCharacteristicType:(HKCharacteristicType *)characteristicType
+ + + +
+

Parameters

+ + + + + + + +
characteristicType

The characteristic type to collect.

+
+ + + +
+

Return Value

+

An initialized HealthKit characteristic type answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

– impliedAnswerFormat +

+ +
+
+ +
+ + +
+

Some answer formats are constructed of other answer formats. This method allows +a subclass to return a different answer format for use in defining the UI/UX for +the answer format type. For example, a Boolean answer format is presented in the +same way as a single-choice answer format with the choices Yes and No mapping to +@(YES) and @(NO), respectively, so its impliedAnswerFormat is an +ORKTextChoiceAnswerFormat with those options.

+
+ + + +
- (ORKAnswerFormat *)impliedAnswerFormat
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  shouldRequestAuthorization +

+ +
+
+ +
+ + +
+

Should authorization be requested for the associated HealthKit data type. Default = YES.

+
+ + + +
@property (nonatomic) BOOL shouldRequestAuthorization
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  characteristicType +

+ +
+
+ +
+ + +
+

The HealthKit characteristic type to be collected by this answer format. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly) HKCharacteristicType *characteristicType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  defaultDate +

+ +
+
+ +
+ + +
+

The default date shown by the date picker.

+
+ + + +
@property (nonatomic, strong, nullable) NSDate *defaultDate
+ + + + + + + + + +
+

Discussion

+

Only used for the HKCharacteristicTypeIdentifierDateOfBirth characteristic type. The date is +displayed in the user’s time zone. If you set this property to nil, the date picker will default +to the date representing 35 years before the current date.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  minimumDate +

+ +
+
+ +
+ + +
+

The minimum date that is allowed by the date picker.

+
+ + + +
@property (nonatomic, strong, nullable) NSDate *minimumDate
+ + + + + + + + + +
+

Discussion

+

Only used for the HKCharacteristicTypeIdentifierDateOfBirth characteristic type. If you set this +property to nil, the date picker will use the date representing 150 years before the curent date +as its minimum date.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  maximumDate +

+ +
+
+ +
+ + +
+

The maximum date that is allowed by the date picker.

+
+ + + +
@property (nonatomic, strong, nullable) NSDate *maximumDate
+ + + + + + + + + +
+

Discussion

+

Only used for the HKCharacteristicTypeIdentifierDateOfBirth characteristic type. If you set this +property to nil, the date picker will use the date representing 1 day after curent date as its +maximum date

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  calendar +

+ +
+
+ +
+ + +
+

The calendar used by the date picker.

+
+ + + +
@property (nonatomic, strong, nullable) NSCalendar *calendar
+ + + + + + + + + +
+

Discussion

+

Only used for the HKCharacteristicTypeIdentifierDateOfBirth characteristic type. If you set this +property to nil, the date picker will use the default calendar for the current locale.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitQuantityTypeAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitQuantityTypeAnswerFormat.html new file mode 100755 index 0000000..544975c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthKitQuantityTypeAnswerFormat.html @@ -0,0 +1,588 @@ + + + + + + ORKHealthKitQuantityTypeAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthKitQuantityTypeAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKHealthAnswerFormat.h
ORKHealthAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKHealthKitQuantityTypeAnswerFormat class represents an answer format that lets participants enter values that correspond to a HealthKit quantity type, such as systolic blood pressure.

+ +

The actual UI used for collecting data with this answer format depends on the HealthKit type being collected. +The default value in the UI is the most recent value received from HealthKit, if such a value exists. +When a step or item is presented using this answer format, authorization is requested unless the property +shouldRequestAuthorization is set to NO.

+ +

You can use the HealthKit quantity type answer format to let users autofill values such as their weight with the most +recent data from HealthKit.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

+ answerFormatWithQuantityType:unit:style: +

+ +
+
+ +
+ + +
+

Returns a new HealthKit quantity answer format with the specified quantity type.

+
+ + + +
+ (instancetype)answerFormatWithQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit style:(ORKNumericAnswerStyle)style
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
quantityType

The HealthKit quantity type to collect.

unit

The unit used to describe the quantity. If the value of this parameter is nil, the default HealthKit unit is used, when available.

style

The numeric answer style to use when collecting this value.

+
+ + + +
+

Return Value

+

A HealthKit quantity answer format instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

– initWithQuantityType:unit:style: +

+ +
+
+ +
+ + +
+

Returns an initialized HealthKit quantity answer format using the specified quantity type, unit, and numeric answer style.

+
+ + + +
- (instancetype)initWithQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit style:(ORKNumericAnswerStyle)style
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
quantityType

The HealthKit quantity type to collect.

unit

The unit used to describe the quantity. If the value of this parameter is nil, the default HealthKit unit is used, when available.

style

The numeric answer style to use when collecting this value.

+
+ + + +
+

Return Value

+

An initialized HealthKit quantity answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

– impliedAnswerFormat +

+ +
+
+ +
+ + +
+

Some answer formats are constructed of other answer formats. This method allows +a subclass to return a different answer format for use in defining the UI/UX for +the answer format type. For example, a Boolean answer format is presented in the +same way as a single-choice answer format with the choices Yes and No mapping to +@(YES) and @(NO), respectively, so its impliedAnswerFormat is an +ORKTextChoiceAnswerFormat with those options.

+
+ + + +
- (ORKAnswerFormat *)impliedAnswerFormat
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  shouldRequestAuthorization +

+ +
+
+ +
+ + +
+

Should authorization be requested for the associated HealthKit data type. Default = YES.

+
+ + + +
@property (nonatomic) BOOL shouldRequestAuthorization
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  quantityType +

+ +
+
+ +
+ + +
+

The HealthKit quantity type to collect. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly) HKQuantityType *quantityType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  unit +

+ +
+
+ +
+ + +
+

The HealthKit unit in which to collect the answer. (read-only)

+
+ + + +
@property (nonatomic, strong, readonly, nullable) HKUnit *unit
+ + + + + + + + + +
+

Discussion

+

The unit is displayed when the user is entering data, and is also +included in the question result generated by form items or question steps +that use this answer format.

+
+ + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+ +

  numericAnswerStyle +

+ +
+
+ +
+ + +
+

The numeric answer style. (read-only)

+
+ + + +
@property (nonatomic, readonly) ORKNumericAnswerStyle numericAnswerStyle
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHealthAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorder.html new file mode 100755 index 0000000..d40611a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorder.html @@ -0,0 +1,422 @@ + + + + + + ORKHealthQuantityTypeRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthQuantityTypeRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKHealthQuantityTypeRecorder.h
ORKHealthQuantityTypeRecorder.m
+ + + + +
+ +

Overview

+

The ORKHealthQuantityTypeRecorder class represents a recorder for collecting real time sample data from HealthKit, such as heart rate, during +an active task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier:healthQuantityType:unit:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized health quantity type recorder using the specified quantity type and unit.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier healthQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

quantityType

The quantity type that should be collected during the active task.

unit

The unit for the data that should be collected and serialized.

step

The step that requested this recorder.

outputDirectory

The directory in which the HealthKit data should be stored.

+
+ + + +
+

Return Value

+

An initialized health quantity type recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKHealthQuantityTypeRecorder.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorderConfiguration.html new file mode 100755 index 0000000..9d8b937 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthQuantityTypeRecorderConfiguration.html @@ -0,0 +1,568 @@ + + + + + + ORKHealthQuantityTypeRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthQuantityTypeRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKHealthQuantityTypeRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKHealthQuantityTypeRecorderConfiguration class represents a configuration +that records data from a HealthKit quantity type during an active step.

+ +

Before you can use this configuration, you must use Xcode to enable the appropriate HealthKit entitlement +for your app.

+ +

HealthKit quantity type data is serialized to JSON and returned as an ORKFileResult object. +For details on the format, see HKSample+ORKJSONDictionary.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithIdentifier:healthQuantityType:unit: +

+ +
+
+ +
+ + +
+

Returns an initialized health quantity type recorder configuration using the specified quantity type and unit designation.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier healthQuantityType:(HKQuantityType *)quantityType unit:(HKUnit *)unit
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder configuration.

quantityType

The quantity type that should be collected during the active task.

unit

The unit for the data that should be collected and serialized.

+
+ + + +
+

Return Value

+

An initialized health quantity type recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new health quantity type recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the health quantity type recorder configuration.

+
+ + + +
+

Return Value

+

A new health quantity type recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

Returns the HealthKit types for which this recorder requires read access in a set of HKSampleType objects.

+
+ + + +
- (NSSet *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

Typically, the task view controller automatically collects +and collates the types of HealthKit data requested by each of the active steps in a task, +and requests access to them at the end of the initial instruction +steps in the task.

+ +

If your recorder requires or would benefit from read access to HealthKit at +runtime during the task, return the appropriate set of HKSampleType objects.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  quantityType +

+ +
+
+ +
+ + +
+

The quantity type to be collected from HealthKit. (read-only)

+
+ + + +
@property (nonatomic, readonly, copy) HKQuantityType *quantityType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

  unit +

+ +
+
+ +
+ + +
+

The unit in which to serialize the data from HealthKit. (read-only)

+
+ + + +
@property (nonatomic, readonly, copy) HKUnit *unit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthSampleQueryOperation.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthSampleQueryOperation.html new file mode 100755 index 0000000..090e045 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHealthSampleQueryOperation.html @@ -0,0 +1,123 @@ + + + + + + ORKHealthSampleQueryOperation Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHealthSampleQueryOperation Class Reference

+ + +
+ + + + + + + +
Inherits fromORKOperation : NSOperation
Declared inORKHealthSampleQueryOperation.h
ORKHealthSampleQueryOperation.m
+ + + + +
+ +

Overview

+

Operation for extracting and preparing HK data for upload. This operation +runs on the specified study / data type combo until there is no more HK data available, +or until file protection kicks in, stopping further preparation.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeightAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeightAnswerFormat.html new file mode 100755 index 0000000..7274263 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHeightAnswerFormat.html @@ -0,0 +1,366 @@ + + + + + + ORKHeightAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHeightAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKHeightAnswerFormat class represents the answer format for questions that require users +to enter a height.

+ +

A height answer format produces an ORKNumericQuestionResult object. The result is always reported +in the metric system using the cm unit.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– init +

+ +
+
+ +
+ + +
+

Returns an initialized height answer format using the measurement system specified in the current +locale.

+
+ + + +
- (instancetype)init
+ + + + + +
+

Return Value

+

An initialized height answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMeasurementSystem: +

+ +
+
+ +
+ + +
+

Returns an initialized height answer format using the specified measurement system.

+
+ + + +
- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem
+ + + +
+

Parameters

+ + + + + + + +
measurementSystem

The measurement system to use. See ORKMeasurementSystem for the + accepted values.

+
+ + + +
+

Return Value

+

An initialized height answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  measurementSystem +

+ +
+
+ +
+ + +
+

The measurement system used by the answer format.

+
+ + + +
@property (readonly) ORKMeasurementSystem measurementSystem
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStep.html new file mode 100755 index 0000000..efbbf72 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStep.html @@ -0,0 +1,304 @@ + + + + + + ORKHolePegTestPlaceStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestPlaceStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKHolePegTestPlaceStep.h
ORKHolePegTestPlaceStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStepViewController.html new file mode 100755 index 0000000..f28668d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestPlaceStepViewController.html @@ -0,0 +1,309 @@ + + + + + + ORKHolePegTestPlaceStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestPlaceStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKHolePegTestPlaceStepViewController.h
ORKHolePegTestPlaceStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStep.html new file mode 100755 index 0000000..a4f12a2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStep.html @@ -0,0 +1,304 @@ + + + + + + ORKHolePegTestRemoveStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestRemoveStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKHolePegTestRemoveStep.h
ORKHolePegTestRemoveStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStepViewController.html new file mode 100755 index 0000000..2c73910 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestRemoveStepViewController.html @@ -0,0 +1,309 @@ + + + + + + ORKHolePegTestRemoveStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestRemoveStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKHolePegTestRemoveStepViewController.h
ORKHolePegTestRemoveStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestResult.html new file mode 100755 index 0000000..25e1217 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestResult.html @@ -0,0 +1,578 @@ + + + + + + ORKHolePegTestResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKHolePegTestResult.h
ORKHolePegTestResult.m
+ + + + +
+ +

Overview

+

The ORKHolePegTestResult class records the results of a hole peg test.

+ +

The hole peg test result object records the number of pegs, an array of move samples, the total duration +and also various attributes of the hole peg test.

+ +

The hole peg test samples are generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize them for transmission to a server, +or to immediately perform analysis on them.

+
+ + + + + +
+ + + + + + +
+
+ +

  movingDirection +

+ +
+
+ +
+ + +
+

The hole peg test moving direction.

+
+ + + +
@property (nonatomic, assign) ORKBodySagittal movingDirection
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  dominantHandTested +

+ +
+
+ +
+ + +
+

The step is for the dominant hand.

+
+ + + +
@property (nonatomic, assign, getter=isDominantHandTested) BOOL dominantHandTested
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  numberOfPegs +

+ +
+
+ +
+ + +
+

The number of pegs to test.

+
+ + + +
@property (nonatomic, assign) NSInteger numberOfPegs
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  threshold +

+ +
+
+ +
+ + +
+

The detection area sensitivity.

+
+ + + +
@property (nonatomic, assign) double threshold
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  rotated +

+ +
+
+ +
+ + +
+

The hole peg test also assesses the rotation capabilities.

+
+ + + +
@property (nonatomic, assign, getter=isRotated) BOOL rotated
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  totalSuccesses +

+ +
+
+ +
+ + +
+

The number of succeeded moves (out of numberOfPegs possible).

+
+ + + +
@property (nonatomic, assign) NSInteger totalSuccesses
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  totalFailures +

+ +
+
+ +
+ + +
+

The number of failed moves.

+
+ + + +
@property (nonatomic, assign) NSInteger totalFailures
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  totalTime +

+ +
+
+ +
+ + +
+

The total time needed to perform the test step (ie. the sum of all samples time).

+
+ + + +
@property (nonatomic, assign) NSTimeInterval totalTime
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  totalDistance +

+ +
+
+ +
+ + +
+

The total distance needed to perform the test step (ie. the sum of all samples distance).

+
+ + + +
@property (nonatomic, assign) double totalDistance
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  samples +

+ +
+
+ +
+ + +
+

An array of collected samples, in which each item is an ORKHolePegTestSample +object that represents a peg move.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray *samples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestSample.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestSample.html new file mode 100755 index 0000000..f8ce1ad --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKHolePegTestSample.html @@ -0,0 +1,237 @@ + + + + + + ORKHolePegTestSample Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKHolePegTestSample Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKHolePegTestResult.h
ORKHolePegTestResult.m
+ + + + +
+ +

Overview

+

The ORKHolePegTestSample class represents a peg move.

+ +

The sample object records the duration, and the move distance. +An hole peg test is included in an ORKHolePegTestResult object, and is recorded +by the step view controller for the corresponding task.

+ +

An hole peg test sample is typically generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize the sample for +transmission to a server, or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  time +

+ +
+
+ +
+ + +
+

The time interval for the peg move.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval time
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+ +

  distance +

+ +
+
+ +
+ + +
+

The peg move distance.

+
+ + + +
@property (nonatomic, assign) double distance
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKHolePegTestResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBBarGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBBarGraphChartViewDataSource.html new file mode 100755 index 0000000..1b6f008 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBBarGraphChartViewDataSource.html @@ -0,0 +1,206 @@ + + + + + + ORKIBBarGraphChartViewDataSource Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKIBBarGraphChartViewDataSource Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKIBGraphChartViewDataSource : NSObject
Conforms toORKValueStackGraphChartViewDataSource
Declared inORKBarGraphChartView.m
+ + + + + + +
+ + + + + + +
+
+ +

– graphChartView:dataPointForPointIndex:plotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the value stack to be plotted at the specified point index for the +specified plot.

+
+ + + +
- (ORKValueStack *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
graphChartView

The graph chart view that is asking for the value stack.

pointIndex

An index number identifying the value stack in the graph chart view.

plotIndex

An index number identifying the plot in the graph chart view. This index +is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The value stack specified by pointIndex in the plot specified by plotIndex for the +specified graph chart view`.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBGraphChartViewDataSource.html new file mode 100755 index 0000000..4478eca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBGraphChartViewDataSource.html @@ -0,0 +1,335 @@ + + + + + + ORKIBGraphChartViewDataSource Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKIBGraphChartViewDataSource Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKGraphChartViewDataSource
Declared inORKGraphChartView.m
ORKGraphChartView_Internal.h
+ + + + + + +
+ + + + + + +
+
+ +

– numberOfPlotsInGraphChartView: +

+ +
+
+ +
+ + +
+

Asks the data source for the number of plots to be plotted by the graph chart view.

+
+ + + +
- (NSInteger)numberOfPlotsInGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the number of plots.

+
+ + + +
+

Return Value

+

The number of plots in the graph chart view.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:numberOfDataPointsForPlotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the number of value points to be plotted by the graph chart view at the +specified plot index.

+
+ + + +
- (NSInteger)graphChartView:(ORKGraphChartView *)graphChartView numberOfDataPointsForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the number of value points.

plotIndex

An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The number of range points in the plot at plotIndex.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:titleForXAxisAtPointIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the title to be displayed adjacent to each division in the x-axis (the +number returned by numberOfDivisionsInXAxisForGraphChartView:). You can return nil from this +method if you don’t want to display a title for the specified point index.

+
+ + + +
- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView titleForXAxisAtPointIndex:(NSInteger)pointIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the title.

pointIndex

The index of the specified x-axis division.

+
+ + + +
+

Return Value

+

The title string to be displayed adjacent to each division of the x-axis of the graph chart +view.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the x-axis has no titles.

+ +

See also: numberOfDivisionsInXAxisForGraphChartView:.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBPieChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBPieChartViewDataSource.html new file mode 100755 index 0000000..eb002e3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBPieChartViewDataSource.html @@ -0,0 +1,406 @@ + + + + + + ORKIBPieChartViewDataSource Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKIBPieChartViewDataSource Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKPieChartViewDataSource
Declared inORKPieChartView.m
+ + + + + + +
+ + + + + + +
+
+ +

– numberOfSegmentsInPieChartView: +

+ +
+
+ +
+ + +
+

Asks the data source for the number of segments in the pie chart view.

+
+ + + +
- (NSInteger)numberOfSegmentsInPieChartView:(ORKPieChartView *)pieChartView
+ + + +
+

Parameters

+ + + + + + + +
pieChartView

The pie chart view asking for the number of segments.

+
+ + + +
+

Return Value

+

The number of segments in the pie chart view.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:valueForSegmentAtIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the value of a segment in the pie chart view.

+
+ + + +
- (CGFloat)pieChartView:(ORKPieChartView *)pieChartView valueForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the value of the segment.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The value of the segment at the specified index in the pie chart view.

+
+ + + + + +
+

Discussion

+

The value can be any arbitrary integer: the pie chart view normalizes them by the sum of all +returned values.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:colorForSegmentAtIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the color of a segment in the pie chart view.

+
+ + + +
- (UIColor *)pieChartView:(ORKPieChartView *)pieChartView colorForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the color of the segment.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The color of the segment at the specified index in the pie chart view.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the pie chart view uses a unique shade of the current +tint color for each segment.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:titleForSegmentAtIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the title to appear in the legend for a segment in the pie chart view.

+
+ + + +
- (NSString *)pieChartView:(ORKPieChartView *)pieChartView titleForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the title.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The title of the segment at the specified index in the pie chat view’s +legend.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the pie chart view does not display the legend.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBValueRangeGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBValueRangeGraphChartViewDataSource.html new file mode 100755 index 0000000..9f895d1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKIBValueRangeGraphChartViewDataSource.html @@ -0,0 +1,206 @@ + + + + + + ORKIBValueRangeGraphChartViewDataSource Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKIBValueRangeGraphChartViewDataSource Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKIBGraphChartViewDataSource : NSObject
Conforms toORKValueRangeGraphChartViewDataSource
Declared inORKGraphChartView.m
ORKGraphChartView_Internal.h
+ + + + + + +
+ + + + + + +
+
+ +

– graphChartView:dataPointForPointIndex:plotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the value range to be plotted at the specified point index for the +specified plot.

+
+ + + +
- (ORKValueRange *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
graphChartView

The graph chart view that is asking for the value range.

pointIndex

An index number identifying the value range in the graph chart view.

plotIndex

An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The value range specified by pointIndex in the plot specified by plotIndex for the +specified graph chart view`.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStep.html new file mode 100755 index 0000000..5e18b92 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStep.html @@ -0,0 +1,481 @@ + + + + + + ORKImageCaptureStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKImageCaptureStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKImageCaptureStep.h
ORKImageCaptureStep.m
+ + + + +
+ +

Overview

+

The ORKImageCaptureStep class represents a step that captures an image through the device +camera. A template image can optionally be laid over the camera preview to assist in properly +capturing the image.

+ +

To use the image capture step, optionally set the templateImage and templateImageInsets +properties, incorporate the step into a task, and present the task with a task view controller.

+ +

If implementing an image capture task like this one, remember that people will +take your instructions literally. So be cautious. Make sure your template image +is high contrast and very visible against a variety of backgrounds.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  templateImage +

+ +
+
+ +
+ + +
+

An image to be displayed over the camera preview.

+
+ + + +
@property (nonatomic, strong) UIImage *templateImage
+ + + + + + + + + +
+

Discussion

+

The image is stretched to fit the available space while retaining its aspect ratio. +When choosing a size for this asset, be sure to take into account the variations in device +form factors.

+
+ + + + + + + +
+

Declared In

+

ORKImageCaptureStep.h

+
+ + +
+
+
+ +

  templateImageInsets +

+ +
+
+ +
+ + +
+

Insets to be used in positioning and sizing the templateImage.

+
+ + + +
@property (nonatomic) UIEdgeInsets templateImageInsets
+ + + + + + + + + +
+

Discussion

+

The insets are interpreted as percentages relative to the preview frame size. The left +and right insets are relative to the width of the preview frame. The top and bottom +insets are relative to the height of the preview frame.

+
+ + + + + + + +
+

Declared In

+

ORKImageCaptureStep.h

+
+ + +
+
+
+ +

  accessibilityInstructions +

+ +
+
+ +
+ + +
+

The accessibility hint for the capture preview.

+
+ + + +
@property (nonatomic, copy) NSString *accessibilityInstructions
+ + + + + + + + + +
+

Discussion

+

This property can be used to specify accessible instructions for capturing the image. The +use of this property can assist when the templateImage may not be visible +to the user.

+ +

For example, if you want to capture an image of the user’s right hand, you may use a template +image that displays the outline of the right hand. You may also want to set this property +to a string such as @“Extend your right hand, palm side down, one foot from your device. +Tap the Capture Image button, or two finger tap on the preview, to capture an image of your +extended right hand.”

+
+ + + + + + + +
+

Declared In

+

ORKImageCaptureStep.h

+
+ + +
+
+
+ +

  accessibilityHint +

+ +
+
+ +
+ + +
+

The accessibility hint for the capture button.

+
+ + + +
@property (nonatomic, copy) NSString *accessibilityHint
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKImageCaptureStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStepViewController.html new file mode 100755 index 0000000..6a017d7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageCaptureStepViewController.html @@ -0,0 +1,394 @@ + + + + + + ORKImageCaptureStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKImageCaptureStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKImageCaptureStepViewController.h
ORKImageCaptureStepViewController.m
+ + + + +
+ +

Overview

+

The ORKImageCaptureStepViewController class represents the step view controller that +corresponds to an ORKImageCaptureStep class.

+ +

It is not usually necessary to instantiate this view controller directly. +Instead, add an image capture step to a task, and present the task in a task +view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoice.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoice.html new file mode 100755 index 0000000..3d19dfb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoice.html @@ -0,0 +1,514 @@ + + + + + + ORKImageChoice Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKImageChoice Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKImageChoice class defines a choice that can +be included in an ORKImageChoiceAnswerFormat object.

+ +

Typically, image choices are displayed in a horizontal row, so you need to use appropriate sizes. +For example, when five image choices are displayed in an ORKImageChoiceAnswerFormat, image sizes +of about 45 to 60 points allow the images to look good in apps that run on all versions of iPhone.

+ +

The text that describes an image choice should be reasonably short. However, only the text for the +currently selected image choice is displayed, so text that wraps to more than one line +is supported.

+
+ + + + + +
+ + + + + + +
+
+ +

+ choiceWithNormalImage:selectedImage:text:value: +

+ +
+
+ +
+ + +
+

Returns an image choice that includes the specified images and text.

+
+ + + +
+ (instancetype)choiceWithNormalImage:(nullable UIImage *)normal selectedImage:(nullable UIImage *)selected text:(nullable NSString *)text value:(id<NSCopying,NSCoding,NSObject>)value
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
normal

The image to display in the unselected state.

selected

The image to display in the selected state.

text

The text to display when the image is selected.

value

The value to record in a result object when the image is selected.

+
+ + + +
+

Return Value

+

An image choice instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithNormalImage:selectedImage:text:value: +

+ +
+
+ +
+ + +
+

Returns an initialized image choice using the specified images and text.

+
+ + + +
- (instancetype)initWithNormalImage:(nullable UIImage *)normal selectedImage:(nullable UIImage *)selected text:(nullable NSString *)text value:(id<NSCopying,NSCoding,NSObject>)value
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
normal

The image to display in the unselected state.

selected

The image to display in the selected state.

text

The text to display when the image is selected.

value

The value to record in a result object when the image is selected.

+
+ + + +
+

Return Value

+

An initialized image choice.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  normalStateImage +

+ +
+
+ +
+ + +
+

The image to display when the choice is not selected. (read-only)

+
+ + + +
@property (strong, readonly) UIImage *normalStateImage
+ + + + + + + + + +
+

Discussion

+

The size of the unselected image depends on the number of choices you need to display. As a +general rule, it’s recommended that you start by creating an image that measures 44 x 44 points, +and adjust it if necessary.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  selectedStateImage +

+ +
+
+ +
+ + +
+

The image to display when the choice is selected. (read-only)

+
+ + + +
@property (strong, readonly, nullable) UIImage *selectedStateImage
+ + + + + + + + + +
+

Discussion

+

For best results, the selected image should be the same size as the unselected image (that is, +the value of the normalStateImage property). +If you don’t specify a selected image, the default UIButton behavior is used to +indicate the selection state of the item.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

The text to display when the image is selected, in a localized string. (read-only)

+
+ + + +
@property (copy, readonly, nullable) NSString *text
+ + + + + + + + + +
+

Discussion

+

Note that the text you supply may be spoken by VoiceOver even when the item is not selected.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  value +

+ +
+
+ +
+ + +
+

The value to return when the image is selected. (read-only)

+
+ + + +
@property (copy, readonly) id<NSCopying,NSCoding,NSObject> value
+ + + + + + + + + +
+

Discussion

+

The value of this property is expected to be a scalar property list type, such as NSNumber or +NSString. If no value is provided, the index of the option in the ORKImageChoiceAnswerFormat +options list is used.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceAnswerFormat.html new file mode 100755 index 0000000..d3642f3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceAnswerFormat.html @@ -0,0 +1,527 @@ + + + + + + ORKImageChoiceAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKImageChoiceAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKImageChoiceAnswerFormat class represents an answer format that lets participants choose +one image from a fixed set of images in a single choice question.

+ +

For example, you might use the image choice answer format to represent a range of moods that range +from very sad +to very happy.

+ +

The image choice answer format produces an ORKChoiceQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithImageChoices: +

+ +
+
+ +
+ + +
+

Returns an initialized image choice answer format using the specified array of images.

+
+ + + +
- (instancetype)initWithImageChoices:(NSArray<ORKImageChoice*> *)imageChoices
+ + + +
+

Parameters

+ + + + + + + +
imageChoices

Array of ORKImageChoice objects.

+
+ + + +
+

Return Value

+

An initialized image choice answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithImageChoices:style:vertical: +

+ +
+
+ +
+ + +
+

Returns an initialized image choice answer format using the specified array of images.

+
+ + + +
- (instancetype)initWithImageChoices:(NSArray<ORKImageChoice*> *)imageChoices style:(ORKChoiceAnswerStyle)style vertical:(BOOL)vertical
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
imageChoices

Array of ORKImageChoice objects.

style

The style of question, such as single or multiple choice.

vertical

Pass YES to stack images vertically; for the default horizontal +layout, pass NO.

+
+ + + +
+

Return Value

+

An initialized image choice answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  imageChoices +

+ +
+
+ +
+ + +
+

An array of ORKImageChoice objects that represent the available choices. (read-only)

+
+ + + +
@property (copy, readonly) NSArray<ORKImageChoice*> *imageChoices
+ + + + + + + + + +
+

Discussion

+

The text of the currently selected choice is displayed on screen. The text for +each choice is spoken by VoiceOver when an image is highlighted.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  style +

+ +
+
+ +
+ + +
+

The style of the question (that is, single or multiple choice).

+
+ + + +
@property (readonly) ORKChoiceAnswerStyle style
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  vertical +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the choices are stacked vertically. (read-only)

+
+ + + +
@property (readonly, getter=isVertical) BOOL vertical
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceLabel.html new file mode 100755 index 0000000..92733a1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKImageChoiceLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKImageChoiceLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKImageChoiceLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKImageChoiceLabel.h
ORKImageChoiceLabel.m
+ + + + +
+ +

Overview

+

Text label under image answer option icon

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStep.html new file mode 100755 index 0000000..f9287a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStep.html @@ -0,0 +1,530 @@ + + + + + + ORKInstructionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKInstructionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKInstructionStep.h
ORKInstructionStep.m
+ + + + +
+ +

Overview

+

An ORKInstructionStep object gives the participant instructions for a task.

+ +

You can use instruction steps to present various types of content during a task, such as +introductory content, instructions in the middle +of a task, or a final message at the completion of a task.

+ +

To indicate the completion of a task, consider using an ORKCompletionStep object instead.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  detailText +

+ +
+
+ +
+ + +
+

Additional detailed explanation for the instruction.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *detailText
+ + + + + + + + + +
+

Discussion

+

The detail text is displayed below the content of the text property.

+
+ + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+ +

  attributedDetailText +

+ +
+
+ +
+ + +
+

Additional attributed explanation for the instruction.

+
+ + + +
@property (nonatomic, copy, nullable) NSAttributedString *attributedDetailText
+ + + + + + + + + +
+

Discussion

+

The attributed detail text is displayed below the content of the text property and overrides detailText.

+
+ + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+ +

  footnote +

+ +
+
+ +
+ + +
+

Additional text to display for the step in a localized string at the bottom of the view.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *footnote
+ + + + + + + + + +
+

Discussion

+

The footnote is displayed in a smaller font below the continue button. It is intended to be used +in order to include disclaimer, copyright, etc. that is important to display in the step but +should not distract from the main purpose of the step.

+
+ + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+ +

  image +

+ +
+
+ +
+ + +
+

An image that provides visual context for the instruction.

+
+ + + +
@property (nonatomic, copy, nullable) UIImage *image
+ + + + + + + + + +
+

Discussion

+

The image is displayed with aspect fit. Depending on the device, the screen area +available for this image can vary. For exact +metrics, see ORKScreenMetricIllustrationHeight.

+
+ + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+ +

  auxiliaryImage +

+ +
+
+ +
+ + +
+

An image that provides visual context for the instruction that will allow for showing +a two-part composite image where the image is tinted and the auxiliaryImage is +shown with light grey.

+
+ + + +
@property (nonatomic, copy, nullable) UIImage *auxiliaryImage
+ + + + + + + + + +
+

Discussion

+

The image is displayed with the same frame as the image so both the auxiliaryImage +and image should have transparently to allow for overlay.

+
+ + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+ +

  iconImage +

+ +
+
+ +
+ + +
+

Optional icon image to show above the title and text.

+
+ + + +
@property (nonatomic, copy, nullable) UIImage *iconImage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKInstructionStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStepViewController.html new file mode 100755 index 0000000..e040267 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKInstructionStepViewController.html @@ -0,0 +1,206 @@ + + + + + + ORKInstructionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKInstructionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKInstructionStepViewController.h
ORKInstructionStepViewController.m
+ + + + +
+ +

Overview

+

An ORKInstructionStepViewController object is the view controller for an ORKInstructionStep object.

+ +

In general, you don’t need to instantiate an instruction step view controller directly. +Instead, add an instruction step to a task and present the task using a +task view controller. When appropriate, the task view controller instantiates the step +view controller for the step.

+
+ + + + + +
+ + + + + + +
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKJSONLogFormatter.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKJSONLogFormatter.html new file mode 100755 index 0000000..0bfb382 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKJSONLogFormatter.html @@ -0,0 +1,476 @@ + + + + + + ORKJSONLogFormatter Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKJSONLogFormatter Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLogFormatter : NSObject
Declared inORKDataLogger.h
ORKDataLogger.m
+ + + + +
+ +

Overview

+

The ORKJSONLogFormatter class represents a log formatter for producing JSON output.

+ +

The JSON log formatter accepts NSDictionary objects for serialization. +The JSON output is a dictionary that contains one key, items, +which contains the array of logged items. The log itself does not contain +any timestamp information, so the items should include such fields, +if desired.

+
+ + + + + +
+ + + + + + +
+
+ +

– canAcceptLogObjectOfClass: +

+ +
+
+ +
+ + +
+

Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object.

+
+ + + +
- (BOOL)canAcceptLogObjectOfClass:(Class)c
+ + + +
+

Parameters

+ + + + + + + +
c

The class of object to serialize.

+
+ + + +
+

Return Value

+

YES if the log formatter can serialize this object class; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– canAcceptLogObject: +

+ +
+
+ +
+ + +
+

Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object.

+
+ + + +
- (BOOL)canAcceptLogObject:(id)object
+ + + +
+

Parameters

+ + + + + + + +
object

The object to serialize.

+
+ + + +
+

Return Value

+

YES if the log formatter can serialize object; otherwise, NO

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– beginLogWithFileHandle:error: +

+ +
+
+ +
+ + +
+

Begins a new log file on the specified file handle.

+
+ + + +
- (BOOL)beginLogWithFileHandle:(NSFileHandle *)fileHandle error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

For example, may write a header or opening stanza of a new log file.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– appendObject:fileHandle:error: +

+ +
+
+ +
+ + +
+

Appends the specified object to the log file.

+
+ + + +
- (BOOL)appendObject:(id)object fileHandle:(NSFileHandle *)fileHandle error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
object

The object to write.

fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– appendObjects:fileHandle:error: +

+ +
+
+ +
+ + +
+

Appends the specified objects to the log file.

+
+ + + +
- (BOOL)appendObjects:(NSArray *)objects fileHandle:(NSFileHandle *)fileHandle error:(NSError *__autoreleasing *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
objects

The objects to write.

fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeyValueStepModifier.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeyValueStepModifier.html new file mode 100755 index 0000000..957e82c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeyValueStepModifier.html @@ -0,0 +1,438 @@ + + + + + + ORKKeyValueStepModifier Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKKeyValueStepModifier Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepModifier : NSObject
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKKeyValueStepModifier class is an class for an object that can be used to modify a step +if a given navigation rule is matched.

+ +

Step modifiers can be used within an ORKNavigableOrderedTask object. You assign step modifiers +to be triggered after a task step is shown. Each step can have one step modifier at most.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  resultPredicate +

+ +
+
+ +
+ + +
+

The result predicate to match.

+
+ + + +
@property (nonatomic, strong, readonly) NSPredicate *resultPredicate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  keyValueMap +

+ +
+
+ +
+ + +
+

A key-value mapping to apply to the modified step if the result predicate matches. +The keys in this are assumed to map using key-value coding.

+
+ + + +
@property (nonatomic, strong, readonly) NSDictionary<NSString*NSObject*> *keyValueMap
+ + + + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithResultPredicate:keyValueMap: +

+ +
+
+ +
+ + +
+

Returns a new step modifier.

+
+ + + +
- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate keyValueMap:(NSDictionary<NSString*,NSObject*> *)keyValueMap
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultPredicate

The result predicate to use to determine if the step should be modified

keyValueMap

The mapping dictionary for this object

stepIdentifier

The step identifier for the step to modify

+
+ + + +
+

Return Value

+

A new step modifier

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new step modifier.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the step navigation rule.

+
+ + + +
+

Return Value

+

A new step modifier

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– modifyStep:withTaskResult: +

+ +
+
+ +
+ + +
+

Modify the steps for a task.

+
+ + + +
- (void)modifyStep:(ORKStep *)step withTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step that is associated with this modifier

taskResult

The current task result

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeychainWrapper.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeychainWrapper.html new file mode 100755 index 0000000..313439b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKKeychainWrapper.html @@ -0,0 +1,409 @@ + + + + + + ORKKeychainWrapper Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKKeychainWrapper Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKKeychainWrapper.h
ORKKeychainWrapper.m
+ + + + +
+ +

Overview

+

The ORKKeychainWrapper class is an abstraction layer for the iOS keychain +communication.

+
+ + + + + +
+ + + + + + +
+
+ +

+ setObject:forKey:error: +

+ +
+
+ +
+ + +
+

Sets the given object in the keychain for the provided key.

+
+ + + +
+ (BOOL)setObject:(id<NSSecureCoding>)object forKey:(NSString *)key error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
object

The data to be stored in the keychain.

key

The key used to set the data in the keychain.

error

If failure occurred, an NSError object indicating the reason for the + failure. The value of this parameter is nil if result does not + indicate failure.

+
+ + + +
+

Return Value

+

A boolean with a value YES if the object was saved; otherwise `NO'.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKKeychainWrapper.h

+
+ + +
+
+
+ +

+ objectForKey:error: +

+ +
+
+ +
+ + +
+

Returns the object in the keychain for the provided key.

+
+ + + +
+ (nullable id<NSSecureCoding>)objectForKey:(nonnull NSString *)key error:(NSError *__autoreleasing _Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
key

The key used to set the data in the keychain.

error

If failure occurred, an NSError object indicating the reason for the + failure. The value of this parameter is nil if result does not + indicate failure.

+
+ + + +
+

Return Value

+

An object or nil if key is not valid.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKKeychainWrapper.h

+
+ + +
+
+
+ +

+ removeObjectForKey:error: +

+ +
+
+ +
+ + +
+

Removes the object in the keychain for the provided key.

+
+ + + +
+ (BOOL)removeObjectForKey:(NSString *)key error:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
key

The key used to set the value in the keychain.

error

If failure occurred, an NSError object indicating the reason for the + failure. The value of this parameter is nil if result does not + indicate failure.

+
+ + + +
+

Return Value

+

A boolean with a value YES if the object was removed; otherwise `NO'.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKKeychainWrapper.h

+
+ + +
+
+
+ +

+ resetKeychainWithError: +

+ +
+
+ +
+ + +
+

Removes all values stored in the keychain for the app.

+
+ + + +
+ (BOOL)resetKeychainWithError:(NSError *_Nullable *)error
+ + + +
+

Parameters

+ + + + + + + +
error

If failure occurred, an NSError object indicating the reason for the + failure. The value of this parameter is nil if result does not + indicate failure.

+
+ + + +
+

Return Value

+

A boolean with a value YES if the keychain was reset; otherwise `NO'.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKKeychainWrapper.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLabel.html new file mode 100755 index 0000000..3ebacbb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLabel.html @@ -0,0 +1,124 @@ + + + + + + ORKLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLabel Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromUILabel
Conforms toORKDefaultFont
Declared inORKLabel.h
ORKLabel.m
+ + + + +
+ +

Overview

+

This is a base class, not being used directly.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLineGraphChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLineGraphChartView.html new file mode 100755 index 0000000..7683853 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLineGraphChartView.html @@ -0,0 +1,125 @@ + + + + + + ORKLineGraphChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLineGraphChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromORKValueRangeGraphChartView : ORKGraphChartView : UIView
Declared inORKLineGraphChartView.h
ORKLineGraphChartView.m
+ + + + +
+ +

Overview

+

The ORKLineGraphChartView class presents the data provided by an object conforming to the +ORKValueRangeGraphChartViewDataSource protocol as a line graph.

+ +

The primary plot is colored by the tintColor, and any additional plots are colored using the +referenceLineColor property.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocation.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocation.html new file mode 100755 index 0000000..4052ad5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocation.html @@ -0,0 +1,315 @@ + + + + + + ORKLocation Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLocation Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKLocation class represents the location addess obtained from a locaton question.

+
+ + + + + +
+ + + + + + +
+
+ +

  coordinate +

+ +
+
+ +
+ + +
+

The geographical coordinate information.

+
+ + + +
@property (nonatomic, readonly) CLLocationCoordinate2D coordinate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  region +

+ +
+
+ +
+ + +
+

The region describes the size of the placemark of the location.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) CLCircularRegion *region
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  userInput +

+ +
+
+ +
+ + +
+

The human readable address typed in by user.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSString *userInput
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  addressDictionary +

+ +
+
+ +
+ + +
+

The address dicitonary for this coordinate from MapKit.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSDictionary *addressDictionary
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationAnswerFormat.html new file mode 100755 index 0000000..d653fc0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationAnswerFormat.html @@ -0,0 +1,255 @@ + + + + + + ORKLocationAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLocationAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKLocationAnswerFormat class represents the answer format for questions that collect a location response +from the user.

+ +

An ORKLocationAnswerFormat object produces an ORKLocationQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  useCurrentLocation +

+ +
+
+ +
+ + +
+

Indicates whether or not the user’s current location should be automatically entered the first time they tap on the input field.

+
+ + + +
@property (nonatomic, assign) BOOL useCurrentLocation
+ + + + + + + + + +
+

Discussion

+

By default, this value is YES.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationQuestionResult.html new file mode 100755 index 0000000..a55d6f5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationQuestionResult.html @@ -0,0 +1,190 @@ + + + + + + ORKLocationQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLocationQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKLocationQuestionResult class represents the result of a question or form item that asks for a location (ORKLocationAnswerFormat).

+ +

A Location question result is produced by the task view controller when it presents a question or form +item with a Location answer format (that is, ORKLocationAnswerFormat).

+ +

A Location question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  locationAnswer +

+ +
+
+ +
+ + +
+

The answer representing the coordinate and the address of a specific location.

+
+ + + +
@property (nonatomic, copy, nullable) ORKLocation *locationAnswer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorder.html new file mode 100755 index 0000000..944d203 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorder.html @@ -0,0 +1,471 @@ + + + + + + ORKLocationRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLocationRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKLocationRecorder.h
ORKLocationRecorder.m
+ + + + +
+ +

Overview

+

The ORKLocationRecorder class represents a recorder for collecting location data from CoreLocation.

+ +

Because location data is sensitive information, you need to take special care in handling it, including removoing or otherwise preparing it for a +anonymous data set.

+ +

The accuracy of location data may be limited indoors.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized location recorder.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier step:(nullable ORKStep *)step outputDirectory:(nullable NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

step

The step that requested this recorder.

outputDirectory

The directory in which the location data should be stored.

+
+ + + +
+

Return Value

+

An initialized location recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKLocationRecorder.h

+
+ + +
+
+
+ +

  locationManager +

+ +
+
+ +
+ + +
+

The location manager, if any, being used by this recorder.

+
+ + + +
@property (nonatomic, strong, nullable, readonly) CLLocationManager *locationManager
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKLocationRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorderConfiguration.html new file mode 100755 index 0000000..5f1f47d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLocationRecorderConfiguration.html @@ -0,0 +1,394 @@ + + + + + + ORKLocationRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLocationRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKLocationRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKLocationRecorderConfiguration class represents a configuration +that records location data during an active step.

+ +

The location data reported is the location provided by CoreLocation.

+ +

If this configuration is included in an active step in a task, the task +view controller requests access to location data at the end of the +initial instruction steps in the task.

+ +

Location data is serialized to JSON and returned as an ORKFileResult object. +For details on the format, see CLLocation+ORKJSONDictionary.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+ +

No additional parameters besides the identifier are required.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized location recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized location recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new location recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the location recorder configuration.

+
+ + + +
+

Return Value

+

A new location recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLogFormatter.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLogFormatter.html new file mode 100755 index 0000000..7882d40 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLogFormatter.html @@ -0,0 +1,478 @@ + + + + + + ORKLogFormatter Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLogFormatter Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKDataLogger.h
ORKDataLogger.m
+ + + + +
+ +

Overview

+

The ORKLogFormatter class represents the base (default) log formatter, which appends data +blindly to a log file.

+ +

A log formatter is used by a data logger to format objects +for output to the log, and to begin a new log file and end an existing log file. +ORKLogFormatter accepts NSData and has neither a header nor a footer.

+ +

A log formatter should ensure that the log is always in a valid state, so that +even if the app is killed, the log is still readable.

+
+ + + + + +
+ + + + + + +
+
+ +

– canAcceptLogObjectOfClass: +

+ +
+
+ +
+ + +
+

Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object.

+
+ + + +
- (BOOL)canAcceptLogObjectOfClass:(Class)c
+ + + +
+

Parameters

+ + + + + + + +
c

The class of object to serialize.

+
+ + + +
+

Return Value

+

YES if the log formatter can serialize this object class; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– canAcceptLogObject: +

+ +
+
+ +
+ + +
+

Returns a Boolean value that indicates whether the log formatter can serialize the specified type of object.

+
+ + + +
- (BOOL)canAcceptLogObject:(id)object
+ + + +
+

Parameters

+ + + + + + + +
object

The object to serialize.

+
+ + + +
+

Return Value

+

YES if the log formatter can serialize object; otherwise, NO

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– beginLogWithFileHandle:error: +

+ +
+
+ +
+ + +
+

Begins a new log file on the specified file handle.

+
+ + + +
- (BOOL)beginLogWithFileHandle:(NSFileHandle *)fileHandle error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + +
+

Discussion

+

For example, may write a header or opening stanza of a new log file.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– appendObject:fileHandle:error: +

+ +
+
+ +
+ + +
+

Appends the specified object to the log file.

+
+ + + +
- (BOOL)appendObject:(id)object fileHandle:(NSFileHandle *)fileHandle error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
object

The object to write.

fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– appendObjects:fileHandle:error: +

+ +
+
+ +
+ + +
+

Appends the specified objects to the log file.

+
+ + + +
- (BOOL)appendObjects:(NSArray *)objects fileHandle:(NSFileHandle *)fileHandle error:(NSError **)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
objects

The objects to write.

fileHandle

The file handle to which to write.

error

The error output, on failure.

+
+ + + +
+

Return Value

+

YES if the write succeeds; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStep.html new file mode 100755 index 0000000..a4c1172 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStep.html @@ -0,0 +1,572 @@ + + + + + + ORKLoginStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLoginStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStep : ORKStep : NSObject
Declared inORKLoginStep.h
ORKLoginStep.m
+ + + + +
+ +

Overview

+

The ORKLoginStep class represents a form step that provides fields commonly used +for account login.

+ +

The login step contains email and password fields.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:title:text: +

+ +
+
+ +
+ + +
+

Returns an initialized form step using the specified identifier, title, and text.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(nullable NSString *)title text:(nullable NSString *)text
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

+
+ + + +
+

Return Value

+

As initialized form step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:title:text:loginViewControllerClass: +

+ +
+
+ +
+ + +
+

Returns an initialized login step using the specified identifier, title, text, and options.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(nullable NSString *)title text:(nullable NSString *)text loginViewControllerClass:(Class)loginViewControllerClass
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

loginViewControllerClass

The subclassed login step view controller class.

+
+ + + +
+

Return Value

+

An initialized login step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKLoginStep.h

+
+ + +
+
+
+ +

  loginViewControllerClass +

+ +
+
+ +
+ + +
+

The view controller subclass used for the step.

+
+ + + +
@property (nonatomic, readonly) Class loginViewControllerClass
+ + + + + + + + + +
+

Discussion

+

The subclass allows you to override button actions in order to provide navigation logic +for the button items on the step.

+
+ + + + + + + +
+

Declared In

+

ORKLoginStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– stepViewControllerClass +

+ +
+
+ +
+ + + + +
- (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– isOptional +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the user can skip the step +without providing an answer.

+
+ + + +
- (BOOL)isOptional
+ + + + + + + + + +
+

Discussion

+

The default value of this property is YES. When the value is NO, the Skip button does not +appear on this step.

+ +

This property may not be meaningful for all steps; for example, an active step +might not provide a way to skip, because it requires a timer to finish.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStepViewController.html new file mode 100755 index 0000000..e4fa28a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKLoginStepViewController.html @@ -0,0 +1,262 @@ + + + + + + ORKLoginStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKLoginStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStepViewController : ORKStepViewController : UIViewController
Declared inORKLoginStepViewController.h
ORKLoginStepViewController.m
+ + + + +
+ +

Overview

+

The ORKLoginStepViewController class is the concrete ORKStepViewController +implementation for ORKLoginStep.

+ +

You should subclass a login step view controller and override the button action +methods to provide your navigation logic. All override methods are required.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– forgotPasswordButtonTapped +

+ +
+
+ +
+ + +
+

Action method for the forgot password button.

+
+ + + +
- (void)forgotPasswordButtonTapped
+ + + + + + + + + +
+

Discussion

+

The forgot password button is shown in place of the skip button. +Override this method to provide custom logic for the button action.

+
+ + + + + + + +
+

Declared In

+

ORKLoginStepViewController.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityCollector.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityCollector.html new file mode 100755 index 0000000..a1dd650 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityCollector.html @@ -0,0 +1,297 @@ + + + + + + ORKMotionActivityCollector Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKMotionActivityCollector Class Reference

+ + +
+ + + + + + + +
Inherits fromORKCollector : NSObject
Declared inORKCollector.h
ORKCollector.m
+ + + + +
+ +

Overview

+

ORKHealthCollector collects CMMotionActivity.

+ +

It cannot be initiated directly. +Use addMotionActivityCollectorWithStartDate:to add one to a ORKDataCollectionManager.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– serializableObjectsForObjects: +

+ +
+
+ +
+ + +
+

Serialization helper that produces objects suitable for serialization to JSON.

+
+ + + +
- (NSArray *)serializableObjectsForObjects:(NSArray<CMMotionActivity*> *)objects
+ + + + + +
+

Return Value

+

Serializable dictionary objects.

+
+ + + + + +
+

Discussion

+

Subclasses should implement to provide a default JSON serialization for upload. +Called by serializedDataForObjects:.

+ +

@params objects The objects to be serialized.

+
+ + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  startDate +

+ +
+
+ +
+ + +
+

Samples should be collected starting at this date.

+
+ + + +
@property (copy, readonly) NSDate *startDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+ +

  lastDate +

+ +
+
+ +
+ + +
+

Last anchor already seen.

+
+ + + +
@property (copy, readonly) NSDate *lastDate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCollector.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityQueryOperation.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityQueryOperation.html new file mode 100755 index 0000000..ca44799 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMotionActivityQueryOperation.html @@ -0,0 +1,122 @@ + + + + + + ORKMotionActivityQueryOperation Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKMotionActivityQueryOperation Class Reference

+ + +
+ + + + + + + +
Inherits fromORKOperation : NSOperation
Declared inORKMotionActivityQueryOperation.h
ORKMotionActivityQueryOperation.m
+ + + + +
+ +

Overview

+

Operation for extracting and preparing CoreMotion data for upload. This operation +runs until there is no more CoreMotion data available, or until otherwise stopped.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleComponentQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleComponentQuestionResult.html new file mode 100755 index 0000000..fea0589 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleComponentQuestionResult.html @@ -0,0 +1,239 @@ + + + + + + ORKMultipleComponentQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKMultipleComponentQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKMultipleComponentQuestionResult class represents the choice +answers from a multiple-component picker-style choice-based answer format.

+ +

For example, an ORKMultipleValuePickerAnswerFormat produces an ORKMultipleComponentQuestionResult object.

+ +

A multiple component question result is typically generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  componentsAnswer +

+ +
+
+ +
+ + +
+

An array of selected components, from the value property of an ORKTextChoice object. +The array will have the same count as the number of components.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray *componentsAnswer
+ + + + + + + + + +
+

Discussion

+

If the user skipped the question, the value of the corresponding array member is nil.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  separator +

+ +
+
+ +
+ + +
+

The string separator used to join the components (if applicable)

+
+ + + +
@property (nonatomic, copy, nullable) NSString *separator
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleValuePickerAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleValuePickerAnswerFormat.html new file mode 100755 index 0000000..31ff424 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKMultipleValuePickerAnswerFormat.html @@ -0,0 +1,473 @@ + + + + + + ORKMultipleValuePickerAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKMultipleValuePickerAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKMultipleValuePickerAnswerFormat class represents an answer format that lets participants use a +multiple-component value picker to choose from a fixed set of text choices.

+ +

Note that the multiple value picker answer format reports itself as being of the multiple picker question +type. The multiple-component value picker answer format produces an ORKMultipleComponentQuestionResult +object where the index into the array matches the array of ORKValuePickerAnswerFormat objects.

+ +

For example, if the picker shows two columns with choices of [[A, B, C], [1, 2, 3, 4]] and the user picked +B and 3 then this would result in componentsAnswer = [B, 3].

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithValuePickers: +

+ +
+
+ +
+ + +
+

Returns a multiple value picker answer format using the specified array of value pickers.

+
+ + + +
- (instancetype)initWithValuePickers:(NSArray<ORKValuePickerAnswerFormat*> *)valuePickers
+ + + +
+

Parameters

+ + + + + + + +
valuePickers

Array of ORKValuePickerAnswerFormat objects.

+
+ + + +
+

Return Value

+

An initialized multiple value picker answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithValuePickers:separator: +

+ +
+
+ +
+ + +
+

Returns a multiple value picker answer format using the specified array of value pickers.

+
+ + + +
- (instancetype)initWithValuePickers:(NSArray<ORKValuePickerAnswerFormat*> *)valuePickers separator:(NSString *)separator
+ + + +
+

Parameters

+ + + + + + + + + + + + +
valuePickers

Array of ORKValuePickerAnswerFormat objects.

separator

String used to separate the components

+
+ + + +
+

Return Value

+

An initialized multiple value picker answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  valuePickers +

+ +
+
+ +
+ + +
+

An array of value pickers that represent the options to display in the picker. (read-only)

+
+ + + +
@property (copy, readonly) NSArray<ORKValuePickerAnswerFormat*> *valuePickers
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  separator +

+ +
+
+ +
+ + +
+

A string used to define the separator for the format of the string. Default = “ ”.

+
+ + + +
@property (copy, readonly) NSString *separator
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigableOrderedTask.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigableOrderedTask.html new file mode 100755 index 0000000..352b7e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigableOrderedTask.html @@ -0,0 +1,1160 @@ + + + + + + ORKNavigableOrderedTask Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNavigableOrderedTask Class Reference

+ + +
+ + + + + + + +
Inherits fromORKOrderedTask : NSObject
Declared inORKNavigableOrderedTask.h
ORKNavigableOrderedTask.m
+ + + + +
+ +

Overview

+

The ORKNavigableOrderedTask class adds conditional step navigation to the behavior inherited from +the ORKOrderedTask class.

+ +

For implementing conditional task navigation, you must instantiate concrete subclasses of +ORKStepNavigationRule and ORKSkipStepNavigationRule and attach them to trigger steps by using +the setNavigationRule:forTriggerStepIdentifier: and setSkipNavigationRule:forStepIdentifier: +methods.

+ +

For example, if you want to display a survey question only when the user answered Yes to a previous +question you can use ORKPredicateStepNavigationRule; or if you want to define an arbitrary jump +between two steps you can use ORKDirectStepNavigationRule. You can also optionally omit steps by +using ORKPredicateSkipStepNavigationRule objects.

+ +

Note that each step in the task can have at most one attached navigation rule and one attached skip +navigation rule.

+ +

Navigable ordered tasks support looping over previously visited steps. Note, however, that results +for steps that are visited more than once will be ovewritten when you revisit the step on the loop. +Thus, going over a loop will produce duplicate results within the task results for the steps that +are seen more than once, but all the duplicate step results will point to the same result instance: +the one corresponding to the last time you visited the step.

+ +

The same applies when navigating backwards over looped steps: only your last valid answer is shown +every time you encounter a revisited step.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– setNavigationRule:forTriggerStepIdentifier: +

+ +
+
+ +
+ + +
+

Adds a navigation rule for a trigger step identifier.

+
+ + + +
- (void)setNavigationRule:(ORKStepNavigationRule *)stepNavigationRule forTriggerStepIdentifier:(NSString *)triggerStepIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepNavigationRule

The step navigation rule to be used when navigating forward from the + trigger step. A strong reference to the rule is kept by the + task.

triggerStepIdentifier

The identifier of the step that triggers the rule.

+
+ + + + + + + +
+

Discussion

+

The rule will be used to obtain a new destination step when the participant goes forward from the +trigger step. You cannot add two different navigation rules to the same trigger step identifier; +only the most recently added rule is kept.

+
+ + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– navigationRuleForTriggerStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns the step navigation rule associated with a trigger step identifier, or nil if there is +no rule associated with that step identifier.

+
+ + + +
- (nullable ORKStepNavigationRule *)navigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
triggerStepIdentifier

The identifier of the step whose rule you want to retrieve.

+
+ + + +
+

Return Value

+

A step navigation rule, or nil if the trigger step identifier has none.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– removeNavigationRuleForTriggerStepIdentifier: +

+ +
+
+ +
+ + +
+

Removes the navigation rule, if any, associated with the specified trigger step identifier.

+
+ + + +
- (void)removeNavigationRuleForTriggerStepIdentifier:(NSString *)triggerStepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
triggerStepIdentifier

The identifier of the step whose rule is to be removed.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

  stepNavigationRules +

+ +
+
+ +
+ + +
+

A dictionary of step navigation rules in the task, keyed by trigger step identifier.

+
+ + + +
@property (nonatomic, copy, readonly) NSDictionary<NSString*ORKStepNavigationRule*> *stepNavigationRules
+ + + + + + + + + +
+

Discussion

+

Each object in the dictionary should be a ORKStepNavigationRule subclass.

+
+ + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– setSkipNavigationRule:forStepIdentifier: +

+ +
+
+ +
+ + +
+

Adds a skip step navigation rule for a step identifier.

+
+ + + +
- (void)setSkipNavigationRule:(ORKSkipStepNavigationRule *)skipStepNavigationRule forStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
skipStepNavigationRule

The skip step navigation rule to be used to determine if the + step should be skipped. A strong reference to the rule is + kept by the task.

stepIdentifier

The identifier of the step that is checked against the skip + rule.

+
+ + + + + + + +
+

Discussion

+

The rule will be used to decide if the identified step needs to be skipped. You cannot add two +different skip navigation rules to the same step identifier; only the most recently added rule is +kept.

+
+ + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– skipNavigationRuleForStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns the skip step navigation rule associated with a step identifier, or nil if there is no +skip rule associated with that step identifier.

+
+ + + +
- (nullable ORKSkipStepNavigationRule *)skipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier of the step whose skip rule you want to retrieve.

+
+ + + +
+

Return Value

+

A skip step navigation rule, or nil if the step identifier has none.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– removeSkipNavigationRuleForStepIdentifier: +

+ +
+
+ +
+ + +
+

Removes the skip step navigation rule, if any, associated with the specified step identifier.

+
+ + + +
- (void)removeSkipNavigationRuleForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier of the step whose rule is to be removed.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

  skipStepNavigationRules +

+ +
+
+ +
+ + +
+

A dictionary of step navigation rules in the task, keyed by trigger step identifier.

+
+ + + +
@property (nonatomic, copy, readonly) NSDictionary<NSString*ORKSkipStepNavigationRule*> *skipStepNavigationRules
+ + + + + + + + + +
+

Discussion

+

Each object in the dictionary should be a ORKStepNavigationRule subclass.

+
+ + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– setStepModifier:forStepIdentifier: +

+ +
+
+ +
+ + +
+

Adds a step modifier for a step identifier.

+
+ + + +
- (void)setStepModifier:(ORKStepModifier *)stepModifier forStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepModifier

The step modifier associated with this step

stepIdentifier

The identifier of the step that is checked against the skip +rule.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– stepModifierForStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns the step modifier associated with a step identifier, or nil if there is no +step modifier associated with that step identifier.

+
+ + + +
- (nullable ORKStepModifier *)stepModifierForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier of the step to be modified

+
+ + + +
+

Return Value

+

A step modifier, or nil if the step identifier has none.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

– removeStepModifierForStepIdentifier: +

+ +
+
+ +
+ + +
+

Removes the step modifier, if any, associated with the specified step identifier.

+
+ + + +
- (void)removeStepModifierForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier of the step whose rule is to be removed.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

  stepModifiers +

+ +
+
+ +
+ + +
+

A dictionary of step modifiers in the task, keyed by trigger step identifier.

+
+ + + +
@property (nonatomic, copy, readonly) NSDictionary<NSString*ORKStepModifier*> *stepModifiers
+ + + + + + + + + +
+

Discussion

+

Each object in the dictionary should be a ORKStepModifier subclass.

+
+ + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+ +

  shouldReportProgress +

+ +
+
+ +
+ + +
+

Determines whether the task should report its progress as a linear ordered task or not. +The default value of this property is NO.

+
+ + + +
@property (nonatomic) BOOL shouldReportProgress
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKNavigableOrderedTask.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:steps: +

+ +
+
+ +
+ + +
+

Returns an initialized ordered task using the specified identifier and array of steps.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray<ORKStep*> *)steps
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier for the task.

steps

An array of ORKStep objects in the order in which they should be presented.

+
+ + + +
+

Return Value

+

An initialized ordered task.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+ +

– stepAfterStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepBeforeStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– progressOfCurrentStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns an ordered task initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the ordered task.

+
+ + + +
+

Return Value

+

An initialized ordered task.

+
+ + + + + +
+

Discussion

+

An ordered task can be serialized and deserialized with NSKeyedArchiver. Note +that this serialization includes strings that might need to be +localized.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigablePageStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigablePageStep.html new file mode 100755 index 0000000..41d1176 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNavigablePageStep.html @@ -0,0 +1,443 @@ + + + + + + ORKNavigablePageStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNavigablePageStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKPageStep : ORKStep : NSObject
Declared inORKNavigablePageStep.h
ORKNavigablePageStep.m
+ + + + +
+ +

Overview

+

The ORKNavigablePageStep class is a concrete subclass of ORKPageStep, used for presenting a subgrouping of +ORKStepViewController views using a UIPageViewController. It allows for using an ORKOrderedTask as +the model object used to define navigation, and has been added specifically to allow developers to use +ORKNavigableOrderedTask and other subclasses of ORKOrderedTask with the ORKPageStep.

+ +

To use ORKNavigablePageStep, instantiate the object, fill in its properties, and include it in a task. +Next, create a task view controller for the task and present it.

+ +

The base class implementation will instatiate a read-only ORKPageStepViewController to display +a series of substeps. For each substep, the ORKStepViewController will be instantiated and added +as a child of the UIPageViewController contained by the parent ORKPageStepViewController..

+ +

Customization can be handled by overriding the base class implementations in either ORKNavigablePageStep +or ORKPageStepViewController.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:steps: +

+ +
+
+ +
+ + +
+

Returns an initialized page step using the specified identifier and array of steps.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray<ORKStep*> *)steps
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier for the step.

steps

An array of ORKStep objects in the order in which they should be presented.

+
+ + + +
+

Return Value

+

An initialized page step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:pageTask: +

+ +
+
+ +
+ + +
+

Returns an initialized page step using the specified identifier and task.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier pageTask:(ORKOrderedTask *)task
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier for the step.

task

The task used to run the subtask.

+
+ + + +
+

Return Value

+

An initialized navigable page step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKNavigablePageStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a page step initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the ordered task.

+
+ + + +
+

Return Value

+

An initialized navigable page step.

+
+ + + + + +
+

Discussion

+

A page step can be serialized and deserialized with NSKeyedArchiver. Note +that this serialization includes strings that might need to be localized.

+
+ + + + + + + +
+

Declared In

+

ORKNavigablePageStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  pageTask +

+ +
+
+ +
+ + +
+

The subtask used to determine the next/previous steps that are in this grouping

+
+ + + +
@property (nonatomic, copy, readonly) ORKOrderedTask *pageTask
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKNavigablePageStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericAnswerFormat.html new file mode 100755 index 0000000..25f19dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericAnswerFormat.html @@ -0,0 +1,786 @@ + + + + + + ORKNumericAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNumericAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKNumericAnswerFormat class defines the attributes for a numeric +answer format that participants enter using a numeric keyboard.

+ +

If you specify maximum or minimum values and the user enters a value outside the +specified range, the question step view controller does not allow navigation +until the participant provides a value that is within the valid range.

+ +

Questions and form items that use this answer format produce an +ORKNumericQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithStyle: +

+ +
+
+ +
+ + +
+

Returns an initialized numeric answer format using the specified style.

+
+ + + +
- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style
+ + + +
+

Parameters

+ + + + + + + +
style

The style of the numeric answer (decimal or integer).

+
+ + + +
+

Return Value

+

An initialized numeric answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithStyle:unit: +

+ +
+
+ +
+ + +
+

Returns an initialized numeric answer format using the specified style and unit designation.

+
+ + + +
- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style unit:(nullable NSString *)unit
+ + + +
+

Parameters

+ + + + + + + + + + + + +
style

The style of the numeric answer (decimal or integer).

unit

A string that displays a localized version of the unit designation.

+
+ + + +
+

Return Value

+

An initialized numeric answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithStyle:unit:minimum:maximum: +

+ +
+
+ +
+ + +
+

Returns an initialized numeric answer format using the specified style, unit designation, and range +values.

+
+ + + +
- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style unit:(nullable NSString *)unit minimum:(nullable NSNumber *)minimum maximum:(nullable NSNumber *)maximum
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
style

The style of the numeric answer (decimal or integer).

unit

A string that displays a localized version of the unit designation.

minimum

The minimum value to apply, or nil if none is specified.

maximum

The maximum value to apply, or nil if none is specified.

+
+ + + +
+

Return Value

+

An initialized numeric answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithStyle:unit:minimum:maximum:maximumFractionDigits: +

+ +
+
+ +
+ + +
+

Returns an initialized numeric answer format using the specified style, unit designation, and range +values.

+
+ + + +
- (instancetype)initWithStyle:(ORKNumericAnswerStyle)style unit:(nullable NSString *)unit minimum:(nullable NSNumber *)minimum maximum:(nullable NSNumber *)maximum maximumFractionDigits:(nullable NSNumber *)maximumFractionDigits
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
style

The style of the numeric answer (decimal or integer).

unit

A string that displays a localized version of the unit designation.

minimum

The minimum value to apply, or nil if none is specified.

maximum

The maximum value to apply, or nil if none is specified.

maximumFractionDigits

The maximum fraction digits, or nil if no maximum is specified.

+
+ + + +
+

Return Value

+

An initialized numeric answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  style +

+ +
+
+ +
+ + +
+

The style of numeric entry (decimal or integer). (read-only)

+
+ + + +
@property (readonly) ORKNumericAnswerStyle style
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  unit +

+ +
+
+ +
+ + +
+

A string that displays a localized version of the unit designation next to the numeric value. +(read-only)

+
+ + + +
@property (copy, readonly, nullable) NSString *unit
+ + + + + + + + + +
+

Discussion

+

Examples of unit designations are days, lbs, and liters. +The unit string is included in the ORKNumericQuestionResult object.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimum +

+ +
+
+ +
+ + +
+

The minimum allowed value for the numeric answer.

+
+ + + +
@property (copy, nullable) NSNumber *minimum
+ + + + + + + + + +
+

Discussion

+

The default value of this property is nil, which means that no minimum value is displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximum +

+ +
+
+ +
+ + +
+

The maximum allowed value for the numeric answer.

+
+ + + +
@property (copy, nullable) NSNumber *maximum
+ + + + + + + + + +
+

Discussion

+

The default value of this property is nil, which means that no maximum value is displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumFractionDigits +

+ +
+
+ +
+ + +
+

The maximum number of fraction digits to the right of the decimal point for the +numeric answer.

+
+ + + +
@property (copy, nullable) NSNumber *maximumFractionDigits
+ + + + + + + + + +
+

Discussion

+

The default value of this property is nil, which means that there’s no maximum number of fraction +digits.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultNumericAnswer +

+ +
+
+ +
+ + +
+

The default numeric answer.

+
+ + + +
@property (copy, nullable) NSNumber *defaultNumericAnswer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericQuestionResult.html new file mode 100755 index 0000000..8a646ab --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKNumericQuestionResult.html @@ -0,0 +1,232 @@ + + + + + + ORKNumericQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNumericQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKNumericQuestionResult class represents a question or form item that uses an answer format that produces a numeric answer.

+ +

Examples of this type of answer format include ORKScaleAnswerFormat and ORKNumericAnswerFormat.

+ +

A numeric question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  numericAnswer +

+ +
+
+ +
+ + +
+

The number collected, or nil if the user skipped the question.

+
+ + + +
@property (nonatomic, copy, nullable) NSNumber *numericAnswer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+ +

  unit +

+ +
+
+ +
+ + +
+

The unit string displayed to the user when the value was entered, or nil if no unit string was displayed.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *unit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOperation.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOperation.html new file mode 100755 index 0000000..72db11f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOperation.html @@ -0,0 +1,282 @@ + + + + + + ORKOperation Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKOperation Class Reference

+ + +
+ + + + + + + +
Inherits fromNSOperation
Declared inORKOperation.h
ORKOperation.m
+ + + + +
+ +

Overview

+

A concurrent operation for collecting data for upload.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– safeFinish +

+ +
+
+ +
+ + +
+

Finishes the operation cleanly.

+
+ + + +
- (void)safeFinish
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKOperation.h

+
+ + +
+
+
+ +

– doTimeout +

+ +
+
+ +
+ + +
+

Sets the error to indicate a timeout, and finishes.

+
+ + + +
- (void)doTimeout
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKOperation.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  startBlock +

+ +
+
+ +
+ + +
+

Block that will be called inside the lock during -start, +just after transitioning to RKOperationExecuting.

+
+ + + +
@property (nonatomic, strong) ORKOperationBlock startBlock
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKOperation.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOrderedTask.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOrderedTask.html new file mode 100755 index 0000000..84bf93c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKOrderedTask.html @@ -0,0 +1,3084 @@ + + + + + + ORKOrderedTask Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKOrderedTask Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
ORKTask
Declared inORKOrderedTask.h
ORKOrderedTask.m
+ + + + +
+ +

Overview

+

The ORKOrderedTask class implements all the methods in the ORKTask protocol and represents a +task that assumes a fixed order for its steps.

+ +

In the ResearchKit framework, any simple sequential task, such as a survey or an active task, can +be represented as an ordered task.

+ +

If you want further custom conditional behaviors in a task, it can be easier to subclass +ORKOrderedTask or ORKNavigableOrderedTask and override particular ORKTask methods than it is +to implement the ORKTask protocol directly. Override the methods stepAfterStep:withResult: and +stepBeforeStep:withResult:, and call super for all other methods.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:steps: +

+ +
+
+ +
+ + +
+

Returns an initialized ordered task using the specified identifier and array of steps.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray<ORKStep*> *)steps
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier for the task.

steps

An array of ORKStep objects in the order in which they should be presented.

+
+ + + +
+

Return Value

+

An initialized ordered task.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+ +

– copyWithSteps: +

+ +
+
+ +
+ + +
+

Return a mutated copy of self with the steps included in the given array.

+
+ + + +
- (instancetype)copyWithSteps:(NSArray<ORKStep*> *)steps
+ + + +
+

Parameters

+ + + + + + + +
steps

An array of ORKStep objects in the order in which they should be presented.

+
+ + + +
+

Return Value

+

An initialized ordered task.

+
+ + + + + +
+

Discussion

+

This method is intended to allow for mutating an ordered task (or subclass) while retaining +the original class and properties that may not be publicly exposed, but with a mutated set +of steps. An example of where this might be useful is if before performing an ORKPredefinedActiveTask, +the app needed to query the participant about medications, diet or sleep. The app +would need to mutate the steps in order to insert their own steps. While an ORKOrderedTask could +then be created with the same identifier and the new steps, subclass information such rules on an +ORKNavigableOrderedTask would be lost.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the task parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

The implementation of this method should check that all the task parameters are correct. An invalid task +is considered an unrecoverable error: the implementation should throw an exception on parameter validation failure. +For example, the ORKOrderedTask implementation makes sure that all its step identifiers are unique, throwing an +exception otherwise.

+ +

This method is usually called by a task view controller when its task is set.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– identifier +

+ +
+
+ +
+ + +
+

The unique identifier for this task.

+
+ + + +
- (NSString *)identifier
+ + + + + + + + + +
+

Discussion

+

The identifier should be a short string that identifies the task. The identifier is copied +into the ORKTaskResult objects generated by the task view controller for this +task. You can use a human-readable string for the task identifier +or a UUID; the exact string you use depends on your app.

+ +

In the case of apps whose tasks come from a server, the unique +identifier for the task may be in an external database.

+ +

The task view controller uses the identifier when constructing the task result. +The identifier can also be used during UI state restoration to identify the +task that needs to be restored.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– indexOfStep: +

+ +
+
+ +
+ + +
+

Find the index of a given step.

+
+ + + +
- (NSUInteger)indexOfStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to look for

+
+ + + +
+

Return Value

+

The index position of the step (or NSNotFound if not found)

+
+ + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+ +

– stepAfterStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepAfterStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepBeforeStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKStep *)stepBeforeStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns the step that matches the specified identifier.

+
+ + + +
- (ORKStep *)stepWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The identifier of the step to restore.

+
+ + + +
+

Return Value

+

The step that matches the specified identifier.

+
+ + + + + +
+

Discussion

+

Implementing this method allows state restoration of a task +to a particular step. If you don’t implement this method, ORKTaskViewController restores the state +to the first step of the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– progressOfCurrentStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)taskResult
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types that steps in the task need to be able to +read. (read-only)

+
+ + + +
- (NSSet *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The value of this property is a set of HKObjectType values to request for reading from HealthKit during this task. After the last of the initial instruction steps, the task view controller +requests access to these HealthKit types.

+ +

To set this property, you can scan the steps in the task +and collate the HealthKit types that are requested by each active step, question, or +form step that has a Health answer format, and then include any additional types known +to be required. (Note that ORKOrderedTask does something similar for this property.)

+ +

See also: requestedHealthKitTypesForWriting.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForWriting +

+ +
+
+ +
+ + +
+

The set of HealthKit types for which the task needs to request write access.

+
+ + + +
- (NSSet *)requestedHealthKitTypesForWriting
+ + + + + + + + + +
+

Discussion

+

The requested HKObjectType values for writing can be returned by an extended task, +to request write access to these HealthKit types together with the read access +requested by the task view controller by calling requestedHealthKitTypesForReading.

+ +

See also: requestedHealthKitTypesForReading.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– requestedPermissions +

+ +
+
+ +
+ + +
+

The set of permissions requested by the task.

+
+ + + +
- (ORKPermissionMask)requestedPermissions
+ + + + + + + + + +
+

Discussion

+

By default in ORKOrderedTask object, these permissions are collected from the +recorder configurations associated with the active steps in the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– providesBackgroundAudioPrompts +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether this task involves spoken audio prompts. (read-only)

+
+ + + +
- (BOOL)providesBackgroundAudioPrompts
+ + + + + + + + + +
+

Discussion

+

If the value of this property is YES, the shared AVAudioSession is configured for playback in the background. +The audio UIBackgroundMode value must be set in the application’s Info.plist file +for this to be effective.

+ +

By default, this property looks for active steps that have +audio prompts or count down enabled, and returns YES if such steps exist in +the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns an ordered task initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the ordered task.

+
+ + + +
+

Return Value

+

An initialized ordered task.

+
+ + + + + +
+

Discussion

+

An ordered task can be serialized and deserialized with NSKeyedArchiver. Note +that this serialization includes strings that might need to be +localized.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+
+ + + +

Properties

+ +
+
+ +

  steps +

+ +
+
+ +
+ + +
+

The array of steps in the task. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly) NSArray<ORKStep*> *steps
+ + + + + + + + + +
+

Discussion

+

Each element in the array must be a subclass of ORKStep. +The associated task view controller presents the steps in +array order.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+ +

  progressLabelColor +

+ +
+
+ +
+ + +
+

Color property of the progress label. +Default is black.

+
+ + + +
@property (nonatomic) UIColor *progressLabelColor
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask.h

+
+ + +
+
+
+
+ + + +

ORKPredefinedActiveTask Methods

+ +
+
+ +

+ amslerGridTaskWithIdentifier:intendedUseDescription:options: +

+ +
+
+ +
+ + +
+

Returns a predefined Amsler Grid task that helps in detecting problems in user’s vision.

+
+ + + +
+ (ORKOrderedTask *)amslerGridTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data collected. + If the value of this parameter is nil, the default localized text is displayed.

options

Options that affect the features of the predefined task.

+
+ + + + + + + +
+

Discussion

+

In an Amsler Grid task, the participant is shown a square grid. The participant is asked to mark the areas where they notice disctortions in the grid.

+ +

Data collected by the task is in the form of an ORKAmslerGridResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ holePegTestTaskWithIdentifier:intendedUseDescription:dominantHand:numberOfPegs:threshold:rotated:timeLimit:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that measures the upper extremity function.

+
+ + + +
+ (ORKNavigableOrderedTask *)holePegTestTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription dominantHand:(ORKBodySagittal)dominantHand numberOfPegs:(int)numberOfPegs threshold:(double)threshold rotated:(BOOL)rotated timeLimit:(NSTimeInterval)timeLimit options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, the default +localized text will be displayed.

dominantHand

The participant dominant hand that will be tested first.

numberOfPegs

The number of pegs to place in the pegboard.

threshold

The threshold value used for the detection area.

rotated

A test variant that also requires peg rotation.

timeLimit

The duration allowed to validate the peg position.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active hole peg test task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a hole peg test task, the participant is asked to fill holes with pegs.

+ +

A hole peg test task can be used to assess arm and hand function, especially in patients with severe disability.

+ +

Data collected in this task is in the form of an ORKHolePegTestResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ twoFingerTappingIntervalTaskWithIdentifier:intendedUseDescription:duration:handOptions:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of two finger tapping (Optionally with a hand specified)

+
+ + + +
+ (ORKOrderedTask *)twoFingerTappingIntervalTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription duration:(NSTimeInterval)duration handOptions:(ORKPredefinedTaskHandOption)handOptions options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text will be displayed.

duration

The length of the count down timer that runs while touch data is + collected.

handOptions

Options for determining which hand(s) to test.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active two finger tapping task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a two finger tapping task, the participant is asked to rhythmically and alternately tap two +targets on the device screen.

+ +

A two finger tapping task can be used to assess basic motor capabilities including speed, accuracy, +and rhythm.

+ +

Data collected in this task includes touch activity and accelerometer information.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ audioTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:duration:recordingSettings:checkAudioLevel:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that enables an audio recording WITH a check of the audio level.

+
+ + + +
+ (ORKNavigableOrderedTask *)audioTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription speechInstruction:(nullable NSString *)speechInstruction shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction duration:(NSTimeInterval)duration recordingSettings:(nullable NSDictionary *)recordingSettings checkAudioLevel:(BOOL)checkAudioLevel options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, default +localized text is used.

speechInstruction

Instructional content describing what the user needs to do when +recording begins. If the value of this parameter is nil, +default localized text is used.

shortSpeechInstruction

Instructional content shown during audio recording. If the value of +this parameter is nil, default localized text is used.

duration

The length of the count down timer that runs while audio data is +collected.

recordingSettings

See “AV Foundation Audio Settings Constants” for possible values.

checkAudioLevel

If YES then add navigational rules to check the background noise level.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active audio task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In an audio recording task, the participant is asked to make some kind of sound +with their voice, and the audio data is collected.

+ +

An audio task can be used to measure properties of the user’s voice, such as +frequency range, or the ability to pronounce certain sounds.

+ +

If checkAudioLevel == YES then a navigation rule is added to do a simple check of the background +noise level. If the background noise is too loud, then the participant is instructed to move to a +quieter location before trying again.

+ +

Data collected in this task consists of audio information.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ fitnessCheckTaskWithIdentifier:intendedUseDescription:walkDuration:restDuration:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of a fitness check.

+
+ + + +
+ (ORKOrderedTask *)fitnessCheckTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription walkDuration:(NSTimeInterval)walkDuration restDuration:(NSTimeInterval)restDuration options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

walkDuration

The duration of the walk (the maximum is 10 minutes).

restDuration

The duration of the post walk rest period.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active fitness check task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a fitness check task, the participant is asked to walk for a specified duration +(typically several minutes). During this period, various sensor data is collected and returned by +the task view controller’s delegate. Sensor data can include accelerometer, device motion, +pedometer, location, and heart rate data where available.

+ +

At the conclusion of the walk, if heart rate data is available, the participant is asked to sit +down and rest for a period. Data collection continues during this period.

+ +

By default, the task includes an instruction step that explains what the user needs to do during +the task, but this can be excluded with ORKPredefinedTaskOptionExcludeInstructions.

+ +

Data collected from this task can be used to compute measures of general fitness.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ shortWalkTaskWithIdentifier:intendedUseDescription:numberOfStepsPerLeg:restDuration:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of a short walk.

+
+ + + +
+ (ORKOrderedTask *)shortWalkTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription numberOfStepsPerLeg:(NSInteger)numberOfStepsPerLeg restDuration:(NSTimeInterval)restDuration options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

numberOfStepsPerLeg

The number of steps the participant is asked to walk. If the + pedometer is unavailable, a distance is suggested and a suitable + count down timer is displayed for each leg of the walk.

restDuration

The duration of the rest period. When the value of this parameter is + nonzero, the user is asked to stand still for the specified rest + period after the turn sequence has been completed, and baseline + data is collected.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active short walk task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a short walk task, the participant is asked to walk a short distance, which may be indoors. +Typical uses of the resulting data are to assess stride length, smoothness, sway, or other aspects +of the participant’s gait.

+ +

The presentation of the short walk task differs from the fitness check task in that the distance is +replaced by the number of steps taken, and the walk is split into a series of legs. After each leg, +the user is asked to turn and reverse direction.

+ +

The data collected by this task can include accelerometer, device motion, and pedometer data.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ walkBackAndForthTaskWithIdentifier:intendedUseDescription:walkDuration:restDuration:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of a short walk back and forth.

+
+ + + +
+ (ORKOrderedTask *)walkBackAndForthTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription walkDuration:(NSTimeInterval)walkDuration restDuration:(NSTimeInterval)restDuration options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, the default +localized text is displayed.

walkDuration

The duration of the walking period.

restDuration

The duration of the rest period. When the value of this parameter is +nonzero, the user is asked to stand still for the specified rest +period after the turn sequence has been completed, and baseline +data is collected.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active short walk task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a short walk task, the participant is asked to walk a short distance, which may be indoors. +Typical uses of the resulting data are to assess stride length, smoothness, sway, or other aspects +of the participant’s gait.

+ +

The presentation of the back and forth walk task differs from the short walk in that the participant +is asked to walk back and forth rather than walking in a straight line for a certain number of steps.

+ +

The participant is then asked to turn in a full circle and then stand still.

+ +

This task is intended to allow the participant to walk in a confined space where the participant +does not have access to a long hallway to walk in a continuous straight line. Additionally, by asking +the participant to turn in a full circle and then stand still, the activity can access balance and +concentration.

+ +

The data collected by this task can include accelerometer, device motion, and pedometer data.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ kneeRangeOfMotionTaskWithIdentifier:limbOption:intendedUseDescription:options: +

+ +
+
+ +
+ + +
+

The knee range of motion task returns a task that measures the range of motion for either a left or right knee.

+
+ + + +
+ (ORKOrderedTask *)kneeRangeOfMotionTaskWithIdentifier:(NSString *)identifier limbOption:(ORKPredefinedTaskLimbOption)limbOption intendedUseDescription:(NSString *)intendedUseDescription options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

limbOption

Which knee is being measured.

intendedUseDescription

A localized string describing the intended use of the data collected. If the value of this parameter is nil, default localized text is used.

options

Options that affect the features of the predefined task.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ shoulderRangeOfMotionTaskWithIdentifier:limbOption:intendedUseDescription:options: +

+ +
+
+ +
+ + +
+

The shoulder range of motion task returns a task that measures the range of motion for either a left or right shoulder.

+
+ + + +
+ (ORKOrderedTask *)shoulderRangeOfMotionTaskWithIdentifier:(NSString *)identifier limbOption:(ORKPredefinedTaskLimbOption)limbOption intendedUseDescription:(NSString *)intendedUseDescription options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

limbOption

Which shoulder is being measured.

intendedUseDescription

A localized string describing the intended use of the data collected. If the value of this parameter is nil, default localized text is used.

options

Options that affect the features of the predefined task.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ spatialSpanMemoryTaskWithIdentifier:intendedUseDescription:initialSpan:minimumSpan:maximumSpan:playSpeed:maximumTests:maximumConsecutiveFailures:customTargetImage:customTargetPluralName:requireReversal:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that tests spatial span memory.

+
+ + + +
+ (ORKOrderedTask *)spatialSpanMemoryTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(NSString *)intendedUseDescription initialSpan:(NSInteger)initialSpan minimumSpan:(NSInteger)minimumSpan maximumSpan:(NSInteger)maximumSpan playSpeed:(NSTimeInterval)playSpeed maximumTests:(NSInteger)maximumTests maximumConsecutiveFailures:(NSInteger)maximumConsecutiveFailures customTargetImage:(UIImage *)customTargetImage customTargetPluralName:(NSString *)customTargetPluralName requireReversal:(BOOL)requireReversal options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

initialSpan

The sequence length of the initial memory pattern.

minimumSpan

The minimum pattern sequence length.

maximumSpan

The maximum pattern sequence length.

playSpeed

The time per sequence item; a smaller value means faster sequence + play.

maximumTests

The maximum number of rounds to conduct.

maximumConsecutiveFailures

The maximum number of consecutive failures the user can make before + the task is terminated.

customTargetImage

The image to use for the task. By default, and if the value of this + parameter is nil, the image is a flower. To supply a custom + image, create a template image to which iOS adds the tint color.

customTargetPluralName

The name associated with customTargetImage; by default, the value + of this parameter is @“flowers”.

requireReversal

A Boolean value that indicates whether to require the user to tap + the sequence in reverse order.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active spatial span memory task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a spatial span memory task, the participant is asked to repeat pattern sequences of increasing +length in a game-like environment. You can use this task to assess visuospatial memory and +executive function.

+ +

In each round of the task, an array of +target images are shown in a grid (by default, the images are flowers). The round consists of a +demonstration phase and an interactive phase. In the demonstration phase, some of the flowers +change color in a specific sequence. After the demonstration, the user is asked to tap the flowers +in the same sequence for the interactive phase.

+ +

The span (that is, the length of the pattern sequence) is automatically varied during the task, +increasing after users succeed and decreasing after they fail, within the range specified by +minimum and maximum values that you specify. You can also customize the speed of sequence playback +and the shape of the tap target.

+ +

A spatial span memory task finishes when the user has either completed the maximum number of tests +or made the maximum number of errors.

+ +

Data collected by the task is in the form of an ORKSpatialSpanMemoryResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ speechRecognitionTaskWithIdentifier:intendedUseDescription:speechRecognizerLocale:speechRecognitionImage:speechRecognitionText:shouldHideTranscript:allowsEdittingTranscript:options: +

+ +
+
+ +
+ + +
+

Returns a predefined Speech Recognition task that transcribes participant’s speech.

+
+ + + +
+ (ORKOrderedTask *)speechRecognitionTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription speechRecognizerLocale:(ORKSpeechRecognizerLocale)speechRecognizerLocale speechRecognitionImage:(nullable UIImage *)speechRecognitionImage speechRecognitionText:(nullable NSString *)speechRecognitionText shouldHideTranscript:(BOOL)shouldHideTranscript allowsEdittingTranscript:(BOOL)allowsEdittingTranscript options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data collected. + If the value of this parameter is nil, the default localized text is displayed.

speechRecognizerLocale

An enum that represents the locale to be used by speech recognition API.

speechRecognitionImage

The image shown to the participant.

speechRecognitionText

The text shown to the participant.

shouldHideTranscript

The boolean value used to show or hide the transcription from the user.

allowsEdittingTranscript

The boolean value used to present step that allows editting transcription.

options

Options that affect the features of the predefined task.

+
+ + + + + + + +
+

Discussion

+

In a Speech Recognition task, the participant is shown a text or image or both. The participant has to read the text aloud, or describe the image.

+ +

A Speech Recognition task finishes when the user presses the Stop Recording button.

+ +

Data collected by the task is in the form of an ORKSpeechRecognitionResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ speechInNoiseTaskWithIdentifier:intendedUseDescription:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that tests speech audiometry.

+
+ + + +
+ (ORKOrderedTask *)speechInNoiseTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, default +localized text is used.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active speech in noise task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a speech in noise task, the participant is asked to listen to some sentences mixed with background noise at varying signal to noise ratio (SNR).

+ +

You can use a speech in noise task to measure the speech reception threshold (SRT) of an individual.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ stroopTaskWithIdentifier:intendedUseDescription:numberOfAttempts:options: +

+ +
+
+ +
+ + +
+

Returns a predefined Stroop task that tests participants selective attention and cognitive flexibility.

+
+ + + +
+ (ORKOrderedTask *)stroopTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription numberOfAttempts:(NSInteger)numberOfAttempts options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, the default +localized text is displayed.

numberOfAttempts

Total number of stroop questions to include in the task.

options

Options that affect the features of the predefined task.

+
+ + + + + + + +
+

Discussion

+

In a stroop task, the participant is shown a text. The text is a name of a color, but the text is printed in a color that may or may not be denoted by the name. In each attempt of the task, the participant has to press the button that corresponds to the first letter of the color in which the text is printed. The participant has to ignore the name of the color written in the text, but respond based on the color of the text.

+ +

A stroop task finishes when the user has completed all the attempts, irrespective of correct or incorrect answers.

+ +

Data collected by the task is in the form of an ORKStroopResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ toneAudiometryTaskWithIdentifier:intendedUseDescription:speechInstruction:shortSpeechInstruction:toneDuration:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that tests tone audiometry.

+
+ + + +
+ (ORKOrderedTask *)toneAudiometryTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription speechInstruction:(nullable NSString *)speechInstruction shortSpeechInstruction:(nullable NSString *)shortSpeechInstruction toneDuration:(NSTimeInterval)toneDuration options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, default + localized text is used.

speechInstruction

Instructional content describing what the user needs to do when + recording begins. If the value of this parameter is nil, + default localized text is used.

shortSpeechInstruction

Instructional content shown during audio recording. If the value of + this parameter is nil, default localized text is used.

toneDuration

The maximum length of the duration for each tone (each tone can be + interrupted sooner, after the participant presses the main + button).

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active tone audiometry task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a tone audiometry task, the participant is asked to listen to some tones with different audio +frequencies, playing on different channels (left and right), with the volume being progressively +increased until the participant taps a button.

+ +

You can use a tone audiometry task to measure properties of the user’s hearing, based on their +reaction to a wide range of frequencies.

+ +

Data collected in this task consists of audio signal amplitude for specific frequencies and +channels.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ dBHLToneAudiometryTaskWithIdentifier:intendedUseDescription:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that tests dBHL tone audiometry.

+
+ + + +
+ (ORKOrderedTask *)dBHLToneAudiometryTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, default +localized text is used.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active dBHL tone audiometry task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In the dBHL tone audiometry task, the participant is asked to listen to some tones with different audio +frequencies, playing on different channels (left and right), that vary in dB HL values depending on whether or not the user tapped the button.

+ +

You can use a tone audiometry task to measure the hearing threshold of the user.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ towerOfHanoiTaskWithIdentifier:intendedUseDescription:numberOfDisks:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of a Tower of Hanoi puzzle.

+
+ + + +
+ (ORKOrderedTask *)towerOfHanoiTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription numberOfDisks:(NSUInteger)numberOfDisks options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the + default localized text is displayed.

numberOfDisks

The number of disks in the puzzle; the default value for this property is 3.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active device motion reaction time task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a Tower of Hanoi task, the participant is asked to solve the classic puzzle in as few moves as possible. +You can use this task to assess the participant’s problem-solving skills.

+ +

A Tower of Hanoi task finishes when the participant has completed the puzzle correctly or concedes that he or she cannot solve it.

+ +

Data collected by the task is in the form of an ORKTowerOfHanoiResult object. Data collected in this task consists of how many moves were taken and whether the puzzle was successfully completed or not.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ reactionTimeTaskWithIdentifier:intendedUseDescription:maximumStimulusInterval:minimumStimulusInterval:thresholdAcceleration:numberOfAttempts:timeout:successSound:timeoutSound:failureSound:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that tests the participant’s reaction time.

+
+ + + +
+ (ORKOrderedTask *)reactionTimeTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription maximumStimulusInterval:(NSTimeInterval)maximumStimulusInterval minimumStimulusInterval:(NSTimeInterval)minimumStimulusInterval thresholdAcceleration:(double)thresholdAcceleration numberOfAttempts:(int)numberOfAttempts timeout:(NSTimeInterval)timeout successSound:(UInt32)successSoundID timeoutSound:(UInt32)timeoutSoundID failureSound:(UInt32)failureSoundID options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the + study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the + default localized text is displayed.

maximumStimulusInterval

The maximum interval before the stimulus is delivered.

minimumStimulusInterval

The minimum interval before the stimulus is delivered.

thresholdAcceleration

The acceleration required to end a reaction time test.

numberOfAttempts

The number of successful attempts required before the task is + complete. The active step result will contain this many + child results if the task is completed.

timeout

The interval permitted after the stimulus until the test fails, + if the threshold is not reached.

successSoundID

The sound to play after a successful attempt.

timeoutSoundID

The sound to play after an attempt that times out.

failureSoundID

The sound to play after an unsuccessful attempt.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active device motion reaction time task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a reaction time task, the participant is asked to move the device sharply in any +direction in response to a visual cue. You can use this task to accurately assess the participant’s +simple reaction time.

+ +

A reaction time task finishes when the participant has completed the required +number of attempts successfully. An attempt is successful when the participant exerts acceleration +greater than thresholdAcceleration to the device after the stimulus has been delivered and before +timeout has elapsed. An attempt is unsuccessful if acceleration greater than +thresholdAcceleration is applied to the device before the stimulus or if this does not occur +before timeout has elapsed. If unsuccessful, the result is not reported and the participant must +try again to proceed with the task.

+ +

Data collected by the task is in the form of ORKReactionTimeResult objects. These +objects contain a timestamp representing the delivery of the stimulus and an ORKFileResult, which +references the motion data collected during an attempt. The researcher can use these to evaluate +the response to the stimulus and calculate the reaction time.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ timedWalkTaskWithIdentifier:intendedUseDescription:distanceInMeters:timeLimit:turnAroundTimeLimit:includeAssistiveDeviceForm:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of a timed walk, with a distinct turn around step.

+
+ + + +
+ (ORKOrderedTask *)timedWalkTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription distanceInMeters:(double)distanceInMeters timeLimit:(NSTimeInterval)timeLimit turnAroundTimeLimit:(NSTimeInterval)turnAroundTimeLimit includeAssistiveDeviceForm:(BOOL)includeAssistiveDeviceForm options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data +collected. If the value of this parameter is nil, the default +localized text is displayed.

distanceInMeters

The timed walk distance in meters.

timeLimit

The time limit to complete the trials.

turnAroundTimeLimit

The time limit to complete the turn around step, passing zero or negative value to this parameter will bypass the turnAroundTime step.

includeAssistiveDeviceForm

A Boolean value that indicates whether to inlude the form step +about the usage of an assistive device.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active timed walk task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a timed walk task, the participant is asked to walk for a specific distance as quickly as +possible, but safely. Then the participant is asked to turn around. The task is immediately +administered again by having the patient walk back the same distance. +A timed walk task can be used to measure lower extremity function.

+ +

The presentation of the timed walk task differs from both the fitness check task and the short +walk task in that the distance is fixed. After a first walk, the user is asked to turn, then reverse +direction.

+ +

The data collected by this task can include accelerometer, device motion, pedometer data, +and location where available.

+ +

Data collected by the task is in the form of an ORKTimedWalkResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ PSATTaskWithIdentifier:intendedUseDescription:presentationMode:interStimulusInterval:stimulusDuration:seriesLength:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that consists of the paced serial addition test (PSAT).

+
+ + + +
+ (ORKOrderedTask *)PSATTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription presentationMode:(ORKPSATPresentationMode)presentationMode interStimulusInterval:(NSTimeInterval)interStimulusInterval stimulusDuration:(NSTimeInterval)stimulusDuration seriesLength:(NSInteger)seriesLength options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

presentationMode

The presentation mode of the PSAT test (auditory or visual or both).

interStimulusInterval

The time interval between two digits presented.

stimulusDuration

The time duration the digit is shown on screen (only for + visual PSAT, that is PVSAT and PAVSAT).

seriesLength

The number of digits that will be presented during the task.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active PSAT task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a PSAT task, the participant is asked to add a new digit to the one immediately before it +every 2 or 3 seconds.

+ +

A PSAT task can be used to measure the cognitive function that assesses auditory and/or +visual information processing speed and flexibility, as well as calculation ability.

+ +

Data collected by the task is in the form of an ORKPSATResult object.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ tremorTestTaskWithIdentifier:intendedUseDescription:activeStepDuration:activeTaskOptions:handOptions:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that measures hand tremor.

+
+ + + +
+ (ORKNavigableOrderedTask *)tremorTestTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription activeStepDuration:(NSTimeInterval)activeStepDuration activeTaskOptions:(ORKTremorActiveTaskOption)activeTaskOptions handOptions:(ORKPredefinedTaskHandOption)handOptions options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

activeStepDuration

The duration for each active step in the task.

activeTaskOptions

Options that affect which active steps are presented for this task.

handOptions

Options for determining which hand(s) to test.

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active tremor test task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a tremor assessment task, the participant is asked to hold the device with their most affected +hand in various positions while accelerometer and motion data are captured.

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+ +

+ trailmakingTaskWithIdentifier:intendedUseDescription:trailmakingInstruction:trailType:options: +

+ +
+
+ +
+ + +
+

Returns a predefined task that measures visual attention and task switching.

+
+ + + +
+ (ORKOrderedTask *)trailmakingTaskWithIdentifier:(NSString *)identifier intendedUseDescription:(nullable NSString *)intendedUseDescription trailmakingInstruction:(nullable NSString *)trailmakingInstruction trailType:(ORKTrailMakingTypeIdentifier)trailType options:(ORKPredefinedTaskOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The task identifier to use for this task, appropriate to the study.

intendedUseDescription

A localized string describing the intended use of the data + collected. If the value of this parameter is nil, the default + localized text is displayed.

trailmakingInstruction

Instructional content describing what the user needs to do when + the task begins. If the value of this parameter is nil,

trailType

Type of trail to display. Either ORKTrailMakingTypeIdentifierA or ORKTrailMakingTypeIdentifierB

options

Options that affect the features of the predefined task.

+
+ + + +
+

Return Value

+

An active trail making test task that can be presented with an ORKTaskViewController object.

+
+ + + + + +
+

Discussion

+

In a trail making test, the participant is asked to connect a series of cicles labeled 1,2,3… or +1,A,2,B,3,C… and time to complete the test is recorded.

+ +

ORKTrailMakingTypeIdentifierA uses the pattern: 1-2-3-4-5-6-7. +ORKTrailMakingTypeIdentifierB uses the pattern: 1-A-2-B-3-C-4-D-5-E-6-F-7

+
+ + + + + + + +
+

Declared In

+

ORKOrderedTask+ORKPredefinedActiveTask.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStep.html new file mode 100755 index 0000000..4ce0b23 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStep.html @@ -0,0 +1,264 @@ + + + + + + ORKPDFViewerStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPDFViewerStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKPDFViewerStep.h
ORKPDFViewerStep.m
+ + + + +
+ +

Overview

+

The ORKPDFViewerStep class is a concrete subclass of ORKStep, used for presenting a PDF document for reading and limited editing.

+ +

To use ORKPDFViewerStep, instantiate the object, fill in its properties, and include it in a task. +Next, create a task view controller for the task and present it.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStepViewController.html new file mode 100755 index 0000000..feaf5cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPDFViewerStepViewController.html @@ -0,0 +1,254 @@ + + + + + + ORKPDFViewerStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPDFViewerStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKPDFViewerStepViewController.h
ORKPDFViewerStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATResult.html new file mode 100755 index 0000000..6032c63 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATResult.html @@ -0,0 +1,537 @@ + + + + + + ORKPSATResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPSATResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKPSATResult.h
ORKPSATResult.m
+ + + + +
+ +

Overview

+

The ORKPSATResult class records the results of a PSAT test.

+ +

The PSAT result object records the initial digit, an array of addition samples, the total of correct answers +and also various attributes of the PSAT test.

+ +

The PSAT samples are generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize them for transmission to a server, +or to immediately perform analysis on them.

+
+ + + + + +
+ + + + + + +
+
+ +

  presentationMode +

+ +
+
+ +
+ + +
+

The PSAT presentation mode.

+
+ + + +
@property (nonatomic, assign) ORKPSATPresentationMode presentationMode
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  interStimulusInterval +

+ +
+
+ +
+ + +
+

The time interval between two digits presented. +PSAT-2" is 2 seconds; PSAT-3" is 3 seconds.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval interStimulusInterval
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  stimulusDuration +

+ +
+
+ +
+ + +
+

The amount of time a digit is shown on the screen (0 second for PASAT).

+
+ + + +
@property (nonatomic, assign) NSTimeInterval stimulusDuration
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  length +

+ +
+
+ +
+ + +
+

The length of the series, that is, the number of additions.

+
+ + + +
@property (nonatomic, assign) NSInteger length
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  totalCorrect +

+ +
+
+ +
+ + +
+

The number of correct sums given (out of ‘length’ possible ones).

+
+ + + +
@property (nonatomic, assign) NSInteger totalCorrect
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  totalDyad +

+ +
+
+ +
+ + +
+

The number of consecutive correct answers (out of ‘length - 1’ possible ones). +Used to overcome the alternate answer strategy.

+
+ + + +
@property (nonatomic, assign) NSInteger totalDyad
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  totalTime +

+ +
+
+ +
+ + +
+

The total time needed to answer all additions (that is, the sum of all the samples times).

+
+ + + +
@property (nonatomic, assign) NSTimeInterval totalTime
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  initialDigit +

+ +
+
+ +
+ + +
+

The initial digit.

+
+ + + +
@property (nonatomic, assign) NSInteger initialDigit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  samples +

+ +
+
+ +
+ + +
+

An array of collected samples, in which each item is an ORKPSATSample +object that represents an addition sample.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKPSATSample*> *samples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATSample.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATSample.html new file mode 100755 index 0000000..a189e69 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATSample.html @@ -0,0 +1,329 @@ + + + + + + ORKPSATSample Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPSATSample Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKPSATResult.h
ORKPSATResult.m
+ + + + +
+ +

Overview

+

The ORKPSATSample class represents a numeric answer to an addition question. +If the answer is correct, the sample object records the presented digit and the numeric answer. +A PSAT sample is included in an ORKPSATResult object and is recorded +by the step view controller for the corresponding task.

+ +

A PSAT sample is typically generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize the sample for +transmission to a server, or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  correct +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the addition answer was the correct one.

+
+ + + +
@property (nonatomic, assign, getter=isCorrect) BOOL correct
+ + + + + + + + + +
+

Discussion

+

The value of this property is YES when the addition result is the correct +one, and NO otherwise.

+
+ + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  digit +

+ +
+
+ +
+ + +
+

The presented digit.

+
+ + + +
@property (nonatomic, assign) NSInteger digit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  answer +

+ +
+
+ +
+ + +
+

The numeric answer; +-1 if no answer is provided.

+
+ + + +
@property (nonatomic, assign) NSInteger answer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+ +

  time +

+ +
+
+ +
+ + +
+

The time interval between the new digit and the answer, or test duration if no answer is provided.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval time
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPSATResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStep.html new file mode 100755 index 0000000..77605e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStep.html @@ -0,0 +1,304 @@ + + + + + + ORKPSATStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPSATStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKPSATStep.h
ORKPSATStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStepViewController.html new file mode 100755 index 0000000..f42de1b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPSATStepViewController.html @@ -0,0 +1,479 @@ + + + + + + ORKPSATStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPSATStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKPSATStepViewController.h
ORKPSATStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– suspend +

+ +
+
+ +
+ + +
+

Suspends the active step.

+
+ + + +
- (void)suspend
+ + + + + + + + + +
+

Discussion

+

Call this method to suspend data recording and the step’s timer.

+ +

This method may called automatically when the app is suspended. +The view controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes the active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method when the step should be resumed. Calls to this method should +be paired with previous calls to suspend.

+ +

This method may be called automatically when the app is resumed. The view +controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

When the step is resumed, the UI should resume at the point where the user left off, +or, if that does not make sense for the particular step, to the most recent +suitable point.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– finish +

+ +
+
+ +
+ + +
+

Finishes the active step.

+
+ + + +
- (void)finish
+ + + + + + + + + +
+

Discussion

+

Call this method to finish the active step. If the active step is configured with +a timer, this method is called automatically when the timer expires.

+ +

Finishing the active step stops all data recording and stops any timers. In steps that have the +shouldContinueOnFinish property set, forward navigation to the next step +may ensue.

+ +

This method does nothing if the step has already finished.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageResult.html new file mode 100755 index 0000000..cf758c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageResult.html @@ -0,0 +1,123 @@ + + + + + + ORKPageResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPageResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKTaskResult : ORKCollectionResult : ORKResult : NSObject
Declared inORKCollectionResult.m
ORKCollectionResult_Private.h
+ + + + +
+ +

Overview

+

The ORKPageResult is an ORKTaskResult subclass of a collection of ORKStepResult +objects. This is considered private, and it is used internally by ORKPageStepViewController +to track the result set.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStep.html new file mode 100755 index 0000000..f6e1fb4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStep.html @@ -0,0 +1,778 @@ + + + + + + ORKPageStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPageStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKPageStep.h
ORKPageStep.m
+ + + + +
+ +

Overview

+

The ORKPageStep class is a concrete subclass of ORKStep, used for presenting a subgrouping of +ORKStepViewController views using a UIPageViewController.

+ +

To use ORKPageStep, instantiate the object, fill in its properties, and include it in a task. +Next, create a task view controller for the task and present it.

+ +

The base class implementation will instatiate a read-only ORKPageStepViewController to display +a series of substeps. For each substep, the ORKStepViewController will be instantiated and added +as a child of the UIPageViewController contained by the parent ORKPageStepViewController..

+ +

Customization can be handled by overriding the base class implementations in either ORKPageStep +or ORKPageStepViewController.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:steps: +

+ +
+
+ +
+ + +
+

Returns an initialized page step using the specified identifier and array of steps.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier steps:(NSArray<ORKStep*> *)steps
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The unique identifier for the step.

steps

An array of ORKStep objects in the order in which they should be presented.

+
+ + + +
+

Return Value

+

An initialized page step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

– steps +

+ +
+
+ +
+ + +
+

The array of steps in the page step. (read-only)

+
+ + + +
- (NSArray<ORKStep*> *)steps
+ + + + + + + + + +
+

Discussion

+

Each element in the array must be a subclass of ORKStep. +The associated page step view controller presents the steps in +array order.

+
+ + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedPermissions +

+ +
+
+ +
+ + +
+

The set of access permissions required for the step. (read-only)

+
+ + + +
- (ORKPermissionMask)requestedPermissions
+ + + + + + + + + +
+

Discussion

+

The permission mask is used by the task view controller to determine the types of +access to request from users when they complete the initial instruction steps +in a task. If your step requires access to APIs that limit access, include +the permissions you require in this mask.

+ +

By default, the property scans the recorders and collates the permissions +required by the recorders. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types the step requests for reading. (read-only)

+
+ + + +
- (NSSet<HKObjectType*> *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this set of types when constructing a list of +all the HealthKit types required by all the steps in a task, so that it can +present the HealthKit access dialog just once during that task.

+ +

By default, the property scans the recorders and collates the HealthKit +types the recorders require. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– stepAfterStepWithIdentifier:withResult: +

+ +
+
+ +
+ + +
+

Returns the step after the specified step, if there is one.

+
+ + + +
- (ORKStep *)stepAfterStepWithIdentifier:(NSString *)identifier withResult:(ORKTaskResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The reference step identifier. Pass nil to specify the first step.

result

A snapshot of the current set of results.

+
+ + + +
+

Return Value

+

The step that comes after the specified step, or nil if there isn’t one.

+
+ + + + + +
+

Discussion

+

The page view controller calls this method to determine the step to display after the specified step. +The page view controller can also call this method every time the result updates, to determine if the +new result changes which steps are available.

+
+ + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

– stepBeforeStepWithIdentifier:withResult: +

+ +
+
+ +
+ + +
+

Returns the step that precedes the specified step, if there is one.

+
+ + + +
- (ORKStep *)stepBeforeStepWithIdentifier:(NSString *)identifier withResult:(ORKTaskResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The reference step identifier.

result

A snapshot of the current set of results.

+
+ + + +
+

Return Value

+

The step that precedes the reference step, or nil if there isn’t one.

+
+ + + + + +
+

Discussion

+

The page view controller calls this method to determine the step to display before the specified step. +The page view controller can also call this method every time the result changes, to determine if the +new result changes which steps are available.

+
+ + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

– stepWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns the step that matches the specified identifier.

+
+ + + +
- (ORKStep *)stepWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The identifier of the step to restore.

+
+ + + +
+

Return Value

+

The step that matches the specified identifier, or nil if there isn’t one.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a page step initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the ordered task.

+
+ + + +
+

Return Value

+

An initialized page step.

+
+ + + + + +
+

Discussion

+

A page step can be serialized and deserialized with NSKeyedArchiver. Note +that this serialization includes strings that might need to be localized.

+
+ + + + + + + +
+

Declared In

+

ORKPageStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStepViewController.html new file mode 100755 index 0000000..b8b3f41 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPageStepViewController.html @@ -0,0 +1,476 @@ + + + + + + ORKPageStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPageStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKPageStepViewController.h
ORKPageStepViewController.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  pageStep +

+ +
+
+ +
+ + +
+

The ORKPageStep associated with this view controller.

+
+ + + +
@property (nonatomic, readonly, nullable) ORKPageStep *pageStep
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPageStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerForStep: +

+ +
+
+ +
+ + +
+

Returns the step view controller to associate with this step. By default, this will +return the step view controller instantiated by the given step.

+
+ + + +
- (ORKStepViewController *)stepViewControllerForStep:(ORKStep *)step
+ + + + + +
+

Return Value

+

ORKStepViewController subclass for this step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPageStepViewController.h

+
+ + +
+
+
+ +

– resultSource +

+ +
+
+ +
+ + +
+

Returns an ORKTaskResultSource for the steps that are included as substeps for this +page view controller.

+
+ + + +
- (id<ORKTaskResultSource>)resultSource
+ + + + + +
+

Return Value

+

ORKTaskResultSource for the step results

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPageStepViewController.h

+
+ + +
+
+
+ +

– goToStep:direction:animated: +

+ +
+
+ +
+ + +
+

Go to the given step.

+
+ + + +
- (void)goToStep:(ORKStep *)step direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
step

The step to go to

direction

The direction in which navigate

animated

Should the change of view controllers be animated.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPageStepViewController.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeResult.html new file mode 100755 index 0000000..6433f6c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeResult.html @@ -0,0 +1,228 @@ + + + + + + ORKPasscodeResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKPasscodeResult.h
ORKPasscodeResult.m
+ + + + +
+ +

Overview

+

The ORKPasscodeResult class records the results of a passcode step.

+ +

The passcode result object contains a boolean indicating whether the passcode was saved or not.

+
+ + + + + +
+ + + + + + +
+
+ +

  passcodeSaved +

+ +
+
+ +
+ + +
+

A boolean indicating if a passcode was saved or not.

+
+ + + +
@property (nonatomic, assign, getter=isPasscodeSaved) BOOL passcodeSaved
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeResult.h

+
+ + +
+
+
+ +

  touchIdEnabled +

+ +
+
+ +
+ + +
+

A boolean that indicates if the user has enabled/disabled TouchID

+
+ + + +
@property (nonatomic, assign, getter=isTouchIdEnabled) BOOL touchIdEnabled
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStep.html new file mode 100755 index 0000000..55ed135 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStep.html @@ -0,0 +1,394 @@ + + + + + + ORKPasscodeStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKPasscodeStep.h
ORKPasscodeStep.m
+ + + + +
+ +

Overview

+

An ORKPasscodeStep object provides the participant a passcode creation step.

+ +

It is recommended to use a passcode step as part of the consent process to ensure +that the participant signing the consent is the same participant completing other +modules within that context.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ passcodeStepWithIdentifier:passcodeFlow: +

+ +
+
+ +
+ + +
+

Returns a new passcode step with the specified identifier and passcode flow.

+
+ + + +
+ (instancetype)passcodeStepWithIdentifier:(NSString *)identifier passcodeFlow:(ORKPasscodeFlow)passcodeFlow
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

passcodeFlow

The passcode flow to be used for the step.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeStep.h

+
+ + +
+
+
+ +

  passcodeFlow +

+ +
+
+ +
+ + +
+

The passcode flow to be used for the step.

+
+ + + +
@property (nonatomic) ORKPasscodeFlow passcodeFlow
+ + + + + + + + + +
+

Discussion

+

The default value of this property is ORKPasscodeFlowCreate.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeStep.h

+
+ + +
+
+
+ +

  passcodeType +

+ +
+
+ +
+ + +
+

The passcode type to be used for the step.

+
+ + + +
@property (nonatomic) ORKPasscodeType passcodeType
+ + + + + + + + + +
+

Discussion

+

The default value of this property is ORKPasscodeType4Digit.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStepViewController.html new file mode 100755 index 0000000..459e3da --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeStepViewController.html @@ -0,0 +1,382 @@ + + + + + + ORKPasscodeStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKPasscodeStepViewController.h
ORKPasscodeStepViewController.m
+ + + + +
+ +

Overview

+

An ORKPasscodeStepViewController object is the view controller for an ORKPasscodeStep object.

+ +

A passcode view controller can be instantiated indirectly by adding a passcode step to a consent task +and present the task using a task view controller. When appropriate, the task view controller instantiates the step +view controller for the step.

+
+ + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– addResult: +

+ +
+
+ +
+ + +
+

Add a result to the step view controller’s ORKStepResult. By default, the property for +the step view controller’s result will instantiate a copy of the result each time it is +called. Therefore, the result cannot be mutated by adding a result to its result array.

+
+ + + +
- (void)addResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + +
result

The result to add to the step results.

+
+ + + + + + + +
+

Discussion

+

This method can be called by a delegate to add a result to a given step in a way that will +be retained by the step.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– promptTouchIdWithDelay +

+ +
+
+ +
+ + +
+

Device does not support Touch ID.

+
+ + + +
- (void)promptTouchIdWithDelay
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeStepViewController.m

+
+ + +
+
+
+ +

+ savePasscode:withTouchIdEnabled: +

+ +
+
+ +
+ + +
+

Stores the given passcode as the user’s unlock passcode to the keychain.

+
+ + + +
+ (void)savePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled
+ + + +
+

Parameters

+ + + + + + + + + + + + +
passcode

The passcode to store

touchIdEnabled

Whether TouchId will be available during passcode entry

+
+ + + + + + + +
+

Discussion

+

This method will raise an exception if passcode is nil.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeStepViewController_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeViewController.html new file mode 100755 index 0000000..7c1ae5a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPasscodeViewController.html @@ -0,0 +1,452 @@ + + + + + + ORKPasscodeViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromUINavigationController
Declared inORKPasscodeViewController.h
ORKPasscodeViewController.m
+ + + + +
+ +

Overview

+

An ORKPasscodeStepViewController object is the view controller for an ORKPasscodeStep object.

+ +

A passcode view controller can also be instantiated directly for authentication and editing by using one +of the factory methods below. Each factory method requires a delegate to be implemented.

+
+ + + + + +
+ + + + + + +
+
+ +

+ passcodeAuthenticationViewControllerWithText:delegate: +

+ +
+
+ +
+ + +
+

An authenticaiton passcode view controller allows a user to be authenticated using +the passcode stored in the keychain.

+
+ + + +
+ (instancetype)passcodeAuthenticationViewControllerWithText:(NSString *)text delegate:(id<ORKPasscodeDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + +
text

The message displayed to the user.

delegate

The delegate for the passcode view controller.

+
+ + + +
+

Return Value

+

A passcode authentication view controller.

+
+ + + + + +
+

Discussion

+

A passcode must already have been created using a passcode step before presenting +this view controller (see ORKPasscodeStep).

+ +

You must check to see if the passcode is stored in the keychain before presenting +this view controller. A helper method, isPasscodeStoredInKeychain, is provided as +part of this class.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

+ passcodeEditingViewControllerWithText:delegate:passcodeType: +

+ +
+
+ +
+ + +
+

An editing passcode view controller allows a user to be authenticated using +the passcode stored in the keychain and create a new passcode.

+
+ + + +
+ (instancetype)passcodeEditingViewControllerWithText:(NSString *)text delegate:(id<ORKPasscodeDelegate>)delegate passcodeType:(ORKPasscodeType)passcodeType
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
text

The message displayed to the user.

delegate

The delegate for the passcode view controller.

passcodeType

The passcode type for the new passcode.

+
+ + + +
+

Return Value

+

A passcode editing view controller.

+
+ + + + + +
+

Discussion

+

A passcode must already have been created using a passcode step before presenting +this view controller (see ORKPasscodeStep).

+ +

You must check to see if the passcode is stored in the keychain before presenting +this view controller. A helper method, isPasscodeStoredInKeychain, is provided as +part of this class.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

+ isPasscodeStoredInKeychain +

+ +
+
+ +
+ + +
+

Returns ‘YES’ if a passcode is stored in the keychain, otherwise ‘NO’.

+
+ + + +
+ (BOOL)isPasscodeStoredInKeychain
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

+ removePasscodeFromKeychain +

+ +
+
+ +
+ + +
+

Returns ‘YES’ if passcode was successfully removed from the keychain, otherwise ‘NO’.

+
+ + + +
+ (BOOL)removePasscodeFromKeychain
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

+ forcePasscode:withTouchIdEnabled: +

+ +
+
+ +
+ + +
+

This method allows to force the passcode to be a certain value. You only want to use this capability when you’re moving your existing users +from a custom passcode entry mechanism to the one provided by ResearchKit.

+
+ + + +
+ (void)forcePasscode:(NSString *)passcode withTouchIdEnabled:(BOOL)touchIdEnabled
+ + + +
+

Parameters

+ + + + + + + + + + + + +
passcode

The passcode to store

touchIdEnabled

Whether TouchId will be available during passcode entry

+
+ + + + + + + +
+

Discussion

+

This method will raise an exception if passcode is nil.

+
+ + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorder.html new file mode 100755 index 0000000..8e27d89 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorder.html @@ -0,0 +1,422 @@ + + + + + + ORKPedometerRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPedometerRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKPedometerRecorder.h
ORKPedometerRecorder.m
+ + + + +
+ +

Overview

+

A recorder that requests and collects device motion data from CoreMotion at a fixed frequency.

+ +

The accelerometer recorder continues to record if the application enters the +background using UIApplication’s background task support.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized pedometer recorder.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier step:(nullable ORKStep *)step outputDirectory:(nullable NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

step

The step that requested this recorder.

outputDirectory

The directory in which the pedometer data should be stored.

+
+ + + +
+

Return Value

+

An initialized pedometer recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPedometerRecorder.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorderConfiguration.html new file mode 100755 index 0000000..f15e6b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPedometerRecorderConfiguration.html @@ -0,0 +1,394 @@ + + + + + + ORKPedometerRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPedometerRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKPedometerRecorder.m
ORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKPedometerRecorderConfiguration class represents a configuration +that records pedometer data during an active step.

+ +

Pedometer data consists of information about the processed steps provided by CoreMotion, obtained +from a CMPedometer object. The pedometer object essentially reports the total number of steps taken since the +start of recording, updating the value every time a significant number of steps have +been detected.

+ +

Pedometer data is serialized to JSON and returned as an ORKFileResult object. +For details on the format, see CMPedometerData+ORKJSONDictionary.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized pedometer recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized pedometer recorder configuration.

+
+ + + + + +
+

Discussion

+

The recorder instantiates a CMPedometer object, so no additional parameters besides +the identifier are required.

+ +

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new pedometer recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the pedometer recorder configuration.

+
+ + + +
+

Return Value

+

A new pedometer recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPicker.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPicker.html new file mode 100755 index 0000000..4c337f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPicker.html @@ -0,0 +1,210 @@ + + + + + + ORKPicker Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPicker Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKPicker.h
ORKPicker.m
+ + + + +
+ +

Overview

+

Creates a picker appropriate to the type required by answerformat

+
+ + + + + +
+ + + + + + +
+
+ +

+ pickerWithAnswerFormat:answer:delegate: +

+ +
+
+ +
+ + +
+

Creates a picker appropriate to the type required by answerformat

+
+ + + +
+ (id<ORKPicker>)pickerWithAnswerFormat:(ORKAnswerFormat *)answerFormat answer:(id)answer delegate:(id<ORKPickerDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
answerFormat

An ORKAnswerFormat object which specified the format of the result

answer

A default answer (to set as the picker’s current result), or nil if no answer specified.

delegate

A delegate who conforms to ORKPickerDelegate

+
+ + + +
+

Return Value

+

The picker object

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPicker.m

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPieChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPieChartView.html new file mode 100755 index 0000000..7d1e1ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPieChartView.html @@ -0,0 +1,787 @@ + + + + + + ORKPieChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPieChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKPieChartView.h
ORKPieChartView.m
+ + + + +
+ +

Overview

+

The ORKPieChartView class presents data provided by an object conforming to the +ORKPieChartViewDataSource protocol as a pie chart.

+
+ + + + + +
+ + + + + + +
+
+ +

  dataSource +

+ +
+
+ +
+ + +
+

The data source object responsible for populating the pie chart with data.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKPieChartViewDataSource> dataSource
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  lineWidth +

+ +
+
+ +
+ + +
+

The width of the line used to draw the circular sections of the pie chart.

+
+ + + +
@property (nonatomic) IBInspectable CGFloat lineWidth
+ + + + + + + + + +
+

Discussion

+

If you do not set a value for this property, the pie chart view assumes a sensible value. If +you set a number higher than the radius of the pie chart, the pie chart draws a completely +filled pie.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  title +

+ +
+
+ +
+ + +
+

The text to display as a title in the pie chart view.

+
+ + + +
@property (nonatomic, copy, nullable) IBInspectable NSString *title
+ + + + + + + + + +
+

Discussion

+

If you do not set a value for this property, the pie chart does not display a title.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

The text to display beneath the title in the pie chart view.

+
+ + + +
@property (nonatomic, copy, nullable) IBInspectable NSString *text
+ + + + + + + + + +
+

Discussion

+

If you do not set a value for this property, the pie chart does not display any text beneath the +title.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  titleColor +

+ +
+
+ +
+ + +
+

The color used for the text of the title label.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *titleColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a light gray color. Setting this property to nil resets it +to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  textColor +

+ +
+
+ +
+ + +
+

The color used for the text of the text label.

+
+ + + +
@property (nonatomic, strong, null_resettable) IBInspectable UIColor *textColor
+ + + + + + + + + +
+

Discussion

+

The default value for this property is a light gray color. Setting this property to nil resets it +to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  showsTitleAboveChart +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the title and text labels should be drawn above the chart.

+
+ + + +
@property (nonatomic) IBInspectable BOOL showsTitleAboveChart
+ + + + + + + + + +
+

Discussion

+

If this value of this property is NO, the title and text are drawn at the center of the chart. +The default value for this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  showsPercentageLabels +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the pie chart should draw percentage labels next to each +segement.

+
+ + + +
@property (nonatomic) IBInspectable BOOL showsPercentageLabels
+ + + + + + + + + +
+

Discussion

+

The default value for this property is YES.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  drawsClockwise +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the pie chart drawing animation draws clockwise or +counterclockwise.

+
+ + + +
@property (nonatomic) IBInspectable BOOL drawsClockwise
+ + + + + + + + + +
+

Discussion

+

The default value for this property is YES.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  noDataText +

+ +
+
+ +
+ + +
+

The string that will be displayed if the sum of the values of all segments is zero.

+
+ + + +
@property (nonatomic, copy, null_resettable) IBInspectable NSString *noDataText
+ + + + + + + + + +
+

Discussion

+

The default value for this property is an appropriate message string. Setting this property to +nil resets it to its default value.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– animateWithDuration: +

+ +
+
+ +
+ + +
+

Animates the pie chart when it is first displayed on the screen.

+
+ + + +
- (void)animateWithDuration:(NSTimeInterval)animationDuration
+ + + +
+

Parameters

+ + + + + + + +
animationDuration

The duration of the appearing animation.

+
+ + + + + + + +
+

Discussion

+

You can optionally call this method from the viewWillAppear: implementation of the view +controller that owns the pie chart view.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– reloadData +

+ +
+
+ +
+ + +
+

Reloads the plotted data.

+
+ + + +
- (void)reloadData
+ + + + + + + + + +
+

Discussion

+

Call this method to reload the data and re-plot the graph. You should call it if the data provided by the dataSource changes.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

  radiusScaleFactor +

+ +
+
+ +
+ + +
+

A scaling facor for the radius of the pie chart. +Increase it to increase the radius of the pie chart and vice versa.

+
+ + + +
@property (nonatomic) CGFloat radiusScaleFactor
+ + + + + + + + + +
+

Discussion

+

Defaults to 0.5.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateSkipStepNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateSkipStepNavigationRule.html new file mode 100755 index 0000000..a6b3c43 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateSkipStepNavigationRule.html @@ -0,0 +1,432 @@ + + + + + + ORKPredicateSkipStepNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPredicateSkipStepNavigationRule Class Reference

+ + +
+ + + + + + + +
Inherits fromORKSkipStepNavigationRule : NSObject
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithResultPredicate: +

+ +
+
+ +
+ + +
+

Returns an initialized predicate skip step navigation rule using the specified result predicate.

+
+ + + +
- (instancetype)initWithResultPredicate:(NSPredicate *)resultPredicate
+ + + +
+

Parameters

+ + + + + + + +
resultPredicate

A result predicate. If the result predicate matches, the step + will skip.

+
+ + + +
+

Return Value

+

An initialized skip predicate step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new predicate step navigation rule that was initialized from data in the given +unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the step navigation rule.

+
+ + + +
+

Return Value

+

A new predicate skip step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  additionalTaskResults +

+ +
+
+ +
+ + +
+

An optional array of additional task results.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKTaskResult*> *additionalTaskResults
+ + + + + + + + + +
+

Discussion

+

With this property, a task can have different navigation behavior depending on the results of +related tasks that the user may have already completed. The predicate skip step navigation rule can +use the question results within these tasks, in addition to the current task question results, to +match the result predicates.

+ +

You must ensure that all the task result identifiers are unique and that they are different from +the ongoing task result identifier. Also ensure that no task result contains question +results with duplicate identifiers. Question results can have equal identifiers provided that +they belong to different task results.

+ +

Each object in the array should be of the ORKTaskResult class.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  resultPredicate +

+ +
+
+ +
+ + +
+

The result predicate to match.

+
+ + + +
@property (nonatomic, strong, readonly) NSPredicate *resultPredicate
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– stepShouldSkipWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns whether the targeted step should skip.

+
+ + + +
- (BOOL)stepShouldSkipWithTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating whether the task should + skip.

+
+ + + +
+

Return Value

+

YES if the step should skip.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate if the targeted step should skip based on the +passed task result.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateStepNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateStepNavigationRule.html new file mode 100755 index 0000000..0bc34d9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKPredicateStepNavigationRule.html @@ -0,0 +1,723 @@ + + + + + + ORKPredicateStepNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPredicateStepNavigationRule Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepNavigationRule : NSObject
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKPredicateStepNavigationRule can be used to match any answer combination in the results of +the ongoing task (or in those of previously completed tasks) and jump accordingly. You must provide +one or more result predicates (each predicate can match one or more step results within the task).

+ +

Predicate step navigation rules contain an arbitrary number of result predicates with a +corresponding number of destination step identifiers, plus an optional default step identifier that +is used if none of the result predicates match. One result predicate can match one or more question +results; if matching several question results, that predicate can belong to the same or to +different task results). This rule allows you to define arbitrarily complex task navigation +behaviors.

+ +

The ORKResultPredicate class provides convenience class methods to build predicates for all the +ORKQuestionResult subtypes. Predicates must supply both the task result identifier and the +question result identifier, in addition to one or more expected answers.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithResultPredicates:destinationStepIdentifiers:defaultStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized predicate step navigation rule using the specified result predicates, +destination step identifiers, and an optional default step identifier.

+
+ + + +
- (instancetype)initWithResultPredicates:(NSArray<NSPredicate*> *)resultPredicates destinationStepIdentifiers:(NSArray<NSString*> *)destinationStepIdentifiers defaultStepIdentifier:(nullable NSString *)defaultStepIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultPredicates

An array of result predicates. Each result predicate can match + one or more question results in the ongoing task result or + in any of the additional task results.

destinationStepIdentifiers

An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the result predicates parameters. If you want for a + certain predicate match to end te task, you achieve that by + using the ORKNullStepIdentifier constant.

defaultStepIdentifier

The identifier of the step, which is used if none of the + result predicates match. If this argument is nil and none + of the predicates match, the default ordered task navigation + behavior takes place (that is, the task goes to the next + step in order).

+
+ + + +
+

Return Value

+

An initialized predicate step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithResultPredicates:destinationStepIdentifiers: +

+ +
+
+ +
+ + +
+

Returns an initialized predicate step navigation rule using the specified result predicates and +destination step identifiers.

+
+ + + +
- (instancetype)initWithResultPredicates:(NSArray<NSPredicate*> *)resultPredicates destinationStepIdentifiers:(NSArray<NSString*> *)destinationStepIdentifiers
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultPredicates

An array of result predicates. Each result predicate can match + one or more question results in the ongoing task result or + in any of the additional task results.

destinationStepIdentifiers

An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the result predicates parameters.

+
+ + + +
+

Return Value

+

An initialized predicate step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new predicate step navigation rule that was initialized from data in the given +unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the step navigation rule.

+
+ + + +
+

Return Value

+

A new predicate step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  additionalTaskResults +

+ +
+
+ +
+ + +
+

An optional array of additional task results.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKTaskResult*> *additionalTaskResults
+ + + + + + + + + +
+

Discussion

+

With this property, a task can have different navigation behavior depending on the results of +related tasks that the user may have already completed. The predicate step navigation rule can use +the question results within these tasks, in addition to the current task question results, to match +the result predicates.

+ +

You must ensure that all the task result identifiers are unique and that they are different from +the ongoing task result identifier. Also ensure that no task result contains question +results with duplicate identifiers. Question results can have equal identifiers provided that +they belong to different task results.

+ +

Each object in the array should be of the ORKTaskResult class.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  resultPredicates +

+ +
+
+ +
+ + +
+

The array of result predicates.

+
+ + + +
@property (nonatomic, copy, readonly) NSArray<NSPredicate*> *resultPredicates
+ + + + + + + + + +
+

Discussion

+

This property contains one result predicate for each of the step identifiers in the +destinationStepIdentifiers property.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  destinationStepIdentifiers +

+ +
+
+ +
+ + +
+

The array of destination step identifiers. It contains one step identifier for each of the +predicates in the resultPredicates parameter.

+
+ + + +
@property (nonatomic, copy, readonly) NSArray<NSString*> *destinationStepIdentifiers
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+ +

  defaultStepIdentifier +

+ +
+
+ +
+ + +
+

The identifier of the step that is used if none of the result predicates match.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSString *defaultStepIdentifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– initWithResultPredicates:destinationStepIdentifiers:defaultStepIdentifier:validateArrays: +

+ +
+
+ +
+ + +
+

Returns an initialized predicate step navigation rule using the specified result predicates, +destination step identifiers, and an optional default step identifier.

+
+ + + +
- (instancetype)initWithResultPredicates:(NSArray<NSPredicate*> *)resultPredicates destinationStepIdentifiers:(NSArray<NSString*> *)destinationStepIdentifiers defaultStepIdentifier:(NSString *)defaultStepIdentifier validateArrays:(BOOL)validateArrays
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
resultPredicates

An array of result predicates. Each result predicate can match + one or more step results in the ongoing task.

destinationStepIdentifiers

An array of possible destination step identifiers. This array + must contain one step identifier for each of the predicates + in the resultPredicates parameter.

defaultStepIdentifier

The identifier of the step which is used if none of the + result predicates match. If this argument is nil and none + of the predicates match, the default ordered task navigation + behavior takes place (that is, the task goes to the next step in + order).

validateArrays

YES to throw an exception if result predicates or + destination step identifiers are nil or empty; NO to skip + their validation.

+
+ + + +
+

Return Value

+

An initialized predicate step navigation rule.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule_Private.h

+
+ + +
+
+
+ +

– identifierForDestinationStepWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns the target step identifier.

+
+ + + +
- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating the destination step.

+
+ + + +
+

Return Value

+

The identifier of the destination step.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate the next step based on the passed task result. +The ORKNullStepIdentifier constant can be returned to indicate that the ongoing task should end +after the step navigation rule is triggered.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionResult.html new file mode 100755 index 0000000..51a5c25 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionResult.html @@ -0,0 +1,263 @@ + + + + + + ORKQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKQuestionResult class is the base class for leaf results from an item that uses an answer format (ORKAnswerFormat).

+ +

A question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+ +

See also: ORKQuestionStep and ORKFormItem.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– isSaveable +

+ +
+
+ +
+ + +
+

A boolean value indicating whether this result can be saved in a save and +restore procedure.

+
+ + + +
- (BOOL)isSaveable
+ + + + + + + + + +
+

Discussion

+

This is currently considered a private method, but overriding the getter in a result +is the correct way to prevent this result being considered as saveable for +the purpose of deciding whether to offer a “Save” option when the user +cancels a task in progress.

+ +

ORKResult subclasses should return YES if they have data that the user +might want to be able to restore if the task were interrupted and later +resumed from the current state.

+
+ + + + + + + +
+

Declared In

+

ORKResult_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  questionType +

+ +
+
+ +
+ + +
+

A value that indicates the type of question the result came from.

+
+ + + +
@property (nonatomic) ORKQuestionType questionType
+ + + + + + + + + +
+

Discussion

+

The value of questionType generally correlates closely with the class, but it can be +easier to use this value in a switch statement in Objective-C.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStep.html new file mode 100755 index 0000000..52c8a3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStep.html @@ -0,0 +1,847 @@ + + + + + + ORKQuestionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKQuestionStep.h
ORKQuestionStep.m
+ + + + +
+ +

Overview

+

The ORKQuestionStep class is a concrete subclass of ORKStep that represents +a step in which a single question is presented to the user.

+ +

To use a question step, instantiate an ORKQuestionStep object, fill in its properties, and include it +in a task. Next, create a task view controller for the task and present it. +When the task completes, the user’s answer is encoded in the result hierarchy +in the task view controller.

+ +

When a task view controller presents an ORKQuestionStep object, it instantiates an ORKQuestionStepViewController object to present the step. The actual +visual presentation depends on the answer format.

+ +

When you need to present more than one question at the same time, it can be appropriate +to use ORKFormStep instead of ORKQuestionStep.

+ +

The result of a question step is an ORKStepResult object that includes a single child +(ORKQuestionResult).

+ +

Deprecated in v2.0 (scheduled for removal).

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

+ questionStepWithIdentifier:title:question:answer: +

+ +
+
+ +
+ + +
+

Returns a new question step that includes the specified identifier, title, question, and answer format.

+
+ + + +
+ (instancetype)questionStepWithIdentifier:(NSString *)identifier title:(nullable NSString *)title question:(nullable NSString *)question answer:(nullable ORKAnswerFormat *)answerFormat
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

title

A localized string that represents the primary text of the question.

question

A localized string that represents the question as a text.

answerFormat

The format in which the answer is expected.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The question type. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

The value of this property is derived from the answer format.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types the step requests for reading. (read-only)

+
+ + + +
- (NSSet<HKObjectType*> *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this set of types when constructing a list of +all the HealthKit types required by all the steps in a task, so that it can +present the HealthKit access dialog just once during that task.

+ +

By default, the property scans the recorders and collates the HealthKit +types the recorders require. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  answerFormat +

+ +
+
+ +
+ + +
+

The format of the answer.

+
+ + + +
@property (nonatomic, strong, nullable) ORKAnswerFormat *answerFormat
+ + + + + + + + + +
+

Discussion

+

For example, the answer format might include the type of data to collect, the constraints +to place on the answer, or a list of available choices (in the case of single +or multiple select questions).

+
+ + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+ +

  question +

+ +
+
+ +
+ + +
+

The question for the step.

+
+ + + +
@property (nonatomic, strong, nullable) NSString *question
+ + + + + + + + + +
+

Discussion

+

Different from the step title.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+ +

  placeholder +

+ +
+
+ +
+ + +
+

A localized string that represents the placeholder text displayed before an answer has been entered.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *placeholder
+ + + + + + + + + +
+

Discussion

+

For numeric and text-based answers, the placeholder content is displayed in the +text field or text area when an answer has not yet been entered.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+ +

  useCardView +

+ +
+
+ +
+ + +
+

A property to present the question with a card view. Default to YES;

+
+ + + +
@property (nonatomic) BOOL useCardView
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKQuestionStep.h

+
+ + +
+
+
+
+ + + +

Deprecated Methods

+ +
+
+ +

+ questionStepWithIdentifier:title:answer: +

+ +
+
+ +
+ + +
+

Returns a new question step that includes the specified identifier, title, question, and answer format.

+
+ + + +
+ (instancetype)questionStepWithIdentifier:(NSString *)identifier title:(nullable NSString *)title answer:(nullable ORKAnswerFormat *)answerFormat
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

title

A localized string that represents the question.

answerFormat

The format in which the answer is expected.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDeprecated.h

+
+ + +
+
+
+ +

+ questionStepWithIdentifier:title:text:answer: +

+ +
+
+ +
+ + +
+

Returns a new question step that includes the specified identifier, title, question, and answer format.

+
+ + + +
+ (instancetype)questionStepWithIdentifier:(NSString *)identifier title:(nullable NSString *)title text:(nullable NSString *)text answer:(nullable ORKAnswerFormat *)answerFormat
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

title

A localized string that represents the question.

text

The primary text shown below the title string.

answerFormat

The format in which the answer is expected.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDeprecated.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepCustomView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepCustomView.html new file mode 100755 index 0000000..95922c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepCustomView.html @@ -0,0 +1,239 @@ + + + + + + ORKQuestionStepCustomView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionStepCustomView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKCustomStepView.h
ORKCustomStepView.m
+ + + + +
+ +

Overview

+

The ORKQuestionStepCustomView class is a base class for views that are used to +display question steps (ORKQuestionStep objects) in a question step view controller +(an ORKQuestionStepViewController object).

+ +

Typically, you subclass ORKQuestionStepCustomView only when you need to implement a new +answer format for the survey engine.

+ +

To ensure that your subclass is allocated the display space it requires, you should implement +sizeThatFits:, or include internal constraints, or report an intrinsic content size.

+
+ + + + + +
+ + + + + + +
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate of the question step custom view.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKQuestionStepCustomViewDelegate> delegate
+ + + + + + + + + +
+

Discussion

+

A question step custom view should report changes in its result property.

+
+ + + + + + + +
+

Declared In

+

ORKCustomStepView.h

+
+ + +
+
+
+ +

  answer +

+ +
+
+ +
+ + +
+

The answer to the question, which should be represented as a JSON-serializable atomic type.

+
+ + + +
@property (nonatomic, copy, nullable) id answer
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKCustomStepView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepViewController.html new file mode 100755 index 0000000..83764a6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKQuestionStepViewController.html @@ -0,0 +1,603 @@ + + + + + + ORKQuestionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKQuestionStepViewController.h
ORKQuestionStepViewController.m
+ + + + +
+ +

Overview

+

The ORKQuestionStepViewController class is the concrete ORKStepViewController +implementation for ORKQuestionStep.

+ +

You should not need to instantiate an ORKQuestionStepViewController object +directly. Instead, create an ORKQuestionStep object, include it in a task +the task using a task view controller. The task view +controller automatically instantiates the question step view controller +when it needs to present a question step.

+ +

To use ORKQuestionStepViewController directly, create an ORKQuestionStep object and use +initWithStep: to initialize it. To receive the result of the question, and to determine +when to dismiss the view controller, implement ORKStepViewControllerDelegate.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– skipForward +

+ +
+
+ +
+ + +
+

This method is called when the user taps the skip button. By default, it calls goForward.

+
+ + + +
- (void)skipForward
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– goForward +

+ +
+
+ +
+ + +
+

Navigates forward to the next step.

+
+ + + +
- (void)goForward
+ + + + + + + + + +
+

Discussion

+

When a user taps a Next button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– goBackward +

+ +
+
+ +
+ + +
+

Navigates backward to the previous step.

+
+ + + +
- (void)goBackward
+ + + + + + + + + +
+

Discussion

+

When a user taps the Back button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  customQuestionView +

+ +
+
+ +
+ + +
+

Provide a custom question view.

+
+ + + +
@property (nonatomic, strong, nullable) ORKQuestionStepCustomView *customQuestionView
+ + + + + + + + + +
+

Discussion

+

If a question requires a custom control for data entry, provide a suitable +custom step view. This view should provide -sizeThatFits: or autolayout +constraints which determine the vertical space required.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionStepViewController_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionResult.html new file mode 100755 index 0000000..8f6ade9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionResult.html @@ -0,0 +1,228 @@ + + + + + + ORKRangeOfMotionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRangeOfMotionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKRangeOfMotionResult.h
ORKRangeOfMotionResult.m
+ + + + +
+ +

Overview

+

The ORKRangeOfMotionResult class records the results of a range of motion active task.

+ +

An ORKRangeOfMotionResult object records the flexion and extension values in degrees.

+
+ + + + + +
+ + + + + + +
+
+ +

  flexed +

+ +
+
+ +
+ + +
+

The degrees when bent.

+
+ + + +
@property (nonatomic, assign) double flexed
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRangeOfMotionResult.h

+
+ + +
+
+
+ +

  extended +

+ +
+
+ +
+ + +
+

The degrees when extended.

+
+ + + +
@property (nonatomic, assign) double extended
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRangeOfMotionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStep.html new file mode 100755 index 0000000..82e5ad3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStep.html @@ -0,0 +1,275 @@ + + + + + + ORKRangeOfMotionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRangeOfMotionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKRangeOfMotionStep.h
ORKRangeOfMotionStep.m
+ + + + +
+ +

Overview

+

The ORKRangeOfMotionStep class represents a step that takes a range of motion measurement.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStepViewController.html new file mode 100755 index 0000000..42210ce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRangeOfMotionStepViewController.html @@ -0,0 +1,204 @@ + + + + + + ORKRangeOfMotionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRangeOfMotionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKRangeOfMotionStepViewController.h
ORKRangeOfMotionStepViewController.m
+ + + + +
+ +

Overview

+

This class is used by the ORKRangeOfMotionStep. Its result corresponds to the device’s orientation +as recorded by CoreMotion.

+
+ + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeResult.html new file mode 100755 index 0000000..b287c8c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeResult.html @@ -0,0 +1,131 @@ + + + + + + ORKReactionTimeResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKReactionTimeResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKReactionTimeResult.h
ORKReactionTimeResult.m
+ + + + +
+ +

Overview

+

The ORKReactionTimeResult class represents the result of a single successful attempt within an ORKReactionTimeStep.

+ +

The timestamp property is equal to the value of systemUptime (in NSProcessInfo) when the stimulus occurred. +Each entry of motion data in this file contains a time interval which may be directly compared to timestamp in order to determine the elapsed time since the stimulus.

+ +

The fileResult property references the motion data recorded from the beginning of the attempt until the threshold acceleration was reached. +Using the time taken to reach the threshold acceleration as the reaction time of a participant will yield a rather crude measurement. Rather, you should devise your own method using the data recorded to obtain an accurate approximation of the true reaction time.

+ +

A reaction time result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize the sample for transmission to a server +or to immediately perform analysis on it.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeStep.html new file mode 100755 index 0000000..575a7d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeStep.html @@ -0,0 +1,304 @@ + + + + + + ORKReactionTimeStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKReactionTimeStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKReactionTimeStep.h
ORKReactionTimeStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeViewController.html new file mode 100755 index 0000000..af0255d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReactionTimeViewController.html @@ -0,0 +1,249 @@ + + + + + + ORKReactionTimeViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKReactionTimeViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKReactionTimeViewController.h
ORKReactionTimeViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorder.html new file mode 100755 index 0000000..85335c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorder.html @@ -0,0 +1,818 @@ + + + + + + ORKRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKRecorder.h
ORKRecorder.m
+ + + + +
+ +

Overview

+

A recorder is the runtime companion to an ORKRecorderConfiguration object, and is +usually generated by one.

+ +

During active tasks, it is often useful to collect one or more pieces of data +from sensors on the device. In research tasks, it’s not always +necessary to display that data, but it’s important to record it in a controlled manner.

+ +

An active step (ORKActiveStep) has an array of recorder configurations +(ORKRecorderConfiguration) that identify the types of data it needs to record +for the duration of the step. When a step starts, the active step view controller +instantiates a recorder for each of the step’s recorder configurations. +The step view controller starts the recorder when the active step is started, and stops the +recorder when the active step is finished.

+ +

The results of recording are typically written to a file specified by the value of the outputDirectory property.

+ +

Usually, the ORKActiveStepViewController object is the recorder’s delegate, and it +receives callbacks when errors occur or when recording is complete.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder.

step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

An initialized recorder.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– viewController:willStartStepWithView: +

+ +
+
+ +
+ + +
+

A preparation step to provide viewController and view before record starting.

+
+ + + +
- (void)viewController:(UIViewController *)viewController willStartStepWithView:(UIView *)view
+ + + +
+

Parameters

+ + + + + + + + + + + + +
viewController

The view controller that is about to ‘start’

view

Primary active view for the step.

+
+ + + + + + + +
+

Discussion

+

The step view controller should call this method before starting the recorder, +so that recorders that need a view or gesture recognizer in order to function +can attach themselves.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– logName +

+ +
+
+ +
+ + +
+

Returns the log prefix for the log file.

+
+ + + +
- (NSString *)logName
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– applyFileProtection:toFileAtURL: +

+ +
+
+ +
+ + +
+

Helper for subclasses to request that file protection be applied to a file on disk.

+
+ + + +
- (void)applyFileProtection:(ORKFileProtectionMode)fileProtection toFileAtURL:(NSURL *)url
+ + + +
+

Parameters

+ + + + + + + + + + + + +
fileProtection

Level of file protection desired

url

URL of file to protect.

+
+ + + + + + + +
+

Discussion

+

This method is exposed to facilitate unit testing.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Configuration

+ +
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

A short string that uniquely identifies the recorder (usually assigned by the recorder configuration).

+
+ + + +
@property (nonatomic, copy, readonly) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier is reproduced in the results of a recorder created from this configuration. In fact, the only way to link a result +(an ORKFileResult object) to the recorder that generated it is to look at the value of +identifier. To accurately identify recorder results, you need to ensure that recorder identifiers +are unique within each step.

+ +

In some cases, it can be useful to link the recorder identifier to a unique identifier in a +database; in other cases, it can make sense to make the identifier human +readable.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

  step +

+ +
+
+ +
+ + +
+

The step that produced this recorder, configured during initialization.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) ORKStep *step
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

  configuration +

+ +
+
+ +
+ + +
+

The configuration that produced this recorder.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) ORKRecorderConfiguration *configuration
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

  outputDirectory +

+ +
+
+ +
+ + +
+

The file URL of the output directory configured during initialization.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSURL *outputDirectory
+ + + + + + + + + +
+

Discussion

+

Typically, you set the outputDirectory property for the ORKTaskViewController object +before presenting the task.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ + + +

Runtime Life Cycle

+ +
+
+ +

  recording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
@property (nonatomic, readonly, getter=isRecording) BOOL recording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderConfiguration.html new file mode 100755 index 0000000..f2e204c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderConfiguration.html @@ -0,0 +1,515 @@ + + + + + + ORKRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRecorderConfiguration Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSSecureCoding
Declared inORKRecorder.h
ORKRecorder.m
+ + + + +
+ +

Overview

+

The ORKRecorderConfiguration class is the abstract base class for recorder configurations +that can be attached to an active step (ORKActiveStep).

+ +

Recorder configurations provide an easy way to collect CoreMotion +or other sensor data into a serialized format during the duration of an active step. +If you want to filter or process the data in real time, it is better to +use the existing APIs directly.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+ +

To add a new recorder, subclass both ORKRecorderConfiguration and ORKRecorder, +and add the new ORKRecorderConfiguration subclass to an ORKActiveStep object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the recorder configuration.

+
+ + + +
+

Return Value

+

A new recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

Returns the HealthKit types for which this recorder requires read access in a set of HKSampleType objects.

+
+ + + +
- (NSSet<HKObjectType*> *)requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

Typically, the task view controller automatically collects +and collates the types of HealthKit data requested by each of the active steps in a task, +and requests access to them at the end of the initial instruction +steps in the task.

+ +

If your recorder requires or would benefit from read access to HealthKit at +runtime during the task, return the appropriate set of HKSampleType objects.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

A short string that uniquely identifies the recorder configuration within the step.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier is reproduced in the results of a recorder created from this configuration. In fact, the only way to link a result +(an ORKFileResult object) to the recorder that generated it is to look at the value of +identifier. To accurately identify recorder results, you need to ensure that recorder identifiers +are unique within each step.

+ +

In some cases, it can be useful to link the recorder identifier to a unique identifier in a +database; in other cases, it can make sense to make the identifier human +readable.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderTests.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderTests.html new file mode 100755 index 0000000..94eb62b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRecorderTests.html @@ -0,0 +1,263 @@ + + + + + + ORKRecorderTests Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRecorderTests Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromXCTestCase
Conforms toORKRecorderDelegate
Declared inORKRecorderTests.m
+ + + + + + +
+ + + + + + +
+
+ +

– recorder:didCompleteWithResult: +

+ +
+
+ +
+ + +
+

Tells the delegate that the recorder has completed with the specified result.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

result

The generated result.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when recording is stopped.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorder:didFailWithError: +

+ +
+
+ +
+ + +
+

Tells the delegate that recording failed.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

error

The error that occurred.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when the error occurred.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRegistrationStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRegistrationStep.html new file mode 100755 index 0000000..fa5302a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKRegistrationStep.html @@ -0,0 +1,763 @@ + + + + + + ORKRegistrationStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRegistrationStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStep : ORKStep : NSObject
Declared inORKRegistrationStep.h
ORKRegistrationStep.m
+ + + + +
+ +

Overview

+

The ORKRegistrationStep class represents a form step that provides fields commonly used +for account registration.

+ +

The registration step contains email and password fields by default. Optionally, any +of the additional fields can be included based on context and requirements.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:title:text:passcodeValidationRegularExpression:passcodeInvalidMessage:options: +

+ +
+
+ +
+ + +
+

Returns an initialized registration step using the specified identifier, +title, text, options, passcodeValidationRegularExpression, and passcodeInvalidMessage.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title text:(NSString *)text passcodeValidationRegularExpression:(NSRegularExpression *)passcodeValidationRegularExpression passcodeInvalidMessage:(NSString *)passcodeInvalidMessage options:(ORKRegistrationStepOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

passcodeValidationRegularExpression

The regular expression used to validate the passcode form item (see ORKTextAnswerFormat).

passcodeInvalidMessage

The invalid message displayed for invalid input (see ORKTextAnswerFormat).

options

The options used for the step (see ORKRegistrationStepOption).

+
+ + + +
+

Return Value

+

An initialized registration step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:title:text:options: +

+ +
+
+ +
+ + +
+

Returns an initialized registration step using the specified identifier, +title, text, and options.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title text:(NSString *)text options:(ORKRegistrationStepOption)options
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

options

The options used for the step (see ORKRegistrationStepOption).

+
+ + + +
+

Return Value

+

An initialized registration step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:title:text: +

+ +
+
+ +
+ + +
+

Returns an initialized form step using the specified identifier, title, and text.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier title:(NSString *)title text:(NSString *)text
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

title

The title of the form (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

+
+ + + +
+

Return Value

+

As initialized form step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– formItems +

+ +
+
+ +
+ + +
+

The array of items in the form.

+
+ + + +
- (NSArray<ORKFormItem*> *)formItems
+ + + + + + + + + +
+

Discussion

+

A form step that contains no items is considered invalid and an exception will be thrown +when it is presented.

+
+ + + + + + + +
+

Declared In

+

ORKFormStep.h

+
+ + +
+
+
+ +

– passcodeValidationRegularExpression +

+ +
+
+ +
+ + +
+

The regular expression used to validate the passcode form item. +This is a transparent property pointing to its definition in ORKTextAnswerFormat.

+
+ + + +
- (NSRegularExpression *)passcodeValidationRegularExpression
+ + + + + + + + + +
+

Discussion

+

The passcode invalid message property must also be set along with this property. +By default, there is no validation on the passcode.

+
+ + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– passcodeInvalidMessage +

+ +
+
+ +
+ + +
+

The invalid message displayed if the passcode does not match the validation regular expression. +This is a transparent property pointing to its definition in ORKTextAnswerFormat.

+
+ + + +
- (NSString *)passcodeInvalidMessage
+ + + + + + + + + +
+

Discussion

+

The passcode validation regular expression property must also be set along with this property. +By default, there is no invalid message.

+
+ + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– phoneNumberValidationRegularExpression +

+ +
+
+ +
+ + +
+

The regular expression used to validate the phone number form item. +This is a transparent property pointing to its definition in ORKTextAnswerFormat.

+
+ + + +
- (NSRegularExpression *)phoneNumberValidationRegularExpression
+ + + + + + + + + +
+

Discussion

+

The phone number invalid message property must also be set along with this property. +By default, there is no validation on the phone number.

+
+ + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– phoneNumberInvalidMessage +

+ +
+
+ +
+ + +
+

The invalid message displayed if the phone number does not match the validation regular expression. +This is a transparent property pointing to its definition in ORKTextAnswerFormat.

+
+ + + +
- (NSString *)phoneNumberInvalidMessage
+ + + + + + + + + +
+

Discussion

+

The phone number validation regular expression property must also be set along with this property. +By default, there is no invalid message.

+
+ + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  options +

+ +
+
+ +
+ + +
+

The options used for the step.

+
+ + + +
@property (nonatomic, readonly) ORKRegistrationStepOption options
+ + + + + + + + + +
+

Discussion

+

These options allow one or more fields to be included in the registration step.

+
+ + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResult.html new file mode 100755 index 0000000..e847064 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResult.html @@ -0,0 +1,507 @@ + + + + + + ORKResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKResult Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKResult.h
ORKResult.m
+ + + + +
+ +

Overview

+

The ORKResult class defines the attributes of a result from one step or a group +of steps. When you use the ResearchKit framework APIs, you typically get a result from the result property +of either ORKTaskViewController or ORKStepViewController. +Certain types of results can contain other results, which together express a hierarchy; examples of these types of results are ORKCollectionResult subclasses, such as ORKStepResult and ORKTaskResult.

+ +

When you receive a result, you can store it temporarily by archiving it with +NSKeyedArchiver, because all ORKResult objects implement NSSecureCoding. If you want to serialize the result object to other formats, you’re responsible for implementing this.

+ +

The result object hierarchy does not necessarily include all the data collected +during a task. Some result objects, such as ORKFileResult, may refer to files +in the filesystem that were generated during the task. These files are easy to find, because they are all +located in the output directory of the task view controller.

+ +

It’s recommended that you use NSFileProtectionComplete (at a minimum) to protect these files, and that you similarly protect all serialization of ORKResult objects that you write to disk. It is also generally helpful to keep the results together with the referenced files as you submit them to a back-end server. For example, it can be convenient to zip all data corresponding to a particular task result into a single compressed archive.

+ +

Every object in the result hierarchy has an identifier that should correspond +to the identifier of an object in the original step hierarchy. Similarly, every +object has a start date and an end date that correspond to the range of +times during which the result was collected. In an ORKStepResult object, for example, +the start and end dates cover the range of time during which the step view controller was visible on +screen.

+ +

When you implement a new type of step, it is usually helpful to create a new +ORKResult subclass to hold the type of result data the step can generate, unless it makes sense to use an existing subclass. Return your custom result subclass as one of the results attached to the step’s ORKStepResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized result using the specified identifier.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the result.

+
+ + + + + + + +
+

Discussion

+

Typically, objects such as ORKStepViewController and ORKTaskViewController instantiate result (and ORKResult subclass) objects; you seldom need to instantiate a result object in your code.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

A meaningful identifier for the result.

+
+ + + +
@property (nonatomic, copy) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier can be used to identify the question +that was asked or the task that was completed to produce the result. Typically, the identifier is copied from the originating object by the view controller or recorder that produces it.

+ +

For example, a task result receives its identifier from a task, +a step result receives its identifier from a step, +and a question result receives its identifier from a step or a form item. +Results that are generated by recorders also receive an identifier that corresponds to +that recorder.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+ +

  startDate +

+ +
+
+ +
+ + +
+

The time when the task, step, or data collection began.

+
+ + + +
@property (nonatomic, copy) NSDate *startDate
+ + + + + + + + + +
+

Discussion

+

The value of this property is set by the view controller or recorder that produces the result, +to indicate when data collection started.

+ +

Note that for instantaneous items, startDate and endDate can have the same value, and should +generally correspond to the end of the instantaneous data collection period.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+ +

  endDate +

+ +
+
+ +
+ + +
+

The time when the task, step, or data collection stopped.

+
+ + + +
@property (nonatomic, copy) NSDate *endDate
+ + + + + + + + + +
+

Discussion

+

The value of this property is set by the view controller or recorder that produces the result, +to indicate when data collection stopped.

+ +

Note that for instantaneous items, startDate and endDate can have the same value, and should +generally correspond to the end of the instantaneous data collection period.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+ +

  userInfo +

+ +
+
+ +
+ + +
+

Metadata that describes the conditions under which the result was acquired.

+
+ + + +
@property (nonatomic, copy, nullable) NSDictionary *userInfo
+ + + + + + + + + +
+

Discussion

+

The userInfo dictionary can be set by the view controller or recorder +that produces the result. However, it’s often a better choice to use a new ORKResult subclass for passing additional information back to code that uses +the framework, because using +typed accessors is safer than using a dictionary.

+ +

The user info dictionary must contain only keys and values that are suitable for property +list or JSON serialization.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  saveable +

+ +
+
+ +
+ + +
+

A boolean value indicating whether this result can be saved in a save and +restore procedure.

+
+ + + +
@property (nonatomic, readonly, getter=isSaveable) BOOL saveable
+ + + + + + + + + +
+

Discussion

+

This is currently considered a private method, but overriding the getter in a result +is the correct way to prevent this result being considered as saveable for +the purpose of deciding whether to offer a “Save” option when the user +cancels a task in progress.

+ +

ORKResult subclasses should return YES if they have data that the user +might want to be able to restore if the task were interrupted and later +resumed from the current state.

+
+ + + + + + + +
+

Declared In

+

ORKResult_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultPredicate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultPredicate.html new file mode 100755 index 0000000..a09d37e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultPredicate.html @@ -0,0 +1,1693 @@ + + + + + + ORKResultPredicate Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKResultPredicate Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKResultPredicate.h
ORKResultPredicate.m
+ + + + +
+ +

Overview

+

The ORKResultPredicate class provides convenience class methods to build predicates for most of +the ORKQuestionResult subtypes.

+ +

You use result predicates to create ORKPredicateStepNavigationRule objects. The result predicates +are used to match specific ORKQuestionResult instances (created in response to the participant’s +answers) and navigate accordingly. You can match results both in an ongoing task or in previously +completed tasks.

+ +

You chose which question result to match by using an ORKResultSelector object.

+ +

Note that each ORKStep object produces one ORKStepResult collection object. A step +result produced by an ORKQuestionStep object contains one ORKQuestionResult object which has

+ +

the same identifier as the step that generated it. A step result produced by an ORKFormStep +object can contain one or more ORKQuestionResult objects that have the identifiers of the +ORKFormItem objects that generated them.

+ +

For matching a single-question step result, you only need to set the resultIdentifier when +building the result selector object. The stepIdentifier will take the same value.

+ +

For matching a form item result, you need to build a result selector with a stepIdentifier (the +form step identifier) and a resultIdentifier (the form item result identifier).

+ +

For matching results in the ongoing task, leave the taskIdentifier in the the form step identifier +as nil. For matching results in different tasks, set the taskIdentifier appropriately.

+
+ + + + + +
+ + + + + + +
+
+ +

+ predicateForNilQuestionResultWithResultSelector: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of the kind ORKQuestionResult whose answer is nil. +A question result has a nil answer if it was generated by a step that was skipped by +the user or if it was part of a form step and the question was left unanswered.

+
+ + + +
+ (NSPredicate *)predicateForNilQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector
+ + + +
+

Parameters

+ + + + + + + +
resultSelector

The result selector object which specifies the question result you are +interested in.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForScaleQuestionResultWithResultSelector:expectedAnswer: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKScaleQuestionResult whose answer is the +specified integer value.

+
+ + + +
+ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedAnswer:(NSInteger)expectedAnswer
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

expectedAnswer

The expected integer value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForScaleQuestionResultWithResultSelector:minimumExpectedAnswerValue:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKScaleQuestionResult whose answer is within the +specified double values.

+
+ + + +
+ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected double value. Pass ORKIgnoreDoubleValue + if you don’t want to compare the answer against a maximum + double value.

maximumExpectedAnswerValue

The maximum expected double value. Pass ORKIgnoreDoubleValue + if you don’t want to compare the answer against a maximum + double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForScaleQuestionResultWithResultSelector:minimumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKScaleQuestionResult whose answer is greater than +or equal to the specified double value.

+
+ + + +
+ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForScaleQuestionResultWithResultSelector:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKScaleQuestionResult whose answer is less than or +equal to the specified double value.

+
+ + + +
+ (NSPredicate *)predicateForScaleQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

maximumExpectedAnswerValue

The maximum expected double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForChoiceQuestionResultWithResultSelector:expectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKChoiceQuestionResult whose answer is equal to +the specified object.

+
+ + + +
+ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedAnswerValue:(id<NSCopying,NSCoding,NSObject>)expectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you + are interested in.

expectedAnswerValue

The expected answer object.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForChoiceQuestionResultWithResultSelector:expectedAnswerValues: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKChoiceQuestionResult whose answers are equal to +the specified objects.

+
+ + + +
+ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedAnswerValues:(NSArray<id<NSCopying,NSCoding,NSObject> > *)expectedAnswerValues
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you + are interested in.

expectedAnswerValues

An array with a some or of all of the expected answer objects.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForChoiceQuestionResultWithResultSelector:matchingPattern: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKChoiceQuestionResult whose answer matches the +specified regular expression pattern. This predicate can solely be used to match choice results +which only contain string answers.

+
+ + + +
+ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector matchingPattern:(NSString *)pattern
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

pattern

An ICU-compliant regular expression pattern that matches the answer string.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForChoiceQuestionResultWithResultSelector:matchingPatterns: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKChoiceQuestionResult whose answers match the +specified regular expression patterns.

+
+ + + +
+ (NSPredicate *)predicateForChoiceQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector matchingPatterns:(NSArray<NSString*> *)patterns
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

patterns

An array of ICU-compliant regular expression patterns that match the answer strings.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForBooleanQuestionResultWithResultSelector:expectedAnswer: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKBooleanQuestionResult whose answer is the +specified Boolean value.

+
+ + + +
+ (NSPredicate *)predicateForBooleanQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedAnswer:(BOOL)expectedAnswer
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

expectedAnswer

The expected boolean value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTextQuestionResultWithResultSelector:expectedString: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTextQuestionResult whose answer is equal to the +specified string.

+
+ + + +
+ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedString:(NSString *)expectedString
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

expectedString

The expected result string.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTextQuestionResultWithResultSelector:matchingPattern: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTextQuestionResult whose answer matches the +specified regular expression pattern.

+
+ + + +
+ (NSPredicate *)predicateForTextQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector matchingPattern:(NSString *)pattern
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

pattern

An ICU-compliant regular expression pattern that matches the answer string.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForNumericQuestionResultWithResultSelector:expectedAnswer: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKNumericQuestionResult whose answer is the +specified integer value.

+
+ + + +
+ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector expectedAnswer:(NSInteger)expectedAnswer
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you are + interested in.

expectedAnswer

The expected integer value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForNumericQuestionResultWithResultSelector:minimumExpectedAnswerValue:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKNumericQuestionResult whose answer is within the +specified double values.

+
+ + + +
+ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected double value. Pass ORKIgnoreDoubleValue + if you don’t want to compare the answer against a maximum + double value.

maximumExpectedAnswerValue

The maximum expected double value. Pass ORKIgnoreDoubleValue + if you don’t want to compare the answer against a minimum + double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForNumericQuestionResultWithResultSelector:minimumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKNumericQuestionResult whose answer is greater +than or equal to the specified double value.

+
+ + + +
+ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(double)minimumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForNumericQuestionResultWithResultSelector:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKNumericQuestionResult whose answer is less than +or equal to the specified double value.

+
+ + + +
+ (NSPredicate *)predicateForNumericQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector maximumExpectedAnswerValue:(double)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

maximumExpectedAnswerValue

The maximum expected double value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTimeOfDayQuestionResultWithResultSelector:minimumExpectedHour:minimumExpectedMinute:maximumExpectedHour:maximumExpectedMinute: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTimeOfDayQuestionResult whose answer is within +the specified hour and minute values.

+
+ + + +
+ (NSPredicate *)predicateForTimeOfDayQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedHour:(NSInteger)minimumExpectedHour minimumExpectedMinute:(NSInteger)minimumExpectedMinute maximumExpectedHour:(NSInteger)maximumExpectedHour maximumExpectedMinute:(NSInteger)maximumExpectedMinute
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result you + are interested in.

minimumExpectedHour

The minimum expected hour component value.

minimumExpectedMinute

The minimum expected minute component value.

maximumExpectedHour

The maximum integer hour component value.

maximumExpectedMinute

The maximum expected minute component value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + +
+

Discussion

+

Note that ORKTimeOfDayQuestionResult internally stores its answer as an NSDateComponents object. +If you are interested in additional components, you must build the predicate manually.

+
+ + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTimeIntervalQuestionResultWithResultSelector:minimumExpectedAnswerValue:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTimeIntervalQuestionResult whose answer is +within the specified NSTimeInterval values.

+
+ + + +
+ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected NSTimeInterval value. Pass + ORKIgnoreTimeIntervlValue if you don’t want to compare the + answer against a maximum NSTimeInterval value.

maximumExpectedAnswerValue

The maximum expected NSTimeInterval value. Pass + ORKIgnoreTimeIntervlValue if you don’t want to compare the + answer against a minimum NSTimeInterval value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTimeIntervalQuestionResultWithResultSelector:minimumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTimeIntervalQuestionResult whose answer is the +specified integer value.

+
+ + + +
+ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerValue:(NSTimeInterval)minimumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerValue

The minimum expected NSTimeInterval value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForTimeIntervalQuestionResultWithResultSelector:maximumExpectedAnswerValue: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKTimeIntervalQuestionResult whose answer is the +specified integer value.

+
+ + + +
+ (NSPredicate *)predicateForTimeIntervalQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector maximumExpectedAnswerValue:(NSTimeInterval)maximumExpectedAnswerValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

maximumExpectedAnswerValue

The maximum expected NSTimeInterval value.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForDateQuestionResultWithResultSelector:minimumExpectedAnswerDate:maximumExpectedAnswerDate: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKDateQuestionResult whose answer is a date within +the specified dates.

+
+ + + +
+ (NSPredicate *)predicateForDateQuestionResultWithResultSelector:(ORKResultSelector *)resultSelector minimumExpectedAnswerDate:(nullable NSDate *)minimumExpectedAnswerDate maximumExpectedAnswerDate:(nullable NSDate *)maximumExpectedAnswerDate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in.

minimumExpectedAnswerDate

The minimum expected date. Pass nil if you don’t want to + compare the answer against a minimum date.

maximumExpectedAnswerDate

The maximum expected date. Pass nil if you don’t want to + compare the answer against a maximum date.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ predicateForConsentWithResultSelector:didConsent: +

+ +
+
+ +
+ + +
+

Returns a predicate matching a result of type ORKConsentSignatureResult whose consented value +matches the specified boolean value.

+
+ + + +
+ (NSPredicate *)predicateForConsentWithResultSelector:(ORKResultSelector *)resultSelector didConsent:(BOOL)didConsent
+ + + +
+

Parameters

+ + + + + + + +
resultSelector

The result selector object which specifies the question result + you are interested in. Note that when creating this result + selector you must provide the desired step identifier as the + stepIdentifier argument and the corresponding signature + identifier as the resultIdentifier argument). The step + identifier will normally refer to the result of a + ORKConsentReviewStep and the signature identifier will + refer to the contained ORKConsentSignatureResult + corresponding to the signature collected by the consent + review step.

+
+ + + +
+

Return Value

+

A result predicate.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultSelector.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultSelector.html new file mode 100755 index 0000000..2edeb40 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKResultSelector.html @@ -0,0 +1,830 @@ + + + + + + ORKResultSelector Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKResultSelector Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKResultPredicate.h
ORKResultPredicate.m
+ + + + +
+ +

Overview

+

The ORKResultSelector class unequivocally identifies a result within a set of task results.

+ +

You must use an instance of this object to specify the question result you are interested in when +building a result predicate. See ORKResultPredicate for more information.

+ +

A result selector object contains a result identifier and, optionally, a task identifier and a step +identifier. If the task identifier is nil, the selector refers to a result in the ongoing task. +If you set the step identifier to nil, its value will be the same as the result identifier.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ selectorWithTaskIdentifier:stepIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
+ (instancetype)selectorWithTaskIdentifier:(NSString *)taskIdentifier stepIdentifier:(NSString *)stepIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskIdentifier

An optional task identifier string.

stepIdentifier

An optional step identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ selectorWithStepIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
+ (instancetype)selectorWithStepIdentifier:(NSString *)stepIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepIdentifier

An optional step identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ selectorWithTaskIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
+ (instancetype)selectorWithTaskIdentifier:(NSString *)taskIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskIdentifier

An optional task identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

+ selectorWithResultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
+ (instancetype)selectorWithResultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + +
resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

– initWithTaskIdentifier:stepIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
- (instancetype)initWithTaskIdentifier:(NSString *)taskIdentifier stepIdentifier:(NSString *)stepIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskIdentifier

An optional task identifier string.

stepIdentifier

An optional step identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

– initWithTaskIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
- (instancetype)initWithTaskIdentifier:(NSString *)taskIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskIdentifier

An optional task identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

– initWithStepIdentifier:resultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
- (instancetype)initWithStepIdentifier:(NSString *)stepIdentifier resultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepIdentifier

An optional step identifier string.

resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

– initWithResultIdentifier: +

+ +
+
+ +
+ + +
+

Returns a result selector initialized with the specified arguments.

+
+ + + +
- (instancetype)initWithResultIdentifier:(NSString *)resultIdentifier
+ + + +
+

Parameters

+ + + + + + + +
resultIdentifier

The result identifier string.

+
+ + + +
+

Return Value

+

A result selector.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

– stepIdentifier +

+ +
+
+ +
+ + +
+

The encapsulated step identifier.

+
+ + + +
- (NSString *)stepIdentifier
+ + + + + + + + + +
+

Discussion

+

Setting this property to nil makes it have the same value as the result identifier.

+
+ + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  taskIdentifier +

+ +
+
+ +
+ + +
+

The encapsulated task identifier.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *taskIdentifier
+ + + + + + + + + +
+

Discussion

+

A nil value means that the referenced task is the current one.

+
+ + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+ +

  resultIdentifier +

+ +
+
+ +
+ + +
+

The encapsulated result identifier.

+
+ + + +
@property (nonatomic, copy) NSString *resultIdentifier
+ + + + + + + + + +
+

Discussion

+

This property cannot be nil.

+
+ + + + + + + +
+

Declared In

+

ORKResultPredicate.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStep.html new file mode 100755 index 0000000..1e1110f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStep.html @@ -0,0 +1,566 @@ + + + + + + ORKReviewStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKReviewStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKReviewStep.h
ORKReviewStep.m
+ + + + +
+ +

Overview

+

The ORKReviewStep class is a concrete subclass of ORKStep that represents +a step in which existing question results can be reviewed by the user.

+ +

There are two separate scenarios for using ORKReviewStep. The first one is to embed a review step within an ongoing +survey, which means an instance of ORKReviewStep might be placed at the end or in the middle of a task. The second +scenario is meant to use ORKReviewStep standalone for reviewing an already completed task.

+ +

To use a review step, instantiate an ORKReviewStep object, fill in its properties, and include it in a task. Next, +create a task view controller for the task and present it.

+ +

When a task view controller presents an ORKReviewStep object, it instantiates an ORKReviewStepViewController object +to present the step. This view controller lists both steps and step results to provide all entered data at a glance. It +also allows the user to navigate directly to a certain step. However, results may only be changed from there, if the +review step is used within an ongoing survey (embedded).

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ standaloneReviewStepWithIdentifier:steps:resultSource: +

+ +
+
+ +
+ + +
+

Returns a new standalone review step that includes the specified identifier, steps, and result source.

+
+ + + +
+ (instancetype)standaloneReviewStepWithIdentifier:(NSString *)identifier steps:(NSArray *)steps resultSource:(id<ORKTaskResultSource,NSSecureCoding>)resultSource
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

steps

The steps that should be reviewed. Currently, only question, instruction and + form steps can be reviewed. Any other step type will be ignored.

resultSource

The source that should be consulted to obtain the corresponding step results.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKReviewStep.h

+
+ + +
+
+
+ +

+ embeddedReviewStepWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns a new embedded review step that includes the specified identifier. Steps and step results are directly taken +from the current task.

+
+ + + +
+ (instancetype)embeddedReviewStepWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKReviewStep.h

+
+ + +
+
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  steps +

+ +
+
+ +
+ + +
+

The steps to be reviewed. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly) NSArray<ORKStep*> *steps
+ + + + + + + + + +
+

Discussion

+

This property contains all steps that are included in the review process. Currently, only question, instruction and +form steps can be reviewed. Any other step type will be ignored.

+
+ + + + + + + +
+

Declared In

+

ORKReviewStep.h

+
+ + +
+
+
+ +

  resultSource +

+ +
+
+ +
+ + +
+

The result source to obtain step results from. (read-only)

+
+ + + +
@property (nonatomic, readonly) id<ORKTaskResultSource,NSSecureCoding> resultSource
+ + + + + + + + + +
+

Discussion

+

This property contains the source that should be consulted to obtain step results.

+
+ + + + + + + +
+

Declared In

+

ORKReviewStep.h

+
+ + +
+
+
+ +

  excludeInstructionSteps +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether instruction steps should be excluded from review.

+
+ + + +
@property (nonatomic) BOOL excludeInstructionSteps
+ + + + + + + + + +
+

Discussion

+

The default value of this property is NO. When the value is YES, any instances of ORKInstructionStep are +excluded from the review step in either embedded or standalone mode.

+
+ + + + + + + +
+

Declared In

+

ORKReviewStep.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  isStandalone +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether this review step is used in standalone mode (read-only).

+
+ + + +
@property (nonatomic, readonly) BOOL isStandalone
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKReviewStep_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStepViewController.html new file mode 100755 index 0000000..86841bf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKReviewStepViewController.html @@ -0,0 +1,191 @@ + + + + + + ORKReviewStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKReviewStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKReviewStepViewController.h
ORKReviewStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleAnswerFormat.html new file mode 100755 index 0000000..eaee5d0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleAnswerFormat.html @@ -0,0 +1,1084 @@ + + + + + + ORKScaleAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKScaleAnswerFormatclass represents an answer format that includes a slider control.

+ +

The scale answer format produces an ORKScaleQuestionResult object that contains an integer whose +value is between the scale’s minimum and maximum values, and represents one of the quantized step +values.

+ +

The following are the rules bound with scale answer format -

+ +
    +
  • Minimum number of step in a task should not be less than 1.
  • +
  • Minimum number of section on a scale (step count) should not be less than 1.
  • +
  • Maximum number of section on a scale (step count) should not be more than 13.
  • +
  • The lower bound value in scale answer format cannot be lower than - 10000.
  • +
  • The upper bound value in scale answer format cannot be more than 10000.
  • +
+ +
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:step:vertical:maximumValueDescription:minimumValueDescription: +

+ +
+
+ +
+ + +
+

Returns an initialized scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(NSInteger)maximumValue minimumValue:(NSInteger)minimumValue defaultValue:(NSInteger)defaultValue step:(NSInteger)step vertical:(BOOL)vertical maximumValueDescription:(nullable NSString *)maximumValueDescription minimumValueDescription:(nullable NSString *)minimumValueDescription
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, + the slider is displayed without a default value.

step

The size of each discrete offset on the scale.

vertical

Pass YES to use a vertical scale; for the default horizontal + scale, pass NO.

maximumValueDescription

A localized label to describe the maximum value of the scale. + For none, pass nil.

minimumValueDescription

A localized label to describe the minimum value of the scale. + For none, pass nil.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:step:vertical: +

+ +
+
+ +
+ + +
+

Returns an initialized scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(NSInteger)maximumValue minimumValue:(NSInteger)minimumValue defaultValue:(NSInteger)defaultValue step:(NSInteger)step vertical:(BOOL)vertical
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, the slider is + displayed without a default value.

step

The size of each discrete offset on the scale.

vertical

Pass YES to use a vertical scale; for the default horizontal scale, + pass NO.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMaximumValue:minimumValue:defaultValue:step: +

+ +
+
+ +
+ + +
+

Returns an initialized horizontal scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithMaximumValue:(NSInteger)maximumValue minimumValue:(NSInteger)minimumValue defaultValue:(NSInteger)defaultValue step:(NSInteger)step
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
maximumValue

The upper bound of the scale.

minimumValue

The lower bound of the scale.

defaultValue

The default value of the scale. If this value is out of range, the slider is + displayed without a default value.

step

The size of each discrete offset on the scale.

+
+ + + +
+

Return Value

+

An initialized scale answer format.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximum +

+ +
+
+ +
+ + +
+

The upper bound of the scale. (read-only)

+
+ + + +
@property (readonly) NSInteger maximum
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimum +

+ +
+
+ +
+ + +
+

The lower bound of the scale. (read-only)

+
+ + + +
@property (readonly) NSInteger minimum
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  step +

+ +
+
+ +
+ + +
+

The size of each discrete offset on the scale. (read-only)

+
+ + + +
@property (readonly) NSInteger step
+ + + + + + + + + +
+

Discussion

+

The value of this property should be greater than zero. +The difference between maximumValue and minimumValue should be divisible +by the step value.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultValue +

+ +
+
+ +
+ + +
+

The default value for the slider. (read-only)

+
+ + + +
@property (readonly) NSInteger defaultValue
+ + + + + + + + + +
+

Discussion

+

If the value of this property is less than minimum or greater than maximum, the slider has no +default. Otherwise, the value is rounded to the nearest valid step value.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  vertical +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the scale is oriented vertically. (read-only)

+
+ + + +
@property (readonly, getter=isVertical) BOOL vertical
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  numberFormatter +

+ +
+
+ +
+ + +
+

Number formatter applied to the minimum, maximum, and slider values. Can be overridden by +subclasses.

+
+ + + +
@property (readonly) NSNumberFormatter *numberFormatter
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumValueDescription +

+ +
+
+ +
+ + +
+

A localized label to describe the maximum value of the scale. (read-only)

+
+ + + +
@property (readonly, nullable) NSString *maximumValueDescription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumValueDescription +

+ +
+
+ +
+ + +
+

A localized label to describe the minimum value of the scale. (read-only)

+
+ + + +
@property (readonly, nullable) NSString *minimumValueDescription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumImage +

+ +
+
+ +
+ + +
+

An image for the upper bound of the slider. The recommended image size is 30 x 30 points. +The maximum range label will not be visible.

+
+ + + +
@property (strong, nullable) UIImage *maximumImage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumImage +

+ +
+
+ +
+ + +
+

An image for the lower bound of the slider. The recommended image size is 30 x 30 points. +The minimum range label will not be visible.

+
+ + + +
@property (strong, nullable) UIImage *minimumImage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientColors +

+ +
+
+ +
+ + +
+

The colors to use when drawing a color gradient above the slider. Colors are drawn such that +lower indexes correspond to the minimum side of the scale, while colors at higher indexes in +the array corresond to the maximum side of the scale.

+
+ + + +
@property (copy, nullable) NSArray<UIColor*> *gradientColors
+ + + + + + + + + +
+

Discussion

+

Setting this value to nil results in no gradient being drawn. Defaults to nil.

+ +

An example usage would set an array of red and green to visually indicate a scale from bad to good.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientLocations +

+ +
+
+ +
+ + +
+

Indicates the position of gradient stops for the colors specified in gradientColors. +Gradient stops are specified as values between 0 and 1. The values must be monotonically +increasing.

+
+ + + +
@property (copy, nullable) NSArray<NSNumber*> *gradientLocations
+ + + + + + + + + +
+

Discussion

+

If nil, the stops are spread uniformly across the range. Defaults to nil.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleQuestionResult.html new file mode 100755 index 0000000..6b0d65f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleQuestionResult.html @@ -0,0 +1,194 @@ + + + + + + ORKScaleQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKScaleQuestionResult class represents the answer to a continuous or +discrete-value scale answer format.

+ +

A scale question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  scaleAnswer +

+ +
+
+ +
+ + +
+

The answer obtained from the scale question.

+
+ + + +
@property (nonatomic, copy, nullable) NSNumber *scaleAnswer
+ + + + + + + + + +
+

Discussion

+

The value of this property is nil when the user skipped the question or otherwise did not +enter an answer.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeDescriptionLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeDescriptionLabel.html new file mode 100755 index 0000000..84c6e73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeDescriptionLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKScaleRangeDescriptionLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleRangeDescriptionLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKScaleRangeLabel : ORKLabel : UILabel
Declared inORKScaleRangeDescriptionLabel.h
ORKScaleRangeDescriptionLabel.m
+ + + + +
+ +

Overview

+

Start/End description of the range in scale slider.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeImageView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeImageView.html new file mode 100755 index 0000000..82169f2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeImageView.html @@ -0,0 +1,121 @@ + + + + + + ORKScaleRangeImageView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleRangeImageView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIImageView
Declared inORKScaleRangeImageView.h
ORKScaleRangeImageView.m
+ + + + +
+ +

Overview

+

Start/End image of the range in scale slider.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeLabel.html new file mode 100755 index 0000000..24c88dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleRangeLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKScaleRangeLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleRangeLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKScaleRangeLabel.h
ORKScaleRangeLabel.m
+ + + + +
+ +

Overview

+

Start/End of the range in scale slider.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleValueLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleValueLabel.html new file mode 100755 index 0000000..8686f3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKScaleValueLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKScaleValueLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScaleValueLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKScaleValueLabel.h
ORKScaleValueLabel.m
+ + + + +
+ +

Overview

+

Large label shown separately from the scale slider to indicate the current value.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionSubTitleLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionSubTitleLabel.html new file mode 100755 index 0000000..1176cfb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionSubTitleLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKSelectionSubTitleLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSelectionSubTitleLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKSelectionSubTitleLabel.h
ORKSelectionSubTitleLabel.m
+ + + + +
+ +

Overview

+

Details text in selection question’s choice cell.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionTitleLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionTitleLabel.html new file mode 100755 index 0000000..224a037 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSelectionTitleLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKSelectionTitleLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSelectionTitleLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKSelectionTitleLabel.h
ORKSelectionTitleLabel.m
+ + + + +
+ +

Overview

+

Title line in selection question’s choice cell.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStep.html new file mode 100755 index 0000000..25632e6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStep.html @@ -0,0 +1,180 @@ + + + + + + ORKShoulderRangeOfMotionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKShoulderRangeOfMotionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRangeOfMotionStep : ORKActiveStep : ORKStep : NSObject
Declared inORKShoulderRangeOfMotionStep.h
ORKShoulderRangeOfMotionStep.m
+ + + + +
+ +

Overview

+

The ORKShoulderRangeOfMotionStep class represents a step that takes a range of motion measurement +for either a left or right shoulder.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStepViewController.html new file mode 100755 index 0000000..1568390 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKShoulderRangeOfMotionStepViewController.html @@ -0,0 +1,204 @@ + + + + + + ORKShoulderRangeOfMotionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKShoulderRangeOfMotionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRangeOfMotionStepViewController : ORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKShoulderRangeOfMotionStepViewController.h
ORKShoulderRangeOfMotionStepViewController.m
+ + + + +
+ +

Overview

+

This class override its parent’s result because here +a flex result of 0 degrees would mean the device is at a 90 degree angle.

+
+ + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureResult.html new file mode 100755 index 0000000..6fbbaaf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureResult.html @@ -0,0 +1,228 @@ + + + + + + ORKSignatureResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSignatureResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKSignatureResult.h
ORKSignatureResult.m
+ + + + +
+ +

Overview

+

The ORKSignatureResult class represents the result of a signature step (ORKSignatureStep).

+ +

A signature result is produced by the task view controller when it presents a signature step.

+
+ + + + + +
+ + + + + + +
+
+ +

  signatureImage +

+ +
+
+ +
+ + +
+

The signature image generated by this step.

+
+ + + +
@property (nonatomic, nullable) UIImage *signatureImage
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSignatureResult.h

+
+ + +
+
+
+ +

  signaturePath +

+ +
+
+ +
+ + +
+

The bezier path components used to create the signature image.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<UIBezierPath*> *signaturePath
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSignatureResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStep.html new file mode 100755 index 0000000..edb145f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStep.html @@ -0,0 +1,232 @@ + + + + + + ORKSignatureStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSignatureStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKSignatureStep.h
ORKSignatureStep.m
+ + + + +
+ +

Overview

+

The ORKSignatureStep class is used to represent collecting a signature. +Typically, the consent signature is collected as a part of the consent review process.

+ +

However, since in some cases the signature is collected after displaying custom +consent review steps, it is exposed to allow showing this as it’s own step.

+ +

To use a consent signature step, configure it and include it in a task. Then +present the task in a task view controller.

+ +

The result of this step is an ORKSignatureResult which will include both the UIImage and +the path used to draw the image.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStepViewController.html new file mode 100755 index 0000000..211173c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureStepViewController.html @@ -0,0 +1,333 @@ + + + + + + ORKSignatureStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSignatureStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKSignatureStepViewController.h
ORKSignatureStepViewController.m
+ + + + +
+ +

Overview

+

The ORKSignatureStepViewController class is a step view controller subclass +used to manage a signature step (ORKSignatureStep).

+ +

You should not need to instantiate a signature step view controller directly. Instead, include +a signature step in a task, and present a task view controller for that stask.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureView.html new file mode 100755 index 0000000..7fee5bf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSignatureView.html @@ -0,0 +1,183 @@ + + + + + + ORKSignatureView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSignatureView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKSignatureView.h
ORKSignatureView.m
+ + + + + + +
+ + + + + + +
+
+ +

  lineWidthVariation +

+ +
+
+ +
+ + +
+

lineWidthVariation defines the max amount by which the line +width can vary (default 3pts).

+
+ + + +
@property (nonatomic) CGFloat lineWidthVariation
+ + + + + + + + + +
+

Discussion

+

The exact amount of the variation is determined by the amount +of force applied on 3D touch capable devices or by the speed +of the stroke if 3D touch is not available.

+ +

If the user is signing with an Apple Pencil, its force will be used.

+
+ + + + + + + +
+

Declared In

+

ORKSignatureView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSkipStepNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSkipStepNavigationRule.html new file mode 100755 index 0000000..3af4b58 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSkipStepNavigationRule.html @@ -0,0 +1,222 @@ + + + + + + ORKSkipStepNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSkipStepNavigationRule Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKSkipStepNavigationRule class is the abstract base class for concrete skip step navigation +rules.

+ +

Skip step navigation rules can be used within an ORKNavigableOrderedTask object. You assign skip +step navigation rules to be triggered before a task step is shown. Each step can have one skip rule +at most.

+ +

Subclasses must implement the identifierForDestinationStepWithTaskResult: method, which returns +the identifier of the destination step for the rule.

+ +

Two concrete subclasses are included: ORKPredicateStepNavigationRule can match any answer +combination in the results of the ongoing task and jump accordingly; ORKDirectStepNavigationRule +unconditionally navigates to the step specified by the destination step identifier.

+
+ + + + + +
+ + + + + + +
+
+ +

– stepShouldSkipWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns whether the targeted step should skip.

+
+ + + +
- (BOOL)stepShouldSkipWithTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating whether the task should + skip.

+
+ + + +
+

Return Value

+

YES if the step should skip.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate if the targeted step should skip based on the +passed task result.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGame.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGame.html new file mode 100755 index 0000000..60983db --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGame.html @@ -0,0 +1,449 @@ + + + + + + ORKSpatialSpanGame Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanGame Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKSpatialSpanGame.h
ORKSpatialSpanGame.m
+ + + + +
+ +

Overview

+

The ORKSpatialSpanGame class represents a model object that represents one game-like experience in a spatial span memory task.

+ +

A game consists of a subset of a permutation of the integers [0 .. gameSize - 1], +which represent the sequence of targets that should be tapped.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithGameSize:sequenceLength:seed: +

+ +
+
+ +
+ + +
+

Returns an initialized spatial span game using the specified game size, sequence length, and seed.

+
+ + + +
- (instancetype)initWithGameSize:(NSInteger)gameSize sequenceLength:(NSInteger)sequenceLength seed:(uint32_t)seed
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
gameSize

The number of tiles in the game.

sequenceLength

The number of elements in the sequence that the user has to remember.

seed

The generator that should be used for generating the sequence. A value of 0 means that a random seed is used.

+
+ + + + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+ +

  gameSize +

+ +
+
+ +
+ + +
+

The number of tiles in the game.

+
+ + + +
@property (nonatomic, readonly) NSInteger gameSize
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+ +

  sequenceLength +

+ +
+
+ +
+ + +
+

The length of the sequence. A sequence is a sub-array of a random permutation of integers (0..gameSize-1) that has a length of sequenceLength.

+
+ + + +
@property (nonatomic, readonly) NSInteger sequenceLength
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+ +

  seed +

+ +
+
+ +
+ + +
+

The seed to use to generate the sequence. Note that if you pass seed to another game, you get the same game.

+
+ + + +
@property (nonatomic, readonly) uint32_t seed
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+ +

– enumerateSequenceWithHandler: +

+ +
+
+ +
+ + +
+

Enumerates the sequence, calling the block once for each element.

+
+ + + +
- (void)enumerateSequenceWithHandler:(void ( ^ ) ( NSInteger step , NSInteger tileIndex , BOOL isLastStep , BOOL *stop ))handler
+ + + +
+

Parameters

+ + + + + + + +
handler

The block to be called for each element in the sequence. The handler block takes the following parameters:

+ +

step The step in the sequence. The step starts at 0 and increments by one on each call. +tileIndex The index in [ 0 .. gameSize ] that corresponds to the step’s element of the sequence. +isLastStep A Boolean value that indicates if this is the last step in the sequence. +stop A Boolean value that indicates if the enumeration should be terminated (pass NO to terminate the enumeration).

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+ +

– tileIndexForStep: +

+ +
+
+ +
+ + +
+

Returns the value of the specified step in the sequence.

+
+ + + +
- (NSInteger)tileIndexForStep:(NSInteger)step
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGame.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGameState.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGameState.html new file mode 100755 index 0000000..cd397f4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanGameState.html @@ -0,0 +1,216 @@ + + + + + + ORKSpatialSpanGameState Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanGameState Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKSpatialSpanGameState.h
ORKSpatialSpanGameState.m
+ + + + + + +
+ + + + + + +
+
+ +

– enumerateTilesWithHandler: +

+ +
+
+ +
+ + +
+

Enumerates all tiles, indicating the state of each tile at the specified state of the game.

+
+ + + +
- (void)enumerateTilesWithHandler:(void ( ^ ) ( NSInteger tileIndex , ORKSpatialSpanTargetState state , BOOL *stop ))handler
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGameState.h

+
+ + +
+
+
+ +

– playTileIndex: +

+ +
+
+ +
+ + +
+

Returns a result indicating whether the user’s tap was correct, incorrect, or ignorable.

+
+ + + +
- (ORKSpatialSpanResult)playTileIndex:(NSInteger)tileIndex
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanGameState.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameRecord.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameRecord.html new file mode 100755 index 0000000..5a9bcce --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameRecord.html @@ -0,0 +1,469 @@ + + + + + + ORKSpatialSpanMemoryGameRecord Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryGameRecord Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKSpatialSpanMemoryResult.h
ORKSpatialSpanMemoryResult.m
+ + + + +
+ +

Overview

+

The ORKSpatialSpanMemoryGameRecord class records the results of a +single playable instance of the spatial span memory game.

+ +

A spatial span memory game record is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+ +

These records are found in the records property of an ORKSpatialSpanMemoryResult object.

+
+ + + + + +
+ + + + + + +
+
+ +

  seed +

+ +
+
+ +
+ + +
+

An integer used as the seed for the sequence.

+
+ + + +
@property (nonatomic, assign) uint32_t seed
+ + + + + + + + + +
+

Discussion

+

If you pass a specific seed value to another game, you get the same sequence.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  sequence +

+ +
+
+ +
+ + +
+

An array of NSNumber objects that represent the sequence that was presented to the user.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<NSNumber*> *sequence
+ + + + + + + + + +
+

Discussion

+

The sequence is an array of length sequenceLength that contains a random permutation of integers (0..gameSize-1)

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  gameSize +

+ +
+
+ +
+ + +
+

The size of the game.

+
+ + + +
@property (nonatomic, assign) NSInteger gameSize
+ + + + + + + + + +
+

Discussion

+

The game size is the number of targets, such as flowers, in the game.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  targetRects +

+ +
+
+ +
+ + +
+

An array of NSValue objects wrapped in CGRect that record the frames of the target +tiles as displayed, relative to the step view.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<NSValue*> *targetRects
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  touchSamples +

+ +
+
+ +
+ + +
+

An array of ORKSpatialSpanMemoryGameTouchSample objects that record the onscreen locations +the user tapped during the game.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKSpatialSpanMemoryGameTouchSample*> *touchSamples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  gameStatus +

+ +
+
+ +
+ + +
+

A value indicating whether the user completed the sequence and, if the game was not completed, why not.

+
+ + + +
@property (nonatomic, assign) ORKSpatialSpanMemoryGameStatus gameStatus
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  score +

+ +
+
+ +
+ + +
+

An integer that records the number of points obtained during this game toward +the total score.

+
+ + + +
@property (nonatomic, assign) NSInteger score
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameTouchSample.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameTouchSample.html new file mode 100755 index 0000000..5696a39 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryGameTouchSample.html @@ -0,0 +1,334 @@ + + + + + + ORKSpatialSpanMemoryGameTouchSample Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryGameTouchSample Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKSpatialSpanMemoryResult.h
ORKSpatialSpanMemoryResult.m
+ + + + +
+ +

Overview

+

The ORKSpatialSpanMemoryGameTouchSample class represents a tap during the +spatial span memory game.

+ +

A spatial span memory game touch sample is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  timestamp +

+ +
+
+ +
+ + +
+

A timestamp (in seconds) from the beginning of the game.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval timestamp
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  targetIndex +

+ +
+
+ +
+ + +
+

The index of the target that was tapped.

+
+ + + +
@property (nonatomic, assign) NSInteger targetIndex
+ + + + + + + + + +
+

Discussion

+

Usually, this index is a value that ranges between 0 and the number of targets, +indicating which target was tapped.

+ +

If the touch was outside all of the targets, the value of this property is -1.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  location +

+ +
+
+ +
+ + +
+

A point that records the touch location in the step’s view.

+
+ + + +
@property (nonatomic, assign) CGPoint location
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  correct +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the tapped target was the correct one.

+
+ + + +
@property (nonatomic, assign, getter=isCorrect) BOOL correct
+ + + + + + + + + +
+

Discussion

+

The value of this property is YES when the tapped target is the correct +one, and NO otherwise.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryResult.html new file mode 100755 index 0000000..730e26d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryResult.html @@ -0,0 +1,342 @@ + + + + + + ORKSpatialSpanMemoryResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKSpatialSpanMemoryResult.h
ORKSpatialSpanMemoryResult.m
+ + + + +
+ +

Overview

+

The ORKSpatialSpanMemoryResult class represents the result of a spatial span memory step (ORKSpatialSpanMemoryStep).

+ +

A spatial span memory result records the score displayed to the user, the number of games, the +objects recording the actual game, and the user’s taps in response +to the game.

+ +

A spatial span memory result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  score +

+ +
+
+ +
+ + +
+

The score in the game.

+
+ + + +
@property (nonatomic, assign) NSInteger score
+ + + + + + + + + +
+

Discussion

+

The score is an integer value that monotonically increases during the game, across multiple rounds.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  numberOfGames +

+ +
+
+ +
+ + +
+

The number of games.

+
+ + + +
@property (nonatomic, assign) NSInteger numberOfGames
+ + + + + + + + + +
+

Discussion

+

The number of rounds that the user participated in, including successful, +failed, and timed out rounds.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  numberOfFailures +

+ +
+
+ +
+ + +
+

The number of failures.

+
+ + + +
@property (nonatomic, assign) NSInteger numberOfFailures
+ + + + + + + + + +
+

Discussion

+

The number of rounds in which the user participated, but did not correctly +complete the sequence.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+ +

  gameRecords +

+ +
+
+ +
+ + +
+

An array that contains the results of the games played.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKSpatialSpanMemoryGameRecord*> *gameRecords
+ + + + + + + + + +
+

Discussion

+

Each item in the array is an ORKSpatialSpanMemoryGameRecord object.

+
+ + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStep.html new file mode 100755 index 0000000..39aa03c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStep.html @@ -0,0 +1,318 @@ + + + + + + ORKSpatialSpanMemoryStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKSpatialSpanMemoryStep.h
ORKSpatialSpanMemoryStep.m
+ + + + +
+ +

Overview

+

Spatian span memory step.

+ +

This step type is used to present the interactive spatial span memory activity. You are not +supposed to use this step on its own. Use ORKOrderedTask’s +spatialSpanMemoryTaskWithIdentifier:intendedUseDescription:initialSpan:minimumSpan:maximumSpan:playSpeed:maximumTests:maximumConsecutiveFailures:customTargetImage:customTargetPluralName:requireReversal:options: method to get a complete spatial +span memory activity task instead.

+
+ + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStepViewController.html new file mode 100755 index 0000000..09a233d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpatialSpanMemoryStepViewController.html @@ -0,0 +1,489 @@ + + + + + + ORKSpatialSpanMemoryStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKSpatialSpanMemoryStepViewController.h
ORKSpatialSpanMemoryStepViewController.m
+ + + + +
+ +

Overview

+

View controller corresponding to ORKSpatialSpanMemoryStep.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– suspend +

+ +
+
+ +
+ + +
+

Suspends the active step.

+
+ + + +
- (void)suspend
+ + + + + + + + + +
+

Discussion

+

Call this method to suspend data recording and the step’s timer.

+ +

This method may called automatically when the app is suspended. +The view controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes the active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method when the step should be resumed. Calls to this method should +be paired with previous calls to suspend.

+ +

This method may be called automatically when the app is resumed. The view +controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

When the step is resumed, the UI should resume at the point where the user left off, +or, if that does not make sense for the particular step, to the most recent +suitable point.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– finish +

+ +
+
+ +
+ + +
+

Finishes the active step.

+
+ + + +
- (void)finish
+ + + + + + + + + +
+

Discussion

+

Call this method to finish the active step. If the active step is configured with +a timer, this method is called automatically when the timer expires.

+ +

Finishing the active step stops all data recording and stops any timers. In steps that have the +shouldContinueOnFinish property set, forward navigation to the next step +may ensue.

+ +

This method does nothing if the step has already finished.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechInNoiseStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechInNoiseStep.html new file mode 100755 index 0000000..df3ac73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechInNoiseStep.html @@ -0,0 +1,593 @@ + + + + + + ORKSpeechInNoiseStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechInNoiseStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKSpeechInNoiseStep.h
ORKSpeechInNoiseStep.m
+ + + + +
+ +

Overview

+

This active step programatically mixes the speech file with noise file and applies the filter.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– shouldContinueOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to transition automatically when the step finishes.

+
+ + + +
- (BOOL)shouldContinueOnFinish
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, the active step view controller automatically performs the +continue action when the [ORKActiveStepViewController finish] method +is called.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  speechFileNameWithExtension +

+ +
+
+ +
+ + +
+

This property accepts the speech file.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *speechFileNameWithExtension
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechInNoiseStep.h

+
+ + +
+
+
+ +

  noiseFileNameWithExtension +

+ +
+
+ +
+ + +
+

This property accepts the noise file.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *noiseFileNameWithExtension
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechInNoiseStep.h

+
+ + +
+
+
+ +

  filterFileNameWithExtension +

+ +
+
+ +
+ + +
+

This property accepts the filter file.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *filterFileNameWithExtension
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechInNoiseStep.h

+
+ + +
+
+
+ +

  gainAppliedToNoise +

+ +
+
+ +
+ + +
+

The linear gain applied to the noise file before mixing it with the speech file.

+
+ + + +
@property (nonatomic, assign) double gainAppliedToNoise
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechInNoiseStep.h

+
+ + +
+
+
+ +

  willAudioLoop +

+ +
+
+ +
+ + +
+

This boolean determines the repetitions of the file.

+
+ + + +
@property (nonatomic, assign) BOOL willAudioLoop
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechInNoiseStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStep.html new file mode 100755 index 0000000..fa6ba4a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStep.html @@ -0,0 +1,420 @@ + + + + + + ORKSpeechRecognitionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognitionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKSpeechRecognitionStep.h
ORKSpeechRecognitionStep.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– shouldContinueOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to transition automatically when the step finishes.

+
+ + + +
- (BOOL)shouldContinueOnFinish
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, the active step view controller automatically performs the +continue action when the [ORKActiveStepViewController finish] method +is called.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  speechRecognizerLocale +

+ +
+
+ +
+ + +
+

The language for speech recognition

+
+ + + +
@property (nonatomic, copy) ORKSpeechRecognizerLocale speechRecognizerLocale
+ + + + + + + + + +
+

Discussion

+

The default value of this property is @“en-US”.

+
+ + + + + + + +
+

Declared In

+

ORKSpeechRecognitionStep.h

+
+ + +
+
+
+ +

  shouldHideTranscript +

+ +
+
+ +
+ + +
+

The property to hide transcription as the user speaks.

+
+ + + +
@property (nonatomic) BOOL shouldHideTranscript
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognitionStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStepViewController.html new file mode 100755 index 0000000..792d1a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitionStepViewController.html @@ -0,0 +1,525 @@ + + + + + + ORKSpeechRecognitionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognitionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKSpeechRecognitionStepViewController.h
ORKSpeechRecognitionStepViewController.m
+ + + + +
+ +

Overview

+

Step view controller corresponding to ORKSpeechRecognitionStep.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– recordersDidChange +

+ +
+
+ +
+ + +
+

Tells the view controller that the set of recorders changed.

+
+ + + +
- (void)recordersDidChange
+ + + + + + + + + +
+

Discussion

+

This method is usually called by the active step view controller in response +to start or resume.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes the active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method when the step should be resumed. Calls to this method should +be paired with previous calls to suspend.

+ +

This method may be called automatically when the app is resumed. The view +controller can be configured not to suspend even if the app +goes into the background (for more information, see suspendIfInactive).

+ +

When the step is resumed, the UI should resume at the point where the user left off, +or, if that does not make sense for the particular step, to the most recent +suitable point.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– goForward +

+ +
+
+ +
+ + +
+

Navigates forward to the next step.

+
+ + + +
- (void)goForward
+ + + + + + + + + +
+

Discussion

+

When a user taps a Next button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– recordersWillStart +

+ +
+
+ +
+ + +
+

Tells the view controller that the recorders are about to start.

+
+ + + +
- (void)recordersWillStart
+ + + + + + + + + +
+

Discussion

+

This method is called by the active step view controller after instantiating +the recorders, but before starting them.

+ +

Subclasses may override this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitonResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitonResult.html new file mode 100755 index 0000000..16b0cb4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognitonResult.html @@ -0,0 +1,186 @@ + + + + + + ORKSpeechRecognitonResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognitonResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKSpeechRecognitionResult.h
ORKSpeechRecognitionResult.m
+ + + + +
+ +

Overview

+

The ORKSpeechRecognitionResult class represents the result of a single successful attempt of an ORKSpeechRecognitionStep.

+ +

A speech recognition result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  transcription +

+ +
+
+ +
+ + +
+

A hypothesized textual representation of recognized speech +SFTranscription is described at: https://developer.apple.com/documentation/speech/sftranscription

+
+ + + +
@property (nonatomic, copy, nullable) SFTranscription *transcription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognitionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognizer.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognizer.html new file mode 100755 index 0000000..4e55ec0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSpeechRecognizer.html @@ -0,0 +1,356 @@ + + + + + + ORKSpeechRecognizer Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognizer Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKSpeechRecognizer.h
ORKSpeechRecognizer.m
+ + + + +
+ +

Overview

+

The ORKSpeechRecognizer class is a wrapper for the Speech API framework

+
+ + + + + +
+ + + + + + +
+
+ +

+ requestAuthorization +

+ +
+
+ +
+ + +
+

Asks the user to grant your app permission to perform speech recognition.

+
+ + + +
+ (void)requestAuthorization
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+ +

– startRecognitionWithLocale:reportPartialResults:responseDelegate:errorHandler: +

+ +
+
+ +
+ + +
+

Starts speech recognition for the specified locale

+
+ + + +
- (void)startRecognitionWithLocale:(NSLocale *)locale reportPartialResults:(BOOL)reportPartialResults responseDelegate:(id<ORKSpeechRecognitionDelegate>)delegate errorHandler:(void ( ^ ) ( NSError *error ))handler
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
locale

Device’s locale

reportPartialResults

A boolean value that indicates whether partial, nonfinal results for each utterance are reported.

delegate

The delegate for speech recognition response

handler

A handler to report errors

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+ +

– addAudio: +

+ +
+
+ +
+ + +
+

Appends audio to the end of the recognition request.

+
+ + + +
- (void)addAudio:(AVAudioPCMBuffer *)audioBuffer
+ + + +
+

Parameters

+ + + + + + + +
audioBuffer

A buffer of audio

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+ +

– endAudio +

+ +
+
+ +
+ + +
+

Indicates that the audio source is finished and no more audio will be appended to the +recognition request.

+
+ + + +
- (void)endAudio
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStep.html new file mode 100755 index 0000000..ba73e38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStep.html @@ -0,0 +1,941 @@ + + + + + + ORKStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStep Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKStep.h
ORKStep.m
+ + + + +
+ +

Overview

+

ORKStep is the base class for the steps that can compose a task for presentation +in an ORKTaskViewController object. Each ORKStep object represents one logical piece of data +entry or activity in a larger task.

+ +

A step can be a question, an active test, or a simple instruction. An ORKStep +subclass is usually paired with an ORKStepViewController subclass that displays the step.

+ +

To use a step, instantiate an ORKStep object and populate its properties. Add the step to a task, +such as an ORKOrderedTask object, and then present the task using a task view controller (an +ORKTaskViewController object).

+ +

To implement a new type of step, subclass ORKStep and add your additional +properties. Separately, subclass ORKStepViewController and implement +your user interface. Note that if your step is timed or requires sensor data collection, +you should consider subclassing ORKActiveStep and ORKActiveStepViewController +instead.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– copyWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns a copy of this step initialized with the specified identifier.

+
+ + + +
- (instancetype)copyWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier for the new step to be returned.

+
+ + + +
+

Return Value

+

A new step.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  identifier +

+ +
+
+ +
+ + +
+

A short string that uniquely identifies the step within the task.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier is reproduced in the results of a step. In fact, the only way to link a result +(an ORKStepResult object) to the step that generated it is to look at the value of +identifier. To accurately identify step results, you need to ensure that step identifiers +are unique within each task.

+ +

In some cases, it can be useful to link the step identifier to a unique identifier in a +database; in other cases, it can make sense to make the identifier human +readable.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  restorable +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether a task can be restored to the step +during state restoration. (read-only)

+
+ + + +
@property (nonatomic, readonly, getter=isRestorable) BOOL restorable
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is YES, but subclasses of ORKStep might use NO.

+ +

If a task cannot be restored to the step, the task is typically restored to the +last restorable step in the task, or to the first step, if +no restorable steps are available.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  optional +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the user can skip the step +without providing an answer.

+
+ + + +
@property (nonatomic, getter=isOptional) BOOL optional
+ + + + + + + + + +
+

Discussion

+

The default value of this property is YES. When the value is NO, the Skip button does not +appear on this step.

+ +

This property may not be meaningful for all steps; for example, an active step +might not provide a way to skip, because it requires a timer to finish.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  title +

+ +
+
+ +
+ + +
+

The primary text to display for the step in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *title
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

Additional text to display for the step in a localized string.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *text
+ + + + + + + + + +
+

Discussion

+

The additional text is displayed in a smaller font below title. If you need to display a +long question, it can work well to keep the title short and put the additional content in +the text property.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  task +

+ +
+
+ +
+ + +
+

The task that contains the step.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKTask> task
+ + + + + + + + + +
+

Discussion

+

The value of task is usually set when a step is added to the ORKOrderedTask object. +Although it’s a good idea to set this property when you implement a custom task, it’s important +to note that the use of this property is a convenience, and should not be relied +upon within the ResearchKit framework.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  requestedPermissions +

+ +
+
+ +
+ + +
+

The set of access permissions required for the step. (read-only)

+
+ + + +
@property (nonatomic, readonly) ORKPermissionMask requestedPermissions
+ + + + + + + + + +
+

Discussion

+

The permission mask is used by the task view controller to determine the types of +access to request from users when they complete the initial instruction steps +in a task. If your step requires access to APIs that limit access, include +the permissions you require in this mask.

+ +

By default, the property scans the recorders and collates the permissions +required by the recorders. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

  requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types the step requests for reading. (read-only)

+
+ + + +
@property (nonatomic, readonly, nullable) NSSet<HKObjectType*> *requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this set of types when constructing a list of +all the HealthKit types required by all the steps in a task, so that it can +present the HealthKit access dialog just once during that task.

+ +

By default, the property scans the recorders and collates the HealthKit +types the recorders require. Subclasses may override this implementation.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– stepViewControllerClass +

+ +
+
+ +
+ + + + +
- (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– instantiateStepViewControllerWithResult: +

+ +
+
+ +
+ + +
+

Instantiates a step view controller for this class.

+
+ + + +
- (ORKStepViewController *)instantiateStepViewControllerWithResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + +
result

The result associated with this step

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + +
+

Discussion

+

This method is called when a step is about to be presented. The default implementation returns +a view controller that is appropriate to this step by allocating an instance of ORKStepViewController +using the stepViewControllerClass method and initializing that instance by calling initWithIdentifier:result: +on the provided ORKStepViewController class instance.

+ +

Override this method if you need to customize the behavior before presenting the step or if +the view controller is presented using a nib or storyboard.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + +
+

Returns the class that the task view controller should instantiate to display +this step.

+
+ + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + +
+

Discussion

+

This method is used within the framework so that steps can define their +step view controller pairing.

+ +

Outside the framework, developers should instantiate the required view +controller in their task view controller delegate to override the task +view controller’s default.

+
+ + + + + + + +
+

Declared In

+

ORKStep_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepModifier.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepModifier.html new file mode 100755 index 0000000..9dfb1b9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepModifier.html @@ -0,0 +1,207 @@ + + + + + + ORKStepModifier Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepModifier Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKStepModifier class is an abstract base class for an object that can be used to modify a step +if a given navigation rule is matched.

+ +

Step modifiers can be used within an ORKNavigableOrderedTask object. You assign step modifiers +to be triggered after a task step is shown. Each step can have one step modifier at most.

+
+ + + + + +
+ + + + + + +
+
+ +

– modifyStep:withTaskResult: +

+ +
+
+ +
+ + +
+

Modify the steps for a task.

+
+ + + +
- (void)modifyStep:(ORKStep *)step withTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step that is associated with this modifier

taskResult

The current task result

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepNavigationRule.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepNavigationRule.html new file mode 100755 index 0000000..81bff57 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepNavigationRule.html @@ -0,0 +1,220 @@ + + + + + + ORKStepNavigationRule Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepNavigationRule Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKStepNavigationRule.h
ORKStepNavigationRule.m
+ + + + +
+ +

Overview

+

The ORKStepNavigationRule class is the abstract base class for concrete step navigation rules.

+ +

Step navigation rules can be used within an ORKNavigableOrderedTask object. You assign step +navigation rules to be triggered by the task steps. Each step can have one rule at most.

+ +

Subclasses must implement the identifierForDestinationStepWithTaskResult: method, which returns +the identifier of the destination step for the rule.

+ +

Two concrete subclasses are included: ORKPredicateStepNavigationRule can match any answer +combination in the results of the ongoing task and jump accordingly; ORKDirectStepNavigationRule +unconditionally navigates to the step specified by the destination step identifier.

+
+ + + + + +
+ + + + + + +
+
+ +

– identifierForDestinationStepWithTaskResult: +

+ +
+
+ +
+ + +
+

Returns the target step identifier.

+
+ + + +
- (NSString *)identifierForDestinationStepWithTaskResult:(ORKTaskResult *)taskResult
+ + + +
+

Parameters

+ + + + + + + +
taskResult

The up-to-date task result, used for calculating the destination step.

+
+ + + +
+

Return Value

+

The identifier of the destination step.

+
+ + + + + +
+

Discussion

+

Subclasses must implement this method to calculate the next step based on the passed task result. +The ORKNullStepIdentifier constant can be returned to indicate that the ongoing task should end +after the step navigation rule is triggered.

+
+ + + + + + + +
+

Declared In

+

ORKStepNavigationRule.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepResult.html new file mode 100755 index 0000000..2e130be --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepResult.html @@ -0,0 +1,281 @@ + + + + + + ORKStepResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKCollectionResult : ORKResult : NSObject
Declared inORKCollectionResult.h
ORKCollectionResult.m
+ + + + +
+ +

Overview

+

The ORKStepResult class represents a collection result produced by a step view controller to +hold all child results produced by the step.

+ +

A step result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+ +

For example, an ORKQuestionStep object produces an ORKQuestionResult object that becomes +a child of the ORKStepResult object. Similarly, an ORKActiveStep object may produce individual +child result objects for each of the recorder configurations that was active +during that step.

+ +

The results property of the ORKCollectionResult object contains the step results +for the task.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStepIdentifier:results: +

+ +
+
+ +
+ + +
+

Returns an initialized step result using the specified identifier.

+
+ + + +
- (instancetype)initWithStepIdentifier:(NSString *)stepIdentifier results:(nullable NSArray<ORKResult*> *)results
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepIdentifier

The identifier of the step.

results

The array of child results. The value of this parameter can be nil or empty +if no results were collected.

+
+ + + +
+

Return Value

+

An initialized step result.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

  enabledAssistiveTechnology +

+ +
+
+ +
+ + +
+

This property indicates whether the Voice Over or Switch Control assistive technologies were active +while performing the corresponding step.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSString *enabledAssistiveTechnology
+ + + + + + + + + +
+

Discussion

+

This information can be used, for example, to take into consideration the extra time needed by +handicapped participants to complete some tasks, such as the Tower of Hanoi activity.

+ +

The property can have the following values: +- UIAccessibilityNotificationVoiceOverIdentifier if Voice Over was active +- UIAccessibilityNotificationSwitchControlIdentifier if Switch Control was active

+ +

Note that the Voice Over and Switch Control assistive technologies are mutually exclusive.

+ +

If the property is nil, none of these assistive technologies was used.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepViewController.html new file mode 100755 index 0000000..b3c6a99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStepViewController.html @@ -0,0 +1,1132 @@ + + + + + + ORKStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromUIViewController
Declared inORKStepViewController.h
ORKStepViewController.m
+ + + + +
+ +

Overview

+

The ORKStepViewController class is a base class for view controllers that are +presented by an ORKTaskViewController object for the steps in a task.

+ +

In the ResearchKit framework, each step collects some information or data from the user. +Typically, the task view controller instantiates the step view controller +before presenting the next step (ORKStep) in the task.

+ +

When you create a new type of step, you usually have to subclass +ORKStepViewController to manage the step. For examples of subclasses, see +ORKQuestionStepViewController and ORKFormStepViewController. In contrast, the view +controller for an active step is typically a subclass of ORKActiveStepViewController, +because active steps include the concept of life cycle.

+ +

If you are simply trying to change some of the runtime behaviors of ORKStepViewController, +it’s usually not necessary to subclass it. Instead, implement the +[ORKTaskViewControllerDelegate taskViewController:stepViewControllerWillAppear:] method in +the ORKTaskViewControllerDelegate protocol, and modify the appropriate properties +of the step view controller. For example, to change the title of the Learn More +or Next buttons, set the learnMoreButtonTitle or continueButtonTitle +properties in your implementation of this delegate method.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(nullable ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  step +

+ +
+
+ +
+ + +
+

The step presented by the step view controller.

+
+ + + +
@property (nonatomic, strong, nullable) ORKStep *step
+ + + + + + + + + +
+

Discussion

+

If you use a storyboard to initialize the step view controller, initWithStep: isn’t called, +so you need to set the step property directly before the step view controller is presented.

+ +

Setting the value of step after the controller has been presented is an error that +generates an exception. +Modifying the value of step after the controller has been presented is an error that +has undefined results.

+ +

Subclasses that override the setter of this property must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate of the step view controller.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKStepViewControllerDelegate> delegate
+ + + + + + + + + +
+

Discussion

+

The delegate is usually the ORKTaskViewController object that presents the step view +controller. If you need to intercept the delegate methods, you can +assign an intermediary object as the delegate and forward the messages +to the task view controller.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  continueButtonTitle +

+ +
+
+ +
+ + +
+

A localized string that represents the title of the Continue button.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *continueButtonTitle
+ + + + + + + + + +
+

Discussion

+

Most steps display a button that enables forward navigation. This button can have titles +such as Next, Continue, or Done. Use this property to override the forward navigation +button title for the step.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  learnMoreButtonTitle +

+ +
+
+ +
+ + +
+

A localized string that represents the title of the Learn More button.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *learnMoreButtonTitle
+ + + + + + + + + +
+

Discussion

+

Many steps have a button that lets users view more information about the +step than can fit on the screen. Use this property to override the title +of the Learn More button for the step.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  skipButtonTitle +

+ +
+
+ +
+ + +
+

A localized string that represents the title of the “Skip” button.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *skipButtonTitle
+ + + + + + + + + +
+

Discussion

+

Many steps are optional and can be skipped. Set this property to override +the title of the Skip button for the step. Note that setting this property +has no effect if the Skip button is not visible, which is the case in a required question step.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  backButtonItem +

+ +
+
+ +
+ + +
+

The back button item.

+
+ + + +
@property (nonatomic, strong, nullable) UIBarButtonItem *backButtonItem
+ + + + + + + + + +
+

Discussion

+

The back button item controls the Back button displayed in the navigation bar when +the step view controller is current. +This property lets you control the appearance and target of the +Back button at runtime.

+ +

When the value of the property is nil, the Back button is not displayed; otherwise, the title, target, +and action associated with the Back button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The back button item is updated during view loading and when the value of the step property +is changed, but they are safe to set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  cancelButtonItem +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
@property (nonatomic, strong, nullable) UIBarButtonItem *cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly, nullable) ORKStepResult *result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– addResult: +

+ +
+
+ +
+ + +
+

Add a result to the step view controller’s ORKStepResult. By default, the property for +the step view controller’s result will instantiate a copy of the result each time it is +called. Therefore, the result cannot be mutated by adding a result to its result array.

+
+ + + +
- (void)addResult:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + +
result

The result to add to the step results.

+
+ + + + + + + +
+

Discussion

+

This method can be called by a delegate to add a result to a given step in a way that will +be retained by the step.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– hasPreviousStep +

+ +
+
+ +
+ + +
+

Returns a Boolean value indicating whether there is a previous step.

+
+ + + +
- (BOOL)hasPreviousStep
+ + + + + +
+

Return Value

+

YES if there is a previous step; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method is a convenience accessor that subclasses can call to make a delegate callback to +determine whether a previous step exists. Subclasses can also override this method if the step +view controller should always behave as if backward navigation is disabled.

+ +

See also: stepViewControllerHasPreviousStep:

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– hasNextStep +

+ +
+
+ +
+ + +
+

Returns a Boolean value indicating whether there is a next step.

+
+ + + +
- (BOOL)hasNextStep
+ + + + + +
+

Return Value

+

YES if there is a next step; otherwise, NO.

+
+ + + + + +
+

Discussion

+

This method is a convenience method that subclasses can call to make a delegate callback to +determine whether a next step exists.

+ +

See also: stepViewControllerHasNextStep:

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  taskViewController +

+ +
+
+ +
+ + +
+

The presenting task view controller. (read-only)

+
+ + + +
@property (nonatomic, weak, readonly, nullable) ORKTaskViewController *taskViewController
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– goForward +

+ +
+
+ +
+ + +
+

Navigates forward to the next step.

+
+ + + +
- (void)goForward
+ + + + + + + + + +
+

Discussion

+

When a user taps a Next button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– goBackward +

+ +
+
+ +
+ + +
+

Navigates backward to the previous step.

+
+ + + +
- (void)goBackward
+ + + + + + + + + +
+

Discussion

+

When a user taps the Back button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– skipForward +

+ +
+
+ +
+ + +
+

This method is called when the user taps the skip button. By default, it calls goForward.

+
+ + + +
- (void)skipForward
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

  hasBeenPresented +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the view controller has been presented before.

+
+ + + +
@property (nonatomic, readonly) BOOL hasBeenPresented
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorder.html new file mode 100755 index 0000000..d0f9a91 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorder.html @@ -0,0 +1,474 @@ + + + + + + ORKStreamingAudioRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStreamingAudioRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKStreamingAudioRecorder.h
ORKStreamingAudioRecorder.m
+ + + + +
+ +

Overview

+

The ORKStreamingAudioRecorder class represents a recorder that uses the app’s +AVAudioSession object to record audio.

+ +

To audio recording will be discontinued if task enters the background.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:step:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an initialized audio recorder using the specified step, and output directory.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier step:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The unique identifier of the recorder (assigned by the recorder configuration).

step

The step that requested this recorder.

outputDirectory

The directory in which the audio output should be stored.

+
+ + + +
+

Return Value

+

An initialized audio recorder.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStreamingAudioRecorder.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– isRecording +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the recorder is currently recording.

+
+ + + +
- (BOOL)isRecording
+ + + + + +
+

Return Value

+

YES if the recorder is recording; otherwise, NO.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  audioEngine +

+ +
+
+ +
+ + +
+

Reference to the audio recorder being used.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) AVAudioEngine *audioEngine
+ + + + + + + + + +
+

Discussion

+

The value of this property is used in the audio task in order to display recorded volume and metering in real time during the task.

+
+ + + + + + + +
+

Declared In

+

ORKStreamingAudioRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorderConfiguration.html new file mode 100755 index 0000000..4a41e41 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStreamingAudioRecorderConfiguration.html @@ -0,0 +1,385 @@ + + + + + + ORKStreamingAudioRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStreamingAudioRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKRecorder.h
ORKStreamingAudioRecorder.m
+ + + + +
+ +

Overview

+

The ORKStreamingAudioRecorderConfiguration class represents a configuration that records streaming +audio data during an active step.

+ +

An ORKStreamingAudioRecorderConfiguration generates an ORKStreamingAudioRecorder object.

+ +

To use a recorder, include its configuration in the recorderConfigurations property +of an ORKActiveStep object, include that step in a task, and present it with +a task view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized audio recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized audio recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new audio recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the audio recorder configuration.

+
+ + + +
+

Return Value

+

A new audio recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– requestedPermissionMask +

+ +
+
+ +
+ + +
+

Returns the permission mask indicating the permissions required for this configuration.

+
+ + + +
- (ORKPermissionMask)requestedPermissionMask
+ + + + + + + + + +
+

Discussion

+

This method is typically overridden in new recorder configuration subclasses.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopResult.html new file mode 100755 index 0000000..560b5e9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopResult.html @@ -0,0 +1,357 @@ + + + + + + ORKStroopResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStroopResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKStroopResult.h
ORKStroopResult.m
+ + + + +
+ +

Overview

+

The ORKStroopResult class represents the result of a single successful attempt within an ORKStroopStep.

+ +

A stroop result is typically generated by the framework as the task proceeds. When the task completes, it may be appropriate to serialize the sample for transmission to a server or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  startTime +

+ +
+
+ +
+ + +
+

The startTime property is equal to the start time of the each step.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval startTime
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStroopResult.h

+
+ + +
+
+
+ +

  endTime +

+ +
+
+ +
+ + +
+

The endTime property is equal to the timestamp when user answers a particular step by selecting a color.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval endTime
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStroopResult.h

+
+ + +
+
+
+ +

  color +

+ +
+
+ +
+ + +
+

The color property is the color of the question string.

+
+ + + +
@property (nonatomic, copy) NSString *color
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStroopResult.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

The text property is the text of the question string.

+
+ + + +
@property (nonatomic, copy) NSString *text
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStroopResult.h

+
+ + +
+
+
+ +

  colorSelected +

+ +
+
+ +
+ + +
+

The colorSelected corresponds to the button tapped by the user as an answer.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *colorSelected
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStroopResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStep.html new file mode 100755 index 0000000..6350af7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStep.html @@ -0,0 +1,304 @@ + + + + + + ORKStroopStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStroopStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKStroopStep.h
ORKStroopStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStepViewController.html new file mode 100755 index 0000000..08bb48e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKStroopStepViewController.html @@ -0,0 +1,361 @@ + + + + + + ORKStroopStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStroopStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKStroopStepViewController.h
ORKStroopStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSubheadlineLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSubheadlineLabel.html new file mode 100755 index 0000000..c52a9fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKSubheadlineLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKSubheadlineLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSubheadlineLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKSubheadlineLabel.h
ORKSubheadlineLabel.m
+ + + + +
+ +

Overview

+

Step’s details text under title.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStep.html new file mode 100755 index 0000000..c7dc134 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStep.html @@ -0,0 +1,698 @@ + + + + + + ORKTableStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTableStep Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKStep : NSObject
Conforms toORKTableStepSource
Declared inORKTableStep.h
ORKTableStep.m
+ + + + +
+ +

Overview

+

The ORKTableStep class is a concrete subclass of ORKStep, used for presenting a list of model +objects in a UITableView.

+ +

To use ORKTableStep, instantiate the object, fill in its properties, and include it +in a task. Next, create a task view controller for the task and present it.

+ +

The base class implementation will instatiate a read-only ORKTableStepViewController to display +the list of items using UITableViewCell with the text set to the -description for each item in +the items array.

+ +

Customization can be handled by overriding the base class implementations in either ORKTableStep +or ORKTableStepViewController.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  items +

+ +
+
+ +
+ + +
+

The array of items in table. These items must conform to NSCopying and NSSecureCoding protocols.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<id<NSObject,NSCopying,NSSecureCoding> > *items
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

  isBulleted +

+ +
+
+ +
+ + +
+

Boolean flag representing if the table data should be displayed in a bulleted format.

+
+ + + +
@property (nonatomic) BOOL isBulleted
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

  bulletIconNames +

+ +
+
+ +
+ + +
+

The array of icon names to display instead of bullets.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<NSString*> *bulletIconNames
+ + + + + + + + + +
+

Discussion

+

Images are only visible if the isBulleted property is set to YES. Images names must reference +images in you application project not the ResearchKit framework.

+
+ + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– numberOfSections +

+ +
+
+ +
+ + +
+

Returns the number of sections in the tableview used to display this step. Default = 1.

+
+ + + +
- (NSInteger)numberOfSections
+ + + + + +
+

Return Value

+

The number of sections in the tableview.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– numberOfRowsInSection: +

+ +
+
+ +
+ + +
+

Returns the number of rows in the section. Default = items.count

+
+ + + +
- (NSInteger)numberOfRowsInSection:(NSInteger)section
+ + + +
+

Parameters

+ + + + + + + +
section

The section of the table

+
+ + + +
+

Return Value

+

The number of rows in the tableview section

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– objectForRowAtIndexPath: +

+ +
+
+ +
+ + +
+

Returns the model object for this section/row. Default = items[indexPath.row]

+
+ + + +
- (id<NSObject,NSCopying,NSSecureCoding>)objectForRowAtIndexPath:(NSIndexPath *)indexPath
+ + + +
+

Parameters

+ + + + + + + +
indexPath

The indexpath of the section/row for the cell

+
+ + + +
+

Return Value

+

The model object for this section/row

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– reuseIdentifierForRowAtIndexPath: +

+ +
+
+ +
+ + +
+

Returns the reuseIdentifier for the object at this index path. Default = ORKBasicCellReuseIdentifier

+
+ + + +
- (NSString *)reuseIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath
+ + + +
+

Parameters

+ + + + + + + +
indexPath

The indexpath of the section/row for the cell

+
+ + + +
+

Return Value

+

The model object for this section/row

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– registerCellsForTableView: +

+ +
+
+ +
+ + +
+

Optional override for registering UITableViewCell instances. The default registers for ORKBasicCellReuseIdentifier.

+
+ + + +
- (void)registerCellsForTableView:(UITableView *)tableView
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– configureCell:indexPath:tableView: +

+ +
+
+ +
+ + +
+

Optional override for configuring a cell. The default will set the text label using the object description for +the object at a given index path.

+
+ + + +
- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStepViewController.html new file mode 100755 index 0000000..c6962ef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableStepViewController.html @@ -0,0 +1,480 @@ + + + + + + ORKTableStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTableStepViewController Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKStepViewController : UIViewController
Conforms toUITableViewDataSource
UITableViewDelegate
Declared inORKTableStepViewController.h
ORKTableStepViewController.m
+ + + + +
+ +

Overview

+

The ORKTableStepViewController class is an base class that inherits from ORKStepViewController +and provides a UITableView.

+ +

ORKTableStepViewController is designed to take advantage of the internal class methods +used by ORKFormStepViewController, ORKQuestionStepViewController and ORKReviewStepViewController +to allow for a consistent UI in a custom implementation of a main view that is a UITableView.

+ +

This will class will setup a consistent look for the title, text, learn more, skip and next UI elements +that are used by these classes as well as most of the other view controllers within this framework by +automatically adding them as the header and footer of the tableview.

+ +

The base class implementation REQUIRES using an ORKTableStep as its data source. If you do not inherit +the step from ORKTableStep, then subclasses MUST override -cellForRowAtIndexPath.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  tableStep +

+ +
+
+ +
+ + +
+

The step associated with this view controller if it conforms to ORKTableStepSource.

+
+ + + +
@property (nonatomic, readonly, nullable) id<ORKTableStepSource> tableStep
+ + + + + +
+

Return Value

+

The step associated with this view controller if it conforms to ORKTableStepSource.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStepViewController.h

+
+ + +
+
+
+ +

  tableView +

+ +
+
+ +
+ + +
+

The table view managed by the controller object.

+
+ + + +
@property (nonatomic, readonly) UITableView *tableView
+ + + + + +
+

Return Value

+

The table view managed by the controller object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStepViewController.h

+
+ + +
+
+
+ +

– continueButtonEnabled +

+ +
+
+ +
+ + +
+

Whether or not the continue button should be enabled for this step. Default = YES

+
+ + + +
- (BOOL)continueButtonEnabled
+ + + + + +
+

Return Value

+

State of continue button

+
+ + + + + +
+

Discussion

+

Set to NO if there is a validation that needs to be handled before the step +can progress. Your implementation is responsible for overriding selection as needed +to trigger validation and state changes.

+
+ + + + + + + +
+

Declared In

+

ORKTableStepViewController.h

+
+ + +
+
+
+ +

– updateButtonStates +

+ +
+
+ +
+ + +
+

Update the button state for the skip and continue buttons

+
+ + + +
- (void)updateButtonStates
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTableStepViewController.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ + + +

Extension Methods

+ +
+
+ +

  tableViewStyle +

+ +
+
+ +
+ + +
+

The style to use for the tableView. default = UITableViewStyleGrouped if more than one section +and UITableViewStylePlain if there is only 1 section.

+
+ + + +
@property (nonatomic, readonly) UITableViewStyle tableViewStyle
+ + + + + +
+

Return Value

+

The style to use for the tableView. default = UITableViewStyleGrouped if more than one section +and UITableViewStylePlain if there is only 1 section.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStepViewController_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableViewCell.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableViewCell.html new file mode 100755 index 0000000..0dfce63 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTableViewCell.html @@ -0,0 +1,121 @@ + + + + + + ORKTableViewCell Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTableViewCell Class Reference

+ + +
+ + + + + + + +
Inherits fromUITableViewCell
Declared inORKTableViewCell.h
ORKTableViewCell.m
+ + + + +
+ +

Overview

+

Base class, not being used directly.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTapCountLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTapCountLabel.html new file mode 100755 index 0000000..453c7c4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTapCountLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKTapCountLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTapCountLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKTapCountLabel.h
ORKTapCountLabel.m
+ + + + +
+ +

Overview

+

Display tapping count in tapping interval active task

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalResult.html new file mode 100755 index 0000000..45a92e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalResult.html @@ -0,0 +1,321 @@ + + + + + + ORKTappingIntervalResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTappingIntervalResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKTappingIntervalResult.h
ORKTappingIntervalResult.m
+ + + + +
+ +

Overview

+

The ORKTappingIntervalResult class records the results of a tapping interval test.

+ +

The tapping interval result object records an array of touch samples (one for each tap) and also the geometry of the +task at the time it was displayed. You can use the information in the object for reference in interpreting the touch +samples.

+ +

A tapping interval sample is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  samples +

+ +
+
+ +
+ + +
+

An array of collected samples, in which each item is an ORKTappingSample object that represents a +tapping event.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKTappingSample*> *samples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  stepViewSize +

+ +
+
+ +
+ + +
+

The size of the bounds of the step view containing the tap targets.

+
+ + + +
@property (nonatomic) CGSize stepViewSize
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  buttonRect1 +

+ +
+
+ +
+ + +
+

The frame of the left button, in points, relative to the step view bounds.

+
+ + + +
@property (nonatomic) CGRect buttonRect1
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  buttonRect2 +

+ +
+
+ +
+ + +
+

The frame of the right button, in points, relative to the step view bounds.

+
+ + + +
@property (nonatomic) CGRect buttonRect2
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStep.html new file mode 100755 index 0000000..84505d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStep.html @@ -0,0 +1,265 @@ + + + + + + ORKTappingIntervalStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTappingIntervalStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKTappingIntervalStep.h
ORKTappingIntervalStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStepViewController.html new file mode 100755 index 0000000..64292af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingIntervalStepViewController.html @@ -0,0 +1,361 @@ + + + + + + ORKTappingIntervalStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTappingIntervalStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKTappingIntervalStepViewController.h
ORKTappingIntervalStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingSample.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingSample.html new file mode 100755 index 0000000..588fc45 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTappingSample.html @@ -0,0 +1,348 @@ + + + + + + ORKTappingSample Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTappingSample Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKTappingIntervalResult.h
ORKTappingIntervalResult.m
+ + + + +
+ +

Overview

+

The ORKTappingSample class represents a single tap on a button.

+ +

The tapping sample object records the location of the tap, the +button that was tapped, and the time at which the event occurred. A tapping sample is +included in an ORKTappingIntervalResult object, and is recorded by the +step view controller for the corresponding task when a tap is +recognized.

+ +

A tapping sample is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize the sample for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  timestamp +

+ +
+
+ +
+ + +
+

A relative timestamp indicating the time of the tap event.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval timestamp
+ + + + + + + + + +
+

Discussion

+

The timestamp is relative to the value of startDate in the ORKResult object that includes this +sample.

+
+ + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  duration +

+ +
+
+ +
+ + +
+

A duration of the tap event.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval duration
+ + + + + + + + + +
+

Discussion

+

The duration store time interval between touch down and touch release events.

+
+ + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  buttonIdentifier +

+ +
+
+ +
+ + +
+

An enumerated value that indicates which button was tapped, if any.

+
+ + + +
@property (nonatomic, assign) ORKTappingButtonIdentifier buttonIdentifier
+ + + + + + + + + +
+

Discussion

+

If the value of this property is ORKTappingButtonIdentifierNone, it indicates that the tap +was near, but not inside, one of the target buttons.

+
+ + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+ +

  location +

+ +
+
+ +
+ + +
+

The location of the tap within the step’s view.

+
+ + + +
@property (nonatomic, assign) CGPoint location
+ + + + + + + + + +
+

Discussion

+

The location coordinates are relative to a rectangle whose size corresponds to +the stepViewSize in the enclosing ORKTappingIntervalResult object.

+
+ + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskResult.html new file mode 100755 index 0000000..5623e0f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskResult.html @@ -0,0 +1,404 @@ + + + + + + ORKTaskResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTaskResult Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKCollectionResult : ORKResult : NSObject
Conforms toORKTaskResultSource
Declared inORKCollectionResult.h
ORKCollectionResult.m
+ + + + +
+ +

Overview

+

An ORKTaskResult object is a collection result that contains all the step results +generated from one run of a task or ordered task (that is, ORKTask or ORKOrderedTask) in a task view controller.

+ +

A task result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+ +

The results property of the ORKCollectionResult object contains the step results +for the task.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithTaskIdentifier:taskRunUUID:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns an intialized task result using the specified identifiers and directory.

+
+ + + +
- (instancetype)initWithTaskIdentifier:(NSString *)identifier taskRunUUID:(NSUUID *)taskRunUUID outputDirectory:(nullable NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The identifier of the task that produced this result.

taskRunUUID

The UUID of the run of the task that produced this result.

outputDirectory

The directory in which any files referenced by results can be found.

+
+ + + +
+

Return Value

+

An initialized task result.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

  taskRunUUID +

+ +
+
+ +
+ + +
+

A unique identifier (UUID) for the presentation of the task that generated +the result.

+
+ + + +
@property (nonatomic, copy, readonly) NSUUID *taskRunUUID
+ + + + + + + + + +
+

Discussion

+

The unique identifier for a run of the task typically comes directly +from the task view controller that was used to run the task.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

  outputDirectory +

+ +
+
+ +
+ + +
+

The directory in which the generated data files were stored while the task was run.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSURL *outputDirectory
+ + + + + + + + + +
+

Discussion

+

The directory comes directly from the task view controller that was used to run this +task. Generally, when archiving the results of a task, it is useful to archive +all the files found in the output directory.

+ +

The file URL also prefixes the file URLs referenced in any child +ORKFileResult objects.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– stepResultForStepIdentifier: +

+ +
+
+ +
+ + +
+

Returns a step result for the specified step identifier, if one exists.

+
+ + + +
- (ORKStepResult *)stepResultForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier for which to search.

+
+ + + +
+

Return Value

+

The result for the specified step, or nil for none.

+
+ + + + + +
+

Discussion

+

When it’s about to present a step, the task view controller needs to look up a +suitable default answer. The answer can be used to prepopulate a survey with +the results obtained on a previous run of the same task, by passing an +ORKTaskResult object (which itself implements this protocol).

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskViewController.html new file mode 100755 index 0000000..e75df15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTaskViewController.html @@ -0,0 +1,1764 @@ + + + + + + ORKTaskViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTaskViewController Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromUIViewController
Conforms toORKStepViewControllerDelegate
UIViewControllerRestoration
Declared inORKTaskViewController.h
ORKTaskViewController.m
+ + + + +
+ +

Overview

+

The ORKTaskViewController class is the primary entry point for the presentation of the +ResearchKit framework UI. Note that a task view controller usually presents an ORKOrderedTask instance, but it can present any object that implements ORKTask.

+ +

The task view controller is intended for modal presentation, which lets the user cancel participation in the task at any time. Typically, the task view +controller displays a navigation bar and conducts right-to-left +navigation for each step as the user progresses through the task.

+ +

The task view controller supports UI state restoration, which allows users to continue a long task when they resume your app. To enable state restoration, set the restoration +identifier and take the appropriate action to restore the task view controller when your app restarts or resumes.

+ +

The task view controller also lets users save their progress in the middle of a task. To support +this scenario in your app, implement [ORKTaskViewControllerDelegate taskViewControllerSupportsSaveAndRestore:] in your +task view controller delegate, and return YES. If the task completes with the +status ORKTaskViewControllerFinishReasonSaved, copy and store the value of the +restorationData property. When the user resumes the task, create a +new task view controller using the initWithTask:restorationData: initializer, +and present it.

+ +

It is possible to configure the task view controller to prefill surveys with +data from another source, such as a previous run of the same task. +Set the defaultResultSource property to use this feature.

+ +

When conducting active tasks which may produce file results, always set the +outputDirectory property. Files generated during active steps are written to +the output directory that you specify, and references to these files are returned by ORKFileResult +objects in the result hierarchy.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithNibName:bundle: +

+ +
+
+ +
+ + +
+

Returns a newly initialized task view controller using the nib file in the specified bundle.

+
+ + + +
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+ + + +
+

Parameters

+ + + + + + + + + + + + +
nibNameOrNil

The name of the nib file from which to instantiate the task view controller.

nibBundleOrNil

The name of the bundle in which to search for the nib file.

+
+ + + +
+

Return Value

+

A new task view controller.

+
+ + + + + +
+

Discussion

+

This method is a designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new task view controller initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

The coder from which to initialize the task view controller.

+
+ + + +
+

Return Value

+

A new task view controller.

+
+ + + + + +
+

Discussion

+

This method lets you instantiate a task view controller from a storyboard, although this is an atypical use case. This method is a designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– initWithTask:taskRunUUID: +

+ +
+
+ +
+ + +
+

Returns a newly initialized task view controller.

+
+ + + +
- (instancetype)initWithTask:(id<ORKTask>)task taskRunUUID:(NSUUID *)taskRunUUID
+ + + +
+

Parameters

+ + + + + + + + + + + + +
task

The task to be presented.

taskRunUUID

The UUID of this instance of the task. If nil, a new UUID is generated.

+
+ + + +
+

Return Value

+

A new task view controller.

+
+ + + + + +
+

Discussion

+

This method is the primary designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– initWithTask:restorationData:delegate: +

+ +
+
+ +
+ + +
+

Creates a new task view controller from the specified restoration data.

+
+ + + +
- (instancetype)initWithTask:(id<ORKTask>)task restorationData:(NSData *)data delegate:(id<ORKTaskViewControllerDelegate>)delegate
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
task

The task to be presented.

data

Data obtained from the restorationData property of a previous + task view controller instance.

delegate

The delegate for the task view controller.

+
+ + + +
+

Return Value

+

A new task view controller.

+
+ + + + + +
+

Discussion

+

Call this method to restart a task when you have restoration data stored for a +previous run of the task, in which the user canceled their current task and saved their progress.

+ +

This method restores the presentation of the task to the point at which the user stopped. +If the restoration data is not valid, an exception may be thrown.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskRunUUID +

+ +
+
+ +
+ + +
+

A unique identifier (UUID) for this presentation of the task.

+
+ + + +
- (NSUUID *)taskRunUUID
+ + + + + + + + + +
+

Discussion

+

The task run UUID is a unique identifier for this run of the task view controller. +All results produced by this instance are tagged with this UUID.

+ +

The task run UUID is preserved across UI state restoration, or across task +save and restore.

Note: It is an error to set the value of taskRunUUID after the first time the task view controller +is presented.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the task result. (read-only)

+
+ + + +
- (ORKTaskResult *)result
+ + + + + + + + + +
+

Discussion

+

Use this property to obtain or inspect the results of the task. The results +are hierarchical; the children of result are ORKStepResult instances, +one for each step that the user visited during the task.

+ +

If the user uses the Back button to go back through the steps, the +results of steps that are ahead of the currently visible step are not included +in the result.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– restorationData +

+ +
+
+ +
+ + +
+

Snapshot data that can be used for future restoration.

+
+ + + +
- (NSData *)restorationData
+ + + + + + + + + +
+

Discussion

+

When the user taps Cancel during a task and selects the Save option, +the [ORKTaskViewControllerDelegate taskViewController:didFinishWithReason:error:] +method is called with ORKTaskViewControllerFinishReasonSaved. When that happens, +use restorationData to obtain restoration data that can be used to restore +the task at a later date.

+ +

Use initWithTask:restorationData: to create a new task view controller that +restores the current state.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– suspend +

+ +
+
+ +
+ + +
+

Suspends the task.

+
+ + + +
- (void)suspend
+ + + + + + + + + +
+

Discussion

+

Call this method to suspend an active step. To resume later, call +resume. Not all active steps will respond to suspend / resume, so test +thoroughly to verify correct behavior in your tasks.

+ +

This method will disable any background audio prompt session, and suspend +any active step in progress.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController_Private.h

+
+ + +
+
+
+ +

– resume +

+ +
+
+ +
+ + +
+

Resumes any current active step.

+
+ + + +
- (void)resume
+ + + + + + + + + +
+

Discussion

+

Call this method to force resuming an active step may call this +method. Should be paired with a call to suspend.

+ +

This method re-enables background audio prompts, if needed, and resumes +any active step. If not in an active step, it has no effect.

+ +

See also: suspend

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController_Private.h

+
+ + +
+
+
+ +

– goForward +

+ +
+
+ +
+ + +
+

Forces navigation to the next step.

+
+ + + +
- (void)goForward
+ + + + + + + + + +
+

Discussion

+

Call this method to force forward navigation. This method is called by the framework +if the user takes an action that requires navigation, or if the step is timed +and the timer completes.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– goBackward +

+ +
+
+ +
+ + +
+

Forces navigation to the previous step.

+
+ + + +
- (void)goBackward
+ + + + + + + + + +
+

Discussion

+

Call this method to force backward navigation. This method is called by the framework +if the user takes an action that requires backward navigation.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– stepViewControllerWillAppear: +

+ +
+
+ +
+ + +
+

Tells the delegate that the step view controller’s view is about to appear.

+
+ + + +
- (void)stepViewControllerWillAppear:(ORKStepViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + + + + + +
+

Discussion

+

This method is called from the step view controller’s viewWillAppear: method. +You can use this method to customize the appearance of the step view +controller without subclassing it.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewController:didFinishWithNavigationDirection: +

+ +
+
+ +
+ + +
+

Tells the delegate when the user has done something that requires navigation, such as +tap the Back or a Next button, or enter a response to a nonoptional +survey question.

+
+ + + +
- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

direction

Direction of navigation requested.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerDidFail:withError: +

+ +
+
+ +
+ + +
+

Tells the delegate when a step fails due to an error.

+
+ + + +
- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

error

The error detected.

+
+ + + + + + + +
+

Discussion

+

A step view controller can use this method to report its failure to the task view controller. +The task view controller sends the error to its delegate indicating that the task has failed (using ORKTaskViewControllerFinishReasonFailed). +Note that recorder errors are reported by calling the ORKStepViewControllerDelegate method stepViewController:recorder:didFailWithError:.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerResultDidChange: +

+ +
+
+ +
+ + +
+

Tells the delegate when a substantial change has occurred to the result.

+
+ + + +
- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + + + + + +
+

Discussion

+

The result is always available in the step view controller. Although the result is continuously changing +while the step view controller is active (because the time stamp in the result property is different each time it’s called), this method is called only when a substantive change +to the result occurs, such as when the user enters a survey answer or completes +an active step.

+ +

In your implementation of this delegate method, you can collect the value of result from the step view controller.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerHasPreviousStep: +

+ +
+
+ +
+ + +
+

Asks the delegate whether there is a previous step.

+
+ + + +
- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + +
+

Return Value

+

YES if a Back button should be visible; otherwise, NO.

+
+ + + + + +
+

Discussion

+

If there is a previous step, the step view controller adds a Back button to its +navigation item; if not, no Back button is added to the navigation item.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerHasNextStep: +

+ +
+
+ +
+ + +
+

Asks the delegate whether there is a next step.

+
+ + + +
- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + +
+

Return Value

+

YES if there is a step following the current one; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Depending on the result of the step, the step view controller can adjust the language for the +Next button.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewController:recorder:didFailWithError: +

+ +
+
+ +
+ + +
+

Tells the delegate when a recorder error has been detected during the step.

+
+ + + +
- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

recorder

The recorder that detected the error.

error

The error detected.

+
+ + + + + + + +
+

Discussion

+

Recorder errors can occur during active steps, usually due to the +unavailability of sensor data or disk space in which to record results.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setNavigationBarHidden:animated: +

+ +
+
+ +
+ + +
+

Shows or hides the navigation bar, with optional animation.

+
+ + + +
- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated
+ + + +
+

Parameters

+ + + + + + + + + + + + +
hidden

YES to hide the navigation bar; otherwise, NO.

animated

YES to animate the show or hide operation; otherwise, NO.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– navigationBar +

+ +
+
+ +
+ + +
+

The navigation bar for the task view controller. (read-only)

+
+ + + +
- (UINavigationBar *)navigationBar
+ + + + + + + + + +
+

Discussion

+

You can use this method to customize the appearance of the task view controller’s navigation bar.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  delegate +

+ +
+
+ +
+ + +
+

The delegate for the task view controller.

+
+ + + +
@property (nonatomic, weak, nullable) id<ORKTaskViewControllerDelegate> delegate
+ + + + + + + + + +
+

Discussion

+

There are many optional methods in the task view controller protocol, but the delegate must support +completion. When the task view controller completes its task, it is the delegate’s +responsibility to dismiss it.

+ +

See also: [ORKTaskViewControllerDelegate taskViewController:didFinishWithReason:error:].

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  task +

+ +
+
+ +
+ + +
+

The task for this task view controller.

+
+ + + +
@property (nonatomic, strong, nullable) id<ORKTask> task
+ + + + + + + + + +
+

Discussion

+

The task functions as the data source for an ORKTaskViewController object, providing +the steps that the user must complete in order to complete the task. +It is an error to change the task after presenting the task view controller.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  defaultResultSource +

+ +
+
+ +
+ + +
+

A source that the task view controller can consult to obtain default answers +for questions provided in question steps and form steps.

+
+ + + +
@property (nonatomic, strong, nullable) id<ORKTaskResultSource> defaultResultSource
+ + + + + + + + + +
+

Discussion

+

The source can provide default answers, perhaps based on previous runs of +the same task, which will be used to prefill question and form items. +For example, an ORKTaskResult object from a previous run of the task can function as +an ORKTaskResultSource object, because ORKTaskResult implements the protocol.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  outputDirectory +

+ +
+
+ +
+ + +
+

File URL for the directory in which to store generated data files.

+
+ + + +
@property (nonatomic, copy, nullable) NSURL *outputDirectory
+ + + + + + + + + +
+

Discussion

+

Active steps with recorders (and potentially other steps) can save data +to files during the progress of the task. This property specifies where such +data should be written. If no output directory is specified, active steps +that require writing data to disk, such as those with recorders, will typically +fail at runtime.

+ +

In general, set this property after instantiating the task view +controller and before presenting it.

+ +

Before presenting the view controller, set the outputDirectory property to specify a +path where files should be written when an ORKFileResult object must be returned for +a step.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  showsProgressInNavigationBar +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether progress is shown in the navigation bar.

+
+ + + +
@property (nonatomic, assign) BOOL showsProgressInNavigationBar
+ + + + + + + + + +
+

Discussion

+

Setting this property to YES does not display progress if you don’t also implement the progress +method of ORKTask.

+ +

The default value of this property is YES. To disable the display of progress in the navigation bar, set the value to NO.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  currentStepViewController +

+ +
+
+ +
+ + +
+

The current step view controller.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) ORKStepViewController *currentStepViewController
+ + + + + + + + + +
+

Discussion

+

The task view controller instantiates and presents a series of step view +controllers. The current step view controller is the one that is currently +visible on screen.

+ +

The value of this property may be nil if the task view controller has not yet been presented.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

  navigationBarHidden +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the navigation bar is hidden.

+
+ + + +
@property (nonatomic, getter=isNavigationBarHidden) BOOL navigationBarHidden
+ + + + + + + + + +
+

Discussion

+

By default, the task view controller includes a visible navigation bar. To disable the display of the navigation bar, set this property to NO.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextAnswerFormat.html new file mode 100755 index 0000000..3c7ea8d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextAnswerFormat.html @@ -0,0 +1,874 @@ + + + + + + ORKTextAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTextAnswerFormat class represents the answer format for questions that collect a text +response +from the user.

+ +

An ORKTextAnswerFormat object produces an ORKTextQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithValidationRegularExpression:invalidMessage: +

+ +
+
+ +
+ + +
+

Returns an initialized text answer format using the regular expression.

+
+ + + +
- (instancetype)initWithValidationRegularExpression:(NSRegularExpression *)validationRegularExpression invalidMessage:(NSString *)invalidMessage
+ + + +
+

Parameters

+ + + + + + + + + + + + +
validationRegularExpression

The regular expression used to validate the text.

invalidMessage

The text presented to the user when invalid input is received.

+
+ + + +
+

Return Value

+

An initialized validated text answer format.

+
+ + + + + +
+

Discussion

+

This method is one of the designated initializers.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMaximumLength: +

+ +
+
+ +
+ + +
+

Returns an initialized text answer format using the specified maximum string length.

+
+ + + +
- (instancetype)initWithMaximumLength:(NSInteger)maximumLength
+ + + +
+

Parameters

+ + + + + + + +
maximumLength

The maximum number of characters to accept. When the value of this parameter + is 0, there is no maximum.

+
+ + + +
+

Return Value

+

An initialized text answer format.

+
+ + + + + +
+

Discussion

+

This method is one of the designated initializers.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  validationRegularExpression +

+ +
+
+ +
+ + +
+

The regular expression used to validate user’s input.

+
+ + + +
@property (nonatomic, copy, nullable) NSRegularExpression *validationRegularExpression
+ + + + + + + + + +
+

Discussion

+

The default value is nil. If set to nil, no validation will be performed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  invalidMessage +

+ +
+
+ +
+ + +
+

The text presented to the user when invalid input is received.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *invalidMessage
+ + + + + + + + + +
+

Discussion

+

The default value is nil.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultTextAnswer +

+ +
+
+ +
+ + +
+

The text to be used as an answer if user input is not mandatory.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *defaultTextAnswer
+ + + + + + + + + +
+

Discussion

+

The default value is nil. If set to nil, user input is mandatory to answer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumLength +

+ +
+
+ +
+ + +
+

The maximum length of the text users can enter.

+
+ + + +
@property NSInteger maximumLength
+ + + + + + + + + +
+

Discussion

+

When the value of this property is 0, there is no maximum.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  multipleLines +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to expect more than one line of input.

+
+ + + +
@property BOOL multipleLines
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is YES.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  autocapitalizationType +

+ +
+
+ +
+ + +
+

The autocapitalization type that applies to the user’s input.

+
+ + + +
@property UITextAutocapitalizationType autocapitalizationType
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is UITextAutocapitalizationTypeSentences.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  autocorrectionType +

+ +
+
+ +
+ + +
+

The autocorrection type that applies to the user’s input.

+
+ + + +
@property UITextAutocorrectionType autocorrectionType
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is UITextAutocorrectionTypeDefault.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  spellCheckingType +

+ +
+
+ +
+ + +
+

The spell checking type that applies to the user’s input.

+
+ + + +
@property UITextSpellCheckingType spellCheckingType
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is UITextSpellCheckingTypeDefault.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  keyboardType +

+ +
+
+ +
+ + +
+

The keyboard type that applies to the user’s input.

+
+ + + +
@property UIKeyboardType keyboardType
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is UIKeyboardTypeDefault.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  secureTextEntry +

+ +
+
+ +
+ + +
+

Identifies whether the text object should hide the text being entered.

+
+ + + +
@property (nonatomic, getter=isSecureTextEntry) BOOL secureTextEntry
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextButton.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextButton.html new file mode 100755 index 0000000..2e246ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextButton.html @@ -0,0 +1,121 @@ + + + + + + ORKTextButton Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextButton Class Reference

+ + +
+ + + + + + + +
Inherits fromUIButton
Declared inORKTextButton.h
ORKTextButton.m
+ + + + +
+ +

Overview

+

“Skip” button or “Learn More” button.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoice.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoice.html new file mode 100755 index 0000000..b49690c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoice.html @@ -0,0 +1,573 @@ + + + + + + ORKTextChoice Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextChoice Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSObject
NSSecureCoding
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTextChoice class defines the text for a choice in answer formats such +as ORKTextChoiceAnswerFormat and ORKValuePickerAnswerFormat.

+ +

When a participant chooses a text choice item, the value recorded in a result +is specified by the value property.

+
+ + + + + +
+ + + + + + +
+
+ +

+ choiceWithText:detailText:value:exclusive: +

+ +
+
+ +
+ + +
+

Returns a text choice object that includes the specified primary text, detail text, +and exclusivity.

+
+ + + +
+ (instancetype)choiceWithText:(NSString *)text detailText:(nullable NSString *)detailText value:(id<NSCopying,NSCoding,NSObject>)value exclusive:(BOOL)exclusive
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
text

The primary text that describes the choice in a localized string.

detailText

The detail text to display below the primary text, in a localized string.

value

The value to record in a result object when this item is selected.

exclusive

Whether this choice is to be considered exclusive within the set of choices.

+
+ + + +
+

Return Value

+

A text choice instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

+ choiceWithText:value: +

+ +
+
+ +
+ + +
+

Returns a choice object that includes the specified primary text.

+
+ + + +
+ (instancetype)choiceWithText:(NSString *)text value:(id<NSCopying,NSCoding,NSObject>)value
+ + + +
+

Parameters

+ + + + + + + + + + + + +
text

The primary text that describes the choice in a localized string.

value

The value to record in a result object when this item is selected.

+
+ + + +
+

Return Value

+

A text choice instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithText:detailText:value:exclusive: +

+ +
+
+ +
+ + +
+

Returns an initialized text choice object using the specified primary text, detail text, +and exclusivity.

+
+ + + +
- (instancetype)initWithText:(NSString *)text detailText:(nullable NSString *)detailText value:(id<NSCopying,NSCoding,NSObject>)value exclusive:(BOOL)exclusive
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + +
text

The primary text that describes the choice in a localized string.

detailText

The detail text to display below the primary text, in a localized string.

value

The value to record in a result object when this item is selected.

exclusive

Whether this choice is to be considered exclusive within the set of choices.

+
+ + + +
+

Return Value

+

An initialized text choice.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  text +

+ +
+
+ +
+ + +
+

The text that describes the choice in a localized string.

+
+ + + +
@property (copy, readonly) NSString *text
+ + + + + + + + + +
+

Discussion

+

In general, it’s best when the text can fit on one line.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  value +

+ +
+
+ +
+ + +
+

The value to return when this choice is selected.

+
+ + + +
@property (copy, readonly) id<NSCopying,NSCoding,NSObject> value
+ + + + + + + + + +
+

Discussion

+

The value of this property is expected to be a scalar property list type, such as NSNumber +or NSString. If no value is provided, the index of the option in the options list in the +answer format is used.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  detailText +

+ +
+
+ +
+ + +
+

The text that provides additional details about the choice in a localized string.

+
+ + + +
@property (copy, readonly, nullable) NSString *detailText
+ + + + + + + + + +
+

Discussion

+

The detail text can span multiple lines. Note that ORKValuePickerAnswerFormat ignores detail +text.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  exclusive +

+ +
+
+ +
+ + +
+

In a multiple choice format, this indicates whether this choice requires all other choices to be +unselected.

+
+ + + +
@property (readonly) BOOL exclusive
+ + + + + + + + + +
+

Discussion

+

In general, this is used to indicate a “None of the above” choice.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoiceAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoiceAnswerFormat.html new file mode 100755 index 0000000..a716d28 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextChoiceAnswerFormat.html @@ -0,0 +1,420 @@ + + + + + + ORKTextChoiceAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextChoiceAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTextChoiceAnswerFormat class represents an answer format that lets participants choose +from a fixed set of text choices in a multiple or single choice question.

+ +

The text choices are presented in a table view, using one row for each answer. +The text for each answer is given more prominence than the detailText in the row, but +both are shown.

+ +

The text choice answer format produces an ORKChoiceQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithStyle:textChoices: +

+ +
+
+ +
+ + +
+

Returns an initialized text choice answer format using the specified question style and array of +text choices.

+
+ + + +
- (instancetype)initWithStyle:(ORKChoiceAnswerStyle)style textChoices:(NSArray<ORKTextChoice*> *)textChoices
+ + + +
+

Parameters

+ + + + + + + + + + + + +
style

The style of question, such as single or multiple choice.

textChoices

An array of ORKTextChoice objects.

+
+ + + +
+

Return Value

+

An initialized text choice answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  style +

+ +
+
+ +
+ + +
+

The style of the question (that is, single or multiple choice).

+
+ + + +
@property (readonly) ORKChoiceAnswerStyle style
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  textChoices +

+ +
+
+ +
+ + +
+

An array of ORKTextChoice objects that represent the choices that are displayed to participants.

+
+ + + +
@property (copy, readonly) NSArray<ORKTextChoice*> *textChoices
+ + + + + + + + + +
+

Discussion

+

The choices are presented as a table view, using one row for each answer. +The text for each answer is given more prominence than the detailText in the row, but +both are shown.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextFieldView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextFieldView.html new file mode 100755 index 0000000..5ef26e8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextFieldView.html @@ -0,0 +1,121 @@ + + + + + + ORKTextFieldView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextFieldView Class Reference

+ + +
+ + + + + + + +
Inherits fromUIView
Declared inORKTextFieldView.h
ORKTextFieldView.m
+ + + + +
+ +

Overview

+

Manages a text field with unit label and a clear button: [text unit (x)]

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextQuestionResult.html new file mode 100755 index 0000000..5d28c03 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextQuestionResult.html @@ -0,0 +1,193 @@ + + + + + + ORKTextQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKTextQuestionResult class represents the answer to a question or +form item that uses an ORKTextAnswerFormat format.

+ +

A text question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  textAnswer +

+ +
+
+ +
+ + +
+

The answer that the user entered.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *textAnswer
+ + + + + + + + + +
+

Discussion

+

If the user skipped the question, the value of this property is nil.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextScaleAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextScaleAnswerFormat.html new file mode 100755 index 0000000..eacf3ec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTextScaleAnswerFormat.html @@ -0,0 +1,650 @@ + + + + + + ORKTextScaleAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTextScaleAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTextScaleAnswerFormat represents an answer format that includes a discrete slider control +with a text label next to each step.

+ +

The scale answer format produces an ORKChoiceQuestionResult object that contains the selected text +choice’s value.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithTextChoices:defaultIndex:vertical: +

+ +
+
+ +
+ + +
+

Returns an initialized text scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithTextChoices:(NSArray<ORKTextChoice*> *)textChoices defaultIndex:(NSInteger)defaultIndex vertical:(BOOL)vertical
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
textChoices

An array of text choices which will be used to determine the + number of steps in the slider, and + to fill the text label next to each of the steps. The array must + contain between 2 and 8 text choices.

defaultIndex

The default index of the scale. If this value is out of range, + the slider is displayed without a default value.

vertical

Pass YES to use a vertical scale; for the default horizontal + scale, pass NO.

+
+ + + +
+

Return Value

+

An initialized text scale answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithTextChoices:defaultIndex: +

+ +
+
+ +
+ + +
+

Returns an initialized text scale answer format using the specified values.

+
+ + + +
- (instancetype)initWithTextChoices:(NSArray<ORKTextChoice*> *)textChoices defaultIndex:(NSInteger)defaultIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
textChoices

An array of text choices which will be used to determine the + number of steps in the slider, and + to fill the text label next to each of the steps. The array must + contain between 2 and 8 text choices.

defaultIndex

The default index of the scale. If this value is out of range, + the slider is displayed without a default value.

+
+ + + +
+

Return Value

+

An initialized text scale answer format.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  textChoices +

+ +
+
+ +
+ + +
+

An array of text choices which provides the text to be shown next to each of the slider steps. +(read-only)

+
+ + + +
@property (copy, readonly) NSArray<ORKTextChoice*> *textChoices
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultIndex +

+ +
+
+ +
+ + +
+

The default index for the slider. (read-only)

+
+ + + +
@property (readonly) NSInteger defaultIndex
+ + + + + + + + + +
+

Discussion

+

If the value of this property is less than zero or greater than the number of text choices, +the slider has no default value.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  vertical +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the scale is oriented vertically. (read-only)

+
+ + + +
@property (readonly, getter=isVertical) BOOL vertical
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientColors +

+ +
+
+ +
+ + +
+

The colors to use when drawing a color gradient above the slider. Colors are drawn such that +lower indexes correspond to the minimum side of the scale, while colors at higher indexes in +the array corresond to the maximum side of the scale.

+
+ + + +
@property (copy, nullable) NSArray<UIColor*> *gradientColors
+ + + + + + + + + +
+

Discussion

+

Setting this value to nil results in no gradient being drawn. Defaults to nil.

+ +

An example usage would set an array of red and green to visually indicate a scale from bad to good.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  gradientLocations +

+ +
+
+ +
+ + +
+

Indicates the position of gradient stops for the colors specified in gradientColors. +Gradient stops are specified as values between 0 and 1. The values must be monotonically +increasing.

+
+ + + +
@property (copy, nullable) NSArray<NSNumber*> *gradientLocations
+ + + + + + + + + +
+

Discussion

+

If nil, the stops are spread uniformly across the range. Defaults to nil.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalAnswerFormat.html new file mode 100755 index 0000000..fec7021 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalAnswerFormat.html @@ -0,0 +1,426 @@ + + + + + + ORKTimeIntervalAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimeIntervalAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTimeIntervalAnswerFormat class represents the answer format for questions that ask users + to specify a time interval.

+ +

The time interval answer format is suitable for time intervals up to 24 hours. If you need to track +time intervals of longer duration, use a different answer format, such as +ORKValuePickerAnswerFormat.

+ +

Note that the time interval answer format does not support the selection of 0.

+ +

A time interval answer format produces an ORKTimeIntervalQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithDefaultInterval:step: +

+ +
+
+ +
+ + +
+

Returns an initialized time interval answer format using the specified default interval and step +value.

+
+ + + +
- (instancetype)initWithDefaultInterval:(NSTimeInterval)defaultInterval step:(NSInteger)step
+ + + +
+

Parameters

+ + + + + + + + + + + + +
defaultInterval

The default value to display in the picker.

step

The step in the interval, in minutes. The value of this parameter must + be between 1 and 30.

+
+ + + +
+

Return Value

+

An initialized time interval answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultInterval +

+ +
+
+ +
+ + +
+

The initial time interval displayed in the picker.

+
+ + + +
@property (readonly) NSTimeInterval defaultInterval
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  step +

+ +
+
+ +
+ + +
+

The size of the allowed step in the interval, in minutes.

+
+ + + +
@property (readonly) NSInteger step
+ + + + + + + + + +
+

Discussion

+

By default, the value of this property is 1. The minimum value is 1, and the maximum value is 30.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalQuestionResult.html new file mode 100755 index 0000000..03033f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeIntervalQuestionResult.html @@ -0,0 +1,193 @@ + + + + + + ORKTimeIntervalQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimeIntervalQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKTimeIntervalQuestionResult class represents the result of a question +that uses the ORKTimeIntervalAnswerFormat format.

+ +

A time interval question result is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  intervalAnswer +

+ +
+
+ +
+ + +
+

The selected interval, in seconds.

+
+ + + +
@property (nonatomic, copy, nullable) NSNumber *intervalAnswer
+ + + + + + + + + +
+

Discussion

+

The value of this property is nil if the user skipped the question.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayAnswerFormat.html new file mode 100755 index 0000000..491d381 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayAnswerFormat.html @@ -0,0 +1,321 @@ + + + + + + ORKTimeOfDayAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimeOfDayAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKTimeOfDayAnswerFormat class represents the answer format for questions that require users +to enter a time of day.

+ +

A time of day answer format produces an ORKTimeOfDayQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithDefaultComponents: +

+ +
+
+ +
+ + +
+

Returns an initialized time of day answer format using the specified default value.

+
+ + + +
- (instancetype)initWithDefaultComponents:(nullable NSDateComponents *)defaultComponents
+ + + +
+

Parameters

+ + + + + + + +
defaultComponents

The default value with which to configure the picker.

+
+ + + +
+

Return Value

+

An initialized time of day answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultComponents +

+ +
+
+ +
+ + +
+

The default time of day to display in the picker. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSDateComponents *defaultComponents
+ + + + + + + + + +
+

Discussion

+

Note that both the hour and minute components are observed. If the value of this property is nil, +the picker displays the current time of day.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayQuestionResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayQuestionResult.html new file mode 100755 index 0000000..b65dc4c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimeOfDayQuestionResult.html @@ -0,0 +1,188 @@ + + + + + + ORKTimeOfDayQuestionResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimeOfDayQuestionResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKQuestionResult : ORKResult : NSObject
Declared inORKQuestionResult.h
ORKQuestionResult.m
+ + + + +
+ +

Overview

+

The ORKTimeOfDayQuestionResult class represents the result of a question that uses the ORKTimeOfDayAnswerFormat format.

+
+ + + + + +
+ + + + + + +
+
+ +

  dateComponentsAnswer +

+ +
+
+ +
+ + +
+

The date components picked by the user.

+
+ + + +
@property (nonatomic, copy, nullable) NSDateComponents *dateComponentsAnswer
+ + + + + + + + + +
+

Discussion

+

Typically only hour, minute, and AM/PM data are of interest.

+
+ + + + + + + +
+

Declared In

+

ORKQuestionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkResult.html new file mode 100755 index 0000000..70cfeb8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkResult.html @@ -0,0 +1,272 @@ + + + + + + ORKTimedWalkResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimedWalkResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKTimedWalkResult.h
ORKTimedWalkResult.m
+ + + + +
+ +

Overview

+

The ORKTimedWalkResult class records the results of a Timed Walk test.

+ +

The timed walk result object records the duration to complete the trial with a specific distance +and time limit.

+
+ + + + + +
+ + + + + + +
+
+ +

  distanceInMeters +

+ +
+
+ +
+ + +
+

The timed walk distance in meters.

+
+ + + +
@property (nonatomic, assign) double distanceInMeters
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTimedWalkResult.h

+
+ + +
+
+
+ +

  timeLimit +

+ +
+
+ +
+ + +
+

The time limit to complete the trials.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval timeLimit
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTimedWalkResult.h

+
+ + +
+
+
+ +

  duration +

+ +
+
+ +
+ + +
+

The trial duration (that is, the time taken to do the walk).

+
+ + + +
@property (nonatomic, assign) NSTimeInterval duration
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTimedWalkResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStep.html new file mode 100755 index 0000000..b147fae --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStep.html @@ -0,0 +1,265 @@ + + + + + + ORKTimedWalkStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimedWalkStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKTimedWalkStep.h
ORKTimedWalkStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStepViewController.html new file mode 100755 index 0000000..c3770c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTimedWalkStepViewController.html @@ -0,0 +1,310 @@ + + + + + + ORKTimedWalkStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTimedWalkStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKTimedWalkStepViewController.h
ORKTimedWalkStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– finish +

+ +
+
+ +
+ + +
+

Finishes the active step.

+
+ + + +
- (void)finish
+ + + + + + + + + +
+

Discussion

+

Call this method to finish the active step. If the active step is configured with +a timer, this method is called automatically when the timer expires.

+ +

Finishing the active step stops all data recording and stops any timers. In steps that have the +shouldContinueOnFinish property set, forward navigation to the next step +may ensue.

+ +

This method does nothing if the step has already finished.

+ +

Subclasses should call super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryResult.html new file mode 100755 index 0000000..80929fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryResult.html @@ -0,0 +1,237 @@ + + + + + + ORKToneAudiometryResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKToneAudiometryResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKToneAudiometryResult.h
ORKToneAudiometryResult.m
+ + + + +
+ +

Overview

+

The ORKToneAudiometryResult class records the results of a tone audiometry test.

+ +

The audiometry samples are generated by the framework when the task completes. +It may be appropriate to serialize them for transmission to a server, +or to immediately perform analysis on them.

+
+ + + + + +
+ + + + + + +
+
+ +

  outputVolume +

+ +
+
+ +
+ + +
+

The system wide output volume set by the user during the audiometry test.

+
+ + + +
@property (nonatomic, copy, nullable) NSNumber *outputVolume
+ + + + + + + + + +
+

Discussion

+

A value in the range 0.0 to 1.0, with 0.0 representing the minimum volume +and 1.0 representing the maximum volume.

+
+ + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+ +

  samples +

+ +
+
+ +
+ + +
+

An array of collected samples, in which each item is an ORKToneAudiometrySample +object that represents an audiometry sample.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKToneAudiometrySample*> *samples
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometrySample.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometrySample.html new file mode 100755 index 0000000..592ea09 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometrySample.html @@ -0,0 +1,330 @@ + + + + + + ORKToneAudiometrySample Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKToneAudiometrySample Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKToneAudiometryResult.h
ORKToneAudiometryResult.m
+ + + + +
+ +

Overview

+

The ORKToneAudiometrySample class represents an audio amplitude associated +with a frequency and a channel.

+ +

The sample object records the amplitude, the frequency, and the channel for the audio +tone being played. A tone audiometry sample is included in an ORKToneAudiometryResult +object, and is recorded by the step view controller for the corresponding task +when a tap is recognized for a given tone.

+ +

A tone audiometry sample is typically generated by the framework as the task proceeds. +When the task completes, it may be appropriate to serialize the sample for +transmission to a server or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  frequency +

+ +
+
+ +
+ + +
+

The frequency value in hertz for the tone associated with the sample.

+
+ + + +
@property (nonatomic, assign) double frequency
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+ +

  channel +

+ +
+
+ +
+ + +
+

The channel, either left or right, for the tone associated with the sample.

+
+ + + +
@property (nonatomic, assign) ORKAudioChannel channel
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+ +

  channelSelected +

+ +
+
+ +
+ + +
+

The channel selected by the user.

+
+ + + +
@property (nonatomic, assign) ORKAudioChannel channelSelected
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+ +

  amplitude +

+ +
+
+ +
+ + +
+

The audio signal amplitude.

+
+ + + +
@property (nonatomic, assign) double amplitude
+ + + + + + + + + +
+

Discussion

+

The minimum audio sample amplitude needed for the participant to recognize the sound (a double value between 0 and 1).

+
+ + + + + + + +
+

Declared In

+

ORKToneAudiometryResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStep.html new file mode 100755 index 0000000..c29a120 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStep.html @@ -0,0 +1,265 @@ + + + + + + ORKToneAudiometryStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKToneAudiometryStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKToneAudiometryStep.h
ORKToneAudiometryStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStepViewController.html new file mode 100755 index 0000000..6f0e3c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKToneAudiometryStepViewController.html @@ -0,0 +1,361 @@ + + + + + + ORKToneAudiometryStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKToneAudiometryStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKToneAudiometryStepViewController.h
ORKToneAudiometryStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchAnywhereStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchAnywhereStep.html new file mode 100755 index 0000000..b72060a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchAnywhereStep.html @@ -0,0 +1,238 @@ + + + + + + ORKTouchAnywhereStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTouchAnywhereStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKTouchAnywhereStep.h
ORKTouchAnywhereStep.m
+ + + + +
+ +

Overview

+

The ORKTouchAnywhereStep class represents a step that displays a title with custom instructions +and the text “Touch anywhere to continue.” The user can touch almost anywhere on the +screen and the step will end and the task will continue. The back button is still +tappable.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier:instructionText: +

+ +
+
+ +
+ + +
+

Init with an identifier and instruction text. Instruction text should be used to tell the user +where to place the device before touching anywhere.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier instructionText:(NSString *)instructionText
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTouchAnywhereStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorder.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorder.html new file mode 100755 index 0000000..f04d3c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorder.html @@ -0,0 +1,424 @@ + + + + + + ORKTouchRecorder Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTouchRecorder Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorder : NSObject
Declared inORKTouchRecorder.h
ORKTouchRecorder.m
+ + + + +
+ +

Overview

+

The ORKTouchRecorder class defines the attributes and behavior of touch events recorder.

+ +

This class is considered private because its interface is not yet considered +stable. It is not currently used by any of the pre-defined active tasks.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– viewController:willStartStepWithView: +

+ +
+
+ +
+ + +
+

A preparation step to provide viewController and view before record starting.

+
+ + + +
- (void)viewController:(UIViewController *)viewController willStartStepWithView:(UIView *)view
+ + + +
+

Parameters

+ + + + + + + + + + + + +
viewController

The view controller that is about to ‘start’

view

Primary active view for the step.

+
+ + + + + + + +
+

Discussion

+

The step view controller should call this method before starting the recorder, +so that recorders that need a view or gesture recognizer in order to function +can attach themselves.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts data recording.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

If an error occurs when recording starts, it is returned through the delegate.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops data recording, which generally triggers the return of results.

+
+ + + +
- (void)stop
+ + + + + + + + + +
+

Discussion

+

If an error occurs when stopping the recorder, it is returned through the delegate. +Subclasses should call finishRecordingWithError: rather than calling super.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– finishRecordingWithError: +

+ +
+
+ +
+ + +
+

Indicates that recording has failed; stop recording and report the error to the +delegate

+
+ + + +
- (void)finishRecordingWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + +
error

Error that occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  touchView +

+ +
+
+ +
+ + +
+

The ORKTouchRecorder attaches a gesture recognizer to touchView to receive touch events.

+
+ + + +
@property (nonatomic, strong, readonly, nullable) UIView *touchView
+ + + + + + + + + +
+

Discussion

+

Use viewController:willStartStepWithView: to set the touchView property before +the touch recorder starts.

+
+ + + + + + + +
+

Declared In

+

ORKTouchRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorderConfiguration.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorderConfiguration.html new file mode 100755 index 0000000..422da14 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTouchRecorderConfiguration.html @@ -0,0 +1,333 @@ + + + + + + ORKTouchRecorderConfiguration Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTouchRecorderConfiguration Class Reference

+ + +
+ + + + + + + +
Inherits fromORKRecorderConfiguration : NSObject
Declared inORKRecorder_Private.h
ORKTouchRecorder.m
+ + + + +
+ +

Overview

+

The ORKTouchRecorderConfiguration is a recorder configuration class for +generating an ORKTouchRecorder.

+ +

It is currently considered private, and is not used in any of the active tasks.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized touch recorder configuration.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the recorder configuration.

+
+ + + +
+

Return Value

+

An initialized touch recorder configuration.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+ +

– recorderForStep:outputDirectory: +

+ +
+
+ +
+ + +
+

Returns a recorder instance using this configuration.

+
+ + + +
- (ORKRecorder *)recorderForStep:(ORKStep *)step outputDirectory:(NSURL *)outputDirectory
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step for which this recorder is being created.

outputDirectory

The directory in which all output file data should be written (if producing ORKFileResult instances).

+
+ + + +
+

Return Value

+

A configured recorder instance.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + +
+

Returns a new touch recorder configuration initialized from data in the given unarchiver.

+
+ + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + +
+

Parameters

+ + + + + + + +
aDecoder

Coder from which to initialize the touch recorder configuration.

+
+ + + +
+

Return Value

+

A new touch recorder configuration.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKRecorder_Private.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiMove.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiMove.html new file mode 100755 index 0000000..5f08d35 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiMove.html @@ -0,0 +1,303 @@ + + + + + + ORKTowerOfHanoiMove Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTowerOfHanoiMove Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKTowerOfHanoiResult.h
ORKTowerOfHanoiResult.m
+ + + + +
+ +

Overview

+

The ORKTowerOfHanoiMove class represents a single move in a Tower of Hanoi puzzle.

+ +

The Tower of Hanoi move object records the indexes of the donor and recipient towers +and the time at which the event occurred. A towerOfHanoiMove instance is included in +an ORKTowerOfHanoiResult object and is recorded by the step view controller for the +corresponding task when a move is made.

+ +

A Tower of Hanoi move is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize the move for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  timestamp +

+ +
+
+ +
+ + +
+

A relative timestamp indicating the time of the tap event.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval timestamp
+ + + + + + + + + +
+

Discussion

+

The timestamp is relative to the value of startDate in the ORKResult object that includes this move. +The start date of that object represents the time at which the first move was made.

+
+ + + + + + + +
+

Declared In

+

ORKTowerOfHanoiResult.h

+
+ + +
+
+
+ +

  donorTowerIndex +

+ +
+
+ +
+ + +
+

The index of the donor tower in the move.

+
+ + + +
@property (nonatomic, assign) NSUInteger donorTowerIndex
+ + + + + + + + + +
+

Discussion

+

The Tower of Hanoi puzzle has three towers, and so the value of this property is +therefore always 0, 1, or 2. The indexes sequentially represent the towers from left to right when they are laid out +horizontally and from top to bottom when they are layed out vertically. The index for a given tower is consistent +between changes to and from the horizontal and vertical layouts.

+
+ + + + + + + +
+

Declared In

+

ORKTowerOfHanoiResult.h

+
+ + +
+
+
+ +

  recipientTowerIndex +

+ +
+
+ +
+ + +
+

The index of the recipient tower in the move.

+
+ + + +
@property (nonatomic, assign) NSUInteger recipientTowerIndex
+ + + + + + + + + +
+

Discussion

+

The Tower of Hanoi puzzle has three towers, and so the value of this property is +therefore always 0, 1, or 2. The indexes sequentially represent the towers from left to right when they are laid out +horizontally and from top to bottom when they are layed out vertically. The index for a given tower is consistent +between changes to and from the horizontal and vertical layouts.

+
+ + + + + + + +
+

Declared In

+

ORKTowerOfHanoiResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiResult.html new file mode 100755 index 0000000..220ed25 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiResult.html @@ -0,0 +1,238 @@ + + + + + + ORKTowerOfHanoiResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTowerOfHanoiResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKTowerOfHanoiResult.h
ORKTowerOfHanoiResult.m
+ + + + +
+ +

Overview

+

The ORKTowerOfHanoiResult class records the results of a Tower of Hanoi active task.

+ +

An ORKTowerOfHanoiResult object records an array of ORKTowerOfHanoiMove objects (one for each move) +and a Boolean value representing whether the puzzle was solved or not.

+ +

An ORKTowerOfHanoiResult object is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize it for transmission to a server +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  puzzleWasSolved +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether the puzzle was solved.

+
+ + + +
@property (nonatomic, assign) BOOL puzzleWasSolved
+ + + + + + + + + +
+

Discussion

+

The value of this property is YES when the puzzle was solved and NO otherwise.

+
+ + + + + + + +
+

Declared In

+

ORKTowerOfHanoiResult.h

+
+ + +
+
+
+ +

  moves +

+ +
+
+ +
+ + +
+

An array of moves, in which each item is an ORKTowerOfHanoiMove object that represents a move.

+
+ + + +
@property (nonatomic, copy, nullable) NSArray<ORKTowerOfHanoiMove*> *moves
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTowerOfHanoiResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiStep.html new file mode 100755 index 0000000..064e470 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiStep.html @@ -0,0 +1,429 @@ + + + + + + ORKTowerOfHanoiStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTowerOfHanoiStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKTowerOfHanoiStep.h
ORKTowerOfHanoiStep.m
+ + + + +
+ +

Overview

+

Tower of Hanoi step.

+ +

This step is used to present the interactive Tower of Hanoi activity.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  numberOfDisks +

+ +
+
+ +
+ + +
+

The number of disks in the puzzle.

+
+ + + +
@property (nonatomic, assign) NSUInteger numberOfDisks
+ + + + + + + + + +
+

Discussion

+

It is not recommended that you use a large number of disks. As this provides a poor user experience. +The default value of this property is 3.

+
+ + + + + + + +
+

Declared In

+

ORKTowerOfHanoiStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– shouldContinueOnFinish +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether to transition automatically when the step finishes.

+
+ + + +
- (BOOL)shouldContinueOnFinish
+ + + + + + + + + +
+

Discussion

+

When the value of this property is YES, the active step view controller automatically performs the +continue action when the [ORKActiveStepViewController finish] method +is called.

+ +

The default value of this property is NO.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiViewController.html new file mode 100755 index 0000000..ebca61d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTowerOfHanoiViewController.html @@ -0,0 +1,236 @@ + + + + + + ORKTowerOfHanoiViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTowerOfHanoiViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKTowerOfHanoiStepViewController.h
ORKTowerOfHanoiStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– skipForward +

+ +
+
+ +
+ + +
+

This method is called when the user taps the skip button. By default, it calls goForward.

+
+ + + +
- (void)skipForward
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingResult.html new file mode 100755 index 0000000..df87f6a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingResult.html @@ -0,0 +1,300 @@ + + + + + + ORKTrailmakingResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTrailmakingResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKTrailmakingResult.h
ORKTrailmakingResult.m
+ + + + +
+ +

Overview

+

The ORKTrailmakingResult class represents the result of a signature step (ORKTrailmakingStep).

+ +

A trail making result is produced by the task view controller when it presents a trail making step.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns an initialized result using the specified identifier.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The unique identifier of the result.

+
+ + + + + + + +
+

Discussion

+

Typically, objects such as ORKStepViewController and ORKTaskViewController instantiate result (and ORKResult subclass) objects; you seldom need to instantiate a result object in your code.

+
+ + + + + + + +
+

Declared In

+

ORKResult.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  taps +

+ +
+
+ +
+ + +
+

An array of all taps completed during the test

+
+ + + +
@property (nonatomic, copy) NSArray<ORKTrailmakingTap*> *taps
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTrailmakingResult.h

+
+ + +
+
+
+ +

  numberOfErrors +

+ +
+
+ +
+ + +
+

The number of errors generated during the test

+
+ + + +
@property (nonatomic) NSUInteger numberOfErrors
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTrailmakingResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStep.html new file mode 100755 index 0000000..ecbe8c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStep.html @@ -0,0 +1,359 @@ + + + + + + ORKTrailmakingStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTrailmakingStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKTrailmakingStep.h
ORKTrailmakingStep.m
+ + + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  trailType +

+ +
+
+ +
+ + +
+

The type of trail to show. Default = ORKTrailMakingTypeIdentifierA

+
+ + + +
@property (nonatomic, copy) ORKTrailMakingTypeIdentifier trailType
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTrailmakingStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStepViewController.html new file mode 100755 index 0000000..f8274a8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingStepViewController.html @@ -0,0 +1,253 @@ + + + + + + ORKTrailmakingStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTrailmakingStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKTrailmakingStepViewController.h
ORKTrailmakingStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingTap.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingTap.html new file mode 100755 index 0000000..4f303af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKTrailmakingTap.html @@ -0,0 +1,287 @@ + + + + + + ORKTrailmakingTap Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTrailmakingTap Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toNSCopying
NSSecureCoding
Declared inORKTrailmakingResult.h
ORKTrailmakingResult.m
+ + + + +
+ +

Overview

+

The ORKTrailmakingTap class represents a single tap in a trail making test.

+ +

The Trailmaking tap move object records the indexes of tap, if it was in error or not +and the time at which the event occurred. A trailmakingTap instance is included in +an ORKTrailmakingResult object and is recorded by the step view controller for the +corresponding task when a tap is made.

+ +

A trail making tap is typically generated by the framework as the task proceeds. When the task +completes, it may be appropriate to serialize the move for transmission to a server, +or to immediately perform analysis on it.

+
+ + + + + +
+ + + + + + +
+
+ +

  timestamp +

+ +
+
+ +
+ + +
+

A relative timestamp indicating the time of the tap event.

+
+ + + +
@property (nonatomic, assign) NSTimeInterval timestamp
+ + + + + + + + + +
+

Discussion

+

The timestamp is relative to the value of startDate in the ORKResult object that includes this move. +The start date of that object represents the time at which the first move was made.

+
+ + + + + + + +
+

Declared In

+

ORKTrailmakingResult.h

+
+ + +
+
+
+ +

  index +

+ +
+
+ +
+ + +
+

The index of the button tapped.

+
+ + + +
@property (nonatomic, assign) NSUInteger index
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTrailmakingResult.h

+
+ + +
+
+
+ +

  incorrect +

+ +
+
+ +
+ + +
+

If the button was tapped in error.

+
+ + + +
@property (nonatomic, assign) BOOL incorrect
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTrailmakingResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKUnitLabel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKUnitLabel.html new file mode 100755 index 0000000..a9f28bb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKUnitLabel.html @@ -0,0 +1,121 @@ + + + + + + ORKUnitLabel Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKUnitLabel Class Reference

+ + +
+ + + + + + + +
Inherits fromORKLabel : UILabel
Declared inORKUnitLabel.h
ORKUnitLabel.m
+ + + + +
+ +

Overview

+

Text label for units during numeric value entry

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValuePickerAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValuePickerAnswerFormat.html new file mode 100755 index 0000000..fc8469c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValuePickerAnswerFormat.html @@ -0,0 +1,378 @@ + + + + + + ORKValuePickerAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValuePickerAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKValuePickerAnswerFormat class represents an answer format that lets participants use a +value picker to choose from a fixed set of text choices.

+ +

When the number of choices is relatively large and the text that describes each choice +is short, you might want to use the value picker answer format instead of the text choice answer +format (ORKTextChoiceAnswerFormat). When the text that describes each choice is long, or there +are only a very small number of choices, it’s usually better to use the text choice answer format.

+ +

Note that the value picker answer format reports itself as being of the single choice question +type. The value picker answer format produces an ORKChoiceQuestionResult object.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– initWithTextChoices: +

+ +
+
+ +
+ + +
+

Returns a value picker answer format using the specified array of text choices.

+
+ + + +
- (instancetype)initWithTextChoices:(NSArray<ORKTextChoice*> *)textChoices
+ + + +
+

Parameters

+ + + + + + + +
textChoices

Array of ORKTextChoice objects.

+
+ + + +
+

Return Value

+

An initialized value picker answer format.

+
+ + + + + +
+

Discussion

+

Note that the detailText property of each choice is ignored. Be sure to create localized text for +each choice that is short enough to fit in a UIPickerView object.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  textChoices +

+ +
+
+ +
+ + +
+

An array of text choices that represent the options to display in the picker. (read-only)

+
+ + + +
@property (copy, readonly) NSArray<ORKTextChoice*> *textChoices
+ + + + + + + + + +
+

Discussion

+

Note that the detailText property of each choice is ignored. Be sure to create localized text for +each choice that is short enough to fit in a UIPickerView object.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the parameters of the answer format to ensure that they can be displayed.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

Typically, this method is called by the validation methods of the owning objects, which are +themselves called when a step view controller that contains this answer format is +about to be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRange.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRange.html new file mode 100755 index 0000000..3409e1c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRange.html @@ -0,0 +1,507 @@ + + + + + + ORKValueRange Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueRange Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKValueCollectionType
Declared inORKChartTypes.h
ORKChartTypes.m
+ + + + +
+ +

Overview

+

The ORKValueRange class represents a range between two values of the double type. It can be used +in graph chart plots to draw value ranges.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithMinimumValue:maximumValue: +

+ +
+
+ +
+ + +
+

Returns a value range initialized using the specified minimumValue and maximumValue.

+
+ + + +
- (instancetype)initWithMinimumValue:(double)minimumValue maximumValue:(double)maximumValue
+ + + +
+

Parameters

+ + + + + + + + + + + + +
minimumValue

The minimumValue to set.

maximumValue

The maximumValue to set.

+
+ + + +
+

Return Value

+

A value range object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

– initWithValue: +

+ +
+
+ +
+ + +
+

Returns a value range initialized using the specified value for both minimumValue and +maximumValue. This is useful for plotting data points that model a single value with no range.

+
+ + + +
- (instancetype)initWithValue:(double)value
+ + + +
+

Parameters

+ + + + + + + +
value

The minimumValue and maximumValue to set.

+
+ + + +
+

Return Value

+

A value range object.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

– init +

+ +
+
+ +
+ + +
+

Returns a value range initialized using the ORKDoubleInvalidValue value for both minimumValue +and maximumValue. This denotes an unset or invalid value range. It is useful, for example, for +representing unavailable data in discontinous graph chart plots.

+
+ + + +
- (instancetype)init
+ + + + + +
+

Return Value

+

A value range object initialized with the ORKDoubleInvalidValue value.

+
+ + + + + +
+

Discussion

+

This method is a convenience initializer.

+
+ + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  maximumValue +

+ +
+
+ +
+ + +
+

The upper limit of the value range.

+
+ + + +
@property (nonatomic) double maximumValue
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  minimumValue +

+ +
+
+ +
+ + +
+

The lower limit of the value range.

+
+ + + +
@property (nonatomic) double minimumValue
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  isEmptyRange +

+ +
+
+ +
+ + +
+

A Boolean value indicating that minimumValue is equal to maximumValue. (read-only)

+
+ + + +
@property (nonatomic, readonly) BOOL isEmptyRange
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  isUnset +

+ +
+
+ +
+ + +
+

A Boolean value indicating that both minimum value and maximum value are equal to the +ORKDoubleInvalidValue value. (read-only)

+
+ + + +
@property (nonatomic, readonly) BOOL isUnset
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRangeGraphChartView.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRangeGraphChartView.html new file mode 100755 index 0000000..261a517 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueRangeGraphChartView.html @@ -0,0 +1,252 @@ + + + + + + ORKValueRangeGraphChartView Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueRangeGraphChartView Class Reference

+ + +
+ + + + + + + +
Inherits fromORKGraphChartView : UIView
Declared inORKGraphChartView.h
ORKGraphChartView.m
+ + + + +
+ +

Overview

+

The ORKValueRangeGraphChartView class is an abstract class which holds a data source comforming +to the ORKValueRangeGraphChartViewDataSource protocol, common to concrete subclasseses.

+ +

You should not instantiate this class directly; use one of the subclasses instead. The concrete +subclasses are ORKLineGraphChartView and ORKDiscreteGraphChartView.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  dataSource +

+ +
+
+ +
+ + +
+

The data source responsible for providing the data required to populate the graph chart view.

+
+ + + +
@property (nonatomic, weak) id<ORKValueRangeGraphChartViewDataSource> dataSource
+ + + + + + + + + +
+

Discussion

+

See the ORKValueRangeGraphChartViewDataSource protocol.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– reloadData +

+ +
+
+ +
+ + +
+

Reloads the plotted data.

+
+ + + +
- (void)reloadData
+ + + + + + + + + +
+

Discussion

+

Call this method to reload the data and re-plot the graph. You should call it if the data provided by the dataSource changes.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueStack.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueStack.html new file mode 100755 index 0000000..93229e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKValueStack.html @@ -0,0 +1,393 @@ + + + + + + ORKValueStack Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueStack Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKValueCollectionType
Declared inORKChartTypes.h
ORKChartTypes.m
+ + + + +
+ +

Overview

+

The ORKValueStack class represents an arbitrary list of values of the double type. It can be used +in graph chart plots to draw stacked values.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– init +

+ +
+
+ +
+ + +
+

Returns an empty value stack.

+
+ + + +
- (instancetype)init
+ + + + + +
+

Return Value

+

An empty value stack object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

– initWithStackedValues: +

+ +
+
+ +
+ + +
+

Returns a value stack initialized with the passed NSNumber array.

+
+ + + +
- (instancetype)initWithStackedValues:(NSArray<NSNumber*> *)stackedValues
+ + + +
+

Parameters

+ + + + + + + +
stackedValues

An array containing NSNumber objects.

+
+ + + +
+

Return Value

+

A value stack object initialized with the passed NSNumber values.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  stackedValues +

+ +
+
+ +
+ + +
+

An array of NSNumber objects, each one representing a stacked double value.

+
+ + + +
@property (nonatomic, copy, readonly) NSArray<NSNumber*> *stackedValues
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+ +

  totalValue +

+ +
+
+ +
+ + +
+

The total sum of the stacked double values

+
+ + + +
@property (nonatomic) double totalValue
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– isUnset +

+ +
+
+ +
+ + +
+

A Boolean value indicating that the value is unset. (read-only)

+
+ + + +
- (BOOL)isUnset
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStep.html new file mode 100755 index 0000000..57e93bc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStep.html @@ -0,0 +1,446 @@ + + + + + + ORKVerificationStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVerificationStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKVerificationStep.h
ORKVerificationStep.m
+ + + + +
+ +

Overview

+

The ORKVerificationStep class represents a step that serves as placeholder +step to use while the user attempts to verify their account.

+ +

The verification step contains a text field and a resend email button. The button +actions must be overriden inside a subclassed verification view controller to provide +navigation logic.

+ +

The developer should redirect user back to the app once the verification is done +and move forward automatically.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– stepViewControllerClass +

+ +
+
+ +
+ + + + +
- (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:text:verificationViewControllerClass: +

+ +
+
+ +
+ + +
+

Returns an initialized verification step using the specified identifier, +title, text, and class.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier text:(NSString *)text verificationViewControllerClass:(Class)verificationViewControllerClass
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
identifier

The string that identifies the step (see ORKStep).

text

The text shown immediately below the title (see ORKStep).

verificationViewControllerClass

The subclassed verification view controller class.

+
+ + + +
+

Return Value

+

An initialized verification step object.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKVerificationStep.h

+
+ + +
+
+
+ +

– verificationViewControllerClass +

+ +
+
+ +
+ + +
+

The view controller subclass used for the step.

+
+ + + +
- (Class)verificationViewControllerClass
+ + + + + + + + + +
+

Discussion

+

The subclass allows you to override button actions in order to provide navigation logic +for the button items on the step.

+
+ + + + + + + +
+

Declared In

+

ORKVerificationStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStepViewController.html new file mode 100755 index 0000000..b5f9966 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVerificationStepViewController.html @@ -0,0 +1,192 @@ + + + + + + ORKVerificationStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVerificationStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKVerificationStepViewController.h
ORKVerificationStepViewController.m
+ + + + +
+ +

Overview

+

The ORKVerificationStepViewController class is the concrete ORKStepViewController +implementation for ORKVerificationStep.

+ +

You should subclass a verification step view controller and override the button action +methods to provide your navigation logic. All override methods are required.

+
+ + + + + +
+ + + + + + +
+
+ +

– resendEmailButtonTapped +

+ +
+
+ +
+ + +
+

Action method for the resend email button.

+
+ + + +
- (void)resendEmailButtonTapped
+ + + + + + + + + +
+

Discussion

+

Override this method to provide custom logic for the button action.

+
+ + + + + + + +
+

Declared In

+

ORKVerificationStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStep.html new file mode 100755 index 0000000..d8a6029 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStep.html @@ -0,0 +1,679 @@ + + + + + + ORKVideoCaptureStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVideoCaptureStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKVideoCaptureStep.h
ORKVideoCaptureStep.m
+ + + + +
+ +

Overview

+

The ORKVideoCaptureStep class represents a step that captures a video through the device +camera. A template image can optionally be laid over the camera preview to assist in properly +capturing the video.

+ +

To use the video capture step, optionally set the templateImage and templateImageInsets +properties, incorporate the step into a task, and present the task with a task view controller.

+ +

If implementing a video capture task like this one, remember that people will +take your instructions literally. So be cautious. Make sure your template image +is high contrast and very visible against a variety of backgrounds.

+ +

The recording length can be a max of 20 minutes. It defaults to 2 minutes.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  templateImage +

+ +
+
+ +
+ + +
+

An image to be displayed over the camera preview.

+
+ + + +
@property (nonatomic, strong) UIImage *templateImage
+ + + + + + + + + +
+

Discussion

+

The image is stretched to fit the available space while retaining its aspect ratio. +When choosing a size for this asset, be sure to take into account the variations in device +form factors.

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  templateImageInsets +

+ +
+
+ +
+ + +
+

Insets to be used in positioning and sizing the templateImage.

+
+ + + +
@property (nonatomic) UIEdgeInsets templateImageInsets
+ + + + + + + + + +
+

Discussion

+

The insets are interpreted as percentages relative to the preview frame size. The left +and right insets are relative to the width of the preview frame. The top and bottom +insets are relative to the height of the preview frame.

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  duration +

+ +
+
+ +
+ + +
+

The duration, in seconds, for the recording.

+
+ + + +
@property (nonatomic) NSNumber *duration
+ + + + + + + + + +
+

Discussion

+

The maximum that this can be set to is 20.0 minutes (60*20 seconds). +The minimum that this can be set to is 0.01 minutes (1 second).

+ +

The default value is 2.0 minutes (60*2 seconds).

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  audioMute +

+ +
+
+ +
+ + +
+

A Boolean indicating whether the audio is recorded or not.

+
+ + + +
@property (nonatomic, getter=isAudioMute) BOOL audioMute
+ + + + + + + + + +
+

Discussion

+

The default value is NO.

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  flashMode +

+ +
+
+ +
+ + +
+

Constants indicating the mode of the flash on the receiver’s device, if it has one.

+
+ + + +
@property (nonatomic) AVCaptureFlashMode flashMode
+ + + + + + + + + +
+

Discussion

+

The default value is AVCaptureFlashModeOff (see AVCaptureFlashMode).

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  devicePosition +

+ +
+
+ +
+ + +
+

Constants indicating the physical position of an AVCaptureDevice’s hardware on the system.

+
+ + + +
@property (nonatomic) AVCaptureDevicePosition devicePosition
+ + + + + + + + + +
+

Discussion

+

The default value is AVCaptureDevicePositionBack (see AVCaptureDevicePosition). +If AVCaptureDevicePositionUnspecified is set, then it defaults to AVCaptureDevicePositionBack.

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  accessibilityInstructions +

+ +
+
+ +
+ + +
+

An accessibility hint of the capture preview.

+
+ + + +
@property (nonatomic, copy) NSString *accessibilityInstructions
+ + + + + + + + + +
+

Discussion

+

This property can be used to specify accessible instructions for capturing the video. The +use of this property can assist when the templateImage may not be visible +to the user.

+ +

For example, if you want to capture a video of the user’s right hand, you may use a template +image that displays the outline of the right hand. You may also want to set this property +to a string such as @“Extend your right hand, palm side down, one foot from your device. +Tap the Capture Video button, or two finger tap on the preview, to capture a video of your +extended right hand.”

+
+ + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+ +

  accessibilityHint +

+ +
+
+ +
+ + +
+

An accessibility hint of the capture button.

+
+ + + +
@property (nonatomic, copy) NSString *accessibilityHint
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVideoCaptureStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStepViewController.html new file mode 100755 index 0000000..0587bc3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoCaptureStepViewController.html @@ -0,0 +1,394 @@ + + + + + + ORKVideoCaptureStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVideoCaptureStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKVideoCaptureStepViewController.h
ORKVideoCaptureStepViewController.m
+ + + + +
+ +

Overview

+

The ORKVideoCaptureStepViewController class represents the step view controller that +corresponds to an ORKVideoCaptureStep class.

+ +

It is not usually necessary to instantiate this view controller directly. +Instead, add a video capture step to a task, and present the task in a task +view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep:result: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step result:(ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
step

The step to be presented.

result

The current step result for this step.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– setCancelButtonItem: +

+ +
+
+ +
+ + +
+

The cancel button item.

+
+ + + +
- (void)setCancelButtonItem:(UIBarButtonItem *)cancelButtonItem
+ + + + + + + + + +
+

Discussion

+

The cancel button item controls the Cancel button displayed in the navigation bar +when the step view controller is current. +This property lets you control the appearance and target of the +Cancel button at runtime.

+ +

When the value of the property is nil, the Cancel button is not displayed; otherwise, the title, target, +and action associated with the Cancel button item are used (other properties of UIBarButtonItem +are ignored).

+ +

The cancel button item is updated during view loading and when the value of the step property +is changed, but is safe to +set in the taskViewController:stepViewControllerWillAppear: delegate callback.

+ +

Subclasses can safely modify this property any time after calling viewWillAppear: on super.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStep.html new file mode 100755 index 0000000..712febf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStep.html @@ -0,0 +1,370 @@ + + + + + + ORKVideoInstructionStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVideoInstructionStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKInstructionStep : ORKStep : NSObject
Declared inORKVideoInstructionStep.h
ORKVideoInstructionStep.m
+ + + + +
+ +

Overview

+

An ORKVideoInstructionStep object gives the participant video-based instructions for a task.

+ +

You can use video instruction steps to present video content during a task.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  videoURL +

+ +
+
+ +
+ + +
+

The URL of the video to play (local or remote)

+
+ + + +
@property (nonatomic, copy, nullable) NSURL *videoURL
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVideoInstructionStep.h

+
+ + +
+
+
+ +

  thumbnailTime +

+ +
+
+ +
+ + +
+

The time (in seconds) at which the thumbnail image is created.

+
+ + + +
@property (nonatomic) NSUInteger thumbnailTime
+ + + + + + + + + +
+

Discussion

+

When presented, the step view controller will display a preview image of the video to play. +This property tells the step view controller at what time of the video this thumbnail image +should be created.

+ +

Default is 0, negative values will be ignored.

+
+ + + + + + + +
+

Declared In

+

ORKVideoInstructionStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepResult.html new file mode 100755 index 0000000..5500199 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepResult.html @@ -0,0 +1,228 @@ + + + + + + ORKVideoInstructionStepResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVideoInstructionStepResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKVideoInstructionStepResult.h
ORKVideoInstructionStepResult.m
+ + + + +
+ +

Overview

+

The ORKVideoInstructionStepResult class represents the result of a video insruction step (ORKVideoInstructionStep).

+ +

A video instruction result is produced by the task view controller when it presents a video instruction step.

+
+ + + + + +
+ + + + + + +
+
+ +

  playbackStoppedTime +

+ +
+
+ +
+ + +
+

The time (in seconds) after video playback stopped, or NaN if the video was never played.

+
+ + + +
@property (nonatomic) Float64 playbackStoppedTime
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVideoInstructionStepResult.h

+
+ + +
+
+
+ +

  playbackCompleted +

+ +
+
+ +
+ + +
+

Returns ‘YES’ if the video was watched until the end, or ‘NO’ if video playback was stopped half way.

+
+ + + +
@property (nonatomic) BOOL playbackCompleted
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVideoInstructionStepResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepViewController.html new file mode 100755 index 0000000..9c93c38 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVideoInstructionStepViewController.html @@ -0,0 +1,208 @@ + + + + + + ORKVideoInstructionStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVideoInstructionStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKInstructionStepViewController : ORKStepViewController : UIViewController
Declared inORKVideoInstructionStepViewController.h
ORKVideoInstructionStepViewController.m
+ + + + +
+ +

Overview

+

An ORKVideoInstructionStepViewController object is the view controller for an ORKVideoInstructionStep object.

+ +

In general, you don’t need to instantiate an video instruction step view controller directly. +Instead, add an video instruction step to a task and present the task using a +task view controller. When appropriate, the task view controller instantiates the step +view controller for the step.

+
+ + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStep.html new file mode 100755 index 0000000..6a8ce37 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStep.html @@ -0,0 +1,349 @@ + + + + + + ORKVisualConsentStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVisualConsentStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKVisualConsentStep.h
ORKVisualConsentStep.m
+ + + + +
+ +

Overview

+

The ORKVisualConsentStep class represents a step in the visual consent sequence.

+ +

To use a visual consent step, first create a consent document with at least one +section (at least one section must not be of type ORKConsentSectionTypeOnlyInDocument) and attach the document to a visual consent step. Put the visual consent step +into a ResearchKit task, and present it with a task view controller.

+ +

In the ResearchKit framework, an ORKVisualConsentStep object is used to present a series of simple +graphics to help study participants understand the content of an informed +consent document. The default graphics include animated transitions. +The textual content you need to provide in the consentDocument property should relate to the specific study being run and should be localized.

+ +

An ORKVisualConsentStep object produces an ORKStepResult object, in which the dates indicate the total amount of time participants have spent in the consent process, and the route by which they can exit the consent process.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier:document: +

+ +
+
+ +
+ + +
+

Returns an initialized visual consent step using the specified identifier and consent document.

+
+ + + +
- (instancetype)initWithIdentifier:(NSString *)identifier document:(ORKConsentDocument *)consentDocument
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The identifier of the visual consent step, unique within the document.

consentDocument

The informed consent document.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKVisualConsentStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  consentDocument +

+ +
+
+ +
+ + +
+

The consent document whose sections determine the order and appearance of scenes +in the visual consent step.

+
+ + + +
@property (nonatomic, strong, nullable) ORKConsentDocument *consentDocument
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVisualConsentStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStepViewController.html new file mode 100755 index 0000000..01e6ba6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKVisualConsentStepViewController.html @@ -0,0 +1,188 @@ + + + + + + ORKVisualConsentStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKVisualConsentStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKVisualConsentStepViewController.h
ORKVisualConsentStepViewController.m
+ + + + +
+ +

Overview

+

The ORKVisualConsentStepViewController class is a view controller subclass +used to manage a visual consent step (ORKVisualConsentStep).

+ +

You should not need to instantiate a visual consent step view controller directly. Instead, include +a visual consent step in a task, and present a task view controller for that +task.

+
+ + + + + +
+ + + + + + +
+
+ +

  animationView +

+ +
+
+ +
+ + +
+

The view in which animations are displayed.

+
+ + + +
@property (nonatomic, strong, nullable) UIView *animationView
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKVisualConsentStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStep.html new file mode 100755 index 0000000..e66a894 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStep.html @@ -0,0 +1,330 @@ + + + + + + ORKWaitStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWaitStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKWaitStep.h
ORKWaitStep.m
+ + + + +
+ +

Overview

+

The ORKWaitStep class represents a step that displays a label and an activity +indicator mask.

+ +

This task can be used to indicate to a user that a process is occuring that does + not need their input, and possibly indicate the progress that process has made. + To update the progress on screen, use the methods provided on the + ORKWaitStepViewController this step represents. Once the processing is complete, +goForward must be called on the ORKWaitStepViewController in order for the user to +be able to continue.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  indicatorType +

+ +
+
+ +
+ + +
+

This property specifies the type of progress bar that will be displayed.

+
+ + + +
@property (nonatomic) ORKProgressIndicatorType indicatorType
+ + + + + + + + + +
+

Discussion

+

ORKProgressIndicatorTypeIndeterminate (default) is for indeterminate duration operations +ORKProgressIndicatorTypeProgressBar is for determinate duration operations

+
+ + + + + + + +
+

Declared In

+

ORKWaitStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStepViewController.html new file mode 100755 index 0000000..af2ea98 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWaitStepViewController.html @@ -0,0 +1,259 @@ + + + + + + ORKWaitStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWaitStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStepViewController : UIViewController
Declared inORKWaitStepViewController.h
ORKWaitStepViewController.m
+ + + + +
+ +

Overview

+

The ORKWaitStepViewController class represents the step view controller that corresponds to an ORKWaitStep.

+ +

It is not usually necessary to instantiate this view controller directly. +Instead, add a wait step to a task, and present the task in a task +view controller.

+
+ + + + + +
+ + + + + + +
+
+ +

– setProgress:animated: +

+ +
+
+ +
+ + +
+

Updates the amount of progress displayed in the progress bar if the current indicator mask is set to progress bar.

+
+ + + +
- (void)setProgress:(CGFloat)progress animated:(BOOL)animated
+ + + +
+

Parameters

+ + + + + + + + + + + + +
progress

The fraction of work completed on the range of zero to one.

animated

If true, the update is animated.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKWaitStepViewController.h

+
+ + +
+
+
+ +

– updateText: +

+ +
+
+ +
+ + +
+

Updates the text on the step with the process that is occuring.

+
+ + + +
- (void)updateText:(NSString *)text
+ + + +
+

Parameters

+ + + + + + + +
text

The description of the process that is occuring.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKWaitStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStep.html new file mode 100755 index 0000000..6553269 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStep.html @@ -0,0 +1,381 @@ + + + + + + ORKWalkingTaskStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWalkingTaskStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKWalkingTaskStep.h
ORKWalkingTaskStep.m
+ + + + +
+ +

Overview

+

The ORKWalkingTaskStep class implements a step that’s used in the predefined +walking task.

+ +

You don’t usually need to instantiate a walking step directly; +instead, it is instantiated as part of a predefined task. See the +predefined active tasks defined in ORKOrderedTask.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

  numberOfStepsPerLeg +

+ +
+
+ +
+ + +
+

The number of steps the user should be asked to take in each leg of the +walking task step.

+
+ + + +
@property (nonatomic, assign) NSInteger numberOfStepsPerLeg
+ + + + + + + + + +
+

Discussion

+

The step finishes when the number of steps have been completed, +or after 1.5 * numberOfStepsPerLeg seconds, whichever comes first.

+
+ + + + + + + +
+

Declared In

+

ORKWalkingTaskStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStepViewController.html new file mode 100755 index 0000000..308c8c0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWalkingTaskStepViewController.html @@ -0,0 +1,203 @@ + + + + + + ORKWalkingTaskStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWalkingTaskStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKWalkingTaskStepViewController.h
ORKWalkingTaskStepViewController.m
+ + + + +
+ +

Overview

+

View controller corresponding to the ORKWalkingTaskStep.

+ +

Observes the results of the pedometer, in order to finish early +when the threshold number of steps have been observed.

+
+ + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStep.html new file mode 100755 index 0000000..780f469 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStep.html @@ -0,0 +1,401 @@ + + + + + + ORKWebViewStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWebViewStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKStep : NSObject
Declared inORKWebViewStep.h
ORKWebViewStep.m
+ + + + +
+ +

Overview

+

The ORKWebViewStep class represents a step that displays an embedded webview.

+ +

This may be useful in cases where extreme custom styling is necessary, or an instrument +with specific requirements does not yet have a native implementation.

+ +

In order to proceed to the next step from inside the webviewstep, you must execute this +line of javascript when the user should proceed:

+ +

window.webkit.messageHandlers.ResearchKit.postMessage(answer);

+ +

Where “answer” is the string answer that will be captured in the WebViewStepResult. +A string answer is required or the user will be unable to proceed.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

+ webViewStepWithIdentifier:html: +

+ +
+
+ +
+ + +
+

Returns a new web view step that includes the specified identifier and will display the specified html.

+
+ + + +
+ (instancetype)webViewStepWithIdentifier:(NSString *)identifier html:(NSString *)html
+ + + +
+

Parameters

+ + + + + + + + + + + + +
identifier

The identifier of the step (a step identifier should be unique within the task).

html

The html to be displayed in the webview.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKWebViewStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

  html +

+ +
+
+ +
+ + +
+

Embedded html used for displaying the webview.

+
+ + + +
@property (nonatomic, copy, nullable) NSString *html
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKWebViewStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepResult.html new file mode 100755 index 0000000..2cf158a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepResult.html @@ -0,0 +1,185 @@ + + + + + + ORKWebViewStepResult Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWebViewStepResult Class Reference

+ + +
+ + + + + + + +
Inherits fromORKResult : NSObject
Declared inORKWebViewStepResult.h
ORKWebViewStepResult.m
+ + + + +
+ +

Overview

+

The ORKWebViewStepResult class represents the result of a web view step (ORKWebViewStep).

+ +

A web view result is produced by the task view controller when it presents a web view step.

+
+ + + + + +
+ + + + + + +
+
+ +

  result +

+ +
+
+ +
+ + +
+

The answer produced by the webview.

+
+ + + +
@property (nonatomic, nullable) NSString *result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKWebViewStepResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepViewController.html new file mode 100755 index 0000000..cf77acd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWebViewStepViewController.html @@ -0,0 +1,210 @@ + + + + + + ORKWebViewStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWebViewStepViewController Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromORKStepViewController : UIViewController
Conforms toWKNavigationDelegate
WKScriptMessageHandler
Declared inORKWebViewStepViewController.h
ORKWebViewStepViewController.m
+ + + + +
+ +

Overview

+

The ORKWebViewStepViewController class is a step view controller subclass +used to manage a web view step (ORKWebViewStep).

+ +

You should not need to instantiate a web view step view controller directly. Instead, include +a web view step in a task, and present a task view controller for that task.

+
+ + + + + +
+ + + + + + +
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWeightAnswerFormat.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWeightAnswerFormat.html new file mode 100755 index 0000000..6e2d117 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKWeightAnswerFormat.html @@ -0,0 +1,747 @@ + + + + + + ORKWeightAnswerFormat Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKWeightAnswerFormat Class Reference

+ + +
+ + + + + + + +
Inherits fromORKAnswerFormat : NSObject
Declared inORKAnswerFormat.h
ORKAnswerFormat.m
+ + + + +
+ +

Overview

+

The ORKWeightAnswerFormat class represents the answer format for questions that require users +to enter a weight.

+ +

A weight answer format produces an ORKNumericQuestionResult object. The result is always reported +in the metric system using the kg unit.

+
+ + + + + +
+ + + + +

Other Methods

+ +
+
+ +

– init +

+ +
+
+ +
+ + +
+

Returns an initialized weight answer format using the measurement system specified in the current +locale.

+
+ + + +
- (instancetype)init
+ + + + + +
+

Return Value

+

An initialized weight answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMeasurementSystem: +

+ +
+
+ +
+ + +
+

Returns an initialized weight answer format using the specified measurement system.

+
+ + + +
- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem
+ + + +
+

Parameters

+ + + + + + + +
measurementSystem

The measurement system to use. See ORKMeasurementSystem for the +accepted values.

+
+ + + +
+

Return Value

+

An initialized weight answer format.

+
+ + + + + +
+

Discussion

+

This method is the designated initializer.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMeasurementSystem:numericPrecision: +

+ +
+
+ +
+ + +
+

Returns an initialized weight answer format using the specified measurement system and numeric +precision.

+
+ + + +
- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem numericPrecision:(ORKNumericPrecision)numericPrecision
+ + + +
+

Parameters

+ + + + + + + + + + + + +
measurementSystem

The measurement system to use. See ORKMeasurementSystem for the + accepted values.

numericPrecision

The numeric precision used by the picker. If you pass + ORKNumericPrecisionDefault, the picker will use 0.5 kg + increments for the metric measurement system and whole pound + increments for the USC measurement system, which mimics the + default iOS behavior. If you pass ORKNumericPrecisionLow, the + picker will use 1 kg increments for the metric measurement + system and whole pound increments for the USC measurement + system. If you pass ORKNumericPrecisionHigher, the picker + use 0.01 gr increments for the metric measurement system, + and ounce increments for the USC measurement system.

+
+ + + +
+

Return Value

+

An initialized weight answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

– initWithMeasurementSystem:numericPrecision:minimumValue:maximumValue:defaultValue: +

+ +
+
+ +
+ + +
+

Returns an initialized weight answer format using the specified measurement system, numeric +precision, and default, minimum and maximum values.

+
+ + + +
- (instancetype)initWithMeasurementSystem:(ORKMeasurementSystem)measurementSystem numericPrecision:(ORKNumericPrecision)numericPrecision minimumValue:(double)minimumValue maximumValue:(double)maximumValue defaultValue:(double)defaultValue
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
measurementSystem

The measurement system to use. See ORKMeasurementSystem for the + accepted values.

numericPrecision

The numeric precision used by the picker. If you pass + ORKNumericPrecisionDefault, the picker will use 0.5 kg + increments for the metric measurement system and whole pound + increments for the USC measurement system, which mimics the + default iOS behavior. If you pass ORKNumericPrecisionLow, the + picker will use 1 kg increments for the metric measurement + system and whole pound increments for the USC measurement + system. If you pass ORKNumericPrecisionHigher, the picker + use 0.01 gr increments for the metric measurement system, + and ounce increments for the USC measurement system.

minimumValue

The minimum value that is displayed in the picker. If you specify + ORKDefaultValue, the minimum values are 0 kg when using the + metric measurement system and 0 lbs when using the USC + measurement system.

maximumValue

The maximum value that is displayed in the picker. If you specify + ORKDefaultValue, the maximum values are 657 kg when using the + metric measurement system and 1,450 lbs when using the USC + measurement system.

defaultValue

The default value to be initially selected in the picker. If you + specify ORKDefaultValue, the initally selected values are + 60 kg when using the metric measurement system and 133 lbs when + using the USC measurement system. This value must be between + minimumValue and maximumValue.

+
+ + + +
+

Return Value

+

An initialized weight answer format.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  measurementSystem +

+ +
+
+ +
+ + +
+

Indicates the measurement system used by the answer format.

+
+ + + +
@property (readonly) ORKMeasurementSystem measurementSystem
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  numericPrecision +

+ +
+
+ +
+ + +
+

The numeric precision used by the picker.

+
+ + + +
@property (readonly, getter=isAdditionalPrecision) ORKNumericPrecision numericPrecision
+ + + + + + + + + +
+

Discussion

+

An ORKNumericPrecisionDefault value indicates that the picker will use 0.5 kg increments for the +metric measurement system and whole pound increments for the USC measurement system, which mimics +the default iOS behavior. An ORKNumericPrecisionLow value indicates that the picker will use +1 kg increments for the metric measurement system and whole pound increments for the USC +measurement system. An ORKNumericPrecisionHigher value indicates that the picker will use +0.01 gr increments for the metric measurement system and ounce increments for the USC measurement +system.

+ +

The default value of this property is ORKNumericPrecisionDefault.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  minimumValue +

+ +
+
+ +
+ + +
+

The minimum value that is displayed in the picker.

+
+ + + +
@property (readonly) double minimumValue
+ + + + + + + + + +
+

Discussion

+

When this property has a value equal to ORKDefaultValue, the minimum values are 0 kg when using +the metric measurement system and 0 lbs when using the USC measurement system.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  maximumValue +

+ +
+
+ +
+ + +
+

The maximum value that is displayed in the picker.

+
+ + + +
@property (readonly) double maximumValue
+ + + + + + + + + +
+

Discussion

+

When this property has a value equal to ORKDefaultValue, the maximum values are 657 kg when using +the metric measurement system and 1,450 lbs when using the USC measurement system.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+ +

  defaultValue +

+ +
+
+ +
+ + +
+

The default value to initially selected in the picker.

+
+ + + +
@property (readonly) double defaultValue
+ + + + + + + + + +
+

Discussion

+

When this property has a value equal to ORKDefaultValue, the initally selected values are 60 kg +when using the metric measurement system and 133 lbs when using the USC measurement system. This +value must be between minimumValue and maximumValue.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ + + +

Other Methods

+ +
+
+ +

– questionType +

+ +
+
+ +
+ + +
+

The type of question. (read-only)

+
+ + + +
- (ORKQuestionType)questionType
+ + + + + + + + + +
+

Discussion

+

You can use this enumerated value in your Objective-C code to switch on +a rough approximation of the type of question that is being asked.

+ +

Note that answer format subclasses override the getter to return the appropriate question +type.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryAudioGenerator.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryAudioGenerator.html new file mode 100755 index 0000000..e9f03c5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryAudioGenerator.html @@ -0,0 +1,173 @@ + + + + + + ORKdBHLToneAudiometryAudioGenerator Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKdBHLToneAudiometryAudioGenerator Class Reference

+ + +
+ + + + + + + +
Inherits fromNSObject
Declared inORKdBHLToneAudiometryAudioGenerator.h
ORKdBHLToneAudiometryAudioGenerator.m
+ + + + + + +
+ + + + + + +
+
+ +

– stop +

+ +
+
+ +
+ + +
+

Stops the audio being played.

+
+ + + +
- (void)stop
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKdBHLToneAudiometryAudioGenerator.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStep.html new file mode 100755 index 0000000..19757db --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStep.html @@ -0,0 +1,169 @@ + + + + + + ORKdBHLToneAudiometryOnboardingStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKdBHLToneAudiometryOnboardingStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStep : ORKStep : NSObject
Declared inORKdBHLToneAudiometryOnboardingStep.h
ORKdBHLToneAudiometryOnboardingStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStepViewController.html new file mode 100755 index 0000000..97f5ca6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryOnboardingStepViewController.html @@ -0,0 +1,179 @@ + + + + + + ORKdBHLToneAudiometryOnboardingStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKdBHLToneAudiometryOnboardingStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKFormStepViewController : ORKStepViewController : UIViewController
Declared inORKdBHLToneAudiometryOnboardingStepViewController.h
ORKdBHLToneAudiometryOnboardingStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– goForward +

+ +
+
+ +
+ + +
+

Navigates forward to the next step.

+
+ + + +
- (void)goForward
+ + + + + + + + + +
+

Discussion

+

When a user taps a Next button, the information passes through this method. You can use this method as an override +point or a target action for a subclass.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStep.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStep.html new file mode 100755 index 0000000..e5bdaff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStep.html @@ -0,0 +1,304 @@ + + + + + + ORKdBHLToneAudiometryStep Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKdBHLToneAudiometryStep Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStep : ORKStep : NSObject
Declared inORKdBHLToneAudiometryStep.h
ORKdBHLToneAudiometryStep.m
+ + + + + + +
+ + + + + + +
+
+ +

+ stepViewControllerClass +

+ +
+
+ +
+ + + + +
+ (Class)stepViewControllerClass
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithIdentifier: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithIdentifier:(NSString *)identifier
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Checks the parameters of the step and throws exceptions on invalid parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

This method is called when there is a need to validate the step’s parameters, which is typically +the case when adding a step to an ORKStepViewController object, and when presenting the +step view controller.

+ +

Subclasses should override this method to provide validation of their additional +properties, and must call super.

+
+ + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+ +

– initWithCoder: +

+ +
+
+ +
+ + + + +
- (instancetype)initWithCoder:(NSCoder *)aDecoder
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStepViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStepViewController.html new file mode 100755 index 0000000..23da587 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/ORKdBHLToneAudiometryStepViewController.html @@ -0,0 +1,361 @@ + + + + + + ORKdBHLToneAudiometryStepViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKdBHLToneAudiometryStepViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKActiveStepViewController : ORKStepViewController : UIViewController
Declared inORKdBHLToneAudiometryStepViewController.h
ORKdBHLToneAudiometryStepViewController.m
+ + + + + + +
+ + + + + + +
+
+ +

– initWithStep: +

+ +
+
+ +
+ + +
+

Returns a new step view controller for the specified step.

+
+ + + +
- (instancetype)initWithStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + +
step

The step to be presented.

+
+ + + +
+

Return Value

+

A newly initialized step view controller.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– result +

+ +
+
+ +
+ + +
+

The current state of the result. (read-only)

+
+ + + +
- (ORKStepResult *)result
+ + + + + + + + + +
+

Discussion

+

The task view controller uses this property to get the results for the +step, and to collate them into the task result.

+ +

The current step result and any subsidiary results representing data collected +so far are available in this property. You can detect significant changes to the result, +such as when the user enters a new answer, using the +stepViewControllerResultDidChange: delegate callback.

+ +

Subclasses must use this property to return the current results. +Subclasses may call super to obtain +a clean, empty result object appropriate for the step, to which they can +attach appropriate child results.

+ +

The implementations of this method in the ResearchKit framework currently create a new +result object on every call, so do not call this method unless it is +actually necessary.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepDidFinish +

+ +
+
+ +
+ + +
+

Tells the view controller that the active step has finished.

+
+ + + +
- (void)stepDidFinish
+ + + + + + + + + +
+

Discussion

+

This method is an override point for subclasses, called by the base class when +the step has just finished.

+ +

The default implementation does nothing except in the case of steps that have countdown +enabled. When countdown is enabled in a step, the view controller attempts to navigate automatically to the next step, if so configured.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+ +

– start +

+ +
+
+ +
+ + +
+

Starts the active step.

+
+ + + +
- (void)start
+ + + + + + + + + +
+

Discussion

+

Call this method to start the timer on the active step, if there is one, and +to start any data recording.

+ +

When you start the step, recorders are instantiated based on their configurations and then started. All +timers should start, and the UI should show users that the step is in progress.

+ +

This method does nothing if the step has already started.

+ +

Subclasses should super when overriding this method.

+
+ + + + + + + +
+

Declared In

+

ORKActiveStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/TestTaskViewControllerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/TestTaskViewControllerDelegate.html new file mode 100755 index 0000000..dcfd4f8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/TestTaskViewControllerDelegate.html @@ -0,0 +1,280 @@ + + + + + + TestTaskViewControllerDelegate Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

TestTaskViewControllerDelegate Class Reference

+ + +
+ + + + + + + + + + +
Inherits fromNSObject
Conforms toORKTaskViewControllerDelegate
Declared inORKTaskTests.m
+ + + + + + +
+ + + + + + +
+
+ +

– taskViewController:didFinishWithReason:error: +

+ +
+
+ +
+ + +
+

Tells the delegate that the task has finished.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskViewController

The ORKTaskViewControllerinstance that is returning the result.

reason

An ORKTaskViewControllerFinishReason value indicating how the user chose to complete the task.

error

If failure occurred, an NSError object indicating the reason for the failure. The value of this parameter is nil if result does not indicate failure.

+
+ + + + + + + +
+

Discussion

+

The task view controller calls this method when an unrecoverable error occurs, +when the user has canceled the task (with or without saving), or when the user +completes the last step in the task.

+ +

In most circumstances, the receiver should dismiss the task view controller +in response to this method, and may also need to collect and process the results +of the task.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:stepViewControllerWillDisappear:navigationDirection: +

+ +
+
+ +
+ + +
+

Tells the delegate that a step will disappear.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillDisappear:(ORKStepViewController *)stepViewController navigationDirection:(ORKStepViewControllerNavigationDirection)direction
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

stepViewController

The ORKStepViewController that has just finished.

direction

The ORKStepViewControllerNavigationDirection of navigation.

+
+ + + + + + + +
+

Discussion

+

This is called in the ORKStepViewControllerDelegate method for stepViewController:didFinishWithNavigationDirection: +after saving the result of the step to the task view controller and before navigating to the next/previous step.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/VerificationViewController.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/VerificationViewController.html new file mode 100755 index 0000000..d4ef642 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Classes/VerificationViewController.html @@ -0,0 +1,190 @@ + + + + + + VerificationViewController Class Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

VerificationViewController Class Reference

+ + +
+ + + + + + + +
Inherits fromORKVerificationStepViewController : ORKStepViewController : UIViewController
Declared inTaskFactory+Onboarding.m
+ + + + +
+ +

Overview

+

A subclass is required for the verification step.

+ +

The implementation below demonstrates how to subclass and override button actions.

+
+ + + + + +
+ + + + + + +
+
+ +

– resendEmailButtonTapped +

+ +
+
+ +
+ + +
+

Action method for the resend email button.

+
+ + + +
- (void)resendEmailButtonTapped
+ + + + + + + + + +
+

Discussion

+

Override this method to provide custom logic for the button action.

+
+ + + + + + + +
+

Declared In

+

ORKVerificationStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAmslerGridEyeSide.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAmslerGridEyeSide.html new file mode 100755 index 0000000..c65fcba --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAmslerGridEyeSide.html @@ -0,0 +1,197 @@ + + + + + + ORKAmslerGridEyeSide Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAmslerGridEyeSide Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKAmslerGridEyeSide

+ + +
+

Eye side for amsler grid

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKAmslerGridEyeSide ) {
+ +    ORKAmslerGridEyeSideNotSpecified = 0,
+ +    ORKAmslerGridEyeSideLeft,
+ +    ORKAmslerGridEyeSideRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKAmslerGridEyeSideNotSpecified
+
+ + +
 Not Specified
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKAmslerGridEyeSideLeft
+
+ + +
 Left Eye
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKAmslerGridEyeSideRight
+
+ + +
 Right Eye
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAudioChannel.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAudioChannel.html new file mode 100755 index 0000000..2b5433d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKAudioChannel.html @@ -0,0 +1,175 @@ + + + + + + ORKAudioChannel Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAudioChannel Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKAudioChannel

+ + +
+

Audio channel constants.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKAudioChannel ) {
+ +    ORKAudioChannelLeft,
+ +    ORKAudioChannelRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKAudioChannelLeft
+
+ + +

The left audio channel.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKAudioChannelRight
+
+ + +

The right audio channel.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKBodySagittal.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKBodySagittal.html new file mode 100755 index 0000000..f9295cd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKBodySagittal.html @@ -0,0 +1,175 @@ + + + + + + ORKBodySagittal Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKBodySagittal Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKBodySagittal

+ + +
+

Body side constants.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKBodySagittal ) {
+ +    ORKBodySagittalLeft,
+ +    ORKBodySagittalRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKBodySagittalLeft
+
+ + +

The left side.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKBodySagittalRight
+
+ + +

The right side.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKChoiceAnswerStyle.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKChoiceAnswerStyle.html new file mode 100755 index 0000000..096c633 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKChoiceAnswerStyle.html @@ -0,0 +1,177 @@ + + + + + + ORKChoiceAnswerStyle Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKChoiceAnswerStyle Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKChoiceAnswerStyle

+ + +
+

An enumeration of the types of answer choices available.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKChoiceAnswerStyle ) {
+ +    ORKChoiceAnswerStyleSingleChoice,
+ +    ORKChoiceAnswerStyleMultipleChoice,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKChoiceAnswerStyleSingleChoice
+
+ + +
 A single choice question lets the participant pick a single predefined answer option.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKChoiceAnswerStyleMultipleChoice
+
+ + +
 A multiple choice question lets the participant pick one or more predefined answer options.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentReviewPhase.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentReviewPhase.html new file mode 100755 index 0000000..772f79c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentReviewPhase.html @@ -0,0 +1,156 @@ + + + + + + ORKConsentReviewPhase Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentReviewPhase Constants Reference

+ + +
+ + + + +
Declared inORKConsentReviewStepViewController.m
+ + + + + + + +

ORKConsentReviewPhase

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKConsentReviewPhase ) {
+ +    ORKConsentReviewPhaseName,
+ +    ORKConsentReviewPhaseReviewDocument,
+ +    ORKConsentReviewPhaseSignature,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKConsentReviewPhaseName
+
+ + +

+ Declared In ORKConsentReviewStepViewController.m. +

+ +
+ +
ORKConsentReviewPhaseReviewDocument
+
+ + +

+ Declared In ORKConsentReviewStepViewController.m. +

+ +
+ +
ORKConsentReviewPhaseSignature
+
+ + +

+ Declared In ORKConsentReviewStepViewController.m. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentSectionType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentSectionType.html new file mode 100755 index 0000000..de4a599 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKConsentSectionType.html @@ -0,0 +1,379 @@ + + + + + + ORKConsentSectionType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKConsentSectionType Constants Reference

+ + +
+ + + + +
Declared inORKConsentSection.h
+ + + + + + + +

ORKConsentSectionType

+ + +
+

ORKConsentSectionType enumerates the predefined visual consent sections +available in the ResearchKit framework.

+ +

Although the visuals are predefined, and default localized titles and Learn +More button titles are provided, you need to provide in ORKConsentSection the summary strapline on each visual consent +page and the actual Learn More content, because these items are specific to each individual +study.

+ +

Not every section is applicable to every study, and most studies +are likely to require additional sections.

+
+ + + + +
+

Constants

+
+ +
ORKConsentSectionTypeOverview
+
+ + +
 Overview of the informed consent process.
+
+ This content can inform the user of what to expect during the process,
+ and provide general background information on the purpose of the study.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeDataGathering
+
+ + +
 A section informing the user that sensor data will be collected.
+
+ This content can identify which sensors will be used, for how long,
+ and for what purpose.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypePrivacy
+
+ + +
 A section describing the privacy policies for the study.
+
+ This content can describe how data is protected, the processes used
+ to sanitize the collected data or make it anonymous, and address the risks
+ involved.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeDataUse
+
+ + +
 A section describing how the collected data will be used.
+
+ This content can include details about those who will have access to the data, the types of
+ analysis that will be performed, and the degree of control the participant
+ may have over the data after it is collected.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeTimeCommitment
+
+ + +
A section describing how much time is required for the study.
+
+ This content can help users understand what to expect as they participate in the study.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeStudySurvey
+
+ + +
 A section describing survey use in the study.
+
+ This content can explain how survey data will be collected, for what purpose,
+ and make it clear to what extent participation is optional.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeStudyTasks
+
+ + +
 A section describing active task use in the study.
+
+ This content can describe what types of tasks need to be performed, how
+ often, and for what purpose. Any risks that are involved can
+ also be communicated in this section.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeWithdrawing
+
+ + +
 A section describing how to withdraw from the study.
+
+ This section can describe the policies
+ that govern the collected data if the user decides to withdraw.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeCustom
+
+ + +
 A custom section.
+
+ Custom sections don't have a predefined title, summary, content, image,
+ or animation. A consent document may have as many or as few custom sections
+ as needed.
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
ORKConsentSectionTypeOnlyInDocument
+
+ + +
 Document-only sections.
+
+ Document-only sections are ignored for a visual consent step and are only
+ displayed in a consent review step (assuming no value is provided for the  `htmlReviewContent` property).
+
+ + + + + + +

+ Declared In ORKConsentSection.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKConsentSection.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKDateAnswerStyle.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKDateAnswerStyle.html new file mode 100755 index 0000000..033c719 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKDateAnswerStyle.html @@ -0,0 +1,178 @@ + + + + + + ORKDateAnswerStyle Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDateAnswerStyle Constants Reference

+ + +
+ + + + +
Declared inORKAnswerFormat.h
+ + + + + + + +

ORKDateAnswerStyle

+ + +
+

The style of date picker to use in an ORKDateAnswerFormat object.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKDateAnswerStyle ) {
+ +    ORKDateAnswerStyleDateAndTime,
+ +    ORKDateAnswerStyleDate,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKDateAnswerStyleDateAndTime
+
+ + +
 The date and time question type asks participants to choose a time or a combination of date
+ and time, from a picker.
+
+ + + + + + +

+ Declared In ORKAnswerFormat.h. +

+ +
+ +
ORKDateAnswerStyleDate
+
+ + +
 The date question type asks participants to choose a particular date from a picker.
+
+ + + + + + +

+ Declared In ORKAnswerFormat.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKErrorCode.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKErrorCode.html new file mode 100755 index 0000000..44c0a84 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKErrorCode.html @@ -0,0 +1,213 @@ + + + + + + ORKErrorCode Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKErrorCode Constants Reference

+ + +
+ + + + +
Declared inORKErrors.h
+ + + + + + + +

ORKErrorCode

+ + +
+

ORKErrorCode codes are used for errors in the domain ORKErrorDomain.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKErrorCode ) {
+ +    ORKErrorObjectNotFound = 1,
+ +    ORKErrorInvalidObject,
+ +    ORKErrorException,
+ +    ORKErrorMultipleErrors,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKErrorObjectNotFound
+
+ + +

No matching object was found.

+ + + + + + +

+ Declared In ORKErrors.h. +

+ +
+ +
ORKErrorInvalidObject
+
+ + +

An object was invalid and processing could not continue.

+ + + + + + +

+ Declared In ORKErrors.h. +

+ +
+ +
ORKErrorException
+
+ + +

An exception was caught during an operation.

+ + + + + + +

+ Declared In ORKErrors.h. +

+ +
+ +
ORKErrorMultipleErrors
+
+ + +

Multiple errors were encountered during an operation.

+ + + + + + +

+ Declared In ORKErrors.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKErrors.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKFileProtectionMode.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKFileProtectionMode.html new file mode 100755 index 0000000..b30c21e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKFileProtectionMode.html @@ -0,0 +1,218 @@ + + + + + + ORKFileProtectionMode Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKFileProtectionMode Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKFileProtectionMode

+ + +
+

File protection mode constants.

+ +

The file protection mode constants correspond directly to NSFileProtection constants, but are +more convenient to manipulate than strings. Complete file protection is +highly recommended for files containing personal data that will be kept +persistently.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKFileProtectionMode ) {
+ +    ORKFileProtectionNone = 0,
+ +    ORKFileProtectionCompleteUntilFirstUserAuthentication,
+ +    ORKFileProtectionCompleteUnlessOpen,
+ +    ORKFileProtectionComplete,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKFileProtectionNone
+
+ + +

No file protection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKFileProtectionCompleteUntilFirstUserAuthentication
+
+ + +

Complete file protection until first user authentication.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKFileProtectionCompleteUnlessOpen
+
+ + +

Complete file protection unless there was an open file handle before lock.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKFileProtectionComplete
+
+ + +

Complete file protection while the device is locked.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKGraphAnimationType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKGraphAnimationType.html new file mode 100755 index 0000000..f431f8c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKGraphAnimationType.html @@ -0,0 +1,168 @@ + + + + + + ORKGraphAnimationType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKGraphAnimationType Constants Reference

+ + +
+ + + + +
Declared inORKGraphChartView_Internal.h
+ + + + + + + +

ORKGraphAnimationType

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, ORKGraphAnimationType ) {
+ +    ORkGraphAnimationTypeNone,
+ +    ORKGraphAnimationTypeFade,
+ +    ORKGraphAnimationTypeGrow,
+ +    ORKGraphAnimationTypePop,
+ + };
+ +
+ +
+

Constants

+
+ +
ORkGraphAnimationTypeNone
+
+ + +

+ Declared In ORKGraphChartView_Internal.h. +

+ +
+ +
ORKGraphAnimationTypeFade
+
+ + +

+ Declared In ORKGraphChartView_Internal.h. +

+ +
+ +
ORKGraphAnimationTypeGrow
+
+ + +

+ Declared In ORKGraphChartView_Internal.h. +

+ +
+ +
ORKGraphAnimationTypePop
+
+ + +

+ Declared In ORKGraphChartView_Internal.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKMeasurementSystem.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKMeasurementSystem.html new file mode 100755 index 0000000..a99d172 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKMeasurementSystem.html @@ -0,0 +1,196 @@ + + + + + + ORKMeasurementSystem Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKMeasurementSystem Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKMeasurementSystem

+ + +
+

Measurement system.

+ +

Used by ORKHeightAnswerFormat and ORKWeightAnswerFormat.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKMeasurementSystem ) {
+ +    ORKMeasurementSystemLocal = 0,
+ +    ORKMeasurementSystemMetric,
+ +    ORKMeasurementSystemUSC,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKMeasurementSystemLocal
+
+ + +

Measurement system in use by the current locale.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKMeasurementSystemMetric
+
+ + +

Metric measurement system.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKMeasurementSystemUSC
+
+ + +

United States customary system.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNavigationContainerButtonStyle.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNavigationContainerButtonStyle.html new file mode 100755 index 0000000..7d4ec42 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNavigationContainerButtonStyle.html @@ -0,0 +1,197 @@ + + + + + + ORKNavigationContainerButtonStyle Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNavigationContainerButtonStyle Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKNavigationContainerButtonStyle

+ + +
+

An enumeration of the types of button styles for Navigation Containers.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKNavigationContainerButtonStyle ) {
+ +    ORKNavigationContainerButtonStyleTextStandard = 0,
+ +    ORKNavigationContainerButtonStyleTextBold,
+ +    ORKNavigationContainerButtonStyleRoundedRect,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKNavigationContainerButtonStyleTextStandard
+
+ + +
 A standard ORKText button.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKNavigationContainerButtonStyleTextBold
+
+ + +
 A text button with Bold title.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKNavigationContainerButtonStyleRoundedRect
+
+ + +
 A rounded rect button.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumberFormattingStyle.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumberFormattingStyle.html new file mode 100755 index 0000000..9eba14a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumberFormattingStyle.html @@ -0,0 +1,177 @@ + + + + + + ORKNumberFormattingStyle Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNumberFormattingStyle Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKNumberFormattingStyle

+ + +
+

An enumeration of the format styles available for scale answers.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKNumberFormattingStyle ) {
+ +    ORKNumberFormattingStyleDefault,
+ +    ORKNumberFormattingStylePercent,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKNumberFormattingStyleDefault
+
+ + +
 The default decimal style.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKNumberFormattingStylePercent
+
+ + +
 Percent style.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericAnswerStyle.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericAnswerStyle.html new file mode 100755 index 0000000..e32fcd4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericAnswerStyle.html @@ -0,0 +1,178 @@ + + + + + + ORKNumericAnswerStyle Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNumericAnswerStyle Constants Reference

+ + +
+ + + + +
Declared inORKAnswerFormat.h
+ + + + + + + +

ORKNumericAnswerStyle

+ + +
+

The style of answer for an ORKNumericAnswerFormat object, which controls the keyboard that is +presented during numeric entry.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKNumericAnswerStyle ) {
+ +    ORKNumericAnswerStyleDecimal,
+ +    ORKNumericAnswerStyleInteger,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKNumericAnswerStyleDecimal
+
+ + +
 A decimal question type asks the participant to enter a decimal number.
+
+ + + + + + +

+ Declared In ORKAnswerFormat.h. +

+ +
+ +
ORKNumericAnswerStyleInteger
+
+ + +
 An integer question type asks the participant to enter an integer number.
+
+ + + + + + +

+ Declared In ORKAnswerFormat.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKAnswerFormat.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericPrecision.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericPrecision.html new file mode 100755 index 0000000..6d8e196 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKNumericPrecision.html @@ -0,0 +1,196 @@ + + + + + + ORKNumericPrecision Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKNumericPrecision Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKNumericPrecision

+ + +
+

Numeric precision.

+ +

Used by ORKWeightAnswerFormat.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKNumericPrecision ) {
+ +    ORKNumericPrecisionDefault = 0,
+ +    ORKNumericPrecisionLow,
+ +    ORKNumericPrecisionHigh,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKNumericPrecisionDefault
+
+ + +

Default numeric precision.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKNumericPrecisionLow
+
+ + +

Low numeric precision.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKNumericPrecisionHigh
+
+ + +

High numeric preicision.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKOperationState.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKOperationState.html new file mode 100755 index 0000000..952ea4d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKOperationState.html @@ -0,0 +1,156 @@ + + + + + + ORKOperationState Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKOperationState Constants Reference

+ + +
+ + + + +
Declared inORKOperation.h
+ + + + + + + +

ORKOperationState

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKOperationState ) {
+ +    ORKOperationReady,
+ +    ORKOperationExecuting,
+ +    ORKOperationFinished,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKOperationReady
+
+ + +

+ Declared In ORKOperation.h. +

+ +
+ +
ORKOperationExecuting
+
+ + +

+ Declared In ORKOperation.h. +

+ +
+ +
ORKOperationFinished
+
+ + +

+ Declared In ORKOperation.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPDFViewerActionBarOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPDFViewerActionBarOption.html new file mode 100755 index 0000000..c7b25fe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPDFViewerActionBarOption.html @@ -0,0 +1,213 @@ + + + + + + ORKPDFViewerActionBarOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPDFViewerActionBarOption Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPDFViewerActionBarOption

+ + +
+

Enums to exclude options from ORKPDFViewerStep.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKPDFViewerActionBarOption ) {
+ +    ORKPDFViewerActionBarOptionExcludeThumbnail = 1 < < 0,
+ +    ORKPDFViewerActionBarOptionExcludeAnnotation = 1 < < 1,
+ +    ORKPDFViewerActionBarOptionExcludeSearch = 1 < < 2,
+ +    ORKPDFViewerActionBarOptionExcludeShare = 1 < < 3,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPDFViewerActionBarOptionExcludeThumbnail
+
+ + +

Enums to exclude options from ORKPDFViewerStep.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPDFViewerActionBarOptionExcludeAnnotation
+
+ + +

Enums to exclude options from ORKPDFViewerStep.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPDFViewerActionBarOptionExcludeSearch
+
+ + +

Enums to exclude options from ORKPDFViewerStep.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPDFViewerActionBarOptionExcludeShare
+
+ + +

Enums to exclude options from ORKPDFViewerStep.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPSATPresentationMode.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPSATPresentationMode.html new file mode 100755 index 0000000..17852bf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPSATPresentationMode.html @@ -0,0 +1,175 @@ + + + + + + ORKPSATPresentationMode Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPSATPresentationMode Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPSATPresentationMode

+ + +
+

Values that identify the presentation mode of paced serial addition tests that are auditory and/or visual (PSAT).

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSInteger, ORKPSATPresentationMode ) {
+ +    ORKPSATPresentationModeAuditory = 1 < < 0,
+ +    ORKPSATPresentationModeVisual = 1 < < 1,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPSATPresentationModeAuditory
+
+ + +

The PASAT (Paced Auditory Serial Addition Test).

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPSATPresentationModeVisual
+
+ + +

The PVSAT (Paced Visual Serial Addition Test).

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPageNavigationDirection.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPageNavigationDirection.html new file mode 100755 index 0000000..730dae4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPageNavigationDirection.html @@ -0,0 +1,156 @@ + + + + + + ORKPageNavigationDirection Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPageNavigationDirection Constants Reference

+ + +
+ + + + +
Declared inORKPageStepViewController.m
+ + + + + + + +

ORKPageNavigationDirection

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKPageNavigationDirection ) {
+ +    ORKPageNavigationDirectionNone = 0,
+ +    ORKPageNavigationDirectionForward = 1,
+ +    ORKPageNavigationDirectionReverse = -1,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPageNavigationDirectionNone
+
+ + +

+ Declared In ORKPageStepViewController.m. +

+ +
+ +
ORKPageNavigationDirectionForward
+
+ + +

+ Declared In ORKPageStepViewController.m. +

+ +
+ +
ORKPageNavigationDirectionReverse
+
+ + +

+ Declared In ORKPageStepViewController.m. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeFlow.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeFlow.html new file mode 100755 index 0000000..5b083c1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeFlow.html @@ -0,0 +1,198 @@ + + + + + + ORKPasscodeFlow Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeFlow Constants Reference

+ + +
+ + + + +
Declared inORKPasscodeStep.h
+ + + + + + + +

ORKPasscodeFlow

+ + +
+

An enumeration of values used in ORKPasscodeStepViewController to indicate the type of flow used +by the view controller.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, ORKPasscodeFlow ) {
+ +    ORKPasscodeFlowCreate,
+ +    ORKPasscodeFlowAuthenticate,
+ +    ORKPasscodeFlowEdit,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPasscodeFlowCreate
+
+ + +

An enumeration of values used in ORKPasscodeStepViewController to indicate the type of flow used +by the view controller.

+ + + + + + +

+ Declared In ORKPasscodeStep.h. +

+ +
+ +
ORKPasscodeFlowAuthenticate
+
+ + +

An enumeration of values used in ORKPasscodeStepViewController to indicate the type of flow used +by the view controller.

+ + + + + + +

+ Declared In ORKPasscodeStep.h. +

+ +
+ +
ORKPasscodeFlowEdit
+
+ + +

An enumeration of values used in ORKPasscodeStepViewController to indicate the type of flow used +by the view controller.

+ + + + + + +

+ Declared In ORKPasscodeStep.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKPasscodeStep.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeState.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeState.html new file mode 100755 index 0000000..5373847 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeState.html @@ -0,0 +1,192 @@ + + + + + + ORKPasscodeState Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeState Constants Reference

+ + +
+ + + + +
Declared inORKPasscodeStepViewController_Internal.h
+ + + + + + + +

ORKPasscodeState

+ +
+ + +

Definition

+ typedef NS_ENUM(NSUInteger, ORKPasscodeState ) {
+ +    ORKPasscodeStateEntry,
+ +    ORKPasscodeStateConfirm,
+ +    ORKPasscodeStateSaved,
+ +    ORKPasscodeStateOldEntry,
+ +    ORKPasscodeStateNewEntry,
+ +    ORKPasscodeStateConfirmNewEntry,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPasscodeStateEntry
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
ORKPasscodeStateConfirm
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
ORKPasscodeStateSaved
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
ORKPasscodeStateOldEntry
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
ORKPasscodeStateNewEntry
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
ORKPasscodeStateConfirmNewEntry
+
+ + +

+ Declared In ORKPasscodeStepViewController_Internal.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeType.html new file mode 100755 index 0000000..962ba83 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPasscodeType.html @@ -0,0 +1,175 @@ + + + + + + ORKPasscodeType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeType Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPasscodeType

+ + +
+

Identify the type of passcode authentication for ORKPasscodeStepViewController.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKPasscodeType ) {
+ +    ORKPasscodeType4Digit,
+ +    ORKPasscodeType6Digit,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPasscodeType4Digit
+
+ + +

4 digit pin entry

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPasscodeType6Digit
+
+ + +

6 digit pin entry

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPermissionMask.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPermissionMask.html new file mode 100755 index 0000000..10da42d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPermissionMask.html @@ -0,0 +1,252 @@ + + + + + + ORKPermissionMask Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPermissionMask Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPermissionMask

+ + +
+

You can use a permission mask to specify a set of permissions to acquire or +that have been acquired for a task or step.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSInteger, ORKPermissionMask ) {
+ +    ORKPermissionNone = 0,
+ +    ORKPermissionCoreMotionActivity = ( 1 < < 1 ),
+ +    ORKPermissionCoreMotionAccelerometer = ( 1 < < 2 ),
+ +    ORKPermissionAudioRecording = ( 1 < < 3 ),
+ +    ORKPermissionCoreLocation = ( 1 < < 4 ),
+ +    ORKPermissionCamera = ( 1 < < 5 ),
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPermissionNone
+
+ + +

No permissions.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPermissionCoreMotionActivity
+
+ + +

Access to CoreMotion activity is required.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPermissionCoreMotionAccelerometer
+
+ + +

Access to CoreMotion accelerometer data.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPermissionAudioRecording
+
+ + +

Access for audio recording.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPermissionCoreLocation
+
+ + +

Access to location.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPermissionCamera
+
+ + +

Access to camera.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskHandOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskHandOption.html new file mode 100755 index 0000000..c17918a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskHandOption.html @@ -0,0 +1,215 @@ + + + + + + ORKPredefinedTaskHandOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPredefinedTaskHandOption Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPredefinedTaskHandOption

+ + +
+

Values that identify the hand(s) to be used in an active task.

+ +

By default, the participant will be asked to use their most affected hand.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskHandOption ) {
+ +    ORKPredefinedTaskHandOptionUnspecified = 0,
+ +    ORKPredefinedTaskHandOptionLeft = 1 < < 1,
+ +    ORKPredefinedTaskHandOptionRight = 1 < < 2,
+ +    ORKPredefinedTaskHandOptionBoth = ORKPredefinedTaskHandOptionLeft | ORKPredefinedTaskHandOptionRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPredefinedTaskHandOptionUnspecified
+
+ + +

Which hand to use is undefined

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskHandOptionLeft
+
+ + +

Task should test the left hand

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskHandOptionRight
+
+ + +

Task should test the right hand

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskHandOptionBoth
+
+ + +

Task should test both hands (random order)

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskLimbOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskLimbOption.html new file mode 100755 index 0000000..db22eec --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskLimbOption.html @@ -0,0 +1,213 @@ + + + + + + ORKPredefinedTaskLimbOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPredefinedTaskLimbOption Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPredefinedTaskLimbOption

+ + +
+

Values that identify the left or right limb to be used in an active task.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskLimbOption ) {
+ +    ORKPredefinedTaskLimbOptionUnspecified = 0,
+ +    ORKPredefinedTaskLimbOptionLeft = 1 < < 1,
+ +    ORKPredefinedTaskLimbOptionRight = 1 < < 2,
+ +    ORKPredefinedTaskLimbOptionBoth = ORKPredefinedTaskLimbOptionLeft | ORKPredefinedTaskLimbOptionRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPredefinedTaskLimbOptionUnspecified
+
+ + +

Which limb to use is undefined

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskLimbOptionLeft
+
+ + +

Task should test the left limb

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskLimbOptionRight
+
+ + +

Task should test the right limb

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskLimbOptionBoth
+
+ + +

Task should test the both limbs (random order)

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskOption.html new file mode 100755 index 0000000..72a7a05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKPredefinedTaskOption.html @@ -0,0 +1,314 @@ + + + + + + ORKPredefinedTaskOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPredefinedTaskOption Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKPredefinedTaskOption

+ + +
+

The ORKPredefinedTaskOption flags let you exclude particular behaviors from the predefined active +tasks in the predefined category of ORKOrderedTask.

+ +

By default, all predefined tasks include instructions and conclusion steps, and may also include +one or more data collection recorder configurations. Although not all predefined tasks include all +of these data collection types, the predefined task option flags can be used to explicitly specify +that a task option not be included.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKPredefinedTaskOption ) {
+ +    ORKPredefinedTaskOptionNone = 0,
+ +    ORKPredefinedTaskOptionExcludeInstructions = ( 1 < < 0 ),
+ +    ORKPredefinedTaskOptionExcludeConclusion = ( 1 < < 1 ),
+ +    ORKPredefinedTaskOptionExcludeAccelerometer = ( 1 < < 2 ),
+ +    ORKPredefinedTaskOptionExcludeDeviceMotion = ( 1 < < 3 ),
+ +    ORKPredefinedTaskOptionExcludePedometer = ( 1 < < 4 ),
+ +    ORKPredefinedTaskOptionExcludeLocation = ( 1 < < 5 ),
+ +    ORKPredefinedTaskOptionExcludeHeartRate = ( 1 < < 6 ),
+ +    ORKPredefinedTaskOptionExcludeAudio = ( 1 < < 7 ),
+ + };
+ +
+ +
+

Constants

+
+ +
ORKPredefinedTaskOptionNone
+
+ + +

Default behavior.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeInstructions
+
+ + +

Exclude the initial instruction steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeConclusion
+
+ + +

Exclude the conclusion step.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeAccelerometer
+
+ + +

Exclude accelerometer data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeDeviceMotion
+
+ + +

Exclude device motion data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludePedometer
+
+ + +

Exclude pedometer data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeLocation
+
+ + +

Exclude location data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeHeartRate
+
+ + +

Exclude heart rate data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKPredefinedTaskOptionExcludeAudio
+
+ + +

Exclude audio data collection.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKProgressIndicatorType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKProgressIndicatorType.html new file mode 100755 index 0000000..f611d8b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKProgressIndicatorType.html @@ -0,0 +1,175 @@ + + + + + + ORKProgressIndicatorType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKProgressIndicatorType Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKProgressIndicatorType

+ + +
+

Progress indicator type for ORKWaitStep.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKProgressIndicatorType ) {
+ +    ORKProgressIndicatorTypeIndeterminate = 0,
+ +    ORKProgressIndicatorTypeProgressBar,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKProgressIndicatorTypeIndeterminate
+
+ + +

Spinner animation.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKProgressIndicatorTypeProgressBar
+
+ + +

Progressbar animation.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionSection.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionSection.html new file mode 100755 index 0000000..4778214 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionSection.html @@ -0,0 +1,144 @@ + + + + + + ORKQuestionSection Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionSection Constants Reference

+ + +
+ + + + +
Declared inORKQuestionStepViewController.m
+ + + + + + + +

ORKQuestionSection

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKQuestionSection ) {
+ +    ORKQuestionSectionAnswer = 0,
+ +    ORKQuestionSection_COUNT,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKQuestionSectionAnswer
+
+ + +

+ Declared In ORKQuestionStepViewController.m. +

+ +
+ +
ORKQuestionSection_COUNT
+
+ + +

+ Declared In ORKQuestionStepViewController.m. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionType.html new file mode 100755 index 0000000..74f8118 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKQuestionType.html @@ -0,0 +1,461 @@ + + + + + + ORKQuestionType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionType Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKQuestionType

+ + +
+

An enumeration of values that identify the different types of questions that the ResearchKit +framework supports.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKQuestionType ) {
+ +    ORKQuestionTypeNone,
+ +    ORKQuestionTypeScale,
+ +    ORKQuestionTypeSingleChoice,
+ +    ORKQuestionTypeMultipleChoice,
+ +    ORKQuestionTypeMultiplePicker,
+ +    ORKQuestionTypeDecimal,
+ +    ORKQuestionTypeInteger,
+ +    ORKQuestionTypeBoolean,
+ +    ORKQuestionTypeText,
+ +    ORKQuestionTypeTimeOfDay,
+ +    ORKQuestionTypeDateAndTime,
+ +    ORKQuestionTypeDate,
+ +    ORKQuestionTypeTimeInterval,
+ +    ORKQuestionTypeHeight,
+ +    ORKQuestionTypeWeight,
+ +    ORKQuestionTypeLocation,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKQuestionTypeNone
+
+ + +
 No question.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeScale
+
+ + +
 The scale question type asks participants to place a mark at an appropriate position on a
+ continuous or discrete line.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeSingleChoice
+
+ + +
 In a single choice question, the participant can pick only one predefined option.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeMultipleChoice
+
+ + +
 In a multiple choice question, the participant can pick one or more predefined options.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeMultiplePicker
+
+ + +
 In a multiple component choice picker, the participant can pick one choice from each component.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeDecimal
+
+ + +
 The decimal question type asks the participant to enter a decimal number.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeInteger
+
+ + +
 The integer question type asks the participant to enter an integer number.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeBoolean
+
+ + +
 The Boolean question type asks the participant to enter Yes or No (or the appropriate
+ equivalents).
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeText
+
+ + +
 In a text question, the participant can enter multiple lines of text.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeTimeOfDay
+
+ + +
 In a time of day question, the participant can enter a time of day by using a picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeDateAndTime
+
+ + +
 In a date and time question, the participant can enter a combination of date and time by using
+ a picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeDate
+
+ + +
 In a date question, the participant can enter a date by using a picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeTimeInterval
+
+ + +
 In a time interval question, the participant can enter a time span by using a picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeHeight
+
+ + +
 In a height question, the participant can enter a height by using a height picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeWeight
+
+ + +
 In a weight question, the participant can enter a weight by using a weight picker.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKQuestionTypeLocation
+
+ + +
 In a location question, the participant can enter a location using a map view.
+
+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKRegistrationStepOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKRegistrationStepOption.html new file mode 100755 index 0000000..f200eb0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKRegistrationStepOption.html @@ -0,0 +1,252 @@ + + + + + + ORKRegistrationStepOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRegistrationStepOption Constants Reference

+ + +
+ + + + +
Declared inORKRegistrationStep.h
+ + + + + + + +

ORKRegistrationStepOption

+ + +
+

The ORKRegistrationStepOption flags let you include particular fields in addition +to the default fields (email and password) in the registration step.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKRegistrationStepOption ) {
+ +    ORKRegistrationStepDefault = 0,
+ +    ORKRegistrationStepIncludeGivenName = ( 1 < < 1 ),
+ +    ORKRegistrationStepIncludeFamilyName = ( 1 < < 2 ),
+ +    ORKRegistrationStepIncludeGender = ( 1 < < 3 ),
+ +    ORKRegistrationStepIncludeDOB = ( 1 < < 4 ),
+ +    ORKRegistrationStepIncludePhoneNumber = ( 1 < < 5 ),
+ + };
+ +
+ +
+

Constants

+
+ +
ORKRegistrationStepDefault
+
+ + +

Default behavior.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
ORKRegistrationStepIncludeGivenName
+
+ + +

Include the given name field.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
ORKRegistrationStepIncludeFamilyName
+
+ + +

Include the family name field.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
ORKRegistrationStepIncludeGender
+
+ + +

Include the gender field.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
ORKRegistrationStepIncludeDOB
+
+ + +

Include the date of birth field.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
ORKRegistrationStepIncludePhoneNumber
+
+ + +

Include the user phone number.

+ + + + + + +

+ Declared In ORKRegistrationStep.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKRegistrationStep.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSampleJSONOptions.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSampleJSONOptions.html new file mode 100755 index 0000000..0656d2d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSampleJSONOptions.html @@ -0,0 +1,156 @@ + + + + + + ORKSampleJSONOptions Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSampleJSONOptions Constants Reference

+ + +
+ + + + +
Declared inHKSample+ORKJSONDictionary.h
+ + + + + + + +

ORKSampleJSONOptions

+ +
+ + +

Definition

+ typedef NS_OPTIONS(NSInteger, ORKSampleJSONOptions ) {
+ +    ORKSampleIncludeMetadata = 0 x1,
+ +    ORKSampleIncludeSource = 0 x2,
+ +    ORKSampleIncludeUUID = 0 x4,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKSampleIncludeMetadata
+
+ + +

+ Declared In HKSample+ORKJSONDictionary.h. +

+ +
+ +
ORKSampleIncludeSource
+
+ + +

+ Declared In HKSample+ORKJSONDictionary.h. +

+ +
+ +
ORKSampleIncludeUUID
+
+ + +

+ Declared In HKSample+ORKJSONDictionary.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenMetric.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenMetric.html new file mode 100755 index 0000000..0dad528 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenMetric.html @@ -0,0 +1,612 @@ + + + + + + ORKScreenMetric Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScreenMetric Constants Reference

+ + +
+ + + + +
Declared inORKSkin.h
+ + + + + + + +

ORKScreenMetric

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKScreenMetric ) {
+ +    ORKScreenMetricTopToCaptionBaseline,
+ +    ORKScreenMetricFontSizeHeadline,
+ +    ORKScreenMetricMaxFontSizeHeadline,
+ +    ORKScreenMetricFontSizeSurveyHeadline,
+ +    ORKScreenMetricMaxFontSizeSurveyHeadline,
+ +    ORKScreenMetricFontSizeSubheadline,
+ +    ORKScreenMetricFontSizeFootnote,
+ +    ORKScreenMetricCaptionBaselineToFitnessTimerTop,
+ +    ORKScreenMetricCaptionBaselineToTappingLabelTop,
+ +    ORKScreenMetricCaptionBaselineToInstructionBaseline,
+ +    ORKScreenMetricInstructionBaselineToLearnMoreBaseline,
+ +    ORKScreenMetricLearnMoreBaselineToStepViewTop,
+ +    ORKScreenMetricLearnMoreBaselineToStepViewTopWithNoLearnMore,
+ +    ORKScreenMetricContinueButtonTopMargin,
+ +    ORKScreenMetricContinueButtonTopMarginForIntroStep,
+ +    ORKScreenMetricTopToIllustration,
+ +    ORKScreenMetricIllustrationToCaptionBaseline,
+ +    ORKScreenMetricIllustrationHeight,
+ +    ORKScreenMetricInstructionImageHeight,
+ +    ORKScreenMetricContinueButtonHeightRegular,
+ +    ORKScreenMetricContinueButtonHeightCompact,
+ +    ORKScreenMetricContinueButtonWidth,
+ +    ORKScreenMetricMinimumStepHeaderHeightForMemoryGame,
+ +    ORKScreenMetricMinimumStepHeaderHeightForTowerOfHanoiPuzzle,
+ +    ORKScreenMetricTableCellDefaultHeight,
+ +    ORKScreenMetricTextFieldCellHeight,
+ +    ORKScreenMetricChoiceCellFirstBaselineOffsetFromTop,
+ +    ORKScreenMetricChoiceCellLastBaselineToBottom,
+ +    ORKScreenMetricChoiceCellLabelLastBaselineToLabelFirstBaseline,
+ +    ORKScreenMetricLearnMoreButtonSideMargin,
+ +    ORKScreenMetricHeadlineSideMargin,
+ +    ORKScreenMetricToolbarHeight,
+ +    ORKScreenMetricVerticalScaleHeight,
+ +    ORKScreenMetricSignatureViewHeight,
+ +    ORKScreenMetricPSATKeyboardViewWidth,
+ +    ORKScreenMetricPSATKeyboardViewHeight,
+ +    ORKScreenMetricLocationQuestionMapHeight,
+ +    ORKScreenMetricTopToIconImageViewTop,
+ +    ORKScreenMetricIconImageViewToCaptionBaseline,
+ +    ORKScreenMetricVerificationTextBaselineToResendButtonBaseline,
+ +    ORKScreenMetric_COUNT,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKScreenMetricTopToCaptionBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricFontSizeHeadline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricMaxFontSizeHeadline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricFontSizeSurveyHeadline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricMaxFontSizeSurveyHeadline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricFontSizeSubheadline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricFontSizeFootnote
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricCaptionBaselineToFitnessTimerTop
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricCaptionBaselineToTappingLabelTop
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricCaptionBaselineToInstructionBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricInstructionBaselineToLearnMoreBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricLearnMoreBaselineToStepViewTop
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricLearnMoreBaselineToStepViewTopWithNoLearnMore
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricContinueButtonTopMargin
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricContinueButtonTopMarginForIntroStep
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricTopToIllustration
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricIllustrationToCaptionBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricIllustrationHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricInstructionImageHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricContinueButtonHeightRegular
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricContinueButtonHeightCompact
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricContinueButtonWidth
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricMinimumStepHeaderHeightForMemoryGame
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricMinimumStepHeaderHeightForTowerOfHanoiPuzzle
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricTableCellDefaultHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricTextFieldCellHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricChoiceCellFirstBaselineOffsetFromTop
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricChoiceCellLastBaselineToBottom
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricChoiceCellLabelLastBaselineToLabelFirstBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricLearnMoreButtonSideMargin
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricHeadlineSideMargin
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricToolbarHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricVerticalScaleHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricSignatureViewHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricPSATKeyboardViewWidth
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricPSATKeyboardViewHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricLocationQuestionMapHeight
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricTopToIconImageViewTop
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricIconImageViewToCaptionBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetricVerificationTextBaselineToResendButtonBaseline
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenMetric_COUNT
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenType.html new file mode 100755 index 0000000..d83a310 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKScreenType.html @@ -0,0 +1,228 @@ + + + + + + ORKScreenType Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKScreenType Constants Reference

+ + +
+ + + + +
Declared inORKSkin.h
+ + + + + + + +

ORKScreenType

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKScreenType ) {
+ +    ORKScreenTypeiPhoneX,
+ +    ORKScreenTypeiPhone6Plus,
+ +    ORKScreenTypeiPhone6,
+ +    ORKScreenTypeiPhone5,
+ +    ORKScreenTypeiPhone4,
+ +    ORKScreenTypeiPad,
+ +    ORKScreenTypeiPad10_5,
+ +    ORKScreenTypeiPad12_9,
+ +    ORKScreenType_COUNT,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKScreenTypeiPhoneX
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPhone6Plus
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPhone6
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPhone5
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPhone4
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPad
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPad10_5
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenTypeiPad12_9
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
ORKScreenType_COUNT
+
+ + +

+ Declared In ORKSkin.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanMemoryGameStatus.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanMemoryGameStatus.html new file mode 100755 index 0000000..88acac4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanMemoryGameStatus.html @@ -0,0 +1,213 @@ + + + + + + ORKSpatialSpanMemoryGameStatus Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanMemoryGameStatus Constants Reference

+ + +
+ + + + +
Declared inORKSpatialSpanMemoryResult.h
+ + + + + + + +

ORKSpatialSpanMemoryGameStatus

+ + +
+

An enumeration of values that describe the status of a round of the spatial span memory game.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKSpatialSpanMemoryGameStatus ) {
+ +    ORKSpatialSpanMemoryGameStatusUnknown,
+ +    ORKSpatialSpanMemoryGameStatusSuccess,
+ +    ORKSpatialSpanMemoryGameStatusFailure,
+ +    ORKSpatialSpanMemoryGameStatusTimeout,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKSpatialSpanMemoryGameStatusUnknown
+
+ + +

Unknown status. The game is still in progress or has not started.

+ + + + + + +

+ Declared In ORKSpatialSpanMemoryResult.h. +

+ +
+ +
ORKSpatialSpanMemoryGameStatusSuccess
+
+ + +

Success. The user has completed the sequence.

+ + + + + + +

+ Declared In ORKSpatialSpanMemoryResult.h. +

+ +
+ +
ORKSpatialSpanMemoryGameStatusFailure
+
+ + +

Failure. The user has completed the sequence incorrectly.

+ + + + + + +

+ Declared In ORKSpatialSpanMemoryResult.h. +

+ +
+ +
ORKSpatialSpanMemoryGameStatusTimeout
+
+ + +

Timeout. The game timed out during play.

+ + + + + + +

+ Declared In ORKSpatialSpanMemoryResult.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKSpatialSpanMemoryResult.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanResult.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanResult.html new file mode 100755 index 0000000..a978f46 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanResult.html @@ -0,0 +1,156 @@ + + + + + + ORKSpatialSpanResult Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanResult Constants Reference

+ + +
+ + + + +
Declared inORKSpatialSpanGameState.h
+ + + + + + + +

ORKSpatialSpanResult

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKSpatialSpanResult ) {
+ +    ORKSpatialSpanResultIgnore,
+ +    ORKSpatialSpanResultCorrect,
+ +    ORKSpatialSpanResultIncorrect,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKSpatialSpanResultIgnore
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
ORKSpatialSpanResultCorrect
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
ORKSpatialSpanResultIncorrect
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanStepState.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanStepState.html new file mode 100755 index 0000000..8a492f9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanStepState.html @@ -0,0 +1,240 @@ + + + + + + ORKSpatialSpanStepState Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanStepState Constants Reference

+ + +
+ + + + +
Declared inORKSpatialSpanMemoryStepViewController.m
+ + + + + + + +

ORKSpatialSpanStepState

+ + + +
+

Constants

+
+ +
ORKSpatialSpanStepStateInitial
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStatePlayback
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateGameplay
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateTimeout
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateFailed
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateSuccess
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateRestart
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateComplete
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStateStopped
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
ORKSpatialSpanStepStatePaused
+
+ + +

+ Declared In ORKSpatialSpanMemoryStepViewController.m. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanTargetState.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanTargetState.html new file mode 100755 index 0000000..bca06cf --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpatialSpanTargetState.html @@ -0,0 +1,168 @@ + + + + + + ORKSpatialSpanTargetState Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpatialSpanTargetState Constants Reference

+ + +
+ + + + +
Declared inORKSpatialSpanGameState.h
+ + + + + + + +

ORKSpatialSpanTargetState

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKSpatialSpanTargetState ) {
+ +    ORKSpatialSpanTargetStateQuiescent,
+ +    ORKSpatialSpanTargetStateActive,
+ +    ORKSpatialSpanTargetStateCorrect,
+ +    ORKSpatialSpanTargetStateIncorrect,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKSpatialSpanTargetStateQuiescent
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
ORKSpatialSpanTargetStateActive
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
ORKSpatialSpanTargetStateCorrect
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
ORKSpatialSpanTargetStateIncorrect
+
+ + +

+ Declared In ORKSpatialSpanGameState.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpeechRecognitionErrorCode.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpeechRecognitionErrorCode.html new file mode 100755 index 0000000..0565784 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKSpeechRecognitionErrorCode.html @@ -0,0 +1,156 @@ + + + + + + ORKSpeechRecognitionErrorCode Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognitionErrorCode Constants Reference

+ + +
+ + + + +
Declared inORKSpeechRecognitionError.h
+ + + + + + + +

ORKSpeechRecognitionErrorCode

+ +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKSpeechRecognitionErrorCode ) {
+ +    ORKSpeechRecognitionErrorLanguageNotAvailable = 1,
+ +    ORKSpeechRecognitionErrorResumeNotSupported,
+ +    ORKSpeechRecognitionErrorRecognitionFailed,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKSpeechRecognitionErrorLanguageNotAvailable
+
+ + +

+ Declared In ORKSpeechRecognitionError.h. +

+ +
+ +
ORKSpeechRecognitionErrorResumeNotSupported
+
+ + +

+ Declared In ORKSpeechRecognitionError.h. +

+ +
+ +
ORKSpeechRecognitionErrorRecognitionFailed
+
+ + +

+ Declared In ORKSpeechRecognitionError.h. +

+ +
+ +
+
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKStepViewControllerNavigationDirection.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKStepViewControllerNavigationDirection.html new file mode 100755 index 0000000..2dfe73c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKStepViewControllerNavigationDirection.html @@ -0,0 +1,176 @@ + + + + + + ORKStepViewControllerNavigationDirection Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepViewControllerNavigationDirection Constants Reference

+ + +
+ + + + +
Declared inORKStepViewController.h
+ + + + + + + +

ORKStepViewControllerNavigationDirection

+ + +
+

An enumeration of values used in ORKStepViewControllerDelegate to indicate the direction of navigation +requested by the participant.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKStepViewControllerNavigationDirection ) {
+ +    ORKStepViewControllerNavigationDirectionForward,
+ +    ORKStepViewControllerNavigationDirectionReverse,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKStepViewControllerNavigationDirectionForward
+
+ + +

Forward navigation. Indicates that the user tapped the Continue or Next button.

+ + + + + + +

+ Declared In ORKStepViewController.h. +

+ +
+ +
ORKStepViewControllerNavigationDirectionReverse
+
+ + +

Backward navigation. Indicates that the user tapped the Back button.

+ + + + + + +

+ Declared In ORKStepViewController.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTappingButtonIdentifier.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTappingButtonIdentifier.html new file mode 100755 index 0000000..730d066 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTappingButtonIdentifier.html @@ -0,0 +1,194 @@ + + + + + + ORKTappingButtonIdentifier Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTappingButtonIdentifier Constants Reference

+ + +
+ + + + +
Declared inORKTappingIntervalResult.h
+ + + + + + + +

ORKTappingButtonIdentifier

+ + +
+

Values that identify the button that was tapped in a tapping sample.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKTappingButtonIdentifier ) {
+ +    ORKTappingButtonIdentifierNone,
+ +    ORKTappingButtonIdentifierLeft,
+ +    ORKTappingButtonIdentifierRight,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKTappingButtonIdentifierNone
+
+ + +

The touch landed outside of the two buttons.

+ + + + + + +

+ Declared In ORKTappingIntervalResult.h. +

+ +
+ +
ORKTappingButtonIdentifierLeft
+
+ + +

The touch landed in the left button.

+ + + + + + +

+ Declared In ORKTappingIntervalResult.h. +

+ +
+ +
ORKTappingButtonIdentifierRight
+
+ + +

The touch landed in the right button.

+ + + + + + +

+ Declared In ORKTappingIntervalResult.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTappingIntervalResult.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTaskViewControllerFinishReason.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTaskViewControllerFinishReason.html new file mode 100755 index 0000000..e2763f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTaskViewControllerFinishReason.html @@ -0,0 +1,214 @@ + + + + + + ORKTaskViewControllerFinishReason Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTaskViewControllerFinishReason Constants Reference

+ + +
+ + + + +
Declared inORKTaskViewController.h
+ + + + + + + +

ORKTaskViewControllerFinishReason

+ + +
+

The ORKTaskViewControllerFinishReason value indicates how the task view controller has finished +the task.

+
+ + +
+ + +

Definition

+ typedef NS_ENUM(NSInteger, ORKTaskViewControllerFinishReason ) {
+ +    ORKTaskViewControllerFinishReasonSaved,
+ +    ORKTaskViewControllerFinishReasonDiscarded,
+ +    ORKTaskViewControllerFinishReasonCompleted,
+ +    ORKTaskViewControllerFinishReasonFailed,
+ + };
+ +
+ +
+

Constants

+
+ +
ORKTaskViewControllerFinishReasonSaved
+
+ + +

The task was canceled by the participant or the developer, and the participant asked to save the current result.

+ + + + + + +

+ Declared In ORKTaskViewController.h. +

+ +
+ +
ORKTaskViewControllerFinishReasonDiscarded
+
+ + +

The task was canceled by the participant or the developer, and the participant asked to discard the current result.

+ + + + + + +

+ Declared In ORKTaskViewController.h. +

+ +
+ +
ORKTaskViewControllerFinishReasonCompleted
+
+ + +

The task has completed successfully, because all steps have been completed.

+ + + + + + +

+ Declared In ORKTaskViewController.h. +

+ +
+ +
ORKTaskViewControllerFinishReasonFailed
+
+ + +

An error was detected during the current step.

+ + + + + + +

+ Declared In ORKTaskViewController.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTremorActiveTaskOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTremorActiveTaskOption.html new file mode 100755 index 0000000..84ec64b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Constants/ORKTremorActiveTaskOption.html @@ -0,0 +1,255 @@ + + + + + + ORKTremorActiveTaskOption Constants Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTremorActiveTaskOption Constants Reference

+ + +
+ + + + +
Declared inORKTypes.h
+ + + + + + + +

ORKTremorActiveTaskOption

+ + +
+

The ORKTremorActiveTaskOption flags let you exclude particular steps from the predefined active +tasks in the predefined Tremor ORKOrderedTask.

+ +

By default, all predefined active tasks will be included. The tremor active task option flags can +be used to explicitly specify that an active task is not to be included.

+
+ + +
+ + +

Definition

+ typedef NS_OPTIONS(NSUInteger, ORKTremorActiveTaskOption ) {
+ +    ORKTremorActiveTaskOptionNone = 0,
+ +    ORKTremorActiveTaskOptionExcludeHandInLap = ( 1 < < 0 ),
+ +    ORKTremorActiveTaskOptionExcludeHandAtShoulderHeight = ( 1 < < 1 ),
+ +    ORKTremorActiveTaskOptionExcludeHandAtShoulderHeightElbowBent = ( 1 < < 2 ),
+ +    ORKTremorActiveTaskOptionExcludeHandToNose = ( 1 < < 3 ),
+ +    ORKTremorActiveTaskOptionExcludeQueenWave = ( 1 < < 4 ),
+ + };
+ +
+ +
+

Constants

+
+ +
ORKTremorActiveTaskOptionNone
+
+ + +

Default behavior.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKTremorActiveTaskOptionExcludeHandInLap
+
+ + +

Exclude the hand-in-lap steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKTremorActiveTaskOptionExcludeHandAtShoulderHeight
+
+ + +

Exclude the hand-extended-at-shoulder-height steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKTremorActiveTaskOptionExcludeHandAtShoulderHeightElbowBent
+
+ + +

Exclude the elbow-bent-at-shoulder-height steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKTremorActiveTaskOptionExcludeHandToNose
+
+ + +

Exclude the elbow-bent-touch-nose steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
ORKTremorActiveTaskOptionExcludeQueenWave
+
+ + +

Exclude the queen-wave steps.

+ + + + + + +

+ Declared In ORKTypes.h. +

+ +
+ +
+
+ + + + + + + + +
+

Declared In

+

ORKTypes.h

+
+ + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKAnswerOption.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKAnswerOption.html new file mode 100755 index 0000000..84ecf19 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKAnswerOption.html @@ -0,0 +1,232 @@ + + + + + + ORKAnswerOption Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKAnswerOption Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKAnswerFormat_Internal.h
+ + + + +
+ +

Overview

+

The ORKAnswerOption protocol defines brief option text for a option which can be included within ORK*ChoiceAnswerFormat.

+
+ + + + + +
+ + + + + + +
+
+ +

– text +required method

+ +
+
+ +
+ + +
+

Brief option text.

+
+ + + +
- (NSString *)text
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKAnswerFormat_Internal.h

+
+ + +
+
+
+ +

– value +required method

+ +
+
+ +
+ + +
+

The value to be returned if this option is selected.

+
+ + + +
- (nullable id)value
+ + + + + + + + + +
+

Discussion

+

Expected to be a scalar type serializable to JSON, e.g. NSNumber or NSString. +If no value is provided, the index of the option in the ORK*ChoiceAnswerFormat options list will be used.

+
+ + + + + + + +
+

Declared In

+

ORKAnswerFormat_Internal.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataCollectionManagerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataCollectionManagerDelegate.html new file mode 100755 index 0000000..2e619a5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataCollectionManagerDelegate.html @@ -0,0 +1,457 @@ + + + + + + ORKDataCollectionManagerDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataCollectionManagerDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKDataCollectionManager.h
+ + + + +
+ +

Overview

+

The data collection manager delegate is responsible for delivering collected data objects, +and reporting errors during the operation.

+
+ + + + + +
+ + + + + + +
+
+ +

– healthCollector:didCollectSamples: +

+ +
+
+ +
+ + +
+

Method for delivering the collected health data samples.

+
+ + + +
- (BOOL)healthCollector:(ORKHealthCollector *)collector didCollectSamples:(NSArray<HKSample*> *)samples
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

samples

Collected health data samples.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– healthCorrelationCollector:didCollectCorrelations: +

+ +
+
+ +
+ + +
+

Method for delivering the collected health correlations.

+
+ + + +
- (BOOL)healthCorrelationCollector:(ORKHealthCorrelationCollector *)collector didCollectCorrelations:(NSArray<HKCorrelation*> *)correlations
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

correlations

Collected health correlation samples.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– motionActivityCollector:didCollectMotionActivities: +

+ +
+
+ +
+ + +
+

Method for delivering the collected motion activities.

+
+ + + +
- (BOOL)motionActivityCollector:(ORKMotionActivityCollector *)collector didCollectMotionActivities:(NSArray<CMMotionActivity*> *)motionActivities
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

motionActivities

Collected motion activities.

+
+ + + +
+

Return Value

+

Boolean indicating whether the samples has be accepted. +If NO is returned or this method is not implemented, the manager will stop the collection for the collector and repeat this same collection next time, +until the data is accepted.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– dataCollectionManagerDidCompleteCollection: +

+ +
+
+ +
+ + +
+

Indicating the collection is completed for all the collectors.

+
+ + + +
- (void)dataCollectionManagerDidCompleteCollection:(ORKDataCollectionManager *)manager
+ + + +
+

Parameters

+ + + + + + + +
manager

The data collection manager.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+ +

– collector:didDetectError: +

+ +
+
+ +
+ + +
+

Method for reporting the deteted error during collection.

+
+ + + +
- (void)collector:(ORKCollector *)collector didDetectError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
collector

The data collector.

error

The error object.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataCollectionManager.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerDelegate.html new file mode 100755 index 0000000..a2c6cb1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerDelegate.html @@ -0,0 +1,261 @@ + + + + + + ORKDataLoggerDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKDataLogger.h
+ + + + +
+ +

Overview

+

The ORKDataLoggerDelegate protocol defines methods that the delegate of an ORKDataLogger object uses to handle data being logged to disk.

+
+ + + + + +
+ + + + + + +
+
+ +

– dataLogger:finishedLogFile: +required method

+ +
+
+ +
+ + +
+

Tells the delegate when a log file rollover occurs.

+
+ + + +
- (void)dataLogger:(ORKDataLogger *)dataLogger finishedLogFile:(NSURL *)fileUrl
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLogger

The data logger providing the notification.

fileUrl

The URL of the newly renamed log file.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLoggerByteCountsDidChange: +

+ +
+
+ +
+ + +
+

Tells the delegate if the number of bytes in completed logs changes.

+
+ + + +
- (void)dataLoggerByteCountsDidChange:(ORKDataLogger *)dataLogger
+ + + +
+

Parameters

+ + + + + + + +
dataLogger

The data logger providing the notification.

+
+ + + + + + + +
+

Discussion

+

When files are removed or added, or marked as uploaded or unmarked, this delegate method is called a short time later. Multiple directory changes +are rolled up into a single delegate callback.

+
+ + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerExtendedDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerExtendedDelegate.html new file mode 100755 index 0000000..ab38560 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerExtendedDelegate.html @@ -0,0 +1,185 @@ + + + + + + ORKDataLoggerExtendedDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerExtendedDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toORKDataLoggerDelegate
Declared inORKDataLogger.h
+ + + + + + +
+ + + + + + +
+
+ +

– dataLoggerThresholdsDidChange: +

+ +
+
+ +
+ + +
+

Tells the delegate that the maximum current log file lifetime changed.

+
+ + + +
- (void)dataLoggerThresholdsDidChange:(ORKDataLogger *)dataLogger
+ + + +
+

Parameters

+ + + + + + + +
dataLogger

Source of this event.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerManagerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerManagerDelegate.html new file mode 100755 index 0000000..ed96545 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKDataLoggerManagerDelegate.html @@ -0,0 +1,264 @@ + + + + + + ORKDataLoggerManagerDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKDataLoggerManagerDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKDataLogger.h
+ + + + +
+ +

Overview

+

The ORKDataLoggerManagerDelegate protocol defines methods a delegate can implement to receive notifications +when the data loggers managed by a ORKDataLoggerManager reach a certain file size threshold.

+
+ + + + + +
+ + + + + + +
+
+ +

– dataLoggerManager:pendingUploadBytesReachedThreshold: +required method

+ +
+
+ +
+ + +
+

Called by the data logger manager when the total size of files +that are not marked uploaded has reached a threshold.

+
+ + + +
- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLoggerManager pendingUploadBytesReachedThreshold:(unsigned long long)pendingUploadBytes
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLoggerManager

The manager that produced the notification.

pendingUploadBytes

The number of bytes managed by all the loggers, which + have not yet been marked uploaded.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+ +

– dataLoggerManager:totalBytesReachedThreshold: +required method

+ +
+
+ +
+ + +
+

Called by the data logger manager when the total size of files +managed by any of the loggers has reached a threshold.

+
+ + + +
- (void)dataLoggerManager:(ORKDataLoggerManager *)dataLoggerManager totalBytesReachedThreshold:(unsigned long long)totalBytes
+ + + +
+

Parameters

+ + + + + + + + + + + + +
dataLoggerManager

The manager that produced the notification.

totalBytes

The total number of bytes of all files managed.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKDataLogger.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDataSource.html new file mode 100755 index 0000000..8163aa0 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDataSource.html @@ -0,0 +1,1046 @@ + + + + + + ORKGraphChartViewDataSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKGraphChartViewDataSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKGraphChartView.h
+ + + + +
+ +

Overview

+

The abstract ORKGraphChartViewDataSource protocol is the base protocol which conforms the basis +for the ORKValueRangeGraphChartViewDataSource and ORKValueStackGraphChartViewDataSource +protocols, required to populate the concrete ORKGraphChartView subclass.

+ +

At a minimum, a data source object must implement the graphChartView:numberOfPointsInPlot: and +graphChartView:plot:valueForPointAtIndex: methods. These methods return +the number of points in a plot and the points themselves. Each point in a plot is represented by +an object of the ORKValueRange or ORKValueStack class, depending on the concrete subprotocol.

+ +

A data source object may provide additional information to the graph chart view by implementing the +optional methods.

+ +

When configuring an ORKGraphChartView object, assign your data source to its dataSource +property.

+
+ + + + + +
+ + + + + + +
+
+ +

– graphChartView:numberOfDataPointsForPlotIndex: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the number of value points to be plotted by the graph chart view at the +specified plot index.

+
+ + + +
- (NSInteger)graphChartView:(ORKGraphChartView *)graphChartView numberOfDataPointsForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the number of value points.

plotIndex

An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The number of range points in the plot at plotIndex.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– numberOfPlotsInGraphChartView: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the number of plots to be plotted by the graph chart view.

+
+ + + +
- (NSInteger)numberOfPlotsInGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the number of plots.

+
+ + + +
+

Return Value

+

The number of plots in the graph chart view.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:colorForPlotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the color of the specified plot.

+
+ + + +
- (UIColor *)graphChartView:(ORKGraphChartView *)graphChartView colorForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the color of the segment.

plotIndex

An index number identifying the plot in the graph chart view. This index + is always 0 in single-plot graph chart views.

+
+ + + +
+

Return Value

+

The color of the segment at the specified index in a pie chart view.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the first plot uses the graph chart view tintColor, and +all subsequent plots uses the current referenceLineColor.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:fillColorForPlotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the fill color of the specified plot.

+
+ + + +
- (UIColor *)graphChartView:(ORKGraphChartView *)graphChartView fillColorForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the color of the segment.

plotIndex

An index number identifying the plot in the graph chart view. This index +is always 0 in single-plot graph chart views.

+
+ + + +
+

Return Value

+

The color of the fill layer at the specified index in a line chart view.

+
+ + + + + +
+

Discussion

+

The fill color is only used by ORKLineGraphChartView. If this method is not implemented, the +chart uses the main color of the specified plot with a 0.4 opacity value.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– scrubbingPlotIndexForGraphChartView: +

+ +
+
+ +
+ + +
+

Asks the data source which plot the scrubber should snap to in multigraph chart views.

+
+ + + +
- (NSInteger)scrubbingPlotIndexForGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the scrubbing plot index.

+
+ + + +
+

Return Value

+

The index of the plot that the scrubber should snap to.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the scrubber snaps over the first plot.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– maximumValueForGraphChartView: +

+ +
+
+ +
+ + +
+

Asks the data source for the upper limit of the y-axis drawn by the graph chart view.

+
+ + + +
- (double)maximumValueForGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the maximum value.

+
+ + + +
+

Return Value

+

The maximum value of the y-axis drawn by graphChartView.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the greatest maximumValue of all ORKValueRange instances +returned in graphChartView:plot:valueForPointAtIndex: is used.

+ +

See also: graphChartView:plot:valueForPointAtIndex:.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– minimumValueForGraphChartView: +

+ +
+
+ +
+ + +
+

Asks the data source for the lower limit of the y-axis drawn by the graph chart view.

+
+ + + +
- (double)minimumValueForGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the minimum value.

+
+ + + +
+

Return Value

+

The minimum value of the y-axis drawn by graphChartView.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the smallest minimumValue of all ORKValueRange instances +returned in graphChartView:plot:valueForPointAtIndex: is used.

+ +

See also: graphChartView:plot:valueForPointAtIndex:.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– numberOfDivisionsInXAxisForGraphChartView: +

+ +
+
+ +
+ + +
+

Asks the data source for the number of divisions in the x-axis. The value is ignored if it is lower +than the number of data points. A title appearing adjacent to each +division may optionally be returned by the graphChartView:titleForXAxisAtPointIndex: method.

+
+ + + +
- (NSInteger)numberOfDivisionsInXAxisForGraphChartView:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view asking for the number of divisions in its x-axis.

+
+ + + +
+

Return Value

+

The number of divisions in the x-axis for graphChartView.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:titleForXAxisAtPointIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the title to be displayed adjacent to each division in the x-axis (the +number returned by numberOfDivisionsInXAxisForGraphChartView:). You can return nil from this +method if you don’t want to display a title for the specified point index.

+
+ + + +
- (nullable NSString *)graphChartView:(ORKGraphChartView *)graphChartView titleForXAxisAtPointIndex:(NSInteger)pointIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view asking for the title.

pointIndex

The index of the specified x-axis division.

+
+ + + +
+

Return Value

+

The title string to be displayed adjacent to each division of the x-axis of the graph chart +view.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the x-axis has no titles.

+ +

See also: numberOfDivisionsInXAxisForGraphChartView:.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:drawsVerticalReferenceLineAtPointIndex: +

+ +
+
+ +
+ + +
+

Asks the data source if the vertical reference line at the specified point index should be drawn..

+
+ + + +
- (BOOL)graphChartView:(ORKGraphChartView *)graphChartView drawsVerticalReferenceLineAtPointIndex:(NSInteger)pointIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph view asking for the tile.

pointIndex

The index corresponding to the number returned by + numberOfDivisionsInXAxisForGraphChartView:.

+
+ + + +
+

Return Value

+

Whether the graph chart view should draw the vertical reference line.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the graph chart view will draw all vertical reference lines.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:drawsPointIndicatorsForPlotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source if the plot at specified index should display circular indicators on its data points.

+
+ + + +
- (BOOL)graphChartView:(ORKGraphChartView *)graphChartView drawsPointIndicatorsForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph view asking whether point indicators should be drawn.

plotIndex

An index number identifying the plot in the graph chart view. This index +is always 0 in single-plot graph chart views.

+
+ + + +
+

Return Value

+

Whether the graph chart view should draw point indicators for its points.

+
+ + + + + +
+

Discussion

+

This only applys to ORKLineGrapthChartView. +If this method is not implemented, point indicators will be drawn for all plots.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:accessibilityUnitLabelForPlotIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the unit label for the given plot index so VoiceOver’s description of the graph can be read with units.

+
+ + + +
- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView accessibilityUnitLabelForPlotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph view asking for its unit label

plotIndex

An index number identifying the plot in the graph chart view. This index +is always 0 in single-plot graph chart views.

+
+ + + +
+

Return Value

+

An appropriate unit label for the given plot.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, VoiceOver will speak the graph value without units.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:accessibilityLabelForXAxisAtPointIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the accessibilityLabel at a given point on the x-axis

+
+ + + +
- (NSString *)graphChartView:(ORKGraphChartView *)graphChartView accessibilityLabelForXAxisAtPointIndex:(NSInteger)pointIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph view asking for its unit label

pointIndex

The index corresponding to the number returned by numberOfDivisionsInXAxisForGraphChartView:.

+
+ + + +
+

Return Value

+

An appropriate accessibility label for the given index of the graph.

+
+ + + + + +
+

Discussion

+

This is used in cases where the UI may be displaying a shortened form (e.g. M, T, W, etc. for days of the week), but VoiceOver should be speaking the longer form. If this method isn’t implemented, VoiceOver will speak the label displayed in the UI for the given index.

+
+ + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDelegate.html new file mode 100755 index 0000000..de3926c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKGraphChartViewDelegate.html @@ -0,0 +1,314 @@ + + + + + + ORKGraphChartViewDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKGraphChartViewDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKGraphChartView.h
+ + + + +
+ +

Overview

+

The graph chart view delegate protocol forwards pan gesture events occuring +within the bounds of an ORKGraphChartView object.

+
+ + + + + +
+ + + + + + +
+
+ +

– graphChartViewTouchesBegan: +

+ +
+
+ +
+ + +
+

Notifies the delegate that a pan gesture has begun within the bounds of an ORKGraphChartView +object.

+
+ + + +
- (void)graphChartViewTouchesBegan:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view in which the gesture occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartView:touchesMovedToXPosition: +

+ +
+
+ +
+ + +
+

Notifies the delegate of updates in the x-coordinate of an ongoing pan gesture within the bounds +of an ORKGraphChartView object.

+
+ + + +
- (void)graphChartView:(ORKGraphChartView *)graphChartView touchesMovedToXPosition:(CGFloat)xPosition
+ + + +
+

Parameters

+ + + + + + + + + + + + +
graphChartView

The graph chart view object in which the gesture occurred.

xPosition

The updated x-coordinate of the ongoing pan gesture.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+ +

– graphChartViewTouchesEnded: +

+ +
+
+ +
+ + +
+

Notifies the delegate that a pan gesture that began within the bounds of an ORKGraphChartView +object has ended.

+
+ + + +
- (void)graphChartViewTouchesEnded:(ORKGraphChartView *)graphChartView
+ + + +
+

Parameters

+ + + + + + + +
graphChartView

The graph chart view object in which the gesture occurred.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPasscodeDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPasscodeDelegate.html new file mode 100755 index 0000000..3ebed03 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPasscodeDelegate.html @@ -0,0 +1,422 @@ + + + + + + ORKPasscodeDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPasscodeDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKPasscodeViewController.h
+ + + + +
+ +

Overview

+

The passcode delegate protocol declares methods which forward the success or failure of passcode modification +or authentication.

+
+ + + + + +
+ + + + + + +
+
+ +

– passcodeViewControllerDidFinishWithSuccess: +required method

+ +
+
+ +
+ + +
+

Notifies the delegate that the user has finished authenticating or editing the passcode.

+
+ + + +
- (void)passcodeViewControllerDidFinishWithSuccess:(UIViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
viewController

The ORKPasscodeStepViewController object in which the passcode input is entered.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

– passcodeViewControllerDidFailAuthentication: +required method

+ +
+
+ +
+ + +
+

Notifies the delegate that the user failed authentication.

+
+ + + +
- (void)passcodeViewControllerDidFailAuthentication:(UIViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
viewController

The ORKPasscodeStepViewController object in which the passcode input is entered.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

– passcodeViewControllerDidCancel: +

+ +
+
+ +
+ + +
+

Notifies the delegate that the user hit the cancel button item. The cancel button is only visible if this method +is implemented.

+
+ + + +
- (void)passcodeViewControllerDidCancel:(UIViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
viewController

The ORKPasscodeStepViewController object in which the passcode input is entered.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

– passcodeViewControllerTextForForgotPasscode: +

+ +
+
+ +
+ + +
+

Defaults to Localized “Forgot Passcode?” text

+
+ + + +
- (NSString *)passcodeViewControllerTextForForgotPasscode:(UIViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
viewController

The ORKPasscodeStepViewController object in which the passcode input is entered.

+
+ + + +
+

Return Value

+

Text to display for the forgot passcode button

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+ +

– passcodeViewControllerForgotPasscodeTapped: +

+ +
+
+ +
+ + +
+

Notifies the delegate that forgot passcode button has been tapped.

+
+ + + +
- (void)passcodeViewControllerForgotPasscodeTapped:(UIViewController *)viewController
+ + + +
+

Parameters

+ + + + + + + +
viewController

The ORKPasscodeStepViewController object in which the passcode input is entered.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKPasscodeViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPieChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPieChartViewDataSource.html new file mode 100755 index 0000000..30fad4a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKPieChartViewDataSource.html @@ -0,0 +1,422 @@ + + + + + + ORKPieChartViewDataSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKPieChartViewDataSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKPieChartView.h
+ + + + +
+ +

Overview

+

An object that adopts the ORKPieChartViewDataSource protocol is responsible for providing the +data required to populate an ORKPieChartView object.

+ +

At a minimumm, a data source object must implement the numberOfSegmentsInPieChartView and +pieChartView:valueForSegmentAtIndex: methods. These methods are responsible for returning the +number of segments in a pie chart view and the value for each segment. A data source object may +provide additional information to the pie chart by implementing the optional +ORKPieChartViewDataSource methods.

+ +

When configuring an ORKPieChartView object, assign your data source to its dataSource property.

+
+ + + + + +
+ + + + + + +
+
+ +

– numberOfSegmentsInPieChartView: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the number of segments in the pie chart view.

+
+ + + +
- (NSInteger)numberOfSegmentsInPieChartView:(ORKPieChartView *)pieChartView
+ + + +
+

Parameters

+ + + + + + + +
pieChartView

The pie chart view asking for the number of segments.

+
+ + + +
+

Return Value

+

The number of segments in the pie chart view.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:valueForSegmentAtIndex: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the value of a segment in the pie chart view.

+
+ + + +
- (CGFloat)pieChartView:(ORKPieChartView *)pieChartView valueForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the value of the segment.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The value of the segment at the specified index in the pie chart view.

+
+ + + + + +
+

Discussion

+

The value can be any arbitrary integer: the pie chart view normalizes them by the sum of all +returned values.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:colorForSegmentAtIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the color of a segment in the pie chart view.

+
+ + + +
- (UIColor *)pieChartView:(ORKPieChartView *)pieChartView colorForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the color of the segment.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The color of the segment at the specified index in the pie chart view.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the pie chart view uses a unique shade of the current +tint color for each segment.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+ +

– pieChartView:titleForSegmentAtIndex: +

+ +
+
+ +
+ + +
+

Asks the data source for the title to appear in the legend for a segment in the pie chart view.

+
+ + + +
- (NSString *)pieChartView:(ORKPieChartView *)pieChartView titleForSegmentAtIndex:(NSInteger)index
+ + + +
+

Parameters

+ + + + + + + + + + + + +
pieChartView

The pie chart view asking for the title.

index

An index number specifying the segment in the pie chart view.

+
+ + + +
+

Return Value

+

The title of the segment at the specified index in the pie chat view’s +legend.

+
+ + + + + +
+

Discussion

+

If this method is not implemented, the pie chart view does not display the legend.

+
+ + + + + + + +
+

Declared In

+

ORKPieChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKQuestionStepCustomViewDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKQuestionStepCustomViewDelegate.html new file mode 100755 index 0000000..4679f96 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKQuestionStepCustomViewDelegate.html @@ -0,0 +1,124 @@ + + + + + + ORKQuestionStepCustomViewDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKQuestionStepCustomViewDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKCustomStepView.h
+ + + + +
+ +

Overview

+

The ORKQuestionStepCustomViewDelegate protocol defines the methods that a question step custom view should implement.

+ +

Typically, a question step view controller (ORKQuestionStepViewController) is the delegate of a +custom question step view.

+
+ + + + + + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKRecorderDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKRecorderDelegate.html new file mode 100755 index 0000000..45e6c58 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKRecorderDelegate.html @@ -0,0 +1,274 @@ + + + + + + ORKRecorderDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKRecorderDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKRecorder.h
+ + + + +
+ +

Overview

+

The ORKRecorderDelegate protocol defines methods that the delegate of an ORKRecorder object should use to handle errors and log the +completed results.

+ +

This protocol is implemented by ORKActiveStepViewController; your app should not +need to implement it.

+
+ + + + + +
+ + + + + + +
+
+ +

– recorder:didCompleteWithResult: +required method

+ +
+
+ +
+ + +
+

Tells the delegate that the recorder has completed with the specified result.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didCompleteWithResult:(nullable ORKResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

result

The generated result.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when recording is stopped.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+ +

– recorder:didFailWithError: +required method

+ +
+
+ +
+ + +
+

Tells the delegate that recording failed.

+
+ + + +
- (void)recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
recorder

The generating recorder object.

error

The error that occurred.

+
+ + + + + + + +
+

Discussion

+

Typically, this method is called once when the error occurred.

+
+ + + + + + + +
+

Declared In

+

ORKRecorder.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKSpeechRecognitionDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKSpeechRecognitionDelegate.html new file mode 100755 index 0000000..3101acd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKSpeechRecognitionDelegate.html @@ -0,0 +1,256 @@ + + + + + + ORKSpeechRecognitionDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKSpeechRecognitionDelegate Protocol Reference

+ + +
+ + + + +
Declared inORKSpeechRecognizer.h
+ + + + + + +
+ + + + + + +
+
+ +

– didFinishRecognitionWithError: +

+ +
+
+ +
+ + +
+

Tells the delegate when the recognition of requested utterance is finished.

+
+ + + +
- (void)didFinishRecognitionWithError:(NSError *)error
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+ +

– didHypothesizeTranscription: +

+ +
+
+ +
+ + +
+

Tells the delegate that a hypothesized transcription is available.

+
+ + + +
- (void)didHypothesizeTranscription:(SFTranscription *)transcription
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+ +

– availabilityDidChange: +

+ +
+
+ +
+ + +
+

Tells the delegate when the availability of the speech recognizer has changed

+
+ + + +
- (void)availabilityDidChange:(BOOL)available
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKSpeechRecognizer.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKStepViewControllerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKStepViewControllerDelegate.html new file mode 100755 index 0000000..c0167cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKStepViewControllerDelegate.html @@ -0,0 +1,606 @@ + + + + + + ORKStepViewControllerDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKStepViewControllerDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKStepViewController.h
+ + + + +
+ +

Overview

+

The primary implementer of the ORKStepViewControllerDelegate protocol is the +task view controller (ORKTaskViewController). The task view controller observes the messages +of the protocol to correctly update its result property, and to control navigation +through the task.

+ +

If you present step view controllers outside of a task view controller, it +can be helpful to implement this protocol to facilitate navigation and +results collection.

+
+ + + + + +
+ + + + + + +
+
+ +

– stepViewController:didFinishWithNavigationDirection: +required method

+ +
+
+ +
+ + +
+

Tells the delegate when the user has done something that requires navigation, such as +tap the Back or a Next button, or enter a response to a nonoptional +survey question.

+
+ + + +
- (void)stepViewController:(ORKStepViewController *)stepViewController didFinishWithNavigationDirection:(ORKStepViewControllerNavigationDirection)direction
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

direction

Direction of navigation requested.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerResultDidChange: +required method

+ +
+
+ +
+ + +
+

Tells the delegate when a substantial change has occurred to the result.

+
+ + + +
- (void)stepViewControllerResultDidChange:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + + + + + +
+

Discussion

+

The result is always available in the step view controller. Although the result is continuously changing +while the step view controller is active (because the time stamp in the result property is different each time it’s called), this method is called only when a substantive change +to the result occurs, such as when the user enters a survey answer or completes +an active step.

+ +

In your implementation of this delegate method, you can collect the value of result from the step view controller.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerDidFail:withError: +required method

+ +
+
+ +
+ + +
+

Tells the delegate when a step fails due to an error.

+
+ + + +
- (void)stepViewControllerDidFail:(ORKStepViewController *)stepViewController withError:(nullable NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

error

The error detected.

+
+ + + + + + + +
+

Discussion

+

A step view controller can use this method to report its failure to the task view controller. +The task view controller sends the error to its delegate indicating that the task has failed (using ORKTaskViewControllerFinishReasonFailed). +Note that recorder errors are reported by calling the ORKStepViewControllerDelegate method stepViewController:recorder:didFailWithError:.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewController:recorder:didFailWithError: +required method

+ +
+
+ +
+ + +
+

Tells the delegate when a recorder error has been detected during the step.

+
+ + + +
- (void)stepViewController:(ORKStepViewController *)stepViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
stepViewController

The step view controller providing the callback.

recorder

The recorder that detected the error.

error

The error detected.

+
+ + + + + + + +
+

Discussion

+

Recorder errors can occur during active steps, usually due to the +unavailability of sensor data or disk space in which to record results.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerWillAppear: +

+ +
+
+ +
+ + +
+

Tells the delegate that the step view controller’s view is about to appear.

+
+ + + +
- (void)stepViewControllerWillAppear:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + + + + + +
+

Discussion

+

This method is called from the step view controller’s viewWillAppear: method. +You can use this method to customize the appearance of the step view +controller without subclassing it.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerHasPreviousStep: +

+ +
+
+ +
+ + +
+

Asks the delegate whether there is a previous step.

+
+ + + +
- (BOOL)stepViewControllerHasPreviousStep:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + +
+

Return Value

+

YES if a Back button should be visible; otherwise, NO.

+
+ + + + + +
+

Discussion

+

If there is a previous step, the step view controller adds a Back button to its +navigation item; if not, no Back button is added to the navigation item.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+ +

– stepViewControllerHasNextStep: +

+ +
+
+ +
+ + +
+

Asks the delegate whether there is a next step.

+
+ + + +
- (BOOL)stepViewControllerHasNextStep:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + +
stepViewController

The step view controller providing the callback.

+
+ + + +
+

Return Value

+

YES if there is a step following the current one; otherwise, NO.

+
+ + + + + +
+

Discussion

+

Depending on the result of the step, the step view controller can adjust the language for the +Next button.

+
+ + + + + + + +
+

Declared In

+

ORKStepViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTableStepSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTableStepSource.html new file mode 100755 index 0000000..4475ec9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTableStepSource.html @@ -0,0 +1,561 @@ + + + + + + ORKTableStepSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTableStepSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKTableStep.h
+ + + + +
+ +

Overview

+

The ORKTableStepSource is a protocol that can be used for presenting a list of model +objects in a UITableView. Any ORKStep subclass that implements this protocol can be used with +an ORKTableStepViewController to display the list of items.

+
+ + + + + +
+ + + + + + +
+
+ +

– numberOfRowsInSection: +required method

+ +
+
+ +
+ + +
+

Returns the number of rows in the section.

+
+ + + +
- (NSInteger)numberOfRowsInSection:(NSInteger)section
+ + + +
+

Parameters

+ + + + + + + +
section

The section of the table

+
+ + + +
+

Return Value

+

The number of rows in the tableview section

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– configureCell:indexPath:tableView: +required method

+ +
+
+ +
+ + +
+

Method for configuring a cell.

+
+ + + +
- (void)configureCell:(UITableViewCell *)cell indexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
cell

The UITableViewCell to configure.

indexPath

The indexpath for the cell.

tableView

The table view for this cell.

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– numberOfSections +

+ +
+
+ +
+ + +
+

Returns the number of sections in the tableview used to display this step. Default = 1.

+
+ + + +
- (NSInteger)numberOfSections
+ + + + + +
+

Return Value

+

The number of sections in the tableview.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– reuseIdentifierForRowAtIndexPath: +

+ +
+
+ +
+ + +
+

Returns the reuseIdentifier for the object at this index path. Default = ORKBasicCellReuseIdentifier

+
+ + + +
- (NSString *)reuseIdentifierForRowAtIndexPath:(NSIndexPath *)indexPath
+ + + +
+

Parameters

+ + + + + + + +
indexPath

The indexpath of the section/row for the cell

+
+ + + +
+

Return Value

+

The model object for this section/row

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– registerCellsForTableView: +

+ +
+
+ +
+ + +
+

Optional override for registering UITableViewCell instances. The default registers a UITableViewCell +for ORKBasicCellReuseIdentifier.

+
+ + + +
- (void)registerCellsForTableView:(UITableView *)tableView
+ + + +
+

Parameters

+ + + + + + + +
tableView

The table view to register cells

+
+ + + + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– titleForHeaderInSection:tableView: +

+ +
+
+ +
+ + +
+

Optional override to return custom header title for section. The default returns nil.

+
+ + + +
- (nullable NSString *)titleForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView
+ + + +
+

Parameters

+ + + + + + + + + + + + +
section

The section for this custom header title

tableView

The table view for custom section header title

+
+ + + +
+

Return Value

+

The custom header title for this section

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+ +

– viewForHeaderInSection:tableView: +

+ +
+
+ +
+ + +
+

Optional override to return custom header view for section. The default returns nil.

+
+ + + +
- (nullable UIView *)viewForHeaderInSection:(NSInteger)section tableView:(UITableView *)tableView
+ + + +
+

Parameters

+ + + + + + + + + + + + +
section

The section for this custom header view

tableView

The table view for custom section header view

+
+ + + +
+

Return Value

+

The custom header view for this section

+
+ + + + + + + + + + + +
+

Declared In

+

ORKTableStep.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTask.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTask.html new file mode 100755 index 0000000..ce7babe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTask.html @@ -0,0 +1,668 @@ + + + + + + ORKTask Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTask Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKTask.h
+ + + + +
+ +

Overview

+

The ORKTask protocol defines a task to be carried out by a participant +in a research study. To present the ResearchKit framework UI in your app, instantiate an +object that implements the ORKTask protocol (such as ORKOrderedTask) and +provide it to an ORKTaskViewController object.

+ +

Implement this protocol to enable dynamic selection of the steps for a given task. +By default, ORKOrderedTask implements this protocol for simple sequential tasks.

+ +

Each step (ORKStep) in a task roughly corresponds to one screen, and represents the +primary unit of work in any task presented by a task view controller. For example, +an ORKQuestionStep object corresponds to a single question presented on screen, +together with controls the participant uses to answer the question. Another example is ORKFormStep, which corresponds to a single +screen that displays multiple questions or items for which participants provide information, such as first name, last name, and birth date.

+ +

Each step corresponds to one +ORKStepViewController object, which may manage child view controllers in a particular +sequence. The correspondence of step to view controller holds even though some steps, such as ORKVisualConsentStep and +ORKConsentReviewStep, can produce multiple screens.

+
+ + + + + +
+ + + + + + +
+
+ +

  identifier +required method

+ +
+
+ +
+ + +
+

The unique identifier for this task.

+
+ + + +
@property (nonatomic, copy, readonly) NSString *identifier
+ + + + + + + + + +
+

Discussion

+

The identifier should be a short string that identifies the task. The identifier is copied +into the ORKTaskResult objects generated by the task view controller for this +task. You can use a human-readable string for the task identifier +or a UUID; the exact string you use depends on your app.

+ +

In the case of apps whose tasks come from a server, the unique +identifier for the task may be in an external database.

+ +

The task view controller uses the identifier when constructing the task result. +The identifier can also be used during UI state restoration to identify the +task that needs to be restored.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepAfterStep:withResult: +required method

+ +
+
+ +
+ + + + +
- (nullable ORKStep *)stepAfterStep:(nullable ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepBeforeStep:withResult: +required method

+ +
+
+ +
+ + + + +
- (nullable ORKStep *)stepBeforeStep:(nullable ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– stepWithIdentifier: +

+ +
+
+ +
+ + +
+

Returns the step that matches the specified identifier.

+
+ + + +
- (nullable ORKStep *)stepWithIdentifier:(NSString *)identifier
+ + + +
+

Parameters

+ + + + + + + +
identifier

The identifier of the step to restore.

+
+ + + +
+

Return Value

+

The step that matches the specified identifier.

+
+ + + + + +
+

Discussion

+

Implementing this method allows state restoration of a task +to a particular step. If you don’t implement this method, ORKTaskViewController restores the state +to the first step of the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– progressOfCurrentStep:withResult: +

+ +
+
+ +
+ + + + +
- (ORKTaskProgress)progressOfCurrentStep:(ORKStep *)step withResult:(ORKTaskResult *)result
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

– validateParameters +

+ +
+
+ +
+ + +
+

Validates the task parameters.

+
+ + + +
- (void)validateParameters
+ + + + + + + + + +
+

Discussion

+

The implementation of this method should check that all the task parameters are correct. An invalid task +is considered an unrecoverable error: the implementation should throw an exception on parameter validation failure. +For example, the ORKOrderedTask implementation makes sure that all its step identifiers are unique, throwing an +exception otherwise.

+ +

This method is usually called by a task view controller when its task is set.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

  requestedHealthKitTypesForReading +

+ +
+
+ +
+ + +
+

The set of HealthKit types that steps in the task need to be able to +read. (read-only)

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSSet<HKObjectType*> *requestedHealthKitTypesForReading
+ + + + + + + + + +
+

Discussion

+

The value of this property is a set of HKObjectType values to request for reading from HealthKit during this task. After the last of the initial instruction steps, the task view controller +requests access to these HealthKit types.

+ +

To set this property, you can scan the steps in the task +and collate the HealthKit types that are requested by each active step, question, or +form step that has a Health answer format, and then include any additional types known +to be required. (Note that ORKOrderedTask does something similar for this property.)

+ +

See also: requestedHealthKitTypesForWriting.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

  requestedHealthKitTypesForWriting +

+ +
+
+ +
+ + +
+

The set of HealthKit types for which the task needs to request write access.

+
+ + + +
@property (nonatomic, copy, readonly, nullable) NSSet<HKObjectType*> *requestedHealthKitTypesForWriting
+ + + + + + + + + +
+

Discussion

+

The requested HKObjectType values for writing can be returned by an extended task, +to request write access to these HealthKit types together with the read access +requested by the task view controller by calling requestedHealthKitTypesForReading.

+ +

See also: requestedHealthKitTypesForReading.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

  requestedPermissions +

+ +
+
+ +
+ + +
+

The set of permissions requested by the task.

+
+ + + +
@property (nonatomic, readonly) ORKPermissionMask requestedPermissions
+ + + + + + + + + +
+

Discussion

+

By default in ORKOrderedTask object, these permissions are collected from the +recorder configurations associated with the active steps in the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+ +

  providesBackgroundAudioPrompts +

+ +
+
+ +
+ + +
+

A Boolean value indicating whether this task involves spoken audio prompts. (read-only)

+
+ + + +
@property (nonatomic, readonly) BOOL providesBackgroundAudioPrompts
+ + + + + + + + + +
+

Discussion

+

If the value of this property is YES, the shared AVAudioSession is configured for playback in the background. +The audio UIBackgroundMode value must be set in the application’s Info.plist file +for this to be effective.

+ +

By default, this property looks for active steps that have +audio prompts or count down enabled, and returns YES if such steps exist in +the task.

+
+ + + + + + + +
+

Declared In

+

ORKTask.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskResultSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskResultSource.html new file mode 100755 index 0000000..48226fa --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskResultSource.html @@ -0,0 +1,264 @@ + + + + + + ORKTaskResultSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTaskResultSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKCollectionResult.h
+ + + + +
+ +

Overview

+

ORKTaskResultSource is the protocol for [ORKTaskViewController defaultResultSource].

+
+ + + + + +
+ + + + + + +
+
+ +

– stepResultForStepIdentifier: +required method

+ +
+
+ +
+ + +
+

Returns a step result for the specified step identifier, if one exists.

+
+ + + +
- (nullable ORKStepResult *)stepResultForStepIdentifier:(NSString *)stepIdentifier
+ + + +
+

Parameters

+ + + + + + + +
stepIdentifier

The identifier for which to search.

+
+ + + +
+

Return Value

+

The result for the specified step, or nil for none.

+
+ + + + + +
+

Discussion

+

When it’s about to present a step, the task view controller needs to look up a +suitable default answer. The answer can be used to prepopulate a survey with +the results obtained on a previous run of the same task, by passing an +ORKTaskResult object (which itself implements this protocol).

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+ +

– alwaysCheckForDefaultResult +

+ +
+
+ +
+ + +
+

Should the default result store be used even if there is a previous result? (due to +reverse navigation or looping)

+
+ + + +
- (BOOL)alwaysCheckForDefaultResult
+ + + + + +
+

Return Value

+

YES if the default result should be given priority over the previous result.

+
+ + + + + +
+

Discussion

+

By default, the [ORKTaskViewController defaultResultSource] is only queried for a +result if the previous result is nil. This allows the result source to override that +default behavior.

+
+ + + + + + + +
+

Declared In

+

ORKCollectionResult.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskViewControllerDelegate.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskViewControllerDelegate.html new file mode 100755 index 0000000..a1ba48c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKTaskViewControllerDelegate.html @@ -0,0 +1,945 @@ + + + + + + ORKTaskViewControllerDelegate Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKTaskViewControllerDelegate Protocol Reference

+ + +
+ + + + + + + +
Conforms toNSObject
Declared inORKTaskViewController.h
+ + + + +
+ +

Overview

+

The task view controller delegate is responsible for processing the results +of the task, exerting some control over how the controller behaves, and providing +auxiliary content as needed.

+
+ + + + + +
+ + + + + + +
+
+ +

– taskViewController:didFinishWithReason:error: +required method

+ +
+
+ +
+ + +
+

Tells the delegate that the task has finished.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController didFinishWithReason:(ORKTaskViewControllerFinishReason)reason error:(nullable NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskViewController

The ORKTaskViewControllerinstance that is returning the result.

reason

An ORKTaskViewControllerFinishReason value indicating how the user chose to complete the task.

error

If failure occurred, an NSError object indicating the reason for the failure. The value of this parameter is nil if result does not indicate failure.

+
+ + + + + + + +
+

Discussion

+

The task view controller calls this method when an unrecoverable error occurs, +when the user has canceled the task (with or without saving), or when the user +completes the last step in the task.

+ +

In most circumstances, the receiver should dismiss the task view controller +in response to this method, and may also need to collect and process the results +of the task.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:recorder:didFailWithError: +

+ +
+
+ +
+ + +
+

Signals that an error has been detected by a recorder.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController recorder:(ORKRecorder *)recorder didFailWithError:(NSError *)error
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

recorder

The recorder that detected the error. ORKStep and ORKRecorderConfiguration objects can be found in the recorder instance.

error

The error that was detected.

+
+ + + + + + + +
+

Discussion

+

Recorder errors can occur during active steps, typically because sensor data is unavailable or there isn’t enough disk space to record the results. +You can use this method as an opportunity to respond to the error by, for example, logging and ignoring it.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewControllerSupportsSaveAndRestore: +

+ +
+
+ +
+ + +
+

Asks the delegate if the state of the current uncompleted task should be saved.

+
+ + + +
- (BOOL)taskViewControllerSupportsSaveAndRestore:(ORKTaskViewController *)taskViewController
+ + + +
+

Parameters

+ + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

+
+ + + +
+

Return Value

+

YES if save and restore should be supported; otherwise, NO.

+
+ + + + + +
+

Discussion

+

The task view controller calls this method to determine whether to offer +a save option when the user attempts to cancel a task that is in progress.

+ +

If this method is not implemented, the task view controller assumes that save and restore are not supported. +If this method returns YES, it’s recommended that you copy the value of the restorationData property of the +task view controller and pass that data to initWithTask:restorationData: when it is time +to create a new task view controller to continue from the point at which the user stopped.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewControllerShouldConfirmCancel: +

+ +
+
+ +
+ + +
+

Asks the delegate if the cancel action should be confirmed

+
+ + + +
- (BOOL)taskViewControllerShouldConfirmCancel:(ORKTaskViewController *)taskViewController
+ + + +
+

Parameters

+ + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

+
+ + + +
+

Return Value

+

YES to confirm cancel action; NO to immediately discard the results.

+
+ + + + + +
+

Discussion

+

The task view controller calls this method to determine whether or not to confirm +result save or discard when user attempts to cancel a task that is in progress.

+ +

If this method is not implemented, the task view controller assumes that cancel should be confirmed. +If this method returns YES, then cancel action will be confirmed. +If this method returns NO, then the results will immediately be discarded.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:hasLearnMoreForStep: +

+ +
+
+ +
+ + +
+

Asks the delegate if there is Learn More content for this step.

+
+ + + +
- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController hasLearnMoreForStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

step

The step for which the task view controller needs to know if there is Learn More content.

+
+ + + +
+

Return Value

+

NO if there is no Learn More content to display.

+
+ + + + + +
+

Discussion

+

The task view controller calls this method to determine whether a +Learn More button should be displayed for the step.

+ +

The standard templates in ResearchKit for all types of steps include a button +labeled Learn More (or a variant). In consent steps, this is internal to +the implementations of the step and step view controller, but in all other steps, +the task view controller asks its delegate to determine if Learn More content is available, +and to request that it be displayed.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:learnMoreForStep: +

+ +
+
+ +
+ + +
+

Tells the delegate that the user has tapped the Learn More button in the step.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController learnMoreForStep:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

stepViewController

The ORKStepViewController that reported the Learn More event to the task view controller.

+
+ + + + + + + +
+

Discussion

+

The standard templates in ResearchKit for all types of steps include a button +labeled Learn More (or a variant). In consent steps this is internal to +the implementations of the step and step view controller, but in all other steps, +the task view controller asks its delegate to determine if Learn More content is available.

+ +

This method is called only if the delegate returns YES to +taskViewController:hasLearnMoreForStep: for the current step, and the user +subsequently taps on the Learn More button.

+ +

When this method is called, the app should respond to the Learn More action by +presenting a dialog or other view (possibly modal) that contains the Learn More content.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:viewControllerForStep: +

+ +
+
+ +
+ + +
+

Asks the delegate for a custom view controller for the specified step.

+
+ + + +
- (nullable ORKStepViewController *)taskViewController:(ORKTaskViewController *)taskViewController viewControllerForStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

step

The step for which a view controller is requested.

+
+ + + +
+

Return Value

+

A custom view controller, or nil to request the default step controller for this step.

+
+ + + + + +
+

Discussion

+

If this method is implemented, the task view controller calls it to obtain a +step view controller for the step.

+ +

In most circumstances, the task view controller +can determine which view controller to instantiate for a step. However, if +you want to provide a specific view controller instance, you can call this method to do so.

+ +

The delegate should provide a step view controller implementation for any custom step.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:shouldPresentStep: +

+ +
+
+ +
+ + +
+

Asks the delegate if the task view controller should proceed to the specified step.

+
+ + + +
- (BOOL)taskViewController:(ORKTaskViewController *)taskViewController shouldPresentStep:(ORKStep *)step
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

step

The step for which presentation is requested.

+
+ + + +
+

Return Value

+

YES if navigation should proceed to the specified step; NO if navigation should not proceed.

+
+ + + + + +
+

Discussion

+

The task view controller calls this method before creating a step view +controller for the next or previous step.

+ +

Generally, when a step is available, the task view controller presents it when +the user taps a forward or backward navigation button, but the results entered or other circumstances can make this action inappropriate. In these +circumstances, you can implement this delegate method and return NO.

+ +

If you return NO, it’s often appropriate to present a dialog or take +some other UI action to explain why navigation was denied.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:stepViewControllerWillAppear: +

+ +
+
+ +
+ + +
+

Tells the delegate that a step view controller is about to be displayed.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillAppear:(ORKStepViewController *)stepViewController
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

stepViewController

The ORKStepViewController that is about to be displayed.

+
+ + + + + + + +
+

Discussion

+

The task view controller calls this method before presenting the step +view controller.

+ +

This method gives you an opportunity to modify the step view controller before presentation. +For example, you might want to modify the learnMoreButtonTitle or continueButtonTitle +properties, or modify other button state. Another possible use case is when a particular +step view controller requires additional setup before presentation.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:stepViewControllerWillDisappear:navigationDirection: +

+ +
+
+ +
+ + +
+

Tells the delegate that a step will disappear.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController stepViewControllerWillDisappear:(ORKStepViewController *)stepViewController navigationDirection:(ORKStepViewControllerNavigationDirection)direction
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

stepViewController

The ORKStepViewController that has just finished.

direction

The ORKStepViewControllerNavigationDirection of navigation.

+
+ + + + + + + +
+

Discussion

+

This is called in the ORKStepViewControllerDelegate method for stepViewController:didFinishWithNavigationDirection: +after saving the result of the step to the task view controller and before navigating to the next/previous step.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+ +

– taskViewController:didChangeResult: +

+ +
+
+ +
+ + +
+

Tells the delegate that the result has substantively changed.

+
+ + + +
- (void)taskViewController:(ORKTaskViewController *)taskViewController didChangeResult:(ORKTaskResult *)result
+ + + +
+

Parameters

+ + + + + + + + + + + + +
taskViewController

The calling ORKTaskViewController instance.

result

The current value of the result.

+
+ + + + + + + +
+

Discussion

+

The task view controller calls this method when steps start or finish, or if an answer has +changed in the current step due to editing or other user interaction.

+
+ + + + + + + +
+

Declared In

+

ORKTaskViewController.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueCollectionType.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueCollectionType.html new file mode 100755 index 0000000..3489636 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueCollectionType.html @@ -0,0 +1,180 @@ + + + + + + ORKValueCollectionType Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueCollectionType Protocol Reference

+ + +
+ + + + +
Declared inORKChartTypes.h
+ + + + +
+ +

Overview

+

Defines the common attributes of chart values.

+
+ + + + + +
+ + + + + + +
+
+ +

  isUnset +required method

+ +
+
+ +
+ + +
+

A Boolean value indicating that the value is unset. (read-only)

+
+ + + +
@property (nonatomic, readonly) BOOL isUnset
+ + + + + + + + + + + + + + + +
+

Declared In

+

ORKChartTypes.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueRangeGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueRangeGraphChartViewDataSource.html new file mode 100755 index 0000000..b6fe6e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueRangeGraphChartViewDataSource.html @@ -0,0 +1,216 @@ + + + + + + ORKValueRangeGraphChartViewDataSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueRangeGraphChartViewDataSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toORKGraphChartViewDataSource
Declared inORKGraphChartView.h
+ + + + +
+ +

Overview

+

An object that adopts the ORKValueRangeGraphChartViewDataSource protocol is responsible for +providing data in the form of ORKValueRange values required to populate an +ORKValueRangeGraphChartView concrete subclass, such as ORKLineGraphChartView and +ORKDiscreteGraphChartView.

+
+ + + + + +
+ + + + + + +
+
+ +

– graphChartView:dataPointForPointIndex:plotIndex: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the value range to be plotted at the specified point index for the +specified plot.

+
+ + + +
- (ORKValueRange *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
graphChartView

The graph chart view that is asking for the value range.

pointIndex

An index number identifying the value range in the graph chart view.

plotIndex

An index number identifying the plot in the graph chart view. This index + is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The value range specified by pointIndex in the plot specified by plotIndex for the +specified graph chart view`.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueStackGraphChartViewDataSource.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueStackGraphChartViewDataSource.html new file mode 100755 index 0000000..2ed202f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/Protocols/ORKValueStackGraphChartViewDataSource.html @@ -0,0 +1,215 @@ + + + + + + ORKValueStackGraphChartViewDataSource Protocol Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ORKValueStackGraphChartViewDataSource Protocol Reference

+ + +
+ + + + + + + +
Conforms toORKGraphChartViewDataSource
Declared inORKGraphChartView.h
+ + + + +
+ +

Overview

+

An object that adopts the ORKValueStackGraphChartViewDataSource protocol is responsible for +providing data in the form of ORKValueStack values required to populate an ORKBarGraphChartView +object.

+
+ + + + + +
+ + + + + + +
+
+ +

– graphChartView:dataPointForPointIndex:plotIndex: +required method

+ +
+
+ +
+ + +
+

Asks the data source for the value stack to be plotted at the specified point index for the +specified plot.

+
+ + + +
- (ORKValueStack *)graphChartView:(ORKGraphChartView *)graphChartView dataPointForPointIndex:(NSInteger)pointIndex plotIndex:(NSInteger)plotIndex
+ + + +
+

Parameters

+ + + + + + + + + + + + + + + + + +
graphChartView

The graph chart view that is asking for the value stack.

pointIndex

An index number identifying the value stack in the graph chart view.

plotIndex

An index number identifying the plot in the graph chart view. This index +is 0 in a single-plot graph chart view.

+
+ + + +
+

Return Value

+

The value stack specified by pointIndex in the plot specified by plotIndex for the +specified graph chart view`.

+
+ + + + + + + + + + + +
+

Declared In

+

ORKGraphChartView.h

+
+ + +
+
+
+
+ +
+ + + + + + +
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_index.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_index.scss new file mode 100755 index 0000000..6a57ec5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_index.scss @@ -0,0 +1,17 @@ +.index-container { + -webkit-flex-direction: column; + flex-direction: column; + + @media (min-width: $desktop-min-width) { + display: flex; + -webkit-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + } + + .index-column { + -webkit-flex: 1 1 33%; + flex: 1 1 33%; + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_layout.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_layout.scss new file mode 100755 index 0000000..da46aef --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_layout.scss @@ -0,0 +1,302 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; + + @media (max-width: $mobile-max-width) { + background-color: $content-background; + } +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + #header-buttons { + background: rgba(255, 255, 255, .8); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: pointer; + padding: 0 10px; + } + + label, select { + cursor: inherit; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + border: none; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_normalize.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_normalize.scss new file mode 100755 index 0000000..9b8848a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_object.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_object.scss new file mode 100755 index 0000000..22eebd8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_print.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_print.scss new file mode 100755 index 0000000..61bdf99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_variables.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_variables.scss new file mode 100755 index 0000000..38e072d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_variables.scss @@ -0,0 +1,12 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; +$desktop-min-width: 768px; \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_xcode.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_xcode.scss new file mode 100755 index 0000000..340b1f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/style.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/style.scss new file mode 100755 index 0000000..648a608 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/style.css b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/style.css new file mode 100755 index 0000000..d9d59dd --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/css/style.css @@ -0,0 +1,2 @@ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{box-sizing:border-box}.clear{clear:both}.clearfix:before,.container:before,article #content:before,article #content footer:before,.clearfix:after,.container:after,article #content:after,article #content footer:after{clear:both;display:table;content:""}.xcode .hide-in-xcode{display:none}body{font:62.5% -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;background:#f2f2f2}@media (max-width: 650px){body{background-color:#fff}}h1,h2,h3{font-weight:300;color:#808080}h1{font-size:2em;color:#000}h4{font-size:13px;line-height:1.5;margin:21px 0 0 0}a{color:#08c;text-decoration:none}pre,code{font-family:"Source Code Pro",Monaco,Menlo,Consolas,monospace;word-wrap:break-word}pre>code,.method-declaration code{display:inline-block;font-size:.85em;padding:4px 0 4px 10px;border-left:5px solid rgba(0,155,51,0.2)}pre>code:before,.method-declaration code:before{content:"Objective-C";display:block;font:9px/1 -apple-system-font,"Helvetica Neue",Helvetica,sans-serif;color:#009b33;text-transform:uppercase;letter-spacing:2px;padding-bottom:6px}pre>code{font-size:inherit}table,th,td{border:1px solid #e9e9e9}table{width:100%}th,td{padding:7px}th>:first-child,td>:first-child{margin-top:0}th>:last-child,td>:last-child{margin-bottom:0}.container{max-width:980px;padding:0 10px;margin:0 auto}@media (max-width: 650px){.container{padding:0}}header{position:fixed;top:0;left:0;width:100%;z-index:2;background:#414141;color:#fff;font-size:1.1em;line-height:25px;letter-spacing:.05em}header #library-title{float:left}header #developer-home{float:right}header h1{font-size:inherit;font-weight:inherit;margin:0}header p{margin:0}header h1,header a{color:inherit}@media (max-width: 650px){header .container{padding:0 10px}}aside{position:fixed;top:25px;left:0;width:100%;height:25px;z-index:2;font-size:1.1em}aside #header-buttons{background:rgba(255,255,255,0.8);margin:0 1px;padding:0;list-style:none;text-align:right;line-height:32px}aside #header-buttons li{display:inline-block;cursor:pointer;padding:0 10px}aside #header-buttons label,aside #header-buttons select{cursor:inherit}aside #header-buttons #on-this-page{position:relative}aside #header-buttons #on-this-page .chevron{display:inline-block;width:14px;height:4px;position:relative}aside #header-buttons #on-this-page .chevron .chevy{background:#878787;height:2px;position:absolute;width:10px}aside #header-buttons #on-this-page .chevron .chevy.chevron-left{left:0;transform:rotateZ(45deg) scale(0.6)}aside #header-buttons #on-this-page .chevron .chevy.chevron-right{right:0;transform:rotateZ(-45deg) scale(0.6)}aside #header-buttons #on-this-page #jump-to{opacity:0;font-size:16px;position:absolute;top:5px;left:0;width:100%;height:100%}article{margin-top:25px}article #content{background:#fff;border:1px solid #e9e9e9;padding:15px 25px 30px 25px;font-size:1.4em;line-height:1.45;position:relative}@media (max-width: 650px){article #content{padding:15px 10px 20px 10px;border:none}}article #content .navigation-top{position:absolute;top:15px;right:25px}article #content .title{margin:21px 0 0 0;padding:15px 0}article #content p{color:#414141;margin:0 0 15px 0}article #content th p:last-child,article #content td p:last-child{margin-bottom:0}article #content main ul{list-style:none;margin-left:24px;margin-bottom:12px;padding:0}article #content main ul li{position:relative;padding-left:1.3em}article #content main ul li:before{content:"\02022";color:#414141;font-size:1.08em;line-height:1;position:absolute;left:0;padding-top:2px}article #content footer .footer-copyright{margin:70px 25px 10px 0}article #content footer p{font-size:.71em;color:#a0a0a0}.index-container{-webkit-flex-direction:column;flex-direction:column}@media (min-width: 768px){.index-container{display:flex;-webkit-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;flex-wrap:wrap}}.index-container .index-column{-webkit-flex:1 1 33%;flex:1 1 33%}.section-specification table{width:auto}.section-specification table th{text-align:left}.method-title{margin-left:-15px;margin-bottom:8px;transition:margin-left .3s ease-out}.section-method.hide .method-title{margin-left:0}.method-title code{font-weight:400;font-size:.85em}.method-info{background:#f9f9f9;border-bottom:1px solid #e9e9e9;margin:0 -25px;padding:20px 25px 0 25px;transition:height .3s ease-out;position:relative}.method-info .pointy-thing{background:#fff;height:10px;border-bottom:1px solid #e9e9e9;margin:-20px -25px 16px -25px}.method-info .pointy-thing:before{display:inline-block;content:"";background:#f9f9f9;border:1px solid #e9e9e9;border-bottom:0;border-right:0;position:absolute;left:21px;top:3px;width:12px;height:12px;-webkit-transform:rotate(45deg);transform:rotate(45deg) }.method-info .method-subsection{margin-bottom:15px}.method-info .method-subsection .argument-name{width:1px;text-align:right}.method-info .method-subsection .argument-name code{color:#808080;font-style:italic;font-weight:400}.section-method.hide .method-info{height:0 !important;overflow:hidden;display:none}.section-method.hide.animating .method-info{display:block}.section-method.animating .method-info{overflow:hidden}@media print{body{background:#fff;padding:8px}header{position:static;background:#fff;color:#000}aside{display:none}.container{max-width:none;padding:0}article{margin-top:0}article #content{border:0;background:#fff;padding:15px 0 0 0}article #content .title{margin-top:0;padding-top:0}.method-info,.method-info .pointy-thing{background:#fff}}.xcode header,.xcode aside{display:none}.xcode .container{padding:0}.xcode article{margin-top:0}.xcode article #content{border:0;margin:0}.xcode .method-info,.section-method.hide .xcode .method-info{max-height:auto;overflow:visible}.xcode .method-info.hiding,.section-method.hide .xcode .method-info.hiding{display:block} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/hierarchy.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/hierarchy.html new file mode 100755 index 0000000..419259d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/hierarchy.html @@ -0,0 +1,974 @@ + + + + + + ResearchKit Hierarchy + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ResearchKit Hierarchy

+ + +
+

Class Hierarchy

+ + + +
+ + + +
+ +

Protocol References

+ + + +

Constant References

+ + + +

Category References

+ + +
+ + + +
+
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/button_bar_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/button_bar_background.png new file mode 100755 index 0000000..71d1019 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/button_bar_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure.png new file mode 100755 index 0000000..4c5cbf4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure_open.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure_open.png new file mode 100755 index 0000000..82396fe Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/disclosure_open.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/library_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/library_background.png new file mode 100755 index 0000000..3006248 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/library_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/title_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/title_background.png new file mode 100755 index 0000000..846e496 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/img/title_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/index.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/index.html new file mode 100755 index 0000000..18b7711 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/index.html @@ -0,0 +1,811 @@ + + + + + + ResearchKit Reference + + + + + + +
+
+ +

+ ResearchKit +

+ +

+ ResearchKit +

+ +
+
+ + + +
+
+
+
+

ResearchKit Reference

+ + +
+ + +

The ResearchKit™ framework is an open source framework that developers and researchers can use to create apps that let iOS users participate in medical research.

+ +

This is the API documentation for the ResearchKit framework. For an overview of framework and a more general guide to using and extending the framework, see the Programming Guide.

+ +

Constructing Tasks

+ +

ResearchKit tasks are actions to be performed by participants in a research study. Tasks are the building blocks for ResearchKit modules, which address the most common components of medical studies: surveys, consent documents, and active tasks.

+ +

Tasks are constructed using a hierarchy of model objects. +At the root of the hierarchy is an ORKOrderedTask object (or another object that implements the ORKTask protocol). The task defines the order in which steps are presented, and how progress through the task is represented.

+ +

A task consists of steps, which are subclasses of ORKStep. Most steps are designed for data presentation or data entry, but the ORKActiveStep subclasses can also enable data collection. +The ORKQuestionStep and ORKFormStep survey step classes describe a question to be asked. The format of the answer is modeled with subclasses of ORKAnswerFormat.

+ +

Presenting Tasks

+ +

To present a task, you create an ORKTaskViewController object and give it the task. The task view controller manages the task and returns the result through delegate methods.

+ +

For each step, ORKTaskViewController instantiates an appropriate subclass of ORKStepViewController to display the step.

+ +

Getting Results

+ +

The result property of ORKTaskViewController provides the results of the task, both while the task is in progress, and upon completion of the task.

+ +

Results are constructed with a hierarchy that’s similar to the task model hierarchy. In the hierarchy for a result, ORKTaskResult is the root and ORKStepResult objects form the immediate children.

+ +

For survey question steps, the answers collected are reported as ORKQuestionResult objects, which are children of ORKStepResult. Active steps may include additional result objects as children, depending on the types of data that are recorded. To help you get data from various device features, such as the accelerometer or HealthKit, the ResearchKit framework provides the ORKRecorder and ORKRecorderConfiguration classes, which work together to collect and configure data into a serialized format during the duration of an active step.

+ +

Predefined Active Tasks

+ +

An active task invites users to perform activities under semi-controlled conditions, while iPhone sensors actively collect data. A category on ORKOrderedTask provides factory methods for generating ORKOrderedTask instances that correspond to ResearchKit’s predefined active tasks, such as the short walk or fitness task.

+ +

Consent

+ +

The consent features in the ResearchKit framework are implemented using three special steps that can be added to tasks:

+ +
    +
  • ORKVisualConsentStep. The visual consent step presents a series of simple graphics to help participants understand the content of an consent document. The default graphics have animated transitions.

  • +
  • ORKConsentSharingStep. The consent sharing step has predefined transitions that can be used to establish user preferences regarding how widely personal data can be shared.

  • +
  • ORKConsentReviewStep. The consent review step makes the consent document available for review, and provides facilities for collecting the user’s name and signature.

  • +
+ + +

Creating the visual consent step and the consent review step requires a consent document model (that is, an ORKConsentDocument object).

+ + +
+ + +
+ + + +
+

Class References

+ +
+ + + +
+ +

Protocol References

+ + + + +

Constant References

+ + + + +

Category References

+ + +
+ +
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/js/script.js b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/js/script.js new file mode 100755 index 0000000..4074361 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/Documents/js/script.js @@ -0,0 +1,59 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + if (element.classList.contains("hide")) { + e.preventDefault(); + } + setTimeout(function() { + element.classList.remove("animating"); + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx new file mode 100755 index 0000000..cb9880b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-shm b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-shm new file mode 100755 index 0000000..c9397da Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-shm differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-wal b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-wal new file mode 100755 index 0000000..cc9ac32 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.dsidx-wal differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.mom b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.mom new file mode 100755 index 0000000..762bdf0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.mom differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.skidx b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.skidx new file mode 100755 index 0000000..95bd552 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.skidx differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.toc b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.toc new file mode 100755 index 0000000..312c1d0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.toc differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.tokencache b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.tokencache new file mode 100755 index 0000000..4e31554 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/org.researchkit.ResearchKit.docset/Contents/Resources/docSet.tokencache differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/Documents/documents-template b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/Documents/documents-template new file mode 100755 index 0000000..078aab9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/Documents/documents-template @@ -0,0 +1 @@ +This is used only as placeholder for location of Documents directory! \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/nodes-template.xml b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/nodes-template.xml new file mode 100755 index 0000000..2db5e40 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/nodes-template.xml @@ -0,0 +1,131 @@ + + + + + {{projectName}} + {{indexFilename}} + + {{#hasDocs}} + + {{strings.docset.docsTitle}} + {{indexFilename}} + + {{#docs}}{{>NodeRef}} + {{/docs}} + + + {{/hasDocs}} + {{#hasClasses}} + + {{strings.docset.classesTitle}} + {{indexFilename}} + + {{#classes}}{{>NodeRef}} + {{/classes}} + + + {{/hasClasses}} + {{#hasCategories}} + + {{strings.docset.categoriesTitle}} + {{indexFilename}} + + {{#categories}}{{>NodeRef}} + {{/categories}} + + + {{/hasCategories}} + {{#hasProtocols}} + + {{strings.docset.protocolsTitle}} + {{indexFilename}} + + {{#protocols}}{{>NodeRef}} + {{/protocols}} + + + {{/hasProtocols}} + {{#hasConstants}} + + {{strings.docset.constantsTitle}} + {{indexFilename}} + + {{#constants}}{{>NodeRef}} + {{/constants}} + + + {{/hasConstants}} + {{#hasBlocks}} + + {{strings.docset.blocksTitle}} + {{indexFilename}} + + {{#blocks}}{{>NodeRef}} + {{/blocks}} + + + {{/hasBlocks}} + + + + + {{#docs}}{{>Node}} + {{/docs}} + {{#classes}}{{>Node}} + {{/classes}} + {{#categories}}{{>Node}} + {{/categories}} + {{#protocols}}{{>Node}} + {{/protocols}} + {{#constants}}{{>Node}} + {{/constants}} + {{#blocks}}{{>Node}} + {{/blocks}} + + + +Section Node + + {{name}} + {{path}} + {{#hasSubNodes}} + + + {{path}} + Overview + overview + + + {{path}} + Tasks + tasks + + {{#hasProperties}} + + {{path}} + Properties + properties + + {{/hasProperties}} + {{#hasClassMethods}} + + {{path}} + Class Methods + class_methods + + {{/hasClassMethods}} + {{#hasInstanceMethods}} + + {{path}} + Instance Methods + instance_methods + + {{/hasInstanceMethods}} + + {{/hasSubNodes}} + +EndSection + +Section NodeRef + +EndSection diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/tokens-template.xml b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/tokens-template.xml new file mode 100755 index 0000000..5ac05c2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/Resources/tokens-template.xml @@ -0,0 +1,93 @@ + + + + {{#object}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{>DeclaredIn}} + {{>Availability}} + {{>RelatedTokens}} + {{#refid}}{{/refid}} + + {{/object}} + {{#members}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>MethodDeclaration}} + {{#hasParameters}} + {{#parameters}} + {{name}} + {{>Abstract}} + {{/parameters}} + {{/hasParameters}} + {{#returnValue}}{{>Abstract}}{{/returnValue}} + {{#anchor}}{{anchor}}{{/anchor}} + {{#refid}}{{/refid}} + + {{/members}} + {{#constants}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{declaration}} + {{>Availability}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>Reference}} + + {{/constants}} + {{#blocks}} + + {{>TokenIdentifier}} + {{>Abstract}} + {{declaration}} + {{>Availability}} + {{>DeclaredIn}} + {{>RelatedTokens}} + {{>Reference}} + + {{/blocks}} + + + +Section TokenIdentifier + {{identifier}} +EndSection + +Section DeclaredIn + {{declaredin}} +EndSection + +Section RelatedTokens + {{#hasRelatedTokens}} + + {{#relatedTokens}}{{.}} + {{/relatedTokens}} + + {{/hasRelatedTokens}} +EndSection + +Section Abstract +{{#abstract}}{{>GBCommentComponentsList}}{{/abstract}} +EndSection + +Section Availability +{{#availability}}{{>GBCommentComponentsList}}{{/availability}} +EndSection + +Section Reference +{{#refid}}{{/refid}} +EndSection + +Section MethodDeclaration +{{#formattedComponents}}{{value}}{{/formattedComponents}} +EndSection + +Section GBCommentComponentsList +{{#components}}{{textValue}}{{/components}} +EndSection + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/info-template.plist b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/info-template.plist new file mode 100755 index 0000000..26de471 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/docset/Contents/info-template.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + {{#bundleIdentifier}}CFBundleIdentifier + {{bundleIdentifier}}{{/bundleIdentifier}} + {{#bundleName}}CFBundleName + {{bundleName}}{{/bundleName}} + {{#bundleVersion}}CFBundleShortVersionString + {{bundleVersion}} + CFBundleVersion + {{bundleVersion}}{{/bundleVersion}} + {{#certificateIssuer}}DocSetCertificateIssuer + {{certificateIssuer}}{{/certificateIssuer}} + {{#certificateSigner}}DocSetCertificateSigner + {{certificateSigner}}{{/certificateSigner}} + {{#description}}DocSetDescription + {{description}}{{/description}} + {{#fallbackURL}}DocSetFallbackURL + {{fallbackURL}}{{/fallbackURL}} + {{#feedName}}DocSetFeedName + {{feedName}}{{/feedName}} + {{#feedURL}}DocSetFeedURL + {{feedURL}}{{/feedURL}} + {{#minimumXcodeVersion}}DocSetMinimumXcodeVersion + {{minimumXcodeVersion}}{{/minimumXcodeVersion}} + {{#platformFamily}}DocSetPlatformFamily + {{platformFamily}}{{/platformFamily}} + {{#dashPlatformFamily}}DashDocSetFamily + {{dashPlatformFamily}}{{/dashPlatformFamily}} + {{#publisherIdentifier}}DocSetPublisherIdentifier + {{publisherIdentifier}}{{/publisherIdentifier}} + {{#publisherName}}DocSetPublisherName + {{publisherName}}{{/publisherName}} + {{#copyrightMessage}}NSHumanReadableCopyright + {{copyrightMessage}}{{/copyrightMessage}} + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_index.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_index.scss new file mode 100755 index 0000000..7e98029 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_index.scss @@ -0,0 +1,13 @@ +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + + @media (max-width: $mobile-max-width) { + flex-direction: column; + } + + .index-column { + flex: 1 1 33%; + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_layout.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_layout.scss new file mode 100755 index 0000000..b69d199 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_layout.scss @@ -0,0 +1,303 @@ +* { + box-sizing: border-box; +} + +.clear { + clear: both; +} + +.clearfix { + &:before, &:after { + clear: both; + display: table; + content: ""; + } +} + +.xcode .hide-in-xcode { + display: none; +} + +body { + font: 62.5% $body-font; + background: $body-background; +} + +h1, h2, h3 { + font-weight: 300; + color: #808080; +} + +h1 { + font-size: 2em; + color: #000; +} + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; +} + +a { + color: $tint-color; + text-decoration: none; +} + +pre, code { + font-family: $code-font; + word-wrap: break-word; +} + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, .2); + + &:before { + content: "Objective-C"; + display: block; + + font: 9px/1 $body-font; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; + } +} + +pre > code { + font-size: inherit; +} + +table, th, td { + border: 1px solid #e9e9e9; +} + +table { + width: 100%; +} + +th, td { + padding: 7px; + + > :first-child { + margin-top: 0; + } + + > :last-child { + margin-bottom: 0; + } +} + +.container { + @extend .clearfix; + + max-width: 980px; + padding: 0 10px; + margin: 0 auto; + + @media (max-width: $mobile-max-width) { + padding: 0; + } +} + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; + + #library-title { + float: left; + } + + #developer-home { + float: right; + } + + h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; + } + + p { + margin: 0; + } + + h1, a { + color: inherit; + } + + @media (max-width: $mobile-max-width) { + position: absolute; + + .container { + padding: 0 10px; + } + } +} + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + + font-size: 1.1em; + + @media (max-width: $mobile-max-width) { + position: absolute; + } + + #header-buttons { + background: rgba(255, 255, 255, .9); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; + + li { + display: inline-block; + cursor: default; + padding: 0 10px; + } + + label, select { + cursor: auto; + } + + #on-this-page { + position: relative; + + .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; + + .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; + + &.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); + } + + &.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); + } + } + } + + #jump-to { + opacity: 0; + font-size: 16px; + + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; + } + } + } +} + +article { + margin-top: 25px; + + #content { + @extend .clearfix; + + background: $content-background; + border: 1px solid $content-border; + padding: 15px 25px 30px 25px; + + font-size: 1.4em; + line-height: 1.45; + + position: relative; + + @media (max-width: $mobile-max-width) { + padding: 15px 10px 20px 10px; + } + + .navigation-top { + position: absolute; + top: 15px; + right: 25px; + } + + .title { + margin: 21px 0 0 0; + padding: 15px 0; + } + + p { + color: #414141; + margin: 0 0 15px 0; + } + + th, td { + p:last-child { + margin-bottom: 0; + } + } + + main { + ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; + + li { + position: relative; + padding-left: 1.3em; + + &:before { + content: "\02022"; + + color: #414141; + font-size: 1.08em; + line-height: 1; + + position: absolute; + left: 0; + padding-top: 2px; + } + } + } + } + + footer { + @extend .clearfix; + + .footer-copyright { + margin: 70px 25px 10px 0; + } + + p { + font-size: .71em; + color: #a0a0a0; + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_normalize.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_normalize.scss new file mode 100755 index 0000000..9b8848a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_normalize.scss @@ -0,0 +1,581 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ + +$legacy_browser_support: false !default; + +/* Base + ========================================================================== */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ + @if $legacy_browser_support { + *font-size: 100%; /* 3 */ + } +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ + @if $legacy_browser_support { + *display: inline; + *zoom: 1; + } +} + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a { + &:active, &:hover { + outline: 0; + }; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +@if $legacy_browser_support { + blockquote { + margin: 1em 40px; + } +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +@if $legacy_browser_support { + h2 { + font-size: 1.5em; + margin: 0.83em 0; + } + + h3 { + font-size: 1.17em; + margin: 1em 0; + } + + h4 { + font-size: 1em; + margin: 1.33em 0; + } + + h5 { + font-size: 0.83em; + margin: 1.67em 0; + } + + h6 { + font-size: 0.67em; + margin: 2.33em 0; + } +} + +/** + * Addresses styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +@if $legacy_browser_support { + + /** + * Addresses margins set differently in IE 6/7. + */ + + p, + pre { + *margin: 1em 0; + } + + /* + * Addresses CSS quotes not supported in IE 6/7. + */ + + q { + *quotes: none; + } + + /* + * Addresses `quotes` property not supported in Safari 4. + */ + + q:before, + q:after { + content: ''; + content: none; + } +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +@if $legacy_browser_support { + + /* ========================================================================== + Lists + ========================================================================== */ + + /* + * Addresses margins set differently in IE 6/7. + */ + + dl, + menu, + ol, + ul { + *margin: 1em 0; + } + + dd { + *margin: 0 0 0 40px; + } + + /* + * Addresses paddings set differently in IE 6/7. + */ + + menu, + ol, + ul { + *padding: 0 0 0 40px; + } + + /* + * Corrects list images handled incorrectly in IE 7. + */ + + nav ul, + nav ol { + *list-style: none; + *list-style-image: none; + } + +} + +/* Embedded content + ========================================================================== */ + +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; + @if $legacy_browser_support { + *-ms-interpolation-mode: bicubic; /* 2 */ + } +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + @if $legacy_browser_support { + _font-family: 'courier new', monospace; + } + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ + @if $legacy_browser_support { + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ + } +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + @if $legacy_browser_support { + *overflow: visible; /* 4 */ + } +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ + } +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ + @if $legacy_browser_support { + white-space: normal; /* 3 */ + *margin-left: -7px; /* 4 */ + } +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_object.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_object.scss new file mode 100755 index 0000000..22eebd8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_object.scss @@ -0,0 +1,89 @@ +.section-specification { + table { + width: auto; + + th { + text-align: left; + } + } +} + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; + + .section-method.hide & { + margin-left: 0; + } + + code { + font-weight: 400; + font-size: .85em; + } +} + +.method-info { + background: $object-background; + border-bottom: 1px solid $object-border; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + + position: relative; + + .pointy-thing { + background: $content-background; + height: 10px; + border-bottom: 1px solid $object-border; + margin: -20px -25px 16px -25px; + + &:before { + display: inline-block; + content: ""; + + background: $object-background; + border: 1px solid $object-border; + border-bottom: 0; + border-right: 0; + + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); + } + } + + .method-subsection { + margin-bottom: 15px; + + .argument-name { + width: 1px; + text-align: right; + + code { + color: #808080; + font-style: italic; + font-weight: 400; + } + } + } +} + +.section-method { + &.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; + } + + &.hide.animating .method-info { + display: block; + } + + &.animating .method-info { + overflow: hidden; + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_print.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_print.scss new file mode 100755 index 0000000..61bdf99 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_print.scss @@ -0,0 +1,42 @@ +@media print { + body { + background: #fff; + padding: 8px; + } + + header { + position: static; + background: #fff; + color: #000; + } + + aside { + display: none; + } + + .container { + max-width: none; + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; + + .title { + margin-top: 0; + padding-top: 0; + } + } + } + + .method-info { + &, & .pointy-thing { + background: #fff; + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_variables.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_variables.scss new file mode 100755 index 0000000..cbaff3c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_variables.scss @@ -0,0 +1,11 @@ +$body-font: -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; +$code-font: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + +$body-background: #f2f2f2; +$content-background: #fff; +$content-border: #e9e9e9; +$tint-color: #08c; +$object-background: #f9f9f9; +$object-border: #e9e9e9; + +$mobile-max-width: 650px; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_xcode.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_xcode.scss new file mode 100755 index 0000000..340b1f6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/_xcode.scss @@ -0,0 +1,29 @@ +.xcode { + header, aside { + display: none; + } + + .container { + padding: 0; + } + + article { + margin-top: 0; + + #content { + border: 0; + margin: 0; + } + } + + .method-info { + &, .section-method.hide & { + max-height: auto; + overflow: visible; + + &.hiding { + display: block; + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/style.scss b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/style.scss new file mode 100755 index 0000000..648a608 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/scss/style.scss @@ -0,0 +1 @@ +@import "variables", "normalize", "layout", "index", "object", "print", "xcode"; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/style.css b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/style.css new file mode 100755 index 0000000..88a1594 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/css/style.css @@ -0,0 +1,690 @@ +/* ========================================================================== + Normalize.scss settings + ========================================================================== */ +/** + * Includes legacy browser support IE6/7 + * + * Set to false if you want to drop support for IE6 and IE7 + */ +/* Base + ========================================================================== */ +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + * 3. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + */ +html { + font-family: sans-serif; + /* 1 */ + -ms-text-size-adjust: 100%; + /* 2 */ + -webkit-text-size-adjust: 100%; + /* 2 */ } + +/** + * Remove default margin. + */ +body { + margin: 0; } + +/* HTML5 display definitions + ========================================================================== */ +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; } + +/** + * 1. Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ +audio, +canvas, +progress, +video { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ +[hidden], +template { + display: none; } + +/* Links + ========================================================================== */ +/** + * Remove the gray background color from active links in IE 10. + */ +a { + background-color: transparent; } + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ +a:active, a:hover { + outline: 0; } + +/* Text-level semantics + ========================================================================== */ +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ +abbr[title] { + border-bottom: 1px dotted; } + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ +b, +strong { + font-weight: bold; } + +/** + * Address styling not present in Safari and Chrome. + */ +dfn { + font-style: italic; } + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari, and Chrome. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/** + * Addresses styling not present in IE 8/9. + */ +mark { + background: #ff0; + color: #000; } + +/** + * Address inconsistent and variable font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +/* Embedded content + ========================================================================== */ +/** + * 1. Remove border when inside `a` element in IE 8/9/10. + * 2. Improves image quality when scaled in IE 7. + */ +img { + border: 0; } + +/** + * Correct overflow not hidden in IE 9/10/11. + */ +svg:not(:root) { + overflow: hidden; } + +/* Grouping content + ========================================================================== */ +/** + * Address margin not present in IE 8/9 and Safari. + */ +figure { + margin: 1em 40px; } + +/** + * Address differences between Firefox and other browsers. + */ +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; } + +/** + * Contain overflow in all browsers. + */ +pre { + overflow: auto; } + +/** + * Address odd `em`-unit font size rendering in all browsers. + * Correct font family set oddly in IE 6, Safari 4/5, and Chrome. + */ +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; } + +/* Forms + ========================================================================== */ +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + * 4. Improves appearance and consistency in all browsers. + */ +button, +input, +optgroup, +select, +textarea { + color: inherit; + /* 1 */ + font: inherit; + /* 2 */ + margin: 0; + /* 3 */ } + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ +button { + overflow: visible; } + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ +button, +select { + text-transform: none; } + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + /* 2 */ + cursor: pointer; + /* 3 */ } + +/** + * Re-set default cursor for disabled elements. + */ +button[disabled], +html input[disabled] { + cursor: default; } + +/** + * Remove inner padding and border in Firefox 4+. + */ +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; } + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ +input { + line-height: normal; } + +/** + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + * Known issue: excess padding remains in IE 6. + */ +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ +input[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + /* 2 */ + box-sizing: content-box; } + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * Define consistent border, margin, and padding. + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + * 3. Corrects text not wrapping in Firefox 3. + * 4. Corrects alignment displayed oddly in IE 6/7. + */ +legend { + border: 0; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ +textarea { + overflow: auto; } + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ +optgroup { + font-weight: bold; } + +/* Tables + ========================================================================== */ +/** + * Remove most spacing between table cells. + */ +table { + border-collapse: collapse; + border-spacing: 0; } + +td, +th { + padding: 0; } + +* { + box-sizing: border-box; } + +.clear { + clear: both; } + +.clearfix:before, .container:before, article #content:before, article #content footer:before, .clearfix:after, .container:after, article #content:after, article #content footer:after { + clear: both; + display: table; + content: ""; } + +.xcode .hide-in-xcode { + display: none; } + +body { + font: 62.5% -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; + background: #f2f2f2; } + +h1, h2, h3 { + font-weight: 300; + color: #808080; } + +h1 { + font-size: 2em; + color: #000; } + +h4 { + font-size: 13px; + line-height: 1.5; + margin: 21px 0 0 0; } + +a { + color: #08c; + text-decoration: none; } + +pre, code { + font-family: "Source Code Pro", Monaco, Menlo, Consolas, monospace; + word-wrap: break-word; } + +pre > code, .method-declaration code { + display: inline-block; + font-size: .85em; + padding: 4px 0 4px 10px; + border-left: 5px solid rgba(0, 155, 51, 0.2); } + pre > code:before, .method-declaration code:before { + content: "Objective-C"; + display: block; + font: 9px/1 -apple-system-font, "Helvetica Neue", Helvetica, sans-serif; + color: #009b33; + text-transform: uppercase; + letter-spacing: 2px; + padding-bottom: 6px; } + +pre > code { + font-size: inherit; } + +table, th, td { + border: 1px solid #e9e9e9; } + +table { + width: 100%; } + +th, td { + padding: 7px; } + th > :first-child, td > :first-child { + margin-top: 0; } + th > :last-child, td > :last-child { + margin-bottom: 0; } + +.container { + max-width: 980px; + padding: 0 10px; + margin: 0 auto; } + @media (max-width: 650px) { + .container { + padding: 0; } } + +header { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 2; + background: #414141; + color: #fff; + font-size: 1.1em; + line-height: 25px; + letter-spacing: .05em; } + header #library-title { + float: left; } + header #developer-home { + float: right; } + header h1 { + font-size: inherit; + font-weight: inherit; + margin: 0; } + header p { + margin: 0; } + header h1, header a { + color: inherit; } + @media (max-width: 650px) { + header { + position: absolute; } + header .container { + padding: 0 10px; } } + +aside { + position: fixed; + top: 25px; + left: 0; + width: 100%; + height: 25px; + z-index: 2; + font-size: 1.1em; } + @media (max-width: 650px) { + aside { + position: absolute; } } + aside #header-buttons { + background: rgba(255, 255, 255, 0.9); + margin: 0 1px; + padding: 0; + list-style: none; + text-align: right; + line-height: 32px; } + aside #header-buttons li { + display: inline-block; + cursor: default; + padding: 0 10px; } + aside #header-buttons label, aside #header-buttons select { + cursor: auto; } + aside #header-buttons #on-this-page { + position: relative; } + aside #header-buttons #on-this-page .chevron { + display: inline-block; + width: 14px; + height: 4px; + position: relative; } + aside #header-buttons #on-this-page .chevron .chevy { + background: #878787; + height: 2px; + position: absolute; + width: 10px; } + aside #header-buttons #on-this-page .chevron .chevy.chevron-left { + left: 0; + transform: rotateZ(45deg) scale(0.6); } + aside #header-buttons #on-this-page .chevron .chevy.chevron-right { + right: 0; + transform: rotateZ(-45deg) scale(0.6); } + aside #header-buttons #on-this-page #jump-to { + opacity: 0; + font-size: 16px; + position: absolute; + top: 5px; + left: 0; + width: 100%; + height: 100%; } + +article { + margin-top: 25px; } + article #content { + background: #fff; + border: 1px solid #e9e9e9; + padding: 15px 25px 30px 25px; + font-size: 1.4em; + line-height: 1.45; + position: relative; } + @media (max-width: 650px) { + article #content { + padding: 15px 10px 20px 10px; } } + article #content .navigation-top { + position: absolute; + top: 15px; + right: 25px; } + article #content .title { + margin: 21px 0 0 0; + padding: 15px 0; } + article #content p { + color: #414141; + margin: 0 0 15px 0; } + article #content th p:last-child, article #content td p:last-child { + margin-bottom: 0; } + article #content main ul { + list-style: none; + margin-left: 24px; + margin-bottom: 12px; + padding: 0; } + article #content main ul li { + position: relative; + padding-left: 1.3em; } + article #content main ul li:before { + content: "\02022"; + color: #414141; + font-size: 1.08em; + line-height: 1; + position: absolute; + left: 0; + padding-top: 2px; } + article #content footer .footer-copyright { + margin: 70px 25px 10px 0; } + article #content footer p { + font-size: .71em; + color: #a0a0a0; } + +.index-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; } + @media (max-width: 650px) { + .index-container { + flex-direction: column; } } + .index-container .index-column { + flex: 1 1 33%; } + +.section-specification table { + width: auto; } + .section-specification table th { + text-align: left; } + +.method-title { + margin-left: -15px; + margin-bottom: 8px; + transition: margin-left .3s ease-out; } + .section-method.hide .method-title { + margin-left: 0; } + .method-title code { + font-weight: 400; + font-size: .85em; } + +.method-info { + background: #f9f9f9; + border-bottom: 1px solid #e9e9e9; + margin: 0 -25px; + padding: 20px 25px 0 25px; + transition: height .3s ease-out; + position: relative; } + .method-info .pointy-thing { + background: #fff; + height: 10px; + border-bottom: 1px solid #e9e9e9; + margin: -20px -25px 16px -25px; } + .method-info .pointy-thing:before { + display: inline-block; + content: ""; + background: #f9f9f9; + border: 1px solid #e9e9e9; + border-bottom: 0; + border-right: 0; + position: absolute; + left: 21px; + top: 3px; + width: 12px; + height: 12px; + transform: rotate(45deg); } + .method-info .method-subsection { + margin-bottom: 15px; } + .method-info .method-subsection .argument-name { + width: 1px; + text-align: right; } + .method-info .method-subsection .argument-name code { + color: #808080; + font-style: italic; + font-weight: 400; } + +.section-method.hide .method-info { + height: 0 !important; + overflow: hidden; + display: none; } +.section-method.hide.animating .method-info { + display: block; } +.section-method.animating .method-info { + overflow: hidden; } + +@media print { + body { + background: #fff; + padding: 8px; } + + header { + position: static; + background: #fff; + color: #000; } + + aside { + display: none; } + + .container { + max-width: none; + padding: 0; } + + article { + margin-top: 0; } + article #content { + border: 0; + background: #fff; + padding: 15px 0 0 0; } + article #content .title { + margin-top: 0; + padding-top: 0; } + + .method-info, .method-info .pointy-thing { + background: #fff; } } +.xcode header, .xcode aside { + display: none; } +.xcode .container { + padding: 0; } +.xcode article { + margin-top: 0; } + .xcode article #content { + border: 0; + margin: 0; } +.xcode .method-info, .section-method.hide .xcode .method-info { + max-height: auto; + overflow: visible; } + .xcode .method-info.hiding, .section-method.hide .xcode .method-info.hiding { + display: block; } + +/*# sourceMappingURL=style.css.map */ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/document-template.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/document-template.html new file mode 100755 index 0000000..adc9090 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/document-template.html @@ -0,0 +1,84 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
+ +
+ + + +
+
+
+
+ + + {{#object.comment}}{{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}}{{/object.comment}} + +
+ +
+
+
+
+
+ + + + + + +Section GBCommentComponentsList +{{#components}}{{>GBCommentComponent}}{{/components}} +EndSection + +Section GBCommentComponent +{{&htmlValue}} +EndSection + +Section Navigation +
  • Home
  • +EndSection diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/hierarchy-template.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/hierarchy-template.html new file mode 100755 index 0000000..8f6753f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/hierarchy-template.html @@ -0,0 +1,119 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#hasClasses}} +
    +

    {{strings.hierarchyPage.classesTitle}}

    + {{>Classes}} +
    + {{/hasClasses}} + + {{#hasProtocolsOrCategories}} +
    + {{#hasProtocols}} +

    {{strings.hierarchyPage.protocolsTitle}}

    +
      + {{#protocols}} +
    • {{title}}
    • + {{/protocols}} +
    + {{/hasProtocols}} + {{#hasConstants}} +

    {{strings.hierarchyPage.constantsTitle}}

    +
      + {{#constants}} +
    • {{title}}
    • + {{/constants}} +
    + {{/hasConstants}} + {{#hasCategories}} +

    {{strings.hierarchyPage.categoriesTitle}}

    +
      + {{#categories}} +
    • {{title}}
    • + {{/categories}} +
    + {{/hasCategories}} +
    + {{/hasProtocolsOrCategories}} + +
    + +
    +
    +
    +
    +
    + + + + + +Section Classes +{{#hasClasses}} + +{{/hasClasses}} +EndSection + +Section Navigation +
  • Home
  • +EndSection diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/button_bar_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/button_bar_background.png new file mode 100755 index 0000000..71d1019 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/button_bar_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure.png new file mode 100755 index 0000000..4c5cbf4 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure_open.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure_open.png new file mode 100755 index 0000000..82396fe Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/disclosure_open.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/library_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/library_background.png new file mode 100755 index 0000000..3006248 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/library_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/title_background.png b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/title_background.png new file mode 100755 index 0000000..846e496 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/img/title_background.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/index-template.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/index-template.html new file mode 100755 index 0000000..57b22e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/index-template.html @@ -0,0 +1,138 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#indexDescription}} +
    + {{#comment}} + {{#hasLongDescription}} + {{#longDescription}}{{#components}}{{&htmlValue}}{{/components}}{{/longDescription}} + {{/hasLongDescription}} + {{/comment}} +
    + {{/indexDescription}} + +
    + {{#hasDocs}} +
    +

    {{strings.indexPage.docsTitle}}

    + +
    + {{/hasDocs}} + + {{#hasClasses}} +
    +

    {{strings.indexPage.classesTitle}}

    +
      + {{#classes}} +
    • {{title}}
    • + {{/classes}} +
    +
    + {{/hasClasses}} + + {{#hasProtocolsOrCategories}} +
    + {{#hasProtocols}} +

    {{strings.indexPage.protocolsTitle}}

    +
      + {{#protocols}} +
    • {{title}}
    • + {{/protocols}} +
    + {{/hasProtocols}} + + {{#hasConstants}} +

    {{strings.indexPage.constantsTitle}}

    +
      + {{#constants}} +
    • {{title}}
    • + {{/constants}} +
    + {{/hasConstants}} + + {{#hasCategories}} +

    {{strings.indexPage.categoriesTitle}}

    +
      + {{#categories}} +
    • {{title}}
    • + {{/categories}} +
    + {{/hasCategories}} +
    + {{/hasProtocolsOrCategories}} +
    + +
    + +
    +
    +
    +
    +
    + + + + + +Section Navigation +
  • Hierarchy
  • +EndSection diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/js/script.js b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/js/script.js new file mode 100755 index 0000000..4074361 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/js/script.js @@ -0,0 +1,59 @@ +function $() { + return document.querySelector.apply(document, arguments); +} + +if (navigator.userAgent.indexOf("Xcode") != -1) { + document.documentElement.classList.add("xcode"); +} + +var jumpTo = $("#jump-to"); + +if (jumpTo) { + jumpTo.addEventListener("change", function(e) { + location.hash = this.options[this.selectedIndex].value; + }); +} + +function hashChanged() { + if (/^#\/\/api\//.test(location.hash)) { + var element = document.querySelector("a[name='" + location.hash.substring(1) + "']"); + + if (!element) { + return; + } + + element = element.parentNode; + + element.classList.remove("hide"); + fixScrollPosition(element); + } +} + +function fixScrollPosition(element) { + var scrollTop = element.offsetTop - 150; + document.documentElement.scrollTop = scrollTop; + document.body.scrollTop = scrollTop; +} + +[].forEach.call(document.querySelectorAll(".section-method"), function(element) { + element.classList.add("hide"); + + element.querySelector(".method-title a").addEventListener("click", function(e) { + var info = element.querySelector(".method-info"), + infoContainer = element.querySelector(".method-info-container"); + + element.classList.add("animating"); + info.style.height = (infoContainer.clientHeight + 40) + "px"; + fixScrollPosition(element); + element.classList.toggle("hide"); + if (element.classList.contains("hide")) { + e.preventDefault(); + } + setTimeout(function() { + element.classList.remove("animating"); + }, 300); + }); +}); + +window.addEventListener("hashchange", hashChanged); +hashChanged(); diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/object-template.html b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/object-template.html new file mode 100755 index 0000000..10e85db --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/html/object-template.html @@ -0,0 +1,412 @@ + + + + + + {{page.title}} + + + + {{#strings.appledocData}}{{/strings.appledocData}} + + +
    + +
    + + + +
    +
    +
    +
    +

    {{page.title}}

    + + {{#page.specifications}} + {{#used}}
    {{/used}} + {{#values}}{{>ObjectSpecification}}{{/values}} + {{#used}}
    {{/used}} + {{/page.specifications}} + + {{#object.comment}} + {{#hasLongDescription}} +
    + + +

    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + {{/object.comment}} + + {{#object.methods}} + {{#hasSections}} +
    + + {{#sections}} + + {{#sectionName}}{{/sectionName}} + {{>TaskTitle}} +
    + {{#methods}}{{>Method}}{{/methods}} +
    + {{/sections}} +
    + {{/hasSections}} + {{/object.methods}} + + {{#typedefEnum}} +

    {{nameOfEnum}}

    + {{#comment}} + {{#hasLongDescription}} +
    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + {{/comment}} +
    + + {{#constants}} +

    Definition

    + typedef {{enumStyle}}({{enumPrimitive}}, {{nameOfEnum}} ) {
    + {{#constants}} +    {{name}}{{#hasAssignedValue}} = {{assignedValue}}{{/hasAssignedValue}},
    + {{/constants}} + };
    + {{/constants}} +
    + {{#constants}} +
    +

    Constants

    +
    + {{#constants}} + {{>Constant}} + {{/constants}} +
    +
    + {{/constants}} + + {{#comment}} + {{#hasAvailability}} +
    +

    {{strings.objectMethods.availability}}

    + {{#availability}}{{>GBCommentComponentsList}}{{/availability}} +
    + {{/hasAvailability}} + + {{#hasRelatedItems}} +
    +

    {{strings.objectMethods.seeAlsoTitle}}

    +
      + {{#relatedItems.components}} +
    • {{>GBCommentComponent}}
    • + {{/relatedItems.components}} +
    +
    + {{/hasRelatedItems}} + + {{#prefferedSourceInfo}} +
    +

    {{strings.objectMethods.declaredInTitle}}

    +

    {{filename}}

    +
    + {{/prefferedSourceInfo}} + {{/comment}} + {{/typedefEnum}} +
    + +
    + +
    +
    +
    +
    + + + + + + +Section Method +
    + +

    {{>TaskMethod}}

    + +
    +
    + +
    + {{#comment}} + {{#hasShortDescription}} +
    + {{#shortDescription}}{{>GBCommentComponent}}{{/shortDescription}} +
    + {{/hasShortDescription}} + {{/comment}} + +
    {{>MethodDeclaration}}
    + + {{#comment}} + {{#hasMethodParameters}} +
    +

    {{strings.objectMethods.parametersTitle}}

    + + {{#methodParameters}} + + + + + {{/methodParameters}} +
    {{argumentName}}{{#argumentDescription}}{{>GBCommentComponentsList}}{{/argumentDescription}}
    +
    + {{/hasMethodParameters}} + + {{#hasMethodResult}} +
    +

    {{strings.objectMethods.resultTitle}}

    + {{#methodResult}}{{>GBCommentComponentsList}}{{/methodResult}} +
    + {{/hasMethodResult}} + + {{#hasAvailability}} +
    +

    {{strings.objectMethods.availability}}

    + {{#availability}}{{>GBCommentComponentsList}}{{/availability}} +
    + {{/hasAvailability}} + + {{#hasLongDescription}} +
    +

    {{strings.objectMethods.discussionTitle}}

    + {{#longDescription}}{{>GBCommentComponentsList}}{{/longDescription}} +
    + {{/hasLongDescription}} + + {{#hasMethodExceptions}} +
    +

    {{strings.objectMethods.exceptionsTitle}}

    + + {{#methodExceptions}} + + + + + {{/methodExceptions}} +
    {{argumentName}}{{#argumentDescription}}{{>GBCommentComponentsList}}{{/argumentDescription}}
    +
    + {{/hasMethodExceptions}} + + {{#hasRelatedItems}} +
    +

    {{strings.objectMethods.seeAlsoTitle}}

    +
      + {{#relatedItems.components}} +
    • {{>GBCommentComponent}}
    • + {{/relatedItems.components}} +
    +
    + {{/hasRelatedItems}} + + {{#prefferedSourceInfo}} +
    +

    {{strings.objectMethods.declaredInTitle}}

    +

    {{filename}}

    +
    + {{/prefferedSourceInfo}} + {{/comment}} +
    +
    +
    +EndSection + +Section MethodDeclaration +{{#formattedComponents}}{{#emphasized}}{{/emphasized}}{{#href}}{{/href}}{{value}}{{#href}}{{/href}}{{#emphasized}}{{/emphasized}}{{/formattedComponents}} +EndSection + + +Section TaskTitle +{{#hasMultipleSections}}

    {{#sectionName}}{{.}}{{/sectionName}}{{^sectionName}}{{strings.objectTasks.otherMethodsSectionName}}{{/sectionName}}

    {{/hasMultipleSections}} +{{^hasMultipleSections}}{{#sectionName}}

    {{.}}

    {{/sectionName}}{{/hasMultipleSections}} +EndSection + +Section TaskMethod +{{>TaskSelector}} +{{#isRequired}}{{strings.objectTasks.requiredMethod}}{{/isRequired}} +EndSection + +Section TaskSelector +{{#isInstanceMethod}}–{{/isInstanceMethod}}{{#isClassMethod}}+{{/isClassMethod}}{{#isProperty}} {{/isProperty}} {{methodSelector}} +EndSection + + +Section GBCommentComponentsList +{{#components}}{{>GBCommentComponent}}{{/components}} +EndSection + +Section Constant +
    {{name}}
    +
    +{{#comment}} +{{#hasShortDescription}} +{{#shortDescription}}{{>GBCommentComponent}}{{/shortDescription}} +{{/hasShortDescription}} + +{{#hasAvailability}} +

    Available in {{#availability}}{{#components}}{{stringValue}}{{/components}}{{/availability}}

    +{{/hasAvailability}} + +{{/comment}} + {{#prefferedSourceInfo}} +

    + {{strings.objectMethods.declaredInTitle}} {{filename}}. +

    + {{/prefferedSourceInfo}} +
    +EndSection + +Section GBCommentComponent +{{&htmlValue}} +EndSection + +Section ObjectSpecification + + {{title}} + {{#values}}{{#href}}{{/href}}{{string}}{{#href}}{{/href}}{{&delimiter}}{{/values}} + +EndSection + + +Section Navigation +
  • Index
  • +
  • Hierarchy
  • +EndSection + +Section JumpTo + +EndSection + +Section TableOfContents +{{#object.comment}} +
  • {{strings.objectOverview.title}}
  • +{{/object.comment}} + +{{#object.methods}} +{{#hasSections}} +
  • {{strings.objectTasks.title}}
  • +{{/hasSections}} +{{/object.methods}} + +{{#object.methods}} +{{#hasProperties}} +
  • {{strings.objectMethods.propertiesTitle}}
  • +{{/hasProperties}} + +{{#hasClassMethods}} +
  • {{strings.objectMethods.classMethodsTitle}}
  • +{{/hasClassMethods}} + +{{#hasInstanceMethods}} +
  • {{strings.objectMethods.instanceMethodsTitle}}
  • +{{/hasInstanceMethods}} +{{/object.methods}} +EndSection diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/publish/xml-template.xml b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/publish/xml-template.xml new file mode 100755 index 0000000..cd79c3e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/docs/templates/publish/xml-template.xml @@ -0,0 +1,4 @@ + + ${DOCSET_FEED_VERSION} + ${DOCSET_PACKAGE_URL} + \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/.LSOverride b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/.LSOverride new file mode 100755 index 0000000..5d27049 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/.LSOverride differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.pbxproj new file mode 100755 index 0000000..39c4133 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.pbxproj @@ -0,0 +1,587 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 3E39B9FB1ABF682D00C2ABE5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9F91ABF682D00C2ABE5 /* Main.storyboard */; }; + 3E39B9FE1ABF683700C2ABE5 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9FC1ABF683700C2ABE5 /* LaunchScreen.xib */; }; + 3E39BA001ABF683F00C2ABE5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3E39B9FF1ABF683F00C2ABE5 /* Images.xcassets */; }; + 3ED967B81AC13D37007E2D83 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3ED967BA1AC13D37007E2D83 /* Localizable.strings */; }; + 863CCD821ACF545E009FD3B4 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 863CCD811ACF545E009FD3B4 /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 86B89AA51AB2C0A5001626A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */; }; + B125E3D41B1BA47600FF8759 /* tap.aif in Resources */ = {isa = PBXBuildFile; fileRef = B125E3D31B1BA47600FF8759 /* tap.aif */; }; + BAAC3FD620C4EF1C0065B9E1 /* ResearchKit.pdf in Resources */ = {isa = PBXBuildFile; fileRef = BAAC3FD520C4EF1C0065B9E1 /* ResearchKit.pdf */; }; + BC2A3CD91C58F1CA00DA64B7 /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */; }; + BC2A3CDA1C58F1CA00DA64B7 /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + BC9A27341B82740D00BDA84D /* TaskListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27321B82740D00BDA84D /* TaskListRow.swift */; }; + BC9A27351B82740D00BDA84D /* TaskListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27331B82740D00BDA84D /* TaskListViewController.swift */; }; + BC9A273C1B82741900BDA84D /* ImageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27381B82741900BDA84D /* ImageTableViewCell.swift */; }; + BC9A273D1B82741900BDA84D /* ResultTableViewProviders.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27391B82741900BDA84D /* ResultTableViewProviders.swift */; }; + BC9A273E1B82741900BDA84D /* ResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A273A1B82741900BDA84D /* ResultViewController.swift */; }; + BC9A273F1B82741900BDA84D /* TextImageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A273B1B82741900BDA84D /* TextImageTableViewCell.swift */; }; + BC9A27431B82742600BDA84D /* ChartDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27401B82742600BDA84D /* ChartDataSources.swift */; }; + BC9A27441B82742600BDA84D /* ChartListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27411B82742600BDA84D /* ChartListViewController.swift */; }; + BC9A27451B82742600BDA84D /* ChartTableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC9A27421B82742600BDA84D /* ChartTableViewCells.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + BC2A3CDB1C58F1CA00DA64B7 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + BC2A3CDA1C58F1CA00DA64B7 /* ResearchKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 246DF9FF1BEADFDF00591E9A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA021BEAE01700591E9A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA031BEAE02100591E9A /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA041BEAE02900591E9A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = zh_CN.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA051BEAE02F00591E9A /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = zh_TW.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA061BEAE03500591E9A /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA071BEAE03B00591E9A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA081BEAE04100591E9A /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = es_419.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA091BEAE05000591E9A /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA0A1BEAE05500591E9A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA0B1BEAE05A00591E9A /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA0D1BEAE06D00591E9A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = pt.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA0E1BEAE07200591E9A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = pt_PT.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA0F1BEAE07700591E9A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA101BEAE07D00591E9A /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA111BEAE08200591E9A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA121BEAE08600591E9A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA131BEAE08C00591E9A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA141BEAE09000591E9A /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA151BEAE09500591E9A /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA161BEAE09A00591E9A /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA171BEAE09F00591E9A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA181BEAE0A500591E9A /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA191BEAE0AA00591E9A /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1A1BEAE0AF00591E9A /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1B1BEAE0B600591E9A /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1C1BEAE0BA00591E9A /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1D1BEAE0C000591E9A /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1E1BEAE0C500591E9A /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA1F1BEAE0CA00591E9A /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA201BEAE0D000591E9A /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA211BEAE0D600591E9A /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = id.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA221BEAE0DC00591E9A /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA231BEAE0E200591E9A /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA251BEAE23800591E9A /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA261BEAE26200591E9A /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = en_GB.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA271BEAE27000591E9A /* en-AU */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-AU"; path = en_AU.lproj/Localizable.strings; sourceTree = ""; }; + 246DFA281BEAE2A800591E9A /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = zh_HK.lproj/Localizable.strings; sourceTree = ""; }; + 3E39B9E81ABF675000C2ABE5 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 3E39B9FA1ABF682D00C2ABE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3E39B9FD1ABF683700C2ABE5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 3E39B9FF1ABF683F00C2ABE5 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 3ED967B91AC13D37007E2D83 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = ""; }; + 863CCD811ACF545E009FD3B4 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; + 863CCD831ACF545E009FD3B4 /* ORKCatalog.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = ORKCatalog.entitlements; sourceTree = ""; }; + 869230BE1AAA890A00BFE11B /* ORKCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 86B89A981AB2C0A5001626A4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ORKCatalog/AppDelegate.swift; sourceTree = SOURCE_ROOT; }; + B125E3D31B1BA47600FF8759 /* tap.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = tap.aif; sourceTree = ""; }; + BAAC3FD520C4EF1C0065B9E1 /* ResearchKit.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = ResearchKit.pdf; sourceTree = ""; }; + BAFAD7AA1EFB2907004DEC45 /* fr-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "fr-CA"; path = fr_CA.lproj/Localizable.strings; sourceTree = ""; }; + BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ResearchKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BC9A27321B82740D00BDA84D /* TaskListRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TaskListRow.swift; path = Tasks/TaskListRow.swift; sourceTree = ""; }; + BC9A27331B82740D00BDA84D /* TaskListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TaskListViewController.swift; path = Tasks/TaskListViewController.swift; sourceTree = ""; }; + BC9A27381B82741900BDA84D /* ImageTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageTableViewCell.swift; path = Results/ImageTableViewCell.swift; sourceTree = ""; }; + BC9A27391B82741900BDA84D /* ResultTableViewProviders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResultTableViewProviders.swift; path = Results/ResultTableViewProviders.swift; sourceTree = ""; }; + BC9A273A1B82741900BDA84D /* ResultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResultViewController.swift; path = Results/ResultViewController.swift; sourceTree = ""; }; + BC9A273B1B82741900BDA84D /* TextImageTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TextImageTableViewCell.swift; path = Results/TextImageTableViewCell.swift; sourceTree = ""; }; + BC9A27401B82742600BDA84D /* ChartDataSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartDataSources.swift; path = Charts/ChartDataSources.swift; sourceTree = ""; }; + BC9A27411B82742600BDA84D /* ChartListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartListViewController.swift; path = Charts/ChartListViewController.swift; sourceTree = ""; }; + BC9A27421B82742600BDA84D /* ChartTableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChartTableViewCells.swift; path = Charts/ChartTableViewCells.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 869230BB1AAA890A00BFE11B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BC2A3CD91C58F1CA00DA64B7 /* ResearchKit.framework in Frameworks */, + 863CCD821ACF545E009FD3B4 /* HealthKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 259E77171AFFD23B0070F786 /* Displaying Charts */ = { + isa = PBXGroup; + children = ( + BC9A27401B82742600BDA84D /* ChartDataSources.swift */, + BC9A27411B82742600BDA84D /* ChartListViewController.swift */, + BC9A27421B82742600BDA84D /* ChartTableViewCells.swift */, + ); + name = "Displaying Charts"; + sourceTree = ""; + }; + 3E838B881ABFD0E5006AE2D4 /* Presenting Tasks */ = { + isa = PBXGroup; + children = ( + BC9A27321B82740D00BDA84D /* TaskListRow.swift */, + BC9A27331B82740D00BDA84D /* TaskListViewController.swift */, + ); + name = "Presenting Tasks"; + sourceTree = ""; + }; + 3E838B891ABFD104006AE2D4 /* Displaying Results */ = { + isa = PBXGroup; + children = ( + BC9A27381B82741900BDA84D /* ImageTableViewCell.swift */, + BC9A27391B82741900BDA84D /* ResultTableViewProviders.swift */, + BC9A273A1B82741900BDA84D /* ResultViewController.swift */, + BC9A273B1B82741900BDA84D /* TextImageTableViewCell.swift */, + ); + name = "Displaying Results"; + sourceTree = ""; + }; + 869230B51AAA890A00BFE11B = { + isa = PBXGroup; + children = ( + 3E39B9E81ABF675000C2ABE5 /* README.md */, + BC2A3C9E1C58E81500DA64B7 /* Frameworks */, + 869230C01AAA890A00BFE11B /* ORKCatalog */, + 869230BF1AAA890A00BFE11B /* Products */, + ); + sourceTree = ""; + }; + 869230BF1AAA890A00BFE11B /* Products */ = { + isa = PBXGroup; + children = ( + 869230BE1AAA890A00BFE11B /* ORKCatalog.app */, + ); + name = Products; + sourceTree = ""; + }; + 869230C01AAA890A00BFE11B /* ORKCatalog */ = { + isa = PBXGroup; + children = ( + 86B89A9C1AB2C0A5001626A4 /* AppDelegate.swift */, + 259E77171AFFD23B0070F786 /* Displaying Charts */, + 3E838B891ABFD104006AE2D4 /* Displaying Results */, + 3E838B881ABFD0E5006AE2D4 /* Presenting Tasks */, + BC74787A1B990EED0072BFE8 /* Resources */, + 869230C11AAA890A00BFE11B /* Supporting Files */, + ); + path = ORKCatalog; + sourceTree = ""; + }; + 869230C11AAA890A00BFE11B /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 86B89A981AB2C0A5001626A4 /* Info.plist */, + 863CCD831ACF545E009FD3B4 /* ORKCatalog.entitlements */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + BC2A3C9E1C58E81500DA64B7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BC2A3CD81C58F1CA00DA64B7 /* ResearchKit.framework */, + 863CCD811ACF545E009FD3B4 /* HealthKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + BC74787A1B990EED0072BFE8 /* Resources */ = { + isa = PBXGroup; + children = ( + BAAC3FD520C4EF1C0065B9E1 /* ResearchKit.pdf */, + 3E39B9FF1ABF683F00C2ABE5 /* Images.xcassets */, + 3E39B9FC1ABF683700C2ABE5 /* LaunchScreen.xib */, + 3ED967BA1AC13D37007E2D83 /* Localizable.strings */, + 3E39B9F91ABF682D00C2ABE5 /* Main.storyboard */, + B125E3D31B1BA47600FF8759 /* tap.aif */, + ); + path = Resources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 869230BD1AAA890A00BFE11B /* ORKCatalog */ = { + isa = PBXNativeTarget; + buildConfigurationList = 869230DF1AAA890A00BFE11B /* Build configuration list for PBXNativeTarget "ORKCatalog" */; + buildPhases = ( + 869230BA1AAA890A00BFE11B /* Sources */, + 869230BB1AAA890A00BFE11B /* Frameworks */, + 869230BC1AAA890A00BFE11B /* Resources */, + BC2A3CDB1C58F1CA00DA64B7 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ORKCatalog; + productName = Consent.swift; + productReference = 869230BE1AAA890A00BFE11B /* ORKCatalog.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 869230B61AAA890A00BFE11B /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0700; + LastUpgradeCheck = 1000; + ORGANIZATIONNAME = researchkit.org; + TargetAttributes = { + 869230BD1AAA890A00BFE11B = { + CreatedOnToolsVersion = 6.2; + LastSwiftMigration = 1020; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 869230B91AAA890A00BFE11B /* Build configuration list for PBXProject "ORKCatalog" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + English, + en, + Base, + fr, + de, + "zh-Hans", + "zh-Hant", + ja, + es, + it, + nl, + ko, + "pt-PT", + da, + fi, + nb, + sv, + ru, + pl, + tr, + ar, + th, + cs, + hu, + ca, + hr, + el, + he, + ro, + sk, + uk, + id, + ms, + vi, + hi, + "en-GB", + "en-AU", + "zh-HK", + "fr-CA", + "es-419", + pt, + ); + mainGroup = 869230B51AAA890A00BFE11B; + productRefGroup = 869230BF1AAA890A00BFE11B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 869230BD1AAA890A00BFE11B /* ORKCatalog */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 869230BC1AAA890A00BFE11B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3E39BA001ABF683F00C2ABE5 /* Images.xcassets in Resources */, + 3E39B9FB1ABF682D00C2ABE5 /* Main.storyboard in Resources */, + BAAC3FD620C4EF1C0065B9E1 /* ResearchKit.pdf in Resources */, + B125E3D41B1BA47600FF8759 /* tap.aif in Resources */, + 3E39B9FE1ABF683700C2ABE5 /* LaunchScreen.xib in Resources */, + 3ED967B81AC13D37007E2D83 /* Localizable.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 869230BA1AAA890A00BFE11B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BC9A27451B82742600BDA84D /* ChartTableViewCells.swift in Sources */, + BC9A273E1B82741900BDA84D /* ResultViewController.swift in Sources */, + BC9A27441B82742600BDA84D /* ChartListViewController.swift in Sources */, + BC9A27431B82742600BDA84D /* ChartDataSources.swift in Sources */, + BC9A273D1B82741900BDA84D /* ResultTableViewProviders.swift in Sources */, + BC9A273F1B82741900BDA84D /* TextImageTableViewCell.swift in Sources */, + 86B89AA51AB2C0A5001626A4 /* AppDelegate.swift in Sources */, + BC9A273C1B82741900BDA84D /* ImageTableViewCell.swift in Sources */, + BC9A27351B82740D00BDA84D /* TaskListViewController.swift in Sources */, + BC9A27341B82740D00BDA84D /* TaskListRow.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3E39B9F91ABF682D00C2ABE5 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3E39B9FA1ABF682D00C2ABE5 /* Base */, + ); + name = Main.storyboard; + path = Localized; + sourceTree = ""; + }; + 3E39B9FC1ABF683700C2ABE5 /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 3E39B9FD1ABF683700C2ABE5 /* Base */, + ); + name = LaunchScreen.xib; + path = Localized; + sourceTree = ""; + }; + 3ED967BA1AC13D37007E2D83 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + 3ED967B91AC13D37007E2D83 /* Base */, + 246DF9FF1BEADFDF00591E9A /* en */, + 246DFA021BEAE01700591E9A /* fr */, + 246DFA031BEAE02100591E9A /* de */, + 246DFA041BEAE02900591E9A /* zh-Hans */, + 246DFA051BEAE02F00591E9A /* zh-Hant */, + 246DFA061BEAE03500591E9A /* ja */, + 246DFA071BEAE03B00591E9A /* es */, + 246DFA081BEAE04100591E9A /* es-MX */, + 246DFA091BEAE05000591E9A /* it */, + 246DFA0A1BEAE05500591E9A /* nl */, + 246DFA0B1BEAE05A00591E9A /* ko */, + 246DFA0D1BEAE06D00591E9A /* pt-BR */, + 246DFA0E1BEAE07200591E9A /* pt-PT */, + 246DFA0F1BEAE07700591E9A /* da */, + 246DFA101BEAE07D00591E9A /* fi */, + 246DFA111BEAE08200591E9A /* nb */, + 246DFA121BEAE08600591E9A /* sv */, + 246DFA131BEAE08C00591E9A /* ru */, + 246DFA141BEAE09000591E9A /* pl */, + 246DFA151BEAE09500591E9A /* tr */, + 246DFA161BEAE09A00591E9A /* ar */, + 246DFA171BEAE09F00591E9A /* th */, + 246DFA181BEAE0A500591E9A /* cs */, + 246DFA191BEAE0AA00591E9A /* hu */, + 246DFA1A1BEAE0AF00591E9A /* ca */, + 246DFA1B1BEAE0B600591E9A /* hr */, + 246DFA1C1BEAE0BA00591E9A /* el */, + 246DFA1D1BEAE0C000591E9A /* he */, + 246DFA1E1BEAE0C500591E9A /* ro */, + 246DFA1F1BEAE0CA00591E9A /* sk */, + 246DFA201BEAE0D000591E9A /* uk */, + 246DFA211BEAE0D600591E9A /* id */, + 246DFA221BEAE0DC00591E9A /* ms */, + 246DFA231BEAE0E200591E9A /* vi */, + 246DFA251BEAE23800591E9A /* hi */, + 246DFA261BEAE26200591E9A /* en-GB */, + 246DFA271BEAE27000591E9A /* en-AU */, + 246DFA281BEAE2A800591E9A /* zh-HK */, + BAFAD7AA1EFB2907004DEC45 /* fr-CA */, + ); + name = Localizable.strings; + path = Localized; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 869230DD1AAA890A00BFE11B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 869230DE1AAA890A00BFE11B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_VERSION = 4.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 869230E01AAA890A00BFE11B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "ORKCatalog/Supporting Files/ORKCatalog.entitlements"; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/ORKCatalog/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKCatalog"; + PRODUCT_NAME = ORKCatalog; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 869230E11AAA890A00BFE11B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = "ORKCatalog/Supporting Files/ORKCatalog.entitlements"; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + INFOPLIST_FILE = "$(SRCROOT)/ORKCatalog/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKCatalog"; + PRODUCT_NAME = ORKCatalog; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 869230B91AAA890A00BFE11B /* Build configuration list for PBXProject "ORKCatalog" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 869230DD1AAA890A00BFE11B /* Debug */, + 869230DE1AAA890A00BFE11B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 869230DF1AAA890A00BFE11B /* Build configuration list for PBXNativeTarget "ORKCatalog" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 869230E01AAA890A00BFE11B /* Debug */, + 869230E11AAA890A00BFE11B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 869230B61AAA890A00BFE11B /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..56b7a15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/xcshareddata/xcschemes/ORKCatalog.xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/xcshareddata/xcschemes/ORKCatalog.xcscheme new file mode 100755 index 0000000..03a7a31 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog.xcodeproj/xcshareddata/xcschemes/ORKCatalog.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/AppDelegate.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/AppDelegate.swift new file mode 100755 index 0000000..ac53924 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/AppDelegate.swift @@ -0,0 +1,78 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + // MARK: Properties + + var window: UIWindow? + + var tabBarController: UITabBarController { + return window!.rootViewController as! UITabBarController + } + + var taskListViewController: TaskListViewController { + let navigationController = tabBarController.viewControllers!.first as! UINavigationController + + return navigationController.visibleViewController as! TaskListViewController + } + + var resultViewController: ResultViewController? { + let navigationController = tabBarController.viewControllers![1] as! UINavigationController + + // Find the `ResultViewController` (if any) that's a view controller in the navigation controller. + return navigationController.viewControllers.first(where: { (someVC) -> Bool in + someVC is ResultViewController + }) as? ResultViewController + } + + // MARK: UIApplicationDelegate + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { + + // When a task result has been finished, update the result view controller's task result. + taskListViewController.taskResultFinishedCompletionHandler = { [unowned self] taskResult in + /* + If we're displaying a new result, make sure the result view controller's + navigation controller is at the root. + */ + if let navigationController = self.resultViewController?.navigationController { + navigationController.popToRootViewController(animated: false) + } + + // Set the result so we can display it. + self.resultViewController?.result = taskResult + } + + return true + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartDataSources.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartDataSources.swift new file mode 100755 index 0000000..aa7fba6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartDataSources.swift @@ -0,0 +1,191 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +class PieChartDataSource: NSObject, ORKPieChartViewDataSource { + + let colors = [ + UIColor(red: 217 / 225, green: 217 / 255, blue: 217 / 225, alpha: 1), + UIColor(red: 142 / 255, green: 142 / 255, blue: 147 / 255, alpha: 1), + UIColor(red: 244 / 255, green: 190 / 255, blue: 74 / 255, alpha: 1) + ] + let values = [10.0, 25.0, 45.0] + + func numberOfSegments(in pieChartView: ORKPieChartView ) -> Int { + return colors.count + } + + func pieChartView(_ pieChartView: ORKPieChartView, valueForSegmentAt index: Int) -> CGFloat { + return CGFloat(values[index]) + } + + func pieChartView(_ pieChartView: ORKPieChartView, colorForSegmentAt index: Int) -> UIColor { + return colors[index] + } + + func pieChartView(_ pieChartView: ORKPieChartView, titleForSegmentAt index: Int) -> String? { + return "Title \(index + 1)" + } +} + +class LineGraphDataSource: NSObject, ORKValueRangeGraphChartViewDataSource { + + var plotPoints = + [ + [ + ORKValueRange(value: 10), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40) + ], + [ + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 64) + ] + ] + + func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueRange { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func maximumValue(for graphChartView: ORKGraphChartView) -> Double { + return 70 + } + + func minimumValue(for graphChartView: ORKGraphChartView) -> Double { + return 0 + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return "\(pointIndex + 1)" + } + + func graphChartView(_ graphChartView: ORKGraphChartView, drawsPointIndicatorsForPlotIndex plotIndex: Int) -> Bool { + if plotIndex == 1 { + return false + } + return true + } +} + +class DiscreteGraphDataSource: NSObject, ORKValueRangeGraphChartViewDataSource { + + var plotPoints = + [ + [ + ORKValueRange(minimumValue: 0, maximumValue: 2), + ORKValueRange(minimumValue: 1, maximumValue: 4), + ORKValueRange(minimumValue: 2, maximumValue: 6), + ORKValueRange(minimumValue: 3, maximumValue: 8), + ORKValueRange(minimumValue: 5, maximumValue: 10), + ORKValueRange(minimumValue: 8, maximumValue: 13) + ], + [ + ORKValueRange(value: 1), + ORKValueRange(minimumValue: 2, maximumValue: 6), + ORKValueRange(minimumValue: 3, maximumValue: 10), + ORKValueRange(minimumValue: 5, maximumValue: 11), + ORKValueRange(minimumValue: 7, maximumValue: 13), + ORKValueRange(minimumValue: 10, maximumValue: 13) + ] + ] + + func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueRange { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return "\(pointIndex + 1)" + } + +} + +class BarGraphDataSource: NSObject, ORKValueStackGraphChartViewDataSource { + + var plotPoints = + [ + [ + ORKValueStack(stackedValues: [4, 6]), + ORKValueStack(stackedValues: [2, 4, 4]), + ORKValueStack(stackedValues: [2, 6, 3, 6]), + ORKValueStack(stackedValues: [3, 8, 10, 12]), + ORKValueStack(stackedValues: [5, 10, 12, 8]), + ORKValueStack(stackedValues: [8, 13, 18]) + ], + [ + ORKValueStack(stackedValues: [14]), + ORKValueStack(stackedValues: [6, 6]), + ORKValueStack(stackedValues: [3, 10, 12]), + ORKValueStack(stackedValues: [5, 11, 14]), + ORKValueStack(stackedValues: [7, 13, 20]), + ORKValueStack(stackedValues: [10, 13, 25]) + ] + ] + + public func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueStack { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return "\(pointIndex + 1)" + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartListViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartListViewController.swift new file mode 100755 index 0000000..5a5675f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartListViewController.swift @@ -0,0 +1,131 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class ChartListViewController: UITableViewController { + + let pieChartDataSource = PieChartDataSource() + let lineGraphChartDataSource = LineGraphDataSource() + let discreteGraphChartDataSource = DiscreteGraphDataSource() + let barGraphChartDataSource = BarGraphDataSource() + + let pieChartIdentifier = "PieChartCell" + let lineGraphChartIdentifier = "LineGraphChartCell" + let discreteGraphChartIdentifier = "DiscreteGraphChartCell" + let barGraphChartIdentifier = "BarGraphChartCell" + + var pieChartTableViewCell: PieChartTableViewCell! + var lineGraphChartTableViewCell: LineGraphChartTableViewCell! + var discreteGraphChartTableViewCell: DiscreteGraphChartTableViewCell! + var barGraphChartTableViewCell: BarGraphChartTableViewCell! + var chartTableViewCells: [UITableViewCell]! + + override func viewDidLoad() { + super.viewDidLoad() + + if #available(iOS 13.0, *) { + self.tableView.backgroundColor = UIColor.systemBackground + } + + // ORKPieChartView + pieChartTableViewCell = (tableView.dequeueReusableCell(withIdentifier: pieChartIdentifier) as! PieChartTableViewCell) + let pieChartView = pieChartTableViewCell.pieChartView + pieChartView?.dataSource = pieChartDataSource + // Optional custom configuration + + pieChartView?.title = "TITLE" + pieChartView?.text = "TEXT" + pieChartView?.lineWidth = 14 + pieChartView?.radiusScaleFactor = 0.6 + + // ORKLineGraphChartView + lineGraphChartTableViewCell = (tableView.dequeueReusableCell(withIdentifier: lineGraphChartIdentifier) as! LineGraphChartTableViewCell) + let lineGraphChartView = lineGraphChartTableViewCell.graphView as! ORKLineGraphChartView + lineGraphChartView.dataSource = lineGraphChartDataSource + lineGraphChartView.tintColor = UIColor(red: 244 / 255, green: 190 / 255, blue: 74 / 255, alpha: 1) + // Optional custom configuration + lineGraphChartView.showsHorizontalReferenceLines = true + lineGraphChartView.showsVerticalReferenceLines = true + + // ORKDiscreteGraphChartView + discreteGraphChartTableViewCell = (tableView.dequeueReusableCell(withIdentifier: discreteGraphChartIdentifier) as! DiscreteGraphChartTableViewCell) + let discreteGraphChartView = discreteGraphChartTableViewCell.graphView as! ORKDiscreteGraphChartView + discreteGraphChartView.dataSource = discreteGraphChartDataSource + discreteGraphChartView.tintColor = UIColor(red: 244 / 255, green: 190 / 255, blue: 74 / 255, alpha: 1) + // Optional custom configuration + discreteGraphChartView.showsHorizontalReferenceLines = true + discreteGraphChartView.showsVerticalReferenceLines = true + + // ORKBarGraphChartView + barGraphChartTableViewCell = (tableView.dequeueReusableCell(withIdentifier: barGraphChartIdentifier) as! BarGraphChartTableViewCell) + let barGraphChartView = barGraphChartTableViewCell.graphView as! ORKBarGraphChartView + barGraphChartView.dataSource = barGraphChartDataSource + barGraphChartView.tintColor = UIColor(red: 244 / 255, green: 190 / 255, blue: 74 / 255, alpha: 1) + // Optional custom configuration + barGraphChartView.showsHorizontalReferenceLines = true + barGraphChartView.showsVerticalReferenceLines = true + + chartTableViewCells = [pieChartTableViewCell, lineGraphChartTableViewCell, discreteGraphChartTableViewCell, barGraphChartTableViewCell] + + if #available(iOS 13.0, *) { + pieChartView?.backgroundColor = UIColor.secondarySystemBackground + lineGraphChartView.backgroundColor = UIColor.secondarySystemBackground + discreteGraphChartView.backgroundColor = UIColor.secondarySystemBackground + barGraphChartView.backgroundColor = UIColor.secondarySystemBackground + } + + tableView.tableFooterView = UIView(frame: CGRect.zero) + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return chartTableViewCells.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = chartTableViewCells[(indexPath as NSIndexPath).row] + + if #available(iOS 13.0, *) { + cell.contentView.backgroundColor = UIColor.systemBackground + } + + return cell + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + pieChartTableViewCell.pieChartView.animate(withDuration: 0.5) + lineGraphChartTableViewCell.graphView.animate(withDuration: 0.5) + discreteGraphChartTableViewCell.graphView.animate(withDuration: 0.5) + barGraphChartTableViewCell.graphView.animate(withDuration: 0.5) + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartTableViewCells.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartTableViewCells.swift new file mode 100755 index 0000000..36efc71 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Charts/ChartTableViewCells.swift @@ -0,0 +1,46 @@ +/* +Copyright (c) 2015, James Cox. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class PieChartTableViewCell: UITableViewCell { + @IBOutlet weak var pieChartView: ORKPieChartView! +} + +class GraphChartTableViewCell: UITableViewCell { + @IBOutlet weak var graphView: ORKGraphChartView! +} + +class LineGraphChartTableViewCell: GraphChartTableViewCell { } + +class DiscreteGraphChartTableViewCell: GraphChartTableViewCell { } + +class BarGraphChartTableViewCell: GraphChartTableViewCell { } diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..536bc9d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,106 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40.png", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-83.5@2x.png", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100755 index 0000000..4e1028b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100755 index 0000000..43550de Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..2455935 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100755 index 0000000..0068e43 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png new file mode 100755 index 0000000..00e4775 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100755 index 0000000..ed94361 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100755 index 0000000..553628f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100755 index 0000000..4e1028b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/Contents.json new file mode 100755 index 0000000..6c27bc1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "first.pdf" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/first.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/first.pdf new file mode 100755 index 0000000..e9ebbe6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/first_tab.imageset/first.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/Contents.json new file mode 100755 index 0000000..de2ffc3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline_big@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_outline_big@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "right_hand_outline_big@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x.png new file mode 100755 index 0000000..f4647fc Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png new file mode 100755 index 0000000..4d9d639 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@3x.png new file mode 100755 index 0000000..4d9d639 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_outline_big.imageset/right_hand_outline_big@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/Contents.json new file mode 100755 index 0000000..d0c4869 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/Contents.json @@ -0,0 +1,46 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "1x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_solid@2x.png", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "filename" : "right_hand_solid@3x.png", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "subtype" : "retina4", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "filename" : "right_hand_solid@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x.png new file mode 100755 index 0000000..6872ebb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x~ipad.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x~ipad.png new file mode 100755 index 0000000..fe50bd5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@2x~ipad.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@3x.png new file mode 100755 index 0000000..fdd76f2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/hand_solid.imageset/right_hand_solid@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/Contents.json new file mode 100755 index 0000000..33a7451 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "first.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/first.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/first.pdf new file mode 100755 index 0000000..47d911d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/round_shape.imageset/first.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/Contents.json new file mode 100755 index 0000000..12fbf88 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "second.pdf" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/second.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/second.pdf new file mode 100755 index 0000000..0457e63 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/second_tab.imageset/second.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/Contents.json new file mode 100755 index 0000000..4d46ba1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "signature.png" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/signature.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/signature.png new file mode 100755 index 0000000..b486d74 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/signature.imageset/signature.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/Contents.json new file mode 100755 index 0000000..03bd9c9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "second.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/second.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/second.pdf new file mode 100755 index 0000000..401614e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/square_shape.imageset/second.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Contents.json new file mode 100755 index 0000000..c917b4f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Stroop@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Stroop@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@2x.png new file mode 100755 index 0000000..f6c31eb Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@3x.png new file mode 100755 index 0000000..4f00c85 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/stroop.imageset/Stroop@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/Contents.json new file mode 100755 index 0000000..693abbb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "third.pdf" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/third.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/third.pdf new file mode 100755 index 0000000..35ad553 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Images.xcassets/third_tab.imageset/third.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/LaunchScreen.xib b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/LaunchScreen.xib new file mode 100755 index 0000000..8a92321 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/LaunchScreen.xib @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Localizable.strings new file mode 100755 index 0000000..611e630 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Main.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Main.storyboard new file mode 100755 index 0000000..e2e1f15 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/Base.lproj/Main.storyboard @@ -0,0 +1,422 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ar.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ar.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ar.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ca.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ca.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ca.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/cs.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/cs.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/cs.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/da.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/da.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/da.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/de.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/de.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/de.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/el.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/el.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/el.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en.lproj/Localizable.strings new file mode 100755 index 0000000..611e630 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_AU.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_AU.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_AU.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_GB.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_GB.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/en_GB.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es_419.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es_419.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/es_419.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fi.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fi.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr_CA.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr_CA.lproj/Localizable.strings new file mode 100755 index 0000000..2b82978 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/fr_CA.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/he.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/he.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/he.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hi.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hi.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hr.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hr.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hu.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hu.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/hu.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/id.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/id.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/id.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/it.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/it.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/it.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ja.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ja.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ja.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ko.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ko.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ko.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ms.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ms.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ms.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nb.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nb.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nb.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nl.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nl.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/nl.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pl.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pl.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pl.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt_PT.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt_PT.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/pt_PT.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ro.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ro.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ro.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ru.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ru.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/ru.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sk.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sk.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sk.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sv.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sv.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/sv.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/th.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/th.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/th.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/tr.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/tr.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/tr.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/uk.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/uk.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/uk.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/vi.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/vi.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/vi.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh-Hant-HK.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh-Hant-HK.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh-Hant-HK.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_CN.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_CN.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_CN.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_HK.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_HK.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_HK.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_TW.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_TW.lproj/Localizable.strings new file mode 100755 index 0000000..9268031 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/Localized/zh_TW.lproj/Localizable.strings differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/ResearchKit.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/ResearchKit.pdf new file mode 100755 index 0000000..a2881f1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/ResearchKit.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/tap.aif b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/tap.aif new file mode 100755 index 0000000..818676e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Resources/tap.aif differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ImageTableViewCell.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ImageTableViewCell.swift new file mode 100755 index 0000000..6bbfcf3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ImageTableViewCell.swift @@ -0,0 +1,42 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +/** + A simple `UITableViewCell` subclass that can display an image view. + Properties in this table view cell are set in Interface Builder in the main + storyboard. +*/ +class ImageTableViewCell: UITableViewCell { + // MARK: Properties + + @IBOutlet weak var fullImageView: UIImageView! +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultTableViewProviders.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultTableViewProviders.swift new file mode 100755 index 0000000..0857fc2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultTableViewProviders.swift @@ -0,0 +1,1364 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit +import MapKit +import Speech + +/** + Create a `protocol` that knows + how to present the metadata for an `ORKResult` instance. Extra metadata is + displayed for specific `ORKResult` types. For example, a table view provider + for an `ORKFileResult` instance will display the `fileURL` in addition to the + standard `ORKResult` properties. + + To learn about how to read metadata from the different kinds of `ORKResult` + instances, see the `ResultTableViewProvider` subclasses below. Specifically, + look at their `resultRowsForSection(_:)` implementations which are meant to + enhance the metadata that is displayed for the result table view provider. + + Note: since these table view providers are meant to display data for developers + and are not user visible (see description in `ResultViewController`), none + of the properties / content are localized. +*/ +func resultTableViewProviderForResult(_ result: ORKResult?) -> UITableViewDataSource & UITableViewDelegate { + guard let result = result else { + /* + Use a table view provider that shows that there hasn't been a recently + provided result. + */ + return NoRecentResultTableViewProvider() + } + + // The type that will be used to create an instance of a table view provider. + let providerType: ResultTableViewProvider.Type + + /* + Map the type of the result to its associated `ResultTableViewProvider`. + To reduce the possible effects of someone modifying this code--i.e. + cases getting reordered and accidentally getting matches for subtypes + of the intended result type, we guard against any subtype matches + (e.g. the `ORKCollectionResult` guard against `result` being an + `ORKTaskResult` instance). + */ + switch result { + // Survey Questions + case is ORKBooleanQuestionResult: + providerType = BooleanQuestionResultTableViewProvider.self + + case is ORKChoiceQuestionResult: + providerType = ChoiceQuestionResultTableViewProvider.self + + case is ORKDateQuestionResult: + providerType = DateQuestionResultTableViewProvider.self + + case is ORKLocationQuestionResult: + providerType = LocationQuestionResultTableViewProvider.self + + case is ORKNumericQuestionResult: + providerType = NumericQuestionResultTableViewProvider.self + + case is ORKScaleQuestionResult: + providerType = ScaleQuestionResultTableViewProvider.self + + case is ORKTextQuestionResult: + providerType = TextQuestionResultTableViewProvider.self + + case is ORKTimeIntervalQuestionResult: + providerType = TimeIntervalQuestionResultTableViewProvider.self + + case is ORKTimeOfDayQuestionResult: + providerType = TimeOfDayQuestionResultTableViewProvider.self + + // Consent + case is ORKConsentSignatureResult: + providerType = ConsentSignatureResultTableViewProvider.self + + // Active Tasks + case is ORKAmslerGridResult: + providerType = AmslerGridResultTableViewProvider.self + + case is ORKPasscodeResult: + providerType = PasscodeResultTableViewProvider.self + + case is ORKFileResult: + providerType = FileResultTableViewProvider.self + + case is ORKSpatialSpanMemoryResult: + providerType = SpatialSpanMemoryResultTableViewProvider.self + + case is ORKSpeechRecognitionResult: + providerType = SpeechRecognitionResultTableViewProvider.self + + case is ORKStroopResult: + providerType = StroopResultTableViewProvider.self + + case is ORKSwiftStroopResult: + providerType = SwiftStroopResultTableViewProvider.self + + case is ORKTappingIntervalResult: + providerType = TappingIntervalResultTableViewProvider.self + + case is ORKToneAudiometryResult: + providerType = ToneAudiometryResultTableViewProvider.self + + case is ORKReactionTimeResult: + providerType = ReactionTimeViewProvider.self + + case is ORKRangeOfMotionResult: + providerType = RangeOfMotionResultTableViewProvider.self + + case is ORKTowerOfHanoiResult: + providerType = TowerOfHanoiResultTableViewProvider.self + + case is ORKPSATResult: + providerType = PSATResultTableViewProvider.self + + case is ORKTimedWalkResult: + providerType = TimedWalkResultTableViewProvider.self + + case is ORKHolePegTestResult: + providerType = HolePegTestResultTableViewProvider.self + + case is ORKTrailmakingResult: + providerType = TrailmakingResultTableViewProvider.self + + // All + case is ORKTaskResult: + providerType = TaskResultTableViewProvider.self + + /* + Refer to the comment near the switch statement for why the + additional guard is here. + */ + case is ORKCollectionResult where !(result is ORKTaskResult): + providerType = CollectionResultTableViewProvider.self + + case is ORKVideoInstructionStepResult: + providerType = VideoInstructionStepResultTableViewProvider.self + + case is ORKWebViewStepResult: + providerType = WebViewStepResultTableViewProvider.self + + case is ORKLandoltCResult: + providerType = LandoltCStepResultProvider.self + + case is ORKEnvironmentSPLMeterResult: + providerType = SPLMeterStepResultTableViewProvider.self + + default: + fatalError("No ResultTableViewProvider defined for \(type(of: result)).") + } + + // Return a new instance of the specific `ResultTableViewProvider`. + return providerType.init(result: result) +} + +/** + An enum representing the data that can be presented in a `UITableViewCell` by + a `ResultsTableViewProvider` type. +*/ +enum ResultRow { + // MARK: Cases + + case text(String, detail: String, selectable: Bool) + case textImage(String, image: UIImage?) + case image(UIImage?) + + // MARK: Types + + /** + Possible `UITableViewCell` identifiers that have been defined in the main + storyboard. + */ + enum TableViewCellIdentifier: String { + case `default` = "Default" + case noResultSet = "NoResultSet" + case noChildResults = "NoChildResults" + case textImage = "TextImage" + case image = "Image" + } + + // MARK: Initialization + + /// Helper initializer for `ResultRow.Text`. + init(text: String, detail: Any?, selectable: Bool = false) { + /* + Show the string value if `detail` is not `nil`, otherwise show that + it's "nil". Use Optional's map method to map the value to a string + if the detail is not `nil`. + */ + let detailText = detail.map { String(describing: $0) } ?? "nil" + + self = .text(text, detail: detailText, selectable: selectable) + } +} + +/** + A special `protocol` that displays + a row saying that there's no result. +*/ +class NoRecentResultTableViewProvider: NSObject, UITableViewDataSource, UITableViewDelegate { + // MARK: UITableViewDataSource + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + return tableView.dequeueReusableCell(withIdentifier: ResultRow.TableViewCellIdentifier.noResultSet.rawValue, for: indexPath) + } +} + +// MARK: ResultTableViewProvider and Subclasses + +/** + Base class for displaying metadata for an `ORKResult` instance. The metadata + that's displayed are common properties for all `ORKResult` instances (e.g. + `startDate` and `endDate`). +*/ +class ResultTableViewProvider: NSObject, UITableViewDataSource, UITableViewDelegate { + // MARK: Properties + + let result: ORKResult + + // MARK: Initializers + + required init(result: ORKResult) { + self.result = result + } + + // MARK: UITableViewDataSource + + func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + let resultRows = resultRowsForSection(section) + + // Show an empty row if there isn't any metadata in the rows for this section. + if resultRows.isEmpty { + return 1 + } + + return resultRows.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let resultRows = resultRowsForSection((indexPath as NSIndexPath).section) + + // Show an empty row if there isn't any metadata in the rows for this section. + if resultRows.isEmpty { + let noChildResultsCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: ResultRow.TableViewCellIdentifier.noChildResults.rawValue, for: indexPath) + + if #available(iOS 13.0, *) { + noChildResultsCell.textLabel?.textColor = UIColor.label + } + + return noChildResultsCell + } + + // Fetch the `ResultRow` that corresponds to `indexPath`. + let resultRow = resultRows[(indexPath as NSIndexPath).row] + + switch resultRow { + case let .text(text, detail: detailText, selectable): + let cell = tableView.dequeueReusableCell(withIdentifier: ResultRow.TableViewCellIdentifier.default.rawValue, for: indexPath) + + cell.textLabel!.text = text + cell.detailTextLabel!.text = detailText + + if #available(iOS 13.0, *) { + cell.textLabel?.textColor = UIColor.label + cell.detailTextLabel?.textColor = UIColor.secondaryLabel + } + + /* + In this sample, the accessory type should be a disclosure + indicator if the table view cell is selectable. + */ + cell.selectionStyle = selectable ? .default : .none + cell.accessoryType = selectable ? .disclosureIndicator : .none + + return cell + + case let .textImage(text, image): + let cell = tableView.dequeueReusableCell(withIdentifier: ResultRow.TableViewCellIdentifier.textImage.rawValue, for: indexPath) as! TextImageTableViewCell + + cell.leftTextLabel.text = text + cell.rightImageView.image = image + + if #available(iOS 13.0, *) { + cell.leftTextLabel.textColor = UIColor.label + } + + return cell + + case let .image(image): + let cell = tableView.dequeueReusableCell(withIdentifier: ResultRow.TableViewCellIdentifier.image.rawValue, for: indexPath) as! ImageTableViewCell + + cell.fullImageView.image = image + + return cell + } + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return section == 0 ? "Result" : nil + } + + // MARK: Overridable Methods + + func resultRowsForSection(_ section: Int) -> [ResultRow] { + // Default to an empty array. + guard section == 0 else { return [] } + + return [ + // The class name of the result object. + ResultRow(text: "type", detail: type(of: result)), + + /* + The identifier of the result, which corresponds to the task, + step or item that generated it. + */ + ResultRow(text: "identifier", detail: result.identifier), + + // The start date for the result. + ResultRow(text: "start", detail: result.startDate), + + // The end date for the result. + ResultRow(text: "end", detail: result.endDate) + ] + } +} + +/// Table view provider specific to an `ORKBooleanQuestionResult` instance. +class BooleanQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let boolResult = result as! ORKBooleanQuestionResult + + var boolResultDetailText: String? + if let booleanAnswer = boolResult.booleanAnswer { + boolResultDetailText = booleanAnswer.boolValue ? "true" : "false" + } + + return super.resultRowsForSection(section) + [ + ResultRow(text: "bool", detail: boolResultDetailText) + ] + } +} + +/// Table view provider specific to an `ORKChoiceQuestionResult` instance. +class ChoiceQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let choiceResult = result as! ORKChoiceQuestionResult + + return super.resultRowsForSection(section) + [ + ResultRow(text: "choices", detail: choiceResult.choiceAnswers) + ] + } +} + + +/// Table view provider specific to an `ORKDateQuestionResult` instance. +class DateQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKDateQuestionResult + + return super.resultRowsForSection(section) + [ + // The date the user entered. + ResultRow(text: "dateAnswer", detail: questionResult.dateAnswer), + + // The calendar that was used when the date picker was presented. + ResultRow(text: "calendar", detail: questionResult.calendar), + + // The timezone when the user answered. + ResultRow(text: "timeZone", detail: questionResult.timeZone) + ] + } +} + +/// Table view provider specific to an `ORKLocationQuestionResult` instance. +class LocationQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKLocationQuestionResult + let location = questionResult.locationAnswer + let address = CNPostalAddressFormatter.string(from: (location?.postalAddress)!, style: .mailingAddress) + let rows = super.resultRowsForSection(section) + [ + // The latitude of the location the user entered. + ResultRow(text: "latitude", detail: location?.coordinate.latitude), + ResultRow(text: "longitude", detail: location?.coordinate.longitude), + ResultRow(text: "address", detail: address) + ] + + return rows + } +} + +/// Table view provider specific to an `ORKNumericQuestionResult` instance. +class NumericQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKNumericQuestionResult + + return super.resultRowsForSection(section) + [ + // The numeric value the user entered. + ResultRow(text: "numericAnswer", detail: questionResult.numericAnswer), + + // The unit string that was displayed with the numeric value. + ResultRow(text: "unit", detail: questionResult.unit) + ] + } +} + +/// Table view provider specific to an `ORKScaleQuestionResult` instance. +class ScaleQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let scaleQuestionResult = result as! ORKScaleQuestionResult + + return super.resultRowsForSection(section) + [ + // The numeric value returned from the discrete or continuous slider. + ResultRow(text: "scaleAnswer", detail: scaleQuestionResult.scaleAnswer) + ] + } +} + +/// Table view provider specific to an `ORKTextQuestionResult` instance. +class TextQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKTextQuestionResult + + return super.resultRowsForSection(section) + [ + // The text the user typed into the text view. + ResultRow(text: "textAnswer", detail: questionResult.textAnswer) + ] + } +} + +/// Table view provider specific to an `ORKTimeIntervalQuestionResult` instance. +class TimeIntervalQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKTimeIntervalQuestionResult + + return super.resultRowsForSection(section) + [ + // The time interval the user answered. + ResultRow(text: "intervalAnswer", detail: questionResult.intervalAnswer) + ] + } +} + +/// Table view provider specific to an `ORKTimeOfDayQuestionResult` instance. +class TimeOfDayQuestionResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKTimeOfDayQuestionResult + + // Format the date components received in the result. + let dateComponentsFormatter = DateComponentsFormatter() + let dateComponentsAnswerText = dateComponentsFormatter.string(from: questionResult.dateComponentsAnswer!) + + return super.resultRowsForSection(section) + [ + // String summarizing the date components the user entered. + ResultRow(text: "dateComponentsAnswer", detail: dateComponentsAnswerText) + ] + } +} + +/// Table view provider specific to an `ORKConsentSignatureResult` instance. +class ConsentSignatureResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let signatureResult = result as! ORKConsentSignatureResult + let signature = signatureResult.signature! + + return super.resultRowsForSection(section) + [ + /* + The identifier for the signature, identifying which one it is in + the document. + */ + ResultRow(text: "identifier", detail: signature.identifier), + + /* + The title of the signatory, displayed under the line. For + example, "Participant". + */ + ResultRow(text: "title", detail: signature.title), + + // The given name of the signatory. + ResultRow(text: "givenName", detail: signature.givenName), + + // The family name of the signatory. + ResultRow(text: "familyName", detail: signature.familyName), + + // The date the signature was obtained. + ResultRow(text: "date", detail: signature.signatureDate), + + // The captured image. + .textImage("signature", image: signature.signatureImage) + ] + } + + func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat { + let lastRow = self.tableView(tableView, numberOfRowsInSection: (indexPath as NSIndexPath).section) - 1 + + if (indexPath as NSIndexPath).row == lastRow { + return 200 + } + + return UITableView.automaticDimension + } +} + +/// Table view provider specific to an `ORKAmslerGridResult` instance. +class AmslerGridResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let amslerGridResult = result as! ORKAmslerGridResult + let image = amslerGridResult.image! + let eyeSide: String = amslerGridResult.eyeSide.rawValue == 0 ? "Not Specified": amslerGridResult.eyeSide.rawValue == 1 ? "Left": "Right" + + return super.resultRowsForSection(section) + [ + // The captured image. + ResultRow(text: "Eye Side", detail: eyeSide), + .textImage("image", image: image) + ] + } + + func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat { + let lastRow = self.tableView(tableView, numberOfRowsInSection: (indexPath as NSIndexPath).section) - 1 + + if (indexPath as NSIndexPath).row == lastRow { + return 300 + } + + return UITableView.automaticDimension + } +} + +/// Table view provider specific to an `ORKPasscodeResult` instance. +class PasscodeResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let passcodeResult = result as! ORKPasscodeResult + + var passcodeResultDetailText: String? + passcodeResultDetailText = passcodeResult.isPasscodeSaved ? "true" : "false" + + return super.resultRowsForSection(section) + [ + ResultRow(text: "passcodeSaved", detail: passcodeResultDetailText) + ] + } +} + +/// Table view provider specific to an `ORKFileResult` instance. +class FileResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKFileResult + + let rows = super.resultRowsForSection(section) + [ + // The MIME content type for the file produced. + ResultRow(text: "contentType", detail: questionResult.contentType), + + // The URL of the generated file on disk. + ResultRow(text: "fileURL", detail: questionResult.fileURL) + ] + + + if let fileURL = questionResult.fileURL, let contentType = questionResult.contentType, contentType.hasPrefix("image/"), !contentType.hasSuffix(".dng") { + + if let image = UIImage(contentsOfFile: fileURL.path) { + return rows + [ + // The image of the generated file on disk. + .image(image) + ] + } + } + + return rows + } + + func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: IndexPath) -> CGFloat { + let resultRows = resultRowsForSection((indexPath as NSIndexPath).section) + + if !resultRows.isEmpty { + switch resultRows[(indexPath as NSIndexPath).row] { + case .image(.some(let image)): + // Keep the aspect ratio the same. + let imageAspectRatio = image.size.width / image.size.height + + return tableView.frame.size.width / imageAspectRatio + + default: + break + } + } + + return UITableView.automaticDimension + } +} + +/// Table view provider specific to an `ORKSpatialSpanMemoryResult` instance. +class SpatialSpanMemoryResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Game Records" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKSpatialSpanMemoryResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + // The score the user received for the game as a whole. + ResultRow(text: "score", detail: questionResult.score), + + // The number of games played. + ResultRow(text: "numberOfGames", detail: questionResult.numberOfGames), + + // The number of failures. + ResultRow(text: "numberOfFailures", detail: questionResult.numberOfFailures) + ] + } + + return rows + questionResult.gameRecords!.map { gameRecord in + // Note `gameRecord` is of type `ORKSpatialSpanMemoryGameRecord`. + return ResultRow(text: "game", detail: gameRecord.score) + } + } +} + +/// Table view provider specific to an `ORKSpeechRecognitionResult` instance. +class SpeechRecognitionResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + let speechRecognitionResult = result as! ORKSpeechRecognitionResult + if let segments = speechRecognitionResult.transcription?.segments { + return segments.count + 1 + } else { + return 2 + } + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + let speechRecognitionResult = result as! ORKSpeechRecognitionResult + if speechRecognitionResult.transcription?.segments != nil { + return "Transcritption " + String(section) + } else { + return "Error" + } + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let speechRecognitionResult = result as! ORKSpeechRecognitionResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + } + + if let segments = speechRecognitionResult.transcription?.segments { + let segement = segments[section - 1] + return [ + ResultRow(text: "substring", detail: segement.substring), + ResultRow(text: "confidence", detail: segement.confidence), + ResultRow(text: "timestamp", detail: segement.timestamp), + ResultRow(text: "duration", detail: segement.duration) + ] + } else { + return [ResultRow(text: "error", detail: "speech recognition failed or cancelled")] + } + } +} + +/// Table view provider specific to an `ORKStroopResult` instance. +class StroopResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Samples" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let stroopResult = result as! ORKStroopResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + } + return [ + ResultRow(text: "Color", detail: stroopResult.color), + ResultRow(text: "Text", detail: stroopResult.text), + ResultRow(text: "Color Selected", detail: stroopResult.colorSelected) + ] + } +} + +/// Table view provider specific to an `ResearchKit.ORKSStroopResult` instance. +class SwiftStroopResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Samples" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let stroopResult = result as! ResearchKit.ORKSwiftStroopResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + } + return [ + ResultRow(text: "Color", detail: stroopResult.color), + ResultRow(text: "Text", detail: stroopResult.text), + ResultRow(text: "Color Selected", detail: stroopResult.colorSelected) + ] + } +} + +/// Table view provider specific to an `ORKTappingIntervalResult` instance. +class TappingIntervalResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Samples" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let questionResult = result as! ORKTappingIntervalResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + // The size of the view where the two target buttons are displayed. + ResultRow(text: "stepViewSize", detail: questionResult.stepViewSize), + + // The rect corresponding to the left button. + ResultRow(text: "buttonRect1", detail: questionResult.buttonRect1), + + // The rect corresponding to the right button. + ResultRow(text: "buttonRect2", detail: questionResult.buttonRect2) + ] + } + + // Add a `ResultRow` for each sample. + return rows + questionResult.samples!.map { tappingSample in + + // These tap locations are relative to the rectangle defined by `stepViewSize`. + let buttonText = tappingSample.buttonIdentifier == .none ? "None" : "button \(tappingSample.buttonIdentifier.rawValue)" + + let text = String(format: "%.3f", tappingSample.timestamp) + let detail = "\(buttonText) \(tappingSample.location)" + + return ResultRow(text: text, detail: detail) + } + } +} + +/// Table view provider specific to an `ORKToneAudiometryResult` instance. +class ToneAudiometryResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Samples" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let toneAudiometryResult = result as! ORKToneAudiometryResult + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + // The size of the view where the two target buttons are displayed. + ResultRow(text: "outputVolume", detail: toneAudiometryResult.outputVolume) + ] + } + + // Add a `ResultRow` for each sample. + return rows + toneAudiometryResult.samples!.map { toneSample in + let text: String + let detail: String + + let channelName = toneSample.channel == .left ? "Left" : "Right" + let correct = toneSample.channelSelected == toneSample.channel ? "Correct" : "Incorrect" + + text = "\(toneSample.frequency) \(channelName)" + detail = "\(toneSample.amplitude) \(correct)" + + return ResultRow(text: text, detail: detail) + } + } +} + +/// Table view provider specific to an `ORKReactionTimeResult` instance. +class ReactionTimeViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "File Results" + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let reactionTimeResult = result as! ORKReactionTimeResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + ResultRow(text: "timestamp", detail: reactionTimeResult.timestamp) + ] + } + + let fileResultDetail = reactionTimeResult.fileResult.fileURL!.absoluteString + + return rows + [ + ResultRow(text: "File Result", detail: fileResultDetail) + ] + } +} + +/// Table view provider specific to an `ORKRangeOfMotionResult` instance. +class RangeOfMotionResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let rangeOfMotionResult = result as! ORKRangeOfMotionResult + let rows = super.resultRowsForSection(section) + return rows + [ + ResultRow(text: "start", detail: rangeOfMotionResult.start), + ResultRow(text: "finish", detail: rangeOfMotionResult.finish), + ResultRow(text: "minimum", detail: rangeOfMotionResult.minimum), + ResultRow(text: "maximum", detail: rangeOfMotionResult.maximum), + ResultRow(text: "range", detail: rangeOfMotionResult.range) + ] + } +} + +/// Table view provider specific to an `ORKTowerOfHanoiResult` instance. +class TowerOfHanoiResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + let towerOfHanoiResult = result as! ORKTowerOfHanoiResult + return towerOfHanoiResult.moves != nil ? (towerOfHanoiResult.moves!.count + 1) : 1 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Move \(section )" + } + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let towerOfHanoiResult = result as! ORKTowerOfHanoiResult + let rows = super.resultRowsForSection(section) + if section == 0 { + return rows + [ + ResultRow(text: "solved", detail: towerOfHanoiResult.puzzleWasSolved ? "true" : "false"), + ResultRow(text: "moves", detail: "\(towerOfHanoiResult.moves?.count ?? 0 )")] + } + // Add a `ResultRow` for each sample. + let move = towerOfHanoiResult.moves![section - 1] + return rows + [ + ResultRow(text: "donor tower", detail: "\(move.donorTowerIndex)"), + ResultRow(text: "recipient tower", detail: "\(move.recipientTowerIndex)"), + ResultRow(text: "timestamp", detail: "\(move.timestamp)")] + } +} + +/// Table view provider specific to an `ORKTrailmaking` instance. +class TrailmakingResultTableViewProvider: ResultTableViewProvider { +// MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let rows = super.resultRowsForSection(section) + return rows + } +} + +/// Table view provider specific to an `ORKPSATResult` instance. +class PSATResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Answers" + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: IndexPath) -> Bool { + return false + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let PSATResult = result as! ORKPSATResult + + var rows = super.resultRowsForSection(section) + + if section == 0 { + var presentation = "" + let presentationMode = PSATResult.presentationMode + if presentationMode == .auditory { + presentation = "PASAT" + } else if presentationMode == .visual { + presentation = "PVSAT" + } else if presentationMode.contains(.auditory) && presentationMode.contains(.visual) { + presentation = "PAVSAT" + } else { + presentation = "Unknown" + } + + // The presentation mode (auditory and/or visual) of the PSAT. + rows.append(ResultRow(text: "presentation", detail: presentation)) + + // The time interval between two digits. + rows.append(ResultRow(text: "ISI", detail: PSATResult.interStimulusInterval)) + + // The time duration the digit is shown on screen. + rows.append(ResultRow(text: "stimulus", detail: PSATResult.stimulusDuration)) + + // The serie length of the PSAT. + rows.append(ResultRow(text: "length", detail: PSATResult.length)) + + // The number of correct answers. + rows.append(ResultRow(text: "total correct", detail: PSATResult.totalCorrect)) + + // The total number of consecutive correct answers. + rows.append(ResultRow(text: "total dyad", detail: PSATResult.totalDyad)) + + // The total time for the answers. + rows.append(ResultRow(text: "total time", detail: PSATResult.totalTime)) + + // The initial digit number. + rows.append(ResultRow(text: "initial digit", detail: PSATResult.initialDigit)) + + return rows + } + + // Add a `ResultRow` for each sample. + return rows + PSATResult.samples!.map { sample in + let PSATSample = sample + + let text = String(format: "%@", PSATSample.isCorrect ? "correct" : "error") + let detail = "\(PSATSample.answer) (digit: \(PSATSample.digit), time: \(PSATSample.time))" + + return ResultRow(text: text, detail: detail) + } + } +} + +/// Table view provider specific to an `ORKTimedWalkResult` instance. +class TimedWalkResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 1 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: IndexPath) -> Bool { + return false + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let timedWalkResult = result as! ORKTimedWalkResult + + let rows = super.resultRowsForSection(section) + + return rows + [ + // The timed walk distance in meters. + ResultRow(text: "distance (m)", detail: timedWalkResult.distanceInMeters), + + // The time limit to complete the trials. + ResultRow(text: "time limit (s)", detail: timedWalkResult.timeLimit), + + // The duration for a Timed Walk. + ResultRow(text: "duration (s)", detail: timedWalkResult.duration) + ] + } +} + +/// Table view provider specific to an `ORKHolePegTestResult` instance. +class HolePegTestResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Moves" + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: IndexPath) -> Bool { + return false + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let holePegTestResult = result as! ORKHolePegTestResult + + var rows = super.resultRowsForSection(section) + + if section == 0 { + var side = "" + let movingDirection = holePegTestResult.movingDirection + if movingDirection == .left { + side = "left > right" + } else if movingDirection == .right { + side = "right > left" + } + + // The hole peg test moving direction. + rows.append(ResultRow(text: "direction", detail: side)) + + // The step is for the dominant hand. + rows.append(ResultRow(text: "dominant hand", detail: holePegTestResult.isDominantHandTested)) + + // The number of pegs to test. + rows.append(ResultRow(text: "number of pegs", detail: holePegTestResult.numberOfPegs)) + + // The detection area sensitivity. + rows.append(ResultRow(text: "threshold", detail: holePegTestResult.threshold)) + + // The hole peg test also assesses the rotation capabilities. + if result.identifier.range(of: "place") != nil { + rows.append(ResultRow(text: "rotated", detail: holePegTestResult.isRotated)) + } + + // The number of succeeded moves (out of `numberOfPegs` possible). + rows.append(ResultRow(text: "total successes", detail: holePegTestResult.totalSuccesses)) + + // The number of failed moves. + rows.append(ResultRow(text: "total failures", detail: holePegTestResult.totalFailures)) + + // The total time needed to perform the test step (ie. the sum of all samples time). + rows.append(ResultRow(text: "total time", detail: holePegTestResult.totalTime)) + + // The total distance needed to perform the test step (ie. the sum of all samples distance). + rows.append(ResultRow(text: "total distance", detail: holePegTestResult.totalDistance)) + + return rows + } + + // Add a `ResultRow` for each sample. + return rows + holePegTestResult.samples!.map { sample in + let holePegTestSample = sample as! ORKHolePegTestSample + + let text = "time (s): \(holePegTestSample.time))" + let detail = "distance (pt): \(holePegTestSample.distance)" + + return ResultRow(text: text, detail: detail) + } + } +} + +/// Table view provider specific to an `ORKTaskResult` instance. +class TaskResultTableViewProvider: CollectionResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let taskResult = result as! ORKTaskResult + + let rows = super.resultRowsForSection(section) + + if section == 0 && (taskResult.results?.count)! > 0 { + return rows + [ + ResultRow(text: "taskRunUUID", detail: taskResult.taskRunUUID.uuidString), + ResultRow(text: "outputDirectory", detail: taskResult.outputDirectory) + ] + } + + return rows + } +} + +/// Table view provider specific to an `ORKCollectionResult` instance. +class CollectionResultTableViewProvider: ResultTableViewProvider { + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return 2 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if section == 0 { + return super.tableView(tableView, titleForHeaderInSection: 0) + } + + return "Child Results" + } + + // MARK: UITableViewDelegate + + func tableView(_ tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: IndexPath) -> Bool { + return (indexPath as NSIndexPath).section == 1 + } + + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let collectionResult = result as! ORKCollectionResult + + let rows = super.resultRowsForSection(section) + + // Show the child results in section 1. + if section == 1 { + return rows + collectionResult.results!.map { childResult in + let childResultClassName = "\(type(of: childResult))" + + return ResultRow(text: childResultClassName, detail: childResult.identifier, selectable: true) + } + } + + return rows + } +} + +/// Table view provider specific to an `ORKVideoInstructionStepResult` instance. +class VideoInstructionStepResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let videoInstructionStepResult = result as! ORKVideoInstructionStepResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + ResultRow(text: "playbackStoppedTime", detail: videoInstructionStepResult.playbackStoppedTime), + ResultRow(text: "playbackCompleted", detail: videoInstructionStepResult.playbackCompleted) + ] + } + + return rows + } +} + +/// Table view provider specific to an `ORKWebViewStepResult` instance. +class WebViewStepResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let webViewStepResult = result as! ORKWebViewStepResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + ResultRow(text: "result", detail: webViewStepResult.result) + ] + } + + return rows + } +} + +class LandoltCStepResultProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let landoltCResult = result as! ORKLandoltCResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + ResultRow(text: "outcome", detail: landoltCResult.outcome), + ResultRow(text: "letterAngle", detail: landoltCResult.letterAngle), + ResultRow(text: "sliderAngle", detail: landoltCResult.sliderAngle), + ResultRow(text: "score", detail: landoltCResult.score) + ] + } + + return rows + } +} + +/// Table view provider specific to an `ORKEnvironmentSPLMeterResult` instance. +class SPLMeterStepResultTableViewProvider: ResultTableViewProvider { + // MARK: ResultTableViewProvider + + override func resultRowsForSection(_ section: Int) -> [ResultRow] { + let splMeterResult = result as! ORKEnvironmentSPLMeterResult + + let rows = super.resultRowsForSection(section) + + if section == 0 { + return rows + [ + ResultRow(text: "sensitivityOffset", detail: splMeterResult.sensitivityOffset), + ResultRow(text: "recordedSPLMeterSamples", detail: splMeterResult.recordedSPLMeterSamples) + ] + } + + return rows + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultViewController.swift new file mode 100755 index 0000000..866b59c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/ResultViewController.swift @@ -0,0 +1,125 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +/** + The purpose of this view controller is to show you the kinds of data + you can fetch from a specific `ORKResult`. The intention is for this view + controller to be purely for demonstration and testing purposes--specifically, + it should not ever be shown to a user. Because of this, the UI for this view + controller is not localized. +*/ +class ResultViewController: UITableViewController { + // MARK: Types + + enum SegueIdentifier: String { + case showTaskResult = "ShowTaskResult" + } + + // MARK: Properties + + var result: ORKResult? = ORKTaskResult() + + var currentResult: ORKResult? = ORKTaskResult() + + var resultTableViewProvider: UITableViewDataSource & UITableViewDelegate = resultTableViewProviderForResult(ORKTaskResult()) + + // MARK: View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + if #available(iOS 13.0, *) { + self.tableView.backgroundColor = UIColor.systemGroupedBackground + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + /* + Don't update the UI if there hasn't been a change between the currently + displayed result, and the result that has been most recently set on + the `ResultViewController`. + */ +// guard result != currentResult || currentResult == nil else { return } + + // Update the currently displayed result. + currentResult = result + + /* + Display result specific metadata, done by a result table view provider. + Although we're not going to use `resultTableViewProvider` directly, + we need to maintain a reference to it so that it can remain "alive" + while its the table view's delegate and data source. + */ + resultTableViewProvider = resultTableViewProviderForResult(result) + + tableView.dataSource = resultTableViewProvider + tableView.delegate = resultTableViewProvider + } + + // MARK: UIStoryboardSegue Handling + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + /* + Check to see if the segue identifier is meant for presenting a new + result view controller. + */ + if let identifier = segue.identifier, + let segueIdentifier = SegueIdentifier(rawValue: identifier), segueIdentifier == .showTaskResult { + + let cell = sender as! UITableViewCell + + let indexPath = tableView.indexPath(for: cell)! + + let destinationViewController = segue.destination as! ResultViewController + + let collectionResult = result as! ORKCollectionResult + + destinationViewController.result = collectionResult.results![(indexPath as NSIndexPath).row] + } + } + + override func shouldPerformSegue(withIdentifier segueIdentifier: String?, sender: Any?) -> Bool { + /* + Only perform a segue if the cell that was tapped has a disclosure + indicator. These are the only kinds of cells that we allow to perform + segues in a `ResultViewController`. + */ + if let cell = sender as? UITableViewCell { + return cell.accessoryType == .disclosureIndicator + } + + return false + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/TextImageTableViewCell.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/TextImageTableViewCell.swift new file mode 100755 index 0000000..7efe734 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Results/TextImageTableViewCell.swift @@ -0,0 +1,44 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +/** + A simple `UITableViewCell` subclass that can display an image view and label. + Properties in this table view cell are set in Interface Builder in the main + storyboard. +*/ +class TextImageTableViewCell: UITableViewCell { + // MARK: Properties + + @IBOutlet weak var leftTextLabel: UILabel! + + @IBOutlet weak var rightImageView: UIImageView! +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/Info.plist new file mode 100755 index 0000000..259daca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/Info.plist @@ -0,0 +1,64 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.3 + CFBundleSignature + ???? + CFBundleVersion + 1.3 + LSRequiresIPhoneOS + + NSCameraUsageDescription + This app captures photos and video during certain tasks. + NSFaceIDUsageDescription + This app uses Face ID during passcode step. + NSHealthClinicalHealthRecordsShareUsageDescription + This app reads your Health Records data during certain tasks. + NSHealthShareUsageDescription + This app reads your HealthKit data during certain tasks. + NSLocationWhenInUseUsageDescription + This app records your location during certain tasks. + NSMicrophoneUsageDescription + This app records audio during certain tasks. + NSMotionUsageDescription + This app records motion data during certain tasks. + NSSpeechRecognitionUsageDescription + This app uses Speech Recognition during certain tasks. + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarTintParameters + + UINavigationBar + + Style + UIBarStyleDefault + Translucent + + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/ORKCatalog.entitlements b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/ORKCatalog.entitlements new file mode 100755 index 0000000..e10f430 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Supporting Files/ORKCatalog.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.healthkit + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/TaskListRow.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/TaskListRow.swift new file mode 100755 index 0000000..584b9fb --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/TaskListRow.swift @@ -0,0 +1,962 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit +import AudioToolbox + +/** + An enum that corresponds to a row displayed in a `TaskListViewController`. + + Each of the tasks is composed of one or more steps giving examples of the + types of functionality supported by the ResearchKit framework. +*/ +enum TaskListRow: Int, Printable { + case scaleQuestion = 0 + case numericQuestion + case timeOfDayQuestion + case dateQuestion + case dateTimeQuestion + case timeIntervalQuestion + case textQuestion + case valuePickerChoiceQuestion + case textChoiceQuestion + case imageChoiceQuestion + case booleanQuestion + case twoFingerTappingInterval + case spatialSpanMemory + case fitness + case shortWalk + case audio + case toneAudiometry + case reactionTime + case towerOfHanoi + case psat + case timedWalk + case holePegTest + case imageCapture + case survey + case consent + case form + + /// Returns an array of all the task list row enum cases. + static var allCases: [TaskListRow] { + /* + Create a generator that creates a `TaskListRow` at a specific index. + When `TaskListRow`'s `rawValue` initializer returns `nil`, the generator + will stop generating values. This will happen when the enum has no more + cases represented by `caseIndex`. + */ + var caseIndex = 0 + let caseGenerator = GeneratorOf { TaskListRow(rawValue: caseIndex++) } + + // Create a sequence that will consume the generator to create an array. + let caseSequence = SequenceOf(caseGenerator) + + return Array(caseSequence) + } + + // MARK: Printable + + var description: String { + switch self { + case .ScaleQuestion: + return NSLocalizedString("Scale Question", comment: "") + + case .NumericQuestion: + return NSLocalizedString("Numeric Question", comment: "") + + case .TimeOfDayQuestion: + return NSLocalizedString("Time of Day Question", comment: "") + + case .DateQuestion: + return NSLocalizedString("Date Question", comment: "") + + case .DateTimeQuestion: + return NSLocalizedString("Date and Time Question", comment: "") + + case .TimeIntervalQuestion: + return NSLocalizedString("Time Interval Question", comment: "") + + case .TextQuestion: + return NSLocalizedString("Text Question", comment: "") + + case .ValuePickerChoiceQuestion: + return NSLocalizedString("Value Picker Choice Question", comment: "") + + case .TextChoiceQuestion: + return NSLocalizedString("Text Choice Question", comment: "") + + case .ImageChoiceQuestion: + return NSLocalizedString("Image Choice Question", comment: "") + + case .BooleanQuestion: + return NSLocalizedString("Boolean Question", comment: "") + + case .TwoFingerTappingInterval: + return NSLocalizedString("Two Finger Tapping Interval Active Task", comment: "") + + case .SpatialSpanMemory: + return NSLocalizedString("Spatial Span Memory Active Task", comment: "") + + case .Fitness: + return NSLocalizedString("Fitness Check Active Task", comment: "") + + case .ShortWalk: + return NSLocalizedString("Short Walk Active Task", comment: "") + + case .Audio: + return NSLocalizedString("Audio Active Task", comment: "") + + case .ToneAudiometry: + return NSLocalizedString("Tone Audiometry Active Task", comment: "") + + case .ReactionTime: + return NSLocalizedString("Reaction Time Active Task", comment: "") + + case .TowerOfHanoi: + return NSLocalizedString("Tower of Hanoi Active Task", comment: "") + + case .PSAT: + return NSLocalizedString("PSAT Active Task", comment: "") + + case .TimedWalk: + return NSLocalizedString("Timed Walk", comment: "") + + case .HolePegTest: + return NSLocalizedString("Hole Peg Test Task", comment: "") + + case .ImageCapture: + return NSLocalizedString("Image Capture Task", comment: "") + + case .Survey: + return NSLocalizedString("Simple Survey", comment: "") + + case .Consent: + return NSLocalizedString("Consent", comment: "") + + case .Form: + return NSLocalizedString("Form", comment: "") + } + } + + // MARK: Types + + /** + Every step and task in the ResearchKit framework has to have an identifier. Within a + task, the step identifiers should be unique. + + Here we use an enum to ensure that the identifiers are kept unique. Since + the enum has a raw underlying type of a `String`, the compiler can determine + the uniqueness of the case values at compile time. + + In a real application, the identifiers for your tasks and steps might + come from a database, or in a smaller application, might have some + human-readable meaning. + */ + private enum Identifier: String { + // Task with examples of questions with sliding scales. + case scaleQuestionTask = "ScaleQuestionTask" + case discreteScaleQuestionStep = "DiscreteScaleQuestionStep" + case continuousScaleQuestionStep = "ContinuousScaleQuestionStep" + case discreteVerticalScaleQuestionStep = "DiscreteVerticalScaleQuestionStep" + case continuousVerticalScaleQuestionStep = "ContinuousVerticalScaleQuestionStep" + + // Task with examples of numeric questions. + case numericQuestionTask = "NumericQuestionTask" + case numericQuestionStep = "NumericQuestionStep" + case numericNoUnitQuestionStep = "NumericNoUnitQuestionStep" + + // Task with an example of time of day entry. + case timeOfDayQuestionTask = "TimeOfDayQuestionTask" + case timeOfDayQuestionStep = "TimeOfDayQuestionStep" + + // Task with an example of date entry. + case dateQuestionTask = "DateQuestionTask" + case dateQuestionStep = "DateQuestionStep" + + // Task with an example of date and time entry. + case dateTimeQuestionTask = "DateTimeQuestionTask" + case dateTimeQuestionStep = "DateTimeQuestionStep" + + // Task with an example of time interval entry. + case timeIntervalQuestionTask = "TimeIntervalQuestionTask" + case timeIntervalQuestionStep = "TimeIntervalQuestionStep" + + // Task with an example of free text entry. + case textQuestionTask = "TextQuestionTask" + case textQuestionStep = "TextQuestionStep" + + // Task with a value picker. + case valuePickerChoiceQuestionTask = "ValuePickerChoiceQuestionTask" + case valuePickerChoiceQuestionStep = "ValuePickerChoiceQuestionStep" + + // Task with an example of a multiple choice question. + case textChoiceQuestionTask = "TextChoiceQuestionTask" + case textChoiceQuestionStep = "TextChoiceQuestionStep" + + // Task with an image choice question. + case imageChoiceQuestionTask = "ImageChoiceQuestionTask" + case imageChoiceQuestionStep = "ImageChoiceQuestionStep" + + // Survey example with a Boolean question. + case booleanQuestionTask = "BooleanQuestionTask" + case booleanQuestionStep = "BooleanQuestionStep" + + // Active tasks. + case twoFingerTappingIntervalTask = "TwoFingerTappingIntervalTask" + case spatialSpanMemoryTask = "SpatialSpanMemoryTask" + case fitnessTask = "FitnessTask" + case shortWalkTask = "ShortWalkTask" + case audioTask = "AudioTask" + case toneAudiometryTask = "ToneAudiometry" + case reactionTime = "ReactionTime" + case towerOfHanoi = "TowerOfHanoi" + case psatTask = "PSATTask" + case timedWalkTask = "TimedWalkTask" + case holePegTestTask = "HolePegTestTask" + + // Image capture task specific identifiers. + case imageCaptureTask = "ImageCaptureTask" + case imageCaptureStep = "ImageCaptureStep" + + // Survey task specific identifiers. + case surveyTask = "SurveyTask" + case introStep = "IntroStep" + case questionStep = "QuestionStep" + case summaryStep = "SummaryStep" + + // Consent task specific identifiers. + case consentTask = "ConsentTask" + case visualConsentStep = "VisualConsentStep" + case consentSharingStep = "ConsentSharingStep" + case consentReviewStep = "ConsentReviewStep" + case consentDocumentParticipantSignature = "ConsentDocumentParticipantSignature" + case consentDocumentInvestigatorSignature = "ConsentDocumentInvestigatorSignature" + + // Task with a form, where multiple items appear on one page. + case formTask = "FormTask" + case formStep = "FormStep" + case formItem01 = "FormItem01" + case formItem02 = "FormItem02" + } + + // MARK: Properties + + /// Returns a new `ORKTask` that the `TaskListRow` enumeration represents. + var representedTask: ORKTask { + switch self { + case .ScaleQuestion: + return scaleQuestionTask + + case .NumericQuestion: + return numericQuestionTask + + case .TimeOfDayQuestion: + return timeOfDayQuestionTask + + case .DateQuestion: + return dateQuestionTask + + case .DateTimeQuestion: + return dateTimeQuestionTask + + case .TimeIntervalQuestion: + return timeIntervalQuestionTask + + case .TextQuestion: + return textQuestionTask + + case .ValuePickerChoiceQuestion: + return valuePickerChoiceQuestionTask + + case .TextChoiceQuestion: + return textChoiceQuestionTask + + case .ImageChoiceQuestion: + return imageChoiceQuestionTask + + case .BooleanQuestion: + return booleanQuestionTask + + case .TwoFingerTappingInterval: + return twoFingerTappingIntervalTask + + case .SpatialSpanMemory: + return spatialSpanMemoryTask + + case .Fitness: + return fitnessTask + + case .ShortWalk: + return shortWalkTask + + case .Audio: + return audioTask + + case .ToneAudiometry: + return toneAudiometryTask + + case .ReactionTime: + return reactionTimeTask + + case .TowerOfHanoi: + return towerOfHanoiTask + + case .PSAT: + return PSATTask + + case .TimedWalk: + return TimedWalkTask + + case .HolePegTest: + return holePegTestTask + + case .ImageCapture: + return imageCaptureTask + + case .Survey: + return surveyTask + + case .Consent: + return consentTask + + case .Form: + return formTask + } + } + + // MARK: Task Creation Convenience + + /// This task presents two options for questions displaying a scale control. + private var scaleQuestionTask: ORKTask { + var steps = [ORKStep]() + + // The first step is a scale control with 10 discrete ticks. + let step1AnswerFormat = ORKAnswerFormat.scaleAnswerFormatWithMaximumValue(10, minimumValue: 1, defaultValue: NSIntegerMax, step: 1, vertical: false, maximumValueDescription: exampleHighValueText, minimumValueDescription: exampleLowValueText) + + let questionStep1 = ORKQuestionStep(identifier: Identifier.DiscreteScaleQuestionStep.rawValue, title: exampleQuestionText, answer: step1AnswerFormat) + + questionStep1.text = exampleDetailText + + steps += [questionStep1] + + // The second step is a scale control that allows continuous movement with a percent formatter. + let step2AnswerFormat = ORKAnswerFormat.continuousScaleAnswerFormatWithMaximumValue(1.0, minimumValue: 0.0, defaultValue: 99.0, maximumFractionDigits: 0, vertical: false, maximumValueDescription: nil, minimumValueDescription: nil) + step2AnswerFormat.numberStyle = .Percent + + let questionStep2 = ORKQuestionStep(identifier: Identifier.ContinuousScaleQuestionStep.rawValue, title: exampleQuestionText, answer: step2AnswerFormat) + + questionStep2.text = exampleDetailText + + steps += [questionStep2] + + // The third step is a vertical scale control with 10 discrete ticks. + let step3AnswerFormat = ORKAnswerFormat.scaleAnswerFormatWithMaximumValue(10, minimumValue: 1, defaultValue: NSIntegerMax, step: 1, vertical: true, maximumValueDescription: nil, minimumValueDescription: nil) + + let questionStep3 = ORKQuestionStep(identifier: Identifier.DiscreteVerticalScaleQuestionStep.rawValue, title: exampleQuestionText, answer: step3AnswerFormat) + + questionStep3.text = exampleDetailText + + steps += [questionStep3] + + // The fourth step is a vertical scale control that allows continuous movement. + let step4AnswerFormat = ORKAnswerFormat.continuousScaleAnswerFormatWithMaximumValue(5.0, minimumValue: 1.0, defaultValue: 99.0, maximumFractionDigits: 2, vertical: true, maximumValueDescription: exampleHighValueText, minimumValueDescription: exampleLowValueText) + + let questionStep4 = ORKQuestionStep(identifier: Identifier.ContinuousVerticalScaleQuestionStep.rawValue, title: exampleQuestionText, answer: step4AnswerFormat) + + questionStep4.text = exampleDetailText + + steps += [questionStep4] + + return ORKOrderedTask(identifier: Identifier.ScaleQuestionTask.rawValue, steps: steps) + } + + /** + This task demonstrates use of numeric questions with and without units. + Note that the unit is just a string, prompting the user to enter the value + in the expected unit. The unit string propagates into the result object. + */ + private var numericQuestionTask: ORKTask { + var steps = [ORKStep]() + + // This answer format will display a unit in-line with the numeric entry field. + let localizedQuestionStep1AnswerFormatUnit = NSLocalizedString("Your unit", comment: "") + let questionStep1AnswerFormat = ORKAnswerFormat.decimalAnswerFormatWithUnit(localizedQuestionStep1AnswerFormatUnit) + + let questionStep1 = ORKQuestionStep(identifier: Identifier.NumericQuestionStep.rawValue, title: exampleQuestionText, answer: questionStep1AnswerFormat) + + questionStep1.text = exampleDetailText + questionStep1.placeholder = NSLocalizedString("Your placeholder.", comment: "") + + steps += [questionStep1] + + // This answer format is similar to the previous one, but this time without displaying a unit. + let questionStep2 = ORKQuestionStep(identifier: Identifier.NumericNoUnitQuestionStep.rawValue, title: exampleQuestionText, answer: ORKAnswerFormat.decimalAnswerFormatWithUnit(nil)) + + questionStep2.text = exampleDetailText + questionStep2.placeholder = NSLocalizedString("Placeholder without unit.", comment: "") + + steps += [questionStep2] + + return ORKOrderedTask(identifier: Identifier.NumericQuestionTask.rawValue, steps: steps) + } + + /// This task demonstrates a question asking for a time of day. + private var timeOfDayQuestionTask: ORKTask { + /* + Because we don't specify a default, the picker will default to the + time the step is presented. For questions like "What time do you have + breakfast?", it would make sense to set the default on the answer + format. + */ + let answerFormat = ORKAnswerFormat.timeOfDayAnswerFormat() + + let questionStep = ORKQuestionStep(identifier: Identifier.TimeOfDayQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.TimeOfDayQuestionTask.rawValue, steps: [questionStep]) + } + + /// This task demonstrates a question which asks for a date. + private var dateQuestionTask: ORKTask { + /* + The date answer format can also support minimum and maximum limits, + a specific default value, and overriding the calendar to use. + */ + let answerFormat = ORKAnswerFormat.dateAnswerFormat() + + let step = ORKQuestionStep(identifier: Identifier.DateQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.DateQuestionTask.rawValue, steps: [step]) + } + + /// This task demonstrates a question asking for a date and time of an event. + private var dateTimeQuestionTask: ORKTask { + /* + This uses the default calendar. Use a more detailed constructor to + set minimum / maximum limits. + */ + let answerFormat = ORKAnswerFormat.dateTimeAnswerFormat() + + let step = ORKQuestionStep(identifier: Identifier.DateTimeQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.DateTimeQuestionTask.rawValue, steps: [step]) + } + + /** + This task demonstrates requesting a time interval. For example, this might + be a suitable answer format for a question like "How long is your morning + commute?" + */ + private var timeIntervalQuestionTask: ORKTask { + /* + The time interval answer format is constrained to entering a time + less than 24 hours and in steps of minutes. For times that don't fit + these restrictions, use another mode of data entry. + */ + let answerFormat = ORKAnswerFormat.timeIntervalAnswerFormat() + + let step = ORKQuestionStep(identifier: Identifier.TimeIntervalQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.TimeIntervalQuestionTask.rawValue, steps: [step]) + } + + /** + This task demonstrates asking for text entry. Both single and multi-line + text entry are supported, with appropriate parameters to the text answer + format. + */ + private var textQuestionTask: ORKTask { + let answerFormat = ORKAnswerFormat.textAnswerFormat() + + let step = ORKQuestionStep(identifier: Identifier.TextQuestionStep.rawValue, title: exampleQuestionText, answer: ORKAnswerFormat.textAnswerFormat()) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.TextQuestionTask.rawValue, steps: [step]) + } + + /** + This task demonstrates a survey question using a value picker wheel. + Compare with the `textChoiceQuestionTask` and `imageChoiceQuestionTask` + which can serve a similar purpose. + */ + private var valuePickerChoiceQuestionTask: ORKTask { + let textChoiceOneText = NSLocalizedString("Choice 1", comment: "") + let textChoiceTwoText = NSLocalizedString("Choice 2", comment: "") + let textChoiceThreeText = NSLocalizedString("Choice 3", comment: "") + + // The text to display can be separate from the value coded for each choice: + let textChoices = [ + ORKTextChoice(text: textChoiceOneText, value: "choice_1"), + ORKTextChoice(text: textChoiceTwoText, value: "choice_2"), + ORKTextChoice(text: textChoiceThreeText, value: "choice_3") + ] + + let answerFormat = ORKAnswerFormat.valuePickerAnswerFormatWithTextChoices(textChoices) + + let questionStep = ORKQuestionStep(identifier: Identifier.ValuePickerChoiceQuestionStep.rawValue, title: exampleQuestionText, + answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.ValuePickerChoiceQuestionTask.rawValue, steps: [questionStep]) + } + + /** + This task demonstrates a survey question for picking from a list of text + choices. In this case, the text choices are presented in a table view + (compare with the `valuePickerQuestionTask`). + */ + private var textChoiceQuestionTask: ORKTask { + let textChoiceOneText = NSLocalizedString("Choice 1", comment: "") + let textChoiceTwoText = NSLocalizedString("Choice 2", comment: "") + let textChoiceThreeText = NSLocalizedString("Choice 3", comment: "") + + // The text to display can be separate from the value coded for each choice: + let textChoices = [ + ORKTextChoice(text: textChoiceOneText, value: "choice_1"), + ORKTextChoice(text: textChoiceTwoText, value: "choice_2"), + ORKTextChoice(text: textChoiceThreeText, value: "choice_3") + ] + + let answerFormat = ORKAnswerFormat.choiceAnswerFormatWithStyle(.SingleChoice, textChoices: textChoices) + + let questionStep = ORKQuestionStep(identifier: Identifier.TextChoiceQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.TextChoiceQuestionTask.rawValue, steps: [questionStep]) + } + + /** + This task demonstrates a survey question involving picking from a series of + image choices. A more realistic applciation of this type of question might be to + use a range of icons for faces ranging from happy to sad. + */ + private var imageChoiceQuestionTask: ORKTask { + let roundShapeImage = UIImage(named: "round_shape")! + let roundShapeText = NSLocalizedString("Round Shape", comment: "") + + let squareShapeImage = UIImage(named: "square_shape")! + let squareShapeText = NSLocalizedString("Square Shape", comment: "") + + let imageChoces = [ + ORKImageChoice(normalImage: roundShapeImage, selectedImage: nil, text: roundShapeText, value: roundShapeText), + ORKImageChoice(normalImage: squareShapeImage, selectedImage: nil, text: squareShapeText, value: squareShapeText) + ] + + let answerFormat = ORKAnswerFormat.choiceAnswerFormatWithImageChoices(imageChoces) + + let questionStep = ORKQuestionStep(identifier: Identifier.ImageChoiceQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.ImageChoiceQuestionTask.rawValue, steps: [questionStep]) + } + + /// This task presents just a single "Yes" / "No" question. + private var booleanQuestionTask: ORKTask { + let answerFormat = ORKBooleanAnswerFormat() + + // We attach an answer format to a question step to specify what controls the user sees. + let questionStep = ORKQuestionStep(identifier: Identifier.BooleanQuestionStep.rawValue, title: exampleQuestionText, answer: answerFormat) + + // The detail text is shown in a small font below the title. + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: Identifier.BooleanQuestionTask.rawValue, steps: [questionStep]) + } + + /// This task presents the Two Finger Tapping pre-defined active task. + private var twoFingerTappingIntervalTask: ORKTask { + return ORKOrderedTask.twoFingerTappingIntervalTaskWithIdentifier(Identifier.TwoFingerTappingIntervalTask.rawValue, intendedUseDescription: exampleDescription, duration: 20, options: nil) + } + + /// This task presents the Spatial Span Memory pre-defined active task. + private var spatialSpanMemoryTask: ORKTask { + return ORKOrderedTask.spatialSpanMemoryTaskWithIdentifier(Identifier.SpatialSpanMemoryTask.rawValue, intendedUseDescription: exampleDescription, initialSpan: 3, minimumSpan: 2, maximumSpan: 15, playSpeed: 1.0, maxTests: 5, maxConsecutiveFailures: 3, customTargetImage: nil, customTargetPluralName: nil, requireReversal: false, options: nil) + } + + /** + This task presents the Fitness pre-defined active task. For this example, + short walking and rest durations of 20 seconds each are used, whereas more + realistic durations might be several minutes each. + */ + private var fitnessTask: ORKTask { + return ORKOrderedTask.fitnessCheckTaskWithIdentifier(Identifier.FitnessTask.rawValue, intendedUseDescription: exampleDescription, walkDuration: 20, restDuration: 20, options: nil) + } + + /// This task presents the Gait and Balance pre-defined active task. + private var shortWalkTask: ORKTask { + return ORKOrderedTask.shortWalkTaskWithIdentifier(Identifier.ShortWalkTask.rawValue, intendedUseDescription: exampleDescription, numberOfStepsPerLeg: 20, restDuration: 20, options: nil) + } + + /// This task presents the Audio pre-defined active task. + private var audioTask: ORKTask { + return ORKOrderedTask.audioTaskWithIdentifier(Identifier.AudioTask.rawValue, intendedUseDescription: exampleDescription, speechInstruction: exampleSpeechInstruction, shortSpeechInstruction: exampleSpeechInstruction, duration: 20, recordingSettings: nil, options: nil) + } + + private var reactionTimeTask: ORKTask { + return ORKOrderedTask.reactionTimeTaskWithIdentifier(Identifier.ReactionTime.rawValue, intendedUseDescription: exampleDescription, maximumStimulusInterval: 10, minimumStimulusInterval: 4, thresholdAcceleration: 0.5, numberOfAttempts: 3, timeout: 3, successSound: exampleSuccessSound, timeoutSound: 0, failureSound: UInt32(kSystemSoundID_Vibrate), options: nil) + } + + private var towerOfHanoiTask: ORKTask { + return ORKOrderedTask.towerOfHanoiTaskWithIdentifier(Identifier.TowerOfHanoi.rawValue, intendedUseDescription: exampleDescription, numberOfDisks: 5, options: nil) + } + + /// This task presents the PSAT pre-defined active task. + private var PSATTask: ORKTask { + return ORKOrderedTask.PSATTaskWithIdentifier(Identifier.PSATTask.rawValue, intendedUseDescription: exampleDescription, presentationMode: (.Auditory | .Visual), interStimulusInterval: 3.0, stimulusDuration: 1.0, seriesLength: 60, options: nil) + } + + /// This task presents the Timed Walk pre-defined active task. + private var timedWalkTask: ORKTask { + return ORKOrderedTask.timedWalkTaskWithIdentifier(String(Identifier.TimedWalkTask), intendedUseDescription: exampleDescription, distanceInMeters: 100.0, timeLimit: 180.0, includeAssistiveDeviceForm: true, options: []) + } + + /// This task presents the Hole Peg Test pre-defined active task. + private var holePegTestTask: ORKTask { + return ORKNavigableOrderedTask.holePegTestTaskWithIdentifier(Identifier.HolePegTestTask.rawValue, intendedUseDescription: exampleDescription, dominantHand: .Right, numberOfPegs: 9, threshold: 0.2, rotated: false, timeLimit: 300, options: nil) + } + + private var exampleSuccessSound: UInt32 { + var successSoundPath: CFURLRef! = NSURL(fileURLWithPath: "///System/Library/Audio/UISounds/Modern/sms_alert_complete.caf") as CFURLRef! + var soundID: SystemSoundID = 0 + AudioServicesCreateSystemSoundID(successSoundPath, &soundID) + return soundID + } + + /// This task presents the Tone Audiometry pre-defined active task. + private var toneAudiometryTask: ORKTask { + return ORKOrderedTask.toneAudiometryTaskWithIdentifier(Identifier.ToneAudiometryTask.rawValue, intendedUseDescription: exampleDescription, speechInstruction: nil, shortSpeechInstruction: nil, toneDuration: 20, options: nil) + } + + /// This task presents the image capture step in an ordered task. + private var imageCaptureTask: ORKTask { + var steps = [ORKStep]() + + // Create the intro step. + let instructionStep = ORKInstructionStep(identifier: Identifier.IntroStep.rawValue) + + instructionStep.title = NSLocalizedString("Sample Survey", comment: "") + + instructionStep.text = exampleDescription + + instructionStep.image = UIImage(named: "hand_solid")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) + + steps += [instructionStep] + + let imageCaptureStep = ORKImageCaptureStep(identifier: Identifier.ImageCaptureStep.rawValue) + imageCaptureStep.optional = false + imageCaptureStep.accessibilityInstructions = NSLocalizedString("Your instructions for capturing the image", comment: "") + imageCaptureStep.accessibilityHint = NSLocalizedString("Captures the image visible in the preview", comment: "") + + imageCaptureStep.templateImage = UIImage(named: "hand_outline_big")! + + imageCaptureStep.templateImageInsets = UIEdgeInsets(top: 0.05, left: 0.05, bottom: 0.05, right: 0.05) + + steps += [imageCaptureStep] + + return ORKOrderedTask(identifier: Identifier.ImageCaptureTask.rawValue, steps: steps) + } + + /** + A task demonstrating how the ResearchKit framework can be used to present a simple + survey with an introduction, a question, and a conclusion. + */ + private var surveyTask: ORKTask { + var steps = [ORKStep]() + + // Create the intro step. + let instructionStep = ORKInstructionStep(identifier: Identifier.IntroStep.rawValue) + + instructionStep.title = NSLocalizedString("Sample Survey", comment: "") + + instructionStep.text = exampleDescription + + steps += [instructionStep] + + // Add a question step. + let questionStepAnswerFormat = ORKBooleanAnswerFormat() + + let questionStepTitle = NSLocalizedString("Would you like to subscribe to our newsletter?", comment: "") + let questionStep = ORKQuestionStep(identifier: Identifier.QuestionStep.rawValue, title: questionStepTitle, answer: questionStepAnswerFormat) + + steps += [questionStep] + + // Add a summary step. + let summaryStep = ORKInstructionStep(identifier: Identifier.SummaryStep.rawValue) + summaryStep.title = NSLocalizedString("Thanks", comment: "") + summaryStep.text = NSLocalizedString("Thank you for participating in this sample survey.", comment: "") + + steps += [summaryStep] + + return ORKOrderedTask(identifier: Identifier.SurveyTask.rawValue, steps: steps) + } + + /// A task demonstrating how the ResearchKit framework can be used to obtain informed consent. + private var consentTask: ORKTask { + var steps = [ORKStep]() + + /* + Informed consent starts by presenting an animated sequence conveying + the main points of your consent document. + */ + let visualConsentStep = ORKVisualConsentStep(identifier: Identifier.VisualConsentStep.rawValue, document: consentDocument) + + steps += [visualConsentStep] + + let investigatorShortDescription = NSLocalizedString("Institution", comment: "") + let investigatorLongDescription = NSLocalizedString("Institution and its partners", comment: "") + let localizedLearnMoreHTMLContent = NSLocalizedString("Your sharing learn more content here.", comment: "") + + /* + If you want to share the data you collect with other researchers for + use in other studies beyond this one, it is best practice to get + explicit permission from the participant. Use the consent sharing step + for this. + */ + let sharingConsentStep = ORKConsentSharingStep(identifier: Identifier.ConsentSharingStep.rawValue, investigatorShortDescription: investigatorShortDescription, investigatorLongDescription: investigatorLongDescription, localizedLearnMoreHTMLContent: localizedLearnMoreHTMLContent) + + steps += [sharingConsentStep] + + /* + After the visual presentation, the consent review step displays + your consent document and can obtain a signature from the participant. + + The first signature in the document is the participant's signature. + This effectively tells the consent review step which signatory is + reviewing the document. + */ + let signature = consentDocument.signatures!.first as? ORKConsentSignature + + let reviewConsentStep = ORKConsentReviewStep(identifier: Identifier.ConsentReviewStep.rawValue, signature: signature, inDocument: consentDocument) + + // In a real application, you would supply your own localized text. + reviewConsentStep.text = loremIpsumText + reviewConsentStep.reasonForConsent = loremIpsumText + + steps += [reviewConsentStep] + + return ORKOrderedTask(identifier: Identifier.ConsentTask.rawValue, steps: steps) + } + + /** + This task demonstrates a form step, in which multiple items are presented + in a single scrollable form. This might be used for entering multi-value + data, like taking a blood pressure reading with separate systolic and + diastolic values. + */ + private var formTask: ORKTask { + let step = ORKFormStep(identifier: Identifier.FormTask.rawValue, title: exampleQuestionText, text: exampleDetailText) + + // A first field, for entering an integer. + let formItem01Text = NSLocalizedString("Field01", comment: "") + let formItem01 = ORKFormItem(identifier: Identifier.FormItem01.rawValue, text: formItem01Text, answerFormat: ORKAnswerFormat.integerAnswerFormatWithUnit(nil)) + formItem01.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + // A second field, for entering a time interval. + let formItem02Text = NSLocalizedString("Field02", comment: "") + let formItem02 = ORKFormItem(identifier: Identifier.FormItem02.rawValue, text: formItem02Text, answerFormat: ORKTimeIntervalAnswerFormat()) + formItem02.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + step.formItems = [formItem01, formItem02] + + return ORKOrderedTask(identifier: Identifier.FormTask.rawValue, steps: [step]) + } + + // MARK: Consent Document Creation Convenience + + /** + A consent document provides the content for the visual consent and consent + review steps. This helper sets up a consent document with some dummy + content. You should populate your consent document to suit your study. + */ + private var consentDocument: ORKConsentDocument { + let consentDocument = ORKConsentDocument() + + /* + This is the title of the document, displayed both for review and in + the generated PDF. + */ + consentDocument.title = NSLocalizedString("Example Consent", comment: "") + + // This is the title of the signature page in the generated document. + consentDocument.signaturePageTitle = NSLocalizedString("Consent", comment: "") + + /* + This is the line shown on the signature page of the generated document, + just above the signatures. + */ + consentDocument.signaturePageContent = NSLocalizedString("I agree to participate in this research study.", comment: "") + + /* + Add the participant signature, which will be filled in during the + consent review process. This signature initially does not have a + signature image or a participant name; these are collected during + the consent review step. + */ + let participantSignatureTitle = NSLocalizedString("Participant", comment: "") + let participantSignature = ORKConsentSignature(forPersonWithTitle: participantSignatureTitle, dateFormatString: nil, identifier: Identifier.ConsentDocumentParticipantSignature.rawValue) + + consentDocument.addSignature(participantSignature) + + /* + Add the investigator signature. This is pre-populated with the + investigator's signature image and name, and the date of their + signature. If you need to specify the date as now, you could generate + a date string with code here. + + This signature is only used for the generated PDF. + */ + let signatureImage = UIImage(named: "signature")! + let investigatorSignatureTitle = NSLocalizedString("Investigator", comment: "") + let investigatorSignatureGivenName = NSLocalizedString("Jonny", comment: "") + let investigatorSignatureFamilyName = NSLocalizedString("Appleseed", comment: "") + let investigatorSignatureDateString = "3/10/15" + + let investigatorSignature = ORKConsentSignature(forPersonWithTitle: investigatorSignatureTitle, dateFormatString: nil, identifier: Identifier.ConsentDocumentInvestigatorSignature.rawValue, givenName: investigatorSignatureGivenName, familyName: investigatorSignatureFamilyName, signatureImage: signatureImage, dateString: investigatorSignatureDateString) + + consentDocument.addSignature(investigatorSignature) + + /* + This is the HTML content for the "Learn More" page for each consent + section. In a real consent, this would be your content, and you would + have different content for each section. + + If your content is just text, you can use the `content` property + instead of the `htmlContent` property of `ORKConsentSection`. + */ + let htmlContentString = "
    • Lorem
    • ipsum
    • dolor

    \(loremIpsumLongText)

    \(loremIpsumMediumText)

    " + + /* + These are all the consent section types that have pre-defined animations + and images. We use them in this specific order, so we see the available + animated transitions. + */ + let consentSectionTypes: [ORKConsentSectionType] = [ + .Overview, + .DataGathering, + .Privacy, + .DataUse, + .TimeCommitment, + .StudySurvey, + .StudyTasks, + .Withdrawing + ] + + /* + For each consent section type in `consentSectionTypes`, create an + `ORKConsentSection` that represents it. + + In a real app, you would set specific content for each section. + */ + var consentSections: [ORKConsentSection] = consentSectionTypes.map { contentSectionType in + let consentSection = ORKConsentSection(type: contentSectionType) + + consentSection.summary = self.loremIpsumShortText + + if contentSectionType == .Overview { + consentSection.htmlContent = htmlContentString + } else { + consentSection.content = self.loremIpsumLongText + } + + return consentSection + } + + /* + This is an example of a section that is only in the review document + or only in the generated PDF, and is not displayed in `ORKVisualConsentStep`. + */ + let consentSection = ORKConsentSection(type: .OnlyInDocument) + consentSection.summary = NSLocalizedString(".OnlyInDocument Scene Summary", comment: "") + consentSection.title = NSLocalizedString(".OnlyInDocument Scene", comment: "") + consentSection.content = loremIpsumLongText + + consentSections += [consentSection] + + // Set the sections on the document after they've been created. + consentDocument.sections = consentSections + + return consentDocument + } + + // MARK: `ORKTask` Reused Text Convenience + + private var exampleDescription: String { + return NSLocalizedString("Your description goes here.", comment: "") + } + + private var exampleSpeechInstruction: String { + return NSLocalizedString("Your more specific voice instruction goes here. For example, say 'Aaaah'.", comment: "") + } + + private var exampleQuestionText: String { + return NSLocalizedString("Your question goes here.", comment: "") + } + + private var exampleHighValueText: String { + return NSLocalizedString("High Value", comment: "") + } + + private var exampleLowValueText: String { + return NSLocalizedString("Low Value", comment: "") + } + + private var exampleDetailText: String { + return NSLocalizedString("Additional text can go here.", comment: "") + } + + private var loremIpsumText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + } + + private var loremIpsumShortText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + } + + private var loremIpsumMediumText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?" + } + + private var loremIpsumLongText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?" + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift new file mode 100755 index 0000000..dcff84a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListRow.swift @@ -0,0 +1,2023 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015-2016, Ricardo Sánchez-Sáez. + Copyright (c) 2017, Macro Yau. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit +import AudioToolbox + +/** + Wraps a SystemSoundID. + + A class is used in order to provide appropriate cleanup when the sound is + no longer needed. +*/ +class SystemSound { + var soundID: SystemSoundID = 0 + + init?(soundURL: URL) { + if AudioServicesCreateSystemSoundID(soundURL as CFURL, &soundID) != noErr { + return nil + } + } + + deinit { + AudioServicesDisposeSystemSoundID(soundID) + } +} + +/** + An enum that corresponds to a row displayed in a `TaskListViewController`. + + Each of the tasks is composed of one or more steps giving examples of the + types of functionality supported by the ResearchKit framework. +*/ +enum TaskListRow: Int, CustomStringConvertible { + case form = 0 + case groupedForm + case survey + case booleanQuestion + case customBooleanQuestion + case dateQuestion + case dateTimeQuestion + case imageChoiceQuestion + case locationQuestion + case numericQuestion + case scaleQuestion + case textQuestion + case textChoiceQuestion + case timeIntervalQuestion + case timeOfDayQuestion + case valuePickerChoiceQuestion + case validatedTextQuestion + case imageCapture + case videoCapture + case wait + case PDFViewer + case eligibilityTask + case consent + case accountCreation + case login + case passcode + case audio + case amslerGrid + case fitness + case holePegTest + case psat + case reactionTime + case shortWalk + case spatialSpanMemory + case speechRecognition + case speechInNoise + case stroop + case swiftStroop + case timedWalkWithTurnAround + case toneAudiometry + case dBHLToneAudiometry + case splMeter + case towerOfHanoi + case tremorTest + case twoFingerTappingInterval + case walkBackAndForth + case heightQuestion + case weightQuestion + case kneeRangeOfMotion + case shoulderRangeOfMotion + case trailMaking + case visualAcuityLandoltC + case contrastSensitivityPeakLandoltC + case videoInstruction + case webView + + class TaskListRowSection { + var title: String + var rows: [TaskListRow] + + init(title: String, rows: [TaskListRow]) { + self.title = title + self.rows = rows + } + } + + /// Returns an array of all the task list row enum cases. + static var sections: [ TaskListRowSection ] { + + return [ + TaskListRowSection(title: "Surveys", rows: + [ + .form, + .groupedForm, + .survey + ]), + TaskListRowSection(title: "Survey Questions", rows: + [ + .booleanQuestion, + .customBooleanQuestion, + .dateQuestion, + .dateTimeQuestion, + .heightQuestion, + .weightQuestion, + .imageChoiceQuestion, + .locationQuestion, + .numericQuestion, + .scaleQuestion, + .textQuestion, + .textChoiceQuestion, + .timeIntervalQuestion, + .timeOfDayQuestion, + .valuePickerChoiceQuestion, + .validatedTextQuestion, + .imageCapture, + .videoCapture, + .wait, + .PDFViewer + ]), + TaskListRowSection(title: "Onboarding", rows: + [ + .eligibilityTask, + .consent, + .accountCreation, + .login, + .passcode + ]), + TaskListRowSection(title: "Active Tasks", rows: + [ + .audio, + .amslerGrid, + .fitness, + .holePegTest, + .psat, + .reactionTime, + .shortWalk, + .spatialSpanMemory, + .speechRecognition, + .speechInNoise, + .stroop, + .swiftStroop, + .timedWalkWithTurnAround, + .toneAudiometry, + .dBHLToneAudiometry, + .splMeter, + .towerOfHanoi, + .tremorTest, + .twoFingerTappingInterval, + .walkBackAndForth, + .kneeRangeOfMotion, + .shoulderRangeOfMotion, + .trailMaking, + .visualAcuityLandoltC, + .contrastSensitivityPeakLandoltC + ]), + TaskListRowSection(title: "Miscellaneous", rows: + [ + .videoInstruction, + .webView + ]) + ]} + + // MARK: CustomStringConvertible + + var description: String { + switch self { + case .form: + return NSLocalizedString("Form Survey Example", comment: "") + + case .groupedForm: + return NSLocalizedString("Grouped Form Survey Example", comment: "") + + case .survey: + return NSLocalizedString("Simple Survey Example", comment: "") + + case .booleanQuestion: + return NSLocalizedString("Boolean Question", comment: "") + + case .customBooleanQuestion: + return NSLocalizedString("Custom Boolean Question", comment: "") + + case .dateQuestion: + return NSLocalizedString("Date Question", comment: "") + + case .dateTimeQuestion: + return NSLocalizedString("Date and Time Question", comment: "") + + case .heightQuestion: + return NSLocalizedString("Height Question", comment: "") + + case .weightQuestion: + return NSLocalizedString("Weight Question", comment: "") + + case .imageChoiceQuestion: + return NSLocalizedString("Image Choice Question", comment: "") + + case .locationQuestion: + return NSLocalizedString("Location Question", comment: "") + + case .numericQuestion: + return NSLocalizedString("Numeric Question", comment: "") + + case .scaleQuestion: + return NSLocalizedString("Scale Question", comment: "") + + case .textQuestion: + return NSLocalizedString("Text Question", comment: "") + + case .textChoiceQuestion: + return NSLocalizedString("Text Choice Question", comment: "") + + case .timeIntervalQuestion: + return NSLocalizedString("Time Interval Question", comment: "") + + case .timeOfDayQuestion: + return NSLocalizedString("Time of Day Question", comment: "") + + case .valuePickerChoiceQuestion: + return NSLocalizedString("Value Picker Choice Question", comment: "") + + case .validatedTextQuestion: + return NSLocalizedString("Validated Text Question", comment: "") + + case .imageCapture: + return NSLocalizedString("Image Capture Step", comment: "") + + case .videoCapture: + return NSLocalizedString("Video Capture Step", comment: "") + + case .wait: + return NSLocalizedString("Wait Step", comment: "") + + case .PDFViewer: + return NSLocalizedString("PDF Viewer Step", comment: "") + + case .eligibilityTask: + return NSLocalizedString("Eligibility Task Example", comment: "") + + case .consent: + return NSLocalizedString("Consent-Obtaining Example", comment: "") + + case .accountCreation: + return NSLocalizedString("Account Creation", comment: "") + + case .login: + return NSLocalizedString("Login", comment: "") + + case .passcode: + return NSLocalizedString("Passcode Creation", comment: "") + + case .audio: + return NSLocalizedString("Audio", comment: "") + + case .amslerGrid: + return NSLocalizedString("Amsler Grid", comment: "") + + case .fitness: + return NSLocalizedString("Fitness Check", comment: "") + + case .holePegTest: + return NSLocalizedString("Hole Peg Test", comment: "") + + case .psat: + return NSLocalizedString("PSAT", comment: "") + + case .reactionTime: + return NSLocalizedString("Reaction Time", comment: "") + + case .shortWalk: + return NSLocalizedString("Short Walk", comment: "") + + case .spatialSpanMemory: + return NSLocalizedString("Spatial Span Memory", comment: "") + + case .speechRecognition: + return NSLocalizedString("Speech Recognition", comment: "") + + case .speechInNoise: + return NSLocalizedString("Speech in Noise", comment: "") + + case .stroop: + return NSLocalizedString("Stroop", comment: "") + + case .swiftStroop: + return NSLocalizedString("Swift Stroop", comment: "") + + case .timedWalkWithTurnAround: + return NSLocalizedString("Timed Walk with Turn Around", comment: "") + + case .toneAudiometry: + return NSLocalizedString("Tone Audiometry", comment: "") + + case .dBHLToneAudiometry: + return NSLocalizedString("dBHL Tone Audiometry", comment: "") + + case .splMeter: + return NSLocalizedString("Environment SPL Meter", comment: "") + + case .towerOfHanoi: + return NSLocalizedString("Tower of Hanoi", comment: "") + + case .twoFingerTappingInterval: + return NSLocalizedString("Two Finger Tapping Interval", comment: "") + + case .walkBackAndForth: + return NSLocalizedString("Walk Back and Forth", comment: "") + + case .tremorTest: + return NSLocalizedString("Tremor Test", comment: "") + + case .videoInstruction: + return NSLocalizedString("Video Instruction Task", comment: "") + + case .kneeRangeOfMotion: + return NSLocalizedString("Knee Range of Motion", comment: "") + + case .shoulderRangeOfMotion: + return NSLocalizedString("Shoulder Range of Motion", comment: "") + + case .trailMaking: + return NSLocalizedString("Trail Making Test", comment: "") + + case .visualAcuityLandoltC: + return NSLocalizedString("Visual Acuity Landolt C", comment: "") + + case .contrastSensitivityPeakLandoltC: + return NSLocalizedString("Contrast Sensitivity Peak", comment: "") + + case .webView: + return NSLocalizedString("Web View", comment: "") + } + } + + // MARK: Types + + /** + Every step and task in the ResearchKit framework has to have an identifier. + Within a task, the step identifiers should be unique. + + Here we use an enum to ensure that the identifiers are kept unique. Since + the enum has a raw underlying type of a `String`, the compiler can determine + the uniqueness of the case values at compile time. + + In a real application, the identifiers for your tasks and steps might + come from a database, or in a smaller application, might have some + human-readable meaning. + */ + enum Identifier { + // Task with a form, where multiple items appear on one page. + case formTask + case groupedFormTask + case formStep + case groupedFormStep + case formItem01 + case formItem02 + case formItem03 + case formItem04 + + // Survey task specific identifiers. + case surveyTask + case introStep + case questionStep + case birthdayQuestion + case summaryStep + + // Task with a Boolean question. + case booleanQuestionTask + case booleanQuestionStep + + // Task with an example of date entry. + case dateQuestionTask + case dateQuestionStep + + // Task with an example of date and time entry. + case dateTimeQuestionTask + case dateTimeQuestionStep + + // Task with an example of height entry. + case heightQuestionTask + case heightQuestionStep1 + case heightQuestionStep2 + case heightQuestionStep3 + case heightQuestionStep4 + + // Task with an example of weight entry. + case weightQuestionTask + case weightQuestionStep1 + case weightQuestionStep2 + case weightQuestionStep3 + case weightQuestionStep4 + case weightQuestionStep5 + case weightQuestionStep6 + case weightQuestionStep7 + + // Task with an image choice question. + case imageChoiceQuestionTask + case imageChoiceQuestionStep1 + case imageChoiceQuestionStep2 + + // Task with a location entry. + case locationQuestionTask + case locationQuestionStep + + // Task with examples of numeric questions. + case numericQuestionTask + case numericQuestionStep + case numericNoUnitQuestionStep + + // Task with examples of questions with sliding scales. + case scaleQuestionTask + case discreteScaleQuestionStep + case continuousScaleQuestionStep + case discreteVerticalScaleQuestionStep + case continuousVerticalScaleQuestionStep + case textScaleQuestionStep + case textVerticalScaleQuestionStep + + // Task with an example of free text entry. + case textQuestionTask + case textQuestionStep + + // Task with an example of a multiple choice question. + case textChoiceQuestionTask + case textChoiceQuestionStep + + // Task with an example of time of day entry. + case timeOfDayQuestionTask + case timeOfDayQuestionStep + + // Task with an example of time interval entry. + case timeIntervalQuestionTask + case timeIntervalQuestionStep + + // Task with a value picker. + case valuePickerChoiceQuestionTask + case valuePickerChoiceQuestionStep + + // Task with an example of validated text entry. + case validatedTextQuestionTask + case validatedTextQuestionStepEmail + case validatedTextQuestionStepDomain + + // Image capture task specific identifiers. + case imageCaptureTask + case imageCaptureStep + + // Video capture task specific identifiers. + case videoCaptureTask + case videoCaptureStep + + // Task with an example of waiting. + case waitTask + case waitStepDeterminate + case waitStepIndeterminate + + case pdfViewerStep + case pdfViewerTask + + // Eligibility task specific indentifiers. + case eligibilityTask + case eligibilityIntroStep + case eligibilityFormStep + case eligibilityFormItem01 + case eligibilityFormItem02 + case eligibilityFormItem03 + case eligibilityIneligibleStep + case eligibilityEligibleStep + + // Consent task specific identifiers. + case consentTask + case visualConsentStep + case consentSharingStep + case consentReviewStep + case consentDocumentParticipantSignature + case consentDocumentInvestigatorSignature + + // Account creation task specific identifiers. + case accountCreationTask + case registrationStep + case waitStep + case verificationStep + + // Login task specific identifiers. + case loginTask + case loginStep + case loginWaitStep + + // Passcode task specific identifiers. + case passcodeTask + case passcodeStep + + // Active tasks. + case audioTask + case amslerGridTask + case fitnessTask + case holePegTestTask + case psatTask + case reactionTime + case shortWalkTask + case spatialSpanMemoryTask + case speechRecognitionTask + case speechInNoiseTask + case stroopTask + case swiftStroopTask + case timedWalkWithTurnAroundTask + case toneAudiometryTask + case dBHLToneAudiometryTask + case splMeterTask + case splMeterStep + case towerOfHanoi + case tremorTestTask + case twoFingerTappingIntervalTask + case walkBackAndForthTask + case kneeRangeOfMotion + case shoulderRangeOfMotion + case trailMaking + case visualAcuityLandoltC + case contrastSensitivityPeakLandoltC + + // Video instruction tasks. + case videoInstructionTask + case videoInstructionStep + + // Web view tasks. + case webViewTask + case webViewStep + } + + // MARK: Properties + + /// Returns a new `ORKTask` that the `TaskListRow` enumeration represents. + var representedTask: ORKTask { + switch self { + case .form: + return formTask + + case .groupedForm: + return groupedFormTask + + case .survey: + return surveyTask + + case .booleanQuestion: + return booleanQuestionTask + + case .customBooleanQuestion: + return customBooleanQuestionTask + + case .dateQuestion: + return dateQuestionTask + + case .dateTimeQuestion: + return dateTimeQuestionTask + + case .heightQuestion: + return heightQuestionTask + + case .weightQuestion: + return weightQuestionTask + + case .imageChoiceQuestion: + return imageChoiceQuestionTask + + case .locationQuestion: + return locationQuestionTask + + case .numericQuestion: + return numericQuestionTask + + case .scaleQuestion: + return scaleQuestionTask + + case .textQuestion: + return textQuestionTask + + case .textChoiceQuestion: + return textChoiceQuestionTask + + case .timeIntervalQuestion: + return timeIntervalQuestionTask + + case .timeOfDayQuestion: + return timeOfDayQuestionTask + + case .valuePickerChoiceQuestion: + return valuePickerChoiceQuestionTask + + case .validatedTextQuestion: + return validatedTextQuestionTask + + case .imageCapture: + return imageCaptureTask + + case .videoCapture: + return videoCaptureTask + case .wait: + return waitTask + + case .PDFViewer: + return PDFViewerTask + + case .eligibilityTask: + return eligibilityTask + + case .consent: + return consentTask + + case .accountCreation: + return accountCreationTask + + case .login: + return loginTask + + case .passcode: + return passcodeTask + + case .audio: + return audioTask + + case .amslerGrid: + return amslerGridTask + + case .fitness: + return fitnessTask + + case .holePegTest: + return holePegTestTask + + case .psat: + return PSATTask + + case .reactionTime: + return reactionTimeTask + + case .shortWalk: + return shortWalkTask + + case .spatialSpanMemory: + return spatialSpanMemoryTask + + case .speechRecognition: + return speechRecognitionTask + + case .speechInNoise: + return speechInNoiseTask + + case .stroop: + return stroopTask + + case .swiftStroop: + return swiftStroopTask + + case .timedWalkWithTurnAround: + return timedWalkWithTurnAroundTask + + case .toneAudiometry: + return toneAudiometryTask + + case .dBHLToneAudiometry: + return dBHLToneAudiometryTask + + case .splMeter: + return splMeterTask + + case .towerOfHanoi: + return towerOfHanoiTask + + case .twoFingerTappingInterval: + return twoFingerTappingIntervalTask + + case .walkBackAndForth: + return walkBackAndForthTask + + case .tremorTest: + return tremorTestTask + + case .kneeRangeOfMotion: + return kneeRangeOfMotion + + case .shoulderRangeOfMotion: + return shoulderRangeOfMotion + + case .trailMaking: + return trailMaking + + case .visualAcuityLandoltC: + return visualAcuityLandoltC + + case .contrastSensitivityPeakLandoltC: + return contrastSensitivityPeakLandoltC + + case .videoInstruction: + return videoInstruction + + case .webView: + return webView + } + } + + // MARK: Task Creation Convenience + + /** + This task demonstrates a form step, in which multiple items are presented + in a single scrollable form. This might be used for entering multi-value + data, like taking a blood pressure reading with separate systolic and + diastolic values. + */ + private var formTask: ORKTask { + let step = ORKFormStep(identifier: String(describing: Identifier.formStep), title: NSLocalizedString("Form Step", comment: ""), text: exampleDetailText) + + // A first field, for entering an integer. + let formItem01Text = NSLocalizedString("Field01", comment: "") + let formItem01 = ORKFormItem(identifier: String(describing: Identifier.formItem01), text: formItem01Text, answerFormat: ORKAnswerFormat.integerAnswerFormat(withUnit: nil)) + formItem01.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + // A second field, for entering a time interval. + let formItem02Text = NSLocalizedString("Field02", comment: "") + let formItem02 = ORKFormItem(identifier: String(describing: Identifier.formItem02), text: formItem02Text, answerFormat: ORKTimeIntervalAnswerFormat()) + formItem02.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + let formItem03Text = NSLocalizedString(exampleQuestionText, comment: "") + let scaleAnswerFormat = ORKScaleAnswerFormat(maximumValue: 10, minimumValue: 0, defaultValue: 0, step: 1)//ORKScaleAnswerFormat(maximumValue: 10, minimumValue: 0, defaultValue: 0, step: 1) + scaleAnswerFormat.shouldHideRanges = true + let formItem03 = ORKFormItem(identifier: String(describing: Identifier.formItem03), text: formItem03Text, answerFormat: scaleAnswerFormat) + + let textChoices: [ORKTextChoice] = [ + ORKTextChoice(text: "choice 1", detailText: "detail 1", value: 1 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false), + ORKTextChoice(text: "choice 2", detailText: "detail 2", value: 2 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false), + ORKTextChoice(text: "choice 3", detailText: "detail 3", value: 3 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false), + ORKTextChoice(text: "choice 4", detailText: "detail 4", value: 4 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false), + ORKTextChoice(text: "choice 5", detailText: "detail 5", value: 5 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false), + ORKTextChoice(text: "choice 6", detailText: "detail 6", value: 6 as NSCoding & NSCopying & NSObjectProtocol, exclusive: false) + ] + + let textScaleAnswerFormat = ORKTextScaleAnswerFormat(textChoices: textChoices, defaultIndex: 10) + textScaleAnswerFormat.shouldHideLabels = true + textScaleAnswerFormat.shouldShowDontKnowButton = true + let formItem04 = ORKFormItem(identifier: String(describing: Identifier.formItem04), text: exampleQuestionText, answerFormat: textScaleAnswerFormat) + + let appleChoices: [ORKTextChoice] = [ORKTextChoice(text: "Granny Smith", value: 1 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Honeycrisp", value: 2 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Fuji", value: 3 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "McIntosh", value: 10 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Kanzi", value: 5 as NSCoding & NSCopying & NSObjectProtocol)] + + let appleAnswerFormat = ORKTextChoiceAnswerFormat(style: .singleChoice, textChoices: appleChoices) + + let appleFormItem = ORKFormItem(identifier: "appleFormItemIdentifier", text: "Which is your favorite apple?", answerFormat: appleAnswerFormat) + + + step.formItems = [ + appleFormItem, + formItem03, + formItem04, + formItem01, + formItem02 + ] + let completionStep = ORKCompletionStep(identifier: "CompletionStep") + completionStep.title = NSLocalizedString("All Done!", comment: "") + completionStep.detailText = NSLocalizedString("You have completed the questionnaire.", comment: "") + return ORKOrderedTask(identifier: String(describing: Identifier.formTask), steps: [step, completionStep]) + } + + private var groupedFormTask: ORKTask { + let step = ORKFormStep(identifier: String(describing: Identifier.groupedFormStep), title: NSLocalizedString("Form Step", comment: ""), text: exampleDetailText) + + //Start of first section + let learnMoreInstructionStep01 = ORKLearnMoreInstructionStep(identifier: "LearnMoreInstructionStep01") + learnMoreInstructionStep01.title = NSLocalizedString("Learn more title", comment: "") + learnMoreInstructionStep01.text = NSLocalizedString("Learn more text", comment: "") + let learnMoreItem01 = ORKLearnMoreItem(text: nil, learnMoreInstructionStep: learnMoreInstructionStep01) + let section01 = ORKFormItem(sectionTitle: NSLocalizedString("Section title", comment: ""), detailText: NSLocalizedString("Section detail text", comment: ""), learnMoreItem: learnMoreItem01, showsProgress: true) + + // A first field, for entering an integer. + let formItem01Text = NSLocalizedString("Field01", comment: "") + let formItem01 = ORKFormItem(identifier: String(describing: Identifier.formItem01), text: formItem01Text, answerFormat: ORKAnswerFormat.integerAnswerFormat(withUnit: nil)) + formItem01.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + // A second field, for entering a time interval. + let formItem02Text = NSLocalizedString("Field02", comment: "") + let formItem02 = ORKFormItem(identifier: String(describing: Identifier.formItem02), text: formItem02Text, answerFormat: ORKTimeIntervalAnswerFormat()) + formItem02.placeholder = NSLocalizedString("Your placeholder here", comment: "") + + + let sesAnswerFormat = ORKSESAnswerFormat(topRungText: "Best Off", bottomRungText: "Worst Off") + let sesFormItem = ORKFormItem(identifier: "sesIdentifier", text: "Select where you are on the socioeconomic ladder.", answerFormat: sesAnswerFormat) + + + //Start of section for scale question + let formItem03Text = NSLocalizedString(exampleQuestionText, comment: "") + let scaleAnswerFormat = ORKContinuousScaleAnswerFormat(maximumValue: 10, minimumValue: 0, defaultValue: 0.0, maximumFractionDigits: 1)//ORKScaleAnswerFormat(maximumValue: 10, minimumValue: 0, defaultValue: 0, step: 1) + let formItem03 = ORKFormItem(identifier: String(describing: Identifier.formItem03), text: formItem03Text, detailText: nil, learnMoreItem: nil, showsProgress: true, answerFormat: scaleAnswerFormat, tagText: nil, optional: true) + + step.formItems = [ + section01, + formItem01, + formItem02, + formItem03, + sesFormItem + ] + + // Add a question step. + let question1StepAnswerFormat = ORKBooleanAnswerFormat() + + let question1 = NSLocalizedString("Would you like to subscribe to our newsletter?", comment: "") + + let learnMoreInstructionStep = ORKLearnMoreInstructionStep(identifier: "LearnMoreInstructionStep01") + learnMoreInstructionStep.title = NSLocalizedString("Learn more title", comment: "") + learnMoreInstructionStep.text = NSLocalizedString("Learn more text", comment: "") + let learnMoreItem = ORKLearnMoreItem(text: nil, learnMoreInstructionStep: learnMoreInstructionStep) + + let question1Step = ORKQuestionStep(identifier: String(describing: Identifier.questionStep), title: "Questionnaire", question: question1, answer: question1StepAnswerFormat, learnMoreItem: learnMoreItem) + question1Step.text = exampleDetailText + + //Add a question step with different layout format. + let question2StepAnswerFormat = ORKAnswerFormat.dateAnswerFormat(withDefaultDate: nil, minimumDate: nil, maximumDate: Date(), calendar: nil) + + let question2 = NSLocalizedString("When is your birthday?", comment: "") + let question2Step = ORKQuestionStep(identifier: String(describing: Identifier.birthdayQuestion), title: "Questionnaire", question: question2, answer: question2StepAnswerFormat) + question2Step.text = exampleDetailText + + + let appleChoices: [ORKTextChoice] = [ORKTextChoice(text: "Granny Smith", value: 1 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Honeycrisp", value: 2 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Fuji", value: 3 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "McIntosh", value: 10 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Kanzi", value: 5 as NSCoding & NSCopying & NSObjectProtocol)] + + let appleAnswerFormat = ORKTextChoiceAnswerFormat(style: .singleChoice, textChoices: appleChoices) + + let appleFormItem = ORKFormItem(identifier: "appleFormItemIdentifier", text: "Which is your favorite apple?", answerFormat: appleAnswerFormat) + + let appleFormStep = ORKFormStep(identifier: "appleFormStepIdentifier", title: "Fruit!", text: "Select the fruit you like.") + + appleFormStep.formItems = [appleFormItem] + + return ORKOrderedTask(identifier: String(describing: Identifier.groupedFormTask), steps: [step, question1Step, question2Step, appleFormStep]) + } + + /** + A task demonstrating how the ResearchKit framework can be used to present a simple + survey with an introduction, a question, and a conclusion. + */ + private var surveyTask: ORKTask { + // Create the intro step. + let instructionStep = ORKInstructionStep(identifier: String(describing: Identifier.introStep)) + instructionStep.title = NSLocalizedString("Simple Survey", comment: "") + instructionStep.text = exampleDescription + instructionStep.detailText = NSLocalizedString("Please use this space to provide instructions for participants. Please make sure to provide enough information so that users can progress through the survey and complete with ease.", comment: "") + + // Add a question step. + let question1StepAnswerFormat = ORKBooleanAnswerFormat() + + let question1 = NSLocalizedString("Would you like to subscribe to our newsletter?", comment: "") + + let learnMoreInstructionStep = ORKLearnMoreInstructionStep(identifier: "LearnMoreInstructionStep01") + learnMoreInstructionStep.title = NSLocalizedString("Learn more title", comment: "") + learnMoreInstructionStep.text = NSLocalizedString("Learn more text", comment: "") + let learnMoreItem = ORKLearnMoreItem(text: nil, learnMoreInstructionStep: learnMoreInstructionStep) + + let question1Step = ORKQuestionStep(identifier: String(describing: Identifier.questionStep), title: "Questionnaire", question: question1, answer: question1StepAnswerFormat, learnMoreItem: learnMoreItem) + question1Step.text = exampleDetailText + + //Add a question step with different layout format. + let question2StepAnswerFormat = ORKAnswerFormat.dateAnswerFormat(withDefaultDate: nil, minimumDate: nil, maximumDate: Date(), calendar: nil) + + let question2 = NSLocalizedString("When is your birthday?", comment: "") + let question2Step = ORKQuestionStep(identifier: String(describing: Identifier.birthdayQuestion), title: "Questionnaire", question: question2, answer: question2StepAnswerFormat) + question2Step.text = exampleDetailText + + // Add a summary step. + let summaryStep = ORKInstructionStep(identifier: String(describing: Identifier.summaryStep)) + summaryStep.title = NSLocalizedString("Thanks", comment: "") + summaryStep.text = NSLocalizedString("Thank you for participating in this sample survey.", comment: "") + + return ORKOrderedTask(identifier: String(describing: Identifier.surveyTask), steps: [ + instructionStep, + question1Step, + question2Step, + summaryStep + ]) + } + + /// This task presents just a single "Yes" / "No" question. + private var booleanQuestionTask: ORKTask { + let answerFormat = ORKBooleanAnswerFormat() + + // We attach an answer format to a question step to specify what controls the user sees. + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.booleanQuestionStep), title: NSLocalizedString("Boolean", comment: ""), question: exampleQuestionText, answer: answerFormat) + + // The detail text is shown in a small font below the title. + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.booleanQuestionTask), steps: [questionStep]) + } + + /// This task presents a customized "Yes" / "No" question. + private var customBooleanQuestionTask: ORKTask { + let answerFormat = ORKBooleanAnswerFormat(yesString: "Agree", noString: "Disagree") + + // We attach an answer format to a question step to specify what controls the user sees. + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.booleanQuestionStep), title: NSLocalizedString("Custom Boolean", comment: ""), question: exampleQuestionText, answer: answerFormat) + + // The detail text is shown in a small font below the title. + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.booleanQuestionTask), steps: [questionStep]) + } + + /// This task demonstrates a question which asks for a date. + private var dateQuestionTask: ORKTask { + /* + The date answer format can also support minimum and maximum limits, + a specific default value, and overriding the calendar to use. + */ + let answerFormat = ORKAnswerFormat.dateAnswerFormat() + + let step = ORKQuestionStep(identifier: String(describing: Identifier.dateQuestionStep), title: NSLocalizedString("Date", comment: ""), question: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.dateQuestionTask), steps: [step]) + } + + /// This task demonstrates a question asking for a date and time of an event. + private var dateTimeQuestionTask: ORKTask { + /* + This uses the default calendar. Use a more detailed constructor to + set minimum / maximum limits. + */ + let answerFormat = ORKAnswerFormat.dateTime() + + let step = ORKQuestionStep(identifier: String(describing: Identifier.dateTimeQuestionStep), title: NSLocalizedString("Date and Time", comment: ""), question: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.dateTimeQuestionTask), steps: [step]) + } + + /// This task demonstrates a question asking for the user height. + private var heightQuestionTask: ORKTask { + let answerFormat1 = ORKAnswerFormat.heightAnswerFormat() + + let step1 = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep1), title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat1) + + step1.text = "Local system" + + let answerFormat2 = ORKAnswerFormat.heightAnswerFormat(with: ORKMeasurementSystem.metric) + + let step2 = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep2), title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat2) + + step2.text = "Metric system" + + let answerFormat3 = ORKAnswerFormat.heightAnswerFormat(with: ORKMeasurementSystem.USC) + + let step3 = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep3), title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat3) + + step3.text = "USC system" + + let answerFormat4 = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!, unit: HKUnit.meterUnit(with: .centi), style: .decimal) + + let step4 = ORKQuestionStep(identifier: String(describing: Identifier.heightQuestionStep4), title: NSLocalizedString("Height", comment: ""), question: exampleQuestionText, answer: answerFormat4) + + step4.text = "HealthKit, height" + + return ORKOrderedTask(identifier: String(describing: Identifier.heightQuestionTask), steps: [step1, step2, step3, step4]) + } + + /// This task demonstrates a question asking for the user weight. + private var weightQuestionTask: ORKTask { + let answerFormat1 = ORKAnswerFormat.weightAnswerFormat() + + let step1 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep1), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat1) + + step1.text = "Local system, default precision" + + let answerFormat2 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric) + + let step2 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep2), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat2) + + step2.text = "Metric system, default precision" + + let answerFormat3 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.low, minimumValue: ORKDoubleDefaultValue, maximumValue: ORKDoubleDefaultValue, defaultValue: ORKDoubleDefaultValue) + + let step3 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep3), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat3) + + step3.text = "Metric system, low precision" + + let answerFormat4 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.metric, numericPrecision: ORKNumericPrecision.high, minimumValue: 20.0, maximumValue: 100.0, defaultValue: 45.50) + + let step4 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep4), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat4) + + step4.text = "Metric system, high precision" + + let answerFormat5 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC) + + let step5 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep5), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat5) + + step5.text = "USC system, default precision" + + let answerFormat6 = ORKAnswerFormat.weightAnswerFormat(with: ORKMeasurementSystem.USC, numericPrecision: ORKNumericPrecision.high, minimumValue: 50.0, maximumValue: 150.0, defaultValue: 100.0) + + let step6 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep6), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat6) + + step6.text = "USC system, high precision" + + let answerFormat7 = ORKHealthKitQuantityTypeAnswerFormat(quantityType: HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!, unit: HKUnit.gramUnit(with: .kilo), style: .decimal) + + let step7 = ORKQuestionStep(identifier: String(describing: Identifier.weightQuestionStep7), title: NSLocalizedString("Weight", comment: ""), question: exampleQuestionText, answer: answerFormat7) + + step7.text = "HealthKit, body mass" + + return ORKOrderedTask(identifier: String(describing: Identifier.weightQuestionTask), steps: [step1, step2, step3, step4, step5, step6, step7]) + } + + /** + This task demonstrates a survey question involving picking from a series of + image choices. A more realistic applciation of this type of question might be to + use a range of icons for faces ranging from happy to sad. + */ + private var imageChoiceQuestionTask: ORKTask { + let roundShapeImage = UIImage(named: "round_shape")! + let roundShapeText = NSLocalizedString("Round Shape", comment: "") + + let squareShapeImage = UIImage(named: "square_shape")! + let squareShapeText = NSLocalizedString("Square Shape", comment: "") + + let imageChoces = [ + ORKImageChoice(normalImage: roundShapeImage, selectedImage: nil, text: roundShapeText, value: roundShapeText as NSCoding & NSCopying & NSObjectProtocol), + ORKImageChoice(normalImage: squareShapeImage, selectedImage: nil, text: squareShapeText, value: squareShapeText as NSCoding & NSCopying & NSObjectProtocol) + ] + + let answerFormat1 = ORKAnswerFormat.choiceAnswerFormat(with: imageChoces) + + let questionStep1 = ORKQuestionStep(identifier: String(describing: Identifier.imageChoiceQuestionStep1), title: NSLocalizedString("Image Choice", comment: ""), question: exampleQuestionText, answer: answerFormat1) + + questionStep1.text = exampleDetailText + + let answerFormat2 = ORKAnswerFormat.choiceAnswerFormat(with: imageChoces, style: .singleChoice, vertical: true) + + let questionStep2 = ORKQuestionStep(identifier: String(describing: Identifier.imageChoiceQuestionStep2), title: NSLocalizedString("Image Choice", comment: ""), question: exampleQuestionText, answer: answerFormat2) + + questionStep2.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.imageChoiceQuestionTask), steps: [questionStep1, questionStep2]) + } + + /// This task presents just a single location question. + private var locationQuestionTask: ORKTask { + let answerFormat = ORKLocationAnswerFormat() + + // We attach an answer format to a question step to specify what controls the user sees. + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.locationQuestionStep), title: NSLocalizedString("Location", comment: ""), question: exampleQuestionText, answer: answerFormat) + // The detail text is shown in a small font below the title. + questionStep.text = exampleDetailText + questionStep.placeholder = NSLocalizedString("Address", comment: "") + + return ORKOrderedTask(identifier: String(describing: Identifier.locationQuestionTask), steps: [questionStep]) + } + + /** + This task demonstrates use of numeric questions with and without units. + Note that the unit is just a string, prompting the user to enter the value + in the expected unit. The unit string propagates into the result object. + */ + private var numericQuestionTask: ORKTask { + // This answer format will display a unit in-line with the numeric entry field. + let localizedQuestionStep1AnswerFormatUnit = NSLocalizedString("Your unit", comment: "") + let questionStep1AnswerFormat = ORKAnswerFormat.decimalAnswerFormat(withUnit: localizedQuestionStep1AnswerFormatUnit) + + let questionStep1 = ORKQuestionStep(identifier: String(describing: Identifier.numericQuestionStep), title: NSLocalizedString("Numeric", comment: ""), question: exampleQuestionText, answer: questionStep1AnswerFormat) + + questionStep1.text = exampleDetailText + questionStep1.placeholder = NSLocalizedString("Your placeholder.", comment: "") + + // This answer format is similar to the previous one, but this time without displaying a unit. + let questionStep2 = ORKQuestionStep(identifier: String(describing: Identifier.numericNoUnitQuestionStep), title: NSLocalizedString("Numeric", comment: ""), question: exampleQuestionText, answer: ORKAnswerFormat.decimalAnswerFormat(withUnit: nil)) + + questionStep2.text = exampleDetailText + questionStep2.placeholder = NSLocalizedString("Placeholder without unit.", comment: "") + + return ORKOrderedTask(identifier: String(describing: Identifier.numericQuestionTask), steps: [ + questionStep1, + questionStep2 + ]) + } + + /// This task presents two options for questions displaying a scale control. + private var scaleQuestionTask: ORKTask { + // The first step is a scale control with 10 discrete ticks. + let stepTitle = NSLocalizedString("Scale", comment: "") + + let step1AnswerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: NSIntegerMax, step: 1, vertical: false, maximumValueDescription: exampleHighValueText, minimumValueDescription: exampleLowValueText) + + let questionStep1 = ORKQuestionStep(identifier: String(describing: Identifier.discreteScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step1AnswerFormat) + + questionStep1.text = NSLocalizedString("Discrete Scale", comment: "") + + // The second step is a scale control that allows continuous movement with a percent formatter. + let step2AnswerFormat = ORKAnswerFormat.continuousScale(withMaximumValue: 1.0, minimumValue: 0.0, defaultValue: 99.0, maximumFractionDigits: 0, vertical: false, maximumValueDescription: nil, minimumValueDescription: nil) + step2AnswerFormat.numberStyle = .percent + + let questionStep2 = ORKQuestionStep(identifier: String(describing: Identifier.continuousScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step2AnswerFormat) + + questionStep2.text = NSLocalizedString("Continuous Scale", comment: "") + + // The third step is a vertical scale control with 10 discrete ticks. + let step3AnswerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: NSIntegerMax, step: 1, vertical: true, maximumValueDescription: nil, minimumValueDescription: nil) + + let questionStep3 = ORKQuestionStep(identifier: String(describing: Identifier.discreteVerticalScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step3AnswerFormat) + + questionStep3.text = NSLocalizedString("Discrete Vertical Scale", comment: "") + + // The fourth step is a vertical scale control that allows continuous movement. + let step4AnswerFormat = ORKAnswerFormat.continuousScale(withMaximumValue: 5.0, minimumValue: 1.0, defaultValue: 99.0, maximumFractionDigits: 2, vertical: true, maximumValueDescription: exampleHighValueText, minimumValueDescription: exampleLowValueText) + + let questionStep4 = ORKQuestionStep(identifier: String(describing: Identifier.continuousVerticalScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step4AnswerFormat) + + questionStep4.text = "Continuous Vertical Scale" + + // The fifth step is a scale control that allows text choices. + let textChoices: [ORKTextChoice] = [ORKTextChoice(text: "Poor", value: 1 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Fair", value: 2 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Good", value: 3 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Above Average", value: 10 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Excellent", value: 5 as NSCoding & NSCopying & NSObjectProtocol)] + + let step5AnswerFormat = ORKAnswerFormat.textScale(with: textChoices, defaultIndex: NSIntegerMax, vertical: false) + + let questionStep5 = ORKQuestionStep(identifier: String(describing: Identifier.textScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step5AnswerFormat) + + questionStep5.text = "Text Scale" + + // The sixth step is a vertical scale control that allows text choices. + let step6AnswerFormat = ORKAnswerFormat.textScale(with: textChoices, defaultIndex: NSIntegerMax, vertical: true) + + let questionStep6 = ORKQuestionStep(identifier: String(describing: Identifier.textVerticalScaleQuestionStep), title: stepTitle, question: exampleQuestionText, answer: step6AnswerFormat) + + questionStep6.text = "Text Vertical Scale" + + return ORKOrderedTask(identifier: String(describing: Identifier.scaleQuestionTask), steps: [ + questionStep1, + questionStep2, + questionStep3, + questionStep4, + questionStep5, + questionStep6 + ]) + } + + /** + This task demonstrates asking for text entry. Both single and multi-line + text entry are supported, with appropriate parameters to the text answer + format. + */ + private var textQuestionTask: ORKTask { + let answerFormat = ORKAnswerFormat.textAnswerFormat() + answerFormat.multipleLines = true + answerFormat.maximumLength = 280; + + let step = ORKQuestionStep(identifier: String(describing: Identifier.textQuestionStep), title: NSLocalizedString("Text", comment: ""), question: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.textQuestionTask), steps: [step]) + } + + /** + This task demonstrates a survey question for picking from a list of text + choices. In this case, the text choices are presented in a table view + (compare with the `valuePickerQuestionTask`). + */ + private var textChoiceQuestionTask: ORKTask { + let textChoiceOneText = NSLocalizedString("Choice 1", comment: "") + let textChoiceTwoText = NSLocalizedString("Choice 2", comment: "") + let textChoiceThreeText = NSLocalizedString("Choice 3", comment: "") + let textChoiceFourText = NSLocalizedString("Other", comment: "") + + // The text to display can be separate from the value coded for each choice: + let textChoices = [ + ORKTextChoice(text: textChoiceOneText, value: "choice_1" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: textChoiceTwoText, value: "choice_2" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: textChoiceThreeText, value: "choice_3" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoiceOther.choice(withText: textChoiceFourText, detailText: nil, value: "choice_4" as NSCoding & NSCopying & NSObjectProtocol, exclusive: true, textViewPlaceholderText: "enter additional information") + ] + + let answerFormat = ORKAnswerFormat.choiceAnswerFormat(with: .singleChoice, textChoices: textChoices) + + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.textChoiceQuestionStep), title: NSLocalizedString("Text Choice", comment: ""), question: exampleQuestionText, answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.textChoiceQuestionTask), steps: [questionStep]) + } + + /** + This task demonstrates requesting a time interval. For example, this might + be a suitable answer format for a question like "How long is your morning + commute?" + */ + private var timeIntervalQuestionTask: ORKTask { + /* + The time interval answer format is constrained to entering a time + less than 24 hours and in steps of minutes. For times that don't fit + these restrictions, use another mode of data entry. + */ + let answerFormat = ORKAnswerFormat.timeIntervalAnswerFormat() + + let step = ORKQuestionStep(identifier: String(describing: Identifier.timeIntervalQuestionStep), title: NSLocalizedString("Time Interval", comment: ""), question: exampleQuestionText, answer: answerFormat) + + step.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.timeIntervalQuestionTask), steps: [step]) + } + + /// This task demonstrates a question asking for a time of day. + private var timeOfDayQuestionTask: ORKTask { + /* + Because we don't specify a default, the picker will default to the + time the step is presented. For questions like "What time do you have + breakfast?", it would make sense to set the default on the answer + format. + */ + let answerFormat = ORKAnswerFormat.timeOfDayAnswerFormat() + + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.timeOfDayQuestionStep), title: NSLocalizedString("Time", comment: ""), question: exampleQuestionText, answer: answerFormat) + + questionStep.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.timeOfDayQuestionTask), steps: [questionStep]) + } + + /** + This task demonstrates a survey question using a value picker wheel. + Compare with the `textChoiceQuestionTask` and `imageChoiceQuestionTask` + which can serve a similar purpose. + */ + private var valuePickerChoiceQuestionTask: ORKTask { + let textChoiceOneText = NSLocalizedString("Choice 1", comment: "") + let textChoiceTwoText = NSLocalizedString("Choice 2", comment: "") + let textChoiceThreeText = NSLocalizedString("Choice 3", comment: "") + + // The text to display can be separate from the value coded for each choice: + let textChoices = [ + ORKTextChoice(text: textChoiceOneText, value: "choice_1" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: textChoiceTwoText, value: "choice_2" as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: textChoiceThreeText, value: "choice_3" as NSCoding & NSCopying & NSObjectProtocol) + ] + + let answerFormat = ORKAnswerFormat.valuePickerAnswerFormat(with: textChoices) + + let questionStep = ORKQuestionStep(identifier: String(describing: Identifier.valuePickerChoiceQuestionStep), title: NSLocalizedString("Value Picker", comment: ""), question: exampleQuestionText, answer: answerFormat) + + questionStep.text = NSLocalizedString("Text Value picker", comment: "") + + return ORKOrderedTask(identifier: String(describing: Identifier.valuePickerChoiceQuestionTask), steps: [questionStep]) + } + + /** + This task demonstrates asking for text entry. Both single and multi-line + text entry are supported, with appropriate parameters to the text answer + format. + */ + private var validatedTextQuestionTask: ORKTask { + let answerFormatEmail = ORKAnswerFormat.emailAnswerFormat() + let stepEmail = ORKQuestionStep(identifier: String(describing: Identifier.validatedTextQuestionStepEmail), title: NSLocalizedString("Validated Text", comment: ""), question: NSLocalizedString("Email", comment: ""), answer: answerFormatEmail) + stepEmail.text = exampleDetailText + + let domainRegularExpressionPattern = "^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$" + let domainRegularExpression = try? NSRegularExpression(pattern: domainRegularExpressionPattern) + let answerFormatDomain = ORKAnswerFormat.textAnswerFormat(withValidationRegularExpression: domainRegularExpression!, invalidMessage: "Invalid URL: %@") + answerFormatDomain.multipleLines = false + answerFormatDomain.keyboardType = .URL + answerFormatDomain.autocapitalizationType = UITextAutocapitalizationType.none + answerFormatDomain.autocorrectionType = UITextAutocorrectionType.no + answerFormatDomain.spellCheckingType = UITextSpellCheckingType.no + answerFormatDomain.textContentType = UITextContentType.URL + let stepDomain = ORKQuestionStep(identifier: String(describing: Identifier.validatedTextQuestionStepDomain), title: NSLocalizedString("Validated Text", comment: ""), question: NSLocalizedString("URL", comment: ""), answer: answerFormatDomain) + stepDomain.text = exampleDetailText + + return ORKOrderedTask(identifier: String(describing: Identifier.validatedTextQuestionTask), steps: [stepEmail, stepDomain]) + } + + /// This task presents the image capture step in an ordered task. + private var imageCaptureTask: ORKTask { + // Create the intro step. + let instructionStep = ORKInstructionStep(identifier: String(describing: Identifier.introStep)) + + instructionStep.title = NSLocalizedString("Image Capture Survey", comment: "") + + instructionStep.text = exampleDescription + + let handSolidImage = UIImage(named: "hand_solid")! + instructionStep.image = handSolidImage.withRenderingMode(.alwaysTemplate) + + let imageCaptureStep = ORKImageCaptureStep(identifier: String(describing: Identifier.imageCaptureStep)) + imageCaptureStep.title = NSLocalizedString("Image Capture", comment: "") + imageCaptureStep.isOptional = false + imageCaptureStep.accessibilityInstructions = NSLocalizedString("Your instructions for capturing the image", comment: "") + imageCaptureStep.accessibilityHint = NSLocalizedString("Captures the image visible in the preview", comment: "") + + imageCaptureStep.templateImage = UIImage(named: "hand_outline_big")! + + imageCaptureStep.templateImageInsets = UIEdgeInsets(top: 0.05, left: 0.05, bottom: 0.05, right: 0.05) + + return ORKOrderedTask(identifier: String(describing: Identifier.imageCaptureTask), steps: [ + instructionStep, + imageCaptureStep + ]) + } + + /// This task presents the video capture step in an ordered task. + private var videoCaptureTask: ORKTask { + // Create the intro step. + let instructionStep = ORKInstructionStep(identifier: String(describing: Identifier.introStep)) + + instructionStep.title = NSLocalizedString("Video Capture Survey", comment: "") + + instructionStep.text = exampleDescription + + let handSolidImage = UIImage(named: "hand_solid")! + instructionStep.image = handSolidImage.withRenderingMode(.alwaysTemplate) + + let videoCaptureStep = ORKVideoCaptureStep(identifier: String(describing: Identifier.videoCaptureStep)) + videoCaptureStep.title = NSLocalizedString("Video Capture", comment: "") + videoCaptureStep.accessibilityInstructions = NSLocalizedString("Your instructions for capturing the video", comment: "") + videoCaptureStep.accessibilityHint = NSLocalizedString("Captures the video visible in the preview", comment: "") + videoCaptureStep.templateImage = UIImage(named: "hand_outline_big")! + videoCaptureStep.templateImageInsets = UIEdgeInsets(top: 0.05, left: 0.05, bottom: 0.05, right: 0.05) + videoCaptureStep.duration = 30.0; // 30 seconds + + return ORKOrderedTask(identifier: String(describing: Identifier.videoCaptureTask), steps: [ + instructionStep, + videoCaptureStep + ]) + } + + /// This task presents a wait task. + private var waitTask: ORKTask { + let waitStepIndeterminate = ORKWaitStep(identifier: String(describing: Identifier.waitStepIndeterminate)) + waitStepIndeterminate.title = NSLocalizedString("Wait Step", comment: "") + waitStepIndeterminate.text = exampleDescription + waitStepIndeterminate.indicatorType = ORKProgressIndicatorType.indeterminate + + let waitStepDeterminate = ORKWaitStep(identifier: String(describing: Identifier.waitStepDeterminate)) + waitStepDeterminate.title = NSLocalizedString("Wait Step", comment: "") + waitStepDeterminate.text = exampleDescription + waitStepDeterminate.indicatorType = ORKProgressIndicatorType.progressBar + + return ORKOrderedTask(identifier: String(describing: Identifier.waitTask), steps: [waitStepIndeterminate, waitStepDeterminate]) + } + + /// This task presents the PDF Viewer Step + private var PDFViewerTask: ORKTask { + + let PDFViewerStep = ORKPDFViewerStep(identifier: String(describing: Identifier.pdfViewerStep), pdfURL: Bundle.main.bundleURL.appendingPathComponent("ResearchKit.pdf")) + PDFViewerStep.title = NSLocalizedString("PDF Step", comment: "") + + return ORKOrderedTask(identifier: String(describing: Identifier.pdfViewerTask), steps: [PDFViewerStep]) + } + + /** + A task demonstrating how the ResearchKit framework can be used to determine + eligibility using a navigable ordered task. + */ + private var eligibilityTask: ORKTask { + // Intro step + let introStep = ORKInstructionStep(identifier: String(describing: Identifier.eligibilityIntroStep)) + introStep.title = NSLocalizedString("Eligibility Task", comment: "") + introStep.text = exampleDescription + introStep.detailText = NSLocalizedString("Please use this space to provide instructions for participants. Please make sure to provide enough information so that users can progress through the survey and complete with ease.", comment: "") + + // Form step + let formStep = ORKFormStep(identifier: String(describing: Identifier.eligibilityFormStep)) + formStep.title = NSLocalizedString("Eligibility", comment: "") + formStep.isOptional = false + + // Form items + let textChoices: [ORKTextChoice] = [ORKTextChoice(text: "Yes", value: "Yes" as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "No", value: "No" as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "N/A", value: "N/A" as NSCoding & NSCopying & NSObjectProtocol)] + let answerFormat = ORKTextChoiceAnswerFormat(style: ORKChoiceAnswerStyle.singleChoice, textChoices: textChoices) + + let formItem01 = ORKFormItem(identifier: String(describing: Identifier.eligibilityFormItem01), text: exampleQuestionText, answerFormat: answerFormat) + formItem01.isOptional = false + let formItem02 = ORKFormItem(identifier: String(describing: Identifier.eligibilityFormItem02), text: exampleQuestionText, answerFormat: answerFormat) + formItem02.isOptional = false + let formItem03 = ORKFormItem(identifier: String(describing: Identifier.eligibilityFormItem03), text: exampleQuestionText, answerFormat: answerFormat) + formItem03.isOptional = false + + formStep.formItems = [ + formItem01, + formItem02, + formItem03 + ] + + // Ineligible step + let ineligibleStep = ORKInstructionStep(identifier: String(describing: Identifier.eligibilityIneligibleStep)) + ineligibleStep.title = NSLocalizedString("Eligibility Result", comment: "") + ineligibleStep.detailText = NSLocalizedString("You are ineligible to join the study", comment: "") + + // Eligible step + let eligibleStep = ORKCompletionStep(identifier: String(describing: Identifier.eligibilityEligibleStep)) + eligibleStep.title = NSLocalizedString("Eligibility Result", comment: "") + eligibleStep.detailText = NSLocalizedString("You are eligible to join the study", comment: "") + + // Create the task + let eligibilityTask = ORKNavigableOrderedTask(identifier: String(describing: Identifier.eligibilityTask), steps: [ + introStep, + formStep, + ineligibleStep, + eligibleStep + ]) + + // Build navigation rules. + var resultSelector = ORKResultSelector(stepIdentifier: String(describing: Identifier.eligibilityFormStep), resultIdentifier: String(describing: Identifier.eligibilityFormItem01)) + let predicateFormItem01 = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "Yes" as NSCoding & NSCopying & NSObjectProtocol) + + resultSelector = ORKResultSelector(stepIdentifier: String(describing: Identifier.eligibilityFormStep), resultIdentifier: String(describing: Identifier.eligibilityFormItem02)) + let predicateFormItem02 = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "Yes" as NSCoding & NSCopying & NSObjectProtocol) + + resultSelector = ORKResultSelector(stepIdentifier: String(describing: Identifier.eligibilityFormStep), resultIdentifier: String(describing: Identifier.eligibilityFormItem03)) + let predicateFormItem03 = ORKResultPredicate.predicateForChoiceQuestionResult(with: resultSelector, expectedAnswerValue: "No" as NSCoding & NSCopying & NSObjectProtocol) + + let predicateEligible = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateFormItem01, predicateFormItem02, predicateFormItem03]) + let predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: [ (predicateEligible, String(describing: Identifier.eligibilityEligibleStep)) ]) + + eligibilityTask.setNavigationRule(predicateRule, forTriggerStepIdentifier: String(describing: Identifier.eligibilityFormStep)) + + // Add end direct rules to skip unneeded steps + let directRule = ORKDirectStepNavigationRule(destinationStepIdentifier: ORKNullStepIdentifier) + eligibilityTask.setNavigationRule(directRule, forTriggerStepIdentifier: String(describing: Identifier.eligibilityIneligibleStep)) + + return eligibilityTask + } + + /// A task demonstrating how the ResearchKit framework can be used to obtain informed consent. + private var consentTask: ORKTask { + /* + Informed consent starts by presenting an animated sequence conveying + the main points of your consent document. + */ + let visualConsentStep = ORKVisualConsentStep(identifier: String(describing: Identifier.visualConsentStep), document: consentDocument) + + let investigatorShortDescription = NSLocalizedString("Institution", comment: "") + let investigatorLongDescription = NSLocalizedString("Institution and its partners", comment: "") + let localizedLearnMoreHTMLContent = NSLocalizedString("Your sharing learn more content here.", comment: "") + + /* + If you want to share the data you collect with other researchers for + use in other studies beyond this one, it is best practice to get + explicit permission from the participant. Use the consent sharing step + for this. + */ + let sharingConsentStep = ORKConsentSharingStep(identifier: String(describing: Identifier.consentSharingStep), investigatorShortDescription: investigatorShortDescription, investigatorLongDescription: investigatorLongDescription, localizedLearnMoreHTMLContent: localizedLearnMoreHTMLContent) + + /* + After the visual presentation, the consent review step displays + your consent document and can obtain a signature from the participant. + + The first signature in the document is the participant's signature. + This effectively tells the consent review step which signatory is + reviewing the document. + */ + let signature = consentDocument.signatures!.first + + let reviewConsentStep = ORKConsentReviewStep(identifier: String(describing: Identifier.consentReviewStep), signature: signature, in: consentDocument) + reviewConsentStep.requiresScrollToBottom = true + + // In a real application, you would supply your own localized text. + reviewConsentStep.title = NSLocalizedString("Consent Document", comment: "") + reviewConsentStep.text = loremIpsumText + reviewConsentStep.reasonForConsent = loremIpsumText + + return ORKOrderedTask(identifier: String(describing: Identifier.consentTask), steps: [ + visualConsentStep, + sharingConsentStep, + reviewConsentStep + ]) + } + + /// This task presents the Account Creation process. + private var accountCreationTask: ORKTask { + /* + A registration step provides a form step that is populated with email and password fields. + If you wish to include any of the additional fields, then you can specify it through the `options` parameter. + */ + let registrationTitle = NSLocalizedString("Registration", comment: "") + let passcodeValidationRegexPattern = "^(?=.*\\d).{4,8}$" + let passcodeValidationRegularExpression = try? NSRegularExpression(pattern: passcodeValidationRegexPattern) + let passcodeInvalidMessage = NSLocalizedString("A valid password must be 4 to 8 characters long and include at least one numeric character.", comment: "") + let registrationOptions: ORKRegistrationStepOption = [.includeGivenName, .includeFamilyName, .includeGender, .includeDOB, .includePhoneNumber] + let registrationStep = ORKRegistrationStep(identifier: String(describing: Identifier.registrationStep), title: registrationTitle, text: exampleDetailText, passcodeValidationRegularExpression: passcodeValidationRegularExpression, passcodeInvalidMessage: passcodeInvalidMessage, options: registrationOptions) + registrationStep.phoneNumberValidationRegularExpression = try? NSRegularExpression(pattern: "^[+]{1,1}[1]{1,1}\\s{1,1}[(]{1,1}[1-9]{3,3}[)]{1,1}\\s{1,1}[1-9]{3,3}\\s{1,1}[1-9]{4,4}$") + registrationStep.phoneNumberInvalidMessage = "Expected format +1 (555) 555 5555" + + /* + A wait step allows you to upload the data from the user registration onto your server before presenting the verification step. + */ + let waitTitle = NSLocalizedString("Creating account", comment: "") + let waitText = NSLocalizedString("Please wait while we upload your data", comment: "") + let waitStep = ORKWaitStep(identifier: String(describing: Identifier.waitStep)) + waitStep.title = waitTitle + waitStep.text = waitText + + /* + A verification step view controller subclass is required in order to use the verification step. + The subclass provides the view controller button and UI behavior by overriding the following methods. + */ + class VerificationViewController: ORKVerificationStepViewController { + override func resendEmailButtonTapped() { + let alertTitle = NSLocalizedString("Resend Verification Email", comment: "") + let alertMessage = NSLocalizedString("Button tapped", comment: "") + let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: UIAlertController.Style.alert) + alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) + self.present(alert, animated: true, completion: nil) + } + } + + let verificationStep = ORKVerificationStep(identifier: String(describing: Identifier.verificationStep), text: exampleDetailText, verificationViewControllerClass: VerificationViewController.self) + + return ORKOrderedTask(identifier: String(describing: Identifier.accountCreationTask), steps: [ + registrationStep, + waitStep, + verificationStep + ]) + } + + /// This tasks presents the login step. + private var loginTask: ORKTask { + /* + A login step view controller subclass is required in order to use the login step. + The subclass provides the behavior for the login step forgot password button. + */ + class LoginViewController: ORKLoginStepViewController { + override func forgotPasswordButtonTapped() { + let alertTitle = NSLocalizedString("Forgot password?", comment: "") + let alertMessage = NSLocalizedString("Button tapped", comment: "") + let alert = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: UIAlertController.Style.alert) + alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil)) + self.present(alert, animated: true, completion: nil) + } + } + + /* + A login step provides a form step that is populated with email and password fields, + and a button for `Forgot password?`. + */ + let loginTitle = NSLocalizedString("Login", comment: "") + let loginStep = ORKLoginStep(identifier: String(describing: Identifier.loginStep), title: loginTitle, text: exampleDetailText, loginViewControllerClass: LoginViewController.self) + + /* + A wait step allows you to validate the data from the user login against your server before proceeding. + */ + let waitTitle = NSLocalizedString("Logging in", comment: "") + let waitText = NSLocalizedString("Please wait while we validate your credentials", comment: "") + let waitStep = ORKWaitStep(identifier: String(describing: Identifier.loginWaitStep)) + waitStep.title = waitTitle + waitStep.text = waitText + + return ORKOrderedTask(identifier: String(describing: Identifier.loginTask), steps: [loginStep, waitStep]) + } + + /// This task demonstrates the Passcode creation process. + private var passcodeTask: ORKTask { + /* + If you want to protect the app using a passcode. It is reccomended to + ask user to create passcode as part of the consent process and use the + authentication and editing view controllers to interact with the passcode. + + The passcode is stored in the keychain. + */ + let passcodeConsentStep = ORKPasscodeStep(identifier: String(describing: Identifier.passcodeStep)) + passcodeConsentStep.title = NSLocalizedString("Passcode", comment: "") + return ORKOrderedTask(identifier: String(describing: Identifier.passcodeTask), steps: [passcodeConsentStep]) + } + + /// This task presents the Audio pre-defined active task. + private var audioTask: ORKTask { + return ORKOrderedTask.audioTask(withIdentifier: String(describing: Identifier.audioTask), intendedUseDescription: exampleDescription, speechInstruction: exampleSpeechInstruction, shortSpeechInstruction: exampleSpeechInstruction, duration: 20, recordingSettings: nil, checkAudioLevel: true, options: []) + } + + /** + Amsler Grid + */ + private var amslerGridTask: ORKTask { + return ORKOrderedTask.amslerGridTask(withIdentifier: String(describing: Identifier.amslerGridTask), intendedUseDescription: exampleDescription, options: []) + } + + /** + This task presents the Fitness pre-defined active task. For this example, + short walking and rest durations of 20 seconds each are used, whereas more + realistic durations might be several minutes each. + */ + private var fitnessTask: ORKTask { + return ORKOrderedTask.fitnessCheck(withIdentifier: String(describing: Identifier.fitnessTask), intendedUseDescription: exampleDescription, walkDuration: 20, restDuration: 20, options: []) + } + + /// This task presents the Hole Peg Test pre-defined active task. + private var holePegTestTask: ORKTask { + return ORKNavigableOrderedTask.holePegTest(withIdentifier: String(describing: Identifier.holePegTestTask), intendedUseDescription: exampleDescription, dominantHand: .right, numberOfPegs: 9, threshold: 0.2, rotated: false, timeLimit: 300, options: []) + } + + /// This task presents the PSAT pre-defined active task. + private var PSATTask: ORKTask { + return ORKOrderedTask.psatTask(withIdentifier: String(describing: Identifier.psatTask), intendedUseDescription: exampleDescription, presentationMode: ORKPSATPresentationMode.auditory.union(.visual), interStimulusInterval: 3.0, stimulusDuration: 1.0, seriesLength: 60, options: []) + } + + /// This task presents the Reaction Time pre-defined active task. + private var reactionTimeTask: ORKTask { + /// An example of a custom sound. + let successSoundURL = Bundle.main.url(forResource: "tap", withExtension: "aif")! + let successSound = SystemSound(soundURL: successSoundURL)! + return ORKOrderedTask.reactionTime(withIdentifier: String(describing: Identifier.reactionTime), intendedUseDescription: exampleDescription, maximumStimulusInterval: 10, minimumStimulusInterval: 4, thresholdAcceleration: 0.5, numberOfAttempts: 3, timeout: 3, successSound: successSound.soundID, timeoutSound: 0, failureSound: UInt32(kSystemSoundID_Vibrate), options: []) + } + + /// This task presents the Gait and Balance pre-defined active task. + private var shortWalkTask: ORKTask { + return ORKOrderedTask.shortWalk(withIdentifier: String(describing: Identifier.shortWalkTask), intendedUseDescription: exampleDescription, numberOfStepsPerLeg: 20, restDuration: 20, options: []) + } + + /// This task presents the Spatial Span Memory pre-defined active task. + private var spatialSpanMemoryTask: ORKTask { + return ORKOrderedTask.spatialSpanMemoryTask(withIdentifier: String(describing: Identifier.spatialSpanMemoryTask), intendedUseDescription: exampleDescription, initialSpan: 3, minimumSpan: 2, maximumSpan: 15, playSpeed: 1.0, maximumTests: 5, maximumConsecutiveFailures: 3, customTargetImage: nil, customTargetPluralName: nil, requireReversal: false, options: []) + } + + /// This task presents the Speech Recognition pre-defined active task. + private var speechRecognitionTask: ORKTask { + return ORKOrderedTask.speechRecognitionTask(withIdentifier: String(describing: Identifier.speechRecognitionTask), intendedUseDescription: exampleDescription, speechRecognizerLocale: .englishUS, speechRecognitionImage: nil, speechRecognitionText: NSLocalizedString("A quick brown fox jumps over the lazy dog.", comment: ""), shouldHideTranscript: false, allowsEdittingTranscript: true, options: []) + } + + /// This task presents the Speech in Noise pre-defined active task. + private var speechInNoiseTask: ORKTask { + return ORKOrderedTask.speechInNoiseTask(withIdentifier: String(describing: Identifier.speechInNoiseTask), intendedUseDescription: nil, options: []) + } + + /// This task presents the Stroop pre-defined active task. + private var stroopTask: ORKTask { + return ORKOrderedTask.stroopTask(withIdentifier: String(describing: Identifier.stroopTask), intendedUseDescription: exampleDescription, numberOfAttempts: 10, options: []) + } + + /// This task presents the swift Stroop pre-defined active task. + private var swiftStroopTask: ORKTask { + let instructionStep = ORKInstructionStep(identifier: "stroopInstructionStep") + instructionStep.title = "Stroop" + instructionStep.text = "Your description goes here." + instructionStep.image = UIImage(named: "stroop") + instructionStep.imageContentMode = .center + instructionStep.detailText = "Every time a word appears, select the first letter of the name of the COLOR that is shown." + + let instructionStep2 = ORKInstructionStep(identifier: "stroopInstructionStep2") + instructionStep2.title = "Stroop" + instructionStep2.text = "Your description goes here." + instructionStep2.detailText = "Every time a word appears, select the first letter of the name of the COLOR that is shown." + instructionStep2.image = UIImage(named: "stroop") + instructionStep2.imageContentMode = .center + + let countdownStep = ORKCountdownStep(identifier: "stroopCountdownStep") + countdownStep.title = "Stroop" + + let stroopStep = ORKSwiftStroopStep(identifier: "stroopStep") + stroopStep.numberOfAttempts = 10 + stroopStep.title = "Stroop" + stroopStep.text = "Select the first letter of the name of the COLOR that is shown." + stroopStep.spokenInstruction = stroopStep.text + + let completionStep = ORKCompletionStep(identifier: "stroopCompletionStep") + completionStep.title = "Activity Complete" + completionStep.text = "Your data will be analyzed and you will be notified when your results are ready." + + return ORKOrderedTask(identifier: "stroopTask", steps: [instructionStep, instructionStep2, countdownStep, stroopStep, completionStep]) + } + + /// This task presents the Timed Walk with turn around pre-defined active task. + private var timedWalkWithTurnAroundTask: ORKTask { + return ORKOrderedTask.timedWalk(withIdentifier: String(describing: Identifier.timedWalkWithTurnAroundTask), intendedUseDescription: exampleDescription, distanceInMeters: 100.0, timeLimit: 180.0, turnAroundTimeLimit: 60.0, includeAssistiveDeviceForm: true, options: []) + } + + /// This task presents the Tone Audiometry pre-defined active task. + private var toneAudiometryTask: ORKTask { + return ORKOrderedTask.toneAudiometryTask(withIdentifier: String(describing: Identifier.toneAudiometryTask), intendedUseDescription: exampleDescription, speechInstruction: nil, shortSpeechInstruction: nil, toneDuration: 20, options: []) + } + + /// This task presents the dBHL Tone Audiometry pre-defined active task. + private var dBHLToneAudiometryTask: ORKTask { + return ORKOrderedTask.dBHLToneAudiometryTask(withIdentifier: String(describing: Identifier.dBHLToneAudiometryTask), intendedUseDescription: nil, options: []) + } + + /// This task presents the environment spl meter step. + private var splMeterTask: ORKTask { + let splMeterStep = ORKEnvironmentSPLMeterStep(identifier: String(describing: Identifier.splMeterStep)) + splMeterStep.samplingInterval = 2 + splMeterStep.requiredContiguousSamples = 10 + splMeterStep.thresholdValue = 60 + splMeterStep.title = NSLocalizedString("SPL Meter", comment: "") + return ORKOrderedTask(identifier: String(describing: Identifier.splMeterTask), steps: [splMeterStep]) + } + + private var towerOfHanoiTask: ORKTask { + return ORKOrderedTask.towerOfHanoiTask(withIdentifier: String(describing: Identifier.towerOfHanoi), intendedUseDescription: exampleDescription, numberOfDisks: 5, options: []) + } + + /// This task presents the Two Finger Tapping pre-defined active task. + private var twoFingerTappingIntervalTask: ORKTask { + return ORKOrderedTask.twoFingerTappingIntervalTask(withIdentifier: String(describing: Identifier.twoFingerTappingIntervalTask), intendedUseDescription: exampleDescription, duration: 10, + handOptions: [.both], options: []) + } + + /// This task presents a walk back-and-forth task + private var walkBackAndForthTask: ORKTask { + return ORKOrderedTask.walkBackAndForthTask(withIdentifier: String(describing: Identifier.walkBackAndForthTask), intendedUseDescription: exampleDescription, walkDuration: 30, restDuration: 30, options: []) + } + + /// This task presents the Tremor Test pre-defined active task. + private var tremorTestTask: ORKTask { + return ORKOrderedTask.tremorTest(withIdentifier: String(describing: Identifier.tremorTestTask), + intendedUseDescription: exampleDescription, + activeStepDuration: 10, + activeTaskOptions: [], + handOptions: [.both], + options: []) + } + + /// This task presents a knee range of motion task + private var kneeRangeOfMotion: ORKTask { + return ORKOrderedTask.kneeRangeOfMotionTask(withIdentifier: String(describing: Identifier.kneeRangeOfMotion), limbOption: .right, intendedUseDescription: exampleDescription, options: []) + } + + /// This task presents a shoulder range of motion task + private var shoulderRangeOfMotion: ORKTask { + return ORKOrderedTask.shoulderRangeOfMotionTask(withIdentifier: String(describing: Identifier.shoulderRangeOfMotion), limbOption: .left, intendedUseDescription: exampleDescription, options: []) + } + + /// This task presents a trail making task + private var trailMaking: ORKTask { + let intendedUseDescription = "Tests visual attention and task switching" + return ORKOrderedTask.trailmakingTask(withIdentifier: String(describing: Identifier.trailMaking), intendedUseDescription: intendedUseDescription, trailmakingInstruction: nil, trailType: .B, options: []) + } + + // This task presents a visual acuity landolt C task + private var visualAcuityLandoltC: ORKTask { + let orderedTask = ORKOrderedTask.landoltCVisualAcuityTask(withIdentifier: String(describing: Identifier.visualAcuityLandoltC), intendedUseDescription: "lorem ipsum") + return orderedTask + } + + // This task presents a contrast sensitivity peak landolt C task + private var contrastSensitivityPeakLandoltC: ORKTask { + let orderedTask = ORKOrderedTask.landoltCContrastSensitivityTask(withIdentifier: String(describing: Identifier.contrastSensitivityPeakLandoltC), intendedUseDescription: "lorem ipsum") + return orderedTask + } + + /// This task presents a video instruction step + private var videoInstruction: ORKTask { + let videoInstructionStep = ORKVideoInstructionStep(identifier: String(describing: Identifier.videoInstructionStep)) + videoInstructionStep.title = NSLocalizedString("Video Instruction Step", comment: "") + videoInstructionStep.videoURL = URL(string: "https://www.apple.com/media/us/researchkit/2016/a63aa7d4_e6fd_483f_a59d_d962016c8093/films/carekit/researchkit-carekit-cc-us-20160321_r848-9dwc.mov") + videoInstructionStep.thumbnailTime = 2 // Customizable thumbnail timestamp + return ORKOrderedTask(identifier: String(describing: Identifier.videoInstructionTask), steps: [videoInstructionStep]) + } + + // This task presents a web view step + private var webView: ORKTask { + let webViewStep = ORKWebViewStep(identifier: String(describing: Identifier.webViewStep), html: exampleHtml) + webViewStep.title = NSLocalizedString("Web View", comment: "") + return ORKOrderedTask(identifier: String(describing: Identifier.webViewTask), steps: [webViewStep]) + } + + // MARK: Consent Document Creation Convenience + + /** + A consent document provides the content for the visual consent and consent + review steps. This helper sets up a consent document with some dummy + content. You should populate your consent document to suit your study. + */ + private var consentDocument: ORKConsentDocument { + let consentDocument = ORKConsentDocument() + + /* + This is the title of the document, displayed both for review and in + the generated PDF. + */ + consentDocument.title = NSLocalizedString("Example Consent", comment: "") + + // This is the title of the signature page in the generated document. + consentDocument.signaturePageTitle = NSLocalizedString("Consent", comment: "") + + /* + This is the line shown on the signature page of the generated document, + just above the signatures. + */ + consentDocument.signaturePageContent = NSLocalizedString("I agree to participate in this research study.", comment: "") + + /* + Add the participant signature, which will be filled in during the + consent review process. This signature initially does not have a + signature image or a participant name; these are collected during + the consent review step. + */ + let participantSignatureTitle = NSLocalizedString("Participant", comment: "") + let participantSignature = ORKConsentSignature(forPersonWithTitle: participantSignatureTitle, dateFormatString: nil, identifier: String(describing: Identifier.consentDocumentParticipantSignature)) + + consentDocument.addSignature(participantSignature) + + /* + Add the investigator signature. This is pre-populated with the + investigator's signature image and name, and the date of their + signature. If you need to specify the date as now, you could generate + a date string with code here. + + This signature is only used for the generated PDF. + */ + let signatureImage = UIImage(named: "signature")! + let investigatorSignatureTitle = NSLocalizedString("Investigator", comment: "") + let investigatorSignatureGivenName = NSLocalizedString("Jonny", comment: "") + let investigatorSignatureFamilyName = NSLocalizedString("Appleseed", comment: "") + let investigatorSignatureDateString = "3/10/15" + + let investigatorSignature = ORKConsentSignature(forPersonWithTitle: investigatorSignatureTitle, dateFormatString: nil, identifier: String(describing: Identifier.consentDocumentInvestigatorSignature), givenName: investigatorSignatureGivenName, familyName: investigatorSignatureFamilyName, signatureImage: signatureImage, dateString: investigatorSignatureDateString) + + consentDocument.addSignature(investigatorSignature) + + /* + This is the HTML content for the "Learn More" page for each consent + section. In a real consent, this would be your content, and you would + have different content for each section. + + If your content is just text, you can use the `content` property + instead of the `htmlContent` property of `ORKConsentSection`. + */ + let htmlContentString = "
    • Lorem
    • ipsum
    • dolor

    \(loremIpsumLongText)

    \(loremIpsumMediumText)

    " + + /* + These are all the consent section types that have pre-defined animations + and images. We use them in this specific order, so we see the available + animated transitions. + */ + let consentSectionTypes: [ORKConsentSectionType] = [ + .overview, + .dataGathering, + .privacy, + .dataUse, + .timeCommitment, + .studySurvey, + .studyTasks, + .withdrawing + ] + + /* + For each consent section type in `consentSectionTypes`, create an + `ORKConsentSection` that represents it. + + In a real app, you would set specific content for each section. + */ + var consentSections: [ORKConsentSection] = consentSectionTypes.map { contentSectionType in + let consentSection = ORKConsentSection(type: contentSectionType) + + consentSection.summary = loremIpsumShortText + + if contentSectionType == .overview { + consentSection.htmlContent = htmlContentString + } else { + consentSection.content = loremIpsumLongText + } + + return consentSection + } + + /* + This is an example of a section that is only in the review document + or only in the generated PDF, and is not displayed in `ORKVisualConsentStep`. + */ + let consentSection = ORKConsentSection(type: .onlyInDocument) + consentSection.summary = NSLocalizedString(".OnlyInDocument Scene Summary", comment: "") + consentSection.title = NSLocalizedString(".OnlyInDocument Scene", comment: "") + consentSection.content = loremIpsumLongText + + consentSections += [consentSection] + + // Set the sections on the document after they've been created. + consentDocument.sections = consentSections + + return consentDocument + } + + // MARK: `ORKTask` Reused Text Convenience + + private var exampleDescription: String { + return NSLocalizedString("Your description goes here.", comment: "") + } + + private var exampleSpeechInstruction: String { + return NSLocalizedString("Your more specific voice instruction goes here. For example, say 'Aaaah'.", comment: "") + } + + private var exampleQuestionText: String { + return NSLocalizedString("Your question goes here.", comment: "") + } + + private var exampleHighValueText: String { + return NSLocalizedString("High Value", comment: "") + } + + private var exampleLowValueText: String { + return NSLocalizedString("Low Value", comment: "") + } + + private var exampleDetailText: String { + return NSLocalizedString("Additional text can go here.", comment: "") + } + + private var exampleEmailText: String { + return NSLocalizedString("jappleseed@example.com", comment: "") + } + + private var loremIpsumText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + } + + private var loremIpsumShortText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + } + + private var loremIpsumMediumText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo?" + } + + private var loremIpsumLongText: String { + return "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam adhuc, meo fortasse vitio, quid ego quaeram non perspicis. Plane idem, inquit, et maxima quidem, qua fieri nulla maior potest. Quonam, inquit, modo? An potest, inquit ille, quicquam esse suavius quam nihil dolere? Cave putes quicquam esse verius. Quonam, inquit, modo?" + } + + private var exampleHtml: String { + return """ + + + + + + + + + + +
    + + +
    + + + """ + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListViewController.swift new file mode 100755 index 0000000..9595d7b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/ORKCatalog/Tasks/TaskListViewController.swift @@ -0,0 +1,203 @@ +/* + Copyright (c) 2015, Apple Inc. All rights reserved. + Copyright (c) 2015, Ricardo Sánchez-Sáez. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +/** + This example displays a catalog of tasks, each consisting of one or two steps, + built using the ResearchKit framework. The `TaskListViewController` displays the + available tasks in this catalog. + + When you tap a task, it is presented like a participant in a study might + see it. After completing the task, you can see the results generated by + the task by switching to the results tab. +*/ +class TaskListViewController: UITableViewController, ORKTaskViewControllerDelegate { + + var waitStepViewController: ORKWaitStepViewController? + var waitStepUpdateTimer: Timer? + var waitStepProgress: CGFloat = 0.0 + + // MARK: Types + + enum TableViewCellIdentifier: String { + case `default` = "Default" + } + + // MARK: Properties + + /** + When a task is completed, the `TaskListViewController` calls this closure + with the created task. + */ + var taskResultFinishedCompletionHandler: ((ORKResult) -> Void)? + + // MARK: View Life Cycle + + override func viewDidLoad() { + super.viewDidLoad() + + if #available(iOS 13.0, *) { + self.tableView.backgroundColor = UIColor.systemGroupedBackground + } + } + + // MARK: UITableViewDataSource + + override func numberOfSections(in tableView: UITableView) -> Int { + return TaskListRow.sections.count + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return TaskListRow.sections[section].rows.count + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return TaskListRow.sections[section].title + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCellIdentifier.default.rawValue, for: indexPath) + + let taskListRow = TaskListRow.sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row] + + cell.textLabel!.text = "\(taskListRow)" + + if #available(iOS 13.0, *) { + cell.textLabel?.textColor = UIColor.label + } + + return cell + } + + // MARK: UITableViewDelegate + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + // Present the task view controller that the user asked for. + let taskListRow = TaskListRow.sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row] + + // Create a task from the `TaskListRow` to present in the `ORKTaskViewController`. + let task = taskListRow.representedTask + + /* + Passing `nil` for the `taskRunUUID` lets the task view controller + generate an identifier for this run of the task. + */ + let taskViewController = ORKTaskViewController(task: task, taskRun: nil) + + // Make sure we receive events from `taskViewController`. + taskViewController.delegate = self + + // Assign a directory to store `taskViewController` output. + taskViewController.outputDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + /* + We present the task directly, but it is also possible to use segues. + The task property of the task view controller can be set any time before + the task view controller is presented. + */ + present(taskViewController, animated: true, completion: nil) + } + + // MARK: ORKTaskViewControllerDelegate + + func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + /* + The `reason` passed to this method indicates why the task view + controller finished: Did the user cancel, save, or actually complete + the task; or was there an error? + + The actual result of the task is on the `result` property of the task + view controller. + */ + taskResultFinishedCompletionHandler?(taskViewController.result) + + taskViewController.dismiss(animated: true, completion: nil) + } + + func taskViewController(_ taskViewController: ORKTaskViewController, stepViewControllerWillAppear stepViewController: ORKStepViewController) { + // Example data processing for the wait step. + if stepViewController.step?.identifier == "WaitStepIndeterminate" || + stepViewController.step?.identifier == "WaitStep" || + stepViewController.step?.identifier == "LoginWaitStep" { + delay(5.0, closure: { () -> Void in + if let stepViewController = stepViewController as? ORKWaitStepViewController { + stepViewController.goForward() + } + }) + } else if stepViewController.step?.identifier == "WaitStepDeterminate" { + delay(1.0, closure: { () -> Void in + if let stepViewController = stepViewController as? ORKWaitStepViewController { + self.waitStepViewController = stepViewController + self.waitStepProgress = 0.0 + self.waitStepUpdateTimer = Timer(timeInterval: 0.1, target: self, selector: #selector(TaskListViewController.updateProgressOfWaitStepViewController), userInfo: nil, repeats: true) + RunLoop.main.add(self.waitStepUpdateTimer!, forMode: RunLoop.Mode.common) + } + }) + } + } + + func taskViewController(_ taskViewController: ORKTaskViewController, learnMoreButtonPressedWith learnMoreStep: ORKLearnMoreInstructionStep, for stepViewController: ORKStepViewController) { + // FIXME: Temporary fix. This method should not be called if it is only used to present the learnMoreStepViewController, the stepViewController should present the learnMoreStepViewController. + stepViewController.present(UINavigationController(rootViewController: ORKLearnMoreStepViewController(step: learnMoreStep)), animated: true) { + + } + } + + func delay(_ delay: Double, closure: @escaping () -> Void ) { + let delayTime = DispatchTime.now() + delay + let dispatchWorkItem = DispatchWorkItem(block: closure) + DispatchQueue.main.asyncAfter(deadline: delayTime, execute: dispatchWorkItem) + } + + @objc + func updateProgressOfWaitStepViewController() { + if let waitStepViewController = waitStepViewController { + waitStepProgress += 0.01 + DispatchQueue.main.async(execute: { () -> Void in + waitStepViewController.setProgress(self.waitStepProgress, animated: true) + }) + if waitStepProgress < 1.0 { + return + } else { + self.waitStepUpdateTimer?.invalidate() + waitStepViewController.goForward() + self.waitStepViewController = nil + } + } else { + self.waitStepUpdateTimer?.invalidate() + } + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/readme.md b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/readme.md new file mode 100755 index 0000000..8a6b2c3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKCatalog/readme.md @@ -0,0 +1,98 @@ +# ORKCatalog + +*ORKCatalog* is a sample app that demonstrates the types of elements you can use to +present tasks using the *ResearchKit framework*, such as *surveys*, *consent tasks*, and *active tasks*. + +*ORKCatalog* shows you how to: + ++ Use the ResearchKit framework model elements to construct a task. ++ Present a task view controller. ++ Handle the delegate callbacks from the task view controller. + +Note that the task list view controller (`TaskListViewController`) uses the +`NSLocalizedString()` function to present all content, which makes it easy for +you to localize. + +ORKCatalog also shows you how to access the structure of the results collected by +an `ORKTaskViewController` instance, which are displayed in a result view controller +(`ResultViewController`). To see the results collected by a task, start the app, +perform a task, and tap the Results tab to view the result hierarchy. Note that +this result view controller is included solely for the purpose of demonstrating +how to access the properties and methods of `ORKResult` instances; for that reason, +none of the content in the result view controller is localized. A shipping ResearchKit +app does not expose the content in a result view controller to users. + +The *ORKCatalog* sample app is written in *Swift*. + +For more conceptual information about the *ResearchKit framework*, see the +[ResearchKit Framework Programming Guide](http://researchkit.github.io/docs/docs/Overview/GuideOverview.html). + + +## Build Requirements + ++ Xcode 7.0. ++ iOS 9.0 SDK or later. + + +## Runtime Requirements + ++ iOS 8.0 or later. + + +## Architecture + +*ORKCatalog* functionality is divided into two main parts: + +1) Presenting tasks to the user. + +The logic for presenting tasks is in `TaskListViewController` and `TaskListRow`. +`TaskListRow` is an enumeration of all the different types of tasks that *ORKCatalog* +demonstrates. This enum also contains all of the logic for creating an `ORKTask` +representation of the `TaskListRow`. For example, if you have a `TaskListRow.TimeOfDayQuestion` +instance, accessing the `representedTask` property returns an `ORKOrderedTask` +instance that contains an `ORKQuestionStep` that uses a date / time answer format +(`ORKAnswerFormat.dateTimeAnswerFormat()`). + +2) Displaying results of the most recently presented task. + +Results are displayed inside a `ResultViewController`. The result view controller +contains a `result` property that is set in the app delegate when the `TaskListViewController` +presents a task. Even if the user does not complete a task, the result is displayed +in the result view controller (in the case of an unfinished task, the result view +controller displays the parts of the task that the user has completed). + +The logic to present a specific task (that is, the result view controller's data +source and delegate) is defined in *ResultTableViewProviders.swift*. Each type of +result that's displayed in the `ResultViewController` has an associated `ResultTableViewProvider` +subclass. For example, when displaying the metadata of an `ORKChoiceQuestionResult` +instance, a `ChoiceQuestionResultTableViewProvider` is used. Each table view provider +returns more specific information about the type of task that it presents. + +Results are also displayed in a hierarchy. If a result has children, you can view +the metadata by tapping the child's table view cell. When you do this, you're +presented with another `ResultViewController` instance that displays the metadata +for that specific child result. + + +## Using the Sample + +You can run *ORKCatalog* on an *iOS device* or in the *iOS Simulator*. + +Tasks are subdivided into four categories: *Surveys*, *Survey Questions*, *Consent*, +and *Active Tasks*. Each category mostly presents the examples in an alphabetically-ordered +fashion. + +Note that for the most part, the *ORKCatalog* source code uses a consistent ordering +for the boilerplate code throughout the project. Within the `TaskListRow` enum potion +corresponding to the *Survey Question* section, for example, grouped sections of code always +handle the `.BooleanQuestion` case first, and the task that represents the `.BooleanQuestion` +enum is displayed first in the `TaskListViewController`. This ordering makes it easy to navigate +the sample. + +As much as possible, this ordering is also maintained in the `TaskListRow` and +`ResultTableViewProvider` code. For example, in the `resultTableViewProviderForResult()` +function, the `ORKBooleanQuestionResult` case is handled first to match the order +that is used in the `TaskListRow` enum. + +If you want to add functionality that needs to integrate with the `TaskListRow` +or `ResultTableViewProvider` code, be sure to consider the ordering. diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Base.lproj/Interface.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Base.lproj/Interface.storyboard new file mode 100755 index 0000000..365e83e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Base.lproj/Interface.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Info.plist new file mode 100755 index 0000000..2bb74ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit App/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ORKParkinsonStudy WatchKit App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + + WKCompanionAppBundleIdentifier + com.example.researchkit-samplecode.ORKParkinsonStudy + WKWatchKitApp + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/AssessmentManager.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/AssessmentManager.swift new file mode 100755 index 0000000..03ef188 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/AssessmentManager.swift @@ -0,0 +1,63 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation + +@available(watchOSApplicationExtension 5.0, *) +class AssessmentManager { + private var manager: CMMovementDisorderManager? + init() { + if CMMovementDisorderManager.isAvailable() { + manager = CMMovementDisorderManager() + + monitorForParkinsons() + + } + } + + func monitorForParkinsons() { + manager?.monitorKinesias(forDuration: 7 * 24 * 3600) + } + + func queryNewAssessments() { + let calendar = Calendar.current + let toDate = Date() + let fromDate: Date = calendar.date(byAdding: .day, value: -7, to: toDate)! + + manager?.queryTremor(from: fromDate, to: toDate, withHandler: { (results, error) in + + }) + + manager?.queryDyskineticSymptom(from: fromDate, to: toDate, withHandler: { (results, error) in + + }) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ComplicationController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ComplicationController.swift new file mode 100755 index 0000000..368d1ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ComplicationController.swift @@ -0,0 +1,79 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import ClockKit + + +class ComplicationController: NSObject, CLKComplicationDataSource { + + // MARK: - Timeline Configuration + + func getSupportedTimeTravelDirections(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimeTravelDirections) -> Void) { + handler([.forward, .backward]) + } + + func getTimelineStartDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { + handler(nil) + } + + func getTimelineEndDate(for complication: CLKComplication, withHandler handler: @escaping (Date?) -> Void) { + handler(nil) + } + + func getPrivacyBehavior(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationPrivacyBehavior) -> Void) { + handler(.showOnLockScreen) + } + + // MARK: - Timeline Population + + func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) { + // Call the handler with the current timeline entry + handler(nil) + } + + func getTimelineEntries(for complication: CLKComplication, before date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { + // Call the handler with the timeline entries prior to the given date + handler(nil) + } + + func getTimelineEntries(for complication: CLKComplication, after date: Date, limit: Int, withHandler handler: @escaping ([CLKComplicationTimelineEntry]?) -> Void) { + // Call the handler with the timeline entries after to the given date + handler(nil) + } + + // MARK: - Placeholder Templates + + func getLocalizableSampleTemplate(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTemplate?) -> Void) { + // This method will be called once per supported complication, and the results will be cached + handler(nil) + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ExtensionDelegate.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ExtensionDelegate.swift new file mode 100755 index 0000000..e925545 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ExtensionDelegate.swift @@ -0,0 +1,78 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import WatchKit + +class ExtensionDelegate: NSObject, WKExtensionDelegate { + + func applicationDidFinishLaunching() { + // Perform any final initialization of your application. + } + + func applicationDidBecomeActive() { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillResignActive() { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, etc. + } + + func handle(_ backgroundTasks: Set) { + // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one. + for task in backgroundTasks { + // Use a switch statement to check the task type + switch task { + case let backgroundTask as WKApplicationRefreshBackgroundTask: + // Be sure to complete the background task once you’re done. + backgroundTask.setTaskCompletedWithSnapshot(false) + case let snapshotTask as WKSnapshotRefreshBackgroundTask: + // Snapshot tasks have a unique completion call, make sure to set your expiration date + snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil) + case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask: + // Be sure to complete the connectivity task once you’re done. + connectivityTask.setTaskCompletedWithSnapshot(false) + case let urlSessionTask as WKURLSessionRefreshBackgroundTask: + // Be sure to complete the URL session task once you’re done. + urlSessionTask.setTaskCompletedWithSnapshot(false) + case let relevantShortcutTask as WKRelevantShortcutRefreshBackgroundTask: + // Be sure to complete the relevant-shortcut task once you're done. + relevantShortcutTask.setTaskCompletedWithSnapshot(false) + case let intentDidRunTask as WKIntentDidRunRefreshBackgroundTask: + // Be sure to complete the intent-did-run task once you're done. + intentDidRunTask.setTaskCompletedWithSnapshot(false) + default: + // make sure to complete unhandled task types + task.setTaskCompletedWithSnapshot(false) + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/Info.plist new file mode 100755 index 0000000..468d114 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/Info.plist @@ -0,0 +1,48 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ORKParkinsonStudy WatchKit Extension + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + XPC! + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + CLKComplicationPrincipalClass + $(PRODUCT_MODULE_NAME).ComplicationController + CLKComplicationSupportedFamilies + + CLKComplicationFamilyModularSmall + CLKComplicationFamilyModularLarge + CLKComplicationFamilyUtilitarianSmall + CLKComplicationFamilyUtilitarianSmallFlat + CLKComplicationFamilyUtilitarianLarge + CLKComplicationFamilyCircularSmall + CLKComplicationFamilyExtraLarge + + NSExtension + + NSExtensionAttributes + + WKAppBundleIdentifier + com.example.researchkit-samplecode.ORKParkinsonStudy.watchkitapp + + NSExtensionPointIdentifier + com.apple.watchkit + + WKExtensionDelegateClassName + $(PRODUCT_MODULE_NAME).ExtensionDelegate + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/InterfaceController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/InterfaceController.swift new file mode 100755 index 0000000..d1e5aca --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/InterfaceController.swift @@ -0,0 +1,54 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import WatchKit +import Foundation + + +class InterfaceController: WKInterfaceController { + + override func awake(withContext context: Any?) { + super.awake(withContext: context) + + // Configure interface objects here. + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/NotificationController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/NotificationController.swift new file mode 100755 index 0000000..c64f117 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/NotificationController.swift @@ -0,0 +1,61 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import WatchKit +import Foundation +import UserNotifications + + +class NotificationController: WKUserNotificationInterfaceController { + + override init() { + // Initialize variables here. + super.init() + + // Configure interface objects here. + } + + override func willActivate() { + // This method is called when watch view controller is about to be visible to user + super.willActivate() + } + + override func didDeactivate() { + // This method is called when watch view controller is no longer visible + super.didDeactivate() + } + + override func didReceive(_ notification: UNNotification) { + // This method is called when a notification needs to be presented. + // Implement it if you use a dynamic notification interface. + // Populate your dynamic notification interface as quickly as possible. + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ORKParkinsonStudy-Bridging-Header.h b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ORKParkinsonStudy-Bridging-Header.h new file mode 100755 index 0000000..99745ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/ORKParkinsonStudy-Bridging-Header.h @@ -0,0 +1,32 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#import diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/PushNotificationPayload.apns b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/PushNotificationPayload.apns new file mode 100755 index 0000000..5ac5526 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy WatchKit Extension/Supporting Files/PushNotificationPayload.apns @@ -0,0 +1,20 @@ +{ + "aps": { + "alert": { + "body": "Test message", + "title": "Optional title", + "subtitle": "Optional subtitle" + }, + "category": "myCategory", + "thread-id":"5280" + }, + + "WatchKit Simulator Actions": [ + { + "title": "First Button", + "identifier": "firstButtonAction" + } + ], + + "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App." +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/project.pbxproj new file mode 100755 index 0000000..c62c08c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/project.pbxproj @@ -0,0 +1,777 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + BA29889020BCF89200D19DEF /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA29888F20BCF89200D19DEF /* Colors.swift */; }; + BA2988A020BDCE1900D19DEF /* AssessmentManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA29889F20BDCE1900D19DEF /* AssessmentManager.swift */; }; + BA357DCC20BDD0DF00000AF0 /* ExtensionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA357DCB20BDD0DF00000AF0 /* ExtensionDelegate.swift */; }; + BA87DBA220B80FFB004ACAFF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBA120B80FFB004ACAFF /* AppDelegate.swift */; }; + BA87DBA720B80FFB004ACAFF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BA87DBA520B80FFB004ACAFF /* Main.storyboard */; }; + BA87DBA920B80FFD004ACAFF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BA87DBA820B80FFD004ACAFF /* Assets.xcassets */; }; + BA87DBAC20B80FFD004ACAFF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BA87DBAA20B80FFD004ACAFF /* LaunchScreen.storyboard */; }; + BA87DBB120B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = BA87DBB020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app */; }; + BA87DBB720B80FFD004ACAFF /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BA87DBB520B80FFD004ACAFF /* Interface.storyboard */; }; + BA87DBC020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = BA87DBBF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + BA87DBC520B80FFD004ACAFF /* InterfaceController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBC420B80FFD004ACAFF /* InterfaceController.swift */; }; + BA87DBC920B80FFD004ACAFF /* NotificationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBC820B80FFD004ACAFF /* NotificationController.swift */; }; + BA87DBCB20B80FFD004ACAFF /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBCA20B80FFD004ACAFF /* ComplicationController.swift */; }; + BA87DBF020B81A79004ACAFF /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBEF20B81A79004ACAFF /* RootViewController.swift */; }; + BA87DBF320B81BFB004ACAFF /* OnboardingStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBF220B81BFB004ACAFF /* OnboardingStateManager.swift */; }; + BA87DBF520B81D21004ACAFF /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBF420B81D21004ACAFF /* OnboardingViewController.swift */; }; + BA87DBF820B81DB1004ACAFF /* TaskListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBF720B81DB1004ACAFF /* TaskListViewController.swift */; }; + BA87DBFA20B81E3D004ACAFF /* ConsentDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DBF920B81E3D004ACAFF /* ConsentDocument.swift */; }; + BA87DBFE20B81EBF004ACAFF /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BA87DBFD20B81EBF004ACAFF /* ResearchKit.framework */; }; + BA87DBFF20B81EBF004ACAFF /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BA87DBFD20B81EBF004ACAFF /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + BA87DC0A20B8334C004ACAFF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = BA87DC0820B8334C004ACAFF /* Localizable.strings */; }; + BA87DC0E20B83642004ACAFF /* HeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DC0D20B83642004ACAFF /* HeaderView.swift */; }; + BA87DC1120B8BA08004ACAFF /* GraphViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA87DC1020B8BA08004ACAFF /* GraphViewController.swift */; }; + BA907FAF20C07558003E7BE9 /* tremor.json in Resources */ = {isa = PBXBuildFile; fileRef = BA907FAD20C07558003E7BE9 /* tremor.json */; }; + BA907FB020C07558003E7BE9 /* dyskinesia.json in Resources */ = {isa = PBXBuildFile; fileRef = BA907FAE20C07558003E7BE9 /* dyskinesia.json */; }; + BADF599E20BB55150070F7D9 /* ChartDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADF599D20BB55150070F7D9 /* ChartDataSources.swift */; }; + BADF59A820BB61800070F7D9 /* BarGraphChartTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BADF59A720BB61800070F7D9 /* BarGraphChartTableViewCell.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + BA87DBB220B80FFD004ACAFF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA87DB9620B80FFB004ACAFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA87DBAF20B80FFD004ACAFF; + remoteInfo = "ORKParkinsonStudy WatchKit App"; + }; + BA87DBC120B80FFD004ACAFF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = BA87DB9620B80FFB004ACAFF /* Project object */; + proxyType = 1; + remoteGlobalIDString = BA87DBBE20B80FFD004ACAFF; + remoteInfo = "ORKParkinsonStudy WatchKit Extension"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + BA87DBD520B80FFE004ACAFF /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + BA87DBC020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DBD920B80FFE004ACAFF /* Embed Watch Content */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "$(CONTENTS_FOLDER_PATH)/Watch"; + dstSubfolderSpec = 16; + files = ( + BA87DBB120B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app in Embed Watch Content */, + ); + name = "Embed Watch Content"; + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DC0020B81EBF004ACAFF /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + BA87DBFF20B81EBF004ACAFF /* ResearchKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + BA29888F20BCF89200D19DEF /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; + BA29889320BDC88500D19DEF /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = Platforms/WatchOS.platform/Developer/SDKs/WatchOS5.0.sdk/System/Library/Frameworks/CoreMotion.framework; sourceTree = DEVELOPER_DIR; }; + BA29889F20BDCE1900D19DEF /* AssessmentManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssessmentManager.swift; sourceTree = ""; }; + BA357DCA20BDD05B00000AF0 /* ORKParkinsonStudy-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ORKParkinsonStudy-Bridging-Header.h"; sourceTree = ""; }; + BA357DCB20BDD0DF00000AF0 /* ExtensionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionDelegate.swift; sourceTree = ""; }; + BA87DB9E20B80FFB004ACAFF /* ORKParkinsonStudy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKParkinsonStudy.app; sourceTree = BUILT_PRODUCTS_DIR; }; + BA87DBA120B80FFB004ACAFF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + BA87DBA620B80FFB004ACAFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + BA87DBA820B80FFD004ACAFF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + BA87DBAB20B80FFD004ACAFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + BA87DBAD20B80FFD004ACAFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + BA87DBB020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ORKParkinsonStudy WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + BA87DBB620B80FFD004ACAFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; + BA87DBBA20B80FFD004ACAFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + BA87DBBF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "ORKParkinsonStudy WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; + BA87DBC420B80FFD004ACAFF /* InterfaceController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InterfaceController.swift; sourceTree = ""; }; + BA87DBC820B80FFD004ACAFF /* NotificationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationController.swift; sourceTree = ""; }; + BA87DBCA20B80FFD004ACAFF /* ComplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComplicationController.swift; sourceTree = ""; }; + BA87DBCE20B80FFE004ACAFF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + BA87DBCF20B80FFE004ACAFF /* PushNotificationPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = PushNotificationPayload.apns; sourceTree = ""; }; + BA87DBE620B81307004ACAFF /* ResearchKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ResearchKit.framework; path = "../../../../../../Library/Developer/Xcode/DerivedData/RKWorkspace-cwgffykaxbqdxvcunvphbajbfyhl/Build/Products/Debug-iphoneos/ResearchKit.framework"; sourceTree = ""; }; + BA87DBE820B814A7004ACAFF /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + BA87DBEF20B81A79004ACAFF /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; + BA87DBF220B81BFB004ACAFF /* OnboardingStateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingStateManager.swift; sourceTree = ""; }; + BA87DBF420B81D21004ACAFF /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = ""; }; + BA87DBF720B81DB1004ACAFF /* TaskListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskListViewController.swift; sourceTree = ""; }; + BA87DBF920B81E3D004ACAFF /* ConsentDocument.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConsentDocument.swift; sourceTree = ""; }; + BA87DBFD20B81EBF004ACAFF /* ResearchKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ResearchKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BA87DC0920B8334C004ACAFF /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = ORKParkinsonStudy/Base.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; }; + BA87DC0D20B83642004ACAFF /* HeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderView.swift; sourceTree = ""; }; + BA87DC1020B8BA08004ACAFF /* GraphViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphViewController.swift; sourceTree = ""; }; + BA907FAD20C07558003E7BE9 /* tremor.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tremor.json; sourceTree = ""; }; + BA907FAE20C07558003E7BE9 /* dyskinesia.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = dyskinesia.json; sourceTree = ""; }; + BADF599D20BB55150070F7D9 /* ChartDataSources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartDataSources.swift; sourceTree = ""; }; + BADF59A720BB61800070F7D9 /* BarGraphChartTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarGraphChartTableViewCell.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + BA87DB9B20B80FFB004ACAFF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BA87DBFE20B81EBF004ACAFF /* ResearchKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DBBC20B80FFD004ACAFF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + BA2988A120BDCE2B00D19DEF /* Supporting Files */ = { + isa = PBXGroup; + children = ( + BA357DCB20BDD0DF00000AF0 /* ExtensionDelegate.swift */, + BA357DCA20BDD05B00000AF0 /* ORKParkinsonStudy-Bridging-Header.h */, + BA87DBCE20B80FFE004ACAFF /* Info.plist */, + BA87DBCF20B80FFE004ACAFF /* PushNotificationPayload.apns */, + BA87DBC420B80FFD004ACAFF /* InterfaceController.swift */, + BA87DBC820B80FFD004ACAFF /* NotificationController.swift */, + BA87DBCA20B80FFD004ACAFF /* ComplicationController.swift */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + BA87DB9520B80FFB004ACAFF = { + isa = PBXGroup; + children = ( + BA87DBFD20B81EBF004ACAFF /* ResearchKit.framework */, + BA87DBE820B814A7004ACAFF /* README.md */, + BA87DBA020B80FFB004ACAFF /* ORKParkinsonStudy */, + BA87DBB420B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App */, + BA87DBC320B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension */, + BA87DB9F20B80FFB004ACAFF /* Products */, + BA87DBE120B812DC004ACAFF /* Frameworks */, + ); + sourceTree = ""; + }; + BA87DB9F20B80FFB004ACAFF /* Products */ = { + isa = PBXGroup; + children = ( + BA87DB9E20B80FFB004ACAFF /* ORKParkinsonStudy.app */, + BA87DBB020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app */, + BA87DBBF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex */, + ); + name = Products; + sourceTree = ""; + }; + BA87DBA020B80FFB004ACAFF /* ORKParkinsonStudy */ = { + isa = PBXGroup; + children = ( + BA87DBA120B80FFB004ACAFF /* AppDelegate.swift */, + BA87DBF620B81D90004ACAFF /* Presenting Tasks */, + BA87DC0F20B8B9EC004ACAFF /* Graphs */, + BA87DBF120B81BB2004ACAFF /* Onboarding */, + BA87DBEE20B81A36004ACAFF /* Main */, + BA87DBED20B8192C004ACAFF /* Supporting Files */, + ); + path = ORKParkinsonStudy; + sourceTree = ""; + }; + BA87DBB420B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App */ = { + isa = PBXGroup; + children = ( + BA87DBB520B80FFD004ACAFF /* Interface.storyboard */, + BA87DBBA20B80FFD004ACAFF /* Info.plist */, + ); + path = "ORKParkinsonStudy WatchKit App"; + sourceTree = ""; + }; + BA87DBC320B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension */ = { + isa = PBXGroup; + children = ( + BA29889F20BDCE1900D19DEF /* AssessmentManager.swift */, + BA2988A120BDCE2B00D19DEF /* Supporting Files */, + ); + path = "ORKParkinsonStudy WatchKit Extension"; + sourceTree = ""; + }; + BA87DBE120B812DC004ACAFF /* Frameworks */ = { + isa = PBXGroup; + children = ( + BA29889320BDC88500D19DEF /* CoreMotion.framework */, + BA87DBE620B81307004ACAFF /* ResearchKit.framework */, + ); + path = Frameworks; + sourceTree = ""; + }; + BA87DBED20B8192C004ACAFF /* Supporting Files */ = { + isa = PBXGroup; + children = ( + BA907FAE20C07558003E7BE9 /* dyskinesia.json */, + BA907FAD20C07558003E7BE9 /* tremor.json */, + BA87DC0820B8334C004ACAFF /* Localizable.strings */, + BA87DBA520B80FFB004ACAFF /* Main.storyboard */, + BA87DBA820B80FFD004ACAFF /* Assets.xcassets */, + BA87DBAA20B80FFD004ACAFF /* LaunchScreen.storyboard */, + BA87DBAD20B80FFD004ACAFF /* Info.plist */, + BA29888F20BCF89200D19DEF /* Colors.swift */, + ); + path = "Supporting Files"; + sourceTree = ""; + }; + BA87DBEE20B81A36004ACAFF /* Main */ = { + isa = PBXGroup; + children = ( + BA87DC0C20B83628004ACAFF /* Header */, + BA87DBEF20B81A79004ACAFF /* RootViewController.swift */, + ); + path = Main; + sourceTree = ""; + }; + BA87DBF120B81BB2004ACAFF /* Onboarding */ = { + isa = PBXGroup; + children = ( + BA87DBF220B81BFB004ACAFF /* OnboardingStateManager.swift */, + BA87DBF420B81D21004ACAFF /* OnboardingViewController.swift */, + BA87DBF920B81E3D004ACAFF /* ConsentDocument.swift */, + ); + path = Onboarding; + sourceTree = ""; + }; + BA87DBF620B81D90004ACAFF /* Presenting Tasks */ = { + isa = PBXGroup; + children = ( + BA87DBF720B81DB1004ACAFF /* TaskListViewController.swift */, + ); + path = "Presenting Tasks"; + sourceTree = ""; + }; + BA87DC0C20B83628004ACAFF /* Header */ = { + isa = PBXGroup; + children = ( + BA87DC0D20B83642004ACAFF /* HeaderView.swift */, + ); + path = Header; + sourceTree = ""; + }; + BA87DC0F20B8B9EC004ACAFF /* Graphs */ = { + isa = PBXGroup; + children = ( + BA87DC1020B8BA08004ACAFF /* GraphViewController.swift */, + BADF599D20BB55150070F7D9 /* ChartDataSources.swift */, + BADF59A720BB61800070F7D9 /* BarGraphChartTableViewCell.swift */, + ); + path = Graphs; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + BA87DB9D20B80FFB004ACAFF /* ORKParkinsonStudy */ = { + isa = PBXNativeTarget; + buildConfigurationList = BA87DBDA20B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy" */; + buildPhases = ( + BA87DB9A20B80FFB004ACAFF /* Sources */, + BA87DB9B20B80FFB004ACAFF /* Frameworks */, + BA87DB9C20B80FFB004ACAFF /* Resources */, + BA87DBD920B80FFE004ACAFF /* Embed Watch Content */, + BA87DC0020B81EBF004ACAFF /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + BA87DBB320B80FFD004ACAFF /* PBXTargetDependency */, + ); + name = ORKParkinsonStudy; + productName = ORKParkinsonStudy; + productReference = BA87DB9E20B80FFB004ACAFF /* ORKParkinsonStudy.app */; + productType = "com.apple.product-type.application"; + }; + BA87DBAF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App */ = { + isa = PBXNativeTarget; + buildConfigurationList = BA87DBD620B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy WatchKit App" */; + buildPhases = ( + BA87DBAE20B80FFD004ACAFF /* Resources */, + BA87DBD520B80FFE004ACAFF /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + BA87DBC220B80FFD004ACAFF /* PBXTargetDependency */, + ); + name = "ORKParkinsonStudy WatchKit App"; + productName = "ORKParkinsonStudy WatchKit App"; + productReference = BA87DBB020B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App.app */; + productType = "com.apple.product-type.application.watchapp2"; + }; + BA87DBBE20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension */ = { + isa = PBXNativeTarget; + buildConfigurationList = BA87DBD220B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy WatchKit Extension" */; + buildPhases = ( + BA87DBBB20B80FFD004ACAFF /* Sources */, + BA87DBBC20B80FFD004ACAFF /* Frameworks */, + BA87DBBD20B80FFD004ACAFF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ORKParkinsonStudy WatchKit Extension"; + productName = "ORKParkinsonStudy WatchKit Extension"; + productReference = BA87DBBF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension.appex */; + productType = "com.apple.product-type.watchkit2-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + BA87DB9620B80FFB004ACAFF /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1000; + LastUpgradeCheck = 1000; + ORGANIZATIONNAME = "Apple, Inc."; + TargetAttributes = { + BA87DB9D20B80FFB004ACAFF = { + CreatedOnToolsVersion = 10.0; + }; + BA87DBAF20B80FFD004ACAFF = { + CreatedOnToolsVersion = 10.0; + }; + BA87DBBE20B80FFD004ACAFF = { + CreatedOnToolsVersion = 10.0; + }; + }; + }; + buildConfigurationList = BA87DB9920B80FFB004ACAFF /* Build configuration list for PBXProject "ORKParkinsonStudy" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = BA87DB9520B80FFB004ACAFF; + productRefGroup = BA87DB9F20B80FFB004ACAFF /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + BA87DB9D20B80FFB004ACAFF /* ORKParkinsonStudy */, + BA87DBAF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App */, + BA87DBBE20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + BA87DB9C20B80FFB004ACAFF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BA87DBAC20B80FFD004ACAFF /* LaunchScreen.storyboard in Resources */, + BA87DC0A20B8334C004ACAFF /* Localizable.strings in Resources */, + BA907FAF20C07558003E7BE9 /* tremor.json in Resources */, + BA87DBA920B80FFD004ACAFF /* Assets.xcassets in Resources */, + BA87DBA720B80FFB004ACAFF /* Main.storyboard in Resources */, + BA907FB020C07558003E7BE9 /* dyskinesia.json in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DBAE20B80FFD004ACAFF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BA87DBB720B80FFD004ACAFF /* Interface.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DBBD20B80FFD004ACAFF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + BA87DB9A20B80FFB004ACAFF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BA87DBF320B81BFB004ACAFF /* OnboardingStateManager.swift in Sources */, + BA29889020BCF89200D19DEF /* Colors.swift in Sources */, + BA87DBFA20B81E3D004ACAFF /* ConsentDocument.swift in Sources */, + BA87DBF020B81A79004ACAFF /* RootViewController.swift in Sources */, + BA87DBA220B80FFB004ACAFF /* AppDelegate.swift in Sources */, + BADF599E20BB55150070F7D9 /* ChartDataSources.swift in Sources */, + BA87DBF520B81D21004ACAFF /* OnboardingViewController.swift in Sources */, + BA87DC1120B8BA08004ACAFF /* GraphViewController.swift in Sources */, + BA87DBF820B81DB1004ACAFF /* TaskListViewController.swift in Sources */, + BADF59A820BB61800070F7D9 /* BarGraphChartTableViewCell.swift in Sources */, + BA87DC0E20B83642004ACAFF /* HeaderView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BA87DBBB20B80FFD004ACAFF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + BA87DBC920B80FFD004ACAFF /* NotificationController.swift in Sources */, + BA2988A020BDCE1900D19DEF /* AssessmentManager.swift in Sources */, + BA357DCC20BDD0DF00000AF0 /* ExtensionDelegate.swift in Sources */, + BA87DBCB20B80FFD004ACAFF /* ComplicationController.swift in Sources */, + BA87DBC520B80FFD004ACAFF /* InterfaceController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + BA87DBB320B80FFD004ACAFF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA87DBAF20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit App */; + targetProxy = BA87DBB220B80FFD004ACAFF /* PBXContainerItemProxy */; + }; + BA87DBC220B80FFD004ACAFF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = BA87DBBE20B80FFD004ACAFF /* ORKParkinsonStudy WatchKit Extension */; + targetProxy = BA87DBC120B80FFD004ACAFF /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + BA87DBA520B80FFB004ACAFF /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + BA87DBA620B80FFB004ACAFF /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + BA87DBAA20B80FFD004ACAFF /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + BA87DBAB20B80FFD004ACAFF /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; + BA87DBB520B80FFD004ACAFF /* Interface.storyboard */ = { + isa = PBXVariantGroup; + children = ( + BA87DBB620B80FFD004ACAFF /* Base */, + ); + name = Interface.storyboard; + sourceTree = ""; + }; + BA87DC0820B8334C004ACAFF /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + BA87DC0920B8334C004ACAFF /* Base */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + BA87DBD020B80FFE004ACAFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + BA87DBD120B80FFE004ACAFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + BA87DBD320B80FFE004ACAFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "ORKParkinsonStudy WatchKit Extension/Supporting Files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy.watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME) WatchKit Extension/Supporting Files/$(PROJECT_NAME)-Bridging-Header.h"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Debug; + }; + BA87DBD420B80FFE004ACAFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_COMPLICATION_NAME = Complication; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "ORKParkinsonStudy WatchKit Extension/Supporting Files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy.watchkitapp.watchkitextension"; + PRODUCT_NAME = "${TARGET_NAME}"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_DIR)/$(PROJECT_NAME) WatchKit Extension/Supporting Files/$(PROJECT_NAME)-Bridging-Header.h"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Release; + }; + BA87DBD720B80FFE004ACAFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + IBSC_MODULE = ORKParkinsonStudy_WatchKit_Extension; + INFOPLIST_FILE = "ORKParkinsonStudy WatchKit App/Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Debug; + }; + BA87DBD820B80FFE004ACAFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ""; + IBSC_MODULE = ORKParkinsonStudy_WatchKit_Extension; + INFOPLIST_FILE = "ORKParkinsonStudy WatchKit App/Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy.watchkitapp"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = watchos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 4; + WATCHOS_DEPLOYMENT_TARGET = 5.0; + }; + name = Release; + }; + BA87DBDB20B80FFE004ACAFF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKParkinsonStudy/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + BA87DBDC20B80FFE004ACAFF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKParkinsonStudy/Supporting Files/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.example.researchkit-samplecode.ORKParkinsonStudy"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + BA87DB9920B80FFB004ACAFF /* Build configuration list for PBXProject "ORKParkinsonStudy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BA87DBD020B80FFE004ACAFF /* Debug */, + BA87DBD120B80FFE004ACAFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BA87DBD220B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy WatchKit Extension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BA87DBD320B80FFE004ACAFF /* Debug */, + BA87DBD420B80FFE004ACAFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BA87DBD620B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy WatchKit App" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BA87DBD720B80FFE004ACAFF /* Debug */, + BA87DBD820B80FFE004ACAFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + BA87DBDA20B80FFE004ACAFF /* Build configuration list for PBXNativeTarget "ORKParkinsonStudy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + BA87DBDB20B80FFE004ACAFF /* Debug */, + BA87DBDC20B80FFE004ACAFF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = BA87DB9620B80FFB004ACAFF /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Complication).xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Complication).xcscheme new file mode 100755 index 0000000..0b16c73 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Complication).xcscheme @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Notification).xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Notification).xcscheme new file mode 100755 index 0000000..95ddc74 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App (Notification).xcscheme @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App.xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App.xcscheme new file mode 100755 index 0000000..2fa3afc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy WatchKit App.xcscheme @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy.xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy.xcscheme new file mode 100755 index 0000000..28a843f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy.xcodeproj/xcshareddata/xcschemes/ORKParkinsonStudy.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/AppDelegate.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/AppDelegate.swift new file mode 100755 index 0000000..c1557e1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/AppDelegate.swift @@ -0,0 +1,71 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.tintColor = Colors.dyskinesiaSymptomGraphColor.color + window?.rootViewController = RootViewController() + window?.makeKeyAndVisible() + + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Base.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Base.lproj/Localizable.strings new file mode 100755 index 0000000..744627a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Base.lproj/Localizable.strings @@ -0,0 +1,77 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// CONSENT + +"CONSENT_DATA" = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam et orci eleifend, pretium sapien vel, mattis est. Vestibulum sit amet blandit leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut tincidunt orci vitae laoreet hendrerit. Morbi blandit commodo vestibulum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque mattis aliquet sapien eu lobortis."; + +"CONSENT_PRIVACY" = "Ut tincidunt orci vitae laoreet hendrerit. Morbi blandit commodo vestibulum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque mattis aliquet sapien eu lobortis."; + + +"CONSENT_DATA_USE" = "Vestibulum dolor augue, porttitor et sapien vitae, dictum eleifend justo. Phasellus nec sollicitudin enim. Nunc vel scelerisque justo, at vehicula eros. Vestibulum tristique felis at quam suscipit, ac blandit nulla volutpat."; +"CONSENT_WITHDRAW" = "Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean sagittis vehicula risus, vehicula gravida purus laoreet at. Morbi euismod tempor urna nec placerat. Vestibulum dolor augue, porttitor et sapien vitae, dictum eleifend justo. Phasellus nec sollicitudin enim. Nunc vel scelerisque justo, at vehicula eros. Vestibulum tristique felis at quam suscipit, ac blandit nulla volutpat."; + +// ONBOARDING + +// ONBOARDING WELCOME + +"ONBOARDING_WELCOME_INTRO_TITLE" = "Welcome"; + +"ONBOARDING_WELCOME_INTRO_DETAIL" = "Welcome to the ResearchKit Example Study. This sample app is an example of how to utilize the ResearchKit modules and views to create a great study.\n\nTo provide the best user experience for your study participants consider only using the necessary steps in the onboarding and consent process. This helps reduce the number of steps required to get into your main application."; + +// ONBOARDING EXPECTATIONS + +"ONBOARDING_WELCOME_EXPECTATIONS_TITLE" = "Study Expectations"; + +"ONBOARDING_WELCOME_EXPECTATIONS_BODY" = "You should expect the following items when participating in the ResearchKit study."; + +"ONBOARDING_WELCOME_EXPECTATIONS_FOREGROUND" = "The study will continue to run on your device even if the study app is not in the foreground."; + +"ONBOARDING_WELCOME_EXPECTATIONS_STUDY_DURATION" = "The study will last for 2-4 weeks."; + +"ONBOARDING_WELCOME_EXPECTATIONS_STUDY_OWNER" = "ResearchKit study data will be sent to the study owner."; + +"ONBOARDING_WELCOME_REQUIREMENTS_TITLE" = "Study Requirements"; + +"ONBOARDING_WELCOME_REQUIREMENTS_BODY" = "In order to participate in this study you must meet the following critera:"; + +"ONBOARDING_WELCOME_REQUIREMENTS_AGE_LIMIT" = "Be over the age of 18"; + +"ONBOARDING_WELCOME_REQUIREMENTS_SIMILAR_STUDY" = "Have not participated in a prior or similar version of this study"; + +"ONBOARDING_WELCOME_REQUIREMENTS_CARRY_IPHONE" = "Carry your iPhone or Apple device around with you regularly"; + +"ONBOARDING_WELCOME_REVIEW_BODY" = "Review the consent agreement and begin the agreement process by entering your first and last name below."; + +"ONBOARDING_WELCOME_REVIEW_CONSENT_AFFIRM" = "Consent to join the ResearchKit Study"; + +"ONBOARDING_WELCOME_REVIEW_COMPLETION_TITLE" = "Success"; + +"ONBOARDING_WELCOME_REVIEW_COMPLETION_BODY" = "Thank you for enrolling in the ResearchKit study.For the best results please stay enrolled in the study for its entire duration."; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/BarGraphChartTableViewCell.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/BarGraphChartTableViewCell.swift new file mode 100755 index 0000000..148a020 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/BarGraphChartTableViewCell.swift @@ -0,0 +1,116 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import UIKit +import ResearchKit + +let padding: CGFloat = 10.0 + +class BarGraphChartTableViewCell: UITableViewCell { + + var graphView: ORKBarGraphChartView + let titleLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + graphView = ORKBarGraphChartView() + super.init(style: style, reuseIdentifier: reuseIdentifier) + self.contentView.addSubview(graphView) + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.font = UIFont.systemFont(ofSize: 25.0, weight: .thin) + titleLabel.textAlignment = .center + self.contentView.addSubview(titleLabel) + setupConstraints() + } + + func setupConstraints() { + graphView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + NSLayoutConstraint(item: titleLabel, + attribute: .top, + relatedBy: .equal, + toItem: self.safeAreaLayoutGuide, + attribute: .top, + multiplier: 1.0, + constant: padding), + NSLayoutConstraint(item: titleLabel, + attribute: .left, + relatedBy: .equal, + toItem: self.safeAreaLayoutGuide, + attribute: .left, + multiplier: 1.0, + constant: padding), + NSLayoutConstraint(item: graphView, + attribute: .top, + relatedBy: .equal, + toItem: titleLabel, + attribute: .bottom, + multiplier: 1.0, + constant: padding), + NSLayoutConstraint(item: graphView, + attribute: .left, + relatedBy: .equal, + toItem: self.safeAreaLayoutGuide, + attribute: .left, + multiplier: 1.0, + constant: padding), + NSLayoutConstraint(item: graphView, + attribute: .right, + relatedBy: .equal, + toItem: self.safeAreaLayoutGuide, + attribute: .right, + multiplier: 1.0, + constant: -padding), + NSLayoutConstraint(item: self, + attribute: .bottom, + relatedBy: .equal, + toItem: graphView.safeAreaLayoutGuide, + attribute: .bottom, + multiplier: 1.0, + constant: padding) + ]) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/ChartDataSources.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/ChartDataSources.swift new file mode 100755 index 0000000..744b42a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/ChartDataSources.swift @@ -0,0 +1,133 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation +import ResearchKit + +class BarGraphDataSource: NSObject, ORKValueStackGraphChartViewDataSource { + + var plotPoints: [[ORKValueStack]]! + var datePoints = [String]() + + + override init() { + super.init() + generatePlotPoints() + } + + func generatePlotPoints() { + + var tremorPoints = [ORKValueStack]() + var dyskinesiaPoints = [ORKValueStack]() + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "hh:mm" + + if let tremorPath = Bundle.main.path(forResource: "tremor", ofType: "json") { + do { + let data = try Data(contentsOf: URL(fileURLWithPath: tremorPath), options: .mappedIfSafe) + let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) + if let tremorData = jsonResult as? [Dictionary] { + + let tremorPerHour = stride(from: 0, to: tremorData.count, by: 60).map { + Array(tremorData[$0..] { + + let dyskinesiaPerHour = stride(from: 0, to: dyskinesiaData.count, by: 60).map { + Array(dyskinesiaData[$0.. Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueStack { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return datePoints[pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, colorForPlotIndex plotIndex: Int) -> UIColor { + return plotIndex == 0 ? Colors.tremorGraphColor.color : Colors.dyskinesiaSymptomGraphColor.color + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/GraphViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/GraphViewController.swift new file mode 100755 index 0000000..a1b038d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Graphs/GraphViewController.swift @@ -0,0 +1,239 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import UIKit +import ResearchKit + +class GraphViewController: UITableViewController { + + let barGraphChartDataSource = BarGraphDataSource() + let barGraphChartIdentifier = "BarGraphChartCell" + var barGraphChartTableViewCell: BarGraphChartTableViewCell! + var chartTableViewCells: [UITableViewCell]! + + override func viewDidLoad() { + super.viewDidLoad() + createGraph() + tableView.backgroundColor = Colors.tableViewBackgroundColor.color + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.navigationController?.navigationBar.barTintColor = Colors.appTintColor.color + } + + func createGraph() { + // ORKBarGraphChartView + barGraphChartTableViewCell = tableView.dequeueReusableCell(withIdentifier: barGraphChartIdentifier) as? BarGraphChartTableViewCell + if barGraphChartTableViewCell == nil { + barGraphChartTableViewCell = BarGraphChartTableViewCell(style: .default, reuseIdentifier: "cell") + } + + barGraphChartTableViewCell.titleLabel.text = "June 4, 2018" + + let barGraphChartView = barGraphChartTableViewCell.graphView + barGraphChartView.dataSource = barGraphChartDataSource + barGraphChartView.tintColor = UIColor.lightGray + barGraphChartView.referenceLineColor = Colors.graphReferenceLinceColor.color + barGraphChartTableViewCell.backgroundColor = Colors.tableViewCellBackgroundColor.color + barGraphChartView.axisColor = Colors.graphReferenceLinceColor.color + barGraphChartView.showsHorizontalReferenceLines = true + barGraphChartView.showsVerticalReferenceLines = true + barGraphChartView.yAxisLabelFactors = [0.0, 0.25, 0.5, 0.75, 1.0] + + chartTableViewCells = [barGraphChartTableViewCell] + tableView.reloadData() + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 280.0 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return chartTableViewCells.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = chartTableViewCells[(indexPath as NSIndexPath).row] + return cell + } + + override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return section == 0 ? (UIDevice.current.orientation == .portrait ? 80.0 : 25.0) : 10.0 + } + + override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + return section == 0 ? LegendSectionHeaderView(legends: [GraphLegend(title: "Tremor", color: Colors.tremorGraphColor.color), GraphLegend(title: "Dyskinesia", color: Colors.dyskinesiaSymptomGraphColor.color)], layout: .horizontal) : nil + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + barGraphChartTableViewCell.graphView.animate(withDuration: 0.5) + } + + override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool { + return false + } + +} + +class GraphLegend: NSObject { + var title: String + var color: UIColor + + init(title: String, color: UIColor) { + self.title = title + self.color = color + super.init() + } +} + +class LegendSectionHeaderView: UIView { + var legends: [GraphLegend] + var axis: NSLayoutConstraint.Axis + var stackView: UIStackView! + + init(legends: [GraphLegend], layout: NSLayoutConstraint.Axis) { + self.legends = legends + self.axis = layout + super.init(frame: .zero) + setupView() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupView() { + if stackView == nil { + stackView = UIStackView() + } + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.axis = axis + stackView.distribution = .fillEqually + addLegends() + self.addSubview(stackView) + NSLayoutConstraint.activate([ + NSLayoutConstraint(item: stackView, + attribute: .top, + relatedBy: .equal, + toItem: self, + attribute: .top, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: stackView, + attribute: .bottom, + relatedBy: .equal, + toItem: self, + attribute: .bottom, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: stackView, + attribute: .left, + relatedBy: .equal, + toItem: self, + attribute: .left, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: stackView, + attribute: .right, + relatedBy: .equal, + toItem: self, + attribute: .right, + multiplier: 1.0, + constant: 0.0) + ]) + } + + func addLegends() { + for legend in legends { + let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 15.0, height: 15.0)) + view.translatesAutoresizingMaskIntoConstraints = false + let colorView = UIView() + colorView.translatesAutoresizingMaskIntoConstraints = false + colorView.backgroundColor = legend.color + let legendLabel = UILabel() + legendLabel.translatesAutoresizingMaskIntoConstraints = false + legendLabel.text = legend.title + legendLabel.textAlignment = .center + + view.addSubview(colorView) + view.addSubview(legendLabel) + + NSLayoutConstraint.activate([ + NSLayoutConstraint(item: legendLabel, + attribute: .centerY, + relatedBy: .equal, + toItem: view, + attribute: .centerY, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: legendLabel, + attribute: .centerX, + relatedBy: .equal, + toItem: view, + attribute: .centerX, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: colorView, + attribute: .centerY, + relatedBy: .equal, + toItem: view, + attribute: .centerY, + multiplier: 1.0, + constant: 0.0), + NSLayoutConstraint(item: colorView, + attribute: .right, + relatedBy: .equal, + toItem: legendLabel, + attribute: .left, + multiplier: 1.0, + constant: -5.0), + NSLayoutConstraint(item: colorView, + attribute: .width, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 1.0, + constant: 10.0), + NSLayoutConstraint(item: colorView, + attribute: .height, + relatedBy: .equal, + toItem: nil, + attribute: .notAnAttribute, + multiplier: 1.0, + constant: 10.0) + ]) + + stackView.addArrangedSubview(view) + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/Header/HeaderView.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/Header/HeaderView.swift new file mode 100755 index 0000000..52832e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/Header/HeaderView.swift @@ -0,0 +1,145 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation +import UIKit + +class HeaderView: UIView { + + var title: String! + var descriptionText: NSAttributedString! + var iconName: String! + var invertColors: Bool! + + let PADDING: CGFloat = 30.0 + let CIRCLEDIM: CGFloat = 60.0 + var nameContainer: UIView! + var iconContainer: UIView! + var bottomLineView: UIView! + + init(title: String, descriptionText: NSAttributedString, iconName: String, invertColors: Bool) { + super.init(frame: .zero) + self.backgroundColor = UIColor.clear + self.title = title + self.descriptionText = descriptionText + self.iconName = iconName + self.invertColors = invertColors + + self.setupNameView() + self.setupIcon() + self.setupConstraints() + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setupNameView() { + self.nameContainer = UIView() + self.nameContainer.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(self.nameContainer) + + let activeLabel = UILabel() + activeLabel.attributedText = self.descriptionText + activeLabel.translatesAutoresizingMaskIntoConstraints = false + activeLabel.textColor = UIColor.white + self.nameContainer.addSubview(activeLabel) + + let nameLabel = UILabel() + nameLabel.text = self.title + nameLabel.textColor = (self.invertColors == true) ? UIColor.white : UIColor.black + nameLabel.translatesAutoresizingMaskIntoConstraints = false + + let largeFont = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .largeTitle) + let boldFont = largeFont.withSymbolicTraits(.traitBold) + nameLabel.font = UIFont(descriptor: boldFont!, size: 0) + self.nameContainer.addSubview(nameLabel) + + activeLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: 3.0).isActive = true + activeLabel.leadingAnchor.constraint(equalTo: self.nameContainer.safeAreaLayoutGuide.leadingAnchor, constant: PADDING).isActive = true + activeLabel.bottomAnchor.constraint(equalTo: self.nameContainer.bottomAnchor, constant: -(PADDING + (CIRCLEDIM / 2) - 15)).isActive = true + + nameLabel.topAnchor.constraint(equalTo: self.nameContainer.topAnchor, constant: PADDING).isActive = true + nameLabel.leadingAnchor.constraint(equalTo: self.nameContainer.safeAreaLayoutGuide.leadingAnchor, constant: PADDING).isActive = true + + bottomLineView = UIView() + bottomLineView.backgroundColor = Colors.tableViewBackgroundColor.color + bottomLineView.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(bottomLineView) + + nameContainer.backgroundColor = invertColors ? UIColor.clear : UIColor.white + } + + func setupIcon() { + self.iconContainer = UIView() + + self.iconContainer.layer.cornerRadius = CIRCLEDIM / 2 + self.iconContainer.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(iconContainer) + + let iconView = UIImageView() + iconView.image = UIImage(named: self.iconName)?.withRenderingMode(.alwaysTemplate) + iconView.contentMode = .scaleAspectFit + iconView.translatesAutoresizingMaskIntoConstraints = false + self.iconContainer.addSubview(iconView) + + let iconPadding: CGFloat = 5.0 + iconView.topAnchor.constraint(equalTo: self.iconContainer.topAnchor, constant: iconPadding).isActive = true + iconView.leadingAnchor.constraint(equalTo: self.iconContainer.leadingAnchor, constant: iconPadding).isActive = true + iconView.trailingAnchor.constraint(equalTo: self.iconContainer.trailingAnchor, constant: -iconPadding).isActive = true + iconView.bottomAnchor.constraint(equalTo: self.iconContainer.bottomAnchor, constant: -iconPadding).isActive = true + iconContainer.backgroundColor = invertColors ? UIColor.white : UIColor.clear + } + + override func tintColorDidChange() { + super.tintColorDidChange() + self.nameContainer.backgroundColor = invertColors ? UIColor.clear: UIColor.white + self.iconContainer.backgroundColor = invertColors ? UIColor.white : UIColor.clear + } + + func setupConstraints() { + + self.nameContainer.topAnchor.constraint(equalTo: self.topAnchor, constant: 20.0).isActive = true + self.nameContainer.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true + self.nameContainer.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true + + self.iconContainer.heightAnchor.constraint(equalToConstant: CIRCLEDIM).isActive = true + self.iconContainer.widthAnchor.constraint(equalToConstant: CIRCLEDIM).isActive = true + self.iconContainer.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: PADDING).isActive = true + self.iconContainer.topAnchor.constraint(equalTo: self.nameContainer.bottomAnchor, constant: -(CIRCLEDIM / 2)).isActive = true + self.iconContainer.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0).isActive = true + + bottomLineView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true + bottomLineView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true + bottomLineView.topAnchor.constraint(equalTo: self.nameContainer.bottomAnchor).isActive = true + bottomLineView.bottomAnchor.constraint(equalTo: self.iconContainer.bottomAnchor).isActive = true + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/RootViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/RootViewController.swift new file mode 100755 index 0000000..9a083f2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Main/RootViewController.swift @@ -0,0 +1,99 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import UIKit + +class RootViewController: UIViewController, OnboardingManagerDelegate { + + override func viewDidLoad() { + super.viewDidLoad() + self.view.backgroundColor = UIColor.white + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if OnboardingStateManager.shared.getOnboardingCompletedState() == false { + let onboardingViewController = OnboardingViewController(task: nil, taskRun: nil) + onboardingViewController.onboardingManagerDelegate = self + + self.present(onboardingViewController, animated: false, completion: nil) + } else { + self.didCompleteOnboarding() + } + } + + func didCompleteOnboarding() { + + let textAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white] + + let taskListViewController = TaskListViewController() + let taskListNavController = UINavigationController(rootViewController: taskListViewController) + taskListNavController.navigationBar.shadowImage = UIImage() + taskListNavController.navigationBar.setBackgroundImage(UIImage(), for: .default) + taskListNavController.tabBarItem.title = NSLocalizedString("Tasks", comment: "") + taskListNavController.tabBarItem.image = UIImage(named: "surveyTab") + taskListNavController.navigationBar.titleTextAttributes = textAttributes + + let graphViewController = GraphViewController(style: .grouped) + graphViewController.title = "Graphs" + let graphNavigationController = UINavigationController(rootViewController: graphViewController) + + graphNavigationController.view.backgroundColor = Colors.tableViewBackgroundColor.color + graphNavigationController.navigationBar.prefersLargeTitles = true + graphNavigationController.navigationBar.barTintColor = Colors.appTintColor.color + graphNavigationController.tabBarItem.title = NSLocalizedString("Graphs", comment: "") + graphNavigationController.tabBarItem.image = UIImage(named: "graphTab") + graphNavigationController.navigationBar.titleTextAttributes = textAttributes + graphNavigationController.navigationBar.largeTitleTextAttributes = textAttributes + + let tabBarController = UITabBarController() + tabBarController.viewControllers = [taskListNavController, graphNavigationController] + tabBarController.tabBar.barTintColor = Colors.tableViewCellBackgroundColor.color + tabBarController.tabBar.tintColor = Colors.dyskinesiaSymptomGraphColor.color + self.present(tabBarController, animated: true, completion: nil) + } +} + +public extension UIImage { + public convenience init?(color: UIColor) { + let rect = CGRect(origin: .zero, size: CGSize(width: 1, height: 1)) + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) + color.setFill() + UIRectFill(rect) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + guard let cgImage = image?.cgImage else { return nil } + self.init(cgImage: cgImage) + } +} + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/ConsentDocument.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/ConsentDocument.swift new file mode 100755 index 0000000..8c7e11d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/ConsentDocument.swift @@ -0,0 +1,106 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation +import ResearchKit + +class ConsentDocument: ORKConsentDocument { + let consentText = [ + NSLocalizedString("CONSENT_DATA", comment: ""), + NSLocalizedString("CONSENT_PRIVACY", comment: ""), + NSLocalizedString("CONSENT_DATA_USE", comment: ""), + NSLocalizedString("CONSENT_WITHDRAW", comment: "") + ] + + override init() { + super.init() + + title = "ResearchKit Study" + + let sectionTypes: [ORKConsentSectionType] = [ + .dataGathering, + .privacy, + .dataUse, + .withdrawing + ] + + sections = [ORKConsentSection]() + + for index in sectionTypes.indices { + let section = ORKConsentSection(type: sectionTypes[index]) + + let localizedText = NSLocalizedString(consentText[index], comment: "") + let localizedSummary = localizedText.components(separatedBy: ".")[0] + "." + + section.summary = localizedSummary + section.content = localizedText + + if sections != nil { + sections!.append(section) + } + } + + let signature = ORKConsentSignature( + forPersonWithTitle: nil, + dateFormatString: nil, + identifier: "ConsentDocumentParticipantSignature" + ) + + signature.title = "Participant Signature" + + addSignature(signature) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension ORKConsentSectionType: CustomStringConvertible { + + public var description: String { + switch self { + case .dataGathering: + return "DataGathering" + + case .privacy: + return "Privacy" + + case .dataUse: + return "DataUse" + + case .withdrawing: + return "Withdrawing" + default: + return "" + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingStateManager.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingStateManager.swift new file mode 100755 index 0000000..07439cc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingStateManager.swift @@ -0,0 +1,48 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation + +class OnboardingStateManager: NSObject { + + static let shared = OnboardingStateManager() + let onboardingCompletedKey = "OnboardingCompletedKey" + + func setOnboardingCompletedState(state: Bool) { + let defaults = UserDefaults.standard + defaults.set(state, forKey: onboardingCompletedKey) + } + + func getOnboardingCompletedState() -> Bool { + let defaults = UserDefaults.standard + return defaults.bool(forKey: onboardingCompletedKey) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingViewController.swift new file mode 100755 index 0000000..abb1e98 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Onboarding/OnboardingViewController.swift @@ -0,0 +1,176 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation +import ResearchKit + +protocol OnboardingManagerDelegate: class { + func didCompleteOnboarding() +} + +class OnboardingViewController: ORKTaskViewController, ORKTaskViewControllerDelegate { + + weak var onboardingManagerDelegate: OnboardingManagerDelegate? + + override init(task: ORKTask?, taskRun taskRunUUID: UUID?) { + super.init(task: task, taskRun: taskRunUUID) + self.task = getTasks() + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + self.delegate = self + } + + func getTasks() -> ORKNavigableOrderedTask { + + // Welcome View Controller + let welcomeStep = ORKInstructionStep(identifier: "welcomeStepIdentifier") + welcomeStep.title = NSLocalizedString("ONBOARDING_WELCOME_INTRO_TITLE", comment: "") + welcomeStep.detailText = NSLocalizedString("ONBOARDING_WELCOME_INTRO_DETAIL", comment: "") + welcomeStep.iconImage = UIImage(named: "graph")!.withRenderingMode(.alwaysTemplate) + + // What to Expect + let whatToExpectStep = ORKTableStep(identifier: "whatToExpectStep") + whatToExpectStep.title = NSLocalizedString("ONBOARDING_WELCOME_EXPECTATIONS_TITLE", comment: "") + whatToExpectStep.text = NSLocalizedString("ONBOARDING_WELCOME_EXPECTATIONS_BODY", comment: "") + whatToExpectStep.items = [ + NSLocalizedString("ONBOARDING_WELCOME_EXPECTATIONS_FOREGROUND", comment: "") as NSString, + NSLocalizedString("ONBOARDING_WELCOME_EXPECTATIONS_STUDY_DURATION", comment: "") as NSString, + NSLocalizedString("ONBOARDING_WELCOME_EXPECTATIONS_STUDY_OWNER", comment: "") as NSString + ] + whatToExpectStep.bulletIconNames = ["phone", "calendar", "share"] + whatToExpectStep.bulletType = .circle + + // Requirements + let requirementsStep = ORKTableStep(identifier: "requirementsStep") + requirementsStep.title = NSLocalizedString("ONBOARDING_WELCOME_REQUIREMENTS_TITLE", comment: "") + requirementsStep.text = NSLocalizedString("ONBOARDING_WELCOME_REQUIREMENTS_BODY", comment: "") + requirementsStep.items = [ + NSLocalizedString("ONBOARDING_WELCOME_REQUIREMENTS_AGE_LIMIT", comment: "") as NSString, + NSLocalizedString("ONBOARDING_WELCOME_REQUIREMENTS_SIMILAR_STUDY", comment: "") as NSString, + NSLocalizedString("ONBOARDING_WELCOME_REQUIREMENTS_CARRY_IPHONE", comment: "") as NSString + ] + requirementsStep.isBulleted = true + + // Consent document including data gathering + let consentDoc = ConsentDocument() + let consentStep = ORKVisualConsentStep(identifier: "consentStep", document: consentDoc) + + // Review step + let signature = consentDoc.signatures!.first! + let reviewStep = ORKConsentReviewStep(identifier: "reviewStep", signature: signature, in: consentDoc) + reviewStep.text = NSLocalizedString("ONBOARDING_WELCOME_REVIEW_BODY", comment: "") + reviewStep.reasonForConsent = NSLocalizedString( + "ONBOARDING_WELCOME_REVIEW_CONSENT_AFFIRM", comment: "" + ) + + // Completion + let completionStep = ORKCompletionStep(identifier: "CompletionStep") + completionStep.title = NSLocalizedString("ONBOARDING_WELCOME_REVIEW_COMPLETION_TITLE", comment: "") + completionStep.text = NSLocalizedString("ONBOARDING_WELCOME_REVIEW_COMPLETION_BODY", comment: "") + + // Create task and present it + let task = ORKNavigableOrderedTask( + identifier: "JoinTask", steps: [ + welcomeStep, + whatToExpectStep, + requirementsStep, + consentStep, + reviewStep, + completionStep + ] + ) + + return task + } + + func signatureResult(taskViewController: ORKTaskViewController) -> ORKConsentSignatureResult? { + + let taskResults: [ORKResult]? = taskViewController.result.results + let reviewStepResult = taskResults?.first(where: { (result) -> Bool in + result.identifier == "reviewStep" + }) + let reviewStepResults = (reviewStepResult as? ORKStepResult)?.results + let signatureResult = reviewStepResults?.first as? ORKConsentSignatureResult + + return signatureResult + + } + + func taskViewController(_ taskViewController: ORKTaskViewController, didChange result: ORKTaskResult) { + + // If there is a signature result, and no consent, exit onboarding. + if + let signatureResult = signatureResult(taskViewController: taskViewController), + signatureResult.consented == false { + + self.presentingViewController?.dismiss(animated: false, completion: nil) + + } + + } + + public func taskViewController( + _ taskViewController: ORKTaskViewController, + didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + + switch reason { + case .discarded, .failed, .saved: + + self.presentingViewController?.dismiss(animated: false, completion: nil) + + case .completed: + + OnboardingStateManager.shared.setOnboardingCompletedState(state: true) + + // Access the first and last name from the review step + + if + let signatureResult = signatureResult(taskViewController: taskViewController), + let signature = signatureResult.signature { + + let defaults = UserDefaults.standard + defaults.set(signature.givenName, forKey: "firstName") + defaults.set(signature.familyName, forKey: "lastName") + + } + + self.presentingViewController?.dismiss(animated: true, completion: nil) + + } + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Presenting Tasks/TaskListViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Presenting Tasks/TaskListViewController.swift new file mode 100755 index 0000000..c50e60a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Presenting Tasks/TaskListViewController.swift @@ -0,0 +1,249 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import Foundation +import UIKit +import ResearchKit + +enum TaskListViewTableSections: Int { + case surveys = 0 + case activeTasks + case count + + func title() -> String { + switch self { + case .surveys: + return "Surveys" + case .activeTasks: + return "Active Tasks" + default: + return "" + } + } +} + +class TaskListViewController: UIViewController { + + var tableView: UITableView! + var headerView: HeaderView! + + override func viewDidLoad() { + super.viewDidLoad() + self.view.backgroundColor = Colors.appTintColor.color + setupHeader() + setupTableView() + setupConstraints() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.view.backgroundColor = Colors.appTintColor.color + } + + func setupTableView() { + tableView = UITableView(frame: .zero, style: .grouped) + tableView.delegate = self + tableView.dataSource = self + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "tableCell") + tableView.tableFooterView = UIView() + tableView.rowHeight = UITableView.automaticDimension + tableView.estimatedRowHeight = 100.0 + tableView.translatesAutoresizingMaskIntoConstraints = false + tableView.backgroundColor = Colors.tableViewBackgroundColor.color + view.addSubview(tableView) + } + + func setupHeader() { + + let attributedDescription = NSMutableAttributedString(string: "Powered by ResearchKit", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0, weight: .light)]) + attributedDescription.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 16.0, weight: .bold), range: NSRange(location: 11, length: 11)) + + headerView = HeaderView(title: "Parkinson's Study", descriptionText: attributedDescription, iconName: "CheckMark", invertColors: true) + headerView.translatesAutoresizingMaskIntoConstraints = false + self.view.addSubview(headerView) + } + + func setupConstraints() { + headerView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: -20.0).isActive = true + headerView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true + headerView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true + + tableView.topAnchor.constraint(equalTo: self.headerView.bottomAnchor).isActive = true + tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true + tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true + tableView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor).isActive = true + } +} + +extension TaskListViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + var cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) + + switch indexPath.section { + case TaskListViewTableSections.surveys.rawValue: + if indexPath.row == 0 { + cell = StudyTableCell(text: "Activities of Daily Life", iconName: "heartbeat", style: .default, reuseIdentifier: "tableCell") + } else if indexPath.row == 1 { + cell = StudyTableCell(text: "Basic Survey", iconName: "timer", style: .default, reuseIdentifier: "tableCell") + } + case TaskListViewTableSections.activeTasks.rawValue: + if indexPath.row == 0 { + cell = StudyTableCell(text: "6-Minute Walk", iconName: "walkingman", style: .default, reuseIdentifier: "tableCell") + } else if indexPath.row == 1 { + cell = StudyTableCell(text: "Spatial Span Memory", iconName: "memory-second-screen", style: .default, reuseIdentifier: "tableCell") + } else if indexPath.row == 2 { + cell = StudyTableCell(text: "Speech Recognition", iconName: "audioGraph", style: .default, reuseIdentifier: "tableCell") + } + default: + break + } + cell.backgroundColor = Colors.tableViewCellBackgroundColor.color + cell.accessoryType = .disclosureIndicator + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + var task: ORKOrderedTask? + + switch indexPath.section { + case TaskListViewTableSections.surveys.rawValue: + if indexPath.row == 0 { + let overallHealthAnswerFormat = ORKAnswerFormat.scale(withMaximumValue: 10, minimumValue: 1, defaultValue: NSIntegerMax, step: 1, vertical: false, maximumValueDescription: "Perfect Health", minimumValueDescription: "Very Poor") + + let overallHealthQStep = ORKQuestionStep(identifier: "OverallHealthQuestion", title: "ADL", question: "How would you rate your overall health?", answer: overallHealthAnswerFormat) + task = ORKOrderedTask(identifier: "task", steps: [overallHealthQStep]) + } else if indexPath.row == 1 { + let significantEventAnswerFormat = ORKBooleanAnswerFormat(yesString: "Yes", noString: "No") + let significantEventQStep = ORKQuestionStep(identifier: "significantEventQuestion", title: "Basic Survey", question: "Have you experienced any falls or significant events that have limited your mobility in the past three months?", answer: significantEventAnswerFormat) + + let nonmotorSymptomsAnswerFormat = ORKTextChoiceAnswerFormat(style: .multipleChoice, textChoices: [ORKTextChoice(text: "Pain", value: 1 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Fatigue", value: 2 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Cognitive impairments", value: 3 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Digestive or Bowel issues", value: 4 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Gait Impairments", value: 5 as NSCoding & NSCopying & NSObjectProtocol), ORKTextChoice(text: "Other", value: 6 as NSCoding & NSCopying & NSObjectProtocol)]) + + let nonmotorSymptomsQStep = ORKQuestionStep(identifier: "nonmotorSymptomsQuestion", title: "Basic Survey", question: "Which of the following non-motor symptoms do you feel", answer: nonmotorSymptomsAnswerFormat) + task = ORKOrderedTask(identifier: "task", steps: [significantEventQStep, nonmotorSymptomsQStep]) + } + case TaskListViewTableSections.activeTasks.rawValue: + if indexPath.row == 0 { + task = ORKOrderedTask.fitnessCheck(withIdentifier: "sixMinuteWalk", intendedUseDescription: "", walkDuration: 6 * 60, restDuration: 2 * 60, options: []) + } else if indexPath.row == 1 { + task = ORKOrderedTask.spatialSpanMemoryTask(withIdentifier: String(describing: "spatialSpan"), intendedUseDescription: "", initialSpan: 3, minimumSpan: 2, maximumSpan: 15, playSpeed: 1.0, maximumTests: 5, maximumConsecutiveFailures: 3, customTargetImage: nil, customTargetPluralName: nil, requireReversal: false, options: []) + break + } else if indexPath.row == 2 { + task = ORKOrderedTask.speechRecognitionTask(withIdentifier: "speechRecognition", intendedUseDescription: "", speechRecognizerLocale: .englishUS, speechRecognitionImage: nil, speechRecognitionText: "A quick brown fox jumps over the lazy dog.", shouldHideTranscript: true, allowsEdittingTranscript: true, options: []) + break + } + default: + break + } + + if task != nil { + let taskViewController = ORKTaskViewController(task: task, taskRun: nil) + taskViewController.delegate = self + + // Assign a directory to store `taskViewController` output. + taskViewController.outputDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + self.present(taskViewController, animated: true, completion: nil) + } + } + + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + return TaskListViewTableSections(rawValue: section)?.title() + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch section { + case TaskListViewTableSections.surveys.rawValue: + return 2 + case TaskListViewTableSections.activeTasks.rawValue: + return 3 + default: + break + } + + return 0 + } + + func numberOfSections(in tableView: UITableView) -> Int { + return TaskListViewTableSections.count.rawValue + } +} + +extension TaskListViewController: ORKTaskViewControllerDelegate { + + public func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + switch reason { + case .completed, .discarded, .failed, .saved: + self.dismiss(animated: false, completion: nil) + } + } +} + +class StudyTableCell: UITableViewCell { + + init(text: String, iconName: String, style: UITableViewCell.CellStyle, reuseIdentifier: String) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + let PADDING: CGFloat = 25.0 + let titleLabel = UILabel() + titleLabel.text = text + titleLabel.textColor = Colors.tableCellTextColor.color + titleLabel.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(titleLabel) + + let imageView = UIImageView() + let bundle = Bundle(for: ORKOrderedTask.self) + let image = UIImage(named: iconName, in: bundle, compatibleWith: nil)?.withRenderingMode(.alwaysTemplate) + imageView.image = image + imageView.contentMode = .scaleAspectFit + imageView.translatesAutoresizingMaskIntoConstraints = false + self.addSubview(imageView) + + imageView.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: PADDING).isActive = true + imageView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true + imageView.heightAnchor.constraint(equalToConstant: 25.0).isActive = true + imageView.widthAnchor.constraint(equalToConstant: 25.0).isActive = true + + if image != nil { + titleLabel.leadingAnchor.constraint(equalTo: imageView.trailingAnchor, constant: 10.0).isActive = true + } else { + titleLabel.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: PADDING).isActive = true + } + + titleLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: PADDING).isActive = true + titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -PADDING).isActive = true + titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -PADDING).isActive = true + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..d8db8d6 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/CheckMark.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/CheckMark.png new file mode 100755 index 0000000..b00c651 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/CheckMark.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/Contents.json new file mode 100755 index 0000000..76701b8 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/CheckMark.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "CheckMark.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage-2.launchimage/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage-2.launchimage/Contents.json new file mode 100755 index 0000000..5a29666 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage-2.launchimage/Contents.json @@ -0,0 +1,49 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage.launchimage/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage.launchimage/Contents.json new file mode 100755 index 0000000..5a29666 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,49 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "minimum-system-version" : "7.0", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "minimum-system-version" : "7.0", + "extent" : "full-screen", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/Contents.json new file mode 100755 index 0000000..3a7a426 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "calendar.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/calendar.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/calendar.png new file mode 100755 index 0000000..31b15ac Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/calendar.imageset/calendar.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/Contents.json new file mode 100755 index 0000000..17a3c46 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "check.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/check.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/check.png new file mode 100755 index 0000000..f39b721 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/check.imageset/check.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/Contents.json new file mode 100755 index 0000000..6b700b7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "checkMarkStroke.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/checkMarkStroke.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/checkMarkStroke.png new file mode 100755 index 0000000..0a1469b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/checkMarkStroke.imageset/checkMarkStroke.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/Contents.json new file mode 100755 index 0000000..14fe2f2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "graph@3x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/graph@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/graph@3x.png new file mode 100755 index 0000000..656ca7d Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graph.imageset/graph@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/Contents.json new file mode 100755 index 0000000..f0fcda2 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "third.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/third.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/third.pdf new file mode 100755 index 0000000..35ad553 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/graphTab.imageset/third.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/Contents.json new file mode 100755 index 0000000..eb34271 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "phone.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/phone.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/phone.png new file mode 100755 index 0000000..c89a2e0 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/phone.imageset/phone.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/Contents.json new file mode 100755 index 0000000..0d1507f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "share.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/share.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/share.png new file mode 100755 index 0000000..ff54b5f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/share.imageset/share.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/Contents.json new file mode 100755 index 0000000..33a7451 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "first.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/first.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/first.pdf new file mode 100755 index 0000000..e9ebbe6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Assets.xcassets/surveyTab.imageset/first.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/LaunchScreen.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..bfa3612 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/Main.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/Main.storyboard new file mode 100755 index 0000000..2cfb56c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Base.lproj/Main.storyboard @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Colors.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Colors.swift new file mode 100755 index 0000000..0e35b2f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Colors.swift @@ -0,0 +1,89 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +import UIKit + +enum Colors { + + private func tremorGraphColor() -> UIColor { + return UIColor(red: 158.0 / 255.0, green: 130.0 / 255.0, blue: 231.0 / 255.0, alpha: 1.0) + } + + private func dyskinesiaGraphColor() -> UIColor { + return UIColor(red: 91.0 / 255.0, green: 162.0 / 255.0, blue: 234.0 / 255.0, alpha: 1.0) + } + + case appTintColor, tableViewCellBackgroundColor, graphReferenceLinceColor, tableViewBackgroundColor, tableCellTextColor, tableCellLineColor, tremorGraphColor, dyskinesiaSymptomGraphColor + + var color: UIColor { + switch self { + + case .appTintColor: + + let backgroundGradientLayer = CAGradientLayer() + backgroundGradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.size.width, height: 1000.0) + + let cgColors = [dyskinesiaGraphColor().cgColor, tremorGraphColor().cgColor] + + backgroundGradientLayer.colors = cgColors + backgroundGradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5) + backgroundGradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5) + UIGraphicsBeginImageContext(backgroundGradientLayer.bounds.size) + backgroundGradientLayer.render(in: UIGraphicsGetCurrentContext()!) + let backgroundColorImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return UIColor(patternImage: backgroundColorImage!) + + case .tableViewCellBackgroundColor: + return UIColor.white + + case .graphReferenceLinceColor: + return UIColor(red: 226.0 / 255.0, green: 226.0 / 255.0, blue: 226.0 / 255.0, alpha: 1.0) + + case .tableViewBackgroundColor: + return UIColor(red: 245.0 / 255.0, green: 246.0 / 255.0, blue: 248.0 / 255.0, alpha: 1.0) + + case .tableCellTextColor: + return UIColor(red: 142.0 / 255.0, green: 141.0 / 255.0, blue: 147.0 / 255.0, alpha: 1.0) + + case .tableCellLineColor: + return UIColor(red: 214.0 / 255.0, green: 214.0 / 255.0, blue: 214.0 / 255.0, alpha: 1.0) + + case .tremorGraphColor: + return tremorGraphColor() + + case .dyskinesiaSymptomGraphColor: + return dyskinesiaGraphColor() + } + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Info.plist new file mode 100755 index 0000000..64a86ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIcons + + CFBundleIcons~ipad + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSHealthShareUsageDescription + This app reads your HealthKit data during certain tasks. + NSMicrophoneUsageDescription + This app uses microphone to record sound + NSSpeechRecognitionUsageDescription + This app uses speech recognition for certain tasks + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/dyskinesia.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/dyskinesia.json new file mode 100755 index 0000000..bbe97a3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/dyskinesia.json @@ -0,0 +1 @@ +[{"startDate":"549986400","endDate":"549986460","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986460","endDate":"549986520","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986520","endDate":"549986580","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986580","endDate":"549986640","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986640","endDate":"549986700","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986700","endDate":"549986760","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986760","endDate":"549986820","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986820","endDate":"549986880","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986880","endDate":"549986940","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549986940","endDate":"549987000","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987000","endDate":"549987060","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987060","endDate":"549987120","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987120","endDate":"549987180","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987180","endDate":"549987240","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987240","endDate":"549987300","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987300","endDate":"549987360","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987360","endDate":"549987420","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987420","endDate":"549987480","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987480","endDate":"549987540","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987540","endDate":"549987600","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987600","endDate":"549987660","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987660","endDate":"549987720","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987720","endDate":"549987780","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987780","endDate":"549987840","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987840","endDate":"549987900","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987900","endDate":"549987960","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549987960","endDate":"549988020","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988020","endDate":"549988080","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988080","endDate":"549988140","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988140","endDate":"549988200","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988200","endDate":"549988260","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988260","endDate":"549988320","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988320","endDate":"549988380","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988380","endDate":"549988440","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988440","endDate":"549988500","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988500","endDate":"549988560","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988560","endDate":"549988620","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988620","endDate":"549988680","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988680","endDate":"549988740","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988740","endDate":"549988800","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988800","endDate":"549988860","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988860","endDate":"549988920","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988920","endDate":"549988980","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549988980","endDate":"549989040","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989040","endDate":"549989100","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989100","endDate":"549989160","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989160","endDate":"549989220","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989220","endDate":"549989280","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989280","endDate":"549989340","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989340","endDate":"549989400","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989400","endDate":"549989460","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989460","endDate":"549989520","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989520","endDate":"549989580","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989580","endDate":"549989640","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989640","endDate":"549989700","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989700","endDate":"549989760","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989760","endDate":"549989820","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989820","endDate":"549989880","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989880","endDate":"549989940","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549989940","endDate":"549990000","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990000","endDate":"549990060","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990060","endDate":"549990120","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990120","endDate":"549990180","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990180","endDate":"549990240","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990240","endDate":"549990300","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990300","endDate":"549990360","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990360","endDate":"549990420","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549990420","endDate":"549990480","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990480","endDate":"549990540","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990540","endDate":"549990600","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990600","endDate":"549990660","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990660","endDate":"549990720","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990720","endDate":"549990780","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990780","endDate":"549990840","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990840","endDate":"549990900","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990900","endDate":"549990960","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549990960","endDate":"549991020","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991020","endDate":"549991080","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991080","endDate":"549991140","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991140","endDate":"549991200","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991200","endDate":"549991260","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991260","endDate":"549991320","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"549991320","endDate":"549991380","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991380","endDate":"549991440","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991440","endDate":"549991500","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991500","endDate":"549991560","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991560","endDate":"549991620","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991620","endDate":"549991680","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991680","endDate":"549991740","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991740","endDate":"549991800","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991800","endDate":"549991860","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991860","endDate":"549991920","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549991920","endDate":"549991980","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549991980","endDate":"549992040","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549992040","endDate":"549992100","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992100","endDate":"549992160","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549992160","endDate":"549992220","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"549992220","endDate":"549992280","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"549992280","endDate":"549992340","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549992340","endDate":"549992400","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"549992400","endDate":"549992460","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549992460","endDate":"549992520","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992520","endDate":"549992580","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549992580","endDate":"549992640","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549992640","endDate":"549992700","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992700","endDate":"549992760","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"549992760","endDate":"549992820","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992820","endDate":"549992880","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992880","endDate":"549992940","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549992940","endDate":"549993000","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549993000","endDate":"549993060","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"549993060","endDate":"549993120","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993120","endDate":"549993180","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993180","endDate":"549993240","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993240","endDate":"549993300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993300","endDate":"549993360","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993360","endDate":"549993420","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993420","endDate":"549993480","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549993480","endDate":"549993540","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"549993540","endDate":"549993600","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993600","endDate":"549993660","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"549993660","endDate":"549993720","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549993720","endDate":"549993780","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549993780","endDate":"549993840","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549993840","endDate":"549993900","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549993900","endDate":"549993960","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549993960","endDate":"549994020","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549994020","endDate":"549994080","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549994080","endDate":"549994140","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994140","endDate":"549994200","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994200","endDate":"549994260","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549994260","endDate":"549994320","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994320","endDate":"549994380","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994380","endDate":"549994440","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549994440","endDate":"549994500","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549994500","endDate":"549994560","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549994560","endDate":"549994620","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994620","endDate":"549994680","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549994680","endDate":"549994740","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994740","endDate":"549994800","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994800","endDate":"549994860","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994860","endDate":"549994920","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549994920","endDate":"549994980","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549994980","endDate":"549995040","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995040","endDate":"549995100","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549995100","endDate":"549995160","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549995160","endDate":"549995220","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995220","endDate":"549995280","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995280","endDate":"549995340","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995340","endDate":"549995400","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995400","endDate":"549995460","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995460","endDate":"549995520","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549995520","endDate":"549995580","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549995580","endDate":"549995640","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995640","endDate":"549995700","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549995700","endDate":"549995760","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549995760","endDate":"549995820","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995820","endDate":"549995880","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549995880","endDate":"549995940","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549995940","endDate":"549996000","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996000","endDate":"549996060","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996060","endDate":"549996120","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996120","endDate":"549996180","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996180","endDate":"549996240","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996240","endDate":"549996300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549996300","endDate":"549996360","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996360","endDate":"549996420","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"549996420","endDate":"549996480","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996480","endDate":"549996540","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996540","endDate":"549996600","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996600","endDate":"549996660","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996660","endDate":"549996720","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996720","endDate":"549996780","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996780","endDate":"549996840","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549996840","endDate":"549996900","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996900","endDate":"549996960","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549996960","endDate":"549997020","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997020","endDate":"549997080","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997080","endDate":"549997140","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997140","endDate":"549997200","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997200","endDate":"549997260","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"549997260","endDate":"549997320","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997320","endDate":"549997380","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997380","endDate":"549997440","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997440","endDate":"549997500","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997500","endDate":"549997560","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997560","endDate":"549997620","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997620","endDate":"549997680","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997680","endDate":"549997740","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997740","endDate":"549997800","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997800","endDate":"549997860","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549997860","endDate":"549997920","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997920","endDate":"549997980","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549997980","endDate":"549998040","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998040","endDate":"549998100","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998100","endDate":"549998160","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998160","endDate":"549998220","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549998220","endDate":"549998280","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549998280","endDate":"549998340","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549998340","endDate":"549998400","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998400","endDate":"549998460","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998460","endDate":"549998520","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998520","endDate":"549998580","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"549998580","endDate":"549998640","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549998640","endDate":"549998700","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998700","endDate":"549998760","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998760","endDate":"549998820","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998820","endDate":"549998880","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549998880","endDate":"549998940","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549998940","endDate":"549999000","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999000","endDate":"549999060","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999060","endDate":"549999120","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549999120","endDate":"549999180","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999180","endDate":"549999240","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999240","endDate":"549999300","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999300","endDate":"549999360","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999360","endDate":"549999420","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549999420","endDate":"549999480","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999480","endDate":"549999540","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999540","endDate":"549999600","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999600","endDate":"549999660","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549999660","endDate":"549999720","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549999720","endDate":"549999780","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999780","endDate":"549999840","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"549999840","endDate":"549999900","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999900","endDate":"549999960","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"549999960","endDate":"550000020","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000020","endDate":"550000080","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000080","endDate":"550000140","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000140","endDate":"550000200","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550000200","endDate":"550000260","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550000260","endDate":"550000320","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000320","endDate":"550000380","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"550000380","endDate":"550000440","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000440","endDate":"550000500","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550000500","endDate":"550000560","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"550000560","endDate":"550000620","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550000620","endDate":"550000680","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"550000680","endDate":"550000740","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000740","endDate":"550000800","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550000800","endDate":"550000860","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550000860","endDate":"550000920","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550000920","endDate":"550000980","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550000980","endDate":"550001040","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550001040","endDate":"550001100","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001100","endDate":"550001160","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001160","endDate":"550001220","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001220","endDate":"550001280","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550001280","endDate":"550001340","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001340","endDate":"550001400","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001400","endDate":"550001460","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001460","endDate":"550001520","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001520","endDate":"550001580","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001580","endDate":"550001640","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550001640","endDate":"550001700","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001700","endDate":"550001760","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001760","endDate":"550001820","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001820","endDate":"550001880","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550001880","endDate":"550001940","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550001940","endDate":"550002000","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002000","endDate":"550002060","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550002060","endDate":"550002120","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002120","endDate":"550002180","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002180","endDate":"550002240","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550002240","endDate":"550002300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002300","endDate":"550002360","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550002360","endDate":"550002420","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550002420","endDate":"550002480","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550002480","endDate":"550002540","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002540","endDate":"550002600","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002600","endDate":"550002660","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002660","endDate":"550002720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002720","endDate":"550002780","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550002780","endDate":"550002840","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550002840","endDate":"550002900","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550002900","endDate":"550002960","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550002960","endDate":"550003020","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550003020","endDate":"550003080","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550003080","endDate":"550003140","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550003140","endDate":"550003200","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550003200","endDate":"550003260","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550003260","endDate":"550003320","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550003320","endDate":"550003380","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003380","endDate":"550003440","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003440","endDate":"550003500","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550003500","endDate":"550003560","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003560","endDate":"550003620","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003620","endDate":"550003680","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550003680","endDate":"550003740","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003740","endDate":"550003800","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550003800","endDate":"550003860","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550003860","endDate":"550003920","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550003920","endDate":"550003980","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550003980","endDate":"550004040","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004040","endDate":"550004100","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550004100","endDate":"550004160","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004160","endDate":"550004220","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004220","endDate":"550004280","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550004280","endDate":"550004340","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550004340","endDate":"550004400","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004400","endDate":"550004460","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004460","endDate":"550004520","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004520","endDate":"550004580","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004580","endDate":"550004640","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004640","endDate":"550004700","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004700","endDate":"550004760","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004760","endDate":"550004820","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004820","endDate":"550004880","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004880","endDate":"550004940","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550004940","endDate":"550005000","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005000","endDate":"550005060","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005060","endDate":"550005120","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550005120","endDate":"550005180","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550005180","endDate":"550005240","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005240","endDate":"550005300","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005300","endDate":"550005360","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005360","endDate":"550005420","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005420","endDate":"550005480","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550005480","endDate":"550005540","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005540","endDate":"550005600","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005600","endDate":"550005660","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005660","endDate":"550005720","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005720","endDate":"550005780","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005780","endDate":"550005840","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005840","endDate":"550005900","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005900","endDate":"550005960","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550005960","endDate":"550006020","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006020","endDate":"550006080","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006080","endDate":"550006140","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550006140","endDate":"550006200","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006200","endDate":"550006260","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006260","endDate":"550006320","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006320","endDate":"550006380","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006380","endDate":"550006440","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006440","endDate":"550006500","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550006500","endDate":"550006560","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550006560","endDate":"550006620","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006620","endDate":"550006680","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550006680","endDate":"550006740","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550006740","endDate":"550006800","percentOffWrist":0,"percentLikely":0,"percentUnlikely":1},{"startDate":"550006800","endDate":"550006860","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550006860","endDate":"550006920","percentOffWrist":0,"percentLikely":0.021739,"percentUnlikely":0.978261},{"startDate":"550006920","endDate":"550006980","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550006980","endDate":"550007040","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007040","endDate":"550007100","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007100","endDate":"550007160","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007160","endDate":"550007220","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007220","endDate":"550007280","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007280","endDate":"550007340","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007340","endDate":"550007400","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007400","endDate":"550007460","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550007460","endDate":"550007520","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007520","endDate":"550007580","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550007580","endDate":"550007640","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550007640","endDate":"550007700","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550007700","endDate":"550007760","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550007760","endDate":"550007820","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550007820","endDate":"550007880","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550007880","endDate":"550007940","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550007940","endDate":"550008000","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550008000","endDate":"550008060","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008060","endDate":"550008120","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550008120","endDate":"550008180","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008180","endDate":"550008240","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550008240","endDate":"550008300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008300","endDate":"550008360","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008360","endDate":"550008420","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008420","endDate":"550008480","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008480","endDate":"550008540","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008540","endDate":"550008600","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008600","endDate":"550008660","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008660","endDate":"550008720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008720","endDate":"550008780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008780","endDate":"550008840","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550008840","endDate":"550008900","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008900","endDate":"550008960","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550008960","endDate":"550009020","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550009020","endDate":"550009080","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550009080","endDate":"550009140","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550009140","endDate":"550009200","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550009200","endDate":"550009260","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550009260","endDate":"550009320","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009320","endDate":"550009380","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550009380","endDate":"550009440","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550009440","endDate":"550009500","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009500","endDate":"550009560","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550009560","endDate":"550009620","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009620","endDate":"550009680","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550009680","endDate":"550009740","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009740","endDate":"550009800","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009800","endDate":"550009860","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009860","endDate":"550009920","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550009920","endDate":"550009980","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550009980","endDate":"550010040","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010040","endDate":"550010100","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010100","endDate":"550010160","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010160","endDate":"550010220","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010220","endDate":"550010280","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010280","endDate":"550010340","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550010340","endDate":"550010400","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010400","endDate":"550010460","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010460","endDate":"550010520","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010520","endDate":"550010580","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010580","endDate":"550010640","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010640","endDate":"550010700","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010700","endDate":"550010760","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010760","endDate":"550010820","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550010820","endDate":"550010880","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010880","endDate":"550010940","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550010940","endDate":"550011000","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550011000","endDate":"550011060","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011060","endDate":"550011120","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011120","endDate":"550011180","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550011180","endDate":"550011240","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550011240","endDate":"550011300","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011300","endDate":"550011360","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"550011360","endDate":"550011420","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011420","endDate":"550011480","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011480","endDate":"550011540","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011540","endDate":"550011600","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011600","endDate":"550011660","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011660","endDate":"550011720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550011720","endDate":"550011780","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550011780","endDate":"550011840","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011840","endDate":"550011900","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550011900","endDate":"550011960","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550011960","endDate":"550012020","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012020","endDate":"550012080","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012080","endDate":"550012140","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012140","endDate":"550012200","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012200","endDate":"550012260","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012260","endDate":"550012320","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012320","endDate":"550012380","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012380","endDate":"550012440","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012440","endDate":"550012500","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012500","endDate":"550012560","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012560","endDate":"550012620","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012620","endDate":"550012680","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012680","endDate":"550012740","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012740","endDate":"550012800","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012800","endDate":"550012860","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012860","endDate":"550012920","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550012920","endDate":"550012980","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550012980","endDate":"550013040","percentOffWrist":0,"percentLikely":0.173913,"percentUnlikely":0.826087},{"startDate":"550013040","endDate":"550013100","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013100","endDate":"550013160","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013160","endDate":"550013220","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013220","endDate":"550013280","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013280","endDate":"550013340","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550013340","endDate":"550013400","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013400","endDate":"550013460","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013460","endDate":"550013520","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013520","endDate":"550013580","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013580","endDate":"550013640","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013640","endDate":"550013700","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550013700","endDate":"550013760","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550013760","endDate":"550013820","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550013820","endDate":"550013880","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550013880","endDate":"550013940","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550013940","endDate":"550014000","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550014000","endDate":"550014060","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550014060","endDate":"550014120","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014120","endDate":"550014180","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550014180","endDate":"550014240","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550014240","endDate":"550014300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014300","endDate":"550014360","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550014360","endDate":"550014420","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014420","endDate":"550014480","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550014480","endDate":"550014540","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550014540","endDate":"550014600","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014600","endDate":"550014660","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014660","endDate":"550014720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014720","endDate":"550014780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014780","endDate":"550014840","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014840","endDate":"550014900","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014900","endDate":"550014960","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550014960","endDate":"550015020","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015020","endDate":"550015080","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015080","endDate":"550015140","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550015140","endDate":"550015200","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550015200","endDate":"550015260","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015260","endDate":"550015320","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550015320","endDate":"550015380","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550015380","endDate":"550015440","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550015440","endDate":"550015500","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550015500","endDate":"550015560","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550015560","endDate":"550015620","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550015620","endDate":"550015680","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550015680","endDate":"550015740","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015740","endDate":"550015800","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015800","endDate":"550015860","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550015860","endDate":"550015920","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550015920","endDate":"550015980","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550015980","endDate":"550016040","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016040","endDate":"550016100","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550016100","endDate":"550016160","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550016160","endDate":"550016220","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550016220","endDate":"550016280","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550016280","endDate":"550016340","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550016340","endDate":"550016400","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550016400","endDate":"550016460","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016460","endDate":"550016520","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550016520","endDate":"550016580","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016580","endDate":"550016640","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016640","endDate":"550016700","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550016700","endDate":"550016760","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016760","endDate":"550016820","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550016820","endDate":"550016880","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550016880","endDate":"550016940","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550016940","endDate":"550017000","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550017000","endDate":"550017060","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550017060","endDate":"550017120","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550017120","endDate":"550017180","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017180","endDate":"550017240","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017240","endDate":"550017300","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550017300","endDate":"550017360","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017360","endDate":"550017420","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017420","endDate":"550017480","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550017480","endDate":"550017540","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017540","endDate":"550017600","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550017600","endDate":"550017660","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017660","endDate":"550017720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550017720","endDate":"550017780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550017780","endDate":"550017840","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550017840","endDate":"550017900","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550017900","endDate":"550017960","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550017960","endDate":"550018020","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018020","endDate":"550018080","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550018080","endDate":"550018140","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018140","endDate":"550018200","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018200","endDate":"550018260","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550018260","endDate":"550018320","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018320","endDate":"550018380","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018380","endDate":"550018440","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018440","endDate":"550018500","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018500","endDate":"550018560","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018560","endDate":"550018620","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018620","endDate":"550018680","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018680","endDate":"550018740","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550018740","endDate":"550018800","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550018800","endDate":"550018860","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550018860","endDate":"550018920","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550018920","endDate":"550018980","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550018980","endDate":"550019040","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019040","endDate":"550019100","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019100","endDate":"550019160","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019160","endDate":"550019220","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019220","endDate":"550019280","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550019280","endDate":"550019340","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019340","endDate":"550019400","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019400","endDate":"550019460","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019460","endDate":"550019520","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019520","endDate":"550019580","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019580","endDate":"550019640","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550019640","endDate":"550019700","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550019700","endDate":"550019760","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019760","endDate":"550019820","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019820","endDate":"550019880","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550019880","endDate":"550019940","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550019940","endDate":"550020000","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550020000","endDate":"550020060","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550020060","endDate":"550020120","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020120","endDate":"550020180","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550020180","endDate":"550020240","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020240","endDate":"550020300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020300","endDate":"550020360","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550020360","endDate":"550020420","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550020420","endDate":"550020480","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020480","endDate":"550020540","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550020540","endDate":"550020600","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550020600","endDate":"550020660","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550020660","endDate":"550020720","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550020720","endDate":"550020780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020780","endDate":"550020840","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550020840","endDate":"550020900","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020900","endDate":"550020960","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550020960","endDate":"550021020","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021020","endDate":"550021080","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021080","endDate":"550021140","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021140","endDate":"550021200","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021200","endDate":"550021260","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021260","endDate":"550021320","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021320","endDate":"550021380","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021380","endDate":"550021440","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021440","endDate":"550021500","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550021500","endDate":"550021560","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021560","endDate":"550021620","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021620","endDate":"550021680","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550021680","endDate":"550021740","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550021740","endDate":"550021800","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021800","endDate":"550021860","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550021860","endDate":"550021920","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550021920","endDate":"550021980","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550021980","endDate":"550022040","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022040","endDate":"550022100","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550022100","endDate":"550022160","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022160","endDate":"550022220","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022220","endDate":"550022280","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022280","endDate":"550022340","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022340","endDate":"550022400","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022400","endDate":"550022460","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022460","endDate":"550022520","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022520","endDate":"550022580","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550022580","endDate":"550022640","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022640","endDate":"550022700","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022700","endDate":"550022760","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022760","endDate":"550022820","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550022820","endDate":"550022880","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550022880","endDate":"550022940","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550022940","endDate":"550023000","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023000","endDate":"550023060","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023060","endDate":"550023120","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550023120","endDate":"550023180","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550023180","endDate":"550023240","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023240","endDate":"550023300","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550023300","endDate":"550023360","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023360","endDate":"550023420","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023420","endDate":"550023480","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550023480","endDate":"550023540","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023540","endDate":"550023600","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550023600","endDate":"550023660","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550023660","endDate":"550023720","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550023720","endDate":"550023780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023780","endDate":"550023840","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023840","endDate":"550023900","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550023900","endDate":"550023960","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550023960","endDate":"550024020","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024020","endDate":"550024080","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024080","endDate":"550024140","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024140","endDate":"550024200","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024200","endDate":"550024260","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024260","endDate":"550024320","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550024320","endDate":"550024380","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024380","endDate":"550024440","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024440","endDate":"550024500","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550024500","endDate":"550024560","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024560","endDate":"550024620","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024620","endDate":"550024680","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024680","endDate":"550024740","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024740","endDate":"550024800","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550024800","endDate":"550024860","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024860","endDate":"550024920","percentOffWrist":0,"percentLikely":0.043478,"percentUnlikely":0.956522},{"startDate":"550024920","endDate":"550024980","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550024980","endDate":"550025040","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025040","endDate":"550025100","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550025100","endDate":"550025160","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025160","endDate":"550025220","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025220","endDate":"550025280","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025280","endDate":"550025340","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025340","endDate":"550025400","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550025400","endDate":"550025460","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025460","endDate":"550025520","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025520","endDate":"550025580","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550025580","endDate":"550025640","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025640","endDate":"550025700","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550025700","endDate":"550025760","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025760","endDate":"550025820","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025820","endDate":"550025880","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025880","endDate":"550025940","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550025940","endDate":"550026000","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026000","endDate":"550026060","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026060","endDate":"550026120","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026120","endDate":"550026180","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026180","endDate":"550026240","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026240","endDate":"550026300","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026300","endDate":"550026360","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026360","endDate":"550026420","percentOffWrist":0,"percentLikely":0.065217,"percentUnlikely":0.934783},{"startDate":"550026420","endDate":"550026480","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550026480","endDate":"550026540","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026540","endDate":"550026600","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026600","endDate":"550026660","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550026660","endDate":"550026720","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026720","endDate":"550026780","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550026780","endDate":"550026840","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550026840","endDate":"550026900","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550026900","endDate":"550026960","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550026960","endDate":"550027020","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027020","endDate":"550027080","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027080","endDate":"550027140","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027140","endDate":"550027200","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027200","endDate":"550027260","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027260","endDate":"550027320","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027320","endDate":"550027380","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027380","endDate":"550027440","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027440","endDate":"550027500","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027500","endDate":"550027560","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027560","endDate":"550027620","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027620","endDate":"550027680","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027680","endDate":"550027740","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027740","endDate":"550027800","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027800","endDate":"550027860","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550027860","endDate":"550027920","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550027920","endDate":"550027980","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550027980","endDate":"550028040","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550028040","endDate":"550028100","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550028100","endDate":"550028160","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550028160","endDate":"550028220","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550028220","endDate":"550028280","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550028280","endDate":"550028340","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550028340","endDate":"550028400","percentOffWrist":0,"percentLikely":0.086957,"percentUnlikely":0.913043},{"startDate":"550028400","endDate":"550028460","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550028460","endDate":"550028520","percentOffWrist":0,"percentLikely":0.108696,"percentUnlikely":0.891304},{"startDate":"550028520","endDate":"550028580","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550028580","endDate":"550028640","percentOffWrist":0,"percentLikely":0.152174,"percentUnlikely":0.847826},{"startDate":"550028640","endDate":"550028700","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550028700","endDate":"550028760","percentOffWrist":0,"percentLikely":0.130435,"percentUnlikely":0.869565},{"startDate":"550028760","endDate":"550028820","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550028820","endDate":"550028880","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550028880","endDate":"550028940","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550028940","endDate":"550029000","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029000","endDate":"550029060","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029060","endDate":"550029120","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029120","endDate":"550029180","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029180","endDate":"550029240","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029240","endDate":"550029300","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029300","endDate":"550029360","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029360","endDate":"550029420","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029420","endDate":"550029480","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029480","endDate":"550029540","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0},{"startDate":"550029540","endDate":"550029600","percentOffWrist":1,"percentLikely":0,"percentUnlikely":0}] \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/tremor.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/tremor.json new file mode 100755 index 0000000..dcfc429 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/Supporting Files/tremor.json @@ -0,0 +1 @@ +[{"startDate":"549986400","endDate":"549986460","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549986460","endDate":"549986520","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549986520","endDate":"549986580","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986580","endDate":"549986640","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.152174,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986640","endDate":"549986700","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.065217,"percentSlight":0.195652,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986700","endDate":"549986760","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.108696,"percentSlight":0.152174,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986760","endDate":"549986820","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.217391,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986820","endDate":"549986880","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549986880","endDate":"549986940","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.021739,"percentSlight":0.195652,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549986940","endDate":"549987000","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.23913,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987000","endDate":"549987060","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.173913,"percentSlight":0.195652,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987060","endDate":"549987120","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.086957,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.065217,"percentStrong":0},{"startDate":"549987120","endDate":"549987180","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0,"percentSlight":0.195652,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987180","endDate":"549987240","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.065217,"percentSlight":0.130435,"percentMild":0.108696,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987240","endDate":"549987300","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0,"percentSlight":0.217391,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987300","endDate":"549987360","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987360","endDate":"549987420","percentOffWrist":0,"percentUnknown":0.478261,"percentNone":0.23913,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987420","endDate":"549987480","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987480","endDate":"549987540","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987540","endDate":"549987600","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0,"percentSlight":0.173913,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987600","endDate":"549987660","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987660","endDate":"549987720","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0,"percentSlight":0.086957,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987720","endDate":"549987780","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.217391,"percentSlight":0.173913,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987780","endDate":"549987840","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987840","endDate":"549987900","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.195652,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549987900","endDate":"549987960","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549987960","endDate":"549988020","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.021739,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988020","endDate":"549988080","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.086957,"percentMild":0.108696,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988080","endDate":"549988140","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.108696,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988140","endDate":"549988200","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.152174,"percentSlight":0.152174,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988200","endDate":"549988260","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.065217,"percentSlight":0.152174,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988260","endDate":"549988320","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988320","endDate":"549988380","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988380","endDate":"549988440","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.173913,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988440","endDate":"549988500","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.021739,"percentSlight":0.173913,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988500","endDate":"549988560","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0,"percentSlight":0.195652,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988560","endDate":"549988620","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988620","endDate":"549988680","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.108696,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0.021739},{"startDate":"549988680","endDate":"549988740","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.173913,"percentSlight":0.086957,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988740","endDate":"549988800","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988800","endDate":"549988860","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.086957,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549988860","endDate":"549988920","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549988920","endDate":"549988980","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.065217,"percentStrong":0},{"startDate":"549988980","endDate":"549989040","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.108696,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549989040","endDate":"549989100","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.043478,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989100","endDate":"549989160","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.195652,"percentSlight":0.108696,"percentMild":0.108696,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549989160","endDate":"549989220","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.043478,"percentSlight":0.130435,"percentMild":0.108696,"percentModerate":0.065217,"percentStrong":0},{"startDate":"549989220","endDate":"549989280","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.130435,"percentSlight":0.152174,"percentMild":0.043478,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989280","endDate":"549989340","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0,"percentSlight":0.173913,"percentMild":0.108696,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989340","endDate":"549989400","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.152174,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989400","endDate":"549989460","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549989460","endDate":"549989520","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0,"percentSlight":0.195652,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989520","endDate":"549989580","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.130435,"percentSlight":0.130435,"percentMild":0.108696,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989580","endDate":"549989640","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989640","endDate":"549989700","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.108696,"percentSlight":0.173913,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989700","endDate":"549989760","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.108696,"percentSlight":0.195652,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989760","endDate":"549989820","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.108696,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549989820","endDate":"549989880","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549989880","endDate":"549989940","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0,"percentSlight":0.130435,"percentMild":0.108696,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549989940","endDate":"549990000","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.065217,"percentSlight":0.086957,"percentMild":0.108696,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990000","endDate":"549990060","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990060","endDate":"549990120","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.152174,"percentSlight":0.130435,"percentMild":0.086957,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990120","endDate":"549990180","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.021739,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990180","endDate":"549990240","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990240","endDate":"549990300","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.021739,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990300","endDate":"549990360","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990360","endDate":"549990420","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990420","endDate":"549990480","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0,"percentSlight":0.152174,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990480","endDate":"549990540","percentOffWrist":0,"percentUnknown":0.478261,"percentNone":0.326087,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.043478,"percentStrong":0},{"startDate":"549990540","endDate":"549990600","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.021739,"percentSlight":0.173913,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990600","endDate":"549990660","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.173913,"percentSlight":0.086957,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990660","endDate":"549990720","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0,"percentSlight":0.173913,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990720","endDate":"549990780","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.130435,"percentSlight":0.108696,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990780","endDate":"549990840","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.108696,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990840","endDate":"549990900","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.217391,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0.021739},{"startDate":"549990900","endDate":"549990960","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.065217,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549990960","endDate":"549991020","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.152174,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991020","endDate":"549991080","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.043478,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0,"percentStrong":0},{"startDate":"549991080","endDate":"549991140","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.195652,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991140","endDate":"549991200","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.065217,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991200","endDate":"549991260","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.23913,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991260","endDate":"549991320","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991320","endDate":"549991380","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.065217,"percentModerate":0,"percentStrong":0},{"startDate":"549991380","endDate":"549991440","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991440","endDate":"549991500","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.021739,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"549991500","endDate":"549991560","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.26087,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991560","endDate":"549991620","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.195652,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991620","endDate":"549991680","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.217391,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991680","endDate":"549991740","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.021739,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991740","endDate":"549991800","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.26087,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991800","endDate":"549991860","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.086957,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991860","endDate":"549991920","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.282609,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991920","endDate":"549991980","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.130435,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549991980","endDate":"549992040","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.304348,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992040","endDate":"549992100","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992100","endDate":"549992160","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992160","endDate":"549992220","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.326087,"percentSlight":0.108696,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992220","endDate":"549992280","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.173913,"percentSlight":0.086957,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992280","endDate":"549992340","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.282609,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992340","endDate":"549992400","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.043478,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992400","endDate":"549992460","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.086957,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992460","endDate":"549992520","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992520","endDate":"549992580","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992580","endDate":"549992640","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992640","endDate":"549992700","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992700","endDate":"549992760","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992760","endDate":"549992820","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992820","endDate":"549992880","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"549992880","endDate":"549992940","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549992940","endDate":"549993000","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993000","endDate":"549993060","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993060","endDate":"549993120","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993120","endDate":"549993180","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993180","endDate":"549993240","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993240","endDate":"549993300","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993300","endDate":"549993360","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.413043,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993360","endDate":"549993420","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993420","endDate":"549993480","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993480","endDate":"549993540","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993540","endDate":"549993600","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993600","endDate":"549993660","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"549993660","endDate":"549993720","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993720","endDate":"549993780","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993780","endDate":"549993840","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993840","endDate":"549993900","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993900","endDate":"549993960","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549993960","endDate":"549994020","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994020","endDate":"549994080","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994080","endDate":"549994140","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994140","endDate":"549994200","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994200","endDate":"549994260","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994260","endDate":"549994320","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994320","endDate":"549994380","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994380","endDate":"549994440","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994440","endDate":"549994500","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994500","endDate":"549994560","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.456522,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994560","endDate":"549994620","percentOffWrist":0,"percentUnknown":0.956522,"percentNone":0.043478,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994620","endDate":"549994680","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994680","endDate":"549994740","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994740","endDate":"549994800","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994800","endDate":"549994860","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.108696,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994860","endDate":"549994920","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994920","endDate":"549994980","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549994980","endDate":"549995040","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995040","endDate":"549995100","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995100","endDate":"549995160","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995160","endDate":"549995220","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995220","endDate":"549995280","percentOffWrist":0,"percentUnknown":0.913043,"percentNone":0.086957,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995280","endDate":"549995340","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995340","endDate":"549995400","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995400","endDate":"549995460","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995460","endDate":"549995520","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995520","endDate":"549995580","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995580","endDate":"549995640","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995640","endDate":"549995700","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995700","endDate":"549995760","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995760","endDate":"549995820","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995820","endDate":"549995880","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995880","endDate":"549995940","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549995940","endDate":"549996000","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996000","endDate":"549996060","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996060","endDate":"549996120","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996120","endDate":"549996180","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996180","endDate":"549996240","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996240","endDate":"549996300","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996300","endDate":"549996360","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996360","endDate":"549996420","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996420","endDate":"549996480","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996480","endDate":"549996540","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996540","endDate":"549996600","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996600","endDate":"549996660","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996660","endDate":"549996720","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996720","endDate":"549996780","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996780","endDate":"549996840","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996840","endDate":"549996900","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996900","endDate":"549996960","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549996960","endDate":"549997020","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997020","endDate":"549997080","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997080","endDate":"549997140","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997140","endDate":"549997200","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997200","endDate":"549997260","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997260","endDate":"549997320","percentOffWrist":0,"percentUnknown":0.913043,"percentNone":0.086957,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997320","endDate":"549997380","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997380","endDate":"549997440","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.413043,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997440","endDate":"549997500","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997500","endDate":"549997560","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997560","endDate":"549997620","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997620","endDate":"549997680","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997680","endDate":"549997740","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997740","endDate":"549997800","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997800","endDate":"549997860","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997860","endDate":"549997920","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997920","endDate":"549997980","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549997980","endDate":"549998040","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998040","endDate":"549998100","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998100","endDate":"549998160","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998160","endDate":"549998220","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998220","endDate":"549998280","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998280","endDate":"549998340","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998340","endDate":"549998400","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998400","endDate":"549998460","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998460","endDate":"549998520","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998520","endDate":"549998580","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998580","endDate":"549998640","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998640","endDate":"549998700","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998700","endDate":"549998760","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998760","endDate":"549998820","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998820","endDate":"549998880","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998880","endDate":"549998940","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549998940","endDate":"549999000","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999000","endDate":"549999060","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999060","endDate":"549999120","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999120","endDate":"549999180","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.5,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999180","endDate":"549999240","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.130435,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999240","endDate":"549999300","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999300","endDate":"549999360","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999360","endDate":"549999420","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999420","endDate":"549999480","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999480","endDate":"549999540","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999540","endDate":"549999600","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999600","endDate":"549999660","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999660","endDate":"549999720","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999720","endDate":"549999780","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999780","endDate":"549999840","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999840","endDate":"549999900","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999900","endDate":"549999960","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"549999960","endDate":"550000020","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000020","endDate":"550000080","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000080","endDate":"550000140","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000140","endDate":"550000200","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000200","endDate":"550000260","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000260","endDate":"550000320","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000320","endDate":"550000380","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000380","endDate":"550000440","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000440","endDate":"550000500","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.413043,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000500","endDate":"550000560","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000560","endDate":"550000620","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000620","endDate":"550000680","percentOffWrist":0,"percentUnknown":0.913043,"percentNone":0.086957,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000680","endDate":"550000740","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000740","endDate":"550000800","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000800","endDate":"550000860","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000860","endDate":"550000920","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000920","endDate":"550000980","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550000980","endDate":"550001040","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001040","endDate":"550001100","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001100","endDate":"550001160","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001160","endDate":"550001220","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001220","endDate":"550001280","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001280","endDate":"550001340","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001340","endDate":"550001400","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001400","endDate":"550001460","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001460","endDate":"550001520","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001520","endDate":"550001580","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.456522,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001580","endDate":"550001640","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001640","endDate":"550001700","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001700","endDate":"550001760","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550001760","endDate":"550001820","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001820","endDate":"550001880","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001880","endDate":"550001940","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550001940","endDate":"550002000","percentOffWrist":0,"percentUnknown":0.956522,"percentNone":0,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002000","endDate":"550002060","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002060","endDate":"550002120","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002120","endDate":"550002180","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002180","endDate":"550002240","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002240","endDate":"550002300","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002300","endDate":"550002360","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002360","endDate":"550002420","percentOffWrist":0,"percentUnknown":0.956522,"percentNone":0,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002420","endDate":"550002480","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550002480","endDate":"550002540","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550002540","endDate":"550002600","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002600","endDate":"550002660","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002660","endDate":"550002720","percentOffWrist":0,"percentUnknown":0.478261,"percentNone":0.478261,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002720","endDate":"550002780","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550002780","endDate":"550002840","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550002840","endDate":"550002900","percentOffWrist":0,"percentUnknown":0.913043,"percentNone":0.021739,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002900","endDate":"550002960","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550002960","endDate":"550003020","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.086957,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003020","endDate":"550003080","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003080","endDate":"550003140","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003140","endDate":"550003200","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003200","endDate":"550003260","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.173913,"percentSlight":0.086957,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003260","endDate":"550003320","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003320","endDate":"550003380","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.043478,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003380","endDate":"550003440","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003440","endDate":"550003500","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003500","endDate":"550003560","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.282609,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550003560","endDate":"550003620","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550003620","endDate":"550003680","percentOffWrist":0,"percentUnknown":0.478261,"percentNone":0.391304,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003680","endDate":"550003740","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.130435,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550003740","endDate":"550003800","percentOffWrist":0,"percentUnknown":0.347826,"percentNone":0.521739,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003800","endDate":"550003860","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.23913,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550003860","endDate":"550003920","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.043478,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550003920","endDate":"550003980","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.152174,"percentSlight":0.086957,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550003980","endDate":"550004040","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.217391,"percentSlight":0.086957,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004040","endDate":"550004100","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004100","endDate":"550004160","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.369565,"percentSlight":0.086957,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004160","endDate":"550004220","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.152174,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004220","endDate":"550004280","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.065217,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004280","endDate":"550004340","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.065217,"percentSlight":0.065217,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004340","endDate":"550004400","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004400","endDate":"550004460","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.173913,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004460","endDate":"550004520","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.152174,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.043478,"percentStrong":0},{"startDate":"550004520","endDate":"550004580","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.217391,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004580","endDate":"550004640","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.195652,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004640","endDate":"550004700","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.086957,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.043478,"percentStrong":0},{"startDate":"550004700","endDate":"550004760","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.217391,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004760","endDate":"550004820","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.108696,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004820","endDate":"550004880","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.065217,"percentSlight":0.108696,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004880","endDate":"550004940","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.021739,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550004940","endDate":"550005000","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.108696,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005000","endDate":"550005060","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.108696,"percentSlight":0.152174,"percentMild":0.065217,"percentModerate":0.043478,"percentStrong":0},{"startDate":"550005060","endDate":"550005120","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.282609,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005120","endDate":"550005180","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.23913,"percentSlight":0.043478,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005180","endDate":"550005240","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.065217,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005240","endDate":"550005300","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.26087,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005300","endDate":"550005360","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005360","endDate":"550005420","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.152174,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005420","endDate":"550005480","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.26087,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005480","endDate":"550005540","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.086957,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005540","endDate":"550005600","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.021739,"percentSlight":0.130435,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005600","endDate":"550005660","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.086957,"percentSlight":0.130435,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005660","endDate":"550005720","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0,"percentSlight":0.130435,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005720","endDate":"550005780","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.021739,"percentSlight":0.108696,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005780","endDate":"550005840","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.152174,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550005840","endDate":"550005900","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.195652,"percentSlight":0.086957,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005900","endDate":"550005960","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550005960","endDate":"550006020","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.173913,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006020","endDate":"550006080","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.130435,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0,"percentStrong":0},{"startDate":"550006080","endDate":"550006140","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.086957,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006140","endDate":"550006200","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.086957,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006200","endDate":"550006260","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.195652,"percentSlight":0.108696,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006260","endDate":"550006320","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.021739,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006320","endDate":"550006380","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.23913,"percentSlight":0.108696,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006380","endDate":"550006440","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006440","endDate":"550006500","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.065217,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006500","endDate":"550006560","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0,"percentSlight":0.086957,"percentMild":0.065217,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006560","endDate":"550006620","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.173913,"percentSlight":0.130435,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550006620","endDate":"550006680","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006680","endDate":"550006740","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006740","endDate":"550006800","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.304348,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550006800","endDate":"550006860","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550006860","endDate":"550006920","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.130435,"percentSlight":0.086957,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006920","endDate":"550006980","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.26087,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550006980","endDate":"550007040","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550007040","endDate":"550007100","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007100","endDate":"550007160","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550007160","endDate":"550007220","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.304348,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007220","endDate":"550007280","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.282609,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007280","endDate":"550007340","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.021739,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550007340","endDate":"550007400","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007400","endDate":"550007460","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007460","endDate":"550007520","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.130435,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550007520","endDate":"550007580","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007580","endDate":"550007640","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.021739,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007640","endDate":"550007700","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007700","endDate":"550007760","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.086957,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007760","endDate":"550007820","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007820","endDate":"550007880","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550007880","endDate":"550007940","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550007940","endDate":"550008000","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.086957,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550008000","endDate":"550008060","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008060","endDate":"550008120","percentOffWrist":0,"percentUnknown":0.934783,"percentNone":0,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550008120","endDate":"550008180","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008180","endDate":"550008240","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008240","endDate":"550008300","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550008300","endDate":"550008360","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008360","endDate":"550008420","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008420","endDate":"550008480","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008480","endDate":"550008540","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008540","endDate":"550008600","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008600","endDate":"550008660","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008660","endDate":"550008720","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.086957,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008720","endDate":"550008780","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008780","endDate":"550008840","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008840","endDate":"550008900","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.434783,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008900","endDate":"550008960","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550008960","endDate":"550009020","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009020","endDate":"550009080","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009080","endDate":"550009140","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009140","endDate":"550009200","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009200","endDate":"550009260","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009260","endDate":"550009320","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009320","endDate":"550009380","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009380","endDate":"550009440","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.456522,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009440","endDate":"550009500","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009500","endDate":"550009560","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009560","endDate":"550009620","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009620","endDate":"550009680","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009680","endDate":"550009740","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.413043,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009740","endDate":"550009800","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009800","endDate":"550009860","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009860","endDate":"550009920","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009920","endDate":"550009980","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550009980","endDate":"550010040","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.456522,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010040","endDate":"550010100","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010100","endDate":"550010160","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010160","endDate":"550010220","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010220","endDate":"550010280","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010280","endDate":"550010340","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010340","endDate":"550010400","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010400","endDate":"550010460","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010460","endDate":"550010520","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010520","endDate":"550010580","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010580","endDate":"550010640","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010640","endDate":"550010700","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010700","endDate":"550010760","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550010760","endDate":"550010820","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010820","endDate":"550010880","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010880","endDate":"550010940","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.108696,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550010940","endDate":"550011000","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.130435,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011000","endDate":"550011060","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011060","endDate":"550011120","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011120","endDate":"550011180","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011180","endDate":"550011240","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011240","endDate":"550011300","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011300","endDate":"550011360","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011360","endDate":"550011420","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011420","endDate":"550011480","percentOffWrist":0,"percentUnknown":0.434783,"percentNone":0.565217,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011480","endDate":"550011540","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011540","endDate":"550011600","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.130435,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011600","endDate":"550011660","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011660","endDate":"550011720","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011720","endDate":"550011780","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011780","endDate":"550011840","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011840","endDate":"550011900","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011900","endDate":"550011960","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550011960","endDate":"550012020","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012020","endDate":"550012080","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012080","endDate":"550012140","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012140","endDate":"550012200","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012200","endDate":"550012260","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012260","endDate":"550012320","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012320","endDate":"550012380","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012380","endDate":"550012440","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012440","endDate":"550012500","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012500","endDate":"550012560","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012560","endDate":"550012620","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.152174,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012620","endDate":"550012680","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012680","endDate":"550012740","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012740","endDate":"550012800","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012800","endDate":"550012860","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012860","endDate":"550012920","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.173913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012920","endDate":"550012980","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.413043,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550012980","endDate":"550013040","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013040","endDate":"550013100","percentOffWrist":0,"percentUnknown":0.978261,"percentNone":0.021739,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013100","endDate":"550013160","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013160","endDate":"550013220","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.282609,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013220","endDate":"550013280","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.195652,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013280","endDate":"550013340","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013340","endDate":"550013400","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013400","endDate":"550013460","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.456522,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013460","endDate":"550013520","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.456522,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013520","endDate":"550013580","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013580","endDate":"550013640","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013640","endDate":"550013700","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013700","endDate":"550013760","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013760","endDate":"550013820","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013820","endDate":"550013880","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.26087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013880","endDate":"550013940","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550013940","endDate":"550014000","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.217391,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014000","endDate":"550014060","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014060","endDate":"550014120","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014120","endDate":"550014180","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014180","endDate":"550014240","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014240","endDate":"550014300","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.369565,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014300","endDate":"550014360","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.434783,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014360","endDate":"550014420","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014420","endDate":"550014480","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.391304,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014480","endDate":"550014540","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014540","endDate":"550014600","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014600","endDate":"550014660","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014660","endDate":"550014720","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014720","endDate":"550014780","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014780","endDate":"550014840","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550014840","endDate":"550014900","percentOffWrist":0,"percentUnknown":0.956522,"percentNone":0,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550014900","endDate":"550014960","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550014960","endDate":"550015020","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550015020","endDate":"550015080","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550015080","endDate":"550015140","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015140","endDate":"550015200","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015200","endDate":"550015260","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015260","endDate":"550015320","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015320","endDate":"550015380","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015380","endDate":"550015440","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.108696,"percentSlight":0,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015440","endDate":"550015500","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015500","endDate":"550015560","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550015560","endDate":"550015620","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015620","endDate":"550015680","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015680","endDate":"550015740","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015740","endDate":"550015800","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015800","endDate":"550015860","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015860","endDate":"550015920","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015920","endDate":"550015980","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550015980","endDate":"550016040","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016040","endDate":"550016100","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016100","endDate":"550016160","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016160","endDate":"550016220","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016220","endDate":"550016280","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016280","endDate":"550016340","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016340","endDate":"550016400","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.434783,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550016400","endDate":"550016460","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016460","endDate":"550016520","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016520","endDate":"550016580","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016580","endDate":"550016640","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016640","endDate":"550016700","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016700","endDate":"550016760","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.23913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016760","endDate":"550016820","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016820","endDate":"550016880","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016880","endDate":"550016940","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.086957,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550016940","endDate":"550017000","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017000","endDate":"550017060","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.217391,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017060","endDate":"550017120","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017120","endDate":"550017180","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017180","endDate":"550017240","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017240","endDate":"550017300","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017300","endDate":"550017360","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017360","endDate":"550017420","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017420","endDate":"550017480","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017480","endDate":"550017540","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017540","endDate":"550017600","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017600","endDate":"550017660","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017660","endDate":"550017720","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.065217,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017720","endDate":"550017780","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017780","endDate":"550017840","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.26087,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017840","endDate":"550017900","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550017900","endDate":"550017960","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.413043,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550017960","endDate":"550018020","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550018020","endDate":"550018080","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.282609,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550018080","endDate":"550018140","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.065217,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550018140","endDate":"550018200","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018200","endDate":"550018260","percentOffWrist":0,"percentUnknown":0.934783,"percentNone":0,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018260","endDate":"550018320","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018320","endDate":"550018380","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018380","endDate":"550018440","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018440","endDate":"550018500","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550018500","endDate":"550018560","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550018560","endDate":"550018620","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.413043,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018620","endDate":"550018680","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018680","endDate":"550018740","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.369565,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018740","endDate":"550018800","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018800","endDate":"550018860","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018860","endDate":"550018920","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018920","endDate":"550018980","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550018980","endDate":"550019040","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019040","endDate":"550019100","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019100","endDate":"550019160","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550019160","endDate":"550019220","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550019220","endDate":"550019280","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019280","endDate":"550019340","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019340","endDate":"550019400","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019400","endDate":"550019460","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019460","endDate":"550019520","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019520","endDate":"550019580","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019580","endDate":"550019640","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019640","endDate":"550019700","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550019700","endDate":"550019760","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019760","endDate":"550019820","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019820","endDate":"550019880","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019880","endDate":"550019940","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550019940","endDate":"550020000","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020000","endDate":"550020060","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020060","endDate":"550020120","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020120","endDate":"550020180","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020180","endDate":"550020240","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020240","endDate":"550020300","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020300","endDate":"550020360","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020360","endDate":"550020420","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020420","endDate":"550020480","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020480","endDate":"550020540","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020540","endDate":"550020600","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020600","endDate":"550020660","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.217391,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020660","endDate":"550020720","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020720","endDate":"550020780","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020780","endDate":"550020840","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020840","endDate":"550020900","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020900","endDate":"550020960","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.413043,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550020960","endDate":"550021020","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021020","endDate":"550021080","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021080","endDate":"550021140","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021140","endDate":"550021200","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550021200","endDate":"550021260","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.434783,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021260","endDate":"550021320","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550021320","endDate":"550021380","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021380","endDate":"550021440","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.391304,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021440","endDate":"550021500","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021500","endDate":"550021560","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021560","endDate":"550021620","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550021620","endDate":"550021680","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.326087,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021680","endDate":"550021740","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.347826,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021740","endDate":"550021800","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550021800","endDate":"550021860","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550021860","endDate":"550021920","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550021920","endDate":"550021980","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.23913,"percentSlight":0.065217,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550021980","endDate":"550022040","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022040","endDate":"550022100","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022100","endDate":"550022160","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022160","endDate":"550022220","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022220","endDate":"550022280","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022280","endDate":"550022340","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550022340","endDate":"550022400","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022400","endDate":"550022460","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022460","endDate":"550022520","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.152174,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022520","endDate":"550022580","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.304348,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022580","endDate":"550022640","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550022640","endDate":"550022700","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.065217,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022700","endDate":"550022760","percentOffWrist":0,"percentUnknown":0.434783,"percentNone":0.5,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022760","endDate":"550022820","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022820","endDate":"550022880","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022880","endDate":"550022940","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550022940","endDate":"550023000","percentOffWrist":0,"percentUnknown":0.869565,"percentNone":0.086957,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023000","endDate":"550023060","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023060","endDate":"550023120","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550023120","endDate":"550023180","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023180","endDate":"550023240","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023240","endDate":"550023300","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.391304,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023300","endDate":"550023360","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023360","endDate":"550023420","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023420","endDate":"550023480","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023480","endDate":"550023540","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023540","endDate":"550023600","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023600","endDate":"550023660","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023660","endDate":"550023720","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.195652,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023720","endDate":"550023780","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023780","endDate":"550023840","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023840","endDate":"550023900","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023900","endDate":"550023960","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550023960","endDate":"550024020","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.391304,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024020","endDate":"550024080","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.304348,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024080","endDate":"550024140","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024140","endDate":"550024200","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0.021739,"percentStrong":0},{"startDate":"550024200","endDate":"550024260","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024260","endDate":"550024320","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024320","endDate":"550024380","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024380","endDate":"550024440","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024440","endDate":"550024500","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.434783,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550024500","endDate":"550024560","percentOffWrist":0,"percentUnknown":0.934783,"percentNone":0,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024560","endDate":"550024620","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024620","endDate":"550024680","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550024680","endDate":"550024740","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.456522,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550024740","endDate":"550024800","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.369565,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024800","endDate":"550024860","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024860","endDate":"550024920","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.173913,"percentSlight":0.065217,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024920","endDate":"550024980","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.347826,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550024980","endDate":"550025040","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.108696,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025040","endDate":"550025100","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025100","endDate":"550025160","percentOffWrist":0,"percentUnknown":0.608696,"percentNone":0.326087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025160","endDate":"550025220","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.23913,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025220","endDate":"550025280","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.021739,"percentMild":0.043478,"percentModerate":0,"percentStrong":0},{"startDate":"550025280","endDate":"550025340","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025340","endDate":"550025400","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025400","endDate":"550025460","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.130435,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025460","endDate":"550025520","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.217391,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025520","endDate":"550025580","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550025580","endDate":"550025640","percentOffWrist":0,"percentUnknown":0.5,"percentNone":0.456522,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025640","endDate":"550025700","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.26087,"percentSlight":0.043478,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025700","endDate":"550025760","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025760","endDate":"550025820","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550025820","endDate":"550025880","percentOffWrist":0,"percentUnknown":0.891304,"percentNone":0.065217,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025880","endDate":"550025940","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550025940","endDate":"550026000","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.369565,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026000","endDate":"550026060","percentOffWrist":0,"percentUnknown":0.847826,"percentNone":0.108696,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026060","endDate":"550026120","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026120","endDate":"550026180","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026180","endDate":"550026240","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026240","endDate":"550026300","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.195652,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026300","endDate":"550026360","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0.021739,"percentModerate":0,"percentStrong":0},{"startDate":"550026360","endDate":"550026420","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026420","endDate":"550026480","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026480","endDate":"550026540","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026540","endDate":"550026600","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026600","endDate":"550026660","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026660","endDate":"550026720","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026720","endDate":"550026780","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026780","endDate":"550026840","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026840","endDate":"550026900","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026900","endDate":"550026960","percentOffWrist":0,"percentUnknown":0.782609,"percentNone":0.173913,"percentSlight":0.043478,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550026960","endDate":"550027020","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027020","endDate":"550027080","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.326087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027080","endDate":"550027140","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027140","endDate":"550027200","percentOffWrist":0,"percentUnknown":0.826087,"percentNone":0.152174,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027200","endDate":"550027260","percentOffWrist":0,"percentUnknown":0.565217,"percentNone":0.413043,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027260","endDate":"550027320","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027320","endDate":"550027380","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.456522,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027380","endDate":"550027440","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027440","endDate":"550027500","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027500","endDate":"550027560","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027560","endDate":"550027620","percentOffWrist":0,"percentUnknown":0.630435,"percentNone":0.347826,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027620","endDate":"550027680","percentOffWrist":0,"percentUnknown":0.804348,"percentNone":0.173913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027680","endDate":"550027740","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027740","endDate":"550027800","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027800","endDate":"550027860","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027860","endDate":"550027920","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.304348,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027920","endDate":"550027980","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550027980","endDate":"550028040","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028040","endDate":"550028100","percentOffWrist":0,"percentUnknown":0.73913,"percentNone":0.23913,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028100","endDate":"550028160","percentOffWrist":0,"percentUnknown":0.521739,"percentNone":0.478261,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028160","endDate":"550028220","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028220","endDate":"550028280","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.23913,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028280","endDate":"550028340","percentOffWrist":0,"percentUnknown":0.717391,"percentNone":0.26087,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028340","endDate":"550028400","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.282609,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028400","endDate":"550028460","percentOffWrist":0,"percentUnknown":0.586957,"percentNone":0.391304,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028460","endDate":"550028520","percentOffWrist":0,"percentUnknown":0.76087,"percentNone":0.217391,"percentSlight":0.021739,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028520","endDate":"550028580","percentOffWrist":0,"percentUnknown":0.543478,"percentNone":0.456522,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028580","endDate":"550028640","percentOffWrist":0,"percentUnknown":0.695652,"percentNone":0.304348,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028640","endDate":"550028700","percentOffWrist":0,"percentUnknown":0.652174,"percentNone":0.347826,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028700","endDate":"550028760","percentOffWrist":0,"percentUnknown":0.673913,"percentNone":0.326087,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028760","endDate":"550028820","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028820","endDate":"550028880","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028880","endDate":"550028940","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550028940","endDate":"550029000","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029000","endDate":"550029060","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029060","endDate":"550029120","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029120","endDate":"550029180","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029180","endDate":"550029240","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029240","endDate":"550029300","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029300","endDate":"550029360","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029360","endDate":"550029420","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029420","endDate":"550029480","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029480","endDate":"550029540","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0},{"startDate":"550029540","endDate":"550029600","percentOffWrist":1,"percentUnknown":0,"percentNone":0,"percentSlight":0,"percentMild":0,"percentModerate":0,"percentStrong":0}] \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/en.lproj/Localizable.strings b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/en.lproj/Localizable.strings new file mode 100755 index 0000000..192768c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/ORKParkinsonStudy/en.lproj/Localizable.strings @@ -0,0 +1,34 @@ +/* + Copyright (c) 2018, Apple Inc. All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + 3. Neither the name of the copyright holder(s) nor the names of any contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. No license is granted to the trademarks of + the copyright holders even if such marks are included in this software. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +"CONSENT_DATA" = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam et orci eleifend, pretium sapien vel, mattis est. Vestibulum sit amet blandit leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut tincidunt orci vitae laoreet hendrerit. Morbi blandit commodo vestibulum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque mattis aliquet sapien eu lobortis."; +"CONSENT_PRIVACY" = "Ut tincidunt orci vitae laoreet hendrerit. Morbi blandit commodo vestibulum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque mattis aliquet sapien eu lobortis."; +"CONSENT_DATA_USE" = "Vestibulum dolor augue, porttitor et sapien vitae, dictum eleifend justo. Phasellus nec sollicitudin enim. Nunc vel scelerisque justo, at vehicula eros. Vestibulum tristique felis at quam suscipit, ac blandit nulla volutpat."; +"CONSENT_WITHDRAW" = "Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean sagittis vehicula risus, vehicula gravida purus laoreet at. Morbi euismod tempor urna nec placerat. Vestibulum dolor augue, porttitor et sapien vitae, dictum eleifend justo. Phasellus nec sollicitudin enim. Nunc vel scelerisque justo, at vehicula eros. Vestibulum tristique felis at quam suscipit, ac blandit nulla volutpat."; diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/README.md b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/README.md new file mode 100755 index 0000000..5abeba3 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKParkinsonStudy/README.md @@ -0,0 +1,2 @@ +# ORKParkinsonStudy + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.pbxproj b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.pbxproj new file mode 100755 index 0000000..3e45134 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.pbxproj @@ -0,0 +1,523 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 161479C41BD6CE8F0099A068 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161479C31BD6CE8F0099A068 /* AppDelegate.swift */; }; + 161479C91BD6CE8F0099A068 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 161479C71BD6CE8F0099A068 /* Main.storyboard */; }; + 161479CB1BD6CE8F0099A068 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 161479CA1BD6CE8F0099A068 /* Assets.xcassets */; }; + 161479CE1BD6CE8F0099A068 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 161479CC1BD6CE8F0099A068 /* LaunchScreen.storyboard */; }; + 16147A0F1BD83F700099A068 /* ActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16147A0E1BD83F700099A068 /* ActivityViewController.swift */; }; + 165A7E661BD99DBA00B6D223 /* StudyTasks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165A7E651BD99DBA00B6D223 /* StudyTasks.swift */; }; + 165A7E6E1BD9AEF800B6D223 /* IntroductionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165A7E6D1BD9AEF800B6D223 /* IntroductionViewController.swift */; }; + 16BF5B691BE2974A007C79C6 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16BF5B681BE2974A007C79C6 /* ProfileViewController.swift */; }; + 16BF5B6F1BE2BE77007C79C6 /* HealthClientType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16BF5B6E1BE2BE77007C79C6 /* HealthClientType.swift */; }; + 16BF5B711BE2C989007C79C6 /* ProfileStaticTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16BF5B701BE2C989007C79C6 /* ProfileStaticTableViewCell.swift */; }; + 86CCDFF61C1B50970042AA39 /* ResearchContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 86CCDFF51C1B50970042AA39 /* ResearchContainerViewController.swift */; }; + B5BC85FA1BF1405900B0CFA5 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 161479C51BD6CE8F0099A068 /* OnboardingViewController.swift */; }; + B5BC85FD1BF1408500B0CFA5 /* HealthDataStepViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 168F25711BE052AD001D2D65 /* HealthDataStepViewController.swift */; }; + B5C2073F1BEC16F00051D9D8 /* ResearchContainerSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C2073E1BEC16F00051D9D8 /* ResearchContainerSegue.swift */; }; + B5C207421BECBA8B0051D9D8 /* WithdrawViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C207411BECBA8B0051D9D8 /* WithdrawViewController.swift */; }; + B5C207501BECCB1A0051D9D8 /* AnimatableChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C2074F1BECCB1A0051D9D8 /* AnimatableChart.swift */; }; + B5C207561BECED750051D9D8 /* ConsentDocument.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C207551BECED750051D9D8 /* ConsentDocument.swift */; }; + B5C366B41BE7ADBA0036112D /* DashboardTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C366B31BE7ADBA0036112D /* DashboardTableViewController.swift */; }; + B5D117581BE8D12000D7F153 /* PieChartDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D117571BE8D12000D7F153 /* PieChartDataSource.swift */; }; + B5D1175C1BE8D15400D7F153 /* DiscreteGraphDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1175B1BE8D15400D7F153 /* DiscreteGraphDataSource.swift */; }; + B5D1175E1BE8D17E00D7F153 /* LineGraphDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D1175D1BE8D17E00D7F153 /* LineGraphDataSource.swift */; }; + B5D35FC71BEA363F004CBB06 /* ProfileHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D35FC61BEA363F004CBB06 /* ProfileHeaderView.swift */; }; + B5D35FC91BEA48D3004CBB06 /* HKHealthStore+Queries.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D35FC81BEA48D3004CBB06 /* HKHealthStore+Queries.swift */; }; + B5FA92E91BF13D98001E46C0 /* HealthDataStep.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FA92E81BF13D98001E46C0 /* HealthDataStep.swift */; }; + BC2A3CA51C58E91E00DA64B7 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CA41C58E91E00DA64B7 /* HealthKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + BC2A3CDD1C58F1DB00DA64B7 /* ResearchKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CDC1C58F1DB00DA64B7 /* ResearchKit.framework */; }; + BC2A3CDE1C58F1DB00DA64B7 /* ResearchKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BC2A3CDC1C58F1DB00DA64B7 /* ResearchKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + BC2A3CDF1C58F1DB00DA64B7 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + BC2A3CDE1C58F1DB00DA64B7 /* ResearchKit.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 161479C01BD6CE8F0099A068 /* ORKSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ORKSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 161479C31BD6CE8F0099A068 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ORKSample/AppDelegate.swift; sourceTree = ""; }; + 161479C51BD6CE8F0099A068 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OnboardingViewController.swift; path = ORKSample/OnboardingViewController.swift; sourceTree = ""; }; + 161479C81BD6CE8F0099A068 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 161479CA1BD6CE8F0099A068 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ORKSample/Assets.xcassets; sourceTree = ""; }; + 161479CD1BD6CE8F0099A068 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 161479CF1BD6CE8F0099A068 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = ORKSample/Info.plist; sourceTree = ""; }; + 16147A0E1BD83F700099A068 /* ActivityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ActivityViewController.swift; path = ORKSample/ActivityViewController.swift; sourceTree = ""; }; + 165A7E651BD99DBA00B6D223 /* StudyTasks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StudyTasks.swift; path = ORKSample/StudyTasks.swift; sourceTree = ""; }; + 165A7E6D1BD9AEF800B6D223 /* IntroductionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IntroductionViewController.swift; path = ORKSample/IntroductionViewController.swift; sourceTree = ""; }; + 168F256F1BE03541001D2D65 /* ORKSample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = ORKSample.entitlements; path = ORKSample/ORKSample.entitlements; sourceTree = ""; }; + 168F25711BE052AD001D2D65 /* HealthDataStepViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthDataStepViewController.swift; path = ORKSample/HealthDataStepViewController.swift; sourceTree = ""; }; + 16BF5B681BE2974A007C79C6 /* ProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProfileViewController.swift; path = ORKSample/ProfileViewController.swift; sourceTree = ""; }; + 16BF5B6E1BE2BE77007C79C6 /* HealthClientType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthClientType.swift; path = ORKSample/HealthClientType.swift; sourceTree = ""; }; + 16BF5B701BE2C989007C79C6 /* ProfileStaticTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProfileStaticTableViewCell.swift; path = ORKSample/ProfileStaticTableViewCell.swift; sourceTree = ""; }; + 86CCDFF51C1B50970042AA39 /* ResearchContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResearchContainerViewController.swift; path = ORKSample/ResearchContainerViewController.swift; sourceTree = SOURCE_ROOT; }; + B5C2073E1BEC16F00051D9D8 /* ResearchContainerSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResearchContainerSegue.swift; path = ORKSample/ResearchContainerSegue.swift; sourceTree = ""; }; + B5C207411BECBA8B0051D9D8 /* WithdrawViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = WithdrawViewController.swift; path = ORKSample/WithdrawViewController.swift; sourceTree = ""; }; + B5C2074F1BECCB1A0051D9D8 /* AnimatableChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AnimatableChart.swift; path = ORKSample/AnimatableChart.swift; sourceTree = ""; }; + B5C207551BECED750051D9D8 /* ConsentDocument.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConsentDocument.swift; path = ORKSample/ConsentDocument.swift; sourceTree = ""; }; + B5C366B31BE7ADBA0036112D /* DashboardTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DashboardTableViewController.swift; path = ORKSample/DashboardTableViewController.swift; sourceTree = ""; }; + B5D117571BE8D12000D7F153 /* PieChartDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PieChartDataSource.swift; path = ORKSample/PieChartDataSource.swift; sourceTree = ""; }; + B5D1175B1BE8D15400D7F153 /* DiscreteGraphDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DiscreteGraphDataSource.swift; path = ORKSample/DiscreteGraphDataSource.swift; sourceTree = ""; }; + B5D1175D1BE8D17E00D7F153 /* LineGraphDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LineGraphDataSource.swift; path = ORKSample/LineGraphDataSource.swift; sourceTree = ""; }; + B5D35FC61BEA363F004CBB06 /* ProfileHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProfileHeaderView.swift; path = ORKSample/ProfileHeaderView.swift; sourceTree = ""; }; + B5D35FC81BEA48D3004CBB06 /* HKHealthStore+Queries.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "HKHealthStore+Queries.swift"; path = "ORKSample/HKHealthStore+Queries.swift"; sourceTree = ""; }; + B5FA92E81BF13D98001E46C0 /* HealthDataStep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HealthDataStep.swift; path = ORKSample/HealthDataStep.swift; sourceTree = ""; }; + BC2A3CA41C58E91E00DA64B7 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; }; + BC2A3CDC1C58F1DB00DA64B7 /* ResearchKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ResearchKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 161479BD1BD6CE8F0099A068 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + BC2A3CDD1C58F1DB00DA64B7 /* ResearchKit.framework in Frameworks */, + BC2A3CA51C58E91E00DA64B7 /* HealthKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 161479B71BD6CE8F0099A068 = { + isa = PBXGroup; + children = ( + BC2A3CA81C58E92600DA64B7 /* Frameworks */, + 161479C21BD6CE8F0099A068 /* ORKSample */, + 161479C11BD6CE8F0099A068 /* Products */, + ); + sourceTree = ""; + }; + 161479C11BD6CE8F0099A068 /* Products */ = { + isa = PBXGroup; + children = ( + 161479C01BD6CE8F0099A068 /* ORKSample.app */, + ); + name = Products; + sourceTree = ""; + }; + 161479C21BD6CE8F0099A068 /* ORKSample */ = { + isa = PBXGroup; + children = ( + 161479C31BD6CE8F0099A068 /* AppDelegate.swift */, + 86CCDFF51C1B50970042AA39 /* ResearchContainerViewController.swift */, + B5C2073E1BEC16F00051D9D8 /* ResearchContainerSegue.swift */, + 16BF5B611BE29643007C79C6 /* Onboarding */, + 16BF5B651BE29658007C79C6 /* Dashboard */, + 16BF5B671BE29676007C79C6 /* Activities */, + 16BF5B641BE2964F007C79C6 /* Profile */, + B5C207401BECBA710051D9D8 /* Withdrawal */, + 168F25701BE05281001D2D65 /* Steps */, + 16BF5B6B1BE2BD1C007C79C6 /* Protocols */, + B5D35FC81BEA48D3004CBB06 /* HKHealthStore+Queries.swift */, + 161479C71BD6CE8F0099A068 /* Main.storyboard */, + 161479CC1BD6CE8F0099A068 /* LaunchScreen.storyboard */, + 161479D51BD6CFB00099A068 /* Supporting Files */, + ); + name = ORKSample; + sourceTree = ""; + }; + 161479D51BD6CFB00099A068 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 161479CA1BD6CE8F0099A068 /* Assets.xcassets */, + 161479CF1BD6CE8F0099A068 /* Info.plist */, + 168F256F1BE03541001D2D65 /* ORKSample.entitlements */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 168F25701BE05281001D2D65 /* Steps */ = { + isa = PBXGroup; + children = ( + B5FA92E81BF13D98001E46C0 /* HealthDataStep.swift */, + 168F25711BE052AD001D2D65 /* HealthDataStepViewController.swift */, + B5C207551BECED750051D9D8 /* ConsentDocument.swift */, + ); + name = Steps; + sourceTree = ""; + }; + 16BF5B611BE29643007C79C6 /* Onboarding */ = { + isa = PBXGroup; + children = ( + 161479C51BD6CE8F0099A068 /* OnboardingViewController.swift */, + 165A7E6D1BD9AEF800B6D223 /* IntroductionViewController.swift */, + ); + name = Onboarding; + sourceTree = ""; + }; + 16BF5B641BE2964F007C79C6 /* Profile */ = { + isa = PBXGroup; + children = ( + 16BF5B681BE2974A007C79C6 /* ProfileViewController.swift */, + 16BF5B701BE2C989007C79C6 /* ProfileStaticTableViewCell.swift */, + B5D35FC61BEA363F004CBB06 /* ProfileHeaderView.swift */, + ); + name = Profile; + sourceTree = ""; + }; + 16BF5B651BE29658007C79C6 /* Dashboard */ = { + isa = PBXGroup; + children = ( + B5C366B31BE7ADBA0036112D /* DashboardTableViewController.swift */, + B5D117571BE8D12000D7F153 /* PieChartDataSource.swift */, + B5D1175B1BE8D15400D7F153 /* DiscreteGraphDataSource.swift */, + B5D1175D1BE8D17E00D7F153 /* LineGraphDataSource.swift */, + ); + name = Dashboard; + sourceTree = ""; + }; + 16BF5B671BE29676007C79C6 /* Activities */ = { + isa = PBXGroup; + children = ( + 16147A0E1BD83F700099A068 /* ActivityViewController.swift */, + 165A7E651BD99DBA00B6D223 /* StudyTasks.swift */, + ); + name = Activities; + sourceTree = ""; + }; + 16BF5B6B1BE2BD1C007C79C6 /* Protocols */ = { + isa = PBXGroup; + children = ( + 16BF5B6E1BE2BE77007C79C6 /* HealthClientType.swift */, + B5C2074F1BECCB1A0051D9D8 /* AnimatableChart.swift */, + ); + name = Protocols; + sourceTree = ""; + }; + B5C207401BECBA710051D9D8 /* Withdrawal */ = { + isa = PBXGroup; + children = ( + B5C207411BECBA8B0051D9D8 /* WithdrawViewController.swift */, + ); + name = Withdrawal; + sourceTree = ""; + }; + BC2A3CA81C58E92600DA64B7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BC2A3CDC1C58F1DB00DA64B7 /* ResearchKit.framework */, + BC2A3CA41C58E91E00DA64B7 /* HealthKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 161479BF1BD6CE8F0099A068 /* ORKSample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 161479D21BD6CE8F0099A068 /* Build configuration list for PBXNativeTarget "ORKSample" */; + buildPhases = ( + 161479BC1BD6CE8F0099A068 /* Sources */, + 161479BD1BD6CE8F0099A068 /* Frameworks */, + 161479BE1BD6CE8F0099A068 /* Resources */, + BC2A3CDF1C58F1DB00DA64B7 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ORKSample; + productName = ResearchHealth; + productReference = 161479C01BD6CE8F0099A068 /* ORKSample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 161479B81BD6CE8F0099A068 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 1100; + ORGANIZATIONNAME = "Apple, Inc."; + TargetAttributes = { + 161479BF1BD6CE8F0099A068 = { + CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0900; + ProvisioningStyle = Manual; + SystemCapabilities = { + com.apple.HealthKit = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = 161479BB1BD6CE8F0099A068 /* Build configuration list for PBXProject "ORKSample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + English, + Base, + en, + ); + mainGroup = 161479B71BD6CE8F0099A068; + productRefGroup = 161479C11BD6CE8F0099A068 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 161479BF1BD6CE8F0099A068 /* ORKSample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 161479BE1BD6CE8F0099A068 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 161479CE1BD6CE8F0099A068 /* LaunchScreen.storyboard in Resources */, + 161479CB1BD6CE8F0099A068 /* Assets.xcassets in Resources */, + 161479C91BD6CE8F0099A068 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 161479BC1BD6CE8F0099A068 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B5D35FC91BEA48D3004CBB06 /* HKHealthStore+Queries.swift in Sources */, + B5BC85FD1BF1408500B0CFA5 /* HealthDataStepViewController.swift in Sources */, + B5C366B41BE7ADBA0036112D /* DashboardTableViewController.swift in Sources */, + 165A7E661BD99DBA00B6D223 /* StudyTasks.swift in Sources */, + B5FA92E91BF13D98001E46C0 /* HealthDataStep.swift in Sources */, + B5D1175E1BE8D17E00D7F153 /* LineGraphDataSource.swift in Sources */, + 16BF5B691BE2974A007C79C6 /* ProfileViewController.swift in Sources */, + B5C207421BECBA8B0051D9D8 /* WithdrawViewController.swift in Sources */, + B5C2073F1BEC16F00051D9D8 /* ResearchContainerSegue.swift in Sources */, + B5BC85FA1BF1405900B0CFA5 /* OnboardingViewController.swift in Sources */, + B5C207561BECED750051D9D8 /* ConsentDocument.swift in Sources */, + 16BF5B711BE2C989007C79C6 /* ProfileStaticTableViewCell.swift in Sources */, + B5D1175C1BE8D15400D7F153 /* DiscreteGraphDataSource.swift in Sources */, + 86CCDFF61C1B50970042AA39 /* ResearchContainerViewController.swift in Sources */, + B5C207501BECCB1A0051D9D8 /* AnimatableChart.swift in Sources */, + 16147A0F1BD83F700099A068 /* ActivityViewController.swift in Sources */, + 16BF5B6F1BE2BE77007C79C6 /* HealthClientType.swift in Sources */, + B5D35FC71BEA363F004CBB06 /* ProfileHeaderView.swift in Sources */, + 161479C41BD6CE8F0099A068 /* AppDelegate.swift in Sources */, + 165A7E6E1BD9AEF800B6D223 /* IntroductionViewController.swift in Sources */, + B5D117581BE8D12000D7F153 /* PieChartDataSource.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 161479C71BD6CE8F0099A068 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 161479C81BD6CE8F0099A068 /* Base */, + ); + name = Main.storyboard; + path = ORKSample; + sourceTree = ""; + }; + 161479CC1BD6CE8F0099A068 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 161479CD1BD6CE8F0099A068 /* Base */, + ); + name = LaunchScreen.storyboard; + path = ORKSample; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 161479D01BD6CE8F0099A068 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 161479D11BD6CE8F0099A068 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 161479D31BD6CE8F0099A068 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ORKSample/ORKSample.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKSample/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-ResearchKit.Sample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 161479D41BD6CE8F0099A068 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = ORKSample/ORKSample.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "$(SRCROOT)/ORKSample/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.example.apple-ResearchKit.Sample"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 161479BB1BD6CE8F0099A068 /* Build configuration list for PBXProject "ORKSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 161479D01BD6CE8F0099A068 /* Debug */, + 161479D11BD6CE8F0099A068 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 161479D21BD6CE8F0099A068 /* Build configuration list for PBXNativeTarget "ORKSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 161479D31BD6CE8F0099A068 /* Debug */, + 161479D41BD6CE8F0099A068 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 161479B81BD6CE8F0099A068 /* Project object */; +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..919434a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/xcshareddata/xcschemes/ORKSample.xcscheme b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/xcshareddata/xcschemes/ORKSample.xcscheme new file mode 100755 index 0000000..bc9c0ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample.xcodeproj/xcshareddata/xcschemes/ORKSample.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ActivityViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ActivityViewController.swift new file mode 100755 index 0000000..d97c0f1 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ActivityViewController.swift @@ -0,0 +1,141 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +enum Activity: Int { + case survey, microphone, tapping, trailmaking + + static var allValues: [Activity] { + var index = 0 + return Array ( + AnyIterator { + let returnedElement = self.init(rawValue: index) + index += 1 + return returnedElement + } + ) + } + + var title: String { + switch self { + case .survey: + return "Survey" + case .microphone: + return "Microphone" + case .tapping: + return "Tapping" + case .trailmaking: + return "Trail Making Test" + } + } + + var subtitle: String { + switch self { + case .survey: + return "Answer 6 short questions" + case .microphone: + return "Voice evaluation" + case .tapping: + return "Test tapping speed" + case .trailmaking: + return "Test visual attention" + } + } +} + +class ActivityViewController: UITableViewController { + // MARK: UITableViewDataSource + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + guard section == 0 else { return 0 } + + return Activity.allValues.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "activityCell", for: indexPath) + + if let activity = Activity(rawValue: (indexPath as NSIndexPath).row) { + cell.textLabel?.text = activity.title + cell.detailTextLabel?.text = activity.subtitle + } + + return cell + } + + // MARK: UITableViewDelegate + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard let activity = Activity(rawValue: (indexPath as NSIndexPath).row) else { return } + + let taskViewController: ORKTaskViewController + switch activity { + case .survey: + taskViewController = ORKTaskViewController(task: StudyTasks.surveyTask, taskRun: NSUUID() as UUID) + + case .microphone: + taskViewController = ORKTaskViewController(task: StudyTasks.microphoneTask, taskRun: NSUUID() as UUID) + + do { + let defaultFileManager = FileManager.default + + // Identify the documents directory. + let documentsDirectory = try defaultFileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) + + // Create a directory based on the `taskRunUUID` to store output from the task. + let outputDirectory = documentsDirectory.appendingPathComponent(taskViewController.taskRunUUID.uuidString) + try defaultFileManager.createDirectory(at: outputDirectory, withIntermediateDirectories: true, attributes: nil) + + taskViewController.outputDirectory = outputDirectory + } catch let error as NSError { + fatalError("The output directory for the task with UUID: \(taskViewController.taskRunUUID.uuidString) could not be created. Error: \(error.localizedDescription)") + } + + case .tapping: + taskViewController = ORKTaskViewController(task: StudyTasks.tappingTask, taskRun: NSUUID() as UUID) + + case .trailmaking: + taskViewController = ORKTaskViewController(task: StudyTasks.trailmakingTask, taskRun: NSUUID() as UUID) + } + + taskViewController.delegate = self + navigationController?.present(taskViewController, animated: true, completion: nil) + } +} + +extension ActivityViewController: ORKTaskViewControllerDelegate { + + func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + // Handle results using taskViewController.result + taskViewController.dismiss(animated: true, completion: nil) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AnimatableChart.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AnimatableChart.swift new file mode 100755 index 0000000..4c7decc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AnimatableChart.swift @@ -0,0 +1,35 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +protocol AnimatableChart { + func animateWithDuration(_ animationDuration: TimeInterval) +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AppDelegate.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AppDelegate.swift new file mode 100755 index 0000000..6d11375 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/AppDelegate.swift @@ -0,0 +1,101 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + let healthStore = HKHealthStore() + + var window: UIWindow? + + var containerViewController: ResearchContainerViewController? { + return window?.rootViewController as? ResearchContainerViewController + } + + func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool { + let standardDefaults = UserDefaults.standard + if standardDefaults.object(forKey: "ORKSampleFirstRun") == nil { + ORKPasscodeViewController.removePasscodeFromKeychain() + standardDefaults.setValue("ORKSampleFirstRun", forKey: "ORKSampleFirstRun") + } + + // Appearance customization + let pageControlAppearance = UIPageControl.appearance() + pageControlAppearance.pageIndicatorTintColor = UIColor.lightGray + pageControlAppearance.currentPageIndicatorTintColor = UIColor.black + + // Dependency injection. + containerViewController?.injectHealthStore(healthStore) + return true + } + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool { + lockApp() + return true + } + + func applicationDidEnterBackground(_ application: UIApplication) { + if ORKPasscodeViewController.isPasscodeStoredInKeychain() { + // Hide content so it doesn't appear in the app switcher. + containerViewController?.contentHidden = true + } + } + + func applicationWillEnterForeground(_ application: UIApplication) { + lockApp() + } + + func lockApp() { + /* + Only lock the app if there is a stored passcode and a passcode + controller isn't already being shown. + */ + guard ORKPasscodeViewController.isPasscodeStoredInKeychain() && !(containerViewController?.presentedViewController is ORKPasscodeViewController) else { return } + + window?.makeKeyAndVisible() + + let passcodeViewController = ORKPasscodeViewController.passcodeAuthenticationViewController(withText: "Welcome back to ResearchKit Sample App", delegate: self) + containerViewController?.present(passcodeViewController, animated: false, completion: nil) + } +} + +extension AppDelegate: ORKPasscodeDelegate { + func passcodeViewControllerDidFinish(withSuccess viewController: UIViewController) { + containerViewController?.contentHidden = false + viewController.dismiss(animated: true, completion: nil) + } + + func passcodeViewControllerDidFailAuthentication(_ viewController: UIViewController) { + } +} + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..536bc9d --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,106 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-Small-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-60@3x.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-Small-40.png", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-83.5@2x.png", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png new file mode 100755 index 0000000..2d32235 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png new file mode 100755 index 0000000..73275a3 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76.png new file mode 100755 index 0000000..16600b5 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png new file mode 100755 index 0000000..78a7d46 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png new file mode 100755 index 0000000..bd13de6 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png new file mode 100755 index 0000000..a6fc9c2 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png new file mode 100755 index 0000000..eba556b Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png new file mode 100755 index 0000000..ca94f4e Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/Contents.json new file mode 100755 index 0000000..da4a164 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/Contents.json new file mode 100755 index 0000000..dbb1e42 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "circle.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/circle.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/circle.png new file mode 100755 index 0000000..ea7e0c7 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/circle.imageset/circle.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/Contents.json new file mode 100755 index 0000000..3d018ea --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "pentagon.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/pentagon.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/pentagon.png new file mode 100755 index 0000000..cd10026 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pentagon.imageset/pentagon.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/Contents.json new file mode 100755 index 0000000..966a01c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "pinwheel.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/pinwheel.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/pinwheel.png new file mode 100755 index 0000000..135ed24 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/pinwheel.imageset/pinwheel.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/Contents.json new file mode 100755 index 0000000..255b90e --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "profile.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/profile.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/profile.pdf new file mode 100755 index 0000000..cf4adb8 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/profilePlaceholder.imageset/profile.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/Contents.json new file mode 100755 index 0000000..3767762 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "square.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/square.png b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/square.png new file mode 100755 index 0000000..4944fa1 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/square.imageset/square.png differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/Contents.json new file mode 100755 index 0000000..3a53647 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tab_activities.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/tab_activities.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/tab_activities.pdf new file mode 100755 index 0000000..b487a93 Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_activities.imageset/tab_activities.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/Contents.json new file mode 100755 index 0000000..c59e5af --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tab_dashboard.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/tab_dashboard.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/tab_dashboard.pdf new file mode 100755 index 0000000..f5b5c2f Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_dashboard.imageset/tab_dashboard.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/Contents.json b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/Contents.json new file mode 100755 index 0000000..eadbbb4 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "tab_profile.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/tab_profile.pdf b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/tab_profile.pdf new file mode 100755 index 0000000..9c42c8c Binary files /dev/null and b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Assets.xcassets/tab_profile.imageset/tab_profile.pdf differ diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/LaunchScreen.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 0000000..8a88100 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/Main.storyboard b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/Main.storyboard new file mode 100755 index 0000000..dbe70a7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Base.lproj/Main.storyboard @@ -0,0 +1,569 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ConsentDocument.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ConsentDocument.swift new file mode 100755 index 0000000..ade04a9 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ConsentDocument.swift @@ -0,0 +1,125 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +class ConsentDocument: ORKConsentDocument { + // MARK: Properties + + let ipsum = [ + "Vivamus laoreet erat sit amet tincidunt scelerisque. Maecenas odio sapien, molestie eu vulputate sodales, tincidunt at neque. Nunc venenatis velit et ligula dictum, eget accumsan felis consectetur. Donec scelerisque fermentum vestibulum. Nam molestie finibus mauris, id congue lectus ultrices eu. Nunc et odio vitae dui interdum dictum. Proin sagittis leo quam. Proin vulputate massa ac orci pulvinar, eget rhoncus urna congue. Sed ut vehicula tellus, eget scelerisque enim. Cras lobortis diam at faucibus scelerisque. Curabitur pharetra arcu erat, nec tincidunt mi eleifend ut. Nunc suscipit risus vitae consectetur sodales. Aenean vitae lectus odio. Phasellus diam orci, accumsan non elementum at, finibus condimentum mauris. Nullam est enim, rhoncus a rutrum sed, laoreet a magna.", + "Duis euismod sollicitudin elementum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed at pharetra sapien. Pellentesque cursus laoreet interdum. Nunc mi sapien, congue vel eleifend in, luctus sit amet massa. Nam tempus metus nec mauris bibendum, vel suscipit quam aliquet. Vestibulum sagittis mi et tempus iaculis. Integer varius eros non sagittis elementum. Proin dictum magna sit amet nulla volutpat posuere eget ac mi. Cras aliquam tristique velit nec porttitor. Integer nulla ligula, vestibulum a ullamcorper non, volutpat non nibh. Integer auctor ipsum id leo pharetra, vitae dapibus augue sagittis. Proin ut diam non orci vulputate rutrum a et nulla. Maecenas in varius augue, eu pretium metus. In auctor ornare augue ac sodales.", + "Aenean in ligula quis arcu rhoncus tristique. Donec ut nisl suscipit augue ornare venenatis. Suspendisse commodo nibh dignissim, congue justo quis, ultrices sapien. Aliquam at lacinia ante. Sed venenatis quam eget dui lobortis, non ullamcorper tellus molestie. Quisque tempus fringilla velit, et viverra odio accumsan quis. Suspendisse potenti. Nullam ac dolor nunc. Pellentesque nec scelerisque risus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Phasellus consectetur efficitur rutrum. Suspendisse in arcu id ex luctus aliquam quis at quam.", + "Maecenas quis varius massa. Nam in dapibus turpis, ut varius eros. Proin a ex enim. Sed faucibus magna vel tincidunt facilisis. Donec id ligula vel mi suscipit sollicitudin. Nulla non magna blandit, semper augue vel, sagittis dui. Curabitur quis rutrum ex. Sed ipsum odio, mattis et dignissim sit amet, volutpat et turpis. Sed quis placerat orci. Duis vitae bibendum diam.", + "Sed nec tortor sapien. Quisque tempor scelerisque vulputate. Nulla eget consequat urna. Aliquam tempus sagittis orci vel tempus. Mauris porta ante sed maximus iaculis. Etiam elit purus, pretium nec ipsum non, aliquam commodo erat. Aliquam sagittis, nibh at porta pellentesque, libero purus finibus nulla, sed consectetur tellus sem non nisl. Duis eu sollicitudin orci. Quisque tincidunt feugiat sapien ac accumsan. Nullam vitae fringilla quam.", + "Integer tristique, nulla nec auctor consectetur, justo dolor sagittis erat, vel laoreet erat turpis vitae dui. Praesent purus tellus, eleifend faucibus sapien id, egestas mollis turpis. Fusce enim lorem, ornare quis ligula a, mattis feugiat diam. Praesent ullamcorper fringilla urna sollicitudin convallis. Curabitur eget dapibus ipsum, ac suscipit mauris. In hac habitasse platea dictumst. Vestibulum non hendrerit ex.", + "Nulla convallis ligula ornare efficitur ullamcorper. Vivamus erat enim, malesuada sit amet dolor ac, tristique blandit felis. Praesent a ante ac nisi tempor elementum. Mauris ligula tellus, porttitor eu vehicula eget, condimentum sed nisi. Donec pharetra lacus tincidunt sapien dignissim iaculis. Duis id ultrices tortor, at congue dolor. Donec consequat fringilla leo, eu congue nulla suscipit non.", + "Sed convallis, ligula vel egestas commodo, mauris nisl tincidunt arcu, id tristique est nunc sit amet felis. Curabitur tortor dolor, ullamcorper vitae pulvinar egestas, venenatis a sem. Cras sit amet maximus magna. Vivamus auctor nisi quis felis mattis, vel sagittis purus pulvinar. Nunc tristique nibh mauris, at eleifend arcu sodales nec. Curabitur rhoncus rutrum metus, ac pretium ante tempor sed. Sed vehicula placerat felis, nec interdum nisl fringilla eu. Nunc iaculis sit amet massa fringilla rhoncus. Maecenas consequat, risus eget commodo suscipit, lorem ex condimentum orci, et sollicitudin nisi eros sed lectus. Sed at erat nisl. Nunc venenatis mi tellus, vitae congue erat dictum a." + ] + + // MARK: Initialization + + override init() { + super.init() + + title = NSLocalizedString("Research Health Study Consent Form", comment: "") + + let sectionTypes: [ORKConsentSectionType] = [ + .overview, + .dataGathering, + .privacy, + .dataUse, + .timeCommitment, + .studySurvey, + .studyTasks, + .withdrawing + ] + sections = [] + + for sectionType in sectionTypes { + let section = ORKConsentSection(type: sectionType) + + let localizedIpsum = NSLocalizedString(ipsum[sectionTypes.index(of: sectionType)!], comment: "") + let localizedSummary = localizedIpsum.components(separatedBy: ".")[0] + "." + + section.summary = localizedSummary + section.content = localizedIpsum + if sections == nil { + sections = [section] + } else { + sections!.append(section) + } + } + + let signature = ORKConsentSignature(forPersonWithTitle: nil, dateFormatString: nil, identifier: "ConsentDocumentParticipantSignature") + addSignature(signature) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension ORKConsentSectionType: CustomStringConvertible { + + public var description: String { + switch self { + case .overview: + return "Overview" + + case .dataGathering: + return "DataGathering" + + case .privacy: + return "Privacy" + + case .dataUse: + return "DataUse" + + case .timeCommitment: + return "TimeCommitment" + + case .studySurvey: + return "StudySurvey" + + case .studyTasks: + return "StudyTasks" + + case .withdrawing: + return "Withdrawing" + + case .custom: + return "Custom" + + case .onlyInDocument: + return "OnlyInDocument" + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DashboardTableViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DashboardTableViewController.swift new file mode 100755 index 0000000..642e64a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DashboardTableViewController.swift @@ -0,0 +1,95 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class DashboardTableViewController: UITableViewController { + // MARK: Properties + + @IBOutlet var pieChart: ORKPieChartView! + @IBOutlet var discreteGraph: ORKDiscreteGraphChartView! + @IBOutlet var lineGraph: ORKLineGraphChartView! + + var allCharts: [UIView] { + return [pieChart, discreteGraph, lineGraph] + } + + let pieChartDataSource = PieChartDataSource() + let discreteGraphDataSource = DiscreteGraphDataSource() + let lineGraphDataSource = LineGraphDataSource() + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + + // Set the data source for each graph + pieChart.dataSource = pieChartDataSource + discreteGraph.dataSource = discreteGraphDataSource + lineGraph.dataSource = lineGraphDataSource + + // Set the table view to automatically calculate the height of cells. + tableView.estimatedRowHeight = tableView.rowHeight + tableView.rowHeight = UITableViewAutomaticDimension + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Animate any visible charts + let visibleCells = tableView.visibleCells + let visibleAnimatableCharts = visibleCells.flatMap { animatableChartInCell($0) } + + for chart in visibleAnimatableCharts { + chart.animateWithDuration(0.5) + } + } + + // MARK: UITableViewDelegate + + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + // Animate charts as they're scrolled into view. + if let animatableChart = animatableChartInCell(cell) { + animatableChart.animateWithDuration(0.5) + } + } + + // MARK: Convenience + + func animatableChartInCell(_ cell: UITableViewCell) -> AnimatableChart? { + for chart in allCharts { + guard let animatableChart = chart as? AnimatableChart, chart.isDescendant(of: cell) else { continue } + return animatableChart + } + + return nil + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DiscreteGraphDataSource.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DiscreteGraphDataSource.swift new file mode 100755 index 0000000..6e3a1dc --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/DiscreteGraphDataSource.swift @@ -0,0 +1,73 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +class DiscreteGraphDataSource: NSObject, ORKValueRangeGraphChartViewDataSource { + // MARK: Properties + + var plotPoints = + [ + [ + ORKValueRange(minimumValue: 0, maximumValue: 2), + ORKValueRange(minimumValue: 1, maximumValue: 4), + ORKValueRange(minimumValue: 2, maximumValue: 6), + ORKValueRange(minimumValue: 3, maximumValue: 8), + ORKValueRange(minimumValue: 5, maximumValue: 10), + ORKValueRange(minimumValue: 8, maximumValue: 13) + ], + [ + ORKValueRange(value: 1), + ORKValueRange(minimumValue: 2, maximumValue: 6), + ORKValueRange(minimumValue: 3, maximumValue: 10), + ORKValueRange(minimumValue: 5, maximumValue: 11), + ORKValueRange(minimumValue: 7, maximumValue: 13), + ORKValueRange(minimumValue: 10, maximumValue: 13) + ] + ] + + // MARK: ORKGraphChartViewDataSource + + func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueRange { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return "\(pointIndex + 1)" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HKHealthStore+Queries.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HKHealthStore+Queries.swift new file mode 100755 index 0000000..412c611 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HKHealthStore+Queries.swift @@ -0,0 +1,48 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import HealthKit + +extension HKHealthStore { + /// Asynchronously fetches the most recent quantity sample of a specified type. + func mostRecentQauntitySampleOfType(_ quantityType: HKQuantityType, predicate: NSPredicate? = nil, completion: @escaping (HKQuantity?, NSError?) -> Void) { + let timeSortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false) + + let query = HKSampleQuery(sampleType: quantityType, predicate: predicate, limit: 1, sortDescriptors: [timeSortDescriptor]) { _, samples, error in + if let firstSample = samples?.first as? HKQuantitySample { + completion(firstSample.quantity, nil) + } else { + completion(nil, error as NSError?) + } + } + + execute(query) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthClientType.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthClientType.swift new file mode 100755 index 0000000..5dfcb8a --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthClientType.swift @@ -0,0 +1,49 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import HealthKit + +protocol HealthClientType { + var healthStore: HKHealthStore? { get set } +} + +extension UIViewController { + + func injectHealthStore(_ healthStore: HKHealthStore) { + if var client = self as? HealthClientType { + client.healthStore = healthStore + } + + for childViewController in childViewControllers { + childViewController.injectHealthStore(healthStore) + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStep.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStep.swift new file mode 100755 index 0000000..8082f05 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStep.swift @@ -0,0 +1,77 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit +import HealthKit + +class HealthDataStep: ORKInstructionStep { + // MARK: Properties + + let healthDataItemsToRead: Set = [ + HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.dateOfBirth)!, + HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!, + HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)! + ] + + let healthDataItemsToWrite: Set = [ + HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!, + HKObjectType.workoutType() + ] + + // MARK: Initialization + + override init(identifier: String) { + super.init(identifier: identifier) + + title = NSLocalizedString("Health Data", comment: "") + text = NSLocalizedString("On the next screen, you will be prompted to grant access to read and write some of your general and health information, such as height, weight, and steps taken so you don't have to enter it again.", comment: "") + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: Convenience + + func getHealthAuthorization(_ completion: @escaping (_ success: Bool, _ error: NSError?) -> Void) { + guard HKHealthStore.isHealthDataAvailable() else { + let error = NSError(domain: "com.example.apple-samplecode.ORKSample", code: 2, userInfo: [NSLocalizedDescriptionKey: "Health data is not available on this device."]) + + completion(false, error) + + return + } + + // Get authorization to access the data + HKHealthStore().requestAuthorization(toShare: healthDataItemsToWrite, read: healthDataItemsToRead) { (success, error) -> Void in + completion(success, error as NSError?) + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStepViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStepViewController.swift new file mode 100755 index 0000000..79931e5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/HealthDataStepViewController.swift @@ -0,0 +1,53 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit +import HealthKit + +class HealthDataStepViewController: ORKInstructionStepViewController { + // MARK: Properties + + var healthDataStep: HealthDataStep? { + return step as? HealthDataStep + } + + // MARK: ORKInstructionStepViewController + + override func goForward() { + healthDataStep?.getHealthAuthorization() { succeeded, _ in + // The second part of the guard condition allows the app to proceed on the Simulator (where health data is not available) + guard succeeded || (TARGET_OS_SIMULATOR != 0) else { return } + + OperationQueue.main.addOperation { + super.goForward() + } + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Info.plist b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Info.plist new file mode 100755 index 0000000..5635717 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/Info.plist @@ -0,0 +1,56 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ORKSample + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.3 + CFBundleSignature + ???? + CFBundleVersion + 1.3 + LSRequiresIPhoneOS + + NSFaceIDUsageDescription + This app uses Face ID during passcode step. + NSHealthShareUsageDescription + Health Share Usage description must be longer than one word + NSHealthUpdateUsageDescription + Use healthkit + NSMicrophoneUsageDescription + Use microphone + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + healthkit + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/IntroductionViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/IntroductionViewController.swift new file mode 100755 index 0000000..4688d20 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/IntroductionViewController.swift @@ -0,0 +1,84 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +class IntroductionViewController: UIPageViewController, UIPageViewControllerDataSource { + // MARK: Properties + + let pageViewControllers: [UIViewController] = { + let introOne = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "introOneViewController") + let introTwo = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "introTwoViewController") + let introThree = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "introThreeViewController") + + return [introOne, introTwo, introThree] + }() + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + dataSource = self + + setViewControllers([pageViewControllers[0]], direction: .forward, animated: false, completion: nil) + } + + // MARK: UIPageViewControllerDataSource + + func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { + let index = pageViewControllers.index(of: viewController)! + + if index - 1 >= 0 { + return pageViewControllers[index - 1] + } + + return nil + } + + func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { + let index = pageViewControllers.index(of: viewController)! + + if index + 1 < pageViewControllers.count { + return pageViewControllers[index + 1] + } + + return nil + } + + func presentationCount(for pageViewController: UIPageViewController) -> Int { + return pageViewControllers.count + } + + func presentationIndex(for pageViewController: UIPageViewController) -> Int { + return 0 + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/LineGraphDataSource.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/LineGraphDataSource.swift new file mode 100755 index 0000000..09a0d04 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/LineGraphDataSource.swift @@ -0,0 +1,81 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +class LineGraphDataSource: NSObject, ORKValueRangeGraphChartViewDataSource { + // MARK: Properties + + var plotPoints = + [ + [ + ORKValueRange(value: 10), + ORKValueRange(value: 20), + ORKValueRange(value: 25), + ORKValueRange(), + ORKValueRange(value: 30), + ORKValueRange(value: 40) + ], + [ + ORKValueRange(value: 2), + ORKValueRange(value: 4), + ORKValueRange(value: 8), + ORKValueRange(value: 16), + ORKValueRange(value: 32), + ORKValueRange(value: 64) + ] + ] + + // MARK: ORKGraphChartViewDataSource + + func numberOfPlots(in graphChartView: ORKGraphChartView) -> Int { + return plotPoints.count + } + + func graphChartView(_ graphChartView: ORKGraphChartView, dataPointForPointIndex pointIndex: Int, plotIndex: Int) -> ORKValueRange { + return plotPoints[plotIndex][pointIndex] + } + + func graphChartView(_ graphChartView: ORKGraphChartView, numberOfDataPointsForPlotIndex plotIndex: Int) -> Int { + return plotPoints[plotIndex].count + } + + func maximumValue(for graphChartView: ORKGraphChartView) -> Double { + return 70 + } + + func minimumValue(for graphChartView: ORKGraphChartView) -> Double { + return 0 + } + + func graphChartView(_ graphChartView: ORKGraphChartView, titleForXAxisAtPointIndex pointIndex: Int) -> String? { + return "\(pointIndex + 1)" + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ORKSample.entitlements b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ORKSample.entitlements new file mode 100755 index 0000000..e10f430 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ORKSample.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.developer.healthkit + + + diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/OnboardingViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/OnboardingViewController.swift new file mode 100755 index 0000000..7523a3b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/OnboardingViewController.swift @@ -0,0 +1,85 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class OnboardingViewController: UIViewController { + // MARK: IB actions + + @IBAction func joinButtonTapped(_ sender: UIButton) { + let consentDocument = ConsentDocument() + let consentStep = ORKVisualConsentStep(identifier: "VisualConsentStep", document: consentDocument) + + let healthDataStep = HealthDataStep(identifier: "Health") + + let signature = consentDocument.signatures!.first! + + let reviewConsentStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: signature, in: consentDocument) + + reviewConsentStep.text = "Review the consent form." + reviewConsentStep.reasonForConsent = "Consent to join the Developer Health Research Study." + + let passcodeStep = ORKPasscodeStep(identifier: "Passcode") + passcodeStep.text = "Now you will create a passcode to identify yourself to the app and protect access to information you've entered." + + let completionStep = ORKCompletionStep(identifier: "CompletionStep") + completionStep.title = "Welcome aboard." + completionStep.text = "Thank you for joining this study." + + let orderedTask = ORKOrderedTask(identifier: "Join", steps: [consentStep, reviewConsentStep, healthDataStep, passcodeStep, completionStep]) + let taskViewController = ORKTaskViewController(task: orderedTask, taskRun: nil) + taskViewController.delegate = self + + present(taskViewController, animated: true, completion: nil) + } +} + +extension OnboardingViewController: ORKTaskViewControllerDelegate { + + public func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + switch reason { + case .completed: + performSegue(withIdentifier: "unwindToStudy", sender: nil) + + case .discarded, .failed, .saved: + dismiss(animated: true, completion: nil) + } + } + + func taskViewController(_ taskViewController: ORKTaskViewController, viewControllerFor step: ORKStep) -> ORKStepViewController? { + if step is HealthDataStep { + let healthStepViewController = HealthDataStepViewController(step: step) + return healthStepViewController + } + + return nil + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/PieChartDataSource.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/PieChartDataSource.swift new file mode 100755 index 0000000..a8e0df7 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/PieChartDataSource.swift @@ -0,0 +1,67 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +class PieChartDataSource: NSObject, ORKPieChartViewDataSource { + // MARK: Types + + struct Segment { + let title: String + let value: Float + let color: UIColor + } + + // MARK: Properties + + let segments = [ + Segment(title: "Title 1", value: 10.0, color: UIColor(red: 217 / 225, green: 217 / 255, blue: 217 / 225, alpha: 1)), + Segment(title: "Title 2", value: 25.0, color: UIColor(red: 142 / 255, green: 142 / 255, blue: 147 / 255, alpha: 1)), + Segment(title: "Title 3", value: 45.0, color: UIColor(red: 244 / 225, green: 190 / 255, blue: 74 / 225, alpha: 1)) + ] + + // MARK: ORKPieChartViewDataSource + + func numberOfSegments(in pieChartView: ORKPieChartView ) -> Int { + return segments.count + } + + func pieChartView(_ pieChartView: ORKPieChartView, valueForSegmentAt index: Int) -> CGFloat { + return CGFloat(segments[index].value) + } + + func pieChartView(_ pieChartView: ORKPieChartView, colorForSegmentAt index: Int) -> UIColor { + return segments[index].color + } + + func pieChartView(_ pieChartView: ORKPieChartView, titleForSegmentAt index: Int) -> String? { + return segments[index].title + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileHeaderView.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileHeaderView.swift new file mode 100755 index 0000000..6bb4ae5 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileHeaderView.swift @@ -0,0 +1,52 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +@IBDesignable +class ProfileHeaderView: UIView { + // MARK: Properties + + var seperatorHeight = CGFloat(0.5) + + var seperatorColor = UIColor.lightGray + + // MARK: UIView + + override func draw(_ rect: CGRect) { + // Draw a seperator line at the bottom of the view. + var fillRect = bounds + fillRect.origin.y = bounds.size.height - seperatorHeight + fillRect.size.height = seperatorHeight + + seperatorColor.setFill() + UIRectFill(fillRect) + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileStaticTableViewCell.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileStaticTableViewCell.swift new file mode 100755 index 0000000..c578d6f --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileStaticTableViewCell.swift @@ -0,0 +1,40 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +class ProfileStaticTableViewCell: UITableViewCell { + // MARK: Properties + + static let reuseIdentifier = "ProfileStaticTableViewCell" + + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var valueLabel: UILabel! +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileViewController.swift new file mode 100755 index 0000000..806f1fe --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ProfileViewController.swift @@ -0,0 +1,165 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit +import HealthKit + +class ProfileViewController: UITableViewController, HealthClientType { + // MARK: Properties + + let healthObjectTypes = [ + HKObjectType.characteristicType(forIdentifier: HKCharacteristicTypeIdentifier.dateOfBirth)!, + HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!, + HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)! + ] + + var healthStore: HKHealthStore? + + @IBOutlet var applicationNameLabel: UILabel! + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + + guard let healthStore = healthStore else { fatalError("healhStore not set") } + + // Ensure the table view automatically sizes its rows. + tableView.estimatedRowHeight = tableView.rowHeight + tableView.rowHeight = UITableViewAutomaticDimension + + // Request authrization to query the health objects that need to be shown. + let typesToRequest = Set(healthObjectTypes) + healthStore.requestAuthorization(toShare: nil, read: typesToRequest) { authorized, error in + guard authorized else { return } + + // Reload the table view cells on the main thread. + + OperationQueue.main.addOperation { + var allRowIndexPaths: [IndexPath] = [] + for index in 0.. Int { + return healthObjectTypes.count + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: ProfileStaticTableViewCell.reuseIdentifier, for: indexPath) as? ProfileStaticTableViewCell else { fatalError("Unable to dequeue a ProfileStaticTableViewCell") } + let objectType = healthObjectTypes[(indexPath as NSIndexPath).row] + + switch objectType.identifier { + case HKCharacteristicTypeIdentifier.dateOfBirth.rawValue: + configureCellWithDateOfBirth(cell) + + case HKQuantityTypeIdentifier.height.rawValue: + let title = NSLocalizedString("Height", comment: "") + configureCell(cell, withTitleText: title, valueForQuantityTypeIdentifier: objectType.identifier) + + case HKQuantityTypeIdentifier.bodyMass.rawValue: + let title = NSLocalizedString("Weight", comment: "") + configureCell(cell, withTitleText: title, valueForQuantityTypeIdentifier: objectType.identifier) + + default: + fatalError("Unexpected health object type identifier - \(objectType.identifier)") + } + + return cell + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + } + + // MARK: Cell configuration + + func configureCellWithDateOfBirth(_ cell: ProfileStaticTableViewCell) { + // Set the default cell content. + cell.titleLabel.text = NSLocalizedString("Date of Birth", comment: "") + cell.valueLabel.text = NSLocalizedString("-", comment: "") + + // Update the value label with the date of birth from the health store. + guard let healthStore = healthStore else { return } + + do { + let dateOfBirth = try healthStore.dateOfBirth() + let now = Date() + + let ageComponents = Calendar.current.dateComponents([.year], from: dateOfBirth, to: now) + let age = ageComponents.year + + cell.valueLabel.text = "\(age ?? 0)" + } catch { + } + } + + func configureCell(_ cell: ProfileStaticTableViewCell, withTitleText titleText: String, valueForQuantityTypeIdentifier identifier: String) { + // Set the default cell content. + cell.titleLabel.text = titleText + cell.valueLabel.text = NSLocalizedString("-", comment: "") + + /* + Check a health store has been set and a `HKQuantityType` can be + created with the identifier provided. + */ + guard let healthStore = healthStore, let quantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier(rawValue: identifier)) else { return } + + // Get the most recent entry from the health store. + healthStore.mostRecentQauntitySampleOfType(quantityType) { quantity, _ in + guard let quantity = quantity else { return } + + // Update the cell on the main thread. + OperationQueue.main.addOperation() { + guard let indexPath = self.indexPathForObjectTypeIdentifier(identifier) else { return } + guard let cell = self.tableView.cellForRow(at: indexPath) as? ProfileStaticTableViewCell else { return } + + cell.valueLabel.text = "\(quantity)" + } + } + } + + // MARK: Convenience + + func indexPathForObjectTypeIdentifier(_ identifier: String) -> IndexPath? { + for (index, objectType) in healthObjectTypes.enumerated() where objectType.identifier == identifier { + return IndexPath(row: index, section: 0) + } + + return nil + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerSegue.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerSegue.swift new file mode 100755 index 0000000..00c58ff --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerSegue.swift @@ -0,0 +1,52 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit + +class ResearchContainerSegue: UIStoryboardSegue { + + override func perform() { + let controllerToReplace = source.childViewControllers.first + let destinationControllerView = destination.view + + destinationControllerView?.translatesAutoresizingMaskIntoConstraints = true + destinationControllerView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] + destinationControllerView?.frame = source.view.bounds + + controllerToReplace?.willMove(toParentViewController: nil) + source.addChildViewController(destination) + + source.view.addSubview(destinationControllerView!) + controllerToReplace?.view.removeFromSuperview() + + destination.didMove(toParentViewController: source) + controllerToReplace?.removeFromParentViewController() + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerViewController.swift new file mode 100755 index 0000000..7102675 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/ResearchContainerViewController.swift @@ -0,0 +1,115 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class ResearchContainerViewController: UIViewController, HealthClientType { + // MARK: HealthClientType + + var healthStore: HKHealthStore? + + // MARK: Propertues + + var contentHidden = false { + didSet { + guard contentHidden != oldValue && isViewLoaded else { return } + childViewControllers.first?.view.isHidden = contentHidden + } + } + + // MARK: UIViewController + + override func viewDidLoad() { + super.viewDidLoad() + + if ORKPasscodeViewController.isPasscodeStoredInKeychain() { + toStudy() + } else { + toOnboarding() + } + } + + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + super.prepare(for: segue, sender: sender) + + if let healthStore = healthStore { + segue.destination.injectHealthStore(healthStore) + } + } + + // MARK: Unwind segues + + @IBAction func unwindToStudy(_ segue: UIStoryboardSegue) { + toStudy() + } + + @IBAction func unwindToWithdrawl(_ segue: UIStoryboardSegue) { + toWithdrawl() + } + + // MARK: Transitions + + func toOnboarding() { + performSegue(withIdentifier: "toOnboarding", sender: self) + } + + func toStudy() { + performSegue(withIdentifier: "toStudy", sender: self) + } + + func toWithdrawl() { + let viewController = WithdrawViewController() + viewController.delegate = self + + present(viewController, animated: true, completion: nil) + } +} + + +extension ResearchContainerViewController: ORKTaskViewControllerDelegate { + + public func taskViewController(_ taskViewController: ORKTaskViewController, didFinishWith reason: ORKTaskViewControllerFinishReason, error: Error?) { + // Check if the user has finished the `WithdrawViewController`. + if taskViewController is WithdrawViewController { + /* + If the user has completed the withdrawl steps, remove them from + the study and transition to the onboarding view. + */ + if reason == .completed { + ORKPasscodeViewController.removePasscodeFromKeychain() + toOnboarding() + } + + // Dismiss the `WithdrawViewController`. + dismiss(animated: true, completion: nil) + } + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/StudyTasks.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/StudyTasks.swift new file mode 100755 index 0000000..540f63b --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/StudyTasks.swift @@ -0,0 +1,133 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import ResearchKit + +struct StudyTasks { + + static let microphoneTask: ORKOrderedTask = { + let intendedUseDescription = "Everyone's voice has unique characteristics." + let speechInstruction = "After the countdown, say Aaaaaaaaaaah for as long as you can. You'll have 10 seconds." + let shortSpeechInstruction = "Say Aaaaaaaaaaah for as long as you can." + + return ORKOrderedTask.audioTask(withIdentifier: "AudioTask", intendedUseDescription: intendedUseDescription, speechInstruction: speechInstruction, shortSpeechInstruction: shortSpeechInstruction, duration: 10, recordingSettings: nil, checkAudioLevel: false, options: ORKPredefinedTaskOption.excludeAccelerometer) + }() + + static let tappingTask: ORKOrderedTask = { + let intendedUseDescription = "Finger tapping is a universal way to communicate." + + return ORKOrderedTask.twoFingerTappingIntervalTask(withIdentifier: "TappingTask", intendedUseDescription: intendedUseDescription, duration: 10, handOptions: .both, options: ORKPredefinedTaskOption()) + }() + + static let trailmakingTask: ORKOrderedTask = { + let intendedUseDescription = "Tests visual attention and task switching" + + return ORKOrderedTask.trailmakingTask(withIdentifier: "TrailmakingTask", intendedUseDescription: intendedUseDescription, trailmakingInstruction: nil, trailType: .B, options: ORKPredefinedTaskOption()) + }() + + static let surveyTask: ORKOrderedTask = { + var steps = [ORKStep]() + + // Instruction step + let instructionStep = ORKInstructionStep(identifier: "IntroStep") + instructionStep.title = "Knoweledge of the Universe Survey" + instructionStep.text = "Please answer these 6 questions to the best of your ability. It's okay to skip a question if you don't know the answer." + + steps += [instructionStep] + + // Quest question using text choice + let questQuestionStepTitle = "Which of the following is not a planet?" + let textChoices = [ + ORKTextChoice(text: "Saturn", value: 0 as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Uranus", value: 1 as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Pluto", value: 2 as NSCoding & NSCopying & NSObjectProtocol), + ORKTextChoice(text: "Mars", value: 3 as NSCoding & NSCopying & NSObjectProtocol) + ] + let questAnswerFormat: ORKTextChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(with: .singleChoice, textChoices: textChoices) + let questQuestionStep = ORKQuestionStep(identifier: "TextChoiceQuestionStep", title: questQuestionStepTitle, answer: questAnswerFormat) + + steps += [questQuestionStep] + + // Name question using text input + let nameAnswerFormat = ORKTextAnswerFormat(maximumLength: 25) + nameAnswerFormat.multipleLines = false + let nameQuestionStepTitle = "What do you think the next comet that's discovered should be named?" + let nameQuestionStep = ORKQuestionStep(identifier: "NameQuestionStep", title: nameQuestionStepTitle, answer: nameAnswerFormat) + + steps += [nameQuestionStep] + + let shapeQuestionStepTitle = "Which shape is the closest to the shape of Messier object 101?" + let shapeTuples = [ + (UIImage(named: "square")!, "Square"), + (UIImage(named: "pinwheel")!, "Pinwheel"), + (UIImage(named: "pentagon")!, "Pentagon"), + (UIImage(named: "circle")!, "Circle") + ] + let imageChoices: [ORKImageChoice] = shapeTuples.map { + return ORKImageChoice(normalImage: $0.0, selectedImage: nil, text: $0.1, value: $0.1 as NSCoding & NSCopying & NSObjectProtocol) + } + let shapeAnswerFormat: ORKImageChoiceAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(with: imageChoices) + let shapeQuestionStep = ORKQuestionStep(identifier: "ImageChoiceQuestionStep", title: shapeQuestionStepTitle, answer: shapeAnswerFormat) + + steps += [shapeQuestionStep] + + // Date question + let today = NSDate() + let dateAnswerFormat = ORKAnswerFormat.dateAnswerFormat(withDefaultDate: nil, minimumDate: today as Date, maximumDate: nil, calendar: nil) + let dateQuestionStepTitle = "When is the next solar eclipse?" + let dateQuestionStep = ORKQuestionStep(identifier: "DateQuestionStep", title: dateQuestionStepTitle, answer: dateAnswerFormat) + + steps += [dateQuestionStep] + + // Boolean question + let booleanAnswerFormat = ORKBooleanAnswerFormat() + let booleanQuestionStepTitle = "Is Venus larger than Saturn?" + let booleanQuestionStep = ORKQuestionStep(identifier: "BooleanQuestionStep", title: booleanQuestionStepTitle, answer: booleanAnswerFormat) + + steps += [booleanQuestionStep] + + // Continuous question + let continuousAnswerFormat = ORKAnswerFormat.scale(withMaximumValue: 150, minimumValue: 30, defaultValue: 20, step: 10, vertical: false, maximumValueDescription: "Objects", minimumValueDescription: " ") + let continuousQuestionStepTitle = "How many objects are in Messier's catalog?" + let continuousQuestionStep = ORKQuestionStep(identifier: "ContinuousQuestionStep", title: continuousQuestionStepTitle, answer: continuousAnswerFormat) + + steps += [continuousQuestionStep] + + // Summary step + + let summaryStep = ORKCompletionStep(identifier: "SummaryStep") + summaryStep.title = "Thank you." + summaryStep.text = "We appreciate your time." + + steps += [summaryStep] + + return ORKOrderedTask(identifier: "SurveyTask", steps: steps) + }() +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/WithdrawViewController.swift b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/WithdrawViewController.swift new file mode 100755 index 0000000..4fe6b03 --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/samples/ORKSample/ORKSample/WithdrawViewController.swift @@ -0,0 +1,54 @@ +/* +Copyright (c) 2015, Apple Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder(s) nor the names of any contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. No license is granted to the trademarks of +the copyright holders even if such marks are included in this software. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import UIKit +import ResearchKit + +class WithdrawViewController: ORKTaskViewController { + // MARK: Initialization + + init() { + let instructionStep = ORKInstructionStep(identifier: "WithdrawlInstruction") + instructionStep.title = NSLocalizedString("Are you sure you want to withdraw?", comment: "") + instructionStep.text = NSLocalizedString("Withdrawing from the study will reset the app to the state it was in prior to you originally joining the study.", comment: "") + + let completionStep = ORKCompletionStep(identifier: "Withdraw") + completionStep.title = NSLocalizedString("We appreciate your time.", comment: "") + completionStep.text = NSLocalizedString("Thank you for your contribution to this study. We are sorry that you could not continue.", comment: "") + + let withdrawTask = ORKOrderedTask(identifier: "Withdraw", steps: [instructionStep, completionStep]) + + super.init(task: withdrawTask, taskRun: nil) + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/scripts/find_headers.rb b/PediatricPancreas_Storyboard/ResearchKit-master/scripts/find_headers.rb new file mode 100755 index 0000000..716fc9c --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/scripts/find_headers.rb @@ -0,0 +1,79 @@ +#!/usr/bin/env ruby + +# Copyright (c) 2015, Dasmer Singh. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder(s) nor the names of any contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. No license is granted to the trademarks of +# the copyright holders even if such marks are included in this software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +require 'pathname' +require 'xcodeproj' +require 'optparse' + +ROOT = Pathname.new(File.expand_path('../../', __FILE__)) + +options = {} +OptionParser.new do |opts| + opts.banner = 'Usage: find_headers.rb [options]' + + opts.on('--public', 'Find public headers') do |v| + options[:public] = v + end + + opts.on('--private', 'Find private headers') do |v| + options[:private] = v + end +end.parse! + +required_opts = options[:public] || options[:private] +fail ArgumentError, 'Must provide --public or --private' unless required_opts + +separator = "\n" + +project = Xcodeproj::Project.open(ROOT + 'ResearchKit.xcodeproj') +target = project.targets.find { |t| t.name == 'ResearchKit' } + +public_headers = target.headers_build_phase.files.select do |build_file| + settings = build_file.settings + settings && settings['ATTRIBUTES'].include?('Public') +end + +private_headers = target.headers_build_phase.files.select do |build_file| + settings = build_file.settings + settings && settings['ATTRIBUTES'].include?('Private') +end + +if options[:public] + puts public_headers.map { |build_file| + build_file.file_ref.real_path.relative_path_from(ROOT) + }.join(separator) +end + +if options[:private] + puts private_headers.map { |build_file| + build_file.file_ref.real_path.relative_path_from(ROOT) + }.join(separator) +end diff --git a/PediatricPancreas_Storyboard/ResearchKit-master/scripts/plist-to-strings.py b/PediatricPancreas_Storyboard/ResearchKit-master/scripts/plist-to-strings.py new file mode 100755 index 0000000..14194ee --- /dev/null +++ b/PediatricPancreas_Storyboard/ResearchKit-master/scripts/plist-to-strings.py @@ -0,0 +1,149 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2015, Ricardo Sánchez-Sáez. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder(s) nor the names of any contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. No license is granted to the trademarks of +# the copyright holders even if such marks are included in this software. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This script reads and converts a binary .strings file (binary .plist) into a plaintext .string file. +# +# Since binary .strings files are generally unsorted, it takes a master plaintext .strings file +# (typically en.lproj/Localizable.strings) and uses it for sorting they keys in the target converted file. +# +# The target file can have all or some of the string keys in the master file. If the master file has +# additional string keys not found in the target file, they are ignored. +# String keys present in the target file but not present in the master file are added at the end of the +# converted file in an undefined order. +# +# This script has been tested with Python 2.7.6. You need to have Xcode Command Line Tools installed (it uses plutil). +# +# Single file usage example: +# ./plist-to-strings.py -m en.lproj/ResearchKit.strings -t es.lproj/ResearchKit.strings +# +# Whole project usage example (using 'en.lproj' as the master plaintext localization): +# localizedFolder="../ProjectPath/Localized"; for languageFolder in $(ls $localizedFolder); do if [[ "$languageFolder" != "en.lproj" ]]; then ./plist-to-strings.py -m ${localizedFolder}/en.lproj/Localizable.strings -t ${localizedFolder}/${languageFolder}/Localizable.strings; fi; done + +import argparse +import os +import plistlib +import shutil +import subprocess +import sys +import uuid + +def warning(string): + sys.stdout.write("WARNING: " + string + '\n\n') + +def error(string): + sys.stderr.write("ERROR: " + string + '\n\n') + +parser = argparse.ArgumentParser() +parser.add_argument('-m', '--master', help='Master plain text .strings file', required=True) +parser.add_argument('-t', '--target', help='Target binary plist .strings file to convert to plain text', required=True) +args = parser.parse_args() +masterFileName = args.master +targetFileName = args.target + +def checkIfEssentialFileExists(fileName, fileTag): + if not os.path.isfile(fileName): + print(fileTag + ' .strings file not found: ' + fileName + '\n') + parser.print_usage() + sys.exit(1) + +checkIfEssentialFileExists(masterFileName, "Master") +checkIfEssentialFileExists(targetFileName, "Target") + +def convertBinaryPlistToStrings(masterFileName, targetFileName): + def buildStringsLine(stringKey, localizedString): + # escape '\', '"', '\n' and '\r' characters on the target plain text string + escapedString = localizedString.replace('\\', '\\\\').replace('"','\\"').replace('\n','\\n').replace('\r','\\r') + return '"' + stringKey + '" = "' + escapedString + '";\n' + + outputEncoding = 'UTF-8' + + targetFileNameWithoutExtension = os.path.splitext(targetFileName)[0] + UUID = uuid.uuid1() + temporaryTargetFileName = targetFileNameWithoutExtension + '.' + UUID.hex + '.strings.plist' + shutil.copyfile(targetFileName, temporaryTargetFileName) + + # convert binary .strings.plist to hex .strings.plist + subprocess.call(['plutil', '-convert', 'xml1', temporaryTargetFileName]) + targetPlist = plistlib.readPlist(temporaryTargetFileName) + + masterFile = open(masterFileName) + + temporaryOutputFileName = targetFileNameWithoutExtension + '.' + UUID.hex + '.strings' + temporaryOutputFile = open(temporaryOutputFileName, 'w') + + for line in masterFile: + # preserve comments and blank lines + # warning: multiline comments cannot have a line starting with the double quote character " + if len(line.strip())==0 or line.strip()[0] != '"': + temporaryOutputFile.write(line.encode(outputEncoding)) + + else: + # get appropriate string from target plist, convert it, and write to output + + # master line example: "CONSENT_NAME_TITLE" = "Consent"; + # master tokenizedLine example: ['', 'CONSENT_NAME_TITLE', ' = ', 'Consent', ';'] + + # remove escaped \\ and \" so they don't interfere with the tokenizer (we don't need the correct master string) + intermediateLine = line.strip().replace('\\\\', '').replace('\\"','') + tokenizedLine = intermediateLine.split('"') + + # ignore abnormal lines (these should not appear) + if len(tokenizedLine) != 5: + error("Ignoring malformed line:" + line.strip()) + continue + + stringKey = tokenizedLine[1] + if stringKey not in targetPlist: + warning("String key not found in target file: " + stringKey) + continue + + targetLine = buildStringsLine(stringKey, targetPlist[stringKey]) + temporaryOutputFile.write(targetLine.encode(outputEncoding)) + + del targetPlist[stringKey] + + # Add remaining target string keys + if len(targetPlist) > 0: + temporaryOutputFile.write("\n\n/* Unsorted */\n") + for stringKey in targetPlist: + targetLine = buildStringsLine(stringKey, targetPlist[stringKey]).encode(outputEncoding) + temporaryOutputFile.write(targetLine) + + temporaryOutputFile.close() + masterFile.close() + + os.remove(temporaryTargetFileName) + os.rename(temporaryOutputFileName, targetFileName) + + +print('Converting: ' + targetFileName) +convertBinaryPlistToStrings(masterFileName, targetFileName) +print('...done')